#define CLK 13
#define DIN 11
#define CS 10
#define X_SEGMENTS 4
#define Y_SEGMENTS 2
#define NUM_SEGMENTS (X_SEGMENTS * Y_SEGMENTS)
#define rb 5
#define gb 4
#define yb 6
#define bb 7
// a framebuffer to hold the state of the entire matrix of LEDs
// laid out in raster order, with (0, 0) at the top-left
byte fb[8 * NUM_SEGMENTS];
//coord matrix for lit up leds
int matrix[16][32];
// array of snake coordinates (fir line for x, second line for y)
int snake[2][16*32];
int len = 1;
bool gameOver = false;
int dir = 0; // 0 - left, 1 - up, 2 - right, 3 - down
unsigned long start = millis();
void shiftAll(byte send_to_address, byte send_this_data){
//start communication
digitalWrite(CS, LOW);
for (int i = 0; i < NUM_SEGMENTS; i++) {
//send an address and the data
shiftOut(DIN, CLK, MSBFIRST, send_to_address);
shiftOut(DIN, CLK, MSBFIRST, send_this_data);
}
digitalWrite(CS, HIGH);
}
void matrixToDisplay(int matrix[][32]){
int v;
int fb_ind = 63;
for(int line_ind = 0; line_ind < 16; ++line_ind){
for(int col_ind = 0; col_ind < 32; col_ind += 8){
v = 0;
for(int i=0; i<8; ++i){
v |= ((matrix[line_ind][col_ind + 7 - i] > 0) << i); //sau la shiftare 7-i
fb[fb_ind] = v;
}
--fb_ind;
}
}
}
void generateFruit(){
int fruit_line = rand() % 16;
int fruit_col = rand() % 32;
matrix[fruit_line][fruit_col] = 2;
}
void setup() {
Serial.begin(115200);
pinMode(CLK, OUTPUT);
pinMode(DIN, OUTPUT);
pinMode(CS, OUTPUT);
// Setup each MAX7219
shiftAll(0x0f, 0x00); //display test register - test mode off
shiftAll(0x0b, 0x07); //scan limit register - display digits 0 thru 7
shiftAll(0x0c, 0x01); //shutdown register - normal operation
shiftAll(0x0a, 0x0f); //intensity register - max brightness
shiftAll(0x09, 0x00); //decode mode register - No decode
pinMode(23, OUTPUT);
pinMode(bb, INPUT);
pinMode(gb, INPUT);
pinMode(rb, INPUT);
pinMode(yb, INPUT);
srand(analogRead(0));
generateFruit();
snake[0][0] = rand() % 32;
snake[1][0] = rand() % 16;
matrix[snake[1][0]][snake[0][0]] = 1;
}
void show(int matrix[][32]) {
matrixToDisplay(matrix);
for (byte row = 0; row < 8; row++) {
digitalWrite(CS, LOW);
byte segment = NUM_SEGMENTS;
while (segment--) {
//compute row and column
byte x = segment % X_SEGMENTS;
byte y = segment / X_SEGMENTS * 8;
//compute address given the above
byte addr = (row + y) * X_SEGMENTS;
// odd rows of segments
if (segment & X_SEGMENTS) {
shiftOut(DIN, CLK, MSBFIRST, 8 - row); //?????
shiftOut(DIN, CLK, LSBFIRST, fb[addr + x]);
} else {
shiftOut(DIN, CLK, MSBFIRST, 1 + row);
shiftOut(DIN, CLK, MSBFIRST, fb[addr - x + X_SEGMENTS - 1]);
}
}
digitalWrite(CS, HIGH);
}
}
void updateSnakeCoords(){
int head_x = snake[0][0];
int head_y = snake[1][0];
int tail_x = snake[0][len-1];
int tail_y = snake[1][len-1];
int new_head_x = head_x, new_head_y = head_y, new_tail_x = tail_x, new_tail_y = tail_y;
switch(dir){
case 0:{
if(head_x == 0){
new_head_x = 31;
}else{
new_head_x = head_x - 1;
}
break;
}
case 1:{
if(head_y == 0){
new_head_y = 15;
}else{
new_head_y = head_y - 1;
}
break;
}
case 2:{
if(head_x == 31){
new_head_x = 0;
}else{
new_head_x = head_x + 1;
}
break;
}
case 3:{
if(head_y == 15){
new_head_y = 0;
}else{
new_head_y = head_y + 1;
}
break;
}
}
//right shift of coordinates
for(int i = len-1; i >= 0; --i){
snake[0][i+1] = snake[0][i];
snake[1][i+1] = snake[1][i];
}
if(matrix[new_head_y][new_head_x] == 2){
len++;
generateFruit();
}else if(matrix[new_head_y][new_head_x] == 1){
gameOver = true;
Serial.println("GAME OVER");
}
else{
matrix[tail_y][tail_x] = 0;
}
//updating head coordinates and displaying it
snake[0][0] = new_head_x;
snake[1][0] = new_head_y;
matrix[snake[1][0]][snake[0][0]] = 1;
}
bool updateDirection(){
bool changed = false;
byte rbtn = digitalRead(rb);
byte gbtn = digitalRead(gb);
byte bbtn = digitalRead(bb);
byte ybtn = digitalRead(yb);
if (rbtn==1){
changed = (dir!=3);
dir = 3;
}else if(gbtn == 1){
changed = (dir!=2);
dir = 2;
}else if(bbtn == 1){
changed = (dir!=1);
dir = 1;
}else if(ybtn == 1){
changed = (dir!=0);
dir = 0;
}
return changed;
// if (rbtn==1){
// changed = (dir=3)!=dir;
// }else if(gbtn == 1){
// changed = (dir=2)!=dir;
// }else if(bbtn == 1){
// changed = (dir=1)!=dir;
// }else if(ybtn == 1){
// changed = (dir=0)!=dir;
// }
// return changed;
}
void loop() {
//as putea sa adaug un delay la care se poate da update la directie
if(!gameOver){
// matrix[4][4] = 1;
if(updateDirection() || millis() - start > 367){
updateSnakeCoords();
start = millis();
}
show(matrix);
// byte rbtn = digitalRead(5);
// if (rbtn==1) digitalWrite(23,1);
// else digitalWrite(23,0);
}
}