Initial import
[avr_bc100.git] / BaseTinyFirmware / IAR / Release / List / USI.lst
1 ###############################################################################\r
2 #                                                                             #\r
3 # IAR Atmel AVR C/C++ Compiler V4.30F/W32               13/Mar/2008  04:52:02 #\r
4 # Copyright 1996-2007 IAR Systems. All rights reserved.                       #\r
5 #                                                                             #\r
6 #    Source file           =  C:\home\kevin\pub\src\bc100\IAR\USI.c           #\r
7 #    Command line          =  C:\home\kevin\pub\src\bc100\IAR\USI.c           #\r
8 #                             --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc10 #\r
9 #                             0\IAR\Release\Obj\ -D NDEBUG -lCN               #\r
10 #                             C:\home\kevin\pub\src\bc100\IAR\Release\List\   #\r
11 #                             -lB C:\home\kevin\pub\src\bc100\IAR\Release\Lis #\r
12 #                             t\ --initializers_in_flash -s9 --no_cross_call  #\r
13 #                             --no_tbaa -DENABLE_BIT_DEFINITIONS -e -I        #\r
14 #                             "C:\Program Files\IAR Systems\Embedded          #\r
15 #                             Workbench 4.0\avr\INC\" -I "C:\Program          #\r
16 #                             Files\IAR Systems\Embedded Workbench            #\r
17 #                             4.0\avr\INC\CLIB\" --eeprom_size 512            #\r
18 #                             --misrac=5-9,11-12,14,16-17,19-21,24-26,29-32,  #\r
19 #                             34-35,38-39,42-43,46,50,52-54,56-59,61-62,      #\r
20 #                             64-65,68-80,83-84,87-91,94-95,98-100,103-110,   #\r
21 #                             112-126                                         #\r
22 #    Enabled MISRA C rules =  5-9,11-12,14,16-17,19-21,24-26,29-32,34-35,     #\r
23 #                             38-39,42-43,46,50,52-54,56-59,61-62,64-65,      #\r
24 #                             68-80,83-84,87-91,94-95,98-100,103-110,112-126  #\r
25 #      Checked             =  5,7-9,11-12,14,17,19-21,24,29-32,34-35,38-39,   #\r
26 #                             42,46,50,52-54,56-59,61-62,64,68-69,71-80,      #\r
27 #                             83-84,87-89,91,94-95,98,100,104-105,108-109,    #\r
28 #                             112-115,118-126                                 #\r
29 #      Not checked         =  6,16,25-26,43,65,70,90,99,103,106-107,110,      #\r
30 #                             116-117                                         #\r
31 #    List file             =  C:\home\kevin\pub\src\bc100\IAR\Release\List\US #\r
32 #                             I.lst                                           #\r
33 #    Object file           =  C:\home\kevin\pub\src\bc100\IAR\Release\Obj\USI #\r
34 #                             .r90                                            #\r
35 #                                                                             #\r
36 #                                                                             #\r
37 ###############################################################################\r
38 \r
39 C:\home\kevin\pub\src\bc100\IAR\USI.c\r
40       1          /* This file has been prepared for Doxygen automatic documentation generation.*/\r
41       2          /*! \file *********************************************************************\r
42       3           *\r
43       4           * \brief\r
44       5           *      Functions for use of the Universal Serial Interface\r
45       6           *\r
46       7           *      Contains high level functions for initializing the USI as an SPI slave,\r
47       8           *      interrupt handling, sending and receiving single bytes.\r
48       9           *\r
49      10           * \par Application note:\r
50      11           *      AVR458: Charging Li-Ion Batteries with BC100 \n\r
51      12           *      AVR463: Charging NiMH Batteries with BC100\r
52      13           *\r
53      14           * \par Documentation:\r
54      15           *      For comprehensive code documentation, supported compilers, compiler\r
55      16           *      settings and supported devices see readme.html\r
56      17           *\r
57      18           * \author\r
58      19           *      Atmel Corporation: http://www.atmel.com \n\r
59      20           *      Support email: avr@atmel.com \n\r
60      21           *      Original author: \n\r
61      22           *\r
62      23           * $Name$\r
63      24           * $Revision: 2299 $\r
64      25           * $RCSfile$\r
65      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
66      27           * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
67      28           ******************************************************************************/\r
68      29          \r
69      30          #include <ioavr.h>\r
70 \r
71    \                                 In  segment ABSOLUTE, at 0x38\r
72    \   <unnamed> volatile __io _A_PORTB\r
73    \                     _A_PORTB:\r
74    \   00000000                      DS 1\r
75 \r
76    \                                 In  segment ABSOLUTE, at 0x37\r
77    \   <unnamed> volatile __io _A_DDRB\r
78    \                     _A_DDRB:\r
79    \   00000000                      DS 1\r
80 \r
81    \                                 In  segment ABSOLUTE, at 0x2f\r
82    \   <unnamed> volatile __io _A_USIDR\r
83    \                     _A_USIDR:\r
84    \   00000000                      DS 1\r
85 \r
86    \                                 In  segment ABSOLUTE, at 0x2e\r
87    \   <unnamed> volatile __io _A_USISR\r
88    \                     _A_USISR:\r
89    \   00000000                      DS 1\r
90 \r
91    \                                 In  segment ABSOLUTE, at 0x2d\r
92    \   <unnamed> volatile __io _A_USICR\r
93    \                     _A_USICR:\r
94    \   00000000                      DS 1\r
95      31          #include <inavr.h>\r
96      32          \r
97      33          #include "enums.h"\r
98      34          #include "structs.h"\r
99      35          \r
100      36          #include "main.h"\r
101      37          #include "ADC.h"\r
102      38          #include "battery.h"\r
103      39          #include "time.h"\r
104      40          #include "USI.h"\r
105      41          \r
106      42          \r
107      43          //******************************************************************************\r
108      44          // Variables\r
109      45          //******************************************************************************\r
110      46          //! SPI status struct\r
111 \r
112    \                                 In  segment NEAR_Z, align 1, keep-with-next\r
113    \   00000000                      REQUIRE `?<Segment init: NEAR_Z>`\r
114      47          SPI_Status_t SPI;\r
115    \                     SPI:\r
116    \   00000000                      DS 4\r
117      48          \r
118      49          \r
119      50          //******************************************************************************\r
120      51          //Functions\r
121      52          //*****************************************************************************\r
122      53          /*! \brief USI Counter Overflow Interrupt Service Routine\r
123      54           *\r
124      55           * When the USI counter overflows, a byte has been transferred.\n\r
125      56           * The USIDR contents are stored and flags are updated.\r
126      57           *\r
127      58           * The protocol is quite simple and has three sequential states: command,\r
128      59           * address and data.\r
129      60           * (Keep in mind that the Master is in charge of data clocking, which means\r
130      61           * there is a one byte "delay" from when the Slave puts something to SPI till\r
131      62           * the Master can read it.)\r
132      63           *\r
133      64           * 1. If a non-zero byte is received in the command state, the ISR will\r
134      65           * store the commands to the SPI struct (read/write, EEPROM/SRAM, number of\r
135      66           * bytes). To signal that the command was received, 0xCC is put to the SPI bus.\r
136      67           * If a zero byte (0x00) is received in the command state, it is simply ignored\r
137      68           * because it is an invalid command.\r
138      69           *\r
139      70           * 2. When a byte is received in the address state, it is stored to the SPI\r
140      71           * struct. To signal that the address was received, 0xBB is put to SPI bus.\r
141      72           * \r
142      73           * 3. In the data state, variables are read/written "from back to front" until\r
143      74           * the byte counter reaches zero. Since the Master is in charge of the data\r
144      75           * clocking, the Slave will go to command state before the last byte is\r
145      76           * transferred during reading. This means that the Master should send an \r
146      77           * invalid command when getting each byte, ie 0x00.\r
147      78           *\r
148      79           * If the time between two transfers is 1 second or more, the Slave\r
149      80           * automatically reverts to command state.\r
150      81           *\r
151      82           * \note Battery charging is not automatically halted during SPI communication.\r
152      83           * This means that the current charge state (current and voltage) will\r
153      84           * remain constant during heavy and prolonged serial traffic.\r
154      85           *\r
155      86           * \todo Variable writing not implemented yet.\r
156      87           * \todo EEPROM/SRAM flag doesn't really do anything with this implementation.\r
157      88           */\r
158      89          #pragma vector=USI_OVF_vect\r
159 \r
160    \                                 In  segment CODE, align 2, keep-with-next\r
161      90          __interrupt void USI_OVF_ISR(void)\r
162    \                     USI_OVF_ISR:\r
163      91          {\r
164    \   00000000   938A               ST      -Y, R24\r
165    \   00000002   93FA               ST      -Y, R31\r
166    \   00000004   93EA               ST      -Y, R30\r
167    \   00000006   923A               ST      -Y, R3\r
168    \   00000008   922A               ST      -Y, R2\r
169    \   0000000A   921A               ST      -Y, R1\r
170    \   0000000C   920A               ST      -Y, R0\r
171    \   0000000E   937A               ST      -Y, R23\r
172    \   00000010   936A               ST      -Y, R22\r
173    \   00000012   935A               ST      -Y, R21\r
174    \   00000014   934A               ST      -Y, R20\r
175    \   00000016   933A               ST      -Y, R19\r
176    \   00000018   932A               ST      -Y, R18\r
177    \   0000001A   931A               ST      -Y, R17\r
178    \   0000001C   930A               ST      -Y, R16\r
179    \   0000001E   B78F               IN      R24, 0x3F\r
180      92                 // If the communication timed out, set ST_CMD as current state.\r
181      93                 if (!Time_Left(TIMER_USI)) {\r
182    \   00000020   E000               LDI     R16, 0\r
183    \   00000022   ....               RCALL   Time_Left\r
184    \   00000024   2300               TST     R16\r
185    \   00000026   F431               BRNE    ??USI_OVF_ISR_0\r
186      94                         SPI.State = ST_CMD;\r
187    \   00000028   ....               LDI     R30, LOW(SPI)\r
188    \   0000002A   ....               LDI     R31, (SPI) >> 8\r
189    \   0000002C   8102               LDD     R16, Z+2\r
190    \   0000002E   730F               ANDI    R16, 0x3F\r
191    \   00000030   6400               ORI     R16, 0x40\r
192    \   00000032   8302               STD     Z+2, R16\r
193      95                 }\r
194      96          \r
195      97                 // Start communication timer. If further communication doesn't happen\r
196      98                 // within 1 second, the SPI communication state is reset to CMD.\r
197      99                 Time_Set(TIMER_USI, 0, 1, 0);\r
198    \                     ??USI_OVF_ISR_0:\r
199    \   00000034   E040               LDI     R20, 0\r
200    \   00000036   E011               LDI     R17, 1\r
201    \   00000038   E020               LDI     R18, 0\r
202    \   0000003A   E030               LDI     R19, 0\r
203    \   0000003C   E000               LDI     R16, 0\r
204    \   0000003E   ....               RCALL   Time_Set\r
205     100                 \r
206     101                 // Clear USI counter and flag completed transfer.\r
207     102                 USISR = (1<<USIOIF);\r
208    \   00000040   E400               LDI     R16, 64\r
209    \   00000042   B90E               OUT     0x0E, R16\r
210     103                 SPI.XferComplete = TRUE;\r
211    \   00000044   ....               LDI     R30, LOW(SPI)\r
212    \   00000046   ....               LDI     R31, (SPI) >> 8\r
213    \   00000048   8103               LDD     R16, Z+3\r
214    \   0000004A   6004               ORI     R16, 0x04\r
215    \   0000004C   8303               STD     Z+3, R16\r
216     104                 \r
217     105                 // Process incoming data.\r
218     106                 switch(SPI.State)       {\r
219    \   0000004E   8112               LDD     R17, Z+2\r
220    \   00000050   2F01               MOV     R16, R17\r
221    \   00000052   0F00               LSL     R16\r
222    \   00000054   1F00               ROL     R16\r
223    \   00000056   1F00               ROL     R16\r
224    \   00000058   7003               ANDI    R16, 0x03\r
225    \   0000005A   5001               SUBI    R16, 1\r
226    \   0000005C   F029               BREQ    ??USI_OVF_ISR_1\r
227    \   0000005E   950A               DEC     R16\r
228    \   00000060   F101               BREQ    ??USI_OVF_ISR_2\r
229    \   00000062   950A               DEC     R16\r
230    \   00000064   F131               BREQ    ??USI_OVF_ISR_3\r
231    \   00000066   C072               RJMP    ??USI_OVF_ISR_4\r
232     107                 // A valid SPI transfer starts with a Command Byte sent by the Master.\r
233     108                 case ST_CMD:   \r
234     109                         SPI.Data = USIDR;  // Store the transferred byte.\r
235    \                     ??USI_OVF_ISR_1:\r
236    \   00000068   B10F               IN      R16, 0x0F\r
237    \   0000006A   8300               ST      Z, R16\r
238     110                         \r
239     111                         // If the master sent 0, it is trying to get data. Ignore in this state.\r
240     112                         if (SPI.Data != 0) {\r
241    \   0000006C   2300               TST     R16\r
242    \   0000006E   F409               BRNE    $+2+2\r
243    \   00000070   C06D               RJMP    ??USI_OVF_ISR_4\r
244     113                                 // Does the master want to read or write?\r
245     114                                 if (SPI.Data & 0x40) {\r
246    \   00000072   FF06               SBRS    R16, 6\r
247    \   00000074   C003               RJMP    ??USI_OVF_ISR_5\r
248     115                                         SPI.Read = FALSE;\r
249    \   00000076   8103               LDD     R16, Z+3\r
250    \   00000078   7F0E               ANDI    R16, 0xFE\r
251    \   0000007A   C002               RJMP    ??USI_OVF_ISR_6\r
252     116                                 } else {\r
253     117                                         SPI.Read = TRUE;\r
254    \                     ??USI_OVF_ISR_5:\r
255    \   0000007C   8103               LDD     R16, Z+3\r
256    \   0000007E   6001               ORI     R16, 0x01\r
257    \                     ??USI_OVF_ISR_6:\r
258    \   00000080   8303               STD     Z+3, R16\r
259     118                                 }\r
260     119          \r
261     120                                         // From/to EEPROM or SRAM?\r
262     121                                 if (SPI.Data &0x80) {\r
263    \   00000082   8100               LD      R16, Z\r
264    \   00000084   FF07               SBRS    R16, 7\r
265    \   00000086   C003               RJMP    ??USI_OVF_ISR_7\r
266     122                                         SPI.EEPROM = TRUE;\r
267    \   00000088   8103               LDD     R16, Z+3\r
268    \   0000008A   6002               ORI     R16, 0x02\r
269    \   0000008C   C002               RJMP    ??USI_OVF_ISR_8\r
270     123                                 } else {\r
271     124                                         SPI.EEPROM = FALSE;\r
272    \                     ??USI_OVF_ISR_7:\r
273    \   0000008E   8103               LDD     R16, Z+3\r
274    \   00000090   7F0D               ANDI    R16, 0xFD\r
275    \                     ??USI_OVF_ISR_8:\r
276    \   00000092   8303               STD     Z+3, R16\r
277     125                                 }\r
278     126          \r
279     127                                 SPI.Count = (SPI.Data & 0x3F);  // Get number of bytes to receive/send.\r
280     128                                 SPI.State = ST_ADDR;  // The Master will send the address byte next.\r
281    \   00000094   8100               LD      R16, Z\r
282    \   00000096   730F               ANDI    R16, 0x3F\r
283    \   00000098   6800               ORI     R16, 0x80\r
284    \   0000009A   8302               STD     Z+2, R16\r
285     129          \r
286     130                                 SPI_Put(0xCC);  // Signal that command was received.\r
287    \   0000009C   EC0C               LDI     R16, 204\r
288    \                     ??USI_OVF_ISR_9:\r
289    \   0000009E   ....               RCALL   SPI_Put\r
290    \   000000A0   C055               RJMP    ??USI_OVF_ISR_4\r
291     131                         }\r
292     132                 break;\r
293     133          \r
294     134                                 \r
295     135                 case ST_ADDR:  \r
296     136                         SPI.Data = USIDR;  // Store the address.\r
297    \                     ??USI_OVF_ISR_2:\r
298    \   000000A2   B10F               IN      R16, 0x0F\r
299    \   000000A4   8300               ST      Z, R16\r
300     137                         SPI.Address = SPI.Data;\r
301    \   000000A6   8301               STD     Z+1, R16\r
302     138                         SPI.State = ST_DATA;  // The master will send/wait for data next.\r
303    \   000000A8   2F01               MOV     R16, R17\r
304    \   000000AA   6C00               ORI     R16, 0xC0\r
305    \   000000AC   8302               STD     Z+2, R16\r
306     139          \r
307     140                         SPI_Put(0xBB);  // Signal that address was received.\r
308    \   000000AE   EB0B               LDI     R16, 187\r
309    \   000000B0   CFF6               RJMP    ??USI_OVF_ISR_9\r
310     141                 break;\r
311     142          \r
312     143          \r
313     144                 // Note well: this will process at least one byte, regardless of Count.\r
314     145                 case ST_DATA:\r
315     146                         if (SPI.Count-- > 0) {\r
316    \                     ??USI_OVF_ISR_3:\r
317    \   000000B2   2F21               MOV     R18, R17\r
318    \   000000B4   7C10               ANDI    R17, 0xC0\r
319    \   000000B6   2F02               MOV     R16, R18\r
320    \   000000B8   950A               DEC     R16\r
321    \   000000BA   730F               ANDI    R16, 0x3F\r
322    \   000000BC   2B01               OR      R16, R17\r
323    \   000000BE   8302               STD     Z+2, R16\r
324    \   000000C0   732F               ANDI    R18, 0x3F\r
325    \   000000C2   F409               BRNE    $+2+2\r
326    \   000000C4   C040               RJMP    ??USI_OVF_ISR_10\r
327     147                                 // Write specified variable to SPI, "back to front".\r
328     148                                 if (SPI.Read) {\r
329    \   000000C6   8121               LDD     R18, Z+1\r
330    \   000000C8   8113               LDD     R17, Z+3\r
331    \   000000CA   FF10               SBRS    R17, 0\r
332    \   000000CC   C02E               RJMP    ??USI_OVF_ISR_11\r
333     149                                         switch (SPI.Address) {\r
334    \   000000CE   952A               DEC     R18\r
335    \   000000D0   F049               BREQ    ??USI_OVF_ISR_12\r
336    \   000000D2   952A               DEC     R18\r
337    \   000000D4   F071               BREQ    ??USI_OVF_ISR_13\r
338    \   000000D6   952A               DEC     R18\r
339    \   000000D8   F091               BREQ    ??USI_OVF_ISR_14\r
340    \   000000DA   952A               DEC     R18\r
341    \   000000DC   F0B1               BREQ    ??USI_OVF_ISR_15\r
342    \   000000DE   952A               DEC     R18\r
343    \   000000E0   F0E1               BREQ    ??USI_OVF_ISR_16\r
344    \   000000E2   C021               RJMP    ??USI_OVF_ISR_17\r
345     150                                         case ADR_ADCS:\r
346     151                                                 SPI_Put(*(((unsigned char*)&ADCS) + (SPI.Count)));\r
347    \                     ??USI_OVF_ISR_12:\r
348    \   000000E4   730F               ANDI    R16, 0x3F\r
349    \   000000E6   E010               LDI     R17, 0\r
350    \   000000E8   01F8               MOVW    R31:R30, R17:R16\r
351    \   000000EA   ....               SUBI    R30, LOW((-(ADCS) & 0xFFFF))\r
352    \   000000EC   ....               SBCI    R31, (-(ADCS) & 0xFFFF) >> 8\r
353    \                     ??USI_OVF_ISR_18:\r
354    \   000000EE   8100               LD      R16, Z\r
355    \   000000F0   CFD6               RJMP    ??USI_OVF_ISR_9\r
356     152                                         break;\r
357     153                                         \r
358     154                                         \r
359     155                                         case ADR_BATTACTIVE:\r
360     156                                                 SPI_Put(*((unsigned char*)&BattActive + (SPI.Count)));\r
361    \                     ??USI_OVF_ISR_13:\r
362    \   000000F2   730F               ANDI    R16, 0x3F\r
363    \   000000F4   E010               LDI     R17, 0\r
364    \   000000F6   01F8               MOVW    R31:R30, R17:R16\r
365    \   000000F8   ....               SUBI    R30, LOW((-(BattActive) & 0xFFFF))\r
366    \   000000FA   ....               SBCI    R31, (-(BattActive) & 0xFFFF) >> 8\r
367    \   000000FC   CFF8               RJMP    ??USI_OVF_ISR_18\r
368     157                                         break;\r
369     158                                         \r
370     159                                         \r
371     160                                         case ADR_BATTDATA:\r
372     161                                                 SPI_Put(*((unsigned char*)&BattData + (SPI.Count)));\r
373    \                     ??USI_OVF_ISR_14:\r
374    \   000000FE   730F               ANDI    R16, 0x3F\r
375    \   00000100   E010               LDI     R17, 0\r
376    \   00000102   01F8               MOVW    R31:R30, R17:R16\r
377    \   00000104   ....               SUBI    R30, LOW((-(BattData) & 0xFFFF))\r
378    \   00000106   ....               SBCI    R31, (-(BattData) & 0xFFFF) >> 8\r
379    \   00000108   CFF2               RJMP    ??USI_OVF_ISR_18\r
380     162                                         break;\r
381     163                                         \r
382     164                                         \r
383     165                                         case ADR_BATTCTRL:\r
384     166                                                 SPI_Put(*((__eeprom unsigned char*)&BattControl + (SPI.Count)));\r
385    \                     ??USI_OVF_ISR_15:\r
386    \   0000010A   730F               ANDI    R16, 0x3F\r
387    \   0000010C   E010               LDI     R17, 0\r
388    \   0000010E   ....               LDI     R20, LOW(BattControl)\r
389    \   00000110   ....               LDI     R21, (BattControl) >> 8\r
390    \   00000112   0F40               ADD     R20, R16\r
391    \   00000114   1F51               ADC     R21, R17\r
392    \   00000116   ....               RCALL   __eeget8_16\r
393    \   00000118   CFC2               RJMP    ??USI_OVF_ISR_9\r
394     167                                         break;\r
395     168                                         \r
396     169                                         case ADR_TIMERS:\r
397     170                                                 SPI_Put(*((unsigned char*)&timeval + (SPI.Count)));\r
398    \                     ??USI_OVF_ISR_16:\r
399    \   0000011A   730F               ANDI    R16, 0x3F\r
400    \   0000011C   E010               LDI     R17, 0\r
401    \   0000011E   01F8               MOVW    R31:R30, R17:R16\r
402    \   00000120   ....               SUBI    R30, LOW((-(timeval) & 0xFFFF))\r
403    \   00000122   ....               SBCI    R31, (-(timeval) & 0xFFFF) >> 8\r
404    \   00000124   CFE4               RJMP    ??USI_OVF_ISR_18\r
405     171                                         break;\r
406     172          \r
407     173                                         \r
408     174                                         default:\r
409     175                                                 SPI_Put(0);\r
410    \                     ??USI_OVF_ISR_17:\r
411    \   00000126   E000               LDI     R16, 0\r
412    \   00000128   CFBA               RJMP    ??USI_OVF_ISR_9\r
413     176                                         break;\r
414     177                                         }\r
415     178                                 } else {\r
416     179                                         // Read byte from SPI\r
417     180                                         SPI.Data = USIDR;\r
418    \                     ??USI_OVF_ISR_11:\r
419    \   0000012A   B11F               IN      R17, 0x0F\r
420    \   0000012C   8310               ST      Z, R17\r
421     181          \r
422     182                                         // ********************************************\r
423     183                                         // THIS FUNCTION HAS NOT BEEN FULLY IMPLEMENTED\r
424     184                                         // ********************************************\r
425     185                                                                         \r
426     186                                         // Save byte to specified variable.\r
427     187                                         switch (SPI.Address) {\r
428    \   0000012E   5024               SUBI    R18, 4\r
429    \   00000130   F469               BRNE    ??USI_OVF_ISR_4\r
430     188                                         case ADR_BATTCTRL:\r
431     189                                                 *((__eeprom unsigned char*)&BattControl + SPI.Count) = SPI.Data;\r
432    \   00000132   2F21               MOV     R18, R17\r
433    \   00000134   730F               ANDI    R16, 0x3F\r
434    \   00000136   E010               LDI     R17, 0\r
435    \   00000138   ....               LDI     R20, LOW(BattControl)\r
436    \   0000013A   ....               LDI     R21, (BattControl) >> 8\r
437    \   0000013C   0F40               ADD     R20, R16\r
438    \   0000013E   1F51               ADC     R21, R17\r
439    \   00000140   2F02               MOV     R16, R18\r
440    \   00000142   ....               RCALL   __eeput8_16\r
441    \   00000144   C003               RJMP    ??USI_OVF_ISR_4\r
442     190                                         break;\r
443     191          \r
444     192                                         \r
445     193                                         default:\r
446     194                                         break;\r
447     195                                         }\r
448     196                                 }\r
449     197                                 \r
450     198          \r
451     199                         } else {\r
452     200                                 SPI.State = ST_CMD;\r
453    \                     ??USI_OVF_ISR_10:\r
454    \   00000146   730F               ANDI    R16, 0x3F\r
455    \   00000148   6400               ORI     R16, 0x40\r
456    \   0000014A   8302               STD     Z+2, R16\r
457     201                         }\r
458     202                 break;\r
459     203          \r
460     204                 default:  // Shouldn't end up here. (Unknown SPI-state)\r
461     205                 break;\r
462     206                 }\r
463     207          }\r
464    \                     ??USI_OVF_ISR_4:\r
465    \   0000014C   BF8F               OUT     0x3F, R24\r
466    \   0000014E   9109               LD      R16, Y+\r
467    \   00000150   9119               LD      R17, Y+\r
468    \   00000152   9129               LD      R18, Y+\r
469    \   00000154   9139               LD      R19, Y+\r
470    \   00000156   9149               LD      R20, Y+\r
471    \   00000158   9159               LD      R21, Y+\r
472    \   0000015A   9169               LD      R22, Y+\r
473    \   0000015C   9179               LD      R23, Y+\r
474    \   0000015E   9009               LD      R0, Y+\r
475    \   00000160   9019               LD      R1, Y+\r
476    \   00000162   9029               LD      R2, Y+\r
477    \   00000164   9039               LD      R3, Y+\r
478    \   00000166   91E9               LD      R30, Y+\r
479    \   00000168   91F9               LD      R31, Y+\r
480    \   0000016A   9189               LD      R24, Y+\r
481    \   0000016C   9518               RETI\r
482    \   0000016E                      REQUIRE _A_USIDR\r
483    \   0000016E                      REQUIRE _A_USISR\r
484     208          \r
485     209          \r
486     210          /*! \brief Initializes USI as an SPI slave\r
487     211           *\r
488     212           * Initializes USI as a 3-wire SPI slave using the pins specified in USI.h for\r
489     213           * I/O and clock, and USI counter overflow interrupts enabled.\n\r
490     214           * Also initializes the SPI status struct.\r
491     215           * \r
492     216           * \param spi_mode Specifies if USI should trigger on positive (0) or negative\r
493     217           * (1) edge of clock signal\r
494     218           *\r
495     219           * \note Clears the stored data\r
496     220           *\r
497     221           * \todo Timer should reset SPI protocol on timeout\r
498     222           */\r
499 \r
500    \                                 In  segment CODE, align 2, keep-with-next\r
501     223          void SPI_Init(unsigned char spi_mode)\r
502    \                     SPI_Init:\r
503     224          {\r
504     225                 __disable_interrupt();\r
505    \   00000000   94F8               CLI\r
506     226                 \r
507     227                 // Configure outputs and inputs, enable pull-ups for DATAIN and CLOCK pins.\r
508     228                 USI_DIR_REG |= (1<<USI_DATAOUT_PIN);\r
509    \   00000002   9AB9               SBI     0x17, 0x01\r
510     229                 USI_DIR_REG &= ~((1<<USI_DATAIN_PIN) | (1<<USI_CLOCK_PIN));\r
511    \   00000004   B317               IN      R17, 0x17\r
512    \   00000006   7F1A               ANDI    R17, 0xFA\r
513    \   00000008   BB17               OUT     0x17, R17\r
514     230                 USI_OUT_REG |= (1<<USI_DATAIN_PIN) | (1<<USI_CLOCK_PIN);\r
515    \   0000000A   B318               IN      R17, 0x18\r
516    \   0000000C   6015               ORI     R17, 0x05\r
517    \   0000000E   BB18               OUT     0x18, R17\r
518     231                 \r
519     232                 // Configure USI to 3-wire slave mode with overflow interrupt\r
520     233                 USICR = ( (1<<USIOIE) | (1<<USIWM0) | (1<<USICS1) | (spi_mode<<USICS0) );\r
521    \   00000010   0F00               LSL     R16\r
522    \   00000012   0F00               LSL     R16\r
523    \   00000014   6508               ORI     R16, 0x58\r
524    \   00000016   B90D               OUT     0x0D, R16\r
525     234          \r
526     235                 // Initialize the SPI struct\r
527     236                 SPI.Data = 0;                 // Clear data.\r
528    \   00000018   ....               LDI     R30, LOW(SPI)\r
529    \   0000001A   ....               LDI     R31, (SPI) >> 8\r
530    \   0000001C   E000               LDI     R16, 0\r
531    \   0000001E   8300               ST      Z, R16\r
532     237                 SPI.State = ST_CMD;           // Initial SPI state: wait for command.\r
533     238                 SPI.Read = FALSE;             // Doesn't matter right now.\r
534     239                 SPI.EEPROM = FALSE;           // Doesn't matter right now.\r
535    \   00000020   8103               LDD     R16, Z+3\r
536    \   00000022   7F0C               ANDI    R16, 0xFC\r
537    \   00000024   8303               STD     Z+3, R16\r
538     240                 SPI.Count = 0;                // Doesn't matter right now.\r
539    \   00000026   E400               LDI     R16, 64\r
540    \   00000028   8302               STD     Z+2, R16\r
541     241                 SPI.Address = 0;              // Doesn't matter right now.\r
542    \   0000002A   E000               LDI     R16, 0\r
543    \   0000002C   8301               STD     Z+1, R16\r
544     242                 SPI.XferComplete = FALSE;     // We haven't even started a transfer yet.\r
545     243                 SPI.WriteCollision = FALSE;   // ..And therefore a collision hasn't happened.\r
546    \   0000002E   8103               LDD     R16, Z+3\r
547    \   00000030   7F03               ANDI    R16, 0xF3\r
548    \   00000032   8303               STD     Z+3, R16\r
549     244          \r
550     245                 __enable_interrupt();\r
551    \   00000034   9478               SEI\r
552     246          }\r
553    \   00000036   9508               RET\r
554    \   00000038                      REQUIRE _A_PORTB\r
555    \   00000038                      REQUIRE _A_DDRB\r
556    \   00000038                      REQUIRE _A_USICR\r
557     247          \r
558     248          \r
559     249          // Put one byte on bus. Use this function like you would write to the SPDR\r
560     250          // register in the native SPI module. Calling this function will prepare a\r
561     251          // byte for the next transfer initiated by the master device. If a transfer\r
562     252          // is in progress, this function will set the write collision flag and return\r
563     253          // without altering the data registers.\r
564     254          //\r
565     255          // Returns 0 if a write collision occurred, 1 otherwise.\r
566     256          /*! \brief Write a byte to SPI bus\r
567     257           *\r
568     258           * This function first checks if a transmission is in progress, and if so, flags\r
569     259           * a write collision, and returns FALSE.\n\r
570     260           * If a transmission is not in progress, the flags for write collision and\r
571     261           * transfer complete are cleared, and the input byte is written to SPDR.\n\r
572     262           *\r
573     263           * \param val The byte to send.\r
574     264           *\r
575     265           * \retval FALSE A write collision happened.\r
576     266           * \retval TRUE Byte written to SPDR.\r
577     267           */\r
578 \r
579    \                                 In  segment CODE, align 2, keep-with-next\r
580     268          unsigned char SPI_Put(unsigned char val)\r
581    \                     SPI_Put:\r
582     269          {\r
583     270                 // Check if transmission in progress, i.e. if USI counter doesn't equal zero.\r
584     271                 // If this fails, flag a write collision and return.\r
585     272                 if((USISR & 0x0F) != 0) {\r
586    \   00000000   B11E               IN      R17, 0x0E\r
587    \   00000002   701F               ANDI    R17, 0x0F\r
588    \   00000004   ....               LDI     R30, LOW(SPI)\r
589    \   00000006   ....               LDI     R31, (SPI) >> 8\r
590    \   00000008   F029               BREQ    ??SPI_Put_0\r
591     273                         SPI.WriteCollision = TRUE;\r
592    \   0000000A   8103               LDD     R16, Z+3\r
593    \   0000000C   6008               ORI     R16, 0x08\r
594    \   0000000E   8303               STD     Z+3, R16\r
595     274                         return(FALSE);\r
596    \   00000010   E000               LDI     R16, 0\r
597    \   00000012   9508               RET\r
598     275                 }\r
599     276          \r
600     277                 // Reinitialize flags.\r
601     278                 SPI.XferComplete = FALSE;\r
602     279                 SPI.WriteCollision = FALSE;\r
603    \                     ??SPI_Put_0:\r
604    \   00000014   8113               LDD     R17, Z+3\r
605    \   00000016   7F13               ANDI    R17, 0xF3\r
606    \   00000018   8313               STD     Z+3, R17\r
607     280          \r
608     281                 USIDR = val;  // Put data in USI data register.\r
609    \   0000001A   B90F               OUT     0x0F, R16\r
610     282          \r
611     283                 return (TRUE);\r
612    \   0000001C   E001               LDI     R16, 1\r
613    \   0000001E   9508               RET\r
614    \   00000020                      REQUIRE _A_USIDR\r
615    \   00000020                      REQUIRE _A_USISR\r
616     284          }\r
617     285          \r
618     286          \r
619     287          // Get one byte from bus. This function only returns the previous stored\r
620     288          // USIDR value. The transfer complete flag is not checked. Use this function\r
621     289          // like you would read from the SPDR register in the native SPI module.\r
622     290          /*! \brief Get the last byte received from SPI bus\r
623     291           *\r
624     292           * This function simply returns the last byte stored to the SPI status struct,\r
625     293           * without checking if a completed transfer is flagged.\r
626     294           *\r
627     295           * \retval SPI.Data The last byte read from SPI.\r
628     296           */\r
629 \r
630    \                                 In  segment CODE, align 2, keep-with-next\r
631     297          unsigned char SPI_Get(void)\r
632    \                     SPI_Get:\r
633     298          {\r
634     299                 return SPI.Data;\r
635    \   00000000   9100....           LDS     R16, SPI\r
636    \   00000004   9508               RET\r
637     300          }\r
638     301          \r
639     302          \r
640     303          /*! \brief Wait for SPI transfer to complete\r
641     304           *\r
642     305           * This function waits for a transfer complete to be flagged.\r
643     306           */\r
644 \r
645    \                                 In  segment CODE, align 2, keep-with-next\r
646     307          void SPI_Wait(void)\r
647    \                     SPI_Wait:\r
648     308          {\r
649    \   00000000   9100....           LDS     R16, (SPI + 3)\r
650    \   00000004   FF02               SBRS    R16, 2\r
651     309                 do {  // Wait for transfer complete.\r
652     310                 } while (SPI.XferComplete == FALSE);\r
653    \                     ??SPI_Wait_0:\r
654    \   00000006   CFFF               RJMP    ??SPI_Wait_0\r
655     311          }\r
656    \                     ??SPI_Wait_1:\r
657    \   00000008   9508               RET\r
658 \r
659    \                                 In  segment INTVEC, offset 0x10, root\r
660    \                     `??USI_OVF_ISR??INTVEC 16`:\r
661    \   00000010   ....               RJMP    USI_OVF_ISR\r
662 \r
663    Maximum stack usage in bytes:\r
664 \r
665      Function       CSTACK RSTACK\r
666      --------       ------ ------\r
667      SPI_Get            0      2\r
668      SPI_Init           0      2\r
669      SPI_Put            0      2\r
670      SPI_Wait           0      2\r
671      USI_OVF_ISR       15      4\r
672        -> Time_Left    15      2\r
673        -> Time_Set     15      2\r
674        -> SPI_Put      15      2\r
675        -> SPI_Put      15      2\r
676        -> SPI_Put      15      2\r
677        -> SPI_Put      15      2\r
678        -> SPI_Put      15      2\r
679        -> SPI_Put      15      2\r
680        -> SPI_Put      15      2\r
681        -> SPI_Put      15      2\r
682 \r
683 \r
684    Segment part sizes:\r
685 \r
686      Function/Label           Bytes\r
687      --------------           -----\r
688      _A_PORTB                    1\r
689      _A_DDRB                     1\r
690      _A_USIDR                    1\r
691      _A_USISR                    1\r
692      _A_USICR                    1\r
693      SPI                         4\r
694      USI_OVF_ISR               366\r
695      SPI_Init                   56\r
696      SPI_Put                    32\r
697      SPI_Get                     6\r
698      SPI_Wait                   10\r
699      ??USI_OVF_ISR??INTVEC 16    2\r
700       Others                     6\r
701 \r
702  \r
703    5 bytes in segment ABSOLUTE\r
704  470 bytes in segment CODE\r
705    6 bytes in segment INITTAB\r
706    2 bytes in segment INTVEC\r
707    4 bytes in segment NEAR_Z\r
708  \r
709  470 bytes of CODE memory (+ 8 bytes shared)\r
710    4 bytes of DATA memory (+ 5 bytes shared)\r
711 \r
712 Errors: none\r
713 Warnings: none\r