diff --git a/src/mesh/MeshModule.cpp b/src/mesh/MeshModule.cpp index 2ef46e4db..04fa250bf 100644 --- a/src/mesh/MeshModule.cpp +++ b/src/mesh/MeshModule.cpp @@ -62,7 +62,10 @@ meshtastic_MeshPacket *MeshModule::allocAckNak(meshtastic_Routing_Error err, Nod meshtastic_MeshPacket *MeshModule::allocErrorResponse(meshtastic_Routing_Error err, const meshtastic_MeshPacket *p) { - auto r = allocAckNak(err, getFrom(p), p->id, p->channel); + // If the original packet couldn't be decoded, use the primary channel + uint8_t channelIndex = + p->which_payload_variant == meshtastic_MeshPacket_decoded_tag ? p->channel : channels.getPrimaryIndex(); + auto r = allocAckNak(err, getFrom(p), p->id, channelIndex); setReplyTo(r, *p); @@ -114,13 +117,13 @@ void MeshModule::callModules(meshtastic_MeshPacket &mp, RxSource src) /// Also: if a packet comes in on the local PC interface, we don't check for bound channels, because it is TRUSTED and /// it needs to to be able to fetch the initial admin packets without yet knowing any channels. - bool rxChannelOk = !pi.boundChannel || (mp.from == 0) || (strcasecmp(ch->settings.name, pi.boundChannel) == 0); + bool rxChannelOk = !pi.boundChannel || (mp.from == 0) || (ch && strcasecmp(ch->settings.name, pi.boundChannel) == 0); if (!rxChannelOk) { // no one should have already replied! assert(!currentReply); - if (mp.decoded.want_response) { + if (isDecoded && mp.decoded.want_response) { printPacket("packet on wrong channel, returning error", &mp); currentReply = pi.allocErrorResponse(meshtastic_Routing_Error_NOT_AUTHORIZED, &mp); } else @@ -138,7 +141,8 @@ void MeshModule::callModules(meshtastic_MeshPacket &mp, RxSource src) // because currently when the phone sends things, it sends things using the local node ID as the from address. A // better solution (FIXME) would be to let phones have their own distinct addresses and we 'route' to them like // any other node. - if (mp.decoded.want_response && toUs && (getFrom(&mp) != ourNodeNum || mp.to == ourNodeNum) && !currentReply) { + if (isDecoded && mp.decoded.want_response && toUs && (getFrom(&mp) != ourNodeNum || mp.to == ourNodeNum) && + !currentReply) { pi.sendResponse(mp); ignoreRequest = ignoreRequest || pi.ignoreRequest; // If at least one module asks it, we may ignore a request LOG_INFO("Asked module '%s' to send a response\n", pi.name); @@ -163,7 +167,7 @@ void MeshModule::callModules(meshtastic_MeshPacket &mp, RxSource src) pi.currentRequest = NULL; } - if (mp.decoded.want_response && toUs) { + if (isDecoded && mp.decoded.want_response && toUs) { if (currentReply) { printPacket("Sending response", currentReply); service.sendToMesh(currentReply); @@ -183,7 +187,7 @@ void MeshModule::callModules(meshtastic_MeshPacket &mp, RxSource src) } } - if (!moduleFound) { + if (!moduleFound && isDecoded) { LOG_DEBUG("No modules interested in portnum=%d, src=%s\n", mp.decoded.portnum, (src == RX_SRC_LOCAL) ? "LOCAL" : "REMOTE"); } diff --git a/src/mesh/RF95Interface.cpp b/src/mesh/RF95Interface.cpp index 5677e6eda..c5356ad3b 100644 --- a/src/mesh/RF95Interface.cpp +++ b/src/mesh/RF95Interface.cpp @@ -17,6 +17,48 @@ // if you set power to something higher than 17 or 20 you might fry your board. #define POWER_DEFAULT 17 // How much power to use if the user hasn't set a power level +#ifdef RADIOMASTER_900_BANDIT_NANO +// Structure to hold DAC and DB values +typedef struct { + uint8_t dac; + uint8_t db; +} DACDB; + +// Interpolation function +DACDB interpolate(uint8_t dbm, uint8_t dbm1, uint8_t dbm2, DACDB val1, DACDB val2) { + DACDB result; + double fraction = (double)(dbm - dbm1) / (dbm2 - dbm1); + result.dac = (uint8_t)(val1.dac + fraction * (val2.dac - val1.dac)); + result.db = (uint8_t)(val1.db + fraction * (val2.db - val1.db)); + return result; +} + +// Function to find the correct DAC and DB values based on dBm using interpolation +DACDB getDACandDB(uint8_t dbm) { + // Predefined values + static const struct { + uint8_t dbm; + DACDB values; + } dbmToDACDB[] = { + {20, {168, 2}}, // 100mW + {24, {148, 6}}, // 250mW + {27, {128, 9}}, // 500mW + {30, {90, 12}} // 1000mW + }; + const int numValues = sizeof(dbmToDACDB) / sizeof(dbmToDACDB[0]); + + // Find the interval dbm falls within and interpolate + for (int i = 0; i < numValues - 1; i++) { + if (dbm >= dbmToDACDB[i].dbm && dbm <= dbmToDACDB[i + 1].dbm) { + return interpolate(dbm, dbmToDACDB[i].dbm, dbmToDACDB[i + 1].dbm, dbmToDACDB[i].values, dbmToDACDB[i + 1].values); + } + } + + // Return a default value if no match is found and default to 100mW + DACDB defaultValue = {168, 2}; + return defaultValue; +} +#endif RF95Interface::RF95Interface(LockingArduinoHal *hal, RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy) @@ -52,9 +94,16 @@ bool RF95Interface::init() { RadioLibInterface::init(); +#ifdef RADIOMASTER_900_BANDIT_NANO + // DAC and DB values based on dBm using interpolation + DACDB dacDbValues = getDACandDB(power); + int8_t powerDAC = dacDbValues.dac; + power = dacDbValues.db; +#endif + if (power > RF95_MAX_POWER) // This chip has lower power limits than some power = RF95_MAX_POWER; - + limitPower(); iface = lora = new RadioLibRF95(&module); @@ -67,7 +116,13 @@ bool RF95Interface::init() // enable PA #ifdef RF95_PA_EN #if defined(RF95_PA_DAC_EN) - dacWrite(RF95_PA_EN, RF95_PA_LEVEL); + #ifdef RADIOMASTER_900_BANDIT_NANO + // Use calculated DAC value + dacWrite(RF95_PA_EN, powerDAC); + #else + // Use Value set in /*/variant.h + dacWrite(RF95_PA_EN, RF95_PA_LEVEL); + #endif #endif #endif @@ -107,6 +162,9 @@ bool RF95Interface::init() LOG_INFO("Frequency set to %f\n", getFreq()); LOG_INFO("Bandwidth set to %f\n", bw); LOG_INFO("Power output set to %d\n", power); +#ifdef RADIOMASTER_900_BANDIT_NANO + LOG_INFO("DAC output set to %d\n", powerDAC); +#endif if (res == RADIOLIB_ERR_NONE) res = lora->setCRC(RADIOLIB_SX126X_LORA_CRC_ON); @@ -259,4 +317,4 @@ bool RF95Interface::sleep() #endif return true; -} \ No newline at end of file +} diff --git a/src/modules/TraceRouteModule.cpp b/src/modules/TraceRouteModule.cpp index aa0b6a1eb..f390aafcd 100644 --- a/src/modules/TraceRouteModule.cpp +++ b/src/modules/TraceRouteModule.cpp @@ -16,17 +16,37 @@ bool TraceRouteModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, m void TraceRouteModule::alterReceivedProtobuf(meshtastic_MeshPacket &p, meshtastic_RouteDiscovery *r) { auto &incoming = p.decoded; - // Only append an ID for the request (one way) and if we are not the destination (the reply will have our NodeNum already) - if (!incoming.request_id && p.to != nodeDB->getNodeNum()) { - appendMyID(r); - printRoute(r, p.from, NODENUM_BROADCAST); + // Only append IDs for the request (one way) + if (!incoming.request_id) { + // Insert unknown hops if necessary + insertUnknownHops(p, r); + // Don't add ourselves if we are the destination (the reply will have our NodeNum already) + if (p.to != nodeDB->getNodeNum()) { + appendMyID(r); + printRoute(r, p.from, NODENUM_BROADCAST); + } // Set updated route to the payload of the to be flooded packet p.decoded.payload.size = pb_encode_to_bytes(p.decoded.payload.bytes, sizeof(p.decoded.payload.bytes), &meshtastic_RouteDiscovery_msg, r); } } +void TraceRouteModule::insertUnknownHops(meshtastic_MeshPacket &p, meshtastic_RouteDiscovery *r) +{ + // Only insert unknown hops if hop_start is valid + if (p.hop_start != 0 && p.hop_limit <= p.hop_start) { + uint8_t hopsTaken = p.hop_start - p.hop_limit; + int8_t diff = hopsTaken - r->route_count; + for (uint8_t i = 0; i < diff; i++) { + if (r->route_count < sizeof(r->route) / sizeof(r->route[0])) { + r->route[r->route_count] = NODENUM_BROADCAST; // This will represent an unknown hop + r->route_count += 1; + } + } + } +} + void TraceRouteModule::appendMyID(meshtastic_RouteDiscovery *updated) { // Length of route array can normally not be exceeded due to the max. hop_limit of 7 diff --git a/src/modules/TraceRouteModule.h b/src/modules/TraceRouteModule.h index 15e01debd..18a5ac0cb 100644 --- a/src/modules/TraceRouteModule.h +++ b/src/modules/TraceRouteModule.h @@ -19,6 +19,9 @@ class TraceRouteModule : public ProtobufModule void alterReceivedProtobuf(meshtastic_MeshPacket &p, meshtastic_RouteDiscovery *r) override; private: + // Call to add unknown hops (e.g. when a node couldn't decrypt it) to the route based on hopStart and current hopLimit + void insertUnknownHops(meshtastic_MeshPacket &p, meshtastic_RouteDiscovery *r); + // Call to add your ID to the route array of a RouteDiscovery message void appendMyID(meshtastic_RouteDiscovery *r); diff --git a/version.properties b/version.properties index 700044e6f..a26da1996 100644 --- a/version.properties +++ b/version.properties @@ -1,4 +1,4 @@ [VERSION] major = 2 minor = 3 -build = 12 +build = 13