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 Jan 22 23:25:16 2017 +0000
Revision:
19:e8058fd532d6
Parent:
18:133e42dc82b0
code cleanup

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