;
; mode_traplay.inc: handles track play mode
;
; author: Marko Kanala, raato ]a t[ mulletronic.com
;
; Play mode:
;
; T01:my demo song
; 001/003:A02 x2
;
; Edit mode:
;
; Edit T01 001/002
; A02: pattern x2
;
;
; 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).
;
; called when the track play mode is entered
mode_trackplay_enter:
SETDISPLAY s_tp_main ; see lcd.inc
; load first measure
call i2c_flash_read_measure
CLEARMODE MODE_FILL
CLEARMODE MODE_CHAIN
return
; called in continuous loop when in track play mode
mode_trackplay:
; if the last step of the pattern has been
; reached read the next pattern from the
; flash memory if needed
IFEVENTCALL EVENT_LASTSTEP, tp_handleflash
; refresh lcd display if needed
call lcd_refresh
; do we have key events ?
IFNOEVENT EVENT_KEY, tp_no_keyevents
; starts the sequencer
KEYEVENT KEY_START, tp_start
; stops or continues the sequencer
KEYEVENT KEY_STOPCONT, tp_stopcont
; trigger a fill
KEYEVENT KEY_ENTER, tp_fill
; KEYEVENT KEY_S1, tp_stepkey
; KEYEVENT KEY_S2, tp_stepkey
; KEYEVENT KEY_S3, tp_stepkey
; KEYEVENT KEY_S4, tp_stepkey
; KEYEVENT KEY_S5, tp_stepkey
; KEYEVENT KEY_S6, tp_stepkey
; KEYEVENT KEY_S7, tp_stepkey
; KEYEVENT KEY_S8, tp_stepkey
; KEYEVENT KEY_S9, tp_stepkey
; KEYEVENT KEY_S10, tp_stepkey
; KEYEVENT KEY_S11, tp_stepkey
; KEYEVENT KEY_S12, tp_stepkey
; KEYEVENT KEY_S13, tp_stepkey
; KEYEVENT KEY_S14, tp_stepkey
; KEYEVENT KEY_S15, tp_stepkey
; KEYEVENT KEY_S16, tp_stepkey
STEPKEYEVENT tp_stepkey
KEYEVENT KEY_SCALE, tp_nextmeasure
KEYEVENT KEY_PATTPLAYWRITE, tp_pattplaywrite
KEYEVENT KEY_TRACKPLAYWRITE, tp_trackplaywrite
tp_no_keyevents:
; no specific keyevents, check for downkeys
; hoax to generate a key events from downkeys
IFKEYNOTDOWN DOWNKEY_LASTSTEP, tp_laststeplifted
IFKEYDOWN DOWNKEY_LASTSTEP, tp_laststeppressed
tp_laststepchecked:
tp_no_downkeys:
; no keyevents and no downkeys, all keys up
; set default display
SETDISPLAY s_tp_main
call tp_refreshleds
; call lcd_refreshbpm
return
; all keyhandlers should call this afterwards
tp_keydone:
call tp_refreshleds
tp_keydone_keepleds:
CLEAREVENT EVENT_KEY
return
; called when laststep downkey is pressed
tp_laststeppressed:
; call tp_prevmeasure only, if the laststep downkey
; was lifted before
btfsc downkeypresses, DOWNKEY_LASTSTEP
bra tp_laststepchecked
bsf downkeypresses, DOWNKEY_LASTSTEP
bra tp_prevmeasure
; called when laststep downkey is not pressed
tp_laststeplifted:
bcf downkeypresses, DOWNKEY_LASTSTEP
bra tp_laststepchecked
; lights up the led for selected track
tp_refreshleds:
movlw 1<<LED_START ; preserve start-led
andwf LEDREG_START ; and clear bus b
clrf leds_busb_2
movlw 8
cpfslt currenttrack
bra tp_refreshleds_upper
movf currenttrack, W
call get_bit
movwf leds_temp_1
clrf leds_temp_2
IFRUNNING tp_refreshleds_running
bra tp_refreshleds_write
tp_refreshleds_upper:
subwf currenttrack, W
call get_bit
clrf leds_temp_1
movwf leds_temp_2
IFRUNNING tp_refreshleds_running
bra tp_refreshleds_write
tp_refreshleds_running:
movf currentstep, W ; if currentstep is 0
bz tp_refreshleds_write ; skip the xor
movlw -9
addwf currentstep, W ; W = currentstep - 9
bn tp_r_lower_ledbus
; over 8, upper ledbus, W ok (0 - 7)
call get_bit
xorwf leds_temp_2 ; leds XOR currentstep
bra tp_refreshleds_write
tp_r_lower_ledbus:
addlw 8 ; W = currentstep - 1
call get_bit
xorwf leds_temp_1
tp_refreshleds_write:
movff leds_temp_1, leds_busa_1
movff leds_temp_2, leds_busa_2
return
; switches between track play and -write modes
tp_trackplaywrite:
SETMODE MODE_TWRITE
CLEARMODE MODE_TPLAY
call mode_trackwrite_enter
bra tp_keydone_keepleds
; switches between pattern play and -write modes
tp_pattplaywrite:
SETMODE MODE_PPLAY
CLEARMODE MODE_TPLAY
call mode_pattplay_enter
bra tp_keydone_keepleds
; changes the current track
tp_stepkey:
IFRUNNING tp_keydone ; only allow the change when stopped
movlw 16
movwf temp
decf keypress, W
bn tp_keydone ; accept only keys 0 ...
cpfsgt temp
bra tp_keydone ; to 15
FORCEDISPLAYREFRESH
movwf currenttrack
CLRF16 currentmeasure
CLRF16 nextmeasure
clrf currentrepeat
; fetch track name and length
call i2c_flash_read_trackmeta
; fetch first measure
call i2c_flash_read_measure
bra tp_keydone
; moves to prev measure if stopped
tp_prevmeasure:
IFRUNNING tp_keydone
; check if we can go back one step
tstfsz nextmeasure ; xx__ == 0
bra tp_prevmeasure_dec
tstfsz nextmeasure + 1 ; __xx == 0
bra tp_prevmeasure_dec
; position == 0, rollover to the last position
movff currenttracklen, nextmeasure
movff currenttracklen + 1, nextmeasure + 1
tp_prevmeasure_dec:
DECF16 nextmeasure
; note: this discards current edit which is fine
call i2c_flash_read_measure
movff nextmeasure, currentmeasure
movff nextmeasure + 1, currentmeasure + 1
FORCEDISPLAYREFRESH
bra tp_keydone
; moves to next measure if stopped
tp_nextmeasure:
IFRUNNING tp_keydone
INCF16 nextmeasure
; if currentmeasure == currenttracklen
; rollover to position 1
movf nextmeasure, W
cpfseq currenttracklen
bra tw_nextmeasure_ok
movf nextmeasure + 1, W
cpfseq currenttracklen + 1
bra tp_nextmeasure_ok
clrf nextmeasure
clrf nextmeasure + 1
tp_nextmeasure_ok:
call i2c_flash_read_measure
; update currentmeasure
movff nextmeasure, currentmeasure
movff nextmeasure + 1, currentmeasure + 1
FORCEDISPLAYREFRESH
bra tp_keydone
; starts the sequencer
tp_start:
movf currentmeasuredata, W
DECODE_BANK_FROM_MEASURE
movwf currentbank
movf currentmeasuredata, W
DECODE_PATTERN_FROM_MEASURE
movwf currentpattern
movff currentpattern, nextpattern
movff currentbank, nextbank
; load first pattern from flash
call i2c_flash_read
; reset repeat counter
clrf repeatcounter
; and start
call player_start
bra tp_keydone
; stops / continues
tp_stopcont:
FORCEDISPLAYREFRESH
IFRUNNING pp_stopcont_running
; sequencer is not running, we should continue
call player_continue
bra tp_keydone
tp_stopcont_running:
; sequencer is running, stop the player
call player_stop
bra tp_keydone
; changes the fill pattern as a active pattern
tp_fill:
SETMODE MODE_FILL
FORCEDISPLAYREFRESH
bra tp_keydone
; called always when last step of the pattern has been
; triggered
; If incremented nextmeasure points to a different pattern than
; the current the pattern is loaded to the current
tp_handleflash:
CLEAREVENT EVENT_LASTSTEP
; check if repeats are played
movf currentmeasuredata, W
DECODE_REPEAT_FROM_MEASURE ; W = repeat
cpfseq repeatcounter
; repeat counter != current repeat
;
; advance only if all repeats are played
; otherwise just return
return
INCF16 nextmeasure
; if currentmeasure == currenttracklen
; rollover to position 1
movf nextmeasure, W
cpfseq currenttracklen
bra tp_handleflash_nm_ok
movf nextmeasure + 1, W
cpfseq currenttracklen + 1
bra tp_handleflash_nm_ok
clrf nextmeasure
clrf nextmeasure + 1
tp_handleflash_nm_ok:
lfsr FSR1, nextmeasuredata
; read measure from "nextmeasure"
call i2c_flash_read_measure_fsr1
movf INDF1, W ; nextmeasuredata
cpfseq currentmeasuredata ; do we need a new pattern ?
bra tp_handleflash_loadpat
return
tp_handleflash_loadpat:
; pattern is changed in next measure,
; decode nextmeasuredata to nextbank/nextpattern
; and load
movf INDF1, W
DECODE_BANK_FROM_MEASURE
movwf nextbank
movf INDF1, W
DECODE_PATTERN_FROM_MEASURE
movwf nextpattern
call i2c_flash_read
return
External Labels :
i2c_flash_read_measure
lcd_refresh
tp_refreshleds
get_bit
mode_trackwrite_enter
mode_pattplay_enter
i2c_flash_read_trackmeta
i2c_flash_read
player_start
player_continue
player_stop
i2c_flash_read_measure_fsr1