Skip to content

Instantly share code, notes, and snippets.

@buzztiaan
Created September 18, 2019 02:43
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 buzztiaan/0485951b08548315407f9e4495443178 to your computer and use it in GitHub Desktop.
Save buzztiaan/0485951b08548315407f9e4495443178 to your computer and use it in GitHub Desktop.
Pixelflut on a ESP8266 with a HD44780 on a PCF8574 'i2c lcd backpack'
// Pixelflut on a ESP8266 with a HD44780 on a PCF8574 'i2c lcd backpack'
// yeah pretty silly :)
// 2019-09-18 buZz NURDspace.nl
#include <LiquidCrystal_PCF8574.h>
#include <Wire.h>
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#define MAXBUF 4096
LiquidCrystal_PCF8574 lcd(0x3F);
WiFiUDP Udp;
unsigned int localUdpPort = 4242;
char incomingPacket[MAXBUF];
char replyPacket[] = "OK";
// the LCD is just 20x4 characters, and only has 1 block character thats fully filled (5x8 pixels) , which is 0xFF
// lets add two more custom characters to get 20x8
int upperpixel[8] = {
B11111,
B11111,
B11111,
B11111,
B00000,
B00000,
B00000,
B00000
};
int lowerpixel[8] = {
B00000,
B00000,
B00000,
B00000,
B11111,
B11111,
B11111,
B11111
};
byte hexToByte (char c) {
if ( (c >= '0') && (c <= '9') ) {
return c - '0';
}
if ( (c >= 'A') && (c <= 'F') ) {
return (c - 'A')+10;
}
}
void setup() {
WiFi.begin("YOURNET", "YOURPASS");
int error;
Serial.begin(115200);
Serial.print("Connecting");
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
Serial.println();
Serial.print("Connected, IP address: ");
Serial.println(WiFi.localIP());
while (!Serial)
;
Serial.println("check for LCD");
Wire.setClock(100000);
Wire.begin();
Wire.beginTransmission(0x3F);
error = Wire.endTransmission();
Serial.print("Error: ");
Serial.print(error);
if (error == 0) {
Serial.println("LCD found.");
lcd.createChar(0,upperpixel);
lcd.createChar(1,lowerpixel);
lcd.begin(20, 4); // initialize the lcd
} else {
Serial.println("LCD not found.");
}
lcd.setBacklight(255);
lcd.home();
lcd.clear();
Udp.begin(localUdpPort);
}
int pixels[20*8]; // doublesize because of the custom char trick
int characters[20*4]; // cache
unsigned long previousMillis = 0;
const long interval = 200;
void loop() {
unsigned long currentMillis = millis();
// grab pixelflut ascii data
int packetSize = Udp.parsePacket();
if (packetSize)
{
int len = Udp.read(incomingPacket, MAXBUF);
if (len > 0)
{
incomingPacket[len] = '\0';
}
}
// parse
// format is "PX x y 24bithexcolor\n" and can come multiple times per package
char *saveptr1, *saveptr2;
char *token = strtok_r(incomingPacket, "\n", &saveptr1);
while (token) {
char *subtoken = strtok_r(token," ", &saveptr2);
int pos = 0;
int pixelvalues[8];
byte n = 0;
while (subtoken) {
if (pos==3) {
n = hexToByte( subtoken[ 0 ] );
n = ( n * 16 ) + hexToByte( subtoken[1] );
pixelvalues[2] = n;
n = hexToByte( subtoken[ 2 ] );
n = ( n * 16 ) + hexToByte( subtoken[3] );
pixelvalues[3] = n;
n = hexToByte( subtoken[ 4 ] );
n = ( n * 16 ) + hexToByte( subtoken[5] );
pixelvalues[4] = n;
} else if (pos>0) {
pixelvalues[pos-1] = atoi(subtoken);
}
pos++;
subtoken = strtok_r(NULL," ", &saveptr2);
}
token = strtok_r(NULL, "\n", &saveptr1);
// int comparecolor = (pixelvalues[2] + pixelvalues[3] + pixelvalues[4])/3;
int comparecolor = (pixelvalues[2]/3)+(pixelvalues[3]/2)+(pixelvalues[4]/6);
if (comparecolor>127) {
pixels[(pixelvalues[1]*20)+pixelvalues[0]] = 255;
} else {
pixels[(pixelvalues[1]*20)+pixelvalues[0]] = 0;
}
// pixels[(pixelvalues[1]*20)+pixelvalues[0]] = pixelvalues[2];
}
// display
// calc what could be displayed
for (int x = 0; x < 20; x++ ) {
int realY = 0;
for (int y = 0; y < 8; y+=2 ) {
// either this pixel is on or off
// but you'll need to check the X,Y+1 pixel aswell
// to know the right value to draw
if (pixels[(y*20)+x]>127) {
if (pixels[(y*20)+x+20]>127) {
// both full
characters[(realY * 20) + x] = 255;
} else {
// only top full
characters[(realY * 20) + x] = 0;
}
} else {
// top isnt full
if (pixels[(y*20)+x+20]>127) {
// bottom full
characters[(realY * 20) + x] = 1;
} else {
// both empty
characters[(realY * 20) + x] = 32;
}
}
realY++;
}
}
// lcd isnt that fast, dont draw too often
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
lcd.home();
for (int i = 0; i < (20*4); i++) {
lcd.write(characters[i]);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment