Skip to content

Commit fdc09de

Browse files
committed
first pass at 2020B working at freeDV API level
1 parent 603880b commit fdc09de

File tree

7 files changed

+125
-49
lines changed

7 files changed

+125
-49
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -575,7 +575,7 @@ endif()
575575
# 2020B AWGN test
576576
add_test(NAME test_OFDM_modem_2020B_AWGN
577577
COMMAND sh -c "cd ${CMAKE_CURRENT_BINARY_DIR}/src;
578-
./ofdm_mod --in /dev/zero --testframes 10 --mode 2020B --ldpc |
578+
./ofdm_mod --in /dev/zero --testframes 10 --mode 2020B --ldpc --clip --txbpf |
579579
./ch - - --No -19 |
580580
./ofdm_demod --mode 2020B --testframes --ldpc -v 2 > /dev/null")
581581

src/freedv_2020.c

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -36,36 +36,66 @@
3636
extern char *ofdm_statemode[];
3737

3838
#ifdef __LPCNET__
39-
void freedv_2020_open(struct freedv *f, int vq_type) {
39+
void freedv_2020x_open(struct freedv *f, int vq_type) {
4040
f->speech_sample_rate = FREEDV_FS_16000;
4141
f->snr_squelch_thresh = 4.0;
4242
f->squelch_en = 0;
4343

4444
struct OFDM_CONFIG ofdm_config;
45-
ofdm_init_mode("2020", &ofdm_config);
45+
switch (f->mode) {
46+
case FREEDV_MODE_2020:
47+
case FREEDV_MODE_2020A:
48+
ofdm_init_mode("2020", &ofdm_config);
49+
break;
50+
case FREEDV_MODE_2020B:
51+
ofdm_init_mode("2020B", &ofdm_config);
52+
break;
53+
default:
54+
assert(0);
55+
}
56+
4657
f->ofdm = ofdm_create(&ofdm_config);
4758

4859
f->ldpc = (struct LDPC*)MALLOC(sizeof(struct LDPC));
4960
assert(f->ldpc != NULL);
5061

5162
ldpc_codes_setup(f->ldpc, f->ofdm->codename);
52-
int data_bits_per_frame = 312;
63+
int data_bits_per_frame;
64+
switch (f->mode) {
65+
case FREEDV_MODE_2020:
66+
data_bits_per_frame = 312;
67+
break;
68+
case FREEDV_MODE_2020A:
69+
data_bits_per_frame = 312;
70+
f->ldpc->protection_mode = LDPC_PROT_2020A;
71+
break;
72+
case FREEDV_MODE_2020B:
73+
f->ldpc->protection_mode = LDPC_PROT_2020B;
74+
data_bits_per_frame = 156;
75+
break;
76+
default:
77+
assert(0);
78+
}
79+
5380
set_data_bits_per_frame(f->ldpc, data_bits_per_frame);
5481
int coded_syms_per_frame = f->ldpc->coded_bits_per_frame/f->ofdm->bps;
5582

5683
f->ofdm_bitsperframe = ofdm_get_bits_per_frame(f->ofdm);
57-
f->ofdm_nuwbits = (f->ofdm->config.ns - 1) * f->ofdm->config.bps - f->ofdm->config.txtbits;
84+
f->ofdm_nuwbits = f->ofdm->config.nuwbits;
5885
f->ofdm_ntxtbits = f->ofdm->config.txtbits;
59-
assert(f->ofdm_nuwbits == 10);
6086
assert(f->ofdm_ntxtbits == 4);
61-
87+
f->verbose=1;
6288
if (f->verbose) {
89+
fprintf(stderr, "f->mode = %d\n", f->mode);
90+
fprintf(stderr, "vq_type = %d\n", vq_type);
6391
fprintf(stderr, "ldpc_data_bits_per_frame = %d\n", f->ldpc->ldpc_data_bits_per_frame);
6492
fprintf(stderr, "ldpc_coded_bits_per_frame = %d\n", f->ldpc->ldpc_coded_bits_per_frame);
6593
fprintf(stderr, "data_bits_per_frame = %d\n", data_bits_per_frame);
6694
fprintf(stderr, "coded_bits_per_frame = %d\n", f->ldpc->coded_bits_per_frame);
6795
fprintf(stderr, "coded_syms_per_frame = %d\n", f->ldpc->coded_bits_per_frame/f->ofdm->bps);
6896
fprintf(stderr, "ofdm_bits_per_frame = %d\n", f->ofdm_bitsperframe);
97+
fprintf(stderr, "ofdm_nuwbits = %d\n", f->ofdm_nuwbits);
98+
fprintf(stderr, "ofdm_ntxtbits = %d\n", f->ofdm_ntxtbits);
6999
}
70100

71101
f->codeword_symbols = (COMP*)MALLOC(sizeof(COMP) * coded_syms_per_frame);
@@ -118,11 +148,6 @@ void freedv_2020_open(struct freedv *f, int vq_type) {
118148
f->passthrough_gain = 0.25;
119149
}
120150

121-
void freedv_2020a_open(struct freedv *f, int vq_type) {
122-
freedv_2020_open(f, vq_type);
123-
f->ldpc->protection_mode = LDPC_PROT_2020A;
124-
}
125-
126151
void freedv_comptx_2020(struct freedv *f, COMP mod_out[]) {
127152
int i, k;
128153

src/freedv_api.c

Lines changed: 43 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,19 @@ char *rx_sync_flags_to_text[] = {
109109

110110
struct freedv *freedv_open(int mode) {
111111
// defaults for those modes that support the use of adv
112-
struct freedv_advanced adv = {1,2,100,8000,1000,200, "H_256_512_4"};
112+
struct freedv_advanced adv = {0,2,100,8000,1000,200, "H_256_512_4"};
113+
#ifdef __LPCNET__
114+
// set up default Vector Quantisers (VQs) for LPCNet */
115+
switch (mode) {
116+
case FREEDV_MODE_2020:
117+
adv.lpcnet_vq_type = 1; /* vanilla VQ */
118+
break;
119+
case FREEDV_MODE_2020A:
120+
case FREEDV_MODE_2020B:
121+
adv.lpcnet_vq_type = 2; /* index optimised VQ for theorectical robustness to single bit errors */
122+
break;
123+
}
124+
#endif
113125
return freedv_open_advanced(mode, &adv);
114126
}
115127

@@ -128,6 +140,7 @@ struct freedv *freedv_open_advanced(int mode, struct freedv_advanced *adv) {
128140
FDV_MODE_ACTIVE( FREEDV_MODE_800XA, mode) ||
129141
FDV_MODE_ACTIVE( FREEDV_MODE_2020, mode) ||
130142
FDV_MODE_ACTIVE( FREEDV_MODE_2020A, mode) ||
143+
FDV_MODE_ACTIVE( FREEDV_MODE_2020B, mode) ||
131144
FDV_MODE_ACTIVE( FREEDV_MODE_FSK_LDPC, mode) ||
132145
FDV_MODE_ACTIVE( FREEDV_MODE_DATAC0, mode) ||
133146
FDV_MODE_ACTIVE( FREEDV_MODE_DATAC1, mode) ||
@@ -144,8 +157,10 @@ struct freedv *freedv_open_advanced(int mode, struct freedv_advanced *adv) {
144157
if (FDV_MODE_ACTIVE( FREEDV_MODE_700D, mode)) freedv_ofdm_voice_open(f, "700D");
145158
if (FDV_MODE_ACTIVE( FREEDV_MODE_700E, mode)) freedv_ofdm_voice_open(f, "700E");
146159
#ifdef __LPCNET__
147-
if (FDV_MODE_ACTIVE( FREEDV_MODE_2020, mode)) freedv_2020_open(f, adv->lpcnet_vq_type);
148-
if (FDV_MODE_ACTIVE( FREEDV_MODE_2020A, mode)) freedv_2020a_open(f, adv->lpcnet_vq_type);
160+
if (FDV_MODE_ACTIVE( FREEDV_MODE_2020, mode) ||
161+
FDV_MODE_ACTIVE( FREEDV_MODE_2020A, mode) ||
162+
FDV_MODE_ACTIVE( FREEDV_MODE_2020B, mode))
163+
freedv_2020x_open(f, adv->lpcnet_vq_type);
149164
#endif
150165
if (FDV_MODE_ACTIVE( FREEDV_MODE_2400A, mode)) freedv_2400a_open(f);
151166
if (FDV_MODE_ACTIVE( FREEDV_MODE_2400B, mode)) freedv_2400b_open(f);
@@ -200,8 +215,9 @@ void freedv_close(struct freedv *freedv) {
200215
ofdm_destroy(freedv->ofdm);
201216
}
202217

203-
if (FDV_MODE_ACTIVE( FREEDV_MODE_2020, freedv->mode) ||
204-
FDV_MODE_ACTIVE( FREEDV_MODE_2020A, freedv->mode)) {
218+
if (FDV_MODE_ACTIVE( FREEDV_MODE_2020, freedv->mode) ||
219+
FDV_MODE_ACTIVE( FREEDV_MODE_2020A, freedv->mode) ||
220+
FDV_MODE_ACTIVE( FREEDV_MODE_2020B, freedv->mode)) {
205221
FREE(freedv->codeword_symbols);
206222
FREE(freedv->codeword_amps);
207223
FREE(freedv->ldpc);
@@ -257,6 +273,7 @@ static void codec2_encode_upacked(struct freedv *f, uint8_t unpacked_bits[], sho
257273
static int is_ofdm_mode(struct freedv *f) {
258274
return FDV_MODE_ACTIVE( FREEDV_MODE_2020, f->mode) ||
259275
FDV_MODE_ACTIVE( FREEDV_MODE_2020A, f->mode) ||
276+
FDV_MODE_ACTIVE( FREEDV_MODE_2020B, f->mode) ||
260277
FDV_MODE_ACTIVE( FREEDV_MODE_700D, f->mode) ||
261278
FDV_MODE_ACTIVE( FREEDV_MODE_700E, f->mode) ||
262279
FDV_MODE_ACTIVE( FREEDV_MODE_DATAC0, f->mode) ||
@@ -343,7 +360,8 @@ void freedv_comptx(struct freedv *f, COMP mod_out[], short speech_in[]) {
343360
assert( FDV_MODE_ACTIVE( FREEDV_MODE_1600, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_700C, f->mode) ||
344361
FDV_MODE_ACTIVE( FREEDV_MODE_2400A, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_2400B, f->mode) ||
345362
FDV_MODE_ACTIVE( FREEDV_MODE_700D, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_700E, f->mode) ||
346-
FDV_MODE_ACTIVE( FREEDV_MODE_2020, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_2020A, f->mode) );
363+
FDV_MODE_ACTIVE( FREEDV_MODE_2020, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_2020A, f->mode) ||
364+
FDV_MODE_ACTIVE( FREEDV_MODE_2020B, f->mode));
347365

348366
if (FDV_MODE_ACTIVE( FREEDV_MODE_1600, f->mode)) {
349367
codec2_encode_upacked(f, f->tx_payload_bits, speech_in);
@@ -374,7 +392,9 @@ void freedv_comptx(struct freedv *f, COMP mod_out[], short speech_in[]) {
374392
}
375393

376394
#ifdef __LPCNET__
377-
if (FDV_MODE_ACTIVE( FREEDV_MODE_2020, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_2020A, f->mode)) {
395+
if (FDV_MODE_ACTIVE( FREEDV_MODE_2020, f->mode) ||
396+
FDV_MODE_ACTIVE( FREEDV_MODE_2020A, f->mode) ||
397+
FDV_MODE_ACTIVE( FREEDV_MODE_2020B, f->mode)) {
378398

379399
/* buffer up bits until we get enough encoded bits for interleaver */
380400

@@ -726,7 +746,7 @@ int freedv_rx(struct freedv *f, short speech_out[], short demod_in[]) {
726746

727747
assert(nin <= f->n_max_modem_samples);
728748

729-
/* FSK RX happens in real floats, so convert to those and call their demod here */
749+
/* FSK Rx happens in real floats, so convert to those and call their demod here */
730750
if( FDV_MODE_ACTIVE( FREEDV_MODE_2400A, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_2400B, f->mode) ||
731751
FDV_MODE_ACTIVE( FREEDV_MODE_800XA, f->mode) ){
732752
float rx_float[f->n_max_modem_samples];
@@ -736,8 +756,9 @@ int freedv_rx(struct freedv *f, short speech_out[], short demod_in[]) {
736756
return freedv_floatrx(f,speech_out,rx_float);
737757
}
738758

739-
if ( FDV_MODE_ACTIVE( FREEDV_MODE_1600, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_700C, f->mode) ||
740-
FDV_MODE_ACTIVE( FREEDV_MODE_2020, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_2020A, f->mode)) {
759+
if ( FDV_MODE_ACTIVE( FREEDV_MODE_1600, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_700C, f->mode) ||
760+
FDV_MODE_ACTIVE( FREEDV_MODE_2020, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_2020A, f->mode) ||
761+
FDV_MODE_ACTIVE( FREEDV_MODE_2020B, f->mode)) {
741762

742763
float gain = 1.0f;
743764

@@ -784,7 +805,9 @@ int freedv_comprx(struct freedv *f, short speech_out[], COMP demod_in[]) {
784805
rx_status = freedv_comp_short_rx_ofdm(f, (void*)demod_in, 0, 2.0f); // was 1.0 ??
785806
}
786807

787-
if (FDV_MODE_ACTIVE( FREEDV_MODE_2020, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_2020A, f->mode)) {
808+
if (FDV_MODE_ACTIVE( FREEDV_MODE_2020, f->mode) ||
809+
FDV_MODE_ACTIVE( FREEDV_MODE_2020A, f->mode) ||
810+
FDV_MODE_ACTIVE( FREEDV_MODE_2020B, f->mode)) {
788811
#ifdef __LPCNET__
789812
rx_status = freedv_comprx_2020(f, demod_in);
790813
#endif
@@ -867,7 +890,7 @@ int freedv_bits_to_speech(struct freedv *f, short speech_out[], short demod_in[]
867890

868891
/* pass through received samples so we can hear what's going on, e.g. during tuning */
869892

870-
if ((f->mode == FREEDV_MODE_2020) || (f->mode == FREEDV_MODE_2020A)) {
893+
if ((f->mode == FREEDV_MODE_2020) || (f->mode == FREEDV_MODE_2020A) || (f->mode == FREEDV_MODE_2020B)) {
871894
/* 8kHz modem sample rate but 16 kHz speech sample
872895
rate, so we need to resample */
873896
nout = 2*f->nin_prev;
@@ -913,7 +936,9 @@ int freedv_bits_to_speech(struct freedv *f, short speech_out[], short demod_in[]
913936
}
914937

915938
if (decode_speech) {
916-
if(FDV_MODE_ACTIVE( FREEDV_MODE_2020, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_2020A, f->mode)) {
939+
if(FDV_MODE_ACTIVE( FREEDV_MODE_2020, f->mode) ||
940+
FDV_MODE_ACTIVE( FREEDV_MODE_2020A, f->mode) ||
941+
FDV_MODE_ACTIVE( FREEDV_MODE_2020B, f->mode)) {
917942
#ifdef __LPCNET__
918943
/* LPCNet decoder */
919944

@@ -1107,7 +1132,8 @@ void freedv_set_callback_txt_sym(struct freedv *f, freedv_callback_rx_sym rx, vo
11071132
if (FDV_MODE_ACTIVE( FREEDV_MODE_700D, f->mode ) ||
11081133
FDV_MODE_ACTIVE( FREEDV_MODE_700E, f->mode ) ||
11091134
FDV_MODE_ACTIVE( FREEDV_MODE_2020, f->mode ) ||
1110-
FDV_MODE_ACTIVE( FREEDV_MODE_2020A, f->mode)) {
1135+
FDV_MODE_ACTIVE( FREEDV_MODE_2020A, f->mode) ||
1136+
FDV_MODE_ACTIVE( FREEDV_MODE_2020B, f->mode)) {
11111137
f->freedv_put_next_rx_symbol = rx;
11121138
f->callback_state_sym = state;
11131139
}
@@ -1382,7 +1408,9 @@ int freedv_get_n_max_speech_samples(struct freedv *f) {
13821408
freedv_get_n_max_modem_samples() via the speech_output[]
13831409
array */
13841410
int max_output_passthrough_samples;
1385-
if (FDV_MODE_ACTIVE(FREEDV_MODE_2020, f->mode) || FDV_MODE_ACTIVE(FREEDV_MODE_2020A, f->mode))
1411+
if (FDV_MODE_ACTIVE(FREEDV_MODE_2020, f->mode) ||
1412+
FDV_MODE_ACTIVE(FREEDV_MODE_2020A, f->mode) ||
1413+
FDV_MODE_ACTIVE(FREEDV_MODE_2020B, f->mode))
13861414
// In 2020 we oversample the input modem samples from 8->16 kHz
13871415
max_output_passthrough_samples = 2*freedv_get_n_max_modem_samples(f);
13881416
else

src/freedv_api.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
#define FREEDV_MODE_700D 7
5252
#define FREEDV_MODE_2020 8
5353
#define FREEDV_MODE_2020A 15
54+
#define FREEDV_MODE_2020B 16
5455
#define FREEDV_MODE_700E 13
5556

5657
// available data modes
@@ -117,6 +118,9 @@
117118
#if !defined(FREEDV_MODE_2020A_EN)
118119
#define FREEDV_MODE_2020A_EN FREEDV_MODE_EN_DEFAULT
119120
#endif
121+
#if !defined(FREEDV_MODE_2020B_EN)
122+
#define FREEDV_MODE_2020B_EN FREEDV_MODE_EN_DEFAULT
123+
#endif
120124
#if !defined(FREEDV_MODE_FSK_LDPC_EN)
121125
#define FREEDV_MODE_FSK_LDPC_EN FREEDV_MODE_EN_DEFAULT
122126
#endif

src/freedv_api_internal.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,8 +197,7 @@ struct freedv {
197197
void freedv_1600_open(struct freedv *f);
198198
void freedv_700c_open(struct freedv *f);
199199
void freedv_ofdm_voice_open(struct freedv *f, char *mode);
200-
void freedv_2020_open(struct freedv *f, int vq_type);
201-
void freedv_2020a_open(struct freedv *f, int vq_type);
200+
void freedv_2020x_open(struct freedv *f, int vq_type);
202201
void freedv_2400a_open(struct freedv *f);
203202
void freedv_2400b_open(struct freedv *f);
204203
void freedv_800xa_open(struct freedv *f);

src/freedv_rx.c

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ int main(int argc, char *argv[]) {
6969
struct freedv *freedv;
7070
char f2020[80] = {0};
7171
#ifdef __LPCNET__
72-
sprintf(f2020,"|2020|2020A");
72+
sprintf(f2020,"|2020|2020A|2020B");
7373
#endif
7474

7575
if (argc < 4) {
@@ -78,7 +78,8 @@ int main(int argc, char *argv[]) {
7878
"\n"
7979
" --discard Reset BER stats on loss of sync, helps us get sensible BER results\n"
8080
" --dpsk Use differential PSK rather than coherent PSK\n"
81-
" --indopt Use index optimised VQs for 2020/2020A, no effect other modes\n"
81+
" --indopt 0|1 Choose index optimised VQ for 2020/2020A/2020B, no effect other modes\n"
82+
" default for 2020/2020A/2020B 0/1/1 (off/on/on)\n"
8283
" --reliabletext txt Send 'txt' using reliable text protocol\n"
8384
" --txtrx filename Store reliable text output to filename\n"
8485
" --squelch leveldB Set squelch level\n"
@@ -92,7 +93,7 @@ int main(int argc, char *argv[]) {
9293
}
9394

9495
use_testframes = verbose = discard = use_complex = use_dpsk = use_squelch = 0; use_reliabletext = 0;
95-
vq_type = 1;
96+
vq_type = -1;
9697

9798
int o = 0;
9899
int opt_idx = 0;
@@ -108,11 +109,11 @@ int main(int argc, char *argv[]) {
108109
{"usecomplex", no_argument, 0, 'c'},
109110
{"verbose1", no_argument, 0, 'v'},
110111
{"vv", no_argument, 0, 'w'},
111-
{"indopt", no_argument, 0, 'n'},
112+
{"indopt", required_argument, 0, 'n'},
112113
{0, 0, 0, 0}
113114
};
114115

115-
o = getopt_long(argc,argv,"idhr:s:x:tcvw",long_opts,&opt_idx);
116+
o = getopt_long(argc,argv,"idhr:s:x:tcvwn:",long_opts,&opt_idx);
116117

117118
switch(o) {
118119
case 'i':
@@ -125,7 +126,10 @@ int main(int argc, char *argv[]) {
125126
use_dpsk = 1;
126127
break;
127128
case 'n':
128-
vq_type = 2;
129+
if (atoi(optarg) == 0)
130+
vq_type = 1;
131+
else
132+
vq_type = 2;
129133
break;
130134
case 'r':
131135
use_reliabletext = 1;
@@ -171,6 +175,7 @@ int main(int argc, char *argv[]) {
171175
#ifdef __LPCNET__
172176
if (!strcmp(argv[dx],"2020")) mode = FREEDV_MODE_2020;
173177
if (!strcmp(argv[dx],"2020A")) mode = FREEDV_MODE_2020A;
178+
if (!strcmp(argv[dx],"2020B")) mode = FREEDV_MODE_2020B;
174179
#endif
175180
if (mode == -1) {
176181
fprintf(stderr, "Error in mode: %s\n", argv[dx]);
@@ -191,9 +196,14 @@ int main(int argc, char *argv[]) {
191196
exit(1);
192197
}
193198

194-
// the vanilla freedv_open() could be used for all modes except 2020/2020A
195-
struct freedv_advanced adv; adv.lpcnet_vq_type = vq_type;
196-
freedv = freedv_open_advanced(mode, &adv);
199+
if (vq_type == -1)
200+
freedv = freedv_open(mode);
201+
else {
202+
// 2020x: specify VQ type
203+
struct freedv_advanced adv;
204+
adv.lpcnet_vq_type = vq_type;
205+
freedv = freedv_open_advanced(mode, &adv);
206+
}
197207
assert(freedv != NULL);
198208

199209
/* set up a few options, calling these is optional -------------------------*/

0 commit comments

Comments
 (0)