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:
Sun Apr 19 17:59:59 2020 +0000
Revision:
23:2d57c3ea08dc
Parent:
22:8dc7a24ff429
Child:
24:80345e511574
fix

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 20:36931ee9af85 71 void functionSender();
mariob 20:36931ee9af85 72 void functionReceiver();
mariob 4:dbbf82c966c2 73
mariob 20:36931ee9af85 74 static Thread readingThread;
mariob 20:36931ee9af85 75 static Thread writingThread;
mariob 4:dbbf82c966c2 76
mariob 4:dbbf82c966c2 77 bool ssWi_init (ssWiChannel* c, int rateTX, int rateRX)
mariob 4:dbbf82c966c2 78 {
mariob 4:dbbf82c966c2 79 if (channel!=NULL)
mariob 4:dbbf82c966c2 80 return false;
mariob 20:36931ee9af85 81 //mutexChannel.lock();
mariob 4:dbbf82c966c2 82 channel = c;
mariob 20:36931ee9af85 83 //mutexChannel.unlock();
mariob 20:36931ee9af85 84 TXRate = rateTX > 0 ? 1000/rateTX : 0;
mariob 20:36931ee9af85 85 RXRate = rateRX > 0 ? 1000/rateRX : 0;
mariob 20:36931ee9af85 86
mariob 20:36931ee9af85 87 readingThread.start(functionReceiver);
mariob 20:36931ee9af85 88 writingThread.start(functionSender);
mariob 20:36931ee9af85 89
mariob 4:dbbf82c966c2 90 return true;
mariob 4:dbbf82c966c2 91 }
mariob 4:dbbf82c966c2 92
mariob 20:36931ee9af85 93 void functionSender() {
mariob 15:fb0f6cbc0ed5 94 static char buffer[INTERNAL_BUFFER_SIZE];
mariob 20:36931ee9af85 95
mariob 20:36931ee9af85 96 while (1) {
mariob 9:b5b5d0533fa6 97 int n = 3;
mariob 9:b5b5d0533fa6 98 int numFrames = 0;
mariob 20:36931ee9af85 99 for (std::map<int, ssWiPort>::iterator it = ports.begin();
mariob 20:36931ee9af85 100 it != ports.end(); it++) {
mariob 4:dbbf82c966c2 101 if ((*it).second.isModified()) {
mariob 4:dbbf82c966c2 102 buffer[n++] = (*it).first;
mariob 4:dbbf82c966c2 103 PortValue tmp = (*it).second.getTXValue();
mariob 5:0b0ca40aeb81 104 memcpy(&buffer[n], &tmp, sizeof(PortValue));
mariob 5:0b0ca40aeb81 105 n += sizeof(PortValue);
mariob 9:b5b5d0533fa6 106 numFrames++;
mariob 4:dbbf82c966c2 107 }
mariob 4:dbbf82c966c2 108 }
mariob 20:36931ee9af85 109 if (numFrames > 0) {
mariob 9:b5b5d0533fa6 110 buffer[0] = START_0;
mariob 9:b5b5d0533fa6 111 buffer[1] = START_1;
mariob 9:b5b5d0533fa6 112 buffer[2] = START_2;
mariob 20:36931ee9af85 113 if (!mutexChannel.trylock())
mariob 20:36931ee9af85 114 return;
mariob 4:dbbf82c966c2 115 channel->write(buffer, n);
mariob 4:dbbf82c966c2 116 mutexChannel.unlock();
mariob 4:dbbf82c966c2 117 }
mariob 20:36931ee9af85 118 thread_sleep_for(TXRate);
mariob 4:dbbf82c966c2 119 }
mariob 4:dbbf82c966c2 120 }
mariob 4:dbbf82c966c2 121
mariob 20:36931ee9af85 122 void functionReceiver ()
mariob 4:dbbf82c966c2 123 {
mariob 15:fb0f6cbc0ed5 124 static char buffer[INTERNAL_BUFFER_SIZE];
mariob 22:8dc7a24ff429 125 int offset = 0;
mariob 20:36931ee9af85 126
mariob 20:36931ee9af85 127 while(1) {
mariob 22:8dc7a24ff429 128 thread_sleep_for(RXRate);
mariob 22:8dc7a24ff429 129
mariob 20:36931ee9af85 130 if (!mutexChannel.trylock())
mariob 20:36931ee9af85 131 return;
mariob 22:8dc7a24ff429 132 int n = channel->read(buffer + offset);
mariob 4:dbbf82c966c2 133 mutexChannel.unlock();
mariob 22:8dc7a24ff429 134
mariob 22:8dc7a24ff429 135 if (n < 3) {
mariob 22:8dc7a24ff429 136 offset = n;
mariob 22:8dc7a24ff429 137 continue;
mariob 22:8dc7a24ff429 138 }
mariob 22:8dc7a24ff429 139
mariob 22:8dc7a24ff429 140 int index = -1;
mariob 22:8dc7a24ff429 141 for (int i=0; i<(n-2); i++) {
mariob 9:b5b5d0533fa6 142 if (buffer[i]==START_0 && buffer[i+1]==START_1 && buffer[i+2]==START_2) {
mariob 22:8dc7a24ff429 143 index = i + 3;
mariob 22:8dc7a24ff429 144 break;
mariob 15:fb0f6cbc0ed5 145 }
mariob 4:dbbf82c966c2 146 }
mariob 22:8dc7a24ff429 147
mariob 22:8dc7a24ff429 148 if (index < 0) {
mariob 22:8dc7a24ff429 149 offset = n;
mariob 22:8dc7a24ff429 150 continue;
mariob 22:8dc7a24ff429 151 }
mariob 22:8dc7a24ff429 152 offset = 0;
mariob 22:8dc7a24ff429 153
mariob 23:2d57c3ea08dc 154 while((index + sizeof(PortID) + sizeof(PortValue)) <= n) {
mariob 22:8dc7a24ff429 155 PortID port = buffer[index++];
mariob 22:8dc7a24ff429 156 PortValue value = 0;
mariob 22:8dc7a24ff429 157 memcpy(&value, &buffer[index], sizeof(PortValue));
mariob 22:8dc7a24ff429 158 index += sizeof(PortValue);
mariob 22:8dc7a24ff429 159 if (ports.find(port)!=ports.end())
mariob 22:8dc7a24ff429 160 ports[port].setRXValue(value);
mariob 22:8dc7a24ff429 161 }
mariob 4:dbbf82c966c2 162 }
mariob 4:dbbf82c966c2 163 }
mariob 13:69ff47a83260 164
mariob 13:69ff47a83260 165
mariob 13:69ff47a83260 166 inline bool ssWi_isActive (PortID port)
mariob 13:69ff47a83260 167 {
mariob 13:69ff47a83260 168 return channel!=NULL && ports.find(port)!=ports.end();
mariob 13:69ff47a83260 169 }
mariob 13:69ff47a83260 170
mariob 13:69ff47a83260 171
mariob 13:69ff47a83260 172 bool ssWi_setPort (PortID port)
mariob 13:69ff47a83260 173 {
mariob 13:69ff47a83260 174 if (channel==NULL)
mariob 13:69ff47a83260 175 return false;
mariob 13:69ff47a83260 176 ports[port];
mariob 13:69ff47a83260 177 return true;
mariob 13:69ff47a83260 178 }
mariob 13:69ff47a83260 179
mariob 13:69ff47a83260 180
mariob 13:69ff47a83260 181 bool ssWi_unsetPort (PortID port)
mariob 13:69ff47a83260 182 {
mariob 13:69ff47a83260 183 if (!ssWi_isActive(port))
mariob 13:69ff47a83260 184 return false;
mariob 13:69ff47a83260 185 ports.erase(port);
mariob 13:69ff47a83260 186 return true;
mariob 13:69ff47a83260 187 }