mirror of
https://github.com/meshcore-dev/MeshCore.git
synced 2026-04-20 22:13:47 +00:00
Merge branch 'meshcore-dev:dev' into dev
This commit is contained in:
commit
1cc578c102
217 changed files with 2822 additions and 205 deletions
|
|
@ -17,6 +17,7 @@
|
|||
#define PATH_HASH_SIZE 1
|
||||
|
||||
#define MAX_PACKET_PAYLOAD 184
|
||||
#define MAX_GROUP_DATA_LENGTH (MAX_PACKET_PAYLOAD - CIPHER_BLOCK_SIZE - 3)
|
||||
#define MAX_PATH_SIZE 64
|
||||
#define MAX_TRANS_UNIT 255
|
||||
|
||||
|
|
@ -100,4 +101,4 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ namespace mesh {
|
|||
#define PAYLOAD_TYPE_ACK 0x03 // a simple ack
|
||||
#define PAYLOAD_TYPE_ADVERT 0x04 // a node advertising its Identity
|
||||
#define PAYLOAD_TYPE_GRP_TXT 0x05 // an (unverified) group text message (prefixed with channel hash, MAC) (enc data: timestamp, "name: msg")
|
||||
#define PAYLOAD_TYPE_GRP_DATA 0x06 // an (unverified) group datagram (prefixed with channel hash, MAC) (enc data: timestamp, blob)
|
||||
#define PAYLOAD_TYPE_GRP_DATA 0x06 // an (unverified) group datagram (prefixed with channel hash, MAC) (enc data: data_type(uint16), data_len, blob)
|
||||
#define PAYLOAD_TYPE_ANON_REQ 0x07 // generic request (prefixed with dest_hash, ephemeral pub_key, MAC) (enc data: ...)
|
||||
#define PAYLOAD_TYPE_PATH 0x08 // returned path (prefixed with dest/src hashes, MAC) (enc data: path, extra)
|
||||
#define PAYLOAD_TYPE_TRACE 0x09 // trace a path, collecting SNI for each hop
|
||||
|
|
|
|||
|
|
@ -353,8 +353,18 @@ int BaseChatMesh::searchChannelsByHash(const uint8_t* hash, mesh::GroupChannel d
|
|||
#endif
|
||||
|
||||
void BaseChatMesh::onGroupDataRecv(mesh::Packet* packet, uint8_t type, const mesh::GroupChannel& channel, uint8_t* data, size_t len) {
|
||||
uint8_t txt_type = data[4];
|
||||
if (type == PAYLOAD_TYPE_GRP_TXT && len > 5 && (txt_type >> 2) == 0) { // 0 = plain text msg
|
||||
if (type == PAYLOAD_TYPE_GRP_TXT) {
|
||||
if (len < 5) {
|
||||
MESH_DEBUG_PRINTLN("onGroupDataRecv: dropping short group text payload len=%d", (uint32_t)len);
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t txt_type = data[4];
|
||||
if ((txt_type >> 2) != 0) {
|
||||
MESH_DEBUG_PRINTLN("onGroupDataRecv: dropping unsupported group text type=%d", (uint32_t)txt_type);
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t timestamp;
|
||||
memcpy(×tamp, data, 4);
|
||||
|
||||
|
|
@ -363,6 +373,23 @@ void BaseChatMesh::onGroupDataRecv(mesh::Packet* packet, uint8_t type, const mes
|
|||
|
||||
// notify UI of this new message
|
||||
onChannelMessageRecv(channel, packet, timestamp, (const char *) &data[5]); // let UI know
|
||||
} else if (type == PAYLOAD_TYPE_GRP_DATA) {
|
||||
if (len < 3) {
|
||||
MESH_DEBUG_PRINTLN("onGroupDataRecv: dropping short group data payload len=%d", (uint32_t)len);
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t data_type = ((uint16_t)data[0]) | (((uint16_t)data[1]) << 8);
|
||||
uint8_t data_len = data[2];
|
||||
size_t available_len = len - 3;
|
||||
|
||||
if (data_len > available_len) {
|
||||
MESH_DEBUG_PRINTLN("onGroupDataRecv: dropping malformed group data type=%d len=%d available=%d",
|
||||
(uint32_t)data_type, (uint32_t)data_len, (uint32_t)available_len);
|
||||
return;
|
||||
}
|
||||
|
||||
onChannelDataRecv(channel, packet, data_type, &data[3], data_len);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -454,6 +481,37 @@ bool BaseChatMesh::sendGroupMessage(uint32_t timestamp, mesh::GroupChannel& chan
|
|||
return false;
|
||||
}
|
||||
|
||||
bool BaseChatMesh::sendGroupData(mesh::GroupChannel& channel, uint8_t* path, uint8_t path_len, uint16_t data_type, const uint8_t* data, int data_len) {
|
||||
if (data_len < 0) {
|
||||
MESH_DEBUG_PRINTLN("sendGroupData: invalid negative data_len=%d", data_len);
|
||||
return false;
|
||||
}
|
||||
if (data_len > MAX_GROUP_DATA_LENGTH) {
|
||||
MESH_DEBUG_PRINTLN("sendGroupData: data_len=%d exceeds max=%d", data_len, MAX_GROUP_DATA_LENGTH);
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t temp[3 + MAX_GROUP_DATA_LENGTH];
|
||||
temp[0] = (uint8_t)(data_type & 0xFF);
|
||||
temp[1] = (uint8_t)(data_type >> 8);
|
||||
temp[2] = (uint8_t)data_len;
|
||||
if (data_len > 0) memcpy(&temp[3], data, data_len);
|
||||
|
||||
auto pkt = createGroupDatagram(PAYLOAD_TYPE_GRP_DATA, channel, temp, 3 + data_len);
|
||||
if (pkt == NULL) {
|
||||
MESH_DEBUG_PRINTLN("sendGroupData: unable to create group datagram, data_len=%d", data_len);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (path_len == OUT_PATH_UNKNOWN) {
|
||||
sendFloodScoped(channel, pkt);
|
||||
} else {
|
||||
sendDirect(pkt, path, path_len);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BaseChatMesh::shareContactZeroHop(const ContactInfo& contact) {
|
||||
int plen = getBlobByKey(contact.id.pub_key, PUB_KEY_SIZE, temp_buf); // retrieve last raw advert packet
|
||||
if (plen == 0) return false; // not found
|
||||
|
|
|
|||
|
|
@ -111,6 +111,8 @@ protected:
|
|||
virtual uint32_t calcDirectTimeoutMillisFor(uint32_t pkt_airtime_millis, uint8_t path_len) const = 0;
|
||||
virtual void onSendTimeout() = 0;
|
||||
virtual void onChannelMessageRecv(const mesh::GroupChannel& channel, mesh::Packet* pkt, uint32_t timestamp, const char *text) = 0;
|
||||
virtual void onChannelDataRecv(const mesh::GroupChannel& channel, mesh::Packet* pkt, uint16_t data_type,
|
||||
const uint8_t* data, size_t data_len) {}
|
||||
virtual uint8_t onContactRequest(const ContactInfo& contact, uint32_t sender_timestamp, const uint8_t* data, uint8_t len, uint8_t* reply) = 0;
|
||||
virtual void onContactResponse(const ContactInfo& contact, const uint8_t* data, uint8_t len) = 0;
|
||||
virtual void handleReturnPathRetry(const ContactInfo& contact, const uint8_t* path, uint8_t path_len);
|
||||
|
|
@ -148,6 +150,7 @@ public:
|
|||
int sendMessage(const ContactInfo& recipient, uint32_t timestamp, uint8_t attempt, const char* text, uint32_t& expected_ack, uint32_t& est_timeout);
|
||||
int sendCommandData(const ContactInfo& recipient, uint32_t timestamp, uint8_t attempt, const char* text, uint32_t& est_timeout);
|
||||
bool sendGroupMessage(uint32_t timestamp, mesh::GroupChannel& channel, const char* sender_name, const char* text, int text_len);
|
||||
bool sendGroupData(mesh::GroupChannel& channel, uint8_t* path, uint8_t path_len, uint16_t data_type, const uint8_t* data, int data_len);
|
||||
int sendLogin(const ContactInfo& recipient, const char* password, uint32_t& est_timeout);
|
||||
int sendAnonReq(const ContactInfo& recipient, const uint8_t* data, uint8_t len, uint32_t& tag, uint32_t& est_timeout);
|
||||
int sendRequest(const ContactInfo& recipient, uint8_t req_type, uint32_t& tag, uint32_t& est_timeout);
|
||||
|
|
|
|||
|
|
@ -55,12 +55,12 @@ void CommonCLI::loadPrefsInt(FILESYSTEM* fs, const char* filename) {
|
|||
file.read((uint8_t *)&_prefs->tx_power_dbm, sizeof(_prefs->tx_power_dbm)); // 76
|
||||
file.read((uint8_t *)&_prefs->disable_fwd, sizeof(_prefs->disable_fwd)); // 77
|
||||
file.read((uint8_t *)&_prefs->advert_interval, sizeof(_prefs->advert_interval)); // 78
|
||||
file.read((uint8_t *)pad, 1); // 79 was 'unused'
|
||||
file.read(pad, 1); // 79 : 1 byte unused (was rx_boosted_gain in v1.14.1, moved to end for upgrade compat)
|
||||
file.read((uint8_t *)&_prefs->rx_delay_base, sizeof(_prefs->rx_delay_base)); // 80
|
||||
file.read((uint8_t *)&_prefs->tx_delay_factor, sizeof(_prefs->tx_delay_factor)); // 84
|
||||
file.read((uint8_t *)&_prefs->guest_password[0], sizeof(_prefs->guest_password)); // 88
|
||||
file.read((uint8_t *)&_prefs->direct_tx_delay_factor, sizeof(_prefs->direct_tx_delay_factor)); // 104
|
||||
file.read(pad, 4); // 108
|
||||
file.read(pad, 4); // 108 : 4 bytes unused
|
||||
file.read((uint8_t *)&_prefs->sf, sizeof(_prefs->sf)); // 112
|
||||
file.read((uint8_t *)&_prefs->cr, sizeof(_prefs->cr)); // 113
|
||||
file.read((uint8_t *)&_prefs->allow_read_only, sizeof(_prefs->allow_read_only)); // 114
|
||||
|
|
@ -85,16 +85,17 @@ void CommonCLI::loadPrefsInt(FILESYSTEM* fs, const char* filename) {
|
|||
file.read((uint8_t *)&_prefs->gps_interval, sizeof(_prefs->gps_interval)); // 157
|
||||
file.read((uint8_t *)&_prefs->advert_loc_policy, sizeof (_prefs->advert_loc_policy)); // 161
|
||||
file.read((uint8_t *)&_prefs->discovery_mod_timestamp, sizeof(_prefs->discovery_mod_timestamp)); // 162
|
||||
file.read((uint8_t *)&_prefs->adc_multiplier, sizeof(_prefs->adc_multiplier)); // 166
|
||||
file.read((uint8_t *)_prefs->owner_info, sizeof(_prefs->owner_info)); // 170
|
||||
// 290
|
||||
file.read((uint8_t *)&_prefs->adc_multiplier, sizeof(_prefs->adc_multiplier)); // 166
|
||||
file.read((uint8_t *)_prefs->owner_info, sizeof(_prefs->owner_info)); // 170
|
||||
file.read((uint8_t *)&_prefs->rx_boosted_gain, sizeof(_prefs->rx_boosted_gain)); // 290
|
||||
// next: 291
|
||||
|
||||
// sanitise bad pref values
|
||||
_prefs->rx_delay_base = constrain(_prefs->rx_delay_base, 0, 20.0f);
|
||||
_prefs->tx_delay_factor = constrain(_prefs->tx_delay_factor, 0, 2.0f);
|
||||
_prefs->direct_tx_delay_factor = constrain(_prefs->direct_tx_delay_factor, 0, 2.0f);
|
||||
_prefs->airtime_factor = constrain(_prefs->airtime_factor, 0, 9.0f);
|
||||
_prefs->freq = constrain(_prefs->freq, 400.0f, 2500.0f);
|
||||
_prefs->freq = constrain(_prefs->freq, 150.0f, 2500.0f);
|
||||
_prefs->bw = constrain(_prefs->bw, 7.8f, 500.0f);
|
||||
_prefs->sf = constrain(_prefs->sf, 5, 12);
|
||||
_prefs->cr = constrain(_prefs->cr, 5, 8);
|
||||
|
|
@ -115,6 +116,9 @@ void CommonCLI::loadPrefsInt(FILESYSTEM* fs, const char* filename) {
|
|||
_prefs->gps_enabled = constrain(_prefs->gps_enabled, 0, 1);
|
||||
_prefs->advert_loc_policy = constrain(_prefs->advert_loc_policy, 0, 2);
|
||||
|
||||
// sanitise settings
|
||||
_prefs->rx_boosted_gain = constrain(_prefs->rx_boosted_gain, 0, 1); // boolean
|
||||
|
||||
file.close();
|
||||
}
|
||||
}
|
||||
|
|
@ -142,12 +146,12 @@ void CommonCLI::savePrefs(FILESYSTEM* fs) {
|
|||
file.write((uint8_t *)&_prefs->tx_power_dbm, sizeof(_prefs->tx_power_dbm)); // 76
|
||||
file.write((uint8_t *)&_prefs->disable_fwd, sizeof(_prefs->disable_fwd)); // 77
|
||||
file.write((uint8_t *)&_prefs->advert_interval, sizeof(_prefs->advert_interval)); // 78
|
||||
file.write((uint8_t *)pad, 1); // 79 was 'unused'
|
||||
file.write(pad, 1); // 79 : 1 byte unused (rx_boosted_gain moved to end)
|
||||
file.write((uint8_t *)&_prefs->rx_delay_base, sizeof(_prefs->rx_delay_base)); // 80
|
||||
file.write((uint8_t *)&_prefs->tx_delay_factor, sizeof(_prefs->tx_delay_factor)); // 84
|
||||
file.write((uint8_t *)&_prefs->guest_password[0], sizeof(_prefs->guest_password)); // 88
|
||||
file.write((uint8_t *)&_prefs->direct_tx_delay_factor, sizeof(_prefs->direct_tx_delay_factor)); // 104
|
||||
file.write(pad, 4); // 108
|
||||
file.write(pad, 4); // 108 : 4 byte unused
|
||||
file.write((uint8_t *)&_prefs->sf, sizeof(_prefs->sf)); // 112
|
||||
file.write((uint8_t *)&_prefs->cr, sizeof(_prefs->cr)); // 113
|
||||
file.write((uint8_t *)&_prefs->allow_read_only, sizeof(_prefs->allow_read_only)); // 114
|
||||
|
|
@ -173,8 +177,9 @@ void CommonCLI::savePrefs(FILESYSTEM* fs) {
|
|||
file.write((uint8_t *)&_prefs->advert_loc_policy, sizeof(_prefs->advert_loc_policy)); // 161
|
||||
file.write((uint8_t *)&_prefs->discovery_mod_timestamp, sizeof(_prefs->discovery_mod_timestamp)); // 162
|
||||
file.write((uint8_t *)&_prefs->adc_multiplier, sizeof(_prefs->adc_multiplier)); // 166
|
||||
file.write((uint8_t *)_prefs->owner_info, sizeof(_prefs->owner_info)); // 170
|
||||
// 290
|
||||
file.write((uint8_t *)_prefs->owner_info, sizeof(_prefs->owner_info)); // 170
|
||||
file.write((uint8_t *)&_prefs->rx_boosted_gain, sizeof(_prefs->rx_boosted_gain)); // 290
|
||||
// next: 291
|
||||
|
||||
file.close();
|
||||
}
|
||||
|
|
@ -270,7 +275,7 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
|
|||
uint8_t sf = num > 2 ? atoi(parts[2]) : 0;
|
||||
uint8_t cr = num > 3 ? atoi(parts[3]) : 0;
|
||||
int temp_timeout_mins = num > 4 ? atoi(parts[4]) : 0;
|
||||
if (freq >= 300.0f && freq <= 2500.0f && sf >= 5 && sf <= 12 && cr >= 5 && cr <= 8 && bw >= 7.0f && bw <= 500.0f && temp_timeout_mins > 0) {
|
||||
if (freq >= 150.0f && freq <= 2500.0f && sf >= 5 && sf <= 12 && cr >= 5 && cr <= 8 && bw >= 7.0f && bw <= 500.0f && temp_timeout_mins > 0) {
|
||||
_callbacks->applyTempRadioParams(freq, bw, sf, cr, temp_timeout_mins);
|
||||
sprintf(reply, "OK - temp params for %d mins", temp_timeout_mins);
|
||||
} else {
|
||||
|
|
@ -289,7 +294,12 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
|
|||
*/
|
||||
} else if (memcmp(command, "get ", 4) == 0) {
|
||||
const char* config = &command[4];
|
||||
if (memcmp(config, "af", 2) == 0) {
|
||||
if (memcmp(config, "dutycycle", 9) == 0) {
|
||||
float dc = 100.0f / (_prefs->airtime_factor + 1.0f);
|
||||
int dc_int = (int)dc;
|
||||
int dc_frac = (int)((dc - dc_int) * 10.0f + 0.5f);
|
||||
sprintf(reply, "> %d.%d%%", dc_int, dc_frac);
|
||||
} else if (memcmp(config, "af", 2) == 0) {
|
||||
sprintf(reply, "> %s", StrHelper::ftoa(_prefs->airtime_factor));
|
||||
} else if (memcmp(config, "int.thresh", 10) == 0) {
|
||||
sprintf(reply, "> %d", (uint32_t) _prefs->interference_threshold);
|
||||
|
|
@ -318,6 +328,10 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
|
|||
sprintf(reply, "> %s", StrHelper::ftoa(_prefs->node_lat));
|
||||
} else if (memcmp(config, "lon", 3) == 0) {
|
||||
sprintf(reply, "> %s", StrHelper::ftoa(_prefs->node_lon));
|
||||
#if defined(USE_SX1262) || defined(USE_SX1268)
|
||||
} else if (memcmp(config, "radio.rxgain", 12) == 0) {
|
||||
sprintf(reply, "> %s", _prefs->rx_boosted_gain ? "on" : "off");
|
||||
#endif
|
||||
} else if (memcmp(config, "radio", 5) == 0) {
|
||||
char freq[16], bw[16];
|
||||
strcpy(freq, StrHelper::ftoa(_prefs->freq));
|
||||
|
|
@ -442,7 +456,19 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
|
|||
*/
|
||||
} else if (memcmp(command, "set ", 4) == 0) {
|
||||
const char* config = &command[4];
|
||||
if (memcmp(config, "af ", 3) == 0) {
|
||||
if (memcmp(config, "dutycycle ", 10) == 0) {
|
||||
float dc = atof(&config[10]);
|
||||
if (dc < 1 || dc > 100) {
|
||||
strcpy(reply, "ERROR: dutycycle must be 1-100");
|
||||
} else {
|
||||
_prefs->airtime_factor = (100.0f / dc) - 1.0f;
|
||||
savePrefs();
|
||||
float actual = 100.0f / (_prefs->airtime_factor + 1.0f);
|
||||
int a_int = (int)actual;
|
||||
int a_frac = (int)((actual - a_int) * 10.0f + 0.5f);
|
||||
sprintf(reply, "OK - %d.%d%%", a_int, a_frac);
|
||||
}
|
||||
} else if (memcmp(config, "af ", 3) == 0) {
|
||||
_prefs->airtime_factor = atof(&config[3]);
|
||||
savePrefs();
|
||||
strcpy(reply, "OK");
|
||||
|
|
@ -511,6 +537,13 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
|
|||
_prefs->disable_fwd = memcmp(&config[7], "off", 3) == 0;
|
||||
savePrefs();
|
||||
strcpy(reply, _prefs->disable_fwd ? "OK - repeat is now OFF" : "OK - repeat is now ON");
|
||||
#if defined(USE_SX1262) || defined(USE_SX1268)
|
||||
} else if (memcmp(config, "radio.rxgain ", 13) == 0) {
|
||||
_prefs->rx_boosted_gain = memcmp(&config[13], "on", 2) == 0;
|
||||
strcpy(reply, "OK");
|
||||
savePrefs();
|
||||
_callbacks->setRxBoostedGain(_prefs->rx_boosted_gain);
|
||||
#endif
|
||||
} else if (memcmp(config, "radio ", 6) == 0) {
|
||||
strcpy(tmp, &config[6]);
|
||||
const char *parts[4];
|
||||
|
|
@ -519,7 +552,7 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
|
|||
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) {
|
||||
if (freq >= 150.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;
|
||||
|
|
@ -704,7 +737,7 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
|
|||
}
|
||||
} else if (memcmp(command, "sensor set ", 11) == 0) {
|
||||
strcpy(tmp, &command[11]);
|
||||
const char *parts[2];
|
||||
const char *parts[2];
|
||||
int num = mesh::Utils::parseTextParts(tmp, parts, 2, ' ');
|
||||
const char *key = (num > 0) ? parts[0] : "";
|
||||
const char *value = (num > 1) ? parts[1] : "null";
|
||||
|
|
@ -727,7 +760,7 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
|
|||
dp = strchr(dp, 0);
|
||||
int i;
|
||||
for (i = start; i < end && (dp-reply < 134); i++) {
|
||||
sprintf(dp, "%s=%s\n",
|
||||
sprintf(dp, "%s=%s\n",
|
||||
_sensors->getSettingName(i),
|
||||
_sensors->getSettingValue(i));
|
||||
dp = strchr(dp, 0);
|
||||
|
|
@ -807,8 +840,8 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
|
|||
bool active = !strcmp(_sensors->getSettingByKey("gps"), "1");
|
||||
if (enabled) {
|
||||
sprintf(reply, "on, %s, %s, %d sats",
|
||||
active?"active":"deactivated",
|
||||
fix?"fix":"no fix",
|
||||
active?"active":"deactivated",
|
||||
fix?"fix":"no fix",
|
||||
sats);
|
||||
} else {
|
||||
strcpy(reply, "off");
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ struct NodePrefs { // persisted to file
|
|||
uint32_t discovery_mod_timestamp;
|
||||
float adc_multiplier;
|
||||
char owner_info[120];
|
||||
uint8_t rx_boosted_gain; // power settings
|
||||
uint8_t path_hash_mode; // which path mode to use when sending
|
||||
uint8_t loop_detect;
|
||||
};
|
||||
|
|
@ -94,6 +95,10 @@ public:
|
|||
virtual void restartBridge() {
|
||||
// no op by default
|
||||
};
|
||||
|
||||
virtual void setRxBoostedGain(bool enable) {
|
||||
// no op by default
|
||||
};
|
||||
};
|
||||
|
||||
class CommonCLI {
|
||||
|
|
|
|||
|
|
@ -3,9 +3,11 @@
|
|||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#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
|
||||
#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
|
||||
#define DATA_TYPE_RESERVED 0x0000 // reserved for future use
|
||||
#define DATA_TYPE_DEV 0xFFFF // developer namespace for experimenting with group/channel datagrams and building apps
|
||||
|
||||
class StrHelper {
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -83,4 +83,10 @@ class CustomLLCC68 : public LLCC68 {
|
|||
bool detected = (irq & SX126X_IRQ_HEADER_VALID) || (irq & SX126X_IRQ_PREAMBLE_DETECTED);
|
||||
return detected;
|
||||
}
|
||||
|
||||
bool getRxBoostedGainMode() {
|
||||
uint8_t rxGain = 0;
|
||||
readRegister(RADIOLIB_SX126X_REG_RX_GAIN, &rxGain, 1);
|
||||
return (rxGain == RADIOLIB_SX126X_RX_GAIN_BOOSTED);
|
||||
}
|
||||
};
|
||||
|
|
@ -22,4 +22,11 @@ public:
|
|||
}
|
||||
|
||||
void doResetAGC() override { sx126xResetAGC((SX126x *)_radio); }
|
||||
|
||||
void setRxBoostedGainMode(bool en) override {
|
||||
((CustomLLCC68 *)_radio)->setRxBoostedGainMode(en);
|
||||
}
|
||||
bool getRxBoostedGainMode() const override {
|
||||
return ((CustomLLCC68 *)_radio)->getRxBoostedGainMode();
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@
|
|||
#include "MeshCore.h"
|
||||
|
||||
class CustomLR1110 : public LR1110 {
|
||||
bool _rx_boosted = false;
|
||||
|
||||
public:
|
||||
CustomLR1110(Module *mod) : LR1110(mod) { }
|
||||
|
||||
|
|
@ -22,6 +24,13 @@ class CustomLR1110 : public LR1110 {
|
|||
|
||||
float getFreqMHz() const { return freqMHz; }
|
||||
|
||||
int16_t setRxBoostedGainMode(bool en) {
|
||||
_rx_boosted = en;
|
||||
return LR1110::setRxBoostedGainMode(en);
|
||||
}
|
||||
|
||||
bool getRxBoostedGainMode() const { return _rx_boosted; }
|
||||
|
||||
bool isReceiving() {
|
||||
uint16_t irq = getIrqStatus();
|
||||
bool detected = ((irq & RADIOLIB_LR11X0_IRQ_SYNC_WORD_HEADER_VALID) || (irq & RADIOLIB_LR11X0_IRQ_PREAMBLE_DETECTED));
|
||||
|
|
|
|||
|
|
@ -24,5 +24,11 @@ public:
|
|||
|
||||
float getLastRSSI() const override { return ((CustomLR1110 *)_radio)->getRSSI(); }
|
||||
float getLastSNR() const override { return ((CustomLR1110 *)_radio)->getSNR(); }
|
||||
int16_t setRxBoostedGainMode(bool en) { return ((CustomLR1110 *)_radio)->setRxBoostedGainMode(en); };
|
||||
|
||||
void setRxBoostedGainMode(bool en) override {
|
||||
((CustomLR1110 *)_radio)->setRxBoostedGainMode(en);
|
||||
}
|
||||
bool getRxBoostedGainMode() const override {
|
||||
return ((CustomLR1110 *)_radio)->getRxBoostedGainMode();
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
#include <RadioLib.h>
|
||||
|
||||
#define SX126X_IRQ_HEADER_VALID 0b0000010000 // 4 4 valid LoRa header received
|
||||
#define SX126X_IRQ_HEADER_VALID 0b0000010000 // 4 4 valid LoRa header received
|
||||
#define SX126X_IRQ_PREAMBLE_DETECTED 0x04
|
||||
|
||||
class CustomSX1262 : public SX1262 {
|
||||
|
|
@ -91,4 +91,10 @@ class CustomSX1262 : public SX1262 {
|
|||
bool detected = (irq & SX126X_IRQ_HEADER_VALID) || (irq & SX126X_IRQ_PREAMBLE_DETECTED);
|
||||
return detected;
|
||||
}
|
||||
|
||||
bool getRxBoostedGainMode() {
|
||||
uint8_t rxGain = 0;
|
||||
readRegister(RADIOLIB_SX126X_REG_RX_GAIN, &rxGain, 1);
|
||||
return (rxGain == RADIOLIB_SX126X_RX_GAIN_BOOSTED);
|
||||
}
|
||||
};
|
||||
|
|
@ -4,6 +4,10 @@
|
|||
#include "RadioLibWrappers.h"
|
||||
#include "SX126xReset.h"
|
||||
|
||||
#ifndef USE_SX1262
|
||||
#define USE_SX1262
|
||||
#endif
|
||||
|
||||
class CustomSX1262Wrapper : public RadioLibWrapper {
|
||||
public:
|
||||
CustomSX1262Wrapper(CustomSX1262& radio, mesh::MainBoard& board) : RadioLibWrapper(radio, board) { }
|
||||
|
|
@ -25,4 +29,11 @@ public:
|
|||
}
|
||||
|
||||
void doResetAGC() override { sx126xResetAGC((SX126x *)_radio); }
|
||||
|
||||
void setRxBoostedGainMode(bool en) override {
|
||||
((CustomSX1262 *)_radio)->setRxBoostedGainMode(en);
|
||||
}
|
||||
bool getRxBoostedGainMode() const override {
|
||||
return ((CustomSX1262 *)_radio)->getRxBoostedGainMode();
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
#include <RadioLib.h>
|
||||
|
||||
#define SX126X_IRQ_HEADER_VALID 0b0000010000 // 4 4 valid LoRa header received
|
||||
#define SX126X_IRQ_HEADER_VALID 0b0000010000 // 4 4 valid LoRa header received
|
||||
#define SX126X_IRQ_PREAMBLE_DETECTED 0x04
|
||||
|
||||
class CustomSX1268 : public SX1268 {
|
||||
|
|
@ -83,4 +83,10 @@ class CustomSX1268 : public SX1268 {
|
|||
bool detected = (irq & SX126X_IRQ_HEADER_VALID) || (irq & SX126X_IRQ_PREAMBLE_DETECTED);
|
||||
return detected;
|
||||
}
|
||||
|
||||
bool getRxBoostedGainMode() {
|
||||
uint8_t rxGain = 0;
|
||||
readRegister(RADIOLIB_SX126X_REG_RX_GAIN, &rxGain, 1);
|
||||
return (rxGain == RADIOLIB_SX126X_RX_GAIN_BOOSTED);
|
||||
}
|
||||
};
|
||||
|
|
@ -4,6 +4,10 @@
|
|||
#include "RadioLibWrappers.h"
|
||||
#include "SX126xReset.h"
|
||||
|
||||
#ifndef USE_SX1268
|
||||
#define USE_SX1268
|
||||
#endif
|
||||
|
||||
class CustomSX1268Wrapper : public RadioLibWrapper {
|
||||
public:
|
||||
CustomSX1268Wrapper(CustomSX1268& radio, mesh::MainBoard& board) : RadioLibWrapper(radio, board) { }
|
||||
|
|
@ -22,4 +26,11 @@ public:
|
|||
}
|
||||
|
||||
void doResetAGC() override { sx126xResetAGC((SX126x *)_radio); }
|
||||
|
||||
void setRxBoostedGainMode(bool en) override {
|
||||
((CustomSX1268 *)_radio)->setRxBoostedGainMode(en);
|
||||
}
|
||||
bool getRxBoostedGainMode() const override {
|
||||
return ((CustomSX1268 *)_radio)->getRxBoostedGainMode();
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -3,6 +3,10 @@
|
|||
#include "CustomSX1276.h"
|
||||
#include "RadioLibWrappers.h"
|
||||
|
||||
#ifndef USE_SX1276
|
||||
#define USE_SX1276
|
||||
#endif
|
||||
|
||||
class CustomSX1276Wrapper : public RadioLibWrapper {
|
||||
public:
|
||||
CustomSX1276Wrapper(CustomSX1276& radio, mesh::MainBoard& board) : RadioLibWrapper(radio, board) { }
|
||||
|
|
|
|||
|
|
@ -54,6 +54,9 @@ public:
|
|||
virtual float getLastSNR() const override;
|
||||
|
||||
float packetScore(float snr, int packet_len) override { return packetScoreInt(snr, 10, packet_len); } // assume sf=10
|
||||
|
||||
virtual void setRxBoostedGainMode(bool) { }
|
||||
virtual bool getRxBoostedGainMode() const { return false; }
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -59,44 +59,58 @@ bool E213Display::begin() {
|
|||
}
|
||||
|
||||
void E213Display::powerOn() {
|
||||
if (_periph_power) {
|
||||
_periph_power->claim();
|
||||
} else {
|
||||
#ifdef PIN_VEXT_EN
|
||||
pinMode(PIN_VEXT_EN, OUTPUT);
|
||||
pinMode(PIN_VEXT_EN, OUTPUT);
|
||||
#ifdef PIN_VEXT_EN_ACTIVE
|
||||
digitalWrite(PIN_VEXT_EN, PIN_VEXT_EN_ACTIVE);
|
||||
digitalWrite(PIN_VEXT_EN, PIN_VEXT_EN_ACTIVE);
|
||||
#else
|
||||
digitalWrite(PIN_VEXT_EN, LOW); // Active low
|
||||
digitalWrite(PIN_VEXT_EN, LOW); // Active low
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
delay(50); // Allow power to stabilize
|
||||
#endif
|
||||
}
|
||||
|
||||
void E213Display::powerOff() {
|
||||
if (_periph_power) {
|
||||
_periph_power->release();
|
||||
} else {
|
||||
#ifdef PIN_VEXT_EN
|
||||
#ifdef PIN_VEXT_EN_ACTIVE
|
||||
digitalWrite(PIN_VEXT_EN, !PIN_VEXT_EN_ACTIVE);
|
||||
digitalWrite(PIN_VEXT_EN, !PIN_VEXT_EN_ACTIVE);
|
||||
#else
|
||||
digitalWrite(PIN_VEXT_EN, HIGH); // Turn off power
|
||||
digitalWrite(PIN_VEXT_EN, HIGH); // Turn off power
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void E213Display::turnOn() {
|
||||
if (!_init) begin();
|
||||
powerOn();
|
||||
else if (!_isOn) {
|
||||
powerOn();
|
||||
display->fastmodeOn(); // Reinitialize display controller after power was cut
|
||||
}
|
||||
_isOn = true;
|
||||
}
|
||||
|
||||
void E213Display::turnOff() {
|
||||
powerOff();
|
||||
_isOn = false;
|
||||
if (_isOn) {
|
||||
powerOff();
|
||||
_isOn = false;
|
||||
}
|
||||
}
|
||||
|
||||
void E213Display::clear() {
|
||||
display->clear();
|
||||
|
||||
}
|
||||
|
||||
void E213Display::startFrame(Color bkg) {
|
||||
display_crc.reset();
|
||||
|
||||
// Fill screen with white first to ensure clean background
|
||||
display->fillRect(0, 0, width(), height(), WHITE);
|
||||
|
||||
|
|
@ -107,31 +121,50 @@ void E213Display::startFrame(Color bkg) {
|
|||
}
|
||||
|
||||
void E213Display::setTextSize(int sz) {
|
||||
display_crc.update<int>(sz);
|
||||
// The library handles text size internally
|
||||
display->setTextSize(sz);
|
||||
}
|
||||
|
||||
void E213Display::setColor(Color c) {
|
||||
display_crc.update<Color>(c);
|
||||
// implemented in individual display methods
|
||||
}
|
||||
|
||||
void E213Display::setCursor(int x, int y) {
|
||||
display_crc.update<int>(x);
|
||||
display_crc.update<int>(y);
|
||||
display->setCursor(x, y);
|
||||
}
|
||||
|
||||
void E213Display::print(const char *str) {
|
||||
display_crc.update<char>(str, strlen(str));
|
||||
display->print(str);
|
||||
}
|
||||
|
||||
void E213Display::fillRect(int x, int y, int w, int h) {
|
||||
display_crc.update<int>(x);
|
||||
display_crc.update<int>(y);
|
||||
display_crc.update<int>(w);
|
||||
display_crc.update<int>(h);
|
||||
display->fillRect(x, y, w, h, BLACK);
|
||||
}
|
||||
|
||||
void E213Display::drawRect(int x, int y, int w, int h) {
|
||||
display_crc.update<int>(x);
|
||||
display_crc.update<int>(y);
|
||||
display_crc.update<int>(w);
|
||||
display_crc.update<int>(h);
|
||||
display->drawRect(x, y, w, h, BLACK);
|
||||
}
|
||||
|
||||
void E213Display::drawXbm(int x, int y, const uint8_t *bits, int w, int h) {
|
||||
display_crc.update<int>(x);
|
||||
display_crc.update<int>(y);
|
||||
display_crc.update<int>(w);
|
||||
display_crc.update<int>(h);
|
||||
display_crc.update<uint8_t>(bits, w * h / 8);
|
||||
|
||||
// Width in bytes for bitmap processing
|
||||
uint16_t widthInBytes = (w + 7) / 8;
|
||||
|
||||
|
|
@ -160,5 +193,9 @@ uint16_t E213Display::getTextWidth(const char *str) {
|
|||
}
|
||||
|
||||
void E213Display::endFrame() {
|
||||
uint32_t crc = display_crc.finalize();
|
||||
if (crc != last_display_crc_value) {
|
||||
display->update();
|
||||
last_display_crc_value = crc;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,15 +5,20 @@
|
|||
#include <SPI.h>
|
||||
#include <Wire.h>
|
||||
#include <heltec-eink-modules.h>
|
||||
#include <CRC32.h>
|
||||
#include <helpers/RefCountedDigitalPin.h>
|
||||
|
||||
// Display driver for E213 e-ink display
|
||||
class E213Display : public DisplayDriver {
|
||||
BaseDisplay* display=NULL;
|
||||
bool _init = false;
|
||||
bool _isOn = false;
|
||||
RefCountedDigitalPin* _periph_power;
|
||||
CRC32 display_crc;
|
||||
uint32_t last_display_crc_value = 0;
|
||||
|
||||
public:
|
||||
E213Display() : DisplayDriver(250, 122) {}
|
||||
E213Display(RefCountedDigitalPin* periph_power = NULL) : DisplayDriver(250, 122), _periph_power(periph_power) {}
|
||||
~E213Display(){
|
||||
if(display!=NULL) {
|
||||
delete display;
|
||||
|
|
@ -39,4 +44,4 @@ private:
|
|||
BaseDisplay* detectEInk();
|
||||
void powerOn();
|
||||
void powerOff();
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -21,28 +21,41 @@ bool E290Display::begin() {
|
|||
}
|
||||
|
||||
void E290Display::powerOn() {
|
||||
if (_periph_power) {
|
||||
_periph_power->claim();
|
||||
} else {
|
||||
#ifdef PIN_VEXT_EN
|
||||
pinMode(PIN_VEXT_EN, OUTPUT);
|
||||
digitalWrite(PIN_VEXT_EN, PIN_VEXT_EN_ACTIVE);
|
||||
delay(50); // Allow power to stabilize
|
||||
pinMode(PIN_VEXT_EN, OUTPUT);
|
||||
digitalWrite(PIN_VEXT_EN, PIN_VEXT_EN_ACTIVE);
|
||||
#endif
|
||||
}
|
||||
delay(50); // Allow power to stabilize
|
||||
}
|
||||
|
||||
void E290Display::powerOff() {
|
||||
if (_periph_power) {
|
||||
_periph_power->release();
|
||||
} else {
|
||||
#ifdef PIN_VEXT_EN
|
||||
digitalWrite(PIN_VEXT_EN, !PIN_VEXT_EN_ACTIVE); // Turn off power
|
||||
digitalWrite(PIN_VEXT_EN, !PIN_VEXT_EN_ACTIVE); // Turn off power
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void E290Display::turnOn() {
|
||||
if (!_init) begin();
|
||||
powerOn();
|
||||
else if (!_isOn) {
|
||||
powerOn();
|
||||
display.fastmodeOn(); // Reinitialize display controller after power was cut
|
||||
}
|
||||
_isOn = true;
|
||||
}
|
||||
|
||||
void E290Display::turnOff() {
|
||||
powerOff();
|
||||
_isOn = false;
|
||||
if (_isOn) {
|
||||
powerOff();
|
||||
_isOn = false;
|
||||
}
|
||||
}
|
||||
|
||||
void E290Display::clear() {
|
||||
|
|
@ -50,6 +63,8 @@ void E290Display::clear() {
|
|||
}
|
||||
|
||||
void E290Display::startFrame(Color bkg) {
|
||||
display_crc.reset();
|
||||
|
||||
// Fill screen with white first to ensure clean background
|
||||
display.fillRect(0, 0, width(), height(), WHITE);
|
||||
if (bkg == LIGHT) {
|
||||
|
|
@ -59,31 +74,50 @@ void E290Display::startFrame(Color bkg) {
|
|||
}
|
||||
|
||||
void E290Display::setTextSize(int sz) {
|
||||
display_crc.update<int>(sz);
|
||||
// The library handles text size internally
|
||||
display.setTextSize(sz);
|
||||
}
|
||||
|
||||
void E290Display::setColor(Color c) {
|
||||
display_crc.update<Color>(c);
|
||||
// implemented in individual display methods
|
||||
}
|
||||
|
||||
void E290Display::setCursor(int x, int y) {
|
||||
display_crc.update<int>(x);
|
||||
display_crc.update<int>(y);
|
||||
display.setCursor(x, y);
|
||||
}
|
||||
|
||||
void E290Display::print(const char *str) {
|
||||
display_crc.update<char>(str, strlen(str));
|
||||
display.print(str);
|
||||
}
|
||||
|
||||
void E290Display::fillRect(int x, int y, int w, int h) {
|
||||
display_crc.update<int>(x);
|
||||
display_crc.update<int>(y);
|
||||
display_crc.update<int>(w);
|
||||
display_crc.update<int>(h);
|
||||
display.fillRect(x, y, w, h, BLACK);
|
||||
}
|
||||
|
||||
void E290Display::drawRect(int x, int y, int w, int h) {
|
||||
display_crc.update<int>(x);
|
||||
display_crc.update<int>(y);
|
||||
display_crc.update<int>(w);
|
||||
display_crc.update<int>(h);
|
||||
display.drawRect(x, y, w, h, BLACK);
|
||||
}
|
||||
|
||||
void E290Display::drawXbm(int x, int y, const uint8_t *bits, int w, int h) {
|
||||
display_crc.update<int>(x);
|
||||
display_crc.update<int>(y);
|
||||
display_crc.update<int>(w);
|
||||
display_crc.update<int>(h);
|
||||
display_crc.update<uint8_t>(bits, w * h / 8);
|
||||
|
||||
// Width in bytes for bitmap processing
|
||||
uint16_t widthInBytes = (w + 7) / 8;
|
||||
|
||||
|
|
@ -112,5 +146,9 @@ uint16_t E290Display::getTextWidth(const char *str) {
|
|||
}
|
||||
|
||||
void E290Display::endFrame() {
|
||||
display.update();
|
||||
uint32_t crc = display_crc.finalize();
|
||||
if (crc != last_display_crc_value) {
|
||||
display.update();
|
||||
last_display_crc_value = crc;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,15 +5,20 @@
|
|||
#include <SPI.h>
|
||||
#include <Wire.h>
|
||||
#include <heltec-eink-modules.h>
|
||||
#include <CRC32.h>
|
||||
#include <helpers/RefCountedDigitalPin.h>
|
||||
|
||||
// Display driver for E290 e-ink display
|
||||
class E290Display : public DisplayDriver {
|
||||
EInkDisplay_VisionMasterE290 display;
|
||||
bool _init = false;
|
||||
bool _isOn = false;
|
||||
RefCountedDigitalPin* _periph_power;
|
||||
CRC32 display_crc;
|
||||
uint32_t last_display_crc_value = 0;
|
||||
|
||||
public:
|
||||
E290Display() : DisplayDriver(296, 128) {}
|
||||
E290Display(RefCountedDigitalPin* periph_power = NULL) : DisplayDriver(296, 128), _periph_power(periph_power) {}
|
||||
|
||||
bool begin();
|
||||
bool isOn() override { return _isOn; }
|
||||
|
|
@ -34,4 +39,4 @@ public:
|
|||
private:
|
||||
void powerOn();
|
||||
void powerOff();
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -21,10 +21,14 @@ bool ST7735Display::begin() {
|
|||
if (_peripher_power) _peripher_power->claim();
|
||||
|
||||
pinMode(PIN_TFT_LEDA_CTL, OUTPUT);
|
||||
digitalWrite(PIN_TFT_LEDA_CTL, HIGH);
|
||||
#if defined(PIN_TFT_LEDA_CTL_ACTIVE)
|
||||
digitalWrite(PIN_TFT_LEDA_CTL, PIN_TFT_LEDA_CTL_ACTIVE);
|
||||
#else
|
||||
digitalWrite(PIN_TFT_LEDA_CTL, HIGH);
|
||||
#endif
|
||||
digitalWrite(PIN_TFT_RST, HIGH);
|
||||
|
||||
#if defined(HELTEC_TRACKER_V2)
|
||||
#if defined(HELTEC_TRACKER_V2) || defined(HELTEC_T096)
|
||||
display.initR(INITR_MINI160x80);
|
||||
display.setRotation(DISPLAY_ROTATION);
|
||||
uint8_t madctl = ST77XX_MADCTL_MY | ST77XX_MADCTL_MV |ST7735_MADCTL_BGR;//Adjust color to BGR
|
||||
|
|
@ -50,9 +54,12 @@ void ST7735Display::turnOn() {
|
|||
|
||||
void ST7735Display::turnOff() {
|
||||
if (_isOn) {
|
||||
digitalWrite(PIN_TFT_LEDA_CTL, HIGH);
|
||||
digitalWrite(PIN_TFT_RST, LOW);
|
||||
digitalWrite(PIN_TFT_LEDA_CTL, LOW);
|
||||
#if defined(PIN_TFT_LEDA_CTL_ACTIVE)
|
||||
digitalWrite(PIN_TFT_LEDA_CTL, !PIN_TFT_LEDA_CTL_ACTIVE);
|
||||
#else
|
||||
digitalWrite(PIN_TFT_LEDA_CTL, LOW);
|
||||
#endif
|
||||
_isOn = false;
|
||||
|
||||
if (_peripher_power) _peripher_power->release();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue