All of lore.kernel.org
 help / color / mirror / Atom feed
* ham radio OSS duplex realtime mmap program.
@ 2003-09-26 11:26 Dr. med. Günther Montag
  2003-09-26 11:47 ` Paul Davis
                   ` (2 more replies)
  0 siblings, 3 replies; 13+ messages in thread
From: Dr. med. Günther Montag @ 2003-09-26 11:26 UTC (permalink / raw)
  To: alsa-devel; +Cc: hfterm-hackers

Hello
I work at "hfkernel" by Tom Sailer, a program for pactor/rtty (soundcard ham 
radio digimodes). It seems complicated, because it uses realtime scheduling, 
select(), mmap(), and runs in 3 threads. 
It was made in 1996 for OSS; I am trying to get it running with ALSA. 

It is unique thing because it can do 
Pactor without the expensive PTC (something like a radio modem), 
may be of interest for many hams outside Europe /USA.

I and friends see messages like
" 512 fragments passed since last wakeup", in endless loop, leading to 
crashes, seems to be xruns, not able to ctrl-alt-del, have to switch off 
machine.
.
What do You think, how can ALSA support it, or Do I have to rewrite it for 
ALSA.
I tried already with no success to say "Direct" and "non-block" in all 
combinations to /proc/asound/card0/pcm0p etc... 
If to rewrite, what function / ioctl matches
SNDCTL_DSP_GETISPACE...SNDCTL_DSP_GETOSPACE...
" ioctl(fd_audio, SNDCTL_DSP_GETIPTR, &cinfo) "
and 
" ioctl(fd_audio, SNDCTL_DSP_GETOPTR, &cinfo) " ?

The prog is at https//projects.sourceforge.net/hfterm.
Here is one of the important functions out of l1/user/oss.c my prog:
Thanks for Your ideas!

*****************************************************************************/

/*
 *      oss.c  --  Linux sound I/O.
 *
 *      Copyright (C) 1997  Thomas Sailer (sailer@ife.ee.ethz.ch)
 *        Swiss Federal Institute of Technology (ETH), Electronics Lab
 *
...
 *  This is the Linux realtime sound output driver
      
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <asm/byteorder.h>
#include <sys/soundcard.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <signal.h>
#include <endian.h>
#include <pthread.h>
#include "os.h"
#include "l1.h"
#include "l1user.h"

static int samples_remain = 0;
static int samples_count = 0;
static short *samples_ptr = NULL;

static int invert_ptt = 0;

static pthread_t thr_l1;

static float snd_corr;

#if __BYTE_ORDER == __BIG_ENDIAN
#define AUDIO_FMT AFMT_S16_BE
#else
#define AUDIO_FMT AFMT_S16_LE
#endif


static void *fdx_driver(void *name_audio)
{
        size_t pagesize = getpagesize();
        int apar, fd_audio, i;
	union {
		caddr_t v;
		short *s;
	} ibuf;
	caddr_t ibuf_ext;
	union {
		caddr_t v;
		short *s;
	} obuf;
	struct audio_buf_info iinfo, oinfo;
	unsigned int isize, osize;
	unsigned int ifragptr, ofragptr;
	fd_set rmask, wmask;
	struct count_info cinfo;
	unsigned int curfrag, lastfrag, nfrags;
	unsigned long long itime, otime, inc_fragment;
	l1_time_t inc_sample;
	int ptt_frames;
	short *s;
	
        if ((fd_audio = open(name_audio, O_RDWR, 0)) < 0)
                errstr(SEV_FATAL, "open");
        /*
         * configure audio
         */
        apar = AUDIO_FMT;
        if (ioctl(fd_audio, SNDCTL_DSP_SETFMT, &apar) == -1)
                errstr(SEV_FATAL, "ioctl: SNDCTL_DSP_SETFMT");
        if (apar != AUDIO_FMT) 
		errprintf(SEV_FATAL, "audio driver does not support the S16 format\n");
        apar = 0;
        if (ioctl(fd_audio, SNDCTL_DSP_STEREO, &apar) == -1)
                errstr(SEV_FATAL, "ioctl: SNDCTL_DSP_STEREO");
        if (apar != 0)
		errprintf(SEV_FATAL, "audio driver does not support mono\n");
        apar = SAMPLE_RATE;
        if (ioctl(fd_audio, SNDCTL_DSP_SPEED, &apar) == -1)
                errstr(SEV_FATAL, "ioctl: SNDCTL_DSP_SPEED");
	if (apar != SAMPLE_RATE) {
		if (abs(apar-SAMPLE_RATE) >= SAMPLE_RATE/100)
			errprintf(SEV_FATAL, "audio driver does not support 8kHz sampling 
frequency\n");
	}
	inc_sample = 1000000.0*snd_corr/apar;
	inc_fragment = 64*1000000.0*snd_corr/apar*(1<<24);
        ifragptr = 0;
	itime = 0;
	ofragptr = 1;
	otime = ofragptr * inc_fragment;
	ptt_frames = 0;
	lastfrag = 0;
        /*
         * set fragment sizes
         */
        apar = 0xffff0007U;
        if (ioctl(fd_audio, SNDCTL_DSP_SETFRAGMENT, &apar) == -1)
                errstr(SEV_FATAL, "ioctl: SNDCTL_DSP_SETFRAGMENT");
	if (ioctl(fd_audio, SNDCTL_DSP_GETOSPACE, &oinfo) == -1)
		errstr(SEV_FATAL, "ioctl: SNDCTL_DSP_GETOSPACE");
	osize = oinfo.fragstotal * oinfo.fragsize;
	if (ioctl(fd_audio, SNDCTL_DSP_GETISPACE, &iinfo) == -1)
		errstr(SEV_FATAL, "ioctl: SNDCTL_DSP_GETISPACE");
	isize = iinfo.fragstotal * iinfo.fragsize;
	if (EXCESS_FRAGS * iinfo.fragsize > pagesize)
		errprintf(SEV_FATAL, "OSS: input: fragment size %d times excess frags > page 
size %d\n",
			  iinfo.fragsize, pagesize);
	/*
         * mmap buffers
         *
	 * BSD people attention: you may need to uncomment the PROT_READ
	 * feedback welcome: sailer@ife.ee.ethz.ch
	 */
	if ((ibuf.v = mmap(NULL, pagesize+isize, PROT_READ | PROT_WRITE, 
			   MAP_ANON | MAP_PRIVATE, -1, 0)) == MAP_FAILED)
		errstr(SEV_FATAL, "mmap: MAP_ANONYMOUS");
	ibuf_ext = ibuf.v + isize;
	if (munmap(ibuf.v, isize))
		errstr(SEV_FATAL, "munmap: MAP_ANONYMOUS");
/* following line: '| PROT_WRITE ' helps against abort in my machine. Guenther 
*/
	if ((ibuf.v = mmap(ibuf.v, isize, PROT_READ | PROT_WRITE, MAP_FILE 
			  | MAP_SHARED | MAP_FIXED, 
			  fd_audio, 0)) == MAP_FAILED)
		errstr(SEV_FATAL, "mmap: PROT_READ");
	if ((obuf.v = mmap(NULL, osize, PROT_WRITE /* | PROT_READ*/, 
			   MAP_FILE | MAP_SHARED, fd_audio, 0)) == MAP_FAILED)
		errstr(SEV_FATAL, "mmap: PROT_WRITE");
	errprintf(SEV_INFO, "OSS: output: #frag: %d  fragsz: %d  totbuf: %d  bufaddr: 
%p\n"
		  "OSS: input: #frag: %d  fragsz: %d  totbuf: %d  bufaddr: %p  mempage: 
%p\n"
		  "OSS: sample time increment: %u  fragment time increment: %u\n",
		  oinfo.fragstotal, oinfo.fragsize, osize, obuf.s,
		  iinfo.fragstotal, iinfo.fragsize, isize, ibuf.s, ibuf_ext, 
		  (unsigned int)inc_sample, (unsigned int)(inc_fragment >> 24));
        /*
         * start playback/recording
         */
        apar = 0;
        if (ioctl(fd_audio, SNDCTL_DSP_SETTRIGGER, &apar) == -1)
                errstr(SEV_FATAL, "ioctl: SNDCTL_DSP_SETTRIGGER");
	apar = PCM_ENABLE_OUTPUT | PCM_ENABLE_INPUT;
        if (ioctl(fd_audio, SNDCTL_DSP_SETTRIGGER, &apar) == -1)
                errstr(SEV_FATAL, "ioctl: SNDCTL_DSP_SETTRIGGER");
	/*
	 * loop
	 */
	for (;;) {
		FD_ZERO(&rmask);
		FD_ZERO(&wmask);
		FD_SET(fd_audio, &rmask);
		FD_SET(fd_audio, &wmask);
		i = select(fd_audio+1, &rmask, &wmask, NULL, NULL);
		if (i < 0) 
			errstr(SEV_FATAL, "select");
		if (!FD_ISSET(fd_audio, &rmask) && !FD_ISSET(fd_audio, &wmask))
			continue;
		/*
		 * process input
		 */
		if (ioctl(fd_audio, SNDCTL_DSP_GETIPTR, &cinfo) == -1)
			errstr(SEV_FATAL, "ioctl: SNDCTL_DSP_GETIPTR");
		curfrag = cinfo.ptr / iinfo.fragsize;
		if (cinfo.blocks > 2)
			errprintf(SEV_WARNING, "%d fragments passed since last wakeup\n", 
cinfo.blocks);
		while (ifragptr != curfrag) {
			if (!ifragptr) {
				s = (short *)(ibuf.v + isize + iinfo.fragsize * ifragptr);
				memcpy(s, ibuf.v + iinfo.fragsize * ifragptr, iinfo.fragsize);
			} else
				s = (short *)(ibuf.v + iinfo.fragsize * ifragptr);
			if (samples_remain > 0) {
				i = 2*samples_remain;
				if (i > iinfo.fragsize)
					i = iinfo.fragsize;
				memcpy(samples_ptr, s, i);
				samples_ptr += i/2;
				samples_remain -= i/2;
			}
			l1_input_samples(itime >> 24, inc_sample, s, iinfo.fragsize/2);
			itime += inc_fragment;			
			ifragptr++;
			if (ifragptr >= iinfo.fragstotal)
				ifragptr = 0;
		}
		/*
		 * process output
		 */
		if (ioctl(fd_audio, SNDCTL_DSP_GETOPTR, &cinfo) == -1)
			errstr(SEV_FATAL, "ioctl: SNDCTL_DSP_GETOPTR");
		curfrag = cinfo.ptr / oinfo.fragsize;
		nfrags = oinfo.fragstotal + curfrag - lastfrag;
		lastfrag = curfrag;
		if (nfrags >= oinfo.fragstotal)
			nfrags -= oinfo.fragstotal;
		if (nfrags != cinfo.blocks)
			errprintf(SEV_WARNING, "OSS sound driver lost interrupt!\n");
		if (nfrags > 2)
			errprintf(SEV_WARNING, "%d fragments passed since last wakeup\n", nfrags);
		ptt_frames -= nfrags;
		if (ptt_frames < 0) {
			otime += (-ptt_frames) * inc_fragment;
			ofragptr -= ptt_frames;
			while (ofragptr >= oinfo.fragstotal)
				ofragptr -= oinfo.fragstotal;
			ptt_frames = 0;
			memset(obuf.s, 0, oinfo.fragsize * oinfo.fragstotal);
		}
		/* sanity check */
		if (!ptt_frames && ofragptr != (curfrag + 1) % oinfo.fragstotal)
			errprintf(SEV_FATAL, "output pointers inconsistent %u %u %lu\n",
				  ofragptr, curfrag, (unsigned long)(otime >> 24));
		while (ptt_frames < oinfo.fragstotal && ptt_frames <= 4 && 
		       l1_output_samples(otime >> 24, inc_sample, (short *)(obuf.v + 
oinfo.fragsize * ofragptr), 
					 oinfo.fragsize/2)) {
			ofragptr++;
			if (ofragptr >= oinfo.fragstotal)
				ofragptr = 0;
			ptt_frames++;
			otime += inc_fragment;
		}
		output_ptt(ptt_frames > 0);
	}
}

/* --------------------------------------------------------------------- */

Günther 
Safari.Doktor@addcom.de


-------------------------------------------------------
This sf.net email is sponsored by:ThinkGeek
Welcome to geek heaven.
http://thinkgeek.com/sf

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2003-10-03 11:55 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-09-26 11:26 ham radio OSS duplex realtime mmap program Dr. med. Günther Montag
2003-09-26 11:47 ` Paul Davis
2003-09-26 13:52   ` James Courtier-Dutton
2003-09-26 14:33     ` Jaroslav Kysela
2003-09-26 14:50       ` Paul Davis
2003-09-26 16:08         ` Abramo Bagnara
2003-09-26 16:14           ` Paul Davis
2003-09-26 18:36             ` Steve Harris
2003-09-30 11:39             ` Dr. med. Günther Montag
2003-10-03 11:55             ` bugs found in ham program Günther Montag
2003-09-26 14:23 ` ham radio OSS duplex realtime mmap program Jaroslav Kysela
2003-09-26 14:51 ` James Courtier-Dutton
2003-09-30 11:35   ` [Hfterm-hackers] " Dr. med. Günther Montag

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.