151 |
kaklik |
1 |
;
|
|
|
2 |
; Copyright (C) 2004 John Orlando
|
|
|
3 |
;
|
|
|
4 |
; AVRcam: a small real-time image processing engine.
|
|
|
5 |
|
|
|
6 |
; This program is free software; you can redistribute it and/or
|
|
|
7 |
; modify it under the terms of the GNU General Public
|
|
|
8 |
; License as published by the Free Software Foundation; either
|
|
|
9 |
; version 2 of the License, or (at your option) any later version.
|
|
|
10 |
|
|
|
11 |
; This program is distributed in the hope that it will be useful,
|
|
|
12 |
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
13 |
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
14 |
; General Public License for more details.
|
|
|
15 |
|
|
|
16 |
; You should have received a copy of the GNU General Public
|
|
|
17 |
; License along with this program; if not, write to the Free Software
|
|
|
18 |
; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
19 |
|
|
|
20 |
; For more information on the AVRcam, please contact:
|
|
|
21 |
|
|
|
22 |
; john@jrobot.net
|
|
|
23 |
|
|
|
24 |
; or go to www.jrobot.net for more details regarding the system.
|
|
|
25 |
;**********************************************************************
|
|
|
26 |
; Module Name: CanInterfaceAsm.S
|
|
|
27 |
; Module Date: 04/14/2004
|
|
|
28 |
; Module Auth: John Orlando
|
|
|
29 |
;
|
|
|
30 |
; Description: This module provides the low-level interface
|
|
|
31 |
; to the OV6620 camera hardware. It is responsible for
|
|
|
32 |
; acquiring each pixel block (R,G,B), performing the mapping
|
|
|
33 |
; into an actual color (orange, purple, etc), run-length
|
|
|
34 |
; encoding the data, and storing the info off to the appropriate
|
|
|
35 |
; line buffer. This routine is synchronized with the pixel data
|
|
|
36 |
; so that no polling of the camera data needs to be done (the
|
|
|
37 |
; OV6620 is clocked off of the same crystal source as the mega8,
|
|
|
38 |
; thus providing inherent synchronization between the two).
|
|
|
39 |
;
|
|
|
40 |
; Revision History:
|
|
|
41 |
; Date Rel Ver. Notes
|
|
|
42 |
; 4/10/2004 0.1 Module created
|
|
|
43 |
; 6/30/2004 1.0 Initial release for Circuit Cellar
|
|
|
44 |
; contest.
|
|
|
45 |
; 1/16/2005 1.4 Fixed issue with the TCCR1B register
|
|
|
46 |
; where PCLK was getting routed to the
|
|
|
47 |
; timer1 even when it wasn't needed.
|
|
|
48 |
; This caused excessive counter overflow
|
|
|
49 |
; interrupts, and caused problems. Now,
|
|
|
50 |
; the "PCLK" pipe feeds timer1 when needed,
|
|
|
51 |
; and is turned off when it isn't needed.
|
|
|
52 |
|
|
|
53 |
#include <avr/io.h>
|
|
|
54 |
#include "Events.h"
|
|
|
55 |
|
|
|
56 |
.extern fastEventBitmask ; This is the flag used to indicate to the rest
|
|
|
57 |
; of the system that the line is complete
|
|
|
58 |
|
|
|
59 |
#define HREF_INTERRUPT_ENABLE_MASK 0x80
|
|
|
60 |
#define HREF_INTERRUPT_DISABLE_MASK 0x7F
|
|
|
61 |
#define ENABLE_PCLK_TIMER1_OVERFLOW_BITMASK 0x04
|
|
|
62 |
#define DISABLE_PCLK_TIMER1_OVERFLOW_BITMASK 0xFB
|
|
|
63 |
#define G_PORT _SFR_IO_ADDR(PINC)
|
|
|
64 |
#define RB_PORT _SFR_IO_ADDR(PINB)
|
|
|
65 |
#define PIXEL_RUN_START_INITIAL 0x50 ; This value causes our pixel counter (TCNT1)
|
|
|
66 |
; to overflow after 176 (horizontal) pixels
|
|
|
67 |
|
|
|
68 |
#define RED_MEM_OFFSET 0x00
|
|
|
69 |
#define GREEN_MEM_OFFSET 0x10
|
|
|
70 |
#define BLUE_MEM_OFFSET 0x20
|
|
|
71 |
|
|
|
72 |
; A pixelBlock is defined as a contiguous group of 4 pixels that are combined
|
|
|
73 |
; together to form a specific color. Typically, this is formed by sampling a
|
|
|
74 |
; a green value, followed by a red and blue value (since we are dealing
|
|
|
75 |
; with Bayer color data). We could optionally sample a second green with
|
|
|
76 |
; the red and average the greens, because the eye is more sensitive to
|
|
|
77 |
; green, but for speed we don't do this. These three values (RGB) are then
|
|
|
78 |
; used as indices into the color membership lookup table (memLookup) to
|
|
|
79 |
; determine which color the pixelBlock maps into. The memLookup table is
|
|
|
80 |
; manually generated for now (though it will hopefully be modified over
|
|
|
81 |
; the serial interface eventually).
|
|
|
82 |
;
|
|
|
83 |
; Here is a pixel block:
|
|
|
84 |
; ...G G G G... (row x)
|
|
|
85 |
; ...B R B R... (row x+1)
|
|
|
86 |
; | | | |--this is skipped
|
|
|
87 |
; | | |--this is skipped
|
|
|
88 |
; | |--this is sampled
|
|
|
89 |
; |--this is sampled
|
|
|
90 |
|
|
|
91 |
; As pixel blocks are sampled, the red, green, and blue values are
|
|
|
92 |
; used to index into their respective color maps. The color maps
|
|
|
93 |
; return values that can be logically ANDed together so that a
|
|
|
94 |
; particular RGB triplet will result in a single bit being set
|
|
|
95 |
; after the AND operation. This single bit indicates which color
|
|
|
96 |
; the RGB triplet represents. It is also possible for no bits to
|
|
|
97 |
; be set after the AND process, indicating that the RGB triplet
|
|
|
98 |
; does not map to any of the colors configured in the color map.
|
|
|
99 |
; This isn't quite as fast as a pure RGB lookup table, but
|
|
|
100 |
; it then again it doesn't require 2^12 (4-bits for each color
|
|
|
101 |
; channel) bytes to store the lookup table. It takes just a few
|
|
|
102 |
; more cycles, and only requires 48 bytes of precious RAM (16
|
|
|
103 |
; per color channel, since our resolution on each color channel
|
|
|
104 |
; is only 4-bits). Not bad....for more information, see:
|
|
|
105 |
; http://www.cs.cmu.edu/~trb/papers/wirevision00.pdf for more
|
|
|
106 |
; information on this color segmentation technique.
|
|
|
107 |
|
|
|
108 |
; One other note: this code does depend on the colorMap residing
|
|
|
109 |
; at a well-defined position in memory; specifically, it mus
|
|
|
110 |
; start at a 256-byte boundary so that the lowest byte in the
|
|
|
111 |
; map is set to 0x00. Currently, the colorMap is forced to
|
|
|
112 |
; start at RAM location 0x300. This could potentially be changed
|
|
|
113 |
; by the developer if needed, but offsets would have to be added
|
|
|
114 |
; in to the colorMap look-up code below to make it work.
|
|
|
115 |
|
|
|
116 |
|
|
|
117 |
; These are the registers that will be used throughout this
|
|
|
118 |
; module for acquiring each line of pixel data
|
|
|
119 |
pixelCount = 16
|
|
|
120 |
pixelRunStart = 17
|
|
|
121 |
lastColor = 18
|
|
|
122 |
tmp1 = 19 ; be sure to not use tmp1 and color simultaneously
|
|
|
123 |
tmp2 = 20
|
|
|
124 |
color = 19
|
|
|
125 |
greenData = 20
|
|
|
126 |
blueData = 21
|
|
|
127 |
colorMapLow = 22
|
|
|
128 |
colorMapHigh = 23
|
|
|
129 |
prevLineBuffLow = 22 ; overlaps with memLookupLow (but orthogonal)
|
|
|
130 |
prevLineBuffHigh = 23 ; overlaps with memLookupHigh (but orthogonal)
|
|
|
131 |
currLineBuffLow = 24
|
|
|
132 |
currLineBuffHigh = 25
|
|
|
133 |
|
|
|
134 |
.section .text
|
|
|
135 |
|
|
|
136 |
; These are the global assembly function names that are accessed via other
|
|
|
137 |
; C functions
|
|
|
138 |
.global CamIntAsm_waitForNewTrackingFrame
|
|
|
139 |
.global CamIntAsm_waitForNewDumpFrame
|
|
|
140 |
.global CamIntAsm_acquireDumpLine
|
|
|
141 |
.global CamIntAsm_acquireTrackingLine
|
|
|
142 |
.global SIG_INTERRUPT0
|
|
|
143 |
.global SIG_INTERRUPT1
|
|
|
144 |
.global SIG_OVERFLOW0
|
|
|
145 |
.global SIG_OVERFLOW1
|
|
|
146 |
|
|
|
147 |
;*****************************************************************
|
|
|
148 |
; Function Name: CamIntAsm_waitForNewTrackingFrame
|
|
|
149 |
; Function Description: This function is responsible for
|
|
|
150 |
; going to sleep until a new frame begins (indicated by
|
|
|
151 |
; VSYNC transitioning from low to high. This will wake
|
|
|
152 |
; the "VSYNC sleep" up and allow it to continue with
|
|
|
153 |
; the acquireLine function, where the system waits for
|
|
|
154 |
; an "HREF sleep" that we use to synchronize with the
|
|
|
155 |
; data.
|
|
|
156 |
; Inputs: r25 - MSB of currentLineBuffer
|
|
|
157 |
; r24 - LSB of currentLineBuffer
|
|
|
158 |
; r23 - MSB of colorMap
|
|
|
159 |
; r22 - LSB of colorMap
|
|
|
160 |
; Outputs: none
|
|
|
161 |
; NOTES: This function doesn't really return...it sorta just
|
|
|
162 |
; floats into the acquireLine function after the "VSYNC sleep"
|
|
|
163 |
; is awoken, then begins processing the line data. Once
|
|
|
164 |
; 176 pixels are sampled (and the counter overflows), then
|
|
|
165 |
; an interrupt will occur, the 'T' bit in the SREG will be
|
|
|
166 |
; set, and the function will return.
|
|
|
167 |
;*****************************************************************
|
|
|
168 |
|
|
|
169 |
CamIntAsm_waitForNewTrackingFrame:
|
|
|
170 |
sbi _SFR_IO_ADDR(PORTD),PD6 ; For testing...
|
|
|
171 |
cbi _SFR_IO_ADDR(PORTD),PD6
|
|
|
172 |
sleep
|
|
|
173 |
|
|
|
174 |
;*****************************************************************
|
|
|
175 |
; REMEMBER...everything from here on out is critically timed to be
|
|
|
176 |
; synchronized with the flow of pixel data from the camera...
|
|
|
177 |
;*****************************************************************
|
|
|
178 |
|
|
|
179 |
CamIntAsm_acquireTrackingLine:
|
|
|
180 |
brts _cleanUp
|
|
|
181 |
;sbi _SFR_IO_ADDR(PORTD),PD6 ; For testing...
|
|
|
182 |
;cbi _SFR_IO_ADDR(PORTD),PD6
|
|
|
183 |
|
|
|
184 |
in tmp1,_SFR_IO_ADDR(TCCR1B) ; Enable the PCLK line to actually
|
|
|
185 |
ori tmp1, 0x07 ; feed Timer1
|
|
|
186 |
out _SFR_IO_ADDR(TCCR1B),tmp1
|
|
|
187 |
; The line is about to start...
|
|
|
188 |
ldi pixelCount,0 ; Initialize the RLE stats...
|
|
|
189 |
ldi pixelRunStart,PIXEL_RUN_START_INITIAL ; Remember, we always calculate
|
|
|
190 |
; the pixel run length as
|
|
|
191 |
; TCNT1L - pixelRunStart
|
|
|
192 |
|
|
|
193 |
ldi lastColor,0x00 ; clear out the last color before we start
|
|
|
194 |
|
|
|
195 |
mov XH,currLineBuffHigh ; Load the pointer to the current line
|
|
|
196 |
mov XL,currLineBuffLow ; buffer into the X pointer regs
|
|
|
197 |
|
|
|
198 |
mov ZH,colorMapHigh ; Load the pointers to the membership
|
|
|
199 |
mov ZL,colorMapLow ; lookup tables (ZL and YL will be overwritten
|
|
|
200 |
mov YH,colorMapHigh ; as soon as we start reading data) to Z and Y
|
|
|
201 |
|
|
|
202 |
in tmp1, _SFR_IO_ADDR(TIMSK) ; enable TIMER1 to start counting
|
|
|
203 |
ori tmp1, ENABLE_PCLK_TIMER1_OVERFLOW_BITMASK ; external PCLK pulses and interrupt on
|
|
|
204 |
out _SFR_IO_ADDR(TIMSK),tmp1 ; overflow
|
|
|
205 |
|
|
|
206 |
ldi tmp1,PIXEL_RUN_START_INITIAL ; set up the TCNT1 to overflow (and
|
|
|
207 |
ldi tmp2,0xFF ; interrupts) after 176 pixels
|
|
|
208 |
out _SFR_IO_ADDR(TCNT1H),tmp2
|
|
|
209 |
out _SFR_IO_ADDR(TCNT1L),tmp1
|
|
|
210 |
|
|
|
211 |
mov YL,colorMapLow
|
|
|
212 |
|
|
|
213 |
in tmp1, _SFR_IO_ADDR(GICR) ; enable the HREF interrupt...remember, we
|
|
|
214 |
; only use this interrupt to synchronize
|
|
|
215 |
; the beginning of the line
|
|
|
216 |
ori tmp1, HREF_INTERRUPT_ENABLE_MASK
|
|
|
217 |
out _SFR_IO_ADDR(GICR), tmp1
|
|
|
218 |
|
|
|
219 |
;*******************************************************************************************
|
|
|
220 |
; Track Frame handler
|
|
|
221 |
;*******************************************************************************************
|
|
|
222 |
|
|
|
223 |
_trackFrame:
|
|
|
224 |
sbi _SFR_IO_ADDR(PORTD),PD6
|
|
|
225 |
sleep ; ...And we wait...
|
|
|
226 |
|
|
|
227 |
; Returning from the interrupt/sleep wakeup will consume
|
|
|
228 |
; 14 clock cycles (7 to wakeup from idle sleep, 3 to vector, and 4 to return)
|
|
|
229 |
|
|
|
230 |
; Disable the HREF interrupt
|
|
|
231 |
cbi _SFR_IO_ADDR(PORTD),PD6
|
|
|
232 |
in tmp1, _SFR_IO_ADDR(GICR)
|
|
|
233 |
andi tmp1, HREF_INTERRUPT_DISABLE_MASK
|
|
|
234 |
out _SFR_IO_ADDR(GICR), tmp1
|
|
|
235 |
|
|
|
236 |
; A couple of NOPs are needed here to sync up the pixel data...the number (2)
|
|
|
237 |
; of NOPs was determined emperically by trial and error.
|
|
|
238 |
nop
|
|
|
239 |
nop
|
|
|
240 |
_acquirePixelBlock: ; Clock Cycle Count
|
|
|
241 |
in ZL,RB_PORT ; sample the red value (PINB) (1)
|
|
|
242 |
in YL,G_PORT ; sample the green value (PINC) (1)
|
|
|
243 |
andi YL,0x0F ; clear the high nibble (1)
|
|
|
244 |
ldd color,Z+RED_MEM_OFFSET ; lookup the red membership (2)
|
|
|
245 |
in ZL,RB_PORT ; sample the blue value (PINB) (1)
|
|
|
246 |
ldd greenData,Y+GREEN_MEM_OFFSET; lookup the green membership (2)
|
|
|
247 |
ldd blueData,Z+BLUE_MEM_OFFSET ; lookup the blue membership (2)
|
|
|
248 |
and color,greenData ; mask memberships together (1)
|
|
|
249 |
and color,blueData ; to produce the final color (1)
|
|
|
250 |
brts _cleanUpTrackingLine ; if some interrupt routine has (1...not set)
|
|
|
251 |
; come in and set our T flag in
|
|
|
252 |
; SREG, then we need to hop out
|
|
|
253 |
; and blow away this frames data (common cleanup)
|
|
|
254 |
cp color,lastColor ; check to see if the run continues (1)
|
|
|
255 |
breq _acquirePixelBlock ; (2...equal)
|
|
|
256 |
; ___________
|
|
|
257 |
; 16 clock cycles
|
|
|
258 |
; (16 clock cycles = 1 uS = 1 pixelBlock time)
|
|
|
259 |
|
|
|
260 |
; Toggle the debug line to indicate a color change
|
|
|
261 |
sbi _SFR_IO_ADDR(PORTD),PD6
|
|
|
262 |
nop
|
|
|
263 |
cbi _SFR_IO_ADDR(PORTD),PD6
|
|
|
264 |
|
|
|
265 |
mov tmp2,pixelRunStart ; get the count value of the
|
|
|
266 |
; current pixel run
|
|
|
267 |
in pixelCount,_SFR_IO_ADDR(TCNT1L) ; get the current TCNT1 value
|
|
|
268 |
mov pixelRunStart,pixelCount ; reload pixelRunStart for the
|
|
|
269 |
; next run
|
|
|
270 |
sub pixelCount,tmp2 ; pixelCount = TCNT1L - pixelRunStart
|
|
|
271 |
|
|
|
272 |
st X+,lastColor ; record the color run in the current line buffer
|
|
|
273 |
st X+,pixelCount ; with its length
|
|
|
274 |
mov lastColor,color ; set lastColor so we can figure out when it changes
|
|
|
275 |
|
|
|
276 |
nop ; waste one more cycle for a total of 16
|
|
|
277 |
rjmp _acquirePixelBlock
|
|
|
278 |
|
|
|
279 |
; _cleanUpTrackingLine is used to write the last run length block off to the currentLineBuffer so
|
|
|
280 |
; that all 176 pixels in the line are accounted for.
|
|
|
281 |
_cleanUpTrackingLine:
|
|
|
282 |
ldi pixelCount,0xFF ; the length of the last run is ALWAYS 0xFF minus the last
|
|
|
283 |
sub pixelCount,pixelRunStart ; pixelRunStart
|
|
|
284 |
|
|
|
285 |
inc pixelCount ; increment pixelCount since we actually need to account
|
|
|
286 |
; for the overflow of TCNT1
|
|
|
287 |
|
|
|
288 |
st X+,color ; record the color run in the current line buffer
|
|
|
289 |
st X,pixelCount
|
|
|
290 |
rjmp _cleanUp
|
|
|
291 |
|
|
|
292 |
_cleanUpDumpLine:
|
|
|
293 |
; NOTE: If serial data is received, to interrupt the tracking of a line, we'll
|
|
|
294 |
; get a EV_SERIAL_DATA_RECEIVED event, and the T bit set so we will end the
|
|
|
295 |
; line's processing...however, the PCLK will keep on ticking for the rest of
|
|
|
296 |
; the frame/line, which will cause the TCNT to eventually overflow and
|
|
|
297 |
; interrupt us, generating a EV_ACQUIRE_LINE_COMPLETE event. We don't want
|
|
|
298 |
; this, so we need to actually turn off the PCLK counting each time we exit
|
|
|
299 |
; this loop, and only turn it on when we begin acquiring lines....
|
|
|
300 |
; NOT NEEDED FOR NOW...
|
|
|
301 |
;in tmp1, _SFR_IO_ADDR(TIMSK) ; disable TIMER1 to stop counting
|
|
|
302 |
;andi tmp1, DISABLE_PCLK_TIMER1_OVERFLOW_BITMASK ; external PCLK pulses
|
|
|
303 |
;out _SFR_IO_ADDR(TIMSK),tmp1
|
|
|
304 |
|
|
|
305 |
_cleanUp:
|
|
|
306 |
; Disable the external clocking of the Timer1 counter
|
|
|
307 |
in tmp1, _SFR_IO_ADDR(TCCR1B)
|
|
|
308 |
andi tmp1, 0xF8
|
|
|
309 |
out _SFR_IO_ADDR(TCCR1B),tmp1
|
|
|
310 |
|
|
|
311 |
; Toggle the debug line to indicate the line is complete
|
|
|
312 |
sbi _SFR_IO_ADDR(PORTD),PD6
|
|
|
313 |
cbi _SFR_IO_ADDR(PORTD),PD6
|
|
|
314 |
clt ; clear out the T bit since we have detected
|
|
|
315 |
; the interruption and are exiting to handle it
|
|
|
316 |
_exit:
|
|
|
317 |
ret
|
|
|
318 |
|
|
|
319 |
;*****************************************************************
|
|
|
320 |
; Function Name: CamIntAsm_waitForNewDumpFrame
|
|
|
321 |
; Function Description: This function is responsible for
|
|
|
322 |
; going to sleep until a new frame begins (indicated by
|
|
|
323 |
; VSYNC transitioning from low to high. This will wake
|
|
|
324 |
; the "VSYNC sleep" up and allow it to continue with
|
|
|
325 |
; acquiring a line of pixel data to dump out to the UI.
|
|
|
326 |
; Inputs: r25 - MSB of currentLineBuffer
|
|
|
327 |
; r24 - LSB of currentLineBuffer
|
|
|
328 |
; r23 - MSB of prevLineBuffer
|
|
|
329 |
; r22 - LSB of prevLineBuffer
|
|
|
330 |
; Outputs: none
|
|
|
331 |
; NOTES: This function doesn't really return...it sorta just
|
|
|
332 |
; floats into the acquireDumpLine function after the "VSYNC sleep"
|
|
|
333 |
; is awoken.
|
|
|
334 |
;*****************************************************************
|
|
|
335 |
CamIntAsm_waitForNewDumpFrame:
|
|
|
336 |
sbi _SFR_IO_ADDR(PORTD),PD6 ; For testing...
|
|
|
337 |
cbi _SFR_IO_ADDR(PORTD),PD6
|
|
|
338 |
sleep
|
|
|
339 |
|
|
|
340 |
;*****************************************************************
|
|
|
341 |
; REMEMBER...everything from here on out is critically timed to be
|
|
|
342 |
; synchronized with the flow of pixel data from the camera...
|
|
|
343 |
;*****************************************************************
|
|
|
344 |
|
|
|
345 |
CamIntAsm_acquireDumpLine:
|
|
|
346 |
brts _cleanUp
|
|
|
347 |
;sbi _SFR_IO_ADDR(PORTD),PD6 ; For testing...
|
|
|
348 |
;cbi _SFR_IO_ADDR(PORTD),PD6
|
|
|
349 |
|
|
|
350 |
mov XH,currLineBuffHigh ; Load the pointer to the current line
|
|
|
351 |
mov XL,currLineBuffLow ; buffer into the X pointer regs
|
|
|
352 |
|
|
|
353 |
mov YH,prevLineBuffHigh ; Load the pointer to the previous line
|
|
|
354 |
mov YL,prevLineBuffLow ; buffer into the Y pointer regs
|
|
|
355 |
|
|
|
356 |
ldi tmp1,PIXEL_RUN_START_INITIAL ; set up the TCNT1 to overflow (and
|
|
|
357 |
ldi tmp2,0xFF ; interrupts) after 176 pixels
|
|
|
358 |
out _SFR_IO_ADDR(TCNT1H),tmp2
|
|
|
359 |
out _SFR_IO_ADDR(TCNT1L),tmp1
|
|
|
360 |
|
|
|
361 |
in tmp1, _SFR_IO_ADDR(TCCR1B) ; Enable the PCLK line to actually
|
|
|
362 |
ori tmp1, 0x07 ; feed Timer1
|
|
|
363 |
out _SFR_IO_ADDR(TCCR1B),tmp1
|
|
|
364 |
nop
|
|
|
365 |
|
|
|
366 |
in tmp1, _SFR_IO_ADDR(TIMSK) ; enable TIMER1 to start counting
|
|
|
367 |
ori tmp1, ENABLE_PCLK_TIMER1_OVERFLOW_BITMASK ; external PCLK pulses and interrupt on
|
|
|
368 |
out _SFR_IO_ADDR(TIMSK),tmp1 ; overflow
|
|
|
369 |
|
|
|
370 |
in tmp1, _SFR_IO_ADDR(GICR) ; enable the HREF interrupt...remember, we
|
|
|
371 |
; only use this interrupt to synchronize
|
|
|
372 |
; the beginning of the line
|
|
|
373 |
ori tmp1, HREF_INTERRUPT_ENABLE_MASK
|
|
|
374 |
out _SFR_IO_ADDR(GICR), tmp1
|
|
|
375 |
|
|
|
376 |
;*******************************************************************************************
|
|
|
377 |
; Dump Frame handler
|
|
|
378 |
;*******************************************************************************************
|
|
|
379 |
|
|
|
380 |
_dumpFrame:
|
|
|
381 |
sbi _SFR_IO_ADDR(PORTD),PD6
|
|
|
382 |
sleep ; ...And we wait...
|
|
|
383 |
|
|
|
384 |
cbi _SFR_IO_ADDR(PORTD),PD6
|
|
|
385 |
in tmp1, _SFR_IO_ADDR(GICR) ; disable the HREF interrupt
|
|
|
386 |
andi tmp1, HREF_INTERRUPT_DISABLE_MASK ; so we don't get interrupted
|
|
|
387 |
out _SFR_IO_ADDR(GICR), tmp1 ; while dumping the line
|
|
|
388 |
|
|
|
389 |
nop ; Remember...if we ever remove the "cbi" instruction above,
|
|
|
390 |
; we need to add two more NOPs to cover this
|
|
|
391 |
|
|
|
392 |
; Ok...the following loop needs to run in 8 clock cycles, so we can get every
|
|
|
393 |
; pixel in the line...this shouldn't be a problem, since the PCLK timing was
|
|
|
394 |
; reduced by a factor of 2 whenever we go to dump a line (this is to give us
|
|
|
395 |
; enough time to do the sampling and storing of the pixel data). In addition,
|
|
|
396 |
; it is assumed that we will have to do some minor processing on the data right
|
|
|
397 |
; before we send it out, like mask off the top 4-bits of each, and then pack both
|
|
|
398 |
; low nibbles into a single byte for transmission...we just don't have time to
|
|
|
399 |
; do that here (only 8 instruction cycles :-) )
|
|
|
400 |
_sampleDumpPixel:
|
|
|
401 |
in tmp1,G_PORT ; sample the G value (1)
|
|
|
402 |
in tmp2,RB_PORT ; sample the R/B value (1)
|
|
|
403 |
st X+,tmp1 ; store to the currLineBuff and inc ptrs(2)
|
|
|
404 |
st Y+,tmp2 ; store to the prevLineBuff and inc ptrs(2)
|
|
|
405 |
brtc _sampleDumpPixel ; loop back unless flag is set (2...if not set)
|
|
|
406 |
; ___________
|
|
|
407 |
; 8 cycles normally
|
|
|
408 |
|
|
|
409 |
; if we make it here, it means the T flag is set, and we must have been interrupted
|
|
|
410 |
; so we need to exit (what if we were interrupted for serial? should we disable it?)
|
|
|
411 |
rjmp _cleanUpDumpLine
|
|
|
412 |
|
|
|
413 |
;***********************************************************
|
|
|
414 |
; Function Name: <interrupt handler for External Interrupt0>
|
|
|
415 |
; Function Description: This function is responsible
|
|
|
416 |
; for handling a rising edge on the Ext Interrupt 0. This
|
|
|
417 |
; routine simply returns, since we just want to wake up
|
|
|
418 |
; whenever the VSYNC transitions (meaning the start of a new
|
|
|
419 |
; frame).
|
|
|
420 |
; Inputs: none
|
|
|
421 |
; Outputs: none
|
|
|
422 |
;***********************************************************
|
|
|
423 |
SIG_INTERRUPT0:
|
|
|
424 |
; This will wake us up when VSYNC transitions high...we just want to return
|
|
|
425 |
reti
|
|
|
426 |
|
|
|
427 |
;***********************************************************
|
|
|
428 |
; Function Name: <interrupt handler for External Interrupt1>
|
|
|
429 |
; Function Description: This function is responsible
|
|
|
430 |
; for handling a falling edge on the Ext Interrupt 1. This
|
|
|
431 |
; routine simply returns, since we just want to wake up
|
|
|
432 |
; whenever the HREF transitions (meaning the pixels
|
|
|
433 |
; are starting after VSYNC transitioned, and we need to
|
|
|
434 |
; start acquiring the pixel blocks
|
|
|
435 |
; Inputs: none
|
|
|
436 |
; Outputs: none
|
|
|
437 |
;***********************************************************
|
|
|
438 |
SIG_INTERRUPT1:
|
|
|
439 |
; This will wake us up when HREF transitions high...we just want to return
|
|
|
440 |
reti
|
|
|
441 |
|
|
|
442 |
;***********************************************************
|
|
|
443 |
; Function Name: <interrupt handler for Timer0 overflow>
|
|
|
444 |
; Function Description: This function is responsible
|
|
|
445 |
; for handling the Timer0 overflow (hooked up to indicate
|
|
|
446 |
; when we have reached the number of HREFs required in a
|
|
|
447 |
; single frame). We set the T flag in the SREG to
|
|
|
448 |
; indicate to the _acquirePixelBlock routine that it needs
|
|
|
449 |
; to exit, and then set the appropriate action to take in
|
|
|
450 |
; the eventList of the Executive module.
|
|
|
451 |
; Inputs: none
|
|
|
452 |
; Outputs: none
|
|
|
453 |
; Note: Originally, the HREF pulses were also going to
|
|
|
454 |
; be counted by a hardware counter, but it didn't end up
|
|
|
455 |
; being necessary
|
|
|
456 |
;***********************************************************
|
|
|
457 |
;SIG_OVERFLOW0:
|
|
|
458 |
; set ; set the T bit in SREG
|
|
|
459 |
; lds tmp1,eventBitmask
|
|
|
460 |
; ori tmp1,EV_ACQUIRE_FRAME_COMPLETE
|
|
|
461 |
; sts eventBitmask,tmp1
|
|
|
462 |
; reti
|
|
|
463 |
|
|
|
464 |
;***********************************************************
|
|
|
465 |
; Function Name: <interrupt handler for Timer1 overflow>
|
|
|
466 |
; Function Description: This function is responsible
|
|
|
467 |
; for handling the Timer1 overflow (hooked up to indicate
|
|
|
468 |
; when we have reached the end of a line of pixel data,
|
|
|
469 |
; since PCLK is hooked up to overflow TCNT1 after 176
|
|
|
470 |
; pixels). This routine generates an acquire line complete
|
|
|
471 |
; event in the fastEventBitmask, which is streamlined for
|
|
|
472 |
; efficiency reasons.
|
|
|
473 |
;***********************************************************
|
|
|
474 |
SIG_OVERFLOW1:
|
|
|
475 |
lds tmp1,fastEventBitmask ; set a flag indicating
|
|
|
476 |
ori tmp1,FEV_ACQUIRE_LINE_COMPLETE ; a line is complete
|
|
|
477 |
sts fastEventBitmask,tmp1
|
|
|
478 |
set ; set the T bit in SREG
|
|
|
479 |
;sbi _SFR_IO_ADDR(PORTD),PD6 ; For testing...
|
|
|
480 |
;cbi _SFR_IO_ADDR(PORTD),PD6 ; For testing...
|
|
|
481 |
|
|
|
482 |
reti
|
|
|
483 |
|
|
|
484 |
; This is the default handler for all interrupts that don't
|
|
|
485 |
; have handler routines specified for them.
|
|
|
486 |
.global __vector_default
|
|
|
487 |
__vector_default:
|
|
|
488 |
reti
|
|
|
489 |
|
|
|
490 |
.end
|