およそ20年前に、68HC05 の開発の練習に書いた車のブレイクライト・方向指示器コントローラです。
リビジョン | 87d119348dbdd8f7afe497e05a5883312ac349d7 (tree) |
---|---|
日時 | 2013-07-08 21:52:31 |
作者 | Joel Matthew Rees <reiisi@user...> |
コミッター | Joel Matthew Rees |
Refactoring and cleaning up the brake lights and emergency flashers.
@@ -3,7 +3,7 @@ | ||
3 | 3 | |
4 | 4 | * Electronic Turn Signal and Emergency Flasher Switch/Timer |
5 | 5 | * Version 1.00 |
6 | -* Implemented on the 68HC(7)05Kx | |
6 | +* Implemented on the 68HC705K1 | |
7 | 7 | * Assembled and tested on the M68HC705KICS |
8 | 8 | * |
9 | 9 | * Copyright 1993 Joel Matthew Rees |
@@ -11,11 +11,11 @@ | ||
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 October 1993 | |
15 | -* of | |
16 | -* South Salt Lake City | |
17 | -* Utah | |
18 | -* | |
14 | +* Authored by Joel Matthew Rees, June to November 1993 | |
15 | +* of also of | |
16 | +* South Salt Lake City Amagasaki | |
17 | +* Utah Japan | |
18 | +* | |
19 | 19 | |
20 | 20 | |
21 | 21 |
@@ -54,7 +54,7 @@ | ||
54 | 54 | * program, but has not been tested in a physical mock up or real |
55 | 55 | * vehicle. |
56 | 56 | |
57 | -* One of the objects of this design was to replace mechanical | |
57 | +* One of the intents of this design was to replace mechanical | |
58 | 58 | * parts (that tend to flow in hot climates and become brittle in cold) |
59 | 59 | * with logic. In order to eliminate the mechanical latching lever with |
60 | 60 | * spring loaded return, I have (perhaps arbitrarily) enforced a new "user |
@@ -213,7 +213,8 @@ | ||
213 | 213 | * manual cancel, the cancel port can sense steering wheel rotation. In |
214 | 214 | * same direction rotation, there is a lead period when the cancel input |
215 | 215 | * does not remain high if the turn signal input ports' output states are |
216 | -* inverted. Debounce suppresses cancel under these conditions. | |
216 | +* inverted. The debounce routine suppresses cancel under the latter | |
217 | +* conditions. | |
217 | 218 | |
218 | 219 | * Since the opposite direction turn signal switch port remains an |
219 | 220 | * input, it can still be sensed. The operator can change turn signals |
@@ -222,11 +223,11 @@ | ||
222 | 223 | * The separation of the switches and the actuation arc length I |
223 | 224 | * specify are based on my assumption that the steering wheel will rotate |
224 | 225 | * at a maximum speed of three revolutions per second, and that the four |
225 | -* to six mS required debounce period requires a minimum 10 milli-second | |
226 | -* separate actuation period. The actual result was 10.9 degrees | |
227 | -* separate actuation (21.8 total), which I arbitrarily rounded up to a | |
228 | -* power of two fraction of the circle: 2*PI/16 total actuation and | |
229 | -* 2*PI/32 separate actuation. | |
226 | +* to six mS (1 MHz crystal) required debounce period requires a minimum | |
227 | +* 10 milli-second separate actuation period. The actual result was 10.9 | |
228 | +* degrees separate actuation (21.8 total), which I arbitrarily rounded | |
229 | +* up to a power of two fraction of the circle: 2*PI/16 total actuation | |
230 | +* and 2*PI/32 separate actuation. | |
230 | 231 | |
231 | 232 | * A peculiar characteristic of this design is the apparent lack of |
232 | 233 | * use for the RESET input. Since power-on reset is built in to the |
@@ -235,7 +236,7 @@ | ||
235 | 236 | |
236 | 237 | * This assembler appears not to have a bit-not function for |
237 | 238 | * operand expressions. So, I have in several places resorted to the |
238 | -* rather obtuse expedient of exclusive-orring bits to be reset with $FF, | |
239 | +* obtuse expedient of exclusive-orring bits to be reset with $FF, | |
239 | 240 | * ergo, AND #{$FF ^ F_OPC ^ F_MNC} |
240 | 241 | * instead of AND #~(F_OPC | F_MNC) |
241 | 242 | * which I think would have been clearer. |
@@ -257,11 +258,11 @@ R_LDRV equ B5 | ||
257 | 258 | R_LDRV_ equ B5_ |
258 | 259 | R_RDRV equ B4 |
259 | 260 | R_RDRV_ equ B4_ |
260 | -ALLAMPS equ {F_LDRV | F_RDRV | R_LDRV | R_RDRV} | |
261 | +DRVLMPS equ {F_LDRV | F_RDRV | R_LDRV | R_RDRV} | |
261 | 262 | LFTDRV equ {F_LDRV | R_LDRV} |
262 | 263 | RGTDRV equ {F_RDRV | R_RDRV} |
263 | 264 | FRNTDRV equ {F_LDRV | F_RDRV} |
264 | -REARDRV eau {R_LDRV | R_RDRV} | |
265 | +REARDRV equ {R_LDRV | R_RDRV} | |
265 | 266 | BRK_SW equ B3 |
266 | 267 | BRK_SW_ equ B3_ |
267 | 268 | NGN_SW equ B2 ; engine (ENG and EMG could be confusing) |
@@ -311,7 +312,15 @@ FLASH0 equ {32*XTAL/RTIRATE/4} ; about 1/4 second off time | ||
311 | 312 | FLASH1 equ {32*XTAL/RTIRATE/2} ; about 1/2 second on time |
312 | 313 | |
313 | 314 | org MOR |
314 | - fcb {PIN3 | RC | PIRQ | COPEN} | |
315 | +* Software Pulldown is used. | |
316 | +* Can't spare the third RC oscillator pin. | |
317 | +* Set RC because we assume the cheap oscillator. | |
318 | +* STOP must not convert to WAIT: saves power when engine off. | |
319 | +* Assume Low Voltage Reset would be meaningless. | |
320 | +* PA3 - PA0 interrupts are used to bring the chip up for brake, engine on. | |
321 | +* Accept level sensitive interrupts, since IRQ is disabled immediately. | |
322 | +* Assume COP might be useful here. | |
323 | + fcb {RC | PIRQ | LEVEL | COPEN} | |
315 | 324 | |
316 | 325 | org RAMBEG |
317 | 326 | DEBO rmb 3 ; the debounce record chain |
@@ -338,11 +347,11 @@ FLMASK rmb 1 ; flash mask to communicate between BRK, EMG, and TRN | ||
338 | 347 | |
339 | 348 | * The debounce routine translates the physical inputs to logical |
340 | 349 | * inputs, maintains a record of the last three logical states sensed in |
341 | -* DEBO, debounces each input on three identical states, flags changes in | |
342 | -* the debounced input in TOGGLE, and leaves the current debounced input | |
343 | -* in ISTATE. Since debouncing occurs on three identical states, the | |
344 | -* debounce period is between two and three timer overflows -- 4 to 6 mS | |
345 | -* with a 1 MHz crystal, 2 to 3 mS with a 2 MHz crystal. | |
350 | +* DEBO, debounces (in parallel) each input on three identical states, | |
351 | +* flags changes in the debounced input in TOGGLE, and leaves the current | |
352 | +* debounced input in ISTATE. Since debouncing occurs on three identical | |
353 | +* states, the debounce period is between two and three timer overflows | |
354 | +* -- 4 to 6 mS with a 1 MHz crystal, 2 to 3 mS with a 2 MHz crystal. | |
346 | 355 | |
347 | 356 | * This debounce technique works because we don't care what is |
348 | 357 | * happening to the inputs between timer overflows, and because we assume |
@@ -357,28 +366,52 @@ FLMASK rmb 1 ; flash mask to communicate between BRK, EMG, and TRN | ||
357 | 366 | |
358 | 367 | * After adding an event queue and checking the timing results, two |
359 | 368 | * things became clear: there is plenty of time to handle all the changes |
360 | -* to STATES without a queue, and TOGGLE makes a sort of horizontal queue | |
361 | -* anyway. In other words, there is no reason to make the adjustments to | |
362 | -* STATES asynchronous when there is plenty of headroom for synchronous | |
363 | -* adjustments. Moreover, the adjustments take less time than organizing | |
364 | -* the button events in a queue. (Darn! I was kind of proud of that six | |
365 | -* byte queue, and the shift technique for storing events into it.) | |
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. | |
369 | +* to STATES without a queue, and TOGGLE makes a sort of horizontal | |
370 | +* priority queue anyway. In other words, there is no reason to make the | |
371 | +* adjustments to STATES asynchronous when there is plenty of headroom | |
372 | +* for synchronous adjustments. Moreover, the adjustments take less time | |
373 | +* than organizing the button events in a queue. (Darn! I was kind of | |
374 | +* proud of that six byte queue, and the shift technique for storing | |
375 | +* events into it.) | |
376 | + | |
377 | +* The engine time-out counter communicates with the power down | |
378 | +* routine via the STATES engine on (F_NGN) bit. In other words, STATES | |
379 | +* F_NGN bit is held off until the ISTATE F_NGN bit and the STATES F_EMG | |
380 | +* and F_BRK bits have been inactive for five minutes. (This perhaps | |
381 | +* overloads the semantics of STATES F_NGN.) | |
382 | + | |
383 | +* In the current design, the turn signals are not masked with the | |
384 | +* ISTATE F_NGN bit, and so will function during the time-out period. | |
385 | +* This "feature" can easily be corrected in the debounce routine. | |
386 | + | |
387 | +* It should be relatively easy to add a turn signal time-out | |
388 | +* counter to turn off the turn signals after the same turn signal has | |
389 | +* been on an un-reasonable period, such as five or more minutes. | |
390 | +* Such a time-out might negatively impact safety when attempting to turn | |
391 | +* in backed-up traffic or onto a very busy highway, or when using the | |
392 | +* turn signal to show a car parked for delivery, etc. It also might | |
393 | +* cause drivers to become even lazier. | |
372 | 394 | |
373 | 395 | * Both timers reset in such a manner as to be in a known state at |
374 | 396 | * any time they are put into use. |
375 | 397 | |
376 | -* The emergency and turn signal signal flasher shares a single | |
398 | +* The single emergency and turn signal signal flasher uses a single | |
377 | 399 | * rate and duty cycle. |
378 | 400 | |
379 | 401 | SUBHEADER 'Timer Service Code -- Debounce and Toggle Filter' |
380 | 402 | PAGE |
381 | 403 | |
404 | + swi ; since we have a few unused ROM locations | |
405 | + swi | |
406 | + swi | |
407 | + swi | |
408 | + swi | |
409 | + swi | |
410 | + swi | |
411 | + swi | |
412 | + swi | |
413 | + swi | |
414 | + swi | |
382 | 415 | swi |
383 | 416 | |
384 | 417 | $CYCLE_ADDER_ON |
@@ -393,10 +426,10 @@ TIMSRV bset TOFR_,TSCR | ||
393 | 426 | * read the static inputs, converting physical to logical |
394 | 427 | lda PORTA |
395 | 428 | and #{BRK_SW | NGN_SW | CAN_BT} ; clears DRV_DRV |
396 | - bih TMMEMG ; invert EMG and fold it in | |
429 | + bih TMIEMG ; invert EMG and fold it in | |
397 | 430 | ora #F_EMG |
398 | -TMMEMG lsra ; remap | |
399 | - lsra | |
431 | +TMIEMG lsla ; remap | |
432 | + lsla | |
400 | 433 | sta DEBO |
401 | 434 | lda PORTB ; PB2-7 always read 0 |
402 | 435 | ora DEBO |
@@ -406,33 +439,36 @@ TMMEMG lsra ; remap | ||
406 | 439 | * (F_CAN & turn_sig_on) <=> read auxiliary flags |
407 | 440 | * Assume that DDRB showing output means turn signal on and waiting |
408 | 441 | * for cancel. |
442 | + | |
409 | 443 | bit #F_CAN ; nothing at all without cancel |
410 | - beq TMSTGL | |
444 | + beq TM0TURN | |
411 | 445 | ldx DDRB ; meaningless if not waiting for cancel |
412 | - beq TMSTGL | |
446 | + beq TM0TURN | |
413 | 447 | $CYCLE_ADDER_OFF |
414 | 448 | $CYCLE_ADDER_ON |
415 | 449 | txa |
416 | 450 | eor #{LFT_BT | RGT_BT} ; strobe other side |
417 | 451 | sta PORTB ; set output state first |
418 | 452 | sta DDRB ; handy output state, huh? |
419 | - brset F_CAN_,PORTA,TM0000 ; F_CAN into carry | |
420 | -TM0000 rora | |
421 | - clr DDRB ; no strobe: manual cancel? | |
422 | - brset F_CAN_,PORTA,TM0001 ; F_CAN into carry again | |
423 | -TM0001 rora | |
453 | + brset F_CAN_,PORTA,TMTBIT6 ; F_CAN into carry | |
454 | +TMTBIT6 rora ; carry into bit 7 | |
455 | + clr DDRB ; kill strobe: manual cancel? | |
456 | + brset F_CAN_,PORTA,TMTBIT7 ; F_CAN into carry again | |
457 | +TMTBIT7 rora ; carry into bit 7 again | |
424 | 458 | and #{F_OPC | F_MNC} |
425 | 459 | ora DEBO |
426 | 460 | sta DEBO |
427 | 461 | stx PORTB ; restore turn signal inputs |
428 | 462 | stx DDRB |
463 | +TM0TURN equ * | |
464 | +* leave A == DEBO | |
429 | 465 | $CYCLE_ADDER_OFF |
430 | 466 | $CYCLE_ADDER_ON |
431 | 467 | |
432 | 468 | * debounce inputs, set flags in TOGGLE and ISTATE |
433 | 469 | * STABLE_BITS = ~((DEBO[0] ^ DEBO[1]) | (DEBO[1] ^ DEBO[2])) |
434 | -* | |
435 | -TMSTGL eor DEBO+1 | |
470 | +* A == DEBO on entry | |
471 | + eor DEBO+1 | |
436 | 472 | sta TOGGLE ; re-use TOGGLE, TOGGLE not valid |
437 | 473 | lda DEBO+1 |
438 | 474 | eor DEBO+2 |
@@ -452,16 +488,20 @@ TMSTGL eor DEBO+1 | ||
452 | 488 | and SSTBLE ; new states of bits that toggled |
453 | 489 | ora ISTATE |
454 | 490 | sta ISTATE ; ISTATE now has current debounced inputs |
491 | +* leave A == ISTATE | |
455 | 492 | |
456 | 493 | * filter out TOGGLE F_CAN if same direction |
494 | +* A == ISTATE on ENTRY | |
457 | 495 | bit #{F_OPC | F_MNC} ; opposite direction or manual? |
458 | - bne TMFFAL | |
496 | + bne TMF1CAN | |
459 | 497 | bclr F_CAN_,TOGGLE ; same direction |
498 | +TMF1CAN equ * | |
499 | +* leave A == ISTATE | |
460 | 500 | |
461 | 501 | * filter out trailing edge of F_LFT, F_RGT, F_EMG, F_CAN in TOGGLE |
462 | 502 | * also filter out auxiliary TOGGLEs in passing |
463 | -* assumes ISTATE still in A | |
464 | -TMFFAL ora #{F_NGN | F_BRK} ; not filtered | |
503 | +* ISTATE == A on entry | |
504 | + ora #{F_NGN | F_BRK} ; not filtered | |
465 | 505 | and TOGGLE ; filter any other (logical) fall(en) edge |
466 | 506 | and #{$FF ^ F_OPC ^ F_MNC} ; auxiliaries should never TOGGLE |
467 | 507 | sta TOGGLE |
@@ -470,15 +510,16 @@ TMFFAL ora #{F_NGN | F_BRK} ; not filtered | ||
470 | 510 | PAGE |
471 | 511 | |
472 | 512 | * move brake bit from ISTATE to STATES |
473 | -TMBRKMV bclr F_BRK_,STATES | |
474 | - brclr F_BRK_,ISTATE,TMEMGMV | |
513 | + bclr F_BRK_,STATES | |
514 | + brclr F_BRK_,ISTATE,TMF0BRK | |
475 | 515 | bset F_BRK_,STATES |
516 | +TMF0BRK equ * | |
476 | 517 | |
477 | 518 | * toggle STATES F_EMG if TOGGLE F_EMG |
478 | -TMEMGMV brclr F_EMG_,TOGGLE,TMEMG0 | |
519 | + brclr F_EMG_,TOGGLE,TMF0EMG | |
479 | 520 | lda STATES |
480 | 521 | eor #F_EMG |
481 | -TMEMG0 sta STATES | |
522 | +TMF0EMG sta STATES ; STATES not yet valid! | |
482 | 523 | |
483 | 524 | * turn on STATES turn signal if TOGGLE turn signal |
484 | 525 | * (TOGGLE was filtered on trailing edge!) |
@@ -489,47 +530,55 @@ TMEMG0 sta STATES | ||
489 | 530 | * cancel STATES turn signal if TOGGLE F_CAN is not filtered out |
490 | 531 | brclr F_CAN_,TOGGLE,TMCAN0 |
491 | 532 | and #{$FF ^ TURNSIG} ; STATES still in A |
492 | -TMCAN0 sta STATES | |
533 | +TMCAN0 sta STATES ; STATES not yet valid! | |
534 | + | |
535 | +* if not timed out, STATES F_NGN should not yet be clear! | |
536 | + lda NGN_TIM+1 | |
537 | + ora NGN_TIM | |
538 | + bne TMFNGN0 | |
539 | + bset F_NGN_,STATES ; might time out before RTI | |
540 | +TMFNGN0 equ * | |
493 | 541 | |
494 | -* Engine time out state is handled within the software timer | |
495 | -* routines. | |
542 | +* STATES is still not valid! | |
543 | +* fall through to TMCLOCK | |
496 | 544 | |
497 | 545 | SUBHEADER 'Timer Service Code -- Engine Time Out and Flasher Timers' |
498 | 546 | PAGE |
499 | 547 | |
500 | -* Although the Real Time Interrupt is masked, the software clocks | |
501 | -* use the RTI flag. See RTIPOW for the RTI flag rate | |
502 | - | |
503 | 548 | TMCLOCK |
504 | - brclr RTIF_,TSCR,TIMDUN | |
505 | - bset RTIFR_,TSCR | |
506 | - | |
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. | |
511 | - | |
549 | +* reset engine time-out if F_NGN, F_EMG, or F_BRK TOGGLEs | |
512 | 550 | lda TOGGLE |
513 | 551 | and #{F_NGN | F_EMG | F_BRK} |
514 | - beq TMNGN0 ; reset on toggle off (and on) | |
515 | - lda #{TIMOUT & $FF } ; reset value low byte | |
552 | + beq TMORST | |
553 | + lda #{TIMOUT & $FF } ; reset value low byte | |
516 | 554 | sta NGN_TIM+1 |
517 | 555 | lda #{TIMOUT / $100 + 1} ; borrow on 0, not -1 |
518 | 556 | sta NGN_TIM |
519 | - bra TMFLASH | |
557 | +TMORST equ * | |
558 | + | |
559 | +* Although the Real Time Interrupt is masked, the software clocks | |
560 | +* clock on the RTI flag. See RTIPOW for the RTI flag rate | |
520 | 561 | |
521 | -TMNGN0 | |
562 | + brclr RTIF_,TSCR,TIMDUN | |
563 | + bset RTIFR_,TSCR | |
564 | + | |
565 | +* Engine time-out counter only runs when the ISTATE F_NGN bit is | |
566 | +* low and the emergency flashers and brakes (STATES F_EMG and F_BRK) are | |
567 | +* off. Underflow is held off by cleared STATES F_NGN bit. Communicates | |
568 | +* with power down routine via STATES F_NGN. | |
569 | + | |
570 | + brset F_NGN_,ISTATE,TMNGNR0 | |
522 | 571 | lda STATES |
523 | 572 | and #{F_NGN | F_EMG | F_BRK} ; brakes or emg flashers? |
524 | - eor #F_NGN ; engine already off? | |
525 | - bne TMFLASH | |
526 | - brset F_NGN_,ISTATE,TMFLASH ; ISTATE F_NGN back on? | |
573 | + eor #F_NGN ; already counted out? | |
574 | + bne TMNGNR0 | |
527 | 575 | dec NGN_TIM+1 |
528 | - bne TMFLASH ; initial count is adjusted to make this work | |
576 | + bne TMNGNR0 ; initial count is adjusted to make this work | |
529 | 577 | dec NGN_TIM |
530 | - bne TMFLASH | |
578 | + bne TMNGNR0 | |
531 | 579 | bclr F_NGN_,STATES ; signal timed out |
532 | 580 | bset F_NGN_,TOGGLE ; communicate change to STATES F_NGN |
581 | +TMNGNR0 equ * ; Only now is STATES valid! | |
533 | 582 | |
534 | 583 | * The flasher counter runs only when STATES F_EMG, F_LFT, or F_RGT |
535 | 584 | * are set. When there are no flashers running, FLDARK is set, causing |
@@ -542,19 +591,37 @@ TMFLASH lda #{F_EMG | TURNSIG} | ||
542 | 591 | sta FLDARK |
543 | 592 | lda #FLASH1 |
544 | 593 | sta FLASH |
545 | - bra TIMDUN | |
594 | + bra TMNFLH | |
546 | 595 | |
547 | 596 | TMFLH1 dec FLASH |
548 | - bne TIMDUN | |
597 | + bne TMNFLH | |
549 | 598 | lda #FLASH1 |
550 | - com FDARK | |
599 | + com FLDARK | |
551 | 600 | bpl TMFLTM ; result dark (1s) or light (0s) |
552 | 601 | lda #FLASH0 |
553 | 602 | TMFLTM sta FLASH |
603 | +TMNFLH equ * | |
604 | + | |
605 | +* It might be amusing to install a turn signal time out so that if | |
606 | +* the turn signals remain flashing for more than ten minutes, they turn | |
607 | +* themselves off. The entire mechanism should fit here. As mentioned | |
608 | +* above, consider safety first! | |
554 | 609 | |
555 | 610 | TIMDUN rti |
556 | 611 | $CYCLE_ADDER_OFF |
557 | 612 | |
613 | + swi ; more unused ROM | |
614 | + swi | |
615 | + swi | |
616 | + swi | |
617 | + swi | |
618 | + swi | |
619 | + swi | |
620 | + swi | |
621 | + swi | |
622 | + swi | |
623 | + swi | |
624 | + swi | |
558 | 625 | swi |
559 | 626 | |
560 | 627 | SUBHEADER 'Initializations' |
@@ -564,28 +631,28 @@ $CYCLE_ADDER_OFF | ||
564 | 631 | * if SWI occurs, the machine is not in a defined state, and must reset |
565 | 632 | IRQSRV |
566 | 633 | SWISRV |
567 | - clra | |
568 | - sta COPR | |
634 | + ldx #$5C ; unique | |
635 | + stx COPR | |
569 | 636 | rsp ; now falls through to RSTSRV |
570 | 637 | |
571 | 638 | * general inits |
572 | -RSTSRV lda #ALLAMPS | |
639 | +RSTSRV lda #DRVLMPS | |
573 | 640 | sta PORTA ; initial output values |
574 | - lda #{ALLAMPS | DRVDRV} | |
641 | + lda #{DRVLMPS | DRVDRV} | |
575 | 642 | sta DDRA ; set up directions |
576 | 643 | sta PDRA ; pull downs only on inputs |
577 | 644 | clr PORTB ; initial outputs (do port B just in case) |
578 | 645 | clr DDRB ; B initially input |
579 | 646 | clr PDRB ; with pull downs set |
580 | 647 | * make sure EPROM programming stuff is out of the way |
581 | - clr EPROG | |
648 | + clr EPROG ; ICS05K complains, skip by hand | |
582 | 649 | clr PESCR |
583 | 650 | * disable external interrupts |
584 | 651 | bclr IRQE_,ISCR |
585 | 652 | bset IRQR_,ISCR ; clear the flag |
586 | 653 | * set up hardware timer |
587 | - clra | |
588 | - sta COPR ; b0 clear, about to change timer rate | |
654 | + ldx #$6A ; unique use of X | |
655 | + stx COPR ; b0 clear, about to change timer rate | |
589 | 656 | lda #{TOIE | RTIPOW} ; only timer overflow interrupts |
590 | 657 | sta TSCR ; RTIPOW has the timer rate |
591 | 658 | ora #{TOFR|RTIFR} ; clear the flags |
@@ -596,73 +663,130 @@ RSTSRV lda #ALLAMPS | ||
596 | 663 | sta DEBO+1 ; DEBO+2 is thrown out on first timer interrupt |
597 | 664 | sta STATES ; no unknown states |
598 | 665 | sta ISTATE |
599 | - sta TOGGLE ; forces time-out counter to reset | |
666 | + lda #{TIMOUT & $FF } ; reset time-out low byte | |
667 | + sta NGN_TIM+1 | |
668 | + lda #{TIMOUT / $100 + 1} ; counter borrows on 0, not -1 | |
669 | + sta NGN_TIM | |
600 | 670 | lda #-1 |
601 | 671 | sta FLDARK ; initial flash state is dark |
602 | 672 | lda #FLASH1 |
603 | 673 | sta FLASH ; initial flash time is on/light state |
604 | 674 | |
605 | - | |
606 | 675 | * Falls through to DOSTATES |
607 | 676 | |
608 | 677 | SUBHEADER 'DOSTATES: Interpret States' |
609 | 678 | PAGE |
610 | 679 | |
611 | -DOSTATES: | |
612 | - wait | |
613 | - clra | |
614 | - sta COPR ; tell COP we're in control | |
615 | - | |
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} | |
680 | +* The debounce and timer routines make the output state machine | |
681 | +* simple. All indicator lamps are set according to the indicator STATES, | |
682 | +* then masked by the current flasher output state (FLDARK). Then, if the | |
683 | +* brake light STATES bit is set, the rear lamps are forced on. Then, | |
684 | +* DRVDRV is only set if lamps are on (to save power when the engine is | |
685 | +* off). | |
686 | + | |
687 | +* Finally, if STATES F_NGN bit is clear, the power-down routine is | |
688 | +* executed (and never returned from). Again, requiring the time-out | |
689 | +* counter to hold off the STATES engine-on bit may be a bit of a | |
690 | +* semantic overload, but it seems more natural than making the STATES | |
691 | +* F_NGN bit a mere mirror of ISTATE F_NGN, and then maintaining a | |
692 | +* separate flag which would operate by the same rules as STATES F_NGN | |
693 | +* does in the present design. It also seems less data coupled than | |
694 | +* having the power-down sense routine examine the internals of the | |
695 | +* counter. | |
696 | + | |
697 | +* FLDARK is used slightly ambiguously: in the flasher timer | |
698 | +* routine, bit 7 is used to determine whether to use the on period or | |
699 | +* off period. In the output state machine, below, all lamp bits are | |
700 | +* used to mask out the signal lamps when the flasher says they should be | |
701 | +* dark. Rather than concern myself in several places with the state of | |
702 | +* non-lamp bits, I mask them out where they could cause trouble. | |
620 | 703 | |
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? | |
704 | +DOSTATES: | |
705 | + wait ; wait for something intelligible to debounce | |
706 | + ldx #$78 ; unique | |
707 | + stx COPR ; tell COP we're in control | |
708 | + | |
709 | +* update the (inverted) lamp output state | |
710 | + lda #DRVLMPS ; guess nothing shines (inverted drive) | |
711 | +* A == lamp output state | |
712 | + | |
713 | +* now mask in inverted drive bits for any flashers that are on | |
714 | + brclr F_EMG_,STATES,STT0EMG | |
715 | + and #{$FF ^ DRVLMPS} | |
716 | +STT0EMG equ * | |
717 | +* A == lamp output state | |
718 | + | |
719 | + brclr F_LFT_,STATES,STT0LFT | |
720 | + and #{$FF ^ LFTDRV} | |
721 | +STT0LFT equ * | |
722 | +* A == lamp output state | |
723 | + | |
724 | + brclr F_RGT_,STATES,STT0RGT | |
625 | 725 | and #{$FF ^ RGTDRV} |
726 | +STT0RGT equ * | |
727 | +* A == lamp output state | |
626 | 728 | |
627 | -STTFLH ora FLDARK ; mask out if flashers off | |
729 | +* mask out flasher lamps if flasher is in off state | |
730 | + ora FLDARK | |
731 | +* A == lamp output state | |
628 | 732 | |
629 | -STTBRK brclr F_BRK_,STATES,STTLIT | |
630 | - and #{$FF ^ REARDRV} ; brake has highest priority | |
631 | - and #ALLAMPS ; filter out DRVDRV, in particular | |
733 | +* check for brake lights | |
734 | +STTBRK brclr F_BRK_,STATES,STT0BRK | |
735 | + and #{$FF ^ REARDRV} ; brake has higher priority than flash | |
736 | +STT0BRK equ * | |
737 | +* A == lamp output state | |
738 | + | |
739 | + and #DRVLMPS ; filter out extraneous bits | |
632 | 740 | 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 | |
741 | + eor #DRVLMPS ; any lamps driven? | |
742 | + beq STT0FLH ; invert the CCR zero bit and move it to DRVDRV | |
743 | + bset DRVDRV_,FLMASK | |
744 | +STT0FLH equ * | |
745 | +* now A is free | |
637 | 746 | |
638 | -STT0LIT lda PORTA | |
639 | - and #{$FF ^ ALLAMPS ^ DRVDRV} | |
747 | + lda PORTA | |
748 | + and #{$FF ^ DRVLMPS ^ DRVDRV} | |
640 | 749 | ora FLMASK |
641 | 750 | sta PORTA |
642 | 751 | |
643 | - brclr F_NGN_,STATES,DOSTATES ; all done until next time out | |
752 | +* all done with lamps until next timer interrupt | |
753 | +* loop to wait if engine not timed-out | |
754 | + brclr F_NGN_,STATES,DOSTATES | |
644 | 755 | |
645 | -* At this point, we know there has been neither engine nor flasher activity | |
646 | -* for about five minutes. | |
756 | +* At this point, we know there has been no engine, emergency flasher, or | |
757 | +* brake activity for about five minutes. | |
647 | 758 | |
648 | 759 | * 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} | |
760 | +* first shut down all lamps | |
761 | + lda #DRVLMPS ; DRVDRV also off! | |
762 | +* should be lda #{DRVLMPS & ~DRVDRV} for maximum clarity | |
763 | + sta PORTA | |
764 | +* now make sure power down state is valid! | |
765 | + lda #{DRVLMPS | DRVDRV} | |
652 | 766 | sta DDRA ; set up directions |
653 | 767 | sta PDRA ; pull downs only on inputs |
654 | 768 | clr PORTB ; initial outputs (do port B just in case) |
655 | 769 | clr DDRB ; B initially input |
656 | 770 | clr PDRB ; with pull downs set |
657 | 771 | * make sure EPROM programming stuff is out of the way |
658 | - clr EPROG | |
772 | + clr EPROG ; ICS complains, skip by hand | |
659 | 773 | clr PESCR |
660 | 774 | * enable external interrupts |
661 | 775 | bset IRQE_,ISCR ; DO NOT clear the flag (don't miss anything) |
662 | 776 | stop ; also shuts timer down |
663 | - swi ; should never come here (resets stack pointer) | |
664 | - | |
777 | + swi ; should never come here (IRQSRV resests stack pointer) | |
778 | + swi ; more unused ROM | |
779 | + swi | |
780 | + swi | |
781 | + swi | |
782 | + swi | |
783 | + swi | |
784 | + swi | |
785 | + swi | |
786 | + swi | |
665 | 787 | |
788 | +* Darn! I never found a way to use the personality EPROM bits for | |
789 | +* a state machine! | |
666 | 790 | |
667 | 791 | |
668 | 792 | org VECTORS |
@@ -672,3 +796,4 @@ MNSTOP lda #ALLAMPS ; make sure they are off | ||
672 | 796 | fdb RSTSRV |
673 | 797 | |
674 | 798 | end |
799 | + |