/*
 * System Timer Utility
 *
 * org: 6/28/2014
 * rev: 9/02/2014
 * auth: Nels "Chip" Pearson
 *
 * Target: I2C Demo Board w/ display and keypad I/O, 20MHz
 *
 * Usage:
 * 	.include sys_timers.asm
 *
 */ 

// Add specific labels here for time tic flag consumption.
// NOTE: For more or fewer flags, adj code in st_tmr0_intr() and comments here.
;
; 1ms tic flags
.equ	DELAY_1MS_TIC	= GPIOR00		; General purpose 1ms delay tic
.equ	MS_1MS_TIC		= GPIOR01		; Master Service 1ms TIC
.equ	I2C_10MS_TIC				= GPIOR02		; 
;.equ					= GPIOR03		; 
; 10ms tic flags
.equ	SWITCH_10MS_TIC	= GPIOR04		;
.equ	KP_DS_SW_10MS	= GPIOR05		; KeyPad, Display, and Switch
.equ	LED_10MS_TIC	= GPIOR06		; LED service
.equ	MS_10MS_TIC		= GPIOR07		; Master Service 10ms TIC

.equ	SLOW_TIC		= 5			; 1ms * N for the slow tic

.DSEG
st_cnt_10ms:		.BYTE	1			; secondary timer counter.

.CSEG
/*
 * Set up Timer0 to generate System Time Tic for 1 ms using 20MHz CPU clock
 * Call this once after RESET.
 *
 * Modifies: OCR0A, TCCR0A, TIMSK0, TCCR0B, and GPIOR0
 *
 * input reg:	none
 * output reg:	none
 * resources:	R16
 *
 * NOTE: Approx 1ms .. 2.4% error
 */
st_init_tmr0:
	ldi		R16, 79				; 2 * 256 * (1 + OCR0A) : 512 * (40*2) : 1024 * 20 * 2
	out		OCR0A, R16
	ldi		R16, (1<<WGM01)
	out		TCCR0A, R16
	ldi		R16, (1<<OCIE0A)
	sts		TIMSK0, R16			; enable counter 0 OCO intr
;
	ldi		R16, 0b100			; CPU div 256
	out		TCCR0B, R16
;
	ldi		R16, SLOW_TIC		; set for 10ms count.
	sts		st_cnt_10ms, R16
;
	clr		R16
	sts		GPIOR0, R16			; clear all tic flags
;
	ret

/*
 * Set up Timer1 for ADC Trigger and Tone Gen at 125us using 20MHz CPU clock
 * Call this once after RESET.
 * ADC used CTC-B
 * Tone Gen used CTC-A interrupt service
 *
 * Modifies: OCR1A, OCR1B, TCCR1A, TCCR1B, and TIMSK1
 *
 * input reg:	none
 * output reg:	none
 * resources:	R16
 *
 * NOTE: Other values are provided for different clock rates.
 */
st_init_tmr1:
;	clr		R16				; 0    .. 1 MHz
;	ldi		R16, 3				; 768  .. 8 MHz CPU
	ldi		R16, 9				; 2304 .. 20 MHz CPU
	sts		OCR1AH, R16
	sts		OCR1BH, R16
;	ldi		R16, 62			; 2 * n * (1+62) = 126 us..1 MHz CPU
;	ldi		R16, 231			; 2 * n * (1+768+231) = 125 us..8 MHz CPU
	ldi		R16, 155			; 2 * n * (1+2304+155) = 125 us..20 MHz CPU
	sts		OCR1AL, R16
	sts		OCR1BL, R16
;
	clr		R16
	sts		TCCR1A, R16		; WGM11:0 = 00 for CTC
;
	ldi		R16, 0b00001001	; WGM13:2 = 01, CPU div 1 = 1 us
	sts		TCCR1B, R16
;
	ldi		R16, (1<<OCIE1B)
	sts		TIMSK1, R16
;
	ret

/*
 * Timer0 CTC (compare) interrupt service.
 * Called each 1ms
 *
 * input reg:	none
 * output reg:	none
 * resources:	GPIOR0.GPIR00:7
 * 				SRAM	1 byte
 *				Stack:3
 *
 */
st_tmr0_intr:
; Save SREG
	push	R0
	in		R0, SREG
	push	R0
;
	push	R16
; tic1ms flags
	sbi		GPIOR0, GPIOR00		;
	sbi		GPIOR0, GPIOR01		; 
	sbi		GPIOR0, GPIOR02		; 
	sbi		GPIOR0, GPIOR03		;
;
	lds		R16, st_cnt_10ms	; get counter
	dec		R16
	brne	st_skip00
	ldi		R16, SLOW_TIC		; reload 10ms count down.
; tic10ms flags
	sbi		GPIOR0, GPIOR04		; 
	sbi		GPIOR0, GPIOR05		;
	sbi		GPIOR0, GPIOR06		; 
	sbi		GPIOR0, GPIOR07		;
;
st_skip00:
	sts		st_cnt_10ms, R16	; update
	pop		R16
; Restore SREG
	pop		R0
	out		SREG, R0
	pop		R0
;
	reti
