およそ20年前に、68HC05 の開発の練習に書いた車のブレイクライト・方向指示器コントローラです。
リビジョン | 770232dd4179d7fecd156d30e95eb3bab098b7ac (tree) |
---|---|
日時 | 2013-07-08 21:35:39 |
作者 | Joel Matthew Rees <reiisi@user...> |
コミッター | Joel Matthew Rees |
Shift from asynchronous queued debounce to synchronous debounce, no queue.
@@ -15,7 +15,7 @@ | ||
15 | 15 | * of |
16 | 16 | * South Salt Lake City |
17 | 17 | * Utah |
18 | -* | |
18 | +* | |
19 | 19 | |
20 | 20 | |
21 | 21 |
@@ -107,7 +107,7 @@ | ||
107 | 107 | * | | |
108 | 108 | * +---5V_ZENER---GND +---CENTER_BRK_LGHT---GND |
109 | 109 | |
110 | -* PA2<---+---160K_OHM---ENG_ON_SW---12V | |
110 | +* PA2<---+---160K_OHM---ENGINE_ON_SW---12V | |
111 | 111 | * | |
112 | 112 | * +---5V_ZENER---GND |
113 | 113 |
@@ -231,6 +231,13 @@ | ||
231 | 231 | * K-series MCUs, RESET should probably be tied high. However, I suppose |
232 | 232 | * it could make a good manual cancel-all input, if such is necessary. |
233 | 233 | |
234 | +* This assembler appears not to have a bit not function for | |
235 | +* operand expressions. So, I have in several places resorted to the | |
236 | +* rather obtuse expedient of exclusive-orring bits to be reset with $FF, | |
237 | +* ergo, AND #{$FF ^ F_OPC ^ F_MNC} | |
238 | +* instead of AND #~(F_OPC | F_MNC) | |
239 | +* which I think is clearer. | |
240 | + | |
234 | 241 | SUBHEADER 'Obligatory Mnemonics' |
235 | 242 | PAGE |
236 | 243 | $base $0A |
@@ -250,8 +257,8 @@ R_RDRV equ B4 | ||
250 | 257 | R_RDRV_ equ B4_ |
251 | 258 | BRK_SW equ B3 |
252 | 259 | BRK_SW_ equ B3_ |
253 | -ENG_SW equ B2 | |
254 | -ENG_SW_ equ B2_ | |
260 | +NGN_SW equ B2 ; engine (ENG and EMG could be confusing) | |
261 | +NGN_SW_ equ B2_ | |
255 | 262 | DRVDRV equ B1 |
256 | 263 | DRVDRV_ equ B1_ |
257 | 264 | CAN_BT equ B0 |
@@ -265,7 +272,7 @@ RGT_BT_ equ B0_ | ||
265 | 272 | |
266 | 273 | |
267 | 274 | * logical input definitions for debounce and states |
268 | -* bits are remapped for debounce and queue speed | |
275 | +* bits are remapped for debounce and speed | |
269 | 276 | * six bits of physical input, high two bits used for cancel logic |
270 | 277 | F_LFT equ LFT_BT |
271 | 278 | F_LFT_ equ LFT_BT_ |
@@ -273,8 +280,8 @@ F_RGT equ RGT_BT | ||
273 | 280 | F_RGT_ equ RGT_BT_ |
274 | 281 | F_BRK equ {BRK_SW < 2} ; physical output bit |
275 | 282 | F_BRK_ equ {BRK_SW_ + 2} |
276 | -F_ENG equ {ENG_SW < 2} ; physical output bit | |
277 | -F_ENG_ equ {ENG_SW_ + 2} | |
283 | +F_NGN equ {NGN_SW < 2} ; physical output bit | |
284 | +F_NGN_ equ {NGN_SW_ + 2} | |
278 | 285 | F_EMG equ {DRVDRV < 2} ; fold onto output bit |
279 | 286 | F_EMG_ equ {DRVDRV_ + 2} |
280 | 287 | F_CAN equ {CAN_BT < 2} |
@@ -282,12 +289,6 @@ F_CAN_ equ {CAN_BT_ + 2} | ||
282 | 289 | F_OPC equ $40 ; opposite direction cancel record |
283 | 290 | F_MNC equ $80 ; manual cancel record |
284 | 291 | |
285 | -* Event queue constants | |
286 | -* We only have 6 bit events and only record 4 in the queue. | |
287 | -* Event scan algorithm wired to highest event bit in bit 3. | |
288 | - | |
289 | -MAXEVENTS equ 6 ; more than max bit changes in "time slice" | |
290 | - | |
291 | 292 | SUBHEADER 'Resource Definitions' |
292 | 293 | PAGE |
293 | 294 |
@@ -306,30 +307,24 @@ FLASH1 equ {32*XTAL/RTIRATE/2} ; about 1/2 second | ||
306 | 307 | org RAMBEG |
307 | 308 | DEBO rmb 3 ; the debounce record chain |
308 | 309 | STABLE rmb 1 ; temporary record of stable bits |
309 | -TOGGLQ equ STABLE ; temporary record of queue events | |
310 | 310 | TOGGLE rmb 1 ; record of toggles |
311 | 311 | ISTATE rmb 1 ; record of the current input state |
312 | -QIN rmb 1 ; queue input point | |
313 | -QOUT rmb 1 ; queue output point | |
314 | -EVENTQ rmb MAXEVENTS ; no need to initialize this | |
315 | 312 | STATES rmb 1 ; current controller states |
316 | -ENG_TIM rmb 2 ; engine time out timer | |
313 | +NGN_TIM rmb 2 ; engine time out timer | |
317 | 314 | FLASH rmb 1 ; flash timer |
318 | 315 | FLTIME rmb 1 ; flash flash time to load |
319 | -CANCEL rmb 1 ; debounce for cancel button | |
320 | -RETURN rmb 1 ; debounce for return logic | |
321 | 316 | |
322 | 317 | |
323 | 318 | * ROM definitions follow: |
324 | 319 | org ROMBEG |
325 | 320 | |
326 | - SUBHEADER 'Timer Service Code -- debounce' | |
321 | + SUBHEADER 'Timer Service Code' | |
327 | 322 | PAGE |
328 | 323 | |
329 | -* The timer service routine has five functions: debouncing the | |
330 | -* inputs, directly setting the brake lights, loading the flasher event | |
331 | -* queue, and maintaining two software clocks. Interrupts occur on timer | |
332 | -* overflow (1024 CPU cycles). | |
324 | +* 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). | |
333 | 328 | |
334 | 329 | * The debounce routine translates the physical inputs to logical |
335 | 330 | * inputs, maintains a record of the last three logical states sensed in |
@@ -343,20 +338,36 @@ RETURN rmb 1 ; debounce for return logic | ||
343 | 338 | * happening to the inputs between timer overflows, and because there is |
344 | 339 | * no mechanism for noise coincident and rythmic with timer overflow. |
345 | 340 | |
346 | -* The cancel TOGGLE bit is suppresed on same-direction rotation. | |
341 | +* The cancel TOGGLE bit is suppressed on same-direction rotation. | |
347 | 342 | * Trailing edge TOGGLEs are filtered out for all but brake and engine-on. |
348 | -* Cancel direction and manual cancel TOGGLEs are always filtered out. | |
343 | +* Opposite direction cancel (F_OPC) and manual cancel (F_MNC) ISTATE | |
344 | +* auxiliary flags are maintained to provide information on the source of | |
345 | +* the F_CAN bit, and are always filtered out of TOGGLE. | |
346 | + | |
347 | +* After adding an event queue and checking the timing results, two | |
348 | +* things became clear: there is plenty of time to handle all the changes | |
349 | +* to STATES without a queue, and TOGGLE makes a sort of horizontal queue | |
350 | +* anyway. In other words, there is no reason to make the adjustments to | |
351 | +* STATES asynchronous when there is plenty of headroom for synchronous | |
352 | +* adjustments. Moreover, the adjustments take less time than organizing | |
353 | +* the button events in a queue. (Darn! I was kind of proud of that six | |
354 | +* byte queue, and the shift technique for storing events into it.) | |
355 | + | |
356 | + SUBHEADER 'Timer Service Code -- Debounce and Toggle Filter' | |
357 | + PAGE | |
349 | 358 | |
350 | 359 | $CYCLE_ADDER_ON |
351 | 360 | TIMSRV bset TOFR_,TSCR |
352 | - lda DEBO+1 ; move the debounce chain | |
361 | + | |
362 | +* move the debounce chain | |
363 | + lda DEBO+1 | |
353 | 364 | sta DEBO+2 |
354 | 365 | lda DEBO |
355 | 366 | sta DEBO+1 |
356 | 367 | |
357 | -* read the inputs, converting physical to logical | |
368 | +* read the static inputs, converting physical to logical | |
358 | 369 | lda PORTA |
359 | - and #{BRK_SW | ENG_SW | CAN_BT } ; clears F_EMG | |
370 | + and #{BRK_SW | NGN_SW | CAN_BT} ; clears DRV_DRV | |
360 | 371 | bih TMMEMG ; invert EMG and fold it in |
361 | 372 | ora #F_EMG |
362 | 373 | TMMEMG lsra ; remap |
@@ -366,14 +377,15 @@ TMMEMG lsra ; remap | ||
366 | 377 | ora DEBO |
367 | 378 | sta DEBO |
368 | 379 | |
369 | -* check for turn signal return and cancel | |
380 | +* read the turn signal return and manual cancel auxiliary flags | |
381 | +* (F_CAN & turn_sig_on) <=> read auxiliary flags | |
370 | 382 | bit #F_CAN ; nothing at all without cancel |
371 | 383 | beq TMSTGL |
372 | - lda DDRB ; meaningless when no turn signal | |
384 | + ldx DDRB ; meaningless if not waiting for cancel | |
373 | 385 | beq TMSTGL |
374 | 386 | $CYCLE_ADDER_OFF |
375 | 387 | $CYCLE_ADDER_ON |
376 | - tax | |
388 | + txa | |
377 | 389 | eor #{LFT_BT | RGT_BT} ; strobe other side |
378 | 390 | sta PORTB ; set output state first |
379 | 391 | sta DDRB ; handy output state, huh? |
@@ -390,9 +402,10 @@ TM0001 rora | ||
390 | 402 | $CYCLE_ADDER_OFF |
391 | 403 | $CYCLE_ADDER_ON |
392 | 404 | |
393 | -* debounce inputs, set flags in TOGGLE | |
394 | -TMSTGL lda DEBO | |
395 | - eor DEBO+1 | |
405 | +* debounce inputs, set flags in TOGGLE and ISTATE | |
406 | +* STABLE = ~((DEBO[0] ^ DEBO[1]) | (DEBO[1] ^ DEBO[2])) | |
407 | +* | |
408 | +TMSTGL eor DEBO+1 | |
396 | 409 | sta TOGGLE ; re-use TOGGLE, TOGGLE not valid |
397 | 410 | lda DEBO+1 |
398 | 411 | eor DEBO+2 |
@@ -404,7 +417,7 @@ TMSTGL lda DEBO | ||
404 | 417 | txa |
405 | 418 | and ISTATE ; look only at bits that are stable |
406 | 419 | eor STABLE ; flag bits that toggled |
407 | - sta TOGGLE ; TOGGLE valid, but not filtered | |
420 | + sta TOGGLE ; true TOGGLEs, but not yet filtered | |
408 | 421 | coma ; mask of non-toggles |
409 | 422 | and ISTATE ; old state of non-toggles |
410 | 423 | sta ISTATE ; (toggled bits cleared) |
@@ -413,113 +426,80 @@ TMSTGL lda DEBO | ||
413 | 426 | ora ISTATE |
414 | 427 | sta ISTATE ; ISTATE now has current debounced inputs |
415 | 428 | |
416 | -* filter TOGGLE F_CAN if same direction | |
429 | +* filter out TOGGLE F_CAN if same direction | |
417 | 430 | bit #{F_OPC | F_MNC} ; opposite direction or manual? |
418 | 431 | bne TMFFAL |
419 | 432 | bclr F_CAN_,TOGGLE ; same direction |
420 | 433 | |
421 | -* filter falling edge of F_LFT, F_RGT, F_EMG, F_CAN in TOGGLE | |
434 | +* filter out trailing edge of F_LFT, F_RGT, F_EMG, F_CAN in TOGGLE | |
435 | +* also filter out auxiliary TOGGLEs in passing | |
422 | 436 | * 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 | |
437 | +TMFFAL ora #{F_NGN | F_BRK} ; not filtered | |
438 | + and TOGGLE ; filter any other (logical) fall(en) edge | |
439 | + and #{$FF ^ F_OPC ^ F_MNC} ; auxiliaries should never TOGGLE | |
426 | 440 | sta TOGGLE |
427 | 441 | |
428 | - SUBHEADER 'Timer Service Code -- brake lights' | |
442 | + SUBHEADER 'Timer Service Code -- Adjust STATES' | |
429 | 443 | PAGE |
430 | 444 | |
431 | -* Brake lights are the highest priority function, depending only | |
432 | -* on the ISTATE F_BRK. The STATES F_BRK is returned as a flag to other | |
433 | -* routines. | |
434 | - | |
435 | - brclr F_BRK_,ISTATE,TMBRK0 | |
445 | +* move brake bit from ISTATE to STATES | |
446 | +TMBRKMV bclr F_BRK_,STATES | |
447 | + brclr F_BRK_,ISTATE,TMEMGMV | |
436 | 448 | bset F_BRK_,STATES |
437 | - bclr R_LDRV_,PORTA ; brake lights on | |
438 | - bclr R_RDRV_,PORTA | |
439 | -* high center brake light connects directly to brake switch. | |
440 | - bra TMBRKDUN | |
441 | -TMBRK0 bclr F_BRK_,STATES | |
442 | - bset R_LDRV_,PORTA ; brake lights off | |
443 | - bset R_RDRV_,PORTA ; (flashers can turn them back on) | |
444 | -TMBRKDUN | |
445 | - | |
446 | - SUBHEADER 'Timer Service Code -- fill event queue' | |
447 | - PAGE | |
448 | 449 | |
449 | -* General debounce complete; now put signal events in queue: | |
450 | -* Brake and engine-on are handled in TIMSRV, as synchronous events, and | |
451 | -* so are not queued. Turn signal and emergency inputs are positive edge | |
452 | -* sensitive, falling edges are ignored. | |
450 | +* toggle STATES F_EMG if TOGGLE F_EMG | |
451 | +TMEMGMV brclr F_EMG_,TOGGLE,TMEMGM0 | |
452 | + lda STATES | |
453 | + eor #F_EMG | |
454 | +TMEMG0 sta STATES | |
453 | 455 | |
454 | -* Queue is post-inc push and pull; QIN == QOUT is empty queue; | |
455 | -* queue overflow causes the oldest event to be discarded, but should | |
456 | -* never occur. | |
456 | +* turn on STATES turn signal if TOGGLE turn signal | |
457 | + lda TOGGLE | |
458 | + and #{F_LFT | F_RGT} | |
459 | + ora STATES | |
457 | 460 | |
458 | - lda TOGGLE ; F_BRK & F_ENG are not queued! | |
459 | - and #{$FF ^ F_BRK ^ F_ENG} ; KICS assembler has no bit not? | |
460 | - sta TOGGLQ | |
461 | - beq TMCLOCK ; save time | |
462 | - ldx QIN | |
463 | - lda #$10 ; start with bit 3! | |
464 | -* cycles to this point, plus interrupt response (19 cycles) | |
461 | +* cancel STATES turn signal if TOGGLE F_CAN is not filtered out | |
462 | + brclr F_CAN_,TOGGLE,TMCAN0 | |
463 | + and #{$FF ^ F_LFT ^ F_RGT} ; STATES still in A | |
464 | +TMCAN0 sta STATES | |
465 | 465 | |
466 | -$CYCLE_ADDER_OFF | |
467 | -$CYCLE_ADDER_ON | |
468 | -TMQSCAN lsra ; scan TOGGLE | |
469 | - beq TMQDUN | |
470 | - bit TOGGLQ | |
471 | - beq TMQSCAN | |
472 | -* 12 cycles minimum time in loop | |
473 | -$CYCLE_ADDER_OFF | |
474 | -$CYCLE_ADDER_ON | |
475 | - sta ,x | |
476 | - incx | |
477 | - cpx #EVENTQ+MAXEVENTS | |
478 | - blo TMQNWRP | |
479 | - ldx #EVENTQ ; 2 cycles | |
480 | -TMQNWRP cpx QOUT | |
481 | - bne TMQSCAN | |
482 | - inc QOUT ; 5 cycles | |
483 | -TMQNBMP bra TMQSCAN ; 3 cycles | |
484 | -* 40 cycles maximum time in loop, (40 - 2 - 5 - 3) == 30 typical max; | |
485 | -* Minimum queue time is 12 * 3 + 30 == 66 (no wrap, no bump); | |
486 | -* max is 30 * 3 + 40 == 130 (one wrap, one bump max) | |
487 | -$CYCLE_ADDER_OFF | |
488 | -$CYCLE_ADDER_ON | |
489 | -TMQDUN stx QIN | |
466 | +* Engine time out state is handled within the software timer | |
467 | +* routines. | |
490 | 468 | |
491 | - SUBHEADER 'Timer Service Code -- engine time out and flasher timers' | |
469 | + SUBHEADER 'Timer Service Code -- Engine Time Out and Flasher Timers' | |
492 | 470 | PAGE |
471 | + | |
493 | 472 | * Although the Real Time Interrupt is masked, the software clocks |
494 | -* use the RTI flag. Selecting the fastest RTI rate gives the software | |
495 | -* clocks a resolution of eight timer overflows (8192 CPU cycles). | |
473 | +* use the RTI flag. See RTIPOW for the RTI flag rate | |
496 | 474 | |
497 | 475 | TMCLOCK |
498 | 476 | brclr RTIF_,TSCR,TIMDUN |
499 | 477 | bset RTIFR_,TSCR |
500 | 478 | |
501 | -* The engine time-out counter resets if the engine toggles on. It | |
502 | -* runs only when the ISTATE F_ENG bit is low and the emergency flashers | |
503 | -* (STATES F_EMG) are off. It does not underfow. The timer flags | |
504 | -* timeout in STATES F_ENG. | |
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. | |
505 | 483 | |
506 | - brclr F_ENG_,TOGGLE,TMENG0 | |
507 | - lda #{TIMOUT & $FF } ; reset the clock | |
508 | - sta ENG_TIM+1 | |
484 | + brclr F_NGN_,TOGGLE,TMNGN0 ; reset on toggle off (and on) | |
485 | + lda #{TIMOUT & $FF } ; reset value low byte | |
486 | + sta NGN_TIM+1 | |
509 | 487 | lda #{TIMOUT / $100 + 1} ; borrow on 0, not -1 |
510 | - sta ENG_TIM | |
488 | + sta NGN_TIM | |
511 | 489 | bra TMFLASH |
512 | 490 | |
513 | -TMENG0 | |
514 | - brset F_ENG_,ISTATE,TMFLASH | |
515 | - brset F_EMG_,STATES,TMFLASH | |
516 | - brclr F_ENG_,STATES,TMFLASH ; do not underflow! | |
517 | - dec ENG_TIM+1 | |
491 | +TMNGN0 | |
492 | + lda STATES | |
493 | + and #{F_NGN | F_EMG | F_BRK} ; brakes or emg flashers? | |
494 | + eor #F_NGN ; no underflow | |
495 | + bne TMFLASH | |
496 | + brset F_NGN_,ISTATE,TMFLASH | |
497 | + dec NGN_TIM+1 | |
518 | 498 | bne TIMFLH ; initial count is adjusted to make this work |
519 | - dec ENG_TIM | |
499 | + dec NGN_TIM | |
520 | 500 | bne TIMFLH |
521 | - bclr F_ENG_,STATES ; signal timed out | |
522 | - bset F_ENG_,TOGGLE ; communicate with MAINLOOP | |
501 | + bclr F_NGN_,STATES ; signal timed out | |
502 | + bset F_NGN_,TOGGLE ; communicate with MAINLOOP | |
523 | 503 | |
524 | 504 | * flasher counter |
525 | 505 | TMFLASH lda #{F_EMG | F_LFT | F_RGT} |
@@ -532,18 +512,18 @@ TMFLASH lda #{F_EMG | F_LFT | F_RGT} | ||
532 | 512 | |
533 | 513 | TIMDUN rti |
534 | 514 | $CYCLE_ADDER_OFF |
535 | -* Keep the maximum clock cycles in TIMSRV below half of TOFR period. | |
536 | -* It is probably physically impossible to operate the switches fast | |
537 | -* enough to overflow the queue that way. | |
538 | 515 | |
539 | 516 | SUBHEADER 'Initializations' |
540 | 517 | PAGE |
518 | + | |
541 | 519 | * waking up simply resets the MCU |
542 | 520 | * if SWI occurs, the machine is not in a defined state, and must reset |
543 | 521 | IRQSRV |
544 | -SWISRV rsp ; now falls through to RSTSRV | |
522 | +SWISRV | |
545 | 523 | clra |
546 | 524 | sta COPR |
525 | + rsp ; now falls through to RSTSRV | |
526 | + | |
547 | 527 | * general inits |
548 | 528 | RSTSRV lda #{F_LDRV | F_RDRV | R_LDRV | R_RDRV} |
549 | 529 | sta PORTA ; initial output values |
@@ -563,199 +543,93 @@ RSTSRV lda #{F_LDRV | F_RDRV | R_LDRV | R_RDRV} | ||
563 | 543 | clra |
564 | 544 | sta COPR ; b0 clear, about to change timer rate |
565 | 545 | lda #{TOIE | RTIPOW} ; only timer overflow interrupts |
566 | - sta TSCR | |
546 | + sta TSCR ; RTIPOW has the timer rate | |
567 | 547 | ora #{TOFR|RTIFR} ; clear the flags |
568 | 548 | sta TSCR |
569 | 549 | * set up specific variables |
570 | 550 | clr DEBO ; start debounce chain clear |
571 | 551 | clr DEBO+1 ; DEBO+2 is thrown out on first timer interrupt |
572 | - lda #{F_ENG} | |
573 | - sta ISTATE ; force TIMOUT to be set | |
574 | - sta TOGGLE | |
575 | - sta STATES ; we think the engine is on | |
576 | - ldx #EVENTQ ; empty QUEUE | |
577 | - stx QIN | |
578 | - stx QOUT | |
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 | |
579 | 559 | |
580 | -* Falls through to MAINLOOP | |
560 | +* Falls through to DOSTATES | |
581 | 561 | |
582 | - SUBHEADER 'Dequeue Events and Modify STATES, also STOP' | |
562 | + SUBHEADER 'DOSTATES: Interpret States' | |
583 | 563 | PAGE |
584 | 564 | |
585 | -MAINLOOP | |
565 | +DOSTATES: | |
586 | 566 | cli ; leave interrupts enabled as much as possible |
587 | 567 | clra |
588 | 568 | sta COPR ; tell COP we're in control |
589 | -* check for STOP, dequeue flasher events, wait if necessary | |
590 | - sei | |
591 | - brclr F_ENG_,STATES,MNSTOP | |
592 | - ldx QOUT | |
593 | - cpx QIN ; QUEUE empty? | |
594 | - bne MNDEQUEUE | |
595 | - lda STATES ; can we save power for a bit? | |
596 | - and #{F_LFT | F_RGT | F_BRK | F_EMG} | |
597 | - bne MNDRVWT | |
598 | - bclr DRVDRV_,PORTA | |
599 | -MNDRVWT wait ; enable interrupts, wait for timer | |
600 | - tst TOGGLE | |
601 | - beq MNDRVWT ; nothing changed, nothing to respond to | |
602 | -* with no activity, COP periodically resets the MCU system | |
603 | -* this is not generally good engineering practice. | |
604 | - bset DRVDRV_,PORTA ; IRQSRV might have driven the brake lights | |
605 | - bra MAINLOOP ; check STOP and QUEUE again | |
606 | - | |
607 | -* go to power conserving state | |
608 | -MNSTOP lda #{F_LDRV | F_RDRV | R_LDRV | R_RDRV} | |
609 | - sta PORTA ; shut everything down, organized! | |
610 | - lda #{F_LDRV | F_RDRV | R_LDRV | R_RDRV | DRVDRV} | |
611 | - sta DDRA ; set up directions | |
612 | - sta PDRA ; pull downs only on inputs | |
613 | - clr PORTB ; initial outputs (do port B just in case) | |
614 | - clr DDRB ; B initially input | |
615 | - clr PDRB ; with pull downs set | |
616 | -* make sure EPROM programming stuff is out of the way | |
617 | - clr EPROG | |
618 | - clr PESCR | |
619 | -* enable external interrupts | |
620 | - bset IRQE_,ISCR ; DO NOT clear the flag (IRQ won't return) | |
621 | - stop ; also shuts timer down | |
622 | - jmp SWISRV ; should never come here (resets stack pointer) | |
623 | - | |
624 | -MNDEQUEUE | |
625 | - lda ,x | |
626 | - incx | |
627 | - cpx #EVENTQ+MAXEVENTS | |
628 | - blo MNQNWRP | |
629 | - ldx #EVENTQ | |
630 | -MNQNWRP stx QOUT | |
631 | - cmp #F_EMG | |
632 | - bne MNCAN | |
633 | - eor STATES ; toggle STATES F_EMG emergency flashers bit | |
634 | - sta STATES | |
635 | - bra MNDOSTATES | |
636 | - | |
637 | -MNQCAN cmp #F_CAN | |
638 | - bne MNQLFT | |
639 | - ldx #7 | |
640 | - | |
641 | - lda STATES | |
642 | - and #{F_LFT | F_RGT} | |
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 | |
655 | - | |
656 | - | |
657 | -MNQLFT cmp #F_LFT | |
658 | - bne MNQRGT | |
659 | - bset F_LFT_,STATES | |
660 | - bclr F_RGT_,STATES | |
661 | - bra MNDOSTATES | |
662 | - | |
663 | -MNQRGT cmp #F_RGT | |
664 | - bne MNQDEF | |
665 | - bset F_RGT_,STATES | |
666 | - bclr F_LFT_,STATES | |
667 | - bra MNDOSTATES | |
668 | - | |
669 | -MNQDEF jmp SWISRV ; nothing else should be queued | |
670 | - | |
671 | -* then make the output mirror the state | |
672 | - | |
673 | - | |
674 | -DOSTATE | |
675 | - brset F_BRK_,STATES,MAINLOOP ; if brakes set, do nothing else | |
676 | - brset F_EMG_,STATES,DOEMERG ; if emergency flash, skip engine | |
677 | - brset F_ENG_,STATES,DOTURN ; no turn signals if engine off | |
678 | -* engine off and timed out, no brakes, no emergency flashers | |
679 | - lda | |
680 | - | |
681 | - | |
682 | -* Emergency flasher filter simply toggles F_EMG bit of STATES | |
683 | -* when emergency flasher button is pressed. Release is ignored. | |
684 | - | |
685 | -INFEMG cli ; allow interrupts | |
686 | - sei ; critical: not seamless access | |
687 | - brclr F_EMG_,TOGGLE,INFTRN | |
688 | - bclr F_EMG_,TOGGLE | |
689 | - brclr F_EMG_,ISTATE,INFTRN ; no action when button released | |
690 | - lda STATES | |
691 | - eor #F_EMG | |
692 | - sta STATES | |
693 | -* fall through | |
694 | 569 | |
570 | +* State machine for STATES | |
571 | +* Brake, eNgine, emerGency, Left, and Right | |
695 | 572 | * |
696 | - | |
697 | -INFTRN cli ; allow interrupts | |
698 | - sei ; critical: not seamless access | |
699 | - lda STATES | |
700 | - and ISTATE | |
701 | - and #{F_LFT | F_RGT} ; mask | |
702 | - eor #{F_LFT | F_RGT} ; ignore if already on | |
703 | - and TOGGLE | |
704 | - beq FNENG | |
705 | - tax | |
706 | - and ISTATE ; too late at night, all my work this aft is gone | |
707 | -* check here for turning | |
708 | -FNENG | |
709 | - | |
710 | -* support on and off states on signal timer. | |
711 | - | |
712 | -* if engine is off and timed out, shut down. | |
713 | -* else if brakes on, set break lights, let front and turn signals flash | |
714 | -* else if emergency set, flash all | |
715 | -* else run turn signals | |
716 | - | |
717 | - | |
718 | -* this should be discarded: | |
719 | - | |
720 | -* Four major state machines are implemented and maintained: | |
721 | -* ENGINE state, BRAKE state, EMERGENCY flasher state, | |
722 | -* and TURN_SIGNAL state. | |
723 | - | |
724 | -* If brake lights and emergency flashers are independent, EMERGENCY and | |
725 | -* BRAKE states should be the only pieces of code that need modifying. | |
726 | - | |
727 | - | |
728 | -* The ENGINE state machine has three states: | |
729 | -* ENG_OFF (MCU in STOP state) | |
730 | -* ENG_ON (MCU running, time out counter reset) | |
731 | -* ENG_TO (MCU running, time out counter counting) | |
732 | - | |
733 | -* The BRAKE state machine has two states: | |
734 | -* BRK_ON (F_BRK in ISTATE high, brake lights forced on) | |
735 | -* BRK_OFF (F_BRK in ISTATE low) | |
736 | - | |
737 | -* The EMERGENCY state machine has two states: | |
738 | -* EMG_ON (F_EMG in STATES high, flasher counters running) | |
739 | -* EMG_OFF (F_EMG in STATES low) | |
740 | -* -- consider flasher rates, turnsignal vs emergency | |
741 | - | |
742 | -* The TURN_SIGNAL state machine has two state machines: | |
743 | - | |
744 | -* BRK_OFF (F_BRK==1)---> BRK_ON { possibly interrupting } | |
745 | -* BRK_OFF <---(F_BRK==0) BRK_ON | |
746 | - | |
747 | -* ENG_OFF (F_ENG==1)---> ENG_ON { usually interrupting } | |
748 | -* ENG_TMO <---(F_ENG==0) ENG_ON | |
749 | -* ENG_TMO (F_ENG==1)---> ENG_ON | |
750 | -* ENG_OFF <---(F_ENG==0 && 5 Minutes delay) ENG_TMO | |
751 | -* (Change the XTAL constant if a 1 MHz crystal is not used!) | |
752 | - | |
753 | -* EMG_NO (F_EMG==1 && EMG_FL==0)---> EMG_FL | |
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 | |
754 | 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 | |
755 | 631 | |
756 | 632 | |
757 | - bra MAINLOOP | |
758 | - | |
759 | 633 | |
760 | 634 | org VECTORS |
761 | 635 | fdb TIMSRV |