Last active
December 15, 2020 08:48
-
-
Save AnthonyDiGirolamo/9491567 to your computer and use it in GitHub Desktop.
RGB LED CPU usage on a Raspberry Pi
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdint.h> | |
#include <unistd.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <getopt.h> | |
#include <fcntl.h> | |
#include <sys/ioctl.h> | |
#include <linux/types.h> | |
#include <linux/spi/spidev.h> | |
#include <signal.h> | |
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) | |
static void pabort(const char *s) | |
{ | |
perror(s); | |
abort(); | |
} | |
static const char *device = "/dev/spidev0.0"; | |
static uint8_t mode; | |
static uint8_t bits = 8; | |
static uint32_t speed = 500000; | |
static uint16_t delay; | |
static int color_mode = 0; | |
static int max_brightness = 128; | |
#define BLUE_TO_RED 0 | |
#define GREEN_TO_RED 1 | |
static void transfer(int fd, uint8_t r_color, uint8_t g_color, uint8_t b_color) | |
{ | |
int ret; | |
uint8_t tx[] = { | |
r_color, g_color, b_color, | |
}; | |
uint8_t rx[ARRAY_SIZE(tx)] = {0, }; | |
struct spi_ioc_transfer tr = { | |
.tx_buf = (unsigned long)tx, | |
.rx_buf = (unsigned long)rx, | |
.len = ARRAY_SIZE(tx), | |
.delay_usecs = delay, | |
.speed_hz = speed, | |
.bits_per_word = bits, | |
}; | |
ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr); | |
if (ret < 1) | |
pabort("can't send spi message"); | |
} | |
static void print_usage(const char *prog) | |
{ | |
printf("Usage: %s [-DsbdlHOLC3]\n", prog); | |
puts(" -D --device device to use (default /dev/spidev0.0)\n" | |
" -s --speed max speed (Hz)\n" | |
" -d --delay delay (usec)\n" | |
" -b --bpw bits per word \n" | |
" -l --loop loopback\n" | |
" -H --cpha clock phase\n" | |
" -O --cpol clock polarity\n" | |
" -L --lsb least significant bit first\n" | |
" -C --cs-high chip select active high\n" | |
" -3 --3wire SI/SO signals shared\n" | |
" -B --blue_to_red\n" | |
" -G --green_to_red\n" | |
" -M --max_brightness\n"); | |
exit(1); | |
} | |
static void parse_opts(int argc, char *argv[]) | |
{ | |
while (1) { | |
static const struct option lopts[] = { | |
{ "device", 1, 0, 'D' }, | |
{ "speed", 1, 0, 's' }, | |
{ "delay", 1, 0, 'd' }, | |
{ "bpw", 1, 0, 'b' }, | |
{ "loop", 0, 0, 'l' }, | |
{ "cpha", 0, 0, 'H' }, | |
{ "cpol", 0, 0, 'O' }, | |
{ "lsb", 0, 0, 'L' }, | |
{ "cs-high", 0, 0, 'C' }, | |
{ "3wire", 0, 0, '3' }, | |
{ "no-cs", 0, 0, 'N' }, | |
{ "ready", 0, 0, 'R' }, | |
{ "blue_to_red", 0, 0, 'B' }, | |
{ "green_to_red", 0, 0, 'G' }, | |
{ "max_brightness", 1, 0, 'M' }, | |
{ NULL, 0, 0, 0 }, | |
}; | |
int c; | |
c = getopt_long(argc, argv, "D:s:d:b:lHOLC3NRBGM:", lopts, NULL); | |
if (c == -1) | |
break; | |
switch (c) { | |
case 'D': | |
device = optarg; | |
break; | |
case 's': | |
speed = atoi(optarg); | |
break; | |
case 'd': | |
delay = atoi(optarg); | |
break; | |
case 'b': | |
bits = atoi(optarg); | |
break; | |
case 'l': | |
mode |= SPI_LOOP; | |
break; | |
case 'H': | |
mode |= SPI_CPHA; | |
break; | |
case 'O': | |
mode |= SPI_CPOL; | |
break; | |
case 'L': | |
mode |= SPI_LSB_FIRST; | |
break; | |
case 'C': | |
mode |= SPI_CS_HIGH; | |
break; | |
case '3': | |
mode |= SPI_3WIRE; | |
break; | |
case 'N': | |
mode |= SPI_NO_CS; | |
break; | |
case 'R': | |
mode |= SPI_READY; | |
break; | |
case 'B': | |
color_mode = BLUE_TO_RED; | |
break; | |
case 'G': | |
color_mode = GREEN_TO_RED; | |
break; | |
case 'M': | |
max_brightness = atoi(optarg); | |
if (max_brightness > 254) | |
max_brightness = 254; | |
if (max_brightness < 0) | |
max_brightness = 0; | |
break; | |
default: | |
print_usage(argv[0]); | |
break; | |
} | |
} | |
} | |
FILE *stat_file; | |
int fd; | |
int signal_trapped = 0; | |
void signal_handler(int sig) { | |
signal_trapped = 1; | |
} | |
int main(int argc, char *argv[]) | |
{ | |
signal(SIGINT, signal_handler); | |
signal(SIGTERM, signal_handler); | |
signal(SIGABRT, signal_handler); | |
signal(SIGKILL, signal_handler); | |
signal(SIGQUIT, signal_handler); | |
int ret = 0; | |
parse_opts(argc, argv); | |
fd = open(device, O_RDWR); | |
if (fd < 0) | |
pabort("can't open device"); | |
// spi mode | |
ret = ioctl(fd, SPI_IOC_WR_MODE, &mode); | |
if (ret == -1) | |
pabort("can't set spi mode"); | |
ret = ioctl(fd, SPI_IOC_RD_MODE, &mode); | |
if (ret == -1) | |
pabort("can't get spi mode"); | |
// bits per word | |
ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits); | |
if (ret == -1) | |
pabort("can't set bits per word"); | |
ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits); | |
if (ret == -1) | |
pabort("can't get bits per word"); | |
// max speed hz | |
ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed); | |
if (ret == -1) | |
pabort("can't set max speed hz"); | |
ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed); | |
if (ret == -1) | |
pabort("can't get max speed hz"); | |
// printf("spi mode: %d\n", mode); | |
// printf("bits per word: %d\n", bits); | |
// printf("max speed: %d Hz (%d KHz)\n", speed, speed/1000); | |
int user[2], nice[2], system[2], idle[2], iowait[2], irq[2], softirq[2]; | |
float cpu_usage[3] = {0.0, 0.0, 0.0}; | |
float cpu_average; | |
int i, j; | |
float r=0, g=0, b=0; | |
float r_step=0, g_step=0, b_step=0; | |
float r0=0, g0=0, b0=0; | |
float r1=0, g1=0, b1=0; | |
stat_file = fopen("/proc/stat", "r"); | |
fscanf(stat_file, "cpu %d %d %d %d %d %d %d\n", &user[1], &nice[1], &system[1], &idle[1], &iowait[1], &irq[1], &softirq[1]); | |
fclose(stat_file); | |
sleep(1); | |
while (1) { | |
user[0] = user[1]; | |
nice[0] = nice[1]; | |
system[0] = system[1]; | |
idle[0] = idle[1]; | |
iowait[0] = iowait[1]; | |
irq[0] = irq[1]; | |
softirq[0] = softirq[1]; | |
stat_file = fopen("/proc/stat", "r"); | |
fscanf(stat_file, "cpu %d %d %d %d %d %d %d\n", &user[1], &nice[1], &system[1], &idle[1], &iowait[1], &irq[1], &softirq[1]); | |
fclose(stat_file); | |
cpu_usage[2] = cpu_usage[1]; | |
cpu_usage[1] = cpu_usage[0]; | |
cpu_usage[0] = (float) ((user[1] + nice[1] + system[1]) - (user[0] + nice[0] + system[0])) / ((user[1] + nice[1] + system[1] + idle[1] + iowait[1] + irq[1] + softirq[1]) - (user[0] + nice[0] + system[0] + idle[0] + iowait[0] + irq[0] + softirq[0])); | |
/* printf("cpu_usage = %f\n", cpu_usage[0]); */ | |
/* cpu_average = (cpu_usage[0] + cpu_usage[1] + cpu_usage[2]) / 3.0; */ | |
cpu_average = cpu_usage[0]; | |
/* printf("cpu_average = %f\n", cpu_average); */ | |
r0 = r1; g0 = g1; b0 = b1; | |
if (color_mode == BLUE_TO_RED) { | |
r1 = (cpu_average * max_brightness); | |
g1 = 0; | |
b1 = (max_brightness - (cpu_average * max_brightness)); | |
} | |
else if (color_mode == GREEN_TO_RED) { | |
r1 = (cpu_average * max_brightness); | |
g1 = (max_brightness - (cpu_average * max_brightness)); | |
b1 = 0; | |
} | |
r = r0; g = g0; b = b0; | |
/* printf("r0 g0 b0 = %f %f %f\n", r0, g0, b0); */ | |
/* printf("r g b = %f %f %f\n", r, g, b); */ | |
/* printf("r1 g1 b1 = %f %f %f\n", r1, g1, b1); */ | |
r_step = ((r1 - r0) / 10.0); | |
g_step = ((g1 - g0) / 10.0); | |
b_step = ((b1 - b0) / 10.0); | |
/* printf("r g b step = %f %f %f\n", r_step, g_step, b_step); */ | |
for (i=0; i<10; i++) { | |
transfer(fd, (uint8_t) r, (uint8_t) g, (uint8_t) b); | |
r += r_step; | |
g += g_step; | |
b += b_step; | |
usleep(100000); | |
} | |
if (signal_trapped) | |
break; | |
} | |
// Turn off the light and exit | |
transfer(fd, 0, 0, 0); | |
close(fd); | |
return ret; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment