Mercurial > sdl-ios-xcode
comparison src/audio/mint/SDL_mintaudio_xbios.c @ 961:185acc07127a
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.
author | Patrice Mandin <patmandin@gmail.com> |
---|---|
date | Fri, 29 Oct 2004 09:56:53 +0000 |
parents | b8d311d90021 |
children | 176240cf4405 |
comparison
equal
deleted
inserted
replaced
960:eec28a5278be | 961:185acc07127a |
---|---|
22 | 22 |
23 /* | 23 /* |
24 MiNT audio driver | 24 MiNT audio driver |
25 using XBIOS functions (Falcon) | 25 using XBIOS functions (Falcon) |
26 | 26 |
27 Patrice Mandin | 27 Patrice Mandin, Didier Méquignon |
28 */ | 28 */ |
29 | 29 |
30 #include <stdlib.h> | 30 #include <stdlib.h> |
31 #include <stdio.h> | 31 #include <stdio.h> |
32 #include <string.h> | 32 #include <string.h> |
33 #include <unistd.h> | |
33 | 34 |
34 /* Mint includes */ | 35 /* Mint includes */ |
35 #include <mint/osbind.h> | 36 #include <mint/osbind.h> |
36 #include <mint/falcon.h> | 37 #include <mint/falcon.h> |
37 #include <mint/cookie.h> | 38 #include <mint/cookie.h> |
43 #include "SDL_sysaudio.h" | 44 #include "SDL_sysaudio.h" |
44 | 45 |
45 #include "SDL_atarimxalloc_c.h" | 46 #include "SDL_atarimxalloc_c.h" |
46 | 47 |
47 #include "SDL_mintaudio.h" | 48 #include "SDL_mintaudio.h" |
49 #include "SDL_mintaudio_dma8.h" | |
48 | 50 |
49 /*--- Defines ---*/ | 51 /*--- Defines ---*/ |
50 | 52 |
51 #define MINT_AUDIO_DRIVER_NAME "mint_xbios" | 53 #define MINT_AUDIO_DRIVER_NAME "mint_xbios" |
52 | 54 |
53 /* Debug print info */ | 55 /* Debug print info */ |
54 #define DEBUG_NAME "audio:xbios: " | 56 #define DEBUG_NAME "audio:xbios: " |
55 #if 0 | 57 #if 1 |
56 #define DEBUG_PRINT(what) \ | 58 #define DEBUG_PRINT(what) \ |
57 { \ | 59 { \ |
58 printf what; \ | 60 printf what; \ |
59 } | 61 } |
60 #else | 62 #else |
184 | 186 |
185 /* Unlock sound system */ | 187 /* Unlock sound system */ |
186 Unlocksnd(); | 188 Unlocksnd(); |
187 } | 189 } |
188 | 190 |
191 /* Falcon XBIOS implementation of Devconnect() is buggy with external clock */ | |
192 static void Devconnect2(int src, int dst, int sclk, int pre) | |
193 { | |
194 static const unsigned short MASK1[3] = { 0, 0x6000, 0 }; | |
195 static const unsigned short MASK2[4] = { 0xFFF0, 0xFF8F, 0xF0FF, 0x0FFF }; | |
196 static const unsigned short INDEX1[4] = { 1, 3, 5, 7 }; | |
197 static const unsigned short INDEX2[4] = { 0, 2, 4, 6 }; | |
198 unsigned short sync_div,dev_ctrl,dest_ctrl; | |
199 void *oldstack; | |
200 | |
201 if (dst==0) { | |
202 return; | |
203 } | |
204 | |
205 oldstack=(void *)Super(0); | |
206 | |
207 dev_ctrl = DMAAUDIO_IO.dev_ctrl; | |
208 dest_ctrl = DMAAUDIO_IO.dest_ctrl; | |
209 dev_ctrl &= MASK2[src]; | |
210 | |
211 if (src==ADC) { | |
212 dev_ctrl |= MASK1[sclk]; | |
213 } else { | |
214 dev_ctrl |= (INDEX1[sclk] << (src<<4)); | |
215 } | |
216 | |
217 if (dst & DMAREC) { | |
218 dest_ctrl &= 0xFFF0; | |
219 dest_ctrl |= INDEX1[src]; | |
220 } | |
221 | |
222 if (dst & DSPRECV) { | |
223 dest_ctrl &= 0xFF8F; | |
224 dest_ctrl |= (INDEX1[src]<<4); | |
225 } | |
226 | |
227 if (dst & EXTOUT) { | |
228 dest_ctrl &= 0xF0FF; | |
229 dest_ctrl |= (INDEX1[src]<<8); | |
230 } | |
231 | |
232 if (dst & DAC) { | |
233 dev_ctrl &= 0x0FFF; | |
234 dev_ctrl |= MASK1[sclk]; | |
235 dest_ctrl &= 0x0FFF; | |
236 dest_ctrl |= (INDEX2[src]<<12); | |
237 } | |
238 | |
239 sync_div = DMAAUDIO_IO.sync_div; | |
240 if (sclk==CLKEXT) { | |
241 pre<<=8; | |
242 sync_div &= 0xF0FF; | |
243 } else { | |
244 sync_div &= 0xFFF0; | |
245 } | |
246 sync_div |= pre; | |
247 | |
248 DMAAUDIO_IO.dev_ctrl = dev_ctrl; | |
249 DMAAUDIO_IO.dest_ctrl = dest_ctrl; | |
250 DMAAUDIO_IO.sync_div = sync_div; | |
251 | |
252 Super(oldstack); | |
253 } | |
254 | |
255 static Uint32 Mint_CheckExternalClock(void) | |
256 { | |
257 #define SIZE_BUF_CLOCK_MEASURE (44100/10) | |
258 | |
259 unsigned long cookie_snd; | |
260 Uint32 masterclock; | |
261 char *buffer; | |
262 int i; | |
263 | |
264 /* DSP present with its GPIO port ? */ | |
265 if (Getcookie(C__SND, &cookie_snd) == C_NOTFOUND) { | |
266 return 0; | |
267 } | |
268 if ((cookie_snd & SND_DSP)==0) { | |
269 return 0; | |
270 } | |
271 | |
272 buffer = Atari_SysMalloc(SIZE_BUF_CLOCK_MEASURE, MX_STRAM); | |
273 if (buffer==NULL) { | |
274 DEBUG_PRINT((DEBUG_NAME "Not enough memory for the measure\n")); | |
275 return 0; | |
276 } | |
277 memset(buffer, 0, SIZE_BUF_CLOCK_MEASURE); | |
278 | |
279 masterclock=0; | |
280 | |
281 Buffoper(0); | |
282 Settracks(0,0); | |
283 Setmontracks(0); | |
284 Setmode(MONO8); | |
285 Jdisint(MFP_TIMERA); | |
286 | |
287 for (i=0; i<2; i++) { | |
288 Gpio(GPIO_SET,7); /* DSP port gpio outputs */ | |
289 Gpio(GPIO_WRITE,2+i); /* 22.5792/24.576 MHz for 44.1/48KHz */ | |
290 Devconnect2(DMAPLAY, DAC, CLKEXT, CLK50K); /* Matrix and clock source */ | |
291 Setbuffer(0, buffer, buffer + SIZE_BUF_CLOCK_MEASURE); /* Set buffer */ | |
292 Xbtimer(XB_TIMERA, 5, 38, SDL_MintAudio_XbiosInterruptMeasureClock); /* delay mode timer A, prediv /64, 1KHz */ | |
293 Jenabint(MFP_TIMERA); | |
294 SDL_MintAudio_clocktics = 0; | |
295 Buffoper(SB_PLA_ENA); | |
296 usleep(110000); | |
297 | |
298 if((Buffoper(-1) & 1)==0) { | |
299 if (SDL_MintAudio_clocktics) { | |
300 unsigned long khz; | |
301 | |
302 khz = ((SIZE_BUF_CLOCK_MEASURE/SDL_MintAudio_clocktics) +1) & 0xFFFFFFFE; | |
303 DEBUG_PRINT((DEBUG_NAME "measure %d: freq=%lu KHz\n", i+1, khz)); | |
304 | |
305 if (i==0) { | |
306 if(khz==44) { | |
307 masterclock = MASTERCLOCK_44K; | |
308 } | |
309 } else { | |
310 if(khz==48) { | |
311 masterclock = MASTERCLOCK_48K; | |
312 } | |
313 } | |
314 } else { | |
315 DEBUG_PRINT((DEBUG_NAME "No measure\n")); | |
316 } | |
317 } else { | |
318 DEBUG_PRINT((DEBUG_NAME "No SDMA clock\n")); | |
319 } | |
320 | |
321 Buffoper(0); /* stop */ | |
322 Jdisint(MFP_TIMERA); /* Uninstall interrupt */ | |
323 if (masterclock == 0) | |
324 break; | |
325 } | |
326 | |
327 Mfree(buffer); | |
328 return masterclock; | |
329 } | |
330 | |
189 static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec) | 331 static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec) |
190 { | 332 { |
191 int i; | 333 int i; |
334 Uint32 extclock; | |
192 | 335 |
193 DEBUG_PRINT((DEBUG_NAME "asked: %d bits, ",spec->format & 0x00ff)); | 336 DEBUG_PRINT((DEBUG_NAME "asked: %d bits, ",spec->format & 0x00ff)); |
194 DEBUG_PRINT(("signed=%d, ", ((spec->format & 0x8000)!=0))); | 337 DEBUG_PRINT(("signed=%d, ", ((spec->format & 0x8000)!=0))); |
195 DEBUG_PRINT(("big endian=%d, ", ((spec->format & 0x1000)!=0))); | 338 DEBUG_PRINT(("big endian=%d, ", ((spec->format & 0x1000)!=0))); |
196 DEBUG_PRINT(("channels=%d, ", spec->channels)); | 339 DEBUG_PRINT(("channels=%d, ", spec->channels)); |
200 if ((spec->format & 0x00ff)==16) { | 343 if ((spec->format & 0x00ff)==16) { |
201 spec->format |= 0x1000; /* Audio is always big endian */ | 344 spec->format |= 0x1000; /* Audio is always big endian */ |
202 spec->channels=2; /* 16 bits always stereo */ | 345 spec->channels=2; /* 16 bits always stereo */ |
203 } | 346 } |
204 | 347 |
205 /* FIXME: check for an external clock */ | 348 extclock=Mint_CheckExternalClock(); |
206 MINTAUDIO_sfreq=1; | 349 |
207 MINTAUDIO_nfreq=12; | 350 /* Standard clocks */ |
208 for (i=MINTAUDIO_sfreq;i<MINTAUDIO_nfreq;i++) { | 351 MINTAUDIO_freqcount=0; |
209 MINTAUDIO_hardfreq[i]=MASTERCLOCK_FALCON1/(MASTERPREDIV_FALCON*(i+1)); | 352 for (i=1;i<12;i++) { |
210 DEBUG_PRINT((DEBUG_NAME "calc:freq(%d)=%lu\n", i, MINTAUDIO_hardfreq[i])); | 353 /* Remove unusable Falcon codec predivisors */ |
211 } | 354 if ((i==6) || (i==8) || (i==10)) { |
212 | 355 continue; |
213 MINTAUDIO_numfreq=SDL_MintAudio_SearchFrequency(this, 1, spec->freq); | 356 } |
214 spec->freq=MINTAUDIO_hardfreq[MINTAUDIO_numfreq]; | 357 SDL_MintAudio_AddFrequency(this, MASTERCLOCK_FALCON1/(MASTERPREDIV_FALCON*(i+1)), MASTERCLOCK_FALCON1, i); |
358 } | |
359 | |
360 if (extclock>0) { | |
361 for (i=1; i<4; i++) { | |
362 SDL_MintAudio_AddFrequency(this, extclock/(MASTERPREDIV_FALCON*(1<<i)), extclock, (1<<i)-1); | |
363 } | |
364 } | |
365 | |
366 #if 1 | |
367 for (i=0; i<MINTAUDIO_freqcount; i++) { | |
368 DEBUG_PRINT((DEBUG_NAME "freq %d: %lu Hz, clock %lu, prediv %d\n", | |
369 i, MINTAUDIO_frequencies[i].frequency, MINTAUDIO_frequencies[i].masterclock, | |
370 MINTAUDIO_frequencies[i].predivisor | |
371 )); | |
372 } | |
373 #endif | |
374 | |
375 MINTAUDIO_numfreq=SDL_MintAudio_SearchFrequency(this, spec->freq); | |
376 spec->freq=MINTAUDIO_frequencies[MINTAUDIO_numfreq].frequency; | |
215 | 377 |
216 DEBUG_PRINT((DEBUG_NAME "obtained: %d bits, ",spec->format & 0x00ff)); | 378 DEBUG_PRINT((DEBUG_NAME "obtained: %d bits, ",spec->format & 0x00ff)); |
217 DEBUG_PRINT(("signed=%d, ", ((spec->format & 0x8000)!=0))); | 379 DEBUG_PRINT(("signed=%d, ", ((spec->format & 0x8000)!=0))); |
218 DEBUG_PRINT(("big endian=%d, ", ((spec->format & 0x1000)!=0))); | 380 DEBUG_PRINT(("big endian=%d, ", ((spec->format & 0x1000)!=0))); |
219 DEBUG_PRINT(("channels=%d, ", spec->channels)); | 381 DEBUG_PRINT(("channels=%d, ", spec->channels)); |
222 return 0; | 384 return 0; |
223 } | 385 } |
224 | 386 |
225 static void Mint_InitAudio(_THIS, SDL_AudioSpec *spec) | 387 static void Mint_InitAudio(_THIS, SDL_AudioSpec *spec) |
226 { | 388 { |
227 int channels_mode; | 389 int channels_mode, dmaclock, prediv; |
228 void *buffer; | 390 void *buffer; |
229 | 391 |
230 /* Stop currently playing sound */ | 392 /* Stop currently playing sound */ |
231 Buffoper(0); | 393 Buffoper(0); |
232 | 394 |
247 } | 409 } |
248 if (Setmode(channels_mode)<0) { | 410 if (Setmode(channels_mode)<0) { |
249 DEBUG_PRINT((DEBUG_NAME "Setmode() failed\n")); | 411 DEBUG_PRINT((DEBUG_NAME "Setmode() failed\n")); |
250 } | 412 } |
251 | 413 |
252 /* FIXME: select an external clock */ | 414 dmaclock = MINTAUDIO_frequencies[MINTAUDIO_numfreq].masterclock; |
253 | 415 prediv = MINTAUDIO_frequencies[MINTAUDIO_numfreq].predivisor; |
254 Devconnect(DMAPLAY, DAC, CLK25M, MINTAUDIO_numfreq, 1); | 416 if (dmaclock != MASTERCLOCK_FALCON1) { |
255 DEBUG_PRINT((DEBUG_NAME "25.175 MHz clock selected, prescaler %d\n", MINTAUDIO_numfreq)); | 417 Gpio(GPIO_SET,7); /* DSP port gpio outputs */ |
418 if (dmaclock == MASTERCLOCK_44K) { | |
419 Gpio(GPIO_WRITE,2); /* 22.5792 MHz for 44.1KHz */ | |
420 } else { | |
421 Gpio(GPIO_WRITE,3); /* 24.576 MHz for 48KHz */ | |
422 } | |
423 Devconnect2(DMAPLAY, DAC, CLKEXT, prediv); | |
424 } else { | |
425 Devconnect(DMAPLAY, DAC, CLK25M, prediv, 1); | |
426 } | |
256 | 427 |
257 /* Set buffer */ | 428 /* Set buffer */ |
258 buffer = SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf]; | 429 buffer = SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf]; |
259 if (Setbuffer(0, buffer, buffer + spec->size)<0) { | 430 if (Setbuffer(0, buffer, buffer + spec->size)<0) { |
260 DEBUG_PRINT((DEBUG_NAME "Setbuffer() failed\n")); | 431 DEBUG_PRINT((DEBUG_NAME "Setbuffer() failed\n")); |