From: drowe67 Date: Sun, 13 Dec 2015 06:57:28 +0000 (+0000) Subject: back to full duplex sound, added writing wave files and RS232 PTT control, untested X-Git-Url: http://git.whiteaudio.com/gitweb/?a=commitdiff_plain;h=6d3f158836e69ec35c80e75a906956f5826593cd;p=freetel-svn-tracking.git back to full duplex sound, added writing wave files and RS232 PTT control, untested git-svn-id: https://svn.code.sf.net/p/freetel/code@2523 01035d8c-6547-0410-b346-abe4f91aad63 --- diff --git a/freebeacon/freebeacon.c b/freebeacon/freebeacon.c index 463d743b..768a6fea 100644 --- a/freebeacon/freebeacon.c +++ b/freebeacon/freebeacon.c @@ -4,10 +4,11 @@ Created Dec 2015 FreeDV beacon daemon. Listens for freedv signals, then transmits a - reply. Saves received signals as a rotating log of wave files so - they can be published on a web site. + reply. Saves received signal from radio and decoded audio as wavefiles + so they can be saved to a web site. - If stereo audio device we use left channel only. + If stereo audio device we use left channel only. RTS and DTR is + rasised on Tx to trigger Radio PTT. A whole lot of code was lifted from freedv-dev for this program. @@ -18,16 +19,20 @@ [X] command line processing framework [X] beacon state machine [X] install codec2 - [ ] debug sound dongle - [ ] modify for half duplex - [ ] sample rate option - [ ] rotating log - [ ] RS232 tx code - [ ] writing to wave files + [X] attempt debug sound dongle + [X] modify for half duplex + [X] sample rate option + [X] prog sound dongle debug + [X] RS232 PTT code + [X] writing to wave files + [ ] test mode to tx straight away then end, to check levels, debug RS232 + [ ] test OTA + [ ] OTA on RPi + [ ] writing text string to a web page (cat, create if doesn't exist) + [ ] samples from stdin option to work from sdr + [ ] option to not tx, just log info, for rx only stations [ ] basic SM1000 version + has audio interfaces - [ ] test mode to tx straight away then end, to check levels, debug RS232 - [ ] sound dongle/8-bit audio Building: Note you need the libraries on the gcc line installed (TODO find apt-get package names) @@ -42,6 +47,13 @@ #include #include #include +#include +#include +#include +#include +#include +#include + #include #include @@ -57,6 +69,8 @@ #define FS48 48000 // 48 kHz sampling rate rec. as we can trust accuracy of sound card #define SYNC_FRAMES 50 // frames of valid rx sync we need to see to change state #define UNSYNC_FRAMES 25 // frames of lost sync we need to see to change state +#define PEAK_COUNTER 10 // how often to report peak input level +#define COM_HANDLE_INVALID -1 /* globals used to communicate with async events */ @@ -64,6 +78,7 @@ volatile int keepRunning; char txtMsg[MAX_CHAR], *ptxtMsg, triggerString[MAX_CHAR]; int triggered; float snr_est, snr_sample; +int com_handle; /* state machine defines */ @@ -82,6 +97,13 @@ char *state_str[] = { }; +int openComPort(const char *name); +void closeComPort(void); +void raiseDTR(void); +void lowerDTR(void); +void raiseRTS(void); +void lowerRTS(void); + /* Called on Ctrl-C */ void intHandler(int dummy) { @@ -128,7 +150,6 @@ int resample(SRC_STATE *src, void listAudioDevices(void) { const PaDeviceInfo *deviceInfo = NULL; - PaError err; int numDevices, devn; numDevices = Pa_GetDeviceCount(); @@ -159,7 +180,9 @@ void printHelp(const struct option* long_options, int num_opts, char* argv[]) fprintf(stderr, "\nFreeBeacon - FreeDV Beacon\n" "usage: %s [OPTIONS]\n\n" "Options:\n" - "\t-l --list (audio devices)\n", argv[0]); + "\t-l --list (audio devices)\n" + "\t-c (comm port for Tx PTT)\n" + "\t-v (verbose)\n", argv[0]); for(i=0; idefaultHighOutputLatency; outputParameters.hostApiSpecificStreamInfo = NULL; - /* open port audio for input */ + /* open port audio for full duplex operation */ err = Pa_OpenStream( &stream, &inputParameters, - NULL, + &outputParameters, fssc, 0, /* let the driver decide */ paClipOff, @@ -405,7 +466,7 @@ int main(int argc, char *argv[]) { err = Pa_StartStream(stream); if (err != paNoError) { fprintf(stderr, "Couldn't start sound device\n"); - return; + exit(1); } fprintf(stderr, "Ctrl-C to exit\n"); @@ -421,6 +482,10 @@ int main(int argc, char *argv[]) { *txtMsg = 0; ptxtMsg = txtMsg; triggered = 0; + peakCounter = 0; + if (com_handle != COM_HANDLE_INVALID) { + lowerRTS(); lowerDTR(); + } while(keepRunning) { @@ -440,9 +505,22 @@ int main(int argc, char *argv[]) { for(j=0; j peak) + peak = rxfsm[j]; + if (peakCounter++ == PEAK_COUNTER) { + peakCounter = 0; + fprintf(stderr, "peak: %d\n", peak); + } + } + fifo_write(fifo, rxfsm, n8m_out); /* demodulate to decoded speech samples */ @@ -450,8 +528,18 @@ int main(int argc, char *argv[]) { nin = freedv_nin(f); //printf("n8m_out: %d fifo_used: %d nin: %d\n", n8m_out, fifo_used(fifo), nin); while (fifo_read(fifo, demod_in, nin) == 0) { - freedv_rx(f, speech_out, demod_in); + int nout = freedv_rx(f, speech_out, demod_in); freedv_get_modem_stats(f, &sync, &snr_est); + + if (sfRecFileFromRadio) + sf_write_short(sfRecFileFromRadio, demod_in, nin); + if (sfRecFileDecAudio) + sf_write_short(sfRecFileDecAudio, speech_out, nout); + tnout += nout; + if (tnout > mnout) { + sf_close(sfRecFileFromRadio); + sf_close(sfRecFileDecAudio); + } } } @@ -483,7 +571,7 @@ int main(int argc, char *argv[]) { int n48_out = resample(txsrc, tx48k, mod_out, fssc, fsm, n48, n8m); //printf("n48_out: %d n48: %d n_nom: %d\n", n48_out, n48, n8m); - fwrite(tx48k, sizeof(short), n48_out, ftmp); + //fwrite(tx48k, sizeof(short), n48_out, ftmp); for(j=0; jMAYBE_SYNC as this fires on channel noise all the time */ - int quiet = 0; - if ((state == SRX_IDLE) && (next_state == SRX_MAYBE_SYNC)) - quiet = 1; - if ((state == SRX_MAYBE_SYNC) && (next_state == SRX_IDLE)) - quiet = 1; - if ((next_state != state) && !quiet) + if ((next_state != state) && verbose) fprintf(stderr, "state: %-20s next_state: %-20s\n", state_str[state], state_str[next_state]); state = next_state; } + /* Shut down port audio */ + + err = Pa_StopStream(stream); + if (err != paNoError) { + fprintf(stderr, "Couldn't stop sound device\n"); + exit(1); + } + Pa_CloseStream(stream); Pa_Terminate(); + fifo_destroy(fifo); src_delete(rxsrc); src_delete(txsrc); src_delete(playsrc); freedv_close(f); fclose(ftmp); + + return 0; +} + + +/* Comm port fuctions lifted from FreeDV -------------------------------------------------------------------*/ + +//---------------------------------------------------------------- +// openComPort() opens the com port specified by the string +// ie: "/dev/ttyUSB0" +//---------------------------------------------------------------- + +int openComPort(const char *name) +{ + if(com_handle != COM_HANDLE_INVALID) + closeComPort(); + + { + struct termios t; + + if((com_handle=open(name, O_NONBLOCK|O_RDWR))==COM_HANDLE_INVALID) + return -1; + + if(tcgetattr(com_handle, &t)==-1) { + close(com_handle); + com_handle = COM_HANDLE_INVALID; + return -1; + } + + t.c_iflag = ( + IGNBRK /* ignore BREAK condition */ + | IGNPAR /* ignore (discard) parity errors */ + ); + t.c_oflag = 0; /* No output processing */ + t.c_cflag = ( + CS8 /* 8 bits */ + | CREAD /* enable receiver */ + /* + Fun snippet from the FreeBSD manpage: + + If CREAD is set, the receiver is enabled. Otherwise, no character is + received. Not all hardware supports this bit. In fact, this flag is + pretty silly and if it were not part of the termios specification it + would be omitted. + */ + | CLOCAL /* ignore modem status lines */ + ); + t.c_lflag = 0; /* No local modes */ + if(tcsetattr(com_handle, TCSANOW, &t)==-1) { + close(com_handle); + com_handle = COM_HANDLE_INVALID; + return -1; + } + + } + + return 0; +} + +void closeComPort(void) +{ + close(com_handle); + com_handle = COM_HANDLE_INVALID; +} + +//---------------------------------------------------------------- +// (raise|lower)(RTS|DTR)() +// +// Raises/lowers the specified signal +//---------------------------------------------------------------- + +void raiseDTR(void) +{ + if(com_handle == COM_HANDLE_INVALID) + return; + { // For C89 happiness + int flags = TIOCM_DTR; + ioctl(com_handle, TIOCMBIS, &flags); + } +} + + +void raiseRTS(void) +{ + if(com_handle == COM_HANDLE_INVALID) + return; + { // For C89 happiness + int flags = TIOCM_RTS; + ioctl(com_handle, TIOCMBIS, &flags); + } +} + +void lowerDTR(void) +{ + if(com_handle == COM_HANDLE_INVALID) + return; + { // For C89 happiness + int flags = TIOCM_DTR; + ioctl(com_handle, TIOCMBIC, &flags); + } } + +void lowerRTS(void) +{ + if(com_handle == COM_HANDLE_INVALID) + return; + { // For C89 happiness + int flags = TIOCM_RTS; + ioctl(com_handle, TIOCMBIC, &flags); + } +} +