Beispiel #1
0
/////////////////////////////////////////////////////////////////////////////
// fetches the pos entries of a song
// returns -1 if recursion counter reached max position
/////////////////////////////////////////////////////////////////////////////
s32 SEQ_SONG_FetchPos(u8 force_immediate_change, u8 dont_dump_mixer_map)
{
  int recursion_ctr = 0;

  u8 again;
  do {
    again = 0;

    // stop song once recursion counter reached 64 loops
    if( ++recursion_ctr >= 64 ) {
      SEQ_BPM_Stop();
      return -1; // recursion detected
    }

    // reset song position if we reached the end (loop over 128 steps)
    if( song_pos >= SEQ_SONG_NUM_STEPS )
      song_pos = 0;

    // get step entry
    seq_song_step_t *s = (seq_song_step_t *)&seq_song_steps[song_pos];

    // branch depending on action
    switch( s->action ) {
      case SEQ_SONG_ACTION_End:
#if 0
	if( song_active ) // not in phrase mode
	  SEQ_BPM_Stop();
#else
	song_finished = 1; // deactivate song incrementer
#endif
	break;

      case SEQ_SONG_ACTION_JmpPos:
	song_pos = s->action_value % SEQ_SONG_NUM_STEPS;
	again = 1;
	break;

      case SEQ_SONG_ACTION_JmpSong: {
	if( song_active ) { // not in phrase mode
	  u32 new_song_num = s->action_value % SEQ_SONG_NUM;

	  SEQ_SONG_Save(song_num);
	  SEQ_SONG_Load(new_song_num);
	  song_pos = 0;
	  again = 1;
	}
      } break;

      case SEQ_SONG_ACTION_SelMixerMap:
	SEQ_MIXER_Load(s->action_value);
	SEQ_MIDI_IN_ExtCtrlSend(SEQ_MIDI_IN_EXT_CTRL_MIXER_MAP, s->action_value, 0);
	if( !dont_dump_mixer_map )
	  SEQ_MIXER_SendAll();
	++song_pos;
	again = 1;
	break;

      case SEQ_SONG_ACTION_Tempo: {
	float bpm = (float)s->action_value;
	if( bpm < 25.0 )
	  bpm = 25.0;
	float ramp = (float)s->pattern_g1;
	SEQ_CORE_BPM_Update(bpm, ramp);
	++song_pos;
	again = 1;
      } break;

      case SEQ_SONG_ACTION_Mutes: {
	// access to seq_core_trk[] must be atomic!
	portENTER_CRITICAL();

	seq_core_trk_muted =
	  ((s->pattern_g1 & 0x0f) <<  0) |
	  ((s->pattern_g2 & 0x0f) <<  4) |
	  ((s->pattern_g3 & 0x0f) <<  8) |
	  ((s->pattern_g4 & 0x0f) << 12);

	portEXIT_CRITICAL();

	++song_pos;
	again = 1;
      } break;

      case SEQ_SONG_ACTION_GuideTrack: {
	if( s->action_value <= 16 )
	  seq_song_guide_track = s->action_value;
	++song_pos;
	again = 1;
      } break;

      default:
	if( s->action >= SEQ_SONG_ACTION_Loop1 && s->action <= SEQ_SONG_ACTION_Loop16 ) {
	  song_loop_ctr = 0;
	  song_loop_ctr_max = s->action - SEQ_SONG_ACTION_Loop1;

	  // TODO: implement prefetching until end of step!
	  
	  SEQ_SONG_FetchHlp_PatternChange(0, s->pattern_g1, s->bank_g1, force_immediate_change);
	  SEQ_SONG_FetchHlp_PatternChange(1, s->pattern_g2, s->bank_g2, force_immediate_change);
	  SEQ_SONG_FetchHlp_PatternChange(2, s->pattern_g3, s->bank_g3, force_immediate_change);
	  SEQ_SONG_FetchHlp_PatternChange(3, s->pattern_g4, s->bank_g4, force_immediate_change);
	}
    }

  } while( again );

  return 0; // no error
}
Beispiel #2
0
/////////////////////////////////////////////////////////////////////////////
// This task is called periodically each second
/////////////////////////////////////////////////////////////////////////////
void SEQ_TASK_Period1S(void)
{
  static s8 wait_boot_ctr = 3; // wait 3 seconds before loading from SD Card - this is to increase the time where the boot screen is print!
  u8 load_sd_content = 0;

  // poll for IIC modules as long as HW config hasn't been locked (read from SD card)
  // TODO: use proper mutex handling here
#ifndef MIOS32_FAMILY_EMULATION
  if( !SEQ_FILE_HW_ConfigLocked() ) {
    MIOS32_IIC_MIDI_ScanInterfaces();
  }
#endif  

  // boot phase of 2 seconds finished?
  if( wait_boot_ctr > 0 ) {
    --wait_boot_ctr;
    if( wait_boot_ctr )
      return;
  }

  // BLM timeout counter
  MIOS32_IRQ_Disable();
  if( seq_blm_timeout_ctr )
    --seq_blm_timeout_ctr;
  MIOS32_IRQ_Enable();

  // check if SD Card connected
  MUTEX_SDCARD_TAKE;

  s32 status = FILE_CheckSDCard();

  if( status == 1 ) {
    if( wait_boot_ctr != 0 ) { // don't print message if we just booted
      char str[21];
      sprintf(str, "Label: %s", FILE_VolumeLabel());
#ifndef MBSEQV4L
      SEQ_UI_Msg(SEQ_UI_MSG_SDCARD, 2000, " SD Card connected", "        :-D");
#endif
      DEBUG_MSG("SD Card connected: %s\n", FILE_VolumeLabel());
    }
    SEQ_FILE_LoadSessionName();
    DEBUG_MSG("Loading session %s\n", seq_file_session_name);
    SEQ_FILE_LoadAllFiles(1);
  } else if( status == 2 ) {
#ifndef MBSEQV4L
    SEQ_UI_Msg(SEQ_UI_MSG_SDCARD, 2000, "SD Card disconnected", "        :-/");
#endif
    DEBUG_MSG("SD Card disconnected\n");
    SEQ_FILE_UnloadAllFiles();
    wait_boot_ctr = -1;
  } else if( status == 3 ) {
    if( !FILE_SDCardAvailable() ) {
#ifndef MBSEQV4L
      SEQ_UI_Msg(SEQ_UI_MSG_SDCARD, 2000, "  No SD Card found  ", "        :-(");
#endif
      DEBUG_MSG("SD Card not found\n");
      SEQ_FILE_HW_LockConfig(); // lock configuration
      wait_boot_ctr = -1;
    } else if( !FILE_VolumeAvailable() ) {
#ifndef MBSEQV4L
      SEQ_UI_Msg(SEQ_UI_MSG_SDCARD, 2000, "!! SD Card Error !!!", "!! Invalid FAT !!!!!");
#endif
      DEBUG_MSG("ERROR: SD Card contains invalid FAT!\n");
      SEQ_FILE_HW_LockConfig(); // lock configuration
      wait_boot_ctr = -1;
    } else {
#ifndef MBSEQV4L
      if( wait_boot_ctr != 0 ) { // don't print message if we just booted
	char str1[30];
	sprintf(str1, "Banks: ....");
	u8 bank;
	for(bank=0; bank<4; ++bank)
	  str1[7+bank] = SEQ_FILE_B_NumPatterns(bank) ? ('1'+bank) : '-';
	char str2[30];
	sprintf(str2, 
		"M:%c S:%c G:%c C:%c%c HW:%c", 
		SEQ_FILE_M_NumMaps() ? '*':'-',
		SEQ_FILE_S_NumSongs() ? '*':'-',
		SEQ_FILE_G_Valid() ? '*':'-',
		SEQ_FILE_C_Valid() ? 'S':'-',
		SEQ_FILE_GC_Valid() ? 'G':'-',
		SEQ_FILE_HW_Valid() ? '*':'-');
	SEQ_UI_Msg(SEQ_UI_MSG_SDCARD, 2000, str1, str2);
      }
#endif

#if MBSEQV4L
      // auto-format
      // check if formatting is required
      if( SEQ_FILE_FormattingRequired() ) {
	strcpy(seq_file_new_session_name, "DEF_V4L");
	DEBUG_MSG("Creating initial session '%s'... this can take some seconds!\n", seq_file_new_session_name);

	if( (status=SEQ_FILE_Format()) < 0 ) {
	  DEBUG_MSG("Failed to create session! (status: %d)\n", status);
	} else {
	  SEQ_FILE_StoreSessionName();
	  DEBUG_MSG("Done!\n");
	}
      }
#endif

      // request to load content of SD card
      load_sd_content = 1;

      // notify that boot finished
      wait_boot_ctr = -1;
    }
  } else if( status < 0 ) {
    wait_boot_ctr = -1;
#ifndef MBSEQV4L
    SEQ_UI_SDCardErrMsg(2000, status);
#endif
    DEBUG_MSG("ERROR: SD Card Error %d (FatFs: D%3d)\n", status, file_dfs_errno);
  }

  // check for format request
  // this is running with low priority, so that LCD is updated in parallel!
  if( seq_ui_format_req ) {
    // note: request should be cleared at the end of this process to avoid double-triggers!
    if( (status = SEQ_FILE_Format()) < 0 ) {
#ifndef MBSEQV4L
      SEQ_UI_SDCardErrMsg(2000, status);
#endif
      DEBUG_MSG("ERROR: SD Card Error %d (FatFs: D%3d)\n", status, file_dfs_errno);
    } else {
#ifndef MBSEQV4L
      SEQ_UI_Msg(SEQ_UI_MSG_USER, 1000, "Files created", "successfully!");
#endif
      DEBUG_MSG("Files created successfully!\n");

      // store session name
      status |= SEQ_FILE_StoreSessionName();
    }

    // request to load content of SD card
    load_sd_content = 1;

    // finally clear request
    seq_ui_format_req = 0;
  }

  // check for backup request
  // this is running with low priority, so that LCD is updated in parallel!
  if( seq_ui_backup_req ) {
    // note: request should be cleared at the end of this process to avoid double-triggers!
    status = SEQ_FILE_CreateBackup();
      
    if( status < 0 ) {
      if( status == FILE_ERR_COPY ) {
#ifndef MBSEQV4L
	SEQ_UI_Msg(SEQ_UI_MSG_USER, 2000, "COPY FAILED!", "ERROR :-(");
#endif
	DEBUG_MSG("ERROR: copy failed!\n");
      } else {
#ifndef MBSEQV4L
	SEQ_UI_SDCardErrMsg(2000, status);
#endif
	DEBUG_MSG("ERROR: SD Card Error %d (FatFs: D%3d)\n", status, file_dfs_errno);
      }
    }
    else {
#ifndef MBSEQV4L
      SEQ_UI_Msg(SEQ_UI_MSG_USER, 1000, "Files copied", "successfully!");
#endif
      DEBUG_MSG("Files copied successfully!\n");

      // store session name
      status |= SEQ_FILE_StoreSessionName();
    }

    // finally clear request
    seq_ui_backup_req = 0;
  }

  // check for save all request
  // this is running with low priority, so that LCD is updated in parallel!
  if( seq_ui_saveall_req ) {
    s32 status = 0;

    // store all patterns
    int group;
    for(group=0; group<SEQ_CORE_NUM_GROUPS; ++group)
      status |= SEQ_FILE_B_PatternWrite(seq_file_session_name, seq_pattern[group].bank, seq_pattern[group].pattern, group, 1);

    // store config (e.g. to store current song/mixermap/pattern numbers
    SEQ_FILE_C_Write(seq_file_session_name);

    // store global config
    SEQ_FILE_GC_Write();

    // store mixer map
    SEQ_MIXER_Save(SEQ_MIXER_NumGet());

    // store session name
    if( status >= 0 )
      status |= SEQ_FILE_StoreSessionName();

    if( status < 0 ) {
#ifndef MBSEQV4L
      SEQ_UI_SDCardErrMsg(2000, status);
#endif
      DEBUG_MSG("ERROR: SD Card Error %d (FatFs: D%3d)\n", status, file_dfs_errno);
    }

    // finally clear request
    seq_ui_saveall_req = 0;
  }

  MUTEX_SDCARD_GIVE;

  // load content of SD card if requested ((re-)connection detected)
  if( load_sd_content && !SEQ_FILE_FormattingRequired() ) {
    // send layout request to MBHP_BLM_SCALAR
    MUTEX_MIDIOUT_TAKE;
    SEQ_BLM_SYSEX_SendRequest(0x00);
    MUTEX_MIDIOUT_GIVE;

    // TODO: should we load the patterns when SD Card has been detected?
    // disadvantage: current edit patterns are destroyed - this could be fatal during a live session if there is a bad contact!

    SEQ_MIXER_Load(SEQ_MIXER_NumGet());
    SEQ_SONG_Load(SEQ_SONG_NumGet());
  }

#ifndef MBSEQV4L
  SEQ_LCD_LOGO_ScreenSaver_Period1S();
#endif
}