 // =======================================================================================
 // /////////////////////////Padawan360 Dome Code v1.0///////////////////////////////////////
 // =======================================================================================
-//                                 danf
+//                                 Dan K
 //                        Revised  Date: 08/02/2014
 //   Designed to be used with a second Arduino running the Padawan Body code
 //
 // Much of this code is from various sources including...
 // DanF, Paul Murphy (JoyMonkey), John V, Michael Erwin, Michael Smith, Roger Moolay, Chris Reiff and Brad Oakley
 //
-// EasyTransfer and PS2X_lib libraries by Bill Porter
+// EasyTransfer libraries by Bill Porter
 //
 // Required : http://arduino.cc/playground/uploads/Main/LedControl.zip
 // (that's an Arduino Library - it needs to be downloaded and extracted into your

  B00000100 };

//Blank Symbol
int cb[] = {
  B00000000,
  B00000000,
  B00000000,
  B00000000,
  B00000000 };

//upSymbol
int cu[] = {
  B00000001,
  B00000010,
  B00000100,
  B00001000,
  B00010000 };

//down Symbol
int cn[] = {
  B00010000,
  B00001000,
  B00000100,
  B00000010,
  B00000001 };
void drawLetter(byte display, char let, int shift)
{
  int *pLetter;
  switch (let)
  {
  case 'A':
    pLetter=cA;
    break;
  case 'B':
    pLetter=cB;
    break;
  case 'C':
    pLetter=cC;
    break;
  case 'D':
    pLetter=cD;
    break;
  case 'E':
    pLetter=cE;
    break;
  case 'F':
    pLetter=cF;
    break;
  case 'G':
    pLetter=cG;
    break;
  case 'H':
    pLetter=cH;
    break;
  case 'I':
    pLetter=cI;
    break;
  case 'J':
    pLetter=cJ;
    break;
  case 'K':
    pLetter=cK;
    break;
  case 'L':
    pLetter=cL;
    break;
  case 'M':
    pLetter=cM;
    break;
  case 'N':
    pLetter=cN;
    break;
  case 'O':
    pLetter=cO;
    break;
  case 'P':
    pLetter=cP;
    break;
  case 'Q':
    pLetter=cQ;
    break;
  case 'R':
    pLetter=cR;
    break;
  case 'S':
    pLetter=cS;
    break;
  case 'T':
    pLetter=cT;
    break;
  case 'U':
    pLetter=cU;
    break;
  case 'V':
    pLetter=cV;
    break;
  case 'W':
    pLetter=cW;
    break;
  case 'X':
    pLetter=cX;
    break;
  case 'Y':
    pLetter=cY;
    break;
  case 'Z':
    pLetter=cZ;
    break;
    //non-letters
    //numbers
  case '0':
    pLetter=c0;
    break;
  case '1':
    pLetter=c1;
    break;
  case '2':
    pLetter=c2;
    break;
  case '3':
    pLetter=c3;
    break;
  case '4':
    pLetter=c4;
    break;
  case '5':
    pLetter=c5;
    break;
  case '6':
    pLetter=c6;
    break;
  case '7':
    pLetter=c7;
    break;
  case '8':
    pLetter=c8;
    break;
  case '9':
    pLetter=c9;
    break;
    //special characters
  case '*':
    pLetter=ch;
    break;
  case '#':
    pLetter=ct;
    break;
  case '@':
    pLetter=cr;
    break;
  case '-':
    pLetter=cd;
    break;
  case '|':
    pLetter=cf;
    break;
    //whitespace
  case ' ':
    pLetter=cb;
    break;
  case '<':
    pLetter=cu;
    break;
  case '>':
    pLetter=cn;
    break;
  default:
    return;
  }
  //loop thru rows of the letter
  for (byte i=0; i<5; i++)
  {
    if (shift>0) //positive shift means letter is slid to the right on the display
      v_grid[display][i] += (long)pLetter[i] << shift;
    else //negative shift means letter is slid to the left so that only part of it is visible
    v_grid[display][i] += (long)pLetter[i] >> -shift;
  }
}

//////////////////////////////////////////////////////////////////////////////////////
void scrollingText(byte display, char text[])
{
  unsigned long currentMillis = millis();

  if((currentMillis - previousMillis[display]) >= scrollSpeed)
  {
    initGrid(display);
    previousMillis[display] = currentMillis;

    for (int i=0; i<strlen(text); i++)
    {
      drawLetter(display, text[i], i*5 + scrollPositions[display]);
    }

    scrollPositions[display]--;
    if (scrollPositions[display] < -5*(int)strlen(text))
    {
      if (display==2)
      {
        scrollPositions[display]=27;
      }
      else
      {
        scrollPositions[display]=9;
      }

      scrollCount[display]++;

    }
  }
  showGrid(display);

}
//////////////////////////////////////////////////////////////////////////////////////
void displayHelper(byte display, byte &counter, byte &limit){
  if (display == 0){
    counter = 0;
    limit = 1;
  }
  else if(display == 1){
    counter = 1;
    limit = 2;
  }
  else if(display == 2){
    counter = 0;
    limit = 3;
  }
}

///////////////////////////////////////////////////////////////////
void flicker()
{
  unsigned long currentMillis = millis();

  if(currentMillis - previousMillis[1] > flick) {
    // save the last time you blinked the LED
    previousMillis[1] = currentMillis;

    analogWrite(hpPin, random(255));
    flick = random(100);
  }
}
//////////////////////////////////////////////////////////////////////////////////////

void randomPsi()
{
  unsigned long currentMillis = millis();
  if(currentMillis - psiMillis > psiTime*500) // delay between .5 to 5 seconds
  {
    psiMillis = currentMillis;
    if (psiColor ==0)
    {
      psiColor = 5;
      psiNum=0;
    }
    else
    {
      psiColor = 0;
      psiNum=HPROW-1;
    }
    psiTime = random(1,10);

    // Serial.print("psiTime: ");Serial.println(psiTime);Serial.print("psiColor: ");
    // Serial.println(psiColor);Serial.print("psiNum: ");Serial.println(psiNum);
  }

  unsigned long currentMillis2 = millis();
  if(currentMillis2 - psiMillis2 > wipe)
  {
    if (psiNum<HPROW && psiColor == 5)
    {
      psiMillis2 = currentMillis2;
      lcRear.setRow(3, psiNum, psiRow[psiNum+psiColor]);
      lcFront.setRow(2, psiNum, psiRow[psiNum+psiColor]);
      //if (psiNum<3)
      psiNum++;
      //Serial.print("psiNum: "); Serial.println(psiNum);

    }
    else if (psiNum>=0 && psiColor == 0)
    {
      psiMillis2 = currentMillis2;
      lcRear.setRow(3, psiNum, psiRow[psiNum+psiColor]);
      lcFront.setRow(2, psiNum, psiRow[psiNum+psiColor]);
      psiNum--;
      //Serial.print("psiNum: "); Serial.println(psiNum);
    }
  }
}
///////////////////////////////////////////////////////////////////
void autoHP()
{
  if (hpY!=150&&hpY!=30&&hpX!=150&&hpX!=30&&displayMode!=5)
  {
    unsigned long currentMillis = millis();
    if (currentMillis - HpMillis > twitch)
    {
      hpY=random(31,150);
      hpX=random(31,150);
      HpMillis = currentMillis;

//   RLD OUT1 -> Rear PSI
//   RLD OUT2 -> FLD -> FLD -> Front PSI
//

//=============================================================================================
//////////////// Here are the things you need to set to your configuration////////////////////
//=============================================================================================

// Type of Arduino you are using
  // 1 = Arduino Pro Mini or Uno or Duemilanove (the cleanest option, but you need an FTDI adapter)
  // 2 = Sparkfun Pro Micro (but be ready to deal with USB and upload issues)
  // 3 = Arduino Micro 
  // 4 = Arduino Nano (my fav of the small boards)
#define BOARDtype 1

// PSItype sets the type of our front and rear PSI's
  // 1 = Teeces original (6 LEDs of each color, arranged side by side)
  // 2 = Teeces original checkerboard (6 LEDs of each color arranged in a checkerboard pattern)
  // 3 = Teeces V3.2 PSI by John V (13 LEDs of each color, arranged side by side)
  // 4 = Teeces V3.2 PSI checkerboard by John V  (13 LEDs of each color, in a checkerboard pattern)
#define PSItype 4

// For flipped bottom logic displays
  // un-comment the following line if your bottom FLD is flipped upside down
//#define flipBottomFLD

// Set pins used for front hp servos
#define HPY A4
#define HPX A5

// Startup Text
char TFLDtext[] =  "PADAWAN   "; //PUT YOUR TOP FRONT STARTUP TEXT HERE.
char BFLDtext[] =  "       BOOTING"; //PUT YOUR BOTTOM FRONT STARTUP TEXT HERE.
char RLDtext[] = "ARTOO DETOO  "; //PUT YOUR REAR STARTUP TEXT HERE.


// =======================================================================================
// Most builders shouldn't have to edit anything below here, 
// but you can tweak the effects by changing the numbers below
// =======================================================================================

// set brightness levels here (a value of 0-15)
byte LDbrightness = 1;   // Logics
#define PSIbrightness   15  // PSI

// time in ms between logic display updates (lower = blink faster)
#define LOGICupdateDelay 100

// default random blinking styles of the logics. 
// Styles 0 to 2 are for special effects (I used them in Failure)
// Style 3 is legacy Teeces ("blocky random", about 50% off, most LED changing at a time)
// Styles 4 and 5 are recommended, more organic random styles (not all LEDs change at the same time, more LEDs on)
// Stlye 6 is most LEDs on (special effect). 
// 0= almost all off, 1= most off, 2= some off, 3= legacy random, 4= stage 1 organic, 5= stage 2 organic, 6 = stage 3 organic
#define LOGICRandomStyle 4

// update speed of bargraph display
#define BARGRAPHupdateDelay 50

// Delay (in ms) between color wipe steps when PSI changes color (lower= wipe faster)
#define PSIwipeDelay  70

// You can make the front or rear PSI get stuck inbetween colors from time to time by setting these parameters to 1 (0 for normal operation
#define FPSIgetsStuck 1
#define RPSIgetsStuck 1

// parameters for how long and how often it gets stuck
#define PSIstuckhowlong 10000  // stuck time in ms
#define PSIstuckhowoften 5     // how often. 5 means 1 out of 5 swipes on average. So the higher the less often.

// text scroll speed (in ms, lower= scroll faster)
#define SCROLLspeed 56

// Leia effect parameters
#define LEIAduration  35000 // in ms
#define LEIAspeed  100 //2200         // in no particular units, lower=faster

// Alarm effect parameters
#define ALARMduration 4000 // in ms
#define ALARMspeed   100  // in ms

// March effect parameters
#define MARCHduration 175000 // in ms
#define MARCHspeed   555  // in ms. 

// Cantina effect parameters
#define CANTINAduration 165000 // in ms

// Failure effect parameters
#define FAILUREduration 10000
#define FAILUREloops 5
#define FAILUREspeed 75

// =========================================================================
// Only make changes below here if you know what you are doing
// =========================================================================

// include libraries
#include <LedControl.h>
#include <avr/pgmspace.h>
#include <EasyTransfer.h>
#include <Servo.h>
#include <Wire.h>
/*
Different Arduino's have different pin numbers that are used for the rear chains.
 Arduino Pro Mini uses pins 12,11,10 for rear D,C,L
 Sparkfun Pro Micro uses pins 14,16,10 for rear D,C,L
 Arduino Micro uses pins A2,A1,A0 for rear D,C,L
 */

#if (BOARDtype==1) 
#define DVAL 12
#define CVAL 11
#define LVAL 10
#elif (BOARDtype==2) 
#define DVAL 14
#define CVAL 16
#define LVAL 10
#elif (BOARDtype==3||BOARDtype==4) 
#define DVAL A2
#define CVAL A1
#define LVAL A0
#endif

#define FDEV 3    //3 devices for front chain (top FLD, bottom FLD, front PSI
#define FPSIDEV 2 //front PSI is device #2 in the front chain
#define RPSIDEV 3 //rear PSI is device #3 in the rear chain

#define LETTERWIDTH 5 // letter with in pixels
#define MAXSTRINGSIZE 64  // maximum number of letters in a logic display message
#define BAUDRATE 57600

///////global variables////////////////////////////

// This is the LED grid for the 3 logic displays. 
// Since an "unsigned long" is 32 bits wide in gcc, this gives
// 3 grids of 5 rows x 32 bits (which could control 5 rows of 32 LEDs)
// Grid 0 if used for the top FLD, uses only the first 5x9 LEDs/bits
// Grid 1 is used for the bottom FLD, uses only the first 5x9 LEDs/bits
// Grid 3 is used for the RLD, uses only 5x27 LEDs/bits
// This LED grid is sent to the actual display in the function showGrid(display)
unsigned long LEDgrid[3][5]; 

// starting values for text scrolling positions on each display.
int scrollPositions[]={
  9,9,27};

// textScrollCount
// 0,1, and 2 are used in scrollText for each display, counts how many times the string has completely scrolled
long textScrollCount[3];

// display mode
#define NORM 0
#define ALARM 1
#define MARCH 2
#define LEIA 3
#define FAILURE 4
byte displayEffect; // 0 = normal, 1 = alarm, 2 = march, 3 = leia, 4 = failure

// display state for the logics, 0=normal random, 1=text display, 2=bargraph, 3=test, 4=off 
#define RANDOM 0
#define TEXT 1
#define BARGRAPH 2
#define TEST 3
#define OFF 4
byte displayState[3];

// display state for the PSI, 0=normal random, 1=color1, 2=color2, 3=test, 4=off (0, 3 and 4 are shared with displays above)
#define COLOR1 1
#define COLOR2 2
byte psiState[2];

#define BLUE         COLOR1
#define RED          COLOR2
#define YELLOW       COLOR1
#define GREEN        COLOR2

// start with the default display random mode.
byte randomStyle[3]={
  LOGICRandomStyle, LOGICRandomStyle, LOGICRandomStyle};

// tracks if we are in the midst of running an effect
byte effectRunning;

// memory for the text strings to be displayed, add one for the NULL character at the end
char logicText[3][MAXSTRINGSIZE+1];

// Create Maxim devices SPI driver objects for front and rear chains
LedControl lcRear=LedControl(DVAL,CVAL,LVAL,4);  //rear chain, 3 devices for RLD, one for the rear PSI
LedControl lcFront=LedControl(9,8,7,FDEV);       //front chain, 3 devices: TFLD, BFLD, front PSI

// handle to the Serial object, since it's a different one Micro than Minis
HardwareSerial* serialPort;

// the array psiPatterns is used to program the psi wipe
// The first five elements are the LED values for the first color for each row.
// The second five elements are the LED values for the second color for each row.
#if (PSItype==4)  
#define HPROW 5
#define HPPAT1 B10101010
#define HPPAT2 B01010101
int psiPatterns[]={
  HPPAT1,HPPAT2,HPPAT1,HPPAT2,HPPAT1,HPPAT2,HPPAT1,HPPAT2,HPPAT1,HPPAT2};
#elif (PSItype==3)  
#define HPROW 5
#define HPPAT1 B11100000
#define HPPAT2 B00010000
int psiPatterns[]={
  HPPAT1,HPPAT1,HPPAT1,HPPAT1,HPPAT1,HPPAT2,HPPAT2,HPPAT2,HPPAT2,HPPAT2};
#elif (PSItype==2) 
#define HPROW 4
#define HPPAT1 B10101000
#define HPPAT2 B01010100
int psiPatterns[]={
  HPPAT1,HPPAT2,HPPAT1,HPPAT2,HPPAT1,HPPAT2,HPPAT1,HPPAT2,HPPAT1,HPPAT2};
#elif (PSItype==1)
#define HPROW 4
#define HPPAT1 B11000000
#define HPPAT2 B00110000
int psiPatterns[]={
  HPPAT1,HPPAT1,HPPAT1,HPPAT1,HPPAT1,HPPAT2,HPPAT2,HPPAT2,HPPAT2,HPPAT2};
#endif

// Used for front holo projector
long twitch = 2500;
unsigned long HpMillis = 0;
Servo HPXservo;
Servo HPYservo;
int posY = 90;
int posX = 90;
int hpY = 0;
int hpX = 0;
int hpPin = 3;



// Set up the EasyTransfer communication
EasyTransfer ET;//create object
struct RECEIVE_DATA_STRUCTURE{
  //put your variable definitions here for the data you want to receive
  //THIS MUST BE EXACTLY THE SAME ON THE OTHER ARDUINO
