Пример #1
0
/////////////////////////////////////////////////////////////////////////////
// Should be called whenever a Note event has been received.
// We expect, that velocity is 0 on a Note Off event
/////////////////////////////////////////////////////////////////////////////
s32 SEQ_NotifyNoteOn(u8 note, u8 velocity)
{
  u8 clear_stack = 0;

  if( velocity )
    // push note into note stack
    NOTESTACK_Push(&notestack, note, velocity);
  else {
    // remove note from note stack
    // function returns 2 if no note played anymore (all keys depressed)
    if( NOTESTACK_Pop(&notestack, note) == 2 )
      clear_stack = 1;
  }

  // At least one note played?
  if( !clear_stack && notestack.len > 0 ) {
    // start sequencer if it isn't already running
    if( !SEQ_BPM_IsRunning() )
      SEQ_BPM_Start();
  } else {
    // clear stack
    NOTESTACK_Clear(&notestack);

    // no key is pressed anymore: stop sequencer
    SEQ_BPM_Stop();
  }


#if 1
  // optional debug messages
  NOTESTACK_SendDebugMessage(&notestack);
#endif

  return 0; // no error
}
Пример #2
0
/////////////////////////////////////////////////////////////////////////////
//! To control the play/stop button function
/////////////////////////////////////////////////////////////////////////////
s32 MBNG_SEQ_PlayStopButton(void)
{
  if( SEQ_BPM_IsRunning() ) {
    MBNG_SEQ_StopButton();
  } else {
    MBNG_SEQ_PlayButton();
  }

  return 0; // no error
}
Пример #3
0
/////////////////////////////////////////////////////////////////////////////
// This hook is called when a MIDI package has been received
/////////////////////////////////////////////////////////////////////////////
void APP_MIDI_NotifyPackage(mios32_midi_port_t port, mios32_midi_package_t midi_package)
{
  // Note On received?
  if( midi_package.type == NoteOn &&
      midi_package.chn == Chn1 &&
      midi_package.velocity > 0 ) {

    // determine base key number (0=C, 1=C#, 2=D, ...)
    u8 base_key = midi_package.note % 12;

    // branch depending on note
    switch( base_key ) {
      case 0: // "C" starts the sequencer
	MIOS32_MIDI_SendDebugMessage("Start\n");
	// if in auto mode and BPM generator is clocked in slave mode:
	// change to master mode
	SEQ_BPM_CheckAutoMaster();
	// start sequencer
	SEQ_BPM_Start();
	break;

      case 2: // "D" stops the sequencer. If pressed twice, the sequencer will be reset
	MIOS32_MIDI_SendDebugMessage("Stop\n");
	if( SEQ_BPM_IsRunning() )
	  SEQ_BPM_Stop();          // stop sequencer
	else
	  SEQ_Reset(1);            // reset sequencer
	break;

      case 4: // "E" pauses the sequencer
	// if in auto mode and BPM generator is clocked in slave mode:
	// change to master mode
	SEQ_BPM_CheckAutoMaster();

	// toggle pause mode
	seq_pause ^= 1;

	MIOS32_MIDI_SendDebugMessage("Pause %s\n", seq_pause ? "on" : "off");

	// execute stop/continue depending on new mode
	if( seq_pause )
	  SEQ_BPM_Stop();         // stop sequencer
	else
	  SEQ_BPM_Cont();         // continue sequencer
	break;

      case 5: // "F" switches to next file
	MIOS32_MIDI_SendDebugMessage("Next File\n");
	SEQ_PlayFileReq(1);
	break;
    }
  }
}
Пример #4
0
/////////////////////////////////////////////////////////////////////////////
//! To control the stop button function
/////////////////////////////////////////////////////////////////////////////
s32 MBNG_SEQ_StopButton(void)
{
  if( SEQ_BPM_IsRunning() ) {
    SEQ_BPM_Stop();          // stop sequencer
  } else {
    // reset sequencer
    MBNG_SEQ_Reset();

    // disable pause mode
    MBNG_SEQ_SetPauseMode(0);
  }

  return 0; // no error
}
Пример #5
0
/////////////////////////////////////////////////////////////////////////////
//! To control the stop button function
/////////////////////////////////////////////////////////////////////////////
s32 MBNG_SEQ_PauseButton(void)
{
  // if in auto mode and BPM generator is not clocked in slave mode:
  // change to master mode
  SEQ_BPM_CheckAutoMaster();

  // toggle pause
  seq_pause ^= 1;

  // execute stop/continue depending on new mode
  MIOS32_IRQ_Disable();
  if( seq_pause ) {
    SEQ_BPM_Stop();
  } else {
    if( !SEQ_BPM_IsRunning() )
      SEQ_BPM_Cont();
  }
  MIOS32_IRQ_Enable();

  return 0; // no error
}
Пример #6
0
/////////////////////////////////////////////////////////////////////////////
// (Public) Tap Tempo Function
// Can also be accessed by pressing MENU+PLAY
/////////////////////////////////////////////////////////////////////////////
s32 SEQ_UI_BPM_TapTempo(void)
{
  // determine current timestamp
  u32 timestamp = MIOS32_TIMESTAMP_Get();
  u32 delay = MIOS32_TIMESTAMP_GetDelay(tap_tempo_last_timestamp);

  // if delay < 100 (mS) we assume a bouncing button - ignore this tap!
  if( delay < 100 )
    return -1;

  // reset counter if last timestamp zero (first tap) or difference between timestamps > 2 seconds (< 30 BPM...)
  if( !tap_tempo_last_timestamp || delay > 2000 ) {
    resetTapTempo();
  } else {    
    // store measured delay
    tap_tempo_delay[tap_tempo_beat_ix] = delay;

    // increment index, wrap at number of stored tap delays
    tap_tempo_beat_ix = (tap_tempo_beat_ix + 1) % TAP_DELAY_STORAGE_SIZE;
  }

  // store timestamp
  tap_tempo_last_timestamp = timestamp;

  // take over BPM and start sequencer once we reached the 5th tap
  if( tap_tempo_beat_ctr >= TAP_DELAY_STORAGE_SIZE ) {
    // hold counter at delay storage size + 1 (for display)
    tap_tempo_beat_ctr = TAP_DELAY_STORAGE_SIZE + 1;

    // determine BPM
    int tap;
    int accumulated_delay = 0;
    for(tap=0; tap<TAP_DELAY_STORAGE_SIZE; ++tap)
      accumulated_delay += tap_tempo_delay[tap];
    u32 bpm = 60000000 / (accumulated_delay / TAP_DELAY_STORAGE_SIZE);

    // set BPM
    float bpmF = bpm / 1000.0;
    seq_core_bpm_preset_tempo[seq_core_bpm_preset_num] = bpmF;
    SEQ_BPM_Set(bpmF);

    // if in auto mode and BPM generator is clocked in slave mode:
    // change to master mode
    SEQ_BPM_CheckAutoMaster();

    // if sequencer not running: start it!
    if( !SEQ_BPM_IsRunning() )
      SEQ_BPM_Start();

  } else {
    // increment counter
    ++tap_tempo_beat_ctr;
  }

  // print message
  char buffer1[30];
  if( tap_tempo_beat_ctr > TAP_DELAY_STORAGE_SIZE ) {
    float bpm = SEQ_BPM_Get();
    sprintf(buffer1, "Tap Tempo: %3d.%d", (int)bpm, (int)(10*bpm)%10);
  } else
    sprintf(buffer1, "Tap Tempo: ???.?");

  char buffer2[30];
  int i;
  for(i=0; i<((tap_tempo_beat_ix+1)*4); ++i)
    buffer2[i] = '>';
  for(; i<16; ++i)
    buffer2[i] = ' ';
  buffer2[i] = 0;
  SEQ_UI_Msg(SEQ_UI_MSG_USER_R, 2000, buffer1, buffer2);

  return 0; // no error
}
Пример #7
0
/////////////////////////////////////////////////////////////////////////////
// Local encoder callback function
// Should return:
//   1 if value has been changed
//   0 if value hasn't been changed
//  -1 if invalid or unsupported encoder
/////////////////////////////////////////////////////////////////////////////
static s32 Encoder_Handler(seq_ui_encoder_t encoder, s32 incrementer)
{
#if 0
  // leads to: comparison is always true due to limited range of data type
  if( (encoder >= SEQ_UI_ENCODER_GP1 && encoder <= SEQ_UI_ENCODER_GP16) ) {
#else
  if( encoder <= SEQ_UI_ENCODER_GP16 ) {
#endif
    if( seq_ui_button_state.SELECT_PRESSED && !seq_ui_button_state.CHANGE_ALL_STEPS ) {
	// select button pressed: indirect MUTED flag modification (taken over when select button depressed)
	u16 mask = 1 << encoder;
	if( incrementer < 0 || (incrementer == 0 && !(latched_mute & mask)) )
	  latched_mute |= mask;
	else
	  latched_mute &= ~mask;
    } else {
      // select button not pressed: direct MUTED flag modification
      // access to seq_core_trk[] must be atomic!
      portENTER_CRITICAL();

      u8 visible_track = SEQ_UI_VisibleTrackGet();
      u16 mask = 1 << encoder;
      u16 *muted = (u16 *)&seq_core_trk_muted;

      if( seq_ui_button_state.CHANGE_ALL_STEPS ) {
	switch( encoder ) {
	case SEQ_UI_ENCODER_GP1:
	case SEQ_UI_ENCODER_GP2:
	  *muted = 0xffff;
	  SEQ_UI_Msg(SEQ_UI_MSG_USER, 1000, "All Tracks", "muted");
	  break;

	case SEQ_UI_ENCODER_GP3:
	case SEQ_UI_ENCODER_GP4:
	case SEQ_UI_ENCODER_GP5:
	  muted = (u16 *)&seq_core_trk[visible_track].layer_muted;
	  *muted = 0xffff;
	  SEQ_UI_Msg(SEQ_UI_MSG_USER, 1000, "All Layers", "of current Track muted");
	  break;

	case SEQ_UI_ENCODER_GP6:
	case SEQ_UI_ENCODER_GP7:
	case SEQ_UI_ENCODER_GP8: {
	  *muted = 0xffff;

	  int track;
	  for(track=0; track<SEQ_CORE_NUM_TRACKS; ++track) {
	    seq_core_trk[track].layer_muted = 0xffff;
	  }
	  SEQ_UI_Msg(SEQ_UI_MSG_USER, 1000, "All Layers", "and Tracks muted");
	} break;

	case SEQ_UI_ENCODER_GP9:
	case SEQ_UI_ENCODER_GP10:
	  *muted = 0x0000;
	  SEQ_UI_Msg(SEQ_UI_MSG_USER_R, 1000, "All Tracks", "unmuted");
	  break;

	case SEQ_UI_ENCODER_GP11:
	case SEQ_UI_ENCODER_GP12:
	case SEQ_UI_ENCODER_GP13:
	  muted = (u16 *)&seq_core_trk[visible_track].layer_muted;
	  *muted = 0x0000;
	  SEQ_UI_Msg(SEQ_UI_MSG_USER_R, 1000, "All Layers", "of current Track unmuted");
	  break;

	case SEQ_UI_ENCODER_GP14:
	case SEQ_UI_ENCODER_GP15:
	case SEQ_UI_ENCODER_GP16: {
	  *muted = 0x0000;

	  int track;
	  for(track=0; track<SEQ_CORE_NUM_TRACKS; ++track) {
	    seq_core_trk[track].layer_muted = 0x0000;
	  }
	  SEQ_UI_Msg(SEQ_UI_MSG_USER_R, 1000, "All Layers", "and Tracks unmuted");
	} break;
	}
      } else {
	if( seq_ui_button_state.MUTE_PRESSED )
	  muted = (u16 *)&seq_core_trk[visible_track].layer_muted;
	else if( SEQ_BPM_IsRunning() ) { // Synched Mutes only when sequencer is running
	  if( !(*muted & mask) && seq_core_options.SYNCHED_MUTE && !seq_ui_button_state.FAST_ENCODERS ) { // Fast button will disable synched mute
	    muted = (u16 *)&seq_core_trk_synched_mute;
	  } else if( (*muted & mask) && seq_core_options.SYNCHED_UNMUTE && !seq_ui_button_state.FAST_ENCODERS ) { // Fast button will disable synched unmute
	    muted = (u16 *)&seq_core_trk_synched_unmute;
	  }
	} else {
	  // clear synched mutes/unmutes if sequencer not running
	  seq_core_trk_synched_mute = 0;
	  seq_core_trk_synched_unmute = 0;
	}
	  
	if( incrementer < 0 )
	  *muted |= mask;
	else if( incrementer > 0 )
	  *muted &= ~mask;
	else
	  *muted ^= mask;
      }

      portEXIT_CRITICAL();

      if( muted == ((u16 *)&seq_core_trk_muted) ) {
	// send to external
	SEQ_MIDI_IN_ExtCtrlSend(SEQ_MIDI_IN_EXT_CTRL_MUTES, (*muted & mask) ? 127 : 0, encoder);
      }
    }

    return 1; // value changed
  }

  return -1; // invalid or unsupported encoder
}


/////////////////////////////////////////////////////////////////////////////
// Local button callback function
// Should return:
//   1 if value has been changed
//   0 if value hasn't been changed
//  -1 if invalid or unsupported button
/////////////////////////////////////////////////////////////////////////////
static s32 Button_Handler(seq_ui_button_t button, s32 depressed)
{
#if 0
  // leads to: comparison is always true due to limited range of data type
  if( button >= SEQ_UI_BUTTON_GP1 && button <= SEQ_UI_BUTTON_GP16 ) {
#else
  if( button <= SEQ_UI_BUTTON_GP16 ) {
#endif
    if( depressed ) return 0; // ignore when button depressed

    // re-using encoder routine
    return Encoder_Handler(button, 0);
  }

  switch( button ) {
    case SEQ_UI_BUTTON_Select:
      portENTER_CRITICAL();
      if( depressed ) {
	// select button released: take over latched mutes
	if( seq_ui_button_state.MUTE_PRESSED ) {
	  u8 visible_track = SEQ_UI_VisibleTrackGet();
	  seq_core_trk[visible_track].layer_muted = latched_mute;
	} else {
	  u16 new_mutes = latched_mute & ~seq_core_trk_muted;
	  if( SEQ_BPM_IsRunning() && seq_core_options.SYNCHED_MUTE && !seq_ui_button_state.FAST_ENCODERS ) // Fast button will disable synched mute
	    seq_core_trk_synched_mute |= new_mutes;
	  else
	    seq_core_trk_muted |= new_mutes;

	  u16 new_unmutes = ~latched_mute & seq_core_trk_muted;
	  if( SEQ_BPM_IsRunning() && seq_core_options.SYNCHED_UNMUTE && !seq_ui_button_state.FAST_ENCODERS ) // Fast button will disable synched unmute
	    seq_core_trk_synched_unmute |= new_unmutes;
	  else
	    seq_core_trk_muted &= ~new_unmutes;
	}
      } else {
	// select pressed: init latched mutes which will be taken over once SELECT button released
	if( seq_ui_button_state.MUTE_PRESSED ) {
	  u8 visible_track = SEQ_UI_VisibleTrackGet();
	  latched_mute = seq_core_trk[visible_track].layer_muted;
	} else {
	  latched_mute = seq_core_trk_muted;
	}
      }

      portEXIT_CRITICAL();
      return 1;
  }

  return -1; // invalid or unsupported button
}


/////////////////////////////////////////////////////////////////////////////
// Local Display Handler function
// IN: <high_prio>: if set, a high-priority LCD update is requested
/////////////////////////////////////////////////////////////////////////////
static s32 LCD_Handler(u8 high_prio)
{
  // layout:
  // 00000000001111111111222222222233333333330000000000111111111122222222223333333333
  // 01234567890123456789012345678901234567890123456789012345678901234567890123456789
  // <--------------------------------------><-------------------------------------->
  //  > 1<   2    3    4    5    6    7    8    9   10   11   12   13   14   15   16 
  // ...horizontal VU meters...

  // Mute All screen:
  // 00000000001111111111222222222233333333330000000000111111111122222222223333333333
  // 01234567890123456789012345678901234567890123456789012345678901234567890123456789
  // <--------------------------------------><-------------------------------------->
  //    Mute       Mute       Mute all Tracks  Unmute      Unmute   Unmute all Tracks
  // all Tracks G1T1 Layers    and all Layersall Tracks G1T1 Layers    and all Layers

  if( seq_ui_button_state.CHANGE_ALL_STEPS ) {
    if( high_prio )
      return 0;

    SEQ_LCD_CursorSet(0, 0);
    SEQ_LCD_PrintString("   Mute       Mute       Mute all Tracks  Unmute      Unmute   Unmute all Tracks");
    SEQ_LCD_CursorSet(0, 1);
    SEQ_LCD_PrintString("all Tracks ");
    SEQ_LCD_PrintGxTy(ui_selected_group, ui_selected_tracks);
    SEQ_LCD_PrintString(" Layers    and all Layersall Tracks ");
    SEQ_LCD_PrintGxTy(ui_selected_group, ui_selected_tracks);
    SEQ_LCD_PrintString(" Layers    and all Layers");

    return 0;
  }

  if( high_prio ) {
    ///////////////////////////////////////////////////////////////////////////
    // frequently update VU meters
    SEQ_LCD_CursorSet(0, 1);

    u8 track;
    u16 mute_flags = 0;
    u16 mute_flags_from_midi = 0;

    if( !ui_cursor_flash && seq_ui_button_state.SELECT_PRESSED ) {
      mute_flags = latched_mute;
    } else {
      if( seq_ui_button_state.MUTE_PRESSED ) {
	u8 visible_track = SEQ_UI_VisibleTrackGet();
	mute_flags = seq_core_trk[visible_track].layer_muted;
	mute_flags_from_midi = seq_core_trk[visible_track].layer_muted_from_midi;
      } else {
	mute_flags = seq_core_trk_muted;
      }
    }

    if( seq_ui_button_state.MUTE_PRESSED ) {
      u8 layer;
      u16 mask = (1 << 0);
      for(layer=0; layer<16; ++layer, mask <<= 1)
	if( mute_flags_from_midi & mask ) {
	  SEQ_LCD_PrintString("MIDI ");
	} else if( mute_flags & mask ) {
	  SEQ_LCD_PrintString("Mute ");
	} else {
	  SEQ_LCD_PrintHBar((seq_layer_vu_meter[layer] >> 3) & 0xf);
	}
    } else {
      int remaining_steps = (seq_core_steps_per_measure - seq_core_state.ref_step) + 1;
      seq_core_trk_t *t = &seq_core_trk[0];
      u16 mask = (1 << 0);
      for(track=0; track<16; ++t, ++track, mask <<= 1)
	if( mute_flags & mask ) {
	  if( !seq_ui_button_state.SELECT_PRESSED && (seq_core_trk_synched_unmute & mask) ) {
	    SEQ_LCD_PrintFormattedString("U%3d ", remaining_steps);
	  } else {
	    SEQ_LCD_PrintString("Mute ");
	  }
	} else {
	  if( !seq_ui_button_state.SELECT_PRESSED && (seq_core_trk_synched_mute & mask) ) {
	    SEQ_LCD_PrintFormattedString("M%3d ", remaining_steps);
	  } else {
	    SEQ_LCD_PrintHBar(t->vu_meter >> 3);
	  }
	}
    }
  } else {
/////////////////////////////////////////////////////////////////////////////
// Local encoder callback function
// Should return:
//   1 if value has been changed
//   0 if value hasn't been changed
//  -1 if invalid or unsupported encoder
/////////////////////////////////////////////////////////////////////////////
static s32 Encoder_Handler(seq_ui_encoder_t encoder, s32 incrementer)
{
  u8 visible_track = SEQ_UI_VisibleTrackGet();
  int num_steps = SEQ_TRG_NumStepsGet(visible_track);
  int track_length = (int)SEQ_CC_Get(visible_track, SEQ_CC_LENGTH) + 1;

#if 0
  // leads to: comparison is always true due to limited range of data type
  if( (encoder >= SEQ_UI_ENCODER_GP1 && encoder <= SEQ_UI_ENCODER_GP16) ) {
#else
  if( encoder <= SEQ_UI_ENCODER_GP16 ) {
#endif
    if( seq_ui_button_state.SELECT_PRESSED ) {
      int section;
      if( num_steps > 128 )
	section = encoder / (track_length / 16);
      else if( num_steps > 64 )
	section = encoder / ((2 * track_length) / 16);
      else
	section = encoder / ((4 * track_length) / 16);

      // operation should be atomic (change all selected tracks)
      u8 track;
      seq_core_trk_t *t = &seq_core_trk[0];
      MIOS32_IRQ_Disable();
      for(track=0; track<SEQ_CORE_NUM_TRACKS; ++track, ++t)
	if( ui_selected_tracks & (1 << track) )
	  t->play_section = section;
      MIOS32_IRQ_Enable();
    } else {
      // won't work if Follow function active!
      if( seq_core_state.FOLLOW ) {
	// print message and exit
	SEQ_UI_Msg((encoder <= SEQ_UI_ENCODER_GP8) ? SEQ_UI_MSG_USER : SEQ_UI_MSG_USER_R, 2000, "\"Follow\" active!", "Please deactivate!");
	return 1;
      }
    }

    // select new step view
    ui_selected_step_view = (encoder * (num_steps/16)) / 16;

    // select step within view
    if( !seq_ui_button_state.CHANGE_ALL_STEPS ) { // don't change the selected step if ALL function is active, otherwise the ramp can't be changed over multiple views
      ui_selected_step = (ui_selected_step_view << 4) | (ui_selected_step & 0xf);
    }

    if( seq_hwcfg_button_beh.step_view ) {
      // if toggle function active: jump back to previous menu
      // this is especially useful for the emulated MBSEQ, where we can only click on a single button
      // (stepview gets deactivated when clicking on GP button)
      if( seq_ui_button_state.STEP_VIEW ) {
	seq_ui_button_state.STEP_VIEW = 0;
	SEQ_UI_PageSet(ui_stepview_prev_page);
      }
    }

    return 1; // value changed
  } else if( encoder == SEQ_UI_ENCODER_Datawheel ) {
    if( SEQ_UI_Var8_Inc(&ui_selected_step_view, 0, (num_steps-1)/16, incrementer) >= 1 ) {
      // select step within view
      if( !seq_ui_button_state.CHANGE_ALL_STEPS ) { // don't change the selected step if ALL function is active, otherwise the ramp can't be changed over multiple views
	ui_selected_step = (ui_selected_step_view << 4) | (ui_selected_step & 0xf);
      }
    } else {
      return 0;
    }
  }

  return -1; // invalid or unsupported encoder
}


/////////////////////////////////////////////////////////////////////////////
// Local button callback function
// Should return:
//   1 if value has been changed
//   0 if value hasn't been changed
//  -1 if invalid or unsupported button
/////////////////////////////////////////////////////////////////////////////
static s32 Button_Handler(seq_ui_button_t button, s32 depressed)
{
  if( depressed ) return 0; // ignore when button depressed

#if 0
  // leads to: comparison is always true due to limited range of data type
  if( button >= SEQ_UI_BUTTON_GP1 && button <= SEQ_UI_BUTTON_GP16 ) {
#else
  if( button <= SEQ_UI_BUTTON_GP16 ) {
#endif
    // -> same handling like for encoders
    return Encoder_Handler(button, 0);
  }

  switch( button ) {
    case SEQ_UI_BUTTON_Select:
      return 1; // selects section mode, checked via seq_ui_button_state.SELECT_PRESSED

    case SEQ_UI_BUTTON_Right:
    case SEQ_UI_BUTTON_Up:
      if( depressed ) return 0; // ignore when button depressed
      return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, 1);

    case SEQ_UI_BUTTON_Left:
    case SEQ_UI_BUTTON_Down:
      if( depressed ) return 0; // ignore when button depressed
      return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, -1);
  }

  return -1; // invalid or unsupported button
}


/////////////////////////////////////////////////////////////////////////////
// Local Display Handler function
// IN: <high_prio>: if set, a high-priority LCD update is requested
/////////////////////////////////////////////////////////////////////////////
static s32 LCD_Handler(u8 high_prio)
{
  // layout:
  // 00000000001111111111222222222233333333330000000000111111111122222222223333333333
  // 01234567890123456789012345678901234567890123456789012345678901234567890123456789
  // <--------------------------------------><-------------------------------------->
  // 1                   17                  33                  49
  // *... *... *... *... *... *... *... *... *... *... *... *... *... *... *... *... 


  // 5 character usage in 256 step view (5 chars have to display 16 steps, 8 special chars available,
  // due to this limitation, we only display 15 steps (shouldn't really hurt))
  // 43210 43210 43210 43210 43210
  // * * * * . . . * . . . * . . .  (Small charset)

  // 5 character usage in 128 step view (5 chars have to display 8 steps):
  // 43210 43210 43210 43210 43210
  //  * *   . *   * .   . .         (Medium charset)

  // 5 character usage in 64 step view (5 chars have to display 4 steps):
  // 43210 43210 43210 43210 43210
  //   *     *     *     *     *    (Big charset)

  u8 visible_track = SEQ_UI_VisibleTrackGet();
  u8 event_mode = SEQ_CC_Get(visible_track, SEQ_CC_MIDI_EVENT_MODE);
  int num_steps = SEQ_TRG_NumStepsGet(visible_track);
  int steps_per_item = num_steps / 16;
  int played_step = SEQ_BPM_IsRunning() ? seq_core_trk[visible_track].step : -1;

  int i;

  if( !high_prio ) {
    SEQ_LCD_CursorSet(0, 0);
    for(i=0; i<16; ++i)
      if( ((i*steps_per_item) % 16) || ((((i*steps_per_item)/16) == ui_selected_step_view) && ui_cursor_flash) )
	SEQ_LCD_PrintSpaces(5);
      else
	SEQ_LCD_PrintFormattedString("%-3d  ", i*steps_per_item+1);

    // print flashing *LOOPED* at right corner if loop mode activated to remind that steps will be played differntly
    if( (ui_cursor_flash_overrun_ctr & 1) && seq_core_state.LOOP ) {
      SEQ_LCD_CursorSet(71, 0);
      SEQ_LCD_PrintString(" *LOOPED*");
    } else if( (ui_cursor_flash_overrun_ctr & 1) && seq_core_trk[visible_track].play_section > 0 ) {
      SEQ_LCD_CursorSet(71, 0);
      SEQ_LCD_PrintFormattedString(" *Sect.%c*", 'A'+seq_core_trk[visible_track].play_section);
    } else {
      if( event_mode == SEQ_EVENT_MODE_Drum ) {
	// print drum name at the rightmost side
	SEQ_LCD_CursorSet(75, 0);
	SEQ_LCD_PrintTrackDrum(visible_track, ui_selected_instrument, (char *)seq_core_trk[visible_track].name);
      } else {
	// print trigger layer and name at the rightmost side
	SEQ_LCD_CursorSet(73, 0);
	SEQ_LCD_PrintFormattedString("%c:%s", 'A' + ui_selected_trg_layer, SEQ_TRG_AssignedTypeStr(visible_track, ui_selected_trg_layer));
      }
    }
  }

  SEQ_LCD_CursorSet(0, 1);

  if( steps_per_item > 8 ) {
    SEQ_LCD_InitSpecialChars(SEQ_LCD_CHARSET_DrumSymbolsSmall);

    for(i=0; i<16; ++i) {
      u16 step = i*steps_per_item;
      u8 step8 = step / 8;

      u8 layer = (event_mode == SEQ_EVENT_MODE_Drum) ? 0 : ui_selected_trg_layer;
      u16 steps = (SEQ_TRG_Get8(visible_track, step8+1, layer, ui_selected_instrument) << 8) |
	          (SEQ_TRG_Get8(visible_track, step8+0, layer, ui_selected_instrument) << 0);

      if( played_step >= step && played_step < (step+16) )
	steps ^= (1 << (played_step % 16));

      int j;
      for(j=0; j<5; ++j) {
	SEQ_LCD_PrintChar(steps & 0x7);
	steps >>= 3;
      }
    }
  } else if( steps_per_item > 4 ) {
Пример #9
0
/////////////////////////////////////////////////////////////////////////////
// This task is running endless in background
/////////////////////////////////////////////////////////////////////////////
void APP_Background(void)
{
  // set LED depending on sequencer run state
  MIOS32_BOARD_LED_Set(1, SEQ_BPM_IsRunning() ? 1 : 0);
}
Пример #10
0
/////////////////////////////////////////////////////////////////////////////
// Called from SEQ_MIDI_IN_Receive() if MIDI event has been received on
// matching IN port and channel
/////////////////////////////////////////////////////////////////////////////
s32 SEQ_RECORD_Receive(mios32_midi_package_t midi_package, u8 track)
{
  // step recording mode?
  // Note: if sequencer is not running, "Live Recording" will be handled like "Step Recording"
  u8 step_record_mode = seq_record_options.STEP_RECORD || !SEQ_BPM_IsRunning();

#if MBSEQV4L
  // extra for MBSEQ V4L: seq_record_state.ARMED_TRACKS and auto-assignment
  if( !seq_record_state.ARMED_TRACKS )
    return 0; // no track armed

  track = 0;
  if( seq_record_state.ARMED_TRACKS & 0xff00)
    track = 8;

  // search for free track/layer
  if( (midi_package.event == NoteOn) || (midi_package.event == NoteOff) ) {
    // fine, we will record Note in selected track
  } else if( midi_package.event == PitchBend ) {
    track += 3; // G1T4 resp. G3T4
  } else if( midi_package.event == CC ) {
    const u8 track_layer_cc_table[19][2] = {
      { 4, 0 },
      { 5, 0 },
      { 6, 0 },
      { 7, 0 },
      { 7, 1 }, { 7, 2 }, { 7, 3 },
      { 6, 1 }, { 6, 2 }, { 6, 3 },
      { 5, 1 }, { 5, 2 }, { 5, 3 },
      { 4, 1 }, { 4, 2 }, { 4, 3 },
      { 3, 1 }, { 3, 2 }, { 3, 3 },
    };

    // search for same (or free) CC entry
    // new track/layer search algorithm since V4L.082
    u8 seq_track_offset = track; // depends on sequence
    int par_layer = 0;
    int i;
    u8 free_layer_found = 0;
    for(i=0; i<19 && !free_layer_found; ++i) {
      track = seq_track_offset + track_layer_cc_table[i][0];
      par_layer = track_layer_cc_table[i][1];
      seq_cc_trk_t *tcc = &seq_cc_trk[track];
      u8 *layer_type_ptr = (u8 *)&tcc->lay_const[0*16 + par_layer];
      u8 *layer_cc_ptr = (u8 *)&tcc->lay_const[1*16 + par_layer];

      if( *layer_type_ptr == SEQ_PAR_Type_CC &&
	  (*layer_cc_ptr >= 0x80 || *layer_cc_ptr == midi_package.cc_number) &&
	  (seq_record_state.ARMED_TRACKS & (1 << track)) ) {

	if( *layer_cc_ptr >= 0x80 ) {
	  *layer_cc_ptr = midi_package.cc_number; // assing CC number to free track

	  // initialize whole layer with invalid value 0xc0 (indicates: not recorded)
	  int num_p_steps = SEQ_PAR_NumStepsGet(track);
	  int instrument = 0;
	  int step;
	  for(step=0; step<num_p_steps; ++step)
	    SEQ_PAR_Set(track, step, par_layer, instrument, 0xc0);
#if DEBUG_VERBOSE_LEVEL >= 2
	  DEBUG_MSG("[SEQ_RECORD_Receive] free CC layer found for CC#%d in track #%d.%c\n", midi_package.cc_number, track+1, 'A'+par_layer);
#endif
	}

	free_layer_found = 1;
      }
    }

    if( !free_layer_found ) {
#if DEBUG_VERBOSE_LEVEL >= 2
      DEBUG_MSG("[SEQ_RECORD_Receive] no free CC layer found for CC#%d\n", midi_package.cc_number);
#endif
      return 0; // no free layer
    }
  } else {
    return 0; // event not relevant
  }

  // exit if track not armed
  if( !(seq_record_state.ARMED_TRACKS & (1 << track)) )
    return 0;
#else
  // MBSEQV4 (without L)
  if( midi_package.event == CC && track == SEQ_UI_VisibleTrackGet() ) {
    // search for same (or free) CC entry
    seq_cc_trk_t *tcc = &seq_cc_trk[track];
    u8 free_layer_found = 0;
    {
      u8 num_p_layers = SEQ_PAR_NumLayersGet(track);
      u8 *layer_type_ptr = (u8 *)&tcc->lay_const[0*16];
      u8 *layer_cc_ptr = (u8 *)&tcc->lay_const[1*16];
      int par_layer;
      for(par_layer=0; par_layer<num_p_layers && !free_layer_found; ++par_layer, ++layer_type_ptr, ++layer_cc_ptr) {
	if( *layer_type_ptr == SEQ_PAR_Type_CC &&
	    (*layer_cc_ptr >= 0x80 || *layer_cc_ptr == midi_package.cc_number) ) {

	  if( *layer_cc_ptr >= 0x80 ) {
	    *layer_cc_ptr = midi_package.cc_number; // assing CC number to free track

	    // initialize whole layer with invalid value 0xc0 (indicates: not recorded)
	    int num_p_steps = SEQ_PAR_NumStepsGet(track);
	    int instrument = 0;
	    int step;
	    for(step=0; step<num_p_steps; ++step)
	      SEQ_PAR_Set(track, step, par_layer, instrument, 0xc0);
#if DEBUG_VERBOSE_LEVEL >= 2
	    DEBUG_MSG("[SEQ_RECORD_Receive] free CC layer found for CC#%d in track #%d.%c\n", midi_package.cc_number, track+1, 'A'+par_layer);
#endif
	  }

	  free_layer_found = 1;
	  break;
	}
      }
    }

    if( !free_layer_found ) {
#if DEBUG_VERBOSE_LEVEL >= 2
      DEBUG_MSG("[SEQ_RECORD_Receive] no free CC layer found for CC#%d\n", midi_package.cc_number);
#endif
      return 0; // no free layer
    }
  }
#endif

#if DEBUG_VERBOSE_LEVEL >= 2
  DEBUG_MSG("[SEQ_RECORD_Receive] %02x %02x %02x -> track #%d\n", 
	    midi_package.evnt0, midi_package.evnt1, midi_package.evnt2, 
	    track+1);
#endif

  // exit if track number too high
  if( track >= SEQ_CORE_NUM_TRACKS )
    return -1; // unsupported track

  seq_core_trk_t *t = &seq_core_trk[track];
  seq_cc_trk_t *tcc = &seq_cc_trk[track];

  // branch depending on event
  u8 rec_event = 0;
  u8 send_note_off = 0;
  switch( midi_package.event ) {
    case NoteOff:
    case NoteOn: {
      midi_package.note &= 0x7f; // to avoid array overwrites
      u32 note_mask = 1 << (midi_package.note & 0x1f);

      // if Note Off and new note number matches with recorded note number
      if( midi_package.event == NoteOff || midi_package.velocity == 0 ) {
	if( seq_record_played_notes[midi_package.note>>5] & note_mask ) {
	  MIOS32_IRQ_Disable();
	  // note not active anymore
	  seq_record_played_notes[midi_package.note>>5] &= ~note_mask;

	  // determine duration in mS (for step recording function)
	  u16 duration_ms = MIOS32_TIMESTAMP_Get() - seq_record_note_timestamp_ms[midi_package.note];
	  // map to BPM
	  int duration = (int)((float)duration_ms / ((1000.0*60.0) / SEQ_BPM_EffectiveGet() / (float)SEQ_BPM_PPQN_Get()));
#if DEBUG_VERBOSE_LEVEL >= 3
	  DEBUG_MSG("[SEQ_RECORD_Receive] duration of note 0x%02x was %d mS (%d ticks)\n",
		    midi_package.note, duration_ms, duration);
#endif	  

	  // insert length into current step
	  u8 instrument = 0;
	  int len;
	  if( step_record_mode ) {
	    len = 71; // 75%
	    if( tcc->event_mode != SEQ_EVENT_MODE_Drum )
	      len = (duration <= 96) ? duration : 96; // for duration >= 96 the length will be stretched after record
	  } else {
	    len = SEQ_BPM_TickGet() - t->rec_timestamp;

	    if( len < 1 )
	      len = 1;
	    else if( len > 95 )
	      len = 95;
	  }

	  int len_step = step_record_mode ? ui_selected_step : t->step;
	  u8 num_p_layers = SEQ_PAR_NumLayersGet(track);

	  while( 1 ) {
	    if( tcc->event_mode == SEQ_EVENT_MODE_Combined ) {
	      // extra for MBSEQ V4L:
	      // search for note in track 1/8, insert length into track 3/10
	      int par_layer;
	      for(par_layer=0; par_layer<num_p_layers; ++par_layer) {
		if( SEQ_PAR_Get(track, len_step, par_layer, instrument) == midi_package.note ) {
		  SEQ_PAR_Set(track+2, len_step, par_layer, instrument, len);
		  break;
		}
	      }
	    } else {
	      if( tcc->link_par_layer_length >= 0 )
		SEQ_PAR_Set(track, len_step, tcc->link_par_layer_length, instrument, len);
	    }

	    if( !step_record_mode )
	      break;
	    if( tcc->event_mode == SEQ_EVENT_MODE_Drum )
	      break;
	    if( duration <= 0 )
	      break;
	    duration -= 96;

	    // insert length into all following steps until a gate is set
	    if( ++len_step > tcc->length ) // TODO: handle this correctly if track is played backwards
	      len_step = tcc->loop;

	    if( SEQ_TRG_GateGet(track, len_step, instrument) )
	      break;

	    len = (duration > 0) ? 96 : -duration;

	    // copy notes
	    u8 *layer_type_ptr = (u8 *)&tcc->lay_const[0*16];
	    int par_layer;
	    for(par_layer=0; par_layer<num_p_layers; ++par_layer, ++layer_type_ptr) {
	      if( *layer_type_ptr == SEQ_PAR_Type_Note || *layer_type_ptr == SEQ_PAR_Type_Chord ) {
		u8 note = SEQ_PAR_Get(track, ui_selected_step, par_layer, instrument);
		SEQ_PAR_Set(track, len_step, par_layer, instrument, note);
	      }
	    }
	  }

	  MIOS32_IRQ_Enable();
	}

	if( step_record_mode && seq_record_options.FWD_MIDI ) {
	  // send Note Off events of current track if no key is played anymore
	  u8 any_note_played = seq_record_played_notes[0] || seq_record_played_notes[1] || seq_record_played_notes[2] || seq_record_played_notes[3];
	  if( !any_note_played )
	    send_note_off = 1;     
	}
      } else {
	MIOS32_IRQ_Disable();

	if( step_record_mode && tcc->event_mode != SEQ_EVENT_MODE_Drum ) {
	  // check if another note is already played
	  u8 any_note_played = seq_record_played_notes[0] || seq_record_played_notes[1] || seq_record_played_notes[2] || seq_record_played_notes[3];
	  // if not: clear poly counter and all notes (so that new chord can be entered if all keys were released)
	  if( !any_note_played ) {
	    t->rec_poly_ctr = 0;

	    u8 num_p_layers = SEQ_PAR_NumLayersGet(track);
	    u8 *layer_type_ptr = (u8 *)&tcc->lay_const[0*16];
	    int par_layer;
	    u8 instrument = 0;
	    for(par_layer=0; par_layer<num_p_layers; ++par_layer, ++layer_type_ptr) {
	      if( *layer_type_ptr == SEQ_PAR_Type_Note || *layer_type_ptr == SEQ_PAR_Type_Chord )
		SEQ_PAR_Set(track, ui_selected_step, par_layer, instrument, 0x00);
	    }
	  }
	}

	// note is active
	seq_record_played_notes[midi_package.note>>5] |= note_mask;
	// start measuring length
	t->rec_timestamp = SEQ_BPM_TickGet();
	// for step record function: independent from BPM
	seq_record_note_timestamp_ms[midi_package.note & 0x7f] = MIOS32_TIMESTAMP_Get(); // note: 16bit only

	MIOS32_IRQ_Enable();

	// record event
	rec_event = 1;
      }
    } break;

    case CC:
    case PitchBend: {
      rec_event = 1;
    } break;

    default: {
#if DEBUG_VERBOSE_LEVEL >= 2
      DEBUG_MSG("[SEQ_RECORD_Receive] event %x not supported.\n", midi_package.event);
#endif
      return -2; // unsupported event
    }
  }
Пример #11
0
/////////////////////////////////////////////////////////////////////////////
// This hook is called before the shift register chain is scanned
/////////////////////////////////////////////////////////////////////////////
void APP_SRIO_ServicePrepare(void)
{
  static u8 led_digit_ctr = 0;
  if( ++led_digit_ctr >= 7 )
    led_digit_ctr = 0;

#ifndef MBSEQV4L
  if( seq_hwcfg_blm.enabled ) {
    // prepare DOUT registers of BLM to drive the column
    BLM_PrepareCol();
  }
#else
  BLM_CHEAPO_PrepareCol();
#endif

  if( seq_hwcfg_blm8x8.enabled ) {
    // prepare DOUT registers of 8x8 BLM to drive the row
    BLM_X_PrepareRow();
  }

  // TK: using MIOS32_DOUT_SRSet/PinSet instead of SEQ_LED_SRSet/PinSet to ensure compatibility with MBSEQV4L
  if( seq_hwcfg_bpm_digits.enabled ) {
    // invert for common anodes
    u8 inversion_mask = (seq_hwcfg_bpm_digits.enabled == 2) ? 0xff : 0x00;
    u8 common_enable = (seq_hwcfg_bpm_digits.enabled == 2) ? 1 : 0;

    float bpm = SEQ_BPM_EffectiveGet();
    if( led_digit_ctr == 0 ) {
      u8 sr_value = SEQ_LED_DigitPatternGet(((int)(bpm*10)) % 10);
      MIOS32_DOUT_SRSet(seq_hwcfg_bpm_digits.segments_sr - 1, sr_value ^ inversion_mask);
      MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common1_pin, common_enable);
      MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common2_pin, !common_enable);
      MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common3_pin, !common_enable);
      MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common4_pin, !common_enable);
    } else if( led_digit_ctr == 1 ) {
      u8 sr_value = SEQ_LED_DigitPatternGet((int)bpm % 10) | 0x80; // +dot
      MIOS32_DOUT_SRSet(seq_hwcfg_bpm_digits.segments_sr - 1, sr_value ^ inversion_mask);
      MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common1_pin, !common_enable);
      MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common2_pin, common_enable);
      MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common3_pin, !common_enable);
      MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common4_pin, !common_enable);
    } else if( led_digit_ctr == 2 ) {
      u8 sr_value = SEQ_LED_DigitPatternGet(((int)bpm / 10) % 10);
      MIOS32_DOUT_SRSet(seq_hwcfg_bpm_digits.segments_sr - 1, sr_value ^ inversion_mask);
      MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common1_pin, !common_enable);
      MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common2_pin, !common_enable);
      MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common3_pin, common_enable);
      MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common4_pin, !common_enable);
    } else if( led_digit_ctr == 3 ) {
      u8 sr_value = SEQ_LED_DigitPatternGet(((int)bpm / 100) % 10);
      MIOS32_DOUT_SRSet(seq_hwcfg_bpm_digits.segments_sr - 1, sr_value ^ inversion_mask);
      MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common1_pin, !common_enable);
      MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common2_pin, !common_enable);
      MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common3_pin, !common_enable);
      MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common4_pin, common_enable);
    }
    else { // not displaying bpm digit in this cycle, disable common pins
      MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common1_pin, !common_enable);
      MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common2_pin, !common_enable);
      MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common3_pin, !common_enable);
      MIOS32_DOUT_PinSet(seq_hwcfg_bpm_digits.common4_pin, !common_enable);
    }
  }

  if( seq_hwcfg_step_digits.enabled ) {
    // invert for common anodes
    u8 inversion_mask = (seq_hwcfg_step_digits.enabled == 2) ? 0xff : 0x00;
    u8 common_enable = (seq_hwcfg_step_digits.enabled == 2) ? 1 : 0;
    
    int step = (int)(SEQ_BPM_IsRunning() ? seq_core_trk[SEQ_UI_VisibleTrackGet()].step : ui_selected_step) + 1;
    if( led_digit_ctr == 4 ) {
      u8 sr_value = SEQ_LED_DigitPatternGet(step % 10);
      MIOS32_DOUT_SRSet(seq_hwcfg_step_digits.segments_sr - 1, sr_value ^ inversion_mask);
      MIOS32_DOUT_PinSet(seq_hwcfg_step_digits.common1_pin, common_enable);
      MIOS32_DOUT_PinSet(seq_hwcfg_step_digits.common2_pin, !common_enable);
      MIOS32_DOUT_PinSet(seq_hwcfg_step_digits.common3_pin, !common_enable);
    } else if( led_digit_ctr == 5 ) {
      u8 sr_value = SEQ_LED_DigitPatternGet((step / 10) % 10);
      MIOS32_DOUT_SRSet(seq_hwcfg_step_digits.segments_sr - 1, sr_value ^ inversion_mask);
      MIOS32_DOUT_PinSet(seq_hwcfg_step_digits.common1_pin, !common_enable);
      MIOS32_DOUT_PinSet(seq_hwcfg_step_digits.common2_pin, common_enable);
      MIOS32_DOUT_PinSet(seq_hwcfg_step_digits.common3_pin, !common_enable);
    } else if( led_digit_ctr == 6 ) {
      u8 sr_value = SEQ_LED_DigitPatternGet((step / 100) % 10);
      MIOS32_DOUT_SRSet(seq_hwcfg_step_digits.segments_sr - 1, sr_value ^ inversion_mask);
      MIOS32_DOUT_PinSet(seq_hwcfg_step_digits.common1_pin, !common_enable);
      MIOS32_DOUT_PinSet(seq_hwcfg_step_digits.common2_pin, !common_enable);
      MIOS32_DOUT_PinSet(seq_hwcfg_step_digits.common3_pin, common_enable);
    }
    else { // not displaying step digit in this cycle, disable common pins
      MIOS32_DOUT_PinSet(seq_hwcfg_step_digits.common1_pin, !common_enable);
      MIOS32_DOUT_PinSet(seq_hwcfg_step_digits.common2_pin, !common_enable);
      MIOS32_DOUT_PinSet(seq_hwcfg_step_digits.common3_pin, !common_enable);
    }    
  }
  
  SEQ_TPD_LED_Update();     
}
Пример #12
0
/////////////////////////////////////////////////////////////////////////////
//! This function can overrule the display output
//! If it returns 0, the original SCS output will be print
//! If it returns 1, the output copied into line1 and/or line2 will be print
//! If a line is not changed (line[0] = 0 or line[1] = 0), the original output
//! will be displayed - this allows to overrule only a single line
/////////////////////////////////////////////////////////////////////////////
static s32 displayHook(char *line1, char *line2)
{
  static u8 special_chars_from_mbng = 0;

  // switch between charsets
  if( SCS_MenuStateGet() == SCS_MENU_STATE_MAINPAGE && !special_chars_from_mbng ) {
    special_chars_from_mbng = 1;
    MBNG_LCD_SpecialCharsReInit();
  } else if( SCS_MenuStateGet() != SCS_MENU_STATE_MAINPAGE && special_chars_from_mbng ) {
    special_chars_from_mbng = 0;
    SCS_LCD_SpecialCharsReInit();
  }

  if( SCS_MenuStateGet() != SCS_MENU_STATE_MAINPAGE && extraPage ) {
    char msdStr[5];
    TASK_MSD_FlagStrGet(msdStr);

    u8 clkMode = SEQ_BPM_ModeGet();
    sprintf(line1, "Clk  BPM  DOUT MSD  ");
    sprintf(line2, "%s %s Off  %s",
	    SEQ_BPM_IsRunning() ? "STOP" : "PLAY",
	    (clkMode == SEQ_BPM_MODE_Slave) ? "Slve" : ((clkMode == SEQ_BPM_MODE_Master) ? "Mstr" : "Auto"),
	    TASK_MSD_EnableGet() ? msdStr : "----");
    return 1;
  }

  // overlay in MSD mode (user should disable soon since this sucks performance)
  if( TASK_MSD_EnableGet() ) {
    char msdStr[5];
    TASK_MSD_FlagStrGet(msdStr);

    sprintf(line1, "[ MSD ACTIVE: %s ]", msdStr);
  }

  if( SCS_MenuStateGet() == SCS_MENU_STATE_MAINPAGE ) {
    // overlayed by LCD handler in MBNG_LCD!
    // only exception: not in MIDI learn mode
    if( MBNG_EVENT_MidiLearnModeGet() ) {
      MBNG_EVENT_MidiLearnStatusMsg(line1, line2);
      SCS_DisplayUpdateRequest(); // fast updates
    } else if( MBNG_EVENT_EventLearnIdGet() ) {
      MBNG_EVENT_EventLearnStatusMsg(line1, line2);
      SCS_DisplayUpdateRequest(); // fast updates
    }

    return 1;
  }

  if( SCS_MenuStateGet() == SCS_MENU_STATE_SELECT_PAGE ) {
    if( line1[0] == 0 ) { // no MSD overlay?
      if( MBNG_FILE_StatusMsgGet() )
	sprintf(line1, MBNG_FILE_StatusMsgGet());
      else
	sprintf(line1, "Config: %s", mbng_file_c_config_name);
    }
    return 1;
  }

  if( SCS_MenuPageGet() == pageDsk ) {
    // Disk page: we want to show the patch at upper line, and menu items at lower line
    if( line1[0] == 0 ) { // no MSD overlay?
      if( MBNG_FILE_StatusMsgGet() )
	sprintf(line1, MBNG_FILE_StatusMsgGet());
      else
	sprintf(line1, "Config: %s", mbng_file_c_config_name);
    }
    sprintf(line2, "Load Save");
    return 1;
  }

  if( SCS_MenuPageGet() == pageMON ) {
    u8 fastRefresh = line1[0] == 0;

    int i;
    for(i=0; i<SCS_NumMenuItemsGet(); ++i) {
      u8 portIx = 1 + i + monPageOffset;

      if( fastRefresh ) { // no MSD overlay?
	mios32_midi_port_t port = MIDI_PORT_InPortGet(portIx);
	mios32_midi_package_t package = MIDI_PORT_InPackageGet(port);
	if( port == 0xff ) {
	  strcat(line1, "     ");
	} else if( package.type ) {
	  char buffer[6];
	  MIDI_PORT_EventNameGet(package, buffer, 5);
	  strcat(line1, buffer);
	} else {
	  strcat(line1, MIDI_PORT_InNameGet(portIx));
	  strcat(line1, " ");
	}

	// insert arrow at upper right corner
	int numItems = MIDI_PORT_OutNumGet() - 1;
	int lastColumn = SCS_NumMenuItemsGet()*SCS_MENU_ITEM_WIDTH - 1;
	if( monPageOffset == 0 )
	  line1[lastColumn] = MIOS32_LCD_TypeIsGLCD() ? '>' : 3; // right arrow
	else if( monPageOffset >= (numItems-SCS_NumMenuItemsGet()) )
	  line1[lastColumn] = MIOS32_LCD_TypeIsGLCD() ? '<' : 1; // left arrow
	else
	  line1[lastColumn] = MIOS32_LCD_TypeIsGLCD() ? '-' : 2; // left/right arrow
      }

      mios32_midi_port_t port = MIDI_PORT_OutPortGet(portIx);
      mios32_midi_package_t package = MIDI_PORT_OutPackageGet(port);
      if( port == 0xff ) {
	strcat(line2, "     ");
      } else if( package.type ) {
	char buffer[6];
	MIDI_PORT_EventNameGet(package, buffer, 5);
	strcat(line2, buffer);
      } else {
	strcat(line2, MIDI_PORT_OutNameGet(portIx));
	strcat(line2, " ");
      }
    }

    // request LCD update - this will lead to fast refresh rate in monitor screen
    if( fastRefresh )
      SCS_DisplayUpdateRequest();

    return 1;
  }

  if( SCS_MenuPageGet() == pageLearn ) {
    if( MBNG_EVENT_MidiLearnModeGet() ) {
      MBNG_EVENT_MidiLearnStatusMsg(line1, line2);
    } else {
      if( line1[0] == 0 ) { // no MSD overlay?
	sprintf(line1, "  Common  NRPN      ");
      }
      sprintf(line2, "  Learn   Learn     ");
    }

    // fast updates
    SCS_DisplayUpdateRequest();

    return 1;
  }

  return (line1[0] != 0) ? 1 : 0; // return 1 if MSD overlay
}
Пример #13
0
static void stringStop(u32 ix, u16 value, char *label)
{
  sprintf(label, SEQ_BPM_IsRunning() ? "    " : " ** ");
}
Пример #14
0
static void stringPlay(u32 ix, u16 value, char *label)
{
  sprintf(label, SEQ_BPM_IsRunning() ? " ** " : "    ");
}