Example #1
0
/////////////////////////////////////////////////////////////////////////////
// resets the variables of all tracks
/////////////////////////////////////////////////////////////////////////////
s32 SEQ_RECORD_ResetAllTracks(void)
{
  s32 status = 0;

  u8 track;
  for(track=0; track<SEQ_CORE_NUM_TRACKS; ++track)
    status |= SEQ_RECORD_Reset(track);

  return status;
}
Example #2
0
/////////////////////////////////////////////////////////////////////////////
// Called when a GP button has been toggled
/////////////////////////////////////////////////////////////////////////////
s32 SEQ_UI_PAGES_GP_Button_Handler(u8 button, u8 depressed)
{
  if( ui_controller_mode )
    return SEQ_UI_PAGES_GP_Button_Handler_Controller(button, depressed);

  // no page reacts on depressed buttons
  if( depressed )
    return 0;

  // clear button pressed: clear track
  if( seq_ui_button_state.CLEAR ) {
    u8 seq = (button >= 8) ? 1 : 0;
    u8 track_offset = seq ? 8 : 0;
    ui_selected_tracks = seq ? 0xff00 : 0x00ff;
    seq_record_state.ARMED_TRACKS = seq ? 0xff00 : 0x00ff;

    u8 seq_button = button % 8;
    switch( seq_button ) {
    case 0: { // clear note triggers (values are kept but not played)
      u8 track = track_offset;
      int num_t_steps = SEQ_TRG_NumStepsGet(track);
      int step8;
      u8 instrument = 0;
      u8 layer = 0;
      for(step8=0; step8<(num_t_steps/8); ++step8)
	SEQ_TRG_Set8(track, step8, layer, instrument, 0x00);
    } break;

    case 1: { // reset velocity values to 64
      u8 track = track_offset + 1;
      int num_p_layers = SEQ_PAR_NumLayersGet(track);
      int par_layer;
      for(par_layer=0; par_layer<num_p_layers; ++par_layer) {
	int num_p_instruments = SEQ_PAR_NumInstrumentsGet(track);
	int num_p_steps  = SEQ_PAR_NumStepsGet(track);;
	u8 init_value = 64;

	int step;
	int instrument;
	for(instrument=0; instrument<num_p_instruments; ++instrument)
	  for(step=0; step<num_p_steps; ++step)
	    SEQ_PAR_Set(track, step, par_layer, instrument, init_value);
      }
    } break;

    case 2: { // reset note length values to half step
      u8 track = track_offset + 2;
      int num_p_layers = SEQ_PAR_NumLayersGet(track);
      int par_layer;
      for(par_layer=0; par_layer<num_p_layers; ++par_layer) {
	int num_p_instruments = SEQ_PAR_NumInstrumentsGet(track);
	int num_p_steps  = SEQ_PAR_NumStepsGet(track);;
	u8 init_value = 51; // half length

	int step;
	int instrument;
	for(instrument=0; instrument<num_p_instruments; ++instrument)
	  for(step=0; step<num_p_steps; ++step)
	    SEQ_PAR_Set(track, step, par_layer, instrument, init_value);
      }
    } break;

    default: {
      u8 track = track_offset + seq_button;

      if( seq_button == 3 ) { // special treatmend for pitchbend
	int par_layer = 0;
	{
	  int num_p_instruments = SEQ_PAR_NumInstrumentsGet(track);
	  int num_p_steps  = SEQ_PAR_NumStepsGet(track);;
	  u8 init_value = 64;

	  int step;
	  int instrument;
	  for(instrument=0; instrument<num_p_instruments; ++instrument)
	    for(step=0; step<num_p_steps; ++step)
	      SEQ_PAR_Set(track, step, par_layer, instrument, init_value);
	}
	// send pitchbend 0 for proper reset of MIDI device
	SEQ_LAYER_DirectSendEvent(track, par_layer);
      }

      // clear CCs
      {
	int num_p_layers = SEQ_PAR_NumLayersGet(track);
	int par_layer;
	for(par_layer=(track == 3) ? 1 : 0; par_layer<num_p_layers; ++par_layer) { // don't touch pitchbender
	  int num_p_instruments = SEQ_PAR_NumInstrumentsGet(track);
	  int num_p_steps  = SEQ_PAR_NumStepsGet(track);;
	  u8 init_value = 64;

	  int step;
	  int instrument;
	  for(instrument=0; instrument<num_p_instruments; ++instrument)
	    for(step=0; step<num_p_steps; ++step)
	      SEQ_PAR_Set(track, step, par_layer, instrument, init_value);

	  // disable CC assignment
	  SEQ_CC_Set(track, SEQ_CC_LAY_CONST_B1+par_layer, 0x80);
	}
      }
    }
    }

    return 0;
  }

  switch( ui_page ) {

  ///////////////////////////////////////////////////////////////////////////
  case SEQ_UI_PAGE_LOAD:
  case SEQ_UI_PAGE_SAVE: {
    // not atomic so that files can be stored in background
    //portENTER_CRITICAL();

    u8 group;
    for(group=0; group<SEQ_CORE_NUM_GROUPS; ++group) {
      seq_pattern_t *pattern = &ui_selected_pattern[group];

      pattern->bank = group; // always same as group
      if( button < 8 ) {
	pattern->group = button;
	ui_selected_pattern_changing = 1;
      } else {
	pattern->num = button-8;
	ui_selected_pattern_changing = 0;

	if( ui_page == SEQ_UI_PAGE_SAVE ) {
	  //DEBUG_MSG("BEGIN Save %d:%c%d\n", pattern->bank+1, 'A'+pattern->group, pattern->num+1);
	  s32 status = 0;
	  if( (status=SEQ_PATTERN_Save(group, *pattern)) < 0 )
	    SEQ_UI_SDCardErrMsg(2000, status);
	  else
	    load_save_notifier_ctr = 300; // notify about save operation for 300 mS
	  //DEBUG_MSG("END   Save %d:%c%d\n", pattern->bank+1, 'A'+pattern->group, pattern->num+1);
	} else {
	  //DEBUG_MSG("BEGIN Load %d:%c%d\n", pattern->bank+1, 'A'+pattern->group, pattern->num+1);
	  SEQ_PATTERN_Change(group, *pattern, 0);
	  load_save_notifier_ctr = 300; // notify about load operation for 300 mS
	  //DEBUG_MSG("END   Load %d:%c%d\n", pattern->bank+1, 'A'+pattern->group, pattern->num+1);
	}
      }
    }

    //portEXIT_CRITICAL();
    return 0;
  } break;

  ///////////////////////////////////////////////////////////////////////////
  case SEQ_UI_PAGE_TRIGGER: {
    // should be atomic
    portENTER_CRITICAL();

    ui_selected_step = button;

    u8 track; // only change triggers if track 0 and 8
    for(track=0; track<SEQ_CORE_NUM_TRACKS; track+=8)
      if( ui_selected_tracks & (1 << track) ) {
	u8 *trg_ptr = (u8 *)&seq_trg_layer_value[track][2*ui_selected_step_view + (button>>3)];
	*trg_ptr ^= (1 << (button&7));
      }

    portEXIT_CRITICAL();
    return 0;
  } break;

  ///////////////////////////////////////////////////////////////////////////
  case SEQ_UI_PAGE_LENGTH: {
    // should be atomic
    portENTER_CRITICAL();

    u8 track;
    for(track=0; track<SEQ_CORE_NUM_TRACKS; ++track) {
      if( ui_selected_tracks & (1 << track) ) {
	if( seq_ui_button_state.LENGTH_PRESSED ) {
	  if( (track >= 0 && track <= 2) || (track >= 8 && track <= 10) )
	    SEQ_CC_Set(track, SEQ_CC_LOOP, 16*ui_selected_step_view + button);
	  else
	    SEQ_CC_Set(track, SEQ_CC_LOOP, 64*ui_selected_step_view + 4*button + 3); // 4x resolution
	} else {
	  if( (track >= 0 && track <= 2) || (track >= 8 && track <= 10) )
	    SEQ_CC_Set(track, SEQ_CC_LENGTH, 16*ui_selected_step_view + button);
	  else
	    SEQ_CC_Set(track, SEQ_CC_LENGTH, 64*ui_selected_step_view + 4*button + 3); // 4x resolution
	}
      }
    }

    portEXIT_CRITICAL();
    return 0;
  } break;

  ///////////////////////////////////////////////////////////////////////////
  case SEQ_UI_PAGE_PROGRESSION: {
    // should be atomic
    portENTER_CRITICAL();

    ui_selected_progression_preset = button;
    seq_ui_pages_progression_presets_t *preset = (seq_ui_pages_progression_presets_t *)&seq_ui_pages_progression_presets[ui_selected_progression_preset];
    u8 track;
    for(track=0; track<SEQ_CORE_NUM_TRACKS; track+=8) {
      if( ui_selected_tracks & (1 << track) ) {
	SEQ_CC_Set(track, SEQ_CC_STEPS_FORWARD, (preset->steps_forward > 0) ? (preset->steps_forward-1) : 0);
	SEQ_CC_Set(track, SEQ_CC_STEPS_JMPBCK, preset->steps_jump_back);
	SEQ_CC_Set(track, SEQ_CC_STEPS_REPLAY, preset->steps_replay);
	SEQ_CC_Set(track, SEQ_CC_STEPS_REPEAT, preset->steps_repeat);
	SEQ_CC_Set(track, SEQ_CC_STEPS_SKIP, preset->steps_skip);
	SEQ_CC_Set(track, SEQ_CC_STEPS_RS_INTERVAL, preset->steps_rs_interval);
      }
    }

    // GP1 also requests synch to measure
    // it's a good idea to do this for all tracks so that both sequences are in synch again
    if( button == 0 )
      SEQ_CORE_ManualSynchToMeasure(0xffff);

    portEXIT_CRITICAL();
    return 0;
  } break;

  ///////////////////////////////////////////////////////////////////////////
  case SEQ_UI_PAGE_GROOVE: {
    // should be atomic
    portENTER_CRITICAL();

    // first button turns off groove function
    // remaining buttons select custom groove #1..15
    u8 groove_style = 0;
    if( button > 0 ) // note: starting at second custom groove, the first groove is always "off"
      groove_style = button+8-1;
    SEQ_UI_CC_Set(SEQ_CC_GROOVE_STYLE, groove_style);
    portEXIT_CRITICAL();
    return 0;
  } break;

  ///////////////////////////////////////////////////////////////////////////
  case SEQ_UI_PAGE_ECHO: {
    // should be atomic
    portENTER_CRITICAL();

    ui_selected_echo_preset = button;
    seq_ui_pages_echo_presets_t *preset = (seq_ui_pages_echo_presets_t *)&seq_ui_pages_echo_presets[ui_selected_echo_preset];
    u8 track;
    for(track=0; track<SEQ_CORE_NUM_TRACKS; track+=8) {
      if( ui_selected_tracks & (1 << track) ) {
	SEQ_CC_Set(track, SEQ_CC_ECHO_REPEATS, preset->repeats);
	SEQ_CC_Set(track, SEQ_CC_ECHO_DELAY, preset->delay);
	SEQ_CC_Set(track, SEQ_CC_ECHO_VELOCITY, preset->velocity);
	SEQ_CC_Set(track, SEQ_CC_ECHO_FB_VELOCITY, preset->fb_velocity);
	SEQ_CC_Set(track, SEQ_CC_ECHO_FB_NOTE, preset->fb_note);
	SEQ_CC_Set(track, SEQ_CC_ECHO_FB_GATELENGTH, preset->fb_gatelength);
	SEQ_CC_Set(track, SEQ_CC_ECHO_FB_TICKS, preset->fb_ticks);
      }
    }

    portEXIT_CRITICAL();
  } break;

  ///////////////////////////////////////////////////////////////////////////
  case SEQ_UI_PAGE_HUMANIZER: {
    // should be atomic
    portENTER_CRITICAL();

    ui_selected_humanizer_preset = button;
    seq_ui_pages_humanizer_presets_t *preset = (seq_ui_pages_humanizer_presets_t *)&seq_ui_pages_humanizer_presets[ui_selected_humanizer_preset];
    u8 track;
    for(track=0; track<SEQ_CORE_NUM_TRACKS; track+=8) {
      if( ui_selected_tracks & (1 << track) ) {
	SEQ_CC_Set(track, SEQ_CC_HUMANIZE_MODE, preset->mode);
	SEQ_CC_Set(track, SEQ_CC_HUMANIZE_VALUE, preset->value);
      }
    }

    portEXIT_CRITICAL();
    return 0;
  } break;

  ///////////////////////////////////////////////////////////////////////////
  case SEQ_UI_PAGE_LFO: {
    // should be atomic
    portENTER_CRITICAL();

    ui_selected_lfo_preset = button;
    seq_ui_pages_lfo_presets_t *preset = (seq_ui_pages_lfo_presets_t *)&seq_ui_pages_lfo_presets[ui_selected_lfo_preset];
    u8 track;
    for(track=0; track<SEQ_CORE_NUM_TRACKS; track+=8) {
      if( ui_selected_tracks & (1 << track) ) {
	SEQ_CC_Set(track, SEQ_CC_LFO_WAVEFORM, preset->waveform);
	SEQ_CC_Set(track, SEQ_CC_LFO_AMPLITUDE, preset->amplitude);
	SEQ_CC_Set(track, SEQ_CC_LFO_PHASE, preset->phase);
	SEQ_CC_Set(track, SEQ_CC_LFO_STEPS, preset->steps);
	SEQ_CC_Set(track, SEQ_CC_LFO_STEPS_RST, preset->steps_rst);
	SEQ_CC_Set(track, SEQ_CC_LFO_ENABLE_FLAGS, preset->enable_flags);
	SEQ_CC_Set(track, SEQ_CC_LFO_CC, preset->cc);
	SEQ_CC_Set(track, SEQ_CC_LFO_CC_OFFSET, preset->cc_offset);
	SEQ_CC_Set(track, SEQ_CC_LFO_CC_PPQN, preset->cc_ppqn);
      }
    }

    portEXIT_CRITICAL();
    return 0;
  } break;

  ///////////////////////////////////////////////////////////////////////////
  case SEQ_UI_PAGE_SCALE: {
    // should be atomic
    portENTER_CRITICAL();

    // if SCALE button not pressed: select root key
    if( !seq_ui_button_state.SCALE_PRESSED ) {
      if( button < 12 ) {
	seq_core_global_scale_root_selection = button + 1;
      } else {
	seq_core_global_scale_root_selection = 0; // via keyboard
      }
    } else {
      // if pressed: select scale

      ui_selected_scale = button;

      if( ui_selected_scale == 0 ) {
	// disable force-to-scale for both note tracks (makes sense, since the scale itself is global as well)
	u8 track;
	for(track=0; track<SEQ_CORE_NUM_TRACKS; track+=8)
	  seq_cc_trk[track].mode.FORCE_SCALE = 0;
      } else {
	// select scale
	seq_core_global_scale = seq_ui_pages_scale_presets[ui_selected_scale];

	// enable force-to-scale for both note tracks (makes sense, since the scale itself is global as well)
	u8 track;
	for(track=0; track<SEQ_CORE_NUM_TRACKS; track+=8)
	  seq_cc_trk[track].mode.FORCE_SCALE = 1;
      }
    }

    portEXIT_CRITICAL();
    return 0;
  } break;

  ///////////////////////////////////////////////////////////////////////////
  case SEQ_UI_PAGE_MUTE: {
    // should be atomic
    portENTER_CRITICAL();

    seq_core_trk_muted ^= (1 << button);

    portEXIT_CRITICAL();
    return 0;
  } break;

  ///////////////////////////////////////////////////////////////////////////
  case SEQ_UI_PAGE_MIDICHN: {
    // should be atomic
    portENTER_CRITICAL();

    u8 track;
    for(track=0; track<SEQ_CORE_NUM_TRACKS; ++track)
      if( ui_selected_tracks & (1 << track) )
	SEQ_CC_Set(track, SEQ_CC_MIDI_CHANNEL, button);

    portEXIT_CRITICAL();
    return 0;
  } break;

  ///////////////////////////////////////////////////////////////////////////
  case SEQ_UI_PAGE_REC_ARM: {
    // should be atomic
    portENTER_CRITICAL();

    // allow to select an unplayed track
    if( button >= 8 && (seq_record_state.ARMED_TRACKS & 0x00ff) )
      seq_record_state.ARMED_TRACKS = 0xff00;
    else if( button < 8 && (seq_record_state.ARMED_TRACKS & 0xff00) )
      seq_record_state.ARMED_TRACKS = 0x00ff;
    else {
      seq_record_state.ARMED_TRACKS ^= (1 << button);
    }

    portEXIT_CRITICAL();
    return 0;
  } break;

  ///////////////////////////////////////////////////////////////////////////
  case SEQ_UI_PAGE_REC_STEP: {
  case SEQ_UI_PAGE_REC_LIVE:
    // should be atomic
    portENTER_CRITICAL();

    seq_record_step = 16*ui_selected_step_view + button;

    // we will always clear the current step for more comfortable handling
    // (no need to select the Trigger page for doing this)
    u8 track; // only change triggers if track 0 and 8
    for(track=0; track<SEQ_CORE_NUM_TRACKS; track+=8)
      if( seq_record_state.ARMED_TRACKS & (1 << track) ) {
	u8 *trg_ptr = (u8 *)&seq_trg_layer_value[track][2*ui_selected_step_view + (button>>3)];
	*trg_ptr &= ~(1 << (button&7));

	SEQ_RECORD_Reset(track);
      }

    portEXIT_CRITICAL();
    return 0;
  } break;