diff --git a/decoder_modules/pager_decoder/src/pocsag/decoder.h b/decoder_modules/pager_decoder/src/pocsag/decoder.h index 54923755..506f8770 100644 --- a/decoder_modules/pager_decoder/src/pocsag/decoder.h +++ b/decoder_modules/pager_decoder/src/pocsag/decoder.h @@ -15,9 +15,12 @@ const char* msgTypes[] = { "Alphanumeric", }; +#define BAUDRATE 2400 +#define SAMPLERATE (BAUDRATE*10) + class POCSAGDecoder : public Decoder { public: - POCSAGDecoder(const std::string& name, VFOManager::VFO* vfo) : diag(0.6, 2400) { + POCSAGDecoder(const std::string& name, VFOManager::VFO* vfo) : diag(0.6, BAUDRATE) { this->name = name; this->vfo = vfo; @@ -28,9 +31,9 @@ public: // Init DSP vfo->setBandwidthLimits(12500, 12500, true); - vfo->setSampleRate(24000, 12500); - dsp.init(vfo->output, 24000, 2400); - reshape.init(&dsp.soft, 2400.0, (2400 / 30.0) - 2400.0); + vfo->setSampleRate(SAMPLERATE, 12500); + dsp.init(vfo->output, SAMPLERATE, BAUDRATE); + reshape.init(&dsp.soft, BAUDRATE, (BAUDRATE / 30.0) - BAUDRATE); dataHandler.init(&dsp.out, _dataHandler, this); diagHandler.init(&reshape.out, _diagHandler, this); @@ -49,6 +52,10 @@ public: // TODO } + if (ImGui::Button("Detune")) { + dsp.detune(); + } + ImGui::FillWidth(); diag.draw(); } diff --git a/decoder_modules/pager_decoder/src/pocsag/dsp.h b/decoder_modules/pager_decoder/src/pocsag/dsp.h index 3faca285..8b15c349 100644 --- a/decoder_modules/pager_decoder/src/pocsag/dsp.h +++ b/decoder_modules/pager_decoder/src/pocsag/dsp.h @@ -23,14 +23,14 @@ public: // Configure blocks demod.init(NULL, -4500.0, samplerate); - dcBlock.init(NULL, 0.001); + //dcBlock.init(NULL, 0.001); // NOTE: DC blocking causes issues because no scrambling, think more about it float taps[] = { 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f }; shape = dsp::taps::fromArray(10, taps); fir.init(NULL, shape); - recov.init(NULL, samplerate/baudrate, 1e5, 0.1, 0.05); + recov.init(NULL, samplerate/baudrate, 1e-4, 1.0, 0.05); // Free useless buffers - dcBlock.out.free(); + // dcBlock.out.free(); fir.out.free(); recov.out.free(); @@ -40,13 +40,17 @@ public: int process(int count, dsp::complex_t* in, float* softOut, uint8_t* out) { count = demod.process(count, in, demod.out.readBuf); - count = dcBlock.process(count, demod.out.readBuf, demod.out.readBuf); + //count = dcBlock.process(count, demod.out.readBuf, demod.out.readBuf); count = fir.process(count, demod.out.readBuf, demod.out.readBuf); count = recov.process(count, demod.out.readBuf, softOut); dsp::digital::BinarySlicer::process(count, softOut, out); return count; } + void detune() { + recov.setOmega(9.99); + } + int run() { int count = base_type::_in->read(); if (count < 0) { return -1; } @@ -63,7 +67,7 @@ public: private: dsp::demod::Quadrature demod; - dsp::correction::DCBlocker dcBlock; + //dsp::correction::DCBlocker dcBlock; dsp::tap shape; dsp::filter::FIR fir; dsp::clock_recovery::MM recov; diff --git a/decoder_modules/pager_decoder/src/pocsag/pocsag.cpp b/decoder_modules/pager_decoder/src/pocsag/pocsag.cpp index 572f69e7..e075df81 100644 --- a/decoder_modules/pager_decoder/src/pocsag/pocsag.cpp +++ b/decoder_modules/pager_decoder/src/pocsag/pocsag.cpp @@ -5,6 +5,7 @@ #define POCSAG_FRAME_SYNC_CODEWORD ((uint32_t)(0b01111100110100100001010111011000)) #define POCSAG_IDLE_CODEWORD_DATA ((uint32_t)(0b011110101100100111000)) #define POCSAG_BATCH_BIT_COUNT (POCSAG_BATCH_CODEWORD_COUNT*32) +#define POCSAG_DATA_BITS_PER_CW 20 #define POCSAG_GEN_POLY ((uint32_t)(0b11101101001)) @@ -28,6 +29,11 @@ namespace pocsag { '[' }; + Decoder::Decoder() { + // Zero out batch + memset(batch, 0, sizeof(batch)); + } + void Decoder::process(uint8_t* symbols, int count) { for (int i = 0; i < count; i++) { // Get symbol @@ -78,8 +84,37 @@ namespace pocsag { void Decoder::flushMessage() { if (!msg.empty()) { - onMessage(addr, msgType, msg); + + // Unpack bits + std::string outStr = ""; + + for (int i = 0; (i+7) <= msg.size(); i += 7) { + uint8_t b0 = msg[i]; + uint8_t b1 = msg[i+1]; + uint8_t b2 = msg[i+2]; + uint8_t b3 = msg[i+3]; + uint8_t b4 = msg[i+4]; + uint8_t b5 = msg[i+5]; + uint8_t b6 = msg[i+6]; + outStr += (char)((b6<<6) | (b5<<5) | (b4<<4) | (b3<<3) | (b2<<2) | (b1<<1) | b0); + } + + onMessage(addr, msgType, outStr); msg.clear(); + leftInLast = 0; + } + } + + void printbin(uint32_t cw) { + for (int i = 31; i >= 0; i--) { + printf("%c", ((cw >> i) & 1) ? '1':'0'); + } + } + + void bitswapChar(char in, char& out) { + out = 0; + for (int i = 0; i < 7; i++) { + out |= ((in >> (6-i)) & 1) << i; } } @@ -102,14 +137,14 @@ namespace pocsag { if (type == CODEWORD_TYPE_IDLE) { // If a non-empty message is available, send it out and clear flushMessage(); - flog::debug("[{}:{}]: IDLE", (i >> 1), i&1); } else if (type == CODEWORD_TYPE_ADDRESS) { // If a non-empty message is available, send it out and clear flushMessage(); // Decode message type - msgType = (MessageType)((cw >> 11) & 0b11); + msgType = MESSAGE_TYPE_ALPHANUMERIC; + // msgType = (MessageType)((cw >> 11) & 0b11); // Decode address and append lower 8 bits from position addr = ((cw >> 13) & 0b111111111111111111) << 3; @@ -122,14 +157,38 @@ namespace pocsag { // Decode data depending on message type if (msgType == MESSAGE_TYPE_NUMERIC) { // Numeric messages pack 5 characters per message codeword - msg += NUMERIC_CHARSET[(data >> 16) & 0b1111]; - msg += NUMERIC_CHARSET[(data >> 12) & 0b1111]; - msg += NUMERIC_CHARSET[(data >> 8) & 0b1111]; - msg += NUMERIC_CHARSET[(data >> 4) & 0b1111]; - msg += NUMERIC_CHARSET[data & 0b1111]; + //msg += NUMERIC_CHARSET[(data >> 16) & 0b1111]; + //msg += NUMERIC_CHARSET[(data >> 12) & 0b1111]; + //msg += NUMERIC_CHARSET[(data >> 8) & 0b1111]; + //msg += NUMERIC_CHARSET[(data >> 4) & 0b1111]; + //msg += NUMERIC_CHARSET[data & 0b1111]; } else if (msgType == MESSAGE_TYPE_ALPHANUMERIC) { - + // Alpha messages pack 7bit characters in the entire codeword stream + // int lasti; + // for (int i = -leftInLast; i <= POCSAG_DATA_BITS_PER_CW-7; i += 7) { + // // Read 7 bits + // char c = 0; + // if (i < 0) { + // c = (lastMsgData & ((1 << (-i)) - 1)) << (7+i); + // } + // c |= (data >> (13 - i)) & 0b1111111; + + // // Save character + // bitswapChar(c, c); + // msg += c; + + // // Update last successful unpack + // lasti = i; + // } + + // Pack the bits backwards + for (int i = 19; i >= 0; i--) { + msg += (char)((data >> i) & 1); + } + + // Save how much is still left to read + //leftInLast = 20 - (lasti + 7); } // Save last data diff --git a/decoder_modules/pager_decoder/src/pocsag/pocsag.h b/decoder_modules/pager_decoder/src/pocsag/pocsag.h index b0e78cfa..6452f59c 100644 --- a/decoder_modules/pager_decoder/src/pocsag/pocsag.h +++ b/decoder_modules/pager_decoder/src/pocsag/pocsag.h @@ -23,6 +23,8 @@ namespace pocsag { class Decoder { public: + Decoder(); + void process(uint8_t* symbols, int count); NewEvent onMessage; @@ -44,5 +46,6 @@ namespace pocsag { std::string msg; uint32_t lastMsgData; + bool leftInLast = 0; }; } \ No newline at end of file