;
; irq_hipri.inc: high priority interrupt handling
;
; bpm ticks, trigger falling edge and midi signals.
;
; 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).
;
hp_irq:
movwf hp_irq_wtmp
movff STATUS, hp_irq_statustmp
movff BSR, hp_irq_bsrtmp
; which interrupt occurred ?
hp_check_irq:
; USART receive interrupt ? (midi sync)
btfsc PIR1, RCIF
bra hp_irq_midi_in
; ccp1 interrupt ? (din sync)
btfsc PIR1, CCP1IF
bra hp_irq_din_tick
; timer 1 interrupt ? (internal clock)
btfsc PIR1, TMR1IF
bra hp_irq_bpm_tick
; trigger / din falling edge interrupt ?
btfsc PIR2, TMR3IF
bra hp_irq_trig_end
movff hp_irq_bsrtmp, BSR
movf hp_irq_wtmp, W
movff hp_irq_statustmp, STATUS
retfie
;
; external din sync tick
;
hp_irq_din_tick:
; bypass din input if set off
IFSETTINGOFF SETTING_DIN_IN, hp_irq_din_tick_stopped
; if we are syncing to midi ignore din sync
IFEVENT EVENT_MIDIRUN, hp_irq_din_tick_stopped
; check if run/stop is up ?
call hp_irq_check_dinsync
IFNOEVENT EVENT_DINRUN, hp_irq_din_tick_stopped
; echo sync to din out
; call din_clock
IFSETTINGONCALL SETTING_DIN_OUT, din_clock
; din sync 24 ppqn, so call player twice
call player_tick
call player_tick
; send midi clock
; call midi_out_clock
IFSETTINGONCALL SETTING_MIDIS_OUT, midi_out_clock
hp_irq_din_tick_stopped:
; clear interrupt
bcf PIR1, CCP1IF
bra hp_check_irq
;
; internal clock tick (note: 48ppqn)
;
hp_irq_bpm_tick:
; if we are syncing to midi or din ignore internal ticks
IFEVENT EVENT_MIDIRUN, hp_irq_bpm_done
IFEVENT EVENT_DINRUN, hp_irq_bpm_done
; send syncs out if applicable
IFNOTINMODE MODE_RUN, hp_irq_bpm_tick_cont
movlw 1
andwf bpmtick, W
bnz hp_irq_bpm_tick_cont
; send din clock
;call din_clock
IFSETTINGONCALL SETTING_DIN_OUT, din_clock
; send midi clock
;call midi_out_clock
IFSETTINGONCALL SETTING_MIDIS_OUT, midi_out_clock
; note: sync start/stop is set in 9090.inc
hp_irq_bpm_tick_cont:
; player_tick gets called 48 ppqn
call player_tick
hp_irq_bpm_skip:
; store table pointers
movff TBLPTRH, hp_irq_tblptrh
movff TBLPTRL, hp_irq_tblptrl
movff TABLAT, hp_irq_tablat
; reset timer 1 according to
; tempo value
movf tempo, W
clrf TBLPTRH
bcf STATUS, C
rlcf WREG, W ; tempo * 2
btfsc STATUS, C
incf TBLPTRH ; +$100 if >127
addlw bpm_table & 0xff
movwf TBLPTRL
movlw bpm_table >> 8
addwfc TBLPTRH, F
TBLRD*+ ; read high byte and increment
movff TABLAT, TMR1H
TBLRD* ; read low byte
movff TABLAT, TMR1L
; restore table pointers
movff hp_irq_tblptrl, TBLPTRL
movff hp_irq_tblptrh, TBLPTRH
movff hp_irq_tablat, TABLAT
hp_irq_bpm_done:
; clear interrupt
bcf PIR1, TMR1IF
bra hp_check_irq
;
; midi in (midi clock in)
;
hp_irq_midi_in:
; if we are slaving to din sync, ignore midi
; note: this should not be skipped anymore because
; midi is listened for more than the sync
; IFEVENT EVENT_DINRUN, hp_irq_midi_ignore
call midi_handlemidi
hp_irq_midi_ignore:
; clear interrupt
bcf PIR1, RCIF
bra hp_check_irq
;
; trigger width timer, we should clear triggers
;
hp_irq_trig_end:
call player_trig_off
; clear interrupt
bcf PIR2, TMR3IF
bra hp_check_irq
;
; handles the din sync run/stop checking
;
; note: this function does not get called if din sync input
; is set off
hp_irq_check_dinsync:
; check if run/stop in din sync is clear (+5 sent) ?
btfsc DIN_IN_PORT, DIN_IN_STARTSTOP_PIN
bra hp_irq_nodinrun
; din was running, just started ?
IFNOEVENT EVENT_DINRUN, hp_irq_dimrun_started
return
hp_irq_dimrun_started:
; din sync started
call player_start
SETEVENT EVENT_DINRUN
return
hp_irq_nodinrun:
; din is stopped but DINRUN-event was set
; => din sync was stopped
IFEVENT EVENT_DINRUN, hp_irq_nodinrun_reset
return
hp_irq_nodinrun_reset:
call player_stop
CLEAREVENT EVENT_DINRUN
return
External Labels :
hp_irq_check_dinsync
player_tick
midi_handlemidi
player_trig_off
player_start
player_stop