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:
Thu Jan 19 23:29:34 2017 +0000
Revision:
18:133e42dc82b0
Parent:
17:8ba1b278b407
Child:
19:e8058fd532d6
fix: buffer management

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