├── Htmlpages.zip ├── README.md ├── convert.java ├── example.ino ├── images.h ├── ledTable.h ├── ledtable.ino ├── library.json ├── library.properties ├── paint.h ├── paint.html ├── paint.txt ├── tetris.h ├── tetris.html └── yves_image.h /Htmlpages.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hpwit/ledtable/5bb932e59f737a24e108cb2714cf2ef06156aa8f/Htmlpages.zip -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ledtable 2 | Program for ledtable with esp8266 3 | -------------------------------------------------------------------------------- /convert.java: -------------------------------------------------------------------------------- 1 | import java.io.*; 2 | 3 | 4 | public class Main { 5 | 6 | public static void main(String[] args) { 7 | File file = new File("/Users/yvesbazin/Downloads/add.bmp"); 8 | byte[] fileData = new byte[(int) file.length()]; 9 | try { 10 | DataInputStream dis = new DataInputStream(new FileInputStream(file)); 11 | dis.readFully(fileData); 12 | dis.close(); 13 | // System.out.println("here"); 14 | for (int i=0;i 19 | 20 | #include 21 | extern "C" { 22 | #include "user_interface.h" 23 | } 24 | // How many leds in your strip? 25 | 26 | 27 | 28 | 29 | #include 30 | #include 31 | #include 32 | //#include 33 | //#include 34 | 35 | #include 36 | //#include 37 | 38 | 39 | 40 | // For led chips like Neopixels, which have a data line, ground, and power, you just 41 | // need to define DATA_PIN. For led chipsets that are SPI based (four wires - data, clock, 42 | // ground, and power), like the LPD8806 define both DATA_PIN and CLOCK_PIN 43 | 44 | #define DATA_PIN 3 45 | #define CLOCK_PIN 13 //needed if we go for ws2801 46 | 47 | 48 | #define DATA_PIN D7 // for Huzzah: Pins w/o special function: #4, #5, #12, #13, #14; // #16 does not work :( 49 | #define LED_TYPE WS2812 50 | #define COLOR_ORDER GRB 51 | 52 | //Define table orientation this is where the pixel 0 is 53 | #define DOWN_RIGHT 0 //natural mode no transpostion to be made 54 | #define DOWN_LEFT 1 //We turn 90° clock wise 55 | #define UP_LEFT 2 56 | #define UP_RIGHT 3 57 | #define DOWN_RIGHT_INV 4 //natural mode no transpostion to be made 58 | #define DOWN_LEFT_INV 5 //We turn 90° clock wise 59 | #define UP_LEFT_INV 6 60 | #define UP_RIGHT_INV 7 61 | #define DEFAULT_BRIGHTNESS 16 62 | 63 | 64 | byte font1[][7]= 65 | { 66 | 67 | //32->47 68 | {B00000, B00000, B00000, B00000, B00000, B00000, B00000 },{B01000, B01000, B01000, B01000, B01000, B00000, B01000 }, {B01010, B01010, B01010, B00000, B00000, B00000, B00000 }, {B01010, B01010, B11111, B01010, B11111, B01010, B01010 }, {B00100, B01111, B10100, B01110, B00101, B11110, B00100 }, {B11000, B11001, B00010, B00100, B01000, B10011, B00011 }, {B01000, B10100, B10100, B01000, B10101, B10010, B01101 }, {B01100, B00100, B01000, B00000, B00000, B00000, B00000 }, {B00010, B00100, B01000, B01000, B01000, B00100, B00010 }, {B01000, B00100, B00010, B00010, B00010, B00100, B01000 }, {B10101, B01110, B00100, B01110, B10101, B00000, B00000 }, {B00100, B00100, B00100, B11111, B00100, B00100, B00100 }, {B00000, B00000, B00000, B00000, B11000, B01000, B10000 }, {B00000, B00000, B00000, B11100, B00000, B00000, B00000 }, {B00000, B00000, B00000, B00000, B00000, B01100, B01100 }, {B00000, B00001, B00010, B00100, B01000, B10000, B00000 }, 69 | 70 | //48->57 71 | {B01110, B10001, B10011, B10101, B11001, B10001, B01110 }, {B00100, B01100, B00100, B00100, B00100, B00100, B01110 }, {B01110, B10001, B00001, B00010, B00100, B01000, B11111 }, {B11111, B00010, B00100, B00010, B00001, B10001, B01110 }, {B00010, B00110, B01010, B10010, B11111, B00010, B00010 }, {B11111, B10000, B11110, B00001, B00001, B10001, B01110 }, {B00110, B01000, B10000, B11110, B10001, B10001, B01110 }, {B11111, B00001, B00010, B00100, B01000, B10000, B10000 }, {B01110, B10001, B10001, B01110, B10001, B10001, B01110 }, {B01110, B10001, B10001, B01111, B00001, B00010, B01100 }, 72 | 73 | //58->64 74 | {B00000, B01100, B01100, B00000, B01100, B01100, B00000 }, {B00000, B01100, B01100, B00000, B01100, B00100, B01000 }, {B00010, B00100, B01000, B10000, B01000, B00100, B00010 }, {B00000, B00000, B11111, B00000, B11111, B00000, B00000 }, {B10000, B01000, B00100, B00010, B00100, B01000, B10000 }, {B01110, B10001, B00001, B00010, B00100, B00000, B00100 }, {B01110, B10001, B10011, B10100, B10101, B10001, B01110 }, 75 | 76 | //65->90 77 | {B01110, B10001, B10001, B11111, B10001, B10001, B10001 }, {B11110, B10001, B10001, B11110, B10001, B10001, B11110 }, {B01110, B10001, B10000, B10000, B10000, B10001, B01110 }, {B11110, B10001, B10001, B10001, B10001, B10001, B11110 }, {B11111, B10000, B10000, B11110, B10000, B10000, B11111 }, {B11111, B10000, B10000, B11110, B10000, B10000, B10000 }, {B01110, B10001, B10000, B10111, B10001, B10001, B01110 }, {B10001, B10001, B10001, B11111, B10001, B10001, B10001 }, {B01110, B00100, B00100, B00100, B00100, B00100, B01110 }, {B00111, B00010, B00010, B00010, B00010, B10010, B01100 }, {B10001, B10010, B10100, B11000, B10100, B10010, B10001 }, {B10000, B10000, B10000, B10000, B10000, B10000, B11111 }, {B10001, B11011, B10101, B10101, B10001, B10001, B10001 }, {B10001, B10001, B11001, B10101, B10011, B10001, B10001 }, {B01110, B10001, B10001, B10001, B10001, B10001, B01110 }, {B11110, B10001, B10001, B11110, B10000, B10000, B10000 }, {B01110, B10001, B10001, B10001, B10101, B10010, B01101 }, {B11110, B10001, B10001, B11110, B10100, B10010, B10001 }, {B01111, B10000, B10000, B01110, B00001, B00001, B11110 }, {B11111, B00100, B00100, B00100, B00100, B00100, B00100 }, {B10001, B10001, B10001, B10001, B10001, B10001, B01110 }, {B10001, B10001, B10001, B10001, B10001, B01010, B00100 }, {B10001, B10001, B10001, B10001, B10101, B10101, B01010 }, {B10001, B10001, B01010, B00100, B01010, B10001, B10001 }, {B10001, B10001, B10001, B01010, B00100, B00100, B00100 }, {B11111, B00001, B00010, B00100, B01000, B10000, B11111 }, 78 | 79 | //91->96 80 | {B01110, B01000, B01000, B01000, B01000, B01000, B01110 }, {B10001, B01010, B11111, B00100, B11111, B00100, B00100 }, {B01110, B00010, B00010, B00010, B00010, B00010, B01110 }, {B00100, B01010, B10001, B00000, B00000, B00000, B00000 }, {B00000, B00000, B00000, B00000, B00000, B00000, B11111 }, {B01000, B00100, B00010, B00000, B00000, B00000, B00000 }, 81 | 82 | //97->122 83 | {B00000, B00000, B01110, B00001, B01111, B10001, B01111 }, {B10000, B10000, B10110, B11001, B10001, B10001, B11110 }, {B00000, B00000, B01110, B10000, B10000, B10001, B01110 }, {B00001, B00001, B01101, B10011, B10001, B10001, B01111 }, {B00000, B00000, B01110, B10001, B11111, B10000, B01110 }, {B00110, B01001, B01000, B11100, B01000, B01000, B01000 }, {B00000, B01111, B10001, B10001, B01111, B00001, B01110 }, {B10000, B10000, B10110, B11001, B10001, B10001, B10001 }, {B00100, B00000, B01100, B00100, B00100, B00100, B01110 }, {B00010, B00000, B00110, B00010, B00010, B10010, B01100 }, {B10000, B10000, B10010, B10100, B11000, B10100, B10010 }, {B01100, B00100, B00100, B00100, B00100, B00100, B01110 }, {B00000, B00000, B11010, B10101, B10101, B10001, B10001 }, {B00000, B00000, B10110, B11001, B10001, B10001, B10001 }, {B00000, B00000, B01110, B10001, B10001, B10001, B01110 }, {B00000, B00000, B11110, B10001, B11110, B10000, B10000 }, {B00000, B00000, B01110, B10001, B01111, B00001, B00001 }, {B00000, B00000, B10110, B11001, B10000, B10000, B10000 }, {B00000, B00000, B01110, B10000, B01110, B00001, B11110 }, {B01000, B01000, B11100, B01000, B01000, B01001, B00110 }, {B00000, B00000, B10001, B10001, B10001, B10011, B01101 }, {B00000, B00000, B10001, B10001, B10001, B01010, B00100 }, {B00000, B00000, B10001, B10001, B10001, B10101, B01010 }, {B00000, B00000, B10001, B01010, B00100, B01010, B10001 }, {B00000, B00000, B10001, B10001, B01111, B00001, B01110 }, {B00000, B00000, B11111, B00010, B00100, B01000, B11111 }, 84 | 85 | 86 | }; 87 | 88 | const uint8_t gamma8[] = { 89 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 91 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 92 | 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 93 | 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 94 | 10, 10, 11, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16, 95 | 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 24, 24, 25, 96 | 25, 26, 27, 27, 28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 35, 36, 97 | 37, 38, 39, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 50, 98 | 51, 52, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 66, 67, 68, 99 | 69, 70, 72, 73, 74, 75, 77, 78, 79, 81, 82, 83, 85, 86, 87, 89, 100 | 90, 92, 93, 95, 96, 98, 99,101,102,104,105,107,109,110,112,114, 101 | 115,117,119,120,122,124,126,127,129,131,133,135,137,138,140,142, 102 | 144,146,148,150,152,154,156,158,160,162,164,167,169,171,173,175, 103 | 177,180,182,184,186,189,191,193,196,198,200,203,205,208,210,213, 104 | 215,218,220,223,225,228,231,233,236,239,241,244,247,249,252,255 }; 105 | 106 | CRGB lettrefont1[35]; 107 | 108 | CRGB *leds;//leds[420]; 109 | CRGB *Tpic; 110 | 111 | CRGB solidColor = CRGB(10, 10, 10); 112 | CRGB bgColor = CRGB(10, 10, 10); 113 | CRGB Color = CRGB :: Blue; 114 | CRGB Color2 = CRGB :: Green; 115 | bool isTable=false; 116 | int tableOrientation=DOWN_RIGHT; //we put the first pixel down and right 117 | 118 | int LED_WIDTH=30; 119 | int LED_HEIGHT=14; 120 | int NUM_LEDS; 121 | 122 | ESP8266WebServer server(80); 123 | 124 | 125 | 126 | 127 | //CREATTION DES LEDS (on prend la longueur des strips w et le nombre de strip h) 128 | bool initTable(int w,int h) 129 | { 130 | LED_WIDTH=w; 131 | LED_HEIGHT=h; 132 | NUM_LEDS=w*h; 133 | leds =(CRGB*)os_malloc(NUM_LEDS*sizeof(CRGB)) ; 134 | Tpic =(CRGB*)os_malloc(NUM_LEDS*sizeof(CRGB)) ; 135 | if(!leds or !Tpic) 136 | { 137 | Serial.println("Unable to create the screen"); 138 | isTable=false; 139 | return false; 140 | } 141 | Serial.println("Table créée"); 142 | isTable=true; 143 | FastLED.addLeds(leds, NUM_LEDS); 144 | FastLED.setBrightness(DEFAULT_BRIGHTNESS); 145 | return true; 146 | } 147 | 148 | 149 | 150 | void putOrientation(CRGB *pic,int h,int w,int x0,int y0) 151 | { 152 | //CRGB * Tpic = (CRGB*)calloc(h*w,sizeof(CRGB)); 153 | if(!Tpic) 154 | { 155 | Serial.println("pas possible"); 156 | return ;//NULL; 157 | } 158 | switch(tableOrientation){ 159 | 160 | case DOWN_RIGHT: //on ne fait rien 161 | for(int y=0;y=0 && y+y0>=0 && x+x0=0 && y+y0>=0 && LED_HEIGHT-1-x-x0=0 && LED_WIDTH-1-(y+y0)>=0 && (x+x0)=0 && LED_WIDTH*(LED_HEIGHT-1-(y+y0))>=0 && (LED_HEIGHT-1-(y+y0))=0 && y+y0>=0 && LED_WIDTH-1-x-x0=0 && y+y0>=0 && x+x0=0 && (y+y0)>=0 && (x+x0)=0 && LED_WIDTH*(LED_HEIGHT-1-(y+y0))>=0 && (LED_HEIGHT-1-(y+y0))= 0) { 274 | if (y % 2 == 0) 275 | { 276 | if (x0 < 0) 277 | { 278 | int nh = wmin + x0; 279 | if (nh > 0) 280 | memcpy(&leds[LED_WIDTH * y], &Tpic[(y - y0) *wmin - x0], nh * sizeof(CRGB)); 281 | } 282 | else 283 | memcpy(&leds[LED_WIDTH * y + x0], &Tpic[(y - y0)*wmin], wmin * sizeof(CRGB)); 284 | } 285 | else 286 | { 287 | for (int x = x0; x < wmin + x0; x++) 288 | { 289 | if (x >= 0) 290 | leds[2 * LED_WIDTH * ((int)floor(y / 2) + 1) - 1 - x] = Tpic[wmin * (y - y0) + x - x0 ]; 291 | } 292 | } 293 | } 294 | } 295 | 296 | } 297 | } 298 | 299 | 300 | 301 | void displayBitmap(unsigned char *pic,int x0,int y0,int h,int w) 302 | { 303 | //frame size 304 | int max_wide=0; 305 | int wide=w+x0; 306 | int offsety; 307 | int offsetx; 308 | int newx=0; 309 | int newy=0; 310 | if(wide<=0) 311 | return; // l'image ne peut etre affichée 312 | if(tableOrientation%2==0) 313 | max_wide=LED_WIDTH; 314 | else 315 | max_wide=LED_HEIGHT; 316 | 317 | if (x0>=max_wide) //on est en dehors du cadre 318 | return; 319 | if(x0>=0) 320 | { 321 | newx=x0; 322 | offsetx=0; 323 | if(w+x0=max_height) //on est en dehors du cadre 351 | return; 352 | if(y0>=0) 353 | { 354 | newy=y0; 355 | offsety=0; 356 | if(h+y0 maxx) ? maxx : w; 424 | r=gamma8[(int)pic[3*(y*w+x)]];//<0 ) ? (256+(int)pic[3*(y*w+x)]):(int)pic[3*(y*w+x)]; 425 | // Serial.println("r"); 426 | g= gamma8[(int)pic[3*(y*w+x)+1]];//<0 ) ? (256+(int)pic[3*(y*w+x)+1]):(int)pic[3*(y*w+x)+1]; 427 | b= gamma8[(int)pic[3*(y*w+x)+2]];//<0 ) ? (256+(int)pic[3*(y*w+x)+2]):(int)pic[3*(y*w+x)+2]; 428 | // Serial.print(r);Serial.print(";");Serial.print(g);Serial.print(";");Serial.print(b);Serial.println(""); 429 | // bitmapRGB[x+y*w]=CRGB(pic[3*(y*w+x)+2],pic[3*(y*w+x)+1],pic[3*(y*w+x)]); 430 | //Serial.println("ecrire"); 431 | bitmapRGB[x+y*w]=CRGB(r,g,b); 432 | } 433 | } 434 | displaypic(bitmapRGB,x0,y0,h,w); 435 | os_free(bitmapRGB); 436 | 437 | } 438 | 439 | void displayBitmapFromProgmem(unsigned char *pic,int x0,int y0,int h,int w ) 440 | { 441 | 442 | int max_wide=0; 443 | int wide=w+x0; 444 | int offsety; 445 | int offsetx; 446 | int newx=0; 447 | int newy=0; 448 | if(wide<0) 449 | return; // l'image ne peut etre affichée 450 | if(tableOrientation%2==0) 451 | max_wide=LED_WIDTH; 452 | else 453 | max_wide=LED_HEIGHT; 454 | 455 | if (x0==max_wide) //on est en dehors du cadre 456 | return; 457 | if(x0>=0) 458 | { 459 | newx=x0; 460 | offsetx=0; 461 | if(w+x0=0) 491 | { 492 | newy=y0; 493 | offsety=0; 494 | if(h+y0 0 ) 552 | { 553 | lettrefont1[(x-x0)+(y-y0)*5]=CRGB(Color); 554 | } 555 | else 556 | { 557 | lettrefont1[(x-x0)+(y-y0)*5]=CRGB(bgColor); 558 | } 559 | } 560 | } 561 | 562 | displaypic(lettrefont1,x0,y0,7,5); 563 | 564 | } 565 | 566 | 567 | 568 | #endif /* ledTable_h */ 569 | 570 | -------------------------------------------------------------------------------- /ledtable.ino: -------------------------------------------------------------------------------- 1 | #include "ledTable.h" 2 | #include "tetris.h" 3 | 4 | int k = 0; 5 | 6 | void setup() { 7 | // system_update_cpu_freq(SYS_CPU_160MHZ); 8 | Serial.begin(115200); 9 | delay(100); 10 | Serial.setDebugOutput(true); 11 | 12 | Serial.println("Setup"); 13 | 14 | if (initTable(30, 20)) //size of your led grid (wide*height) 15 | { 16 | FastLED.setBrightness(32); 17 | fill(bgColor); 18 | Serial.println("Fill"); 19 | 20 | FastLED.show(); 21 | 22 | tableOrientation = DOWN_RIGHT_INV; //used if i want ta change table orientation ) 23 | 24 | } 25 | initTetris(10, 20); 26 | initTetrisScoketControl(); 27 | } 28 | 29 | void loop() { 30 | tetrisWebSocket.loop(); 31 | } 32 | 33 | -------------------------------------------------------------------------------- /library.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "LEDTable", 3 | "description": "To manage the lad table", 4 | "keywords": "led,noise,rgb,math,fast", 5 | "authors": [ 6 | { 7 | "name": "Yves BAZIN", 8 | "url": "", 9 | "maintainer": true 10 | } 11 | ], 12 | "repository": { 13 | 14 | }, 15 | "version": "1.0", 16 | "license": "MIT", 17 | , 18 | "frameworks": "arduino", 19 | "platforms": "*", 20 | "examples": [ 21 | "examples/*.ino" 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=LEDtable 2 | version=0.9 3 | author=Yves BAZIN 4 | maintainer=Yves BAIZN 5 | sentence=Function for ledtable. 6 | paragraph=Function for ledtable. 7 | category=Display 8 | url= 9 | architectures=* 10 | -------------------------------------------------------------------------------- /paint.h: -------------------------------------------------------------------------------- 1 | // 2 | // paint.h 3 | // 4 | // 5 | // Created by Yves BAZIN on 14/12/17. 6 | // 7 | 8 | #ifndef paint_h 9 | #define paint_h 10 | 11 | 12 | void initPaintScoketControl(); 13 | void paintWebSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length); 14 | void initPaint(); 15 | void newPaint(); 16 | void executePaintSocketControl(); 17 | 18 | int paintWebSocketPort=82; 19 | bool paintInitiated=false; 20 | bool inPaint=false; 21 | 22 | WebSocketsServer paintWebSocket = WebSocketsServer(paintWebSocketPort); 23 | 24 | void initPaintScoketControl() 25 | { 26 | paintWebSocket.begin(); 27 | paintWebSocket.onEvent(paintWebSocketEvent); 28 | } 29 | 30 | void executePaintSocketControl() 31 | { 32 | paintWebSocket.loop(); 33 | 34 | } 35 | 36 | 37 | 38 | 39 | bool initPaint() 40 | { 41 | if(isTable) 42 | { 43 | server.serveStatic("/paint.html", SPIFFS, "/paint.html"); //on ajoute le lien vers tetris 44 | initPaintScoketControl(); 45 | paintInitiated=true; 46 | Serial.println("patint cree"); 47 | return true; 48 | 49 | } 50 | else{ 51 | Serial.println("No table existing create the table first"); 52 | paintInitiated=false; 53 | return false; 54 | } 55 | } 56 | 57 | 58 | 59 | 60 | void newPaint() 61 | { 62 | 63 | Serial.println("voici paint");// clears the red display matrix 64 | if(!paintInitiated) 65 | { 66 | Serial.println("on cree la base fait"); 67 | initPaint(); 68 | 69 | } 70 | inPaint=true; 71 | fill(CRGB(0,0,0)); 72 | FastLED.show(); 73 | 74 | } 75 | 76 | 77 | void paintWebSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length) 78 | { 79 | // noInterrupts(); 80 | // Serial.printf("webSocketEvent(%d, %d, ...)\r\n", num, type); 81 | switch(type) { 82 | case WStype_DISCONNECTED: 83 | Serial.printf("[%u] Disconnected!\r\n", num); 84 | break; 85 | case WStype_CONNECTED: 86 | { 87 | IPAddress ip = paintWebSocket.remoteIP(num); 88 | // Serial.printf("[%u] Connected from %d.%d.%d.%d url: %s\r\n", num, ip[0], ip[1], ip[2], ip[3], payload); 89 | // Send the current LED status 90 | } 91 | break; 92 | case WStype_TEXT: 93 | Serial.printf("[%u] get Text: %s\r\n", num, payload); 94 | /* if (strcmp("up", (const char *)payload) == 0) { 95 | //writeLED(true); 96 | Serial.println("on go up"); 97 | YO = (YO + 1) % LED_HEIGHT; 98 | fill_solid(leds, NUM_LEDS, bgColor); 99 | } 100 | else if (strcmp("down", (const char *)payload) == 0) { 101 | Serial.println("on go down"); 102 | YO = (YO -1) % LED_HEIGHT; 103 | fill_solid(leds, NUM_LEDS, bgColor); 104 | } 105 | */ 106 | 107 | char str[20]; 108 | int x,y,r,g,b; 109 | sscanf ((const char *)payload,"%s %d %d %d %d %d",str,&x,&y,&r,&b,&g); 110 | if (strcmp("paint", (const char *)str) == 0) { 111 | PixelOn(x,y,CRGB(r,g,b)); 112 | FastLED.show(); 113 | // Serial.println("on va a droite"); 114 | 115 | } 116 | 117 | 118 | if (strcmp("new", (const char *)payload) == 0) { 119 | fill(CRGB(0,0,0)); 120 | 121 | newPaint(); 122 | } 123 | if (strcmp("stop", (const char *)payload) == 0) { 124 | fill(bgColor); 125 | inPaint=false; 126 | 127 | 128 | } 129 | 130 | 131 | 132 | else { 133 | // Serial.println("Unknown command"); 134 | } 135 | // send data to all connected clients 136 | //webSocket.broadcastTXT(payload, length); 137 | break; 138 | case WStype_BIN: 139 | Serial.printf("[%u] get binary length: %u\r\n", num, length); 140 | hexdump(payload, length); 141 | 142 | // echo data back to browser 143 | // webSocket.sendBIN(num, payload, length); 144 | break; 145 | default: 146 | Serial.printf("Invalid WStype [%d]\r\n", type); 147 | break; 148 | } 149 | 150 | // interrupts(); 151 | } 152 | 153 | #endif /* paint_h */ 154 | -------------------------------------------------------------------------------- /paint.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | PAINT 5 | 6 | 7 | 8 | 9 | 10 | 11 | 24 | 36 | 37 | 38 |

PAINT

39 | 40 | 41 | 50 |
42 | 43 | 44 | 45 |
46 |
47 |
48 |
49 |
51 |
52 |
53 |
54 | 55 | 56 | main menu 57 | 162 | 163 | 164 | -------------------------------------------------------------------------------- /paint.txt: -------------------------------------------------------------------------------- 1 | Hello 2 | here is how to do it 3 | Create a sketch via arduino 4 | unzip the htmlpages.zip in the directorty Arduino/you_sketch_name/data 5 | you sketch should look like this 6 | download paint.h and put it in you sketch directory 7 | 8 | 9 | edit paint.h 10 | line 63 11 | replace 12 | fill(CRGB(0,0,0)); 13 | by 14 | 15 | fill_solid(leds, NUM_LEDS, CRGB(0,0,0)); //or whateever color you prefer 16 | 17 | 18 | you sketch.ino should look like this 19 | 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | 29 | #define FASTLED_ESP8266_RAW_PIN_ORDER 30 | #define FASTLED_ESP8266_NODEMCU_PIN_ORDER 31 | #define FASTLED_ESP8266_D1_PIN_ORDER 32 | #define FASTLED_ALLOW_INTERRUPTS 0 33 | #include "FastLED.h" 34 | FASTLED_USING_NAMESPACE 35 | 36 | #include "paint.h" 37 | 38 | #define LED_WIDTH 128 39 | #define LED_HEIGHT 32 40 | #define DATA_PIN 3 //or whatever you like 41 | 42 | 43 | bool isTable=true //this is on muy internal variable for the entire library when I create the ledstrip 44 | int NUM_LEDS=LED_WIDTH*LED_HEIGHT; 45 | 46 | CRGB leds[LED_WIDTH*LED_HEIGHT]; 47 | 48 | 49 | 50 | void PixelOn(byte x,byte y,CRGB Color) 51 | { 52 | int offset=0; 53 | if (x<0 or y<0 or x>=LED_WIDTH or y>=LED_HEIGHT) 54 | return ; 55 | if(y%2==0) 56 | offset=x+y*LED_WIDTH; 57 | else 58 | offset=2 * LED_WIDTH * ((int)floor(y / 2) + 1) - 1 - x; 59 | 60 | leds[offset]=Color; 61 | 62 | } // this is for ma table 'cause i am going snake up to you to use another one depending on how your strips are wired 63 | 64 | 65 | void setup() 66 | { 67 | //all you code to initiate the web server and connect to the wifi 68 | //and activate the SPIFF 69 | 70 | //something like this 71 | 72 | WiFi.mode(WIFI_STA); 73 | Serial.printf("Connecting to %s\n", "SSID"); 74 | Serial.printf("Connecting "); 75 | WiFi.begin("SSID", "password"); 76 | while (WiFi.status() != WL_CONNECTED) { 77 | delay(500); 78 | Serial.print("."); 79 | } 80 | 81 | Serial.print("Connected! Open http://"); 82 | Serial.print(WiFi.localIP()); 83 | Serial.println(" in your browser"); 84 | if(mdns.begin("ledtable",WiFi.localIP())) //i use mdns to avoid to tape the ip address i can look at the page using http://ledtable.local 85 | Serial.println("MDNS has started"); 86 | SPIFFS.begin(); 87 | 88 | Dir dir = SPIFFS.openDir("/"); 89 | while (dir.next()) { 90 | String fileName = dir.fileName(); 91 | size_t fileSize = dir.fileSize(); 92 | Serial.printf("FS File: %s, size: %s\n", fileName.c_str(), String(fileSize).c_str()); 93 | } 94 | MDNS.addService("http","tcp",80); 95 | MDNS.addService("ws", "tcp", 82); 96 | 97 | 98 | FastLED.addLeds(leds, NUM_LEDS ) ; 99 | 100 | initPaint() //this create the websockets on port 82 and add the static page 101 | server.serveStatic("/", SPIFFS, "/index.html"); 102 | 103 | server.serveStatic("/farbtastic.js", SPIFFS, "/farbtastic.js"); 104 | 105 | server.serveStatic("/farbtastic.css", SPIFFS, "/farbtastic.css"); 106 | 107 | server.serveStatic("/marker.png", SPIFFS, "/marker.png"); 108 | 109 | server.serveStatic("/mask.png", SPIFFS, "/mask.png"); 110 | 111 | server.serveStatic("/wheel.png", SPIFFS, "/wheel.png"); 112 | 113 | 114 | // the code above could be added to the initPaint() 115 | 116 | server.begin(); 117 | } 118 | 119 | void loop() 120 | { 121 | 122 | server.handleClient(); 123 | executePaintSocketControl(); 124 | 125 | } 126 | 127 | 128 | 129 | 130 | 131 | 132 | now in the file paint.html 133 | line 94 134 | creategrid(30,20); //Here you decice the size of the grid for you 128*32 135 | 136 | the size of a square is defined in image.css 137 | .case { 138 | border: 2px solid black; 139 | /*border-color:rgba(215,5,9,1.00);*/ 140 | width: 10px; 141 | height: 10px; 142 | } 143 | // just change the width and height 144 | 145 | 146 | when you launch go to 147 | http://ledtable.local/paint.html 148 | 149 | and click "new party" 150 | 151 | to erase the board clieck again new party 152 | 153 | 154 | please ask question of needed 155 | rgds 156 | YVes 157 | -------------------------------------------------------------------------------- /tetris.h: -------------------------------------------------------------------------------- 1 | // 2 | // tetris.h 3 | // 4 | // 5 | // Created by Yves BAZIN on 30/11/17. 6 | // 7 | 8 | #ifndef tetris_h 9 | #define tetris_h 10 | 11 | 12 | 13 | 14 | 15 | #define DISP_RIGHT 0 16 | #define DISP_UP 1 17 | 18 | int displayNextPiecePos=DISP_UP; 19 | 20 | int hauteur=25; 21 | int largeur=18; 22 | int score=0; 23 | 24 | 25 | CRGB *backgroundBlocks; //8 x 16 display + 4 x 8 blocks above for blocks to spawn in 26 | CRGB *displayScreen; 27 | CRGB nextBlockImage[12]; //je prends les deux premieres lignes du block 28 | //CRGB TdisplayScreen [160]; 29 | 30 | int TETRIS_HEIGHT=25; 31 | int TETRIS_WIDTH=12; 32 | int TETRIS_X=1; 33 | int TETRIS_Y=1; 34 | int blockType ; //7 different block types 35 | int nextBlockType; //to Display the next piece 36 | int state; //4 possible rotation states 37 | bool isInitiated=false; 38 | bool isDisplayNextPiece=false; 39 | bool isDisplayScore=false; 40 | int tetrisWebSocketPort=81; 41 | 42 | const int activeBlocks [28][4][4] = { 43 | {{0,0,1,0}, // blockType + 7(state) 44 | {0,1,1,0}, // 0 = 0 + 7(0) 45 | {0,1,0,0}, 46 | {0,0,0,0}} , 47 | 48 | {{0,2,0,0}, // 1 = 1 + 7(0) 49 | {0,2,2,0}, 50 | {0,2,0,0}, 51 | {0,0,0,0}} , 52 | 53 | {{0,3,0,0}, // 2 = 2 + 7(0) 54 | {0,3,3,0}, 55 | {0,0,3,0}, 56 | {0,0,0,0}} , 57 | 58 | {{0,0,0,0}, // 3 = 3 + 7(0) 59 | {0,4,4,0}, 60 | {0,4,4,0}, 61 | {0,0,0,0}} , 62 | 63 | {{0,5,0,0}, // 4 = 4 + 7(0) 64 | {0,5,0,0}, 65 | {0,5,5,0}, 66 | {0,0,0,0}} , 67 | 68 | {{0,6,6,0}, // 5 = 5 + 7(0) 69 | {0,6,0,0}, 70 | {0,6,0,0}, 71 | {0,0,0,0}} , 72 | 73 | {{0,0,7,0}, // 6 = 6 + 7(0) 74 | {0,0,7,0}, 75 | {0,0,7,0}, 76 | {0,0,7,0}} , 77 | 78 | {{0,0,0,0}, // 7 = 0 + 7(1) 79 | {1,1,0,0}, 80 | {0,1,1,0}, 81 | {0,0,0,0}} , 82 | 83 | {{0,0,0,0}, // 8 = 1 + 7(1) 84 | {2,2,2,0}, 85 | {0,2,0,0}, 86 | {0,0,0,0}} , 87 | 88 | {{0,0,0,0}, // 9 = 2 + 7(1) 89 | {0,3,3,0}, 90 | {3,3,0,0}, 91 | {0,0,0,0}} , 92 | 93 | {{0,0,0,0}, // 10 = 3 + 7(1) 94 | {0,4,4,0}, 95 | {0,4,4,0}, 96 | {0,0,0,0}} , 97 | 98 | {{0,0,0,0}, // 11 = 4 + 7(1) 99 | {5,5,5,0}, 100 | {5,0,0,0}, 101 | {0,0,0,0}} , 102 | 103 | {{0,0,0,0}, // 12 = 5 + 7(1) 104 | {6,6,6,0}, 105 | {0,0,6,0}, 106 | {0,0,0,0}} , 107 | 108 | {{0,0,0,0}, // 13 = 6 + 7(1) 109 | {0,0,0,0}, 110 | {7,7,7,7}, 111 | {0,0,0,0}} , 112 | 113 | {{0,1,0,0}, // 14 = 0 + 7(2) 114 | {1,1,0,0}, 115 | {1,0,0,0}, 116 | {0,0,0,0}} , 117 | 118 | {{0,2,0,0}, // 15 = 1 + 7(2) 119 | {2,2,0,0}, 120 | {0,2,0,0}, 121 | {0,0,0,0}} , 122 | 123 | {{3,0,0,0}, // 16 = 2 + 7(2) 124 | {3,3,0,0}, 125 | {0,3,0,0}, 126 | {0,0,0,0}} , 127 | 128 | {{0,0,0,0}, // 17 = 3 + 7(2) 129 | {0,4,4,0}, 130 | {0,4,4,0}, 131 | {0,0,0,0}} , 132 | 133 | {{5,5,0,0}, // 18 = 4 + 7(2) 134 | {0,5,0,0}, 135 | {0,5,0,0}, 136 | {0,0,0,0}} , 137 | 138 | {{0,6,0,0}, // 19 = 5 + 7(2) 139 | {0,6,0,0}, 140 | {6,6,0,0}, 141 | {0,0,0,0}} , 142 | 143 | {{0,7,0,0}, // 20 = 6 + 7(2) 144 | {0,7,0,0}, 145 | {0,7,0,0}, 146 | {0,7,0,0}} , 147 | 148 | {{1,1,0,0}, // 21 = 0 + 7(3) 149 | {0,1,1,0}, 150 | {0,0,0,0}, 151 | {0,0,0,0}} , 152 | 153 | {{0,2,0,0}, // 22 = 1 + 7(3) 154 | {2,2,2,0}, 155 | {0,0,0,0}, 156 | {0,0,0,0}} , 157 | 158 | {{0,3,3,0}, // 23 = 2 + 7(3) 159 | {3,3,0,0}, 160 | {0,0,0,0}, 161 | {0,0,0,0}} , 162 | 163 | {{0,0,0,0}, // 24 = 3 + 7(3) 164 | {0,4,4,0}, 165 | {0,4,4,0}, 166 | {0,0,0,0}} , 167 | 168 | {{0,0,5,0}, // 25 = 4 + 7(3) 169 | {5,5,5,0}, 170 | {0,0,0,0}, 171 | {0,0,0,0}} , 172 | 173 | {{6,0,0,0}, // 26 = 5 + 7(3) 174 | {6,6,6,0}, 175 | {0,0,0,0}, 176 | {0,0,0,0}} , 177 | 178 | {{0,0,0,0}, // 27 = 6 + 7(3) 179 | {7,7,7,7}, 180 | {0,0,0,0}, 181 | {0,0,0,0}} 182 | }; 183 | 184 | CRGB paletblock[10]={CRGB::Black,CRGB::Red,CRGB::Green,CRGB::Blue,CRGB::Yellow,CRGB::Purple,CRGB::Cyan,CRGB::White} ; 185 | int blockColumn; //the x value of the left most row in the 4x4 active block placeholder 186 | int blockRow; //the y value of the bottom column in the 4x4 active block placeholder 187 | 188 | int rowToBeDeleted; 189 | bool inGame = false; 190 | bool justLost = false; 191 | int brightness = 8; 192 | long fallRate; 193 | long dixs=4000000; 194 | 195 | WebSocketsServer tetrisWebSocket = WebSocketsServer(tetrisWebSocketPort); //creating the entry for socket 196 | 197 | bool initTetris(int w,int h) 198 | { 199 | if(isTable) 200 | { 201 | TETRIS_WIDTH=w; 202 | TETRIS_HEIGHT=h; 203 | backgroundBlocks =(CRGB*)os_malloc(w*h*sizeof(CRGB)) ; 204 | displayScreen =(CRGB*)os_malloc(w*h*sizeof(CRGB)) ; 205 | if(!backgroundBlocks && !displayScreen) 206 | { 207 | Serial.println("Unable to create the screens"); 208 | isInitiated=false; 209 | return false; 210 | } 211 | Serial.println("Tetris créée"); 212 | isInitiated=true; 213 | return true; 214 | } 215 | else{ 216 | Serial.println("No table existing create the table first"); 217 | isInitiated=false; 218 | return false; 219 | } 220 | } 221 | 222 | void combineArrays() //updates the displayScreen array by combining the current positions of the backgroundBlocks and the activeBlocks 223 | { 224 | //first make an exact copy of the backgroundBlocks 225 | // Serial.println("on combine"); 226 | for(byte y = 0; y < TETRIS_HEIGHT; y++) 227 | for(byte x = 0; x < TETRIS_WIDTH; x++) 228 | displayScreen[x+TETRIS_WIDTH*y] = backgroundBlocks[x+TETRIS_WIDTH*y]; 229 | 230 | //then add the non zero elements of the activeBlocks 231 | for(int y = 0; y < 4; y++) 232 | for(int x = 0; x < 4; x++) 233 | if(activeBlocks[blockType + (7 * state)][y][x] > 0) 234 | { 235 | // Serial.print("e:"); 236 | //Serial.println(activeBlocks[blockType + (7 * state)][x][y]); 237 | displayScreen[x + blockColumn+TETRIS_WIDTH*(y + blockRow)] = paletblock[ activeBlocks[blockType + (7 * state)][y][x] ]; 238 | } 239 | } 240 | 241 | 242 | void displayArray() // cycles through each pixel in displayScreen and outputs corresponding colour 243 | { 244 | 245 | displaypic(displayScreen,TETRIS_X,TETRIS_Y,TETRIS_HEIGHT,TETRIS_WIDTH); 246 | if(isDisplayNextPiece) 247 | { 248 | int x=0; 249 | int y=0; 250 | switch (displayNextPiecePos) { 251 | case DISP_UP: 252 | x=2; 253 | y=(TETRIS_HEIGHT+1+TETRIS_Y); 254 | break; 255 | case DISP_RIGHT: 256 | x=TETRIS_X+TETRIS_WIDTH+2; 257 | y=2; 258 | break; 259 | default: 260 | break; 261 | } 262 | displaypic(nextBlockImage,x,y,3,4); //on ecrit la next piece 263 | } 264 | if(isDisplayScore) 265 | { 266 | char chi[1]; 267 | sprintf(chi, "%d", score); 268 | afficheLettre((int)(chi[0])-32,14, 10); 269 | } 270 | } 271 | 272 | void updateDisplay() // this function is called by a timer interupt every 10 milliseconds 273 | { 274 | //Serial.println("on affiche"); 275 | combineArrays(); 276 | 277 | 278 | 279 | 280 | // adds the latest position of the active block to the displayScreen Array 281 | //Serial.println("on display"); 282 | displayArray(); 283 | 284 | FastLED.show();// outputs the displayScreen Array 285 | } 286 | 287 | 288 | void resetArrays() // resets arrays to all zeros 289 | { 290 | for(byte y = 0; y < TETRIS_HEIGHT; y++) 291 | for(byte x = 0; x < TETRIS_WIDTH; x++) 292 | { 293 | displayScreen[x+TETRIS_WIDTH*y] = CRGB(0,0,0); 294 | backgroundBlocks[x+TETRIS_WIDTH*y] = CRGB(0,0,0); 295 | } } 296 | 297 | 298 | void fillNextBlock(int blockType) 299 | { 300 | for(int y = 0; y < 3; y++) 301 | for(int x = 0; x < 4; x++) 302 | nextBlockImage[x +4*y] = paletblock[ activeBlocks[blockType + (7 * 3)][y][x] ]; 303 | } 304 | 305 | void newBlock() // 306 | { 307 | blockColumn = 2; 308 | blockRow = TETRIS_HEIGHT-3; 309 | blockType=nextBlockType; 310 | nextBlockType = random(7);// blocktype is a random between 0 and 6 inclusive 311 | //Serial.println(blockType); 312 | fillNextBlock(nextBlockType); 313 | state = 3; // reset state back to spawn block state 314 | } 315 | 316 | 317 | bool canBeMoved(int newCol, int newRow) // return true if the there is empty pixels for the block to move in to 318 | { 319 | for(int y = 0; y < 4; y++) 320 | { 321 | for(int x = 0; x < 4; x++) 322 | { 323 | if(activeBlocks[blockType + (7 * state)][y][x] > 0) // finds the positions of the non-blank blocks in the 4x4 matrix 324 | { 325 | int boardX = x + newCol; // calculates the corresponding x position on the display board 326 | int boardY = y + newRow; // calculates the corresponding y position on the display board 327 | //Serial.println(boardY); 328 | if(boardX < 0 || boardX > TETRIS_WIDTH-1 || boardY < 0) // if the pixel is outside the boundaries of the board 329 | return false; 330 | if(backgroundBlocks[boardX+TETRIS_WIDTH*boardY] > CRGB(0,0,0)) // if the pixel is already full 331 | return false; 332 | } 333 | } 334 | } 335 | return true; 336 | } 337 | 338 | bool canMoveDown() // row - 1 339 | { 340 | if(blockRow-1<0) 341 | Serial.println(blockRow); 342 | 343 | if(canBeMoved(blockColumn, blockRow -1)) 344 | return true; 345 | else 346 | return false; 347 | } 348 | 349 | bool canMoveLeft() 350 | { 351 | if(canBeMoved(blockColumn - 1, blockRow)) // column -1 352 | return true; 353 | else 354 | return false; 355 | } 356 | 357 | bool canMoveRight() 358 | { 359 | if(canBeMoved(blockColumn + 1, blockRow)) // column + 1 360 | return true; 361 | else 362 | return false; 363 | } 364 | 365 | bool canBeRotated(int newState) 366 | { 367 | for(int y = 0; y < 4; y++) 368 | { 369 | for(int x = 0; x < 4; x++) 370 | { 371 | if(activeBlocks[blockType + (7 * newState)][y][x] > 0) // finds the positions of the non-blank blocks in the 4x4 matrix 372 | { 373 | int boardX = x + blockColumn; // calculates the corresponding x position on the display board 374 | int boardY = y + blockRow; // calculates the corresponding y position on the display board 375 | if(boardX < 0 || boardX > TETRIS_WIDTH || boardY < 0) // if the pixel is outside the boundaries of the board 376 | return false; 377 | 378 | if(backgroundBlocks[boardX+TETRIS_WIDTH*boardY] > CRGB(0,0,0)) // if the pixel is already full 379 | return false; 380 | } 381 | } 382 | } 383 | return true; 384 | } 385 | 386 | bool canRotateLeft() 387 | { 388 | int nextState; 389 | if(state == 0) // state to the left of 0 is 3 390 | nextState = 3; 391 | else 392 | nextState = state - 1; 393 | 394 | if(canBeRotated(nextState)) 395 | return true; 396 | else 397 | return false; 398 | } 399 | 400 | bool canRotateRight() 401 | { 402 | int nextState; 403 | if(state == 3) // state to the right of 3 is 0 404 | nextState = 0; 405 | else 406 | nextState = state + 1; 407 | 408 | if(canBeRotated(nextState)) 409 | return true; 410 | else 411 | return false; 412 | } 413 | 414 | void moveActiveBlocksToBackground() 415 | { 416 | combineArrays(); //updated the display array 417 | 418 | for(byte y = 0; y < TETRIS_HEIGHT; y++) 419 | for(byte x = 0; x < TETRIS_WIDTH; x++) 420 | backgroundBlocks[x+TETRIS_WIDTH*y] = displayScreen[x+TETRIS_WIDTH*y]; // copy the displayScreen to the backgroundBlocks 421 | } 422 | 423 | bool rowIsFull() // goes through all 16 rows and checks if they are full 424 | { 425 | for(byte y = 0; y < TETRIS_HEIGHT; y++) 426 | { 427 | bool isfull=true; 428 | for(byte x=0;x 1) // to stop fallRate decreasing to zero 468 | fallRate -= 1; // blocks falling speeds up by 50000 nanoseconds every full row made 469 | 470 | 471 | } 472 | 473 | void deleteFullRows() 474 | { 475 | for(int i = 0; i < 4; i++) // checking 4 times if there are full rows to be deleted 476 | { 477 | if(rowIsFull()) 478 | { 479 | deleteRow(); 480 | speedUpFalling(); 481 | } 482 | } 483 | } 484 | 485 | bool spaceForNewBlock() // returns true if there is space for the new block to be spawned at the top of the matrix 486 | { 487 | if(canBeMoved(2, TETRIS_HEIGHT-3)) 488 | return true; 489 | else 490 | return false; 491 | } 492 | 493 | 494 | void fillScreenT() // fills pixels one at a time with green at the end of the game one at a time starting from the top 495 | { 496 | for(int y = 0; y 2 | 3 | Tetris 4 | 5 | 17 | 18 | 19 |

Tetris

20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 84 | 85 | 86 | --------------------------------------------------------------------------------