Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
fd02fb6
Issue #15: Add buzzer driver implementation
hasslesstech Jul 19, 2025
91b6900
Issue #15: Extract definitions from driver.c into their separate file…
hasslesstech Jul 26, 2025
ee933aa
Issue #15: Add buzzer manager task
hasslesstech Aug 1, 2025
f23af02
Issue #15: fix configuration sanity check
hasslesstech Aug 1, 2025
31408ae
Issue #15: improve total timing precision of pulse function
hasslesstech Aug 1, 2025
5e86956
Issue #15: add new task for buzzer manager
hasslesstech Aug 1, 2025
26aa038
Issue #15: [fix] make pulse function non-blocking and abortable
hasslesstech Aug 16, 2025
ee5f7aa
Issue #15: simplify count_bits_16bit function
hasslesstech Aug 16, 2025
133cf06
Issue #15: Extract memory from driver to manager
hasslesstech Sep 14, 2025
244f5c6
Issue #15: switch to CMSISv2 functions in manager to improve OS indep…
hasslesstech Sep 14, 2025
d848155
Issue #15: Change all types to platform-independant alternatives
hasslesstech Sep 14, 2025
5084403
Issue #15: increase maximum stack size to prevent accidental task cra…
hasslesstech Sep 28, 2025
981b69f
Issue #15: refactor code into a state machine
hasslesstech Sep 28, 2025
eebc972
Issue #32: Add mock timers.c implementation
hasslesstech Aug 22, 2025
205fddc
Issue #32: Add basic working unit-tests
hasslesstech Aug 22, 2025
bacbd0f
Issue #32: Add more unit-tests, improve timer emulation
hasslesstech Aug 23, 2025
2461120
Issue #32: Add support for CMSISv2 timer calls, adjust unit-tests to …
hasslesstech Sep 29, 2025
93143cc
Issue #32: Migrate to using gTest testing framework
hasslesstech Oct 8, 2025
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
9 changes: 8 additions & 1 deletion Core/Src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ static void MX_TIM3_Init(void);
void StartDefaultTask(void *argument);

/* USER CODE BEGIN PFP */

void buzzer_manager_task(void *);
/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
Expand Down Expand Up @@ -158,6 +158,13 @@ int main(void)

ul_ulog_init();

static const osThreadAttr_t buzzer_task_attrs = {
.name = "buzzer",
.stack_size = 64 * 4,
.priority = (osPriority_t) osPriorityHigh,
};
(void) osThreadNew(buzzer_manager_task, NULL, &buzzer_task_attrs);


/* USER CODE END RTOS_THREADS */

Expand Down
284 changes: 284 additions & 0 deletions KPI_Rover/Buzzer/driver.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,284 @@
#include <stddef.h>

#include "stm32f4xx_hal.h"

#include "generic.h"
#include "driver.h"

#define BUZZER_BLOCKING_TIME_LIMIT 1000

#define CHECK_ERROR(condition, err_value) do { \
if (condition) { \
errors = (err_value); \
goto fail; \
} \
} while (0)


static uint8_t count_bits_16bit(uint16_t value)
{
uint8_t result = 0;

for ( ; value; value >>= 1)
result += value & 1;

return result;
}

static uint32_t Buzzer_SetON(struct BuzzerObject * const self)
{
uint32_t errors = 0;

CHECK_ERROR(!self->c.initialized, BUZZER_NOT_INITIALIZED_ERROR);

HAL_GPIO_WritePin(self->c.GPIO_port, self->c.GPIO_pin, GPIO_PIN_SET);

fail:
return errors;
}

static uint32_t Buzzer_SetOFF(struct BuzzerObject * const self)
{
uint32_t errors = 0;

CHECK_ERROR(!self->c.initialized, BUZZER_NOT_INITIALIZED_ERROR);

HAL_GPIO_WritePin(self->c.GPIO_port, self->c.GPIO_pin, GPIO_PIN_RESET);

fail:
return errors;
}


static void Buzzer_OFF_Enter(struct BuzzerObject * const self, const struct BuzzerEvent * const ev)
{
Buzzer_SetOFF(self);
}

static void Buzzer_OFF_Handle(struct BuzzerObject * const self)
{

}

static void Buzzer_OFF_Leave(struct BuzzerObject * const self)
{
Buzzer_SetOFF(self);
}


static void Buzzer_ON_Enter(struct BuzzerObject * const self, const struct BuzzerEvent * const ev)
{
Buzzer_SetON(self);
}

static void Buzzer_ON_Handle(struct BuzzerObject * const self)
{

}

static void Buzzer_ON_Leave(struct BuzzerObject * const self)
{
Buzzer_SetON(self);
}


static void Buzzer_PULSE_Enter(struct BuzzerObject * const self, const struct BuzzerEvent * const ev)
{
self->ps.config.pulse_on_for = ev->pulse_on_for;
self->ps.config.pulse_off_for = ev->pulse_off_for;
self->ps.config.pulse_total_for = ev->pulse_total_for;

self->ps.current_state = BUZZER_TO_ON;
}

static void Buzzer_PULSE_Handle(struct BuzzerObject * const self)
{
uint32_t tss;

switch (self->ps.current_state) {
case BUZZER_TO_ON:
Buzzer_SetON(self);
self->ps.current_state_since = HAL_GetTick();

tss = ticks_elapsed_since(self->s.current_state_since);

if ((tss + self->ps.config.pulse_on_for) >= self->ps.config.pulse_total_for) {
self->ps.current_state = BUZZER_FINAL_DELAY;
self->ps.state_lifetime_override = self->ps.config.pulse_total_for - tss;
} else {
self->ps.current_state = BUZZER_DELAY_BEFORE_OFF;
}

break;
case BUZZER_DELAY_BEFORE_OFF:
if (ticks_elapsed_since(self->ps.current_state_since) >= self->ps.config.pulse_on_for)
self->ps.current_state = BUZZER_TO_OFF;

break;
case BUZZER_TO_OFF:
Buzzer_SetOFF(self);
self->ps.current_state_since = HAL_GetTick();

tss = ticks_elapsed_since(self->s.current_state_since);

if ((tss + self->ps.config.pulse_off_for) >= self->ps.config.pulse_total_for) {
self->ps.current_state = BUZZER_FINAL_DELAY;
self->ps.state_lifetime_override = self->ps.config.pulse_total_for - tss;
} else {
self->ps.current_state = BUZZER_DELAY_BEFORE_ON;
}

break;
case BUZZER_DELAY_BEFORE_ON:
if (ticks_elapsed_since(self->ps.current_state_since) >= self->ps.config.pulse_off_for)
self->ps.current_state = BUZZER_TO_ON;

break;
case BUZZER_FINAL_DELAY:
if (ticks_elapsed_since(self->ps.current_state_since) < self->ps.state_lifetime_override)
break;

self->e.ev = TO_OFF;
break;
}
}

static void Buzzer_PULSE_Leave(struct BuzzerObject * const self)
{
Buzzer_SetOFF(self);
}


static void Buzzer_Reset(struct BuzzerObject * const self)
{
switch (self->s.current_state) {
case BUZZER_OFF:
Buzzer_OFF_Leave(self);
break;
case BUZZER_ON:
Buzzer_ON_Leave(self);
break;
case BUZZER_PULSE:
Buzzer_PULSE_Leave(self);
break;
case IMPOSSIBLE_STATE:
default:
break;
}

self->s.current_state = BUZZER_OFF;
}

static void Buzzer_ProcessEvent(struct BuzzerObject * const self)
{
if (self->e.ev == NO_EVENT || self->e.ev == IMPOSSIBLE_EVENT)
return;

switch (self->s.current_state) {
case BUZZER_ON:
Buzzer_ON_Leave(self);
break;
case BUZZER_OFF:
Buzzer_OFF_Leave(self);
break;
case BUZZER_PULSE:
Buzzer_PULSE_Leave(self);
break;
default:
break;
}

switch (self->e.ev) {
case TO_ON:
self->s.current_state = BUZZER_ON;
Buzzer_ON_Enter(self, &(self->e));
break;
case TO_OFF:
self->s.current_state = BUZZER_OFF;
Buzzer_OFF_Enter(self, &(self->e));
break;
case TO_PULSE:
self->s.current_state = BUZZER_PULSE;
Buzzer_PULSE_Enter(self, &(self->e));
break;
default:
self->s.current_state = IMPOSSIBLE_STATE;
break;
}

self->s.current_state_since = HAL_GetTick();
self->e.ev = NO_EVENT;
}


uint32_t Buzzer_ConfigurePort(struct BuzzerObject * const self, const GPIO_TypeDef * const gpio_port, const uint16_t gpio_pin)
{
Buzzer_Reset(self);

uint32_t errors = 0;

CHECK_ERROR(count_bits_16bit(gpio_pin) != 1, BUZZER_PIN_ERROR);

self->c.GPIO_port = (GPIO_TypeDef *) gpio_port;
self->c.GPIO_pin = (uint16_t) gpio_pin;

self->c.initialized = 1;

return errors;

fail:
self->c.initialized = 0;
return errors;
}


uint32_t Buzzer_Enable(struct BuzzerObject * const self)
{
self->e.ev = TO_ON;
return 0;
}

uint32_t Buzzer_Disable(struct BuzzerObject * const self)
{
self->e.ev = TO_OFF;
return 0;
}

uint32_t Buzzer_Pulse(struct BuzzerObject * const self, const uint32_t on_time_ms, const uint32_t period_time_ms, const uint32_t total_active_time_ms)
{
uint32_t errors = 0;

const uint32_t off_time_ms = period_time_ms - on_time_ms;

CHECK_ERROR(!on_time_ms, BUZZER_ZERO_ONTIME_ERROR);
CHECK_ERROR(!off_time_ms, BUZZER_ZERO_OFFTIME_ERROR);
CHECK_ERROR(!total_active_time_ms, BUZZER_ZERO_ACTIVE_TIME_ERROR);

self->e.pulse_on_for = on_time_ms;
self->e.pulse_off_for = off_time_ms;
self->e.pulse_total_for = total_active_time_ms;

self->e.ev = TO_PULSE;

fail:
return errors;
}

void Buzzer_TimerTask(struct BuzzerObject * const self)
{
(void) Buzzer_ProcessEvent(self);

switch (self->s.current_state) {
case BUZZER_OFF:
Buzzer_OFF_Handle(self);
break;
case BUZZER_ON:
Buzzer_ON_Handle(self);
break;
case BUZZER_PULSE:
Buzzer_PULSE_Handle(self);
break;
default:
break;
}
}
86 changes: 86 additions & 0 deletions KPI_Rover/Buzzer/driver.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
#ifndef __BUZZER_DRIVER
#define __BUZZER_DRIVER

#include "stm32f4xx_hal.h"

#define BUZZER_PIN_ERROR 0x1U
#define BUZZER_NOT_INITIALIZED_ERROR 0x2U
#define BUZZER_HAL_ERROR 0x3U
#define BUZZER_VALUE_ERROR 0x4U
#define BUZZER_ZERO_ONTIME_ERROR 0x5U
#define BUZZER_ZERO_OFFTIME_ERROR 0x6U
#define BUZZER_ZERO_ACTIVE_TIME_ERROR 0x7U
#define BUZZER_TIMER_BUSY 0x8U


enum BuzzerEventType {
NO_EVENT,
IMPOSSIBLE_EVENT,
TO_ON,
TO_OFF,
TO_PULSE
};

struct BuzzerEvent {
enum BuzzerEventType ev;
uint32_t pulse_on_for;
uint32_t pulse_off_for;
uint32_t pulse_total_for;
};


enum BuzzerGlobalStateType {
IMPOSSIBLE_STATE,
BUZZER_OFF,
BUZZER_ON,
BUZZER_PULSE
};

struct BuzzerGlobalState {
enum BuzzerGlobalStateType current_state;
uint32_t current_state_since;
};


enum BuzzerPulseSubStateType {
BUZZER_TO_ON,
BUZZER_DELAY_BEFORE_OFF,
BUZZER_TO_OFF,
BUZZER_DELAY_BEFORE_ON,
BUZZER_FINAL_DELAY
};

struct BuzzerPulseConfig {
uint32_t pulse_on_for;
uint32_t pulse_off_for;
uint32_t pulse_total_for;
};

struct BuzzerPulseSubState {
enum BuzzerPulseSubStateType current_state;
struct BuzzerPulseConfig config;
uint32_t current_state_since;
uint32_t state_lifetime_override;
};


struct BuzzerConfig {
GPIO_TypeDef *GPIO_port;
uint16_t GPIO_pin;
int8_t initialized;
};

struct BuzzerObject {
struct BuzzerConfig c;
struct BuzzerGlobalState s;
struct BuzzerPulseSubState ps;
struct BuzzerEvent e;
};

uint32_t Buzzer_ConfigurePort(struct BuzzerObject * const self, const GPIO_TypeDef * const gpio_port, const uint16_t gpio_pin);
uint32_t Buzzer_Enable(struct BuzzerObject * const self);
uint32_t Buzzer_Disable(struct BuzzerObject * const self);
uint32_t Buzzer_Pulse(struct BuzzerObject * const self, const uint32_t on_time_ms, const uint32_t period_time_ms, const uint32_t total_active_time_ms);
void Buzzer_TimerTask(struct BuzzerObject * const self);

#endif /* __BUZZER_DRIVER */
Loading