Subversion Repositories svn.mios32

Compare Revisions

Ignore whitespace Rev 1260 → Rev 1261

/trunk/apps/examples/speech_synth/app.c
26,6 → 26,7
#include <scs.h>
#include "scs_config.h"
 
#include "file.h"
#include "synth_file.h"
#include "synth_file_b.h"
 
283,6 → 284,8
/////////////////////////////////////////////////////////////////////////////
static void TASK_Period_1mS_LP(void *pvParameters)
{
u16 sdcard_check_ctr = 0;
 
MIOS32_LCD_Clear();
 
while( 1 ) {
291,74 → 294,82
// call SCS handler
SCS_Tick();
 
// SD Card handler
MUTEX_SDCARD_TAKE;
s32 status = SYNTH_FILE_CheckSDCard();
// each second: check if SD Card (still) available
if( ++sdcard_check_ctr >= 1000 ) {
sdcard_check_ctr = 0;
 
if( status == 1 ) {
DEBUG_MSG("SD Card connected: %s\n", SYNTH_FILE_VolumeLabel());
} else if( status == 2 ) {
DEBUG_MSG("SD Card disconnected\n");
} else if( status == 3 ) {
if( !SYNTH_FILE_SDCardAvailable() ) {
DEBUG_MSG("SD Card not found\n");
} else if( !SYNTH_FILE_VolumeAvailable() ) {
DEBUG_MSG("ERROR: SD Card contains invalid FAT!\n");
} else {
int bank;
for(bank=0; bank<SYNTH_FILE_B_NUM_BANKS; ++bank) {
u8 numPatches = SYNTH_FILE_B_NumPatches(bank);
MUTEX_SDCARD_TAKE;
s32 status = FILE_CheckSDCard();
 
if( numPatches ) {
DEBUG_MSG("Bank #%d contains %d patches\n", bank+1, numPatches);
} else {
DEBUG_MSG("Bank #%d not found - creating new one\n", bank+1);
if( (status=SYNTH_FILE_B_Create(synth_file_session_name, bank)) < 0 ) {
DEBUG_MSG("Failed to create Bank #%d (status: %d)\n", bank+1, status);
if( status == 1 ) {
DEBUG_MSG("SD Card connected: %s\n", FILE_VolumeLabel());
// load all file infos
SYNTH_FILE_LoadAllFiles(1); // including HW info
} else if( status == 2 ) {
DEBUG_MSG("SD Card disconnected\n");
// invalidate all file infos
SYNTH_FILE_UnloadAllFiles();
} else if( status == 3 ) {
if( !FILE_SDCardAvailable() ) {
DEBUG_MSG("SD Card not found\n");
} else if( !FILE_VolumeAvailable() ) {
DEBUG_MSG("ERROR: SD Card contains invalid FAT!\n");
} else {
int bank;
for(bank=0; bank<SYNTH_FILE_B_NUM_BANKS; ++bank) {
u8 numPatches = SYNTH_FILE_B_NumPatches(bank);
 
if( numPatches ) {
DEBUG_MSG("Bank #%d contains %d patches\n", bank+1, numPatches);
} else {
DEBUG_MSG("Bank #%d successfully created!\n", bank+1);
DEBUG_MSG("Bank #%d not found - creating new one\n", bank+1);
if( (status=SYNTH_FILE_B_Create(bank)) < 0 ) {
DEBUG_MSG("Failed to create Bank #%d (status: %d)\n", bank+1, status);
} else {
DEBUG_MSG("Bank #%d successfully created!\n", bank+1);
 
int numPatches = SYNTH_FILE_B_NumPatches(bank);
int patch;
for(patch=0; patch<numPatches; ++patch) {
DEBUG_MSG("Writing Bank %d Patch #%d\n", bank+1, patch+1);
MIOS32_LCD_CursorSet(0, 0); // TMP - use message system later
MIOS32_LCD_PrintFormattedString("Write Patch %d.%03d ", bank+1, patch+1);
MIOS32_LCD_CursorSet(0, 1); // TMP - use message system later
MIOS32_LCD_PrintFormattedString("Please wait... ");
u8 sourceGroup = 0;
u8 rename_if_empty_name = 0;
if( (status=SYNTH_FILE_B_PatchWrite(synth_file_session_name, bank, patch, sourceGroup, rename_if_empty_name)) < 0 ) {
DEBUG_MSG("Failed to write patch #%d into bank #%d (status: %d)\n", patch+1, bank+1, status);
int numPatches = SYNTH_FILE_B_NumPatches(bank);
int patch;
for(patch=0; patch<numPatches; ++patch) {
DEBUG_MSG("Writing Bank %d Patch #%d\n", bank+1, patch+1);
MIOS32_LCD_CursorSet(0, 0); // TMP - use message system later
MIOS32_LCD_PrintFormattedString("Write Patch %d.%03d ", bank+1, patch+1);
MIOS32_LCD_CursorSet(0, 1); // TMP - use message system later
MIOS32_LCD_PrintFormattedString("Please wait... ");
u8 sourceGroup = 0;
u8 rename_if_empty_name = 0;
if( (status=SYNTH_FILE_B_PatchWrite(bank, patch, sourceGroup, rename_if_empty_name)) < 0 ) {
DEBUG_MSG("Failed to write patch #%d into bank #%d (status: %d)\n", patch+1, bank+1, status);
}
}
 
SCS_DisplayUpdateRequest();
}
 
SCS_DisplayUpdateRequest();
}
}
}
status = SYNTH_FILE_UnloadAllFiles();
status = SYNTH_FILE_LoadAllFiles(1);
if( status < 0 ) {
DEBUG_MSG("Failed to load the newly created files!\n");
} else {
u8 initialBank = 0;
u8 initialPatch = 0;
u8 targetGroup = 0;
if( (status=SYNTH_FILE_B_PatchRead(initialBank, initialPatch, targetGroup)) < 0 ) {
char buffer[100];
sprintf(buffer, "Patch %c%03d", 'A'+initialBank, initialPatch+1);
SCS_Msg(SCS_MSG_ERROR_L, 1000, "Failed to read", buffer);
status = SYNTH_FILE_UnloadAllFiles();
status = SYNTH_FILE_LoadAllFiles(1);
if( status < 0 ) {
DEBUG_MSG("Failed to load the newly created files!\n");
} else {
// char buffer[100];
// sprintf(buffer, "Patch %c%03d", 'A'+initialBank, initialPatch+1);
// SCS_Msg(SCS_MSG_L, 1000, buffer, "read!");
u8 initialBank = 0;
u8 initialPatch = 0;
u8 targetGroup = 0;
if( (status=SYNTH_FILE_B_PatchRead(initialBank, initialPatch, targetGroup)) < 0 ) {
char buffer[100];
sprintf(buffer, "Patch %c%03d", 'A'+initialBank, initialPatch+1);
SCS_Msg(SCS_MSG_ERROR_L, 1000, "Failed to read", buffer);
} else {
// char buffer[100];
// sprintf(buffer, "Patch %c%03d", 'A'+initialBank, initialPatch+1);
// SCS_Msg(SCS_MSG_L, 1000, buffer, "read!");
}
}
}
}
 
MUTEX_SDCARD_GIVE;
}
 
MUTEX_SDCARD_GIVE;
}
 
}
/trunk/apps/examples/speech_synth/synth_file.c
2,18 → 2,6
/*
* File access functions
*
* Frontend functions to read/write files.
* Optimized for Memory Size and Speed!
*
* For the whole application only single file handlers for read and write
* operations are available. They are shared globally to save memory (because
* each FatFs handler allocates more than 512 bytes to store the last read
* sector)
*
* For read operations it is possible to re-open a file via a synth_file_t reference
* so that no directory access is required to find the first sector of the
* file (again).
*
* NOTE: before accessing the SD Card, the upper level function should
* synchronize with the SD Card semaphore!
* MUTEX_SDCARD_TAKE; // to take the semaphore
21,7 → 9,7
*
* ==========================================================================
*
* Copyright (C) 2008 Thorsten Klose (tk@midibox.org)
* Copyright (C) 2011 Thorsten Klose (tk@midibox.org)
* Licensed for personal non-commercial use only.
* All other rights reserved.
*
34,14 → 22,8
 
#include <mios32.h>
 
#include <ff.h>
#include <diskio.h>
#include <string.h>
 
#include "tasks.h"
 
#include "file.h"
#include "synth_file.h"
 
#include "synth_file_b.h"
 
 
58,260 → 40,32
// Global variables
/////////////////////////////////////////////////////////////////////////////
 
// name/directory of session
char synth_file_session_name[13];
char synth_file_new_session_name[13];
 
// last error status returned by DFS
// can be used as additional debugging help if SYNTH_FILE_*ERR returned by function
u32 synth_file_dfs_errno;
 
 
/////////////////////////////////////////////////////////////////////////////
// Local prototypes
/////////////////////////////////////////////////////////////////////////////
 
static s32 SYNTH_FILE_MountFS(void);
 
 
/////////////////////////////////////////////////////////////////////////////
// Local variables
/////////////////////////////////////////////////////////////////////////////
 
// FatFs variables
#define SECTOR_SIZE _MAX_SS
 
// Work area (file system object) for logical drives
static FATFS fs;
 
// disk label
static char disk_label[12];
 
// complete file structure for read/write accesses
static FIL synth_file_read;
static u8 synth_file_read_is_open; // only for safety purposes
static FIL synth_file_write;
static u8 synth_file_write_is_open; // only for safety purposes
 
// SD Card status
static u8 sdcard_available;
static u8 volume_available;
static u32 volume_free_bytes;
 
// buffer for copy operations and SysEx sender
#define TMP_BUFFER_SIZE _MAX_SS
static u8 tmp_buffer[TMP_BUFFER_SIZE];
 
static u8 status_msg_ctr;
 
 
/////////////////////////////////////////////////////////////////////////////
// Initialisation
/////////////////////////////////////////////////////////////////////////////
s32 SYNTH_FILE_Init(u32 mode)
{
strcpy(synth_file_session_name, "DEFAULT");
synth_file_new_session_name[0] = 0; // invalidate
synth_file_read_is_open = 0;
synth_file_write_is_open = 0;
sdcard_available = 0;
volume_available = 0;
volume_free_bytes = 0;
s32 status = 0;
 
// init SDCard access
s32 error = MIOS32_SDCARD_Init(0);
#if DEBUG_VERBOSE_LEVEL >= 2
DEBUG_MSG("[SYNTH_FILE] SD Card interface initialized, status: %d\n", error);
#endif
status |= FILE_Init(0);
status |= SYNTH_FILE_B_Init(0);
 
// for status message
status_msg_ctr = 5;
 
// init:
SYNTH_FILE_B_Init(0); // patch file access
 
 
return error;
return status;
}
 
 
/////////////////////////////////////////////////////////////////////////////
// This function should be called periodically to check the availability
// of the SD Card
//
// Once the chard has been detected, all banks will be read
// returns < 0 on errors (error codes are documented in synth_file.h)
// returns 1 if SD card has been connected
// returns 2 if SD card has been disconnected
// returns 3 if status message should be print
/////////////////////////////////////////////////////////////////////////////
s32 SYNTH_FILE_CheckSDCard(void)
{
// check if SD card is available
// High-speed access if SD card was previously available
u8 prev_sdcard_available = sdcard_available;
sdcard_available = MIOS32_SDCARD_CheckAvailable(prev_sdcard_available);
 
if( sdcard_available && !prev_sdcard_available ) {
#if DEBUG_VERBOSE_LEVEL >= 2
DEBUG_MSG("[SYNTH_FILE] SD Card has been connected!\n");
#endif
 
s32 error = SYNTH_FILE_MountFS();
#if DEBUG_VERBOSE_LEVEL >= 2
DEBUG_MSG("[SYNTH_FILE] Tried to mount file system, status: %d\n", error);
#endif
 
if( error < 0 ) {
// ensure that volume flagged as not available
volume_available = 0;
 
return error; // break here!
}
 
// load last selected session name
SYNTH_FILE_LoadSessionName();
 
// load all file infos
SYNTH_FILE_LoadAllFiles(1); // including HW info
 
// status message after 3 seconds
status_msg_ctr = 3;
 
return 1; // SD card has been connected
 
} else if( !sdcard_available && prev_sdcard_available ) {
#if DEBUG_VERBOSE_LEVEL >= 2
DEBUG_MSG("[SYNTH_FILE] SD Card disconnected!\n");
#endif
volume_available = 0;
 
// invalidate all file infos
SYNTH_FILE_UnloadAllFiles();
 
// invalidate session
strcpy(synth_file_session_name, "DEFAULT");
synth_file_new_session_name[0] = 0; // invalidate
 
return 2; // SD card has been disconnected
}
 
if( status_msg_ctr ) {
if( !--status_msg_ctr )
return 3;
}
 
return 0; // no error
}
 
 
/////////////////////////////////////////////////////////////////////////////
// Mount the file system
// returns < 0 on errors (error codes are documented in synth_file.h)
/////////////////////////////////////////////////////////////////////////////
static s32 SYNTH_FILE_MountFS(void)
{
FRESULT res;
DIR dir;
 
synth_file_read_is_open = 0;
synth_file_write_is_open = 0;
 
if( (res=f_mount(0, &fs)) != FR_OK ) {
DEBUG_MSG("[SYNTH_FILE] Failed to mount SD Card - error status: %d\n", res);
return -1; // error
}
 
if( (res=f_opendir(&dir, "/")) != FR_OK ) {
DEBUG_MSG("[SYNTH_FILE] Failed to open root directory - error status: %d\n", res);
return -2; // error
}
 
// TODO: read from master sector
disk_label[0] = 0;
 
volume_available = 1;
 
return 0; // no error
}
 
 
/////////////////////////////////////////////////////////////////////////////
// This function updates the number of free bytes by scanning the FAT for
// unused clusters.
// should be called before SYNTH_FILE_Volume* bytes are read
/////////////////////////////////////////////////////////////////////////////
s32 SYNTH_FILE_UpdateFreeBytes(void)
{
FRESULT res;
DIR dir;
DWORD free_clust;
 
if( (res=f_opendir(&dir, "/")) != FR_OK ) {
DEBUG_MSG("[SYNTH_FILE_UpdateFreeBytes] f_opendir failed with status %d!\n", res);
return SYNTH_FILE_ERR_UPDATE_FREE;
}
 
if( (res=f_getfree("/", &free_clust, &dir.fs)) != FR_OK ) {
#if DEBUG_VERBOSE_LEVEL >= 1
DEBUG_MSG("[SYNTH_FILE_UpdateFreeBytes] f_getfree failed with status %d!\n", res);
#endif
return SYNTH_FILE_ERR_UPDATE_FREE;
}
 
volume_free_bytes = free_clust * fs.csize * 512;
 
return 0; // no error
}
 
 
/////////////////////////////////////////////////////////////////////////////
// returns 1 if SD card available
/////////////////////////////////////////////////////////////////////////////
s32 SYNTH_FILE_SDCardAvailable(void)
{
return sdcard_available;
}
 
 
/////////////////////////////////////////////////////////////////////////////
// returns 1 if volume available
/////////////////////////////////////////////////////////////////////////////
s32 SYNTH_FILE_VolumeAvailable(void)
{
return volume_available;
}
 
 
/////////////////////////////////////////////////////////////////////////////
// returns number of available bytes
/////////////////////////////////////////////////////////////////////////////
u32 SYNTH_FILE_VolumeBytesFree(void)
{
return volume_free_bytes;
}
 
 
/////////////////////////////////////////////////////////////////////////////
// returns total number of available bytes
/////////////////////////////////////////////////////////////////////////////
u32 SYNTH_FILE_VolumeBytesTotal(void)
{
return (fs.max_clust-2)*fs.csize * 512;
}
 
 
/////////////////////////////////////////////////////////////////////////////
// returns volume label
/////////////////////////////////////////////////////////////////////////////
char *SYNTH_FILE_VolumeLabel(void)
{
return disk_label;
}
 
 
/////////////////////////////////////////////////////////////////////////////
// Loads all files
/////////////////////////////////////////////////////////////////////////////
s32 SYNTH_FILE_LoadAllFiles(u8 including_hw)
322,7 → 76,7
//status |= SYNTH_FILE_HW_Load();
}
 
status |= SYNTH_FILE_B_LoadAllBanks(synth_file_session_name);
status |= SYNTH_FILE_B_LoadAllBanks();
 
return status;
}
337,562 → 91,3
status |= SYNTH_FILE_B_UnloadAllBanks();
return status;
}
 
 
/////////////////////////////////////////////////////////////////////////////
// Stores the current name of the session in a file (/SESSIONS/LAST_ONE.V4), so
// that it can be restored after startup
/////////////////////////////////////////////////////////////////////////////
s32 SYNTH_FILE_StoreSessionName(void)
{
s32 status;
char filepath[30];
 
sprintf(filepath, "%s/LAST_ONE.V4", SYNTH_FILE_SESSION_PATH);
status=SYNTH_FILE_WriteOpen(filepath, 1);
if( status >= 0 ) {
status = SYNTH_FILE_WriteBuffer((u8 *)synth_file_session_name, strlen(synth_file_session_name));
if( status >= 0 )
status = SYNTH_FILE_WriteByte('\n');
SYNTH_FILE_WriteClose();
}
 
if( status < 0 ) {
#if DEBUG_VERBOSE_LEVEL >= 1
DEBUG_MSG("[SYNTH_FILE_StoreSessionName] ERROR: failed to store last session name (status: %d)\n", status);
#endif
}
 
return status;
}
 
 
/////////////////////////////////////////////////////////////////////////////
// Restores the last session from the file /SESSIONS/LAST_ONE.V4
/////////////////////////////////////////////////////////////////////////////
s32 SYNTH_FILE_LoadSessionName(void)
{
s32 status;
char filepath[30];
synth_file_t file;
 
sprintf(filepath, "%s/LAST_ONE.V4", SYNTH_FILE_SESSION_PATH);
if( (status=SYNTH_FILE_ReadOpen(&file, filepath)) >= 0 ) {
char linebuffer[20];
status = SYNTH_FILE_ReadLine((u8 *)&linebuffer, 20);
if( status < 0 || strlen(linebuffer) > 8 ) {
#if DEBUG_VERBOSE_LEVEL >= 1
DEBUG_MSG("[SYNTH_FILE_LoadSessionName] ERROR: invalid session name '%s'\n", linebuffer);
#endif
status = SYNTH_FILE_ERR_INVALID_SESSION_NAME;
} else {
// take over session name
strcpy(synth_file_session_name, linebuffer);
}
 
SYNTH_FILE_ReadClose(&file);
}
return status;
}
 
 
/////////////////////////////////////////////////////////////////////////////
// opens a file for reading
// Note: to save memory, one a single file is allowed to be opened per
// time - always use SYNTH_FILE_ReadClose() before opening a new file!
// Use SYNTH_FILE_ReadReOpen() to continue reading
// returns < 0 on errors (error codes are documented in synth_file.h)
/////////////////////////////////////////////////////////////////////////////
s32 SYNTH_FILE_ReadOpen(synth_file_t* file, char *filepath)
{
#if DEBUG_VERBOSE_LEVEL >= 2
DEBUG_MSG("[SYNTH_FILE] Opening file '%s'\n", filepath);
#endif
 
if( synth_file_read_is_open ) {
#if DEBUG_VERBOSE_LEVEL >= 1
DEBUG_MSG("[SYNTH_FILE] FAILURE: tried to open file '%s' for reading, but previous file hasn't been closed!\n", filepath);
#endif
return SYNTH_FILE_ERR_OPEN_READ_WITHOUT_CLOSE;
}
 
if( (synth_file_dfs_errno=f_open(&synth_file_read, filepath, FA_OPEN_EXISTING | FA_READ)) != FR_OK ) {
#if DEBUG_VERBOSE_LEVEL >= 2
DEBUG_MSG("[SYNTH_FILE] Error opening file - try mounting the partition again\n");
#endif
 
s32 error;
if( (error = SYNTH_FILE_MountFS()) < 0 ) {
#if DEBUG_VERBOSE_LEVEL >= 2
DEBUG_MSG("[SYNTH_FILE] mounting failed with status: %d\n", error);
#endif
return SYNTH_FILE_ERR_SD_CARD;
}
 
if( (synth_file_dfs_errno=f_open(&synth_file_read, filepath, FA_OPEN_EXISTING | FA_READ)) != FR_OK ) {
#if DEBUG_VERBOSE_LEVEL >= 2
DEBUG_MSG("[SYNTH_FILE] Still not able to open file - giving up!\n");
#endif
return SYNTH_FILE_ERR_OPEN_READ;
}
}
 
#if DEBUG_VERBOSE_LEVEL >= 2
DEBUG_MSG("[SYNTH_FILE] found '%s' of length %u\n", filepath, synth_file_read.fsize);
#endif
 
// store current file variables in synth_file_t
file->flag = synth_file_read.flag;
file->csect = synth_file_read.csect;
file->fptr = synth_file_read.fptr;
file->fsize = synth_file_read.fsize;
file->org_clust = synth_file_read.org_clust;
file->curr_clust = synth_file_read.curr_clust;
file->dsect = synth_file_read.dsect;
file->dir_sect = synth_file_read.dir_sect;
file->dir_ptr = synth_file_read.dir_ptr;
 
// file is opened
synth_file_read_is_open = 1;
 
return 0;
}
 
 
/////////////////////////////////////////////////////////////////////////////
// reopens a file for reading
// returns < 0 on errors (error codes are documented in synth_file.h)
/////////////////////////////////////////////////////////////////////////////
s32 SYNTH_FILE_ReadReOpen(synth_file_t* file)
{
#if DEBUG_VERBOSE_LEVEL >= 2
DEBUG_MSG("[SYNTH_FILE] Reopening file\n");
#endif
 
if( synth_file_read_is_open ) {
#if DEBUG_VERBOSE_LEVEL >= 1
DEBUG_MSG("[SYNTH_FILE] FAILURE: tried to reopen file, but previous file hasn't been closed!\n");
#endif
return SYNTH_FILE_ERR_OPEN_READ_WITHOUT_CLOSE;
}
 
// restore file variables from synth_file_t
synth_file_read.fs = &fs;
synth_file_read.id = fs.id;
synth_file_read.flag = file->flag;
synth_file_read.csect = file->csect;
synth_file_read.fptr = file->fptr;
synth_file_read.fsize = file->fsize;
synth_file_read.org_clust = file->org_clust;
synth_file_read.curr_clust = file->curr_clust;
synth_file_read.dsect = file->dsect;
synth_file_read.dir_sect = file->dir_sect;
synth_file_read.dir_ptr = file->dir_ptr;
 
// ensure that the right sector is in cache again
disk_read(synth_file_read.fs->drive, synth_file_read.buf, synth_file_read.dsect, 1);
 
// file is opened (again)
synth_file_read_is_open = 1;
 
return 0;
}
 
 
/////////////////////////////////////////////////////////////////////////////
// Closes a file which has been read
// File can be re-opened if required thereafter w/o performance issues
// returns < 0 on errors (error codes are documented in synth_file.h)
/////////////////////////////////////////////////////////////////////////////
s32 SYNTH_FILE_ReadClose(synth_file_t *file)
{
// store current file variables in synth_file_t
file->flag = synth_file_read.flag;
file->csect = synth_file_read.csect;
file->fptr = synth_file_read.fptr;
file->fsize = synth_file_read.fsize;
file->org_clust = synth_file_read.org_clust;
file->curr_clust = synth_file_read.curr_clust;
file->dsect = synth_file_read.dsect;
file->dir_sect = synth_file_read.dir_sect;
file->dir_ptr = synth_file_read.dir_ptr;
 
// file has been closed
synth_file_read_is_open = 0;
 
 
// don't close file via f_close()! We allow to open the file again
return 0;
}
 
 
/////////////////////////////////////////////////////////////////////////////
// Changes to a new file position
// returns < 0 on errors (error codes are documented in synth_file.h)
/////////////////////////////////////////////////////////////////////////////
s32 SYNTH_FILE_ReadSeek(u32 offset)
{
if( (synth_file_dfs_errno=f_lseek(&synth_file_read, offset)) != FR_OK ) {
#if DEBUG_VERBOSE_LEVEL >= 2
DEBUG_MSG("[SYNTH_FILE_ReadSeek] ERROR: seek to offset %u failed (FatFs status: %d)\n", offset, synth_file_dfs_errno);
#endif
return SYNTH_FILE_ERR_SEEK;
}
return 0; // no error
}
 
 
/////////////////////////////////////////////////////////////////////////////
// Read from file
// returns < 0 on errors (error codes are documented in synth_file.h)
/////////////////////////////////////////////////////////////////////////////
s32 SYNTH_FILE_ReadBuffer(u8 *buffer, u32 len)
{
UINT successcount;
 
// exit if volume not available
if( !volume_available )
return SYNTH_FILE_ERR_NO_VOLUME;
 
if( (synth_file_dfs_errno=f_read(&synth_file_read, buffer, len, &successcount)) != FR_OK ) {
#if DEBUG_VERBOSE_LEVEL >= 3
DEBUG_MSG("[SYNTH_FILE] Failed to read sector at position 0x%08x, status: %u\n", synth_file_read.fptr, synth_file_dfs_errno);
#endif
return SYNTH_FILE_ERR_READ;
}
if( successcount != len ) {
#if DEBUG_VERBOSE_LEVEL >= 3
DEBUG_MSG("[SYNTH_FILE] Wrong successcount while reading from position 0x%08x (count: %d)\n", synth_file_read.fptr, successcount);
#endif
return SYNTH_FILE_ERR_READCOUNT;
}
 
return 0; // no error
}
 
s32 SYNTH_FILE_ReadLine(u8 *buffer, u32 max_len)
{
s32 status;
u32 num_read = 0;
 
while( synth_file_read.fptr < synth_file_read.fsize ) {
status = SYNTH_FILE_ReadBuffer(buffer, 1);
 
if( status < 0 )
return status;
 
++num_read;
 
if( *buffer == '\n' || *buffer == '\r' )
break;
 
if( num_read < max_len )
++buffer;
}
 
// replace newline by terminator
*buffer = 0;
 
return num_read;
}
 
s32 SYNTH_FILE_ReadByte(u8 *byte)
{
return SYNTH_FILE_ReadBuffer(byte, 1);
}
 
s32 SYNTH_FILE_ReadHWord(u16 *hword)
{
// ensure little endian coding
u8 tmp[2];
s32 status = SYNTH_FILE_ReadBuffer(tmp, 2);
*hword = ((u16)tmp[0] << 0) | ((u16)tmp[1] << 8);
return status;
}
 
s32 SYNTH_FILE_ReadWord(u32 *word)
{
// ensure little endian coding
u8 tmp[4];
s32 status = SYNTH_FILE_ReadBuffer(tmp, 4);
*word = ((u32)tmp[0] << 0) | ((u32)tmp[1] << 8) | ((u32)tmp[2] << 16) | ((u32)tmp[3] << 24);
return status;
}
 
 
/////////////////////////////////////////////////////////////////////////////
// Opens a file for writing
// returns < 0 on errors (error codes are documented in synth_file.h)
/////////////////////////////////////////////////////////////////////////////
s32 SYNTH_FILE_WriteOpen(char *filepath, u8 create)
{
if( synth_file_write_is_open ) {
#if DEBUG_VERBOSE_LEVEL >= 1
DEBUG_MSG("[SYNTH_FILE] FAILURE: tried to open file '%s' for writing, but previous file hasn't been closed!\n", filepath);
#endif
return SYNTH_FILE_ERR_OPEN_WRITE_WITHOUT_CLOSE;
}
 
if( (synth_file_dfs_errno=f_open(&synth_file_write, filepath, (create ? FA_CREATE_ALWAYS : FA_OPEN_EXISTING) | FA_WRITE)) != FR_OK ) {
#if DEBUG_VERBOSE_LEVEL >= 2
DEBUG_MSG("[SYNTH_FILE] error opening file '%s' for writing!\n", filepath);
#endif
return SYNTH_FILE_ERR_OPEN_WRITE;
}
 
// remember state
synth_file_write_is_open = 1;
 
return 0; // no error
}
 
 
/////////////////////////////////////////////////////////////////////////////
// Closes a file by writing the last bytes
// returns < 0 on errors (error codes are documented in synth_file.h)
/////////////////////////////////////////////////////////////////////////////
s32 SYNTH_FILE_WriteClose(void)
{
s32 status = 0;
 
// close file
if( (synth_file_dfs_errno=f_close(&synth_file_write)) != FR_OK )
status = SYNTH_FILE_ERR_WRITECLOSE;
 
synth_file_write_is_open = 0;
 
return status;
}
 
 
 
/////////////////////////////////////////////////////////////////////////////
// Changes to a new file position
// returns < 0 on errors (error codes are documented in synth_file.h)
/////////////////////////////////////////////////////////////////////////////
s32 SYNTH_FILE_WriteSeek(u32 offset)
{
if( (synth_file_dfs_errno=f_lseek(&synth_file_write, offset)) != FR_OK ) {
#if DEBUG_VERBOSE_LEVEL >= 2
DEBUG_MSG("[SYNTH_FILE_ReadSeek] ERROR: seek to offset %u failed (FatFs status: %d)\n", offset, synth_file_dfs_errno);
#endif
return SYNTH_FILE_ERR_SEEK;
}
return 0; // no error
}
 
 
/////////////////////////////////////////////////////////////////////////////
// Returns current size of write file
/////////////////////////////////////////////////////////////////////////////
u32 SYNTH_FILE_WriteGetCurrentSize(void)
{
if( !synth_file_write_is_open )
return 0;
return synth_file_write.fsize;
}
 
 
/////////////////////////////////////////////////////////////////////////////
// Writes into a file with caching mechanism (actual write at end of sector)
// File has to be closed via SYNTH_FILE_WriteClose() after the last byte has
// been written
// returns < 0 on errors (error codes are documented in synth_file.h)
/////////////////////////////////////////////////////////////////////////////
s32 SYNTH_FILE_WriteBuffer(u8 *buffer, u32 len)
{
// exit if volume not available
if( !volume_available )
return SYNTH_FILE_ERR_NO_VOLUME;
 
UINT successcount;
if( (synth_file_dfs_errno=f_write(&synth_file_write, buffer, len, &successcount)) != FR_OK ) {
#if DEBUG_VERBOSE_LEVEL >= 3
DEBUG_MSG("[SYNTH_FILE] Failed to write buffer, status: %u\n", synth_file_dfs_errno);
#endif
return SYNTH_FILE_ERR_WRITE;
}
if( successcount != len ) {
#if DEBUG_VERBOSE_LEVEL >= 3
DEBUG_MSG("[SYNTH_FILE] Wrong successcount while writing buffer (count: %d)\n", successcount);
#endif
return SYNTH_FILE_ERR_WRITECOUNT;
}
 
return 0; // no error
}
 
s32 SYNTH_FILE_WriteByte(u8 byte)
{
return SYNTH_FILE_WriteBuffer(&byte, 1);
}
 
s32 SYNTH_FILE_WriteHWord(u16 hword)
{
// ensure little endian coding
u8 tmp[2];
tmp[0] = (u8)(hword >> 0);
tmp[1] = (u8)(hword >> 8);
return SYNTH_FILE_WriteBuffer(tmp, 2);
}
 
s32 SYNTH_FILE_WriteWord(u32 word)
{
// ensure little endian coding
u8 tmp[4];
tmp[0] = (u8)(word >> 0);
tmp[1] = (u8)(word >> 8);
tmp[2] = (u8)(word >> 16);
tmp[3] = (u8)(word >> 24);
return SYNTH_FILE_WriteBuffer(tmp, 4);
}
 
 
/////////////////////////////////////////////////////////////////////////////
// Creates a directory
/////////////////////////////////////////////////////////////////////////////
s32 SYNTH_FILE_MakeDir(char *path)
{
// exit if volume not available
if( !volume_available ) {
#if DEBUG_VERBOSE_LEVEL >= 2
DEBUG_MSG("[SYNTH_FILE_MakeDir] ERROR: volume doesn't exist!\n");
#endif
return SYNTH_FILE_ERR_NO_VOLUME;
}
 
if( (synth_file_dfs_errno=f_mkdir(path)) != FR_OK )
return SYNTH_FILE_ERR_MKDIR;
 
return 0; // directory created
}
 
 
/////////////////////////////////////////////////////////////////////////////
// Returns 1 if file exists, 0 if it doesn't exist, < 0 on errors
/////////////////////////////////////////////////////////////////////////////
s32 SYNTH_FILE_FileExists(char *filepath)
{
// exit if volume not available
if( !volume_available ) {
#if DEBUG_VERBOSE_LEVEL >= 2
DEBUG_MSG("[SYNTH_FILE_FileExists] ERROR: volume doesn't exist!\n");
#endif
return SYNTH_FILE_ERR_NO_VOLUME;
}
 
if( f_open(&synth_file_read, filepath, FA_OPEN_EXISTING | FA_READ) != FR_OK )
return 0; // file doesn't exist
//f_close(&synth_file_read); // never close read files to avoid "invalid object"
return 1; // file exists
}
 
 
/////////////////////////////////////////////////////////////////////////////
// Returns 1 if directory exists, 0 if it doesn't exist, < 0 on errors
/////////////////////////////////////////////////////////////////////////////
s32 SYNTH_FILE_DirExists(char *path)
{
DIR dir;
 
if( !volume_available ) {
#if DEBUG_VERBOSE_LEVEL >= 2
DEBUG_MSG("[SYNTH_FILE_DirExists] ERROR: volume doesn't exist!\n");
#endif
return SYNTH_FILE_ERR_NO_VOLUME;
}
 
return (synth_file_dfs_errno=f_opendir(&dir, path)) == FR_OK;
}
 
 
/////////////////////////////////////////////////////////////////////////////
// returns 1 if it is required to format any file
/////////////////////////////////////////////////////////////////////////////
s32 SYNTH_FILE_FormattingRequired(void)
{
return 0;
}
 
/////////////////////////////////////////////////////////////////////////////
// This function formats Bank/Mixer/Song files
/////////////////////////////////////////////////////////////////////////////
s32 SYNTH_FILE_Format(void)
{
s32 status = 0;
 
if( !volume_available ) {
#if DEBUG_VERBOSE_LEVEL >= 2
DEBUG_MSG("[SYNTH_FILE_Format] ERROR: volume doesn't exist!\n");
#endif
return SYNTH_FILE_ERR_NO_VOLUME;
}
 
if( synth_file_new_session_name[0] == 0 ) {
#if DEBUG_VERBOSE_LEVEL >= 1
DEBUG_MSG("[SYNTH_FILE_Format] ERROR: no new session specified!\n");
#endif
return SYNTH_FILE_ERR_NO_VOLUME;
}
 
// switch to new session name, store old name for the case that we have to switch back
char prev_session_name[13];
strcpy(prev_session_name, synth_file_session_name);
strcpy(synth_file_session_name, synth_file_new_session_name);
 
 
#if DEBUG_VERBOSE_LEVEL >= 2
DEBUG_MSG("[SYNTH_FILE_Format] Creating Session %s (previous was %s)\n", synth_file_session_name, prev_session_name);
#endif
 
// in any case invalidate new session name
synth_file_new_session_name[0] = 0;
 
// not implemented yet...
return status;
}
 
 
/////////////////////////////////////////////////////////////////////////////
// Send a verbose error message to MIOS terminal
// Used by SEQ_UI_SDCardErrMsg
/////////////////////////////////////////////////////////////////////////////
s32 SYNTH_FILE_SendErrorMessage(s32 error_status)
{
#if DEBUG_VERBOSE_LEVEL >= 1
switch( error_status ) {
case SYNTH_FILE_ERR_SD_CARD: DEBUG_MSG("[SDCARD_ERROR:%d] failed to access SD card\n", error_status); break;
case SYNTH_FILE_ERR_NO_PARTITION: DEBUG_MSG("[SDCARD_ERROR:%d] DFS_GetPtnStart failed to find partition\n", error_status); break;
case SYNTH_FILE_ERR_NO_VOLUME: DEBUG_MSG("[SDCARD_ERROR:%d] DFS_GetVolInfo failed to find volume information\n", error_status); break;
case SYNTH_FILE_ERR_UNKNOWN_FS: DEBUG_MSG("[SDCARD_ERROR:%d] unknown filesystem (only FAT12/16/32 supported)\n", error_status); break;
case SYNTH_FILE_ERR_OPEN_READ: DEBUG_MSG("[SDCARD_ERROR:%d] DFS_OpenFile(..DFS_READ..) failed, e.g. file not found\n", error_status); break;
case SYNTH_FILE_ERR_OPEN_READ_WITHOUT_CLOSE: DEBUG_MSG("[SDCARD_ERROR:%d] SYNTH_FILE_ReadOpen() has been called while previous file hasn't been closed\n", error_status); break;
case SYNTH_FILE_ERR_READ: DEBUG_MSG("[SDCARD_ERROR:%d] DFS_ReadFile failed\n", error_status); break;
case SYNTH_FILE_ERR_READCOUNT: DEBUG_MSG("[SDCARD_ERROR:%d] less bytes read than expected\n", error_status); break;
case SYNTH_FILE_ERR_READCLOSE: DEBUG_MSG("[SDCARD_ERROR:%d] DFS_ReadClose aborted due to previous error\n", error_status); break;
case SYNTH_FILE_ERR_WRITE_MALLOC: DEBUG_MSG("[SDCARD_ERROR:%d] SYNTH_FILE_WriteOpen failed to allocate memory for write buffer\n", error_status); break;
case SYNTH_FILE_ERR_OPEN_WRITE: DEBUG_MSG("[SDCARD_ERROR:%d] DFS_OpenFile(..DFS_WRITE..) failed\n", error_status); break;
case SYNTH_FILE_ERR_OPEN_WRITE_WITHOUT_CLOSE: DEBUG_MSG("[SDCARD_ERROR:%d] SYNTH_FILE_WriteOpen() has been called while previous file hasn't been closed\n", error_status); break;
case SYNTH_FILE_ERR_WRITE: DEBUG_MSG("[SDCARD_ERROR:%d] DFS_WriteFile failed\n", error_status); break;
case SYNTH_FILE_ERR_WRITECOUNT: DEBUG_MSG("[SDCARD_ERROR:%d] less bytes written than expected\n", error_status); break;
case SYNTH_FILE_ERR_WRITECLOSE: DEBUG_MSG("[SDCARD_ERROR:%d] DFS_WriteClose aborted due to previous error\n", error_status); break;
case SYNTH_FILE_ERR_SEEK: DEBUG_MSG("[SDCARD_ERROR:%d] SYNTH_FILE_Seek() failed\n", error_status); break;
case SYNTH_FILE_ERR_OPEN_DIR: DEBUG_MSG("[SDCARD_ERROR:%d] DFS_OpenDir(..DFS_READ..) failed, e.g. directory not found\n", error_status); break;
case SYNTH_FILE_ERR_COPY: DEBUG_MSG("[SDCARD_ERROR:%d] SYNTH_FILE_Copy() failed\n", error_status); break;
case SYNTH_FILE_ERR_COPY_NO_FILE: DEBUG_MSG("[SDCARD_ERROR:%d] source file doesn't exist\n", error_status); break;
case SYNTH_FILE_ERR_NO_DIR: DEBUG_MSG("[SDCARD_ERROR:%d] SYNTH_FILE_GetDirs() or SYNTH_FILE_GetFiles() failed because of missing directory\n", error_status); break;
case SYNTH_FILE_ERR_NO_FILE: DEBUG_MSG("[SDCARD_ERROR:%d] SYNTH_FILE_GetFiles() failed because of missing directory\n", error_status); break;
case SYNTH_FILE_ERR_SYSEX_READ: DEBUG_MSG("[SDCARD_ERROR:%d] error while reading .syx file\n", error_status); break;
case SYNTH_FILE_ERR_MKDIR: DEBUG_MSG("[SDCARD_ERROR:%d] SYNTH_FILE_MakeDir() failed\n", error_status); break;
case SYNTH_FILE_ERR_INVALID_SESSION_NAME: DEBUG_MSG("[SDCARD_ERROR:%d] SYNTH_FILE_LoadSessionName()\n", error_status); break;
case SYNTH_FILE_ERR_UPDATE_FREE: DEBUG_MSG("[SDCARD_ERROR:%d] SYNTH_FILE_UpdateFreeBytes()\n", error_status); break;
 
default:
// remaining errors just print the number
DEBUG_MSG("[SDCARD_ERROR:%d] see synth_file.h for description\n", error_status);
}
#endif
 
return 0; // no error
}
 
/trunk/apps/examples/speech_synth/synth_file_b.c
9,7 → 9,7
*
* ==========================================================================
*
* Copyright (C) 2008 Thorsten Klose (tk@midibox.org)
* Copyright (C) 2011 Thorsten Klose (tk@midibox.org)
* Licensed for personal non-commercial use only.
* All other rights reserved.
*
24,6 → 24,7
 
#include <string.h>
 
#include "file.h"
#include "synth_file.h"
#include "synth_file_b.h"
 
70,7 → 71,7
 
synth_file_b_header_t header;
 
synth_file_t file; // file informations
file_t file; // file informations
} synth_file_b_info_t;
 
 
107,7 → 108,7
// Called from SYNTH_FILE_CheckSDCard() when the SD card has been connected
// returns < 0 on errors
/////////////////////////////////////////////////////////////////////////////
s32 SYNTH_FILE_B_LoadAllBanks(char *session)
s32 SYNTH_FILE_B_LoadAllBanks(void)
{
s32 status = 0;
 
114,13 → 115,13
// load all banks
u8 bank;
for(bank=0; bank<SYNTH_FILE_B_NUM_BANKS; ++bank) {
s32 error = SYNTH_FILE_B_Open(session, bank);
s32 error = SYNTH_FILE_B_Open(bank);
#if DEBUG_VERBOSE_LEVEL >= 1
DEBUG_MSG("[SYNTH_FILE_B] Tried to open bank #%d file, status: %d\n", bank+1, error);
#endif
#if 0
if( error == -2 ) {
error = SYNTH_FILE_B_Create(session, bank);
error = SYNTH_FILE_B_Create(bank);
#if DEBUG_VERBOSE_LEVEL >= 1
DEBUG_MSG("[SYNTH_FILE_B] Tried to create bank #%d file, status: %d\n", bank+1, error);
#endif
166,7 → 167,7
// create a complete bank file
// returns < 0 on errors (error codes are documented in synth_file.h)
/////////////////////////////////////////////////////////////////////////////
s32 SYNTH_FILE_B_Create(char *session, u8 bank)
s32 SYNTH_FILE_B_Create(u8 bank)
{
if( bank >= SYNTH_FILE_B_NUM_BANKS )
return SYNTH_FILE_B_ERR_INVALID_BANK;
175,12 → 176,7
info->valid = 0; // set to invalid as long as we are not sure if file can be accessed
 
char filepath[MAX_PATH];
#if 0
sprintf(filepath, "%s/%s/SYNTH_B%d.V1", SYNTH_FILE_SESSION_PATH, session, bank+1);
#else
// currently no sessions used
sprintf(filepath, "/SYNTH_B%d.V1", bank+1);
#endif
 
#if DEBUG_VERBOSE_LEVEL >= 1
DEBUG_MSG("[SYNTH_FILE_B] Creating new bank file '%s'\n", filepath);
187,7 → 183,7
#endif
 
s32 status = 0;
if( (status=SYNTH_FILE_WriteOpen(filepath, 1)) < 0 ) {
if( (status=FILE_WriteOpen(filepath, 1)) < 0 ) {
#if DEBUG_VERBOSE_LEVEL >= 1
DEBUG_MSG("[SYNTH_FILE_B] Failed to create file, status: %d\n", status);
#endif
196,13 → 192,13
 
// write synth_file_b_header
const char file_type[10] = "SYNTHZZ_B";
status |= SYNTH_FILE_WriteBuffer((u8 *)file_type, 10);
status |= FILE_WriteBuffer((u8 *)file_type, 10);
 
// write bank name w/o zero terminator
char bank_name[21];
sprintf(bank_name, "Default Bank ");
memcpy(info->header.name, bank_name, 20);
status |= SYNTH_FILE_WriteBuffer((u8 *)info->header.name, 20);
status |= FILE_WriteBuffer((u8 *)info->header.name, 20);
#if DEBUG_VERBOSE_LEVEL >= 1
DEBUG_MSG("[SYNTH_FILE_B] writing '%s'...\n", bank_name);
#endif
209,13 → 205,13
 
// number of patches
info->header.num_patches = 64;
status |= SYNTH_FILE_WriteHWord(info->header.num_patches);
status |= FILE_WriteHWord(info->header.num_patches);
 
info->header.patch_size = SYNTH_NUM_PHRASES * (16*16 + 16); // currently hardcoded
status |= SYNTH_FILE_WriteWord(info->header.patch_size);
status |= FILE_WriteWord(info->header.patch_size);
 
// close file
status |= SYNTH_FILE_WriteClose();
status |= FILE_WriteClose();
 
if( status >= 0 )
// bank valid - caller should fill the patch slots with useful data now
234,7 → 230,7
// open a bank file
// returns < 0 on errors (error codes are documented in synth_file.h)
/////////////////////////////////////////////////////////////////////////////
s32 SYNTH_FILE_B_Open(char *session, u8 bank)
s32 SYNTH_FILE_B_Open(u8 bank)
{
if( bank >= SYNTH_FILE_B_NUM_BANKS )
return SYNTH_FILE_B_ERR_INVALID_BANK;
244,12 → 240,7
info->valid = 0; // will be set to valid if bank header has been read successfully
 
char filepath[MAX_PATH];
#if 0
sprintf(filepath, "%s/%s/SYNTH_B%d.V1", SYNTH_FILE_SESSION_PATH, session, bank+1);
#else
// currently no sessions used
sprintf(filepath, "/SYNTH_B%d.V1", bank+1);
#endif
 
#if DEBUG_VERBOSE_LEVEL >= 1
DEBUG_MSG("[SYNTH_FILE_B] Open bank file '%s'\n", filepath);
256,7 → 247,7
#endif
 
s32 status;
if( (status=SYNTH_FILE_ReadOpen((synth_file_t*)&info->file, filepath)) < 0 ) {
if( (status=FILE_ReadOpen((file_t*)&info->file, filepath)) < 0 ) {
#if DEBUG_VERBOSE_LEVEL >= 1
DEBUG_MSG("[SYNTH_FILE_B] failed to open file, status: %d\n", status);
#endif
266,7 → 257,7
// read and check header
// in order to avoid endianess issues, we have to read the sector bytewise!
char file_type[10];
if( (status=SYNTH_FILE_ReadBuffer((u8 *)file_type, 10)) < 0 ) {
if( (status=FILE_ReadBuffer((u8 *)file_type, 10)) < 0 ) {
#if DEBUG_VERBOSE_LEVEL >= 1
DEBUG_MSG("[SYNTH_FILE_B] failed to read header, status: %d\n", status);
#endif
281,9 → 272,9
return SYNTH_FILE_B_ERR_FORMAT;
}
 
status |= SYNTH_FILE_ReadBuffer((u8 *)info->header.name, 20);
status |= SYNTH_FILE_ReadHWord((u16 *)&info->header.num_patches);
status |= SYNTH_FILE_ReadWord((u32 *)&info->header.patch_size);
status |= FILE_ReadBuffer((u8 *)info->header.name, 20);
status |= FILE_ReadHWord((u16 *)&info->header.num_patches);
status |= FILE_ReadWord((u32 *)&info->header.patch_size);
 
if( status < 0 ) {
#if DEBUG_VERBOSE_LEVEL >= 1
293,7 → 284,7
}
 
// close file (so that it can be re-opened)
SYNTH_FILE_ReadClose((synth_file_t*)&info->file);
FILE_ReadClose((file_t*)&info->file);
 
// bank is valid! :)
info->valid = 1;
331,18 → 322,18
return SYNTH_FILE_B_ERR_INVALID_PATCH;
 
// re-open file
if( SYNTH_FILE_ReadReOpen((synth_file_t*)&info->file) < 0 )
if( FILE_ReadReOpen((file_t*)&info->file) < 0 )
return -1; // file cannot be re-opened
 
// change to file position
s32 status;
u32 offset = 10 + sizeof(synth_file_b_header_t) + patch * info->header.patch_size;
if( (status=SYNTH_FILE_ReadSeek(offset)) < 0 ) {
if( (status=FILE_ReadSeek(offset)) < 0 ) {
#if DEBUG_VERBOSE_LEVEL >= 1
DEBUG_MSG("[SYNTH_FILE_B] failed to change patch offset in file, status: %d\n", status);
#endif
// close file (so that it can be re-opened)
SYNTH_FILE_ReadClose((synth_file_t*)&info->file);
FILE_ReadClose((file_t*)&info->file);
return SYNTH_FILE_B_ERR_READ;
}
 
349,18 → 340,18
u8 patchNameLen = 16; // failsave to avoid unwanted overwrite
if( patchNameLen > SYNTH_PATCH_NAME_LEN )
patchNameLen = SYNTH_PATCH_NAME_LEN;
status |= SYNTH_FILE_ReadBuffer((u8 *)SYNTH_PatchNameGet(target_group), patchNameLen);
status |= FILE_ReadBuffer((u8 *)SYNTH_PatchNameGet(target_group), patchNameLen);
u32 reservedName; // reserve 4 chars for longer name
status |= SYNTH_FILE_ReadWord(&reservedName);
status |= FILE_ReadWord(&reservedName);
 
u8 reserved1;
status |= SYNTH_FILE_ReadByte(&reserved1);
status |= FILE_ReadByte(&reserved1);
u8 reserved2;
status |= SYNTH_FILE_ReadByte(&reserved2);
status |= FILE_ReadByte(&reserved2);
u8 reserved3;
status |= SYNTH_FILE_ReadByte(&reserved3);
status |= FILE_ReadByte(&reserved3);
u8 reserved4;
status |= SYNTH_FILE_ReadByte(&reserved4);
status |= FILE_ReadByte(&reserved4);
 
#if DEBUG_VERBOSE_LEVEL >= 1
DEBUG_MSG("[SYNTH_FILE_B] read patch B%d:P%d '%s'\n", bank+1, patch, SYNTH_PatchNameGet(target_group));
373,7 → 364,7
int par;
for(par=0; par<16; ++par) {
u8 value;
status |= SYNTH_FILE_ReadByte(&value);
status |= FILE_ReadByte(&value);
SYNTH_PhonemeParSet(phrase, ix, par, value);
}
}
381,13 → 372,13
int par;
for(par=0; par<16; ++par) {
u8 value;
status |= SYNTH_FILE_ReadByte(&value);
status |= FILE_ReadByte(&value);
SYNTH_PhraseParSet(phrase, par, value);
}
}
 
// close file (so that it can be re-opened)
SYNTH_FILE_ReadClose((synth_file_t*)&info->file);
FILE_ReadClose((file_t*)&info->file);
 
if( status < 0 ) {
#if DEBUG_VERBOSE_LEVEL >= 1
404,7 → 395,7
// writes a patch of a given group into bank
// returns < 0 on errors (error codes are documented in synth_file.h)
/////////////////////////////////////////////////////////////////////////////
s32 SYNTH_FILE_B_PatchWrite(char *session, u8 bank, u8 patch, u8 source_group, u8 rename_if_empty_name)
s32 SYNTH_FILE_B_PatchWrite(u8 bank, u8 patch, u8 source_group, u8 rename_if_empty_name)
{
if( bank >= SYNTH_FILE_B_NUM_BANKS )
return SYNTH_FILE_B_ERR_INVALID_BANK;
421,12 → 412,7
return SYNTH_FILE_B_ERR_INVALID_PATCH;
 
char filepath[MAX_PATH];
#if 0
sprintf(filepath, "%s/%s/SYNTH_B%d.V1", SYNTH_FILE_SESSION_PATH, session, bank+1);
#else
// currently no sessions used
sprintf(filepath, "/SYNTH_B%d.V1", bank+1);
#endif
 
#if DEBUG_VERBOSE_LEVEL >= 1
DEBUG_MSG("[SYNTH_FILE_B] Open bank file '%s' for writing\n", filepath);
433,21 → 419,21
#endif
 
s32 status = 0;
if( (status=SYNTH_FILE_WriteOpen(filepath, 0)) < 0 ) {
if( (status=FILE_WriteOpen(filepath, 0)) < 0 ) {
#if DEBUG_VERBOSE_LEVEL >= 1
DEBUG_MSG("[SYNTH_FILE_B] Failed to open file, status: %d\n", status);
#endif
SYNTH_FILE_WriteClose(); // important to free memory given by malloc
FILE_WriteClose(); // important to free memory given by malloc
return status;
}
 
// change to file position
u32 offset = 10 + sizeof(synth_file_b_header_t) + patch * info->header.patch_size;
if( (status=SYNTH_FILE_WriteSeek(offset)) < 0 ) {
if( (status=FILE_WriteSeek(offset)) < 0 ) {
#if DEBUG_VERBOSE_LEVEL >= 1
DEBUG_MSG("[SYNTH_FILE_B] failed to change patch offset in file, status: %d\n", status);
#endif
SYNTH_FILE_WriteClose(); // important to free memory given by malloc
FILE_WriteClose(); // important to free memory given by malloc
return status;
}
 
467,9 → 453,9
}
 
// write patch name w/o zero terminator
status |= SYNTH_FILE_WriteBuffer((u8 *)SYNTH_PatchNameGet(source_group), 16);
status |= FILE_WriteBuffer((u8 *)SYNTH_PatchNameGet(source_group), 16);
u32 reservedName; // reserve 4 chars for longer name
status |= SYNTH_FILE_ReadWord(&reservedName);
status |= FILE_ReadWord(&reservedName);
 
#if DEBUG_VERBOSE_LEVEL >= 2
DEBUG_MSG("[SYNTH_FILE_B] writing patch '%s'...\n", SYNTH_PatchNameGet(source_group));
476,10 → 462,10
#endif
 
// reserved
status |= SYNTH_FILE_WriteByte(0x00);
status |= SYNTH_FILE_WriteByte(0x00);
status |= SYNTH_FILE_WriteByte(0x00);
status |= SYNTH_FILE_WriteByte(0x00);
status |= FILE_WriteByte(0x00);
status |= FILE_WriteByte(0x00);
status |= FILE_WriteByte(0x00);
status |= FILE_WriteByte(0x00);
 
// writing phrases
int phrase;
488,18 → 474,18
for(ix=0; ix<SYNTH_PHRASE_MAX_LENGTH; ++ix) {
int par;
for(par=0; par<16; ++par) {
status |= SYNTH_FILE_WriteByte(SYNTH_PhonemeParGet(phrase, ix, par));
status |= FILE_WriteByte(SYNTH_PhonemeParGet(phrase, ix, par));
}
}
 
int par;
for(par=0; par<16; ++par) {
status |= SYNTH_FILE_WriteByte(SYNTH_PhraseParGet(phrase, par));
status |= FILE_WriteByte(SYNTH_PhraseParGet(phrase, par));
}
}
 
// close file
status |= SYNTH_FILE_WriteClose();
status |= FILE_WriteClose();
 
#if DEBUG_VERBOSE_LEVEL >= 1
DEBUG_MSG("[SYNTH_FILE_B] Patch written with status %d\n", status);
552,27 → 538,27
return SYNTH_FILE_B_ERR_INVALID_PATCH;
 
// re-open file
if( SYNTH_FILE_ReadReOpen((synth_file_t*)&info->file) < 0 )
if( FILE_ReadReOpen((file_t*)&info->file) < 0 )
return -1; // file cannot be re-opened
 
// change to file position
s32 status;
u32 offset = 10 + sizeof(synth_file_b_header_t) + patch * info->header.patch_size;
if( (status=SYNTH_FILE_ReadSeek(offset)) < 0 ) {
if( (status=FILE_ReadSeek(offset)) < 0 ) {
#if DEBUG_VERBOSE_LEVEL >= 1
DEBUG_MSG("[SYNTH_FILE_B] failed to change patch offset in file, status: %d\n", status);
#endif
// close file (so that it can be re-opened)
SYNTH_FILE_ReadClose((synth_file_t*)&info->file);
FILE_ReadClose((file_t*)&info->file);
return SYNTH_FILE_B_ERR_READ;
}
 
// read name
status |= SYNTH_FILE_ReadBuffer((u8 *)cached_patch_name, 20);
status |= FILE_ReadBuffer((u8 *)cached_patch_name, 20);
cached_patch_name[20] = 0;
 
// close file (so that it can be re-opened)
SYNTH_FILE_ReadClose((synth_file_t*)&info->file);
FILE_ReadClose((file_t*)&info->file);
 
// fill category with "-----" if it is empty
int i;
/trunk/apps/examples/speech_synth/synth_file.h
22,39 → 22,9
// Global definitions
/////////////////////////////////////////////////////////////////////////////
 
// in which subdirectory of the SD card are session directories located?
#define SYNTH_FILE_SESSION_PATH "/SESSIONS"
 
 
// error codes
// NOTE: SYNTH_FILE_SendErrorMessage() should be extended whenever new codes have been added!
// see also basic error codes which are documented in file.h
 
#define SYNTH_FILE_ERR_SD_CARD -1 // failed to access SD card
#define SYNTH_FILE_ERR_NO_PARTITION -2 // DFS_GetPtnStart failed to find partition
#define SYNTH_FILE_ERR_NO_VOLUME -3 // DFS_GetVolInfo failed to find volume information
#define SYNTH_FILE_ERR_UNKNOWN_FS -4 // unknown filesystem (only FAT12/16/32 supported)
#define SYNTH_FILE_ERR_OPEN_READ -5 // DFS_OpenFile(..DFS_READ..) failed, e.g. file not found
#define SYNTH_FILE_ERR_OPEN_READ_WITHOUT_CLOSE -6 // SYNTH_FILE_ReadOpen() has been called while previous file hasn't been closed via SYNTH_FILE_ReadClose()
#define SYNTH_FILE_ERR_READ -7 // DFS_ReadFile failed
#define SYNTH_FILE_ERR_READCOUNT -8 // less bytes read than expected
#define SYNTH_FILE_ERR_READCLOSE -9 // DFS_ReadClose aborted due to previous error
#define SYNTH_FILE_ERR_WRITE_MALLOC -10 // SYNTH_FILE_WriteOpen failed to allocate memory for write buffer
#define SYNTH_FILE_ERR_OPEN_WRITE -11 // DFS_OpenFile(..DFS_WRITE..) failed
#define SYNTH_FILE_ERR_OPEN_WRITE_WITHOUT_CLOSE -12 // SYNTH_FILE_WriteOpen() has been called while previous file hasn't been closed via SYNTH_FILE_WriteClose()
#define SYNTH_FILE_ERR_WRITE -13 // DFS_WriteFile failed
#define SYNTH_FILE_ERR_WRITECOUNT -14 // less bytes written than expected
#define SYNTH_FILE_ERR_WRITECLOSE -15 // DFS_WriteClose aborted due to previous error
#define SYNTH_FILE_ERR_SEEK -16 // SYNTH_FILE_Seek() failed
#define SYNTH_FILE_ERR_OPEN_DIR -17 // DFS_OpenDir(..DFS_READ..) failed, e.g. directory not found
#define SYNTH_FILE_ERR_COPY -18 // SYNTH_FILE_Copy() failed
#define SYNTH_FILE_ERR_COPY_NO_FILE -19 // source file doesn't exist
#define SYNTH_FILE_ERR_NO_DIR -20 // SYNTH_FILE_GetDirs() or SYNTH_FILE_GetFiles() failed because of missing directory
#define SYNTH_FILE_ERR_NO_FILE -21 // SYNTH_FILE_GetFiles() failed because of missing directory
#define SYNTH_FILE_ERR_SYSEX_READ -22 // error while reading .syx file
#define SYNTH_FILE_ERR_MKDIR -23 // SYNTH_FILE_MakeDir() failed
#define SYNTH_FILE_ERR_INVALID_SESSION_NAME -24 // SYNTH_FILE_LoadSessionName()
#define SYNTH_FILE_ERR_UPDATE_FREE -25 // SYNTH_FILE_UpdateFreeBytes()
 
// used by synth_file_b.c
#define SYNTH_FILE_B_ERR_INVALID_BANK -128 // invalid bank number
#define SYNTH_FILE_B_ERR_INVALID_GROUP -129 // invalid group number
70,20 → 40,7
// Global Types
/////////////////////////////////////////////////////////////////////////////
 
// simplified file reference, part of FIL structure of FatFs
typedef struct {
u8 flag; // file status flag
u8 csect; // sector address in cluster
u32 fptr; // file r/w pointer
u32 fsize; // file size
u32 org_clust; // file start cluster
u32 curr_clust; // current cluster
u32 dsect; // current data sector;
u32 dir_sect; // sector containing the directory entry
u8 *dir_ptr; // pointer to the directory entry in the window
} synth_file_t;
 
 
/////////////////////////////////////////////////////////////////////////////
// Prototypes
/////////////////////////////////////////////////////////////////////////////
90,66 → 47,13
 
extern s32 SYNTH_FILE_Init(u32 mode);
 
extern s32 SYNTH_FILE_CheckSDCard(void);
 
extern s32 SYNTH_FILE_SDCardAvailable(void);
extern s32 SYNTH_FILE_VolumeAvailable(void);
extern u32 SYNTH_FILE_VolumeBytesFree(void);
extern u32 SYNTH_FILE_VolumeBytesTotal(void);
extern char *SYNTH_FILE_VolumeLabel(void);
extern s32 SYNTH_FILE_UpdateFreeBytes(void);
 
extern s32 SYNTH_FILE_LoadAllFiles(u8 including_hw);
extern s32 SYNTH_FILE_UnloadAllFiles(void);
 
extern s32 SYNTH_FILE_StoreSessionName(void);
extern s32 SYNTH_FILE_LoadSessionName(void);
 
extern s32 SYNTH_FILE_ReadOpen(synth_file_t* file, char *filepath);
extern s32 SYNTH_FILE_ReadReOpen(synth_file_t* file);
extern s32 SYNTH_FILE_ReadClose(synth_file_t* file);
extern s32 SYNTH_FILE_ReadSeek(u32 offset);
extern s32 SYNTH_FILE_ReadBuffer(u8 *buffer, u32 len);
extern s32 SYNTH_FILE_ReadLine(u8 *buffer, u32 max_len);
extern s32 SYNTH_FILE_ReadByte(u8 *byte);
extern s32 SYNTH_FILE_ReadHWord(u16 *hword);
extern s32 SYNTH_FILE_ReadWord(u32 *word);
 
extern s32 SYNTH_FILE_WriteOpen(char *filepath, u8 create);
extern s32 SYNTH_FILE_WriteClose(void);
extern s32 SYNTH_FILE_WriteSeek(u32 offset);
extern u32 SYNTH_FILE_WriteGetCurrentSize(void);
extern s32 SYNTH_FILE_WriteBuffer(u8 *buffer, u32 len);
extern s32 SYNTH_FILE_WriteByte(u8 byte);
extern s32 SYNTH_FILE_WriteHWord(u16 hword);
extern s32 SYNTH_FILE_WriteWord(u32 word);
 
extern s32 SYNTH_FILE_MakeDir(char *path);
 
extern s32 SYNTH_FILE_FileExists(char *filepath);
extern s32 SYNTH_FILE_DirExists(char *path);
 
extern s32 SYNTH_FILE_FormattingRequired(void);
extern s32 SYNTH_FILE_Format(void);
 
extern s32 SYNTH_FILE_SendErrorMessage(s32 error_status);
 
 
/////////////////////////////////////////////////////////////////////////////
// Export global variables
/////////////////////////////////////////////////////////////////////////////
 
// name/directory of session
extern char synth_file_session_name[13];
extern char synth_file_new_session_name[13];
 
// last error status returned by DFS
// can be used as additional debugging help if SYNTH_FILE_*ERR returned by function
extern u32 synth_file_dfs_errno;
 
extern char *synth_file_backup_notification;
 
extern u8 synth_file_copy_percentage;
extern u8 synth_file_backup_percentage;
 
#endif /* _SYNTH_FILE_H */
/trunk/apps/examples/speech_synth/synth_file_b.h
4,7 → 4,7
*
* ==========================================================================
*
* Copyright (C) 2008 Thorsten Klose (tk@midibox.org)
* Copyright (C) 2011 Thorsten Klose (tk@midibox.org)
* Licensed for personal non-commercial use only.
* All other rights reserved.
*
32,16 → 32,16
/////////////////////////////////////////////////////////////////////////////
 
extern s32 SYNTH_FILE_B_Init(u32 mode);
extern s32 SYNTH_FILE_B_LoadAllBanks(char *session);
extern s32 SYNTH_FILE_B_LoadAllBanks(void);
extern s32 SYNTH_FILE_B_UnloadAllBanks(void);
 
extern s32 SYNTH_FILE_B_NumPatches(u8 bank);
 
extern s32 SYNTH_FILE_B_Create(char *session, u8 bank);
extern s32 SYNTH_FILE_B_Open(char *session, u8 bank);
extern s32 SYNTH_FILE_B_Create(u8 bank);
extern s32 SYNTH_FILE_B_Open(u8 bank);
 
extern s32 SYNTH_FILE_B_PatchRead(u8 bank, u8 patch, u8 target_group);
extern s32 SYNTH_FILE_B_PatchWrite(char *session, u8 bank, u8 patch, u8 source_group, u8 rename_if_empty_name);
extern s32 SYNTH_FILE_B_PatchWrite(u8 bank, u8 patch, u8 source_group, u8 rename_if_empty_name);
 
extern s32 SYNTH_FILE_B_PatchPeekName(u8 bank, u8 patch, u8 non_cached, char *patch_name);
 
/trunk/apps/examples/speech_synth/Makefile
65,6 → 65,9
# FATFS Driver
include $(MIOS32_PATH)/modules/fatfs/fatfs.mk
 
# FILE Access Layer
include $(MIOS32_PATH)/modules/file/file.mk
 
# Sources for Standard Control Surface
include $(MIOS32_PATH)/modules/scs/scs.mk
 
/trunk/apps/examples/speech_synth/scs_config.c
80,7 → 80,7
SYNTH_PatchNameSet(sourceGroup, newString);
 
MUTEX_SDCARD_TAKE;
if( (status=SYNTH_FILE_B_PatchWrite(synth_file_session_name, selectedBank, selectedPatch, sourceGroup, rename_if_empty_name)) < 0 ) {
if( (status=SYNTH_FILE_B_PatchWrite(selectedBank, selectedPatch, sourceGroup, rename_if_empty_name)) < 0 ) {
char buffer[100];
sprintf(buffer, "Patch %c%03d", 'A'+selectedBank, selectedPatch+1);
SCS_Msg(SCS_MSG_ERROR_L, 1000, "Failed to store", buffer);