Browse Source

Various small stuff

master
Jeroen Vreeken 2 years ago
parent
commit
74824887d5
16 changed files with 467 additions and 123 deletions
  1. +10
    -6
      Makefile.am
  2. +10
    -10
      configure.ac
  3. +3
    -0
      eth_ar/fprs.h
  4. +65
    -0
      eth_ar_test.c
  5. +4
    -4
      fprs2aprs.c
  6. +5
    -3
      fprs_test.c
  7. +69
    -9
      freedv_eth.c
  8. +0
    -2
      freedv_eth.conf
  9. +10
    -2
      freedv_eth.h
  10. +106
    -0
      freedv_eth_baseband_in.c
  11. +79
    -0
      freedv_eth_queue.c
  12. +2
    -10
      freedv_eth_rx.c
  13. +4
    -23
      freedv_eth_rxa.c
  14. +33
    -11
      freedv_eth_tx.c
  15. +65
    -41
      freedv_eth_txa.c
  16. +2
    -2
      sound.c

+ 10
- 6
Makefile.am View File

@ -6,21 +6,25 @@ lib_LTLIBRARIES=libeth_ar.la
libeth_ar_la_SOURCES= eth_ar.c fprs.c fprs2aprs.c
libeth_ar_la_CFLAGS=-fPIC
libeth_ar_la_LDFLAGS= -shared -fPIC -version-info 1:0:1 -lm
libeth_ar_la_LDFLAGS= -fPIC -version-info 1:0:1 -lm
nobase_include_HEADERS = eth_ar/eth_ar.h eth_ar/fprs.h
if ENABLE_HAMLIB
bin_PROGRAMS = analog_trx freedv_eth fprs2aprs_gate eth_ar_if fprs_request fprs_destination fprs_monitor
noinst_PROGRAMS = fprs_test emphasis_test
endif
noinst_PROGRAMS = fprs_test emphasis_test eth_ar_test
analog_trx_SOURCES = sound.c alaw.c ulaw.c dsp.c io.c interface.c analog_trx.c freedv_eth_config.c
analog_trx_LDADD = libeth_ar.la
analog_trx_LDFLAGS = -lcodec2 -lsamplerate -lasound -lhamlib
analog_trx_LDFLAGS = -lcodec2 -lsamplerate -lasound -lhamlib -lpthread -lm
freedv_eth_SOURCES = sound.c alaw.c ulaw.c dsp.c io.c interface.c nmea.c freedv_eth.c freedv_eth_rx.c freedv_eth_config.c freedv_eth_transcode.c freedv_eth_queue.c freedv_eth_tx.c freedv_eth_txa.c ctcss.c beacon.c emphasis.c freedv_eth_rxa.c
freedv_eth_SOURCES = sound.c alaw.c ulaw.c dsp.c io.c interface.c nmea.c freedv_eth.c freedv_eth_rx.c freedv_eth_config.c freedv_eth_transcode.c freedv_eth_queue.c freedv_eth_tx.c freedv_eth_txa.c ctcss.c beacon.c emphasis.c freedv_eth_rxa.c freedv_eth_baseband_in.c
freedv_eth_LDADD = libeth_ar.la
freedv_eth_LDFLAGS = -lcodec2 -lsamplerate -lasound -lhamlib
freedv_eth_LDFLAGS = -lcodec2 -lsamplerate -lasound -lhamlib -lpthread -lm
eth_ar_test_SOURCES = eth_ar_test.c
eth_ar_test_LDADD = libeth_ar.la
fprs_test_SOURCES = nmea.c fprs_test.c
fprs_test_LDADD = libeth_ar.la


+ 10
- 10
configure.ac View File

@ -11,7 +11,7 @@ AC_CONFIG_MACRO_DIR([m4])
dnl Search for libcodec2
AC_SEARCH_LIBS([freedv_set_data_header], [codec2], [], [
AC_MSG_ERROR([unable to find the freedv data channel functions in libcodec2])
])
], [-lm])
AC_CHECK_HEADERS([codec2/codec2.h codec2/freedv_api.h],
[codec2_found_headers=yes; break;])
@ -23,7 +23,7 @@ AS_IF([test "x$codec2_found_headers" != "xyes"],
dnl Search for libsamplerate
AC_SEARCH_LIBS([src_process], [samplerate], [], [
AC_MSG_ERROR([unable to find the src_process() function in libsamplerate])
])
], [-lm])
AC_CHECK_HEADERS([samplerate.h],
[samplerate_found_headers=yes; break;])
@ -36,7 +36,7 @@ AS_IF([test "x$samplerate_found_headers" != "xyes"],
dnl Search for libspeexdsp
AC_SEARCH_LIBS([speex_preprocess_state_init], [speexdsp], [], [
AC_MSG_ERROR([unable to find libspeexdsp])
])
], [-lm])
AC_CHECK_HEADERS([speex/speex_preprocess.h],
[speexdsp_found_headers=yes; break;])
@ -48,19 +48,19 @@ AS_IF([test "x$speexdsp_found_headers" != "xyes"],
dnl Search for hamlib
AC_SEARCH_LIBS([rig_init], [hamlib], [], [
AC_MSG_ERROR([unable to find the rig_init() function in hamlib])
])
AC_SEARCH_LIBS([rig_init], [hamlib], [hamlib_found_lib=yes], [])
AC_CHECK_HEADERS([hamlib/rig.h],
[hamlib_found_headers=yes; break;])
AS_IF([test "x$hamlib_found_headers" != "xyes"],
[AC_MSG_ERROR([Unable to find the hamlib headers])])
AM_CONDITIONAL(ENABLE_HAMLIB, test "x$hamlib_found_headers" = "xyes")
AC_CHECK_DECLS([RIG_PTT_GPIO], [], [
AS_IF([test "x$hamlib_found_headers" == "xyes"],
[AC_CHECK_DECLS([RIG_PTT_GPIO], [], [
AC_MSG_ERROR([This version of hamlib does not support PTT by GPIO])],
[[#include <hamlib/rig.h>]])
[[#include <hamlib/rig.h>]])]
)
AC_OUTPUT([Makefile])


+ 3
- 0
eth_ar/fprs.h View File

@ -26,6 +26,7 @@ extern "C" {
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <sys/types.h>
/*
@ -95,6 +96,8 @@ enum fprs_type {
FPRS_MESSAGE = 32, /* Message text */
FPRS_MESSAGEID = 33, /* Message ID */
FPRS_MESSAGEACK = 34, /* Message acknowledge */
FPRS_TYPE_MAX = 8191
};
char *fprs_type2str(enum fprs_type);


+ 65
- 0
eth_ar_test.c View File

@ -0,0 +1,65 @@
/*
Copyright Jeroen Vreeken (jeroen@vreeken.net), 2016
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <eth_ar/eth_ar.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
static int test_eth_ar_call2mac(void)
{
char *call = "test";
uint8_t mac[6];
if (eth_ar_call2mac(mac, call, 0, false))
return -1;
return 0;
}
struct fprs_test {
char *name;
int (*func)(void);
} tests[] = {
{ "eth_ar_call2mac", test_eth_ar_call2mac },
};
int main(int argc, char **argv)
{
int i;
int passed = 0;
int failed = 0;
for (i = 0; i < sizeof(tests)/sizeof(struct fprs_test); i++) {
int test_ret = tests[i].func();
printf("Test: %s: %s\n", tests[i].name, test_ret ? "Failed" : "Passed");
if (test_ret)
failed++;
else
passed++;
}
printf("%d passed, %d failed, Result: %s\n", passed, failed, failed ? "Failed" : "Passed");
return failed;
}

+ 4
- 4
fprs2aprs.c View File

@ -247,15 +247,15 @@ int fprs2aprs(char *aprs, size_t *aprs_len, struct fprs_frame *frame, uint8_t *c
else
type = '!';
int lond = fabs(lon);
int lond = (int)fabs(lon) % 360;
double lonmin = fabs(lon - (int)lon) * 60;
char lons = lon < 0 ? 'W' : 'E';
sprintf(lonstr, "%03d%05.02f%c", lond, lonmin, lons);
snprintf(lonstr, sizeof(lonstr), "%03d%05.02f%c", lond, lonmin, lons);
int latd = fabs(lat);
int latd = (int)fabs(lat) % 90;
double latmin = fabs(lat - (int)lat) * 60;
char lats = lat < 0 ? 'S' : 'N';
sprintf(latstr, "%02d%05.02f%c", latd, latmin, lats);
snprintf(latstr, sizeof(latstr), "%02d%05.02f%c", latd, latmin, lats);
} else {
type = '>';
}


+ 5
- 3
fprs_test.c View File

@ -514,7 +514,7 @@ static int test_fprs2aprs(void)
for (lat = -90; lat <= 90; lat += 35.803) {
i++;
fixed = i & 0x1;
uint8_t *callsign_arg = i & 0x04 ? NULL : mac;
uint8_t *callsign_arg = i & 0x02 ? NULL : mac;
frame = fprs_frame_create();
if (!frame) {
@ -522,7 +522,7 @@ static int test_fprs2aprs(void)
return -1;
}
if (i & 0x02) {
if (i & 0x06) {
uint8_t callsign[6];
eth_ar_callssid2mac(callsign, "TESTTEST-15", i & 0x01);
if (fprs_frame_add_callsign(frame, callsign)) {
@ -553,8 +553,10 @@ static int test_fprs2aprs(void)
char aprs[81] = { 0 };
size_t aprs_size = 80;
if (fprs2aprs(aprs, &aprs_size, frame, callsign_arg, "FPRSGATE"))
if (fprs2aprs(aprs, &aprs_size, frame, callsign_arg, "FPRSGATE")) {
fprintf(stderr, "fprs2aprs() failed\n");
return -1;
}
}
}


+ 69
- 9
freedv_eth.c View File

@ -43,6 +43,7 @@
#include "freedv_eth.h"
#include "freedv_eth_config.h"
#include "io.h"
#include "alaw.h"
static bool verbose;
static bool fullduplex;
@ -54,6 +55,10 @@ static int freedv_rx_channel;
static int tx_codecmode;
static int analog_rx_channel;
static bool use_short;
static bool baseband_out;
static bool baseband_in;
static bool baseband_in_tx;
static int tx_delay_msec;
static int tx_tail_msec;
@ -69,6 +74,7 @@ enum tx_mode {
TX_MODE_NONE,
TX_MODE_FREEDV,
TX_MODE_ANALOG,
TX_MODE_MIXED,
};
static enum tx_mode tx_mode;
@ -82,14 +88,14 @@ enum rx_mode {
static enum rx_mode rx_mode;
void freedv_eth_voice_rx(uint8_t to[6], uint8_t from[6], uint16_t eth_type, uint8_t *data, size_t len)
void freedv_eth_voice_rx(uint8_t to[6], uint8_t from[6], uint16_t eth_type, uint8_t *data, size_t len, bool local_rx)
{
struct tx_packet *packet;
if (tx_mode == TX_MODE_NONE)
return;
if (repeater) {
if (repeater || (baseband_in_tx && !local_rx)) {
if (len > tx_packet_max())
return;
packet = tx_packet_alloc();
@ -99,9 +105,33 @@ void freedv_eth_voice_rx(uint8_t to[6], uint8_t from[6], uint16_t eth_type, uint
freedv_eth_transcode(packet, tx_codecmode, eth_type);
packet->local_rx = true;
packet->local_rx = local_rx;
enqueue_voice(packet);
}
if (local_rx && baseband_out) {
if (len > tx_packet_max())
return;
packet = tx_packet_alloc();
packet->len = len;
memcpy(packet->data, data, len);
memcpy(packet->from, from, 6);
freedv_eth_transcode(packet, CODEC2_MODE_NATIVE16, eth_type);
packet->local_rx = local_rx;
enqueue_baseband(packet);
}
if (eth_type == ETH_P_NATIVE16 && !use_short) {
size_t nr = len/2;
uint8_t alaw[nr];
int16_t *s16data = (void*)data;
alaw_encode(alaw, s16data, nr);
interface_rx(to, from, ETH_P_ALAW, alaw, nr);
} else {
interface_rx(to, from, eth_type, data, len);
}
}
static void cb_sound_in(int16_t *samples_l, int16_t *samples_r, int nr_l, int nr_r)
@ -148,6 +178,17 @@ static int cb_int_tx(uint8_t to[6], uint8_t from[6], uint16_t eth_type, uint8_t
freedv_eth_transcode(packet, tx_codecmode, eth_type);
enqueue_voice(packet);
if (baseband_out) {
packet = tx_packet_alloc();
packet->len = len;
memcpy(packet->data, data, len);
memcpy(packet->from, from, 6);
freedv_eth_transcode(packet, CODEC2_MODE_NATIVE16, eth_type);
enqueue_baseband(packet);
}
} else {
if (eth_type == ETH_P_FPRS && !memcmp(mac, from, 6)) {
struct fprs_frame *frame = fprs_frame_create();
@ -165,7 +206,7 @@ static int cb_int_tx(uint8_t to[6], uint8_t from[6], uint16_t eth_type, uint8_t
}
fprs_frame_destroy(frame);
}
if (tx_mode == TX_MODE_FREEDV) {
if (tx_mode == TX_MODE_FREEDV || tx_mode == TX_MODE_MIXED) {
// printf("Data: %d %x\n", eth_type, eth_type);
/* TODO: send control as DTMF in analog mode */
if (eth_type == ETH_P_AR_CONTROL && vc_control) {
@ -301,9 +342,12 @@ int main(int argc, char **argv)
bool tx_emphasis = atoi(freedv_eth_config_value("analog_tx_emphasis", NULL, "0"));
bool rx_emphasis = atoi(freedv_eth_config_value("analog_rx_emphasis", NULL, "0"));
int dcd_threshold = atoi(freedv_eth_config_value("analog_rx_dcd_threshold", NULL, "1"));
bool tx_bb = atoi(freedv_eth_config_value("analog_tx_baseband", NULL, "0"));
bool tx_tone = atoi(freedv_eth_config_value("analog_tx_tone", NULL, "0"));
int dtmf_mute = atoi(freedv_eth_config_value("analog_dtmf_mute", NULL, "1"));
use_short = atoi(freedv_eth_config_value("analog_rx_short", NULL, "0"));
baseband_out = atoi(freedv_eth_config_value("baseband_out", NULL, "0"));
baseband_in = atoi(freedv_eth_config_value("baseband_in", NULL, "0"));
baseband_in_tx = atoi(freedv_eth_config_value("baseband_in_tx", NULL, "0"));
if (!strcmp(freedv_mode_str, "1600")) {
freedv_mode = FREEDV_MODE_1600;
@ -337,6 +381,8 @@ int main(int argc, char **argv)
tx_mode = TX_MODE_FREEDV;
} else if (!strcmp(tx_mode_str, "analog")) {
tx_mode = TX_MODE_ANALOG;
} else if (!strcmp(rx_mode_str, "mixed")) {
tx_mode = RX_MODE_MIXED;
} else {
printf("Invalid tx_mode\n");
return -1;
@ -449,21 +495,24 @@ int main(int argc, char **argv)
freedv_eth_rx_init(freedv, mac, sound_rate);
freedv_eth_rxa_init(sound_rate, mac, rx_emphasis, rx_ctcss_f, dtmf_mute, analog_rx_gain);
if (baseband_in)
freedv_eth_bb_in_init(sound_rate, mac, nr_samples);
if (tx_mode == TX_MODE_FREEDV) {
if (tx_mode == TX_MODE_FREEDV || tx_mode == TX_MODE_MIXED) {
freedv_eth_tx_init(freedv, mac, nmea, fullduplex,
sound_rate,
tx_tail_msec, tx_delay_msec,
tx_header_msec, tx_header_max_msec,
tx_fprs_msec);
} else if (tx_mode == TX_MODE_ANALOG) {
} else if (tx_mode == TX_MODE_ANALOG || tx_mode == TX_MODE_MIXED) {
freedv_eth_txa_init(fullduplex,
sound_rate,
tx_tail_msec,
tx_ctcss_f, tx_ctcss_amp,
beacon_interval, beacon_msg,
tx_emphasis,
tx_bb, tx_tone);
tx_tone);
}
if (nmeadev) {
@ -501,7 +550,18 @@ int main(int argc, char **argv)
do {
poll(fds, nfds, -1);
if (sound_poll_out_tx(fds, sound_fdc_tx)) {
if (tx_mode == TX_MODE_FREEDV)
if (tx_mode == TX_MODE_MIXED) {
bool q_v = queue_voice_filled();
bool q_d = queue_data_filled() || queue_control_filled();
bool tx_v = freedv_eth_txa_ptt();
bool tx_d = freedv_eth_tx_ptt();
if (tx_d || (!tx_v && !q_v && q_d)) {
freedv_eth_txa_state_machine();
} else {
freedv_eth_txa_state_machine();
}
} else if (tx_mode == TX_MODE_FREEDV)
freedv_eth_tx_state_machine();
else if (tx_mode == TX_MODE_ANALOG)
freedv_eth_txa_state_machine();


+ 0
- 2
freedv_eth.conf View File

@ -66,8 +66,6 @@
#analog_rx_ctcss_frequency = 0.0
#analog_rx_gain = 1.0
## Output baseband on second audio channel (without ctcss, emphasis, beacon)
#analog_tx_baseband = 0
## Output CTCSS tone on second audio channel
#analog_tx_tone = 0


+ 10
- 2
freedv_eth.h View File

@ -77,6 +77,12 @@ struct tx_packet *peek_voice(void);
void enqueue_voice(struct tx_packet *packet);
bool queue_voice_filled(void);
struct tx_packet *dequeue_baseband(void);
struct tx_packet *peek_baseband(void);
void enqueue_baseband(struct tx_packet *packet);
bool queue_baseband_filled(void);
void ensure_baseband(size_t nr);
struct tx_packet *dequeue_data(void);
struct tx_packet *peek_data(void);
void enqueue_data(struct tx_packet *packet);
@ -87,7 +93,7 @@ struct tx_packet *peek_control(void);
void enqueue_control(struct tx_packet *packet);
bool queue_control_filled(void);
void freedv_eth_voice_rx(uint8_t to[6], uint8_t from[6], uint16_t eth_type, uint8_t *data, size_t len);
void freedv_eth_voice_rx(uint8_t to[6], uint8_t from[6], uint16_t eth_type, uint8_t *data, size_t len, bool local_rx);
bool freedv_eth_cdc(void);
int freedv_eth_transcode(struct tx_packet *packet, int to_codecmode, uint16_t from_type);
@ -111,7 +117,6 @@ int freedv_eth_txa_init(bool init_fullduplex, int hw_rate,
double ctcss_f, double ctcss_amp,
int beacon_interval, char *beacon_msg,
bool emphasis,
bool init_output_bb,
bool init_output_tone);
void freedv_eth_txa_state_machine(void);
bool freedv_eth_txa_ptt(void);
@ -122,4 +127,7 @@ int freedv_eth_rxa_init(int hw_rate, uint8_t mac_init[6],
float rx_gain);
void freedv_eth_rxa(int16_t *samples, int nr);
int freedv_eth_bb_in_init(int hw_rate, uint8_t mac_init[6], int nr_hw);
bool freedv_eth_baseband_in_cdc(void);
#endif /* _INCLUDE_FREEDV_ETH_H_ */

+ 106
- 0
freedv_eth_baseband_in.c View File

@ -0,0 +1,106 @@
/*
Copyright Jeroen Vreeken (jeroen@vreeken.net), 2017
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "freedv_eth.h"
#include "freedv_eth_config.h"
#include "io.h"
#include "dtmf.h"
#include "emphasis.h"
#include "interface.h"
#include "alaw.h"
#include "sound.h"
#include "ctcss.h"
#include "eth_ar_codec2.h"
#include <string.h>
#include <speex/speex_preprocess.h>
static uint8_t mac[6];
static uint8_t bcast[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
static bool cdc = false;
static struct sound_resample *sr = NULL;
static float rx_gain = 1.0;
SpeexPreprocessState *st;
bool freedv_eth_baseband_in_cdc(void)
{
return cdc;
}
void freedv_eth_baseband_in(int16_t *samples, int nr)
{
int nr_a = sound_resample_nr_out(sr, nr);
int16_t mod_a[nr_a];
if (st)
speex_preprocess_run(st, samples);
sound_resample_perform_gain_limit(sr, mod_a, samples, nr_a, nr, rx_gain);
cdc = io_hl_aux2_get();
if (cdc) {
freedv_eth_voice_rx(bcast, mac, ETH_P_NATIVE16,
(uint8_t *)mod_a, nr_a * sizeof(int16_t), false);
}
}
int freedv_eth_bb_in_init(int hw_rate, uint8_t mac_init[6], int nr_hw)
{
int a_rate = FREEDV_ALAW_RATE;
bool denoise = atoi(freedv_eth_config_value("baseband_in_denoise", NULL, "1"));
rx_gain = atof(freedv_eth_config_value("baseband_in_gain", NULL, "1.0"));
memcpy(mac, mac_init, 6);
printf("Baseband in gain: %f\n", rx_gain);
cdc = io_hl_aux2_get();
sound_resample_destroy(sr);
sr = sound_resample_create(a_rate, hw_rate);
if (denoise) {
printf("Denoise and AGC active\n");
int val;
float fval;
st = speex_preprocess_state_init(nr_hw, hw_rate);
val= denoise;
speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_DENOISE, &val);
val = -30;
speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_NOISE_SUPPRESS, &val);
val=1;
speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_AGC, &val);
fval=32768;
speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_AGC_LEVEL, &fval);
val = 40;
speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_AGC_INCREMENT, &val);
val=60;
speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_AGC_MAX_GAIN, &val);
} else {
printf("No denoise and AGC\n");
}
return 0;
}

+ 79
- 0
freedv_eth_queue.c View File

@ -19,6 +19,7 @@
#include "freedv_eth.h"
#include <stdlib.h>
#include <stdatomic.h>
#include <string.h>
static _Atomic(struct tx_packet *) tx_packet_pool = NULL;
@ -83,6 +84,84 @@ bool queue_voice_filled(void)
return queue_voice;
}
static struct tx_packet *queue_baseband = NULL;
static struct tx_packet **queue_baseband_tail = &queue_baseband;
struct tx_packet *dequeue_baseband(void)
{
struct tx_packet *packet;
packet = queue_baseband;
queue_baseband = packet->next;
if (&packet->next == queue_baseband_tail) {
queue_baseband_tail = &queue_baseband;
}
return packet;
}
struct tx_packet *peek_baseband(void)
{
return queue_baseband;
}
void enqueue_baseband(struct tx_packet *packet)
{
packet->next = NULL;
*queue_baseband_tail = packet;
queue_baseband_tail = &packet->next;
}
bool queue_baseband_filled(void)
{
return queue_baseband;
}
void ensure_baseband(size_t nr)
{
struct tx_packet *packet = queue_baseband;
if (packet->len == nr)
return;
if (packet->len > nr) {
struct tx_packet *p2 = tx_packet_alloc();
size_t new_nr = packet->len - nr;
p2->local_rx = packet->local_rx;
memcpy(p2->data, packet->data + nr, new_nr);
p2->len = new_nr;
packet->len = nr;
p2->next = packet->next;
packet->next = p2->next;
} else {
while (packet->next) {
struct tx_packet *p2 = packet->next;
size_t nr_extra = nr - packet->len;
if (nr_extra > p2->len)
nr_extra = p2->len;
memcpy(packet->data + packet->len, p2->data, nr_extra);
packet->len += nr_extra;
size_t nr_off = p2->len - nr_extra;
if (!nr_off) {
packet->next = p2->next;
tx_packet_free(p2);
} else {
memmove(p2->data, p2->data + nr_extra, nr_off);
p2->len = nr_off;
}
if (packet->len == nr)
return;
}
size_t nr_zero = nr - packet->len;
memset(packet->data + packet->len, 0, nr_zero);
packet->len = nr;
}
}
static struct tx_packet *queue_data = NULL;
static struct tx_packet **queue_data_tail = &queue_data;


+ 2
- 10
freedv_eth_rx.c View File

@ -105,11 +105,7 @@ void freedv_eth_rx(int16_t *hw_samples, int hw_nr)
freedv_eth_voice_rx(
bcast, rx_add, eth_type_rx,
packed_codec_bits + i * bytes_per_eth_frame,
bytes_per_eth_frame);
interface_rx(
bcast, rx_add, eth_type_rx,
packed_codec_bits + i * bytes_per_eth_frame,
bytes_per_eth_frame);
bytes_per_eth_frame, true);
}
printf(".");
fflush(NULL);
@ -124,11 +120,7 @@ void freedv_eth_rx(int16_t *hw_samples, int hw_nr)
freedv_eth_voice_rx(
bcast, rx_add, eth_type_rx,
silence_packet,
bytes_per_eth_frame);
interface_rx(
bcast, rx_add, eth_type_rx,
silence_packet,
bytes_per_eth_frame);
bytes_per_eth_frame, true);
}
}
}


+ 4
- 23
freedv_eth_rxa.c View File

@ -38,7 +38,6 @@ static bool ctcss_sql;
static int dtmf_mute = 1;
static struct sound_resample *sr = NULL;
static float rx_gain = 1.0;
static int voice_mode = CODEC2_MODE_ALAW;
static char dtmf_control_start = '*';
static char dtmf_control_stop = '#';
@ -83,12 +82,12 @@ void freedv_eth_rxa(int16_t *samples, int nr)
sound_resample_perform_gain_limit(sr, mod_a, samples, nr_a, nr, rx_gain);
cdc = io_hl_dcd_get();
if (emphasis_d)
emphasis_de(emphasis_d, mod_a, nr_a);
if (ctcss_sql) {
cdc |= ctcss_detect_rx(mod_a, nr_a);
cdc = ctcss_detect_rx(mod_a, nr_a);
} else {
cdc = io_hl_dcd_get();
}
dtmf_rx(mod_a, nr_a, cb_control, &detected);
@ -100,20 +99,7 @@ void freedv_eth_rxa(int16_t *samples, int nr)
}
if (cdc) {
freedv_eth_voice_rx(bcast, mac, ETH_P_NATIVE16, (uint8_t *)mod_a, nr_a * sizeof(int16_t));
switch (voice_mode) {
case CODEC2_MODE_ALAW: {
uint8_t alaw[nr_a];
alaw_encode(alaw, mod_a, nr_a);
interface_rx(bcast, mac, ETH_P_ALAW, alaw, nr_a);
break;
}
case CODEC2_MODE_NATIVE16: {
interface_rx(bcast, mac, ETH_P_NATIVE16, (uint8_t *)mod_a, nr_a * sizeof(int16_t));
break;
}
}
freedv_eth_voice_rx(bcast, mac, ETH_P_NATIVE16, (uint8_t *)mod_a, nr_a * sizeof(int16_t), true);
} else {
dtmf_state = DTMF_IDLE;
}
@ -124,11 +110,6 @@ int freedv_eth_rxa_init(int hw_rate, uint8_t mac_init[6],
float rx_gain_init)
{
int a_rate = FREEDV_ALAW_RATE;
bool use_short = atoi(freedv_eth_config_value("analog_rx_short", NULL, "0"));
if (use_short) {
voice_mode = CODEC2_MODE_NATIVE16;
}
rx_gain = rx_gain_init;
memcpy(mac, mac_init, 6);


+ 33
- 11
freedv_eth_tx.c View File

@ -55,19 +55,38 @@ static struct freedv *freedv = NULL;
static int nom_modem_samples;
static int16_t *mod_out;
static struct sound_resample *sr = NULL;
static struct sound_resample *sr0 = NULL;
static struct sound_resample *sr1 = NULL;
static int tx_sound_out(int16_t *samples, int nr)
{
if (!sr) {
sound_out(samples, nr, true, true);
int16_t *samples1 = NULL;
struct tx_packet *packet = peek_baseband();
if (packet) {
ensure_baseband(nr*sizeof(int16_t));
packet = dequeue_baseband();
samples1 = (int16_t*)packet->data;
}
if (!sr0) {
sound_out_lr(samples, samples1, nr);
} else {
int nr_out = sound_resample_nr_out(sr, nr);
int16_t hw_mod_out[nr_out];
sound_resample_perform(sr, hw_mod_out, samples, nr_out, nr);
sound_out(hw_mod_out, nr_out, true, true);
int nr_out = sound_resample_nr_out(sr0, nr);
int16_t hw_mod_out0[nr_out];
int16_t hw_mod_out1[nr_out];
sound_resample_perform(sr0, hw_mod_out0, samples, nr_out, nr);
if (samples1) {
sound_resample_perform(sr1, hw_mod_out1, samples1, nr_out, nr);
}
sound_out_lr(hw_mod_out0, samples1 ? hw_mod_out1 : NULL, nr_out);
}
if (packet) {
tx_packet_free(packet);
}
return 0;
}
@ -335,11 +354,14 @@ int freedv_eth_tx_init(struct freedv *init_freedv, uint8_t init_mac[6],
int freedv_rate = freedv_get_modem_sample_rate(freedv);
printf("TX freedv rate: %d\n", freedv_rate);
sound_resample_destroy(sr);
sound_resample_destroy(sr0);
sound_resample_destroy(sr1);
if (freedv_rate != hw_rate) {
sr = sound_resample_create(hw_rate, freedv_rate);
sr0 = sound_resample_create(hw_rate, freedv_rate);
sr1 = sound_resample_create(hw_rate, freedv_rate);
} else {
sr = NULL;
sr0 = NULL;
sr1 = NULL;
}
int period_msec = 1000 / (freedv_rate / freedv_get_n_nom_modem_samples(freedv));
printf("TX period: %d msec\n", period_msec);


+ 65
- 41
freedv_eth_txa.c View File

@ -48,7 +48,6 @@ static struct ctcss *ctcss = NULL;
static struct beacon *beacon = NULL;
static struct emphasis *emphasis_p = NULL;
static int nr_samples = FREEDV_ALAW_NR_SAMPLES;
static bool output_bb = false;
static bool output_tone = false;
static enum io_hl_ptt ptt = IO_HL_PTT_OFF;
static bool tx_tail_other = false;
@ -57,18 +56,38 @@ struct beacon_sample *beep_1k;
struct beacon_sample *beep_1k2;
struct beacon_sample *beep_2k;
static int tx_sound_out(int16_t *samples, int16_t *samples_bb, int nr)
static int tx_sound_out(int16_t *samples0, int16_t *samples1, int nr)
{
struct tx_packet *packet = peek_baseband();
if (!samples1 && packet) {
ensure_baseband(nr*sizeof(int16_t));
packet = dequeue_baseband();
samples1 = (int16_t*)packet->data;
}
if (!sr_l) {
sound_out_lr(samples, samples_bb, nr);
sound_out_lr(samples0, samples1, nr);
} else {
int nr_out = sound_resample_nr_out(sr_l, nr);
int16_t hw_mod_out_l[nr_out];
int16_t hw_mod_out_r[nr_out];
sound_resample_perform(sr_l, hw_mod_out_l, samples, nr_out, nr);
sound_resample_perform(sr_r, hw_mod_out_r, samples_bb, nr_out, nr);
sound_out_lr(hw_mod_out_l, hw_mod_out_r, nr_out);
int16_t *out_l, *out_r;
if (samples0) {
sound_resample_perform(sr_l, hw_mod_out_l, samples0, nr_out, nr);
out_l = hw_mod_out_l;
} else
out_l = NULL;
if (samples1) {
sound_resample_perform(sr_r, hw_mod_out_r, samples1, nr_out, nr);
out_r = hw_mod_out_r;
} else
out_r = NULL;
sound_out_lr(out_l, out_r, nr_out);
}
if (packet) {
tx_packet_free(packet);
}
return 0;
}
@ -76,21 +95,23 @@ static int tx_sound_out(int16_t *samples, int16_t *samples_bb, int nr)
static void tx_silence(void)
{
int16_t buffer[nr_samples];
int16_t buffer_bb[nr_samples];
memset(buffer, 0, sizeof(int16_t)*nr_samples);
memset(buffer_bb, 0, sizeof(int16_t)*nr_samples);
int16_t *bp0 = NULL, *bp1 = NULL;
if (tx_hadvoice) {
if (ctcss) {
if (output_tone)
ctcss_add(ctcss, buffer_bb, nr_samples);
else
memset(buffer, 0, sizeof(int16_t)*nr_samples);
if (output_tone) {
bp1 = buffer;
ctcss_add(ctcss, buffer, nr_samples);
} else {
bp0 = buffer;
ctcss_add(ctcss, buffer, nr_samples);
if (emphasis_p)
emphasis_pre(emphasis_p, buffer, nr_samples);
}
}
if (emphasis_p)
emphasis_pre(emphasis_p, buffer, nr_samples);
}
tx_sound_out(buffer, buffer_bb, nr_samples);
tx_sound_out(bp0, bp1, nr_samples);
}
static void tx_beep(void)
@ -104,19 +125,21 @@ static void tx_beep(void)
bs = beep_2k;
}
int16_t buffer[nr_samples];
int16_t buffer_bb[nr_samples];
int16_t buffer_tone[nr_samples];
int16_t *buffer1 = NULL;
memcpy(buffer, bs->samples + tx_state_cnt * nr_samples, sizeof(int16_t)*nr_samples);
memset(buffer_bb, 0, sizeof(int16_t)*nr_samples);
if (ctcss) {
if (output_tone)
ctcss_add(ctcss, buffer_bb, nr_samples);
else
if (output_tone) {
buffer1 = buffer_tone;
memset(buffer_tone, 0, sizeof(int16_t)*nr_samples);
ctcss_add(ctcss, buffer_tone, nr_samples);
} else {
ctcss_add(ctcss, buffer, nr_samples);
}
if (emphasis_p)
}
} if (emphasis_p)
emphasis_pre(emphasis_p, buffer, nr_samples);
tx_sound_out(buffer, buffer_bb, nr_samples);
tx_sound_out(buffer, buffer1, nr_samples);
}
static void tx_voice(void)
@ -128,45 +151,48 @@ static void tx_voice(void)
tx_silence();
} else {
int16_t buffer[nr_samples];
int16_t buffer_bb[nr_samples];
memset(buffer_bb, 0, sizeof(int16_t)*nr_samples);
int16_t *bp1 = NULL;
int16_t buffer_tone[nr_samples];
beacon_generate(beacon, buffer, nr_samples);
if (tx_hadvoice) {
if (ctcss) {
if (output_tone)
ctcss_add(ctcss, buffer_bb, nr_samples);
else
if (output_tone) {
bp1 = buffer_tone;
memset(buffer_tone, 0, sizeof(int16_t)*nr_samples);
ctcss_add(ctcss, buffer_tone, nr_samples);
} else {
ctcss_add(ctcss, buffer, nr_samples);
}
}
}
if (emphasis_p)
emphasis_pre(emphasis_p, buffer, nr_samples);
tx_sound_out(buffer, buffer_bb, nr_samples);
tx_sound_out(buffer, bp1, nr_samples);
}
} else {
int nr = packet->len / sizeof(short);
int16_t buffer[nr];
int16_t buffer_bb[nr];
int16_t *bp1 = NULL;
int16_t buffer_tone[nr];
tx_hadvoice = true;
memcpy(buffer, packet->data, packet->len);
if (output_bb)
memcpy(buffer_bb, packet->data, packet->len);
else
memset(buffer_bb, 0, packet->len);
if (beacon)
beacon_generate_add(beacon, buffer, nr);
if (emphasis_p)
emphasis_pre(emphasis_p, buffer, nr);
if (ctcss) {
if (output_tone)
ctcss_add(ctcss, buffer_bb, nr);
else
if (output_tone) {
bp1 = buffer_tone;
memset(buffer_tone, 0, packet->len);
ctcss_add(ctcss, buffer_tone, nr);
} else {
ctcss_add(ctcss, buffer, nr);
}
}
tx_sound_out(buffer, buffer_bb, nr);
tx_sound_out(buffer, bp1, nr);
packet = dequeue_voice();
tx_packet_free(packet);
@ -308,7 +334,6 @@ int freedv_eth_txa_init(bool init_fullduplex, int hw_rate,
double ctcss_f, double ctcss_amp,
int beacon_interval, char *beacon_msg,
bool emphasis,
bool init_output_bb,
bool init_output_tone)
{
int a_rate = FREEDV_ALAW_RATE;
@ -318,7 +343,6 @@ int freedv_eth_txa_init(bool init_fullduplex, int hw_rate,
beep_2k = beacon_beep_create(a_rate, 2000.0, 0.35, 0.25, 0.25);
fullduplex = init_fullduplex;
output_bb = init_output_bb;
output_tone = init_output_tone;
tx_state = TX_STATE_OFF;


+ 2
- 2
sound.c View File

@ -168,8 +168,8 @@ int sound_out_lr(int16_t *samples_l, int16_t *samples_r, int nr)
int i;
for (i = 0; i < nr; i++) {
samples[i * 2 + 0] = samples_l[i];
samples[i * 2 + 1] = samples_r[i];
samples[i * 2 + 0] = samples_l ? samples_l[i] : 0;
samples[i * 2 + 1] = samples_r ? samples_r[i] : 0;
}
return sound_out_alsa(samples, nr);


Loading…
Cancel
Save