Skip to content

Instantly share code, notes, and snippets.

@stolk
Created June 11, 2022 23:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stolk/3356e4e350bae7921e55693ba65d6f4a to your computer and use it in GitHub Desktop.
Save stolk/3356e4e350bae7921e55693ba65d6f4a to your computer and use it in GitHub Desktop.
#include <linux/fb.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
static uint32_t* fbi=0;
static int fbw=0;
static int fbh=0;
static uint32_t* im;
#define STENCILX 136
#define STENCILY 362
#define STENCILW 208
#define STENCILH 35
static uint32_t graph[STENCILH][STENCILW];
static int writer=0;
uint8_t* readpgm(const char* nm, int* w, int* h)
{
FILE* f = fopen(nm, "rb");
assert(f);
int maxv=0;
char eol=0;
int scanned = fscanf(f, "P5 %d %d %d%c", w, h, &maxv, &eol);
assert(scanned==4);
uint8_t* img = (uint8_t*)malloc(*w * *h);
assert(img);
const int numr = fread(img, *w, *h, f);
assert(numr==*h);
fclose(f);
return img;
}
static void cut_stencil(void)
{
uint32_t* dst = fbi + STENCILX + STENCILY*fbw;
const size_t sz = STENCILW * sizeof(int32_t);
for (int i=0; i<STENCILH; ++i)
{
memcpy(dst, graph[i], sz);
//memset(dst, 0, sz);
dst += fbw;
}
}
static void write_sample(float s)
{
static int tprv = 0;
const int t = (int) ( STENCILH - 1.5f - s * (STENCILH-3) );
uint32_t* dst = fbi + STENCILX + 1 + writer + STENCILY*fbw;
for (int y=0; y<STENCILH; ++y)
{
*dst = ((y>=t && y<=tprv) || (y>=tprv && y<=t)) ? 0x0080ff80 : 0x00000000;
dst += fbw;
}
writer = writer+1;
writer = writer >= STENCILW-2 ? 0 : writer;
tprv = t;
}
static uint32_t *prev=0;
static uint32_t *curr=0;
// Reads for each cpu: how many jiffies were spent in each state:
// user, nice, system, idle, iowait, irq, softirq
// NOTE: nice is a sub category of user. iowait is a sub category of idle. (soft)irq are sub categories too.
void get_usages( int num_cpus, float* usages )
{
if ( !prev || !curr )
{
const size_t sz = sizeof(uint32_t) * 7 * num_cpus;
prev = (uint32_t*) malloc( sz );
curr = (uint32_t*) malloc( sz );
memset( prev, 0, sz );
memset( curr, 0, sz );
}
static FILE* f = 0;
if ( !f )
{
f = fopen( "/proc/stat", "rb" );
assert( f );
}
char info[16384];
const int numr = fread( info, 1, sizeof(info), f );
assert( numr > 0 );
rewind(f);
if ( numr < sizeof(info) )
{
info[numr] = 0;
for ( int cpu=0; cpu<num_cpus; ++cpu )
{
char tag[16];
snprintf( tag, sizeof(tag), "cpu%d", cpu );
const char* s = strstr( info, tag );
assert( s );
int cpunr;
uint32_t* prv = prev + cpu * 7;
uint32_t* cur = curr + cpu * 7;
const int numscanned = sscanf( s, "cpu%d %u %u %u %u %u %u %u", &cpunr, cur+0, cur+1, cur+2, cur+3, cur+4, cur+5, cur+6 );
assert( numscanned == 8 );
assert( cpunr == cpu );
uint32_t deltas[7];
for ( int i=0; i<7; ++i )
{
deltas[i] = cur[i] - prv[i];
prv[i] = cur[i];
}
const uint32_t user = deltas[0];
const uint32_t syst = deltas[2];
const uint32_t idle = deltas[3];
const uint32_t work = user + syst;
float denom = (idle+work);
denom = denom <= 0 ? 1 : denom;
usages[ cpu ] = work / denom;
}
}
}
int setup(void)
{
// How many cores in this system?
const int num_cpus = sysconf( _SC_NPROCESSORS_ONLN );
fprintf( stderr, "Found %d cpus.\n", num_cpus );
return num_cpus;
}
int main(int argc, char* argv[])
{
int fb = open("/dev/fb0", O_RDWR);
assert(fb > 0);
struct fb_fix_screeninfo info_fix;
struct fb_var_screeninfo info_var;
int r;
r=ioctl(fb, FBIOGET_FSCREENINFO, &info_fix);
if (r<0) perror("FBIOGET_FSCREENINFO");
assert(r>=0);
r=ioctl(fb, FBIOGET_VSCREENINFO, &info_var);
if (r<0) perror("FBIOGET_VSCREENINFO");
assert(r>=0);
fbw = info_fix.line_length/4;
fbh = info_var.yres;
fprintf(stderr,"RES: %dx%d\n", fbw, fbh);
const size_t len = 4 * fbw * fbh;
fbi = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fb, 0);
assert(fbi != MAP_FAILED);
const int num_cpus = setup();
float* usages = (float*)malloc(sizeof(float) * num_cpus);
get_usages(num_cpus, usages);
if (argc==2)
{
const char* fname = argv[1];
FILE* f = fopen(fname,"rb");
assert(f);
const int numpix = fbw*fbh;
const size_t imsz = numpix*sizeof(uint32_t);
im = (uint32_t*)malloc(imsz);
const size_t numr = fread(im, sizeof(uint32_t), numpix, f);
assert(numr==numpix);
fclose(f);
memcpy(fbi, im, imsz);
cut_stencil();
}
//for (int i=0; i<100000; ++i)
while(1)
{
static float smooth_val=0.0f;
get_usages(num_cpus, usages);
smooth_val = 0.9f * smooth_val + 0.1f * usages[0];
assert(usages[0]>=0);
assert(usages[0]<=1);
write_sample(smooth_val);
usleep(10000);
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment