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:
Fri Apr 17 15:19:40 2020 +0000
Revision:
20:36931ee9af85
Parent:
16:b50c3b3b241c
Child:
21:2db8d5db6c57
few fixes, moving to new os

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 20:36931ee9af85 94 static DigitalOut led4(LED4);
mariob 15:fb0f6cbc0ed5 95 static char buffer[INTERNAL_BUFFER_SIZE];
mariob 20:36931ee9af85 96
mariob 20:36931ee9af85 97 while (1) {
mariob 20:36931ee9af85 98 led4 = !led4;
mariob 9:b5b5d0533fa6 99 int n = 3;
mariob 9:b5b5d0533fa6 100 int numFrames = 0;
mariob 20:36931ee9af85 101 for (std::map<int, ssWiPort>::iterator it = ports.begin();
mariob 20:36931ee9af85 102 it != ports.end(); it++) {
mariob 4:dbbf82c966c2 103 if ((*it).second.isModified()) {
mariob 4:dbbf82c966c2 104 buffer[n++] = (*it).first;
mariob 4:dbbf82c966c2 105 PortValue tmp = (*it).second.getTXValue();
mariob 5:0b0ca40aeb81 106 memcpy(&buffer[n], &tmp, sizeof(PortValue));
mariob 5:0b0ca40aeb81 107 n += sizeof(PortValue);
mariob 9:b5b5d0533fa6 108 numFrames++;
mariob 4:dbbf82c966c2 109 }
mariob 4:dbbf82c966c2 110 }
mariob 20:36931ee9af85 111 if (numFrames > 0) {
mariob 9:b5b5d0533fa6 112 buffer[0] = START_0;
mariob 9:b5b5d0533fa6 113 buffer[1] = START_1;
mariob 9:b5b5d0533fa6 114 buffer[2] = START_2;
mariob 20:36931ee9af85 115 if (!mutexChannel.trylock())
mariob 20:36931ee9af85 116 return;
mariob 4:dbbf82c966c2 117 channel->write(buffer, n);
mariob 4:dbbf82c966c2 118 mutexChannel.unlock();
mariob 4:dbbf82c966c2 119 }
mariob 20:36931ee9af85 120 thread_sleep_for(TXRate);
mariob 4:dbbf82c966c2 121 }
mariob 4:dbbf82c966c2 122 }
mariob 4:dbbf82c966c2 123
mariob 20:36931ee9af85 124 void functionReceiver ()
mariob 4:dbbf82c966c2 125 {
mariob 15:fb0f6cbc0ed5 126 static char buffer[INTERNAL_BUFFER_SIZE];
mariob 20:36931ee9af85 127
mariob 20:36931ee9af85 128 while(1) {
mariob 20:36931ee9af85 129 if (!mutexChannel.trylock())
mariob 20:36931ee9af85 130 return;
mariob 5:0b0ca40aeb81 131 int n = channel->read(buffer);
mariob 4:dbbf82c966c2 132 mutexChannel.unlock();
mariob 9:b5b5d0533fa6 133 bool alreadyIn = false;
mariob 9:b5b5d0533fa6 134 for (int i=0; i<(n-2);) {
mariob 9:b5b5d0533fa6 135 bool found = false;
mariob 9:b5b5d0533fa6 136 if (buffer[i]==START_0 && buffer[i+1]==START_1 && buffer[i+2]==START_2) {
mariob 9:b5b5d0533fa6 137 found = true;
mariob 9:b5b5d0533fa6 138 alreadyIn = true;
mariob 9:b5b5d0533fa6 139 i += 3;
mariob 4:dbbf82c966c2 140 }
mariob 9:b5b5d0533fa6 141 if ((found || alreadyIn) && (n-i)>=(sizeof(PortID)+sizeof(PortValue))) {
mariob 9:b5b5d0533fa6 142 PortID port = buffer[i++];
mariob 9:b5b5d0533fa6 143 PortValue value = 0;
mariob 9:b5b5d0533fa6 144 memcpy(&value, &buffer[i], sizeof(PortValue));
mariob 9:b5b5d0533fa6 145 i += sizeof(PortValue);
mariob 9:b5b5d0533fa6 146 if (ports.find(port)!=ports.end())
mariob 9:b5b5d0533fa6 147 ports[port].setRXValue(value);
mariob 15:fb0f6cbc0ed5 148 }
mariob 4:dbbf82c966c2 149 }
mariob 20:36931ee9af85 150 thread_sleep_for(RXRate);
mariob 4:dbbf82c966c2 151 }
mariob 4:dbbf82c966c2 152 }
mariob 13:69ff47a83260 153
mariob 13:69ff47a83260 154
mariob 13:69ff47a83260 155 inline bool ssWi_isActive (PortID port)
mariob 13:69ff47a83260 156 {
mariob 13:69ff47a83260 157 return channel!=NULL && ports.find(port)!=ports.end();
mariob 13:69ff47a83260 158 }
mariob 13:69ff47a83260 159
mariob 13:69ff47a83260 160
mariob 13:69ff47a83260 161 bool ssWi_setPort (PortID port)
mariob 13:69ff47a83260 162 {
mariob 13:69ff47a83260 163 if (channel==NULL)
mariob 13:69ff47a83260 164 return false;
mariob 13:69ff47a83260 165 ports[port];
mariob 13:69ff47a83260 166 return true;
mariob 13:69ff47a83260 167 }
mariob 13:69ff47a83260 168
mariob 13:69ff47a83260 169
mariob 13:69ff47a83260 170 bool ssWi_unsetPort (PortID port)
mariob 13:69ff47a83260 171 {
mariob 13:69ff47a83260 172 if (!ssWi_isActive(port))
mariob 13:69ff47a83260 173 return false;
mariob 13:69ff47a83260 174 ports.erase(port);
mariob 13:69ff47a83260 175 return true;
mariob 13:69ff47a83260 176 }