picoco/buzzer/jobs.c
2025-03-03 15:36:32 +01:00

171 lines
3.9 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"
#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) {
printf("error: mutex init failed\n");
return -1;
}
#endif
return 0;
}
int lock(AppState *s) {
#ifdef PICO
if (xSemaphoreTake(s->lock, (TickType_t)10) != pdTRUE) {
printf("unable to lock the FreeRTOS task\n");
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);
return 0;
}
#else
if (s->task != NULL) {
if (pthread_cancel(*s->task) != 0) {
perror("error: unable to cancel the thread task\n");
return -1;
}
if (pthread_join(*s->task, NULL) != 0) {
perror("error: unable to wait for finished task\n");
return -1;
}
free(s->task);
s->task = NULL;
}
return 0;
#endif
}
int launch_task(AppState *s, FnJob f) {
debug("starting task thread...");
#ifdef PICO
TaskHandle_t* task = malloc(sizeof(TaskHandle_t));
if (task == NULL) {
blink_failed(GPIOS[0]->pin, 300);
}
BaseType_t res =
xTaskCreate(f, "task", configMINIMAL_STACK_SIZE,
NULL, configMAX_PRIORITIES - 1U, task);
if (res != pdPASS) {
printf("error: unable to launch run alarm task task, code error: %d\n",
res);
return -1;
}
s->task = task;
#else
pthread_t* task = malloc(sizeof(task));
if (task == NULL) {
perror("error: unable to allocate memory for task thread");
return -1;
}
if (pthread_create(task, NULL, f, s) != 0) {
perror("error: thread task creation failed\n");
return -1;
}
s->task = task;
#endif
return 0;
}
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) {
blink_failed(PICO_DEFAULT_LED_PIN, 200);
}
if (s->action == START) {
s->action = STOP;
cancel_task(s);
if (release(s) != 0) {
blink_failed(PICO_DEFAULT_LED_PIN, 200);
}
gpio_set_state(GPIOS[0], false);
has_proceed = true;
continue;
}
s->action = START;
if (launch_task(s, params->f) != 0) {
blink_failed(PICO_DEFAULT_LED_PIN, 200);
}
if (release(s) != 0) {
blink_failed(PICO_DEFAULT_LED_PIN, 200);
}
gpio_set_state(GPIOS[0], true);
has_proceed = true;
}
continue;
}
has_proceed = false;
}
}
#ifdef PICO
void vApplicationStackOverflowHook(TaskHandle_t pxTask, char *pcTaskName) {
blink_failed(PICO_DEFAULT_LED_PIN, 200);
}
#endif