A simple wireless protocol to let my examples communicate each other. ssWi stands for Shared Slotted Wireless protocol
Dependents: rover_car rover_pc supervisor watering_unit ... more
This library aims at implementing a simple communication protocol among nodes, abstracting from the hardware. The name ssWi stands for Shared Slotted Wireless. Wireless is part of the name, even though the library abstracts from the hardware, as the first version was entirely focused on the XBee modules and then the name has not been changed.
The communication channel is represented by ssWiChannel, an abstract class which models the channel that the transceivers access to. The concrete classes must implement the functions: init, read and write. The protocol automatically sends and receives data through the selected channel, exploiting the operting system timers. Addresses are not considered as the communication lays on broadcast transmissions.
The protocol provides the ssWiPort abstraction which is like memory areas shared among all the connected nodes. Reading from one port lets the node retrieve the last written value from the other nodes. Writing on one port means sending such value to other nodes.
Objects instantiated from ssWiSocket are the interface for allowing nodes to access the protocol ports.
TODO:
- improve the parsing of the received messages
- communication tests with many nodes (so far, only 2 nodes have been tested)
Revision 4:dbbf82c966c2, committed 2012-09-07
- Comitter:
- mariob
- Date:
- Fri Sep 07 23:02:04 2012 +0000
- Parent:
- 3:1adc077d4906
- Child:
- 5:0b0ca40aeb81
- Commit message:
- new version
Changed in this revision
--- a/ssWi.cpp Thu Sep 06 12:11:52 2012 +0000 +++ b/ssWi.cpp Fri Sep 07 23:02:04 2012 +0000 @@ -1,116 +1,118 @@ -#include "ssWi.hpp" - -#include "mbed.h" -#include "rtos.h" - - -void threadSender (void const* arg); -void threadReceiver (void const* arg); - - -ssWi::ssWi (ssWiChannel* c, int rateTX, int rateRX) -{ - msTXSleep = 1000/rateTX; - msRXSleep = 1000/rateRX; - mutexChannel.lock(); - channel = c; - sender = new Thread(threadSender, this); - receiver = new Thread(threadReceiver, this); - mutexChannel.unlock(); -} - -ssWi::~ssWi () -{ - delete sender; - delete receiver; -} - -ssWiSocket* ssWi::createSocket (PortID port) -{ - setPort(port); - return new ssWiSocket(&ports[port]); -} - -bool ssWi::setPort (PortID port) -{ - if (isActive(port)) - return false; - ports[port]; - return true; -} - -bool ssWi::unsetPort (PortID port) -{ - if (!isActive(port)) - return false; - ports.erase(port); - return true; -} - -void ssWi::readFromChannel (char* msg, int& len) -{ - mutexChannel.lock(); - len = channel->read(msg); - mutexChannel.unlock(); -} - -void ssWi::writeOnChannel (char* msg, int len) -{ - mutexChannel.lock(); - channel->write(msg, len); - mutexChannel.unlock(); -} - -#define INTERNAL_BUFFER_SIZE 100 - -void threadSender (void const* arg) -{ - ssWi* s = (ssWi*)arg; - char buffer[INTERNAL_BUFFER_SIZE]; - while(true) { - int n = 0; - std::map<int, ssWiPort>::iterator it = s->ports.begin(); - - buffer[n++] = 255; - for (; it!=s->ports.end(); it++) { - if ((*it).second.isModified()) { - buffer[n++] = (*it).first; - PortValue tmp = (*it).second.getTXValue(); - for (int i=0; i<sizeof(PortValue); i++) { - buffer[n++] = tmp & 0x00ff; - tmp = tmp>>8; - } - } - } - if (n>1) - s->writeOnChannel(buffer, n); - Thread::wait(s->getTXSleep()); - } -} - -void threadReceiver (void const* arg) -{ - ssWi* s = (ssWi*)arg; - char buffer[INTERNAL_BUFFER_SIZE]; - while(true) { - int n; - s->readFromChannel(buffer, n); - - int i = 0; - for (; buffer[i]!=255 && i<n; i++); - i++; - - for (; i<n;) { - PortID port = buffer[i++]; - PortValue value = 0; - for (int j=sizeof(PortValue)-1; j>=0; j--) { - value = value<<8; - value += buffer[i+j]; - } - i += sizeof(PortValue); - if (s->ports.find(port)!=s->ports.end()) - s->ports[port].setRXValue(value); - } - Thread::wait(s->getRXSleep()); - } -} +#include "ssWiChannel.hpp" +#include "ssWiPort.hpp" +#include "ssWi.hpp" + +#include "mbed.h" +#include "rtos.h" + +#include <map> + + +#define INTERNAL_BUFFER_SIZE 100 + + +Thread* sender; +Thread* receiver; + +ssWiChannel* channel = NULL; +Mutex mutexChannel; + +std::map<int, ssWiPort> ports; + +int TXRate; +int RXRate; + + +void threadSender (void const* arg); +void threadReceiver (void const* arg); + + +bool ssWi_init (ssWiChannel* c, int rateTX, int rateRX) +{ + if (channel!=NULL) + return false; + TXRate = 1000/rateTX; + RXRate = 1000/rateRX; + mutexChannel.lock(); + channel = c; + sender = new Thread(threadSender); + receiver = new Thread(threadReceiver); + mutexChannel.unlock(); + return true; +} + +bool ssWi_isActive (PortID port) +{ + return channel!=NULL && ports.find(port)!=ports.end(); +} + +bool ssWi_setPort (PortID port) +{ + if (channel==NULL) + return false; + ports[port]; + return true; +} + +bool ssWi_unsetPort (PortID port) +{ + if (!ssWi_isActive(port)) + return false; + ports.erase(port); + return true; +} + +void threadSender (void const* arg) +{ + char buffer[INTERNAL_BUFFER_SIZE]; + while(true) { + int n = 0; + std::map<int, ssWiPort>::iterator it = ports.begin(); + + buffer[n++] = 255; + for (; it!=ports.end(); it++) { + if ((*it).second.isModified()) { + buffer[n++] = (*it).first; + PortValue tmp = (*it).second.getTXValue(); + for (int i=0; i<sizeof(PortValue); i++) { + buffer[n++] = tmp & 0x00ff; + tmp = tmp>>8; + } + } + } + if (n>1) { + mutexChannel.lock(); + channel->write(buffer, n); + mutexChannel.unlock(); + } + Thread::wait(TXRate); + } +} + +void threadReceiver (void const* arg) +{ + char buffer[INTERNAL_BUFFER_SIZE]; + while(true) { + int n; + mutexChannel.lock(); + n = channel->read(buffer); + mutexChannel.unlock(); + + int i = 0; + for (; buffer[i]!=255 && i<n; i++); + i++; + + for (; i<n;) { + PortID port = buffer[i++]; + PortValue value = 0; + for (int j=sizeof(PortValue)-1; j>=0; j--) { + value = value<<8; + value += buffer[i+j]; + } + i += sizeof(PortValue); + if (ports.find(port)!=ports.end()) + ports[port].setRXValue(value); + } + Thread::wait(RXRate); + } +}
--- a/ssWi.hpp Thu Sep 06 12:11:52 2012 +0000 +++ b/ssWi.hpp Fri Sep 07 23:02:04 2012 +0000 @@ -1,63 +1,33 @@ -#ifndef __SHARED_SLOTTED_WIRELESS_HPP__ -#define __SHARED_SLOTTED_WIRELESS_HPP__ - -#include "ssWiTypes.hpp" -#include "ssWiChannel.hpp" -#include "ssWiPort.hpp" -#include "ssWiSocket.hpp" - -#include "rtos.h" - -#include <map> - - - -#define N_PORTS 256 - - - -class ssWi -{ - - ssWiChannel* channel; - Mutex mutexChannel; - - Thread* sender; - Thread* receiver; - - int msTXSleep; - int msRXSleep; - - std::map<int, ssWiPort> ports; - - friend void threadReceiver (void const* arg); - friend void threadSender (void const* arg); - - bool setPort (PortID port); - bool isActive (PortID port) { - return ports.find(port)!=ports.end(); - } - bool unsetPort (PortID port); - - void readFromChannel (char* msg, int& len); - void writeOnChannel (char* msg, int len); - - int getTXSleep () { - return msTXSleep; - } - int getRXSleep () { - return msRXSleep; - } - -public: - - ssWi (ssWiChannel* channel, int rateTX=10, int rateRX=20); - ~ssWi (); - - ssWiSocket* createSocket (PortID port); - - - -}; - -#endif //__SHARED_SLOTTED_WIRELESS_HPP__ +#ifndef __SHARED_SLOTTED_WIRELESS_HPP__ +#define __SHARED_SLOTTED_WIRELESS_HPP__ + +#include "ssWiTypes.hpp" + +/** \brief number of provided ports + * + */ +#define N_PORTS 256 + +class ssWiChannel; + +/** \brief Initialize the ssWi protocol + * + * It is not possible to have two instances of this protocol at the same time. + * + * \param c channel to be used for sending/receving data + * \param rateTX transmission rate + * \param rateRX receiving rate + * \return true if the network has been correctly initialized, false otherwise + */ +bool ssWi_init (ssWiChannel* c, int rateTX, int rateRX); + +void ssWi_stop (); + +bool ssWi_isActive (PortID port); + +bool ssWi_setPort (PortID port); + +bool ssWi_unsetPort (PortID port); + + +#endif //__SHARED_SLOTTED_WIRELESS_HPP__
--- a/ssWiChannel.hpp Thu Sep 06 12:11:52 2012 +0000 +++ b/ssWiChannel.hpp Fri Sep 07 23:02:04 2012 +0000 @@ -1,11 +1,53 @@ +/** \file ssWiChannel.hpp + * \brief Abstract class for the communication channel + * + */ + #ifndef __SHARED_SLOTTED_WIRELESS_CHANNEL_HPP__ #define __SHARED_SLOTTED_WIRELESS_CHANNEL_HPP__ + +#include "ssWi.hpp" + + +/** \brief Abstract class for a communication channel + * + */ class ssWiChannel { + +protected: + + /** \brief Initialize the protocol + */ + bool _init (ssWiChannel* c, int TXRate, int RXRate) { + return ssWi_init(c, TXRate, RXRate); + } + public: + + /** \brief Initialize ssWi on this channel + * + * \param TXRate number of transmissions per second + * \param RXRate number of receptions per second + * \return true if ssWi has been initialized succefully + */ + virtual bool init (int TXRate, int RXRate) = 0; + + /** \brief read from the socket + * + * \param msg buffer where to write the read message + * \return the number of read bytes + */ virtual int read (char* msg) = 0; + + /** \brief write to the socket + * + * \param msg buffer with the message to send + * \n number of bytes to send + */ virtual void write (const char* msg, int n) = 0; + }; #endif //__SHARED_SLOTTED_WIRELESS_CHANNEL_HPP__
--- a/ssWiPort.cpp Thu Sep 06 12:11:52 2012 +0000 +++ b/ssWiPort.cpp Fri Sep 07 23:02:04 2012 +0000 @@ -1,3 +1,8 @@ +/** \file ssWiPort.cpp + * \brief Implementation of the dual head port + * + */ + #include "ssWiPort.hpp" PortValue ssWiPort::getTXValue()
--- a/ssWiPort.hpp Thu Sep 06 12:11:52 2012 +0000 +++ b/ssWiPort.hpp Fri Sep 07 23:02:04 2012 +0000 @@ -1,9 +1,14 @@ +/** \file ssWiPort.hpp + * \brief Header for introducing the dual head port + * + */ + #ifndef __SHARED_SLOTTED_WIRELESS_PORT_HPP__ #define __SHARED_SLOTTED_WIRELESS_PORT_HPP__ -#include "ssWiTypes.hpp" +#include "rtos.h" -#include "rtos.h" +#include "ssWiTypes.hpp" /** \brief Internal type which represents a logical flow @@ -15,33 +20,46 @@ */ class ssWiPort { - /** receiving buffer */ + /** \brief receiving buffer */ PortValue valueRX; + /** \brief receiving mutex */ Mutex mutexRX; - - /** transmission buffer */ + + /** \brief transmission buffer */ PortValue valueTX; + /** \brief transmission mutex */ Mutex mutexTX; - /** modification flag (true: someone has write a new value to be sent */ + /** \brief modification flag (if true a new value has to be sent) */ bool modified; - public: + /** \brief constructor */ ssWiPort () { modified = false; valueTX = 0; valueRX = 0; } - //transmission + /** \brief get the value to be sent + */ PortValue getTXValue(); + + /** \brief write a value to be sent + */ void setTXValue(PortValue tmp); + + /** \brief true if there is a value to be sent + */ bool isModified(); - //reception + /** \brief Read the last received value + */ PortValue getRXValue(); + + /** \brief Write the last received value + */ void setRXValue(PortValue tmp); };
--- a/ssWiSocket.cpp Thu Sep 06 12:11:52 2012 +0000 +++ b/ssWiSocket.cpp Fri Sep 07 23:02:04 2012 +0000 @@ -1,168 +1,24 @@ -/* -//#include "ssWi.hpp" #include "ssWiSocket.hpp" #include "ssWiPort.hpp" - +#include "ssWi.hpp" -ssWiChannel* ssWiSocket::channel = NULL; -Mutex ssWiSocket::chMutex = Mutex(); - -static Thread* ssWiSocket::sender = NULL; -static Thread* ssWiSocket::receiver = NULL; +#include <map> -static bool ssWiSocket::setChannel (ssWiChannel* c) -{ - if (sender!=NULL) - delete sender; - if (receiver!=NULL) - delete receiver; - chMutex.lock(); - channel = c; - sender = new Thread(threadSender); - receiver = new Thread(threadReceiver); - chMutex.unlock(); -} - -ssWiSocket::ssWiSocket(PortID port) -{ - this->port = port; - setPort (port); -} - -bool ssWiSocket::valid () -{ - return isActive(port); -} - -bool ssWiSocket::close() -{ - return unsetPort(port); -} - -bool ssWiSocket::read (PortValue &value) -{ - return readPort (port, value); -} - -bool ssWiSocket::write (PortValue value) -{ - return writePort (port, value); -} +extern std::map<int, ssWiPort> ports; -#include "ssWi.hpp" - - - - -#include "mbed.h" -#include "rtos.h" - - - - -bool setPort (PortID port) -{ - if (ports.find(port)!=ports.end()) - return false; - ports[port]; - return true; -} - -bool isActive (PortID port) -{ - return ports.find(port)!=ports.end(); +PortValue ssWiSocket::read () { + return ports[_id].getRXValue(); } -bool unsetPort (PortID port) -{ - if (ports.find(port)==ports.end()) - return false; - ports.erase(port); - return true; -} - -bool readPort (PortID port, PortValue &value) -{ - if (ports.find(port)==ports.end()) - return false; - value = ports[port].getRXValue(); - return true; -} - -bool writePort (PortID port, PortValue value) -{ - if (ports.find(port)==ports.end()) - return false; - ports[port].setTXValue(value); - return true; +void ssWiSocket::write (PortValue value) { + ports[_id].setTXValue(value); } - -#define INTERNAL_BUFFER_SIZE 100 - -void threadSender (void const* arg) +ssWiSocket* ssWiSocket::createSocket(PortID id) { - char buffer[INTERNAL_BUFFER_SIZE]; - while(true) { - int n = 0; - std::map<int, ssWiPort>::iterator it = ports.begin(); - - buffer[n++] = 255; - // && n<(INTERNAL_BUFFER_SIZE-sizeof(PortID)-sizeof(PortValue)-1) - for (; it!=ports.end(); it++) { - if ((*it).second.isModified()) { - buffer[n++] = (*it).first; - PortValue tmp = (*it).second.getTXValue(); - for (int i=0; i<sizeof(PortValue); i++) { - buffer[n++] = tmp & 0x00ff; - tmp = tmp>>8; - } - } - } - //buffer[n++] = '\r'; - if (n>1) { - mutexChannel.lock(); - channel->write(buffer, n); - mutexChannel.unlock(); - } - //printf("Totale byte: %d\n\r", n); - //for (int i=0; i<n; i++) - // printf("%d ", buffer[i]); - //printf("\n\r"); - Thread::wait(200); - } + if (!ssWi_setPort(id)) + return false; + return new ssWiSocket(id); } - -void threadReceiver (void const* arg) -{ - char buffer[INTERNAL_BUFFER_SIZE]; - while(true) { - mutexChannel.lock(); - int n = channel->read(buffer); - //printf("Byte letti: %d\n\r", n); - //for (int i=0; i<n; i++) - // printf("%d ", buffer[i]); - //printf("\n\r"); - mutexChannel.unlock(); - - int i = 0; - for (; buffer[i]!=255 && i<n; i++); - i++; - - for (; i<n;) { - PortID port = buffer[i++]; - PortValue value = 0; - for (int j=sizeof(PortValue)-1; j>=0; j--) { - value = value<<8; - value += buffer[i+j]; - } - i += sizeof(PortValue); - if (ports.find(port)!=ports.end()) - ports[port].setRXValue(value); - } - Thread::wait(100); - } -} -*/ \ No newline at end of file
--- a/ssWiSocket.hpp Thu Sep 06 12:11:52 2012 +0000 +++ b/ssWiSocket.hpp Fri Sep 07 23:02:04 2012 +0000 @@ -1,36 +1,48 @@ +/** \file ssWiSockert.hpp + * \brief Header for the communcation socket + * + */ + #ifndef __SHARED_SLOTTED_WIRELESS_SOCKET_HPP__ #define __SHARED_SLOTTED_WIRELESS_SOCKET_HPP__ -#include "ssWiPort.hpp" + +#include "ssWiTypes.hpp" + +/** \brief Socket to communciate through ssWi + * + * It is not possible to instanciate directly a ssWiSocket, use the static + * method createSocket + */ class ssWiSocket { - - friend class ssWi; - - //ssWi* w; - ssWiPort* p; + /** \brief Port identifier */ + PortID _id; - //ssWiSocket(ssWi* w, ssWiPort* p) { - ssWiSocket(ssWiPort* p) { - //this->w = w; - this->p = p; - } + /** \brief Hidden constructor */ + ssWiSocket(PortID id) : _id(id) {} public: - PortValue read () { - return p->getRXValue(); - } - void write (PortValue value) { - p->setTXValue(value); - } + /** \brief create a new socket + * + * If the network is not inizialized yet, the method returns false + * + * \param id port identifier to connect the socket with + */ + static ssWiSocket* createSocket(PortID id); -/* - bool close() { - w->unsetPort(); - } -*/ + /** \brief read the last value read through the network on such socket + */ + PortValue read (); + + /** \brief write a new value to be sent through the socket + * + * \param value value to be sent + */ + void write (PortValue value); + };
--- a/ssWiTypes.hpp Thu Sep 06 12:11:52 2012 +0000 +++ b/ssWiTypes.hpp Fri Sep 07 23:02:04 2012 +0000 @@ -1,7 +1,7 @@ /** \file ssWiTypes.hpp * \brief type definition file */ - +// #ifndef __SHARED_SLOTTED_TYPES_HPP__ #define __SHARED_SLOTTED_TYPES_HPP__
--- a/xbee/xbee.hpp Thu Sep 06 12:11:52 2012 +0000 +++ b/xbee/xbee.hpp Fri Sep 07 23:02:04 2012 +0000 @@ -1,79 +1,83 @@ -#ifndef __XBEE_MODULE_HPP__ -#define __XBEE_MODULE_HPP__ - -#include "mbed.h" - -#include <ssWiChannel.hpp> - -#include "string" - - -class XBeeAddress -{ - string low; - string high; - -public: - - XBeeAddress () : low(""), high("") {} - - XBeeAddress (string low, string high) { - this->low = low; - this->high = high; - } - - string getLowAddr () { - return low; - } - - string getHighAddr () { - return high; - } -}; - - -class XBeeBroadcastAddress: public XBeeAddress -{ -public: - XBeeBroadcastAddress () : XBeeAddress("00FFFF", "0") {} -}; - - -class XBeeModule: public ssWiChannel -{ - - Serial xbee; - XBeeAddress local; - - bool status; - - bool executeWithOk (const char* cmd); - void executeWithRes (const char* cmd, char* res); - void readResponse (char* msg); - - bool _getLocalAddr (); - bool _setChannel (int channel); - bool _setPanID (int id); - - public: - - XBeeModule (PinName tx, PinName rx, int panID, int channel); - - XBeeAddress getLocalAddress () { - return local; - } - - bool setDstAddress (XBeeAddress addr); - - XBeeAddress getDstAddress (); - - - int getChannel (); - int getPanID (); - - virtual int read (char* msg); - virtual void write (const char* msg, int n); - -}; - -#endif //__XBEE_MODULE_HPP__ +#ifndef __XBEE_MODULE_HPP__ +#define __XBEE_MODULE_HPP__ + +#include "mbed.h" + +#include <ssWiChannel.hpp> + +#include "string" + + +class XBeeAddress +{ + string low; + string high; + +public: + + XBeeAddress () : low(""), high("") {} + + XBeeAddress (string low, string high) { + this->low = low; + this->high = high; + } + + string getLowAddr () { + return low; + } + + string getHighAddr () { + return high; + } +}; + + +class XBeeBroadcastAddress: public XBeeAddress +{ +public: + XBeeBroadcastAddress () : XBeeAddress("00FFFF", "0") {} +}; + + +class XBeeModule: public ssWiChannel +{ + + Serial xbee; + XBeeAddress local; + + bool status; + + bool executeWithOk (const char* cmd); + void executeWithRes (const char* cmd, char* res); + void readResponse (char* msg); + + bool _getLocalAddr (); + bool _setChannel (int channel); + bool _setPanID (int id); + + public: + + XBeeModule (PinName tx, PinName rx, int panID, int channel); + + XBeeAddress getLocalAddress () { + return local; + } + + bool setDstAddress (XBeeAddress addr); + + XBeeAddress getDstAddress (); + + + int getChannel (); + int getPanID (); + + virtual bool init (int TXRate, int RXRate) { + return _init(this, TXRate, RXRate); + } + + virtual int read (char* msg); + virtual void write (const char* msg, int n); + +}; + +#endif //__XBEE_MODULE_HPP__