Compare commits

..

No commits in common. "55a8efa57913b21389e873a6949cc723cb74beeb" and "ce4f8eb8f5c02e2832ad3f396a0d84822e2b04ad" have entirely different histories.

23 changed files with 746 additions and 783 deletions

View File

@ -1,67 +0,0 @@
# Generated from CLion C/C++ Code Style settings
BasedOnStyle: LLVM
AccessModifierOffset: -2
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignOperands: true
AllowAllArgumentsOnNextLine: false
AllowAllConstructorInitializersOnNextLine: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: Always
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: Always
AllowShortLambdasOnASingleLine: All
AllowShortLoopsOnASingleLine: true
AlwaysBreakAfterReturnType: None
AlwaysBreakTemplateDeclarations: Yes
BreakBeforeBraces: Custom
BraceWrapping:
AfterCaseLabel: false
AfterClass: true
AfterControlStatement: Always
AfterEnum: true
AfterFunction: true
AfterNamespace: true
AfterUnion: true
AfterStruct: true
BeforeCatch: false
BeforeElse: false
IndentBraces: false
SplitEmptyFunction: false
SplitEmptyRecord: true
BreakBeforeBinaryOperators: None
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: BeforeColon
BreakInheritanceList: BeforeComma
ColumnLimit: 0
CompactNamespaces: false
ContinuationIndentWidth: 8
IndentCaseLabels: true
IndentPPDirectives: None
IndentWidth: 2
KeepEmptyLinesAtTheStartOfBlocks: true
MaxEmptyLinesToKeep: 2
NamespaceIndentation: None
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PointerAlignment: Left
ReflowComments: false
SpaceAfterCStyleCast: true
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 0
SpacesInAngles: false
SpacesInCStyleCastParentheses: false
SpacesInContainerLiterals: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
TabWidth: 2
UseTab: Never

View File

@ -5,9 +5,9 @@ add_library(messaging INTERFACE)
add_library(skullc::messaging ALIAS messaging) add_library(skullc::messaging ALIAS messaging)
target_include_directories(messaging target_include_directories(messaging
INTERFACE INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/Inc> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/Inc>
$<INSTALL_INTERFACE:include> $<INSTALL_INTERFACE:include>
) )
skullc_install_packages(skullc messaging ${version}) skullc_install_packages(skullc messaging ${version})

View File

@ -8,9 +8,9 @@
#ifndef MESSAGING_INC_MESSAGING_PACKET_HPP_ #ifndef MESSAGING_INC_MESSAGING_PACKET_HPP_
#define MESSAGING_INC_MESSAGING_PACKET_HPP_ #define MESSAGING_INC_MESSAGING_PACKET_HPP_
#include <array>
#include <cstdint>
#include <cstring> #include <cstring>
#include <cstdint>
#include <array>
namespace Messaging namespace Messaging
{ {
@ -20,8 +20,8 @@ struct Packet
{ {
using length_type = std::uint32_t; using length_type = std::uint32_t;
static constexpr std::uint8_t preamble[] = {'A', 'A'}; static constexpr std::uint8_t preamble[] = { 'A', 'A' };
std::array<std::uint8_t, N> data = {0}; std::array<std::uint8_t, N> data = { 0 };
std::uint32_t data_length = 0; std::uint32_t data_length = 0;
const std::uint32_t max_data_length = N; const std::uint32_t max_data_length = N;
@ -34,16 +34,13 @@ struct Packet
} }
Packet() = default; Packet() = default;
Packet(const Packet&) = default; Packet(const Packet&) = default;
Packet(Packet&&) noexcept = default; Packet(Packet&&) noexcept = default;
template<std::size_t data_in_length> template<std::size_t data_in_length>
void copy_data_in(const std::uint8_t (&data_in)[data_in_length]) void copy_data_in(const std::uint8_t (&data_in)[data_in_length])
{ {
const std::uint32_t to_copy_length = const std::uint32_t to_copy_length = std::min(std::uint32_t(data_in_length), max_data_length);
std::min(std::uint32_t(data_in_length), max_data_length);
std::memcpy(data.data(), data_in, to_copy_length); std::memcpy(data.data(), data_in, to_copy_length);
data_length = to_copy_length; data_length = to_copy_length;
@ -52,8 +49,7 @@ struct Packet
template<std::size_t data_in_length> template<std::size_t data_in_length>
void copy_data_in(const std::array<std::uint8_t, data_in_length>& data_in) void copy_data_in(const std::array<std::uint8_t, data_in_length>& data_in)
{ {
const std::uint32_t to_copy_length = const std::uint32_t to_copy_length = std::min(std::uint32_t(data_in_length), max_data_length);
std::min(std::uint32_t(data_in_length), max_data_length);
std::memcpy(data.data(), data_in.data(), to_copy_length); std::memcpy(data.data(), data_in.data(), to_copy_length);
data_length = to_copy_length; data_length = to_copy_length;
@ -61,8 +57,7 @@ struct Packet
bool serialize(std::uint8_t* buffer, const std::uint32_t max_length) bool serialize(std::uint8_t* buffer, const std::uint32_t max_length)
{ {
const std::uint32_t required_size = const std::uint32_t required_size = preamble_length + data_length_length + data_length;
preamble_length + data_length_length + data_length;
if (max_length < required_size) if (max_length < required_size)
return false; return false;
@ -101,9 +96,10 @@ struct Packet
} }
}; };
template<std::size_t N> template <std::size_t N>
constexpr std::uint8_t Packet<N>::preamble[2]; constexpr std::uint8_t Packet<N>::preamble[2];
}// namespace Messaging }
#endif /* MESSAGING_INC_MESSAGING_PACKET_HPP_ */ #endif /* MESSAGING_INC_MESSAGING_PACKET_HPP_ */

View File

@ -5,9 +5,9 @@
#ifndef SKULLC_MESSAGING_PARSER_HPP #ifndef SKULLC_MESSAGING_PARSER_HPP
#define SKULLC_MESSAGING_PARSER_HPP #define SKULLC_MESSAGING_PARSER_HPP
#include <array>
#include <cstdint> #include <cstdint>
#include <cstring> #include <cstring>
#include <array>
namespace Messaging namespace Messaging
{ {
@ -19,10 +19,11 @@ public:
using Packet = P; using Packet = P;
const std::size_t buffer_length = N; const std::size_t buffer_length = N;
Parser() { reset(); } Parser()
{
reset();
}
Parser(const Parser&) = delete; Parser(const Parser&) = delete;
Parser(Parser&&) = delete; Parser(Parser&&) = delete;
void reset() void reset()
@ -42,20 +43,20 @@ public:
switch (_state) switch (_state)
{ {
case _State::Preamble: case _State::Preamble:
if (byte != P::preamble[_current_pos]) if (byte != P::preamble[_current_pos])
{ {
reset(); reset();
return; return;
} }
[[fallthrough]]; [[fallthrough]];
case _State::Length: case _State::Length:
case _State::Body: case _State::Body:
_buffer[buffer_loc] = byte; _buffer[buffer_loc] = byte;
_current_pos++; _current_pos++;
break; break;
default: default:
break; break;
} }
if (_current_pos == _expected) if (_current_pos == _expected)
@ -64,7 +65,10 @@ public:
} }
} }
bool packetReady() const { return _state == _State::Done; } bool packetReady() const
{
return _state == _State::Done;
}
bool getPacket(Packet& packet) const bool getPacket(Packet& packet) const
{ {
@ -102,19 +106,19 @@ private:
{ {
switch (_state) switch (_state)
{ {
case _State::Preamble: case _State::Preamble:
_state = _State::Length; _state = _State::Length;
_expected = sizeof(typename P::length_type); _expected = sizeof(typename P::length_type);
break; break;
case _State::Length: case _State::Length:
_state = _State::Body; _state = _State::Body;
_expected = _deserializeLength<typename P::length_type>(_current_offset); _expected = _deserializeLength<typename P::length_type>(_current_offset);
break; break;
case _State::Body: case _State::Body:
_state = _State::Done; _state = _State::Done;
break; break;
default: default:
break; break;
} }
_current_offset += _current_pos; _current_offset += _current_pos;
@ -122,6 +126,6 @@ private:
} }
}; };
}// namespace Messaging }
#endif// SKULLC_MESSAGING_PARSER_HPP #endif //SKULLC_MESSAGING_PARSER_HPP

View File

@ -8,8 +8,8 @@
#ifndef PERIPHERALS_INC_PERIPHERALS_ADC_HPP_ #ifndef PERIPHERALS_INC_PERIPHERALS_ADC_HPP_
#define PERIPHERALS_INC_PERIPHERALS_ADC_HPP_ #define PERIPHERALS_INC_PERIPHERALS_ADC_HPP_
#include <array>
#include <cstdint> #include <cstdint>
#include <array>
#include <adc.h> #include <adc.h>
@ -19,14 +19,19 @@ namespace Peripherals
template<std::size_t N> template<std::size_t N>
struct Adc struct Adc
{ {
std::array<std::uint16_t, N> readings = {0}; std::array<std::uint16_t, N> readings = { 0 };
ADC_HandleTypeDef* hadc = nullptr; ADC_HandleTypeDef* hadc = nullptr;
static constexpr std::uint32_t readingsCount() { return N; } static constexpr std::uint32_t readingsCount()
{
return N;
}
Adc() = delete; Adc() = delete;
explicit Adc(ADC_HandleTypeDef* hadc) : hadc(hadc) {} explicit Adc(ADC_HandleTypeDef* hadc)
: hadc(hadc)
{ }
Adc(const Adc&) = delete; Adc(const Adc&) = delete;
Adc(Adc&&) = delete; Adc(Adc&&) = delete;
@ -51,13 +56,16 @@ struct Adc
void startDma() void startDma()
{ {
HAL_ADC_Start_DMA(hadc, reinterpret_cast<std::uint32_t*>(readings.data()), HAL_ADC_Start_DMA(hadc, reinterpret_cast<std::uint32_t*>(readings.data()), readingsCount());
readingsCount());
} }
void stopDma() { HAL_ADC_Stop_DMA(hadc); } void stopDma()
{
HAL_ADC_Stop_DMA(hadc);
}
}; };
}// namespace Peripherals }
#endif /* PERIPHERALS_INC_PERIPHERALS_ADC_HPP_ */ #endif /* PERIPHERALS_INC_PERIPHERALS_ADC_HPP_ */

View File

@ -22,14 +22,19 @@ namespace St
{ {
template<typename Origin> template<typename Origin>
using IsrCallbackFn = void (*)(Origin*); using IsrCallbackFn = void(*)(Origin*);
template<typename Origin, typename Handler, void (Handler::*func)(), template<typename Origin, typename Handler, void (Handler::*func)(), typename Tag>
typename Tag>
IsrCallbackFn<Origin> createCallback(Handler& h_in) IsrCallbackFn<Origin> createCallback(Handler& h_in)
{ {
static Handler* h = &h_in; static Handler* h = &h_in;
return +[](Origin*) { (h->*func)(); }; printf("Set handler: %p\n", h);
return +[](Origin*)
{
printf("Into callback we go.\n");
(h->*func)();
printf("And we're out.\n");
};
} }
struct StaticHal struct StaticHal
@ -51,19 +56,24 @@ struct StaticHal
static void DelayUs(const std::uint32_t micros) static void DelayUs(const std::uint32_t micros)
{ {
#ifdef USE_DELAY_US #ifdef USE_DELAY_US
const std::uint32_t tick_start = DWT->CYCCNT; const std::uint32_t tick_start = DWT->CYCCNT;
const std::uint32_t ticks_delay = micros * (SystemCoreClock / 1'000'000); const std::uint32_t ticks_delay = micros * (SystemCoreClock / 1'000'000);
while (DWT->CYCCNT - tick_start < ticks_delay) while (DWT->CYCCNT - tick_start < ticks_delay);
;
#else #else
(void) micros; (void)micros;
#endif #endif
} }
static void enableInterrupts() { __enable_irq(); } static void enableInterrupts()
{
__enable_irq();
}
static void disableInterrupts() { __disable_irq(); } static void disableInterrupts()
{
__disable_irq();
}
}; };
#ifdef HAL_GPIO_MODULE_ENABLED #ifdef HAL_GPIO_MODULE_ENABLED
@ -75,33 +85,40 @@ struct Gpio
Gpio() = delete; Gpio() = delete;
explicit Gpio(GPIO_TypeDef* port, const std::uint16_t pin) explicit Gpio(GPIO_TypeDef* port, const std::uint16_t pin)
: port(port), pin(pin) {} : port(port)
, pin(pin)
{ }
void Set(const bool& state) void Set(const bool& state)
{ {
HAL_GPIO_WritePin(port, pin, GPIO_PinState(state)); HAL_GPIO_WritePin(port, pin, GPIO_PinState(state));
} }
void Toggle() { HAL_GPIO_TogglePin(port, pin); } void Toggle()
{
HAL_GPIO_TogglePin(port, pin);
}
bool Read() const { return HAL_GPIO_ReadPin(port, pin); } bool Read() const
{
return HAL_GPIO_ReadPin(port, pin);
}
}; };
#endif// HAL_GPIO_MODULE_ENABLED #endif // HAL_GPIO_MODULE_ENABLED
template< template<typename T,
typename T, HAL_StatusTypeDef (*transmit)(T*, std::uint8_t* data, std::uint16_t data_len, std::uint32_t timeout),
HAL_StatusTypeDef (*transmit)( HAL_StatusTypeDef (*receive)(T*, std::uint8_t* data, std::uint16_t data_len, std::uint32_t timeout)>
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 struct SerialInterface
{ {
using underlying_handle_type = T; using underlying_handle_type = T;
underlying_handle_type* handle; underlying_handle_type* handle;
SerialInterface() = delete; SerialInterface() = delete;
explicit SerialInterface(underlying_handle_type* handle) : handle(handle) {} explicit SerialInterface(underlying_handle_type* handle)
: handle(handle)
{ }
bool Transmit(std::uint8_t* data, const std::uint32_t data_len) bool Transmit(std::uint8_t* data, const std::uint32_t data_len)
{ {
@ -115,10 +132,8 @@ struct SerialInterface
}; };
template<typename T, template<typename T,
HAL_StatusTypeDef (*transmit)(T*, std::uint8_t* data, HAL_StatusTypeDef (*transmit)(T*, std::uint8_t* data, std::uint16_t data_len),
std::uint16_t data_len), HAL_StatusTypeDef (*receive)(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 struct SerialInterfaceAsync
{ {
using underlying_handle_type = T; using underlying_handle_type = T;
@ -126,7 +141,8 @@ struct SerialInterfaceAsync
SerialInterfaceAsync() = delete; SerialInterfaceAsync() = delete;
explicit SerialInterfaceAsync(underlying_handle_type* handle) explicit SerialInterfaceAsync(underlying_handle_type* handle)
: handle(handle) {} : handle(handle)
{ }
bool Transmit(std::uint8_t* data, const std::uint32_t data_len) bool Transmit(std::uint8_t* data, const std::uint32_t data_len)
{ {
@ -141,8 +157,7 @@ struct SerialInterfaceAsync
#ifdef HAL_SPI_MODULE_ENABLED #ifdef HAL_SPI_MODULE_ENABLED
using SpiInterface = using SpiInterface = SerialInterface<SPI_HandleTypeDef, HAL_SPI_Transmit, HAL_SPI_Receive>;
SerialInterface<SPI_HandleTypeDef, HAL_SPI_Transmit, HAL_SPI_Receive>;
struct SpiRegisters struct SpiRegisters
{ {
@ -151,7 +166,9 @@ struct SpiRegisters
SpiRegisters() = delete; SpiRegisters() = delete;
explicit SpiRegisters(const SpiInterface& handle, const Gpio& chip_select) explicit SpiRegisters(const SpiInterface& handle, const Gpio& chip_select)
: handle(handle), chip_select(chip_select) {} : handle(handle)
, chip_select(chip_select)
{ }
void WriteRegister(std::uint8_t reg, uint8_t data) void WriteRegister(std::uint8_t reg, uint8_t data)
{ {
@ -163,8 +180,7 @@ struct SpiRegisters
chip_select.Set(true); chip_select.Set(true);
} }
void WriteRegisterMultibyte(std::uint8_t reg, std::uint8_t* data, void WriteRegisterMultibyte(std::uint8_t reg, std::uint8_t* data, const std::uint32_t len)
const std::uint32_t len)
{ {
chip_select.Set(false); chip_select.Set(false);
@ -174,8 +190,7 @@ struct SpiRegisters
chip_select.Set(true); chip_select.Set(true);
} }
std::uint8_t ReadRegister(std::uint8_t reg, std::uint8_t ReadRegister(std::uint8_t reg, const std::uint32_t read_delay = 0)
const std::uint32_t read_delay = 0)
{ {
chip_select.Set(false); chip_select.Set(false);
@ -193,9 +208,7 @@ struct SpiRegisters
return output; return output;
} }
void ReadRegisterMultibyte(std::uint8_t reg, std::uint8_t* data, void ReadRegisterMultibyte(std::uint8_t reg, std::uint8_t* data, const std::uint32_t len, const std::uint32_t read_delay = 0)
const std::uint32_t len,
const std::uint32_t read_delay = 0)
{ {
chip_select.Set(false); chip_select.Set(false);
@ -210,17 +223,14 @@ struct SpiRegisters
} }
}; };
#endif// HAL_SPI_MODULE_ENABLED #endif // HAL_SPI_MODULE_ENABLED
#ifdef HAL_UART_MODULE_ENABLED #ifdef HAL_UART_MODULE_ENABLED
using UartInterface = using UartInterface = SerialInterface<UART_HandleTypeDef, HAL_UART_Transmit, HAL_UART_Receive>;
SerialInterface<UART_HandleTypeDef, HAL_UART_Transmit, HAL_UART_Receive>; using UartInterfaceDMA = SerialInterfaceAsync<UART_HandleTypeDef, HAL_UART_Transmit_DMA, HAL_UART_Receive_DMA>;
using UartInterfaceDMA =
SerialInterfaceAsync<UART_HandleTypeDef, HAL_UART_Transmit_DMA,
HAL_UART_Receive_DMA>;
#endif// HAL_UART_MODULE_ENABLED #endif // HAL_UART_MODULE_ENABLED
#ifdef HAL_TIM_MODULE_ENABLED #ifdef HAL_TIM_MODULE_ENABLED
@ -231,21 +241,32 @@ struct PwmChannel
PwmChannel() = delete; PwmChannel() = delete;
explicit PwmChannel(TIM_HandleTypeDef* handle, const std::uint32_t channel) explicit PwmChannel(TIM_HandleTypeDef* handle, const std::uint32_t channel)
: handle(handle), channel(channel) {} : handle(handle)
, channel(channel)
{ }
void Enable() { HAL_TIM_PWM_Start(handle, channel); } void Enable()
{
HAL_TIM_PWM_Start(handle, channel);
}
void Disable() { HAL_TIM_PWM_Stop(handle, channel); } void Disable()
{
HAL_TIM_PWM_Stop(handle, channel);
}
void SetCompare(const std::uint32_t compare) void SetCompare(const std::uint32_t compare)
{ {
__HAL_TIM_SET_COMPARE(handle, channel, compare); __HAL_TIM_SET_COMPARE(handle, channel, compare);
} }
std::uint32_t MaxValue() { return handle->Init.Period; } std::uint32_t MaxValue()
{
return handle->Init.Period;
}
}; };
#endif// HAL_TIM_MODULE_ENABLED #endif // HAL_TIM_MODULE_ENABLED
struct ItmSerialInterface struct ItmSerialInterface
{ {
@ -259,8 +280,8 @@ struct ItmSerialInterface
} }
}; };
}// namespace St }
}// namespace Hal }
}// namespace Peripherals }
#endif /* PERIPHERALS_INC_PERIPHERALS_HAL_ST_HPP_ */ #endif /* PERIPHERALS_INC_PERIPHERALS_HAL_ST_HPP_ */

View File

@ -16,23 +16,24 @@ namespace Peripherals
class IImu class IImu
{ {
public: public:
enum class Axis : std::uint32_t enum class Axis : std::uint32_t
{ {
X = 0, X = 0,
Y, Y,
Z Z
}; };
virtual void Setup() = 0; virtual void Setup() = 0;
virtual void Calibrate(const std::uint32_t samples) = 0; virtual void Calibrate(const std::uint32_t samples) = 0;
virtual void ReadGyro(float* output) = 0; virtual void ReadGyro(float* output) = 0;
virtual void ReadGyroRaw(std::int16_t* output) = 0; virtual void ReadGyroRaw(std::int16_t* output) = 0;
virtual void ReadAccelerometer(float* output) = 0; virtual void ReadAccelerometer(float* output) = 0;
virtual void ReadAccelerometerRaw(std::int16_t* output) = 0; virtual void ReadAccelerometerRaw(std::int16_t* output) = 0;
}; };
}// namespace Peripherals }
#endif /* PERIPHERALS_IMU_HPP_ */ #endif /* PERIPHERALS_IMU_HPP_ */

View File

@ -24,269 +24,259 @@ public:
using registers_handle = T; using registers_handle = T;
using hal = HAL; using hal = HAL;
enum class GyroScale : std::uint32_t enum class GyroScale : std::uint32_t
{ {
DPS_250 = 0, DPS_250 = 0,
DPS_500, DPS_500,
DPS_1000, DPS_1000,
DPS_2000 DPS_2000
}; };
enum class AccelerometerScale : std::uint32_t enum class AccelerometerScale : std::uint32_t
{ {
G2 = 0, G2 = 0,
G4, G4,
G8, G8,
G16 G16
}; };
registers_handle registers; registers_handle registers;
ImuIcm() = delete; ImuIcm() = delete;
ImuIcm(const registers_handle& registers) : registers(registers) {} ImuIcm(const registers_handle& registers)
: registers(registers)
{ }
void Setup() override void Setup() override
{ {
registers.WriteRegister(_Registers::PWR_MGMT_1 & _Registers::WRITE_MASK, registers.WriteRegister(_Registers::PWR_MGMT_1 & _Registers::WRITE_MASK, 0b10000000);
0b10000000); hal::Delay(10);
hal::Delay(10);
registers.WriteRegister(_Registers::USER_CTRL & _Registers::WRITE_MASK, registers.WriteRegister(_Registers::USER_CTRL & _Registers::WRITE_MASK, 0b00010000);
0b00010000); hal::Delay(10);
hal::Delay(10);
registers.WriteRegister(_Registers::PWR_MGMT_1 & _Registers::WRITE_MASK, registers.WriteRegister(_Registers::PWR_MGMT_1 & _Registers::WRITE_MASK, 0b00000000);
0b00000000); hal::Delay(10);
hal::Delay(10);
registers.WriteRegister(_Registers::PWR_MGMT_1 & _Registers::WRITE_MASK, registers.WriteRegister(_Registers::PWR_MGMT_1 & _Registers::WRITE_MASK, 0b00000001);
0b00000001); hal::Delay(10);
hal::Delay(10);
registers.WriteRegister(_Registers::CONFIG & _Registers::WRITE_MASK, registers.WriteRegister(_Registers::CONFIG & _Registers::WRITE_MASK, 0x03); // DLPF_CFG = 3, gyro filter = 41/59.0, gyro rate = 1KHz, temp filter = 42
0x03);// DLPF_CFG = 3, gyro filter = 41/59.0, gyro hal::Delay(10);
// rate = 1KHz, temp filter = 42
hal::Delay(10);
SetGyroscopeScale(_scale_gyro); SetGyroscopeScale(_scale_gyro);
SetAccelerometerScale(_scale_accel); SetAccelerometerScale(_scale_accel);
// ACCEL_FCHOICE_B = 0, A_DLPF_CFG = 3 filter=44.8/61.5 rate=1KHz // ACCEL_FCHOICE_B = 0, A_DLPF_CFG = 3 filter=44.8/61.5 rate=1KHz
registers.WriteRegister(_Registers::ACCEL_CONFIG2 & _Registers::WRITE_MASK, registers.WriteRegister(_Registers::ACCEL_CONFIG2 & _Registers::WRITE_MASK, 0x03);
0x03); hal::Delay(10);
hal::Delay(10);
// SAMPLE_RATE = INTERNAL_SAMPLE_RATE / (1 + SMPLRT_DIV) Where // SAMPLE_RATE = INTERNAL_SAMPLE_RATE / (1 + SMPLRT_DIV) Where INTERNAL_SAMPLE_RATE = 1kHz
// INTERNAL_SAMPLE_RATE = 1kHz registers.WriteRegister(_Registers::SMPLRT_DIV & _Registers::WRITE_MASK, 0);
registers.WriteRegister(_Registers::SMPLRT_DIV & _Registers::WRITE_MASK, 0); hal::Delay(10);
hal::Delay(10);
// Enable interrupt // Enable interrupt
// The logic level for INT/DRDY pin is active high. // The logic level for INT/DRDY pin is active high.
// INT/DRDY pin is configured as push-pull. // INT/DRDY pin is configured as push-pull.
// INT/DRDY pin indicates interrupt pulse's width is 50us. // INT/DRDY pin indicates interrupt pulse's width is 50us.
// Interrupt status is cleared only by reading INT_STATUS register // Interrupt status is cleared only by reading INT_STATUS register
registers.WriteRegister(_Registers::INT_PIN_CFG & _Registers::WRITE_MASK, registers.WriteRegister(_Registers::INT_PIN_CFG & _Registers::WRITE_MASK, 0);
0); hal::Delay(10);
hal::Delay(10);
registers.WriteRegister(_Registers::INT_ENABLE & _Registers::WRITE_MASK, 1); registers.WriteRegister(_Registers::INT_ENABLE & _Registers::WRITE_MASK, 1);
hal::Delay(10); hal::Delay(10);
} }
void Calibrate(const std::uint32_t samples) override void Calibrate(const std::uint32_t samples) override
{ {
std::array<std::int32_t, 3> avg_gyro; std::array<std::int32_t, 3> avg_gyro;
std::array<std::int32_t, 3> avg_accel; std::array<std::int32_t, 3> avg_accel;
for (std::uint32_t i = 0; i < samples; i++) for (std::uint32_t i = 0; i < samples; i++)
{ {
std::array<std::int16_t, 3> raw; std::array<std::int16_t, 3> raw;
auto add_to_avg = [&raw](std::array<std::int32_t, 3>& out) { auto add_to_avg = [&raw](std::array<std::int32_t, 3>& out)
for (std::uint32_t j = 0; j < 3; j++) {
out[j] += raw[j]; for (std::uint32_t j = 0; j < 3; j++)
}; out[j] += raw[j];
};
ReadGyroRaw(raw.data()); ReadGyroRaw(raw.data());
add_to_avg(avg_gyro); add_to_avg(avg_gyro);
ReadAccelerometerRaw(raw.data()); ReadAccelerometerRaw(raw.data());
add_to_avg(avg_accel); add_to_avg(avg_accel);
} }
for (std::uint32_t i = 0; i < 3; i++) for (std::uint32_t i = 0; i < 3; i++)
{ {
const std::int32_t max = std::numeric_limits<std::int16_t>::max(); const std::int32_t max = std::numeric_limits<std::int16_t>::max();
const std::int32_t min = std::numeric_limits<std::int16_t>::min(); const std::int32_t min = std::numeric_limits<std::int16_t>::min();
_bias_gyro[i] = Clamp(avg_gyro[i], max, min); _bias_gyro[i] = Clamp(avg_gyro[i], max, min);
_bias_accel[i] = Clamp(avg_accel[i], max, min); _bias_accel[i] = Clamp(avg_accel[i], max, min);
} }
_bias_accel[2] -= AccelerometerReadingToRaw(1); _bias_accel[2] -= AccelerometerReadingToRaw(1);
} }
void SetGyroscopeScale(const GyroScale scale) void SetGyroscopeScale(const GyroScale scale)
{ {
const std::uint8_t current_config = const std::uint8_t current_config = registers.ReadRegister(_Registers::GYRO_CONFIG | _Registers::READ_MASK);
registers.ReadRegister(_Registers::GYRO_CONFIG | _Registers::READ_MASK); const std::uint8_t new_config = (current_config & 0xE7) | (std::uint8_t(scale) << 3);
const std::uint8_t new_config = registers.WriteRegister(_Registers::GYRO_CONFIG & _Registers::WRITE_MASK, new_config);
(current_config & 0xE7) | (std::uint8_t(scale) << 3);
registers.WriteRegister(_Registers::GYRO_CONFIG & _Registers::WRITE_MASK,
new_config);
_scale_gyro = scale; _scale_gyro = scale;
} }
void SetAccelerometerScale(const AccelerometerScale scale) void SetAccelerometerScale(const AccelerometerScale scale)
{ {
const std::uint8_t current_config = registers.ReadRegister( const std::uint8_t current_config = registers.ReadRegister(_Registers::ACCEL_CONFIG | _Registers::READ_MASK);
_Registers::ACCEL_CONFIG | _Registers::READ_MASK); const std::uint8_t new_config = (current_config & 0xE7) | (std::uint8_t(scale) << 3);
const std::uint8_t new_config = registers.WriteRegister(_Registers::ACCEL_CONFIG & _Registers::WRITE_MASK, new_config);
(current_config & 0xE7) | (std::uint8_t(scale) << 3);
registers.WriteRegister(_Registers::ACCEL_CONFIG & _Registers::WRITE_MASK,
new_config);
_scale_accel = scale; _scale_accel = scale;
} }
void ReadGyro(float* output) override void ReadGyro(float* output) override
{ {
uint8_t data[6] = {0}; uint8_t data[6] = { 0 };
registers.ReadRegisterMultibyte( registers.ReadRegisterMultibyte(_Registers::GYRO_XOUT_H | _Registers::READ_MASK, data, 6);
_Registers::GYRO_XOUT_H | _Registers::READ_MASK, data, 6);
for (std::uint32_t i = 0; i < 3; i++) for (std::uint32_t i = 0; i < 3; i++)
{ {
const std::int16_t bit = ByteToTypeBE<std::int16_t, 2>(&data[i * 2]); const std::int16_t bit = ByteToTypeBE<std::int16_t, 2>(&data[i * 2]);
output[i] = GyroRawToReading(bit); output[i] = GyroRawToReading(bit);
} }
} }
void ReadGyroRaw(std::int16_t* output) override void ReadGyroRaw(std::int16_t* output) override
{ {
uint8_t data[6] = {0}; uint8_t data[6] = { 0 };
registers.ReadRegisterMultibyte( registers.ReadRegisterMultibyte(_Registers::GYRO_XOUT_H | _Registers::READ_MASK, data, 6);
_Registers::GYRO_XOUT_H | _Registers::READ_MASK, data, 6);
for (std::uint32_t i = 0; i < 3; i++) for (std::uint32_t i = 0; i < 3; i++)
{ {
output[i] = ByteToTypeBE<std::int16_t, 2>(&data[i * 2]); output[i] = ByteToTypeBE<std::int16_t, 2>(&data[i * 2]);
} }
} }
void ReadAccelerometer(float* output) override void ReadAccelerometer(float* output) override
{ {
uint8_t data[6] = {0}; uint8_t data[6] = { 0 };
registers.ReadRegisterMultibyte( registers.ReadRegisterMultibyte(_Registers::ACCEL_XOUT_H | _Registers::READ_MASK, data, 6);
_Registers::ACCEL_XOUT_H | _Registers::READ_MASK, data, 6);
for (std::uint32_t i = 0; i < 3; i++) for (std::uint32_t i = 0; i < 3; i++)
{ {
const std::int16_t bit = ByteToTypeBE<std::int16_t, 2>(&data[i * 2]); const std::int16_t bit = ByteToTypeBE<std::int16_t, 2>(&data[i * 2]);
output[i] = AccelerometerRawToReading(bit); output[i] = AccelerometerRawToReading(bit);
} }
} }
void ReadAccelerometerRaw(std::int16_t* output) override void ReadAccelerometerRaw(std::int16_t* output) override
{ {
uint8_t data[6] = {0}; uint8_t data[6] = { 0 };
registers.ReadRegisterMultibyte( registers.ReadRegisterMultibyte(_Registers::ACCEL_XOUT_H | _Registers::READ_MASK, data, 6);
_Registers::ACCEL_XOUT_H | _Registers::READ_MASK, data, 6);
for (std::uint32_t i = 0; i < 3; i++) for (std::uint32_t i = 0; i < 3; i++)
{ {
output[i] = ByteToTypeBE<std::int16_t, 2>(&data[i * 2]); output[i] = ByteToTypeBE<std::int16_t, 2>(&data[i * 2]);
} }
} }
std::int16_t AccelerometerReadingToRaw(const float& fs) const std::int16_t AccelerometerReadingToRaw(const float& fs) const
{ {
return fs / _accel_fs_to_bit_constants[std::uint32_t(_scale_accel)]; return fs / _accel_fs_to_bit_constants[std::uint32_t(_scale_accel)];
} }
std::int16_t GyroReadingToRaw(const float& fs) const std::int16_t GyroReadingToRaw(const float& fs) const
{ {
return fs / _gyro_fs_to_bit_constants[std::uint32_t(_scale_gyro)]; return fs / _gyro_fs_to_bit_constants[std::uint32_t(_scale_gyro)];
} }
float AccelerometerRawToReading(const std::int16_t bit) const float AccelerometerRawToReading(const std::int16_t bit) const
{ {
return float(bit) * _accel_fs_to_bit_constants[std::uint32_t(_scale_accel)]; return float(bit) * _accel_fs_to_bit_constants[std::uint32_t(_scale_accel)];
} }
float GyroRawToReading(const std::int16_t bit) const float GyroRawToReading(const std::int16_t bit) const
{ {
return float(bit) * _gyro_fs_to_bit_constants[std::uint32_t(_scale_gyro)]; return float(bit) * _gyro_fs_to_bit_constants[std::uint32_t(_scale_gyro)];
} }
private: private:
GyroScale _scale_gyro = GyroScale::DPS_2000; GyroScale _scale_gyro = GyroScale::DPS_2000;
AccelerometerScale _scale_accel = AccelerometerScale::G16; AccelerometerScale _scale_accel = AccelerometerScale::G16;
std::array<std::int16_t, 3> _bias_gyro; std::array<std::int16_t, 3> _bias_gyro;
std::array<std::int16_t, 3> _bias_accel; std::array<std::int16_t, 3> _bias_accel;
static constexpr float _accel_fs_to_bit_constants[4] = { static constexpr float _accel_fs_to_bit_constants[4] = {
(2.0f / 32768.0f), (4.0f / 32768.0f), (8.0f / 32768.0f), (2.0f / 32768.0f),
(16.0f / 32768.0f)}; (4.0f / 32768.0f),
(8.0f / 32768.0f),
(16.0f / 32768.0f)
};
static constexpr float _gyro_fs_to_bit_constants[4] = { static constexpr float _gyro_fs_to_bit_constants[4] = {
(250.0f / 32768.0f), (500.0f / 32768.0f), (1000.0f / 32768.0f), (250.0f / 32768.0f),
(2000.0f / 32768.0f)}; (500.0f / 32768.0f),
(1000.0f / 32768.0f),
(2000.0f / 32768.0f)
};
struct _Registers struct _Registers
{ {
static constexpr std::uint32_t ICM20689_ID = 0x98; static constexpr std::uint32_t ICM20689_ID = 0x98;
static constexpr std::uint8_t READ_MASK = 0x80; static constexpr std::uint8_t READ_MASK = 0x80;
static constexpr std::uint8_t WRITE_MASK = 0x7F; static constexpr std::uint8_t WRITE_MASK = 0x7F;
static constexpr std::uint8_t SMPLRT_DIV = 0x19; static constexpr std::uint8_t SMPLRT_DIV = 0x19;
static constexpr std::uint8_t CONFIG = 0x1A; static constexpr std::uint8_t CONFIG = 0x1A;
static constexpr std::uint8_t GYRO_CONFIG = 0x1B; static constexpr std::uint8_t GYRO_CONFIG = 0x1B;
static constexpr std::uint8_t ACCEL_CONFIG = 0x1C; static constexpr std::uint8_t ACCEL_CONFIG =0x1C;
static constexpr std::uint8_t ACCEL_CONFIG2 = 0x1D; static constexpr std::uint8_t ACCEL_CONFIG2=0x1D;
static constexpr std::uint8_t INT_PIN_CFG = 0x37; static constexpr std::uint8_t INT_PIN_CFG = 0x37;
static constexpr std::uint8_t INT_ENABLE = 0x38; static constexpr std::uint8_t INT_ENABLE = 0x38;
static constexpr std::uint8_t INT_STATUS = 0x3A; static constexpr std::uint8_t INT_STATUS = 0x3A;
static constexpr std::uint8_t GYRO_XOUT_H = 0x43; static constexpr std::uint8_t GYRO_XOUT_H = 0x43;
static constexpr std::uint8_t GYRO_XOUT_L = 0x44; static constexpr std::uint8_t GYRO_XOUT_L = 0x44;
static constexpr std::uint8_t GYRO_YOUT_H = 0x45; static constexpr std::uint8_t GYRO_YOUT_H = 0x45;
static constexpr std::uint8_t GYRO_YOUT_L = 0x46; static constexpr std::uint8_t GYRO_YOUT_L = 0x46;
static constexpr std::uint8_t GYRO_ZOUT_H = 0x47; static constexpr std::uint8_t GYRO_ZOUT_H = 0x47;
static constexpr std::uint8_t GYRO_ZOUT_L = 0x48; static constexpr std::uint8_t GYRO_ZOUT_L = 0x48;
static constexpr std::uint8_t ACCEL_XOUT_H = 0x3B; static constexpr std::uint8_t ACCEL_XOUT_H =0x3B;
static constexpr std::uint8_t ACCEL_XOUT_L = 0x3C; static constexpr std::uint8_t ACCEL_XOUT_L =0x3C;
static constexpr std::uint8_t ACCEL_YOUT_H = 0x3D; static constexpr std::uint8_t ACCEL_YOUT_H =0x3D;
static constexpr std::uint8_t ACCEL_YOUT_L = 0x3E; static constexpr std::uint8_t ACCEL_YOUT_L =0x3E;
static constexpr std::uint8_t ACCEL_ZOUT_H = 0x3F; static constexpr std::uint8_t ACCEL_ZOUT_H =0x3F;
static constexpr std::uint8_t ACCEL_ZOUT_L = 0x40; static constexpr std::uint8_t ACCEL_ZOUT_L =0x40;
static constexpr std::uint8_t USER_CTRL = 0x6A; static constexpr std::uint8_t USER_CTRL = 0x6A;
static constexpr std::uint8_t PWR_MGMT_1 = 0x6B; static constexpr std::uint8_t PWR_MGMT_1 = 0x6B;
static constexpr std::uint8_t PWR_MGMT_2 = 0x6C; static constexpr std::uint8_t PWR_MGMT_2 = 0x6C;
static constexpr std::uint8_t WHO_AM_I = 0x75; static constexpr std::uint8_t WHO_AM_I = 0x75;
static constexpr std::uint8_t XG_OFFSET_H = 0x13; static constexpr std::uint8_t XG_OFFSET_H = 0x13;
static constexpr std::uint8_t XG_OFFSET_L = 0x14; static constexpr std::uint8_t XG_OFFSET_L = 0x14;
static constexpr std::uint8_t YG_OFFSET_H = 0x15; static constexpr std::uint8_t YG_OFFSET_H = 0x15;
static constexpr std::uint8_t YG_OFFSET_L = 0x16; static constexpr std::uint8_t YG_OFFSET_L = 0x16;
static constexpr std::uint8_t ZG_OFFSET_H = 0x17; static constexpr std::uint8_t ZG_OFFSET_H = 0x17;
static constexpr std::uint8_t ZG_OFFSET_L = 0x18; static constexpr std::uint8_t ZG_OFFSET_L = 0x18;
static constexpr std::uint8_t XA_OFFSET_H = 0x77; static constexpr std::uint8_t XA_OFFSET_H = 0x77;
static constexpr std::uint8_t XA_OFFSET_L = 0x78; static constexpr std::uint8_t XA_OFFSET_L = 0x78;
static constexpr std::uint8_t YA_OFFSET_H = 0x7A; static constexpr std::uint8_t YA_OFFSET_H = 0x7A;
static constexpr std::uint8_t YA_OFFSET_L = 0x7B; static constexpr std::uint8_t YA_OFFSET_L = 0x7B;
static constexpr std::uint8_t ZA_OFFSET_H = 0x7D; static constexpr std::uint8_t ZA_OFFSET_H = 0x7D;
static constexpr std::uint8_t ZA_OFFSET_L = 0x7E; static constexpr std::uint8_t ZA_OFFSET_L = 0x7E;
}; };
}; };
template<typename T, typename HAL> template<typename T, typename HAL>
@ -295,6 +285,6 @@ constexpr float ImuIcm<T, HAL>::_accel_fs_to_bit_constants[4];
template<typename T, typename HAL> template<typename T, typename HAL>
constexpr float ImuIcm<T, HAL>::_gyro_fs_to_bit_constants[4]; constexpr float ImuIcm<T, HAL>::_gyro_fs_to_bit_constants[4];
}// namespace Peripherals }
#endif /* PERIPHERALS_IMU_ICM_HPP_ */ #endif /* PERIPHERALS_IMU_ICM_HPP_ */

View File

@ -22,9 +22,9 @@ struct TwoChannelMotorData
class IMotors class IMotors
{ {
public: public:
virtual void Set(const std::int16_t left, const std::int16_t right) = 0; virtual void Set(const std::int16_t left, const std::int16_t right) = 0;
virtual void Coast() = 0; virtual void Coast() = 0;
virtual void Break() = 0; virtual void Break() = 0;
}; };
template<typename T, typename I> template<typename T, typename I>
@ -34,65 +34,69 @@ public:
using single_motor = TwoChannelMotorData<T>; using single_motor = TwoChannelMotorData<T>;
using gpio = I; using gpio = I;
DualDrvMotors(const single_motor& left, const single_motor& right, DualDrvMotors(const single_motor& left, const single_motor& right, const gpio& sleep_pin)
const gpio& sleep_pin) : _left(left)
: _left(left), _right(right), _sleep_pin(sleep_pin) , _right(right)
, _sleep_pin(sleep_pin)
{ {
_left.forward.Enable(); _left.forward.Enable();
_left.backward.Enable(); _left.backward.Enable();
_right.forward.Enable(); _right.forward.Enable();
_right.backward.Enable(); _right.backward.Enable();
Set(0, 0); Set(0, 0);
} }
virtual void Set(const std::int16_t left, const std::int16_t right) override virtual void Set(const std::int16_t left, const std::int16_t right) override
{ {
if (left > 0) if (left > 0)
{ {
_left.forward.SetCompare(left); _left.forward.SetCompare(left);
_left.backward.SetCompare(0); _left.backward.SetCompare(0);
} else }
{ else
_left.forward.SetCompare(0); {
_left.backward.SetCompare(-1 * left); _left.forward.SetCompare(0);
} _left.backward.SetCompare(-1 * left);
}
if (right > 0) if (right > 0)
{ {
_right.forward.SetCompare(right); _right.forward.SetCompare(right);
_right.backward.SetCompare(0); _right.backward.SetCompare(0);
} else }
{ else
_right.forward.SetCompare(0); {
_right.backward.SetCompare(-1 * right); _right.forward.SetCompare(0);
} _right.backward.SetCompare(-1 * right);
} }
}
virtual void Coast() override virtual void Coast() override
{ {
_left.forward.SetCompare(0); _left.forward.SetCompare(0);
_left.backward.SetCompare(0); _left.backward.SetCompare(0);
_right.forward.SetCompare(0); _right.forward.SetCompare(0);
_right.backward.SetCompare(0); _right.backward.SetCompare(0);
} }
virtual void Break() override virtual void Break() override
{ {
_left.forward.SetCompare(_left.forward.MaxValue()); _left.forward.SetCompare(_left.forward.MaxValue());
_left.backward.SetCompare(_left.backward.MaxValue()); _left.backward.SetCompare(_left.backward.MaxValue());
_right.forward.SetCompare(_right.forward.MaxValue()); _right.forward.SetCompare(_right.forward.MaxValue());
_right.backward.SetCompare(_right.backward.MaxValue()); _right.backward.SetCompare(_right.backward.MaxValue());
} }
private: private:
single_motor _left; single_motor _left;
single_motor _right; single_motor _right;
gpio _sleep_pin; gpio _sleep_pin;
}; };
}// namespace Peripherals }
#endif /* PERIPHERALS_MOTORS_HPP_ */ #endif /* PERIPHERALS_MOTORS_HPP_ */

View File

@ -19,25 +19,28 @@ namespace Peripherals
struct PwmChannel struct PwmChannel
{ {
TIM_HandleTypeDef* timer; TIM_HandleTypeDef* timer;
std::uint32_t channel; std::uint32_t channel;
std::uint32_t timer_code; std::uint32_t timer_code;
Io pin; Io pin;
PwmChannel() = delete; PwmChannel() = delete;
PwmChannel(TIM_HandleTypeDef* timer, const std::uint32_t channel, PwmChannel(TIM_HandleTypeDef* timer,
const std::uint32_t timer_code, const Io& pin); const std::uint32_t channel,
const std::uint32_t timer_code,
const Io& pin);
void PinToPwm(); void PinToPwm();
void PinToGpio(); void PinToGpio();
void Enable(); void Enable();
void Disable(); void Disable();
void SetCompare(const std::uint32_t compare); void SetCompare(const std::uint32_t compare);
}; };
}// namespace Peripherals }
#endif /* PERIPHERALS_PWM_CHANNEL_HPP_ */ #endif /* PERIPHERALS_PWM_CHANNEL_HPP_ */

View File

@ -36,7 +36,9 @@ struct Rgb
Rgb() = delete; Rgb() = delete;
Rgb(const IOType& r, const IOType& g, const IOType& b) Rgb(const IOType& r, const IOType& g, const IOType& b)
: red(r), green(g), blue(b) : red(r)
, green(g)
, blue(b)
{ {
Set(RgbColor::OFF); Set(RgbColor::OFF);
} }
@ -47,50 +49,51 @@ struct Rgb
switch (color) switch (color)
{ {
case RgbColor::OFF: case RgbColor::OFF:
red.Set(false); red.Set(false);
green.Set(false); green.Set(false);
blue.Set(false); blue.Set(false);
break; break;
case RgbColor::RED: case RgbColor::RED:
red.Set(true); red.Set(true);
green.Set(false); green.Set(false);
blue.Set(false); blue.Set(false);
break; break;
case RgbColor::GREEN: case RgbColor::GREEN:
red.Set(false); red.Set(false);
green.Set(true); green.Set(true);
blue.Set(false); blue.Set(false);
break; break;
case RgbColor::BLUE: case RgbColor::BLUE:
red.Set(false); red.Set(false);
green.Set(false); green.Set(false);
blue.Set(true); blue.Set(true);
break; break;
case RgbColor::CYAN: case RgbColor::CYAN:
red.Set(false); red.Set(false);
green.Set(true); green.Set(true);
blue.Set(true); blue.Set(true);
break; break;
case RgbColor::PINK: case RgbColor::PINK:
red.Set(true); red.Set(true);
green.Set(false); green.Set(false);
blue.Set(true); blue.Set(true);
break; break;
case RgbColor::YELLOW: case RgbColor::YELLOW:
red.Set(true); red.Set(true);
green.Set(true); green.Set(true);
blue.Set(false); blue.Set(false);
break; break;
case RgbColor::WHITE: case RgbColor::WHITE:
red.Set(true); red.Set(true);
green.Set(true); green.Set(true);
blue.Set(true); blue.Set(true);
break; break;
} }
} }
}; };
}// namespace Peripherals }
#endif /* PERIPHERALS_INC_PERIPHERALS_RGB_HPP_ */ #endif /* PERIPHERALS_INC_PERIPHERALS_RGB_HPP_ */

View File

@ -13,47 +13,48 @@
namespace Peripherals namespace Peripherals
{ {
#define SKULLC_CONCAT_IMPL(x, y) x##y #define SKULLC_CONCAT_IMPL(x, y) x ## y
#define SKULLC_CONCAT(x, y) SKULLC_CONCAT_IMPL(x, y) #define SKULLC_CONCAT(x, y) SKULLC_CONCAT_IMPL(x, y)
#define SKULLC_TAG struct SKULLC_CONCAT(SkullCTag_, __COUNTER__) #define SKULLC_TAG struct SKULLC_CONCAT(SkullCTag_, __COUNTER__)
template<typename T> template<typename T>
constexpr const T& Clamp(const T& v, const T& lo, const T& hi) constexpr const T& Clamp(const T& v, const T& lo, const T& hi)
{ {
if (v > hi) if (v > hi)
return hi; return hi;
else if (v < lo) else if (v < lo)
return lo; return lo;
else else
return v; return v;
} }
template<typename T, std::size_t N> template<typename T, std::size_t N>
T ByteToTypeBE(const std::uint8_t a[N]) T ByteToTypeBE(const std::uint8_t a[N])
{ {
T t(0); T t(0);
for (std::size_t i = 0; i < N; i++) for (std::size_t i = 0; i < N; i++)
{ {
t |= a[i] << (i * 8); t |= a[i] << (i * 8);
} }
return t; return t;
} }
template<typename T, std::size_t N> template<typename T, std::size_t N>
T ByteToTypeLE(const std::uint8_t a[N]) T ByteToTypeLE(const std::uint8_t a[N])
{ {
T t(0); T t(0);
for (std::size_t i = N; i >= 0; i--) for (std::size_t i = N; i >= 0; i--)
{ {
t |= a[i] << ((i - 1) * 8); t |= a[i] << ((i - 1) * 8);
} }
return t;
}
return t;
} }
}// namespace Peripherals
#endif /* PERIPHERALS_UTILITY_HPP_ */ #endif /* PERIPHERALS_UTILITY_HPP_ */

View File

@ -2,6 +2,5 @@
// Created by erki on 13.03.21. // Created by erki on 13.03.21.
// //
#define CATCH_CONFIG_MAIN// This tells Catch to provide a main() - only do this \ #define CATCH_CONFIG_MAIN // This tells Catch to provide a main() - only do this in one cpp file
// in one cpp file
#include <catch2/catch.hpp> #include <catch2/catch.hpp>

View File

@ -12,7 +12,7 @@ TEST_CASE("Packet copy_data_in copies data in.", "[messaging],[packet]")
SECTION("Plain C-array data copies properly.") SECTION("Plain C-array data copies properly.")
{ {
const std::uint8_t data[2] = {'C', 'D'}; const std::uint8_t data[2] = { 'C', 'D' };
const std::uint32_t data_size = sizeof(data); const std::uint32_t data_size = sizeof(data);
packet.copy_data_in(data); packet.copy_data_in(data);
@ -24,7 +24,7 @@ TEST_CASE("Packet copy_data_in copies data in.", "[messaging],[packet]")
SECTION("STL data copies properly.") SECTION("STL data copies properly.")
{ {
const std::array<std::uint8_t, 2> data = {'C', 'D'}; const std::array<std::uint8_t, 2> data = { 'C', 'D' };
packet.copy_data_in(data); packet.copy_data_in(data);
@ -34,12 +34,11 @@ TEST_CASE("Packet copy_data_in copies data in.", "[messaging],[packet]")
} }
} }
TEST_CASE("Packet copying data in cuts off excess bytes.", TEST_CASE("Packet copying data in cuts off excess bytes.", "[messaging],[packet]")
"[messaging],[packet]")
{ {
Messaging::Packet<2> packet; Messaging::Packet<2> packet;
const std::uint8_t data[4] = {'C', 'D', 'E', 'F'}; const std::uint8_t data[4] = { 'C', 'D', 'E', 'F' };
packet.copy_data_in(data); packet.copy_data_in(data);
@ -52,7 +51,7 @@ TEST_CASE("Packet gets serialized properly.", "[messaging],[packet]")
{ {
Messaging::Packet<2> packet; Messaging::Packet<2> packet;
const std::uint8_t data[2] = {'C', 'D'}; const std::uint8_t data[2] = { 'C', 'D' };
const std::uint32_t data_size = sizeof(data); const std::uint32_t data_size = sizeof(data);
packet.copy_data_in(data); packet.copy_data_in(data);
@ -83,15 +82,14 @@ TEST_CASE("Packet gets serialized properly.", "[messaging],[packet]")
} }
} }
TEST_CASE("Packet serialization fails if buffer too small.", TEST_CASE("Packet serialization fails if buffer too small.", "[messaging],[packet]")
"[messaging],[packet]")
{ {
Messaging::Packet<2> packet; Messaging::Packet<2> packet;
const std::uint8_t data[2] = {'C', 'D'}; const std::uint8_t data[2] = { 'C', 'D' };
packet.copy_data_in(data); packet.copy_data_in(data);
std::uint8_t output[4] = {0}; std::uint8_t output[4] = { 0 };
REQUIRE(packet.serialize(output, sizeof(output)) == false); REQUIRE(packet.serialize(output, sizeof(output)) == false);
SECTION("Output buffer is left unmodified.") SECTION("Output buffer is left unmodified.")
@ -105,7 +103,9 @@ TEST_CASE("Packet serialization fails if buffer too small.",
TEST_CASE("Packet deserialization works as expected.", "[messaging],[packet]") TEST_CASE("Packet deserialization works as expected.", "[messaging],[packet]")
{ {
std::uint8_t data[] = {'A', 'A', 0, 0, 0, 0, 'C', 'D'}; std::uint8_t data[] = {
'A', 'A', 0, 0, 0, 0, 'C', 'D'
};
const std::uint32_t data_length = 2; const std::uint32_t data_length = 2;
std::memcpy(data + 2, &data_length, sizeof(data_length)); std::memcpy(data + 2, &data_length, sizeof(data_length));
@ -118,10 +118,11 @@ TEST_CASE("Packet deserialization works as expected.", "[messaging],[packet]")
REQUIRE(packet.data[1] == 'D'); REQUIRE(packet.data[1] == 'D');
} }
TEST_CASE("Packet deserialization fails with invalid conditions.", TEST_CASE("Packet deserialization fails with invalid conditions.", "[messaging],[packet]")
"[messaging],[packet]")
{ {
std::uint8_t data[] = {'A', 'A', 0, 0, 0, 0, 'C', 'D'}; std::uint8_t data[] = {
'A', 'A', 0, 0, 0, 0, 'C', 'D'
};
const std::uint32_t data_length = 2; const std::uint32_t data_length = 2;
std::memcpy(data + 2, &data_length, sizeof(data_length)); std::memcpy(data + 2, &data_length, sizeof(data_length));

View File

@ -4,20 +4,21 @@
#include <catch2/catch.hpp> #include <catch2/catch.hpp>
#include <messaging_packet.hpp>
#include <messaging_parser.hpp> #include <messaging_parser.hpp>
#include <messaging_packet.hpp>
using Packet = Messaging::Packet<2>; using Packet = Messaging::Packet<2>;
namespace namespace
{ {
std::array<std::uint8_t, 2> test_data = {'C', 'D'}; std::array<std::uint8_t, 2> test_data = { 'C', 'D' };
std::array<std::uint8_t, 8> std::array<std::uint8_t, 8> getRawData(const std::array<std::uint8_t, 2>& data)
getRawData(const std::array<std::uint8_t, 2>& data)
{ {
std::array<std::uint8_t, 8> raw = {'A', 'A', 0, 0, 0, 0, data[0], data[1]}; std::array<std::uint8_t, 8> raw = {
'A', 'A', 0, 0, 0, 0, data[0], data[1]
};
const std::uint32_t len = 2; const std::uint32_t len = 2;
std::memcpy(raw.data() + 2, &len, 4); std::memcpy(raw.data() + 2, &len, 4);
@ -25,9 +26,12 @@ getRawData(const std::array<std::uint8_t, 2>& data)
return raw; return raw;
} }
std::array<std::uint8_t, 8> getRawData() { return getRawData({'C', 'D'}); } std::array<std::uint8_t, 8> getRawData()
{
return getRawData({'C', 'D'});
}
}// namespace }
TEST_CASE("Parser parses raw message successfully.", "[messaging],[parser]") TEST_CASE("Parser parses raw message successfully.", "[messaging],[parser]")
{ {
@ -62,7 +66,7 @@ TEST_CASE("Parser ignores extra bytes when done.", "[messaging],[parser]")
REQUIRE(parser.packetReady()); REQUIRE(parser.packetReady());
for (const std::uint8_t& byte : getRawData({'E', 'F'})) for (const std::uint8_t& byte : getRawData({ 'E', 'F' }))
{ {
parser.pushByte(byte); parser.pushByte(byte);
} }
@ -78,12 +82,12 @@ TEST_CASE("Parser ignores extra bytes when done.", "[messaging],[parser]")
} }
} }
TEST_CASE("Parser ignores junk data until header is spotted.", TEST_CASE("Parser ignores junk data until header is spotted.", "[messaging],[parser]")
"[messaging],[parser]")
{ {
Messaging::Parser<Packet, Packet::totalLength()> parser; Messaging::Parser<Packet, Packet::totalLength()> parser;
const std::array<std::uint8_t, 8> junk_data = {'E', 'F', 'A', 'H', const std::array<std::uint8_t, 8> junk_data = {
'I', 'J', 'K', 'L'}; 'E', 'F', 'A', 'H', 'I', 'J', 'K', 'L'
};
for (const std::uint8_t& byte : junk_data) for (const std::uint8_t& byte : junk_data)
{ {

View File

@ -9,7 +9,7 @@
template<size_t N> template<size_t N>
using Ringbuffer = Utility::Ringbuffer<int, N>; using Ringbuffer = Utility::Ringbuffer<int, N>;
TEST_CASE("Ringbuffer iterator", "[utility],[ringbuffer]") TEST_CASE("Ringbuffer iterator", "[peripherals],[ringbuffer]")
{ {
using iterator = Ringbuffer<10>::iterator; using iterator = Ringbuffer<10>::iterator;
const auto begin = iterator::pointer(10); const auto begin = iterator::pointer(10);
@ -43,7 +43,7 @@ TEST_CASE("Ringbuffer iterator", "[utility],[ringbuffer]")
} }
} }
TEST_CASE("Ringbuffer iterator at the end", "[utility],[ringbuffer]") TEST_CASE("Ringbuffer iterator at the end", "[peripherals],[ringbuffer]")
{ {
using iterator = Ringbuffer<10>::iterator; using iterator = Ringbuffer<10>::iterator;
const auto begin = iterator::pointer(10); const auto begin = iterator::pointer(10);
@ -71,7 +71,7 @@ TEST_CASE("Ringbuffer iterator at the end", "[utility],[ringbuffer]")
} }
} }
TEST_CASE("Ringbuffer iterator at the beginning", "[utility],[ringbuffer]") TEST_CASE("Ringbuffer iterator at the beginning", "[peripherals],[ringbuffer]")
{ {
using iterator = Ringbuffer<10>::iterator; using iterator = Ringbuffer<10>::iterator;
const auto begin = iterator::pointer(10); const auto begin = iterator::pointer(10);
@ -87,17 +87,16 @@ TEST_CASE("Ringbuffer iterator at the beginning", "[utility],[ringbuffer]")
} }
} }
TEST_CASE("Ringbuffer constructed buffer is empty.", "[utility],[ringbuffer]") TEST_CASE("Constructed buffer is empty.", "[peripherals],[ringbuffer]")
{ {
Ringbuffer<10> buffer; Ringbuffer<10> buffer;
REQUIRE(buffer.begin() == buffer.end()); REQUIRE(buffer.begin() == buffer.end());
REQUIRE(buffer.size() == 0); REQUIRE(buffer.size() == 0);
REQUIRE(buffer.empty()); REQUIRE(buffer.empty());
REQUIRE(&buffer.front() == &buffer.back());
} }
TEST_CASE("Ringbuffer reports size properly.", "[utility],[ringbuffer]") TEST_CASE("Buffer reports size properly.", "[peripherals],[ringbuffer]")
{ {
Ringbuffer<3> buffer; Ringbuffer<3> buffer;
@ -141,7 +140,7 @@ TEST_CASE("Ringbuffer reports size properly.", "[utility],[ringbuffer]")
} }
} }
TEST_CASE("Ringbuffer adding single element.", "[utility],[ringbuffer]") TEST_CASE("Adding single element.", "[peripherals],[ringbuffer]")
{ {
Ringbuffer<10> buffer; Ringbuffer<10> buffer;
const auto old_end = buffer.end(); const auto old_end = buffer.end();
@ -155,9 +154,15 @@ TEST_CASE("Ringbuffer adding single element.", "[utility],[ringbuffer]")
REQUIRE(!buffer.empty()); REQUIRE(!buffer.empty());
} }
SECTION("Updates end() appropriately.") { REQUIRE(old_end != buffer.end()); } SECTION("Updates end() appropriately.")
{
REQUIRE(old_end != buffer.end());
}
SECTION("begin() remains the same.") { REQUIRE(old_begin == buffer.begin()); } SECTION("begin() remains the same.")
{
REQUIRE(old_begin == buffer.begin());
}
SECTION("Makes begin() refer to the inserted member.") SECTION("Makes begin() refer to the inserted member.")
{ {
@ -186,7 +191,7 @@ TEST_CASE("Ringbuffer adding single element.", "[utility],[ringbuffer]")
} }
} }
TEST_CASE("Ringbuffer adding multiple elements.", "[utility],[ringbuffer]") TEST_CASE("Adding multiple elements.", "[peripherals],[ringbuffer]")
{ {
Ringbuffer<10> buffer; Ringbuffer<10> buffer;
const auto old_begin = buffer.begin(); const auto old_begin = buffer.begin();
@ -218,8 +223,7 @@ TEST_CASE("Ringbuffer adding multiple elements.", "[utility],[ringbuffer]")
} }
} }
TEST_CASE("Ringbuffer removing elements from the ringbuffer.", TEST_CASE("Removing elements from the ringbuffer.", "[peripherals],[ringbuffer]")
"[utility],[ringbuffer]")
{ {
Ringbuffer<10> buffer; Ringbuffer<10> buffer;
const auto old_begin = buffer.begin(); const auto old_begin = buffer.begin();
@ -240,25 +244,34 @@ TEST_CASE("Ringbuffer removing elements from the ringbuffer.",
REQUIRE(buffer.begin() - old_begin == 1); REQUIRE(buffer.begin() - old_begin == 1);
} }
SECTION("Updates size() appropriately.") { REQUIRE(buffer.size() == 2); } SECTION("Updates size() appropriately.")
{
REQUIRE(buffer.size() == 2);
}
SECTION("Erasing remaining elements") SECTION("Erasing remaining elements")
{ {
buffer.pop_front(); buffer.pop_front();
buffer.pop_front(); buffer.pop_front();
SECTION("Updates empty() appropriately.") { REQUIRE(buffer.empty()); } SECTION("Updates empty() appropriately.")
{
REQUIRE(buffer.empty());
}
SECTION("Updates begin() and end() appropriately.") SECTION("Updates begin() and end() appropriately.")
{ {
REQUIRE(buffer.begin() == buffer.end()); REQUIRE(buffer.begin() == buffer.end());
} }
SECTION("Updates size() appropriately.") { REQUIRE(buffer.size() == 0); } SECTION("Updates size() appropriately.")
{
REQUIRE(buffer.size() == 0);
}
} }
} }
TEST_CASE("Ringbuffer clearing a ringbuffer works.", "[utility],[ringbuffer]") TEST_CASE("Clearing a ringbuffer works.", "[peripherals],[ringbuffer]")
{ {
Ringbuffer<10> buffer; Ringbuffer<10> buffer;
@ -277,12 +290,10 @@ TEST_CASE("Ringbuffer clearing a ringbuffer works.", "[utility],[ringbuffer]")
SECTION("Sets begin() and end() pointers appropriately.") SECTION("Sets begin() and end() pointers appropriately.")
{ {
REQUIRE(buffer.begin() == buffer.end()); REQUIRE(buffer.begin() == buffer.end());
REQUIRE(&buffer.front() == &buffer.back());
} }
} }
TEST_CASE("Ringbuffer manually incrementing tail works.", TEST_CASE("Manually incrementing tail works.", "[peripherals],[ringbuffer]")
"[utility],[ringbuffer]")
{ {
Ringbuffer<10> buffer; Ringbuffer<10> buffer;
@ -301,57 +312,7 @@ TEST_CASE("Ringbuffer manually incrementing tail works.",
} }
} }
TEST_CASE("Ringbuffer manually incrementing tail from empty state works.", TEST_CASE("Manually incrementing tail when full deletes data.", "[peripherals],[ringbuffer]")
"[utility],[ringbuffer]")
{
Ringbuffer<10> buffer;
const auto old_end = buffer.end();
const auto old_begin = buffer.begin();
auto* old_tail_item_ptr = &(*old_end);
buffer.increment_tail();
SECTION("Head remains in place.")
{
const auto new_end = buffer.end();
const auto new_begin = buffer.begin();
REQUIRE(old_begin == new_begin);
REQUIRE(new_end != new_begin);
REQUIRE(new_end - new_begin == 1);
}
SECTION("Tail has been incremented.")
{
const auto new_end = buffer.end();
REQUIRE(new_end != old_end);
REQUIRE(new_end - old_end == 1);
REQUIRE(buffer.size() == 1);
}
SECTION("Item pointer for end is increased appropriately.")
{
auto* new_tail_item_ptr = &(*buffer.end());
REQUIRE(new_tail_item_ptr != old_tail_item_ptr);
REQUIRE(new_tail_item_ptr - old_tail_item_ptr == 1);
}
SECTION("Second incrementation works as expected.")
{
buffer.increment_tail();
const auto new_end = buffer.end();
const auto new_begin = buffer.begin();
auto* new_tail_item_ptr = &(*buffer.end());
REQUIRE(new_begin == old_begin);
REQUIRE(new_end - old_end == 2);
REQUIRE(new_tail_item_ptr - old_tail_item_ptr == 2);
REQUIRE(buffer.size() == 2);
}
}
TEST_CASE("Ringbuffer manually incrementing tail when full deletes data.",
"[utility],[ringbuffer]")
{ {
Ringbuffer<2> buffer; Ringbuffer<2> buffer;

View File

@ -9,8 +9,8 @@
#define UTILITY_INC_UTILITY_ASYNCLOGGER_HPP_ #define UTILITY_INC_UTILITY_ASYNCLOGGER_HPP_
#include "utility_atomicscopeguard.hpp" #include "utility_atomicscopeguard.hpp"
#include "utility_ilogger.hpp"
#include "utility_ringbuffer.hpp" #include "utility_ringbuffer.hpp"
#include "utility_ilogger.hpp"
#include <array> #include <array>
#include <cstdarg> #include <cstdarg>
@ -19,8 +19,7 @@
namespace Utility namespace Utility
{ {
template<typename T, typename H, std::size_t BufferCount, template<typename T, typename H, std::size_t BufferCount, std::size_t BufferSize>
std::size_t BufferSize>
class AsyncLogger : public ILogger class AsyncLogger : public ILogger
{ {
public: public:
@ -28,7 +27,9 @@ public:
using hal = H; using hal = H;
AsyncLogger() = delete; AsyncLogger() = delete;
explicit AsyncLogger(const serial_interface& serial) : _serial(serial) {} explicit AsyncLogger(const serial_interface& serial)
: _serial(serial)
{ }
AsyncLogger(const AsyncLogger&) = delete; AsyncLogger(const AsyncLogger&) = delete;
AsyncLogger(AsyncLogger&&) = delete; AsyncLogger(AsyncLogger&&) = delete;
@ -47,9 +48,10 @@ public:
std::va_list args; std::va_list args;
va_start(args, format); va_start(args, format);
_Data& tail = (*_buffer_queue.end()); auto tail = _buffer_queue.end();
tail.length = std::array<char, 255>& buffer = tail->buffer;
vsnprintf(tail.buffer.data(), tail.buffer.size(), format, args);
tail->length = vsnprintf(buffer.data(), buffer.size(), format, args);
{ {
AtomicScopeGuard<hal> s; AtomicScopeGuard<hal> s;
@ -58,8 +60,6 @@ public:
if (!_in_flight) if (!_in_flight)
_sendNextLog(); _sendNextLog();
} }
va_end(args);
} }
void txCompleteCallback() void txCompleteCallback()
@ -86,12 +86,12 @@ private:
_in_flight = true; _in_flight = true;
_Data& head = _buffer_queue.front(); _Data& head = _buffer_queue.front();
_serial.Transmit(reinterpret_cast<uint8_t*>(head.buffer.data()), _serial.Transmit(reinterpret_cast<uint8_t*>(head.buffer.data()), head.length);
head.length);
_buffer_queue.pop_front(); _buffer_queue.pop_front();
} }
}; };
}// namespace Utility }
#endif /* UTILITY_INC_UTILITY_ASYNCLOGGER_HPP_ */ #endif /* UTILITY_INC_UTILITY_ASYNCLOGGER_HPP_ */

View File

@ -36,6 +36,7 @@ struct AtomicScopeGuard
hal::enableInterrupts(); hal::enableInterrupts();
} }
private: private:
static std::int32_t _reentrancy_counter; static std::int32_t _reentrancy_counter;
}; };
@ -43,6 +44,6 @@ private:
template<typename H> template<typename H>
std::int32_t AtomicScopeGuard<H>::_reentrancy_counter = 0; std::int32_t AtomicScopeGuard<H>::_reentrancy_counter = 0;
}// namespace Utility }
#endif /* UTILITY_INC_UTILITY_ATOMICSCOPEGUARD_HPP_ */ #endif /* UTILITY_INC_UTILITY_ATOMICSCOPEGUARD_HPP_ */

View File

@ -26,8 +26,14 @@ public:
LOG_FATAL LOG_FATAL
}; };
constexpr static const char* level_strs[] = {"DEBUG", "INFO", "NOTICE", constexpr static const char* level_strs[] = {
"WARNING", "ERROR", "FATAL"}; "DEBUG",
"INFO",
"NOTICE",
"WARNING",
"ERROR",
"FATAL"
};
ILogger() = default; ILogger() = default;
ILogger(const ILogger&) = delete; ILogger(const ILogger&) = delete;
@ -38,6 +44,6 @@ public:
virtual void log(const char* format, ...) = 0; virtual void log(const char* format, ...) = 0;
}; };
}// namespace Utility }
#endif// SKULLC_UTILITY_ILOGGER_HPP_ #endif //SKULLC_UTILITY_ILOGGER_HPP_

View File

@ -7,22 +7,13 @@
#include "utility_ilogger.hpp" #include "utility_ilogger.hpp"
#define SKULLC_LOG(sev, msg, ...) \ #define SKULLC_LOG(sev, msg, ...) Utility::skullc_logger->log("%s: " msg "\n\r", Utility::ILogger::level_strs[std::uint8_t(sev)], ## __VA_ARGS__)
Utility::skullc_logger->log("%s: " msg "\n\r", \ #define SKULLC_LOG_DEBUG(msg, ...) SKULLC_LOG(Utility::ILogger::LogLevel::LOG_DEBUG, msg, ## __VA_ARGS__)
Utility::ILogger::level_strs[std::uint8_t(sev)], \ #define SKULLC_LOG_INFO(msg, ...) SKULLC_LOG(Utility::ILogger::LogLevel::LOG_INFO, msg, ## __VA_ARGS__)
##__VA_ARGS__) #define SKULLC_LOG_NOTICE(msg, ...) SKULLC_LOG(Utility::ILogger::LogLevel::LOG_NOTICE, msg, ## __VA_ARGS__)
#define SKULLC_LOG_DEBUG(msg, ...) \ #define SKULLC_LOG_WARNING(msg, ...) SKULLC_LOG(Utility::ILogger::LogLevel::LOG_WARNING, msg, ## __VA_ARGS__)
SKULLC_LOG(Utility::ILogger::LogLevel::LOG_DEBUG, msg, ##__VA_ARGS__) #define SKULLC_LOG_ERROR(msg, ...) SKULLC_LOG(Utility::ILogger::LogLevel::LOG_ERROR, msg, ## __VA_ARGS__)
#define SKULLC_LOG_INFO(msg, ...) \ #define SKULLC_LOG_FATAL(msg, ...) SKULLC_LOG(Utility::ILogger::LogLevel::LOG_FATAL, msg, ## __VA_ARGS__)
SKULLC_LOG(Utility::ILogger::LogLevel::LOG_INFO, msg, ##__VA_ARGS__)
#define SKULLC_LOG_NOTICE(msg, ...) \
SKULLC_LOG(Utility::ILogger::LogLevel::LOG_NOTICE, msg, ##__VA_ARGS__)
#define SKULLC_LOG_WARNING(msg, ...) \
SKULLC_LOG(Utility::ILogger::LogLevel::LOG_WARNING, msg, ##__VA_ARGS__)
#define SKULLC_LOG_ERROR(msg, ...) \
SKULLC_LOG(Utility::ILogger::LogLevel::LOG_ERROR, msg, ##__VA_ARGS__)
#define SKULLC_LOG_FATAL(msg, ...) \
SKULLC_LOG(Utility::ILogger::LogLevel::LOG_FATAL, msg, ##__VA_ARGS__)
namespace Utility namespace Utility
{ {
@ -32,6 +23,6 @@ extern ILogger* skullc_logger;
void setLogger(ILogger* log); void setLogger(ILogger* log);
void setLogger(ILogger& log); void setLogger(ILogger& log);
}// namespace Utility }
#endif// UTILITY_LOGGING_HPP_ #endif //UTILITY_LOGGING_HPP_

View File

@ -9,8 +9,8 @@
#define UTILITY_RINGBUFFER_HPP_ #define UTILITY_RINGBUFFER_HPP_
#include <array> #include <array>
#include <cstddef>
#include <iterator> #include <iterator>
#include <cstddef>
namespace Utility namespace Utility
{ {
@ -19,176 +19,197 @@ template<typename T, size_t N>
class Ringbuffer class Ringbuffer
{ {
public: public:
using value_type = T; using value_type = T;
using size_type = std::size_t; using size_type = std::size_t;
using difference_type = std::ptrdiff_t; using difference_type = std::ptrdiff_t;
using reference = value_type&; using reference = value_type&;
using const_reference = const value_type&; using const_reference = const value_type&;
using pointer = value_type*; using pointer = value_type*;
using const_pointer = const value_type*; using const_pointer = const value_type*;
struct iterator struct iterator
{ {
using iterator_category = std::forward_iterator_tag; using iterator_category = std::forward_iterator_tag;
using difference_type = std::ptrdiff_t; using difference_type = std::ptrdiff_t;
using value_type = T; using value_type = T;
using pointer = value_type*; using pointer = value_type*;
using reference = value_type&; using reference = value_type&;
iterator(const pointer ptr, const pointer begin, const pointer end) iterator(const pointer ptr, const pointer begin, const pointer end)
: _ptr(ptr), _arr_begin(begin), _arr_end(end) {} : _ptr(ptr)
iterator(const iterator&) = default; , _arr_begin(begin)
iterator(iterator&&) noexcept = default; , _arr_end(end)
{ }
iterator(const iterator&) = default;
iterator(iterator&&) noexcept = default;
iterator& operator=(const iterator&) = default; iterator& operator=(const iterator&) = default;
reference operator*() const { return *_ptr; } reference operator*() const
{
return *_ptr;
}
pointer operator->() { return _ptr; } pointer operator->()
{
return _ptr;
}
iterator& operator++() iterator& operator++()
{ {
_ptr++; _ptr++;
if (_ptr == _arr_end) if (_ptr == _arr_end)
_ptr = _arr_begin; _ptr = _arr_begin;
return *this; return *this;
} }
iterator operator++(int) iterator operator++(int)
{ {
iterator tmp = *this; iterator tmp = *this;
++(*this); ++(*this);
return tmp; return tmp;
} }
iterator operator+(const difference_type n) const iterator operator+(const difference_type n) const
{ {
const pointer naive = _ptr + n; const pointer naive = _ptr + n;
if (naive < _arr_end) if (naive < _arr_end)
{ {
return iterator(naive, _arr_begin, _arr_end); return iterator(naive, _arr_begin, _arr_end);
} else }
else
{ {
const pointer remainder = pointer(naive - _arr_end); const pointer remainder = pointer(naive - _arr_end);
return iterator(_arr_begin + difference_type(remainder), _arr_begin, return iterator(_arr_begin + difference_type(remainder), _arr_begin, _arr_end);
_arr_end);
} }
} }
iterator operator-(const difference_type n) const iterator operator-(const difference_type n) const
{ {
const pointer naive = _ptr - n; const pointer naive = _ptr - n;
if (naive >= _arr_begin) if (naive >= _arr_begin)
{ {
return iterator(naive, _arr_begin, _arr_end); return iterator(naive, _arr_begin, _arr_end);
} else }
else
{ {
const pointer remainder = pointer(_arr_begin - naive); const pointer remainder = pointer(_arr_begin - naive);
return iterator(_arr_end - difference_type(remainder), _arr_begin, return iterator(_arr_end - difference_type(remainder), _arr_begin, _arr_end);
_arr_end);
} }
} }
friend bool operator==(const iterator& a, const iterator& b) friend bool operator==(const iterator& a, const iterator& b)
{ {
return a._ptr == b._ptr; return a._ptr == b._ptr;
} }
friend bool operator!=(const iterator& a, const iterator& b) friend bool operator!=(const iterator& a, const iterator& b)
{ {
return a._ptr != b._ptr; return a._ptr != b._ptr;
} }
friend difference_type operator-(const iterator& a, const iterator& b) friend difference_type operator-(const iterator& a, const iterator& b)
{ {
return a._ptr - b._ptr; return a._ptr - b._ptr;
} }
friend difference_type operator+(const iterator& a, const iterator& b) friend difference_type operator+(const iterator& a, const iterator& b)
{ {
return a._ptr + b._ptr; return a._ptr + b._ptr;
} }
private: private:
pointer _ptr; pointer _ptr;
pointer _arr_begin; pointer _arr_begin;
pointer _arr_end; pointer _arr_end;
}; };
Ringbuffer() : _head(&_data[0], &_data[0], &_data[N]), _tail(_head) {} Ringbuffer()
: _head(&_data[0], &_data[0], &_data[N])
, _tail(_head)
{ }
Ringbuffer(const Ringbuffer&) = delete; Ringbuffer(const Ringbuffer&) = delete;
Ringbuffer(Ringbuffer&&) noexcept = default; Ringbuffer(Ringbuffer&&) noexcept = default;
iterator begin() { return _head; } iterator begin()
{
return _head;
}
iterator end() { return _tail; } iterator end()
{
return _tail;
}
void clear() { _head = _tail; } void clear()
void push_back(const T& value)
{ {
if (size() == N) _head = _tail;
return;
*_tail = value;
++_tail;
if (_tail == _head)
_is_full = true;
} }
template<typename... Args> void push_back(const T& value)
void emplace_back(Args&&... args) {
if (size() == N)
return;
*_tail = value;
++_tail;
if (_tail == _head)
_is_full = true;
}
template<typename... Args>
void emplace_back(Args&&... args)
{
if (size() == N)
return;
new (&*_tail)T(std::forward<Args>(args)...);
++_tail;
}
void increment_tail()
{
if (_tail == _head)
++_head;
++_tail;
}
void pop_front()
{ {
if (size() == N) if (empty())
return; return;
new (&*_tail) T(std::forward<Args>(args)...);
++_tail;
}
void increment_tail()
{
if (_is_full)
++_head;
++_tail;
}
void pop_front()
{
if (empty())
return;
++_head; ++_head;
_is_full = false; _is_full = false;
} }
reference front() { return *_head; } reference front()
{
return *_head;
}
const_reference front() const { return *_head; } const_reference front() const
{
return *_head;
}
reference back() reference back()
{ {
if (empty()) return *(_tail - 1);
return *_tail;
else
return *(_tail - 1);
} }
const_reference back() const const_reference back() const
{ {
if (empty()) return *(_tail - 1);
return *_tail;
else
return *(_tail - 1);
} }
size_type size() const size_type size() const
{ {
if (_head == _tail) if (_head == _tail)
{ {
if (_is_full) if (_is_full)
return N; return N;
@ -196,30 +217,37 @@ public:
return 0; return 0;
} }
const typename Ringbuffer<T, N>::iterator::difference_type distance = const typename Ringbuffer<T, N>::iterator::difference_type distance = _tail - _head;
_tail - _head;
if (distance > 0) if (distance > 0)
{ {
return distance; return distance;
} else }
else
{ {
return _head - _tail + 1; return _head - _tail + 1;
} }
} }
constexpr size_type max_size() const { return N; } constexpr size_type max_size() const
{
return N;
}
bool empty() const { return size() == 0; } bool empty() const
{
return size() == 0;
}
private: private:
std::array<T, N> _data; std::array<T, N> _data;
bool _is_full = false; bool _is_full = false;
iterator _head; iterator _head;
iterator _tail; iterator _tail;
}; };
}// namespace Utility }
#endif /* UTILITY_RINGBUFFER_HPP_ */ #endif /* UTILITY_RINGBUFFER_HPP_ */

View File

@ -24,15 +24,16 @@ public:
using serial_interface = T; using serial_interface = T;
SerialLogger() = delete; SerialLogger() = delete;
explicit SerialLogger(const serial_interface& serial) : _serial(serial) {} explicit SerialLogger(const serial_interface& serial)
: _serial(serial)
{ }
void log(const char* format, ...) override void log(const char* format, ...) override
{ {
std::va_list args; std::va_list args;
va_start(args, format); va_start(args, format);
const std::int32_t len = const std::int32_t len = vsnprintf(_buffer.data(), _buffer.size(), format, args);
vsnprintf(_buffer.data(), _buffer.size(), format, args);
if (len > 0) if (len > 0)
_serial.Transmit(reinterpret_cast<std::uint8_t*>(_buffer.data()), len); _serial.Transmit(reinterpret_cast<std::uint8_t*>(_buffer.data()), len);
@ -45,6 +46,7 @@ private:
std::array<char, N> _buffer; std::array<char, N> _buffer;
}; };
}// namespace Utility }
#endif /* UTILITY_INC_UTILITY_SERIALLOGGER_HPP_ */ #endif /* UTILITY_INC_UTILITY_SERIALLOGGER_HPP_ */

View File

@ -12,8 +12,14 @@ namespace Utility
ILogger* skullc_logger = nullptr; ILogger* skullc_logger = nullptr;
void setLogger(ILogger* log) { skullc_logger = log; } void setLogger(ILogger* log)
{
skullc_logger = log;
}
void setLogger(ILogger& log) { skullc_logger = &log; } void setLogger(ILogger& log)
{
skullc_logger = &log;
}
}// namespace Utility }