Nios® V/II Embedded Design Suite (EDS)
Support for Embedded Development Tools, Processors (SoCs and Nios® V/II processor), Embedded Development Suites (EDSs), Boot and Configuration, Operating Systems, C and C++
12589 Discussions

Audio Tone Generation on DE1-SOC Linux User Space

vimfulDang
Beginner
701 Views

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

0 Kudos
2 Replies
vimfulDang
Beginner
689 Views

I found the problem. The sampling rate does not match the hardware's

0 Kudos
EBERLAZARE_I_Intel
681 Views

Hi,


Glad you found the fix to your issue, I could not found any specific design example on this, but you may take a look this basic DSP exercise for your future reference:


ftp://ftp.intel.com/pub/fpgaup/pub/Intel_Material/Laboratory_Exercises/Digital_Logic/Verilog/lab12.pdf


0 Kudos
Reply