vimfulDang
New Contributor
5 years agoAudio Tone Generation on DE1-SOC Linux User Space
Hello, I'm having trouble generating sinusoidal tones to the Line Out in Linux User Space on DE1-SOC board. Attached is my code, I'm sure there's some fundamental concept that I'm missing so I'd appreciate the feedback.
#include <stdio.h> #include <unistd.h> #include <math.h> #include <fcntl.h> #include <sys/mman.h> #include "../address_map_arm.h" #include <signal.h> #define SAMPLE_RATE 48000 #define TWO_PI 6.28318531 static double note[13] = {261.626, 277.183, 293.665, 311.127, 329.628, 349.228, 369.994, 391.995, 415.305, 440.000, 466.164, 493.883, 523.251}; static unsigned int * audio_base_ptr; //Function Prototype void write_to_audio_port(double); volatile sig_atomic_t stop; void catchSIGINT (int signum) { stop = 1; } int main (void) { int fd = -1; int i = 0; stop = 0; void * LW_virtual; int nth_sample; double freq; signal(SIGINT, catchSIGINT); // Max volume when multiplied by sin() which ranges from -1 to 1; int vol = 0x7FFFFFF; if ((fd = open("/dev/mem", (O_RDWR | O_SYNC))) == -1) { printf("ERROR: could not open \"/dev/mem\"...\n"); return (-1); } LW_virtual = mmap(NULL, LW_BRIDGE_SPAN, (PROT_READ | PROT_WRITE), MAP_SHARED, fd, LW_BRIDGE_BASE); if (LW_virtual == NULL) { printf("ERROR: could not mmap()...\n"); close(fd); return (-1); } audio_base_ptr = (unsigned int *) (LW_virtual + AUDIO_BASE); //Clear Write FIFO & set back to zero *(audio_base_ptr) |= 0x8; *(audio_base_ptr) &= 0xFFFFFFF7; //printf("left:%#x right:\n", *(audio_base_ptr + 1) & 0xFF000000, *(audio_base_ptr + 1) & 0x00FF0000); for (i = 0; ((i < 13) && !stop); i++) { freq = note[i]; printf("Playing frequency: %f\n", freq); for (nth_sample = 0; nth_sample < 14400; nth_sample++) { write_to_audio_port(vol * sin(nth_sample * M_PI * freq / SAMPLE_RATE)); //printf("%d: %d\n", nth_sample, (int) (vol * sin(nth_sample * M_PI * freq / SAMPLE_RATE))); } } //Unmap printf("Unmapping\n"); if (munmap(LW_virtual, LW_BRIDGE_SPAN) != 0) { printf("ERROR: munmap() failed...\n"); return(-1); } close(fd); return 0; } void write_to_audio_port(double sample) { int write = 0; while ((write == 0) && !stop) { if ((*(audio_base_ptr + 1) & 0xFF00000) && (*(audio_base_ptr + 1) & 0x00FF000)) { *(audio_base_ptr + 2) = (int) sample; *(audio_base_ptr + 3) = (int) sample; write = 1; } } }