Exemplo n.º 1
0
/////////////////////////////////////////////////////////////////////////////
// LED update routine
/////////////////////////////////////////////////////////////////////////////
s32 SEQ_TPD_LED_Update(void)
{
  static u8 cycle_ctr = 0;
  
  if (cycle_ctr++ > 8)
     cycle_ctr = 0;

  // Power the corresponding column anode of this cycle
  MIOS32_DOUT_SRSet(seq_hwcfg_tpd.columns_sr - 1, (1 << cycle_ctr));         

  // Determine upper relative track position (tracks 1-8, "fall upward")
  s32 steps = SEQ_CC_Get(cycle_ctr, SEQ_CC_LENGTH);
  s32 curstep = seq_core_trk[cycle_ctr].step;
  u8 relpos_upper = 3 - (s32)(curstep << 2) / steps;
  
  // Determine lower relative track position (tracks 9-16, "fall downward")
  steps = SEQ_CC_Get(cycle_ctr + 8, SEQ_CC_LENGTH);
  curstep = seq_core_trk[cycle_ctr + 8].step;
  u8 relpos_lower = 4 + (s32)(curstep << 2)/ steps;
    
  // Gate the corresponding cathodes of this cycle (if the tracks are not muted)
  u8 setbyte = 0xFF;
  if (!(seq_core_trk_muted & (1 << cycle_ctr)))
     setbyte ^= (1 << relpos_upper);
  if (!(seq_core_trk_muted & (1 << (cycle_ctr + 8))))
     setbyte ^= (1 << relpos_lower);
  MIOS32_DOUT_SRSet(seq_hwcfg_tpd.rows_sr - 1, setbyte);
  
  return 0; // no error
}
Exemplo n.º 2
0
s32 SEQ_TERMINAL_PrintTracks(void *_output_function)
{
  void (*out)(char *format, ...) = _output_function;
  char str_buffer[128];

  MUTEX_MIDIOUT_TAKE;
  out("Track Overview:\n");
  out("===============\n");

  out("| Track | Mode  | Layer P/T/I | Steps P/T | Length | Port  | Chn. | Muted |\n");
  out("+-------+-------+-------------+-----------+--------+-------+------+-------+\n");

  u8 track;
  for(track=0; track<SEQ_CORE_NUM_TRACKS; ++track) {
    seq_event_mode_t event_mode = SEQ_CC_Get(track, SEQ_CC_MIDI_EVENT_MODE);
    u16 num_instruments = SEQ_TRG_NumInstrumentsGet(track);
    u16 num_par_layers = SEQ_PAR_NumLayersGet(track);
    u16 num_par_steps = SEQ_PAR_NumStepsGet(track);
    u16 num_trg_layers = SEQ_TRG_NumLayersGet(track);
    u16 num_trg_steps = SEQ_TRG_NumStepsGet(track);
    u16 length = (u16)SEQ_CC_Get(track, SEQ_CC_LENGTH) + 1;
    mios32_midi_port_t midi_port = SEQ_CC_Get(track, SEQ_CC_MIDI_PORT);
    u8 midi_chn = SEQ_CC_Get(track, SEQ_CC_MIDI_CHANNEL) + 1;

    sprintf(str_buffer, "| G%dT%d  | %s |",
	    (track/4)+1, (track%4)+1,
	    SEQ_LAYER_GetEvntModeName(event_mode));

    sprintf((char *)(str_buffer + strlen(str_buffer)), "   %2d/%2d/%2d  |  %3d/%3d  |   %3d  | %s%c |  %2d  |",
	    num_par_layers, num_trg_layers, num_instruments, 
	    num_par_steps, num_trg_steps,
	    length,
	    SEQ_MIDI_PORT_OutNameGet(SEQ_MIDI_PORT_OutIxGet(midi_port)),
	    SEQ_MIDI_PORT_OutCheckAvailable(midi_port) ? ' ' : '*',
	    midi_chn);

    if( seq_core_trk_muted & (1 << track) )
      sprintf((char *)(str_buffer + strlen(str_buffer)), "  yes  |\n");
    else if( seq_core_trk[track].layer_muted )
      sprintf((char *)(str_buffer + strlen(str_buffer)), " layer |\n");
    else
      sprintf((char *)(str_buffer + strlen(str_buffer)), "  no   |\n");

    out(str_buffer);
  }

  out("+-------+-------+-------------+-----------+--------+-------+------+-------+\n");

  out("done.\n");
  MUTEX_MIDIOUT_GIVE;

  return 0; // no error
}
Exemplo n.º 3
0
/////////////////////////////////////////////////////////////////////////////
// Local LED handler function
/////////////////////////////////////////////////////////////////////////////
static s32 LED_Handler(u16 *gp_leds)
{
  if( ui_cursor_flash ) // if flashing flag active: no LED flag set
    return 0;

  switch( ui_selected_item ) {
    case ITEM_GXTY: *gp_leds = 0x0001; break;
    case ITEM_WAVEFORM: *gp_leds = 0x0002; break;
    case ITEM_AMPLITUDE: *gp_leds = 0x0004; break;
    case ITEM_PHASE: *gp_leds = 0x0008; break;
    case ITEM_STEPS: *gp_leds = 0x0010; break;
    case ITEM_STEPS_RST: *gp_leds = 0x0020; break;
    case ITEM_ENABLE_ONE_SHOT: *gp_leds = 0x0040; break;
    case ITEM_ENABLE_NOTE: *gp_leds = 0x0100; break;
    case ITEM_ENABLE_VELOCITY: *gp_leds = 0x0200; break;
    case ITEM_ENABLE_LENGTH: *gp_leds = 0x0400; break;
    case ITEM_ENABLE_CC: *gp_leds = 0x0800; break;
    case ITEM_CC: *gp_leds = 0x2000; break;
    case ITEM_CC_OFFSET: *gp_leds = 0x2000; break;
    case ITEM_CC_PPQN: *gp_leds = 0x8000; break;
  }

#if 0
  // inconsistent and doesn't look so nice
  u8 visible_track = SEQ_UI_VisibleTrackGet();
  u8 flags = SEQ_CC_Get(visible_track, SEQ_CC_LFO_ENABLE_FLAGS);
  *gp_leds |= (((u16)(flags & 0x1e)) << 7) | (((u16)(flags & 0x01)) << 6);
#endif

  return 0; // no error
}
Exemplo n.º 4
0
/////////////////////////////////////////////////////////////////////////////
// Search for item in quick selection list
/////////////////////////////////////////////////////////////////////////////
static s32 QUICKSEL_SearchItem(u8 track)
{
  u8 search_pattern_length = SEQ_CC_Get(track, SEQ_CC_LENGTH);
  u8 search_pattern_loop = SEQ_CC_Get(track, SEQ_CC_LOOP);
  int i;

  if( quicksel_mode == QUICKSEL_MODE_LENGTH ) {
    for(i=0; i<8; ++i)
      if( ui_quicksel_length[i] == search_pattern_length )
	return i;
  } else {
    for(i=0; i<8; ++i)
      if( ui_quicksel_loop_length[i] == search_pattern_length && ui_quicksel_loop_loop[i] == search_pattern_loop )
	return i;
  }

  return -1; // item not found
}
Exemplo n.º 5
0
/////////////////////////////////////////////////////////////////////////////
// Local LED handler function
/////////////////////////////////////////////////////////////////////////////
static s32 LED_Handler(u16 *gp_leds)
{
  if( ui_cursor_flash ) // if flashing flag active: no LED flag set
    return 0;

  u8 visible_track = SEQ_UI_VisibleTrackGet();
  u8 event_mode = SEQ_CC_Get(visible_track, SEQ_CC_MIDI_EVENT_MODE);

  if( event_mode == SEQ_EVENT_MODE_Drum )
    *gp_leds = 1 << ui_selected_instrument;
  else
    *gp_leds = 1 << ui_selected_trg_layer;

  return 0; // no error
}
Exemplo n.º 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)
{
  u8 visible_track = SEQ_UI_VisibleTrackGet();
  u8 event_mode = SEQ_CC_Get(visible_track, SEQ_CC_MIDI_EVENT_MODE);

  if( encoder <= SEQ_UI_ENCODER_GP16 ) {
    // select new layer/instrument

    if( event_mode == SEQ_EVENT_MODE_Drum ) {
      if( encoder >= SEQ_TRG_NumInstrumentsGet(visible_track) )
	return -1;
      ui_selected_instrument = encoder;
    } else {
      if( encoder >= SEQ_TRG_NumLayersGet(visible_track) )
	return -1;
      ui_selected_trg_layer = encoder;
    }

    if( seq_hwcfg_button_beh.par_layer ) {
      // 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
      // (trigger gets deactivated when clicking on GP button or moving encoder)
      seq_ui_button_state.TRG_LAYER_SEL = 0;
      SEQ_UI_PageSet(ui_trglayer_prev_page);
    }

    return 1; // value changed
  } else if( encoder == SEQ_UI_ENCODER_Datawheel ) {
    if( event_mode == SEQ_EVENT_MODE_Drum ) {
      return SEQ_UI_Var8_Inc(&ui_selected_instrument, 0, SEQ_TRG_NumInstrumentsGet(visible_track)-1, incrementer);
    } else {
      return SEQ_UI_Var8_Inc(&ui_selected_trg_layer, 0, SEQ_TRG_NumLayersGet(visible_track)-1, incrementer);
    }
  }

  return -1; // invalid or unsupported encoder
}
/////////////////////////////////////////////////////////////////////////////
// Local LED handler function
/////////////////////////////////////////////////////////////////////////////
static s32 LED_Handler(u16 *gp_leds)
{
    if( ui_cursor_flash ) // if flashing flag active: no LED flag set
        return 0;

    switch( ui_selected_item ) {
    case ITEM_GXTY:
        *gp_leds = 0x0001;
        break;
    case ITEM_MODE: {
        int selected_mode = SEQ_CC_Get(SEQ_UI_VisibleTrackGet(), SEQ_CC_MODE);
        *gp_leds = (1 << (selected_mode+1));
    }
    break;
    case ITEM_BUS:
        *gp_leds = 0x0080;
        break;
    case ITEM_HOLD:
        *gp_leds = 0x0100;
        break;
    case ITEM_SORT:
        *gp_leds = 0x0200;
        break;
    case ITEM_RESTART:
        *gp_leds = 0x0c00;
        break;
    case ITEM_FORCE_SCALE:
        *gp_leds = 0x3000;
        break;
    case ITEM_SUSTAIN:
        *gp_leds = 0xc000;
        break;
    }

    return 0; // no error
}
Exemplo n.º 8
0
/////////////////////////////////////////////////////////////////////////////
// Returns the CC value for MIDI (different mapping, especially used by Loopback Feature)
// see also doc/mbseqv4_cc_implementation.txt
// Returns < 0 if CC value not mapped
/////////////////////////////////////////////////////////////////////////////
s32 SEQ_CC_MIDI_Get(u8 track, u8 cc, u8 *mapped_cc)
{
  if( cc >= 0x30 && cc <= 0x7f ) {
    *mapped_cc = cc - 0x20;

    u8 value = SEQ_CC_Get(track, cc);
    switch( cc ) {
      case SEQ_CC_LFO_AMPLITUDE:
	value /= 2; // 8bit -> 7bit
	break;
      case SEQ_CC_MIDI_PORT:
      case SEQ_CC_FX_MIDI_PORT:
	if( value >= 0xf0 )
	  value = 0x70 | (value & 0x0f); // map to Bus
	else if( value >= 0x80 )
	  value = 0x60 | (value & 0x0f); // map to AOUT
	break;
    }

    return value;
  }

  return -1; // CC not mapped
}
/////////////////////////////////////////////////////////////////////////////
// Local Display Handler function
// IN: <high_prio>: if set, a high-priority LCD update is requested
/////////////////////////////////////////////////////////////////////////////
static s32 LCD_Handler(u8 high_prio)
{
  u8 visible_track = SEQ_UI_VisibleTrackGet();

  if( high_prio )
    return 0; // there are no high-priority updates

  // layout:
  // 00000000001111111111222222222233333333330000000000111111111122222222223333333333
  // 01234567890123456789012345678901234567890123456789012345678901234567890123456789
  // <--------------------------------------><-------------------------------------->
  // Trk. Mute Oct. Vel. FTS   Fx             Bus Port Chn. Lower/Upper Mode   Reset 
  // G1T1       +0  100   on   on              1  IN1  #16   ---   ---  T&A    Stacks

  // The selected Bus1 is not configured      Bus Port Chn. Lower/Upper Mode   Reset 
  // for Play mode (but for Transposer&Arp.)   1  IN1  #16   ---   ---  T&A    Stacks

  ///////////////////////////////////////////////////////////////////////////
  SEQ_LCD_CursorSet(0, 0);
  if( !seq_midi_in_options[selected_bus].MODE_PLAY ) {
    SEQ_LCD_PrintFormattedString("The selected Bus%d is not configured     ", selected_bus+1);
  } else {
    SEQ_LCD_PrintString("Trk. Mute Oct. Vel. FTS   Fx            ");
  }

  SEQ_LCD_CursorSet(40, 0);
  SEQ_LCD_PrintString(" Bus Port Chn. Lower/Upper Mode   Reset ");


  ///////////////////////////////////////////////////////////////////////////
  SEQ_LCD_CursorSet(0, 1);
  if( !seq_midi_in_options[selected_bus].MODE_PLAY ) {
    SEQ_LCD_PrintString("for Play mode (but for Transposer&Arp.) ");
  } else {
    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_MUTE && ui_cursor_flash ) {
      SEQ_LCD_PrintSpaces(5);
    } else {
      SEQ_LCD_PrintSpaces(2);
      SEQ_LCD_PrintChar((seq_core_trk_muted & (1 << visible_track)) ? '*' : 'o');
      SEQ_LCD_PrintSpaces(2);
    }

    ///////////////////////////////////////////////////////////////////////////
    if( ui_selected_item == ITEM_OCT_TRANSPOSE && ui_cursor_flash ) {
      SEQ_LCD_PrintSpaces(4);
    } else {
      u8 event_mode = SEQ_CC_Get(visible_track, SEQ_CC_MIDI_EVENT_MODE);
      if( event_mode == SEQ_EVENT_MODE_Drum ) {
	SEQ_LCD_PrintString("Drum");
      } else {
	SEQ_LCD_PrintFormattedString(" %c%d ", (seq_live_options.OCT_TRANSPOSE < 0) ? '-' : '+', abs(seq_live_options.OCT_TRANSPOSE));
      }
    }
    SEQ_LCD_PrintSpaces(1);

    ///////////////////////////////////////////////////////////////////////////
    if( ui_selected_item == ITEM_LIVE_VELOCITY && ui_cursor_flash ) {
      SEQ_LCD_PrintSpaces(3);
    } else {
      SEQ_LCD_PrintFormattedString("%3d", seq_live_options.VELOCITY);
    }
    SEQ_LCD_PrintSpaces(2);

    ///////////////////////////////////////////////////////////////////////////
    if( ui_selected_item == ITEM_LIVE_FORCE_SCALE && ui_cursor_flash ) {
      SEQ_LCD_PrintSpaces(3);
    } else {
      SEQ_LCD_PrintString(seq_live_options.FORCE_SCALE ? " on" : "off");
    }
    SEQ_LCD_PrintSpaces(2);

    ///////////////////////////////////////////////////////////////////////////
    if( ui_selected_item == ITEM_LIVE_FX && ui_cursor_flash ) {
      SEQ_LCD_PrintSpaces(3);
    } else {
      SEQ_LCD_PrintString(seq_live_options.FX ? " on" : "off");
    }
    SEQ_LCD_PrintSpaces(2 + 10);
  }



  ///////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_IN_BUS && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(5);
  } else {
    SEQ_LCD_PrintFormattedString("  %d  ", selected_bus+1);
  }

  ///////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_IN_PORT && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(4);
  } else {
    if( seq_midi_in_port[selected_bus] )
      SEQ_LCD_PrintString(SEQ_MIDI_PORT_InNameGet(SEQ_MIDI_PORT_InIxGet(seq_midi_in_port[selected_bus])));
    else
      SEQ_LCD_PrintString(" All");
  }
  SEQ_LCD_PrintSpaces(1);


  ///////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_IN_CHN && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(3);
  } else {
    if( seq_midi_in_channel[selected_bus] )
      SEQ_LCD_PrintFormattedString("#%2d", seq_midi_in_channel[selected_bus]);
    else
      SEQ_LCD_PrintString("---");
  }
  SEQ_LCD_PrintSpaces(3);


  ///////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_IN_LOWER && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(3);
  } else {
    SEQ_LCD_PrintNote(seq_midi_in_lower[selected_bus]);
  }
  SEQ_LCD_PrintSpaces(3);


  ///////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_IN_UPPER && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(3);
  } else {
    SEQ_LCD_PrintNote(seq_midi_in_upper[selected_bus]);
  }
  SEQ_LCD_PrintSpaces(2);


  ///////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_IN_MODE && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(4);
  } else {
    SEQ_LCD_PrintString(seq_midi_in_options[selected_bus].MODE_PLAY ? "Play" : "T&A ");
  }
  SEQ_LCD_PrintSpaces(3);

  SEQ_LCD_PrintString("Stacks");

  return 0; // no error
}
Exemplo n.º 10
0
/////////////////////////////////////////////////////////////////////////////
// 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; // unsupported (yet)

    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 normal mode:
  // 00000000001111111111222222222233333333330000000000111111111122222222223333333333
  // 01234567890123456789012345678901234567890123456789012345678901234567890123456789
  // <--------------------------------------><-------------------------------------->
  // Gate Acc. Roll Glide Skip R.G  R.V No Fx                                        
  //   A    B    C    D    E    F    G    H                                          

  // layout drum mode (lower line shows drum labels):
  // 00000000001111111111222222222233333333330000000000111111111122222222223333333333
  // 01234567890123456789012345678901234567890123456789012345678901234567890123456789
  // <--------------------------------------><-------------------------------------->
  // Select Drum Instrument:                                                         
  //  BD   SD   LT   MT   HT   CP   MA   RS   CB   CY   OH   CH  Smp1 Smp2 Smp3 Smp4 
  // ...horizontal VU meters...

  u8 visible_track = SEQ_UI_VisibleTrackGet();
  u8 event_mode = SEQ_CC_Get(visible_track, SEQ_CC_MIDI_EVENT_MODE);

  if( high_prio && event_mode == SEQ_EVENT_MODE_Drum ) {
    ///////////////////////////////////////////////////////////////////////////
    // frequently update VU meters

    SEQ_LCD_CursorSet(0, 1);

    u8 drum;
    u8 num_instruments = SEQ_TRG_NumInstrumentsGet(visible_track);
    for(drum=0; drum<num_instruments; ++drum) {
      if( seq_core_trk[visible_track].layer_muted & (1 << drum) )
	SEQ_LCD_PrintString("Mute ");
      else
	SEQ_LCD_PrintHBar((seq_layer_vu_meter[drum] >> 3) & 0xf);
    }

    return 0; // no error
  }
Exemplo n.º 11
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)
{
  u8 visible_track = SEQ_UI_VisibleTrackGet();

  switch( encoder ) {
    case SEQ_UI_ENCODER_GP1:
      ui_selected_item = ITEM_GXTY;
      break;

    case SEQ_UI_ENCODER_GP2:
    case SEQ_UI_ENCODER_GP3:
    case SEQ_UI_ENCODER_GP4:
      ui_selected_item = ITEM_GROOVE_STYLE;
      break;

    case SEQ_UI_ENCODER_GP5:
    case SEQ_UI_ENCODER_GP6:
      ui_selected_item = ITEM_GROOVE_VALUE;
      break;

    case SEQ_UI_ENCODER_GP7:
    case SEQ_UI_ENCODER_GP8:
      ui_selected_item = ITEM_GROOVE_VALUE_GLB;
      break;

    case SEQ_UI_ENCODER_GP9:
      ui_selected_item = ITEM_GROOVE_STEP;
      break;
      
    case SEQ_UI_ENCODER_GP10:
      ui_selected_item = ITEM_GROOVE_DELAY;
      break;
      
    case SEQ_UI_ENCODER_GP11:
      ui_selected_item = ITEM_GROOVE_LENGTH;
      break;
      
    case SEQ_UI_ENCODER_GP12:
      ui_selected_item = ITEM_GROOVE_VELOCITY;
      break;

    case SEQ_UI_ENCODER_GP13:
      ui_selected_item = ITEM_GROOVE_NUM_STEPS;
      break;

    case SEQ_UI_ENCODER_GP14:
    case SEQ_UI_ENCODER_GP15:
    case SEQ_UI_ENCODER_GP16:
      return -1; // not mapped yet
  }

  // for GP encoders and Datawheel
  u8 grooves_total = SEQ_GROOVE_NUM_PRESETS+SEQ_GROOVE_NUM_TEMPLATES;
  u8 selected_groove = SEQ_CC_Get(visible_track, SEQ_CC_GROOVE_STYLE);
  s32 groove_template = selected_groove - SEQ_GROOVE_NUM_PRESETS; // negative if not a custom template
  seq_groove_entry_t *g;
  if( selected_groove >= SEQ_GROOVE_NUM_PRESETS )
    g = (seq_groove_entry_t *)&seq_groove_templates[selected_groove-SEQ_GROOVE_NUM_PRESETS];
  else
    g = (seq_groove_entry_t *)&seq_groove_presets[selected_groove];

  switch( ui_selected_item ) {
    case ITEM_GXTY:              return SEQ_UI_GxTyInc(incrementer);
    case ITEM_GROOVE_STYLE:      return SEQ_UI_CC_Inc(SEQ_CC_GROOVE_STYLE, 0, grooves_total-1, incrementer);
    case ITEM_GROOVE_VALUE:      return SEQ_UI_CC_Inc(SEQ_CC_GROOVE_VALUE, 0, 127, incrementer);
    case ITEM_GROOVE_STEP:       return SEQ_UI_Var8_Inc(&edit_step, 0, g->num_steps-1, incrementer);

    case ITEM_GROOVE_VALUE_GLB: {
      if( SEQ_UI_CC_Inc(SEQ_CC_GROOVE_VALUE, 0, 127, incrementer) > 0 ) {
	// change value for all tracks
	u8 value = SEQ_CC_Get(visible_track, SEQ_CC_GROOVE_VALUE);
	u8 track;
	for(track=0; track<SEQ_CORE_NUM_TRACKS; ++track) {
	  SEQ_CC_Set(track, SEQ_CC_GROOVE_VALUE, value);
	}
	return 1;
      }
      return 0;
    }

    case ITEM_GROOVE_DELAY: {
      if( groove_template < 0 || groove_template >= SEQ_GROOVE_NUM_TEMPLATES )
	return 0;
      u8 value = (u8)seq_groove_templates[groove_template].add_step_delay[edit_step] + 128;
      if( SEQ_UI_Var8_Inc(&value, 0, 255, incrementer) > 0 ) {
	seq_groove_templates[groove_template].add_step_delay[edit_step] = (s8)(value - 128);
	ui_store_file_required = 1;
	return 1;
      }
      return 0;
    }

    case ITEM_GROOVE_LENGTH: {
      if( groove_template < 0 || groove_template >= SEQ_GROOVE_NUM_TEMPLATES )
	return 0;
      u8 value = (u8)seq_groove_templates[groove_template].add_step_length[edit_step] + 128;
      if( SEQ_UI_Var8_Inc(&value, 0, 255, incrementer) > 0 ) {
	seq_groove_templates[groove_template].add_step_length[edit_step] = (s8)(value - 128);
	ui_store_file_required = 1;
	return 1;
      }
      return 0;
    }

    case ITEM_GROOVE_VELOCITY: {
      if( groove_template < 0 || groove_template >= SEQ_GROOVE_NUM_TEMPLATES )
	return 0;
      u8 value = (u8)seq_groove_templates[groove_template].add_step_velocity[edit_step] + 128;
      if( SEQ_UI_Var8_Inc(&value, 0, 255, incrementer) > 0 ) {
	seq_groove_templates[groove_template].add_step_velocity[edit_step] = (s8)(value - 128);
	ui_store_file_required = 1;
	return 1;
      }
      return 0;
    }

    case ITEM_GROOVE_NUM_STEPS: {
      if( groove_template < 0 || groove_template >= SEQ_GROOVE_NUM_TEMPLATES )
	return 0;
      u8 value = (u8)seq_groove_templates[groove_template].num_steps;
      if( SEQ_UI_Var8_Inc(&value, 1, 16, incrementer) > 0 ) {
	seq_groove_templates[groove_template].num_steps = value;
	ui_store_file_required = 1;
	return 1;
      }
      return 0;
    }

  }

  return -1; // invalid or unsupported encoder
}
Exemplo n.º 12
0
/////////////////////////////////////////////////////////////////////////////
// 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

  u8 visible_track = SEQ_UI_VisibleTrackGet();

#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_GP15 ) {
#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_GP16: {
      if( SEQ_GROOVE_Clear(SEQ_CC_Get(visible_track, SEQ_CC_GROOVE_STYLE)) < 0 )
	SEQ_UI_Msg(SEQ_UI_MSG_USER, 1000, "Preset", "not editable!");
      else
	SEQ_UI_Msg(SEQ_UI_MSG_USER, 1000, "Groove", "cleared!");
    } break;

    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.  Groove Style  Intensity Change forStep Dly. Len. Vel. NumSteps        Clr 
  // G1T1  Inv. Shuffle     15     all Tracks  1    0    0    0  Preset not editable!


  u8 visible_track = SEQ_UI_VisibleTrackGet();
  u8 selected_groove = SEQ_CC_Get(visible_track, SEQ_CC_GROOVE_STYLE);
  seq_groove_entry_t *g;
  if( selected_groove >= SEQ_GROOVE_NUM_PRESETS )
    g = (seq_groove_entry_t *)&seq_groove_templates[selected_groove-SEQ_GROOVE_NUM_PRESETS];
  else
    g = (seq_groove_entry_t *)&seq_groove_presets[selected_groove];


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

  SEQ_LCD_PrintString("Trk.  Groove Style  Intensity ");
  if( ui_selected_item == ITEM_GROOVE_VALUE_GLB && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(10);
  } else {
    SEQ_LCD_PrintString("Change for");
  }
  SEQ_LCD_PrintString("Step Dly. Len. Vel. NumSteps        Clr ");


  ///////////////////////////////////////////////////////////////////////////
  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(2);

  ///////////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_GROOVE_STYLE && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(12);
  } else {
    SEQ_LCD_PrintString(SEQ_GROOVE_NameGet(selected_groove));
  }
  SEQ_LCD_PrintSpaces(5);

  ///////////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_GROOVE_VALUE && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(3);
  } else {
    SEQ_LCD_PrintFormattedString("%3d", SEQ_CC_Get(visible_track, SEQ_CC_GROOVE_VALUE));
  }
  SEQ_LCD_PrintSpaces(4);


  ///////////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_GROOVE_VALUE_GLB && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(10);
  } else {
    SEQ_LCD_PrintString("all Tracks");
  }

  ///////////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_GROOVE_STEP && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(4);
  } else {
    SEQ_LCD_PrintFormattedString(" %2d ", edit_step+1);
  }

  ///////////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_GROOVE_DELAY && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(5);
  } else {
    int value = g->add_step_delay[edit_step];
    if( value <= -128 )
      SEQ_LCD_PrintString("VNEG ");
    else if( value >= 127 )
      SEQ_LCD_PrintString("VPOS ");
    else
      SEQ_LCD_PrintFormattedString("%4d ", value);
  }

  ///////////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_GROOVE_LENGTH && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(5);
  } else {
    int value = g->add_step_length[edit_step];
    if( value <= -128 )
      SEQ_LCD_PrintString("VNEG ");
    else if( value >= 127 )
      SEQ_LCD_PrintString("VPOS ");
    else
      SEQ_LCD_PrintFormattedString("%4d ", value);
  }

  ///////////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_GROOVE_VELOCITY && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(5);
  } else {
    int value = g->add_step_velocity[edit_step];
    if( value <= -128 )
      SEQ_LCD_PrintString("VNEG ");
    else if( value >= 127 )
      SEQ_LCD_PrintString("VPOS ");
    else
      SEQ_LCD_PrintFormattedString("%4d ", value);
  }

  ///////////////////////////////////////////////////////////////////////////
  if( selected_groove >= SEQ_GROOVE_NUM_PRESETS ) {
    if( ui_selected_item == ITEM_GROOVE_NUM_STEPS && ui_cursor_flash ) {
      SEQ_LCD_PrintSpaces(6);
    } else {
      SEQ_LCD_PrintFormattedString("  %2d  ", g->num_steps);
    }    
    SEQ_LCD_PrintSpaces(15);
  } else {
    if( ui_cursor_flash && ui_selected_item >= ITEM_GROOVE_LENGTH && ui_selected_item <= ITEM_GROOVE_DELAY )
      SEQ_LCD_PrintSpaces(21);
    else
      SEQ_LCD_PrintString(" Preset not editable!");
  }

  return 0; // no error
}


/////////////////////////////////////////////////////////////////////////////
// Local exit function
/////////////////////////////////////////////////////////////////////////////
static s32 EXIT_Handler(void)
{
  s32 status = 0;

  if( ui_store_file_required ) {
    // write config file
    MUTEX_SDCARD_TAKE;
    if( (status=SEQ_FILE_G_Write(seq_file_session_name)) < 0 )
      SEQ_UI_SDCardErrMsg(2000, status);
    MUTEX_SDCARD_GIVE;

    ui_store_file_required = 0;
  }

  return status;
}
Exemplo n.º 13
0
/////////////////////////////////////////////////////////////////////////////
// Frequently called to return the status of GP LEDs
/////////////////////////////////////////////////////////////////////////////
u16 SEQ_UI_PAGES_GP_LED_Handler(void)
{
  if( ui_controller_mode )
    return SEQ_UI_PAGES_GP_LED_Handler_Controller();

  static u16 check_100mS_ctr = 0;

  if( load_save_notifier_ctr )
    --load_save_notifier_ctr;

  u8 visible_track = SEQ_UI_VisibleTrackGet();

  // for periodic checks (e.g. of selections derived from patches)
  if( ++check_100mS_ctr >= 100 )
    check_100mS_ctr = 0;

  // clear button pressed: print track activity
  if( seq_ui_button_state.CLEAR ) {
    return ui_track_activity_state;
  }

  switch( ui_page ) {

  ///////////////////////////////////////////////////////////////////////////
  case SEQ_UI_PAGE_LOAD:
  case SEQ_UI_PAGE_SAVE: {
    u8 group = 0;
    u16 leds = (1 << ui_selected_pattern[group].group) | (1 << (ui_selected_pattern[group].num+8));
    if( ui_selected_pattern_changing && ui_cursor_flash )
      leds &= 0x00ff;

    // invert LEDs each 50 mS if load/save notifier active
    if( load_save_notifier_ctr && (load_save_notifier_ctr % 100) >= 50 )
      leds ^= 0xffff;

    return leds;
  } break;

  ///////////////////////////////////////////////////////////////////////////
  case SEQ_UI_PAGE_TRIGGER: {
    u8 *trg_ptr = (u8 *)&seq_trg_layer_value[visible_track][2*ui_selected_step_view];
    u16 leds = *trg_ptr;
    ++trg_ptr;
    leds |= (*trg_ptr << 8);

    return leds;
  } break;

  ///////////////////////////////////////////////////////////////////////////
  case SEQ_UI_PAGE_REC_STEP:
  case SEQ_UI_PAGE_REC_LIVE: {
    u8 record_track = 8;
    if( seq_record_state.ARMED_TRACKS & (1 << 0) )
      record_track = 0;

    u8 *trg_ptr = (u8 *)&seq_trg_layer_value[record_track][2*ui_selected_step_view];
    u16 leds = *trg_ptr;
    ++trg_ptr;
    leds |= (*trg_ptr << 8);

    u16 record_step_mask = (1 << (seq_record_step % 16));
    if( ui_cursor_flash &&
	((seq_record_step >> 4) == ui_selected_step_view) ) {
      leds ^= record_step_mask;
    }

    // button of selected step always active as long as GP button is pressed
    if( ui_selected_gp_buttons & record_step_mask )
      leds |= record_step_mask;

    return leds;
  } break;

  ///////////////////////////////////////////////////////////////////////////
  case SEQ_UI_PAGE_LENGTH: {
    u16 leds = 0x0000;
    u8 length = SEQ_CC_Get(visible_track, SEQ_CC_LENGTH);
    u8 loop = SEQ_CC_Get(visible_track, SEQ_CC_LOOP);

    if( length >= 16*(ui_selected_step_view+1) )
      leds = 0xffff;
    else if( (length >> 4) == ui_selected_step_view )
      leds = (1 << ((length % 16)+1))-1;

    if( ui_cursor_flash ) {
      if( (loop/16) == ui_selected_step_view )
	leds &= ~(1 << loop % 16);

      if( (length/16) == ui_selected_step_view )
	leds &= ~(1 << length % 16);
    }

    return leds;
  } break;

  ///////////////////////////////////////////////////////////////////////////
  case SEQ_UI_PAGE_PROGRESSION: {
    // check if selection still valid
    if( check_100mS_ctr == 0 ) {
      seq_cc_trk_t *tcc = &seq_cc_trk[visible_track];
      seq_ui_pages_progression_presets_t *preset = (seq_ui_pages_progression_presets_t *)&seq_ui_pages_progression_presets[0];
      int i;
      for(i=0; i<16; ++i, ++preset) {
	if( ((u8)tcc->steps_forward+1) == preset->steps_forward &&
	    tcc->steps_jump_back == preset->steps_jump_back &&
	    tcc->steps_replay == preset->steps_replay &&
	    tcc->steps_repeat == preset->steps_repeat &&
	    tcc->steps_skip == preset->steps_skip &&
	    tcc->steps_rs_interval == preset->steps_rs_interval ) {
	  ui_selected_progression_preset = i;
	  break;
	}
      }
    }

    return (1 << ui_selected_progression_preset);
  } break;

  ///////////////////////////////////////////////////////////////////////////
  case SEQ_UI_PAGE_GROOVE: {
    u8 groove_style = SEQ_CC_Get(visible_track, SEQ_CC_GROOVE_STYLE);
    if( groove_style < 8 || groove_style > 22 )
      return 0x0001; // off resp. non-selectable value
    else // note: starting at second custom groove, the first groove is always "off"
      return (1 << (groove_style-8+1));
  } break;

  ///////////////////////////////////////////////////////////////////////////
  case SEQ_UI_PAGE_ECHO: {
    // check if selection still valid
    if( check_100mS_ctr == 0 ) {
      seq_cc_trk_t *tcc = &seq_cc_trk[visible_track];
      seq_ui_pages_echo_presets_t *preset = (seq_ui_pages_echo_presets_t *)&seq_ui_pages_echo_presets[0];
      int i;
      for(i=0; i<16; ++i, ++preset) {
	if( tcc->echo_repeats == preset->repeats &&
	    tcc->echo_delay == preset->delay &&
	    tcc->echo_velocity == preset->velocity &&
	    tcc->echo_fb_velocity == preset->fb_velocity &&
	    tcc->echo_fb_note == preset->fb_note &&
	    tcc->echo_fb_gatelength == preset->fb_gatelength &&
	    tcc->echo_fb_ticks == preset->fb_ticks ) {
	  ui_selected_echo_preset = i;
	  break;
	}
      }
    }

    return (1 << ui_selected_echo_preset);
  } break;

  ///////////////////////////////////////////////////////////////////////////
  case SEQ_UI_PAGE_HUMANIZER: {
    // check if selection still valid
    if( check_100mS_ctr == 0 ) {
      seq_cc_trk_t *tcc = &seq_cc_trk[visible_track];
      seq_ui_pages_humanizer_presets_t *preset = (seq_ui_pages_humanizer_presets_t *)&seq_ui_pages_humanizer_presets[0];
      int i;
      for(i=0; i<16; ++i, ++preset) {
	if( tcc->humanize_mode == preset->mode &&
	    tcc->humanize_value == preset->value ) {
	  ui_selected_humanizer_preset = i;
	  break;
	}
      }
    }

    return (1 << ui_selected_humanizer_preset);
  } break;

  ///////////////////////////////////////////////////////////////////////////
  case SEQ_UI_PAGE_LFO: {
    // check if selection still valid
    if( check_100mS_ctr == 0 ) {
      seq_cc_trk_t *tcc = &seq_cc_trk[visible_track];
      seq_ui_pages_lfo_presets_t *preset = (seq_ui_pages_lfo_presets_t *)&seq_ui_pages_lfo_presets[0];
      int i;
      for(i=0; i<16; ++i, ++preset) {
	if( tcc->lfo_waveform == preset->waveform &&
	    tcc->lfo_amplitude == preset->amplitude &&
	    tcc->lfo_phase == preset->phase &&
	    tcc->lfo_steps == preset->steps &&
	    tcc->lfo_steps_rst == preset->steps_rst &&
	    tcc->lfo_enable_flags.ALL == preset->enable_flags &&
	    tcc->lfo_cc == preset->cc &&
	    tcc->lfo_cc_offset == preset->cc_offset &&
	    tcc->lfo_cc_ppqn == preset->cc_ppqn ) {
	  ui_selected_lfo_preset = i;
	  break;
	}
      }
    }

    return (1 << ui_selected_lfo_preset);
  } break;

  ///////////////////////////////////////////////////////////////////////////
  case SEQ_UI_PAGE_SCALE: {
    // check if selection still valid
    if( check_100mS_ctr == 0 ) {
      u8 note_track = 8;
      if( ui_selected_tracks & (1 << 0) )
	note_track = 0;

      if( !seq_cc_trk[note_track].mode.FORCE_SCALE )
	ui_selected_scale = 0;
      else {
	u8 *preset = (u8 *)&seq_ui_pages_scale_presets[1];
	int i;
	for(i=1; i<16; ++i, ++preset)
	  if( seq_core_global_scale == *preset )
	    break;

	ui_selected_scale = (i > 15) ? 15 : i; // if no preset scale, show last LED
      }
    }

    if( seq_ui_button_state.SCALE_PRESSED )
      return (1 << ui_selected_scale);

    if( seq_core_global_scale_root_selection )
      return (1 << (seq_core_global_scale_root_selection-1)); // selected scale
    else
      return 0xf000 | (1 << seq_core_keyb_scale_root); // scale via keyboard
  } break;

  ///////////////////////////////////////////////////////////////////////////
  case SEQ_UI_PAGE_MUTE: {
    u16 muted = seq_core_trk_muted;
    if( ui_cursor_flash && seq_ui_button_state.SOLO ) {
      //muted |= !ui_selected_tracks; // doesn't work with gcc version 4.2.1 ?!?
      muted |= ui_selected_tracks ^ 0xffff;
    }
    return muted;
  } break;

  ///////////////////////////////////////////////////////////////////////////
  case SEQ_UI_PAGE_MIDICHN: {
    u8 chn = SEQ_CC_Get(visible_track, SEQ_CC_MIDI_CHANNEL);
    return (1 << chn);
  } break;

  ///////////////////////////////////////////////////////////////////////////
  case SEQ_UI_PAGE_REC_ARM: {
    return seq_record_state.ARMED_TRACKS;
  } break;

  ///////////////////////////////////////////////////////////////////////////
  case SEQ_UI_PAGE_TEMPO: {
    // check if selection still valid
    if( check_100mS_ctr == 0 ) {
      seq_cc_trk_t *tcc = &seq_cc_trk[visible_track];
      seq_ui_pages_tempo_presets_t *preset = (seq_ui_pages_tempo_presets_t *)&seq_ui_pages_tempo_presets[0];
      int i;
      for(i=0; i<16; ++i, ++preset) {
	if( tcc->clkdiv.value == preset->clkdiv &&
	    tcc->clkdiv.TRIPLETS == preset->triplets ) {
	  ui_selected_tempo_preset = i;
	  break;
	}
      }
    }

    return (1 << ui_selected_tempo_preset);
  } break;
  }

  return 0x0000;
}
Exemplo n.º 14
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)
{
  u8 visible_track = SEQ_UI_VisibleTrackGet();

  switch( encoder ) {
    case SEQ_UI_ENCODER_GP1:
      ui_selected_item = ITEM_GXTY;
      break;

    case SEQ_UI_ENCODER_GP2:
      ui_selected_item = ITEM_WAVEFORM;
      break;

    case SEQ_UI_ENCODER_GP3:
      ui_selected_item = ITEM_AMPLITUDE;
      break;

    case SEQ_UI_ENCODER_GP4:
      ui_selected_item = ITEM_PHASE;
      break;

    case SEQ_UI_ENCODER_GP5:
      ui_selected_item = ITEM_STEPS;
      break;

    case SEQ_UI_ENCODER_GP6:
      ui_selected_item = ITEM_STEPS_RST;
      break;

    case SEQ_UI_ENCODER_GP7:
      ui_selected_item = ITEM_ENABLE_ONE_SHOT;
      break;

    case SEQ_UI_ENCODER_GP8:
      return -1; // not mapped

    case SEQ_UI_ENCODER_GP9:
      ui_selected_item = ITEM_ENABLE_NOTE;
      break;

    case SEQ_UI_ENCODER_GP10:
      ui_selected_item = ITEM_ENABLE_VELOCITY;
      break;

    case SEQ_UI_ENCODER_GP11:
      ui_selected_item = ITEM_ENABLE_LENGTH;
      break;

    case SEQ_UI_ENCODER_GP12:
      ui_selected_item = ITEM_ENABLE_CC;
      break;

    case SEQ_UI_ENCODER_GP13:
      return -1; // not mapped

    case SEQ_UI_ENCODER_GP14:
      // CC number selection now has to be confirmed with GP button
      if( ui_selected_item != ITEM_CC ) {
	edit_cc_number = SEQ_CC_Get(visible_track, SEQ_CC_LFO_CC);
	ui_selected_item = ITEM_CC;
	SEQ_UI_Msg(SEQ_UI_MSG_USER, 2000, "Please confirm CC", "with GP button!");
      } else if( incrementer == 0 ) {
	if( edit_cc_number != SEQ_CC_Get(visible_track, SEQ_CC_LFO_CC) ) {
	  SEQ_CC_Set(visible_track, SEQ_CC_LFO_CC, edit_cc_number);
	  SEQ_UI_Msg(SEQ_UI_MSG_USER, 2000, "CC number", "has been changed.");
	}

	// send event
	mios32_midi_package_t p;
	if( SEQ_LFO_FastCC_Event(visible_track, 0, &p, 1) >= 1 ) {
	  MUTEX_MIDIOUT_TAKE;
	  MIOS32_MIDI_SendPackage(SEQ_CC_Get(visible_track, SEQ_CC_MIDI_PORT), p);
	  MUTEX_MIDIOUT_GIVE;
	}
      }
      break;

    case SEQ_UI_ENCODER_GP15:
      ui_selected_item = ITEM_CC_OFFSET;
      break;

    case SEQ_UI_ENCODER_GP16:
      ui_selected_item = ITEM_CC_PPQN;
      break;
  }

  // for GP encoders and Datawheel
  switch( ui_selected_item ) {
    case ITEM_GXTY:          return SEQ_UI_GxTyInc(incrementer);
    case ITEM_WAVEFORM:      return SEQ_UI_CC_Inc(SEQ_CC_LFO_WAVEFORM, 0, 22, incrementer);
    case ITEM_AMPLITUDE:     return SEQ_UI_CC_Inc(SEQ_CC_LFO_AMPLITUDE, 0, 255, incrementer);
    case ITEM_PHASE:         return SEQ_UI_CC_Inc(SEQ_CC_LFO_PHASE, 0, 99, incrementer);
    case ITEM_STEPS:         return SEQ_UI_CC_Inc(SEQ_CC_LFO_STEPS, 0, 255, incrementer);
    case ITEM_STEPS_RST:     return SEQ_UI_CC_Inc(SEQ_CC_LFO_STEPS_RST, 0, 255, incrementer);
    case ITEM_ENABLE_ONE_SHOT:
    case ITEM_ENABLE_NOTE:
    case ITEM_ENABLE_VELOCITY:
    case ITEM_ENABLE_LENGTH:

    case ITEM_ENABLE_CC: {
      u8 flag = ui_selected_item - ITEM_ENABLE_ONE_SHOT;
      u8 mask = 1 << flag;
      u8 value = SEQ_CC_Get(visible_track, SEQ_CC_LFO_ENABLE_FLAGS);
      if( incrementer == 0 ) // toggle
	SEQ_UI_CC_SetFlags(SEQ_CC_LFO_ENABLE_FLAGS, mask, value ^ mask);
      else if( incrementer > 0 )
	SEQ_UI_CC_SetFlags(SEQ_CC_LFO_ENABLE_FLAGS, mask, mask);
      else
	SEQ_UI_CC_SetFlags(SEQ_CC_LFO_ENABLE_FLAGS, mask, 0);
    } break;

    case ITEM_CC: {
      // CC number selection now has to be confirmed with GP button
      s32 status = SEQ_UI_Var8_Inc(&edit_cc_number, 0, 127, incrementer);
      mios32_midi_port_t port = SEQ_CC_Get(visible_track, SEQ_CC_MIDI_PORT);
      u8 loopback = port == 0xf0;
      if( !edit_cc_number ) {
	SEQ_UI_Msg(SEQ_UI_MSG_USER_R, 1000, "LFO CC", "disabled");
      } else {
	SEQ_UI_Msg(SEQ_UI_MSG_USER_R, 1000, loopback ? "Loopback CC" : "Controller:", (char *)SEQ_CC_LABELS_Get(port, edit_cc_number));
      }
      return status;
    } break;

    case ITEM_CC_OFFSET:     return SEQ_UI_CC_Inc(SEQ_CC_LFO_CC_OFFSET, 0, 127, incrementer);
    case ITEM_CC_PPQN:       return SEQ_UI_CC_Inc(SEQ_CC_LFO_CC_PPQN, 0, 8, incrementer);
  }

  return -1; // invalid or unsupported encoder
}
Exemplo n.º 15
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)
{
  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 ) {
Exemplo n.º 16
0
	  }
	} 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 {
    ///////////////////////////////////////////////////////////////////////////
    SEQ_LCD_CursorSet(0, 0);

    u8 track;
    u8 visible_track = SEQ_UI_VisibleTrackGet();
    u8 event_mode = SEQ_CC_Get(visible_track, SEQ_CC_MIDI_EVENT_MODE);
    u8 num_layers = (event_mode == SEQ_EVENT_MODE_Drum) ? SEQ_TRG_NumInstrumentsGet(visible_track) : SEQ_PAR_NumLayersGet(visible_track);

    for(track=0; track<16; ++track) {
      if( ui_cursor_flash && seq_ui_button_state.SELECT_PRESSED )
	SEQ_LCD_PrintSpaces(5);
      else {
	if( seq_ui_button_state.MUTE_PRESSED ) {
	  if( track >= num_layers )
	    SEQ_LCD_PrintSpaces(5);
	  else {
	    if( event_mode == SEQ_EVENT_MODE_Drum )
	      SEQ_LCD_PrintTrackDrum(visible_track, track, (char *)seq_core_trk[visible_track].name);
	    else
	      SEQ_LCD_PrintString(SEQ_PAR_AssignedTypeStr(visible_track, track));
	  }
Exemplo n.º 17
0
/////////////////////////////////////////////////////////////////////////////
// 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
}
Exemplo n.º 18
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)
{
  u8 visible_track = SEQ_UI_VisibleTrackGet();

  switch( encoder ) {
    case SEQ_UI_ENCODER_GP1:
    case SEQ_UI_ENCODER_GP2:
      ui_selected_item = ITEM_GXTY;
      break;

    case SEQ_UI_ENCODER_GP3:
    case SEQ_UI_ENCODER_GP4:
      ui_selected_item = ITEM_REPEATS;
      break;

    case SEQ_UI_ENCODER_GP5:
    case SEQ_UI_ENCODER_GP6:
      ui_selected_item = ITEM_DELAY;
      break;

    case SEQ_UI_ENCODER_GP7:
    case SEQ_UI_ENCODER_GP8:
      ui_selected_item = ITEM_VELOCITY;
      break;

    case SEQ_UI_ENCODER_GP9:
    case SEQ_UI_ENCODER_GP10:
      ui_selected_item = ITEM_FB_VELOCITY;
      break;

    case SEQ_UI_ENCODER_GP11:
    case SEQ_UI_ENCODER_GP12:
      ui_selected_item = ITEM_FB_NOTE;
      break;

    case SEQ_UI_ENCODER_GP13:
    case SEQ_UI_ENCODER_GP14:
      ui_selected_item = ITEM_FB_GATELENGTH;
      break;

    case SEQ_UI_ENCODER_GP15:
    case SEQ_UI_ENCODER_GP16:
      ui_selected_item = ITEM_FB_TICKS;
      break;
  }

  // for GP encoders and Datawheel
  switch( ui_selected_item ) {
  case ITEM_GXTY:          return SEQ_UI_GxTyInc(incrementer);
  case ITEM_REPEATS:       return SEQ_UI_CC_Inc(SEQ_CC_ECHO_REPEATS, 0, 15, incrementer);
  case ITEM_DELAY: {
    // for compatibility with older patches pre Beta30
    u8 value = SEQ_CC_Get(visible_track, SEQ_CC_ECHO_DELAY);
    value = SEQ_CORE_Echo_MapInternalToUser(value);
    if( SEQ_UI_Var8_Inc(&value, 0, 21, incrementer) ) {
      value = SEQ_CORE_Echo_MapUserToInternal(value);
      SEQ_CC_Set(visible_track, SEQ_CC_ECHO_DELAY, value);
      return 1;
    }
    return 0;
  } break;

  case ITEM_VELOCITY:      return SEQ_UI_CC_Inc(SEQ_CC_ECHO_VELOCITY, 0, 40, incrementer);
  case ITEM_FB_VELOCITY:   return SEQ_UI_CC_Inc(SEQ_CC_ECHO_FB_VELOCITY, 0, 40, incrementer);
  case ITEM_FB_NOTE:       return SEQ_UI_CC_Inc(SEQ_CC_ECHO_FB_NOTE, 0, 49, incrementer);
  case ITEM_FB_GATELENGTH: return SEQ_UI_CC_Inc(SEQ_CC_ECHO_FB_GATELENGTH, 0, 40, incrementer);
  case ITEM_FB_TICKS:      return SEQ_UI_CC_Inc(SEQ_CC_ECHO_FB_TICKS, 0, 40, incrementer);
  }

  return -1; // invalid or unsupported encoder
}
Exemplo n.º 19
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)
{
  u8 visible_track = SEQ_UI_VisibleTrackGet();
  u16 num_steps = SEQ_TRG_NumStepsGet(visible_track);

  switch( encoder ) {
    case SEQ_UI_ENCODER_GP1:
      SEQ_UI_Var8_Inc(&ui_selected_item, 0, NUM_OF_ITEMS, incrementer);
	  
	  //ui_selected_item = ITEM_GXTY;
      break;

    case SEQ_UI_ENCODER_GP2:
    case SEQ_UI_ENCODER_GP3:
      ui_selected_item = ITEM_LENGTH;
      break;

    case SEQ_UI_ENCODER_GP4:
    case SEQ_UI_ENCODER_GP5:
      ui_selected_item = ITEM_LOOP;
      break;

    case SEQ_UI_ENCODER_GP6:
      return 0; // not mapped

    case SEQ_UI_ENCODER_GP7:
    case SEQ_UI_ENCODER_GP8:
      ui_selected_item = ITEM_QUICKSEL_MODE;
      break;

    case SEQ_UI_ENCODER_GP9:
    case SEQ_UI_ENCODER_GP10:
    case SEQ_UI_ENCODER_GP11:
    case SEQ_UI_ENCODER_GP12:
    case SEQ_UI_ENCODER_GP13:
    case SEQ_UI_ENCODER_GP14:
    case SEQ_UI_ENCODER_GP15:
    case SEQ_UI_ENCODER_GP16: {
      int quicksel = encoder - 8;
      int len = (quicksel_mode == QUICKSEL_MODE_LENGTH) ? ui_quicksel_length[quicksel] : ui_quicksel_loop_length[quicksel];

      if( (len+1) > num_steps ) {
	len = num_steps-1;

	char buffer[20];
	sprintf(buffer, "for %d steps", num_steps);

	SEQ_UI_Msg(SEQ_UI_MSG_USER_R, 1000, "Track only prepared", buffer);
      } else if( seq_cc_trk[visible_track].clkdiv.SYNCH_TO_MEASURE && ((int)len > (int)seq_core_steps_per_measure) ) {
	char buffer[20];
	sprintf(buffer, "active for %d steps", (int)seq_core_steps_per_measure+1);
	SEQ_UI_Msg(SEQ_UI_MSG_USER, 1000, "Synch-to-Measure is", buffer);
      }

      SEQ_UI_CC_Set(SEQ_CC_LENGTH, len);

      if( quicksel_mode == QUICKSEL_MODE_LOOP ) {
	SEQ_UI_CC_Set(SEQ_CC_LOOP, ui_quicksel_loop_loop[quicksel]);
      }

      return 1; // value has been changed
    } break;
  }

  // for GP encoders and Datawheel
  if (encoder == SEQ_UI_ENCODER_Datawheel) {
  switch( ui_selected_item ) {
    case ITEM_GXTY:          return SEQ_UI_GxTyInc(incrementer);
    case ITEM_LENGTH: {
      if( SEQ_UI_CC_Inc(SEQ_CC_LENGTH, 0, num_steps-1, incrementer) >= 1 ) {
	if( seq_cc_trk[visible_track].clkdiv.SYNCH_TO_MEASURE && 
	    (int)SEQ_CC_Get(visible_track, SEQ_CC_LENGTH) > (int)seq_core_steps_per_measure ) {
	  char buffer[20];
	  sprintf(buffer, "active for %d steps", (int)seq_core_steps_per_measure+1);
	  SEQ_UI_Msg(SEQ_UI_MSG_USER, 1000, "Synch-to-Measure is", buffer);
	}
	return 1;
      }
      return 0;
    }

    case ITEM_LOOP:
      return SEQ_UI_CC_Inc(SEQ_CC_LOOP, 0, num_steps-1, incrementer);

    case ITEM_QUICKSEL_MODE:
      return SEQ_UI_Var8_Inc(&quicksel_mode, 0, 1, incrementer);
  }
  }
  return -1; // invalid or unsupported encoder
}
Exemplo n.º 20
0
/////////////////////////////////////////////////////////////////////////////
// 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. off     Transpose              Bus Hold Sort  Restart  ForceScale  Sustain
    // G1T1   >Normal<  Arpeggiator         1   on   on     on        on         on

    u8 visible_track = SEQ_UI_VisibleTrackGet();

    ///////////////////////////////////////////////////////////////////////////
    SEQ_LCD_CursorSet(0, 0);
    SEQ_LCD_PrintString("Trk.");

    SEQ_LCD_CursorSet(0, 1);
    if( ui_selected_item == ITEM_GXTY && ui_cursor_flash ) {
        SEQ_LCD_PrintSpaces(9);
    } else {
        SEQ_LCD_PrintGxTy(ui_selected_group, ui_selected_tracks);
        SEQ_LCD_PrintSpaces(5);
    }

    ///////////////////////////////////////////////////////////////////////////
    const char mode_names[7][14] = {
        ">off<        ",
        ">Normal<     ",
        ">Transpose<  ",
        ">Arpeggiator<"
    };
    int i;
    int selected_mode = SEQ_CC_Get(visible_track, SEQ_CC_MODE);
    for(i=0; i<4; ++i) {
        u8 x = 4 + 5*i;
        SEQ_LCD_CursorSet(x, i%2);

        // print unmodified name if item selected
        // replace '>' and '<' by space if item not selected
        // flash item (print only '>'/'<' and spaces) if cursor position == 1 and flash flag set by timer
        int j;
        for(j=0; j<13; ++j) {
            u8 c = mode_names[i][j];

            if( ++x > 35 ) // don't print more than 35 characters per line
                break;

            if( c == '>' || c == '<' ) {
                SEQ_LCD_PrintChar((i == selected_mode) ? c : ' ');
            } else {
                if( ui_selected_item == ITEM_MODE && i == selected_mode && ui_cursor_flash )
                    SEQ_LCD_PrintChar(' ');
                else
                    SEQ_LCD_PrintChar(c);
            }
        }
    }

    // additional spaces to fill LCD (avoids artefacts on page switches)
    SEQ_LCD_CursorSet(25, 0);
    SEQ_LCD_PrintSpaces(15);
    SEQ_LCD_CursorSet(32, 1);
    SEQ_LCD_PrintSpaces(8);

    ///////////////////////////////////////////////////////////////////////////
    SEQ_LCD_CursorSet(35, 0);
    SEQ_LCD_PrintString(" Bus Hold Sort  Restart  ForceScale  Sustain ");
    SEQ_LCD_CursorSet(35, 1);

    ///////////////////////////////////////////////////////////////////////////
    if( ui_selected_item == ITEM_BUS && ui_cursor_flash ) {
        SEQ_LCD_PrintSpaces(3);
    } else {
        SEQ_LCD_PrintFormattedString("  %d", SEQ_CC_Get(visible_track, SEQ_CC_BUSASG) + 1);
    }
    SEQ_LCD_PrintSpaces(3);

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

    ///////////////////////////////////////////////////////////////////////////
    if( ui_selected_item == ITEM_SORT && ui_cursor_flash ) {
        SEQ_LCD_PrintSpaces(3);
    } else {
        SEQ_LCD_PrintString((SEQ_CC_Get(visible_track, SEQ_CC_MODE_FLAGS) & (1 << 0)) ? "off" : "on "); // SORT is inverted!
    }
    SEQ_LCD_PrintSpaces(4);

    ///////////////////////////////////////////////////////////////////////////
    if( ui_selected_item == ITEM_RESTART && ui_cursor_flash ) {
        SEQ_LCD_PrintSpaces(3);
    } else {
        SEQ_LCD_PrintString((SEQ_CC_Get(visible_track, SEQ_CC_MODE_FLAGS) & (1 << 2)) ? "on " : "off");
    }
    SEQ_LCD_PrintSpaces(7);

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

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

    return 0; // no error
}
Exemplo n.º 21
0
/////////////////////////////////////////////////////////////////////////////
// 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.   Length  Loop             QuickSel        Quick Selection: Length         
  // G1T1   256/256   1               Length    4    8   16   24   32   64  128  256

  // Trk.   Length  Loop             QuickSel   1    5    9   13    1    1   17   25 
  // G1T1   256/256   1               Loops     4    8   12   16   16   32   32   32 

  u8 visible_track = SEQ_UI_VisibleTrackGet();
  s32 quicksel_item = QUICKSEL_SearchItem(SEQ_UI_VisibleTrackGet());

  ///////////////////////////////////////////////////////////////////////////
  SEQ_LCD_CursorSet(0, 0);
  SEQ_LCD_PrintString("Trk.   Length  Loop  ");
	
	SEQ_LCD_CursorSet(0, 2);
	SEQ_LCD_PrintString("QuickSel: ");
 
	SEQ_LCD_CursorSet(0, 3);
	SEQ_LCD_PrintSpaces(21);
	SEQ_LCD_CursorSet(0, 4);	
 
  if( quicksel_mode == QUICKSEL_MODE_LENGTH ) {
    //SEQ_LCD_PrintString("Quick Selection: Length         ");
	SEQ_LCD_PrintSpaces(21);
  } else {
    int i;
    for(i=0; i<8; ++i) {
 		switch( i ) {
			case 0:
				SEQ_LCD_CursorSet(0, 4);
				break;
			case 4:
				SEQ_LCD_CursorSet(0, 6);
				break;
		}
	if( quicksel_item == i && ui_cursor_flash ) {
	SEQ_LCD_PrintSpaces(5);
      } else {
	int loop = (int)ui_quicksel_loop_loop[i] + 1;
	PrintLengthOrLoop(loop);
      }
    }
  }


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

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

  ///////////////////////////////////////////////////////////////////////////
  SEQ_LCD_PrintSpaces(8);
  if( ui_selected_item == ITEM_LENGTH && ui_cursor_flash ) {
  } else {
    SEQ_LCD_CursorSet(7, 1);
    u16 num_steps = SEQ_TRG_NumStepsGet(visible_track);
    u16 len = SEQ_CC_Get(visible_track, SEQ_CC_LENGTH)+1;

    if( len > num_steps )
      SEQ_LCD_PrintFormattedString("!!!/%d", num_steps);
    else
      SEQ_LCD_PrintFormattedString("%d/%d", len, num_steps);
  }
  // to allow variable string lengths...
  SEQ_LCD_CursorSet(15, 1);

  ///////////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_LOOP && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(4);
  } else {
    u16 num_steps = SEQ_TRG_NumStepsGet(visible_track);
    u16 loop = SEQ_CC_Get(visible_track, SEQ_CC_LOOP)+1;

    if( loop > num_steps )
      SEQ_LCD_PrintString("!!! ");
    else
      SEQ_LCD_PrintFormattedString("%3d ", loop);
  }

  ///////////////////////////////////////////////////////////////////////////
  //SEQ_LCD_PrintSpaces(14);
	SEQ_LCD_CursorSet(11, 2);  
  // free for sale

  ///////////////////////////////////////////////////////////////////////////
  if( ui_selected_item == ITEM_QUICKSEL_MODE && ui_cursor_flash ) {
    SEQ_LCD_PrintSpaces(7);
  } else {
    if( quicksel_mode == QUICKSEL_MODE_LENGTH ) {
      SEQ_LCD_PrintString("Length     ");
    } else {
      SEQ_LCD_PrintString("Loops      ");
    }
  }

  ///////////////////////////////////////////////////////////////////////////
  int i;
  for(i=0; i<8; ++i) {
   		switch( i ) {
			case 0:
				SEQ_LCD_CursorSet(0, 5);
				break;
			case 4:
				SEQ_LCD_CursorSet(0, 7);
				break;
		}
  
  
    if( quicksel_item == i && ui_cursor_flash ) {
      SEQ_LCD_PrintSpaces(5);
    } else {
      int length = (int)((quicksel_mode == QUICKSEL_MODE_LENGTH) ? ui_quicksel_length[i] : ui_quicksel_loop_length[i]) + 1;

      if( length > SEQ_TRG_NumStepsGet(visible_track) )
	SEQ_LCD_PrintString(" --- ");
      else {
	PrintLengthOrLoop(length);
      }
    }
  }

  return 0; // no error
}
Exemplo n.º 22
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)
{
    u8 visible_track = SEQ_UI_VisibleTrackGet();

    switch( encoder ) {
    case SEQ_UI_ENCODER_GP1:
        ui_selected_item = ITEM_GXTY;
        break;

    case SEQ_UI_ENCODER_GP2:
    case SEQ_UI_ENCODER_GP3:
    case SEQ_UI_ENCODER_GP4:
    case SEQ_UI_ENCODER_GP5:
        ui_selected_item = ITEM_MODE;
        SEQ_UI_CC_Set(SEQ_CC_MODE, encoder-1);
        return 1;

    case SEQ_UI_ENCODER_GP6:
    case SEQ_UI_ENCODER_GP7:
        return -1; // not mapped

    case SEQ_UI_ENCODER_GP8:
        ui_selected_item = ITEM_BUS;
        break;

    case SEQ_UI_ENCODER_GP9:
        ui_selected_item = ITEM_HOLD;
        break;

    case SEQ_UI_ENCODER_GP10:
        ui_selected_item = ITEM_SORT;
        break;

    case SEQ_UI_ENCODER_GP11:
    case SEQ_UI_ENCODER_GP12:
        ui_selected_item = ITEM_RESTART;
        break;

    case SEQ_UI_ENCODER_GP13:
    case SEQ_UI_ENCODER_GP14:
        ui_selected_item = ITEM_FORCE_SCALE;
        break;

    case SEQ_UI_ENCODER_GP15:
    case SEQ_UI_ENCODER_GP16:
        ui_selected_item = ITEM_SUSTAIN;
        break;
    }

    // for GP encoders and Datawheel
    switch( ui_selected_item ) {
    case ITEM_GXTY:
        return SEQ_UI_GxTyInc(incrementer);

    case ITEM_MODE:
        return SEQ_UI_CC_Inc(SEQ_CC_MODE, 0, 3, incrementer);

    case ITEM_BUS:
        return SEQ_UI_CC_Inc(SEQ_CC_BUSASG, 0, 3, incrementer);

    case ITEM_HOLD:
        if( !incrementer ) // toggle flag
            incrementer = (SEQ_CC_Get(visible_track, SEQ_CC_MODE_FLAGS) & (1<<1)) ? -1 : 1;
        return SEQ_UI_CC_SetFlags(SEQ_CC_MODE_FLAGS, (1<<1), (incrementer >= 0) ? (1<<1) : 0);

    case ITEM_SORT:
        if( !incrementer ) // toggle flag - SORT is inverted!
            incrementer = (SEQ_CC_Get(visible_track, SEQ_CC_MODE_FLAGS) & (1<<0)) ? 1 : -1;
        return SEQ_UI_CC_SetFlags(SEQ_CC_MODE_FLAGS, (1<<0), (incrementer >= 0) ? 0 : (1<<0)); // SORT is inverted!

    case ITEM_RESTART:
        if( !incrementer ) // toggle flag
            incrementer = (SEQ_CC_Get(visible_track, SEQ_CC_MODE_FLAGS) & (1<<2)) ? -1 : 1;
        return SEQ_UI_CC_SetFlags(SEQ_CC_MODE_FLAGS, (1<<2), (incrementer >= 0) ? (1<<2) : 0);

    case ITEM_FORCE_SCALE:
        if( !incrementer ) // toggle flag
            incrementer = (SEQ_CC_Get(visible_track, SEQ_CC_MODE_FLAGS) & (1<<3)) ? -1 : 1;
        return SEQ_UI_CC_SetFlags(SEQ_CC_MODE_FLAGS, (1<<3), (incrementer >= 0) ? (1<<3) : 0);

    case ITEM_SUSTAIN:
        if( !incrementer ) // toggle flag
            incrementer = (SEQ_CC_Get(visible_track, SEQ_CC_MODE_FLAGS) & (1<<4)) ? -1 : 1;
        return SEQ_UI_CC_SetFlags(SEQ_CC_MODE_FLAGS, (1<<4), (incrementer >= 0) ? (1<<4) : 0);
    }

    return -1; // invalid or unsupported encoder
}
Exemplo n.º 23
0
/////////////////////////////////////////////////////////////////////////////
// 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
}