//Define Led Pins:

#include <Wire.h>

long accelX;

const int charLEDwidth = 5;               // number of LEDs wide a character is
const int charLEDheight = 7;              // number of LEDs tall a character is
const int LEDmap[7] = {9,8,7,6,5,4,3};    // pinmap for the output pins in use for the LEDs

const int mid_char_delay = 5;             // additional delay BETWEEN writing a single value to each LED in the POV wand
const int end_char_delay = 20;            // additional delay AFTER writing a single character
const int end_string_delay = 40;          // additional delay AFTER finishing a string

const int strln = 3;                      // length of string
char sentence[strln] = "zit";             // string itselt


// notes: -> 'numLEDs' was changed to 'charLEDwidth' since numLEDs was slightly misleading:
//        ---> Now accurately means the width of each characer in terms of number of LEDs
//        -> created 'charLEDheight' to represent anytime the height of each character in LEDs is represented
//
//        -> replaced delay variables
//        ---> char_delay: is now mid_char_delay, to represent that it occurs in the middle of a character
//        ---> end_char_delay: end of char delay was given a variable name to be end_char_delay, and thus configurable
//        ---> end_string_delay: an end of word delay was created as end_string_delay, executes after the last character in a string is written


// letters
int a[] = {63,72,72,72,63};
int b[] = {127,73,73,73,54};
int c[] = {62,65,65,65,65};
int d[] = {127,65,65,65,62};
int e[] = {127,73,73,73,73};
int f[] = {127,72,72,64,64};
int g[] = {62,65,65,73,46};
int h[] = {127,8,8,8,127};
int i[] = {65,65,127,65,65};             // 7 bit alphabet for LED letters
int j[] = {70,65,126,64,64};
int k[] = {127,8,20,34,65};
int l[] = {127,1,1,1,1};
int m[] = {127,32,24,32,127};
int n[] = {127,48,8,6,127};
int o[] = {62,65,65,65,62};
int p[] = {127,72,72,72,48};
int q[] = {60,68,68,70,61};
int r[] = {127,72,76,74,49};
int s[] = {50,73,73,73,38};
int t[] = {64,64,127,64,64};
int u[] = {126,1,1,1,126};
int v[] = {112,12,3,12,112};
int w[] = {126,1,14,1,126};
int x[] = {99,20,8,20,99};
int y[] = {112,8,7,8,112};
int z[] = {65,71,73,113,65};
int left_chev[] = {8,20,34,65,65};
int right_chev[] = {65,65,34,20,8};

void setup() {
  // put your setup code here, to run once:

  Serial.begin(115200);                       // begin serial functions w/ baud rate set
  for(int i=0; i<charLEDheight; i++){         // loop for each LED
    pinMode(LEDmap[i], OUTPUT);               // configures 7 pins to output for LEDs
  }
  setupMPU();                                 // call setupMPU function
}


void loop() {
  // put your main code here, to run repeatedly:


  if(recordAccel() > 10000){                  // if accelerometer is moving the LED array left to right
    for(int i=0; i<strln; i++){               // loop for the length of the string, forwards
        
      //writeCharBackward(sentence[i]);
      writeCharForward(sentence[i]);          // write the character at that position in the string

      if(recordAccel() < -10000){break;}      // check to see if acceleration is the other way, break 
                                              //  out of for loop if switched
      if(i == (strln - 1) ) {
        delay(end_string_delay);                // if the last character in the string was printed, delay
      }
    }
  }
  
  if(recordAccel() < -10000){                 // if accelerometer is moving the LED array right to left
    for(int i = strln; i>=0; i--){            // loop for the length of the string, backwards

      //writeCharForward(sentence[i]);
      writeCharBackward(sentence[i]);         // write the character at that position in the string

      if(recordAccel() > 10000){break;}       // check to see if acceleration is the other way, break 
                                              //  out of for loop if switched
      if(i == (strln - 1) ) {
        delay(end_string_delay);                // if the last character in the string was printed, delay
      }
    }                         
  }

  
}

void setupMPU(){
  Wire.beginTransmission(0b1101000);  //This is the I2C address of the MPU (b1101000/b1101001 for AC0 low/high datasheet sec. 9.2)
  Wire.write(0x6B);                   //Accessing the register 6B - Power Management (Sec. 4.28)
  Wire.write(0b00000000);             //Setting SLEEP register to 0. (Required; see Note on p. 9)
  Wire.endTransmission();  
  Wire.beginTransmission(0b1101000);  //I2C address of the MPU
  Wire.write(0x1B);                   //Accessing the register 1B - Gyroscope Configuration (Sec. 4.4) 
  Wire.write(0x00000000);             //Setting the gyro to full scale +/- 250deg./s 
  Wire.endTransmission(); 
  Wire.beginTransmission(0b1101000);  //I2C address of the MPU
  Wire.write(0x1C);                   //Accessing the register 1C - Acccelerometer Configuration (Sec. 4.5) 
  Wire.write(0b00000000);             //Setting the accel to +/- 2g
  Wire.endTransmission(); 
}

long recordAccel(){
  long accelX;
  Wire.beginTransmission(0b1101000);    //I2C address of the MPU
  Wire.write(0x3B);                     //Starting register for Accel Readings
  Wire.endTransmission();
  Wire.requestFrom(0b1101000,6);        //Request Accel Registers (3B - 40)
  while(Wire.available() < 6);
  accelX = Wire.read()<<8|Wire.read();  //Store first two bytes into accelX
  return accelX;
}
/*
 * WriteCharForward takes in a letter argument and writes the LED sequence for that letter in forward order
 * 
 * As a whole, each case statement writes a character. It writes each LED of each vertical strip of that character, then waits for 
 *   the character delay, then writes the next strip. After the case statement completes, a letter delay is input, then the function ends
 * 
 */

void writeCharForward(char letter){

  switch(letter){
    case 'a': 
      for(int j=0; j<charLEDwidth; j++){           
        for(int i=0; i<charLEDheight; i++){               
          digitalWrite(LEDmap[i], bitRead(a[j], i));   // Writes the bit at the i'th position in the number at the j'th spot of the "a" array
                                                       //   to the LED represented by the pin at index i of LEDmap. I increments all the
                                                       //   way through everytime J increments once, going forwards
        } 
        delay(mid_char_delay);                    // delay for a prescribed amount, in milliseconds
      } 
      break;
      
    case 'b': for(int j=0; j<charLEDwidth; j++){ for(int i=0; i<charLEDheight; i++){digitalWrite(LEDmap[i], bitRead(b[j], i));} delay(mid_char_delay);} break;
    case 'c': for(int j=0; j<charLEDwidth; j++){ for(int i=0; i<charLEDheight; i++){digitalWrite(LEDmap[i], bitRead(c[j], i));} delay(mid_char_delay);} break;
    case 'd': for(int j=0; j<charLEDwidth; j++){ for(int i=0; i<charLEDheight; i++){digitalWrite(LEDmap[i], bitRead(d[j], i));} delay(mid_char_delay);} break;
    case 'e': for(int j=0; j<charLEDwidth; j++){ for(int i=0; i<charLEDheight; i++){digitalWrite(LEDmap[i], bitRead(e[j], i));} delay(mid_char_delay);} break;
    case 'f': for(int j=0; j<charLEDwidth; j++){ for(int i=0; i<charLEDheight; i++){digitalWrite(LEDmap[i], bitRead(f[j], i));} delay(mid_char_delay);} break;
    case 'g': for(int j=0; j<charLEDwidth; j++){ for(int i=0; i<charLEDheight; i++){digitalWrite(LEDmap[i], bitRead(g[j], i));} delay(mid_char_delay);} break;
    case 'h': for(int j=0; j<charLEDwidth; j++){ for(int i=0; i<charLEDheight; i++){digitalWrite(LEDmap[i], bitRead(h[j], i));} delay(mid_char_delay);} break;
    case 'i': for(int j=0; j<charLEDwidth; j++){ for(int l=0; l<charLEDheight; l++){digitalWrite(LEDmap[l], bitRead(i[j], l));} delay(mid_char_delay);} break;
    case 'j': for(int k=0; k<charLEDwidth; k++){ for(int i=0; i<charLEDheight; i++){digitalWrite(LEDmap[i], bitRead(j[k], i));} delay(mid_char_delay);} break;
    case 'k': for(int j=0; j<charLEDwidth; j++){ for(int i=0; i<charLEDheight; i++){digitalWrite(LEDmap[i], bitRead(k[j], i));} delay(mid_char_delay);} break;
    case 'l': for(int j=0; j<charLEDwidth; j++){ for(int i=0; i<charLEDheight; i++){digitalWrite(LEDmap[i], bitRead(l[j], i));} delay(mid_char_delay);} break;
    case 'm': for(int j=0; j<charLEDwidth; j++){ for(int i=0; i<charLEDheight; i++){digitalWrite(LEDmap[i], bitRead(m[j], i));} delay(mid_char_delay);} break;
    case 'n': for(int j=0; j<charLEDwidth; j++){ for(int i=0; i<charLEDheight; i++){digitalWrite(LEDmap[i], bitRead(n[j], i));} delay(mid_char_delay);} break;
    case 'o': for(int j=0; j<charLEDwidth; j++){ for(int i=0; i<charLEDheight; i++){digitalWrite(LEDmap[i], bitRead(o[j], i));} delay(mid_char_delay);} break;
    case 'p': for(int j=0; j<charLEDwidth; j++){ for(int i=0; i<charLEDheight; i++){digitalWrite(LEDmap[i], bitRead(p[j], i));} delay(mid_char_delay);} break;
    case 'q': for(int j=0; j<charLEDwidth; j++){ for(int i=0; i<charLEDheight; i++){digitalWrite(LEDmap[i], bitRead(q[j], i));} delay(mid_char_delay);} break;
    case 'r': for(int j=0; j<charLEDwidth; j++){ for(int i=0; i<charLEDheight; i++){digitalWrite(LEDmap[i], bitRead(r[j], i));} delay(mid_char_delay);} break;
    case 's': for(int j=0; j<charLEDwidth; j++){ for(int i=0; i<charLEDheight; i++){digitalWrite(LEDmap[i], bitRead(s[j], i));} delay(mid_char_delay);} break;
    case 't': for(int j=0; j<charLEDwidth; j++){ for(int i=0; i<charLEDheight; i++){digitalWrite(LEDmap[i], bitRead(t[j], i));} delay(mid_char_delay);} break;
    case 'u': for(int j=0; j<charLEDwidth; j++){ for(int i=0; i<charLEDheight; i++){digitalWrite(LEDmap[i], bitRead(u[j], i));} delay(mid_char_delay);} break;
    case 'v': for(int j=0; j<charLEDwidth; j++){ for(int i=0; i<charLEDheight; i++){digitalWrite(LEDmap[i], bitRead(v[j], i));} delay(mid_char_delay);} break;
    case 'w': for(int j=0; j<charLEDwidth; j++){ for(int i=0; i<charLEDheight; i++){digitalWrite(LEDmap[i], bitRead(w[j], i));} delay(mid_char_delay);} break;
    case 'x': for(int j=0; j<charLEDwidth; j++){ for(int i=0; i<charLEDheight; i++){digitalWrite(LEDmap[i], bitRead(x[j], i));} delay(mid_char_delay);} break;
    case 'y': for(int j=0; j<charLEDwidth; j++){ for(int i=0; i<charLEDheight; i++){digitalWrite(LEDmap[i], bitRead(y[j], i));} delay(mid_char_delay);} break;
    case 'z': for(int j=0; j<charLEDwidth; j++){ for(int i=0; i<charLEDheight; i++){digitalWrite(LEDmap[i], bitRead(z[j], i));} delay(mid_char_delay);} break;
    case '>': for(int j=0; j<charLEDwidth; j++){ for(int i=0; i<charLEDheight; i++){digitalWrite(LEDmap[i], bitRead(right_chev[j], i));} delay(mid_char_delay);} break;
    case '<': for(int j=0; j<charLEDwidth; j++){ for(int i=0; i<charLEDheight; i++){digitalWrite(LEDmap[i], bitRead(left_chev[j], i));} delay(mid_char_delay);} break;
  
  }
  for(int i=0; i<charLEDheight; i++){
    digitalWrite(LEDmap[i], LOW);
  }
  delay(end_char_delay);

}
/*
 * WriteCharBackward takes in a letter argument and writes the LED sequence for that letter in reverse order
 * 
 *  As a whole, each case statement writes a character. It writes each LED of each vertical strip of that character, then waits for 
 *   the character delay, then writes the next strip. After the case statement completes, a letter delay is input, then the function ends
 * 
 */

void writeCharBackward(char letter){

  switch(letter){
    case 'a': 
      for(int j=(charLEDwidth -1); j>=0; j--){ 
        for(int i=0; i<charLEDheight; i++){
          digitalWrite(LEDmap[i], bitRead(a[j], i));   // Writes the bit at the i'th spot in the number at the j'th spot of the a array
                                                       //   to the LED represented by the pin at index i of LEDmap. I increments all the
                                                       //   way through everytime J increments once, going backwards
        } 
        delay(mid_char_delay);                    // delay for a prescribed amount, in milliseconds
      } 
      break;
      
    case 'b': for(int j=(charLEDwidth -1); j>=0; j--){ for(int i=0; i<charLEDheight; i++){digitalWrite(LEDmap[i], bitRead(b[j], i));} delay(mid_char_delay);} break;
    case 'c': for(int j=(charLEDwidth -1); j>=0; j--){ for(int i=0; i<charLEDheight; i++){digitalWrite(LEDmap[i], bitRead(c[j], i));} delay(mid_char_delay);} break;
    case 'd': for(int j=(charLEDwidth -1); j>=0; j--){ for(int i=0; i<charLEDheight; i++){digitalWrite(LEDmap[i], bitRead(d[j], i));} delay(mid_char_delay);} break;
    case 'e': for(int j=(charLEDwidth -1); j>=0; j--){ for(int i=0; i<charLEDheight; i++){digitalWrite(LEDmap[i], bitRead(e[j], i));} delay(mid_char_delay);} break;
    case 'f': for(int j=(charLEDwidth -1); j>=0; j--){ for(int i=0; i<charLEDheight; i++){digitalWrite(LEDmap[i], bitRead(f[j], i));} delay(mid_char_delay);} break;
    case 'g': for(int j=(charLEDwidth -1); j>=0; j--){ for(int i=0; i<charLEDheight; i++){digitalWrite(LEDmap[i], bitRead(g[j], i));} delay(mid_char_delay);} break;
    case 'h': for(int j=(charLEDwidth -1); j>=0; j--){ for(int i=0; i<charLEDheight; i++){digitalWrite(LEDmap[i], bitRead(h[j], i));} delay(mid_char_delay);} break;
    case 'i': for(int j=(charLEDwidth -1); j>=0; j--){ for(int l=0; l<charLEDheight; l++){digitalWrite(LEDmap[l], bitRead(i[j], l));} delay(mid_char_delay);} break;
    case 'j': for(int k=(charLEDwidth -1); k>=0; k--){ for(int i=0; i<charLEDheight; i++){digitalWrite(LEDmap[i], bitRead(j[k], i));} delay(mid_char_delay);} break;
    case 'k': for(int j=(charLEDwidth -1); j>=0; j--){ for(int i=0; i<charLEDheight; i++){digitalWrite(LEDmap[i], bitRead(k[j], i));} delay(mid_char_delay);} break;
    case 'l': for(int j=(charLEDwidth -1); j>=0; j--){ for(int i=0; i<charLEDheight; i++){digitalWrite(LEDmap[i], bitRead(l[j], i));} delay(mid_char_delay);} break;
    case 'm': for(int j=(charLEDwidth -1); j>=0; j--){ for(int i=0; i<charLEDheight; i++){digitalWrite(LEDmap[i], bitRead(m[j], i));} delay(mid_char_delay);} break;
    case 'n': for(int j=(charLEDwidth -1); j>=0; j--){ for(int i=0; i<charLEDheight; i++){digitalWrite(LEDmap[i], bitRead(n[j], i));} delay(mid_char_delay);} break;
    case 'o': for(int j=(charLEDwidth -1); j>=0; j--){ for(int i=0; i<charLEDheight; i++){digitalWrite(LEDmap[i], bitRead(o[j], i));} delay(mid_char_delay);} break;
    case 'p': for(int j=(charLEDwidth -1); j>=0; j--){ for(int i=0; i<charLEDheight; i++){digitalWrite(LEDmap[i], bitRead(p[j], i));} delay(mid_char_delay);} break;
    case 'q': for(int j=(charLEDwidth -1); j>=0; j--){ for(int i=0; i<charLEDheight; i++){digitalWrite(LEDmap[i], bitRead(q[j], i));} delay(mid_char_delay);} break;
    case 'r': for(int j=(charLEDwidth -1); j>=0; j--){ for(int i=0; i<charLEDheight; i++){digitalWrite(LEDmap[i], bitRead(r[j], i));} delay(mid_char_delay);} break;
    case 's': for(int j=(charLEDwidth -1); j>=0; j--){ for(int i=0; i<charLEDheight; i++){digitalWrite(LEDmap[i], bitRead(s[j], i));} delay(mid_char_delay);} break;
    case 't': for(int j=(charLEDwidth -1); j>=0; j--){ for(int i=0; i<charLEDheight; i++){digitalWrite(LEDmap[i], bitRead(t[j], i));} delay(mid_char_delay);} break;
    case 'u': for(int j=(charLEDwidth -1); j>=0; j--){ for(int i=0; i<charLEDheight; i++){digitalWrite(LEDmap[i], bitRead(u[j], i));} delay(mid_char_delay);} break;
    case 'v': for(int j=(charLEDwidth -1); j>=0; j--){ for(int i=0; i<charLEDheight; i++){digitalWrite(LEDmap[i], bitRead(v[j], i));} delay(mid_char_delay);} break;
    case 'w': for(int j=(charLEDwidth -1); j>=0; j--){ for(int i=0; i<charLEDheight; i++){digitalWrite(LEDmap[i], bitRead(w[j], i));} delay(mid_char_delay);} break;
    case 'x': for(int j=(charLEDwidth -1); j>=0; j--){ for(int i=0; i<charLEDheight; i++){digitalWrite(LEDmap[i], bitRead(x[j], i));} delay(mid_char_delay);} break;
    case 'y': for(int j=(charLEDwidth -1); j>=0; j--){ for(int i=0; i<charLEDheight; i++){digitalWrite(LEDmap[i], bitRead(y[j], i));} delay(mid_char_delay);} break;
    case 'z': for(int j=(charLEDwidth -1); j>=0; j--){ for(int i=0; i<charLEDheight; i++){digitalWrite(LEDmap[i], bitRead(z[j], i));} delay(mid_char_delay);} break;
    case '>': for(int j=(charLEDwidth -1); j>=0; j--){ for(int i=0; i<charLEDheight; i++){digitalWrite(LEDmap[i], bitRead(right_chev[j], i));} delay(mid_char_delay);} break;
    case '<': for(int j=(charLEDwidth -1); j>=0; j--){ for(int i=0; i<charLEDheight; i++){digitalWrite(LEDmap[i], bitRead(left_chev[j], i));} delay(mid_char_delay);} break;
  }
  for(int i=0; i<charLEDheight; i++){
    digitalWrite(LEDmap[i], LOW);
  }
  delay(end_char_delay);
}
