From 867c36e770865bbce7b12d82151b03e74944eeef Mon Sep 17 00:00:00 2001 From: drowe67 Date: Mon, 14 Dec 2015 01:21:27 +0000 Subject: [PATCH] wavefiles being saved OK, RS232 DTR/RTS works, improved txt layout, ready for OTA testing git-svn-id: https://svn.code.sf.net/p/freetel/code@2525 01035d8c-6547-0410-b346-abe4f91aad63 --- freebeacon/Makefile | 4 + freebeacon/README.txt | 1 + freebeacon/freebeacon.c | 173 +++++++++++++++++++++++++++----------- freebeacon/freebeacon.txt | 36 -------- 4 files changed, 127 insertions(+), 87 deletions(-) create mode 100644 freebeacon/Makefile create mode 100644 freebeacon/README.txt delete mode 100644 freebeacon/freebeacon.txt diff --git a/freebeacon/Makefile b/freebeacon/Makefile new file mode 100644 index 00000000..c1065145 --- /dev/null +++ b/freebeacon/Makefile @@ -0,0 +1,4 @@ +all: freebeacon + +freebeacon: freebeacon.c + gcc -I/usr/local/include/codec2 freebeacon.c -g -o freebeacon -lsamplerate -lportaudio -lsndfile -lcodec2 -Wall diff --git a/freebeacon/README.txt b/freebeacon/README.txt new file mode 100644 index 00000000..4d41e8d7 --- /dev/null +++ b/freebeacon/README.txt @@ -0,0 +1 @@ +See comments at top of freedvbeacon.txt diff --git a/freebeacon/freebeacon.c b/freebeacon/freebeacon.c index 768a6fea..0e85dbd7 100644 --- a/freebeacon/freebeacon.c +++ b/freebeacon/freebeacon.c @@ -3,12 +3,30 @@ David Rowe Created Dec 2015 - FreeDV beacon daemon. Listens for freedv signals, then transmits a - 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. RTS and DTR is - rasised on Tx to trigger Radio PTT. + FreeDV 1600 beacon. Listens for FreeDV signals, then transmits a + reply. Places the received signal files on a web server. Requires a + Linux machine with a sound card and RS232-PTT interface to your radio. + Just one sound card is required. + + When a "trigger" string is detected in the rx FreeDV text message + (e.g. "hello beacon", or the beacon callsign), the beacon will + transmit a signal report back to you. + + It requires a "txfilename" wave file to transmit, e.g. some one + saying "Hi, I am a FreeDV beacon blah blah". The signal report is + encoded into the transmit text message. Make the wave file long + enough so that the the signal report is repeated a few times, say 30 + seconds. Transmit will stop when the wave file is played once. + + Freebeacon saves the received audio from the radio AND the decoded + audio as wavefiles. The file length is limited to 60 seconds. If + you run freebeacon in a webserver directory these will appear on the + Web. Add a cron job to your machine to clean these files up once a + day. + + If your input audio device is stereo note we only listen to + the left channel. RTS and DTR is raised on transmit, and lowered + otherwise. A whole lot of code was lifted from freedv-dev for this program. @@ -25,21 +43,33 @@ [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 + [X] test mode to tx straight away then end, to check levels, debug RS232 + [ ] FreeDV 700 support + [ ] daemonise + + change all fprintfs to use log file in daemon mode + [ ] test OTA on laptop + [ ] test OTA on RPi [ ] writing text string to a web page (cat, create if doesn't exist) [ ] samples from stdin option to work from sdr + [ ] monitor rx and tx audio on another sound device [ ] option to not tx, just log info, for rx only stations + [ ] Hamlib support for keying different radios [ ] basic SM1000 version - + has audio interfaces + + add mode, state machine + + has audio interfaces, PTT, so neat solution Building: Note you need the libraries on the gcc line installed (TODO find apt-get package names) gcc -I/usr/local/include/codec2 freebeacon.c -o freebeacon -lsamplerate -lportaudio -lsndfile -lcodec2 - Running: - ./freebeacon + Usage: + ./freebeacon -h + + List sound devices + ./freebeacon -l + + Example usage: + ./freebeacon -c /dev/ttyUSB1 --txfilename ~/codec2-dev/wav/vk5qi.wav --dev 4 -v --trigger hello */ @@ -71,14 +101,15 @@ #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 +#define LOG_COUNTER 50 -/* globals used to communicate with async events */ +/* globals used to communicate with async events and callback functions */ volatile int keepRunning; char txtMsg[MAX_CHAR], *ptxtMsg, triggerString[MAX_CHAR]; int triggered; float snr_est, snr_sample; -int com_handle; +int com_handle, verbose; /* state machine defines */ @@ -104,10 +135,18 @@ void lowerDTR(void); void raiseRTS(void); void lowerRTS(void); + +/*--------------------------------------------------------------------------------------------------------*\ + + FUNCTIONS + +\*--------------------------------------------------------------------------------------------------------*/ + /* Called on Ctrl-C */ void intHandler(int dummy) { keepRunning = 0; + fprintf(stderr,"\nShutting Down ......\n"); } /* returns number of output samples generated by resampling */ @@ -182,6 +221,7 @@ void printHelp(const struct option* long_options, int num_opts, char* argv[]) "Options:\n" "\t-l --list (audio devices)\n" "\t-c (comm port for Tx PTT)\n" + "\t-t (tx on start up, useful for testing)\n" "\t-v (verbose)\n", argv[0]); for(i=0; i peak) peak = rxfsm[j]; if (peakCounter++ == PEAK_COUNTER) { peakCounter = 0; - fprintf(stderr, "peak: %d\n", peak); } } @@ -526,7 +586,6 @@ int main(int argc, char *argv[]) { /* demodulate to decoded speech samples */ 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) { int nout = freedv_rx(f, speech_out, demod_in); freedv_get_modem_stats(f, &sync, &snr_est); @@ -543,11 +602,10 @@ int main(int argc, char *argv[]) { } } + if (state == STX) { short mod_out[freedv_get_n_max_modem_samples(f)]; short speech_in[freedv_get_n_speech_samples(f)]; - - /* TODO: assert PTT, e.g. via RS232 */ if (sfPlayFile != NULL) { /* resample input sound file as can't guarantee 8KHz sample rate */ @@ -555,7 +613,7 @@ int main(int argc, char *argv[]) { unsigned int nsf = freedv_get_n_speech_samples(f)*sfFs/FS8; short insf[nsf]; unsigned int n = sf_read_short(sfPlayFile, insf, nsf); - n8k = resample(playsrc, speech_in, insf, FS8, sfFs, freedv_get_n_speech_samples(f), nsf); + resample(playsrc, speech_in, insf, FS8, sfFs, freedv_get_n_speech_samples(f), nsf); //fwrite(speech_in, sizeof(short), freedv_get_n_nom_modem_samples(f), ftmp); @@ -614,10 +672,11 @@ int main(int argc, char *argv[]) { char timeStr[MAX_CHAR]; sprintf(timeStr, "%s",asctime( localtime(<ime) ) ); int i=0; - unsigned char str[]="a "; - while (str[i]) { - if (isspace(str[i])) - str[i]='_'; + while (timeStr[i]) { + if (isspace(timeStr[i]) || (timeStr[i] == ':')) + timeStr[i]='_'; + else + timeStr[i] = tolower(timeStr[i]); i++; } char recFileFromRadioName[MAX_CHAR], recFileDecAudioName[MAX_CHAR]; @@ -635,8 +694,6 @@ int main(int argc, char *argv[]) { break; case SRX_SYNC: sync_counter++; - if (((sync_counter % SYNC_FRAMES) == 0) && verbose) - fprintf(stderr, "sync: %d snr: %3.1f\n", sync, snr_est); if (!sync) { sync_counter = 0; next_state = SRX_MAYBE_UNSYNC; @@ -664,14 +721,14 @@ int main(int argc, char *argv[]) { sprintf(tmpStr, "SNR: %3.1f BER: %4.3f de %s\r", snr_sample, ber, callsign); strcpy(txtMsg, tmpStr); - fprintf(stderr, "TX txtMsg: %s\n", txtMsg); + //fprintf(stderr, "TX txtMsg: %s\n", txtMsg); ptxtMsg = txtMsg; sfPlayFile = openPlayFile(txFileName, &sfFs); if (com_handle != COM_HANDLE_INVALID) { raiseRTS(); raiseDTR(); } - next_state = STX; + next_state = STX; } else { next_state = SRX_IDLE; @@ -685,20 +742,30 @@ int main(int argc, char *argv[]) { if (sfPlayFile == NULL) { if (com_handle != COM_HANDLE_INVALID) { - raiseRTS(); raiseDTR(); + lowerRTS(); lowerDTR(); } next_state = SRX_IDLE; } break; } - /* filter out IDLE->MAYBE_SYNC as this fires on channel noise all the time */ + if (verbose) { + if (logCounter++ == LOG_COUNTER) { + logCounter = 0; + fprintf(stderr, "state: %-20s peak: %6d sync: %d SNR: %3.1f triggered: %d\n", + state_str[state], peak, sync, snr_est, triggered); + } + } - if ((next_state != state) && verbose) - fprintf(stderr, "state: %-20s next_state: %-20s\n", state_str[state], state_str[next_state]); state = next_state; } + /* lower PTT lines */ + + if (com_handle != COM_HANDLE_INVALID) { + lowerRTS(); lowerDTR(); + } + /* Shut down port audio */ err = Pa_StopStream(stream); @@ -720,7 +787,11 @@ int main(int argc, char *argv[]) { } -/* Comm port fuctions lifted from FreeDV -------------------------------------------------------------------*/ +/*--------------------------------------------------------------------------------------------------------*\ + + Comm port fuctions lifted from FreeDV + +\*--------------------------------------------------------------------------------------------------------*/ //---------------------------------------------------------------- // openComPort() opens the com port specified by the string diff --git a/freebeacon/freebeacon.txt b/freebeacon/freebeacon.txt deleted file mode 100644 index a042d464..00000000 --- a/freebeacon/freebeacon.txt +++ /dev/null @@ -1,36 +0,0 @@ -- freebeacon runs as a linux daemon -- configured via command line at start up - -Beacon: - -- text string "XXX" entered on command line at start up -- when we get valid sync, start parsing rx text -- on rx of "XXX", trigger tx event. -- tx starts after sync is lost for 10 seconds -- send canned, encoded speech, echoing received txt string -- then back to listen - -Logging files: - -- log dir entered on command line. This could be a web server directory, - then logged files will automatically appear on the web -- maximum nuber of audio log files entered on command line -- when we get a valid sync and txt string "XXX" - - log rx audio to wave file in log directory - - log decoded audio to wave file in log directory -- stop writing wave files when sync lost for 10s or after 60 seconds -- use rotating file names 0 ... 9 so we re-use storage -- optional: fire off event to another process, perhaps via a UDP port, - this could be used to add text to a web page, (e.g. txt string) - -Task List ---------- - -[ ] daemonise -[ ] command line parsing for - [ ] log dir and number of log files - [ ] sound devices -[ ] state machine -[ ] work out how to play to sound devices, maybe portaudio? -[ ] code to key tx via rs232 - -- 2.25.1