;*****************************************************************+
;* Lab 3b Skeleton                                                *
;* 18348, Fall 2007                                               *
;* Original author: Justin Ray                                    *
;* Filename: lab_3b_skeleton.asm                                  *
;* Change History: 7-29-07 - Unknown - Fall 2007 updates          *
;*                 8-19-09 - Szilagyi - Updated for APS12C128     *
;* Intended target:  MC9S12C128                                   *
;*                                                                *
;*****************************************************************+

;******************************************************************+
;* Group:                                                         *
;* Group Members and andrew id:                                   *
;******************************************************************+

; export symbols
            XDEF Entry            ; export 'Entry' symbol
            ABSENTRY Entry        ; for absolute assembly: mark this as 
                                  ; application entry point


; include derivative specific macros
            INCLUDE 'mc9s12c128.inc'

; variable/data section
            INCLUDE 'RAMLocation.inc'
            
;*************************************************
; ADD GLOBAL VARIABLES HERE
;*************************************************
WiperPosition     DS.B  1  ;location of the wiper is stored as a bit pattern
WiperSpeed        DS.B  1  ;speed of the wiper, values are the SPEED_* constants
WiperStatus       DS.B  1  ;direction of the wiper
ControllerState   DS.B  1  ;state variable for the controller

;button constants - correspond to bit masks for inputs
Button1           EQU   $01
Button2           EQU   $02
Button3           EQU   $04
ButtonMask        EQU   $07

;state constants - integer values for states
StateOff          EQU   $00
StatePark         EQU   $01
StateSlow         EQU   $02
StateFast         EQU   $03
StateMask         EQU   $07

;wiper constants - values used in the wiper control code
SPEED_OFF         EQU   $00
SPEED_SLOW        EQU   $01
SPEED_FAST        EQU   $02
DIR_BIT           EQU   $01
DIR_BIT_INV       EQU   $FE
WIPER_MIN         EQU   $01
WIPER_MAX         EQU   $80



ROMStart    EQU  $4000  ; absolute address to place my code/constant data

; code section
            ORG   ROMStart
Entry:
            INCLUDE 'StackInfo.inc'

            CLI                   ; enable interrupts

;*****************************************************
; ADD CODE HERE
;*****************************************************

;---------------------
;MAIN CODE STARTS HERE



;---------------------
;INITILIZATION

            ;initilization
            JSR IOInit
            JSR wiperUpdateInit
            LDAA #StateOff
            STAA ControllerState

;---------------------
;BEGIN STATE LOOP


stateLoop   


            ;be sure to call wiperupdate in every loop so the wiper moves
            JSR wiperUpdate
            
;switch statement for transitions
; TODO write a switch statement here that jumps to 
;      the appropriate code block based
;      on the current value of ControllerState.  You switch 
;      statement must use an index-indirect
;      (JMP [D,xysp] or JMP [oprx16, xysp]) style instruction. 

            
sw_Start:
sw_Default:
sw_StateOff:
            ;TODO trace to the appropriate state in your statechart

            ;load default DO for the current state
            ; TODO
            
            ;transitions to other states                                        
            ; TODO 
    sw_StateOff_TransitionDone:
            BRA sw_End   ;break

sw_StatePark:
            ;TODO trace to the appropriate state in your statechart
            
            ;load default DO for the current state
            ; TODO
            
            ;transitions to other states
            ;TODO

    sw_StatePark_TransitionDone:
            BRA sw_End   ;break

sw_StateSlow:
            ;TODO trace to the appropriate state in your statechart
            
            ;load default DO for the current state
            LDX #StateSlow_Do
            
            ;transitions to other states
            LDAA PTAD         ;read button input
            COMA              ;invert inputs
            ANDA #ButtonMask  ;mask inputs
            
    ;test to see if button 1 is pressed
    sw_Slow_Button1Test:
            CMPA #Button1
            BNE sw_StateSlow_Button3Test
            ;transition to Park state
            ;TODO trace to the appropriate transition in your statechart
            LDAB #StatePark
            STAB ControllerState
            LDX #StatePark_Do ;load DO address
            BRA sw_StateSlow_Transition_Done
    ;test to see if button 2 is pressed
    sw_StateSlow_Button3Test:
            CMPA #Button3
            BNE sw_StateSlow_Transition_Done
            ;transition to Fast state
            ;TODO trace to the appropriate transition in your statechart
            LDAB #StateFast
            STAB ControllerState
            LDX #StateFast_Do ;load DO address
            
    ;Done with transitions
    sw_StateSlow_Transition_Done:
            BRA sw_End   ;break

sw_StateFast:
            ;TODO trace to the appropriate state in your statechart

            ;load default DO for the current state
            ;TODO
            
            ;transitions to other states
            ;TODO
    sw_StateFast_TransitionDone:
            BRA sw_End   ;break
            


sw_End:
;end of switch statement

;call appropriate DO routine, stored in X register
            JSR X

            JMP stateLoop

;catch loop to protect subroutines
loopForever:
            BRA loopForever
            
            
;---------------------
;END OF MAIN CODE

;****************************************
;   Beginning of subroutine definitions
;****************************************


;-----------------
;State subroutines


StateOff_Do:
;TODO trace to the appropriate state in your statechart

            ;DO: actions for the current state
            ;TODO
            RTS
;end of StateOff_Do


StatePark_Do:
;TODO trace to the appropriate state in your statechart

            ;DO: actions for the current state
            ;TODO
            RTS
;end fo StatePark_Do
            
; Do actions for slow state
; Stack:
; * Ret Hi
; * Ret Lo
StateSlow_Do:
;TODO trace to the appropriate state in your statechart

            ;DO: actions for the current state
            MOVB #SPEED_SLOW, WiperSpeed  ;set the wiper speed to off            
            RTS;
;end of StateSlow_Do
            
StateFast_Do:
;TODO trace to the appropriate state in your statechart

            ;DO: actions for the current state
            ;TODO
            RTS
;end of StateFast_Do


;---------------------
;WIPER RELATED SUBROUTINES

;initilizaton for the wiper control function
;Stack:
;* RetHi
;* RetLo
;* reg A save
wiperUpdateInit:
            
            PSHA  ;save A

            ;init wiper position
            LDAA #WIPER_MIN
            STAA WiperPosition
            BSR writeA ;set display to init value

            ;init status
            LDAA #DIR_BIT
            STAA WiperStatus

            ;init speed
            LDAA #SPEED_OFF
            STAA WiperSpeed

            PULA  ;restore A

            RTS
;end of wiperUpdateInit            

;function to update the wiper position
;based on the current inputs
;Stack:
;* RetHi
;* RetLo
;* reg D Hi save
;* reg D Lo save
wiperUpdate:
            PSHD ;save D 
            
            ;if speed is off, then don't modify the
            ;wiper position.  Jump straight to wait instead
            LDAA WiperSpeed
            CMPA #SPEED_OFF
            BEQ wiperUpdateShortWait
            
            ;speed is not off,su update the wiper position
            LDAA WiperPosition ;load wiper position
            LDAB WiperStatus ;status has wiper direction            
            CMPB #DIR_BIT          ;
            BNE shiftDown           ;
shiftUp:
            LSLA ;shift the display value
            CMPA #WIPER_MAX ;compare to wiper max
            BNE wiperUpdateShiftDone
            ;if we get here, the wiper is all the way up
            ;set it to come back down
            ANDB #DIR_BIT_INV  ;clear the direction bit       
            BRA wiperUpdateShiftDone

shiftDown:
            LSRA ;shift the display value
            CMPA #WIPER_MIN  ;compare to wiper min
            BNE wiperUpdateShiftDone
            ;if we get here, the wiper is all the way down
            ;set it to go back up
            ORAB #DIR_BIT     ;set the direction bit          
            
wiperUpdateShiftDone:
            ;write the new value to the LEDs
            BSR writeA ;write the display value
            ;store position information
            STAA WiperPosition
            STAB WiperStatus
            ;now decide how long the wait should be
            ;if the speed is fast, jump to short-wait
            ;otherwise the speed must be slow or park
            ;and we will go to Long wait automatically
            LDAA WiperSpeed
            CMPA #SPEED_FAST
            BEQ wiperUpdateShortWait

wiperUpdateLongWait:
            BSR wait14thSec
wiperUpdateShortWait:
            BSR wait14thSec
            
            
wiperUpdateCleanup:
            ;cleanup before returning
            PULD  ;restore D value
            RTS
;end of wiperUpdate

;---------------------
;UTILITY SUBROUTINES


;wait 1/14th of a second
;Stack:
;* RetHi
;* RetLo
;* reg X Hi save
;* reg X Lo save
wait14thSec:
            PSHX
            LDX #0
wait14Loop:
            INX
            NOP
            NOP
            NOP
            NOP
            NOP
            NOP
            NOP
            NOP
            NOP
            NOP
            NOP            
            CPX #$FF  ; TODO hand tune value for correct wait period
                      ;  Hint: use simulator for this
            BNE wait14Loop
            PULX
            RTS

            

;writes the value in reg A to the LEDS
;Stack:
;* RetHi
;* RetLo
;* reg B save
writeA:
            PSHB ;save B
            COMA ;invert before writing
            STAA PTT
            COMA ;restore original A
            LDAB #$FF
            STAB PORTA
            CLRB
            STAB PORTA
            PULB ;restore B
            RTS


;Initilizes the IO ports
;Stack:
;* RetHi
;* RetLo
IOInit:
;configure port T for output
            ;TODO 
;configure port AD as input
            ;TODO
;configure port P as input
            ;TODO
;configure port A for output
            ;TODO
;end of IOInit
            RTS

;*****************************************************
; DO NOT MODIFY OR ADD ANYTHING AFTER THIS POINT
;*****************************************************

;**************************************************************
;*                 Interrupt Vectors                          *
;**************************************************************
            ORG   $FFFE
            DC.W  Entry           ; Reset Vector
