およそ20年前に、68HC05 の開発の練習に書いた車のブレイクライト・方向指示器コントローラです。
Revision | 59f3ed335f43973a07314214acc90f05997e2847 (tree) |
---|---|
Time | 2013-07-08 22:08:18 |
Author | Joel Matthew Rees <reiisi@user...> |
Commiter | Joel Matthew Rees |
iCleaning up the flasher code,
discussion of potential problems using this in a real car.
@@ -52,7 +52,25 @@ | ||
52 | 52 | * applications), and details of lamp driver circuits are mostly set |
53 | 53 | * aside. The logic has been tested with the M68HC705KICS simulator |
54 | 54 | * program, but has not been tested in a physical mock up or real |
55 | -* vehicle. | |
55 | +* vehicle. (I ran out of time for this project.) | |
56 | + | |
57 | +******* Potential problems: ****************************************** | |
58 | + | |
59 | +* I have not dealt with the problems that occur when the turn signals | |
60 | +* are turned on while the return sensors are within range of their | |
61 | +* actuator fields. Two more bits of port B would have allowed complete | |
62 | +* separation of the two functions. A little extra code might allow | |
63 | +* suppressing the turn signal inputs while both return switches are | |
64 | +* active, to reduce the operator frustration factor. | |
65 | + | |
66 | +* I have also mostly ignored the problems presented by shorted switches. | |
67 | +* Having the turn signal functions on port B is handy, because a week | |
68 | +* turn signal spring will not keep the circuit from staying in the STOP | |
69 | +* instruction. Another 50 bytes of ROM might have allowed tracking time | |
70 | +* of no change for every sensor, which could allow shutting out a | |
71 | +* sensor that has been active more than n minutes. | |
72 | + | |
73 | +********************************************************************** | |
56 | 74 | |
57 | 75 | * One of the intents of this design was to replace mechanical |
58 | 76 | * parts (that tend to flow in hot climates and become brittle in cold) |
@@ -273,6 +291,8 @@ NGN_SW equ B2 ; engine (ENG and EMG could be confusing) | ||
273 | 291 | NGN_SW_ equ B2_ |
274 | 292 | DRVDRV equ B1 |
275 | 293 | DRVDRV_ equ B1_ |
294 | +EMG_BTF equ DRVDRV ; where to fold EMG_BT | |
295 | +EMG_BTF_ equ DRVDRV_ | |
276 | 296 | CAN_BT equ B0 |
277 | 297 | CAN_BT_ equ B0_ |
278 | 298 | * PORTB |
@@ -280,7 +300,7 @@ LFT_BT equ B1 ; a handy data dependency! DO NOT CHANGE | ||
280 | 300 | LFT_BT_ equ B1_ |
281 | 301 | RGT_BT equ B0 ; another handy data dependency! |
282 | 302 | RGT_BT_ equ B0_ |
283 | -* EMG_BT equ IRQ inverted | |
303 | +* IRQ input (inverted) is the real EMG_BT | |
284 | 304 | |
285 | 305 | |
286 | 306 | * logical input definitions for debounce and states |
@@ -303,17 +323,26 @@ F_CAN_ equ {CAN_BT_ + 2} | ||
303 | 323 | F_OPC equ $40 ; opposite direction cancel record |
304 | 324 | F_MNC equ $80 ; manual cancel record |
305 | 325 | |
326 | +* The turn signal table and many of the turn signal routines | |
327 | +* depend on F_LFT and F_RGT and LFT_BT and RGT_BT being in bits one and | |
328 | +* zero (but not particular which is which!). If these are changed, | |
329 | +* there will be a domino effect on the rest of the code. | |
330 | + | |
306 | 331 | SUBHEADER 'Resource Definitions' |
307 | 332 | PAGE |
308 | 333 | |
309 | 334 | |
310 | 335 | XTAL equ 1 ; crystal frequency, in MHz |
311 | -RTIPOW equ 1 ; bits 1 & 0 for timer hardware | |
336 | +RTIPOW equ 0 | |
337 | +* 1 ; bits 1 & 0 for timer hardware | |
312 | 338 | RTIRATE equ {2 < RTIPOW} ; 2 ^ RTIPOW |
313 | -TIMOUT equ {9155*XTAL/RTIRATE+1} ; 5 minutes (if XTAL equ is correct) | |
339 | +TIMOUT equ 1 | |
340 | +* {9155*XTAL/RTIRATE+1} ; 5 minutes (if XTAL equ is correct) | |
314 | 341 | * only one flash rate, 2/3 duty cycle |
315 | -FLASH0 equ {32*XTAL/RTIRATE/4} ; about 1/4 second off time | |
316 | -FLASH1 equ {32*XTAL/RTIRATE/2} ; about 1/2 second on time | |
342 | +FLASH0 equ 1 | |
343 | +* {32*XTAL/RTIRATE/4} ; about 1/4 second off time | |
344 | +FLASH1 equ 1 | |
345 | +* {32*XTAL/RTIRATE/2} ; about 1/2 second on time | |
317 | 346 | |
318 | 347 | org MOR |
319 | 348 | * Software Pulldown is used. |
@@ -337,6 +366,9 @@ FLASH rmb 1 ; flash timer | ||
337 | 366 | FLDARK rmb 1 ; flash light or dark state, 11111111 == dark |
338 | 367 | FLMASK rmb 1 ; flash mask to communicate between BRK, EMG, and TRN |
339 | 368 | TMPTRN rmb 1 ; temporary for keep turn signal interpretation |
369 | +LASTST rmb 1 ; previous state record to separate timer from decode | |
370 | + rmb 4 | |
371 | +DBGCT rmb 4 ; count how many times TIMSRV has executed | |
340 | 372 | |
341 | 373 | |
342 | 374 | * ROM definitions follow: |
@@ -430,12 +462,17 @@ TIMSRV bset TOFR_,TSCR | ||
430 | 462 | lda DEBO |
431 | 463 | sta DEBO+1 |
432 | 464 | |
465 | +* record previous STATE | |
466 | + lda STATES | |
467 | + sta LASTST | |
468 | + | |
433 | 469 | * read the static inputs, converting physical to logical |
434 | 470 | lda PORTA |
435 | 471 | and #{BRK_SW | NGN_SW | CAN_BT} ; clears DRV_DRV |
436 | 472 | bih TMIEMG ; invert EMG and fold it in |
437 | - ora #F_EMG | |
438 | -TMIEMG lsla ; remap | |
473 | + ora #EMG_BTF ; keep temporally very close to first read | |
474 | +TMIEMG equ * | |
475 | + lsla ; remap | |
439 | 476 | lsla |
440 | 477 | sta DEBO |
441 | 478 | lda PORTB ; PB2-7 always read 0 |
@@ -460,14 +497,17 @@ $CYCLE_ADDER_ON | ||
460 | 497 | eor #{LFT_BT | RGT_BT} ; strobe other side |
461 | 498 | sta PORTB ; set output state first |
462 | 499 | sta DDRB ; handy (data dependent) output state, huh? |
463 | - brset F_CAN_,PORTA,TMTBIT6 ; F_CAN into carry | |
500 | + brset CAN_BT_,PORTA,TMTBIT6 ; CAN_BT_ into carry | |
464 | 501 | TMTBIT6 rora ; carry into bit 7 |
465 | 502 | clr DDRB ; kill strobe: manual cancel? |
466 | - brset F_CAN_,PORTA,TMTBIT7 ; F_CAN into carry again | |
503 | + brset CAN_BT_,PORTA,TMTBIT7 ; CAN_BT_ into carry again | |
467 | 504 | TMTBIT7 rora ; carry into bit 7 again |
468 | 505 | and #{F_OPC | F_MNC} |
469 | 506 | ora DEBO |
470 | - sta DEBO | |
507 | + bit #F_OPC ; ignore turn signals if opposition cancel | |
508 | + beq TMTNTN | |
509 | + and #{$FF ^ TURNSIG} | |
510 | +TMTNTN sta DEBO | |
471 | 511 | stx PORTB ; restore turn signal inputs |
472 | 512 | stx DDRB |
473 | 513 | TM0TURN equ * |
@@ -527,11 +567,13 @@ TMF1CAN equ * | ||
527 | 567 | TMF0BRK equ * |
528 | 568 | |
529 | 569 | * toggle STATES F_EMG if TOGGLE F_EMG |
570 | +* act on TOGGLE to avoid multiple reads of EMG button | |
530 | 571 | brclr F_EMG_,TOGGLE,TMF0EMG |
531 | 572 | lda STATES |
532 | 573 | eor #F_EMG |
533 | 574 | sta STATES ; STATES not yet valid! |
534 | -TMF0EMG bra TMSTRN ; skip over the turn signal states table | |
575 | +TMF0EMG equ * | |
576 | + bra TMSTRN ; skip over the turn signal states table | |
535 | 577 | * leaves A indeterminate |
536 | 578 | |
537 | 579 | swi ; since we have a few unused ROM locations |
@@ -540,6 +582,7 @@ TMF0EMG bra TMSTRN ; skip over the turn signal states table | ||
540 | 582 | swi |
541 | 583 | swi |
542 | 584 | |
585 | +* this table is very data dependent | |
543 | 586 | TURNSTATE equ * ; depends on turn signals being rightmost |
544 | 587 | * S' S I |
545 | 588 | fcb %00 ; 00 00 |
@@ -566,7 +609,7 @@ TURNSTATE equ * ; depends on turn signals being rightmost | ||
566 | 609 | * Darn! |
567 | 610 | * After careful consideration, I decided this table does not benefit |
568 | 611 | * from a more symbolic construction. As it stands, it does not matter |
569 | -* whether F_LFT or F_RGT is b0, only that both reside in B0 and B1. | |
612 | +* whether F_LFT or F_RGT is b0, only that they do reside in B0 and B1. | |
570 | 613 | |
571 | 614 | swi ; since we have a few unused ROM locations |
572 | 615 | swi |
@@ -594,7 +637,7 @@ TMSTRN lda STATES | ||
594 | 637 | * leaves A == STATES |
595 | 638 | |
596 | 639 | * cancel STATES turn signal if TOGGLE F_CAN is not filtered out |
597 | -* Act here on TOGGLE to avoid multiple reads of single actuator pass! | |
640 | +* Act on TOGGLE to avoid multiple reads of single actuator pass! | |
598 | 641 | * A == STATES on entry |
599 | 642 | brclr F_CAN_,TOGGLE,TMCAN0 |
600 | 643 | and #{$FF ^ TURNSIG} |
@@ -604,11 +647,18 @@ TMCAN0 equ * ; turn signals are valid | ||
604 | 647 | |
605 | 648 | * Now we should have no more than one turn signal on. |
606 | 649 | * set up steering wheel return sense state or clear it |
650 | +* then latch turn signal input to keep it from reverting | |
607 | 651 | * A == STATES on entry |
608 | 652 | and #TURNSIG |
609 | 653 | sta PORTB ; another handy value dependency! |
610 | 654 | sta DDRB ; gate it out, if there |
611 | -* A is trashed | |
655 | +* I feel there is a better way, but I'm out of time | |
656 | + sta TMPTRN ; feed response back | |
657 | + lda ISTATE | |
658 | + and #{$FF ^ TURNSIG} | |
659 | + ora TMPTRN | |
660 | + sta ISTATE | |
661 | +* leaves A == ISTATE | |
612 | 662 | |
613 | 663 | * if not timed out, STATES F_NGN should not yet be clear! |
614 | 664 | lda NGN_TIM+1 |
@@ -623,9 +673,8 @@ TMFNGN0 equ * | ||
623 | 673 | SUBHEADER 'Timer Service Code -- Engine Time Out and Flasher Timers' |
624 | 674 | PAGE |
625 | 675 | |
626 | -TMCLOCK | |
627 | 676 | * reset engine time-out if F_NGN, F_EMG, or F_BRK TOGGLEs |
628 | - lda TOGGLE | |
677 | +TMCLOCK lda TOGGLE | |
629 | 678 | and #{F_NGN | F_EMG | F_BRK} |
630 | 679 | beq TMORST |
631 | 680 | lda #{TIMOUT & $FF } ; reset value low byte |
@@ -634,10 +683,28 @@ TMCLOCK | ||
634 | 683 | sta NGN_TIM |
635 | 684 | TMORST equ * |
636 | 685 | |
686 | +* if flashers TOGGLE off, reset the flashers | |
687 | +* if they TOGGLE on, clear the mask only if none on before | |
688 | + lda #{F_EMG | TURNSIG} | |
689 | + bit TOGGLE | |
690 | + beq TMSCLK | |
691 | + bit STATES ; flasher active? | |
692 | + bne TMMFLH | |
693 | + lda #$FF ; reset flash timer | |
694 | + sta FLDARK | |
695 | + lda #FLASH1 | |
696 | + sta FLASH | |
697 | + bra TMSCLK | |
698 | + | |
699 | +TMMFLH bit LASTST ; flashers already running? | |
700 | + bne TMMFLH0 ; might be better to shine on every change? | |
701 | + clr FLDARK | |
702 | +TMMFLH0 equ * | |
703 | + | |
637 | 704 | * Although the Real Time Interrupt is masked, the software clocks |
638 | 705 | * clock on the RTI flag. See RTIPOW for the RTI flag rate |
639 | 706 | |
640 | - brclr RTIF_,TSCR,TIMDUN | |
707 | +TMSCLK brclr RTIF_,TSCR,TIMDUN | |
641 | 708 | bset RTIFR_,TSCR |
642 | 709 | |
643 | 710 | * Engine time-out counter only runs when the ISTATE F_NGN bit is |
@@ -664,28 +731,32 @@ TMNGNR0 equ * ; Only now is STATES valid! | ||
664 | 731 | |
665 | 732 | TMFLASH lda #{F_EMG | TURNSIG} |
666 | 733 | bit STATES ; flasher active? |
667 | - bne TMFLH1 | |
668 | - lda #$FF ; reset flash timer | |
669 | - sta FLDARK | |
670 | - lda #FLASH1 | |
671 | - sta FLASH | |
672 | - bra TMNFLH | |
673 | - | |
674 | -TMFLH1 dec FLASH | |
675 | - bne TMNFLH | |
734 | + beq TMFLH0 | |
735 | + dec FLASH | |
736 | + bne TMFLH0 | |
676 | 737 | lda #FLASH1 |
677 | 738 | com FLDARK |
678 | 739 | bpl TMFLTM ; result dark (1s) or light (0s) |
679 | 740 | lda #FLASH0 |
680 | 741 | TMFLTM sta FLASH |
681 | -TMNFLH equ * | |
742 | +TMFLH0 equ * | |
682 | 743 | |
683 | 744 | * It might be amusing to install a turn signal time out so that if |
684 | 745 | * the turn signals remain flashing for more than ten minutes, they turn |
685 | 746 | * themselves off. The entire mechanism should fit here. As mentioned |
686 | 747 | * above, consider safety first! |
687 | 748 | |
688 | -TIMDUN rti | |
749 | +TIMDUN | |
750 | + inc DBGCT+3 ; count number of timer interrupts serviced | |
751 | + bne TIMDUX ; put here strictly for debugging sessions | |
752 | + inc DBGCT+2 ; so I can have an idea of virtual time | |
753 | + bne TIMDUX | |
754 | + inc DBGCT+1 | |
755 | + bne TIMDUX | |
756 | + inc DBGCT | |
757 | +TIMDUX | |
758 | + bset IRQR_,ISCR ; POTA and IRQ activity may set IRQF | |
759 | + rti | |
689 | 760 | $CYCLE_ADDER_OFF |
690 | 761 | |
691 | 762 | swi ; more unused ROM |
@@ -706,9 +777,15 @@ SWISRV | ||
706 | 777 | ldx #$5C ; unique |
707 | 778 | stx COPR |
708 | 779 | rsp ; now falls through to RSTSRV |
780 | + bset IRQR_,ISCR ; it just gets us started | |
709 | 781 | |
710 | 782 | * general inits |
711 | -RSTSRV lda #DRVLMPS | |
783 | +RSTSRV | |
784 | +* disable external interrupts | |
785 | + bclr IRQE_,ISCR ; disable external interrupts | |
786 | + bset IRQR_,ISCR ; clear the external interrupt flag | |
787 | +* get ports stared right | |
788 | + lda #DRVLMPS | |
712 | 789 | sta PORTA ; initial output values |
713 | 790 | lda #{DRVLMPS | DRVDRV} |
714 | 791 | sta DDRA ; set up directions |
@@ -717,18 +794,8 @@ RSTSRV lda #DRVLMPS | ||
717 | 794 | clr DDRB ; B initially input |
718 | 795 | clr PDRB ; with pull downs set |
719 | 796 | * make sure EPROM programming stuff is out of the way |
720 | - clr EPROG ; ICS05K complains, skip by hand | |
797 | +* clr EPROG ; ICS05K complains, skip by hand | |
721 | 798 | clr PESCR |
722 | -* disable external interrupts | |
723 | - bclr IRQE_,ISCR | |
724 | - bset IRQR_,ISCR ; clear the flag | |
725 | -* set up hardware timer | |
726 | - ldx #$6A ; unique use of X | |
727 | - stx COPR ; b0 clear, about to change timer rate | |
728 | - lda #{TOIE | RTIPOW} ; only timer overflow interrupts | |
729 | - sta TSCR ; RTIPOW has the timer rate | |
730 | - ora #{TOFR|RTIFR} ; clear the flags | |
731 | - sta TSCR | |
732 | 799 | * set up specific variables |
733 | 800 | lda #F_NGN ; pretend the engine is on, to get us started |
734 | 801 | sta DEBO ; start debounce chain clear |
@@ -743,6 +810,19 @@ RSTSRV lda #DRVLMPS | ||
743 | 810 | sta FLDARK ; initial flash state is dark |
744 | 811 | lda #FLASH1 |
745 | 812 | sta FLASH ; initial flash time is on/light state |
813 | +* clear the virtual debugging time counter | |
814 | + clr DBGCT | |
815 | + clr DBGCT+1 | |
816 | + clr DBGCT+2 | |
817 | + clr DBGCT+3 | |
818 | +* set up hardware timer | |
819 | + ldx #$6A ; unique use of X | |
820 | + stx COPR ; b0 clear, about to change timer rate | |
821 | + lda #{RTIPOW} ; set rate | |
822 | + sta TSCR | |
823 | + ora #{TOFR | RTIFR} ; clear pending interrupts | |
824 | + sta TSCR | |
825 | + bset TOIE_,TSCR ; first section overflow interrupt only | |
746 | 826 | |
747 | 827 | * Falls through to DOSTATES |
748 | 828 |
@@ -830,18 +910,18 @@ STT0FLH equ * | ||
830 | 910 | |
831 | 911 | * go to power conserving state |
832 | 912 | * first shut down all lamps |
833 | - lda #DRVLMPS ; DRVDRV also off! | |
834 | -* should be lda #{DRVLMPS & ~DRVDRV} for maximum clarity | |
835 | - sta PORTA | |
913 | + lda #DRVLMPS ; DRVDRV, CAN_BT also off! | |
914 | +* should be lda #{DRVLMPS & ~DRVDRV & ~CAN_BT} for clarity | |
915 | + sta PORTA ; don't feed CAN_BT to pull downs | |
836 | 916 | * now make sure power down state is valid! |
837 | - lda #{DRVLMPS | DRVDRV} | |
838 | - sta DDRA ; set up directions | |
917 | + lda #{DRVLMPS | DRVDRV | CAN_BT} | |
918 | + sta DDRA ; interrupts only from NGN_SW, BRK_SW, EMG_BT | |
839 | 919 | sta PDRA ; pull downs only on inputs |
840 | 920 | clr PORTB ; initial outputs (do port B just in case) |
841 | 921 | clr DDRB ; B initially input |
842 | 922 | clr PDRB ; with pull downs set |
843 | 923 | * make sure EPROM programming stuff is out of the way |
844 | - clr EPROG ; ICS complains, skip by hand | |
924 | +* clr EPROG ; ICS complains, skip by hand | |
845 | 925 | clr PESCR |
846 | 926 | * enable external interrupts |
847 | 927 | bset IRQE_,ISCR ; DO NOT clear the flag (don't miss anything) |
@@ -850,12 +930,6 @@ STT0FLH equ * | ||
850 | 930 | swi ; more unused ROM |
851 | 931 | swi |
852 | 932 | swi |
853 | - swi | |
854 | - swi | |
855 | - swi | |
856 | - swi | |
857 | - swi | |
858 | - swi | |
859 | 933 | |
860 | 934 | SUBHEADER 'Interrupt Vectors' |
861 | 935 | PAGE |