kopia lustrzana https://github.com/jamescoxon/dl-fldigi
230 wiersze
4.6 KiB
C++
230 wiersze
4.6 KiB
C++
// ----------------------------------------------------------------------------
|
|
// blank.cxx -- BLANK modem
|
|
//
|
|
// Copyright (C) 2006
|
|
// Dave Freese, W1HKJ
|
|
//
|
|
// This file is part of fldigi. Adapted from code contained in gMFSK source code
|
|
// distribution.
|
|
// gMFSK Copyright (C) 2001, 2002, 2003
|
|
// Tomi Manninen (oh2bns@sral.fi)
|
|
//
|
|
// Fldigi 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.
|
|
//
|
|
// Fldigi 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 fldigi. If not, see <http://www.gnu.org/licenses/>.
|
|
// ----------------------------------------------------------------------------
|
|
|
|
#include <config.h>
|
|
|
|
#include <stdlib.h>
|
|
#include <iostream>
|
|
|
|
#include "BLANK.h"
|
|
#include "ascii.h"
|
|
|
|
char BLANKmsg[80];
|
|
|
|
void BLANK::tx_init(SoundBase *sc)
|
|
{
|
|
scard = sc;
|
|
}
|
|
|
|
void BLANK::rx_init()
|
|
{
|
|
put_MODEstatus(mode);
|
|
}
|
|
|
|
void BLANK::init()
|
|
{
|
|
modem::init();
|
|
rx_init();
|
|
digiscope->mode(Digiscope::SCOPE);
|
|
}
|
|
|
|
BLANK::~BLANK()
|
|
{
|
|
delete bandpass;
|
|
delete hilbert;
|
|
delete lowpass;
|
|
delete sliding;
|
|
delete [] scope_data;
|
|
delete [] out_buf;
|
|
delete [] in_buf;
|
|
}
|
|
|
|
BLANK::BLANK(trx_mode BLANK_mode) : modem()
|
|
{
|
|
double cf, flo, fhi;
|
|
|
|
mode = BLANK_mode;
|
|
symlen = SYMLEN;
|
|
bandwidth = BLANK_BW;
|
|
samplerate = BLANKSampleRate;
|
|
|
|
flo = LP_F1 / corrRxSampleRate();
|
|
lowpass = new C_FIR_filter();
|
|
lowpass->init_lowpass (LP_FIRLEN, LP_DEC, flo );
|
|
|
|
flo = BP_F1 / corrRxSampleRate();
|
|
fhi = BP_F2 / corrRxSampleRate();
|
|
bandpass = new C_FIR_filter();
|
|
bandpass->init_bandpass (BP_FIRLEN, BP_DEC, flo, fhi );
|
|
|
|
hilbert = new C_FIR_filter();
|
|
hilbert->init_hilbert(37, 1);
|
|
|
|
sliding = new sfft (SL_LEN, SL_F1, SL_F2); // all integer values
|
|
|
|
scope_data = new double [SCOPE_DATA_LEN];
|
|
out_buf = new double [SYMLEN];
|
|
in_buf = new double [BUFLEN];
|
|
|
|
// init();
|
|
}
|
|
|
|
//=====================================================================
|
|
// receive processing
|
|
//=====================================================================
|
|
|
|
void BLANK::recvchar(int c)
|
|
{
|
|
if (c == -1)
|
|
return;
|
|
put_rx_char(c);
|
|
}
|
|
|
|
void BLANK::decodesymbol(unsigned char symbol)
|
|
{
|
|
}
|
|
|
|
complex BLANK::mixer(complex in, double f)
|
|
{
|
|
complex z;
|
|
|
|
// f may have to be modified
|
|
z = in * complex( cos(phaseacc), sin(phaseacc) );
|
|
|
|
phaseacc -= TWOPI * f / corrRxSampleRate();
|
|
if (phaseacc < 0) phaseacc += TWOPI;
|
|
|
|
return z;
|
|
}
|
|
|
|
void BLANK::update_syncscope()
|
|
{
|
|
int j;
|
|
memset(scopedata, 0, 2 * SCOPE_DATA_LEN);
|
|
if (!squelchon || metric >= squelch)
|
|
for (int i = 0; i < 2 * symlen; i++) {
|
|
// j = (i + pipeptr) % (2 * symlen);
|
|
// scopedata[i] = (pipe[j].vector[prev1symbol]).mag();
|
|
}
|
|
set_scope(scope_data, SCOPE_DATA_LEN);
|
|
}
|
|
|
|
void BLANK::afc()
|
|
{
|
|
complex z;
|
|
double x;
|
|
|
|
if (metric < squelch)
|
|
return;
|
|
// adjust "frequency" iaw with afc processing
|
|
}
|
|
|
|
int BLANK::rx_process(const double *buf, int len)
|
|
{
|
|
complex z;
|
|
int i;
|
|
|
|
while (len-- > 0) {
|
|
// create analytic signal...
|
|
z.re = z.im = *buf++;
|
|
hbfilt->run ( z, z );
|
|
// shift in frequency to the base freq of 1000 hz
|
|
z = mixer(z, frequency);
|
|
// bandpass filter around the shifted center frequency
|
|
// with required bandwidth
|
|
bandpass->run ( z, z );
|
|
|
|
// binsfft->run(z) copies frequencies of interest
|
|
complex dummy ;
|
|
sliding->run (z, &dummy, 0 );
|
|
// etc
|
|
decodesymbol();
|
|
update_syncscope();
|
|
afc();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
//=====================================================================
|
|
// transmit processing
|
|
//=====================================================================
|
|
|
|
|
|
void BLANK::sendchar(unsigned char c)
|
|
{
|
|
// need to generate the outbuf
|
|
ModulateXmtr(outbuf, symlen);
|
|
put_echo_char(c);
|
|
}
|
|
|
|
void sendidle() {
|
|
}
|
|
|
|
int BLANK::tx_process()
|
|
{
|
|
int xmtbyte;
|
|
switch (txstate) {
|
|
case TX_STATE_PREAMBLE:
|
|
for (int i = 0; i < 32; i++)
|
|
sendbit(0);
|
|
txstate = TX_STATE_START;
|
|
break;
|
|
|
|
case TX_STATE_START:
|
|
sendchar('\r');
|
|
sendchar(2); // STX
|
|
sendchar('\r');
|
|
txstate = TX_STATE_DATA;
|
|
break;
|
|
|
|
case TX_STATE_DATA:
|
|
xmtbyte = get_tx_char();
|
|
if (xmtbyte == GET_TX_CHAR_NODATA)
|
|
sendidle();
|
|
else if ( xmtbyte == GET_TX_CHAR_ETX || stopflag)
|
|
txstate = TX_STATE_FLUSH;
|
|
else
|
|
sendchar(xmtbyte);
|
|
break;
|
|
|
|
case TX_STATE_FLUSH:
|
|
sendchar('\r');
|
|
sendchar(4); // EOT
|
|
sendchar('\r');
|
|
flushtx();
|
|
stopflag = false;
|
|
// tell trx process that xmt is done
|
|
return -1;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|