This commit is contained in:
2026-05-11 11:13:54 +02:00
parent c93ae21114
commit c1fd1f706e
11 changed files with 41 additions and 39 deletions

View File

@@ -6,9 +6,9 @@ project(linuxSmartie
)
# Use C23
set(CMAKE_C_STANDARD 23)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_C_EXTENSIONS ON)
set(CMAKE_C_STANDARD 99)
#set(CMAKE_C_STANDARD_REQUIRED ON)
#set(CMAKE_C_EXTENSIONS ON)
# Collect sources
file(GLOB SOURCES

View File

@@ -1,7 +1,7 @@
# linuxSmartie
Alphanumeric LCD controller software for Linux (kind of LCDSmartie for Windows but no GUI, no config file, no plugins, no Windows).
Big ol rewrite in C, like God intended because GOOD LORD C++ IS A MESS.
Big ol rewrite in C, like God intended because GOOD LORD C++ IS A MESS. Originally written with C23, then ported to C99 because it's a bigger numer. Also trivially portable to ANSI C. Idk maybe I'll port it to C23 again.
Hardcoded to work with 4x40 character display because that's what I have and I don't plan on using anything else. Uses Matrix Orbital protocol over serial. Should work with most other display sizes by modifying `src/LCDDisplay.cpp`. Best of luck if you try to make it work with anything else.

View File

@@ -2,6 +2,7 @@
#define GPU_H
#include <stdint.h>
#include <stdbool.h>
struct gpu_sensors_t {
uint64_t vram_used;

View File

@@ -20,7 +20,7 @@ typedef enum {
LOG_ERR,
LOG_DBG,
LOG_START,
} LogLevel;
} log_level_t;
/* __PRETTY_FUNCTION__ is a GCC/Clang extension that gives the full
s ignature: "voi*d foo(int x)" — same thing source_location gave you.
@@ -30,7 +30,7 @@ log_write(level, __PRETTY_FUNCTION__, fmt, ##__VA_ARGS__)
/* format attribute gives compile-time printf format checking —
better than wha*t std::format gave you at runtime */
void log_write(LogLevel level, const char *func, const char *fmt, ...)
void log_write(log_level_t level, const char *func, const char *fmt, ...)
__attribute__((format(printf, 3, 4)));
#else /* APPLOG_ENABLED not defined */

View File

@@ -2,11 +2,12 @@
#define UTILS_H
#include <time.h>
#include <stdbool.h>
uint64_t timespec_diff_us(const struct timespec *a, const struct timespec *b);
void timespec_add_ms(struct timespec *ts, uint16_t ms);
char *pretty_bytes(uint64_t bytes, int8_t start_suffix, char *buf, size_t bufsz);
char *pretty_num(const double num, char *buf, const size_t bufsz);
char *pretty_num(double num, char *buf, size_t bufsz);
void fast_read_num_u64(const char* dir, const char* file, char* buf, uint64_t* result, uint32_t divider);
void fast_read_num_u16(const char* dir, const char* file, char* buf, uint16_t* result, uint32_t divider);

View File

@@ -7,8 +7,8 @@
#include "utils.h"
#include "log.h"
constexpr char rel_metrics_path[] = "/../../gpu_metrics"; // gpu_metrics path relative to hwmon path
constexpr uint16_t max_metrics_length = 512; // length of the metrics buffer
const char rel_metrics_path[] = "/../../gpu_metrics"; // gpu_metrics path relative to hwmon path
const uint16_t max_metrics_length = 512; // length of the metrics buffer
void gpu_detect(struct gpu_sensors_t *t, const char *pci) {
snprintf(t->hwmon, sizeof(t->hwmon), "/sys/bus/pci/devices/%s/hwmon", pci);

View File

@@ -36,7 +36,7 @@ void lcd_write(struct lcd_t* lcd, const uint8_t* cmdbuf, const uint8_t len) {
}
void lcd_clear(struct lcd_t* lcd) {
constexpr uint8_t cmdbuf[] = {254, 88};
const uint8_t cmdbuf[] = {254, 88};
lcd_write(lcd, cmdbuf, sizeof(cmdbuf));
}
@@ -106,7 +106,7 @@ inline void lcd_clear_buf(struct lcd_t* lcd) {
/* flushes writebuffer to lcd, hyperoptmized, flushes buffer and commands in a single write operation */
inline void lcd_flush_buf(struct lcd_t* lcd) {
constexpr uint8_t set_disp[] = {254, 71, 1, 1}; // set cursor to char 1, line 1
const uint8_t set_disp[] = {254, 71, 1, 1}; // set cursor to char 1, line 1
memcpy(&lcd->writebuf[0], set_disp, 4);
memcpy(&lcd->writebuf[2 * LCD_COLS + 4], set_disp, 4);
lcd->writebuf[2 * LCD_COLS + 7] = 3; // overwrite set cursor c1 l1 to c1 l3
@@ -138,7 +138,7 @@ int lcd_init(struct lcd_t* lcd) {
tcsetattr(lcd->fd, TCSANOW, &term);
lcd_clear_buf(lcd);
constexpr uint8_t cmdbuf[] = {254, 75, 254, 84};
const uint8_t cmdbuf[] = {254, 75, 254, 84};
lcd_write(lcd, cmdbuf, sizeof(cmdbuf));
lcd_clear(lcd);

View File

@@ -33,7 +33,7 @@ static void fmt_funcname(const char *pretty, char *out, size_t outsz) {
out[len] = '\0';
}
void log_write(const LogLevel level, const char *func, const char *fmt, ...) {
void log_write(const log_level_t level, const char *func, const char *fmt, ...) {
static const char *reset = "\033[0m";
const char *color;

View File

@@ -14,10 +14,10 @@
#include "sys.h"
#include "utils.h"
static constexpr uint16_t refresh_interval_ms = 500;
static constexpr char netif[] = "enp7s0";
static constexpr char cpu_pcidev[] = "0000:00:18.3";
static constexpr char gpu_pcidev[] = "0000:0a:00.0";
static const uint16_t refresh_interval_ms = 500;
static const char netif[] = "enp7s0";
static const char cpu_pcidev[] = "0000:00:18.3";
static const char gpu_pcidev[] = "0000:0a:00.0";
struct control_t {
pthread_mutex_t sensors_mtx;
@@ -67,11 +67,11 @@ static void *sensors_thread(void *arg) {
pthread_cond_signal(&control.sensors_ready);
timespec_add_ms(&next, refresh_interval_ms);
clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &next, nullptr);
clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &next, NULL);
}
applog(LOG_WRN, "sensors thread stopped");
return nullptr;
return NULL;
}
static void *display_thread(void *arg) {
@@ -148,7 +148,7 @@ static void *display_thread(void *arg) {
lcd_flush_buf(&lcd);
lcd_close(&lcd);
applog(LOG_WRN, "display thread stopped");
return nullptr;
return NULL;
}
int main(void) {
@@ -161,18 +161,18 @@ int main(void) {
sigaddset(&sigset, SIGINT);
sigaddset(&sigset, SIGTERM);
sigaddset(&sigset, SIGQUIT);
pthread_sigmask(SIG_BLOCK, &sigset, nullptr);
pthread_sigmask(SIG_BLOCK, &sigset, NULL);
struct signalfd_siginfo info;
const int sfd = signalfd(-1, &sigset, SFD_CLOEXEC);
/* control vars setup */
pthread_mutex_init(&control.sensors_mtx, nullptr);
pthread_cond_init(&control.sensors_ready, nullptr);
pthread_mutex_init(&control.sensors_mtx, NULL);
pthread_cond_init(&control.sensors_ready, NULL);
/* allocate mem for the main struct */
struct sensors_t *sensors = malloc(sizeof(struct sensors_t));
if (sensors == nullptr) {
if (sensors == NULL) {
applog(LOG_ERR, "cant allocate mem for the sensor struct");
free(sensors);
return -1;
@@ -184,8 +184,8 @@ int main(void) {
pthread_t sensors_pthread;
/* actually start the threads */
pthread_create(&display_pthread, nullptr, display_thread, sensors);
pthread_create(&sensors_pthread, nullptr, sensors_thread, sensors);
pthread_create(&display_pthread, NULL, display_thread, sensors);
pthread_create(&sensors_pthread, NULL, sensors_thread, sensors);
const ssize_t ret = read(sfd, &info, sizeof(info)); // halts on this until SIGTERM
(void)ret;
@@ -194,8 +194,8 @@ int main(void) {
applog(LOG_WRN, "got stop signal, shutting down...");
close(sfd);
control.g_running = false;
pthread_join(display_pthread, nullptr);
pthread_join(sensors_pthread, nullptr);
pthread_join(display_pthread, NULL);
pthread_join(sensors_pthread, NULL);
free(sensors);
return 0;
}

View File

@@ -10,9 +10,9 @@
void sys_get_time(struct time_date_t *td) {
constexpr char months[][4] = {"sty", "lut", "mar", "kwi", "maj", "cze", "lip", "sie", "wrz", "paz", "lis", "gru"};
constexpr char wdays[][4] = {"Nie", "Pon", "Wto", "Sro", "Czw", "Pia", "Sob"};
const time_t t = time(nullptr);
const char months[][4] = {"sty", "lut", "mar", "kwi", "maj", "cze", "lip", "sie", "wrz", "paz", "lis", "gru"};
const char wdays[][4] = {"Nie", "Pon", "Wto", "Sro", "Czw", "Pia", "Sob"};
const time_t t = time(NULL);
const struct tm *tm = localtime(&t);
snprintf(td->time, sizeof(td->time), "%02d:%02d:%02d", tm->tm_hour, tm->tm_min, tm->tm_sec);
snprintf(td->date, sizeof(td->date), "%s, %02d %s", wdays[tm->tm_wday], tm->tm_mday, months[tm->tm_mon]);
@@ -27,7 +27,7 @@ void sys_get_ram(struct memory_t *ram) {
memset(ram, 0, sizeof(struct memory_t)); // zero out all values so we dont break out of the loop early
FILE *f = fopen("/proc/meminfo", "r");
if (f == nullptr)
if (f == NULL)
return;
while (fgets(buf, sizeof(buf), f)) {

View File

@@ -36,7 +36,7 @@ inline char *pretty_num(const double num, char *buf, const size_t bufsz) {
}
inline char *pretty_bytes(const uint64_t bytes, int8_t start_suffix, char *buf, const size_t bufsz) {
constexpr char suffix_list[] = {'K', 'M', 'G', 'T', 'P', 'E', 'Z'};
const char suffix_list[] = {'K', 'M', 'G', 'T', 'P', 'E', 'Z'};
start_suffix *= -1;
double bytes_d = (double)bytes;
while (bytes_d > 1024.0) {
@@ -57,7 +57,7 @@ int get_hwmon_dir(char* path) {
glob_t g;
strncat(path, "/hwmon*", 10);
if (glob(path, 0, nullptr, &g) == 0) {
if (glob(path, 0, NULL, &g) == 0) {
strncpy(path, g.gl_pathv[0], 128); // bug prone, careful
globfree(&g);
return 0;
@@ -82,33 +82,33 @@ inline void fast_read_num_u64(const char* dir, const char* file, char* buf, uint
char path[256];
MKPATH(path, dir, file);
read_file(path, buf, 32);
*result = strtoull(buf, nullptr, 10) / divider;
*result = strtoull(buf, NULL, 10) / divider;
}
inline void fast_read_num_u16(const char* dir, const char* file, char* buf, uint16_t* result, const uint32_t divider) {
char path[256];
MKPATH(path, dir, file);
read_file(path, buf, 32);
*result = strtol(buf, nullptr, 10) / divider;
*result = strtol(buf, NULL, 10) / divider;
}
inline void fast_read_num_u8(const char* dir, const char* file, char* buf, uint8_t* result, const uint32_t divider) {
char path[256];
MKPATH(path, dir, file);
read_file(path, buf, 32);
*result = strtol(buf, nullptr, 10) / divider;
*result = strtol(buf, NULL, 10) / divider;
}
inline void fast_read_num_i16(const char* dir, const char* file, char* buf, int16_t* result, const uint32_t divider) {
char path[256];
MKPATH(path, dir, file);
read_file(path, buf, 32);
*result = strtol(buf, nullptr, 10) / divider;
*result = strtol(buf, NULL, 10) / divider;
}
inline void fast_read_num_f(const char* dir, const char* file, char* buf, float* result, const uint32_t divider) {
char path[256];
MKPATH(path, dir, file);
read_file(path, buf, 32);
*result = (float)strtoull(buf, nullptr, 10) / (float)divider;
*result = (float)strtoull(buf, NULL, 10) / (float)divider;
}