idfhack/main/task_blink.c
2025-07-11 18:45:57 +02:00

200 lines
5.2 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "freertos/idf_additions.h"
#include "freertos/projdefs.h"
#include "freertos/semphr.h"
#include "portmacro.h"
#include <driver/gpio.h>
#include <esp_rom_gpio.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <inttypes.h>
#include <stdio.h>
#include "tasks.h"
QueueHandle_t blink_cmd_q;
void blink_cmd_print(const BlinkCmd_t *cmd) {
printf("BlinkCmd { ");
switch (cmd->variant) {
case BLINK_RATE:
printf("variant: BLINK_RATE, ");
printf("rate: %" PRIu32, cmd->rate);
break;
case BLINK_STATE:
printf("variant: BLINK_STATE, ");
printf("state: %s", cmd->state ? "ON" : "OFF");
break;
default:
printf("variant: UNKNOWN (%d)", cmd->variant);
break;
}
printf(" }\n");
}
void task_blink(void *pvParams) {
esp_rom_gpio_pad_select_gpio(LED_PIN);
gpio_set_direction(LED_PIN, GPIO_MODE_OUTPUT);
u32 level = 1; // For blinking
// Set this to some initial value
BlinkCmd_t command = {
.variant = BLINK_RATE,
.rate = 800,
};
if (pvParams != NULL) {
command = *(BlinkCmd_t *)pvParams;
printf("Got initial configuration for leds: ");
blink_cmd_print(&command);
}
while (1) {
if (pdPASS == xQueueReceive(blink_cmd_q, &command, 0))
blink_cmd_print(&command);
switch (command.variant) {
case BLINK_RATE:
level = !level;
gpio_set_level(LED_PIN, level);
vTaskDelay(command.rate / portTICK_PERIOD_MS);
break;
case BLINK_STATE:
gpio_set_level(LED_PIN, command.state);
vTaskDelay(pdMS_TO_TICKS(20));
break;
default:
break;
}
}
}
void task_blink_cycle(void *pvParams) {
BlinkCmd_t cmd = {
.variant = BLINK_RATE,
.rate = 1000,
};
vTaskDelay(pdMS_TO_TICKS(2000));
if (xQueueSend(blink_cmd_q, &cmd, pdMS_TO_TICKS(200)) != pdPASS) {
printf("Error sending blink command...");
}
vTaskDelay(pdMS_TO_TICKS(2000));
cmd.rate = 50;
if (xQueueSend(blink_cmd_q, &cmd, pdMS_TO_TICKS(200)) != pdPASS) {
printf("Error sending blink command...");
}
vTaskDelay(pdMS_TO_TICKS(2000));
cmd.rate = 25;
if (xQueueSend(blink_cmd_q, &cmd, pdMS_TO_TICKS(200)) != pdPASS) {
printf("Error sending blink command...");
}
vTaskDelay(pdMS_TO_TICKS(2000));
cmd.rate = 500;
if (xQueueSend(blink_cmd_q, &cmd, pdMS_TO_TICKS(200)) != pdPASS) {
printf("Error sending blink command...");
}
vTaskDelay(pdMS_TO_TICKS(2000));
cmd.variant = BLINK_STATE;
cmd.state = 1;
if (xQueueSend(blink_cmd_q, &cmd, pdMS_TO_TICKS(200)) != pdPASS) {
printf("Error sending blink command...");
}
vTaskDelay(pdMS_TO_TICKS(2000));
cmd.variant = BLINK_RATE;
cmd.rate = 200;
if (xQueueSend(blink_cmd_q, &cmd, pdMS_TO_TICKS(200)) != pdPASS) {
printf("Error sending blink command...");
}
vTaskDelay(pdMS_TO_TICKS(2000));
cmd.variant = BLINK_STATE;
cmd.state = 0;
if (xQueueSend(blink_cmd_q, &cmd, pdMS_TO_TICKS(200)) != pdPASS) {
printf("Error sending blink command...");
}
vTaskDelete(NULL);
}
void vPeriodicTask(void *pvParameters) {
TickType_t xLastWakeTime;
const TickType_t xDelay3ms = pdMS_TO_TICKS(2000);
/*
* The xLastWakeTime variable needs to be initialized with the current tick
* count. Note that this is the only time the variable is explicitly
* written to. After this xLastWakeTime is managed automatically by the
* vTaskDelayUntil() API function.
*/
xLastWakeTime = xTaskGetTickCount();
char *taskname = pcTaskGetName(NULL);
/* As per most tasks, this task is implemented in an infinite loop. */
for (;;) {
/* Print out the name of this task. */
printf("%s - %" PRIu32 ": Running...\n", taskname, pdTICKS_TO_MS(xLastWakeTime));
/*
* The task should execute every 3 milliseconds exactly see the
* declaration of xDelay3ms in this function.
*/
vTaskDelayUntil(&xLastWakeTime, xDelay3ms);
}
}
#define BUTTON_GPIO GPIO_NUM_0
SemaphoreHandle_t button_sem;
static void IRAM_ATTR button_isr_handler(void *arg) {
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xSemaphoreGiveFromISR(button_sem, &xHigherPriorityTaskWoken);
if (xHigherPriorityTaskWoken) {
portYIELD_FROM_ISR(); // Request context switch if needed
}
}
void button_task(void *pvParams) {
while (1) {
if (xSemaphoreTake(button_sem, portMAX_DELAY)) {
printf("Button pressed (from ISR)\n");
}
}
}
void task_gpio_demo(void *pvParams) {
button_sem = xSemaphoreCreateBinary();
// Setup GPIO
gpio_config_t io_conf = {
.intr_type = GPIO_INTR_NEGEDGE,
.mode = GPIO_MODE_INPUT,
.pin_bit_mask = (1ULL << BUTTON_GPIO),
.pull_up_en = 1,
};
gpio_config(&io_conf);
// Install ISR handler
gpio_install_isr_service(0);
gpio_isr_handler_add(BUTTON_GPIO, button_isr_handler, NULL);
// Start the task
xTaskCreate(button_task, "button_task", 2048, NULL, 10, NULL);
vTaskDelete(NULL);
}