PixelBrite

Part 1 by Kohpai @ ESL KMITL

Software Design

State Machine

Arduino

Sample Code

#include <Adafruit_NeoPixel.h>
#include <TimerOne.h>
#include <SPI.h>
#include <SD.h>

#define SEL_SGL_OR_GRP 0
#define SEL_IMG_OR_TXT 1
#define SEL_IMG 2
#define RCV_TXT 3

#define MODE_SINGLE 0
#define MODE_GROUP 1

#define PIN 6

/* snake defines */

#define UP 1
#define DOWN 2
#define RIGHT 3
#define LEFT 4

uint8_t state;
char cmd[3];
volatile long curTime, startTime;
uint8_t mode;
Adafruit_NeoPixel strip = Adafruit_NeoPixel(100, PIN, NEO_RGB + NEO_KHZ800); // change this ? !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
File myFile;

/* snake's variable */

uint8_t sizeSnake, applePosition, vector;
uint8_t snake[100];



void setup() 
{    
    Serial.begin(9600);
    
    Timer1.initialize(1000000);
    strip.begin();
    strip.show();
    
    while (true) {
        Serial.print("Initializing SD card...");
  
        if (SD.begin(4)) {
            Serial.println("initialization done");
            
            break;
        }
        Serial.println("initialization failed!");
        initFailed();
    }
    
    initOkay();
    
    state = SEL_SGL_OR_GRP;
    curTime = startTime = 0;
    
}

void loop() 
{
    
NEW_STATE: 
    if (read_CMD()) {
       
        switch (state) {
            case SEL_SGL_OR_GRP :
                Serial.write(cmd);
                
                if (compare_CMD(cmd, "<S>")) {
                    mode = MODE_SINGLE;
                    state = SEL_IMG_OR_TXT;
                }
                else if  (compare_CMD(cmd, "<G>")) {
                    mode = MODE_GROUP;
                    state = SEL_IMG_OR_TXT;
                }
                else if (compare_CMD(cmd, "<A>")) {
                    /* snake initialization */
                    initSnake();
                    
                    playSnake();
                }
                
                break;
                
            case SEL_IMG_OR_TXT :
                Serial.write(cmd);
            
                if (compare_CMD(cmd, "<I>")) {
                    state = SEL_IMG;
                }
                else if (compare_CMD(cmd, "<T>")) {
                    state = RCV_TXT;
                }
                
                break;
                
            case SEL_IMG :
                Serial.write(cmd);
                
                if (cmd[1] < 0x40 && cmd[1] > 0x29) {
                    switch (mode) {
                        case MODE_SINGLE :
                            playImage();
                            
                            break;
                        
                        case MODE_GROUP :
                            
                            collectTime();
                            Timer1.attachInterrupt(timer_ISR);
                            
                            while (curTime < startTime);
                            
                            Timer1.detachInterrupt();
                            playImage();
                            
                            break;       
                    }
                }
                
                break;
                
            case RCV_TXT :
                Serial.write(cmd);
                
                break;
            
        }
    }

}

boolean read_CMD() 
{
    uint8_t count;
    
    for (count = 10; count && !Serial.available(); --count) delay(1);
    
    if (!count) return false;
    
    cmd[0] = Serial.read();
    
    for (count = 10; count && !Serial.available(); --count) delay(1);
    
    if (!count) return false;
    
    cmd[1] = Serial.read();
    
    for (count = 10; count && !Serial.available(); --count) delay(1);
    
    if (!count) return false;
    
    cmd[2] = Serial.read();
        
    return true;
}

boolean compare_CMD(char* fst, char* snd)
{
    uint8_t i;
    
    for (i = 0; (i < 3) && (fst[i] == snd[i]); i++);
    
    if (i == 3) return true;
    else return false;
}

char readChar()
{
    uint8_t count;
    
    for (count = 10; count && !Serial.available(); --count) delay(10);
    
    if (count) return Serial.read();
    else return 'A'; // not a digit.
}

void collectTime()
{
    char input;
    char time[5];
    uint8_t len;
    uint8_t count = 0;
    
    if ((input = readChar()) == '<') {
        Serial.write(input);
        while ((input = readChar()) != '>') {
            Serial.write(input);
            time[count] = input;
            
            count++;
        }
        
        len = (--count);
        
        for (uint8_t i = 0; i <= len; i++) {
            curTime += (time[i] - 0x30)*power(10, count);
            
            --count;
        }
        
        count = 0;
        
        if ((input = readChar()) == '<') {
            Serial.write(input);
            while ((input = readChar()) != '>') {
                Serial.write(input);
                time[count] = input;
                
                count++;
            }
            
            len = (--count);
            
            for (uint8_t i = 0; i <= len; i++) {
                startTime += (time[i] - 0x30)*power(10, count);
                
                --count;
            }
        }
        
    }
    
    startCounting();
    
    Serial.println(curTime);
    Serial.println(startTime);
    
}

int power(int base, int degree)
{
    if (degree == 0) return 1;
    else if (degree == 1) return base;
    else {
        return base * power(base, (degree - 1));
    }
}

void playImage()
{
    boolean isStopped = false;
    char input;
    
    while (!isStopped) {
        char img[7] = "p .txt";
        
        if (mode == MODE_GROUP) img[0] = 'g';
        
        img[6] = 0;
        img[1] = cmd[1];
        
        myFile = SD.open(img);
    
        // if the file opened okay, write to it:
        if (!myFile) {
             Serial.println("error openning the file.");
             
             fileNotFound();
             
             state = SEL_SGL_OR_GRP;
             break;
        }
         
        while (myFile.available()) {
            if (read_CMD()) {
                
                if (compare_CMD(cmd, "<E>")) {                   
                    state = SEL_SGL_OR_GRP;
                    
                    myFile.close();

                    goto TO_MAIN_ROUTINE;
                }
            }
            
            uint8_t red, green, blue;
            
            for (uint8_t y = 1; y <= 10; y++) {
                
                for (uint8_t x = 1; x <= 10; x++) {
                    red = myFile.read();
                    green = myFile.read();
                    blue = myFile.read();
                    
                    strip.setPixelColor(getPixel(x, y), red, green, blue);
//                    Serial.write(red);
//                    Serial.write(green);
//                    Serial.write(blue);
                }
            }
            strip.show();
            //delay(10);
        }
        myFile.close();
    }
    
TO_MAIN_ROUTINE:
    
    return;
}

void initSnake() {
    sizeSnake = 3;
    vector = RIGHT;
    snake[0]= 45;
    snake[1]= 44;
    snake[2]= 43;
    snake[sizeSnake] = 42;
    applePosition = random(99);
}

void moveSnake() {
  int varSize;
  
  for(varSize = sizeSnake;varSize>=0;varSize-- ) {
      
      if(varSize == 0){
          if(vector == 1){
            int var = snake[0];
            
            if((var>=0)&&(var<=9)){
              snake[0] = 99 - var;
            }
            else if((var>=10)&&(var<=19)){
              snake[0] = 19- var;
            }
            else if((var>=20)&&(var<=29)){
              snake[0] = 39 - var;
            }
            else if((var>=30)&&(var<=39)){
              snake[0] = 59 - var;
            }       
            else if((var>=40)&&(var<=49)){
              snake[0] = 79 - var;
            }       
            else if((var>=50)&&(var<=59)){
              snake[0] = 99 - var;
            }        
            else if((var>=60)&&(var<=69)){
              snake[0] = 119 - var;
            }               
            else if((var>=70)&&(var<=79)){
              snake[0] = 139 - var;
            }        
            else if((var>=80)&&(var<=89)){
              snake[0] = 159 - var;
            }        
            else if((var>=90)&&(var<=99)){
              snake[0] = 179 - var;
            }
          }
          
          else if(vector == 2){
            int var = snake[0];
            if((var>=0)&&(var<=9)){
              snake[0] = 19 - var;
            }
            else if((var>=10)&&(var<=19)){
              snake[0] = 39- var;
            }
            else if((var>=20)&&(var<=29)){
              snake[0] = 59 - var;
            }
            else if((var>=30)&&(var<=39)){
              snake[0] = 79 - var;
            }       
            else if((var>=40)&&(var<=49)){
              snake[0] = 99 - var;
            }       
            else if((var>=50)&&(var<=59)){
              snake[0] = 119 - var;
            }        
            else if((var>=60)&&(var<=69)){
              snake[0] = 139 - var;
            }               
            else if((var>=70)&&(var<=79)){
              snake[0] = 159 - var;
            }        
            else if((var>=80)&&(var<=89)){
              snake[0] = 179 - var;
            }        
            else if((var>=90)&&(var<=99)){
              snake[0] = 99 - var;
            }
          }
          //right
          else if(vector == 3){
            int var = snake[0];
            if(((var>=0)&&(var<=8))||((var>=20)&&(var<=28))||((var>=40)&&(var<=48))||((var>=60)&&(var<=68))||((var>=80)&&(var<=88))){
              snake[0] = var+1;
            }
            else if(((var>=11)&&(var<=19))||((var>=31)&&(var<=39))||((var>=51)&&(var<=59))||((var>=71)&&(var<=79))||((var>=91)&&(var<=99))){
              snake[0] = var-1;
            }
            else if((var == 9)||(var == 29)||(var == 49)||(var == 69)||(var == 89)){
              snake[0] = var-9;          
            }
            else if((var == 10)||(var == 30)||(var == 50)||(var == 70)||(var == 90)){
              snake[0] = var+9;
            }
          }
          //left
          else{
            int var = snake[0];
            if(((var>=1)&&(var<=9))||((var>=21)&&(var<=29))||((var>=41)&&(var<=49))||((var>=61)&&(var<=69))||((var>=81)&&(var<=89))){
              snake[0] = var-1;
            }
            else if(((var>=10)&&(var<=18))||((var>=30)&&(var<=38))||((var>=50)&&(var<=58))||((var>=70)&&(var<=78))||((var>=90)&&(var<=98))){
              snake[0] = var+1;
            }
            else if((var == 0)||(var == 20)||(var == 40)||(var == 60)||(var == 80)){
              snake[0] = var+9;          
            }
            else if((var == 19)||(var == 39)||(var == 59)||(var == 79)||(var == 99)){
              snake[0] = var-9;
            }     
          }
        }
        else{
          snake[varSize] = snake[varSize-1]; 
          }
  }
}

int randomApple(){
  int randomPosition = 0;
  do{
    randomPosition = random(99);
  }
  while(findSnake(randomPosition));
  return randomPosition;
}

boolean findSnake(int positionHead){
  boolean check = false;
  int varSize;
  for(varSize = sizeSnake-1;varSize>0;varSize--){
    if(snake[varSize] == positionHead){
      check = true;
      varSize = 0;
    }
  }
  return check;
}

boolean findApple(int positionHead){
  boolean check = false;
  if(positionHead == applePosition){
    check = true;
  }
  return check;
}

void clearBlock(){
  int pixel;
  for(pixel = 0;pixel<100;pixel++){
    strip.setPixelColor(pixel,strip.Color(0, 0, 0));
  }
}

boolean changeDirection() {
    boolean isContinued = true;
    
    //Serial.println("fucked");
    
    if (read_CMD()) {
        if (compare_CMD(cmd, "<U>")) {
            if (vector != DOWN) {
                vector = UP;
            }
        }
        else if (compare_CMD(cmd, "<D>")) {
            if (vector != UP) {
                vector = DOWN;
            }
        }
        else if (compare_CMD(cmd, "<R>")) {
            if (vector != LEFT) {
                vector = RIGHT;
            }
        }
        else if (compare_CMD(cmd, "<L>")) {
            if (vector != RIGHT) {
                vector = LEFT;
            }
        }
        else if (compare_CMD(cmd, "<E>")) {
            isContinued = false;
        }
    }
    
    return isContinued;
}

void playSnake() {
    while (true) {
        //Serial.println(cmd);
        
        if (!changeDirection()) {
            state = SEL_SGL_OR_GRP;
            
            break;
        }
        
        clearBlock();
  
        strip.setPixelColor(applePosition,strip.Color(255, 0, 0));
        int snakePosition;
        for(snakePosition =0;snakePosition<sizeSnake;snakePosition++){
          strip.setPixelColor(snake[snakePosition],strip.Color(127, 127, 127));
         }
         
        if(findSnake(snake[0])) {
            Serial.print("Death\n");
            for(uint16_t i=0; i<strip.numPixels(); i++) {
                strip.setPixelColor(i, strip.Color(0, 255, 0));
                strip.show();
                delay(50);
            }
            state = SEL_SGL_OR_GRP;
            
            break;
        }
        
        if(findApple(snake[0])){
          sizeSnake += 1;
          applePosition = randomApple();
          Serial.print("Eat\n");
        }
        
        moveSnake();
        
        strip.show();  
        delay(250);
    }
}

uint8_t getPixel(uint8_t x, uint8_t y)
{
  return (100 - (10*y)) + (y % 2 == 0 ? (10 - x) : (x - 1)); // change this ? !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
}

void timer_ISR()
{
    if (curTime < startTime) curTime++;
    Serial.println(curTime);
}

void fileNotFound()
{
    strip.setPixelColor(getPixel(5,3), 255, 255, 255);
    strip.setPixelColor(getPixel(6,3), 255, 255, 255);
    strip.setPixelColor(getPixel(5,8), 255, 255, 255);
    strip.setPixelColor(getPixel(6,8), 255, 255, 255);
    
    strip.show();
}

void initOkay()
{
    strip.setPixelColor(getPixel(5,6), 255, 255, 255);
    strip.setPixelColor(getPixel(6,5), 255, 255, 255);
    strip.setPixelColor(getPixel(5,5), 255, 255, 255);
    strip.setPixelColor(getPixel(6,6), 255, 255, 255);
    
    strip.show();
}

void initFailed()
{
    strip.setPixelColor(getPixel(5,6), 255, 0, 0);
    strip.setPixelColor(getPixel(6,5), 255, 0, 0);
    strip.setPixelColor(getPixel(5,5), 255, 0, 0);
    strip.setPixelColor(getPixel(6,6), 255, 0, 0);
    
    strip.show();
}

void startCounting()
{
    strip.setPixelColor(getPixel(1,1), 255, 255, 255);
    strip.setPixelColor(getPixel(10,1), 255, 255, 255);
    strip.setPixelColor(getPixel(1,10), 255, 255, 255);
    strip.setPixelColor(getPixel(10,10), 255, 255, 255);
    
    strip.show();
}

What We Need More

  • Synchronization
  • Scalability
  • And More Games

PixelBrite

By whcwhc78

PixelBrite

  • 662