Part 1 by Kohpai @ ESL KMITL
State Machine
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();
}