From 438c6a9cb0006e88b8131b47f52dfb0078a3f25d Mon Sep 17 00:00:00 2001 From: Hatagashira Date: Sun, 22 Feb 2015 10:51:47 +0100 Subject: [PATCH 1/8] Added switches to kill the carrierwave Added switches to kill the carrier wave immediately or at exit. It just sets pin 4 to 1 and is probably needlessly complicated. Moved the argument info to a separate function. --- src/pi_fm_rds.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 69 insertions(+), 3 deletions(-) diff --git a/src/pi_fm_rds.c b/src/pi_fm_rds.c index 4a414a3..2ec34db 100644 --- a/src/pi_fm_rds.c +++ b/src/pi_fm_rds.c @@ -512,6 +512,64 @@ int tx(uint32_t carrier_freq, char *audio_file, uint16_t pi, char *ps, char *rt, return 0; } +#define BCM2708_PERI_BASE 0x20000000 +//#define GPIO_BASE (BCM2708_PERI_BASE + 0x200000) /* GPIO controller */ +#define INP_GPIO(g) *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3)) +#define OUT_GPIO(g) *(gpio+((g)/10)) |= (1<<(((g)%10)*3)) +#define GPIO_SET *(gpio+7) // sets bits which are 1 ignores bits which are 0 + +//#define PAGE_SIZE (4*1024) +#define BLOCK_SIZE (4*1024) + +int mem_fd; +void *gpio_map; +// I/O access +volatile unsigned *gpio; + +void setup_io() +{ + /* open /dev/mem */ + if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) { + printf("can't open /dev/mem \n"); + exit(-1); + } + + /* mmap GPIO */ + gpio_map = mmap( + NULL, //Any adddress in our space will do + BLOCK_SIZE, //Map length + PROT_READ|PROT_WRITE,// Enable reading & writting to mapped memory + MAP_SHARED, //Shared with other processes + mem_fd, //File to map + GPIO_BASE //Offset to GPIO peripheral + ); + + close(mem_fd); //No need to keep mem_fd open after mmap + + if (gpio_map == MAP_FAILED) { + printf("mmap error %d\n", (int)gpio_map);//errno also set! + exit(-1); + } + + // Always use volatile pointer! + gpio = (volatile unsigned *)gpio_map; + + +} // setup_io + +void kill_fm(){ + setup_io(); + INP_GPIO(4); // must use INP_GPIO before we can use OUT_GPIO + OUT_GPIO(4); + GPIO_SET = 1<<4; + printf("FM Transmission terminated.\n"); +} + +void print_info(){ + printf("Syntax: pi_fm_rds [-freq freq] [-audio file] [-ppm ppm_error] [-pi pi_code]\n" + " [-ps ps_text] [-rt rt_text] [-ctl control_pipe] [-autokill]\n" + " [-kill]\n"); +} int main(int argc, char **argv) { char *audio_file = NULL; @@ -524,6 +582,10 @@ int main(int argc, char **argv) { // Parse command-line arguments + if(argc <= 1){ + print_info(); + exit(0); + } for(int i=1; i Date: Sun, 22 Feb 2015 10:56:05 +0100 Subject: [PATCH 2/8] Update pi_fm_rds.c --- src/pi_fm_rds.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pi_fm_rds.c b/src/pi_fm_rds.c index 2ec34db..ff62f1d 100644 --- a/src/pi_fm_rds.c +++ b/src/pi_fm_rds.c @@ -621,6 +621,7 @@ int main(int argc, char **argv) { kill_fm(); terminate(0); } else { + printf("Unrecognised argument: %s\n", arg); print_info(); exit(0); } From 9e964c66867853bcd2f707fcc8643358bcc383c8 Mon Sep 17 00:00:00 2001 From: Hatagashira Date: Sun, 22 Feb 2015 13:43:01 +0100 Subject: [PATCH 3/8] Added "raw mode" and Japanese FM band compatibility Added "raw mode". Raw mode expects no header, 44100HZ bitrate, 2 channels and PCM 16 format. --- src/pi_fm_rds.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/pi_fm_rds.c b/src/pi_fm_rds.c index ff62f1d..16ec7f6 100644 --- a/src/pi_fm_rds.c +++ b/src/pi_fm_rds.c @@ -271,7 +271,7 @@ map_peripheral(uint32_t base, uint32_t len) #define DATA_SIZE 5000 -int tx(uint32_t carrier_freq, char *audio_file, uint16_t pi, char *ps, char *rt, float ppm, char *control_pipe) { +int tx(uint32_t carrier_freq, char *audio_file, uint16_t pi, char *ps, char *rt, float ppm, char *control_pipe, int raw) { int i, fd, pid; char pagemap_fn[64]; @@ -421,7 +421,7 @@ int tx(uint32_t carrier_freq, char *audio_file, uint16_t pi, char *ps, char *rt, int data_index = 0; // Initialize the baseband generator - if(fm_mpx_open(audio_file, DATA_SIZE) < 0) return 1; + if(fm_mpx_open(audio_file, DATA_SIZE, raw) < 0) return 1; // Initialize the RDS modulator char myps[9] = {0}; @@ -486,7 +486,8 @@ int tx(uint32_t carrier_freq, char *audio_file, uint16_t pi, char *ps, char *rt, // get more baseband samples if necessary if(data_len == 0) { if( fm_mpx_get_samples(data) < 0 ) { - terminate(0); + //terminate(0); + return 0; } data_len = DATA_SIZE; data_index = 0; @@ -579,6 +580,7 @@ int main(int argc, char **argv) { char *rt = "PiFmRds: live FM-RDS transmission from the RaspberryPi"; uint16_t pi = 0x1234; float ppm = 0; + int raw = 0; // Parse command-line arguments @@ -598,7 +600,7 @@ int main(int argc, char **argv) { } else if(strcmp("-freq", arg)==0 && param != NULL) { i++; carrier_freq = 1e6 * atof(param); - if(carrier_freq < 87500000 || carrier_freq > 108000000) + if(carrier_freq < 76000000 || carrier_freq > 108000000) fatal("Incorrect frequency specification. Must be in megahertz, of the form 107.9\n"); } else if(strcmp("-pi", arg)==0 && param != NULL) { i++; @@ -620,6 +622,8 @@ int main(int argc, char **argv) { } else if(strcmp("-kill", arg)==0) { //kill carrierwave now and exit kill_fm(); terminate(0); + } else if(strcmp("-raw", arg)==0) { //expect raw input of 44.1khz, 2 channels, 16 bit pcm. + raw = 1; } else { printf("Unrecognised argument: %s\n", arg); print_info(); @@ -627,7 +631,7 @@ int main(int argc, char **argv) { } } - int errcode = tx(carrier_freq, audio_file, pi, ps, rt, ppm, control_pipe); + int errcode = tx(carrier_freq, audio_file, pi, ps, rt, ppm, control_pipe, raw); terminate(errcode); } From 01fd4dbe0cf0eaf67f88830f72309aa09f8dbc16 Mon Sep 17 00:00:00 2001 From: Hatagashira Date: Sun, 22 Feb 2015 13:44:03 +0100 Subject: [PATCH 4/8] Added raw mode --- src/fm_mpx.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/fm_mpx.h b/src/fm_mpx.h index 81b61be..c65c69c 100644 --- a/src/fm_mpx.h +++ b/src/fm_mpx.h @@ -21,6 +21,6 @@ along with this program. If not, see . */ -extern int fm_mpx_open(char *filename, size_t len); +extern int fm_mpx_open(char *filename, size_t len, int raw); extern int fm_mpx_get_samples(float *mpx_buffer); -extern int fm_mpx_close(); \ No newline at end of file +extern int fm_mpx_close(); From 3ce9eabefb5b44eab5342094a05ca4d41f8147b8 Mon Sep 17 00:00:00 2001 From: Hatagashira Date: Sun, 22 Feb 2015 13:45:13 +0100 Subject: [PATCH 5/8] Added raw mode --- src/fm_mpx.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/fm_mpx.c b/src/fm_mpx.c index fd0b7fa..b0207dc 100644 --- a/src/fm_mpx.c +++ b/src/fm_mpx.c @@ -80,13 +80,19 @@ float *alloc_empty_buffer(size_t length) { } -int fm_mpx_open(char *filename, size_t len) { +int fm_mpx_open(char *filename, size_t len, int raw) { length = len; if(filename != NULL) { // Open the input file SF_INFO sfinfo; + if(raw){ + sfinfo.format = SF_FORMAT_RAW | SF_FORMAT_PCM_16; + sfinfo.samplerate = 44100; + sfinfo.channels = 2; + } + // stdin or file on the filesystem? if(filename[0] == '-') { if(! (inf = sf_open_fd(fileno(stdin), SFM_READ, &sfinfo, 0))) { @@ -177,8 +183,9 @@ int fm_mpx_get_samples(float *mpx_buffer) { } if(audio_len == 0) { if( sf_seek(inf, 0, SEEK_SET) < 0 ) { - fprintf(stderr, "Could not rewind in audio file, terminating\n"); - return -1; + //fprintf(stderr, "Could not rewind in audio file, terminating\n"); + //return -1; + return 0; } } else { break; @@ -263,4 +270,4 @@ int fm_mpx_close() { if(audio_buffer != NULL) free(audio_buffer); return 0; -} \ No newline at end of file +} From 551e71789e5fea98142be7706d61ef20a1a07e26 Mon Sep 17 00:00:00 2001 From: Hatagashira Date: Sun, 22 Feb 2015 14:38:57 +0100 Subject: [PATCH 6/8] included new arguments --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index c79410f..c5cdf12 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,9 @@ All arguments are optional: * `-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. +* `-autokill` stop broadcasting the carrier wave at exit. +* `-kill` stop any ongoing broadcast, reset the DMA controller and exit. Do not use while an instance is running! +* `-raw` raw mode expects 44100HZ bitrate, 2 channels and PCM 16 bit. 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. From c4d40b801872ed10796e886b5eb90d351d21217b Mon Sep 17 00:00:00 2001 From: Hatagashira Date: Mon, 23 Feb 2015 15:44:30 +0100 Subject: [PATCH 7/8] added -raw to print_info() because it's nice to have a _complete_ list of arguments... hehe. --- src/pi_fm_rds.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pi_fm_rds.c b/src/pi_fm_rds.c index 16ec7f6..aedf1f2 100644 --- a/src/pi_fm_rds.c +++ b/src/pi_fm_rds.c @@ -569,7 +569,7 @@ void kill_fm(){ void print_info(){ printf("Syntax: pi_fm_rds [-freq freq] [-audio file] [-ppm ppm_error] [-pi pi_code]\n" " [-ps ps_text] [-rt rt_text] [-ctl control_pipe] [-autokill]\n" - " [-kill]\n"); + " [-kill] [-raw]\n"); } int main(int argc, char **argv) { From 8142f123e1115039c98c4ec2abaee408f00a2c2e Mon Sep 17 00:00:00 2001 From: Ruben Lagrouw Date: Sat, 7 Mar 2015 21:53:59 +0100 Subject: [PATCH 8/8] Added todo comment --- src/pi_fm_rds.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pi_fm_rds.c b/src/pi_fm_rds.c index aedf1f2..2d9676d 100644 --- a/src/pi_fm_rds.c +++ b/src/pi_fm_rds.c @@ -118,7 +118,7 @@ #define DMA_CS (0x00/4) #define DMA_CONBLK_AD (0x04/4) #define DMA_DEBUG (0x20/4) - +//TODO use different DMA channel: DMA0 is used by PCM audio. #define DMA_BASE 0x20007000 #define DMA_LEN 0x24 #define PWM_BASE 0x2020C000