diff --git a/TODO.md b/TODO.md index cf1e74b12..dc5a148da 100644 --- a/TODO.md +++ b/TODO.md @@ -2,13 +2,27 @@ # High priority -* add mesh layer -* wrap in nice MeshRadio class +* make protobufs more real +* attach mesh service to radio and bluetooth # Medium priority * add interrupt detach/sleep mode config to lora radio so we can enable deepsleep without panicing +* figure out if we can use PA_BOOST +* scrub default radio config settings for bandwidth/range/speed +* use a freertos thread to remain blocked reading from recvfromAckTimeout, so that we don't need to keep polling it from our main thread +* override peekAtMessage so we can see any messages that pass through our node (even if not broadcast)? would that be useful? + +# Pre-beta priority + +* make sure main cpu is not woken for packets with bad crc or not addressed to this node - do that in the radio hw +* enable fast init inside the gps chip +* dynamically select node nums +* triple check fcc compliance +* allow setting full radio params from android # Done * change the partition table to take advantage of the 4MB flash on the wroom: http://docs.platformio.org/en/latest/platforms/espressif32.html#partition-tables +* wrap in nice MeshRadio class +* add mesh send & rx diff --git a/lib/BluetoothOTA/src/MeshBluetoothService.cpp b/lib/BluetoothOTA/src/MeshBluetoothService.cpp index 135a2b05a..44fb34eea 100644 --- a/lib/BluetoothOTA/src/MeshBluetoothService.cpp +++ b/lib/BluetoothOTA/src/MeshBluetoothService.cpp @@ -43,7 +43,7 @@ public: mesh sw does if it does conflict? would it be better for people who are replying with denynode num to just broadcast their denial?) }; -class Mesh { +class MeshRadio { public: @@ -51,11 +51,11 @@ public: void handleFromMesh(NodeNum fromNode, NodeNum toNode, std::string s); /// handle a packet from the phone, send it on the mesh - void handleFromRadio(MeshPacket p); + void handleToMesh(MeshPacket p); }; /// Top level app for this service. keeps the mesh, the radio config and the queue of received packets. -class MeshRadio { +class MeshService { public: }; diff --git a/src/MeshRadio.cpp b/src/MeshRadio.cpp index d6fde2fe2..261e7c151 100644 --- a/src/MeshRadio.cpp +++ b/src/MeshRadio.cpp @@ -1,47 +1,84 @@ #include #include +#include +#include #include "MeshRadio.h" #include "configuration.h" -// Singleton instance of the radio driver -RH_RF95 rf95(NSS_GPIO, DIO0_GPIO); + // Change to 434.0 or other frequency, must match RX's freq! #define RF95_FREQ 915.0 +MeshRadio radio; + +/** + * get our starting (provisional) nodenum from flash. But check first if anyone else is using it, by trying to send a message to it (arping) + */ +NodeNum getDesiredNodeNum() { + uint8_t dmac[6]; + esp_efuse_mac_get_default(dmac); + + // FIXME + uint8_t r = dmac[5]; + assert(r != 0xff); // It better not be the broadcast address + return r; +} + + +MeshRadio::MeshRadio() : rf95(NSS_GPIO, DIO0_GPIO), manager(rf95, getDesiredNodeNum()) { + +} + +bool MeshRadio::init() { + pinMode(RESET_GPIO, OUTPUT); // Deassert reset + digitalWrite(RESET_GPIO, HIGH); + + // pulse reset + digitalWrite(RESET_GPIO, LOW); + delay(10); + digitalWrite(RESET_GPIO, HIGH); + delay(10); + + if (!manager.init()) { + Serial.println("LoRa radio init failed"); + Serial.println("Uncomment '#define SERIAL_DEBUG' in RH_RF95.cpp for detailed debug info"); + return false; + } + + Serial.println("LoRa radio init OK!"); + + // Defaults after init are 434.0MHz, modulation GFSK_Rb250Fd250, +13dbM + if (!rf95.setFrequency(RF95_FREQ)) { + Serial.println("setFrequency failed"); + while (1); + } + Serial.print("Set Freq to: "); Serial.println(RF95_FREQ); + + // Defaults after init are 434.0MHz, 13dBm, Bw = 125 kHz, Cr = 4/5, Sf = 128chips/symbol, CRC on + + // The default transmitter power is 13dBm, using PA_BOOST. + // If you are using RFM95/96/97/98 modules which uses the PA_BOOST transmitter pin, then + // you can set transmitter powers from 5 to 23 dBm: + // FIXME - can we do this? + // rf95.setTxPower(23, false); +} + + +ErrorCode MeshRadio::sendTo(NodeNum dest, const uint8_t *buf, size_t len) { + return manager.sendtoWait((uint8_t *) buf, len, dest); +} + +void MeshRadio::loop() { + // FIXME read from radio with recvfromAckTimeout +} void mesh_init() { - pinMode(RESET_GPIO, OUTPUT); - digitalWrite(RESET_GPIO, HIGH); - - - // manual reset - digitalWrite(RESET_GPIO, LOW); - delay(10); - digitalWrite(RESET_GPIO, HIGH); - delay(10); - - while (!rf95.init()) { - Serial.println("LoRa radio init failed"); - Serial.println("Uncomment '#define SERIAL_DEBUG' in RH_RF95.cpp for detailed debug info"); + while (!radio.init()) { + Serial.println("radio init failed"); while (1); } - Serial.println("LoRa radio init OK!"); - - // Defaults after init are 434.0MHz, modulation GFSK_Rb250Fd250, +13dbM - if (!rf95.setFrequency(RF95_FREQ)) { - Serial.println("setFrequency failed"); - while (1); - } - Serial.print("Set Freq to: "); Serial.println(RF95_FREQ); - - // Defaults after init are 434.0MHz, 13dBm, Bw = 125 kHz, Cr = 4/5, Sf = 128chips/symbol, CRC on - - // The default transmitter power is 13dBm, using PA_BOOST. - // If you are using RFM95/96/97/98 modules which uses the PA_BOOST transmitter pin, then - // you can set transmitter powers from 5 to 23 dBm: - rf95.setTxPower(23, false); } @@ -49,15 +86,14 @@ int16_t packetnum = 0; // packet counter, we increment per xmission void mesh_loop() { + radio.loop(); + delay(1000); // Wait 1 second between transmits, could also 'sleep' here! Serial.println("Transmitting..."); // Send a message to rf95_server char radiopacket[20] = "Hello World # "; - itoa(packetnum++, radiopacket+13, 10); - Serial.print("Sending "); Serial.println(radiopacket); - radiopacket[19] = 0; + sprintf(radiopacket, "hello %d", packetnum++); Serial.println("Sending..."); - delay(10); - rf95.send((uint8_t *)radiopacket, 20); + radio.sendTo(NODENUM_BROADCAST, (uint8_t *)radiopacket, sizeof(radiopacket)); } diff --git a/src/MeshRadio.h b/src/MeshRadio.h index 1a66f9100..11b915476 100644 --- a/src/MeshRadio.h +++ b/src/MeshRadio.h @@ -1,4 +1,37 @@ #pragma once +#include +#include + +#define NODENUM_BROADCAST 255 + +typedef int ErrorCode; +typedef uint8_t NodeNum; + + +/** + * A raw low level interface to our mesh. Only understands nodenums and bytes (not protobufs or node ids) + */ +class MeshRadio { +public: + MeshRadio(); + + bool init(); + + /// Send a packet - the current implementation blocks for a while possibly (FIXME) + ErrorCode sendTo(NodeNum dest, const uint8_t *buf, size_t len); + + /// Do loop callback operations (we currently FIXME poll the receive mailbox here) + void loop(); + + +private: + RH_RF95 rf95; // the raw radio interface + RHMesh manager; + +}; + +extern MeshRadio radio; + void mesh_init(); void mesh_loop(); \ No newline at end of file