More generic and scalable parser

Dependencies:   SLCD mbed-rtos mbed

Fork of Serial_IO_test_v6 by Stanley Cohen

Committer:
scohennm
Date:
Mon Mar 23 16:37:23 2015 +0000
Revision:
4:31207d384db0
Parent:
serialO_v6.cpp@3:2266158bf72f
NMHU serial command parser program - more generic and scalable

Who changed what in which revision?

UserRevisionLine numberNew contents of line
scohennm 2:8196b4cc681b 1 #include "mbed.h"
scohennm 2:8196b4cc681b 2 #include <iostream>
scohennm 2:8196b4cc681b 3 #include <stdio.h>
scohennm 2:8196b4cc681b 4 #include <ctype.h>
scohennm 2:8196b4cc681b 5 #include <string.h>
scohennm 2:8196b4cc681b 6 #include <locale.h>
scohennm 2:8196b4cc681b 7 #include "rtos.h"
scohennm 2:8196b4cc681b 8 #include "SLCD.h"
scohennm 3:2266158bf72f 9 // Debug printout control
scohennm 3:2266158bf72f 10 #define PRINTDBUG
scohennm 4:31207d384db0 11 #define PROGNAME "Serial_parser_v1 - sc\n\r"
scohennm 2:8196b4cc681b 12
scohennm 2:8196b4cc681b 13 #define LCDLEN 10
scohennm 2:8196b4cc681b 14 #define MAXCHAR 4
scohennm 2:8196b4cc681b 15 #define ALL8 "8888"
scohennm 2:8196b4cc681b 16 #define LCDUPDATE 100 //ms
scohennm 2:8196b4cc681b 17 #define LEDBLINKTIME 300 // ms *** NOTE Change of units ***
scohennm 2:8196b4cc681b 18 #define SERIALREADTIME 50 //ms
scohennm 2:8196b4cc681b 19 // ASCII constants
scohennm 2:8196b4cc681b 20 #define CR '\r'
scohennm 3:2266158bf72f 21 #define ALLNOTES "CDEFGAB" // Note only 7 unique notes.
scohennm 4:31207d384db0 22 #define NONOTE 7
scohennm 4:31207d384db0 23 #define OCTAVELLEN 7
scohennm 4:31207d384db0 24 #define VALIDOCTAVES "45"
scohennm 4:31207d384db0 25 #define NOOCTAVE 2
scohennm 4:31207d384db0 26 #define NUMTONES 14 // length of two octaves
scohennm 4:31207d384db0 27 #define COMMANDLEN 2 //Max characters in the command
scohennm 4:31207d384db0 28 #define NOTOK "NOK"
scohennm 4:31207d384db0 29
scohennm 3:2266158bf72f 30 #define NOTEOFFSET 1
scohennm 4:31207d384db0 31 #define NOTEINVALID 20 // length of
scohennm 2:8196b4cc681b 32
scohennm 2:8196b4cc681b 33
scohennm 2:8196b4cc681b 34
scohennm 4:31207d384db0 35 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};
scohennm 2:8196b4cc681b 36
scohennm 2:8196b4cc681b 37 DigitalOut rLed(LED_RED);
scohennm 2:8196b4cc681b 38
scohennm 2:8196b4cc681b 39
scohennm 2:8196b4cc681b 40 Serial pc(USBTX, USBRX); // tx, rx
scohennm 2:8196b4cc681b 41 SLCD slcd; //define LCD display
scohennm 2:8196b4cc681b 42 char rxChar;
scohennm 2:8196b4cc681b 43 char rxString[LCDLEN];
scohennm 2:8196b4cc681b 44 string rxRealString;
scohennm 4:31207d384db0 45 bool commandReady = false; // This is the flag to even look at the command string
scohennm 2:8196b4cc681b 46
scohennm 2:8196b4cc681b 47 void clearString (char * aString){
scohennm 2:8196b4cc681b 48 int i;
scohennm 2:8196b4cc681b 49 int sSize = sizeof(aString);
scohennm 2:8196b4cc681b 50
scohennm 2:8196b4cc681b 51 for (i=0; i< sSize; i++){
scohennm 2:8196b4cc681b 52 aString[i] = NULL;
scohennm 2:8196b4cc681b 53 }
scohennm 2:8196b4cc681b 54 return;
scohennm 2:8196b4cc681b 55 }
scohennm 2:8196b4cc681b 56
scohennm 2:8196b4cc681b 57
scohennm 3:2266158bf72f 58 int isNote(char theNote){ //check for valid onte
scohennm 3:2266158bf72f 59 int noteListLen = sizeof(ALLNOTES);
scohennm 3:2266158bf72f 60 int pos = NONOTE;
scohennm 3:2266158bf72f 61 int i;
scohennm 3:2266158bf72f 62 for (i=0; i<noteListLen; i++){
scohennm 3:2266158bf72f 63 if (ALLNOTES[i] == theNote){
scohennm 3:2266158bf72f 64 pos = i;
scohennm 3:2266158bf72f 65 break;
scohennm 3:2266158bf72f 66 }
scohennm 3:2266158bf72f 67 }
scohennm 3:2266158bf72f 68 return (pos);
scohennm 3:2266158bf72f 69 }
scohennm 3:2266158bf72f 70
scohennm 4:31207d384db0 71 int isOctave(char theOct){ //check for valid onte
scohennm 4:31207d384db0 72 int noteListLen = sizeof(VALIDOCTAVES);
scohennm 4:31207d384db0 73 int pos = NOOCTAVE;
scohennm 4:31207d384db0 74 int i;
scohennm 4:31207d384db0 75 for (i=0; i<noteListLen; i++){
scohennm 4:31207d384db0 76 if (VALIDOCTAVES[i] == theOct){
scohennm 4:31207d384db0 77 pos = i;
scohennm 4:31207d384db0 78 break;
scohennm 4:31207d384db0 79 }
scohennm 4:31207d384db0 80 }
scohennm 4:31207d384db0 81 return (pos);
scohennm 4:31207d384db0 82 }
scohennm 2:8196b4cc681b 83
scohennm 4:31207d384db0 84 /* one way to do the parsing **************
scohennm 4:31207d384db0 85 void parseCommand (char * commandChars){
scohennm 4:31207d384db0 86 int charPos = 0;
scohennm 4:31207d384db0 87 int noteIndex = 0; // this is the length into the diatonic scale array
scohennm 4:31207d384db0 88 bool validCommand = false;
scohennm 4:31207d384db0 89
scohennm 4:31207d384db0 90 noteIndex = isNote(commandChars[charPos]);
scohennm 4:31207d384db0 91 validCommand = (noteIndex != NONOTE); // First test for a good command string
scohennm 4:31207d384db0 92 if (validCommand) {
scohennm 4:31207d384db0 93 charPos++;
scohennm 4:31207d384db0 94 noteIndex = noteIndex + OCTAVELLEN * isOctave(commandChars[charPos]);
scohennm 4:31207d384db0 95 validCommand = (noteIndex < NUMTONES); // Final test for a good string
scohennm 4:31207d384db0 96 }
scohennm 4:31207d384db0 97 #ifdef PRINTDBUG
scohennm 4:31207d384db0 98 if (validCommand) {
scohennm 4:31207d384db0 99 pc.printf("%s - IsNote - %4.2f OK\n\r", rxString, diatonicScale[noteIndex]);
scohennm 4:31207d384db0 100 sprintf(rxString,"%4.1f", diatonicScale[noteIndex]); // show frequency on LCD
scohennm 4:31207d384db0 101 } else {
scohennm 4:31207d384db0 102 pc.printf("%s - Not a Note NOK\n\r", rxString);
scohennm 4:31207d384db0 103 sprintf(rxString,"%s", NOTOK );
scohennm 4:31207d384db0 104 }
scohennm 4:31207d384db0 105 #endif
scohennm 4:31207d384db0 106 return;
scohennm 4:31207d384db0 107 }
scohennm 4:31207d384db0 108 **************** */
scohennm 4:31207d384db0 109 // calculating the valid command
scohennm 4:31207d384db0 110 void parseCommand (char * commandChars){
scohennm 4:31207d384db0 111 #define NOTEPOS 0 // index of note and octive tokens
scohennm 4:31207d384db0 112 #define OCTPOS 1
scohennm 4:31207d384db0 113 int noteIndex;
scohennm 4:31207d384db0 114 int octaveIndex;
scohennm 4:31207d384db0 115 int diatonicArrayIndex = 0; // this is the length into the diatonic scale array
scohennm 4:31207d384db0 116 bool validCommand = false;
scohennm 4:31207d384db0 117
scohennm 4:31207d384db0 118 noteIndex = isNote(commandChars[NOTEPOS]);
scohennm 4:31207d384db0 119 octaveIndex = isOctave(commandChars[OCTPOS]);
scohennm 4:31207d384db0 120 validCommand = ((noteIndex != NONOTE)&&(octaveIndex != NOOCTAVE)); // test for good command string
scohennm 4:31207d384db0 121 #ifdef PRINTDBUG
scohennm 4:31207d384db0 122 if (validCommand) {
scohennm 4:31207d384db0 123 diatonicArrayIndex = noteIndex + (OCTAVELLEN * octaveIndex);
scohennm 4:31207d384db0 124 pc.printf("%s - IsNote - %4.2f OK\n\r", rxString, diatonicScale[diatonicArrayIndex]);
scohennm 4:31207d384db0 125 sprintf(rxString,"%4.1f", diatonicScale[diatonicArrayIndex]); // show frequency on LCD
scohennm 4:31207d384db0 126 } else {
scohennm 4:31207d384db0 127 pc.printf("%s - Not a Note NOK\n\r", rxString);
scohennm 4:31207d384db0 128 sprintf(rxString,"%s", NOTOK );
scohennm 4:31207d384db0 129 }
scohennm 4:31207d384db0 130 #endif
scohennm 4:31207d384db0 131 return;
scohennm 4:31207d384db0 132 }
scohennm 2:8196b4cc681b 133 void LCDMessNoDwell(char *lMess){
scohennm 2:8196b4cc681b 134 slcd.Home();
scohennm 2:8196b4cc681b 135 slcd.clear();
scohennm 2:8196b4cc681b 136 slcd.printf(lMess);
scohennm 2:8196b4cc681b 137 }
scohennm 2:8196b4cc681b 138
scohennm 2:8196b4cc681b 139 // use "thread" in the name to keep things straight
scohennm 2:8196b4cc681b 140 // note the use of void constant * args - understand memory resources
scohennm 2:8196b4cc681b 141 // Thes are "forever loops"
scohennm 2:8196b4cc681b 142 void LCDdis_thread(void const *args){
scohennm 2:8196b4cc681b 143 while(true) {
scohennm 2:8196b4cc681b 144 LCDMessNoDwell(rxString);
scohennm 2:8196b4cc681b 145 Thread::wait(LCDUPDATE);
scohennm 2:8196b4cc681b 146 }
scohennm 2:8196b4cc681b 147 }
scohennm 2:8196b4cc681b 148
scohennm 4:31207d384db0 149
scohennm 2:8196b4cc681b 150 void serial_thread(void const *args){
scohennm 2:8196b4cc681b 151 static int charIndex =0;
scohennm 2:8196b4cc681b 152 int rxStringLen;
scohennm 2:8196b4cc681b 153 while(true) {
scohennm 2:8196b4cc681b 154 if (pc.readable()) { // only read from the serial port if there is a character
scohennm 3:2266158bf72f 155 rxChar= toupper(pc.getc()); // reading clears the buffer
scohennm 4:31207d384db0 156 // noteOK = isNote(rxChar);
scohennm 2:8196b4cc681b 157 // construct a 4-digit string for the LCD
scohennm 2:8196b4cc681b 158 // check for carriage return
scohennm 2:8196b4cc681b 159 if (rxChar == CR) {
scohennm 2:8196b4cc681b 160 rxRealString.assign(rxString);
scohennm 3:2266158bf72f 161 rxStringLen = rxRealString.length();
scohennm 4:31207d384db0 162 if(rxStringLen == COMMANDLEN) { // if the input string does not equal the expected
scohennm 4:31207d384db0 163 parseCommand(rxString); // command length it's not a good command
scohennm 4:31207d384db0 164 } else {
scohennm 4:31207d384db0 165 #ifdef PRINTDBUG
scohennm 4:31207d384db0 166 pc.printf("%s NOK\n\r", rxString);
scohennm 4:31207d384db0 167 sprintf(rxString,"%s", NOTOK );
scohennm 4:31207d384db0 168 #endif
scohennm 4:31207d384db0 169 }
scohennm 2:8196b4cc681b 170 charIndex = 0; // start building string from position zero next time around
scohennm 2:8196b4cc681b 171 } else {
scohennm 2:8196b4cc681b 172 if(charIndex == 0) clearString(rxString);
scohennm 2:8196b4cc681b 173 rxString[charIndex] = rxChar;
scohennm 4:31207d384db0 174 rxRealString.assign(rxString);
scohennm 3:2266158bf72f 175 #ifdef PRINTDBUG
scohennm 4:31207d384db0 176 pc.printf("%s\n\r", rxString); // This echo's the new char and prevous up to 4 chars
scohennm 4:31207d384db0 177 #endif
scohennm 4:31207d384db0 178 charIndex = (charIndex + 1)% (MAXCHAR); // Only allow 4 characters then roll over
scohennm 2:8196b4cc681b 179 }
scohennm 2:8196b4cc681b 180 }
scohennm 2:8196b4cc681b 181 Thread::wait(SERIALREADTIME);
scohennm 2:8196b4cc681b 182 }
scohennm 2:8196b4cc681b 183 }
scohennm 2:8196b4cc681b 184
scohennm 2:8196b4cc681b 185 int main()
scohennm 2:8196b4cc681b 186 {
scohennm 2:8196b4cc681b 187
scohennm 2:8196b4cc681b 188 Thread lthread(LCDdis_thread);
scohennm 2:8196b4cc681b 189 Thread serthread(serial_thread);
scohennm 2:8196b4cc681b 190
scohennm 2:8196b4cc681b 191 sprintf(rxString,"%s",ALL8); // just put something on the LCD to show it's working
scohennm 3:2266158bf72f 192
scohennm 3:2266158bf72f 193 #ifdef PRINTDBUG
scohennm 3:2266158bf72f 194 pc.printf(PROGNAME);
scohennm 3:2266158bf72f 195 #endif
scohennm 2:8196b4cc681b 196
scohennm 2:8196b4cc681b 197 while (true) {
scohennm 2:8196b4cc681b 198 rLed = !rLed; // toggle led
scohennm 2:8196b4cc681b 199 Thread::wait(LEDBLINKTIME);
scohennm 2:8196b4cc681b 200 }
scohennm 2:8196b4cc681b 201 }