;EE 476
;MIDI Sequencer
;Tareq Aryne
;Andy Pierson


; ******* WARNING!!!  EVERYTHING IS ACTIVE LOW!!! ************


.nolist
.include "8535def.inc"
.list


.def	save	=r1	; SREG temp reg

.def	temp	=r16	; crack is bad for your health
.def	memRead	=r17	; last value read from memory for the sequencer
.def	input	=r18	; Debounced input from Timer 0 ISR
.def	output	=r19	; Output to the Synthesizer processor
.def	itemp	=r20	; i temp, you jane
.def	state	=r21	; "memory" for the RX ISR, the MAGIC ISR
.def	button	=r22	; push button input
.def	mode	=r23	; operation mode (Play or Record)
.def	beatnum	=r24	; Measure number (1 - 8)
.def	beatL	=r28	; duration (in ticks) of a beat
.def	beatH	=r29	; (double precision)

; Set the baud rate in precompile time
;.equ clock = 8000000
.equ	clock	= 4000000
.equ	baud	= 31250
;.equ	baud	= ((clock/31250)-16)/16
.equ	rate	= clock/(16*baud) - 1


.equ	RAMSTART=0x60
.equ	RAMSTOP=RAMSTART + 127

;***** Initialization
.cseg
.org $0000
        rjmp	RESET		; RESET
	reti			; INT0
	reti			; INT1
	reti 			; TIMER2_COMP
	reti			; TIMER2_OVF
	reti			; TIMER1_CAPT
	rjmp	T1CompA		; TIMER1_COMPA
	reti			; TIMER1_COMPB
	reti			; TIMER1_OVF
	reti			; TIMER0_OVF
	reti			; SPI_STC
	reti			; UART_RX
	reti			; UART_UDRE
	reti			; UART_TX
	reti			; ADC
	reti			; EE_RDY
	reti			; ANA_COMP


RESET:
	;setup stack pointer
	ldi     temp, LOW(RAMEND)
	out     SPL, temp
	ldi     temp, HIGH(RAMEND)
	out     SPH, temp
	
;**** Port setup
	
	;set PortA for output to LCD and clear it
	ser	temp
	out	DDRA, temp
	clr	temp	
	out	PortA, temp

	;set PortB for output to LED's and turn them off
	ser	temp
	out	DDRB, temp
	out	PortB, temp
	
	;Set Port C for output to produce audio beat
	ldi	temp,0b11011111
	out	DDRC, temp
	clr	temp
	out	PortC, temp
	
	;Set PortD to be all inputs with pullups for push buttons
	clr	temp
	out	DDRD, temp
	ser	temp
	out	PORTD,temp
	
;******	Setup Timer 1 for interrupt and reset on compare match A at Clk/64

        ldi     temp, 0b00001011
        out     TCCR1B, temp

	;beat ticks every
	ldi	temp, high(10000)
	mov	beatL,temp
	ldi	temp, low(10000)
	mov	beatH, temp

	mov	temp, beatH
	out	OCR1AH, temp
	mov	temp, beatL
	out	OCR1AL, temp

	ldi	temp,0b00010000
	out	TIMSK,temp


;***** Initialize the RAM
	clr	ZH
	ldi	ZL, RAMSTART
clear: 
	ldi	temp,0xff
	st	Z+,temp
	cpi	ZL,low(RAMSTOP)
	brne	clear
	cpi	ZH,high(RAMSTOP)
	brne	clear
	
	ldi	ZH,high(RAMSTART)
	ldi	ZL, low(RAMSTART)

	;Start in Play mode
	ldi	mode,0b10000000
	;Start in Beat 1
	ldi	beatnum,1
	;Start with no buttons pushed and no input
	ser	state
	ser	input
	
	sei
	
;***** Main Loop
	
HandShake:
	sbis	PinC,5
	rjmp	HandShake

	mov	output,memread
	com	output
	andi	output,0b11011111
	out	PortC,output
	rjmp	Handshake

;***** Timer 1 Compare Match A handler
T1CompA:
	in	save, SREG
	push	temp



	in	itemp,PIND
	mov	temp,itemp
	mov	input,itemp
	com	input
	and	input,state
	com	input

	mov	state,itemp	;update the state


	mov	button,input
;	in	button,PIND

	;PD 7 means go to play
	sbrs	button, 7
	ldi	mode, 0b10000000
	;PD 6 means go to Record
	sbrs	button, 6
	ldi	mode, 0b01000000

	sbrc	button, 5
	rjmp	BeatUp
	ldi	itemp,1
	add	beatH,itemp
	out	OCR1AH,beatH
	out	OCR1AL,beatL
	rjmp	BeatDone
BeatUp:
	sbrc	button,4
	rjmp	BeatDone
	sbci	beatH,1
	out	OCR1AH,beatH
	out	OCR1AL,beatL

BeatDone:
	ld 	memRead,Z
	;Disable the upper nible because we only have four sounds
	ori	button,0xF0
	;Combine the input with the memory value
	and	memRead,button
	out	PortB,memRead

	mov	temp,ZL
	andi	temp,0b00001111
	cpi	temp,0b00001000
	brne	NextLB

	cpi	beatnum,1
	brne	chk2
	inc	beatnum
	ldi	temp,0b10010001
	rjmp	Print

chk2:	cpi	beatnum,2
	brne	chk3
	inc	beatnum
	ldi	temp,0b01101011
	rjmp	Print

chk3:	cpi	beatnum,3
	brne	chk4
	inc	beatnum
	ldi	temp,0b00111011
	rjmp	Print

chk4:	cpi	beatnum,4
	brne	chk5
	inc	beatnum
	ldi	temp,0b00011101
	rjmp	Print

chk5:	cpi	beatnum,5
	brne	chk6
	inc	beatnum
	ldi	temp,0b00111110
	rjmp	Print

chk6:	cpi	beatnum,6
	brne	chk7
	inc	beatnum
	ldi	temp,0b01111110
	rjmp	Print

chk7:	cpi	beatnum,7
	brne	chk8
	inc	beatnum
	ldi	temp,0b00010011
	rjmp	Print

chk8:	cpi	beatnum,8
	brne	Print
	ldi	beatnum,1
	ldi	temp,0b01111111
Print:
	out	PortA,temp
NextLB:
	;toggle beat LED beat number display
	ldi	temp,0b00001000
	and	temp,ZL
	breq	NextLED
	sbi	PortA,7
	cbi	PortB,4
	
NextLED:

	sbrc	mode,7
	adiw	ZL,1
	sbrc	mode,7
	cbi	PortB, 7
	sbrc	mode,6
	st	Z+,memRead
	sbrc	mode,6
	cbi	PortB, 6

	rcall	CheckZ

	pop	temp
	out	SREG, save
        reti                    ;back to backgound tasks

CheckZ:
	;check if we have overflown the RAM
	cpi	ZL,low(RAMSTOP)
	brne	CheckEnd
	cpi	ZH,high(RAMSTOP)
	brne	CheckEnd

	ldi	ZH,high(RAMSTART)
	ldi	ZL,low(RAMSTART)
CheckEnd:
	ret