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");
|
||||
if (f == NULL) {
|
||||
return 0.0f; /* Return 0.0 if the kernel module is not loaded */
|
||||
@@ -26,7 +26,7 @@ float get_temperature() {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
uint32_t get_mode() {
|
||||
uint32_t sysfs_get_mode() {
|
||||
FILE *f = fopen(PATH_MODE, "r");
|
||||
if (f == NULL) return 0;
|
||||
|
||||
@@ -37,7 +37,7 @@ uint32_t get_mode() {
|
||||
return mode;
|
||||
}
|
||||
|
||||
void set_mode(uint32_t mode) {
|
||||
void sysfs_set_mode(uint32_t mode) {
|
||||
FILE *f = fopen(PATH_MODE, "w");
|
||||
if (f == NULL) return;
|
||||
|
||||
@@ -46,7 +46,7 @@ void set_mode(uint32_t mode) {
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
uint32_t get_period() {
|
||||
uint32_t sysfs_get_period() {
|
||||
FILE *f = fopen(PATH_PERIOD_ST, "r");
|
||||
if (f == NULL) return 0;
|
||||
|
||||
@@ -57,7 +57,7 @@ uint32_t get_period() {
|
||||
return period;
|
||||
}
|
||||
|
||||
void set_period(uint32_t period) {
|
||||
void sysfs_set_period(uint32_t period) {
|
||||
FILE *f = fopen(PATH_PERIOD_SET, "w");
|
||||
if (f == NULL) return;
|
||||
|
||||
@@ -10,11 +10,11 @@
|
||||
#define PATH_PERIOD_ST SYSFS_BASE_PATH "/period_status"
|
||||
#define PATH_PERIOD_SET SYSFS_BASE_PATH "/period_set"
|
||||
|
||||
float get_temperature();
|
||||
uint32_t get_mode();
|
||||
void set_mode(uint32_t mode);
|
||||
uint32_t get_period();
|
||||
void set_period(uint32_t period);
|
||||
float sysfs_get_temperature();
|
||||
uint32_t sysfs_get_mode();
|
||||
void sysfs_set_mode(uint32_t mode);
|
||||
uint32_t sysfs_get_period();
|
||||
void sysfs_set_period(uint32_t period);
|
||||
|
||||
|
||||
#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/button.h"
|
||||
#include "ipc/ipc_server.h"
|
||||
#include "oled/oled.h"
|
||||
#include "application/app.h"
|
||||
|
||||
#define DEFAULT_TIME_MS 1000
|
||||
#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) {
|
||||
|
||||
@@ -56,23 +30,34 @@ int main(void) {
|
||||
|
||||
led_t* led_power = led_init(LED_POWER);
|
||||
|
||||
btn_set_callback(btn_inc, period_inc);
|
||||
btn_set_callback(btn_dec, period_dec);
|
||||
btn_set_callback(btn_mode, period_reset);
|
||||
btn_set_callback(btn_inc, btn_decrease_period);
|
||||
btn_set_callback(btn_dec, btn_decrease_period);
|
||||
btn_set_callback(btn_mode, set_mode);
|
||||
|
||||
struct ipc_callbacks_t ipc_cbs = {
|
||||
.on_dec_frequency = period_dec,
|
||||
.on_inc_frequency = period_inc,
|
||||
.on_set_frequency = set_period,
|
||||
.on_dec_frequency = decrease_period,
|
||||
.on_inc_frequency = increase_period,
|
||||
// .on_set_frequency = set_period,
|
||||
.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);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Failed to start IPC server: %d\n", ret);
|
||||
return 1;
|
||||
}
|
||||
|
||||
init_oled(&oled_cbs);
|
||||
|
||||
btn_set_led(led_power);
|
||||
init_animations();
|
||||
|
||||
while (1) {
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
@@ -26,26 +26,26 @@ static void display(int mode, float temp, uint32_t period_ms) {
|
||||
/* Static header rows */
|
||||
ssd1306_set_position(0, 0);
|
||||
ssd1306_puts("CSEL1a - SP.07");
|
||||
ssd1306_set_position(0, 1);
|
||||
ssd1306_puts(" WATCHDOG CPU ");
|
||||
ssd1306_set_position(0, 2);
|
||||
ssd1306_puts("--------------");
|
||||
// ssd1306_set_position(0, 1);
|
||||
// ssd1306_puts(" WATCHDOG CPU ");
|
||||
// ssd1306_set_position(0, 2);
|
||||
// ssd1306_puts("--------------");
|
||||
|
||||
/* Mode display: switches between AUTO and MANU strings */
|
||||
ssd1306_set_position(0, 3);
|
||||
snprintf(buffer, sizeof(buffer), "Mode: %s", mode ? "AUTO" : "MANU");
|
||||
ssd1306_puts(buffer);
|
||||
// /* Mode display: switches between AUTO and MANU strings */
|
||||
// ssd1306_set_position(0, 3);
|
||||
// snprintf(buffer, sizeof(buffer), "Mode: %s", mode ? "AUTO" : "MANU");
|
||||
// ssd1306_puts(buffer);
|
||||
|
||||
/* Temperature display: formatted with one decimal precision */
|
||||
ssd1306_set_position(0, 4);
|
||||
snprintf(buffer, sizeof(buffer), "Temp: %.1f'C", temp);
|
||||
ssd1306_puts(buffer);
|
||||
// /* Temperature display: formatted with one decimal precision */
|
||||
// ssd1306_set_position(0, 4);
|
||||
// snprintf(buffer, sizeof(buffer), "Temp: %.1f'C", temp);
|
||||
// ssd1306_puts(buffer);
|
||||
|
||||
/* Period/Frequency display: shows the value in milliseconds */
|
||||
ssd1306_set_position(0, 5);
|
||||
float freq = 1.0f / (period_ms / 1000.0f);
|
||||
snprintf(buffer, sizeof(buffer), "Freq: %.1fHz", freq);
|
||||
ssd1306_puts(buffer);
|
||||
// /* Period/Frequency display: shows the value in milliseconds */
|
||||
// ssd1306_set_position(0, 5);
|
||||
// float freq = 1.0f / (period_ms / 1000.0f);
|
||||
// snprintf(buffer, sizeof(buffer), "Freq: %.1fHz", freq);
|
||||
// ssd1306_puts(buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -65,7 +65,7 @@ static void *update_oled_thread(void* arg) {
|
||||
);
|
||||
}
|
||||
/* Sleep to control refresh rate and save CPU cycles */
|
||||
usleep(250000);
|
||||
usleep(1000000);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -14,11 +14,11 @@
|
||||
|
||||
#define ARRAY_OF(x) (sizeof(x)/sizeof(x[0]))
|
||||
|
||||
#define I2C_BUS "/dev/i2c-0"
|
||||
#define OLED_ADDR 0x3c
|
||||
#define I2C_BUS "/dev/i2c-1"
|
||||
#define OLED_ADDR 0x3c
|
||||
#define OLED_COMMAND_MODE 0x00
|
||||
#define OLED_DATA_MODE 0x40
|
||||
#define OLED_DISPLAY_OFF_CMD 0xae
|
||||
#define OLED_DATA_MODE 0x40
|
||||
#define OLED_DISPLAY_OFF_CMD 0xae
|
||||
#define OLED_DISPLAY_ON_CMD 0xaf
|
||||
|
||||
static const uint8_t font[][8] = {
|
||||
@@ -163,7 +163,7 @@ static void send_command(uint8_t cmd)
|
||||
}
|
||||
}
|
||||
|
||||
void send_data(uint8_t byte)
|
||||
void send_data(uint8_t byte)
|
||||
{
|
||||
uint8_t buf[2] = {
|
||||
[0] = OLED_DATA_MODE,
|
||||
@@ -181,7 +181,7 @@ void ssd1306_set_position (uint32_t column, uint32_t row)
|
||||
send_command(0x10 + ((8*column>>4)&0x0f)); //set column higher address
|
||||
}
|
||||
|
||||
void ssd1306_putc(char c)
|
||||
void ssd1306_putc(char c)
|
||||
{
|
||||
if ((c<32) || (c>127)) // Ignore non-printable ASCII characters
|
||||
c=' ';
|
||||
@@ -193,7 +193,7 @@ void ssd1306_putc(char c)
|
||||
}
|
||||
}
|
||||
|
||||
void ssd1306_puts(const char* str)
|
||||
void ssd1306_puts(const char* str)
|
||||
{
|
||||
while (*str != 0)
|
||||
ssd1306_putc(*str++);
|
||||
@@ -203,7 +203,7 @@ void ssd1306_clear_display()
|
||||
{
|
||||
send_command(OLED_DISPLAY_OFF_CMD);// display off
|
||||
for (int j=0; j<8; j++) {
|
||||
ssd1306_set_position(0,j);
|
||||
ssd1306_set_position(0,j);
|
||||
for (int i=0; i<16; i++) //clear all columns
|
||||
ssd1306_putc(' ');
|
||||
}
|
||||
@@ -218,7 +218,7 @@ int ssd1306_init()
|
||||
printf("ERROR: unable to open i2c bus interface (%s)\n", I2C_BUS);
|
||||
return -1;
|
||||
}
|
||||
if (ioctl(fd, I2C_SLAVE, OLED_ADDR) < 0) {
|
||||
if (ioctl(fd, I2C_SLAVE, OLED_ADDR) < 0) {
|
||||
printf("ERROR: unable to access OLED as slave\n");
|
||||
return -1;
|
||||
}
|
||||
@@ -231,6 +231,3 @@ int ssd1306_init()
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user