diff --git a/README.md b/README.md
index cdcb6c9..d89778e 100644
--- a/README.md
+++ b/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
diff --git a/src/Makefile b/src/Makefile
index e9f25ce..76cb079 100644
--- a/src/Makefile
+++ b/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
diff --git a/src/control_pipe.c b/src/control_pipe.c
new file mode 100644
index 0000000..5833c18
--- /dev/null
+++ b/src/control_pipe.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 .
+
+ control_pipe.c: handles command written to a non-blocking control pipe,
+ in order to change RDS PS and RT at runtime.
+*/
+
+
+#include
+#include
+#include
+#include
+#include
+
+#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;
+}
diff --git a/src/control_pipe.h b/src/control_pipe.h
new file mode 100644
index 0000000..467116f
--- /dev/null
+++ b/src/control_pipe.h
@@ -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 .
+*/
+
+
+#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();
diff --git a/src/pi_fm_rds.c b/src/pi_fm_rds.c
index 10186e7..a88cd1c 100644
--- a/src/pi_fm_rds.c
+++ b/src/pi_fm_rds.c
@@ -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: \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