Add RTTY 8N2 support.

pull/2/head
Mark Jessop 2020-07-08 19:51:00 +09:30
rodzic 3fd53e9370
commit ddcb74f220
9 zmienionych plików z 92 dodań i 22 usunięć

Wyświetl plik

@ -62,10 +62,17 @@ enable_testing()
add_test(NAME test_horus_rtty_7n2 add_test(NAME test_horus_rtty_7n2
COMMAND sh -c "cd ${CMAKE_CURRENT_BINARY_DIR}/src; COMMAND sh -c "cd ${CMAKE_CURRENT_BINARY_DIR}/src;
sox ${CMAKE_CURRENT_SOURCE_DIR}/samples/rtty_7n2.wav -r 48000 -t raw - | sox ${CMAKE_CURRENT_SOURCE_DIR}/samples/rtty_7n2.wav -r 48000 -t raw - |
./horus_demod -m rtty -c - - | grep OK | wc -l" ./horus_demod -c -m rtty - - | grep OK | wc -l"
) )
set_tests_properties(test_horus_rtty_7n2 PROPERTIES PASS_REGULAR_EXPRESSION "6") set_tests_properties(test_horus_rtty_7n2 PROPERTIES PASS_REGULAR_EXPRESSION "6")
add_test(NAME test_horus_rtty_8n2
COMMAND sh -c "cd ${CMAKE_CURRENT_BINARY_DIR}/src;
sox ${CMAKE_CURRENT_SOURCE_DIR}/samples/rtty_8n2.wav -r 48000 -t raw - |
./horus_demod -c --rate=300 -m rtty8n2 - - | grep OK | wc -l"
)
set_tests_properties(test_horus_rtty_8n2 PROPERTIES PASS_REGULAR_EXPRESSION "4")
add_test(NAME test_horus_binary_iq add_test(NAME test_horus_binary_iq
COMMAND sh -c "cd ${CMAKE_CURRENT_BINARY_DIR}/src; COMMAND sh -c "cd ${CMAKE_CURRENT_BINARY_DIR}/src;
cat ${CMAKE_CURRENT_SOURCE_DIR}/samples/horusb_iq_s16.raw | cat ${CMAKE_CURRENT_SOURCE_DIR}/samples/horusb_iq_s16.raw |

Wyświetl plik

@ -1 +1 @@
__version__ = "0.1.5" __version__ = "0.1.6"

Wyświetl plik

@ -64,6 +64,7 @@ class Mode(Enum):
BINARY_V1 = 0 BINARY_V1 = 0
RTTY_7N2 = 90 RTTY_7N2 = 90
RTTY = 90 RTTY = 90
RTTY_8N2 = 91
BINARY_V2_256BIT = 1 BINARY_V2_256BIT = 1
BINARY_V2_128BIT = 2 BINARY_V2_128BIT = 2

Wyświetl plik

@ -98,11 +98,11 @@ def grab_latest_payload_id_list(url=PAYLOAD_ID_LIST_URL, local_file="payload_id_
return True return True
def init_payload_id_list(): def init_payload_id_list(filename="payload_id_list.txt"):
""" Initialise and update the local payload ID list. """ """ Initialise and update the local payload ID list. """
grab_latest_payload_id_list() grab_latest_payload_id_list(local_file=filename)
HORUS_PAYLOAD_LIST = read_payload_list() HORUS_PAYLOAD_LIST = read_payload_list(filename=filename)
@ -171,10 +171,10 @@ def grab_latest_custom_field_list(url=HORUS_CUSTOM_FIELD_URL, local_file="custom
return True return True
def init_custom_field_list(): def init_custom_field_list(filename="custom_field_list.json"):
""" Initialise and update the local custom field list """ """ Initialise and update the local custom field list """
grab_latest_custom_field_list() grab_latest_custom_field_list(local_file=filename)
HORUS_CUSTOM_FIELDS = read_custom_field_list() HORUS_CUSTOM_FIELDS = read_custom_field_list(filename=filename)
if __name__ == "__main__": if __name__ == "__main__":

Wyświetl plik

@ -1,6 +1,6 @@
[tool.poetry] [tool.poetry]
name = "horusdemodlib" name = "horusdemodlib"
version = "0.1.5" version = "0.1.6"
description = "Project Horus HAB Telemetry Demodulators" description = "Project Horus HAB Telemetry Demodulators"
authors = ["Mark Jessop"] authors = ["Mark Jessop"]
license = "LGPL-2.1-or-later" license = "LGPL-2.1-or-later"

Plik binarny nie jest wyświetlany.

Wyświetl plik

@ -58,8 +58,12 @@ struct horus {
int total_payload_bits; /* num bits rx-ed in last RTTY packet */ int total_payload_bits; /* num bits rx-ed in last RTTY packet */
}; };
/* Unique word for Horus RTTY 7 bit '$' character, 3 sync bits,
repeated 5 times */ /*
RTTY Unique word = $ characters, repeated at least 2 times.
$ = (0)010 0100
Reversed = 0010010(0)
*/
int8_t uw_horus_rtty_7N2[] = { 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,
@ -69,6 +73,14 @@ 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
}; };
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 */ /* Unique word for Horus Binary V1 */
int8_t uw_horus_binary_v1[] = { int8_t uw_horus_binary_v1[] = {
@ -104,7 +116,7 @@ struct horus *horus_open (int mode) {
struct horus *horus_open_advanced (int mode, int Rs, int tx_tone_spacing) { struct horus *horus_open_advanced (int mode, int Rs, int tx_tone_spacing) {
int i, mask; int i, mask;
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_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)); struct horus *hstates = (struct horus *)malloc(sizeof(struct horus));
assert(hstates != NULL); assert(hstates != NULL);
@ -112,10 +124,10 @@ struct horus *horus_open_advanced (int mode, int Rs, int tx_tone_spacing) {
hstates->Fs = 48000; hstates->Rs = Rs; hstates->verbose = 0; hstates->mode = mode; hstates->Fs = 48000; hstates->Rs = Rs; hstates->verbose = 0; hstates->mode = mode;
if (mode == HORUS_MODE_RTTY_7N2) { if (mode == HORUS_MODE_RTTY_7N2) {
// Parameter setup for RTTY Reception // Parameter setup for RTTY 7N2 Reception
hstates->mFSK = 2; hstates->mFSK = 2;
hstates->max_packet_len = HORUS_RTTY_NUM_BITS; hstates->max_packet_len = HORUS_RTTY_7N2_NUM_BITS;
// If baud rate not provided, use default // If baud rate not provided, use default
if (hstates->Rs == -1){ if (hstates->Rs == -1){
@ -140,6 +152,35 @@ struct horus *horus_open_advanced (int mode, int Rs, int tx_tone_spacing) {
hstates->rx_bits_len = hstates->max_packet_len; hstates->rx_bits_len = hstates->max_packet_len;
} }
if (mode == HORUS_MODE_RTTY_8N2) {
// Parameter setup for RTTY 8N2 Reception
hstates->mFSK = 2;
hstates->max_packet_len = HORUS_RTTY_8N2_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_8N2); i++) {
hstates->uw[i] = 2*uw_horus_rtty_8N2[i] - 1;
}
hstates->uw_len = sizeof(uw_horus_rtty_8N2);
hstates->uw_thresh = sizeof(uw_horus_rtty_8N2) - 2; /* allow a few bit errors in UW detection */
hstates->rx_bits_len = hstates->max_packet_len;
}
if (mode == HORUS_MODE_BINARY_V1) { if (mode == HORUS_MODE_BINARY_V1) {
// Parameter setup for the Legacy Horus Binary Mode (22 byte frames, Golay encoding) // Parameter setup for the Legacy Horus Binary Mode (22 byte frames, Golay encoding)
@ -324,9 +365,9 @@ int hex2int(char ch) {
} }
int extract_horus_rtty(struct horus *hstates, char ascii_out[], int uw_loc) { int extract_horus_rtty(struct horus *hstates, char ascii_out[], int uw_loc, int ascii_bits, int stop_bits) {
const int nfield = 7; /* 7 bit ASCII */ const int nfield = ascii_bits; /* 7 or 8 bit ASCII */
const int npad = 3; /* 3 sync bits between characters */ const int npad = stop_bits + 1; /* N stop bits + start bit between characters */
int st = uw_loc; /* first bit of first char */ int st = uw_loc; /* first bit of first char */
int en = hstates->max_packet_len - nfield; /* last bit of max length packet */ int en = hstates->max_packet_len - nfield; /* last bit of max length packet */
@ -375,7 +416,7 @@ int extract_horus_rtty(struct horus *hstates, char ascii_out[], int uw_loc) {
fprintf(stderr, " begin endpacket\n"); fprintf(stderr, " begin endpacket\n");
} }
// Only process up to the next 5 characters (checksum + line ending) // Only process up to the next 5 characters (checksum + line ending)
en = i + 10*5; en = i + (ascii_bits+stop_bits+1)*5;
} }
/* build up output array, really only need up to tx crc but /* build up output array, really only need up to tx crc but
@ -402,7 +443,7 @@ int extract_horus_rtty(struct horus *hstates, char ascii_out[], int uw_loc) {
*(ptx_crc+4) = 0; /* terminate ASCII string */ *(ptx_crc+4) = 0; /* terminate ASCII string */
if (crc_ok) { if (crc_ok) {
hstates->total_payload_bits = strlen(ascii_out)*7; hstates->total_payload_bits = strlen(ascii_out)*ascii_bits;
} }
} }
else { else {
@ -703,7 +744,20 @@ int horus_rx(struct horus *hstates, char ascii_out[], short demod_in[], int quad
a packet, so lets try to extract valid packets */ a packet, so lets try to extract valid packets */
if (hstates->mode == HORUS_MODE_RTTY_7N2) { if (hstates->mode == HORUS_MODE_RTTY_7N2) {
packet_detected = extract_horus_rtty(hstates, ascii_out, uw_loc); packet_detected = extract_horus_rtty(hstates, ascii_out, uw_loc, 7, 2);
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_8N2) {
packet_detected = extract_horus_rtty(hstates, ascii_out, uw_loc, 8, 2);
if (packet_detected){ if (packet_detected){
// If we have found a packet, advance the bits enough that we don't detect the // If we have found a packet, advance the bits enough that we don't detect the
@ -766,6 +820,9 @@ int horus_get_max_ascii_out_len(struct horus *hstates) {
if (hstates->mode == HORUS_MODE_RTTY_7N2) { if (hstates->mode == HORUS_MODE_RTTY_7N2) {
return hstates->max_packet_len/10; /* 7 bit ASCII, plus 3 sync bits */ return hstates->max_packet_len/10; /* 7 bit ASCII, plus 3 sync bits */
} }
if (hstates->mode == HORUS_MODE_RTTY_8N2) {
return hstates->max_packet_len/11; /* 8 bit ASCII, plus 3 sync bits */
}
if (hstates->mode == HORUS_MODE_BINARY_V1) { if (hstates->mode == HORUS_MODE_BINARY_V1) {
return (HORUS_BINARY_V1_NUM_UNCODED_PAYLOAD_BYTES*2+1); /* Hexadecimal encoded */ return (HORUS_BINARY_V1_NUM_UNCODED_PAYLOAD_BYTES*2+1); /* Hexadecimal encoded */
} }

Wyświetl plik

@ -40,7 +40,7 @@
#define HORUS_MODE_BINARY_V2_256BIT 1 // New 256-bit LDPC-encoded 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_BINARY_V2_128BIT 2 // New 128-bit LDPC-encoded mode
#define HORUS_MODE_RTTY_7N2 90 // RTTY Decoding - 7N2 #define HORUS_MODE_RTTY_7N2 90 // RTTY Decoding - 7N2
#define HORUS_MODE_RTTY_8N2 90 // RTTY Decoding - 8N2 #define HORUS_MODE_RTTY_8N2 91 // RTTY Decoding - 8N2
// Settings for Legacy Horus Binary Mode (Golay Encoding) // Settings for Legacy Horus Binary Mode (Golay Encoding)
@ -65,7 +65,9 @@
#define HORUS_BINARY_V2_128BIT_DEFAULT_TONE_SPACING 270 #define HORUS_BINARY_V2_128BIT_DEFAULT_TONE_SPACING 270
// Settings for RTTY Decoder // Settings for RTTY Decoder
#define HORUS_RTTY_NUM_BITS 1000 // Limit the RTTY decoder to 100 characters per line (frame). #define HORUS_RTTY_MAX_CHARS 120
#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 #define HORUS_RTTY_DEFAULT_BAUD 100
struct horus; struct horus;

Wyświetl plik

@ -84,6 +84,9 @@ int main(int argc, char *argv[]) {
if ((strcmp(optarg, "RTTY") == 0) || (strcmp(optarg, "rtty") == 0)) { if ((strcmp(optarg, "RTTY") == 0) || (strcmp(optarg, "rtty") == 0)) {
mode = HORUS_MODE_RTTY_7N2; mode = HORUS_MODE_RTTY_7N2;
} }
if ((strcmp(optarg, "RTTY8N2") == 0) || (strcmp(optarg, "rtty8n2") == 0)) {
mode = HORUS_MODE_RTTY_8N2;
}
if ((strcmp(optarg, "BINARY") == 0) || (strcmp(optarg, "binary") == 0)) { if ((strcmp(optarg, "BINARY") == 0) || (strcmp(optarg, "binary") == 0)) {
mode = HORUS_MODE_BINARY_V1; mode = HORUS_MODE_BINARY_V1;
} }