;
; startupinit.inc: initialize the application & pic
;
; author: Marko Kanala, raato ]a t[ mulletronic.com
;
; LICENSE
; Creative Commons Attribution-NonCommercial-ShareALike 2.5
;
; You are free:
;
; * to copy, distribute, display, and perform the work
; * to make derivative works
;
; Under the following conditions:
;	
; 1. Attribution. You must attribute the work in the manner specified by the 
;    author or licensor.
; 2. Noncommercial. You may not use this work for commercial purposes.
; 3. Share Alike. If you alter, transform, or build upon this work, you may 
;    distribute the resulting work only under a license identical to this one.
;
; * For any reuse or distribution, you must make clear to others the license 
;   terms of this work.
; * Any of these conditions can be waived if you get permission from the 
;   copyright holder.
;
; Your fair use and other rights are in no way affected by the above.
;
; This is a human-readable summary of the Legal Code.
; See full license at http://creativecommons.org/licenses/by-nc-sa/2.5/legalcode
;
; Copyright: Marko Kanala (raato@mulletronic.com).
;

startupinit:

; MEMORY -->

	clrf	sysexstatus
	movlw	-1
	movwf	sysexcounter

	clrf	led_counter
	movlw	12
	movwf	led_scaler

	movlw	blink_speed	
	movwf	blink_counter
	movlw	blink_speed2
	movwf	blink_counter2
	clrf	blink
	clrf	blink_tempo

	clrf	chainshowpos
	clrf	chainposition
	clrf	chainshowblink
	; fill chainbuffer with -1
	movlw	16
	movwf	temp
	movlw	-1
	lfsr	FSR1, chainbuffer
init_fillchain:
	movwf	POSTINC1
	decfsz	temp
	bra		init_fillchain

	clrf	keypress
	clrf	last_key
	clrf	irq_key
	clrf	downkeys
	clrf	event
	clrf	bpmtick
	clrf	bpmscaler
	movlw	1
	movwf	currentstep
	movwf	currentstep_bdrum
	movwf	currentstep_sdrum
	movwf	currentstep_ltom
	movwf	currentstep_mtom
	movwf	currentstep_htom
	movwf	currentstep_rshot
	movwf	currentstep_hclap
	movwf	currentstep_chihat
	movwf	currentstep_ohihat
	movwf	currentstep_crash
	movwf	currentstep_ride
	movwf	currentstep_accent

;	movlw	1 << set_mode_on_start
;	movwf	mode
	clrf	mode
	movlw	set_instr_on_start		; bd selected by default
	movwf	selectedinst
	clrf	currentdisplay
	clrf	lastdisplay
	clrf	display_arg

	clrf	currentshuffle
	movlw	16				; 1 - 16
	movwf	currentlength

	clrf	leds_busa_1
	clrf	leds_busa_2
	clrf	leds_busb_1
	clrf	leds_busb_2

	clrf	lcdwait

	clrf	currenttrack
	clrf	currentmeasure
	clrf	currentmeasure + 1

	clrf	nextmeasure
	clrf	nextmeasure + 1

	clrf	currenttracklen
	clrf	currenttracklen + 1
	clrf	currentrepeat

	clrf	downkeypresses

;	clrf	midi_in_buffer
;	clrf	midi_in_buffer_note
;	clrf	midi_in_buffer_vel

; PORTS -->	
	; port a, inputs: ra0, ra1, ra5
	movlw	b'00100011'
	movwf	TRISA
	clrf	PORTA

	; port b, inputs: -
	clrf	TRISB
	clrf	PORTB
	clrf	LATB

	; port c, inputs: rc1, rc2, rc7
	;                 SCA & SCL for i2c bus
	movlw	b'10011110'
	movwf	TRISC
	clrf	PORTC

	; port d, inputs: -
	clrf	TRISD
	clrf	PORTD
	clrf	LATD

	; port e, inputs: -
	clrf	TRISE
	clrf	PORTE
	clrf	LATE

	; A/D left justified,
	;  A/D clock = internal RC osc,
	;  AN0 == analog, 
	;   VREF+ = Vdd,
	;   VREF- = Vss
	movlw	b'00001110'
  	movwf	ADCON1

	; A/D clock = internal RC osc, 
	;  channel = AN0, 
	;  converter on
	movlw	b'11000001'
	movwf	ADCON0

	bcf		PORT_LCD_EN, LCD_EN_PIN
	; inhibit trigger muxes
	bsf		TRIGMUXINH_PORT, TRIGMUXINH_PIN
	; latches low to wait for clock pulse
	bcf		TRIGLATCHA_PORT, TRIGLATCHA_PIN	
	bcf		TRIGLATCHB_PORT, TRIGLATCHB_PIN
	; clear triggers
	clrf	PORT_TRIG
	nop
	nop
	nop
	; latch triggers
	bsf		TRIGLATCHA_PORT, TRIGLATCHA_PIN	
	bsf		TRIGLATCHB_PORT, TRIGLATCHB_PIN

; I2C BUS -->
	call	i2c_init

; LCD -->
	call	lcd_init
	
; TIMERS -->
; 40mhz Fosc => cycle = 40mhz / 4 == 100ns == 0.1us == 0.0001ms

	; timer 0: din sync clock width timer
	;          sets the din trigger off
	movlw	b'00001000'		; no prescaler, disabled, 
							; 16-bit timer, internal clock
	movwf	T0CON
	; timer 1: bpm timer
	;  8-bit operation, 1:8 prescaler, osc off, 
	;  timer enabled, increments every intr. cycle,
	;  generates interrupt every 65536th cycle
	; 
	; 65536 * 8 * 0.0001ms == 52,4288ms
    ; db 0xd1, 0x0d ; 130.0bpm
	movlw	0xd1
	movwf	TMR1H
	movlw	0x0d
	movwf	TMR1L

    movlw	b'00110001' 
    movwf   T1CON

	; timer 2: keys / led multiplexing timer
	;  8-bit oper., 1:2 postscaler, timer enabled, 
	;  1:16 prescaler, period = 20
	;
	; 20 * 2 * 16 * 0.0001ms ~= 0.064ms period
	; every ~670 cycles :)
	movlw	b'00001110'		; pre 1:2, post 1:16
    movwf   T2CON
    movlw  	20
    movwf  	PR2

	; timer 3: 2ms delay timer for trigger pulses
	; note: this timer is enabled on demand
	; see 9090.inc
	movlw	b'00000000'		; pre 1:1, disabled
	movwf	T3CON

; CCP1

	; capture mode, every rising edge of RC2 triggers CCP1 interrupt
	movlw	b'00000101'
	movwf	CCP1CON

; INTERRUPTS -->

	; enable irq priority levels
	movlw	(1 << IPEN)
	movwf	RCON

	; usart receive, timer 1, timer 3 and CCP1IP as high priority,
	;  timer 2, adcon etc. as low priority
	movlw	(1 << RCIP) | (1 << TMR1IP) | (1 << CCP1IP) 
	movwf	IPR1
	movlw	(1 << TMR3IP)
	movwf	IPR2

	; clear irqs
	clrf	PIR1
	clrf	PIR2

	; enable USART receive and 
	;  timer 1 & 2 & 3 irqs and
	;  a/d converter irq and
	;  CCP1 irq
	movlw   (1 << RCIE) | (1 << TMR1IE) | (1 << TMR2IE) | (1 << ADIE) | (1 << CCP1IE)
 	movwf   PIE1
;	bcf		PIE1, TXIE
	movlw	(1 << TMR3IE)
	movwf	PIE2

  	; set baudrate to 31250 baud (midi)
	movlw	(1 << TXEN)			
  	movwf	TXSTA
  	movlw	2 * 0x0a - 1
  	movwf	SPBRG

  	; configure receive status and control register
  	movlw	(1 << SPEN) | (1 << CREN)
  	movwf	RCSTA

  	; make sure that USART receive buffer is empty
  	bcf     RCSTA, CREN
  	movf    RCREG, W
  	bsf     RCSTA, CREN
	
	; timer 0 overflow as low priority
	bcf		INTCON2, TMR0IP

  	; enable maskable IRQs (and timer 0 overflow)
  	movlw   (1 << GIE) | (1 << PEIE) | (1 << TMR0IE)
  	movwf   INTCON

; A/D Converter -->

	; starts the first conversion
	call	ad_start
	; print out the intro texts
	call	startupinit_intro
	; check if start button is pressed at the
	;  startup => if so ask for flash initialization
	call	check_startup_reset

	; load settings from flash
	call	s_load_settings

	; select a bank & pattern at startup
	movlw	set_bank_on_start
	movwf	currentbank
	movwf	nextbank
	movlw	set_patt_on_start
	movwf	currentpattern
	movwf	nextpattern

	; load pattern
	call	i2c_flash_read

	; load track
	call	i2c_flash_read_trackmeta
	; and first measure
	call	i2c_flash_read_measure
startupinit_end:
	return

;
; prints out the introduction text
;  to lcd and flashes leds
;
startupinit_intro:
	call	lcd_clear
	movlw	15
	movwf	temp
startupinit_intro_loop:
	TABLE_ADDR	text_welcome
	movf	temp, W
	call	lcd_send_text_posw
	TABLE_ADDR	text_welcome2
	movf	temp, W
	addlw	LCD_LINE2
	call	lcd_send_text_posw
	movlw	version_major
	call	lcd_send_char
	movlw	"."
	call	lcd_send_char
	movlw	version_minor
	call	lcd_send_char
	call	lcd_delay15ms
	call	lcd_delay15ms
	call	lcd_delay15ms
	decf	temp
	bnn		startupinit_intro_loop
	call	startupinit_introdelay
	return

startupinit_introdelay:
	clrf	lcd_delay_z
startupinit_ldelay_long_loop:
	; ~12ms delay
	movlw	112
	call	lcd_delay_custom
	decfsz	lcd_delay_z
	bra 	startupinit_ldelay_long_loop
	return


External Labels :

i2c_init
lcd_init
ad_start
startupinit_intro
check_startup_reset
s_load_settings
i2c_flash_read
i2c_flash_read_trackmeta
i2c_flash_read_measure
lcd_clear
lcd_send_text_posw
lcd_send_char
lcd_delay15ms
startupinit_introdelay
lcd_delay_custom