temp sync broken
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -217,7 +217,7 @@ s32 getVoltage(void)
|
||||
u16 ADC_val;
|
||||
s32 val_mv;
|
||||
|
||||
ADC_val = Get_ADC_Average( ADC_Channel_0, 10 );
|
||||
ADC_val = Get_ADC_Average( ADC_Channel_1, 10 );
|
||||
|
||||
ADC_val = Get_ConversionVal(ADC_val);
|
||||
|
||||
|
||||
@@ -3,16 +3,17 @@
|
||||
static const char b64_enc_table[] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
void base64_encode(const uint8_t *in, size_t ilen, char *out)
|
||||
{
|
||||
void base64_encode (const uint8_t *in, size_t ilen, char *out) {
|
||||
size_t out_len = 0;
|
||||
for (size_t i = 0; i < ilen; i += 3) {
|
||||
uint32_t triple = 0;
|
||||
int remain = ilen - i;
|
||||
|
||||
triple |= in[i] << 16;
|
||||
if (remain > 1) triple |= in[i + 1] << 8;
|
||||
if (remain > 2) triple |= in[i + 2];
|
||||
if (remain > 1)
|
||||
triple |= in[i + 1] << 8;
|
||||
if (remain > 2)
|
||||
triple |= in[i + 2];
|
||||
|
||||
out[out_len++] = b64_enc_table[(triple >> 18) & 0x3F];
|
||||
out[out_len++] = b64_enc_table[(triple >> 12) & 0x3F];
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void base64_encode(const uint8_t *in, size_t ilen, char *out);
|
||||
void base64_encode (const uint8_t *in, size_t ilen, char *out);
|
||||
|
||||
#endif
|
||||
@@ -1,17 +1,30 @@
|
||||
#include "config.h"
|
||||
#include "ch32v30x_flash.h"
|
||||
#include "ch32v30x_rng.h"
|
||||
#include "lib/cifra/sha2.h"
|
||||
#include "lib/ed25519/ed_25519.h"
|
||||
#include "sx1262.h"
|
||||
#include "util/hexdump.h"
|
||||
#include "util/log.h"
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
PersistentData_t persistent;
|
||||
|
||||
LoRaSettings currentLoRaSettings;
|
||||
|
||||
#define TAG "Config"
|
||||
|
||||
NodeEntry * getNextNode() {
|
||||
NodeEntry *getNextNode() {
|
||||
uint32_t oldest_timestamp = UINT32_MAX;
|
||||
NodeEntry *selectedNode = &(persistent.contacts[0]);
|
||||
for (int i = 0; i < CONTACT_COUNT; i++) {
|
||||
NodeEntry *curNode = &(persistent.contacts[i]);
|
||||
if (curNode->flags & NODE_ENTRY_FAV_FLAG) {
|
||||
continue;
|
||||
}
|
||||
if (curNode->last_seen_lt == 0) {
|
||||
selectedNode = curNode;
|
||||
break;
|
||||
}
|
||||
if (curNode->last_seen_lt < oldest_timestamp) {
|
||||
@@ -22,7 +35,7 @@ NodeEntry * getNextNode() {
|
||||
return selectedNode;
|
||||
}
|
||||
|
||||
NodeEntry * getNode(uint8_t hash) {
|
||||
NodeEntry *getNode (uint8_t hash) {
|
||||
NodeEntry *selectedNode = NULL;
|
||||
for (int i = 0; i < CONTACT_COUNT; i++) {
|
||||
NodeEntry *curNode = &(persistent.contacts[i]);
|
||||
@@ -34,34 +47,111 @@ NodeEntry * getNode(uint8_t hash) {
|
||||
return selectedNode;
|
||||
}
|
||||
|
||||
NodeEntry *getNodePrefix (const uint8_t *hash) {
|
||||
NodeEntry *selectedNode = NULL;
|
||||
for (int i = 0; i < CONTACT_COUNT; i++) {
|
||||
NodeEntry *curNode = &(persistent.contacts[i]);
|
||||
if (memcmp (curNode->pubKey, hash, 4)) {
|
||||
selectedNode = curNode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return selectedNode;
|
||||
}
|
||||
|
||||
Channel *getChannel (uint8_t hash, uint8_t ignoreCount) {
|
||||
Channel *selectedChannel = NULL;
|
||||
Channel *finalChannel = NULL;
|
||||
uint8_t matchCount = 0;
|
||||
for (int i = 0; i < ChannelCount; i++) {
|
||||
Channel *curChannel = &(persistent.channels[i]);
|
||||
if (curChannel->hash == hash) {
|
||||
selectedChannel = curChannel;
|
||||
if (++matchCount > ignoreCount) {
|
||||
finalChannel = selectedChannel;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return finalChannel;
|
||||
}
|
||||
|
||||
void addChannel (char *name, const uint8_t *key) {
|
||||
|
||||
uint32_t oldest_timestamp = UINT32_MAX;
|
||||
Channel *selectedChannel = &(persistent.channels[0]);
|
||||
for (int i = 0; i < ChannelCount; i++) {
|
||||
Channel *curChan = &(persistent.channels[i]);
|
||||
|
||||
if (curChan->timestamp == 0) {
|
||||
selectedChannel = curChan;
|
||||
MESH_LOGD (TAG, "Deciding on channel index %d because of timestamp 0, name is %s", i, name);
|
||||
break;
|
||||
}
|
||||
if (strlen (curChan->name) == 0) {
|
||||
selectedChannel = curChan;
|
||||
MESH_LOGD (TAG, "Deciding on channel index %d because of name len 0, name is %s", i, name);
|
||||
break;
|
||||
}
|
||||
|
||||
if (curChan->timestamp < oldest_timestamp) {
|
||||
oldest_timestamp = curChan->timestamp;
|
||||
selectedChannel = curChan;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
memset (selectedChannel->name, 0, sizeof (selectedChannel->name));
|
||||
strncpy (selectedChannel->name, name, sizeof (selectedChannel->name));
|
||||
memcpy (selectedChannel->key, key, sizeof (selectedChannel->key));
|
||||
// Buffer for the digest
|
||||
uint8_t hash[CF_SHA256_HASHSZ];
|
||||
|
||||
// Context
|
||||
cf_sha256_context ctx;
|
||||
|
||||
// 1. Initialize
|
||||
cf_sha256_init (&ctx);
|
||||
|
||||
// 2. Feed in your data
|
||||
cf_sha256_update (&ctx, selectedChannel->key, sizeof (selectedChannel->key));
|
||||
|
||||
// 3. Compute digest
|
||||
cf_sha256_digest (&ctx, hash);
|
||||
selectedChannel->hash = hash[0];
|
||||
selectedChannel->timestamp = RTC_GetCounter();
|
||||
}
|
||||
|
||||
void printNodeDB() {
|
||||
printf("Node database:\n");
|
||||
printf ("Node database:\n");
|
||||
for (int i = 0; i < CONTACT_COUNT; i++) {
|
||||
const NodeEntry *node = &(persistent.contacts[i]);
|
||||
if (node->last_seen_lt == 0) continue; // skip inactive nodes
|
||||
if (node->last_seen_lt == 0)
|
||||
continue; // skip inactive nodes
|
||||
|
||||
printf("Node %d:\n", i);
|
||||
printf(" Name: %s\n", node->name);
|
||||
hexdump("Pubkey", node->pubKey, sizeof(node->pubKey));
|
||||
hexdump("Secret", node->secret, sizeof(node->secret));
|
||||
printf("\n");
|
||||
printf ("Node %d:\n", i);
|
||||
printf (" Name: %s\n", node->name);
|
||||
hexdump ("Pubkey", node->pubKey, sizeof (node->pubKey));
|
||||
hexdump ("Secret", node->secret, sizeof (node->secret));
|
||||
printf ("\n");
|
||||
|
||||
printf(" GPS: lat=%d, lon=%d\n", node->gps_latitude, node->gps_longitude);
|
||||
printf(" Path: ... (not expanded, add if needed)\n");
|
||||
printf(" Flags: 0x%02X\n", node->flags);
|
||||
printf(" Type: 0x%02X\n", node->type);
|
||||
printf(" Authenticated: %s\n", node->authenticated ? "Yes" : "No");
|
||||
printf(" Last Seen (remote ts): %d\n", node->last_seen_rt);
|
||||
printf(" Last Seen (local ts): %d\n", node->last_seen_lt);
|
||||
printf(" Sync timestamp: %d\n", node->sync_timestamp);
|
||||
printf("--------------------------------------\n");
|
||||
printf (" GPS: lat=%d, lon=%d\n", node->gps_latitude, node->gps_longitude);
|
||||
printf (" Path: ... (not expanded, add if needed)\n");
|
||||
printf (" Flags: 0x%02X\n", node->flags);
|
||||
printf (" Type: 0x%02X\n", node->type);
|
||||
printf (" Authenticated: %s\n", node->authenticated ? "Yes" : "No");
|
||||
printf (" Last Seen (remote ts): %d\n", node->last_seen_rt);
|
||||
printf (" Last Seen (local ts): %d\n", node->last_seen_lt);
|
||||
printf (" Sync timestamp: %d\n", node->sync_timestamp);
|
||||
printf ("--------------------------------------\n");
|
||||
}
|
||||
}
|
||||
|
||||
void loadConfig() {
|
||||
memcpy (&persistent, FLASH_USER_PAGE_ADDR, sizeof (persistent));
|
||||
memcpy(¤tLoRaSettings, &(persistent.loraSettings), sizeof(currentLoRaSettings));
|
||||
uint32_t crcSum = *((uint32_t *)(((uint8_t *)&persistent) + (sizeof (persistent) - 2)));
|
||||
memset ((((uint8_t *)&persistent) + (sizeof (persistent) - sizeof(crcSum))), 0, 4);
|
||||
memset ((((uint8_t *)&persistent) + (sizeof (persistent) - sizeof (crcSum))), 0, 4);
|
||||
CRC_ResetDR();
|
||||
uint32_t currentSum = CRC_CalcBlockCRC ((uint32_t *)&persistent, sizeof (persistent) - 2);
|
||||
|
||||
@@ -73,9 +163,112 @@ void loadConfig() {
|
||||
void saveConfig() {
|
||||
CRC_ResetDR();
|
||||
uint32_t currentSum = CRC_CalcBlockCRC ((uint32_t *)&persistent, sizeof (persistent) - 2);
|
||||
memcpy ((((uint8_t *)&persistent) + (sizeof (persistent) - sizeof(currentSum))), (uint8_t *)currentSum, 4);
|
||||
memcpy ((((uint8_t *)&persistent) + (sizeof (persistent) - sizeof (currentSum))), (uint8_t *)currentSum, 4);
|
||||
FLASH_Unlock();
|
||||
FLASH_ErasePage_Fast (1919);
|
||||
FLASH_ProgramPage_Fast (1919, (uint32_t *)&persistent);
|
||||
FLASH_Lock();
|
||||
}
|
||||
|
||||
void genSeed (uint8_t *seedOut) {
|
||||
RCC_AHBPeriphClockCmd (RCC_AHBPeriph_RNG, ENABLE);
|
||||
RNG_Cmd (ENABLE);
|
||||
uint32_t random;
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
while (RNG_GetFlagStatus (RNG_FLAG_DRDY) == RESET) {
|
||||
vTaskDelay (10);
|
||||
}
|
||||
random = RNG_GetRandomNumber();
|
||||
|
||||
memcpy (&(seedOut[i * 4]), &random, sizeof (random));
|
||||
}
|
||||
RCC_AHBPeriphClockCmd (RCC_AHBPeriph_RNG, DISABLE);
|
||||
RNG_Cmd (DISABLE);
|
||||
}
|
||||
|
||||
const uint8_t publicChannelPSK[16] = {0x8b, 0x33, 0x87, 0xe9, 0xc5, 0xcd, 0xea, 0x6a, 0xc9, 0xe5, 0xed, 0xba, 0xa1, 0x15, 0xcd, 0x72};
|
||||
const uint8_t BRNTestChannelPSK[16] = {0x44, 0x81, 0xda, 0x0e, 0x4e, 0x03, 0xc4, 0x9e, 0x84, 0x77, 0x25, 0xd8, 0x3a, 0x93, 0xbf, 0x80};
|
||||
|
||||
const char *getStringRole (uint8_t role) {
|
||||
switch (role) {
|
||||
case NODE_TYPE_CHAT_NODE:
|
||||
return "Chat node";
|
||||
|
||||
case NODE_TYPE_REPEATER:
|
||||
return "Repeater";
|
||||
|
||||
case NODE_TYPE_ROOM_SERVER:
|
||||
return "Room server";
|
||||
|
||||
case NODE_TYPE_SENSOR:
|
||||
return "Sensor";
|
||||
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
void populateDefaults() {
|
||||
|
||||
uint8_t seed[32];
|
||||
// memcpy(seed, "vFt0FRugSOeqnkshImMCVfgHM5vBxz4", 32); //chat node identity
|
||||
memcpy (seed, "vFt0FRugSOeqnkshImMCVfgHM5vBxz3", 32); // repeater identity
|
||||
// genSeed(seed); //random identity
|
||||
|
||||
ed25519_create_keypair (persistent.pubkey, persistent.privkey, seed);
|
||||
|
||||
|
||||
// persistent.nodeType = NODE_TYPE_CHAT_NODE;
|
||||
persistent.nodeType = NODE_TYPE_REPEATER;
|
||||
memset (persistent.password, 0, sizeof (persistent.password));
|
||||
strcpy (persistent.password, "hesielko");
|
||||
strcpy (persistent.nodeName, "BRN RiscVpeater");
|
||||
|
||||
persistent.adcMultiplier = 0;
|
||||
|
||||
persistent.loraSettings.txPowerInDbm = 20;
|
||||
persistent.loraSettings.frequencyInHz = 869554000;
|
||||
persistent.loraSettings.spreadingFactor = 8;
|
||||
persistent.loraSettings.bandwidth = SX126X_LORA_BW_62_5;
|
||||
persistent.loraSettings.codingRate = SX126X_LORA_CR_4_8;
|
||||
persistent.loraSettings.preambleLength = 16;
|
||||
persistent.loraSettings.tcxoVoltage = 2.2; // ebyte
|
||||
// persistent.tcxoVoltage = 1.8; // heltec
|
||||
|
||||
memcpy(¤tLoRaSettings, &(persistent.loraSettings), sizeof(currentLoRaSettings));
|
||||
|
||||
addChannel ("Public", publicChannelPSK);
|
||||
addChannel ("BRNTest", BRNTestChannelPSK);
|
||||
|
||||
persistent.doRepeat = 1;
|
||||
persistent.allowReadOnly = 1;
|
||||
|
||||
|
||||
persistent.latitude = 48190900;
|
||||
persistent.longitude = 17030300;
|
||||
persistent.altitude = 23400;
|
||||
}
|
||||
|
||||
void LoraApply() {
|
||||
|
||||
MESH_LOGW (TAG, "LoraInit");
|
||||
LoRaInit();
|
||||
|
||||
|
||||
char useRegulatorLDO = 0;
|
||||
|
||||
LoRaDebugPrint (0);
|
||||
uint16_t loraBeginStat = LoRaBegin (currentLoRaSettings.frequencyInHz, currentLoRaSettings.txPowerInDbm, currentLoRaSettings.tcxoVoltage, useRegulatorLDO);
|
||||
if (loraBeginStat != 0) {
|
||||
MESH_LOGE (TAG, "Does not recognize the module");
|
||||
while (1) {
|
||||
vTaskDelay (pdMS_TO_TICKS (1000));
|
||||
MESH_LOGE (TAG, "CRITICAL: LoRa not found, halted");
|
||||
}
|
||||
}
|
||||
|
||||
char crcOn = 1;
|
||||
char invertIrq = 0;
|
||||
|
||||
LoRaConfig (currentLoRaSettings.spreadingFactor, currentLoRaSettings.bandwidth, currentLoRaSettings.codingRate, currentLoRaSettings.preambleLength, 0, crcOn, invertIrq);
|
||||
}
|
||||
@@ -6,18 +6,14 @@
|
||||
|
||||
#define FLASH_USER_PAGE_ADDR ((const void *)(0x08077F00))
|
||||
|
||||
#define AESKeyCount 8
|
||||
#define ChannelCount 8
|
||||
#define CONTACT_COUNT 100
|
||||
|
||||
typedef struct {
|
||||
uint32_t magic; // e.g. 0xDEADBEEF
|
||||
uint8_t privkey[32]; // Ed25519 private
|
||||
uint8_t pubkey[32]; // Ed25519 public
|
||||
uint8_t nodeType;
|
||||
int32_t latitude;
|
||||
int32_t longitude;
|
||||
int32_t altitude;
|
||||
|
||||
#define VERSION "v0.0.1 - BRN Systems RISC-V"
|
||||
|
||||
#define BOARD "WCH CH32V307"
|
||||
|
||||
typedef struct LoRaSettings {
|
||||
int8_t txPowerInDbm;
|
||||
uint32_t frequencyInHz;
|
||||
uint8_t spreadingFactor;
|
||||
@@ -25,11 +21,35 @@ typedef struct {
|
||||
uint8_t codingRate;
|
||||
uint16_t preambleLength;
|
||||
float tcxoVoltage;
|
||||
} LoRaSettings;
|
||||
|
||||
uint8_t aesKeys[AESKeyCount][17];
|
||||
uint8_t password[16];
|
||||
extern LoRaSettings currentLoRaSettings;
|
||||
|
||||
typedef struct {
|
||||
uint32_t magic; // e.g. 0xDEADBEEF
|
||||
|
||||
uint8_t privkey[32]; // Ed25519 private
|
||||
uint8_t pubkey[32]; // Ed25519 public
|
||||
|
||||
uint8_t nodeType;
|
||||
char nodeName[32];
|
||||
|
||||
int32_t latitude;
|
||||
int32_t longitude;
|
||||
int32_t altitude;
|
||||
|
||||
LoRaSettings loraSettings;
|
||||
|
||||
Channel channels[ChannelCount];
|
||||
NodeEntry contacts[CONTACT_COUNT];
|
||||
|
||||
uint8_t password[16];
|
||||
uint8_t guestPassword[16];
|
||||
|
||||
uint8_t doRepeat;
|
||||
uint8_t allowReadOnly;
|
||||
float adcMultiplier;
|
||||
float airtimeFactor;
|
||||
uint32_t crc32; // integrity check
|
||||
} PersistentData_t;
|
||||
|
||||
@@ -40,7 +60,20 @@ void loadConfig();
|
||||
|
||||
void printNodeDB();
|
||||
|
||||
NodeEntry * getNextNode();
|
||||
NodeEntry *getNextNode();
|
||||
|
||||
NodeEntry *getNode (uint8_t hash);
|
||||
|
||||
Channel *getChannel (uint8_t hash, uint8_t ignoreCount);
|
||||
|
||||
void addChannel (char *name, const uint8_t *key);
|
||||
|
||||
NodeEntry *getNodePrefix (const uint8_t *hash);
|
||||
|
||||
const char *getStringRole (uint8_t role);
|
||||
|
||||
void populateDefaults();
|
||||
|
||||
void LoraApply();
|
||||
|
||||
NodeEntry * getNode(uint8_t hash);
|
||||
#endif
|
||||
106
User/main.c
106
User/main.c
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "ch32v30x_rng.h"
|
||||
#include "meshcore/meshframing.h"
|
||||
#include "meshcore/packets/advert.h"
|
||||
#include "meshcore/packets/control.h"
|
||||
@@ -82,49 +83,6 @@ TaskHandle_t Task2Task_Handler;
|
||||
// uint8_t bufIn[260];
|
||||
|
||||
void task2_task (void *pvParameters) {
|
||||
MESH_LOGD (TAG, "Task2 boot0");
|
||||
RTC_Init();
|
||||
startupTime = RTC_GetCounter();
|
||||
memset (&stats, 0, sizeof (stats));
|
||||
MESH_LOGD (TAG, "Task2 boot1");
|
||||
|
||||
ADC_Function_Init();
|
||||
MESH_LOGD (TAG, "Task2 boot2");
|
||||
// ed25519_create_keypair (persistent.pubkey, persistent.privkey, "vFt0FRugSOeqnkshImMCVfgHM5vBxz4");
|
||||
ed25519_create_keypair (persistent.pubkey, persistent.privkey, "vFt0FRugSOeqnkshImMCVfgHM5vBxz3");
|
||||
MESH_LOGD (TAG, "Task2 boot3");
|
||||
// persistent.nodeType = NODE_TYPE_CHAT_NODE;
|
||||
persistent.nodeType = NODE_TYPE_REPEATER;
|
||||
memset (persistent.password, 0, sizeof (persistent.password));
|
||||
strcpy (persistent.password, "hesielko");
|
||||
strcpy (persistent.nodeName, "BRN RiscVpeater");
|
||||
|
||||
const uint8_t aesKeysDefault[AESKeyCount][17] = {
|
||||
{0x11, 0x8b, 0x33, 0x87, 0xe9, 0xc5,
|
||||
0xcd, 0xea, 0x6a, 0xc9, 0xe5, 0xed,
|
||||
0xba, 0xa1, 0x15, 0xcd, 0x72},
|
||||
|
||||
{0x0a, 0x44, 0x81, 0xda, 0x0e, 0x4e,
|
||||
0x03, 0xc4, 0x9e, 0x84, 0x77, 0x25,
|
||||
0xd8, 0x3a, 0x93, 0xbf, 0x80}
|
||||
};
|
||||
|
||||
memcpy (persistent.aesKeys, aesKeysDefault, sizeof (persistent.aesKeys));
|
||||
|
||||
// sendAdvert();
|
||||
|
||||
DiscoverRequestPayload discReq;
|
||||
discReq.prefixOnly = 0;
|
||||
discReq.since = 0;
|
||||
discReq.tag = RTC_GetCounter();
|
||||
discReq.typeFilter = 0xFF;
|
||||
sendDiscoverRequest (&discReq);
|
||||
|
||||
persistent.latitude = 48190900;
|
||||
persistent.longitude = 17030300;
|
||||
persistent.altitude = 23400;
|
||||
|
||||
|
||||
char x;
|
||||
MESH_LOGD (TAG, "Task2 boot");
|
||||
while (1) {
|
||||
@@ -156,6 +114,19 @@ void task2_task (void *pvParameters) {
|
||||
printf ("Sending a direct message to the first node\n");
|
||||
sendEncryptedTextMessage (&(persistent.contacts[0]), &plainTextMessage);
|
||||
}
|
||||
if (x == 'C') {
|
||||
for (uint8_t i = 0; i < ChannelCount; i++) {
|
||||
Channel *channel = &(persistent.channels[i]);
|
||||
if (strlen (channel->name) == 0) {
|
||||
continue;
|
||||
}
|
||||
if (channel->timestamp == 0) {
|
||||
continue;
|
||||
}
|
||||
printf ("Channel index %d, named %s, timestamp is %d, hash is %d\n", i, channel->name, channel->timestamp, channel->hash);
|
||||
hexdump ("Pubkey", channel->key, sizeof (channel->key));
|
||||
}
|
||||
}
|
||||
}
|
||||
vTaskDelay (pdMS_TO_TICKS (2000));
|
||||
}
|
||||
@@ -163,40 +134,27 @@ void task2_task (void *pvParameters) {
|
||||
|
||||
void task1_task (void *pvParameters) {
|
||||
// loadConfig();
|
||||
populateDefaults();
|
||||
|
||||
LoraApply();
|
||||
|
||||
const int64_t interval_ms = 10; // 10 ms
|
||||
int64_t start_time, end_time, elapsed;
|
||||
|
||||
MESH_LOGW (TAG, "LoraInit");
|
||||
LoRaInit();
|
||||
int8_t txPowerInDbm = 20;
|
||||
uint32_t frequencyInHz = 869554000;
|
||||
uint8_t spreadingFactor = 8;
|
||||
uint8_t bandwidth = SX126X_LORA_BW_62_5;
|
||||
uint8_t codingRate = SX126X_LORA_CR_4_8;
|
||||
uint16_t preambleLength = 16;
|
||||
float tcxoVoltage = 2.2; // ebyte
|
||||
// float tcxoVoltage = 1.8; // heltec
|
||||
ADC_Function_Init();
|
||||
RTC_Init();
|
||||
startupTime = RTC_GetCounter();
|
||||
memset (&stats, 0, sizeof (stats));
|
||||
|
||||
MESH_LOGW (TAG, "Enable TCXO");
|
||||
char useRegulatorLDO = 1;
|
||||
|
||||
LoRaDebugPrint (0);
|
||||
MESH_LOGW (TAG, "Starting lora");
|
||||
uint16_t loraBeginStat = LoRaBegin (frequencyInHz, txPowerInDbm, tcxoVoltage, useRegulatorLDO);
|
||||
if (loraBeginStat != 0) {
|
||||
MESH_LOGE (TAG, "Does not recognize the module");
|
||||
while (1) {
|
||||
vTaskDelay (pdMS_TO_TICKS (1000));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
char crcOn = 1;
|
||||
char invertIrq = 0;
|
||||
|
||||
LoRaConfig (spreadingFactor, bandwidth, codingRate, preambleLength, 0, crcOn,
|
||||
invertIrq);
|
||||
DiscoverRequestPayload discReq;
|
||||
discReq.prefixOnly = 0;
|
||||
discReq.since = 0;
|
||||
discReq.tag = RTC_GetCounter();
|
||||
discReq.typeFilter = 0xFF;
|
||||
sendDiscoverRequest (&discReq);
|
||||
|
||||
sendAdvert (1);
|
||||
|
||||
while (1) {
|
||||
start_time = xTaskGetTickCount();
|
||||
@@ -211,8 +169,10 @@ void task1_task (void *pvParameters) {
|
||||
// frame = decodeFrame (bufIn, rxLen);
|
||||
MESH_LOGD (TAG, "Free stack before processFrame: %u bytes", uxTaskGetStackHighWaterMark (NULL) * 4);
|
||||
processFrame (&frame);
|
||||
MESH_LOGD (TAG, "Free stack before retransmitFrame: %u bytes", uxTaskGetStackHighWaterMark (NULL) * 4);
|
||||
retransmitFrame (&frame);
|
||||
if (persistent.doRepeat) {
|
||||
MESH_LOGD (TAG, "Free stack before retransmitFrame: %u bytes", uxTaskGetStackHighWaterMark (NULL) * 4);
|
||||
retransmitFrame (&frame);
|
||||
}
|
||||
memset (&frame, 0, sizeof (FrameStruct)); // prepare for the next round
|
||||
}
|
||||
|
||||
|
||||
@@ -21,12 +21,12 @@
|
||||
// requires at least a 256 byte data
|
||||
|
||||
|
||||
void processFrame (const FrameStruct *frame) {
|
||||
void processFrame (FrameStruct *frame) {
|
||||
printFrameHeader (frame);
|
||||
if (frame->header & PAYLOAD_VERSION_3) { // more than the version 0
|
||||
MESH_LOGW (TAG, "Frame too new, got version %d instead of 0", (frame->header & PAYLOAD_VERSION_3) >> 6);
|
||||
}
|
||||
|
||||
|
||||
unsigned char frameType = frame->header & PAYLOAD_TYPE_MASK;
|
||||
|
||||
unsigned char index = 0;
|
||||
@@ -67,12 +67,15 @@ void processFrame (const FrameStruct *frame) {
|
||||
} else if (frameType == PAYLOAD_TYPE_MULTIPART) {
|
||||
|
||||
} else if (frameType == PAYLOAD_TYPE_CONTROL) {
|
||||
decodeControlFrame (frame);
|
||||
if (frame->path.pathLen == 0) {
|
||||
decodeControlFrame (frame);
|
||||
}
|
||||
frame->header = 0xFF;
|
||||
|
||||
} else if (frameType == PAYLOAD_TYPE_RAW_CUSTOM) {
|
||||
// not implemented
|
||||
} else {
|
||||
stats.packetsReceivedCount--;
|
||||
}
|
||||
MESH_LOGD(TAG, "Processed frame");
|
||||
MESH_LOGD (TAG, "Processed frame");
|
||||
}
|
||||
|
||||
@@ -11,6 +11,6 @@
|
||||
#include <ctype.h>
|
||||
#include "stdio.h"
|
||||
|
||||
void processFrame (const FrameStruct * frame);
|
||||
void processFrame (FrameStruct *frame);
|
||||
|
||||
#endif
|
||||
@@ -381,20 +381,39 @@ void sendFrame (const FrameStruct *frame) {
|
||||
*/
|
||||
|
||||
void retransmitFrame (FrameStruct *frame) {
|
||||
MESH_LOGD (TAG, "Going to check ReTx");
|
||||
if (frame->header & ROUTE_TYPE_FLOOD || frame->header & ROUTE_TYPE_TRANSPORT_FLOOD) {
|
||||
MESH_LOGD (TAG, "Header is flood");
|
||||
if (frame->header != DONT_RETRANSMIT_HEADER && frame->path.pathLen + 1 < MAX_FLOOD_TTL) {
|
||||
MESH_LOGD (TAG, "Writing pubkey");
|
||||
|
||||
/* -------- FLOOD -------- */
|
||||
if (frame->header & ROUTE_TYPE_FLOOD ||
|
||||
frame->header & ROUTE_TYPE_TRANSPORT_FLOOD) {
|
||||
|
||||
if (frame->header != DONT_RETRANSMIT_HEADER &&
|
||||
frame->path.pathLen + 1 < MAX_FLOOD_TTL) {
|
||||
|
||||
// append self to END of path
|
||||
frame->path.path[frame->path.pathLen++] = persistent.pubkey[0];
|
||||
MESH_LOGD (TAG, "Flooding");
|
||||
vTaskDelay (10);
|
||||
LoRaTransmit (frame); // TODO check if correct
|
||||
MESH_LOGD (TAG, "Flooded");
|
||||
LoRaTransmit (frame);
|
||||
}
|
||||
}
|
||||
|
||||
if (frame->header & ROUTE_TYPE_DIRECT || frame->header & ROUTE_TYPE_TRANSPORT_DIRECT) {
|
||||
/* -------- DIRECT -------- */
|
||||
if (frame->header & ROUTE_TYPE_DIRECT ||
|
||||
frame->header & ROUTE_TYPE_TRANSPORT_DIRECT) {
|
||||
|
||||
// are we the next hop?
|
||||
if (frame->path.pathLen > 0 &&
|
||||
frame->path.path[0] == persistent.pubkey[0]) {
|
||||
|
||||
// remove self from START of path
|
||||
frame->path.pathLen--;
|
||||
memmove (frame->path.path,
|
||||
frame->path.path + 1,
|
||||
frame->path.pathLen);
|
||||
|
||||
// forward only if there's another hop
|
||||
if (frame->path.pathLen > 0) {
|
||||
LoRaTransmit (frame);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#define HMAC_SIZE 2 // meshcore size
|
||||
#define MAX_FLOOD_TTL 64
|
||||
|
||||
int ReadFrame(FrameStruct *frame, int8_t *rssiPacket, int8_t *snrPacket, int8_t *rawSnr);
|
||||
int ReadFrame (FrameStruct *frame, int8_t *rssiPacket, int8_t *snrPacket, int8_t *rawSnr);
|
||||
|
||||
void LoRaTransmit (const FrameStruct *frame);
|
||||
|
||||
@@ -22,10 +22,10 @@ FrameStruct decodeFrame (unsigned char *data, unsigned char dataLen);
|
||||
void sendFrame (const FrameStruct * frame);
|
||||
*/
|
||||
|
||||
void printFrameHeader (const FrameStruct * frame) ;
|
||||
void printFrameHeader (const FrameStruct *frame);
|
||||
|
||||
//CALL LAST, PATH GETS MODIFIED
|
||||
void retransmitFrame (FrameStruct * frame) ;
|
||||
// CALL LAST, PATH GETS MODIFIED
|
||||
void retransmitFrame (FrameStruct *frame);
|
||||
|
||||
// Verify MAC + Decrypt
|
||||
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
|
||||
void sendAdvert (uint8_t shouldFlood);
|
||||
|
||||
void decodeAdvertisement (const FrameStruct * frame);
|
||||
void decodeAdvertisement (const FrameStruct *frame);
|
||||
|
||||
void printAdvertisement (const AdvertisementPayload * advert);
|
||||
void printAdvertisement (const AdvertisementPayload *advert);
|
||||
|
||||
void saveAdvert(const AdvertisementPayload * advert);
|
||||
void saveAdvert (const AdvertisementPayload *advert);
|
||||
|
||||
#endif
|
||||
@@ -105,10 +105,10 @@ void printAnonRequest (const AnonymousRequestPayload *req, int isRoomServer) {
|
||||
printf (" sync timestamp: %u\n", syncTimestamp);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// remaining bytes = password
|
||||
if (index < req->payloadLen) {
|
||||
uint8_t passwordLen = req->payloadLen - index;
|
||||
uint8_t passwordLen = req->payloadLen - index;
|
||||
if (passwordLen > 16)
|
||||
passwordLen = 16;
|
||||
passwordLen = strnlen (&(req->payload[index]), passwordLen);
|
||||
@@ -175,8 +175,10 @@ void decodeAnonReq (const FrameStruct *frame) {
|
||||
printAnonRequest (&anonReq, persistent.nodeType == NODE_TYPE_ROOM_SERVER);
|
||||
|
||||
uint8_t passwordLen = anonReq.payloadLen - index2;
|
||||
if (passwordLen > 16)
|
||||
if (passwordLen > 16) {
|
||||
passwordLen = 16;
|
||||
}
|
||||
|
||||
passwordLen = strnlen (&(anonReq.payload[index2]), passwordLen);
|
||||
|
||||
MESH_LOGI (TAG, "Password len is %d.", passwordLen);
|
||||
@@ -206,5 +208,9 @@ void decodeAnonReq (const FrameStruct *frame) {
|
||||
resp.data[index3++] = (randOut >> 24) & 0xFF;
|
||||
resp.data[index3++] = FIRMWARE_VER_LEVEL;
|
||||
resp.dataLen = index3;
|
||||
if ((frame->header & ROUTE_TYPE_MASK) == ROUTE_TYPE_FLOOD ||
|
||||
(frame->header & ROUTE_TYPE_MASK) == ROUTE_TYPE_TRANSPORT_FLOOD) {
|
||||
sendPathBack (foundNode, &(frame->path));
|
||||
}
|
||||
sendEncryptedResponse (foundNode, &resp);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include "meshcore/packetstructs.h"
|
||||
#include "lib/config.h"
|
||||
|
||||
void decodeAnonReq (const FrameStruct * frame);
|
||||
void decodeAnonReq (const FrameStruct *frame);
|
||||
|
||||
void sendAnonymousRequest (const NodeEntry *targetNode, const uint8_t *password, uint32_t sync);
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
#include "util/hexdump.h"
|
||||
#include "util/log.h"
|
||||
#include <stdio.h>
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
#define TAG "Control"
|
||||
|
||||
@@ -41,6 +43,7 @@ void sendDiscoverRequest (const DiscoverRequestPayload *discReq) {
|
||||
|
||||
void sendDiscoverResponse (const DiscoverResponsePayload *discResp) {
|
||||
FrameStruct frame;
|
||||
frame.header = ROUTE_TYPE_DIRECT | PAYLOAD_TYPE_CONTROL | PAYLOAD_VERSION_0;
|
||||
frame.path.pathLen = 0;
|
||||
uint8_t offset = 0;
|
||||
|
||||
@@ -89,7 +92,7 @@ void printDiscoverResponse (const DiscoverResponsePayload *p) {
|
||||
printf ("\n");
|
||||
}
|
||||
|
||||
void decodeControlFrame (const FrameStruct * frame) {
|
||||
void decodeControlFrame (const FrameStruct *frame) {
|
||||
uint8_t index = 0;
|
||||
uint8_t type = frame->payload[index] & 0xF0;
|
||||
if (type == CONTROL_DATA_FLAG_TYPE_NODE_DISCOVER_REQ) {
|
||||
@@ -110,7 +113,7 @@ void decodeControlFrame (const FrameStruct * frame) {
|
||||
discReq.since |= frame->payload[index++] << 24;
|
||||
}
|
||||
printDiscoverRequest (&discReq);
|
||||
if ((discReq.typeFilter >> 2) & persistent.nodeType) {
|
||||
if ((discReq.typeFilter >> 1) & persistent.nodeType) {
|
||||
DiscoverResponsePayload discResp;
|
||||
|
||||
discResp.tag = discReq.tag;
|
||||
@@ -119,8 +122,10 @@ void decodeControlFrame (const FrameStruct * frame) {
|
||||
memcpy (discResp.pubkey, persistent.pubkey, discResp.pubkeyLen);
|
||||
discResp.snr = stats.lastSNR; // hopefully the correct one
|
||||
|
||||
|
||||
MESH_LOGD (TAG, "Replying to a discover request with tag %d", discResp.tag);
|
||||
sendDiscoverResponse (&discResp);
|
||||
MESH_LOGD(TAG, "Replying to a discover request with tag %d", discResp.tag);
|
||||
printDiscoverResponse (&discResp);
|
||||
}
|
||||
|
||||
} else if (type == CONTROL_DATA_FLAG_DISCOVER_RESP) {
|
||||
|
||||
@@ -3,14 +3,14 @@
|
||||
|
||||
#include "meshcore/packetstructs.h"
|
||||
|
||||
void sendDiscoverRequest(const DiscoverRequestPayload *discReq);
|
||||
void sendDiscoverRequest (const DiscoverRequestPayload *discReq);
|
||||
|
||||
void sendDiscoverResponse(const DiscoverResponsePayload *discResp);
|
||||
void sendDiscoverResponse (const DiscoverResponsePayload *discResp);
|
||||
|
||||
void printDiscoverRequest(const DiscoverRequestPayload *p);
|
||||
void printDiscoverRequest (const DiscoverRequestPayload *p);
|
||||
|
||||
void printDiscoverResponse(const DiscoverResponsePayload *p);
|
||||
void printDiscoverResponse (const DiscoverResponsePayload *p);
|
||||
|
||||
void decodeControlFrame(const FrameStruct * frame);
|
||||
void decodeControlFrame (const FrameStruct *frame);
|
||||
|
||||
#endif
|
||||
@@ -2,5 +2,4 @@
|
||||
#define CUSTOM_HEADER
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -2,23 +2,27 @@
|
||||
#include "lib/telemetry/telemetry.h"
|
||||
#include "meshcore/meshframing.h"
|
||||
#include "meshcore/packets/ack.h"
|
||||
#include "meshcore/packets/advert.h"
|
||||
#include "meshcore/packetstructs.h"
|
||||
#include "meshcore/stats.h"
|
||||
#include "util/hexdump.h"
|
||||
#include "util/log.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "encrypted.h"
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "lib/adc/temperature.h"
|
||||
#include "lib/rtc/rtc.h"
|
||||
#include "sx1262.h"
|
||||
|
||||
#define TICKS_TO_MS(xTicks) (((uint32_t)(xTicks)*1000U) / (uint32_t)configTICK_RATE_HZ)
|
||||
|
||||
|
||||
#define TAG "EncryptedMessage"
|
||||
|
||||
void sendEncryptedFrame (NodeEntry *targetNode, uint8_t payloadType, const uint8_t *plain, size_t plainLen) {
|
||||
void sendEncryptedFrame (const NodeEntry *targetNode, uint8_t payloadType, const uint8_t *plain, size_t plainLen) {
|
||||
FrameStruct frame;
|
||||
uint8_t offset = 0;
|
||||
|
||||
@@ -52,7 +56,7 @@ void sendEncryptedFrame (NodeEntry *targetNode, uint8_t payloadType, const uint8
|
||||
LoRaTransmit (&frame);
|
||||
}
|
||||
|
||||
void sendEncryptedTextMessage (NodeEntry *targetNode, const PlainTextMessagePayload *msg) {
|
||||
void sendEncryptedTextMessage (const NodeEntry *targetNode, const PlainTextMessagePayload *msg) {
|
||||
if (targetNode == NULL) {
|
||||
MESH_LOGW (TAG, "Node is null");
|
||||
return;
|
||||
@@ -72,15 +76,16 @@ void sendEncryptedTextMessage (NodeEntry *targetNode, const PlainTextMessagePayl
|
||||
|
||||
buf[index++] = (msg->textType << 2) | (msg->attempt & 0x03);
|
||||
memcpy (&buf[index], msg->message, msgLen);
|
||||
index += msgLen;
|
||||
|
||||
sendEncryptedFrame (
|
||||
targetNode,
|
||||
PAYLOAD_TYPE_TXT_MSG,
|
||||
buf,
|
||||
index + msgLen);
|
||||
index);
|
||||
}
|
||||
|
||||
void sendEncryptedResponse (NodeEntry *targetNode, const Response *resp) {
|
||||
void sendEncryptedResponse (const NodeEntry *targetNode, const Response *resp) {
|
||||
uint8_t buf[256];
|
||||
uint8_t index = 0;
|
||||
|
||||
@@ -99,7 +104,7 @@ void sendEncryptedResponse (NodeEntry *targetNode, const Response *resp) {
|
||||
index);
|
||||
}
|
||||
|
||||
void sendEncryptedRequest (NodeEntry *targetNode, const Request *req) {
|
||||
void sendEncryptedRequest (const NodeEntry *targetNode, const Request *req) {
|
||||
uint8_t buf[256];
|
||||
uint8_t index = 0;
|
||||
|
||||
@@ -119,7 +124,7 @@ void sendEncryptedRequest (NodeEntry *targetNode, const Request *req) {
|
||||
index);
|
||||
}
|
||||
|
||||
void sendEncryptedPathPayload (NodeEntry *targetNode, const ReturnedPathPayload *path) {
|
||||
void sendEncryptedPathPayload (const NodeEntry *targetNode, const ReturnedPathPayload *path) {
|
||||
uint8_t buf[256];
|
||||
uint8_t index = 0;
|
||||
|
||||
@@ -127,9 +132,17 @@ void sendEncryptedPathPayload (NodeEntry *targetNode, const ReturnedPathPayload
|
||||
memcpy (&buf[index], path->path.path, path->path.pathLen);
|
||||
index += path->path.pathLen;
|
||||
|
||||
buf[index++] = path->extra.type;
|
||||
memcpy (&buf[index], path->extra.data,
|
||||
path->extra.dataLen);
|
||||
if (path->extra.dataLen > 0) {
|
||||
buf[index++] = path->extra.type;
|
||||
memcpy (&buf[index], path->extra.data, path->extra.dataLen);
|
||||
} else {
|
||||
buf[index++] = 0xFF;
|
||||
uint32_t timestamp = RTC_GetCounter();
|
||||
buf[index++] = timestamp;
|
||||
buf[index++] = timestamp >> 8;
|
||||
buf[index++] = timestamp >> 16;
|
||||
buf[index++] = timestamp >> 24;
|
||||
}
|
||||
|
||||
sendEncryptedFrame (
|
||||
targetNode,
|
||||
@@ -188,6 +201,8 @@ void printEncryptedPayload (const EncryptedPayloadStruct *enc) {
|
||||
void decodeEncryptedPayload (const FrameStruct *frame) {
|
||||
EncryptedPayloadStruct enc;
|
||||
memset (&enc, 0, sizeof (enc));
|
||||
enc.path = &(frame->path);
|
||||
enc.origFrame = frame;
|
||||
enc.type = frame->header & PAYLOAD_TYPE_MASK;
|
||||
unsigned char index = 0;
|
||||
|
||||
@@ -206,11 +221,11 @@ void decodeEncryptedPayload (const FrameStruct *frame) {
|
||||
|
||||
enc.remNode = remNode;
|
||||
|
||||
|
||||
if (remNode == NULL) {
|
||||
MESH_LOGW (TAG, "Node not in DB");
|
||||
return;
|
||||
}
|
||||
remNode->last_seen_lt = RTC_GetCounter();
|
||||
MESH_LOGI (TAG, "Found node with index %d", remNode - persistent.contacts);
|
||||
|
||||
|
||||
@@ -228,6 +243,17 @@ void decodeEncryptedPayload (const FrameStruct *frame) {
|
||||
}
|
||||
}
|
||||
|
||||
void sendPathBack (const NodeEntry *node, const Path *path) {
|
||||
ReturnedPathPayload retPath;
|
||||
retPath.extra.dataLen = 0; // redo to send the resp in path
|
||||
retPath.extra.type = 0xFF;
|
||||
|
||||
retPath.path.pathLen = path->pathLen;
|
||||
memcpy (retPath.path.path, path->path, path->pathLen);
|
||||
|
||||
sendEncryptedPathPayload (node, &retPath);
|
||||
}
|
||||
|
||||
void parseEncryptedPayload (const EncryptedPayloadStruct *enc) {
|
||||
// printEncryptedPayload(&enc);
|
||||
|
||||
@@ -242,7 +268,6 @@ void parseEncryptedPayload (const EncryptedPayloadStruct *enc) {
|
||||
|
||||
uint8_t index = 0;
|
||||
if (enc->type == PAYLOAD_TYPE_PATH) {
|
||||
|
||||
ReturnedPathPayload retPath;
|
||||
retPath.path.pathLen = enc->payload[index++];
|
||||
if (retPath.path.pathLen > 64) {
|
||||
@@ -255,16 +280,26 @@ void parseEncryptedPayload (const EncryptedPayloadStruct *enc) {
|
||||
retPath.extra.dataLen = enc->payloadLen - index;
|
||||
memcpy (retPath.extra.data, &(enc->payload[index]), retPath.extra.dataLen);
|
||||
|
||||
if ((enc->origFrame->header & ROUTE_TYPE_MASK) == ROUTE_TYPE_FLOOD ||
|
||||
(enc->origFrame->header & ROUTE_TYPE_MASK) == ROUTE_TYPE_TRANSPORT_FLOOD) {
|
||||
sendPathBack (enc->remNode, enc->path);
|
||||
}
|
||||
|
||||
} else if (enc->type == PAYLOAD_TYPE_REQ) {
|
||||
Request req;
|
||||
req.timestamp = enc->payload[index++];
|
||||
req.timestamp |= enc->payload[index++] << 8;
|
||||
req.timestamp |= enc->payload[index++] << 16;
|
||||
req.timestamp |= enc->payload[index++] << 24;
|
||||
enc->remNode->last_seen_rt = req.timestamp;
|
||||
req.requestType = enc->payload[index++];
|
||||
req.dataLen = enc->payloadLen - index;
|
||||
memcpy (req.data, &(enc->payload[index]), req.dataLen);
|
||||
printRequest (&req);
|
||||
if ((enc->origFrame->header & ROUTE_TYPE_MASK) == ROUTE_TYPE_FLOOD ||
|
||||
(enc->origFrame->header & ROUTE_TYPE_MASK) == ROUTE_TYPE_TRANSPORT_FLOOD) {
|
||||
sendPathBack (enc->remNode, enc->path);
|
||||
}
|
||||
switch (req.requestType) {
|
||||
case REQUEST_GET_STATS: {
|
||||
Response resp;
|
||||
@@ -281,6 +316,7 @@ void parseEncryptedPayload (const EncryptedPayloadStruct *enc) {
|
||||
case REQUEST_GET_TELEMETRY_DATA: {
|
||||
Response resp;
|
||||
resp.tag = req.timestamp;
|
||||
enc->remNode->last_seen_rt = req.timestamp;
|
||||
uint8_t index2 = 0;
|
||||
resp.data[index2++] = TELEM_CHANNEL_SELF;
|
||||
resp.data[index2++] = LPP_TEMPERATURE;
|
||||
@@ -351,9 +387,403 @@ void parseEncryptedPayload (const EncryptedPayloadStruct *enc) {
|
||||
plaintext.timestamp |= enc->payload[index++] << 8;
|
||||
plaintext.timestamp |= enc->payload[index++] << 16;
|
||||
plaintext.timestamp |= enc->payload[index++] << 24;
|
||||
enc->remNode->last_seen_rt = plaintext.timestamp;
|
||||
plaintext.attempt = enc->payload[index] & 0x03;
|
||||
plaintext.textType = enc->payload[index++] >> 2;
|
||||
memcpy (plaintext.message, &(enc->payload[index]), enc->payloadLen - index);
|
||||
printPlainTextMessage (&plaintext);
|
||||
if ((enc->origFrame->header & ROUTE_TYPE_MASK) == ROUTE_TYPE_FLOOD ||
|
||||
(enc->origFrame->header & ROUTE_TYPE_MASK) == ROUTE_TYPE_TRANSPORT_FLOOD) {
|
||||
sendPathBack (enc->remNode, enc->path);
|
||||
}
|
||||
switch (plaintext.textType) {
|
||||
case TXT_TYPE_PLAIN:
|
||||
printf ("Plaintext message from %s, attempt %d, timestamp %d: %s", enc->remNode->name, plaintext.attempt, plaintext.timestamp, plaintext.message);
|
||||
break;
|
||||
|
||||
case TXT_TYPE_CLI_DATA:
|
||||
if (enc->remNode->authenticated) {
|
||||
processCommand (plaintext.message, enc->remNode);
|
||||
}
|
||||
break;
|
||||
|
||||
case TXT_TYPE_SIGNED_PLAIN: {
|
||||
uint8_t senderPubKeyPrefix[4];
|
||||
memcpy (senderPubKeyPrefix, plaintext.message, sizeof (senderPubKeyPrefix));
|
||||
NodeEntry *senderNode = getNodePrefix (senderPubKeyPrefix);
|
||||
printf ("Plaintext message from server %s, sender is %s, attempt %d, timestamp %d: %s", enc->remNode->name, senderNode->name, plaintext.attempt, plaintext.timestamp, &(plaintext.message[4]));
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
MESH_LOGW (TAG, "Unknown text type: %d", plaintext.textType);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define STR_EQ_LIT(s, lit) (memcmp ((s), (lit), sizeof (lit) - 1) == 0)
|
||||
|
||||
void processCommand (char *cmd, NodeEntry *remNode) {
|
||||
PlainTextMessagePayload replyPayload;
|
||||
replyPayload.timestamp = RTC_GetCounter();
|
||||
replyPayload.attempt = 0;
|
||||
replyPayload.textType = TXT_TYPE_CLI_DATA;
|
||||
|
||||
uint8_t *reply = replyPayload.message;
|
||||
reply[0] = 0;
|
||||
|
||||
while (*cmd == ' ') cmd++; // skip leading spaces
|
||||
|
||||
// Optional CLI prefix (xx|) for companion radio
|
||||
if (strlen (cmd) > 4 && cmd[2] == '|') {
|
||||
memcpy (reply, cmd, 3);
|
||||
reply += 3;
|
||||
cmd += 3;
|
||||
}
|
||||
|
||||
/* ---------------- System ---------------- */
|
||||
if (STR_EQ_LIT (cmd, "reboot")) {
|
||||
NVIC_SystemReset();
|
||||
} else if (STR_EQ_LIT (cmd, "advert")) {
|
||||
sendAdvert (1); // 1500ms delay in reference
|
||||
strcpy ((char *)reply, "OK - Advert sent");
|
||||
} else if (STR_EQ_LIT (cmd, "clear stats")) {
|
||||
memset (&stats, 0, sizeof (stats));
|
||||
strcpy ((char *)reply, "(OK - stats reset)");
|
||||
}
|
||||
|
||||
else if (STR_EQ_LIT (cmd, "ver")) {
|
||||
sprintf ((char *)reply, "%s (Build: %s)", VERSION, __DATE__);
|
||||
}
|
||||
|
||||
else if (STR_EQ_LIT (cmd, "board")) {
|
||||
sprintf ((char *)reply, "%s", BOARD);
|
||||
}
|
||||
|
||||
/* ---------------- Clock ---------------- */
|
||||
else if (STR_EQ_LIT (cmd, "clock")) {
|
||||
RTC_Get();
|
||||
sprintf ((char *)reply, "%02d:%02d:%02d - %d/%d/%d UTC",
|
||||
calendar.hour, calendar.min, calendar.sec,
|
||||
calendar.w_date, calendar.w_month, calendar.w_year);
|
||||
} else if (STR_EQ_LIT (cmd, "time ")) {
|
||||
uint32_t secs = atoi (&cmd[5]);
|
||||
uint32_t curr = RTC_GetCounter();
|
||||
if (secs > curr) {
|
||||
RTC_SetCounter (secs);
|
||||
RTC_Get();
|
||||
sprintf ((char *)reply, "OK - clock set: %02d:%02d:%02d - %d/%d/%d UTC",
|
||||
calendar.hour, calendar.min, calendar.sec,
|
||||
calendar.w_date, calendar.w_month, calendar.w_year);
|
||||
} else {
|
||||
strcpy ((char *)reply, "(ERR: clock cannot go backwards)");
|
||||
}
|
||||
} else if (STR_EQ_LIT (cmd, "clock sync")) {
|
||||
uint32_t curr = RTC_GetCounter();
|
||||
uint32_t sender = replyPayload.timestamp;
|
||||
if (sender > curr) {
|
||||
RTC_SetCounter (sender + 1);
|
||||
RTC_Get();
|
||||
sprintf ((char *)reply, "OK - clock set: %02d:%02d:%02d - %d/%d/%d UTC",
|
||||
calendar.hour, calendar.min, calendar.sec,
|
||||
calendar.w_date, calendar.w_month, calendar.w_year);
|
||||
} else {
|
||||
strcpy ((char *)reply, "ERR: clock cannot go backwards");
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------- Neighbors ---------------- */
|
||||
else if (STR_EQ_LIT (cmd, "neighbors")) {
|
||||
Callbacks_FormatNeighborsReply ((char *)reply);
|
||||
} else if (STR_EQ_LIT (cmd, "neighbor.remove ")) {
|
||||
const char *hex = cmd + 16;
|
||||
uint8_t pubkey[PUB_KEY_SIZE];
|
||||
int len = strlen (hex) / 2;
|
||||
if (mesh_fromHex (pubkey, len, hex)) {
|
||||
Callbacks_RemoveNeighbor (pubkey, len);
|
||||
strcpy ((char *)reply, "OK");
|
||||
} else {
|
||||
strcpy ((char *)reply, "ERR: bad pubkey");
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------- Radio / Temp ---------------- */
|
||||
else if (STR_EQ_LIT (cmd, "tempradio ")) {
|
||||
char tmp[64];
|
||||
strcpy (tmp, &cmd[10]);
|
||||
|
||||
const char *parts[5];
|
||||
int num = mesh_ParseTextParts (tmp, parts, 5); // assume helper
|
||||
float freq = num > 0 ? strtof (parts[0], NULL) : 0.0f;
|
||||
float bw = num > 1 ? strtof (parts[1], NULL) : 0.0f;
|
||||
uint8_t sf = num > 2 ? atoi (parts[2]) : 0;
|
||||
uint8_t cr = num > 3 ? atoi (parts[3]) : 0;
|
||||
int timeout_mins = num > 4 ? atoi (parts[4]) : 0;
|
||||
if (freq >= 300.0f && freq <= 2500.0f && bw >= 7.0f && bw <= 500.0f &&
|
||||
sf >= 5 && sf <= 12 && cr >= 5 && cr <= 8 && timeout_mins > 0) {
|
||||
Callbacks_ApplyTempRadioParams (freq, bw, sf, cr, timeout_mins);
|
||||
|
||||
LoraApply();
|
||||
sprintf ((char *)reply, "OK - temp params for %d mins", timeout_mins);
|
||||
} else {
|
||||
strcpy ((char *)reply, "Error, invalid params");
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------- Password ---------------- */
|
||||
else if (STR_EQ_LIT (cmd, "password ")) {
|
||||
strncpy (persistent.password, &cmd[9], sizeof (persistent.password));
|
||||
// savePrefs(); TODO add this
|
||||
sprintf ((char *)reply, "password now: %s", persistent.password);
|
||||
}
|
||||
|
||||
/* ---------------- GET / SET Config ---------------- */
|
||||
else if (STR_EQ_LIT (cmd, "get ")) {
|
||||
const char *config = &cmd[4];
|
||||
|
||||
if (memcmp (config, "af", 2) == 0) {
|
||||
sprintf (reply, "> %f", persistent.airtimeFactor);
|
||||
} else if (memcmp (config, "int.thresh", 10) == 0) {
|
||||
sprintf (reply, "> %d", (uint32_t)_prefs->interference_threshold);
|
||||
} else if (memcmp (config, "agc.reset.interval", 18) == 0) {
|
||||
sprintf (reply, "> %d", ((uint32_t)_prefs->agc_reset_interval) * 4);
|
||||
} else if (memcmp (config, "multi.acks", 10) == 0) {
|
||||
sprintf (reply, "> %d", (uint32_t)_prefs->multi_acks);
|
||||
} else if (memcmp (config, "allow.read.only", 15) == 0) {
|
||||
sprintf (reply, "> %s", _prefs->allow_read_only ? "on" : "off");
|
||||
} else if (memcmp (config, "flood.advert.interval", 21) == 0) {
|
||||
sprintf (reply, "> %d", (uint32_t)_prefs->flood_advert_interval);
|
||||
} else if (memcmp (config, "advert.interval", 15) == 0) {
|
||||
sprintf (reply, "> %d", ((uint32_t)_prefs->advert_interval) * 2);
|
||||
} else if (memcmp (config, "guest.password", 14) == 0) {
|
||||
sprintf (reply, "> %s", persistent.guestPassword);
|
||||
} else if (memcmp (config, "name", 4) == 0) {
|
||||
sprintf (reply, "> %s", persistent.nodeName);
|
||||
} else if (memcmp (config, "repeat", 6) == 0) {
|
||||
sprintf (reply, "> %s", persistent.doRepeat ? "on" : "off");
|
||||
} else if (memcmp (config, "lat", 3) == 0) {
|
||||
sprintf (reply, "> %d", persistent.latitude);
|
||||
} else if (memcmp (config, "lon", 3) == 0) {
|
||||
sprintf (reply, "> %d", persistent.longitude);
|
||||
} else if (memcmp (config, "radio", 5) == 0) {
|
||||
char freq[16], bw[16];
|
||||
snprintf(freq, sizeof(freq), "%lf", persistent.frequencyInHz / 1000000.0);
|
||||
snprintf(bw, sizeof(bw), "%lf", loraBwToFloat(persistent.bandwidth));
|
||||
sprintf (reply, "> %s,%s,%d,%d", freq, bw, persistent.spreadingFactor, persistent.codingRate + 4);
|
||||
} else if (memcmp (config, "rxdelay", 7) == 0) {
|
||||
sprintf (reply, "> %s", StrHelper::ftoa (_prefs->rx_delay_base));
|
||||
} else if (memcmp (config, "txdelay", 7) == 0) {
|
||||
sprintf (reply, "> %s", StrHelper::ftoa (_prefs->tx_delay_factor));
|
||||
} else if (memcmp (config, "flood.max", 9) == 0) {
|
||||
sprintf (reply, "> %d", (uint32_t)_prefs->flood_max);
|
||||
} else if (memcmp (config, "direct.txdelay", 14) == 0) {
|
||||
sprintf (reply, "> %s", StrHelper::ftoa (_prefs->direct_tx_delay_factor));
|
||||
} else if (memcmp (config, "tx", 2) == 0 && (config[2] == 0 || config[2] == ' ')) {
|
||||
sprintf (reply, "> %d", (uint32_t)_prefs->tx_power_dbm);
|
||||
} else if (memcmp (config, "freq", 4) == 0) {
|
||||
sprintf (reply, "> %s", StrHelper::ftoa (_prefs->freq));
|
||||
} else if (memcmp (config, "public.key", 10) == 0) {
|
||||
strcpy (reply, "> ");
|
||||
hexdump_compact(persistent.pubkey, sizeof(persistent.pubkey), &(reply[2]), 70);
|
||||
} else if (memcmp (config, "role", 4) == 0) {
|
||||
sprintf (reply, "> %s", getStringRole(persistent.nodeType));
|
||||
} else if (memcmp (config, "adc.multiplier", 14) == 0) {
|
||||
sprintf (reply, "> %.3f", persistent.adcMultiplier);
|
||||
} else {
|
||||
sprintf (reply, "??: %s", config);
|
||||
}
|
||||
|
||||
} else if (STR_EQ_LIT (cmd, "set ")) {
|
||||
const char *config = &cmd[4];
|
||||
|
||||
if (memcmp (config, "af ", 3) == 0) {
|
||||
persistent.airtimeFactor = atof (&config[3]);
|
||||
// savePrefs();
|
||||
strcpy (reply, "OK");
|
||||
} else if (memcmp (config, "int.thresh ", 11) == 0) {
|
||||
_prefs->interference_threshold = atoi (&config[11]);
|
||||
// savePrefs();
|
||||
strcpy (reply, "OK");
|
||||
} else if (memcmp (config, "agc.reset.interval ", 19) == 0) {
|
||||
_prefs->agc_reset_interval = atoi (&config[19]) / 4;
|
||||
// savePrefs();
|
||||
sprintf (reply, "OK - interval rounded to %d", ((uint32_t)_prefs->agc_reset_interval) * 4);
|
||||
} else if (memcmp (config, "multi.acks ", 11) == 0) {
|
||||
_prefs->multi_acks = atoi (&config[11]);
|
||||
// savePrefs();
|
||||
strcpy (reply, "OK");
|
||||
} else if (memcmp (config, "allow.read.only ", 16) == 0) {
|
||||
if (memcmp (&config[16], "on", 2) == 0) {
|
||||
persistent.allowReadOnly = 1;
|
||||
strcpy (reply, "OK");
|
||||
} else if (memcmp (&config[16], "off", 3) == 0) {
|
||||
persistent.allowReadOnly = 0;
|
||||
strcpy (reply, "OK");
|
||||
}
|
||||
//savePrefs();
|
||||
|
||||
} else if (memcmp (config, "flood.advert.interval ", 22) == 0) {
|
||||
int hours = _atoi (&config[22]);
|
||||
if ((hours > 0 && hours < 3) || (hours > 48)) {
|
||||
strcpy (reply, "Error: interval range is 3-48 hours");
|
||||
} else {
|
||||
_prefs->flood_advert_interval = (uint8_t)hours;
|
||||
_callbacks->updateFloodAdvertTimer();
|
||||
savePrefs();
|
||||
strcpy (reply, "OK");
|
||||
}
|
||||
} else if (memcmp (config, "advert.interval ", 16) == 0) {
|
||||
int mins = _atoi (&config[16]);
|
||||
if ((mins > 0 && mins < MIN_LOCAL_ADVERT_INTERVAL) || (mins > 240)) {
|
||||
sprintf (reply, "Error: interval range is %d-240 minutes", MIN_LOCAL_ADVERT_INTERVAL);
|
||||
} else {
|
||||
_prefs->advert_interval = (uint8_t)(mins / 2);
|
||||
_callbacks->updateAdvertTimer();
|
||||
savePrefs();
|
||||
strcpy (reply, "OK");
|
||||
}
|
||||
} else if (memcmp (config, "guest.password ", 15) == 0) {
|
||||
strncpy (persistent.guestPassword, &config[15], sizeof (persistent.guestPassword));
|
||||
// savePrefs();
|
||||
strcpy (reply, "OK");
|
||||
} else if (memcmp (config, "name ", 5) == 0) {
|
||||
strncpy (persistent.nodeName, &config[5], sizeof (persistent.nodeName));
|
||||
// savePrefs();
|
||||
strcpy (reply, "OK");
|
||||
} else if (memcmp (config, "repeat ", 7) == 0) {
|
||||
if (memcmp (&config[7], "off", 3) == 0) {
|
||||
persistent.doRepeat = 0;
|
||||
} else if (memcmp (&config[7], "on", 2) == 0) {
|
||||
persistent.doRepeat = 1;
|
||||
}
|
||||
// savePrefs();
|
||||
strcpy (reply, persistent.doRepeat ? "OK - repeat is now ON" : "OK - repeat is now OFF");
|
||||
} else if (memcmp (config, "radio ", 6) == 0) {
|
||||
strcpy (tmp, &config[6]);
|
||||
const char *parts[4];
|
||||
int num = mesh::Utils::parseTextParts (tmp, parts, 4);
|
||||
float freq = num > 0 ? strtof (parts[0], nullptr) : 0.0f;
|
||||
float bw = num > 1 ? strtof (parts[1], nullptr) : 0.0f;
|
||||
uint8_t sf = num > 2 ? atoi (parts[2]) : 0;
|
||||
uint8_t cr = num > 3 ? atoi (parts[3]) : 0;
|
||||
if (freq >= 300.0f && freq <= 2500.0f && sf >= 5 && sf <= 12 && cr >= 5 && cr <= 8 && bw >= 7.0f && bw <= 500.0f) {
|
||||
_prefs->sf = sf;
|
||||
_prefs->cr = cr;
|
||||
_prefs->freq = freq;
|
||||
_prefs->bw = bw;
|
||||
_callbacks->savePrefs();
|
||||
strcpy (reply, "OK - reboot to apply");
|
||||
} else {
|
||||
strcpy (reply, "Error, invalid radio params");
|
||||
}
|
||||
} else if (memcmp (config, "lat ", 4) == 0) {
|
||||
double lat = atof (&config[4]);
|
||||
lat *= 1000000;
|
||||
persistent.latitude = lat;
|
||||
// savePrefs();
|
||||
strcpy (reply, "OK");
|
||||
} else if (memcmp (config, "lon ", 4) == 0) {
|
||||
double lon = atof (&config[4]);
|
||||
lon *= 1000000;
|
||||
persistent.longitude = lon;
|
||||
// savePrefs();
|
||||
strcpy (reply, "OK");
|
||||
} else if (memcmp (config, "rxdelay ", 8) == 0) {
|
||||
float db = atof (&config[8]);
|
||||
if (db >= 0) {
|
||||
_prefs->rx_delay_base = db;
|
||||
savePrefs();
|
||||
strcpy (reply, "OK");
|
||||
} else {
|
||||
strcpy (reply, "Error, cannot be negative");
|
||||
}
|
||||
} else if (memcmp (config, "txdelay ", 8) == 0) {
|
||||
float f = atof (&config[8]);
|
||||
if (f >= 0) {
|
||||
_prefs->tx_delay_factor = f;
|
||||
savePrefs();
|
||||
strcpy (reply, "OK");
|
||||
} else {
|
||||
strcpy (reply, "Error, cannot be negative");
|
||||
}
|
||||
} else if (memcmp (config, "flood.max ", 10) == 0) {
|
||||
uint8_t m = atoi (&config[10]);
|
||||
if (m <= 64) {
|
||||
_prefs->flood_max = m;
|
||||
savePrefs();
|
||||
strcpy (reply, "OK");
|
||||
} else {
|
||||
strcpy (reply, "Error, max 64");
|
||||
}
|
||||
} else if (memcmp (config, "direct.txdelay ", 15) == 0) {
|
||||
float f = atof (&config[15]);
|
||||
if (f >= 0) {
|
||||
_prefs->direct_tx_delay_factor = f;
|
||||
savePrefs();
|
||||
strcpy (reply, "OK");
|
||||
} else {
|
||||
strcpy (reply, "Error, cannot be negative");
|
||||
}
|
||||
} else if (memcmp (config, "tx ", 3) == 0) {
|
||||
_prefs->tx_power_dbm = atoi (&config[3]);
|
||||
savePrefs();
|
||||
_callbacks->setTxPower (_prefs->tx_power_dbm);
|
||||
strcpy (reply, "OK");
|
||||
} else if (memcmp (config, "freq ", 5) == 0) {
|
||||
double freq = atof (&config[5]);
|
||||
uint32_t newFreq = mhzToHzLimited (persistent.frequencyInHz);
|
||||
if (newFreq != 0) {
|
||||
persistent.frequencyInHz = newFreq;
|
||||
}
|
||||
// savePrefs();
|
||||
strcpy (reply, "OK - reboot to apply");
|
||||
} else if (memcmp (config, "adc.multiplier ", 15) == 0) {
|
||||
persistent.adcMultiplier = atof (&config[15]);
|
||||
if (persistent.adcMultiplier == 0.0f) {
|
||||
strcpy (reply, "OK - using default board multiplier");
|
||||
} else {
|
||||
sprintf (reply, "OK - multiplier set to %.3f", persistent.adcMultiplier);
|
||||
}
|
||||
// savePrefs();
|
||||
} else {
|
||||
sprintf (reply, "unknown config: %s", config);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ---------------- Stats ---------------- */
|
||||
else if (STR_EQ_LIT (cmd, "stats-packets")) {
|
||||
sprintf (reply,
|
||||
"{\"recv\":%u,\"sent\":%u,\"flood_tx\":%u,\"direct_tx\":%u,\"flood_rx\":%u,\"direct_rx\":%u}",
|
||||
stats.packetsReceivedCount,
|
||||
stats.packetsSentCount,
|
||||
stats.sentFloodCount,
|
||||
stats.sentDirectCount,
|
||||
stats.receivedFloodCount,
|
||||
stats.receivedDirectCount);
|
||||
} else if (STR_EQ_LIT (cmd, "stats-radio")) {
|
||||
sprintf (reply,
|
||||
"{\"noise_floor\":%d,\"last_rssi\":%d,\"last_snr\":%.2f,\"tx_air_secs\":%u,\"rx_air_secs\":%u}",
|
||||
stats.noiseFloor,
|
||||
stats.lastRSSI,
|
||||
stats.lastSNR / 4.0,
|
||||
stats.totalAirTimeSeconds,
|
||||
stats.total_rx_air_time_secs);
|
||||
} else if (STR_EQ_LIT (cmd, "stats-core")) {
|
||||
stats.totalUpTimeSeconds = RTC_GetCounter() - startupTime;
|
||||
stats.totalAirTimeSeconds = TICKS_TO_MS (tickAirtime / 1000);
|
||||
sprintf (reply,
|
||||
"{\"battery_mv\":%u,\"uptime_secs\":%u,\"errors\":%u,\"queue_len\":%u}",
|
||||
getVoltage(),
|
||||
stats.totalUpTimeSeconds,
|
||||
stats.err_events,
|
||||
stats.txQueueLength);
|
||||
}
|
||||
|
||||
/* ---------------- Unknown ---------------- */
|
||||
else {
|
||||
strcpy ((char *)reply, "Unknown command");
|
||||
}
|
||||
|
||||
sendEncryptedTextMessage (remNode, &replyPayload);
|
||||
}
|
||||
|
||||
@@ -8,18 +8,22 @@
|
||||
#include <string.h>
|
||||
|
||||
|
||||
void sendEncryptedFrame (NodeEntry *targetNode, uint8_t payloadType, const uint8_t *plain, size_t plainLen);
|
||||
void sendEncryptedFrame (const NodeEntry *targetNode, uint8_t payloadType, const uint8_t *plain, size_t plainLen);
|
||||
|
||||
void sendEncryptedTextMessage (NodeEntry *targetNode, const PlainTextMessagePayload *msg);
|
||||
void sendEncryptedTextMessage (const NodeEntry *targetNode, const PlainTextMessagePayload *msg);
|
||||
|
||||
void sendEncryptedResponse (NodeEntry *targetNode, const Response *resp);
|
||||
void sendEncryptedResponse (const NodeEntry *targetNode, const Response *resp);
|
||||
|
||||
void sendEncryptedRequest (NodeEntry *targetNode, const Request *req);
|
||||
void sendEncryptedRequest (const NodeEntry *targetNode, const Request *req);
|
||||
|
||||
void sendEncryptedPathPayload (NodeEntry *targetNode, const ReturnedPathPayload *path);
|
||||
void sendEncryptedPathPayload (const NodeEntry *targetNode, const ReturnedPathPayload *path);
|
||||
|
||||
void decodeEncryptedPayload (const FrameStruct *frame);
|
||||
|
||||
void parseEncryptedPayload (const EncryptedPayloadStruct * enc);
|
||||
void parseEncryptedPayload (const EncryptedPayloadStruct *enc);
|
||||
|
||||
void processCommand(char * cmd, NodeEntry * remNode);
|
||||
|
||||
void sendPathBack (const NodeEntry *node, const Path *path);
|
||||
|
||||
#endif
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
void sendGroupMessage (const GroupTextMessage *msg) {
|
||||
// Prepare values locally instead of modifying msg
|
||||
uint8_t channelHash = persistent.aesKeys[msg->keyIndex][0];
|
||||
Channel *channel = &(persistent.channels[msg->keyIndex]);
|
||||
uint8_t flags = 0;
|
||||
int32_t timestamp = RTC_GetCounter();
|
||||
|
||||
@@ -19,7 +19,7 @@ void sendGroupMessage (const GroupTextMessage *msg) {
|
||||
frame.header = ROUTE_TYPE_FLOOD | PAYLOAD_TYPE_GRP_TXT | PAYLOAD_VERSION_0;
|
||||
frame.path.pathLen = 0;
|
||||
size_t offset = 0;
|
||||
frame.payload[offset++] = channelHash;
|
||||
frame.payload[offset++] = channel->hash;
|
||||
|
||||
// Build encryption buffer directly on stack (no extra large buffer)
|
||||
uint8_t buf[180]; // enough for timestamp + flags + text
|
||||
@@ -41,10 +41,13 @@ void sendGroupMessage (const GroupTextMessage *msg) {
|
||||
|
||||
// Encrypt and MAC directly into frame payload after channelHash
|
||||
size_t olen = 0;
|
||||
encrypt_then_mac (&persistent.aesKeys[msg->keyIndex][1], 16, buf, buf_offset, &frame.payload[offset], &olen);
|
||||
|
||||
encrypt_then_mac (channel->key, 16, buf, buf_offset, &frame.payload[offset], &olen);
|
||||
|
||||
frame.payloadLen = olen + 1; // +1 for channelHash
|
||||
|
||||
channel->timestamp = timestamp;
|
||||
|
||||
LoRaTransmit (&frame);
|
||||
}
|
||||
|
||||
@@ -70,43 +73,35 @@ void decodeGroupMessage (const FrameStruct *frame) {
|
||||
unsigned char tmp[184];
|
||||
|
||||
|
||||
unsigned char decrypted = 0;
|
||||
for (unsigned char i = 0; i < AESKeyCount; i++) {
|
||||
Channel *channel = NULL;
|
||||
|
||||
if (msg.channelHash != persistent.aesKeys[i][0]) {
|
||||
MESH_LOGW (TAG, "Hash %d does not equal %d", persistent.aesKeys[i][0], msg.channelHash);
|
||||
uint8_t i = 0;
|
||||
do {
|
||||
channel = getChannel (msg.channelHash, i);
|
||||
if (channel == NULL) {
|
||||
MESH_LOGW (TAG, "Channel hash %d not found", msg.channelHash);
|
||||
return;
|
||||
}
|
||||
if (mac_then_decrypt (channel->key, 16, frame->payload + index, frame->payloadLen - index, tmp) != 0) {
|
||||
MESH_LOGW (TAG, "HMAC failed on grouphash key %d", msg.channelHash);
|
||||
i++;
|
||||
continue;
|
||||
} else {
|
||||
unsigned char plaintextLen = frame->payloadLen - index;
|
||||
index = 0;
|
||||
|
||||
memcpy (&msg.timestamp, tmp + index, 4);
|
||||
index += 4;
|
||||
msg.flags = tmp[index++];
|
||||
|
||||
memcpy (msg.text, tmp + index, plaintextLen - index);
|
||||
|
||||
channel->timestamp = RTC_GetCounter();
|
||||
|
||||
printf ("Message from channel %s: %s\n", channel->name, msg.text);
|
||||
break;
|
||||
}
|
||||
|
||||
MESH_LOGW (TAG, "Hash does equal %d", msg.channelHash);
|
||||
|
||||
if (mac_then_decrypt (persistent.aesKeys[i] + 1, 16, frame->payload + index, frame->payloadLen - index, tmp) != 0) {
|
||||
MESH_LOGW (TAG, "HMAC failed on grouphash key %d not matching %d", persistent.aesKeys[i][0], msg.channelHash);
|
||||
continue;
|
||||
}
|
||||
hexdump ("RxDumpDec", tmp, frame->payloadLen - index);
|
||||
decrypted = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (!decrypted) {
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned char plaintextLen = frame->payloadLen - index;
|
||||
index = 0;
|
||||
|
||||
memcpy (&msg.timestamp, tmp + index, 4);
|
||||
index += 4;
|
||||
msg.flags = tmp[index++];
|
||||
|
||||
memcpy (msg.text, tmp + index, plaintextLen - index);
|
||||
|
||||
printGroupMessage (&msg);
|
||||
}
|
||||
|
||||
void printGroupMessage (const GroupTextMessage *msg) {
|
||||
printf ("Message with channel hash %d, flags %d: %s\n", msg->channelHash,
|
||||
msg->flags, msg->text);
|
||||
} while (channel != NULL);
|
||||
}
|
||||
@@ -4,12 +4,10 @@
|
||||
#include "stdint.h"
|
||||
#include "meshcore/packetstructs.h"
|
||||
|
||||
void sendGroupMessage (const GroupTextMessage * msg);
|
||||
void sendGroupMessage (const GroupTextMessage *msg);
|
||||
|
||||
void makeSendGroupMessage (char *txt, uint8_t keyIndex);
|
||||
|
||||
void decodeGroupMessage (const FrameStruct * frame);
|
||||
|
||||
void printGroupMessage (const GroupTextMessage * msg);
|
||||
void decodeGroupMessage (const FrameStruct *frame);
|
||||
|
||||
#endif
|
||||
@@ -2,5 +2,4 @@
|
||||
#define TRACE_HEADER
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -18,9 +18,16 @@
|
||||
#define PERM_ACL_READ_WRITE 2
|
||||
#define PERM_ACL_ADMIN 3
|
||||
|
||||
#define NODE_ENTRY_FAV_FLAG (1 << 0)
|
||||
|
||||
|
||||
#define MAX_PATH_LEN 64
|
||||
|
||||
|
||||
#define TXT_TYPE_PLAIN 0 // a plain text message
|
||||
#define TXT_TYPE_CLI_DATA 1 // a CLI command
|
||||
#define TXT_TYPE_SIGNED_PLAIN 2 // plain text, signed by sender
|
||||
|
||||
typedef enum RouteType {
|
||||
ROUTE_TYPE_TRANSPORT_FLOOD = 0x00,
|
||||
ROUTE_TYPE_FLOOD = 0x01,
|
||||
@@ -126,14 +133,14 @@ typedef struct {
|
||||
int32_t gps_longitude;
|
||||
|
||||
Path path;
|
||||
|
||||
|
||||
uint8_t flags;
|
||||
uint8_t type;
|
||||
|
||||
uint8_t authenticated;
|
||||
|
||||
uint32_t last_seen_rt; //remote timestamp
|
||||
uint32_t last_seen_lt; //local timestamp
|
||||
|
||||
uint32_t last_seen_rt; // remote timestamp
|
||||
uint32_t last_seen_lt; // local timestamp
|
||||
|
||||
uint32_t sync_timestamp;
|
||||
} NodeEntry;
|
||||
@@ -146,6 +153,8 @@ typedef struct EncryptedPayloadStruct {
|
||||
uint8_t payload[180];
|
||||
uint8_t type;
|
||||
NodeEntry *remNode;
|
||||
const Path *path;
|
||||
const FrameStruct *origFrame;
|
||||
} EncryptedPayloadStruct;
|
||||
|
||||
typedef enum NodeType {
|
||||
@@ -229,7 +238,10 @@ typedef struct RepeaterStats {
|
||||
} RepeaterStats;
|
||||
|
||||
typedef struct Channel {
|
||||
|
||||
char name[32];
|
||||
uint8_t key[16];
|
||||
uint8_t hash;
|
||||
int32_t timestamp;
|
||||
} Channel;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -29,6 +29,67 @@ void LoRaError (int error) {
|
||||
}
|
||||
}
|
||||
|
||||
// Convert bandwidth constant to float in kHz
|
||||
float loraBwToFloat(uint8_t bw) {
|
||||
switch (bw) {
|
||||
case SX126X_LORA_BW_7_8: return 7.8f;
|
||||
case SX126X_LORA_BW_10_4: return 10.4f;
|
||||
case SX126X_LORA_BW_15_6: return 15.6f;
|
||||
case SX126X_LORA_BW_20_8: return 20.8f;
|
||||
case SX126X_LORA_BW_31_25: return 31.25f;
|
||||
case SX126X_LORA_BW_41_7: return 41.7f;
|
||||
case SX126X_LORA_BW_62_5: return 62.5f;
|
||||
case SX126X_LORA_BW_125_0: return 125.0f;
|
||||
case SX126X_LORA_BW_250_0: return 250.0f;
|
||||
case SX126X_LORA_BW_500_0: return 500.0f;
|
||||
default: return 0.0f; // unknown
|
||||
}
|
||||
}
|
||||
|
||||
// Convert float bandwidth (kHz) to constant
|
||||
uint8_t floatToLoraBw(float bw) {
|
||||
if (bw == 7.8f) return SX126X_LORA_BW_7_8;
|
||||
if (bw == 10.4f) return SX126X_LORA_BW_10_4;
|
||||
if (bw == 15.6f) return SX126X_LORA_BW_15_6;
|
||||
if (bw == 20.8f) return SX126X_LORA_BW_20_8;
|
||||
if (bw == 31.25f) return SX126X_LORA_BW_31_25;
|
||||
if (bw == 41.7f) return SX126X_LORA_BW_41_7;
|
||||
if (bw == 62.5f) return SX126X_LORA_BW_62_5;
|
||||
if (bw == 125.0f) return SX126X_LORA_BW_125_0;
|
||||
if (bw == 250.0f) return SX126X_LORA_BW_250_0;
|
||||
if (bw == 500.0f) return SX126X_LORA_BW_500_0;
|
||||
return 0xFF; // invalid
|
||||
}
|
||||
|
||||
// Convert coding rate constant to float
|
||||
float loraCrToFloat(uint8_t cr) {
|
||||
switch (cr) {
|
||||
case SX126X_LORA_CR_4_5: return 4.0f / 5.0f;
|
||||
case SX126X_LORA_CR_4_6: return 4.0f / 6.0f;
|
||||
case SX126X_LORA_CR_4_7: return 4.0f / 7.0f;
|
||||
case SX126X_LORA_CR_4_8: return 4.0f / 8.0f;
|
||||
default: return 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert float coding rate to constant
|
||||
uint8_t floatToLoraCr(float cr) {
|
||||
if (cr == 4.0f / 5.0f) return SX126X_LORA_CR_4_5;
|
||||
if (cr == 4.0f / 6.0f) return SX126X_LORA_CR_4_6;
|
||||
if (cr == 4.0f / 7.0f) return SX126X_LORA_CR_4_7;
|
||||
if (cr == 4.0f / 8.0f) return SX126X_LORA_CR_4_8;
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
// Convert MHz to Hz with limit check
|
||||
uint32_t mhzToHzLimited(double freqMHz) {
|
||||
double freqHz = freqMHz * 1000000.0;
|
||||
if (freqHz > 860000000.0 && freqHz < 880000000.0) {
|
||||
return (uint32_t)freqHz;
|
||||
}
|
||||
return 0; // out of range
|
||||
}
|
||||
|
||||
void LoRaInit (void) {
|
||||
|
||||
txActive = 0;
|
||||
@@ -637,8 +698,8 @@ void SetTx (uint32_t timeoutInMs) {
|
||||
}
|
||||
if (debugPrint) {
|
||||
MESH_LOGI (TAG, "SetTx timeoutInMs=%d"
|
||||
" tout=%d",
|
||||
timeoutInMs, tout);
|
||||
" tout=%d",
|
||||
timeoutInMs, tout);
|
||||
}
|
||||
buf[0] = (uint8_t)((tout >> 16) & 0xFF);
|
||||
buf[1] = (uint8_t)((tout >> 8) & 0xFF);
|
||||
|
||||
759
User/sx1262.h
759
User/sx1262.h
@@ -1,434 +1,449 @@
|
||||
#ifndef _RA01S_H
|
||||
#define _RA01S_H
|
||||
|
||||
//return values
|
||||
#define ERR_NONE 0
|
||||
#define ERR_PACKET_TOO_LONG 1
|
||||
#define ERR_UNKNOWN 2
|
||||
#define ERR_TX_TIMEOUT 3
|
||||
#define ERR_RX_TIMEOUT 4
|
||||
#define ERR_CRC_MISMATCH 5
|
||||
#define ERR_WRONG_MODEM 6
|
||||
#define ERR_INVALID_BANDWIDTH 7
|
||||
#define ERR_INVALID_SPREADING_FACTOR 8
|
||||
#define ERR_INVALID_CODING_RATE 9
|
||||
// return values
|
||||
#define ERR_NONE 0
|
||||
#define ERR_PACKET_TOO_LONG 1
|
||||
#define ERR_UNKNOWN 2
|
||||
#define ERR_TX_TIMEOUT 3
|
||||
#define ERR_RX_TIMEOUT 4
|
||||
#define ERR_CRC_MISMATCH 5
|
||||
#define ERR_WRONG_MODEM 6
|
||||
#define ERR_INVALID_BANDWIDTH 7
|
||||
#define ERR_INVALID_SPREADING_FACTOR 8
|
||||
#define ERR_INVALID_CODING_RATE 9
|
||||
#define ERR_INVALID_FREQUENCY_DEVIATION 10
|
||||
#define ERR_INVALID_BIT_RATE 11
|
||||
#define ERR_INVALID_RX_BANDWIDTH 12
|
||||
#define ERR_INVALID_DATA_SHAPING 13
|
||||
#define ERR_INVALID_SYNC_WORD 14
|
||||
#define ERR_INVALID_OUTPUT_POWER 15
|
||||
#define ERR_INVALID_MODE 16
|
||||
#define ERR_INVALID_TRANCEIVER 17
|
||||
#define ERR_INVALID_SETRX_STATE 18
|
||||
#define ERR_INVALID_SETTX_STATE 19
|
||||
#define ERR_IDLE_TIMEOUT 20
|
||||
#define ERR_SPI_TRANSACTION 21
|
||||
#define ERR_INVALID_BIT_RATE 11
|
||||
#define ERR_INVALID_RX_BANDWIDTH 12
|
||||
#define ERR_INVALID_DATA_SHAPING 13
|
||||
#define ERR_INVALID_SYNC_WORD 14
|
||||
#define ERR_INVALID_OUTPUT_POWER 15
|
||||
#define ERR_INVALID_MODE 16
|
||||
#define ERR_INVALID_TRANCEIVER 17
|
||||
#define ERR_INVALID_SETRX_STATE 18
|
||||
#define ERR_INVALID_SETTX_STATE 19
|
||||
#define ERR_IDLE_TIMEOUT 20
|
||||
#define ERR_SPI_TRANSACTION 21
|
||||
|
||||
// SX126X physical layer properties
|
||||
#define XTAL_FREQ ( double )32000000
|
||||
#define FREQ_DIV ( double )pow( 2.0, 25.0 )
|
||||
#define FREQ_STEP ( double )( XTAL_FREQ / FREQ_DIV )
|
||||
#define XTAL_FREQ (double)32000000
|
||||
#define FREQ_DIV (double)pow (2.0, 25.0)
|
||||
#define FREQ_STEP (double)(XTAL_FREQ / FREQ_DIV)
|
||||
|
||||
#define LOW 0
|
||||
#define HIGH 1
|
||||
#define BUSY_WAIT 5000
|
||||
#define LOW 0
|
||||
#define HIGH 1
|
||||
#define BUSY_WAIT 5000
|
||||
|
||||
// SX126X Model
|
||||
#define SX1261_TRANCEIVER 0x01
|
||||
#define SX1262_TRANCEIVER 0x02
|
||||
#define SX1268_TRANCEIVER 0x08
|
||||
#define SX1261_TRANCEIVER 0x01
|
||||
#define SX1262_TRANCEIVER 0x02
|
||||
#define SX1268_TRANCEIVER 0x08
|
||||
|
||||
// SX126X SPI commands
|
||||
// operational modes commands
|
||||
#define SX126X_CMD_NOP 0x00
|
||||
#define SX126X_CMD_SET_SLEEP 0x84
|
||||
#define SX126X_CMD_SET_STANDBY 0x80
|
||||
#define SX126X_CMD_SET_FS 0xC1
|
||||
#define SX126X_CMD_SET_TX 0x83
|
||||
#define SX126X_CMD_SET_RX 0x82
|
||||
#define SX126X_CMD_STOP_TIMER_ON_PREAMBLE 0x9F
|
||||
#define SX126X_CMD_SET_RX_DUTY_CYCLE 0x94
|
||||
#define SX126X_CMD_SET_CAD 0xC5
|
||||
#define SX126X_CMD_SET_TX_CONTINUOUS_WAVE 0xD1
|
||||
#define SX126X_CMD_SET_TX_INFINITE_PREAMBLE 0xD2
|
||||
#define SX126X_CMD_SET_REGULATOR_MODE 0x96
|
||||
#define SX126X_CMD_CALIBRATE 0x89
|
||||
#define SX126X_CMD_CALIBRATE_IMAGE 0x98
|
||||
#define SX126X_CMD_SET_PA_CONFIG 0x95
|
||||
#define SX126X_CMD_SET_RX_TX_FALLBACK_MODE 0x93
|
||||
#define SX126X_CMD_NOP 0x00
|
||||
#define SX126X_CMD_SET_SLEEP 0x84
|
||||
#define SX126X_CMD_SET_STANDBY 0x80
|
||||
#define SX126X_CMD_SET_FS 0xC1
|
||||
#define SX126X_CMD_SET_TX 0x83
|
||||
#define SX126X_CMD_SET_RX 0x82
|
||||
#define SX126X_CMD_STOP_TIMER_ON_PREAMBLE 0x9F
|
||||
#define SX126X_CMD_SET_RX_DUTY_CYCLE 0x94
|
||||
#define SX126X_CMD_SET_CAD 0xC5
|
||||
#define SX126X_CMD_SET_TX_CONTINUOUS_WAVE 0xD1
|
||||
#define SX126X_CMD_SET_TX_INFINITE_PREAMBLE 0xD2
|
||||
#define SX126X_CMD_SET_REGULATOR_MODE 0x96
|
||||
#define SX126X_CMD_CALIBRATE 0x89
|
||||
#define SX126X_CMD_CALIBRATE_IMAGE 0x98
|
||||
#define SX126X_CMD_SET_PA_CONFIG 0x95
|
||||
#define SX126X_CMD_SET_RX_TX_FALLBACK_MODE 0x93
|
||||
|
||||
// register and buffer access commands
|
||||
#define SX126X_CMD_WRITE_REGISTER 0x0D
|
||||
#define SX126X_CMD_READ_REGISTER 0x1D
|
||||
#define SX126X_CMD_WRITE_BUFFER 0x0E
|
||||
#define SX126X_CMD_READ_BUFFER 0x1E
|
||||
#define SX126X_CMD_WRITE_REGISTER 0x0D
|
||||
#define SX126X_CMD_READ_REGISTER 0x1D
|
||||
#define SX126X_CMD_WRITE_BUFFER 0x0E
|
||||
#define SX126X_CMD_READ_BUFFER 0x1E
|
||||
|
||||
// DIO and IRQ control
|
||||
#define SX126X_CMD_SET_DIO_IRQ_PARAMS 0x08
|
||||
#define SX126X_CMD_GET_IRQ_STATUS 0x12
|
||||
#define SX126X_CMD_CLEAR_IRQ_STATUS 0x02
|
||||
#define SX126X_CMD_SET_DIO2_AS_RF_SWITCH_CTRL 0x9D
|
||||
#define SX126X_CMD_SET_DIO3_AS_TCXO_CTRL 0x97
|
||||
#define SX126X_CMD_SET_DIO_IRQ_PARAMS 0x08
|
||||
#define SX126X_CMD_GET_IRQ_STATUS 0x12
|
||||
#define SX126X_CMD_CLEAR_IRQ_STATUS 0x02
|
||||
#define SX126X_CMD_SET_DIO2_AS_RF_SWITCH_CTRL 0x9D
|
||||
#define SX126X_CMD_SET_DIO3_AS_TCXO_CTRL 0x97
|
||||
|
||||
// RF, modulation and packet commands
|
||||
#define SX126X_CMD_SET_RF_FREQUENCY 0x86
|
||||
#define SX126X_CMD_SET_PACKET_TYPE 0x8A
|
||||
#define SX126X_CMD_GET_PACKET_TYPE 0x11
|
||||
#define SX126X_CMD_SET_TX_PARAMS 0x8E
|
||||
#define SX126X_CMD_SET_MODULATION_PARAMS 0x8B
|
||||
#define SX126X_CMD_SET_PACKET_PARAMS 0x8C
|
||||
#define SX126X_CMD_SET_CAD_PARAMS 0x88
|
||||
#define SX126X_CMD_SET_BUFFER_BASE_ADDRESS 0x8F
|
||||
#define SX126X_CMD_SET_LORA_SYMB_NUM_TIMEOUT 0xA0
|
||||
#define SX126X_CMD_SET_RF_FREQUENCY 0x86
|
||||
#define SX126X_CMD_SET_PACKET_TYPE 0x8A
|
||||
#define SX126X_CMD_GET_PACKET_TYPE 0x11
|
||||
#define SX126X_CMD_SET_TX_PARAMS 0x8E
|
||||
#define SX126X_CMD_SET_MODULATION_PARAMS 0x8B
|
||||
#define SX126X_CMD_SET_PACKET_PARAMS 0x8C
|
||||
#define SX126X_CMD_SET_CAD_PARAMS 0x88
|
||||
#define SX126X_CMD_SET_BUFFER_BASE_ADDRESS 0x8F
|
||||
#define SX126X_CMD_SET_LORA_SYMB_NUM_TIMEOUT 0xA0
|
||||
|
||||
#define SX126X_PA_CONFIG_SX1261 0x01
|
||||
#define SX126X_PA_CONFIG_SX1262 0x00
|
||||
#define SX126X_PA_CONFIG_SX1261 0x01
|
||||
#define SX126X_PA_CONFIG_SX1262 0x00
|
||||
|
||||
// status commands
|
||||
#define SX126X_CMD_GET_STATUS 0xC0
|
||||
#define SX126X_CMD_GET_RSSI_INST 0x15
|
||||
#define SX126X_CMD_GET_RX_BUFFER_STATUS 0x13
|
||||
#define SX126X_CMD_GET_PACKET_STATUS 0x14
|
||||
#define SX126X_CMD_GET_DEVICE_ERRORS 0x17
|
||||
#define SX126X_CMD_CLEAR_DEVICE_ERRORS 0x07
|
||||
#define SX126X_CMD_GET_STATS 0x10
|
||||
#define SX126X_CMD_RESET_STATS 0x00
|
||||
#define SX126X_CMD_GET_STATUS 0xC0
|
||||
#define SX126X_CMD_GET_RSSI_INST 0x15
|
||||
#define SX126X_CMD_GET_RX_BUFFER_STATUS 0x13
|
||||
#define SX126X_CMD_GET_PACKET_STATUS 0x14
|
||||
#define SX126X_CMD_GET_DEVICE_ERRORS 0x17
|
||||
#define SX126X_CMD_CLEAR_DEVICE_ERRORS 0x07
|
||||
#define SX126X_CMD_GET_STATS 0x10
|
||||
#define SX126X_CMD_RESET_STATS 0x00
|
||||
|
||||
|
||||
// SX126X register map
|
||||
#define SX126X_REG_HOPPING_ENABLE 0x0385
|
||||
#define SX126X_REG_PACKECT_LENGTH 0x0386
|
||||
#define SX126X_REG_NB_HOPPING_BLOCKS 0x0387
|
||||
#define SX126X_REG_NB_SYMBOLS0 0x0388
|
||||
#define SX126X_REG_FREQ0 0x038A
|
||||
#define SX126X_REG_NB_SYMBOLS15 0x03E2
|
||||
#define SX126X_REG_FREQ15 0x03E4
|
||||
#define SX126X_REG_DIOX_OUTPUT_ENABLE 0x0580
|
||||
#define SX126X_REG_DIOX_INPUT_ENABLE 0x0583
|
||||
#define SX126X_REG_DIOX_PILL_UP_CONTROL 0x0584
|
||||
#define SX126X_REG_DIOX_PULL_DOWN_CONTROL 0x0585
|
||||
#define SX126X_REG_WHITENING_INITIAL_MSB 0x06B8
|
||||
#define SX126X_REG_WHITENING_INITIAL_LSB 0x06B9
|
||||
#define SX126X_REG_CRC_INITIAL_MSB 0x06BC
|
||||
#define SX126X_REG_CRC_INITIAL_LSB 0x06BD
|
||||
#define SX126X_REG_CRC_POLYNOMIAL_MSB 0x06BE
|
||||
#define SX126X_REG_CRC_POLYNOMIAL_LSB 0x06BF
|
||||
#define SX126X_REG_SYNC_WORD_0 0x06C0
|
||||
#define SX126X_REG_SYNC_WORD_1 0x06C1
|
||||
#define SX126X_REG_SYNC_WORD_2 0x06C2
|
||||
#define SX126X_REG_SYNC_WORD_3 0x06C3
|
||||
#define SX126X_REG_SYNC_WORD_4 0x06C4
|
||||
#define SX126X_REG_SYNC_WORD_5 0x06C5
|
||||
#define SX126X_REG_SYNC_WORD_6 0x06C6
|
||||
#define SX126X_REG_SYNC_WORD_7 0x06C7
|
||||
#define SX126X_REG_NODE_ADDRESS 0x06CD
|
||||
#define SX126X_REG_BROADCAST_ADDRESS 0x06CE
|
||||
#define SX126X_REG_IQ_POLARITY_SETUP 0x0736
|
||||
#define SX126X_REG_LORA_SYNC_WORD_MSB 0x0740
|
||||
#define SX126X_REG_LORA_SYNC_WORD_LSB 0x0741
|
||||
#define SX126X_REG_RANDOM_NUMBER_0 0x0819
|
||||
#define SX126X_REG_RANDOM_NUMBER_1 0x081A
|
||||
#define SX126X_REG_RANDOM_NUMBER_2 0x081B
|
||||
#define SX126X_REG_RANDOM_NUMBER_3 0x081C
|
||||
#define SX126X_REG_TX_MODULETION 0x0889
|
||||
#define SX126X_REG_RX_GAIN 0x08AC
|
||||
#define SX126X_REG_TX_CLAMP_CONFIG 0x08D8
|
||||
#define SX126X_REG_OCP_CONFIGURATION 0x08E7
|
||||
#define SX126X_REG_RTC_CONTROL 0x0902
|
||||
#define SX126X_REG_XTA_TRIM 0x0911
|
||||
#define SX126X_REG_XTB_TRIM 0x0912
|
||||
#define SX126X_REG_DIO3_OUTPUT_VOLTAGE_CONTROL 0x0920
|
||||
#define SX126X_REG_EVENT_MASK 0x0944
|
||||
#define SX126X_REG_HOPPING_ENABLE 0x0385
|
||||
#define SX126X_REG_PACKECT_LENGTH 0x0386
|
||||
#define SX126X_REG_NB_HOPPING_BLOCKS 0x0387
|
||||
#define SX126X_REG_NB_SYMBOLS0 0x0388
|
||||
#define SX126X_REG_FREQ0 0x038A
|
||||
#define SX126X_REG_NB_SYMBOLS15 0x03E2
|
||||
#define SX126X_REG_FREQ15 0x03E4
|
||||
#define SX126X_REG_DIOX_OUTPUT_ENABLE 0x0580
|
||||
#define SX126X_REG_DIOX_INPUT_ENABLE 0x0583
|
||||
#define SX126X_REG_DIOX_PILL_UP_CONTROL 0x0584
|
||||
#define SX126X_REG_DIOX_PULL_DOWN_CONTROL 0x0585
|
||||
#define SX126X_REG_WHITENING_INITIAL_MSB 0x06B8
|
||||
#define SX126X_REG_WHITENING_INITIAL_LSB 0x06B9
|
||||
#define SX126X_REG_CRC_INITIAL_MSB 0x06BC
|
||||
#define SX126X_REG_CRC_INITIAL_LSB 0x06BD
|
||||
#define SX126X_REG_CRC_POLYNOMIAL_MSB 0x06BE
|
||||
#define SX126X_REG_CRC_POLYNOMIAL_LSB 0x06BF
|
||||
#define SX126X_REG_SYNC_WORD_0 0x06C0
|
||||
#define SX126X_REG_SYNC_WORD_1 0x06C1
|
||||
#define SX126X_REG_SYNC_WORD_2 0x06C2
|
||||
#define SX126X_REG_SYNC_WORD_3 0x06C3
|
||||
#define SX126X_REG_SYNC_WORD_4 0x06C4
|
||||
#define SX126X_REG_SYNC_WORD_5 0x06C5
|
||||
#define SX126X_REG_SYNC_WORD_6 0x06C6
|
||||
#define SX126X_REG_SYNC_WORD_7 0x06C7
|
||||
#define SX126X_REG_NODE_ADDRESS 0x06CD
|
||||
#define SX126X_REG_BROADCAST_ADDRESS 0x06CE
|
||||
#define SX126X_REG_IQ_POLARITY_SETUP 0x0736
|
||||
#define SX126X_REG_LORA_SYNC_WORD_MSB 0x0740
|
||||
#define SX126X_REG_LORA_SYNC_WORD_LSB 0x0741
|
||||
#define SX126X_REG_RANDOM_NUMBER_0 0x0819
|
||||
#define SX126X_REG_RANDOM_NUMBER_1 0x081A
|
||||
#define SX126X_REG_RANDOM_NUMBER_2 0x081B
|
||||
#define SX126X_REG_RANDOM_NUMBER_3 0x081C
|
||||
#define SX126X_REG_TX_MODULETION 0x0889
|
||||
#define SX126X_REG_RX_GAIN 0x08AC
|
||||
#define SX126X_REG_TX_CLAMP_CONFIG 0x08D8
|
||||
#define SX126X_REG_OCP_CONFIGURATION 0x08E7
|
||||
#define SX126X_REG_RTC_CONTROL 0x0902
|
||||
#define SX126X_REG_XTA_TRIM 0x0911
|
||||
#define SX126X_REG_XTB_TRIM 0x0912
|
||||
#define SX126X_REG_DIO3_OUTPUT_VOLTAGE_CONTROL 0x0920
|
||||
#define SX126X_REG_EVENT_MASK 0x0944
|
||||
|
||||
|
||||
// SX126X SPI command variables
|
||||
//SX126X_CMD_SET_SLEEP
|
||||
#define SX126X_SLEEP_START_COLD 0b00000000 // 2 2 sleep mode: cold start, configuration is lost (default)
|
||||
#define SX126X_SLEEP_START_WARM 0b00000100 // 2 2 warm start, configuration is retained
|
||||
#define SX126X_SLEEP_RTC_OFF 0b00000000 // 0 0 wake on RTC timeout: disabled
|
||||
#define SX126X_SLEEP_RTC_ON 0b00000001 // 0 0 enabled
|
||||
// SX126X_CMD_SET_SLEEP
|
||||
#define SX126X_SLEEP_START_COLD 0b00000000 // 2 2 sleep mode: cold start, configuration is lost (default)
|
||||
#define SX126X_SLEEP_START_WARM 0b00000100 // 2 2 warm start, configuration is retained
|
||||
#define SX126X_SLEEP_RTC_OFF 0b00000000 // 0 0 wake on RTC timeout: disabled
|
||||
#define SX126X_SLEEP_RTC_ON 0b00000001 // 0 0 enabled
|
||||
|
||||
//SX126X_CMD_SET_STANDBY
|
||||
#define SX126X_STANDBY_RC 0x00 // 7 0 standby mode: 13 MHz RC oscillator
|
||||
#define SX126X_STANDBY_XOSC 0x01 // 7 0 32 MHz crystal oscillator
|
||||
// SX126X_CMD_SET_STANDBY
|
||||
#define SX126X_STANDBY_RC 0x00 // 7 0 standby mode: 13 MHz RC oscillator
|
||||
#define SX126X_STANDBY_XOSC 0x01 // 7 0 32 MHz crystal oscillator
|
||||
|
||||
//SX126X_CMD_SET_RX
|
||||
#define SX126X_RX_TIMEOUT_NONE 0x000000 // 23 0 Rx timeout duration: no timeout (Rx single mode)
|
||||
#define SX126X_RX_TIMEOUT_INF 0xFFFFFF // 23 0 infinite (Rx continuous mode)
|
||||
// SX126X_CMD_SET_RX
|
||||
#define SX126X_RX_TIMEOUT_NONE 0x000000 // 23 0 Rx timeout duration: no timeout (Rx single mode)
|
||||
#define SX126X_RX_TIMEOUT_INF 0xFFFFFF // 23 0 infinite (Rx continuous mode)
|
||||
|
||||
//SX126X_CMD_STOP_TIMER_ON_PREAMBLE
|
||||
#define SX126X_STOP_ON_PREAMBLE_OFF 0x00 // 7 0 stop timer on: sync word or header (default)
|
||||
#define SX126X_STOP_ON_PREAMBLE_ON 0x01 // 7 0 preamble detection
|
||||
// SX126X_CMD_STOP_TIMER_ON_PREAMBLE
|
||||
#define SX126X_STOP_ON_PREAMBLE_OFF 0x00 // 7 0 stop timer on: sync word or header (default)
|
||||
#define SX126X_STOP_ON_PREAMBLE_ON 0x01 // 7 0 preamble detection
|
||||
|
||||
//SX126X_CMD_SET_REGULATOR_MODE
|
||||
#define SX126X_REGULATOR_LDO 0x00 // 7 0 set regulator mode: LDO (default)
|
||||
#define SX126X_REGULATOR_DC_DC 0x01 // 7 0 DC-DC
|
||||
// SX126X_CMD_SET_REGULATOR_MODE
|
||||
#define SX126X_REGULATOR_LDO 0x00 // 7 0 set regulator mode: LDO (default)
|
||||
#define SX126X_REGULATOR_DC_DC 0x01 // 7 0 DC-DC
|
||||
|
||||
//SX126X_CMD_CALIBRATE
|
||||
#define SX126X_CALIBRATE_IMAGE_OFF 0b00000000 // 6 6 image calibration: disabled
|
||||
#define SX126X_CALIBRATE_IMAGE_ON 0b01000000 // 6 6 enabled
|
||||
#define SX126X_CALIBRATE_ADC_BULK_P_OFF 0b00000000 // 5 5 ADC bulk P calibration: disabled
|
||||
#define SX126X_CALIBRATE_ADC_BULK_P_ON 0b00100000 // 5 5 enabled
|
||||
#define SX126X_CALIBRATE_ADC_BULK_N_OFF 0b00000000 // 4 4 ADC bulk N calibration: disabled
|
||||
#define SX126X_CALIBRATE_ADC_BULK_N_ON 0b00010000 // 4 4 enabled
|
||||
#define SX126X_CALIBRATE_ADC_PULSE_OFF 0b00000000 // 3 3 ADC pulse calibration: disabled
|
||||
#define SX126X_CALIBRATE_ADC_PULSE_ON 0b00001000 // 3 3 enabled
|
||||
#define SX126X_CALIBRATE_PLL_OFF 0b00000000 // 2 2 PLL calibration: disabled
|
||||
#define SX126X_CALIBRATE_PLL_ON 0b00000100 // 2 2 enabled
|
||||
#define SX126X_CALIBRATE_RC13M_OFF 0b00000000 // 1 1 13 MHz RC osc. calibration: disabled
|
||||
#define SX126X_CALIBRATE_RC13M_ON 0b00000010 // 1 1 enabled
|
||||
#define SX126X_CALIBRATE_RC64K_OFF 0b00000000 // 0 0 64 kHz RC osc. calibration: disabled
|
||||
#define SX126X_CALIBRATE_RC64K_ON 0b00000001 // 0 0 enabled
|
||||
// SX126X_CMD_CALIBRATE
|
||||
#define SX126X_CALIBRATE_IMAGE_OFF 0b00000000 // 6 6 image calibration: disabled
|
||||
#define SX126X_CALIBRATE_IMAGE_ON 0b01000000 // 6 6 enabled
|
||||
#define SX126X_CALIBRATE_ADC_BULK_P_OFF 0b00000000 // 5 5 ADC bulk P calibration: disabled
|
||||
#define SX126X_CALIBRATE_ADC_BULK_P_ON 0b00100000 // 5 5 enabled
|
||||
#define SX126X_CALIBRATE_ADC_BULK_N_OFF 0b00000000 // 4 4 ADC bulk N calibration: disabled
|
||||
#define SX126X_CALIBRATE_ADC_BULK_N_ON 0b00010000 // 4 4 enabled
|
||||
#define SX126X_CALIBRATE_ADC_PULSE_OFF 0b00000000 // 3 3 ADC pulse calibration: disabled
|
||||
#define SX126X_CALIBRATE_ADC_PULSE_ON 0b00001000 // 3 3 enabled
|
||||
#define SX126X_CALIBRATE_PLL_OFF 0b00000000 // 2 2 PLL calibration: disabled
|
||||
#define SX126X_CALIBRATE_PLL_ON 0b00000100 // 2 2 enabled
|
||||
#define SX126X_CALIBRATE_RC13M_OFF 0b00000000 // 1 1 13 MHz RC osc. calibration: disabled
|
||||
#define SX126X_CALIBRATE_RC13M_ON 0b00000010 // 1 1 enabled
|
||||
#define SX126X_CALIBRATE_RC64K_OFF 0b00000000 // 0 0 64 kHz RC osc. calibration: disabled
|
||||
#define SX126X_CALIBRATE_RC64K_ON 0b00000001 // 0 0 enabled
|
||||
|
||||
//SX126X_CMD_CALIBRATE_IMAGE
|
||||
#define SX126X_CAL_IMG_430_MHZ_1 0x6B
|
||||
#define SX126X_CAL_IMG_430_MHZ_2 0x6F
|
||||
#define SX126X_CAL_IMG_470_MHZ_1 0x75
|
||||
#define SX126X_CAL_IMG_470_MHZ_2 0x81
|
||||
#define SX126X_CAL_IMG_779_MHZ_1 0xC1
|
||||
#define SX126X_CAL_IMG_779_MHZ_2 0xC5
|
||||
#define SX126X_CAL_IMG_863_MHZ_1 0xD7
|
||||
#define SX126X_CAL_IMG_863_MHZ_2 0xDB
|
||||
#define SX126X_CAL_IMG_902_MHZ_1 0xE1
|
||||
#define SX126X_CAL_IMG_902_MHZ_2 0xE9
|
||||
// SX126X_CMD_CALIBRATE_IMAGE
|
||||
#define SX126X_CAL_IMG_430_MHZ_1 0x6B
|
||||
#define SX126X_CAL_IMG_430_MHZ_2 0x6F
|
||||
#define SX126X_CAL_IMG_470_MHZ_1 0x75
|
||||
#define SX126X_CAL_IMG_470_MHZ_2 0x81
|
||||
#define SX126X_CAL_IMG_779_MHZ_1 0xC1
|
||||
#define SX126X_CAL_IMG_779_MHZ_2 0xC5
|
||||
#define SX126X_CAL_IMG_863_MHZ_1 0xD7
|
||||
#define SX126X_CAL_IMG_863_MHZ_2 0xDB
|
||||
#define SX126X_CAL_IMG_902_MHZ_1 0xE1
|
||||
#define SX126X_CAL_IMG_902_MHZ_2 0xE9
|
||||
|
||||
//SX126X_CMD_SET_PA_CONFIG
|
||||
#define SX126X_PA_CONFIG_HP_MAX 0x07
|
||||
#define SX126X_PA_CONFIG_SX1268 0x01
|
||||
#define SX126X_PA_CONFIG_PA_LUT 0x01
|
||||
// SX126X_CMD_SET_PA_CONFIG
|
||||
#define SX126X_PA_CONFIG_HP_MAX 0x07
|
||||
#define SX126X_PA_CONFIG_SX1268 0x01
|
||||
#define SX126X_PA_CONFIG_PA_LUT 0x01
|
||||
|
||||
//SX126X_CMD_SET_RX_TX_FALLBACK_MODE
|
||||
#define SX126X_RX_TX_FALLBACK_MODE_FS 0x40 // 7 0 after Rx/Tx go to: FS mode
|
||||
#define SX126X_RX_TX_FALLBACK_MODE_STDBY_XOSC 0x30 // 7 0 standby with crystal oscillator
|
||||
#define SX126X_RX_TX_FALLBACK_MODE_STDBY_RC 0x20 // 7 0 standby with RC oscillator (default)
|
||||
// SX126X_CMD_SET_RX_TX_FALLBACK_MODE
|
||||
#define SX126X_RX_TX_FALLBACK_MODE_FS 0x40 // 7 0 after Rx/Tx go to: FS mode
|
||||
#define SX126X_RX_TX_FALLBACK_MODE_STDBY_XOSC 0x30 // 7 0 standby with crystal oscillator
|
||||
#define SX126X_RX_TX_FALLBACK_MODE_STDBY_RC 0x20 // 7 0 standby with RC oscillator (default)
|
||||
|
||||
//SX126X_CMD_SET_DIO_IRQ_PARAMS
|
||||
#define SX126X_IRQ_TIMEOUT 0b1000000000 // 9 9 Rx or Tx timeout
|
||||
#define SX126X_IRQ_CAD_DETECTED 0b0100000000 // 8 8 channel activity detected
|
||||
#define SX126X_IRQ_CAD_DONE 0b0010000000 // 7 7 channel activity detection finished
|
||||
#define SX126X_IRQ_CRC_ERR 0b0001000000 // 6 6 wrong CRC received
|
||||
#define SX126X_IRQ_HEADER_ERR 0b0000100000 // 5 5 LoRa header CRC error
|
||||
#define SX126X_IRQ_HEADER_VALID 0b0000010000 // 4 4 valid LoRa header received
|
||||
#define SX126X_IRQ_SYNC_WORD_VALID 0b0000001000 // 3 3 valid sync word detected
|
||||
#define SX126X_IRQ_PREAMBLE_DETECTED 0b0000000100 // 2 2 preamble detected
|
||||
#define SX126X_IRQ_RX_DONE 0b0000000010 // 1 1 packet received
|
||||
#define SX126X_IRQ_TX_DONE 0b0000000001 // 0 0 packet transmission completed
|
||||
#define SX126X_IRQ_ALL 0b1111111111 // 9 0 all interrupts
|
||||
#define SX126X_IRQ_NONE 0b0000000000 // 9 0 no interrupts
|
||||
// SX126X_CMD_SET_DIO_IRQ_PARAMS
|
||||
#define SX126X_IRQ_TIMEOUT 0b1000000000 // 9 9 Rx or Tx timeout
|
||||
#define SX126X_IRQ_CAD_DETECTED 0b0100000000 // 8 8 channel activity detected
|
||||
#define SX126X_IRQ_CAD_DONE 0b0010000000 // 7 7 channel activity detection finished
|
||||
#define SX126X_IRQ_CRC_ERR 0b0001000000 // 6 6 wrong CRC received
|
||||
#define SX126X_IRQ_HEADER_ERR 0b0000100000 // 5 5 LoRa header CRC error
|
||||
#define SX126X_IRQ_HEADER_VALID 0b0000010000 // 4 4 valid LoRa header received
|
||||
#define SX126X_IRQ_SYNC_WORD_VALID 0b0000001000 // 3 3 valid sync word detected
|
||||
#define SX126X_IRQ_PREAMBLE_DETECTED 0b0000000100 // 2 2 preamble detected
|
||||
#define SX126X_IRQ_RX_DONE 0b0000000010 // 1 1 packet received
|
||||
#define SX126X_IRQ_TX_DONE 0b0000000001 // 0 0 packet transmission completed
|
||||
#define SX126X_IRQ_ALL 0b1111111111 // 9 0 all interrupts
|
||||
#define SX126X_IRQ_NONE 0b0000000000 // 9 0 no interrupts
|
||||
|
||||
//SX126X_CMD_SET_DIO2_AS_RF_SWITCH_CTRL
|
||||
#define SX126X_DIO2_AS_IRQ 0x00 // 7 0 DIO2 configuration: IRQ
|
||||
#define SX126X_DIO2_AS_RF_SWITCH 0x01 // 7 0 RF switch control
|
||||
// SX126X_CMD_SET_DIO2_AS_RF_SWITCH_CTRL
|
||||
#define SX126X_DIO2_AS_IRQ 0x00 // 7 0 DIO2 configuration: IRQ
|
||||
#define SX126X_DIO2_AS_RF_SWITCH 0x01 // 7 0 RF switch control
|
||||
|
||||
//SX126X_CMD_SET_DIO3_AS_TCXO_CTRL
|
||||
#define SX126X_DIO3_OUTPUT_1_6 0x00 // 7 0 DIO3 voltage output for TCXO: 1.6 V
|
||||
#define SX126X_DIO3_OUTPUT_1_7 0x01 // 7 0 1.7 V
|
||||
#define SX126X_DIO3_OUTPUT_1_8 0x02 // 7 0 1.8 V
|
||||
#define SX126X_DIO3_OUTPUT_2_2 0x03 // 7 0 2.2 V
|
||||
#define SX126X_DIO3_OUTPUT_2_4 0x04 // 7 0 2.4 V
|
||||
#define SX126X_DIO3_OUTPUT_2_7 0x05 // 7 0 2.7 V
|
||||
#define SX126X_DIO3_OUTPUT_3_0 0x06 // 7 0 3.0 V
|
||||
#define SX126X_DIO3_OUTPUT_3_3 0x07 // 7 0 3.3 V
|
||||
// SX126X_CMD_SET_DIO3_AS_TCXO_CTRL
|
||||
#define SX126X_DIO3_OUTPUT_1_6 0x00 // 7 0 DIO3 voltage output for TCXO: 1.6 V
|
||||
#define SX126X_DIO3_OUTPUT_1_7 0x01 // 7 0 1.7 V
|
||||
#define SX126X_DIO3_OUTPUT_1_8 0x02 // 7 0 1.8 V
|
||||
#define SX126X_DIO3_OUTPUT_2_2 0x03 // 7 0 2.2 V
|
||||
#define SX126X_DIO3_OUTPUT_2_4 0x04 // 7 0 2.4 V
|
||||
#define SX126X_DIO3_OUTPUT_2_7 0x05 // 7 0 2.7 V
|
||||
#define SX126X_DIO3_OUTPUT_3_0 0x06 // 7 0 3.0 V
|
||||
#define SX126X_DIO3_OUTPUT_3_3 0x07 // 7 0 3.3 V
|
||||
|
||||
//Radio complete Wake-up Time with TCXO stabilisation time
|
||||
#define RADIO_TCXO_SETUP_TIME 5000 // [us]
|
||||
// Radio complete Wake-up Time with TCXO stabilisation time
|
||||
#define RADIO_TCXO_SETUP_TIME 5000 // [us]
|
||||
|
||||
//SX126X_CMD_SET_PACKET_TYPE
|
||||
#define SX126X_PACKET_TYPE_GFSK 0x00 // 7 0 packet type: GFSK
|
||||
#define SX126X_PACKET_TYPE_LORA 0x01 // 7 0 LoRa
|
||||
// SX126X_CMD_SET_PACKET_TYPE
|
||||
#define SX126X_PACKET_TYPE_GFSK 0x00 // 7 0 packet type: GFSK
|
||||
#define SX126X_PACKET_TYPE_LORA 0x01 // 7 0 LoRa
|
||||
|
||||
//SX126X_CMD_SET_TX_PARAMS
|
||||
#define SX126X_PA_RAMP_10U 0x00 // 7 0 ramp time: 10 us
|
||||
#define SX126X_PA_RAMP_20U 0x01 // 7 0 20 us
|
||||
#define SX126X_PA_RAMP_40U 0x02 // 7 0 40 us
|
||||
#define SX126X_PA_RAMP_80U 0x03 // 7 0 80 us
|
||||
#define SX126X_PA_RAMP_200U 0x04 // 7 0 200 us
|
||||
#define SX126X_PA_RAMP_800U 0x05 // 7 0 800 us
|
||||
#define SX126X_PA_RAMP_1700U 0x06 // 7 0 1700 us
|
||||
#define SX126X_PA_RAMP_3400U 0x07 // 7 0 3400 us
|
||||
// SX126X_CMD_SET_TX_PARAMS
|
||||
#define SX126X_PA_RAMP_10U 0x00 // 7 0 ramp time: 10 us
|
||||
#define SX126X_PA_RAMP_20U 0x01 // 7 0 20 us
|
||||
#define SX126X_PA_RAMP_40U 0x02 // 7 0 40 us
|
||||
#define SX126X_PA_RAMP_80U 0x03 // 7 0 80 us
|
||||
#define SX126X_PA_RAMP_200U 0x04 // 7 0 200 us
|
||||
#define SX126X_PA_RAMP_800U 0x05 // 7 0 800 us
|
||||
#define SX126X_PA_RAMP_1700U 0x06 // 7 0 1700 us
|
||||
#define SX126X_PA_RAMP_3400U 0x07 // 7 0 3400 us
|
||||
|
||||
//SX126X_CMD_SET_MODULATION_PARAMS
|
||||
#define SX126X_GFSK_FILTER_NONE 0x00 // 7 0 GFSK filter: none
|
||||
#define SX126X_GFSK_FILTER_GAUSS_0_3 0x08 // 7 0 Gaussian, BT = 0.3
|
||||
#define SX126X_GFSK_FILTER_GAUSS_0_5 0x09 // 7 0 Gaussian, BT = 0.5
|
||||
#define SX126X_GFSK_FILTER_GAUSS_0_7 0x0A // 7 0 Gaussian, BT = 0.7
|
||||
#define SX126X_GFSK_FILTER_GAUSS_1 0x0B // 7 0 Gaussian, BT = 1
|
||||
#define SX126X_GFSK_RX_BW_4_8 0x1F // 7 0 GFSK Rx bandwidth: 4.8 kHz
|
||||
#define SX126X_GFSK_RX_BW_5_8 0x17 // 7 0 5.8 kHz
|
||||
#define SX126X_GFSK_RX_BW_7_3 0x0F // 7 0 7.3 kHz
|
||||
#define SX126X_GFSK_RX_BW_9_7 0x1E // 7 0 9.7 kHz
|
||||
#define SX126X_GFSK_RX_BW_11_7 0x16 // 7 0 11.7 kHz
|
||||
#define SX126X_GFSK_RX_BW_14_6 0x0E // 7 0 14.6 kHz
|
||||
#define SX126X_GFSK_RX_BW_19_5 0x1D // 7 0 19.5 kHz
|
||||
#define SX126X_GFSK_RX_BW_23_4 0x15 // 7 0 23.4 kHz
|
||||
#define SX126X_GFSK_RX_BW_29_3 0x0D // 7 0 29.3 kHz
|
||||
#define SX126X_GFSK_RX_BW_39_0 0x1C // 7 0 39.0 kHz
|
||||
#define SX126X_GFSK_RX_BW_46_9 0x14 // 7 0 46.9 kHz
|
||||
#define SX126X_GFSK_RX_BW_58_6 0x0C // 7 0 58.6 kHz
|
||||
#define SX126X_GFSK_RX_BW_78_2 0x1B // 7 0 78.2 kHz
|
||||
#define SX126X_GFSK_RX_BW_93_8 0x13 // 7 0 93.8 kHz
|
||||
#define SX126X_GFSK_RX_BW_117_3 0x0B // 7 0 117.3 kHz
|
||||
#define SX126X_GFSK_RX_BW_156_2 0x1A // 7 0 156.2 kHz
|
||||
#define SX126X_GFSK_RX_BW_187_2 0x12 // 7 0 187.2 kHz
|
||||
#define SX126X_GFSK_RX_BW_234_3 0x0A // 7 0 234.3 kHz
|
||||
#define SX126X_GFSK_RX_BW_312_0 0x19 // 7 0 312.0 kHz
|
||||
#define SX126X_GFSK_RX_BW_373_6 0x11 // 7 0 373.6 kHz
|
||||
#define SX126X_GFSK_RX_BW_467_0 0x09 // 7 0 467.0 kHz
|
||||
#define SX126X_LORA_BW_7_8 0x00 // 7 0 LoRa bandwidth: 7.8 kHz
|
||||
#define SX126X_LORA_BW_10_4 0x08 // 7 0 10.4 kHz
|
||||
#define SX126X_LORA_BW_15_6 0x01 // 7 0 15.6 kHz
|
||||
#define SX126X_LORA_BW_20_8 0x09 // 7 0 20.8 kHz
|
||||
#define SX126X_LORA_BW_31_25 0x02 // 7 0 31.25 kHz
|
||||
#define SX126X_LORA_BW_41_7 0x0A // 7 0 41.7 kHz
|
||||
#define SX126X_LORA_BW_62_5 0x03 // 7 0 62.5 kHz
|
||||
#define SX126X_LORA_BW_125_0 0x04 // 7 0 125.0 kHz
|
||||
#define SX126X_LORA_BW_250_0 0x05 // 7 0 250.0 kHz
|
||||
#define SX126X_LORA_BW_500_0 0x06 // 7 0 500.0 kHz
|
||||
#define SX126X_LORA_CR_4_5 0x01 // 7 0 LoRa coding rate: 4/5
|
||||
#define SX126X_LORA_CR_4_6 0x02 // 7 0 4/6
|
||||
#define SX126X_LORA_CR_4_7 0x03 // 7 0 4/7
|
||||
#define SX126X_LORA_CR_4_8 0x04 // 7 0 4/8
|
||||
#define SX126X_LORA_LOW_DATA_RATE_OPTIMIZE_OFF 0x00 // 7 0 LoRa low data rate optimization: disabled
|
||||
#define SX126X_LORA_LOW_DATA_RATE_OPTIMIZE_ON 0x01 // 7 0 enabled
|
||||
// SX126X_CMD_SET_MODULATION_PARAMS
|
||||
#define SX126X_GFSK_FILTER_NONE 0x00 // 7 0 GFSK filter: none
|
||||
#define SX126X_GFSK_FILTER_GAUSS_0_3 0x08 // 7 0 Gaussian, BT = 0.3
|
||||
#define SX126X_GFSK_FILTER_GAUSS_0_5 0x09 // 7 0 Gaussian, BT = 0.5
|
||||
#define SX126X_GFSK_FILTER_GAUSS_0_7 0x0A // 7 0 Gaussian, BT = 0.7
|
||||
#define SX126X_GFSK_FILTER_GAUSS_1 0x0B // 7 0 Gaussian, BT = 1
|
||||
#define SX126X_GFSK_RX_BW_4_8 0x1F // 7 0 GFSK Rx bandwidth: 4.8 kHz
|
||||
#define SX126X_GFSK_RX_BW_5_8 0x17 // 7 0 5.8 kHz
|
||||
#define SX126X_GFSK_RX_BW_7_3 0x0F // 7 0 7.3 kHz
|
||||
#define SX126X_GFSK_RX_BW_9_7 0x1E // 7 0 9.7 kHz
|
||||
#define SX126X_GFSK_RX_BW_11_7 0x16 // 7 0 11.7 kHz
|
||||
#define SX126X_GFSK_RX_BW_14_6 0x0E // 7 0 14.6 kHz
|
||||
#define SX126X_GFSK_RX_BW_19_5 0x1D // 7 0 19.5 kHz
|
||||
#define SX126X_GFSK_RX_BW_23_4 0x15 // 7 0 23.4 kHz
|
||||
#define SX126X_GFSK_RX_BW_29_3 0x0D // 7 0 29.3 kHz
|
||||
#define SX126X_GFSK_RX_BW_39_0 0x1C // 7 0 39.0 kHz
|
||||
#define SX126X_GFSK_RX_BW_46_9 0x14 // 7 0 46.9 kHz
|
||||
#define SX126X_GFSK_RX_BW_58_6 0x0C // 7 0 58.6 kHz
|
||||
#define SX126X_GFSK_RX_BW_78_2 0x1B // 7 0 78.2 kHz
|
||||
#define SX126X_GFSK_RX_BW_93_8 0x13 // 7 0 93.8 kHz
|
||||
#define SX126X_GFSK_RX_BW_117_3 0x0B // 7 0 117.3 kHz
|
||||
#define SX126X_GFSK_RX_BW_156_2 0x1A // 7 0 156.2 kHz
|
||||
#define SX126X_GFSK_RX_BW_187_2 0x12 // 7 0 187.2 kHz
|
||||
#define SX126X_GFSK_RX_BW_234_3 0x0A // 7 0 234.3 kHz
|
||||
#define SX126X_GFSK_RX_BW_312_0 0x19 // 7 0 312.0 kHz
|
||||
#define SX126X_GFSK_RX_BW_373_6 0x11 // 7 0 373.6 kHz
|
||||
#define SX126X_GFSK_RX_BW_467_0 0x09 // 7 0 467.0 kHz
|
||||
#define SX126X_LORA_BW_7_8 0x00 // 7 0 LoRa bandwidth: 7.8 kHz
|
||||
#define SX126X_LORA_BW_10_4 0x08 // 7 0 10.4 kHz
|
||||
#define SX126X_LORA_BW_15_6 0x01 // 7 0 15.6 kHz
|
||||
#define SX126X_LORA_BW_20_8 0x09 // 7 0 20.8 kHz
|
||||
#define SX126X_LORA_BW_31_25 0x02 // 7 0 31.25 kHz
|
||||
#define SX126X_LORA_BW_41_7 0x0A // 7 0 41.7 kHz
|
||||
#define SX126X_LORA_BW_62_5 0x03 // 7 0 62.5 kHz
|
||||
#define SX126X_LORA_BW_125_0 0x04 // 7 0 125.0 kHz
|
||||
#define SX126X_LORA_BW_250_0 0x05 // 7 0 250.0 kHz
|
||||
#define SX126X_LORA_BW_500_0 0x06 // 7 0 500.0 kHz
|
||||
#define SX126X_LORA_CR_4_5 0x01 // 7 0 LoRa coding rate: 4/5
|
||||
#define SX126X_LORA_CR_4_6 0x02 // 7 0 4/6
|
||||
#define SX126X_LORA_CR_4_7 0x03 // 7 0 4/7
|
||||
#define SX126X_LORA_CR_4_8 0x04 // 7 0 4/8
|
||||
#define SX126X_LORA_LOW_DATA_RATE_OPTIMIZE_OFF 0x00 // 7 0 LoRa low data rate optimization: disabled
|
||||
#define SX126X_LORA_LOW_DATA_RATE_OPTIMIZE_ON 0x01 // 7 0 enabled
|
||||
|
||||
//SX126X_CMD_SET_PACKET_PARAMS
|
||||
#define SX126X_GFSK_PREAMBLE_DETECT_OFF 0x00 // 7 0 GFSK minimum preamble length before reception starts: detector disabled
|
||||
#define SX126X_GFSK_PREAMBLE_DETECT_8 0x04 // 7 0 8 bits
|
||||
#define SX126X_GFSK_PREAMBLE_DETECT_16 0x05 // 7 0 16 bits
|
||||
#define SX126X_GFSK_PREAMBLE_DETECT_24 0x06 // 7 0 24 bits
|
||||
#define SX126X_GFSK_PREAMBLE_DETECT_32 0x07 // 7 0 32 bits
|
||||
#define SX126X_GFSK_ADDRESS_FILT_OFF 0x00 // 7 0 GFSK address filtering: disabled
|
||||
#define SX126X_GFSK_ADDRESS_FILT_NODE 0x01 // 7 0 node only
|
||||
#define SX126X_GFSK_ADDRESS_FILT_NODE_BROADCAST 0x02 // 7 0 node and broadcast
|
||||
#define SX126X_GFSK_PACKET_FIXED 0x00 // 7 0 GFSK packet type: fixed (payload length known in advance to both sides)
|
||||
#define SX126X_GFSK_PACKET_VARIABLE 0x01 // 7 0 variable (payload length added to packet)
|
||||
#define SX126X_GFSK_CRC_OFF 0x01 // 7 0 GFSK packet CRC: disabled
|
||||
#define SX126X_GFSK_CRC_1_BYTE 0x00 // 7 0 1 byte
|
||||
#define SX126X_GFSK_CRC_2_BYTE 0x02 // 7 0 2 byte
|
||||
#define SX126X_GFSK_CRC_1_BYTE_INV 0x04 // 7 0 1 byte, inverted
|
||||
#define SX126X_GFSK_CRC_2_BYTE_INV 0x06 // 7 0 2 byte, inverted
|
||||
#define SX126X_GFSK_WHITENING_OFF 0x00 // 7 0 GFSK data whitening: disabled
|
||||
#define SX126X_GFSK_WHITENING_ON 0x01 // 7 0 enabled
|
||||
#define SX126X_LORA_HEADER_EXPLICIT 0x00 // 7 0 LoRa header mode: explicit
|
||||
#define SX126X_LORA_HEADER_IMPLICIT 0x01 // 7 0 implicit
|
||||
#define SX126X_LORA_CRC_OFF 0x00 // 7 0 LoRa CRC mode: disabled
|
||||
#define SX126X_LORA_CRC_ON 0x01 // 7 0 enabled
|
||||
#define SX126X_LORA_IQ_STANDARD 0x00 // 7 0 LoRa IQ setup: standard
|
||||
#define SX126X_LORA_IQ_INVERTED 0x01 // 7 0 inverted
|
||||
// SX126X_CMD_SET_PACKET_PARAMS
|
||||
#define SX126X_GFSK_PREAMBLE_DETECT_OFF 0x00 // 7 0 GFSK minimum preamble length before reception starts: detector disabled
|
||||
#define SX126X_GFSK_PREAMBLE_DETECT_8 0x04 // 7 0 8 bits
|
||||
#define SX126X_GFSK_PREAMBLE_DETECT_16 0x05 // 7 0 16 bits
|
||||
#define SX126X_GFSK_PREAMBLE_DETECT_24 0x06 // 7 0 24 bits
|
||||
#define SX126X_GFSK_PREAMBLE_DETECT_32 0x07 // 7 0 32 bits
|
||||
#define SX126X_GFSK_ADDRESS_FILT_OFF 0x00 // 7 0 GFSK address filtering: disabled
|
||||
#define SX126X_GFSK_ADDRESS_FILT_NODE 0x01 // 7 0 node only
|
||||
#define SX126X_GFSK_ADDRESS_FILT_NODE_BROADCAST 0x02 // 7 0 node and broadcast
|
||||
#define SX126X_GFSK_PACKET_FIXED 0x00 // 7 0 GFSK packet type: fixed (payload length known in advance to both sides)
|
||||
#define SX126X_GFSK_PACKET_VARIABLE 0x01 // 7 0 variable (payload length added to packet)
|
||||
#define SX126X_GFSK_CRC_OFF 0x01 // 7 0 GFSK packet CRC: disabled
|
||||
#define SX126X_GFSK_CRC_1_BYTE 0x00 // 7 0 1 byte
|
||||
#define SX126X_GFSK_CRC_2_BYTE 0x02 // 7 0 2 byte
|
||||
#define SX126X_GFSK_CRC_1_BYTE_INV 0x04 // 7 0 1 byte, inverted
|
||||
#define SX126X_GFSK_CRC_2_BYTE_INV 0x06 // 7 0 2 byte, inverted
|
||||
#define SX126X_GFSK_WHITENING_OFF 0x00 // 7 0 GFSK data whitening: disabled
|
||||
#define SX126X_GFSK_WHITENING_ON 0x01 // 7 0 enabled
|
||||
#define SX126X_LORA_HEADER_EXPLICIT 0x00 // 7 0 LoRa header mode: explicit
|
||||
#define SX126X_LORA_HEADER_IMPLICIT 0x01 // 7 0 implicit
|
||||
#define SX126X_LORA_CRC_OFF 0x00 // 7 0 LoRa CRC mode: disabled
|
||||
#define SX126X_LORA_CRC_ON 0x01 // 7 0 enabled
|
||||
#define SX126X_LORA_IQ_STANDARD 0x00 // 7 0 LoRa IQ setup: standard
|
||||
#define SX126X_LORA_IQ_INVERTED 0x01 // 7 0 inverted
|
||||
|
||||
//SX126X_CMD_SET_CAD_PARAMS
|
||||
#define SX126X_CAD_ON_1_SYMB 0x00 // 7 0 number of symbols used for CAD: 1
|
||||
#define SX126X_CAD_ON_2_SYMB 0x01 // 7 0 2
|
||||
#define SX126X_CAD_ON_4_SYMB 0x02 // 7 0 4
|
||||
#define SX126X_CAD_ON_8_SYMB 0x03 // 7 0 8
|
||||
#define SX126X_CAD_ON_16_SYMB 0x04 // 7 0 16
|
||||
#define SX126X_CAD_GOTO_STDBY 0x00 // 7 0 after CAD is done, always go to STDBY_RC mode
|
||||
#define SX126X_CAD_GOTO_RX 0x01 // 7 0 after CAD is done, go to Rx mode if activity is detected
|
||||
// SX126X_CMD_SET_CAD_PARAMS
|
||||
#define SX126X_CAD_ON_1_SYMB 0x00 // 7 0 number of symbols used for CAD: 1
|
||||
#define SX126X_CAD_ON_2_SYMB 0x01 // 7 0 2
|
||||
#define SX126X_CAD_ON_4_SYMB 0x02 // 7 0 4
|
||||
#define SX126X_CAD_ON_8_SYMB 0x03 // 7 0 8
|
||||
#define SX126X_CAD_ON_16_SYMB 0x04 // 7 0 16
|
||||
#define SX126X_CAD_GOTO_STDBY 0x00 // 7 0 after CAD is done, always go to STDBY_RC mode
|
||||
#define SX126X_CAD_GOTO_RX 0x01 // 7 0 after CAD is done, go to Rx mode if activity is detected
|
||||
|
||||
//SX126X_CMD_GET_STATUS
|
||||
#define SX126X_STATUS_MODE_STDBY_RC 0b00100000 // 6 4 current chip mode: STDBY_RC
|
||||
#define SX126X_STATUS_MODE_STDBY_XOSC 0b00110000 // 6 4 STDBY_XOSC
|
||||
#define SX126X_STATUS_MODE_FS 0b01000000 // 6 4 FS
|
||||
#define SX126X_STATUS_MODE_RX 0b01010000 // 6 4 RX
|
||||
#define SX126X_STATUS_MODE_TX 0b01100000 // 6 4 TX
|
||||
#define SX126X_STATUS_DATA_AVAILABLE 0b00000100 // 3 1 command status: packet received and data can be retrieved
|
||||
#define SX126X_STATUS_CMD_TIMEOUT 0b00000110 // 3 1 SPI command timed out
|
||||
#define SX126X_STATUS_CMD_INVALID 0b00001000 // 3 1 invalid SPI command
|
||||
#define SX126X_STATUS_CMD_FAILED 0b00001010 // 3 1 SPI command failed to execute
|
||||
#define SX126X_STATUS_TX_DONE 0b00001100 // 3 1 packet transmission done
|
||||
#define SX126X_STATUS_SPI_FAILED 0b11111111 // 7 0 SPI transaction failed
|
||||
// SX126X_CMD_GET_STATUS
|
||||
#define SX126X_STATUS_MODE_STDBY_RC 0b00100000 // 6 4 current chip mode: STDBY_RC
|
||||
#define SX126X_STATUS_MODE_STDBY_XOSC 0b00110000 // 6 4 STDBY_XOSC
|
||||
#define SX126X_STATUS_MODE_FS 0b01000000 // 6 4 FS
|
||||
#define SX126X_STATUS_MODE_RX 0b01010000 // 6 4 RX
|
||||
#define SX126X_STATUS_MODE_TX 0b01100000 // 6 4 TX
|
||||
#define SX126X_STATUS_DATA_AVAILABLE 0b00000100 // 3 1 command status: packet received and data can be retrieved
|
||||
#define SX126X_STATUS_CMD_TIMEOUT 0b00000110 // 3 1 SPI command timed out
|
||||
#define SX126X_STATUS_CMD_INVALID 0b00001000 // 3 1 invalid SPI command
|
||||
#define SX126X_STATUS_CMD_FAILED 0b00001010 // 3 1 SPI command failed to execute
|
||||
#define SX126X_STATUS_TX_DONE 0b00001100 // 3 1 packet transmission done
|
||||
#define SX126X_STATUS_SPI_FAILED 0b11111111 // 7 0 SPI transaction failed
|
||||
|
||||
//SX126X_CMD_GET_PACKET_STATUS
|
||||
#define SX126X_GFSK_RX_STATUS_PREAMBLE_ERR 0b10000000 // 7 7 GFSK Rx status: preamble error
|
||||
#define SX126X_GFSK_RX_STATUS_SYNC_ERR 0b01000000 // 6 6 sync word error
|
||||
#define SX126X_GFSK_RX_STATUS_ADRS_ERR 0b00100000 // 5 5 address error
|
||||
#define SX126X_GFSK_RX_STATUS_CRC_ERR 0b00010000 // 4 4 CRC error
|
||||
#define SX126X_GFSK_RX_STATUS_LENGTH_ERR 0b00001000 // 3 3 length error
|
||||
#define SX126X_GFSK_RX_STATUS_ABORT_ERR 0b00000100 // 2 2 abort error
|
||||
#define SX126X_GFSK_RX_STATUS_PACKET_RECEIVED 0b00000010 // 2 2 packet received
|
||||
#define SX126X_GFSK_RX_STATUS_PACKET_SENT 0b00000001 // 2 2 packet sent
|
||||
// SX126X_CMD_GET_PACKET_STATUS
|
||||
#define SX126X_GFSK_RX_STATUS_PREAMBLE_ERR 0b10000000 // 7 7 GFSK Rx status: preamble error
|
||||
#define SX126X_GFSK_RX_STATUS_SYNC_ERR 0b01000000 // 6 6 sync word error
|
||||
#define SX126X_GFSK_RX_STATUS_ADRS_ERR 0b00100000 // 5 5 address error
|
||||
#define SX126X_GFSK_RX_STATUS_CRC_ERR 0b00010000 // 4 4 CRC error
|
||||
#define SX126X_GFSK_RX_STATUS_LENGTH_ERR 0b00001000 // 3 3 length error
|
||||
#define SX126X_GFSK_RX_STATUS_ABORT_ERR 0b00000100 // 2 2 abort error
|
||||
#define SX126X_GFSK_RX_STATUS_PACKET_RECEIVED 0b00000010 // 2 2 packet received
|
||||
#define SX126X_GFSK_RX_STATUS_PACKET_SENT 0b00000001 // 2 2 packet sent
|
||||
|
||||
//SX126X_CMD_GET_DEVICE_ERRORS
|
||||
#define SX126X_PA_RAMP_ERR 0b100000000 // 8 8 device errors: PA ramping failed
|
||||
#define SX126X_PLL_LOCK_ERR 0b001000000 // 6 6 PLL failed to lock
|
||||
#define SX126X_XOSC_START_ERR 0b000100000 // 5 5 crystal oscillator failed to start
|
||||
#define SX126X_IMG_CALIB_ERR 0b000010000 // 4 4 image calibration failed
|
||||
#define SX126X_ADC_CALIB_ERR 0b000001000 // 3 3 ADC calibration failed
|
||||
#define SX126X_PLL_CALIB_ERR 0b000000100 // 2 2 PLL calibration failed
|
||||
#define SX126X_RC13M_CALIB_ERR 0b000000010 // 1 1 RC13M calibration failed
|
||||
#define SX126X_RC64K_CALIB_ERR 0b000000001 // 0 0 RC64K calibration failed
|
||||
// SX126X_CMD_GET_DEVICE_ERRORS
|
||||
#define SX126X_PA_RAMP_ERR 0b100000000 // 8 8 device errors: PA ramping failed
|
||||
#define SX126X_PLL_LOCK_ERR 0b001000000 // 6 6 PLL failed to lock
|
||||
#define SX126X_XOSC_START_ERR 0b000100000 // 5 5 crystal oscillator failed to start
|
||||
#define SX126X_IMG_CALIB_ERR 0b000010000 // 4 4 image calibration failed
|
||||
#define SX126X_ADC_CALIB_ERR 0b000001000 // 3 3 ADC calibration failed
|
||||
#define SX126X_PLL_CALIB_ERR 0b000000100 // 2 2 PLL calibration failed
|
||||
#define SX126X_RC13M_CALIB_ERR 0b000000010 // 1 1 RC13M calibration failed
|
||||
#define SX126X_RC64K_CALIB_ERR 0b000000001 // 0 0 RC64K calibration failed
|
||||
|
||||
|
||||
// SX126X SPI register variables
|
||||
//SX126X_REG_LORA_SYNC_WORD_MSB + LSB
|
||||
//#define SX126X_SYNC_WORD_PUBLIC 0x3444
|
||||
#define SX126X_SYNC_WORD_PUBLIC 0x24B4 //meshtastic
|
||||
#define SX126X_SYNC_WORD_PRIVATE 0x1424
|
||||
// SX126X_REG_LORA_SYNC_WORD_MSB + LSB
|
||||
// #define SX126X_SYNC_WORD_PUBLIC 0x3444
|
||||
#define SX126X_SYNC_WORD_PUBLIC 0x24B4 // meshtastic
|
||||
#define SX126X_SYNC_WORD_PRIVATE 0x1424
|
||||
|
||||
#define SX126x_TXMODE_ASYNC 0x01
|
||||
#define SX126x_TXMODE_SYNC 0x02
|
||||
#define SX126x_TXMODE_BACK2RX 0x04
|
||||
#define SX126x_TXMODE_ASYNC 0x01
|
||||
#define SX126x_TXMODE_SYNC 0x02
|
||||
#define SX126x_TXMODE_BACK2RX 0x04
|
||||
|
||||
// Convert bandwidth constant to float in kHz
|
||||
float loraBwToFloat(uint8_t bw);
|
||||
|
||||
// Convert float bandwidth (kHz) to constant
|
||||
uint8_t floatToLoraBw(float bw);
|
||||
|
||||
// Convert coding rate constant to float
|
||||
float loraCrToFloat(uint8_t cr);
|
||||
|
||||
// Convert float coding rate to constant
|
||||
uint8_t floatToLoraCr(float cr);
|
||||
|
||||
// Convert MHz to Hz with limit check
|
||||
uint32_t mhzToHzLimited(double freqMHz);
|
||||
|
||||
// Public function
|
||||
void LoRaInit(void);
|
||||
int16_t LoRaBegin(uint32_t frequencyInHz, int8_t txPowerInDbm, float tcxoVoltage, char useRegulatorLDO);
|
||||
void LoRaConfig(uint8_t spreadingFactor, uint8_t bandwidth, uint8_t codingRate, uint16_t preambleLength, uint8_t payloadLen, char crcOn, char invertIrq);
|
||||
uint8_t LoRaReceive(uint8_t *pData, int16_t len);
|
||||
char LoRaSend(uint8_t *pData, int16_t len, uint8_t mode);
|
||||
void LoRaDebugPrint(char enable);
|
||||
void LoRaInit (void);
|
||||
int16_t LoRaBegin (uint32_t frequencyInHz, int8_t txPowerInDbm, float tcxoVoltage, char useRegulatorLDO);
|
||||
void LoRaConfig (uint8_t spreadingFactor, uint8_t bandwidth, uint8_t codingRate, uint16_t preambleLength, uint8_t payloadLen, char crcOn, char invertIrq);
|
||||
uint8_t LoRaReceive (uint8_t *pData, int16_t len);
|
||||
char LoRaSend (uint8_t *pData, int16_t len, uint8_t mode);
|
||||
void LoRaDebugPrint (char enable);
|
||||
|
||||
// Private function
|
||||
void spi_write_byte(uint8_t* Dataout, size_t DataLength );
|
||||
void spi_read_byte(uint8_t *rx, const uint8_t *tx, size_t len);
|
||||
void spi_write_byte (uint8_t *Dataout, size_t DataLength);
|
||||
void spi_read_byte (uint8_t *rx, const uint8_t *tx, size_t len);
|
||||
void spi_read_byte_offs (uint8_t *rx, const uint8_t *tx, size_t len, uint8_t off);
|
||||
uint8_t spi_transfer(uint8_t address);
|
||||
uint8_t spi_transfer (uint8_t address);
|
||||
|
||||
char ReceiveMode(void);
|
||||
char ReceiveMode (void);
|
||||
void GetPacketStatus (int8_t *rssiPacket, int8_t *snrPacket, int8_t *rawSnr);
|
||||
void SetTxPower(int8_t txPowerInDbm);
|
||||
void SetTxPower (int8_t txPowerInDbm);
|
||||
|
||||
void FixInvertedIQ(uint8_t iqConfig);
|
||||
void SetDio3AsTcxoCtrl(float voltage, uint32_t delay);
|
||||
void SetDio2AsRfSwitchCtrl(uint8_t enable);
|
||||
void ResetLora(void);
|
||||
void SetStandby(uint8_t mode);
|
||||
void SetRfFrequency(uint32_t frequency);
|
||||
void Calibrate(uint8_t calibParam);
|
||||
void CalibrateImage(uint32_t frequency);
|
||||
void SetRegulatorMode(uint8_t mode);
|
||||
void SetBufferBaseAddress(uint8_t txBaseAddress, uint8_t rxBaseAddress);
|
||||
void SetPowerConfig(int8_t power, uint8_t rampTime);
|
||||
void SetOvercurrentProtection(float currentLimit);
|
||||
void SetSyncWord(int16_t sync);
|
||||
void SetPaConfig(uint8_t paDutyCycle, uint8_t hpMax, uint8_t deviceSel, uint8_t paLut);
|
||||
void SetDioIrqParams(uint16_t irqMask, uint16_t dio1Mask, uint16_t dio2Mask, uint16_t dio3Mask);
|
||||
void SetStopRxTimerOnPreambleDetect(char enable);
|
||||
void SetLoRaSymbNumTimeout(uint8_t SymbNum);
|
||||
void SetPacketType(uint8_t packetType);
|
||||
void SetModulationParams(uint8_t spreadingFactor, uint8_t bandwidth, uint8_t codingRate, uint8_t lowDataRateOptimize);
|
||||
void SetCadParams(uint8_t cadSymbolNum, uint8_t cadDetPeak, uint8_t cadDetMin, uint8_t cadExitMode, uint32_t cadTimeout);
|
||||
void SetCad();
|
||||
uint8_t GetStatus(void);
|
||||
uint16_t GetIrqStatus(void);
|
||||
void ClearIrqStatus(uint16_t irq);
|
||||
void SetRx(uint32_t timeout);
|
||||
void SetTx(uint32_t timeoutInMs);
|
||||
int GetPacketLost();
|
||||
uint8_t GetRssiInst();
|
||||
void GetRxBufferStatus(uint8_t *payloadLength, uint8_t *rxStartBufferPointer);
|
||||
void Wakeup(void);
|
||||
void WaitForIdleBegin(unsigned long timeout, char *text);
|
||||
char WaitForIdle(unsigned long timeout, char *text, char stop);
|
||||
uint8_t ReadBuffer(uint8_t *rxData, int16_t rxDataLen);
|
||||
void WriteBuffer(uint8_t *txData, int16_t txDataLen);
|
||||
void WriteRegister(uint16_t reg, uint8_t* data, uint8_t numBytes);
|
||||
void ReadRegister(uint16_t reg, uint8_t* data, uint8_t numBytes);
|
||||
void WriteCommand(uint8_t cmd, uint8_t* data, uint8_t numBytes);
|
||||
uint8_t WriteCommand2(uint8_t cmd, uint8_t* data, uint8_t numBytes);
|
||||
void ReadCommand(uint8_t cmd, uint8_t* data, uint8_t numBytes);
|
||||
void SPItransfer(uint8_t cmd, char write, uint8_t* dataOut, uint8_t* dataIn, uint8_t numBytes, char waitForBusy);
|
||||
void LoRaError(int error);
|
||||
void FixInvertedIQ (uint8_t iqConfig);
|
||||
void SetDio3AsTcxoCtrl (float voltage, uint32_t delay);
|
||||
void SetDio2AsRfSwitchCtrl (uint8_t enable);
|
||||
void ResetLora (void);
|
||||
void SetStandby (uint8_t mode);
|
||||
void SetRfFrequency (uint32_t frequency);
|
||||
void Calibrate (uint8_t calibParam);
|
||||
void CalibrateImage (uint32_t frequency);
|
||||
void SetRegulatorMode (uint8_t mode);
|
||||
void SetBufferBaseAddress (uint8_t txBaseAddress, uint8_t rxBaseAddress);
|
||||
void SetPowerConfig (int8_t power, uint8_t rampTime);
|
||||
void SetOvercurrentProtection (float currentLimit);
|
||||
void SetSyncWord (int16_t sync);
|
||||
void SetPaConfig (uint8_t paDutyCycle, uint8_t hpMax, uint8_t deviceSel, uint8_t paLut);
|
||||
void SetDioIrqParams (uint16_t irqMask, uint16_t dio1Mask, uint16_t dio2Mask, uint16_t dio3Mask);
|
||||
void SetStopRxTimerOnPreambleDetect (char enable);
|
||||
void SetLoRaSymbNumTimeout (uint8_t SymbNum);
|
||||
void SetPacketType (uint8_t packetType);
|
||||
void SetModulationParams (uint8_t spreadingFactor, uint8_t bandwidth, uint8_t codingRate, uint8_t lowDataRateOptimize);
|
||||
void SetCadParams (uint8_t cadSymbolNum, uint8_t cadDetPeak, uint8_t cadDetMin, uint8_t cadExitMode, uint32_t cadTimeout);
|
||||
void SetCad();
|
||||
uint8_t GetStatus (void);
|
||||
uint16_t GetIrqStatus (void);
|
||||
void ClearIrqStatus (uint16_t irq);
|
||||
void SetRx (uint32_t timeout);
|
||||
void SetTx (uint32_t timeoutInMs);
|
||||
int GetPacketLost();
|
||||
uint8_t GetRssiInst();
|
||||
void GetRxBufferStatus (uint8_t *payloadLength, uint8_t *rxStartBufferPointer);
|
||||
void Wakeup (void);
|
||||
void WaitForIdleBegin (unsigned long timeout, char *text);
|
||||
char WaitForIdle (unsigned long timeout, char *text, char stop);
|
||||
uint8_t ReadBuffer (uint8_t *rxData, int16_t rxDataLen);
|
||||
void WriteBuffer (uint8_t *txData, int16_t txDataLen);
|
||||
void WriteRegister (uint16_t reg, uint8_t *data, uint8_t numBytes);
|
||||
void ReadRegister (uint16_t reg, uint8_t *data, uint8_t numBytes);
|
||||
void WriteCommand (uint8_t cmd, uint8_t *data, uint8_t numBytes);
|
||||
uint8_t WriteCommand2 (uint8_t cmd, uint8_t *data, uint8_t numBytes);
|
||||
void ReadCommand (uint8_t cmd, uint8_t *data, uint8_t numBytes);
|
||||
void SPItransfer (uint8_t cmd, char write, uint8_t *dataOut, uint8_t *dataIn, uint8_t numBytes, char waitForBusy);
|
||||
void LoRaError (int error);
|
||||
|
||||
extern uint8_t PacketParams[6];
|
||||
extern char txActive;
|
||||
|
||||
@@ -21,4 +21,19 @@ void hexdump (const char *label, const uint8_t *data, size_t len) {
|
||||
}
|
||||
printf ("\n");
|
||||
}
|
||||
}
|
||||
|
||||
void hexdump_compact(const uint8_t* data, size_t len, char* out, size_t out_size) {
|
||||
size_t pos = 0;
|
||||
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
if (pos + 2 >= out_size) break; // make sure we don¡¯t overflow
|
||||
snprintf(out + pos, 3, "%02x", data[i]); // 2 chars + null terminator
|
||||
pos += 2;
|
||||
}
|
||||
|
||||
if (pos < out_size)
|
||||
out[pos] = '\0';
|
||||
else
|
||||
out[out_size - 1] = '\0'; // ensure null termination
|
||||
}
|
||||
@@ -6,4 +6,6 @@
|
||||
#include "stdint.h"
|
||||
void hexdump (const char *label, const uint8_t *data, size_t len);
|
||||
|
||||
void hexdump_compact(const uint8_t* data, size_t len, char* out, size_t out_size);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user