Date: 2/20/2016
The next step in Processing was to put the 3 animations together, with timers to run each for a certain amount of time and then automatically advance to the next. When I was assembling the code for the sequences, I also decided that a fourth sequence of a random dot pattern.
Below is the combined code. This also includes the first attempt to write the pixel display to the networked displays:
// Combined 5
//
// For LinkSprite V3 and AlfaZeta flip-dot display
// by Michael Shaub 2016
import processing.serial.*;
import processing.net.*;
//Server and client stuff
Server s;
Client c;
//switches
boolean drawPreview = true;
boolean useSerialPort = false;
// The serial port:
Serial myPort;
int frameDelay = 50;
//variables for flipDot
int rowCounter = 0;
int row1 = 0; //hold variable for row1
int row2 = 0; //hold variable for row2
int row3 = 0; //hold variable for row3
int row4 = 0; //hold variable for row4
int row5 = 0; //hold variable for row5
int row6 = 0; //hold variable for row6
int row7 = 0; //hold variable for row7
//int rowArray[ ] = {0,0,0,0,0,0,0};
int rowArray[ ] = {0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0,0};
boolean mirrorX = true; //flip Left & Right?
boolean mirrorY = false; //flip Top & Bottom?
int dotSize = 50; //diameter of the dots - for preview
PImage pix = createImage(28,7, RGB); //PImage to hold the actual size image
int pixLength = pix.width*pix.height; //total amount of pixels
//snow mode variables
boolean drawRow = false; //use to alternate drawing a row of dots or skipping
int snowFrameRepeat = 0;
int snowFrames = 3; // repeat each snow frame 3 times
int snowCounter = 0;
int totalSnowFrames = 100; // how many times should we draw snow before moving on to the next mode
//gradation mode variables
int gradFrameRepeat = 0;
int gradFrames = 2; // repeat each snow frame 3 times
int gradCounter = 0;
int totalGradFrames = 100; // how many times should we draw snow before moving on to the next mode
//random mode variables
int randCounter = 0;
int randLikelyhood = 100; // how unlikely is it that a dot will be added (larger number = less likely)
int randTwinkle = 600; // how unlikely is it that a dot will be added (larger number = less likely)
float a = 0.0;
float inc = TWO_PI/25.0;
PGraphics pixOrig; //PGraphics to hold the actual size image
PImage text1;
PImage text2;
PImage text3;
int scrollCounter = 0;
int textSelector = 1;
int modeSelector = 4; //1=Scrolling Text, 2=snow, 3=gradation, 4=random noise
//set the number of columns that are being calculated
int numColumns = 28; //switch back to 7?
void setup(){
size(1400,350);
//Server and client stuff
s = new Server(this, 12345); // Start a simple server on a port
// List all the available serial ports:
printArray(Serial.list());
// Open the port you are using at the rate you want:
if(useSerialPort) myPort = new Serial(this, Serial.list()[0], 57600);
ellipseMode(CORNER);
noStroke();
//frameRate(3);
text1 = loadImage("artatthemca.png"); //PImage for text image
text2 = loadImage("gensler.png"); //PImage for text image
text3 = loadImage("fiftyon.png"); //PImage for text image
pixOrig = createGraphics(28,7); //PGraphics to hold the actual size image
//preset the PImage
pix.loadPixels();
for(int i=0; i<pixLength; i++){
pix.pixels[i] = color(0); //set each pixel to black
}
pix.updatePixels();
}
void draw(){
background(35);
if(modeSelector > 4) {
modeSelector = 1; //reset any values that are too high
//println("mode reset to: " + modeSelector);
}
switch(modeSelector){
case(1):
textScroller(); //Draw Text
//println("I'm drawing text");
break;
case(2):
pixelSnow(); //Draw Snow
//println("I'm making snow");
break;
case(3):
//gradation
gradation();
//modeSelector = 1; //go back to the beginning
break;
case(4):
//gradation
randomSparkle();
//modeSelector = 1; //go back to the beginning
break;
}
if(modeSelector != 2 && modeSelector != 3){
//do dithering biz here
pix.loadPixels();
pixOrig.loadPixels();
for(int y=0; y<7; y++){
for(int x=0; x<28; x++){
color oldpixel = pixOrig.get(x, y);
color newpixel = findClosestColor( color(brightness(oldpixel) + random(-100,100)) ); //the wider the range of randomness the "softer" the result. Lower is harder edge
pix.pixels[x+y*pix.width] = newpixel; //copy colors from one image to the other
}
}
pix.updatePixels();
}
if(drawPreview) drawOnScreen(); //draw on screen
sendToClients(); //send out to clients
printToFlipDots(); //call the flipDot conversion
delay (frameDelay);
}
void drawOnScreen(){
//draw on screen
pix.loadPixels();
for(int j=0; j<7; j++){
for(int i=0; i<28; i++){
if(i < numColumns) { //for now, only do for the 1st 7 columns?
if(mirrorX){
rowArray[numColumns-1-i] = int( red(pix.pixels[i+j*pix.width])/255); //for now, only do for the 1st 7 columns
}else{
rowArray[i] = int( red(pix.pixels[i+j*pix.width])/255); //for now, only do for the 1st 7 columns
}
//println( rowArray[i] );
}
fill( pix.pixels[i+j*pix.width] ); //read pixel values, set fill color to that
ellipse(i*dotSize,j*dotSize,dotSize,dotSize);
}
rowCounter = j;
prepDotRow(j); //set the row through bitwise operations
}
}
void prepDotRow(int rowNum){
int tempRowCounter = rowNum+1;
if(mirrorY) tempRowCounter = 7-rowNum;
//bitshift values from array
for(int i=0; i<rowArray.length; i++){
int a = rowArray[i];
int b = a << i; //bitshift the value the number of positions equal to the digit
switch(tempRowCounter){
case 1:
row1 = row1 | b; //bitwise OR addition of the "b" value to the existing "row3" value
break;
case 2:
row2 = row2 | b; //bitwise OR addition of the "b" value to the existing "row3" value
break;
case 3:
row3 = row3 | b; //bitwise OR addition of the "b" value to the existing "row3" value
break;
case 4:
row4 = row4 | b; //bitwise OR addition of the "b" value to the existing "row3" value
break;
case 5:
row5 = row5 | b; //bitwise OR addition of the "b" value to the existing "row3" value
break;
case 6:
row6 = row6 | b; //bitwise OR addition of the "b" value to the existing "row3" value
break;
case 7:
row7 = row7 | b; //bitwise OR addition of the "b" value to the existing "row3" value
break;
}
}
}
void sendToClients(){
//send a single string that has comma deliminated values for each row and a line return at the end of the "frame"
s.write(row1 + "," + row2 + "," + row3 + "," + row4 + "," + row5 + "," + row6 + "," + row7 + "\n");
}
void printToFlipDots(){
int test_2[]= {0x80, 0x87, 0xFF, row1, row2, row3, row4, row5, row6, row7, 0x8F};
//int test_2[]= {0x80, 0x87, 0xFF, 0, rowCounter, scrollCounter, 0, 0, 0, 0, 0x8F};
for(int i=0; i<test_2.length; i++){
if(useSerialPort) myPort.write(test_2[i]);
//println(test_2[i]);
}
//reset row values for next frame
row1 = 0;
row2 = 0;
row3 = 0;
row4 = 0;
row5 = 0;
row6 = 0;
row7 = 0;
}
void randomSparkle() { //MODE 4
//Draw Randomly
int totalBright = 0;
pixOrig.beginDraw();
//pixOrig.background(0);
for(int j=0; j<7; j++){
for(int i=0; i<28; i++){
totalBright += pixOrig.get(i,j)/255 ; //set the fill color to a smooth gradation
if(random(randLikelyhood)<1){ //is the random number less than 1? A bigger variable = less likely
if(randCounter==0) pixOrig.set(i,j, 255 ); //add a white dot
if(randCounter==1) pixOrig.set(i,j, 0 ); //add a black dot
}
if(random(randTwinkle)<1){ //is the random number less than 1? A bigger variable = less likely
pixOrig.set(i,j, 255 ); //add a white dot
if(randCounter==1) totalBright++; //add
}
if(random(randTwinkle)<1){ //is the random number less than 1? A bigger variable = less likely
pixOrig.set(i,j, 0 ); //add a black dot
if(randCounter==0) totalBright--; //deduct
}
}
}
pixOrig.endDraw();
if(totalBright > 28*5.5 && randCounter == 0) randCounter = 1; //start dimming
if(totalBright < 28*1.5 && randCounter == 1) {
randCounter = 0; //go on to the next mode
modeSelector++;
}
}
void pixelSnow() { //MODE 2
//Draw Snow
if(snowFrameRepeat > snowFrames){
snowFrameRepeat=0;
pix.loadPixels();
//Copy each row of pixels down to the next row
for(int j=6; j>0; j--){ //step through every row but the top one, in reverse
int wind = round( random(-1,1) ); //set a value to blow the snow to the left, right, or none
//println(wind);
for(int i=0; i<28; i++){
if(!drawRow && j==6){ //only if this is the bottom row and on a frame when the snow isn't drawn on the top row
//skip drawing over the last row this frame
}else{
//draw this frame
int targetPix;
//test boundaries for values
if( (i+j*pix.width+wind) < 0){
targetPix = 0;
}else{
if( (i+j*pix.width+wind) > 7*pix.width-1){
targetPix = (i+j*pix.width);
}else{
targetPix = (i+j*pix.width+wind);
}
}
pix.pixels[targetPix] = pix.pixels[i+(j-1)*pix.width]; //read pixel values, set fill color to the row above
}
}
}
//Draw the first row of pixels with random values
int lastRand = 0;
for(int i=0; i<pix.width; i++){
int randValue = 0;
if(drawRow){
randValue = round(random(.6))*255; //randomly black or white, decimal sets how likely it'll be a white dot
if(i>0 && lastRand==255){
randValue = 0; //never have 2 white dots in a row
}
}
pix.pixels[i] = color(randValue); //set each pixel to black or white
lastRand = randValue;
}
drawRow = !drawRow; //toggle the variable
pix.updatePixels();
snowCounter++; //count the number of snow frames so far
}
snowFrameRepeat++;
if(snowCounter == totalSnowFrames) {
modeSelector = 3; //move on to the next mode
//println("mode: " + modeSelector);
snowCounter = 0; //reset the counter
}
}
void gradation(){ //MODE 3
if(gradFrameRepeat > gradFrames){
gradFrameRepeat=0;
//Draw Gradation
pixOrig.beginDraw();
pixOrig.background(0);
for(int j=0; j<7; j++){
for(int i=0; i<28; i++){
//pixOrig.pixels[i+j*pix.width] = int(128+sin(a)*128.0); //set the fill color to a smooth gradation
pixOrig.set(i,j, int(128+sin(a)*128.0) ); //set the fill color to a smooth gradation
a = a + inc;
}
}
pixOrig.endDraw();
//do dithering biz here
pix.loadPixels();
pixOrig.loadPixels();
for(int y=0; y<7; y++){
for(int x=0; x<28; x++){
color oldpixel = pixOrig.get(x, y);
color newpixel = findClosestColor( color(brightness(oldpixel) + random(-100,100)) ); //the wider the range of randomness the "softer" the result. Lower is harder edge
pix.pixels[x+y*pix.width] = newpixel; //copy colors from one image to the other
}
}
pix.updatePixels();
if(gradCounter == totalGradFrames) {
modeSelector = 1; //move on to the next mode
//println("mode: " + modeSelector);
gradCounter = 0; //reset the counter
}else{
gradCounter++;
}
}
gradFrameRepeat++;
}
void textScroller(){ //MODE 1
/*
if(textSelector > 3) {
textSelector = 1;
//scrollCounter = 0;
modeSelector++;
println("mode: " + modeSelector);
}*/
//println("drawing text: " + textSelector);
//println("scroll counter: " + scrollCounter);
//Draw Text
pixOrig.beginDraw();
pixOrig.background(0);
switch(textSelector){
case(1):
pixOrig.image(text1, pixOrig.width-scrollCounter, 0); //draw text starting offscreen to the right
break;
case(2):
pixOrig.image(text2, pixOrig.width-scrollCounter, 0); //draw text starting offscreen to the right
break;
case(3):
pixOrig.image(text3, pixOrig.width-scrollCounter, 0); //draw text starting offscreen to the right
break;
}
pixOrig.endDraw();
switch(textSelector){
case(1):
if(scrollCounter > text1.width+pixOrig.width){
scrollCounter = 0;
textSelector = 2;
modeSelector = 2;
//println("mode: " + modeSelector);
}
break;
case(2):
if(scrollCounter > text2.width+pixOrig.width){
scrollCounter = 0;
textSelector = 3;
modeSelector = 2;
//println("mode: " + modeSelector);
}
break;
case(3):
if(scrollCounter > text3.width+pixOrig.width){
scrollCounter = 0;
textSelector = 1;
modeSelector = 2;
//println("mode: " + modeSelector);
}
break;
}
scrollCounter++;
}
void keyPressed(){
if(key == 'x') mirrorX = ! mirrorX;
if(key == 'y') mirrorY = ! mirrorY;
}
color findClosestColor(color c) {
color r;
// Treshold function
if (brightness(c) < 128) {
r = color(0);
}
else {
r = color(255);
}
return r;
}
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.