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.

/media/uploads/mariob/scheme.png

TODO:

  • improve the parsing of the received messages
  • communication tests with many nodes (so far, only 2 nodes have been tested)
Committer:
mariob
Date:
Wed Mar 06 23:13:31 2013 +0000
Revision:
15:fb0f6cbc0ed5
Parent:
13:69ff47a83260
Child:
16:b50c3b3b241c
From threads to timers; MB

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mariob 13:69ff47a83260 1 /** \file ssWi.cpp
mariob 13:69ff47a83260 2 * \brief implementation of the internal functions for mananing the protocol
mariob 13:69ff47a83260 3 *
mariob 13:69ff47a83260 4 */
mariob 13:69ff47a83260 5
mariob 15:fb0f6cbc0ed5 6 #include "ssWiChannel.hpp"
mariob 4:dbbf82c966c2 7 #include "ssWiPort.hpp"
mariob 4:dbbf82c966c2 8 #include "ssWi.hpp"
mariob 4:dbbf82c966c2 9
mariob 4:dbbf82c966c2 10 #include "mbed.h"
mariob 4:dbbf82c966c2 11 #include "rtos.h"
mariob 4:dbbf82c966c2 12
mariob 4:dbbf82c966c2 13 #include <map>
mariob 4:dbbf82c966c2 14
mariob 13:69ff47a83260 15
mariob 13:69ff47a83260 16
mariob 13:69ff47a83260 17 /** \brief first byte of the header
mariob 13:69ff47a83260 18 *
mariob 13:69ff47a83260 19 * The header is composed of 3 bytes
mariob 13:69ff47a83260 20 */
mariob 13:69ff47a83260 21 #define START_0 255
mariob 13:69ff47a83260 22
mariob 13:69ff47a83260 23 /** \brief second byte of the header
mariob 13:69ff47a83260 24 *
mariob 13:69ff47a83260 25 * The header is composed of 3 bytes
mariob 13:69ff47a83260 26 */
mariob 13:69ff47a83260 27 #define START_1 130
mariob 13:69ff47a83260 28
mariob 13:69ff47a83260 29 /** \brief third byte of the header
mariob 13:69ff47a83260 30 *
mariob 13:69ff47a83260 31 * The header is composed of 3 bytes
mariob 13:69ff47a83260 32 */
mariob 13:69ff47a83260 33 #define START_2 255
mariob 13:69ff47a83260 34
mariob 13:69ff47a83260 35
mariob 13:69ff47a83260 36 /**
mariob 13:69ff47a83260 37 * dimension of the buffers used by the sender and receiver procedure
mariob 13:69ff47a83260 38 */
mariob 4:dbbf82c966c2 39 #define INTERNAL_BUFFER_SIZE 100
mariob 4:dbbf82c966c2 40
mariob 13:69ff47a83260 41
mariob 13:69ff47a83260 42 /** \brief channel abstraction
mariob 13:69ff47a83260 43 *
mariob 13:69ff47a83260 44 * This object represent the communication channel that can be
mariob 13:69ff47a83260 45 * different means
mariob 13:69ff47a83260 46 */
mariob 13:69ff47a83260 47 ssWiChannel* channel = NULL;
mariob 13:69ff47a83260 48
mariob 13:69ff47a83260 49 /** \brief serialize read and write operations
mariob 13:69ff47a83260 50 *
mariob 13:69ff47a83260 51 * simultaneous multiple accesses to the mean are avoided
mariob 13:69ff47a83260 52 */
mariob 13:69ff47a83260 53 Mutex mutexChannel;
mariob 13:69ff47a83260 54
mariob 13:69ff47a83260 55 /** \brief set of registered communication ports
mariob 13:69ff47a83260 56 *
mariob 13:69ff47a83260 57 */
mariob 13:69ff47a83260 58 std::map<int, ssWiPort> ports;
mariob 13:69ff47a83260 59
mariob 13:69ff47a83260 60 /** \brief transmission rate
mariob 13:69ff47a83260 61 *
mariob 13:69ff47a83260 62 */
mariob 13:69ff47a83260 63 int TXRate;
mariob 13:69ff47a83260 64
mariob 13:69ff47a83260 65 /** \brief reading rate
mariob 13:69ff47a83260 66 *
mariob 13:69ff47a83260 67 */
mariob 13:69ff47a83260 68 int RXRate;
mariob 13:69ff47a83260 69
mariob 13:69ff47a83260 70
mariob 15:fb0f6cbc0ed5 71 /*
mariob 4:dbbf82c966c2 72 Thread* sender;
mariob 4:dbbf82c966c2 73 Thread* receiver;
mariob 4:dbbf82c966c2 74
mariob 4:dbbf82c966c2 75 void threadSender (void const* arg);
mariob 4:dbbf82c966c2 76 void threadReceiver (void const* arg);
mariob 4:dbbf82c966c2 77
mariob 4:dbbf82c966c2 78 bool ssWi_init (ssWiChannel* c, int rateTX, int rateRX)
mariob 4:dbbf82c966c2 79 {
mariob 4:dbbf82c966c2 80 if (channel!=NULL)
mariob 4:dbbf82c966c2 81 return false;
mariob 8:354a0e3087c1 82 TXRate = 1000.0/rateTX;
mariob 8:354a0e3087c1 83 RXRate = 1000.0/rateRX;
mariob 4:dbbf82c966c2 84 mutexChannel.lock();
mariob 4:dbbf82c966c2 85 channel = c;
mariob 15:fb0f6cbc0ed5 86 mutexChannel.unlock();
mariob 4:dbbf82c966c2 87 sender = new Thread(threadSender);
mariob 4:dbbf82c966c2 88 receiver = new Thread(threadReceiver);
mariob 4:dbbf82c966c2 89 return true;
mariob 4:dbbf82c966c2 90 }
mariob 4:dbbf82c966c2 91
mariob 4:dbbf82c966c2 92 void threadSender (void const* arg)
mariob 4:dbbf82c966c2 93 {
mariob 15:fb0f6cbc0ed5 94 static char buffer[INTERNAL_BUFFER_SIZE];
mariob 4:dbbf82c966c2 95 while(true) {
mariob 9:b5b5d0533fa6 96 int n = 3;
mariob 9:b5b5d0533fa6 97 int numFrames = 0;
mariob 9:b5b5d0533fa6 98 for (std::map<int, ssWiPort>::iterator it = ports.begin(); it!=ports.end(); it++) {
mariob 4:dbbf82c966c2 99 if ((*it).second.isModified()) {
mariob 4:dbbf82c966c2 100 buffer[n++] = (*it).first;
mariob 4:dbbf82c966c2 101 PortValue tmp = (*it).second.getTXValue();
mariob 5:0b0ca40aeb81 102 memcpy(&buffer[n], &tmp, sizeof(PortValue));
mariob 5:0b0ca40aeb81 103 n += sizeof(PortValue);
mariob 9:b5b5d0533fa6 104 //printf("Write[%d] = %d\n\r", (*it).first, tmp);
mariob 9:b5b5d0533fa6 105 numFrames++;
mariob 4:dbbf82c966c2 106 }
mariob 4:dbbf82c966c2 107 }
mariob 9:b5b5d0533fa6 108 if (numFrames>0) {
mariob 9:b5b5d0533fa6 109 buffer[0] = START_0;
mariob 9:b5b5d0533fa6 110 buffer[1] = START_1;
mariob 9:b5b5d0533fa6 111 buffer[2] = START_2;
mariob 4:dbbf82c966c2 112 mutexChannel.lock();
mariob 4:dbbf82c966c2 113 channel->write(buffer, n);
mariob 4:dbbf82c966c2 114 mutexChannel.unlock();
mariob 15:fb0f6cbc0ed5 115 // printf("W(%d): ", n);
mariob 15:fb0f6cbc0ed5 116 // for(int k=0; k<n; k++)
mariob 15:fb0f6cbc0ed5 117 // printf("%d ", buffer[k]);
mariob 15:fb0f6cbc0ed5 118 // printf("\n\r");
mariob 4:dbbf82c966c2 119 }
mariob 4:dbbf82c966c2 120 Thread::wait(TXRate);
mariob 4:dbbf82c966c2 121 }
mariob 4:dbbf82c966c2 122 }
mariob 4:dbbf82c966c2 123
mariob 4:dbbf82c966c2 124 void threadReceiver (void const* arg)
mariob 4:dbbf82c966c2 125 {
mariob 15:fb0f6cbc0ed5 126 static char buffer[INTERNAL_BUFFER_SIZE];
mariob 4:dbbf82c966c2 127 while(true) {
mariob 15:fb0f6cbc0ed5 128 printf("...read...\n\r");
mariob 4:dbbf82c966c2 129 mutexChannel.lock();
mariob 5:0b0ca40aeb81 130 int n = channel->read(buffer);
mariob 4:dbbf82c966c2 131 mutexChannel.unlock();
mariob 15:fb0f6cbc0ed5 132 // if (n>0) {
mariob 15:fb0f6cbc0ed5 133 // printf("R(%d): ", n);
mariob 15:fb0f6cbc0ed5 134 // for(int k=0; k<n; k++)
mariob 15:fb0f6cbc0ed5 135 // printf("%d ", buffer[k]);
mariob 15:fb0f6cbc0ed5 136 // printf("\n\r");
mariob 15:fb0f6cbc0ed5 137 // }
mariob 9:b5b5d0533fa6 138 bool alreadyIn = false;
mariob 9:b5b5d0533fa6 139 for (int i=0; i<(n-2);) {
mariob 9:b5b5d0533fa6 140 bool found = false;
mariob 9:b5b5d0533fa6 141 if (buffer[i]==START_0 && buffer[i+1]==START_1 && buffer[i+2]==START_2) {
mariob 9:b5b5d0533fa6 142 found = true;
mariob 9:b5b5d0533fa6 143 alreadyIn = true;
mariob 9:b5b5d0533fa6 144 i += 3;
mariob 4:dbbf82c966c2 145 }
mariob 9:b5b5d0533fa6 146 if ((found || alreadyIn) && (n-i)>=(sizeof(PortID)+sizeof(PortValue))) {
mariob 9:b5b5d0533fa6 147 PortID port = buffer[i++];
mariob 9:b5b5d0533fa6 148 PortValue value = 0;
mariob 9:b5b5d0533fa6 149 memcpy(&value, &buffer[i], sizeof(PortValue));
mariob 11:4ad44d62d510 150 // printf("Read[%d] = %d\n\r", port, value);
mariob 9:b5b5d0533fa6 151 i += sizeof(PortValue);
mariob 9:b5b5d0533fa6 152 if (ports.find(port)!=ports.end())
mariob 9:b5b5d0533fa6 153 ports[port].setRXValue(value);
mariob 15:fb0f6cbc0ed5 154 }
mariob 4:dbbf82c966c2 155 }
mariob 4:dbbf82c966c2 156 Thread::wait(RXRate);
mariob 4:dbbf82c966c2 157 }
mariob 4:dbbf82c966c2 158 }
mariob 15:fb0f6cbc0ed5 159 */
mariob 15:fb0f6cbc0ed5 160
mariob 15:fb0f6cbc0ed5 161
mariob 15:fb0f6cbc0ed5 162 void functionSender (void const* arg);
mariob 15:fb0f6cbc0ed5 163 void functionReceiver (void const* arg);
mariob 15:fb0f6cbc0ed5 164
mariob 15:fb0f6cbc0ed5 165 RtosTimer *senderTimer;
mariob 15:fb0f6cbc0ed5 166 RtosTimer *receiverTimer;
mariob 15:fb0f6cbc0ed5 167
mariob 15:fb0f6cbc0ed5 168 bool ssWi_init (ssWiChannel* c, int rateTX, int rateRX)
mariob 15:fb0f6cbc0ed5 169 {
mariob 15:fb0f6cbc0ed5 170 if (channel!=NULL)
mariob 15:fb0f6cbc0ed5 171 return false;
mariob 15:fb0f6cbc0ed5 172 TXRate = 1000.0/rateTX;
mariob 15:fb0f6cbc0ed5 173 RXRate = 1000.0/rateRX;
mariob 15:fb0f6cbc0ed5 174 mutexChannel.lock();
mariob 15:fb0f6cbc0ed5 175 channel = c;
mariob 15:fb0f6cbc0ed5 176 mutexChannel.unlock();
mariob 15:fb0f6cbc0ed5 177 senderTimer = new RtosTimer(functionSender, osTimerPeriodic, NULL);
mariob 15:fb0f6cbc0ed5 178 receiverTimer = new RtosTimer(functionReceiver, osTimerPeriodic, NULL);
mariob 15:fb0f6cbc0ed5 179 senderTimer->start(TXRate);
mariob 15:fb0f6cbc0ed5 180 receiverTimer->start(RXRate);
mariob 15:fb0f6cbc0ed5 181 return true;
mariob 15:fb0f6cbc0ed5 182 }
mariob 15:fb0f6cbc0ed5 183
mariob 15:fb0f6cbc0ed5 184 void functionSender (void const* arg)
mariob 15:fb0f6cbc0ed5 185 {
mariob 15:fb0f6cbc0ed5 186 static char buffer[INTERNAL_BUFFER_SIZE];
mariob 15:fb0f6cbc0ed5 187 int n = 3;
mariob 15:fb0f6cbc0ed5 188 int numFrames = 0;
mariob 15:fb0f6cbc0ed5 189 for (std::map<int, ssWiPort>::iterator it = ports.begin(); it!=ports.end(); it++) {
mariob 15:fb0f6cbc0ed5 190 if ((*it).second.isModified()) {
mariob 15:fb0f6cbc0ed5 191 buffer[n++] = (*it).first;
mariob 15:fb0f6cbc0ed5 192 PortValue tmp = (*it).second.getTXValue();
mariob 15:fb0f6cbc0ed5 193 memcpy(&buffer[n], &tmp, sizeof(PortValue));
mariob 15:fb0f6cbc0ed5 194 n += sizeof(PortValue);
mariob 15:fb0f6cbc0ed5 195 numFrames++;
mariob 15:fb0f6cbc0ed5 196 }
mariob 15:fb0f6cbc0ed5 197 }
mariob 15:fb0f6cbc0ed5 198 if (numFrames>0) {
mariob 15:fb0f6cbc0ed5 199 buffer[0] = START_0;
mariob 15:fb0f6cbc0ed5 200 buffer[1] = START_1;
mariob 15:fb0f6cbc0ed5 201 buffer[2] = START_2;
mariob 15:fb0f6cbc0ed5 202 if (!mutexChannel.trylock())
mariob 15:fb0f6cbc0ed5 203 return;
mariob 15:fb0f6cbc0ed5 204 channel->write(buffer, n);
mariob 15:fb0f6cbc0ed5 205 mutexChannel.unlock();
mariob 15:fb0f6cbc0ed5 206 }
mariob 15:fb0f6cbc0ed5 207 }
mariob 15:fb0f6cbc0ed5 208
mariob 15:fb0f6cbc0ed5 209 void functionReceiver (void const* arg)
mariob 15:fb0f6cbc0ed5 210 {
mariob 15:fb0f6cbc0ed5 211 static char buffer[INTERNAL_BUFFER_SIZE];
mariob 15:fb0f6cbc0ed5 212 if (!mutexChannel.trylock())
mariob 15:fb0f6cbc0ed5 213 return;
mariob 15:fb0f6cbc0ed5 214 int n = channel->read(buffer);
mariob 15:fb0f6cbc0ed5 215 mutexChannel.unlock();
mariob 15:fb0f6cbc0ed5 216 bool alreadyIn = false;
mariob 15:fb0f6cbc0ed5 217 for (int i=0; i<(n-2);) {
mariob 15:fb0f6cbc0ed5 218 bool found = false;
mariob 15:fb0f6cbc0ed5 219 if (buffer[i]==START_0 && buffer[i+1]==START_1 && buffer[i+2]==START_2) {
mariob 15:fb0f6cbc0ed5 220 found = true;
mariob 15:fb0f6cbc0ed5 221 alreadyIn = true;
mariob 15:fb0f6cbc0ed5 222 i += 3;
mariob 15:fb0f6cbc0ed5 223 }
mariob 15:fb0f6cbc0ed5 224 if ((found || alreadyIn) && (n-i)>=(sizeof(PortID)+sizeof(PortValue))) {
mariob 15:fb0f6cbc0ed5 225 PortID port = buffer[i++];
mariob 15:fb0f6cbc0ed5 226 PortValue value = 0;
mariob 15:fb0f6cbc0ed5 227 memcpy(&value, &buffer[i], sizeof(PortValue));
mariob 15:fb0f6cbc0ed5 228 i += sizeof(PortValue);
mariob 15:fb0f6cbc0ed5 229 if (ports.find(port)!=ports.end())
mariob 15:fb0f6cbc0ed5 230 ports[port].setRXValue(value);
mariob 15:fb0f6cbc0ed5 231 }
mariob 15:fb0f6cbc0ed5 232 }
mariob 15:fb0f6cbc0ed5 233 }
mariob 15:fb0f6cbc0ed5 234
mariob 15:fb0f6cbc0ed5 235
mariob 13:69ff47a83260 236
mariob 13:69ff47a83260 237
mariob 13:69ff47a83260 238 inline bool ssWi_isActive (PortID port)
mariob 13:69ff47a83260 239 {
mariob 13:69ff47a83260 240 return channel!=NULL && ports.find(port)!=ports.end();
mariob 13:69ff47a83260 241 }
mariob 13:69ff47a83260 242
mariob 13:69ff47a83260 243
mariob 13:69ff47a83260 244 bool ssWi_setPort (PortID port)
mariob 13:69ff47a83260 245 {
mariob 13:69ff47a83260 246 if (channel==NULL)
mariob 13:69ff47a83260 247 return false;
mariob 13:69ff47a83260 248 ports[port];
mariob 13:69ff47a83260 249 return true;
mariob 13:69ff47a83260 250 }
mariob 13:69ff47a83260 251
mariob 13:69ff47a83260 252
mariob 13:69ff47a83260 253 bool ssWi_unsetPort (PortID port)
mariob 13:69ff47a83260 254 {
mariob 13:69ff47a83260 255 if (!ssWi_isActive(port))
mariob 13:69ff47a83260 256 return false;
mariob 13:69ff47a83260 257 ports.erase(port);
mariob 13:69ff47a83260 258 return true;
mariob 13:69ff47a83260 259 }