;***************************************************************
; ECE331 Lab 4 Starter Program (KEH, August 2004)
; BLINKY.ASM - Demonstrates simultaneous operation of a non-interrupt driven 
; main program that flashes an LED (on PT7) on and off at an approximate 1-second rate 
; and also a precisely timed 500 Hz square wave (on PT6) generating program using Timer Channel 6 
; as an output compare register.
;
            XDEF BLINKY        
            ABSENTRY BLINKY   
            INCLUDE 'mc9s12c32.inc'
            
            ORG $3800
            
storeLoc:     DS.B  4

toneLoc:      DS.B  4
        
            ORG $4000

Combo:        DC.B  %00001111,%00001111,%00001111,%00001111

LUT:          DC.B  %00111111,%00000110,%01011011,%01001111,%01100110,%01101101,%01111101,%00000111,%01111111,%01100111

BLINKY:       lds #$3f00
              jsr PLL_init
              movb  #%10101110,DDRT   		;Make PT1,2,3,5,7 digital outputs.
              movb  #%01111111,ATDDIEN    ;Disable ATD conversion on PAD0-6
              movb  #%01110000,DDRAD      ;Set PAD0-PAD3 as digital inputs and PAD7 as an analog input
              movb  #%00000000,PERAD      ;Disable internal pull-ups
              bset  ATDCTL2,%10000000     ;Power up ATD Unit
              movb  #%00001000,ATDCTL3    ;Select single conversion per sequence
              movb  #%00000111,ATDCTL4    ;Select 10 bit conversion, 2-clock sample time, 1/16 prescale
              movb  #%01111111,RTICTL     ;Set interrupt period to be every 43.7 ms.

              movb  #%00111000,DDRM       ;Set PTM3-5 as outputs
              movb  #$5C,SPICR1           ;Power up SPI interface, and set it up
              movb  #$27,SPIBR            ;Set up SPI baud rate
              bset  CRGINT,%10000000      ;Initialize RTI interrupts
              movb  #%00000000,PTM        ;
              
              movb  #5,TSCR2    		;Set prescaler bits to 5 so TCNT increments every 
                             				;32/24MHz = 1.333 microseconds.
              movb  #$80,TSCR1  		;Enable Timer TCNT to begin counting
              movb  #%01010001,TIE  ;Locally Enable TC6 and TC4 interrupts
              movb  #%01000000,TIOS ;Make TC6 an Output Compare register and TC4 and Input Compare register
              movb  #$10,TCTL1    	;Make TC6 pin toggle when the scheduled output compare occurs
              movb  #2,TCTL3        ;Enable falling edge sensitivity for PT4, PT0
              movb  #2,TCTL4        ;
				

              ldd   TCNTHi      		;Load TCNT into register D
              addd  #750        		;Add 750 TCNT increments to it.
                                    ;Note 750*1.33us = 1 ms.
              std   TC6Hi       		;Schedule next output compare interrupt to occur in 1 ms
              movb  #%01010001,TFLG1;Make sure TC6 and TC4 interrupt flags are cleared
              cli		            		;globally enable interrupts
blinkagain: 	
              bclr  PTT,%10000000	  ;Turn off LED on PT7
              bsr   onesecdelay
              bset  PTT,%10000000   ;Turn ON LED on PT7
              bsr   onesecdelay
              bra   blinkagain
;*********Here ends the main program "BLINKY"
onesecdelay:            			      ;Software timing loop delay routine -- 
                                    ;Delays approx 1 second,depending upon how 
              pshx                  ;much time is taken away to process interrupts.
              pshy
              ldx   #46
outerloop:  
              ldy   #$ffff
innerloop:  
	            dey
            	bne   innerloop
            	dex
            	bne   outerloop
            	puly
            	pulx
            	rts

TOC6ISR:    
            	ldd   TCNTHi
            	addd  #750            ;Schedule another interrupt in 1 ms from now
            	std   TC6Hi
            	movb  #$40,TFLG1      ;Relax the TC6 interrupt flag
            	rti

TOC4ISR:      movb  #%00010000,TFLG1 ;Relax the TC4 interrupt flag
              ldx   #storeLoc
              ldy   #Combo
                          	
            	movb  2,X,3,X         ;Rotate stored data
            	movb  1,X,2,X
            	movb  X,1,X
            	            	
            	ldaa  PTAD            ;Load newest value
            	anda  #%00001111      ;Mask out other bits
            	staa  X               ;Store it to memory
            	
             	cmpa  Y               ;Compare list of values
              bne notCorrect        ;
            	ldaa  1,X             ;
            	cmpa  1,Y             ;
            	bne notCorrect        ;
            	ldaa  2,X             ;
            	cmpa  2,Y             ;
            	bne notCorrect        ;
            	ldaa  3,X             ;
            	cmpa  3,Y             ;
            	bne notCorrect        ;
            	
            	ldaa  PTT             ;Turn on the LED if correct combo entered
            	oraa  #%00100000      ;
            	staa  PTT             ;
            	rti                   ;
            	
notCorrect:  	bclr PTT,%00100000    ;Shut off LED
              rti

TOC0ISR:      movb #%00000001,TFLG1 ;Relax the TC4 interrupt flag
              ldx #toneLoc          ;
              
              movw X,2,X            ;Rotate Data around
              
              ldd TC0Hi             ;Read input capture reg and
              std X                 ;determine whether the frequency is alright
              subd 2,X              ;
              cpd #1750             ;
              bhi tooLow            ;
              cpd #1680             ;
              blo tooHigh           ;
              
              bclr PTT,%00001110    ;Turn the freq good light on
              bset PTT,%00000100
              rti

tooHigh:      bclr PTT,%00001110    ;Turn the freq too high light on
              bset PTT,%00001000
              rti
              
tooLow:       bclr PTT,%00001110    ;Turn the freq too low light on
              bset PTT,%00000010
              rti
              
ATD:          bset  CRGFLG,%10000000          ;Relax interrupt flag
              movb  #%10000111,ATDCTL5        ;Start ATD conversion process
Wait:         brclr ATDSTAT0,#%10000000,Wait  ;Wait for the flag to be set
              ldd  ATDDR0                    ;Load converted data into accumulator A
              ldy  #50                       ;Convert to a value in the range of 0-50
              emul                            ;
              addd  #25                       ;
              ldx   #1024                     ;
              idiv
              tfr x,d   
              ldx #10
              idiv   
              tfr d,y
              ldaa  LUT,y
              
              ldab  LUT,x
              
              bclr  PTM,%00001000 
                          ;Lower PTM3
              ;psha
              ;ldaa   SPISR
              ;pula 
              ldx   SPISR            ;Dummy read
              STAB  SPIDR  
                                 ;Write first byte
Wait2:        ldab  SPISR
              andb  #$20
              beq Wait2                       ;brclr SPISR,#%10000000,Wait2    ;Check to see if flag set
              ; not needed ldx  SPIDR                      ;Dummy read
              STAA  SPIDR                     ;Write second byte
Wait3:        ldab  SPISR
              andb  #$20
              beq Wait3                       ;brclr SPISR,#%10000000,Wait3    ;Check to see if flag set
              bset  PTM,%00001000             ;Raise PTM3
              rti

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;Subroutine Name: PLL_init
;;Purpose: Initialize clock generator and PLL to increase CPU clock speed by factor of 6
;;Author: Dr. Hoover
;;Creation Date: Unknown
;;Revision Number: Unknown
;;Input Data Required: None.
;;Output Data: None
;;Registers Affected: None.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

PLL_init:bclr	  CLKSEL,$80 	;Disconnect PLL from system if connected.
	       bset	  PLLCTL,$40 	;Turn on the PLL hardware block.
	       movb #2,SYNR     	;Set PLL multiplier 
	       movb #1,REFDV   	  ;Set PLL divider
				        				    ;From Section 3.1.1 of CRG Block Guide
				        				    ;PLLCLK = OSCCLK*(SYNR+!)/(REFDV+1)
				        				    ;       = 16 MHz * (2+1)/(1+1) = 24MHz
	       nop	              ;NOP delays put here to allow time for  	
         nop	              ;CRGFLG flag register to become valid.
wt_PLL_Lock:	
	       brclr CRGFLG, 8, wt_PLL_Lock   ;Wait here for PLL to �Lock in� 
	       bset	CLKSEL,$80      	          ;Connect PLL back into system.
         rts

;**************************************************************
;*    Initialize Reset Vector and TC4 and TC6 Interrupt Vector  *
;**************************************************************
  	ORG     $FFFE
  	fdb     BLINKY                 ;Make reset vector point to entry point of BLINKY program
  	ORG     $FFE2
  	fdb     TOC6ISR                ;Make TC6 interrupt vector point to TC6 interrupt rtn
  	ORG     $FFE6
  	fdb     TOC4ISR                ;Make TC4 interrupt vector point to TC4 interrupt rtn
  	ORG     $FFEE
  	fdb     TOC0ISR                ;Make TC0 interrupt vector point to TC0 interrupt rtn
    ORG     $FFF0
    fdb     ATD                    ;Make RTI interrupt vector point to ATD interrupt rtn