SEQ_BPM

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)

Detailed Description

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

Note:
these flags have to be polled as well, otherwise clock requests will be held back

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 Documentation

#define SLAVE_CLK_TIMEOUT_DELAY   11000
#define TIMER_RATE_SLAVE_MODE_US   250

Function Documentation

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:
1 if we changed from auto slave to master mode

Here is the call graph for this function:

s32 SEQ_BPM_ChkReqClk ( u32 bpm_tick_ptr  ) 

Returns the bpm_tick which is related to the clock request

Attention:
ChkReqClk will return 0 as long as Stop/Cont/Start/SongPos haven't been checked to ensure that clocks won't be propagated as long as a position or run state change hasn't been flagged to the sequencer. Accordingly, the sequencer application has to poll all requests as shown in the examples, otherwise it will never receive a clock
Parameters:
[out] bpm_tick_ptr a pointer to a u32 value which will get the requested bpm_tick
Returns:
0 if no clock request (content of bpm_tick invalid)
1 if clock has been requested (content of bpm_tick valid)

Here is the call graph for this function:

s32 SEQ_BPM_ChkReqCont ( void   ) 

Has to be called by the sequencer to check for a continue request

Returns:
0 if no continue request
1 if continue has been requested

Here is the call graph for this function:

s32 SEQ_BPM_ChkReqSongPos ( u16 song_pos  ) 

Returns a new song position if requested from external

Parameters:
[out] song_pos a pointer to a u32 value which will get the new song position
Returns:
0 if no song position request (content of song_pos invalid)
1 if new song position has been requested (content of song_pos valid)

Here is the call graph for this function:

s32 SEQ_BPM_ChkReqStart ( void   ) 

Has to be called by the sequencer to check for a start request

Returns:
0 if no start request
1 if start has been requested

Here is the call graph for this function:

s32 SEQ_BPM_ChkReqStop ( void   ) 

Has to be called by the sequencer to check for a stop request

Returns:
0 if no stop request
1 if stop has been requested

Here is the call graph for this function:

s32 SEQ_BPM_Cont ( void   ) 

This function continues the BPM generator and forwards this event to the sequencer.

Returns:
< 0 on errors

Here is the call graph for this function:

float SEQ_BPM_EffectiveGet ( void   ) 

Returns the effective BPM rate (Master mode: selected BPM, Slave mode: received BPM)

Returns:
effective bpm rate as float
float SEQ_BPM_Get ( void   ) 

Queries the current BPM rate

Returns:
bpm rate as float
s32 SEQ_BPM_Init ( u32  mode  ) 

Initialisation of BPM generator

Parameters:
[in] mode currently only mode 0 supported
Returns:
< 0 if initialisation failed

Here is the call graph for this function:

s32 SEQ_BPM_IsMaster ( void   ) 

BPM clocked as master or slave?

Returns:
0: BPM clocked as slave, 1: BPM clocked as master
s32 SEQ_BPM_IsRunning ( void   ) 

BPM generator running?

Returns:
0 if generator not running
1 if start event or clock has been received
seq_bpm_mode_t SEQ_BPM_ModeGet ( void   ) 

Queries the current run mode

Returns:
the run mode
s32 SEQ_BPM_ModeSet ( seq_bpm_mode_t  mode  ) 

Sets a new run mode

Parameters:
[in] mode the run mode
Returns:
< 0 on errors
s32 SEQ_BPM_NotifyMIDIRx ( u8  midi_byte  ) 

should be called from Direct Rx notification hook in app.c on incoming MIDI bytes see also example code

Returns:
< 0 on errors

Here is the call graph for this function:

s32 SEQ_BPM_PPQN_Get ( void   ) 

Queries the current PPQN value

Returns:
ppqn value
s32 SEQ_BPM_PPQN_Set ( u16  _ppqn  ) 

Sets a new PPQN value

Note:
after changing PPQN, SEQ_BPM_Set() has to be called again to take over the new value. In other words: set PPQN before BPM

Supported ppqn for slave mode: 24, 48, 96, 192 and 384

seq_bpm_run_mode_t SEQ_BPM_RunModeGet ( void   ) 

BPM generator running?

Returns:
SEQ_BPM_RUN_MODE_Off if generator not running
SEQ_BPM_RUN_MODE_Armed if start event has been received
SEQ_BPM_RUN_MODE_Clocked if first clock after start has been received and bpm_tick will be incremented
s32 SEQ_BPM_Set ( float  _bpm  ) 

Sets a new BPM rate

Parameters:
[in] _bpm rate as float

Here is the call graph for this function:

s32 SEQ_BPM_Start ( void   ) 

This function starts the BPM generator and forwards this event to the sequencer.

Here is the call graph for this function:

s32 SEQ_BPM_Stop ( void   ) 

This function stops the BPM generator and forwards this event to the sequencer

Returns:
< 0 on errors

Here is the call graph for this function:

u32 SEQ_BPM_TickGet ( void   ) 

Queries the current tick value

Returns:
BPM tick value
s32 SEQ_BPM_TickSet ( u32  tick  ) 

Sets a new BPM tick value

Parameters:
[in] tick new BPM tick value
Returns:
< 0 on errors
u32 SEQ_BPM_TicksFor_mS ( u16  time_ms  ) 

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

Parameters:
[in] time_ms the time in milliseconds (e.g. 50 corresponds to 50 mS)
Returns:
the number of BPM ticks

Generated on 22 Jan 2016 for MIOS32 by  doxygen 1.6.1