FSK LDPC mode, builds OK but not tested

development
David 2020-09-29 17:38:53 +09:30
parent 4e85c4d1d0
commit 8ba0319b4b
1 changed files with 80 additions and 19 deletions

View File

@ -31,6 +31,7 @@
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <getopt.h>
#ifndef _WIN32
@ -44,8 +45,14 @@
#include "rtl-sdr.h"
#include "convenience/convenience.h"
#include "convenience/rtl_convenience.h"
#include "fsk.h"
#include "libcsdr.h"
#include "ldpc_codes.h"
#include "freedv_api.h"
// not normally exposed by FreeDV API
int freedv_tx_fsk_ldpc_bits_per_frame(struct freedv *f);
/* rtlsdr ------------------------------------*/
@ -99,6 +106,10 @@ static COMP* modembuf;
static size_t nmodembuf = 0;
static size_t nmodembuf_max = 0;
static struct freedv *freedv = NULL;
static int fsk_ldpc = 0;
static uint8_t *bytes_out;
void usage(void)
{
fprintf(stderr,
@ -120,6 +131,8 @@ void usage(void)
"\t[-u hostname (optional hostname:8001 where we send UDP dashboard diagnostics)\n"
"\t[-x output complex float samples (default output demodulated oneCharPerBit)]\n"
"\t[-t toneSpacing use 'mask' freq est]\n"
"\t[--code CodeName Use LDPC code CodeName] (note packed bytes out)\n"
"\t[--listcodes List available LDPC codes]\n"
"\tfilename (a '-' dumps bits to stdout)\n\n", DEFAULT_MODEM_SAMPLE_RATE, DEFAULT_SAMPLE_RATE, DEFAULT_SYMBOL_RATE, DEFAULT_M);
exit(1);
}
@ -293,6 +306,7 @@ static void rtlsdr_callback(unsigned char *buf, uint32_t len, void *ctx)
unsigned char bitbuf[fsk->Nbits];
COMP *pmodembuf;
int prev_fsk_nin;
int nbytes = 0;
if (ctx) {
if (do_exit)
@ -344,24 +358,34 @@ static void rtlsdr_callback(unsigned char *buf, uint32_t len, void *ctx)
pmodembuf = modembuf;
while(nmodembuf >= fsk_nin(fsk)) {
prev_fsk_nin = fsk_nin(fsk); /* fsk_nin gets updated in fsk_demod() */
/* note: in coded mode fsk_nin() == freedv_nin() */
if (output_bits == 0)
fwrite((float*)pmodembuf, sizeof(complexf), prev_fsk_nin, (FILE*)ctx);
else
fsk_demod(fsk, bitbuf, pmodembuf);
else {
if (fsk_ldpc == 0)
fsk_demod(fsk, bitbuf, pmodembuf);
else
nbytes = freedv_rawdatacomprx(freedv, bytes_out, pmodembuf);
}
pmodembuf += prev_fsk_nin;
nmodembuf -= prev_fsk_nin;
assert(nmodembuf >= 0);
/* output demodulated bits */
if (output_bits)
fwrite(bitbuf, 1, fsk->Nbits, (FILE*)ctx);
if (output_bits) {
if (fsk_ldpc == 0)
fwrite(bitbuf, 1, fsk->Nbits, (FILE*)ctx); /* one bit per byte */
else
fwrite(bytes_out, 1, nbytes, (FILE*)ctx); /* packed bytes */
}
if((FILE*)ctx == stdout) fflush((FILE*)ctx);
if (dashboard) {
update_dashboard(fsk);
}
}
/* copy left over modem saples to start of buffer */
/* copy left over modem samples to start of buffer */
memmove(modembuf, pmodembuf, nmodembuf*sizeof(COMP));
if (bytes_to_read > 0)
@ -392,15 +416,34 @@ int main(int argc, char **argv)
uint32_t bandwidth = DEFAULT_BANDWIDTH;
int tone_spacing = 100;
int freq_est_mask = 0;
output_bits = 1;
int ext_gain = 0;
int gains_hex, lna_gain, mixer_gain, vga_gain;
int gains_hex, lna_gain=15, mixer_gain=15, vga_gain=8;
int opt_idx = 0;
struct freedv_advanced adv;
output_bits = 1;
opt = 0;
while ((opt = getopt(argc, argv, "a:d:e:f:g:s:b:n:p:S:u:r:m:c:M:R:xt:w:")) != -1) {
switch (opt) {
while( opt != -1 ){
static struct option long_opts[] = {
{"listcodes", no_argument, 0, 'j'},
{"code", required_argument, 0, 'k'},
{0, 0, 0, 0}
};
opt = getopt_long(argc,argv,"a:d:e:f:g:s:b:n:p:S:u:r:m:c:M:R:xt:w:jk:",long_opts,&opt_idx);
switch (opt) {
case 'a':
modem_samp_rate = (uint32_t)atofs(optarg);
break;
case 'j':
ldpc_codes_list();
exit(0);
break;
case 'k':
fsk_ldpc = 1;
adv.codename = optarg;
break;
case 'd':
dev_index = verbose_device_search(optarg);
dev_given = 1;
@ -459,9 +502,6 @@ int main(int argc, char **argv)
freq_est_mask = 1;
tone_spacing = atoi(optarg);
break;
default:
usage();
break;
}
}
@ -603,15 +643,30 @@ int main(int argc, char **argv)
/* Setup the FSK demod -------------------------------------------------*/
{
if (fsk_ldpc == 0) {
/* uncoded mode: just set up FSK demod by itself */
int P = modem_samp_rate/Rs;
fsk = fsk_create_hbr(modem_samp_rate,Rs,M,P,FSK_DEFAULT_NSYM,FSK_NONE,tone_spacing);
fsk_set_freq_est_alg(fsk, freq_est_mask);
fprintf(stderr,"FSK Demod Fs: %5.1f kHz Rs: %3.1f kHz M: %d P: %d Ndft: %d fest_mask: %d\n",
(float)modem_samp_rate/1000,
(float)Rs/1000, M, P, fsk->Ndft, freq_est_mask);
} else {
/* coded mode: use FreeDV API to set up and run FSK modem, LDPC, framer */
int data_bits_per_frame, bits_per_frame;
adv.Rs = Rs; adv.Fs = modem_samp_rate; adv.M = M;
freedv = freedv_open_advanced(FREEDV_MODE_FSK_LDPC, &adv);
assert(freedv != NULL);
data_bits_per_frame = freedv_get_bits_per_modem_frame(freedv);
bits_per_frame = freedv_tx_fsk_ldpc_bits_per_frame(freedv);
assert(data_bits_ber_frame % 8); /* only want codes that send complete bytes */
fprintf(stderr, "FSK LDPC mode code: %s data_bits_per_frame: %d\n", adv.codename, data_bits_per_frame);
fsk = freedv_get_fsk(freedv);
bytes_out = malloc(data_bits_per_frame / 8);
}
{
fprintf(stderr,"FSK Demod Fs: %5.1f kHz Rs: %3.1f kHz M: %d P: %d Ndft: %d fest_mask: %d\n",
(float)modem_samp_rate/1000,
(float)Rs/1000, M, fsk->P, fsk->Ndft, freq_est_mask);
fsk_set_freq_est_alg(fsk, freq_est_mask);
{
/* set minimum "channel" for freq est */
fsk_lower = Rs/2;
fsk_upper = 4*Rs;
@ -667,7 +722,13 @@ int main(int argc, char **argv)
fclose(file);
rtlsdr_close(dev);
fsk_destroy(fsk);
if (fsk_ldpc == 0)
fsk_destroy(fsk);
else {
free(bytes_out);
freedv_close(freedv);
}
free (buffer);
free (rawbuf);
free(modembuf);