From e0277f7dc1a77e91b8ad8eaf97889a29875c1252 Mon Sep 17 00:00:00 2001 From: Yann Locatelli Date: Fri, 1 Mar 2024 17:05:02 +0100 Subject: [PATCH 01/18] :sparkles: (dac): Add CoreSTM32HalBasicTimer Co-Authored-By: Maxime Blanc <66126094+aermanio@users.noreply.github.com> Co-Authored-By: SamHadjes <48731907+samhadjes@users.noreply.github.com> --- config/mbed_app.json | 4 + drivers/CMakeLists.txt | 1 + drivers/CoreDAC/CMakeLists.txt | 27 ++++++ .../CoreDAC/include/CoreSTM32HalBasicTimer.h | 41 +++++++++ .../include/interface/STM32HalBasicTimer.h | 27 ++++++ .../CoreDAC/source/CoreSTM32HalBasicTimer.cpp | 86 +++++++++++++++++++ drivers/CoreDAC/source/HAL_IRQHandlers.cpp | 17 ++++ drivers/CoreDAC/tests/mocks/STM32HalTimer.h | 26 ++++++ drivers/CoreSTM32Hal/include/CoreSTM32Hal.h | 14 +++ drivers/CoreSTM32Hal/source/CoreSTM32Hal.cpp | 52 +++++++++++ include/interface/drivers/STM32Hal.h | 15 ++++ tests/unit/headers/mbed/mbed_config.h | 1 + tests/unit/mocks/mocks/leka/CoreSTM32Hal.h | 14 ++- 13 files changed, 324 insertions(+), 1 deletion(-) create mode 100644 drivers/CoreDAC/CMakeLists.txt create mode 100644 drivers/CoreDAC/include/CoreSTM32HalBasicTimer.h create mode 100644 drivers/CoreDAC/include/interface/STM32HalBasicTimer.h create mode 100644 drivers/CoreDAC/source/CoreSTM32HalBasicTimer.cpp create mode 100644 drivers/CoreDAC/source/HAL_IRQHandlers.cpp create mode 100644 drivers/CoreDAC/tests/mocks/STM32HalTimer.h diff --git a/config/mbed_app.json b/config/mbed_app.json index f9bb933cae..24801e62f1 100644 --- a/config/mbed_app.json +++ b/config/mbed_app.json @@ -4,6 +4,10 @@ "USE_HAL_JPEG_REGISTER_CALLBACKS": { "macro_name": "USE_HAL_JPEG_REGISTER_CALLBACKS", "value": "1U" + }, + "USE_HAL_TIM_REGISTER_CALLBACKS": { + "macro_name": "USE_HAL_TIM_REGISTER_CALLBACKS", + "value": "1U" } }, "target_overrides": { diff --git a/drivers/CMakeLists.txt b/drivers/CMakeLists.txt index 4282cae5cf..daa3090cc5 100644 --- a/drivers/CMakeLists.txt +++ b/drivers/CMakeLists.txt @@ -6,6 +6,7 @@ add_subdirectory(${DRIVERS_DIR}/CoreBufferedSerial) add_subdirectory(${DRIVERS_DIR}/CoreEventFlags) add_subdirectory(${DRIVERS_DIR}/CoreEventQueue) +add_subdirectory(${DRIVERS_DIR}/CoreDAC) add_subdirectory(${DRIVERS_DIR}/CoreI2C) add_subdirectory(${DRIVERS_DIR}/CoreInterruptIn) add_subdirectory(${DRIVERS_DIR}/CoreLL) diff --git a/drivers/CoreDAC/CMakeLists.txt b/drivers/CoreDAC/CMakeLists.txt new file mode 100644 index 0000000000..c50cf4348a --- /dev/null +++ b/drivers/CoreDAC/CMakeLists.txt @@ -0,0 +1,27 @@ +# Leka - LekaOS +# Copyright 2024 APF France handicap +# SPDX-License-Identifier: Apache-2.0 + +add_library(CoreDAC STATIC) + +target_include_directories(CoreDAC + PUBLIC + include +) + +target_sources(CoreDAC + PRIVATE + source/CoreSTM32HalBasicTimer.cpp +) + +if(NOT(${CMAKE_PROJECT_NAME} STREQUAL "LekaOSUnitTests")) + target_sources(CoreDAC + PUBLIC + source/HAL_IRQHandlers.cpp + ) +endif() + +target_link_libraries(CoreDAC + mbed-os + CoreSTM32Hal +) diff --git a/drivers/CoreDAC/include/CoreSTM32HalBasicTimer.h b/drivers/CoreDAC/include/CoreSTM32HalBasicTimer.h new file mode 100644 index 0000000000..94c3b3f1d6 --- /dev/null +++ b/drivers/CoreDAC/include/CoreSTM32HalBasicTimer.h @@ -0,0 +1,41 @@ +// Leka - LekaOS +// Copyright 2024 APF France handicap +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include + +#include "interface/STM32HalBasicTimer.h" + +namespace leka { + +class CoreSTM32HalBasicTimer : public interface::STM32HalBasicTimer +{ + static constexpr float DEFAULT_AUDIO_FILE_SAMPLE_RATE = 44'100; + + public: + CoreSTM32HalBasicTimer(interface::STM32Hal &hal); + + [[nodiscard]] auto getHandle() -> TIM_HandleTypeDef & final; + + void registerCallback(std::function const &callback); + void linkDACTimer(DAC_ChannelConfTypeDef *config) final; + + void initialize(float frequency = DEFAULT_AUDIO_FILE_SAMPLE_RATE) final; + void terminate() final; + + void start() final; + void stop() final; + + private: + void _registerMspCallbacks(); + + interface::STM32Hal &_hal; + + TIM_HandleTypeDef _htim {}; + + std::function _callback {}; +}; + +} // namespace leka diff --git a/drivers/CoreDAC/include/interface/STM32HalBasicTimer.h b/drivers/CoreDAC/include/interface/STM32HalBasicTimer.h new file mode 100644 index 0000000000..73fee09ee3 --- /dev/null +++ b/drivers/CoreDAC/include/interface/STM32HalBasicTimer.h @@ -0,0 +1,27 @@ +// Leka - LekaOS +// Copyright 2024 APF France handicap +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "interface/drivers/STM32Hal.h" + +namespace leka::interface { + +class STM32HalBasicTimer +{ + public: + virtual ~STM32HalBasicTimer() = default; + + [[nodiscard]] virtual auto getHandle() -> TIM_HandleTypeDef & = 0; + + virtual void linkDACTimer(DAC_ChannelConfTypeDef *config) = 0; + + virtual void initialize(float frequency) = 0; + virtual void terminate() = 0; + + virtual void start() = 0; + virtual void stop() = 0; +}; + +} // namespace leka::interface diff --git a/drivers/CoreDAC/source/CoreSTM32HalBasicTimer.cpp b/drivers/CoreDAC/source/CoreSTM32HalBasicTimer.cpp new file mode 100644 index 0000000000..bb54da1113 --- /dev/null +++ b/drivers/CoreDAC/source/CoreSTM32HalBasicTimer.cpp @@ -0,0 +1,86 @@ +// Leka - LekaOS +// Copyright 2024 APF France handicap +// SPDX-License-Identifier: Apache-2.0 + +#include "CoreSTM32HalBasicTimer.h" +#include + +using namespace leka; + +CoreSTM32HalBasicTimer::CoreSTM32HalBasicTimer(interface::STM32Hal &hal) : _hal(hal) +{ + _htim.Instance = TIM6; +} + +auto CoreSTM32HalBasicTimer::getHandle() -> TIM_HandleTypeDef & +{ + return _htim; +} + +void CoreSTM32HalBasicTimer::registerCallback(std::function const &callback) +{ + _callback = callback; +} + +void CoreSTM32HalBasicTimer::initialize(float frequency) +{ + _registerMspCallbacks(); + + // CK_Timer = CK_INT / ((Prescaler + 1) * (Period + 1)) + const auto CK_INT = float {108'000'000.0}; + auto divider = static_cast(std::round(CK_INT / frequency)); + + _htim.Init.Prescaler = 0; + _htim.Init.Period = divider - 1; // ? min 1 + _htim.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; + _hal.HAL_TIM_Base_Init(&_htim); + + auto timerMasterConfig = TIM_MasterConfigTypeDef {}; + timerMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE; + _hal.HAL_TIMEx_MasterConfigSynchronization(&_htim, &timerMasterConfig); + + static const auto &self = *this; + _hal.HAL_TIM_RegisterCallback(&_htim, HAL_TIM_PERIOD_ELAPSED_CB_ID, []([[maybe_unused]] TIM_HandleTypeDef *htim) { + if (self._callback != nullptr) { + self._callback(); + } + }); +} + +void CoreSTM32HalBasicTimer::_registerMspCallbacks() +{ + static const auto &self = *this; + + _hal.HAL_TIM_RegisterCallback(&_htim, HAL_TIM_BASE_MSPINIT_CB_ID, []([[maybe_unused]] TIM_HandleTypeDef *htim) { + self._hal.HAL_RCC_TIM6_CLK_ENABLE(); + + self._hal.HAL_NVIC_SetPriority(TIM6_DAC_IRQn, 0x00, 0x00); + self._hal.HAL_NVIC_EnableIRQ(TIM6_DAC_IRQn); + }); + + _hal.HAL_TIM_RegisterCallback(&_htim, HAL_TIM_BASE_MSPDEINIT_CB_ID, []([[maybe_unused]] TIM_HandleTypeDef *htim) { + self._hal.HAL_RCC_TIM6_CLK_DISABLE(); + }); +} + +void CoreSTM32HalBasicTimer::linkDACTimer(DAC_ChannelConfTypeDef *config) +{ + if (config != nullptr) { + config->DAC_Trigger = DAC_TRIGGER_T6_TRGO; + } +} + +void CoreSTM32HalBasicTimer::terminate() +{ + _hal.HAL_TIM_Base_DeInit(&_htim); +} + +void CoreSTM32HalBasicTimer::start() +{ + _hal.HAL_TIM_Base_Start_IT(&_htim); +} + +void CoreSTM32HalBasicTimer::stop() +{ + _hal.HAL_TIM_Base_Stop_IT(&_htim); +} diff --git a/drivers/CoreDAC/source/HAL_IRQHandlers.cpp b/drivers/CoreDAC/source/HAL_IRQHandlers.cpp new file mode 100644 index 0000000000..2cfc4bf0a0 --- /dev/null +++ b/drivers/CoreDAC/source/HAL_IRQHandlers.cpp @@ -0,0 +1,17 @@ +#include "CoreSTM32HalBasicTimer.h" + +extern "C" { + +extern leka::CoreSTM32HalBasicTimer hal_timer; + +void TIM6_DAC_IRQHandler() +{ + HAL_TIM_IRQHandler(&hal_timer.getHandle()); +} + +void TIM7_DAC_IRQHandler() +{ + HAL_TIM_IRQHandler(&hal_timer.getHandle()); +} + +} // extern "C" diff --git a/drivers/CoreDAC/tests/mocks/STM32HalTimer.h b/drivers/CoreDAC/tests/mocks/STM32HalTimer.h new file mode 100644 index 0000000000..c374de18ac --- /dev/null +++ b/drivers/CoreDAC/tests/mocks/STM32HalTimer.h @@ -0,0 +1,26 @@ +// Leka - LekaOS +// Copyright 2024 APF France handicap +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "gmock/gmock.h" +#include "interface/STM32HalBasicTimer.h" + +namespace leka::mock { + +class STM32HalTimer : public interface::STM32HalBasicTimer +{ + public: + MOCK_METHOD(TIM_HandleTypeDef &, getHandle, (), (override)); + + MOCK_METHOD(void, linkDACTimer, (DAC_ChannelConfTypeDef *), (override)); + + MOCK_METHOD(void, initialize, (float), (override)); + MOCK_METHOD(void, terminate, (), (override)); + + MOCK_METHOD(void, start, (), (override)); + MOCK_METHOD(void, stop, (), (override)); +}; + +} // namespace leka::mock diff --git a/drivers/CoreSTM32Hal/include/CoreSTM32Hal.h b/drivers/CoreSTM32Hal/include/CoreSTM32Hal.h index 7daa41772a..0d552636b5 100644 --- a/drivers/CoreSTM32Hal/include/CoreSTM32Hal.h +++ b/drivers/CoreSTM32Hal/include/CoreSTM32Hal.h @@ -22,6 +22,11 @@ class CoreSTM32Hal : public interface::STM32Hal void HAL_RCC_GPIOI_CLK_ENABLE() final; void HAL_RCC_GPIOJ_CLK_ENABLE() final; + void HAL_RCC_TIM6_CLK_ENABLE() final; + void HAL_RCC_TIM6_CLK_DISABLE() final; + void HAL_RCC_TIM7_CLK_ENABLE() final; + void HAL_RCC_TIM7_CLK_DISABLE() final; + void HAL_RCC_FMC_CLK_ENABLE() final; void HAL_RCC_DMA2_CLK_ENABLE() final; @@ -104,6 +109,15 @@ class CoreSTM32Hal : public interface::STM32Hal auto HAL_JPEG_Pause(JPEG_HandleTypeDef *hjpeg, uint32_t XferSelection) -> HAL_StatusTypeDef final; auto HAL_JPEG_Resume(JPEG_HandleTypeDef *hjpeg, uint32_t XferSelection) -> HAL_StatusTypeDef final; + + auto HAL_TIM_Base_Init(TIM_HandleTypeDef *htim) -> HAL_StatusTypeDef final; + auto HAL_TIMEx_MasterConfigSynchronization(TIM_HandleTypeDef *htim, TIM_MasterConfigTypeDef *sMasterConfig) + -> HAL_StatusTypeDef final; + auto HAL_TIM_RegisterCallback(TIM_HandleTypeDef *htim, HAL_TIM_CallbackIDTypeDef CallbackID, + pTIM_CallbackTypeDef pCallback) -> HAL_StatusTypeDef final; + auto HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *htim) -> HAL_StatusTypeDef final; + auto HAL_TIM_Base_Stop_IT(TIM_HandleTypeDef *htim) -> HAL_StatusTypeDef final; + auto HAL_TIM_Base_DeInit(TIM_HandleTypeDef *htim) -> HAL_StatusTypeDef final; }; } // namespace leka diff --git a/drivers/CoreSTM32Hal/source/CoreSTM32Hal.cpp b/drivers/CoreSTM32Hal/source/CoreSTM32Hal.cpp index c9352501ad..50a925207e 100644 --- a/drivers/CoreSTM32Hal/source/CoreSTM32Hal.cpp +++ b/drivers/CoreSTM32Hal/source/CoreSTM32Hal.cpp @@ -41,6 +41,26 @@ void CoreSTM32Hal::HAL_RCC_GPIOJ_CLK_ENABLE() __HAL_RCC_GPIOJ_CLK_ENABLE(); // NOLINT } +void CoreSTM32Hal::HAL_RCC_TIM6_CLK_ENABLE() +{ + __HAL_RCC_TIM6_CLK_ENABLE(); // NOLINT +} + +void CoreSTM32Hal::HAL_RCC_TIM6_CLK_DISABLE() +{ + __HAL_RCC_TIM6_CLK_DISABLE(); // NOLINT +} + +void CoreSTM32Hal::HAL_RCC_TIM7_CLK_ENABLE() +{ + __HAL_RCC_TIM7_CLK_ENABLE(); // NOLINT +} + +void CoreSTM32Hal::HAL_RCC_TIM7_CLK_DISABLE() +{ + __HAL_RCC_TIM7_CLK_DISABLE(); // NOLINT +} + void CoreSTM32Hal::HAL_RCC_FMC_CLK_ENABLE() { __HAL_RCC_FMC_CLK_ENABLE(); // NOLINT @@ -311,4 +331,36 @@ auto CoreSTM32Hal::HAL_JPEG_Resume(JPEG_HandleTypeDef *hjpeg, uint32_t XferSelec return ::HAL_JPEG_Resume(hjpeg, XferSelection); } +auto CoreSTM32Hal::HAL_TIM_Base_Init(TIM_HandleTypeDef *htim) -> HAL_StatusTypeDef +{ + return ::HAL_TIM_Base_Init(htim); +} + +auto CoreSTM32Hal::HAL_TIMEx_MasterConfigSynchronization(TIM_HandleTypeDef *htim, + TIM_MasterConfigTypeDef *sMasterConfig) -> HAL_StatusTypeDef +{ + return ::HAL_TIMEx_MasterConfigSynchronization(htim, sMasterConfig); +} + +auto CoreSTM32Hal::HAL_TIM_RegisterCallback(TIM_HandleTypeDef *htim, HAL_TIM_CallbackIDTypeDef CallbackID, + pTIM_CallbackTypeDef pCallback) -> HAL_StatusTypeDef +{ + return ::HAL_TIM_RegisterCallback(htim, CallbackID, pCallback); +} + +auto CoreSTM32Hal::HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *htim) -> HAL_StatusTypeDef +{ + return ::HAL_TIM_Base_Start_IT(htim); +} + +auto CoreSTM32Hal::HAL_TIM_Base_Stop_IT(TIM_HandleTypeDef *htim) -> HAL_StatusTypeDef +{ + return ::HAL_TIM_Base_Stop_IT(htim); +} + +auto CoreSTM32Hal::HAL_TIM_Base_DeInit(TIM_HandleTypeDef *htim) -> HAL_StatusTypeDef +{ + return ::HAL_TIM_Base_DeInit(htim); +} + } // namespace leka diff --git a/include/interface/drivers/STM32Hal.h b/include/interface/drivers/STM32Hal.h index b70089f827..79417cc996 100644 --- a/include/interface/drivers/STM32Hal.h +++ b/include/interface/drivers/STM32Hal.h @@ -21,6 +21,12 @@ class STM32Hal virtual void HAL_RCC_GPIOI_CLK_ENABLE() = 0; virtual void HAL_RCC_GPIOJ_CLK_ENABLE() = 0; + virtual void HAL_RCC_TIM6_CLK_ENABLE() = 0; + virtual void HAL_RCC_TIM6_CLK_DISABLE() = 0; + + virtual void HAL_RCC_TIM7_CLK_ENABLE() = 0; + virtual void HAL_RCC_TIM7_CLK_DISABLE() = 0; + virtual void HAL_RCC_FMC_CLK_ENABLE() = 0; virtual void HAL_RCC_DMA2_CLK_ENABLE() = 0; @@ -106,6 +112,15 @@ class STM32Hal virtual auto HAL_JPEG_Pause(JPEG_HandleTypeDef *hjpeg, uint32_t XferSelection) -> HAL_StatusTypeDef = 0; virtual auto HAL_JPEG_Resume(JPEG_HandleTypeDef *hjpeg, uint32_t XferSelection) -> HAL_StatusTypeDef = 0; + + virtual auto HAL_TIM_Base_Init(TIM_HandleTypeDef *htim) -> HAL_StatusTypeDef = 0; + virtual auto HAL_TIMEx_MasterConfigSynchronization(TIM_HandleTypeDef *htim, TIM_MasterConfigTypeDef *sMasterConfig) + -> HAL_StatusTypeDef = 0; + virtual auto HAL_TIM_RegisterCallback(TIM_HandleTypeDef *htim, HAL_TIM_CallbackIDTypeDef CallbackID, + pTIM_CallbackTypeDef pCallback) -> HAL_StatusTypeDef = 0; + virtual auto HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *htim) -> HAL_StatusTypeDef = 0; + virtual auto HAL_TIM_Base_Stop_IT(TIM_HandleTypeDef *htim) -> HAL_StatusTypeDef = 0; + virtual auto HAL_TIM_Base_DeInit(TIM_HandleTypeDef *htim) -> HAL_StatusTypeDef = 0; }; } // namespace leka::interface diff --git a/tests/unit/headers/mbed/mbed_config.h b/tests/unit/headers/mbed/mbed_config.h index e7fee6c006..5ff7967da5 100644 --- a/tests/unit/headers/mbed/mbed_config.h +++ b/tests/unit/headers/mbed/mbed_config.h @@ -288,6 +288,7 @@ #define SMP_DB_MAX_DEVICES 3 // set by library:cordio #define TARGET_LSE_DRIVE_LOAD_LEVEL RCC_LSEDRIVE_LOW // set by target:MCU_STM32F7 #define USE_HAL_JPEG_REGISTER_CALLBACKS 1U // set by application +#define USE_HAL_TIM_REGISTER_CALLBACKS 1U // set by application // Macros #define WSF_MS_PER_TICK 1 // defined by library:cordio #define _RTE_ // defined by library:rtos diff --git a/tests/unit/mocks/mocks/leka/CoreSTM32Hal.h b/tests/unit/mocks/mocks/leka/CoreSTM32Hal.h index 2d950de3e7..d72b263f4d 100644 --- a/tests/unit/mocks/mocks/leka/CoreSTM32Hal.h +++ b/tests/unit/mocks/mocks/leka/CoreSTM32Hal.h @@ -19,7 +19,10 @@ class CoreSTM32Hal : public interface::STM32Hal MOCK_METHOD(void, HAL_RCC_GPIOH_CLK_ENABLE, (), (override)); MOCK_METHOD(void, HAL_RCC_GPIOI_CLK_ENABLE, (), (override)); MOCK_METHOD(void, HAL_RCC_GPIOJ_CLK_ENABLE, (), (override)); - + MOCK_METHOD(void, HAL_RCC_TIM6_CLK_ENABLE, (), (override)); + MOCK_METHOD(void, HAL_RCC_TIM6_CLK_DISABLE, (), (override)); + MOCK_METHOD(void, HAL_RCC_TIM7_CLK_ENABLE, (), (override)); + MOCK_METHOD(void, HAL_RCC_TIM7_CLK_DISABLE, (), (override)); MOCK_METHOD(void, HAL_RCC_FMC_CLK_ENABLE, (), (override)); MOCK_METHOD(void, HAL_RCC_DMA2_CLK_ENABLE, (), (override)); MOCK_METHOD(void, HAL_RCC_JPEG_CLK_ENABLE, (), (override)); @@ -113,6 +116,15 @@ class CoreSTM32Hal : public interface::STM32Hal MOCK_METHOD(HAL_StatusTypeDef, HAL_JPEG_Pause, (JPEG_HandleTypeDef *, uint32_t), (override)); MOCK_METHOD(HAL_StatusTypeDef, HAL_JPEG_Resume, (JPEG_HandleTypeDef *, uint32_t), (override)); + MOCK_METHOD(HAL_StatusTypeDef, HAL_TIM_Base_Init, (TIM_HandleTypeDef * htim), (override)); + MOCK_METHOD(HAL_StatusTypeDef, HAL_TIMEx_MasterConfigSynchronization, + (TIM_HandleTypeDef * htim, TIM_MasterConfigTypeDef *sMasterConfig), (override)); + MOCK_METHOD(HAL_StatusTypeDef, HAL_TIM_RegisterCallback, + (TIM_HandleTypeDef * htim, HAL_TIM_CallbackIDTypeDef CallbackID, pTIM_CallbackTypeDef pCallback), + (override)); + MOCK_METHOD(HAL_StatusTypeDef, HAL_TIM_Base_Start_IT, (TIM_HandleTypeDef * htim), (override)); + MOCK_METHOD(HAL_StatusTypeDef, HAL_TIM_Base_Stop_IT, (TIM_HandleTypeDef * htim), (override)); + MOCK_METHOD(HAL_StatusTypeDef, HAL_TIM_Base_DeInit, (TIM_HandleTypeDef * htim), (override)); }; } // namespace leka::mock From 1056d1c23e888a3edde6683a3674cb960c8270b0 Mon Sep 17 00:00:00 2001 From: Yann Locatelli Date: Fri, 1 Mar 2024 17:10:00 +0100 Subject: [PATCH 02/18] :sparkles: (dac): Add CoreDAC Co-Authored-By: Maxime Blanc <66126094+aermanio@users.noreply.github.com> Co-Authored-By: SamHadjes <48731907+samhadjes@users.noreply.github.com> --- config/mbed_app.json | 4 + drivers/CoreDAC/CMakeLists.txt | 1 + drivers/CoreDAC/include/CoreDAC.h | 49 ++++++++ drivers/CoreDAC/source/CoreDAC.cpp | 116 +++++++++++++++++++ drivers/CoreDAC/source/HAL_IRQHandlers.cpp | 7 ++ drivers/CoreSTM32Hal/include/CoreSTM32Hal.h | 14 +++ drivers/CoreSTM32Hal/source/CoreSTM32Hal.cpp | 48 ++++++++ include/interface/drivers/DAC.h | 24 ++++ include/interface/drivers/STM32Hal.h | 14 +++ tests/unit/headers/mbed/mbed_config.h | 1 + tests/unit/mocks/mocks/leka/CoreSTM32Hal.h | 15 +++ 11 files changed, 293 insertions(+) create mode 100644 drivers/CoreDAC/include/CoreDAC.h create mode 100644 drivers/CoreDAC/source/CoreDAC.cpp create mode 100644 include/interface/drivers/DAC.h diff --git a/config/mbed_app.json b/config/mbed_app.json index 24801e62f1..d65055a6ce 100644 --- a/config/mbed_app.json +++ b/config/mbed_app.json @@ -8,6 +8,10 @@ "USE_HAL_TIM_REGISTER_CALLBACKS": { "macro_name": "USE_HAL_TIM_REGISTER_CALLBACKS", "value": "1U" + }, + "USE_HAL_DAC_REGISTER_CALLBACKS": { + "macro_name": "USE_HAL_DAC_REGISTER_CALLBACKS", + "value": "1U" } }, "target_overrides": { diff --git a/drivers/CoreDAC/CMakeLists.txt b/drivers/CoreDAC/CMakeLists.txt index c50cf4348a..c2e26193d8 100644 --- a/drivers/CoreDAC/CMakeLists.txt +++ b/drivers/CoreDAC/CMakeLists.txt @@ -12,6 +12,7 @@ target_include_directories(CoreDAC target_sources(CoreDAC PRIVATE source/CoreSTM32HalBasicTimer.cpp + source/CoreDAC.cpp ) if(NOT(${CMAKE_PROJECT_NAME} STREQUAL "LekaOSUnitTests")) diff --git a/drivers/CoreDAC/include/CoreDAC.h b/drivers/CoreDAC/include/CoreDAC.h new file mode 100644 index 0000000000..a04818033f --- /dev/null +++ b/drivers/CoreDAC/include/CoreDAC.h @@ -0,0 +1,49 @@ +// Leka - LekaOS +// Copyright 2024 APF France handicap +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include +#include +#include + +#include "interface/STM32HalBasicTimer.h" +#include "interface/drivers/DAC.h" +#include "interface/drivers/STM32Hal.h" + +namespace leka { + +class CoreDAC : public interface::DACBase +{ + public: + CoreDAC(interface::STM32Hal &hal, interface::STM32HalBasicTimer &hal_timer); + + [[nodiscard]] auto getHandle() -> DAC_HandleTypeDef & final; + + void initialize() final; + void terminate() final; + + void registerDataToPlay(std::span data); + void registerDMACallbacks(std::function const &on_half_transfer, + std::function const &on_complete_transfer); + + void start() final; + void stop() final; + + private: + void _registerMspCallbacks(); + void _initializeDMA(); + + interface::STM32Hal &_hal; + interface::STM32HalBasicTimer &_hal_timer; + + DAC_HandleTypeDef _hdac {}; + DMA_HandleTypeDef _hdma {}; + + std::span _data; + std::function _on_half_transfer {}; + std::function _on_complete_transfer {}; +}; + +} // namespace leka diff --git a/drivers/CoreDAC/source/CoreDAC.cpp b/drivers/CoreDAC/source/CoreDAC.cpp new file mode 100644 index 0000000000..c3a28f899e --- /dev/null +++ b/drivers/CoreDAC/source/CoreDAC.cpp @@ -0,0 +1,116 @@ +// Leka - LekaOS +// Copyright 2024 APF France handicap +// SPDX-License-Identifier: Apache-2.0 + +#include "CoreDAC.h" + +using namespace leka; + +CoreDAC::CoreDAC(interface::STM32Hal &hal, interface::STM32HalBasicTimer &hal_timer) : _hal(hal), _hal_timer(hal_timer) +{ + _hdac.Instance = DAC; +} + +auto CoreDAC::getHandle() -> DAC_HandleTypeDef & +{ + return _hdac; +} + +void CoreDAC::initialize() +{ + _registerMspCallbacks(); + + _hal.HAL_DAC_Init(&_hdac); + + DAC_ChannelConfTypeDef config = {}; + config.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE; + _hal_timer.linkDACTimer(&config); + _hal.HAL_DAC_ConfigChannel(&_hdac, &config, DAC_CHANNEL_1); + + static const auto &self = *this; + _hal.HAL_DAC_RegisterCallback(&_hdac, HAL_DAC_CH1_HALF_COMPLETE_CB_ID, + []([[maybe_unused]] DAC_HandleTypeDef *hdac) { + if (self._on_half_transfer != nullptr) { + self._on_half_transfer(); + } + }); + _hal.HAL_DAC_RegisterCallback(&_hdac, HAL_DAC_CH1_COMPLETE_CB_ID, []([[maybe_unused]] DAC_HandleTypeDef *hdac) { + if (self._on_complete_transfer != nullptr) { + self._on_complete_transfer(); + } + }); +} + +void CoreDAC::terminate() +{ + _hal.HAL_DAC_DeInit(&_hdac); +} + +void CoreDAC::registerDataToPlay(std::span data) +{ + _data = data; +} + +void CoreDAC::registerDMACallbacks(std::function const &on_half_transfer, + std::function const &on_complete_transfer) +{ + _on_half_transfer = on_half_transfer; + _on_complete_transfer = on_complete_transfer; +} + +void CoreDAC::start() +{ + _hal_timer.start(); + _hal.HAL_DAC_Start_DMA(&_hdac, DAC_CHANNEL_1, reinterpret_cast(_data.data()), _data.size(), + DAC_ALIGN_12B_R); +} + +void CoreDAC::stop() +{ + _hal.HAL_DAC_Stop_DMA(&_hdac, DAC_CHANNEL_1); +} + +void CoreDAC::_registerMspCallbacks() +{ + static auto &self = *this; + + _hal.HAL_DAC_RegisterCallback(&_hdac, HAL_DAC_MSPINIT_CB_ID, []([[maybe_unused]] DAC_HandleTypeDef *hdac) { + __HAL_LINKDMA(&self._hdac, DMA_Handle1, self._hdma); + self._initializeDMA(); + + self._hal.HAL_RCC_DAC_CLK_ENABLE(); + }); + + _hal.HAL_DAC_RegisterCallback(&_hdac, HAL_DAC_MSPDEINIT_CB_ID, []([[maybe_unused]] DAC_HandleTypeDef *hdac) { + self._hal.HAL_DMA_DeInit(&self._hdma); + + self._hal.HAL_RCC_DAC_CLK_DISABLE(); + }); +} + +void CoreDAC::_initializeDMA() +{ + _hal.HAL_RCC_DMA1_CLK_ENABLE(); + + _hal.HAL_NVIC_SetPriority(DMA1_Stream5_IRQn, 3, 0); + _hal.HAL_NVIC_EnableIRQ(DMA1_Stream5_IRQn); + + _hdma.Instance = DMA1_Stream5; // DMA1_Stream5 is the only DMA channel for DAC + + _hdma.Init.Channel = DMA_CHANNEL_7; + _hdma.Init.Direction = DMA_MEMORY_TO_PERIPH; + _hdma.Init.PeriphInc = DMA_PINC_DISABLE; + _hdma.Init.MemInc = DMA_MINC_ENABLE; + _hdma.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; + _hdma.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; + _hdma.Init.Mode = DMA_CIRCULAR; + _hdma.Init.Priority = DMA_PRIORITY_LOW; + _hdma.Init.FIFOMode = DMA_FIFOMODE_ENABLE; + _hdma.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_HALFFULL; + _hdma.Init.MemBurst = DMA_MBURST_SINGLE; + // Single mem burst is more ressource consuming than 4 burst or more + // However the buffer apparently needs to be of a size multiple of the burst mode chosen + _hdma.Init.PeriphBurst = DMA_PBURST_SINGLE; + + _hal.HAL_DMA_Init(&_hdma); +} diff --git a/drivers/CoreDAC/source/HAL_IRQHandlers.cpp b/drivers/CoreDAC/source/HAL_IRQHandlers.cpp index 2cfc4bf0a0..31ae2946df 100644 --- a/drivers/CoreDAC/source/HAL_IRQHandlers.cpp +++ b/drivers/CoreDAC/source/HAL_IRQHandlers.cpp @@ -1,8 +1,10 @@ +#include "CoreDAC.h" #include "CoreSTM32HalBasicTimer.h" extern "C" { extern leka::CoreSTM32HalBasicTimer hal_timer; +extern leka::CoreDAC coredac; void TIM6_DAC_IRQHandler() { @@ -14,4 +16,9 @@ void TIM7_DAC_IRQHandler() HAL_TIM_IRQHandler(&hal_timer.getHandle()); } +void DMA1_Stream5_IRQHandler() +{ + HAL_DMA_IRQHandler(coredac.getHandle().DMA_Handle1); +} + } // extern "C" diff --git a/drivers/CoreSTM32Hal/include/CoreSTM32Hal.h b/drivers/CoreSTM32Hal/include/CoreSTM32Hal.h index 0d552636b5..2453a066f8 100644 --- a/drivers/CoreSTM32Hal/include/CoreSTM32Hal.h +++ b/drivers/CoreSTM32Hal/include/CoreSTM32Hal.h @@ -29,8 +29,12 @@ class CoreSTM32Hal : public interface::STM32Hal void HAL_RCC_FMC_CLK_ENABLE() final; + void HAL_RCC_DMA1_CLK_ENABLE() final; void HAL_RCC_DMA2_CLK_ENABLE() final; + void HAL_RCC_DAC_CLK_ENABLE() final; + void HAL_RCC_DAC_CLK_DISABLE() final; + void HAL_RCC_JPEG_CLK_ENABLE() final; void HAL_RCC_JPEG_FORCE_RESET() final; void HAL_RCC_JPEG_RELEASE_RESET() final; @@ -118,6 +122,16 @@ class CoreSTM32Hal : public interface::STM32Hal auto HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *htim) -> HAL_StatusTypeDef final; auto HAL_TIM_Base_Stop_IT(TIM_HandleTypeDef *htim) -> HAL_StatusTypeDef final; auto HAL_TIM_Base_DeInit(TIM_HandleTypeDef *htim) -> HAL_StatusTypeDef final; + + auto HAL_DAC_Init(DAC_HandleTypeDef *hdac) -> HAL_StatusTypeDef final; + auto HAL_DAC_ConfigChannel(DAC_HandleTypeDef *hdac, DAC_ChannelConfTypeDef *sConfig, uint32_t Channel) + -> HAL_StatusTypeDef final; + auto HAL_DAC_RegisterCallback(DAC_HandleTypeDef *hdac, HAL_DAC_CallbackIDTypeDef CallbackID, + pDAC_CallbackTypeDef pCallback) -> HAL_StatusTypeDef final; + auto HAL_DAC_Start_DMA(DAC_HandleTypeDef *hdac, uint32_t Channel, uint32_t *pData, uint32_t Length, + uint32_t Alignment) -> HAL_StatusTypeDef final; + auto HAL_DAC_Stop_DMA(DAC_HandleTypeDef *hdac, uint32_t Channel) -> HAL_StatusTypeDef final; + auto HAL_DAC_DeInit(DAC_HandleTypeDef *hdac) -> HAL_StatusTypeDef final; }; } // namespace leka diff --git a/drivers/CoreSTM32Hal/source/CoreSTM32Hal.cpp b/drivers/CoreSTM32Hal/source/CoreSTM32Hal.cpp index 50a925207e..2beb724e2a 100644 --- a/drivers/CoreSTM32Hal/source/CoreSTM32Hal.cpp +++ b/drivers/CoreSTM32Hal/source/CoreSTM32Hal.cpp @@ -66,11 +66,26 @@ void CoreSTM32Hal::HAL_RCC_FMC_CLK_ENABLE() __HAL_RCC_FMC_CLK_ENABLE(); // NOLINT } +void CoreSTM32Hal::HAL_RCC_DMA1_CLK_ENABLE() +{ + __HAL_RCC_DMA1_CLK_ENABLE(); // NOLINT +} + void CoreSTM32Hal::HAL_RCC_DMA2_CLK_ENABLE() { __HAL_RCC_DMA2_CLK_ENABLE(); // NOLINT } +void CoreSTM32Hal::HAL_RCC_DAC_CLK_ENABLE() +{ + __HAL_RCC_DAC_CLK_ENABLE(); // NOLINT +} + +void CoreSTM32Hal::HAL_RCC_DAC_CLK_DISABLE() +{ + __HAL_RCC_DAC_CLK_DISABLE(); // NOLINT +} + void CoreSTM32Hal::HAL_RCC_JPEG_CLK_ENABLE() { __HAL_RCC_JPEG_CLK_ENABLE(); // NOLINT @@ -363,4 +378,37 @@ auto CoreSTM32Hal::HAL_TIM_Base_DeInit(TIM_HandleTypeDef *htim) -> HAL_StatusTyp return ::HAL_TIM_Base_DeInit(htim); } +auto CoreSTM32Hal::HAL_DAC_Init(DAC_HandleTypeDef *hdac) -> HAL_StatusTypeDef +{ + return ::HAL_DAC_Init(hdac); +} + +auto CoreSTM32Hal::HAL_DAC_ConfigChannel(DAC_HandleTypeDef *hdac, DAC_ChannelConfTypeDef *sConfig, uint32_t Channel) + -> HAL_StatusTypeDef +{ + return ::HAL_DAC_ConfigChannel(hdac, sConfig, Channel); +} + +auto CoreSTM32Hal::HAL_DAC_RegisterCallback(DAC_HandleTypeDef *hdac, HAL_DAC_CallbackIDTypeDef CallbackID, + pDAC_CallbackTypeDef pCallback) -> HAL_StatusTypeDef +{ + return ::HAL_DAC_RegisterCallback(hdac, CallbackID, pCallback); +} + +auto CoreSTM32Hal::HAL_DAC_Start_DMA(DAC_HandleTypeDef *hdac, uint32_t Channel, uint32_t *pData, uint32_t Length, + uint32_t Alignment) -> HAL_StatusTypeDef +{ + return ::HAL_DAC_Start_DMA(hdac, Channel, pData, Length, Alignment); +} + +auto CoreSTM32Hal::HAL_DAC_Stop_DMA(DAC_HandleTypeDef *hdac, uint32_t Channel) -> HAL_StatusTypeDef +{ + return ::HAL_DAC_Stop_DMA(hdac, Channel); +} + +auto CoreSTM32Hal::HAL_DAC_DeInit(DAC_HandleTypeDef *hdac) -> HAL_StatusTypeDef +{ + return ::HAL_DAC_DeInit(hdac); +} + } // namespace leka diff --git a/include/interface/drivers/DAC.h b/include/interface/drivers/DAC.h new file mode 100644 index 0000000000..d9a4707664 --- /dev/null +++ b/include/interface/drivers/DAC.h @@ -0,0 +1,24 @@ +// Leka - LekaOS +// Copyright 2024 APF France handicap +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "interface/drivers/STM32Hal.h" + +namespace leka::interface { +class DACBase +{ + public: + virtual ~DACBase() = default; + + [[nodiscard]] virtual auto getHandle() -> DAC_HandleTypeDef & = 0; + + virtual void initialize() = 0; + virtual void terminate() = 0; + + virtual void start() = 0; + virtual void stop() = 0; +}; + +} // namespace leka::interface diff --git a/include/interface/drivers/STM32Hal.h b/include/interface/drivers/STM32Hal.h index 79417cc996..4b5f56ad86 100644 --- a/include/interface/drivers/STM32Hal.h +++ b/include/interface/drivers/STM32Hal.h @@ -29,8 +29,12 @@ class STM32Hal virtual void HAL_RCC_FMC_CLK_ENABLE() = 0; + virtual void HAL_RCC_DMA1_CLK_ENABLE() = 0; virtual void HAL_RCC_DMA2_CLK_ENABLE() = 0; + virtual void HAL_RCC_DAC_CLK_ENABLE() = 0; + virtual void HAL_RCC_DAC_CLK_DISABLE() = 0; + virtual void HAL_RCC_JPEG_CLK_ENABLE() = 0; virtual void HAL_RCC_JPEG_FORCE_RESET() = 0; virtual void HAL_RCC_JPEG_RELEASE_RESET() = 0; @@ -121,6 +125,16 @@ class STM32Hal virtual auto HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *htim) -> HAL_StatusTypeDef = 0; virtual auto HAL_TIM_Base_Stop_IT(TIM_HandleTypeDef *htim) -> HAL_StatusTypeDef = 0; virtual auto HAL_TIM_Base_DeInit(TIM_HandleTypeDef *htim) -> HAL_StatusTypeDef = 0; + + virtual auto HAL_DAC_Init(DAC_HandleTypeDef *hdac) -> HAL_StatusTypeDef = 0; + virtual auto HAL_DAC_ConfigChannel(DAC_HandleTypeDef *hdac, DAC_ChannelConfTypeDef *sConfig, uint32_t Channel) + -> HAL_StatusTypeDef = 0; + virtual auto HAL_DAC_RegisterCallback(DAC_HandleTypeDef *hdac, HAL_DAC_CallbackIDTypeDef CallbackID, + pDAC_CallbackTypeDef pCallback) -> HAL_StatusTypeDef = 0; + virtual auto HAL_DAC_Start_DMA(DAC_HandleTypeDef *hdac, uint32_t Channel, uint32_t *pData, uint32_t Length, + uint32_t Alignment) -> HAL_StatusTypeDef = 0; + virtual auto HAL_DAC_Stop_DMA(DAC_HandleTypeDef *hdac, uint32_t Channel) -> HAL_StatusTypeDef = 0; + virtual auto HAL_DAC_DeInit(DAC_HandleTypeDef *hdac) -> HAL_StatusTypeDef = 0; }; } // namespace leka::interface diff --git a/tests/unit/headers/mbed/mbed_config.h b/tests/unit/headers/mbed/mbed_config.h index 5ff7967da5..5b057607c0 100644 --- a/tests/unit/headers/mbed/mbed_config.h +++ b/tests/unit/headers/mbed/mbed_config.h @@ -289,6 +289,7 @@ #define TARGET_LSE_DRIVE_LOAD_LEVEL RCC_LSEDRIVE_LOW // set by target:MCU_STM32F7 #define USE_HAL_JPEG_REGISTER_CALLBACKS 1U // set by application #define USE_HAL_TIM_REGISTER_CALLBACKS 1U // set by application +#define USE_HAL_DAC_REGISTER_CALLBACKS 1U // set by application // Macros #define WSF_MS_PER_TICK 1 // defined by library:cordio #define _RTE_ // defined by library:rtos diff --git a/tests/unit/mocks/mocks/leka/CoreSTM32Hal.h b/tests/unit/mocks/mocks/leka/CoreSTM32Hal.h index d72b263f4d..5751098106 100644 --- a/tests/unit/mocks/mocks/leka/CoreSTM32Hal.h +++ b/tests/unit/mocks/mocks/leka/CoreSTM32Hal.h @@ -24,7 +24,10 @@ class CoreSTM32Hal : public interface::STM32Hal MOCK_METHOD(void, HAL_RCC_TIM7_CLK_ENABLE, (), (override)); MOCK_METHOD(void, HAL_RCC_TIM7_CLK_DISABLE, (), (override)); MOCK_METHOD(void, HAL_RCC_FMC_CLK_ENABLE, (), (override)); + MOCK_METHOD(void, HAL_RCC_DMA1_CLK_ENABLE, (), (override)); MOCK_METHOD(void, HAL_RCC_DMA2_CLK_ENABLE, (), (override)); + MOCK_METHOD(void, HAL_RCC_DAC_CLK_ENABLE, (), (override)); + MOCK_METHOD(void, HAL_RCC_DAC_CLK_DISABLE, (), (override)); MOCK_METHOD(void, HAL_RCC_JPEG_CLK_ENABLE, (), (override)); MOCK_METHOD(void, HAL_RCC_JPEG_FORCE_RESET, (), (override)); MOCK_METHOD(void, HAL_RCC_JPEG_RELEASE_RESET, (), (override)); @@ -125,6 +128,18 @@ class CoreSTM32Hal : public interface::STM32Hal MOCK_METHOD(HAL_StatusTypeDef, HAL_TIM_Base_Start_IT, (TIM_HandleTypeDef * htim), (override)); MOCK_METHOD(HAL_StatusTypeDef, HAL_TIM_Base_Stop_IT, (TIM_HandleTypeDef * htim), (override)); MOCK_METHOD(HAL_StatusTypeDef, HAL_TIM_Base_DeInit, (TIM_HandleTypeDef * htim), (override)); + + MOCK_METHOD(HAL_StatusTypeDef, HAL_DAC_Init, (DAC_HandleTypeDef * hdac), (override)); + MOCK_METHOD(HAL_StatusTypeDef, HAL_DAC_ConfigChannel, + (DAC_HandleTypeDef * hdac, DAC_ChannelConfTypeDef *sConfig, uint32_t Channel), (override)); + MOCK_METHOD(HAL_StatusTypeDef, HAL_DAC_RegisterCallback, + (DAC_HandleTypeDef * hdac, HAL_DAC_CallbackIDTypeDef CallbackID, pDAC_CallbackTypeDef pCallback), + (override)); + MOCK_METHOD(HAL_StatusTypeDef, HAL_DAC_Start_DMA, + (DAC_HandleTypeDef * hdac, uint32_t Channel, uint32_t *pData, uint32_t Length, uint32_t Alignment), + (override)); + MOCK_METHOD(HAL_StatusTypeDef, HAL_DAC_Stop_DMA, (DAC_HandleTypeDef * hdac, uint32_t Channel), (override)); + MOCK_METHOD(HAL_StatusTypeDef, HAL_DAC_DeInit, (DAC_HandleTypeDef * hdac), (override)); }; } // namespace leka::mock From 46fa96315ec203bd36e5241587bbfb445b1c5b29 Mon Sep 17 00:00:00 2001 From: Yann Locatelli Date: Fri, 1 Mar 2024 16:57:41 +0100 Subject: [PATCH 03/18] :sparkles: (dac): Add CoreDAC spike Co-Authored-By: Maxime Blanc <66126094+aermanio@users.noreply.github.com> Co-Authored-By: SamHadjes <48731907+samhadjes@users.noreply.github.com> --- spikes/CMakeLists.txt | 2 + spikes/lk_dac/CMakeLists.txt | 22 +++++++++++ spikes/lk_dac/main.cpp | 72 ++++++++++++++++++++++++++++++++++++ 3 files changed, 96 insertions(+) create mode 100644 spikes/lk_dac/CMakeLists.txt create mode 100644 spikes/lk_dac/main.cpp diff --git a/spikes/CMakeLists.txt b/spikes/CMakeLists.txt index cc3bd94479..23f862caa5 100644 --- a/spikes/CMakeLists.txt +++ b/spikes/CMakeLists.txt @@ -13,6 +13,7 @@ add_subdirectory(${SPIKES_DIR}/lk_command_kit) add_subdirectory(${SPIKES_DIR}/lk_config_kit) add_subdirectory(${SPIKES_DIR}/lk_coreled) add_subdirectory(${SPIKES_DIR}/lk_core_touch_sensor) +add_subdirectory(${SPIKES_DIR}/lk_dac) add_subdirectory(${SPIKES_DIR}/lk_event_queue) add_subdirectory(${SPIKES_DIR}/lk_file_reception) add_subdirectory(${SPIKES_DIR}/lk_file_manager_kit) @@ -57,6 +58,7 @@ add_dependencies(spikes_leka spike_lk_command_kit spike_lk_coreled spike_lk_core_touch_sensor + spike_lk_dac spike_lk_event_queue spike_lk_file_reception spike_lk_file_manager_kit diff --git a/spikes/lk_dac/CMakeLists.txt b/spikes/lk_dac/CMakeLists.txt new file mode 100644 index 0000000000..0de1b5fb64 --- /dev/null +++ b/spikes/lk_dac/CMakeLists.txt @@ -0,0 +1,22 @@ +# Leka - LekaOS +# Copyright 2024 APF France handicap +# SPDX-License-Identifier: Apache-2.0 + +add_mbed_executable(spike_lk_dac) + +target_include_directories(spike_lk_dac + PRIVATE + . +) + +target_sources(spike_lk_dac + PRIVATE + main.cpp +) + +target_link_libraries(spike_lk_dac + CoreSTM32Hal + CoreDAC +) + +target_link_custom_leka_targets(spike_lk_dac) diff --git a/spikes/lk_dac/main.cpp b/spikes/lk_dac/main.cpp new file mode 100644 index 0000000000..2b1cdf3d48 --- /dev/null +++ b/spikes/lk_dac/main.cpp @@ -0,0 +1,72 @@ +// Leka - LekaOS +// Copyright 2024 APF France handicap +// SPDX-License-Identifier: Apache-2.0 + +#include + +#include "rtos/ThisThread.h" + +#include "CoreDAC.h" +#include "CoreSTM32Hal.h" +#include "CoreSTM32HalBasicTimer.h" +#include "DigitalOut.h" +#include "LogKit.h" + +using namespace leka; +using namespace std::chrono_literals; + +auto hal = CoreSTM32Hal {}; +auto hal_timer = CoreSTM32HalBasicTimer {hal}; +auto coredac = CoreDAC {hal, hal_timer}; + +auto audio_enable = mbed::DigitalOut {SOUND_ENABLE, 1}; + +constexpr uint32_t sample_rate_hz = 44'100; +constexpr auto coefficient = 10; + +void fillBufferWithSinWave(uint16_t *buffer, uint32_t samples_per_period, uint16_t maxValue, uint16_t minValue) +{ + auto resolution = 2.0 * M_PI / samples_per_period; + + auto sin0_1 = [](double value) { return (sin(value) + 1.0) / 2.0; }; + auto normalization = [maxValue, minValue](double standard_value) { + return standard_value * (maxValue - minValue) + minValue; + }; + + for (uint32_t sample = 0; sample < samples_per_period; sample += coefficient) { + auto standard_value = sin0_1(sample * resolution); + auto normalized_value = normalization(standard_value); + std::fill_n(buffer + sample, coefficient, static_cast(normalized_value)); + } +} + +auto main() -> int +{ + logger::init(); + + log_info("Hello, World!\n\n"); + + hal_timer.initialize(sample_rate_hz * coefficient); + coredac.initialize(); + + const uint32_t frequency = 440; + const uint16_t maxVal = 0xFFF; + const uint16_t minVal = 0x000; + std::array buffer {}; + fillBufferWithSinWave(buffer.data(), buffer.size(), maxVal, minVal); + + coredac.registerDataToPlay(buffer); + + log_info("buffer size: %d", buffer.size()); + log_info("Start sound"); + coredac.start(); + + rtos::ThisThread::sleep_for(1s); + + log_info("Stop sound"); + coredac.stop(); + + while (true) { + rtos::ThisThread::sleep_for(1min); + } +} From 27459f75816dc8439bf69501431699721d94b405 Mon Sep 17 00:00:00 2001 From: Yann Locatelli Date: Mon, 4 Mar 2024 15:39:04 +0100 Subject: [PATCH 04/18] Update lk_audio spike --- include/interface/platform/File.h | 2 + libs/FileManagerKit/include/FileManagerKit.h | 2 + libs/FileManagerKit/source/File.cpp | 5 + spikes/lk_audio/AudioKit.cpp | 1 + spikes/lk_audio/AudioKit.h | 5 + spikes/lk_audio/CMakeLists.txt | 5 + spikes/lk_audio/WavFile.cpp | 1 + spikes/lk_audio/WavFile.h | 5 + spikes/lk_audio/WavReader.cpp | 1 + spikes/lk_audio/WavReader.h | 5 + spikes/lk_audio/main.cpp | 137 ++++++++++++------- 11 files changed, 121 insertions(+), 48 deletions(-) create mode 100644 spikes/lk_audio/AudioKit.cpp create mode 100644 spikes/lk_audio/AudioKit.h create mode 100644 spikes/lk_audio/WavFile.cpp create mode 100644 spikes/lk_audio/WavFile.h create mode 100644 spikes/lk_audio/WavReader.cpp create mode 100644 spikes/lk_audio/WavReader.h diff --git a/include/interface/platform/File.h b/include/interface/platform/File.h index b991d7e40b..9e9e24c720 100644 --- a/include/interface/platform/File.h +++ b/include/interface/platform/File.h @@ -21,6 +21,8 @@ struct File { virtual auto read(std::span buffer) -> std::size_t = 0; virtual auto write(std::span data) -> std::size_t = 0; + virtual auto read(std::span buffer) -> std::size_t = 0; + virtual auto read(std::span buffer) -> std::size_t = 0; virtual auto write(std::span data) -> std::size_t = 0; diff --git a/libs/FileManagerKit/include/FileManagerKit.h b/libs/FileManagerKit/include/FileManagerKit.h index b519adeddc..660d165f4d 100644 --- a/libs/FileManagerKit/include/FileManagerKit.h +++ b/libs/FileManagerKit/include/FileManagerKit.h @@ -25,6 +25,8 @@ struct File : public interface::File, public mbed::NonCopyable { auto read(std::span buffer) -> std::size_t final; auto write(std::span data) -> std::size_t final; + auto read(std::span buffer) -> std::size_t final; + auto read(std::span buffer) -> std::size_t final; auto write(std::span data) -> std::size_t final; diff --git a/libs/FileManagerKit/source/File.cpp b/libs/FileManagerKit/source/File.cpp index ba30698850..9d376a30d4 100644 --- a/libs/FileManagerKit/source/File.cpp +++ b/libs/FileManagerKit/source/File.cpp @@ -60,6 +60,11 @@ auto File::read(std::span buffer) -> std::size_t return std::fread(buffer.data(), sizeof(uint8_t), buffer.size(), _file.get()); } +auto File::read(std::span buffer) -> std::size_t +{ + return std::fread(buffer.data(), sizeof(uint16_t), buffer.size(), _file.get()); +} + auto File::write(std::span data) -> std::size_t { return std::fwrite(data.data(), sizeof(uint8_t), data.size(), _file.get()); diff --git a/spikes/lk_audio/AudioKit.cpp b/spikes/lk_audio/AudioKit.cpp new file mode 100644 index 0000000000..fdac1d50b2 --- /dev/null +++ b/spikes/lk_audio/AudioKit.cpp @@ -0,0 +1 @@ +#include "AudioKit.h" diff --git a/spikes/lk_audio/AudioKit.h b/spikes/lk_audio/AudioKit.h new file mode 100644 index 0000000000..273e74391c --- /dev/null +++ b/spikes/lk_audio/AudioKit.h @@ -0,0 +1,5 @@ +// Leka - LekaOS +// Copyright 2024 APF France handicap +// SPDX-License-Identifier: Apache-2.0 + +#pragma once diff --git a/spikes/lk_audio/CMakeLists.txt b/spikes/lk_audio/CMakeLists.txt index afa028ed84..33b5b44844 100644 --- a/spikes/lk_audio/CMakeLists.txt +++ b/spikes/lk_audio/CMakeLists.txt @@ -12,9 +12,14 @@ target_include_directories(spike_lk_audio target_sources(spike_lk_audio PRIVATE main.cpp + WavFile.cpp + WavReader.cpp + AudioKit.cpp ) target_link_libraries(spike_lk_audio + CoreSTM32Hal + CoreDAC FileManagerKit ) diff --git a/spikes/lk_audio/WavFile.cpp b/spikes/lk_audio/WavFile.cpp new file mode 100644 index 0000000000..0df933a2b8 --- /dev/null +++ b/spikes/lk_audio/WavFile.cpp @@ -0,0 +1 @@ +#include "WavFile.h" diff --git a/spikes/lk_audio/WavFile.h b/spikes/lk_audio/WavFile.h new file mode 100644 index 0000000000..273e74391c --- /dev/null +++ b/spikes/lk_audio/WavFile.h @@ -0,0 +1,5 @@ +// Leka - LekaOS +// Copyright 2024 APF France handicap +// SPDX-License-Identifier: Apache-2.0 + +#pragma once diff --git a/spikes/lk_audio/WavReader.cpp b/spikes/lk_audio/WavReader.cpp new file mode 100644 index 0000000000..21637eed4c --- /dev/null +++ b/spikes/lk_audio/WavReader.cpp @@ -0,0 +1 @@ +#include "WavReader.h" diff --git a/spikes/lk_audio/WavReader.h b/spikes/lk_audio/WavReader.h new file mode 100644 index 0000000000..273e74391c --- /dev/null +++ b/spikes/lk_audio/WavReader.h @@ -0,0 +1,5 @@ +// Leka - LekaOS +// Copyright 2024 APF France handicap +// SPDX-License-Identifier: Apache-2.0 + +#pragma once diff --git a/spikes/lk_audio/main.cpp b/spikes/lk_audio/main.cpp index 3483f70263..7ea7281aff 100644 --- a/spikes/lk_audio/main.cpp +++ b/spikes/lk_audio/main.cpp @@ -1,16 +1,15 @@ // Leka - LekaOS -// Copyright 2022 APF France handicap +// Copyright 2024 APF France handicap // SPDX-License-Identifier: Apache-2.0 -#include -#include +#include -#include "drivers/AnalogOut.h" -#include "drivers/DigitalOut.h" -#include "platform/mbed_wait_api.h" #include "rtos/ThisThread.h" -#include "rtos/Thread.h" +#include "CoreDAC.h" +#include "CoreSTM32Hal.h" +#include "CoreSTM32HalBasicTimer.h" +#include "DigitalOut.h" #include "FATFileSystem.h" #include "FileManagerKit.h" #include "LogKit.h" @@ -19,69 +18,111 @@ using namespace leka; using namespace std::chrono_literals; -auto sd_bd = SDBlockDevice {SD_SPI_MOSI, SD_SPI_MISO, SD_SPI_SCK}; -auto fatfs = FATFileSystem {"fs"}; +auto hal = CoreSTM32Hal {}; +auto hal_timer = CoreSTM32HalBasicTimer {hal}; +auto coredac = CoreDAC {hal, hal_timer}; -const auto sound_file_path = std::filesystem::path {"/fs/home/wav/fur-elise.wav"}; -auto file = FileManagerKit::File {sound_file_path}; +auto audio_enable = mbed::DigitalOut {SOUND_ENABLE, 1}; -auto thread_audio = rtos::Thread {}; +constexpr uint32_t sample_rate_hz = 44'100; -auto audio_enable = mbed::DigitalOut {SOUND_ENABLE, 1}; -auto audio_output = mbed::AnalogOut {MCU_SOUND_OUT}; +auto sd_blockdevice = SDBlockDevice {SD_SPI_MOSI, SD_SPI_MISO, SD_SPI_SCK}; +auto fatfs = FATFileSystem {"fs"}; + +auto file = FileManagerKit::File {}; + +const auto sound_file_path = std::filesystem::path {"/fs/home/wav/fur-elise.wav"}; void initializeSD() { - constexpr auto default_sd_bd_frequency = uint64_t {25'000'000}; + constexpr auto default_sd_blockdevice_frequency = uint64_t {25'000'000}; - sd_bd.init(); - sd_bd.frequency(default_sd_bd_frequency); + sd_blockdevice.init(); + sd_blockdevice.frequency(default_sd_blockdevice_frequency); - fatfs.mount(&sd_bd); + fatfs.mount(&sd_blockdevice); } -void playSound() -{ - static const auto _n_bytes_to_read = int {512}; // arbitrary - auto _buffer = std::array {0}; - - auto _ns_sample_rate = uint32_t {22676}; // 1,000,000,000 / 44,100 (in ns) - auto _ns_sample_rate_adapted = _ns_sample_rate * 1.7; // arbitrary, 1s in MCU is not exactly 1s in real life - auto bytesread = uint32_t {_n_bytes_to_read}; - - /* START READ WAV */ - while (bytesread == _n_bytes_to_read) { - // Read "_n_bytes_to_read" from file at each iteration. Real bytes read is given by "bytesread" - if (bytesread = file.read(_buffer.data(), _n_bytes_to_read); bytesread != 0) { - // Play every 2-bytes (sound encoded in 16 bits) - for (uint32_t j = 0; j < bytesread; j += 4) { // Play one channel, data for stereo are alternate - audio_output.write_u16((_buffer.at(j + 1) + 0x8000) >> - 1); // offset for int16 data (0x8000) and volume 50% (>>1) - - wait_ns(_ns_sample_rate_adapted); // adjust play speed - } - } - } - /* END READ WAV*/ -} +// constexpr auto size = 128; +// constexpr auto size = 256; +// constexpr auto size = 512; +// constexpr auto size = 1'024; +// constexpr auto size = 2'048; +// constexpr auto size = 4'096; +// constexpr auto size = 8'192; +// constexpr auto size = 16'384; +constexpr auto size = 32'768; +// constexpr auto size = 65'536; // NOK +std::array data_file {}; +std::array data_play {}; auto main() -> int { logger::init(); log_info("Hello, World!\n\n"); + rtos::ThisThread::sleep_for(1s); initializeSD(); - if (FileManagerKit::file_is_missing(sound_file_path)) { return 1; } - while (true) { - file.open(sound_file_path); - playSound(); - file.close(); + // BEGIN -- NEW CODE + + log_info("Initialize"); + rtos::ThisThread::sleep_for(1s); + + auto file = FileManagerKit::File {sound_file_path}; - rtos::ThisThread::sleep_for(1s); + file.read(data_file); + for (int index = 0; index < data_file.size(); index += 2) { + data_play[index / 2] = (data_file[index + 1] << 8) | data_file[index]; + // data_play[index / 2] = (data_file[index] << 8) | data_file[index + 1]; + } + + // for (auto one_data: data_play) { + // printf("%04x", one_data); + // } + // printf("\n"); + + coredac.registerDMACallbacks( + [&file] { + // Fill first half + std::array data_first_half {}; + file.read(data_first_half); // THIS FAIL + + // for (int index = 0; index < data_file.size(); index += 2) { + // data_play[index / 2] = (data_file[index + 1] << 8) | data_file[index]; + // } + }, + [&file] { + // Fill second half + + // file.read(data_file); + // for (int index = 0; index < data_file.size(); index += 2) { + // data_play[size / 2 + index / 2] = (data_file[index + 1] << 8) | data_file[index]; + // } + }); + + hal_timer.initialize(sample_rate_hz); + coredac.initialize(); + + coredac.registerDataToPlay(data_play); + // Play on audio + + log_info("Start sound"); + rtos::ThisThread::sleep_for(1s); + + // END -- NEW CODE + coredac.start(); + + rtos::ThisThread::sleep_for(1s); + + log_info("Stop sound"); + coredac.stop(); + + while (true) { + rtos::ThisThread::sleep_for(1min); } } From 930667abcb01691bb078d0f572897b86ec82a39f Mon Sep 17 00:00:00 2001 From: Yann Locatelli Date: Tue, 5 Mar 2024 18:33:02 +0100 Subject: [PATCH 05/18] tmp --- spikes/lk_audio/CMakeLists.txt | 1 + spikes/lk_audio/main.cpp | 66 +++++++++++++++++----------------- 2 files changed, 35 insertions(+), 32 deletions(-) diff --git a/spikes/lk_audio/CMakeLists.txt b/spikes/lk_audio/CMakeLists.txt index 33b5b44844..0a4eefdc7b 100644 --- a/spikes/lk_audio/CMakeLists.txt +++ b/spikes/lk_audio/CMakeLists.txt @@ -21,6 +21,7 @@ target_link_libraries(spike_lk_audio CoreSTM32Hal CoreDAC FileManagerKit + CoreEventQueue ) target_link_custom_leka_targets(spike_lk_audio) diff --git a/spikes/lk_audio/main.cpp b/spikes/lk_audio/main.cpp index 7ea7281aff..7bb2f64bbf 100644 --- a/spikes/lk_audio/main.cpp +++ b/spikes/lk_audio/main.cpp @@ -7,6 +7,7 @@ #include "rtos/ThisThread.h" #include "CoreDAC.h" +#include "CoreEventQueue.h" #include "CoreSTM32Hal.h" #include "CoreSTM32HalBasicTimer.h" #include "DigitalOut.h" @@ -26,12 +27,13 @@ auto audio_enable = mbed::DigitalOut {SOUND_ENABLE, 1}; constexpr uint32_t sample_rate_hz = 44'100; +auto event_queue = CoreEventQueue {}; + auto sd_blockdevice = SDBlockDevice {SD_SPI_MOSI, SD_SPI_MISO, SD_SPI_SCK}; auto fatfs = FATFileSystem {"fs"}; -auto file = FileManagerKit::File {}; - const auto sound_file_path = std::filesystem::path {"/fs/home/wav/fur-elise.wav"}; +auto file = FileManagerKit::File {}; void initializeSD() { @@ -56,6 +58,28 @@ constexpr auto size = 32'768; std::array data_file {}; std::array data_play {}; +void setData(uint16_t offset) +{ + file.read(data_file); + for (uint32_t index = 0; index < data_file.size(); index += 2) { + // data_play.at(offset + index / 2) = (data_file[index + 1] << 8) | data_file[index]; + // data_play[offset + index / 2] = (data_file[index] << 8) | data_file[index + 1]; + + data_play.at(offset + index / 2) = (data_file.at(index + 1) + 0x8000) >> 0; + } +} + +void onHalfTransfer() +{ + // Fill first half + setData(0); +} +void onCompleteTransfer() +{ + // Fill second half + setData(size / 2); +} + auto main() -> int { logger::init(); @@ -63,6 +87,8 @@ auto main() -> int log_info("Hello, World!\n\n"); rtos::ThisThread::sleep_for(1s); + event_queue.dispatch_forever(); + initializeSD(); if (FileManagerKit::file_is_missing(sound_file_path)) { return 1; @@ -73,37 +99,13 @@ auto main() -> int log_info("Initialize"); rtos::ThisThread::sleep_for(1s); - auto file = FileManagerKit::File {sound_file_path}; + file.open(sound_file_path); - file.read(data_file); - for (int index = 0; index < data_file.size(); index += 2) { - data_play[index / 2] = (data_file[index + 1] << 8) | data_file[index]; - // data_play[index / 2] = (data_file[index] << 8) | data_file[index + 1]; - } + setData(0); + setData(size / 2); - // for (auto one_data: data_play) { - // printf("%04x", one_data); - // } - // printf("\n"); - - coredac.registerDMACallbacks( - [&file] { - // Fill first half - std::array data_first_half {}; - file.read(data_first_half); // THIS FAIL - - // for (int index = 0; index < data_file.size(); index += 2) { - // data_play[index / 2] = (data_file[index + 1] << 8) | data_file[index]; - // } - }, - [&file] { - // Fill second half - - // file.read(data_file); - // for (int index = 0; index < data_file.size(); index += 2) { - // data_play[size / 2 + index / 2] = (data_file[index + 1] << 8) | data_file[index]; - // } - }); + coredac.registerDMACallbacks([] { event_queue.call(onHalfTransfer); }, + [] { event_queue.call(onCompleteTransfer); }); hal_timer.initialize(sample_rate_hz); coredac.initialize(); @@ -117,7 +119,7 @@ auto main() -> int // END -- NEW CODE coredac.start(); - rtos::ThisThread::sleep_for(1s); + rtos::ThisThread::sleep_for(5s); log_info("Stop sound"); coredac.stop(); From fba88b4a28d3f412d161f88605d5e7ed0943d01c Mon Sep 17 00:00:00 2001 From: Yann Locatelli Date: Wed, 6 Mar 2024 15:11:00 +0100 Subject: [PATCH 06/18] closer --- spikes/lk_audio/main.cpp | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/spikes/lk_audio/main.cpp b/spikes/lk_audio/main.cpp index 7bb2f64bbf..718b974a77 100644 --- a/spikes/lk_audio/main.cpp +++ b/spikes/lk_audio/main.cpp @@ -52,20 +52,27 @@ void initializeSD() // constexpr auto size = 2'048; // constexpr auto size = 4'096; // constexpr auto size = 8'192; -// constexpr auto size = 16'384; -constexpr auto size = 32'768; +constexpr auto size = 16'384; +// constexpr auto size = 32'768; // constexpr auto size = 65'536; // NOK std::array data_file {}; -std::array data_play {}; +std::array data_play {}; void setData(uint16_t offset) { file.read(data_file); - for (uint32_t index = 0; index < data_file.size(); index += 2) { + // for (uint32_t index = 0; index < data_file.size(); index += 2) { + // // data_play.at(offset + index / 2) = (data_file[index + 1] << 8) | data_file[index]; + // data_play[offset + index / 2] = (data_file[index] << 8) | data_file[index + 1]; + + // // data_play.at(offset + index / 2) = (data_file.at(index + 1) + 0x8000) >> 0; + // } + + for (uint32_t index = 0; index < data_file.size(); index++) { // data_play.at(offset + index / 2) = (data_file[index + 1] << 8) | data_file[index]; // data_play[offset + index / 2] = (data_file[index] << 8) | data_file[index + 1]; - data_play.at(offset + index / 2) = (data_file.at(index + 1) + 0x8000) >> 0; + data_play.at(offset + index) = (data_file.at(index) + 0x8000) >> 0; } } @@ -77,7 +84,7 @@ void onHalfTransfer() void onCompleteTransfer() { // Fill second half - setData(size / 2); + setData(size); } auto main() -> int @@ -119,7 +126,7 @@ auto main() -> int // END -- NEW CODE coredac.start(); - rtos::ThisThread::sleep_for(5s); + rtos::ThisThread::sleep_for(10s); log_info("Stop sound"); coredac.stop(); From 42ee97e65561c344886c01e7635f447293b4be68 Mon Sep 17 00:00:00 2001 From: Yann Locatelli Date: Wed, 6 Mar 2024 16:38:21 +0100 Subject: [PATCH 07/18] some test --- drivers/CoreDAC/source/CoreDAC.cpp | 8 ++++ .../CoreDAC/source/CoreSTM32HalBasicTimer.cpp | 40 ++++++++++++++----- libs/FileManagerKit/include/FileManagerKit.h | 2 + libs/FileManagerKit/source/File.cpp | 5 +++ spikes/lk_audio/main.cpp | 26 ++++++------ 5 files changed, 59 insertions(+), 22 deletions(-) diff --git a/drivers/CoreDAC/source/CoreDAC.cpp b/drivers/CoreDAC/source/CoreDAC.cpp index c3a28f899e..4a95000da5 100644 --- a/drivers/CoreDAC/source/CoreDAC.cpp +++ b/drivers/CoreDAC/source/CoreDAC.cpp @@ -18,6 +18,14 @@ auto CoreDAC::getHandle() -> DAC_HandleTypeDef & void CoreDAC::initialize() { + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOA_CLK_ENABLE(); + GPIO_InitTypeDef GPIO_InitStruct = {0}; + GPIO_InitStruct.Pin = GPIO_PIN_4; + GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; + GPIO_InitStruct.Pull = GPIO_NOPULL; + _hal.HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + _registerMspCallbacks(); _hal.HAL_DAC_Init(&_hdac); diff --git a/drivers/CoreDAC/source/CoreSTM32HalBasicTimer.cpp b/drivers/CoreDAC/source/CoreSTM32HalBasicTimer.cpp index bb54da1113..e6252de611 100644 --- a/drivers/CoreDAC/source/CoreSTM32HalBasicTimer.cpp +++ b/drivers/CoreDAC/source/CoreSTM32HalBasicTimer.cpp @@ -5,6 +5,8 @@ #include "CoreSTM32HalBasicTimer.h" #include +#include "LogKit.h" + using namespace leka; CoreSTM32HalBasicTimer::CoreSTM32HalBasicTimer(interface::STM32Hal &hal) : _hal(hal) @@ -35,16 +37,34 @@ void CoreSTM32HalBasicTimer::initialize(float frequency) _htim.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; _hal.HAL_TIM_Base_Init(&_htim); + auto _calculatePeriod = [](uint32_t frequency) { + uint32_t clockFreq = HAL_RCC_GetPCLK1Freq(); + + /* Get PCLK1 prescaler */ + if ((RCC->CFGR & RCC_CFGR_PPRE1) != 0) { + clockFreq *= 2; + } + + if (frequency < (clockFreq >> 16) || frequency > clockFreq) { + log_error("Chosen freq out of bounds\n"); + } + + return (clockFreq / frequency); + }; + auto periodCalculated = _calculatePeriod(frequency); + + log_info("divider: %ld, prescaler: %ld, calculated: %ld", divider, _htim.Init.Prescaler, periodCalculated); + auto timerMasterConfig = TIM_MasterConfigTypeDef {}; timerMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE; + timerMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; _hal.HAL_TIMEx_MasterConfigSynchronization(&_htim, &timerMasterConfig); - static const auto &self = *this; - _hal.HAL_TIM_RegisterCallback(&_htim, HAL_TIM_PERIOD_ELAPSED_CB_ID, []([[maybe_unused]] TIM_HandleTypeDef *htim) { - if (self._callback != nullptr) { - self._callback(); - } - }); + // static const auto &self = *this; + // _hal.HAL_TIM_RegisterCallback(&_htim, HAL_TIM_PERIOD_ELAPSED_CB_ID, []([[maybe_unused]] TIM_HandleTypeDef *htim) + // { if (self._callback != nullptr) { self._callback(); + // } + // }); } void CoreSTM32HalBasicTimer::_registerMspCallbacks() @@ -54,13 +74,13 @@ void CoreSTM32HalBasicTimer::_registerMspCallbacks() _hal.HAL_TIM_RegisterCallback(&_htim, HAL_TIM_BASE_MSPINIT_CB_ID, []([[maybe_unused]] TIM_HandleTypeDef *htim) { self._hal.HAL_RCC_TIM6_CLK_ENABLE(); - self._hal.HAL_NVIC_SetPriority(TIM6_DAC_IRQn, 0x00, 0x00); + self._hal.HAL_NVIC_SetPriority(TIM6_DAC_IRQn, 0x01, 0x00); self._hal.HAL_NVIC_EnableIRQ(TIM6_DAC_IRQn); }); - _hal.HAL_TIM_RegisterCallback(&_htim, HAL_TIM_BASE_MSPDEINIT_CB_ID, []([[maybe_unused]] TIM_HandleTypeDef *htim) { - self._hal.HAL_RCC_TIM6_CLK_DISABLE(); - }); + // _hal.HAL_TIM_RegisterCallback(&_htim, HAL_TIM_BASE_MSPDEINIT_CB_ID, []([[maybe_unused]] TIM_HandleTypeDef *htim) + // { self._hal.HAL_RCC_TIM6_CLK_DISABLE(); + // }); } void CoreSTM32HalBasicTimer::linkDACTimer(DAC_ChannelConfTypeDef *config) diff --git a/libs/FileManagerKit/include/FileManagerKit.h b/libs/FileManagerKit/include/FileManagerKit.h index 660d165f4d..88c88dfd00 100644 --- a/libs/FileManagerKit/include/FileManagerKit.h +++ b/libs/FileManagerKit/include/FileManagerKit.h @@ -33,6 +33,8 @@ struct File : public interface::File, public mbed::NonCopyable { auto read(uint8_t *buffer, uint32_t size) -> std::size_t final; auto write(const uint8_t *data, uint32_t size) -> std::size_t final; + auto read(uint16_t *buffer, uint32_t size) -> std::size_t; + auto read(char *buffer, uint32_t size) -> std::size_t final; auto write(const char *data, uint32_t size) -> std::size_t final; diff --git a/libs/FileManagerKit/source/File.cpp b/libs/FileManagerKit/source/File.cpp index 9d376a30d4..04a17922f4 100644 --- a/libs/FileManagerKit/source/File.cpp +++ b/libs/FileManagerKit/source/File.cpp @@ -85,6 +85,11 @@ auto File::read(uint8_t *buffer, uint32_t size) -> std::size_t return std::fread(buffer, sizeof(uint8_t), size, _file.get()); } +auto File::read(uint16_t *buffer, uint32_t size) -> std::size_t +{ + return std::fread(buffer, sizeof(uint16_t), size, _file.get()); +} + auto File::write(const uint8_t *data, uint32_t size) -> std::size_t { return std::fwrite(data, sizeof(uint8_t), size, _file.get()); diff --git a/spikes/lk_audio/main.cpp b/spikes/lk_audio/main.cpp index 718b974a77..3cc8cdad7f 100644 --- a/spikes/lk_audio/main.cpp +++ b/spikes/lk_audio/main.cpp @@ -60,20 +60,22 @@ std::array data_play {}; void setData(uint16_t offset) { - file.read(data_file); - // for (uint32_t index = 0; index < data_file.size(); index += 2) { - // // data_play.at(offset + index / 2) = (data_file[index + 1] << 8) | data_file[index]; - // data_play[offset + index / 2] = (data_file[index] << 8) | data_file[index + 1]; + file.read(data_play.data() + offset, size); - // // data_play.at(offset + index / 2) = (data_file.at(index + 1) + 0x8000) >> 0; - // } + // file.read(data_file); + // // for (uint32_t index = 0; index < data_file.size(); index += 2) { + // // // data_play.at(offset + index / 2) = (data_file[index + 1] << 8) | data_file[index]; + // // data_play[offset + index / 2] = (data_file[index] << 8) | data_file[index + 1]; - for (uint32_t index = 0; index < data_file.size(); index++) { - // data_play.at(offset + index / 2) = (data_file[index + 1] << 8) | data_file[index]; - // data_play[offset + index / 2] = (data_file[index] << 8) | data_file[index + 1]; + // // // data_play.at(offset + index / 2) = (data_file.at(index + 1) + 0x8000) >> 0; + // // } - data_play.at(offset + index) = (data_file.at(index) + 0x8000) >> 0; - } + // for (uint32_t index = 0; index < data_file.size(); index++) { + // // data_play.at(offset + index / 2) = (data_file[index + 1] << 8) | data_file[index]; + // // data_play[offset + index / 2] = (data_file[index] << 8) | data_file[index + 1]; + + // data_play.at(offset + index) = data_file.at(index) + 0x8000; + // } } void onHalfTransfer() @@ -114,7 +116,7 @@ auto main() -> int coredac.registerDMACallbacks([] { event_queue.call(onHalfTransfer); }, [] { event_queue.call(onCompleteTransfer); }); - hal_timer.initialize(sample_rate_hz); + hal_timer.initialize(116'000); // 116'883 coredac.initialize(); coredac.registerDataToPlay(data_play); From 770af35a684c5f6a52fbb4743f6711f88b7285b2 Mon Sep 17 00:00:00 2001 From: Yann Locatelli Date: Wed, 6 Mar 2024 17:44:10 +0100 Subject: [PATCH 08/18] functional --- drivers/CoreDAC/source/CoreDAC.cpp | 8 -------- drivers/CoreDAC/source/CoreSTM32HalBasicTimer.cpp | 8 ++++---- drivers/CoreDAC/source/HAL_IRQHandlers.cpp | 6 +++++- 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/drivers/CoreDAC/source/CoreDAC.cpp b/drivers/CoreDAC/source/CoreDAC.cpp index 4a95000da5..c3a28f899e 100644 --- a/drivers/CoreDAC/source/CoreDAC.cpp +++ b/drivers/CoreDAC/source/CoreDAC.cpp @@ -18,14 +18,6 @@ auto CoreDAC::getHandle() -> DAC_HandleTypeDef & void CoreDAC::initialize() { - __HAL_RCC_GPIOA_CLK_ENABLE(); - __HAL_RCC_GPIOA_CLK_ENABLE(); - GPIO_InitTypeDef GPIO_InitStruct = {0}; - GPIO_InitStruct.Pin = GPIO_PIN_4; - GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; - GPIO_InitStruct.Pull = GPIO_NOPULL; - _hal.HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); - _registerMspCallbacks(); _hal.HAL_DAC_Init(&_hdac); diff --git a/drivers/CoreDAC/source/CoreSTM32HalBasicTimer.cpp b/drivers/CoreDAC/source/CoreSTM32HalBasicTimer.cpp index e6252de611..77d3fe5a38 100644 --- a/drivers/CoreDAC/source/CoreSTM32HalBasicTimer.cpp +++ b/drivers/CoreDAC/source/CoreSTM32HalBasicTimer.cpp @@ -74,13 +74,13 @@ void CoreSTM32HalBasicTimer::_registerMspCallbacks() _hal.HAL_TIM_RegisterCallback(&_htim, HAL_TIM_BASE_MSPINIT_CB_ID, []([[maybe_unused]] TIM_HandleTypeDef *htim) { self._hal.HAL_RCC_TIM6_CLK_ENABLE(); - self._hal.HAL_NVIC_SetPriority(TIM6_DAC_IRQn, 0x01, 0x00); + self._hal.HAL_NVIC_SetPriority(TIM6_DAC_IRQn, 0x00, 0x00); self._hal.HAL_NVIC_EnableIRQ(TIM6_DAC_IRQn); }); - // _hal.HAL_TIM_RegisterCallback(&_htim, HAL_TIM_BASE_MSPDEINIT_CB_ID, []([[maybe_unused]] TIM_HandleTypeDef *htim) - // { self._hal.HAL_RCC_TIM6_CLK_DISABLE(); - // }); + _hal.HAL_TIM_RegisterCallback(&_htim, HAL_TIM_BASE_MSPDEINIT_CB_ID, []([[maybe_unused]] TIM_HandleTypeDef *htim) { + self._hal.HAL_RCC_TIM6_CLK_DISABLE(); + }); } void CoreSTM32HalBasicTimer::linkDACTimer(DAC_ChannelConfTypeDef *config) diff --git a/drivers/CoreDAC/source/HAL_IRQHandlers.cpp b/drivers/CoreDAC/source/HAL_IRQHandlers.cpp index 31ae2946df..22fbb79217 100644 --- a/drivers/CoreDAC/source/HAL_IRQHandlers.cpp +++ b/drivers/CoreDAC/source/HAL_IRQHandlers.cpp @@ -8,7 +8,11 @@ extern leka::CoreDAC coredac; void TIM6_DAC_IRQHandler() { - HAL_TIM_IRQHandler(&hal_timer.getHandle()); + TIM6->SR = ~TIM_SR_UIF; + // GPIOG->ODR ^= (1 << 6); + // HAL_TIM_IRQHandler(&hal_timer.getHandle()); + // have to be replace + // https://stackoverflow.com/questions/56995426/issue-with-frequency-limitation-on-the-timers-on-stm32f7 } void TIM7_DAC_IRQHandler() From 6137360a94c169b91476c1e3fa562d99c8f2edae Mon Sep 17 00:00:00 2001 From: Yann Locatelli Date: Thu, 7 Mar 2024 12:22:11 +0100 Subject: [PATCH 09/18] tmp --- spikes/lk_dac/main.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/spikes/lk_dac/main.cpp b/spikes/lk_dac/main.cpp index 2b1cdf3d48..b6c6411144 100644 --- a/spikes/lk_dac/main.cpp +++ b/spikes/lk_dac/main.cpp @@ -34,9 +34,15 @@ void fillBufferWithSinWave(uint16_t *buffer, uint32_t samples_per_period, uint16 }; for (uint32_t sample = 0; sample < samples_per_period; sample += coefficient) { - auto standard_value = sin0_1(sample * resolution); - auto normalized_value = normalization(standard_value); - std::fill_n(buffer + sample, coefficient, static_cast(normalized_value)); + if (sample < samples_per_period / 2) { + std::fill_n(buffer + sample, coefficient, maxValue); + } else { + std::fill_n(buffer + sample, coefficient, minValue); + } + + // auto standard_value = sin0_1(sample * resolution); + // auto normalized_value = normalization(standard_value); + // std::fill_n(buffer + sample, coefficient, static_cast(normalized_value)); } } From de5b722537c93d6940294e8b1cf82ed9ad9479d2 Mon Sep 17 00:00:00 2001 From: Yann Locatelli Date: Fri, 8 Mar 2024 15:21:05 +0100 Subject: [PATCH 10/18] essai diff config --- drivers/CoreDAC/source/CoreDAC.cpp | 2 +- .../CoreDAC/source/CoreSTM32HalBasicTimer.cpp | 2 +- include/interface/platform/File.h | 2 +- libs/FileManagerKit/include/FileManagerKit.h | 4 +-- libs/FileManagerKit/source/File.cpp | 8 +++--- spikes/lk_audio/main.cpp | 22 +++++++++++----- spikes/lk_dac/CMakeLists.txt | 1 + spikes/lk_dac/main.cpp | 26 ++++++++++++++++--- 8 files changed, 48 insertions(+), 19 deletions(-) diff --git a/drivers/CoreDAC/source/CoreDAC.cpp b/drivers/CoreDAC/source/CoreDAC.cpp index c3a28f899e..33ff3d1fb8 100644 --- a/drivers/CoreDAC/source/CoreDAC.cpp +++ b/drivers/CoreDAC/source/CoreDAC.cpp @@ -23,7 +23,7 @@ void CoreDAC::initialize() _hal.HAL_DAC_Init(&_hdac); DAC_ChannelConfTypeDef config = {}; - config.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE; + config.DAC_OutputBuffer = DAC_OUTPUTBUFFER_DISABLE; _hal_timer.linkDACTimer(&config); _hal.HAL_DAC_ConfigChannel(&_hdac, &config, DAC_CHANNEL_1); diff --git a/drivers/CoreDAC/source/CoreSTM32HalBasicTimer.cpp b/drivers/CoreDAC/source/CoreSTM32HalBasicTimer.cpp index 77d3fe5a38..a122c313ab 100644 --- a/drivers/CoreDAC/source/CoreSTM32HalBasicTimer.cpp +++ b/drivers/CoreDAC/source/CoreSTM32HalBasicTimer.cpp @@ -34,7 +34,7 @@ void CoreSTM32HalBasicTimer::initialize(float frequency) _htim.Init.Prescaler = 0; _htim.Init.Period = divider - 1; // ? min 1 - _htim.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; + _htim.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE; _hal.HAL_TIM_Base_Init(&_htim); auto _calculatePeriod = [](uint32_t frequency) { diff --git a/include/interface/platform/File.h b/include/interface/platform/File.h index 9e9e24c720..df16153fc1 100644 --- a/include/interface/platform/File.h +++ b/include/interface/platform/File.h @@ -21,7 +21,7 @@ struct File { virtual auto read(std::span buffer) -> std::size_t = 0; virtual auto write(std::span data) -> std::size_t = 0; - virtual auto read(std::span buffer) -> std::size_t = 0; + virtual auto read(std::span buffer) -> std::size_t = 0; virtual auto read(std::span buffer) -> std::size_t = 0; virtual auto write(std::span data) -> std::size_t = 0; diff --git a/libs/FileManagerKit/include/FileManagerKit.h b/libs/FileManagerKit/include/FileManagerKit.h index 88c88dfd00..1b42d8cad1 100644 --- a/libs/FileManagerKit/include/FileManagerKit.h +++ b/libs/FileManagerKit/include/FileManagerKit.h @@ -25,7 +25,7 @@ struct File : public interface::File, public mbed::NonCopyable { auto read(std::span buffer) -> std::size_t final; auto write(std::span data) -> std::size_t final; - auto read(std::span buffer) -> std::size_t final; + auto read(std::span buffer) -> std::size_t final; auto read(std::span buffer) -> std::size_t final; auto write(std::span data) -> std::size_t final; @@ -33,7 +33,7 @@ struct File : public interface::File, public mbed::NonCopyable { auto read(uint8_t *buffer, uint32_t size) -> std::size_t final; auto write(const uint8_t *data, uint32_t size) -> std::size_t final; - auto read(uint16_t *buffer, uint32_t size) -> std::size_t; + auto read(int16_t *buffer, uint32_t size) -> std::size_t; auto read(char *buffer, uint32_t size) -> std::size_t final; auto write(const char *data, uint32_t size) -> std::size_t final; diff --git a/libs/FileManagerKit/source/File.cpp b/libs/FileManagerKit/source/File.cpp index 04a17922f4..c4be239c15 100644 --- a/libs/FileManagerKit/source/File.cpp +++ b/libs/FileManagerKit/source/File.cpp @@ -60,9 +60,9 @@ auto File::read(std::span buffer) -> std::size_t return std::fread(buffer.data(), sizeof(uint8_t), buffer.size(), _file.get()); } -auto File::read(std::span buffer) -> std::size_t +auto File::read(std::span buffer) -> std::size_t { - return std::fread(buffer.data(), sizeof(uint16_t), buffer.size(), _file.get()); + return std::fread(buffer.data(), sizeof(int16_t), buffer.size(), _file.get()); } auto File::write(std::span data) -> std::size_t @@ -85,9 +85,9 @@ auto File::read(uint8_t *buffer, uint32_t size) -> std::size_t return std::fread(buffer, sizeof(uint8_t), size, _file.get()); } -auto File::read(uint16_t *buffer, uint32_t size) -> std::size_t +auto File::read(int16_t *buffer, uint32_t size) -> std::size_t { - return std::fread(buffer, sizeof(uint16_t), size, _file.get()); + return std::fread(buffer, sizeof(int16_t), size, _file.get()); } auto File::write(const uint8_t *data, uint32_t size) -> std::size_t diff --git a/spikes/lk_audio/main.cpp b/spikes/lk_audio/main.cpp index 3cc8cdad7f..4d4ddd0259 100644 --- a/spikes/lk_audio/main.cpp +++ b/spikes/lk_audio/main.cpp @@ -32,7 +32,7 @@ auto event_queue = CoreEventQueue {}; auto sd_blockdevice = SDBlockDevice {SD_SPI_MOSI, SD_SPI_MISO, SD_SPI_SCK}; auto fatfs = FATFileSystem {"fs"}; -const auto sound_file_path = std::filesystem::path {"/fs/home/wav/fur-elise.wav"}; +const auto sound_file_path = std::filesystem::path {"/fs/home/wav/440.wav"}; auto file = FileManagerKit::File {}; void initializeSD() @@ -48,19 +48,27 @@ void initializeSD() // constexpr auto size = 128; // constexpr auto size = 256; // constexpr auto size = 512; +constexpr auto size = 1'000; // constexpr auto size = 1'024; // constexpr auto size = 2'048; // constexpr auto size = 4'096; // constexpr auto size = 8'192; -constexpr auto size = 16'384; +// constexpr auto size = 16'384; // constexpr auto size = 32'768; // constexpr auto size = 65'536; // NOK -std::array data_file {}; -std::array data_play {}; +constexpr auto data_file_size = size / 10; +std::array data_file {}; +// std::array data_file {}; +std::array data_play {}; void setData(uint16_t offset) { - file.read(data_play.data() + offset, size); + constexpr auto adjustment = 10; // Related to ARR + file.read(data_file); + for (auto i = 0; i < data_file_size; i++) { + std::fill_n(data_play.begin() + i * adjustment, adjustment, (data_file.at(i) + 0x8000)); + } + // file.read(data_play.data() + offset, size / 2); // file.read(data_file); // // for (uint32_t index = 0; index < data_file.size(); index += 2) { @@ -109,6 +117,8 @@ auto main() -> int rtos::ThisThread::sleep_for(1s); file.open(sound_file_path); + auto header_array = std::array {}; + file.read(header_array); // header setData(0); setData(size / 2); @@ -128,7 +138,7 @@ auto main() -> int // END -- NEW CODE coredac.start(); - rtos::ThisThread::sleep_for(10s); + rtos::ThisThread::sleep_for(1min); log_info("Stop sound"); coredac.stop(); diff --git a/spikes/lk_dac/CMakeLists.txt b/spikes/lk_dac/CMakeLists.txt index 0de1b5fb64..134729c224 100644 --- a/spikes/lk_dac/CMakeLists.txt +++ b/spikes/lk_dac/CMakeLists.txt @@ -17,6 +17,7 @@ target_sources(spike_lk_dac target_link_libraries(spike_lk_dac CoreSTM32Hal CoreDAC + CoreEventQueue ) target_link_custom_leka_targets(spike_lk_dac) diff --git a/spikes/lk_dac/main.cpp b/spikes/lk_dac/main.cpp index b6c6411144..0bdb6bb1f9 100644 --- a/spikes/lk_dac/main.cpp +++ b/spikes/lk_dac/main.cpp @@ -7,6 +7,7 @@ #include "rtos/ThisThread.h" #include "CoreDAC.h" +#include "CoreEventQueue.h" #include "CoreSTM32Hal.h" #include "CoreSTM32HalBasicTimer.h" #include "DigitalOut.h" @@ -21,6 +22,8 @@ auto coredac = CoreDAC {hal, hal_timer}; auto audio_enable = mbed::DigitalOut {SOUND_ENABLE, 1}; +auto event_queue = CoreEventQueue {}; + constexpr uint32_t sample_rate_hz = 44'100; constexpr auto coefficient = 10; @@ -46,6 +49,14 @@ void fillBufferWithSinWave(uint16_t *buffer, uint32_t samples_per_period, uint16 } } +constexpr auto played_buffer_size = 256; +std::array played_buffer {}; + +void setData(uint16_t offset, uint16_t value) +{ + std::fill_n(played_buffer.begin() + offset, played_buffer_size / 2, value); +} + auto main() -> int { logger::init(); @@ -58,16 +69,23 @@ auto main() -> int const uint32_t frequency = 440; const uint16_t maxVal = 0xFFF; const uint16_t minVal = 0x000; - std::array buffer {}; + std::array buffer {}; fillBufferWithSinWave(buffer.data(), buffer.size(), maxVal, minVal); - coredac.registerDataToPlay(buffer); + event_queue.dispatch_forever(); + setData(0, minVal); + setData(played_buffer_size / 2, maxVal); + + coredac.registerDMACallbacks([] { event_queue.call([] { setData(0, minVal); }); }, + [] { event_queue.call([] { setData(played_buffer_size / 2, maxVal); }); }); + + coredac.registerDataToPlay(played_buffer); - log_info("buffer size: %d", buffer.size()); + // log_info("buffer size: %d", buffer.size()); log_info("Start sound"); coredac.start(); - rtos::ThisThread::sleep_for(1s); + rtos::ThisThread::sleep_for(4min); log_info("Stop sound"); coredac.stop(); From 4d961d9804bf7f0393845bce7fe3ba252a0ebdf7 Mon Sep 17 00:00:00 2001 From: Yann Locatelli Date: Mon, 11 Mar 2024 18:45:33 +0100 Subject: [PATCH 11/18] progression --- drivers/CoreDAC/source/CoreDAC.cpp | 2 +- .../CoreDAC/source/CoreSTM32HalBasicTimer.cpp | 3 +- spikes/lk_audio/main.cpp | 71 ++++++++++++------- spikes/lk_dac/main.cpp | 2 +- 4 files changed, 51 insertions(+), 27 deletions(-) diff --git a/drivers/CoreDAC/source/CoreDAC.cpp b/drivers/CoreDAC/source/CoreDAC.cpp index 33ff3d1fb8..c3a28f899e 100644 --- a/drivers/CoreDAC/source/CoreDAC.cpp +++ b/drivers/CoreDAC/source/CoreDAC.cpp @@ -23,7 +23,7 @@ void CoreDAC::initialize() _hal.HAL_DAC_Init(&_hdac); DAC_ChannelConfTypeDef config = {}; - config.DAC_OutputBuffer = DAC_OUTPUTBUFFER_DISABLE; + config.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE; _hal_timer.linkDACTimer(&config); _hal.HAL_DAC_ConfigChannel(&_hdac, &config, DAC_CHANNEL_1); diff --git a/drivers/CoreDAC/source/CoreSTM32HalBasicTimer.cpp b/drivers/CoreDAC/source/CoreSTM32HalBasicTimer.cpp index a122c313ab..40a68e30f3 100644 --- a/drivers/CoreDAC/source/CoreSTM32HalBasicTimer.cpp +++ b/drivers/CoreDAC/source/CoreSTM32HalBasicTimer.cpp @@ -53,7 +53,8 @@ void CoreSTM32HalBasicTimer::initialize(float frequency) }; auto periodCalculated = _calculatePeriod(frequency); - log_info("divider: %ld, prescaler: %ld, calculated: %ld", divider, _htim.Init.Prescaler, periodCalculated); + log_info("divider: %ld, prescaler: %ld, period: %ld, calculated: %ld", divider, _htim.Init.Prescaler, + _htim.Init.Period, periodCalculated); auto timerMasterConfig = TIM_MasterConfigTypeDef {}; timerMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE; diff --git a/spikes/lk_audio/main.cpp b/spikes/lk_audio/main.cpp index 4d4ddd0259..9d17f87386 100644 --- a/spikes/lk_audio/main.cpp +++ b/spikes/lk_audio/main.cpp @@ -48,7 +48,7 @@ void initializeSD() // constexpr auto size = 128; // constexpr auto size = 256; // constexpr auto size = 512; -constexpr auto size = 1'000; +constexpr auto size = 2'000; // constexpr auto size = 1'024; // constexpr auto size = 2'048; // constexpr auto size = 4'096; @@ -56,34 +56,32 @@ constexpr auto size = 1'000; // constexpr auto size = 16'384; // constexpr auto size = 32'768; // constexpr auto size = 65'536; // NOK -constexpr auto data_file_size = size / 10; +constexpr auto coefficient = 1; +constexpr auto data_file_size = size / coefficient / 2; // /2 for half buffer and *2 std::array data_file {}; // std::array data_file {}; std::array data_play {}; void setData(uint16_t offset) { - constexpr auto adjustment = 10; // Related to ARR + static constexpr auto adjustment = coefficient; // Related to ARR file.read(data_file); - for (auto i = 0; i < data_file_size; i++) { - std::fill_n(data_play.begin() + i * adjustment, adjustment, (data_file.at(i) + 0x8000)); - } - // file.read(data_play.data() + offset, size / 2); - - // file.read(data_file); - // // for (uint32_t index = 0; index < data_file.size(); index += 2) { - // // // data_play.at(offset + index / 2) = (data_file[index + 1] << 8) | data_file[index]; - // // data_play[offset + index / 2] = (data_file[index] << 8) | data_file[index + 1]; - - // // // data_play.at(offset + index / 2) = (data_file.at(index + 1) + 0x8000) >> 0; - // // } - - // for (uint32_t index = 0; index < data_file.size(); index++) { - // // data_play.at(offset + index / 2) = (data_file[index + 1] << 8) | data_file[index]; - // // data_play[offset + index / 2] = (data_file[index] << 8) | data_file[index + 1]; - // data_play.at(offset + index) = data_file.at(index) + 0x8000; - // } + if (coefficient == 1) { + for (auto i = 0; i < data_file_size; i++) { + auto normalized_value = static_cast((data_file.at(i) + 0x8000) >> 4); + data_play.at(offset + i) = normalized_value; + } + + } else { + for (auto i = 0; i < data_file_size; i++) { + auto normalized_value = static_cast((data_file.at(i) + 0x8000) >> 4); + for (auto j = 0; j < adjustment; j++) { + data_play.at(offset + i * adjustment + j) = normalized_value; + } + // std::fill_n(data_play.begin() + offset + i * adjustment, adjustment, normalized_value); + } + } } void onHalfTransfer() @@ -94,7 +92,7 @@ void onHalfTransfer() void onCompleteTransfer() { // Fill second half - setData(size); + setData(size / 2); } auto main() -> int @@ -120,13 +118,38 @@ auto main() -> int auto header_array = std::array {}; file.read(header_array); // header + // { + // log_info("Header: "); + // rtos::ThisThread::sleep_for(100ms); + // for (auto &elem: header_array) { + // printf("%x ", elem); + // } + // printf("\n"); + + // rtos::ThisThread::sleep_for(1s); + + // file.read(data_file); + // log_info("Content: "); + // rtos::ThisThread::sleep_for(1s); + // for (auto i = 0; i < data_file_size; i++) { + // int16_t file_value = data_file.at(i); + // printf("At %3i: %d\n", i * 2 + 44, file_value); + // // uint16_t normalized_value = static_cast(data_file.at(i) + 0x8000) >> 4; + // // printf("%x ", normalized_value); + // } + // printf("\n"); + + // rtos::ThisThread::sleep_for(1s); + // return 0; + // } // Normalization + setData(0); setData(size / 2); coredac.registerDMACallbacks([] { event_queue.call(onHalfTransfer); }, [] { event_queue.call(onCompleteTransfer); }); - hal_timer.initialize(116'000); // 116'883 + hal_timer.initialize(); coredac.initialize(); coredac.registerDataToPlay(data_play); @@ -138,7 +161,7 @@ auto main() -> int // END -- NEW CODE coredac.start(); - rtos::ThisThread::sleep_for(1min); + rtos::ThisThread::sleep_for(4s); log_info("Stop sound"); coredac.stop(); diff --git a/spikes/lk_dac/main.cpp b/spikes/lk_dac/main.cpp index 0bdb6bb1f9..80c89a1412 100644 --- a/spikes/lk_dac/main.cpp +++ b/spikes/lk_dac/main.cpp @@ -20,7 +20,7 @@ auto hal = CoreSTM32Hal {}; auto hal_timer = CoreSTM32HalBasicTimer {hal}; auto coredac = CoreDAC {hal, hal_timer}; -auto audio_enable = mbed::DigitalOut {SOUND_ENABLE, 1}; +auto audio_enable = mbed::DigitalOut {SOUND_ENABLE, 0}; auto event_queue = CoreEventQueue {}; From ef09c60d1c6068e9c2fd367d824b51aca07cb842 Mon Sep 17 00:00:00 2001 From: Yann Locatelli Date: Mon, 11 Mar 2024 19:18:23 +0100 Subject: [PATCH 12/18] should check DMA config next time --- drivers/CoreDAC/source/CoreDAC.cpp | 2 +- spikes/lk_audio/main.cpp | 49 ++++++++++++++++++++---------- 2 files changed, 34 insertions(+), 17 deletions(-) diff --git a/drivers/CoreDAC/source/CoreDAC.cpp b/drivers/CoreDAC/source/CoreDAC.cpp index c3a28f899e..d5d51e9ddd 100644 --- a/drivers/CoreDAC/source/CoreDAC.cpp +++ b/drivers/CoreDAC/source/CoreDAC.cpp @@ -104,7 +104,7 @@ void CoreDAC::_initializeDMA() _hdma.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; _hdma.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; _hdma.Init.Mode = DMA_CIRCULAR; - _hdma.Init.Priority = DMA_PRIORITY_LOW; + _hdma.Init.Priority = DMA_PRIORITY_VERY_HIGH; _hdma.Init.FIFOMode = DMA_FIFOMODE_ENABLE; _hdma.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_HALFFULL; _hdma.Init.MemBurst = DMA_MBURST_SINGLE; diff --git a/spikes/lk_audio/main.cpp b/spikes/lk_audio/main.cpp index 9d17f87386..5153594813 100644 --- a/spikes/lk_audio/main.cpp +++ b/spikes/lk_audio/main.cpp @@ -56,7 +56,7 @@ constexpr auto size = 2'000; // constexpr auto size = 16'384; // constexpr auto size = 32'768; // constexpr auto size = 65'536; // NOK -constexpr auto coefficient = 1; +constexpr auto coefficient = 2; // Related to ARR | ARR*coefficient ~= 2448 constexpr auto data_file_size = size / coefficient / 2; // /2 for half buffer and *2 std::array data_file {}; // std::array data_file {}; @@ -64,23 +64,11 @@ std::array data_play {}; void setData(uint16_t offset) { - static constexpr auto adjustment = coefficient; // Related to ARR file.read(data_file); - if (coefficient == 1) { - for (auto i = 0; i < data_file_size; i++) { - auto normalized_value = static_cast((data_file.at(i) + 0x8000) >> 4); - data_play.at(offset + i) = normalized_value; - } - - } else { - for (auto i = 0; i < data_file_size; i++) { - auto normalized_value = static_cast((data_file.at(i) + 0x8000) >> 4); - for (auto j = 0; j < adjustment; j++) { - data_play.at(offset + i * adjustment + j) = normalized_value; - } - // std::fill_n(data_play.begin() + offset + i * adjustment, adjustment, normalized_value); - } + for (auto i = 0; i < data_file_size; i++) { + auto normalized_value = static_cast((data_file.at(i) + 0x8000) >> 4); + std::fill_n(data_play.begin() + offset + i * coefficient, coefficient, normalized_value); } } @@ -143,6 +131,35 @@ auto main() -> int // return 0; // } // Normalization + // { + // setData(0); + // log_info("Data play (first half loaded):"); + // rtos::ThisThread::sleep_for(1s); + // for (auto i = 0; i < data_play.size(); i++) { + // printf("At %3i: %x\n", i * 2 + 44, data_play.at(i)); + // } + // printf("\n"); + + // setData(size / 2); + // log_info("Data play (second half loaded): "); + // rtos::ThisThread::sleep_for(1s); + // for (auto i = 0; i < data_play.size(); i++) { + // printf("At %3i: %x\n", i * 2 + 44, data_play.at(i)); + // } + // printf("\n"); + + // setData(0); + // log_info("Data play (next chunk): "); + // rtos::ThisThread::sleep_for(1s); + // for (auto i = 0; i < data_play.size() / 2; i++) { + // printf("At %3i: %x\n", i * 2 + 44 + size * 2, data_play.at(i)); + // } + // printf("\n"); + + // rtos::ThisThread::sleep_for(1s); + // return 0; + // } // Correctly filled + setData(0); setData(size / 2); From ededb385f8f8466314778b209398801634fd6453 Mon Sep 17 00:00:00 2001 From: Yann Locatelli Date: Tue, 12 Mar 2024 19:06:45 +0100 Subject: [PATCH 13/18] good setup --- spikes/lk_audio/main.cpp | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/spikes/lk_audio/main.cpp b/spikes/lk_audio/main.cpp index 5153594813..0c09d213c4 100644 --- a/spikes/lk_audio/main.cpp +++ b/spikes/lk_audio/main.cpp @@ -27,7 +27,8 @@ auto audio_enable = mbed::DigitalOut {SOUND_ENABLE, 1}; constexpr uint32_t sample_rate_hz = 44'100; -auto event_queue = CoreEventQueue {}; +auto event_queue = CoreEventQueue {}; +auto event_queue_converted = CoreEventQueue {}; auto sd_blockdevice = SDBlockDevice {SD_SPI_MOSI, SD_SPI_MISO, SD_SPI_SCK}; auto fatfs = FATFileSystem {"fs"}; @@ -48,7 +49,7 @@ void initializeSD() // constexpr auto size = 128; // constexpr auto size = 256; // constexpr auto size = 512; -constexpr auto size = 2'000; +constexpr auto size = 5'000; // constexpr auto size = 1'024; // constexpr auto size = 2'048; // constexpr auto size = 4'096; @@ -56,31 +57,45 @@ constexpr auto size = 2'000; // constexpr auto size = 16'384; // constexpr auto size = 32'768; // constexpr auto size = 65'536; // NOK -constexpr auto coefficient = 2; // Related to ARR | ARR*coefficient ~= 2448 +constexpr auto coefficient = 10; // Related to ARR | ARR*coefficient ~= 2448 constexpr auto data_file_size = size / coefficient / 2; // /2 for half buffer and *2 std::array data_file {}; // std::array data_file {}; +std::array data_converted {}; std::array data_play {}; -void setData(uint16_t offset) +void convertData(uint32_t offset) { file.read(data_file); for (auto i = 0; i < data_file_size; i++) { auto normalized_value = static_cast((data_file.at(i) + 0x8000) >> 4); - std::fill_n(data_play.begin() + offset + i * coefficient, coefficient, normalized_value); + std::fill_n(data_converted.begin() + offset + i * coefficient, coefficient, normalized_value); } + log_info("offset %d", offset); // Better than sleep_for +} + +void setData(uint32_t offset) +{ + std::copy(data_converted.begin() + offset, data_converted.begin() + offset + size / 2, data_play.begin() + offset); + + event_queue_converted.call([offset] { convertData(offset); }); + + // log_info("offset %d", offset); // Better than sleep_for + rtos::ThisThread::sleep_for(1ms); } void onHalfTransfer() { // Fill first half setData(0); + // std::fill_n(data_play.begin(), size / 2, 0x0); } void onCompleteTransfer() { // Fill second half setData(size / 2); + // std::fill_n(data_play.begin() + size / 2, size / 2, 0xFFF); } auto main() -> int @@ -90,6 +105,7 @@ auto main() -> int log_info("Hello, World!\n\n"); rtos::ThisThread::sleep_for(1s); + event_queue_converted.dispatch_forever(); event_queue.dispatch_forever(); initializeSD(); @@ -160,13 +176,20 @@ auto main() -> int // return 0; // } // Correctly filled + convertData(0); + rtos::ThisThread::sleep_for(300ms); + convertData(size / 2); + rtos::ThisThread::sleep_for(300ms); + setData(0); + rtos::ThisThread::sleep_for(300ms); setData(size / 2); + rtos::ThisThread::sleep_for(300ms); coredac.registerDMACallbacks([] { event_queue.call(onHalfTransfer); }, [] { event_queue.call(onCompleteTransfer); }); - hal_timer.initialize(); + hal_timer.initialize(44'100 * coefficient); coredac.initialize(); coredac.registerDataToPlay(data_play); From 8e8633804c0aaaa0909e26632546d9180ddff0b0 Mon Sep 17 00:00:00 2001 From: Yann Locatelli Date: Tue, 12 Mar 2024 19:16:39 +0100 Subject: [PATCH 14/18] eof --- spikes/lk_audio/main.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/spikes/lk_audio/main.cpp b/spikes/lk_audio/main.cpp index 0c09d213c4..b12c495442 100644 --- a/spikes/lk_audio/main.cpp +++ b/spikes/lk_audio/main.cpp @@ -64,19 +64,27 @@ std::array data_file {}; std::array data_converted {}; std::array data_play {}; +auto is_eof = false; + void convertData(uint32_t offset) { - file.read(data_file); + auto bytes_read = file.read(data_file); for (auto i = 0; i < data_file_size; i++) { auto normalized_value = static_cast((data_file.at(i) + 0x8000) >> 4); std::fill_n(data_converted.begin() + offset + i * coefficient, coefficient, normalized_value); } - log_info("offset %d", offset); // Better than sleep_for + is_eof = bytes_read != data_file_size; + log_info("bytes_read %d", bytes_read); // Better than sleep_for } void setData(uint32_t offset) { + if (is_eof) { + coredac.stop(); + return; + } + std::copy(data_converted.begin() + offset, data_converted.begin() + offset + size / 2, data_play.begin() + offset); event_queue_converted.call([offset] { convertData(offset); }); @@ -201,7 +209,7 @@ auto main() -> int // END -- NEW CODE coredac.start(); - rtos::ThisThread::sleep_for(4s); + rtos::ThisThread::sleep_for(1min); log_info("Stop sound"); coredac.stop(); From 2112bcc6007fb92ee74fe615bcc7b27a72b3a45a Mon Sep 17 00:00:00 2001 From: Yann Locatelli Date: Tue, 12 Mar 2024 19:25:25 +0100 Subject: [PATCH 15/18] Loop play --- spikes/lk_audio/WavFile.cpp | 54 ++++++++++++++++++ spikes/lk_audio/main.cpp | 108 +++++++++--------------------------- 2 files changed, 80 insertions(+), 82 deletions(-) diff --git a/spikes/lk_audio/WavFile.cpp b/spikes/lk_audio/WavFile.cpp index 0df933a2b8..e6f774d598 100644 --- a/spikes/lk_audio/WavFile.cpp +++ b/spikes/lk_audio/WavFile.cpp @@ -1 +1,55 @@ #include "WavFile.h" + +// { +// log_info("Header: "); +// rtos::ThisThread::sleep_for(100ms); +// for (auto &elem: header_array) { +// printf("%x ", elem); +// } +// printf("\n"); + +// rtos::ThisThread::sleep_for(1s); + +// file.read(data_file); +// log_info("Content: "); +// rtos::ThisThread::sleep_for(1s); +// for (auto i = 0; i < data_file_size; i++) { +// int16_t file_value = data_file.at(i); +// printf("At %3i: %d\n", i * 2 + 44, file_value); +// // uint16_t normalized_value = static_cast(data_file.at(i) + 0x8000) >> 4; +// // printf("%x ", normalized_value); +// } +// printf("\n"); + +// rtos::ThisThread::sleep_for(1s); +// return 0; +// } // Normalization + +// { +// setData(0); +// log_info("Data play (first half loaded):"); +// rtos::ThisThread::sleep_for(1s); +// for (auto i = 0; i < data_play.size(); i++) { +// printf("At %3i: %x\n", i * 2 + 44, data_play.at(i)); +// } +// printf("\n"); + +// setData(size / 2); +// log_info("Data play (second half loaded): "); +// rtos::ThisThread::sleep_for(1s); +// for (auto i = 0; i < data_play.size(); i++) { +// printf("At %3i: %x\n", i * 2 + 44, data_play.at(i)); +// } +// printf("\n"); + +// setData(0); +// log_info("Data play (next chunk): "); +// rtos::ThisThread::sleep_for(1s); +// for (auto i = 0; i < data_play.size() / 2; i++) { +// printf("At %3i: %x\n", i * 2 + 44 + size * 2, data_play.at(i)); +// } +// printf("\n"); + +// rtos::ThisThread::sleep_for(1s); +// return 0; +// } // Correctly filled diff --git a/spikes/lk_audio/main.cpp b/spikes/lk_audio/main.cpp index b12c495442..2255a76a77 100644 --- a/spikes/lk_audio/main.cpp +++ b/spikes/lk_audio/main.cpp @@ -75,7 +75,8 @@ void convertData(uint32_t offset) std::fill_n(data_converted.begin() + offset + i * coefficient, coefficient, normalized_value); } is_eof = bytes_read != data_file_size; - log_info("bytes_read %d", bytes_read); // Better than sleep_for + + log_info(""); // Better than sleep_for } void setData(uint32_t offset) @@ -89,8 +90,7 @@ void setData(uint32_t offset) event_queue_converted.call([offset] { convertData(offset); }); - // log_info("offset %d", offset); // Better than sleep_for - rtos::ThisThread::sleep_for(1ms); + log_info(""); // Better than sleep_for } void onHalfTransfer() @@ -126,95 +126,39 @@ auto main() -> int log_info("Initialize"); rtos::ThisThread::sleep_for(1s); - file.open(sound_file_path); - auto header_array = std::array {}; - file.read(header_array); // header - - // { - // log_info("Header: "); - // rtos::ThisThread::sleep_for(100ms); - // for (auto &elem: header_array) { - // printf("%x ", elem); - // } - // printf("\n"); - - // rtos::ThisThread::sleep_for(1s); - - // file.read(data_file); - // log_info("Content: "); - // rtos::ThisThread::sleep_for(1s); - // for (auto i = 0; i < data_file_size; i++) { - // int16_t file_value = data_file.at(i); - // printf("At %3i: %d\n", i * 2 + 44, file_value); - // // uint16_t normalized_value = static_cast(data_file.at(i) + 0x8000) >> 4; - // // printf("%x ", normalized_value); - // } - // printf("\n"); - - // rtos::ThisThread::sleep_for(1s); - // return 0; - // } // Normalization - - // { - // setData(0); - // log_info("Data play (first half loaded):"); - // rtos::ThisThread::sleep_for(1s); - // for (auto i = 0; i < data_play.size(); i++) { - // printf("At %3i: %x\n", i * 2 + 44, data_play.at(i)); - // } - // printf("\n"); - - // setData(size / 2); - // log_info("Data play (second half loaded): "); - // rtos::ThisThread::sleep_for(1s); - // for (auto i = 0; i < data_play.size(); i++) { - // printf("At %3i: %x\n", i * 2 + 44, data_play.at(i)); - // } - // printf("\n"); - - // setData(0); - // log_info("Data play (next chunk): "); - // rtos::ThisThread::sleep_for(1s); - // for (auto i = 0; i < data_play.size() / 2; i++) { - // printf("At %3i: %x\n", i * 2 + 44 + size * 2, data_play.at(i)); - // } - // printf("\n"); - - // rtos::ThisThread::sleep_for(1s); - // return 0; - // } // Correctly filled - - convertData(0); - rtos::ThisThread::sleep_for(300ms); - convertData(size / 2); - rtos::ThisThread::sleep_for(300ms); - - setData(0); - rtos::ThisThread::sleep_for(300ms); - setData(size / 2); - rtos::ThisThread::sleep_for(300ms); - coredac.registerDMACallbacks([] { event_queue.call(onHalfTransfer); }, [] { event_queue.call(onCompleteTransfer); }); hal_timer.initialize(44'100 * coefficient); coredac.initialize(); - coredac.registerDataToPlay(data_play); - // Play on audio + while (true) { + { + file.open(sound_file_path); + auto header_array = std::array {}; + file.read(header_array); // header - log_info("Start sound"); - rtos::ThisThread::sleep_for(1s); + is_eof = false; - // END -- NEW CODE - coredac.start(); + convertData(0); + rtos::ThisThread::sleep_for(300ms); + convertData(size / 2); + rtos::ThisThread::sleep_for(300ms); - rtos::ThisThread::sleep_for(1min); + setData(0); + rtos::ThisThread::sleep_for(300ms); + setData(size / 2); + rtos::ThisThread::sleep_for(300ms); - log_info("Stop sound"); - coredac.stop(); + coredac.registerDataToPlay(data_play); + rtos::ThisThread::sleep_for(100ms); + } // Setup new file - while (true) { - rtos::ThisThread::sleep_for(1min); + { + coredac.start(); + while (!is_eof) rtos::ThisThread::sleep_for(500ms); + } // Play on audio + + rtos::ThisThread::sleep_for(1s); } } From 7ff1afdb3f4b65a48853bf65fc24c2224ca62629 Mon Sep 17 00:00:00 2001 From: Yann Locatelli Date: Tue, 12 Mar 2024 19:32:42 +0100 Subject: [PATCH 16/18] flags --- spikes/lk_audio/CMakeLists.txt | 1 + spikes/lk_audio/main.cpp | 19 ++++++++++++++++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/spikes/lk_audio/CMakeLists.txt b/spikes/lk_audio/CMakeLists.txt index 0a4eefdc7b..1068b29537 100644 --- a/spikes/lk_audio/CMakeLists.txt +++ b/spikes/lk_audio/CMakeLists.txt @@ -22,6 +22,7 @@ target_link_libraries(spike_lk_audio CoreDAC FileManagerKit CoreEventQueue + CoreEventFlags ) target_link_custom_leka_targets(spike_lk_audio) diff --git a/spikes/lk_audio/main.cpp b/spikes/lk_audio/main.cpp index 2255a76a77..2831e8a400 100644 --- a/spikes/lk_audio/main.cpp +++ b/spikes/lk_audio/main.cpp @@ -7,6 +7,7 @@ #include "rtos/ThisThread.h" #include "CoreDAC.h" +#include "CoreEventFlags.h" #include "CoreEventQueue.h" #include "CoreSTM32Hal.h" #include "CoreSTM32HalBasicTimer.h" @@ -36,6 +37,12 @@ auto fatfs = FATFileSystem {"fs"}; const auto sound_file_path = std::filesystem::path {"/fs/home/wav/440.wav"}; auto file = FileManagerKit::File {}; +auto event_flags = CoreEventFlags {}; + +struct flag { + static constexpr uint32_t START = (1UL << 1); +}; + void initializeSD() { constexpr auto default_sd_blockdevice_frequency = uint64_t {25'000'000}; @@ -76,7 +83,7 @@ void convertData(uint32_t offset) } is_eof = bytes_read != data_file_size; - log_info(""); // Better than sleep_for + log_info("bytes_read %d", bytes_read); // Better than sleep_for } void setData(uint32_t offset) @@ -90,7 +97,8 @@ void setData(uint32_t offset) event_queue_converted.call([offset] { convertData(offset); }); - log_info(""); // Better than sleep_for + // log_info(""); // Better than sleep_for + rtos::ThisThread::sleep_for(1ms); } void onHalfTransfer() @@ -132,7 +140,12 @@ auto main() -> int hal_timer.initialize(44'100 * coefficient); coredac.initialize(); + event_flags.set(flag::START); + while (true) { + event_flags.wait_any(flag::START); + event_flags.set(flag::START); // Temporary + { file.open(sound_file_path); auto header_array = std::array {}; @@ -156,7 +169,7 @@ auto main() -> int { coredac.start(); - while (!is_eof) rtos::ThisThread::sleep_for(500ms); + while (!is_eof) rtos::ThisThread::sleep_for(1s); } // Play on audio rtos::ThisThread::sleep_for(1s); From 201d6a2a70c8f382af5664111e4901fb63185b4d Mon Sep 17 00:00:00 2001 From: Yann Locatelli Date: Tue, 12 Mar 2024 20:12:22 +0100 Subject: [PATCH 17/18] ble --- spikes/lk_audio/CMakeLists.txt | 1 + spikes/lk_audio/main.cpp | 25 ++++++++++++++++++++++--- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/spikes/lk_audio/CMakeLists.txt b/spikes/lk_audio/CMakeLists.txt index 1068b29537..ec8bf8170f 100644 --- a/spikes/lk_audio/CMakeLists.txt +++ b/spikes/lk_audio/CMakeLists.txt @@ -23,6 +23,7 @@ target_link_libraries(spike_lk_audio FileManagerKit CoreEventQueue CoreEventFlags + BLEKit ) target_link_custom_leka_targets(spike_lk_audio) diff --git a/spikes/lk_audio/main.cpp b/spikes/lk_audio/main.cpp index 2831e8a400..29a0493e0e 100644 --- a/spikes/lk_audio/main.cpp +++ b/spikes/lk_audio/main.cpp @@ -6,6 +6,9 @@ #include "rtos/ThisThread.h" +#include "BLEKit.h" +#include "BLEServiceConfig.h" + #include "CoreDAC.h" #include "CoreEventFlags.h" #include "CoreEventQueue.h" @@ -34,8 +37,9 @@ auto event_queue_converted = CoreEventQueue {}; auto sd_blockdevice = SDBlockDevice {SD_SPI_MOSI, SD_SPI_MISO, SD_SPI_SCK}; auto fatfs = FATFileSystem {"fs"}; -const auto sound_file_path = std::filesystem::path {"/fs/home/wav/440.wav"}; -auto file = FileManagerKit::File {}; +const auto sound_directory_path = std::filesystem::path {"/fs/home/wav"}; +auto sound_file_path = sound_directory_path / std::filesystem::path {"440.wav"}; +auto file = FileManagerKit::File {}; auto event_flags = CoreEventFlags {}; @@ -43,6 +47,10 @@ struct flag { static constexpr uint32_t START = (1UL << 1); }; +auto service_config = BLEServiceConfig {}; +auto services = std::to_array({&service_config}); +auto blekit = BLEKit {}; + void initializeSD() { constexpr auto default_sd_blockdevice_frequency = uint64_t {25'000'000}; @@ -124,11 +132,23 @@ auto main() -> int event_queue_converted.dispatch_forever(); event_queue.dispatch_forever(); + blekit.setServices(services); + blekit.init(); + initializeSD(); if (FileManagerKit::file_is_missing(sound_file_path)) { return 1; } + service_config.onRobotNameUpdated([](const std::array &robot_name) { + const auto *end_index = std::find(robot_name.begin(), robot_name.end(), '\0'); + auto filename = std::string {robot_name.begin(), end_index} + ".wav"; + sound_file_path = sound_directory_path / std::filesystem::path {filename}; + + log_info("Play file: %s", sound_file_path.c_str()); + event_flags.set(flag::START); + }); + // BEGIN -- NEW CODE log_info("Initialize"); @@ -144,7 +164,6 @@ auto main() -> int while (true) { event_flags.wait_any(flag::START); - event_flags.set(flag::START); // Temporary { file.open(sound_file_path); From 94f4e60906b1b7de2601a42a3f62a47aa490ccc7 Mon Sep 17 00:00:00 2001 From: Yann Locatelli Date: Wed, 13 Mar 2024 15:42:05 +0100 Subject: [PATCH 18/18] revert some changes --- drivers/CoreDAC/source/CoreDAC.cpp | 2 +- .../CoreDAC/source/CoreSTM32HalBasicTimer.cpp | 35 ++++--------------- drivers/CoreDAC/source/HAL_IRQHandlers.cpp | 6 +--- 3 files changed, 9 insertions(+), 34 deletions(-) diff --git a/drivers/CoreDAC/source/CoreDAC.cpp b/drivers/CoreDAC/source/CoreDAC.cpp index d5d51e9ddd..c3a28f899e 100644 --- a/drivers/CoreDAC/source/CoreDAC.cpp +++ b/drivers/CoreDAC/source/CoreDAC.cpp @@ -104,7 +104,7 @@ void CoreDAC::_initializeDMA() _hdma.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; _hdma.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; _hdma.Init.Mode = DMA_CIRCULAR; - _hdma.Init.Priority = DMA_PRIORITY_VERY_HIGH; + _hdma.Init.Priority = DMA_PRIORITY_LOW; _hdma.Init.FIFOMode = DMA_FIFOMODE_ENABLE; _hdma.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_HALFFULL; _hdma.Init.MemBurst = DMA_MBURST_SINGLE; diff --git a/drivers/CoreDAC/source/CoreSTM32HalBasicTimer.cpp b/drivers/CoreDAC/source/CoreSTM32HalBasicTimer.cpp index 40a68e30f3..bb54da1113 100644 --- a/drivers/CoreDAC/source/CoreSTM32HalBasicTimer.cpp +++ b/drivers/CoreDAC/source/CoreSTM32HalBasicTimer.cpp @@ -5,8 +5,6 @@ #include "CoreSTM32HalBasicTimer.h" #include -#include "LogKit.h" - using namespace leka; CoreSTM32HalBasicTimer::CoreSTM32HalBasicTimer(interface::STM32Hal &hal) : _hal(hal) @@ -34,38 +32,19 @@ void CoreSTM32HalBasicTimer::initialize(float frequency) _htim.Init.Prescaler = 0; _htim.Init.Period = divider - 1; // ? min 1 - _htim.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE; + _htim.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; _hal.HAL_TIM_Base_Init(&_htim); - auto _calculatePeriod = [](uint32_t frequency) { - uint32_t clockFreq = HAL_RCC_GetPCLK1Freq(); - - /* Get PCLK1 prescaler */ - if ((RCC->CFGR & RCC_CFGR_PPRE1) != 0) { - clockFreq *= 2; - } - - if (frequency < (clockFreq >> 16) || frequency > clockFreq) { - log_error("Chosen freq out of bounds\n"); - } - - return (clockFreq / frequency); - }; - auto periodCalculated = _calculatePeriod(frequency); - - log_info("divider: %ld, prescaler: %ld, period: %ld, calculated: %ld", divider, _htim.Init.Prescaler, - _htim.Init.Period, periodCalculated); - auto timerMasterConfig = TIM_MasterConfigTypeDef {}; timerMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE; - timerMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; _hal.HAL_TIMEx_MasterConfigSynchronization(&_htim, &timerMasterConfig); - // static const auto &self = *this; - // _hal.HAL_TIM_RegisterCallback(&_htim, HAL_TIM_PERIOD_ELAPSED_CB_ID, []([[maybe_unused]] TIM_HandleTypeDef *htim) - // { if (self._callback != nullptr) { self._callback(); - // } - // }); + static const auto &self = *this; + _hal.HAL_TIM_RegisterCallback(&_htim, HAL_TIM_PERIOD_ELAPSED_CB_ID, []([[maybe_unused]] TIM_HandleTypeDef *htim) { + if (self._callback != nullptr) { + self._callback(); + } + }); } void CoreSTM32HalBasicTimer::_registerMspCallbacks() diff --git a/drivers/CoreDAC/source/HAL_IRQHandlers.cpp b/drivers/CoreDAC/source/HAL_IRQHandlers.cpp index 22fbb79217..31ae2946df 100644 --- a/drivers/CoreDAC/source/HAL_IRQHandlers.cpp +++ b/drivers/CoreDAC/source/HAL_IRQHandlers.cpp @@ -8,11 +8,7 @@ extern leka::CoreDAC coredac; void TIM6_DAC_IRQHandler() { - TIM6->SR = ~TIM_SR_UIF; - // GPIOG->ODR ^= (1 << 6); - // HAL_TIM_IRQHandler(&hal_timer.getHandle()); - // have to be replace - // https://stackoverflow.com/questions/56995426/issue-with-frequency-limitation-on-the-timers-on-stm32f7 + HAL_TIM_IRQHandler(&hal_timer.getHandle()); } void TIM7_DAC_IRQHandler()