; Lab8
; Andrew Fowler
; Damian Szmulewicz Section: 3276
; Controlling an LCD with a remote control. This program first
; Stores the 10 keys and then allows the user to press a key and cvreate an event
data_sect	.set		0xa000			;constant that is actually the starting addr of .data section
bss_sect	.set		0xb000
GPAMUX1 	.set 	0x6F86
GPAMUX2 	.set 	0x6F87
WDCR		.set	0x7029
GPADIR 		.set	0x6F8A
GPADAT 		.set 	0x6FC0
GPATOGGLE	.set	0x6FC6
PIEIFR3		.set	0x0CE6
TBCTR 		.set	0x6804
PCLKCR0		.set	0x701C
PCLKCR1		.set	0x701D
TBPRD		.set	0x6805
CMPB		.set	0x694A
CMPA		.set	0x6949
TBCTL		.set	0x6800
AQCTLA		.set	0x680B
CMPCTL		.set	0x6947	
TSCTR 		.set 	0x6A00	;Time-Stamp Counter
CTRPHS		.set 	0x6A02 ;Counter Phase Offset
CAP1 		.set 	0x6A04 ;Capture 1 Register
CAP2		.set 	0x6A06
CAP3 		.set 	0x6A08
CAP4 		.set 	0x6A0A
ECCTL1 		.set 	0x6A14 ;Capture Control Register 1
ECCTL2 		.set 	0x6A15 ;Capture Control Register 2
ECEINT 		.set 	0x6A16 ;Capture Interrupt Enable Reg
ECFLG 		.set 	0x6A17 ;Capture Interrupt Flag Reg
ECCLR 		.set 	0x6A18 ;Capture Interrupt Clear Reg
ECFRC 		.set 	0x6A19 ;Capture Interrupt Force Reg
TIMER1PRD	.set 	0x0C0A		
TIMER1TCR	.set	0x0C0C		
TIMER1PR	.set	0x0C0E		
TIMER1PR	.set	0x0C0E		;msb current prescaler count, prescale amount [low bytes]
TIMER1PRH	.set 	0x0C0F		;msb current prescaler count, prescale amount [high bytes]
PERIODL		.set	4000		
PERIODH		.set 	0
TIMER1PRDH	.set 	0x0C0B		;holds period of counter [high]
PRESCALEL	.set	0x0			;8-bit lower prescale value
PRESCALEH	.set	0x00		;8-bit upper prescale value
INT13_VECT	.set	0x00001A
TIMREGPG	.set	0xC00>>6

Fail    .byte    	"Fail " 	;define string, ASCII characters placed in memory as WORDS!
		.byte		0
Key1    .byte    	"1 MP-3: We are the Champions " 	;define string, ASCII characters placed in memory as WORDS!
		.byte		0
Key2    .byte    	"2 DVR: The Daily Show " 	;define string, ASCII characters placed in memory as WORDS!
		.byte		0
Key3    .byte    	"3 Audio Book: The Girl With the Dragon Tattoo " 	;define string, ASCII characters placed in memory as WORDS!
		.byte		0
Key4    .byte    	"4 DVR: Biggest Loser " 	;define string, ASCII characters placed in memory as WORDS!
		.byte		0
Key5    .byte    	"5 Blu-ray: The Sound of Music " 	;define string, ASCII characters placed in memory as WORDS!
		.byte		0
Key6    .byte    	"6 TV: Dancing with the Stars " 	;define string, ASCII characters placed in memory as WORDS!
		.byte		0		
Key7    .byte    	"7 DVD: Wall-E " 	;define string, ASCII characters placed in memory as WORDS!
		.byte		0		
Key8    .byte    	"8 DVR: Colbert Report " 	;define string, ASCII characters placed in memory as WORDS!
		.byte		0		
Key9    .byte    	"9 MP-3: Bohemian Rhapsody " 	;define string, ASCII characters placed in memory as WORDS!
		.byte		0	
Key0    .byte    	"0 MP-3: Born This Way " 	;define string, ASCII characters placed in memory as WORDS!
		.byte		0
		
			.global _c_int00	;This assembler directive allows _c_int00 to be a
								;global variable.
			.bss		results,256	;reserves 256 words at label 'results' in the .bss section	
;****************************************************************************************
.text	;program section, see the command linker file, program code
		;should be placed in the text section which starts at 0x9000

_c_int00:
	LC INIT_CPU			;initialize CPU (objmode, disable watchdog)
	LC INIT_ECAP
	LC INIT_OUTPUTS
	OR IER,#0x2000		;enable Timer interupts
	CLRC INTM			;enable global interrupts (by clearing the global interrupt mask)
	MOV AR4, #0xAFFF	; Sets a little coutner in memory
	MOV	*AR4, #10		; How many keys do you want to store
	INC AR4
	MOV AR1, #500		; Zeroes memory for debugging purposes
	MOV AR7, #0xB000	; Start of data location
	MOV AR6, #1			; ISR Clears this to stop
Zero:
	MOV *AR4, #0		; Zeroes 500 locations in memory
	INC AR4
	DEC AR1
	B poll, EQ
	B Zero, UNC
	
poll					; Wait for a key to be pressed since
	MOV	AR4, AR7		; I cannot figure out PIE interupts for the life of me
	MOV	AR2, #ECFLG		; Location of Flag
	
loop:
	MOV	AL, AR6			; AR6 is the bit the ISR sets when it goes off
	B	a100Reached, EQ	; If the ISR went off then reading that key is done
	MOV AL, *AR2
	SUB	AL, #2
	B skip, EQ
	B	loop, unc
skip:
	MOV	AR5, #CAP1		; Clears the ISR flag and moves the
	MOV	AL, *AR5		; Cap coutner value to memory
	MOV	*AR4, AL
	MOV	AR3, #ECCLR
	MOV *AR3, #3
	INC AR4
	LC INIT_TIMER2_INT	; Initiate a timer to see when there is radio silience
	B	loop, UNC


a100Reached:		; Waht happens when the whole set of pulses are read?
	MOV AL, AR7		; We increment the location and decrement the remaining keys!
	ADD	AL, #40
	MOV	AR7, AL		; Increments storage location
	INC AR6
	MOV	AR0, #0xAFFF
	DEC	*AR0		; Dec coutner
	B ReadT, EQ
	B poll, UNC

ReadT:				; Short for read time, beginning of second part of program
	MOV AR4, #0xAFFF	; Resets Key coutner
	MOV	*AR4, #10
	LC WriteKey		; Writes the 11th value so comparations can be done
	MOV AR7, #0xB001	; the first value read is always garbage since the program
	LC CompareLoop		; and eCap is doing delta mode.
	


WriteKey:				; Same as above routine but writes it into the 11th location
	MOV AR7, #0xB190	; where the compare function looks for vvalues to compare
	MOV	AR4, AR7
	MOV	AR2, #ECFLG
	
loopw:
	MOV	AL, AR6
	B	WriteEnd, EQ	
	MOV AL, *AR2
	SUB	AL, #2
	B skipw, EQ
	B	loopw, unc
skipw:
	MOV	AR5, #CAP1
	MOV	AL, *AR5
	MOV	*AR4, AL
	MOV	AR3, #ECCLR
	MOV *AR3, #3
	INC AR4
	LC INIT_TIMER2_INT
	B	loopw, UNC
	LRET
	
WriteEnd:
	LRET
		
CompareLoop:	
	MOV AR0, #40	; 40 possible locations
	MOV AR1, #37	; If 37 are good then that key was probably pressed
	MOV AR3, AR7	; AR7 as a pointer for where data should be read from
	MOV AR4, #0xB191	; b191 is where the 11th key was started off at
loopIN:
	MOV AL, *AR3	; Gets value from stored table
	MOV AH, *AR4	; Gets value from recent keypress
	INC AR4			; Incrememnt locations
	INC AR3
	AND AH, #0xFFC0	; Mask out the LSB bits from both tables
	AND AL, #0xFFC0
	DEC AR0
	B NotFound, EQ	; If all 40 have gone by and it has not been found yet then its not the eky
	SUB AL, AH		; If the 2 values were close to the same thenincrement the amoutn right
	B	INCREM, EQ
	B loopIN, UNC
INCREM:
	DEC AR1			; Increments the amount that was right
	B	Found, EQ	; Goes to found if there has been enough
	B loopIN, UNC
NotFound:			; Whoops Time to decrement the key array value
	PUSH AR4
	MOV AR4, #0xAFFF
	DEC	*AR4		; keeps a count of what key
	B FAILED, EQ	; If it does nto recognize a key then goes to fail routine
	POP AR4
	
	MOV AR6, #1

IncrementMemRead:
	MOV AL, AR7	; updates to next set of data
	ADD AL, #40
	MOV AR7, AL
	B CompareLoop, UNC
	
FAILED:				; Just displays a message that it failed
	LC Failed
	MOV AR6, #1
	MOV AR0, #GPATOGGLE
	MOV AL, #0x80
	B ReadT, UNC

Found:	
	MOV AR4, #0xAFFF		; Moves which key # was pressed to AH
	MOV AH, *AR4
	
	MOV AR6, #1				; TOggle a few LEDs to be cool
	MOV AR0, #GPATOGGLE
	MOV AL, #0x70
	MOV *AR0, AL	
	
	B Print, UNC		; Branch to next step
	
Print: ; Just runs through all the possible keys presses and branches to the needed KeyEvent
	MOV AR5, AH
	DEC AR5
	B Key9c, EQ
	DEC AR5
	B Key8c, EQ
	DEC AR5
	B Key7c, EQ
	DEC AR5
	B Key6c, EQ
	DEC AR5
	B Key5c, EQ
	DEC AR5
	B Key4c, EQ
	DEC AR5
	B Key3c, EQ
	DEC AR5
	B Key2c, EQ
	DEC AR5
	B Key1c, EQ
	DEC AR5
	B Key0c, EQ

Finish:
	B ReadT, UNC	

	
;***********************************************
; 				Key EVENTS					   *
;***********************************************
Failed:

	LC LCDINIT
	MOV AR0, #Fail	; AR0 is what passes the beginning of the string
	LC LCD_STRING
	LC INIT_TIMER2_INT
	MOV AR2, #0
	LC INIT_EPWM_REST	; Initializes the sound timer
	B Finish, UNC	

Key0c:

	LC LCDINIT
	MOV AR0, #Key0	; AR0 is what passes the beginning of the string
	LC LCD_STRING
	LC INIT_TIMER2_INT
	MOV AR2, #564
	LC INIT_EPWM_REST	; Initializes the sound timer
	B Finish, UNC	
	
Key1c:

	LC LCDINIT
	MOV AR0, #Key1	; AR0 is what passes the beginning of the string
	LC LCD_STRING
	LC INIT_TIMER2_INT
	MOV AR2, #949
	LC INIT_EPWM_REST	; Initializes the sound timer
	B Finish, UNC			
	
Key2c:
	LC LCDINIT
	MOV AR0, #Key2	
	LC LCD_STRING
	LC INIT_TIMER2_INT
	MOV AR2, #896
	LC INIT_EPWM_REST	; Initializes the sound timer
	B Finish, UNC	

Key3c:

	LC LCDINIT
	MOV AR0, #Key3	; AR0 is what passes the beginning of the string
	LC LCD_STRING
	LC INIT_TIMER2_INT
	MOV AR2, #846
	LC INIT_EPWM_REST	; Initializes the sound timer
	B Finish, UNC	

Key4c:

	LC LCDINIT
	MOV AR0, #Key4	; AR0 is what passes the beginning of the string
	LC LCD_STRING
	LC INIT_TIMER2_INT
	MOV AR2, #798
	LC INIT_EPWM_REST	; Initializes the sound timer
	B Finish, UNC	

Key5c:

	LC LCDINIT
	MOV AR0, #Key5	; AR0 is what passes the beginning of the string
	LC LCD_STRING
	LC INIT_TIMER2_INT
	MOV AR2, #753
	LC INIT_EPWM_REST	; Initializes the sound timer
	B Finish, UNC	

Key6c:

	LC LCDINIT
	MOV AR0, #Key6	; AR0 is what passes the beginning of the string
	LC LCD_STRING
	LC INIT_TIMER2_INT
	MOV AR2, #711
	LC INIT_EPWM_REST	; Initializes the sound timer
	B Finish, UNC	

Key7c:

	LC LCDINIT
	MOV AR0, #Key7	; AR0 is what passes the beginning of the string
	LC LCD_STRING
	LC INIT_TIMER2_INT
	MOV AR2, #671
	LC INIT_EPWM_REST	; Initializes the sound timer
	B Finish, UNC	

Key8c:

	LC LCDINIT
	MOV AR0, #Key8	; AR0 is what passes the beginning of the string
	LC LCD_STRING
	LC INIT_TIMER2_INT
	MOV AR2, #633
	LC INIT_EPWM_REST	; Initializes the sound timer
	B Finish, UNC	

Key9c:

	LC LCDINIT
	MOV AR0, #Key9	; AR0 is what passes the beginning of the string
	LC LCD_STRING
	LC INIT_TIMER2_INT
	MOV AR2, #599
	LC INIT_EPWM_REST	; Initializes the sound timer
	B Finish, UNC	
;***********************************************
; 				LCD STUFF					   *
;***********************************************

LCDINIT:
		; Initializations
		
	MOV		AR1, #GPAMUX2		; Sets to inputs/outputs
	MOV		AL, #0x000
	MOV		*AR1, AL
	
	MOV		AR1, #GPADIR+1		; Sets the pins to outputs
	MOV		AH, #111111b	
	MOV		*AR1, AH	
	
	MOV		AR1, #GPADAT+1 		; Do not use AR1 again while LCD writing
	
	MOV 	AH, #010011b
	MOV		*AR1, AH	
	LC		LCDDELAY
	MOV 	AH, #000011b
	MOV		*AR1, AH
	LC		LCDDELAY

	MOV 	AH, #010011b
	MOV		*AR1, AH
	LC		LCDDELAY
	MOV 	AH, #000011b
	MOV		*AR1, AH
	LC		LCDDELAY

	MOV 	AH, #010011b
	MOV		*AR1, AH
	LC		LCDDELAY	
	MOV 	AH, #000011b
	MOV		*AR1, AH
	LC		LCDDELAY

	MOV 	AH, #010010b
	MOV		*AR1, AH
	LC		LCDDELAY	
	MOV 	AH, #000010b
	MOV		*AR1, AH
	LC		LCDDELAY

	MOV 	AH, #010010b 
	MOV		*AR1, AH
	LC		LCDDELAY
	MOV 	AH, #000010b  	; 2 lines
	MOV		*AR1, AH
	LC		LCDDELAY
	MOV		AH, #011000b
	MOV		*AR1, AH
	LC		LCDDELAY
	MOV		AH, #001000b
	MOV		*AR1, AH
	LC		LCDDELAY
	
	MOV 	AH, #010000b 	; Display on; Cursor on, blink on
	MOV		*AR1, AH
	LC		LCDDELAY
	MOV 	AH, #000000b 	; Display on; Cursor on, blink on
	MOV		*AR1, AH
	LC		LCDDELAY
	MOV		AH, #011111b
	MOV		*AR1, AH
	LC		LCDDELAY
	MOV		AH, #001111b
	MOV		*AR1, AH
	LC		LCDDELAY
	
	MOV 	AH, #010000b
	MOV		*AR1, AH
	LC		LCDDELAY
	MOV 	AH, #000000b 	;Clear SCreen, Cursor home
	MOV		*AR1, AH
	LC		LCDDELAY
	MOV		AH, #010001b
	MOV		*AR1, AH
	LC		LCDDELAY
	MOV		AH, #000001b
	MOV		*AR1, AH
	LC		LCDDELAY
	
	LRET
	
	;<INITIALIZATION COMPLETE>;
	
LCD_STRING:
		
		MOV		AH, #0 ; this is where it breaks on me
loopL	MOV		AL, *AR0		; Mov Char to AL
		B		LCD_CHAR, NEQ	; If not null write the char
		LRET					; All done if there was a null char
		
LCD_CHAR:
		MOV		AL, *AR0	; points to the GPADAT
		LSR		AL, 4		; only gets the last 4 chars
		AND		AL, #1111b	; deletes everything else
		ADD		AL, #100000b ; Makes the enable low register data
		MOV		*AR1, AL	; Moves other nibble to LCD to write it
		ADD		AL, #10000b ;makes enable high register data
		MOV		*AR1, AL
		LC		LCDDELAY	
		
		
		MOV		AL, *AR0	; points to the CHAR
		AND		AL, #1111b	; only gets the first 4 chars
		ADD		AL, #100000b	; Makes the enable low and reg select high
		MOV		*AR1, AL	; Writes to GPADAT the first nibble
		ADD		AL, #010000b ; Clocks the enable
		MOV		*AR1, AL
		LC		LCDDELAY
		

		
		INC		AR0			;  updates to enxt char		
		B		loopL, UNC	; Goes back to string function		
		
LCDDELAY:
		MOV 	AL, #5000	; Small little for loop delay
loopd	DEC 	AL
		B	loopd, NEQ
		LRET	
INIT_TIMER2_INT:

	CLRC VMAP					; allows writing ISRdirectly to vector
	
	MOV	AR0, #TIMER1PRD+8		; sets period				
	MOV	*AR0, #PERIODL	
	MOV	AR0, #TIMER1PRDH+8						
	MOV	*AR0, #PERIODH							
	MOV	AR0, #TIMER1PR+8		; sets prescaler			
	MOV	*AR0, #0x0FFF	
	MOV	AR0, #TIMER1PRH+8						
	MOV	*AR0, #0					
	MOV	AR0, #TIMER1TCR+8		; enables timer			
	TSET	*AR0, #14				
	MOV	AR0, #TIMER1TCR+8		; loads prescaler and period			
	TSET	*AR0, #5				
								
	MOVL XAR0, #INT13_VECT+2	;need to load interrupt vector with isr address
	MOV *XAR0++, #TIMER2_ISR	;load lower byte (little endian)
	MOV *XAR0, #TIMER2_ISR>>16	;load upper byte							

	LRET
INIT_EPWM_REST:
	INC AR5
	MOV AR0, #PCLKCR1	; enables the epwm1 timers
	OR *AR0, #0x1

	MOV	AR0, #TBCTL	; sets all the needed ctrl registers for the epwm
	MOV	AR1, #0xC0B8	
	MOV	*AR0, AR1
	
	MOV AR0, #TBPRD		; sets the toggler frequency so you can play music
	MOV	AR1, AR2
	MOV	*AR0, AR1

	MOV AR0, #AQCTLA	; makes it so it toggles and when the counter gets to the period
	MOV	AR1, #0xC
	MOV	*AR0, AR1
	
	MOV AR0, #PCLKCR0	; Enables the TimerCLK for the epwm (also needs PCLKCCR1)
	OR *AR0, #0x4
	
;	MOV AR0, #CMPCTL	; Could never get the interupts working, but decided
;	MOV	AR1, #0x50		; it was not that important anyway so these are not needed
;	MOV	*AR0, AR1
	
;	MOV	AR0, #CMPB		; also for doing interupts
;	MOV	AR1, #0xF0F0
;	MOV	*AR0, AR1
	
	LRET	
TIMER2_ISR:

	MOV AR0, #PCLKCR1	; enables the epwm1 timers
	OR *AR0, #0x1

	MOV	AR0, #TBCTL	; sets all the needed ctrl registers for the epwm
	MOV	AR1, #0xC0B8	
	MOV	*AR0, AR1
	
	MOV AR0, #TBPRD		; sets the toggler frequency so you can play music
	MOV	AR1, #0
	MOV	*AR0, AR1

	MOV AR0, #AQCTLA	; makes it so it toggles and when the counter gets to the period
	MOV	AR1, #0xC
	MOV	*AR0, AR1
	
	MOV AR0, #PCLKCR0	; Enables the TimerCLK for the epwm (also needs PCLKCCR1)
	OR *AR0, #0x4
	
	MOV AR1, #GPATOGGLE			;load AR1 with address of GPIO0
	MOV *AR1, #8				;toggle  GPIO0
	
	MOV	AR6, #0
	
	MOV	AR0, #TIMER1TCR+8		; enables timer			
	TCLR	*AR0, #14	
	
	IRET	
	
INIT_CPU:
		EALLOW 						; Allow access to protected registers
		SETC 	OBJMODE 			; Allow 32 bit mov instructions
		SETC 	VMAP			; 
								; WDCR is watchdog timer control register
								; In constants section need to set WDCR=0x7029
		MOV 	AL,#1101000b 	; Disable the watchdog timer.
								; Must have 101 in bits 5, 4, 3 for
								; any writes to WDCR. 1 in bit 6
								; disables watchdog
		MOV 	AR1,#WDCR
		MOV		*AR1, AL 		; Disables watchdog timer
		LRET
INIT_ECAP:
	MOV AR0, #GPAMUX2+2	; Set GPIO 23 to ecap
	MOV	*AR0, #01b
	MOV AR0, #PCLKCR1	; Enable ecap clk
	TSET *AR0, #8
	MOV AR0, #ECCTL1	; Sets the bits to be rising/falling active low high
	MOV	*AR0, #0x8102 	
	MOV AR0, #ECCTL2
	MOV	*AR0, #0x90		;  	Sets up the baskgroudn stuff like parody and such
	LRET

DELAY:	; A polling delay just in case its needed
		MOV		AL, #0
loop10	MOV		AR3, #5
		MOV		AH,	#0	
		INC		AL
		SUB		@AR3,AL
		B		loop110, NEQ
		LRET
loop110	MOV		AR4, #40000
		INC		AH
		SUB		@AR4,AH
		B		loop110, NEQ
		B		loop10,UNC

INIT_OUTPUTS:
	PUSH AR0
	PUSH AR1
	MOV AR1,#GPAMUX1
	OR *AR1,#1
	MOV AR0,#11111111b		;set GPIO0 as an output
	MOV AR1,#GPADIR
	MOV *AR1,AR0
	POP AR1
	POP AR0
	LRET