;
; copypasteetc.inc: copies patterns and instruments
;                   to copy buffer and vice versa,
;                   rols and rors, randomizes etc
;
; author: Marko Kanala, raato ]a t[ mulletronic.com

; copies active pattern to the copy buffer
;
; note: disables timer2 interrupt to allow the use of FSR0
;
; 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).
;

copy_patt_to_buf:
	; disable timer 2 irq
	bcf		PIE1, TMR2IE
	LOADPATTOFSR	1, 0
	lfsr	FSR0, pattcopybuffer
	movlw	PATTERN_HALF_SIZE
	movwf	temp
copy_patt_to_buf_loop:
	movff	POSTINC1, POSTINC0
	decfsz	temp
	bra		copy_patt_to_buf_loop	
	; enable timer 2 irq
	bsf		PIE1, TMR2IE
	return

; copies copy buffer to the active pattern
;
; note: disables timer2 interrupt to allow the use of FSR0
copy_buf_to_patt:
	; disable timer 2 irq
	bcf		PIE1, TMR2IE
	LOADPATTOFSR	1, 0
	lfsr	FSR0, pattcopybuffer
	movlw	PATTERN_HALF_SIZE
	movwf	temp
copy_buf_to_patt_loop:
	movff	POSTINC0, POSTINC1
	decfsz	temp
	bra		copy_buf_to_patt_loop	
	; enable timer 2 irq
	bsf		PIE1, TMR2IE
	return

; copies active instrument to copy buffer
;
; note: disables timer2 interrupt to allow the use of FSR0
copy_instr_to_buf:
	LOADFSR1_CURRENTTRIGGERROW
	; disable timer 2 irq
	bcf		PIE1, TMR2IE
	lfsr	FSR0, instrcopybuffer
	movff	POSTINC1, POSTINC0 	; first 8 triggers
	movff	POSTINC1, POSTINC0 	; last 8 triggers
	movlw	INSTR_ACCENT
	cpfseq	selectedinst
	bra		copy_instr_to_buf_notacc
	; accent, no accents or flams
	clrf	POSTINC0			; just clear instr accents
	clrf	POSTINC0
	clrf	POSTINC0			; and flams
	clrf	POSTINC0
	bra		copy_instr_to_buf_skip_acc
copy_instr_to_buf_notacc:
	; not accent
	movlw	PAT_ACCENTS - PAT_TRIGS - 2
	addwf	FSR1L
	movff	POSTINC1, POSTINC0	; first 8 accents
	movff	POSTINC1, POSTINC0	; last 8 accents
	movlw	PAT_FLAMS - PAT_ACCENTS - 2
	addwf	FSR1L
	movff	POSTINC1, POSTINC0	; first 8 flams
	movff	POSTINC1, POSTINC0	; last 8 flams
copy_instr_to_buf_skip_acc:
	INSTRLENGTHTOW 1, temp
	movwf	INDF0				; length
	; enable timer 2 irq
	bsf		PIE1, TMR2IE
	return

; copies copy buffer to active instrument
;
; note: disables timer2 interrupt to allow the use of FSR0
copy_buf_to_instr:
	LOADFSR1_CURRENTTRIGGERROW
	; disable timer 2 irq
	bcf		PIE1, TMR2IE
	lfsr	FSR0, instrcopybuffer
	movff	POSTINC0, POSTINC1 	; first 8 triggers
	movff	POSTINC0, POSTINC1 	; last 8 triggers
	movlw	INSTR_ACCENT
	cpfseq	selectedinst
	bra		copy_buf_to_instr_notacc
	; accent dest, no accents or flams
	movlw	4
	addwf	FSR0L
	movlw	PAT_LENGTHS - PAT_TRIGS - 2
	bra		copy_buf_to_instr_skip_acc
copy_buf_to_instr_notacc:
	; not accent
	movlw	PAT_ACCENTS - PAT_TRIGS - 2
	addwf	FSR1L
	movff	POSTINC0, POSTINC1	; first 8 accents
	movff	POSTINC0, POSTINC1	; last 8 accents
	movlw	PAT_FLAMS - PAT_ACCENTS - 2
	addwf	FSR1L
	movff	POSTINC0, POSTINC1	; first 8 flams
	movff	POSTINC0, POSTINC1	; last 8 flams
	movlw	PAT_LENGTHS - PAT_FLAMS - 2
copy_buf_to_instr_skip_acc:
	addwf	FSR1L
	movff	INDF0, temp			; temp = instr last step
	; store the instr last step to selected instr
	; hoax hoax, takes space but but ... we have space
	
	; FSR1 should point to PAT_LENGTHS
	btfss	selectedinst, 0
	bra		cbti_even
	; odd instrument => store to lsb nybble
	bcf		STATUS, C
	rrcf	selectedinst, W			; instrument / 2
	addwf	FSR1L					; select correct patt reg
	movlw	0xf0
	andwf	INDF1, W				; XXXX0000
	iorwf	temp, W					; XXXXLLLL
	movwf	INDF1					; store
	bra		cbti_done	
cbti_even:
	; even instrument => store to msb nybble
	bcf		STATUS, C
	rrcf	selectedinst, W			; instrument / 2
	addwf	FSR1L					; select correct patt reg
	swapf	temp					; LLLL0000
	movlw	0x0f
	andwf	INDF1, W				; 0000XXXX
	iorwf	temp, W					; LLLLXXXX
	movwf	INDF1					; store
cbti_done:
	; enable timer 2 irq
	bsf		PIE1, TMR2IE
	return

; "randomizes" current instrument triggers
randomize_instr:
	; TODO: better randomizer ?
	movf	TMR1L, W
	mulwf	TMR1H
	LOADFSR1_CURRENTTRIGGERROW
	movff	PRODH, POSTINC1
	movff	PRODL, INDF1
	return

; rotates the triggers, accents and flams
;  of the current instrument left
;  "bit-wise"
; note: instrument length is not used here by design
rotate_instr_trigs_left:
	LOADFSR1_CURRENTTRIGGERROW
	call	rol_2_bytes_fsr1			; triggers
	movlw	INSTR_ACCENT
	cpfslt	selectedinst
	return
	movlw	PAT_ACCENTS - PAT_TRIGS - 2
	addwf	FSR1L
	call	rol_2_bytes_fsr1			; accents
	movlw	PAT_FLAMS - PAT_ACCENTS - 2
	addwf	FSR1L
	call	rol_2_bytes_fsr1			; flams
	return

; rotates the triggers, accents and flams
;  of the current instrument right
;  "bit-wise"
; note: instrument length is not used here by design
rotate_instr_trigs_right:
	LOADFSR1_CURRENTTRIGGERROW
	call	ror_2_bytes_fsr1
	movlw	INSTR_ACCENT
	cpfslt	selectedinst
	return
	movlw	PAT_ACCENTS - PAT_TRIGS - 2
	addwf	FSR1L
	call	ror_2_bytes_fsr1			; accents
	movlw	PAT_FLAMS - PAT_ACCENTS - 2
	addwf	FSR1L
	call	ror_2_bytes_fsr1			; flams
	return

; rotates the triggers, accents and flams of the
; pattern left "bit-wise"
; note: pattern or instruments lengths are not used here
;       by design
rotate_pattern_left:
	LOADPATTOFSR	1, PAT_TRIGS
	movlw	12 + 11 + 11			; triggers, accents and flams
	movwf	temp
rotate_pattern_left_loop:
	call	rol_2_bytes_fsr1		; in
	decfsz	temp
	bra		rotate_pattern_left_loop
	return

; rotates the triggers, accents and flams of the
; pattern right "bit-wise"
; note: pattern or instruments lengths are not used here
;       by design
rotate_pattern_right:
	LOADPATTOFSR	1, PAT_TRIGS
	movlw	12 + 11 + 11			; triggers, accents and flams
	movwf	temp
rotate_pattern_right_loop:
	call	ror_2_bytes_fsr1		; in
	decfsz	temp
	bra		rotate_pattern_right_loop
	return

; rotates 2 bytes right bit-wise in FSR1
ror_2_bytes_fsr1:
	bcf		STATUS, C
	rrcf	POSTINC1				; 0 8 7 6 5 4 3 2 , c = 1
	rrcf	POSTDEC1, W				; 1 8_7_6_5_4_3_2_, c = 1_
	btfsc	STATUS, C
	bsf		INDF1, 7					
	movwf	PREINC1					; 1_8 7 6 5 4 3 2
	movf	POSTINC1, W				; FSR1 + 1
	return

; rotates 2 bytes left bit-wise in FSR1
rol_2_bytes_fsr1:
	bcf		STATUS, C
	rlcf	POSTINC1				; 7 6 5 4 3 2 1 0 , c = 8
	rlcf	POSTDEC1, W				; 7_6_5_4_3_2_1_8 , c = 8_
	btfsc	STATUS, C
	bsf		INDF1, 0
	movwf	PREINC1					; 7 6 5 4 3 2 1 8_
	movf	POSTINC1, W				; FSR1 + 1
	return

External Labels :

rol_2_bytes_fsr1
ror_2_bytes_fsr1