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