Re: Few Jornada 690 questions

Adam Wysocki via ArcaBit <[email protected]> Mon, 21 Aug 2006 21:23:04 +0200 (CEST)
Newsgroups gmane.os.netbsd.ports.hpcsh
Message-ID <[email protected]>
17.08.06 [email protected] wrote:

> There's no sound *card* in sh3 jornadas.  There's an on-chip 8-bit DAC
> and one of its channels is hooked to the speaker.  You need to feed
> the DAC directly from the CPU.  This means that you need to have 8K
> interrupts per second to play even crappy lo-fi 8KHz 8bit audio.

I tried to do it in userspace (I'm new to NetBSD so writing a custom 
driver could be kind of challenge for now) and even managed to output 
some sound (and learned the hard way that securelevel greater than 0 
prevents readwrite /dev/mem accesses), but it seems that there's no 
easy way to get the userspace code executed at 8000 Hz. NetBSD doesn't 
seem to have a realtime scheduler (seems strange, so maybe I'm wrong) 
and setitimer() and usleep() on this CPU just doesn't work at this 
frequency even when reniced to -20. Maximum archieved frequency, 
both using setitimer() and usleep(), was 32 Hz.

[gophi@hpcsh ~/src]$ make test && sudo nice -n -20 ./test
cc -O   -o test test.c
us=3122254 (should be 1000000), freq=32 (should be 100)

[gophi@hpcsh ~/src]$ make test2 && sudo nice -n -20 ./test2
cc -O   -o test2 test2.c
us=3119995 (should be 1000000), freq=32 (should be 100)

(test.c and test2.c attached)

> There is on-chip DMAC that can do timed transfers using internal 
> counter-timer, but attempts to use it wedge the machine ~immediately.

Seems promising. Have you tried it with a lower frequency than 8 kHz? 
Maybe it just didn't worked because of too high frequency. Do you have 
some details on this controller?

-- 
[ Adam Wysocki, www.chmurka.net, GSM: +48 514 710 213 ]
[ Software Development Department, ArcaBit Sp. z o.o. ]
[ Ul. Fortuny 9 :: 01-339 Warszawa :: www.arcabit.com ]
test.c (text/x-csrc, 878 B)
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <stdio.h>
#include <sys/time.h>

#define FREQ	100
#define NUM	FREQ

volatile int i = 0;

void sighnd(int signo)
{
	i++;
}

main()
{
	struct itimerval it;
	struct sigaction sa;
	struct timeval tv[2];
	unsigned long us;

	it.it_value.tv_sec = 0;
	it.it_value.tv_usec = 1000000L / FREQ;
	memcpy(&it.it_interval, &it.it_value, sizeof(it.it_interval));

	memset(&sa, 0, sizeof(sa));
	sa.sa_handler = sighnd;
	sigaction(SIGALRM, &sa, NULL);

	gettimeofday(&tv[0], NULL);
	setitimer(ITIMER_REAL, &it, NULL);

	while(i < NUM)
		pause();

	gettimeofday(&tv[1], NULL);

	us = (tv[1].tv_sec - tv[0].tv_sec) * 1000000L + (tv[1].tv_usec - tv[0].tv_usec);

	printf("us=%lu (should be %lu), freq=%lu (should be %lu)\n", 
		us, NUM * 1000000L / FREQ, 1000000L * NUM / us, FREQ);
}
test2.c (text/x-csrc, 505 B)
#include <unistd.h>
#include <stdio.h>
#include <sys/time.h>

#define FREQ	100
#define NUM	FREQ

main()
{
	struct timeval tv[2];
	int i = 0;
	unsigned long us;

	gettimeofday(&tv[0], NULL);

	while(i++ < NUM)
		usleep(1000000L / (FREQ * NUM));

	gettimeofday(&tv[1], NULL);

	us = (tv[1].tv_sec - tv[0].tv_sec) * 1000000L + (tv[1].tv_usec - tv[0].tv_usec);

	printf("us=%lu (should be %lu), freq=%lu (should be %lu)\n", 
		us, NUM * 1000000L / FREQ, 1000000L * NUM / us, FREQ);
}