mirror of https://github.com/wb2osz/direwolf.git
Added support for gen_packets.
**** NOTE THAN THE MARK AND SPACE FREQUENCIES ARE BACKWARDS in gen_tone.c. Lines 228-229 correctly set f1_change_per_sample to the MARK frequency and f2_change_per_sample the space frequency. Line 383, however, sends MARK on 0 and SPACE on 1: tone_phase[chan] += dat ? f2_change_per_sample[chan] : f1_change_per_sample[chan]; As such, you have to generate packets like this: gen_packets -e R -m 1800 -s 1200 -o test.wav eotd.data EOTD input to the program consists of lines of 8 byte packets in HCB+ATAD format; i.e. the format that direwolf appends to the decoded packet. Ex: 81 b0 32 fb 31 23 73 8f A new option has been added to atest: -e type. That enables EOTD generation and the 'type' signifies 'R'ear to front or 'F'ront to rear decoding. Using "atest -B EOTD test.wav" the above packet decodes to: DECODED[1] 0:00.123 EOTD audio level = 49(30/31) [0] EOTD>APDW16:{DRREAR>FRONT:ts=2022-04-07T10:02:00.350,chain=ONLY,block=BASIC,devbat=OK,msgid=ONEWAY,unit_addr=18151,brake_status=GO(49 psig),disc_bits=f6,valve=OPERATIONAL,confirm=UPDATE,disc_bit_1=1,motion=STOPPED/NOT_MONITORED,light_batt=OK/NOT_MONITORED,light=ON,hex=81 b0 32 fb 31 23 73 8f
This commit is contained in:
parent
971383adfa
commit
2ea1a1892f
|
@ -278,6 +278,7 @@ list(APPEND gen_packets_SOURCES
|
||||||
dtmf.c
|
dtmf.c
|
||||||
textcolor.c
|
textcolor.c
|
||||||
dsp.c
|
dsp.c
|
||||||
|
eotd_send.c
|
||||||
)
|
)
|
||||||
|
|
||||||
add_executable(gen_packets
|
add_executable(gen_packets
|
||||||
|
|
|
@ -63,7 +63,7 @@ printf("data_len=%d, crc_len=%d\n", data_len, crc_len);
|
||||||
//
|
//
|
||||||
// THIS IS THE LSB-FIRST VERSION
|
// THIS IS THE LSB-FIRST VERSION
|
||||||
//
|
//
|
||||||
fprintf(stderr, "Enter HCB+ATAD _WITH_ the parity bit intact.\n");
|
fprintf(stderr, "Enter HCB+ATAD _WITH_ the parity bit intact and XOR already applied.\n");
|
||||||
while (1) {
|
while (1) {
|
||||||
for (int i = 0; i < 8; i++) {
|
for (int i = 0; i < 8; i++) {
|
||||||
int temp;
|
int temp;
|
||||||
|
|
|
@ -0,0 +1,102 @@
|
||||||
|
#include "direwolf.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "eotd_send.h"
|
||||||
|
#include "audio.h"
|
||||||
|
#include "gen_tone.h"
|
||||||
|
#include "eotd_defs.h"
|
||||||
|
|
||||||
|
#define EOTD_SILENCE_SAMPLES 1000
|
||||||
|
//#define EOTD_SEND_DEBUG
|
||||||
|
|
||||||
|
static int eotd_fs[] = {1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0};
|
||||||
|
static int hotd_fs[] = {1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1 };
|
||||||
|
|
||||||
|
void my_tone_gen_put_bit (int chan, int bit) {
|
||||||
|
|
||||||
|
#ifdef EOTD_SEND_DEBUG
|
||||||
|
printf("mytone bit %d\n", bit);
|
||||||
|
#endif
|
||||||
|
tone_gen_put_bit (chan, bit);
|
||||||
|
}
|
||||||
|
|
||||||
|
void my_gen_tone_put_sample (int chan, int a, int sam) {
|
||||||
|
|
||||||
|
#ifdef EOTD_SEND_DEBUG
|
||||||
|
printf("mysilence sample %d\n", sam);
|
||||||
|
#endif
|
||||||
|
gen_tone_put_sample (chan, a, sam);
|
||||||
|
}
|
||||||
|
|
||||||
|
void send_preamble(int chan, char type) {
|
||||||
|
int bit = 0;
|
||||||
|
int preamble_count;
|
||||||
|
int fs_count;
|
||||||
|
int *fs;
|
||||||
|
|
||||||
|
if (type == EOTD_TYPE_R2F) {
|
||||||
|
bit = 0;
|
||||||
|
preamble_count = 69;
|
||||||
|
fs_count = sizeof(eotd_fs) / sizeof(int);
|
||||||
|
fs = eotd_fs;
|
||||||
|
} else {
|
||||||
|
preamble_count = 456;
|
||||||
|
fs_count = sizeof(hotd_fs) / sizeof(int);
|
||||||
|
fs = hotd_fs;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < preamble_count; i++) {
|
||||||
|
my_tone_gen_put_bit (chan, bit);
|
||||||
|
bit ^= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef EOTD_SEND_DEBUG
|
||||||
|
printf("end-of-preamble\n");
|
||||||
|
#endif
|
||||||
|
// send FS
|
||||||
|
for (int i = 0; i < fs_count; i++) {
|
||||||
|
my_tone_gen_put_bit (chan, fs[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef EOTD_SEND_DEBUG
|
||||||
|
printf("end-of-fs\n");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void send_silence(int chan) {
|
||||||
|
int a = ACHAN2ADEV(chan);
|
||||||
|
|
||||||
|
for (int i = 0; i < EOTD_SILENCE_SAMPLES; i++) {
|
||||||
|
my_gen_tone_put_sample (chan, a, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int eotd_send_block (int chan, char *str, char type) {
|
||||||
|
|
||||||
|
unsigned int b[EOTD_LENGTH];
|
||||||
|
|
||||||
|
int status = sscanf(str, "%x %x %x %x %x %x %x %x", b, b+1, b+2, b+3, b+4, b+5, b+6, b+7);
|
||||||
|
if (status != EOTD_LENGTH) {
|
||||||
|
fprintf(stderr, "Error: expected 8, read %d", status);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
send_preamble(chan, type);
|
||||||
|
|
||||||
|
for (int i = 7; i >= 0; i--) {
|
||||||
|
int byte = b[i]; // Copy this non-destructively so we can repeat it later, per spec.
|
||||||
|
for (int j = 0; j < 8; j++) {
|
||||||
|
int bit = byte & 0x01;
|
||||||
|
byte >>= 1;
|
||||||
|
my_tone_gen_put_bit (chan, bit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef EOTD_SEND_DEBUG
|
||||||
|
printf("end-of-data\n");
|
||||||
|
#endif
|
||||||
|
send_silence(chan);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
#ifndef __EOTD_SEND_H
|
||||||
|
#define __EOTD_SEND_H
|
||||||
|
|
||||||
|
int eotd_send_block (int chan, char *str, char type);
|
||||||
|
|
||||||
|
#endif
|
|
@ -76,6 +76,8 @@
|
||||||
#include "morse.h"
|
#include "morse.h"
|
||||||
#include "dtmf.h"
|
#include "dtmf.h"
|
||||||
#include "fx25.h"
|
#include "fx25.h"
|
||||||
|
#include "eotd_send.h"
|
||||||
|
#include "eotd_defs.h"
|
||||||
|
|
||||||
|
|
||||||
/* Own random number generator so we can get */
|
/* Own random number generator so we can get */
|
||||||
|
@ -97,6 +99,10 @@ static int audio_file_close (void);
|
||||||
static int g_add_noise = 0;
|
static int g_add_noise = 0;
|
||||||
static float g_noise_level = 0;
|
static float g_noise_level = 0;
|
||||||
static int g_morse_wpm = 0; /* Send morse code at this speed. */
|
static int g_morse_wpm = 0; /* Send morse code at this speed. */
|
||||||
|
static int g_eotd_type = 0;
|
||||||
|
|
||||||
|
static int byte_count; /* Number of data bytes written to file. */
|
||||||
|
/* Will be written to header when file is closed. */
|
||||||
|
|
||||||
|
|
||||||
static struct audio_s modem;
|
static struct audio_s modem;
|
||||||
|
@ -115,6 +121,11 @@ static void send_packet (char *str)
|
||||||
|
|
||||||
morse_send (0, str, g_morse_wpm, 100, 100);
|
morse_send (0, str, g_morse_wpm, 100, 100);
|
||||||
}
|
}
|
||||||
|
else if (g_eotd_type > 0) {
|
||||||
|
for (c=0; c<modem.adev[0].num_channels; c++) {
|
||||||
|
eotd_send_block (c, str, g_eotd_type);
|
||||||
|
}
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
pp = ax25_from_text (str, 1);
|
pp = ax25_from_text (str, 1);
|
||||||
if (pp == NULL) {
|
if (pp == NULL) {
|
||||||
|
@ -227,7 +238,7 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
/* ':' following option character means arg is required. */
|
/* ':' following option character means arg is required. */
|
||||||
|
|
||||||
c = getopt_long(argc, argv, "gjJm:s:a:b:B:r:n:N:o:z:82M:X:",
|
c = getopt_long(argc, argv, "gjJm:s:a:b:B:r:n:N:o:z:82M:X:e:",
|
||||||
long_options, &option_index);
|
long_options, &option_index);
|
||||||
if (c == -1)
|
if (c == -1)
|
||||||
break;
|
break;
|
||||||
|
@ -462,6 +473,15 @@ int main(int argc, char **argv)
|
||||||
usage (argv);
|
usage (argv);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'e':
|
||||||
|
g_eotd_type = optarg[0];
|
||||||
|
if (g_eotd_type != EOTD_TYPE_F2R && g_eotd_type != EOTD_TYPE_R2F) {
|
||||||
|
text_color_set(DW_COLOR_ERROR);
|
||||||
|
dw_printf ("EOTD type must be %c or %c\n", EOTD_TYPE_F2R, EOTD_TYPE_R2F);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
||||||
/* Should not be here. */
|
/* Should not be here. */
|
||||||
|
@ -757,9 +777,6 @@ static FILE *out_fp = NULL;
|
||||||
|
|
||||||
static struct wav_header header;
|
static struct wav_header header;
|
||||||
|
|
||||||
static int byte_count; /* Number of data bytes written to file. */
|
|
||||||
/* Will be written to header when file is closed. */
|
|
||||||
|
|
||||||
|
|
||||||
static int audio_file_open (char *fname, struct audio_s *pa)
|
static int audio_file_open (char *fname, struct audio_s *pa)
|
||||||
{
|
{
|
||||||
|
|
|
@ -50,6 +50,7 @@
|
||||||
#include "bch.h"
|
#include "bch.h"
|
||||||
#include "eotd_defs.h"
|
#include "eotd_defs.h"
|
||||||
|
|
||||||
|
//#define EOTD_DEBUG
|
||||||
|
|
||||||
//#define TEST 1 /* Define for unit testing. */
|
//#define TEST 1 /* Define for unit testing. */
|
||||||
|
|
||||||
|
@ -473,11 +474,20 @@ int is_eotd_valid(struct hdlc_state_s *H) {
|
||||||
|
|
||||||
// Note: bits are changed in-place.
|
// Note: bits are changed in-place.
|
||||||
int corrected = apply_bch(temp_bch, bits + 1);
|
int corrected = apply_bch(temp_bch, bits + 1);
|
||||||
|
|
||||||
// Put back in HCB+ATAD format
|
// Put back in HCB+ATAD format
|
||||||
rotate_bits(bits + 1, temp_bits, crc_len);
|
rotate_bits(bits + 1, temp_bits, crc_len);
|
||||||
memcpy(bits + 1, temp_bits, crc_len * sizeof(int));
|
memcpy(bits + 1, temp_bits, crc_len * sizeof(int));
|
||||||
bits_to_bytes(bits, H->frame_buf, 64);
|
bits_to_bytes(bits, H->frame_buf, 64);
|
||||||
|
|
||||||
|
// Put the XOR-ed bits back.
|
||||||
|
if (H->eotd_type == EOTD_TYPE_R2F) {
|
||||||
|
// The HCB needs to be XOR'ed with a special constant.
|
||||||
|
for (int i = 0; i < sizeof(r2f_mask); i++) {
|
||||||
|
H->frame_buf[i] ^= r2f_mask[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return corrected;
|
return corrected;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -515,7 +525,8 @@ static void eotd_rec_bit (int chan, int subchan, int slice, int raw, int future_
|
||||||
H = &hdlc_state[chan][subchan][slice];
|
H = &hdlc_state[chan][subchan][slice];
|
||||||
|
|
||||||
#ifdef EOTD_DEBUG
|
#ifdef EOTD_DEBUG
|
||||||
dw_printf("chan=%d subchan=%d slice=%d raw=%d\n", chan, subchan, slice, raw);
|
// dw_printf("chan=%d subchan=%d slice=%d raw=%d\n", chan, subchan, slice, raw);
|
||||||
|
dw_printf("%d ", raw);
|
||||||
#endif
|
#endif
|
||||||
//dw_printf ("slice %d = %d\n", slice, raw);
|
//dw_printf ("slice %d = %d\n", slice, raw);
|
||||||
|
|
||||||
|
@ -565,6 +576,11 @@ for (int ii=0; ii < EOTD_LENGTH; ii++) {dw_printf("%02x ", H->frame_buf[ii]); }
|
||||||
if (is_eotd_valid(H) >= 0) {
|
if (is_eotd_valid(H) >= 0) {
|
||||||
alevel_t alevel = demod_get_audio_level (chan, subchan);
|
alevel_t alevel = demod_get_audio_level (chan, subchan);
|
||||||
multi_modem_process_rec_frame (chan, subchan, slice, H->frame_buf, H->frame_len, alevel, 0, 0);
|
multi_modem_process_rec_frame (chan, subchan, slice, H->frame_buf, H->frame_len, alevel, 0, 0);
|
||||||
|
} else {
|
||||||
|
#ifdef EOTD_DEBUG
|
||||||
|
print_bytes("BCH failed for packet (type byte appended) ", H->frame_buf, H->frame_len);
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
H->eotd_acc = 0;
|
H->eotd_acc = 0;
|
||||||
|
|
Loading…
Reference in New Issue