Add RTTY7N1 support to C lib

pull/21/head
Mark Jessop 2020-07-15 18:14:32 +09:30
rodzic 9de63dcd67
commit f736c4e8f0
5 zmienionych plików z 122 dodań i 18 usunięć

Wyświetl plik

@ -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 */
}

Wyświetl plik

@ -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

Wyświetl plik

@ -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;
}

Wyświetl plik

@ -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

Wyświetl plik

@ -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
}
}