picoco/buzzer/jobs.c
2025-03-05 10:43:11 +01:00

208 lines
5.0 KiB
C

//#define PICO
#ifdef PICO
#include <pico/printf.h>
#include <pico/stdlib.h>
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#else
#include <stdio.h>
#include <stdbool.h>
#include <pthread.h>
#endif
#include "gpio.h"
#include "jobs.h"
#include "log.h"
#include "utils.h"
#define BUTTON_BUFFETING_SLEEP_DURATION_MS 20
int init_app_state(AppState *s) {
s->action = STOP;
#ifdef PICO
s->lock = xSemaphoreCreateMutex();
#else
if (pthread_mutex_init(&s->lock, NULL) != 0) {
error("mutex init failed");
return -1;
}
#endif
s->freq_multiplicator = 0;
return 0;
}
int lock(AppState *s) {
#ifdef PICO
if (xSemaphoreTake(s->lock, (TickType_t)10) != pdTRUE) {
error("unable to lock the FreeRTOS task");
return -1;
}
return 0;
#else
return pthread_mutex_lock(&s->lock);
#endif
}
int release(AppState *s) {
#ifdef PICO
xSemaphoreGive(s->lock);
return 0;
#else
return pthread_mutex_unlock(&s->lock);
#endif
}
int cancel_task(AppState *s) {
debug("stopping task...");
#ifdef PICO
if (s->task != NULL) {
vTaskDelete(*s->task);
free(s->task);
gpio_set_state(GPIOS[2], false);
gpio_set_level(GPIOS[4],0);
return 0;
}
#else
if (s->task != NULL) {
if (pthread_cancel(*s->task) != 0) {
error("unable to cancel the thread task");
return -1;
}
if (pthread_join(*s->task, NULL) != 0) {
error("unable to wait for finished task");
return -1;
}
free(s->task);
s->task = NULL;
}
gpio_set_level(GPIOS[4],0);
return 0;
#endif
}
int launch_task(AppState *s, FnJob f) {
debug("starting app task...");
#ifdef PICO
TaskHandle_t* task = malloc(sizeof(TaskHandle_t));
if (task == NULL) {
error("unable allocate memory for the app task");
return -1;
}
BaseType_t res =
xTaskCreateAffinitySet(f, "task", configMINIMAL_STACK_SIZE,
s, configMAX_PRIORITIES - 1U, 1 << 1,task);
if (res != pdPASS) {
error("unable to launch run alarm task task, code error: %d",
res);
return -1;
}
s->task = task;
#else
pthread_t* task = malloc(sizeof(task));
if (task == NULL) {
error("unable to allocate memory for task thread");
return -1;
}
if (pthread_create(task, NULL, f, s) != 0) {
error("thread task creation failed");
return -1;
}
s->task = task;
#endif
return 0;
}
/**
*
*/
void check_acd_value(void* args) {
AppState* s = (AppState*) args;
uint16_t current_freq_multiplicator = 0;
for (;;) {
double freq_mul = gpio_get_adc();
if (freq_mul != current_freq_multiplicator) {
#ifdef PICO
gpio_set_level(GPIOS[4], current_freq_multiplicator * DEFAULT_WRAP_LEVEL);
#endif
if (lock(s) != 0)
fatal(stop_app_fallback, "unable to lock app mutex");
s->freq_multiplicator = freq_mul;
current_freq_multiplicator = freq_mul;
if (release(s) != 0)
fatal(stop_app_fallback, "unable to release app mutex");
debug("freq multiplicator updated: %d\n", current_freq_multiplicator);
}
#ifdef PICO
gpio_set_level(GPIOS[4], current_freq_multiplicator * DEFAULT_WRAP_LEVEL);
#endif
}
}
/**
* Main app loop.
*
* Check the button state and if the button state is pushed (LOW level)
* the app task is launched.
*
*/
void check_btn_state(void* args) {
TaskParam* params = (TaskParam*) args;
AppState *s = params->s;
bool has_proceed = false;
for (;;) {
if (!gpio_get_input(GPIOS[1])) {
#ifdef PICO
vTaskDelay(pdMS_TO_TICKS(BUTTON_BUFFETING_SLEEP_DURATION_MS));
#else
_sleep_ms(BUTTON_BUFFETING_SLEEP_DURATION_MS);
#endif
if(!gpio_get_input(GPIOS[1]) && !has_proceed) {
if (lock(s) != 0)
fatal(stop_app_fallback, "unable to lock app mutex");
if (s->action == START) {
s->action = STOP;
cancel_task(s);
if (release(s) != 0)
fatal(stop_app_fallback, "unable to release app mutex");
gpio_set_state(GPIOS[0], false);
has_proceed = true;
continue;
}
s->action = START;
if (launch_task(s, params->f) != 0)
fatal(stop_app_fallback, "unable to launch app task");
if (release(s) != 0)
fatal(stop_app_fallback, "unable to release app mutex");
gpio_set_state(GPIOS[0], true);
has_proceed = true;
}
continue;
}
has_proceed = false;
}
}
#ifdef PICO
void vApplicationStackOverflowHook(TaskHandle_t pxTask, char *pcTaskName) {
fatal(stop_app_fallback, "a task stack overflow, please fix it");
}
#endif