• R/O
  • HTTP
  • SSH
  • HTTPS

コミット

よく使われているワード(クリックで追加)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

およそ20年前に、68HC05 の開発の練習に書いた車のブレイクライト・方向指示器コントローラです。


コミットメタ情報

リビジョン4ab5c3b066d5a8b0c0f5be069e9225e4601e9435 (tree)
日時2013-07-08 20:10:59
作者Joel Matthew Rees <reiisi@user...>
コミッターJoel Matthew Rees

ログメッセージ

Second backup. Nothing stands out besides work on debouncing and decoding.

変更サマリ

  • delete: TURNSIG.AS0 => TURNSIG.AS1

差分

--- a/TURNSIG.AS0
+++ b/TURNSIG.AS1
@@ -2,15 +2,20 @@
22 HEADER 'Turn Signal Switch by Joel Matthew Rees'
33
44 * Electronic Turn Signal and Emergency Flasher Switch/Timer
5+* Version 1.00
56 * Implemented on the 68HC(7)05Kx
67 * Assembled and tested on the M68HC705KICS
8+*
79 * Copyright 1993 Joel Matthew Rees
10+*
11+* Permission granted in advance for strictly non-profit
12+* educational use. All other rights retained by the author.
813
914 * Authored by Joel Matthew Rees, June to August 1993
1015 * of
1116 * South Salt Lake City
1217 * Utah
13-*
18+*
1419
1520
1621
@@ -35,7 +40,8 @@
3540 * switch back to mind. I thought ten bits of I/O, internal timers,
3641 * and the STOP mode would be sufficient to replicate the logic of that
3742 * switch assembly, adding directional turn signal return switches and
38-* flasher logic as well. It turned out to be a tight squeeze.
43+* flasher and turn sgnal return logic as well. It turned out to be a
44+* tight squeeze.
3945
4046 * The intent of this document is to focus on the problems of
4147 * decoding inputs, directionalizing the turn signal return, eliminating
@@ -44,7 +50,8 @@
4450 * electro-static discharge protection (very important in automotive
4551 * applications), and details of lamp driver circuits are mostly set
4652 * aside. The logic has been tested with the M68HC705KICS simulator
47-* program, but has not been tested in physical mock up or real vehicle.
53+* program, but has not been tested in a physical mock up or real
54+* vehicle.
4855
4956 * One of the objects of this design was to replace mechanical
5057 * parts (that tend to flow in hot climates and become brittle in cold)
@@ -66,15 +73,16 @@
6673 * The turn signal return mechanism is a pair of reed relays
6774 * mounted inside the bottom of the steering column cowling about ten
6875 * degrees apart, with three magnetic actuators mounted to the steering
69-* shaft at ten o'clock, two o'clock, and six o'clock. (Four magnets in
70-* an x pattern might also be workable, I haven't reworked the angular
71-* timing to be sure.) The shape and position of the magnets and reeds
72-* should be such that the reeds close only once as a magnet passes, and
73-* such that the reeds have about ten degrees of overlapping actuation.
74-* The overlap in actuation helps determine the direction the steering
75-* wheel is rotating. Minor changes to the software should allow the use
76-* of optical sensors, but I have the impression the magnetic devices are
77-* more immune to extremes of climate.
76+* shaft at ten o'clock, two o'clock, and six o'clock. (More magnets and
77+* other patterns might also be workable, but they should be tested in
78+* real steering assembly before the design is locked in. The shape and
79+* position of the magnets and reeds should be such that the reeds close
80+* only once as a magnet passes, and such that the reeds have about ten
81+* degrees of overlapping actuation. The overlap in actuation helps
82+* determine the direction the steering wheel is rotating. Minor changes
83+* to the design should allow the use of optical sensors, but I have the
84+* impression that magnetic devices are more immune to extremes of
85+* climate.
7886
7987 SUBHEADER 'Model Schematic'
8088 PAGE
@@ -106,11 +114,11 @@
106114 * +---5V_ZENER---GND
107115
108116 * PA1>---DRVRS_ON_CNTRL
109-*
117+
110118 * IRQ<---+---100K_OHM---Vdd
111119 * |
112120 * +---EMG_SW---GND
113-*
121+
114122 * PB1<>--+----------LEFT_RETURN_SW---+
115123 * | |
116124 * +---LEFT_TURN_SW---+ |
@@ -140,9 +148,8 @@
140148 * active high.
141149
142150 * I arbitrarily assume the signal lamp drivers will be active low.
143-* Who could say why? I considered attempting to hide this assumption in
144-* a macro but I'll skip that complexity. It shouldn't be too hard to
145-* find all the places to invert the outputs.
151+* Who could say why? However, I have hidden this assumption in a macro
152+* so I don't have to remember it.
146153
147154 * Hanging the indicators and the audio feedback on the front lamp
148155 * drivers separates them from brake activity. Two audio feedback
@@ -167,27 +174,34 @@
167174 * natural match for IRQ.
168175
169176 * The right turn signal return switch is positioned about five
170-* degrees right of bottom, and the left return is positioned the same
171-* distance to the left. In this way, when the steering wheel rotates,
172-* the return switch for the direction of rotation actuates first, then
173-* the opposite direction switch closes, then the same direction switch
174-* opens, and then the opposite direction switch opens. Thus, when
175-* restoring from a turn, the return switch for the appropriate direction
176-* closes after the other switch. In other words, if you turn right, the
177-* steering wheel will be rotate to the left when you restore to the
178-* straight, and the switches actuate from left to right during the
179-* restore.
177+* degrees right of bottom of the steering column housing, and the left
178+* return is positioned the same distance to the left. In this way, when
179+* the steering wheel rotates, the return switch for the direction of
180+* rotation actuates first, then the opposite direction switch closes,
181+* then the same direction switch opens, and then the opposite direction
182+* switch opens. Thus, when restoring from a turn, the return switch for
183+* the appropriate direction closes after the other switch. In other
184+* words, if you turn right, the steering wheel will be rotate to the
185+* left when you return to straight, and the switches actuate from left
186+* to right during the restore.
180187
181188 * When both turn signals are off, both turn signal ports are set
182189 * as inputs. When a turn signal switch input senses a closure, that
183190 * port is made an output and driven high. When the cancel input senses
184-* a closure, the turn signal ports are restored to both input. If the
185-* cancel input remains high, a manual cancel is decoded. If not, the
186-* other direction input is made output and driven high. If the cancel
187-* input remains high now, the other direction switch closed first, and a
188-* restoring rotation is decoded. If not, same direction rotation is
189-* decoded, so the opposite direction port is returned to input, and the
190-* original direction port is again made output and driven high.
191+* a closure, the turn signal ports are restored to both input.
192+
193+* If the cancel input remains high, a manual cancel is decoded.
194+* If not, the other direction input is made output and driven high. If
195+* the cancel input returns high now, the other direction switch closed
196+* first, and a restoring rotation is decoded. If not, same direction
197+* rotation is decoded; then the the opposite direction port is returned
198+* to input, and the original direction port is again made output and
199+* driven high to wait again.
200+
201+* In the meantime, if the opposite direction turn signal input
202+* senses a closure, then it is assumed that the operator changed his
203+* mind without hitting the manual cancel, and the roles of the turn
204+* signal I/O bits are reversed.
191205
192206 * A peculiar characteristic of this design is the apparent lack of
193207 * use for the RESET input. Since power-on reset is built in to the
@@ -196,6 +210,7 @@
196210
197211 SUBHEADER 'Obligatory Mnemonics'
198212 PAGE
213+$base $0A
199214 $include "68HC05K.EQU"
200215
201216 SUBHEADER 'Program Mnemonics'
@@ -227,38 +242,54 @@ RGT_BT_ equ B0_
227242
228243
229244 * logical input definitions for debounce and states
230-F_LFT equ {LFT_BT < 4} ; fold onto output
231-F_LFT_ equ {LFT_BT + 4}
232-F_RGT equ {RGT_BT < 4} ; fold onto output
233-F_RGT_ equ {RGT_BT + 4}
234-F_BRK equ BRK_SW
235-F_BRK_ equ BRK_SW_
236-F_ENG equ ENG_SW
237-F_ENG_ equ ENG_SW_
238-F_EMG equ DRVDRV ; fold onto output
239-F_EMG_ equ DRVDRV_
240-F_CAN equ CAN_BT
241-F_CAN_ equ CAN_BT_
242-
245+* bits are remapped for debounce and queue speed
246+F_LFT equ LFT_BT
247+F_LFT_ equ LFT_BT_
248+F_RGT equ RGT_BT
249+F_RGT_ equ RGT_BT_
250+F_BRK equ {BRK_SW < 2} ; physical output bit
251+F_BRK_ equ {BRK_SW_ + 2}
252+F_ENG equ {ENG_SW < 2} ; physical output bit
253+F_ENG_ equ {ENG_SW_ + 2}
254+F_EMG equ {DRVDRV < 2} ; fold onto output bit
255+F_EMG_ equ {DRVDRV_ + 2}
256+F_CAN equ {CAN_BT < 2}
257+F_CAN_ equ {CAN_BT_ + 2}
258+
259+* Event queue constants
260+* We only have 6 bit events and only record 4 in the queue.
261+* Event scan algorithm wired to highest event bit in bit 3.
262+
263+MAXEVENTS equ 6 ; more than max bit changes in "time slice"
243264
244265 SUBHEADER 'Resource Definitions'
245266 PAGE
246267
247268 * crystal frequency, in MHz:
248269 XTAL equ 1
270+RTIPOW equ 1 ; ls bits is right place for timer hardware
271+RTIRATE equ {2 < RTIPOW} ; 2 ^ RTIPOW stored is actual divide
272+TIMOUT equ {9155*XTAL/RTIRATE+1} ; 5 minutes (if XTAL equ is correct)
273+* only one flash rate, 2/3 duty cycle
274+FLASH0 equ {32*XTAL/RTIRATE/4} ; about 1/4 second
275+FLASH1 equ {32*XTAL/RTIRATE/2} ; about 1/2 second
249276
250277 org MOR
251278 fcb {PIN3 | RC | PIRQ | COPEN}
252279
253-
254280 org RAMBEG
255281 DEBO rmb 3 ; the debounce record chain
282+STABLE rmb 1 ; temporary record of stable bits
283+TOGGLQ equ STABLE ; temporary record of queue events
256284 TOGGLE rmb 1 ; record of toggles
257-STABLE rmb 1 ; timer service temporary
258285 ISTATE rmb 1 ; record of the current input state
286+QIN rmb 1 ; queue input point
287+QOUT rmb 1 ; queue output point
288+EVENTQ rmb MAXEVENTS ; no need to initialize this
259289 STATES rmb 1 ; current controller states
260290 ENG_TIM rmb 2 ; engine time out timer
261-SOFTIM rmb 2 ; flash timer
291+FLASH rmb 1 ; flash timer
292+FLTIME rmb 1 ; flash flash time to load
262293
263294
264295 * ROM definitions follow:
@@ -266,22 +297,21 @@ SOFTIM rmb 2 ; flash timer
266297
267298 SUBHEADER 'Timer Service Code -- debounce'
268299 PAGE
269-* The timer service routine has two functions: debouncing the
270-* inputs and maintaining the software clocks. Interrupts occur on timer
300+* The timer service routine has five functions: debouncing the
301+* inputs, directly setting the brake lights, loading the flasher event
302+* queue, and maintaining two software clocks. Interrupts occur on timer
271303 * overflow (1024 CPU cycles).
272304
273305 * The debounce routine translates the physical inputs to logical
274306 * inputs, maintains a record of the last three logical states sensed in
275307 * DEBO, debounces each input on three identical states, flags changes in
276308 * the debounced input in TOGGLE, and leaves the current debounced input
277-* in ISTATE. STABLE is a local variable with dynamic scope.
278-
279-* Since debouncing occurs on three identical states, the debounce
280-* period is between two and three timer overflows -- 4 to 6 mS with a
281-* 1 MHz crystal, 2 to 3 mS with a 2 MHz crystal.
282-
283-* Debouncing ignores the return switch logic.
309+* in ISTATE. Since debouncing occurs on three identical states, the
310+* debounce period is between two and three timer overflows -- 4 to 6 mS
311+* with a 1 MHz crystal, 2 to 3 mS with a 2 MHz crystal. Debouncing
312+* ignores the return switch logic and related activities.
284313
314+$CYCLE_ADDER_ON
285315 TIMSRV bset TOFR_,TSCR
286316 lda DEBO+1 ; move the debounce chain
287317 sta DEBO+2
@@ -289,67 +319,147 @@ TIMSRV bset TOFR_,TSCR
289319 sta DEBO+1
290320 * read the inputs, converting physical to logical
291321 lda PORTB ; PB2-7 always read 0
292- lsla ; move bits to flag positions
293- lsla
294- lsla
295- lsla
296- sta DEBO ; B read complete
322+ sta DEBO
297323 lda PORTA
298324 and #{BRK_SW | ENG_SW | CAN_BT } ; clears F_EMG
299325 bih TIM0MG ; invert EMG and fold it in
300326 ora #F_EMG
301-TIM0MG ora DEBO
327+TIM0MG lsra ; remap
328+ lsra
329+ ora DEBO
302330 sta DEBO ; current state
303-
304331 * debounce inputs, set flags in TOGGLE
305332 lda DEBO
306333 eor DEBO+1
307- sta TOGGLE ; re-use! (TOGGLE not valid)
334+ sta TOGGLE ; re-use TOGGLE, TOGGLE not valid
308335 lda DEBO+1
309336 eor DEBO+2
310337 ora TOGGLE ; a bit for any input that bounced
311- coma ; bits that did not bounce are set
338+ coma ; bits that bounced are clear
312339 tax
313340 and DEBO+2 ; state of stable bits
314- sta STABLE ; (unstable bits cleared)
341+ sta STABLE ; (unstable bits still clear)
315342 txa
316- and ISTATE ; clear bits that are now unstable
343+ and ISTATE ; look only at bits that are stable
317344 eor STABLE ; flag bits that toggled
318345 sta TOGGLE ; TOGGLE now valid
319346 coma ; mask of non-toggles
320347 and ISTATE ; old state of non-toggles
321348 sta ISTATE ; (toggled bits cleared)
322349 lda TOGGLE ; mask of toggles
323- and DEBO+2 ; new states
350+ and STABLE ; new states of bits that toggled
324351 ora ISTATE
325352 sta ISTATE ; ISTATE now has current debounced inputs
326353
327- SUBHEADER 'Timer Service Code -- timers'
354+ SUBHEADER 'Timer Service Code -- brake lights'
355+ PAGE
356+* Brake lights are the highest priority function, depending only
357+* on the ISTATE F_BRK. The STATES F_BRK is returned as a flag to other
358+* routines.
359+
360+ brclr F_BRK_,ISTATE,TMBRK0
361+ bset F_BRK_,STATES
362+ bclr R_LDRV_,PORTA ; brake lights on
363+ bclr R_RDRV_,PORTA
364+* high center brake light connects directly to brake switch.
365+ bra TMBRKDUN
366+TMBRK0 bclr F_BRK_,STATES
367+ bset R_LDRV_,PORTA ; brake lights off
368+ bset R_RDRV_,PORTA ; (flashers can turn them back on)
369+TMBRKDUN
370+
371+ SUBHEADER 'Timer Service Code -- fill event queue'
372+ PAGE
373+* General debounce complete; now put signal events in queue:
374+* Brake and engine-on are handled in TIMSRV, as synchronous events, and
375+* so are not queued. Turn signal and emergency inputs are positive edge
376+* sensitive, falling edges are ignored.
377+
378+* Queue is post-inc push and pull; QIN == QOUT is empty queue;
379+* queue overflow causes the oldest event to be discarded, but should
380+* never occur.
381+
382+ lda TOGGLE ; F_BRK & F_ENG are not queued!
383+ and #{$FF ^ F_BRK ^ F_ENG} ; KICS assembler has no bit not?
384+ and ISTATE ; queue only TOGGLE on
385+ sta TOGGLQ
386+ beq TMCLOCK ; save time
387+ ldx QIN
388+ lda #$10 ; start with bit 3!
389+* cycles to this point, plus interrupt response (19 cycles)
390+
391+$CYCLE_ADDER_OFF
392+$CYCLE_ADDER_ON
393+TMQSCAN lsra ; scan TOGGLE
394+ beq TMQDUN
395+ bit TOGGLQ
396+ beq TMQSCAN
397+* 12 cycles minimum time in loop
398+$CYCLE_ADDER_OFF
399+$CYCLE_ADDER_ON
400+ sta ,x
401+ incx
402+ cpx #EVENTQ+MAXEVENTS
403+ blo TMQNWRP
404+ ldx #EVENTQ ; 2 cycles
405+TMQNWRP cpx QOUT
406+ bne TMQSCAN
407+ inc QOUT ; 5 cycles
408+TMQNBMP bra TMQSCAN ; 3 cycles
409+* 40 cycles maximum time in loop, (40 - 2 - 5 - 3) == 30 typical max;
410+* Minimum queue time is 12 * 3 + 30 == 66 (no wrap, no bump);
411+* max is 30 * 3 + 40 == 130 (one wrap, one bump max)
412+$CYCLE_ADDER_OFF
413+$CYCLE_ADDER_ON
414+TMQDUN stx QIN
415+
416+ SUBHEADER 'Timer Service Code -- engine time out and flasher timers'
328417 PAGE
329418 * Although the Real Time Interrupt is masked, the software clocks
330419 * use the RTI flag. Selecting the fastest RTI rate gives the software
331420 * clocks a resolution of eight timer overflows (8192 CPU cycles).
332421
333-* The engine timeout counter is not allowed to underflow
334-
335-* time to clock?
422+TMCLOCK
336423 brclr RTIF_,TSCR,TIMDUN
337424 bset RTIFR_,TSCR
338-* engine time out counter:
339- brset F_ENG_,ISTATE,TIMFLH ; avoid wasting time here
425+
426+* The engine time-out counter resets if the engine toggles on. It
427+* runs only when the ISTATE F_ENG bit is low and the emergency flashers
428+* (STATES F_EMG) are off. It does not underfow. The timer flags
429+* timeout in STATES F_ENG.
430+
431+ brclr F_ENG_,TOGGLE,TMENG0
432+ lda #{TIMOUT & $FF } ; reset the clock
433+ sta ENG_TIM+1
434+ lda #{TIMOUT / $100 + 1} ; borrow on 0, not -1
435+ sta ENG_TIM
436+ bra TMFLASH
437+
438+TMENG0
439+ brset F_ENG_,ISTATE,TMFLASH
440+ brset F_EMG_,STATES,TMFLASH
441+ brclr F_ENG_,STATES,TMFLASH ; do not underflow!
340442 dec ENG_TIM+1
341443 bne TIMFLH ; initial count is adjusted to make this work
342444 dec ENG_TIM
343445 bne TIMFLH
344- clr ENG_TIM+1 ; no underflow
345- clr ENG_TIM
346- bset F_ENG_,STATES ; signal timed out
347-TIMFLH
348- inc SOFTIM+1
446+ bclr F_ENG_,STATES ; signal timed out
447+ bset F_ENG_,TOGGLE ; communicate with MAINLOOP
448+
449+* flasher counter
450+TMFLASH lda #{F_EMG | F_LFT | F_RGT}
451+ and STATES ; flasher active?
452+ beq TIMDUN
453+ dec FLASH
349454 bne TIMDUN
350- inc SOFTIM
351-TIMDUN rti ; careful with the interrupt service time!
455+ lda FLTIME
456+ sta FLASH
352457
458+TIMDUN rti
459+$CYCLE_ADDER_OFF
460+* Keep the maximum clock cycles in TIMSRV below half of TOFR period.
461+* It is probably physically impossible to operate the switches fast
462+* enough to overflow the queue that way.
353463
354464 SUBHEADER 'Initializations'
355465 PAGE
@@ -357,9 +467,10 @@ TIMDUN rti ; careful with the interrupt service time!
357467 * if SWI occurs, the machine is not in a defined state, and must reset
358468 IRQSRV
359469 SWISRV rsp ; now falls through to RSTSRV
470+ clra
471+ sta COPR
360472 * general inits
361-RSTSRV clr COPR ; just in case
362- lda #{F_LDRV | F_RDRV | R_LDRV | R_RDRV}
473+RSTSRV lda #{F_LDRV | F_RDRV | R_LDRV | R_RDRV}
363474 sta PORTA ; initial output values
364475 lda #{F_LDRV | F_RDRV | R_LDRV | R_RDRV | DRVDRV}
365476 sta DDRA ; set up directions
@@ -373,67 +484,166 @@ RSTSRV clr COPR ; just in case
373484 * disable external interrupts
374485 bclr IRQE_,ISCR
375486 bset IRQR_,ISCR ; clear the flag
376-* clear RAM
377- ldx #RAMBEG
378- lda #RAMSIZ
379-RSTCLR clr ,x ; this is probably a waste?
380- incx
381- deca
382- bne RSTCLR
383487 * set up hardware timer
384- clr COPR ; the manual suggests doing this before timer rate
385- lda #TOIE ; only timer overflow interrupts
386- sta TSCR ; and the fastest Real Time rate
488+ clra
489+ sta COPR ; b0 clear, about to change timer rate
490+ lda #{TOIE | RTIPOW} ; only timer overflow interrupts
491+ sta TSCR
387492 ora #{TOFR|RTIFR} ; clear the flags
388493 sta TSCR
389494 * set up specific variables
495+ clr DEBO ; start debounce chain clear
496+ clr DEBO+1 ; DEBO+2 is thrown out on first timer interrupt
390497 lda #{F_ENG}
391- sta ISTATE ; we know the engine is on!
498+ sta ISTATE ; force TIMOUT to be set
392499 sta TOGGLE
393- sta STATES
500+ sta STATES ; we think the engine is on
501+ ldx #EVENTQ ; empty QUEUE
502+ stx QIN
503+ stx QOUT
394504
395-MAINLOOP
396-* Assume interrupts enabled, except for brief critical sections
397-* Falls through to input filter functions
505+* Falls through to MAINLOOP
398506
399- SUBHEADER 'Main function: input filter state machines'
507+ SUBHEADER 'STOP and dequeue'
400508 PAGE
401509
402-* Engine on filter resets the toggle bit and sets the timer if
403-* toggled off. STATES bit is handled by TIMSRV.
510+MAINLOOP
511+ cli ; leave interrupts enabled as much as possible
512+ clra
513+ sta COPR ; tell COP we're in control
514+* check for STOP, dequeue flasher events, wait if necessary
515+ sei
516+ brclr F_ENG_,STATES,MNSTOP
517+ ldx QOUT
518+ cpx QIN ; QUEUE empty?
519+ bne MNDEQUEUE
520+ lda STATES ; can we save power for a bit?
521+ and #{F_LFT | F_RGT | F_BRK | F_EMG}
522+ bne MNDRVWT
523+ bclr DRVDRV_,PORTA
524+MNDRVWT wait ; enable interrupts, wait for timer
525+ tst TOGGLE
526+ beq MNDRVWT ; nothing changed, nothing to respond to
527+* with no activity, COP periodically resets the MCU system
528+* this is not generally good engineering practice.
529+ bset DRVDRV_,PORTA ; IRQSRV might have driven the brake lights
530+ bra MAINLOOP ; check STOP and QUEUE again
531+
532+* go to power conserving state
533+MNSTOP lda #{F_LDRV | F_RDRV | R_LDRV | R_RDRV}
534+ sta PORTA ; shut everything down, organized!
535+ lda #{F_LDRV | F_RDRV | R_LDRV | R_RDRV | DRVDRV}
536+ sta DDRA ; set up directions
537+ sta PDRA ; pull downs only on inputs
538+ clr PORTB ; initial outputs (do port B just in case)
539+ clr DDRB ; B initially input
540+ clr PDRB ; with pull downs set
541+* make sure EPROM programming stuff is out of the way
542+ clr EPROG
543+ clr PESCR
544+* enable external interrupts
545+ bset IRQE_,ISCR ; DO NOT clear the flag (IRQ won't return)
546+ stop ; also shuts timer down
547+ jmp SWISRV ; should never come here (resets stack pointer)
404548
405-TIMOUT EQU 18311/XTAL ; 5 minutes (if XTAL equ is correct)
549+MNDEQUEUE
550+ lda ,x
551+ incx
552+ cpx #EVENTQ+MAXEVENTS
553+ blo MNQNWRP
554+ ldx #EVENTQ
555+MNQNWRP stx QOUT
556+ cmp #F_EMG
557+ bne MNCAN
558+ eor STATES ; toggle STATES F_EMG emergency flashers bit
559+ sta STATES
560+ bra MNDOSTATES
561+
562+MNQCAN cmp #F_CAN
563+ bne MNQLFT
564+ lda DDRB
565+ eor #3
566+
567+ clr DDRB
568+ bsr CANDEBO
569+ cmp #6
570+ blo MNQCAND
571+ bset F_CAN_,STATES
572+ bra MNDOSTATES
573+MNQCAND lda STATES
574+ and #{F_LFT | F_RGT}
575+ eor #{F_LFT | F_RGT} ; other port
576+ sta DDRB
577+ bsr CANDEBO
578+
579+
580+MNQLFT cmp #F_LFT
581+ bne MNQRGT
582+ bset F_LFT_,STATES
583+ bclr F_RGT_,STATES
584+ bra MNDOSTATES
585+
586+MNQRGT cmp #F_RGT
587+ bne MNQDEF
588+ bset F_RGT_,STATES
589+ bclr F_LFT_,STATES
590+ bra MNDOSTATES
591+
592+MNQDEF jmp SWISRV ; nothing else should be queued
593+
594+* subroutine to quickly "debounce" the cancel input
595+* reads CAN_BT eight times, summing the bits into A
596+* trashes X
597+$CYCLE_ADDER_ON
598+CANDEBO ldx #8
599+ clra
600+ brclr CAN_BT_,PORTA,CANDEB1 ; get CAN_BT into carry
601+CANDEB1 adc #0
602+ decx
603+ bne CANDEBO
604+$CYCLE_ADDER_OFF
605+* about 1/4 mS at 1 MHz, sufficient to believe the input bit
606+ rts
607+
608+
609+* then make the output mirror the state
610+
611+
612+DOSTATE
613+ brset F_BRK_,STATES,MAINLOOP ; if brakes set, do nothing else
614+ brset F_EMG_,STATES,DOEMERG ; if emergency flash, skip engine
615+ brset F_ENG_,STATES,DOTURN ; no turn signals if engine off
616+* engine off and timed out, no brakes, no emergency flashers
617+ lda
406618
407-INFENG cli ; allow interrupts
408- sei ; critical: not seamless access
409- brclr F_ENG_,TOGGLE,INFEMG
410- bclr F_ENG_,TOGGLE
411- brset F_ENG_,ISTATE,INFEMG ; engine on input toggled off
412- lda #{TIMOUT & $FF}
413- sta ENG_TIM+1
414- lda #{TIMOUT / 256 + 1} ; counter borrows on 0, not -1
415- sta ENG_TIM
416-* fall through
417619
418620 * Emergency flasher filter simply toggles F_EMG bit of STATES
419-* when emergency flasher button is pressed.
621+* when emergency flasher button is pressed. Release is ignored.
420622
421623 INFEMG cli ; allow interrupts
422624 sei ; critical: not seamless access
423625 brclr F_EMG_,TOGGLE,INFTRN
424626 bclr F_EMG_,TOGGLE
425627 brclr F_EMG_,ISTATE,INFTRN ; no action when button released
426- lda #F_EMG
427- eor STATES
628+ lda STATES
629+ eor #F_EMG
428630 sta STATES
429631 * fall through
430632
431633 *
634+
432635 INFTRN cli ; allow interrupts
433636 sei ; critical: not seamless access
434-
435-
436-* stuff in state machines:
637+ lda STATES
638+ and ISTATE
639+ and #{F_LFT | F_RGT} ; mask
640+ eor #{F_LFT | F_RGT} ; ignore if already on
641+ and TOGGLE
642+ beq FNENG
643+ tax
644+ and ISTATE ; too late at night, all my work this aft is gone
645+* check here for turning
646+FNENG
437647
438648 * support on and off states on signal timer.
439649
@@ -481,12 +691,8 @@ INFTRN cli ; allow interrupts
481691 * EMG_NO (F_EMG==1 && EMG_FL==0)---> EMG_FL
482692 *
483693
484- wait
485- clr COPR
486- tst TOGGLE
487- beq FUNSTATE
488694
489- bra WAITLOOP
695+ bra MAINLOOP
490696
491697
492698 org VECTORS