Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 27 additions & 13 deletions CmdMessenger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,20 +50,34 @@ extern "C" {

#define _CMDMESSENGER_VERSION 3_6 // software version of this library

// **** Initialization ****
#if defined(__MBED__) || defined(MBED_STREAM_H)
#define BYTEAVAILLABLE(comms) comms->readable()
#define READONECHAR(comms) comms->getc()
#define PRINTONECHAR(comms,c) comms->putc(c)
#define PRINTSTRING(comms,s) comms->puts(s)
#define millis() (us_ticker_read()/1000)
#endif
#if defined(ARDUINO) && !defined(MBED_STREAM_H)
#define BYTEAVAILLABLE(comms) comms->available()
#define READONECHAR(comms) comms->read()
#define PRINTONECHAR(comms,c) comms->print(c)
#define PRINTSTRING(comms,s) comms->print(s)
#endif

// **** Initialization ****

/**
* CmdMessenger constructor
*/
CmdMessenger::CmdMessenger(Stream &ccomms, const char fld_separator, const char cmd_separator, const char esc_character)
CmdMessenger::CmdMessenger(__DEVICESTREAMTYPE &ccomms, const char fld_separator, const char cmd_separator, const char esc_character)
{
init(ccomms, fld_separator, cmd_separator, esc_character);
}

/**
* Enables printing newline after a sent command
*/
void CmdMessenger::init(Stream &ccomms, const char fld_separator, const char cmd_separator, const char esc_character)
void CmdMessenger::init(__DEVICESTREAMTYPE &ccomms, const char fld_separator, const char cmd_separator, const char esc_character)
{
default_callback = NULL;
comms = &ccomms;
Expand Down Expand Up @@ -112,7 +126,7 @@ void CmdMessenger::attach(messengerCallbackFunction newFunction)
/**
* Attaches a function to a command ID
*/
void CmdMessenger::attach(byte msgId, messengerCallbackFunction newFunction)
void CmdMessenger::attach(CmdMsgByte msgId, messengerCallbackFunction newFunction)
{
if (msgId >= 0 && msgId < MAXCALLBACKS)
callbackList[msgId] = newFunction;
Expand All @@ -127,7 +141,7 @@ void CmdMessenger::feedinSerialData()
{
while (!pauseProcessing && comms->available())
{
// The Stream class has a readBytes() function that reads many bytes at once. On Teensy 2.0 and 3.0, readBytes() is optimized.
// The Stream class has a readBytes() function that reads many bytes at once. On Teensy 2.0 and 3.0, readBytes() is optimized.
// Benchmarks about the incredible difference it makes: http://www.pjrc.com/teensy/benchmark_usb_serial_receive.html

size_t bytesAvailable = min(comms->available(), MAXSTREAMBUFFERSIZE);
Expand Down Expand Up @@ -188,7 +202,7 @@ void CmdMessenger::handleMessage()
/**
* Waits for reply from sender or timeout before continuing
*/
bool CmdMessenger::blockedTillReply(unsigned int timeout, byte ackCmdId)
bool CmdMessenger::blockedTillReply(unsigned int timeout, CmdMsgByte ackCmdId)
{
unsigned long time = millis();
unsigned long start = time;
Expand All @@ -203,10 +217,10 @@ bool CmdMessenger::blockedTillReply(unsigned int timeout, byte ackCmdId)
/**
* Loops as long data is available to determine if acknowledge has come in
*/
bool CmdMessenger::checkForAck(byte ackCommand)
bool CmdMessenger::checkForAck(CmdMsgByte ackCommand)
{
while (comms->available()) {
//Processes a byte and determines if an acknowlegde has come in
//Processes a CmdMsgByte and determines if an acknowlegde has come in
int messageState = processLine(comms->read());
if (messageState == kEndOfMessage) {
int id = readInt16Arg();
Expand Down Expand Up @@ -275,7 +289,7 @@ uint8_t CmdMessenger::commandID()
/**
* Send start of command. This makes it easy to send multiple arguments per command
*/
void CmdMessenger::sendCmdStart(byte cmdId)
void CmdMessenger::sendCmdStart(CmdMsgByte cmdId)
{
if (!startCommand) {
startCommand = true;
Expand Down Expand Up @@ -330,7 +344,7 @@ void CmdMessenger::sendCmdSciArg(double arg, unsigned int n)
/**
* Send end of command
*/
bool CmdMessenger::sendCmdEnd(bool reqAc, byte ackCmdId, unsigned int timeout)
bool CmdMessenger::sendCmdEnd(bool reqAc, CmdMsgByte ackCmdId, unsigned int timeout)
{
bool ackReply = false;
if (startCommand) {
Expand All @@ -349,7 +363,7 @@ bool CmdMessenger::sendCmdEnd(bool reqAc, byte ackCmdId, unsigned int timeout)
/**
* Send a command without arguments, with acknowledge
*/
bool CmdMessenger::sendCmd(byte cmdId, bool reqAc, byte ackCmdId)
bool CmdMessenger::sendCmd(CmdMsgByte cmdId, bool reqAc, CmdMsgByte ackCmdId)
{
if (!startCommand) {
sendCmdStart(cmdId);
Expand All @@ -361,7 +375,7 @@ bool CmdMessenger::sendCmd(byte cmdId, bool reqAc, byte ackCmdId)
/**
* Send a command without arguments, without acknowledge
*/
bool CmdMessenger::sendCmd(byte cmdId)
bool CmdMessenger::sendCmd(CmdMsgByte cmdId)
{
if (!startCommand) {
sendCmdStart(cmdId);
Expand Down Expand Up @@ -675,4 +689,4 @@ void CmdMessenger::printSci(double f, unsigned int digits)
char output[16];
sprintf(output, format, whole, part, exponent);
comms->print(output);
}
}
86 changes: 65 additions & 21 deletions CmdMessenger.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,22 @@
#include <WProgram.h>
#endif

#if defined(__MBED__)
#include <mbed.h>
#endif

#if defined(MBED_STREAM_H)
/** Mbed platform compatibility and mbed like Stream**/
/** #include <Serial.h> */

#define __DEVICESTREAMTYPE UARTClass
#define CmdMsgByte uint8_t
#endif
#if defined(ARDUINO) && !defined(MBED_STREAM_H)
#define __DEVICESTREAMTYPE Stream
#define CmdMsgByte byte
#endif

//#include "Stream.h"

extern "C"
Expand All @@ -58,8 +74,8 @@ enum

class CmdMessenger
{
private:
// **** Private variables ***
protected:
// **** Protected variables ***

bool startCommand; // Indicates if sending of a command is underway
uint8_t lastCommandId; // ID of last received command
Expand All @@ -78,7 +94,7 @@ class CmdMessenger
char *current; // Pointer to current buffer position
char *last; // Pointer to previous buffer position
char prevChar; // Previous char (needed for unescaping)
Stream *comms; // Serial data stream
__DEVICESTREAMTYPE *comms; // Serial data stream

char command_separator; // Character indicating end of command (default: ';')
char field_separator; // Character indicating end of argument (default: ',')
Expand All @@ -90,15 +106,15 @@ class CmdMessenger

// **** Initialize ****

void init(Stream & comms, const char fld_separator, const char cmd_separator, const char esc_character);
void init(__DEVICESTREAMTYPE & comms, const char fld_separator, const char cmd_separator, const char esc_character);
void reset();

// **** Command processing ****

inline uint8_t processLine(char serialChar) __attribute__((always_inline));
inline void handleMessage() __attribute__((always_inline));
inline bool blockedTillReply(unsigned int timeout = DEFAULT_TIMEOUT, byte ackCmdId = 1) __attribute__((always_inline));
inline bool checkForAck(byte AckCommand) __attribute__((always_inline));
inline bool blockedTillReply(unsigned int timeout = DEFAULT_TIMEOUT, CmdMsgByte ackCmdId = 1) __attribute__((always_inline));
inline bool checkForAck(CmdMsgByte AckCommand) __attribute__((always_inline));

// **** Command sending ****

Expand All @@ -108,7 +124,7 @@ class CmdMessenger
template < class T >
void writeBin(const T & value)
{
const byte *bytePointer = (const byte *)(const void *)&value;
const CmdMsgByte *bytePointer = (const CmdMsgByte *)(const void *)&value;
for (unsigned int i = 0; i < sizeof(value); i++)
{
printEsc(*bytePointer);
Expand All @@ -128,7 +144,7 @@ class CmdMessenger
{
T value;
unescape(str);
byte *bytePointer = (byte *)(const void *)&value;
CmdMsgByte *bytePointer = (CmdMsgByte *)(const void *)&value;
for (unsigned int i = 0; i < sizeof(value); i++)
{
*bytePointer = str[i];
Expand All @@ -141,7 +157,7 @@ class CmdMessenger
T empty()
{
T value;
byte *bytePointer = (byte *)(const void *)&value;
CmdMsgByte *bytePointer = (CmdMsgByte *)(const void *)&value;
for (unsigned int i = 0; i < sizeof(value); i++)
{
*bytePointer = '\0';
Expand All @@ -164,13 +180,13 @@ class CmdMessenger

// **** Initialization ****

CmdMessenger(Stream & comms, const char fld_separator = ',',
CmdMessenger(__DEVICESTREAMTYPE & comms, const char fld_separator = ',',
const char cmd_separator = ';',
const char esc_character = '/');

void printLfCr(bool addNewLine = true);
void attach(messengerCallbackFunction newFunction);
void attach(byte msgId, messengerCallbackFunction newFunction);
void attach(CmdMsgByte msgId, messengerCallbackFunction newFunction);

// **** Command processing ****

Expand All @@ -187,7 +203,7 @@ class CmdMessenger
* Note that the argument is sent as string
*/
template < class T >
bool sendCmd(byte cmdId, T arg, bool reqAc = false, byte ackCmdId = 1,
bool sendCmd(CmdMsgByte cmdId, T arg, bool reqAc = false, CmdMsgByte ackCmdId = 1,
unsigned int timeout = DEFAULT_TIMEOUT)
{
if (!startCommand) {
Expand All @@ -203,7 +219,7 @@ class CmdMessenger
* Note that the argument is sent in binary format
*/
template < class T >
bool sendBinCmd(byte cmdId, T arg, bool reqAc = false, byte ackCmdId = 1,
bool sendBinCmd(CmdMsgByte cmdId, T arg, bool reqAc = false, CmdMsgByte ackCmdId = 1,
unsigned int timeout = DEFAULT_TIMEOUT)
{
if (!startCommand) {
Expand All @@ -214,27 +230,53 @@ class CmdMessenger
return false;
}

bool sendCmd(byte cmdId);
bool sendCmd(byte cmdId, bool reqAc, byte ackCmdId);
bool sendCmd(CmdMsgByte cmdId);
bool sendCmd(CmdMsgByte cmdId, bool reqAc, CmdMsgByte ackCmdId);
// **** Command sending with multiple arguments ****

void sendCmdStart(byte cmdId);
void sendCmdStart(CmdMsgByte cmdId);
void sendCmdEscArg(char *arg);
void sendCmdfArg(char *fmt, ...);
bool sendCmdEnd(bool reqAc = false, byte ackCmdId = 1, unsigned int timeout = DEFAULT_TIMEOUT);
bool sendCmdEnd(bool reqAc = false, CmdMsgByte ackCmdId = 1, unsigned int timeout = DEFAULT_TIMEOUT);

/**
* Send a single argument as string
* Note that this will only succeed if a sendCmdStart has been issued first
*/
template < class T > void sendCmdArg(T arg)
{
if (startCommand) {
comms->print(field_separator);
comms->print(arg);
if (startCommand) {
#if !defined(MBED) // Arduino and ReadBear OK
comms->print(field_separator);
comms->print(arg);
#else
comms->putc(field_separator);
comms->puts(arg);
#endif
}

}

#if defined(MBED)
void sendCmdArg(bool arg) {
comms->putc(field_separator);
comms->printf("%i", arg);
}
void sendCmdArg(float arg) {
comms->putc(field_separator);
comms->printf("%f", arg);
}
void sendCmdArg(long arg) {
comms->putc(field_separator);
comms->printf("%i", arg);
}
void sendCmdArg(int arg) {
comms->putc(field_separator);
comms->printf("%i", arg);
}
#endif

#if !defined(MBED_STREAM_H)
/**
* Send a single argument as string with custom accuracy
* Note that this will only succeed if a sendCmdStart has been issued first
Expand All @@ -246,14 +288,15 @@ class CmdMessenger
comms->print(arg, n);
}
}
#endif

/**
* Send double argument in scientific format.
* This will overcome the boundary of normal d sending which is limited to abs(f) <= MAXLONG
*/
void sendCmdSciArg(double arg, unsigned int n = 6);


#if !defined(MBED_STREAM_H)
/**
* Send a single argument in binary format
* Note that this will only succeed if a sendCmdStart has been issued first
Expand All @@ -265,6 +308,7 @@ class CmdMessenger
writeBin(arg);
}
}
#endif

// **** Command receiving ****
bool readBoolArg();
Expand Down