This commit is contained in:
Ruben Lagrouw 2015-03-08 13:29:03 +00:00
commit 21a37e5df7
4 changed files with 96 additions and 15 deletions

View File

@ -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.

View File

@ -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;
}
}

View File

@ -21,6 +21,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
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();
extern int fm_mpx_close();

View File

@ -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<argc; i++) {
char *arg = argv[i];
char *param = NULL;
@ -536,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++;
@ -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);
}