* Filename      : TIME.ASM
* Programmer    : Michael Hattermann
* Date          : February 21, 2002
* Version       : 1.0
* Description   : This file contains time functions.  The
*                  following functions are available:
*
*                   INITTIME - initialize timer system
*                   KILLTIME - shut down timer system
*                   WAITSPEED - waits for a speeder to go by
*                   FLASHON - turns on flashing lights
*                   FLASHOFF - turns off flashing lights
*                   SIRENON - turns on the siren
*                   SIRENOFF - turns off the siren
*                   LEFTSTS - handles left speed trap sensor
*                   RIGHTSTS - handles right speed trap sensor
*                   TIMEEXT - handles extended timer,flashing lights,siren
*                   UPDMOTORS - updates speed on motors
*                   SIREN - handles siren output
*
*#define __DEBUGTIME_        1
*#define __PRINTTIME_        1

#include "hc12.asm"

*
************************************************************
* Time Equates
************************************************************
*
LSPDFLAG        EQU         BIT0    ; Flags to indicate if a
RSPDFLAG        EQU         BIT1    ;  beam was broken
BSPDFLAG        EQU         3       ;

SPDLIMIT        EQU         $1F     ; speed limit
FLASHRATE       EQU         15      ; flashing light rate (1/4 second)
FLASHPAT1       EQU         $0F     ; 1st light pattern
FLASHPAT2       EQU         $F0     ; 2nd light pattern

SIRENRATE1      EQU         -10     ; siren frequency change rate
SIRENRATE2      EQU         10      ; siren frequency change rate
SIRENFREQ1      EQU         2000    ; first siren frequency
SIRENFREQ2      EQU         1200    ; second siren frequency

*
************************************************************
* Time Debug Program
************************************************************
*
#ifdef  __DEBUGTIME_
            ORG     T0_PVECT
            JMP     LEFTSTS
            ORG     T1_PVECT
            JMP     RIGHTSTS
            ORG     TMR_OVER_PVECT
            JMP     TIMEEXT
            ORG     RTI_PVECT
            JMP     UPDMOTORS
            ORG     T6_PVECT
            JMP     SIREN
*
************************************************************
* Time Global Vairables
************************************************************
*
                ORG     $0900
UPPERTIMER      DC.W    $0000           ; 16-bit extension of TCNT
LEFTSPDTIME     DC.W    $0000           ; Time left break beam was broken
RIGHTSPDTIME    DC.W    $0000           ; Time right break beam was broken
SPDTIMEFLG      DC.B    $00             ; Flags to indicate which beams were broken
SPDCAUGHT       DC.B    $00             ; Flags to indicate speeder caught
FLASHTIMER      DC.B    $00             ; Timer for flashing lights
FLASHPREV       DC.B    $00             ; Previous status of lights
SIRENFREQ       DC.W    $0000           ; Frequency of the siren
SIRENTIMER      DC.W    $0000           ; Timer for siren


            ORG     USERPROG_PVECT
            JMP     TEST

            ORG     $B000
TEST        LDAA    #$00            ; turn off COP watchdog timer
            STAA    COPCTL
            LDS     #$0bff          ; init the stack pointer

            JSR     INITTIME        ; initialize the time system

*            LDX     #0              ; wait 0 ms
*            JSR     WAIT            ;
*            LDX     #1              ; wait 1 ms
*            JSR     WAIT            ;
*            LDX     #10             ; wait 10 ms
*            JSR     WAIT            ;

            CLI                     ; turn on interrupts
            JSR     FLASHON         ;
*            JSR     SIRENON

HERE        BRA     HERE            ; end of program

LEFTMOTOR       RTS
RIGHTMOTOR      RTS

LEFTSPSTR   DC.B    'L'
            DC.B    CR,LF,EOS
RIGHTSPSTR  DC.B    'R'
            DC.B    CR,LF,EOS
NEWLINE     DC.B    CR,LF,EOS

#include "sci.asm"
*#include "wait.asm"

#endif
*
*******************************************************************************
*                       SUBROUTINE -  INITTIME
* Description: Initializes the timer system
*               TC0     - left speed trap IR receiver
*               TC1     - right speed trap IR receiver
*               TC6     - siren output
* Input         : None.
* Output        : None.
* Destroys      : None.
* Calls         : None.
*******************************************************************************
*
INITTIME    MOVB    #$40,TIOS           ; setup input capture/output compare lines
            MOVB    #$00,CFORC          ; setup timer compare force register
            MOVB    #$00,OC7M           ; setup OC7 mask register
            MOVB    #$00,OC7D           ; setup OC7 data register
            MOVB    #$00,TCTL1          ; setup output compare pin action reg 1
            MOVB    #$00,TCTL2          ; setup output compare pin action reg 2
            MOVB    #$00,TCTL3          ; setup input capture edge detection reg 1
            MOVB    #$05,TCTL4          ; setup input capture edge detection reg 2
            MOVB    #$03,TMSK1          ; setup interrupts on timer lines
            MOVB    #$A0,TMSK2          ; setup misc timer pin options(pullups on IC pins)
            MOVW    #$0000,TC0          ; clear TC0 register
            MOVW    #$0000,TC1          ; clear TC1 register
            MOVW    #$0000,TC2          ; clear TC2 register
            MOVW    #$0000,TC3          ; clear TC3 register
            MOVW    #$0000,TC4          ; clear TC4 register
            MOVW    #$0000,TC5          ; clear TC5 register
            MOVW    #$0000,TC6          ; clear TC6 register
            MOVW    #$0000,TC7          ; clear TC7 register
            MOVB    #$FF,TFLG1          ; clear all interrupt flags
            MOVB    #$80,TFLG2          ; clear interrupt flag
            MOVW    #$0000,UPPERTIMER   ; clear timer extension timer
            MOVW    #$0000,LEFTSPDTIME  ; clear left speed time
            MOVW    #$0000,RIGHTSPDTIME ; clear left speed time
            MOVB    #$00,FLASHTIMER     ; clear flashing lights timer
            MOVB    #$00,SPDTIMEFLG     ; clear broken beam flags
            MOVB    #$00,SPDCAUGHT      ; clear speeder caught flag
            MOVB    #$00,FLASHPREV      ; turn off flashing lights
            MOVW    #$0000,SIRENFREQ    ; clear siren frequency
            MOVW    #$0000,SIRENTIMER   ; clear siren timer
            MOVB    #$00,BUMPVALUE      ; clear bumper value
            MOVB    #$86,RTICTL         ; set up, enable RTI
            MOVB    #$FF,RTIFLG         ; clear all RTI flags
            MOVB    #$80,TSCR           ; enable the timer
            RTS                         ; return to caller
*
*******************************************************************************
*                       SUBROUTINE -  KILLTIME
* Description: Shuts down the timer system
* Input         : None.
* Output        : None.
* Destroys      : None.
* Calls         : None.
*******************************************************************************
*
KILLTIME    MOVB    #$00,TCTL1          ; disconnect all output compare pins
            MOVB    #$00,TCTL2          ;
            MOVB    #$00,TCTL3          ; disable all input capture pins
            MOVB    #$00,TCTL4          ;
            MOVB    #$00,TMSK1          ; turn off interrupts
            MOVB    #$00,TMSK2          ; turn off timer overflow interrupts
            MOVB    #$00,PACTL          ; turn off pulse accumulator
            MOVB    #$00,TSCR           ; turn off timer
            RTS                         ; return to caller
*
*******************************************************************************
*                       SUBROUTINE -  WAITSPEED
* Description: Waits for a speeder to be caught and returns the direction the
*               object was travelling (Reg A).  Valid values are:
*                    LSPDFLAG - object was going left
*                    RSPDFLAG - object was going right
*
* Input         : None.
* Output        : Direction in reg A.
* Destroys      : None.
* Calls         : None.
*******************************************************************************
*
WAITSPEED
WAITSPEED1  LDAA    SPDCAUGHT       ; get flags for speeder caught
            TBEQ    A,WAITSPEED1    ; wait for a caught speeder
            BCLR    TMSK1,#BIT0     ; turn off left interrupts
            BCLR    TMSK1,#BIT0     ; turn off right interrupts
            RTS                     ; return to caller
*
*******************************************************************************
*                       SUBROUTINE -  FLASHON
* Description: Turns the flashing lights on
* Input         : None.
* Output        : None.
* Destroys      : None.
* Calls         : None.
*******************************************************************************
*
FLASHON     MOVB    #FLASHPAT1,FLASHPREV    ; turn on the lights
            RTS                             ; return to caller
*
*******************************************************************************
*                       SUBROUTINE -  FLASHOFF
* Description: Turns the flashing lights off
* Input         : None.
* Output        : None.
* Destroys      : None.
* Calls         : None.
*******************************************************************************
*
FLASHOFF    MOVB    #$00,FLASHPREV          ; turn off the lights
            RTS                             ; return to caller
*
*******************************************************************************
*                       SUBROUTINE -  SIRENON
* Description: Turns the siren on
* Input         : None.
* Output        : None.
* Destroys      : None.
* Calls         : None.
*******************************************************************************
*
SIRENON     MOVB    #$10,TCTL1              ; turn on pin action for siren
            BSET    TMSK1,#BIT6              ; turn on interrupts for siren
            MOVW    #SIRENFREQ1,SIRENFREQ   ; initialize the siren frequency

            MOVW    #SIRENRATE1,SIRENTIMER  ; start going up in frequency first

            RTS                             ; return to caller
*
*******************************************************************************
*                       SUBROUTINE -  SIRENOFF
* Description: Turns the siren off
* Input         : None.
* Output        : None.
* Destroys      : None.
* Calls         : None.
*******************************************************************************
*
SIRENOFF    BCLR    TMSK1,#BIT6              ; turn off interrupts for siren
            MOVB    #$00,TCTL1              ; turn off pin action for siren
            MOVW    #$0000,SIRENFREQ        ; clear siren frequency
            RTS                             ; return to caller
*
*******************************************************************************
*                 INTERRUPT SERVICE ROUTINE - LEFTSTS
* Description: Handles the processing for a signal received from the left
*               speed trap sensor.
* Input         : None.
* Output        : None.
* Destroys      : None.
* Calls         : None.
*******************************************************************************
*
LEFTSTS     BRCLR   TFLG1,BIT0,LEFTSTSX     ; make sure we should be here
            MOVB    #BIT0,TFLG1             ; clear the flag

#ifdef __PRINTTIME_
            PSHX                            ; save reg X
            LDX     #LEFTSPSTR              ; print beam broken
            JSR     OUTSTR                  ;
            PULX                            ; restore X
#endif

            MOVW    UPPERTIMER,LEFTSPDTIME  ; save time beam was broken
            LDAA    SPDTIMEFLG              ; load flags for broken beams
            ORAA    #LSPDFLAG               ; set the left flag
            CMPA    #BSPDFLAG               ; have both beams been broken?
            BEQ     LEFTSTS1                ; yes, then go handle
            STAA    SPDTIMEFLG              ; no, save flags for borken beams
            BRA     LEFTSTSX                ; get out

LEFTSTS1    MOVB    #$00,SPDTIMEFLG         ; clear flags for broken beams
            LDD     LEFTSPDTIME             ; get the left beam broken time
            CPD     RIGHTSPDTIME            ; did the timer roll over
            BLO     LEFTSTS2                ; yes, so calc speed differently
            SUBD    RIGHTSPDTIME            ; calculate time difference
            BRA     LEFTSTS3

LEFTSTS2    LDD     RIGHTSPDTIME            ; load time right beam broken
            SUBD    LEFTSPDTIME             ; calculate time difference

LEFTSTS3    CPD     #SPDLIMIT               ; was the object speeding?
            BHS     LEFTSTS4                ; no, so get out

            MOVB    #LSPDFLAG,SPDCAUGHT     ; yes, set flag for speeder caught

LEFTSTS4    COMB                            ;
            STAB    SEG7PORT                ; write speed to port
LEFTSTSX    RTI                             ; return from interrupt
*
*******************************************************************************
*                 INTERRUPT SERVICE ROUTINE - RIGHTSTS
* Description: Handles the processing for a signal received from the right
*               speed trap sensor.
* Input         : None.
* Output        : None.
* Destroys      : None.
* Calls         : None.
*******************************************************************************
*
RIGHTSTS    BRCLR   TFLG1,BIT1,RIGHTSTSX    ; make sure we should be here
            MOVB    #BIT1,TFLG1             ; clear the flag

#ifdef __PRINTTIME_
            PSHX                            ; save reg X
            LDX     #RIGHTSPSTR             ; print beam broken
            JSR     OUTSTR                  ;
            PULX                            ; restore reg X
#endif

            MOVW    UPPERTIMER,RIGHTSPDTIME ; save time beam was broken
            LDAA    SPDTIMEFLG              ; load flags for broken beams
            ORAA    #RSPDFLAG               ; set the right flag
            CMPA    #BSPDFLAG               ; have both beams been broken?
            BEQ     RIGHTSTS1               ; yes, then go handle
            STAA    SPDTIMEFLG              ; no, save flags for borken beams
            BRA     RIGHTSTSX               ; get out

RIGHTSTS1   MOVB    #$00,SPDTIMEFLG         ; clear flags for broken beams
            LDD     RIGHTSPDTIME            ; get the right beam broken time
            CPD     LEFTSPDTIME             ; did the timer roll over
            BLO     RIGHTSTS2               ; yes, so calc speed differently
            SUBD    LEFTSPDTIME             ; calculate time difference
            BRA     RIGHTSTS3

RIGHTSTS2   LDD     LEFTSPDTIME             ; load time right beam broken
            SUBD    RIGHTSPDTIME            ; calculate time difference

RIGHTSTS3   CPD     #SPDLIMIT               ; was the object speeding?
            BHS     RIGHTSTS4               ; no, so get out

            MOVB    #RSPDFLAG,SPDCAUGHT     ; yes, set flag for speeder caught (going right)

RIGHTSTS4   COMB                            ;
            STAB    SEG7PORT                ; write speed to port
RIGHTSTSX   RTI                             ; return from interrupt
*
*******************************************************************************
*                 INTERRUPT SERVICE ROUTINE - TIMEEXT
* Description: Increments the extended timer when a timer overflow occurs in
*               TCNT (it is incremented every 8ms).
* Input         : None.
* Output        : None.
* Destroys      : None.
* Calls         : None.
*******************************************************************************
*
TIMEEXT     BRCLR   TFLG2,BIT7,TIMEEXTX     ; make sure we should be here
            MOVB    #BIT7,TFLG2             ; clear the flag
            LDX     UPPERTIMER              ; get the timer extension
            INX                             ; increment the timer extension
            STX     UPPERTIMER              ; save the timer extension

            LDD     SIRENFREQ               ; get previous siren frequency
            BEQ     TIMEEXT2                ; if siren off, keep it off

            ADDD    SIRENTIMER              ; update siren frequency
            STD     SIRENFREQ               ; save siren frequency

            CPD     #SIRENFREQ1             ; are we at low end of range
            BLO     TIMEEXT1                ; no, continue
            MOVW    #SIRENRATE1,SIRENTIMER  ; yes, so start going back up
            BRA     TIMEEXT2                ; continue

TIMEEXT1    CPD     #SIRENFREQ2             ; are we at high end of range
            BHI     TIMEEXT2                ; no, continue
            MOVW    #SIRENRATE2,SIRENTIMER   ; yes, so start going down

TIMEEXT2    LDAB    FLASHPREV               ; get previous status of lights
            BEQ     TIMEEXTX                ; if lights off, keep them off

            LDAA    FLASHTIMER              ; get the flashing lights timer
            INCA                            ; increment the timer
            STAA    FLASHTIMER              ; save flashing lights timer
            CMPA    #FLASHRATE              ; do we need to change light status
            BNE     TIMEEXTX                ; no, so get out

            COMB                            ; switch light pattern
            STAB    FLASHPREV               ; save new light pattern
            STAB    LED1PORT                ; turn on lights with new pattern

            MOVB    #$00,FLASHTIMER         ; reset flashing lights timer

TIMEEXTX    RTI                             ; return from interrupt
*
*******************************************************************************
*                 INTERRUPT SERVICE ROUTINE - UPDMOTORS
* Description: Updates the speed of the motors on every RTI interrupt
* Input         : None.
* Output        : None.
* Destroys      : None.
* Calls         : None.
*******************************************************************************
*
UPDMOTORS   BRCLR   RTIFLG,BIT7,UPDMOTORSX      ; make sure we should be here
            MOVB    #BIT7,RTIFLG                ; clear the flag

            JSR     LEFTMOTOR                   ; update speed on left motor
            JSR     RIGHTMOTOR                  ; update speed on right motor

UPDMOTORSX  RTI                                 ; return from interrupt
*
*******************************************************************************
*                 INTERRUPT SERVICE ROUTINE - SIREN
* Description: Handles generating the frequency of the siren
* Input         : None.
* Output        : None.
* Destroys      : None.
* Calls         : None.
*******************************************************************************
*
SIREN       BRCLR   TFLG1,BIT6,SIRENX           ; make sure we should be here
            MOVB    #BIT6,TFLG1                 ; clear the flag

            LDD     TC6                         ; get previous interrupt time
            ADDD    SIRENFREQ                   ; calc next time (set frequency of siren)
            STD     TC6                         ; set next interrupt time

SIRENX      RTI                                 ; return from interrupt
*
*******************************************************************************
