New idea for dealing with serial input and blocking

This probably won't be well accepted.. But how about callback that is called when a full c string has been read from the Serial port?

Like this..

#include "serialWatch.h"

serialWatch strReader;


void setup(void) {

   Serial.begin(57600);                                     // Fire up the serial stuff.
   Serial.println(F("Enter something. I'll repeat it."));   // Tell Mrs user to start inputting numbers.
   strReader.setCallback(haveStr);                          // Hook up our callback.
}


// Magically... Complete c strings show up here.
void haveStr(char* inStr) {
   
   int i=0;

   if (strReader.hadOverrun()) {                      // If we had an overrun..
      Serial.println(F("Oh no! overrun! Lost data!"));  // Tell the user.
   }
   Serial.print(F("Entered : "));                     // Show what we got..
   Serial.println(inStr);                             
   Serial.print(F("Reply   : "));                     // Show our repy.
   while(inStr[i]) {
      Serial.print((char)toupper(inStr[i++]));
   }
   Serial.println();
}


void loop(void) {

idle();
// And whatever else you would like to do in loop.
}

Still interested?

Here's the .h bit..

#ifndef serialWatch_h
#define serialWatch_h

#include <idlers.h>

class serialWatch :  public idler {

   public:
               serialWatch(char endChar='\n',int numBytes=64);
   virtual     ~serialWatch(void);

               void  setCallback(void(*funct)(char*)); // Use a callback for a complete string.
   virtual     void  idle(void);
               bool  hadOverrun(void);

               int   index;
               char  EOL;
               int   bytes;
               char* buff;
               void  (*callback)(char*);
               bool  overrun;
};

And the guts of the matter. The .cpp bit.

#include "serialWatch.h"
#include <resizeBuff.h>

 
serialWatch::serialWatch(char endChar,int numBytes) {

    index   = 0;
    EOL     = endChar;
    bytes   = numBytes;
    overrun = false;
    resizeBuff(numBytes,&buff);
}


serialWatch::~serialWatch(void) { resizeBuff(0,&buff); }


void serialWatch::setCallback(void(*funct)(char*)) { 

   callback = funct;
   hookup();
}


void serialWatch::idle(void) {

   char  aChar;
   
   if (Serial.available()) {        // If there is a char in the waiting to be read..
      aChar = Serial.read();        // Grab and save the char.
      if (aChar==EOL) {             // If its a newline char..
         callback(buff);            // call it.
         overrun = false;           // If set, cler the overrun flag.
         buff[0] = '\0';            // Clear the inBuff string.
         index = 0;                 // Reset the index to start a new number string.
      } else {                      // Else, it wasn't a newline char..
         if (index<bytes) {
            buff[index++] = aChar;  // So we save the char we got into the c string.
            buff[index] = '\0';     // And pop an end of string after it.
         } else {
            overrun = true;         // Just blew past the buffer.
         }
      }
   }
}



bool serialWatch::hadOverrun(void) { return overrun; }

I think its pretty slick! Gets rid of all those pesky while(available()) and read until things. Does not block. And, what could be easier than suddenly having your string all ready to go? Every newbie's dream!

-jim lee

1 Like

Quite a good idea.
I do similar in my own code (without a class)

This should cook a bit longer on the forum for optional suggested functionality, but it’s certainly a good idea.

(e.g. supporting a simple line editor within the input buffer BS, ESC etc).

Good thinking.

2 Likes

Looks quite interesting.

My problem, with simple libraries ex: timer.h etc., when I see them, I then have to download them, figure them out, and then try to respond.

Hence, I immediately mark the thread ignore this user.

Actually, I'm kinda/ the same way. That's why I write so many. I like my own ideas better than trying to follow someone else's.

But its hard to watch lemmings for so long.

-jim lee

A better version would pass a class that protects the buffer and provides access to hadOverrun.

I suspect you've written past the end of buff.

1 Like

You are right, Good catch! I counted wrong on my fingers. It should be..

if (index<bytes-1) {

But this was written as fast as I could type, so its not very well debugged.

I used the callback because I figured that would be the easiest to understand. Of course that can be argued forever.

-jim lee

I'm not suggesting dropping the callback. I'm suggesting a different argument for the callback. Something that carries more details and some safety.

Safety? What are you worried they may do to that string? It gets cleared the next line of code.

-jim lee

1 Like

Modify it. The argument you passed allows that. Modify before or after the extents of the buffer. The argument you passed allows that.

Yeah, well.. My feeling is : It's their foot and it's their gun.

-jim lee