s32 SEQ_TERMINAL_PrintSdCardInfo(void *_output_function) { void (*out)(char *format, ...) = _output_function; FRESULT res; FILINFO fno; DIR dir; char *fn; char str_buffer[128]; MUTEX_MIDIOUT_TAKE; out("SD Card Informations\n"); out("====================\n"); #if !defined(MIOS32_FAMILY_EMULATION) // this yield ensures, that Debug Messages are sent before we continue the execution // Since MIOS Studio displays the time at which the messages arrived, this allows // us to measure the delay of following operations taskYIELD(); MUTEX_SDCARD_TAKE; SEQ_FILE_PrintSDCardInfos(); MUTEX_SDCARD_GIVE; #endif out("\n"); out("Reading Root Directory\n"); out("======================\n"); taskYIELD(); if( !SEQ_FILE_SDCardAvailable() ) { sprintf(str_buffer, "not connected"); } else if( !SEQ_FILE_VolumeAvailable() ) { sprintf(str_buffer, "Invalid FAT"); } else { out("Retrieving SD Card informations - please wait!\n"); MUTEX_MIDIOUT_GIVE; MUTEX_SDCARD_TAKE; SEQ_FILE_UpdateFreeBytes(); MUTEX_SDCARD_GIVE; MUTEX_MIDIOUT_TAKE; sprintf(str_buffer, "'%s': %u of %u MB free", SEQ_FILE_VolumeLabel(), (unsigned int)(SEQ_FILE_VolumeBytesFree()/1000000), (unsigned int)(SEQ_FILE_VolumeBytesTotal()/1000000)); } out("SD Card: %s\n", str_buffer); taskYIELD(); #if _USE_LFN static char lfn[_MAX_LFN * (_DF1S ? 2 : 1) + 1]; fno.lfname = lfn; fno.lfsize = sizeof(lfn); #endif MUTEX_SDCARD_TAKE; if( (res=f_opendir(&dir, "/")) != FR_OK ) { out("Failed to open root directory - error status: %d\n", res); } else { while( (f_readdir(&dir, &fno) == FR_OK) && fno.fname[0] ) { #if _USE_LFN fn = *fno.lfname ? fno.lfname : fno.fname; #else fn = fno.fname; #endif char date[10]; ShowFatDate(fno.fdate,(char*)&date); char time[12]; ShowFatTime(fno.ftime,(char*)&time); out("[%s%s%s%s%s%s%s] %s %s %s %u %s\n", (fno.fattrib & AM_RDO ) ? "r" : ".", (fno.fattrib & AM_HID ) ? "h" : ".", (fno.fattrib & AM_SYS ) ? "s" : ".", (fno.fattrib & AM_VOL ) ? "v" : ".", (fno.fattrib & AM_LFN ) ? "l" : ".", (fno.fattrib & AM_DIR ) ? "d" : ".", (fno.fattrib & AM_ARC ) ? "a" : ".", date,time, (fno.fattrib & AM_DIR) ? "<DIR>" : " ", fno.fsize,fn); } } MUTEX_SDCARD_GIVE; taskYIELD(); out("\n"); out("Checking SD Card at application layer\n"); out("=====================================\n"); out("Current session: /SESSIONS/%s\n", seq_file_session_name); { u8 bank; for(bank=0; bank<SEQ_FILE_B_NUM_BANKS; ++bank) { int num_patterns = SEQ_FILE_B_NumPatterns(bank); if( num_patterns ) out("File /SESSIONS/%s/MBSEQ_B%d.V4: valid (%d patterns)\n", seq_file_session_name, bank+1, num_patterns); else out("File /SESSIONS/%s/MBSEQ_B%d.V4: doesn't exist\n", seq_file_session_name, bank+1, num_patterns); } int num_maps = SEQ_FILE_M_NumMaps(); if( num_maps ) out("File /SESSIONS/%sMBSEQ_M.V4: valid (%d mixer maps)\n", seq_file_session_name, num_maps); else out("File /SESSIONS/%s/MBSEQ_M.V4: doesn't exist\n", seq_file_session_name); int num_songs = SEQ_FILE_S_NumSongs(); if( num_songs ) out("File /SESSIONS/%s/MBSEQ_S.V4: valid (%d songs)\n", seq_file_session_name, num_songs); else out("File /SESSIONS/%s/MBSEQ_S.V4: doesn't exist\n", seq_file_session_name); if( SEQ_FILE_G_Valid() ) out("File /SESSIONS/%s/MBSEQ_G.V4: valid\n", seq_file_session_name); else out("File /SESSIONS/%s/MBSEQ_G.V4: doesn't exist\n", seq_file_session_name); if( SEQ_FILE_C_Valid() ) out("File /SESSIONS/%s/MBSEQ_C.V4: valid\n", seq_file_session_name); else out("File /SESSIONS/%s/MBSEQ_C.V4: doesn't exist\n", seq_file_session_name); if( SEQ_FILE_HW_Valid() ) out("File /SESSIONS/%s/MBSEQ_HW.V4: valid\n", seq_file_session_name); else out("File /SESSIONS/%s/MBSEQ_HW.V4: doesn't exist or hasn't been re-loaded\n", seq_file_session_name); } out("done.\n"); MUTEX_MIDIOUT_GIVE; return 0; // no error }
///////////////////////////////////////////////////////////////////////////// // 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 }