Defines | |
#define | SLAVE_CLK_TIMEOUT_DELAY 11000 |
#define | TIMER_RATE_SLAVE_MODE_US 250 |
Functions | |
s32 | SEQ_BPM_Init (u32 mode) |
seq_bpm_mode_t | SEQ_BPM_ModeGet (void) |
s32 | SEQ_BPM_ModeSet (seq_bpm_mode_t mode) |
float | SEQ_BPM_Get (void) |
float | SEQ_BPM_EffectiveGet (void) |
s32 | SEQ_BPM_Set (float _bpm) |
s32 | SEQ_BPM_PPQN_Get (void) |
s32 | SEQ_BPM_PPQN_Set (u16 _ppqn) |
u32 | SEQ_BPM_TickGet (void) |
s32 | SEQ_BPM_TickSet (u32 tick) |
s32 | SEQ_BPM_IsRunning (void) |
seq_bpm_run_mode_t | SEQ_BPM_RunModeGet (void) |
s32 | SEQ_BPM_IsMaster (void) |
s32 | SEQ_BPM_CheckAutoMaster (void) |
s32 | SEQ_BPM_NotifyMIDIRx (u8 midi_byte) |
s32 | SEQ_BPM_Start (void) |
s32 | SEQ_BPM_Cont (void) |
s32 | SEQ_BPM_Stop (void) |
s32 | SEQ_BPM_ChkReqStop (void) |
s32 | SEQ_BPM_ChkReqStart (void) |
s32 | SEQ_BPM_ChkReqCont (void) |
s32 | SEQ_BPM_ChkReqClk (u32 *bpm_tick_ptr) |
s32 | SEQ_BPM_ChkReqSongPos (u16 *song_pos) |
u32 | SEQ_BPM_TicksFor_mS (u16 time_ms) |
Some comments to the way how the bpm_tick is generated:
MASTER MODE
A timer interrupt will be triggered with an interval of: interval = (60 / (bpm * 24)) / (ppqn/24)
It increments bpm_tick, and request the clock event to the sequencer.
The sequencer can check for clock events by calling
u32 bpm_tick_ptr; // will contain the BPM tick which has to be processed while( SEQ_BPM_ChkReqClk(&bpm_tick_ctr) ) { // got a new tick }
This polling scheme ensures, that no bpm_tick gets lost if the sequencer task is stalled for any reason
Since the *_ChkReq* function is a destructive call, it should only be used by the sequencer task, and not called from any other function.
Similar request flags exist for MIDI Clock Start/Stop/Continue and Song Position
SLAVE MODE
In order to reach a higher ppqn resolution (e.g. 384 ppqn) than provided by MIDI (24 ppqn), the incoming clock has to be interpolated in ppqn/24 steps
A timer interrupt with an interval of 250 uS is used to measure the delay between two incoming MIDI clock events. The same interrupt will call the sequencer clock handler with an interval of: interval = 250 uS * measured_delay / (ppqn/24) (e.g. 384 ppqn: 16x interpolated clock)
There is a protection (-> sent_clk_ctr) which ensures, that never more that 16 internal ticks will be triggered between two F8 events to improve the robustness on BPM sweeps or jittering incoming MIDI clock
Note that instead of the timer interrupt, we could also use a HW timer to measure the delay. Problem: currently I don't know how to handle this in the MacOS based emulation...
#define SLAVE_CLK_TIMEOUT_DELAY 11000 |
#define TIMER_RATE_SLAVE_MODE_US 250 |
s32 SEQ_BPM_CheckAutoMaster | ( | void | ) |
BPM should be clocked as master or slave? If this function is called in Auto Mode, BPM will switch to Master Clock
Returns the bpm_tick which is related to the clock request
[out] | bpm_tick_ptr | a pointer to a u32 value which will get the requested bpm_tick |
s32 SEQ_BPM_ChkReqCont | ( | void | ) |
Has to be called by the sequencer to check for a continue request
Returns a new song position if requested from external
[out] | song_pos | a pointer to a u32 value which will get the new song position |
s32 SEQ_BPM_ChkReqStart | ( | void | ) |
Has to be called by the sequencer to check for a start request
s32 SEQ_BPM_ChkReqStop | ( | void | ) |
Has to be called by the sequencer to check for a stop request
s32 SEQ_BPM_Cont | ( | void | ) |
This function continues the BPM generator and forwards this event to the sequencer.
float SEQ_BPM_EffectiveGet | ( | void | ) |
Returns the effective BPM rate (Master mode: selected BPM, Slave mode: received BPM)
float SEQ_BPM_Get | ( | void | ) |
Queries the current BPM rate
Initialisation of BPM generator
[in] | mode | currently only mode 0 supported |
s32 SEQ_BPM_IsMaster | ( | void | ) |
BPM clocked as master or slave?
s32 SEQ_BPM_IsRunning | ( | void | ) |
BPM generator running?
seq_bpm_mode_t SEQ_BPM_ModeGet | ( | void | ) |
Queries the current run mode
s32 SEQ_BPM_ModeSet | ( | seq_bpm_mode_t | mode | ) |
Sets a new run mode
[in] | mode | the run mode |
should be called from Direct Rx notification hook in app.c on incoming MIDI bytes see also example code
s32 SEQ_BPM_PPQN_Get | ( | void | ) |
Queries the current PPQN value
Sets a new PPQN value
Supported ppqn for slave mode: 24, 48, 96, 192 and 384
seq_bpm_run_mode_t SEQ_BPM_RunModeGet | ( | void | ) |
BPM generator running?
s32 SEQ_BPM_Set | ( | float | _bpm | ) |
Sets a new BPM rate
[in] | _bpm | rate as float |
s32 SEQ_BPM_Start | ( | void | ) |
This function starts the BPM generator and forwards this event to the sequencer.
s32 SEQ_BPM_Stop | ( | void | ) |
This function stops the BPM generator and forwards this event to the sequencer
u32 SEQ_BPM_TickGet | ( | void | ) |
Queries the current tick value
Sets a new BPM tick value
[in] | tick | new BPM tick value |
This help function returns the number of BPM ticks for a given time E.g.: SEQ_BPM_TicksFor_mS(50) returns 38 ticks @ 120 BPM 384 ppqn Regardless if BPM generator is clocked in master or slave mode
[in] | time_ms | the time in milliseconds (e.g. 50 corresponds to 50 mS) |