Advanced version of Serial Out

Hey all,

I had a few friends ask me about a state machine that I made for the serial out example.

I was new to the Arduino, and I wanted to play around with the ‘serial’ class.

… So this is for them, but I’m happy for any comments/suggestions…

/*****************************************************
 * SUMMARY
 *****************************************************/
//LDU
/*
 This program is designed to print out
 all the ASCII keys as an intro to 
 Serial communication.
 
 It is based on <arduino.cc/en/Tutorial/ASCIITable>
 and been carefully studied for my understanding, and
 then updated to enclude some more advanced techniques.
 
 ASCII table
 
 Prints out byte values in all possible formats:  
 as raw binary values
 as ASCII-encoded decimal, hex, octal, and binary values
 
 For more on ASCII, see http://www.asciitable.com and 
 http://en.wikipedia.org/wiki/ASCII
 
 */

/*****************************************************
 * PROPERTIES
 *****************************************************/
//Functions in project
void PrintMenu(void);
void GetInputState(void);
void GetInputState(void);
void SetupPrintingInstance(struct PrintingInstance *PrintWindow, int Start, int Finish);
void PrintLine(struct PrintingInstance *PrintWindow);

//Constants for project
const int FirstPrintableChar = '!';
const int LastPrintableChar = '~';

const int FirstNumber = '0';
const int LastNumber = '9';

const int FirstLowerLetter = 'a';
const int LastLowerLetter = 'z';

const int FirstCapitalLetter = 'A';
const int LastCapitalLetter = 'Z';


//Enumerations for program
//(This is a customised variable type)
enum State //What State the program is in
{
  InitialiseObjects,
  PromptPrintingList,
  WaitingForInput,
  PrintAllChar,
  PrintNumbers,
  PrintLower,
  PrintCapital,
  AfterPrintingToScreen,
  unknown
};

//Objects for program
struct PrintingInstance //A window of characters to print
{
  int StartingChar;
  int FinishChar;
  int CurrentChar;
};

//Declare printing window object
PrintingInstance FullPrintingWindow;
PrintingInstance NumberPrintingWindow;
PrintingInstance LowerPrintingWindow;
PrintingInstance CapitalPrintingWindow;

//Declare Program state
State PrintingState;

//Declare variable for user input
int UserInput;

/*****************************************************
 * SETUP
 *****************************************************/

void setup()
{
  //Set up port speed
  Serial.begin(9600);

  //Prints title which explains what is to be explained
  Serial.println("ASCII Table ~ Character Map");

  //Set up initial state
  PrintingState = InitialiseObjects;

}

/*****************************************************
 * MAIN STATE MACHINE
 *****************************************************/

void loop()
{
  switch(PrintingState)
  {
  case InitialiseObjects:

    //initialise "FullPrintingWindow"
    SetupPrintingInstance(&FullPrintingWindow, FirstPrintableChar, LastPrintableChar);

    //initialise "NumberPrintingWindow"
    SetupPrintingInstance(&NumberPrintingWindow, FirstNumber, LastNumber);

    //initialise "LowerPrintingWindow"
    SetupPrintingInstance(&LowerPrintingWindow, FirstLowerLetter, LastLowerLetter);

    //initialise "CapitalPrintingWindow"
    SetupPrintingInstance(&CapitalPrintingWindow, FirstCapitalLetter, LastCapitalLetter);

    break;

  case PromptPrintingList:

    //Prompt user with options
    PrintMenu();

    break;  

  case WaitingForInput:

    GetInputState();

    break; 

  case PrintAllChar:

    //Print all characters
    PrintLine(&FullPrintingWindow);

    break;

  case PrintNumbers:

    //Print all numbers
    PrintLine(&NumberPrintingWindow);

    break;

  case PrintLower:

    //Print all lower letters
    PrintLine(&LowerPrintingWindow);

    break;

  case PrintCapital:

    //Print all Capital Letters
    PrintLine(&CapitalPrintingWindow);

    break;

  case AfterPrintingToScreen:
  
    //Do not do anything
    
    break;

  default:
  
    //Restore nonprinting state
    PrintingState = AfterPrintingToScreen;
    
    break;

  }

}

/*****************************************************
 * METHODS
 *****************************************************/

void SetupPrintingInstance(struct PrintingInstance *PrintWindow, int Start, int Finish)
{
  // Address of a PrintingInstance object, start position
  // and finish position is passed into function

  //Set up domain of Charactors wanted to print
  PrintWindow->StartingChar = Start;
  PrintWindow->FinishChar = Finish;
  PrintWindow->CurrentChar = Start;

  //Update State
  PrintingState = PromptPrintingList;

}

void PrintMenu()
{
  //Menu for user to select from:
  Serial.println("What would you like to see?");
  Serial.println("1 - All printable ASCII characters");
  Serial.println("2 - All numbers");
  Serial.println("3 - All lower case letters");
  Serial.println("4 - All capital letters");

  //Update State
  PrintingState = WaitingForInput;

}

void GetInputState()
{
  int IncomingCharacter;

  while(Serial.available() == 0)
  {
    //Do Nothing...
  } 

  //Get users incoming character
  IncomingCharacter = Serial.read();

  //match input to printing state
  switch(IncomingCharacter)
  {
  case '1':

    //User wants to print out all ASCII Characters
    PrintingState = PrintAllChar;

    break;

  case '2':

    //User wants to print out all ASCII Numbers
    PrintingState = PrintNumbers;

    break;

  case '3':

    //User wants to print out all ASCII lower letters
    PrintingState = PrintLower;

    break;

  case '4':

    //User wants to print out all ASCII Capital Letters
    PrintingState = PrintCapital;

    break;

  default:

    //User has made an error
    PrintingState = WaitingForInput;

    break;
  } 
}

void PrintLine(struct PrintingInstance *PrintWindow)
{
  //Address of a PrintingInstance object is passed into function

  //Prints a line based on what character is in 
  //object currently.

  //Note that "->" is used when dealing with structure elements
  //and pointers.

  //Declare what first print is going to be
  Serial.print("Character: ");
  //Print out current byte
  Serial.print(PrintWindow->CurrentChar, BYTE);

  //Declare what the second print will be
  Serial.print(", Dec: ");
  //Print out byte as Decimal (base 10)
  //(Note that the ", DEC" is not actually
  //needed by default)
  Serial.print(PrintWindow->CurrentChar, DEC);

  //Same with third print 
  Serial.print(", Hex: ");
  Serial.print(PrintWindow->CurrentChar, HEX);

  //Same with forth print
  Serial.print(", Oct: ");
  Serial.print(PrintWindow->CurrentChar, OCT);

  //Same with fith print
  Serial.print(", Binary: ");
  Serial.println(PrintWindow->CurrentChar, BIN);

  //If last character is found, switch to
  //a non printing state
  if(PrintWindow->CurrentChar == PrintWindow->FinishChar)

  {
    PrintingState = WaitingForInput;
  }

  //Increment current ASCII Byte
  PrintWindow->CurrentChar++;

}

And I have never posted anything on exhibition, so I thought that it would be different!

:slight_smile:

I think this might be a pretty useful technique for some; it shows some techniques that others may not know about (or think about), like the enum structure. Perhaps once you get some more feedback and/or corrections on it (not saying there are bugs, I don't know - I haven't tried it) - you should put it in the Playground for others...

:)