#pragma platform(NXT)
#include "NXCDefs.h"
#define TouchPort IN_2
#define I2CPort IN_1
#define I2CAddress 0x70  // 0x40 for PCF8574 or 0x70 for PCF8574A
#define INITnWORD 1
#define INITnLETTER 2

// -------------- Variable Declarations --------------

// Arguments for low speed comm syscalls
  CommLSWriteType lswArgs;           // Low speed write structure I2C
  CommLSCheckStatusType lscsArgs;    // Low speed status structure I2C
// Display patterns
// Each byte represents a column of dots with last byte = 0
// Bit set to 1 means lit LED.
// Least significant bit is at top of column.
// Maximum number of bytes per pattern: 15
  byte A[] = {0xfe, 0x09, 0x09, 0x09, 0x09, 0x09, 0xfe, 0 };
  byte B[] = {0xff, 0x89, 0x89, 0x89, 0x89, 0x56, 0x20, 0 };
  byte C[] = {0x7e, 0x81, 0x81, 0x81, 0x81, 0x81, 0x42, 0 };
  byte D[] = {0xff, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c, 0 };
  byte E[] = {0xff, 0x89, 0x89, 0x89, 0x81, 0x81, 0x81, 0 };
  byte F[] = {0xff, 0x09, 0x09, 0x09, 0x01, 0x01, 0x01, 0 };
  byte G[] = {0x7e, 0x81, 0x81, 0x81, 0x91, 0x91, 0x72, 0};
  byte H[] = {0xff, 0x08, 0x08, 0x08, 0x08, 0x08, 0xff, 0};
  byte I[] = {0x00, 0x81, 0x81, 0xff, 0x81, 0x81, 0x00, 0};
  byte J[] = {0x20, 0xc0, 0x80, 0x80, 0x80, 0x60, 0x1f, 0};
  byte K[] = {0xff, 0x08, 0x16, 0x36, 0x63, 0xc1, 0x80, 0};
  byte L[] = {0xff, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0};
  byte M[] = {0xff, 0x02, 0x04, 0x08, 0x10, 0x08, 0x04, 0x02, 0xff, 0};
  byte N[] = {0xff, 0x02, 0x04, 0x08, 0x10, 0x20, 0xff, 0};
  byte O[] = {0x7e, 0x81, 0x81, 0x81, 0x81, 0x81, 0x7e, 0};
  byte P[] = {0xff, 0x09, 0x09, 0x09, 0x09, 0x09, 0x06, 0};
  byte Q[] = {0x7e, 0x81, 0x81, 0x81, 0xa1, 0xc1, 0xfe, 0};
  byte R[] = {0xfe, 0x09, 0x09, 0x19, 0x29, 0x49, 0x86, 0};
  byte S[] = {0x86, 0x89, 0x89, 0x89, 0x89, 0x89, 0x71, 0};
  byte T[] = {0x01, 0x01, 0x01, 0xff, 0x01, 0x01, 0x01, 0};
  byte U[] = {0x7f, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f, 0};
  byte V[] = {0x03, 0x0c, 0x30, 0xc0, 0x30, 0x0c, 0x03, 0};
  byte W[] = {0x03, 0x0c, 0x30, 0xc3, 0xcc, 0x30, 0xcc, 0xc3, 0x30, 0x0c, 0x03, 0};
  byte X[] = {0x81, 0x42, 0x24, 0x18, 0x24, 0x42, 0x81, 0};
  byte Y[] = {0x01, 0x02, 0x04, 0xf8, 0x04, 0x02, 0x01, 0};
  byte Z[] = {0xc1, 0xa9, 0x99, 0x89, 0x8d, 0x8b, 0x81, 0};

// Misc
  byte DispBuf[];          // buffer for write to I2C
  byte nWord;              // number of words
  byte nLetter;            // number of letter for word
  string LetterWord;       // letter for each word
  string ViewWord1, ViewWord2, ViewWord3, ViewWord4;     // word for view

  byte temp, temp1, temp2; // temporary variable
  string tempWord = "";    // temporary word
// **** SUB for Initialize variables
  void Initialize(){
    lswArgs.ReturnLen = 0; // only send data
    lswArgs.Port = I2CPort;
// Init Touch Sensor, used to detect leftmost position of sweep
    SetSensorType(TouchPort,IN_TYPE_SWITCH);
    SetSensorMode(TouchPort,IN_MODE_BOOLEAN);
    ResetSensor(TouchPort);
// Initalize input port to I2C
    SetSensorType(I2CPort,IN_TYPE_LOWSPEED);
    SetSensorMode(I2CPort,IN_MODE_RAW);
    ResetSensor(I2CPort);
  }

// **** SUB for setting number of words
  void NumberWord(){

    TextOut(2, LCD_LINE2, "  Select number", TRUE);
	  TextOut(2, LCD_LINE3, "of words (Max 4)");
    TextOut(2, LCD_LINE8, "< (-)  OK  (+) >");
    nWord = INITnWORD;
    NumOut(47, LCD_LINE6, nWord);
    while (TRUE){  // Top of loop
      until (ButtonPressed(BTNLEFT, true) | ButtonPressed(BTNCENTER, true) | ButtonPressed(BTNRIGHT, true)); // until push button
      PlayTone(500,50);
      if (ButtonPressed(BTNRIGHT, true)){
        nWord = nWord + 1;
        if (nWord == 5) nWord = 1; }
      if (ButtonPressed(BTNLEFT, true)){
        nWord = nWord - 1;
        if (nWord == 0) nWord = 4; }
      if (ButtonPressed(BTNCENTER, true)){
        break; }
      NumOut(47, LCD_LINE6, nWord);
      Wait(500);
    }
  }

// **** SUB for setting number of words
  void StringWord(){

    Wait(500);
    tempWord = "";
    temp1 = 0;
    TextOut(2, LCD_LINE1, "Number of letter", TRUE);
	  TextOut(2, LCD_LINE2, "   for Word");
	  NumOut(72, LCD_LINE2, temp2);
    TextOut(4, LCD_LINE3, "    (Max 6)");
    TextOut(2, LCD_LINE8, "< (-)  OK  (+) >");
    nLetter = INITnLETTER;
    NumOut(47, LCD_LINE6, nLetter);
    while (TRUE){  // Top of loop
      until (ButtonPressed(BTNLEFT, true) | ButtonPressed(BTNCENTER, true) | ButtonPressed(BTNRIGHT, true)); // until push button
      PlayTone(500,50);
      if (ButtonPressed(BTNRIGHT, true)){
        nLetter = nLetter + 1;
        if (nLetter == 7) nLetter = 1; }
      if (ButtonPressed(BTNLEFT, true)){
        nLetter = nLetter - 1;
        if (nLetter == 0) nLetter = 6; }
      if (ButtonPressed(BTNCENTER, true)){
        break; }
    NumOut(47, LCD_LINE6, nLetter);
    Wait(500);
    }

    TextOut(2, LCD_LINE1, " Select letter  ");
	  TextOut(2, LCD_LINE2, "   for Word");
	  NumOut(72, LCD_LINE2, temp2);
    TextOut(4, LCD_LINE3, "            ");
    temp = 65;
    repeat (nLetter)
    {
      Wait(500);
      temp1 = temp1 + 1;
      LetterWord = Flatten(temp);
      TextOut(47, LCD_LINE6, LetterWord);
      TextOut(41 + (temp1 *6), LCD_LINE4, LetterWord);

      while (TRUE){  // Top of loop

        TextOut(2, LCD_LINE4, "Word  :");
        NumOut(30, LCD_LINE4, temp2);
        until (ButtonPressed(BTNLEFT, true) | ButtonPressed(BTNCENTER, true) | ButtonPressed(BTNRIGHT, true)); // until push button
        PlayTone(500,50);
        if (ButtonPressed(BTNRIGHT, true)){
          temp = temp + 1;
          if (temp == 91) temp = 65; }
        if (ButtonPressed(BTNLEFT, true)){
          temp = temp - 1;
          if (temp == 64) temp = 90; }
        if (ButtonPressed(BTNCENTER, true)){
          break; }
        TextOut(47, LCD_LINE6, Flatten(temp));
        TextOut(41 + (temp1 *6), LCD_LINE4, Flatten(temp));
        Wait(500);
      }
      LetterWord = Flatten(temp);
      LetterWord = SubStr(LetterWord, 0, 1);
      tempWord = StrCat(tempWord, LetterWord);
    }
  }

// **** SUB for view the setting
  void ViewSetting(){

    TextOut(2, LCD_LINE2, "Number words: ", TRUE);
	  NumOut(85, LCD_LINE2, nWord);
    TextOut(2, LCD_LINE3, "Word 1:");
    TextOut(44, LCD_LINE3, ViewWord1);
    if (nWord >= 2){
      TextOut(2, LCD_LINE4, "Word 2:");
      TextOut(44, LCD_LINE4, ViewWord2);}
    if (nWord >= 3){
      TextOut(2, LCD_LINE5, "Word 3:");
      TextOut(44, LCD_LINE5, ViewWord3);}
    if (nWord == 4){
      TextOut(2, LCD_LINE6, "Word 4:");
      TextOut(44, LCD_LINE6, ViewWord4);}
    TextOut(2, LCD_LINE8, "       OK      ");
    Wait(1000);
    until (ButtonPressed(BTNCENTER, true)); // until push button
    TextOut(2, LCD_LINE8, "               ");
  }

// **** SUB for Sends the buffer containing the pattern to be displayed.
// Each column is displayed during the time needed to send a byte, about 1ms
  void DispLetter(){

  asm{  // START ASM/NBC only for XOR BUFFER
    xor DispBuf, DispBuf, 0xff // Invert all bytes of display buffer
    arrbuild lswArgs.Buffer, I2CAddress, DispBuf // Prepare buffer
    }  // END ASM/NBC only for XOR BUFFER **********

  do{   // Wait for the end of previously sent data
    SysCommLSCheckStatus (lscsArgs);
    } while (lscsArgs.Result > 0)
  SysCommLSWrite(lswArgs); // Send new buffer
  }
  
// **** SUB for display the magic word
  void MagicWord(){

    // Wait for start
    until (SENSOR_2 == 1);  // until press button
    until (SENSOR_2 == 0);  // until release button
    temp = 0;
    temp1 = StrLen(tempWord);
    Wait(40 - (temp1 * 5));  // Wait a little to center display

    repeat(temp1){  // Top of loop
      LetterWord = SubStr(tempWord, temp, 1);
      if (LetterWord == "A"){ DispBuf = A; }
      if (LetterWord == "B"){ DispBuf = B; }
      if (LetterWord == "C"){ DispBuf = C; }
      if (LetterWord == "D"){ DispBuf = D; }
      if (LetterWord == "E"){ DispBuf = E; }
      if (LetterWord == "F"){ DispBuf = F; }
      if (LetterWord == "G"){ DispBuf = G; }
      if (LetterWord == "H"){ DispBuf = H; }
      if (LetterWord == "I"){ DispBuf = I; }
      if (LetterWord == "J"){ DispBuf = J; }
      if (LetterWord == "K"){ DispBuf = K; }
      if (LetterWord == "L"){ DispBuf = L; }
      if (LetterWord == "M"){ DispBuf = M; }
      if (LetterWord == "N"){ DispBuf = N; }
      if (LetterWord == "O"){ DispBuf = O; }
      if (LetterWord == "P"){ DispBuf = P; }
      if (LetterWord == "Q"){ DispBuf = Q; }
      if (LetterWord == "R"){ DispBuf = R; }
      if (LetterWord == "S"){ DispBuf = S; }
      if (LetterWord == "T"){ DispBuf = T; }
      if (LetterWord == "U"){ DispBuf = U; }
      if (LetterWord == "V"){ DispBuf = V; }
      if (LetterWord == "W"){ DispBuf = W; }
      if (LetterWord == "X"){ DispBuf = X; }
      if (LetterWord == "Y"){ DispBuf = Y; }
      if (LetterWord == "Z"){ DispBuf = Z; }
      DispLetter();
      temp = temp + 1;
    }
  }
  
// ---------------- Program Code ----------------
task main()
{
  Initialize();             // Initialize variables
  NumberWord();             // Select number of words
  temp2 = 1;
  StringWord();             // Set string word (1 to 4)
  ViewWord1 = tempWord;
  if (nWord >= 2){ temp2 = 2; StringWord(); ViewWord2 = tempWord; }
  if (nWord >= 3){ temp2 = 3; StringWord(); ViewWord3 = tempWord; }
  if (nWord == 4){ temp2 = 4; StringWord(); ViewWord4 = tempWord; }
  ViewSetting();

// Start Motor, full speed
  OnFwd(OUT_A, 100);

  while (TRUE){
    tempWord = ViewWord1;
    MagicWord();
    if (nWord >= 2){ tempWord = ViewWord2; MagicWord(); }
    if (nWord >= 3){ tempWord = ViewWord3; MagicWord(); }
    if (nWord == 4){ tempWord = ViewWord4; MagicWord(); }
  }
}
