[FL-3040] Audio support for SubGhz (#2131)
* Furi_hal_speaker: multiple resource usage * Furi_hal_speaker: fix multiple resource usage * Furi_hal_speaker: fix music_player_worker * Furi_hal_speaker: fix mutex release queue handling * SubGhz: add furi_hal_subghz_set_debug_pin * SubGhz: add sound SubGhz Read, SubGhz Read RAW * furi_hal_speaker: add __attribute__((warn_unused_result)) for furi_hal_speaker_acquire() * Furi_hal_speaker: fix review comments * SubGhz: cleanup naming and locking timings * SubGhz,FuriHal: fix speaker deinit logic and subghz speaker release sequence * FuriHal: crash on speaker acquire/release from IRQ * Furi, FuriHal: FURI_WARN_UNUSED and documentation update * Bump api symbols version: fix broken speaker Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
This commit is contained in:
@@ -4,7 +4,6 @@
|
||||
#include <furi_hal_region.h>
|
||||
#include <furi_hal_version.h>
|
||||
#include <furi_hal_rtc.h>
|
||||
#include <furi_hal_gpio.h>
|
||||
#include <furi_hal_spi.h>
|
||||
#include <furi_hal_interrupt.h>
|
||||
#include <furi_hal_resources.h>
|
||||
@@ -17,39 +16,26 @@
|
||||
|
||||
#define TAG "FuriHalSubGhz"
|
||||
|
||||
/*
|
||||
* Uncomment define to enable duplication of
|
||||
* IO GO0 CC1101 to an external comb.
|
||||
* Debug pin can be assigned
|
||||
* gpio_ext_pc0
|
||||
* gpio_ext_pc1
|
||||
* gpio_ext_pc3
|
||||
* gpio_ext_pb2
|
||||
* gpio_ext_pb3
|
||||
* gpio_ext_pa4
|
||||
* gpio_ext_pa6
|
||||
* gpio_ext_pa7
|
||||
* Attention this setting switches pin to output.
|
||||
* Make sure it is not connected directly to power or ground
|
||||
*/
|
||||
|
||||
//#define SUBGHZ_DEBUG_CC1101_PIN gpio_ext_pa7
|
||||
#ifdef SUBGHZ_DEBUG_CC1101_PIN
|
||||
uint32_t subghz_debug_gpio_buff[2];
|
||||
#endif
|
||||
static uint32_t furi_hal_subghz_debug_gpio_buff[2];
|
||||
|
||||
typedef struct {
|
||||
volatile SubGhzState state;
|
||||
volatile SubGhzRegulation regulation;
|
||||
volatile FuriHalSubGhzPreset preset;
|
||||
const GpioPin* async_mirror_pin;
|
||||
} FuriHalSubGhz;
|
||||
|
||||
volatile FuriHalSubGhz furi_hal_subghz = {
|
||||
.state = SubGhzStateInit,
|
||||
.regulation = SubGhzRegulationTxRx,
|
||||
.preset = FuriHalSubGhzPresetIDLE,
|
||||
.async_mirror_pin = NULL,
|
||||
};
|
||||
|
||||
void furi_hal_subghz_set_async_mirror_pin(const GpioPin* pin) {
|
||||
furi_hal_subghz.async_mirror_pin = pin;
|
||||
}
|
||||
|
||||
void furi_hal_subghz_init() {
|
||||
furi_assert(furi_hal_subghz.state == SubGhzStateInit);
|
||||
furi_hal_subghz.state = SubGhzStateIdle;
|
||||
@@ -372,6 +358,29 @@ void furi_hal_subghz_set_path(FuriHalSubGhzPath path) {
|
||||
furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz);
|
||||
}
|
||||
|
||||
static bool furi_hal_subghz_start_debug() {
|
||||
bool ret = false;
|
||||
if(furi_hal_subghz.async_mirror_pin != NULL) {
|
||||
furi_hal_gpio_init(
|
||||
furi_hal_subghz.async_mirror_pin,
|
||||
GpioModeOutputPushPull,
|
||||
GpioPullNo,
|
||||
GpioSpeedVeryHigh);
|
||||
ret = true;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool furi_hal_subghz_stop_debug() {
|
||||
bool ret = false;
|
||||
if(furi_hal_subghz.async_mirror_pin != NULL) {
|
||||
furi_hal_gpio_init(
|
||||
furi_hal_subghz.async_mirror_pin, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
ret = true;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
volatile uint32_t furi_hal_subghz_capture_delta_duration = 0;
|
||||
volatile FuriHalSubGhzCaptureCallback furi_hal_subghz_capture_callback = NULL;
|
||||
volatile void* furi_hal_subghz_capture_callback_context = NULL;
|
||||
@@ -382,9 +391,9 @@ static void furi_hal_subghz_capture_ISR() {
|
||||
LL_TIM_ClearFlag_CC1(TIM2);
|
||||
furi_hal_subghz_capture_delta_duration = LL_TIM_IC_GetCaptureCH1(TIM2);
|
||||
if(furi_hal_subghz_capture_callback) {
|
||||
#ifdef SUBGHZ_DEBUG_CC1101_PIN
|
||||
furi_hal_gpio_write(&SUBGHZ_DEBUG_CC1101_PIN, false);
|
||||
#endif
|
||||
if(furi_hal_subghz.async_mirror_pin != NULL)
|
||||
furi_hal_gpio_write(furi_hal_subghz.async_mirror_pin, false);
|
||||
|
||||
furi_hal_subghz_capture_callback(
|
||||
true,
|
||||
furi_hal_subghz_capture_delta_duration,
|
||||
@@ -395,9 +404,9 @@ static void furi_hal_subghz_capture_ISR() {
|
||||
if(LL_TIM_IsActiveFlag_CC2(TIM2)) {
|
||||
LL_TIM_ClearFlag_CC2(TIM2);
|
||||
if(furi_hal_subghz_capture_callback) {
|
||||
#ifdef SUBGHZ_DEBUG_CC1101_PIN
|
||||
furi_hal_gpio_write(&SUBGHZ_DEBUG_CC1101_PIN, true);
|
||||
#endif
|
||||
if(furi_hal_subghz.async_mirror_pin != NULL)
|
||||
furi_hal_gpio_write(furi_hal_subghz.async_mirror_pin, true);
|
||||
|
||||
furi_hal_subghz_capture_callback(
|
||||
false,
|
||||
LL_TIM_IC_GetCaptureCH2(TIM2) - furi_hal_subghz_capture_delta_duration,
|
||||
@@ -459,10 +468,8 @@ void furi_hal_subghz_start_async_rx(FuriHalSubGhzCaptureCallback callback, void*
|
||||
LL_TIM_SetCounter(TIM2, 0);
|
||||
LL_TIM_EnableCounter(TIM2);
|
||||
|
||||
#ifdef SUBGHZ_DEBUG_CC1101_PIN
|
||||
furi_hal_gpio_init(
|
||||
&SUBGHZ_DEBUG_CC1101_PIN, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh);
|
||||
#endif
|
||||
// Start debug
|
||||
furi_hal_subghz_start_debug();
|
||||
|
||||
// Switch to RX
|
||||
furi_hal_subghz_rx();
|
||||
@@ -478,9 +485,8 @@ void furi_hal_subghz_stop_async_rx() {
|
||||
FURI_CRITICAL_ENTER();
|
||||
LL_TIM_DeInit(TIM2);
|
||||
|
||||
#ifdef SUBGHZ_DEBUG_CC1101_PIN
|
||||
furi_hal_gpio_init(&SUBGHZ_DEBUG_CC1101_PIN, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
#endif
|
||||
// Stop debug
|
||||
furi_hal_subghz_stop_debug();
|
||||
|
||||
FURI_CRITICAL_EXIT();
|
||||
furi_hal_interrupt_set_isr(FuriHalInterruptIdTIM2, NULL, NULL);
|
||||
@@ -673,30 +679,27 @@ bool furi_hal_subghz_start_async_tx(FuriHalSubGhzAsyncTxCallback callback, void*
|
||||
LL_TIM_SetCounter(TIM2, 0);
|
||||
LL_TIM_EnableCounter(TIM2);
|
||||
|
||||
#ifdef SUBGHZ_DEBUG_CC1101_PIN
|
||||
furi_hal_gpio_init(
|
||||
&SUBGHZ_DEBUG_CC1101_PIN, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh);
|
||||
// Start debug
|
||||
if(furi_hal_subghz_start_debug()) {
|
||||
const GpioPin* gpio = furi_hal_subghz.async_mirror_pin;
|
||||
furi_hal_subghz_debug_gpio_buff[0] = (uint32_t)gpio->pin << GPIO_NUMBER;
|
||||
furi_hal_subghz_debug_gpio_buff[1] = gpio->pin;
|
||||
|
||||
const GpioPin* gpio = &SUBGHZ_DEBUG_CC1101_PIN;
|
||||
subghz_debug_gpio_buff[0] = (uint32_t)gpio->pin << GPIO_NUMBER;
|
||||
subghz_debug_gpio_buff[1] = gpio->pin;
|
||||
|
||||
dma_config.MemoryOrM2MDstAddress = (uint32_t)subghz_debug_gpio_buff;
|
||||
dma_config.PeriphOrM2MSrcAddress = (uint32_t) & (gpio->port->BSRR);
|
||||
dma_config.Direction = LL_DMA_DIRECTION_MEMORY_TO_PERIPH;
|
||||
dma_config.Mode = LL_DMA_MODE_CIRCULAR;
|
||||
dma_config.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT;
|
||||
dma_config.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT;
|
||||
dma_config.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_WORD;
|
||||
dma_config.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_WORD;
|
||||
dma_config.NbData = 2;
|
||||
dma_config.PeriphRequest = LL_DMAMUX_REQ_TIM2_UP;
|
||||
dma_config.Priority = LL_DMA_PRIORITY_VERYHIGH;
|
||||
LL_DMA_Init(DMA1, LL_DMA_CHANNEL_2, &dma_config);
|
||||
LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_2, 2);
|
||||
LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_2);
|
||||
|
||||
#endif
|
||||
dma_config.MemoryOrM2MDstAddress = (uint32_t)furi_hal_subghz_debug_gpio_buff;
|
||||
dma_config.PeriphOrM2MSrcAddress = (uint32_t) & (gpio->port->BSRR);
|
||||
dma_config.Direction = LL_DMA_DIRECTION_MEMORY_TO_PERIPH;
|
||||
dma_config.Mode = LL_DMA_MODE_CIRCULAR;
|
||||
dma_config.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT;
|
||||
dma_config.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT;
|
||||
dma_config.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_WORD;
|
||||
dma_config.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_WORD;
|
||||
dma_config.NbData = 2;
|
||||
dma_config.PeriphRequest = LL_DMAMUX_REQ_TIM2_UP;
|
||||
dma_config.Priority = LL_DMA_PRIORITY_VERYHIGH;
|
||||
LL_DMA_Init(DMA1, LL_DMA_CHANNEL_2, &dma_config);
|
||||
LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_2, 2);
|
||||
LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_2);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -730,10 +733,10 @@ void furi_hal_subghz_stop_async_tx() {
|
||||
// Deinitialize GPIO
|
||||
furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
|
||||
#ifdef SUBGHZ_DEBUG_CC1101_PIN
|
||||
LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_2);
|
||||
furi_hal_gpio_init(&SUBGHZ_DEBUG_CC1101_PIN, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
#endif
|
||||
// Stop debug
|
||||
if(furi_hal_subghz_stop_debug()) {
|
||||
LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_2);
|
||||
}
|
||||
|
||||
FURI_CRITICAL_EXIT();
|
||||
|
||||
|
Reference in New Issue
Block a user