More generic and scalable parser

Dependencies:   SLCD mbed-rtos mbed

Fork of Serial_IO_test_v6 by Stanley Cohen

Serial_parser_v1.cpp

Committer:
scohennm
Date:
2015-03-23
Revision:
4:31207d384db0
Parent:
serialO_v6.cpp@ 3:2266158bf72f

File content as of revision 4:31207d384db0:

#include "mbed.h"
#include <iostream>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <locale.h> 
#include "rtos.h"
#include "SLCD.h"
// Debug printout control
#define PRINTDBUG
#define PROGNAME        "Serial_parser_v1 - sc\n\r"

#define LCDLEN          10
#define MAXCHAR         4
#define ALL8          "8888"
#define LCDUPDATE       100 //ms
#define LEDBLINKTIME    300 // ms *** NOTE Change of units ***
#define SERIALREADTIME  50 //ms
// ASCII constants
#define CR              '\r'
#define ALLNOTES        "CDEFGAB" // Note only 7 unique notes.
#define NONOTE          7
#define OCTAVELLEN      7
#define VALIDOCTAVES    "45"
#define NOOCTAVE        2
#define NUMTONES        14 // length of two octaves
#define COMMANDLEN      2 //Max characters in the command
#define NOTOK           "NOK"

#define NOTEOFFSET      1
#define NOTEINVALID     20 // length of



float diatonicScale[NUMTONES] = {261.63,293.66,329.63,349.23,392.00,440.00,493.88,523.25,587.33,659.25,698.46,783.99,880.00,987.77};

DigitalOut rLed(LED_RED);

 
Serial pc(USBTX, USBRX); // tx, rx
SLCD slcd; //define LCD display
char rxChar;
char rxString[LCDLEN];
string rxRealString;
bool commandReady = false; // This is the flag to even look at the command string

void clearString (char * aString){
    int i;
    int sSize = sizeof(aString);
    
    for (i=0; i< sSize; i++){
        aString[i] = NULL;
    }
    return;
}
    
    
int isNote(char theNote){ //check for valid onte
    int noteListLen = sizeof(ALLNOTES);
    int pos = NONOTE;
    int i;
    for (i=0; i<noteListLen; i++){
        if (ALLNOTES[i] == theNote){
            pos = i;
            break;
        }
    }
    return (pos);
}

int isOctave(char theOct){ //check for valid onte
    int noteListLen = sizeof(VALIDOCTAVES);
    int pos = NOOCTAVE;
    int i;
    for (i=0; i<noteListLen; i++){
        if (VALIDOCTAVES[i] == theOct){
            pos = i;
            break;
        }
    }
    return (pos);
}

/* one way to do the parsing **************
void parseCommand (char * commandChars){
    int charPos = 0;  
    int noteIndex = 0; // this is the length into the diatonic scale array
    bool validCommand = false;
    
    noteIndex = isNote(commandChars[charPos]);
    validCommand = (noteIndex != NONOTE); // First test for a good command string
    if (validCommand) {
        charPos++;
        noteIndex = noteIndex + OCTAVELLEN * isOctave(commandChars[charPos]);
        validCommand = (noteIndex < NUMTONES); // Final test for a good string
    }
#ifdef PRINTDBUG
    if (validCommand) {
        pc.printf("%s - IsNote - %4.2f OK\n\r", rxString, diatonicScale[noteIndex]); 
        sprintf(rxString,"%4.1f", diatonicScale[noteIndex]); // show frequency on LCD
    } else {
        pc.printf("%s - Not a Note NOK\n\r", rxString);
        sprintf(rxString,"%s", NOTOK );
    } 
#endif
    return;
}
**************** */   
// calculating the valid command
void parseCommand (char * commandChars){
#define NOTEPOS     0 // index of note and octive tokens
#define OCTPOS      1
    int noteIndex;
    int octaveIndex;
    int diatonicArrayIndex = 0; // this is the length into the diatonic scale array
    bool validCommand = false;
    
    noteIndex = isNote(commandChars[NOTEPOS]);
    octaveIndex = isOctave(commandChars[OCTPOS]);
    validCommand = ((noteIndex != NONOTE)&&(octaveIndex != NOOCTAVE)); // test for good command string
#ifdef PRINTDBUG
    if (validCommand) {
        diatonicArrayIndex = noteIndex + (OCTAVELLEN * octaveIndex);
        pc.printf("%s - IsNote - %4.2f OK\n\r", rxString, diatonicScale[diatonicArrayIndex]); 
        sprintf(rxString,"%4.1f", diatonicScale[diatonicArrayIndex]); // show frequency on LCD
    } else {
        pc.printf("%s - Not a Note NOK\n\r", rxString);
        sprintf(rxString,"%s", NOTOK );
    } 
#endif
    return;
}
void LCDMessNoDwell(char *lMess){
        slcd.Home();
        slcd.clear();
        slcd.printf(lMess);
}

// use "thread" in the name to keep things straight 
// note the use of void constant * args - understand memory resources
// Thes are "forever loops"
void LCDdis_thread(void const *args){
    while(true) {
        LCDMessNoDwell(rxString);
        Thread::wait(LCDUPDATE);
    }
}


void serial_thread(void const *args){
   static int charIndex =0;
   int rxStringLen;
   while(true) {
      if (pc.readable()) {                // only read from the serial port if there is a character
            rxChar= toupper(pc.getc());           // reading clears the buffer
            // noteOK = isNote(rxChar);
            // construct a 4-digit string for the LCD          
            // check for carriage return           
            if (rxChar == CR) { 
                rxRealString.assign(rxString);                                                                
                rxStringLen = rxRealString.length();  
                 if(rxStringLen == COMMANDLEN) { // if the input string does not equal the expected 
                     parseCommand(rxString);     // command length it's not a good command 
                 } else { 
 #ifdef PRINTDBUG
                    pc.printf("%s NOK\n\r", rxString); 
                    sprintf(rxString,"%s", NOTOK );
#endif                                     
                }
                charIndex = 0; // start building string from position zero next time around
            } else {
                if(charIndex == 0) clearString(rxString);
                rxString[charIndex] = rxChar;
                rxRealString.assign(rxString); 
#ifdef PRINTDBUG
                    pc.printf("%s\n\r", rxString); // This echo's the new char and prevous up to 4 chars
#endif        
                charIndex = (charIndex + 1)% (MAXCHAR); // Only allow 4 characters then roll over            
            }
      }
      Thread::wait(SERIALREADTIME);
    }
}

int main()
{  
 
    Thread lthread(LCDdis_thread);
    Thread serthread(serial_thread);
    
    sprintf(rxString,"%s",ALL8);  // just put something on the LCD to show it's working
    
#ifdef PRINTDBUG
        pc.printf(PROGNAME);
#endif

    while (true) {     
        rLed = !rLed; // toggle led
        Thread::wait(LEDBLINKTIME);
    }
}