Skip to content
Permalink
Browse files

Date: Fri, 29 Oct 2004 11:47:09 +0200

From: Patrice Mandin
Subject: Reworked audio drivers for Atari platform

These are reworked audio drivers for the Atari platform.

Previous drivers were missing some features:
- Test external clock plugged to DSP port on Atari Falcon 030.
- Ability to select internal or external clock.

So now, I generate a list of frequencies available, with the master clock
and predivisor to use. One big caveat to this: I do not have an external
clock, so I hope it works.
  • Loading branch information
pmandin committed Oct 29, 2004
1 parent dfd5fc7 commit f93596fd90fec804aa45f941157929178574bfe5
@@ -41,6 +41,7 @@ Uint8 *SDL_MintAudio_audiobuf[2]; /* Pointers to buffers */
unsigned long SDL_MintAudio_audiosize; /* Length of audio buffer=spec->size */
unsigned short SDL_MintAudio_numbuf; /* Buffer to play */
unsigned short SDL_MintAudio_mutex;
unsigned long SDL_MintAudio_clocktics;
cookie_stfa_t *SDL_MintAudio_stfa;

/* The callback function, called by each driver whenever needed */
@@ -64,30 +65,57 @@ void SDL_MintAudio_Callback(void)
}
}

/* Simple function to search for the nearest frequency */
int SDL_MintAudio_SearchFrequency(_THIS, int falcon_codec, int desired_freq)
/* Add a new frequency/clock/predivisor to the current list */
void SDL_MintAudio_AddFrequency(_THIS, Uint32 frequency, Uint32 clock, Uint32 prediv)
{
int i, p;

if (MINTAUDIO_freqcount==MINTAUDIO_maxfreqs) {
return;
}

/* Search where to insert the frequency (highest first) */
for (p=0; p<MINTAUDIO_freqcount; p++) {
if (frequency > MINTAUDIO_frequencies[p].frequency) {
break;
}
}

/* Put all following ones farer */
if (MINTAUDIO_freqcount>0) {
for (i=MINTAUDIO_freqcount; i>p; i--) {
MINTAUDIO_frequencies[i].frequency = MINTAUDIO_frequencies[i-1].frequency;
MINTAUDIO_frequencies[i].masterclock = MINTAUDIO_frequencies[i-1].masterclock;
MINTAUDIO_frequencies[i].predivisor = MINTAUDIO_frequencies[i-1].predivisor;
}
}

/* And insert new one */
MINTAUDIO_frequencies[p].frequency = frequency;
MINTAUDIO_frequencies[p].masterclock = clock;
MINTAUDIO_frequencies[p].predivisor = prediv;

MINTAUDIO_freqcount++;
}

/* Search for the nearest frequency */
int SDL_MintAudio_SearchFrequency(_THIS, int desired_freq)
{
int i;

/* Only 1 freq ? */
if (MINTAUDIO_nfreq==1) {
return(MINTAUDIO_sfreq);
if (MINTAUDIO_freqcount==1) {
return 0;
}

/* Check the array */
for (i=MINTAUDIO_sfreq; i<MINTAUDIO_nfreq-1; i++) {
/* Remove unusable falcon codec frequencies */
if (falcon_codec) {
if ((i==6) || (i==8) || (i==10)) {
continue;
}
}

if (desired_freq >= ((MINTAUDIO_hardfreq[i]+MINTAUDIO_hardfreq[i+1])>>1)) {
for (i=0; i<MINTAUDIO_freqcount; i++) {
if (desired_freq >= ((MINTAUDIO_frequencies[i].frequency+
MINTAUDIO_frequencies[i+1].frequency)>>1)) {
return i;
}
}

/* Not in the array, give the latest */
return MINTAUDIO_nfreq-1;
return MINTAUDIO_freqcount-1;
}
@@ -35,17 +35,25 @@
/* Hidden "this" pointer for the audio functions */
#define _THIS SDL_AudioDevice *this

/* 16 predivisors with 3 clocks max. */
#define MINTAUDIO_maxfreqs (16*3)

typedef struct {
Uint32 frequency;
Uint32 masterclock;
Uint32 predivisor;
} mint_frequency_t;

struct SDL_PrivateAudioData {
Uint32 hardfreq[16]; /* Array of replay freqs of the hardware */
int sfreq; /* First number of freq to use in the array */
int nfreq; /* Number of freqs to use in the array */
mint_frequency_t frequencies[MINTAUDIO_maxfreqs];
int freq_count; /* Number of frequencies in the array */
int numfreq; /* Number of selected frequency */
};

/* Old variable names */
#define MINTAUDIO_hardfreq (this->hidden->hardfreq)
#define MINTAUDIO_sfreq (this->hidden->sfreq)
#define MINTAUDIO_nfreq (this->hidden->nfreq)

#define MINTAUDIO_frequencies (this->hidden->frequencies)
#define MINTAUDIO_freqcount (this->hidden->freq_count)
#define MINTAUDIO_numfreq (this->hidden->numfreq)

/* _MCH cookie (values>>16) */
@@ -110,14 +118,17 @@ extern unsigned long SDL_MintAudio_audiosize; /* Length of audio buffer=spec->s
extern unsigned short SDL_MintAudio_numbuf; /* Buffer to play */
extern unsigned short SDL_MintAudio_mutex;
extern cookie_stfa_t *SDL_MintAudio_stfa;
extern unsigned long SDL_MintAudio_clocktics;

/* Functions */
void SDL_MintAudio_Callback(void);
int SDL_MintAudio_SearchFrequency(_THIS, int falcon_codec, int desired_freq);
void SDL_MintAudio_AddFrequency(_THIS, Uint32 frequency, Uint32 clock, Uint32 prediv);
int SDL_MintAudio_SearchFrequency(_THIS, int desired_freq);

/* ASM interrupt functions */
void SDL_MintAudio_GsxbInterrupt(void);
void SDL_MintAudio_EmptyGsxbInterrupt(void);
void SDL_MintAudio_XbiosInterruptMeasureClock(void);
void SDL_MintAudio_XbiosInterrupt(void);
void SDL_MintAudio_Dma8Interrupt(void);
void SDL_MintAudio_StfaInterrupt(void);
@@ -53,7 +53,7 @@

/* Debug print info */
#define DEBUG_NAME "audio:dma8: "
#if 0
#if 1
#define DEBUG_PRINT(what) \
{ \
printf what; \
@@ -100,11 +100,12 @@ static int Audio_Available(void)
}

/* Check if we have 8 bits audio */
/*
if ((cookie_snd & SND_8BIT)==0) {
DEBUG_PRINT((DEBUG_NAME "no 8 bits sound\n"));
return(0);
}

*/
if ((cookie_mch>>16)>MCH_F30) {
DEBUG_PRINT((DEBUG_NAME "unknown 8 bits audio chip\n"));
return 0;
@@ -218,7 +219,7 @@ static void Mint_CloseAudio(_THIS)

static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec)
{
int i, masterprediv;
int i, masterprediv, sfreq;
unsigned long masterclock;

DEBUG_PRINT((DEBUG_NAME "asked: %d bits, ",spec->format & 0x00ff));
@@ -231,8 +232,7 @@ static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec)
spec->format = AUDIO_S8;

/* Calculate and select the closest frequency */
MINTAUDIO_nfreq=4;
MINTAUDIO_sfreq=0;
sfreq=0;
masterclock=MASTERCLOCK_STE;
masterprediv=MASTERPREDIV_STE;
switch(cookie_mch>>16) {
@@ -248,18 +248,27 @@ static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec)
break;
case MCH_F30:
masterclock=MASTERCLOCK_FALCON1;
masterprediv=MASTERPREDIV_FALCON<<1;
MINTAUDIO_nfreq=3;
MINTAUDIO_sfreq=1;
masterprediv=MASTERPREDIV_FALCON;
sfreq=1;
break;
}
for (i=MINTAUDIO_sfreq;i<MINTAUDIO_nfreq;i++) {
MINTAUDIO_hardfreq[i]=masterclock/(masterprediv*(1<<i));
DEBUG_PRINT((DEBUG_NAME "calc:freq(%d)=%lu\n", i, MINTAUDIO_hardfreq[i]));

MINTAUDIO_freqcount=0;
for (i=sfreq;i<4;i++) {
SDL_MintAudio_AddFrequency(this, masterclock/(masterprediv*(1<<i)), masterclock, i-sfreq);
}

MINTAUDIO_numfreq=SDL_MintAudio_SearchFrequency(this, 0, spec->freq);
spec->freq=MINTAUDIO_hardfreq[MINTAUDIO_numfreq];
#if 1
for (i=0; i<MINTAUDIO_freqcount; i++) {
DEBUG_PRINT((DEBUG_NAME "freq %d: %lu Hz, clock %lu, prediv %d\n",
i, MINTAUDIO_frequencies[i].frequency, MINTAUDIO_frequencies[i].masterclock,
MINTAUDIO_frequencies[i].predivisor
));
}
#endif

MINTAUDIO_numfreq=SDL_MintAudio_SearchFrequency(this, spec->freq);
spec->freq=MINTAUDIO_frequencies[MINTAUDIO_numfreq].frequency;

DEBUG_PRINT((DEBUG_NAME "obtained: %d bits, ",spec->format & 0x00ff));
DEBUG_PRINT(("signed=%d, ", ((spec->format & 0x8000)!=0)));
@@ -298,11 +307,11 @@ static void Mint_InitAudio(_THIS, SDL_AudioSpec *spec)
DMAAUDIO_IO.end_mid = (buffer>>8) & 255;
DMAAUDIO_IO.end_low = buffer & 255;

mode = 3-MINTAUDIO_numfreq;
mode = 3-MINTAUDIO_frequencies[MINTAUDIO_numfreq].predivisor;
if (spec->channels==1) {
mode |= 1<<7;
}
DMAAUDIO_IO.mode = mode;
DMAAUDIO_IO.sound_ctrl = mode;

/* Set interrupt */
Jdisint(MFP_DMASOUND);
@@ -21,9 +21,9 @@
*/

/*
DMA 8bits audio definitions
DMA 8bits and Falcon Codec audio definitions
Patrice Mandin
Patrice Mandin, Didier Méquignon
*/

#ifndef _SDL_mintaudio_dma8_h
@@ -57,8 +57,27 @@ struct DMAAUDIO_IO_S {

unsigned char dummy10[12];

unsigned char track_select; /* CODEC only */
unsigned char mode;
unsigned char track_ctrl; /* CODEC only */
unsigned char sound_ctrl;
unsigned short sound_data;
unsigned short sound_mask;

unsigned char dummy11[10];

unsigned short dev_ctrl;
unsigned short dest_ctrl;
unsigned short sync_div;
unsigned char track_rec;
unsigned char adderin_input;
unsigned char channel_input;
unsigned char channel_amplification;
unsigned char channel_reduction;

unsigned char dummy12[6];

unsigned char data_direction;
unsigned char dummy13;
unsigned char dev_data;
};
#define DMAAUDIO_IO ((*(volatile struct DMAAUDIO_IO_S *)DMAAUDIO_IO_BASE))

@@ -53,7 +53,7 @@

/* Debug print info */
#define DEBUG_NAME "audio:gsxb: "
#if 0
#if 1
#define DEBUG_PRINT(what) \
{ \
printf what; \
@@ -179,29 +179,21 @@ static void Mint_CloseAudio(_THIS)
/* Stop replay */
Buffoper(0);

DEBUG_PRINT((DEBUG_NAME "closeaudio: replay stopped\n"));

/* Uninstall interrupt */
if (NSetinterrupt(2, SI_NONE, SDL_MintAudio_EmptyGsxbInterrupt)<0) {
DEBUG_PRINT((DEBUG_NAME "NSetinterrupt() failed in close\n"));
}

DEBUG_PRINT((DEBUG_NAME "closeaudio: interrupt disabled\n"));

/* Wait if currently playing sound */
while (SDL_MintAudio_mutex != 0) {
}

DEBUG_PRINT((DEBUG_NAME "closeaudio: no more interrupt running\n"));

/* Clear buffers */
if (SDL_MintAudio_audiobuf[0]) {
Mfree(SDL_MintAudio_audiobuf[0]);
SDL_MintAudio_audiobuf[0] = SDL_MintAudio_audiobuf[1] = NULL;
}

DEBUG_PRINT((DEBUG_NAME "closeaudio: buffers freed\n"));

/* Unlock sound system */
Unlocksnd();
}
@@ -278,15 +270,22 @@ static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec)
}

/* Calculate and select the closest frequency */
MINTAUDIO_sfreq=1;
MINTAUDIO_nfreq=12;
for (i=MINTAUDIO_sfreq;i<MINTAUDIO_nfreq;i++) {
MINTAUDIO_hardfreq[i]=MASTERCLOCK_44K/(MASTERPREDIV_MILAN*(i+1));
DEBUG_PRINT((DEBUG_NAME "calc:freq(%d)=%lu\n", i, MINTAUDIO_hardfreq[i]));
MINTAUDIO_freqcount=0;
for (i=1;i<4;i++) {
SDL_MintAudio_AddFrequency(this, MASTERCLOCK_44K/(MASTERPREDIV_MILAN*(1<<i)), MASTERCLOCK_44K, (1<<i)-1);
}

MINTAUDIO_numfreq=SDL_MintAudio_SearchFrequency(this, 1, spec->freq);
spec->freq=MINTAUDIO_hardfreq[MINTAUDIO_numfreq];
#if 1
for (i=0; i<MINTAUDIO_freqcount; i++) {
DEBUG_PRINT((DEBUG_NAME "freq %d: %lu Hz, clock %lu, prediv %d\n",
i, MINTAUDIO_frequencies[i].frequency, MINTAUDIO_frequencies[i].masterclock,
MINTAUDIO_frequencies[i].predivisor
));
}
#endif

MINTAUDIO_numfreq=SDL_MintAudio_SearchFrequency(this, spec->freq);
spec->freq=MINTAUDIO_frequencies[MINTAUDIO_numfreq].frequency;

DEBUG_PRINT((DEBUG_NAME "obtained: %d bits, ",spec->format & 0x00ff));
DEBUG_PRINT(("signed=%d, ", ((spec->format & 0x8000)!=0)));
@@ -299,7 +298,7 @@ static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec)

static void Mint_InitAudio(_THIS, SDL_AudioSpec *spec)
{
int channels_mode;
int channels_mode, prediv;
void *buffer;

/* Stop currently playing sound */
@@ -333,7 +332,8 @@ static void Mint_InitAudio(_THIS, SDL_AudioSpec *spec)
DEBUG_PRINT((DEBUG_NAME "Setmode() failed\n"));
}

Devconnect(DMAPLAY, DAC, CLKEXT, MINTAUDIO_numfreq, 1);
prediv = MINTAUDIO_frequencies[MINTAUDIO_numfreq].predivisor;
Devconnect(DMAPLAY, DAC, CLKEXT, prediv, 1);

/* Set buffer */
buffer = SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf];
@@ -23,7 +23,7 @@
/*
Audio interrupts

Patrice Mandin
Patrice Mandin, Didier Méquignon
*/

.text
@@ -33,13 +33,15 @@
.globl _SDL_MintAudio_GsxbInterrupt
.globl _SDL_MintAudio_EmptyGsxbInterrupt
.globl _SDL_MintAudio_XbiosInterrupt
.globl _SDL_MintAudio_XbiosInterruptMeasureClock
.globl _SDL_MintAudio_Dma8Interrupt
.globl _SDL_MintAudio_StfaInterrupt

.globl _SDL_MintAudio_mutex
.globl _SDL_MintAudio_audiobuf
.globl _SDL_MintAudio_numbuf
.globl _SDL_MintAudio_audiosize
.globl _SDL_MintAudio_clocktics

.globl _SDL_MintAudio_stfa

@@ -94,6 +96,17 @@ _SDL_MintAudio_GsxbInterrupt:
_SDL_MintAudio_EmptyGsxbInterrupt:
rts

/*--- Xbios interrupt vector to measure Falcon external clock ---*/

_SDL_MintAudio_XbiosInterruptMeasureClock: /* 1 mS */

btst #0,0xFFFF8901:w /* state DMA sound */
beqs SDL_MintAudio_EndIntMeasure
addql #1,_SDL_MintAudio_clocktics
SDL_MintAudio_EndIntMeasure:
bclr #5,0xFFFFFA0F:w /* Clear service bit */
rte

/*--- Xbios interrupt vector ---*/

_SDL_MintAudio_XbiosInterrupt:

0 comments on commit f93596f

Please sign in to comment.