Skip to content

Instantly share code, notes, and snippets.

@AnthonyDiGirolamo
Last active December 15, 2020 08:48
Show Gist options
  • Save AnthonyDiGirolamo/9491567 to your computer and use it in GitHub Desktop.
Save AnthonyDiGirolamo/9491567 to your computer and use it in GitHub Desktop.
RGB LED CPU usage on a Raspberry Pi
#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