mirror of
https://github.com/opentx/opentx.git
synced 2025-07-24 00:35:18 +03:00
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:
parent
434baf15c4
commit
41cd128ad5
14 changed files with 351 additions and 54 deletions
|
@ -33,8 +33,9 @@ IF ( SDL_FOUND )
|
|||
INCLUDE_DIRECTORIES( ${SDL_INCLUDE_DIR} )
|
||||
MESSAGE("SDL Include Path: " ${SDL_INCLUDE_DIR} )
|
||||
ADD_DEFINITIONS( -DJOYSTICKS )
|
||||
ADD_DEFINITIONS( -DSIMU_AUDIO )
|
||||
ELSE()
|
||||
MESSAGE( "SDL not found! Joysticks support will be disabled" )
|
||||
MESSAGE( "SDL not found! Joysticks support will be disabled. Simulator audio will not work." )
|
||||
ENDIF()
|
||||
|
||||
FIND_PACKAGE(Qt4 4.8.4 REQUIRED)
|
||||
|
|
|
@ -198,7 +198,7 @@ bool Open9xSky9xSimulator::timer10ms()
|
|||
#include "simulatorimport.h"
|
||||
}
|
||||
|
||||
uint8_t * Open9xSky9xSimulator::getLcd()
|
||||
::uint8_t * Open9xSky9xSimulator::getLcd()
|
||||
{
|
||||
#define GETLCD_IMPORT
|
||||
#include "simulatorimport.h"
|
||||
|
@ -215,6 +215,7 @@ void Open9xSky9xSimulator::start(QByteArray & eeprom, bool tests)
|
|||
g_rotenc[0] = 0;
|
||||
memcpy(Open9xSky9x::eeprom, eeprom.data(), std::min<int>(sizeof(Open9xSky9x::eeprom), eeprom.size()));
|
||||
StartEepromThread(NULL);
|
||||
StartAudioThread();
|
||||
StartMainThread(tests);
|
||||
}
|
||||
|
||||
|
@ -222,12 +223,14 @@ void Open9xSky9xSimulator::start(const char * filename, bool tests)
|
|||
{
|
||||
g_rotenc[0] = 0;
|
||||
StartEepromThread(filename);
|
||||
StartAudioThread();
|
||||
StartMainThread(tests);
|
||||
}
|
||||
|
||||
void Open9xSky9xSimulator::stop()
|
||||
{
|
||||
StopMainThread();
|
||||
StopAudioThread();
|
||||
StopEepromThread();
|
||||
}
|
||||
|
||||
|
@ -249,27 +252,27 @@ void Open9xSky9xSimulator::setValues(TxInputs &inputs)
|
|||
void Open9xSky9xSimulator::setTrim(unsigned int idx, int value)
|
||||
{
|
||||
idx = Open9xSky9x::modn12x3[4*getStickMode() + idx];
|
||||
uint8_t phase = getTrimFlightPhase(getFlightMode(), idx);
|
||||
::uint8_t phase = getTrimFlightPhase(getFlightMode(), idx);
|
||||
setTrimValue(phase, idx, value);
|
||||
}
|
||||
|
||||
void Open9xSky9xSimulator::getTrims(Trims & trims)
|
||||
{
|
||||
uint8_t phase = getFlightMode();
|
||||
::uint8_t phase = getFlightMode();
|
||||
trims.extended = hasExtendedTrims();
|
||||
for (uint8_t idx=0; idx<4; idx++) {
|
||||
for (::uint8_t idx=0; idx<4; idx++) {
|
||||
trims.values[idx] = getTrimValue(getTrimFlightPhase(phase, idx), idx);
|
||||
}
|
||||
|
||||
for (int i=0; i<2; i++) {
|
||||
uint8_t idx = Open9xSky9x::modn12x3[4*getStickMode() + i];
|
||||
int16_t tmp = trims.values[i];
|
||||
::uint8_t idx = Open9xSky9x::modn12x3[4*getStickMode() + i];
|
||||
::int16_t tmp = trims.values[i];
|
||||
trims.values[i] = trims.values[idx];
|
||||
trims.values[idx] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
void Open9xSky9xSimulator::wheelEvent(uint8_t steps)
|
||||
void Open9xSky9xSimulator::wheelEvent(::uint8_t steps)
|
||||
{
|
||||
g_rotenc[0] += steps*4;
|
||||
}
|
||||
|
@ -292,7 +295,7 @@ const char * Open9xSky9xSimulator::getError()
|
|||
#include "simulatorimport.h"
|
||||
}
|
||||
|
||||
void Open9xSky9xSimulator::setTrainerInput(unsigned int inputNumber, int16_t value)
|
||||
void Open9xSky9xSimulator::setTrainerInput(unsigned int inputNumber, ::int16_t value)
|
||||
{
|
||||
#define SETTRAINER_IMPORT
|
||||
#include "simulatorimport.h"
|
||||
|
|
|
@ -145,10 +145,9 @@ inline int geteepromsize() {
|
|||
#include "radio/src/haptic.cpp"
|
||||
#include "radio/src/sbus.cpp"
|
||||
#include "radio/src/targets/taranis/haptic_driver.cpp"
|
||||
// TODO Because FatFS in not C++ there cannot be namespaces there and the functions are defined several times!
|
||||
#undef SDCARD
|
||||
// Because FatFS in not C++ there cannot be namespaces there and the functions are defined several times!
|
||||
#define SKIP_FATFS_DECLARATION
|
||||
#include "radio/src/targets/simu/simpgmspace.cpp"
|
||||
#define SDCARD
|
||||
#include "radio/src/translations.cpp"
|
||||
#include "radio/src/gui/Taranis/fonts.cpp"
|
||||
#include "radio/src/telemetry/telemetry.cpp"
|
||||
|
@ -245,7 +244,7 @@ bool OpentxTaranisSimulator::timer10ms()
|
|||
#include "simulatorimport.h"
|
||||
}
|
||||
|
||||
uint8_t * OpentxTaranisSimulator::getLcd()
|
||||
::uint8_t * OpentxTaranisSimulator::getLcd()
|
||||
{
|
||||
#define GETLCD_IMPORT
|
||||
#include "simulatorimport.h"
|
||||
|
@ -261,18 +260,21 @@ void OpentxTaranisSimulator::start(QByteArray & eeprom, bool tests)
|
|||
{
|
||||
memcpy(Open9xX9D::eeprom, eeprom.data(), std::min<int>(sizeof(Open9xX9D::eeprom), eeprom.size()));
|
||||
StartEepromThread(NULL);
|
||||
StartAudioThread();
|
||||
StartMainThread(tests);
|
||||
}
|
||||
|
||||
void OpentxTaranisSimulator::start(const char * filename, bool tests)
|
||||
{
|
||||
StartEepromThread(filename);
|
||||
StartAudioThread();
|
||||
StartMainThread(tests);
|
||||
}
|
||||
|
||||
void OpentxTaranisSimulator::stop()
|
||||
{
|
||||
StopMainThread();
|
||||
StopAudioThread();
|
||||
StopEepromThread();
|
||||
}
|
||||
|
||||
|
@ -292,27 +294,27 @@ void OpentxTaranisSimulator::setValues(TxInputs &inputs)
|
|||
void OpentxTaranisSimulator::setTrim(unsigned int idx, int value)
|
||||
{
|
||||
idx = Open9xX9D::modn12x3[4*getStickMode() + idx];
|
||||
uint8_t phase = getTrimFlightPhase(getFlightMode(), idx);
|
||||
::uint8_t phase = getTrimFlightPhase(getFlightMode(), idx);
|
||||
setTrimValue(phase, idx, value);
|
||||
}
|
||||
|
||||
void OpentxTaranisSimulator::getTrims(Trims & trims)
|
||||
{
|
||||
uint8_t phase = getFlightMode();
|
||||
::uint8_t phase = getFlightMode();
|
||||
trims.extended = hasExtendedTrims();
|
||||
for (uint8_t idx=0; idx<4; idx++) {
|
||||
for (::uint8_t idx=0; idx<4; idx++) {
|
||||
trims.values[idx] = getTrimValue(getTrimFlightPhase(phase, idx), idx);
|
||||
}
|
||||
|
||||
for (int i=0; i<2; i++) {
|
||||
uint8_t idx = Open9xX9D::modn12x3[4*getStickMode() + i];
|
||||
int16_t tmp = trims.values[i];
|
||||
::uint8_t idx = Open9xX9D::modn12x3[4*getStickMode() + i];
|
||||
::int16_t tmp = trims.values[i];
|
||||
trims.values[i] = trims.values[idx];
|
||||
trims.values[idx] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
void OpentxTaranisSimulator::wheelEvent(uint8_t steps)
|
||||
void OpentxTaranisSimulator::wheelEvent(::uint8_t steps)
|
||||
{
|
||||
// g_rotenc[0] += steps*4;
|
||||
}
|
||||
|
@ -335,12 +337,12 @@ const char * OpentxTaranisSimulator::getError()
|
|||
#include "simulatorimport.h"
|
||||
}
|
||||
|
||||
void OpentxTaranisSimulator::sendTelemetry(uint8_t * data, unsigned int len)
|
||||
void OpentxTaranisSimulator::sendTelemetry(::uint8_t * data, unsigned int len)
|
||||
{
|
||||
processSportPacket(data);
|
||||
}
|
||||
|
||||
void OpentxTaranisSimulator::setTrainerInput(unsigned int inputNumber, int16_t value)
|
||||
void OpentxTaranisSimulator::setTrainerInput(unsigned int inputNumber, ::int16_t value)
|
||||
{
|
||||
#define SETTRAINER_IMPORT
|
||||
#include "simulatorimport.h"
|
||||
|
|
|
@ -106,6 +106,6 @@ return main_thread_error;
|
|||
#ifdef SETTRAINER_IMPORT
|
||||
#undef SETTRAINER_IMPORT
|
||||
ppmInValid = 100;
|
||||
g_ppmIns[inputNumber] = LIMIT<int16_t>(-512, value, 512);
|
||||
g_ppmIns[inputNumber] = LIMIT< ::int16_t>(-512, value, 512);
|
||||
#endif
|
||||
|
||||
|
|
|
@ -348,6 +348,10 @@ TARANIS_INTERNAL_PPM = NO
|
|||
# Values = NO, YES
|
||||
SIMU_DISKIO = NO
|
||||
|
||||
# Enable audio in simulator
|
||||
# Values = NO, YES
|
||||
SIMU_AUDIO = NO
|
||||
|
||||
#------- END BUILD OPTIONS ---------------------------
|
||||
|
||||
# Define programs and commands.
|
||||
|
@ -1567,13 +1571,20 @@ FOXLIB=-L/usr/local/lib \
|
|||
-lFOX-1.6 \
|
||||
-Wl,-rpath,$(FOXPATH)/src/.libs
|
||||
|
||||
SIMUDEFS = -DSIMU -DLUA_USE_APICHECK
|
||||
ifeq ($(SIMU_AUDIO), YES)
|
||||
AUDIOLIB = -L/usr/lib/x86_64-linux-gnu/ -lSDLmain -lSDL
|
||||
AUDIOINC = -I/usr/include/SDL
|
||||
SIMUDEFS += -DSIMU_AUDIO
|
||||
endif
|
||||
|
||||
ifeq ($(SIMU_DISKIO), YES)
|
||||
CPPDEFS += -DSIMU_DISKIO
|
||||
CPPSRC += FatFs/ff.c FatFs/option/ccsbcs.c
|
||||
SIMUDEFS += -DSIMU_DISKIO
|
||||
endif
|
||||
|
||||
simu: $(LUADEP) stamp_header allsimusrc.cpp Makefile simu.cpp targets/simu/simpgmspace.cpp *.h tra lbm eeprom.bin
|
||||
g++ $(CPPFLAGS) $(INCFLAGS) simu.cpp allsimusrc.cpp $(LUASRC) targets/simu/simpgmspace.cpp -MD -DSIMU -DLUA_USE_APICHECK -O0 -o simu $(FOXINC) $(FOXLIB) -pthread -fexceptions
|
||||
g++ $(CPPFLAGS) $(INCFLAGS) simu.cpp allsimusrc.cpp $(LUASRC) targets/simu/simpgmspace.cpp -MD $(SIMUDEFS) -O0 -o simu $(FOXINC) $(FOXLIB) $(AUDIOINC) $(AUDIOLIB) -pthread -fexceptions
|
||||
|
||||
eeprom.bin:
|
||||
dd if=/dev/zero of=$@ bs=1 count=2048
|
||||
|
|
|
@ -362,14 +362,17 @@ void referenceModelAudioFiles()
|
|||
|
||||
// Eliminates directories / non wav files
|
||||
if (len < 5 || strcasecmp(fn+len-4, SOUNDS_EXT) || (fno.fattrib & AM_DIR)) continue;
|
||||
TRACE("referenceModelAudioFiles(): using file: %s", fn);
|
||||
|
||||
// Phases Audio Files <phasename>-[on|off].wav
|
||||
for (int i=0; i<MAX_FLIGHT_MODES && !found; i++) {
|
||||
for (int event=0; event<2; event++) {
|
||||
getPhaseAudioFile(path, i, event);
|
||||
// TRACE("referenceModelAudioFiles(): searching for %s in %s", filename, fn);
|
||||
if (!strcasecmp(filename, fn)) {
|
||||
sdAvailablePhaseAudioFiles |= MASK_PHASE_AUDIO_FILE(i, event);
|
||||
found = true;
|
||||
TRACE("\tfound: %s", filename);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -378,9 +381,11 @@ void referenceModelAudioFiles()
|
|||
// Switches Audio Files <switchname>-[up|mid|down].wav
|
||||
for (int i=0; i<SWSRC_LAST_SWITCH+NUM_XPOTS*XPOTS_MULTIPOS_COUNT && !found; i++) {
|
||||
getSwitchAudioFile(path, i);
|
||||
// TRACE("referenceModelAudioFiles(): searching for %s in %s", filename, fn);
|
||||
if (!strcasecmp(filename, fn)) {
|
||||
sdAvailableSwitchAudioFiles |= MASK_SWITCH_AUDIO_FILE(i);
|
||||
found = true;
|
||||
TRACE("\tfound: %s", filename);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -388,9 +393,11 @@ void referenceModelAudioFiles()
|
|||
for (int i=0; i<NUM_LOGICAL_SWITCH && !found; i++) {
|
||||
for (int event=0; event<2; event++) {
|
||||
getLogicalSwitchAudioFile(path, i, event);
|
||||
// TRACE("referenceModelAudioFiles(): searching for %s in %s", filename, fn);
|
||||
if (!strcasecmp(filename, fn)) {
|
||||
sdAvailableLogicalSwitchAudioFiles |= MASK_LOGICAL_SWITCH_AUDIO_FILE(i, event);
|
||||
found = true;
|
||||
TRACE("\tfound: %s", filename);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -499,10 +506,14 @@ void audioTask(void* pdata)
|
|||
|
||||
void mixSample(uint16_t * result, int sample, unsigned int fade)
|
||||
{
|
||||
#if defined(SIMU_AUDIO)
|
||||
*result = limit(0, *result + ((sample >> fade) ), 0xFFFF);
|
||||
#else
|
||||
*result = limit(0, *result + ((sample >> fade) >> 4), 4095);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(SDCARD) && !defined(SIMU)
|
||||
#if defined(SDCARD)
|
||||
|
||||
#define RIFF_CHUNK_SIZE 12
|
||||
uint8_t wavBuffer[AUDIO_BUFFER_SIZE*2];
|
||||
|
@ -695,7 +706,11 @@ void AudioQueue::wakeup()
|
|||
|
||||
// write silence in the buffer
|
||||
for (uint32_t i=0; i<AUDIO_BUFFER_SIZE; i++) {
|
||||
#if defined(SIMU_AUDIO)
|
||||
buffer->data[i] = 0x8000; /* silence */
|
||||
#else
|
||||
buffer->data[i] = 0x8000 >> 4; /* silence */
|
||||
#endif
|
||||
}
|
||||
|
||||
// mix the priority context (only tones)
|
||||
|
@ -751,6 +766,7 @@ void AudioQueue::wakeup()
|
|||
// push the buffer if needed
|
||||
if (size > 0) {
|
||||
__disable_irq();
|
||||
// TRACE("pushing buffer %d\n", bufferWIdx);
|
||||
bufferWIdx = nextBufferIdx(bufferWIdx);
|
||||
buffer->size = size;
|
||||
buffer->state = dacQueue(buffer) ? AUDIO_BUFFER_PLAYING : AUDIO_BUFFER_FILLED;
|
||||
|
@ -793,6 +809,10 @@ bool AudioQueue::isPlaying(uint8_t id)
|
|||
|
||||
void AudioQueue::playTone(uint16_t freq, uint16_t len, uint16_t pause, uint8_t flags, int8_t freqIncr)
|
||||
{
|
||||
#if defined(SIMU) && !defined(SIMU_AUDIO)
|
||||
return;
|
||||
#endif
|
||||
|
||||
CoEnterMutexSection(audioMutex);
|
||||
|
||||
if (freq && freq < BEEP_MIN_FREQ) {
|
||||
|
@ -849,9 +869,13 @@ void AudioQueue::playFile(const char *filename, uint8_t flags, uint8_t id)
|
|||
TRACE("playFile(\"%s\", flags=%x, id=%d)", filename, flags, id);
|
||||
if (strlen(filename) > AUDIO_FILENAME_MAXLEN) {
|
||||
TRACE("file name too long! maximum length is %d characters", AUDIO_FILENAME_MAXLEN);
|
||||
return;
|
||||
}
|
||||
fflush(stdout);
|
||||
#else
|
||||
#if !defined(SIMU_AUDIO)
|
||||
return;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
if (!sdMounted())
|
||||
return;
|
||||
|
@ -887,7 +911,6 @@ void AudioQueue::playFile(const char *filename, uint8_t flags, uint8_t id)
|
|||
}
|
||||
|
||||
CoLeaveMutexSection(audioMutex);
|
||||
#endif
|
||||
}
|
||||
|
||||
void AudioQueue::stopPlay(uint8_t id)
|
||||
|
@ -896,6 +919,10 @@ void AudioQueue::stopPlay(uint8_t id)
|
|||
TRACE("stopPlay(id=%d)", id);
|
||||
#endif
|
||||
|
||||
#if defined(SIMU) && !defined(SIMU_AUDIO)
|
||||
return;
|
||||
#endif
|
||||
|
||||
// For the moment it's only needed to stop the background music
|
||||
if (backgroundContext.fragment.id == id) {
|
||||
backgroundContext.fragment.type = FRAGMENT_EMPTY;
|
||||
|
|
|
@ -46,7 +46,11 @@
|
|||
#define AUDIO_SAMPLE_RATE (32000)
|
||||
#define AUDIO_BUFFER_DURATION (10)
|
||||
#define AUDIO_BUFFER_SIZE (AUDIO_SAMPLE_RATE*AUDIO_BUFFER_DURATION/1000)
|
||||
#define AUDIO_BUFFER_COUNT (3)
|
||||
#if defined(SIMU_AUDIO)
|
||||
#define AUDIO_BUFFER_COUNT (10) // simulator needs more buffers for smooth audio
|
||||
#else
|
||||
#define AUDIO_BUFFER_COUNT (3)
|
||||
#endif
|
||||
|
||||
#define BEEP_MIN_FREQ (150)
|
||||
#define BEEP_DEFAULT_FREQ (2250)
|
||||
|
@ -155,6 +159,9 @@ bool dacQueue(AudioBuffer *buffer);
|
|||
class AudioQueue {
|
||||
|
||||
friend void audioTask(void* pdata);
|
||||
#if defined(SIMU_AUDIO)
|
||||
friend void *audio_thread(void *);
|
||||
#endif
|
||||
|
||||
public:
|
||||
|
||||
|
@ -196,7 +203,7 @@ class AudioQueue {
|
|||
}
|
||||
|
||||
uint8_t idx = bufferRIdx;
|
||||
while (idx != bufferWIdx) {
|
||||
do {
|
||||
AudioBuffer * buffer = &buffers[idx];
|
||||
if (buffer->state == AUDIO_BUFFER_FILLED) {
|
||||
buffer->state = AUDIO_BUFFER_PLAYING;
|
||||
|
@ -204,11 +211,23 @@ class AudioQueue {
|
|||
return buffer;
|
||||
}
|
||||
idx = nextBufferIdx(idx);
|
||||
}
|
||||
} while (idx != bufferWIdx); //this fixes a bug if all buffers are filled
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool filledAtleast(int noBuffers) {
|
||||
int count = 0;
|
||||
for(int n= 0; n<AUDIO_BUFFER_COUNT; ++n) {
|
||||
if (buffers[n].state == AUDIO_BUFFER_FILLED) {
|
||||
if (++count >= noBuffers) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
void wakeup();
|
||||
|
|
|
@ -134,6 +134,7 @@ Open9xSim::Open9xSim(FXApp* a):
|
|||
Open9xSim::~Open9xSim()
|
||||
{
|
||||
StopMainThread();
|
||||
StopAudioThread();
|
||||
StopEepromThread();
|
||||
|
||||
delete bmp;
|
||||
|
@ -430,6 +431,7 @@ int main(int argc,char **argv)
|
|||
printf("Model size = %d\n", (int)sizeof(g_model));
|
||||
|
||||
StartEepromThread(argc >= 2 ? argv[1] : "eeprom.bin");
|
||||
StartAudioThread();
|
||||
StartMainThread();
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -363,6 +363,13 @@ void StartMainThread(bool tests=true);
|
|||
void StopMainThread();
|
||||
void StartEepromThread(const char *filename="eeprom.bin");
|
||||
void StopEepromThread();
|
||||
#if defined(SIMU_AUDIO) && defined(CPUARM)
|
||||
void StartAudioThread(void);
|
||||
void StopAudioThread(void);
|
||||
#else
|
||||
#define StartAudioThread()
|
||||
#define StopAudioThread()
|
||||
#endif
|
||||
|
||||
extern const char *eepromFile;
|
||||
#if defined(PCBTARANIS) || defined(PCBACT)
|
||||
|
|
|
@ -36,6 +36,14 @@
|
|||
|
||||
#include "../../opentx.h"
|
||||
|
||||
const int8_t volumeScale[VOLUME_LEVEL_MAX+1] =
|
||||
{
|
||||
0, 2, 4, 6, 8, 10, 13, 17, 22, 27, 33, 40,
|
||||
64, 82, 96, 105, 112, 117, 120, 122, 124, 125, 126, 127
|
||||
} ;
|
||||
|
||||
#if !defined(SIMU)
|
||||
|
||||
void setSampleRate(uint32_t frequency)
|
||||
{
|
||||
register Tc *ptc ;
|
||||
|
@ -154,12 +162,6 @@ void audioEnd()
|
|||
PMC->PMC_PCER0 &= ~0x40000000L ; // Disable peripheral clock to DAC
|
||||
}
|
||||
|
||||
static const int8_t volumeScale[VOLUME_LEVEL_MAX+1] =
|
||||
{
|
||||
0, 2, 4, 6, 8, 10, 13, 17, 22, 27, 33, 40,
|
||||
64, 82, 96, 105, 112, 117, 120, 122, 124, 125, 126, 127
|
||||
} ;
|
||||
|
||||
void setVolume(uint8_t volume)
|
||||
{
|
||||
volumeRequired = volumeScale[min<uint8_t>(volume, VOLUME_LEVEL_MAX)];
|
||||
|
@ -169,4 +171,5 @@ void setVolume(uint8_t volume)
|
|||
}
|
||||
|
||||
|
||||
#endif // #if !defined(SIMU)
|
||||
|
||||
|
|
|
@ -55,6 +55,8 @@ inline void dacStop()
|
|||
|
||||
#define VOLUME_LEVEL_MAX 23
|
||||
#define VOLUME_LEVEL_DEF 12
|
||||
extern const int8_t volumeScale[];
|
||||
|
||||
void setVolume(uint8_t volume);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -36,6 +36,13 @@
|
|||
|
||||
#include "../../opentx.h"
|
||||
|
||||
const int8_t volumeScale[VOLUME_LEVEL_MAX+1] =
|
||||
{
|
||||
0, 1, 2, 3, 5, 9, 13, 17, 22, 27, 33, 40,
|
||||
64, 82, 96, 105, 112, 117, 120, 122, 124, 125, 126, 127
|
||||
};
|
||||
|
||||
#if !defined(SIMU)
|
||||
bool dacIdle = true;
|
||||
|
||||
void setSampleRate(uint32_t frequency)
|
||||
|
@ -139,7 +146,6 @@ void audioEnd()
|
|||
NVIC_DisableIRQ(DMA1_Stream5_IRQn) ;
|
||||
}
|
||||
|
||||
#if !defined(SIMU)
|
||||
extern "C" void TIM6_DAC_IRQHandler()
|
||||
{
|
||||
DAC->CR &= ~DAC_CR_DMAEN1 ; // Stop DMA requests
|
||||
|
@ -167,7 +173,7 @@ extern "C" void DMA1_Stream5_IRQHandler()
|
|||
dacIdle = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif // #if !defined(SIMU)
|
||||
|
||||
#if 0
|
||||
static void Audio_GPIO_Init()
|
||||
|
|
|
@ -46,16 +46,12 @@ extern void setSampleRate(uint32_t frequency);
|
|||
|
||||
#define VOLUME_LEVEL_MAX 23
|
||||
#define VOLUME_LEVEL_DEF 12
|
||||
static const int8_t volumeScale[VOLUME_LEVEL_MAX+1] =
|
||||
{
|
||||
0, 1, 2, 3, 5, 9, 13, 17, 22, 27, 33, 40,
|
||||
64, 82, 96, 105, 112, 117, 120, 122, 124, 125, 126, 127
|
||||
} ;
|
||||
extern const int8_t volumeScale[];
|
||||
|
||||
#if !defined(SIMU)
|
||||
#define setVolume(v) I2C_set_volume(volumeScale[min<uint8_t>(v, VOLUME_LEVEL_MAX)])
|
||||
#else
|
||||
#define setVolume(v)
|
||||
void setVolume(uint8_t volume);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue