wp_dc22_attiny88.elf: file format elf32-avr Sections: Idx Name Size VMA LMA File off Algn 0 .data 00000004 00800100 000008a8 0000093c 2**0 CONTENTS, ALLOC, LOAD, DATA 1 .text 000008a8 00000000 00000000 00000094 2**1 CONTENTS, ALLOC, LOAD, READONLY, CODE 2 .bss 00000030 00800104 00800104 00000940 2**0 ALLOC 3 .comment 00000030 00000000 00000000 00000940 2**0 CONTENTS, READONLY 4 .note.gnu.avr.deviceinfo 0000003c 00000000 00000000 00000970 2**2 CONTENTS, READONLY 5 .debug_aranges 00000178 00000000 00000000 000009b0 2**3 CONTENTS, READONLY, DEBUGGING 6 .debug_info 00001493 00000000 00000000 00000b28 2**0 CONTENTS, READONLY, DEBUGGING 7 .debug_abbrev 00000b12 00000000 00000000 00001fbb 2**0 CONTENTS, READONLY, DEBUGGING 8 .debug_line 00000e6a 00000000 00000000 00002acd 2**0 CONTENTS, READONLY, DEBUGGING 9 .debug_frame 00000230 00000000 00000000 00003938 2**2 CONTENTS, READONLY, DEBUGGING 10 .debug_str 000006f2 00000000 00000000 00003b68 2**0 CONTENTS, READONLY, DEBUGGING 11 .debug_loc 000004a9 00000000 00000000 0000425a 2**0 CONTENTS, READONLY, DEBUGGING 12 .debug_ranges 000000a8 00000000 00000000 00004703 2**0 CONTENTS, READONLY, DEBUGGING Disassembly of section .text: 00000000 <__vectors>: 0: 2d c0 rjmp .+90 ; 0x5c <__ctors_end> 2: 47 c0 rjmp .+142 ; 0x92 <__bad_interrupt> 4: 46 c0 rjmp .+140 ; 0x92 <__bad_interrupt> 6: 45 c0 rjmp .+138 ; 0x92 <__bad_interrupt> 8: 44 c0 rjmp .+136 ; 0x92 <__bad_interrupt> a: 43 c0 rjmp .+134 ; 0x92 <__bad_interrupt> c: 42 c0 rjmp .+132 ; 0x92 <__bad_interrupt> e: 41 c0 rjmp .+130 ; 0x92 <__bad_interrupt> 10: 40 c0 rjmp .+128 ; 0x92 <__bad_interrupt> 12: 3f c0 rjmp .+126 ; 0x92 <__bad_interrupt> 14: 3e c0 rjmp .+124 ; 0x92 <__bad_interrupt> 16: 3d c0 rjmp .+122 ; 0x92 <__bad_interrupt> 18: aa c3 rjmp .+1876 ; 0x76e <__vector_12> 1a: 3b c0 rjmp .+118 ; 0x92 <__bad_interrupt> 1c: 3a c0 rjmp .+116 ; 0x92 <__bad_interrupt> 1e: 39 c0 rjmp .+114 ; 0x92 <__bad_interrupt> 20: 8b c0 rjmp .+278 ; 0x138 <__vector_16> 22: 37 c0 rjmp .+110 ; 0x92 <__bad_interrupt> 24: 36 c0 rjmp .+108 ; 0x92 <__bad_interrupt> 26: 34 c3 rjmp .+1640 ; 0x690 <__vector_19> 28: bd c1 rjmp .+890 ; 0x3a4 2a: c0 c1 rjmp .+896 ; 0x3ac 2c: ca c1 rjmp .+916 ; 0x3c2 2e: db c1 rjmp .+950 ; 0x3e6 30: f8 c1 rjmp .+1008 ; 0x422 <__LOCK_REGION_LENGTH__+0x22> 32: 16 c2 rjmp .+1068 ; 0x460 <__LOCK_REGION_LENGTH__+0x60> 34: 28 c2 rjmp .+1104 ; 0x486 <__LOCK_REGION_LENGTH__+0x86> 36: 27 c2 rjmp .+1102 ; 0x486 <__LOCK_REGION_LENGTH__+0x86> 38: f9 c1 rjmp .+1010 ; 0x42c <__LOCK_REGION_LENGTH__+0x2c> 3a: 03 c2 rjmp .+1030 ; 0x442 <__LOCK_REGION_LENGTH__+0x42> 3c: 24 c2 rjmp .+1096 ; 0x486 <__LOCK_REGION_LENGTH__+0x86> 3e: 23 c2 rjmp .+1094 ; 0x486 <__LOCK_REGION_LENGTH__+0x86> 40: 22 c2 rjmp .+1092 ; 0x486 <__LOCK_REGION_LENGTH__+0x86> 42: 21 c2 rjmp .+1090 ; 0x486 <__LOCK_REGION_LENGTH__+0x86> 44: 20 c2 rjmp .+1088 ; 0x486 <__LOCK_REGION_LENGTH__+0x86> 46: 09 c2 rjmp .+1042 ; 0x45a <__LOCK_REGION_LENGTH__+0x5a> 48: 0b c2 rjmp .+1046 ; 0x460 <__LOCK_REGION_LENGTH__+0x60> 4a: 0a c2 rjmp .+1044 ; 0x460 <__LOCK_REGION_LENGTH__+0x60> 4c: 1c c2 rjmp .+1080 ; 0x486 <__LOCK_REGION_LENGTH__+0x86> 4e: 1b c2 rjmp .+1078 ; 0x486 <__LOCK_REGION_LENGTH__+0x86> 50: 1a c2 rjmp .+1076 ; 0x486 <__LOCK_REGION_LENGTH__+0x86> 52: 19 c2 rjmp .+1074 ; 0x486 <__LOCK_REGION_LENGTH__+0x86> 54: 18 c2 rjmp .+1072 ; 0x486 <__LOCK_REGION_LENGTH__+0x86> 56: 17 c2 rjmp .+1070 ; 0x486 <__LOCK_REGION_LENGTH__+0x86> 58: 16 c2 rjmp .+1068 ; 0x486 <__LOCK_REGION_LENGTH__+0x86> 5a: 07 c2 rjmp .+1038 ; 0x46a <__LOCK_REGION_LENGTH__+0x6a> 0000005c <__ctors_end>: 5c: 11 24 eor r1, r1 5e: 1f be out 0x3f, r1 ; 63 60: cf ef ldi r28, 0xFF ; 255 62: d2 e0 ldi r29, 0x02 ; 2 64: de bf out 0x3e, r29 ; 62 66: cd bf out 0x3d, r28 ; 61 00000068 <__do_copy_data>: 68: 11 e0 ldi r17, 0x01 ; 1 6a: a0 e0 ldi r26, 0x00 ; 0 6c: b1 e0 ldi r27, 0x01 ; 1 6e: e8 ea ldi r30, 0xA8 ; 168 70: f8 e0 ldi r31, 0x08 ; 8 72: 02 c0 rjmp .+4 ; 0x78 <__do_copy_data+0x10> 74: 05 90 lpm r0, Z+ 76: 0d 92 st X+, r0 78: a4 30 cpi r26, 0x04 ; 4 7a: b1 07 cpc r27, r17 7c: d9 f7 brne .-10 ; 0x74 <__do_copy_data+0xc> 0000007e <__do_clear_bss>: 7e: 21 e0 ldi r18, 0x01 ; 1 80: a4 e0 ldi r26, 0x04 ; 4 82: b1 e0 ldi r27, 0x01 ; 1 84: 01 c0 rjmp .+2 ; 0x88 <.do_clear_bss_start> 00000086 <.do_clear_bss_loop>: 86: 1d 92 st X+, r1 00000088 <.do_clear_bss_start>: 88: a4 33 cpi r26, 0x34 ; 52 8a: b2 07 cpc r27, r18 8c: e1 f7 brne .-8 ; 0x86 <.do_clear_bss_loop> 8e: 6d d2 rcall .+1242 ; 0x56a
90: 09 c4 rjmp .+2066 ; 0x8a4 <_exit> 00000092 <__bad_interrupt>: 92: b6 cf rjmp .-148 ; 0x0 <__vectors> 00000094 : /* functions */ void adc_init() { // make sure ADC power is enabled PRR &= ~_BV(PRADC); 94: e4 e6 ldi r30, 0x64 ; 100 96: f0 e0 ldi r31, 0x00 ; 0 98: 80 81 ld r24, Z 9a: 8e 7f andi r24, 0xFE ; 254 9c: 80 83 st Z, r24 // 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)); 9e: ea e7 ldi r30, 0x7A ; 122 a0: f0 e0 ldi r31, 0x00 ; 0 a2: 8f ed ldi r24, 0xDF ; 223 a4: 80 83 st Z, r24 // set to right-aligned mode ADMUX &= ~(_BV(ADLAR)); a6: ac e7 ldi r26, 0x7C ; 124 a8: b0 e0 ldi r27, 0x00 ; 0 aa: 8c 91 ld r24, X ac: 8f 7d andi r24, 0xDF ; 223 ae: 8c 93 st X, r24 // enable the ADC, enable interrupts ADCSRA |= _BV(ADEN) | _BV(ADIE); b0: 80 81 ld r24, Z b2: 88 68 ori r24, 0x88 ; 136 b4: 80 83 st Z, r24 b6: 08 95 ret 000000b8 : } void adc_channel(uint8_t channel, uint8_t vref) { b8: 28 2f mov r18, r24 // can we set channel? if (channel < ADC_CHAN_INVALID) { ba: 80 31 cpi r24, 0x10 ; 16 bc: 88 f4 brcc .+34 ; 0xe0 // set MUX[3:0] to the specified channel ADMUX = (ADMUX & 0xf0) | (channel & 0x0f); be: 90 91 7c 00 lds r25, 0x007C ; 0x80007c <__EEPROM_REGION_LENGTH__+0x7f007c> c2: 90 7f andi r25, 0xF0 ; 240 c4: 98 2b or r25, r24 c6: 90 93 7c 00 sts 0x007C, r25 ; 0x80007c <__EEPROM_REGION_LENGTH__+0x7f007c> // also, if this is an actual pin, disable digital input on this pin DIDR0 = (channel < 8) ? _BV(channel) : 0; ca: 88 30 cpi r24, 0x08 ; 8 cc: 30 f4 brcc .+12 ; 0xda ce: 81 e0 ldi r24, 0x01 ; 1 d0: 01 c0 rjmp .+2 ; 0xd4 d2: 88 0f add r24, r24 d4: 2a 95 dec r18 d6: ea f7 brpl .-6 ; 0xd2 d8: 01 c0 rjmp .+2 ; 0xdc da: 80 e0 ldi r24, 0x00 ; 0 dc: 80 93 7e 00 sts 0x007E, r24 ; 0x80007e <__EEPROM_REGION_LENGTH__+0x7f007e> } // set the voltage source if (vref == ADC_REF_AVCC) { e0: 61 30 cpi r22, 0x01 ; 1 e2: 21 f4 brne .+8 ; 0xec ADMUX |= (_BV(REFS0)); e4: 80 91 7c 00 lds r24, 0x007C ; 0x80007c <__EEPROM_REGION_LENGTH__+0x7f007c> e8: 80 64 ori r24, 0x40 ; 64 ea: 05 c0 rjmp .+10 ; 0xf6 } else if (vref == ADC_REF_BANDGAP) { ec: 62 30 cpi r22, 0x02 ; 2 ee: 29 f4 brne .+10 ; 0xfa ADMUX &= ~(_BV(REFS0)); f0: 80 91 7c 00 lds r24, 0x007C ; 0x80007c <__EEPROM_REGION_LENGTH__+0x7f007c> f4: 8f 7b andi r24, 0xBF ; 191 f6: 80 93 7c 00 sts 0x007C, r24 ; 0x80007c <__EEPROM_REGION_LENGTH__+0x7f007c> fa: 08 95 ret 000000fc : } uint8_t adc_start(uint8_t reread, uint8_t enable_averaging) { // is a conversion already running? if (ADCSRA & _BV(ADSC)) { fc: 90 91 7a 00 lds r25, 0x007A ; 0x80007a <__EEPROM_REGION_LENGTH__+0x7f007a> 100: 29 2f mov r18, r25 102: 20 74 andi r18, 0x40 ; 64 104: 96 fd sbrc r25, 6 106: 15 c0 rjmp .+42 ; 0x132 return 1; } // set up amount of times to re-read, and mark the amount of values to average adc_reread = reread; 108: 80 93 0c 01 sts 0x010C, r24 ; 0x80010c adc_averages = enable_averaging ? reread : 0; 10c: 66 23 and r22, r22 10e: 11 f0 breq .+4 ; 0x114 110: 98 2f mov r25, r24 112: 01 c0 rjmp .+2 ; 0x116 114: 90 e0 ldi r25, 0x00 ; 0 116: 90 93 04 01 sts 0x0104, r25 ; 0x800104 <__data_end> // start conversion adc_busy = 0x80 | (ADMUX & 0x0f); 11a: 90 91 7c 00 lds r25, 0x007C ; 0x80007c <__EEPROM_REGION_LENGTH__+0x7f007c> 11e: 9f 70 andi r25, 0x0F ; 15 120: 90 68 ori r25, 0x80 ; 128 122: 90 93 1f 01 sts 0x011F, r25 ; 0x80011f ADCSRA |= _BV(ADSC); 126: 90 91 7a 00 lds r25, 0x007A ; 0x80007a <__EEPROM_REGION_LENGTH__+0x7f007a> 12a: 90 64 ori r25, 0x40 ; 64 12c: 90 93 7a 00 sts 0x007A, r25 ; 0x80007a <__EEPROM_REGION_LENGTH__+0x7f007a> return 0; 130: 01 c0 rjmp .+2 ; 0x134 uint8_t adc_start(uint8_t reread, uint8_t enable_averaging) { // is a conversion already running? if (ADCSRA & _BV(ADSC)) { return 1; 132: 21 e0 ldi r18, 0x01 ; 1 // start conversion adc_busy = 0x80 | (ADMUX & 0x0f); ADCSRA |= _BV(ADSC); return 0; } 134: 82 2f mov r24, r18 136: 08 95 ret 00000138 <__vector_16>: /* ISR */ ISR(ADC_vect) { 138: 1f 92 push r1 13a: 0f 92 push r0 13c: 0f b6 in r0, 0x3f ; 63 13e: 0f 92 push r0 140: 11 24 eor r1, r1 142: 2f 93 push r18 144: 4f 93 push r20 146: 5f 93 push r21 148: 8f 93 push r24 14a: 9f 93 push r25 14c: af 93 push r26 14e: bf 93 push r27 150: ef 93 push r30 152: ff 93 push r31 uint8_t channel; channel = ADMUX & 0x0f; 154: e0 91 7c 00 lds r30, 0x007C ; 0x80007c <__EEPROM_REGION_LENGTH__+0x7f007c> 158: ef 70 andi r30, 0x0F ; 15 // mark our result in the average table if (adc_averages) { 15a: 20 91 04 01 lds r18, 0x0104 ; 0x800104 <__data_end> 15e: 22 23 and r18, r18 160: d1 f0 breq .+52 ; 0x196 <__vector_16+0x5e> // except for the first read if (adc_averages != adc_reread) { 162: 80 91 0c 01 lds r24, 0x010C ; 0x80010c 166: 28 17 cp r18, r24 168: b1 f0 breq .+44 ; 0x196 <__vector_16+0x5e> // 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) { 16a: e9 30 cpi r30, 0x09 ; 9 16c: a0 f4 brcc .+40 ; 0x196 <__vector_16+0x5e> adc_result[channel] = (adc_result[channel] + ADC) >> 1; 16e: ae 2f mov r26, r30 170: b0 e0 ldi r27, 0x00 ; 0 172: aa 0f add r26, r26 174: bb 1f adc r27, r27 176: a3 5f subi r26, 0xF3 ; 243 178: be 4f sbci r27, 0xFE ; 254 17a: 4d 91 ld r20, X+ 17c: 5c 91 ld r21, X 17e: 11 97 sbiw r26, 0x01 ; 1 180: 80 91 78 00 lds r24, 0x0078 ; 0x800078 <__EEPROM_REGION_LENGTH__+0x7f0078> 184: 90 91 79 00 lds r25, 0x0079 ; 0x800079 <__EEPROM_REGION_LENGTH__+0x7f0079> 188: 84 0f add r24, r20 18a: 95 1f adc r25, r21 18c: 96 95 lsr r25 18e: 87 95 ror r24 190: 11 96 adiw r26, 0x01 ; 1 192: 9c 93 st X, r25 194: 8e 93 st -X, r24 } } } if (adc_reread) { 196: 80 91 0c 01 lds r24, 0x010C ; 0x80010c 19a: 88 23 and r24, r24 19c: 59 f0 breq .+22 ; 0x1b4 <__vector_16+0x7c> adc_reread--; 19e: 80 91 0c 01 lds r24, 0x010C ; 0x80010c 1a2: 81 50 subi r24, 0x01 ; 1 1a4: 80 93 0c 01 sts 0x010C, r24 ; 0x80010c // start another conversion ADCSRA |= _BV(ADSC); 1a8: 80 91 7a 00 lds r24, 0x007A ; 0x80007a <__EEPROM_REGION_LENGTH__+0x7f007a> 1ac: 80 64 ori r24, 0x40 ; 64 1ae: 80 93 7a 00 sts 0x007A, r24 ; 0x80007a <__EEPROM_REGION_LENGTH__+0x7f007a> 1b2: 11 c0 rjmp .+34 ; 0x1d6 <__vector_16+0x9e> } else { // determine if we need to update feedback if (!adc_averages && channel <= ADC_MAX_FEEDBACK) { 1b4: 21 11 cpse r18, r1 1b6: 0d c0 rjmp .+26 ; 0x1d2 <__vector_16+0x9a> 1b8: e9 30 cpi r30, 0x09 ; 9 1ba: 58 f4 brcc .+22 ; 0x1d2 <__vector_16+0x9a> // not averaging, so just store last result adc_result[channel] = ADC; 1bc: f0 e0 ldi r31, 0x00 ; 0 1be: 80 91 78 00 lds r24, 0x0078 ; 0x800078 <__EEPROM_REGION_LENGTH__+0x7f0078> 1c2: 90 91 79 00 lds r25, 0x0079 ; 0x800079 <__EEPROM_REGION_LENGTH__+0x7f0079> 1c6: ee 0f add r30, r30 1c8: ff 1f adc r31, r31 1ca: e3 5f subi r30, 0xF3 ; 243 1cc: fe 4f sbci r31, 0xFE ; 254 1ce: 91 83 std Z+1, r25 ; 0x01 1d0: 80 83 st Z, r24 } adc_busy = 0; 1d2: 10 92 1f 01 sts 0x011F, r1 ; 0x80011f } 1d6: ff 91 pop r31 1d8: ef 91 pop r30 1da: bf 91 pop r27 1dc: af 91 pop r26 1de: 9f 91 pop r25 1e0: 8f 91 pop r24 1e2: 5f 91 pop r21 1e4: 4f 91 pop r20 1e6: 2f 91 pop r18 1e8: 0f 90 pop r0 1ea: 0f be out 0x3f, r0 ; 63 1ec: 0f 90 pop r0 1ee: 1f 90 pop r1 1f0: 18 95 reti 000001f2 : { // 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; 1f2: 8a b1 in r24, 0x0a ; 10 1f4: 80 6f ori r24, 0xF0 ; 240 1f6: 8a b9 out 0x0a, r24 ; 10 DDRC |= 0x0f; 1f8: 87 b1 in r24, 0x07 ; 7 1fa: 8f 60 ori r24, 0x0F ; 15 1fc: 87 b9 out 0x07, r24 ; 7 #ifdef LED_COMMON_ANODE // com-anode: pin is high to disable PORTD |= 0xf0; 1fe: 8b b1 in r24, 0x0b ; 11 200: 80 6f ori r24, 0xF0 ; 240 202: 8b b9 out 0x0b, r24 ; 11 PORTC |= 0x0f; 204: 88 b1 in r24, 0x08 ; 8 206: 8f 60 ori r24, 0x0F ; 15 208: 88 b9 out 0x08, r24 ; 8 20a: 08 95 ret 0000020c : } // 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() { 20c: cf 93 push r28 20e: df 93 push r29 // 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; 210: 8b b1 in r24, 0x0b ; 11 212: 80 6f ori r24, 0xF0 ; 240 214: 8b b9 out 0x0b, r24 ; 11 PORTC |= 0x0f; 216: 88 b1 in r24, 0x08 ; 8 218: 8f 60 ori r24, 0x0F ; 15 21a: 88 b9 out 0x08, r24 ; 8 PORTD &= 0x0f; PORTC &= 0xf0; #endif // set pwm OCx registers to max timer1_set_oca(TIMER1_COMPARE); 21c: c8 e8 ldi r28, 0x88 ; 136 21e: d0 e0 ldi r29, 0x00 ; 0 220: 8e ef ldi r24, 0xFE ; 254 222: 88 83 st Y, r24 timer1_set_ocb(TIMER1_COMPARE); 224: aa e8 ldi r26, 0x8A ; 138 226: b0 e0 ldi r27, 0x00 ; 0 228: 8c 93 st X, r24 DDRB |= (_BV(DDB2) | _BV(DDB1)); } inline void timer1_set(uint16_t set) { TCNT1 = set; 22a: 8a ef ldi r24, 0xFA ; 250 22c: 90 e0 ldi r25, 0x00 ; 0 22e: 90 93 85 00 sts 0x0085, r25 ; 0x800085 <__EEPROM_REGION_LENGTH__+0x7f0085> 232: 80 93 84 00 sts 0x0084, r24 ; 0x800084 <__EEPROM_REGION_LENGTH__+0x7f0084> // 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)); 236: 3b b1 in r19, 0x0b ; 11 238: 24 e0 ldi r18, 0x04 ; 4 23a: 2d 0d add r18, r13 23c: 81 e0 ldi r24, 0x01 ; 1 23e: 90 e0 ldi r25, 0x00 ; 0 240: ac 01 movw r20, r24 242: 01 c0 rjmp .+2 ; 0x246 244: 44 0f add r20, r20 246: 2a 95 dec r18 248: ea f7 brpl .-6 ; 0x244 24a: 24 2f mov r18, r20 24c: 20 95 com r18 24e: 23 23 and r18, r19 250: 2b b9 out 0x0b, r18 ; 11 PORTC &= ~(_BV(rgbled_idx)); 252: 28 b1 in r18, 0x08 ; 8 254: 0d 2c mov r0, r13 256: 01 c0 rjmp .+2 ; 0x25a 258: 88 0f add r24, r24 25a: 0a 94 dec r0 25c: ea f7 brpl .-6 ; 0x258 25e: 80 95 com r24 260: 82 23 and r24, r18 262: 88 b9 out 0x08, r24 ; 8 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]); 264: ed 2d mov r30, r13 266: f0 e0 ldi r31, 0x00 ; 0 268: eb 5d subi r30, 0xDB ; 219 26a: fe 4f sbci r31, 0xFE ; 254 26c: 8b ef ldi r24, 0xFB ; 251 26e: 90 81 ld r25, Z 270: 28 2f mov r18, r24 272: 29 1b sub r18, r25 274: 28 83 st Y, r18 timer1_set_ocb(rgbled_pwm_rt[rgbled_idx]); 276: ed 2d mov r30, r13 278: f0 e0 ldi r31, 0x00 ; 0 27a: ef 5d subi r30, 0xDF ; 223 27c: fe 4f sbci r31, 0xFE ; 254 27e: 90 81 ld r25, Z 280: 89 1b sub r24, r25 282: 8c 93 st X, r24 } 284: df 91 pop r29 286: cf 91 pop r28 288: 08 95 ret 0000028a : // 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; 28a: 9b b1 in r25, 0x0b ; 11 28c: 90 6f ori r25, 0xF0 ; 240 28e: 9b b9 out 0x0b, r25 ; 11 // 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)); 290: e0 e8 ldi r30, 0x80 ; 128 292: f0 e0 ldi r31, 0x00 ; 0 294: 90 81 ld r25, Z 296: 9f 70 andi r25, 0x0F ; 15 298: 90 83 st Z, r25 // ground the LED DDRC &= 0xf0; // set all LEDs cathode as inputs 29a: 97 b1 in r25, 0x07 ; 7 29c: 90 7f andi r25, 0xF0 ; 240 29e: 97 b9 out 0x07, r25 ; 7 MCUCR |= (_BV(PUD)); // globally disable pullups 2a0: 95 b7 in r25, 0x35 ; 53 2a2: 90 61 ori r25, 0x10 ; 16 2a4: 95 bf out 0x35, r25 ; 53 DDRC |= (_BV(led)); // set our LED as an output 2a6: 47 b1 in r20, 0x07 ; 7 2a8: 21 e0 ldi r18, 0x01 ; 1 2aa: 30 e0 ldi r19, 0x00 ; 0 2ac: b9 01 movw r22, r18 2ae: 02 c0 rjmp .+4 ; 0x2b4 2b0: 66 0f add r22, r22 2b2: 77 1f adc r23, r23 2b4: 8a 95 dec r24 2b6: e2 f7 brpl .-8 ; 0x2b0 2b8: cb 01 movw r24, r22 2ba: 46 2b or r20, r22 2bc: 47 b9 out 0x07, r20 ; 7 PORTC = (PORTC & 0xf0); // set all LEDs cathode low 2be: 98 b1 in r25, 0x08 ; 8 2c0: 90 7f andi r25, 0xF0 ; 240 2c2: 98 b9 out 0x08, r25 ; 8 PORTB |= (_BV(PORTB2)); // set anode high 2c4: 2a 9a sbi 0x05, 2 ; 5 // reverse LED bias PORTC |= (_BV(led)); // set cathode high 2c6: 98 b1 in r25, 0x08 ; 8 2c8: 98 2b or r25, r24 2ca: 98 b9 out 0x08, r25 ; 8 PORTB &= ~(_BV(PORTB2)); // set anode low 2cc: 2a 98 cbi 0x05, 2 ; 5 #else //round up by default __ticks_dc = (uint32_t)(ceil(fabs(__tmp))); #endif __builtin_avr_delay_cycles(__ticks_dc); 2ce: 78 e0 ldi r23, 0x08 ; 8 2d0: 7a 95 dec r23 2d2: f1 f7 brne .-4 ; 0x2d0 _delay_us(3); // allow it to charge fully // set LED as input DDRC &= ~(_BV(led)); // set led cathode as input 2d4: 97 b1 in r25, 0x07 ; 7 2d6: 80 95 com r24 2d8: 98 23 and r25, r24 2da: 97 b9 out 0x07, r25 ; 7 PORTC &= ~(_BV(led)); // set led cathode pullup off 2dc: 98 b1 in r25, 0x08 ; 8 2de: 89 23 and r24, r25 2e0: 88 b9 out 0x08, r24 ; 8 MCUCR &= ~(_BV(PUD)); // re-enable global pullups 2e2: 85 b7 in r24, 0x35 ; 53 2e4: 8f 7e andi r24, 0xEF ; 239 2e6: 85 bf out 0x35, r24 ; 53 2e8: 08 95 ret 000002ea : } // 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) { 2ea: 84 30 cpi r24, 0x04 ; 4 2ec: 38 f4 brcc .+14 ; 0x2fc if (sensitivity) { 2ee: 66 23 and r22, r22 2f0: 29 f0 breq .+10 ; 0x2fc rgbled_sensitivity[ledidx] = sensitivity; 2f2: e8 2f mov r30, r24 2f4: f0 e0 ldi r31, 0x00 ; 0 2f6: e0 50 subi r30, 0x00 ; 0 2f8: ff 4f sbci r31, 0xFF ; 255 2fa: 60 83 st Z, r22 2fc: 08 95 ret 000002fe : } } void rgbled_sensor_read_idx(uint8_t ledidx) { rgbled_read_sel = ledidx & 0x03; 2fe: 83 70 andi r24, 0x03 ; 3 300: 80 93 05 01 sts 0x0105, r24 ; 0x800105 304: 08 95 ret 00000306 : void rgbled_sensor_read() { uint8_t sens; sens = rgbled_sensitivity[rgbled_read_sel]; 306: 80 91 05 01 lds r24, 0x0105 ; 0x800105 30a: e8 2f mov r30, r24 30c: f0 e0 ldi r31, 0x00 ; 0 30e: e0 50 subi r30, 0x00 ; 0 310: ff 4f sbci r31, 0xFF ; 255 312: 90 81 ld r25, Z if (!sens) sens = 1; 314: 91 11 cpse r25, r1 316: 01 c0 rjmp .+2 ; 0x31a 318: 91 e0 ldi r25, 0x01 ; 1 if (adc_read_step == 0) { 31a: 2e 2d mov r18, r14 31c: e1 10 cpse r14, r1 31e: 03 c0 rjmp .+6 ; 0x326 // adc_init(); // clear ADC bias by reading ground adc_channel(ADC_CHAN_GND, ADC_REF_AVCC); 320: 61 e0 ldi r22, 0x01 ; 1 322: 8f e0 ldi r24, 0x0F ; 15 324: 12 c0 rjmp .+36 ; 0x34a } else if (adc_read_step == 1) { 326: 21 30 cpi r18, 0x01 ; 1 328: 19 f4 brne .+6 ; 0x330 adc_start(0, 0); 32a: 60 e0 ldi r22, 0x00 ; 0 32c: 80 e0 ldi r24, 0x00 ; 0 32e: 18 c0 rjmp .+48 ; 0x360 } else if (adc_read_step == 2) { 330: 22 30 cpi r18, 0x02 ; 2 332: 61 f4 brne .+24 ; 0x34c // if the ADC is done, charge up LED for reading if (adc_busy) { 334: 90 91 1f 01 lds r25, 0x011F ; 0x80011f 338: 99 23 and r25, r25 33a: 19 f0 breq .+6 ; 0x342 adc_read_step--; 33c: ee 24 eor r14, r14 33e: e3 94 inc r14 340: 08 95 ret } else { rgbled_sensor_init(rgbled_read_sel); 342: a3 df rcall .-186 ; 0x28a adc_channel(rgbled_read_sel, ADC_REF_NO_SET); 344: 6f ef ldi r22, 0xFF ; 255 346: 80 91 05 01 lds r24, 0x0105 ; 0x800105 34a: b6 ce rjmp .-660 ; 0xb8 } } else if (adc_read_step == (2 + sens)) { 34c: 4e 2d mov r20, r14 34e: 50 e0 ldi r21, 0x00 ; 0 350: 89 2f mov r24, r25 352: 90 e0 ldi r25, 0x00 ; 0 354: 02 96 adiw r24, 0x02 ; 2 356: 48 17 cp r20, r24 358: 59 07 cpc r21, r25 35a: 19 f4 brne .+6 ; 0x362 // if vref has changed, it should be stable by now; start reading LED value adc_start(3, 1); 35c: 61 e0 ldi r22, 0x01 ; 1 35e: 83 e0 ldi r24, 0x03 ; 3 360: cd ce rjmp .-614 ; 0xfc } else if (adc_read_step > (2 + sens)) { 362: 84 17 cp r24, r20 364: 95 07 cpc r25, r21 366: 94 f4 brge .+36 ; 0x38c adc_read_step--; 368: 21 50 subi r18, 0x01 ; 1 36a: e2 2e mov r14, r18 if (!adc_busy) { 36c: 80 91 1f 01 lds r24, 0x011F ; 0x80011f 370: 81 11 cpse r24, r1 372: 0c c0 rjmp .+24 ; 0x38c // we are done! :) finish up... adc_channel(ADC_CHAN_GND, ADC_REF_NO_SET); // change ADC to not look at a real pin 374: 6f ef ldi r22, 0xFF ; 255 376: 8f e0 ldi r24, 0x0F ; 15 378: 9f de rcall .-706 ; 0xb8 rgbled_io_init(); // set LED pins up again 37a: 3b df rcall .-394 ; 0x1f2 } inline void timer1_pwm_reinit() { // enable pwm output on OCx pins TCCR1A = (_BV(COM1A1)) | (_BV(COM1B1)) | (_BV(WGM11) | ~(_BV(WGM10))); 37c: 8e ef ldi r24, 0xFE ; 254 37e: 80 93 80 00 sts 0x0080, r24 ; 0x800080 <__EEPROM_REGION_LENGTH__+0x7f0080> // set OC pins as outputs DDRB |= (_BV(DDB2) | _BV(DDB1)); 382: 84 b1 in r24, 0x04 ; 4 384: 86 60 ori r24, 0x06 ; 6 386: 84 b9 out 0x04, r24 ; 4 timer1_pwm_reinit(); // and set up PWM again adc_read_mode = 0; // clear ADC read mode 388: 10 92 20 01 sts 0x0120, r1 ; 0x800120 38c: 08 95 ret 0000038e : return 0; } static uint8_t pegleg_cmd() { switch (comm_cmd) { 38e: 8f 2d mov r24, r15 390: 4f 2d mov r20, r15 392: 50 e0 ldi r21, 0x00 ; 0 394: 4a 31 cpi r20, 0x1A ; 26 396: 51 05 cpc r21, r1 398: 08 f0 brcs .+2 ; 0x39c 39a: 75 c0 rjmp .+234 ; 0x486 <__LOCK_REGION_LENGTH__+0x86> 39c: fa 01 movw r30, r20 39e: ec 5e subi r30, 0xEC ; 236 3a0: ff 4f sbci r31, 0xFF ; 255 3a2: 09 94 ijmp // no command: we just ACK this as we shouldn't ever get here case MODE_NONE: { comm_cmd = 0; 3a4: f1 2c mov r15, r1 comm_timeout = 0; 3a6: 10 92 2a 01 sts 0x012A, r1 ; 0x80012a break; 3aa: 08 95 ret } // standard commands case MODE_EXT_CMD: { // used for more commands if (comm_data_idx >= 1) { 3ac: 80 91 33 01 lds r24, 0x0133 ; 0x800133 3b0: 88 23 and r24, r24 3b2: 09 f4 brne .+2 ; 0x3b6 3b4: 6c c0 rjmp .+216 ; 0x48e <__LOCK_REGION_LENGTH__+0x8e> comm_cmd = comm_data[1]; 3b6: f0 90 30 01 lds r15, 0x0130 ; 0x800130 // 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; 3ba: 83 e0 ldi r24, 0x03 ; 3 3bc: 80 93 33 01 sts 0x0133, r24 ; 0x800133 3c0: 50 c0 rjmp .+160 ; 0x462 <__LOCK_REGION_LENGTH__+0x62> } break; } case MODE_LED_SET_LEVEL: { // sets PWM rate for the 8 PWM LEDs if (comm_data[0] < 4) { 3c2: e0 91 2f 01 lds r30, 0x012F ; 0x80012f 3c6: e4 30 cpi r30, 0x04 ; 4 3c8: 20 f4 brcc .+8 ; 0x3d2 rgbled_pwm_lf[comm_data[0]] = comm_data[1]; 3ca: f0 e0 ldi r31, 0x00 ; 0 3cc: eb 5d subi r30, 0xDB ; 219 3ce: fe 4f sbci r31, 0xFE ; 254 3d0: 06 c0 rjmp .+12 ; 0x3de } else if (comm_data[0] < 8) { 3d2: e8 30 cpi r30, 0x08 ; 8 3d4: 08 f0 brcs .+2 ; 0x3d8 3d6: 44 c0 rjmp .+136 ; 0x460 <__LOCK_REGION_LENGTH__+0x60> rgbled_pwm_rt[comm_data[0] - 4] = comm_data[1]; 3d8: f0 e0 ldi r31, 0x00 ; 0 3da: e3 5e subi r30, 0xE3 ; 227 3dc: fe 4f sbci r31, 0xFE ; 254 3de: 80 91 30 01 lds r24, 0x0130 ; 0x800130 3e2: 80 83 st Z, r24 3e4: 3d c0 rjmp .+122 ; 0x460 <__LOCK_REGION_LENGTH__+0x60> } 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) { 3e6: 80 91 33 01 lds r24, 0x0133 ; 0x800133 3ea: 88 23 and r24, r24 3ec: 09 f4 brne .+2 ; 0x3f0 3ee: 4f c0 rjmp .+158 ; 0x48e <__LOCK_REGION_LENGTH__+0x8e> // update the offset if (adc_result[ADC_CHAN_TEMP]) { 3f0: 80 91 1d 01 lds r24, 0x011D ; 0x80011d 3f4: 90 91 1e 01 lds r25, 0x011E ; 0x80011e 3f8: 89 2b or r24, r25 3fa: 09 f4 brne .+2 ; 0x3fe 3fc: 44 c0 rjmp .+136 ; 0x486 <__LOCK_REGION_LENGTH__+0x86> temp_offset = adc_result[ADC_CHAN_TEMP] - (int8_t)comm_data[1]; 3fe: 60 91 1d 01 lds r22, 0x011D ; 0x80011d 402: 70 91 1e 01 lds r23, 0x011E ; 0x80011e 406: 80 91 30 01 lds r24, 0x0130 ; 0x800130 40a: 68 1b sub r22, r24 40c: 71 09 sbc r23, r1 40e: 87 fd sbrc r24, 7 410: 73 95 inc r23 412: 70 93 07 01 sts 0x0107, r23 ; 0x800107 416: 60 93 06 01 sts 0x0106, r22 ; 0x800106 // write it to eeprom eeprom_write_word((uint16_t *)EEPROM_ADDR_TEMPCAL, temp_offset); 41a: 8e e3 ldi r24, 0x3E ; 62 41c: 90 e0 ldi r25, 0x00 ; 0 41e: 24 d2 rcall .+1096 ; 0x868 420: 1f c0 rjmp .+62 ; 0x460 <__LOCK_REGION_LENGTH__+0x60> } case MODE_EEPROM_READ: { // our data packet is already set; ready for read. // but if the host keeps writing... if (comm_data_idx > 1) { 422: 80 91 33 01 lds r24, 0x0133 ; 0x800133 426: 82 30 cpi r24, 0x02 ; 2 428: d8 f4 brcc .+54 ; 0x460 <__LOCK_REGION_LENGTH__+0x60> 42a: 1d c0 rjmp .+58 ; 0x466 <__LOCK_REGION_LENGTH__+0x66> } // immediate commands case MODE_TEMPSENSOR_READ: { // attempt another read if (!adc_read_mode) { 42c: 80 91 20 01 lds r24, 0x0120 ; 0x800120 430: 81 11 cpse r24, r1 432: 17 c0 rjmp .+46 ; 0x462 <__LOCK_REGION_LENGTH__+0x62> adc_read_mode = 0; 434: 10 92 20 01 sts 0x0120, r1 ; 0x800120 adc_read_step = 0; 438: e1 2c mov r14, r1 adc_read_mode = ADC_MODE_TEMPSENSOR; 43a: 88 e0 ldi r24, 0x08 ; 8 43c: 80 93 20 01 sts 0x0120, r24 ; 0x800120 440: 10 c0 rjmp .+32 ; 0x462 <__LOCK_REGION_LENGTH__+0x62> // 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) { 442: 80 91 20 01 lds r24, 0x0120 ; 0x800120 446: 81 11 cpse r24, r1 448: 0c c0 rjmp .+24 ; 0x462 <__LOCK_REGION_LENGTH__+0x62> // set the led and step to first step adc_read_mode = 0; 44a: 10 92 20 01 sts 0x0120, r1 ; 0x800120 adc_read_step = 0; 44e: e1 2c mov r14, r1 rgbled_sensor_read_idx(comm_data[0]); 450: 80 91 2f 01 lds r24, 0x012F ; 0x80012f 454: 54 df rcall .-344 ; 0x2fe adc_read_mode = ADC_MODE_LIGHTSENSOR; 456: 81 e0 ldi r24, 0x01 ; 1 458: f1 cf rjmp .-30 ; 0x43c <__LOCK_REGION_LENGTH__+0x3c> 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; 45a: 84 e0 ldi r24, 0x04 ; 4 45c: 80 93 09 01 sts 0x0109, r24 ; 0x800109 // 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; 460: f1 2c mov r15, r1 comm_timeout = 0; 462: 10 92 2a 01 sts 0x012A, r1 ; 0x80012a comm_timeout = 0; return 1; } } return 0; 466: 80 e0 ldi r24, 0x00 ; 0 case MODE_AUX_PIN_GET: { // TODO: implement when response sending is ...implemented comm_cmd = 0; comm_timeout = 0; break; 468: 08 95 ret } case MODE_LIGHTSENSOR_SENS: { // 0x10 0x19 if (comm_data_idx >= 1) { 46a: 80 91 33 01 lds r24, 0x0133 ; 0x800133 46e: 88 23 and r24, r24 470: 71 f0 breq .+28 ; 0x48e <__LOCK_REGION_LENGTH__+0x8e> if ((comm_data[0] <= 0x03) && (comm_data[1])) { 472: 80 91 2f 01 lds r24, 0x012F ; 0x80012f 476: 84 30 cpi r24, 0x04 ; 4 478: 98 f7 brcc .-26 ; 0x460 <__LOCK_REGION_LENGTH__+0x60> 47a: 60 91 30 01 lds r22, 0x0130 ; 0x800130 47e: 66 23 and r22, r22 480: 79 f3 breq .-34 ; 0x460 <__LOCK_REGION_LENGTH__+0x60> rgbled_sensor_sensitivity(comm_data[0], comm_data[1]); 482: 33 df rcall .-410 ; 0x2ea 484: ed cf rjmp .-38 ; 0x460 <__LOCK_REGION_LENGTH__+0x60> } // invalid commands default: { // send NAK comm_cmd = 0; 486: f1 2c mov r15, r1 comm_timeout = 0; 488: 10 92 2a 01 sts 0x012A, r1 ; 0x80012a return 1; 48c: 81 e0 ldi r24, 0x01 ; 1 } } return 0; } 48e: 08 95 ret 00000490 : /* sending */ static uint8_t i2c_slave_tx(uint8_t byte, uint8_t is_last_byte) { // load data TWDR = byte; 490: 80 93 bb 00 sts 0x00BB, r24 ; 0x8000bb <__EEPROM_REGION_LENGTH__+0x7f00bb> // start sending TWCR |= _BV(TWINT); 494: ec eb ldi r30, 0xBC ; 188 496: f0 e0 ldi r31, 0x00 ; 0 498: 80 81 ld r24, Z 49a: 80 68 ori r24, 0x80 ; 128 49c: 80 83 st Z, r24 if (is_last_byte) { // this is all the data we have to send; send a nack after this byte i2c_disable_slave(); 49e: 80 81 ld r24, Z 4a0: 8f 7b andi r24, 0xBF ; 191 4a2: 80 83 st Z, r24 } return 0; } 4a4: 80 e0 ldi r24, 0x00 ; 0 4a6: 08 95 ret 000004a8 : /* comms */ static inline uint8_t pegleg_data_tx() { uint8_t ret; switch (comm_cmd) { 4a8: 8f 2d mov r24, r15 4aa: 88 30 cpi r24, 0x08 ; 8 4ac: b9 f0 breq .+46 ; 0x4dc 4ae: 89 30 cpi r24, 0x09 ; 9 4b0: c1 f0 breq .+48 ; 0x4e2 4b2: 84 30 cpi r24, 0x04 ; 4 4b4: 51 f5 brne .+84 ; 0x50a case MODE_EEPROM_READ: { if (comm_data[0] < 64) { 4b6: 80 91 2f 01 lds r24, 0x012F ; 0x80012f 4ba: 80 34 cpi r24, 0x40 ; 64 4bc: 28 f4 brcc .+10 ; 0x4c8 i2c_slave_tx(eeprom_read_byte((uint8_t *)(uint16_t)comm_data[0]), 1); 4be: 90 e0 ldi r25, 0x00 ; 0 4c0: c8 d1 rcall .+912 ; 0x852 4c2: e6 df rcall .-52 ; 0x490 ret = 1; 4c4: 81 e0 ldi r24, 0x01 ; 1 4c6: 06 c0 rjmp .+12 ; 0x4d4 } else { // invalid address... i2c_disable_slave(); 4c8: 80 91 bc 00 lds r24, 0x00BC ; 0x8000bc <__EEPROM_REGION_LENGTH__+0x7f00bc> 4cc: 8f 7b andi r24, 0xBF ; 191 4ce: 80 93 bc 00 sts 0x00BC, r24 ; 0x8000bc <__EEPROM_REGION_LENGTH__+0x7f00bc> ret = 255; 4d2: 8f ef ldi r24, 0xFF ; 255 } comm_cmd = 0; 4d4: f1 2c mov r15, r1 comm_timeout = 0; 4d6: 10 92 2a 01 sts 0x012A, r1 ; 0x80012a 4da: 08 95 ret return ret; } case MODE_TEMPSENSOR_READ: { i2c_slave_tx(temperature, 1); 4dc: 80 91 08 01 lds r24, 0x0108 ; 0x800108 4e0: 0e c0 rjmp .+28 ; 0x4fe comm_cmd = 0; comm_timeout = 0; return 1; } case MODE_LIGHTSENSOR_READ: { i2c_slave_tx(adc_result[comm_data[0] & 0x03] >> 2, 1); 4e2: e0 91 2f 01 lds r30, 0x012F ; 0x80012f 4e6: e3 70 andi r30, 0x03 ; 3 4e8: f0 e0 ldi r31, 0x00 ; 0 4ea: ee 0f add r30, r30 4ec: ff 1f adc r31, r31 4ee: e3 5f subi r30, 0xF3 ; 243 4f0: fe 4f sbci r31, 0xFE ; 254 4f2: 80 81 ld r24, Z 4f4: 91 81 ldd r25, Z+1 ; 0x01 4f6: 96 95 lsr r25 4f8: 87 95 ror r24 4fa: 96 95 lsr r25 4fc: 87 95 ror r24 4fe: c8 df rcall .-112 ; 0x490 comm_cmd = 0; 500: f1 2c mov r15, r1 comm_timeout = 0; 502: 10 92 2a 01 sts 0x012A, r1 ; 0x80012a return 1; 506: 81 e0 ldi r24, 0x01 ; 1 508: 08 95 ret } default: { // nothing active; invalid :( i2c_disable_slave(); 50a: 80 91 bc 00 lds r24, 0x00BC ; 0x8000bc <__EEPROM_REGION_LENGTH__+0x7f00bc> 50e: 8f 7b andi r24, 0xBF ; 191 510: 80 93 bc 00 sts 0x00BC, r24 ; 0x8000bc <__EEPROM_REGION_LENGTH__+0x7f00bc> return 255; 514: 8f ef ldi r24, 0xFF ; 255 } } return 0; } 516: 08 95 ret 00000518 : 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 518: 80 91 1d 01 lds r24, 0x011D ; 0x80011d 51c: 90 91 1e 01 lds r25, 0x011E ; 0x80011e 520: 90 91 06 01 lds r25, 0x0106 ; 0x800106 524: 89 1b sub r24, r25 temp_gain = temp_adj >> 3; // our gain adjust amount 526: 98 2f mov r25, r24 528: 95 95 asr r25 52a: 95 95 asr r25 52c: 95 95 asr r25 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; } 52e: 89 1b sub r24, r25 530: 08 95 ret 00000532 : void tempsensor_read() { if (adc_read_step == 0) { 532: 8e 2d mov r24, r14 534: e1 10 cpse r14, r1 536: 03 c0 rjmp .+6 ; 0x53e // select temperature channel adc_channel(ADC_CHAN_TEMP, ADC_REF_BANDGAP); 538: 62 e0 ldi r22, 0x02 ; 2 53a: 88 e0 ldi r24, 0x08 ; 8 53c: bd cd rjmp .-1158 ; 0xb8 } else if (adc_read_step == 3) { 53e: 83 30 cpi r24, 0x03 ; 3 540: 19 f4 brne .+6 ; 0x548 // 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); 542: 61 e0 ldi r22, 0x01 ; 1 544: 84 e0 ldi r24, 0x04 ; 4 546: da cd rjmp .-1100 ; 0xfc } else if (adc_read_step > 3) { 548: 84 30 cpi r24, 0x04 ; 4 54a: 70 f0 brcs .+28 ; 0x568 adc_read_step--; 54c: 81 50 subi r24, 0x01 ; 1 54e: e8 2e mov r14, r24 if (!adc_busy) { 550: 80 91 1f 01 lds r24, 0x011F ; 0x80011f 554: 81 11 cpse r24, r1 556: 08 c0 rjmp .+16 ; 0x568 // 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); 558: 61 e0 ldi r22, 0x01 ; 1 55a: 8f e0 ldi r24, 0x0F ; 15 55c: ad dd rcall .-1190 ; 0xb8 adc_read_mode = 0; 55e: 10 92 20 01 sts 0x0120, r1 ; 0x800120 temperature = tempsensor_process(); 562: da df rcall .-76 ; 0x518 564: 80 93 08 01 sts 0x0108, r24 ; 0x800108 568: 08 95 ret 0000056a
: /* func */ static void system_init() { // make SURE we are running at 8MHz // do this by first enabling clock divider setup mode, CLKPR = _BV(CLKPCE); 56a: 80 e8 ldi r24, 0x80 ; 128 56c: 80 93 61 00 sts 0x0061, r24 ; 0x800061 <__EEPROM_REGION_LENGTH__+0x7f0061> // and disabling any divider CLKPR = 0; 570: 10 92 61 00 sts 0x0061, r1 ; 0x800061 <__EEPROM_REGION_LENGTH__+0x7f0061> } static void system_io_init() { // enable break-before-make outputs on all IO PORTCR |= (_BV(BBMA) | _BV(BBMB) | _BV(BBMC) | _BV(BBMD)); 574: 82 b3 in r24, 0x12 ; 18 576: 80 6f ori r24, 0xF0 ; 240 578: 82 bb out 0x12, r24 ; 18 // set ALL pins as inputs except PB0 DDRA = 0x00; 57a: 1d b8 out 0x0d, r1 ; 13 DDRB = 0x01; 57c: 81 e0 ldi r24, 0x01 ; 1 57e: 84 b9 out 0x04, r24 ; 4 DDRC = 0x00; 580: 17 b8 out 0x07, r1 ; 7 DDRD = 0x00; 582: 1a b8 out 0x0a, r1 ; 10 // and enable pullups (this reduces power consumption) // in the case of PB0, set it LOW PORTA = 0xff; 584: cf ef ldi r28, 0xFF ; 255 586: ce b9 out 0x0e, r28 ; 14 PORTB = 0xfe; 588: de ef ldi r29, 0xFE ; 254 58a: d5 b9 out 0x05, r29 ; 5 PORTC = 0xff; 58c: c8 b9 out 0x08, r28 ; 8 PORTD = 0xff; 58e: cb b9 out 0x0b, r28 ; 11 // configure device and IO system_init(); system_io_init(); // configure RGBLEDs rgbled_io_init(); 590: 30 de rcall .-928 ; 0x1f2 /* 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; 592: 22 e0 ldi r18, 0x02 ; 2 594: 20 93 b8 00 sts 0x00B8, r18 ; 0x8000b8 <__EEPROM_REGION_LENGTH__+0x7f00b8> TWSR = ~(_BV(TWPS0) | _BV(TWPS1)); 598: 8c ef ldi r24, 0xFC ; 252 59a: 80 93 b9 00 sts 0x00B9, r24 ; 0x8000b9 <__EEPROM_REGION_LENGTH__+0x7f00b9> // set slave address and clear address mask TWAR = ((address << 1) | (enable_general_addr & 1)); 59e: 86 ee ldi r24, 0xE6 ; 230 5a0: 80 93 ba 00 sts 0x00BA, r24 ; 0x8000ba <__EEPROM_REGION_LENGTH__+0x7f00ba> TWAMR = 0; 5a4: 10 92 bd 00 sts 0x00BD, r1 ; 0x8000bd <__EEPROM_REGION_LENGTH__+0x7f00bd> // enable auto-ack, enable TWI, and enable the TWI interrupt TWCR = _BV(TWEA) | _BV(TWEN) | _BV(TWIE); 5a8: 85 e4 ldi r24, 0x45 ; 69 5aa: 80 93 bc 00 sts 0x00BC, r24 ; 0x8000bc <__EEPROM_REGION_LENGTH__+0x7f00bc> /* implementations */ inline static void timer0_init() { // make sure timer is enabled PRR &= ~PRTIM0; 5ae: 80 91 64 00 lds r24, 0x0064 ; 0x800064 <__EEPROM_REGION_LENGTH__+0x7f0064> 5b2: 8a 7f andi r24, 0xFA ; 250 5b4: 80 93 64 00 sts 0x0064, r24 ; 0x800064 <__EEPROM_REGION_LENGTH__+0x7f0064> // enable timer with prescale divider /64, enable TOP mode TCCR0A = _BV(CTC0) | (_BV(CS00) | _BV(CS01) | ~(_BV(CS02))); 5b8: 9b ef ldi r25, 0xFB ; 251 5ba: 95 bd out 0x25, r25 ; 37 // set TOP level to be 62 to 63 counts; this will result in 2KHz cycle @8MHz OCR0A = TIMER0_COMPARE; 5bc: 8d e3 ldi r24, 0x3D ; 61 5be: 87 bd out 0x27, r24 ; 39 // clear timer TCNT0 = 0; 5c0: 16 bc out 0x26, r1 ; 38 // and enable OCA interrupt (we don't use overflow interrupt as we are in TOP mode) TIMSK0 = _BV(OCIE0A); 5c2: 20 93 6e 00 sts 0x006E, r18 ; 0x80006e <__EEPROM_REGION_LENGTH__+0x7f006e> #define timer0_set_compare(x) OCR0A = x inline static void timer1_init() { // make sure timer is enabled PRR &= ~PRTIM1; 5c6: 80 91 64 00 lds r24, 0x0064 ; 0x800064 <__EEPROM_REGION_LENGTH__+0x7f0064> 5ca: 8c 7f andi r24, 0xFC ; 252 5cc: 80 93 64 00 sts 0x0064, r24 ; 0x800064 <__EEPROM_REGION_LENGTH__+0x7f0064> // clear PWM OCx OCR1AH = 0xff; // sets temp register to 0xff 5d0: c0 93 89 00 sts 0x0089, r28 ; 0x800089 <__EEPROM_REGION_LENGTH__+0x7f0089> OCR1AL = 0xff; 5d4: c0 93 88 00 sts 0x0088, r28 ; 0x800088 <__EEPROM_REGION_LENGTH__+0x7f0088> OCR1BL = 0xff; 5d8: c0 93 8a 00 sts 0x008A, r28 ; 0x80008a <__EEPROM_REGION_LENGTH__+0x7f008a> // clear timer TCNT1H = 0; // sets temp register to 0 5dc: 10 92 85 00 sts 0x0085, r1 ; 0x800085 <__EEPROM_REGION_LENGTH__+0x7f0085> TCNT1L = 0; 5e0: 10 92 84 00 sts 0x0084, r1 ; 0x800084 <__EEPROM_REGION_LENGTH__+0x7f0084> // 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))); 5e4: d0 93 80 00 sts 0x0080, r29 ; 0x800080 <__EEPROM_REGION_LENGTH__+0x7f0080> TCCR1B = (_BV(WGM12) | _BV(WGM13)) | (_BV(CS10)); 5e8: 89 e1 ldi r24, 0x19 ; 25 5ea: 80 93 81 00 sts 0x0081, r24 ; 0x800081 <__EEPROM_REGION_LENGTH__+0x7f0081> TCCR1C = 0; 5ee: 10 92 82 00 sts 0x0082, r1 ; 0x800082 <__EEPROM_REGION_LENGTH__+0x7f0082> // store timer1 mode to allow enabling / disabling timer timer1_mode = TCCR1A; 5f2: 80 91 80 00 lds r24, 0x0080 ; 0x800080 <__EEPROM_REGION_LENGTH__+0x7f0080> 5f6: 80 93 29 01 sts 0x0129, r24 ; 0x800129 // 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; 5fa: 90 93 86 00 sts 0x0086, r25 ; 0x800086 <__EEPROM_REGION_LENGTH__+0x7f0086> // set OC pins as outputs DDRB |= (_BV(DDB2) | _BV(DDB1)); 5fe: 84 b1 in r24, 0x04 ; 4 600: 86 60 ori r24, 0x06 ; 6 602: 84 b9 out 0x04, r24 ; 4 // disable interrupts TIMSK1 = 0; 604: 10 92 6f 00 sts 0x006F, r1 ; 0x80006f <__EEPROM_REGION_LENGTH__+0x7f006f> timer0_init(); // configure led pwm timer timer1_init(); // initialize adc adc_init(); 608: 45 dd rcall .-1398 ; 0x94 // 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) { 60a: 62 99 sbic 0x0c, 2 ; 12 60c: 23 c0 rjmp .+70 ; 0x654 // turn on the ADC, wait for it to warm up adc_init(); 60e: 42 dd rcall .-1404 ; 0x94 #else //round up by default __ticks_dc = (uint32_t)(ceil(fabs(__tmp))); #endif __builtin_avr_delay_cycles(__ticks_dc); 610: 2f ef ldi r18, 0xFF ; 255 612: 80 e7 ldi r24, 0x70 ; 112 614: 92 e0 ldi r25, 0x02 ; 2 616: 21 50 subi r18, 0x01 ; 1 618: 80 40 sbci r24, 0x00 ; 0 61a: 90 40 sbci r25, 0x00 ; 0 61c: e1 f7 brne .-8 ; 0x616 61e: 00 c0 rjmp .+0 ; 0x620 620: 00 00 nop _delay_ms(100); // todo: is this right? this seems slow // is the pin still low? not a glitch? if ((PINA & _BV(PINA2)) == 0) { 622: 62 99 sbic 0x0c, 2 ; 12 624: 17 c0 rjmp .+46 ; 0x654 // enable interrupts sei(); 626: 78 94 sei // start reading the temp sensor; stall until adc is done adc_read_mode = ADC_MODE_TEMPSENSOR; 628: 88 e0 ldi r24, 0x08 ; 8 62a: 80 93 20 01 sts 0x0120, r24 ; 0x800120 tempsensor_read(); 62e: 81 df rcall .-254 ; 0x532 while (adc_busy); 630: 80 91 1f 01 lds r24, 0x011F ; 0x80011f 634: 81 11 cpse r24, r1 636: fc cf rjmp .-8 ; 0x630 // here's our correction factor! temp_offset = adc_result[ADC_CHAN_TEMP]; 638: 60 91 1d 01 lds r22, 0x011D ; 0x80011d 63c: 70 91 1e 01 lds r23, 0x011E ; 0x80011e 640: 70 93 07 01 sts 0x0107, r23 ; 0x800107 644: 60 93 06 01 sts 0x0106, r22 ; 0x800106 // write it to eeprom eeprom_write_word((uint16_t *)EEPROM_ADDR_TEMPCAL, temp_offset); 648: 8e e3 ldi r24, 0x3E ; 62 64a: 90 e0 ldi r25, 0x00 ; 0 64c: 0d d1 rcall .+538 ; 0x868 // and that's it - we're done. adc_read_mode = 0; 64e: 10 92 20 01 sts 0x0120, r1 ; 0x800120 652: 0d c0 rjmp .+26 ; 0x66e return; } } // not saving a value - read the value from eeprom temp_offset = eeprom_read_word((uint16_t *)EEPROM_ADDR_TEMPCAL); 654: 8e e3 ldi r24, 0x3E ; 62 656: 90 e0 ldi r25, 0x00 ; 0 658: 03 d1 rcall .+518 ; 0x860 // does it seem invalid? if (temp_offset > 560) { 65a: 81 33 cpi r24, 0x31 ; 49 65c: 22 e0 ldi r18, 0x02 ; 2 65e: 92 07 cpc r25, r18 660: 14 f0 brlt .+4 ; 0x666 // 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; 662: 81 e1 ldi r24, 0x11 ; 17 664: 91 e0 ldi r25, 0x01 ; 1 666: 90 93 07 01 sts 0x0107, r25 ; 0x800107 66a: 80 93 06 01 sts 0x0106, r24 ; 0x800106 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); 66e: 83 b7 in r24, 0x33 ; 51 670: 89 7f andi r24, 0xF9 ; 249 672: 90 91 09 01 lds r25, 0x0109 ; 0x800109 676: 89 2b or r24, r25 678: 83 bf out 0x33, r24 ; 51 pirate_sleep_mode = SLEEP_MODE_IDLE; 67a: 10 92 09 01 sts 0x0109, r1 ; 0x800109 // re-enable interrupts and nap. sei(); 67e: 78 94 sei sleep_mode(); 680: 83 b7 in r24, 0x33 ; 51 682: 81 60 ori r24, 0x01 ; 1 684: 83 bf out 0x33, r24 ; 51 686: 88 95 sleep 688: 83 b7 in r24, 0x33 ; 51 68a: 8e 7f andi r24, 0xFE ; 254 68c: 83 bf out 0x33, r24 ; 51 68e: ef cf rjmp .-34 ; 0x66e 00000690 <__vector_19>: #include "config.h" ISR(TWI_vect) { 690: 1f 92 push r1 692: 0f 92 push r0 694: 0f b6 in r0, 0x3f ; 63 696: 0f 92 push r0 698: 11 24 eor r1, r1 69a: 2f 93 push r18 69c: 3f 93 push r19 69e: 4f 93 push r20 6a0: 5f 93 push r21 6a2: 6f 93 push r22 6a4: 7f 93 push r23 6a6: 8f 93 push r24 6a8: 9f 93 push r25 6aa: af 93 push r26 6ac: bf 93 push r27 6ae: ef 93 push r30 6b0: ff 93 push r31 // i2c is low priority - allow it to be interrupted // sei(); // figure out wtf to do switch (TWSR & 0xf8) { // TWI state 6b2: 80 91 b9 00 lds r24, 0x00B9 ; 0x8000b9 <__EEPROM_REGION_LENGTH__+0x7f00b9> 6b6: 88 7f andi r24, 0xF8 ; 248 6b8: 80 3a cpi r24, 0xA0 ; 160 6ba: f1 f1 breq .+124 ; 0x738 <__vector_19+0xa8> 6bc: 60 f4 brcc .+24 ; 0x6d6 <__vector_19+0x46> 6be: 88 36 cpi r24, 0x68 ; 104 6c0: 09 f4 brne .+2 ; 0x6c4 <__vector_19+0x34> 6c2: 3f c0 rjmp .+126 ; 0x742 <__vector_19+0xb2> 6c4: 28 f4 brcc .+10 ; 0x6d0 <__vector_19+0x40> 6c6: 88 23 and r24, r24 6c8: 91 f1 breq .+100 ; 0x72e <__vector_19+0x9e> 6ca: 80 36 cpi r24, 0x60 ; 96 6cc: d1 f1 breq .+116 ; 0x742 <__vector_19+0xb2> 6ce: 34 c0 rjmp .+104 ; 0x738 <__vector_19+0xa8> 6d0: 80 38 cpi r24, 0x80 ; 128 6d2: 39 f0 breq .+14 ; 0x6e2 <__vector_19+0x52> 6d4: 31 c0 rjmp .+98 ; 0x738 <__vector_19+0xa8> 6d6: 88 3b cpi r24, 0xB8 ; 184 6d8: 41 f1 breq .+80 ; 0x72a <__vector_19+0x9a> 6da: 70 f5 brcc .+92 ; 0x738 <__vector_19+0xa8> 6dc: 88 3a cpi r24, 0xA8 ; 168 6de: 29 f1 breq .+74 ; 0x72a <__vector_19+0x9a> 6e0: 2b c0 rjmp .+86 ; 0x738 <__vector_19+0xa8> case 0x78: { // unused: this is for genaddr mode. } */ case 0x80: { // slave data receive w/ACK returned if (pegleg_data_rx(TWDR)) { 6e2: 80 91 bb 00 lds r24, 0x00BB ; 0x8000bb <__EEPROM_REGION_LENGTH__+0x7f00bb> return 0; } static uint8_t pegleg_data_rx(uint8_t data) { if (comm_cmd == MODE_NONE) { 6e6: f1 10 cpse r15, r1 6e8: 0f c0 rjmp .+30 ; 0x708 <__vector_19+0x78> // we aren't processing any commands, so this must be a new command/request. // first 4 bits = command comm_cmd = data >> 4; 6ea: 98 2f mov r25, r24 6ec: 92 95 swap r25 6ee: 9f 70 andi r25, 0x0F ; 15 6f0: f9 2e mov r15, r25 // last 4 bits = optional data comm_data[0] = data & 0x0f; 6f2: 98 2f mov r25, r24 6f4: 9f 70 andi r25, 0x0F ; 15 6f6: 90 93 2f 01 sts 0x012F, r25 ; 0x80012f // clear our data watchdog and data index comm_data_idx = 0; 6fa: 10 92 33 01 sts 0x0133, r1 ; 0x800133 comm_timeout = 0; 6fe: 10 92 2a 01 sts 0x012A, r1 ; 0x80012a // if this is an immediate command, process it if (data & 0x80) { 702: 87 ff sbrs r24, 7 704: 1e c0 rjmp .+60 ; 0x742 <__vector_19+0xb2> 706: 0a c0 rjmp .+20 ; 0x71c <__vector_19+0x8c> 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 708: e0 91 33 01 lds r30, 0x0133 ; 0x800133 70c: ef 5f subi r30, 0xFF ; 255 70e: e3 70 andi r30, 0x03 ; 3 710: e0 93 33 01 sts 0x0133, r30 ; 0x800133 comm_data[comm_data_idx] = data; 714: f0 e0 ldi r31, 0x00 ; 0 716: e1 5d subi r30, 0xD1 ; 209 718: fe 4f sbci r31, 0xFE ; 254 71a: 80 83 st Z, r24 return pegleg_cmd(); 71c: 38 de rcall .-912 ; 0x38e 71e: 88 23 and r24, r24 720: 81 f0 breq .+32 ; 0x742 <__vector_19+0xb2> // 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(); 722: 80 91 bc 00 lds r24, 0x00BC ; 0x8000bc <__EEPROM_REGION_LENGTH__+0x7f00bc> 726: 8f 7b andi r24, 0xBF ; 191 728: 0a c0 rjmp .+20 ; 0x73e <__vector_19+0xae> } 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(); 72a: be de rcall .-644 ; 0x4a8 break; 72c: 0a c0 rjmp .+20 ; 0x742 <__vector_19+0xb2> } // ** ERROR AND UNHANDLED ** // case 0x00: { // bus error // set TWSTO, clear TWINT (by setting) as per datasheet TWCR |= (_BV(TWSTO)) | (_BV(TWINT)); 72e: 80 91 bc 00 lds r24, 0x00BC ; 0x8000bc <__EEPROM_REGION_LENGTH__+0x7f00bc> 732: 80 69 ori r24, 0x90 ; 144 734: 80 93 bc 00 sts 0x00BC, r24 ; 0x8000bc <__EEPROM_REGION_LENGTH__+0x7f00bc> break; } default: { // something unhandled? fuck it, we want to be a slave. // reset everything and start over. i2c_enable_slave(); 738: 80 91 bc 00 lds r24, 0x00BC ; 0x8000bc <__EEPROM_REGION_LENGTH__+0x7f00bc> 73c: 80 64 ori r24, 0x40 ; 64 73e: 80 93 bc 00 sts 0x00BC, r24 ; 0x8000bc <__EEPROM_REGION_LENGTH__+0x7f00bc> } } // done with this TWI bit i2c_clear_int_flag(); 742: 80 91 bc 00 lds r24, 0x00BC ; 0x8000bc <__EEPROM_REGION_LENGTH__+0x7f00bc> 746: 80 68 ori r24, 0x80 ; 128 748: 80 93 bc 00 sts 0x00BC, r24 ; 0x8000bc <__EEPROM_REGION_LENGTH__+0x7f00bc> } 74c: ff 91 pop r31 74e: ef 91 pop r30 750: bf 91 pop r27 752: af 91 pop r26 754: 9f 91 pop r25 756: 8f 91 pop r24 758: 7f 91 pop r23 75a: 6f 91 pop r22 75c: 5f 91 pop r21 75e: 4f 91 pop r20 760: 3f 91 pop r19 762: 2f 91 pop r18 764: 0f 90 pop r0 766: 0f be out 0x3f, r0 ; 63 768: 0f 90 pop r0 76a: 1f 90 pop r1 76c: 18 95 reti 0000076e <__vector_12>: #include "i2c_interrupt.h" /* ISR handlers */ ISR(TIMER0_COMPA_vect) { 76e: 1f 92 push r1 770: 0f 92 push r0 772: 0f b6 in r0, 0x3f ; 63 774: 0f 92 push r0 776: 11 24 eor r1, r1 778: 2f 93 push r18 77a: 3f 93 push r19 77c: 4f 93 push r20 77e: 5f 93 push r21 780: 6f 93 push r22 782: 7f 93 push r23 784: 8f 93 push r24 786: 9f 93 push r25 788: af 93 push r26 78a: bf 93 push r27 78c: ef 93 push r30 78e: ff 93 push r31 * 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++; 790: 80 91 0b 01 lds r24, 0x010B ; 0x80010b 794: 8f 5f subi r24, 0xFF ; 255 if (tim0_milli >= 200) { 796: 88 3c cpi r24, 0xC8 ; 200 798: 18 f4 brcc .+6 ; 0x7a0 <__vector_12+0x32> * 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++; 79a: 80 93 0b 01 sts 0x010B, r24 ; 0x80010b 79e: 0c c0 rjmp .+24 ; 0x7b8 <__vector_12+0x4a> if (tim0_milli >= 200) { tim0_milli = 0; 7a0: 10 92 0b 01 sts 0x010B, r1 ; 0x80010b tim0_centi++; 7a4: 80 91 0a 01 lds r24, 0x010A ; 0x80010a 7a8: 8f 5f subi r24, 0xFF ; 255 if (tim0_centi >= 100) { 7aa: 84 36 cpi r24, 0x64 ; 100 7ac: 18 f4 brcc .+6 ; 0x7b4 <__vector_12+0x46> /* 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++; 7ae: 80 93 0a 01 sts 0x010A, r24 ; 0x80010a 7b2: 02 c0 rjmp .+4 ; 0x7b8 <__vector_12+0x4a> if (tim0_centi >= 100) { tim0_centi = 0; 7b4: 10 92 0a 01 sts 0x010A, r1 ; 0x80010a } } // 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; 7b8: 87 b5 in r24, 0x27 ; 39 7ba: 8d 33 cpi r24, 0x3D ; 61 7bc: 11 f0 breq .+4 ; 0x7c2 <__vector_12+0x54> 7be: 8d e3 ldi r24, 0x3D ; 61 7c0: 01 c0 rjmp .+2 ; 0x7c4 <__vector_12+0x56> 7c2: 8e e3 ldi r24, 0x3E ; 62 7c4: 87 bd out 0x27, r24 ; 39 /* ADC / LIGHT SENSOR / TEMP SENSOR */ // main adc handler if (adc_read_mode) { 7c6: 80 91 20 01 lds r24, 0x0120 ; 0x800120 7ca: 88 23 and r24, r24 7cc: 71 f0 breq .+28 ; 0x7ea <__vector_12+0x7c> switch (adc_read_mode) { 7ce: 80 91 20 01 lds r24, 0x0120 ; 0x800120 7d2: 81 30 cpi r24, 0x01 ; 1 7d4: 21 f0 breq .+8 ; 0x7de <__vector_12+0x70> 7d6: 88 30 cpi r24, 0x08 ; 8 7d8: 19 f4 brne .+6 ; 0x7e0 <__vector_12+0x72> case ADC_MODE_TEMPSENSOR: { tempsensor_read(); 7da: ab de rcall .-682 ; 0x532 break; 7dc: 01 c0 rjmp .+2 ; 0x7e0 <__vector_12+0x72> } case ADC_MODE_LIGHTSENSOR: { rgbled_sensor_read(); 7de: 93 dd rcall .-1242 ; 0x306 break; } } if (adc_read_step <= 0xfe) { 7e0: 8e 2d mov r24, r14 7e2: 8f 3f cpi r24, 0xFF ; 255 7e4: 11 f0 breq .+4 ; 0x7ea <__vector_12+0x7c> adc_read_step++; 7e6: 8f 5f subi r24, 0xFF ; 255 7e8: e8 2e mov r14, r24 /* 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) { 7ea: 80 91 20 01 lds r24, 0x0120 ; 0x800120 7ee: 81 30 cpi r24, 0x01 ; 1 7f0: 41 f0 breq .+16 ; 0x802 <__vector_12+0x94> rgbled_idx++; 7f2: 81 e0 ldi r24, 0x01 ; 1 7f4: 8d 0d add r24, r13 #ifdef LED_RGBX_4LED rgbled_idx &= 0x03; #else if (rgbled_idx > 2) { 7f6: 83 30 cpi r24, 0x03 ; 3 7f8: 10 f4 brcc .+4 ; 0x7fe <__vector_12+0x90> /* 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++; 7fa: d8 2e mov r13, r24 7fc: 01 c0 rjmp .+2 ; 0x800 <__vector_12+0x92> #ifdef LED_RGBX_4LED rgbled_idx &= 0x03; #else if (rgbled_idx > 2) { rgbled_idx = 0; 7fe: d1 2c mov r13, r1 } #endif // and now update them rgbled_update(); 800: 05 dd rcall .-1526 ; 0x20c } /* COMMAND IO */ // stop processing the command if it isn't complete in 100ms. if (comm_cmd != MODE_NONE) { 802: ff 20 and r15, r15 804: a1 f0 breq .+40 ; 0x82e <__vector_12+0xc0> if (++comm_timeout >= 50) { 806: 80 91 2a 01 lds r24, 0x012A ; 0x80012a 80a: 8f 5f subi r24, 0xFF ; 255 80c: 80 93 2a 01 sts 0x012A, r24 ; 0x80012a 810: 82 33 cpi r24, 0x32 ; 50 812: 68 f0 brcs .+26 ; 0x82e <__vector_12+0xc0> comm_cmd = MODE_NONE; 814: f1 2c mov r15, r1 comm_timeout = 0; 816: 10 92 2a 01 sts 0x012A, r1 ; 0x80012a i2c_disable_slave(); 81a: 80 91 bc 00 lds r24, 0x00BC ; 0x8000bc <__EEPROM_REGION_LENGTH__+0x7f00bc> 81e: 8f 7b andi r24, 0xBF ; 191 820: 80 93 bc 00 sts 0x00BC, r24 ; 0x8000bc <__EEPROM_REGION_LENGTH__+0x7f00bc> i2c_enable_slave(); 824: 80 91 bc 00 lds r24, 0x00BC ; 0x8000bc <__EEPROM_REGION_LENGTH__+0x7f00bc> 828: 80 64 ori r24, 0x40 ; 64 82a: 80 93 bc 00 sts 0x00BC, r24 ; 0x8000bc <__EEPROM_REGION_LENGTH__+0x7f00bc> } } /* PROFILING */ // determine how much CPU usage we are consuming tim0_profiler = TCNT0; 82e: 86 b5 in r24, 0x26 ; 38 } 830: ff 91 pop r31 832: ef 91 pop r30 834: bf 91 pop r27 836: af 91 pop r26 838: 9f 91 pop r25 83a: 8f 91 pop r24 83c: 7f 91 pop r23 83e: 6f 91 pop r22 840: 5f 91 pop r21 842: 4f 91 pop r20 844: 3f 91 pop r19 846: 2f 91 pop r18 848: 0f 90 pop r0 84a: 0f be out 0x3f, r0 ; 63 84c: 0f 90 pop r0 84e: 1f 90 pop r1 850: 18 95 reti 00000852 : 852: f9 99 sbic 0x1f, 1 ; 31 854: fe cf rjmp .-4 ; 0x852 856: 81 bd out 0x21, r24 ; 33 858: f8 9a sbi 0x1f, 0 ; 31 85a: 99 27 eor r25, r25 85c: 80 b5 in r24, 0x20 ; 32 85e: 08 95 ret 00000860 : 860: a8 e1 ldi r26, 0x18 ; 24 862: b0 e0 ldi r27, 0x00 ; 0 864: 42 e0 ldi r20, 0x02 ; 2 866: 05 c0 rjmp .+10 ; 0x872 00000868 : 868: 10 d0 rcall .+32 ; 0x88a 86a: 27 2f mov r18, r23 86c: 0f c0 rjmp .+30 ; 0x88c 0000086e : 86e: dc 01 movw r26, r24 870: 86 2f mov r24, r22 00000872 : 872: e8 2f mov r30, r24 874: f9 99 sbic 0x1f, 1 ; 31 876: fe cf rjmp .-4 ; 0x874 878: 05 c0 rjmp .+10 ; 0x884 87a: e1 bd out 0x21, r30 ; 33 87c: f8 9a sbi 0x1f, 0 ; 31 87e: e3 95 inc r30 880: 00 b4 in r0, 0x20 ; 32 882: 0d 92 st X+, r0 884: 41 50 subi r20, 0x01 ; 1 886: c8 f7 brcc .-14 ; 0x87a 888: 08 95 ret 0000088a : 88a: 26 2f mov r18, r22 0000088c : 88c: f9 99 sbic 0x1f, 1 ; 31 88e: fe cf rjmp .-4 ; 0x88c 890: 1f ba out 0x1f, r1 ; 31 892: 81 bd out 0x21, r24 ; 33 894: 20 bd out 0x20, r18 ; 32 896: 0f b6 in r0, 0x3f ; 63 898: f8 94 cli 89a: fa 9a sbi 0x1f, 2 ; 31 89c: f9 9a sbi 0x1f, 1 ; 31 89e: 0f be out 0x3f, r0 ; 63 8a0: 01 96 adiw r24, 0x01 ; 1 8a2: 08 95 ret 000008a4 <_exit>: 8a4: f8 94 cli 000008a6 <__stop_program>: 8a6: ff cf rjmp .-2 ; 0x8a6 <__stop_program>