およそ20年前に、68HC05 の開発の練習に書いた車のブレイクライト・方向指示器コントローラです。
Revision | abab0080b8a4f62e9d4ddb41422fc80ab39aa024 (tree) |
---|---|
Time | 2013-07-08 21:39:02 |
Author | Joel Matthew Rees <reiisi@user...> |
Commiter | Joel Matthew Rees |
I think this was working on the engine off state.
@@ -11,7 +11,7 @@ | ||
11 | 11 | * Permission granted in advance for strictly non-profit |
12 | 12 | * educational use. All other rights retained by the author. |
13 | 13 | |
14 | -* Authored by Joel Matthew Rees, June to August 1993 | |
14 | +* Authored by Joel Matthew Rees, June to October 1993 | |
15 | 15 | * of |
16 | 16 | * South Salt Lake City |
17 | 17 | * Utah |
@@ -27,14 +27,15 @@ | ||
27 | 27 | * parents' 1971 Colt fell apart some years back, rather than go to the |
28 | 28 | * nearest Dodge dealer in the next city to order the part, I designed a |
29 | 29 | * substitute switch using a pair of double-pole, double-throw relays in |
30 | -* set-reset latch configuration. Momentary-closed pushbuttons set the | |
31 | -* turn signals, and a momentary open pushbutton or reed switch shut them | |
32 | -* off. (The reed switch and a magnet were glued inside the steering | |
33 | -* column to provide a directionless turn signal return.) I usurped the | |
34 | -* emergency flasher unit and took power from the battery lead on the | |
35 | -* ignition switch, so when I needed emergency flashers, I could just | |
36 | -* turn both turn signals on. Mom had trouble getting used to this | |
37 | -* arrangement, but it passed Texas inspection in the seventies. | |
30 | +* set-reset latch configuration. Momentary-closed pushbuttons (mounted | |
31 | +* to the steering column cover) set the turn signals, and a momentary | |
32 | +* open pushbutton (mounted between the set buttons) or reed switch | |
33 | +* (mounted inside the cover housing so a magnet mounted to the steering | |
34 | +* column would actuate it) shut them off. I usurped the emergency | |
35 | +* flasher unit and took power from the battery lead on the ignition | |
36 | +* switch, so when I needed emergency flashers, I could just turn both | |
37 | +* turn signals on. Mom had trouble getting used to this arrangement, but | |
38 | +* it passed Texas inspection in the seventies. | |
38 | 39 | |
39 | 40 | * Examining the 68HC05K series MCUs brought that turn signal |
40 | 41 | * switch back to mind. I thought ten bits of I/O, internal timers, |
@@ -57,14 +58,15 @@ | ||
57 | 58 | * parts (that tend to flow in hot climates and become brittle in cold) |
58 | 59 | * with logic. In order to eliminate the mechanical latching lever with |
59 | 60 | * spring loaded return, I have (perhaps arbitrarily) enforced a new "user |
60 | -* Interface" involving momentary contact switches for the turn signals. | |
61 | +* interface" involving momentary contact switches for the turn signals. | |
61 | 62 | * Two possible physical arrangements for the turn signal present |
62 | 63 | * themselves to my mind: In the one, a spring-loaded, non-latching |
63 | 64 | * signal rod (the latch/return mechanism was the weakest part) actuates |
64 | 65 | * momentary contact switches in two axes; the rod can be pushed up or |
65 | 66 | * down to activate the turn signals, or it can be pushed in to actuate |
66 | 67 | * the manual cancel. In the other arrangement, the signal rod is fixed, |
67 | -* and three pushbuttons are provided on a pad at its end. | |
68 | +* and three pushbuttons are provided on a pad at its end. (Cancel in | |
69 | +* the center would seem logical.) | |
68 | 70 | |
69 | 71 | * The emergency flasher switch is a momentary on pushbutton, and |
70 | 72 | * it cancels itself in software -- push on, push off. I think the audio |
@@ -72,15 +74,14 @@ | ||
72 | 74 | |
73 | 75 | * The turn signal return mechanism is a pair of reed relays |
74 | 76 | * mounted inside the bottom of the steering column housing about 11.25 |
75 | -* degrees apart, with three to eight magnetic actuators distributed | |
76 | -* around the steering shaft. The shape, size, and position of the | |
77 | -* magnets and reeds should be such that the reeds close only once as a | |
78 | -* magnet passes, and such that the reeds have about 22.5 degrees of | |
79 | -* overlapping actuation. The overlap in actuation is used to determine | |
80 | -* the direction the steering wheel is rotating. Minor changes to the | |
81 | -* design should allow the use of optical sensors, but I have the | |
82 | -* impression that magnetic devices are more immune to extremes of | |
83 | -* climate. | |
77 | +* degrees apart, with one to four magnetic actuators distributed around | |
78 | +* the steering shaft. The shape, size, and position of the magnets and | |
79 | +* reeds should be such that the reeds close only once as a magnet | |
80 | +* passes, and such that the reeds have about 22.5 degrees of total | |
81 | +* actuation. The overlap in actuation is used to determine the direction | |
82 | +* the steering wheel is rotating. Minor changes to the design should | |
83 | +* allow the use of optical sensors, but I have the impression that | |
84 | +* magnetic devices are more immune to extremes of climate. (Maybe?) | |
84 | 85 | |
85 | 86 | SUBHEADER 'Model Schematic' |
86 | 87 | PAGE |
@@ -146,17 +147,18 @@ | ||
146 | 147 | * active high. |
147 | 148 | |
148 | 149 | * I arbitrarily assume the signal lamp drivers will be active low. |
149 | -* Who could say why? However, I have hidden this assumption in a macro | |
150 | -* so I don't have to remember it. | |
150 | +* Who could say why? It should be easy to find all references to the | |
151 | +* driver lines with a text editor and reverse the active states of the | |
152 | +* outputs. | |
151 | 153 | |
152 | 154 | * Hanging the indicators and the audio feedback on the front lamp |
153 | 155 | * drivers separates them from brake activity. Two audio feedback |
154 | 156 | * devices are used here because there were not enough MCU outputs to |
155 | 157 | * drive a single cheap clicking device. Stereo audio feedback might be |
156 | -* a nice touch anyway, allowing a person with normal hearing to | |
157 | -* determine by sound which signal is on. (A single channel of audio | |
158 | -* feedback could be modulated as another way to distinguish the active | |
159 | -* signal.) | |
158 | +* a nice touch anyway, allowing a person with binaural hearing to | |
159 | +* determine by sound which signal is on. (If the ROM were a little | |
160 | +* larger, a separate audio feedback could be modulated with different | |
161 | +* sounds for left, right, and emergency flashers.) | |
160 | 162 | |
161 | 163 | * The center brake light is directly switched to eliminate one of |
162 | 164 | * the separate high-power outputs. Fortunately, its state is not |
@@ -167,8 +169,8 @@ | ||
167 | 169 | * input so that the MCU STOP mode can be used. Brake lights and |
168 | 170 | * emergency flashers must be accessible when the engine is off, so those |
169 | 171 | * inputs are also interrupting. The engine-on and brake inputs are |
170 | -* naturally positive-going signals, and the emergency flasher input is | |
171 | -* not naturally biased, so the the emergency flasher seemed a more | |
172 | +* naturally positive-going signals, but the emergency flasher input is | |
173 | +* not naturally biased. So the the emergency flasher seemed a more | |
172 | 174 | * natural match for IRQ. |
173 | 175 | |
174 | 176 | * The following crude diagram illustrates the actuation in a left |
@@ -210,9 +212,9 @@ | ||
210 | 212 | * its port is made an output and driven high. Now, in addition to |
211 | 213 | * manual cancel, the cancel port can sense steering wheel rotation. In |
212 | 214 | * same direction rotation, there is a lead period when the cancel input |
213 | -* does not remain high if the turn signal input port states are | |
214 | -* inverted. Debounce suppresses cancel under these conditions. | |
215 | - | |
215 | +* does not remain high if the turn signal input ports' output states are | |
216 | +* inverted. Debounce suppresses cancel under these conditions. | |
217 | + | |
216 | 218 | * Since the opposite direction turn signal switch port remains an |
217 | 219 | * input, it can still be sensed. The operator can change turn signals |
218 | 220 | * directly, without hitting the cancel button. |
@@ -223,20 +225,20 @@ | ||
223 | 225 | * to six mS required debounce period requires a minimum 10 milli-second |
224 | 226 | * separate actuation period. The actual result was 10.9 degrees |
225 | 227 | * separate actuation (21.8 total), which I arbitrarily rounded up to a |
226 | -* power of two fraction of the circle: 1/16 circle total actuation and | |
227 | -* 1/32 circle separate actuation. | |
228 | +* power of two fraction of the circle: 2*PI/16 total actuation and | |
229 | +* 2*PI/32 separate actuation. | |
228 | 230 | |
229 | 231 | * A peculiar characteristic of this design is the apparent lack of |
230 | 232 | * use for the RESET input. Since power-on reset is built in to the |
231 | 233 | * K-series MCUs, RESET should probably be tied high. However, I suppose |
232 | 234 | * it could make a good manual cancel-all input, if such is necessary. |
233 | 235 | |
234 | -* This assembler appears not to have a bit not function for | |
236 | +* This assembler appears not to have a bit-not function for | |
235 | 237 | * operand expressions. So, I have in several places resorted to the |
236 | 238 | * rather obtuse expedient of exclusive-orring bits to be reset with $FF, |
237 | 239 | * ergo, AND #{$FF ^ F_OPC ^ F_MNC} |
238 | 240 | * instead of AND #~(F_OPC | F_MNC) |
239 | -* which I think is clearer. | |
241 | +* which I think would have been clearer. | |
240 | 242 | |
241 | 243 | SUBHEADER 'Obligatory Mnemonics' |
242 | 244 | PAGE |
@@ -245,9 +247,9 @@ $include "68HC05K.EQU" | ||
245 | 247 | |
246 | 248 | SUBHEADER 'Program Mnemonics' |
247 | 249 | PAGE |
248 | -* physical input definitions | |
250 | +* physical I/O definitions | |
249 | 251 | * PORTA |
250 | -F_LDRV equ B7 | |
252 | +F_LDRV equ B7 ; four lamp drivers | |
251 | 253 | F_LDRV_ equ B7_ |
252 | 254 | F_RDRV equ B6 |
253 | 255 | F_RDRV_ equ B6_ |
@@ -255,6 +257,11 @@ R_LDRV equ B5 | ||
255 | 257 | R_LDRV_ equ B5_ |
256 | 258 | R_RDRV equ B4 |
257 | 259 | R_RDRV_ equ B4_ |
260 | +ALLAMPS equ {F_LDRV | F_RDRV | R_LDRV | R_RDRV} | |
261 | +LFTDRV equ {F_LDRV | R_LDRV} | |
262 | +RGTDRV equ {F_RDRV | R_RDRV} | |
263 | +FRNTDRV equ {F_LDRV | F_RDRV} | |
264 | +REARDRV eau {R_LDRV | R_RDRV} | |
258 | 265 | BRK_SW equ B3 |
259 | 266 | BRK_SW_ equ B3_ |
260 | 267 | NGN_SW equ B2 ; engine (ENG and EMG could be confusing) |
@@ -273,17 +280,19 @@ RGT_BT_ equ B0_ | ||
273 | 280 | |
274 | 281 | * logical input definitions for debounce and states |
275 | 282 | * bits are remapped for debounce and speed |
276 | -* six bits of physical input, high two bits used for cancel logic | |
283 | +* six bits of physical input, high two bits borrowed for cancel logic | |
277 | 284 | F_LFT equ LFT_BT |
278 | 285 | F_LFT_ equ LFT_BT_ |
279 | 286 | F_RGT equ RGT_BT |
280 | 287 | F_RGT_ equ RGT_BT_ |
288 | +TURNSIG equ {F_LFT | F_RGT} | |
281 | 289 | F_BRK equ {BRK_SW < 2} ; physical output bit |
282 | 290 | F_BRK_ equ {BRK_SW_ + 2} |
283 | 291 | F_NGN equ {NGN_SW < 2} ; physical output bit |
284 | 292 | F_NGN_ equ {NGN_SW_ + 2} |
285 | 293 | F_EMG equ {DRVDRV < 2} ; fold onto output bit |
286 | 294 | F_EMG_ equ {DRVDRV_ + 2} |
295 | +ANYLITE equ {TURNSIG | F_BRK | F_EMG} | |
287 | 296 | F_CAN equ {CAN_BT < 2} |
288 | 297 | F_CAN_ equ {CAN_BT_ + 2} |
289 | 298 | F_OPC equ $40 ; opposite direction cancel record |
@@ -292,27 +301,28 @@ F_MNC equ $80 ; manual cancel record | ||
292 | 301 | SUBHEADER 'Resource Definitions' |
293 | 302 | PAGE |
294 | 303 | |
295 | -* crystal frequency, in MHz: | |
296 | -XTAL equ 1 | |
297 | -RTIPOW equ 1 ; ls bits is right place for timer hardware | |
298 | -RTIRATE equ {2 < RTIPOW} ; 2 ^ RTIPOW stored is actual divide | |
304 | + | |
305 | +XTAL equ 1 ; crystal frequency, in MHz | |
306 | +RTIPOW equ 1 ; bits 1 & 0 for timer hardware | |
307 | +RTIRATE equ {2 < RTIPOW} ; 2 ^ RTIPOW | |
299 | 308 | TIMOUT equ {9155*XTAL/RTIRATE+1} ; 5 minutes (if XTAL equ is correct) |
300 | 309 | * only one flash rate, 2/3 duty cycle |
301 | -FLASH0 equ {32*XTAL/RTIRATE/4} ; about 1/4 second | |
302 | -FLASH1 equ {32*XTAL/RTIRATE/2} ; about 1/2 second | |
310 | +FLASH0 equ {32*XTAL/RTIRATE/4} ; about 1/4 second off time | |
311 | +FLASH1 equ {32*XTAL/RTIRATE/2} ; about 1/2 second on time | |
303 | 312 | |
304 | 313 | org MOR |
305 | 314 | fcb {PIN3 | RC | PIRQ | COPEN} |
306 | 315 | |
307 | 316 | org RAMBEG |
308 | 317 | DEBO rmb 3 ; the debounce record chain |
309 | -STABLE rmb 1 ; temporary record of stable bits | |
318 | +SSTBLE rmb 1 ; temporary record of stable bits | |
310 | 319 | TOGGLE rmb 1 ; record of toggles |
311 | 320 | ISTATE rmb 1 ; record of the current input state |
312 | 321 | STATES rmb 1 ; current controller states |
313 | 322 | NGN_TIM rmb 2 ; engine time out timer |
314 | 323 | FLASH rmb 1 ; flash timer |
315 | -FLTIME rmb 1 ; flash flash time to load | |
324 | +FLDARK rmb 1 ; flash light or dark state, 11111111 == dark | |
325 | +FLMASK rmb 1 ; flash mask to communicate between BRK, EMG, and TRN | |
316 | 326 | |
317 | 327 | |
318 | 328 | * ROM definitions follow: |
@@ -322,9 +332,9 @@ FLTIME rmb 1 ; flash flash time to load | ||
322 | 332 | PAGE |
323 | 333 | |
324 | 334 | * The timer service routine has these functions: debouncing the |
325 | -* inputs, directly setting the brake lights, flagging changes in TOGGLE, | |
326 | -* adjusting STATES to match the inputs, and maintaining two software | |
327 | -* clocks. Interrupts occur on timer overflow (1024 CPU cycles). | |
335 | +* inputs, flagging changes in TOGGLE, adjusting STATES to match the | |
336 | +* inputs, and maintaining two software clocks. Interrupts occur on timer | |
337 | +* overflow (1024 CPU cycles). | |
328 | 338 | |
329 | 339 | * The debounce routine translates the physical inputs to logical |
330 | 340 | * inputs, maintains a record of the last three logical states sensed in |
@@ -335,8 +345,9 @@ FLTIME rmb 1 ; flash flash time to load | ||
335 | 345 | * with a 1 MHz crystal, 2 to 3 mS with a 2 MHz crystal. |
336 | 346 | |
337 | 347 | * This debounce technique works because we don't care what is |
338 | -* happening to the inputs between timer overflows, and because there is | |
339 | -* no mechanism for noise coincident and rythmic with timer overflow. | |
348 | +* happening to the inputs between timer overflows, and because we assume | |
349 | +* there is no physical mechanism to induce noise coincident and rythmic | |
350 | +* with timer overflow. | |
340 | 351 | |
341 | 352 | * The cancel TOGGLE bit is suppressed on same-direction rotation. |
342 | 353 | * Trailing edge TOGGLEs are filtered out for all but brake and engine-on. |
@@ -353,9 +364,23 @@ FLTIME rmb 1 ; flash flash time to load | ||
353 | 364 | * the button events in a queue. (Darn! I was kind of proud of that six |
354 | 365 | * byte queue, and the shift technique for storing events into it.) |
355 | 366 | |
367 | +* The engine time-out counter resets on any activity on the engine | |
368 | +* switch, emergency flashers, or brake lights. This has the side effect | |
369 | +* of allowing the turn signals to function with the engine off for five | |
370 | +* minutes after the engine is shut off, or for five minutes after either | |
371 | +* the brakes or emergency flashers are used. | |
372 | + | |
373 | +* Both timers reset in such a manner as to be in a known state at | |
374 | +* any time they are put into use. | |
375 | + | |
376 | +* The emergency and turn signal signal flasher shares a single | |
377 | +* rate and duty cycle. | |
378 | + | |
356 | 379 | SUBHEADER 'Timer Service Code -- Debounce and Toggle Filter' |
357 | 380 | PAGE |
358 | 381 | |
382 | + swi | |
383 | + | |
359 | 384 | $CYCLE_ADDER_ON |
360 | 385 | TIMSRV bset TOFR_,TSCR |
361 | 386 |
@@ -379,6 +404,8 @@ TMMEMG lsra ; remap | ||
379 | 404 | |
380 | 405 | * read the turn signal return and manual cancel auxiliary flags |
381 | 406 | * (F_CAN & turn_sig_on) <=> read auxiliary flags |
407 | +* Assume that DDRB showing output means turn signal on and waiting | |
408 | +* for cancel. | |
382 | 409 | bit #F_CAN ; nothing at all without cancel |
383 | 410 | beq TMSTGL |
384 | 411 | ldx DDRB ; meaningless if not waiting for cancel |
@@ -403,7 +430,7 @@ $CYCLE_ADDER_OFF | ||
403 | 430 | $CYCLE_ADDER_ON |
404 | 431 | |
405 | 432 | * debounce inputs, set flags in TOGGLE and ISTATE |
406 | -* STABLE = ~((DEBO[0] ^ DEBO[1]) | (DEBO[1] ^ DEBO[2])) | |
433 | +* STABLE_BITS = ~((DEBO[0] ^ DEBO[1]) | (DEBO[1] ^ DEBO[2])) | |
407 | 434 | * |
408 | 435 | TMSTGL eor DEBO+1 |
409 | 436 | sta TOGGLE ; re-use TOGGLE, TOGGLE not valid |
@@ -411,18 +438,18 @@ TMSTGL eor DEBO+1 | ||
411 | 438 | eor DEBO+2 |
412 | 439 | ora TOGGLE ; a bit for any input that bounced |
413 | 440 | coma ; bits that bounced are clear |
414 | - tax | |
415 | - and DEBO+2 ; state of stable bits | |
416 | - sta STABLE ; (unstable bits still clear) | |
441 | + tax ; STABLE_BITS | |
442 | + and DEBO ; state of stable bits | |
443 | + sta SSTBLE ; (unstable bits still clear) | |
417 | 444 | txa |
418 | 445 | and ISTATE ; look only at bits that are stable |
419 | - eor STABLE ; flag bits that toggled | |
446 | + eor SSTBLE ; flag bits that toggled | |
420 | 447 | sta TOGGLE ; true TOGGLEs, but not yet filtered |
421 | 448 | coma ; mask of non-toggles |
422 | 449 | and ISTATE ; old state of non-toggles |
423 | 450 | sta ISTATE ; (toggled bits cleared) |
424 | 451 | lda TOGGLE ; mask of toggles |
425 | - and STABLE ; new states of bits that toggled | |
452 | + and SSTBLE ; new states of bits that toggled | |
426 | 453 | ora ISTATE |
427 | 454 | sta ISTATE ; ISTATE now has current debounced inputs |
428 | 455 |
@@ -448,19 +475,20 @@ TMBRKMV bclr F_BRK_,STATES | ||
448 | 475 | bset F_BRK_,STATES |
449 | 476 | |
450 | 477 | * toggle STATES F_EMG if TOGGLE F_EMG |
451 | -TMEMGMV brclr F_EMG_,TOGGLE,TMEMGM0 | |
478 | +TMEMGMV brclr F_EMG_,TOGGLE,TMEMG0 | |
452 | 479 | lda STATES |
453 | 480 | eor #F_EMG |
454 | 481 | TMEMG0 sta STATES |
455 | 482 | |
456 | 483 | * turn on STATES turn signal if TOGGLE turn signal |
484 | +* (TOGGLE was filtered on trailing edge!) | |
457 | 485 | lda TOGGLE |
458 | - and #{F_LFT | F_RGT} | |
486 | + and #TURNSIG | |
459 | 487 | ora STATES |
460 | 488 | |
461 | 489 | * cancel STATES turn signal if TOGGLE F_CAN is not filtered out |
462 | 490 | brclr F_CAN_,TOGGLE,TMCAN0 |
463 | - and #{$FF ^ F_LFT ^ F_RGT} ; STATES still in A | |
491 | + and #{$FF ^ TURNSIG} ; STATES still in A | |
464 | 492 | TMCAN0 sta STATES |
465 | 493 | |
466 | 494 | * Engine time out state is handled within the software timer |
@@ -476,12 +504,14 @@ TMCLOCK | ||
476 | 504 | brclr RTIF_,TSCR,TIMDUN |
477 | 505 | bset RTIFR_,TSCR |
478 | 506 | |
479 | -* The engine time-out counter resets if engine on toggles. It | |
480 | -* runs only when the ISTATE F_NGN bit is low and the emergency flashers | |
481 | -* and brakes (STATES F_EMG and F_BRK) are off. It does not underfow. | |
482 | -* The timer flags timeout in STATES F_NGN. | |
507 | +* The engine time-out counter resets if NGN, EMG, or BRK toggles. | |
508 | +* It runs only when the ISTATE F_NGN bit is low and the emergency | |
509 | +* flashers and brakes (STATES F_EMG and F_BRK) are off. It does not | |
510 | +* underfow. The timer flags timeout in STATES F_NGN. | |
483 | 511 | |
484 | - brclr F_NGN_,TOGGLE,TMNGN0 ; reset on toggle off (and on) | |
512 | + lda TOGGLE | |
513 | + and #{F_NGN | F_EMG | F_BRK} | |
514 | + beq TMNGN0 ; reset on toggle off (and on) | |
485 | 515 | lda #{TIMOUT & $FF } ; reset value low byte |
486 | 516 | sta NGN_TIM+1 |
487 | 517 | lda #{TIMOUT / $100 + 1} ; borrow on 0, not -1 |
@@ -491,28 +521,42 @@ TMCLOCK | ||
491 | 521 | TMNGN0 |
492 | 522 | lda STATES |
493 | 523 | and #{F_NGN | F_EMG | F_BRK} ; brakes or emg flashers? |
494 | - eor #F_NGN ; no underflow | |
524 | + eor #F_NGN ; engine already off? | |
495 | 525 | bne TMFLASH |
496 | - brset F_NGN_,ISTATE,TMFLASH | |
526 | + brset F_NGN_,ISTATE,TMFLASH ; ISTATE F_NGN back on? | |
497 | 527 | dec NGN_TIM+1 |
498 | - bne TIMFLH ; initial count is adjusted to make this work | |
528 | + bne TMFLASH ; initial count is adjusted to make this work | |
499 | 529 | dec NGN_TIM |
500 | - bne TIMFLH | |
530 | + bne TMFLASH | |
501 | 531 | bclr F_NGN_,STATES ; signal timed out |
502 | - bset F_NGN_,TOGGLE ; communicate with MAINLOOP | |
532 | + bset F_NGN_,TOGGLE ; communicate change to STATES F_NGN | |
533 | + | |
534 | +* The flasher counter runs only when STATES F_EMG, F_LFT, or F_RGT | |
535 | +* are set. When there are no flashers running, FLDARK is set, causing | |
536 | +* FLASH1 (on time) to be loaded when when flasher timer starts. | |
537 | + | |
538 | +TMFLASH lda #{F_EMG | TURNSIG} | |
539 | + bit STATES ; flasher active? | |
540 | + bne TMFLH1 | |
541 | + lda #-1 ; reset flash timer | |
542 | + sta FLDARK | |
543 | + lda #FLASH1 | |
544 | + sta FLASH | |
545 | + bra TIMDUN | |
503 | 546 | |
504 | -* flasher counter | |
505 | -TMFLASH lda #{F_EMG | F_LFT | F_RGT} | |
506 | - and STATES ; flasher active? | |
507 | - beq TIMDUN | |
508 | - dec FLASH | |
547 | +TMFLH1 dec FLASH | |
509 | 548 | bne TIMDUN |
510 | - lda FLTIME | |
511 | - sta FLASH | |
549 | + lda #FLASH1 | |
550 | + com FDARK | |
551 | + bpl TMFLTM ; result dark (1s) or light (0s) | |
552 | + lda #FLASH0 | |
553 | +TMFLTM sta FLASH | |
512 | 554 | |
513 | 555 | TIMDUN rti |
514 | 556 | $CYCLE_ADDER_OFF |
515 | 557 | |
558 | + swi | |
559 | + | |
516 | 560 | SUBHEADER 'Initializations' |
517 | 561 | PAGE |
518 | 562 |
@@ -525,9 +569,9 @@ SWISRV | ||
525 | 569 | rsp ; now falls through to RSTSRV |
526 | 570 | |
527 | 571 | * general inits |
528 | -RSTSRV lda #{F_LDRV | F_RDRV | R_LDRV | R_RDRV} | |
572 | +RSTSRV lda #ALLAMPS | |
529 | 573 | sta PORTA ; initial output values |
530 | - lda #{F_LDRV | F_RDRV | R_LDRV | R_RDRV | DRVDRV} | |
574 | + lda #{ALLAMPS | DRVDRV} | |
531 | 575 | sta DDRA ; set up directions |
532 | 576 | sta PDRA ; pull downs only on inputs |
533 | 577 | clr PORTB ; initial outputs (do port B just in case) |
@@ -547,15 +591,17 @@ RSTSRV lda #{F_LDRV | F_RDRV | R_LDRV | R_RDRV} | ||
547 | 591 | ora #{TOFR|RTIFR} ; clear the flags |
548 | 592 | sta TSCR |
549 | 593 | * set up specific variables |
550 | - clr DEBO ; start debounce chain clear | |
551 | - clr DEBO+1 ; DEBO+2 is thrown out on first timer interrupt | |
552 | - clr STATES ; no unknown states | |
553 | - clr ISTATE | |
554 | -* because F_NGN may not be on, and we don't depend on timer reset quirks: | |
555 | - lda #{TIMOUT & $FF } ; reset value low byte | |
556 | - sta NGN_TIM+1 | |
557 | - lda #{TIMOUT / $100 + 1} ; borrow on 0, not -1 | |
558 | - sta NGN_TIM | |
594 | + lda #F_NGN ; pretend the engine is on, to get us started | |
595 | + sta DEBO ; start debounce chain clear | |
596 | + sta DEBO+1 ; DEBO+2 is thrown out on first timer interrupt | |
597 | + sta STATES ; no unknown states | |
598 | + sta ISTATE | |
599 | + sta TOGGLE ; forces time-out counter to reset | |
600 | + lda #-1 | |
601 | + sta FLDARK ; initial flash state is dark | |
602 | + lda #FLASH1 | |
603 | + sta FLASH ; initial flash time is on/light state | |
604 | + | |
559 | 605 | |
560 | 606 | * Falls through to DOSTATES |
561 | 607 |
@@ -563,71 +609,59 @@ RSTSRV lda #{F_LDRV | F_RDRV | R_LDRV | R_RDRV} | ||
563 | 609 | PAGE |
564 | 610 | |
565 | 611 | DOSTATES: |
566 | - cli ; leave interrupts enabled as much as possible | |
612 | + wait | |
567 | 613 | clra |
568 | 614 | sta COPR ; tell COP we're in control |
569 | 615 | |
570 | -* State machine for STATES | |
571 | -* Brake, eNgine, emerGency, Left, and Right | |
572 | -* | |
573 | -* B N G L R | output | |
574 | -* ----------|------ | |
575 | -* 1 x x x x | Brake lights! | |
576 | -* 0 x 1 x x | Emergency flashers! | |
577 | -* 0 0 0 x x | Power Down | |
578 | -* 0 1 0 0 0 | No outputs | |
579 | -* 0 1 0 0 1 | Right turn signal | |
580 | -* 0 1 0 1 0 | Left turn signal | |
581 | -* 0 1 0 1 1 | NONE, clear turn signal states | |
582 | -* | |
583 | -* Cancel is entirely handled within TIMSRV | |
584 | - | |
585 | - sei ; is this necessary? | |
586 | - brset F_BRK_,STATES,STBRK | |
587 | - brset F_EMG_,STATES,STEMG | |
588 | - brclr F_EMG_,STATES,STNG0 | |
589 | - | |
590 | -****** put turn signal code in here | |
591 | - | |
592 | -STBRK | |
593 | - bra DOSTATES | |
594 | - | |
595 | -STEMG | |
596 | - bra DOSTATES | |
597 | - | |
598 | -STNG0 | |
599 | - | |
600 | -* had some power conserving in here | |
601 | -* lda STATES ; can we save power for a bit? | |
602 | -* and #{F_LFT | F_RGT | F_BRK | F_EMG} | |
603 | -* bne MNDRVWT | |
604 | -* bclr DRVDRV_,PORTA | |
605 | -*MNDRVWT wait ; enable interrupts, wait for timer | |
606 | -* tst TOGGLE | |
607 | -* beq MNDRVWT ; nothing changed, nothing to respond to | |
608 | -** with no activity, COP periodically resets the MCU system | |
609 | -** this is not generally good engineering practice. | |
610 | -* bset DRVDRV_,PORTA ; IRQSRV might have driven the brake lights | |
611 | -* bra MAINLOOP ; check STOP and QUEUE again | |
612 | -* | |
613 | -** go to power conserving state | |
614 | -*MNSTOP lda #{F_LDRV | F_RDRV | R_LDRV | R_RDRV} | |
615 | -* sta PORTA ; shut everything down, organized! | |
616 | -* lda #{F_LDRV | F_RDRV | R_LDRV | R_RDRV | DRVDRV} | |
617 | -* sta DDRA ; set up directions | |
618 | -* sta PDRA ; pull downs only on inputs | |
619 | -* clr PORTB ; initial outputs (do port B just in case) | |
620 | -* clr DDRB ; B initially input | |
621 | -* clr PDRB ; with pull downs set | |
622 | -** make sure EPROM programming stuff is out of the way | |
623 | -* clr EPROG | |
624 | -* clr PESCR | |
625 | -** enable external interrupts | |
626 | -* bset IRQE_,ISCR ; DO NOT clear the flag (IRQ won't return) | |
627 | -* stop ; also shuts timer down | |
628 | -* jmp SWISRV ; should never come here (resets stack pointer) | |
629 | - | |
630 | - bra DOSTATES | |
616 | +* update the output state | |
617 | + lda #ALLAMPS ; guess nothing shines | |
618 | +STTBRK0 brclr F_EMG_,STATES,STTRGT ; EMG has priority | |
619 | + and #{$FF ^ ALLAMPS} | |
620 | + | |
621 | +STTRGT brclr F_LFT_,STATES,STTLFT | |
622 | + and #{$FF ^ LFTDRV} ; assume never LFT & RGT both | |
623 | + | |
624 | +STTLFT brclr F_RGT_,STATES,STTBRK ; no flashers? | |
625 | + and #{$FF ^ RGTDRV} | |
626 | + | |
627 | +STTFLH ora FLDARK ; mask out if flashers off | |
628 | + | |
629 | +STTBRK brclr F_BRK_,STATES,STTLIT | |
630 | + and #{$FF ^ REARDRV} ; brake has highest priority | |
631 | + and #ALLAMPS ; filter out DRVDRV, in particular | |
632 | + sta FLMASK | |
633 | + lda STATES ; do we need DRVDRV? | |
634 | + and #ANYLITE ; avoid turning DRVDRV on and off: | |
635 | + beq STT0LIT | |
636 | + bset DRVDRV_ ; keep set during dark part of flash | |
637 | + | |
638 | +STT0LIT lda PORTA | |
639 | + and #{$FF ^ ALLAMPS ^ DRVDRV} | |
640 | + ora FLMASK | |
641 | + sta PORTA | |
642 | + | |
643 | + brclr F_NGN_,STATES,DOSTATES ; all done until next time out | |
644 | + | |
645 | +* At this point, we know there has been neither engine nor flasher activity | |
646 | +* for about five minutes. | |
647 | + | |
648 | +* go to power conserving state | |
649 | +MNSTOP lda #ALLAMPS ; make sure they are off | |
650 | + sta PORTA ; shut everything down, organized! | |
651 | + lda #{ALLAMPS | DRVDRV} | |
652 | + sta DDRA ; set up directions | |
653 | + sta PDRA ; pull downs only on inputs | |
654 | + clr PORTB ; initial outputs (do port B just in case) | |
655 | + clr DDRB ; B initially input | |
656 | + clr PDRB ; with pull downs set | |
657 | +* make sure EPROM programming stuff is out of the way | |
658 | + clr EPROG | |
659 | + clr PESCR | |
660 | +* enable external interrupts | |
661 | + bset IRQE_,ISCR ; DO NOT clear the flag (don't miss anything) | |
662 | + stop ; also shuts timer down | |
663 | + swi ; should never come here (resets stack pointer) | |
664 | + | |
631 | 665 | |
632 | 666 | |
633 | 667 |