This is the SerialBuffered class, which wraps Serial and adds interrupt-powered buffered reading (so it will catch inbound data even when your app is busy doing something else) and simple read timeouts. There's a tiny demo app in there too.

Dependencies:   mbed

Files at this revision

API Documentation at this revision

Comitter:
jarkman
Date:
Wed Nov 18 21:27:15 2009 +0000
Commit message:

Changed in this revision

SerialBuffered.cpp Show annotated file Show diff for this revision Revisions of this file
SerialBuffered.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r b55ca3bb8017 SerialBuffered.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SerialBuffered.cpp	Wed Nov 18 21:27:15 2009 +0000
@@ -0,0 +1,108 @@
+
+#include "mbed.h"
+#include "SerialBuffered.h"
+ 
+extern Serial loggerSerial;
+ 
+SerialBuffered::SerialBuffered( size_t bufferSize, PinName tx, PinName rx ) : Serial(  tx,  rx ) 
+{
+    m_buffSize = 0;
+    m_contentStart = 0;
+    m_contentEnd = 0;
+    m_timeout = 1.0;
+   
+    
+    attach( this, &SerialBuffered::handleInterrupt );
+    
+    m_buff = (uint8_t *) malloc( bufferSize );
+    if( m_buff == NULL )
+    {
+        //loggerSerial.printf("SerialBuffered - failed to alloc buffer size %d\r\n", (int) bufferSize );
+    }
+    else
+    {
+        m_buffSize = bufferSize;
+    }
+}
+
+
+SerialBuffered::~SerialBuffered()
+{
+    if( m_buff )
+        free( m_buff );
+}
+
+void SerialBuffered::setTimeout( float seconds )
+{
+    m_timeout = seconds;
+}
+    
+size_t SerialBuffered::readBytes( uint8_t *bytes, size_t requested )
+{
+    int i = 0;
+
+    for( ; i < requested; )
+    {
+        int c = getc();
+        if( c < 0 )
+            break;
+        bytes[i] = c;
+        i++;
+    }
+    
+    return i;
+        
+}
+
+
+int SerialBuffered::getc()
+{
+    m_timer.reset();
+    m_timer.start();
+    while( m_contentStart == m_contentEnd )
+    {
+      
+
+        wait_ms( 1 );
+        if( m_timeout > 0 &&  m_timer.read() > m_timeout )
+            return EOF;
+    }
+
+    m_timer.stop();
+   
+    uint8_t result = m_buff[m_contentStart++];
+    m_contentStart =  m_contentStart % m_buffSize;
+
+   
+    return result;    
+}
+
+
+int SerialBuffered::readable()
+{
+    return m_contentStart != m_contentEnd ;
+}
+
+void SerialBuffered::handleInterrupt()
+{
+    
+    while( Serial::readable())
+    {
+        if( m_contentStart == (m_contentEnd +1) % m_buffSize)
+        {
+           loggerSerial.printf("SerialBuffered - buffer overrun, data lost!\r\n" );
+           Serial::getc();
+
+        }
+        else
+        {
+          
+            m_buff[ m_contentEnd ++ ] = Serial::getc();
+            m_contentEnd = m_contentEnd % m_buffSize;
+            
+           
+           
+        }
+    }
+}
+
diff -r 000000000000 -r b55ca3bb8017 SerialBuffered.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SerialBuffered.h	Wed Nov 18 21:27:15 2009 +0000
@@ -0,0 +1,39 @@
+#pragma once
+
+// This is a buffered serial reading class, using the serial interrupt introduced in mbed library version 18 on 17/11/09
+
+// In the simplest case, construct it with a buffer size at least equal to the largest message you 
+// expect your program to receive in one go.
+
+class SerialBuffered : public Serial
+{
+public:
+    SerialBuffered( size_t bufferSize, PinName tx, PinName rx );
+    virtual ~SerialBuffered();
+    
+    int getc();     // will block till the next character turns up, or return -1 if there is a timeout
+    
+    int readable(); // returns 1 if there is a character available to read, 0 otherwise
+    
+    void setTimeout( float seconds );    // maximum time in seconds that getc() should block 
+                                         // while waiting for a character
+                                         // Pass -1 to disable the timeout.
+    
+    size_t readBytes( uint8_t *bytes, size_t requested );    // read requested bytes into a buffer, 
+                                                             // return number actually read, 
+                                                             // which may be less than requested if there has been a timeout
+    
+
+private:
+    
+    void handleInterrupt();
+    
+   
+    uint8_t *m_buff;            // points at a circular buffer, containing data from m_contentStart, for m_contentSize bytes, wrapping when you get to the end
+    uint16_t  m_contentStart;   // index of first bytes of content
+    uint16_t  m_contentEnd;     // index of bytes after last byte of content
+    uint16_t m_buffSize;
+    float m_timeout;
+    Timer m_timer;
+
+};
\ No newline at end of file
diff -r 000000000000 -r b55ca3bb8017 main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Wed Nov 18 21:27:15 2009 +0000
@@ -0,0 +1,67 @@
+#include "mbed.h"
+#include "SerialBuffered.h"
+
+Serial loggerSerial(USBTX, USBRX);
+
+// run this with p13 joined to p14 to test the SerialBuffered class 
+
+int main() {
+
+   SerialBuffered *b = new SerialBuffered( 1001, p13, p14);
+   
+   b->baud( 112500 );
+   b->setTimeout( 0.1 );
+   
+    // write a bufferful   
+   for( int i = 0; i < 1000; i ++ )
+   {
+       b->putc( i % 0xff );
+   }
+   
+   // and check it all arrived
+   for( int i = 0; i < 1000; i ++ )
+   {
+       uint8_t j = b->getc();
+       if( j != i % 0xff )
+       {
+           loggerSerial.printf("Bad byte %x at %x\r\n", j, i );
+           break;
+       }
+       
+   }
+    
+   // write another bufferful 
+   for( int i = 0; i < 1000; i ++ )
+   {
+       b->putc( i % 0xff );
+   }
+   
+   // and check it arrived too, to confirm the circular buffer is working
+   for( int i = 0; i < 1000; i ++ )
+   {
+       uint8_t j = b->getc();
+       if( j != i % 0xff )
+       {
+           loggerSerial.printf("Bad byte %x at %x\r\n", j, i );
+           break;
+       }
+   }
+   
+    // write another bufferful, deliberately short
+   for( int i = 0; i < 999; i ++ )
+   {
+       b->putc( i % 0xff );
+   }
+
+
+   // and read it back with readBytes   
+   b->setTimeout( 5 ); // set a long timeout so we can see we are waiting for it
+
+
+   uint8_t *buff = (uint8_t*) malloc( 1000 );
+   int nRead = b->readBytes( buff, 1000 );
+   
+   loggerSerial.printf("readBytes got %d\r\n", nRead );       
+   
+   loggerSerial.printf("Done\r\n");    
+}
diff -r 000000000000 -r b55ca3bb8017 mbed.bld
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Wed Nov 18 21:27:15 2009 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/32af5db564d4