1
0

fix(MP/daemon): oled and app files

This commit is contained in:
2026-06-06 13:06:21 +02:00
committed by Fastium
parent fa58b76bcd
commit d515871987
9 changed files with 231 additions and 100 deletions

View File

@@ -0,0 +1,138 @@
#include "app.h"
#include "sysfs.h"
#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
static led_t* led;
/* Threads objects */
static pthread_t anim_thread_id;
static pthread_mutex_t anim_lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t anim_condition = PTHREAD_COND_INITIALIZER; // SHARED RESOURCES
/* The counter of pending animations */
static int pending_animations = 0; // SHARED RESOURCES
static int keep_running = 1;
void btn_set_led(led_t* l) {
if (l != NULL) {
led = l;
}
}
void set_period(uint32_t period_ms){
sysfs_set_period(period_ms);
}
uint32_t get_period() {
return sysfs_get_period();
}
void increase_period() {
uint32_t current_period = sysfs_get_period();
set_period(current_period + GAP_PERIOD_MS);
}
void decrease_period() {
uint32_t current_period = sysfs_get_period();
set_period(current_period - GAP_PERIOD_MS);
}
int get_mode() {
return sysfs_get_mode();
}
void set_mode(int mode) {
sysfs_set_mode(mode);
}
void mode_toggle() {
int current_mode = sysfs_get_mode();
set_mode(current_mode ^ 1);
}
float get_temperature() {
return sysfs_get_temperature();
}
/**
* animation_worker() - The single thread that processes the queue
*/
static void* animation_worker(void* arg) {
while (keep_running) {
// ENTER CRITICAL SECTION
pthread_mutex_lock(&anim_lock);
/*
* As long as there are no animations to do, the thread sleeps here.
* It consumes 0% CPU while waiting.
*/
while (pending_animations == 0 && keep_running) {
/*
* Wait signal to make animation.
* The function unlocks the mutex to allow another process to add an animation.
* The function forces the thread to sleep until a signal is received.
*/
pthread_cond_wait(&anim_condition, &anim_lock);
}
if (!keep_running) {
pthread_mutex_unlock(&anim_lock);
break;
}
/* We take one animation from the queue */
pending_animations--;
pthread_mutex_unlock(&anim_lock);
// LEAVE CRITICAL SECTION
/* Perform the visual task */
if (led != NULL) {
led_on(led);
usleep(150000);
led_off(led);
usleep(100000); /* Small delay between consecutive pulses */
}
}
return NULL;
}
/**
* init_animations() - To be called once during daemon startup
*/
void init_animations(void) {
pthread_create(&anim_thread_id, NULL, animation_worker, NULL);
}
/**
* trigger_pulse() - Increments the counter and wakes up the thread
*/
static void trigger_pulse(void) {
// ENTER CRITICAL SECTION
pthread_mutex_lock(&anim_lock);
pending_animations++;
/* Signal the thread that there is work to do */
pthread_cond_signal(&anim_condition);
pthread_mutex_unlock(&anim_lock);
// LEAVE CRITICAL SECTION
}
void btn_increase_period() {
trigger_pulse();
increase_period();
}
void btn_decrease_period() {
trigger_pulse();
decrease_period();
}

View File

@@ -0,0 +1,37 @@
#ifndef APP_H
#define APP_H
#include <stdint.h>
#include "../gpio/led.h"
#define DEFAULT_PERIOD_MS 1000
#define GAP_PERIOD_MS 50
/* --- Period functions --- */
void increase_period();
void decrease_period();
void set_period(uint32_t period_ms);
uint32_t get_period();
/* --- Mode functions --- */
void mode_toggle();
void set_mode(int mode);
int get_mode();
/* --- Temperature functions --- */
float get_temperature();
/* --- Button specific function --- */
void btn_set_led(led_t* l);
void init_animations(void);
void btn_increase_period();
void btn_decrease_period();
#endif /* APP_H */

View File

@@ -5,7 +5,7 @@
float get_temperature() { float sysfs_get_temperature() {
FILE *f = fopen(PATH_TEMPERATURE, "r"); FILE *f = fopen(PATH_TEMPERATURE, "r");
if (f == NULL) { if (f == NULL) {
return 0.0f; /* Return 0.0 if the kernel module is not loaded */ return 0.0f; /* Return 0.0 if the kernel module is not loaded */
@@ -26,7 +26,7 @@ float get_temperature() {
return 0.0f; return 0.0f;
} }
uint32_t get_mode() { uint32_t sysfs_get_mode() {
FILE *f = fopen(PATH_MODE, "r"); FILE *f = fopen(PATH_MODE, "r");
if (f == NULL) return 0; if (f == NULL) return 0;
@@ -37,7 +37,7 @@ uint32_t get_mode() {
return mode; return mode;
} }
void set_mode(uint32_t mode) { void sysfs_set_mode(uint32_t mode) {
FILE *f = fopen(PATH_MODE, "w"); FILE *f = fopen(PATH_MODE, "w");
if (f == NULL) return; if (f == NULL) return;
@@ -46,7 +46,7 @@ void set_mode(uint32_t mode) {
fclose(f); fclose(f);
} }
uint32_t get_period() { uint32_t sysfs_get_period() {
FILE *f = fopen(PATH_PERIOD_ST, "r"); FILE *f = fopen(PATH_PERIOD_ST, "r");
if (f == NULL) return 0; if (f == NULL) return 0;
@@ -57,7 +57,7 @@ uint32_t get_period() {
return period; return period;
} }
void set_period(uint32_t period) { void sysfs_set_period(uint32_t period) {
FILE *f = fopen(PATH_PERIOD_SET, "w"); FILE *f = fopen(PATH_PERIOD_SET, "w");
if (f == NULL) return; if (f == NULL) return;

View File

@@ -10,11 +10,11 @@
#define PATH_PERIOD_ST SYSFS_BASE_PATH "/period_status" #define PATH_PERIOD_ST SYSFS_BASE_PATH "/period_status"
#define PATH_PERIOD_SET SYSFS_BASE_PATH "/period_set" #define PATH_PERIOD_SET SYSFS_BASE_PATH "/period_set"
float get_temperature(); float sysfs_get_temperature();
uint32_t get_mode(); uint32_t sysfs_get_mode();
void set_mode(uint32_t mode); void sysfs_set_mode(uint32_t mode);
uint32_t get_period(); uint32_t sysfs_get_period();
void set_period(uint32_t period); void sysfs_set_period(uint32_t period);
#endif /* SYSFS_H */ #endif /* SYSFS_H */

View File

@@ -1 +0,0 @@
#include "app.h"

View File

@@ -1,25 +0,0 @@
#ifndef APP_H
#define APP_H
#include "../gpio/led.h"
#define DEFAULT_PERIOD_MS 1000
void set_led(
void increase_period();
void decrease_period();
void set_period(int period_ms);
void mode_toggle();
void set_mode(int mode);
float get_temperature();
/* Button specific function */
void btn_increase_period();
void btn_decrease_period();
#endif /* APP_H */

View File

@@ -14,38 +14,12 @@
#include "gpio/led.h" #include "gpio/led.h"
#include "gpio/button.h" #include "gpio/button.h"
#include "ipc/ipc_server.h" #include "ipc/ipc_server.h"
#include "oled/oled.h"
#include "application/app.h"
#define DEFAULT_TIME_MS 1000 #define DEFAULT_TIME_MS 1000
#define DUTY_CYCLE_PERCENT 2 #define DUTY_CYCLE_PERCENT 2
void set_mode(int mode) {
printf("set_mode: %d\n", mode);
}
void set_period(int period) {
printf("set_period: %d\n", period);
}
uint32_t get_period() {
printf("get_period\n");
return 200;
}
void period_inc() {
printf("period_inc\n");
}
void period_dec() {
printf("period_dec\n");
}
void period_reset() {
printf("period_reset\n");
}
void get_temp() {
printf("get_temp\n");
}
int main(void) { int main(void) {
@@ -56,23 +30,34 @@ int main(void) {
led_t* led_power = led_init(LED_POWER); led_t* led_power = led_init(LED_POWER);
btn_set_callback(btn_inc, period_inc); btn_set_callback(btn_inc, btn_decrease_period);
btn_set_callback(btn_dec, period_dec); btn_set_callback(btn_dec, btn_decrease_period);
btn_set_callback(btn_mode, period_reset); btn_set_callback(btn_mode, set_mode);
struct ipc_callbacks_t ipc_cbs = { struct ipc_callbacks_t ipc_cbs = {
.on_dec_frequency = period_dec, .on_dec_frequency = decrease_period,
.on_inc_frequency = period_inc, .on_inc_frequency = increase_period,
.on_set_frequency = set_period, // .on_set_frequency = set_period,
.on_set_mode = set_mode, .on_set_mode = set_mode,
}; };
struct oled_callbacks_t oled_cbs = {
.get_mode = get_mode,
.get_period = get_period,
.get_temperature = get_temperature,
};
int ret = start_ipc_server(&ipc_cbs); int ret = start_ipc_server(&ipc_cbs);
if (ret < 0) { if (ret < 0) {
fprintf(stderr, "Failed to start IPC server: %d\n", ret); fprintf(stderr, "Failed to start IPC server: %d\n", ret);
return 1; return 1;
} }
init_oled(&oled_cbs);
btn_set_led(led_power);
init_animations();
while (1) { while (1) {
sleep(1); sleep(1);
} }

View File

@@ -26,26 +26,26 @@ static void display(int mode, float temp, uint32_t period_ms) {
/* Static header rows */ /* Static header rows */
ssd1306_set_position(0, 0); ssd1306_set_position(0, 0);
ssd1306_puts("CSEL1a - SP.07"); ssd1306_puts("CSEL1a - SP.07");
ssd1306_set_position(0, 1); // ssd1306_set_position(0, 1);
ssd1306_puts(" WATCHDOG CPU "); // ssd1306_puts(" WATCHDOG CPU ");
ssd1306_set_position(0, 2); // ssd1306_set_position(0, 2);
ssd1306_puts("--------------"); // ssd1306_puts("--------------");
/* Mode display: switches between AUTO and MANU strings */ // /* Mode display: switches between AUTO and MANU strings */
ssd1306_set_position(0, 3); // ssd1306_set_position(0, 3);
snprintf(buffer, sizeof(buffer), "Mode: %s", mode ? "AUTO" : "MANU"); // snprintf(buffer, sizeof(buffer), "Mode: %s", mode ? "AUTO" : "MANU");
ssd1306_puts(buffer); // ssd1306_puts(buffer);
/* Temperature display: formatted with one decimal precision */ // /* Temperature display: formatted with one decimal precision */
ssd1306_set_position(0, 4); // ssd1306_set_position(0, 4);
snprintf(buffer, sizeof(buffer), "Temp: %.1f'C", temp); // snprintf(buffer, sizeof(buffer), "Temp: %.1f'C", temp);
ssd1306_puts(buffer); // ssd1306_puts(buffer);
/* Period/Frequency display: shows the value in milliseconds */ // /* Period/Frequency display: shows the value in milliseconds */
ssd1306_set_position(0, 5); // ssd1306_set_position(0, 5);
float freq = 1.0f / (period_ms / 1000.0f); // float freq = 1.0f / (period_ms / 1000.0f);
snprintf(buffer, sizeof(buffer), "Freq: %.1fHz", freq); // snprintf(buffer, sizeof(buffer), "Freq: %.1fHz", freq);
ssd1306_puts(buffer); // ssd1306_puts(buffer);
} }
/** /**
@@ -65,7 +65,7 @@ static void *update_oled_thread(void* arg) {
); );
} }
/* Sleep to control refresh rate and save CPU cycles */ /* Sleep to control refresh rate and save CPU cycles */
usleep(250000); usleep(1000000);
} }
return NULL; return NULL;
} }

View File

@@ -14,7 +14,7 @@
#define ARRAY_OF(x) (sizeof(x)/sizeof(x[0])) #define ARRAY_OF(x) (sizeof(x)/sizeof(x[0]))
#define I2C_BUS "/dev/i2c-0" #define I2C_BUS "/dev/i2c-1"
#define OLED_ADDR 0x3c #define OLED_ADDR 0x3c
#define OLED_COMMAND_MODE 0x00 #define OLED_COMMAND_MODE 0x00
#define OLED_DATA_MODE 0x40 #define OLED_DATA_MODE 0x40
@@ -231,6 +231,3 @@ int ssd1306_init()
return 0; return 0;
} }