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 Jan 18 21:01:25 2017 +0000
Revision:
17:8ba1b278b407
Parent:
16:b50c3b3b241c
Child:
18:133e42dc82b0
bug fix: RtosTimer is executed with a low priority - coded moved into a RealTime task

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 /** \brief first byte of the header
mariob 13:69ff47a83260 17 *
mariob 13:69ff47a83260 18 * The header is composed of 3 bytes
mariob 13:69ff47a83260 19 */
mariob 13:69ff47a83260 20 #define START_0 255
mariob 13:69ff47a83260 21
mariob 13:69ff47a83260 22 /** \brief second byte of the header
mariob 13:69ff47a83260 23 *
mariob 13:69ff47a83260 24 * The header is composed of 3 bytes
mariob 13:69ff47a83260 25 */
mariob 13:69ff47a83260 26 #define START_1 130
mariob 13:69ff47a83260 27
mariob 13:69ff47a83260 28 /** \brief third byte of the header
mariob 13:69ff47a83260 29 *
mariob 13:69ff47a83260 30 * The header is composed of 3 bytes
mariob 13:69ff47a83260 31 */
mariob 13:69ff47a83260 32 #define START_2 255
mariob 13:69ff47a83260 33
mariob 13:69ff47a83260 34
mariob 13:69ff47a83260 35 /**
mariob 13:69ff47a83260 36 * dimension of the buffers used by the sender and receiver procedure
mariob 13:69ff47a83260 37 */
mariob 4:dbbf82c966c2 38 #define INTERNAL_BUFFER_SIZE 100
mariob 4:dbbf82c966c2 39
mariob 13:69ff47a83260 40
mariob 13:69ff47a83260 41 /** \brief channel abstraction
mariob 13:69ff47a83260 42 *
mariob 13:69ff47a83260 43 * This object represent the communication channel that can be
mariob 13:69ff47a83260 44 * different means
mariob 13:69ff47a83260 45 */
mariob 17:8ba1b278b407 46 static ssWiChannel* channel = NULL;
mariob 13:69ff47a83260 47
mariob 13:69ff47a83260 48 /** \brief serialize read and write operations
mariob 13:69ff47a83260 49 *
mariob 13:69ff47a83260 50 * simultaneous multiple accesses to the mean are avoided
mariob 13:69ff47a83260 51 */
mariob 17:8ba1b278b407 52 static Mutex mutexChannel;
mariob 13:69ff47a83260 53
mariob 13:69ff47a83260 54 /** \brief set of registered communication ports
mariob 13:69ff47a83260 55 *
mariob 13:69ff47a83260 56 */
mariob 13:69ff47a83260 57 std::map<int, ssWiPort> ports;
mariob 13:69ff47a83260 58
mariob 13:69ff47a83260 59 /** \brief transmission rate
mariob 13:69ff47a83260 60 *
mariob 13:69ff47a83260 61 */
mariob 17:8ba1b278b407 62 static int TXRate;
mariob 13:69ff47a83260 63
mariob 13:69ff47a83260 64 /** \brief reading rate
mariob 13:69ff47a83260 65 *
mariob 13:69ff47a83260 66 */
mariob 17:8ba1b278b407 67 static int RXRate;
mariob 13:69ff47a83260 68
mariob 17:8ba1b278b407 69 void functionSender ();
mariob 17:8ba1b278b407 70 void functionReceiver ();
mariob 13:69ff47a83260 71
mariob 17:8ba1b278b407 72 // threads
mariob 17:8ba1b278b407 73 static Thread thread_sender(osPriorityRealtime);
mariob 17:8ba1b278b407 74 static Thread thread_receiver(osPriorityRealtime);
mariob 4:dbbf82c966c2 75
mariob 17:8ba1b278b407 76
mariob 4:dbbf82c966c2 77 bool ssWi_init (ssWiChannel* c, int rateTX, int rateRX)
mariob 4:dbbf82c966c2 78 {
mariob 17:8ba1b278b407 79 // protocol cannot be restarted once started
mariob 17:8ba1b278b407 80 if (channel != NULL || rateTX <= 0 || rateRX <= 0)
mariob 4:dbbf82c966c2 81 return false;
mariob 17:8ba1b278b407 82
mariob 4:dbbf82c966c2 83 channel = c;
mariob 17:8ba1b278b407 84
mariob 17:8ba1b278b407 85 TXRate = 1000 / rateTX;
mariob 17:8ba1b278b407 86 RXRate = 1000 / rateRX;
mariob 17:8ba1b278b407 87
mariob 17:8ba1b278b407 88 thread_sender.start(&functionSender);
mariob 17:8ba1b278b407 89 thread_receiver.start(&functionReceiver);
mariob 17:8ba1b278b407 90
mariob 4:dbbf82c966c2 91 return true;
mariob 4:dbbf82c966c2 92 }
mariob 4:dbbf82c966c2 93
mariob 17:8ba1b278b407 94 void functionSender ()
mariob 4:dbbf82c966c2 95 {
mariob 17:8ba1b278b407 96 while (1) {
mariob 17:8ba1b278b407 97 static char buffer[INTERNAL_BUFFER_SIZE];
mariob 9:b5b5d0533fa6 98 int n = 3;
mariob 9:b5b5d0533fa6 99 int numFrames = 0;
mariob 17:8ba1b278b407 100 for (std::map<int, ssWiPort>::iterator it = ports.begin();
mariob 17:8ba1b278b407 101 it!=ports.end(); it++) {
mariob 4:dbbf82c966c2 102 if ((*it).second.isModified()) {
mariob 4:dbbf82c966c2 103 buffer[n++] = (*it).first;
mariob 4:dbbf82c966c2 104 PortValue tmp = (*it).second.getTXValue();
mariob 5:0b0ca40aeb81 105 memcpy(&buffer[n], &tmp, sizeof(PortValue));
mariob 5:0b0ca40aeb81 106 n += sizeof(PortValue);
mariob 9:b5b5d0533fa6 107 numFrames++;
mariob 4:dbbf82c966c2 108 }
mariob 4:dbbf82c966c2 109 }
mariob 17:8ba1b278b407 110 if (numFrames > 0) {
mariob 9:b5b5d0533fa6 111 buffer[0] = START_0;
mariob 9:b5b5d0533fa6 112 buffer[1] = START_1;
mariob 9:b5b5d0533fa6 113 buffer[2] = START_2;
mariob 4:dbbf82c966c2 114 mutexChannel.lock();
mariob 4:dbbf82c966c2 115 channel->write(buffer, n);
mariob 4:dbbf82c966c2 116 mutexChannel.unlock();
mariob 4:dbbf82c966c2 117 }
mariob 4:dbbf82c966c2 118 Thread::wait(TXRate);
mariob 4:dbbf82c966c2 119 }
mariob 4:dbbf82c966c2 120 }
mariob 4:dbbf82c966c2 121
mariob 17:8ba1b278b407 122 void functionReceiver ()
mariob 4:dbbf82c966c2 123 {
mariob 17:8ba1b278b407 124 while (1) {
mariob 17:8ba1b278b407 125 static char buffer[INTERNAL_BUFFER_SIZE];
mariob 4:dbbf82c966c2 126 mutexChannel.lock();
mariob 5:0b0ca40aeb81 127 int n = channel->read(buffer);
mariob 4:dbbf82c966c2 128 mutexChannel.unlock();
mariob 9:b5b5d0533fa6 129 bool alreadyIn = false;
mariob 17:8ba1b278b407 130 for (int i=0; i < (n - 2); ) {
mariob 9:b5b5d0533fa6 131 bool found = false;
mariob 17:8ba1b278b407 132 if (buffer[i] == START_0 && buffer[i+1] == START_1 &&
mariob 17:8ba1b278b407 133 buffer[i+2] == START_2) {
mariob 9:b5b5d0533fa6 134 found = true;
mariob 9:b5b5d0533fa6 135 alreadyIn = true;
mariob 9:b5b5d0533fa6 136 i += 3;
mariob 4:dbbf82c966c2 137 }
mariob 17:8ba1b278b407 138 if ((found || alreadyIn) && (n-i) >= (sizeof(PortID) +
mariob 17:8ba1b278b407 139 sizeof(PortValue))) {
mariob 9:b5b5d0533fa6 140 PortID port = buffer[i++];
mariob 9:b5b5d0533fa6 141 PortValue value = 0;
mariob 9:b5b5d0533fa6 142 memcpy(&value, &buffer[i], sizeof(PortValue));
mariob 9:b5b5d0533fa6 143 i += sizeof(PortValue);
mariob 17:8ba1b278b407 144 if (ports.find(port) != ports.end())
mariob 9:b5b5d0533fa6 145 ports[port].setRXValue(value);
mariob 15:fb0f6cbc0ed5 146 }
mariob 4:dbbf82c966c2 147 }
mariob 4:dbbf82c966c2 148 Thread::wait(RXRate);
mariob 4:dbbf82c966c2 149 }
mariob 4:dbbf82c966c2 150 }
mariob 13:69ff47a83260 151
mariob 13:69ff47a83260 152 inline bool ssWi_isActive (PortID port)
mariob 13:69ff47a83260 153 {
mariob 17:8ba1b278b407 154 return channel != NULL && ports.find(port) != ports.end();
mariob 13:69ff47a83260 155 }
mariob 13:69ff47a83260 156
mariob 13:69ff47a83260 157 bool ssWi_setPort (PortID port)
mariob 13:69ff47a83260 158 {
mariob 17:8ba1b278b407 159 if (channel == NULL)
mariob 13:69ff47a83260 160 return false;
mariob 13:69ff47a83260 161 ports[port];
mariob 13:69ff47a83260 162 return true;
mariob 13:69ff47a83260 163 }
mariob 13:69ff47a83260 164
mariob 13:69ff47a83260 165 bool ssWi_unsetPort (PortID port)
mariob 13:69ff47a83260 166 {
mariob 13:69ff47a83260 167 if (!ssWi_isActive(port))
mariob 13:69ff47a83260 168 return false;
mariob 13:69ff47a83260 169 ports.erase(port);
mariob 13:69ff47a83260 170 return true;
mariob 13:69ff47a83260 171 }