0
0
mirror of https://github.com/ChristopheJacquet/PiFmRds synced 2025-10-06 00:02:53 +02:00

Open control pipe in blocking mode.

Up to now, Pi-FM-RDS was opening the FIFO in non-blocking mode, but with the latest Raspbian, the behavior was: the FIFO had to be opened by the writer before Pi-FM-RDS was started, and not closed after, as pointed out by wmcgrathled. I'm not sure if it was always like this, or if the semantics of opening a FIFO in non-blocking mode changed.

Anyway, it's probably less confusing to open the FIFO in blocking mode, so at Pi-FM-RDS startup, the user is prompted to start the writer process if they haven't done so yet. This commit is changing this.

Fixes #154
This commit is contained in:
ChristopheJacquet
2024-02-24 18:12:02 +00:00
parent a1e08d1298
commit 495757ffce
3 changed files with 43 additions and 36 deletions

View File

@@ -104,7 +104,11 @@ mkfifo rds_ctl
sudo ./pi_fm_rds -ctl rds_ctl
```
Then you can send “commands” to change PS, RT and TA:
At this point, Pi-FM-RDS waits until another program opens the named pipe in write mode
(for example `cat >rds_ctl` in the example below) before it starts transmitting.
You can use the named pipe to send “commands” to change PS, RT and TA. For instance, in
another terminal:
```
cat >rds_ctl
@@ -116,6 +120,10 @@ TA OFF
...
```
> [!TIP]
> The program that opens the named pipe in write mode can be started after Pi-FM-RDS
> (like above) or before (in which case Pi-FM-RDS does not have to wait at startup).
Every line must start with either `PS`, `RT` or `TA`, followed by one space character, and the desired value. Any other line format is silently ignored. `TA ON` switches the Traffic Announcement flag to *on*, any other value switches it to *off*.

View File

@@ -1,11 +1,8 @@
/*
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
@@ -19,7 +16,7 @@
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.
*/
@@ -42,8 +39,8 @@ 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 fd = open(filename, O_RDONLY);
if(fd < 0) return -1;
int flags;
flags = fcntl(fd, F_GETFL, 0);
@@ -89,7 +86,7 @@ int poll_control_pipe() {
return CONTROL_PIPE_TA_SET;
}
}
return -1;
}

View File

@@ -6,7 +6,7 @@
*
* See https://github.com/ChristopheJacquet/PiFmRds
*
* PI-FM-RDS: RaspberryPi FM transmitter, with RDS.
* PI-FM-RDS: RaspberryPi FM transmitter, with RDS.
*
* This file contains the VHF FM modulator. All credit goes to the original
* authors, Oliver Mattos and Oskar Weigl for the original idea, and to
@@ -34,7 +34,7 @@
* http://www.icrobotics.co.uk/wiki/index.php/Turning_the_Raspberry_Pi_Into_an_FM_Transmitter
*
* All credit to Oliver Mattos and Oskar Weigl for creating the original code.
*
*
* I have taken their idea and reworked it to use the Pi DMA engine, so
* reducing the CPU overhead for playing a .wav file from 100% to about 1.6%.
*
@@ -213,7 +213,7 @@ static struct {
unsigned bus_addr; /* From mem_lock() */
uint8_t *virt_addr; /* From mapmem() */
} mbox;
static volatile uint32_t *pwm_reg;
@@ -256,7 +256,7 @@ terminate(int num)
dma_reg[DMA_CS] = BCM2708_DMA_RESET;
udelay(10);
}
fm_mpx_close();
close_control_pipe();
@@ -267,7 +267,7 @@ terminate(int num)
}
printf("Terminating: cleanly deactivated the DMA engine and killed the carrier.\n");
exit(num);
}
@@ -328,7 +328,7 @@ int tx(uint32_t carrier_freq, char *audio_file, uint16_t pi, char *ps, char *rt,
sa.sa_handler = terminate;
sigaction(i, &sa, NULL);
}
dma_reg = map_peripheral(DMA_VIRT_BASE, DMA_LEN);
pwm_reg = map_peripheral(PWM_VIRT_BASE, PWM_LEN);
clk_reg = map_peripheral(CLK_VIRT_BASE, CLK_LEN);
@@ -352,7 +352,7 @@ int tx(uint32_t carrier_freq, char *audio_file, uint16_t pi, char *ps, char *rt,
fatal("Could not map memory.\n");
}
printf("virt_addr = %p\n", mbox.virt_addr);
// GPIO4 needs to be ALT FUNC 0 to output the clock
gpio_reg[GPFSEL0] = (gpio_reg[GPFSEL0] & ~(7 << 12)) | (4 << 12);
@@ -395,7 +395,7 @@ int tx(uint32_t carrier_freq, char *audio_file, uint16_t pi, char *ps, char *rt,
cbp--;
cbp->next = mem_virt_to_phys(mbox.virt_addr);
// Here we define the rate at which we want to update the GPCLK control
// Here we define the rate at which we want to update the GPCLK control
// register.
//
// Set the range to 2 bits. PLLD is at 500 MHz, therefore to get 228 kHz
@@ -405,7 +405,7 @@ int tx(uint32_t carrier_freq, char *audio_file, uint16_t pi, char *ps, char *rt,
//
// However the fractional part may have to be adjusted to take the actual
// frequency of your Pi's oscillator into account. For example on my Pi,
// the fractional part should be 1916 instead of 2012 to get exactly
// the fractional part should be 1916 instead of 2012 to get exactly
// 228 kHz. However RDS decoding is still okay even at 2012.
//
// So we use the 'ppm' parameter to compensate for the oscillator error
@@ -413,8 +413,8 @@ int tx(uint32_t carrier_freq, char *audio_file, uint16_t pi, char *ps, char *rt,
float divider = (PLLFREQ/(2000*228*(1.+ppm/1.e6)));
uint32_t idivider = (uint32_t) divider;
uint32_t fdivider = (uint32_t) ((divider - idivider)*pow(2, 12));
printf("ppm corr is %.4f, divider is %.4f (%d + %d*2^-12) [nominal 1096.4912].\n",
printf("ppm corr is %.4f, divider is %.4f (%d + %d*2^-12) [nominal 1096.4912].\n",
ppm, divider, idivider, fdivider);
pwm_reg[PWM_CTL] = 0;
@@ -434,7 +434,7 @@ int tx(uint32_t carrier_freq, char *audio_file, uint16_t pi, char *ps, char *rt,
udelay(10);
pwm_reg[PWM_CTL] = PWMCTL_USEF1 | PWMCTL_PWEN1;
udelay(10);
// Initialise the DMA
dma_reg[DMA_CS] = BCM2708_DMA_RESET;
@@ -444,7 +444,7 @@ int tx(uint32_t carrier_freq, char *audio_file, uint16_t pi, char *ps, char *rt,
dma_reg[DMA_DEBUG] = 7; // clear debug error flags
dma_reg[DMA_CS] = 0x10880001; // go, mid priority, wait for outstanding writes
uint32_t last_cb = (uint32_t)ctl->cb;
// Data structures for baseband data
@@ -454,7 +454,7 @@ int tx(uint32_t carrier_freq, char *audio_file, uint16_t pi, char *ps, char *rt,
// Initialize the baseband generator
if(fm_mpx_open(audio_file, DATA_SIZE) < 0) return 1;
// Initialize the RDS modulator
char myps[9] = {0};
set_rds_pi(pi);
@@ -462,7 +462,7 @@ int tx(uint32_t carrier_freq, char *audio_file, uint16_t pi, char *ps, char *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);
@@ -471,9 +471,11 @@ int tx(uint32_t carrier_freq, char *audio_file, uint16_t pi, char *ps, char *rt,
varying_ps = 1;
}
printf("RT: \"%s\"\n", rt);
// Initialize the control pipe reader
if(control_pipe) {
printf("Waiting for control pipe `%s` to be opened by the writer, e.g. "
"by running `cat >%s`.\n", control_pipe, control_pipe);
if(open_control_pipe(control_pipe) == 0) {
printf("Reading control commands on %s.\n", control_pipe);
} else {
@@ -481,8 +483,8 @@ int tx(uint32_t carrier_freq, char *audio_file, uint16_t pi, char *ps, char *rt,
control_pipe = NULL;
}
}
printf("Starting to transmit on %3.1f MHz.\n", carrier_freq/1e6);
for (;;) {
@@ -499,11 +501,11 @@ int tx(uint32_t carrier_freq, char *audio_file, uint16_t pi, char *ps, char *rt,
}
count++;
}
if(control_pipe && poll_control_pipe() == CONTROL_PIPE_PS_SET) {
varying_ps = 0;
}
usleep(5000);
uint32_t cur_cb = mem_phys_to_virt(dma_reg[DMA_CONBLK_AD]);
@@ -523,7 +525,7 @@ int tx(uint32_t carrier_freq, char *audio_file, uint16_t pi, char *ps, char *rt,
data_len = DATA_SIZE;
data_index = 0;
}
float dval = data[data_index] * (DEVIATION / 10.);
data_index++;
data_len--;
@@ -553,15 +555,15 @@ int main(int argc, char **argv) {
char *rt = "PiFmRds: live FM-RDS transmission from the RaspberryPi";
uint16_t pi = 0x1234;
float ppm = 0;
// Parse command-line arguments
for(int i=1; i<argc; i++) {
char *arg = argv[i];
char *param = NULL;
if(arg[0] == '-' && i+1 < argc) param = argv[i+1];
if((strcmp("-wav", arg)==0 || strcmp("-audio", arg)==0) && param != NULL) {
i++;
audio_file = param;
@@ -591,13 +593,13 @@ int main(int argc, char **argv) {
" [-ps ps_text] [-rt rt_text] [-ctl control_pipe]\n", arg);
}
}
// Set locale based on the environment variables. This is necessary to decode
// non-ASCII characters using mbtowc() in rds_strings.c.
char* locale = setlocale(LC_ALL, "");
printf("Locale set to %s.\n", locale);
int errcode = tx(carrier_freq, audio_file, pi, ps, rt, ppm, control_pipe);
terminate(errcode);
}