kopia lustrzana https://github.com/projecthorus/horusdemodlib
Add RTTY7N1 support to C lib
rodzic
9de63dcd67
commit
f736c4e8f0
|
@ -64,21 +64,17 @@ RTTY Unique word = $ characters, repeated at least 2 times.
|
|||
$ = (0)010 0100
|
||||
Reversed = 0010010(0)
|
||||
*/
|
||||
|
||||
int8_t uw_horus_rtty_7N1[] = {
|
||||
0,0,1,0,0,1,0,1,0,
|
||||
0,0,1,0,0,1,0,1,0,
|
||||
};
|
||||
int8_t uw_horus_rtty_7N2[] = {
|
||||
0,0,1,0,0,1,0,1,1,0,
|
||||
0,0,1,0,0,1,0,1,1,0,
|
||||
// 0,0,1,0,0,1,0,1,1,0,
|
||||
// 0,0,1,0,0,1,0,1,1,0,
|
||||
// 0,0,1,0,0,1,0,1,1,0
|
||||
};
|
||||
|
||||
int8_t uw_horus_rtty_8N2[] = {
|
||||
0,0,1,0,0,1,0,0,1,1,0,
|
||||
0,0,1,0,0,1,0,0,1,1,0,
|
||||
// 0,0,1,0,0,1,0,1,1,0,
|
||||
// 0,0,1,0,0,1,0,1,1,0,
|
||||
// 0,0,1,0,0,1,0,1,1,0
|
||||
};
|
||||
|
||||
/* Unique word for Horus Binary V1 */
|
||||
|
@ -101,28 +97,73 @@ int8_t uw_horus_binary_v2[] = {
|
|||
|
||||
|
||||
struct horus *horus_open (int mode) {
|
||||
assert((mode == HORUS_MODE_RTTY_7N2) || (mode == HORUS_MODE_BINARY_V1) || (mode == HORUS_MODE_BINARY_V2_256BIT) || (mode == HORUS_MODE_BINARY_V2_128BIT));
|
||||
assert((mode == HORUS_MODE_RTTY_7N1) || (mode == HORUS_MODE_RTTY_7N2) || (mode == HORUS_MODE_RTTY_8N2) || (mode == HORUS_MODE_BINARY_V1) || (mode == HORUS_MODE_BINARY_V2_256BIT) || (mode == HORUS_MODE_BINARY_V2_128BIT));
|
||||
|
||||
if (mode == HORUS_MODE_RTTY_7N1){
|
||||
// RTTY Mode defaults - 100 baud, no assumptions about tone spacing.
|
||||
return horus_open_advanced(HORUS_MODE_RTTY_7N1, HORUS_RTTY_DEFAULT_BAUD, -1);
|
||||
}
|
||||
if (mode == HORUS_MODE_RTTY_7N2){
|
||||
// RTTY Mode defaults - 100 baud, no assumptions about tone spacing.
|
||||
return horus_open_advanced(HORUS_MODE_RTTY_7N2, HORUS_RTTY_DEFAULT_BAUD, -1);
|
||||
} else {
|
||||
// Placeholder until we have more definition of the new modes.
|
||||
}
|
||||
if (mode == HORUS_MODE_RTTY_8N2){
|
||||
// RTTY Mode defaults - 100 baud, no assumptions about tone spacing.
|
||||
return horus_open_advanced(HORUS_MODE_RTTY_8N2, HORUS_RTTY_DEFAULT_BAUD, -1);
|
||||
}
|
||||
if (mode == HORUS_MODE_BINARY_V1){
|
||||
// Legacy Horus Binary Mode defaults - 100 baud, Disable mask estimation.
|
||||
return horus_open_advanced(HORUS_MODE_BINARY_V1, HORUS_BINARY_V1_DEFAULT_BAUD, -1);
|
||||
}
|
||||
if (mode == HORUS_MODE_BINARY_V2_128BIT){
|
||||
// V2 Horus Binary Mode defaults - 100 baud, Disable mask estimation.
|
||||
return horus_open_advanced(HORUS_MODE_BINARY_V2_128BIT, HORUS_BINARY_V2_128BIT_DEFAULT_BAUD, -1);
|
||||
}
|
||||
if (mode == HORUS_MODE_BINARY_V2_256BIT){
|
||||
// V2 Horus Binary Mode defaults - 100 baud, Disable mask estimation.
|
||||
return horus_open_advanced(HORUS_MODE_BINARY_V2_256BIT, HORUS_BINARY_V2_256BIT_DEFAULT_BAUD, -1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct horus *horus_open_advanced (int mode, int Rs, int tx_tone_spacing) {
|
||||
int i, mask;
|
||||
assert((mode == HORUS_MODE_RTTY_7N2) || (mode == HORUS_MODE_RTTY_8N2) || (mode == HORUS_MODE_BINARY_V1) || (mode == HORUS_MODE_BINARY_V2_256BIT) || (mode == HORUS_MODE_BINARY_V2_128BIT));
|
||||
assert((mode == HORUS_MODE_RTTY_7N1) || (mode == HORUS_MODE_RTTY_7N2) || (mode == HORUS_MODE_RTTY_8N2) || (mode == HORUS_MODE_BINARY_V1) || (mode == HORUS_MODE_BINARY_V2_256BIT) || (mode == HORUS_MODE_BINARY_V2_128BIT));
|
||||
|
||||
struct horus *hstates = (struct horus *)malloc(sizeof(struct horus));
|
||||
assert(hstates != NULL);
|
||||
|
||||
hstates->Fs = 48000; hstates->Rs = Rs; hstates->verbose = 0; hstates->mode = mode;
|
||||
|
||||
if (mode == HORUS_MODE_RTTY_7N1) {
|
||||
// Parameter setup for RTTY 7N2 Reception
|
||||
|
||||
hstates->mFSK = 2;
|
||||
hstates->max_packet_len = HORUS_RTTY_7N1_NUM_BITS;
|
||||
|
||||
// If baud rate not provided, use default
|
||||
if (hstates->Rs == -1){
|
||||
hstates->Rs = HORUS_RTTY_DEFAULT_BAUD;
|
||||
}
|
||||
|
||||
if (tx_tone_spacing == -1){
|
||||
// No tone spacing provided. Use dummy value to keep fsk modem happy, and disable mask estimation.
|
||||
tx_tone_spacing = 2*hstates->Rs;
|
||||
mask = 0;
|
||||
} else {
|
||||
mask = 1;
|
||||
}
|
||||
|
||||
/* map UW to make it easier to search for */
|
||||
|
||||
for (i=0; i<sizeof(uw_horus_rtty_7N1); i++) {
|
||||
hstates->uw[i] = 2*uw_horus_rtty_7N1[i] - 1;
|
||||
}
|
||||
hstates->uw_len = sizeof(uw_horus_rtty_7N1);
|
||||
hstates->uw_thresh = sizeof(uw_horus_rtty_7N1) - 2; /* allow a few bit errors in UW detection */
|
||||
hstates->rx_bits_len = hstates->max_packet_len;
|
||||
}
|
||||
|
||||
if (mode == HORUS_MODE_RTTY_7N2) {
|
||||
// Parameter setup for RTTY 7N2 Reception
|
||||
|
||||
|
@ -742,6 +783,19 @@ int horus_rx(struct horus *hstates, char ascii_out[], short demod_in[], int quad
|
|||
|
||||
/* OK we have found a unique word, and therefore the start of
|
||||
a packet, so lets try to extract valid packets */
|
||||
if (hstates->mode == HORUS_MODE_RTTY_7N1) {
|
||||
packet_detected = extract_horus_rtty(hstates, ascii_out, uw_loc, 7, 1);
|
||||
|
||||
if (packet_detected){
|
||||
// If we have found a packet, advance the bits enough that we don't detect the
|
||||
// same packet again, if it has more than 2x $$s.
|
||||
// NEED TO CHECK THIS DOESN'T CAUSE SEGFAULTS!
|
||||
for(i=0,j=100; i<100; i++,j++) {
|
||||
hstates->rx_bits[i] = hstates->rx_bits[j];
|
||||
hstates->soft_bits[i] = hstates->soft_bits[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hstates->mode == HORUS_MODE_RTTY_7N2) {
|
||||
packet_detected = extract_horus_rtty(hstates, ascii_out, uw_loc, 7, 2);
|
||||
|
@ -817,6 +871,9 @@ int horus_get_max_demod_in(struct horus *hstates) {
|
|||
|
||||
int horus_get_max_ascii_out_len(struct horus *hstates) {
|
||||
assert(hstates != NULL);
|
||||
if (hstates->mode == HORUS_MODE_RTTY_7N1) {
|
||||
return hstates->max_packet_len/9; /* 7 bit ASCII, plus 3 sync bits */
|
||||
}
|
||||
if (hstates->mode == HORUS_MODE_RTTY_7N2) {
|
||||
return hstates->max_packet_len/10; /* 7 bit ASCII, plus 3 sync bits */
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#define HORUS_MODE_BINARY_V1 0 // Legacy binary mode
|
||||
#define HORUS_MODE_BINARY_V2_256BIT 1 // New 256-bit LDPC-encoded mode
|
||||
#define HORUS_MODE_BINARY_V2_128BIT 2 // New 128-bit LDPC-encoded mode
|
||||
#define HORUS_MODE_RTTY_7N1 89 // RTTY Decoding - 7N1
|
||||
#define HORUS_MODE_RTTY_7N2 90 // RTTY Decoding - 7N2
|
||||
#define HORUS_MODE_RTTY_8N2 91 // RTTY Decoding - 8N2
|
||||
|
||||
|
@ -66,6 +67,7 @@
|
|||
|
||||
// Settings for RTTY Decoder
|
||||
#define HORUS_RTTY_MAX_CHARS 120
|
||||
#define HORUS_RTTY_7N1_NUM_BITS (HORUS_RTTY_MAX_CHARS*9)
|
||||
#define HORUS_RTTY_7N2_NUM_BITS (HORUS_RTTY_MAX_CHARS*10)
|
||||
#define HORUS_RTTY_8N2_NUM_BITS (HORUS_RTTY_MAX_CHARS*11)
|
||||
#define HORUS_RTTY_DEFAULT_BAUD 100
|
||||
|
|
|
@ -81,9 +81,12 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
switch(o) {
|
||||
case 'm':
|
||||
if ((strcmp(optarg, "RTTY") == 0) || (strcmp(optarg, "rtty") == 0)) {
|
||||
if ((strcmp(optarg, "RTTY") == 0) || (strcmp(optarg, "rtty") == 0) || (strcmp(optarg, "RTTY7N2") == 0) || (strcmp(optarg, "rtty7n2") == 0)) {
|
||||
mode = HORUS_MODE_RTTY_7N2;
|
||||
}
|
||||
if ((strcmp(optarg, "RTTY7N1") == 0) || (strcmp(optarg, "rtty7n1") == 0)) {
|
||||
mode = HORUS_MODE_RTTY_7N1;
|
||||
}
|
||||
if ((strcmp(optarg, "RTTY8N2") == 0) || (strcmp(optarg, "rtty8n2") == 0)) {
|
||||
mode = HORUS_MODE_RTTY_8N2;
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
1/ Unit test on a PC:
|
||||
|
||||
$ gcc horus_l2.c -o horus_l2 -Wall -DHORUS_L2_UNITTEST
|
||||
$ gcc horus_l2.c golay23.c H_128_384_23.c H_256_768_22.c mpdecode_core.c phi0.c -o horus_l2 -Wall -DHORUS_L2_UNITTEST
|
||||
$ ./horus_l2
|
||||
|
||||
test 0: 22 bytes of payload data BER: 0.00 errors: 0
|
||||
|
@ -49,7 +49,7 @@
|
|||
|
||||
5/ Unit testing interleaver:
|
||||
|
||||
$ gcc horus_l2.c golay23.c -o horus_l2 -Wall -DINTERLEAVER -DTEST_INTERLEAVER -DSCRAMBLER
|
||||
$ gcc horus_l2.c golay23.c H_128_384_23.c H_256_768_22.c mpdecode_core.c phi0.c -o horus_l2 -Wall -DINTERLEAVER -DTEST_INTERLEAVER -DSCRAMBLER
|
||||
|
||||
6/ Compile for use as decoder called by fsk_horus.m and fsk_horus_stream.m:
|
||||
|
||||
|
@ -559,6 +559,7 @@ void interleave(unsigned char *inout, int nbytes, int dir)
|
|||
#ifdef TEST_INTERLEAVER
|
||||
int main(void) {
|
||||
int nbytes = 43;
|
||||
//int nbytes = 63; // v2 large packet
|
||||
unsigned char inout[nbytes];
|
||||
unsigned char inter[nbytes];
|
||||
unsigned char incopy[nbytes];
|
||||
|
@ -747,6 +748,7 @@ int test_sending_bytes(int nbytes, float ber, int error_pattern) {
|
|||
/* unit test designed to run on a PC */
|
||||
|
||||
int main(void) {
|
||||
printf("Horus v1 length packets (22 bytes)\n");
|
||||
printf("test 0: BER: 0.00 ...........: %d\n", test_sending_bytes(22, 0.00, 0));
|
||||
printf("test 1: BER: 0.01 ...........: %d\n", test_sending_bytes(22, 0.01, 0));
|
||||
printf("test 2: BER: 0.05 ...........: %d\n", test_sending_bytes(22, 0.05, 0));
|
||||
|
@ -765,6 +767,46 @@ int main(void) {
|
|||
codeword after interleaving */
|
||||
|
||||
printf("test 5: 1 error every 12 bits: %d\n", test_sending_bytes(22, 0.00, 2));
|
||||
|
||||
printf("Horus v2 length packets (16 bytes)\n");
|
||||
printf("test 0: BER: 0.00 ...........: %d\n", test_sending_bytes(16, 0.00, 0));
|
||||
printf("test 1: BER: 0.01 ...........: %d\n", test_sending_bytes(16, 0.01, 0));
|
||||
printf("test 2: BER: 0.05 ...........: %d\n", test_sending_bytes(16, 0.05, 0));
|
||||
|
||||
/* we expect this always to fail, as chance of > 3 errors/codeword is high */
|
||||
|
||||
printf("test 3: BER: 0.10 ...........: %d\n", test_sending_bytes(16, 0.10, 0));
|
||||
|
||||
/* -DINTERLEAVER will make this puppy pass */
|
||||
|
||||
printf("test 4: 8 bit burst error....: %d\n", test_sending_bytes(16, 0.00, 1));
|
||||
|
||||
/* Insert 2 errors in every codeword, the maximum correction
|
||||
capability of a Golay (23,12) code. note this one will fail
|
||||
with -DINTERLEAVER, as we can't guarantee <= 3 errors per
|
||||
codeword after interleaving */
|
||||
|
||||
printf("test 5: 1 error every 12 bits: %d\n", test_sending_bytes(16, 0.00, 2));
|
||||
|
||||
printf("Horus v2 length packets (32 bytes)\n");
|
||||
printf("test 0: BER: 0.00 ...........: %d\n", test_sending_bytes(32, 0.00, 0));
|
||||
printf("test 1: BER: 0.01 ...........: %d\n", test_sending_bytes(32, 0.01, 0));
|
||||
printf("test 2: BER: 0.05 ...........: %d\n", test_sending_bytes(32, 0.05, 0));
|
||||
|
||||
/* we expect this always to fail, as chance of > 3 errors/codeword is high */
|
||||
|
||||
printf("test 3: BER: 0.10 ...........: %d\n", test_sending_bytes(32, 0.10, 0));
|
||||
|
||||
/* -DINTERLEAVER will make this puppy pass */
|
||||
|
||||
printf("test 4: 8 bit burst error....: %d\n", test_sending_bytes(32, 0.00, 1));
|
||||
|
||||
/* Insert 2 errors in every codeword, the maximum correction
|
||||
capability of a Golay (23,12) code. note this one will fail
|
||||
with -DINTERLEAVER, as we can't guarantee <= 3 errors per
|
||||
codeword after interleaving */
|
||||
|
||||
printf("test 5: 1 error every 12 bits: %d\n", test_sending_bytes(32, 0.00, 2));
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -82,17 +82,17 @@ MODE_TYPES = {
|
|||
'binary': {
|
||||
'id': 0,
|
||||
'nfsk': 4,
|
||||
'bits_per_frame': 360
|
||||
'bits_per_frame': 22*8 # UNCODED bits per frame.
|
||||
},
|
||||
'128bit': {
|
||||
'id': 1,
|
||||
'nfsk': 2, # Convert back to 4FSK once 4FSK SD/LLRs are working.
|
||||
'bits_per_frame': 384
|
||||
'bits_per_frame': 128
|
||||
},
|
||||
'256bit': {
|
||||
'id': 1,
|
||||
'nfsk': 2, # Convert back to 4FSK once 4FSK SD/LLRs are working.
|
||||
'bits_per_frame': 768
|
||||
'bits_per_frame': 256
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue