skullc-peripherals/Peripherals/Inc/peripherals_hal_st.hpp
Erki ce4f8eb8f5
All checks were successful
continuous-integration/drone/push Build is passing
New logging interfaces
2021-04-02 00:50:59 +03:00

288 lines
5.8 KiB
C++

/*
* peripherals_hal_st.hpp
*
* Created on: Mar 30, 2021
* Author: erki
*/
#ifndef PERIPHERALS_INC_PERIPHERALS_HAL_ST_HPP_
#define PERIPHERALS_INC_PERIPHERALS_HAL_ST_HPP_
#include <main.h>
#include "peripherals_utility.hpp"
#define USE_DELAY_US
namespace Peripherals
{
namespace Hal
{
namespace St
{
template<typename Origin>
using IsrCallbackFn = void(*)(Origin*);
template<typename Origin, typename Handler, void (Handler::*func)(), typename Tag>
IsrCallbackFn<Origin> createCallback(Handler& h_in)
{
static Handler* h = &h_in;
printf("Set handler: %p\n", h);
return +[](Origin*)
{
printf("Into callback we go.\n");
(h->*func)();
printf("And we're out.\n");
};
}
struct StaticHal
{
static void Initialize()
{
#ifdef USE_DELAY_US
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
DWT->CYCCNT = 0;
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
#endif
}
static void Delay(const std::uint32_t milliseconds)
{
HAL_Delay(milliseconds);
}
static void DelayUs(const std::uint32_t micros)
{
#ifdef USE_DELAY_US
const std::uint32_t tick_start = DWT->CYCCNT;
const std::uint32_t ticks_delay = micros * (SystemCoreClock / 1'000'000);
while (DWT->CYCCNT - tick_start < ticks_delay);
#else
(void)micros;
#endif
}
static void enableInterrupts()
{
__enable_irq();
}
static void disableInterrupts()
{
__disable_irq();
}
};
#ifdef HAL_GPIO_MODULE_ENABLED
struct Gpio
{
GPIO_TypeDef* port;
std::uint16_t pin;
Gpio() = delete;
explicit Gpio(GPIO_TypeDef* port, const std::uint16_t pin)
: port(port)
, pin(pin)
{ }
void Set(const bool& state)
{
HAL_GPIO_WritePin(port, pin, GPIO_PinState(state));
}
void Toggle()
{
HAL_GPIO_TogglePin(port, pin);
}
bool Read() const
{
return HAL_GPIO_ReadPin(port, pin);
}
};
#endif // HAL_GPIO_MODULE_ENABLED
template<typename T,
HAL_StatusTypeDef (*transmit)(T*, std::uint8_t* data, std::uint16_t data_len, std::uint32_t timeout),
HAL_StatusTypeDef (*receive)(T*, std::uint8_t* data, std::uint16_t data_len, std::uint32_t timeout)>
struct SerialInterface
{
using underlying_handle_type = T;
underlying_handle_type* handle;
SerialInterface() = delete;
explicit SerialInterface(underlying_handle_type* handle)
: handle(handle)
{ }
bool Transmit(std::uint8_t* data, const std::uint32_t data_len)
{
return transmit(handle, data, data_len, 100) == HAL_StatusTypeDef::HAL_OK;
}
bool Receive(std::uint8_t* data, const std::uint32_t data_len)
{
return receive(handle, data, data_len, 100) == HAL_StatusTypeDef::HAL_OK;
}
};
template<typename T,
HAL_StatusTypeDef (*transmit)(T*, std::uint8_t* data, std::uint16_t data_len),
HAL_StatusTypeDef (*receive)(T*, std::uint8_t* data, std::uint16_t data_len)>
struct SerialInterfaceAsync
{
using underlying_handle_type = T;
underlying_handle_type* handle;
SerialInterfaceAsync() = delete;
explicit SerialInterfaceAsync(underlying_handle_type* handle)
: handle(handle)
{ }
bool Transmit(std::uint8_t* data, const std::uint32_t data_len)
{
return transmit(handle, data, data_len) == HAL_StatusTypeDef::HAL_OK;
}
bool Receive(std::uint8_t* data, const std::uint32_t data_len)
{
return receive(handle, data, data_len) == HAL_StatusTypeDef::HAL_OK;
}
};
#ifdef HAL_SPI_MODULE_ENABLED
using SpiInterface = SerialInterface<SPI_HandleTypeDef, HAL_SPI_Transmit, HAL_SPI_Receive>;
struct SpiRegisters
{
SpiInterface handle;
Gpio chip_select;
SpiRegisters() = delete;
explicit SpiRegisters(const SpiInterface& handle, const Gpio& chip_select)
: handle(handle)
, chip_select(chip_select)
{ }
void WriteRegister(std::uint8_t reg, uint8_t data)
{
chip_select.Set(false);
handle.Transmit(&reg, 1);
handle.Transmit(&data, 1);
chip_select.Set(true);
}
void WriteRegisterMultibyte(std::uint8_t reg, std::uint8_t* data, const std::uint32_t len)
{
chip_select.Set(false);
handle.Transmit(&reg, 1);
handle.Transmit(data, len);
chip_select.Set(true);
}
std::uint8_t ReadRegister(std::uint8_t reg, const std::uint32_t read_delay = 0)
{
chip_select.Set(false);
handle.Transmit(&reg, 1);
std::uint8_t output = 255;
if (read_delay)
StaticHal::DelayUs(read_delay);
handle.Receive(&output, 1);
chip_select.Set(true);
return output;
}
void ReadRegisterMultibyte(std::uint8_t reg, std::uint8_t* data, const std::uint32_t len, const std::uint32_t read_delay = 0)
{
chip_select.Set(false);
handle.Transmit(&reg, 1);
if (read_delay)
StaticHal::DelayUs(read_delay);
handle.Receive(data, len);
chip_select.Set(true);
}
};
#endif // HAL_SPI_MODULE_ENABLED
#ifdef HAL_UART_MODULE_ENABLED
using UartInterface = SerialInterface<UART_HandleTypeDef, HAL_UART_Transmit, HAL_UART_Receive>;
using UartInterfaceDMA = SerialInterfaceAsync<UART_HandleTypeDef, HAL_UART_Transmit_DMA, HAL_UART_Receive_DMA>;
#endif // HAL_UART_MODULE_ENABLED
#ifdef HAL_TIM_MODULE_ENABLED
struct PwmChannel
{
TIM_HandleTypeDef* handle;
std::uint32_t channel;
PwmChannel() = delete;
explicit PwmChannel(TIM_HandleTypeDef* handle, const std::uint32_t channel)
: handle(handle)
, channel(channel)
{ }
void Enable()
{
HAL_TIM_PWM_Start(handle, channel);
}
void Disable()
{
HAL_TIM_PWM_Stop(handle, channel);
}
void SetCompare(const std::uint32_t compare)
{
__HAL_TIM_SET_COMPARE(handle, channel, compare);
}
std::uint32_t MaxValue()
{
return handle->Init.Period;
}
};
#endif // HAL_TIM_MODULE_ENABLED
struct ItmSerialInterface
{
bool Transmit(std::uint8_t* data, const std::uint32_t data_len)
{
for (std::uint32_t i = 0; i < data_len; i++)
{
ITM_SendChar(char(data[i]));
}
return true;
}
};
}
}
}
#endif /* PERIPHERALS_INC_PERIPHERALS_HAL_ST_HPP_ */