mirror of
https://github.com/AlexandreRouma/SDRPlusPlus.git
synced 2025-06-25 12:07:49 +02:00
Formatted the entire codebase and added a CI check for formatting
This commit is contained in:
@ -3,37 +3,36 @@
|
||||
#include <inttypes.h>
|
||||
|
||||
// WTF???
|
||||
extern "C"
|
||||
{
|
||||
extern "C" {
|
||||
#include <correct.h>
|
||||
}
|
||||
|
||||
const uint8_t toDB[] = {
|
||||
0x00, 0x7b, 0xaf, 0xd4, 0x99, 0xe2, 0x36, 0x4d, 0xfa, 0x81, 0x55, 0x2e, 0x63, 0x18, 0xcc, 0xb7, 0x86, 0xfd, 0x29, 0x52, 0x1f,
|
||||
0x64, 0xb0, 0xcb, 0x7c, 0x07, 0xd3, 0xa8, 0xe5, 0x9e, 0x4a, 0x31, 0xec, 0x97, 0x43, 0x38, 0x75, 0x0e, 0xda, 0xa1, 0x16, 0x6d, 0xb9, 0xc2, 0x8f, 0xf4,
|
||||
0x20, 0x5b, 0x6a, 0x11, 0xc5, 0xbe, 0xf3, 0x88, 0x5c, 0x27, 0x90, 0xeb, 0x3f, 0x44, 0x09, 0x72, 0xa6, 0xdd, 0xef, 0x94, 0x40, 0x3b, 0x76, 0x0d, 0xd9,
|
||||
0xa2, 0x15, 0x6e, 0xba, 0xc1, 0x8c, 0xf7, 0x23, 0x58, 0x69, 0x12, 0xc6, 0xbd, 0xf0, 0x8b, 0x5f, 0x24, 0x93, 0xe8, 0x3c, 0x47, 0x0a, 0x71, 0xa5, 0xde,
|
||||
0x03, 0x78, 0xac, 0xd7, 0x9a, 0xe1, 0x35, 0x4e, 0xf9, 0x82, 0x56, 0x2d, 0x60, 0x1b, 0xcf, 0xb4, 0x85, 0xfe, 0x2a, 0x51, 0x1c, 0x67, 0xb3, 0xc8, 0x7f,
|
||||
0x04, 0xd0, 0xab, 0xe6, 0x9d, 0x49, 0x32, 0x8d, 0xf6, 0x22, 0x59, 0x14, 0x6f, 0xbb, 0xc0, 0x77, 0x0c, 0xd8, 0xa3, 0xee, 0x95, 0x41, 0x3a, 0x0b, 0x70,
|
||||
0xa4, 0xdf, 0x92, 0xe9, 0x3d, 0x46, 0xf1, 0x8a, 0x5e, 0x25, 0x68, 0x13, 0xc7, 0xbc, 0x61, 0x1a, 0xce, 0xb5, 0xf8, 0x83, 0x57, 0x2c, 0x9b, 0xe0, 0x34,
|
||||
0x4f, 0x02, 0x79, 0xad, 0xd6, 0xe7, 0x9c, 0x48, 0x33, 0x7e, 0x05, 0xd1, 0xaa, 0x1d, 0x66, 0xb2, 0xc9, 0x84, 0xff, 0x2b, 0x50, 0x62, 0x19, 0xcd, 0xb6,
|
||||
0xfb, 0x80, 0x54, 0x2f, 0x98, 0xe3, 0x37, 0x4c, 0x01, 0x7a, 0xae, 0xd5, 0xe4, 0x9f, 0x4b, 0x30, 0x7d, 0x06, 0xd2, 0xa9, 0x1e, 0x65, 0xb1, 0xca, 0x87,
|
||||
0xfc, 0x28, 0x53, 0x8e, 0xf5, 0x21, 0x5a, 0x17, 0x6c, 0xb8, 0xc3, 0x74, 0x0f, 0xdb, 0xa0, 0xed, 0x96, 0x42, 0x39, 0x08, 0x73, 0xa7, 0xdc, 0x91, 0xea,
|
||||
0x3e, 0x45, 0xf2, 0x89, 0x5d, 0x26, 0x6b, 0x10, 0xc4, 0xbf
|
||||
const uint8_t toDB[] = {
|
||||
0x00, 0x7b, 0xaf, 0xd4, 0x99, 0xe2, 0x36, 0x4d, 0xfa, 0x81, 0x55, 0x2e, 0x63, 0x18, 0xcc, 0xb7, 0x86, 0xfd, 0x29, 0x52, 0x1f,
|
||||
0x64, 0xb0, 0xcb, 0x7c, 0x07, 0xd3, 0xa8, 0xe5, 0x9e, 0x4a, 0x31, 0xec, 0x97, 0x43, 0x38, 0x75, 0x0e, 0xda, 0xa1, 0x16, 0x6d, 0xb9, 0xc2, 0x8f, 0xf4,
|
||||
0x20, 0x5b, 0x6a, 0x11, 0xc5, 0xbe, 0xf3, 0x88, 0x5c, 0x27, 0x90, 0xeb, 0x3f, 0x44, 0x09, 0x72, 0xa6, 0xdd, 0xef, 0x94, 0x40, 0x3b, 0x76, 0x0d, 0xd9,
|
||||
0xa2, 0x15, 0x6e, 0xba, 0xc1, 0x8c, 0xf7, 0x23, 0x58, 0x69, 0x12, 0xc6, 0xbd, 0xf0, 0x8b, 0x5f, 0x24, 0x93, 0xe8, 0x3c, 0x47, 0x0a, 0x71, 0xa5, 0xde,
|
||||
0x03, 0x78, 0xac, 0xd7, 0x9a, 0xe1, 0x35, 0x4e, 0xf9, 0x82, 0x56, 0x2d, 0x60, 0x1b, 0xcf, 0xb4, 0x85, 0xfe, 0x2a, 0x51, 0x1c, 0x67, 0xb3, 0xc8, 0x7f,
|
||||
0x04, 0xd0, 0xab, 0xe6, 0x9d, 0x49, 0x32, 0x8d, 0xf6, 0x22, 0x59, 0x14, 0x6f, 0xbb, 0xc0, 0x77, 0x0c, 0xd8, 0xa3, 0xee, 0x95, 0x41, 0x3a, 0x0b, 0x70,
|
||||
0xa4, 0xdf, 0x92, 0xe9, 0x3d, 0x46, 0xf1, 0x8a, 0x5e, 0x25, 0x68, 0x13, 0xc7, 0xbc, 0x61, 0x1a, 0xce, 0xb5, 0xf8, 0x83, 0x57, 0x2c, 0x9b, 0xe0, 0x34,
|
||||
0x4f, 0x02, 0x79, 0xad, 0xd6, 0xe7, 0x9c, 0x48, 0x33, 0x7e, 0x05, 0xd1, 0xaa, 0x1d, 0x66, 0xb2, 0xc9, 0x84, 0xff, 0x2b, 0x50, 0x62, 0x19, 0xcd, 0xb6,
|
||||
0xfb, 0x80, 0x54, 0x2f, 0x98, 0xe3, 0x37, 0x4c, 0x01, 0x7a, 0xae, 0xd5, 0xe4, 0x9f, 0x4b, 0x30, 0x7d, 0x06, 0xd2, 0xa9, 0x1e, 0x65, 0xb1, 0xca, 0x87,
|
||||
0xfc, 0x28, 0x53, 0x8e, 0xf5, 0x21, 0x5a, 0x17, 0x6c, 0xb8, 0xc3, 0x74, 0x0f, 0xdb, 0xa0, 0xed, 0x96, 0x42, 0x39, 0x08, 0x73, 0xa7, 0xdc, 0x91, 0xea,
|
||||
0x3e, 0x45, 0xf2, 0x89, 0x5d, 0x26, 0x6b, 0x10, 0xc4, 0xbf
|
||||
};
|
||||
|
||||
const uint8_t fromDB[] = {
|
||||
0x00, 0xcc, 0xac, 0x60, 0x79, 0xb5, 0xd5, 0x19, 0xf0, 0x3c, 0x5c, 0x90, 0x89, 0x45, 0x25, 0xe9, 0xfd, 0x31, 0x51, 0x9d,
|
||||
0x84, 0x48, 0x28, 0xe4, 0x0d, 0xc1, 0xa1, 0x6d, 0x74, 0xb8, 0xd8, 0x14, 0x2e, 0xe2, 0x82, 0x4e, 0x57, 0x9b, 0xfb, 0x37, 0xde, 0x12, 0x72, 0xbe, 0xa7,
|
||||
0x6b, 0x0b, 0xc7, 0xd3, 0x1f, 0x7f, 0xb3, 0xaa, 0x66, 0x06, 0xca, 0x23, 0xef, 0x8f, 0x43, 0x5a, 0x96, 0xf6, 0x3a, 0x42, 0x8e, 0xee, 0x22, 0x3b, 0xf7,
|
||||
0x97, 0x5b, 0xb2, 0x7e, 0x1e, 0xd2, 0xcb, 0x07, 0x67, 0xab, 0xbf, 0x73, 0x13, 0xdf, 0xc6, 0x0a, 0x6a, 0xa6, 0x4f, 0x83, 0xe3, 0x2f, 0x36, 0xfa, 0x9a,
|
||||
0x56, 0x6c, 0xa0, 0xc0, 0x0c, 0x15, 0xd9, 0xb9, 0x75, 0x9c, 0x50, 0x30, 0xfc, 0xe5, 0x29, 0x49, 0x85, 0x91, 0x5d, 0x3d, 0xf1, 0xe8, 0x24, 0x44, 0x88,
|
||||
0x61, 0xad, 0xcd, 0x01, 0x18, 0xd4, 0xb4, 0x78, 0xc5, 0x09, 0x69, 0xa5, 0xbc, 0x70, 0x10, 0xdc, 0x35, 0xf9, 0x99, 0x55, 0x4c, 0x80, 0xe0, 0x2c, 0x38,
|
||||
0xf4, 0x94, 0x58, 0x41, 0x8d, 0xed, 0x21, 0xc8, 0x04, 0x64, 0xa8, 0xb1, 0x7d, 0x1d, 0xd1, 0xeb, 0x27, 0x47, 0x8b, 0x92, 0x5e, 0x3e, 0xf2, 0x1b, 0xd7,
|
||||
0xb7, 0x7b, 0x62, 0xae, 0xce, 0x02, 0x16, 0xda, 0xba, 0x76, 0x6f, 0xa3, 0xc3, 0x0f, 0xe6, 0x2a, 0x4a, 0x86, 0x9f, 0x53, 0x33, 0xff, 0x87, 0x4b, 0x2b,
|
||||
0xe7, 0xfe, 0x32, 0x52, 0x9e, 0x77, 0xbb, 0xdb, 0x17, 0x0e, 0xc2, 0xa2, 0x6e, 0x7a, 0xb6, 0xd6, 0x1a, 0x03, 0xcf, 0xaf, 0x63, 0x8a, 0x46, 0x26, 0xea,
|
||||
0xf3, 0x3f, 0x5f, 0x93, 0xa9, 0x65, 0x05, 0xc9, 0xd0, 0x1c, 0x7c, 0xb0, 0x59, 0x95, 0xf5, 0x39, 0x20, 0xec, 0x8c, 0x40, 0x54, 0x98, 0xf8, 0x34, 0x2d,
|
||||
0xe1, 0x81, 0x4d, 0xa4, 0x68, 0x08, 0xc4, 0xdd, 0x11, 0x71, 0xbd
|
||||
0x84, 0x48, 0x28, 0xe4, 0x0d, 0xc1, 0xa1, 0x6d, 0x74, 0xb8, 0xd8, 0x14, 0x2e, 0xe2, 0x82, 0x4e, 0x57, 0x9b, 0xfb, 0x37, 0xde, 0x12, 0x72, 0xbe, 0xa7,
|
||||
0x6b, 0x0b, 0xc7, 0xd3, 0x1f, 0x7f, 0xb3, 0xaa, 0x66, 0x06, 0xca, 0x23, 0xef, 0x8f, 0x43, 0x5a, 0x96, 0xf6, 0x3a, 0x42, 0x8e, 0xee, 0x22, 0x3b, 0xf7,
|
||||
0x97, 0x5b, 0xb2, 0x7e, 0x1e, 0xd2, 0xcb, 0x07, 0x67, 0xab, 0xbf, 0x73, 0x13, 0xdf, 0xc6, 0x0a, 0x6a, 0xa6, 0x4f, 0x83, 0xe3, 0x2f, 0x36, 0xfa, 0x9a,
|
||||
0x56, 0x6c, 0xa0, 0xc0, 0x0c, 0x15, 0xd9, 0xb9, 0x75, 0x9c, 0x50, 0x30, 0xfc, 0xe5, 0x29, 0x49, 0x85, 0x91, 0x5d, 0x3d, 0xf1, 0xe8, 0x24, 0x44, 0x88,
|
||||
0x61, 0xad, 0xcd, 0x01, 0x18, 0xd4, 0xb4, 0x78, 0xc5, 0x09, 0x69, 0xa5, 0xbc, 0x70, 0x10, 0xdc, 0x35, 0xf9, 0x99, 0x55, 0x4c, 0x80, 0xe0, 0x2c, 0x38,
|
||||
0xf4, 0x94, 0x58, 0x41, 0x8d, 0xed, 0x21, 0xc8, 0x04, 0x64, 0xa8, 0xb1, 0x7d, 0x1d, 0xd1, 0xeb, 0x27, 0x47, 0x8b, 0x92, 0x5e, 0x3e, 0xf2, 0x1b, 0xd7,
|
||||
0xb7, 0x7b, 0x62, 0xae, 0xce, 0x02, 0x16, 0xda, 0xba, 0x76, 0x6f, 0xa3, 0xc3, 0x0f, 0xe6, 0x2a, 0x4a, 0x86, 0x9f, 0x53, 0x33, 0xff, 0x87, 0x4b, 0x2b,
|
||||
0xe7, 0xfe, 0x32, 0x52, 0x9e, 0x77, 0xbb, 0xdb, 0x17, 0x0e, 0xc2, 0xa2, 0x6e, 0x7a, 0xb6, 0xd6, 0x1a, 0x03, 0xcf, 0xaf, 0x63, 0x8a, 0x46, 0x26, 0xea,
|
||||
0xf3, 0x3f, 0x5f, 0x93, 0xa9, 0x65, 0x05, 0xc9, 0xd0, 0x1c, 0x7c, 0xb0, 0x59, 0x95, 0xf5, 0x39, 0x20, 0xec, 0x8c, 0x40, 0x54, 0x98, 0xf8, 0x34, 0x2d,
|
||||
0xe1, 0x81, 0x4d, 0xa4, 0x68, 0x08, 0xc4, 0xdd, 0x11, 0x71, 0xbd
|
||||
};
|
||||
|
||||
const uint8_t randVals[] = {
|
||||
@ -73,7 +72,7 @@ namespace dsp {
|
||||
for (int i = 0; i < 5; i++) { memset(outBuffers[i], 0, 255); }
|
||||
rs = correct_reed_solomon_create(correct_rs_primitive_polynomial_ccsds, 120, 11, 16);
|
||||
if (rs == NULL) { printf("Error creating the reed solomon decoder\n"); }
|
||||
|
||||
|
||||
generic_block<FalconRS>::registerInput(_in);
|
||||
generic_block<FalconRS>::registerOutput(&out);
|
||||
}
|
||||
@ -85,29 +84,44 @@ namespace dsp {
|
||||
uint8_t* data = _in->readBuf + 4;
|
||||
|
||||
// Deinterleave
|
||||
for (int i = 0; i < 255*5; i++) {
|
||||
buffers[i%5][i/5] = fromDB[data[i]];
|
||||
for (int i = 0; i < 255 * 5; i++) {
|
||||
buffers[i % 5][i / 5] = fromDB[data[i]];
|
||||
}
|
||||
|
||||
// Reed the solomon :weary:
|
||||
int result = 0;
|
||||
result = correct_reed_solomon_decode(rs, buffers[0], 255, outBuffers[0]);
|
||||
if (result == -1) { _in->flush(); return count; }
|
||||
if (result == -1) {
|
||||
_in->flush();
|
||||
return count;
|
||||
}
|
||||
result = correct_reed_solomon_decode(rs, buffers[1], 255, outBuffers[1]);
|
||||
if (result == -1) { _in->flush(); return count; }
|
||||
if (result == -1) {
|
||||
_in->flush();
|
||||
return count;
|
||||
}
|
||||
result = correct_reed_solomon_decode(rs, buffers[2], 255, outBuffers[2]);
|
||||
if (result == -1) { _in->flush(); return count; }
|
||||
if (result == -1) {
|
||||
_in->flush();
|
||||
return count;
|
||||
}
|
||||
result = correct_reed_solomon_decode(rs, buffers[3], 255, outBuffers[3]);
|
||||
if (result == -1) { _in->flush(); return count; }
|
||||
if (result == -1) {
|
||||
_in->flush();
|
||||
return count;
|
||||
}
|
||||
result = correct_reed_solomon_decode(rs, buffers[4], 255, outBuffers[4]);
|
||||
if (result == -1) { _in->flush(); return count; }
|
||||
|
||||
// Reinterleave
|
||||
for (int i = 0; i < 255*5; i++) {
|
||||
out.writeBuf[i] = toDB[outBuffers[i%5][i/5]] ^ randVals[i % 255];
|
||||
if (result == -1) {
|
||||
_in->flush();
|
||||
return count;
|
||||
}
|
||||
|
||||
out.swap(255*5);
|
||||
// Reinterleave
|
||||
for (int i = 0; i < 255 * 5; i++) {
|
||||
out.writeBuf[i] = toDB[outBuffers[i % 5][i / 5]] ^ randVals[i % 255];
|
||||
}
|
||||
|
||||
out.swap(255 * 5);
|
||||
|
||||
_in->flush();
|
||||
return count;
|
||||
@ -120,8 +134,7 @@ namespace dsp {
|
||||
uint8_t buffers[5][255];
|
||||
uint8_t outBuffers[5][255];
|
||||
correct_reed_solomon* rs;
|
||||
|
||||
stream<uint8_t>* _in;
|
||||
|
||||
stream<uint8_t>* _in;
|
||||
};
|
||||
}
|
@ -20,7 +20,7 @@ namespace dsp {
|
||||
|
||||
void init(stream<uint8_t>* in) {
|
||||
_in = in;
|
||||
|
||||
|
||||
generic_block<FalconPacketSync>::registerInput(_in);
|
||||
generic_block<FalconPacketSync>::registerOutput(&out);
|
||||
}
|
||||
@ -56,7 +56,7 @@ namespace dsp {
|
||||
else if (header.packet == 2047) {
|
||||
printf("Wow, all data\n");
|
||||
_in->flush();
|
||||
return count;
|
||||
return count;
|
||||
}
|
||||
|
||||
// Finish reading the last package and send it
|
||||
@ -84,9 +84,8 @@ namespace dsp {
|
||||
packetRead = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
uint64_t pktId = ((uint64_t)data[i + 2] << 56) | ((uint64_t)data[i + 3] << 48) | ((uint64_t)data[i + 4] << 40) | ((uint64_t)data[i + 5] << 32)
|
||||
| ((uint64_t)data[i + 6] << 24) | ((uint64_t)data[i + 7] << 16) | ((uint64_t)data[i + 8] << 8) | data[i + 9];
|
||||
|
||||
uint64_t pktId = ((uint64_t)data[i + 2] << 56) | ((uint64_t)data[i + 3] << 48) | ((uint64_t)data[i + 4] << 40) | ((uint64_t)data[i + 5] << 32) | ((uint64_t)data[i + 6] << 24) | ((uint64_t)data[i + 7] << 16) | ((uint64_t)data[i + 8] << 8) | data[i + 9];
|
||||
|
||||
// If the packet doesn't fit the frame, save and go to next frame
|
||||
if (dataLen - i < length) {
|
||||
@ -99,7 +98,6 @@ namespace dsp {
|
||||
memcpy(out.writeBuf, &data[i], length);
|
||||
out.swap(length);
|
||||
i += length;
|
||||
|
||||
}
|
||||
|
||||
_in->flush();
|
||||
@ -114,8 +112,7 @@ namespace dsp {
|
||||
|
||||
int packetRead = -1;
|
||||
uint8_t packet[0x4008];
|
||||
|
||||
stream<uint8_t>* _in;
|
||||
|
||||
stream<uint8_t>* _in;
|
||||
};
|
||||
}
|
@ -23,9 +23,9 @@
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#define CONCAT(a, b) ((std::string(a) + b).c_str())
|
||||
#define CONCAT(a, b) ((std::string(a) + b).c_str())
|
||||
|
||||
SDRPP_MOD_INFO {
|
||||
SDRPP_MOD_INFO{
|
||||
/* Name: */ "falcon9_decoder",
|
||||
/* Description: */ "Falcon9 telemetry decoder for SDR++",
|
||||
/* Author: */ "Ryzerth",
|
||||
@ -33,7 +33,7 @@ SDRPP_MOD_INFO {
|
||||
/* Max instances */ -1
|
||||
};
|
||||
|
||||
#define INPUT_SAMPLE_RATE 6000000
|
||||
#define INPUT_SAMPLE_RATE 6000000
|
||||
|
||||
std::ofstream file("output.ts");
|
||||
|
||||
@ -84,7 +84,6 @@ public:
|
||||
}
|
||||
|
||||
~Falcon9DecoderModule() {
|
||||
|
||||
}
|
||||
|
||||
void postInit() {}
|
||||
@ -187,10 +186,9 @@ private:
|
||||
Falcon9DecoderModule* _this = (Falcon9DecoderModule*)ctx;
|
||||
|
||||
uint16_t length = (((data[0] & 0b1111) << 8) | data[1]) + 2;
|
||||
uint64_t pktId = ((uint64_t)data[2] << 56) | ((uint64_t)data[3] << 48) | ((uint64_t)data[4] << 40) | ((uint64_t)data[5] << 32)
|
||||
| ((uint64_t)data[6] << 24) | ((uint64_t)data[7] << 16) | ((uint64_t)data[8] << 8) | data[9];
|
||||
uint64_t pktId = ((uint64_t)data[2] << 56) | ((uint64_t)data[3] << 48) | ((uint64_t)data[4] << 40) | ((uint64_t)data[5] << 32) | ((uint64_t)data[6] << 24) | ((uint64_t)data[7] << 16) | ((uint64_t)data[8] << 8) | data[9];
|
||||
|
||||
if (pktId == 0x0117FE0800320303 || pktId == 0x0112FA0800320303) {
|
||||
if (pktId == 0x0117FE0800320303 || pktId == 0x0112FA0800320303) {
|
||||
data[length - 2] = 0;
|
||||
_this->logsMtx.lock();
|
||||
_this->gpsLogs += (char*)(data + 25);
|
||||
@ -207,13 +205,13 @@ private:
|
||||
static void symSinkHandler(float* data, int count, void* ctx) {
|
||||
Falcon9DecoderModule* _this = (Falcon9DecoderModule*)ctx;
|
||||
float* buf = _this->symDiag.acquireBuffer();
|
||||
memcpy(buf, data, 1024*sizeof(float));
|
||||
memcpy(buf, data, 1024 * sizeof(float));
|
||||
_this->symDiag.releaseBuffer();
|
||||
}
|
||||
|
||||
std::string name;
|
||||
bool enabled = true;
|
||||
|
||||
|
||||
bool logsVisible = false;
|
||||
|
||||
std::mutex logsMtx;
|
||||
@ -232,7 +230,7 @@ private:
|
||||
dsp::stream<float> thrInput;
|
||||
dsp::Threshold thr;
|
||||
|
||||
uint8_t syncWord[32] = {0,0,0,1,1,0,1,0,1,1,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,0,1};
|
||||
uint8_t syncWord[32] = { 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1 };
|
||||
dsp::Deframer deframe;
|
||||
dsp::FalconRS falconRS;
|
||||
dsp::FalconPacketSync pkt;
|
||||
@ -243,7 +241,6 @@ private:
|
||||
VFOManager::VFO* vfo;
|
||||
|
||||
ImGui::SymbolDiagram symDiag;
|
||||
|
||||
};
|
||||
|
||||
MOD_EXPORT void _INIT_() {
|
||||
|
@ -1,11 +1,11 @@
|
||||
#include <base40.h>
|
||||
|
||||
void decode_callsign_base40(uint64_t encoded, char *callsign) {
|
||||
void decode_callsign_base40(uint64_t encoded, char* callsign) {
|
||||
if (encoded >= 262144000000000) { // 40^9
|
||||
*callsign = 0;
|
||||
return;
|
||||
}
|
||||
char *p = callsign;
|
||||
char* p = callsign;
|
||||
for (; encoded > 0; p++) {
|
||||
*p = " ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-/."[encoded % 40];
|
||||
encoded /= 40;
|
||||
|
@ -6,67 +6,57 @@
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
|
||||
namespace mobilinkd
|
||||
{
|
||||
namespace mobilinkd {
|
||||
|
||||
template <uint16_t Poly = 0x5935, uint16_t Init = 0xFFFF>
|
||||
struct CRC16
|
||||
{
|
||||
static constexpr uint16_t MASK = 0xFFFF;
|
||||
static constexpr uint16_t LSB = 0x0001;
|
||||
static constexpr uint16_t MSB = 0x8000;
|
||||
template <uint16_t Poly = 0x5935, uint16_t Init = 0xFFFF>
|
||||
struct CRC16 {
|
||||
static constexpr uint16_t MASK = 0xFFFF;
|
||||
static constexpr uint16_t LSB = 0x0001;
|
||||
static constexpr uint16_t MSB = 0x8000;
|
||||
|
||||
uint16_t reg_ = Init;
|
||||
uint16_t reg_ = Init;
|
||||
|
||||
void reset()
|
||||
{
|
||||
reg_ = Init;
|
||||
void reset() {
|
||||
reg_ = Init;
|
||||
|
||||
for (size_t i = 0; i != 16; ++i)
|
||||
{
|
||||
auto bit = reg_ & LSB;
|
||||
if (bit) reg_ ^= Poly;
|
||||
reg_ >>= 1;
|
||||
if (bit) reg_ |= MSB;
|
||||
for (size_t i = 0; i != 16; ++i) {
|
||||
auto bit = reg_ & LSB;
|
||||
if (bit) reg_ ^= Poly;
|
||||
reg_ >>= 1;
|
||||
if (bit) reg_ |= MSB;
|
||||
}
|
||||
|
||||
reg_ &= MASK;
|
||||
}
|
||||
|
||||
reg_ &= MASK;
|
||||
}
|
||||
|
||||
void operator()(uint8_t byte)
|
||||
{
|
||||
reg_ = crc(byte, reg_);
|
||||
}
|
||||
|
||||
uint16_t crc(uint8_t byte, uint16_t reg)
|
||||
{
|
||||
for (size_t i = 0; i != 8; ++i)
|
||||
{
|
||||
auto msb = reg & MSB;
|
||||
reg = ((reg << 1) & MASK) | ((byte >> (7 - i)) & LSB);
|
||||
if (msb) reg ^= Poly;
|
||||
void operator()(uint8_t byte) {
|
||||
reg_ = crc(byte, reg_);
|
||||
}
|
||||
return reg & MASK;
|
||||
}
|
||||
|
||||
uint16_t get()
|
||||
{
|
||||
auto reg = reg_;
|
||||
for (size_t i = 0; i != 16; ++i)
|
||||
{
|
||||
auto msb = reg & MSB;
|
||||
reg = ((reg << 1) & MASK);
|
||||
if (msb) reg ^= Poly;
|
||||
|
||||
uint16_t crc(uint8_t byte, uint16_t reg) {
|
||||
for (size_t i = 0; i != 8; ++i) {
|
||||
auto msb = reg & MSB;
|
||||
reg = ((reg << 1) & MASK) | ((byte >> (7 - i)) & LSB);
|
||||
if (msb) reg ^= Poly;
|
||||
}
|
||||
return reg & MASK;
|
||||
}
|
||||
return reg;
|
||||
}
|
||||
|
||||
std::array<uint8_t, 2> get_bytes()
|
||||
{
|
||||
auto crc = get();
|
||||
std::array<uint8_t, 2> result{uint8_t((crc >> 8) & 0xFF), uint8_t(crc & 0xFF)};
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
uint16_t get() {
|
||||
auto reg = reg_;
|
||||
for (size_t i = 0; i != 16; ++i) {
|
||||
auto msb = reg & MSB;
|
||||
reg = ((reg << 1) & MASK);
|
||||
if (msb) reg ^= Poly;
|
||||
}
|
||||
return reg;
|
||||
}
|
||||
|
||||
std::array<uint8_t, 2> get_bytes() {
|
||||
auto crc = get();
|
||||
std::array<uint8_t, 2> result{ uint8_t((crc >> 8) & 0xFF), uint8_t(crc & 0xFF) };
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
} // mobilinkd
|
@ -10,224 +10,194 @@
|
||||
|
||||
namespace mobilinkd {
|
||||
|
||||
// Parts are adapted from:
|
||||
// http://aqdi.com/articles/using-the-golay-error-detection-and-correction-code-3/
|
||||
// Parts are adapted from:
|
||||
// http://aqdi.com/articles/using-the-golay-error-detection-and-correction-code-3/
|
||||
|
||||
namespace Golay24
|
||||
{
|
||||
namespace Golay24 {
|
||||
|
||||
int popcount(uint32_t n) {
|
||||
int count = 0;
|
||||
for (int i = 0; i < 32; i++) {
|
||||
count += ((n >> i) & 1);
|
||||
int popcount(uint32_t n) {
|
||||
int count = 0;
|
||||
for (int i = 0; i < 32; i++) {
|
||||
count += ((n >> i) & 1);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
namespace detail {
|
||||
|
||||
// Need a constexpr sort.
|
||||
// https://stackoverflow.com/a/40030044/854133
|
||||
template<class T>
|
||||
void swap(T& l, T& r)
|
||||
{
|
||||
T tmp = std::move(l);
|
||||
l = std::move(r);
|
||||
r = std::move(tmp);
|
||||
}
|
||||
// Need a constexpr sort.
|
||||
// https://stackoverflow.com/a/40030044/854133
|
||||
template <class T>
|
||||
void swap(T& l, T& r) {
|
||||
T tmp = std::move(l);
|
||||
l = std::move(r);
|
||||
r = std::move(tmp);
|
||||
}
|
||||
|
||||
template <typename T, size_t N>
|
||||
struct array
|
||||
{
|
||||
constexpr T& operator[](size_t i)
|
||||
{
|
||||
return arr[i];
|
||||
}
|
||||
template <typename T, size_t N>
|
||||
struct array {
|
||||
constexpr T& operator[](size_t i) {
|
||||
return arr[i];
|
||||
}
|
||||
|
||||
constexpr const T& operator[](size_t i) const
|
||||
{
|
||||
return arr[i];
|
||||
}
|
||||
constexpr const T& operator[](size_t i) const {
|
||||
return arr[i];
|
||||
}
|
||||
|
||||
constexpr const T* begin() const
|
||||
{
|
||||
return arr;
|
||||
}
|
||||
constexpr const T* end() const
|
||||
{
|
||||
return arr + N;
|
||||
}
|
||||
constexpr const T* begin() const {
|
||||
return arr;
|
||||
}
|
||||
constexpr const T* end() const {
|
||||
return arr + N;
|
||||
}
|
||||
|
||||
T arr[N];
|
||||
};
|
||||
T arr[N];
|
||||
};
|
||||
|
||||
template <typename T, size_t N>
|
||||
void sort_impl(array<T, N> &array, size_t left, size_t right)
|
||||
{
|
||||
if (left < right)
|
||||
{
|
||||
size_t m = left;
|
||||
template <typename T, size_t N>
|
||||
void sort_impl(array<T, N>& array, size_t left, size_t right) {
|
||||
if (left < right) {
|
||||
size_t m = left;
|
||||
|
||||
for (size_t i = left + 1; i<right; i++)
|
||||
if (array[i]<array[left])
|
||||
swap(array[++m], array[i]);
|
||||
for (size_t i = left + 1; i < right; i++)
|
||||
if (array[i] < array[left])
|
||||
swap(array[++m], array[i]);
|
||||
|
||||
swap(array[left], array[m]);
|
||||
swap(array[left], array[m]);
|
||||
|
||||
sort_impl(array, left, m);
|
||||
sort_impl(array, m + 1, right);
|
||||
}
|
||||
}
|
||||
sort_impl(array, left, m);
|
||||
sort_impl(array, m + 1, right);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, size_t N>
|
||||
array<T, N> sort(array<T, N> array)
|
||||
{
|
||||
auto sorted = array;
|
||||
sort_impl(sorted, 0, N);
|
||||
return sorted;
|
||||
}
|
||||
template <typename T, size_t N>
|
||||
array<T, N> sort(array<T, N> array) {
|
||||
auto sorted = array;
|
||||
sort_impl(sorted, 0, N);
|
||||
return sorted;
|
||||
}
|
||||
|
||||
} // detail
|
||||
} // detail
|
||||
|
||||
// static constexpr uint16_t POLY = 0xAE3;
|
||||
constexpr uint16_t POLY = 0xC75;
|
||||
// static constexpr uint16_t POLY = 0xAE3;
|
||||
constexpr uint16_t POLY = 0xC75;
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct SyndromeMapEntry
|
||||
{
|
||||
uint32_t a{0};
|
||||
uint16_t b{0};
|
||||
};
|
||||
struct SyndromeMapEntry {
|
||||
uint32_t a{ 0 };
|
||||
uint16_t b{ 0 };
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
/**
|
||||
/**
|
||||
* Calculate the syndrome of a [23,12] Golay codeword.
|
||||
*
|
||||
* @return the 11-bit syndrome of the codeword in bits [22:12].
|
||||
*/
|
||||
uint32_t syndrome(uint32_t codeword)
|
||||
{
|
||||
codeword &= 0xffffffl;
|
||||
for (size_t i = 0; i != 12; ++i)
|
||||
{
|
||||
if (codeword & 1)
|
||||
codeword ^= POLY;
|
||||
codeword >>= 1;
|
||||
}
|
||||
return (codeword << 12);
|
||||
}
|
||||
|
||||
bool parity(uint32_t codeword)
|
||||
{
|
||||
return popcount(codeword) & 1;
|
||||
}
|
||||
|
||||
SyndromeMapEntry makeSyndromeMapEntry(uint64_t val)
|
||||
{
|
||||
return SyndromeMapEntry{uint32_t(val >> 16), uint16_t(val & 0xFFFF)};
|
||||
}
|
||||
|
||||
uint64_t makeSME(uint64_t syndrome, uint32_t bits)
|
||||
{
|
||||
return (syndrome << 24) | (bits & 0xFFFFFF);
|
||||
}
|
||||
|
||||
constexpr size_t LUT_SIZE = 2048;
|
||||
|
||||
std::array<SyndromeMapEntry, LUT_SIZE> make_lut()
|
||||
{
|
||||
constexpr size_t VECLEN=23;
|
||||
detail::array<uint64_t, LUT_SIZE> result{};
|
||||
|
||||
size_t index = 0;
|
||||
result[index++] = makeSME(syndrome(0), 0);
|
||||
|
||||
for (size_t i = 0; i != VECLEN; ++i)
|
||||
{
|
||||
auto v = (1 << i);
|
||||
result[index++] = makeSME(syndrome(v), v);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i != VECLEN - 1; ++i)
|
||||
{
|
||||
for (size_t j = i + 1; j != VECLEN; ++j)
|
||||
{
|
||||
auto v = (1 << i) | (1 << j);
|
||||
result[index++] = makeSME(syndrome(v), v);
|
||||
uint32_t syndrome(uint32_t codeword) {
|
||||
codeword &= 0xffffffl;
|
||||
for (size_t i = 0; i != 12; ++i) {
|
||||
if (codeword & 1)
|
||||
codeword ^= POLY;
|
||||
codeword >>= 1;
|
||||
}
|
||||
return (codeword << 12);
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i != VECLEN - 2; ++i)
|
||||
{
|
||||
for (size_t j = i + 1; j != VECLEN - 1; ++j)
|
||||
{
|
||||
for (size_t k = j + 1; k != VECLEN; ++k)
|
||||
{
|
||||
auto v = (1 << i) | (1 << j) | (1 << k);
|
||||
bool parity(uint32_t codeword) {
|
||||
return popcount(codeword) & 1;
|
||||
}
|
||||
|
||||
SyndromeMapEntry makeSyndromeMapEntry(uint64_t val) {
|
||||
return SyndromeMapEntry{ uint32_t(val >> 16), uint16_t(val & 0xFFFF) };
|
||||
}
|
||||
|
||||
uint64_t makeSME(uint64_t syndrome, uint32_t bits) {
|
||||
return (syndrome << 24) | (bits & 0xFFFFFF);
|
||||
}
|
||||
|
||||
constexpr size_t LUT_SIZE = 2048;
|
||||
|
||||
std::array<SyndromeMapEntry, LUT_SIZE> make_lut() {
|
||||
constexpr size_t VECLEN = 23;
|
||||
detail::array<uint64_t, LUT_SIZE> result{};
|
||||
|
||||
size_t index = 0;
|
||||
result[index++] = makeSME(syndrome(0), 0);
|
||||
|
||||
for (size_t i = 0; i != VECLEN; ++i) {
|
||||
auto v = (1 << i);
|
||||
result[index++] = makeSME(syndrome(v), v);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i != VECLEN - 1; ++i) {
|
||||
for (size_t j = i + 1; j != VECLEN; ++j) {
|
||||
auto v = (1 << i) | (1 << j);
|
||||
result[index++] = makeSME(syndrome(v), v);
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i != VECLEN - 2; ++i) {
|
||||
for (size_t j = i + 1; j != VECLEN - 1; ++j) {
|
||||
for (size_t k = j + 1; k != VECLEN; ++k) {
|
||||
auto v = (1 << i) | (1 << j) | (1 << k);
|
||||
result[index++] = makeSME(syndrome(v), v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result = detail::sort(result);
|
||||
|
||||
std::array<SyndromeMapEntry, LUT_SIZE> tmp;
|
||||
for (size_t i = 0; i != LUT_SIZE; ++i) {
|
||||
tmp[i] = makeSyndromeMapEntry(result[i]);
|
||||
}
|
||||
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
|
||||
result = detail::sort(result);
|
||||
inline auto LUT = make_lut();
|
||||
|
||||
std::array<SyndromeMapEntry, LUT_SIZE> tmp;
|
||||
for (size_t i = 0; i != LUT_SIZE; ++i)
|
||||
{
|
||||
tmp[i] = makeSyndromeMapEntry(result[i]);
|
||||
}
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
inline auto LUT = make_lut();
|
||||
|
||||
/**
|
||||
/**
|
||||
* Calculate [23,12] Golay codeword.
|
||||
*
|
||||
* @return checkbits(11)|data(12).
|
||||
*/
|
||||
uint32_t encode23(uint16_t data)
|
||||
{
|
||||
// data &= 0xfff;
|
||||
uint32_t codeword = data;
|
||||
for (size_t i = 0; i != 12; ++i)
|
||||
{
|
||||
if (codeword & 1)
|
||||
codeword ^= POLY;
|
||||
codeword >>= 1;
|
||||
}
|
||||
return codeword | (data << 11);
|
||||
}
|
||||
uint32_t encode23(uint16_t data) {
|
||||
// data &= 0xfff;
|
||||
uint32_t codeword = data;
|
||||
for (size_t i = 0; i != 12; ++i) {
|
||||
if (codeword & 1)
|
||||
codeword ^= POLY;
|
||||
codeword >>= 1;
|
||||
}
|
||||
return codeword | (data << 11);
|
||||
}
|
||||
|
||||
uint32_t encode24(uint16_t data)
|
||||
{
|
||||
auto codeword = encode23(data);
|
||||
return ((codeword << 1) | parity(codeword));
|
||||
}
|
||||
uint32_t encode24(uint16_t data) {
|
||||
auto codeword = encode23(data);
|
||||
return ((codeword << 1) | parity(codeword));
|
||||
}
|
||||
|
||||
bool decode(uint32_t input, uint32_t& output)
|
||||
{
|
||||
auto syndrm = syndrome(input >> 1);
|
||||
auto it = std::lower_bound(LUT.begin(), LUT.end(), syndrm,
|
||||
[](const SyndromeMapEntry& sme, uint32_t val){
|
||||
return (sme.a >> 8) < val;
|
||||
});
|
||||
bool decode(uint32_t input, uint32_t& output) {
|
||||
auto syndrm = syndrome(input >> 1);
|
||||
auto it = std::lower_bound(LUT.begin(), LUT.end(), syndrm,
|
||||
[](const SyndromeMapEntry& sme, uint32_t val) {
|
||||
return (sme.a >> 8) < val;
|
||||
});
|
||||
|
||||
if ((it->a >> 8) == syndrm)
|
||||
{
|
||||
// Build the correction from the compressed entry.
|
||||
auto correction = ((((it->a & 0xFF) << 16) | it->b) << 1);
|
||||
// Apply the correction to the input.
|
||||
output = input ^ correction;
|
||||
// Only test parity for 3-bit errors.
|
||||
return popcount(syndrm) < 3 || !parity(output);
|
||||
}
|
||||
if ((it->a >> 8) == syndrm) {
|
||||
// Build the correction from the compressed entry.
|
||||
auto correction = ((((it->a & 0xFF) << 16) | it->b) << 1);
|
||||
// Apply the correction to the input.
|
||||
output = input ^ correction;
|
||||
// Only test parity for 3-bit errors.
|
||||
return popcount(syndrm) < 3 || !parity(output);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // Golay24
|
||||
} // Golay24
|
||||
|
||||
} // mobilinkd
|
@ -31,7 +31,7 @@ M17LSF M17DecodeLSF(uint8_t* _lsf) {
|
||||
// Extract CRC
|
||||
lsf.rawCRC = 0;
|
||||
for (int i = 0; i < 16; i++) {
|
||||
lsf.rawCRC |= (((uint16_t)_lsf[(i+48+48+16+112) / 8] >> (7 - (i%8))) & 1) << (15 - i);
|
||||
lsf.rawCRC |= (((uint16_t)_lsf[(i + 48 + 48 + 16 + 112) / 8] >> (7 - (i % 8))) & 1) << (15 - i);
|
||||
}
|
||||
|
||||
// Check CRC
|
||||
@ -50,19 +50,19 @@ M17LSF M17DecodeLSF(uint8_t* _lsf) {
|
||||
// Extract DST
|
||||
lsf.rawDst = 0;
|
||||
for (int i = 0; i < 48; i++) {
|
||||
lsf.rawDst |= (((uint64_t)_lsf[i / 8] >> (7 - (i%8))) & 1) << (47 - i);
|
||||
lsf.rawDst |= (((uint64_t)_lsf[i / 8] >> (7 - (i % 8))) & 1) << (47 - i);
|
||||
}
|
||||
|
||||
// Extract SRC
|
||||
lsf.rawSrc = 0;
|
||||
for (int i = 0; i < 48; i++) {
|
||||
lsf.rawSrc |= (((uint64_t)_lsf[(i+48) / 8] >> (7 - (i%8))) & 1) << (47 - i);
|
||||
lsf.rawSrc |= (((uint64_t)_lsf[(i + 48) / 8] >> (7 - (i % 8))) & 1) << (47 - i);
|
||||
}
|
||||
|
||||
// Extract TYPE
|
||||
lsf.rawType = 0;
|
||||
for (int i = 0; i < 16; i++) {
|
||||
lsf.rawType |= (((uint16_t)_lsf[(i+48+48) / 8] >> (7 - (i%8))) & 1) << (15 - i);
|
||||
lsf.rawType |= (((uint16_t)_lsf[(i + 48 + 48) / 8] >> (7 - (i % 8))) & 1) << (15 - i);
|
||||
}
|
||||
|
||||
// Extract META
|
||||
|
@ -3,17 +3,17 @@
|
||||
#include <stdint.h>
|
||||
|
||||
enum M17DataType {
|
||||
M17_DATATYPE_UNKNOWN = 0b00,
|
||||
M17_DATATYPE_DATA = 0b01,
|
||||
M17_DATATYPE_VOICE = 0b10,
|
||||
M17_DATATYPE_UNKNOWN = 0b00,
|
||||
M17_DATATYPE_DATA = 0b01,
|
||||
M17_DATATYPE_VOICE = 0b10,
|
||||
M17_DATATYPE_DATA_VOICE = 0b11
|
||||
};
|
||||
|
||||
enum M17EncryptionType {
|
||||
M17_ENCRYPTION_NONE = 0b00,
|
||||
M17_ENCRYPTION_AES = 0b01,
|
||||
M17_ENCRYPTION_NONE = 0b00,
|
||||
M17_ENCRYPTION_AES = 0b01,
|
||||
M17_ENCRYPTION_SCRAMBLE = 0b10,
|
||||
M17_ENCRYPTION_UNKNOWN = 0b11
|
||||
M17_ENCRYPTION_UNKNOWN = 0b11
|
||||
};
|
||||
|
||||
extern const char* M17DataTypesTxt[4];
|
||||
|
@ -7,50 +7,50 @@
|
||||
#include <lsf_decode.h>
|
||||
|
||||
extern "C" {
|
||||
#include <correct.h>
|
||||
#include <correct.h>
|
||||
}
|
||||
|
||||
#define M17_DEVIATION 2400.0f
|
||||
#define M17_BAUDRATE 4800.0f
|
||||
#define M17_RRC_ALPHA 0.5f
|
||||
#define M17_4FSK_HIGH_CUT 0.5f
|
||||
#define M17_DEVIATION 2400.0f
|
||||
#define M17_BAUDRATE 4800.0f
|
||||
#define M17_RRC_ALPHA 0.5f
|
||||
#define M17_4FSK_HIGH_CUT 0.5f
|
||||
|
||||
#define M17_SYNC_SIZE 16
|
||||
#define M17_LICH_SIZE 96
|
||||
#define M17_PAYLOAD_SIZE 144
|
||||
#define M17_ENCODED_PAYLOAD_SIZE 296
|
||||
#define M17_LSF_SIZE 240
|
||||
#define M17_ENCODED_LSF_SIZE 488
|
||||
#define M17_RAW_FRAME_SIZE 384
|
||||
#define M17_CUT_FRAME_SIZE 368
|
||||
#define M17_SYNC_SIZE 16
|
||||
#define M17_LICH_SIZE 96
|
||||
#define M17_PAYLOAD_SIZE 144
|
||||
#define M17_ENCODED_PAYLOAD_SIZE 296
|
||||
#define M17_LSF_SIZE 240
|
||||
#define M17_ENCODED_LSF_SIZE 488
|
||||
#define M17_RAW_FRAME_SIZE 384
|
||||
#define M17_CUT_FRAME_SIZE 368
|
||||
|
||||
const uint8_t M17_LSF_SYNC[16] = { 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1 };
|
||||
const uint8_t M17_STF_SYNC[16] = { 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1 };
|
||||
const uint8_t M17_PKF_SYNC[16] = { 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
|
||||
const uint8_t M17_LSF_SYNC[16] = { 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1 };
|
||||
const uint8_t M17_STF_SYNC[16] = { 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1 };
|
||||
const uint8_t M17_PKF_SYNC[16] = { 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
|
||||
|
||||
const uint8_t M17_SCRAMBLER[368] = { 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1,
|
||||
1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0,
|
||||
1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0,
|
||||
1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0,
|
||||
1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0,
|
||||
1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0,
|
||||
1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1,
|
||||
0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0,
|
||||
0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1,
|
||||
1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1,
|
||||
1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0,
|
||||
0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1,
|
||||
0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0,
|
||||
0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0,
|
||||
1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0,
|
||||
0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1,
|
||||
1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1,
|
||||
1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1,
|
||||
0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0,
|
||||
0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1,
|
||||
0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1 };
|
||||
const uint8_t M17_SCRAMBLER[368] = { 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1,
|
||||
1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0,
|
||||
1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0,
|
||||
1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0,
|
||||
1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0,
|
||||
1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0,
|
||||
1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1,
|
||||
0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0,
|
||||
0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1,
|
||||
1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1,
|
||||
1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0,
|
||||
0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1,
|
||||
0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0,
|
||||
0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0,
|
||||
1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0,
|
||||
0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1,
|
||||
1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1,
|
||||
1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1,
|
||||
0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0,
|
||||
0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1,
|
||||
0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1 };
|
||||
|
||||
const uint16_t M17_INTERLEAVER[368] = { 0, 137, 90, 227, 180, 317, 270, 39, 360, 129, 82, 219, 172, 309, 262, 31,
|
||||
352, 121, 74, 211, 164, 301, 254, 23, 344, 113, 66, 203, 156, 293, 246, 15,
|
||||
@ -83,7 +83,7 @@ const uint8_t M17_PUNCTURING_P1[61] = { 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1
|
||||
|
||||
const uint8_t M17_PUNCTURING_P2[12] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 };
|
||||
|
||||
static const correct_convolutional_polynomial_t correct_conv_m17_polynomial[] = {0b11001, 0b10111};
|
||||
static const correct_convolutional_polynomial_t correct_conv_m17_polynomial[] = { 0b11001, 0b10111 };
|
||||
|
||||
namespace dsp {
|
||||
class M17Slice4FSK : public generic_block<M17Slice4FSK> {
|
||||
@ -116,8 +116,8 @@ namespace dsp {
|
||||
float val;
|
||||
for (int i = 0; i < count; i++) {
|
||||
val = _in->readBuf[i];
|
||||
out.writeBuf[i*2] = (val < 0.0f);
|
||||
out.writeBuf[(i*2)+1] = (fabsf(val) > M17_4FSK_HIGH_CUT);
|
||||
out.writeBuf[i * 2] = (val < 0.0f);
|
||||
out.writeBuf[(i * 2) + 1] = (fabsf(val) > M17_4FSK_HIGH_CUT);
|
||||
}
|
||||
|
||||
_in->flush();
|
||||
@ -130,7 +130,6 @@ namespace dsp {
|
||||
|
||||
private:
|
||||
stream<float>* _in;
|
||||
|
||||
};
|
||||
|
||||
class M17FrameDemux : public generic_block<M17FrameDemux> {
|
||||
@ -176,7 +175,10 @@ namespace dsp {
|
||||
|
||||
for (int i = 0; i < count;) {
|
||||
if (detect) {
|
||||
if (outCount < M17_SYNC_SIZE) { outCount++; i++; }
|
||||
if (outCount < M17_SYNC_SIZE) {
|
||||
outCount++;
|
||||
i++;
|
||||
}
|
||||
else {
|
||||
int id = M17_INTERLEAVER[outCount - M17_SYNC_SIZE];
|
||||
|
||||
@ -192,21 +194,21 @@ namespace dsp {
|
||||
else if (type == 2) {
|
||||
packetOut.writeBuf[id - M17_LICH_SIZE] = (delay[i++] ^ M17_SCRAMBLER[outCount - M17_SYNC_SIZE]);
|
||||
}
|
||||
|
||||
|
||||
outCount++;
|
||||
}
|
||||
|
||||
|
||||
if (outCount >= M17_RAW_FRAME_SIZE) {
|
||||
detect = false;
|
||||
if (type == 0) {
|
||||
if (!linkSetupOut.swap(M17_CUT_FRAME_SIZE)) { return -1; }
|
||||
}
|
||||
else if (type == 1) {
|
||||
if (!lichOut.swap(M17_LICH_SIZE)) {return -1; }
|
||||
if (!streamOut.swap(M17_CUT_FRAME_SIZE)) {return -1; }
|
||||
if (!lichOut.swap(M17_LICH_SIZE)) { return -1; }
|
||||
if (!streamOut.swap(M17_CUT_FRAME_SIZE)) { return -1; }
|
||||
}
|
||||
else if (type == 2) {
|
||||
if (!lichOut.swap(M17_LICH_SIZE)) {return -1; }
|
||||
if (!lichOut.swap(M17_LICH_SIZE)) { return -1; }
|
||||
if (!packetOut.swap(M17_CUT_FRAME_SIZE)) { return -1; }
|
||||
}
|
||||
}
|
||||
@ -242,7 +244,7 @@ namespace dsp {
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
|
||||
memmove(delay, &delay[count], 16);
|
||||
|
||||
_in->flush();
|
||||
@ -264,7 +266,6 @@ namespace dsp {
|
||||
int type;
|
||||
|
||||
int outCount = 0;
|
||||
|
||||
};
|
||||
|
||||
class M17LSFDecoder : public generic_block<M17LSFDecoder> {
|
||||
@ -283,7 +284,7 @@ namespace dsp {
|
||||
_in = in;
|
||||
_handler = handler;
|
||||
_ctx = ctx;
|
||||
|
||||
|
||||
conv = correct_convolutional_create(2, 5, correct_conv_m17_polynomial);
|
||||
|
||||
generic_block<M17LSFDecoder>::registerInput(_in);
|
||||
@ -319,7 +320,7 @@ namespace dsp {
|
||||
// Pack into bytes
|
||||
memset(packed, 0, 61);
|
||||
for (int i = 0; i < M17_ENCODED_LSF_SIZE; i++) {
|
||||
packed[i/8] |= depunctured[i] << (7 - (i%8));
|
||||
packed[i / 8] |= depunctured[i] << (7 - (i % 8));
|
||||
}
|
||||
|
||||
// Run through convolutional decoder
|
||||
@ -343,7 +344,6 @@ namespace dsp {
|
||||
uint8_t lsf[30];
|
||||
|
||||
correct_convolutional* conv;
|
||||
|
||||
};
|
||||
|
||||
class M17PayloadFEC : public generic_block<M17PayloadFEC> {
|
||||
@ -360,7 +360,7 @@ namespace dsp {
|
||||
|
||||
void init(stream<uint8_t>* in) {
|
||||
_in = in;
|
||||
|
||||
|
||||
conv = correct_convolutional_create(2, 5, correct_conv_m17_polynomial);
|
||||
|
||||
generic_block<M17PayloadFEC>::registerInput(_in);
|
||||
@ -395,13 +395,13 @@ namespace dsp {
|
||||
// Pack into bytes
|
||||
memset(packed, 0, 37);
|
||||
for (int i = 0; i < M17_ENCODED_PAYLOAD_SIZE; i++) {
|
||||
if (!(i%8)) { packed[i/8] = 0; }
|
||||
packed[i/8] |= depunctured[i] << (7 - (i%8));
|
||||
if (!(i % 8)) { packed[i / 8] = 0; }
|
||||
packed[i / 8] |= depunctured[i] << (7 - (i % 8));
|
||||
}
|
||||
|
||||
// Run through convolutional decoder
|
||||
correct_convolutional_decode(conv, packed, M17_ENCODED_PAYLOAD_SIZE, out.writeBuf);
|
||||
|
||||
|
||||
_in->flush();
|
||||
|
||||
if (!out.swap(M17_PAYLOAD_SIZE / 8)) { return -1; }
|
||||
@ -417,7 +417,6 @@ namespace dsp {
|
||||
uint8_t packed[37];
|
||||
|
||||
correct_convolutional* conv;
|
||||
|
||||
};
|
||||
|
||||
class M17Codec2Decode : public generic_block<M17Codec2Decode> {
|
||||
@ -464,7 +463,7 @@ namespace dsp {
|
||||
|
||||
// Decode both parts using codec
|
||||
codec2_decode(codec, int16Audio, &_in->readBuf[2]);
|
||||
codec2_decode(codec, &int16Audio[sampsPerC2Frame], &_in->readBuf[2+8]);
|
||||
codec2_decode(codec, &int16Audio[sampsPerC2Frame], &_in->readBuf[2 + 8]);
|
||||
|
||||
// Convert to float
|
||||
volk_16i_s32f_convert_32f(floatAudio, int16Audio, 32768.0f, sampsPerC2FrameDouble);
|
||||
@ -489,7 +488,6 @@ namespace dsp {
|
||||
CODEC2* codec;
|
||||
int sampsPerC2Frame = 0;
|
||||
int sampsPerC2FrameDouble = 0;
|
||||
|
||||
};
|
||||
|
||||
class M17LICHDecoder : public generic_block<M17LICHDecoder> {
|
||||
@ -543,7 +541,7 @@ namespace dsp {
|
||||
uint8_t temp;
|
||||
for (int i = 0; i < 12; i++) {
|
||||
id = (b * 12) + i;
|
||||
chunk[id / 8] |= ((decodedBlock >> (23 - i)) & 1) << (7 - (id%8));
|
||||
chunk[id / 8] |= ((decodedBlock >> (23 - i)) & 1) << (7 - (id % 8));
|
||||
}
|
||||
}
|
||||
|
||||
@ -555,7 +553,7 @@ namespace dsp {
|
||||
if (partId == 0) {
|
||||
newFrame = true;
|
||||
lastId = 0;
|
||||
memcpy(&lsf[partId*5], chunk, 5);
|
||||
memcpy(&lsf[partId * 5], chunk, 5);
|
||||
return count;
|
||||
}
|
||||
|
||||
@ -568,7 +566,7 @@ namespace dsp {
|
||||
// If we're recording and there's no discontinuity (see above), add the data to the full frame
|
||||
if (newFrame) {
|
||||
lastId = partId;
|
||||
memcpy(&lsf[partId*5], chunk, 5);
|
||||
memcpy(&lsf[partId * 5], chunk, 5);
|
||||
|
||||
// If the lsf is complete, send it out
|
||||
if (partId == 5) {
|
||||
@ -590,7 +588,6 @@ namespace dsp {
|
||||
uint8_t lsf[240];
|
||||
bool newFrame = false;
|
||||
int lastId = 0;
|
||||
|
||||
};
|
||||
|
||||
class M17Decoder : public generic_hier_block<M17Decoder> {
|
||||
@ -620,7 +617,7 @@ namespace dsp {
|
||||
|
||||
diagOut = &doubler.outB;
|
||||
out = &decodeAudio.out;
|
||||
|
||||
|
||||
generic_hier_block<M17Decoder>::registerBlock(&demod);
|
||||
generic_hier_block<M17Decoder>::registerBlock(&fir);
|
||||
generic_hier_block<M17Decoder>::registerBlock(&recov);
|
||||
@ -661,7 +658,6 @@ namespace dsp {
|
||||
NullSink<uint8_t> ns2;
|
||||
|
||||
|
||||
float _sampleRate;
|
||||
|
||||
float _sampleRate;
|
||||
};
|
||||
}
|
@ -21,9 +21,9 @@
|
||||
#include <fstream>
|
||||
#include <chrono>
|
||||
|
||||
#define CONCAT(a, b) ((std::string(a) + b).c_str())
|
||||
#define CONCAT(a, b) ((std::string(a) + b).c_str())
|
||||
|
||||
SDRPP_MOD_INFO {
|
||||
SDRPP_MOD_INFO{
|
||||
/* Name: */ "m17_decoder",
|
||||
/* Description: */ "M17 Digital Voice Decoder for SDR++",
|
||||
/* Author: */ "Ryzerth",
|
||||
@ -84,7 +84,7 @@ public:
|
||||
sigpath::sinkManager.registerStream(name, &stream);
|
||||
|
||||
stream.start();
|
||||
|
||||
|
||||
gui::menu.registerEntry(name, menuHandler, this, this);
|
||||
}
|
||||
|
||||
@ -107,7 +107,7 @@ public:
|
||||
|
||||
void enable() {
|
||||
double bw = gui::waterfall.getBandwidth();
|
||||
vfo = sigpath::vfoManager.createVFO(name, ImGui::WaterfallVFO::REF_CENTER, std::clamp<double>(0, -bw/2.0, bw/2.0), 9600, INPUT_SAMPLE_RATE, 9600, 9600, true);
|
||||
vfo = sigpath::vfoManager.createVFO(name, ImGui::WaterfallVFO::REF_CENTER, std::clamp<double>(0, -bw / 2.0, bw / 2.0), 9600, INPUT_SAMPLE_RATE, 9600, 9600, true);
|
||||
vfo->setSnapInterval(250);
|
||||
|
||||
// Set Input of demod here
|
||||
@ -152,7 +152,7 @@ private:
|
||||
std::lock_guard lck(_this->lsfMtx);
|
||||
|
||||
auto now = std::chrono::high_resolution_clock::now();
|
||||
if (std::chrono::duration_cast<std::chrono::milliseconds>(now-_this->lastUpdated).count() > 1000) {
|
||||
if (std::chrono::duration_cast<std::chrono::milliseconds>(now - _this->lastUpdated).count() > 1000) {
|
||||
_this->lsf.valid = false;
|
||||
}
|
||||
|
||||
@ -251,7 +251,7 @@ private:
|
||||
M17DecoderModule* _this = (M17DecoderModule*)ctx;
|
||||
// TODO: If too slow, change all demods here and not when setting
|
||||
_this->audioSampRate = sampleRate;
|
||||
_this->resampWin.setCutoff(std::min<float>(sampleRate/2, 4000));
|
||||
_this->resampWin.setCutoff(std::min<float>(sampleRate / 2, 4000));
|
||||
_this->resamp.tempStop();
|
||||
_this->resamp.setOutSampleRate(sampleRate);
|
||||
_this->resampWin.setSampleRate(8000 * _this->resamp.getInterpolation());
|
||||
@ -273,7 +273,7 @@ private:
|
||||
VFOManager::VFO* vfo;
|
||||
|
||||
dsp::M17Decoder decoder;
|
||||
|
||||
|
||||
dsp::Reshaper<float> reshape;
|
||||
dsp::HandlerSink<float> diagHandler;
|
||||
|
||||
|
@ -21,9 +21,9 @@
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#define CONCAT(a, b) ((std::string(a) + b).c_str())
|
||||
#define CONCAT(a, b) ((std::string(a) + b).c_str())
|
||||
|
||||
SDRPP_MOD_INFO {
|
||||
SDRPP_MOD_INFO{
|
||||
/* Name: */ "meteor_demodulator",
|
||||
/* Description: */ "Meteor demodulator for SDR++",
|
||||
/* Author: */ "Ryzerth",
|
||||
@ -35,7 +35,7 @@ ConfigManager config;
|
||||
|
||||
std::string genFileName(std::string prefix, std::string suffix) {
|
||||
time_t now = time(0);
|
||||
tm *ltm = localtime(&now);
|
||||
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;
|
||||
@ -74,7 +74,7 @@ public:
|
||||
reshape.start();
|
||||
symSink.start();
|
||||
sink.start();
|
||||
|
||||
|
||||
gui::menu.registerEntry(name, menuHandler, this, this);
|
||||
core::modComManager.registerInterface("meteor_demodulator", name, moduleInterfaceHandler, this);
|
||||
}
|
||||
@ -98,7 +98,7 @@ public:
|
||||
|
||||
void enable() {
|
||||
double bw = gui::waterfall.getBandwidth();
|
||||
vfo = sigpath::vfoManager.createVFO(name, ImGui::WaterfallVFO::REF_CENTER, std::clamp<double>(0, -bw/2.0, bw/2.0), 150000, INPUT_SAMPLE_RATE, 150000, 150000, true);
|
||||
vfo = sigpath::vfoManager.createVFO(name, ImGui::WaterfallVFO::REF_CENTER, std::clamp<double>(0, -bw / 2.0, bw / 2.0), 150000, INPUT_SAMPLE_RATE, 150000, 150000, true);
|
||||
|
||||
demod.setInput(vfo->output);
|
||||
|
||||
@ -155,12 +155,12 @@ private:
|
||||
}
|
||||
else {
|
||||
if (ImGui::Button(CONCAT("Record##_recorder_rec_", _this->name), ImVec2(menuWidth, 0))) {
|
||||
_this->startRecording();
|
||||
_this->startRecording();
|
||||
}
|
||||
ImGui::Text("Idle --.--MB");
|
||||
}
|
||||
|
||||
if (!_this->folderSelect.pathIsValid() && _this->enabled) { style::endDisabled(); }
|
||||
if (!_this->folderSelect.pathIsValid() && _this->enabled) { style::endDisabled(); }
|
||||
|
||||
if (!_this->enabled) { style::endDisabled(); }
|
||||
}
|
||||
@ -196,7 +196,7 @@ private:
|
||||
}
|
||||
else {
|
||||
spdlog::error("Could not open file for recording!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void stopRecording() {
|
||||
@ -240,7 +240,6 @@ private:
|
||||
std::ofstream recFile;
|
||||
|
||||
int8_t* writeBuffer;
|
||||
|
||||
};
|
||||
|
||||
MOD_EXPORT void _INIT_() {
|
||||
|
@ -40,7 +40,7 @@ namespace demod {
|
||||
virtual double getAFBandwidth(double bandwidth) = 0;
|
||||
virtual bool getFMIFNRAllowed() = 0;
|
||||
virtual bool getNBAllowed() = 0;
|
||||
|
||||
|
||||
virtual bool getDynamicAFBandwidth() = 0;
|
||||
virtual dsp::stream<dsp::stereo_t>* getOutput() = 0;
|
||||
};
|
||||
|
@ -7,7 +7,7 @@ namespace demod {
|
||||
class AM : public Demodulator {
|
||||
public:
|
||||
AM() {}
|
||||
|
||||
|
||||
AM(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth, EventHandler<dsp::stream<dsp::stereo_t>*> outputChangeHandler, double audioSR) {
|
||||
init(name, config, input, bandwidth, outputChangeHandler, audioSR);
|
||||
}
|
||||
@ -52,23 +52,23 @@ namespace demod {
|
||||
|
||||
// ============= INFO =============
|
||||
|
||||
const char* getName() { return "AM"; }
|
||||
double getIFSampleRate() { return 15000.0; }
|
||||
double getAFSampleRate() { return getIFSampleRate(); }
|
||||
double getDefaultBandwidth() { return 10000.0; }
|
||||
double getMinBandwidth() { return 1000.0; }
|
||||
double getMaxBandwidth() { return getIFSampleRate(); }
|
||||
bool getBandwidthLocked() { return false; }
|
||||
double getMaxAFBandwidth() { return getIFSampleRate() / 2.0; }
|
||||
double getDefaultSnapInterval() { return 1000.0; }
|
||||
int getVFOReference() { return ImGui::WaterfallVFO::REF_CENTER; }
|
||||
bool getDeempAllowed() { return false; }
|
||||
bool getPostProcEnabled() { return true; }
|
||||
int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; }
|
||||
const char* getName() { return "AM"; }
|
||||
double getIFSampleRate() { return 15000.0; }
|
||||
double getAFSampleRate() { return getIFSampleRate(); }
|
||||
double getDefaultBandwidth() { return 10000.0; }
|
||||
double getMinBandwidth() { return 1000.0; }
|
||||
double getMaxBandwidth() { return getIFSampleRate(); }
|
||||
bool getBandwidthLocked() { return false; }
|
||||
double getMaxAFBandwidth() { return getIFSampleRate() / 2.0; }
|
||||
double getDefaultSnapInterval() { return 1000.0; }
|
||||
int getVFOReference() { return ImGui::WaterfallVFO::REF_CENTER; }
|
||||
bool getDeempAllowed() { return false; }
|
||||
bool getPostProcEnabled() { return true; }
|
||||
int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; }
|
||||
double getAFBandwidth(double bandwidth) { return bandwidth / 2.0; }
|
||||
bool getDynamicAFBandwidth() { return true; }
|
||||
bool getFMIFNRAllowed() { return false; }
|
||||
bool getNBAllowed() { return false; }
|
||||
bool getDynamicAFBandwidth() { return true; }
|
||||
bool getFMIFNRAllowed() { return false; }
|
||||
bool getNBAllowed() { return false; }
|
||||
dsp::stream<dsp::stereo_t>* getOutput() { return &m2s.out; }
|
||||
|
||||
private:
|
||||
|
@ -7,7 +7,7 @@ namespace demod {
|
||||
class CW : public Demodulator {
|
||||
public:
|
||||
CW() {}
|
||||
|
||||
|
||||
CW(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth, EventHandler<dsp::stream<dsp::stereo_t>*> outputChangeHandler, double audioSR) {
|
||||
init(name, config, input, bandwidth, outputChangeHandler, audioSR);
|
||||
}
|
||||
@ -53,23 +53,23 @@ namespace demod {
|
||||
|
||||
// ============= INFO =============
|
||||
|
||||
const char* getName() { return "CW"; }
|
||||
double getIFSampleRate() { return 3000.0; }
|
||||
double getAFSampleRate() { return getIFSampleRate(); }
|
||||
double getDefaultBandwidth() { return 500.0; }
|
||||
double getMinBandwidth() { return 50.0; }
|
||||
double getMaxBandwidth() { return 500.0; }
|
||||
bool getBandwidthLocked() { return false; }
|
||||
double getMaxAFBandwidth() { return getIFSampleRate() / 2.0; }
|
||||
double getDefaultSnapInterval() { return 10.0; }
|
||||
int getVFOReference() { return ImGui::WaterfallVFO::REF_CENTER; }
|
||||
bool getDeempAllowed() { return false; }
|
||||
bool getPostProcEnabled() { return true; }
|
||||
int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; }
|
||||
const char* getName() { return "CW"; }
|
||||
double getIFSampleRate() { return 3000.0; }
|
||||
double getAFSampleRate() { return getIFSampleRate(); }
|
||||
double getDefaultBandwidth() { return 500.0; }
|
||||
double getMinBandwidth() { return 50.0; }
|
||||
double getMaxBandwidth() { return 500.0; }
|
||||
bool getBandwidthLocked() { return false; }
|
||||
double getMaxAFBandwidth() { return getIFSampleRate() / 2.0; }
|
||||
double getDefaultSnapInterval() { return 10.0; }
|
||||
int getVFOReference() { return ImGui::WaterfallVFO::REF_CENTER; }
|
||||
bool getDeempAllowed() { return false; }
|
||||
bool getPostProcEnabled() { return true; }
|
||||
int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; }
|
||||
double getAFBandwidth(double bandwidth) { return (bandwidth / 2.0) + 1000.0; }
|
||||
bool getDynamicAFBandwidth() { return true; }
|
||||
bool getFMIFNRAllowed() { return false; }
|
||||
bool getNBAllowed() { return false; }
|
||||
bool getDynamicAFBandwidth() { return true; }
|
||||
bool getFMIFNRAllowed() { return false; }
|
||||
bool getNBAllowed() { return false; }
|
||||
dsp::stream<dsp::stereo_t>* getOutput() { return &m2s.out; }
|
||||
|
||||
private:
|
||||
|
@ -7,7 +7,7 @@ namespace demod {
|
||||
class DSB : public Demodulator {
|
||||
public:
|
||||
DSB() {}
|
||||
|
||||
|
||||
DSB(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth, EventHandler<dsp::stream<dsp::stereo_t>*> outputChangeHandler, double audioSR) {
|
||||
init(name, config, input, bandwidth, outputChangeHandler, audioSR);
|
||||
}
|
||||
@ -54,23 +54,23 @@ namespace demod {
|
||||
|
||||
// ============= INFO =============
|
||||
|
||||
const char* getName() { return "DSB"; }
|
||||
double getIFSampleRate() { return 24000.0; }
|
||||
double getAFSampleRate() { return getIFSampleRate(); }
|
||||
double getDefaultBandwidth() { return 4600.0; }
|
||||
double getMinBandwidth() { return 1000.0; }
|
||||
double getMaxBandwidth() { return getIFSampleRate() / 2.0; }
|
||||
bool getBandwidthLocked() { return false; }
|
||||
double getMaxAFBandwidth() { return getIFSampleRate() / 2.0; }
|
||||
double getDefaultSnapInterval() { return 100.0; }
|
||||
int getVFOReference() { return ImGui::WaterfallVFO::REF_CENTER; }
|
||||
bool getDeempAllowed() { return false; }
|
||||
bool getPostProcEnabled() { return true; }
|
||||
int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; }
|
||||
const char* getName() { return "DSB"; }
|
||||
double getIFSampleRate() { return 24000.0; }
|
||||
double getAFSampleRate() { return getIFSampleRate(); }
|
||||
double getDefaultBandwidth() { return 4600.0; }
|
||||
double getMinBandwidth() { return 1000.0; }
|
||||
double getMaxBandwidth() { return getIFSampleRate() / 2.0; }
|
||||
bool getBandwidthLocked() { return false; }
|
||||
double getMaxAFBandwidth() { return getIFSampleRate() / 2.0; }
|
||||
double getDefaultSnapInterval() { return 100.0; }
|
||||
int getVFOReference() { return ImGui::WaterfallVFO::REF_CENTER; }
|
||||
bool getDeempAllowed() { return false; }
|
||||
bool getPostProcEnabled() { return true; }
|
||||
int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; }
|
||||
double getAFBandwidth(double bandwidth) { return bandwidth / 2.0; }
|
||||
bool getDynamicAFBandwidth() { return true; }
|
||||
bool getFMIFNRAllowed() { return false; }
|
||||
bool getNBAllowed() { return true; }
|
||||
bool getDynamicAFBandwidth() { return true; }
|
||||
bool getFMIFNRAllowed() { return false; }
|
||||
bool getNBAllowed() { return true; }
|
||||
dsp::stream<dsp::stereo_t>* getOutput() { return &m2s.out; }
|
||||
|
||||
private:
|
||||
|
@ -7,7 +7,7 @@ namespace demod {
|
||||
class LSB : public Demodulator {
|
||||
public:
|
||||
LSB() {}
|
||||
|
||||
|
||||
LSB(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth, EventHandler<dsp::stream<dsp::stereo_t>*> outputChangeHandler, double audioSR) {
|
||||
init(name, config, input, bandwidth, outputChangeHandler, audioSR);
|
||||
}
|
||||
@ -54,23 +54,23 @@ namespace demod {
|
||||
|
||||
// ============= INFO =============
|
||||
|
||||
const char* getName() { return "LSB"; }
|
||||
double getIFSampleRate() { return 24000.0; }
|
||||
double getAFSampleRate() { return getIFSampleRate(); }
|
||||
double getDefaultBandwidth() { return 2800.0; }
|
||||
double getMinBandwidth() { return 500.0; }
|
||||
double getMaxBandwidth() { return getIFSampleRate() / 2.0; }
|
||||
bool getBandwidthLocked() { return false; }
|
||||
double getMaxAFBandwidth() { return getIFSampleRate() / 2.0; }
|
||||
double getDefaultSnapInterval() { return 100.0; }
|
||||
int getVFOReference() { return ImGui::WaterfallVFO::REF_UPPER; }
|
||||
bool getDeempAllowed() { return false; }
|
||||
bool getPostProcEnabled() { return true; }
|
||||
int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; }
|
||||
const char* getName() { return "LSB"; }
|
||||
double getIFSampleRate() { return 24000.0; }
|
||||
double getAFSampleRate() { return getIFSampleRate(); }
|
||||
double getDefaultBandwidth() { return 2800.0; }
|
||||
double getMinBandwidth() { return 500.0; }
|
||||
double getMaxBandwidth() { return getIFSampleRate() / 2.0; }
|
||||
bool getBandwidthLocked() { return false; }
|
||||
double getMaxAFBandwidth() { return getIFSampleRate() / 2.0; }
|
||||
double getDefaultSnapInterval() { return 100.0; }
|
||||
int getVFOReference() { return ImGui::WaterfallVFO::REF_UPPER; }
|
||||
bool getDeempAllowed() { return false; }
|
||||
bool getPostProcEnabled() { return true; }
|
||||
int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; }
|
||||
double getAFBandwidth(double bandwidth) { return bandwidth; }
|
||||
bool getDynamicAFBandwidth() { return true; }
|
||||
bool getFMIFNRAllowed() { return false; }
|
||||
bool getNBAllowed() { return true; }
|
||||
bool getDynamicAFBandwidth() { return true; }
|
||||
bool getFMIFNRAllowed() { return false; }
|
||||
bool getNBAllowed() { return true; }
|
||||
dsp::stream<dsp::stereo_t>* getOutput() { return &m2s.out; }
|
||||
|
||||
private:
|
||||
|
@ -7,7 +7,7 @@ namespace demod {
|
||||
class NFM : public Demodulator {
|
||||
public:
|
||||
NFM() {}
|
||||
|
||||
|
||||
NFM(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth, EventHandler<dsp::stream<dsp::stereo_t>*> outputChangeHandler, double audioSR) {
|
||||
init(name, config, input, bandwidth, outputChangeHandler, audioSR);
|
||||
}
|
||||
@ -46,23 +46,23 @@ namespace demod {
|
||||
|
||||
// ============= INFO =============
|
||||
|
||||
const char* getName() { return "FM"; }
|
||||
double getIFSampleRate() { return 50000.0; }
|
||||
double getAFSampleRate() { return getIFSampleRate(); }
|
||||
double getDefaultBandwidth() { return 12500.0; }
|
||||
double getMinBandwidth() { return 1000.0; }
|
||||
double getMaxBandwidth() { return getIFSampleRate(); }
|
||||
bool getBandwidthLocked() { return false; }
|
||||
double getMaxAFBandwidth() { return getIFSampleRate() / 2.0; }
|
||||
double getDefaultSnapInterval() { return 2500.0; }
|
||||
int getVFOReference() { return ImGui::WaterfallVFO::REF_CENTER; }
|
||||
bool getDeempAllowed() { return true; }
|
||||
bool getPostProcEnabled() { return true; }
|
||||
int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; }
|
||||
const char* getName() { return "FM"; }
|
||||
double getIFSampleRate() { return 50000.0; }
|
||||
double getAFSampleRate() { return getIFSampleRate(); }
|
||||
double getDefaultBandwidth() { return 12500.0; }
|
||||
double getMinBandwidth() { return 1000.0; }
|
||||
double getMaxBandwidth() { return getIFSampleRate(); }
|
||||
bool getBandwidthLocked() { return false; }
|
||||
double getMaxAFBandwidth() { return getIFSampleRate() / 2.0; }
|
||||
double getDefaultSnapInterval() { return 2500.0; }
|
||||
int getVFOReference() { return ImGui::WaterfallVFO::REF_CENTER; }
|
||||
bool getDeempAllowed() { return true; }
|
||||
bool getPostProcEnabled() { return true; }
|
||||
int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; }
|
||||
double getAFBandwidth(double bandwidth) { return bandwidth / 2.0; }
|
||||
bool getDynamicAFBandwidth() { return true; }
|
||||
bool getFMIFNRAllowed() { return true; }
|
||||
bool getNBAllowed() { return false; }
|
||||
bool getDynamicAFBandwidth() { return true; }
|
||||
bool getFMIFNRAllowed() { return true; }
|
||||
bool getNBAllowed() { return false; }
|
||||
dsp::stream<dsp::stereo_t>* getOutput() { return &demod.out; }
|
||||
|
||||
private:
|
||||
|
@ -7,7 +7,7 @@ namespace demod {
|
||||
class RAW : public Demodulator {
|
||||
public:
|
||||
RAW() {}
|
||||
|
||||
|
||||
RAW(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth, EventHandler<dsp::stream<dsp::stereo_t>*> outputChangeHandler, double audioSR) {
|
||||
init(name, config, input, bandwidth, outputChangeHandler, audioSR);
|
||||
}
|
||||
@ -47,23 +47,23 @@ namespace demod {
|
||||
|
||||
// ============= INFO =============
|
||||
|
||||
const char* getName() { return "RAW"; }
|
||||
double getIFSampleRate() { return audioSampleRate; }
|
||||
double getAFSampleRate() { return audioSampleRate; }
|
||||
double getDefaultBandwidth() { return audioSampleRate; }
|
||||
double getMinBandwidth() { return audioSampleRate; }
|
||||
double getMaxBandwidth() { return audioSampleRate; }
|
||||
bool getBandwidthLocked() { return true; }
|
||||
double getMaxAFBandwidth() { return audioSampleRate; }
|
||||
double getDefaultSnapInterval() { return 2500.0; }
|
||||
int getVFOReference() { return ImGui::WaterfallVFO::REF_CENTER; }
|
||||
bool getDeempAllowed() { return false; }
|
||||
bool getPostProcEnabled() { return false; }
|
||||
int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; }
|
||||
const char* getName() { return "RAW"; }
|
||||
double getIFSampleRate() { return audioSampleRate; }
|
||||
double getAFSampleRate() { return audioSampleRate; }
|
||||
double getDefaultBandwidth() { return audioSampleRate; }
|
||||
double getMinBandwidth() { return audioSampleRate; }
|
||||
double getMaxBandwidth() { return audioSampleRate; }
|
||||
bool getBandwidthLocked() { return true; }
|
||||
double getMaxAFBandwidth() { return audioSampleRate; }
|
||||
double getDefaultSnapInterval() { return 2500.0; }
|
||||
int getVFOReference() { return ImGui::WaterfallVFO::REF_CENTER; }
|
||||
bool getDeempAllowed() { return false; }
|
||||
bool getPostProcEnabled() { return false; }
|
||||
int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; }
|
||||
double getAFBandwidth(double bandwidth) { return bandwidth; }
|
||||
bool getDynamicAFBandwidth() { return false; }
|
||||
bool getFMIFNRAllowed() { return false; }
|
||||
bool getNBAllowed() { return true; }
|
||||
bool getDynamicAFBandwidth() { return false; }
|
||||
bool getFMIFNRAllowed() { return false; }
|
||||
bool getNBAllowed() { return true; }
|
||||
dsp::stream<dsp::stereo_t>* getOutput() { return &c2s.out; }
|
||||
|
||||
private:
|
||||
|
@ -7,7 +7,7 @@ namespace demod {
|
||||
class USB : public Demodulator {
|
||||
public:
|
||||
USB() {}
|
||||
|
||||
|
||||
USB(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth, EventHandler<dsp::stream<dsp::stereo_t>*> outputChangeHandler, double audioSR) {
|
||||
init(name, config, input, bandwidth, outputChangeHandler, audioSR);
|
||||
}
|
||||
@ -54,23 +54,23 @@ namespace demod {
|
||||
|
||||
// ============= INFO =============
|
||||
|
||||
const char* getName() { return "USB"; }
|
||||
double getIFSampleRate() { return 24000.0; }
|
||||
double getAFSampleRate() { return getIFSampleRate(); }
|
||||
double getDefaultBandwidth() { return 2800.0; }
|
||||
double getMinBandwidth() { return 500.0; }
|
||||
double getMaxBandwidth() { return getIFSampleRate() / 2.0; }
|
||||
bool getBandwidthLocked() { return false; }
|
||||
double getMaxAFBandwidth() { return getIFSampleRate() / 2.0; }
|
||||
double getDefaultSnapInterval() { return 100.0; }
|
||||
int getVFOReference() { return ImGui::WaterfallVFO::REF_LOWER; }
|
||||
bool getDeempAllowed() { return false; }
|
||||
bool getPostProcEnabled() { return true; }
|
||||
int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; }
|
||||
const char* getName() { return "USB"; }
|
||||
double getIFSampleRate() { return 24000.0; }
|
||||
double getAFSampleRate() { return getIFSampleRate(); }
|
||||
double getDefaultBandwidth() { return 2800.0; }
|
||||
double getMinBandwidth() { return 500.0; }
|
||||
double getMaxBandwidth() { return getIFSampleRate() / 2.0; }
|
||||
bool getBandwidthLocked() { return false; }
|
||||
double getMaxAFBandwidth() { return getIFSampleRate() / 2.0; }
|
||||
double getDefaultSnapInterval() { return 100.0; }
|
||||
int getVFOReference() { return ImGui::WaterfallVFO::REF_LOWER; }
|
||||
bool getDeempAllowed() { return false; }
|
||||
bool getPostProcEnabled() { return true; }
|
||||
int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; }
|
||||
double getAFBandwidth(double bandwidth) { return bandwidth; }
|
||||
bool getDynamicAFBandwidth() { return true; }
|
||||
bool getFMIFNRAllowed() { return false; }
|
||||
bool getNBAllowed() { return true; }
|
||||
bool getDynamicAFBandwidth() { return true; }
|
||||
bool getFMIFNRAllowed() { return false; }
|
||||
bool getNBAllowed() { return true; }
|
||||
dsp::stream<dsp::stereo_t>* getOutput() { return &m2s.out; }
|
||||
|
||||
private:
|
||||
|
@ -7,7 +7,7 @@ namespace demod {
|
||||
class WFM : public Demodulator {
|
||||
public:
|
||||
WFM() {}
|
||||
|
||||
|
||||
WFM(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth, EventHandler<dsp::stream<dsp::stereo_t>*> outputChangeHandler, double audioSR) {
|
||||
init(name, config, input, bandwidth, outputChangeHandler, audioSR);
|
||||
}
|
||||
@ -23,7 +23,7 @@ namespace demod {
|
||||
|
||||
// Load config
|
||||
_config->acquire();
|
||||
bool modified =false;
|
||||
bool modified = false;
|
||||
if (!config->conf[name].contains(getName())) {
|
||||
config->conf[name][getName()]["stereo"] = false;
|
||||
modified = true;
|
||||
@ -70,23 +70,23 @@ namespace demod {
|
||||
|
||||
// ============= INFO =============
|
||||
|
||||
const char* getName() { return "WFM"; }
|
||||
double getIFSampleRate() { return 250000.0; }
|
||||
double getAFSampleRate() { return getIFSampleRate(); }
|
||||
double getDefaultBandwidth() { return 150000.0; }
|
||||
double getMinBandwidth() { return 50000.0; }
|
||||
double getMaxBandwidth() { return getIFSampleRate(); }
|
||||
bool getBandwidthLocked() { return false; }
|
||||
double getMaxAFBandwidth() { return 16000.0; }
|
||||
double getDefaultSnapInterval() { return 100000.0; }
|
||||
int getVFOReference() { return ImGui::WaterfallVFO::REF_CENTER; }
|
||||
bool getDeempAllowed() { return true; }
|
||||
bool getPostProcEnabled() { return true; }
|
||||
int getDefaultDeemphasisMode() { return DEEMP_MODE_50US; }
|
||||
const char* getName() { return "WFM"; }
|
||||
double getIFSampleRate() { return 250000.0; }
|
||||
double getAFSampleRate() { return getIFSampleRate(); }
|
||||
double getDefaultBandwidth() { return 150000.0; }
|
||||
double getMinBandwidth() { return 50000.0; }
|
||||
double getMaxBandwidth() { return getIFSampleRate(); }
|
||||
bool getBandwidthLocked() { return false; }
|
||||
double getMaxAFBandwidth() { return 16000.0; }
|
||||
double getDefaultSnapInterval() { return 100000.0; }
|
||||
int getVFOReference() { return ImGui::WaterfallVFO::REF_CENTER; }
|
||||
bool getDeempAllowed() { return true; }
|
||||
bool getPostProcEnabled() { return true; }
|
||||
int getDefaultDeemphasisMode() { return DEEMP_MODE_50US; }
|
||||
double getAFBandwidth(double bandwidth) { return 16000.0; }
|
||||
bool getDynamicAFBandwidth() { return false; }
|
||||
bool getFMIFNRAllowed() { return true; }
|
||||
bool getNBAllowed() { return false; }
|
||||
bool getDynamicAFBandwidth() { return false; }
|
||||
bool getFMIFNRAllowed() { return true; }
|
||||
bool getNBAllowed() { return false; }
|
||||
dsp::stream<dsp::stereo_t>* getOutput() { return stereo ? demodStereo.out : &demod.out; }
|
||||
|
||||
// ============= DEDICATED FUNCTIONS =============
|
||||
@ -108,9 +108,9 @@ namespace demod {
|
||||
private:
|
||||
dsp::FMDemod demod;
|
||||
dsp::StereoFMDemod demodStereo;
|
||||
|
||||
|
||||
ConfigManager* _config = NULL;
|
||||
|
||||
|
||||
bool stereo = false;
|
||||
|
||||
std::string name;
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include "radio_module.h"
|
||||
#include <options.h>
|
||||
|
||||
SDRPP_MOD_INFO {
|
||||
SDRPP_MOD_INFO{
|
||||
/* Name: */ "radio",
|
||||
/* Description: */ "Analog radio decoder",
|
||||
/* Author: */ "Ryzerth",
|
||||
|
@ -14,12 +14,12 @@
|
||||
|
||||
ConfigManager config;
|
||||
|
||||
#define CONCAT(a, b) ((std::string(a) + b).c_str())
|
||||
#define CONCAT(a, b) ((std::string(a) + b).c_str())
|
||||
|
||||
std::map<DeemphasisMode, double> deempTaus = {
|
||||
{DEEMP_MODE_22US, 22e-6},
|
||||
{DEEMP_MODE_50US, 50e-6},
|
||||
{DEEMP_MODE_75US, 75e-6}
|
||||
{ DEEMP_MODE_22US, 22e-6 },
|
||||
{ DEEMP_MODE_50US, 50e-6 },
|
||||
{ DEEMP_MODE_75US, 75e-6 }
|
||||
};
|
||||
|
||||
class RadioModule : public ModuleManager::Instance {
|
||||
@ -91,11 +91,11 @@ public:
|
||||
config.conf[name][demod->getName()]["squelchEnabled"] = false;
|
||||
}
|
||||
bw = std::clamp<double>(bw, demod->getMinBandwidth(), demod->getMaxBandwidth());
|
||||
|
||||
|
||||
// Initialize
|
||||
demod->init(name, &config, ifChain.getOutput(), bw, _demodOutputChangeHandler, stream.getSampleRate());
|
||||
}
|
||||
|
||||
|
||||
// Initialize audio DSP chain
|
||||
afChainOutputChanged.ctx = this;
|
||||
afChainOutputChanged.handler = afChainOutputChangeHandler;
|
||||
@ -194,7 +194,7 @@ private:
|
||||
ImGui::BeginGroup();
|
||||
|
||||
ImGui::Columns(4, CONCAT("RadioModeColumns##_", _this->name), false);
|
||||
if (ImGui::RadioButton(CONCAT("NFM##_", _this->name), _this->selectedDemodID == 0) && _this->selectedDemodID != 0) {
|
||||
if (ImGui::RadioButton(CONCAT("NFM##_", _this->name), _this->selectedDemodID == 0) && _this->selectedDemodID != 0) {
|
||||
_this->selectDemodByID(RADIO_DEMOD_NFM);
|
||||
}
|
||||
if (ImGui::RadioButton(CONCAT("WFM##_", _this->name), _this->selectedDemodID == 1) && _this->selectedDemodID != 1) {
|
||||
@ -204,7 +204,7 @@ private:
|
||||
if (ImGui::RadioButton(CONCAT("AM##_", _this->name), _this->selectedDemodID == 2) && _this->selectedDemodID != 2) {
|
||||
_this->selectDemodByID(RADIO_DEMOD_AM);
|
||||
}
|
||||
if (ImGui::RadioButton(CONCAT("DSB##_", _this->name), _this->selectedDemodID == 3) && _this->selectedDemodID != 3) {
|
||||
if (ImGui::RadioButton(CONCAT("DSB##_", _this->name), _this->selectedDemodID == 3) && _this->selectedDemodID != 3) {
|
||||
_this->selectDemodByID(RADIO_DEMOD_DSB);
|
||||
}
|
||||
ImGui::NextColumn();
|
||||
@ -279,7 +279,7 @@ private:
|
||||
}
|
||||
if (!_this->nbEnabled && _this->enabled) { style::endDisabled(); }
|
||||
}
|
||||
|
||||
|
||||
|
||||
// // Notch filter
|
||||
// if (ImGui::Checkbox("Notch##_radio_notch_ena_", &_this->notchEnabled)) {
|
||||
@ -484,7 +484,7 @@ private:
|
||||
|
||||
// Configure deemphasis sample rate
|
||||
deemp.block.setSampleRate(audioSampleRate);
|
||||
|
||||
|
||||
afChain.start();
|
||||
}
|
||||
|
||||
@ -626,7 +626,7 @@ private:
|
||||
// Success
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Handlers
|
||||
EventHandler<double> onUserChangedBandwidthHandler;
|
||||
EventHandler<float> srChangeHandler;
|
||||
@ -686,5 +686,4 @@ private:
|
||||
const double MAX_SQUELCH = 0.0;
|
||||
|
||||
bool enabled = true;
|
||||
|
||||
};
|
||||
|
@ -22,9 +22,9 @@
|
||||
#include <sat_decoder.h>
|
||||
#include <noaa_hrpt_decoder.h>
|
||||
|
||||
#define CONCAT(a, b) ((std::string(a) + b).c_str())
|
||||
#define CONCAT(a, b) ((std::string(a) + b).c_str())
|
||||
|
||||
SDRPP_MOD_INFO {
|
||||
SDRPP_MOD_INFO{
|
||||
/* Name: */ "weather_sat_decoder",
|
||||
/* Description: */ "Weather Satellite Decoder for SDR++",
|
||||
/* Author: */ "Ryzerth",
|
||||
@ -34,7 +34,7 @@ SDRPP_MOD_INFO {
|
||||
|
||||
std::string genFileName(std::string prefix, std::string suffix) {
|
||||
time_t now = time(0);
|
||||
tm *ltm = localtime(&now);
|
||||
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;
|
||||
@ -59,7 +59,7 @@ public:
|
||||
}
|
||||
|
||||
selectDecoder(decoderNames[0], false);
|
||||
|
||||
|
||||
gui::menu.registerEntry(name, menuHandler, this, this);
|
||||
}
|
||||
|
||||
@ -120,7 +120,7 @@ private:
|
||||
|
||||
std::string name;
|
||||
bool enabled = true;
|
||||
|
||||
|
||||
VFOManager::VFO* vfo;
|
||||
|
||||
std::map<std::string, SatDecoder*> decoders;
|
||||
@ -129,7 +129,6 @@ private:
|
||||
int decoderId = 0;
|
||||
|
||||
SatDecoder* decoder;
|
||||
|
||||
};
|
||||
|
||||
MOD_EXPORT void _INIT_() {
|
||||
|
@ -9,8 +9,8 @@
|
||||
#include <gui/widgets/line_push_image.h>
|
||||
#include <gui/gui.h>
|
||||
|
||||
#define NOAA_HRPT_VFO_SR 3000000.0f
|
||||
#define NOAA_HRPT_VFO_BW 2000000.0f
|
||||
#define NOAA_HRPT_VFO_SR 3000000.0f
|
||||
#define NOAA_HRPT_VFO_BW 2000000.0f
|
||||
|
||||
class NOAAHRPTDecoder : public SatDecoder {
|
||||
public:
|
||||
@ -19,15 +19,15 @@ public:
|
||||
_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);
|
||||
|
||||
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);
|
||||
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);
|
||||
@ -125,7 +125,7 @@ public:
|
||||
|
||||
compositeThread = std::thread(&NOAAHRPTDecoder::avhrrCompositeWorker, this);
|
||||
};
|
||||
|
||||
|
||||
void stop() {
|
||||
compositeIn1.stopReader();
|
||||
compositeIn1.stopWriter();
|
||||
@ -187,7 +187,7 @@ public:
|
||||
compositeIn2.clearReadStop();
|
||||
compositeIn2.clearWriteStop();
|
||||
};
|
||||
|
||||
|
||||
void setVFO(VFOManager::VFO* vfo) {
|
||||
_vfo = vfo;
|
||||
demod.setInput(_vfo->output);
|
||||
@ -196,7 +196,7 @@ public:
|
||||
virtual bool canRecord() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// bool startRecording(std::string recPath) {
|
||||
|
||||
// };
|
||||
@ -208,7 +208,7 @@ public:
|
||||
// bool isRecording() {
|
||||
|
||||
// };
|
||||
|
||||
|
||||
void drawMenu(float menuWidth) {
|
||||
ImGui::SetNextItemWidth(menuWidth);
|
||||
symDiag.draw();
|
||||
@ -285,7 +285,7 @@ public:
|
||||
|
||||
ImGui::Checkbox("Show Image", &showWindow);
|
||||
};
|
||||
|
||||
|
||||
private:
|
||||
// AVHRR Data Handlers
|
||||
void avhrrCompositeWorker() {
|
||||
@ -294,16 +294,16 @@ private:
|
||||
while (true) {
|
||||
if (compositeIn1.read() < 0) { return; }
|
||||
if (compositeIn2.read() < 0) { return; }
|
||||
|
||||
|
||||
uint8_t* buf = avhrrRGBImage.acquireNextLine();
|
||||
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;
|
||||
buf[(i * 4)] = rg;
|
||||
buf[(i * 4) + 1] = rg;
|
||||
buf[(i * 4) + 2] = b;
|
||||
buf[(i * 4) + 3] = 255;
|
||||
}
|
||||
avhrrRGBImage.releaseNextLine();
|
||||
|
||||
@ -318,10 +318,10 @@ private:
|
||||
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;
|
||||
buf[(i * 4)] = val;
|
||||
buf[(i * 4) + 1] = val;
|
||||
buf[(i * 4) + 2] = val;
|
||||
buf[(i * 4) + 3] = 255;
|
||||
}
|
||||
_this->avhrr1Image.releaseNextLine();
|
||||
|
||||
@ -335,10 +335,10 @@ private:
|
||||
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;
|
||||
buf[(i * 4)] = val;
|
||||
buf[(i * 4) + 1] = val;
|
||||
buf[(i * 4) + 2] = val;
|
||||
buf[(i * 4) + 3] = 255;
|
||||
}
|
||||
_this->avhrr2Image.releaseNextLine();
|
||||
|
||||
@ -352,10 +352,10 @@ private:
|
||||
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;
|
||||
buf[(i * 4)] = val;
|
||||
buf[(i * 4) + 1] = val;
|
||||
buf[(i * 4) + 2] = val;
|
||||
buf[(i * 4) + 3] = 255;
|
||||
}
|
||||
_this->avhrr3Image.releaseNextLine();
|
||||
}
|
||||
@ -366,10 +366,10 @@ private:
|
||||
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;
|
||||
buf[(i * 4)] = val;
|
||||
buf[(i * 4) + 1] = val;
|
||||
buf[(i * 4) + 2] = val;
|
||||
buf[(i * 4) + 3] = 255;
|
||||
}
|
||||
_this->avhrr4Image.releaseNextLine();
|
||||
}
|
||||
@ -380,10 +380,10 @@ private:
|
||||
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;
|
||||
buf[(i * 4)] = val;
|
||||
buf[(i * 4) + 1] = val;
|
||||
buf[(i * 4) + 2] = val;
|
||||
buf[(i * 4) + 3] = 255;
|
||||
}
|
||||
_this->avhrr5Image.releaseNextLine();
|
||||
}
|
||||
@ -391,102 +391,82 @@ private:
|
||||
// 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) {
|
||||
@ -568,5 +548,4 @@ private:
|
||||
std::thread compositeThread;
|
||||
|
||||
bool showWindow = false;
|
||||
|
||||
};
|
@ -10,7 +10,7 @@ public:
|
||||
virtual void setVFO(VFOManager::VFO* vfo) = 0;
|
||||
virtual bool canRecord() = 0;
|
||||
virtual bool startRecording(std::string recPath) { return false; };
|
||||
virtual void stopRecording() { };
|
||||
virtual void stopRecording(){};
|
||||
virtual bool isRecording() { return false; };
|
||||
virtual void drawMenu(float menuWidth) = 0;
|
||||
};
|
Reference in New Issue
Block a user