I've extracted the parser parts of a library I made myself (of which I do not want to post the whole thing) and added them to a sketch using your LineReceiver - to say this implementation is a bit kludgy might be like saying sewers are a little smelly but in my defense I can't really spend a lot of time on it right this second and my 'strfig' stuff was made to be called like 'strfig(&myBuffer[myPtr],&myPtr[,cmds])' and by using it that way you didn't have to fix the buffer pointer (accord the offset) and zero the offset for each little call - you could literally just go "Serial.printf("3 values=%f,%f,%f\n",strfig(&myBuffer[myPtr],&myPtr),strfig(&myBuffer[myPtr],&myPtr),strfig(&myBuffer[myPtr],&myPtr));" and it would take care of itself to the end of the buffer.
Maybe it is all just ugly and nobody wants anything like it, but just in case:
Compiled and worked for me (not too embarrassingly) using Arduino 1.6.1 & Teensyduino 1.21 - it should happily show decimal results of you entering hex like 0x40; I was mistaken thinking I bothered making any code for converting numbers the other way, I just used printf
Maybe it is all just ugly and nobody wants anything like it, but just in case:
Code:
#include <LineReceiver.h>
float strHex(char* buf, unsigned char* ptr) // I don't usually leave strHex directly callable, it is a float hidden away in the .cpp file because I figure I just want to call strfig
{
unsigned char go=1;
unsigned char breaker=0;
float tmp=0;
while((*buf<48)&&(*buf!=0)) // while the buffer content at pointer is any of the symbolic or special characters advance unless you hit \0
{
buf++; // the pointer into the buffer the user passed us
*ptr+=1; // the user's copy of the buffer pointer is updated
}
if((*buf=='0')&&(*(buf+1)=='x'))
{
buf+=2; // just skipping over '0x' in the string
*ptr+=2; // I'm not going to explain this again.
}
if(*buf==0) return 0; // what number?
while(go!=0&&(++breaker)) {
if((*buf>64)&&(*buf<71)) *buf-=7; // 'A'-'F' modify appropriately for basic math below
if((*buf>96)&&(*buf<103)) *buf-=39; // 'a'-'f' lower case has to be catered - tempting to just add necessary & (& brackets!) in line above to line above but nvm.
if((*buf>47)&&(*buf<64)) { // so, if this could have been valid hex in text before it got mangled by either of preceeding lines we multiply and add appropriately.
tmp=(tmp*16)+((*buf)-48);
buf++;
*ptr+=1;
} else {
go=0; // we are done, stop looping.
}
}
return tmp;
}
float strfig(char* buf, unsigned char* ptr) // floating point number parser.
{
unsigned char go=1;
unsigned char breaker=0;
float tmp=0;
float frac=0;
float sign1=1; // I'm not going to comment this one up atm, soz.
while(go!=0&&(++breaker)) {
if(*buf!=0) {
if((*buf<33)||(*buf=='=')||(*buf==',')||(*buf==';')||(*buf==':')) {
buf++;
*ptr+=1;
} else {
go=0;
}
} else {
go=0;
}
}
if(((*buf==0)||(*buf<48)||(*buf>57))&&(*buf!='-')) {
return 0;
}
if(*buf=='-')
{
sign1=-1;
buf++;
*ptr+=1;
}
if((*buf=='0')&&(*(buf+1)=='x')) {
return sign1*strHex(buf,ptr);
}
go=1;
while(go!=0&&(++breaker)) {
if((*buf>47)&&(*buf<58)) {
if(frac)
{
tmp=tmp+(((*buf)-48)/frac);
frac*=10;
} else {
tmp=(tmp*10)+((*buf)-48);
}
buf++;
*ptr+=1;
} else if(*buf=='.') {
if(frac) return sign1*tmp; // second decimal point in a number is bullshit.
frac=10;
buf++;
*ptr+=1;
} else {
go=0;
}
}
return sign1*tmp;
}
unsigned char strfig(char* buf1, unsigned char* ptr, const char* cPtr) // parses looking for a match in a list held in obvious enough format,
{ // returns location in list counting from 1 where 0 means no match and the ptr was not advanced
const char * sPtr; // temporary copy for cPtr
char * tPtr; // temporary copy of buf1
unsigned char count=0,cnt2,go=1; // some counter variables to track stuff.
while(go)
{
count++; // this counter will be returned to the user's sketch if there is a match
sPtr=cPtr; // copy the pointer to the const char cmds[] array
while(*cPtr!=0) { // while the content of the array at this pointer is not 0
cPtr++; // advance it
}
cPtr++; // now shift it onto the start of the next command, or the trailing \0 terminator
tPtr=buf1; // we use a copy of the Buf1 pointer because we need to be able to reset here repeatedly
cnt2=0; // cnt2 will track along how much to shift the end user's pointer by.
while((*sPtr==*tPtr)&&(*tPtr!=0)) // While the cmd being compared now matches and we don't hit the \0 expected at the end of *Buf1[]
{
cnt2++;
sPtr++; // just all advance along
tPtr++;
}
if(*sPtr==0) // the cmd matched if the temporary pointer for cmd[] is 'parked' on a terminator at this point in the processing.
{
*ptr+=cnt2; // adjust the end user's pointer kindly for them
return count; // count= which of "first\0second\0third\0forth\0so-on\0last\0\0" matched at the position in the buffer the routine was handed as buf1.
}
go=*cPtr; // at this point if there is another cmd then this pointer in cmd[] will be pointing at the first character, if not it will be on the second terminator which is expected.
}
return 0; // none matched, we did not mangle anything, you can try something else on the buffer if you like.
}
// commands are stored simply enough
const char cmds[]="test1\0test2\0test3\0tested\0\0";
void LineIn(const char* line)
{
// Serial.printf("callback; %s\n", line);
uint8_t ptr=0; // I need to find out how much strfig routines would have adjusted the pointer each time.
uint16_t temp1,temp2; // not owning the buffer means I cannot use strfig as easily as intended without some 'mucking about', I chose this way for the time I felt I could spare it.
char* line1=(char*)line; // The darn const won't work the way I need it to for the methods I am applying.
while(*line1!=0) // while we don't hit the end of the line.
{
switch(strfig(line1,&ptr,cmds)) { // check for cmds[]
case 1: // test1
line1+=ptr; // just moving my non const pointer to the position after the cmd[] because it needs doing.
ptr=0; // Letting this accumulate would be really !funny
Serial.printf("test1=%u\n",(uint16_t)strfig(line1, &ptr)); // strfig is a float and I told printf I was going to give it an unsigned integer of some sort, I figure 16 bits will do and casting is cool.
line1+=ptr; // lol, I wish I owned that darn buffer!
ptr=0;
break;
case 2: // test2
line1+=ptr;
ptr=0;
temp1=(uint16_t)strfig(line1, &ptr);
line1+=ptr;
ptr=0;
Serial.printf("test2=%u,%u\n",temp1,(uint16_t)strfig(line1, &ptr));
line1+=ptr;
ptr=0;
break;
case 3: // test3
line1+=ptr;
ptr=0;
temp1=(uint16_t)strfig(line1, &ptr);
line1+=ptr;
ptr=0;
temp2=(uint16_t)strfig(line1, &ptr);
line1+=ptr;
ptr=0;
Serial.printf("test3=%u,%u,%u\n",temp1,temp2,(uint16_t)strfig(line1, &ptr));
line1+=ptr;
ptr=0;
break;
case 4: // tested
line1+=ptr;
ptr=0;
Serial.println("Kludgy but tested :)");
break;
default:
line1+=(ptr+1);
ptr=0;
}
}
}
LineReceiver LineR(64,LineIn);
void setup() {
Serial.begin(Serial.baud());
}
elapsedMillis heartbeat;
void loop() {
if(Serial.available()) {
LineR.push(Serial.read());
heartbeat=0; // if you are talking to me I don't need to invite you so much
}
/* if(Serial.available())
{
if(LineR.push(Serial.read()))
{
Serial.println("LineR.push(Serial.read()) returned 'true'");
}
} */
if(heartbeat>10000)
{
Serial.println("(send me: test1=# or test2 # # or test3:#,#;# or tested coz I am pretty forgiving...)");
heartbeat=0;
}
}
Last edited: