chore: audio drivers cleanup
This commit is contained in:
committed by
Raphael Coeffic
parent
11f79746f5
commit
6d6c449c12
+5
-8
@@ -30,6 +30,7 @@
|
||||
#endif
|
||||
|
||||
#include "model_audio.h"
|
||||
#include "hal/audio_driver.h"
|
||||
|
||||
extern RTOS_MUTEX_HANDLE audioMutex;
|
||||
|
||||
@@ -366,8 +367,6 @@ void audioTask(void * pdata)
|
||||
RTOS_WAIT_TICKS(1);
|
||||
}
|
||||
|
||||
setSampleRate(AUDIO_SAMPLE_RATE);
|
||||
|
||||
#if defined(PCBX12S) || defined(RADIO_TX16S) || defined(RADIO_F16) || defined(RADIO_V16)
|
||||
// The audio amp needs ~2s to start
|
||||
RTOS_WAIT_MS(1000); // 1s
|
||||
@@ -378,14 +377,14 @@ void audioTask(void * pdata)
|
||||
DEBUG_TIMER_START(debugTimerAudioDuration);
|
||||
audioQueue.wakeup();
|
||||
DEBUG_TIMER_STOP(debugTimerAudioDuration);
|
||||
RTOS_WAIT_MS(4);
|
||||
RTOS_WAIT_MS(4); // ???
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
inline void mixSample(audio_data_t * result, int sample, unsigned int fade)
|
||||
{
|
||||
*result = limit(AUDIO_DATA_MIN, *result + ((sample >> fade) >> (16-AUDIO_BITS_PER_SAMPLE)), AUDIO_DATA_MAX);
|
||||
*result += (sample >> fade);
|
||||
}
|
||||
|
||||
#define RIFF_CHUNK_SIZE 12
|
||||
@@ -646,15 +645,13 @@ void AudioQueue::wakeup()
|
||||
buffer->data[i] = (int16_t) (((tmpSample * currentSpeakerVolume) / VOLUME_LEVEL_MAX) + AUDIO_DATA_SILENCE);
|
||||
}
|
||||
buffersFifo.audioPushBuffer();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
#else
|
||||
buffersFifo.audioPushBuffer();
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// break the endless loop
|
||||
break;
|
||||
}
|
||||
|
||||
+34
-119
@@ -23,10 +23,13 @@
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ff.h"
|
||||
#include "edgetx_types.h"
|
||||
#include "dataconstants.h"
|
||||
|
||||
#include "hal/audio_driver.h"
|
||||
|
||||
/*
|
||||
Implements a bit field, number of bits is set by the template,
|
||||
each bit can be modified and read by the provided methods.
|
||||
@@ -74,10 +77,17 @@ constexpr uint8_t AUDIO_FILENAME_MAXLEN = (AUDIO_LUA_FILENAME_MAXLEN > AUDIO_MOD
|
||||
|
||||
#define AUDIO_QUEUE_LENGTH (16) // must be a power of 2!
|
||||
|
||||
#define AUDIO_SAMPLE_RATE (32000)
|
||||
#define AUDIO_BUFFER_DURATION (10)
|
||||
#define AUDIO_BUFFER_SIZE (AUDIO_SAMPLE_RATE*AUDIO_BUFFER_DURATION/1000)
|
||||
|
||||
#if !defined(AUDIO_SAMPLE_FMT)
|
||||
#if defined(SIMU) || defined(AUDIO_SPI)
|
||||
#define AUDIO_SAMPLE_FMT AUDIO_SAMPLE_FMT_S16
|
||||
#else
|
||||
#define AUDIO_SAMPLE_FMT AUDIO_SAMPLE_FMT_U12
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(SIMU) && defined(SIMU_AUDIO)
|
||||
#define AUDIO_BUFFER_COUNT (10) // simulator needs more buffers for smooth audio
|
||||
#elif defined(PCBX12S)
|
||||
@@ -94,41 +104,19 @@ constexpr uint8_t AUDIO_FILENAME_MAXLEN = (AUDIO_LUA_FILENAME_MAXLEN > AUDIO_MOD
|
||||
|
||||
#define USE_SETTINGS_VOLUME (127)
|
||||
|
||||
#if defined(AUDIO_DUAL_BUFFER)
|
||||
enum AudioBufferState
|
||||
{
|
||||
AUDIO_BUFFER_FREE,
|
||||
AUDIO_BUFFER_FILLED,
|
||||
AUDIO_BUFFER_PLAYING
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(SIMU)
|
||||
typedef uint16_t audio_data_t;
|
||||
#define AUDIO_DATA_SILENCE 0x8000
|
||||
#define AUDIO_DATA_MIN 0
|
||||
#define AUDIO_DATA_MAX 0xffff
|
||||
#define AUDIO_BITS_PER_SAMPLE 16
|
||||
#elif defined(PCBX12S) || defined(PCBNV14)
|
||||
#if AUDIO_SAMPLE_FMT == AUDIO_SAMPLE_FMT_S16
|
||||
typedef int16_t audio_data_t;
|
||||
#define AUDIO_DATA_SILENCE 0
|
||||
#define AUDIO_DATA_MIN INT16_MIN
|
||||
#define AUDIO_DATA_MAX INT16_MAX
|
||||
#define AUDIO_BITS_PER_SAMPLE 16
|
||||
#else
|
||||
#define AUDIO_DATA_SILENCE 0
|
||||
#elif AUDIO_SAMPLE_FMT == AUDIO_SAMPLE_FMT_U12
|
||||
typedef uint16_t audio_data_t;
|
||||
#define AUDIO_DATA_SILENCE (0x8000 >> 4)
|
||||
#define AUDIO_DATA_MIN 0
|
||||
#define AUDIO_DATA_MAX 0x0fff
|
||||
#define AUDIO_BITS_PER_SAMPLE 12
|
||||
#define AUDIO_DATA_SILENCE 0x8000
|
||||
#else
|
||||
#error "Unknown audio sample format"
|
||||
#endif
|
||||
|
||||
struct AudioBuffer {
|
||||
audio_data_t data[AUDIO_BUFFER_SIZE];
|
||||
uint16_t size;
|
||||
#if defined(AUDIO_DUAL_BUFFER)
|
||||
uint8_t state;
|
||||
#endif
|
||||
};
|
||||
|
||||
extern AudioBuffer audioBuffers[AUDIO_BUFFER_COUNT];
|
||||
@@ -314,115 +302,42 @@ class AudioBufferFifo {
|
||||
private:
|
||||
volatile uint8_t readIdx;
|
||||
volatile uint8_t writeIdx;
|
||||
volatile bool bufferFull;
|
||||
|
||||
// readIdx == writeIdx -> buffer empty
|
||||
// readIdx == writeIdx + 1 -> buffer full
|
||||
|
||||
inline uint8_t nextBufferIdx(uint8_t idx) const
|
||||
{
|
||||
return (idx >= AUDIO_BUFFER_COUNT-1 ? 0 : idx+1);
|
||||
return (idx >= AUDIO_BUFFER_COUNT - 1 ? 0 : idx + 1);
|
||||
}
|
||||
|
||||
bool full() const
|
||||
{
|
||||
return bufferFull;
|
||||
}
|
||||
bool full() const { return readIdx == nextBufferIdx(writeIdx); }
|
||||
bool empty() const { return readIdx == writeIdx; }
|
||||
uint8_t used() const { return (writeIdx - readIdx) % AUDIO_BUFFER_COUNT; }
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return (readIdx == writeIdx) && !bufferFull;
|
||||
}
|
||||
|
||||
uint8_t used() const
|
||||
{
|
||||
return bufferFull ? AUDIO_BUFFER_COUNT : writeIdx - readIdx;
|
||||
}
|
||||
|
||||
public:
|
||||
AudioBufferFifo() : readIdx(0), writeIdx(0), bufferFull(false)
|
||||
public:
|
||||
AudioBufferFifo() : readIdx(0), writeIdx(0)
|
||||
{
|
||||
memset(audioBuffers, 0, sizeof(audioBuffers));
|
||||
}
|
||||
|
||||
// returns an empty buffer to be filled wit data and put back into FIFO with audioPushBuffer()
|
||||
AudioBuffer * getEmptyBuffer() const
|
||||
// returns an empty buffer to be filled with data and put back into FIFO
|
||||
// with audioPushBuffer()
|
||||
AudioBuffer *getEmptyBuffer() const
|
||||
{
|
||||
#if defined(AUDIO_DUAL_BUFFER)
|
||||
AudioBuffer * buffer = &audioBuffers[writeIdx];
|
||||
return buffer->state == AUDIO_BUFFER_FREE ? buffer : NULL;
|
||||
#else
|
||||
return full() ? NULL : &audioBuffers[writeIdx];
|
||||
#endif
|
||||
return full() ? nullptr : &audioBuffers[writeIdx];
|
||||
}
|
||||
|
||||
// puts filled buffer into FIFO
|
||||
void audioPushBuffer()
|
||||
{
|
||||
audioDisableIrq();
|
||||
#if defined(AUDIO_DUAL_BUFFER)
|
||||
AudioBuffer * buffer = &audioBuffers[writeIdx];
|
||||
buffer->state = AUDIO_BUFFER_FILLED;
|
||||
#endif
|
||||
writeIdx = nextBufferIdx(writeIdx);
|
||||
bufferFull = (writeIdx == readIdx);
|
||||
audioEnableIrq();
|
||||
}
|
||||
|
||||
// returns a pointer to the audio buffer to be played
|
||||
const AudioBuffer * getNextFilledBuffer()
|
||||
{
|
||||
#if defined(AUDIO_DUAL_BUFFER)
|
||||
uint8_t idx = readIdx;
|
||||
do {
|
||||
AudioBuffer * buffer = &audioBuffers[idx];
|
||||
if (buffer->state == AUDIO_BUFFER_FILLED) {
|
||||
buffer->state = AUDIO_BUFFER_PLAYING;
|
||||
readIdx = idx;
|
||||
return buffer;
|
||||
}
|
||||
idx = nextBufferIdx(idx);
|
||||
} while (idx != writeIdx); // this fixes a bug if all buffers are filled
|
||||
return NULL;
|
||||
#else
|
||||
return empty() ? NULL : &audioBuffers[readIdx];
|
||||
#endif
|
||||
}
|
||||
void audioPushBuffer() { writeIdx = nextBufferIdx(writeIdx); }
|
||||
|
||||
// frees the last played buffer
|
||||
void freeNextFilledBuffer()
|
||||
void freeNextFilledBuffer() { readIdx = nextBufferIdx(readIdx); }
|
||||
|
||||
// returns a pointer to the audio buffer to be played
|
||||
const AudioBuffer *getNextFilledBuffer()
|
||||
{
|
||||
audioDisableIrq();
|
||||
#if defined(AUDIO_DUAL_BUFFER)
|
||||
if (audioBuffers[readIdx].state == AUDIO_BUFFER_PLAYING) {
|
||||
audioBuffers[readIdx].state = AUDIO_BUFFER_FREE;
|
||||
readIdx = nextBufferIdx(readIdx);
|
||||
bufferFull = false;
|
||||
}
|
||||
#else
|
||||
readIdx = nextBufferIdx(readIdx);
|
||||
bufferFull = false;
|
||||
#endif
|
||||
audioEnableIrq();
|
||||
}
|
||||
|
||||
bool filledAtleast(int noBuffers) const
|
||||
{
|
||||
#if defined(AUDIO_DUAL_BUFFER)
|
||||
int count = 0;
|
||||
for(int n= 0; n<AUDIO_BUFFER_COUNT; ++n) {
|
||||
if (audioBuffers[n].state == AUDIO_BUFFER_FILLED) {
|
||||
if (++count >= noBuffers) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
#else
|
||||
return used() >= noBuffers;
|
||||
#endif
|
||||
return empty() ? nullptr : &audioBuffers[readIdx];
|
||||
}
|
||||
|
||||
bool filledAtleast(int noBuffers) const { return used() >= noBuffers; }
|
||||
};
|
||||
|
||||
class AudioFragmentFifo
|
||||
|
||||
+9
-8
@@ -22,21 +22,22 @@
|
||||
#include <FreeRTOS/include/FreeRTOS.h>
|
||||
#include <FreeRTOS/include/stream_buffer.h>
|
||||
|
||||
#include "hal/adc_driver.h"
|
||||
#include "hal/audio_driver.h"
|
||||
#include "hal/fatfs_diskio.h"
|
||||
#include "hal/module_port.h"
|
||||
#include "hal/serial_driver.h"
|
||||
#include "hal/storage.h"
|
||||
#include "hal/usb_driver.h"
|
||||
#include "hal/watchdog_driver.h"
|
||||
|
||||
#include "edgetx.h"
|
||||
#include "timers_driver.h"
|
||||
#include "hal/watchdog_driver.h"
|
||||
|
||||
#if defined(BLUETOOTH)
|
||||
#include "bluetooth_driver.h"
|
||||
#endif
|
||||
|
||||
#include "hal/adc_driver.h"
|
||||
#include "hal/module_port.h"
|
||||
#include "hal/fatfs_diskio.h"
|
||||
#include "hal/storage.h"
|
||||
#include "hal/usb_driver.h"
|
||||
|
||||
#include "tasks.h"
|
||||
#include "tasks/mixer_task.h"
|
||||
|
||||
@@ -975,7 +976,7 @@ int cliSet(const char **argv)
|
||||
else if (!strcmp(argv[1], "volume")) {
|
||||
int level = 0;
|
||||
if (toInt(argv, 2, &level) > 0) {
|
||||
setVolume(level);
|
||||
audioSetVolume(level);
|
||||
} else {
|
||||
cliSerialPrint("%s: Invalid argument \"%s\" \"%s\"", argv[0], argv[1],
|
||||
argv[2]);
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "hal/watchdog_driver.h"
|
||||
#include "hal/abnormal_reboot.h"
|
||||
#include "hal/usb_driver.h"
|
||||
#include "hal/audio_driver.h"
|
||||
|
||||
#include "timers_driver.h"
|
||||
|
||||
@@ -1461,7 +1462,7 @@ void edgeTxInit()
|
||||
currentSpeakerVolume = requiredSpeakerVolume =
|
||||
g_eeGeneral.speakerVolume + VOLUME_LEVEL_DEF;
|
||||
#if !defined(SOFTWARE_VOLUME)
|
||||
setScaledVolume(currentSpeakerVolume);
|
||||
audioSetVolume(currentSpeakerVolume);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
@@ -21,6 +21,9 @@
|
||||
|
||||
#include "edgetx.h"
|
||||
#include "switches.h"
|
||||
|
||||
#include "hal/audio_driver.h"
|
||||
|
||||
#include "boards/generic_stm32/rgb_leds.h"
|
||||
|
||||
#if defined(COLORLCD)
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "tasks/mixer_task.h"
|
||||
#include "hal/adc_driver.h"
|
||||
#include "hal/usb_driver.h"
|
||||
#include "hal/audio_driver.h"
|
||||
#include "input_mapping.h"
|
||||
|
||||
const unsigned char sticks[] = {
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include "hal/adc_driver.h"
|
||||
#include "hal/usb_driver.h"
|
||||
#include "hal/audio_driver.h"
|
||||
|
||||
#define LANGUAGE_PACKS_DEFINITION
|
||||
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
|
||||
#include "hal/adc_driver.h"
|
||||
#include "hal/usb_driver.h"
|
||||
#include "hal/audio_driver.h"
|
||||
|
||||
#include "input_mapping.h"
|
||||
#include "libopenui.h"
|
||||
#include "edgetx.h"
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (C) EdgeTX
|
||||
*
|
||||
* Based on code named
|
||||
* opentx - https://github.com/opentx/opentx
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// Audio volume is defined between 0 and VOLUME_LEVEL_MAX.
|
||||
#define VOLUME_LEVEL_MAX 23
|
||||
#define VOLUME_LEVEL_DEF 12
|
||||
|
||||
#define AUDIO_SAMPLE_RATE 32000
|
||||
|
||||
#define AUDIO_SAMPLE_FMT_S16 0
|
||||
#define AUDIO_SAMPLE_FMT_U12 1
|
||||
|
||||
|
||||
void audioSetVolume(uint8_t volume);
|
||||
|
||||
+3
-1
@@ -23,6 +23,8 @@
|
||||
#include "hal/storage.h"
|
||||
#include "hal/abnormal_reboot.h"
|
||||
#include "hal/usb_driver.h"
|
||||
#include "hal/audio_driver.h"
|
||||
|
||||
#include "edgetx.h"
|
||||
#include "lua/lua_states.h"
|
||||
|
||||
@@ -251,7 +253,7 @@ void checkSpeakerVolume()
|
||||
if (currentSpeakerVolume != requiredSpeakerVolume) {
|
||||
currentSpeakerVolume = requiredSpeakerVolume;
|
||||
#if !defined(SOFTWARE_VOLUME)
|
||||
setScaledVolume(currentSpeakerVolume);
|
||||
audioSetVolume(currentSpeakerVolume);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "hal/adc_driver.h"
|
||||
#include "hal/trainer_driver.h"
|
||||
#include "hal/switch_driver.h"
|
||||
#include "hal/audio_driver.h"
|
||||
|
||||
#define DELAY_POS_MARGIN 3
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
|
||||
#include "hal/switch_driver.h"
|
||||
#include "hal/adc_driver.h"
|
||||
#include "hal/audio_driver.h"
|
||||
|
||||
//
|
||||
// WARNING:
|
||||
|
||||
@@ -20,37 +20,48 @@
|
||||
*/
|
||||
|
||||
#include "hal/gpio.h"
|
||||
#include "hal/audio_driver.h"
|
||||
|
||||
#include "stm32_gpio.h"
|
||||
#include "stm32_timer.h"
|
||||
#include "stm32_dma.h"
|
||||
|
||||
#include "edgetx.h"
|
||||
|
||||
#if !defined(SIMU)
|
||||
const AudioBuffer * nextBuffer = nullptr;
|
||||
|
||||
void setSampleRate(uint32_t frequency)
|
||||
{
|
||||
uint32_t timer = (PERI1_FREQUENCY * TIMER_MULT_APB1) / frequency - 1 ; // MCK/8 and 100 000 Hz
|
||||
AUDIO_TIMER->CR1 &= ~TIM_CR1_CEN ;
|
||||
AUDIO_TIMER->CNT = 0 ;
|
||||
AUDIO_TIMER->ARR = limit<uint32_t>(2, timer, 65535) ;
|
||||
AUDIO_TIMER->CR1 |= TIM_CR1_CEN ;
|
||||
}
|
||||
|
||||
// Start TIMER6 at 100000Hz, used for DAC trigger
|
||||
void dacTimerInit()
|
||||
// Init timer that triggers the DAC conversion
|
||||
// at sampling frequency
|
||||
static void dac_trigger_init()
|
||||
{
|
||||
stm32_timer_enable_clock(AUDIO_TIMER);
|
||||
AUDIO_TIMER->PSC = 0 ; // Max speed
|
||||
AUDIO_TIMER->ARR = (PERI1_FREQUENCY * TIMER_MULT_APB1) / 100000 - 1 ; // 10 uS, 100 kHz
|
||||
AUDIO_TIMER->CR2 = 0 ;
|
||||
AUDIO_TIMER->CR2 = 0x20 ;
|
||||
AUDIO_TIMER->CR1 = TIM_CR1_CEN ;
|
||||
|
||||
// set timer to: 10 uS, 100 kHz
|
||||
AUDIO_TIMER->PSC = 0;
|
||||
AUDIO_TIMER->ARR = (PERI1_FREQUENCY * TIMER_MULT_APB1) / 100000 - 1;
|
||||
|
||||
// reset counter
|
||||
AUDIO_TIMER->CNT = 0;
|
||||
|
||||
// set expiry to sample period (1 / sample_rate)
|
||||
AUDIO_TIMER->ARR =
|
||||
(PERI1_FREQUENCY * TIMER_MULT_APB1) / AUDIO_SAMPLE_RATE - 1;
|
||||
|
||||
// Master mode selection
|
||||
//
|
||||
// 000: Reset
|
||||
AUDIO_TIMER->CR2 = 0;
|
||||
// 010: The update event is selected as trigger output (TRGO)
|
||||
// (used to trigger DAC conversion)
|
||||
AUDIO_TIMER->CR2 = TIM_CR2_MMS_1;
|
||||
|
||||
// enable timer
|
||||
AUDIO_TIMER->CR1 |= TIM_CR1_CEN;
|
||||
}
|
||||
|
||||
#if defined(AUDIO_MUTE_GPIO)
|
||||
static inline void setMutePin(bool enabled)
|
||||
static inline void set_mute_pin(bool enabled)
|
||||
{
|
||||
#if defined(INVERTED_MUTE_PIN)
|
||||
enabled = !enabled;
|
||||
@@ -58,7 +69,7 @@ static inline void setMutePin(bool enabled)
|
||||
gpio_write(AUDIO_MUTE_GPIO, enabled);
|
||||
}
|
||||
|
||||
static inline bool getMutePin(void)
|
||||
static inline bool get_mute_pin(void)
|
||||
{
|
||||
bool enabled = gpio_read(AUDIO_MUTE_GPIO) ? 1 : 0;
|
||||
#if defined(INVERTED_MUTE_PIN)
|
||||
@@ -76,30 +87,45 @@ void dacInit()
|
||||
#if defined(AUDIO_MUTE_GPIO)
|
||||
// Mute before init anything
|
||||
gpio_init(AUDIO_MUTE_GPIO, GPIO_OUT, GPIO_PIN_SPEED_LOW);
|
||||
setMutePin(true);
|
||||
set_mute_pin(true);
|
||||
#endif
|
||||
|
||||
dacTimerInit();
|
||||
dac_trigger_init();
|
||||
|
||||
gpio_init_analog(AUDIO_OUTPUT_GPIO);
|
||||
stm32_dma_enable_clock(AUDIO_DMA);
|
||||
|
||||
// Disable DMA stream
|
||||
AUDIO_DMA_Stream->CR &= ~DMA_SxCR_EN;
|
||||
|
||||
// clear DMA stream flags
|
||||
AUDIO_DMA->HIFCR = DMA_HIFCR_CTCIF5 | DMA_HIFCR_CHTIF5 | DMA_HIFCR_CTEIF5 |
|
||||
DMA_HIFCR_CDMEIF5 | DMA_HIFCR_CFEIF5;
|
||||
|
||||
// Chan 7, 16-bit wide, Medium priority, memory increments
|
||||
AUDIO_DMA_Stream->CR &= ~DMA_SxCR_EN ; // Disable DMA
|
||||
AUDIO_DMA->HIFCR = DMA_HIFCR_CTCIF5 | DMA_HIFCR_CHTIF5 | DMA_HIFCR_CTEIF5 | DMA_HIFCR_CDMEIF5 | DMA_HIFCR_CFEIF5 ; // Write ones to clear bits
|
||||
AUDIO_DMA_Stream->CR = DMA_SxCR_CHSEL_0 | DMA_SxCR_CHSEL_1 | DMA_SxCR_CHSEL_2 | DMA_SxCR_PL_0 |
|
||||
DMA_SxCR_MSIZE_0 | DMA_SxCR_PSIZE_0 | DMA_SxCR_MINC | DMA_SxCR_DIR_0 | DMA_SxCR_CIRC ;
|
||||
AUDIO_DMA_Stream->PAR = CONVERT_PTR_UINT(&DAC->DHR12R1);
|
||||
// AUDIO_DMA_Stream->M0AR = CONVERT_PTR_UINT(Sine_values);
|
||||
AUDIO_DMA_Stream->FCR = 0x05 ; //DMA_SxFCR_DMDIS | DMA_SxFCR_FTH_0 ;
|
||||
// AUDIO_DMA_Stream->NDTR = 100 ;
|
||||
AUDIO_DMA_Stream->CR = DMA_SxCR_CHSEL_0 | DMA_SxCR_CHSEL_1 |
|
||||
DMA_SxCR_CHSEL_2 | DMA_SxCR_PL_0 | DMA_SxCR_MSIZE_0 |
|
||||
DMA_SxCR_PSIZE_0 | DMA_SxCR_MINC | DMA_SxCR_DIR_0 |
|
||||
DMA_SxCR_CIRC;
|
||||
|
||||
// write to DAC channel 1 (12 bits, left-aligned)
|
||||
AUDIO_DMA_Stream->PAR = CONVERT_PTR_UINT(&DAC->DHR12L1);
|
||||
|
||||
// disable direct mode and set FIFO threshold to half
|
||||
AUDIO_DMA_Stream->FCR = DMA_SxFCR_DMDIS | DMA_SxFCR_FTH_0;
|
||||
|
||||
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_DAC1);
|
||||
DAC->DHR12R1 = 2010 ;
|
||||
DAC->SR = DAC_SR_DMAUDR1 ; // Write 1 to clear flag
|
||||
DAC->CR = DAC_CR_TEN1 | DAC_CR_EN1 ; // Enable DAC
|
||||
NVIC_EnableIRQ(AUDIO_TIM_IRQn); // TODO needed?
|
||||
NVIC_SetPriority(AUDIO_TIM_IRQn, 7);
|
||||
|
||||
// set data registre to silence
|
||||
DAC->DHR12L1 = AUDIO_DATA_SILENCE;
|
||||
|
||||
// clear underrun flag
|
||||
DAC->SR = DAC_SR_DMAUDR1;
|
||||
|
||||
// use TIM6 TRGO as trigger (TSEL1 = TSEL2 = 000)
|
||||
// enable DAC & channel 1 trigger
|
||||
DAC->CR = DAC_CR_TEN1 | DAC_CR_EN1;
|
||||
|
||||
NVIC_EnableIRQ(AUDIO_DMA_Stream_IRQn);
|
||||
NVIC_SetPriority(AUDIO_DMA_Stream_IRQn, 7);
|
||||
}
|
||||
@@ -116,32 +142,32 @@ void audioMute()
|
||||
}
|
||||
else if (now - audioQueue.lastAudioPlayTime > AUDIO_MUTE_DELAY / 10) {
|
||||
// delay expired, we may mute
|
||||
setMutePin(true);
|
||||
set_mute_pin(true);
|
||||
}
|
||||
#else
|
||||
// mute
|
||||
setMutePin(true);
|
||||
set_mute_pin(true);
|
||||
#endif
|
||||
}
|
||||
|
||||
void audioUnmute()
|
||||
{
|
||||
if(isFunctionActive(FUNCTION_DISABLE_AUDIO_AMP)) {
|
||||
setMutePin(true);
|
||||
return;
|
||||
}
|
||||
if (isFunctionActive(FUNCTION_DISABLE_AUDIO_AMP)) {
|
||||
set_mute_pin(true);
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(AUDIO_UNMUTE_DELAY)
|
||||
// if muted
|
||||
if (getMutePin()) {
|
||||
if (get_mute_pin()) {
|
||||
// ..un-mute
|
||||
setMutePin(false);
|
||||
set_mute_pin(false);
|
||||
RTOS_WAIT_MS(AUDIO_UNMUTE_DELAY);
|
||||
}
|
||||
// reset the mute delay
|
||||
audioQueue.lastAudioPlayTime = 0;
|
||||
#else
|
||||
setMutePin(false);
|
||||
set_mute_pin(false);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
@@ -151,39 +177,40 @@ void audioConsumeCurrentBuffer()
|
||||
if (!nextBuffer) {
|
||||
nextBuffer = audioQueue.buffersFifo.getNextFilledBuffer();
|
||||
if (nextBuffer) {
|
||||
|
||||
#if defined(AUDIO_MUTE_GPIO)
|
||||
audioUnmute();
|
||||
#endif
|
||||
AUDIO_DMA_Stream->CR &= ~DMA_SxCR_EN; // Disable DMA channel
|
||||
AUDIO_DMA->HIFCR = DMA_HIFCR_CTCIF5 | DMA_HIFCR_CHTIF5 | DMA_HIFCR_CTEIF5 | DMA_HIFCR_CDMEIF5 | DMA_HIFCR_CFEIF5; // Write ones to clear bits
|
||||
|
||||
// Disable DMA stream
|
||||
AUDIO_DMA_Stream->CR &= ~DMA_SxCR_EN;
|
||||
|
||||
// reset DMA flags
|
||||
AUDIO_DMA->HIFCR = DMA_HIFCR_CTCIF5 | DMA_HIFCR_CHTIF5 |
|
||||
DMA_HIFCR_CTEIF5 | DMA_HIFCR_CDMEIF5 |
|
||||
DMA_HIFCR_CFEIF5;
|
||||
|
||||
// set DMA buffer
|
||||
AUDIO_DMA_Stream->M0AR = CONVERT_PTR_UINT(nextBuffer->data);
|
||||
AUDIO_DMA_Stream->NDTR = nextBuffer->size;
|
||||
AUDIO_DMA_Stream->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA channel and interrupt
|
||||
DAC->SR = DAC_SR_DMAUDR1; // Write 1 to clear flag
|
||||
DAC->CR |= DAC_CR_EN1 | DAC_CR_DMAEN1; // Enable DAC
|
||||
}
|
||||
|
||||
// enable DMA stream and transfer complete interrupt
|
||||
AUDIO_DMA_Stream->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE;
|
||||
|
||||
// clear underrun flag
|
||||
DAC->SR = DAC_SR_DMAUDR1;
|
||||
|
||||
// enable DAC
|
||||
DAC->CR |= DAC_CR_EN1 | DAC_CR_DMAEN1;
|
||||
|
||||
} else {
|
||||
#if defined(AUDIO_MUTE_GPIO)
|
||||
else {
|
||||
audioMute();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void dacStart()
|
||||
{
|
||||
AUDIO_DMA->HIFCR = DMA_HIFCR_CTCIF5 | DMA_HIFCR_CHTIF5 | DMA_HIFCR_CTEIF5 | DMA_HIFCR_CDMEIF5 | DMA_HIFCR_CFEIF5 ; // Write ones to clear bits
|
||||
AUDIO_DMA_Stream->CR |= DMA_SxCR_CIRC | DMA_SxCR_EN ; // Enable DMA channel
|
||||
DAC->SR = DAC_SR_DMAUDR1 ; // Write 1 to clear flag
|
||||
DAC->CR |= DAC_CR_EN1 | DAC_CR_DMAEN1 ; // Enable DAC
|
||||
}
|
||||
|
||||
void dacStop()
|
||||
{
|
||||
AUDIO_DMA_Stream->CR &= ~DMA_SxCR_CIRC ;
|
||||
}
|
||||
|
||||
|
||||
// Sound routines
|
||||
void audioInit()
|
||||
{
|
||||
@@ -192,38 +219,42 @@ void audioInit()
|
||||
|
||||
void audioEnd()
|
||||
{
|
||||
DAC->CR = 0 ;
|
||||
AUDIO_TIMER->CR1 = 0 ;
|
||||
// Also need to turn off any possible interrupts
|
||||
NVIC_DisableIRQ(AUDIO_TIM_IRQn) ;
|
||||
NVIC_DisableIRQ(AUDIO_DMA_Stream_IRQn) ;
|
||||
}
|
||||
DAC->CR = 0;
|
||||
AUDIO_TIMER->CR1 = 0;
|
||||
|
||||
extern "C" void AUDIO_TIM_IRQHandler()
|
||||
{
|
||||
DEBUG_INTERRUPT(INT_AUDIO);
|
||||
DAC->CR &= ~DAC_CR_DMAEN1 ; // Stop DMA requests
|
||||
#if defined(STM32F2)
|
||||
DAC->CR &= ~DAC_CR_DMAUDRIE1 ; // Stop underrun interrupt
|
||||
#endif
|
||||
DAC->SR = DAC_SR_DMAUDR1 ; // Write 1 to clear flag
|
||||
// Also need to turn off any possible interrupts
|
||||
NVIC_DisableIRQ(AUDIO_TIM_IRQn);
|
||||
NVIC_DisableIRQ(AUDIO_DMA_Stream_IRQn);
|
||||
}
|
||||
|
||||
extern "C" void AUDIO_DMA_Stream_IRQHandler()
|
||||
{
|
||||
AUDIO_DMA_Stream->CR &= ~DMA_SxCR_TCIE ; // Stop interrupt
|
||||
AUDIO_DMA->HIFCR = DMA_HIFCR_CTCIF5 | DMA_HIFCR_CHTIF5 | DMA_HIFCR_CTEIF5 | DMA_HIFCR_CDMEIF5 | DMA_HIFCR_CFEIF5 ; // Write ones to clear flags
|
||||
AUDIO_DMA_Stream->CR &= ~DMA_SxCR_EN ; // Disable DMA channel
|
||||
// disable transfer complete interrupt
|
||||
AUDIO_DMA_Stream->CR &= ~DMA_SxCR_TCIE;
|
||||
|
||||
// reset DMA flags
|
||||
AUDIO_DMA->HIFCR = DMA_HIFCR_CTCIF5 | DMA_HIFCR_CHTIF5 | DMA_HIFCR_CTEIF5 |
|
||||
DMA_HIFCR_CDMEIF5 | DMA_HIFCR_CFEIF5;
|
||||
|
||||
// Disable DMA stream
|
||||
AUDIO_DMA_Stream->CR &= ~DMA_SxCR_EN;
|
||||
|
||||
// get next buffer if any
|
||||
if (nextBuffer) audioQueue.buffersFifo.freeNextFilledBuffer();
|
||||
|
||||
nextBuffer = audioQueue.buffersFifo.getNextFilledBuffer();
|
||||
|
||||
if (nextBuffer) {
|
||||
AUDIO_DMA_Stream->M0AR = CONVERT_PTR_UINT(nextBuffer->data);
|
||||
AUDIO_DMA_Stream->NDTR = nextBuffer->size;
|
||||
AUDIO_DMA->HIFCR = DMA_HIFCR_CTCIF5 | DMA_HIFCR_CHTIF5 | DMA_HIFCR_CTEIF5 | DMA_HIFCR_CDMEIF5 | DMA_HIFCR_CFEIF5 ; // Write ones to clear bits
|
||||
AUDIO_DMA_Stream->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE ; // Enable DMA channel
|
||||
DAC->SR = DAC_SR_DMAUDR1; // Write 1 to clear flag
|
||||
|
||||
// reset DMA flags (again?)
|
||||
AUDIO_DMA->HIFCR = DMA_HIFCR_CTCIF5 | DMA_HIFCR_CHTIF5 | DMA_HIFCR_CTEIF5 |
|
||||
DMA_HIFCR_CDMEIF5 | DMA_HIFCR_CFEIF5;
|
||||
|
||||
// enable DMA stream and transfer complete interrupt
|
||||
AUDIO_DMA_Stream->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE;
|
||||
|
||||
// clear underrun flag
|
||||
DAC->SR = DAC_SR_DMAUDR1;
|
||||
}
|
||||
}
|
||||
#endif // #if !defined(SIMU)
|
||||
|
||||
@@ -25,7 +25,9 @@
|
||||
#include "stm32_spi.h"
|
||||
|
||||
#include "hal/gpio.h"
|
||||
#include "hal/audio_driver.h"
|
||||
|
||||
#include "board.h"
|
||||
#include "edgetx.h"
|
||||
|
||||
#if !defined(SIMU)
|
||||
@@ -187,25 +189,7 @@ uint16_t audioSpiReadReg(uint8_t address)
|
||||
return result;
|
||||
}
|
||||
|
||||
uint16_t audioSpiReadCmd(uint8_t address)
|
||||
{
|
||||
if (!audioWaitDreq(100))
|
||||
return 0;
|
||||
|
||||
audioSpiSetSpeed(SPI_SPEED_64);
|
||||
XDCS_HIGH();
|
||||
CS_LOW();
|
||||
audioSpiReadWriteByte(VS_READ_COMMAND);
|
||||
audioSpiReadWriteByte(address);
|
||||
uint16_t result = audioSpiReadWriteByte(0) << 8;
|
||||
result |= audioSpiReadWriteByte(0);
|
||||
delay_01us(50); // 5us
|
||||
CS_HIGH();
|
||||
audioSpiSetSpeed(SPI_SPEED_8);
|
||||
return result;
|
||||
}
|
||||
|
||||
uint8_t audioSpiWriteCmd(uint8_t address, uint16_t data)
|
||||
static uint8_t audioSpiWriteCmd(uint8_t address, uint16_t data)
|
||||
{
|
||||
if (!audioWaitDreq(100))
|
||||
return 0;
|
||||
@@ -400,9 +384,19 @@ void audioInit()
|
||||
audioSendRiffHeader();
|
||||
}
|
||||
|
||||
uint8_t * currentBuffer = nullptr;
|
||||
uint32_t currentSize = 0;
|
||||
int16_t newVolume = -1;
|
||||
static uint8_t * currentBuffer = nullptr;
|
||||
static uint32_t currentSize = 0;
|
||||
static int16_t newVolume = -1;
|
||||
|
||||
static void set_volume(uint8_t volume)
|
||||
{
|
||||
newVolume = volume;
|
||||
}
|
||||
|
||||
static int32_t get_volume()
|
||||
{
|
||||
return -1; // TODO
|
||||
}
|
||||
|
||||
void audioSetCurrentBuffer(const AudioBuffer * buffer)
|
||||
{
|
||||
@@ -454,29 +448,19 @@ void audioConsumeCurrentBuffer()
|
||||
// max value is 126
|
||||
#define VOLUME_MIN_DB 40
|
||||
|
||||
void setScaledVolume(uint8_t volume)
|
||||
void audioSetVolume(uint8_t volume)
|
||||
{
|
||||
if (volume > VOLUME_LEVEL_MAX) {
|
||||
volume = VOLUME_LEVEL_MAX;
|
||||
}
|
||||
// maximum volume is 0x00 and total silence is 0xFE
|
||||
if (volume == 0) {
|
||||
setVolume(0xFE); // silence
|
||||
set_volume(0xFE); // silence
|
||||
}
|
||||
else {
|
||||
uint32_t vol = (VOLUME_MIN_DB * 2) - ((uint32_t)volume * (VOLUME_MIN_DB * 2)) / VOLUME_LEVEL_MAX;
|
||||
setVolume(vol);
|
||||
set_volume(vol);
|
||||
}
|
||||
}
|
||||
|
||||
void setVolume(uint8_t volume)
|
||||
{
|
||||
newVolume = volume;
|
||||
}
|
||||
|
||||
int32_t getVolume()
|
||||
{
|
||||
return -1; // TODO
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -261,19 +261,6 @@ bool isBacklightEnabled();
|
||||
// Audio driver
|
||||
void audioInit();
|
||||
void audioConsumeCurrentBuffer();
|
||||
#define audioDisableIrq() // interrupts must stay enabled on Horus
|
||||
#define audioEnableIrq() // interrupts must stay enabled on Horus
|
||||
#if defined(PCBX12S)
|
||||
#define setSampleRate(freq)
|
||||
#else
|
||||
void setSampleRate(uint32_t frequency);
|
||||
#define audioWaitReady()
|
||||
#endif
|
||||
void setScaledVolume(uint8_t volume);
|
||||
void setVolume(uint8_t volume);
|
||||
int32_t getVolume();
|
||||
#define VOLUME_LEVEL_MAX 23
|
||||
#define VOLUME_LEVEL_DEF 12
|
||||
|
||||
// Telemetry driver
|
||||
#define INTMODULE_FIFO_SIZE 512
|
||||
|
||||
@@ -208,19 +208,6 @@ bool audioChipReset();
|
||||
#define SPI_SPEED_128 6
|
||||
#define SPI_SPEED_256 7
|
||||
|
||||
#define audioDisableIrq() // interrupts must stay enabled on Horus
|
||||
#define audioEnableIrq() // interrupts must stay enabled on Horus
|
||||
#if defined(PCBNV14)
|
||||
#define setSampleRate(freq)
|
||||
#else
|
||||
void setSampleRate(uint32_t frequency);
|
||||
#endif
|
||||
void setScaledVolume(uint8_t volume);
|
||||
void setVolume(uint8_t volume);
|
||||
int32_t getVolume();
|
||||
#define VOLUME_LEVEL_MAX 23
|
||||
#define VOLUME_LEVEL_DEF 12
|
||||
|
||||
// Telemetry driver
|
||||
#define INTMODULE_FIFO_SIZE 512
|
||||
#define TELEMETRY_FIFO_SIZE 512
|
||||
|
||||
@@ -195,19 +195,6 @@ bool audioChipReset();
|
||||
#define SPI_SPEED_128 6
|
||||
#define SPI_SPEED_256 7
|
||||
|
||||
#define audioDisableIrq() // interrupts must stay enabled on Horus
|
||||
#define audioEnableIrq() // interrupts must stay enabled on Horus
|
||||
#if defined(PCBNV14)
|
||||
#define setSampleRate(freq)
|
||||
#else
|
||||
void setSampleRate(uint32_t frequency);
|
||||
#endif
|
||||
void setScaledVolume(uint8_t volume);
|
||||
void setVolume(uint8_t volume);
|
||||
int32_t getVolume();
|
||||
#define VOLUME_LEVEL_MAX 23
|
||||
#define VOLUME_LEVEL_DEF 12
|
||||
|
||||
// Telemetry driver
|
||||
#define INTMODULE_FIFO_SIZE 512
|
||||
#define TELEMETRY_FIFO_SIZE 512
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "hal/adc_driver.h"
|
||||
#include "hal/rotary_encoder.h"
|
||||
#include "hal/usb_driver.h"
|
||||
#include "hal/audio_driver.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
@@ -250,7 +251,7 @@ void simuStop()
|
||||
struct SimulatorAudio {
|
||||
int volumeGain;
|
||||
int currentVolume;
|
||||
uint16_t leftoverData[AUDIO_BUFFER_SIZE];
|
||||
int16_t leftoverData[AUDIO_BUFFER_SIZE];
|
||||
int leftoverLen;
|
||||
bool threadRunning;
|
||||
pthread_t threadPid;
|
||||
@@ -275,28 +276,19 @@ void audioConsumeCurrentBuffer()
|
||||
{
|
||||
}
|
||||
|
||||
void setScaledVolume(uint8_t volume)
|
||||
void audioSetVolume(uint8_t volume)
|
||||
{
|
||||
simuAudio.currentVolume = 127 * volume * simuAudio.volumeGain / VOLUME_LEVEL_MAX / 10;
|
||||
// TRACE_SIMPGMSPACE("setVolume(): in: %u, out: %u", volume, simuAudio.currentVolume);
|
||||
}
|
||||
|
||||
void setVolume(uint8_t volume)
|
||||
{
|
||||
}
|
||||
|
||||
int32_t getVolume()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(SIMU_AUDIO)
|
||||
void copyBuffer(uint8_t * dest, const uint16_t * buff, unsigned int samples)
|
||||
void copyBuffer(void* dest, const int16_t* buff, unsigned 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 * simuAudio.currentVolume)/127);
|
||||
dest += 2;
|
||||
for (unsigned i = 0; i < samples; i++) {
|
||||
int16_t sample = buff[i];
|
||||
*((int16_t*)dest) = (int16_t)((sample * simuAudio.currentVolume) / 127);
|
||||
dest = (int16_t*)dest + 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -314,29 +306,29 @@ void fillAudioBuffer(void *udata, Uint8 *stream, int len)
|
||||
if (simuAudio.leftoverLen) return; // buffer fully filled
|
||||
}
|
||||
|
||||
if (audioQueue.buffersFifo.filledAtleast(len/(AUDIO_BUFFER_SIZE*2)+1) ) {
|
||||
while(true) {
|
||||
const AudioBuffer * nextBuffer = audioQueue.buffersFifo.getNextFilledBuffer();
|
||||
if (audioQueue.buffersFifo.filledAtleast(len / (AUDIO_BUFFER_SIZE * 2) + 1)) {
|
||||
while (true) {
|
||||
const AudioBuffer* nextBuffer =
|
||||
audioQueue.buffersFifo.getNextFilledBuffer();
|
||||
if (nextBuffer) {
|
||||
if (len >= nextBuffer->size*2) {
|
||||
if (len >= nextBuffer->size * 2) {
|
||||
copyBuffer(stream, nextBuffer->data, nextBuffer->size);
|
||||
stream += nextBuffer->size*2;
|
||||
len -= nextBuffer->size*2;
|
||||
stream += nextBuffer->size * 2;
|
||||
len -= nextBuffer->size * 2;
|
||||
// putchar('+');
|
||||
audioQueue.buffersFifo.freeNextFilledBuffer();
|
||||
}
|
||||
else {
|
||||
//partial
|
||||
copyBuffer(stream, nextBuffer->data, len/2);
|
||||
simuAudio.leftoverLen = (nextBuffer->size-len/2);
|
||||
memcpy(simuAudio.leftoverData, &nextBuffer->data[len/2], simuAudio.leftoverLen*2);
|
||||
} else {
|
||||
// partial
|
||||
copyBuffer(stream, nextBuffer->data, len / 2);
|
||||
simuAudio.leftoverLen = (nextBuffer->size - len / 2);
|
||||
memcpy(simuAudio.leftoverData, &nextBuffer->data[len / 2],
|
||||
simuAudio.leftoverLen * 2);
|
||||
len = 0;
|
||||
// putchar('p');
|
||||
audioQueue.buffersFifo.freeNextFilledBuffer();
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -367,7 +359,8 @@ void * audioThread(void *)
|
||||
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.samples =
|
||||
AUDIO_BUFFER_SIZE * 2; /* Good low-latency value for callback */
|
||||
wanted.callback = fillAudioBuffer;
|
||||
wanted.userdata = nullptr;
|
||||
|
||||
@@ -395,7 +388,7 @@ void startAudioThread(int volumeGain)
|
||||
simuAudio.threadRunning = true;
|
||||
simuAudio.volumeGain = volumeGain;
|
||||
TRACE_SIMPGMSPACE("startAudioThread(%d)", volumeGain);
|
||||
setScaledVolume(VOLUME_LEVEL_DEF);
|
||||
audioSetVolume(VOLUME_LEVEL_DEF);
|
||||
|
||||
pthread_attr_t attr;
|
||||
pthread_attr_init(&attr);
|
||||
|
||||
@@ -246,18 +246,9 @@ uint8_t isBacklightEnabled();
|
||||
void debugPutc(const char c);
|
||||
|
||||
// Audio driver
|
||||
void audioInit() ;
|
||||
void audioEnd() ;
|
||||
void dacStart();
|
||||
void dacStop();
|
||||
void setSampleRate(uint32_t frequency);
|
||||
#define VOLUME_LEVEL_MAX 23
|
||||
#define VOLUME_LEVEL_DEF 12
|
||||
#if !defined(SOFTWARE_VOLUME)
|
||||
void setScaledVolume(uint8_t volume);
|
||||
void setVolume(uint8_t volume);
|
||||
int32_t getVolume();
|
||||
#endif
|
||||
void audioInit();
|
||||
void audioEnd();
|
||||
|
||||
#if defined(AUDIO_SPEAKER_ENABLE_GPIO)
|
||||
void initSpeakerEnable();
|
||||
void enableSpeaker();
|
||||
@@ -267,6 +258,7 @@ static inline void initSpeakerEnable() { }
|
||||
static inline void enableSpeaker() { }
|
||||
static inline void disableSpeaker() { }
|
||||
#endif
|
||||
|
||||
#if defined(HEADPHONE_TRAINER_SWITCH_GPIO)
|
||||
void initHeadphoneTrainerSwitch();
|
||||
void enableHeadphone();
|
||||
@@ -276,13 +268,13 @@ static inline void initHeadphoneTrainerSwitch() { }
|
||||
static inline void enableHeadphone() { }
|
||||
static inline void enableTrainer() { }
|
||||
#endif
|
||||
|
||||
#if defined(JACK_DETECT_GPIO)
|
||||
void initJackDetect();
|
||||
bool isJackPlugged();
|
||||
#endif
|
||||
|
||||
void audioConsumeCurrentBuffer();
|
||||
#define audioDisableIrq() __disable_irq()
|
||||
#define audioEnableIrq() __enable_irq()
|
||||
|
||||
// Haptic driver
|
||||
void hapticInit();
|
||||
|
||||
@@ -21,17 +21,19 @@
|
||||
|
||||
#if !defined(SOFTWARE_VOLUME)
|
||||
|
||||
#include "hal/i2c_driver.h"
|
||||
#include "stm32_i2c_driver.h"
|
||||
|
||||
#include "hal/i2c_driver.h"
|
||||
#include "hal/audio_driver.h"
|
||||
|
||||
#include "board.h"
|
||||
|
||||
static const uint8_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
|
||||
static const uint8_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,
|
||||
};
|
||||
|
||||
int32_t getVolume()
|
||||
static int32_t read_i2c_volume()
|
||||
{
|
||||
uint8_t value = 0;
|
||||
if (i2c_read(VOLUME_I2C_BUS, VOLUME_I2C_ADDRESS, 0, 1, &value, 1) < 0)
|
||||
@@ -40,19 +42,19 @@ int32_t getVolume()
|
||||
return value;
|
||||
}
|
||||
|
||||
void setVolume(uint8_t volume)
|
||||
static void write_i2c_volume(uint8_t volume)
|
||||
{
|
||||
i2c_init(VOLUME_I2C_BUS);
|
||||
i2c_write(VOLUME_I2C_BUS, VOLUME_I2C_ADDRESS, 0, 1, &volume, 1);
|
||||
}
|
||||
|
||||
void setScaledVolume(uint8_t volume)
|
||||
void audioSetVolume(uint8_t volume)
|
||||
{
|
||||
if (volume > VOLUME_LEVEL_MAX) {
|
||||
volume = VOLUME_LEVEL_MAX;
|
||||
}
|
||||
|
||||
setVolume(volumeScale[volume]);
|
||||
write_i2c_volume(volumeScale[volume]);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user