mirror of
https://github.com/AlexandreRouma/SDRPlusPlus.git
synced 2025-01-11 10:47:11 +01:00
Beginning of code for the RSPduo + bugfix for the hackrf
This commit is contained in:
parent
26e623bec4
commit
d41ae73e0d
65
core/src/dsp/meteor/hrpt.h
Normal file
65
core/src/dsp/meteor/hrpt.h
Normal file
@ -0,0 +1,65 @@
|
||||
#pragma once
|
||||
#include <dsp/block.h>
|
||||
#include <dsp/utils/bitstream.h>
|
||||
|
||||
namespace dsp {
|
||||
namespace meteor {
|
||||
class HRPTDemux : public generic_block<HRPTDemux> {
|
||||
public:
|
||||
HRPTDemux() {}
|
||||
|
||||
HRPTDemux(stream<uint8_t>* in) { init(in); }
|
||||
|
||||
void init(stream<uint8_t>* in) {
|
||||
_in = in;
|
||||
generic_block<HRPTDemux>::registerInput(_in);
|
||||
generic_block<HRPTDemux>::registerOutput(&telemOut);
|
||||
generic_block<HRPTDemux>::registerOutput(&BISMout);
|
||||
generic_block<HRPTDemux>::registerOutput(&SSPDOut);
|
||||
generic_block<HRPTDemux>::registerOutput(&MTVZAOut);
|
||||
generic_block<HRPTDemux>::registerOutput(&MSUMROut);
|
||||
}
|
||||
|
||||
void setInput(stream<uint8_t>* in) {
|
||||
std::lock_guard<std::mutex> lck(generic_block<HRPTDemux>::ctrlMtx);
|
||||
generic_block<HRPTDemux>::tempStop();
|
||||
generic_block<HRPTDemux>::unregisterInput(_in);
|
||||
_in = in;
|
||||
generic_block<HRPTDemux>::registerInput(_in);
|
||||
generic_block<HRPTDemux>::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<uint8_t> telemOut;
|
||||
stream<uint8_t> BISMout;
|
||||
stream<uint8_t> SSPDOut;
|
||||
stream<uint8_t> MTVZAOut;
|
||||
stream<uint8_t> MSUMROut;
|
||||
|
||||
private:
|
||||
stream<uint8_t>* _in;
|
||||
|
||||
};
|
||||
}
|
||||
}
|
76
core/src/dsp/meteor/msumr.h
Normal file
76
core/src/dsp/meteor/msumr.h
Normal file
@ -0,0 +1,76 @@
|
||||
#pragma once
|
||||
#include <dsp/block.h>
|
||||
#include <dsp/utils/bitstream.h>
|
||||
|
||||
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<MSUMRDemux> {
|
||||
public:
|
||||
MSUMRDemux() {}
|
||||
|
||||
MSUMRDemux(stream<uint8_t>* in) { init(in); }
|
||||
|
||||
void init(stream<uint8_t>* in) {
|
||||
_in = in;
|
||||
generic_block<MSUMRDemux>::registerInput(_in);
|
||||
generic_block<MSUMRDemux>::registerOutput(&msumr1Out);
|
||||
generic_block<MSUMRDemux>::registerOutput(&msumr2Out);
|
||||
generic_block<MSUMRDemux>::registerOutput(&msumr3Out);
|
||||
generic_block<MSUMRDemux>::registerOutput(&msumr4Out);
|
||||
generic_block<MSUMRDemux>::registerOutput(&msumr5Out);
|
||||
generic_block<MSUMRDemux>::registerOutput(&msumr6Out);
|
||||
}
|
||||
|
||||
void setInput(stream<uint8_t>* in) {
|
||||
std::lock_guard<std::mutex> lck(generic_block<MSUMRDemux>::ctrlMtx);
|
||||
generic_block<MSUMRDemux>::tempStop();
|
||||
generic_block<MSUMRDemux>::unregisterInput(_in);
|
||||
_in = in;
|
||||
generic_block<MSUMRDemux>::registerInput(_in);
|
||||
generic_block<MSUMRDemux>::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<uint16_t> msumr1Out;
|
||||
stream<uint16_t> msumr2Out;
|
||||
stream<uint16_t> msumr3Out;
|
||||
stream<uint16_t> msumr4Out;
|
||||
stream<uint16_t> msumr5Out;
|
||||
stream<uint16_t> msumr6Out;
|
||||
|
||||
private:
|
||||
stream<uint8_t>* _in;
|
||||
|
||||
};
|
||||
}
|
||||
}
|
109
core/src/dsp/noaa/hrpt.h
Normal file
109
core/src/dsp/noaa/hrpt.h
Normal file
@ -0,0 +1,109 @@
|
||||
#pragma once
|
||||
#include <dsp/block.h>
|
||||
#include <dsp/utils/bitstream.h>
|
||||
|
||||
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<HRPTDemux> {
|
||||
public:
|
||||
HRPTDemux() {}
|
||||
|
||||
HRPTDemux(stream<uint8_t>* in) { init(in); }
|
||||
|
||||
void init(stream<uint8_t>* in) {
|
||||
_in = in;
|
||||
generic_block<HRPTDemux>::registerInput(_in);
|
||||
generic_block<HRPTDemux>::registerOutput(&AVHRRChan1Out);
|
||||
generic_block<HRPTDemux>::registerOutput(&AVHRRChan2Out);
|
||||
generic_block<HRPTDemux>::registerOutput(&AVHRRChan3Out);
|
||||
generic_block<HRPTDemux>::registerOutput(&AVHRRChan4Out);
|
||||
generic_block<HRPTDemux>::registerOutput(&AVHRRChan5Out);
|
||||
}
|
||||
|
||||
void setInput(stream<uint8_t>* in) {
|
||||
std::lock_guard<std::mutex> lck(generic_block<HRPTDemux>::ctrlMtx);
|
||||
generic_block<HRPTDemux>::tempStop();
|
||||
generic_block<HRPTDemux>::unregisterInput(_in);
|
||||
_in = in;
|
||||
generic_block<HRPTDemux>::registerInput(_in);
|
||||
generic_block<HRPTDemux>::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<uint8_t> TIPOut;
|
||||
stream<uint8_t> AIPOut;
|
||||
|
||||
stream<uint16_t> AVHRRChan1Out;
|
||||
stream<uint16_t> AVHRRChan2Out;
|
||||
stream<uint16_t> AVHRRChan3Out;
|
||||
stream<uint16_t> AVHRRChan4Out;
|
||||
stream<uint16_t> AVHRRChan5Out;
|
||||
|
||||
private:
|
||||
stream<uint8_t>* _in;
|
||||
|
||||
};
|
||||
}
|
||||
}
|
240
core/src/dsp/noaa/tip.h
Normal file
240
core/src/dsp/noaa/tip.h
Normal file
@ -0,0 +1,240 @@
|
||||
#pragma once
|
||||
#include <dsp/block.h>
|
||||
#include <dsp/utils/bitstream.h>
|
||||
|
||||
namespace dsp {
|
||||
namespace noaa {
|
||||
class TIPDemux : public generic_block<TIPDemux> {
|
||||
public:
|
||||
TIPDemux() {}
|
||||
|
||||
TIPDemux(stream<uint8_t>* in) { init(in); }
|
||||
|
||||
void init(stream<uint8_t>* in) {
|
||||
_in = in;
|
||||
generic_block<TIPDemux>::registerInput(_in);
|
||||
generic_block<TIPDemux>::registerOutput(&HIRSOut);
|
||||
generic_block<TIPDemux>::registerOutput(&SEMOut);
|
||||
generic_block<TIPDemux>::registerOutput(&DCSOut);
|
||||
generic_block<TIPDemux>::registerOutput(&SBUVOut);
|
||||
}
|
||||
|
||||
void setInput(stream<uint8_t>* in) {
|
||||
std::lock_guard<std::mutex> lck(generic_block<TIPDemux>::ctrlMtx);
|
||||
generic_block<TIPDemux>::tempStop();
|
||||
generic_block<TIPDemux>::unregisterInput(_in);
|
||||
_in = in;
|
||||
generic_block<TIPDemux>::registerInput(_in);
|
||||
generic_block<TIPDemux>::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<uint8_t> HIRSOut;
|
||||
stream<uint8_t> SEMOut;
|
||||
stream<uint8_t> DCSOut;
|
||||
stream<uint8_t> SBUVOut;
|
||||
|
||||
private:
|
||||
stream<uint8_t>* _in;
|
||||
|
||||
};
|
||||
|
||||
inline uint16_t HIRSSignedToUnsigned(uint16_t n) {
|
||||
return (n & 0x1000) ? (0x1000 + (n & 0xFFF)) : (0xFFF - (n & 0xFFF));
|
||||
}
|
||||
|
||||
class HIRSDemux : public generic_block<HIRSDemux> {
|
||||
public:
|
||||
HIRSDemux() {}
|
||||
|
||||
HIRSDemux(stream<uint8_t>* in) { init(in); }
|
||||
|
||||
void init(stream<uint8_t>* in) {
|
||||
_in = in;
|
||||
generic_block<HIRSDemux>::registerInput(_in);
|
||||
for (int i = 0; i < 20; i++) {
|
||||
generic_block<HIRSDemux>::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<uint8_t>* in) {
|
||||
std::lock_guard<std::mutex> lck(generic_block<HIRSDemux>::ctrlMtx);
|
||||
generic_block<HIRSDemux>::tempStop();
|
||||
generic_block<HIRSDemux>::unregisterInput(_in);
|
||||
_in = in;
|
||||
generic_block<HIRSDemux>::registerInput(_in);
|
||||
generic_block<HIRSDemux>::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<uint16_t> radChannels[20];
|
||||
|
||||
private:
|
||||
stream<uint8_t>* _in;
|
||||
int lastElement = 0;
|
||||
bool newImageData = false;
|
||||
|
||||
};
|
||||
}
|
||||
}
|
43
core/src/dsp/utils/bitstream.h
Normal file
43
core/src/dsp/utils/bitstream.h
Normal file
@ -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;
|
||||
}
|
||||
}
|
91
core/src/gui/widgets/line_push_image.cpp
Normal file
91
core/src/gui/widgets/line_push_image.cpp
Normal file
@ -0,0 +1,91 @@
|
||||
#include <gui/widgets/line_push_image.h>
|
||||
|
||||
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<std::mutex> 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<std::mutex> 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);
|
||||
}
|
||||
|
||||
}
|
43
core/src/gui/widgets/line_push_image.h
Normal file
43
core/src/gui/widgets/line_push_image.h
Normal file
@ -0,0 +1,43 @@
|
||||
#pragma once
|
||||
|
||||
#include <imgui.h>
|
||||
#include <imgui_internal.h>
|
||||
#include <dsp/stream.h>
|
||||
#include <mutex>
|
||||
#include <GL/glew.h>
|
||||
|
||||
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;
|
||||
|
||||
|
||||
};
|
||||
}
|
22
weather_sat_decoder/CMakeLists.txt
Normal file
22
weather_sat_decoder/CMakeLists.txt
Normal file
@ -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)
|
147
weather_sat_decoder/src/main.cpp
Normal file
147
weather_sat_decoder/src/main.cpp
Normal file
@ -0,0 +1,147 @@
|
||||
#include <imgui.h>
|
||||
#include <watcher.h>
|
||||
#include <config.h>
|
||||
#include <core.h>
|
||||
#include <gui/style.h>
|
||||
#include <signal_path/signal_path.h>
|
||||
#include <module.h>
|
||||
#include <options.h>
|
||||
|
||||
#include <dsp/pll.h>
|
||||
#include <dsp/stream.h>
|
||||
#include <dsp/demodulator.h>
|
||||
#include <dsp/window.h>
|
||||
#include <dsp/resampling.h>
|
||||
#include <dsp/processing.h>
|
||||
#include <dsp/routing.h>
|
||||
#include <dsp/sink.h>
|
||||
|
||||
#include <gui/widgets/folder_select.h>
|
||||
#include <gui/widgets/constellation_diagram.h>
|
||||
|
||||
#include <sat_decoder.h>
|
||||
#include <noaa_hrpt_decoder.h>
|
||||
|
||||
#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<std::string, SatDecoder*> decoders;
|
||||
std::vector<std::string> 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
|
||||
}
|
563
weather_sat_decoder/src/noaa_hrpt_decoder.h
Normal file
563
weather_sat_decoder/src/noaa_hrpt_decoder.h
Normal file
@ -0,0 +1,563 @@
|
||||
#pragma once
|
||||
#include <sat_decoder.h>
|
||||
#include <dsp/demodulator.h>
|
||||
#include <dsp/deframing.h>
|
||||
#include <dsp/noaa/hrpt.h>
|
||||
#include <dsp/noaa/tip.h>
|
||||
#include <dsp/sink.h>
|
||||
#include <gui/widgets/symbol_diagram.h>
|
||||
#include <gui/widgets/line_push_image.h>
|
||||
|
||||
#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<float> visStream;
|
||||
dsp::stream<float> dataStream;
|
||||
dsp::Splitter<float> split;
|
||||
|
||||
dsp::Reshaper<float> 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<uint16_t> avhrr1Sink;
|
||||
dsp::HandlerSink<uint16_t> avhrr2Sink;
|
||||
dsp::HandlerSink<uint16_t> avhrr3Sink;
|
||||
dsp::HandlerSink<uint16_t> avhrr4Sink;
|
||||
dsp::HandlerSink<uint16_t> avhrr5Sink;
|
||||
|
||||
// (at the moment) Unused TIP handlers
|
||||
dsp::NullSink<uint8_t> sbuvSink;
|
||||
dsp::NullSink<uint8_t> dcsSink;
|
||||
dsp::NullSink<uint8_t> semSink;
|
||||
|
||||
// (at the moment) Unused AIP handlers
|
||||
dsp::NullSink<uint8_t> aipSink;
|
||||
|
||||
// HIRS Handlers
|
||||
dsp::HandlerSink<uint16_t> hirs1Sink;
|
||||
dsp::HandlerSink<uint16_t> hirs2Sink;
|
||||
dsp::HandlerSink<uint16_t> hirs3Sink;
|
||||
dsp::HandlerSink<uint16_t> hirs4Sink;
|
||||
dsp::HandlerSink<uint16_t> hirs5Sink;
|
||||
dsp::HandlerSink<uint16_t> hirs6Sink;
|
||||
dsp::HandlerSink<uint16_t> hirs7Sink;
|
||||
dsp::HandlerSink<uint16_t> hirs8Sink;
|
||||
dsp::HandlerSink<uint16_t> hirs9Sink;
|
||||
dsp::HandlerSink<uint16_t> hirs10Sink;
|
||||
dsp::HandlerSink<uint16_t> hirs11Sink;
|
||||
dsp::HandlerSink<uint16_t> hirs12Sink;
|
||||
dsp::HandlerSink<uint16_t> hirs13Sink;
|
||||
dsp::HandlerSink<uint16_t> hirs14Sink;
|
||||
dsp::HandlerSink<uint16_t> hirs15Sink;
|
||||
dsp::HandlerSink<uint16_t> hirs16Sink;
|
||||
dsp::HandlerSink<uint16_t> hirs17Sink;
|
||||
dsp::HandlerSink<uint16_t> hirs18Sink;
|
||||
dsp::HandlerSink<uint16_t> hirs19Sink;
|
||||
dsp::HandlerSink<uint16_t> hirs20Sink;
|
||||
|
||||
dsp::HandlerSink<float> visSink;
|
||||
|
||||
ImGui::LinePushImage avhrrRGBImage;
|
||||
ImGui::LinePushImage avhrr1Image;
|
||||
ImGui::LinePushImage avhrr2Image;
|
||||
ImGui::LinePushImage avhrr3Image;
|
||||
ImGui::LinePushImage avhrr4Image;
|
||||
ImGui::LinePushImage avhrr5Image;
|
||||
|
||||
ImGui::SymbolDiagram symDiag;
|
||||
|
||||
dsp::stream<uint16_t> compositeIn1;
|
||||
dsp::stream<uint16_t> compositeIn2;
|
||||
std::thread compositeThread;
|
||||
|
||||
};
|
16
weather_sat_decoder/src/sat_decoder.h
Normal file
16
weather_sat_decoder/src/sat_decoder.h
Normal file
@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <signal_path/vfo_manager.h>
|
||||
|
||||
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;
|
||||
};
|
Loading…
Reference in New Issue
Block a user