1 /*---------------------------------------------------------------------------*
2   Project:  Audio visualization tools
3   File:     DEMOAVX.c
4 
5   Copyright 2001 Nintendo. All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law.  They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Log: DEMOAVX.c,v $
14   Revision 1.2  2006/02/20 04:37:44  mitu
15   Changed include path from dolphin/ to revolution/.
16 
17   Revision 1.1.1.1  2005/05/12 02:15:48  yasuh-to
18   Transitioned from the Dolphin source tree
19 
20 
21     1     1/11/02 4:55p Eugene
22     Cheesy method for snooping output from DSP/input to AI-FIFO. It is
23     audio-system agnostic, however.
24 
25 
26   $NoKeywords: $
27  *---------------------------------------------------------------------------*/
28 
29 /*---------------------------------------------------------------------------*
30  * Includes
31  *---------------------------------------------------------------------------*/
32 
33 #include <stdlib.h>
34 #include <stddef.h>
35 #include <string.h>
36 #include <math.h>
37 
38 #include <revolution.h>
39 #include <demo.h>
40 #include <demo/DEMOWin.h>
41 #include <demo/DEMOAVX.h>
42 
43 
44 
45 #define AVX_INTERNAL_NUM_FRAMES  10     // buffer for up to 10 frames (in case we dip to oh, say 20fps)
46 
47 static s16 __AVX_internal_buffer[AVX_FRAME_SIZE_WORDS*AVX_INTERNAL_NUM_FRAMES] ATTRIBUTE_ALIGN(32);
48 
49 
50 static void (*__AVX_save_isr)(void);    // AVX callback for AI-FIFO DMA interrupt
51 
52 static u32  __AVX_num_frames;           // number of audio frames to buffer
53 static u32  __AVX_num_filled;           // number of frames filled since last user refresh
54 static u32  __AVX_curr_frame;
55 
56 static u16 *__AVX_buffer;               // internal AI-FIFO buffer
57 static s16 *__AVX_left_buffer;          // pointer to caller's left-channel sample buffer
58 static s16 *__AVX_right_buffer;         // pointer to caller's right-channel sample buffer
59 
60 static u32  __AVX_write_ptr    = 0;
61 static u32  __AVX_buffer_size  = 0;
62 
63 
64 /*---------------------------------------------------------------------------*
65  * Name        :
66  * Description :
67  * Arguments   : None.
68  * Returns     : None.
69  *---------------------------------------------------------------------------*/
70 
71 
72 static BOOL flag = FALSE;
73 
74 
__DEMOAVX_isr(void)75 static void __DEMOAVX_isr(void)
76 {
77 
78     u32 frame_address;
79 
80         if (__AVX_save_isr)
81         {
82             (*__AVX_save_isr)();
83 
84 
85             // get current address of current AI-FIFO DMA transaction
86             frame_address = 0x80000000 | AIGetDMAStartAddr();
87 
88             // freak out if the address is NULL
89             ASSERTMSG(frame_address, "AVX: frame address is NULL!\n");
90 
91 
92             // invalidate source (DSP output/AI-FIFO input)
93             DCInvalidateRange((void *)(frame_address), AVX_FRAME_SIZE_BYTES);
94 
95             // copy output from DSP into our AVX buffer
96             memcpy((void *)(&__AVX_buffer[__AVX_curr_frame * AVX_FRAME_SIZE_WORDS]), (void *)(frame_address), AVX_FRAME_SIZE_BYTES);
97 
98             // Flush newly copied data from cache
99             DCFlushRange((void *)(&__AVX_buffer[__AVX_curr_frame * AVX_FRAME_SIZE_WORDS]), AVX_FRAME_SIZE_BYTES);
100 
101 
102             // increment frame pointer
103             __AVX_curr_frame = (__AVX_curr_frame + 1) % __AVX_num_frames;
104 
105             // increment frame counter
106             __AVX_num_filled = (__AVX_num_filled + 1) % AVX_INTERNAL_NUM_FRAMES;
107 
108             if (__AVX_curr_frame > 4)
109             {
110                 flag = TRUE;
111             }
112 
113 
114 
115         }
116 
117 } // end __DEMOAVX_isr
118 
119 /*---------------------------------------------------------------------------*
120  * Name        :
121  * Description :
122  * Arguments   : None.
123  * Returns     : None.
124  *---------------------------------------------------------------------------*/
125 
126 
DEMOAVXGetNumFilled(void)127 u32 DEMOAVXGetNumFilled(void)
128 {
129 
130     u32  tmp;
131     BOOL old;
132 
133         old = OSDisableInterrupts();
134 
135         tmp = __AVX_num_filled;
136         __AVX_num_filled = 0;
137 
138         OSRestoreInterrupts(old);
139 
140         return(tmp);
141 
142 } // end DEMOAVXGetNumFilled()
143 
144 /*---------------------------------------------------------------------------*
145  * Name        :
146  * Description :
147  * Arguments   : None.
148  * Returns     : None.
149  *---------------------------------------------------------------------------*/
150 
DEMOAVXGetFrameCounter(void)151 u32 DEMOAVXGetFrameCounter(void)
152 {
153 
154     return(__AVX_curr_frame);
155 
156 } // end DEMOAVXGetFrameCounter()
157 
158 /*---------------------------------------------------------------------------*
159  * Name        :
160  * Description :
161  * Arguments   : None.
162  * Returns     : None.
163  *---------------------------------------------------------------------------*/
164 
DEMOAVXRefreshBuffer(u32 * start_index,u32 * end_index)165 u32 DEMOAVXRefreshBuffer(u32 *start_index, u32 *end_index)
166 {
167 
168     u32  num_filled;
169     u32  curr_frame;
170 
171     u32 i;
172     u32 j;
173 
174         if (flag)
175         {
176 
177             //
178             num_filled = DEMOAVXGetNumFilled();
179 
180             // rewind back through the AI buffer
181             curr_frame = (__AVX_num_frames + DEMOAVXGetFrameCounter() - num_filled) % __AVX_num_frames;
182 
183             // save starting position in final sample buffer
184             *start_index = __AVX_write_ptr;
185 
186 
187             for (i=0; i<num_filled; i++)
188             {
189 
190                 // invalidate the AI buffer range
191                 DCInvalidateRange( (void *)(&__AVX_buffer[curr_frame * AVX_FRAME_SIZE_WORDS]), AVX_FRAME_SIZE_BYTES);
192 
193                 for (j=0; j<AVX_FRAME_SIZE_WORDS; j+=2)
194                 {
195                     __AVX_left_buffer [__AVX_write_ptr] = (s16)(__AVX_buffer[curr_frame * AVX_FRAME_SIZE_WORDS + j]);
196                     __AVX_right_buffer[__AVX_write_ptr] = (s16)(__AVX_buffer[curr_frame * AVX_FRAME_SIZE_WORDS + j + 1]);
197 
198                     __AVX_write_ptr = (__AVX_write_ptr + 1) % __AVX_buffer_size;
199                 }
200 
201                 curr_frame = (curr_frame + 1) % __AVX_num_frames;
202 
203             }
204 
205             *end_index = __AVX_write_ptr;
206 
207 
208 
209             return(num_filled*AVX_FRAME_SIZE_SAMPLES);
210         }
211 
212         else
213         {
214             return(0);
215         }
216 
217 
218 } // end DEMOAudioRefreshBuffer()
219 
220 /*---------------------------------------------------------------------------*
221  * Name        :
222  * Description :
223  * Arguments   : None.
224  * Returns     : None.
225  *---------------------------------------------------------------------------*/
226 
DEMOAVXInit(s16 * left,s16 * right,u32 size)227 void DEMOAVXInit(s16 *left, s16 *right, u32 size)
228 {
229 
230     __AVX_left_buffer  = left;
231     __AVX_right_buffer = right;
232 
233     __AVX_write_ptr = 0;
234 
235     __AVX_buffer_size = size;
236 
237 
238     DEMOAVXAttach((void *)__AVX_internal_buffer, AVX_INTERNAL_NUM_FRAMES);
239 
240 } // end DEMOAVXInit()
241 
242 /*---------------------------------------------------------------------------*
243  * Name        :
244  * Description :
245  * Arguments   : None.
246  * Returns     : None.
247  *---------------------------------------------------------------------------*/
248 
249 
DEMOAVXAttach(void * buffer,u32 num_frames)250 void DEMOAVXAttach(void *buffer, u32 num_frames)
251 {
252 
253     BOOL old;
254     u32  i;
255 
256 
257         __AVX_buffer     = (u16 *)buffer;
258         __AVX_num_frames = num_frames;
259         __AVX_num_filled = 0;
260         __AVX_curr_frame = 0;
261 
262 
263         // clear buffer
264         for (i=0; i<(num_frames*AVX_FRAME_SIZE_WORDS); i++)
265         {
266             *(__AVX_buffer + i) = 0;
267         }
268         DCFlushRange(__AVX_buffer, num_frames*AVX_FRAME_SIZE_WORDS);
269 
270 
271         // attach AVX interrupt handler
272         old = OSDisableInterrupts();
273 
274         __AVX_save_isr = AIRegisterDMACallback(__DEMOAVX_isr);
275 
276         OSRestoreInterrupts(old);
277 
278 
279 } // end DEMOAVXAttach()
280