dc22-wp-badge-firmware/fw_dc22_attiny88/Debug/wp_dc22_attiny88.lss

1839 lines
64 KiB
Plaintext
Raw Normal View History

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 <pegleg_cmd+0x16>
2a: c0 c1 rjmp .+896 ; 0x3ac <pegleg_cmd+0x1e>
2c: ca c1 rjmp .+916 ; 0x3c2 <pegleg_cmd+0x34>
2e: db c1 rjmp .+950 ; 0x3e6 <pegleg_cmd+0x58>
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 <main>
90: 09 c4 rjmp .+2066 ; 0x8a4 <_exit>
00000092 <__bad_interrupt>:
92: b6 cf rjmp .-148 ; 0x0 <__vectors>
00000094 <adc_init>:
/* 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 <adc_channel>:
}
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 <adc_channel+0x28>
// 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 <adc_channel+0x22>
ce: 81 e0 ldi r24, 0x01 ; 1
d0: 01 c0 rjmp .+2 ; 0xd4 <adc_channel+0x1c>
d2: 88 0f add r24, r24
d4: 2a 95 dec r18
d6: ea f7 brpl .-6 ; 0xd2 <adc_channel+0x1a>
d8: 01 c0 rjmp .+2 ; 0xdc <adc_channel+0x24>
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 <adc_channel+0x34>
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 <adc_channel+0x3e>
} else if (vref == ADC_REF_BANDGAP) {
ec: 62 30 cpi r22, 0x02 ; 2
ee: 29 f4 brne .+10 ; 0xfa <adc_channel+0x42>
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 <adc_start>:
}
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 <adc_start+0x36>
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_reread>
adc_averages = enable_averaging ? reread : 0;
10c: 66 23 and r22, r22
10e: 11 f0 breq .+4 ; 0x114 <adc_start+0x18>
110: 98 2f mov r25, r24
112: 01 c0 rjmp .+2 ; 0x116 <adc_start+0x1a>
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 <adc_busy>
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 <adc_start+0x38>
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 <adc_reread>
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 <adc_reread>
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 <adc_reread>
1a2: 81 50 subi r24, 0x01 ; 1
1a4: 80 93 0c 01 sts 0x010C, r24 ; 0x80010c <adc_reread>
// 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 <adc_busy>
}
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 <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;
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 <rgbled_update>:
}
// 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 <rgbled_update+0x3a>
244: 44 0f add r20, r20
246: 2a 95 dec r18
248: ea f7 brpl .-6 ; 0x244 <rgbled_update+0x38>
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 <rgbled_update+0x4e>
258: 88 0f add r24, r24
25a: 0a 94 dec r0
25c: ea f7 brpl .-6 ; 0x258 <rgbled_update+0x4c>
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 <rgbled_sensor_init>:
// 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 <rgbled_sensor_init+0x2a>
2b0: 66 0f add r22, r22
2b2: 77 1f adc r23, r23
2b4: 8a 95 dec r24
2b6: e2 f7 brpl .-8 ; 0x2b0 <rgbled_sensor_init+0x26>
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 <rgbled_sensor_init+0x46>
_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 <rgbled_sensor_sensitivity>:
}
// 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 <rgbled_sensor_sensitivity+0x12>
if (sensitivity) {
2ee: 66 23 and r22, r22
2f0: 29 f0 breq .+10 ; 0x2fc <rgbled_sensor_sensitivity+0x12>
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 <rgbled_sensor_read_idx>:
}
}
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 <rgbled_read_sel>
304: 08 95 ret
00000306 <rgbled_sensor_read>:
void rgbled_sensor_read()
{
uint8_t sens;
sens = rgbled_sensitivity[rgbled_read_sel];
306: 80 91 05 01 lds r24, 0x0105 ; 0x800105 <rgbled_read_sel>
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 <rgbled_sensor_read+0x14>
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 <rgbled_sensor_read+0x20>
// 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 <rgbled_sensor_read+0x44>
} else if (adc_read_step == 1) {
326: 21 30 cpi r18, 0x01 ; 1
328: 19 f4 brne .+6 ; 0x330 <rgbled_sensor_read+0x2a>
adc_start(0, 0);
32a: 60 e0 ldi r22, 0x00 ; 0
32c: 80 e0 ldi r24, 0x00 ; 0
32e: 18 c0 rjmp .+48 ; 0x360 <rgbled_sensor_read+0x5a>
} else if (adc_read_step == 2) {
330: 22 30 cpi r18, 0x02 ; 2
332: 61 f4 brne .+24 ; 0x34c <rgbled_sensor_read+0x46>
// if the ADC is done, charge up LED for reading
if (adc_busy) {
334: 90 91 1f 01 lds r25, 0x011F ; 0x80011f <adc_busy>
338: 99 23 and r25, r25
33a: 19 f0 breq .+6 ; 0x342 <rgbled_sensor_read+0x3c>
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 <rgbled_sensor_init>
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 <rgbled_read_sel>
34a: b6 ce rjmp .-660 ; 0xb8 <adc_channel>
}
} 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 <rgbled_sensor_read+0x5c>
// 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 <adc_start>
} 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 <rgbled_sensor_read+0x86>
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 <adc_busy>
370: 81 11 cpse r24, r1
372: 0c c0 rjmp .+24 ; 0x38c <rgbled_sensor_read+0x86>
// 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 <adc_channel>
rgbled_io_init(); // set LED pins up again
37a: 3b df rcall .-394 ; 0x1f2 <rgbled_io_init>
}
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 <adc_read_mode>
38c: 08 95 ret
0000038e <pegleg_cmd>:
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 <pegleg_cmd+0xe>
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 <comm_timeout>
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 <comm_data_idx>
3b0: 88 23 and r24, r24
3b2: 09 f4 brne .+2 ; 0x3b6 <pegleg_cmd+0x28>
3b4: 6c c0 rjmp .+216 ; 0x48e <__LOCK_REGION_LENGTH__+0x8e>
comm_cmd = comm_data[1];
3b6: f0 90 30 01 lds r15, 0x0130 ; 0x800130 <comm_data+0x1>
// 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 <comm_data_idx>
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 <comm_data>
3c6: e4 30 cpi r30, 0x04 ; 4
3c8: 20 f4 brcc .+8 ; 0x3d2 <pegleg_cmd+0x44>
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 <pegleg_cmd+0x50>
} else if (comm_data[0] < 8) {
3d2: e8 30 cpi r30, 0x08 ; 8
3d4: 08 f0 brcs .+2 ; 0x3d8 <pegleg_cmd+0x4a>
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 <comm_data+0x1>
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 <comm_data_idx>
3ea: 88 23 and r24, r24
3ec: 09 f4 brne .+2 ; 0x3f0 <pegleg_cmd+0x62>
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 <adc_result+0x10>
3f4: 90 91 1e 01 lds r25, 0x011E ; 0x80011e <adc_result+0x11>
3f8: 89 2b or r24, r25
3fa: 09 f4 brne .+2 ; 0x3fe <pegleg_cmd+0x70>
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 <adc_result+0x10>
402: 70 91 1e 01 lds r23, 0x011E ; 0x80011e <adc_result+0x11>
406: 80 91 30 01 lds r24, 0x0130 ; 0x800130 <comm_data+0x1>
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 <temp_offset+0x1>
416: 60 93 06 01 sts 0x0106, r22 ; 0x800106 <temp_offset>
// 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 <eeprom_write_word>
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 <comm_data_idx>
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 <adc_read_mode>
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_mode>
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 <adc_read_mode>
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 <adc_read_mode>
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_mode>
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 <comm_data>
454: 54 df rcall .-344 ; 0x2fe <rgbled_sensor_read_idx>
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 <pirate_sleep_mode>
// 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>
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 <led 0-3> <sens 1-200>
if (comm_data_idx >= 1) {
46a: 80 91 33 01 lds r24, 0x0133 ; 0x800133 <comm_data_idx>
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 <comm_data>
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 <comm_data+0x1>
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 <rgbled_sensor_sensitivity>
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 <comm_timeout>
return 1;
48c: 81 e0 ldi r24, 0x01 ; 1
}
}
return 0;
}
48e: 08 95 ret
00000490 <i2c_slave_tx.constprop.4>:
/* 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 <pegleg_data_tx>:
/* 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 <pegleg_data_tx+0x34>
4ae: 89 30 cpi r24, 0x09 ; 9
4b0: c1 f0 breq .+48 ; 0x4e2 <pegleg_data_tx+0x3a>
4b2: 84 30 cpi r24, 0x04 ; 4
4b4: 51 f5 brne .+84 ; 0x50a <pegleg_data_tx+0x62>
case MODE_EEPROM_READ: {
if (comm_data[0] < 64) {
4b6: 80 91 2f 01 lds r24, 0x012F ; 0x80012f <comm_data>
4ba: 80 34 cpi r24, 0x40 ; 64
4bc: 28 f4 brcc .+10 ; 0x4c8 <pegleg_data_tx+0x20>
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 <eeprom_read_byte>
4c2: e6 df rcall .-52 ; 0x490 <i2c_slave_tx.constprop.4>
ret = 1;
4c4: 81 e0 ldi r24, 0x01 ; 1
4c6: 06 c0 rjmp .+12 ; 0x4d4 <pegleg_data_tx+0x2c>
} 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 <comm_timeout>
4da: 08 95 ret
return ret;
}
case MODE_TEMPSENSOR_READ: {
i2c_slave_tx(temperature, 1);
4dc: 80 91 08 01 lds r24, 0x0108 ; 0x800108 <temperature>
4e0: 0e c0 rjmp .+28 ; 0x4fe <pegleg_data_tx+0x56>
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 <comm_data>
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 <i2c_slave_tx.constprop.4>
comm_cmd = 0;
500: f1 2c mov r15, r1
comm_timeout = 0;
502: 10 92 2a 01 sts 0x012A, r1 ; 0x80012a <comm_timeout>
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 <tempsensor_process>:
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 <adc_result+0x10>
51c: 90 91 1e 01 lds r25, 0x011E ; 0x80011e <adc_result+0x11>
520: 90 91 06 01 lds r25, 0x0106 ; 0x800106 <temp_offset>
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 <tempsensor_read>:
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 <tempsensor_read+0xc>
// 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 <adc_channel>
} else if (adc_read_step == 3) {
53e: 83 30 cpi r24, 0x03 ; 3
540: 19 f4 brne .+6 ; 0x548 <tempsensor_read+0x16>
// 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 <adc_start>
} else if (adc_read_step > 3) {
548: 84 30 cpi r24, 0x04 ; 4
54a: 70 f0 brcs .+28 ; 0x568 <tempsensor_read+0x36>
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 <adc_busy>
554: 81 11 cpse r24, r1
556: 08 c0 rjmp .+16 ; 0x568 <tempsensor_read+0x36>
// 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_channel>
adc_read_mode = 0;
55e: 10 92 20 01 sts 0x0120, r1 ; 0x800120 <adc_read_mode>
temperature = tempsensor_process();
562: da df rcall .-76 ; 0x518 <tempsensor_process>
564: 80 93 08 01 sts 0x0108, r24 ; 0x800108 <temperature>
568: 08 95 ret
0000056a <main>:
/* 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 <rgbled_io_init>
/* 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 <timer1_mode>
// 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 <adc_init>
// 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 <main+0xea>
// turn on the ADC, wait for it to warm up
adc_init();
60e: 42 dd rcall .-1404 ; 0x94 <adc_init>
#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 <main+0xac>
61e: 00 c0 rjmp .+0 ; 0x620 <main+0xb6>
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 <main+0xea>
// 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 <adc_read_mode>
tempsensor_read();
62e: 81 df rcall .-254 ; 0x532 <tempsensor_read>
while (adc_busy);
630: 80 91 1f 01 lds r24, 0x011F ; 0x80011f <adc_busy>
634: 81 11 cpse r24, r1
636: fc cf rjmp .-8 ; 0x630 <main+0xc6>
// here's our correction factor!
temp_offset = adc_result[ADC_CHAN_TEMP];
638: 60 91 1d 01 lds r22, 0x011D ; 0x80011d <adc_result+0x10>
63c: 70 91 1e 01 lds r23, 0x011E ; 0x80011e <adc_result+0x11>
640: 70 93 07 01 sts 0x0107, r23 ; 0x800107 <temp_offset+0x1>
644: 60 93 06 01 sts 0x0106, r22 ; 0x800106 <temp_offset>
// 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 <eeprom_write_word>
// and that's it - we're done.
adc_read_mode = 0;
64e: 10 92 20 01 sts 0x0120, r1 ; 0x800120 <adc_read_mode>
652: 0d c0 rjmp .+26 ; 0x66e <main+0x104>
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 <eeprom_read_word>
// 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 <main+0xfc>
// 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 <temp_offset+0x1>
66a: 80 93 06 01 sts 0x0106, r24 ; 0x800106 <temp_offset>
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 <pirate_sleep_mode>
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 <pirate_sleep_mode>
// 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 <main+0x104>
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 <comm_data>
// clear our data watchdog and data index
comm_data_idx = 0;
6fa: 10 92 33 01 sts 0x0133, r1 ; 0x800133 <comm_data_idx>
comm_timeout = 0;
6fe: 10 92 2a 01 sts 0x012A, r1 ; 0x80012a <comm_timeout>
// 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 <comm_data_idx>
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_idx>
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 <pegleg_cmd>
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 <pegleg_data_tx>
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 <tim0_milli>
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 <tim0_milli>
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_milli>
tim0_centi++;
7a4: 80 91 0a 01 lds r24, 0x010A ; 0x80010a <tim0_centi>
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 <tim0_centi>
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 <tim0_centi>
}
}
// 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 <adc_read_mode>
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 <adc_read_mode>
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 <tempsensor_read>
break;
7dc: 01 c0 rjmp .+2 ; 0x7e0 <__vector_12+0x72>
}
case ADC_MODE_LIGHTSENSOR: {
rgbled_sensor_read();
7de: 93 dd rcall .-1242 ; 0x306 <rgbled_sensor_read>
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 <adc_read_mode>
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 <rgbled_update>
}
/* 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 <comm_timeout>
80a: 8f 5f subi r24, 0xFF ; 255
80c: 80 93 2a 01 sts 0x012A, r24 ; 0x80012a <comm_timeout>
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 <comm_timeout>
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 <eeprom_read_byte>:
852: f9 99 sbic 0x1f, 1 ; 31
854: fe cf rjmp .-4 ; 0x852 <eeprom_read_byte>
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 <eeprom_read_word>:
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 <eeprom_read_blraw>
00000868 <eeprom_write_word>:
868: 10 d0 rcall .+32 ; 0x88a <eeprom_write_byte>
86a: 27 2f mov r18, r23
86c: 0f c0 rjmp .+30 ; 0x88c <eeprom_write_r18>
0000086e <eeprom_read_block>:
86e: dc 01 movw r26, r24
870: 86 2f mov r24, r22
00000872 <eeprom_read_blraw>:
872: e8 2f mov r30, r24
874: f9 99 sbic 0x1f, 1 ; 31
876: fe cf rjmp .-4 ; 0x874 <eeprom_read_blraw+0x2>
878: 05 c0 rjmp .+10 ; 0x884 <eeprom_read_blraw+0x12>
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 <eeprom_read_blraw+0x8>
888: 08 95 ret
0000088a <eeprom_write_byte>:
88a: 26 2f mov r18, r22
0000088c <eeprom_write_r18>:
88c: f9 99 sbic 0x1f, 1 ; 31
88e: fe cf rjmp .-4 ; 0x88c <eeprom_write_r18>
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>