Created
September 18, 2019 02:43
-
-
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'
This file contains hidden or 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
// 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