1 ///////////////////////////////////////////////////////////////////////////////
\r
3 // IAR Atmel AVR C/C++ Compiler V4.30F/W32 13/Mar/2008 04:52:01 /
\r
4 // Copyright 1996-2007 IAR Systems. All rights reserved. /
\r
6 // Source file = C:\home\kevin\pub\src\bc100\IAR\chargefunc.c /
\r
7 // Command line = C:\home\kevin\pub\src\bc100\IAR\chargefunc.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
31 // List file = C:\home\kevin\pub\src\bc100\IAR\Release\List\c /
\r
35 ///////////////////////////////////////////////////////////////////////////////
\r
39 RSEG CSTACK:DATA:NOROOT(0)
\r
40 RSEG RSTACK:DATA:NOROOT(0)
\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 ?Register_R9_is_cg_reg
\r
49 EXTERN ?need_segment_init
\r
53 PUBWEAK `?<Segment init: NEAR_Z>`
\r
54 PUBLIC ChargeParameters
\r
55 PUBLIC ConstantCurrent
\r
56 PUBLIC ConstantVoltage
\r
58 PUBLIC HaltParameters
\r
68 EXTERN PWM_IncrementDutyCycle
\r
70 EXTERN PWM_DecrementDutyCycle
\r
80 // C:\home\kevin\pub\src\bc100\IAR\chargefunc.c
\r
81 // 1 /* This file has been prepared for Doxygen automatic documentation generation.*/
\r
82 // 2 /*! \file *********************************************************************
\r
85 // 5 * Charge functions
\r
87 // 7 * Contains the functions for charging with constant current and voltage,
\r
88 // 8 * and for deciding when to halt.
\r
90 // 10 * \par Application note:
\r
91 // 11 * AVR458: Charging Li-Ion Batteries with BC100 \n
\r
92 // 12 * AVR463: Charging NiMH Batteries with BC100
\r
94 // 14 * \par Documentation
\r
95 // 15 * For comprehensive code documentation, supported compilers, compiler
\r
96 // 16 * settings and supported devices see readme.html
\r
99 // 19 * Atmel Corporation: http://www.atmel.com \n
\r
100 // 20 * Support email: avr@atmel.com
\r
104 // 24 * $Revision: 2299 $
\r
106 // 26 * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/chargefunc.c $
\r
107 // 27 * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n
\r
108 // 28 ******************************************************************************/
\r
110 // 30 #include <ioavr.h>
\r
112 ASEGN ABSOLUTE:DATA:NOROOT,04cH
\r
113 // <unnamed> volatile __io _A_OCR1B
\r
117 // 32 #include "enums.h"
\r
118 // 33 #include "structs.h"
\r
120 // 35 #include "ADC.h"
\r
121 // 36 #include "battery.h"
\r
122 // 37 #include "chargefunc.h"
\r
123 // 38 #include "main.h"
\r
124 // 39 #include "menu.h"
\r
125 // 40 #include "PWM.h"
\r
126 // 41 #include "statefunc.h"
\r
127 // 42 #include "time.h"
\r
130 // 45 #include "NIMHspecs.h"
\r
131 // 46 #endif // NIMH
\r
134 // 49 #include "LIIONspecs.h"
\r
135 // 50 #endif // LIION
\r
138 // 53 //******************************************************************************
\r
140 // 55 //******************************************************************************
\r
141 // 56 //! Struct that holds parameters for ConstantCurrent() and ConstantVoltage().
\r
143 RSEG NEAR_Z:DATA:NOROOT(0)
\r
144 REQUIRE `?<Segment init: NEAR_Z>`
\r
145 // 57 ChargeParameters_t ChargeParameters;
\r
147 // 59 //! Struct that holds parameters for HaltNow().
\r
148 // 60 HaltParameters_t HaltParameters;
\r
155 // 63 //******************************************************************************
\r
157 // 65 //******************************************************************************
\r
158 // 66 /*! \brief Charges battery with a constant current.
\r
160 // 68 * This function applies a constant current (set in ChargeParameters.Current)
\r
161 // 69 * to the battery until HaltNow() returns TRUE, or a PWM error occurs and
\r
162 // 70 * \ref ABORT_IF_PWM_MIN or \ref ABORT_IF_PWM_MAX is defined.\n
\r
163 // 71 * The charge current can vary with +/- \ref BAT_CURRENT_HYST.\n
\r
164 // 72 * If the Master inhibits charging, timers are stopped and PWM output dropped.
\r
165 // 73 * Once the battery is no longer flagged for charge inhibit, timers are
\r
166 // 74 * started again and charging resumed.
\r
168 // 76 * \retval ChargeParameters.NextState Next state once this stage is done.
\r
169 // 77 * If no errors occured, this will be whatever was set in Charge(). Otherwise,
\r
170 // 78 * HaltNow() will have set a new next state.
\r
173 RSEG CODE:CODE:NOROOT(1)
\r
174 // 80 unsigned char ConstantCurrent(void)
\r
183 REQUIRE ?Register_R4_is_cg_reg
\r
184 REQUIRE ?Register_R5_is_cg_reg
\r
185 // 82 unsigned char error = FALSE,
\r
187 // 83 wasStopped = FALSE;
\r
191 // 86 // Wait for ADC conversions to complete.
\r
193 ??ConstantCurrent_0:
\r
196 // 89 // If Master has flagged for a charge inhibit, pause charging.
\r
197 // 90 // (This is to prevent damage during prolonged serial communication.)
\r
198 // 91 if (BattControl[BattActive].ChargeInhibit) {
\r
199 LDS R16, BattActive
\r
201 LDI R20, LOW(BattControl)
\r
202 LDI R21, (BattControl) >> 8
\r
207 BREQ ??ConstantCurrent_1
\r
208 // 92 wasStopped = TRUE;
\r
216 RJMP ??ConstantCurrent_2
\r
218 // 96 // Continue charging!
\r
219 // 97 if (wasStopped) {
\r
220 ??ConstantCurrent_1:
\r
222 BREQ ??ConstantCurrent_3
\r
223 // 98 wasStopped = FALSE;
\r
226 // 100 // Timer variables are not reset by this.
\r
227 // 101 Time_Start();
\r
231 // 104 // Adjust the charge current to within ChargeParameters.Current
\r
232 // 105 // +/- BAT_CURRENT_HYST.
\r
233 // 106 if ((ADCS.avgIBAT < 0) ||
\r
234 // 107 (ADCS.avgIBAT < (ChargeParameters.Current - BAT_CURRENT_HYST))) {
\r
235 ??ConstantCurrent_3:
\r
237 LDI R31, (ADCS) >> 8
\r
241 BRMI ??ConstantCurrent_4
\r
242 LDI R26, LOW((HaltParameters + 19))
\r
243 LDI R27, HIGH((HaltParameters + 19))
\r
246 MOVW R25:R24, R31:R30
\r
250 BRCC ??ConstantCurrent_5
\r
252 // 109 if(!PWM_IncrementDutyCycle()) {
\r
253 ??ConstantCurrent_4:
\r
254 RCALL PWM_IncrementDutyCycle
\r
256 BRNE ??ConstantCurrent_2
\r
257 // 110 #ifdef ABORT_IF_PWM_MAX
\r
258 // 111 // If the duty cycle cannot be incremented, flag error and
\r
259 // 112 // go to error state.
\r
260 // 113 SetErrorFlag(ERR_PWM_CONTROL);
\r
261 ??ConstantCurrent_6:
\r
264 // 114 ChargeParameters.NextState = ST_ERROR;
\r
266 STS (HaltParameters + 21), R16
\r
267 // 115 error = TRUE;
\r
270 RJMP ??ConstantCurrent_2
\r
273 // 118 } else if ((ADCS.avgIBAT >= 0) &&
\r
274 ??ConstantCurrent_5:
\r
278 BRCC ??ConstantCurrent_2
\r
279 // 119 (ADCS.avgIBAT > (ChargeParameters.Current + BAT_CURRENT_HYST))) {
\r
281 // 121 if(!PWM_DecrementDutyCycle()) {
\r
282 RCALL PWM_DecrementDutyCycle
\r
284 BREQ ??ConstantCurrent_6
\r
285 // 122 #ifdef ABORT_IF_PWM_MIN
\r
286 // 123 // If the duty cycle cannot be decremented, flag error and
\r
287 // 124 // go to error state.
\r
288 // 125 SetErrorFlag(ERR_PWM_CONTROL);
\r
289 // 126 ChargeParameters.NextState = ST_ERROR;
\r
290 // 127 error = TRUE;
\r
295 // 132 } while ((!HaltNow()) && (!error));
\r
296 ??ConstantCurrent_2:
\r
299 BRNE ??ConstantCurrent_7
\r
301 BREQ ??ConstantCurrent_0
\r
303 // 134 // Return the next state to Charge(). If an error has occured, this will
\r
304 // 135 // point to some other state than the next state of charging.
\r
305 // 136 return(ChargeParameters.NextState);
\r
306 ??ConstantCurrent_7:
\r
307 LDS R16, (HaltParameters + 21)
\r
319 // 140 /*! \brief Charges battery with a constant voltage
\r
321 // 142 * This function applies a constant voltage (set in ChargeParameters.Voltage)
\r
322 // 143 * to the battery until HaltNow() returns TRUE, or a PWM error occurs and
\r
323 // 144 * \ref ABORT_IF_PWM_MIN or \ref ABORT_IF_PWM_MAX is defined.\n
\r
324 // 145 * The charge voltage can vary with +/- \ref BAT_VOLTAGE_HYST.\n
\r
325 // 146 * If the Master inhibits charging, timers are stopped and PWM output dropped.
\r
326 // 147 * Once the battery is no longer flagged for charge inhibit, timers are
\r
327 // 148 * started again and charging resumed.
\r
329 // 150 * \retval ChargeParameters.NextState Next state once this stage is done.
\r
330 // 151 * If no errors occured, this will be whatever was set in Charge(). Otherwise,
\r
331 // 152 * HaltNow() will have set a new next state.
\r
334 RSEG CODE:CODE:NOROOT(1)
\r
335 // 154 unsigned char ConstantVoltage(void)
\r
342 // 156 unsigned char error = FALSE,
\r
344 // 157 wasStopped = FALSE;
\r
349 // 161 // Wait for ADC conversions to complete.
\r
351 ??ConstantVoltage_0:
\r
354 // 164 // If Master has flagged for a charge inhibit, pause charging.
\r
355 // 165 // (This is to prevent damage during prolonged serial communication.)
\r
356 // 166 if (BattControl[BattActive].ChargeInhibit) {
\r
357 LDS R16, BattActive
\r
359 LDI R20, LOW(BattControl)
\r
360 LDI R21, (BattControl) >> 8
\r
365 BREQ ??ConstantVoltage_1
\r
366 // 167 wasStopped = TRUE;
\r
368 // 168 Time_Stop();
\r
373 RJMP ??ConstantVoltage_2
\r
377 // 173 // Continue charging!
\r
378 // 174 if (wasStopped) {
\r
379 ??ConstantVoltage_1:
\r
381 BREQ ??ConstantVoltage_3
\r
382 // 175 wasStopped = FALSE;
\r
385 // 177 // Timer variables aren't reset by this.
\r
386 // 178 Time_Start();
\r
390 // 181 // Adjust the charge voltage to within ChargeParameters.Voltage
\r
391 // 182 // +/- BAT_VOLTAGE_HYST.
\r
392 // 183 if (ADCS.VBAT < (ChargeParameters.Voltage - BAT_VOLTAGE_HYST)) {
\r
393 ??ConstantVoltage_3:
\r
394 LDI R26, LOW(HaltParameters)
\r
395 LDI R27, (HaltParameters) >> 8
\r
396 MOVW R31:R30, R27:R26
\r
400 LDI R31, (ADCS) >> 8
\r
403 MOVW R31:R30, R17:R16
\r
407 BRCC ??ConstantVoltage_4
\r
409 // 185 if(!PWM_IncrementDutyCycle()) {
\r
410 RCALL PWM_IncrementDutyCycle
\r
412 BRNE ??ConstantVoltage_2
\r
413 // 186 #ifdef ABORT_IF_PWM_MAX
\r
414 // 187 // Flag PWM control error and go to error-state if the duty
\r
415 // 188 // cycle cannot be incremented.
\r
416 // 189 SetErrorFlag(ERR_PWM_CONTROL);
\r
417 ??ConstantVoltage_5:
\r
420 // 190 ChargeParameters.NextState = ST_ERROR;
\r
422 MOVW R31:R30, R27:R26
\r
424 // 191 error = TRUE;
\r
426 RJMP ??ConstantVoltage_2
\r
429 // 194 } else if (ADCS.VBAT > (ChargeParameters.Voltage + BAT_VOLTAGE_HYST)) {
\r
430 ??ConstantVoltage_4:
\r
435 BRCC ??ConstantVoltage_2
\r
437 // 196 if(!PWM_DecrementDutyCycle()) {
\r
438 RCALL PWM_DecrementDutyCycle
\r
440 BREQ ??ConstantVoltage_5
\r
441 // 197 #ifdef ABORT_IF_PWM_MIN
\r
442 // 198 // Flag PWM control error and go to error-state if duty
\r
443 // 199 // cycle cannot be decremented.
\r
444 // 200 SetErrorFlag(ERR_PWM_CONTROL);
\r
445 // 201 ChargeParameters.NextState = ST_ERROR;
\r
446 // 202 error = TRUE;
\r
452 // 208 } while ((!HaltNow()) && (!error));
\r
453 ??ConstantVoltage_2:
\r
456 BRNE ??ConstantVoltage_6
\r
458 BREQ ??ConstantVoltage_0
\r
460 // 210 // Return the next state to Charge(). If an error has occured, this will
\r
461 // 211 // point to some other state than the next state of charging.
\r
462 // 212 return(ChargeParameters.NextState);
\r
463 ??ConstantVoltage_6:
\r
464 LDS R16, (HaltParameters + 21)
\r
474 // 216 /*! \brief Determines when to halt charging.
\r
476 // 218 * This function evaluates parameters depending on what has been flagged in
\r
477 // 219 * HaltParameters.HaltFlags, and returns TRUE or FALSE if the charging should
\r
478 // 220 * halt or not.\n
\r
479 // 221 * In addition, error flagging on timeout (battery exhaustion) can be set.\n
\r
481 // 223 * The function also checks if the battery temperature is within limits,
\r
482 // 224 * if mains is OK, and if BatteryCheck() returns TRUE.
\r
483 // 225 * If an error is detected, the associated errorflag is set and
\r
484 // 226 * ChargeParameters.NextState is changed to an appropriate state.
\r
486 // 228 * \retval TRUE Halt now.
\r
487 // 229 * \retval FALSE Don't halt now.
\r
489 // 231 * \note See chargefunc.h for definitions of halt flags.
\r
490 // 232 * \note It is generally a bad idea not to halt on a timeout.
\r
491 // 233 * \note If HALT_ON_VOLTAGE_DROP is set, HaltParameters.VBATMax should be
\r
492 // 234 * reset in Charge() before calling a charging-function.
\r
494 // 236 * \todo "Priorities" of standard error checks OK?
\r
497 RSEG CODE:CODE:NOROOT(1)
\r
498 // 238 unsigned char HaltNow(void)
\r
511 REQUIRE ?Register_R4_is_cg_reg
\r
512 REQUIRE ?Register_R5_is_cg_reg
\r
513 REQUIRE ?Register_R6_is_cg_reg
\r
514 REQUIRE ?Register_R7_is_cg_reg
\r
515 REQUIRE ?Register_R8_is_cg_reg
\r
516 REQUIRE ?Register_R9_is_cg_reg
\r
517 // 240 unsigned char i, halt = FALSE;
\r
520 // 242 // Wait for a full ADC-cycle to finish.
\r
524 // 245 // Evaluate ADC readings according to HaltFlags. Flag errors if selected.
\r
525 // 246 // If an error is flagged, ChargeParameters.NextState is set to ST_ERROR.
\r
526 // 247 // (Gets overridden if either mains is failing, or the battery changes.)
\r
527 // 248 for (i = 0x01; i != 0; i <<= 1) {
\r
531 LDI R25, (ADCS) >> 8
\r
532 LDI R16, LOW(BattData)
\r
534 LDI R16, (BattData) >> 8
\r
536 LDI R26, LOW(HaltParameters)
\r
537 LDI R27, (HaltParameters) >> 8
\r
538 // 249 if (HaltParameters.HaltFlags & i) {
\r
544 // 250 switch (i) {
\r
558 // 251 // Is VBAT less than the recorded maximum?
\r
559 // 252 case HALT_VOLTAGE_DROP:
\r
561 // 254 // Update VBATMax if VBAT is higher. Evaluate for halt otherwise.
\r
562 // 255 if (ADCS.VBAT > HaltParameters.VBATMax) {
\r
564 MOVW R31:R30, R27:R26
\r
567 MOVW R31:R30, R25:R24
\r
573 // 256 HaltParameters.VBATMax = ADCS.VBAT;
\r
574 MOVW R31:R30, R27:R26
\r
578 // 257 } else if((HaltParameters.VBATMax - ADCS.VBAT) >=
\r
579 // 258 HaltParameters.VoltageDrop) {
\r
583 MOVW R31:R30, R27:R26
\r
590 // 259 halt = TRUE;
\r
599 // 264 // Has VBAT reached the maximum limit?
\r
600 // 265 case HALT_VOLTAGE_MAX:
\r
602 // 267 if (ADCS.VBAT >= HaltParameters.VoltageMax) {
\r
604 MOVW R31:R30, R25:R24
\r
607 MOVW R31:R30, R27:R26
\r
616 // 268 halt = TRUE;
\r
621 // 273 // Has IBAT reached the minimum limit?
\r
622 // 274 case HALT_CURRENT_MIN:
\r
624 // 276 if (ADCS.avgIBAT <= HaltParameters.CurrentMin) {
\r
626 MOVW R31:R30, R27:R26
\r
629 MOVW R31:R30, R25:R24
\r
633 // 277 halt = TRUE;
\r
638 // 282 // Is the temperature rising too fast?
\r
639 // 283 case HALT_TEMPERATURE_RISE:
\r
641 // 285 // If rawNTC has increased, the temperature has dropped.
\r
642 // 286 // We can store this value for now, and start the timer.
\r
643 // 287 // Otherwise, check if NTC has changed too fast.
\r
644 // 288 if (ADCS.rawNTC > HaltParameters.LastNTC) {
\r
646 MOVW R31:R30, R25:R24
\r
649 MOVW R31:R30, R27:R26
\r
655 // 289 HaltParameters.LastNTC = ADCS.rawNTC;
\r
657 MOVW R31:R30, R25:R24
\r
660 MOVW R31:R30, R27:R26
\r
663 // 290 Time_Set(TIMER_TEMP,0,30,0);
\r
672 // 292 // Is the increase in temperature greater than the set threshold?
\r
673 // 293 } else if ((HaltParameters.LastNTC - ADCS.rawNTC) >=
\r
674 // 294 (BattData.ADCSteps * HaltParameters.TemperatureRise)) {
\r
678 MOVW R31:R30, R5:R4
\r
681 MOVW R31:R30, R27:R26
\r
689 // 296 // If this happened within a timeframe of 30 seconds, the
\r
690 // 297 // temperature is rising faster than we want.
\r
691 // 298 // If not, update LastNTC and reset timer.
\r
692 // 299 if (Time_Left(TIMER_TEMP)) {
\r
698 // 300 halt = TRUE;
\r
700 // 302 HaltParameters.LastNTC = ADCS.rawNTC;
\r
701 // 303 Time_Set(TIMER_TEMP,0,30,0);
\r
707 // 309 // Is there any time left?
\r
708 // 310 case HALT_TIME:
\r
710 // 312 if (!Time_Left(TIMER_CHG)) {
\r
716 // 313 halt = TRUE;
\r
720 // 315 // If exhaustion flagging is selected, stop the PWM, disable the
\r
721 // 316 // battery and flag it as exhausted. Make ST_ERROR next state.
\r
722 // 317 if (HaltParameters.HaltFlags & HALT_FLAG_EXHAUSTION) {
\r
728 // 319 BattControl[BattActive].Enabled = FALSE;
\r
729 LDS R16, BattActive
\r
731 LDI R20, LOW(BattControl)
\r
732 LDI R21, (BattControl) >> 8
\r
738 // 320 BattData.Exhausted = TRUE;
\r
739 MOVW R31:R30, R5:R4
\r
743 // 321 SetErrorFlag(ERR_BATTERY_EXHAUSTED);
\r
746 // 322 ChargeParameters.NextState = ST_ERROR;
\r
748 MOVW R31:R30, R27:R26
\r
755 // 328 default: // Shouldn't end up here, but is needed for MISRA compliance.
\r
765 // 334 // Standard checks:
\r
767 // 336 // Battery too cold or hot?
\r
768 // 337 if ((BattData.Temperature <= HaltParameters.TemperatureMin) ||
\r
769 // 338 (BattData.Temperature >= HaltParameters.TemperatureMax)) {
\r
770 LDI R30, LOW(BattData)
\r
771 LDI R31, (BattData) >> 8
\r
773 MOVW R31:R30, R27:R26
\r
794 // 341 SetErrorFlag(ERR_BATTERY_TEMPERATURE);
\r
797 // 342 ChargeParameters.NextState = ST_ERROR;
\r
799 MOVW R31:R30, R27:R26
\r
801 // 343 halt = TRUE;
\r
806 // 346 // Battery not OK?
\r
807 // 347 if (!BatteryCheck()) {
\r
814 // 349 ChargeParameters.NextState = ST_INIT;
\r
816 MOVW R31:R30, R27:R26
\r
818 // 350 halt = TRUE;
\r
823 // 353 // Is mains voltage OK?
\r
824 // 354 if (!ADCS.Mains) {
\r
831 // 356 ChargeParameters.NextState = ST_SLEEP;
\r
833 MOVW R31:R30, R27:R26
\r
835 // 357 halt = TRUE;
\r
840 // 360 return(halt);
\r
856 ASEGN ABSOLUTE:DATA:NOROOT,01cH
\r
859 ASEGN ABSOLUTE:DATA:NOROOT,01dH
\r
862 ASEGN ABSOLUTE:DATA:NOROOT,01eH
\r
865 ASEGN ABSOLUTE:DATA:NOROOT,01fH
\r
868 RSEG INITTAB:CODE:NOROOT(0)
\r
869 `?<Segment init: NEAR_Z>`:
\r
870 DW SFE(NEAR_Z) - SFB(NEAR_Z)
\r
873 REQUIRE ?need_segment_init
\r
877 // 1 byte in segment ABSOLUTE
\r
878 // 716 bytes in segment CODE
\r
879 // 6 bytes in segment INITTAB
\r
880 // 22 bytes in segment NEAR_Z
\r
882 // 716 bytes of CODE memory (+ 6 bytes shared)
\r
883 // 22 bytes of DATA memory (+ 1 byte shared)
\r