Skip to content

Instantly share code, notes, and snippets.

@MightyPork
Created December 10, 2017 19:01
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 MightyPork/a04ba28cc92e191116b75fedbbfa4aa8 to your computer and use it in GitHub Desktop.
Save MightyPork/a04ba28cc92e191116b75fedbbfa4aa8 to your computer and use it in GitHub Desktop.
GEX 0.0.1 demo: Neopixel Dynamic Screen Backlight
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <math.h>
#include "TinyFrame.h"
#include "serial.h"
#include <X11/Xlib.h>
#include <X11/X.h>
#include <X11/Xutil.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
void INThandler(int);
typedef struct RGB_struct {
uint8_t b;
uint8_t g;
uint8_t r;
} RGB;
struct BloomInfo {
Display *display;
Window root;
XWindowAttributes gwa;
uint32_t width;
uint32_t height;
XImage *image;
};
union ScreenColor {
uint32_t hex;
RGB rgb;
struct {
uint8_t b;
uint8_t g;
uint8_t r;
};
};
struct BloomInfo bloom;
int bloom_init(void)
{
bloom.display = XOpenDisplay(NULL);
bloom.root = DefaultRootWindow(bloom.display);
XGetWindowAttributes(bloom.display, bloom.root, &bloom.gwa);
bloom.width = bloom.gwa.width;
bloom.height = bloom.gwa.height;
// The first image, to measure the screen and allocate the buffer
bloom.image = XGetImage(bloom.display, bloom.root, 0, 0, bloom.width, bloom.height, AllPlanes, ZPixmap);
//uint8_t array[width * height * 3];
const uint32_t red_mask = bloom.image->red_mask;
const uint32_t green_mask = bloom.image->green_mask;
const uint32_t blue_mask = bloom.image->blue_mask;
printf("mask: %p %p %p\nbyte_order: %d\nunit: %d\nbit_order: %d\npad: %d\ndepth: %d\nBPL: %d\nbPPx: %d\n",
red_mask, green_mask, blue_mask, bloom.image->byte_order, bloom.image->bitmap_unit,
bloom.image->bitmap_bit_order, bloom.image->bitmap_pad, bloom.image->depth, bloom.image->bytes_per_line, bloom.image->bits_per_pixel);
}
void bloom_grab(uint32_t *dest, uint32_t width, uint32_t height)
{
// sampling steps
const uint32_t xnum = width;
const uint32_t ynum = height;
const uint32_t xstep = bloom.width/xnum;
const uint32_t ystep = (bloom.height*0.6)/ynum;
union ScreenColor *C;
XGetSubImage(bloom.display, bloom.root, 0, 0, bloom.width, bloom.height, AllPlanes, ZPixmap, bloom.image, 0, 0);
#define P_GOTO(x,y) C = ((union ScreenColor*)bloom.image->data + (y)*bloom.width + (x));
for (int i = 0; i < ynum; i++) {
for (int j = 0; j < xnum; j++) {
P_GOTO(j*xstep, (int)(bloom.height*0.5)+i*ystep);
C->r /= 2;
C->g /= 2;
C->b /= 2;
dest[i*xnum+j] = (C->r) | ((C->g&0xFF)<<8) | ((C->b&0xFF)<<16);
}
}
}
#define HIST_LEN 12
struct mm {
uint8_t r[HIST_LEN];
uint8_t g[HIST_LEN];
uint8_t b[HIST_LEN];
uint32_t i;
};
void mm_init(struct mm *mm)
{
memset(mm, 0, sizeof(struct mm));
}
void mm_add(struct mm *mm, uint32_t rgb)
{
mm->r[mm->i] = (rgb>>16)&255;
mm->g[mm->i] = (rgb>>8)&255;
mm->b[mm->i] = (rgb)&255;
if (++mm->i >= HIST_LEN) mm->i = 0;
}
uint32_t mm_avg(struct mm *mm)
{
float ar=0,ag=0,ab=0;
for(int i=0;i<HIST_LEN;i++) {
ar+=mm->r[i];
ag+=mm->g[i];
ab+=mm->b[i];
}
ar /= HIST_LEN;
ag /= HIST_LEN;
ab /= HIST_LEN;
if(ar>255) ar = 255;
if(ag>255) ag = 255;
if(ab>255) ab = 255;
if(ar<0) ar = 0;
if(ag<0) ag = 0;
if(ab<0) ab = 0;
return (uint32_t) (
(((int)floor(ab))&0xFF) |
((((int)floor(ag))&0xFF)<<8) |
((((int)floor(ar))&0xFF)<<16)
);
}
int fd;
const char *portname = "/dev/ttyACM0";
TF_Result respRecv(TF_Msg *msg)
{
printf("Response -> %.*s\n", msg->len, msg->data);
return TF_CLOSE;
}
TF_Result any(TF_Msg *msg)
{
printf("RX: %.*s\n", msg->len, msg->data);
return TF_CLOSE;
}
#define LEDS_N 30
struct rgb_payload {
uint8_t callsign;
uint8_t command;
uint32_t leds[LEDS_N];
} __attribute__((packed));
void TF_WriteImpl(const uint8_t *buff, size_t len)
{
write (fd, buff, len);
}
struct rgb_payload pld;
int main (void)
{
signal(SIGINT, INThandler);
printf("Starting\n");
bloom_init();
TF_Init(TF_MASTER);
TF_AddGenericListener(any);
fd = open (portname, O_RDWR | O_NOCTTY | O_SYNC);
if (fd < 0) {
printf("error %d opening %s: %s", errno, portname, strerror (errno));
return 1;
}
set_interface_attribs (fd, B115200, 0);
set_blocking (fd, 0);
// Send a ping
printf("Sending a ping request...\n");
TF_QuerySimple(1, NULL, 0, respRecv, 0, NULL);
//usleep(1000*50);
char buf [100];
int n = read (fd, buf, sizeof buf); // read up to 100 characters if ready to read
if (n>0) TF_Accept(buf, n);
pld.callsign = 0x02;
pld.command = 2; // sparse BigE
struct mm mms[LEDS_N];
for(int i=0;i<LEDS_N;i++) {
mm_init(&mms[i]);
}
while (1) {
bloom_grab(pld.leds, 30, 1);
for(int i=0;i<LEDS_N;i++) {
mm_add(&mms[i], pld.leds[i]);
pld.leds[i] = mm_avg(&mms[i]);
//printf("%06X",pld.leds[i]);
}
TF_SendSimple(16, (void*)&pld, sizeof(pld));
usleep(20000);
printf("\r");
}
// for(int i = 0; i < LEDS_N; i++) {
// pld.leds[i] = (0x00FF0000 + (i*9&0xFF)) - ((i*9&0xFF)<<16);
// }
/* TF_SendSimple(16, (void*)&pld, sizeof(pld));
usleep(1000000);*/
/*
for(int i = 0; i < LEDS_N; i++) {
pld.leds[i] = 0;
}
TF_SendSimple(16, (void*)&pld, sizeof(pld));
*/
#if 0
for (int i = 0; i < 100; i++) {
// usleep(10);
TF_SendSimple(16, "\x01\x02", 2);
usleep(1000);
// n = read (fd, buf, sizeof buf); // read up to 100 characters if ready to read
// if (n>0) TF_Accept(buf, n);
}
#endif
/*
printf("Sending messages\n");
for (int i = 0; i < 10; i++) {
TF_SendSimple(77, "ABCDEFG", 7);
usleep(1000*50);
}*/
close(fd);
return 0;
}
void INThandler(int sig)
{
for(int i = 0; i < LEDS_N; i++) {
pld.leds[i] = 0;
}
TF_SendSimple(16, (void*)&pld, sizeof(pld));
printf("closing.\r\n");
close(fd);
exit(0);
}
#include "serial.h"
#include <stdio.h>
int
set_interface_attribs (int fd, int speed, int parity)
{
struct termios tty;
memset (&tty, 0, sizeof tty);
if (tcgetattr (fd, &tty) != 0)
{
printf ("error %d from tcgetattr", errno);
return -1;
}
cfsetospeed (&tty, speed);
cfsetispeed (&tty, speed);
tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; // 8-bit chars
// disable IGNBRK for mismatched speed tests; otherwise receive break
// as \000 chars
tty.c_iflag &= ~IGNBRK; // disable break processing
tty.c_lflag = 0; // no signaling chars, no echo,
// no canonical processing
tty.c_oflag = 0; // no remapping, no delays
tty.c_cc[VMIN] = 0; // read doesn't block
tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout
tty.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl
tty.c_cflag |= (CLOCAL | CREAD);// ignore modem controls,
// enable reading
tty.c_cflag &= ~(PARENB | PARODD); // shut off parity
tty.c_cflag |= parity;
tty.c_cflag &= ~CSTOPB;
tty.c_cflag &= ~CRTSCTS;
if (tcsetattr (fd, TCSANOW, &tty) != 0)
{
printf ("error %d from tcsetattr", errno);
return -1;
}
return 0;
}
void
set_blocking (int fd, int should_block)
{
struct termios tty;
memset (&tty, 0, sizeof tty);
if (tcgetattr (fd, &tty) != 0)
{
printf ("error %d from tggetattr", errno);
return;
}
tty.c_cc[VMIN] = should_block ? 1 : 0;
tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout
if (tcsetattr (fd, TCSANOW, &tty) != 0)
printf ("error %d setting term attributes", errno);
}
#ifndef SERIAL_H
#define SERIAL_H
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
int
set_interface_attribs (int fd, int speed, int parity);
void
set_blocking (int fd, int should_block);
/*
...
char *portname = "/dev/ttyUSB1"
...
int fd = open (portname, O_RDWR | O_NOCTTY | O_SYNC);
if (fd < 0)
{
error_message ("error %d opening %s: %s", errno, portname, strerror (errno));
return;
}
set_interface_attribs (fd, B115200, 0); // set speed to 115,200 bps, 8n1 (no parity)
set_blocking (fd, 0); // set no blocking
write (fd, "hello!\n", 7); // send 7 character greeting
usleep ((7 + 25) * 100); // sleep enough to transmit the 7 plus
// receive 25: approx 100 uS per char transmit
char buf [100];
int n = read (fd, buf, sizeof buf); // read up to 100 characters if ready to read
*/
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment