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.
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
+}
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();
diff --git a/src/pi_fm_rds.c b/src/pi_fm_rds.c
index 4a414a3..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
@@ -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;
@@ -512,6 +513,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] [-raw]\n");
+}
int main(int argc, char **argv) {
char *audio_file = NULL;
@@ -521,9 +580,14 @@ 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
+ if(argc <= 1){
+ print_info();
+ exit(0);
+ }
for(int i=1; i 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++;
@@ -553,14 +617,21 @@ int main(int argc, char **argv) {
} else if(strcmp("-ctl", arg)==0 && param != NULL) {
i++;
control_pipe = param;
+ } else if(strcmp("-autokill", arg)==0) { //automatically kill carrierwave at exit
+ atexit(kill_fm);
+ } 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 {
- fatal("Unrecognised argument: %s\n"
- "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);
+ printf("Unrecognised argument: %s\n", arg);
+ print_info();
+ exit(0);
}
}
- 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);
}