kopia lustrzana https://github.com/F5OEO/PiFmRds
Add the ability to receive commands on a named pipe
rodzic
4fdd59327b
commit
20a56c47b0
24
README.md
24
README.md
|
@ -54,6 +54,7 @@ All arguments are optional:
|
|||
* `-pi` specifies the PI-code of the RDS broadcast. 4 hexadecimal digits. Example: `-pi FFFF`.
|
||||
* `-ps` specifies the station name (Program Service name, PS) of the RDS broadcast. Limit: 8 characters. Example: `-ps RASP-PI`.
|
||||
* `-rt` specifies the radiotext (RT) to be transmitted. Limit: 64 characters. Example: `-rt 'Hello, world!'`.
|
||||
* `-ctl` specifies a named pipe (FIFO) to use as a control channel to change PS and RT at run-time (see below).
|
||||
* `-ppm` specifies your Raspberry Pi's oscillator error in parts per million (ppm), see below.
|
||||
|
||||
By default the PS changes back and forth between `Pi-FmRds` and a sequence number, starting at `00000000`. The PS changes around one time per second.
|
||||
|
@ -77,6 +78,29 @@ sox -t mp3 http://www.linuxvoice.com/episodes/lv_s02e01.mp3 -t wav - | sudo ./p
|
|||
```
|
||||
|
||||
|
||||
### Setting PS and RT dynamically at run-time
|
||||
|
||||
You can control PS and RT at run-time using a named pipe (FIFO). For this run Pi-FM-RDS with the `-ctl` argument.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
mkfifo rds_ctl
|
||||
sudo ./pi_fm_rds -ctl rds_ctl
|
||||
```
|
||||
|
||||
Then you can send “commands” to change the PS and RT:
|
||||
|
||||
```
|
||||
cat >rds_ctl
|
||||
PS MyText
|
||||
RT A text to be sent as radiotext
|
||||
PS OtherTxt
|
||||
...
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Warning and Diclaimer
|
||||
|
||||
Never use this program to transmit VHF-FM data through an antenna, as it is
|
||||
|
|
13
src/Makefile
13
src/Makefile
|
@ -1,17 +1,19 @@
|
|||
CC = gcc
|
||||
STD_CFLAGS = -Wall -std=gnu99 -c -g -O3
|
||||
|
||||
# Enable ARM-specific options only on ARM
|
||||
# Enable ARM-specific options only on ARM, and compilation of the app only on ARM
|
||||
UNAME := $(shell uname -m)
|
||||
|
||||
ifeq ($(UNAME), armv6l)
|
||||
CFLAGS = $(STD_CFLAGS) -march=armv6 -mtune=arm1176jzf-s -mfloat-abi=hard -mfpu=vfp -ffast-math
|
||||
|
||||
app: rds.o waveforms.o pi_fm_rds.o fm_mpx.o control_pipe.o
|
||||
$(CC) -o pi_fm_rds rds.o waveforms.o pi_fm_rds.o fm_mpx.o control_pipe.o -lm -lsndfile
|
||||
|
||||
else
|
||||
CFLAGS = $(STD_CFLAGS)
|
||||
endif
|
||||
|
||||
app: rds.o waveforms.o pi_fm_rds.o fm_mpx.o
|
||||
$(CC) -o pi_fm_rds rds.o waveforms.o pi_fm_rds.o fm_mpx.o -lm -lsndfile
|
||||
|
||||
rds_wav: rds.o waveforms.o rds_wav.o fm_mpx.o
|
||||
$(CC) -o rds_wav rds_wav.o rds.o waveforms.o fm_mpx.o -lm -lsndfile
|
||||
|
@ -19,10 +21,13 @@ rds_wav: rds.o waveforms.o rds_wav.o fm_mpx.o
|
|||
rds.o: rds.c waveforms.h
|
||||
$(CC) $(CFLAGS) rds.c
|
||||
|
||||
control_pipe.o: control_pipe.c control_pipe.h rds.h
|
||||
$(CC) $(CFLAGS) control_pipe.c
|
||||
|
||||
waveforms.o: waveforms.c waveforms.h
|
||||
$(CC) $(CFLAGS) waveforms.c
|
||||
|
||||
pi_fm_rds.o: pi_fm_rds.c
|
||||
pi_fm_rds.o: pi_fm_rds.c control_pipe.h fm_mpx.h rds.h
|
||||
$(CC) $(CFLAGS) pi_fm_rds.c
|
||||
|
||||
rds_wav.o: rds_wav.c
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
PiFmRds - FM/RDS transmitter for the Raspberry Pi
|
||||
Copyright (C) 2014 Christophe Jacquet, F8FTK
|
||||
|
||||
See https://github.com/ChristopheJacquet/PiFmRds
|
||||
|
||||
rds_wav.c is a test program that writes a RDS baseband signal to a WAV
|
||||
file. It requires libsndfile.
|
||||
|
||||
This program 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.
|
||||
|
||||
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
control_pipe.c: handles command written to a non-blocking control pipe,
|
||||
in order to change RDS PS and RT at runtime.
|
||||
*/
|
||||
|
||||
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "rds.h"
|
||||
#include "control_pipe.h"
|
||||
|
||||
#define CTL_BUFFER_SIZE 100
|
||||
|
||||
FILE *f_ctl;
|
||||
|
||||
/*
|
||||
* Opens a file (pipe) to be used to control the RDS coder, in non-blocking mode.
|
||||
*/
|
||||
int open_control_pipe(char *filename) {
|
||||
int fd = open(filename, O_RDONLY | O_NONBLOCK);
|
||||
if(fd == -1) return -1;
|
||||
|
||||
int flags;
|
||||
flags = fcntl(fd, F_GETFL, 0);
|
||||
flags |= O_NONBLOCK;
|
||||
if( fcntl(fd, F_SETFL, flags) == -1 ) return -1;
|
||||
|
||||
f_ctl = fdopen(fd, "r");
|
||||
if(f_ctl == NULL) return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Polls the control file (pipe), non-blockingly, and if a command is received,
|
||||
* processes it and updates the RDS data.
|
||||
*/
|
||||
int poll_control_pipe() {
|
||||
static char buf[CTL_BUFFER_SIZE];
|
||||
|
||||
char *res = fgets(buf, CTL_BUFFER_SIZE, f_ctl);
|
||||
if(res == NULL) return -1;
|
||||
if(strlen(res) > 3 && res[2] == ' ') {
|
||||
char *arg = res+3;
|
||||
if(arg[strlen(arg)-1] == '\n') arg[strlen(arg)-1] = 0;
|
||||
if(res[0] == 'P' && res[1] == 'S') {
|
||||
arg[8] = 0;
|
||||
set_rds_ps(arg);
|
||||
printf("PS set to: \"%s\"\n", arg);
|
||||
return CONTROL_PIPE_PS_SET;
|
||||
}
|
||||
if(res[0] == 'R' && res[1] == 'T') {
|
||||
arg[64] = 0;
|
||||
set_rds_rt(arg);
|
||||
printf("RT set to: \"%s\"\n", arg);
|
||||
return CONTROL_PIPE_RT_SET;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Closes the control pipe.
|
||||
*/
|
||||
int close_control_pipe() {
|
||||
if(f_ctl) return fclose(f_ctl);
|
||||
else return 0;
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
PiFmRds - FM/RDS transmitter for the Raspberry Pi
|
||||
Copyright (C) 2014 Christophe Jacquet, F8FTK
|
||||
|
||||
See https://github.com/ChristopheJacquet/PiFmRds
|
||||
|
||||
rds_wav.c is a test program that writes a RDS baseband signal to a WAV
|
||||
file. It requires libsndfile.
|
||||
|
||||
This program 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.
|
||||
|
||||
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#define CONTROL_PIPE_PS_SET 1
|
||||
#define CONTROL_PIPE_RT_SET 2
|
||||
|
||||
extern int open_control_pipe(char *filename);
|
||||
extern int close_control_pipe();
|
||||
extern int poll_control_pipe();
|
|
@ -101,6 +101,7 @@
|
|||
|
||||
#include "rds.h"
|
||||
#include "fm_mpx.h"
|
||||
#include "control_pipe.h"
|
||||
|
||||
|
||||
#define NUM_SAMPLES 50000
|
||||
|
@ -205,6 +206,7 @@ terminate(int dummy)
|
|||
}
|
||||
|
||||
fm_mpx_close();
|
||||
close_control_pipe();
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
@ -262,11 +264,12 @@ map_peripheral(uint32_t base, uint32_t len)
|
|||
}
|
||||
|
||||
|
||||
|
||||
#define SUBSIZE 1
|
||||
#define DATA_SIZE 5000
|
||||
|
||||
|
||||
int tx(uint32_t carrier_freq, char *audio_file, uint16_t pi, char *ps, char *rt, int16_t ppm) {
|
||||
int tx(uint32_t carrier_freq, char *audio_file, uint16_t pi, char *ps, char *rt, int16_t ppm, char *control_pipe) {
|
||||
int i, fd, pid;
|
||||
char pagemap_fn[64];
|
||||
|
||||
|
@ -424,20 +427,33 @@ int tx(uint32_t carrier_freq, char *audio_file, uint16_t pi, char *ps, char *rt,
|
|||
set_rds_rt(rt);
|
||||
uint16_t count = 0;
|
||||
uint16_t count2 = 0;
|
||||
int varying_ps = 0;
|
||||
|
||||
if(ps) {
|
||||
set_rds_ps(ps);
|
||||
printf("PI: %04X, PS: \"%s\"\n", pi, ps);
|
||||
} else {
|
||||
printf("PI: %04X, PS: <Varying>\n", pi);
|
||||
varying_ps = 1;
|
||||
}
|
||||
printf("RT: \"%s\"\n", rt);
|
||||
|
||||
// Initialize the control pipe reader
|
||||
if(control_pipe) {
|
||||
if(open_control_pipe(control_pipe) == 0) {
|
||||
printf("Reading control commands on %s.\n", control_pipe);
|
||||
} else {
|
||||
printf("Failed to open control pipe: %s.\n", control_pipe);
|
||||
control_pipe = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
printf("Starting to transmit on %3.1f MHz.\n", carrier_freq/1e6);
|
||||
|
||||
for (;;) {
|
||||
// Default (varying) PS
|
||||
if(!ps) {
|
||||
if(varying_ps) {
|
||||
if(count == 512) {
|
||||
snprintf(myps, 9, "%08d", count2);
|
||||
set_rds_ps(myps);
|
||||
|
@ -448,7 +464,11 @@ int tx(uint32_t carrier_freq, char *audio_file, uint16_t pi, char *ps, char *rt,
|
|||
count = 0;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
if(control_pipe && poll_control_pipe() == CONTROL_PIPE_PS_SET) {
|
||||
varying_ps = 0;
|
||||
}
|
||||
|
||||
usleep(5000);
|
||||
|
||||
|
@ -493,12 +513,15 @@ int tx(uint32_t carrier_freq, char *audio_file, uint16_t pi, char *ps, char *rt,
|
|||
|
||||
int main(int argc, char **argv) {
|
||||
char *audio_file = NULL;
|
||||
char *control_pipe = NULL;
|
||||
uint32_t carrier_freq = 107900000;
|
||||
char *ps = NULL;
|
||||
char *rt = "PiFmRds: live FM-RDS transmission from the RaspberryPi";
|
||||
uint16_t pi = 0x1234;
|
||||
int16_t ppm = 0;
|
||||
|
||||
|
||||
// Parse command-line arguments
|
||||
for(int i=1; i<argc; i++) {
|
||||
char *arg = argv[i];
|
||||
char *param = NULL;
|
||||
|
@ -525,11 +548,15 @@ int main(int argc, char **argv) {
|
|||
} else if(strcmp("-ppm", arg)==0 && param != NULL) {
|
||||
i++;
|
||||
ppm = atoi(param);
|
||||
} else if(strcmp("-ctl", arg)==0 && param != NULL) {
|
||||
i++;
|
||||
control_pipe = param;
|
||||
} else {
|
||||
fatal("Unrecognised argument: %s\n"
|
||||
"Syntax: pi_fm_rds [-freq freq] [-audio file] [-ppm ppm_error] [-pi pi_code] [-ps ps_text] [-rt rt_text]\n", arg);
|
||||
"Syntax: pi_fm_rds [-freq freq] [-audio file] [-ppm ppm_error] [-pi pi_code]\n"
|
||||
" [-ps ps_text] [-rt rt_text] [-ctl control_pipe]\n", arg);
|
||||
}
|
||||
}
|
||||
|
||||
tx(carrier_freq, audio_file, pi, ps, rt, ppm);
|
||||
tx(carrier_freq, audio_file, pi, ps, rt, ppm, control_pipe);
|
||||
}
|
Ładowanie…
Reference in New Issue