diff --git a/core/src/dsp/meteor/hrpt.h b/core/src/dsp/meteor/hrpt.h new file mode 100644 index 0000000..33ca08c --- /dev/null +++ b/core/src/dsp/meteor/hrpt.h @@ -0,0 +1,65 @@ +#pragma once +#include +#include + +namespace dsp { + namespace meteor { + class HRPTDemux : public generic_block { + public: + HRPTDemux() {} + + HRPTDemux(stream* in) { init(in); } + + void init(stream* in) { + _in = in; + generic_block::registerInput(_in); + generic_block::registerOutput(&telemOut); + generic_block::registerOutput(&BISMout); + generic_block::registerOutput(&SSPDOut); + generic_block::registerOutput(&MTVZAOut); + generic_block::registerOutput(&MSUMROut); + } + + void setInput(stream* in) { + std::lock_guard lck(generic_block::ctrlMtx); + generic_block::tempStop(); + generic_block::unregisterInput(_in); + _in = in; + generic_block::registerInput(_in); + generic_block::tempStart(); + } + + int run() { + int count = _in->read(); + if (count < 0) { return -1; } + + for (int i = 0; i < 4; i++) { + memcpy(telemOut.writeBuf + (i * 2), _in->readBuf + 4 + (i * 256), 2); + memcpy(BISMout.writeBuf + (i * 4), _in->readBuf + 4 + (i * 256) + 2, 4); + memcpy(SSPDOut.writeBuf + (i * 4), _in->readBuf + 4 + (i * 256) + 6, 4); + memcpy(MTVZAOut.writeBuf + (i * 8), _in->readBuf + 4 + (i * 256) + 10, 8); + memcpy(MSUMROut.writeBuf + (i * 238), _in->readBuf + 4 + (i * 256) + 18, (i == 3) ? 234 : 238); + } + + if (!telemOut.swap(8)) { return -1; } + if (!BISMout.swap(16)) { return -1; } + if (!SSPDOut.swap(16)) { return -1; } + if (!MTVZAOut.swap(32)) { return -1; } + if (!MSUMROut.swap(948)) { return -1; } + + _in->flush(); + return count; + } + + stream telemOut; + stream BISMout; + stream SSPDOut; + stream MTVZAOut; + stream MSUMROut; + + private: + stream* _in; + + }; + } +} \ No newline at end of file diff --git a/core/src/dsp/meteor/msumr.h b/core/src/dsp/meteor/msumr.h new file mode 100644 index 0000000..10195ad --- /dev/null +++ b/core/src/dsp/meteor/msumr.h @@ -0,0 +1,76 @@ +#pragma once +#include +#include + +namespace dsp { + namespace meteor { + const uint64_t MSUMR_SYNC_WORD = 0x0218A7A392DD9ABF; + const uint8_t MSUMR_SYNC_BYTES[8] = { 0x02, 0x18, 0xA7, 0xA3, 0x92, 0xDD, 0x9A, 0xBF }; + + class MSUMRDemux : public generic_block { + public: + MSUMRDemux() {} + + MSUMRDemux(stream* in) { init(in); } + + void init(stream* in) { + _in = in; + generic_block::registerInput(_in); + generic_block::registerOutput(&msumr1Out); + generic_block::registerOutput(&msumr2Out); + generic_block::registerOutput(&msumr3Out); + generic_block::registerOutput(&msumr4Out); + generic_block::registerOutput(&msumr5Out); + generic_block::registerOutput(&msumr6Out); + } + + void setInput(stream* in) { + std::lock_guard lck(generic_block::ctrlMtx); + generic_block::tempStop(); + generic_block::unregisterInput(_in); + _in = in; + generic_block::registerInput(_in); + generic_block::tempStart(); + } + + int run() { + int count = _in->read(); + if (count < 0) { return -1; } + + int pixels = 0; + for (int i = 0; i < 11790; i += 30) { + for (int j = 0; j < 4; j++) { + msumr1Out.writeBuf[pixels + j] = (uint16_t)readBits((50 * 8) + (i * 8) + (j * 10), 10, _in->readBuf); + msumr2Out.writeBuf[pixels + j] = (uint16_t)readBits((50 * 8) + (i * 8) + (j * 10) + (40 * 1), 10, _in->readBuf); + msumr3Out.writeBuf[pixels + j] = (uint16_t)readBits((50 * 8) + (i * 8) + (j * 10) + (40 * 2), 10, _in->readBuf); + msumr4Out.writeBuf[pixels + j] = (uint16_t)readBits((50 * 8) + (i * 8) + (j * 10) + (40 * 3), 10, _in->readBuf); + msumr5Out.writeBuf[pixels + j] = (uint16_t)readBits((50 * 8) + (i * 8) + (j * 10) + (40 * 4), 10, _in->readBuf); + msumr6Out.writeBuf[pixels + j] = (uint16_t)readBits((50 * 8) + (i * 8) + (j * 10) + (40 * 5), 10, _in->readBuf); + } + pixels += 4; + } + + if (!msumr1Out.swap(1572)) { return -1; } + if (!msumr2Out.swap(1572)) { return -1; } + if (!msumr3Out.swap(1572)) { return -1; } + if (!msumr4Out.swap(1572)) { return -1; } + if (!msumr5Out.swap(1572)) { return -1; } + if (!msumr6Out.swap(1572)) { return -1; } + + _in->flush(); + return count; + } + + stream msumr1Out; + stream msumr2Out; + stream msumr3Out; + stream msumr4Out; + stream msumr5Out; + stream msumr6Out; + + private: + stream* _in; + + }; + } +} \ No newline at end of file diff --git a/core/src/dsp/noaa/hrpt.h b/core/src/dsp/noaa/hrpt.h new file mode 100644 index 0000000..e28ba3d --- /dev/null +++ b/core/src/dsp/noaa/hrpt.h @@ -0,0 +1,109 @@ +#pragma once +#include +#include + +namespace dsp { + namespace noaa { + inline uint16_t HRPTReadWord(int offset, uint8_t* buffer) { + return (uint16_t)readBits(offset * 10, 10, buffer); + } + + const uint8_t HRPTSyncWord[] = { + 1,0,1,0,0,0,0,1,0,0, + 0,1,0,1,1,0,1,1,1,1, + 1,1,0,1,0,1,1,1,0,0, + 0,1,1,0,0,1,1,1,0,1, + 1,0,0,0,0,0,1,1,1,1, + 0,0,1,0,0,1,0,1,0,1 + }; + + class HRPTDemux : public generic_block { + public: + HRPTDemux() {} + + HRPTDemux(stream* in) { init(in); } + + void init(stream* in) { + _in = in; + generic_block::registerInput(_in); + generic_block::registerOutput(&AVHRRChan1Out); + generic_block::registerOutput(&AVHRRChan2Out); + generic_block::registerOutput(&AVHRRChan3Out); + generic_block::registerOutput(&AVHRRChan4Out); + generic_block::registerOutput(&AVHRRChan5Out); + } + + void setInput(stream* in) { + std::lock_guard lck(generic_block::ctrlMtx); + generic_block::tempStop(); + generic_block::unregisterInput(_in); + _in = in; + generic_block::registerInput(_in); + generic_block::tempStart(); + } + + int run() { + int count = _in->read(); + if (count < 0) { return -1; } + + int minFrame = readBits(61, 2, _in->readBuf); + + // If GAC frame, reject + if (minFrame == 0) { + _in->flush(); + return count; + } + + // Extract TIP frames if present + if (minFrame == 1) { + for (int i = 0; i < 5; i++) { + for (int j = 0; j < 104; j++) { + TIPOut.writeBuf[j] = (HRPTReadWord(103 + (i * 104) + j, _in->readBuf) >> 2) & 0xFF; + } + if (!TIPOut.swap(104)) { return -1; }; + } + } + + // Exctact AIP otherwise + else if (minFrame == 3) { + for (int i = 0; i < 5; i++) { + for (int j = 0; j < 104; j++) { + AIPOut.writeBuf[j] = (HRPTReadWord(103 + (i * 104) + j, _in->readBuf) >> 2) & 0xFF; + } + if (!AIPOut.swap(104)) { return -1; }; + } + } + + // Extract AVHRR data + for (int i = 0; i < 2048; i++) { + AVHRRChan1Out.writeBuf[i] = HRPTReadWord(750 + (i * 5), _in->readBuf); + AVHRRChan2Out.writeBuf[i] = HRPTReadWord(750 + (i * 5) + 1, _in->readBuf); + AVHRRChan3Out.writeBuf[i] = HRPTReadWord(750 + (i * 5) + 2, _in->readBuf); + AVHRRChan4Out.writeBuf[i] = HRPTReadWord(750 + (i * 5) + 3, _in->readBuf); + AVHRRChan5Out.writeBuf[i] = HRPTReadWord(750 + (i * 5) + 4, _in->readBuf); + } + if (!AVHRRChan1Out.swap(2048)) { return -1; }; + if (!AVHRRChan2Out.swap(2048)) { return -1; }; + if (!AVHRRChan3Out.swap(2048)) { return -1; }; + if (!AVHRRChan4Out.swap(2048)) { return -1; }; + if (!AVHRRChan5Out.swap(2048)) { return -1; }; + + _in->flush(); + return count; + } + + stream TIPOut; + stream AIPOut; + + stream AVHRRChan1Out; + stream AVHRRChan2Out; + stream AVHRRChan3Out; + stream AVHRRChan4Out; + stream AVHRRChan5Out; + + private: + stream* _in; + + }; + } +} diff --git a/core/src/dsp/noaa/tip.h b/core/src/dsp/noaa/tip.h new file mode 100644 index 0000000..c7bf7e1 --- /dev/null +++ b/core/src/dsp/noaa/tip.h @@ -0,0 +1,240 @@ +#pragma once +#include +#include + +namespace dsp { + namespace noaa { + class TIPDemux : public generic_block { + public: + TIPDemux() {} + + TIPDemux(stream* in) { init(in); } + + void init(stream* in) { + _in = in; + generic_block::registerInput(_in); + generic_block::registerOutput(&HIRSOut); + generic_block::registerOutput(&SEMOut); + generic_block::registerOutput(&DCSOut); + generic_block::registerOutput(&SBUVOut); + } + + void setInput(stream* in) { + std::lock_guard lck(generic_block::ctrlMtx); + generic_block::tempStop(); + generic_block::unregisterInput(_in); + _in = in; + generic_block::registerInput(_in); + generic_block::tempStart(); + } + + int run() { + int count = _in->read(); + if (count < 0) { return -1; } + + // Extract HIRS + HIRSOut.writeBuf[0] = _in->readBuf[16]; + HIRSOut.writeBuf[1] = _in->readBuf[17]; + HIRSOut.writeBuf[2] = _in->readBuf[22]; + HIRSOut.writeBuf[3] = _in->readBuf[23]; + HIRSOut.writeBuf[4] = _in->readBuf[26]; + HIRSOut.writeBuf[5] = _in->readBuf[27]; + HIRSOut.writeBuf[6] = _in->readBuf[30]; + HIRSOut.writeBuf[7] = _in->readBuf[31]; + HIRSOut.writeBuf[8] = _in->readBuf[34]; + HIRSOut.writeBuf[9] = _in->readBuf[35]; + HIRSOut.writeBuf[10] = _in->readBuf[38]; + HIRSOut.writeBuf[11] = _in->readBuf[39]; + HIRSOut.writeBuf[12] = _in->readBuf[42]; + HIRSOut.writeBuf[13] = _in->readBuf[43]; + HIRSOut.writeBuf[14] = _in->readBuf[54]; + HIRSOut.writeBuf[15] = _in->readBuf[55]; + HIRSOut.writeBuf[16] = _in->readBuf[58]; + HIRSOut.writeBuf[17] = _in->readBuf[59]; + HIRSOut.writeBuf[18] = _in->readBuf[62]; + HIRSOut.writeBuf[19] = _in->readBuf[63]; + HIRSOut.writeBuf[20] = _in->readBuf[66]; + HIRSOut.writeBuf[21] = _in->readBuf[67]; + HIRSOut.writeBuf[22] = _in->readBuf[70]; + HIRSOut.writeBuf[23] = _in->readBuf[71]; + HIRSOut.writeBuf[24] = _in->readBuf[74]; + HIRSOut.writeBuf[25] = _in->readBuf[75]; + HIRSOut.writeBuf[26] = _in->readBuf[78]; + HIRSOut.writeBuf[27] = _in->readBuf[79]; + HIRSOut.writeBuf[28] = _in->readBuf[82]; + HIRSOut.writeBuf[29] = _in->readBuf[83]; + HIRSOut.writeBuf[30] = _in->readBuf[84]; + HIRSOut.writeBuf[31] = _in->readBuf[85]; + HIRSOut.writeBuf[32] = _in->readBuf[88]; + HIRSOut.writeBuf[33] = _in->readBuf[89]; + HIRSOut.writeBuf[34] = _in->readBuf[92]; + HIRSOut.writeBuf[35] = _in->readBuf[93]; + if (!HIRSOut.swap(36)) { return -1; }; + + // Extract SEM + SEMOut.writeBuf[0] = _in->readBuf[20]; + SEMOut.writeBuf[1] = _in->readBuf[21]; + if (!SEMOut.swap(2)) { return -1; }; + + // Extract DCS + DCSOut.writeBuf[0] = _in->readBuf[18]; + DCSOut.writeBuf[1] = _in->readBuf[19]; + DCSOut.writeBuf[2] = _in->readBuf[24]; + DCSOut.writeBuf[3] = _in->readBuf[25]; + DCSOut.writeBuf[4] = _in->readBuf[28]; + DCSOut.writeBuf[5] = _in->readBuf[29]; + DCSOut.writeBuf[6] = _in->readBuf[32]; + DCSOut.writeBuf[7] = _in->readBuf[33]; + DCSOut.writeBuf[8] = _in->readBuf[40]; + DCSOut.writeBuf[9] = _in->readBuf[41]; + DCSOut.writeBuf[10] = _in->readBuf[44]; + DCSOut.writeBuf[11] = _in->readBuf[45]; + DCSOut.writeBuf[12] = _in->readBuf[52]; + DCSOut.writeBuf[13] = _in->readBuf[53]; + DCSOut.writeBuf[14] = _in->readBuf[56]; + DCSOut.writeBuf[15] = _in->readBuf[57]; + DCSOut.writeBuf[16] = _in->readBuf[60]; + DCSOut.writeBuf[17] = _in->readBuf[61]; + DCSOut.writeBuf[18] = _in->readBuf[64]; + DCSOut.writeBuf[19] = _in->readBuf[65]; + DCSOut.writeBuf[20] = _in->readBuf[68]; + DCSOut.writeBuf[21] = _in->readBuf[69]; + DCSOut.writeBuf[22] = _in->readBuf[72]; + DCSOut.writeBuf[23] = _in->readBuf[73]; + DCSOut.writeBuf[24] = _in->readBuf[76]; + DCSOut.writeBuf[25] = _in->readBuf[77]; + DCSOut.writeBuf[26] = _in->readBuf[86]; + DCSOut.writeBuf[27] = _in->readBuf[87]; + DCSOut.writeBuf[28] = _in->readBuf[90]; + DCSOut.writeBuf[29] = _in->readBuf[91]; + DCSOut.writeBuf[30] = _in->readBuf[94]; + DCSOut.writeBuf[31] = _in->readBuf[95]; + if (!DCSOut.swap(32)) { return -1; }; + + // Extract SBUV + SBUVOut.writeBuf[0] = _in->readBuf[36]; + SBUVOut.writeBuf[1] = _in->readBuf[37]; + SBUVOut.writeBuf[2] = _in->readBuf[80]; + SBUVOut.writeBuf[3] = _in->readBuf[81]; + if (!SBUVOut.swap(4)) { return -1; }; + + + _in->flush(); + return count; + } + + stream HIRSOut; + stream SEMOut; + stream DCSOut; + stream SBUVOut; + + private: + stream* _in; + + }; + + inline uint16_t HIRSSignedToUnsigned(uint16_t n) { + return (n & 0x1000) ? (0x1000 + (n & 0xFFF)) : (0xFFF - (n & 0xFFF)); + } + + class HIRSDemux : public generic_block { + public: + HIRSDemux() {} + + HIRSDemux(stream* in) { init(in); } + + void init(stream* in) { + _in = in; + generic_block::registerInput(_in); + for (int i = 0; i < 20; i++) { + generic_block::registerOutput(&radChannels[i]); + } + + // Clear buffers + for (int i = 0; i < 20; i++) { + for (int j = 0; j < 56; j++) { radChannels[i].writeBuf[j] = 0xFFF; } + } + } + + void setInput(stream* in) { + std::lock_guard lck(generic_block::ctrlMtx); + generic_block::tempStop(); + generic_block::unregisterInput(_in); + _in = in; + generic_block::registerInput(_in); + generic_block::tempStart(); + } + + int run() { + int count = _in->read(); + if (count < 0) { return -1; } + + int element = readBits(19, 6, _in->readBuf); + + // If we've skipped or are on a non image element and there's data avilable, send it + if ((element < lastElement || element > 55) && newImageData) { + newImageData = false; + for (int i = 0; i < 20; i++) { + if (!radChannels[i].swap(56)) { return -1; } + } + + // Clear buffers + for (int i = 0; i < 20; i++) { + for (int j = 0; j < 56; j++) { radChannels[i].writeBuf[j] = 0xFFF; } + } + } + lastElement = element; + + // If data is part of a line, save it + if (element <= 55) { + newImageData = true; + + radChannels[0].writeBuf[element] = HIRSSignedToUnsigned(readBits(26, 13, _in->readBuf)); + radChannels[1].writeBuf[element] = HIRSSignedToUnsigned(readBits(52, 13, _in->readBuf)); + radChannels[2].writeBuf[element] = HIRSSignedToUnsigned(readBits(65, 13, _in->readBuf)); + radChannels[3].writeBuf[element] = HIRSSignedToUnsigned(readBits(91, 13, _in->readBuf)); + radChannels[4].writeBuf[element] = HIRSSignedToUnsigned(readBits(221, 13, _in->readBuf)); + radChannels[5].writeBuf[element] = HIRSSignedToUnsigned(readBits(208, 13, _in->readBuf)); + radChannels[6].writeBuf[element] = HIRSSignedToUnsigned(readBits(143, 13, _in->readBuf)); + radChannels[7].writeBuf[element] = HIRSSignedToUnsigned(readBits(156, 13, _in->readBuf)); + radChannels[8].writeBuf[element] = HIRSSignedToUnsigned(readBits(273, 13, _in->readBuf)); + radChannels[9].writeBuf[element] = HIRSSignedToUnsigned(readBits(182, 13, _in->readBuf)); + radChannels[10].writeBuf[element] = HIRSSignedToUnsigned(readBits(119, 13, _in->readBuf)); + radChannels[11].writeBuf[element] = HIRSSignedToUnsigned(readBits(247, 13, _in->readBuf)); + radChannels[12].writeBuf[element] = HIRSSignedToUnsigned(readBits(78, 13, _in->readBuf)); + radChannels[13].writeBuf[element] = HIRSSignedToUnsigned(readBits(195, 13, _in->readBuf)); + radChannels[14].writeBuf[element] = HIRSSignedToUnsigned(readBits(234, 13, _in->readBuf)); + radChannels[15].writeBuf[element] = HIRSSignedToUnsigned(readBits(260, 13, _in->readBuf)); + radChannels[16].writeBuf[element] = HIRSSignedToUnsigned(readBits(39, 13, _in->readBuf)); + radChannels[17].writeBuf[element] = HIRSSignedToUnsigned(readBits(104, 13, _in->readBuf)); + radChannels[18].writeBuf[element] = HIRSSignedToUnsigned(readBits(130, 13, _in->readBuf)); + radChannels[19].writeBuf[element] = HIRSSignedToUnsigned(readBits(169, 13, _in->readBuf)); + } + + // If we are writing the last pixel of a line, send it already + if (element == 55) { + newImageData = false; + for (int i = 0; i < 20; i++) { + if (!radChannels[i].swap(56)) { return -1; } + } + + // Clear buffers + for (int i = 0; i < 20; i++) { + for (int j = 0; j < 56; j++) { radChannels[i].writeBuf[j] = 0xFFF; } + } + } + + _in->flush(); + return count; + } + + stream radChannels[20]; + + private: + stream* _in; + int lastElement = 0; + bool newImageData = false; + + }; + } +} diff --git a/core/src/dsp/utils/bitstream.h b/core/src/dsp/utils/bitstream.h new file mode 100644 index 0000000..8d3deb4 --- /dev/null +++ b/core/src/dsp/utils/bitstream.h @@ -0,0 +1,43 @@ +#pragma once + +namespace dsp { + inline uint64_t readBits(int offset, int length, uint8_t* buffer) { + uint64_t outputValue = 0; + + int lastBit = offset + (length - 1); + + int firstWord = offset / 8; + int lastWord = lastBit / 8; + int firstOffset = offset - (firstWord * 8); + int lastOffset = lastBit - (lastWord * 8); + + int wordCount = (lastWord - firstWord) + 1; + + // If the data fits in a single byte, just get it + if (wordCount == 1) { + return (buffer[firstWord] & (0xFF >> firstOffset)) >> (7 - lastOffset); + } + + int bitsRead = length; + for (int i = 0; i < wordCount; i++) { + // First word + if (i == 0) { + bitsRead -= 8 - firstOffset; + outputValue |= (uint64_t)(buffer[firstWord] & (0xFF >> firstOffset)) << bitsRead; + continue; + } + + // Last word + if (i == (wordCount - 1)) { + outputValue |= (uint64_t)buffer[lastWord] >> (7 - lastOffset); + break; + } + + // Just a normal byte + bitsRead -= 8; + outputValue |= (uint64_t)buffer[firstWord + i] << bitsRead; + } + + return outputValue; + } +} diff --git a/core/src/gui/widgets/line_push_image.cpp b/core/src/gui/widgets/line_push_image.cpp new file mode 100644 index 0000000..ac98778 --- /dev/null +++ b/core/src/gui/widgets/line_push_image.cpp @@ -0,0 +1,91 @@ +#include + +namespace ImGui { + LinePushImage::LinePushImage(int frameWidth, int reservedIncrement) { + _frameWidth = frameWidth; + _reservedIncrement = reservedIncrement; + frameBuffer = (uint8_t*)malloc(_frameWidth * _reservedIncrement * 4); + reservedCount = reservedIncrement; + + glGenTextures(1, &textureId); + } + + void LinePushImage::draw(const ImVec2& size_arg) { + std::lock_guard lck(bufferMtx); + + ImGuiWindow* window = GetCurrentWindow(); + ImGuiStyle& style = GetStyle(); + float pad = style.FramePadding.y; + ImVec2 min = window->DC.CursorPos; + + // Calculate scale + float width = CalcItemWidth(); + float height = roundf((width / (float)_frameWidth) * (float)_lineCount); + + ImVec2 size = CalcItemSize(size_arg, CalcItemWidth(), height); + ImRect bb(min, ImVec2(min.x+size.x, min.y+size.y)); + float lineHeight = size.y; + + // If there are no lines, there is no point in drawing anything + if (_lineCount == 0) { return; } + + ItemSize(size, style.FramePadding.y); + if (!ItemAdd(bb, 0)) { + return; + } + + if (newData) { + newData = false; + updateTexture(); + } + + window->DrawList->AddImage((void*)(intptr_t)textureId, min, ImVec2(min.x + width, min.y + height)); + } + + uint8_t* LinePushImage::aquireNextLine(int count) { + bufferMtx.lock(); + + int oldLineCount = _lineCount; + _lineCount += count; + + // If new data either fills up or excedes the limit, reallocate + // TODO: Change it to avoid bug if count >= reservedIncrement + if (_lineCount > reservedCount) { + printf("Reallocating\n"); + reservedCount += _reservedIncrement; + frameBuffer = (uint8_t*)realloc(frameBuffer, _frameWidth * reservedCount * 4); + } + + return &frameBuffer[_frameWidth * oldLineCount * 4]; + } + + void LinePushImage::releaseNextLine() { + newData = true; + bufferMtx.unlock(); + } + + void LinePushImage::clear() { + std::lock_guard lck(bufferMtx); + _lineCount = 0; + frameBuffer = (uint8_t*)realloc(frameBuffer, _frameWidth * _reservedIncrement * 4); + reservedCount = _reservedIncrement; + newData = true; + } + + void LinePushImage::save(std::string path) { + // TODO: Implement + } + + int LinePushImage::getLineCount() { + return _lineCount; + } + + void LinePushImage::updateTexture() { + glBindTexture(GL_TEXTURE_2D, textureId); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, _frameWidth, _lineCount, 0, GL_RGBA, GL_UNSIGNED_BYTE, frameBuffer); + } + +} \ No newline at end of file diff --git a/core/src/gui/widgets/line_push_image.h b/core/src/gui/widgets/line_push_image.h new file mode 100644 index 0000000..58c0b56 --- /dev/null +++ b/core/src/gui/widgets/line_push_image.h @@ -0,0 +1,43 @@ +#pragma once + +#include +#include +#include +#include +#include + +namespace ImGui { + class LinePushImage { + public: + LinePushImage(int frameWidth, int reservedIncrement); + + void draw(const ImVec2& size_arg = ImVec2(0, 0)); + + uint8_t* aquireNextLine(int count = 1); + + void releaseNextLine(); + + void clear(); + + void save(std::string path); + + int getLineCount(); + + private: + void updateTexture(); + + std::mutex bufferMtx; + uint8_t* frameBuffer; + + int _frameWidth; + int _reservedIncrement; + int _lineCount = 0; + int reservedCount = 0; + + GLuint textureId; + + bool newData = false; + + + }; +} \ No newline at end of file diff --git a/weather_sat_decoder/CMakeLists.txt b/weather_sat_decoder/CMakeLists.txt new file mode 100644 index 0000000..1bc0a9b --- /dev/null +++ b/weather_sat_decoder/CMakeLists.txt @@ -0,0 +1,22 @@ +cmake_minimum_required(VERSION 3.13) +project(weather_sat_decoder) + +if (MSVC) + set(CMAKE_CXX_FLAGS "-O2 /std:c++17 /EHsc") +else() + set(CMAKE_CXX_FLAGS "-O3 -std=c++17 -fpermissive") +endif (MSVC) + +file(GLOB_RECURSE SRC "src/*.cpp" "src/*.c") + +include_directories("src/") +include_directories("src/libcorrect/") + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=native") + +add_library(weather_sat_decoder SHARED ${SRC}) +target_link_libraries(weather_sat_decoder PRIVATE sdrpp_core) +set_target_properties(weather_sat_decoder PROPERTIES PREFIX "") + +# Install directives +install(TARGETS weather_sat_decoder DESTINATION lib/sdrpp/plugins) \ No newline at end of file diff --git a/weather_sat_decoder/src/main.cpp b/weather_sat_decoder/src/main.cpp new file mode 100644 index 0000000..b7a81c9 --- /dev/null +++ b/weather_sat_decoder/src/main.cpp @@ -0,0 +1,147 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#define CONCAT(a, b) ((std::string(a) + b).c_str()) + +SDRPP_MOD_INFO { + /* Name: */ "weather_sat_decoder", + /* Description: */ "Weather Satellite Decoder for SDR++", + /* Author: */ "Ryzerth", + /* Version: */ 0, 1, 0, + /* Max instances */ -1 +}; + +std::string genFileName(std::string prefix, std::string suffix) { + time_t now = time(0); + tm *ltm = localtime(&now); + char buf[1024]; + sprintf(buf, "%s_%02d-%02d-%02d_%02d-%02d-%02d%s", prefix.c_str(), ltm->tm_hour, ltm->tm_min, ltm->tm_sec, ltm->tm_mday, ltm->tm_mon + 1, ltm->tm_year + 1900, suffix.c_str()); + return buf; +} + +class WeatherSatDecoderModule : public ModuleManager::Instance { +public: + WeatherSatDecoderModule(std::string name) { + this->name = name; + + vfo = sigpath::vfoManager.createVFO(name, ImGui::WaterfallVFO::REF_CENTER, 0, 1000000, 1000000, 1); + + decoders["NOAA HRPT"] = new NOAAHRPTDecoder(vfo, name); + + // Generate the list + decoderNames.clear(); + decoderNamesStr = ""; + for (auto const& [name, dec] : decoders) { + decoderNames.push_back(name); + decoderNamesStr += name; + decoderNamesStr += '\0'; + } + + selectDecoder(decoderNames[0], false); + + gui::menu.registerEntry(name, menuHandler, this, this); + } + + ~WeatherSatDecoderModule() { + decoder->stop(); + } + + void enable() { + vfo = sigpath::vfoManager.createVFO(name, ImGui::WaterfallVFO::REF_CENTER, 0, 1000000, 1000000, 1); + for (auto const& [name, dec] : decoders) { dec->setVFO(vfo); } + decoder->select(); + decoder->start(); + enabled = true; + } + + void disable() { + // Stop decoder + decoder->stop(); + + sigpath::vfoManager.deleteVFO(vfo); + enabled = false; + } + + bool isEnabled() { + return enabled; + } + +private: + void selectDecoder(std::string name, bool deselectLast = true) { + if (deselectLast) { + decoder->stop(); + } + decoder = decoders[name]; + decoder->select(); + decoder->start(); + } + + static void menuHandler(void* ctx) { + WeatherSatDecoderModule* _this = (WeatherSatDecoderModule*)ctx; + + float menuWidth = ImGui::GetContentRegionAvailWidth(); + + if (!_this->enabled) { style::beginDisabled(); } + + ImGui::SetNextItemWidth(menuWidth); + if (ImGui::Combo("##todo", &_this->decoderId, _this->decoderNamesStr.c_str())) { + _this->selectDecoder(_this->decoderNames[_this->decoderId]); + } + + _this->decoder->drawMenu(menuWidth); + + ImGui::Button("Record##testdsdfsds", ImVec2(menuWidth, 0)); + + if (!_this->enabled) { style::endDisabled(); } + } + + std::string name; + bool enabled = true; + + VFOManager::VFO* vfo; + + std::map decoders; + std::vector decoderNames; + std::string decoderNamesStr = ""; + int decoderId = 0; + + SatDecoder* decoder; + +}; + +MOD_EXPORT void _INIT_() { + // Nothing +} + +MOD_EXPORT ModuleManager::Instance* _CREATE_INSTANCE_(std::string name) { + return new WeatherSatDecoderModule(name); +} + +MOD_EXPORT void _DELETE_INSTANCE_(void* instance) { + delete (WeatherSatDecoderModule*)instance; +} + +MOD_EXPORT void _END_() { + // Nothing either +} \ No newline at end of file diff --git a/weather_sat_decoder/src/noaa_hrpt_decoder.h b/weather_sat_decoder/src/noaa_hrpt_decoder.h new file mode 100644 index 0000000..b042861 --- /dev/null +++ b/weather_sat_decoder/src/noaa_hrpt_decoder.h @@ -0,0 +1,563 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include + +#define NOAA_HRPT_VFO_SR 3000000.0f +#define NOAA_HRPT_VFO_BW 2000000.0f + +class NOAAHRPTDecoder : public SatDecoder { +public: + NOAAHRPTDecoder(VFOManager::VFO* vfo, std::string name) : avhrrRGBImage(2048, 256), avhrr1Image(2048, 256), avhrr2Image(2048, 256), avhrr3Image(2048, 256), avhrr4Image(2048, 256), avhrr5Image(2048, 256), symDiag(0.5f) { + _vfo = vfo; + _name = name; + + // Core DSP + demod.init(vfo->output, NOAA_HRPT_VFO_SR, 665400.0f * 2.0f, 0.02e-3, (0.06f*0.06f) / 2.0f, 32, 0.6f, (0.01f*0.01f) / 4.0f, 0.01f, 0.005); + + split.init(demod.out); + split.bindStream(&dataStream); + split.bindStream(&visStream); + + reshape.init(&visStream, 1024, (NOAA_HRPT_VFO_SR/30) - 1024); + visSink.init(&reshape.out, visHandler, this); + + deframe.init(&dataStream, 11090 * 10 * 2, (uint8_t*)dsp::noaa::HRPTSyncWord, 60); + manDec.init(&deframe.out, false); + packer.init(&manDec.out); + demux.init(&packer.out); + tipDemux.init(&demux.TIPOut); + hirsDemux.init(&tipDemux.HIRSOut); + + // All Sinks + avhrr1Sink.init(&demux.AVHRRChan1Out, avhrr1Handler, this); + avhrr2Sink.init(&demux.AVHRRChan2Out, avhrr2Handler, this); + avhrr3Sink.init(&demux.AVHRRChan3Out, avhrr3Handler, this); + avhrr4Sink.init(&demux.AVHRRChan4Out, avhrr4Handler, this); + avhrr5Sink.init(&demux.AVHRRChan5Out, avhrr5Handler, this); + + sbuvSink.init(&tipDemux.SBUVOut); + dcsSink.init(&tipDemux.DCSOut); + semSink.init(&tipDemux.SEMOut); + + aipSink.init(&demux.AIPOut); + + hirs1Sink.init(&hirsDemux.radChannels[0], hirs1Handler, this); + hirs2Sink.init(&hirsDemux.radChannels[1], hirs2Handler, this); + hirs3Sink.init(&hirsDemux.radChannels[2], hirs3Handler, this); + hirs4Sink.init(&hirsDemux.radChannels[3], hirs4Handler, this); + hirs5Sink.init(&hirsDemux.radChannels[4], hirs5Handler, this); + hirs6Sink.init(&hirsDemux.radChannels[5], hirs6Handler, this); + hirs7Sink.init(&hirsDemux.radChannels[6], hirs7Handler, this); + hirs8Sink.init(&hirsDemux.radChannels[7], hirs8Handler, this); + hirs9Sink.init(&hirsDemux.radChannels[8], hirs9Handler, this); + hirs10Sink.init(&hirsDemux.radChannels[9], hirs10Handler, this); + hirs11Sink.init(&hirsDemux.radChannels[10], hirs11Handler, this); + hirs12Sink.init(&hirsDemux.radChannels[11], hirs12Handler, this); + hirs13Sink.init(&hirsDemux.radChannels[12], hirs13Handler, this); + hirs14Sink.init(&hirsDemux.radChannels[13], hirs14Handler, this); + hirs15Sink.init(&hirsDemux.radChannels[14], hirs15Handler, this); + hirs16Sink.init(&hirsDemux.radChannels[15], hirs16Handler, this); + hirs17Sink.init(&hirsDemux.radChannels[16], hirs17Handler, this); + hirs18Sink.init(&hirsDemux.radChannels[17], hirs18Handler, this); + hirs19Sink.init(&hirsDemux.radChannels[18], hirs19Handler, this); + hirs20Sink.init(&hirsDemux.radChannels[19], hirs20Handler, this); + } + + void select() { + _vfo->setSampleRate(NOAA_HRPT_VFO_SR, NOAA_HRPT_VFO_BW); + _vfo->setReference(ImGui::WaterfallVFO::REF_CENTER); + }; + + void start() { + demod.start(); + + split.start(); + reshape.start(); + visSink.start(); + + deframe.start(); + manDec.start(); + packer.start(); + demux.start(); + tipDemux.start(); + hirsDemux.start(); + + avhrr1Sink.start(); + avhrr2Sink.start(); + avhrr3Sink.start(); + avhrr4Sink.start(); + avhrr5Sink.start(); + + sbuvSink.start(); + dcsSink.start(); + semSink.start(); + + aipSink.start(); + + hirs1Sink.start(); + hirs2Sink.start(); + hirs3Sink.start(); + hirs4Sink.start(); + hirs5Sink.start(); + hirs6Sink.start(); + hirs7Sink.start(); + hirs8Sink.start(); + hirs9Sink.start(); + hirs10Sink.start(); + hirs11Sink.start(); + hirs12Sink.start(); + hirs13Sink.start(); + hirs14Sink.start(); + hirs15Sink.start(); + hirs16Sink.start(); + hirs17Sink.start(); + hirs18Sink.start(); + hirs19Sink.start(); + hirs20Sink.start(); + + compositeThread = std::thread(&NOAAHRPTDecoder::avhrrCompositeWorker, this); + }; + + void stop() { + compositeIn1.stopReader(); + compositeIn1.stopWriter(); + compositeIn2.stopReader(); + compositeIn2.stopWriter(); + + demod.stop(); + + split.stop(); + reshape.stop(); + visSink.stop(); + + deframe.stop(); + manDec.stop(); + packer.stop(); + demux.stop(); + tipDemux.stop(); + hirsDemux.stop(); + + avhrr1Sink.stop(); + avhrr2Sink.stop(); + avhrr3Sink.stop(); + avhrr4Sink.stop(); + avhrr5Sink.stop(); + + sbuvSink.stop(); + dcsSink.stop(); + semSink.stop(); + + aipSink.stop(); + + hirs1Sink.stop(); + hirs2Sink.stop(); + hirs3Sink.stop(); + hirs4Sink.stop(); + hirs5Sink.stop(); + hirs6Sink.stop(); + hirs7Sink.stop(); + hirs8Sink.stop(); + hirs9Sink.stop(); + hirs10Sink.stop(); + hirs11Sink.stop(); + hirs12Sink.stop(); + hirs13Sink.stop(); + hirs14Sink.stop(); + hirs15Sink.stop(); + hirs16Sink.stop(); + hirs17Sink.stop(); + hirs18Sink.stop(); + hirs19Sink.stop(); + hirs20Sink.stop(); + + if (compositeThread.joinable()) { + compositeThread.join(); + } + + compositeIn1.clearReadStop(); + compositeIn1.clearWriteStop(); + compositeIn2.clearReadStop(); + compositeIn2.clearWriteStop(); + }; + + void setVFO(VFOManager::VFO* vfo) { + _vfo = vfo; + demod.setInput(_vfo->output); + }; + + virtual bool canRecord() { + return false; + } + + // bool startRecording(std::string recPath) { + + // }; + + // void stopRecording() { + + // }; + + // bool isRecording() { + + // }; + + void drawMenu(float menuWidth) { + ImGui::SetNextItemWidth(menuWidth); + symDiag.draw(); + + ImGui::Begin("NOAA HRPT Decoder"); + ImGui::BeginTabBar("NOAAHRPTTabs"); + + if (ImGui::BeginTabItem("AVHRR RGB(221)")) { + ImGui::BeginChild(ImGuiID("AVHRRRGBChild")); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvailWidth()); + avhrrRGBImage.draw(); + ImGui::SetScrollHere(1.0f); + ImGui::EndChild(); + ImGui::EndTabItem(); + } + + if (ImGui::BeginTabItem("AVHRR 1")) { + ImGui::BeginChild(ImGuiID("AVHRR1Child")); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvailWidth()); + avhrr1Image.draw(); + ImGui::SetScrollHere(1.0f); + ImGui::EndChild(); + ImGui::EndTabItem(); + } + + if (ImGui::BeginTabItem("AVHRR 2")) { + ImGui::BeginChild(ImGuiID("AVHRR2Child")); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvailWidth()); + avhrr2Image.draw(); + ImGui::SetScrollHere(1.0f); + ImGui::EndChild(); + ImGui::EndTabItem(); + } + + if (ImGui::BeginTabItem("AVHRR 3")) { + ImGui::BeginChild(ImGuiID("AVHRR3Child")); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvailWidth()); + avhrr3Image.draw(); + ImGui::SetScrollHere(1.0f); + ImGui::EndChild(); + ImGui::EndTabItem(); + } + + if (ImGui::BeginTabItem("AVHRR 4")) { + ImGui::BeginChild(ImGuiID("AVHRR4Child")); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvailWidth()); + avhrr4Image.draw(); + ImGui::SetScrollHere(1.0f); + ImGui::EndChild(); + ImGui::EndTabItem(); + } + + if (ImGui::BeginTabItem("AVHRR 5")) { + ImGui::BeginChild(ImGuiID("AVHRR5Child")); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvailWidth()); + avhrr5Image.draw(); + ImGui::SetScrollHere(1.0f); + ImGui::EndChild(); + ImGui::EndTabItem(); + } + + if (ImGui::BeginTabItem("HIRS")) { + ImGui::BeginChild(ImGuiID("HIRSChild")); + + ImGui::EndChild(); + ImGui::EndTabItem(); + } + + ImGui::EndTabBar(); + ImGui::End(); + }; + +private: + // AVHRR Data Handlers + void avhrrCompositeWorker() { + compositeIn1.flush(); + compositeIn2.flush(); + while (true) { + if (compositeIn1.read() < 0) { return; } + if (compositeIn2.read() < 0) { return; } + + uint8_t* buf = avhrrRGBImage.aquireNextLine(); + float rg, b; + for (int i = 0; i < 2048; i++) { + b = ((float)compositeIn1.readBuf[i] * 255.0f) / 1024.0f; + rg = ((float)compositeIn2.readBuf[i] * 255.0f) / 1024.0f; + buf[(i*4)] = rg; + buf[(i*4) + 1] = rg; + buf[(i*4) + 2] = b; + buf[(i*4) + 3] = 255; + } + avhrrRGBImage.releaseNextLine(); + + compositeIn1.flush(); + compositeIn2.flush(); + } + } + + static void avhrr1Handler(uint16_t* data, int count, void* ctx) { + NOAAHRPTDecoder* _this = (NOAAHRPTDecoder*)ctx; + uint8_t* buf = _this->avhrr1Image.aquireNextLine(); + float val; + for (int i = 0; i < 2048; i++) { + val = ((float)data[i] * 255.0f) / 1024.0f; + buf[(i*4)] = val; + buf[(i*4) + 1] = val; + buf[(i*4) + 2] = val; + buf[(i*4) + 3] = 255; + } + _this->avhrr1Image.releaseNextLine(); + + memcpy(_this->compositeIn1.writeBuf, data, count * sizeof(uint16_t)); + _this->compositeIn1.swap(count); + } + + static void avhrr2Handler(uint16_t* data, int count, void* ctx) { + NOAAHRPTDecoder* _this = (NOAAHRPTDecoder*)ctx; + uint8_t* buf = _this->avhrr2Image.aquireNextLine(); + float val; + for (int i = 0; i < 2048; i++) { + val = ((float)data[i] * 255.0f) / 1024.0f; + buf[(i*4)] = val; + buf[(i*4) + 1] = val; + buf[(i*4) + 2] = val; + buf[(i*4) + 3] = 255; + } + _this->avhrr2Image.releaseNextLine(); + + memcpy(_this->compositeIn2.writeBuf, data, count * sizeof(uint16_t)); + _this->compositeIn2.swap(count); + } + + static void avhrr3Handler(uint16_t* data, int count, void* ctx) { + NOAAHRPTDecoder* _this = (NOAAHRPTDecoder*)ctx; + uint8_t* buf = _this->avhrr3Image.aquireNextLine(); + float val; + for (int i = 0; i < 2048; i++) { + val = ((float)data[i] * 255.0f) / 1024.0f; + buf[(i*4)] = val; + buf[(i*4) + 1] = val; + buf[(i*4) + 2] = val; + buf[(i*4) + 3] = 255; + } + _this->avhrr3Image.releaseNextLine(); + } + + static void avhrr4Handler(uint16_t* data, int count, void* ctx) { + NOAAHRPTDecoder* _this = (NOAAHRPTDecoder*)ctx; + uint8_t* buf = _this->avhrr4Image.aquireNextLine(); + float val; + for (int i = 0; i < 2048; i++) { + val = ((float)data[i] * 255.0f) / 1024.0f; + buf[(i*4)] = val; + buf[(i*4) + 1] = val; + buf[(i*4) + 2] = val; + buf[(i*4) + 3] = 255; + } + _this->avhrr4Image.releaseNextLine(); + } + + static void avhrr5Handler(uint16_t* data, int count, void* ctx) { + NOAAHRPTDecoder* _this = (NOAAHRPTDecoder*)ctx; + uint8_t* buf = _this->avhrr5Image.aquireNextLine(); + float val; + for (int i = 0; i < 2048; i++) { + val = ((float)data[i] * 255.0f) / 1024.0f; + buf[(i*4)] = val; + buf[(i*4) + 1] = val; + buf[(i*4) + 2] = val; + buf[(i*4) + 3] = 255; + } + _this->avhrr5Image.releaseNextLine(); + } + + // HIRS Data Handlers + static void hirs1Handler(uint16_t* data, int count, void* ctx) { + NOAAHRPTDecoder* _this = (NOAAHRPTDecoder*)ctx; + + } + + static void hirs2Handler(uint16_t* data, int count, void* ctx) { + NOAAHRPTDecoder* _this = (NOAAHRPTDecoder*)ctx; + + } + + static void hirs3Handler(uint16_t* data, int count, void* ctx) { + NOAAHRPTDecoder* _this = (NOAAHRPTDecoder*)ctx; + + } + + static void hirs4Handler(uint16_t* data, int count, void* ctx) { + NOAAHRPTDecoder* _this = (NOAAHRPTDecoder*)ctx; + + } + + static void hirs5Handler(uint16_t* data, int count, void* ctx) { + NOAAHRPTDecoder* _this = (NOAAHRPTDecoder*)ctx; + + } + + static void hirs6Handler(uint16_t* data, int count, void* ctx) { + NOAAHRPTDecoder* _this = (NOAAHRPTDecoder*)ctx; + + } + + static void hirs7Handler(uint16_t* data, int count, void* ctx) { + NOAAHRPTDecoder* _this = (NOAAHRPTDecoder*)ctx; + + } + + static void hirs8Handler(uint16_t* data, int count, void* ctx) { + NOAAHRPTDecoder* _this = (NOAAHRPTDecoder*)ctx; + + } + + static void hirs9Handler(uint16_t* data, int count, void* ctx) { + NOAAHRPTDecoder* _this = (NOAAHRPTDecoder*)ctx; + + } + + static void hirs10Handler(uint16_t* data, int count, void* ctx) { + NOAAHRPTDecoder* _this = (NOAAHRPTDecoder*)ctx; + + } + + static void hirs11Handler(uint16_t* data, int count, void* ctx) { + NOAAHRPTDecoder* _this = (NOAAHRPTDecoder*)ctx; + + } + + static void hirs12Handler(uint16_t* data, int count, void* ctx) { + NOAAHRPTDecoder* _this = (NOAAHRPTDecoder*)ctx; + + } + + static void hirs13Handler(uint16_t* data, int count, void* ctx) { + NOAAHRPTDecoder* _this = (NOAAHRPTDecoder*)ctx; + + } + + static void hirs14Handler(uint16_t* data, int count, void* ctx) { + NOAAHRPTDecoder* _this = (NOAAHRPTDecoder*)ctx; + + } + + static void hirs15Handler(uint16_t* data, int count, void* ctx) { + NOAAHRPTDecoder* _this = (NOAAHRPTDecoder*)ctx; + + } + + static void hirs16Handler(uint16_t* data, int count, void* ctx) { + NOAAHRPTDecoder* _this = (NOAAHRPTDecoder*)ctx; + + } + + static void hirs17Handler(uint16_t* data, int count, void* ctx) { + NOAAHRPTDecoder* _this = (NOAAHRPTDecoder*)ctx; + + } + + static void hirs18Handler(uint16_t* data, int count, void* ctx) { + NOAAHRPTDecoder* _this = (NOAAHRPTDecoder*)ctx; + + } + + static void hirs19Handler(uint16_t* data, int count, void* ctx) { + NOAAHRPTDecoder* _this = (NOAAHRPTDecoder*)ctx; + + } + + static void hirs20Handler(uint16_t* data, int count, void* ctx) { + NOAAHRPTDecoder* _this = (NOAAHRPTDecoder*)ctx; + + } + + static void visHandler(float* data, int count, void* ctx) { + NOAAHRPTDecoder* _this = (NOAAHRPTDecoder*)ctx; + memcpy(_this->symDiag.aquireBuffer(), data, 1024 * sizeof(float)); + _this->symDiag.releaseBuffer(); + } + + std::string _name; + std::string _recPath; + VFOManager::VFO* _vfo; + + // DSP + dsp::PMDemod demod; + + dsp::stream visStream; + dsp::stream dataStream; + dsp::Splitter split; + + dsp::Reshaper reshape; + + dsp::ManchesterDeframer deframe; + dsp::ManchesterDecoder manDec; + dsp::BitPacker packer; + dsp::noaa::HRPTDemux demux; + dsp::noaa::TIPDemux tipDemux; + dsp::noaa::HIRSDemux hirsDemux; + + // AHVRR Handlers + dsp::HandlerSink avhrr1Sink; + dsp::HandlerSink avhrr2Sink; + dsp::HandlerSink avhrr3Sink; + dsp::HandlerSink avhrr4Sink; + dsp::HandlerSink avhrr5Sink; + + // (at the moment) Unused TIP handlers + dsp::NullSink sbuvSink; + dsp::NullSink dcsSink; + dsp::NullSink semSink; + + // (at the moment) Unused AIP handlers + dsp::NullSink aipSink; + + // HIRS Handlers + dsp::HandlerSink hirs1Sink; + dsp::HandlerSink hirs2Sink; + dsp::HandlerSink hirs3Sink; + dsp::HandlerSink hirs4Sink; + dsp::HandlerSink hirs5Sink; + dsp::HandlerSink hirs6Sink; + dsp::HandlerSink hirs7Sink; + dsp::HandlerSink hirs8Sink; + dsp::HandlerSink hirs9Sink; + dsp::HandlerSink hirs10Sink; + dsp::HandlerSink hirs11Sink; + dsp::HandlerSink hirs12Sink; + dsp::HandlerSink hirs13Sink; + dsp::HandlerSink hirs14Sink; + dsp::HandlerSink hirs15Sink; + dsp::HandlerSink hirs16Sink; + dsp::HandlerSink hirs17Sink; + dsp::HandlerSink hirs18Sink; + dsp::HandlerSink hirs19Sink; + dsp::HandlerSink hirs20Sink; + + dsp::HandlerSink visSink; + + ImGui::LinePushImage avhrrRGBImage; + ImGui::LinePushImage avhrr1Image; + ImGui::LinePushImage avhrr2Image; + ImGui::LinePushImage avhrr3Image; + ImGui::LinePushImage avhrr4Image; + ImGui::LinePushImage avhrr5Image; + + ImGui::SymbolDiagram symDiag; + + dsp::stream compositeIn1; + dsp::stream compositeIn2; + std::thread compositeThread; + +}; \ No newline at end of file diff --git a/weather_sat_decoder/src/sat_decoder.h b/weather_sat_decoder/src/sat_decoder.h new file mode 100644 index 0000000..ad90469 --- /dev/null +++ b/weather_sat_decoder/src/sat_decoder.h @@ -0,0 +1,16 @@ +#pragma once +#include +#include + +class SatDecoder { +public: + virtual void select() = 0; + virtual void start() = 0; + virtual void stop() = 0; + virtual void setVFO(VFOManager::VFO* vfo) = 0; + virtual bool canRecord() = 0; + virtual bool startRecording(std::string recPath) { return false; }; + virtual void stopRecording() { }; + virtual bool isRecording() { return false; }; + virtual void drawMenu(float menuWidth) = 0; +}; \ No newline at end of file