commit 08102c2bcd02991576feaf06ecfd130c8123377f Author: true Date: Sat Feb 11 04:47:30 2023 -0800 Initial commit of tweaked ATtiny88 code Only some minor cleanup performed. Builds fine with AS7 but is otherwise untested. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..90fc93e --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ + +attiny88_main/Debug +attiny88_main/Release diff --git a/attiny88_main/bin/wp_dc22_attiny88.elf b/attiny88_main/bin/wp_dc22_attiny88.elf new file mode 100644 index 0000000..c2f4fb1 Binary files /dev/null and b/attiny88_main/bin/wp_dc22_attiny88.elf differ diff --git a/attiny88_main/bin/wp_dc22_attiny88.hex b/attiny88_main/bin/wp_dc22_attiny88.hex new file mode 100644 index 0000000..9e9ed19 --- /dev/null +++ b/attiny88_main/bin/wp_dc22_attiny88.hex @@ -0,0 +1,141 @@ +:100000002DC047C046C045C044C043C042C041C0E7 +:1000100040C03FC03EC03DC0AAC33BC03AC039C08B +:100020008BC037C036C034C3BDC1C0C1CAC1DBC17B +:10003000F8C116C228C227C2F9C103C224C223C212 +:1000400022C221C220C209C20BC20AC21CC21BC2E8 +:100050001AC219C218C217C216C207C211241FBE83 +:10006000CFEFD2E0DEBFCDBF11E0A0E0B1E0E8EA23 +:10007000F8E002C005900D92A430B107D9F721E055 +:10008000A4E0B1E001C01D92A433B207E1F76DD244 +:1000900009C4B6CFE4E6F0E080818E7F8083EAE792 +:1000A000F0E08FED8083ACE7B0E08C918F7D8C9396 +:1000B0008081886880830895282F803188F490910A +:1000C0007C00907F982B90937C00883030F481E006 +:1000D00001C0880F2A95EAF701C080E080937E0076 +:1000E000613021F480917C00806405C0623029F485 +:1000F00080917C008F7B80937C00089590917A00A2 +:10010000292F207496FD15C080930C01662311F0F1 +:10011000982F01C090E09093040190917C009F7013 +:10012000906890931F0190917A00906490937A0068 +:1001300001C021E0822F08951F920F920FB60F92F7 +:1001400011242F934F935F938F939F93AF93BF93FC +:10015000EF93FF93E0917C00EF7020910401222344 +:10016000D1F080910C012817B1F0E930A0F4AE2F46 +:10017000B0E0AA0FBB1FA35FBE4F4D915C911197DA +:100180008091780090917900840F951F96958795BE +:1001900011969C938E9380910C01882359F0809145 +:1001A0000C01815080930C0180917A0080648093CF +:1001B0007A0011C021110DC0E93058F4F0E08091AF +:1001C000780090917900EE0FFF1FE35FFE4F91835F +:1001D000808310921F01FF91EF91BF91AF919F918A +:1001E0008F915F914F912F910F900FBE0F901F90A5 +:1001F00018958AB1806F8AB987B18F6087B98BB142 +:10020000806F8BB988B18F6088B90895CF93DF93E1 +:100210008BB1806F8BB988B18F6088B9C8E8D0E0A6 +:100220008EEF8883AAE8B0E08C938AEF90E09093F9 +:100230008500809384003BB124E02D0D81E090E0A7 +:10024000AC0101C0440F2A95EAF7242F20952323FF +:100250002BB928B10D2C01C0880F0A94EAF78095BC +:10026000822388B9ED2DF0E0EB5DFE4F8BEF90819E +:10027000282F291B2883ED2DF0E0EF5DFE4F9081A4 +:10028000891B8C93DF91CF9108959BB1906F9BB99F +:10029000E0E8F0E090819F70908397B1907F97B9EC +:1002A00095B7906195BF47B121E030E0B90102C038 +:1002B000660F771F8A95E2F7CB01462B47B998B1B5 +:1002C000907F98B92A9A98B1982B98B92A9878E093 +:1002D0007A95F1F797B18095982397B998B18923CA +:1002E00088B985B78F7E85BF0895843038F466233A +:1002F00029F0E82FF0E0E050FF4F6083089583700D +:1003000080930501089580910501E82FF0E0E05009 +:10031000FF4F9081911101C091E02E2DE11003C09B +:1003200061E08FE012C0213019F460E080E018C075 +:10033000223061F490911F01992319F0EE24E39487 +:100340000895A3DF6FEF80910501B6CE4E2D50E0EA +:10035000892F90E002964817590719F461E083E06D +:10036000CDCE8417950794F42150E22E80911F0181 +:1003700081110CC06FEF8FE09FDE3BDF8EEF80932B +:10038000800084B1866084B91092200108958F2D79 +:100390004F2D50E04A31510508F075C0FA01EC5E6E +:1003A000FF4F0994F12C10922A0108958091330196 +:1003B000882309F46CC0F090300183E0809333010E +:1003C00050C0E0912F01E43020F4F0E0EB5DFE4FEF +:1003D00006C0E83008F044C0F0E0E35EFE4F8091D4 +:1003E000300180833DC080913301882309F44FC0E0 +:1003F00080911D0190911E01892B09F444C06091E8 +:100400001D0170911E0180913001681B710987FDEB +:10041000739570930701609306018EE390E024D2F8 +:100420001FC0809133018230D8F41DC0809120011B +:10043000811117C010922001E12C88E080932001E7 +:1004400010C08091200181110CC010922001E12C7C +:1004500080912F0154DF81E0F1CF84E08093090186 +:10046000F12C10922A0180E00895809133018823B5 +:1004700071F080912F01843098F7609130016623EC +:1004800079F333DFEDCFF12C10922A0181E008954A +:100490008093BB00ECEBF0E08081806880838081FA +:1004A0008F7B808380E008958F2D8830B9F089306C +:1004B000C1F0843051F580912F01803428F490E010 +:1004C000C8D1E6DF81E006C08091BC008F7B8093BD +:1004D000BC008FEFF12C10922A0108958091080141 +:1004E0000EC0E0912F01E370F0E0EE0FFF1FE35F1D +:1004F000FE4F808191819695879596958795C8DF67 +:10050000F12C10922A0181E008958091BC008F7B2C +:100510008093BC008FEF089580911D0190911E0182 +:1005200090910601891B982F959595959595891B16 +:1005300008958E2DE11003C062E088E0BDCD8330C8 +:1005400019F461E084E0DACD843070F08150E82E57 +:1005500080911F01811108C061E08FE0ADDD109234 +:100560002001DADF80930801089580E8809361001C +:100570001092610082B3806F82BB1DB881E084B9A4 +:1005800017B81AB8CFEFCEB9DEEFD5B9C8B9CBB925 +:1005900030DE22E02093B8008CEF8093B90086EE25 +:1005A0008093BA001092BD0085E48093BC008091D6 +:1005B00064008A7F809364009BEF95BD8DE387BDC7 +:1005C00016BC20936E00809164008C7F8093640041 +:1005D000C0938900C0938800C0938A001092850060 +:1005E00010928400D093800089E180938100109262 +:1005F000820080918000809329019093860084B1CD +:10060000866084B910926F0045DD629923C042DD97 +:100610002FEF80E792E0215080409040E1F700C04A +:100620000000629917C0789488E08093200181DFF0 +:1006300080911F018111FCCF60911D0170911E01FD +:1006400070930701609306018EE390E00DD1109244 +:1006500020010DC08EE390E003D1813322E09207A8 +:1006600014F081E191E0909307018093060183B734 +:10067000897F90910901892B83BF10920901789499 +:1006800083B7816083BF889583B78E7F83BFEFCFA9 +:100690001F920F920FB60F9211242F933F934F93F7 +:1006A0005F936F937F938F939F93AF93BF93EF93DA +:1006B000FF938091B900887F803AF1F160F4883629 +:1006C00009F43FC028F4882391F18036D1F134C079 +:1006D000803839F031C0883B41F170F5883A29F112 +:1006E0002BC08091BB00F1100FC0982F92959F7086 +:1006F000F92E982F9F7090932F0110923301109232 +:100700002A0187FF1EC00AC0E0913301EF5FE3704A +:10071000E0933301F0E0E15DFE4F808338DE882313 +:1007200081F08091BC008F7B0AC0BEDE0AC0809140 +:10073000BC0080698093BC008091BC008064809381 +:10074000BC008091BC0080688093BC00FF91EF9159 +:10075000BF91AF919F918F917F916F915F914F91D9 +:100760003F912F910F900FBE0F901F9018951F92E1 +:100770000F920FB60F9211242F933F934F935F93D5 +:100780006F937F938F939F93AF93BF93EF93FF9359 +:1007900080910B018F5F883C18F480930B010CC093 +:1007A00010920B0180910A018F5F843618F48093B8 +:1007B0000A0102C010920A0187B58D3311F08DE352 +:1007C00001C08EE387BD80912001882371F0809164 +:1007D0002001813021F0883019F4ABDE01C093DDB7 +:1007E0008E2D8F3F11F08F5FE82E80912001813098 +:1007F00041F081E08D0D833010F4D82E01C0D12C52 +:1008000005DDFF20A1F080912A018F5F80932A01EE +:10081000823368F0F12C10922A018091BC008F7B0A +:100820008093BC008091BC0080648093BC0086B53E +:10083000FF91EF91BF91AF919F918F917F916F91B8 +:100840005F914F913F912F910F900FBE0F901F908E +:100850001895F999FECF81BDF89A992780B508952A +:10086000A8E1B0E042E005C010D0272F0FC0DC01A6 +:10087000862FE82FF999FECF05C0E1BDF89AE395E0 +:1008800000B40D924150C8F70895262FF999FECF74 +:100890001FBA81BD20BD0FB6F894FA9AF99A0FBE1F +:0808A00001960895F894FFCFC2 +:0408A8000101010148 +:00000001FF diff --git a/attiny88_main/src/adc.c b/attiny88_main/src/adc.c new file mode 100644 index 0000000..455a004 --- /dev/null +++ b/attiny88_main/src/adc.c @@ -0,0 +1,107 @@ +/* + * adc.c + * + * Created: 6/9/2014 11:07:35 PM + * Author: true + */ + + +#include "adc.h" + +#include + + +volatile uint8_t adc_busy; +volatile uint8_t adc_reread; + +volatile uint16_t adc_result[ADC_MAX_FEEDBACK + 1]; +static uint8_t adc_averages; + +volatile uint8_t adc_read_mode; + + +/* functions */ +void adc_init() +{ + // make sure ADC power is enabled + PRR &= ~_BV(PRADC); + + // clear all settings; set the ADC prescaler bits to get 500KHz ADC clock (SYSCLK/16), disable auto trigger + ADCSRA = _BV(ADPS2) | _BV(ADPS0) | ~(_BV(ADATE)); + + // set to right-aligned mode + ADMUX &= ~(_BV(ADLAR)); + + // enable the ADC, enable interrupts + ADCSRA |= _BV(ADEN) | _BV(ADIE); +} + +void adc_channel(uint8_t channel, uint8_t vref) +{ + // can we set channel? + if (channel < ADC_CHAN_INVALID) { + // set MUX[3:0] to the specified channel + ADMUX = (ADMUX & 0xf0) | (channel & 0x0f); + // also, if this is an actual pin, disable digital input on this pin + DIDR0 = (channel < 8) ? _BV(channel) : 0; + } + + // set the voltage source + if (vref == ADC_REF_AVCC) { + ADMUX |= (_BV(REFS0)); + } else if (vref == ADC_REF_BANDGAP) { + ADMUX &= ~(_BV(REFS0)); + } +} + +uint8_t adc_start(uint8_t reread, uint8_t enable_averaging) +{ + // is a conversion already running? + if (ADCSRA & _BV(ADSC)) { + return 1; + } + + // set up amount of times to re-read, and mark the amount of values to average + adc_reread = reread; + adc_averages = enable_averaging ? reread : 0; + + // start conversion + adc_busy = 0x80 | (ADMUX & 0x0f); + ADCSRA |= _BV(ADSC); + return 0; +} + + +/* ISR */ +ISR(ADC_vect) +{ + uint8_t channel; + + channel = ADMUX & 0x0f; + + // mark our result in the average table + if (adc_averages) { + // except for the first read + if (adc_averages != adc_reread) { + // we do successive averaging; it's faster, smaller code, less RAM, and good enough for our purpose + // update our feedback + if (channel <= ADC_MAX_FEEDBACK) { + adc_result[channel] = (adc_result[channel] + ADC) >> 1; + } + } + } + + if (adc_reread) { + adc_reread--; + // start another conversion + ADCSRA |= _BV(ADSC); + } else { + // determine if we need to update feedback + if (!adc_averages && channel <= ADC_MAX_FEEDBACK) { + // not averaging, so just store last result + adc_result[channel] = ADC; + } + + adc_busy = 0; + } +} \ No newline at end of file diff --git a/attiny88_main/src/adc.h b/attiny88_main/src/adc.h new file mode 100644 index 0000000..7c0559a --- /dev/null +++ b/attiny88_main/src/adc.h @@ -0,0 +1,56 @@ +/* + * adc.h + * + * Created: 6/9/2014 11:07:51 PM + * Author: true + */ + + +#ifndef ADC_H_ +#define ADC_H_ + + +#include "config.h" + + +#define ADC_CHAN_0 0 +#define ADC_CHAN_1 1 +#define ADC_CHAN_2 2 +#define ADC_CHAN_3 3 +#define ADC_CHAN_4 4 +#define ADC_CHAN_5 5 +#define ADC_CHAN_6 6 +#define ADC_CHAN_7 7 +#define ADC_CHAN_TEMP 8 +#define ADC_CHAN_BANDGAP 14 +#define ADC_CHAN_GND 15 +#define ADC_CHAN_INVALID ADC_CHAN_GND + 1 // one above last valid channel + +#define ADC_REF_AVCC 1 +#define ADC_REF_BANDGAP 2 +#define ADC_REF_NO_SET 255 + +#define ADC_MAX_FEEDBACK ADC_CHAN_TEMP + +// adc read interrupt +extern volatile uint8_t adc_busy; +extern volatile uint16_t adc_result[ADC_MAX_FEEDBACK + 1]; + +// main timer adc handler +extern volatile uint8_t adc_read_mode; +register uint8_t adc_read_step asm("r14"); + + +/* application specific */ +#define ADC_READ_LED_RED ADC_CHAN_0 +#define ADC_READ_LED_GREEN ADC_CHAN_1 +#define ADC_READ_LED_BLUE ADC_CHAN_2 + + +/* prototypes */ +void adc_init(); +void adc_channel(uint8_t channel, uint8_t bandgap_ref); +uint8_t adc_start(uint8_t reread, uint8_t enable_averaging); + + +#endif /* ADC_H_ */ \ No newline at end of file diff --git a/attiny88_main/src/config.h b/attiny88_main/src/config.h new file mode 100644 index 0000000..627ca27 --- /dev/null +++ b/attiny88_main/src/config.h @@ -0,0 +1,34 @@ +/* + * config.h + * + * Created: 5/24/2014 9:22:14 AM + * Author: true + */ + + +#ifndef CONFIG_H_ +#define CONFIG_H_ + + +#include + +#include +#include + + +// system +#define F_CPU 8000000UL + + +// LEDs +#define LED_COMMON_ANODE // defined = common anode, undef = common cathode +//#define LED_RGBX_4LED 1 // defined = use 4 LEDs (RGBX), undef = use 3 LEDs (RGB) + + +// i2c config +#define I2C_SLAVE_ADDRESS 0x73 // 7-bit address (0b1110011) +#define I2C_ENABLE_ADDR_ZERO 0 // 1 = enable response on 0x00, 0 = disable + + + +#endif /* CONFIG_H_ */ \ No newline at end of file diff --git a/attiny88_main/src/i2c.h b/attiny88_main/src/i2c.h new file mode 100644 index 0000000..de45bde --- /dev/null +++ b/attiny88_main/src/i2c.h @@ -0,0 +1,60 @@ +/* + * i2c.h + * + * Created: 5/21/2014 11:41:32 PM + * Author: true + */ + + +#ifndef I2C_H_ +#define I2C_H_ + + +#include "config.h" + + +/* macros */ +#define i2c_clear_int_flag() TWCR |= _BV(TWINT) + +#define i2c_disable_interrupt() TWCR &= ~(_BV(TWIE)) +#define i2c_enable_interrupt() TWCR |= _BV(TWIE) + +#define i2c_disable_slave() TWCR &= ~(_BV(TWEA)) +#define i2c_enable_slave() TWCR |= _BV(TWEA) + + +/* configuration */ +static inline void i2c_slave_init(uint8_t address, uint8_t enable_general_addr) +{ + // set bitrate register, clear prescaler + // should get us 400KHz (fast mode) max rate + TWBR = 2; + TWSR = ~(_BV(TWPS0) | _BV(TWPS1)); + + // set slave address and clear address mask + TWAR = ((address << 1) | (enable_general_addr & 1)); + TWAMR = 0; + + // enable auto-ack, enable TWI, and enable the TWI interrupt + TWCR = _BV(TWEA) | _BV(TWEN) | _BV(TWIE); +} + +/* sending */ +static uint8_t i2c_slave_tx(uint8_t byte, uint8_t is_last_byte) +{ + // load data + TWDR = byte; + + // start sending + TWCR |= _BV(TWINT); + + if (is_last_byte) { + // this is all the data we have to send; send a nack after this byte + i2c_disable_slave(); + } + + return 0; +} + + +#endif /* I2C_H_ */ \ No newline at end of file diff --git a/attiny88_main/src/i2c_interrupt.h b/attiny88_main/src/i2c_interrupt.h new file mode 100644 index 0000000..b14cced --- /dev/null +++ b/attiny88_main/src/i2c_interrupt.h @@ -0,0 +1,102 @@ +/* + * i2c_interrupt.h + * + * Created: 6/13/2014 1:53:36 AM + * Author: true + */ + + +#ifndef I2C_INTERRUPT_H_ +#define I2C_INTERRUPT_H_ + + +#include "config.h" + + +ISR(TWI_vect) +{ + // i2c is low priority - allow it to be interrupted + // sei(); + + // figure out wtf to do + switch (TWSR & 0xf8) { // TWI state + // ** SLAVE RECEIVE ** // + case 0x60: // slave addr+write receive to valid address + case 0x68: { // slave addr+write arbitration lost? + // nothing to do. we're ready to receive. + break; + } + /* + case 0x70: + case 0x78: { + // unused: this is for genaddr mode. + } + */ + case 0x80: { // slave data receive w/ACK returned + if (pegleg_data_rx(TWDR)) { + // I wanted to send a NAK, but TWI already sent an ACK. oh fucking well. + // send NACK if any further packets are received + i2c_disable_slave(); + } + break; + } + /*case 0x90: { // slave genaddr data receive w/ACK returned + // not using this + }*/ + + case 0x88: // slave data receive w/NACK returned, no longer addressed + //case 0x98: // slave genaddr data receive w/NACK returned, no longer addressed + case 0xa0: { // STOP asserted; done receiving? no longer addressed + // we can re-enable the slave... + i2c_enable_slave(); + break; + } + + // ** SLAVE TRANSMIT ** // + case 0xa8: { // slave read request to valid address + // try to send data + pegleg_data_tx(); + break; + } + case 0xb8: { // slave read continues, master ACK'd last packet + // do we have a mode in progress? + // NOTE: by default, slave tx modes won't unset, but slave mode will be disabled + // when the last packet is sent, and re-enabled on the following ACK/NACK. + pegleg_data_tx(); + break; + } + + case 0xb0: // arbitration lost + // I don't even know how the fuck this happened + case 0xc0: // slave read ends, master doesn't want more data + // this usually happens after we've sent data and master doesn't want any more. + // if we had more data, tough shit, master doesn't want it. so we don't send it. + case 0xc8: { // slave read ends, master wants more data though + // this usually happens after we're done sending, but master is requesting more. + // but slave mode is disabled, so don't send anything. + // we need to make sure send mode is disabled, and we need to re-enable slave mode. + i2c_enable_slave(); + break; + } + + // ** ERROR AND UNHANDLED ** // + case 0x00: { // bus error + // set TWSTO, clear TWINT (by setting) as per datasheet + TWCR |= (_BV(TWSTO)) | (_BV(TWINT)); + // and make sure slave is enabled + i2c_enable_slave(); + break; + } + default: { + // something unhandled? fuck it, we want to be a slave. + // reset everything and start over. + i2c_enable_slave(); + } + } + + // done with this TWI bit + i2c_clear_int_flag(); +} + + +#endif /* MAIN_INTERRUPT_H_ */ \ No newline at end of file diff --git a/attiny88_main/src/led.c b/attiny88_main/src/led.c new file mode 100644 index 0000000..1d9b0d4 --- /dev/null +++ b/attiny88_main/src/led.c @@ -0,0 +1,164 @@ +/* + * led.c + * + * Created: 6/13/2014 1:44:28 AM + * Author: true + */ + + +#include "led.h" + + +/* led */ +uint8_t rgbled_pwm_lf[4]; // pwm value for TIMER1 OCA LED outputs +uint8_t rgbled_pwm_rt[4]; // pwm value for TIMER1 OCB LED outputs + +static uint8_t rgbled_read_sel; // LED light sensor select +static uint8_t rgbled_sensitivity[4] = {1, 1, 1, 1}; + +/* adc */ +volatile uint8_t adc_busy; +volatile uint16_t adc_result[ADC_MAX_FEEDBACK + 1]; +volatile uint8_t adc_read_mode; + + +/* functions */ + // sets up the IO pins for LED output function. +void rgbled_io_init() +{ + // PortD[4:7] (left) and PortC[0:3] (right) are LEDs + // Also, Right LEDs are capable of ADC input on ALL pins (ADC[0:3]) + + // set all pins as outputs + DDRD |= 0xf0; + DDRC |= 0x0f; + +#ifdef LED_COMMON_ANODE + // com-anode: pin is high to disable + PORTD |= 0xf0; + PORTC |= 0x0f; +#else + // com-cathode: pin is low to disable + PORTD &= 0x0f; + PORTC &= 0xf0; +#endif +} + + // sets the appropriate pins and PWM values for the LED index specified in rgbled_idx. + // note: this index is updated externally, and not by this function. +void rgbled_update() +{ + // clear all selected LED pins + // we have to clear the select line then set it because we can't fully disable the PWM for some reason +#ifdef LED_COMMON_ANODE + // make sure all pins are high + PORTD |= 0xf0; + PORTC |= 0x0f; +#else + // make sure all pins are low + PORTD &= 0x0f; + PORTC &= 0xf0; +#endif + + // set pwm OCx registers to max + timer1_set_oca(TIMER1_COMPARE); + timer1_set_ocb(TIMER1_COMPARE); + // and set pwm counter value to 1 before expiry + timer1_set(TIMER1_COMPARE - 1); + + // now we set the desired LED + // turn on one LED in each group +#ifdef LED_COMMON_ANODE + // make sure active pin is output low and others are high + PORTD &= ~(_BV(rgbled_idx + 4)); + PORTC &= ~(_BV(rgbled_idx)); +#else + // make sure active pin is output high and others are low + PORTD |= _BV(rgbled_idx) << 4; + PORTC |= _BV(rgbled_idx); +#endif + + // load new pwm OCx values for this LED + timer1_set_oca(rgbled_pwm_lf[rgbled_idx]); + timer1_set_ocb(rgbled_pwm_rt[rgbled_idx]); +} + + // sets up the PortC LED matrix as a diode light sensor. + // configures the specified LED on the ADC. + // this function assumes common anode. +void rgbled_sensor_init(uint8_t led) +{ + // set the left eye high (fixes color flash/tearing) + PORTD |= 0xf0; + + // disable both eye's PWM (required for right eye, fixes color flash/tearing in left eye) + TCCR1A &= ~(_BV(COM1A1) | _BV(COM1A0) | _BV(COM1B1) | _BV(COM1B0)); + + // ground the LED + DDRC &= 0xf0; // set all LEDs cathode as inputs + MCUCR |= (_BV(PUD)); // globally disable pullups + DDRC |= (_BV(led)); // set our LED as an output + PORTC = (PORTC & 0xf0); // set all LEDs cathode low + PORTB |= (_BV(PORTB2)); // set anode high + + // reverse LED bias + PORTC |= (_BV(led)); // set cathode high + PORTB &= ~(_BV(PORTB2)); // set anode low + _delay_us(3); // allow it to charge fully + + // set LED as input + DDRC &= ~(_BV(led)); // set led cathode as input + PORTC &= ~(_BV(led)); // set led cathode pullup off + MCUCR &= ~(_BV(PUD)); // re-enable global pullups +} + + // starts ADC to read the value of charge remaining on the LED +void rgbled_sensor_sensitivity(uint8_t ledidx, uint8_t sensitivity) +{ + if (ledidx <= 0x03) { + if (sensitivity) { + rgbled_sensitivity[ledidx] = sensitivity; + } + } +} + +void rgbled_sensor_read_idx(uint8_t ledidx) +{ + rgbled_read_sel = ledidx & 0x03; +} + +void rgbled_sensor_read() +{ + uint8_t sens; + + sens = rgbled_sensitivity[rgbled_read_sel]; + if (!sens) sens = 1; + + if (adc_read_step == 0) { + // adc_init(); + // clear ADC bias by reading ground + adc_channel(ADC_CHAN_GND, ADC_REF_AVCC); + } else if (adc_read_step == 1) { + adc_start(0, 0); + } else if (adc_read_step == 2) { + // if the ADC is done, charge up LED for reading + if (adc_busy) { + adc_read_step--; + } else { + rgbled_sensor_init(rgbled_read_sel); + adc_channel(rgbled_read_sel, ADC_REF_NO_SET); + } + } else if (adc_read_step == (2 + sens)) { + // if vref has changed, it should be stable by now; start reading LED value + adc_start(3, 1); + } else if (adc_read_step > (2 + sens)) { + adc_read_step--; + if (!adc_busy) { + // we are done! :) finish up... + adc_channel(ADC_CHAN_GND, ADC_REF_NO_SET); // change ADC to not look at a real pin + rgbled_io_init(); // set LED pins up again + timer1_pwm_reinit(); // and set up PWM again + adc_read_mode = 0; // clear ADC read mode + } + } +} diff --git a/attiny88_main/src/led.h b/attiny88_main/src/led.h new file mode 100644 index 0000000..eca7944 --- /dev/null +++ b/attiny88_main/src/led.h @@ -0,0 +1,44 @@ +/* + * led.h + * + * Created: 6/13/2014 1:40:53 AM + * Author: true + */ + + +#ifndef LED_H_ +#define LED_H_ + + +/* incl */ +#include "config.h" + +#include + +#include "adc.h" +#include "timer.h" + + +/* led */ +#define LED_RED 0 +#define LED_GREEN 1 +#define LED_BLUE 2 +#define LED_SPARE 3 + + +/* globals */ +extern uint8_t rgbled_pwm_lf[4]; // pwm value for TIMER1 OCA LED outputs +extern uint8_t rgbled_pwm_rt[4]; // pwm value for TIMER1 OCB LED outputs +register uint8_t rgbled_idx asm("r13"); // the currently operated LED + + +/* prototypes */ +void rgbled_io_init(); +void rgbled_update(); + +void rgbled_sensor_sensitivity(uint8_t ledidx, uint8_t sensitivity); +void rgbled_sensor_read_idx(uint8_t ledidx); +void rgbled_sensor_read(); + + +#endif /* LED_H_ */ \ No newline at end of file diff --git a/attiny88_main/src/main.c b/attiny88_main/src/main.c new file mode 100644 index 0000000..72dbb7f --- /dev/null +++ b/attiny88_main/src/main.c @@ -0,0 +1,574 @@ +/* + * Whiskey Pirates Badge "PEGLEG CPU" + * Sub MCU Firmware for ATtiny88 + * + * Created: 5/21/2014 9:24:48 PM + * Author: true + * ts:4 + * + ******** + * PEGLEG CPU is responsible for: + * - aux gpio (todo: list specifically which GPIOs on the badge) + * - eye RGBLED matrix + * - temperature sensor + * - light sensor (using eye RGBLEDs; in practice uses the left eye red LED) + * - user config eeprom + * + ******** + * Use the following fuses for this project. Needs to run at 8MHz for 400khz I2C operation. + * 8MHz, self-program enabled (bootloader support), preserve EEPROM, BOD disabled, ISP enabled + * -U lfuse:w:0xEE:m -U hfuse:w:0xD7:m -U efuse:w:0x00:m + * (efuse will likely show as 0x06 after setting; this is fine, don't worry about it) + * + * Resources used: Mainline ISR 5% (3/63 timer counts simulated, as of some old rev) + * Flash 26.8%, SRAM 10.4% (as of the above rev) + * + ********** + * Register Variables: + * main.c:comm_cmd:r15 + * adc.h:adc_read_step:r14 + * led.c:rgbled_idx:r13 + */ + + +#include "config.h" + + +/* system */ +#include +#include +#include +#include + +#include + + +#include "i2c.h" + +#include "timer.h" +#include "adc.h" +#include "led.h" + + + +/* modes (commands) */ +#define MODE_NONE 0b0000 + +#define MODE_EXT_CMD 0b0001 // bit 4 unset = extra parameters needed, up to 6 commands +#define MODE_LED_SET_LEVEL 0b0010 // (0x00 reserved, 0x1? extra, leaving 0x2? through 0x7?) +#define MODE_TEMPSENSOR_CAL 0b0011 +#define MODE_EEPROM_READ 0b0100 +#define MODE_EEPROM_WRITE 0b0101 + +#define MODE_TEMPSENSOR_READ 0b1000 // bit 4 set = immediate, no extra parameters, process now +#define MODE_LIGHTSENSOR_READ 0b1001 +#define MODE_SLEEP 0b1111 + +#define MODE_AUX_PIN_GET 0x10 // extended (send 0x10, cmd, data...) +#define MODE_AUX_PIN_SET 0x11 // ext commands MUST be 0x10 or higher! 0x00-0x0f are RESERVED! +#define MODE_LIGHTSENSOR_SENS 0x19 + +/* aux pin mode */ +#define AUX_PIN_COUNT 10 +#define AUX_PIN_OUTPUT 0x01 // sets to output if set, input if cleared +#define AUX_PIN_PORTSET 0x02 // output: sets high/low; input: sets pullup on/off + +/* adc modes */ +#define ADC_MODE_TEMPSENSOR 8 +#define ADC_MODE_LIGHTSENSOR 1 + + +/* prototypes */ +static void system_init(); +static void system_io_init(); +static void tempsensor_cal(); + + +/* globals */ +static uint8_t tim0_milli; +static uint8_t tim0_centi; +static uint8_t tim0_profiler; + +#define COMM_DATA_SIZE 4 // must be power of 2; default value is 4 +register uint8_t comm_cmd asm("r15"); // currently processed SPI command +uint8_t comm_data_idx; // command data write index +uint8_t comm_data[COMM_DATA_SIZE]; // command data register +uint8_t comm_timeout; // command invalidate timeout + + +/* core */ +static uint8_t pirate_sleep_mode = SLEEP_MODE_IDLE; + +/* tempsensor */ +static int8_t temperature; +static int16_t temp_offset; + +/* eeprom */ +#define EEPROM_ADDR_TEMPCAL 62 // 2 bytes + +/* adc */ +volatile uint8_t adc_busy; +volatile uint16_t adc_result[ADC_MAX_FEEDBACK + 1]; + +/* led */ +uint8_t rgbled_pwm_lf[4]; // pwm value for TIMER1 OCA LED outputs +uint8_t rgbled_pwm_rt[4]; // pwm value for TIMER1 OCB LED outputs + +uint8_t rgbled_light_level[4]; + + + +/* it begins */ +int main(void) +{ + // configure device and IO + system_init(); + system_io_init(); + + // configure RGBLEDs + rgbled_io_init(); + + // configure i2c communications + i2c_slave_init(I2C_SLAVE_ADDRESS, I2C_ENABLE_ADDR_ZERO); + + // configure system timer + timer0_init(); + // configure led pwm timer + timer1_init(); + + // initialize adc + adc_init(); + + // try calibrating temperature sensor if needed + tempsensor_cal(); + + // and now we wait. + while (1) { + // set sleep mode, then set for idle sleep (CPU off, all peripherals on) + set_sleep_mode(pirate_sleep_mode); + pirate_sleep_mode = SLEEP_MODE_IDLE; + + // re-enable interrupts and nap. + sei(); + sleep_mode(); + } +} + + +/* func */ +static void system_init() +{ + // make SURE we are running at 8MHz + // do this by first enabling clock divider setup mode, + CLKPR = _BV(CLKPCE); + // and disabling any divider + CLKPR = 0; +} + +static void system_io_init() +{ + // enable break-before-make outputs on all IO + PORTCR |= (_BV(BBMA) | _BV(BBMB) | _BV(BBMC) | _BV(BBMD)); + + // set ALL pins as inputs except PB0 + DDRA = 0x00; + DDRB = 0x01; + DDRC = 0x00; + DDRD = 0x00; + + // and enable pullups (this reduces power consumption) + // in the case of PB0, set it LOW + PORTA = 0xff; + PORTB = 0xfe; + PORTC = 0xff; + PORTD = 0xff; +} + +/* temperature */ +uint8_t tempsensor_process() +{ + int8_t temp_gain; + int8_t temp_adj; + + temp_adj = adc_result[ADC_CHAN_TEMP] - temp_offset; // our offset adjusted temperature + temp_gain = temp_adj >> 3; // our gain adjust amount + while (temp_gain > 0) {temp_gain--; temp_adj--;}; // correct positive gain + while (temp_gain < 0) {temp_gain++; temp_adj++;}; // correct negative gain + + // save temperature + return temp_adj; +} + +void tempsensor_read() +{ + if (adc_read_step == 0) { + // select temperature channel + adc_channel(ADC_CHAN_TEMP, ADC_REF_BANDGAP); + + } else if (adc_read_step == 3) { + // we've waited 1.5ms so the bandgap voltage should have been set. + // start conversion after bandgap ref change timeout per datasheet + adc_start(4, 1); + + } else if (adc_read_step > 3) { + adc_read_step--; + + if (!adc_busy) { + // revert reference to AVCC...per the datasheet only changes to + // bandgap should take ~1ms but changes back to AVCC seem to + // take a while to be accurate as well + adc_channel(ADC_CHAN_GND, ADC_REF_AVCC); + adc_read_mode = 0; + temperature = tempsensor_process(); + } + } +} + +void tempsensor_cal() +{ + // NOTE: CALIBRATION IS SINGLE-POINT TO 0 DEGREES CENTIGRADE! ICE YOUR PEGLEG, MOTHERFUCKER! + // todo: figure out wtf I meant by this note in 2014 (this is me in 2023) + // looking at the code, it looks like a pin needs manually changed to calibrate. + // todo: add a zeroing offset calibration command to the command protocol? + + // is pin PA2 low? (pin 3 on attiny88 - is pulled up - short to pin 5 / ground somewhere) + if ((PINA & _BV(PINA2)) == 0) { + // turn on the ADC, wait for it to warm up + adc_init(); + _delay_ms(100); // todo: is this right? this seems slow + + // is the pin still low? not a glitch? + if ((PINA & _BV(PINA2)) == 0) { + // enable interrupts + sei(); + + // start reading the temp sensor; stall until adc is done + adc_read_mode = ADC_MODE_TEMPSENSOR; + tempsensor_read(); + while (adc_busy); + + // here's our correction factor! + temp_offset = adc_result[ADC_CHAN_TEMP]; + + // write it to eeprom + eeprom_write_word((uint16_t *)EEPROM_ADDR_TEMPCAL, temp_offset); + + // and that's it - we're done. + adc_read_mode = 0; + return; + } + } + + // not saving a value - read the value from eeprom + temp_offset = eeprom_read_word((uint16_t *)EEPROM_ADDR_TEMPCAL); + + // does it seem invalid? + if (temp_offset > 560) { + // yeah, this isn't right. load rough value for 0degC from datasheet. + // but you really should calibrate your chip, you lazy fuck. + temp_offset = 273; + } +} + +/* comms */ +static inline uint8_t pegleg_data_tx() +{ + uint8_t ret; + + switch (comm_cmd) { + case MODE_EEPROM_READ: { + if (comm_data[0] < 64) { + i2c_slave_tx(eeprom_read_byte((uint8_t *)(uint16_t)comm_data[0]), 1); + ret = 1; + } else { + // invalid address... + i2c_disable_slave(); + ret = 255; + } + comm_cmd = 0; + comm_timeout = 0; + return ret; + } + + case MODE_TEMPSENSOR_READ: { + i2c_slave_tx(temperature, 1); + comm_cmd = 0; + comm_timeout = 0; + return 1; + } + case MODE_LIGHTSENSOR_READ: { + i2c_slave_tx(adc_result[comm_data[0] & 0x03] >> 2, 1); + comm_cmd = 0; + comm_timeout = 0; + return 1; + } + + default: { + // nothing active; invalid :( + i2c_disable_slave(); + return 255; + } + } + + return 0; +} + +static uint8_t pegleg_cmd() +{ + switch (comm_cmd) { + // no command: we just ACK this as we shouldn't ever get here + case MODE_NONE: { + comm_cmd = 0; + comm_timeout = 0; + break; + } + + // standard commands + case MODE_EXT_CMD: { // used for more commands + if (comm_data_idx >= 1) { + comm_cmd = comm_data[1]; + // set data index to last (will be reset on next data sent) + // and also reset timeout since this is effectively a new command + comm_data_idx = COMM_DATA_SIZE - 1; + comm_timeout = 0; + } + break; + } + + case MODE_LED_SET_LEVEL: { // sets PWM rate for the 8 PWM LEDs + if (comm_data[0] < 4) { + rgbled_pwm_lf[comm_data[0]] = comm_data[1]; + } else if (comm_data[0] < 8) { + rgbled_pwm_rt[comm_data[0] - 4] = comm_data[1]; + } + comm_cmd = 0; + comm_timeout = 0; + break; + } + + case MODE_TEMPSENSOR_CAL: { + // to use this function, make sure the temperature has been previously read. + // calculates the appropriate offset based on the reported temperature. + if (comm_data_idx >= 1) { + // update the offset + if (adc_result[ADC_CHAN_TEMP]) { + temp_offset = adc_result[ADC_CHAN_TEMP] - (int8_t)comm_data[1]; + // write it to eeprom + eeprom_write_word((uint16_t *)EEPROM_ADDR_TEMPCAL, temp_offset); + // and that's it - we're done. + comm_cmd = 0; + comm_timeout = 0; + } else { + // no valid read performed; I fucking told you to do this! + comm_cmd = 0; + comm_timeout = 0; + return 1; + } + } + break; + } + + case MODE_EEPROM_READ: { + // our data packet is already set; ready for read. + // but if the host keeps writing... + if (comm_data_idx > 1) { + comm_cmd = 0; + comm_timeout = 0; + } + break; + } + case MODE_EEPROM_WRITE: { + // TODO: implement + comm_cmd = 0; + comm_timeout = 0; + break; + } + + // immediate commands + case MODE_TEMPSENSOR_READ: { + // attempt another read + if (!adc_read_mode) { + adc_read_mode = 0; + adc_read_step = 0; + adc_read_mode = ADC_MODE_TEMPSENSOR; + } + + // now we are ready to read. + // data will probably be prior data unless the host waits. (need to verify) + comm_timeout = 0; + break; + } + case MODE_LIGHTSENSOR_READ: { + if (!adc_read_mode) { + // set the led and step to first step + adc_read_mode = 0; + adc_read_step = 0; + rgbled_sensor_read_idx(comm_data[0]); + adc_read_mode = ADC_MODE_LIGHTSENSOR; + } + + // now we are ready to read. + // data will probably be prior data unless the host waits. + comm_timeout = 0; + break; + } + case MODE_SLEEP: { + // put this bitch to bed. + // we'll wake up when we get another I2C command. + pirate_sleep_mode = SLEEP_MODE_PWR_DOWN; + + comm_cmd = 0; + comm_timeout = 0; + break; + } + + // extended commands + case MODE_AUX_PIN_SET: { + // TODO: come up with an implementation that isn't shitty + } + + case MODE_AUX_PIN_GET: { + // TODO: implement when response sending is ...implemented + comm_cmd = 0; + comm_timeout = 0; + break; + } + case MODE_LIGHTSENSOR_SENS: { // 0x10 0x19 + if (comm_data_idx >= 1) { + if ((comm_data[0] <= 0x03) && (comm_data[1])) { + rgbled_sensor_sensitivity(comm_data[0], comm_data[1]); + } + comm_cmd = 0; + comm_timeout = 0; + } + break; + } + + // invalid commands + default: { + // send NAK + comm_cmd = 0; + comm_timeout = 0; + return 1; + } + } + + return 0; +} + +static uint8_t pegleg_data_rx(uint8_t data) +{ + if (comm_cmd == MODE_NONE) { + // we aren't processing any commands, so this must be a new command/request. + // first 4 bits = command + comm_cmd = data >> 4; + // last 4 bits = optional data + comm_data[0] = data & 0x0f; + + // clear our data watchdog and data index + comm_data_idx = 0; + comm_timeout = 0; + + // if this is an immediate command, process it + if (data & 0x80) { + return pegleg_cmd(); + } + } else { + // command in progress - add data and continue + comm_data_idx++; + comm_data_idx &= (COMM_DATA_SIZE - 1); // data will LOOP in case of problems; TODO: NAK on failure + comm_data[comm_data_idx] = data; + return pegleg_cmd(); + } + + return 0; +} + +#include "i2c_interrupt.h" + + +/* ISR handlers */ +ISR(TIMER0_COMPA_vect) +{ + /**** + * this mainline loop runs at 2KHz, or 0.5ms. + * at the faster speed, this is ~3968 cycles/loop @8MHz. + ****/ + + /* TIMEKEEPING */ + // we only count a total of 10 seconds this way before we loop. + tim0_milli++; + if (tim0_milli >= 200) { + tim0_milli = 0; + tim0_centi++; + if (tim0_centi >= 100) { + tim0_centi = 0; + } + } + + // 2khz fix. our timer isn't evenly divisible to get our 2K, so we do this... + OCR0A = (OCR0A == TIMER0_COMPARE) ? TIMER0_COMPARE + 1 : TIMER0_COMPARE; + + + /* ADC / LIGHT SENSOR / TEMP SENSOR */ + // main adc handler + if (adc_read_mode) { + switch (adc_read_mode) { + case ADC_MODE_TEMPSENSOR: { + tempsensor_read(); + break; + } + case ADC_MODE_LIGHTSENSOR: { + rgbled_sensor_read(); + break; + } + } + + if (adc_read_step <= 0xfe) { + adc_read_step++; + } + } /* else { + if (adc_read_step != 0xff) { + adc_read_step++; + if (adc_read_step == 0xff) { + // disable the ADC + ADCSRA &= ~(_BV(ADEN)); + } + } + } */ // NOTE: we need to keep the ADC enabled; it takes too long to warm up. + + + /* LEDs */ + // TODO: test common cathode mode + // figure out next LED to update (order is always RGB(X) repeating) + if (adc_read_mode != ADC_MODE_LIGHTSENSOR) { + rgbled_idx++; +#ifdef LED_RGBX_4LED + rgbled_idx &= 0x03; +#else + if (rgbled_idx > 2) { + rgbled_idx = 0; + } +#endif + + // and now update them + rgbled_update(); + } + + + /* COMMAND IO */ + // stop processing the command if it isn't complete in 100ms. + if (comm_cmd != MODE_NONE) { + if (++comm_timeout >= 50) { + comm_cmd = MODE_NONE; + comm_timeout = 0; + i2c_disable_slave(); + i2c_enable_slave(); + } + } + + /* PROFILING */ + // determine how much CPU usage we are consuming + tim0_profiler = TCNT0; +} + diff --git a/attiny88_main/src/timer.h b/attiny88_main/src/timer.h new file mode 100644 index 0000000..6f11f7b --- /dev/null +++ b/attiny88_main/src/timer.h @@ -0,0 +1,110 @@ +/* + * timer.h + * + * Created: 5/21/2014 10:45:08 PM + * Author: true + */ + + +#ifndef TIMER_H_ +#define TIMER_H_ + + +#include "led.h" + + +#define TIMER0_COMPARE 62 - 1 +#define TIMER1_COMPARE 252 - 1 // divisible by 63 which is set every other round for timer0 + + +uint8_t timer1_mode; + + +/* prototypes */ + + +/* implementations */ +inline static void timer0_init() +{ + // make sure timer is enabled + PRR &= ~PRTIM0; + + // enable timer with prescale divider /64, enable TOP mode + TCCR0A = _BV(CTC0) | (_BV(CS00) | _BV(CS01) | ~(_BV(CS02))); + + // set TOP level to be 62 to 63 counts; this will result in 2KHz cycle @8MHz + OCR0A = TIMER0_COMPARE; + + // clear timer + TCNT0 = 0; + + // and enable OCA interrupt (we don't use overflow interrupt as we are in TOP mode) + TIMSK0 = _BV(OCIE0A); +} + +#define timer0_set_compare(x) OCR0A = x + +inline static void timer1_init() +{ + // make sure timer is enabled + PRR &= ~PRTIM1; + + // clear PWM OCx + OCR1AH = 0xff; // sets temp register to 0xff + OCR1AL = 0xff; + OCR1BL = 0xff; + + // clear timer + TCNT1H = 0; // sets temp register to 0 + TCNT1L = 0; + + // enable timer OC1 and OC2 clear on match / set at TOP, set to fast PWM mode 14 (ICR1 compare), prescaler off + // note: in PWM mode 14, pin PB0 can only be used as an output... =( + TCCR1A = (_BV(COM1A1)) | (_BV(COM1B1)) | (_BV(WGM11) | ~(_BV(WGM10))); + TCCR1B = (_BV(WGM12) | _BV(WGM13)) | (_BV(CS10)); + TCCR1C = 0; + + // store timer1 mode to allow enabling / disabling timer + timer1_mode = TCCR1A; + + // set ICR compare to result in a PWM rate of 8MHz / 252, or 32256Hz + // This is 16 PWM updates per timer0 63-count period (16.25 per 62-count period) + // In practice we don't get the first PWM output, so we get: + // 15/16 PWM / (x) LEDs = 31.25% max duty for 3 LED, 23.43% max duty for 4 LED + ICR1L = TIMER1_COMPARE; + + // set OC pins as outputs + DDRB |= (_BV(DDB2) | _BV(DDB1)); + + // disable interrupts + TIMSK1 = 0; +} + +inline void timer1_pwm_reinit() +{ + // enable pwm output on OCx pins + TCCR1A = (_BV(COM1A1)) | (_BV(COM1B1)) | (_BV(WGM11) | ~(_BV(WGM10))); + + // set OC pins as outputs + DDRB |= (_BV(DDB2) | _BV(DDB1)); +} + +inline void timer1_set(uint16_t set) +{ + TCNT1 = set; +} + + +#define timer1_disable() TCCR1A = 0 +#define timer1_enable() TCCR1A = timer1_mode; + +#ifdef LED_COMMON_ANODE + #define timer1_set_oca(v) OCR1AL = TIMER1_COMPARE - v + #define timer1_set_ocb(v) OCR1BL = TIMER1_COMPARE - v +#else + #define timer1_set_oca(v) OCR1AL = TIMER1_COMPARE + #define timer1_set_ocb(v) OCR1BL = TIMER1_COMPARE +#endif + + +#endif /* TIMER_H_ */ \ No newline at end of file diff --git a/attiny88_main/wp_dc22_attiny88.atsln b/attiny88_main/wp_dc22_attiny88.atsln new file mode 100644 index 0000000..9d796fe --- /dev/null +++ b/attiny88_main/wp_dc22_attiny88.atsln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Atmel Studio Solution File, Format Version 11.00 +Project("{54F91283-7BC4-4236-8FF9-10F437C3AD48}") = "wp_dc22_attiny88", "wp_dc22_attiny88.cproj", "{0AAADF73-70F0-4C23-875D-53CCE8ABBF9B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|AVR = Debug|AVR + Release|AVR = Release|AVR + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {0AAADF73-70F0-4C23-875D-53CCE8ABBF9B}.Debug|AVR.ActiveCfg = Debug|AVR + {0AAADF73-70F0-4C23-875D-53CCE8ABBF9B}.Debug|AVR.Build.0 = Debug|AVR + {0AAADF73-70F0-4C23-875D-53CCE8ABBF9B}.Release|AVR.ActiveCfg = Release|AVR + {0AAADF73-70F0-4C23-875D-53CCE8ABBF9B}.Release|AVR.Build.0 = Release|AVR + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/attiny88_main/wp_dc22_attiny88.componentinfo.xml b/attiny88_main/wp_dc22_attiny88.componentinfo.xml new file mode 100644 index 0000000..49c3862 --- /dev/null +++ b/attiny88_main/wp_dc22_attiny88.componentinfo.xml @@ -0,0 +1,86 @@ + + + + + + + Device + Startup + + + Atmel + 1.3.0 + C:/Program Files (x86)\Atmel\Studio\7.0\Packs + + + + + C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATtiny_DFP\1.3.172\include + + include + C + + + include + + + + + C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATtiny_DFP\1.3.172\include\avr\iotn88.h + + header + C + S2HUptOYqYmhL8kjFIMzIA== + + include/avr/iotn88.h + + + + + C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATtiny_DFP\1.3.172\templates\main.c + template + source + C Exe + GD1k8YYhulqRs6FD1B2Hog== + + templates/main.c + Main file (.c) + + + + C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATtiny_DFP\1.3.172\templates\main.cpp + template + source + C Exe + YXFphlh0CtZJU+ebktABgQ== + + templates/main.cpp + Main file (.cpp) + + + + C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATtiny_DFP\1.3.172\gcc\dev\attiny88 + + libraryPrefix + GCC + + + gcc/dev/attiny88 + + + + + ATtiny_DFP + C:/Program Files (x86)/Atmel/Studio/7.0/Packs/atmel/ATtiny_DFP/1.3.172/Atmel.ATtiny_DFP.pdsc + 1.3.172 + true + ATtiny88 + + + + Resolved + Fixed + true + + + \ No newline at end of file diff --git a/attiny88_main/wp_dc22_attiny88.cproj b/attiny88_main/wp_dc22_attiny88.cproj new file mode 100644 index 0000000..180c2cd --- /dev/null +++ b/attiny88_main/wp_dc22_attiny88.cproj @@ -0,0 +1,171 @@ + + + + 2.0 + 7.0 + com.Atmel.AVRGCC8.C + {0aaadf73-70f0-4c23-875d-53cce8abbf9b} + ATtiny88 + none + Executable + C + $(MSBuildProjectName) + .elf + $(MSBuildProjectDirectory)\$(Configuration) + wp_dc22_attiny88 + wp_dc22_attiny88 + wp_dc22_attiny88 + Native + true + false + true + true + 0x20000000 + + exception_table + 2 + 1 + + + + + + + + + + + + + True + com.atmel.avrdbg.tool.simulator + + + + false + + + + + com.atmel.avrdbg.tool.simulator + + + Simulator + + 0 + + + + + + -mmcu=attiny88 -B "%24(PackRepoDir)\atmel\ATtiny_DFP\1.3.172\gcc\dev\attiny88" + True + True + True + True + False + True + True + + + NDEBUG + + + + + %24(PackRepoDir)\atmel\ATtiny_DFP\1.3.172\include + + + Optimize for size (-Os) + True + True + True + + + libm + + + + + %24(PackRepoDir)\atmel\ATtiny_DFP\1.3.172\include + + + + + + + + + -mmcu=attiny88 -B "%24(PackRepoDir)\atmel\ATtiny_DFP\1.3.172\gcc\dev\attiny88" + True + True + True + True + False + True + True + + + DEBUG + + + + + %24(PackRepoDir)\atmel\ATtiny_DFP\1.3.172\include + + + Optimize for size (-Os) + -finline-functions + True + True + Default (-g2) + True + True + + + libm + + + + + %24(PackRepoDir)\atmel\ATtiny_DFP\1.3.172\include + + + Default (-Wa,-g) + + + + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + + + + + \ No newline at end of file