/////////////////////////////////////////////////////////////////////////////
// Initialisation
/////////////////////////////////////////////////////////////////////////////
s32 SEQ_UI_TRKMODE_Init(u32 mode)
{
    // install callback routines
    SEQ_UI_InstallButtonCallback(Button_Handler);
    SEQ_UI_InstallEncoderCallback(Encoder_Handler);
    SEQ_UI_InstallLEDCallback(LED_Handler);
    SEQ_UI_InstallLCDCallback(LCD_Handler);

    return 0; // no error
}
/////////////////////////////////////////////////////////////////////////////
// Initialisation
/////////////////////////////////////////////////////////////////////////////
s32 SEQ_UI_MIDI_Init(u32 mode)
{
  // install callback routines
  SEQ_UI_InstallButtonCallback(Button_Handler);
  SEQ_UI_InstallEncoderCallback(Encoder_Handler);
  SEQ_UI_InstallLEDCallback(LED_Handler);
  SEQ_UI_InstallLCDCallback(LCD_Handler);
  SEQ_UI_InstallExitCallback(EXIT_Handler);

  store_file_required = 0;

  return 0; // no error
}
Beispiel #3
0
/////////////////////////////////////////////////////////////////////////////
// Initialisation
/////////////////////////////////////////////////////////////////////////////
s32 SEQ_UI_INFO_Init(u32 mode)
{
  // install callback routines
  SEQ_UI_InstallButtonCallback(Button_Handler);
  SEQ_UI_InstallEncoderCallback(Encoder_Handler);
  SEQ_UI_InstallLEDCallback(LED_Handler);
  SEQ_UI_InstallLCDCallback(LCD_Handler);

  // load charset (if this hasn't been done yet)
  SEQ_LCD_InitSpecialChars(SEQ_LCD_CHARSET_Menu);

  SEQ_UI_INFO_UpdateList();

  return 0; // no error
}
Beispiel #4
0
/////////////////////////////////////////////////////////////////////////////
// Initialisation
/////////////////////////////////////////////////////////////////////////////
s32 SEQ_UI_BPM_Init(u32 mode)
{
  // install callback routines
  SEQ_UI_InstallButtonCallback(Button_Handler);
  SEQ_UI_InstallEncoderCallback(Encoder_Handler);
  SEQ_UI_InstallLEDCallback(LED_Handler);
  SEQ_UI_InstallLCDCallback(LCD_Handler);
  SEQ_UI_InstallExitCallback(EXIT_Handler);

  store_file_required = 0;

  // reset tap tempo function
  resetTapTempo();

  return 0; // no error
}
/////////////////////////////////////////////////////////////////////////////
// Initialisation
/////////////////////////////////////////////////////////////////////////////
s32 SEQ_UI_SYSEX_Init(u32 mode)
{
  // install callback routines
  SEQ_UI_InstallButtonCallback(Button_Handler);
  SEQ_UI_InstallEncoderCallback(Encoder_Handler);
  SEQ_UI_InstallLEDCallback(LED_Handler);
  SEQ_UI_InstallLCDCallback(LCD_Handler);

  // load charset (if this hasn't been done yet)
  SEQ_LCD_InitSpecialChars(SEQ_LCD_CHARSET_Menu);

  dir_name[0] = 0;

#if TEST_LIST
  dir_num_items = 32;
#else
  SEQ_UI_SYSEX_UpdateDirList();
#endif

  return 0; // no error
}
Beispiel #6
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
    last_bookmark = encoder;
    SEQ_UI_Bookmark_Restore(last_bookmark);
    return 1;
  }

  // all other encoders
  return -1;
}


/////////////////////////////////////////////////////////////////////////////
// button callback function
// Also used by SEQ_UI_Button_DirectBookmark
// Should return:
//   1 if value has been changed
//   0 if value hasn't been changed
//  -1 if invalid or unsupported button
/////////////////////////////////////////////////////////////////////////////
s32 SEQ_UI_BOOKMARKS_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 ) {
      SEQ_UI_UnInstallDelayedActionCallback(Button_StoreRequest);
      if( store_state == 1 ) { // depressed within 1 second: select bookmark
	SEQ_UI_Bookmark_Restore(last_bookmark);
      }
      return 0;
    }
    last_bookmark = button;
    store_state = 1;
    SEQ_UI_InstallDelayedActionCallback(Button_StoreRequest, 500, 0);

    return 1;
  }

#if 0
  // doesn't make much sense here
  switch( button ) {
    case SEQ_UI_BUTTON_Select:
    case SEQ_UI_BUTTON_Right:
    case SEQ_UI_BUTTON_Up:
      return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, 1);

    case SEQ_UI_BUTTON_Left:
    case SEQ_UI_BUTTON_Down:
      return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, -1);
  }
#endif

  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)
{
  if( high_prio )
    return 0; // there are no high-priority updates

  // layout:
  // 00000000001111111111222222222233333333330000000000111111111122222222223333333333
  // 01234567890123456789012345678901234567890123456789012345678901234567890123456789
  // <--------------------------------------><-------------------------------------->
  //             Global Bookmarks                        Session Bookmarks           
  // BM 1 BM 2 BM 3 BM 4 BM 5 BM 6 BM 7 BM 8 BM 9 BM10 BM11 BM12 BM13 BM14 BM15 BM16 

  SEQ_LCD_CursorSet(0, 0);
  SEQ_LCD_PrintString("            Global Bookmarks                        Session Bookmarks           ");

  SEQ_LCD_CursorSet(0, 1);
  int i;
  for(i=0; i<SEQ_UI_BOOKMARKS_NUM; ++i) {
    if( i >= 16 )
      break; // just to ensure...
    seq_ui_bookmark_t *bm = (seq_ui_bookmark_t *)&seq_ui_bookmarks[i];

    if( ui_cursor_flash && (i == last_bookmark) )
      SEQ_LCD_PrintSpaces(5);
    else
      SEQ_LCD_PrintStringPadded(bm->name, 5);
  }

  return 0; // no error
}


/////////////////////////////////////////////////////////////////////////////
// Initialisation
/////////////////////////////////////////////////////////////////////////////
s32 SEQ_UI_BOOKMARKS_Init(u32 mode)
{
  // install callback routines
  SEQ_UI_InstallButtonCallback(SEQ_UI_BOOKMARKS_Button_Handler);
  SEQ_UI_InstallEncoderCallback(Encoder_Handler);
  SEQ_UI_InstallLEDCallback(LED_Handler);
  SEQ_UI_InstallLCDCallback(LCD_Handler);

  store_state = 0;

  return 0; // no error
}


/////////////////////////////////////////////////////////////////////////////
// help function for delayed store action
/////////////////////////////////////////////////////////////////////////////
static void Button_StoreRequest(u32 state)
{
  if( store_state == 1 ) {
    SEQ_UI_Msg(last_bookmark >= 8 ? SEQ_UI_MSG_DELAYED_ACTION_R : SEQ_UI_MSG_DELAYED_ACTION, 2001,
	       "Hold Button", "to store Bookmark!");
    SEQ_UI_InstallDelayedActionCallback(Button_StoreRequest, 2000, 0);
    store_state = 2;
  } else {
    store_state = 0;
    // store into selected slot
    SEQ_UI_Bookmark_Store(last_bookmark);

    SEQ_UI_Msg(last_bookmark >= 8 ? SEQ_UI_MSG_USER_R : SEQ_UI_MSG_USER, 2000,
	       "Storing", "Bookmark!");      
#if !defined(MIOS32_FAMILY_EMULATION)
    // this yield ensures, that the display will be updated before storing the file
    taskYIELD();
#endif
    // and store file
    MUTEX_SDCARD_TAKE;
    s32 error = SEQ_FILE_BM_Write(seq_file_session_name, (last_bookmark < 8) ? 1 : 0);
    MUTEX_SDCARD_GIVE;
    if( error < 0 )
      SEQ_UI_SDCardErrMsg(2000, error);
    else {
      // return to bookmarked page
      SEQ_UI_PageSet((seq_ui_page_t)seq_ui_bookmarks[last_bookmark].page);

      // and print message
      SEQ_UI_Msg(last_bookmark >= 8 ? SEQ_UI_MSG_USER_R : SEQ_UI_MSG_USER, 2000,
		 "Bookmark", "stored!");      
    }
  }
}
/////////////////////////////////////////////////////////////////////////////
// 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
    // re-use encoder handler - only select UI item, don't increment
    return Encoder_Handler((int)button, 0);
  }

  // remaining buttons:
  switch( button ) {
    case SEQ_UI_BUTTON_Select:
    case SEQ_UI_BUTTON_Right:
      if( ++ui_selected_item >= NUM_OF_ITEMS )
	ui_selected_item = 0;
      return 1; // value always changed

    case SEQ_UI_BUTTON_Left:
      if( ui_selected_item == 0 )
	ui_selected_item = NUM_OF_ITEMS-1;
      else
	--ui_selected_item;
      return 1; // value always changed

    case SEQ_UI_BUTTON_Up:
      return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, 1);

    case SEQ_UI_BUTTON_Down:
      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)
{
  if( high_prio )
    return 0; // there are no high-priority updates

  // layout:
  // 00000000001111111111222222222233333333330000000000111111111122222222223333333333
  // 01234567890123456789012345678901234567890123456789012345678901234567890123456789
  // <--------------------------------------><-------------------------------------->
  // Trk.        Repeats   Delay   Vel.Level  FB Velocity  Note   Gatelen.    Ticks  
  // GxTy           3       1/16      75%        120%       + 0     100%       100%

  u8 visible_track = SEQ_UI_VisibleTrackGet();

  ///////////////////////////////////////////////////////////////////////////
  SEQ_LCD_CursorSet(0, 0);
  SEQ_LCD_PrintString("Trk.        Repeats   Delay   Vel.Level  FB Velocity  Note   Gatelen.    Ticks  ");

  ///////////////////////////////////////////////////////////////////////////
  SEQ_LCD_CursorSet(0, 1);

  if( ui_selected_item == ITEM_GXTY && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(4);
  } else {
    SEQ_LCD_PrintGxTy(ui_selected_group, ui_selected_tracks);
  }
  SEQ_LCD_PrintSpaces(10);

  ///////////////////////////////////////////////////////////////////////////

  if( ui_selected_item == ITEM_REPEATS && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(2);
  } else {
    SEQ_LCD_PrintFormattedString("%2d", SEQ_CC_Get(visible_track, SEQ_CC_ECHO_REPEATS));
  }
  SEQ_LCD_PrintSpaces(7);

  ///////////////////////////////////////////////////////////////////////////

  if( ui_selected_item == ITEM_DELAY && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(4);
  } else {
    SEQ_LCD_PrintString((char *)SEQ_CORE_Echo_GetDelayModeName(SEQ_CC_Get(visible_track, SEQ_CC_ECHO_DELAY)));
  }
  SEQ_LCD_PrintSpaces(6);

  ///////////////////////////////////////////////////////////////////////////

  if( ui_selected_item == ITEM_VELOCITY && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(4);
  } else {
    SEQ_LCD_PrintFormattedString("%3d%%", 5*SEQ_CC_Get(visible_track, SEQ_CC_ECHO_VELOCITY));
  }
  SEQ_LCD_PrintSpaces(2);

  ///////////////////////////////////////////////////////////////////////////

  SEQ_LCD_CursorSet(40, 1);
  SEQ_LCD_PrintSpaces(4);

  if( ui_selected_item == ITEM_FB_VELOCITY && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(4);
  } else {
    SEQ_LCD_PrintFormattedString("%3d%%", 5*SEQ_CC_Get(visible_track, SEQ_CC_ECHO_FB_VELOCITY));
  }
  SEQ_LCD_PrintSpaces(7);

  ///////////////////////////////////////////////////////////////////////////

  if( ui_selected_item == ITEM_FB_NOTE && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(3);
  } else {
    u8 note_delta = SEQ_CC_Get(visible_track, SEQ_CC_ECHO_FB_NOTE);
    if( note_delta < 24 )
      SEQ_LCD_PrintFormattedString("-%2d", 24-note_delta);
    else if( note_delta < 49 )
      SEQ_LCD_PrintFormattedString("+%2d", note_delta-24);
    else
      SEQ_LCD_PrintString("Rnd");
  }
  SEQ_LCD_PrintSpaces(5);

  ///////////////////////////////////////////////////////////////////////////

  if( ui_selected_item == ITEM_FB_GATELENGTH && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(4);
  } else {
    SEQ_LCD_PrintFormattedString("%3d%%", 5*SEQ_CC_Get(visible_track, SEQ_CC_ECHO_FB_GATELENGTH));
  }
  SEQ_LCD_PrintSpaces(7);

  ///////////////////////////////////////////////////////////////////////////

  if( ui_selected_item == ITEM_FB_TICKS && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(4);
  } else {
    SEQ_LCD_PrintFormattedString("%3d%%", 5*SEQ_CC_Get(visible_track, SEQ_CC_ECHO_FB_TICKS));
  }
  SEQ_LCD_PrintSpaces(2);


  return 0; // no error
}


/////////////////////////////////////////////////////////////////////////////
// Initialisation
/////////////////////////////////////////////////////////////////////////////
s32 SEQ_UI_FX_ECHO_Init(u32 mode)
{
  // install callback routines
  SEQ_UI_InstallButtonCallback(Button_Handler);
  SEQ_UI_InstallEncoderCallback(Encoder_Handler);
  SEQ_UI_InstallLEDCallback(LED_Handler);
  SEQ_UI_InstallLCDCallback(LCD_Handler);

  return 0; // no error
}
Beispiel #8
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)
{
  // ensure that original screen will be print immediately
  ui_hold_msg_ctr = 0;

#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
    // select step within view
    ui_selected_step = (ui_selected_step_view << 4) | (u8)encoder;

    // show edit page for 2 seconds
    ui_hold_msg_ctr = 2000;

    // forward manual trigger to SEQ_CORE
    SEQ_CORE_ManualTrigger(ui_selected_step);

    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( depressed ) return 0; // ignore when button depressed

  // ensure that original screen will be print immediately
  ui_hold_msg_ctr = 0;

#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: {
      // Request synch to measure for all selected tracks
      SEQ_CORE_ManualSynchToMeasure();
      return 1;
    } break;

    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)
{
  // branch to edit page if requested
  if( ui_hold_msg_ctr )
    return SEQ_UI_EDIT_LCD_Handler(high_prio, SEQ_UI_EDIT_MODE_MANUAL);


  // layout:
  // 00000000001111111111222222222233333333330000000000111111111122222222223333333333
  // 01234567890123456789012345678901234567890123456789012345678901234567890123456789
  // <--------------------------------------><-------------------------------------->
  //   Selected Tracks: 1234 1234 1234 1234     Press SELECT to Synch to Measure!    
  // lower line: print step 1..16/17..32/...

  ///////////////////////////////////////////////////////////////////////////
  SEQ_LCD_CursorSet(0, 0);
  SEQ_LCD_PrintString("  Selected Tracks: ");

  u8 track;
  for(track=0; track<16; ++track) {
    if( seq_core_trk[track].state.SYNC_MEASURE )
      SEQ_LCD_PrintChar('S');
    else if( SEQ_UI_IsSelectedTrack(track) )
      SEQ_LCD_PrintChar('*');
    else
      SEQ_LCD_PrintChar('1' + (track&3));

    if( (track&3) == 3 )
      SEQ_LCD_PrintChar(' ');
  }
  SEQ_LCD_PrintSpaces(1);

  SEQ_LCD_PrintString("   Press SELECT to Synch to Measure!    ");


  ///////////////////////////////////////////////////////////////////////////
  SEQ_LCD_CursorSet(0, 1);

  u8 step;
  for(step=0; step<16; ++step)
    SEQ_LCD_PrintFormattedString(" %2d  ", 16*ui_selected_step_view + step + 1);

  return 0; // no error
}


/////////////////////////////////////////////////////////////////////////////
// Initialisation
/////////////////////////////////////////////////////////////////////////////
s32 SEQ_UI_MANUAL_Init(u32 mode)
{
  // install callback routines
  SEQ_UI_InstallButtonCallback(Button_Handler);
  SEQ_UI_InstallEncoderCallback(Encoder_Handler);
  SEQ_UI_InstallLEDCallback(LED_Handler);
  SEQ_UI_InstallLCDCallback(LCD_Handler);

  return 0; // no error
}
/////////////////////////////////////////////////////////////////////////////
// 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
    // re-use encoder handler - only select UI item, don't increment
    return Encoder_Handler((int)button, 0);
  }

  // remaining buttons:
  switch( button ) {
    case SEQ_UI_BUTTON_Select:
    case SEQ_UI_BUTTON_Right:
      if( ++ui_selected_item >= NUM_OF_ITEMS )
	ui_selected_item = 0;
      return 1; // value always changed

    case SEQ_UI_BUTTON_Left:
      if( ui_selected_item == 0 )
	ui_selected_item = NUM_OF_ITEMS-1;
      else
	--ui_selected_item;
      return 1; // value always changed

    case SEQ_UI_BUTTON_Up:
      return Encoder_Handler(SEQ_UI_ENCODER_Datawheel, 1);

    case SEQ_UI_BUTTON_Down:
      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)
{
  if( high_prio )
    return 0; // there are no high-priority updates

  // layout:
  // 00000000001111111111222222222233333333330000000000111111111122222222223333333333
  // 01234567890123456789012345678901234567890123456789012345678901234567890123456789
  // <--------------------------------------><-------------------------------------->
  // Trk. Wave Amp. Phs. Steps Rst OneShot   Note Vel. Len.  CC   ExtraCC# Offs. PPQN
  // GxTy Sine   64   0%   16   16  on        off  off  off  off        001   64  384

  u8 visible_track = SEQ_UI_VisibleTrackGet();

  ///////////////////////////////////////////////////////////////////////////
  SEQ_LCD_CursorSet(0, 0);
  SEQ_LCD_PrintString("Trk. Wave Amp. Phs. Steps Rst OneShot   Note Vel. Len.  CC   ExtraCC# Offs. PPQN");

  ///////////////////////////////////////////////////////////////////////////
  SEQ_LCD_CursorSet(0, 1);

  if( ui_selected_item == ITEM_GXTY && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(4);
  } else {
    SEQ_LCD_PrintGxTy(ui_selected_group, ui_selected_tracks);
  }
  SEQ_LCD_PrintSpaces(1);

  ///////////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_WAVEFORM && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(5);
  } else {
    u8 value = SEQ_CC_Get(visible_track, SEQ_CC_LFO_WAVEFORM);

    if( value <= 3 ) {
      const char waveform_str[4][6] = {
	" off ",
	"Sine ",
	"Tri. ",
	"Saw. "
      };

      SEQ_LCD_PrintString((char *)waveform_str[value]);
    } else {
      SEQ_LCD_PrintFormattedString(" R%02d ", (value-4+1)*5);
    }
  }

  ///////////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_AMPLITUDE && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(5);
  } else {
    int value = (int)SEQ_CC_Get(visible_track, SEQ_CC_LFO_AMPLITUDE) - 128;
    SEQ_LCD_PrintFormattedString("%4d ", value);
  }

  ///////////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_PHASE && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(6);
  } else {
    SEQ_LCD_PrintFormattedString("%3d%%  ", SEQ_CC_Get(visible_track, SEQ_CC_LFO_PHASE));
  }

  ///////////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_STEPS && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(5);
  } else {
    SEQ_LCD_PrintFormattedString("%3d  ", (int)SEQ_CC_Get(visible_track, SEQ_CC_LFO_STEPS)+1);
  }

  ///////////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_STEPS_RST && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(4);
  } else {
    SEQ_LCD_PrintFormattedString("%3d ", (int)SEQ_CC_Get(visible_track, SEQ_CC_LFO_STEPS_RST)+1);
  }

  ///////////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_ENABLE_ONE_SHOT && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(5);
  } else {
    SEQ_LCD_PrintString((SEQ_CC_Get(visible_track, SEQ_CC_LFO_ENABLE_FLAGS) & (1 << 0)) ? "  on " : " off ");
  }

  SEQ_LCD_PrintSpaces(5);

  ///////////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_ENABLE_NOTE && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(5);
  } else {
    SEQ_LCD_PrintString((SEQ_CC_Get(visible_track, SEQ_CC_LFO_ENABLE_FLAGS) & (1 << 1)) ? "  on " : " off ");
  }

  ///////////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_ENABLE_VELOCITY && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(5);
  } else {
    SEQ_LCD_PrintString((SEQ_CC_Get(visible_track, SEQ_CC_LFO_ENABLE_FLAGS) & (1 << 2)) ? "  on " : " off ");
  }

  ///////////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_ENABLE_LENGTH && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(5);
  } else {
    SEQ_LCD_PrintString((SEQ_CC_Get(visible_track, SEQ_CC_LFO_ENABLE_FLAGS) & (1 << 3)) ? "  on " : " off ");
  }

  ///////////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_ENABLE_CC && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(5);
  } else {
    SEQ_LCD_PrintString((SEQ_CC_Get(visible_track, SEQ_CC_LFO_ENABLE_FLAGS) & (1 << 4)) ? "  on " : " off ");
  }

  ///////////////////////////////////////////////////////////////////////////
  SEQ_LCD_PrintSpaces(5);
  if( ui_selected_item == ITEM_CC && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(5);
  } else {
    u8 current_value = SEQ_CC_Get(visible_track, SEQ_CC_LFO_CC);
    u8 edit_value = (ui_selected_item == ITEM_CC) ? edit_cc_number : current_value;

    if( edit_value )
      SEQ_LCD_PrintFormattedString(" %03d", edit_value);
    else
      SEQ_LCD_PrintString(" ---");
    SEQ_LCD_PrintChar((current_value != edit_value) ? '!' : ' ');
  }

  ///////////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_CC_OFFSET && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(5);
  } else {
    SEQ_LCD_PrintFormattedString(" %3d ", SEQ_CC_Get(visible_track, SEQ_CC_LFO_CC_OFFSET));
  }

  ///////////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_CC_PPQN && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(5);
  } else {
    u8 value = SEQ_CC_Get(visible_track, SEQ_CC_LFO_CC_PPQN);
    int ppqn = 1;
    if( value )
      ppqn = 3 << (value-1);

    SEQ_LCD_PrintFormattedString(" %3d ", ppqn);
  }

  ///////////////////////////////////////////////////////////////////////////

  return 0; // no error
}


/////////////////////////////////////////////////////////////////////////////
// Initialisation
/////////////////////////////////////////////////////////////////////////////
s32 SEQ_UI_FX_LFO_Init(u32 mode)
{
  // install callback routines
  SEQ_UI_InstallButtonCallback(Button_Handler);
  SEQ_UI_InstallEncoderCallback(Encoder_Handler);
  SEQ_UI_InstallLEDCallback(LED_Handler);
  SEQ_UI_InstallLCDCallback(LCD_Handler);

  return 0; // no error
}