およそ20年前に、68HC05 の開発の練習に書いた車のブレイクライト・方向指示器コントローラです。
リビジョン | abb5d611bd9536cb076b1904b9f947c954725189 (tree) |
---|---|
日時 | 2013-07-08 21:19:51 |
作者 | Joel Matthew Rees <reiisi@user...> |
コミッター | Joel Matthew Rees |
Improvements in the debounce and operational analysis.
(The previous commit added break light and related functionality.)
@@ -71,16 +71,14 @@ | ||
71 | 71 | * feedback and dash panel indicators should be sufficient user feedback. |
72 | 72 | |
73 | 73 | * The turn signal return mechanism is a pair of reed relays |
74 | -* mounted inside the bottom of the steering column cowling about ten | |
75 | -* degrees apart, with three magnetic actuators mounted to the steering | |
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 | |
74 | +* 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 | |
84 | 82 | * impression that magnetic devices are more immune to extremes of |
85 | 83 | * climate. |
86 | 84 |
@@ -173,35 +171,60 @@ | ||
173 | 171 | * not naturally biased, so the the emergency flasher seemed a more |
174 | 172 | * natural match for IRQ. |
175 | 173 | |
176 | -* The right turn signal return switch is positioned about five | |
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, | |
174 | +* The following crude diagram illustrates the actuation in a left | |
175 | +* rotation (restoring from a right turn or turning left). The carots | |
176 | +* indicate the position of the reed switches, the asterisks indicate the | |
177 | +* actuation field of a magnet. | |
178 | + | |
179 | +* Actuation Field ******** | |
180 | +* Left Return Switch ^ ^ Right Return Switch | |
181 | +* ******** | |
182 | +* ^ ^ | |
183 | +* ******** | |
184 | +* ^ ^ | |
185 | +* ******** | |
186 | +* ^ ^ | |
187 | +* ******** | |
188 | +* ^ ^ | |
189 | +* ******** | |
190 | +* ^ ^ | |
191 | +* ******** | |
192 | +* ^ ^ | |
193 | + | |
194 | +* Referring to the above diagram, the right turn signal return | |
195 | +* switch is positioned about 5 5/8 degrees right of bottom center below | |
196 | +* the steering column and fixed to the steering column housing, and the | |
197 | +* left return is positioned the same distance to the left. In this way, | |
198 | +* when the steering wheel rotates, the return switch for the direction | |
199 | +* of rotation actuates first, then the opposite direction switch closes, | |
181 | 200 | * then the same direction switch opens, and then the opposite direction |
182 | 201 | * 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. | |
187 | - | |
188 | -* When both turn signals are off, both turn signal ports are set | |
189 | -* as inputs. When a turn signal switch input senses a closure, that | |
190 | -* port is made an output and driven high. When the cancel input senses | |
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. | |
202 | +* the direction of the turn closes after the other switch. In other | |
203 | +* words, if you turn right, the steering wheel will rotate to the left | |
204 | +* when you return to straight, and the switches actuate from left to | |
205 | +* right during the restore. (I say this so many times because it takes | |
206 | +* repeating to convince myself of it.) | |
207 | + | |
208 | +* When both turn signals are off, both turn signal switch ports | |
209 | +* are set as inputs. When a turn signal switch input senses a closure, | |
210 | +* its port is made an output and driven high. Now, in addition to | |
211 | +* manual cancel, the cancel port can sense steering wheel rotation. In | |
212 | +* 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 | + | |
216 | +* Since the opposite direction turn signal switch port remains an | |
217 | +* input, it can still be sensed. The operator can change turn signals | |
218 | +* directly, without hitting the cancel button. | |
219 | + | |
220 | +* The separation of the switches and the actuation arc length I | |
221 | +* specify are based on my assumption that the steering wheel will rotate | |
222 | +* at a maximum speed of three revolutions per second, and that the four | |
223 | +* to six mS required debounce period requires a minimum 10 milli-second | |
224 | +* separate actuation period. The actual result was 10.9 degrees | |
225 | +* 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. | |
205 | 228 | |
206 | 229 | * A peculiar characteristic of this design is the apparent lack of |
207 | 230 | * use for the RESET input. Since power-on reset is built in to the |
@@ -243,6 +266,7 @@ RGT_BT_ equ B0_ | ||
243 | 266 | |
244 | 267 | * logical input definitions for debounce and states |
245 | 268 | * bits are remapped for debounce and queue speed |
269 | +* six bits of physical input, high two bits used for cancel logic | |
246 | 270 | F_LFT equ LFT_BT |
247 | 271 | F_LFT_ equ LFT_BT_ |
248 | 272 | F_RGT equ RGT_BT |
@@ -255,6 +279,8 @@ F_EMG equ {DRVDRV < 2} ; fold onto output bit | ||
255 | 279 | F_EMG_ equ {DRVDRV_ + 2} |
256 | 280 | F_CAN equ {CAN_BT < 2} |
257 | 281 | F_CAN_ equ {CAN_BT_ + 2} |
282 | +F_OPC equ $40 ; opposite direction cancel record | |
283 | +F_MNC equ $80 ; manual cancel record | |
258 | 284 | |
259 | 285 | * Event queue constants |
260 | 286 | * We only have 6 bit events and only record 4 in the queue. |
@@ -290,6 +316,8 @@ STATES rmb 1 ; current controller states | ||
290 | 316 | ENG_TIM rmb 2 ; engine time out timer |
291 | 317 | FLASH rmb 1 ; flash timer |
292 | 318 | FLTIME rmb 1 ; flash flash time to load |
319 | +CANCEL rmb 1 ; debounce for cancel button | |
320 | +RETURN rmb 1 ; debounce for return logic | |
293 | 321 | |
294 | 322 | |
295 | 323 | * ROM definitions follow: |
@@ -297,6 +325,7 @@ FLTIME rmb 1 ; flash flash time to load | ||
297 | 325 | |
298 | 326 | SUBHEADER 'Timer Service Code -- debounce' |
299 | 327 | PAGE |
328 | + | |
300 | 329 | * The timer service routine has five functions: debouncing the |
301 | 330 | * inputs, directly setting the brake lights, loading the flasher event |
302 | 331 | * queue, and maintaining two software clocks. Interrupts occur on timer |
@@ -308,8 +337,15 @@ FLTIME rmb 1 ; flash flash time to load | ||
308 | 337 | * the debounced input in TOGGLE, and leaves the current debounced input |
309 | 338 | * in ISTATE. Since debouncing occurs on three identical states, the |
310 | 339 | * 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. | |
340 | +* with a 1 MHz crystal, 2 to 3 mS with a 2 MHz crystal. | |
341 | + | |
342 | +* This debounce technique works because we don't care what is | |
343 | +* happening to the inputs between timer overflows, and because there is | |
344 | +* no mechanism for noise coincident and rythmic with timer overflow. | |
345 | + | |
346 | +* The cancel TOGGLE bit is suppresed on same-direction rotation. | |
347 | +* Trailing edge TOGGLEs are filtered out for all but brake and engine-on. | |
348 | +* Cancel direction and manual cancel TOGGLEs are always filtered out. | |
313 | 349 | |
314 | 350 | $CYCLE_ADDER_ON |
315 | 351 | TIMSRV bset TOFR_,TSCR |
@@ -317,19 +353,45 @@ TIMSRV bset TOFR_,TSCR | ||
317 | 353 | sta DEBO+2 |
318 | 354 | lda DEBO |
319 | 355 | sta DEBO+1 |
356 | + | |
320 | 357 | * read the inputs, converting physical to logical |
321 | - lda PORTB ; PB2-7 always read 0 | |
322 | - sta DEBO | |
323 | 358 | lda PORTA |
324 | 359 | and #{BRK_SW | ENG_SW | CAN_BT } ; clears F_EMG |
325 | - bih TIM0MG ; invert EMG and fold it in | |
360 | + bih TMMEMG ; invert EMG and fold it in | |
326 | 361 | ora #F_EMG |
327 | -TIM0MG lsra ; remap | |
362 | +TMMEMG lsra ; remap | |
328 | 363 | lsra |
364 | + sta DEBO | |
365 | + lda PORTB ; PB2-7 always read 0 | |
329 | 366 | ora DEBO |
330 | - sta DEBO ; current state | |
367 | + sta DEBO | |
368 | + | |
369 | +* check for turn signal return and cancel | |
370 | + bit #F_CAN ; nothing at all without cancel | |
371 | + beq TMSTGL | |
372 | + lda DDRB ; meaningless when no turn signal | |
373 | + beq TMSTGL | |
374 | +$CYCLE_ADDER_OFF | |
375 | +$CYCLE_ADDER_ON | |
376 | + tax | |
377 | + eor #{LFT_BT | RGT_BT} ; strobe other side | |
378 | + sta PORTB ; set output state first | |
379 | + sta DDRB ; handy output state, huh? | |
380 | + brset F_CAN_,PORTA,TM0000 ; F_CAN into carry | |
381 | +TM0000 rora | |
382 | + clr DDRB ; no strobe: manual cancel? | |
383 | + brset F_CAN_,PORTA,TM0001 ; F_CAN into carry again | |
384 | +TM0001 rora | |
385 | + and #{F_OPC | F_MNC} | |
386 | + ora DEBO | |
387 | + sta DEBO | |
388 | + stx PORTB ; restore turn signal inputs | |
389 | + stx DDRB | |
390 | +$CYCLE_ADDER_OFF | |
391 | +$CYCLE_ADDER_ON | |
392 | + | |
331 | 393 | * debounce inputs, set flags in TOGGLE |
332 | - lda DEBO | |
394 | +TMSTGL lda DEBO | |
333 | 395 | eor DEBO+1 |
334 | 396 | sta TOGGLE ; re-use TOGGLE, TOGGLE not valid |
335 | 397 | lda DEBO+1 |
@@ -342,7 +404,7 @@ TIM0MG lsra ; remap | ||
342 | 404 | txa |
343 | 405 | and ISTATE ; look only at bits that are stable |
344 | 406 | eor STABLE ; flag bits that toggled |
345 | - sta TOGGLE ; TOGGLE now valid | |
407 | + sta TOGGLE ; TOGGLE valid, but not filtered | |
346 | 408 | coma ; mask of non-toggles |
347 | 409 | and ISTATE ; old state of non-toggles |
348 | 410 | sta ISTATE ; (toggled bits cleared) |
@@ -351,8 +413,21 @@ TIM0MG lsra ; remap | ||
351 | 413 | ora ISTATE |
352 | 414 | sta ISTATE ; ISTATE now has current debounced inputs |
353 | 415 | |
416 | +* filter TOGGLE F_CAN if same direction | |
417 | + bit #{F_OPC | F_MNC} ; opposite direction or manual? | |
418 | + bne TMFFAL | |
419 | + bclr F_CAN_,TOGGLE ; same direction | |
420 | + | |
421 | +* filter falling edge of F_LFT, F_RGT, F_EMG, F_CAN in TOGGLE | |
422 | +* assumes ISTATE still in A | |
423 | +TMFFAL ora #{F_ENG | F_BRK} ; not filtered | |
424 | + and TOGGLE ; filter any other fall(en) edge | |
425 | + and #{$FF ^ F_OPC ^ F_MNC} ; these should never TOGGLE | |
426 | + sta TOGGLE | |
427 | + | |
354 | 428 | SUBHEADER 'Timer Service Code -- brake lights' |
355 | 429 | PAGE |
430 | + | |
356 | 431 | * Brake lights are the highest priority function, depending only |
357 | 432 | * on the ISTATE F_BRK. The STATES F_BRK is returned as a flag to other |
358 | 433 | * routines. |
@@ -370,6 +445,7 @@ TMBRKDUN | ||
370 | 445 | |
371 | 446 | SUBHEADER 'Timer Service Code -- fill event queue' |
372 | 447 | PAGE |
448 | + | |
373 | 449 | * General debounce complete; now put signal events in queue: |
374 | 450 | * Brake and engine-on are handled in TIMSRV, as synchronous events, and |
375 | 451 | * so are not queued. Turn signal and emergency inputs are positive edge |
@@ -381,7 +457,6 @@ TMBRKDUN | ||
381 | 457 | |
382 | 458 | lda TOGGLE ; F_BRK & F_ENG are not queued! |
383 | 459 | and #{$FF ^ F_BRK ^ F_ENG} ; KICS assembler has no bit not? |
384 | - and ISTATE ; queue only TOGGLE on | |
385 | 460 | sta TOGGLQ |
386 | 461 | beq TMCLOCK ; save time |
387 | 462 | ldx QIN |
@@ -504,7 +579,7 @@ RSTSRV lda #{F_LDRV | F_RDRV | R_LDRV | R_RDRV} | ||
504 | 579 | |
505 | 580 | * Falls through to MAINLOOP |
506 | 581 | |
507 | - SUBHEADER 'STOP and dequeue' | |
582 | + SUBHEADER 'Dequeue Events and Modify STATES, also STOP' | |
508 | 583 | PAGE |
509 | 584 | |
510 | 585 | MAINLOOP |
@@ -561,20 +636,22 @@ MNQNWRP stx QOUT | ||
561 | 636 | |
562 | 637 | MNQCAN cmp #F_CAN |
563 | 638 | 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 | |
639 | + ldx #7 | |
640 | + | |
641 | + lda STATES | |
574 | 642 | and #{F_LFT | F_RGT} |
575 | - eor #{F_LFT | F_RGT} ; other port | |
576 | - sta DDRB | |
577 | - bsr CANDEBO | |
643 | + beq MNDOSTATES | |
644 | + eor #{F_LFT | F_RGT} | |
645 | + sta TMPTURN | |
646 | + sta PORTB | |
647 | +MNQCANL sta DDRB | |
648 | + brclr CAN_BT_,PORTA,MNQCANM ; opposite direction? | |
649 | + incx | |
650 | +MNQCANM clr DDRB ; all outputs pulled down | |
651 | + brclr CAN_BT_,PORTA,MDQCANT ; manual cancel? | |
652 | + incx | |
653 | + dec something | |
654 | + bne MNQCANL | |
578 | 655 | |
579 | 656 | |
580 | 657 | MNQLFT cmp #F_LFT |
@@ -591,21 +668,6 @@ MNQRGT cmp #F_RGT | ||
591 | 668 | |
592 | 669 | MNQDEF jmp SWISRV ; nothing else should be queued |
593 | 670 | |
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 | 671 | * then make the output mirror the state |
610 | 672 | |
611 | 673 |