Anda di halaman 1dari 56

Please sign in to continue:

Sign in
Sign In

Arduino Web Editor

Getting Started

Arduino Project Hub

Device Manager

Digital
Store

Arduino IoT Cloud

Sign In
NOW CHROME OS READY!

Download the App

My dashboard Add project

Share

Embed the widget on your own site

<iframe framebor
Add the following snippet to your HTML:

Make an interactive table that displays games, an audio spectrum, and animations on a 12x12
built-in LED matrix.

Interactive LED Table for 50€

Project showcase by Antoine Rochebois

 36,966 views
 12 comments
 123 respects

Project showcase

Interactive LED Table for 50€ © CC BY-NC


Make an interactive table that displays games, an audio spectrum, and animations on a 12x12
built-in LED matrix.

 acrylic
 animation
 app
 arcade
 audio
 bluetooth
 board
 cheap
 display
 foam
 game
 hc06
 hc-06
 ikea
 inventor
 lack
 life
 matrix
 meter
 mit
 play
 pong
 printing
 screen
 simon
 snake
 spectrum
 table
 tetris
 text
 ws2812b

 36,605 views
 12 comments
 122 respects

Components and supplies


LACK table - Ikea × 1
WS2812b 5m - 150 LEDs strip × 1
Arduino Nano R3
× 1
You can buy a cheap one in some eastern countries ;)

HC-05 Bluetooth Module × 1

45mm illuminated round arcade push button × 4


19mm illuminated blue push button × 1
Illuminated blue rocker switch × 1
Stereo audio female plug × 2
TL072 based audio amplifier
× 1
Check the story for shematics

Prototype PCB × 1
Too many cables... × 1
405x405mm white acrylic glass × 1
Black foam board (A2 - 5mm thick) × 1
5V - 50W power supply × 1
L profiled aluminium bar × 1

Necessary tools and machines


3D Printer (generic)
Dagoma DiscoEasy200 (If you want a cheap french 3D printer you'd better buy a µDelta Rework from EmotionTech)

Soldering iron (generic)

Hot glue gun (generic)

Box cutter

Wood rasp

Saw

Drill

About this project


To begin with, I would like to thank my parents and my grandfathers who taught me from an
early age the worth and the power of creative work.

WARNING : This is a showcase, not a tutorial. The published code is for illustration and is
not running without other files (containing application source codes). Since the games are
not fully debugged, I do not want to share crappy code. Sorry about that :(
[04/01/2019 UPDATE] The code is now fully uploaded (Bluetooth and buttons mangement,
animations, games fully operational) on this showcase but still verry buggy (RAM overflow)

0. Presentation

In this showcase, I'll explain you how I made a cheap interactive table that uses Bluetooth,
physical controls and a LED matrix from a simple 7€ IKEA table. This table is able to display an
audio spectrum visualizer, some games and animations.

You can see some of these features in the video below :

Video demonstration of the table :)

1. Preparing the project - Java emulation

After having the idea of a project, the first thing to be done is to define an exhaustive to-do list, a
bill of materials and to have a strong idea of what your code will look like.

To cope with this challenge, I designed an emulator for my LED Matrix on Java. The purpose of
this step was to set up the main functions and algorithms that I would need to make my device
work properly. Doing this also allowed me to know more specifically what hardware (inputs
especially) I would need to complete my project.

This program displays a 12x12 color grid and refreshes this grid with a method similar to the
"FastLED.show();" function used by the Arduino FastLED library to control the matrix. The
program displays the menu and is able to launch several modes : displaying
images/animations/text, run Conway's game of life, Tetris, Snake, Pong (for 2 players), the
Simon game, etc...

The Java program displaying the menu interface

The first issue that I had was to define some static images in the program. The specifications of
the Arduino didn't allow me to use .jpg nor .png images, I had to deal with 2D-arrays of 24bits
pixels (defined in hexadecimal as 0xRRGGBB). To make things easier, I wrote another Java
program that translates a 12x12 bitmap image into the desired 2D-Array.

A (very simple) image translated in a 2D-array definition by the homemade script.

Once the emulator was in accordance with my expectations, I bought all the necesary
components for the project...

2. How to read an audio signal ?


One of the main feature of my table will be to display live an audio spectrum on the screen while
I listen to music. In order to achieve that, I used an operational amplifier (the TL072) to center
the voltage around 2.5V and to amplify it. The Arduino is now able to read and to analyze the
provided audio signal. (thanks to a Fast Fourier Transformation algorithm). This circuit was
soldered on a prototype board.

The amplifier shematic

The circuit tested on a breadboard

A 40Hz sin wave as it is read by the Arduino (It's saturating a little bit but this is
goodenough)

3. Time for some cheap woodwork, wiring and 3D printing !

The 150 LEDs strip that I bought was 5 meters (or 16.4ft) long. That means that my 12x12
screen would be at least (500/150*12)=40cm width and long. In order to have more flexibility in
the future, I ordered a 405x405mm white acrylic glass and made a 410x410mm hole in the table
with a drill and a saw.

The 7€ Ikea Lack table is so cheap that it is empty on the inside but this is beneficent for our
purpose. (By the way, having a vacuum cleaner at your side prevents you from breathing wood
dust)

The acryclic glass and the table

Cutting the table

Inside an Ikea cheap table (if you've ever wondered...)

Once I was done with the main hole, I drilled 4 round 40mm holes on the sides of the table to
host 4 control buttons and a small hole on the bottom of the table to host the female powerplug.
Afterwards, I made a square hole where the main control interface will fit. The buttons on this
interface are very small and close to each other, drilling some holes would have led to
disappointing results.

In order to solve this problem, I've designed my interface on Fusion360 and 3D printed it. Next, I
applied a primer coat on it and was quite satisfied by this finish.

Then, it was time for some wiring. I've soldered and glued everything in place as it is shown in
the schematic below.

The "naked" table once drilled.


The 3D printed interface (the small extrusion will host the Arduino Nano)

The final look of the interface (Menu/validation button, arduino USB, Audio IO, power
switch)

It looks pretty clean without all the cables

Wiring done and everything glued in place !

4. Making the screen !

I think this is the part I'm the less proud of. I strongly advice you to use a very soft foam-board
or even a laser cutter to make a decent grid. I cut the LED strip every 12 leds to make 12 small
strips and glued them on a 410x410mm foam-board (with the wiring done). I then glued a foam-
board grid made with a box cutter. Finally, I glued the acrylic glass on the top of the grid and
powered the LED matrix for a test. The problem with the box cutter is that the grid isn't very flat
on the top and that the pixels aren't perfectly aligned.

The foamboard and the LED strips

The LED matrix wired

The (very ugly) grid

First test, the matrix works perfecly :D

Once installed and wired in the table, the matrix was ready to execute the code that we provided
to the Arduino through the USB port.

5. The Android controller

I used the MIT App Inventor software to make a very simple Android application to control my
table through Bluetooth.

6. TO DO :

The work isn't finished yet. I need to debug some features, to improve some and even to program
some others !

I also want to cut and install some L-profiled aluminium bar in the gap between the screen and
the table to make it look nicer and cleaner but I need a hacksaw for that...
This is still work in progress ;)

I need to setup these aluminium bars to finish the table (red tape is temporary)

SCHEMATICS COMING SOON

Code
 Arduino main code
 Game of Life
 Random roulette mode (idk how to call it ^^' )
 decoration.h
 font.h
 imgMario.h
 imgMenu.h
 pong.h
 snake.h
 tetris.h
 Audio spectrum visualizer

Arduino main codeArduino

This file is the main code that run on the Arduino, it uses several home-made methods &
functions to run games and other features.
I'll upload them once the code is finished and bugless.
/*
*
* Code by Antoine ROCHEBOIS : CC-BY-NC
*
*
* This file is the main code that run on the Arduino, it uses several
* home-made methods & functions to run games and other features, I'll
* upload them once the code is finished and bugless.
*
*
*
* */
#include "FastLED.h"
#include <avr/pgmspace.h>
#include <SoftwareSerial.h>

#include "imgMario.h" //Import 2D array of 32bits int provinding the RGB


#include "imgMenu.h" //code for each image of the Menu and Images function

#define M_PIN 2 //Pin for the menuInterrupt


#define R1_PIN 8 //
#define L1_PIN 9 // Digital inputs used by arcade buttons (side)
#define R2_PIN 6 //
#define L2_PIN 7 //
#define DATA_PIN 5 //Data PIN for the led matrix
#define COLOR_ORDER GRB // if colors are mismatched; change this
#define NUM_LEDS 144 // 12*12=144 leds in the strip
#define LED_TYPE WS2812B
// this creates an LED array to hold the values for each led in your strip
CRGB leds[NUM_LEDS];

const PROGMEM byte ledsAdress[12][12] = {{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,


11},
{23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12},
{24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35},
{47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36},
{48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59},
{71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60},
{72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83},
{95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84},
{96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107},
{119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108},
{120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131},
{143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132}
}; //Adress of each led in the matrix (Progmem means stored in FLASH instead
//of SRAM)

SoftwareSerial BT(10, 11); //Emulates an Serial BT terminal

boolean grid[12][12]; //(used in a game, ignore)


char message; //char read on the BT terminal
char curControl; //current control ID
int menuPointer = 0; //Position in the menu
volatile bool menuValidation = 0; //Variable set to true when the menu switch
//is pushed

unsigned long curTime;


unsigned long prevUpdateTime = 0; //Variables for timed events
unsigned long prevButtonTime = 0;

//Function executed when the user push the menuButton (set menuValidation to
//true + debounce input)
void menuInterrupt() {
static unsigned long last_interrupt_time = 0;
unsigned long interrupt_time = millis();
if (interrupt_time - last_interrupt_time > 200) {
menuValidation = true;
}
last_interrupt_time = interrupt_time;
}

//Displays static images stocked in FLASH, if roll == 1, draws it whith a


fancy red line
void setImg(const unsigned long frame[12][12], bool roll) {
if (!roll) {
for (byte i = 0; i < 12; i++) {
for (byte j = 0; j < 12; j++) {
leds[pgm_read_byte(&ledsAdress[i][j])] =
pgm_read_dword(&frame[i][j]);
}
}
FastLED.show();

} else {
for (uint8_t i = 11; i > 0; i--) {
for (byte j = 0; j < 12; j++) {
if (i > 0) {
leds[pgm_read_byte(&ledsAdress[i][j])] = 0xe22c79;
} else {
leds[pgm_read_byte(&ledsAdress[i][j])] =
pgm_read_dword(&frame[i][j]);
}

leds[pgm_read_byte(&ledsAdress[(i + 13) % 12][j])] =


pgm_read_dword(&frame[(i + 13) % 12][j]);
}
FastLED.show();
delay(70);
}
}

//Erase the screen with a red sweeping line


void resetImg() {
for (byte i = 0; i < 12; i++) {
for (byte j = 0; j < 12; j++) {
leds[pgm_read_byte(&ledsAdress[i][j])] = 0xe22c79;
if (i > 0) {
leds[pgm_read_byte(&ledsAdress[(i + 11) % 12][j])] = 0x000000;
}

}
FastLED.show();
delay(70);
}
}
//Erase the screen by fading it
void fadeImg() {
for (uint8_t i = 128; i > 0; i = i - 4) {
FastLED.setBrightness(i);
FastLED.show();
delay(24);
}
delay(250);
FastLED.setBrightness(128);
}
//Instant erase of the screen
void clearImg() {
for (byte dim1 = 0; dim1 < 12; dim1++) {
for (byte dim2 = 0; dim2 < 12; dim2++) {
leds[pgm_read_byte(&ledsAdress[dim1][dim2])] = 0x000000;
}
}
}
//Read inputs (BT + digital IO)
void readPointer() {

//Read BT (hc-05 module)


while (BT.available() > 0) {
message = BT.read();
}
//Changes control variables
if (message == 'q' ) {
--menuPointer;
curControl = 'q';
} else if (message == 'd') {
++menuPointer;
curControl = 'd';
} else if (message == 'z') {
curControl = 'z';
} else if (message == 's') {
curControl = 's';
} else if (message == 'a') {
curControl = 'a';
} else if (message == 'y') {
menuValidation = true;
}
message = 'n'; //Reset message

//Read digital IO pins


if (!digitalRead(L1_PIN)) {
if ( (millis() - prevButtonTime) > 150) {
curControl = 'q';
--menuPointer;
prevButtonTime = millis();
}
} else if (!digitalRead(R1_PIN)) {
if ( (millis() - prevButtonTime) > 150) {
curControl = 'd';
++menuPointer;
prevButtonTime = millis();
}
} else if (!digitalRead(L2_PIN)) {
if ( (millis() - prevButtonTime) > 150) {
curControl = 'z';
--menuPointer;
prevButtonTime = millis();
}
} else if (!digitalRead(l2_PIN)) {
if ( (millis() - prevButtonTime) > 150) {
curControl = 's';
++menuPointer;
prevButtonTime = millis();
}
}

#include "gameOfLife.h" //Include features and games methods and functions


#include "snake.h"
#include "pong.h"
#include "tetris.h"
#include "bottle.h"
#include "decoration.h"
#include "font.h"

/*
*
* RUN AT STARTUP
*
*/

void setup() {
//Setup the BT connection
BT.begin(9600);

//Setup the IO pin (Inputs with a built-in pull-up resistor or interupt)


pinMode(R1_PIN, INPUT_PULLUP);
pinMode(L1_PIN, INPUT_PULLUP);
pinMode(R2_PIN, INPUT_PULLUP);
pinMode(L2_PIN, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(M_PIN), menuInterrupt, FALLING);

//Setup the Led strip


FastLED.addLeds<LED_TYPE, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS);

//Intro animation (display a beer and load the menu)


FastLED.setBrightness(0);
setImg(beer, 0);
delay(250);
for (uint8_t i = 0; i <= 128; i = i + 4) {
FastLED.setBrightness(i);
FastLED.show();
delay(42);
}
delay(2400);
fadeImg();
clearImg();
FastLED.show();
delay(250);
setImg(menuTetris, 1);

/*
*
* RUN PERPETUALY
*
*/
void loop() {

//Menu Interface and games/features launcher


switch ((menuPointer + 12000) % 12) {
case 0:
setImg(menuTetris, 0);
while ((menuPointer + 12000) % 12 == 0 && !menuValidation) {
readPointer();
}
if (menuValidation) {
menuValidation = false;
while (!menuValidation) {
launchTetris(); //Tetris game
}
menuValidation = false;
menuPointer = 0;
resetImg();
setImg(menuTetris, 1);
}
break;
case 1:
setImg(menuSimon, 0);
while ((menuPointer + 12000) % 12 == 1 && !menuValidation) {
readPointer();
}
if (menuValidation) {
menuValidation = false; //Displays a cross : feature not implemented
yet
setImg(menuError, 0);
delay(1250);
menuPointer = 1;
resetImg();
setImg(menuSimon, 1);
}
break;
case 2:
setImg(menuPong, 0);
while ((menuPointer + 12000) % 12 == 2 && !menuValidation) {
readPointer();
}
if (menuValidation) {
menuValidation = false;
while (!menuValidation) {
launchPong(); //Pong game for 2 players
}
menuValidation = false;
menuPointer = 2;
resetImg();
setImg(menuPong, 1);
}
break;
case 3:
setImg(menuSnake, 0);
while ((menuPointer + 12000) % 12 == 3 && !menuValidation) {
readPointer();
}
if (menuValidation) {
menuValidation = false;
while (!menuValidation) {
launchSnake(); //Snake game
}
menuValidation = false;
menuPointer = 3;
resetImg();
setImg(menuSnake, 1);
}
break;
case 4:
setImg(menuBottle, 0);
while ((menuPointer + 12000) % 12 == 4 && !menuValidation) {
readPointer();
}
if (menuValidation) {
menuValidation = false;
while (!menuValidation) {
bottle(); //A wheel that stops on a random location on the screen
}
menuValidation = false;
menuPointer = 4;
resetImg();
setImg(menuBottle, 1);
}
break;
case 5:
setImg(menuGameOfLife, 0);
while ((menuPointer + 12000) % 12 == 5 && !menuValidation) {
readPointer();
}
if (menuValidation) {
menuValidation = false;
while (!menuValidation) {
gameOfLife(); //Run conway's game of life
}
menuValidation = false;
menuPointer = 5;
resetImg();
setImg(menuGameOfLife, 1);
}
break;
case 6:
setImg(menuParty, 0);
while ((menuPointer + 12000) % 12 == 6 && !menuValidation) {
readPointer();
}
if (menuValidation) {
menuValidation = false;
while (!menuValidation) {
launchManualAnimations(); //Visual animation (choice)
}
menuValidation = false;
menuPointer = 6;
resetImg();
setImg(menuParty, 1);
}
break;
case 7:
setImg(menuParty, 0);
while ((menuPointer + 12000) % 12 == 7 && !menuValidation) {
readPointer();
}
if (menuValidation) {
menuValidation = false;
while (!menuValidation) {
launchRandomAnimations(); //Launch random visual animation
}
menuValidation = false;
menuPointer = 7;
resetImg();
setImg(menuParty, 1);
}
break;
case 8:
setImg(menuImage, 0);
while ((menuPointer + 12000) % 12 == 8 && !menuValidation) {
readPointer();
}
if (menuValidation) {
menuValidation = false;
while (!menuValidation) {
launchManualImage(); //Images manual selection
}
menuValidation = false;
menuPointer = 8;
resetImg();
setImg(menuImage, 1);
}
break;
case 9:
setImg(menuImage, 0);
while ((menuPointer + 12000) % 12 == 9 && !menuValidation) {
readPointer();
}
if (menuValidation) {
menuValidation = false;
while (!menuValidation) {
launchRandomImage(); //Images random selection
}
menuValidation = false;
menuPointer = 9;
resetImg();
setImg(menuImage, 1);
}
break;
case 10:
setImg(menuText, 0);
while ((menuPointer + 12000) % 12 == 10 && !menuValidation) {
readPointer();
}
if (menuValidation) {
menuValidation = false;
while (!menuValidation) {
scrollText("Hi!",3, 0xff0000); //Scrolls a defined text on the
screen TODO: BT defined text & color
}
menuValidation = false;
menuPointer = 10;
resetImg();
setImg(menuText, 1);
}
break;
case 11:
setImg(menuSpectrum, 0);
while ((menuPointer + 12000) % 12 == 11 && !menuValidation) {
readPointer();
}
if (menuValidation) { //Spectrum Analyzer code is too heavy for the
FLASH/SRAM, needs a specific upload to run. Displays an error message
menuValidation = false;
setImg(menuError, 0);
delay(1250);
scrollText("Connect USB",11, 0xff0000);
menuPointer = 11;
resetImg();
setImg(menuSpectrum, 1);
}
break;
}

Game of LifeArduino

The algorithm for the Conway's Game of life function


void gameOfLife(void) {
//Génération d'une grille de départ aléatoire
for (byte i = 0; i < 12; i++) {
for (byte j = 0; j < 12; j++) {
byte r = random(0, 100);
if (r < 35) {
grid[i][j] = true;
leds[pgm_read_byte(&ledsAdress[i][j])] = 0x2CB697;
} else {
grid[i][j] = false;
leds[pgm_read_byte(&ledsAdress[i][j])] = 0x11463A;
}
}
}
FastLED.show();

//Tant que la grille n'est pas vide


byte nbCases;
byte iterations = 0;
do {
readPointer();
if (menuValidation) {
break;
}
++iterations;
if (iterations > 250) {
break;
}
//Délai de 150ms
delay(120);

//Initialisation et comptage du nombre de voisins de chaque case


nbCases = 0;
byte voisins[12][12];
for (byte i = 0; i < 12; i++) {
for (byte j = 0; j < 12; j++) {
voisins[i][j] = 0;
}
}

for (byte i = 0; i < 12; i++) {


for (byte j = 0; j < 12; j++) {
for (int k = -1; k < 2; k++) {
for (int m = -1; m < 2; m++) {
if ((grid[(i + k + 12) % 12][(j + m + 12) % 12] == true) && !(k
== 0 && m == 0)) {
voisins[i][j]++;
}
}
}
}
}

//Détermination des cellules vivantes et mortes et mise à jour de


l'affichage
for (byte i = 0; i < 12; i++) {
for (byte j = 0; j < 12; j++) {
if (grid[i][j]) {
nbCases++;
//Cellule vivante reste vivante avec 2 ou 3 voisins
if (voisins[i][j] == 2 || voisins[i][j] == 3) {
grid[i][j] = true;
leds[pgm_read_byte(&ledsAdress[i][j])] = 0x2CB697;
} else {
grid[i][j] = false;
leds[pgm_read_byte(&ledsAdress[i][j])] = 0x11463A;
}

} else {
if (voisins[i][j] == 3) {
//Cellule morte devient vivante si elle a 3 voisins
grid[i][j] = true;
leds[pgm_read_byte(&ledsAdress[i][j])] = 0x2CB697;
}
}
}
}
FastLED.show();
if (nbCases <= 4) {
for (byte i = 0; i < 12; i++) {
for (byte j = 0; j < 12; j++) {
if (i < 12 - 1) {
leds[pgm_read_byte(&ledsAdress[i][j])] = 0xe22c79;
} else {
leds[pgm_read_byte(&ledsAdress[i][j])] = 0x11463A;
}

leds[pgm_read_byte(&ledsAdress[(i + 11) % 12][j])] = 0x11463A;


}
FastLED.show();
delay(100);
}
}
} while (nbCases > 4);
}

Random roulette mode (idk how to call it ^^' )Arduino

const unsigned long PROGMEM img[12][12] = {{0x020EF4, 0x022FF4, 0x0159F3,


0x018AF5, 0x01BFF9, 0x01F5FB, 0x01FFD6, 0x01FDA5, 0x01FC7A, 0x01FB54,
0x01FA38, 0x02F91F},
{0x0100F3, 0x010EF4, 0x0237F3, 0x0170F4, 0x01B1F9, 0x01F2FA, 0x01FFCB,
0x01FC8E, 0x01FB5D, 0x01FA37, 0x01F918, 0x00F905},
{0x0001F2, 0x0000F2, 0x010FF3, 0x0247F4, 0x019BF7, 0x01EFF8, 0x01FFBA,
0x01FB6E, 0x01FA35, 0x00F812, 0x00F802, 0x01F900},
{0x0201F2, 0x0001F2, 0x0000F3, 0x0010F3, 0x016CF6, 0x01E9F5, 0x00FF97,
0x00FA35, 0x00F908, 0x02F900, 0x0EFA00, 0x1FFB01},
{0x2C00F3, 0x1D01F3, 0x0F01F2, 0x0100F2, 0x001BF9, 0x00CEE4, 0x00FF42,
0x08F901, 0x1DFB00, 0x33FC01, 0x41FE00, 0x4BFE00},
{0x6701F3, 0x6501F3, 0x6501F4, 0x6402F5, 0x6700FE, 0x756F82, 0x7CFF00,
0x7BFF02, 0x7AFF02, 0x7BFF02, 0x7AFE02, 0x79FF01},
{0x9F00F3, 0xAC01F3, 0xC301F7, 0xE001F1, 0xF900AE, 0xFF0C15, 0xFFAF00,
0xF3FD04, 0xD8FF03, 0xC0FF03, 0xB2FF04, 0xA9FE04},
{0xD301F5, 0xE600F2, 0xF401DF, 0xF600AF, 0xF4004F, 0xF30001, 0xF95000,
0xFFC002, 0xFFF303, 0xF7FF03, 0xE6FF02, 0xD3FF03},
{0xF301E9, 0xF501D0, 0xF301A9, 0xF30074, 0xF20026, 0xF10000, 0xF52A01,
0xFA8202, 0xFFC003, 0xFFEA04, 0xFFFD03, 0xF7FF03},
{0xF400C5, 0xF301A8, 0xF20182, 0xF2014F, 0xF20113, 0xF20000, 0xF41801,
0xF75C02, 0xFD9502, 0xFEBF02, 0xFFE103, 0xFFF803},
{0xF301A8, 0xF30089, 0xF20065, 0xF10137, 0xF20009, 0xF20000, 0xF30D01,
0xF64301, 0xF97601, 0xFDA001, 0xFEC002, 0xFFDB03},
{0xF30090, 0xF20172, 0xF2014E, 0xF30126, 0xF20003, 0xF20000, 0xF30801,
0xF43201, 0xF75F02, 0xFC8602, 0xFEA601, 0xFEC102}
};

void bottleAnimation(byte t, byte stopb) {


byte iterations = 0;

while (!menuValidation) {
for (byte k = 0; k < 4; k++) {
switch (k) {
case 0:
for (byte i = 2; i < 12; i++) {
iterations++;
if (iterations == stopb) {
goto mainLoopBottle;
}
clearImg();
leds[pgm_read_byte(&ledsAdress[2][i - 2])] =
pgm_read_dword(&img[1][i - 2]);
leds[pgm_read_byte(&ledsAdress[2][i - 1])] =
pgm_read_dword(&img[2][i - 1]);
leds[pgm_read_byte(&ledsAdress[2][i])] =
pgm_read_dword(&img[2][i]);
leds[pgm_read_byte(&ledsAdress[1][i - 2])] =
pgm_read_dword(&img[1][i - 2]);
leds[pgm_read_byte(&ledsAdress[1][i - 1])] =
pgm_read_dword(&img[1][i - 1]);
leds[pgm_read_byte(&ledsAdress[1][i])] =
pgm_read_dword(&img[1][i]);
leds[pgm_read_byte(&ledsAdress[0][i - 2])] =
pgm_read_dword(&img[1][i - 2]);
leds[pgm_read_byte(&ledsAdress[0][i])] =
pgm_read_dword(&img[0][i]);
leds[pgm_read_byte(&ledsAdress[0][i - 1])] =
pgm_read_dword(&img[1][i - 1]);
FastLED.show();
delay(t);
}
break;
case 1:
for (byte i = 2; i < 12; i++) {
iterations++;
if (iterations == stopb) {
goto mainLoopBottle;
}
clearImg();
leds[pgm_read_byte(&ledsAdress[i - 2][11])] =
pgm_read_dword(&img[i - 2][11]);
leds[pgm_read_byte(&ledsAdress[i - 1][11])] =
pgm_read_dword(&img[i - 1][11]);
leds[pgm_read_byte(&ledsAdress[i][11])] =
pgm_read_dword(&img[i][11]);
leds[pgm_read_byte(&ledsAdress[i - 2][10])] =
pgm_read_dword(&img[i - 2][10]);
leds[pgm_read_byte(&ledsAdress[i - 1][10])] =
pgm_read_dword(&img[i - 1][10]);
leds[pgm_read_byte(&ledsAdress[i][10])] =
pgm_read_dword(&img[i][10]);
leds[pgm_read_byte(&ledsAdress[i - 2][9])] =
pgm_read_dword(&img[i - 2][9]);
leds[pgm_read_byte(&ledsAdress[i - 1][9])] =
pgm_read_dword(&img[i - 1][9]);
leds[pgm_read_byte(&ledsAdress[i][9])] =
pgm_read_dword(&img[i][9]);
FastLED.show();
delay(t);
}
break;
case 2:
for (byte i = 12 - 1; i > 1; i--) {
iterations++;
if (iterations == stopb) {
goto mainLoopBottle;
}
clearImg();
leds[pgm_read_byte(&ledsAdress[11][i - 2])] =
pgm_read_dword(&img[11][i - 2]);
leds[pgm_read_byte(&ledsAdress[11][i - 1])] =
pgm_read_dword(&img[11][i - 1]);
leds[pgm_read_byte(&ledsAdress[11][i])] =
pgm_read_dword(&img[11][i]);
leds[pgm_read_byte(&ledsAdress[10][i - 2])] =
pgm_read_dword(&img[10][i - 2]);
leds[pgm_read_byte(&ledsAdress[10][i - 1])] =
pgm_read_dword(&img[10][i - 1]);
leds[pgm_read_byte(&ledsAdress[10][i])] =
pgm_read_dword(&img[10][i]);
leds[pgm_read_byte(&ledsAdress[9][i - 2])] =
pgm_read_dword(&img[9][i - 2]);
leds[pgm_read_byte(&ledsAdress[9][i])] =
pgm_read_dword(&img[9][i]);
leds[pgm_read_byte(&ledsAdress[9][i - 1])] =
pgm_read_dword(&img[9][i - 1]);
FastLED.show();
delay(t);
}
break;
case 3:
for (byte i = 12 - 1; i > 1; i--) {
iterations++;
if (iterations == stopb) {
goto mainLoopBottle;
}
clearImg();
leds[pgm_read_byte(&ledsAdress[i - 2][2])] =
pgm_read_dword(&img[i - 2][2]);
leds[pgm_read_byte(&ledsAdress[i - 1][2])] =
pgm_read_dword(&img[i - 1][2]);
leds[pgm_read_byte(&ledsAdress[i][2])] =
pgm_read_dword(&img[i][2]);
leds[pgm_read_byte(&ledsAdress[i - 2][1])] =
pgm_read_dword(&img[i - 2][1]);
leds[pgm_read_byte(&ledsAdress[i - 1][1])] =
pgm_read_dword(&img[i - 1][1]);
leds[pgm_read_byte(&ledsAdress[i][1])] =
pgm_read_dword(&img[i][1]);
leds[pgm_read_byte(&ledsAdress[i - 2][0])] =
pgm_read_dword(&img[i - 2][0]);
leds[pgm_read_byte(&ledsAdress[i - 1][0])] =
pgm_read_dword(&img[i - 1][0]);
leds[pgm_read_byte(&ledsAdress[i][0])] =
pgm_read_dword(&img[i][0]);
FastLED.show();
delay(t);
}
break;

}
}
} mainLoopBottle:
delay(4);
}

void bottle() {
bottleAnimation(60, random(100, 139));

int prevPointer = menuPointer;


while (!menuValidation && menuPointer == prevPointer) {
readPointer();
delay(4);
}
}

decoration.hC/C++

/*void fillingScreen() {
int iterations = 0;
while (!menuValidation && iterations < 400) {
byte c[3];
for (byte i = 0; i < 3; i++) {
c[i] = random(0, 256);
}
for (byte i = 0; i < 12; i++) {
for (byte j = 0; j < 12; j++) {
leds[pgm_read_byte(&ledsAdress[i][j])] = (( (c[0])) << 16) + ( (c[1])
<< 8) + ( (c[2]));
FastLED.show();
delay(25);
iterations++;
}
}
}
}

void fadingScreen() {
int iterations = 0;
while (!menuValidation && iterations < 400) {
byte c[3];
for (byte i = 0; i < 3; i++) {
c[i] = random(0, 256);
}
for (byte k = 0; k < 128; k = k + 2) {
for (byte i = 0; i < 12; i++) {
for (byte j = 0; j < 12; j++) {
leds[pgm_read_byte(&ledsAdress[i][j])] = (( (c[0])) << 16) + (
(c[1]) << 8) + ( (c[2]));
}

}
iterations++;
FastLED.setBrightness(k);
FastLED.show();
delay(50);
}
for (uint8_t k = 128; k > 0; k = k - 2) {
for (byte i = 0; i < 12; i++) {
for (byte j = 0; j < 12; j++) {
leds[pgm_read_byte(&ledsAdress[i][j])] = (( (c[0])) << 16) + (
(c[1]) << 8) + ( (c[2]));
}

}
iterations++;
FastLED.setBrightness(k);
FastLED.show();
delay(50);
}

}
clearImg();
FastLED.setBrightness(128);
}*/
void crossingSnakes() {
for (byte i = 0; i < 144; i++) {
for (byte j = 0; j < 5; j++) {
leds[(i + j + 0) % 144] = 0xff0000;
leds[(i + j + 12) % 144] = 0xffff00;
leds[(i + j + 23) % 144] = 0x00ff00;
leds[(i + j + 36) % 144] = 0x00ffff;
leds[(i + j + 48) % 144] = 0x0000ff;
leds[(i + j + 59) % 144] = 0xff00ff;
leds[(i + j + 72) % 144] = 0xff0000;
leds[(i + j + 84) % 144] = 0xffff00;
leds[(i + j + 95) % 144] = 0x00ff00;
leds[(i + j + 107) % 144] = 0x00ffff;
leds[(i + j + 120) % 144] = 0x0000ff;
leds[(i + j + 134) % 144] = 0xff00ff;
}
FastLED.show();
delay(85);
clearImg();
if (menuValidation) break;
}
}

/*public void rainingStars(Panel p) {


int iterations = 0;
while (!TableLED.menuValidation && iterations < 400) {

int img[][] = new int[12][12];


int color[][] = new int[12][12];
boolean stars[][] = new boolean[12][12];
for (int i = 0; i < stars.length; i++) {
for (int j = 0; j < stars[i].length; j++) {
if (Math.random() < 0.035) {
stars[i][j] = true;
color[i][j] = (int) (Math.random() * 4);
}
}
}
for (int k = 0; k < 256; k = k + 4) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
iterations++;
for (int i = 0; i < stars.length; i++) {
for (int j = 0; j < stars[i].length; j++) {
if (stars[i][j]) {

switch (color[i][j]) {
case 0:
img[i][j] = (((int) (0.2 * k)) << 16) + ((int) (0.32 * k) <<
8) + ((int) (0.7 * k));
break;
case 1:
img[i][j] = (((int) (0.28 * k)) << 16) + ((int) (0.463 * k)
<< 8) + k;
break;
case 2:
img[i][j] = (k << 16) + ((int) (0.757 * k) << 8) + ((int)
(0.146 * k));
break;
default:
img[i][j] = (((int) (0.27 * k)) << 16) + ((int) (0.118 * k)
<< 8) + ((int) (0.44 * k));
break;
}

}
}
}
p.setFrame(img);
}
}
}*/

/*void decoration() {

byte r = random(0, 6);


readPointer();
switch (r) {
case 0:
crossingSnakes();
break;
case 1:
glitchRainingStars();
break;
case 2:
rainingStars();
break;
case 3:
fadingScreen();
break;
case 4:
bottleAnimation(60, 334);
default:
fillingScreen();
break;
}

}*/

font.hC/C++

/* uTFT Font library


* http://www.henningkarlsen.com/electronics/r_fonts.php
*
*/

const unsigned char PROGMEM font[760] =


{
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // <Space>
0x18,0x3C,0x3C,0x18,0x18,0x00,0x18,0x00, // !
0x66,0x66,0x24,0x00,0x00,0x00,0x00,0x00, // "
0x6C,0x6C,0xFE,0x6C,0xFE,0x6C,0x6C,0x00, // #
0x18,0x3E,0x60,0x3C,0x06,0x7C,0x18,0x00, // $
0x00,0xC6,0xCC,0x18,0x30,0x66,0xC6,0x00, // %
0x38,0x6C,0x38,0x76,0xDC,0xCC,0x76,0x00, // &
0x18,0x18,0x30,0x00,0x00,0x00,0x00,0x00, // '
0x0C,0x18,0x30,0x30,0x30,0x18,0x0C,0x00, // (
0x30,0x18,0x0C,0x0C,0x0C,0x18,0x30,0x00, // )
0x00,0x66,0x3C,0xFF,0x3C,0x66,0x00,0x00, // *
0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00, // +
0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x30, // ,
0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x00, // -
0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00, // .
0x06,0x0C,0x18,0x30,0x60,0xC0,0x80,0x00, // /
0x7C,0xC6,0xCE,0xD6,0xE6,0xC6,0x7C,0x00, // 0
0x18,0x38,0x18,0x18,0x18,0x18,0x7E,0x00, // 1
0x7C,0xC6,0x06,0x1C,0x30,0x66,0xFE,0x00, // 2
0x7C,0xC6,0x06,0x3C,0x06,0xC6,0x7C,0x00, // 3
0x1C,0x3C,0x6C,0xCC,0xFE,0x0C,0x1E,0x00, // 4
0xFE,0xC0,0xC0,0xFC,0x06,0xC6,0x7C,0x00, // 5
0x38,0x60,0xC0,0xFC,0xC6,0xC6,0x7C,0x00, // 6
0xFE,0xC6,0x0C,0x18,0x30,0x30,0x30,0x00, // 7
0x7C,0xC6,0xC6,0x7C,0xC6,0xC6,0x7C,0x00, // 8
0x7C,0xC6,0xC6,0x7E,0x06,0x0C,0x78,0x00, // 9
0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x00, // :
0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x30, // ;
0x06,0x0C,0x18,0x30,0x18,0x0C,0x06,0x00, // <
0x00,0x00,0x7E,0x00,0x00,0x7E,0x00,0x00, // =
0x60,0x30,0x18,0x0C,0x18,0x30,0x60,0x00, // >
0x7C,0xC6,0x0C,0x18,0x18,0x00,0x18,0x00, // ?
0x7C,0xC6,0xDE,0xDE,0xDE,0xC0,0x78,0x00, // @
0x38,0x6C,0xC6,0xFE,0xC6,0xC6,0xC6,0x00, // A
0xFC,0x66,0x66,0x7C,0x66,0x66,0xFC,0x00, // B
0x3C,0x66,0xC0,0xC0,0xC0,0x66,0x3C,0x00, // C
0xF8,0x6C,0x66,0x66,0x66,0x6C,0xF8,0x00, // D
0xFE,0x62,0x68,0x78,0x68,0x62,0xFE,0x00, // E
0xFE,0x62,0x68,0x78,0x68,0x60,0xF0,0x00, // F
0x3C,0x66,0xC0,0xC0,0xCE,0x66,0x3A,0x00, // G
0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x00, // H
0x3C,0x18,0x18,0x18,0x18,0x18,0x3C,0x00, // I
0x1E,0x0C,0x0C,0x0C,0xCC,0xCC,0x78,0x00, // J
0xE6,0x66,0x6C,0x78,0x6C,0x66,0xE6,0x00, // K
0xF0,0x60,0x60,0x60,0x62,0x66,0xFE,0x00, // L
0xC6,0xEE,0xFE,0xFE,0xD6,0xC6,0xC6,0x00, // M
0xC6,0xE6,0xF6,0xDE,0xCE,0xC6,0xC6,0x00, // N
0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00, // O
0xFC,0x66,0x66,0x7C,0x60,0x60,0xF0,0x00, // P
0x7C,0xC6,0xC6,0xC6,0xC6,0xCE,0x7C,0x0E, // Q
0xFC,0x66,0x66,0x7C,0x6C,0x66,0xE6,0x00, // R
0x7C,0xC6,0x60,0x38,0x0C,0xC6,0x7C,0x00, // S
0x7E,0x7E,0x5A,0x18,0x18,0x18,0x3C,0x00, // T
0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00, // U
0xC6,0xC6,0xC6,0xC6,0xC6,0x6C,0x38,0x00, // V
0xC6,0xC6,0xC6,0xD6,0xD6,0xFE,0x6C,0x00, // W
0xC6,0xC6,0x6C,0x38,0x6C,0xC6,0xC6,0x00, // X
0x66,0x66,0x66,0x3C,0x18,0x18,0x3C,0x00, // Y
0xFE,0xC6,0x8C,0x18,0x32,0x66,0xFE,0x00, // Z
0x3C,0x30,0x30,0x30,0x30,0x30,0x3C,0x00, // [
0xC0,0x60,0x30,0x18,0x0C,0x06,0x02,0x00, // <Backslash>
0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00, // ]
0x10,0x38,0x6C,0xC6,0x00,0x00,0x00,0x00, // ^
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF, // _
0x30,0x18,0x0C,0x00,0x00,0x00,0x00,0x00, // '
0x00,0x00,0x78,0x0C,0x7C,0xCC,0x76,0x00, // a
0xE0,0x60,0x7C,0x66,0x66,0x66,0xDC,0x00, // b
0x00,0x00,0x7C,0xC6,0xC0,0xC6,0x7C,0x00, // c
0x1C,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00, // d
0x00,0x00,0x7C,0xC6,0xFE,0xC0,0x7C,0x00, // e
0x3C,0x66,0x60,0xF8,0x60,0x60,0xF0,0x00, // f
0x00,0x00,0x76,0xCC,0xCC,0x7C,0x0C,0xF8, // g
0xE0,0x60,0x6C,0x76,0x66,0x66,0xE6,0x00, // h
0x18,0x00,0x38,0x18,0x18,0x18,0x3C,0x00, // i
0x06,0x00,0x06,0x06,0x06,0x66,0x66,0x3C, // j
0xE0,0x60,0x66,0x6C,0x78,0x6C,0xE6,0x00, // k
0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00, // l
0x00,0x00,0xEC,0xFE,0xD6,0xD6,0xD6,0x00, // m
0x00,0x00,0xDC,0x66,0x66,0x66,0x66,0x00, // n
0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x7C,0x00, // o
0x00,0x00,0xDC,0x66,0x66,0x7C,0x60,0xF0, // p
0x00,0x00,0x76,0xCC,0xCC,0x7C,0x0C,0x1E, // q
0x00,0x00,0xDC,0x76,0x60,0x60,0xF0,0x00, // r
0x00,0x00,0x7E,0xC0,0x7C,0x06,0xFC,0x00, // s
0x30,0x30,0xFC,0x30,0x30,0x36,0x1C,0x00, // t
0x00,0x00,0xCC,0xCC,0xCC,0xCC,0x76,0x00, // u
0x00,0x00,0xC6,0xC6,0xC6,0x6C,0x38,0x00, // v
0x00,0x00,0xC6,0xD6,0xD6,0xFE,0x6C,0x00, // w
0x00,0x00,0xC6,0x6C,0x38,0x6C,0xC6,0x00, // x
0x00,0x00,0xC6,0xC6,0xC6,0x7E,0x06,0xFC, // y
0x00,0x00,0x7E,0x4C,0x18,0x32,0x7E,0x00, // z
0x0E,0x18,0x18,0x70,0x18,0x18,0x0E,0x00, // {
0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00, // |
0x70,0x18,0x18,0x0E,0x18,0x18,0x70,0x00, // }
0x76,0xDC,0x00,0x00,0x00,0x00,0x00,0x00, // ~
};

uint8_t charBuffer[8][8];

//Load char in buffer and return width in pixels


uint8_t loadCharInBuffer(char letter) {
uint8_t* tmpCharPix;
uint8_t tmpCharWidth;

int letterIdx = (letter - 32) * 8;

int x = 0; int y = 0;
for (int idx = letterIdx; idx < letterIdx + 8; idx++) {
for (int x = 0; x < 8; x++) {
charBuffer[x][y] = ((pgm_read_byte(&font[idx])) & (1 << (7 - x))) > 0;
}
y++;
}

tmpCharWidth = 8;
return tmpCharWidth;
}

void printText(char* text, unsigned int textLength, int xoffset, int yoffset,
unsigned long color) {
uint8_t curLetterWidth = 0;
int curX = xoffset;
clearImg();

//Loop over all the letters in the string


for (int i = 0; i < textLength; i++) {
//Determine width of current letter and load its pixels in a buffer
curLetterWidth = loadCharInBuffer(text[i]);
//Loop until width of letter is reached
for (int lx = 0; lx < curLetterWidth; lx++) {
//Now copy column per column to field (as long as within the field
if (curX >= 12) { //If we are to far to the right, stop loop entirely
break;
} else if (curX >= 0) { //Draw pixels as soon as we are "inside" the
drawing area
for (int ly = 0; ly < 8; ly++) { //Finally copy column
leds[pgm_read_byte(&ledsAdress[yoffset + ly][curX])] =
charBuffer[lx][ly] * color;

}
}
curX++;
}
}
FastLED.show();
}
//Scroll current selection text from right to left;
void scrollText(char* curSelectionText, int curSelectionTextLength, unsigned
long color ) {
for (int x = 12; x > -(curSelectionTextLength * 8); x--) {
printText(curSelectionText, curSelectionTextLength, x, 2, color);
delay(80);
}
}

imgMario.hArduino

const unsigned long mushroom[12][12] PROGMEM = {{0x000000, 0x000000,


0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000},
{0x000000, 0x000000, 0x000000, 0xDF0202, 0xDF0202, 0xDF0202, 0xDF0202,
0xDF0202, 0xDF0202, 0x000000, 0x000000, 0x000000},
{0x000000, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xDF0202, 0xDF0202, 0xDF0202,
0xDF0202, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0x000000},
{0x000000, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xDF0202, 0xDF0202, 0xDF0202,
0xDF0202, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0x000000},
{0xDF0202, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xDF0202, 0xDF0202, 0xDF0202,
0xDF0202, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xDF0202},
{0xDF0202, 0xDF0202, 0xDF0202, 0xDF0202, 0xDF0202, 0xDF0202, 0xDF0202,
0xDF0202, 0xDF0202, 0xDF0202, 0xDF0202, 0xDF0202},
{0xDF0202, 0xDF0202, 0xDF0202, 0xDF0202, 0xDF0202, 0xDF0202, 0xDF0202,
0xDF0202, 0xDF0202, 0xDF0202, 0xDF0202, 0xDF0202},
{0xDF0202, 0xDF0202, 0xFFFFFF, 0x000000, 0x000000, 0xFFFFFF, 0xFFFFFF,
0x000000, 0x000000, 0xFFFFFF, 0xDF0202, 0xDF0202},
{0xDF0202, 0xFFFFFF, 0xFFFFFF, 0x000000, 0x000000, 0xFFFFFF, 0xFFFFFF,
0x000000, 0x000000, 0xFFFFFF, 0xFFFFFF, 0xDF0202},
{0x000000, 0xFFFFFF, 0xFFFFFF, 0x000000, 0x000000, 0xFFFFFF, 0xFFFFFF,
0x000000, 0x000000, 0xFFFFFF, 0xFFFFFF, 0x000000},
{0x000000, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF,
0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0x000000},
{0x000000, 0x000000, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF,
0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0x000000, 0x000000}
};

const unsigned long flower[12][12] PROGMEM = {{0x000000, 0x000000, 0x000000,


0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000},
{0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
{0x000000, 0x000000, 0x000000, 0xFC3205, 0xFC3205, 0xFC3205, 0xFC3205,
0xFC3205, 0xFC3205, 0x000000, 0x000000, 0x000000},
{0x000000, 0x000000, 0xFC3205, 0xFAFE13, 0xFAFE13, 0xFAFE13, 0xFAFE13,
0xFAFE13, 0xFAFE13, 0xFC3205, 0x000000, 0x000000},
{0x000000, 0xFC3205, 0xFAFE13, 0xFFFFFF, 0x000000, 0xFFFFFF, 0xFFFFFF,
0x000000, 0xFFFFFF, 0xFAFE13, 0xFC3205, 0x000000},
{0x000000, 0xFC3205, 0xFAFE13, 0xFFFFFF, 0x000000, 0xFFFFFF, 0xFFFFFF,
0x000000, 0xFFFFFF, 0xFAFE13, 0xFC3205, 0x000000},
{0x000000, 0x000000, 0xFC3205, 0xFAFE13, 0xFAFE13, 0xFAFE13, 0xFAFE13,
0xFAFE13, 0xFAFE13, 0xFC3205, 0x000000, 0x000000},
{0x000000, 0x000000, 0x000000, 0xFC3205, 0xFC3205, 0xFC3205, 0xFC3205,
0xFC3205, 0xFC3205, 0x000000, 0x000000, 0x000000},
{0x000000, 0x0DFC03, 0x0DFC03, 0x000000, 0x000000, 0x0DFC03, 0x0DFC03,
0x000000, 0x000000, 0x0DFC03, 0x0DFC03, 0x000000},
{0x000000, 0x0DFC03, 0x0DFC03, 0x0DFC03, 0x000000, 0x0DFC03, 0x0DFC03,
0x000000, 0x0DFC03, 0x0DFC03, 0x0DFC03, 0x000000},
{0x000000, 0x000000, 0x0DFC03, 0x0DFC03, 0x0DFC03, 0x0DFC03, 0x0DFC03,
0x0DFC03, 0x0DFC03, 0x0DFC03, 0x000000, 0x000000},
{0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x0DFC03, 0x0DFC03,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000}
};

const unsigned long star[12][12] PROGMEM = {{0x000000, 0x000000, 0x000000,


0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000},
{0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0xFAFE13, 0xFAFE13,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
{0x000000, 0x000000, 0x000000, 0x000000, 0xFAFE13, 0xFAFE13, 0xFAFE13,
0xFAFE13, 0x000000, 0x000000, 0x000000, 0x000000},
{0x000000, 0x000000, 0x000000, 0x000000, 0xFAFE13, 0xFAFE13, 0xFAFE13,
0xFAFE13, 0x000000, 0x000000, 0x000000, 0x000000},
{0x000000, 0xFAFE13, 0xFAFE13, 0xFAFE13, 0xFAFE13, 0xFAFE13, 0xFAFE13,
0xFAFE13, 0xFAFE13, 0xFAFE13, 0xFAFE13, 0x000000},
{0x000000, 0x000000, 0xFAFE13, 0xFAFE13, 0x000000, 0xFAFE13, 0xFAFE13,
0x000000, 0xFAFE13, 0xFAFE13, 0x000000, 0x000000},
{0x000000, 0x000000, 0x000000, 0xFAFE13, 0x000000, 0xFAFE13, 0xFAFE13,
0x000000, 0xFAFE13, 0x000000, 0x000000, 0x000000},
{0x000000, 0x000000, 0x000000, 0x000000, 0xFAFE13, 0xFAFE13, 0xFAFE13,
0xFAFE13, 0x000000, 0x000000, 0x000000, 0x000000},
{0x000000, 0x000000, 0x000000, 0x000000, 0xFAFE13, 0xFAFE13, 0xFAFE13,
0xFAFE13, 0x000000, 0x000000, 0x000000, 0x000000},
{0x000000, 0x000000, 0x000000, 0xFAFE13, 0xFAFE13, 0xFAFE13, 0xFAFE13,
0xFAFE13, 0xFAFE13, 0x000000, 0x000000, 0x000000},
{0x000000, 0x000000, 0xFAFE13, 0xFAFE13, 0xFAFE13, 0x000000, 0x000000,
0xFAFE13, 0xFAFE13, 0xFAFE13, 0x000000, 0x000000},
{0x000000, 0xFAFE13, 0xFAFE13, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0xFAFE13, 0xFAFE13, 0x000000}
};

const unsigned long beer[12][12] PROGMEM = {{0x020202, 0x020202, 0x020202,


0x020202, 0x020202, 0x020202, 0x020202, 0x020202, 0x020202, 0x020202,
0x020202, 0x020202},
{0x000000, 0x000000, 0x000000, 0xBEBEBD, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF,
0xBEBEBD, 0x000000, 0x000000, 0x000000, 0x000000},
{0x000000, 0x000000, 0x000000, 0xBEBEBD, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF,
0xBEBEBD, 0x000000, 0x000000, 0x000000, 0x000000},
{0x000000, 0x000000, 0x000000, 0xB49C04, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF,
0xB49C04, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0x000000},
{0x000000, 0x000000, 0x000000, 0xB49C04, 0xFAFE13, 0xFAFE13, 0xFAFE13,
0xB49C04, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0x000000},
{0x000000, 0x000000, 0x000000, 0xB49C04, 0xFAFE13, 0xFAFE13, 0xFAFE13,
0xB49C04, 0x000000, 0x000000, 0xFFFFFF, 0x000000},
{0x000000, 0x000000, 0x000000, 0xB49C04, 0xFAFE13, 0xFAFE13, 0xFAFE13,
0xB49C04, 0x000000, 0x000000, 0xFFFFFF, 0x000000},
{0x000000, 0x000000, 0x000000, 0xB49C04, 0xFAFE13, 0xFAFE13, 0xFAFE13,
0xB49C04, 0x000000, 0x000000, 0xFFFFFF, 0x000000},
{0x000000, 0x000000, 0x000000, 0xB49C04, 0xFAFE13, 0xFAFE13, 0xFAFE13,
0xB49C04, 0x000000, 0x000000, 0xFFFFFF, 0x000000},
{0x000000, 0x000000, 0x000000, 0xB49C04, 0xFAFE13, 0xFAFE13, 0xFAFE13,
0xB49C04, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0x000000},
{0x000000, 0x000000, 0x000000, 0xB49C04, 0xFAFE13, 0xFAFE13, 0xFAFE13,
0xA48E01, 0x000000, 0x000000, 0x000000, 0x000000},
{0x000000, 0x000000, 0x000000, 0xB49C04, 0xB49C04, 0xB49C04, 0xB49C04,
0xB49C04, 0x000000, 0x000000, 0x000000, 0x000000}
};

imgMenu.hArduino

const unsigned long PROGMEM menuError[12][12] = {{0xEF3101, 0xED2D01,


0x040100, 0x040100, 0x000000, 0x000000, 0x000000, 0x000000, 0x040100,
0x040100, 0xEB2801, 0xED2C01},
{0xED2C01, 0xEB2701, 0xE92202, 0x040100, 0x040100, 0x000000, 0x000000,
0x040100, 0x040100, 0xE81F02, 0xEA2301, 0xEB2701},
{0x040100, 0xE92202, 0xE81E01, 0xE61A01, 0x040000, 0x040000, 0x040000,
0x040000, 0xE61601, 0xE61A02, 0xE71D02, 0x040100},
{0x040100, 0x040100, 0xE61901, 0xE51501, 0xE31101, 0x040000, 0x040000,
0xE20F01, 0xE41202, 0xE51501, 0x040100, 0x040100},
{0x000000, 0x040000, 0x040000, 0xE31102, 0xE20D02, 0xE10A02, 0xE00902,
0xE10B02, 0xE20D02, 0x040000, 0x040000, 0x000000},
{0x000000, 0x000000, 0x040000, 0x040000, 0xE10B01, 0xDF0701, 0xDF0602,
0xE00702, 0x040000, 0x040000, 0x000000, 0x000000},
{0x000000, 0x000000, 0x040000, 0x040000, 0xE10902, 0xDF0502, 0xDE0202,
0xDF0501, 0x040000, 0x040000, 0x000000, 0x000000},
{0x000000, 0x040000, 0x040000, 0xE30F02, 0xE10A02, 0xE00702, 0xE00502,
0xE00701, 0xE10A02, 0x040000, 0x040000, 0x000000},
{0x040100, 0x040000, 0xE61601, 0xE41102, 0xE20D02, 0x040000, 0x040000,
0xE10B02, 0xE20D02, 0xE41101, 0x040000, 0x040100},
{0x040100, 0xE81F01, 0xE71A01, 0xE51501, 0x040000, 0x040000, 0x040000,
0x040000, 0xE31202, 0xE51502, 0xE61A01, 0x040100},
{0xEB2801, 0xEA2301, 0xE81E01, 0x040000, 0x040000, 0x000000, 0x000000,
0x040000, 0x040000, 0xE71A01, 0xE81D01, 0xEA2301},
{0xED2C01, 0xEB2801, 0x040100, 0x040000, 0x000000, 0x000000, 0x000000,
0x000000, 0x040000, 0x040000, 0xE92202, 0xEB2701}
};

const unsigned long PROGMEM menuGameOfLife[12][12] = {{0x000000, 0x000000,


0x000000, 0x000000, 0x000000, 0x00FF00, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000},

{0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3,


0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3},
{0xb2a24, 0x2cb194, 0xe281f, 0xc2720, 0xb261f, 0xb241e, 0x8231e, 0xa231f,
0x258d76, 0x8211d, 0x91e19, 0x91e19},
{0xb2823, 0xb2823, 0xa2723, 0x92621, 0x27a285, 0x7251d, 0x25977e, 0x7221d,
0x9201a, 0x9201a, 0x1e7f6b, 0x81b17},
{0x2bb292, 0x2aac90, 0x7281f, 0x27a486, 0xa231f, 0xc231b, 0xa2117,
0x238a75, 0x91f1c, 0x81d18, 0x91c1a, 0x1d775e},
{0x2aad8d, 0xc261d, 0xc251f, 0x9241d, 0x92320, 0xb211e, 0x228c76, 0x23876f,
0x91e19, 0x1e7b68, 0x81b17, 0x71a18},
{0x29aa8e, 0x27a387, 0x8261c, 0xc221f, 0x21967b, 0x248e77, 0x228a73,
0x1f826e, 0x1e7d67, 0x71c15, 0x71a16, 0x1d6c59},
{0xc2521, 0x26a286, 0x269b81, 0x28967d, 0x8211b, 0xa211b, 0x218470,
0xa1d19, 0x91c1a, 0x71c17, 0x81815, 0x61915},
{0xa2520, 0xa231f, 0x25977d, 0x9221c, 0x248a75, 0x1f8770, 0xa1f1a, 0x71c17,
0x81b17, 0x1d6e5b, 0x1a6956, 0x196251},
{0xa2520, 0x25977d, 0x8231c, 0x7221b, 0x92018, 0x22816d, 0x1f7c69,
0x1c7563, 0x91916, 0x61915, 0x196352, 0x71613},
{0x259a7f, 0x8231e, 0x8211b, 0x91f1c, 0x20836e, 0x91e17, 0x71c17, 0x91916,
0x1a6b5a, 0x1a6455, 0x81712, 0x61512},
{0xb211e, 0x82219, 0x228974, 0x22836f, 0x1e7f6b, 0x1d7962, 0x71b19,
0x1b6c59, 0x1a6755, 0x186150, 0x175b4c, 0x514f}
};

const unsigned long PROGMEM menuPong[12][12] = {{0x000000, 0x000000,


0xFF0000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000},

{0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3,


0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3},
{0x000000, 0x000000, 0xFF0000, 0xFF0000, 0xFF0000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
{0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
{0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
{0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0xFF0000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
{0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
{0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
{0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
{0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
{0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
{0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0xFF0000, 0xFF0000, 0xFF0000, 0x000000, 0x000000}
};

const unsigned long PROGMEM menuTetris[12][12] = {{0x00a651, 0x000000,


0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000},

{0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3,


0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3},
{0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
{0x000000, 0x000000, 0x000000, 0x000000, 0xFF0000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
{0x000000, 0x000000, 0x000000, 0xFF0000, 0xFF0000, 0xFF0000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
{0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
{0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0xFF0000, 0xFF0000, 0x000000, 0x000000},
{0xFF0000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0xFF0000, 0xFF0000, 0x4DBB2E, 0x000000},
{0xFF0000, 0xFF0000, 0x4DBB2E, 0x4DBB2E, 0x000000, 0x000000, 0xD4BD0D,
0xD4BD0D, 0xD4BD0D, 0x4DBB2E, 0x4DBB2E, 0xFF0000},
{0xFF0000, 0x0DA5D4, 0x4DBB2E, 0x4DBB2E, 0xFF0000, 0x000000, 0x4DBB2E,
0xD4BD0D, 0x0DA5D4, 0x0DA5D4, 0x4DBB2E, 0xFF0000},
{0x0DA5D4, 0x0DA5D4, 0x0DA5D4, 0x000000, 0xFF0000, 0x4DBB2E, 0x4DBB2E,
0x000000, 0x0DA5D4, 0xD4BD0D, 0xD4BD0D, 0xFF0000},
{0xD4BD0D, 0xD4BD0D, 0xD4BD0D, 0xD4BD0D, 0xFF0000, 0xFF0000, 0x4DBB2E,
0x000000, 0x0DA5D4, 0xD4BD0D, 0xD4BD0D, 0xFF0000}
};

const unsigned long PROGMEM menuSnake[12][12] = {{0x000000, 0x000000,


0x000000, 0xF26522, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000},

{0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3,


0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3},
{0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
{0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
{0x388FEC, 0x388FEC, 0x000000, 0xFF0000, 0x000000, 0x388FEC, 0x388FEC,
0x388FEC, 0x000000, 0x000000, 0x388FEC, 0x388FEC},
{0x000000, 0x388FEC, 0x000000, 0x000000, 0x000000, 0x388FEC, 0x000000,
0x388FEC, 0x000000, 0x000000, 0x388FEC, 0x000000},
{0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x388FEC, 0x000000,
0x388FEC, 0x388FEC, 0x388FEC, 0x388FEC, 0x000000},
{0x000000, 0x000000, 0x388FEC, 0x000000, 0x000000, 0x388FEC, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
{0x000000, 0x000000, 0x388FEC, 0x000000, 0x000000, 0x388FEC, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
{0x000000, 0x000000, 0x388FEC, 0x388FEC, 0x388FEC, 0x388FEC, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
{0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
{0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000}
};

const unsigned long PROGMEM menuSimon[12][12] =


{{0x000000, 0x388FEC, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
{0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3,
0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3},
{0xFFF202, 0xFFF202, 0xFFF20C, 0xFFF202, 0xFFF202, 0x000000, 0x000000,
0xFF0202, 0xFF191A, 0xFF2727, 0xFF1A1A, 0xFF0202},
{0xFFF202, 0xFFF234, 0xFFF257, 0xFFF235, 0xFFF202, 0x000000, 0x000000,
0xFF191A, 0xFF4C4C, 0xFF6767, 0xFF4C4C, 0xFF1A19},
{0xFFF20C, 0xFFF257, 0xFFF898, 0xFFF257, 0xFFF20C, 0x000000, 0x000000,
0xFF2727, 0xFF6767, 0xFF9797, 0xFF6767, 0xFF2726},
{0xFFF202, 0xFFF235, 0xFFF257, 0xFFF234, 0xFFF202, 0x000000, 0x000000,
0xFF1919, 0xFF4C4C, 0xFF6767, 0xFF4C4C, 0xFF1A19},
{0xFFF202, 0xFFF202, 0xFFF20C, 0xFFF202, 0xFFF202, 0x000000, 0x000000,
0xFF0202, 0xFF1A19, 0xFF2626, 0xFF1A1A, 0xFF0202},
{0x34BA20, 0x34BA20, 0x34BA20, 0x34BA20, 0x34BA20, 0x000000, 0x000000,
0x2760B9, 0x4360B9, 0x4F68B9, 0x4360B9, 0x2760B9},
{0x34BA20, 0x48BA40, 0x6BBA63, 0x48BA41, 0x34BA20, 0x000000, 0x000000,
0x4360B9, 0x6D87B9, 0x819ABE, 0x6D86B9, 0x4360B9},
{0x34BA20, 0x6BBA63, 0xACE2A4, 0x6BBA63, 0x34BA20, 0x000000, 0x000000,
0x4F68B9, 0x819ABE, 0xA4BEE1, 0x819BBE, 0x4F68B9},
{0x34BA20, 0x49BA40, 0x6BBA63, 0x48BA41, 0x34BA20, 0x000000, 0x000000,
0x4360B9, 0x6D86B9, 0x819BBE, 0x6D86B9, 0x4360B9},
{0x34BA20, 0x34BA20, 0x34BA20, 0x34BA20, 0x34BA20, 0x000000, 0x000000,
0x2760B9, 0x4360B9, 0x4F68B9, 0x4360B9, 0x2760B9}
};

const unsigned long PROGMEM menuBottle[12][12] =


{{0x000000, 0x000000, 0x000000, 0x000000, 0xFFF200, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
{0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3,
0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3},
{0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
{0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x02F900, 0x0EFA00, 0x1FFB01},
{0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x33FC01, 0x41FE00, 0x4BFE00},
{0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x7BFF02, 0x7AFE02, 0x79FF01},
{0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
{0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
{0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
{0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
{0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
{0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000}
};

const unsigned long PROGMEM menuParty[12][12] = {{0x000000, 0x000000,


0x000000, 0x000000, 0x000000, 0x000000, 0x960055, 0x960055, 0x000000,
0x000000, 0x000000, 0x000000},

{0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3,


0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3},
{0x00A651, 0x00A651, 0x00A651, 0x00A651, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x00A651, 0x00A651},
{0xEC008C, 0xEC008C, 0xEC008C, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0xEC008C, 0xEC008C, 0xEC008C},
{0xF7941D, 0xF7941D, 0xF7941D, 0xF7941D, 0xF7941D, 0xF7941D, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
{0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x00AEEF, 0x00AEEF,
0x00AEEF, 0x00AEEF, 0x00AEEF, 0x00AEEF, 0x000000},
{0xFFF200, 0xFFF200, 0xFFF200, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0xFFF200, 0xFFF200, 0xFFF200},
{0x000000, 0x000000, 0xED1C24, 0xED1C24, 0xED1C24, 0xED1C24, 0xED1C24,
0xED1C24, 0x000000, 0x000000, 0x000000, 0x000000},
{0x2E3192, 0x2E3192, 0x2E3192, 0x2E3192, 0x2E3192, 0x2E3192, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
{0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x00A651,
0x00A651, 0x00A651, 0x00A651, 0x00A651, 0x00A651},
{0x000000, 0x000000, 0x000000, 0xF7941D, 0xF7941D, 0xF7941D, 0xF7941D,
0xF7941D, 0xF7941D, 0x000000, 0x000000, 0x000000},
{0xEC008C, 0xEC008C, 0xEC008C, 0xEC008C, 0xEC008C, 0xEC008C, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000}
};

const unsigned long PROGMEM menuImage[12][12] = {{0x000000, 0x000000,


0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0xFF0000,
0xFF0000, 0x000000, 0x000000},

{0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3,


0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3},
{0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
{0x000000, 0xAC8255, 0xFBBD7B, 0xE8AF72, 0xE8AF72, 0xE8AF72, 0xE8AF72,
0xE8AF72, 0xEAB276, 0xE7A45D, 0x9E6C36, 0x000000},
{0x000000, 0xAD7F4F, 0xF1ECCE, 0xD6FFFF, 0xD4FFFF, 0xDCFFFF, 0xFAFFF9,
0xFFFF3E, 0xFFD529, 0xF4A05C, 0x9D6B36, 0x000000},
{0x000000, 0xAD7F4F, 0xF1ECCE, 0xD6FFFF, 0xD4FFFF, 0xDCFFFF, 0xFAFFFA,
0xFFFF42, 0xFFFF00, 0xF4D31A, 0x9D683A, 0x000000},
{0x000000, 0xAB8959, 0xFF5638, 0xFF0000, 0xFF0000, 0xFF2020, 0xFFDFDF,
0xFFFFFF, 0xFFFFFF, 0xF4D3B0, 0x9D6830, 0x000000},
{0x000000, 0xBD8B4E, 0xFF5731, 0xFF0000, 0xFF0000, 0xFF0000, 0xFE0505,
0xE1BDBE, 0xD5FFFF, 0xDDD3B0, 0x9E6830, 0x000000},
{0x000000, 0xB68959, 0x734338, 0x007100, 0x00BF00, 0x001920, 0x0066DF,
0x0088FF, 0x0080FF, 0x5F89B0, 0xA76E30, 0x000000},
{0x000000, 0xB67F59, 0x73EC38, 0x00FF00, 0x00FF00, 0x00FF00, 0x00FD05,
0x00A1BE, 0x0076FF, 0x5F89B0, 0xA76E30, 0x000000},
{0x000000, 0x9F6D38, 0xD38B3D, 0xC7843C, 0xC7843C, 0xC7843C, 0xC7843C,
0xC7843C, 0xC7843C, 0xD38B3D, 0x9F6D38, 0x000000},
{0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000}
};

const unsigned long PROGMEM menuSpectrum[12][12] = {{0x000000, 0x000000,


0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0xffff00},

{0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3,


0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3},
{0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
{0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x531A8D,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
{0x000000, 0x000000, 0x000000, 0x000000, 0x5E2598, 0x000000, 0x2585A9,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
{0x000000, 0x000000, 0x000000, 0x000000, 0x3696B9, 0x591F93, 0x2585A9,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
{0x000000, 0x000000, 0x000000, 0x642B9E, 0x3696B9, 0x3389AA, 0x2585A9,
0x000000, 0x490F83, 0x000000, 0x000000, 0x000000},
{0x000000, 0x6F36A9, 0x000000, 0x3E9EC1, 0x3C92B3, 0x3389AA, 0x2585A9,
0x4E1488, 0x16769A, 0x000000, 0x000000, 0x000000},
{0x743BAE, 0x4EAED2, 0x000000, 0x3E9DC1, 0x3C92B3, 0x3289AA, 0x2A80A1,
0x217898, 0x167699, 0x000000, 0x000000, 0x000000},
{0x60B7D7, 0x4EAED2, 0x000000, 0x3E9DC1, 0x3C92B3, 0x3289AA, 0x2A80A0,
0x217798, 0x16769A, 0x000000, 0x40077A, 0x000000},
{0x60B7D7, 0x4EAED2, 0x6A30A4, 0x3E9EC1, 0x3C92B3, 0x3289AA, 0x2A80A1,
0x217898, 0x167699, 0x000000, 0x0A698D, 0x3D0376},
{0x60B7D7, 0x57AECE, 0x4FA5C5, 0x459CBC, 0x3C92B3, 0x3389A9, 0x2A80A1,
0x217898, 0x167699, 0x440B7E, 0x09698D, 0x065C7C}
};

const unsigned long PROGMEM menuText[12][12] = {{0x000000, 0x000000,


0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0xFFF200, 0x000000},

{0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3,


0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3, 0xFDCAD3},
{0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
{0xFF0000, 0xFF0000, 0xFF0000, 0xFF0000, 0xFF0000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
{0x000000, 0x000000, 0xFF0000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
{0x000000, 0x000000, 0xFF0000, 0x000000, 0x000000, 0x000000, 0x000000,
0xFF0000, 0xFF0000, 0xFF0000, 0x000000, 0x000000},
{0x000000, 0x000000, 0xFF0000, 0x000000, 0x000000, 0x000000, 0xFF0000,
0x000000, 0x000000, 0x000000, 0xFF0000, 0x000000},
{0x000000, 0x000000, 0xFF0000, 0x000000, 0x000000, 0x000000, 0xFF0000,
0xFF0000, 0xFF0000, 0xFF0000, 0xFF0000, 0x000000},
{0x000000, 0x000000, 0xFF0000, 0x000000, 0x000000, 0x000000, 0xFF0000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000},
{0x000000, 0x000000, 0xFF0000, 0x000000, 0x000000, 0x000000, 0xFF0000,
0x000000, 0x000000, 0x000000, 0xFF0000, 0x000000},
{0x000000, 0x000000, 0xFF0000, 0x000000, 0x000000, 0x000000, 0x000000,
0xFF0000, 0xFF0000, 0xFF0000, 0x000000, 0x000000},
{0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000}
};

pong.hArduino

byte scorePlayerLeft = 0;
byte scorePlayerRight = 0;

byte positionPlayerLeft;
byte positionPlayerRight;

uint8_t ballx;
uint8_t previousBallx;
uint8_t bally;
uint8_t previousBally;
uint8_t velocityx;
uint8_t velocityy;
byte ballBounces;

byte gameSpeed;
//Arduino : Unsigned long !!!!!
unsigned long lastAutoPlayerMoveTime;
unsigned long rumbleUntil;
unsigned long waitUntil;

void setPosition() {
if (!digitalRead(R1_PIN)) {
if (positionPlayerLeft + (3 - 1) / 2 < 12 - 1) {
++positionPlayerLeft;
}
}
else if (!digitalRead(L1_PIN)) {
if (positionPlayerLeft - 3 / 2 > 0) {
--positionPlayerLeft;
}
}
if (!digitalRead(L2_PIN)) {
if (positionPlayerRight - 3 / 2 > 0) {
--positionPlayerRight;
}
}
else if (!digitalRead(R2_PIN)) {
if (positionPlayerRight + (3 - 1) / 2 < 12 - 1) {
++positionPlayerRight;
}

}
curControl = 'n';
}

void checkBallHitByPlayer() {
if (ballx == 1)
{
if (bally == positionPlayerLeft)
{
velocityx = 1;
ballx = 1;
++ballBounces;
rumbleUntil = curTime + 200;
}
else if (bally < positionPlayerLeft && bally >= positionPlayerLeft - 3 /
2)
{
velocityx = 1;
velocityy = max(-1, velocityy - 1);
ballx = 1;
bally = positionPlayerLeft - 3 / 2 - 1;
++ballBounces;
rumbleUntil = curTime + 200;
}
else if (bally > positionPlayerLeft && bally <= positionPlayerLeft + (3 -
1) / 2)
{
velocityx = 1;
velocityy = min(1, velocityy + 1);
ballx = 1;
bally = positionPlayerLeft + (3 - 1) / 2 + 1;
++ballBounces;
rumbleUntil = curTime + 200;
}
}
else if (ballx == 12 - 2)
{
if (bally == positionPlayerRight)
{
velocityx = -1;
ballx = 12 - 2;
++ballBounces;
}
else if (bally < positionPlayerRight && bally >= positionPlayerRight - 3
/ 2)
{
velocityx = -1;
velocityy = max(-1, velocityy - 1);
ballx = 12 - 2;
bally = positionPlayerRight - 3 / 2 - 1;
++ballBounces;
}
else if (bally > positionPlayerRight && bally <= positionPlayerRight + (3
- 1) / 2)
{
velocityx = -1;
velocityy = min(1, velocityy + 1);
ballx = 12 - 2;
bally = positionPlayerRight + (3 - 1) / 2 + 1;
++ballBounces;
}
}
}

void checkBallOutOfBounds() {
if (bally < 1)
{
velocityy = - velocityy;
bally = 0;
//bally = 1;
} else if (bally > 12 -1)
{
velocityy = - velocityy;
bally = 12 - 2;
//bally = 12-1;
}
if (ballx < 0)
{
velocityx = - velocityx;
velocityy = 0;
ballx = 12 / 2;
bally = 12 / 2;
++scorePlayerRight;
ballBounces = 0;
waitUntil = curTime + 2000;
fadeImg();
}
else if (ballx > 12 - 1)
{
velocityx = - velocityx;
velocityy = 0;
ballx = 12 / 2;
bally = 12 / 2;
++scorePlayerLeft;
ballBounces = 0;
waitUntil = curTime + 2000;
fadeImg();
}
}

/*boolean moveAutoPlayer()
{
if (bally < positionPlayerRight)
{
if (positionPlayerRight - 3 / 2 > 0)
{
--positionPlayerRight;
return true;
}
}
else if (bally > positionPlayerRight)
{
if (positionPlayerRight + (3 - 1) / 2 < 12 - 1)
{
++positionPlayerRight;
return true;
}
}
return false;
}*/

void pongInit() {
scorePlayerLeft = 0;
scorePlayerRight = 0;
positionPlayerLeft = 12 / 2;
positionPlayerRight = 12 / 2;
ballx = 12 / 2;
bally = 12 / 2;
velocityx = 1;
velocityy = 0;
ballBounces = 0;
gameSpeed = 180;
lastAutoPlayerMoveTime = 0;
rumbleUntil = 0;
waitUntil = 0;
}

void runPong() {
pongInit();

boolean pongRunning = true;


while (pongRunning) {

if (scorePlayerLeft == 5) {
pongRunning = false;
scrollText("Game over", 9, 0xff0000);
scorePlayerLeft = 0;
scorePlayerRight = 0;
break;
} if (scorePlayerRight == 5) {
pongRunning = false;
scrollText("Game over", 9, 0xff0000);
scorePlayerLeft = 0;
scorePlayerRight = 0;
break;
}

checkBallHitByPlayer();

/* if ((curTime - lastAutoPlayerMoveTime) > 200) {


if (moveAutoPlayer()) {
lastAutoPlayerMoveTime = curTime;
}
}*/

ballx += velocityx;
bally += velocityy;

checkBallOutOfBounds();
for (byte i = 0; i < 12; i++) {
for (byte j = 0; j < 12; j++) {
leds[pgm_read_byte(&ledsAdress[i][j])] = 0x000000;
}
}

// Draw ball
leds[pgm_read_byte(&ledsAdress[ballx][bally])] = 0xffffff;
// Draw player left
for (int y = positionPlayerLeft - 3 / 2; y <= positionPlayerLeft + 3 / 2;
++y) {
leds[pgm_read_byte(&ledsAdress[0][y])] = 0x0000ff;
}
// Draw player right
for (int y = positionPlayerRight - 3 / 2; y <= positionPlayerRight + 3 /
2; ++y) {
leds[pgm_read_byte(&ledsAdress[12 - 1][y])] = 0xffff00;
}

FastLED.show();
boolean dirChanged = false;
do {
if (menuValidation) {
pongRunning = false;
break;
}
readPointer();
if (curControl != 'n' && !dirChanged) { //Can only change direction
once per loop
dirChanged = true;
setPosition();
}
curTime = millis();
}
while ((curTime - prevUpdateTime) < 140); //Once enough time has passed,
proceed. The lower this number, the faster the game is
prevUpdateTime = curTime;
}
}

snake.hArduino

byte curLength;//Curren length of snake


int xs[127];//Array containing all snake segments,
int ys[127];// max snake length is array length
char dir;//Current Direction of snake

boolean snakeGameOver;

byte ax = 0;//Apple x position


byte ay = 0;//Apple y position

void snakeInit() {
//Snake start position and direction & initialise variables
curLength = 3;
xs[0] = 3;
xs[1] = 2;
xs[2] = 1;
ys[0] = 12 / 2;
ys[1] = 12 / 2;
ys[2] = 12 / 2;
dir = 'd';
//Generate random apple position
ax = random(0, 11);
ay = random(0, 11);

snakeGameOver = false;
}
/* Set direction from current button state */
void setDirection() {
readPointer();
switch (curControl) {
case 'q':
dir = 'z';
break;
case 'd':
dir = 's';
break;
case 's':
dir = 'd';
break;
case 'z':
dir = 'q';
break;
}
}
/* Ending, show score */
void die() {
snakeGameOver = true;
fadeImg();
}

/* Collision detection function */


boolean collide(int x1, int x2, int y1, int y2, int w1, int w2, int h1, int
h2) {
if ((x1 + w1 > x2) && (x1 < x2 + w2) && (y1 + h1 > y2) && (y1 < y2 + h2)) {
return true;
} else {
return false;
}
}

void runSnake() {
snakeInit();
prevUpdateTime = 0;
boolean snakeRunning = true;
while (snakeRunning) {
//Check self-collision with snake
int i = curLength - 1;
while (i >= 2) {
if (collide(xs[0], xs[i], ys[0], ys[i], 1, 1, 1, 1)) {
die();
}
i = i - 1;
}

if (snakeGameOver) {
snakeRunning = false;
break;
}

//Check collision of snake head with apple


if (collide(xs[0], ax, ys[0], ay, 1, 1, 1, 1)) {
//Increase score and snake length;
curLength = curLength + 1;
//Add snake segment with temporary position of new segments
xs[curLength - 1] = 255;
ys[curLength - 1] = 255;

//Generate new apple position


ax = random(0, 11);
ay = random(0, 11);

for (int j = 0; j < curLength; j++) {


if (collide(ax, xs[j], ay, ys[j], 1, 1, 1, 1)) {
ax = random(0, 11);
ay = random(0, 11);
j = 0; //ICI
}
}
}

//Shift snake position array by one


i = curLength - 1;
while (i >= 1) {
xs[i] = xs[i - 1];
ys[i] = ys[i - 1];
i = i - 1;
}
//Determine new position of head of snake
if (dir == 'd') {
xs[0] = xs[0] + 1;
} else if (dir == 'q') {
xs[0] = xs[0] - 1;
} else if (dir == 'z') {
ys[0] = ys[0] - 1;
} else {//DOWN
ys[0] = ys[0] + 1;
}

//Check if outside playing field


if ((xs[0] < 0) || (xs[0] >= 12) || (ys[0] < 0) || (ys[0] >= 12)) {
if (xs[0] < 0) {
xs[0] = 12 - 1;
} else if (xs[0] >= 12) {
xs[0] = 0;
} else if (ys[0] < 0) {
ys[0] = 12 - 1;
} else if (ys[0] >= 12) {
ys[0] = 0;
}
}

for (int j = 0; j < 144; j++) {


leds[j] = 0x000000;

//Draw apple
leds[pgm_read_byte(&ledsAdress[ax][ay])] = 0xFF0000;

//Draw snake
for (int j = 0; j < curLength; j++) {
leds[pgm_read_byte(&ledsAdress[xs[j]] [ys[j]])] = 0x388FEC;
}

FastLED.show();

//Check buttons and set snake movement direction while we are waiting to
draw the next move
curTime = 0;
boolean dirChanged = false;
do {
if (menuValidation) {
snakeRunning = false;
break;
}
if (curControl != 'n' && !dirChanged) {//Can only change direction once
per loop
dirChanged = true;
setDirection();
}
curTime = millis();
} while ((curTime - prevUpdateTime) < 200);//Once enough time has
passed, proceed. The lower this number, the faster the game is
prevUpdateTime = curTime;
}

tetris.hArduino

// Playing field
byte selectedColor = 0;
const unsigned long PROGMEM colorLib[5] = {0x000000, 0xff0000, 0xffff00,
0x00ff00, 0x03cdff};
struct Field {
boolean pix[12][12 + 1]; //Make field one larger so that collision
detection with bottom of field can be done in a uniform way
byte color[12][12];
};
Field field;

//Structure to represent active brick on screen


struct Brick {
boolean enabled;//Brick is disabled when it has landed
byte xpos, ypos;
byte yOffset;//Y-offset to use when placing brick at top of field
byte siz;
boolean pix[4][4];

byte color;
};
Brick activeBrick;

//Struct to contain the different choices of blocks


struct AbstractBrick {
byte yOffset;//Y-offset to use when placing brick at top of field
byte siz;
byte pix[4][4];
};

//Brick "library"
AbstractBrick brickLib[7] = {
{
1,//yoffset when adding brick to field
4,
{ {0, 0, 0, 0},
{0, 1, 1, 0},
{0, 1, 1, 0},
{0, 0, 0, 0}
}
},
{
0,
4,
{ {0, 1, 0, 0},
{0, 1, 0, 0},
{0, 1, 0, 0},
{0, 1, 0, 0}
}
},
{
1,
3,
{ {0, 0, 0, 0},
{1, 1, 1, 0},
{0, 0, 1, 0},
{0, 0, 0, 0}
}
},
{
1,
3,
{ {0, 0, 1, 0},
{1, 1, 1, 0},
{0, 0, 0, 0},
{0, 0, 0, 0}
}
},
{
1,
3,
{ {0, 0, 0, 0},
{1, 1, 1, 0},
{0, 1, 0, 0},
{0, 0, 0, 0}
}
},
{
1,
3,
{ {0, 1, 1, 0},
{1, 1, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0}
}
},
{
1,
3,
{ {1, 1, 0, 0},
{0, 1, 1, 0},
{0, 0, 0, 0},
{0, 0, 0, 0}
}
}
};

uint16_t brickSpeed;
byte nbRowsThisLevel;
uint16_t nbRowsTotal;
Brick tmpBrick;
boolean tetrisRunning = false;
boolean tetrisGameOver;

/* *** Game functions *** */


//Check collision between bricks in the field and the specified brick
boolean checkFieldCollision(struct Brick* brick) {
byte bx, by;
byte fx, fy;
for (by = 0; by < 4; by++) {
for (bx = 0; bx < 4; bx++) {
fx = (*brick).xpos + bx;
fy = (*brick).ypos + by;
if (( (*brick).pix[bx][by] == 1)
&& ( field.pix[fx][fy] == 1)) {
return true;
}
}
}
return false;
}

void newActiveBrick() {
// byte selectedBrick = 3;
byte selectedBrick = random(7);
++selectedColor;
if (selectedColor > 3) {
selectedColor = 0;
}
//Set properties of brick
activeBrick.siz = brickLib[selectedBrick].siz;
activeBrick.yOffset = brickLib[selectedBrick].yOffset;
activeBrick.xpos = 12 / 2 - activeBrick.siz / 2;
activeBrick.ypos = -1 - activeBrick.yOffset;
activeBrick.enabled = true;

//Set color of brick


switch (selectedColor) {
case 0 :
activeBrick.color = 1;
break;
case 1 :
activeBrick.color = 2;
break;
case 2 :
activeBrick.color = 3;
break;
case 3 :
activeBrick.color = 4;
break;
}
//activeBrick.color = colorLib[1];

//Copy pix array of selected Brick


for (byte y = 0; y < 4; y++) {
for (byte x = 0; x < 4; x++) {
activeBrick.pix[x][y] = (brickLib[selectedBrick]).pix[x][y];
}
}

//Check collision, if already, then game is over


if (checkFieldCollision(&activeBrick)) {
tetrisGameOver = true;
}
}

//Check collision between specified brick and all sides of the playing field
boolean checkSidesCollision(struct Brick* brick) {
//Check vertical collision with sides of field
byte fx, fy;
for (byte by = 0; by < 4; by++) {
for (byte bx = 0; bx < 4; bx++) {
if ( (*brick).pix[bx][by] == 1) {
fx = (*brick).xpos + bx;//Determine actual position in the field of
the current pix of the brick
fy = (*brick).ypos + by;
if (fx < 0 || fx >= 12) {
return true;
}
}
}
}
return false;
}

void printField() {
for (byte x = 0; x < 12; x++) {
for (byte y = 0; y < 12; y++) {
boolean activeBrickPix = 0;
if (activeBrick.enabled) { //Only draw brick if it is enabled
//Now check if brick is "in view"
if ((x >= activeBrick.xpos) && (x < (activeBrick.xpos +
(activeBrick.siz)))
&& (y >= activeBrick.ypos) && (y < (activeBrick.ypos +
(activeBrick.siz)))) {
activeBrickPix = (activeBrick.pix)[x - activeBrick.xpos][y -
activeBrick.ypos];
}
}
if (field.pix[x][y] == 1) {
leds[pgm_read_byte(&ledsAdress[y][x])] =
pgm_read_dword(&colorLib[field.color[x][y]]);
} else if (activeBrickPix == 1) {
leds[pgm_read_byte(&ledsAdress[y][x])] =
pgm_read_dword(&colorLib[activeBrick.color]);
} else {
leds[pgm_read_byte(&ledsAdress[y][x])] = 0x000000;
}
}
}
FastLED.show();
}
void rotateActiveBrick() {
//Copy active brick pix array to temporary pix array
for (byte y = 0; y < 4; y++) {
for (byte x = 0; x < 4; x++) {
tmpBrick.pix[x][y] = activeBrick.pix[x][y];
}
}
tmpBrick.xpos = activeBrick.xpos;
tmpBrick.ypos = activeBrick.ypos;
tmpBrick.siz = activeBrick.siz;

//Depending on size of the active brick, we will rotate differently


if (activeBrick.siz == 3) {
//Perform rotation around center pix
tmpBrick.pix[0][0] = activeBrick.pix[0][2];
tmpBrick.pix[0][1] = activeBrick.pix[1][2];
tmpBrick.pix[0][2] = activeBrick.pix[2][2];
tmpBrick.pix[1][0] = activeBrick.pix[0][1];
tmpBrick.pix[1][1] = activeBrick.pix[1][1];
tmpBrick.pix[1][2] = activeBrick.pix[2][1];
tmpBrick.pix[2][0] = activeBrick.pix[0][0];
tmpBrick.pix[2][1] = activeBrick.pix[1][0];
tmpBrick.pix[2][2] = activeBrick.pix[2][0];
//Keep other parts of temporary block clear
tmpBrick.pix[0][3] = 0;
tmpBrick.pix[1][3] = 0;
tmpBrick.pix[2][3] = 0;
tmpBrick.pix[3][3] = 0;
tmpBrick.pix[3][2] = 0;
tmpBrick.pix[3][1] = 0;
tmpBrick.pix[3][0] = 0;

} else if (activeBrick.siz == 4) {
//Perform rotation around center "cross"
tmpBrick.pix[0][0] = activeBrick.pix[0][3];
tmpBrick.pix[0][1] = activeBrick.pix[1][3];
tmpBrick.pix[0][2] = activeBrick.pix[2][3];
tmpBrick.pix[0][3] = activeBrick.pix[3][3];
tmpBrick.pix[1][0] = activeBrick.pix[0][2];
tmpBrick.pix[1][1] = activeBrick.pix[1][2];
tmpBrick.pix[1][2] = activeBrick.pix[2][2];
tmpBrick.pix[1][3] = activeBrick.pix[3][2];
tmpBrick.pix[2][0] = activeBrick.pix[0][1];
tmpBrick.pix[2][1] = activeBrick.pix[1][1];
tmpBrick.pix[2][2] = activeBrick.pix[2][1];
tmpBrick.pix[2][3] = activeBrick.pix[3][1];
tmpBrick.pix[3][0] = activeBrick.pix[0][0];
tmpBrick.pix[3][1] = activeBrick.pix[1][0];
tmpBrick.pix[3][2] = activeBrick.pix[2][0];
tmpBrick.pix[3][3] = activeBrick.pix[3][0];
}

//Now validate by checking collision.


//Collision possibilities:
// -Brick now sticks outside field
// -Brick now sticks inside fixed bricks of field
//In case of collision, we just discard the rotated temporary brick
if ((!checkSidesCollision(&tmpBrick)) && (!checkFieldCollision(&tmpBrick)))
{
//Copy temporary brick pix array to active pix array
for (byte y = 0; y < 4; y++) {
for (byte x = 0; x < 4; x++) {
activeBrick.pix[x][y] = tmpBrick.pix[x][y];
}
}
}
}

//Copy active pixels to field, including color


void addActiveBrickToField() {
byte fx, fy;
for (byte by = 0; by < 4; by++) {
for (byte bx = 0; bx < 4; bx++) {
fx = activeBrick.xpos + bx;
fy = activeBrick.ypos + by;

if (fx >= 0 && fy >= 0 && fx < 12 && fy < 12 &&


activeBrick.pix[bx][by]) { //Check if inside playing field
//field.pix[fx][fy] = field.pix[fx][fy] || activeBrick.pix[bx][by];
field.pix[fx][fy] = activeBrick.pix[bx][by];
field.color[fx][fy] = activeBrick.color;
}
}
}
}
//Shift brick left/right/down by one if possible
void shiftActiveBrick(char dir) {
//Change position of active brick (no copy to temporary needed)
if (dir == 'q') {
activeBrick.xpos--;
} else if (dir == 'd') {
activeBrick.xpos++;
} else if (dir == 's') {
activeBrick.ypos++;
}

//Check position of active brick


//Two possibilities when collision is detected:
// -Direction was LEFT/RIGHT, just revert position back
// -Direction was DOWN, revert position and fix block to field on
collision
//When no collision, keep activeBrick coordinates
if ((checkSidesCollision(&activeBrick)) ||
(checkFieldCollision(&activeBrick))) {
//Serial.println("coll");
if (dir == 'q') {
activeBrick.xpos++;
} else if (dir == 'd') {
activeBrick.xpos--;
} else if (dir == 's') {
activeBrick.ypos--;//Go back up one
addActiveBrickToField();
activeBrick.enabled = false;//Disable brick, it is no longer moving
}
}
}

//Move all pix from te field above startRow down by one. startRow is
overwritten
void moveFieldDownOne(byte startRow) {
if (startRow == 0) { //Topmost row has nothing on top to move...
return;
}
byte x, y;
for (y = startRow - 1; y > 0; y--) {
for (x = 0; x < 12; x++) {
field.pix[x][y + 1] = field.pix[x][y];
field.color[x][y + 1] = field.color[x][y];
}
}
}

void checkFullLines() {
int x, y;
int minY = 0;
for (y = (12 - 1); y >= minY; y--) {
byte rowSum = 0;
for (x = 0; x < 12; x++) {
rowSum = rowSum + (field.pix[x][y]);
}
if (rowSum >= 12) {
//Found full row, animate its removal
for (x = 0; x < 12; x++) {
field.pix[x][y] = 0;
printField();
delay(100);
}
//Move all upper rows down by one
moveFieldDownOne(y);
y++; minY++;
printField();
delay(100);

nbRowsThisLevel++; nbRowsTotal++;
if (nbRowsThisLevel >= 2) {
nbRowsThisLevel = 0;
brickSpeed = brickSpeed - 100;
if (brickSpeed < 200) {
brickSpeed = 200;
}
}
}
}
}

void clearField() {
for (byte y = 0; y < 12; y++) {
for (byte x = 0; x < 12; x++) {
field.pix[x][y] = 0;
field.color[x][y] = 0;
}
}
for (byte x = 0; x < 12; x++) { //This last row is invisible to the player
and only used for the collision detection routine
field.pix[x][12] = 1;
}
}

void playerControlActiveBrick() {
switch (curControl) {
case 'd':
shiftActiveBrick('d');
break;
case 'q':
shiftActiveBrick('q');
break;
case 's':
shiftActiveBrick('s');
break;
case 'a':
rotateActiveBrick();
break;
case 'y':
tetrisRunning = false;
break;
}
}

void tetrisInit() {
clearField();
brickSpeed = 1000;
nbRowsThisLevel = 0;
nbRowsTotal = 0;
tetrisGameOver = false;

newActiveBrick();
}

void runTetris(void) {
tetrisInit();

prevUpdateTime = 0;

tetrisRunning = true;
while (tetrisRunning) {
curTime = 0;

do {
readPointer(); //ATTENTION SOURCE BUG ?!
if (menuValidation) {
tetrisRunning = false;
break;
}
if (curControl != 'n') {
playerControlActiveBrick();
printField();
curControl = 'n';
}
if (tetrisGameOver) break;

curTime = millis();
} while ((curTime - prevUpdateTime) < brickSpeed);//Once enough time has
passed, proceed. The lower this number, the faster the game is
prevUpdateTime = curTime;

if (tetrisGameOver) {
fadeImg();

//Disable loop and exit to main menu of led table


tetrisRunning = false;
break;
}

//If brick is still "on the loose", then move it down by one
if (activeBrick.enabled) {
shiftActiveBrick('s');
} else {
//Active brick has "crashed", check for full lines
//and create new brick at top of field
checkFullLines();
newActiveBrick();
prevUpdateTime = millis();//Reset update time to avoid brick dropping
two spaces
}
printField();
}

Audio spectrum visualizerArduino

FischiMc's code adapted to my LED matrix


/*
Written by FischiMc and SupaStefe, modified by Antoine Rochebois (scaling
to 12*12)

This sketch uses a 10x10 RGB LED-Matrix as a spectrum analyzer


It uses a FTT Library to analyze an audio signal connected to the
pin A7 of an Arduino nano. Everytime a column gets higher than
10 pixels the color of each column changes.
*/

#define LOG_OUT 0 //set output of FFT library to linear not


logarithmical
#define LIN_OUT 1
#define FFT_N 256 //set to 256 point fft

#include <FFT.h> //include the FFT library


#include <FastLED.h> //include the FastLED Library
#include <math.h> //include library for mathematic funcions
#define DATA_PIN 5 //DATA PIN WHERE YOUR LEDS ARE CONNECTED
#define NUM_LEDS 144 //amount of LEDs in your matrix
CRGB leds[NUM_LEDS];
float faktoren[12] = {1, 1.1, 1.15, 1.25, 1.35, 1.45, 1.55, 1.65 , 1.75, 1.8,
2, 3}; //factors to increase the height of each column
unsigned char hs[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 , 0};
//height of each column
float hue = 0;
//hue value of the colors

void setBalken(unsigned char column, unsigned char height) {


//calculation of the height of each column
unsigned char h = (unsigned char)map(height, 0, 255, 0, 12);
h = (unsigned char)(h * faktoren[column]);
if (h < hs[column]) {
hs[column]--;
}
else if (h > hs[column]) {
hs[column] = h;
}
if (height > 250) {
hue += 2; //CHANGE THIS VALUE IF YOU WANT THE
DIFFERENCE BETWEEN THE COLORS TO BE BIGGER
if (hue > 25) hue = 0;
}

for (unsigned char y = 0; y < 12; y++) { //set


colors of pixels according to column and hue
if (hs[column] > y) {
if (column % 2 == 0) {
leds[y + (column * 12)] = CHSV((hue * 12) + (column * 12), 255, 200);
} else {
leds[12 - y + (column * 12)] = CHSV((hue * 12) + (column * 12), 255,
200);
}

} else {
if (column % 2 == 0) {
leds[y + (column * 12)] = CRGB::Black;
} else {
leds[12 - y + (column * 12)] = CRGB::Black;
}
}
}
}

unsigned char grenzen[13] = {0, 3, 5, 7, 9, 11, 13, 15, 17, 20, 24, 32, 69};
//borders of the frequency areas

void setup() {
FastLED.addLeds<WS2812B, DATA_PIN, GRB> (leds, NUM_LEDS);
TIMSK0 = 0; //turn
off timer0 for lower jitter
ADCSRA = 0xe5; //set the
adc to free running mode
ADMUX = 0x40; //use pin A0
DIDR0 = 0x01; //turn
off the digital input for
analogReference(EXTERNAL); //set
aref to external
}

void loop() {
while (1) { //reduces
jitter
cli(); //UDRE
interrupt slows this way down on arduino1.0
for (int i = 0 ; i < 512 ; i += 2) { //save
256 samples
while (!(ADCSRA & 0x10)); //wait
for adc to be ready
ADCSRA = 0xf5; //restart
adc
byte m = ADCL; //fetch
adc data
byte j = ADCH;
int k = (j << 8) | m; //form
into an int
k -= 0x0200; //form
into a signed int
k <<= 6; //form
into a 16b signed int
fft_input[i] = k; //put
real data into even bins
}

fft_window(); // window
the data for better frequency response
fft_reorder(); //
reorder the data before doing the fft
fft_run(); //
process the data in the fft
fft_mag_lin(); // take
the output of the fft
sei();

fft_lin_out[0] = 0;
fft_lin_out[1] = 0;

for (unsigned char i = 0; i < 13; i++) {


unsigned char maxW = 0;
for (unsigned char x = grenzen[i]; x < grenzen[i + 1]; x++) {

if ((unsigned char)fft_lin_out[x] > maxW) {


maxW = (unsigned char)fft_lin_out[x];
}
}

setBalken(i, maxW);

}
TIMSK0 = 1;
FastLED.show();
TIMSK0 = 0;
}
}

Custom parts and enclosures


Main interface panel

Download
On this panel you'll find the main control buttons, audio IO and the USB port used to upload the
code on the Arduino Nano.

Made on Fusion360

Comments
Author

Antoine Rochebois

 1 project
 23 followers

Follow

Additional contributors

 Base for the fft-based spectrum analyzer code by FischiMc

Published on

August 22, 2017


Respect project
Write a comment
Share

Members who respect this project

and 115 others


See similar projects
you might like

Table of contents

 5 Minute Christmas Neopixel Led Strip


 Components and supplies
 Necessary tools and machines
 Apps and online services
 About this project
 Code
 Schematics
 Comments(19)

Respect project
Write a comment
Share

Similar projects you might like

Arbalet is a touch table made of 150 LEDs. Play Tetris Snake or Piano on your coffee table, or
develop your own Python apps!

Touch LED Table - Retrogaming And Ambiant Light

Project tutorial by Arbalet Project

 7,887 views
 1 comment
 38 respects

Create an awesome looking motion activated RGB lights for any staircase under $20!

Automated Staircase RGB LED Lights

Project tutorial by Team NotEnoughTech.com

 27,618 views
 19 comments
 99 respects
Tthis project is going to show you how to make Bluetooth led control with lcd beside the
Arduino sowing the new led status.

Bluetooth control led with lcd led status display real time.

Project tutorial by Youssef Sabaa

 17,312 views
 4 comments
 34 respects

Name on a box that lights up and has three different patterns that provide a cool light show.

Interactive LED Name

Project tutorial by Pedro Mendez and Daniel Jablonski

 1,872 views
 1 comment
 5 respects

"Otto DIY with steroids" + Bluetooth + APP + switch + touch sensors + strength + sound
detection...

Otto DIY+ Arduino Bluetooth Robot Easy to 3D Print

Project tutorial by Team Otto builders

 48,222 views
 117 comments
 162 respects

Using 64 LED to create a cube, it separates to 4 layers and every layer have 16 LED which is
connecting each other layer.

Interactive 4x4x4 LED cube

Project tutorial by Tong Xin Hua

 1,608 views
 0 comments
 0 respects
Powered by

Good to see you again

Keep me signed in on this device


Forgot your password?

Or connect with your social account:

Login with Arduino

New here? Create an account

Add projectSign up / Login

Anda mungkin juga menyukai