#include <MD_MAX72xx.h>
#include <string.h>
#define MAX_DEVICES 15
const int maxX = MAX_DEVICES * 8 - 1;
const int maxY = 7;
#define CLK_PIN 13
#define DATA_PIN 11
#define CS_PIN 10
#define EXPR_NEUTRAL 0
#define EXPR_ANGRY 1
#define EXPR_SAD 2
#define EXPR_HAPPY 3
MD_MAX72XX mx = MD_MAX72XX(MD_MAX72XX::PAROLA_HW, CS_PIN, MAX_DEVICES);
int x = 0;
int y = 0;
void setPoint(int y, int x, bool state)
{
if(x < maxX && x >= 0)
mx.setPoint(y,x,state);
}
void screenText(String text, int offset1)
{
mx.clear();
for(int i = 0; i < text.length(); i++)
{
int offset = (maxX-(i*6)-0) + offset1;
mx.setFont(nullptr);
mx.setChar(offset, text[i]);
}
mx.transform(MD_MAX72XX::TFLR);
mx.transform(MD_MAX72XX::TFUD);
//mx.transform(MD_MAX72XX::TSU);
mx.update();
}
void vainstainsLogo(int x = 0)
{
int upperOffset = 72 + x;
//#### #### ######## ########
//#### #### ######## ###### ##
//#### #### #### ####
//#### #### ######## ## ######
//#### #### ######## ########
//
//########## ######## ######
// ######## ## ##
// ######## ## ##
//########## ######## ######
//
//#### #### ######## ########
//#### #### ## ## ## ######
// ## ## #### ####
//#### #### ## ## ###### ##
//#### #### ######## ########
//lower half
setPoint(0,0+x,true);
setPoint(1,0+x,true);
setPoint(0,1+x,true);
setPoint(1,1+x,true);
setPoint(3,0+x,true);
setPoint(4,0+x,true);
setPoint(3,1+x,true);
setPoint(4,1+x,true);
setPoint(0,3+x,true);
setPoint(1,3+x,true);
setPoint(0,4+x,true);
setPoint(1,4+x,true);
setPoint(3,3+x,true);
setPoint(4,3+x,true);
setPoint(3,4+x,true);
setPoint(4,4+x,true);
setPoint(0,6+x,true);
setPoint(0,7+x,true);
setPoint(0,8+x,true);
setPoint(0,9+x,true);
setPoint(1,9+x,true);
setPoint(2,9+x,true);
setPoint(3,9+x,true);
setPoint(4,9+x,true);
setPoint(4,8+x,true);
setPoint(4,7+x,true);
setPoint(4,6+x,true);
setPoint(3,6+x,true);
setPoint(2,6+x,true);
setPoint(1,6+x,true);
setPoint(0,11+x,true);
setPoint(0,12+x,true);
setPoint(0,13+x,true);
setPoint(0,14+x,true);
setPoint(1,11+x,true);
setPoint(1,12+x,true);
setPoint(1,13+x,true);
setPoint(1,15+x,true);
setPoint(2,11+x,true);
setPoint(2,12+x,true);
setPoint(2,14+x,true);
setPoint(2,15+x,true);
setPoint(3,11+x,true);
setPoint(3,13+x,true);
setPoint(3,14+x,true);
setPoint(3,15+x,true);
setPoint(4,12+x,true);
setPoint(4,13+x,true);
setPoint(4,14+x,true);
setPoint(4,15+x,true);
setPoint(6,0+x,true);
setPoint(6,1+x,true);
setPoint(6,2+x,true);
setPoint(6,3+x,true);
setPoint(6,4+x,true);
setPoint(6,6+x,true);
setPoint(6,7+x,true);
setPoint(6,8+x,true);
setPoint(6,9+x,true);
setPoint(7,6+x,true);
setPoint(7,7+x,true);
setPoint(7,8+x,true);
setPoint(7,9+x,true);
setPoint(7,11+x,true);
setPoint(6,12+x,true);
setPoint(6,13+x,true);
setPoint(6,14+x,true);
setPoint(7,15+x,true);
//top half
setPoint(1,upperOffset,true);
setPoint(1,upperOffset+1,true);
setPoint(1,upperOffset+2,true);
setPoint(1,upperOffset+3,true);
setPoint(1,upperOffset+4,true);
setPoint(0,upperOffset+6,true);
setPoint(0,upperOffset+7,true);
setPoint(0,upperOffset+8,true);
setPoint(0,upperOffset+9,true);
setPoint(1,upperOffset+6,true);
setPoint(1,upperOffset+7,true);
setPoint(1,upperOffset+8,true);
setPoint(1,upperOffset+9,true);
setPoint(0,upperOffset+11,true);
setPoint(1,upperOffset+12,true);
setPoint(1,upperOffset+13,true);
setPoint(1,upperOffset+14,true);
setPoint(0,upperOffset+15,true);
setPoint(3,upperOffset,true);
setPoint(3,upperOffset+1,true);
setPoint(3,upperOffset+3,true);
setPoint(3,upperOffset+4,true);
setPoint(4,upperOffset,true);
setPoint(4,upperOffset+1,true);
setPoint(4,upperOffset+3,true);
setPoint(4,upperOffset+4,true);
setPoint(5,upperOffset,true);
setPoint(5,upperOffset+1,true);
setPoint(5,upperOffset+3,true);
setPoint(5,upperOffset+4,true);
setPoint(6,upperOffset,true);
setPoint(6,upperOffset+1,true);
setPoint(6,upperOffset+3,true);
setPoint(6,upperOffset+4,true);
setPoint(7,upperOffset,true);
setPoint(7,upperOffset+1,true);
setPoint(7,upperOffset+3,true);
setPoint(7,upperOffset+4,true);
setPoint(3,upperOffset+6,true);
setPoint(4,upperOffset+6,true);
setPoint(3,upperOffset+7,true);
setPoint(4,upperOffset+7,true);
setPoint(3,upperOffset+8,true);
setPoint(4,upperOffset+8,true);
setPoint(3,upperOffset+9,true);
setPoint(4,upperOffset+9,true);
setPoint(6,upperOffset+6,true);
setPoint(7,upperOffset+6,true);
setPoint(6,upperOffset+7,true);
setPoint(7,upperOffset+7,true);
setPoint(6,upperOffset+8,true);
setPoint(7,upperOffset+8,true);
setPoint(6,upperOffset+9,true);
setPoint(7,upperOffset+9,true);
setPoint(7,upperOffset+11,true);
setPoint(7,upperOffset+12,true);
setPoint(7,upperOffset+13,true);
setPoint(7,upperOffset+14,true);
setPoint(6,upperOffset+11,true);
setPoint(6,upperOffset+12,true);
setPoint(6,upperOffset+13,true);
setPoint(6,upperOffset+15,true);
setPoint(5,upperOffset+11,true);
setPoint(5,upperOffset+12,true);
setPoint(5,upperOffset+14,true);
setPoint(5,upperOffset+15,true);
setPoint(4,upperOffset+11,true);
setPoint(4,upperOffset+13,true);
setPoint(4,upperOffset+14,true);
setPoint(4,upperOffset+15,true);
setPoint(3,upperOffset+12,true);
setPoint(3,upperOffset+13,true);
setPoint(3,upperOffset+14,true);
setPoint(3,upperOffset+15,true);
}
void setup() {
mx.begin();
mx.control(MD_MAX72XX::INTENSITY, MAX_INTENSITY/2);
mx.control(MD_MAX72XX::UPDATE, false);
float vel = 1;
float pos = 45;
for(int i = 0; i < 300; i++)
{
pos += vel;
vel += pos*-0.002;
vel *= 0.965;
mx.clear();
vainstainsLogo(int(pos*2));
mx.update();
}
delay(1000);
mx.clear();
delay(500);
screenText("Loadi ng", 0);
delay(500);
mx.clear();
delay(500);
pinMode(A0, INPUT);
pinMode(A1, INPUT);
pinMode(A2, INPUT);
pinMode(2, INPUT);
Serial.begin(9600);
}
float mouthOpen = 0.0;
float leftEyeOpen = 0.0;
float rightEyeOpen = 0.0;
int expr = 0;
int ticks = 0;
void rightMouth()
{
int openLevel1 = int((mouthOpen*0.75)+2);
int openLevel2 = int((mouthOpen*1.25)+2);
int i = 0;
for(i = 0; i < openLevel1; i++)
{
mx.setPoint(5-i,0,true);
mx.setPoint(5-i,1,true);
mx.setPoint(5-i,5,true);
mx.setPoint(5-i,6,true);
mx.setPoint(5-i,7,true);
mx.setPoint(5-i,8,true);
mx.setPoint(5-i,9,true);
mx.setPoint(5-i,10,true);
mx.setPoint(5-i,11,true);
mx.setPoint(5-i,12,true);
mx.setPoint(5-i,13,true);
mx.setPoint(4-i,14,true);
mx.setPoint(4-i,15,true);
mx.setPoint(4-i,16,true);
mx.setPoint(4-i,17,true);
mx.setPoint(4-i,18,true);
mx.setPoint(3-i,19,true);
mx.setPoint(3-i,20,true);
mx.setPoint(3-i,21,true);
mx.setPoint(2-i,22,true);
mx.setPoint(2-i,23,true);
}
for(i = 0; i < openLevel1+1; i++)
{
mx.setPoint(6-i,2,true);
mx.setPoint(6-i,4,true);
}
for(i = 0; i < openLevel1+2; i++)
{
mx.setPoint(7-i,3,true);
}
for(i = 0; i < openLevel2; i++)
{
mx.setPoint(3-i,24,true);
mx.setPoint(3-i,25,true);
mx.setPoint(4-i,26,true);
mx.setPoint(4-i,27,true);
mx.setPoint(5-i,28,true);
mx.setPoint(5-i,29,true);
mx.setPoint(4-i,30,true);
mx.setPoint(4-i,31,true);
}
}
void leftMouth()
{
int openLevel1 = int((mouthOpen*0.75)+2);
int openLevel2 = int((mouthOpen*1.25)+2);
int i = 0;
for(i = 0; i < openLevel1; i++)
{
mx.setPoint(5-i,71,true);
mx.setPoint(5-i,70,true);
mx.setPoint(5-i,66,true);
mx.setPoint(5-i,65,true);
mx.setPoint(5-i,64,true);
mx.setPoint(5-i,63,true);
mx.setPoint(5-i,62,true);
mx.setPoint(5-i,61,true);
mx.setPoint(5-i,60,true);
mx.setPoint(5-i,59,true);
mx.setPoint(5-i,58,true);
mx.setPoint(4-i,57,true);
mx.setPoint(4-i,56,true);
mx.setPoint(4-i,55,true);
mx.setPoint(4-i,54,true);
mx.setPoint(4-i,53,true);
mx.setPoint(3-i,52,true);
mx.setPoint(3-i,51,true);
mx.setPoint(3-i,50,true);
mx.setPoint(2-i,49,true);
mx.setPoint(2-i,48,true);
mx.setPoint(3-i,47,true);
mx.setPoint(3-i,46,true);
mx.setPoint(4-i,45,true);
mx.setPoint(4-i,44,true);
mx.setPoint(5-i,43,true);
mx.setPoint(5-i,42,true);
mx.setPoint(4-i,41,true);
mx.setPoint(4-i,40,true);
}
for(i = 0; i < openLevel1+1; i++)
{
mx.setPoint(6-i,69,true);
mx.setPoint(6-i,67,true);
}
for(i = 0; i < openLevel1+2; i++)
{
mx.setPoint(7-i,68,true);
}
for(i = 0; i < openLevel2; i++)
{
mx.setPoint(3-i,47,true);
mx.setPoint(3-i,46,true);
mx.setPoint(4-i,45,true);
mx.setPoint(4-i,44,true);
mx.setPoint(5-i,43,true);
mx.setPoint(5-i,42,true);
mx.setPoint(4-i,41,true);
mx.setPoint(4-i,40,true);
}
}
void middleMouth()
{
int openLevel1 = int((mouthOpen*1.15)+2);
int i = 0;
if(openLevel1 > 3)
i--;
for(; i < openLevel1; i++)
{
mx.setPoint(3-i,32,true);
mx.setPoint(4-i,33,true);
mx.setPoint(5-i,34,true);
mx.setPoint(6-i,35,true);
mx.setPoint(6-i,36,true);
mx.setPoint(5-i,37,true);
mx.setPoint(4-i,38,true);
mx.setPoint(3-i,39,true);
}
}
void eye(float open, int start, bool reverse)
{
int i = 0;
int sign = reverse?-1:1;
int start1 = start + (reverse?15:0);
mx.setPoint(6,start1+sign*20,true);
mx.setPoint(6,start1+sign*21,true);
mx.setPoint(6,start1+sign*22,true);
mx.setPoint(5,start1+sign*22,true);
mx.setPoint(4,start1+sign*22,true);
mx.setPoint(3,start1+sign*22,true);
int openLevel1;
switch(expr)
{
case EXPR_NEUTRAL:
openLevel1 = int((open*2.4)+1);
for(i = 3; i < 16; i++)
{
mx.setPoint(openLevel1,sign*i+start1,true);
}
for(i = 3; i < min(7, openLevel1); i++)
{
mx.setPoint(i,start1+sign*6,true);
mx.setPoint(i,start1+sign*13,true);
}
for(i = 2; i < min(7, openLevel1); i++)
{
mx.setPoint(i,start1+sign*7,true);
mx.setPoint(i,start1+sign*12,true);
}
for(i = 1; i < min(7, openLevel1); i++)
{
mx.setPoint(i,start1+sign*8,true);
mx.setPoint(i,start1+sign*9,true);
mx.setPoint(i,start1+sign*10,true);
mx.setPoint(i,start1+sign*11,true);
}
break;
case EXPR_ANGRY:
openLevel1 = int((open*2)+2);
for(i = 3; i < 13; i++)
{
mx.setPoint(openLevel1-(i/5),sign*i+start1,true);
}
mx.setPoint(openLevel1-3,sign*13+start1,true);
mx.setPoint(openLevel1-3,sign*14+start1,true);
mx.setPoint(openLevel1-2,sign*15+start1,true);
for(i = 3; i < min(7, openLevel1); i++)
{
mx.setPoint(i,start1+sign*6,true);
}
for(i = 3; i < min(7, openLevel1-2); i++)
{
mx.setPoint(i,start1+sign*13,true);
}
for(i = 2; i < min(7, openLevel1-1); i++)
{
mx.setPoint(i,start1+sign*7,true);
mx.setPoint(i,start1+sign*12,true);
}
for(i = 1; i < min(7, openLevel1-1); i++)
{
mx.setPoint(i,start1+sign*8,true);
mx.setPoint(i,start1+sign*9,true);
mx.setPoint(i,start1+sign*10,true);
mx.setPoint(i,start1+sign*11,true);
}
break;
case EXPR_SAD:
openLevel1 = int((open*2)+2);
for(i = 3; i < 16; i++)
{
mx.setPoint((openLevel1-3)+(i/5),sign*i+start1,true);
}
for(i = 3; i < min(7, openLevel1-2); i++)
{
mx.setPoint(i,start1+sign*6,true);
}
for(i = 3; i < min(7, openLevel1-1); i++)
{
mx.setPoint(i,start1+sign*13,true);
}
for(i = 2; i < min(7, openLevel1-1); i++)
{
mx.setPoint(i,start1+sign*7,true);
mx.setPoint(i,start1+sign*12,true);
}
for(i = 1; i < min(7, openLevel1-1); i++)
{
mx.setPoint(i,start1+sign*8,true);
mx.setPoint(i,start1+sign*9,true);
mx.setPoint(i,start1+sign*10,true);
mx.setPoint(i,start1+sign*11,true);
}
break;
case EXPR_HAPPY:
for(i = 0; i < 3; i++)
{
mx.setPoint(3-i,sign*2+start1,true);
mx.setPoint(3-i,sign*3+start1,true);
mx.setPoint(4-i,sign*4+start1,true);
mx.setPoint(4-i,sign*5+start1,true);
mx.setPoint(5-i,sign*6+start1,true);
mx.setPoint(5-i,sign*7+start1,true);
mx.setPoint(6-i,sign*8+start1,true);
mx.setPoint(6-i,sign*9+start1,true);
mx.setPoint(5-i,sign*10+start1,true);
mx.setPoint(5-i,sign*11+start1,true);
mx.setPoint(4-i,sign*12+start1,true);
mx.setPoint(4-i,sign*13+start1,true);
mx.setPoint(3-i,sign*14+start1,true);
mx.setPoint(3-i,sign*15+start1,true);
}
break;
}
}
void draw()
{
if(ticks > 800)
rightMouth();
if(ticks > 700)
leftMouth();
if(ticks > 500)
middleMouth();
if(ticks > 50 && (ticks < 192 || ticks > 745))
eye(leftEyeOpen, 72, false);
if(ticks > 80 && (ticks < 312 || ticks > 465))
eye(rightEyeOpen, 104, true);
}
// the loop function runs over and over again forever
int upd = 0;
int updates = 0;
int lastState = 0;
void loop()
{
upd++;
expr += max(digitalRead(2)-lastState, 0);
expr %= 4;
lastState = digitalRead(2);
ticks++;
if(ticks > 1000)
ticks--;
if(upd < 40)
{
return;
}
upd = 0;
mouthOpen = analogRead(A0)/400.0;
leftEyeOpen = analogRead(A1)/400.0;
rightEyeOpen = analogRead(A2)/400.0;
updates++;
if(updates > 100)
{
updates = 0;
leftEyeOpen = 0;
rightEyeOpen = 0;
}
mx.clear();
draw();
mx.update();
delay(10);
}