Re #457: audio working in Companion, Simulator and simu using SDL library (use SIMU_AUDIO=YES to enable)

Re #457: case insensitive f_stat() and f_open() for SIMU
This commit is contained in:
Damjan Adamic
2015-02-22 15:49:15 +01:00
parent 434baf15c4
commit 41cd128ad5
14 changed files with 351 additions and 54 deletions
+227 -9
View File
@@ -51,6 +51,10 @@
FILE * diskImage = 0;
#endif
#if defined(SIMU_AUDIO) && defined(CPUARM)
#include <SDL.h>
#endif
volatile uint8_t pina=0xff, pinb=0xff, pinc=0xff, pind, pine=0xff, pinf=0xff, ping=0xff, pinh=0xff, pinj=0xff, pinl=0;
uint8_t portb, portc, porth=0, dummyport;
uint16_t dummyport16;
@@ -89,7 +93,7 @@ Adc Adc0;
#define EESIZE_SIMU EESIZE
#endif
#if defined(SDCARD)
#if defined(SDCARD) && !defined(SKIP_FATFS_DECLARATION)
char simuSdDirectory[1024] = "";
#endif
@@ -402,7 +406,7 @@ void StartMainThread(bool tests)
pthread_mutex_init(&audioMutex, NULL);
#endif
g_tmr10ms = 0;
g_tmr10ms = 1; // must be non-zero otherwise some SF functions (that use this timer as a marker when it was last executed) will be executed twice on startup
#if defined(RTCLOCK)
g_rtcTime = time(0);
#endif
@@ -417,7 +421,130 @@ void StopMainThread()
pthread_join(main_thread_pid, NULL);
}
#if defined(CPUARM)
int Volume = volumeScale[VOLUME_LEVEL_DEF];
bool dacQueue(AudioBuffer *buffer)
{
return false;
}
void setVolume(uint8_t volume)
{
Volume = volumeScale[min<uint8_t>(volume, VOLUME_LEVEL_MAX)];
}
#endif
#if defined(SIMU_AUDIO) && defined(CPUARM)
int leftover_len = 0;
uint16_t leftover_data[AUDIO_BUFFER_SIZE];
void copyBuffer(uint8_t * dest, uint16_t * buff, unsigned int samples)
{
for(unsigned int i=0; i<samples; i++) {
int sample = ((int32_t)(uint32_t)(buff[i]) - 0x8000); // conversion from uint16_t
*((uint16_t*)dest) = (int16_t)((sample * Volume)/127);
dest += 2;
}
}
void fill_audio(void *udata, Uint8 *stream, int len)
{
SDL_memset(stream, 0, len);
if (leftover_len) {
copyBuffer(stream, leftover_data, leftover_len);
len -= leftover_len*2;
stream += leftover_len*2;
leftover_len = 0;
// putchar('l');
}
if (audioQueue.filledAtleast(len/(AUDIO_BUFFER_SIZE*2)+1) ) {
while(true) {
AudioBuffer *nextBuffer = audioQueue.getNextFilledBuffer();
if (nextBuffer) {
if (len >= nextBuffer->size*2) {
copyBuffer(stream, nextBuffer->data, nextBuffer->size);
stream += nextBuffer->size*2;
len -= nextBuffer->size*2;
// putchar('+');
}
else {
//partial
copyBuffer(stream, nextBuffer->data, len/2);
leftover_len = (nextBuffer->size-len/2);
memcpy(leftover_data, &nextBuffer->data[len/2], leftover_len*2);
len = 0;
// putchar('p');
break;
}
}
else {
break;
}
}
}
//fill the rest of buffer with silence
if (len > 0) {
SDL_memset(stream, 0x8000, len); // make sure this is silence.
// putchar('.');
}
}
bool audio_thread_running = false;
void *audio_thread(void *)
{
SDL_AudioSpec wanted, have;
/* Set the audio format */
wanted.freq = AUDIO_SAMPLE_RATE;
wanted.format = AUDIO_S16SYS;
wanted.channels = 1; /* 1 = mono, 2 = stereo */
wanted.samples = AUDIO_BUFFER_SIZE*2; /* Good low-latency value for callback */
wanted.callback = fill_audio;
wanted.userdata = NULL;
/* Open the audio device, forcing the desired format */
if ( SDL_OpenAudio(&wanted, &have) < 0 ) {
fprintf(stderr, "Couldn't open audio: %s\n", SDL_GetError());
return 0;
}
SDL_PauseAudio(0);
while (audio_thread_running) {
audioQueue.wakeup();
sleep(1);
}
SDL_CloseAudio();
return 0;
}
pthread_t audio_thread_pid;
void StartAudioThread()
{
pthread_attr_t attr;
pthread_attr_init(&attr);
struct sched_param sp;
sp.sched_priority = SCHED_RR;
pthread_attr_setschedparam(&attr, &sp);
pthread_create(&audio_thread_pid, &attr, &audio_thread, NULL);
audio_thread_running = true;
return;
}
void StopAudioThread()
{
audio_thread_running = false;
pthread_join(audio_thread_pid, NULL);
}
#endif // #if defined(CPUARM)
pthread_t eeprom_thread_pid;
void StartEepromThread(const char *filename)
{
eepromFile = filename;
@@ -510,16 +637,23 @@ static void EeFsDump(){
}
#endif
#if defined(SDCARD) && !defined(SIMU_DISKIO)
#if defined(SDCARD) && !defined(SKIP_FATFS_DECLARATION) && !defined(SIMU_DISKIO)
namespace simu {
#include <dirent.h>
#if !defined WIN32
#include <libgen.h>
#endif
}
#include "FatFs/ff.h"
#if defined WIN32 || !defined __GNUC__
#include <direct.h>
#include <stdlib.h>
#endif
#include <map>
#include <string>
#if defined(CPUARM)
FATFS g_FATFS_Obj;
#endif
@@ -535,11 +669,89 @@ char *convertSimuPath(const char *path)
return result;
}
typedef std::map<std::string, std::string> filemap_t;
filemap_t fileMap;
char *findTrueFileName(const char *path)
{
TRACE("findTrueFileName(%s)", path);
static char result[1024];
filemap_t::iterator i = fileMap.find(path);
if (i != fileMap.end()) {
strcpy(result, i->second.c_str());
TRACE("\tfound in map: %s", result);
return result;
}
else {
//find file
//add to map
#if defined WIN32 || !defined __GNUC__
char drive[_MAX_DRIVE];
char dir[_MAX_DIR];
char fname[_MAX_FNAME];
char ext[_MAX_EXT];
_splitpath(path, drive, dir, fname, ext);
std::string fileName = std::string(fname) + "." + std::string(ext);
std::string dirName = std::string(drive) + std::string(dir);
if (dir) {
// TRACE("\tsearching for: %s", fileName.c_str());
WIN32_FIND_DATA ffd;
HANDLE hFind = FindFirstFile(dirName.c_str(), &ffd);
if (INVALID_HANDLE_VALUE != hFind) {
do {
if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY == 0) {
// TRACE("comparing with: %s", ffd.cFileName);
if (!strcasecmp(fileName.c_str(), ffd.cFileName)) {
strcpy(result, dirName.c_str());
strcat(result, "/");
strcat(result, ffd.cFileName);
TRACE("\tfound: %s", ffd.cFileName);
fileMap.insert(filemap_t:: value_type(path, result));
return result;
}
}
}
while (FindNextFile(hFind, &ffd) != 0);
}
}
#else
strcpy(result, path);
std::string fileName = simu::basename(result);
strcpy(result, path);
std::string dirName = simu::dirname(result);
simu::DIR * dir = simu::opendir(dirName.c_str());
if (dir) {
// TRACE("\tsearching for: %s", fileName.c_str());
for (;;) {
struct simu::dirent * res = simu::readdir(dir);
if (res == 0) break;
if ((res->d_type == simu::DT_REG) || (res->d_type == simu::DT_LNK)) {
// TRACE("comparing with: %s", res->d_name);
if (!strcasecmp(fileName.c_str(), res->d_name)) {
strcpy(result, dirName.c_str());
strcat(result, "/");
strcat(result, res->d_name);
TRACE("\tfound: %s", res->d_name);
fileMap.insert(filemap_t:: value_type(path, result));
return result;
}
}
}
}
#endif
}
TRACE("\tnot found");
strcpy(result, path);
return result;
}
FRESULT f_stat (const TCHAR * name, FILINFO *)
{
char *path = convertSimuPath(name);
char * realPath = findTrueFileName(path);
struct stat tmp;
if (stat(path, &tmp)) {
if (stat(realPath, &tmp)) {
TRACE("f_stat(%s) = error %d (%s)", path, errno, strerror(errno));
return FR_INVALID_NAME;
}
@@ -557,17 +769,19 @@ FRESULT f_mount (FATFS* ,const TCHAR*, BYTE opt)
FRESULT f_open (FIL * fil, const TCHAR *name, BYTE flag)
{
char *path = convertSimuPath(name);
char * realPath = findTrueFileName(path);
if (!(flag & FA_WRITE)) {
struct stat tmp;
if (stat(path, &tmp)) {
if (stat(realPath, &tmp)) {
TRACE("f_open(%s) = INVALID_NAME", path);
return FR_INVALID_NAME;
}
fil->fsize = tmp.st_size;
}
fil->fs = (FATFS*)fopen(path, (flag & FA_WRITE) ? "wb+" : "rb+");
if ( fil->fs ) {
TRACE("f_open(%s) = OK", path);
fil->fs = (FATFS*)fopen(realPath, (flag & FA_WRITE) ? "wb+" : "rb+");
fil->fptr = 0;
if (fil->fs) {
TRACE("f_open(%s) = %p", path, (FILE*)fil->fs);
return FR_OK;
}
TRACE("f_open(%s) = error %d (%s)", path, errno, strerror(errno));
@@ -578,6 +792,7 @@ FRESULT f_read (FIL* fil, void* data, UINT size, UINT* read)
{
if (fil && fil->fs) {
*read = fread(data, 1, size, (FILE*)fil->fs);
fil->fptr += *read;
// TRACE("fread(%p) %u, %u", fil->fs, size, *read);
}
return FR_OK;
@@ -587,6 +802,7 @@ FRESULT f_write (FIL* fil, const void* data, UINT size, UINT* written)
{
if (fil && fil->fs) {
*written = fwrite(data, 1, size, (FILE*)fil->fs);
fil->fptr += size;
// TRACE("fwrite(%p) %u, %u", fil->fs, size, *written);
}
return FR_OK;
@@ -595,12 +811,14 @@ FRESULT f_write (FIL* fil, const void* data, UINT size, UINT* written)
FRESULT f_lseek (FIL* fil, DWORD offset)
{
if (fil && fil->fs) fseek((FILE*)fil->fs, offset, SEEK_SET);
fil->fptr = offset;
return FR_OK;
}
FRESULT f_close (FIL * fil)
{
if (fil && fil->fs) {
TRACE("f_close(%p)", (FILE*)fil->fs);
fclose((FILE*)fil->fs);
fil->fs = NULL;
}
@@ -724,7 +942,7 @@ int32_t Card_state = SD_ST_MOUNTED;
uint32_t Card_CSD[4]; // TODO elsewhere
#endif
#endif // #if defined(SDCARD) && !defined(SIMU_DISKIO)
#endif // #if defined(SDCARD) && !defined(SKIP_FATFS_DECLARATION) && !defined(SIMU_DISKIO)
#if defined(SIMU_DISKIO)