Blame | Last modification | View Log | Download
AVRcam.elf: file format elf32-avr
Sections:
Idx Name Size VMA LMA File off Algn
0 .noinit 00000030 00800300 00800300 00001162 2**0
ALLOC
1 .bss 00000274 00800070 00800070 00001162 2**0
ALLOC
2 .data 00000010 00800060 0000109e 00001152 2**0
CONTENTS, ALLOC, LOAD, DATA
3 .text 0000109e 00000000 00000000 000000b4 2**1
CONTENTS, ALLOC, LOAD, READONLY, CODE
4 .eeprom 00000000 00810000 00810000 00001162 2**0
CONTENTS
5 .stab 00003f30 00000000 00000000 00001164 2**2
CONTENTS, READONLY, DEBUGGING
6 .stabstr 0000181e 00000000 00000000 00005094 2**0
CONTENTS, READONLY, DEBUGGING
Disassembly of section .text:
00000000 <__vectors>:
0: 63 c0 rjmp .+198 ; 0xc8
2: ea c7 rjmp .+4052 ; 0xfd8
4: ea c7 rjmp .+4052 ; 0xfda
6: 7a c0 rjmp .+244 ; 0xfc
8: 79 c0 rjmp .+242 ; 0xfc
a: 78 c0 rjmp .+240 ; 0xfc
c: 77 c0 rjmp .+238 ; 0xfc
e: 76 c0 rjmp .+236 ; 0xfc
10: e5 c7 rjmp .+4042 ; 0xfdc
12: 74 c0 rjmp .+232 ; 0xfc
14: 73 c0 rjmp .+230 ; 0xfc
16: a8 c5 rjmp .+2896 ; 0xb68
18: 71 c0 rjmp .+226 ; 0xfc
1a: 70 c0 rjmp .+224 ; 0xfc
1c: 6f c0 rjmp .+222 ; 0xfc
1e: 6e c0 rjmp .+220 ; 0xfc
20: 6d c0 rjmp .+218 ; 0xfc
22: 13 c6 rjmp .+3110 ; 0xc4a
24: 6b c0 rjmp .+214 ; 0xfc
00000026 <__ctors_end>:
26: 2a c6 rjmp .+3156 ; 0xc7c
28: 93 c6 rjmp .+3366 ; 0xd50
2a: 92 c6 rjmp .+3364 ; 0xd50
2c: 91 c6 rjmp .+3362 ; 0xd50
2e: 90 c6 rjmp .+3360 ; 0xd50
30: 8f c6 rjmp .+3358 ; 0xd50
32: 8e c6 rjmp .+3356 ; 0xd50
34: 8d c6 rjmp .+3354 ; 0xd50
36: 22 c6 rjmp .+3140 ; 0xc7c
38: 8b c6 rjmp .+3350 ; 0xd50
3a: 8a c6 rjmp .+3348 ; 0xd50
3c: 89 c6 rjmp .+3346 ; 0xd50
3e: 88 c6 rjmp .+3344 ; 0xd50
40: 87 c6 rjmp .+3342 ; 0xd50
42: 86 c6 rjmp .+3340 ; 0xd50
44: 85 c6 rjmp .+3338 ; 0xd50
46: 2a c6 rjmp .+3156 ; 0xc9c
48: 83 c6 rjmp .+3334 ; 0xd50
4a: 82 c6 rjmp .+3332 ; 0xd50
4c: 81 c6 rjmp .+3330 ; 0xd50
4e: 80 c6 rjmp .+3328 ; 0xd50
50: 7f c6 rjmp .+3326 ; 0xd50
52: 7e c6 rjmp .+3324 ; 0xd50
54: 7d c6 rjmp .+3322 ; 0xd50
56: 25 c6 rjmp .+3146 ; 0xca2
58: 7b c6 rjmp .+3318 ; 0xd50
5a: 7a c6 rjmp .+3316 ; 0xd50
5c: 79 c6 rjmp .+3314 ; 0xd50
5e: 78 c6 rjmp .+3312 ; 0xd50
60: 77 c6 rjmp .+3310 ; 0xd50
62: 76 c6 rjmp .+3308 ; 0xd50
64: 75 c6 rjmp .+3306 ; 0xd50
66: 25 c6 rjmp .+3146 ; 0xcb2
68: 73 c6 rjmp .+3302 ; 0xd50
6a: 72 c6 rjmp .+3300 ; 0xd50
6c: 71 c6 rjmp .+3298 ; 0xd50
6e: 70 c6 rjmp .+3296 ; 0xd50
70: 6f c6 rjmp .+3294 ; 0xd50
72: 6e c6 rjmp .+3292 ; 0xd50
74: 6d c6 rjmp .+3290 ; 0xd50
76: 64 c6 rjmp .+3272 ; 0xd40
78: 6b c6 rjmp .+3286 ; 0xd50
7a: 6a c6 rjmp .+3284 ; 0xd50
7c: 69 c6 rjmp .+3282 ; 0xd50
7e: 68 c6 rjmp .+3280 ; 0xd50
80: 67 c6 rjmp .+3278 ; 0xd50
82: 66 c6 rjmp .+3276 ; 0xd50
84: 65 c6 rjmp .+3274 ; 0xd50
86: 64 c6 rjmp .+3272 ; 0xd50
88: 63 c6 rjmp .+3270 ; 0xd50
8a: 62 c6 rjmp .+3268 ; 0xd50
8c: 61 c6 rjmp .+3266 ; 0xd50
8e: 60 c6 rjmp .+3264 ; 0xd50
90: 5f c6 rjmp .+3262 ; 0xd50
92: 5e c6 rjmp .+3260 ; 0xd50
94: 5d c6 rjmp .+3258 ; 0xd50
96: 23 c6 rjmp .+3142 ; 0xcde
98: 5b c6 rjmp .+3254 ; 0xd50
9a: 5a c6 rjmp .+3252 ; 0xd50
9c: 59 c6 rjmp .+3250 ; 0xd50
9e: 58 c6 rjmp .+3248 ; 0xd50
a0: 57 c6 rjmp .+3246 ; 0xd50
a2: 56 c6 rjmp .+3244 ; 0xd50
a4: 55 c6 rjmp .+3242 ; 0xd50
a6: fd c5 rjmp .+3066 ; 0xca2
a8: 53 c6 rjmp .+3238 ; 0xd50
aa: 52 c6 rjmp .+3236 ; 0xd50
ac: 51 c6 rjmp .+3234 ; 0xd50
ae: 50 c6 rjmp .+3232 ; 0xd50
b0: 4f c6 rjmp .+3230 ; 0xd50
b2: 4e c6 rjmp .+3228 ; 0xd50
b4: 4d c6 rjmp .+3226 ; 0xd50
b6: 1f c6 rjmp .+3134 ; 0xcf6
b8: 4b c6 rjmp .+3222 ; 0xd50
ba: 4a c6 rjmp .+3220 ; 0xd50
bc: 49 c6 rjmp .+3218 ; 0xd50
be: 48 c6 rjmp .+3216 ; 0xd50
c0: 47 c6 rjmp .+3214 ; 0xd50
c2: 46 c6 rjmp .+3212 ; 0xd50
c4: 45 c6 rjmp .+3210 ; 0xd50
c6: 36 c6 rjmp .+3180 ; 0xd34
000000c8 <__init>:
c8: 11 24 eor r1, r1
ca: 1f be out 0x3f, r1 ; 63
cc: cf e5 ldi r28, 0x5F ; 95
ce: d4 e0 ldi r29, 0x04 ; 4
d0: de bf out 0x3e, r29 ; 62
d2: cd bf out 0x3d, r28 ; 61
000000d4 <__do_copy_data>:
d4: 10 e0 ldi r17, 0x00 ; 0
d6: a0 e6 ldi r26, 0x60 ; 96
d8: b0 e0 ldi r27, 0x00 ; 0
da: ee e9 ldi r30, 0x9E ; 158
dc: f0 e1 ldi r31, 0x10 ; 16
de: 02 c0 rjmp .+4 ; 0xe4
000000e0 <.do_copy_data_loop>:
e0: 05 90 lpm r0, Z+
e2: 0d 92 st X+, r0
000000e4 <.do_copy_data_start>:
e4: a0 37 cpi r26, 0x70 ; 112
e6: b1 07 cpc r27, r17
e8: d9 f7 brne .-10 ; 0xe0
000000ea <__do_clear_bss>:
ea: 12 e0 ldi r17, 0x02 ; 2
ec: a0 e7 ldi r26, 0x70 ; 112
ee: b0 e0 ldi r27, 0x00 ; 0
f0: 01 c0 rjmp .+2 ; 0xf4
000000f2 <.do_clear_bss_loop>:
f2: 1d 92 st X+, r1
000000f4 <.do_clear_bss_start>:
f4: a4 3e cpi r26, 0xE4 ; 228
f6: b1 07 cpc r27, r17
f8: e1 f7 brne .-8 ; 0xf2
fa: 31 c0 rjmp .+98 ; 0x15e
000000fc <__bad_interrupt>:
fc: 76 c7 rjmp .+3820 ; 0xfea
000000fe <CamInt_init>:
#endif
/* set up the mega8 ports that will be interfacing
with the camera */
CAM_CONTROL_PORT_DIR |= (1<<CAM_RESET_LINE); /* cam reset is output */
fe: 8f 9a sbi 0x11, 7 ; 17
CAM_CONTROL_PORT_DIR |= 0x80; /* set just the MSB as an output */
100: 8f 9a sbi 0x11, 7 ; 17
CAM_CONTROL_PORT_DIR &= 0xFB; /* make sure bit2 is clear (input) */
102: 8a 98 cbi 0x11, 2 ; 17
CAM_CONTROL_PORT &= 0x7F; /* set reset line low */
104: 97 98 cbi 0x12, 7 ; 18
CAM_G_BUS_DIR &= 0xF0; /* 4-bit G bus all inputs */
106: 90 ef ldi r25, 0xF0 ; 240
108: 87 b3 in r24, 0x17 ; 23
10a: 89 23 and r24, r25
10c: 87 bb out 0x17, r24 ; 23
CAM_G_BUS_DIR |= 0xF0; /* disable the pull-up on PB4 and PB5 */
10e: 87 b3 in r24, 0x17 ; 23
110: 89 2b or r24, r25
112: 87 bb out 0x17, r24 ; 23
CAM_RB_BUS_DIR &= 0xF0; /* 4-bit RB bus all inputs */
114: 84 b3 in r24, 0x14 ; 20
116: 89 23 and r24, r25
118: 84 bb out 0x14, r24 ; 20
/* ensure that timer1 is disabled to start...eventually, when PCLK needs
to feed timer1 through the external counter, it will be enabled on an
"as needed" basis...*/
TCCR1B &= ~( (1<<CS12)|(1<<CS11)|(1<<CS10) );
11a: 8e b5 in r24, 0x2e ; 46
11c: 88 7f andi r24, 0xF8 ; 248
11e: 8e bd out 0x2e, r24 ; 46
/* we'll turn on the interrupt after we assign the initial TCNT value */
/* set up External Interrupt1 to interrupt us on rising edges (HREF)...
this is needed to indicate when the first pixel of each line is about to start, so
we can synch up with it...this interrupt will be disabled once HREF goes high */
MCUCR |= (1<<ISC11) | (1<<ISC10); /* rising edge interrupt */
120: 85 b7 in r24, 0x35 ; 53
122: 8c 60 ori r24, 0x0C ; 12
124: 85 bf out 0x35, r24 ; 53
/* the interrupt will be enabled when we are ready to detect the rising edge of
HREF...its now primed and ready to go */
/* set up External Interrupt0 to interrupt us on rising edges (VSYNC) */
MCUCR |= (1<<ISC01) | (1<<ISC00); /* rising edge interrupt */
126: 85 b7 in r24, 0x35 ; 53
128: 83 60 ori r24, 0x03 ; 3
12a: 85 bf out 0x35, r24 ; 53
GICR |= (1<<INT0); /* interrupt request enabled */
12c: 8b b7 in r24, 0x3b ; 59
12e: 80 64 ori r24, 0x40 ; 64
130: 8b bf out 0x3b, r24 ; 59
/* set up TimerO to count and be clocked from an external pulse source
(HREF) on falling edges...eventually, we need to enable the interrupt
for this! FIX THIS */
TCCR0 = (1<<CS02)|(1<<CS01)|(0<<CS00);
132: 86 e0 ldi r24, 0x06 ; 6
134: 83 bf out 0x33, r24 ; 51
/* setting up the PCLK counter with Timer1 will be done right after
we start receiving pixels in each line...we sacrifice the first pixel
in each line, but we'll account for it...*/
/* set up the mega8 so that its sleep mode puts it in an IDLE sleep
mode, where it can wake up as fast as possible */
set_sleep_mode(SLEEP_MODE_IDLE);
136: 85 b7 in r24, 0x35 ; 53
138: 8f 78 andi r24, 0x8F ; 143
13a: 85 bf out 0x35, r24 ; 53
/* umm....we need to actually enable the sleep mode...*/
MCUCR |= 0x80;
13c: 85 b7 in r24, 0x35 ; 53
13e: 80 68 ori r24, 0x80 ; 128
140: 85 bf out 0x35, r24 ; 53
/* initialize the memLookup table */
memset(colorMap,0x00,NUM_ELEMENTS_IN_COLOR_MAP);
142: 80 e0 ldi r24, 0x00 ; 0
144: 93 e0 ldi r25, 0x03 ; 3
146: 20 e3 ldi r18, 0x30 ; 48
148: fc 01 movw r30, r24
14a: 11 92 st Z+, r1
14c: 2a 95 dec r18
14e: e9 f7 brne .-6 ; 0x14a
/* read the color map out of EEPROM */
eeprom_read_block(colorMap, (unsigned char*)0x01,NUM_ELEMENTS_IN_COLOR_MAP);
150: 40 e3 ldi r20, 0x30 ; 48
152: 50 e0 ldi r21, 0x00 ; 0
154: 61 e0 ldi r22, 0x01 ; 1
156: 70 e0 ldi r23, 0x00 ; 0
158: 7d d7 rcall .+3834 ; 0x1054
#if OUTPUT_INITIAL_COLOR_MAP
UIMgr_txBuffer("\r\n",2);
for (i=0; i<NUM_ELEMENTS_IN_COLOR_MAP; i++)
{
memset(asciiBuffer,0x00,5);
itoa(colorMap[i],asciiBuffer,10);
UIMgr_txBuffer(asciiBuffer,3);
UIMgr_txBuffer(" ",1);
if (i==15 || i == 31)
{
/* break up the output */
UIMgr_txBuffer("\r\n",2);
}
}
#endif
#ifndef NO_CRYSTAL
CamInt_resetCam();
#endif
}
15a: 08 95 ret
0000015c <CamInt_resetCam>:
/***********************************************************
Function Name: CamInt_resetCam
Function Description: This function is responsible
for resetting the camera. This is accomplished by
toggling the reset line on the OV6620 for ~100 mS.
Inputs: none
Outputs: none
IMPORTANT NOTE: This function has effectively been removed
since resetting the camera now causes the camera to not
output the clock signal. Thus, if we reset the cam, the
AVR has no clock, and thus doesn't run...
***********************************************************/
void CamInt_resetCam(void)
{
15c: 08 95 ret
0000015e <main>:
Inputs: none
Outputs: int
***********************************************************/
int main(void)
{
15e: cf e5 ldi r28, 0x5F ; 95
160: d4 e0 ldi r29, 0x04 ; 4
162: de bf out 0x3e, r29 ; 62
164: cd bf out 0x3d, r28 ; 61
/* initialize all of the interface modules */
DebugInt_init();
166: aa d6 rcall .+3412 ; 0xebc
UartInt_init();
168: f1 d4 rcall .+2530 ; 0xb4c
I2CInt_init();
16a: 2c d5 rcall .+2648 ; 0xbc4
CamInt_init();
16c: c8 df rcall .-112 ; 0xfe
/* initialize the remaining modules that will process
data...interrupts need to be on for these */
ENABLE_INTS();
16e: 78 94 sei
CamConfig_init();
170: fa d5 rcall .+3060 ; 0xd66
UIMgr_init();
172: 94 d2 rcall .+1320 ; 0x69c
FrameMgr_init();
174: 7f d0 rcall .+254 ; 0x274
/* provide a short delay for the camera to stabilize before
we let the executive start up */
Utility_delay(1000);
176: 88 ee ldi r24, 0xE8 ; 232
178: 93 e0 ldi r25, 0x03 ; 3
17a: 65 d6 rcall .+3274 ; 0xe46
/* the rest of the application will be under the
control of the Executive. */
Exec_run();
17c: 03 d0 rcall .+6 ; 0x184
/* this should never be reached */
return(0);
}
17e: 80 e0 ldi r24, 0x00 ; 0
180: 90 e0 ldi r25, 0x00 ; 0
182: 8c c7 rjmp .+3864 ; 0x109c
00000184 <Exec_run>:
Inputs: none
Outputs: none
***********************************************************/
void Exec_run(void)
{
184: cf 93 push r28
unsigned char eventGenerated;
while(1)
{
if (fastEventBitmask)
186: 80 91 72 00 lds r24, 0x0072
18a: 88 23 and r24, r24
18c: b9 f0 breq .+46 ; 0x1bc
{
/* an event needing fast processing has been received */
/* a received line needs to be processed...this
needs to be processed as quickly as possible */
if (fastEventBitmask & FEV_ACQUIRE_LINE_COMPLETE)
18e: 80 ff sbrs r24, 0
190: 09 c0 rjmp .+18 ; 0x1a4
{
DISABLE_INTS();
192: f8 94 cli
fastEventBitmask &= ~FEV_ACQUIRE_LINE_COMPLETE;
194: 80 91 72 00 lds r24, 0x0072
198: 8e 7f andi r24, 0xFE ; 254
19a: 80 93 72 00 sts 0x0072, r24
ENABLE_INTS();
19e: 78 94 sei
FrameMgr_processLine();
1a0: f8 d0 rcall .+496 ; 0x392
/* also check if serial data needs to be sent
out through UIMgr */
UIMgr_transmitPendingData();
1a2: ac d2 rcall .+1368 ; 0x6fc
/* we can't just call acquire line again here,
since we don't know if we need to acquire another
line or not (it depends on the FrameMgr to figure
this out) */
}
if (fastEventBitmask & FEV_PROCESS_LINE_COMPLETE)
1a4: 80 91 72 00 lds r24, 0x0072
1a8: 81 ff sbrs r24, 1
1aa: 08 c0 rjmp .+16 ; 0x1bc
{
DISABLE_INTS();
1ac: f8 94 cli
fastEventBitmask &= ~FEV_PROCESS_LINE_COMPLETE;
1ae: 80 91 72 00 lds r24, 0x0072
1b2: 8d 7f andi r24, 0xFD ; 253
1b4: 80 93 72 00 sts 0x0072, r24
ENABLE_INTS();
1b8: 78 94 sei
FrameMgr_acquireLine();
1ba: b9 d0 rcall .+370 ; 0x32e
}
}
if (IS_DATA_IN_EVENT_FIFO() == TRUE)
1bc: 90 91 70 00 lds r25, 0x0070
1c0: 80 91 71 00 lds r24, 0x0071
1c4: 98 17 cp r25, r24
1c6: f9 f2 breq .-66 ; 0x186
{
eventGenerated = Exec_readEventFifo();
1c8: 32 d0 rcall .+100 ; 0x22e
1ca: c8 2f mov r28, r24
switch(eventGenerated)
1cc: 99 27 eor r25, r25
1ce: 80 31 cpi r24, 0x10 ; 16
1d0: 91 05 cpc r25, r1
1d2: 11 f1 breq .+68 ; 0x218
1d4: 81 31 cpi r24, 0x11 ; 17
1d6: 91 05 cpc r25, r1
1d8: 7c f4 brge .+30 ; 0x1f8
1da: 82 30 cpi r24, 0x02 ; 2
1dc: 91 05 cpc r25, r1
1de: 09 f1 breq .+66 ; 0x222
1e0: 83 30 cpi r24, 0x03 ; 3
1e2: 91 05 cpc r25, r1
1e4: 1c f4 brge .+6 ; 0x1ec
1e6: 01 97 sbiw r24, 0x01 ; 1
1e8: d1 f0 breq .+52 ; 0x21e
1ea: cd cf rjmp .-102 ; 0x186
1ec: 84 30 cpi r24, 0x04 ; 4
1ee: 91 05 cpc r25, r1
1f0: c1 f0 breq .+48 ; 0x222
1f2: 08 97 sbiw r24, 0x08 ; 8
1f4: b1 f0 breq .+44 ; 0x222
1f6: c7 cf rjmp .-114 ; 0x186
1f8: 80 38 cpi r24, 0x80 ; 128
1fa: 91 05 cpc r25, r1
1fc: 91 f0 breq .+36 ; 0x222
1fe: 81 38 cpi r24, 0x81 ; 129
200: 91 05 cpc r25, r1
202: 1c f4 brge .+6 ; 0x20a
204: 80 97 sbiw r24, 0x20 ; 32
206: 69 f0 breq .+26 ; 0x222
208: be cf rjmp .-132 ; 0x186
20a: 81 38 cpi r24, 0x81 ; 129
20c: 91 05 cpc r25, r1
20e: 49 f0 breq .+18 ; 0x222
210: 80 39 cpi r24, 0x90 ; 144
212: 91 05 cpc r25, r1
214: 49 f0 breq .+18 ; 0x228
216: b7 cf rjmp .-146 ; 0x186
{
case (EV_DUMP_FRAME):
FrameMgr_dispatchEvent(eventGenerated);
break;
case (EV_ENABLE_TRACKING):
FrameMgr_dispatchEvent(eventGenerated);
break;
case (EV_DISABLE_TRACKING):
FrameMgr_dispatchEvent(eventGenerated);
break;
case (EV_ACQUIRE_LINE_COMPLETE):
FrameMgr_dispatchEvent(eventGenerated);
218: 8c 2f mov r24, r28
21a: 33 d0 rcall .+102 ; 0x282
UIMgr_dispatchEvent(eventGenerated);
21c: 05 c0 rjmp .+10 ; 0x228
break;
case (EV_ACQUIRE_FRAME_COMPLETE):
FrameMgr_dispatchEvent(eventGenerated);
break;
case (EV_PROCESS_LINE_COMPLETE):
FrameMgr_dispatchEvent(eventGenerated);
break;
case (EV_PROCESS_FRAME_COMPLETE):
FrameMgr_dispatchEvent(eventGenerated);
break;
case (EV_SERIAL_DATA_RECEIVED):
UIMgr_dispatchEvent(eventGenerated);
21e: 8c 2f mov r24, r28
220: 58 d2 rcall .+1200 ; 0x6d2
FrameMgr_dispatchEvent(eventGenerated);
222: 8c 2f mov r24, r28
224: 2e d0 rcall .+92 ; 0x282
break;
226: af cf rjmp .-162 ; 0x186
case (EV_SERIAL_DATA_PENDING_TX):
UIMgr_dispatchEvent(eventGenerated);
228: 8c 2f mov r24, r28
22a: 53 d2 rcall .+1190 ; 0x6d2
break;
22c: ac cf rjmp .-168 ; 0x186
0000022e <Exec_readEventFifo>:
default:
break;
}
}
/* toggle the debug line */
}
}
/***********************************************************
Function Name: Exec_readEventFifo
Function Description: This function is responsible for
reading a single event out of the event fifo.
Inputs: none
Outputs: unsigned char-the data read
***********************************************************/
static unsigned char Exec_readEventFifo(void)
{
unsigned char dataByte, tmpTail;
DISABLE_INTS();
22e: f8 94 cli
/* just return the current tail from the tx fifo */
dataByte = Exec_eventFifo[Exec_eventFifoTail];
230: 20 91 71 00 lds r18, 0x0071
234: 8c e6 ldi r24, 0x6C ; 108
236: 92 e0 ldi r25, 0x02 ; 2
238: fc 01 movw r30, r24
23a: e2 0f add r30, r18
23c: f1 1d adc r31, r1
23e: 90 81 ld r25, Z
tmpTail = (Exec_eventFifoTail+1) & (EXEC_EVENT_FIFO_MASK);
240: 82 2f mov r24, r18
242: 8f 5f subi r24, 0xFF ; 255
244: 87 70 andi r24, 0x07 ; 7
Exec_eventFifoTail = tmpTail;
246: 80 93 71 00 sts 0x0071, r24
ENABLE_INTS();
24a: 78 94 sei
return(dataByte);
24c: 89 2f mov r24, r25
24e: 99 27 eor r25, r25
}
250: 08 95 ret
00000252 <Exec_writeEventFifo>:
/***********************************************************
Function Name: Exec_writeEventFifo
Function Description: This function is responsible for
writing a single event to the event fifo and
updating the appropriate pointers.
Inputs: data - the byte to write to the Fifo
Outputs: none
***********************************************************/
void Exec_writeEventFifo(unsigned char event)
{
252: 38 2f mov r19, r24
unsigned char tmpHead;
DISABLE_INTS();
254: f8 94 cli
Exec_eventFifo[Exec_eventFifoHead] = event;
256: 20 91 70 00 lds r18, 0x0070
25a: 8c e6 ldi r24, 0x6C ; 108
25c: 92 e0 ldi r25, 0x02 ; 2
25e: fc 01 movw r30, r24
260: e2 0f add r30, r18
262: f1 1d adc r31, r1
264: 30 83 st Z, r19
/* now move the head up */
tmpHead = (Exec_eventFifoHead + 1) & (EXEC_EVENT_FIFO_MASK);
266: 82 2f mov r24, r18
268: 8f 5f subi r24, 0xFF ; 255
26a: 87 70 andi r24, 0x07 ; 7
Exec_eventFifoHead = tmpHead;
26c: 80 93 70 00 sts 0x0070, r24
ENABLE_INTS();
270: 78 94 sei
}
272: 08 95 ret
00000274 <FrameMgr_init>:
Outputs: none
***********************************************************/
void FrameMgr_init(void)
{
memset(trackedObjectTable,0x00,sizeof(trackedObjectTable));
274: 80 e4 ldi r24, 0x40 ; 64
276: e8 e7 ldi r30, 0x78 ; 120
278: f0 e0 ldi r31, 0x00 ; 0
27a: 11 92 st Z+, r1
27c: 8a 95 dec r24
27e: e9 f7 brne .-6 ; 0x27a
}
280: 08 95 ret
00000282 <FrameMgr_dispatchEvent>:
/***********************************************************
Function Name: FrameMgr_dispatchEvent
Function Description: This function is responsible for
taking an incoming event and performing the needed
actions with it as pertains to the FrameMgr.
Inputs: event - the generated event
Outputs: none
***********************************************************/
void FrameMgr_dispatchEvent(unsigned char event)
{
switch(event)
282: 99 27 eor r25, r25
284: 84 30 cpi r24, 0x04 ; 4
286: 91 05 cpc r25, r1
288: 51 f1 breq .+84 ; 0x2de
28a: 85 30 cpi r24, 0x05 ; 5
28c: 91 05 cpc r25, r1
28e: 34 f4 brge .+12 ; 0x29c
290: 81 30 cpi r24, 0x01 ; 1
292: 91 05 cpc r25, r1
294: 31 f1 breq .+76 ; 0x2e2
296: 02 97 sbiw r24, 0x02 ; 2
298: 71 f0 breq .+28 ; 0x2b6
{
case EV_DUMP_FRAME:
/* try re-initializing the camera before we start dumping */
CamConfig_setCamReg(0x11,0x01); /* reduce the frame rate for dumping*/
CamConfig_sendFifoCmds();
Utility_delay(1000); /* allow the new frame rate to settle */
lineCount = 0;
currentState = ST_FrameMgr_DumpingFrame;
//CamIntAsm_waitForNewDumpFrame(currentLineBuffer,previousLineBuffer);
FrameMgr_acquireLine();
break;
case EV_ENABLE_TRACKING:
currentState = ST_FrameMgr_TrackingFrame;
FrameMgr_acquireFrame();
break;
case EV_ACQUIRE_FRAME_COMPLETE:
FrameMgr_processFrame();
break;
case EV_PROCESS_FRAME_COMPLETE:
FrameMgr_acquireFrame();
break;
case EV_SERIAL_DATA_RECEIVED:
if (currentState != ST_FrameMgr_idle)
{
/* we need to go back to processing line data, since
serial data reception interrupted us....just trash the
frame and act like the frame has been processed, which
will kick off the system to wait for the next line */
PUBLISH_EVENT(EV_PROCESS_FRAME_COMPLETE);
}
break;
case EV_DISABLE_TRACKING:
/* tracking needs to be turned off */
currentState = ST_FrameMgr_idle;
break;
}
}
29a: 08 95 ret
29c: 80 38 cpi r24, 0x80 ; 128
29e: 91 05 cpc r25, r1
2a0: c1 f0 breq .+48 ; 0x2d2
2a2: 81 38 cpi r24, 0x81 ; 129
2a4: 91 05 cpc r25, r1
2a6: 1c f4 brge .+6 ; 0x2ae
2a8: 80 97 sbiw r24, 0x20 ; 32
2aa: b9 f0 breq .+46 ; 0x2da
2ac: 08 95 ret
2ae: 81 38 cpi r24, 0x81 ; 129
2b0: 91 05 cpc r25, r1
2b2: f1 f0 breq .+60 ; 0x2f0
2b4: 08 95 ret
2b6: 61 e0 ldi r22, 0x01 ; 1
2b8: 81 e1 ldi r24, 0x11 ; 17
2ba: 66 d5 rcall .+2764 ; 0xd88
2bc: 6a d5 rcall .+2772 ; 0xd92
2be: 88 ee ldi r24, 0xE8 ; 232
2c0: 93 e0 ldi r25, 0x03 ; 3
2c2: c1 d5 rcall .+2946 ; 0xe46
2c4: 10 92 73 00 sts 0x0073, r1
2c8: 82 e0 ldi r24, 0x02 ; 2
2ca: 80 93 74 00 sts 0x0074, r24
2ce: 2f d0 rcall .+94 ; 0x32e
2d0: 08 95 ret
2d2: 81 e0 ldi r24, 0x01 ; 1
2d4: 80 93 74 00 sts 0x0074, r24
2d8: 02 c0 rjmp .+4 ; 0x2de
2da: 18 d1 rcall .+560 ; 0x50c
2dc: 08 95 ret
2de: 0c d0 rcall .+24 ; 0x2f8
2e0: 08 95 ret
2e2: 80 91 74 00 lds r24, 0x0074
2e6: 88 23 and r24, r24
2e8: 29 f0 breq .+10 ; 0x2f4
2ea: 84 e0 ldi r24, 0x04 ; 4
2ec: b2 df rcall .-156 ; 0x252
2ee: 08 95 ret
2f0: 10 92 74 00 sts 0x0074, r1
2f4: 08 95 ret
2f6: 08 95 ret
000002f8 <FrameMgr_acquireFrame>:
/***********************************************************
Function Name: FrameMgr_acquireFrame
Function Description: This function is responsible for
beginning of the acquisition of a new frame of data
from the camera interface. The acquisition of this line
depends on the current state of the FrameMgr.
Inputs: none
Outputs: none
***********************************************************/
void FrameMgr_acquireFrame(void)
{
if (currentState == ST_FrameMgr_TrackingFrame)
2f8: 80 91 74 00 lds r24, 0x0074
2fc: 81 30 cpi r24, 0x01 ; 1
2fe: a9 f4 brne .+42 ; 0x32a
{
trackedLineCount = 0;
300: 10 92 77 00 sts 0x0077, r1
numPrevTrackedObjects = numCurrTrackedObjects;
304: 80 91 75 00 lds r24, 0x0075
308: 80 93 76 00 sts 0x0076, r24
numCurrTrackedObjects = 0;
30c: 10 92 75 00 sts 0x0075, r1
/* clear out the tracking table, and wait for the new frame
to start */
memset(trackedObjectTable,0x00,sizeof(trackedObjectTable));
310: 80 e4 ldi r24, 0x40 ; 64
312: e8 e7 ldi r30, 0x78 ; 120
314: f0 e0 ldi r31, 0x00 ; 0
316: 11 92 st Z+, r1
318: 8a 95 dec r24
31a: e9 f7 brne .-6 ; 0x316
//CamIntAsm_waitForNewTrackingFrame(currentLineBuffer,colorMap);
WAIT_FOR_VSYNC_HIGH();
31c: 82 9b sbis 0x10, 2 ; 16
31e: fe cf rjmp .-4 ; 0x31c
CamIntAsm_acquireTrackingLine(currentLineBuffer,colorMap);
320: 60 e0 ldi r22, 0x00 ; 0
322: 73 e0 ldi r23, 0x03 ; 3
324: 8c eb ldi r24, 0xBC ; 188
326: 91 e0 ldi r25, 0x01 ; 1
328: f0 d5 rcall .+3040 ; 0xf0a
}
}
32a: 08 95 ret
32c: 08 95 ret
0000032e <FrameMgr_acquireLine>:
/***********************************************************
Function Name: FrameMgr_acquireLine
Function Description: This function is responsible for
acquiring a line of data from the camera interface.
The acquisition of this line depends on the current
state of the FrameMgr.
Inputs: none
Outputs: none
***********************************************************/
void FrameMgr_acquireLine(void)
{
unsigned char tmpLineCount;
/* clearing out the buffers takes too long...we should
just overwrite the data here without a problem when
we start acquiring...at no point do we check for
a 0x00 value in the current or previous lineBuffers,
so it was a bit excessive :-) */
/* check which state we are in and proceed as needed */
if (currentState == ST_FrameMgr_DumpingFrame)
32e: 80 91 74 00 lds r24, 0x0074
332: 82 30 cpi r24, 0x02 ; 2
334: 11 f5 brne .+68 ; 0x37a
{
tmpLineCount = lineCount*2;
336: 80 91 73 00 lds r24, 0x0073
33a: 88 0f add r24, r24
/* clearing out the line data in dump mode is ok, and actually
is needed, since it is possible for the first dump line in
a frame to come back with the last line captured of the
last capture session...*/
memset(currentLineBuffer,0x00,LENGTH_OF_LINE_BUFFER);
33c: 90 eb ldi r25, 0xB0 ; 176
33e: ec eb ldi r30, 0xBC ; 188
340: f1 e0 ldi r31, 0x01 ; 1
342: 11 92 st Z+, r1
344: 9a 95 dec r25
346: e9 f7 brne .-6 ; 0x342
memset(previousLineBuffer,0x00,LENGTH_OF_LINE_BUFFER);
348: 90 eb ldi r25, 0xB0 ; 176
34a: ec e0 ldi r30, 0x0C ; 12
34c: f1 e0 ldi r31, 0x01 ; 1
34e: 11 92 st Z+, r1
350: 9a 95 dec r25
352: e9 f7 brne .-6 ; 0x34e
/* wait for another VSYNC so we know which frame to use
to start looking for a line to receive */
WAIT_FOR_VSYNC_HIGH();
354: 82 9b sbis 0x10, 2 ; 16
356: fe cf rjmp .-4 ; 0x354
WAIT_FOR_VSYNC_LOW();
358: 82 99 sbic 0x10, 2 ; 16
35a: fe cf rjmp .-4 ; 0x358
/* look at lineCount to determine how many HREFs we should
wait before we start sampling */
while(tmpLineCount != 0)
35c: 88 23 and r24, r24
35e: 39 f0 breq .+14 ; 0x36e
{
WAIT_FOR_HREF_HIGH();
360: 84 9b sbis 0x10, 4 ; 16
362: fe cf rjmp .-4 ; 0x360
tmpLineCount--;
364: 81 50 subi r24, 0x01 ; 1
WAIT_FOR_HREF_LOW();
366: 84 99 sbic 0x10, 4 ; 16
368: fe cf rjmp .-4 ; 0x366
36a: 88 23 and r24, r24
36c: c9 f7 brne .-14 ; 0x360
}
/* we should now be ready to sample our line...*/
CamIntAsm_acquireDumpLine(currentLineBuffer,previousLineBuffer);
36e: 6c e0 ldi r22, 0x0C ; 12
370: 71 e0 ldi r23, 0x01 ; 1
372: 8c eb ldi r24, 0xBC ; 188
374: 91 e0 ldi r25, 0x01 ; 1
376: 10 d6 rcall .+3104 ; 0xf98
}
else if (currentState == ST_FrameMgr_TrackingFrame)
{
WAIT_FOR_HREF_LOW();
CamIntAsm_acquireTrackingLine(currentLineBuffer,colorMap);
}
}
378: 08 95 ret
37a: 80 91 74 00 lds r24, 0x0074
37e: 81 30 cpi r24, 0x01 ; 1
380: 39 f4 brne .+14 ; 0x390
382: 84 99 sbic 0x10, 4 ; 16
384: fe cf rjmp .-4 ; 0x382
386: 60 e0 ldi r22, 0x00 ; 0
388: 73 e0 ldi r23, 0x03 ; 3
38a: 8c eb ldi r24, 0xBC ; 188
38c: 91 e0 ldi r25, 0x01 ; 1
38e: bd d5 rcall .+2938 ; 0xf0a
390: 08 95 ret
00000392 <FrameMgr_processLine>:
/***********************************************************
Function Name: FrameMgr_processLine
Function Description: This function is responsible for
parsing the received image line and performing either
connected region mapping (if in the Tracking state) or
sending out the raw sampled data (if in the Dumping
state).
Inputs: none
Outputs: none
***********************************************************/
void FrameMgr_processLine(void)
{
392: df 92 push r13
394: ef 92 push r14
396: ff 92 push r15
398: 0f 93 push r16
39a: 1f 93 push r17
39c: cf 93 push r28
39e: df 93 push r29
3a0: cd b7 in r28, 0x3d ; 61
3a2: de b7 in r29, 0x3e ; 62
3a4: 21 97 sbiw r28, 0x01 ; 1
3a6: 0f b6 in r0, 0x3f ; 63
3a8: f8 94 cli
3aa: de bf out 0x3e, r29 ; 62
3ac: 0f be out 0x3f, r0 ; 63
3ae: cd bf out 0x3d, r28 ; 61
unsigned char i;
volatile unsigned char dataToSend;
unsigned char *pTrackedObjectData = (unsigned char *)pCurrentTrackedObjectTable;
3b0: 00 91 60 00 lds r16, 0x0060
3b4: 10 91 61 00 lds r17, 0x0061
#ifdef DEBUG_TRACKED_LINE
unsigned char *pSendData;
unsigned char asciiBuffer[5];
unsigned char pixelCount = 0;
#endif
if (currentState == ST_FrameMgr_DumpingFrame)
3b8: 80 91 74 00 lds r24, 0x0074
3bc: 82 30 cpi r24, 0x02 ; 2
3be: 09 f0 breq .+2 ; 0x3c2
3c0: 54 c0 rjmp .+168 ; 0x46a
{
/* we want to sit in a tight loop and send the acquired data
sitting in current and previous line buffers out the serial
port...it is sent out the serial port immediately instead
of going into the UIMgr tx fifo because we can't do anything
until its sent out anyway...may as well just get it out now */
/* currentLineBuffer is getting "g" previousLineBuffer is getting "b-r" */
UartInt_txByte(0x0B); /* send the header byte */
3c2: 8b e0 ldi r24, 0x0B ; 11
3c4: cd d3 rcall .+1946 ; 0xb60
UartInt_txByte(lineCount); /* send the line count */
3c6: 80 91 73 00 lds r24, 0x0073
3ca: ca d3 rcall .+1940 ; 0xb60
for (i=0; i<NUM_PIXELS_IN_A_DUMP_LINE; i+=2)
3cc: dd 24 eor r13, r13
{
/* when a dump line is sampled, the upper byte can potentially
have garbage in it...we don't have time to mask it off as we're
sampling, so it is done here before we send it out...we also
combine the samples together so we really are sending up a
sample for line N as well as line N+1 */
dataToSend = currentLineBuffer[i];
3ce: 2d 2d mov r18, r13
3d0: 33 27 eor r19, r19
3d2: 0f 2e mov r0, r31
3d4: fc eb ldi r31, 0xBC ; 188
3d6: ef 2e mov r14, r31
3d8: f1 e0 ldi r31, 0x01 ; 1
3da: ff 2e mov r15, r31
3dc: f0 2d mov r31, r0
3de: e2 0e add r14, r18
3e0: f3 1e adc r15, r19
3e2: f7 01 movw r30, r14
3e4: 80 81 ld r24, Z
3e6: 89 83 std Y+1, r24 ; 0x01
dataToSend &= 0x0F;
3e8: 89 81 ldd r24, Y+1 ; 0x01
3ea: 8f 70 andi r24, 0x0F ; 15
3ec: 89 83 std Y+1, r24 ; 0x01
dataToSend <<= 4;
3ee: 89 81 ldd r24, Y+1 ; 0x01
3f0: 82 95 swap r24
3f2: 80 7f andi r24, 0xF0 ; 240
3f4: 89 83 std Y+1, r24 ; 0x01
dataToSend |= (previousLineBuffer[i] & 0x0F);
3f6: 89 01 movw r16, r18
3f8: 04 5f subi r16, 0xF4 ; 244
3fa: 1e 4f sbci r17, 0xFE ; 254
3fc: f8 01 movw r30, r16
3fe: 80 81 ld r24, Z
400: 98 2f mov r25, r24
402: 9f 70 andi r25, 0x0F ; 15
404: 89 81 ldd r24, Y+1 ; 0x01
406: 89 2b or r24, r25
408: 89 83 std Y+1, r24 ; 0x01
/* dataToSend should be packed now */
UartInt_txByte(dataToSend);
40a: 89 81 ldd r24, Y+1 ; 0x01
40c: a9 d3 rcall .+1874 ; 0xb60
/* flip the colors around since we are doing all G on Y and BR on UV */
dataToSend = previousLineBuffer[i+1];
40e: f8 01 movw r30, r16
410: 81 81 ldd r24, Z+1 ; 0x01
412: 89 83 std Y+1, r24 ; 0x01
dataToSend &= 0x0F;
414: 89 81 ldd r24, Y+1 ; 0x01
416: 8f 70 andi r24, 0x0F ; 15
418: 89 83 std Y+1, r24 ; 0x01
dataToSend <<= 4;
41a: 89 81 ldd r24, Y+1 ; 0x01
41c: 82 95 swap r24
41e: 80 7f andi r24, 0xF0 ; 240
420: 89 83 std Y+1, r24 ; 0x01
dataToSend |= (currentLineBuffer[i+1] & 0x0F);
422: f7 01 movw r30, r14
424: 81 81 ldd r24, Z+1 ; 0x01
426: 98 2f mov r25, r24
428: 9f 70 andi r25, 0x0F ; 15
42a: 89 81 ldd r24, Y+1 ; 0x01
42c: 89 2b or r24, r25
42e: 89 83 std Y+1, r24 ; 0x01
/* dataToSend should be packed now */
UartInt_txByte(dataToSend);
430: 89 81 ldd r24, Y+1 ; 0x01
432: 96 d3 rcall .+1836 ; 0xb60
434: f2 e0 ldi r31, 0x02 ; 2
436: df 0e add r13, r31
438: 4f ea ldi r20, 0xAF ; 175
43a: 4d 15 cp r20, r13
43c: 40 f6 brcc .-112 ; 0x3ce
}
UartInt_txByte(0x0F); /* send line end */
43e: 8f e0 ldi r24, 0x0F ; 15
440: 8f d3 rcall .+1822 ; 0xb60
/* once all the data is sent, increment out line count by 2 since
we really get 2 lines worth of pixels on each pass */
/* Update...increment only by 1, but only send 72 double-lines */
lineCount++;
442: 80 91 73 00 lds r24, 0x0073
446: 8f 5f subi r24, 0xFF ; 255
448: 80 93 73 00 sts 0x0073, r24
/* check to see if we have retrieved all of the needed lines */
if (lineCount >= 72) /* half 144, since we send two lines at a time */
44c: 88 34 cpi r24, 0x48 ; 72
44e: 08 f4 brcc .+2 ; 0x452
450: 4a c0 rjmp .+148 ; 0x4e6
{
/* we're done, so send the dump complete?...nope, just change
states and we should be fine */
lineCount = 0;
452: 10 92 73 00 sts 0x0073, r1
currentState = ST_FrameMgr_idle;
456: 10 92 74 00 sts 0x0074, r1
/* disable the PCLK counting overflow interrupt */
TIMSK &= DISABLE_PCLK_TIMER1_OVERFLOW_BITMASK;
45a: 89 b7 in r24, 0x39 ; 57
45c: 8b 7f andi r24, 0xFB ; 251
45e: 89 bf out 0x39, r24 ; 57
CamConfig_setCamReg(0x11,0x00); /* reset the frame rate to normal*/
460: 60 e0 ldi r22, 0x00 ; 0
462: 81 e1 ldi r24, 0x11 ; 17
464: 91 d4 rcall .+2338 ; 0xd88
CamConfig_sendFifoCmds();
466: 95 d4 rcall .+2346 ; 0xd92
468: 43 c0 rjmp .+134 ; 0x4f0
}
else
{
/* we have more lines to acquire in this frame, so keep on truckin...*/
PUBLISH_FAST_EVENT(FEV_PROCESS_LINE_COMPLETE);
}
}
else if (currentState == ST_FrameMgr_TrackingFrame)
46a: 80 91 74 00 lds r24, 0x0074
46e: 81 30 cpi r24, 0x01 ; 1
470: 09 f0 breq .+2 ; 0x474
472: 3e c0 rjmp .+124 ; 0x4f0
{
#ifdef DEBUG_TRACKED_LINE
/* send the received line over serial...this should only send
until a pixelCount == 176 */
pSendData = currentLineBuffer;
itoa(trackedLineCount,asciiBuffer,10);
UIMgr_txBuffer(asciiBuffer,3);
UIMgr_txBuffer(" ",1);
while(pixelCount < ACTUAL_NUM_PIXELS_IN_A_LINE)
{
memset(asciiBuffer,0x00,5);
itoa(*pSendData++,asciiBuffer,10); /* color is first byte */
UIMgr_txBuffer(asciiBuffer,3); /* 3 ascii bytes for data */
UIMgr_txBuffer(" ",1);
pixelCount += *pSendData; /* run-length is second byte */
memset(asciiBuffer,0x00,5);
itoa(*pSendData++,asciiBuffer,10);
UIMgr_txBuffer(asciiBuffer,3);
UIMgr_txBuffer(" ",1);
}
UIMgr_txBuffer("\n\r",2);
trackedLineCount++;
if (trackedLineCount == 144)
{
UIMgr_txBuffer(" FC \n\r",8);
trackedLineCount = 0;
PUBLISH_EVENT(EV_PROCESS_FRAME_COMPLETE);
}
else
{
PUBLISH_EVENT(EV_PROCESS_LINE_COMPLETE);
}
#else
/* determine if any of the RLE blocks overlap */
FrameMgr_findConnectedness();
474: a1 d0 rcall .+322 ; 0x5b8
/* we also want to remove any objects that are less than
a minimum height...we already removed portions of the
run-length that are less than MIN_PIXEL_WIDTH in the
findConnectedness() routine...doing it here instead of
a function to speed things up...this may end up slowing down the
frame rate slightly, and can be removed if this isn't needed */
/* run this routine once every 8 lines */
if ( (trackedLineCount & RUN_OBJECT_FILTER_MASK) == RUN_OBJECT_FILTER_MASK)
476: 80 91 77 00 lds r24, 0x0077
47a: 99 27 eor r25, r25
47c: 87 70 andi r24, 0x07 ; 7
47e: 90 70 andi r25, 0x00 ; 0
480: 07 97 sbiw r24, 0x07 ; 7
482: 11 f5 brne .+68 ; 0x4c8
{
for (i=0; i<MAX_TRACKED_OBJECTS; i++)
484: dd 24 eor r13, r13
{
if ( *(pTrackedObjectData + VALID_OBJECT_OFFSET) == TRUE)
486: f8 01 movw r30, r16
488: 87 81 ldd r24, Z+7 ; 0x07
48a: 81 30 cpi r24, 0x01 ; 1
48c: b9 f4 brne .+46 ; 0x4bc
{
/* check to see if the object is already in
our past...i.e., its last */
if ( (*(pTrackedObjectData + Y_LOWER_RIGHT_OFFSET) -
48e: 86 81 ldd r24, Z+6 ; 0x06
490: 28 2f mov r18, r24
492: 33 27 eor r19, r19
494: 84 81 ldd r24, Z+4 ; 0x04
496: a9 01 movw r20, r18
498: 48 1b sub r20, r24
49a: 51 09 sbc r21, r1
49c: 43 30 cpi r20, 0x03 ; 3
49e: 51 05 cpc r21, r1
4a0: 6c f4 brge .+26 ; 0x4bc
*(pTrackedObjectData + Y_UPPER_LEFT_OFFSET)) < MIN_OBJECT_TRACKING_HEIGHT)
{
/* the object is less than the minimum height...see if it is adjacent
to the current line we just processed...if so, leave it here...otherwise,
it needs to be invalidated since its too small */
if ( trackedLineCount - *(pTrackedObjectData + Y_LOWER_RIGHT_OFFSET) > 2)
4a2: 80 91 77 00 lds r24, 0x0077
4a6: 99 27 eor r25, r25
4a8: 82 1b sub r24, r18
4aa: 93 0b sbc r25, r19
4ac: 03 97 sbiw r24, 0x03 ; 3
4ae: 34 f0 brlt .+12 ; 0x4bc
{
/* invalidate the object */
*(pTrackedObjectData + VALID_OBJECT_OFFSET) = FALSE;
4b0: 17 82 std Z+7, r1 ; 0x07
numCurrTrackedObjects--;
4b2: 80 91 75 00 lds r24, 0x0075
4b6: 81 50 subi r24, 0x01 ; 1
4b8: 80 93 75 00 sts 0x0075, r24
}
}
}
pTrackedObjectData += SIZE_OF_TRACKED_OBJECT;
4bc: 08 5f subi r16, 0xF8 ; 248
4be: 1f 4f sbci r17, 0xFF ; 255
4c0: d3 94 inc r13
4c2: 57 e0 ldi r21, 0x07 ; 7
4c4: 5d 15 cp r21, r13
4c6: f8 f6 brcc .-66 ; 0x486
}
}
trackedLineCount++;
4c8: 80 91 77 00 lds r24, 0x0077
4cc: 8f 5f subi r24, 0xFF ; 255
4ce: 80 93 77 00 sts 0x0077, r24
if (trackedLineCount == ACTUAL_NUM_LINES_IN_A_FRAME)
4d2: 80 39 cpi r24, 0x90 ; 144
4d4: 41 f4 brne .+16 ; 0x4e6
{
/* an entire frame of tracking data has been acquired, so
publish an event letting the system know this fact */
PUBLISH_EVENT(EV_ACQUIRE_FRAME_COMPLETE);
4d6: 80 e2 ldi r24, 0x20 ; 32
4d8: bc de rcall .-648 ; 0x252
/* disable the PCLK counting overflow interrupt */
TIMSK &= DISABLE_PCLK_TIMER1_OVERFLOW_BITMASK;
4da: 89 b7 in r24, 0x39 ; 57
4dc: 8b 7f andi r24, 0xFB ; 251
4de: 89 bf out 0x39, r24 ; 57
trackedLineCount = 0;
4e0: 10 92 77 00 sts 0x0077, r1
4e4: 05 c0 rjmp .+10 ; 0x4f0
}
else
{
PUBLISH_FAST_EVENT(FEV_PROCESS_LINE_COMPLETE);
4e6: 80 91 72 00 lds r24, 0x0072
4ea: 82 60 ori r24, 0x02 ; 2
4ec: 80 93 72 00 sts 0x0072, r24
}
#endif
}
else
{
/* ...and here? */
}
}
4f0: 21 96 adiw r28, 0x01 ; 1
4f2: 0f b6 in r0, 0x3f ; 63
4f4: f8 94 cli
4f6: de bf out 0x3e, r29 ; 62
4f8: 0f be out 0x3f, r0 ; 63
4fa: cd bf out 0x3d, r28 ; 61
4fc: df 91 pop r29
4fe: cf 91 pop r28
500: 1f 91 pop r17
502: 0f 91 pop r16
504: ff 90 pop r15
506: ef 90 pop r14
508: df 90 pop r13
50a: 08 95 ret
0000050c <FrameMgr_processFrame>:
/***********************************************************
Function Name: FrameMgr_processFrame
Function Description: This function is responsible for
parsing the completed frame and performing all actions
needed at this level.
Inputs: none
Outputs: none
***********************************************************/
void FrameMgr_processFrame(void)
{
50c: df 92 push r13
50e: ef 92 push r14
510: ff 92 push r15
512: 0f 93 push r16
514: 1f 93 push r17
516: cf 93 push r28
518: df 93 push r29
unsigned char i,k,color;
#if DEBUG_FRAME_DATA
unsigned char asciiBuffer[5];
unsigned char j;
#endif
unsigned char *pTableData = (unsigned char *)pCurrentTrackedObjectTable;
unsigned char tmpUpperLeftX,tmpUpperLeftY,tmpLowerRightX,tmpLowerRightY;
#if DEBUG_FRAME_DATA
/* we want to send all of the currently tracked table out
the serial port for debugging */
for (i=0; i<numCurrTrackedObjects; i++)
{
UIMgr_txBuffer("----------\r\n",12);
for (j=0; j<SIZE_OF_TRACKED_OBJECT; j++)
{
memset(asciiBuffer,0x00,5);
itoa(*pTableData++,asciiBuffer,10);
UIMgr_txBuffer(asciiBuffer,3); /* 3 ascii bytes for data
+ 1 space */
UIMgr_txBuffer("\r\n",2);
}
}
/* finally, send a new line */
UIMgr_txBuffer("\r\n",2);
memset(asciiBuffer,0x00,5);
itoa(numCurrTrackedObjects,asciiBuffer,10);
UIMgr_txBuffer(asciiBuffer,3);
UIMgr_txBuffer(" PFC\r\n",5);
#else
/* we only send tracking packets if there are tracked objects */
if (numCurrTrackedObjects > 0)
51a: 80 91 75 00 lds r24, 0x0075
51e: 88 23 and r24, r24
520: 09 f4 brne .+2 ; 0x524
522: 40 c0 rjmp .+128 ; 0x5a4
{
UIMgr_writeTxFifo(0x0A); /* header byte for a tracking packet */
524: 8a e0 ldi r24, 0x0A ; 10
526: 01 d3 rcall .+1538 ; 0xb2a
/* reset the pointer */
pTableData = (unsigned char *)pCurrentTrackedObjectTable;
528: c0 91 60 00 lds r28, 0x0060
52c: d0 91 61 00 lds r29, 0x0061
UIMgr_writeTxFifo(numCurrTrackedObjects); /* num of objects tracked */
530: 80 91 75 00 lds r24, 0x0075
534: fa d2 rcall .+1524 ; 0xb2a
for (i=0; i<MAX_TRACKED_OBJECTS; i++)
536: dd 24 eor r13, r13
{
/* we only want to process objects that have their objectValid flag
set to TRUE */
if ( *(pTableData + VALID_OBJECT_OFFSET) == TRUE)
538: 8f 81 ldd r24, Y+7 ; 0x07
53a: 81 30 cpi r24, 0x01 ; 1
53c: 61 f5 brne .+88 ; 0x596
{
/* the object is valid...convert the color from bit position to value...remember,
each bit in the "color" byte corresponds to a color */
k=0;
53e: 80 e0 ldi r24, 0x00 ; 0
color = *(pTableData + COLOR_OFFSET);
540: 98 81 ld r25, Y
if (color == 128) k=0;
542: 90 38 cpi r25, 0x80 ; 128
544: d9 f0 breq .+54 ; 0x57c
else if (color == 64) k=1;
546: 90 34 cpi r25, 0x40 ; 64
548: 11 f4 brne .+4 ; 0x54e
54a: 81 e0 ldi r24, 0x01 ; 1
54c: 17 c0 rjmp .+46 ; 0x57c
else if (color == 32) k=2;
54e: 90 32 cpi r25, 0x20 ; 32
550: 11 f4 brne .+4 ; 0x556
552: 82 e0 ldi r24, 0x02 ; 2
554: 13 c0 rjmp .+38 ; 0x57c
else if (color == 16) k=3;
556: 90 31 cpi r25, 0x10 ; 16
558: 11 f4 brne .+4 ; 0x55e
55a: 83 e0 ldi r24, 0x03 ; 3
55c: 0f c0 rjmp .+30 ; 0x57c
else if (color == 8) k=4;
55e: 98 30 cpi r25, 0x08 ; 8
560: 11 f4 brne .+4 ; 0x566
562: 84 e0 ldi r24, 0x04 ; 4
564: 0b c0 rjmp .+22 ; 0x57c
else if (color == 4) k=5;
566: 94 30 cpi r25, 0x04 ; 4
568: 11 f4 brne .+4 ; 0x56e
56a: 85 e0 ldi r24, 0x05 ; 5
56c: 07 c0 rjmp .+14 ; 0x57c
else if (color == 2) k=6;
56e: 92 30 cpi r25, 0x02 ; 2
570: 11 f4 brne .+4 ; 0x576
572: 86 e0 ldi r24, 0x06 ; 6
574: 03 c0 rjmp .+6 ; 0x57c
else if (color == 1) k=7;
576: 91 30 cpi r25, 0x01 ; 1
578: 09 f4 brne .+2 ; 0x57c
57a: 87 e0 ldi r24, 0x07 ; 7
tmpUpperLeftX = *(pTableData + X_UPPER_LEFT_OFFSET); /* get the upper left X */
57c: 1b 81 ldd r17, Y+3 ; 0x03
tmpUpperLeftY = *(pTableData + Y_UPPER_LEFT_OFFSET); /* get the upper left Y */
57e: 0c 81 ldd r16, Y+4 ; 0x04
tmpLowerRightX = *(pTableData + X_LOWER_RIGHT_OFFSET); /* get the lower right X */
580: fd 80 ldd r15, Y+5 ; 0x05
tmpLowerRightY = *(pTableData + Y_LOWER_RIGHT_OFFSET); /* get the lower right Y */
582: ee 80 ldd r14, Y+6 ; 0x06
UIMgr_writeTxFifo(k); /* send the color first */
584: d2 d2 rcall .+1444 ; 0xb2a
UIMgr_writeTxFifo(tmpUpperLeftX);
586: 81 2f mov r24, r17
588: d0 d2 rcall .+1440 ; 0xb2a
UIMgr_writeTxFifo(tmpUpperLeftY);
58a: 80 2f mov r24, r16
58c: ce d2 rcall .+1436 ; 0xb2a
UIMgr_writeTxFifo(tmpLowerRightX);
58e: 8f 2d mov r24, r15
590: cc d2 rcall .+1432 ; 0xb2a
UIMgr_writeTxFifo(tmpLowerRightY);
592: 8e 2d mov r24, r14
594: ca d2 rcall .+1428 ; 0xb2a
}
/* move our pointer up to the beginning of the next object */
pTableData += SIZE_OF_TRACKED_OBJECT;
596: 28 96 adiw r28, 0x08 ; 8
598: d3 94 inc r13
59a: 87 e0 ldi r24, 0x07 ; 7
59c: 8d 15 cp r24, r13
59e: 60 f6 brcc .-104 ; 0x538
}
/* all done...send the end of tracking packets char */
UIMgr_writeTxFifo(0xFF);
5a0: 8f ef ldi r24, 0xFF ; 255
5a2: c3 d2 rcall .+1414 ; 0xb2a
}
#endif
/* the tracked object table will be cleared out right before we start
to wait for VSYNC to indicate a new frame...so it doesn't need to be
done now */
/* schedule the next action to acquire a new frame */
PUBLISH_EVENT(EV_PROCESS_FRAME_COMPLETE);
5a4: 84 e0 ldi r24, 0x04 ; 4
5a6: 55 de rcall .-854 ; 0x252
}
5a8: df 91 pop r29
5aa: cf 91 pop r28
5ac: 1f 91 pop r17
5ae: 0f 91 pop r16
5b0: ff 90 pop r15
5b2: ef 90 pop r14
5b4: df 90 pop r13
5b6: 08 95 ret
000005b8 <FrameMgr_findConnectedness>:
/***********************************************************
Function Name: FrameMgr_findConnectedness
Function Description: This function is responsible for
finding the connectedness between two particular run-
length encoded lines of pixel data. It updates the
trackingTable as needed.
Inputs: none
Outputs: none
***********************************************************/
static void FrameMgr_findConnectedness(void)
{
5b8: 1f 93 push r17
5ba: cf 93 push r28
trackedColor_t currColor;
unsigned char *pCurrLineColorInfo = currentLineBuffer;
5bc: ac eb ldi r26, 0xBC ; 188
5be: b1 e0 ldi r27, 0x01 ; 1
unsigned char *pTrackedObjectData;
register unsigned char currPixelRunStart=0;
5c0: 60 e0 ldi r22, 0x00 ; 0
register unsigned char currPixelRunFinish=0;
5c2: c6 2f mov r28, r22
register unsigned char lastLineXStart=0;
register unsigned char lastLineXFinish=0;
register unsigned char runLength=1;
5c4: 71 e0 ldi r23, 0x01 ; 1
unsigned char i;
bool_t colorConnected;
do
{
/* grab both the current color and the number of pixels
in the run...remember, pixels start at 1, not 0! */
colorConnected = FALSE;
5c6: 10 e0 ldi r17, 0x00 ; 0
currColor = *pCurrLineColorInfo++;
5c8: 5d 91 ld r21, X+
currPixelRunStart += runLength;
5ca: c7 0f add r28, r23
runLength = *pCurrLineColorInfo++;
5cc: 7d 91 ld r23, X+
currPixelRunFinish += runLength;
5ce: 67 0f add r22, r23
/* make sure that the run-length is at least as wide as
the minimum horizontal tracking width, and we care about the color */
if ( (currColor != notTracked) && (runLength > MIN_OBJECT_TRACKING_WIDTH) )
5d0: 55 23 and r21, r21
5d2: 09 f4 brne .+2 ; 0x5d6
5d4: 5d c0 rjmp .+186 ; 0x690
5d6: 74 30 cpi r23, 0x04 ; 4
5d8: 08 f4 brcc .+2 ; 0x5dc
5da: 5a c0 rjmp .+180 ; 0x690
{
/* this run contains a color we care about, so
either it will begin a new tracked object, or it
is connected to a currently tracked object...
compare it with each object in the tracking
table...we can't just look at the numTrackedObjects because
it is entirely possible that the first couple of objects could
be invalid...
NOTE: Instead of accessing each element in the trackedObjectTable
through the 'i' index, and then accessing the fields in each structure,
a pointer to each entry is established each time through the loop, followed
by accessing the elements through specified offsets. GCC seems to be
able to optimize this code much better than simply accessing the elements
of each structure in the array the more normal way...*/
pTrackedObjectData = (unsigned char *)pCurrentTrackedObjectTable;
5dc: e0 91 60 00 lds r30, 0x0060
5e0: f0 91 61 00 lds r31, 0x0061
for (i=0; i<MAX_TRACKED_OBJECTS; i++)
5e4: 41 2f mov r20, r17
{
if ( (currColor == *(pTrackedObjectData + COLOR_OFFSET)) &&
5e6: 80 81 ld r24, Z
5e8: 58 17 cp r21, r24
5ea: 51 f5 brne .+84 ; 0x640
5ec: 87 81 ldd r24, Z+7 ; 0x07
5ee: 81 30 cpi r24, 0x01 ; 1
5f0: 39 f5 brne .+78 ; 0x640
5f2: 86 81 ldd r24, Z+6 ; 0x06
5f4: 28 2f mov r18, r24
5f6: 33 27 eor r19, r19
5f8: 80 91 77 00 lds r24, 0x0077
5fc: 99 27 eor r25, r25
5fe: 01 97 sbiw r24, 0x01 ; 1
600: 28 17 cp r18, r24
602: 39 07 cpc r19, r25
604: e9 f4 brne .+58 ; 0x640
(*(pTrackedObjectData + VALID_OBJECT_OFFSET) == TRUE) &&
(*(pTrackedObjectData + Y_LOWER_RIGHT_OFFSET) == trackedLineCount - 1) )
{
/* found a color match and the object is valid...check to see if there is
connectedness */
lastLineXStart = *(pTrackedObjectData + LAST_LINE_X_START_OFFSET);
606: 81 81 ldd r24, Z+1 ; 0x01
lastLineXFinish = *(pTrackedObjectData + LAST_LINE_X_FINISH_OFFSET);
608: 92 81 ldd r25, Z+2 ; 0x02
/* Check for the 5 following types of line connectedness:
---------------------
| |
---------------------
-------------------------
| |
------------------------- */
if ( ( (currPixelRunStart >= lastLineXStart) &&
60a: c8 17 cp r28, r24
60c: 10 f0 brcs .+4 ; 0x612
60e: 9c 17 cp r25, r28
610: 40 f4 brcc .+16 ; 0x622
612: 68 17 cp r22, r24
614: 10 f0 brcs .+4 ; 0x61a
616: 96 17 cp r25, r22
618: 20 f4 brcc .+8 ; 0x622
61a: 8c 17 cp r24, r28
61c: 88 f0 brcs .+34 ; 0x640
61e: 69 17 cp r22, r25
620: 78 f0 brcs .+30 ; 0x640
(currPixelRunStart <= lastLineXFinish) ) ||
/* ---------------------
| |
---------------------
-------------------
| |
-------------------
OR
------------------------------
| |
------------------------------
---------
| |
--------- */
( (currPixelRunFinish >= lastLineXStart) &&
(currPixelRunFinish <= lastLineXFinish) ) ||
/* -------------------------------
| |
-------------------------------
-------------------------------
| |
-------------------------------
OR
-------------
| |
-------------
-------------------------------
| |
------------------------------- */
( (currPixelRunStart <= lastLineXStart) &&
(currPixelRunFinish >= lastLineXFinish) ) )
{
/* THERE IS CONNECTEDNESS...update the lastLineXStart and lastLineXFinish
data pointed to by pTrackedObjectData */
*(pTrackedObjectData + LAST_LINE_X_START_OFFSET) = currPixelRunStart;
622: c1 83 std Z+1, r28 ; 0x01
*(pTrackedObjectData + LAST_LINE_X_FINISH_OFFSET) = currPixelRunFinish;
624: 62 83 std Z+2, r22 ; 0x02
/* check if the bounding box needs to be updated */
if (*(pTrackedObjectData + X_UPPER_LEFT_OFFSET) > currPixelRunStart)
626: 83 81 ldd r24, Z+3 ; 0x03
628: c8 17 cp r28, r24
62a: 08 f4 brcc .+2 ; 0x62e
{
/* need to update the bounding box for the upper left point to
enclose this new left-most point...we never have to update the
upper left Y point, since each scan line we process moves from
top to bottom */
*(pTrackedObjectData + X_UPPER_LEFT_OFFSET) = currPixelRunStart;
62c: c3 83 std Z+3, r28 ; 0x03
}
if ( *(pTrackedObjectData + X_LOWER_RIGHT_OFFSET) < currPixelRunFinish)
62e: 85 81 ldd r24, Z+5 ; 0x05
630: 86 17 cp r24, r22
632: 08 f4 brcc .+2 ; 0x636
{
/* need to update the bounding box for the lower right X point to
enclose this new right-most point */
*(pTrackedObjectData + X_LOWER_RIGHT_OFFSET) = currPixelRunFinish;
634: 65 83 std Z+5, r22 ; 0x05
}
/* the lower right 'y' point always gets updated when connectedness is found */
*(pTrackedObjectData + Y_LOWER_RIGHT_OFFSET) = trackedLineCount;
636: 80 91 77 00 lds r24, 0x0077
63a: 86 83 std Z+6, r24 ; 0x06
/* set a flag indicating that that color run is part of another
object and thus doesn't need to be added as a new entry into the
tracking table */
colorConnected = TRUE;
63c: 11 e0 ldi r17, 0x01 ; 1
break;
63e: 04 c0 rjmp .+8 ; 0x648
}
}
/* go to the next object */
pTrackedObjectData += SIZE_OF_TRACKED_OBJECT;
640: 38 96 adiw r30, 0x08 ; 8
642: 4f 5f subi r20, 0xFF ; 255
644: 48 30 cpi r20, 0x08 ; 8
646: 78 f2 brcs .-98 ; 0x5e6
}
if (colorConnected == FALSE)
648: 11 23 and r17, r17
64a: 11 f5 brne .+68 ; 0x690
{
/* a new entry needs to be made to the tracking table, since we have
a run-length with a color, and it isn't connected to anything...but we
can only do this if there is space left in the trackedObject table */
if (numCurrTrackedObjects < MAX_TRACKED_OBJECTS)
64c: 80 91 75 00 lds r24, 0x0075
650: 88 30 cpi r24, 0x08 ; 8
652: f0 f4 brcc .+60 ; 0x690
{
/* space is available...add the object...but first we need to find an
invalid object in the object tracking table */
pTrackedObjectData = (unsigned char *)pCurrentTrackedObjectTable;
654: e0 91 60 00 lds r30, 0x0060
658: f0 91 61 00 lds r31, 0x0061
for (i=0; i<MAX_TRACKED_OBJECTS; i++)
65c: 41 2f mov r20, r17
{
if ( *(pTrackedObjectData + VALID_OBJECT_OFFSET) == FALSE) break;
65e: 87 81 ldd r24, Z+7 ; 0x07
660: 88 23 and r24, r24
662: 21 f0 breq .+8 ; 0x66c
/* if we haven't broken above, then the object must have been valid...
go ahead and move the pointer to the next object to check it */
pTrackedObjectData += SIZE_OF_TRACKED_OBJECT;
664: 38 96 adiw r30, 0x08 ; 8
666: 4f 5f subi r20, 0xFF ; 255
668: 48 30 cpi r20, 0x08 ; 8
66a: c8 f3 brcs .-14 ; 0x65e
}
/* now that we have a pointer to the tracked object to be updated, update all
the fields */
*(pTrackedObjectData + COLOR_OFFSET) = currColor; /* color */
66c: 50 83 st Z, r21
*(pTrackedObjectData + LAST_LINE_X_START_OFFSET) = currPixelRunStart; /* lastLineXStart */
66e: c1 83 std Z+1, r28 ; 0x01
*(pTrackedObjectData + LAST_LINE_X_FINISH_OFFSET) = currPixelRunFinish; /* lastLineXFinish */
670: 62 83 std Z+2, r22 ; 0x02
*(pTrackedObjectData + X_UPPER_LEFT_OFFSET) = currPixelRunStart; /* x_upperLeft */
672: c3 83 std Z+3, r28 ; 0x03
*(pTrackedObjectData + Y_UPPER_LEFT_OFFSET) = trackedLineCount; /* y_upperLeft */
674: 80 91 77 00 lds r24, 0x0077
678: 84 83 std Z+4, r24 ; 0x04
*(pTrackedObjectData + X_LOWER_RIGHT_OFFSET) = currPixelRunFinish; /* x_lowerRight */
67a: 65 83 std Z+5, r22 ; 0x05
*(pTrackedObjectData + Y_LOWER_RIGHT_OFFSET) = trackedLineCount; /* y_lowerRight */
67c: 80 91 77 00 lds r24, 0x0077
680: 86 83 std Z+6, r24 ; 0x06
*(pTrackedObjectData + VALID_OBJECT_OFFSET) = TRUE; /* objectValid flag */
682: 81 e0 ldi r24, 0x01 ; 1
684: 87 83 std Z+7, r24 ; 0x07
numCurrTrackedObjects++;
686: 80 91 75 00 lds r24, 0x0075
68a: 8f 5f subi r24, 0xFF ; 255
68c: 80 93 75 00 sts 0x0075, r24
}
}
/* move the pointer to the beginning of the next tracked object */
pTrackedObjectData += SIZE_OF_TRACKED_OBJECT;
}
} while(currPixelRunFinish < ACTUAL_NUM_PIXELS_IN_A_LINE);
690: 60 3b cpi r22, 0xB0 ; 176
692: 08 f4 brcc .+2 ; 0x696
694: 98 cf rjmp .-208 ; 0x5c6
}
696: cf 91 pop r28
698: 1f 91 pop r17
69a: 08 95 ret
0000069c <UIMgr_init>:
Outputs: none
***********************************************************/
void UIMgr_init(void)
{
memset(asciiTokenBuffer,0x00,MAX_TOKEN_LENGTH+1);
69c: 10 92 bf 00 sts 0x00BF, r1
6a0: 10 92 c0 00 sts 0x00C0, r1
6a4: 10 92 c1 00 sts 0x00C1, r1
6a8: 10 92 c2 00 sts 0x00C2, r1
memset(tokenBuffer,0x00,MAX_TOKEN_COUNT);
6ac: 80 e4 ldi r24, 0x40 ; 64
6ae: e3 ec ldi r30, 0xC3 ; 195
6b0: f0 e0 ldi r31, 0x00 ; 0
6b2: 11 92 st Z+, r1
6b4: 8a 95 dec r24
6b6: e9 f7 brne .-6 ; 0x6b2
memset(UIMgr_txFifo,0x00,UI_MGR_TX_FIFO_SIZE);
6b8: 80 e4 ldi r24, 0x40 ; 64
6ba: e4 e9 ldi r30, 0x94 ; 148
6bc: f2 e0 ldi r31, 0x02 ; 2
6be: 11 92 st Z+, r1
6c0: 8a 95 dec r24
6c2: e9 f7 brne .-6 ; 0x6be
memset(UIMgr_rxFifo,0x00,UI_MGR_RX_FIFO_SIZE);
6c4: 80 e2 ldi r24, 0x20 ; 32
6c6: e4 e7 ldi r30, 0x74 ; 116
6c8: f2 e0 ldi r31, 0x02 ; 2
6ca: 11 92 st Z+, r1
6cc: 8a 95 dec r24
6ce: e9 f7 brne .-6 ; 0x6ca
}
6d0: 08 95 ret
000006d2 <UIMgr_dispatchEvent>:
/***********************************************************
Function Name: UIMgr_dispatchEvent
Function Description: This function is responsible for
processing events that pertain to the UIMgr.
Inputs: event - the generated event
Outputs: none
***********************************************************/
void UIMgr_dispatchEvent(unsigned char event)
{
switch(event)
6d2: 99 27 eor r25, r25
6d4: 80 31 cpi r24, 0x10 ; 16
6d6: 91 05 cpc r25, r1
6d8: 51 f0 breq .+20 ; 0x6ee
6da: 81 31 cpi r24, 0x11 ; 17
6dc: 91 05 cpc r25, r1
6de: 1c f4 brge .+6 ; 0x6e6
6e0: 01 97 sbiw r24, 0x01 ; 1
6e2: 39 f0 breq .+14 ; 0x6f2
{
case EV_ACQUIRE_LINE_COMPLETE:
UIMgr_transmitPendingData();
break;
case EV_SERIAL_DATA_RECEIVED:
UIMgr_processReceivedData();
break;
case EV_SERIAL_DATA_PENDING_TX:
UIMgr_flushTxBuffer();
break;
}
}
6e4: 08 95 ret
6e6: 80 39 cpi r24, 0x90 ; 144
6e8: 91 05 cpc r25, r1
6ea: 29 f0 breq .+10 ; 0x6f6
6ec: 08 95 ret
6ee: 06 d0 rcall .+12 ; 0x6fc
6f0: 08 95 ret
6f2: 0e d0 rcall .+28 ; 0x710
6f4: 08 95 ret
6f6: e6 d1 rcall .+972 ; 0xac4
6f8: 08 95 ret
6fa: 08 95 ret
000006fc <UIMgr_transmitPendingData>:
/***********************************************************
Function Name: UIMgr_transmitPendingData
Function Description: This function is responsible for
transmitting a single byte of data if data is waiting
to be sent. Otherwise, if nothing is waiting, the
function just returns.
Inputs: none
Outputs: none
***********************************************************/
void UIMgr_transmitPendingData(void)
{
if (IS_DATA_IN_TX_FIFO() == TRUE)
6fc: 90 91 ba 00 lds r25, 0x00BA
700: 80 91 bb 00 lds r24, 0x00BB
704: 98 17 cp r25, r24
706: 11 f0 breq .+4 ; 0x70c
{
/* data is waiting...send a single byte */
UartInt_txByte( UIMgr_readTxFifo() );
708: fe d1 rcall .+1020 ; 0xb06
70a: 2a d2 rcall .+1108 ; 0xb60
}
}
70c: 08 95 ret
70e: 08 95 ret
00000710 <UIMgr_processReceivedData>:
/***********************************************************
Function Name: UIMgr_processReceivedData
Function Description: This function is responsible for
parsing any serial data waiting in the rx fifo
Inputs: none
Outputs: none
***********************************************************/
void UIMgr_processReceivedData(void)
{
710: cf 93 push r28
unsigned char tmpData = 0;
/* still need to add a mechanism to handle token counts
that are excessive!!! FIX ME!!! */
while(IS_DATA_IN_RX_FIFO() == TRUE)
712: 90 91 b8 00 lds r25, 0x00B8
716: 80 91 b9 00 lds r24, 0x00B9
71a: 98 17 cp r25, r24
71c: 09 f4 brne .+2 ; 0x720
71e: 6f c0 rjmp .+222 ; 0x7fe
720: c9 e0 ldi r28, 0x09 ; 9
{
tmpData = UIMgr_readRxFifo();
722: df d1 rcall .+958 ; 0xae2
724: 38 2f mov r19, r24
if (tmpData == '\r')
726: 8d 30 cpi r24, 0x0D ; 13
728: 29 f5 brne .+74 ; 0x774
{
/* we have reached a token separator */
if (tokenCount == 0)
72a: 80 91 be 00 lds r24, 0x00BE
72e: 88 23 and r24, r24
730: 11 f4 brne .+4 ; 0x736
{
/* convert the command */
UIMgr_convertTokenToCmd();
732: 2c d1 rcall .+600 ; 0x98c
734: 06 c0 rjmp .+12 ; 0x742
}
else
{
/* convert a value */
UIMgr_convertTokenToValue();
736: 02 d1 rcall .+516 ; 0x93c
tokenCount++;
738: 80 91 be 00 lds r24, 0x00BE
73c: 8f 5f subi r24, 0xFF ; 255
73e: 80 93 be 00 sts 0x00BE, r24
}
/* either way, it is time to try to process the received
token list since we have reached the end of the cmd. */
Utility_delay(100);
742: 84 e6 ldi r24, 0x64 ; 100
744: 90 e0 ldi r25, 0x00 ; 0
746: 7f d3 rcall .+1790 ; 0xe46
if (receivedCmd == invalidCmd ||
748: 80 91 62 00 lds r24, 0x0062
74c: 88 50 subi r24, 0x08 ; 8
74e: 82 30 cpi r24, 0x02 ; 2
750: 20 f4 brcc .+8 ; 0x75a
receivedCmd == noCmd )
{
UIMgr_sendNck();
752: 84 d1 rcall .+776 ; 0xa5c
PUBLISH_EVENT(EV_SERIAL_DATA_PENDING_TX);
754: 80 e9 ldi r24, 0x90 ; 144
756: 7d dd rcall .-1286 ; 0x252
758: 04 c0 rjmp .+8 ; 0x762
}
else
{
UIMgr_sendAck();
75a: 77 d1 rcall .+750 ; 0xa4a
/* publish the serial data pending event, so it
will push the ACK out before we execute the cmd */
PUBLISH_EVENT(EV_SERIAL_DATA_PENDING_TX);
75c: 80 e9 ldi r24, 0x90 ; 144
75e: 79 dd rcall .-1294 ; 0x252
UIMgr_executeCmd();
760: 51 d0 rcall .+162 ; 0x804
}
/* reset any necessary data */
tokenCount = 0;
762: 10 92 be 00 sts 0x00BE, r1
memset(tokenBuffer,0x00,MAX_TOKEN_COUNT);
766: 80 e4 ldi r24, 0x40 ; 64
768: e3 ec ldi r30, 0xC3 ; 195
76a: f0 e0 ldi r31, 0x00 ; 0
76c: 11 92 st Z+, r1
76e: 8a 95 dec r24
770: e9 f7 brne .-6 ; 0x76c
772: 3e c0 rjmp .+124 ; 0x7f0
}
else if (tmpData == ' ') /* space char */
774: 80 32 cpi r24, 0x20 ; 32
776: d9 f4 brne .+54 ; 0x7ae
{
/* the end of a token has been reached */
if (tokenCount == 0)
778: 80 91 be 00 lds r24, 0x00BE
77c: 88 23 and r24, r24
77e: 11 f4 brne .+4 ; 0x784
{
UIMgr_convertTokenToCmd();
780: 05 d1 rcall .+522 ; 0x98c
tokenCount++; /* check this...why is this being incremented here??? This
782: 0f c0 rjmp .+30 ; 0x7a2
means we have received a token, with tokenCount == 0, which means it is a
command...why is this contributing to tokenCount?
This might cause the set color map command to include too much data, since
it sets the color map based on tokenCount...CHECK*/
}
else
{
/* check to see if this token is going to push
us over the limit...if so, abort the transaction */
if (tokenCount+1 >= MAX_TOKEN_COUNT)
784: 80 91 be 00 lds r24, 0x00BE
788: 99 27 eor r25, r25
78a: 01 96 adiw r24, 0x01 ; 1
78c: 80 34 cpi r24, 0x40 ; 64
78e: 91 05 cpc r25, r1
790: 3c f0 brlt .+14 ; 0x7a0
{
/* we received too many tokens, and
need to NCK this request, since its too
large...reset everything...*/
charCount=0;
792: 10 92 bc 00 sts 0x00BC, r1
charIndex=0;
796: 10 92 bd 00 sts 0x00BD, r1
tokenCount=0;
79a: 10 92 be 00 sts 0x00BE, r1
receivedCmd = invalidCmd;
79e: 26 c0 rjmp .+76 ; 0x7ec
}
else
{
/* tokenCount is still in range...*/
UIMgr_convertTokenToValue();
7a0: cd d0 rcall .+410 ; 0x93c
tokenCount++;
7a2: 80 91 be 00 lds r24, 0x00BE
7a6: 8f 5f subi r24, 0xFF ; 255
7a8: 80 93 be 00 sts 0x00BE, r24
7ac: 21 c0 rjmp .+66 ; 0x7f0
}
}
}
else if ( (tmpData >= 'A' && tmpData <= 'Z') ||
7ae: 81 54 subi r24, 0x41 ; 65
7b0: 8a 31 cpi r24, 0x1A ; 26
7b2: 18 f0 brcs .+6 ; 0x7ba
7b4: 8f 5e subi r24, 0xEF ; 239
7b6: 8a 30 cpi r24, 0x0A ; 10
7b8: c8 f4 brcc .+50 ; 0x7ec
(tmpData >= '0' && tmpData <= '9') )
{
/* a valid range of token was received */
asciiTokenBuffer[charIndex] = tmpData;
7ba: 20 91 bd 00 lds r18, 0x00BD
7be: 82 2f mov r24, r18
7c0: 99 27 eor r25, r25
7c2: fc 01 movw r30, r24
7c4: e1 54 subi r30, 0x41 ; 65
7c6: ff 4f sbci r31, 0xFF ; 255
7c8: 30 83 st Z, r19
charCount++;
7ca: 80 91 bc 00 lds r24, 0x00BC
7ce: 98 2f mov r25, r24
7d0: 9f 5f subi r25, 0xFF ; 255
7d2: 90 93 bc 00 sts 0x00BC, r25
charIndex++;
7d6: 82 2f mov r24, r18
7d8: 8f 5f subi r24, 0xFF ; 255
7da: 80 93 bd 00 sts 0x00BD, r24
if (charCount > MAX_TOKEN_LENGTH)
7de: 94 30 cpi r25, 0x04 ; 4
7e0: 38 f0 brcs .+14 ; 0x7f0
{
/* we have received a token that cannot be handled...
set the received cmd to an invalid cmd, and wait
for the \r to process it */
receivedCmd = invalidCmd;
7e2: c0 93 62 00 sts 0x0062, r28
charIndex = 0; /* ...so we won't overwrite memory */
7e6: 10 92 bd 00 sts 0x00BD, r1
7ea: 02 c0 rjmp .+4 ; 0x7f0
}
}
else
{
/* an invalid character was received */
receivedCmd = invalidCmd;
7ec: c0 93 62 00 sts 0x0062, r28
7f0: 90 91 b8 00 lds r25, 0x00B8
7f4: 80 91 b9 00 lds r24, 0x00B9
7f8: 98 17 cp r25, r24
7fa: 09 f0 breq .+2 ; 0x7fe
7fc: 92 cf rjmp .-220 ; 0x722
}
} /* end while */
asm volatile("clt"::); /* clear out the T flag in case it wasn't
7fe: e8 94 clt
cleared already */
}
800: cf 91 pop r28
802: 08 95 ret
00000804 <UIMgr_executeCmd>:
/***********************************************************
Function Name: UIMgr_executeCmd
Function Description: This function is responsible for
executing whatever cmd is stored in the receivedCmd
object.
Inputs: none
Outputs: none
***********************************************************/
static void UIMgr_executeCmd(void)
{
804: df 92 push r13
806: ef 92 push r14
808: ff 92 push r15
80a: 0f 93 push r16
80c: 1f 93 push r17
80e: cf 93 push r28
810: df 93 push r29
unsigned char i,eepromData, num_writes=0;
812: ee 24 eor r14, r14
unsigned char *pData;
unsigned char eeprom_write_succeeded = FALSE;
#if DEBUG_COLOR_MAP
unsigned char asciiBuffer[5];
#endif
if (receivedCmd == pingCmd)
814: 80 91 62 00 lds r24, 0x0062
818: 81 30 cpi r24, 0x01 ; 1
81a: 09 f4 brne .+2 ; 0x81e
81c: 87 c0 rjmp .+270 ; 0x92c
{
}
else if (receivedCmd == getVersionCmd)
81e: 88 23 and r24, r24
820: 69 f4 brne .+26 ; 0x83c
{
pData = AVRcamVersion;
822: c3 e6 ldi r28, 0x63 ; 99
824: d0 e0 ldi r29, 0x00 ; 0
while(*pData != 0)
826: 80 91 63 00 lds r24, 0x0063
82a: 88 23 and r24, r24
82c: 09 f4 brne .+2 ; 0x830
82e: 7e c0 rjmp .+252 ; 0x92c
{
UIMgr_writeTxFifo(*pData++);
830: 89 91 ld r24, Y+
832: 7b d1 rcall .+758 ; 0xb2a
834: 88 81 ld r24, Y
836: 88 23 and r24, r24
838: d9 f7 brne .-10 ; 0x830
83a: 78 c0 rjmp .+240 ; 0x92c
}
}
else if (receivedCmd == resetCameraCmd)
83c: 80 91 62 00 lds r24, 0x0062
840: 87 30 cpi r24, 0x07 ; 7
842: 11 f4 brne .+4 ; 0x848
{
CamInt_resetCam();
844: 8b dc rcall .-1770 ; 0x15c
846: 72 c0 rjmp .+228 ; 0x92c
}
else if (receivedCmd == dumpFrameCmd)
848: 80 91 62 00 lds r24, 0x0062
84c: 83 30 cpi r24, 0x03 ; 3
84e: 29 f4 brne .+10 ; 0x85a
{
/* publish the event that will indicate that
a request has come to dump a frame...this will
be received by the FrameMgr, which will begin
dumping the frame...a short delay is needed
here to keep the Java demo app happy (sometimes
it wouldn't be able to receive the serial data
as quickly as AVRcam can provide it). */
Utility_delay(100);
850: 84 e6 ldi r24, 0x64 ; 100
852: 90 e0 ldi r25, 0x00 ; 0
854: f8 d2 rcall .+1520 ; 0xe46
PUBLISH_EVENT(EV_DUMP_FRAME);
856: 82 e0 ldi r24, 0x02 ; 2
858: 28 c0 rjmp .+80 ; 0x8aa
}
else if (receivedCmd == setCameraRegsCmd)
85a: 80 91 62 00 lds r24, 0x0062
85e: 82 30 cpi r24, 0x02 ; 2
860: b1 f4 brne .+44 ; 0x88e
{
/* we need to gather the tokens and
build config cmds to be sent to the camera */
for (i=1; i<tokenCount; i+=2) /* starts at 1 since first token
862: ff 24 eor r15, r15
864: f3 94 inc r15
866: 80 91 be 00 lds r24, 0x00BE
86a: f8 16 cp r15, r24
86c: 70 f4 brcc .+28 ; 0x88a
is the CR cmd */
{
CamConfig_setCamReg(tokenBuffer[i],tokenBuffer[i+1]);
86e: 8f 2d mov r24, r15
870: 99 27 eor r25, r25
872: fc 01 movw r30, r24
874: ed 53 subi r30, 0x3D ; 61
876: ff 4f sbci r31, 0xFF ; 255
878: 61 81 ldd r22, Z+1 ; 0x01
87a: 80 81 ld r24, Z
87c: 85 d2 rcall .+1290 ; 0xd88
87e: 82 e0 ldi r24, 0x02 ; 2
880: f8 0e add r15, r24
882: 80 91 be 00 lds r24, 0x00BE
886: f8 16 cp r15, r24
888: 90 f3 brcs .-28 ; 0x86e
}
CamConfig_sendFifoCmds();
88a: 83 d2 rcall .+1286 ; 0xd92
88c: 4f c0 rjmp .+158 ; 0x92c
}
else if (receivedCmd == enableTrackingCmd)
88e: 80 91 62 00 lds r24, 0x0062
892: 84 30 cpi r24, 0x04 ; 4
894: 29 f4 brne .+10 ; 0x8a0
{
/* publish the event...again with a short delay */
Utility_delay(100);
896: 84 e6 ldi r24, 0x64 ; 100
898: 90 e0 ldi r25, 0x00 ; 0
89a: d5 d2 rcall .+1450 ; 0xe46
PUBLISH_EVENT(EV_ENABLE_TRACKING);
89c: 80 e8 ldi r24, 0x80 ; 128
89e: 05 c0 rjmp .+10 ; 0x8aa
}
else if (receivedCmd == disableTrackingCmd)
8a0: 80 91 62 00 lds r24, 0x0062
8a4: 85 30 cpi r24, 0x05 ; 5
8a6: 19 f4 brne .+6 ; 0x8ae
{
PUBLISH_EVENT(EV_DISABLE_TRACKING);
8a8: 81 e8 ldi r24, 0x81 ; 129
8aa: d3 dc rcall .-1626 ; 0x252
8ac: 3f c0 rjmp .+126 ; 0x92c
}
else if (receivedCmd == setColorMapCmd)
8ae: 80 91 62 00 lds r24, 0x0062
8b2: 86 30 cpi r24, 0x06 ; 6
8b4: d9 f5 brne .+118 ; 0x92c
{
/* copy the received tokens into the color map */
for (i=0; i<tokenCount; i++)
8b6: ff 24 eor r15, r15
8b8: 80 91 be 00 lds r24, 0x00BE
8bc: f8 16 cp r15, r24
8be: b0 f5 brcc .+108 ; 0x92c
{
colorMap[i] = tokenBuffer[i+1];
8c0: 8f 2d mov r24, r15
8c2: 99 27 eor r25, r25
8c4: 8c 01 movw r16, r24
8c6: 00 50 subi r16, 0x00 ; 0
8c8: 1d 4f sbci r17, 0xFD ; 253
8ca: fc 01 movw r30, r24
8cc: ed 53 subi r30, 0x3D ; 61
8ce: ff 4f sbci r31, 0xFF ; 255
8d0: 21 81 ldd r18, Z+1 ; 0x01
8d2: f8 01 movw r30, r16
8d4: 20 83 st Z, r18
/* write each colorMap byte to EEPROM, but only those
that changed...this will help reduce wear on the EEPROM */
eepromData = eeprom_read_byte( (unsigned char*)(i+1));
8d6: 01 96 adiw r24, 0x01 ; 1
8d8: b5 d3 rcall .+1898 ; 0x1044
8da: 98 2f mov r25, r24
if (eepromData != colorMap[i])
8dc: f8 01 movw r30, r16
8de: 80 81 ld r24, Z
8e0: 98 17 cp r25, r24
8e2: f9 f0 breq .+62 ; 0x922
{
/* need to actually perform the write because the
data in eeprom is different than the current colorMap */
eeprom_write_succeeded = FALSE;
8e4: dd 24 eor r13, r13
while(eeprom_write_succeeded == FALSE && num_writes < MAX_EEPROM_WRITE_ATTEMPTS)
8e6: f2 e0 ldi r31, 0x02 ; 2
8e8: fe 15 cp r31, r14
8ea: d0 f0 brcs .+52 ; 0x920
8ec: 8f 2d mov r24, r15
8ee: 99 27 eor r25, r25
8f0: 8c 01 movw r16, r24
8f2: 00 50 subi r16, 0x00 ; 0
8f4: 1d 4f sbci r17, 0xFD ; 253
8f6: ec 01 movw r28, r24
8f8: 21 96 adiw r28, 0x01 ; 1
{
eeprom_write_byte((unsigned char*)(i+1),colorMap[i]);
8fa: f8 01 movw r30, r16
8fc: 60 81 ld r22, Z
8fe: ce 01 movw r24, r28
900: ba d3 rcall .+1908 ; 0x1076
num_writes++;
902: e3 94 inc r14
eepromData = eeprom_read_byte( (unsigned char*)(i+1));
904: ce 01 movw r24, r28
906: 9e d3 rcall .+1852 ; 0x1044
908: 98 2f mov r25, r24
if (eepromData == colorMap[i])
90a: f8 01 movw r30, r16
90c: 80 81 ld r24, Z
90e: 98 17 cp r25, r24
910: 11 f4 brne .+4 ; 0x916
{
eeprom_write_succeeded = TRUE;
912: dd 24 eor r13, r13
914: d3 94 inc r13
916: dd 20 and r13, r13
918: 19 f4 brne .+6 ; 0x920
91a: f2 e0 ldi r31, 0x02 ; 2
91c: fe 15 cp r31, r14
91e: 68 f7 brcc .-38 ; 0x8fa
}
}
num_writes = 0;
920: ee 24 eor r14, r14
922: f3 94 inc r15
924: 80 91 be 00 lds r24, 0x00BE
928: f8 16 cp r15, r24
92a: 50 f2 brcs .-108 ; 0x8c0
}
}
#if DEBUG_COLOR_MAP
/* for debugging...send out the entire color map */
UIMgr_txBuffer("\r\n",2);
for (i=0; i<NUM_ELEMENTS_IN_COLOR_MAP; i++)
{
memset(asciiBuffer,0x00,5);
itoa(colorMap[i],asciiBuffer,10);
UIMgr_txBuffer(asciiBuffer,3);
UIMgr_txBuffer(" ",1);
if (i==15 || i == 31)
{
/* break up the output */
UIMgr_txBuffer("\r\n",2);
}
}
#endif
}
}
92c: df 91 pop r29
92e: cf 91 pop r28
930: 1f 91 pop r17
932: 0f 91 pop r16
934: ff 90 pop r15
936: ef 90 pop r14
938: df 90 pop r13
93a: 08 95 ret
0000093c <UIMgr_convertTokenToValue>:
/***********************************************************
Function Name: UIMgr_convertTokenToValue
Function Description: This function is responsible for
converting a received token to a hex value It will
access the asciiTokenBuffer directly, and store the
result in the appropriate token buffer.
Inputs: none
Outputs: none
***********************************************************/
static void UIMgr_convertTokenToValue(void)
{
unsigned int newValue;
newValue = atoi(asciiTokenBuffer);
93c: 8f eb ldi r24, 0xBF ; 191
93e: 90 e0 ldi r25, 0x00 ; 0
940: 55 d3 rcall .+1706 ; 0xfec
942: ac 01 movw r20, r24
if (newValue > 255)
944: 8f 3f cpi r24, 0xFF ; 255
946: 91 05 cpc r25, r1
948: 71 f0 breq .+28 ; 0x966
94a: 68 f0 brcs .+26 ; 0x966
{
/* the value is too large */
receivedCmd = invalidCmd;
94c: 89 e0 ldi r24, 0x09 ; 9
94e: 80 93 62 00 sts 0x0062, r24
tokenBuffer[tokenCount] = 0xFF; /* to indicate an error */
952: 20 91 be 00 lds r18, 0x00BE
956: 83 ec ldi r24, 0xC3 ; 195
958: 90 e0 ldi r25, 0x00 ; 0
95a: fc 01 movw r30, r24
95c: e2 0f add r30, r18
95e: f1 1d adc r31, r1
960: 8f ef ldi r24, 0xFF ; 255
962: 80 83 st Z, r24
964: 08 c0 rjmp .+16 ; 0x976
}
else
{
/* copy the value into the tokenBuffer */
tokenBuffer[tokenCount] = newValue;
966: 80 91 be 00 lds r24, 0x00BE
96a: 23 ec ldi r18, 0xC3 ; 195
96c: 30 e0 ldi r19, 0x00 ; 0
96e: f9 01 movw r30, r18
970: e8 0f add r30, r24
972: f1 1d adc r31, r1
974: 40 83 st Z, r20
}
memset(asciiTokenBuffer,0x00,MAX_TOKEN_LENGTH);
976: 83 e0 ldi r24, 0x03 ; 3
978: ef eb ldi r30, 0xBF ; 191
97a: f0 e0 ldi r31, 0x00 ; 0
97c: 11 92 st Z+, r1
97e: 8a 95 dec r24
980: e9 f7 brne .-6 ; 0x97c
charIndex = 0;
982: 10 92 bd 00 sts 0x00BD, r1
charCount = 0;
986: 10 92 bc 00 sts 0x00BC, r1
}
98a: 08 95 ret
0000098c <UIMgr_convertTokenToCmd>:
/***********************************************************
Function Name: UIMgr_convertTokenToCmd
Function Description: This function is responsible for
parsing a received 2-character command. It will
access the asciiTokenBuffer directly.
Inputs: none
Outputs: none
***********************************************************/
static void UIMgr_convertTokenToCmd(void)
{
if ( (asciiTokenBuffer[0] == 'P') &&
98c: 80 91 bf 00 lds r24, 0x00BF
990: 80 35 cpi r24, 0x50 ; 80
992: 31 f4 brne .+12 ; 0x9a0
994: 80 91 c0 00 lds r24, 0x00C0
998: 87 34 cpi r24, 0x47 ; 71
99a: 11 f4 brne .+4 ; 0x9a0
(asciiTokenBuffer[1] == 'G') )
{
/* we got a "ping" command...but we still need to see
if we are going to get the \r */
receivedCmd = pingCmd;
99c: 81 e0 ldi r24, 0x01 ; 1
99e: 48 c0 rjmp .+144 ; 0xa30
}
else if ( (asciiTokenBuffer[0] == 'G') &&
9a0: 80 91 bf 00 lds r24, 0x00BF
9a4: 87 34 cpi r24, 0x47 ; 71
9a6: 39 f4 brne .+14 ; 0x9b6
9a8: 80 91 c0 00 lds r24, 0x00C0
9ac: 86 35 cpi r24, 0x56 ; 86
9ae: 19 f4 brne .+6 ; 0x9b6
(asciiTokenBuffer[1] == 'V') )
{
/* we got the "get version" command */
receivedCmd = getVersionCmd;
9b0: 10 92 62 00 sts 0x0062, r1
9b4: 3f c0 rjmp .+126 ; 0xa34
}
else if ( (asciiTokenBuffer[0] == 'D') &&
9b6: 80 91 bf 00 lds r24, 0x00BF
9ba: 84 34 cpi r24, 0x44 ; 68
9bc: 31 f4 brne .+12 ; 0x9ca
9be: 80 91 c0 00 lds r24, 0x00C0
9c2: 86 34 cpi r24, 0x46 ; 70
9c4: 11 f4 brne .+4 ; 0x9ca
(asciiTokenBuffer[1] == 'F') )
{
/* we should go into frame dump mode */
receivedCmd = dumpFrameCmd;
9c6: 83 e0 ldi r24, 0x03 ; 3
9c8: 33 c0 rjmp .+102 ; 0xa30
}
else if ( (asciiTokenBuffer[0] == 'C') &&
9ca: 80 91 bf 00 lds r24, 0x00BF
9ce: 83 34 cpi r24, 0x43 ; 67
9d0: 31 f4 brne .+12 ; 0x9de
9d2: 80 91 c0 00 lds r24, 0x00C0
9d6: 82 35 cpi r24, 0x52 ; 82
9d8: 11 f4 brne .+4 ; 0x9de
(asciiTokenBuffer[1] == 'R') )
{
/* the user wants to set registers in the OV6620 */
receivedCmd = setCameraRegsCmd;
9da: 82 e0 ldi r24, 0x02 ; 2
9dc: 29 c0 rjmp .+82 ; 0xa30
}
else if ( (asciiTokenBuffer[0] == 'E') &&
9de: 80 91 bf 00 lds r24, 0x00BF
9e2: 85 34 cpi r24, 0x45 ; 69
9e4: 31 f4 brne .+12 ; 0x9f2
9e6: 80 91 c0 00 lds r24, 0x00C0
9ea: 84 35 cpi r24, 0x54 ; 84
9ec: 11 f4 brne .+4 ; 0x9f2
(asciiTokenBuffer[1] == 'T') )
{
/* the user wants to enable tracking */
receivedCmd = enableTrackingCmd;
9ee: 84 e0 ldi r24, 0x04 ; 4
9f0: 1f c0 rjmp .+62 ; 0xa30
}
else if ( (asciiTokenBuffer[0] == 'S') &&
9f2: 80 91 bf 00 lds r24, 0x00BF
9f6: 83 35 cpi r24, 0x53 ; 83
9f8: 31 f4 brne .+12 ; 0xa06
9fa: 80 91 c0 00 lds r24, 0x00C0
9fe: 8d 34 cpi r24, 0x4D ; 77
a00: 11 f4 brne .+4 ; 0xa06
(asciiTokenBuffer[1] == 'M') )
{
/* the user wants to set the color map */
receivedCmd = setColorMapCmd;
a02: 86 e0 ldi r24, 0x06 ; 6
a04: 15 c0 rjmp .+42 ; 0xa30
}
else if ( (asciiTokenBuffer[0] == 'D') &&
a06: 80 91 bf 00 lds r24, 0x00BF
a0a: 84 34 cpi r24, 0x44 ; 68
a0c: 31 f4 brne .+12 ; 0xa1a
a0e: 80 91 c0 00 lds r24, 0x00C0
a12: 84 35 cpi r24, 0x54 ; 84
a14: 11 f4 brne .+4 ; 0xa1a
(asciiTokenBuffer[1] == 'T') )
{
receivedCmd = disableTrackingCmd;
a16: 85 e0 ldi r24, 0x05 ; 5
a18: 0b c0 rjmp .+22 ; 0xa30
}
else if ( (asciiTokenBuffer[0] == 'R') &&
a1a: 80 91 bf 00 lds r24, 0x00BF
a1e: 82 35 cpi r24, 0x52 ; 82
a20: 31 f4 brne .+12 ; 0xa2e
a22: 80 91 c0 00 lds r24, 0x00C0
a26: 83 35 cpi r24, 0x53 ; 83
a28: 11 f4 brne .+4 ; 0xa2e
(asciiTokenBuffer[1] == 'S') )
{
receivedCmd = resetCameraCmd;
a2a: 87 e0 ldi r24, 0x07 ; 7
a2c: 01 c0 rjmp .+2 ; 0xa30
}
else
{
/* don't recognize the cmd */
receivedCmd = invalidCmd;
a2e: 89 e0 ldi r24, 0x09 ; 9
a30: 80 93 62 00 sts 0x0062, r24
}
memset(asciiTokenBuffer,0x00,MAX_TOKEN_LENGTH);
a34: 83 e0 ldi r24, 0x03 ; 3
a36: ef eb ldi r30, 0xBF ; 191
a38: f0 e0 ldi r31, 0x00 ; 0
a3a: 11 92 st Z+, r1
a3c: 8a 95 dec r24
a3e: e9 f7 brne .-6 ; 0xa3a
charIndex = 0;
a40: 10 92 bd 00 sts 0x00BD, r1
charCount = 0;
a44: 10 92 bc 00 sts 0x00BC, r1
}
a48: 08 95 ret
00000a4a <UIMgr_sendAck>:
/***********************************************************
Function Name: UIMgr_sendAck
Function Description: This function is responsible for
queuing up an ACK to be sent to the user.
Inputs: none
Outputs: none
***********************************************************/
static void UIMgr_sendAck(void)
{
UIMgr_writeTxFifo('A');
a4a: 81 e4 ldi r24, 0x41 ; 65
a4c: 6e d0 rcall .+220 ; 0xb2a
UIMgr_writeTxFifo('C');
a4e: 83 e4 ldi r24, 0x43 ; 67
a50: 6c d0 rcall .+216 ; 0xb2a
UIMgr_writeTxFifo('K');
a52: 8b e4 ldi r24, 0x4B ; 75
a54: 6a d0 rcall .+212 ; 0xb2a
UIMgr_writeTxFifo('\r');
a56: 8d e0 ldi r24, 0x0D ; 13
a58: 68 d0 rcall .+208 ; 0xb2a
}
a5a: 08 95 ret
00000a5c <UIMgr_sendNck>:
/***********************************************************
Function Name: UIMgr_sendNck
Function Description: This function is responsible for
queueing up an NCK to be sent to the user.
Inputs: none
Outputs: none
***********************************************************/
static void UIMgr_sendNck(void)
{
UIMgr_writeTxFifo('N');
a5c: 8e e4 ldi r24, 0x4E ; 78
a5e: 65 d0 rcall .+202 ; 0xb2a
UIMgr_writeTxFifo('C');
a60: 83 e4 ldi r24, 0x43 ; 67
a62: 63 d0 rcall .+198 ; 0xb2a
UIMgr_writeTxFifo('K');
a64: 8b e4 ldi r24, 0x4B ; 75
a66: 61 d0 rcall .+194 ; 0xb2a
UIMgr_writeTxFifo('\r');
a68: 8d e0 ldi r24, 0x0D ; 13
a6a: 5f d0 rcall .+190 ; 0xb2a
}
a6c: 08 95 ret
00000a6e <UIMgr_writeBufferToTxFifo>:
/***********************************************************
Function Name: UIMgr_writeBufferToTxFifo
Function Description: This function is responsible for
placing "length" bytes into the tx FIFO.
Inputs: pData - a pointer to the data to send
length - the number of bytes to send
Outputs: none
***********************************************************/
void UIMgr_writeBufferToTxFifo(unsigned char *pData, unsigned char length)
{
a6e: dc 01 movw r26, r24
unsigned char tmpHead;
if (length == 0)
a70: 66 23 and r22, r22
a72: a9 f0 breq .+42 ; 0xa9e
{
return;
}
DISABLE_INTS();
a74: f8 94 cli
while(length-- != 0)
a76: 61 50 subi r22, 0x01 ; 1
a78: 6f 3f cpi r22, 0xFF ; 255
a7a: 81 f0 breq .+32 ; 0xa9c
a7c: 24 e9 ldi r18, 0x94 ; 148
a7e: 32 e0 ldi r19, 0x02 ; 2
{
UIMgr_txFifo[UIMgr_txFifoHead] = *pData++;
a80: 90 91 ba 00 lds r25, 0x00BA
a84: f9 01 movw r30, r18
a86: e9 0f add r30, r25
a88: f1 1d adc r31, r1
a8a: 8d 91 ld r24, X+
a8c: 80 83 st Z, r24
/* now move the head up */
tmpHead = (UIMgr_txFifoHead + 1) & (UI_MGR_TX_FIFO_MASK);
a8e: 89 2f mov r24, r25
a90: 8f 5f subi r24, 0xFF ; 255
a92: 8f 73 andi r24, 0x3F ; 63
UIMgr_txFifoHead = tmpHead;
a94: 80 93 ba 00 sts 0x00BA, r24
a98: 61 50 subi r22, 0x01 ; 1
a9a: 90 f7 brcc .-28 ; 0xa80
}
ENABLE_INTS();
a9c: 78 94 sei
}
a9e: 08 95 ret
00000aa0 <UIMgr_txBuffer>:
/***********************************************************
Function Name: UIMgr_txBuffer
Function Description: This function is responsible for
sending 'length' bytes out using the UartInterface
module.
Inputs: pData - a pointer to the data to send
length - the number of bytes to send
Outputs: none
***********************************************************/
void UIMgr_txBuffer(unsigned char *pData, unsigned char length)
{
aa0: 0f 93 push r16
aa2: 1f 93 push r17
aa4: cf 93 push r28
aa6: 8c 01 movw r16, r24
aa8: c6 2f mov r28, r22
while(length-- != 0)
aaa: c1 50 subi r28, 0x01 ; 1
aac: cf 3f cpi r28, 0xFF ; 255
aae: 31 f0 breq .+12 ; 0xabc
{
UartInt_txByte(*pData++);
ab0: f8 01 movw r30, r16
ab2: 81 91 ld r24, Z+
ab4: 8f 01 movw r16, r30
ab6: 54 d0 rcall .+168 ; 0xb60
ab8: c1 50 subi r28, 0x01 ; 1
aba: d0 f7 brcc .-12 ; 0xab0
}
}
abc: cf 91 pop r28
abe: 1f 91 pop r17
ac0: 0f 91 pop r16
ac2: 08 95 ret
00000ac4 <UIMgr_flushTxBuffer>:
/***********************************************************
Function Name: UIMgr_flushTxBuffer
Function Description: This function is responsible for
sending all data currently in the serial tx buffer
to the user.
Inputs: none
Outputs: none
***********************************************************/
void UIMgr_flushTxBuffer(void)
{
while(IS_DATA_IN_TX_FIFO() == TRUE)
ac4: 90 91 ba 00 lds r25, 0x00BA
ac8: 80 91 bb 00 lds r24, 0x00BB
acc: 98 17 cp r25, r24
ace: 41 f0 breq .+16 ; 0xae0
{
UartInt_txByte(UIMgr_readTxFifo() );
ad0: 1a d0 rcall .+52 ; 0xb06
ad2: 46 d0 rcall .+140 ; 0xb60
ad4: 90 91 ba 00 lds r25, 0x00BA
ad8: 80 91 bb 00 lds r24, 0x00BB
adc: 98 17 cp r25, r24
ade: c1 f7 brne .-16 ; 0xad0
}
}
ae0: 08 95 ret
00000ae2 <UIMgr_readRxFifo>:
/***********************************************************
Function Name: UIMgr_readRxFifo
Function Description: This function is responsible for
reading a single byte of data from the rx fifo, and
updating the appropriate pointers.
Inputs: none
Outputs: unsigned char-the data read
***********************************************************/
static unsigned char UIMgr_readRxFifo(void)
{
unsigned char dataByte, tmpTail;
/* just return the current tail from the rx fifo */
DISABLE_INTS();
ae2: f8 94 cli
dataByte = UIMgr_rxFifo[UIMgr_rxFifoTail];
ae4: 20 91 b9 00 lds r18, 0x00B9
ae8: 84 e7 ldi r24, 0x74 ; 116
aea: 92 e0 ldi r25, 0x02 ; 2
aec: fc 01 movw r30, r24
aee: e2 0f add r30, r18
af0: f1 1d adc r31, r1
af2: 90 81 ld r25, Z
tmpTail = (UIMgr_rxFifoTail+1) & (UI_MGR_RX_FIFO_MASK);
af4: 82 2f mov r24, r18
af6: 8f 5f subi r24, 0xFF ; 255
af8: 8f 71 andi r24, 0x1F ; 31
UIMgr_rxFifoTail = tmpTail;
afa: 80 93 b9 00 sts 0x00B9, r24
ENABLE_INTS();
afe: 78 94 sei
return(dataByte);
b00: 89 2f mov r24, r25
b02: 99 27 eor r25, r25
}
b04: 08 95 ret
00000b06 <UIMgr_readTxFifo>:
/***********************************************************
Function Name: UIMgr_readTxFifo
Function Description: This function is responsible for
reading a single byte of data from the tx fifo, and
updating the appropriate pointers.
Inputs: none
Outputs: unsigned char-the data read
***********************************************************/
static unsigned char UIMgr_readTxFifo(void)
{
unsigned char dataByte, tmpTail;
/* just return the current tail from the tx fifo */
DISABLE_INTS();
b06: f8 94 cli
dataByte = UIMgr_txFifo[UIMgr_txFifoTail];
b08: 20 91 bb 00 lds r18, 0x00BB
b0c: 84 e9 ldi r24, 0x94 ; 148
b0e: 92 e0 ldi r25, 0x02 ; 2
b10: fc 01 movw r30, r24
b12: e2 0f add r30, r18
b14: f1 1d adc r31, r1
b16: 90 81 ld r25, Z
tmpTail = (UIMgr_txFifoTail+1) & (UI_MGR_TX_FIFO_MASK);
b18: 82 2f mov r24, r18
b1a: 8f 5f subi r24, 0xFF ; 255
b1c: 8f 73 andi r24, 0x3F ; 63
UIMgr_txFifoTail = tmpTail;
b1e: 80 93 bb 00 sts 0x00BB, r24
ENABLE_INTS();
b22: 78 94 sei
return(dataByte);
b24: 89 2f mov r24, r25
b26: 99 27 eor r25, r25
}
b28: 08 95 ret
00000b2a <UIMgr_writeTxFifo>:
/***********************************************************
Function Name: UIMgr_writeTxFifo
Function Description: This function is responsible for
writing a single byte to the TxFifo and
updating the appropriate pointers.
Inputs: data - the byte to write to the Fifo
Outputs: none
***********************************************************/
void UIMgr_writeTxFifo(unsigned char data)
{
b2a: 38 2f mov r19, r24
unsigned char tmpHead;
DISABLE_INTS();
b2c: f8 94 cli
UIMgr_txFifo[UIMgr_txFifoHead] = data;
b2e: 20 91 ba 00 lds r18, 0x00BA
b32: 84 e9 ldi r24, 0x94 ; 148
b34: 92 e0 ldi r25, 0x02 ; 2
b36: fc 01 movw r30, r24
b38: e2 0f add r30, r18
b3a: f1 1d adc r31, r1
b3c: 30 83 st Z, r19
/* now move the head up */
tmpHead = (UIMgr_txFifoHead + 1) & (UI_MGR_TX_FIFO_MASK);
b3e: 82 2f mov r24, r18
b40: 8f 5f subi r24, 0xFF ; 255
b42: 8f 73 andi r24, 0x3F ; 63
UIMgr_txFifoHead = tmpHead;
b44: 80 93 ba 00 sts 0x00BA, r24
ENABLE_INTS();
b48: 78 94 sei
}
b4a: 08 95 ret
00000b4c <UartInt_init>:
void UartInt_init(void)
{
/* set up the baud rate registers so the UART will operate
at 115.2 Kbps */
UBRRH = 0x00;
b4c: 10 bc out 0x20, r1 ; 32
#ifdef NO_CRYSTAL
UBRRL = 18; /* 18 for double clocking at 115.2 kbps */
b4e: 82 e1 ldi r24, 0x12 ; 18
b50: 89 b9 out 0x09, r24 ; 9
#else
UBRRL = 0x08; /* for 16 MHz crystal at 115.2 kbps */
#endif
/* enable the tx and rx capabilities of the UART...as well
as the receive complete interrupt */
UCSRB = (1<<RXCIE)|(1<<RXEN)|(1<<TXEN);
b52: 88 e9 ldi r24, 0x98 ; 152
b54: 8a b9 out 0x0a, r24 ; 10
/* set up the control registers so the UART works at 8N1 */
UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);
b56: 86 e8 ldi r24, 0x86 ; 134
b58: 80 bd out 0x20, r24 ; 32
#ifdef NO_CRYSTAL
/* set the baud rate to use the double-speed */
UCSRA = (1<<U2X);
b5a: 82 e0 ldi r24, 0x02 ; 2
b5c: 8b b9 out 0x0b, r24 ; 11
#endif
}
b5e: 08 95 ret
00000b60 <UartInt_txByte>:
/***********************************************************
Function Name: UartInt_txByte
Function Description: This function is responsible for
transmitting a single byte on the uart.
Inputs: txByte - the byte to send
Outputs: none
NOTES: When the TX UDRE (data register empty) is set, there
is puposefully no interrupt...thus, to send a string of
data out, the calling routine needs to hold up the entire
application while this takes place (or just send one
byte at a time at strtegically timed intervals, like
the stats data is sent out :-)
***********************************************************/
void UartInt_txByte(unsigned char txByte)
{
/* Wait for empty transmit buffer */
while ( !( UCSRA & (1<<UDRE)) );
b60: 5d 9b sbis 0x0b, 5 ; 11
b62: fe cf rjmp .-4 ; 0xb60
/* Put data into buffer, sends the data */
UDR = txByte;
b64: 8c b9 out 0x0c, r24 ; 12
}
b66: 08 95 ret
00000b68 <__vector_11>:
/***********************************************************
Function Name: SIG_UART_RECV ISR
Function Description: This function is responsible for
handling the interrupt caused when a data byte is
received by the UART.
Inputs: none
Outputs: none
NOTES: This function was originally written in assembly,
but moved over to C when the setting of the "T" bit at
the end of the routine was no longer necessary (this
theoretically allowed the AVRcam to respond to serial
bytes in the middle of tracking or dumping a frame.
But it wasn't really needed, and understanding the C
is easier :-)
***********************************************************/
SIGNAL(SIG_UART_RECV)
{
b68: 1f 92 push r1
b6a: 0f 92 push r0
b6c: 0f b6 in r0, 0x3f ; 63
b6e: 0f 92 push r0
b70: 11 24 eor r1, r1
b72: 2f 93 push r18
b74: 8f 93 push r24
b76: 9f 93 push r25
b78: ef 93 push r30
b7a: ff 93 push r31
unsigned char tmpHead;
/* read the data byte, put it in the serial queue, and
post the event */
UIMgr_rxFifo[UIMgr_rxFifoHead] = UDR;
b7c: 20 91 b8 00 lds r18, 0x00B8
b80: 84 e7 ldi r24, 0x74 ; 116
b82: 92 e0 ldi r25, 0x02 ; 2
b84: fc 01 movw r30, r24
b86: e2 0f add r30, r18
b88: f1 1d adc r31, r1
b8a: 8c b1 in r24, 0x0c ; 12
b8c: 80 83 st Z, r24
/* now move the head up */
tmpHead = (UIMgr_rxFifoHead + 1) & (UI_MGR_RX_FIFO_MASK);
b8e: 2f 5f subi r18, 0xFF ; 255
b90: 2f 71 andi r18, 0x1F ; 31
UIMgr_rxFifoHead = tmpHead;
b92: 20 93 b8 00 sts 0x00B8, r18
/* write the serial received event to the event fifo */
Exec_eventFifo[Exec_eventFifoHead] = EV_SERIAL_DATA_RECEIVED;
b96: 20 91 70 00 lds r18, 0x0070
b9a: 8c e6 ldi r24, 0x6C ; 108
b9c: 92 e0 ldi r25, 0x02 ; 2
b9e: fc 01 movw r30, r24
ba0: e2 0f add r30, r18
ba2: f1 1d adc r31, r1
ba4: 81 e0 ldi r24, 0x01 ; 1
ba6: 80 83 st Z, r24
/* now move the head up */
tmpHead = (Exec_eventFifoHead + 1) & (EXEC_EVENT_FIFO_MASK);
ba8: 28 0f add r18, r24
baa: 27 70 andi r18, 0x07 ; 7
Exec_eventFifoHead = tmpHead;
bac: 20 93 70 00 sts 0x0070, r18
}
bb0: ff 91 pop r31
bb2: ef 91 pop r30
bb4: 9f 91 pop r25
bb6: 8f 91 pop r24
bb8: 2f 91 pop r18
bba: 0f 90 pop r0
bbc: 0f be out 0x3f, r0 ; 63
bbe: 0f 90 pop r0
bc0: 1f 90 pop r1
bc2: 18 95 reti
00000bc4 <I2CInt_init>:
Outputs: none
***********************************************************/
void I2CInt_init(void)
{
TWSR = 0;
bc4: 11 b8 out 0x01, r1 ; 1
/* init the speed of the I2C interface, running at
100 Kbps */
TWBR = (FOSC / I2C_SPEED - 16)/2;
bc6: 88 e4 ldi r24, 0x48 ; 72
bc8: 80 b9 out 0x00, r24 ; 0
}
bca: 08 95 ret
00000bcc <I2CInt_writeData>:
/***********************************************************
Function Name: I2CInt_writeData
Function Description: This function is responsible for
initiating the process of writing a sequence of bytes
an I2C slave address. This function will try to write
the data three times before giving up.
Inputs: address: the address of the I2C slave device
data: a pointer to the data to be written
to the slave...for camera interfacing,
the data follows a <register #><data>
format
bytes: the number of bytes to write
Outputs: none
***********************************************************/
void I2CInt_writeData(unsigned char address, unsigned char *data, unsigned char bytes)
{
bcc: 98 2f mov r25, r24
while(status & (1<<BUSY)); /* Bus is busy wait (or exit with error code) */
bce: 80 91 08 01 lds r24, 0x0108
bd2: 88 23 and r24, r24
bd4: e4 f3 brlt .-8 ; 0xbce
while(TWCR & (1<<TWSTO));
bd6: 06 b6 in r0, 0x36 ; 54
bd8: 04 fc sbrc r0, 4
bda: fd cf rjmp .-6 ; 0xbd6
/* copy the needed data and state info to our local I2C command structure */
twi_address = address;
bdc: 90 93 03 01 sts 0x0103, r25
twi_data = data;
be0: 70 93 05 01 sts 0x0105, r23
be4: 60 93 04 01 sts 0x0104, r22
twi_bytes = bytes;
be8: 40 93 07 01 sts 0x0107, r20
twi_ddr = TW_WRITE;
bec: 10 92 06 01 sts 0x0106, r1
retry_cnt = 0;
bf0: 10 92 09 01 sts 0x0109, r1
/* Generate start condition, the remainder of the transfer is interrupt driven and
will be performed in the background */
TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN)|(1<<TWIE);
bf4: 85 ea ldi r24, 0xA5 ; 165
bf6: 86 bf out 0x36, r24 ; 54
status |= (1<<BUSY);
bf8: 80 91 08 01 lds r24, 0x0108
bfc: 80 68 ori r24, 0x80 ; 128
bfe: 80 93 08 01 sts 0x0108, r24
}
c02: 08 95 ret
00000c04 <I2CInt_readData>:
/***********************************************************
Function Name: I2CInt_readData
Function Description: This funcion is responsible for
reading the specified number of bytes from a slave
device.
Inputs: address: the slave address to read from
data: a pointer to where the data will be stored
bytes: the number of bytes to read
Outputs: none
***********************************************************/
void I2CInt_readData(unsigned char address, unsigned char *data, unsigned char bytes)
{
c04: 98 2f mov r25, r24
/* Bus is busy wait (or exit with error code) */
while(status & (1<<BUSY));
c06: 80 91 08 01 lds r24, 0x0108
c0a: 88 23 and r24, r24
c0c: e4 f3 brlt .-8 ; 0xc06
twi_address = address;
c0e: 90 93 03 01 sts 0x0103, r25
twi_data = data;
c12: 70 93 05 01 sts 0x0105, r23
c16: 60 93 04 01 sts 0x0104, r22
twi_bytes = bytes;
c1a: 40 93 07 01 sts 0x0107, r20
twi_ddr = TW_READ;
c1e: 81 e0 ldi r24, 0x01 ; 1
c20: 80 93 06 01 sts 0x0106, r24
retry_cnt = 0;
c24: 10 92 09 01 sts 0x0109, r1
/* Generate start condition, the remainder of the transfer is interrupt driven and
will be performed in the background */
TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN)|(1<<TWIE);
c28: 85 ea ldi r24, 0xA5 ; 165
c2a: 86 bf out 0x36, r24 ; 54
status |= (1<<BUSY);
c2c: 80 91 08 01 lds r24, 0x0108
c30: 80 68 ori r24, 0x80 ; 128
c32: 80 93 08 01 sts 0x0108, r24
}
c36: 08 95 ret
00000c38 <I2CInt_isI2cBusy>:
/***********************************************************
Function Name: I2CInt_isI2cBusy
Function Description: This funcion is responsible for
indicating if the I2C bus is currently busy to external
modules.
device.
Inputs: none
Outputs: bool_t - indicating if bus is busy
***********************************************************/
bool_t I2CInt_isI2cBusy(void)
{
bool_t retVal = FALSE;
c38: 90 e0 ldi r25, 0x00 ; 0
if ( (status & (1<<BUSY)) != 0)
c3a: 80 91 08 01 lds r24, 0x0108
c3e: 88 23 and r24, r24
c40: 0c f4 brge .+2 ; 0xc44
{
retVal = TRUE;
c42: 91 e0 ldi r25, 0x01 ; 1
}
return(retVal);
c44: 89 2f mov r24, r25
c46: 99 27 eor r25, r25
}
c48: 08 95 ret
00000c4a <__vector_17>:
/***********************************************************
Function Name: <interrupt handler for I2C>
Function Description: This function is responsible for
implementing the control logic needed to perform a
read or write operation with an I2C slave.
Inputs: none
Outputs: none
***********************************************************/
SIGNAL(SIG_2WIRE_SERIAL)
{
c4a: 1f 92 push r1
c4c: 0f 92 push r0
c4e: 0f b6 in r0, 0x3f ; 63
c50: 0f 92 push r0
c52: 11 24 eor r1, r1
c54: 8f 93 push r24
c56: 9f 93 push r25
c58: af 93 push r26
c5a: bf 93 push r27
c5c: ef 93 push r30
c5e: ff 93 push r31
unsigned char TWI_status = TWSR & TW_STATUS_MASK; /* grab just the status bits */
c60: 81 b1 in r24, 0x01 ; 1
c62: 88 7f andi r24, 0xF8 ; 248
/* the entire I2C handler is state-based...determine
what needs to be done based on TWI_status */
switch(TWI_status)
c64: 99 27 eor r25, r25
c66: aa 27 eor r26, r26
c68: bb 27 eor r27, r27
c6a: fc 01 movw r30, r24
c6c: 38 97 sbiw r30, 0x08 ; 8
c6e: e1 35 cpi r30, 0x51 ; 81
c70: f1 05 cpc r31, r1
c72: 08 f0 brcs .+2 ; 0xc76
c74: 6d c0 rjmp .+218 ; 0xd50
c76: ed 5e subi r30, 0xED ; 237
c78: ff 4f sbci r31, 0xFF ; 255
c7a: 09 94 ijmp
{
case TW_START: /* Start condition */
case TW_REP_START: /* Repeated start condition */
if(retry_cnt > MAX_TWI_RETRIES)
c7c: 80 91 09 01 lds r24, 0x0109
c80: 83 30 cpi r24, 0x03 ; 3
c82: 08 f0 brcs .+2 ; 0xc86
c84: 5d c0 rjmp .+186 ; 0xd40
{
/* generate stop condition if we've reached our retry limit */
TWCR |= (1<<TWINT)|(1<<TWSTO);
status &= ~(1<<BUSY);
return;
}
/* indicate read or write */
TWDR = (twi_address<<1) + twi_ddr;
c86: 80 91 03 01 lds r24, 0x0103
c8a: 98 2f mov r25, r24
c8c: 99 0f add r25, r25
c8e: 80 91 06 01 lds r24, 0x0106
c92: 89 0f add r24, r25
c94: 83 b9 out 0x03, r24 ; 3
/* TWSTA must be cleared...also clears TWINT */
TWCR &= ~(1<<TWSTA);
c96: 86 b7 in r24, 0x36 ; 54
c98: 8f 7d andi r24, 0xDF ; 223
c9a: 4a c0 rjmp .+148 ; 0xd30
break;
case TW_MT_SLA_ACK: /* Slave acknowledged address, */
retry_cnt = 0;
c9c: 10 92 09 01 sts 0x0109, r1
/* tx the data, and increment the data pointer */
TWDR = *twi_data;
ca0: 11 c0 rjmp .+34 ; 0xcc4
twi_data++;
/* clear the int to continue */
TWCR |= (1<<TWINT);
break;
case TW_MT_SLA_NACK: /* Slave didn't acknowledge address, */
case TW_MR_SLA_NACK:
retry_cnt++;
ca2: 80 91 09 01 lds r24, 0x0109
ca6: 8f 5f subi r24, 0xFF ; 255
ca8: 80 93 09 01 sts 0x0109, r24
/* retry...*/
TWCR |= (1<<TWINT)|(1<<TWSTA)|(1<<TWSTO);
cac: 86 b7 in r24, 0x36 ; 54
cae: 80 6b ori r24, 0xB0 ; 176
cb0: 3f c0 rjmp .+126 ; 0xd30
break;
case TW_MT_DATA_ACK: /* Slave Acknowledged data, */
if(--twi_bytes > 0)
cb2: 80 91 07 01 lds r24, 0x0107
cb6: 81 50 subi r24, 0x01 ; 1
cb8: 80 93 07 01 sts 0x0107, r24
cbc: 80 91 07 01 lds r24, 0x0107
cc0: 88 23 and r24, r24
cc2: f1 f1 breq .+124 ; 0xd40
{
/* more data to send, so send it */
TWDR = *twi_data;
cc4: e0 91 04 01 lds r30, 0x0104
cc8: f0 91 05 01 lds r31, 0x0105
ccc: 80 81 ld r24, Z
cce: 83 b9 out 0x03, r24 ; 3
twi_data++;
cd0: cf 01 movw r24, r30
cd2: 01 96 adiw r24, 0x01 ; 1
cd4: 90 93 05 01 sts 0x0105, r25
cd8: 80 93 04 01 sts 0x0104, r24
TWCR |= (1<<TWINT);
cdc: 09 c0 rjmp .+18 ; 0xcf0
}
else
{
/* generate the stop condition if needed */
TWCR |= (1<<TWSTO)|(1<<TWINT);
status &= ~(1<<BUSY);
}
break;
case TW_MT_DATA_NACK: /* Slave didn't acknowledge data */
/* send the stop condition */
TWCR |= (1<<TWINT)|(1<<TWSTO);
status &= ~(1<<BUSY);
break;
case TW_MR_SLA_ACK: /* Slave acknowledged address */
if(--twi_bytes > 0)
cde: 80 91 07 01 lds r24, 0x0107
ce2: 81 50 subi r24, 0x01 ; 1
ce4: 80 93 07 01 sts 0x0107, r24
ce8: 80 91 07 01 lds r24, 0x0107
cec: 88 23 and r24, r24
cee: d9 f4 brne .+54 ; 0xd26
{
/* if there is more than one byte to read, acknowledge */
TWCR |= (1<<TWEA)|(1<<TWINT);
}
else
{
/* no acknowledge */
TWCR |= (1<<TWINT);
cf0: 86 b7 in r24, 0x36 ; 54
cf2: 80 68 ori r24, 0x80 ; 128
cf4: 1d c0 rjmp .+58 ; 0xd30
}
break;
case TW_MR_DATA_ACK: /* Master acknowledged data */
/* grab the received data */
*twi_data = TWDR;
cf6: e0 91 04 01 lds r30, 0x0104
cfa: f0 91 05 01 lds r31, 0x0105
cfe: 83 b1 in r24, 0x03 ; 3
d00: 80 83 st Z, r24
twi_data++;
d02: 80 91 04 01 lds r24, 0x0104
d06: 90 91 05 01 lds r25, 0x0105
d0a: 01 96 adiw r24, 0x01 ; 1
d0c: 90 93 05 01 sts 0x0105, r25
d10: 80 93 04 01 sts 0x0104, r24
if(--twi_bytes > 0)
d14: 80 91 07 01 lds r24, 0x0107
d18: 81 50 subi r24, 0x01 ; 1
d1a: 80 93 07 01 sts 0x0107, r24
d1e: 80 91 07 01 lds r24, 0x0107
d22: 88 23 and r24, r24
d24: 19 f0 breq .+6 ; 0xd2c
{
/* get the next data byte and ack */
TWCR |= (1<<TWEA)|(1<<TWINT);
d26: 86 b7 in r24, 0x36 ; 54
d28: 80 6c ori r24, 0xC0 ; 192
d2a: 02 c0 rjmp .+4 ; 0xd30
}
else
{
/* clear out the enable acknowledge bit */
TWCR &= ~(1<<TWEA);
d2c: 86 b7 in r24, 0x36 ; 54
d2e: 8f 7b andi r24, 0xBF ; 191
d30: 86 bf out 0x36, r24 ; 54
}
break;
d32: 0e c0 rjmp .+28 ; 0xd50
case TW_MR_DATA_NACK: /* Master didn't acknowledge data -> end of read process */
/* read data, and generate the stop condition */
*twi_data = TWDR;
d34: e0 91 04 01 lds r30, 0x0104
d38: f0 91 05 01 lds r31, 0x0105
d3c: 83 b1 in r24, 0x03 ; 3
d3e: 80 83 st Z, r24
TWCR |= (1<<TWSTO)|(1<<TWINT);
d40: 86 b7 in r24, 0x36 ; 54
d42: 80 69 ori r24, 0x90 ; 144
d44: 86 bf out 0x36, r24 ; 54
status &= ~(1<<BUSY);
d46: 80 91 08 01 lds r24, 0x0108
d4a: 8f 77 andi r24, 0x7F ; 127
d4c: 80 93 08 01 sts 0x0108, r24
break;
}
}
d50: ff 91 pop r31
d52: ef 91 pop r30
d54: bf 91 pop r27
d56: af 91 pop r26
d58: 9f 91 pop r25
d5a: 8f 91 pop r24
d5c: 0f 90 pop r0
d5e: 0f be out 0x3f, r0 ; 63
d60: 0f 90 pop r0
d62: 1f 90 pop r1
d64: 18 95 reti
00000d66 <CamConfig_init>:
Outputs: none
***********************************************************/
void CamConfig_init(void)
{
CamConfig_setCamReg(0x14,0x20); /* reduce frame size */
d66: 60 e2 ldi r22, 0x20 ; 32
d68: 84 e1 ldi r24, 0x14 ; 20
d6a: 0e d0 rcall .+28 ; 0xd88
CamConfig_setCamReg(0x39,0x40); /* gate PCLK with HREF */
d6c: 60 e4 ldi r22, 0x40 ; 64
d6e: 89 e3 ldi r24, 0x39 ; 57
d70: 0b d0 rcall .+22 ; 0xd88
CamConfig_setCamReg(0x12,0x28); /* set RGB mode, with no AWB */
d72: 68 e2 ldi r22, 0x28 ; 40
d74: 82 e1 ldi r24, 0x12 ; 18
d76: 08 d0 rcall .+16 ; 0xd88
CamConfig_setCamReg(0x28,0x05); /* set color sequencer */
d78: 65 e0 ldi r22, 0x05 ; 5
d7a: 88 e2 ldi r24, 0x28 ; 40
d7c: 05 d0 rcall .+10 ; 0xd88
CamConfig_setCamReg(0x13,0x01); /* un-tri-state the Y/UV lines */
d7e: 61 e0 ldi r22, 0x01 ; 1
d80: 83 e1 ldi r24, 0x13 ; 19
d82: 02 d0 rcall .+4 ; 0xd88
/* send the first four cmds in the I2C fifo */
CamConfig_sendFifoCmds();
d84: 06 d0 rcall .+12 ; 0xd92
}
d86: 08 95 ret
00000d88 <CamConfig_setCamReg>:
/***********************************************************
Function Name: CamConfig_setCamReg
Function Description: This function is responsible for
creating an I2C cmd structure and placing it into the
cmd fifo.
Inputs: reg - the register to modify
val - the new value of the register
Outputs: none
***********************************************************/
void CamConfig_setCamReg(unsigned char reg, unsigned char val)
{
i2cCmd_t cmd;
cmd.configReg = reg;
d88: 28 2f mov r18, r24
cmd.data = val;
d8a: 36 2f mov r19, r22
#ifndef SIMULATION
CamConfig_writeTxFifo(cmd);
d8c: c9 01 movw r24, r18
d8e: 2f d0 rcall .+94 ; 0xdee
#endif
}
d90: 08 95 ret
00000d92 <CamConfig_sendFifoCmds>:
/***********************************************************
Function Name: CamConfig_sendFifoCmds
Function Description: This function is responsible for
sending the entire contents of the config fifo. This
function won't return until the configuration process
is complete (or an error is encountered).
Inputs: none
Outputs: none
Note: Since this function is written to use the TWI
interrupt in the I2CInterface module, there will be
some busy-waiting here...no big deal, since we end up
having to trash the frame that we are executing this
slave write in anyway (since we can't meet the strict
timing requirements and write i2c at the same time).
***********************************************************/
void CamConfig_sendFifoCmds(void)
{
d92: cf 93 push r28
d94: df 93 push r29
d96: cd b7 in r28, 0x3d ; 61
d98: de b7 in r29, 0x3e ; 62
d9a: 22 97 sbiw r28, 0x02 ; 2
d9c: 0f b6 in r0, 0x3f ; 63
d9e: f8 94 cli
da0: de bf out 0x3e, r29 ; 62
da2: 0f be out 0x3f, r0 ; 63
da4: cd bf out 0x3d, r28 ; 61
i2cCmd_t cmd;
while (CamConfig_txFifoHead != CamConfig_txFifoTail)
da6: 90 91 0a 01 lds r25, 0x010A
daa: 80 91 0b 01 lds r24, 0x010B
dae: 98 17 cp r25, r24
db0: a9 f0 breq .+42 ; 0xddc
{
cmd = CamConfig_readTxFifo();
db2: 37 d0 rcall .+110 ; 0xe22
db4: 89 83 std Y+1, r24 ; 0x01
db6: 9a 83 std Y+2, r25 ; 0x02
I2CInt_writeData(CAM_ADDRESS,&cmd.configReg,SIZE_OF_I2C_CMD);
db8: 42 e0 ldi r20, 0x02 ; 2
dba: be 01 movw r22, r28
dbc: 6f 5f subi r22, 0xFF ; 255
dbe: 7f 4f sbci r23, 0xFF ; 255
dc0: 80 e6 ldi r24, 0x60 ; 96
dc2: 04 df rcall .-504 ; 0xbcc
Utility_delay(100);
dc4: 84 e6 ldi r24, 0x64 ; 100
dc6: 90 e0 ldi r25, 0x00 ; 0
dc8: 3e d0 rcall .+124 ; 0xe46
/* wait for the I2C transaction to complete */
while(I2CInt_isI2cBusy() == TRUE);
dca: 36 df rcall .-404 ; 0xc38
dcc: 81 30 cpi r24, 0x01 ; 1
dce: e9 f3 breq .-6 ; 0xdca
dd0: 90 91 0a 01 lds r25, 0x010A
dd4: 80 91 0b 01 lds r24, 0x010B
dd8: 98 17 cp r25, r24
dda: 59 f7 brne .-42 ; 0xdb2
}
}
ddc: 22 96 adiw r28, 0x02 ; 2
dde: 0f b6 in r0, 0x3f ; 63
de0: f8 94 cli
de2: de bf out 0x3e, r29 ; 62
de4: 0f be out 0x3f, r0 ; 63
de6: cd bf out 0x3d, r28 ; 61
de8: df 91 pop r29
dea: cf 91 pop r28
dec: 08 95 ret
00000dee <CamConfig_writeTxFifo>:
/***********************************************************
Function Name: CamConfig_writeTxFifo
Function Description: This function is responsible for
adding a new command to the tx fifo. It adjusts all
needed pointers.
Inputs: cmd - the i2cCmd_t to add to the fifo
Outputs: bool_t - indicating if writing to the fifo
causes it to wrap
***********************************************************/
bool_t CamConfig_writeTxFifo(i2cCmd_t cmd)
{
dee: 9c 01 movw r18, r24
unsigned char tmpHead;
bool_t retVal = TRUE;
df0: 51 e0 ldi r21, 0x01 ; 1
CamConfig_txFifo[CamConfig_txFifoHead] = cmd;
df2: 40 91 0a 01 lds r20, 0x010A
df6: 84 2f mov r24, r20
df8: 99 27 eor r25, r25
dfa: 88 0f add r24, r24
dfc: 99 1f adc r25, r25
dfe: fc 01 movw r30, r24
e00: ec 52 subi r30, 0x2C ; 44
e02: fd 4f sbci r31, 0xFD ; 253
e04: 20 83 st Z, r18
e06: 31 83 std Z+1, r19 ; 0x01
/* see if we need to wrap */
tmpHead = (CamConfig_txFifoHead+1) & (CAM_CONFIG_TX_FIFO_MASK);
e08: 84 2f mov r24, r20
e0a: 85 0f add r24, r21
e0c: 87 70 andi r24, 0x07 ; 7
CamConfig_txFifoHead = tmpHead;
e0e: 80 93 0a 01 sts 0x010A, r24
/* check to see if we have filled up the queue */
if (CamConfig_txFifoHead == CamConfig_txFifoTail)
e12: 90 91 0b 01 lds r25, 0x010B
e16: 89 17 cp r24, r25
e18: 09 f4 brne .+2 ; 0xe1c
{
/* we wrapped the fifo...return false */
retVal = FALSE;
e1a: 50 e0 ldi r21, 0x00 ; 0
}
return(retVal);
e1c: 85 2f mov r24, r21
e1e: 99 27 eor r25, r25
}
e20: 08 95 ret
00000e22 <CamConfig_readTxFifo>:
/***********************************************************
Function Name: CamConfig_readTxFifo
Function Description: This function is responsible for
reading a cmd out of the tx fifo.
Inputs: none
Outputs: i2cCmd_t - the cmd read from the fifo
***********************************************************/
static i2cCmd_t CamConfig_readTxFifo(void)
{
i2cCmd_t cmd;
unsigned char tmpTail;
/* just return the current tail from the rx fifo */
cmd = CamConfig_txFifo[CamConfig_txFifoTail];
e22: 40 91 0b 01 lds r20, 0x010B
e26: 84 2f mov r24, r20
e28: 99 27 eor r25, r25
e2a: 88 0f add r24, r24
e2c: 99 1f adc r25, r25
e2e: fc 01 movw r30, r24
e30: ec 52 subi r30, 0x2C ; 44
e32: fd 4f sbci r31, 0xFD ; 253
e34: 20 81 ld r18, Z
e36: 31 81 ldd r19, Z+1 ; 0x01
tmpTail = (CamConfig_txFifoTail+1) & (CAM_CONFIG_TX_FIFO_MASK);
e38: 84 2f mov r24, r20
e3a: 8f 5f subi r24, 0xFF ; 255
e3c: 87 70 andi r24, 0x07 ; 7
CamConfig_txFifoTail = tmpTail;
e3e: 80 93 0b 01 sts 0x010B, r24
return(cmd);
}
e42: c9 01 movw r24, r18
e44: 08 95 ret
00000e46 <Utility_delay>:
if needed...this isn't really a millisecond, so DON'T
depend on it for exact timing...
***********************************************************/
void Utility_delay(unsigned short numMs)
{
e46: cf 93 push r28
e48: df 93 push r29
e4a: cd b7 in r28, 0x3d ; 61
e4c: de b7 in r29, 0x3e ; 62
e4e: 24 97 sbiw r28, 0x04 ; 4
e50: 0f b6 in r0, 0x3f ; 63
e52: f8 94 cli
e54: de bf out 0x3e, r29 ; 62
e56: 0f be out 0x3f, r0 ; 63
e58: cd bf out 0x3d, r28 ; 61
e5a: 9c 01 movw r18, r24
volatile unsigned short i=0,j=0;
e5c: 19 82 std Y+1, r1 ; 0x01
e5e: 1a 82 std Y+2, r1 ; 0x02
e60: 1b 82 std Y+3, r1 ; 0x03
e62: 1c 82 std Y+4, r1 ; 0x04
#ifndef SIMULATION
for (i=0; i<numMs; i++)
e64: 19 82 std Y+1, r1 ; 0x01
e66: 1a 82 std Y+2, r1 ; 0x02
e68: 89 81 ldd r24, Y+1 ; 0x01
e6a: 9a 81 ldd r25, Y+2 ; 0x02
e6c: 82 17 cp r24, r18
e6e: 93 07 cpc r25, r19
e70: e0 f4 brcc .+56 ; 0xeaa
{
for (j=0; j<1000; j++)
e72: 1b 82 std Y+3, r1 ; 0x03
e74: 1c 82 std Y+4, r1 ; 0x04
e76: 8b 81 ldd r24, Y+3 ; 0x03
e78: 9c 81 ldd r25, Y+4 ; 0x04
e7a: 88 5e subi r24, 0xE8 ; 232
e7c: 93 40 sbci r25, 0x03 ; 3
e7e: 58 f4 brcc .+22 ; 0xe96
{
asm volatile("nop"::);
e80: 00 00 nop
e82: 8b 81 ldd r24, Y+3 ; 0x03
e84: 9c 81 ldd r25, Y+4 ; 0x04
e86: 01 96 adiw r24, 0x01 ; 1
e88: 8b 83 std Y+3, r24 ; 0x03
e8a: 9c 83 std Y+4, r25 ; 0x04
e8c: 8b 81 ldd r24, Y+3 ; 0x03
e8e: 9c 81 ldd r25, Y+4 ; 0x04
e90: 88 5e subi r24, 0xE8 ; 232
e92: 93 40 sbci r25, 0x03 ; 3
e94: a8 f3 brcs .-22 ; 0xe80
e96: 89 81 ldd r24, Y+1 ; 0x01
e98: 9a 81 ldd r25, Y+2 ; 0x02
e9a: 01 96 adiw r24, 0x01 ; 1
e9c: 89 83 std Y+1, r24 ; 0x01
e9e: 9a 83 std Y+2, r25 ; 0x02
ea0: 89 81 ldd r24, Y+1 ; 0x01
ea2: 9a 81 ldd r25, Y+2 ; 0x02
ea4: 82 17 cp r24, r18
ea6: 93 07 cpc r25, r19
ea8: 20 f3 brcs .-56 ; 0xe72
}
}
#endif
}
eaa: 24 96 adiw r28, 0x04 ; 4
eac: 0f b6 in r0, 0x3f ; 63
eae: f8 94 cli
eb0: de bf out 0x3e, r29 ; 62
eb2: 0f be out 0x3f, r0 ; 63
eb4: cd bf out 0x3d, r28 ; 61
eb6: df 91 pop r29
eb8: cf 91 pop r28
eba: 08 95 ret
00000ebc <DebugInt_init>:
Inputs: none
Outputs: none
***********************************************************/
void DebugInt_init(void)
{
ebc: 1f 93 push r17
/* set PortD pin6 for output */
DDRD |= 0x40;
ebe: 8e 9a sbi 0x11, 6 ; 17
/* turn on LED */
PORTD |= 0x40;
ec0: 96 9a sbi 0x12, 6 ; 18
Utility_delay(500);
ec2: 84 ef ldi r24, 0xF4 ; 244
ec4: 91 e0 ldi r25, 0x01 ; 1
ec6: bf df rcall .-130 ; 0xe46
PORTD &= 0xBF;
ec8: 1f eb ldi r17, 0xBF ; 191
eca: 82 b3 in r24, 0x12 ; 18
ecc: 81 23 and r24, r17
ece: 82 bb out 0x12, r24 ; 18
Utility_delay(500);
ed0: 84 ef ldi r24, 0xF4 ; 244
ed2: 91 e0 ldi r25, 0x01 ; 1
ed4: b8 df rcall .-144 ; 0xe46
PORTD |= 0x40;
ed6: 96 9a sbi 0x12, 6 ; 18
Utility_delay(500);
ed8: 84 ef ldi r24, 0xF4 ; 244
eda: 91 e0 ldi r25, 0x01 ; 1
edc: b4 df rcall .-152 ; 0xe46
PORTD &= 0xBF;
ede: 82 b3 in r24, 0x12 ; 18
ee0: 81 23 and r24, r17
ee2: 82 bb out 0x12, r24 ; 18
Utility_delay(500);
ee4: 84 ef ldi r24, 0xF4 ; 244
ee6: 91 e0 ldi r25, 0x01 ; 1
ee8: ae df rcall .-164 ; 0xe46
PORTD |= 0x40;
eea: 96 9a sbi 0x12, 6 ; 18
Utility_delay(500);
eec: 84 ef ldi r24, 0xF4 ; 244
eee: 91 e0 ldi r25, 0x01 ; 1
ef0: aa df rcall .-172 ; 0xe46
PORTD &= 0xBF;
ef2: 82 b3 in r24, 0x12 ; 18
ef4: 81 23 and r24, r17
ef6: 82 bb out 0x12, r24 ; 18
Utility_delay(500);
ef8: 84 ef ldi r24, 0xF4 ; 244
efa: 91 e0 ldi r25, 0x01 ; 1
efc: a4 df rcall .-184 ; 0xe46
PORTD |= 0x40;
efe: 96 9a sbi 0x12, 6 ; 18
}
f00: 1f 91 pop r17
f02: 08 95 ret
00000f04 <CamIntAsm_waitForNewTrackingFrame>:
; set, and the function will return.
;*****************************************************************
CamIntAsm_waitForNewTrackingFrame:
sbi _SFR_IO_ADDR(PORTD),PD6 ; For testing...
f04: 96 9a sbi 0x12, 6 ; 18
cbi _SFR_IO_ADDR(PORTD),PD6
f06: 96 98 cbi 0x12, 6 ; 18
sleep
f08: 88 95 sleep
00000f0a <CamIntAsm_acquireTrackingLine>:
;*****************************************************************
; REMEMBER...everything from here on out is critically timed to be
; synchronized with the flow of pixel data from the camera...
;*****************************************************************
CamIntAsm_acquireTrackingLine:
brts _cleanUp
f0a: e6 f1 brts .+120 ; 0xf84
;sbi _SFR_IO_ADDR(PORTD),PD6 ; For testing...
;cbi _SFR_IO_ADDR(PORTD),PD6
in tmp1,_SFR_IO_ADDR(TCCR1B) ; Enable the PCLK line to actually
f0c: 3e b5 in r19, 0x2e ; 46
ori tmp1, 0x07 ; feed Timer1
f0e: 37 60 ori r19, 0x07 ; 7
out _SFR_IO_ADDR(TCCR1B),tmp1
f10: 3e bd out 0x2e, r19 ; 46
; The line is about to start...
ldi pixelCount,0 ; Initialize the RLE stats...
f12: 00 e0 ldi r16, 0x00 ; 0
ldi pixelRunStart,PIXEL_RUN_START_INITIAL ; Remember, we always calculate
f14: 10 e5 ldi r17, 0x50 ; 80
; the pixel run length as
; TCNT1L - pixelRunStart
ldi lastColor,0x00 ; clear out the last color before we start
f16: 20 e0 ldi r18, 0x00 ; 0
mov XH,currLineBuffHigh ; Load the pointer to the current line
f18: b9 2f mov r27, r25
mov XL,currLineBuffLow ; buffer into the X pointer regs
f1a: a8 2f mov r26, r24
mov ZH,colorMapHigh ; Load the pointers to the membership
f1c: f7 2f mov r31, r23
mov ZL,colorMapLow ; lookup tables (ZL and YL will be overwritten
f1e: e6 2f mov r30, r22
mov YH,colorMapHigh ; as soon as we start reading data) to Z and Y
f20: d7 2f mov r29, r23
in tmp1, _SFR_IO_ADDR(TIMSK) ; enable TIMER1 to start counting
f22: 39 b7 in r19, 0x39 ; 57
ori tmp1, ENABLE_PCLK_TIMER1_OVERFLOW_BITMASK ; external PCLK pulses and interrupt on
f24: 34 60 ori r19, 0x04 ; 4
out _SFR_IO_ADDR(TIMSK),tmp1 ; overflow
f26: 39 bf out 0x39, r19 ; 57
ldi tmp1,PIXEL_RUN_START_INITIAL ; set up the TCNT1 to overflow (and
f28: 30 e5 ldi r19, 0x50 ; 80
ldi tmp2,0xFF ; interrupts) after 176 pixels
f2a: 4f ef ldi r20, 0xFF ; 255
out _SFR_IO_ADDR(TCNT1H),tmp2
f2c: 4d bd out 0x2d, r20 ; 45
out _SFR_IO_ADDR(TCNT1L),tmp1
f2e: 3c bd out 0x2c, r19 ; 44
mov YL,colorMapLow
f30: c6 2f mov r28, r22
in tmp1, _SFR_IO_ADDR(GICR) ; enable the HREF interrupt...remember, we
f32: 3b b7 in r19, 0x3b ; 59
; only use this interrupt to synchronize
; the beginning of the line
ori tmp1, HREF_INTERRUPT_ENABLE_MASK
f34: 30 68 ori r19, 0x80 ; 128
out _SFR_IO_ADDR(GICR), tmp1
f36: 3b bf out 0x3b, r19 ; 59
00000f38 <_trackFrame>:
;*******************************************************************************************
; Track Frame handler
;*******************************************************************************************
_trackFrame:
sbi _SFR_IO_ADDR(PORTD),PD6
f38: 96 9a sbi 0x12, 6 ; 18
sleep ; ...And we wait...
f3a: 88 95 sleep
; Returning from the interrupt/sleep wakeup will consume
; 14 clock cycles (7 to wakeup from idle sleep, 3 to vector, and 4 to return)
; Disable the HREF interrupt
cbi _SFR_IO_ADDR(PORTD),PD6
f3c: 96 98 cbi 0x12, 6 ; 18
in tmp1, _SFR_IO_ADDR(GICR)
f3e: 3b b7 in r19, 0x3b ; 59
andi tmp1, HREF_INTERRUPT_DISABLE_MASK
f40: 3f 77 andi r19, 0x7F ; 127
out _SFR_IO_ADDR(GICR), tmp1
f42: 3b bf out 0x3b, r19 ; 59
; A couple of NOPs are needed here to sync up the pixel data...the number (2)
; of NOPs was determined emperically by trial and error.
nop
f44: 00 00 nop
...
00000f48 <_acquirePixelBlock>:
nop
_acquirePixelBlock: ; Clock Cycle Count
in ZL,RB_PORT ; sample the red value (PINB) (1)
f48: e6 b3 in r30, 0x16 ; 22
in YL,G_PORT ; sample the green value (PINC) (1)
f4a: c3 b3 in r28, 0x13 ; 19
andi YL,0x0F ; clear the high nibble (1)
f4c: cf 70 andi r28, 0x0F ; 15
ldd color,Z+RED_MEM_OFFSET ; lookup the red membership (2)
f4e: 30 81 ld r19, Z
in ZL,RB_PORT ; sample the blue value (PINB) (1)
f50: e6 b3 in r30, 0x16 ; 22
ldd greenData,Y+GREEN_MEM_OFFSET; lookup the green membership (2)
f52: 48 89 ldd r20, Y+16 ; 0x10
ldd blueData,Z+BLUE_MEM_OFFSET ; lookup the blue membership (2)
f54: 50 a1 ldd r21, Z+32 ; 0x20
and color,greenData ; mask memberships together (1)
f56: 34 23 and r19, r20
and color,blueData ; to produce the final color (1)
f58: 35 23 and r19, r21
brts _cleanUpTrackingLine ; if some interrupt routine has (1...not set)
f5a: 76 f0 brts .+28 ; 0xf78
; come in and set our T flag in
; SREG, then we need to hop out
; and blow away this frames data (common cleanup)
cp color,lastColor ; check to see if the run continues (1)
f5c: 32 17 cp r19, r18
breq _acquirePixelBlock ; (2...equal)
f5e: a1 f3 breq .-24 ; 0xf48
; ___________
; 16 clock cycles
; (16 clock cycles = 1 uS = 1 pixelBlock time)
; Toggle the debug line to indicate a color change
sbi _SFR_IO_ADDR(PORTD),PD6
f60: 96 9a sbi 0x12, 6 ; 18
nop
f62: 00 00 nop
cbi _SFR_IO_ADDR(PORTD),PD6
f64: 96 98 cbi 0x12, 6 ; 18
mov tmp2,pixelRunStart ; get the count value of the
f66: 41 2f mov r20, r17
; current pixel run
in pixelCount,_SFR_IO_ADDR(TCNT1L) ; get the current TCNT1 value
f68: 0c b5 in r16, 0x2c ; 44
mov pixelRunStart,pixelCount ; reload pixelRunStart for the
f6a: 10 2f mov r17, r16
; next run
sub pixelCount,tmp2 ; pixelCount = TCNT1L - pixelRunStart
f6c: 04 1b sub r16, r20
st X+,lastColor ; record the color run in the current line buffer
f6e: 2d 93 st X+, r18
st X+,pixelCount ; with its length
f70: 0d 93 st X+, r16
mov lastColor,color ; set lastColor so we can figure out when it changes
f72: 23 2f mov r18, r19
nop ; waste one more cycle for a total of 16
f74: 00 00 nop
rjmp _acquirePixelBlock
f76: e8 cf rjmp .-48 ; 0xf48
00000f78 <_cleanUpTrackingLine>:
; _cleanUpTrackingLine is used to write the last run length block off to the currentLineBuffer so
; that all 176 pixels in the line are accounted for.
_cleanUpTrackingLine:
ldi pixelCount,0xFF ; the length of the last run is ALWAYS 0xFF minus the last
f78: 0f ef ldi r16, 0xFF ; 255
sub pixelCount,pixelRunStart ; pixelRunStart
f7a: 01 1b sub r16, r17
inc pixelCount ; increment pixelCount since we actually need to account
f7c: 03 95 inc r16
; for the overflow of TCNT1
st X+,color ; record the color run in the current line buffer
f7e: 3d 93 st X+, r19
st X,pixelCount
f80: 0c 93 st X, r16
rjmp _cleanUp
f82: 00 c0 rjmp .+0 ; 0xf84
00000f84 <_cleanUp>:
_cleanUpDumpLine:
; NOTE: If serial data is received, to interrupt the tracking of a line, we'll
; get a EV_SERIAL_DATA_RECEIVED event, and the T bit set so we will end the
; line's processing...however, the PCLK will keep on ticking for the rest of
; the frame/line, which will cause the TCNT to eventually overflow and
; interrupt us, generating a EV_ACQUIRE_LINE_COMPLETE event. We don't want
; this, so we need to actually turn off the PCLK counting each time we exit
; this loop, and only turn it on when we begin acquiring lines....
; NOT NEEDED FOR NOW...
;in tmp1, _SFR_IO_ADDR(TIMSK) ; disable TIMER1 to stop counting
;andi tmp1, DISABLE_PCLK_TIMER1_OVERFLOW_BITMASK ; external PCLK pulses
;out _SFR_IO_ADDR(TIMSK),tmp1
_cleanUp:
; Disable the external clocking of the Timer1 counter
in tmp1, _SFR_IO_ADDR(TCCR1B)
f84: 3e b5 in r19, 0x2e ; 46
andi tmp1, 0xF8
f86: 38 7f andi r19, 0xF8 ; 248
out _SFR_IO_ADDR(TCCR1B),tmp1
f88: 3e bd out 0x2e, r19 ; 46
; Toggle the debug line to indicate the line is complete
sbi _SFR_IO_ADDR(PORTD),PD6
f8a: 96 9a sbi 0x12, 6 ; 18
cbi _SFR_IO_ADDR(PORTD),PD6
f8c: 96 98 cbi 0x12, 6 ; 18
clt ; clear out the T bit since we have detected
f8e: e8 94 clt
00000f90 <_exit>:
; the interruption and are exiting to handle it
_exit:
ret
f90: 08 95 ret
00000f92 <CamIntAsm_waitForNewDumpFrame>:
;*****************************************************************
; Function Name: CamIntAsm_waitForNewDumpFrame
; Function Description: This function is responsible for
; going to sleep until a new frame begins (indicated by
; VSYNC transitioning from low to high. This will wake
; the "VSYNC sleep" up and allow it to continue with
; acquiring a line of pixel data to dump out to the UI.
; Inputs: r25 - MSB of currentLineBuffer
; r24 - LSB of currentLineBuffer
; r23 - MSB of prevLineBuffer
; r22 - LSB of prevLineBuffer
; Outputs: none
; NOTES: This function doesn't really return...it sorta just
; floats into the acquireDumpLine function after the "VSYNC sleep"
; is awoken.
;*****************************************************************
CamIntAsm_waitForNewDumpFrame:
sbi _SFR_IO_ADDR(PORTD),PD6 ; For testing...
f92: 96 9a sbi 0x12, 6 ; 18
cbi _SFR_IO_ADDR(PORTD),PD6
f94: 96 98 cbi 0x12, 6 ; 18
sleep
f96: 88 95 sleep
00000f98 <CamIntAsm_acquireDumpLine>:
;*****************************************************************
; REMEMBER...everything from here on out is critically timed to be
; synchronized with the flow of pixel data from the camera...
;*****************************************************************
CamIntAsm_acquireDumpLine:
brts _cleanUp
f98: ae f3 brts .-22 ; 0xf84
;sbi _SFR_IO_ADDR(PORTD),PD6 ; For testing...
;cbi _SFR_IO_ADDR(PORTD),PD6
mov XH,currLineBuffHigh ; Load the pointer to the current line
f9a: b9 2f mov r27, r25
mov XL,currLineBuffLow ; buffer into the X pointer regs
f9c: a8 2f mov r26, r24
mov YH,prevLineBuffHigh ; Load the pointer to the previous line
f9e: d7 2f mov r29, r23
mov YL,prevLineBuffLow ; buffer into the Y pointer regs
fa0: c6 2f mov r28, r22
ldi tmp1,PIXEL_RUN_START_INITIAL ; set up the TCNT1 to overflow (and
fa2: 30 e5 ldi r19, 0x50 ; 80
ldi tmp2,0xFF ; interrupts) after 176 pixels
fa4: 4f ef ldi r20, 0xFF ; 255
out _SFR_IO_ADDR(TCNT1H),tmp2
fa6: 4d bd out 0x2d, r20 ; 45
out _SFR_IO_ADDR(TCNT1L),tmp1
fa8: 3c bd out 0x2c, r19 ; 44
in tmp1, _SFR_IO_ADDR(TCCR1B) ; Enable the PCLK line to actually
faa: 3e b5 in r19, 0x2e ; 46
ori tmp1, 0x07 ; feed Timer1
fac: 37 60 ori r19, 0x07 ; 7
out _SFR_IO_ADDR(TCCR1B),tmp1
fae: 3e bd out 0x2e, r19 ; 46
nop
fb0: 00 00 nop
in tmp1, _SFR_IO_ADDR(TIMSK) ; enable TIMER1 to start counting
fb2: 39 b7 in r19, 0x39 ; 57
ori tmp1, ENABLE_PCLK_TIMER1_OVERFLOW_BITMASK ; external PCLK pulses and interrupt on
fb4: 34 60 ori r19, 0x04 ; 4
out _SFR_IO_ADDR(TIMSK),tmp1 ; overflow
fb6: 39 bf out 0x39, r19 ; 57
in tmp1, _SFR_IO_ADDR(GICR) ; enable the HREF interrupt...remember, we
fb8: 3b b7 in r19, 0x3b ; 59
; only use this interrupt to synchronize
; the beginning of the line
ori tmp1, HREF_INTERRUPT_ENABLE_MASK
fba: 30 68 ori r19, 0x80 ; 128
out _SFR_IO_ADDR(GICR), tmp1
fbc: 3b bf out 0x3b, r19 ; 59
00000fbe <_dumpFrame>:
;*******************************************************************************************
; Dump Frame handler
;*******************************************************************************************
_dumpFrame:
sbi _SFR_IO_ADDR(PORTD),PD6
fbe: 96 9a sbi 0x12, 6 ; 18
sleep ; ...And we wait...
fc0: 88 95 sleep
cbi _SFR_IO_ADDR(PORTD),PD6
fc2: 96 98 cbi 0x12, 6 ; 18
in tmp1, _SFR_IO_ADDR(GICR) ; disable the HREF interrupt
fc4: 3b b7 in r19, 0x3b ; 59
andi tmp1, HREF_INTERRUPT_DISABLE_MASK ; so we don't get interrupted
fc6: 3f 77 andi r19, 0x7F ; 127
out _SFR_IO_ADDR(GICR), tmp1 ; while dumping the line
fc8: 3b bf out 0x3b, r19 ; 59
...
00000fcc <_sampleDumpPixel>:
nop ; Remember...if we ever remove the "cbi" instruction above,
; we need to add two more NOPs to cover this
; Ok...the following loop needs to run in 8 clock cycles, so we can get every
; pixel in the line...this shouldn't be a problem, since the PCLK timing was
; reduced by a factor of 2 whenever we go to dump a line (this is to give us
; enough time to do the sampling and storing of the pixel data). In addition,
; it is assumed that we will have to do some minor processing on the data right
; before we send it out, like mask off the top 4-bits of each, and then pack both
; low nibbles into a single byte for transmission...we just don't have time to
; do that here (only 8 instruction cycles :-) )
_sampleDumpPixel:
in tmp1,G_PORT ; sample the G value (1)
fcc: 33 b3 in r19, 0x13 ; 19
in tmp2,RB_PORT ; sample the R/B value (1)
fce: 46 b3 in r20, 0x16 ; 22
st X+,tmp1 ; store to the currLineBuff and inc ptrs(2)
fd0: 3d 93 st X+, r19
st Y+,tmp2 ; store to the prevLineBuff and inc ptrs(2)
fd2: 49 93 st Y+, r20
brtc _sampleDumpPixel ; loop back unless flag is set (2...if not set)
fd4: de f7 brtc .-10 ; 0xfcc
; ___________
; 8 cycles normally
; if we make it here, it means the T flag is set, and we must have been interrupted
; so we need to exit (what if we were interrupted for serial? should we disable it?)
rjmp _cleanUpDumpLine
fd6: d6 cf rjmp .-84 ; 0xf84
00000fd8 <__vector_1>:
;***********************************************************
; Function Name: <interrupt handler for External Interrupt0>
; Function Description: This function is responsible
; for handling a rising edge on the Ext Interrupt 0. This
; routine simply returns, since we just want to wake up
; whenever the VSYNC transitions (meaning the start of a new
; frame).
; Inputs: none
; Outputs: none
;***********************************************************
SIG_INTERRUPT0:
; This will wake us up when VSYNC transitions high...we just want to return
reti
fd8: 18 95 reti
00000fda <__vector_2>:
;***********************************************************
; Function Name: <interrupt handler for External Interrupt1>
; Function Description: This function is responsible
; for handling a falling edge on the Ext Interrupt 1. This
; routine simply returns, since we just want to wake up
; whenever the HREF transitions (meaning the pixels
; are starting after VSYNC transitioned, and we need to
; start acquiring the pixel blocks
; Inputs: none
; Outputs: none
;***********************************************************
SIG_INTERRUPT1:
; This will wake us up when HREF transitions high...we just want to return
reti
fda: 18 95 reti
00000fdc <__vector_8>:
;***********************************************************
; Function Name: <interrupt handler for Timer0 overflow>
; Function Description: This function is responsible
; for handling the Timer0 overflow (hooked up to indicate
; when we have reached the number of HREFs required in a
; single frame). We set the T flag in the SREG to
; indicate to the _acquirePixelBlock routine that it needs
; to exit, and then set the appropriate action to take in
; the eventList of the Executive module.
; Inputs: none
; Outputs: none
; Note: Originally, the HREF pulses were also going to
; be counted by a hardware counter, but it didn't end up
; being necessary
;***********************************************************
;SIG_OVERFLOW0:
; set ; set the T bit in SREG
; lds tmp1,eventBitmask
; ori tmp1,EV_ACQUIRE_FRAME_COMPLETE
; sts eventBitmask,tmp1
; reti
;***********************************************************
; Function Name: <interrupt handler for Timer1 overflow>
; Function Description: This function is responsible
; for handling the Timer1 overflow (hooked up to indicate
; when we have reached the end of a line of pixel data,
; since PCLK is hooked up to overflow TCNT1 after 176
; pixels). This routine generates an acquire line complete
; event in the fastEventBitmask, which is streamlined for
; efficiency reasons.
;***********************************************************
SIG_OVERFLOW1:
lds tmp1,fastEventBitmask ; set a flag indicating
fdc: 30 91 72 00 lds r19, 0x0072
ori tmp1,FEV_ACQUIRE_LINE_COMPLETE ; a line is complete
fe0: 31 60 ori r19, 0x01 ; 1
sts fastEventBitmask,tmp1
fe2: 30 93 72 00 sts 0x0072, r19
set ; set the T bit in SREG
fe6: 68 94 set
;sbi _SFR_IO_ADDR(PORTD),PD6 ; For testing...
;cbi _SFR_IO_ADDR(PORTD),PD6 ; For testing...
reti
fe8: 18 95 reti
00000fea <__vector_default>:
; This is the default handler for all interrupts that don't
; have handler routines specified for them.
.global __vector_default
__vector_default:
reti
fea: 18 95 reti
00000fec <atoi>:
fec: fc 01 movw r30, r24
fee: 88 27 eor r24, r24
ff0: 99 27 eor r25, r25
ff2: e8 94 clt
00000ff4 <.atoi_loop>:
ff4: 21 91 ld r18, Z+
ff6: 22 23 and r18, r18
ff8: e9 f0 breq .+58 ; 0x1034
ffa: 20 32 cpi r18, 0x20 ; 32
ffc: d9 f3 breq .-10 ; 0xff4
ffe: 29 30 cpi r18, 0x09 ; 9
1000: c9 f3 breq .-14 ; 0xff4
1002: 2a 30 cpi r18, 0x0A ; 10
1004: b9 f3 breq .-18 ; 0xff4
1006: 2c 30 cpi r18, 0x0C ; 12
1008: a9 f3 breq .-22 ; 0xff4
100a: 2d 30 cpi r18, 0x0D ; 13
100c: 99 f3 breq .-26 ; 0xff4
100e: 26 37 cpi r18, 0x76 ; 118
1010: 89 f3 breq .-30 ; 0xff4
1012: 2b 32 cpi r18, 0x2B ; 43
1014: 19 f0 breq .+6 ; 0x101c
1016: 2d 32 cpi r18, 0x2D ; 45
1018: 21 f4 brne .+8 ; 0x1022
0000101a <.atoi_neg>:
101a: 68 94 set
0000101c <.atoi_loop2>:
101c: 21 91 ld r18, Z+
101e: 22 23 and r18, r18
1020: 49 f0 breq .+18 ; 0x1034
00001022 <.atoi_digit>:
1022: 20 33 cpi r18, 0x30 ; 48
1024: 3c f0 brlt .+14 ; 0x1034
1026: 2a 33 cpi r18, 0x3A ; 58
1028: 2c f4 brge .+10 ; 0x1034
102a: 20 53 subi r18, 0x30 ; 48
102c: 2f d0 rcall .+94 ; 0x108c
102e: 82 0f add r24, r18
1030: 91 1d adc r25, r1
1032: f4 cf rjmp .-24 ; 0x101c
00001034 <.atoi_sig>:
1034: 81 15 cp r24, r1
1036: 91 05 cpc r25, r1
1038: 21 f0 breq .+8 ; 0x1042
103a: 1e f4 brtc .+6 ; 0x1042
103c: 80 95 com r24
103e: 90 95 com r25
1040: 01 96 adiw r24, 0x01 ; 1
00001042 <.atoi_done>:
1042: 08 95 ret
00001044 <eeprom_read_byte>:
1044: e1 99 sbic 0x1c, 1 ; 28
1046: fe cf rjmp .-4 ; 0x1044
1048: 9f bb out 0x1f, r25 ; 31
104a: 8e bb out 0x1e, r24 ; 30
104c: e0 9a sbi 0x1c, 0 ; 28
104e: 99 27 eor r25, r25
1050: 8d b3 in r24, 0x1d ; 29
1052: 08 95 ret
00001054 <eeprom_read_block>:
1054: 41 15 cp r20, r1
1056: 51 05 cpc r21, r1
1058: 69 f0 breq .+26 ; 0x1074
105a: dc 01 movw r26, r24
0000105c <eeprom_read_block_busy>:
105c: e1 99 sbic 0x1c, 1 ; 28
105e: fe cf rjmp .-4 ; 0x105c
00001060 <eeprom_read_block_loop>:
1060: 7f bb out 0x1f, r23 ; 31
1062: 6e bb out 0x1e, r22 ; 30
1064: e0 9a sbi 0x1c, 0 ; 28
1066: 6f 5f subi r22, 0xFF ; 255
1068: 7f 4f sbci r23, 0xFF ; 255
106a: 0d b2 in r0, 0x1d ; 29
106c: 0d 92 st X+, r0
106e: 41 50 subi r20, 0x01 ; 1
1070: 50 40 sbci r21, 0x00 ; 0
1072: b1 f7 brne .-20 ; 0x1060
00001074 <eeprom_read_block_done>:
1074: 08 95 ret
00001076 <eeprom_write_byte>:
1076: e1 99 sbic 0x1c, 1 ; 28
1078: fe cf rjmp .-4 ; 0x1076
107a: 9f bb out 0x1f, r25 ; 31
107c: 8e bb out 0x1e, r24 ; 30
107e: 6d bb out 0x1d, r22 ; 29
1080: 0f b6 in r0, 0x3f ; 63
1082: f8 94 cli
1084: e2 9a sbi 0x1c, 2 ; 28
1086: e1 9a sbi 0x1c, 1 ; 28
1088: 0f be out 0x3f, r0 ; 63
108a: 08 95 ret
0000108c <__mulhi_const_10>:
108c: 7a e0 ldi r23, 0x0A ; 10
108e: 97 9f mul r25, r23
1090: 90 2d mov r25, r0
1092: 87 9f mul r24, r23
1094: 80 2d mov r24, r0
1096: 91 0d add r25, r1
1098: 11 24 eor r1, r1
109a: 08 95 ret
0000109c <_exit>:
109c: ff cf rjmp .-2 ; 0x109c