Use MiNT thread to update DMA pointers instead of unusable MFP interrupt
authorPatrice Mandin <patmandin@gmail.com>
Wed, 10 Aug 2005 13:29:49 +0000
changeset 1111 12c49532be00
parent 1110 b6fdf299a2f3
child 1112 6ded3dd929f5
Use MiNT thread to update DMA pointers instead of unusable MFP interrupt
src/audio/mint/SDL_mintaudio.c
src/audio/mint/SDL_mintaudio.h
src/audio/mint/SDL_mintaudio_mcsn.c
src/audio/mint/SDL_mintaudio_xbios.c
--- a/src/audio/mint/SDL_mintaudio.c	Tue Aug 09 07:28:35 2005 +0000
+++ b/src/audio/mint/SDL_mintaudio.c	Wed Aug 10 13:29:49 2005 +0000
@@ -27,6 +27,11 @@
 */
 
 #include <string.h>
+#include <unistd.h>
+
+#include <mint/osbind.h>
+#include <mint/falcon.h>
+#include <mint/mintbind.h>
 
 #include "SDL_types.h"
 #include "SDL_audio.h"
@@ -44,6 +49,12 @@
 unsigned long SDL_MintAudio_clocktics;
 cookie_stfa_t	*SDL_MintAudio_stfa;
 
+/* MiNT thread variables */
+SDL_bool SDL_MintAudio_mint_present;
+SDL_bool SDL_MintAudio_quit_thread;
+SDL_bool SDL_MintAudio_thread_finished;
+long SDL_MintAudio_thread_pid;
+
 /* The callback function, called by each driver whenever needed */
 
 void SDL_MintAudio_Callback(void)
@@ -129,3 +140,56 @@
 	/* Not in the array, give the latest */
 	return MINTAUDIO_freqcount-1;
 }
+
+/* The thread function, used under MiNT with xbios */
+int SDL_MintAudio_Thread(long param)
+{
+	SndBufPtr	pointers;
+	SDL_bool	buffers_filled[2] = {SDL_FALSE, SDL_FALSE};
+
+	SDL_MintAudio_thread_finished = SDL_FALSE;
+	while (!SDL_MintAudio_quit_thread) {
+		if (Buffptr(&pointers)!=0)
+			continue;
+
+		if (( (unsigned long)pointers.play>=(unsigned long)SDL_MintAudio_audiobuf[0])
+			&& ( (unsigned long)pointers.play<=(unsigned long)SDL_MintAudio_audiobuf[1])) 
+		{
+			/* DMA is reading buffer #0, setup buffer #1 if not already done */
+			if (!buffers_filled[1]) {
+				SDL_MintAudio_numbuf = 1;
+				SDL_MintAudio_Callback();
+				Setbuffer(0, SDL_MintAudio_audiobuf[1], SDL_MintAudio_audiobuf[1] + SDL_MintAudio_audiosize);
+				buffers_filled[1]=SDL_TRUE;
+				buffers_filled[0]=SDL_FALSE;
+			}
+		} else {
+			/* DMA is reading buffer #1, setup buffer #0 if not already done */
+			if (!buffers_filled[0]) {
+				SDL_MintAudio_numbuf = 0;
+				SDL_MintAudio_Callback();
+				Setbuffer(0, SDL_MintAudio_audiobuf[0], SDL_MintAudio_audiobuf[0] + SDL_MintAudio_audiosize);
+				buffers_filled[0]=SDL_TRUE;
+				buffers_filled[1]=SDL_FALSE;
+			}
+		}
+
+		usleep(1000);
+	}
+	SDL_MintAudio_thread_finished = SDL_TRUE;
+	return 0;
+}
+
+void SDL_MintAudio_WaitThread(void)
+{
+	if (!SDL_MintAudio_mint_present)
+		return;
+
+	if (SDL_MintAudio_thread_finished)
+		return;
+
+	SDL_MintAudio_quit_thread = SDL_TRUE;
+	while (!SDL_MintAudio_thread_finished) {
+		Syield();
+	}
+}
--- a/src/audio/mint/SDL_mintaudio.h	Tue Aug 09 07:28:35 2005 +0000
+++ b/src/audio/mint/SDL_mintaudio.h	Wed Aug 10 13:29:49 2005 +0000
@@ -123,12 +123,22 @@
 extern cookie_stfa_t *SDL_MintAudio_stfa;
 extern unsigned long SDL_MintAudio_clocktics;
 
+/* MiNT thread variables */
+extern SDL_bool	SDL_MintAudio_mint_present;
+extern SDL_bool SDL_MintAudio_quit_thread;
+extern SDL_bool SDL_MintAudio_thread_finished;
+extern long SDL_MintAudio_thread_pid;
+
 /* Functions */
 void SDL_MintAudio_Callback(void);
 void SDL_MintAudio_AddFrequency(_THIS, Uint32 frequency, Uint32 clock,
 	Uint32 prediv, int gpio_bits);
 int SDL_MintAudio_SearchFrequency(_THIS, int desired_freq);
 
+/* MiNT thread functions */
+int SDL_MintAudio_Thread(long param);
+void SDL_MintAudio_WaitThread(void);
+
 /* ASM interrupt functions */
 void SDL_MintAudio_GsxbInterrupt(void);
 void SDL_MintAudio_EmptyGsxbInterrupt(void);
--- a/src/audio/mint/SDL_mintaudio_mcsn.c	Tue Aug 09 07:28:35 2005 +0000
+++ b/src/audio/mint/SDL_mintaudio_mcsn.c	Wed Aug 10 13:29:49 2005 +0000
@@ -30,6 +30,7 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
+#include <support.h>
 
 /* Mint includes */
 #include <mint/osbind.h>
@@ -85,12 +86,9 @@
 	unsigned long dummy;
 	const char *envr = getenv("SDL_AUDIODRIVER");
 
-	/* We can't use XBIOS in interrupt under MiNT */
-	if (Getcookie(C_MiNT, &dummy) == C_FOUND) {
-		return(0);
-	}
+	SDL_MintAudio_mint_present = (Getcookie(C_MiNT, &dummy) == C_FOUND);
 
-	/* nor with Magic */
+	/* We can't use XBIOS in interrupt with Magic, don't know about thread */
 	if (Getcookie(C_MagX, &dummy) == C_FOUND) {
 		return(0);
 	}
@@ -197,10 +195,13 @@
 static void Mint_CloseAudio(_THIS)
 {
 	/* Stop replay */
+	SDL_MintAudio_WaitThread();
 	Buffoper(0);
 
-	/* Uninstall interrupt */
-	Jdisint(MFP_DMASOUND);
+	if (!SDL_MintAudio_mint_present) {
+		/* Uninstall interrupt */
+		Jdisint(MFP_DMASOUND);
+	}
 
 	/* Wait if currently playing sound */
 	while (SDL_MintAudio_mutex != 0) {
@@ -298,6 +299,9 @@
 	void *buffer;
 
 	/* Stop currently playing sound */
+	SDL_MintAudio_quit_thread = SDL_FALSE;
+	SDL_MintAudio_thread_finished = SDL_TRUE;
+	SDL_MintAudio_WaitThread();
 	Buffoper(0);
 
 	/* Set replay tracks */
@@ -339,13 +343,17 @@
 		DEBUG_PRINT((DEBUG_NAME "Setbuffer() failed\n"));
 	}
 	
-	/* Install interrupt */
-	Jdisint(MFP_DMASOUND);
-	Xbtimer(XB_TIMERA, 8, 1, SDL_MintAudio_XbiosInterrupt);
-	Jenabint(MFP_DMASOUND);
+	if (SDL_MintAudio_mint_present) {
+		SDL_MintAudio_thread_pid = tfork(SDL_MintAudio_Thread, 0);
+	} else {
+		/* Install interrupt */
+		Jdisint(MFP_DMASOUND);
+		Xbtimer(XB_TIMERA, 8, 1, SDL_MintAudio_XbiosInterrupt);
+		Jenabint(MFP_DMASOUND);
 
-	if (Setinterrupt(SI_TIMERA, SI_PLAY)<0) {
-		DEBUG_PRINT((DEBUG_NAME "Setinterrupt() failed\n"));
+		if (Setinterrupt(SI_TIMERA, SI_PLAY)<0) {
+			DEBUG_PRINT((DEBUG_NAME "Setinterrupt() failed\n"));
+		}
 	}
 
 	/* Go */
@@ -390,5 +398,5 @@
 	/* Setup audio hardware */
 	Mint_InitAudio(this, spec);
 
-    return(1);	/* We don't use threaded audio */
+    return(1);	/* We don't use SDL threaded audio */
 }
--- a/src/audio/mint/SDL_mintaudio_xbios.c	Tue Aug 09 07:28:35 2005 +0000
+++ b/src/audio/mint/SDL_mintaudio_xbios.c	Wed Aug 10 13:29:49 2005 +0000
@@ -31,6 +31,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <unistd.h>
+#include <support.h>
 
 /* Mint includes */
 #include <mint/osbind.h>
@@ -85,12 +86,9 @@
 	unsigned long dummy;
 	const char *envr = getenv("SDL_AUDIODRIVER");
 
-	/* We can't use XBIOS in interrupt under MiNT */
-	if (Getcookie(C_MiNT, &dummy) == C_FOUND) {
-		return(0);
-	}
+	SDL_MintAudio_mint_present = (Getcookie(C_MiNT, &dummy) == C_FOUND);
 
-	/* nor with Magic */
+	/* We can't use XBIOS in interrupt with Magic, don't know about thread */
 	if (Getcookie(C_MagX, &dummy) == C_FOUND) {
 		return(0);
 	}
@@ -180,10 +178,13 @@
 static void Mint_CloseAudio(_THIS)
 {
 	/* Stop replay */
+	SDL_MintAudio_WaitThread();
 	Buffoper(0);
 
-	/* Uninstall interrupt */
-	Jdisint(MFP_DMASOUND);
+	if (!SDL_MintAudio_mint_present) {
+		/* Uninstall interrupt */
+		Jdisint(MFP_DMASOUND);
+	}
 
 	/* Wait if currently playing sound */
 	while (SDL_MintAudio_mutex != 0) {
@@ -391,6 +392,9 @@
 	void *buffer;
 
 	/* Stop currently playing sound */
+	SDL_MintAudio_quit_thread = SDL_FALSE;
+	SDL_MintAudio_thread_finished = SDL_TRUE;
+	SDL_MintAudio_WaitThread();
 	Buffoper(0);
 
 	/* Set replay tracks */
@@ -428,13 +432,17 @@
 		DEBUG_PRINT((DEBUG_NAME "Setbuffer() failed\n"));
 	}
 	
-	/* Install interrupt */
-	Jdisint(MFP_DMASOUND);
-	Xbtimer(XB_TIMERA, 8, 1, SDL_MintAudio_XbiosInterrupt);
-	Jenabint(MFP_DMASOUND);
+	if (SDL_MintAudio_mint_present) {
+		SDL_MintAudio_thread_pid = tfork(SDL_MintAudio_Thread, 0);
+	} else {
+		/* Install interrupt */
+		Jdisint(MFP_DMASOUND);
+		Xbtimer(XB_TIMERA, 8, 1, SDL_MintAudio_XbiosInterrupt);
+		Jenabint(MFP_DMASOUND);
 
-	if (Setinterrupt(SI_TIMERA, SI_PLAY)<0) {
-		DEBUG_PRINT((DEBUG_NAME "Setinterrupt() failed\n"));
+		if (Setinterrupt(SI_TIMERA, SI_PLAY)<0) {
+			DEBUG_PRINT((DEBUG_NAME "Setinterrupt() failed\n"));
+		}
 	}
 
 	/* Go */
@@ -479,5 +487,5 @@
 	/* Setup audio hardware */
 	Mint_InitAudio(this, spec);
 
-    return(1);	/* We don't use threaded audio */
+    return(1);	/* We don't use SDL threaded audio */
 }