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:
Tue Apr 21 08:23:47 2020 +0000
Revision:
25:83172a067b57
Parent:
24:80345e511574
added comments

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mariob 13:69ff47a83260 1 /** \file ssWi.cpp
mariob 24:80345e511574 2 *
mariob 13:69ff47a83260 3 * \brief implementation of the internal functions for mananing the protocol
mariob 13:69ff47a83260 4 *
mariob 13:69ff47a83260 5 */
mariob 13:69ff47a83260 6
mariob 15:fb0f6cbc0ed5 7 #include "ssWiChannel.hpp"
mariob 4:dbbf82c966c2 8 #include "ssWiPort.hpp"
mariob 4:dbbf82c966c2 9 #include "ssWi.hpp"
mariob 4:dbbf82c966c2 10
mariob 4:dbbf82c966c2 11 #include "mbed.h"
mariob 4:dbbf82c966c2 12 #include "rtos.h"
mariob 4:dbbf82c966c2 13
mariob 4:dbbf82c966c2 14 #include <map>
mariob 4:dbbf82c966c2 15
mariob 13:69ff47a83260 16
mariob 13:69ff47a83260 17 /** \brief first byte of the header
mariob 13:69ff47a83260 18 *
mariob 24:80345e511574 19 * The header is composed of 3 bytes: START_0 START_1 START_2
mariob 13:69ff47a83260 20 */
mariob 13:69ff47a83260 21 #define START_0 255
mariob 13:69ff47a83260 22 #define START_1 130
mariob 13:69ff47a83260 23 #define START_2 255
mariob 13:69ff47a83260 24
mariob 13:69ff47a83260 25
mariob 13:69ff47a83260 26 /**
mariob 13:69ff47a83260 27 * dimension of the buffers used by the sender and receiver procedure
mariob 13:69ff47a83260 28 */
mariob 4:dbbf82c966c2 29 #define INTERNAL_BUFFER_SIZE 100
mariob 4:dbbf82c966c2 30
mariob 13:69ff47a83260 31
mariob 13:69ff47a83260 32 /** \brief channel abstraction
mariob 13:69ff47a83260 33 *
mariob 24:80345e511574 34 * This object represent the communication channel. It can be different means
mariob 13:69ff47a83260 35 */
mariob 13:69ff47a83260 36 ssWiChannel* channel = NULL;
mariob 13:69ff47a83260 37
mariob 13:69ff47a83260 38 /** \brief serialize read and write operations
mariob 13:69ff47a83260 39 *
mariob 13:69ff47a83260 40 * simultaneous multiple accesses to the mean are avoided
mariob 13:69ff47a83260 41 */
mariob 13:69ff47a83260 42 Mutex mutexChannel;
mariob 13:69ff47a83260 43
mariob 13:69ff47a83260 44 /** \brief set of registered communication ports
mariob 13:69ff47a83260 45 *
mariob 13:69ff47a83260 46 */
mariob 13:69ff47a83260 47 std::map<int, ssWiPort> ports;
mariob 13:69ff47a83260 48
mariob 13:69ff47a83260 49 /** \brief transmission rate
mariob 13:69ff47a83260 50 *
mariob 13:69ff47a83260 51 */
mariob 13:69ff47a83260 52 int TXRate;
mariob 13:69ff47a83260 53
mariob 13:69ff47a83260 54 /** \brief reading rate
mariob 13:69ff47a83260 55 *
mariob 13:69ff47a83260 56 */
mariob 13:69ff47a83260 57 int RXRate;
mariob 13:69ff47a83260 58
mariob 13:69ff47a83260 59
mariob 20:36931ee9af85 60 void functionSender();
mariob 20:36931ee9af85 61 void functionReceiver();
mariob 4:dbbf82c966c2 62
mariob 20:36931ee9af85 63 static Thread readingThread;
mariob 20:36931ee9af85 64 static Thread writingThread;
mariob 4:dbbf82c966c2 65
mariob 4:dbbf82c966c2 66 bool ssWi_init (ssWiChannel* c, int rateTX, int rateRX)
mariob 4:dbbf82c966c2 67 {
mariob 4:dbbf82c966c2 68 if (channel!=NULL)
mariob 4:dbbf82c966c2 69 return false;
mariob 24:80345e511574 70
mariob 24:80345e511574 71 // nothing else is using the channel
mariob 4:dbbf82c966c2 72 channel = c;
mariob 20:36931ee9af85 73 TXRate = rateTX > 0 ? 1000/rateTX : 0;
mariob 20:36931ee9af85 74 RXRate = rateRX > 0 ? 1000/rateRX : 0;
mariob 24:80345e511574 75 // start txer and rxer
mariob 20:36931ee9af85 76 readingThread.start(functionReceiver);
mariob 20:36931ee9af85 77 writingThread.start(functionSender);
mariob 20:36931ee9af85 78
mariob 4:dbbf82c966c2 79 return true;
mariob 4:dbbf82c966c2 80 }
mariob 4:dbbf82c966c2 81
mariob 20:36931ee9af85 82 void functionSender() {
mariob 15:fb0f6cbc0ed5 83 static char buffer[INTERNAL_BUFFER_SIZE];
mariob 20:36931ee9af85 84
mariob 24:80345e511574 85 while (true) {
mariob 9:b5b5d0533fa6 86 int n = 3;
mariob 9:b5b5d0533fa6 87 int numFrames = 0;
mariob 24:80345e511574 88
mariob 24:80345e511574 89 // copy data
mariob 20:36931ee9af85 90 for (std::map<int, ssWiPort>::iterator it = ports.begin();
mariob 24:80345e511574 91 it != ports.end(); it++) {
mariob 24:80345e511574 92 if ((n + sizeof(PortValue) + sizeof(PortID)) > INTERNAL_BUFFER_SIZE)
mariob 24:80345e511574 93 break;
mariob 4:dbbf82c966c2 94 if ((*it).second.isModified()) {
mariob 4:dbbf82c966c2 95 buffer[n++] = (*it).first;
mariob 4:dbbf82c966c2 96 PortValue tmp = (*it).second.getTXValue();
mariob 5:0b0ca40aeb81 97 memcpy(&buffer[n], &tmp, sizeof(PortValue));
mariob 5:0b0ca40aeb81 98 n += sizeof(PortValue);
mariob 9:b5b5d0533fa6 99 numFrames++;
mariob 4:dbbf82c966c2 100 }
mariob 4:dbbf82c966c2 101 }
mariob 24:80345e511574 102 // add header and send
mariob 20:36931ee9af85 103 if (numFrames > 0) {
mariob 9:b5b5d0533fa6 104 buffer[0] = START_0;
mariob 9:b5b5d0533fa6 105 buffer[1] = START_1;
mariob 9:b5b5d0533fa6 106 buffer[2] = START_2;
mariob 24:80345e511574 107 mutexChannel.lock();
mariob 4:dbbf82c966c2 108 channel->write(buffer, n);
mariob 4:dbbf82c966c2 109 mutexChannel.unlock();
mariob 4:dbbf82c966c2 110 }
mariob 24:80345e511574 111
mariob 20:36931ee9af85 112 thread_sleep_for(TXRate);
mariob 4:dbbf82c966c2 113 }
mariob 4:dbbf82c966c2 114 }
mariob 4:dbbf82c966c2 115
mariob 20:36931ee9af85 116 void functionReceiver ()
mariob 4:dbbf82c966c2 117 {
mariob 15:fb0f6cbc0ed5 118 static char buffer[INTERNAL_BUFFER_SIZE];
mariob 22:8dc7a24ff429 119 int offset = 0;
mariob 20:36931ee9af85 120
mariob 20:36931ee9af85 121 while(1) {
mariob 22:8dc7a24ff429 122 thread_sleep_for(RXRate);
mariob 22:8dc7a24ff429 123
mariob 24:80345e511574 124 // read buffer
mariob 24:80345e511574 125 mutexChannel.lock();
mariob 22:8dc7a24ff429 126 int n = channel->read(buffer + offset);
mariob 4:dbbf82c966c2 127 mutexChannel.unlock();
mariob 24:80345e511574 128 // not enough to find the header, merge with next message as the buffer
mariob 24:80345e511574 129 // can contain part of the header
mariob 22:8dc7a24ff429 130 if (n < 3) {
mariob 22:8dc7a24ff429 131 offset = n;
mariob 22:8dc7a24ff429 132 continue;
mariob 22:8dc7a24ff429 133 }
mariob 24:80345e511574 134 // find header
mariob 22:8dc7a24ff429 135 int index = -1;
mariob 22:8dc7a24ff429 136 for (int i=0; i<(n-2); i++) {
mariob 9:b5b5d0533fa6 137 if (buffer[i]==START_0 && buffer[i+1]==START_1 && buffer[i+2]==START_2) {
mariob 22:8dc7a24ff429 138 index = i + 3;
mariob 22:8dc7a24ff429 139 break;
mariob 15:fb0f6cbc0ed5 140 }
mariob 4:dbbf82c966c2 141 }
mariob 24:80345e511574 142 // header not found, discard everthing
mariob 24:80345e511574 143 offset = 0;
mariob 24:80345e511574 144 if (index < 0)
mariob 22:8dc7a24ff429 145 continue;
mariob 24:80345e511574 146 // read samples
mariob 23:2d57c3ea08dc 147 while((index + sizeof(PortID) + sizeof(PortValue)) <= n) {
mariob 22:8dc7a24ff429 148 PortID port = buffer[index++];
mariob 22:8dc7a24ff429 149 PortValue value = 0;
mariob 22:8dc7a24ff429 150 memcpy(&value, &buffer[index], sizeof(PortValue));
mariob 22:8dc7a24ff429 151 index += sizeof(PortValue);
mariob 22:8dc7a24ff429 152 if (ports.find(port)!=ports.end())
mariob 22:8dc7a24ff429 153 ports[port].setRXValue(value);
mariob 22:8dc7a24ff429 154 }
mariob 4:dbbf82c966c2 155 }
mariob 4:dbbf82c966c2 156 }
mariob 13:69ff47a83260 157
mariob 13:69ff47a83260 158
mariob 13:69ff47a83260 159 inline bool ssWi_isActive (PortID port)
mariob 13:69ff47a83260 160 {
mariob 24:80345e511574 161 return channel != NULL && ports.find(port) != ports.end();
mariob 13:69ff47a83260 162 }
mariob 13:69ff47a83260 163
mariob 13:69ff47a83260 164
mariob 13:69ff47a83260 165 bool ssWi_setPort (PortID port)
mariob 13:69ff47a83260 166 {
mariob 24:80345e511574 167 if (channel == NULL)
mariob 13:69ff47a83260 168 return false;
mariob 24:80345e511574 169
mariob 13:69ff47a83260 170 ports[port];
mariob 24:80345e511574 171
mariob 13:69ff47a83260 172 return true;
mariob 13:69ff47a83260 173 }
mariob 13:69ff47a83260 174
mariob 13:69ff47a83260 175
mariob 13:69ff47a83260 176 bool ssWi_unsetPort (PortID port)
mariob 13:69ff47a83260 177 {
mariob 13:69ff47a83260 178 if (!ssWi_isActive(port))
mariob 13:69ff47a83260 179 return false;
mariob 24:80345e511574 180
mariob 13:69ff47a83260 181 ports.erase(port);
mariob 24:80345e511574 182
mariob 13:69ff47a83260 183 return true;
mariob 13:69ff47a83260 184 }