fix(MP/daemon): oled and app files
This commit is contained in:
138
src/06-mini-project/daemon/application/app.c
Normal file
138
src/06-mini-project/daemon/application/app.c
Normal 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();
|
||||||
|
}
|
||||||
37
src/06-mini-project/daemon/application/app.h
Normal file
37
src/06-mini-project/daemon/application/app.h
Normal 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 */
|
||||||
@@ -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;
|
||||||
|
|
||||||
@@ -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 */
|
||||||
@@ -1 +0,0 @@
|
|||||||
#include "app.h"
|
|
||||||
@@ -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 */
|
|
||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user