diff --git a/src/shared/drivers/SX1278/SX1278.cpp b/src/shared/drivers/SX1278/SX1278.cpp index 52a91f3ba06520aa4b18974468319a22256b6774..6a7f718f422a9a298e225da2f7773b5b76c14062 100644 --- a/src/shared/drivers/SX1278/SX1278.cpp +++ b/src/shared/drivers/SX1278/SX1278.cpp @@ -31,6 +31,8 @@ namespace Boardcore using namespace SX1278Defs; +long long now() { return miosix::getTick() * 1000 / miosix::TICK_FREQ; } + // Default values for registers constexpr uint8_t REG_OP_MODE_DEFAULT = RegOpMode::LONG_RANGE_MODE_FSK | RegOpMode::MODULATION_TYPE_FSK | @@ -247,31 +249,55 @@ ssize_t SX1278::receive(uint8_t *pkt, size_t max_len) bool SX1278::send(uint8_t *pkt, size_t len) { - // Packets longer than 255 are not supported - if (len > 255) - return false; + // Hacked together larger packets support + while (len > 0) + { + // This shouldn't be needed, but for some reason the device "lies" about + // being ready, so lock up if we are going too fast + rateLimitTx(); - bus_mgr.lock(SX1278BusManager::Mode::MODE_TX); + bus_mgr.lock(SX1278BusManager::Mode::MODE_TX); - // Wait for TX ready - bus_mgr.waitForIrq(RegIrqFlags::TX_READY); + // Wait for TX ready + bus_mgr.waitForIrq(RegIrqFlags::TX_READY); - { - SPITransaction spi(bus_mgr.getBus(), - SPITransaction::WriteBit::INVERTED); + // Segment a packet that is bigger than the MTU (-1 for the length) + uint8_t pkt_len = std::min(len, FIFO_LEN - 1); + + { + SPITransaction spi(bus_mgr.getBus(), + SPITransaction::WriteBit::INVERTED); + + spi.writeRegister(REG_FIFO, pkt_len); + spi.writeRegisters(REG_FIFO, pkt, pkt_len); + } + + // Wait for packet sent + bus_mgr.waitForIrq(RegIrqFlags::PACKET_SENT); + + pkt += pkt_len; + len -= pkt_len; + bus_mgr.unlock(); - spi.writeRegister(REG_FIFO, static_cast<uint8_t>(len)); - spi.writeRegisters(REG_FIFO, pkt, len); + last_tx = now(); } - // Wait for packet sent - bus_mgr.waitForIrq(RegIrqFlags::PACKET_SENT); - bus_mgr.unlock(); return true; } void SX1278::handleDioIRQ() { bus_mgr.handleDioIRQ(); } +void SX1278::rateLimitTx() +{ + const long long RATE_LIMIT = 2; + + long long delta = now() - last_tx; + if (delta <= RATE_LIMIT) + { + miosix::Thread::sleep(RATE_LIMIT - delta); + } +} + uint8_t SX1278::getVersion() { SPITransaction spi(bus_mgr.getBus(), SPITransaction::WriteBit::INVERTED); diff --git a/src/shared/drivers/SX1278/SX1278.h b/src/shared/drivers/SX1278/SX1278.h index 6fb4c355d36f81331e7299e6a291e58c737e4156..3d89a9f9494a95ddcae4871f84a8c21132571066 100644 --- a/src/shared/drivers/SX1278/SX1278.h +++ b/src/shared/drivers/SX1278/SX1278.h @@ -228,6 +228,8 @@ public: public: using Mode = SX1278BusManager::Mode; + void rateLimitTx(); + void setBitrate(int bitrate); void setFreqDev(int freq_dev); void setFreqRF(int freq_rf); @@ -240,6 +242,7 @@ public: void waitForIrq(uint16_t mask); + long long last_tx = 0; SX1278BusManager bus_mgr; PrintLogger logger = Logging::getLogger("sx1278"); }; diff --git a/src/shared/drivers/SX1278/SX1278Defs.h b/src/shared/drivers/SX1278/SX1278Defs.h index cd50d09a8c3294659f1c1186f2ad1fd0512937c6..f38059551c2ca51b04393263044abc0abc004715 100644 --- a/src/shared/drivers/SX1278/SX1278Defs.h +++ b/src/shared/drivers/SX1278/SX1278Defs.h @@ -33,6 +33,11 @@ namespace Boardcore namespace SX1278Defs { +/** + * @brief Length of the fifo. + */ +constexpr size_t FIFO_LEN = 64; + /** * @brief Main oscillator frequency (Hz) */ diff --git a/src/tests/drivers/sx1278/test-sx1278-bench.cpp b/src/tests/drivers/sx1278/test-sx1278-bench.cpp index 5ddb67f00a8800f77f5597fa3c9538fb8496a6e5..3d46b9b4690516eb6d241ee56a62d0f07e5ffe6e 100644 --- a/src/tests/drivers/sx1278/test-sx1278-bench.cpp +++ b/src/tests/drivers/sx1278/test-sx1278-bench.cpp @@ -93,9 +93,6 @@ struct Stats } stats; -/// Interval between transmissions. -const int TX_INTERVAL = 1; - SX1278 *sx1278[2] = {nullptr, nullptr}; struct Msg @@ -115,12 +112,10 @@ void recvLoop(int idx) while (1) { Msg msg; - msg.idx = 0; - msg.dummy_1 = 0; - msg.dummy_2 = 0; - msg.dummy_3 = 0; + memset(&msg, 0, sizeof(msg)); int len = sx1278[idx]->receive((uint8_t *)&msg, sizeof(msg)); + if (len != sizeof(msg)) { stats.recv_errors++; @@ -143,8 +138,6 @@ void sendLoop(int idx) { while (1) { - miosix::Thread::sleep(TX_INTERVAL); - int next_idx = stats.send_count + 1; Msg msg; @@ -269,6 +262,7 @@ int main() std::thread recv([]() { recvLoop(0); }); #endif #ifndef DISABLE_TX + miosix::Thread::sleep(500); std::thread send([]() { sendLoop(1); }); #endif