Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Yann/feature/haptic/coredac #1416

Open
wants to merge 2 commits into
base: yann/feature/haptic/halbasictimer
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions config/mbed_app.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": {
Expand Down
1 change: 1 addition & 0 deletions drivers/CoreDAC/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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"))
Expand Down
49 changes: 49 additions & 0 deletions drivers/CoreDAC/include/CoreDAC.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Leka - LekaOS
// Copyright 2024 APF France handicap
// SPDX-License-Identifier: Apache-2.0

#pragma once

#include <array>
#include <functional>
#include <span>

#include "interface/drivers/DAC.h"
#include "interface/drivers/STM32Hal.h"
#include "interface/drivers/STM32HalBasicTimer.h"

namespace leka {

class CoreDAC : public interface::DACDMA
{
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<uint16_t> data) final;
void registerDMACallbacks(std::function<void()> const &on_half_transfer,
std::function<void()> const &on_complete_transfer) final;

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<uint16_t> _data;
std::function<void()> _on_half_transfer {};
std::function<void()> _on_complete_transfer {};
};

} // namespace leka
116 changes: 116 additions & 0 deletions drivers/CoreDAC/source/CoreDAC.cpp
Original file line number Diff line number Diff line change
@@ -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<uint16_t> data)
{
_data = data;
}

void CoreDAC::registerDMACallbacks(std::function<void()> const &on_half_transfer,
std::function<void()> 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<uint32_t *>(_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);
}
9 changes: 8 additions & 1 deletion drivers/CoreDAC/source/HAL_IRQHandlers.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
#include "CoreDAC.h"
#include "CoreSTM32HalBasicTimer.h"

extern "C" {

namespace audio::internal {
extern leka::CoreSTM32HalBasicTimer hal_timer;
}
extern leka::CoreDAC coredac;
} // namespace audio::internal

void TIM6_DAC_IRQHandler()
{
Expand All @@ -16,4 +18,9 @@ void TIM7_DAC_IRQHandler()
HAL_TIM_IRQHandler(&audio::internal::hal_timer.getHandle());
}

void DMA1_Stream5_IRQHandler()
{
HAL_DMA_IRQHandler(audio::internal::coredac.getHandle().DMA_Handle1);
}

} // extern "C"
14 changes: 14 additions & 0 deletions drivers/CoreSTM32Hal/include/CoreSTM32Hal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
48 changes: 48 additions & 0 deletions drivers/CoreSTM32Hal/source/CoreSTM32Hal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
38 changes: 38 additions & 0 deletions include/interface/drivers/DAC.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Leka - LekaOS
// Copyright 2024 APF France handicap
// SPDX-License-Identifier: Apache-2.0

#pragma once

#include <functional>
#include <span>

#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;
};

class DACDMA : public DACBase
{
public:
virtual ~DACDMA() = default;

virtual void registerDataToPlay(std::span<uint16_t> data) = 0;
virtual void registerDMACallbacks(std::function<void()> const &on_half_transfer,
std::function<void()> const &on_complete_transfer) = 0;
};

} // namespace leka::interface
14 changes: 14 additions & 0 deletions include/interface/drivers/STM32Hal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
1 change: 1 addition & 0 deletions tests/unit/headers/mbed/mbed_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading