From 68367c2d09ee1ffa4994ca90acf59bb261c7fcdc Mon Sep 17 00:00:00 2001 From: Georgi Gerganov Date: Sat, 11 Jun 2022 15:23:02 +0300 Subject: [PATCH] ggwave : optimize memory footprint even more --- examples/arduino-tx2/arduino-tx2.ino | 5 ++++ include/ggwave/ggwave.h | 34 ++++++++++++++++++---------- src/ggwave.cpp | 33 +++++++++++++++------------ 3 files changed, 45 insertions(+), 27 deletions(-) diff --git a/examples/arduino-tx2/arduino-tx2.ino b/examples/arduino-tx2/arduino-tx2.ino index 6a89c70..8ccaf6e 100644 --- a/examples/arduino-tx2/arduino-tx2.ino +++ b/examples/arduino-tx2/arduino-tx2.ino @@ -11,6 +11,9 @@ const int sampleRate = 6000; GGWave * g_ggwave = nullptr; void send_text(GGWave & ggwave, uint8_t pin, const char * text, GGWave::TxProtocolId protocolId) { + Serial.print(F("Sending text: ")); + Serial.println(text); + ggwave.init(text, protocolId); ggwave.encode(); @@ -64,6 +67,8 @@ bool isDown = false; #define P(str) (strcpy_P(txt, PSTR(str)), txt) void loop() { + Serial.println(F("Starting main loop")); + auto & ggwave = *g_ggwave; delay(1000); diff --git a/include/ggwave/ggwave.h b/include/ggwave/ggwave.h index 6991a0b..4cad003 100644 --- a/include/ggwave/ggwave.h +++ b/include/ggwave/ggwave.h @@ -389,6 +389,10 @@ public: #include #include +#ifdef ARDUINO +#include +#endif + class GGWave { public: static constexpr auto kSampleRateMin = 1000.0f; @@ -480,22 +484,28 @@ public: protocols.data[i].name = nullptr; protocols.data[i].enabled = false; } +#ifndef ARDUINO +#define PSTR(str) (str) +#endif #ifndef GGWAVE_CONFIG_FEW_PROTOCOLS - protocols.data[GGWAVE_PROTOCOL_AUDIBLE_NORMAL] = { "Normal", 40, 9, 3, 1, true, }; - protocols.data[GGWAVE_PROTOCOL_AUDIBLE_FAST] = { "Fast", 40, 6, 3, 1, true, }; - protocols.data[GGWAVE_PROTOCOL_AUDIBLE_FASTEST] = { "Fastest", 40, 3, 3, 1, true, }; - protocols.data[GGWAVE_PROTOCOL_ULTRASOUND_NORMAL] = { "[U] Normal", 320, 9, 3, 1, true, }; - protocols.data[GGWAVE_PROTOCOL_ULTRASOUND_FAST] = { "[U] Fast", 320, 6, 3, 1, true, }; - protocols.data[GGWAVE_PROTOCOL_ULTRASOUND_FASTEST] = { "[U] Fastest", 320, 3, 3, 1, true, }; - protocols.data[GGWAVE_PROTOCOL_DT_NORMAL] = { "[DT] Normal", 24, 9, 1, 1, true, }; - protocols.data[GGWAVE_PROTOCOL_DT_FAST] = { "[DT] Fast", 24, 6, 1, 1, true, }; - protocols.data[GGWAVE_PROTOCOL_DT_FASTEST] = { "[DT] Fastest", 24, 3, 1, 1, true, }; + protocols.data[GGWAVE_PROTOCOL_AUDIBLE_NORMAL] = { PSTR("Normal"), 40, 9, 3, 1, true, }; + protocols.data[GGWAVE_PROTOCOL_AUDIBLE_FAST] = { PSTR("Fast"), 40, 6, 3, 1, true, }; + protocols.data[GGWAVE_PROTOCOL_AUDIBLE_FASTEST] = { PSTR("Fastest"), 40, 3, 3, 1, true, }; + protocols.data[GGWAVE_PROTOCOL_ULTRASOUND_NORMAL] = { PSTR("[U] Normal"), 320, 9, 3, 1, true, }; + protocols.data[GGWAVE_PROTOCOL_ULTRASOUND_FAST] = { PSTR("[U] Fast"), 320, 6, 3, 1, true, }; + protocols.data[GGWAVE_PROTOCOL_ULTRASOUND_FASTEST] = { PSTR("[U] Fastest"), 320, 3, 3, 1, true, }; + protocols.data[GGWAVE_PROTOCOL_DT_NORMAL] = { PSTR("[DT] Normal"), 24, 9, 1, 1, true, }; + protocols.data[GGWAVE_PROTOCOL_DT_FAST] = { PSTR("[DT] Fast"), 24, 6, 1, 1, true, }; + protocols.data[GGWAVE_PROTOCOL_DT_FASTEST] = { PSTR("[DT] Fastest"), 24, 3, 1, 1, true, }; #endif - protocols.data[GGWAVE_PROTOCOL_MT_NORMAL] = { "[MT] Normal", 24, 9, 1, 2, true, }; - protocols.data[GGWAVE_PROTOCOL_MT_FAST] = { "[MT] Fast", 24, 6, 1, 2, true, }; - protocols.data[GGWAVE_PROTOCOL_MT_FASTEST] = { "[MT] Fastest", 24, 3, 1, 2, true, }; + protocols.data[GGWAVE_PROTOCOL_MT_NORMAL] = { PSTR("[MT] Normal"), 24, 9, 1, 2, true, }; + protocols.data[GGWAVE_PROTOCOL_MT_FAST] = { PSTR("[MT] Fast"), 24, 6, 1, 2, true, }; + protocols.data[GGWAVE_PROTOCOL_MT_FASTEST] = { PSTR("[MT] Fastest"), 24, 3, 1, 2, true, }; +#ifndef ARDUINO +#undef PSTR +#endif initialized = true; } diff --git a/src/ggwave.cpp b/src/ggwave.cpp index 70a5406..a770ab4 100644 --- a/src/ggwave.cpp +++ b/src/ggwave.cpp @@ -2,8 +2,6 @@ #if !defined(ARDUINO) && !defined(PROGMEM) #define PROGMEM -#else -#include #endif #include "fft.h" @@ -317,7 +315,9 @@ template struct ggvector; template void ggmatrix::zero() { - memset(m_data, 0, m_size0*m_size1*sizeof(T)); + if (m_size0 > 0 && m_size1 > 0) { + memset(m_data, 0, m_size0*m_size1*sizeof(T)); + } } // @@ -539,8 +539,18 @@ bool GGWave::prepare(const Parameters & parameters) { } bool GGWave::alloc(void * p, int & n) { + const int maxLength = m_isFixedPayloadLength ? m_payloadLength : kMaxLengthVariable; + const int totalLength = maxLength + getECCBytesForLength(maxLength); + const int totalTxs = (totalLength + minBytesPerTx(Protocols::rx()) - 1)/minBytesPerTx(Protocols::tx()); + + if (totalLength > kMaxDataSize) { + ggprintf("Error: total length %d (payload %d + ECC %d bytes) is too large ( > %d)\n", + totalLength, maxLength, getECCBytesForLength(maxLength), kMaxDataSize); + return false; + } + // common - ::ggalloc(m_dataEncoded, kMaxDataSize, p, n); + ::ggalloc(m_dataEncoded, totalLength + m_encodedDataOffset, p, n); if (m_isRxEnabled) { ::ggalloc(m_rx.fftOut, 2*m_samplesPerFrame, p, n); @@ -554,7 +564,7 @@ bool GGWave::alloc(void * p, int & n) { ::ggalloc(m_rx.amplitudeResampled, m_needResampling ? 8*m_samplesPerFrame : m_samplesPerFrame, p, n); ::ggalloc(m_rx.amplitudeTmp, m_needResampling ? 8*m_samplesPerFrame*m_sampleSizeInp : m_samplesPerFrame*m_sampleSizeInp, p, n); - ::ggalloc(m_rx.data, kMaxDataSize, p, n); + ::ggalloc(m_rx.data, maxLength + 1, p, n); // extra byte for null-termination if (m_isFixedPayloadLength) { if (m_payloadLength > kMaxLengthFixed) { @@ -562,9 +572,6 @@ bool GGWave::alloc(void * p, int & n) { return false; } - const int totalLength = m_payloadLength + getECCBytesForLength(m_payloadLength); - const int totalTxs = (totalLength + minBytesPerTx(Protocols::rx()) - 1)/minBytesPerTx(Protocols::rx()); - ::ggalloc(m_rx.spectrumHistoryFixed, totalTxs*maxFramesPerTx(Protocols::rx(), false), m_samplesPerFrame, p, n); ::ggalloc(m_rx.detectedBins, 2*totalLength, p, n); ::ggalloc(m_rx.detectedTones, 2*16*maxBytesPerTx(Protocols::rx()), p, n); @@ -579,9 +586,6 @@ bool GGWave::alloc(void * p, int & n) { if (m_isTxEnabled) { const int maxDataBits = 2*16*maxBytesPerTx(Protocols::tx()); - ::ggalloc(m_tx.data, kMaxDataSize, p, n); - ::ggalloc(m_tx.dataBits, maxDataBits, p, n); - if (m_txOnlyTones == false) { ::ggalloc(m_tx.phaseOffsets, maxDataBits, p, n); ::ggalloc(m_tx.bit0Amplitude, maxDataBits, m_samplesPerFrame, p, n); @@ -592,12 +596,11 @@ bool GGWave::alloc(void * p, int & n) { ::ggalloc(m_tx.outputI16, kMaxRecordedFrames*m_samplesPerFrame, p, n); } - const int maxLength = m_isFixedPayloadLength ? m_payloadLength : kMaxLengthVariable; - const int totalLength = maxLength + getECCBytesForLength(maxLength); - const int totalTxs = (totalLength + minBytesPerTx(Protocols::rx()) - 1)/minBytesPerTx(Protocols::tx()); const int maxTones = m_isFixedPayloadLength ? maxTonesPerTx(Protocols::tx()) : m_nBitsInMarker; - ::ggalloc(m_tx.tones, maxTones*totalTxs + (maxTones > 1 ? totalTxs : 0), p, n); + ::ggalloc(m_tx.data, maxLength + 1, p, n); // first byte stores the length + ::ggalloc(m_tx.dataBits, maxDataBits, p, n); + ::ggalloc(m_tx.tones, maxTones*totalTxs + (maxTones > 1 ? totalTxs : 0), p, n); } // pre-allocate Reed-Solomon memory buffers