From ebff73a95ffa66eb5cdc7c93fbbf5c1de2fb2ec5 Mon Sep 17 00:00:00 2001 From: Silvano Seva Date: Sun, 9 Jun 2024 14:33:05 +0200 Subject: [PATCH] CS7000: audio driver --- meson.build | 3 +- platform/drivers/audio/audio_CS7000.cpp | 185 +++++++++++++++++++++ platform/drivers/baseband/radio_CS7000.cpp | 8 +- platform/targets/CS7000/platform.c | 7 +- 4 files changed, 193 insertions(+), 10 deletions(-) create mode 100644 platform/drivers/audio/audio_CS7000.cpp diff --git a/meson.build b/meson.build index 4007ec9d..fa34fc6d 100644 --- a/meson.build +++ b/meson.build @@ -469,7 +469,8 @@ cs7000_src = ['platform/drivers/NVM/nvmem_CS7000.c', 'platform/drivers/keyboard/keyboard_CS7000.c', 'platform/drivers/display/ST7735R_CS7000.c', 'platform/drivers/backlight/backlight_CS7000.c', - 'platform/drivers/stubs/audio_stub.c', + 'platform/drivers/audio/Cx000_dac.cpp', + 'platform/drivers/audio/audio_CS7000.cpp', 'platform/drivers/GPIO/gpio_shiftReg.c', 'platform/drivers/SPI/spi_custom.c', 'platform/drivers/SPI/spi_bitbang.c', diff --git a/platform/drivers/audio/audio_CS7000.cpp b/platform/drivers/audio/audio_CS7000.cpp new file mode 100644 index 00000000..f05d7bc0 --- /dev/null +++ b/platform/drivers/audio/audio_CS7000.cpp @@ -0,0 +1,185 @@ +/*************************************************************************** + * Copyright (C) 2024 by Federico Amedeo Izzo IU2NUO, * + * Niccolò Izzo IU2KIN * + * Frederik Saraci IU2NRO * + * Silvano Seva IU2KWO * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 3 of the License, or * + * (at your option) any later version. * + * * + * 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. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, see * + ***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "stm32_dac.h" +#include "stm32_adc.h" +#include "Cx000_dac.h" + +#define PATH(x,y) ((x << 4) | y) + +const struct audioDevice outputDevices[] = +{ + {NULL, NULL, 0, SINK_MCU}, + {&stm32_dac_audio_driver, NULL, STM32_DAC_CH2, SINK_RTX}, + {&Cx000_dac_audio_driver, NULL, 0, SINK_SPK}, +}; + +const struct audioDevice inputDevices[] = +{ + {NULL, 0, 0, SOURCE_MCU}, + {&stm32_adc_audio_driver, (const void *) ADC_RTX_CH, STM32_ADC_ADC2, SOURCE_RTX}, + {&stm32_adc_audio_driver, (const void *) ADC_MIC_CH, STM32_ADC_ADC2, SOURCE_MIC}, +}; + +static void *audio_thread(void *arg) +{ + (void) arg; + + unsigned long long now = getTick(); + + Cx000dac_init(&C6000); + + while(state.devStatus != SHUTDOWN) + { + Cx000dac_task(); + + now += 4; + sleepUntil(now); + } + + Cx000dac_terminate(); + + return NULL; +} + +void audio_init() +{ + gpio_setMode(BEEP_OUT, ANALOG); + gpio_setMode(AIN_MIC, ANALOG); + gpio_setMode(AIN_RTX, ANALOG); + gpio_setMode(C6K_CLK, OUTPUT); + gpio_setMode(C6K_MOSI, OUTPUT); + gpio_setMode(C6K_MISO, INPUT); + + stm32dac_init(STM32_DAC_CH2, 2048); + stm32adc_init(STM32_ADC_ADC2); + + gpioDev_clear(C6K_SLEEP); + delayMs(10); + spi_init((const struct spiDevice *) &c6000_spi); + C6000.init(); + + pthread_attr_t attr; + pthread_t thread; + struct sched_param param; + + pthread_attr_init(&attr); + pthread_attr_setstacksize(&attr, AUDIO_THREAD_STKSIZE); + + param.sched_priority = THREAD_PRIO_RT; + pthread_attr_setschedparam(&attr, ¶m); + pthread_create(&thread, &attr, audio_thread, NULL); +} + +void audio_terminate() +{ + gpioDev_clear(AUDIO_AMP_EN); + gpioDev_clear(MIC_PWR_EN); + gpioDev_set(C6K_SLEEP); + + stm32dac_terminate(); + stm32adc_terminate(); + C6000.terminate(); +} + + +void audio_connect(const enum AudioSource source, const enum AudioSink sink) +{ + uint32_t path = PATH(source, sink); + + switch(path) + { + case PATH(SOURCE_MIC, SINK_SPK): + case PATH(SOURCE_MIC, SINK_RTX): + case PATH(SOURCE_MIC, SINK_MCU): + gpioDev_set(MIC_PWR_EN); + gpioDev_set(INT_MIC_SEL); + break; + + case PATH(SOURCE_MCU, SINK_SPK): + case PATH(SOURCE_RTX, SINK_SPK): + radio_enableAfOutput(); + break; + + default: + break; + } + + if(sink == SINK_SPK) + { + // Anti-pop: unmute speaker after 10ms from amp. power on + gpioDev_set(AUDIO_AMP_EN); + sleepFor(0, 10); + gpioDev_clear(INT_SPK_MUTE); + } +} + +void audio_disconnect(const enum AudioSource source, const enum AudioSink sink) +{ + uint32_t path = PATH(source, sink); + + if(sink == SINK_SPK) + { + gpioDev_set(INT_SPK_MUTE); + gpioDev_clear(AUDIO_AMP_EN); + } + + switch(path) + { + case PATH(SOURCE_MIC, SINK_SPK): + case PATH(SOURCE_MIC, SINK_RTX): + case PATH(SOURCE_MIC, SINK_MCU): + gpioDev_clear(MIC_PWR_EN); + gpioDev_clear(INT_MIC_SEL); + break; + + case PATH(SOURCE_MCU, SINK_SPK): + case PATH(SOURCE_RTX, SINK_SPK): + radio_disableAfOutput(); + break; + + default: + break; + } +} + +bool audio_checkPathCompatibility(const enum AudioSource p1Source, + const enum AudioSink p1Sink, + const enum AudioSource p2Source, + const enum AudioSink p2Sink) + +{ + if(p1Source == p2Source) + return false; + + if(p1Sink == p2Sink) + return false; + + return true; +} diff --git a/platform/drivers/baseband/radio_CS7000.cpp b/platform/drivers/baseband/radio_CS7000.cpp index b407f056..07d41558 100644 --- a/platform/drivers/baseband/radio_CS7000.cpp +++ b/platform/drivers/baseband/radio_CS7000.cpp @@ -123,7 +123,6 @@ void radio_init(const rtxStatus_t *rtxState) spiBitbang_init(&det_spi); spiBitbang_init(&pll_spi); - spiBitbang_init(&c6000_spi); /* * Load calibration data @@ -137,11 +136,8 @@ void radio_init(const rtxStatus_t *rtxState) SKY73210_init(&pll); /* - * Configure HR_C5000 + * Set VCTXO bias */ - gpioDev_clear(C6K_SLEEP); // Exit from sleep - delayMs(10); - C6000.init(); C6000.setModOffset(calData.errorRate[0]); } @@ -153,11 +149,9 @@ void radio_terminate() gpioDev_clear(CTCSS_AMP_EN); // Power off CTCSS amplifier and filter gpioDev_clear(VCO_PWR_EN); // Power off PLL and VCO gpioDev_clear(DET_PDN); // Power off FM demod chip - gpioDev_set(C6K_SLEEP); // Power off HR_C6000 SKY73210_terminate(&pll); AK2365A_terminate(&detector); - C6000.terminate(); DAC->DHR12R1 = 0; RCC->APB1ENR &= ~RCC_APB1ENR_DACEN; diff --git a/platform/targets/CS7000/platform.c b/platform/targets/CS7000/platform.c index 294d5fd4..47b53f64 100644 --- a/platform/targets/CS7000/platform.c +++ b/platform/targets/CS7000/platform.c @@ -18,9 +18,11 @@ #include #include #include +#include #include #include #include +#include #include #include @@ -53,6 +55,7 @@ void platform_init() gpioShiftReg_init(&extGpio); adcStm32_init(&adc1); nvm_init(); + audio_init(); #ifndef RUNNING_TESTSUITE gpioDev_set(MAIN_PWR_SW); @@ -191,12 +194,12 @@ void platform_ledOff(led_t led) void platform_beepStart(uint16_t freq) { - (void) freq; + Cx000dac_startBeep(freq); } void platform_beepStop() { - + Cx000dac_stopBeep(); } const hwInfo_t *platform_getHwInfo()