Initial import
[avr_bc100.git] / BaseTinyFirmware / IAR / Release / List / battery.s90
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\battery.c      /\r
7 //    Command line          =  C:\home\kevin\pub\src\bc100\IAR\battery.c      /\r
8 //                             --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc1 /\r
9 //                             00\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\Li /\r
12 //                             st\ --initializers_in_flash -s9                /\r
13 //                             --no_cross_call --no_tbaa                      /\r
14 //                             -DENABLE_BIT_DEFINITIONS -e -I "C:\Program     /\r
15 //                             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 --misrac=5-9,11-12,14,16-17, /\r
19 //                             19-21,24-26,29-32,34-35,38-39,42-43,46,50,     /\r
20 //                             52-54,56-59,61-62,64-65,68-80,83-84,87-91,     /\r
21 //                             94-95,98-100,103-110,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\b /\r
32 //                             attery.s90                                     /\r
33 //                                                                            /\r
34 //                                                                            /\r
35 ///////////////////////////////////////////////////////////////////////////////\r
36 \r
37         NAME battery\r
38 \r
39         RSEG CSTACK:DATA:NOROOT(0)\r
40         RSEG RSTACK:DATA:NOROOT(0)\r
41 \r
42         EXTERN ?Register_R4_is_cg_reg\r
43         EXTERN ?Register_R5_is_cg_reg\r
44         EXTERN ?Register_R6_is_cg_reg\r
45         EXTERN ?Register_R7_is_cg_reg\r
46         EXTERN ?Register_R8_is_cg_reg\r
47         EXTERN ?S_SHL_L02\r
48         EXTERN ?US_DIVMOD_L02\r
49         EXTERN ?need_segment_init\r
50         EXTERN __eeput8_16\r
51 \r
52         PUBWEAK `?<Segment init: NEAR_I>`\r
53         PUBWEAK `?<Segment init: NEAR_Z>`\r
54         PUBLIC BattActive\r
55         PUBLIC BattControl\r
56         PUBLIC BattData\r
57         PUBLIC BattEEPROM\r
58         PUBLIC BatteryCheck\r
59         PUBLIC BatteryDataRefresh\r
60         PUBLIC BatteryStatusRefresh\r
61         PUBLIC DisableBatteries\r
62         PUBLIC EnableBattery\r
63         PUBLIC NTC\r
64         PUBLIC NTCLookUp\r
65         PUBLIC RID\r
66         PUBLIC RIDLookUp\r
67         PUBWEAK _A_OCR1B\r
68         PUBWEAK _A_PORTB\r
69         PUBWEAK __?EEARH\r
70         PUBWEAK __?EEARL\r
71         PUBWEAK __?EECR\r
72         PUBWEAK __?EEDR\r
73 \r
74         EXTERN OWI_DetectPresence\r
75         EXTERN OWI_SendByte\r
76         EXTERN OWI_ReceiveByte\r
77         EXTERN OWI_ComputeCRC8\r
78         EXTERN Time_Set\r
79         EXTERN Time_Left\r
80         EXTERN ADCS\r
81 \r
82 // C:\home\kevin\pub\src\bc100\IAR\battery.c\r
83 //    1 /* This file has been prepared for Doxygen automatic documentation generation.*/\r
84 //    2 /*! \file *********************************************************************\r
85 //    3  *\r
86 //    4  * \brief\r
87 //    5  *      Functions related to battery control and data acquisition.\r
88 //    6  *\r
89 //    7  *      Contains functions for enabling/disabling batteries, and looking up\r
90 //    8  *      their status and specifications using the ADC.\r
91 //    9  *\r
92 //   10  * \par Application note:\r
93 //   11  *      AVR458: Charging Li-Ion Batteries with BC100 \n\r
94 //   12  *      AVR463: Charging NiMH Batteries with BC100\r
95 //   13 \r
96 //   14  *\r
97 //   15  * \par Documentation\r
98 //   16  *      For comprehensive code documentation, supported compilers, compiler \r
99 //   17  *      settings and supported devices see readme.html\r
100 //   18  *\r
101 //   19  * \author\r
102 //   20  *      Atmel Corporation: http://www.atmel.com \n\r
103 //   21  *      Support email: avr@atmel.com\r
104 //   22  *\r
105 //   23  * \r
106 //   24  * $Name$\r
107 //   25  * $Revision: 2299 $\r
108 //   26  * $RCSfile$\r
109 //   27  * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/battery.c $\r
110 //   28  * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
111 //   29  ******************************************************************************/\r
112 //   30 \r
113 //   31 #include <ioavr.h>\r
114 \r
115         ASEGN ABSOLUTE:DATA:NOROOT,04cH\r
116 // <unnamed> volatile __io _A_OCR1B\r
117 _A_OCR1B:\r
118         DS 1\r
119 \r
120         ASEGN ABSOLUTE:DATA:NOROOT,038H\r
121 // <unnamed> volatile __io _A_PORTB\r
122 _A_PORTB:\r
123         DS 1\r
124 //   32 #include <inavr.h>\r
125 //   33 \r
126 //   34 #include "structs.h"\r
127 //   35 #include "enums.h"\r
128 //   36 \r
129 //   37 #include "ADC.h"\r
130 //   38 #include "battery.h"\r
131 //   39 #include "main.h"\r
132 //   40 #include "OWI.h"\r
133 //   41 #include "time.h"\r
134 //   42 \r
135 //   43 #ifdef NIMH\r
136 //   44 #include "NIMHspecs.h"\r
137 //   45 #endif // NIMH\r
138 //   46 \r
139 //   47 #ifdef LIION\r
140 //   48 #include "LIIONspecs.h"\r
141 //   49 #endif // LIION\r
142 //   50 \r
143 //   51 \r
144 //   52 \r
145 //   53 //******************************************************************************\r
146 //   54 // Variables\r
147 //   55 //******************************************************************************\r
148 //   56 /* Control-struct for batteries */\r
149 //   57 /*! \brief Holds control data for both batteries\r
150 //   58  * \note Stored in EEPROM.\r
151 //   59  */\r
152 \r
153         RSEG EEPROM_I:XDATA:NOROOT(0)\r
154 //   60 __eeprom Battery_t BattControl[2] = {{TRUE, TRUE, FALSE},\r
155 BattControl:\r
156         DB 3, 3\r
157 //   61                                      {TRUE, TRUE, FALSE}};\r
158 //   62 \r
159 //   63 /* Data-struct for battery */\r
160 \r
161         RSEG NEAR_Z:DATA:NOROOT(0)\r
162         REQUIRE `?<Segment init: NEAR_Z>`\r
163 //   64 Batteries_t BattData; //!< Holds data for the current battery\r
164 BattData:\r
165         DS 12\r
166 //   65 \r
167 //   66 \r
168 //   67 /* Storage for battery EPROM */\r
169 //   68 /*! \brief Storage space for data from the batteries' own EPROMs.\r
170 //   69  * \note Stored in EEPROM.\r
171 //   70  */\r
172 \r
173         RSEG EEPROM_I:XDATA:NOROOT(0)\r
174 //   71 __eeprom unsigned char BattEEPROM[4][32];\r
175 BattEEPROM:\r
176         DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
177         DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
178         DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
179         DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
180         DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
181         DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
182         DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
183         DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
184 //   72 \r
185 //   73 \r
186 //   74 //! Global that indicates current battery (0 = battery A, 1 = B)\r
187 \r
188         RSEG NEAR_Z:DATA:NOROOT(0)\r
189         REQUIRE `?<Segment init: NEAR_Z>`\r
190 //   75 unsigned char BattActive;\r
191 BattActive:\r
192         DS 1\r
193 //   76 \r
194 //   77 \r
195 //   78 /*! \brief RID lookup-table\r
196 //   79  *\r
197 //   80  * Contains Resistor ID data specified by manufacturer.\r
198 //   81  *\r
199 //   82  * \note Values have been calculated assuming a +/- 15% tolerance.\r
200 //   83  */\r
201 \r
202         RSEG NEAR_I:DATA:NOROOT(0)\r
203         REQUIRE `?<Segment init: NEAR_I>`\r
204 //   84 const RID_Lookup_t RID[RID_TABLE_SIZE] = {\r
205 RID:\r
206         DS 56\r
207         REQUIRE `?<Initializer for RID>`\r
208 //   85   {558, 659, 3900, 550, 260, 300, 10},\r
209 //   86   {744, 843, 6800, 750, 360, 300, 14},\r
210 //   87   {869, 958, 10000, 1000, 475, 300, 19},\r
211 //   88   {1097, 1153, 24000, 2000, 475, 420, 38}\r
212 //   89 };\r
213 //   90 \r
214 //   91 \r
215 //   92 /*! \brief NTC lookup-table\r
216 //   93  *\r
217 //   94  * The first entry is 0 degrees. For every entry after, temperature increases\r
218 //   95  * with 4 degrees. With 20 entries, the last one equals (20-1)*4 = 76 degrees.\n\r
219 //   96  * It must be sorted in descending ADC order.\r
220 //   97  *\r
221 //   98  * \note This was calculated for a Mitsubishi RH16-3H103FB NTC.\r
222 //   99  *\r
223 //  100  * \note NTCLookUp() must be modified if this table is changed so that:\r
224 //  101  * - first entry is no longer 0 degrees.\r
225 //  102  * - temperature difference between entries is no longer 4 degrees.\r
226 //  103  * - ADCsteps no longer specifies ADC steps per half degree.\r
227 //  104  */\r
228 //  105 // FOR VARTA POLYFLEX NTC\r
229 \r
230         RSEG NEAR_I:DATA:NOROOT(0)\r
231         REQUIRE `?<Segment init: NEAR_I>`\r
232 //  106 const NTC_Lookup_t NTC[NTC_TABLE_SIZE] = {\r
233 NTC:\r
234         DS 60\r
235         REQUIRE `?<Initializer for NTC>`\r
236 //  107         {1002, 23}, {953, 25}, {902, 26}, {849, 27}, {796, 27},\r
237 //  108         {742, 27}, {689, 26}, {637, 26}, {587, 25}, {539, 24},\r
238 //  109         {494, 22}, {451, 21}, {412, 19}, {375, 18}, {341, 17},\r
239 //  110         {310, 15}, {282, 14}, {256, 13}, {233, 11}, {212, 10}\r
240 //  111 };\r
241 //  112 \r
242 //  113 \r
243 //  114 // FOR MITSUBISHI NTC\r
244 //  115 /*\r
245 //  116 const NTC_Lookup_t NTC[NTC_TABLE_SIZE] = {\r
246 //  117   {1004, 24}, {954, 25}, {903, 26}, {850, 27}, {796, 27},\r
247 //  118   {742, 27}, {689, 27}, {637, 26}, {587, 25}, {539, 24},\r
248 //  119   {493, 22}, {451, 21}, {411, 20}, {374, 18}, {340, 17},\r
249 //  120   {309, 15}, {281, 14}, {255, 13}, {232, 11}, {211, 10}\r
250 //  121 };\r
251 //  122 */\r
252 //  123 \r
253 //  124 \r
254 //  125 //******************************************************************************\r
255 //  126 // Functions\r
256 //  127 //******************************************************************************\r
257 //  128 /*! \brief Checks if battery has changed\r
258 //  129  *\r
259 //  130  * Stores current capacity, then attempts to refresh battery status.\n\r
260 //  131  * If the refresh is successful, old capacity is compared with the new one.\r
261 //  132  * \r
262 //  133  * \retval FALSE Battery is disconnected, or capacity has changed.\r
263 //  134  * \retval TRUE All OK.\r
264 //  135  */\r
265 \r
266         RSEG CODE:CODE:NOROOT(1)\r
267 //  136 unsigned char BatteryCheck(void)\r
268 BatteryCheck:\r
269 //  137 {\r
270         ST      -Y, R27\r
271         ST      -Y, R26\r
272         ST      -Y, R24\r
273 //  138         unsigned char success = TRUE;\r
274         LDI     R24, 1\r
275 //  139         unsigned int  oldCapacity;\r
276 //  140         \r
277 //  141         // Save to see if battery data has changed.\r
278 //  142         oldCapacity = BattData.Capacity;  \r
279         LDI     R30, LOW(BattData)\r
280         LDI     R31, (BattData) >> 8\r
281         LDD     R26, Z+4\r
282         LDD     R27, Z+5\r
283 //  143         \r
284 //  144         if (!BatteryStatusRefresh()) {\r
285         RCALL   BatteryStatusRefresh\r
286         TST     R16\r
287         BRNE    ??BatteryCheck_0\r
288 //  145                 success = FALSE;              // Battery not present or RID was invalid.\r
289         LDI     R24, 0\r
290 //  146         }\r
291 //  147         \r
292 //  148         if (oldCapacity != BattData.Capacity) {\r
293 ??BatteryCheck_0:\r
294         LDI     R30, LOW(BattData)\r
295         LDI     R31, (BattData) >> 8\r
296         LDD     R16, Z+4\r
297         LDD     R17, Z+5\r
298         CP      R26, R16\r
299         CPC     R27, R17\r
300         BREQ    ??BatteryCheck_1\r
301 //  149                 success = FALSE;              // Battery configuration has changed.\r
302         LDI     R24, 0\r
303 //  150         }\r
304 //  151 \r
305 //  152         return(success);\r
306 ??BatteryCheck_1:\r
307         MOV     R16, R24\r
308         LD      R24, Y+\r
309         LD      R26, Y+\r
310         LD      R27, Y+\r
311         RET\r
312 //  153 }\r
313 //  154 \r
314 //  155 \r
315 //  156 /*! \brief Refreshes battery status information\r
316 //  157  *\r
317 //  158  * Refreshes battery status information, if it is present, based on\r
318 //  159  * RID and NTC (read by ADC).\n\r
319 //  160  * The battery must have been enabled and a complete set of ADC data must have\r
320 //  161  * been collected before calling.\n\r
321 //  162  *\r
322 //  163  * \retval FALSE No battery present.\r
323 //  164  * \retval TRUE Battery present, status refreshed.\r
324 //  165  *\r
325 //  166  * \note If ALLOW_NO_RID is defined, charging will NOT stop if no fitting entry\r
326 //  167  * is found in the lookup table. Instead, default battery data will be used.\r
327 //  168  */\r
328 \r
329         RSEG CODE:CODE:NOROOT(1)\r
330 //  169 unsigned char BatteryStatusRefresh(void)\r
331 BatteryStatusRefresh:\r
332 //  170 {\r
333         ST      -Y, R27\r
334         ST      -Y, R26\r
335         ST      -Y, R25\r
336         ST      -Y, R24\r
337 //  171         // Assume the worst..\r
338 //  172         unsigned char success = FALSE;\r
339 //  173         \r
340 //  174         BattData.Present = FALSE;\r
341 //  175         BattData.Charged = FALSE;\r
342 //  176         BattData.Low = TRUE;\r
343         LDI     R26, LOW(BattData)\r
344         LDI     R27, (BattData) >> 8\r
345         LD      R16, X\r
346         ANDI    R16, 0xFC\r
347         ORI     R16, 0x04\r
348         ST      X, R16\r
349 //  177         BattData.Circuit = OW_NONE;\r
350         LDI     R16, 0\r
351         MOVW    R31:R30, R27:R26\r
352         STD     Z+1, R16\r
353 //  178         BattData.Temperature = 0;\r
354         STD     Z+2, R16\r
355 //  179         BattData.Capacity = 0;\r
356         STD     Z+4, R16\r
357         STD     Z+5, R16\r
358 //  180         BattData.MaxCurrent = 0;\r
359         STD     Z+6, R16\r
360         STD     Z+7, R16\r
361 //  181         BattData.MaxTime = 0;\r
362         STD     Z+8, R16\r
363         STD     Z+9, R16\r
364 //  182         BattData.MinCurrent = 0;\r
365         STD     Z+10, R16\r
366         STD     Z+11, R16\r
367 //  183 \r
368 //  184         NTCLookUp();\r
369         RCALL   NTCLookUp\r
370 //  185         BattData.HasRID = RIDLookUp();\r
371         RCALL   RIDLookUp\r
372         MOV     R17, R16\r
373         ANDI    R17, 0x01\r
374         BST     R17, 0\r
375         LD      R16, X\r
376         BLD     R16, 4\r
377         ST      X, R16\r
378 //  186 \r
379 //  187         // Is the battery voltage above minimum safe cell voltage?\r
380 //  188         if (ADCS.VBAT >= BAT_VOLTAGE_MIN) {\r
381         LDI     R30, LOW(ADCS)\r
382         LDI     R31, (ADCS) >> 8\r
383         LDD     R16, Z+10\r
384         LDD     R17, Z+11\r
385         CPI     R16, 96\r
386         LDI     R18, 9\r
387         CPC     R17, R18\r
388         BRCS    ??BatteryStatusRefresh_0\r
389 //  189                 BattData.Low = FALSE;\r
390         LD      R16, X\r
391         ANDI    R16, 0xFB\r
392         ST      X, R16\r
393 //  190         }\r
394 //  191 \r
395 //  192         // Is the battery charged?\r
396 //  193         if (ADCS.VBAT >= BAT_VOLTAGE_LOW) {\r
397 ??BatteryStatusRefresh_0:\r
398         LDD     R16, Z+10\r
399         CPI     R16, 210\r
400         SBCI    R17, 15\r
401         BRCS    ??BatteryStatusRefresh_1\r
402 //  194                 BattData.Charged = TRUE;\r
403         LD      R16, X\r
404         ORI     R16, 0x02\r
405         ST      X, R16\r
406 //  195         }\r
407 //  196 \r
408 //  197         // If we are not charging, yet VBAT is above safe limit, battery is present.\r
409 //  198         // If we are charging and there's a current flowing, the battery is present.\r
410 //  199         \r
411 //  200         /*! \todo If ABORT_IF_PWM_MAX is defined this last check battery presence\r
412 //  201         * check is redundant since charging will be aborted due to low current at\r
413 //  202         * max duty cycle. That is preferrable since the charge current reading is\r
414 //  203         * not 100% proof.\r
415 //  204         */\r
416 //  205         if (((OCR1B == 0) && (!BattData.Low)) ||\r
417 //  206             ((OCR1B != 0) && (ADCS.avgIBAT > 0))) {\r
418 ??BatteryStatusRefresh_1:\r
419         IN      R16, 0x2C\r
420         TST     R16\r
421         BRNE    ??BatteryStatusRefresh_2\r
422         LD      R16, X\r
423         SBRS    R16, 2\r
424         RJMP    ??BatteryStatusRefresh_3\r
425 ??BatteryStatusRefresh_2:\r
426         IN      R16, 0x2C\r
427         TST     R16\r
428         BREQ    ??BatteryStatusRefresh_4\r
429         LDD     R24, Z+22\r
430         LDD     R25, Z+23\r
431         CPI     R24, 1\r
432         SBCI    R25, 0\r
433         BRLT    ??BatteryStatusRefresh_4\r
434 //  207                 BattData.Present = TRUE;\r
435 ??BatteryStatusRefresh_3:\r
436         LD      R16, X\r
437         ORI     R16, 0x01\r
438         ST      X, R16\r
439 //  208                 success = TRUE;\r
440         LDI     R16, 1\r
441         RJMP    ??BatteryStatusRefresh_5\r
442 //  209         } else {\r
443 //  210                 BattData.Low = FALSE;  // (This is just a technicality..)\r
444 ??BatteryStatusRefresh_4:\r
445         LD      R16, X\r
446         ANDI    R16, 0xFB\r
447         ST      X, R16\r
448 //  211                 success = FALSE;\r
449         LDI     R16, 0\r
450 //  212         }\r
451 //  213 \r
452 //  214 #ifndef ALLOW_NO_RID\r
453 //  215         // Return FALSE if no valid RID entry was found, to stop charging.\r
454 //  216         if(!BattData.HasRID) {\r
455 ??BatteryStatusRefresh_5:\r
456         LD      R17, X\r
457         SBRS    R17, 4\r
458 //  217                 success = FALSE;\r
459         LDI     R16, 0\r
460 //  218         }\r
461 //  219 #endif\r
462 //  220 \r
463 //  221         return(success);\r
464 ??BatteryStatusRefresh_6:\r
465         LD      R24, Y+\r
466         LD      R25, Y+\r
467         LD      R26, Y+\r
468         LD      R27, Y+\r
469         RET\r
470         REQUIRE _A_OCR1B\r
471 //  222 }\r
472 //  223 \r
473 //  224 \r
474 //  225 /*! \brief Refreshes battery data in the EEPROM\r
475 //  226  *\r
476 //  227  * Attempts to read 4 pages of 32 bytes each from the battery's EPROM and store\r
477 //  228  * these data in on-chip EEPROM.\n\r
478 //  229  * If unsuccessful (CRC doesn't check out), the on-chip EEPROM is cleared.\r
479 //  230  *\r
480 //  231  * \todo Updating BattData with these data. Specs needed.\r
481 //  232  *\r
482 //  233  * \retval FALSE Refresh failed.\r
483 //  234  * \retval TRUE Refresh successful.\r
484 //  235  */\r
485 \r
486         RSEG CODE:CODE:NOROOT(1)\r
487 //  236 unsigned char BatteryDataRefresh(void)\r
488 BatteryDataRefresh:\r
489 //  237 {\r
490         ST      -Y, R8\r
491         ST      -Y, R7\r
492         ST      -Y, R6\r
493         ST      -Y, R5\r
494         ST      -Y, R4\r
495         ST      -Y, R27\r
496         ST      -Y, R26\r
497         ST      -Y, R25\r
498         ST      -Y, R24\r
499         REQUIRE ?Register_R4_is_cg_reg\r
500         REQUIRE ?Register_R5_is_cg_reg\r
501         REQUIRE ?Register_R6_is_cg_reg\r
502         REQUIRE ?Register_R7_is_cg_reg\r
503         REQUIRE ?Register_R8_is_cg_reg\r
504 //  238         unsigned char offset;\r
505 //  239         unsigned char i, crc, family, temp, page;\r
506 //  240         unsigned char success;\r
507 //  241         \r
508 //  242         // Look for EPROM and read 4 pages of 32 bytes each worth of data, if found.\r
509 //  243         for (page = 0; page < 4; page++)        {\r
510         LDI     R25, 0\r
511         LDI     R26, LOW(BattEEPROM)\r
512         LDI     R27, (BattEEPROM) >> 8\r
513 //  244                 success = FALSE;\r
514 ??BatteryDataRefresh_0:\r
515         CLR     R7\r
516 //  245         \r
517 //  246                 if (OWI_DetectPresence(OWIBUS) == OWIBUS) {\r
518         LDI     R16, 1\r
519         RCALL   OWI_DetectPresence\r
520         CPI     R16, 1\r
521         BREQ    $+2+2\r
522         RJMP    ??BatteryDataRefresh_1\r
523 //  247                         \r
524 //  248                         // Presence detected, check type and CRC.\r
525 //  249                         OWI_SendByte(OWI_ROM_READ, OWIBUS);\r
526         LDI     R17, 1\r
527         LDI     R16, 51\r
528         RCALL   OWI_SendByte\r
529 //  250                         family = OWI_ReceiveByte(OWIBUS);\r
530         LDI     R16, 1\r
531         RCALL   OWI_ReceiveByte\r
532         MOV     R5, R16\r
533 //  251                         crc = OWI_ComputeCRC8(family,0);\r
534         LDI     R17, 0\r
535         RCALL   OWI_ComputeCRC8\r
536         MOV     R24, R16\r
537 //  252 \r
538 //  253                         for (i = 0; i < 6; i++) {\r
539         LDI     R16, 6\r
540         MOV     R4, R16\r
541 //  254                                 crc = OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc);\r
542 ??BatteryDataRefresh_2:\r
543         LDI     R16, 1\r
544         RCALL   OWI_ReceiveByte\r
545         MOV     R17, R24\r
546         RCALL   OWI_ComputeCRC8\r
547         MOV     R24, R16\r
548 //  255                         }\r
549         DEC     R4\r
550         BRNE    ??BatteryDataRefresh_2\r
551 //  256 \r
552 //  257                         // CRC ok, device found.\r
553 //  258                         if (OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc) == 0) {\r
554         LDI     R16, 1\r
555         RCALL   OWI_ReceiveByte\r
556         MOV     R17, R24\r
557         RCALL   OWI_ComputeCRC8\r
558         TST     R16\r
559         BRNE    ??BatteryDataRefresh_1\r
560 //  259                                 BattData.Circuit = family;\r
561         STS     (BattData + 1), R5\r
562 //  260 \r
563 //  261                                 // For now, we only read data from DS2505 EPROMs.\r
564 //  262                                 if (BattData.Circuit == OW_DS2505) {\r
565         LDS     R16, (BattData + 1)\r
566         CPI     R16, 9\r
567         BRNE    ??BatteryDataRefresh_1\r
568 //  263                                         offset = page*32;\r
569         MOV     R4, R25\r
570         SWAP    R4\r
571         LDI     R16, 240\r
572         AND     R4, R16\r
573         LSL     R4\r
574 //  264                                         OWI_SendByte(DS2505_DATA_READ, OWIBUS);  // Command: read data.\r
575         LDI     R17, 1\r
576         LDI     R16, 195\r
577         RCALL   OWI_SendByte\r
578 //  265                                         OWI_SendByte(offset, OWIBUS);            // Data: low address.\r
579         LDI     R17, 1\r
580         MOV     R16, R4\r
581         RCALL   OWI_SendByte\r
582 //  266                                         OWI_SendByte(0, OWIBUS);                 // Data: high address.\r
583         LDI     R17, 1\r
584         LDI     R16, 0\r
585         RCALL   OWI_SendByte\r
586 //  267 \r
587 //  268                                         // Calculate checksums.\r
588 //  269                                         crc = OWI_ComputeCRC8(DS2505_DATA_READ,0);\r
589         LDI     R17, 0\r
590         LDI     R16, 195\r
591         RCALL   OWI_ComputeCRC8\r
592 //  270                                         crc = OWI_ComputeCRC8(offset,crc);\r
593         MOV     R17, R16\r
594         MOV     R16, R4\r
595         RCALL   OWI_ComputeCRC8\r
596 //  271                                         crc = OWI_ComputeCRC8(0,crc);\r
597         MOV     R17, R16\r
598         LDI     R16, 0\r
599         RCALL   OWI_ComputeCRC8\r
600         MOV     R24, R16\r
601 //  272 \r
602 //  273                                         // Command received succesfully, now start reading data\r
603 //  274                                         // and writing it to EEPROM.\r
604 //  275                                         if (OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc) == 0) {\r
605         LDI     R16, 1\r
606         RCALL   OWI_ReceiveByte\r
607         MOV     R17, R24\r
608         RCALL   OWI_ComputeCRC8\r
609         TST     R16\r
610         BRNE    ??BatteryDataRefresh_1\r
611 //  276                                                 crc = 0;\r
612         LDI     R24, 0\r
613 //  277                                                 \r
614 //  278                                                 // Fill page with data.\r
615 //  279                                                 for (i=0; i<32; i++) {\r
616         MOVW    R5:R4, R27:R26\r
617         LDI     R16, 32\r
618         MOV     R6, R16\r
619 //  280                                                         temp = OWI_ReceiveByte(OWIBUS);\r
620 ??BatteryDataRefresh_3:\r
621         LDI     R16, 1\r
622         RCALL   OWI_ReceiveByte\r
623         MOV     R8, R16\r
624 //  281                                                         crc = OWI_ComputeCRC8(temp, crc);\r
625         MOV     R17, R24\r
626         RCALL   OWI_ComputeCRC8\r
627         MOV     R24, R16\r
628 //  282                                                         BattEEPROM[page][i] = temp;\r
629         MOV     R16, R8\r
630         MOVW    R21:R20, R5:R4\r
631         RCALL   __eeput8_16\r
632 //  283                                                 }\r
633         LDI     R16, 1\r
634         ADD     R4, R16\r
635         ADC     R5, R7\r
636         DEC     R6\r
637         BRNE    ??BatteryDataRefresh_3\r
638 //  284                                                 \r
639 //  285                                                 if (OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc) == 0) {\r
640         RCALL   OWI_ReceiveByte\r
641         MOV     R17, R24\r
642         RCALL   OWI_ComputeCRC8\r
643         TST     R16\r
644         BRNE    ??BatteryDataRefresh_1\r
645 //  286                                                                 success = TRUE;  // Data read OK\r
646         INC     R7\r
647         RJMP    ??BatteryDataRefresh_4\r
648 //  287                                                 }\r
649 //  288                                         } else { // Not able to start reading data.\r
650 //  289                                         }\r
651 //  290                                 } else { // Wrong device type.\r
652 //  291                                 }\r
653 //  292                         } else { // No device found.             \r
654 //  293                         }\r
655 //  294                 } else { // No presence detected on one-wire bus.\r
656 //  295                 }\r
657 //  296 \r
658 //  297           // Erase local EEPROM page if there were any errors during transfer.\r
659 //  298                 if (!success) {\r
660 //  299                         for (i=0; i<32; i++) {\r
661 ??BatteryDataRefresh_1:\r
662         MOVW    R21:R20, R27:R26\r
663         LDI     R17, 32\r
664 //  300                                 BattEEPROM[page][i] = 0;\r
665 ??BatteryDataRefresh_5:\r
666         LDI     R16, 0\r
667         RCALL   __eeput8_16\r
668 //  301                         }\r
669         SUBI    R20, 255\r
670         SBCI    R21, 255\r
671         DEC     R17\r
672         BRNE    ??BatteryDataRefresh_5\r
673 //  302                 }\r
674 //  303         }\r
675 ??BatteryDataRefresh_4:\r
676         INC     R25\r
677         ADIW    R27:R26, 32\r
678         CPI     R25, 4\r
679         BRCC    $+2+2\r
680         RJMP    ??BatteryDataRefresh_0\r
681 //  304 \r
682 //  305         return(success);\r
683         MOV     R16, R7\r
684         LD      R24, Y+\r
685         LD      R25, Y+\r
686         LD      R26, Y+\r
687         LD      R27, Y+\r
688         LD      R4, Y+\r
689         LD      R5, Y+\r
690         LD      R6, Y+\r
691         LD      R7, Y+\r
692         LD      R8, Y+\r
693         RET\r
694 //  306 }\r
695 //  307 \r
696 //  308 \r
697 //  309 /*! \brief Enables specified battery\r
698 //  310  *\r
699 //  311  * Updates \ref BattActive to specified battery, then sets PB4/PB5 and clears\r
700 //  312  * PB5/PB4 in PORTB, depending on which battery is specified.\n\r
701 //  313  * The function takes 100 ms to allow the port switch to settle.\r
702 //  314  *\r
703 //  315  * \param bat Specifies which battery to enable (0 = battery A, 1 = B)\r
704 //  316  */\r
705 \r
706         RSEG CODE:CODE:NOROOT(1)\r
707 //  317 void EnableBattery(unsigned char bat)\r
708 EnableBattery:\r
709 //  318 {\r
710         ST      -Y, R24\r
711         MOV     R24, R16\r
712 //  319         // Use general timer, set timeout to 100ms.\r
713 //  320         Time_Set(TIMER_GEN,0,0,100);\r
714         LDI     R20, 100\r
715         LDI     R17, 0\r
716         LDI     R18, 0\r
717         LDI     R19, 0\r
718         LDI     R16, 2\r
719         RCALL   Time_Set\r
720 //  321 \r
721 //  322         // Set specified battery as the active one.\r
722 //  323         BattActive = bat;\r
723         STS     BattActive, R24\r
724 //  324 \r
725 //  325         // Enable current battery in hardware, light LED & connect battery.\r
726 //  326         PORTB |= (1 << (PB4+bat));\r
727         LDI     R16, 1\r
728         LDI     R17, 0\r
729         MOV     R20, R24\r
730         SUBI    R20, 252\r
731         RCALL   ?S_SHL_L02\r
732         IN      R17, 0x18\r
733         OR      R17, R16\r
734         OUT     0x18, R17\r
735 //  327 \r
736 //  328         // Disconnect other battery.\r
737 //  329         PORTB &= ~(1<<(PB5-bat));     \r
738         LDI     R16, 1\r
739         LDI     R17, 0\r
740         LDI     R20, 5\r
741         SUB     R20, R24\r
742         RCALL   ?S_SHL_L02\r
743         COM     R16\r
744         IN      R17, 0x18\r
745         AND     R17, R16\r
746         OUT     0x18, R17\r
747 //  330 \r
748 //  331         do { // Let port switch settle.\r
749 //  332         } while (Time_Left(TIMER_GEN));  \r
750 ??EnableBattery_0:\r
751         LDI     R16, 2\r
752         RCALL   Time_Left\r
753         TST     R16\r
754         BRNE    ??EnableBattery_0\r
755 //  333 }\r
756         LD      R24, Y+\r
757         RET\r
758         REQUIRE _A_PORTB\r
759 //  334 \r
760 //  335 \r
761 //  336 /*! \brief Disables both batteries\r
762 //  337  *\r
763 //  338  * Clears PB4 and PB5 in PORTB, disabling both batteries.\r
764 //  339  */\r
765 \r
766         RSEG CODE:CODE:NOROOT(1)\r
767 //  340 void DisableBatteries(void)\r
768 DisableBatteries:\r
769 //  341 {\r
770 //  342         // Turn off LEDs and disconnect batteries.\r
771 //  343         PORTB &= ~((1<<PB4)|(1<<PB5));  \r
772         IN      R16, 0x18\r
773         ANDI    R16, 0xCF\r
774         OUT     0x18, R16\r
775 //  344 }\r
776         RET\r
777         REQUIRE _A_PORTB\r
778 //  345 \r
779 //  346 \r
780 //  347 /*! \brief Looks up battery data from RID table\r
781 //  348  *\r
782 //  349  * Attempts to find data for the battery from the RID lookup-table.\n\r
783 //  350  * If no valid entry is found, default data (defined in battery.h)\r
784 //  351  * are used.\r
785 //  352  *\r
786 //  353  * \retval TRUE Entry found, battery data updated.\r
787 //  354  * \retval FALSE No entry found, using defaults for battery data.\r
788 //  355  */\r
789 \r
790         RSEG CODE:CODE:NOROOT(1)\r
791 //  356 unsigned char RIDLookUp (void)\r
792 RIDLookUp:\r
793 //  357 {\r
794         MOV     R19, R27\r
795         MOV     R2, R26\r
796 //  358         unsigned char i, found = FALSE;\r
797         LDI     R20, 0\r
798 //  359                 \r
799 //  360         // Lookup in the RID-table. If measured RID is within the limits\r
800 //  361         // of an entry, those data are used, and TRUE is returned.\r
801 //  362         for (i = 0 ; i < RID_TABLE_SIZE; i++) {\r
802         LDI     R30, LOW(RID)\r
803         LDI     R31, (RID) >> 8\r
804         LDI     R18, 4\r
805         LDI     R16, LOW(BattData)\r
806         LDI     R17, (BattData) >> 8\r
807 //  363                 if (ADCS.rawRID >= RID[i].Low) {\r
808 ??RIDLookUp_0:\r
809         LDI     R26, LOW((ADCS + 2))\r
810         LDI     R27, HIGH((ADCS + 2))\r
811         LD      R22, X+\r
812         LD      R23, X\r
813         LD      R0, Z\r
814         LDD     R1, Z+1\r
815         CP      R22, R0\r
816         CPC     R23, R1\r
817         BRCS    ??RIDLookUp_1\r
818 //  364                         if (ADCS.rawRID <= RID[i].High) {\r
819         LDD     R0, Z+2\r
820         LDD     R1, Z+3\r
821         CP      R0, R22\r
822         CPC     R1, R23\r
823         BRCS    ??RIDLookUp_1\r
824 //  365                                 BattData.Capacity = RID[i].Capacity;\r
825         LDD     R20, Z+6\r
826         LDD     R21, Z+7\r
827         MOVW    R27:R26, R17:R16\r
828         ADIW    R27:R26, 4\r
829         ST      X+, R20\r
830         ST      X, R21\r
831 //  366                                 BattData.MaxCurrent = RID[i].Icharge;\r
832         LDD     R20, Z+8\r
833         LDD     R21, Z+9\r
834         MOVW    R27:R26, R17:R16\r
835         ADIW    R27:R26, 6\r
836         ST      X+, R20\r
837         ST      X, R21\r
838 //  367                                 BattData.MaxTime = RID[i].tCutOff;\r
839         LDD     R20, Z+10\r
840         LDD     R21, Z+11\r
841         MOVW    R27:R26, R17:R16\r
842         ADIW    R27:R26, 8\r
843         ST      X+, R20\r
844         ST      X, R21\r
845 //  368                                 BattData.MinCurrent = RID[i].ICutOff;\r
846         LDD     R20, Z+12\r
847         LDD     R21, Z+13\r
848         MOVW    R27:R26, R17:R16\r
849         ADIW    R27:R26, 10\r
850         ST      X+, R20\r
851         ST      X, R21\r
852 //  369                                 \r
853 //  370                                 found = TRUE;\r
854         LDI     R20, 1\r
855 //  371                         }\r
856 //  372                 }\r
857 //  373         }\r
858 ??RIDLookUp_1:\r
859         ADIW    R31:R30, 14\r
860         DEC     R18\r
861         BRNE    ??RIDLookUp_0\r
862 //  374         \r
863 //  375         // If no valid entry is found, use defaults and return FALSE.\r
864 //  376         if (!found) {\r
865         TST     R20\r
866         BRNE    ??RIDLookUp_2\r
867 //  377                 BattData.Capacity = DEF_BAT_CAPACITY;\r
868         LDI     R18, 0\r
869         MOVW    R31:R30, R17:R16\r
870         STD     Z+4, R18\r
871         STD     Z+5, R18\r
872 //  378                 BattData.MaxCurrent = DEF_BAT_CURRENT_MAX;\r
873         STD     Z+6, R18\r
874         STD     Z+7, R18\r
875 //  379                 BattData.MaxTime = DEF_BAT_TIME_MAX;\r
876         STD     Z+8, R18\r
877         STD     Z+9, R18\r
878 //  380                 BattData.MinCurrent = DEF_BAT_CURRENT_MIN;\r
879         STD     Z+10, R18\r
880         STD     Z+11, R18\r
881 //  381         }\r
882 //  382         \r
883 //  383         return(found);\r
884 ??RIDLookUp_2:\r
885         MOV     R16, R20\r
886         MOV     R26, R2\r
887         MOV     R27, R19\r
888         RET\r
889 //  384 }\r
890 //  385 \r
891 //  386 \r
892 //  387 /*! \brief Calculates temperature from a lookup table\r
893 //  388  *\r
894 //  389  * Looks up the highest NTC value below or equal to the measured one.\n\r
895 //  390  * With the current lookup table, temperature is calculated with the formula:\n\r
896 //  391  * 4*(index of entry) - 2*(measured NTC - NTC from entry) / (ADCsteps of entry)\r
897 //  392  *\r
898 //  393  * \note If the NTC-measurement is saturated, with the current lookup table,\r
899 //  394  * the temperature will be reported as -1 C.\r
900 //  395  *\r
901 //  396  * \note If no valid entry is found, battery temperature is set to 80.\r
902 //  397  */\r
903 \r
904         RSEG CODE:CODE:NOROOT(1)\r
905 //  398 void NTCLookUp (void)\r
906 NTCLookUp:\r
907 //  399 {\r
908         ST      -Y, R27\r
909         MOV     R3, R26\r
910         MOV     R2, R24\r
911 //  400         unsigned char i;\r
912 //  401         unsigned char found = FALSE;\r
913         LDI     R16, 0\r
914 //  402         \r
915 //  403         // Lookup in the NTC-table. Use the first entry which is equal or below\r
916 //  404         // sampled NTC. Calculate temperature by using the index number, and the\r
917 //  405         // difference between the measured NTC value and the one in the entry.\r
918 //  406         for (i=0 ; (i < NTC_TABLE_SIZE) && (!found); i++)       {\r
919         LDI     R24, 0\r
920         LDI     R26, LOW(BattData)\r
921         LDI     R27, (BattData) >> 8\r
922 //  407                 if (ADCS.rawNTC >= NTC[i].ADC) {\r
923 ??NTCLookUp_0:\r
924         MOV     R20, R24\r
925         LDI     R21, 0\r
926         MOVW    R19:R18, R21:R20\r
927         LSL     R20\r
928         ROL     R21\r
929         ADD     R20, R18\r
930         ADC     R21, R19\r
931         LDI     R18, LOW(NTC)\r
932         LDI     R19, (NTC) >> 8\r
933         ADD     R18, R20\r
934         ADC     R19, R21\r
935         LDI     R30, LOW(ADCS)\r
936         LDI     R31, (ADCS) >> 8\r
937         LDD     R20, Z+4\r
938         LDD     R21, Z+5\r
939         MOVW    R31:R30, R19:R18\r
940         LD      R22, Z\r
941         LDD     R23, Z+1\r
942         CP      R20, R22\r
943         CPC     R21, R23\r
944         BRCS    ??NTCLookUp_1\r
945 //  408                         BattData.Temperature = (i<<2) ;\r
946         MOV     R16, R24\r
947         LSL     R16\r
948         LSL     R16\r
949         MOVW    R31:R30, R27:R26\r
950         STD     Z+2, R16\r
951 //  409                         BattData.ADCSteps = NTC[i].ADCsteps;  \r
952         MOVW    R31:R30, R19:R18\r
953         LDD     R20, Z+2\r
954         MOVW    R31:R30, R27:R26\r
955         STD     Z+3, R20\r
956 //  410                         BattData.Temperature -= ((ADCS.rawNTC - NTC[i].ADC)<<1) / BattData.ADCSteps;\r
957         LDS     R16, (ADCS + 4)\r
958         MOV     R17, R21\r
959         MOVW    R31:R30, R19:R18\r
960         LD      R18, Z\r
961         LDD     R19, Z+1\r
962         SUB     R16, R18\r
963         SBC     R17, R19\r
964         LSL     R16\r
965         ROL     R17\r
966         LDI     R21, 0\r
967         RCALL   ?US_DIVMOD_L02\r
968         MOVW    R31:R30, R27:R26\r
969         LDD     R17, Z+2\r
970         SUB     R17, R16\r
971         STD     Z+2, R17\r
972 //  411                         \r
973 //  412                         found = TRUE;  // Could be done with a break, but that violates MISRA.\r
974         LDI     R16, 1\r
975 //  413                 }\r
976 //  414         }\r
977 ??NTCLookUp_1:\r
978         INC     R24\r
979         CPI     R24, 20\r
980         BRCC    ??NTCLookUp_2\r
981         TST     R16\r
982         BREQ    ??NTCLookUp_0\r
983 //  415         \r
984 //  416         // For safety, is temperature is greater than the NTC \r
985 //  417         if (!found) {\r
986 ??NTCLookUp_2:\r
987         TST     R16\r
988         BRNE    ??NTCLookUp_3\r
989 //  418                 BattData.Temperature = 80;\r
990         LDI     R16, 80\r
991         STS     (BattData + 2), R16\r
992 //  419         }\r
993 //  420 }\r
994 ??NTCLookUp_3:\r
995         MOV     R24, R2\r
996         MOV     R26, R3\r
997         LD      R27, Y+\r
998         RET\r
999 \r
1000         ASEGN ABSOLUTE:DATA:NOROOT,01cH\r
1001 __?EECR:\r
1002 \r
1003         ASEGN ABSOLUTE:DATA:NOROOT,01dH\r
1004 __?EEDR:\r
1005 \r
1006         ASEGN ABSOLUTE:DATA:NOROOT,01eH\r
1007 __?EEARL:\r
1008 \r
1009         ASEGN ABSOLUTE:DATA:NOROOT,01fH\r
1010 __?EEARH:\r
1011 \r
1012         RSEG INITTAB:CODE:NOROOT(0)\r
1013 `?<Segment init: NEAR_Z>`:\r
1014         DW      SFE(NEAR_Z) - SFB(NEAR_Z)\r
1015         DW      SFB(NEAR_Z)\r
1016         DW      0\r
1017         REQUIRE ?need_segment_init\r
1018 \r
1019         RSEG NEAR_ID:CODE:NOROOT(0)\r
1020 `?<Initializer for RID>`:\r
1021         DW 558, 659, 3900, 550, 260, 300, 10, 744, 843, 6800, 750, 360, 300, 14\r
1022         DW 869, 958, 10000, 1000, 475, 300, 19, 1097, 1153, 24000, 2000, 475\r
1023         DW 420, 38\r
1024 \r
1025         RSEG INITTAB:CODE:NOROOT(0)\r
1026 `?<Segment init: NEAR_I>`:\r
1027         DW      SFE(NEAR_I) - SFB(NEAR_I)\r
1028         DW      SFB(NEAR_I)\r
1029         DW      SFB(NEAR_ID)\r
1030         REQUIRE ?need_segment_init\r
1031 \r
1032         RSEG NEAR_ID:CODE:NOROOT(0)\r
1033 `?<Initializer for NTC>`:\r
1034         DW 1002\r
1035         DB 23\r
1036         DW 953\r
1037         DB 25\r
1038         DW 902\r
1039         DB 26\r
1040         DW 849\r
1041         DB 27\r
1042         DW 796\r
1043         DB 27\r
1044         DW 742\r
1045         DB 27\r
1046         DW 689\r
1047         DB 26\r
1048         DW 637\r
1049         DB 26\r
1050         DW 587\r
1051         DB 25\r
1052         DW 539\r
1053         DB 24\r
1054         DW 494\r
1055         DB 22\r
1056         DW 451\r
1057         DB 21\r
1058         DW 412\r
1059         DB 19\r
1060         DW 375\r
1061         DB 18\r
1062         DW 341\r
1063         DB 17\r
1064         DW 310\r
1065         DB 15\r
1066         DW 282\r
1067         DB 14\r
1068         DW 256\r
1069         DB 13\r
1070         DW 233\r
1071         DB 11\r
1072         DW 212\r
1073         DB 10\r
1074 \r
1075         END\r
1076 // \r
1077 //   2 bytes in segment ABSOLUTE\r
1078 // 804 bytes in segment CODE\r
1079 // 130 bytes in segment EEPROM_I\r
1080 //  12 bytes in segment INITTAB\r
1081 // 116 bytes in segment NEAR_I\r
1082 // 116 bytes in segment NEAR_ID\r
1083 //  13 bytes in segment NEAR_Z\r
1084 // \r
1085 // 920 bytes of CODE  memory (+ 12 bytes shared)\r
1086 // 129 bytes of DATA  memory (+  2 bytes shared)\r
1087 // 130 bytes of XDATA memory\r
1088 //\r
1089 //Errors: none\r
1090 //Warnings: none\r