RadioShuttle Lib for the STM32 L4 Heltec Board

Dependents:   Turtle_RadioShuttle

Committer:
Helmut64
Date:
Wed Feb 06 15:26:48 2019 +0000
Revision:
0:0c31756924a2
Child:
11:91bc7ef20f21
new lib

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Helmut64 0:0c31756924a2 1 /*
Helmut64 0:0c31756924a2 2 * This is an unpublished work copyright
Helmut64 0:0c31756924a2 3 * (c) 2019 Helmut Tschemernjak
Helmut64 0:0c31756924a2 4 * 30826 Garbsen (Hannover) Germany
Helmut64 0:0c31756924a2 5 *
Helmut64 0:0c31756924a2 6 *
Helmut64 0:0c31756924a2 7 * Use is granted to registered RadioShuttle licensees only.
Helmut64 0:0c31756924a2 8 * Licensees must own a valid serial number and product code.
Helmut64 0:0c31756924a2 9 * Details see: www.radioshuttle.de
Helmut64 0:0c31756924a2 10 */
Helmut64 0:0c31756924a2 11
Helmut64 0:0c31756924a2 12 #ifndef __RADIOSHUTTLE_H__
Helmut64 0:0c31756924a2 13 #define __RADIOSHUTTLE_H__
Helmut64 0:0c31756924a2 14
Helmut64 0:0c31756924a2 15 #ifdef ARDUINO
Helmut64 0:0c31756924a2 16 #include "arduino-mbed.h"
Helmut64 0:0c31756924a2 17 #include <time.h>
Helmut64 0:0c31756924a2 18 #include <assert.h>
Helmut64 0:0c31756924a2 19 #undef min
Helmut64 0:0c31756924a2 20 #undef max
Helmut64 0:0c31756924a2 21 #undef map
Helmut64 0:0c31756924a2 22 #define MyTimeout Timeout
Helmut64 0:0c31756924a2 23 #define MyTimer Timer
Helmut64 0:0c31756924a2 24 #define STATIC_ASSERT _Static_assert
Helmut64 0:0c31756924a2 25 #define ASSERT assert
Helmut64 0:0c31756924a2 26 using namespace std;
Helmut64 0:0c31756924a2 27 #define FEATURE_LORA 1
Helmut64 0:0c31756924a2 28
Helmut64 0:0c31756924a2 29 #else
Helmut64 0:0c31756924a2 30
Helmut64 0:0c31756924a2 31 #if defined(DEVICE_LPTICKER) || defined(DEVICE_LOWPOWERTIMER) // LOWPOWERTIMER in older mbed versions
Helmut64 0:0c31756924a2 32 #define MyTimeout LowPowerTimeout
Helmut64 0:0c31756924a2 33 #define MyTimer LowPowerTimer
Helmut64 0:0c31756924a2 34 #else
Helmut64 0:0c31756924a2 35 #define MyTimeout Timeout
Helmut64 0:0c31756924a2 36 #define MyTimer Timer
Helmut64 0:0c31756924a2 37 #endif
Helmut64 0:0c31756924a2 38
Helmut64 0:0c31756924a2 39 #endif
Helmut64 0:0c31756924a2 40
Helmut64 0:0c31756924a2 41 #include <list>
Helmut64 0:0c31756924a2 42 #include <map>
Helmut64 0:0c31756924a2 43 #include "radio.h"
Helmut64 0:0c31756924a2 44 #include "RadioStatusInterface.h"
Helmut64 0:0c31756924a2 45 #include "RadioSecurityInterface.h"
Helmut64 0:0c31756924a2 46
Helmut64 0:0c31756924a2 47 #ifdef ARDUINO
Helmut64 0:0c31756924a2 48 #define map std::map // map clashes with Arduino map()
Helmut64 0:0c31756924a2 49 #endif
Helmut64 0:0c31756924a2 50 #ifdef FEATURE_LORA
Helmut64 0:0c31756924a2 51
Helmut64 0:0c31756924a2 52
Helmut64 0:0c31756924a2 53 typedef enum RSErrorCode {
Helmut64 0:0c31756924a2 54 RS_NoErr = 0,
Helmut64 0:0c31756924a2 55 RS_DuplicateAppID,
Helmut64 0:0c31756924a2 56 RS_AppID_NotFound,
Helmut64 0:0c31756924a2 57 RS_StationNotConnected,
Helmut64 0:0c31756924a2 58 RS_NoPasswordSet,
Helmut64 0:0c31756924a2 59 RS_PasswordSet,
Helmut64 0:0c31756924a2 60 RS_NoSecurityInterface,
Helmut64 0:0c31756924a2 61 RS_MsgID_NotFound,
Helmut64 0:0c31756924a2 62 RS_NoRadioConfigured, // No radio added so far
Helmut64 0:0c31756924a2 63 RS_NoRadioAvailable, // Radio could not be detected
Helmut64 0:0c31756924a2 64 RS_RadioNotFound, // The specified radio is not available
Helmut64 0:0c31756924a2 65 RS_UnknownModemType, // No FSK no LoRa modem type
Helmut64 0:0c31756924a2 66 RS_MessageSizeExceeded, // Message size too long
Helmut64 0:0c31756924a2 67 RS_InvalidProductCode, // license does not match
Helmut64 0:0c31756924a2 68 RS_InvalidParam, // invalid parameter.
Helmut64 0:0c31756924a2 69 RS_OutOfMemory, // unable to allocate memory
Helmut64 0:0c31756924a2 70 } RSCode;
Helmut64 0:0c31756924a2 71
Helmut64 0:0c31756924a2 72
Helmut64 0:0c31756924a2 73
Helmut64 0:0c31756924a2 74 // Shuttle
Helmut64 0:0c31756924a2 75 class RadioShuttle
Helmut64 0:0c31756924a2 76 {
Helmut64 0:0c31756924a2 77 public:
Helmut64 0:0c31756924a2 78 typedef uint32_t devid_t;
Helmut64 0:0c31756924a2 79 static const int DEV_ID_ANY = 0;
Helmut64 0:0c31756924a2 80 static const int TX_POWER_AUTO = 9999;
Helmut64 0:0c31756924a2 81
Helmut64 0:0c31756924a2 82 struct RadioProfile {
Helmut64 0:0c31756924a2 83 int Frequency; // in Hz
Helmut64 0:0c31756924a2 84 int Bandwidth; // in Hz
Helmut64 0:0c31756924a2 85 int TXPower; // in dBm
Helmut64 0:0c31756924a2 86 int SpreadingFaktor;// 7-12
Helmut64 0:0c31756924a2 87 int FrequencyOffset;// +/- in Hz
Helmut64 0:0c31756924a2 88 };
Helmut64 0:0c31756924a2 89
Helmut64 0:0c31756924a2 90 enum RadioType {
Helmut64 0:0c31756924a2 91 RS_RadioType_Invalid = 0,
Helmut64 0:0c31756924a2 92 RS_Node_Offline, // Sleep mode until sending, < 10k RAM
Helmut64 0:0c31756924a2 93 RS_Node_Checking, // Sleep mode, checks for messages regulary, < 10k RAM
Helmut64 0:0c31756924a2 94 RS_Node_Online, // Always powered-on, < 10k RAM
Helmut64 0:0c31756924a2 95 RS_Station_Basic, // Always active for one or more apps < 15k RAM
Helmut64 0:0c31756924a2 96 RS_Station_Server, // Always active, lots of memory, routing options, < 1 MB RAM
Helmut64 0:0c31756924a2 97 };
Helmut64 0:0c31756924a2 98
Helmut64 0:0c31756924a2 99 typedef void (*AppRecvHandler)(int AppID, devid_t stationID, int msgID, int status, void *data, int length);
Helmut64 0:0c31756924a2 100
Helmut64 0:0c31756924a2 101
Helmut64 0:0c31756924a2 102 enum MsgStatus {
Helmut64 0:0c31756924a2 103 MS_SentCompleted, // A previous SendMsg has been sent
Helmut64 0:0c31756924a2 104 MS_SentCompletedConfirmed, // A previous SendMsg has been sent and confirmed
Helmut64 0:0c31756924a2 105 MS_SentTimeout, // A timeout occurred, number of retries exceeded
Helmut64 0:0c31756924a2 106
Helmut64 0:0c31756924a2 107 MS_RecvData, // A simple input message
Helmut64 0:0c31756924a2 108 MS_RecvDataConfirmed, // Received a confirmed message
Helmut64 0:0c31756924a2 109 MS_NoStationFound,
Helmut64 0:0c31756924a2 110 MS_NoStationSupportsApp,
Helmut64 0:0c31756924a2 111 MS_AuthenicationRequired,
Helmut64 0:0c31756924a2 112
Helmut64 0:0c31756924a2 113 MS_StationConnected, // A confirmation that the connection was accepted
Helmut64 0:0c31756924a2 114 MS_StationDisconnected, // A confirmation that the disconnect was accepted
Helmut64 0:0c31756924a2 115 };
Helmut64 0:0c31756924a2 116
Helmut64 0:0c31756924a2 117 enum MsgFlags {
Helmut64 0:0c31756924a2 118 MF_Response = 0x01, // A response from a previous request, or request
Helmut64 0:0c31756924a2 119 MF_NeedsConfirm = 0x02, // Station needs to acknloglage receivd
Helmut64 0:0c31756924a2 120 MF_LowPriority = 0x04, // Transfer within one minute
Helmut64 0:0c31756924a2 121 MF_HighPriority = 0x08, // ImmEdate transfer
Helmut64 0:0c31756924a2 122 MF_MoreDataToCome = 0x10, // Additional data is wait to be sent
Helmut64 0:0c31756924a2 123 MF_Connect = 0x20, // Connect a node to the station with password
Helmut64 0:0c31756924a2 124 MF_Encrypted = 0x40, // Message is encrypted
Helmut64 0:0c31756924a2 125 MF_Authentication = 0x80, // Message requires prior authentication
Helmut64 0:0c31756924a2 126 MF_SwitchOptions = 0x100,// Tell the node to switch the channel for this trans ID
Helmut64 0:0c31756924a2 127 MF_FlagsMask = 0b111111111, // max flags for the RadioShuttle protocol, see msgFlags : 9
Helmut64 0:0c31756924a2 128 /*
Helmut64 0:0c31756924a2 129 * optional control flags are here.
Helmut64 0:0c31756924a2 130 */
Helmut64 0:0c31756924a2 131 CF_FreeData = 0x200, // if a data buffer is provided, free it afterwords.
Helmut64 0:0c31756924a2 132 CF_CopyData = 0x400, // create a copy of the data.
Helmut64 0:0c31756924a2 133 };
Helmut64 0:0c31756924a2 134
Helmut64 0:0c31756924a2 135 struct RadioStats {
Helmut64 0:0c31756924a2 136 int RxPackets;
Helmut64 0:0c31756924a2 137 int TxPackets;
Helmut64 0:0c31756924a2 138 int RxErrorCount;
Helmut64 0:0c31756924a2 139 int channelBusyCount;
Helmut64 0:0c31756924a2 140 long long rxBytes;
Helmut64 0:0c31756924a2 141 long long txBytes;
Helmut64 0:0c31756924a2 142 int noAuthMessageCount;
Helmut64 0:0c31756924a2 143 int unkownMessageCount;
Helmut64 0:0c31756924a2 144 int appNotSupported;
Helmut64 0:0c31756924a2 145 int protocolError;
Helmut64 0:0c31756924a2 146 int noMemoryError;
Helmut64 0:0c31756924a2 147 int decryptError;
Helmut64 0:0c31756924a2 148 int lastRSSI;
Helmut64 0:0c31756924a2 149 int lastSNR;
Helmut64 0:0c31756924a2 150 devid_t lastRXdeviceID;
Helmut64 0:0c31756924a2 151 time_t startupTime;
Helmut64 0:0c31756924a2 152 };
Helmut64 0:0c31756924a2 153
Helmut64 0:0c31756924a2 154 /*
Helmut64 0:0c31756924a2 155 * Constructor requires a radio
Helmut64 0:0c31756924a2 156 */
Helmut64 0:0c31756924a2 157 RadioShuttle(const char *deviceName);
Helmut64 0:0c31756924a2 158
Helmut64 0:0c31756924a2 159 /*
Helmut64 0:0c31756924a2 160 * Destructor, stop radios, free resources
Helmut64 0:0c31756924a2 161 */
Helmut64 0:0c31756924a2 162 ~RadioShuttle();
Helmut64 0:0c31756924a2 163
Helmut64 0:0c31756924a2 164 /*
Helmut64 0:0c31756924a2 165 * Adds a license to use the RadioShuttle, licenses are
Helmut64 0:0c31756924a2 166 * may be bundled with the board or are available for
Helmut64 0:0c31756924a2 167 * purchase at: www.radioshuttle.com
Helmut64 0:0c31756924a2 168 * The license is bound to a special board ID and a fixed
Helmut64 0:0c31756924a2 169 * node deviceID.
Helmut64 0:0c31756924a2 170 */
Helmut64 0:0c31756924a2 171 RSCode AddLicense(devid_t deviceID, uint32_t productCode);
Helmut64 0:0c31756924a2 172
Helmut64 0:0c31756924a2 173 /*
Helmut64 0:0c31756924a2 174 * Adds a new radio with a given profile
Helmut64 0:0c31756924a2 175 * Optional profile, must be called before startup
Helmut64 0:0c31756924a2 176 */
Helmut64 0:0c31756924a2 177 RSCode AddRadio(Radio *radio, RadioModems_t modem, const struct RadioProfile *profile = NULL);
Helmut64 0:0c31756924a2 178
Helmut64 0:0c31756924a2 179 /*
Helmut64 0:0c31756924a2 180 * This allows to swtich between RS_Node_Offline and RS_Node_Online
Helmut64 0:0c31756924a2 181 * after the Startup() is already completed.
Helmut64 0:0c31756924a2 182 */
Helmut64 0:0c31756924a2 183 RSCode UpdateNodeStartup(RadioType newRadioType);
Helmut64 0:0c31756924a2 184
Helmut64 0:0c31756924a2 185 /*
Helmut64 0:0c31756924a2 186 * The status interface allows custom status callbacks for
Helmut64 0:0c31756924a2 187 * reporting send/receive/timeout activity e.g.: LED blinks
Helmut64 0:0c31756924a2 188 */
Helmut64 0:0c31756924a2 189 RSCode AddRadioStatus(RadioStatusInterface *statusIntf);
Helmut64 0:0c31756924a2 190
Helmut64 0:0c31756924a2 191 /*
Helmut64 0:0c31756924a2 192 * Support function for password hash generation and encryption
Helmut64 0:0c31756924a2 193 * The external API interface has the advantage that the security
Helmut64 0:0c31756924a2 194 * can be upgraded independently of the RadioShuttle library.
Helmut64 0:0c31756924a2 195 * AES hardware accelleration can be one reason for it.
Helmut64 0:0c31756924a2 196 */
Helmut64 0:0c31756924a2 197 RSCode AddRadioSecurity(RadioSecurityInterface *securityIntf);
Helmut64 0:0c31756924a2 198
Helmut64 0:0c31756924a2 199 /*
Helmut64 0:0c31756924a2 200 * Starts the service with the specified RadioType
Helmut64 0:0c31756924a2 201 */
Helmut64 0:0c31756924a2 202 RSCode Startup(RadioType radioType);
Helmut64 0:0c31756924a2 203
Helmut64 0:0c31756924a2 204 /*
Helmut64 0:0c31756924a2 205 * get the current radio type
Helmut64 0:0c31756924a2 206 */
Helmut64 0:0c31756924a2 207 RadioType GetRadioType(void);
Helmut64 0:0c31756924a2 208
Helmut64 0:0c31756924a2 209 /*
Helmut64 0:0c31756924a2 210 * Registers an application, the AppType is unique worldwide
Helmut64 0:0c31756924a2 211 * and must be used for sending and receiving app data.
Helmut64 0:0c31756924a2 212 * Multiple AppID registrations are supported.
Helmut64 0:0c31756924a2 213 * The password can be a string to the password,
Helmut64 0:0c31756924a2 214 * in case of binary passwd data the pwLen must be set.
Helmut64 0:0c31756924a2 215 * If the password is set, clients must call Connect() prior
Helmut64 0:0c31756924a2 216 * to any SendMsg.
Helmut64 0:0c31756924a2 217 */
Helmut64 0:0c31756924a2 218 RSCode RegisterApplication(int AppID, AppRecvHandler, void *password = NULL, int pwLen = 0);
Helmut64 0:0c31756924a2 219 /*
Helmut64 0:0c31756924a2 220 * Removes the AppID
Helmut64 0:0c31756924a2 221 */
Helmut64 0:0c31756924a2 222 RSCode DeRegisterApplication(int AppID);
Helmut64 0:0c31756924a2 223
Helmut64 0:0c31756924a2 224 /*
Helmut64 0:0c31756924a2 225 * Check if the password is specified for an app
Helmut64 0:0c31756924a2 226 */
Helmut64 0:0c31756924a2 227 RSCode AppRequiresAuthentication(int AppID);
Helmut64 0:0c31756924a2 228
Helmut64 0:0c31756924a2 229 /*
Helmut64 0:0c31756924a2 230 * Start a pairing process to connect a node to a station
Helmut64 0:0c31756924a2 231 */
Helmut64 0:0c31756924a2 232 RSCode StartPairing(char *name = NULL);
Helmut64 0:0c31756924a2 233 /*
Helmut64 0:0c31756924a2 234 * Connect the node against a station, it can be called multiple times
Helmut64 0:0c31756924a2 235 * if communication with multiple station IDs is used.
Helmut64 0:0c31756924a2 236 * The connect verifies the password against the app of remote station.
Helmut64 0:0c31756924a2 237 */
Helmut64 0:0c31756924a2 238 RSCode Connect(int AppID, devid_t stationID = DEV_ID_ANY);
Helmut64 0:0c31756924a2 239
Helmut64 0:0c31756924a2 240 /*
Helmut64 0:0c31756924a2 241 * Inform the station that an app is discontinuing
Helmut64 0:0c31756924a2 242 */
Helmut64 0:0c31756924a2 243 RSCode Disconnect(int AppID, devid_t stationID = ~0);
Helmut64 0:0c31756924a2 244
Helmut64 0:0c31756924a2 245 /*
Helmut64 0:0c31756924a2 246 * Prepare sending data to a remote application
Helmut64 0:0c31756924a2 247 * The request is queued for sending.
Helmut64 0:0c31756924a2 248 * valid flags see enum MsgFlags
Helmut64 0:0c31756924a2 249 * txPower allows to overwrite the txPower in dBm.
Helmut64 0:0c31756924a2 250 * The data is busy until the AppRecvHandler is called
Helmut64 0:0c31756924a2 251 */
Helmut64 0:0c31756924a2 252 RSCode SendMsg(int AppID, void *data, int len, int flags = 0, devid_t stationID = DEV_ID_ANY, int txPower = TX_POWER_AUTO, int *msgID = NULL);
Helmut64 0:0c31756924a2 253 /*
Helmut64 0:0c31756924a2 254 * Removes a message from the queue
Helmut64 0:0c31756924a2 255 */
Helmut64 0:0c31756924a2 256 RSCode KillMsg(int AppID, int msgID);
Helmut64 0:0c31756924a2 257
Helmut64 0:0c31756924a2 258 /*
Helmut64 0:0c31756924a2 259 * Sets a new profile for a given radio with a given profile
Helmut64 0:0c31756924a2 260 * This can be called anytime after the RadioShuttle startup.
Helmut64 0:0c31756924a2 261 */
Helmut64 0:0c31756924a2 262 RSCode UpdateRadioProfile(Radio *radio, RadioType radioType, const struct RadioProfile *profile);
Helmut64 0:0c31756924a2 263
Helmut64 0:0c31756924a2 264 /*
Helmut64 0:0c31756924a2 265 * Sets the size value to the largest messages available
Helmut64 0:0c31756924a2 266 * for all configured radios
Helmut64 0:0c31756924a2 267 * The flags are important because encrypted messages need more space
Helmut64 0:0c31756924a2 268 */
Helmut64 0:0c31756924a2 269 RSCode MaxMessageSize(int *size, int msgFlags = 0);
Helmut64 0:0c31756924a2 270
Helmut64 0:0c31756924a2 271 /*
Helmut64 0:0c31756924a2 272 * Get statistics of all messages and errors
Helmut64 0:0c31756924a2 273 * A pointer reference containing the RadioStats must be provided.
Helmut64 0:0c31756924a2 274 * The statistics contain the information of the first radio, unless
Helmut64 0:0c31756924a2 275 * the RadioEntry parameter is provided for a specified radio.
Helmut64 0:0c31756924a2 276 */
Helmut64 0:0c31756924a2 277 RSCode GetStatistics(struct RadioStats **stats, Radio *radio = NULL);
Helmut64 0:0c31756924a2 278
Helmut64 0:0c31756924a2 279
Helmut64 0:0c31756924a2 280 /*
Helmut64 0:0c31756924a2 281 * Dump all received and sent packets
Helmut64 0:0c31756924a2 282 */
Helmut64 0:0c31756924a2 283 void EnablePacketTrace(devid_t stationID = DEV_ID_ANY, bool sents = false, bool recvs = false, Radio *radio = 0);
Helmut64 0:0c31756924a2 284
Helmut64 0:0c31756924a2 285 /*
Helmut64 0:0c31756924a2 286 * The RadioShuttle is idle when there are no ongoing jobs, etc.
Helmut64 0:0c31756924a2 287 */
Helmut64 0:0c31756924a2 288 bool Idle(void);
Helmut64 0:0c31756924a2 289
Helmut64 0:0c31756924a2 290 /*
Helmut64 0:0c31756924a2 291 * Converts a RadioShuttle error code into a string.
Helmut64 0:0c31756924a2 292 */
Helmut64 0:0c31756924a2 293 const char *StrError(RSErrorCode err);
Helmut64 0:0c31756924a2 294
Helmut64 0:0c31756924a2 295 /*
Helmut64 0:0c31756924a2 296 * Converts the radio type into a clear text name
Helmut64 0:0c31756924a2 297 */
Helmut64 0:0c31756924a2 298 const char *GetRadioName(RadioType radioType);
Helmut64 0:0c31756924a2 299
Helmut64 0:0c31756924a2 300 /*
Helmut64 0:0c31756924a2 301 * Starts the main RadioShuttle loop, returns 0 when nothing needs to be done
Helmut64 0:0c31756924a2 302 * Retuns > 0 when it should be called again
Helmut64 0:0c31756924a2 303 * RunShuttle is called on user level (non-interrupt level)
Helmut64 0:0c31756924a2 304 */
Helmut64 0:0c31756924a2 305 int RunShuttle(void);
Helmut64 0:0c31756924a2 306
Helmut64 0:0c31756924a2 307 private:
Helmut64 0:0c31756924a2 308 enum PacketStatus {
Helmut64 0:0c31756924a2 309 PS_Queued,
Helmut64 0:0c31756924a2 310 PS_Sent,
Helmut64 0:0c31756924a2 311 PS_GotSendSlot,
Helmut64 0:0c31756924a2 312 PS_WaitForConfirm,
Helmut64 0:0c31756924a2 313 PS_SendRequestCompleted,
Helmut64 0:0c31756924a2 314 PS_SendRequestConfirmed,
Helmut64 0:0c31756924a2 315 PS_SendTimeout,
Helmut64 0:0c31756924a2 316 };
Helmut64 0:0c31756924a2 317
Helmut64 0:0c31756924a2 318 struct RadioEntry; // forward decl.
Helmut64 0:0c31756924a2 319 struct ReceivedMsgEntry {
Helmut64 0:0c31756924a2 320 void *RxData;
Helmut64 0:0c31756924a2 321 int RxSize;
Helmut64 0:0c31756924a2 322 int rssi;
Helmut64 0:0c31756924a2 323 int snr;
Helmut64 0:0c31756924a2 324 struct RadioEntry *re;
Helmut64 0:0c31756924a2 325 };
Helmut64 0:0c31756924a2 326
Helmut64 0:0c31756924a2 327
Helmut64 0:0c31756924a2 328 struct RadioEntry {
Helmut64 0:0c31756924a2 329 Radio *radio;
Helmut64 0:0c31756924a2 330 RadioEvents_t radioEvents;
Helmut64 0:0c31756924a2 331 const RadioProfile *profile;
Helmut64 0:0c31756924a2 332 RadioModems_t modem;
Helmut64 0:0c31756924a2 333 volatile signed char _CADdetected;
Helmut64 0:0c31756924a2 334 uint16_t lastTxSize;
Helmut64 0:0c31756924a2 335 int lastTxPower;
Helmut64 0:0c31756924a2 336 int timeOnAir12Bytes;
Helmut64 0:0c31756924a2 337 struct ReceivedMsgEntry rxMsg;
Helmut64 0:0c31756924a2 338 struct RadioStats rStats;
Helmut64 0:0c31756924a2 339 int maxTimeOnAir;
Helmut64 0:0c31756924a2 340 int retry_ms;
Helmut64 0:0c31756924a2 341 uint32_t lastTxDone;
Helmut64 0:0c31756924a2 342 volatile bool txDoneReceived;
Helmut64 0:0c31756924a2 343 volatile const char *intrDelayedMsg;
Helmut64 0:0c31756924a2 344 uint32_t random;
Helmut64 0:0c31756924a2 345 uint32_t random2;
Helmut64 0:0c31756924a2 346 };
Helmut64 0:0c31756924a2 347
Helmut64 0:0c31756924a2 348 struct AppEntry {
Helmut64 0:0c31756924a2 349 int AppID;
Helmut64 0:0c31756924a2 350 AppRecvHandler handler;
Helmut64 0:0c31756924a2 351 int msgID;
Helmut64 0:0c31756924a2 352 void *password;
Helmut64 0:0c31756924a2 353 uint8_t pwLen;
Helmut64 0:0c31756924a2 354 bool pwdConnected;
Helmut64 0:0c31756924a2 355 };
Helmut64 0:0c31756924a2 356
Helmut64 0:0c31756924a2 357 struct ConnectEntry {
Helmut64 0:0c31756924a2 358 devid_t stationID;
Helmut64 0:0c31756924a2 359 int AppID;
Helmut64 0:0c31756924a2 360 bool authorized;
Helmut64 0:0c31756924a2 361 uint32_t random[2];
Helmut64 0:0c31756924a2 362 };
Helmut64 0:0c31756924a2 363
Helmut64 0:0c31756924a2 364 struct SendMsgEntry {
Helmut64 0:0c31756924a2 365 int AppID;
Helmut64 0:0c31756924a2 366 void *data;
Helmut64 0:0c31756924a2 367 int len;
Helmut64 0:0c31756924a2 368 int flags;
Helmut64 0:0c31756924a2 369 devid_t stationID;
Helmut64 0:0c31756924a2 370 int txPower;
Helmut64 0:0c31756924a2 371 int msgID;
Helmut64 0:0c31756924a2 372 int retryCount;
Helmut64 0:0c31756924a2 373 bool releaseData;
Helmut64 0:0c31756924a2 374 AppEntry *aep;
Helmut64 0:0c31756924a2 375 ConnectEntry *cep;
Helmut64 0:0c31756924a2 376 PacketStatus pStatus;
Helmut64 0:0c31756924a2 377 int respWindow;
Helmut64 0:0c31756924a2 378 uint32_t responseTime;
Helmut64 0:0c31756924a2 379 uint32_t lastSentTime;
Helmut64 0:0c31756924a2 380 uint32_t lastTimeOnAir;
Helmut64 0:0c31756924a2 381 uint32_t confirmTimeout;
Helmut64 0:0c31756924a2 382 int retry_ms;
Helmut64 0:0c31756924a2 383 uint8_t channel;
Helmut64 0:0c31756924a2 384 uint8_t factor;
Helmut64 0:0c31756924a2 385 uint32_t securityData[8];
Helmut64 0:0c31756924a2 386 uint32_t tmpRandom[2];
Helmut64 0:0c31756924a2 387 };
Helmut64 0:0c31756924a2 388
Helmut64 0:0c31756924a2 389 struct SignalStrengthEntry {
Helmut64 0:0c31756924a2 390 int rx_dBm;
Helmut64 0:0c31756924a2 391 devid_t stationID;
Helmut64 0:0c31756924a2 392 time_t lastUpdate;
Helmut64 0:0c31756924a2 393 int rcnCnt;
Helmut64 0:0c31756924a2 394 };
Helmut64 0:0c31756924a2 395
Helmut64 0:0c31756924a2 396 struct TimeOnAirSlotEntry {
Helmut64 0:0c31756924a2 397 devid_t stationID;
Helmut64 0:0c31756924a2 398 int AppID;
Helmut64 0:0c31756924a2 399 uint8_t channel;
Helmut64 0:0c31756924a2 400 uint8_t factor;
Helmut64 0:0c31756924a2 401 uint32_t busy_time;
Helmut64 0:0c31756924a2 402 int busy_ms;
Helmut64 0:0c31756924a2 403 };
Helmut64 0:0c31756924a2 404
Helmut64 0:0c31756924a2 405 struct EncryptionHeader {
Helmut64 0:0c31756924a2 406 uint32_t version : 3; // 3-bit encryption version
Helmut64 0:0c31756924a2 407 uint32_t dataSum : 13; // Checksum of all packet data
Helmut64 0:0c31756924a2 408 uint16_t msgSize : 11; // Same as in RadioHeader
Helmut64 0:0c31756924a2 409 uint16_t msgID : 5; // Same as in RadioHeader
Helmut64 0:0c31756924a2 410 uint32_t random;
Helmut64 0:0c31756924a2 411 };
Helmut64 0:0c31756924a2 412
Helmut64 0:0c31756924a2 413 enum RadioHeaderVersions {
Helmut64 0:0c31756924a2 414 RSMagic = 0b1011,
Helmut64 0:0c31756924a2 415 RSHeaderFully_v1 = 0b001,
Helmut64 0:0c31756924a2 416 RSHeaderPacked_v1 = 0b010,
Helmut64 0:0c31756924a2 417 RSHeaderFullySize_v1 = 16,
Helmut64 0:0c31756924a2 418 RSHeaderPackedSize_v1 = 12,
Helmut64 0:0c31756924a2 419 msgIDv1Mask = 0b11111,
Helmut64 0:0c31756924a2 420 Packedv1MaxApps = (1<<11)-1,
Helmut64 0:0c31756924a2 421 Packedv1MaxRespWindow = (1<<11)-1,
Helmut64 0:0c31756924a2 422 Fullyv1MaxRespWindow = (1<<16)-1,
Helmut64 0:0c31756924a2 423 Packedv1MaxDeviceID = (1<<21)-1,
Helmut64 0:0c31756924a2 424 MaxWinScale = (1<<4)-1,
Helmut64 0:0c31756924a2 425 DataSumBits = 13,
Helmut64 0:0c31756924a2 426 };
Helmut64 0:0c31756924a2 427
Helmut64 0:0c31756924a2 428 /*
Helmut64 0:0c31756924a2 429 * The RadioShuttle communication header (similar to UDP),
Helmut64 0:0c31756924a2 430 * but optimized for radios.
Helmut64 0:0c31756924a2 431 * A packet crc checksum is done on the link layer, no field needed here
Helmut64 0:0c31756924a2 432 * The source always sends this request to the other side
Helmut64 0:0c31756924a2 433 * - Check immediately for a response after sending
Helmut64 0:0c31756924a2 434 * - Check again for a response in responseWindow*2 milliseconds
Helmut64 0:0c31756924a2 435 *
Helmut64 0:0c31756924a2 436 */
Helmut64 0:0c31756924a2 437 struct RadioHeader {
Helmut64 0:0c31756924a2 438 // 4 bytes
Helmut64 0:0c31756924a2 439 uint16_t magic : 4; // 4-bit magic,
Helmut64 0:0c31756924a2 440 uint16_t version : 3; // 3-bit version
Helmut64 0:0c31756924a2 441 uint16_t msgFlags: 9; // e.g.: Request/Response NeedsConfirm, Priority, Encrypted
Helmut64 0:0c31756924a2 442 union {
Helmut64 0:0c31756924a2 443 struct {
Helmut64 0:0c31756924a2 444 uint16_t msgSize : 11; // 11-bit message size allows a maximum of 2048 bytes
Helmut64 0:0c31756924a2 445 uint16_t msgID : 5; // ID for the app communication, truncated to 5-bit
Helmut64 0:0c31756924a2 446 } data;
Helmut64 0:0c31756924a2 447 struct {
Helmut64 0:0c31756924a2 448 uint16_t channel : 4; // Specify the channel to switch to for this transaction
Helmut64 0:0c31756924a2 449 uint16_t factor : 3; // Specifies the spreading factor index (6-12)
Helmut64 0:0c31756924a2 450 uint16_t winScale: 4; // Set the window scaling factor
Helmut64 0:0c31756924a2 451 } option;
Helmut64 0:0c31756924a2 452 } s;
Helmut64 0:0c31756924a2 453 union {
Helmut64 0:0c31756924a2 454 struct { // 8 bytes
Helmut64 0:0c31756924a2 455 uint32_t appID : 11; // First 2048 application identifiers for the request
Helmut64 0:0c31756924a2 456 devid_t destination : 21; // Device ID of the destination 2^11 first 2 million devices
Helmut64 0:0c31756924a2 457 uint32_t respWindow : 11; // Wait for the respWindow (ms) max 2048 ms before sending data.
Helmut64 0:0c31756924a2 458 devid_t source : 21; // Device ID of the destination 2^11 first 2 million devices
Helmut64 0:0c31756924a2 459 } packedv1;
Helmut64 0:0c31756924a2 460 struct { // 12 bytes
Helmut64 0:0c31756924a2 461 uint16_t appID; // Application identifier for the request
Helmut64 0:0c31756924a2 462 uint16_t respWindow; // We listen for a 2nd resonse in responseWindow (ms)
Helmut64 0:0c31756924a2 463 devid_t destination; // Device ID of the destination
Helmut64 0:0c31756924a2 464 devid_t source; // DeviceID of the source
Helmut64 0:0c31756924a2 465 } fullyv1;
Helmut64 0:0c31756924a2 466 } u;
Helmut64 0:0c31756924a2 467 };
Helmut64 0:0c31756924a2 468
Helmut64 0:0c31756924a2 469 struct WireDumpSettings {
Helmut64 0:0c31756924a2 470 devid_t stationID;
Helmut64 0:0c31756924a2 471 bool sents;
Helmut64 0:0c31756924a2 472 bool recvs;
Helmut64 0:0c31756924a2 473 Radio *radio;
Helmut64 0:0c31756924a2 474 };
Helmut64 0:0c31756924a2 475
Helmut64 0:0c31756924a2 476 /*
Helmut64 0:0c31756924a2 477 * Radio specific callbacks are public to allow C wrapper function to call us.
Helmut64 0:0c31756924a2 478 */
Helmut64 0:0c31756924a2 479 public:
Helmut64 0:0c31756924a2 480 void RS_TxDone(Radio *radio, void *userData);
Helmut64 0:0c31756924a2 481 void RS_RxDone(Radio *radio, void *userData, uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr);
Helmut64 0:0c31756924a2 482 void RS_TxTimeout(Radio *radio, void *userData);
Helmut64 0:0c31756924a2 483 void RS_RxTimeout(Radio *radio, void *userData);
Helmut64 0:0c31756924a2 484 void RS_RxError(Radio *radio, void *userData);
Helmut64 0:0c31756924a2 485 void RS_CadDone(Radio *radio, void *userData, bool channelActivityDetected);
Helmut64 0:0c31756924a2 486
Helmut64 0:0c31756924a2 487 private:
Helmut64 0:0c31756924a2 488 /*
Helmut64 0:0c31756924a2 489 * The CadDetection will turn the radio into a Cad listening mode
Helmut64 0:0c31756924a2 490 * to detect radio-modulated signals on the channel.
Helmut64 0:0c31756924a2 491 * This takes a few ms (at SF7) and the interrupt RS_CadDone will report
Helmut64 0:0c31756924a2 492 * the status.
Helmut64 0:0c31756924a2 493 * The radio->_CADdetected contains the result (0 for idle, 1 for busy)
Helmut64 0:0c31756924a2 494 */
Helmut64 0:0c31756924a2 495 bool CadDetection(RadioEntry *re);
Helmut64 0:0c31756924a2 496
Helmut64 0:0c31756924a2 497 /*
Helmut64 0:0c31756924a2 498 * init the RX/TX of the Radio.
Helmut64 0:0c31756924a2 499 */
Helmut64 0:0c31756924a2 500 RSCode _initRadio(RadioEntry *re);
Helmut64 0:0c31756924a2 501
Helmut64 0:0c31756924a2 502 /*
Helmut64 0:0c31756924a2 503 * The processing function returns a status code if it has been able to process
Helmut64 0:0c31756924a2 504 * this message. true' for messages processed, false for messages skipped.
Helmut64 0:0c31756924a2 505 */
Helmut64 0:0c31756924a2 506 bool ProcessResponseMessage(ReceivedMsgEntry *rme, AppEntry *aep, SendMsgEntry *mep, int msgFlags, void *data, int len, devid_t source, devid_t respWindow, uint8_t channel, uint8_t factor);
Helmut64 0:0c31756924a2 507
Helmut64 0:0c31756924a2 508 bool ProcessRequestMessage(ReceivedMsgEntry *rme, AppEntry *aep, int msgFlags, void *data, int len, int msgID, devid_t source, uint32_t respWindow, uint8_t channel, uint8_t factor);
Helmut64 0:0c31756924a2 509
Helmut64 0:0c31756924a2 510 void MessageSecurityError(ReceivedMsgEntry *rme, AppEntry *aep, int msgID, devid_t source, uint8_t channel, uint8_t factor);
Helmut64 0:0c31756924a2 511
Helmut64 0:0c31756924a2 512 void SaveTimeOnAirSlot(devid_t destination, int AppID, int msgFlags, int respWindow, uint8_t channel, uint8_t factor, int timeOnAir);
Helmut64 0:0c31756924a2 513
Helmut64 0:0c31756924a2 514 /*
Helmut64 0:0c31756924a2 515 * Our main send function is responsible for header packing,
Helmut64 0:0c31756924a2 516 * compression and encryption, and finally sends a packet via the radio.
Helmut64 0:0c31756924a2 517 * It returns true if we have been able to sent the message.
Helmut64 0:0c31756924a2 518 */
Helmut64 0:0c31756924a2 519 bool SendMessage(RadioEntry *re, void *data, int len, int msgID, int AppID, devid_t stationID, int flags, int txPower, int respWindow, uint8_t channel, uint8_t factor);
Helmut64 0:0c31756924a2 520
Helmut64 0:0c31756924a2 521 /*
Helmut64 0:0c31756924a2 522 * We keep a little cache list of the power needed for different stations
Helmut64 0:0c31756924a2 523 * This saves a lot of energy and reduces signal strength to keep the network
Helmut64 0:0c31756924a2 524 * less busy. For example, other radio networks need not receive our signals.
Helmut64 0:0c31756924a2 525 */
Helmut64 0:0c31756924a2 526 int CalculateTXPower(RadioEntry *re, devid_t stationID);
Helmut64 0:0c31756924a2 527 bool UpdateSignalStrength(devid_t stationID, int dBm);
Helmut64 0:0c31756924a2 528 bool DeleteSignalStrength(devid_t stationID);
Helmut64 0:0c31756924a2 529
Helmut64 0:0c31756924a2 530
Helmut64 0:0c31756924a2 531 /*
Helmut64 0:0c31756924a2 532 * Our main receive function is responsible for header unpacking,
Helmut64 0:0c31756924a2 533 * de-compression and decryption, and finally provides the unpacked data.
Helmut64 0:0c31756924a2 534 * It returns true if we have been able to detect and unpack the message.
Helmut64 0:0c31756924a2 535 */
Helmut64 0:0c31756924a2 536 bool ReceiveMessage(ReceivedMsgEntry *rme, void **data, int &len, int &msgID, int &AppID, int &flags, devid_t &destination, devid_t &source, int &respWindow, uint8_t &channel, uint8_t &factor);
Helmut64 0:0c31756924a2 537
Helmut64 0:0c31756924a2 538 /*
Helmut64 0:0c31756924a2 539 * We need to process all input messages, the _recv list should be empty ASAP
Helmut64 0:0c31756924a2 540 * because the data is only temporarily available until the next packet.
Helmut64 0:0c31756924a2 541 */
Helmut64 0:0c31756924a2 542 void ProcessReceivedMessages(void);
Helmut64 0:0c31756924a2 543
Helmut64 0:0c31756924a2 544
Helmut64 0:0c31756924a2 545 void PacketTrace(RadioEntry *re, const char *name, RadioHeader *rh, void *data, int len, bool sent, ReceivedMsgEntry *rme);
Helmut64 0:0c31756924a2 546
Helmut64 0:0c31756924a2 547 /*
Helmut64 0:0c31756924a2 548 * A dummy function which is called for every timeout, the timer wakes up
Helmut64 0:0c31756924a2 549 * the sleep and therefore the RunShuttle starts processing.
Helmut64 0:0c31756924a2 550 */
Helmut64 0:0c31756924a2 551 void TimeoutFunc(void);
Helmut64 0:0c31756924a2 552
Helmut64 0:0c31756924a2 553 uint32_t GetDataSum(int maxbits, void *data, int len);
Helmut64 0:0c31756924a2 554
Helmut64 0:0c31756924a2 555
Helmut64 0:0c31756924a2 556 private:
Helmut64 0:0c31756924a2 557 const char *_name;
Helmut64 0:0c31756924a2 558 devid_t _deviceID;
Helmut64 0:0c31756924a2 559 devid_t _tmpdeviceID;
Helmut64 0:0c31756924a2 560 uint8_t _uuid[16];
Helmut64 0:0c31756924a2 561 RadioType _radioType;
Helmut64 0:0c31756924a2 562 int _maxMTUSize;
Helmut64 0:0c31756924a2 563 list<RadioEntry> _radios;
Helmut64 0:0c31756924a2 564 map<int, AppEntry> _apps;
Helmut64 0:0c31756924a2 565 map<std::pair<devid_t,int>, ConnectEntry> _connections;
Helmut64 0:0c31756924a2 566 list<SendMsgEntry> _sends;
Helmut64 0:0c31756924a2 567 list<ReceivedMsgEntry> _recvs;
Helmut64 0:0c31756924a2 568 map<devid_t, SignalStrengthEntry> _signals;
Helmut64 0:0c31756924a2 569 list<TimeOnAirSlotEntry> _airtimes;
Helmut64 0:0c31756924a2 570 MyTimeout *timer;
Helmut64 0:0c31756924a2 571 MyTimer *ticker;
Helmut64 0:0c31756924a2 572 volatile uint32_t prevWakeup;
Helmut64 0:0c31756924a2 573 int SetTimerCount;
Helmut64 0:0c31756924a2 574
Helmut64 0:0c31756924a2 575 static const RadioProfile defaultProfile[];
Helmut64 0:0c31756924a2 576 volatile bool busyInShuttle;
Helmut64 0:0c31756924a2 577 WireDumpSettings _wireDumpSettings;
Helmut64 0:0c31756924a2 578 const static int MAX_SENT_RETRIES = 3; // Defines the number of retries of sents (with confirm)
Helmut64 0:0c31756924a2 579 const static int RX_TIMEOUT_1HOUR = 3600000;
Helmut64 0:0c31756924a2 580 RadioStatusInterface *_statusIntf;
Helmut64 0:0c31756924a2 581 RadioSecurityInterface *_securityIntf;
Helmut64 0:0c31756924a2 582 uint32_t _;
Helmut64 0:0c31756924a2 583 };
Helmut64 0:0c31756924a2 584
Helmut64 0:0c31756924a2 585 #endif // __RADIOSHUTTLE_H__
Helmut64 0:0c31756924a2 586 #endif // FEATURE_LORA