Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

carrier wave kill, raw mode #23

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down
15 changes: 11 additions & 4 deletions src/fm_mpx.c
Original file line number Diff line number Diff line change
Expand Up @@ -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))) {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -263,4 +270,4 @@ int fm_mpx_close() {
if(audio_buffer != NULL) free(audio_buffer);

return 0;
}
}
4 changes: 2 additions & 2 deletions src/fm_mpx.h
Original file line number Diff line number Diff line change
Expand Up @@ -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();
89 changes: 80 additions & 9 deletions src/pi_fm_rds.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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];

Expand Down Expand Up @@ -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};
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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++;
Expand All @@ -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);
}