Initial import
[avr_bc100.git] / BaseTinyFirmware / IAR / Debug / List / USI.s90
1 ///////////////////////////////////////////////////////////////////////////////\r
2 //                                                                            /\r
3 // IAR Atmel AVR C/C++ Compiler V4.30F/W32              12/Mar/2008  23:01:39 /\r
4 // Copyright 1996-2007 IAR Systems. All rights reserved.                      /\r
5 //                                                                            /\r
6 //    Source file  =  C:\home\kevin\pub\src\bc100_cal\IAR\USI.c               /\r
7 //    Command line =  C:\home\kevin\pub\src\bc100_cal\IAR\USI.c               /\r
8 //                    --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc100_cal\IA /\r
9 //                    R\Debug\Obj\ -lC C:\home\kevin\pub\src\bc100_cal\IAR\De /\r
10 //                    bug\List\ -lB C:\home\kevin\pub\src\bc100_cal\IAR\Debug /\r
11 //                    \List\ --initializers_in_flash -z2 --no_cse             /\r
12 //                    --no_inline --no_code_motion --no_cross_call            /\r
13 //                    --no_clustering --no_tbaa --debug                       /\r
14 //                    -DENABLE_BIT_DEFINITIONS -e --require_prototypes -I     /\r
15 //                    "C:\Program Files\IAR Systems\Embedded Workbench        /\r
16 //                    4.0\avr\INC\" -I "C:\Program Files\IAR                  /\r
17 //                    Systems\Embedded Workbench 4.0\avr\INC\CLIB\"           /\r
18 //                    --eeprom_size 512                                       /\r
19 //    List file    =  C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\USI.s90  /\r
20 //                                                                            /\r
21 //                                                                            /\r
22 ///////////////////////////////////////////////////////////////////////////////\r
23 \r
24         NAME USI\r
25 \r
26         RSEG CSTACK:DATA:NOROOT(0)\r
27         RSEG RSTACK:DATA:NOROOT(0)\r
28 \r
29         EXTERN ?need_segment_init\r
30         EXTERN __eeget8_16\r
31         EXTERN __eeput8_16\r
32 \r
33         PUBWEAK `?<Segment init: NEAR_Z>`\r
34         PUBWEAK `??USI_OVF_ISR??INTVEC 16`\r
35         PUBLIC SPI\r
36         PUBLIC SPI_Get\r
37         PUBLIC SPI_Init\r
38         PUBLIC SPI_Put\r
39         PUBLIC SPI_Wait\r
40         PUBLIC USI_OVF_ISR\r
41         PUBWEAK _A_DDRB\r
42         PUBWEAK _A_PORTB\r
43         PUBWEAK _A_USICR\r
44         PUBWEAK _A_USIDR\r
45         PUBWEAK _A_USISR\r
46         PUBWEAK __?EEARH\r
47         PUBWEAK __?EEARL\r
48         PUBWEAK __?EECR\r
49         PUBWEAK __?EEDR\r
50 \r
51 USI_OVF_ISR         SYMBOL "USI_OVF_ISR"\r
52 `??USI_OVF_ISR??INTVEC 16` SYMBOL "??INTVEC 16", USI_OVF_ISR\r
53 \r
54         EXTERN Time_Left\r
55         EXTERN Time_Set\r
56         EXTERN ADCS\r
57         EXTERN BattActive\r
58         EXTERN BattControl\r
59         EXTERN BattData\r
60         EXTERN timeval\r
61 \r
62 // C:\home\kevin\pub\src\bc100_cal\IAR\USI.c\r
63 //    1 /* This file has been prepared for Doxygen automatic documentation generation.*/\r
64 //    2 /*! \file *********************************************************************\r
65 //    3  *\r
66 //    4  * \brief\r
67 //    5  *      Functions for use of the Universal Serial Interface\r
68 //    6  *\r
69 //    7  *      Contains high level functions for initializing the USI as an SPI slave,\r
70 //    8  *      interrupt handling, sending and receiving single bytes.\r
71 //    9  *\r
72 //   10  * \par Application note:\r
73 //   11  *      AVR458: Charging Li-Ion Batteries with BC100 \n\r
74 //   12  *      AVR463: Charging NiMH Batteries with BC100\r
75 //   13  *\r
76 //   14  * \par Documentation:\r
77 //   15  *      For comprehensive code documentation, supported compilers, compiler\r
78 //   16  *      settings and supported devices see readme.html\r
79 //   17  *\r
80 //   18  * \author\r
81 //   19  *      Atmel Corporation: http://www.atmel.com \n\r
82 //   20  *      Support email: avr@atmel.com \n\r
83 //   21  *      Original author: \n\r
84 //   22  *\r
85 //   23  * $Name$\r
86 //   24  * $Revision: 2299 $\r
87 //   25  * $RCSfile$\r
88 //   26  * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/USI.c $\r
89 //   27  * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
90 //   28  ******************************************************************************/\r
91 //   29 \r
92 //   30 #include <ioavr.h>\r
93 \r
94         ASEGN ABSOLUTE:DATA:NOROOT,038H\r
95 // <unnamed> volatile __io _A_PORTB\r
96 _A_PORTB:\r
97         DS 1\r
98 \r
99         ASEGN ABSOLUTE:DATA:NOROOT,037H\r
100 // <unnamed> volatile __io _A_DDRB\r
101 _A_DDRB:\r
102         DS 1\r
103 \r
104         ASEGN ABSOLUTE:DATA:NOROOT,02fH\r
105 // <unnamed> volatile __io _A_USIDR\r
106 _A_USIDR:\r
107         DS 1\r
108 \r
109         ASEGN ABSOLUTE:DATA:NOROOT,02eH\r
110 // <unnamed> volatile __io _A_USISR\r
111 _A_USISR:\r
112         DS 1\r
113 \r
114         ASEGN ABSOLUTE:DATA:NOROOT,02dH\r
115 // <unnamed> volatile __io _A_USICR\r
116 _A_USICR:\r
117         DS 1\r
118 //   31 #include <inavr.h>\r
119 //   32 \r
120 //   33 #include "enums.h"\r
121 //   34 #include "structs.h"\r
122 //   35 \r
123 //   36 #include "main.h"\r
124 //   37 #include "ADC.h"\r
125 //   38 #include "battery.h"\r
126 //   39 #include "time.h"\r
127 //   40 #include "USI.h"\r
128 //   41 \r
129 //   42 \r
130 //   43 //******************************************************************************\r
131 //   44 // Variables\r
132 //   45 //******************************************************************************\r
133 //   46 //! SPI status struct\r
134 \r
135         RSEG NEAR_Z:DATA:NOROOT(0)\r
136         REQUIRE `?<Segment init: NEAR_Z>`\r
137 //   47 SPI_Status_t SPI;\r
138 SPI:\r
139         DS 4\r
140 //   48 \r
141 //   49 \r
142 //   50 //******************************************************************************\r
143 //   51 //Functions\r
144 //   52 //*****************************************************************************\r
145 //   53 /*! \brief USI Counter Overflow Interrupt Service Routine\r
146 //   54  *\r
147 //   55  * When the USI counter overflows, a byte has been transferred.\n\r
148 //   56  * The USIDR contents are stored and flags are updated.\r
149 //   57  *\r
150 //   58  * The protocol is quite simple and has three sequential states: command,\r
151 //   59  * address and data.\r
152 //   60  * (Keep in mind that the Master is in charge of data clocking, which means\r
153 //   61  * there is a one byte "delay" from when the Slave puts something to SPI till\r
154 //   62  * the Master can read it.)\r
155 //   63  *\r
156 //   64  * 1. If a non-zero byte is received in the command state, the ISR will\r
157 //   65  * store the commands to the SPI struct (read/write, EEPROM/SRAM, number of\r
158 //   66  * bytes). To signal that the command was received, 0xCC is put to the SPI bus.\r
159 //   67  * If a zero byte (0x00) is received in the command state, it is simply ignored\r
160 //   68  * because it is an invalid command.\r
161 //   69  *\r
162 //   70  * 2. When a byte is received in the address state, it is stored to the SPI\r
163 //   71  * struct. To signal that the address was received, 0xBB is put to SPI bus.\r
164 //   72  * \r
165 //   73  * 3. In the data state, variables are read/written "from back to front" until\r
166 //   74  * the byte counter reaches zero. Since the Master is in charge of the data\r
167 //   75  * clocking, the Slave will go to command state before the last byte is\r
168 //   76  * transferred during reading. This means that the Master should send an \r
169 //   77  * invalid command when getting each byte, ie 0x00.\r
170 //   78  *\r
171 //   79  * If the time between two transfers is 1 second or more, the Slave\r
172 //   80  * automatically reverts to command state.\r
173 //   81  *\r
174 //   82  * \note Battery charging is not automatically halted during SPI communication.\r
175 //   83  * This means that the current charge state (current and voltage) will\r
176 //   84  * remain constant during heavy and prolonged serial traffic.\r
177 //   85  *\r
178 //   86  * \todo Variable writing not implemented yet.\r
179 //   87  * \todo EEPROM/SRAM flag doesn't really do anything with this implementation.\r
180 //   88  */\r
181 //   89 #pragma vector=USI_OVF_vect\r
182 \r
183         RSEG CODE:CODE:NOROOT(1)\r
184 //   90 __interrupt void USI_OVF_ISR(void)\r
185 USI_OVF_ISR:\r
186 //   91 {\r
187         ST      -Y, R26\r
188         ST      -Y, R25\r
189         ST      -Y, R24\r
190         ST      -Y, R31\r
191         ST      -Y, R30\r
192         ST      -Y, R3\r
193         ST      -Y, R2\r
194         ST      -Y, R1\r
195         ST      -Y, R0\r
196         ST      -Y, R23\r
197         ST      -Y, R22\r
198         ST      -Y, R21\r
199         ST      -Y, R20\r
200         ST      -Y, R19\r
201         ST      -Y, R18\r
202         ST      -Y, R17\r
203         ST      -Y, R16\r
204         IN      R26, 0x3F\r
205 //   92         // If the communication timed out, set ST_CMD as current state.\r
206 //   93         if (!Time_Left(TIMER_USI)) {\r
207         LDI     R16, 0\r
208         RCALL   Time_Left\r
209         TST     R16\r
210         BRNE    ??USI_OVF_ISR_0\r
211 //   94                 SPI.State = ST_CMD;\r
212         LDS     R16, (SPI + 2)\r
213         ANDI    R16, 0x3F\r
214         ORI     R16, 0x40\r
215         STS     (SPI + 2), R16\r
216 //   95         }\r
217 //   96 \r
218 //   97         // Start communication timer. If further communication doesn't happen\r
219 //   98         // within 1 second, the SPI communication state is reset to CMD.\r
220 //   99         Time_Set(TIMER_USI, 0, 1, 0);\r
221 ??USI_OVF_ISR_0:\r
222         LDI     R20, 0\r
223         LDI     R17, 1\r
224         LDI     R18, 0\r
225         LDI     R19, 0\r
226         LDI     R16, 0\r
227         RCALL   Time_Set\r
228 //  100         \r
229 //  101         // Clear USI counter and flag completed transfer.\r
230 //  102         USISR = (1<<USIOIF);\r
231         LDI     R16, 64\r
232         OUT     0x0E, R16\r
233 //  103         SPI.XferComplete = TRUE;\r
234         LDI     R30, LOW(SPI)\r
235         LDI     R31, (SPI) >> 8\r
236         LDD     R16, Z+3\r
237         ORI     R16, 0x04\r
238         STD     Z+3, R16\r
239 //  104         \r
240 //  105         // Process incoming data.\r
241 //  106         switch(SPI.State)       {\r
242         LDS     R16, (SPI + 2)\r
243         LSL     R16\r
244         ROL     R16\r
245         ROL     R16\r
246         ANDI    R16, 0x03\r
247         SUBI    R16, 1\r
248         BREQ    ??USI_OVF_ISR_1\r
249         DEC     R16\r
250         BRNE    $+2+2\r
251         RJMP    ??USI_OVF_ISR_2\r
252         DEC     R16\r
253         BRNE    $+2+2\r
254         RJMP    ??USI_OVF_ISR_3\r
255         RJMP    ??USI_OVF_ISR_4\r
256 //  107         // A valid SPI transfer starts with a Command Byte sent by the Master.\r
257 //  108         case ST_CMD:   \r
258 //  109                 SPI.Data = USIDR;  // Store the transferred byte.\r
259 ??USI_OVF_ISR_1:\r
260         IN      R16, 0x0F\r
261         LDS     R17, SPI\r
262         STS     SPI, R16\r
263 //  110                 \r
264 //  111                 // If the master sent 0, it is trying to get data. Ignore in this state.\r
265 //  112                 if (SPI.Data != 0) {\r
266         LDS     R16, SPI\r
267         TST     R16\r
268         BRNE    $+2+2\r
269         RJMP    ??USI_OVF_ISR_4\r
270 //  113                         // Does the master want to read or write?\r
271 //  114                         if (SPI.Data & 0x40) {\r
272         LDI     R30, LOW(SPI)\r
273         LDI     R31, (SPI) >> 8\r
274         LD      R16, Z\r
275         SBRS    R16, 6\r
276         RJMP    ??USI_OVF_ISR_5\r
277 //  115                                 SPI.Read = FALSE;\r
278         LDI     R30, LOW(SPI)\r
279         LDI     R31, (SPI) >> 8\r
280         LDD     R16, Z+3\r
281         ANDI    R16, 0xFE\r
282         STD     Z+3, R16\r
283         RJMP    ??USI_OVF_ISR_6\r
284 //  116                         } else {\r
285 //  117                                 SPI.Read = TRUE;\r
286 ??USI_OVF_ISR_5:\r
287         LDI     R30, LOW(SPI)\r
288         LDI     R31, (SPI) >> 8\r
289         LDD     R16, Z+3\r
290         ORI     R16, 0x01\r
291         STD     Z+3, R16\r
292 //  118                         }\r
293 //  119 \r
294 //  120                                 // From/to EEPROM or SRAM?\r
295 //  121                         if (SPI.Data &0x80) {\r
296 ??USI_OVF_ISR_6:\r
297         LDI     R30, LOW(SPI)\r
298         LDI     R31, (SPI) >> 8\r
299         LD      R16, Z\r
300         SBRS    R16, 7\r
301         RJMP    ??USI_OVF_ISR_7\r
302 //  122                                 SPI.EEPROM = TRUE;\r
303         LDI     R30, LOW(SPI)\r
304         LDI     R31, (SPI) >> 8\r
305         LDD     R16, Z+3\r
306         ORI     R16, 0x02\r
307         STD     Z+3, R16\r
308         RJMP    ??USI_OVF_ISR_8\r
309 //  123                         } else {\r
310 //  124                                 SPI.EEPROM = FALSE;\r
311 ??USI_OVF_ISR_7:\r
312         LDI     R30, LOW(SPI)\r
313         LDI     R31, (SPI) >> 8\r
314         LDD     R16, Z+3\r
315         ANDI    R16, 0xFD\r
316         STD     Z+3, R16\r
317 //  125                         }\r
318 //  126 \r
319 //  127                         SPI.Count = (SPI.Data & 0x3F);  // Get number of bytes to receive/send.\r
320 ??USI_OVF_ISR_8:\r
321         LDS     R17, (SPI + 2)\r
322         ANDI    R17, 0xC0\r
323         LDS     R16, SPI\r
324         ANDI    R16, 0x3F\r
325         OR      R16, R17\r
326         STS     (SPI + 2), R16\r
327 //  128                         SPI.State = ST_ADDR;  // The Master will send the address byte next.\r
328         LDS     R16, (SPI + 2)\r
329         ANDI    R16, 0x3F\r
330         ORI     R16, 0x80\r
331         STS     (SPI + 2), R16\r
332 //  129 \r
333 //  130                         SPI_Put(0xCC);  // Signal that command was received.\r
334         LDI     R16, 204\r
335         RCALL   SPI_Put\r
336         RJMP    ??USI_OVF_ISR_4\r
337 //  131                 }\r
338 //  132         break;\r
339 //  133 \r
340 //  134                         \r
341 //  135         case ST_ADDR:  \r
342 //  136                 SPI.Data = USIDR;  // Store the address.\r
343 ??USI_OVF_ISR_2:\r
344         IN      R16, 0x0F\r
345         LDS     R24, SPI\r
346         STS     SPI, R16\r
347 //  137                 SPI.Address = SPI.Data;\r
348         LDS     R25, (SPI + 1)\r
349         LDS     R16, SPI\r
350         STS     (SPI + 1), R16\r
351 //  138                 SPI.State = ST_DATA;  // The master will send/wait for data next.\r
352         LDI     R30, LOW(SPI)\r
353         LDI     R31, (SPI) >> 8\r
354         LDD     R16, Z+2\r
355         ORI     R16, 0xC0\r
356         STD     Z+2, R16\r
357 //  139 \r
358 //  140                 SPI_Put(0xBB);  // Signal that address was received.\r
359         LDI     R16, 187\r
360         RCALL   SPI_Put\r
361         RJMP    ??USI_OVF_ISR_4\r
362 //  141         break;\r
363 //  142 \r
364 //  143 \r
365 //  144         // Note well: this will process at least one byte, regardless of Count.\r
366 //  145         case ST_DATA:\r
367 //  146                 if (SPI.Count-- > 0) {\r
368 ??USI_OVF_ISR_3:\r
369         LDS     R16, (SPI + 2)\r
370         MOV     R18, R16\r
371         ANDI    R18, 0xC0\r
372         MOV     R17, R16\r
373         DEC     R17\r
374         ANDI    R17, 0x3F\r
375         OR      R17, R18\r
376         STS     (SPI + 2), R17\r
377         ANDI    R16, 0x3F\r
378         CPI     R16, 1\r
379         BRCC    $+2+2\r
380         RJMP    ??USI_OVF_ISR_9\r
381 //  147                         // Write specified variable to SPI, "back to front".\r
382 //  148                         if (SPI.Read) {\r
383         LDI     R30, LOW(SPI)\r
384         LDI     R31, (SPI) >> 8\r
385         LDD     R16, Z+3\r
386         SBRS    R16, 0\r
387         RJMP    ??USI_OVF_ISR_10\r
388 //  149                                 switch (SPI.Address) {\r
389         LDS     R16, (SPI + 1)\r
390         SUBI    R16, 1\r
391         BREQ    ??USI_OVF_ISR_11\r
392         DEC     R16\r
393         BREQ    ??USI_OVF_ISR_12\r
394         DEC     R16\r
395         BREQ    ??USI_OVF_ISR_13\r
396         DEC     R16\r
397         BREQ    ??USI_OVF_ISR_14\r
398         DEC     R16\r
399         BREQ    ??USI_OVF_ISR_15\r
400         RJMP    ??USI_OVF_ISR_16\r
401 //  150                                 case ADR_ADCS:\r
402 //  151                                         SPI_Put(*(((unsigned char*)&ADCS) + (SPI.Count)));\r
403 ??USI_OVF_ISR_11:\r
404         LDS     R16, (SPI + 2)\r
405         ANDI    R16, 0x3F\r
406         LDI     R17, 0\r
407         MOVW    R31:R30, R17:R16\r
408         SUBI    R30, LOW((-(ADCS) & 0xFFFF))\r
409         SBCI    R31, (-(ADCS) & 0xFFFF) >> 8\r
410         LD      R16, Z\r
411         RCALL   SPI_Put\r
412         RJMP    ??USI_OVF_ISR_4\r
413 //  152                                 break;\r
414 //  153                                 \r
415 //  154                                 \r
416 //  155                                 case ADR_BATTACTIVE:\r
417 //  156                                         SPI_Put(*((unsigned char*)&BattActive + (SPI.Count)));\r
418 ??USI_OVF_ISR_12:\r
419         LDS     R16, (SPI + 2)\r
420         ANDI    R16, 0x3F\r
421         LDI     R17, 0\r
422         MOVW    R31:R30, R17:R16\r
423         SUBI    R30, LOW((-(BattActive) & 0xFFFF))\r
424         SBCI    R31, (-(BattActive) & 0xFFFF) >> 8\r
425         LD      R16, Z\r
426         RCALL   SPI_Put\r
427         RJMP    ??USI_OVF_ISR_4\r
428 //  157                                 break;\r
429 //  158                                 \r
430 //  159                                 \r
431 //  160                                 case ADR_BATTDATA:\r
432 //  161                                         SPI_Put(*((unsigned char*)&BattData + (SPI.Count)));\r
433 ??USI_OVF_ISR_13:\r
434         LDS     R16, (SPI + 2)\r
435         ANDI    R16, 0x3F\r
436         LDI     R17, 0\r
437         MOVW    R31:R30, R17:R16\r
438         SUBI    R30, LOW((-(BattData) & 0xFFFF))\r
439         SBCI    R31, (-(BattData) & 0xFFFF) >> 8\r
440         LD      R16, Z\r
441         RCALL   SPI_Put\r
442         RJMP    ??USI_OVF_ISR_4\r
443 //  162                                 break;\r
444 //  163                                 \r
445 //  164                                 \r
446 //  165                                 case ADR_BATTCTRL:\r
447 //  166                                         SPI_Put(*((__eeprom unsigned char*)&BattControl + (SPI.Count)));\r
448 ??USI_OVF_ISR_14:\r
449         LDS     R16, (SPI + 2)\r
450         ANDI    R16, 0x3F\r
451         LDI     R17, 0\r
452         LDI     R20, LOW(BattControl)\r
453         LDI     R21, (BattControl) >> 8\r
454         ADD     R20, R16\r
455         ADC     R21, R17\r
456         RCALL   __eeget8_16\r
457         RCALL   SPI_Put\r
458         RJMP    ??USI_OVF_ISR_4\r
459 //  167                                 break;\r
460 //  168                                 \r
461 //  169                                 case ADR_TIMERS:\r
462 //  170                                         SPI_Put(*((unsigned char*)&timeval + (SPI.Count)));\r
463 ??USI_OVF_ISR_15:\r
464         LDS     R16, (SPI + 2)\r
465         ANDI    R16, 0x3F\r
466         LDI     R17, 0\r
467         MOVW    R31:R30, R17:R16\r
468         SUBI    R30, LOW((-(timeval) & 0xFFFF))\r
469         SBCI    R31, (-(timeval) & 0xFFFF) >> 8\r
470         LD      R16, Z\r
471         RCALL   SPI_Put\r
472         RJMP    ??USI_OVF_ISR_4\r
473 //  171                                 break;\r
474 //  172 \r
475 //  173                                 \r
476 //  174                                 default:\r
477 //  175                                         SPI_Put(0);\r
478 ??USI_OVF_ISR_16:\r
479         LDI     R16, 0\r
480         RCALL   SPI_Put\r
481         RJMP    ??USI_OVF_ISR_4\r
482 //  176                                 break;\r
483 //  177                                 }\r
484 //  178                         } else {\r
485 //  179                                 // Read byte from SPI\r
486 //  180                                 SPI.Data = USIDR;\r
487 ??USI_OVF_ISR_10:\r
488         IN      R16, 0x0F\r
489         LDS     R17, SPI\r
490         STS     SPI, R16\r
491 //  181 \r
492 //  182                                 // ********************************************\r
493 //  183                                 // THIS FUNCTION HAS NOT BEEN FULLY IMPLEMENTED\r
494 //  184                                 // ********************************************\r
495 //  185                                                                 \r
496 //  186                                 // Save byte to specified variable.\r
497 //  187                                 switch (SPI.Address) {\r
498         LDS     R16, (SPI + 1)\r
499         SUBI    R16, 4\r
500         BRNE    ??USI_OVF_ISR_4\r
501 //  188                                 case ADR_BATTCTRL:\r
502 //  189                                         *((__eeprom unsigned char*)&BattControl + SPI.Count) = SPI.Data;\r
503         LDS     R16, SPI\r
504         LDS     R18, (SPI + 2)\r
505         ANDI    R18, 0x3F\r
506         LDI     R19, 0\r
507         LDI     R20, LOW(BattControl)\r
508         LDI     R21, (BattControl) >> 8\r
509         ADD     R20, R18\r
510         ADC     R21, R19\r
511         RCALL   __eeput8_16\r
512         RJMP    ??USI_OVF_ISR_4\r
513 //  190                                 break;\r
514 //  191 \r
515 //  192                                 \r
516 //  193                                 default:\r
517 //  194                                 break;\r
518 //  195                                 }\r
519 //  196                         }\r
520 //  197                         \r
521 //  198 \r
522 //  199                 } else {\r
523 //  200                         SPI.State = ST_CMD;\r
524 ??USI_OVF_ISR_9:\r
525         LDS     R16, (SPI + 2)\r
526         ANDI    R16, 0x3F\r
527         ORI     R16, 0x40\r
528         STS     (SPI + 2), R16\r
529 //  201                 }\r
530 //  202         break;\r
531 //  203 \r
532 //  204         default:  // Shouldn't end up here. (Unknown SPI-state)\r
533 //  205         break;\r
534 //  206         }\r
535 //  207 }\r
536 ??USI_OVF_ISR_4:\r
537         OUT     0x3F, R26\r
538         LD      R16, Y+\r
539         LD      R17, Y+\r
540         LD      R18, Y+\r
541         LD      R19, Y+\r
542         LD      R20, Y+\r
543         LD      R21, Y+\r
544         LD      R22, Y+\r
545         LD      R23, Y+\r
546         LD      R0, Y+\r
547         LD      R1, Y+\r
548         LD      R2, Y+\r
549         LD      R3, Y+\r
550         LD      R30, Y+\r
551         LD      R31, Y+\r
552         LD      R24, Y+\r
553         LD      R25, Y+\r
554         LD      R26, Y+\r
555         RETI\r
556         REQUIRE _A_USIDR\r
557         REQUIRE _A_USISR\r
558 //  208 \r
559 //  209 \r
560 //  210 /*! \brief Initializes USI as an SPI slave\r
561 //  211  *\r
562 //  212  * Initializes USI as a 3-wire SPI slave using the pins specified in USI.h for\r
563 //  213  * I/O and clock, and USI counter overflow interrupts enabled.\n\r
564 //  214  * Also initializes the SPI status struct.\r
565 //  215  * \r
566 //  216  * \param spi_mode Specifies if USI should trigger on positive (0) or negative\r
567 //  217  * (1) edge of clock signal\r
568 //  218  *\r
569 //  219  * \note Clears the stored data\r
570 //  220  *\r
571 //  221  * \todo Timer should reset SPI protocol on timeout\r
572 //  222  */\r
573 \r
574         RSEG CODE:CODE:NOROOT(1)\r
575 //  223 void SPI_Init(unsigned char spi_mode)\r
576 SPI_Init:\r
577 //  224 {\r
578 //  225         __disable_interrupt();\r
579         CLI\r
580 //  226         \r
581 //  227         // Configure outputs and inputs, enable pull-ups for DATAIN and CLOCK pins.\r
582 //  228         USI_DIR_REG |= (1<<USI_DATAOUT_PIN);\r
583         SBI     0x17, 0x01\r
584 //  229         USI_DIR_REG &= ~((1<<USI_DATAIN_PIN) | (1<<USI_CLOCK_PIN));\r
585         IN      R17, 0x17\r
586         ANDI    R17, 0xFA\r
587         OUT     0x17, R17\r
588 //  230         USI_OUT_REG |= (1<<USI_DATAIN_PIN) | (1<<USI_CLOCK_PIN);\r
589         IN      R17, 0x18\r
590         ORI     R17, 0x05\r
591         OUT     0x18, R17\r
592 //  231         \r
593 //  232         // Configure USI to 3-wire slave mode with overflow interrupt\r
594 //  233         USICR = ( (1<<USIOIE) | (1<<USIWM0) | (1<<USICS1) | (spi_mode<<USICS0) );\r
595         MOV     R17, R16\r
596         LSL     R17\r
597         LSL     R17\r
598         ORI     R17, 0x58\r
599         OUT     0x0D, R17\r
600 //  234 \r
601 //  235         // Initialize the SPI struct\r
602 //  236         SPI.Data = 0;                 // Clear data.\r
603         LDI     R17, 0\r
604         STS     SPI, R17\r
605 //  237         SPI.State = ST_CMD;           // Initial SPI state: wait for command.\r
606         LDS     R17, (SPI + 2)\r
607         ANDI    R17, 0x3F\r
608         ORI     R17, 0x40\r
609         STS     (SPI + 2), R17\r
610 //  238         SPI.Read = FALSE;             // Doesn't matter right now.\r
611         LDI     R30, LOW(SPI)\r
612         LDI     R31, (SPI) >> 8\r
613         LDD     R17, Z+3\r
614         ANDI    R17, 0xFE\r
615         STD     Z+3, R17\r
616 //  239         SPI.EEPROM = FALSE;           // Doesn't matter right now.\r
617         LDI     R30, LOW(SPI)\r
618         LDI     R31, (SPI) >> 8\r
619         LDD     R17, Z+3\r
620         ANDI    R17, 0xFD\r
621         STD     Z+3, R17\r
622 //  240         SPI.Count = 0;                // Doesn't matter right now.\r
623         LDI     R30, LOW(SPI)\r
624         LDI     R31, (SPI) >> 8\r
625         LDD     R17, Z+2\r
626         ANDI    R17, 0xC0\r
627         STD     Z+2, R17\r
628 //  241         SPI.Address = 0;              // Doesn't matter right now.\r
629         LDI     R17, 0\r
630         STS     (SPI + 1), R17\r
631 //  242         SPI.XferComplete = FALSE;     // We haven't even started a transfer yet.\r
632         LDI     R30, LOW(SPI)\r
633         LDI     R31, (SPI) >> 8\r
634         LDD     R17, Z+3\r
635         ANDI    R17, 0xFB\r
636         STD     Z+3, R17\r
637 //  243         SPI.WriteCollision = FALSE;   // ..And therefore a collision hasn't happened.\r
638         LDI     R30, LOW(SPI)\r
639         LDI     R31, (SPI) >> 8\r
640         LDD     R17, Z+3\r
641         ANDI    R17, 0xF7\r
642         STD     Z+3, R17\r
643 //  244 \r
644 //  245         __enable_interrupt();\r
645         SEI\r
646 //  246 }\r
647         RET\r
648         REQUIRE _A_PORTB\r
649         REQUIRE _A_DDRB\r
650         REQUIRE _A_USICR\r
651 //  247 \r
652 //  248 \r
653 //  249 // Put one byte on bus. Use this function like you would write to the SPDR\r
654 //  250 // register in the native SPI module. Calling this function will prepare a\r
655 //  251 // byte for the next transfer initiated by the master device. If a transfer\r
656 //  252 // is in progress, this function will set the write collision flag and return\r
657 //  253 // without altering the data registers.\r
658 //  254 //\r
659 //  255 // Returns 0 if a write collision occurred, 1 otherwise.\r
660 //  256 /*! \brief Write a byte to SPI bus\r
661 //  257  *\r
662 //  258  * This function first checks if a transmission is in progress, and if so, flags\r
663 //  259  * a write collision, and returns FALSE.\n\r
664 //  260  * If a transmission is not in progress, the flags for write collision and\r
665 //  261  * transfer complete are cleared, and the input byte is written to SPDR.\n\r
666 //  262  *\r
667 //  263  * \param val The byte to send.\r
668 //  264  *\r
669 //  265  * \retval FALSE A write collision happened.\r
670 //  266  * \retval TRUE Byte written to SPDR.\r
671 //  267  */\r
672 \r
673         RSEG CODE:CODE:NOROOT(1)\r
674 //  268 unsigned char SPI_Put(unsigned char val)\r
675 SPI_Put:\r
676 //  269 {\r
677         MOV     R17, R16\r
678 //  270         // Check if transmission in progress, i.e. if USI counter doesn't equal zero.\r
679 //  271         // If this fails, flag a write collision and return.\r
680 //  272         if((USISR & 0x0F) != 0) {\r
681         IN      R16, 0x0E\r
682         ANDI    R16, 0x0F\r
683         TST     R16\r
684         BREQ    ??SPI_Put_0\r
685 //  273                 SPI.WriteCollision = TRUE;\r
686         LDI     R30, LOW(SPI)\r
687         LDI     R31, (SPI) >> 8\r
688         LDD     R16, Z+3\r
689         ORI     R16, 0x08\r
690         STD     Z+3, R16\r
691 //  274                 return(FALSE);\r
692         LDI     R16, 0\r
693         RET\r
694 //  275         }\r
695 //  276 \r
696 //  277         // Reinitialize flags.\r
697 //  278         SPI.XferComplete = FALSE;\r
698 ??SPI_Put_0:\r
699         LDI     R30, LOW(SPI)\r
700         LDI     R31, (SPI) >> 8\r
701         LDD     R16, Z+3\r
702         ANDI    R16, 0xFB\r
703         STD     Z+3, R16\r
704 //  279         SPI.WriteCollision = FALSE;\r
705         LDI     R30, LOW(SPI)\r
706         LDI     R31, (SPI) >> 8\r
707         LDD     R16, Z+3\r
708         ANDI    R16, 0xF7\r
709         STD     Z+3, R16\r
710 //  280 \r
711 //  281         USIDR = val;  // Put data in USI data register.\r
712         OUT     0x0F, R17\r
713 //  282 \r
714 //  283         return (TRUE);\r
715         LDI     R16, 1\r
716         RET\r
717         REQUIRE _A_USIDR\r
718         REQUIRE _A_USISR\r
719 //  284 }\r
720 //  285 \r
721 //  286 \r
722 //  287 // Get one byte from bus. This function only returns the previous stored\r
723 //  288 // USIDR value. The transfer complete flag is not checked. Use this function\r
724 //  289 // like you would read from the SPDR register in the native SPI module.\r
725 //  290 /*! \brief Get the last byte received from SPI bus\r
726 //  291  *\r
727 //  292  * This function simply returns the last byte stored to the SPI status struct,\r
728 //  293  * without checking if a completed transfer is flagged.\r
729 //  294  *\r
730 //  295  * \retval SPI.Data The last byte read from SPI.\r
731 //  296  */\r
732 \r
733         RSEG CODE:CODE:NOROOT(1)\r
734 //  297 unsigned char SPI_Get(void)\r
735 SPI_Get:\r
736 //  298 {\r
737 //  299         return SPI.Data;\r
738         LDS     R16, SPI\r
739         RET\r
740 //  300 }\r
741 //  301 \r
742 //  302 \r
743 //  303 /*! \brief Wait for SPI transfer to complete\r
744 //  304  *\r
745 //  305  * This function waits for a transfer complete to be flagged.\r
746 //  306  */\r
747 \r
748         RSEG CODE:CODE:NOROOT(1)\r
749 //  307 void SPI_Wait(void)\r
750 SPI_Wait:\r
751 ??SPI_Wait_0:\r
752 //  308 {\r
753 //  309         do {  // Wait for transfer complete.\r
754 //  310         } while (SPI.XferComplete == FALSE);\r
755         LDI     R30, LOW(SPI)\r
756         LDI     R31, (SPI) >> 8\r
757         LDD     R16, Z+3\r
758         SBRS    R16, 2\r
759         RJMP    ??SPI_Wait_0\r
760 //  311 }\r
761         RET\r
762 \r
763         ASEGN ABSOLUTE:DATA:NOROOT,01cH\r
764 __?EECR:\r
765 \r
766         ASEGN ABSOLUTE:DATA:NOROOT,01dH\r
767 __?EEDR:\r
768 \r
769         ASEGN ABSOLUTE:DATA:NOROOT,01eH\r
770 __?EEARL:\r
771 \r
772         ASEGN ABSOLUTE:DATA:NOROOT,01fH\r
773 __?EEARH:\r
774 \r
775         COMMON INTVEC:CODE:ROOT(1)\r
776         ORG 16\r
777 `??USI_OVF_ISR??INTVEC 16`:\r
778         RJMP    USI_OVF_ISR\r
779 \r
780         RSEG INITTAB:CODE:NOROOT(0)\r
781 `?<Segment init: NEAR_Z>`:\r
782         DW      SFE(NEAR_Z) - SFB(NEAR_Z)\r
783         DW      SFB(NEAR_Z)\r
784         DW      0\r
785         REQUIRE ?need_segment_init\r
786 \r
787         END\r
788 // \r
789 //   5 bytes in segment ABSOLUTE\r
790 // 706 bytes in segment CODE\r
791 //   6 bytes in segment INITTAB\r
792 //   2 bytes in segment INTVEC\r
793 //   4 bytes in segment NEAR_Z\r
794 // \r
795 // 706 bytes of CODE memory (+ 8 bytes shared)\r
796 //   4 bytes of DATA memory (+ 5 bytes shared)\r
797 //\r
798 //Errors: none\r
799 //Warnings: none\r