1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - libraries - snd
3 File: sndex.c
4
5 Copyright 2008 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 $Date:: 2009-02-03#$
14 $Rev: 9957 $
15 $Author: nishimoto_takashi $
16 *---------------------------------------------------------------------------*/
17
18 #include <twl/os.h>
19 #include <twl/snd/ARM9/sndex.h>
20 #include <nitro/pxi.h>
21 #include <twl/os/common/codecmode.h>
22
23
24 /*---------------------------------------------------------------------------*
25 Macro Definitions
26 *---------------------------------------------------------------------------*/
27 #ifdef SDK_DEBUG
28 #define SNDEXi_Warning OS_TWarning
29 #else
30 #define SNDEXi_Warning(...) ((void)0)
31 #endif
32
33 /*---------------------------------------------------------------------------*
34 Structure Definitions
35 *---------------------------------------------------------------------------*/
36
37 /* Work structure for asynchronous processes */
38 typedef struct SNDEXWork
39 {
40 SNDEXCallback callback;
41 void* cbArg;
42 void* dest;
43 u8 command;
44 u8 padding[3];
45
46 } SNDEXWork;
47
48 /* Internal status */
49 typedef enum SNDEXState
50 {
51 SNDEX_STATE_BEFORE_INIT = 0,
52 SNDEX_STATE_INITIALIZING = 1,
53 SNDEX_STATE_INITIALIZED = 2,
54 SNDEX_STATE_LOCKED = 3,
55 SNDEX_STATE_PLAY_SHUTTER = 4, // Shutter sound is playing (Exclude all SNDEX functions other than PreProcessForShutterSound and PostProcessForShutterSound)
56 SNDEX_STATE_POST_PROC_SHUTTER = 5, // Currently postprocessing the shutter sound playback (Exclude all SNDEX functions)
57 SNDEX_STATE_MAX
58
59 } SNDEXState;
60
61 /* Set audio output device */
62 typedef enum SNDEXDevice
63 {
64 SNDEX_DEVICE_AUTO = 0,
65 SNDEX_DEVICE_SPEAKER = 1,
66 SNDEX_DEVICE_HEADPHONE = 2,
67 SNDEX_DEVICE_BOTH = 3,
68 SNDEX_DEVICE_MAX
69
70 } SNDEXDevice;
71
72 /*---------------------------------------------------------------------------*
73 Variable Definitions
74 *---------------------------------------------------------------------------*/
75 static volatile SNDEXState sndexState = SNDEX_STATE_BEFORE_INIT;
76 static SNDEXWork sndexWork;
77 static SNDEXVolumeSwitchCallbackInfo SNDEXi_VolumeSwitchCallbackInfo = {NULL, NULL, NULL, 0};
78
79 PMSleepCallbackInfo sleepCallbackInfo;
80 PMExitCallbackInfo exitCallbackInfo;
81 static volatile BOOL isIirFilterSetting = FALSE; // TRUE if already executing SetIirFilterAsync
82 static volatile BOOL isLockSpi = FALSE; // This indicates whether SPI exclusion control is currently being applied within SNDEX_SetIirFilter[Async]
83
84 static volatile BOOL isPlayShutter = FALSE; // TRUE if currently processing shutter sound playback
85 static volatile BOOL isStoreVolume = FALSE; // Whether a volume has been saved by SNDEXi_SetIgnoreHWVolume
86 static u8 storeVolume = 0; // Value of the volume before it is temporarily changed by SNDEXi_SetIgnoreHWVolume
87
88 /*---------------------------------------------------------------------------*
89 Function Definitions
90 *---------------------------------------------------------------------------*/
91 static void CommonCallback (PXIFifoTag tag, u32 data, BOOL err);
92 static void SyncCallback (SNDEXResult result, void* arg);
93 static BOOL SendCommand (u8 command, u8 param);
94 static BOOL SendCommandEx (u8 command, u16 param);
95 static SNDEXResult CheckState (void);
96 static void ReplyCallback (SNDEXResult result);
97 static void SetSndexWork (SNDEXCallback cb, void* cbarg, void* dst, u8 command);
98
99 static void SndexSleepAndExitCallback (void *arg);
100
101 static void WaitIirFilterSetting (void);
102 static void ResetTempVolume (void);
103
104 SNDEXResult SNDEXi_GetDeviceAsync (SNDEXDevice* device, SNDEXCallback callback, void* arg);
105 SNDEXResult SNDEXi_GetDevice (SNDEXDevice* device);
106 SNDEXResult SNDEXi_SetDeviceAsync (SNDEXDevice device, SNDEXCallback callback, void* arg);
107 SNDEXResult SNDEXi_SetDevice (SNDEXDevice device);
108
109 /*---------------------------------------------------------------------------*
110 Name: SNDEXi_Init
111
112 Description: Initializes the extended sound features library.
113
114 Arguments: None.
115
116 Returns: None.
117 *---------------------------------------------------------------------------*/
118 void
SNDEXi_Init(void)119 SNDEXi_Init (void)
120 {
121 OSIntrMode e = OS_DisableInterrupts();
122
123 /* Confirm that initialized */
124 if (sndexState != SNDEX_STATE_BEFORE_INIT)
125 {
126 (void)OS_RestoreInterrupts(e);
127 SNDEXi_Warning("%s: Already initialized.\n", __FUNCTION__);
128 return;
129 }
130 sndexState = SNDEX_STATE_INITIALIZING;
131 (void)OS_RestoreInterrupts(e);
132
133 /* Variable initialization */
134 SetSndexWork(NULL, NULL, NULL, 0);
135
136 /* Stand by until the ARM7's SNDEX library is started. */
137 PXI_Init();
138 while (!PXI_IsCallbackReady(PXI_FIFO_TAG_SNDEX, PXI_PROC_ARM7))
139 {
140 SVC_WaitByLoop(10);
141 }
142 /* Set the PXI callback function. */
143 PXI_SetFifoRecvCallback(PXI_FIFO_TAG_SNDEX, CommonCallback);
144
145 /* Set the postprocessing callback function for when executing a hardware reset or shutdown*/
146 PM_SetExitCallbackInfo(&exitCallbackInfo, SndexSleepAndExitCallback, NULL);
147 PMi_InsertPostExitCallbackEx(&exitCallbackInfo, PM_CALLBACK_PRIORITY_SNDEX);
148
149 /* Register the pre-sleep callback */
150 PM_SetSleepCallbackInfo(&sleepCallbackInfo, SndexSleepAndExitCallback, NULL);
151 PMi_InsertPreSleepCallbackEx(&sleepCallbackInfo, PM_CALLBACK_PRIORITY_SNDEX);
152
153 /* Initialization complete */
154 sndexState = SNDEX_STATE_INITIALIZED;
155 }
156
157 /*---------------------------------------------------------------------------*
158 Name: SNDEXi_GetMuteAsync
159
160 Description: Asynchronously gets the mute status of the audio output.
161 Because the writing of results to the results buffer is asynchronous compared to the function call, the buffer should not be used for other purposes until the asynchronous process completes.
162
163
164 Arguments: mute: Specifies the buffer used to get the mute status.
165 callback: Specifies the callback function that notifies of the results when the asynchronous process is completed.
166
167 arg: Specifies parameter passed to the callback function.
168
169 Returns: SNDEXResult: Returns processing results.
170 When returning SNDEX_RESULT_SUCCESS, the actual processing results are notified to the function registered to the callback after the asynchronous process is complete.
171
172 *---------------------------------------------------------------------------*/
173 SNDEXResult
SNDEXi_GetMuteAsync(SNDEXMute * mute,SNDEXCallback callback,void * arg)174 SNDEXi_GetMuteAsync (SNDEXMute* mute, SNDEXCallback callback, void* arg)
175 {
176 /* No parameter restrictions */
177
178 /* Confirm status */
179 {
180 SNDEXResult result = CheckState();
181 if (result != SNDEX_RESULT_SUCCESS)
182 {
183 return result;
184 }
185 }
186
187 /* Register asynchronous process */
188 SetSndexWork(callback, arg, (void*)mute, SNDEX_PXI_COMMAND_GET_SMIX_MUTE);
189
190 /* Issue command to ARM7 */
191 if (FALSE == SendCommand(sndexWork.command, 0))
192 {
193 return SNDEX_RESULT_PXI_SEND_ERROR;
194 }
195 return SNDEX_RESULT_SUCCESS;
196 }
197
198 /*---------------------------------------------------------------------------*
199 Name: SNDEXi_GetMute
200
201 Description: Gets the mute status of the audio output.
202 This is a synchronous function, so calling from within an interrupt handler is prohibited.
203
204 Arguments: mute: Specifies the buffer used to get the mute status.
205
206 Returns: SNDEXResult: Returns processing results.
207 *---------------------------------------------------------------------------*/
208 SNDEXResult
SNDEXi_GetMute(SNDEXMute * mute)209 SNDEXi_GetMute (SNDEXMute* mute)
210 {
211 SNDEXResult result;
212 OSMessageQueue msgQ;
213 OSMessage msg[1];
214
215 /* Calling this from an exception handler is prohibited */
216 if (OS_GetCurrentThread() == NULL)
217 {
218 SNDEXi_Warning("%s: Syncronous API could not process in exception handler.\n", __FUNCTION__);
219 return SNDEX_RESULT_ILLEGAL_STATE;
220 }
221
222 /* Initialize the message queue used for synchronization */
223 OS_InitMessageQueue(&msgQ, msg, 1);
224
225 /* Execute the asynchronous function and idle the callback */
226 result = SNDEXi_GetMuteAsync(mute, SyncCallback, (void*)(&msgQ));
227 if (result == SNDEX_RESULT_SUCCESS)
228 {
229 (void)OS_ReceiveMessage(&msgQ, (OSMessage*)(&result), OS_MESSAGE_BLOCK);
230 }
231 return result;
232 }
233
234 /*---------------------------------------------------------------------------*
235 Name: SNDEXi_GetI2SFrequencyAsync
236
237 Description: Asynchronously gets the I2S frequency information.
238 Because the writing of results to the results buffer is asynchronous compared to the function call, the buffer should not be used for other purposes until the asynchronous process completes.
239
240
241 Arguments: freq: Specifies the buffer used to get the frequency information.
242 callback: Specifies the callback function that notifies of the results when the asynchronous process is completed.
243
244 arg: Specifies parameter passed to the callback function.
245
246 Returns: SNDEXResult: Returns processing results.
247 When returning SNDEX_RESULT_SUCCESS, the actual processing results are notified to the function registered to the callback after the asynchronous process is complete.
248
249 *---------------------------------------------------------------------------*/
250 SNDEXResult
SNDEXi_GetI2SFrequencyAsync(SNDEXFrequency * freq,SNDEXCallback callback,void * arg)251 SNDEXi_GetI2SFrequencyAsync (SNDEXFrequency* freq, SNDEXCallback callback, void* arg)
252 {
253 /* No parameter restrictions */
254
255 /* Confirm status */
256 {
257 SNDEXResult result = CheckState();
258 if (result != SNDEX_RESULT_SUCCESS)
259 {
260 return result;
261 }
262 }
263
264 /* Register asynchronous process */
265 SetSndexWork(callback, arg, (void*)freq, SNDEX_PXI_COMMAND_GET_SMIX_FREQ);
266
267 /* Issue command to ARM7 */
268 if (FALSE == SendCommand(sndexWork.command, 0))
269 {
270 return SNDEX_RESULT_PXI_SEND_ERROR;
271 }
272 return SNDEX_RESULT_SUCCESS;
273 }
274
275 /*---------------------------------------------------------------------------*
276 Name: SNDEXi_GetI2SFrequency
277
278 Description: Gets I2S frequency information.
279 This is a synchronous function, so calling from within an interrupt handler is prohibited.
280
281 Arguments: freq: Specifies the buffer used to get the frequency information.
282
283 Returns: SNDEXResult: Returns processing results.
284 *---------------------------------------------------------------------------*/
285 SNDEXResult
SNDEXi_GetI2SFrequency(SNDEXFrequency * freq)286 SNDEXi_GetI2SFrequency(SNDEXFrequency* freq)
287 {
288 SNDEXResult result;
289 OSMessageQueue msgQ;
290 OSMessage msg[1];
291
292 /* Calling this from an exception handler is prohibited */
293 if (OS_GetCurrentThread() == NULL)
294 {
295 SNDEXi_Warning("%s: Syncronous API could not process in exception handler.\n", __FUNCTION__);
296 return SNDEX_RESULT_ILLEGAL_STATE;
297 }
298
299 /* Initialize the message queue used for synchronization */
300 OS_InitMessageQueue(&msgQ, msg, 1);
301
302 /* Execute the asynchronous function and idle the callback */
303 result = SNDEXi_GetI2SFrequencyAsync(freq, SyncCallback, (void*)(&msgQ));
304 if (result == SNDEX_RESULT_SUCCESS)
305 {
306 (void)OS_ReceiveMessage(&msgQ, (OSMessage*)(&result), OS_MESSAGE_BLOCK);
307 }
308 return result;
309 }
310
311 /*---------------------------------------------------------------------------*
312 Name: SNDEXi_GetDSPMixRateAsync
313
314 Description: Gets the audio output mix rate information for the CPU and DSP.
315 Minimum mix rate: 0 (DSP 100%), maximum: 8 (CPU 100%).
316 Because the writing of results to the results buffer is asynchronous compared to the function call, the buffer should not be used for other purposes until the asynchronous process completes.
317
318
319 Arguments: rate: Specifies the buffer used to get the mix rate information.
320 callback: Specifies the callback function that notifies of the results when the asynchronous process is completed.
321
322 arg: Specifies parameter passed to the callback function.
323
324 Returns: SNDEXResult: Returns processing results.
325 When returning SNDEX_RESULT_SUCCESS, the actual processing results are notified to the function registered to the callback after the asynchronous process is complete.
326
327 *---------------------------------------------------------------------------*/
328 SNDEXResult
SNDEXi_GetDSPMixRateAsync(u8 * rate,SNDEXCallback callback,void * arg)329 SNDEXi_GetDSPMixRateAsync (u8* rate, SNDEXCallback callback, void* arg)
330 {
331 /* No parameter restrictions */
332
333 /* Confirm status */
334 {
335 SNDEXResult result = CheckState();
336 if (result != SNDEX_RESULT_SUCCESS)
337 {
338 return result;
339 }
340 }
341
342 /* Register asynchronous process */
343 SetSndexWork(callback, arg, (void*)rate, SNDEX_PXI_COMMAND_GET_SMIX_DSP);
344
345 /* Issue command to ARM7 */
346 if (FALSE == SendCommand(sndexWork.command, 0))
347 {
348 return SNDEX_RESULT_PXI_SEND_ERROR;
349 }
350 return SNDEX_RESULT_SUCCESS;
351 }
352
353 /*---------------------------------------------------------------------------*
354 Name: SNDEXi_GetDSPMixRate
355
356 Description: Gets the audio output mix rate information for the CPU and DSP.
357 Minimum mix rate: 0 (DSP 100%), maximum: 8 (CPU 100%).
358 This is a synchronous function, so calling from within an interrupt handler is prohibited.
359
360 Arguments: rate: Specifies the buffer used to get the mix rate information.
361
362 Returns: SNDEXResult: Returns processing results.
363 *---------------------------------------------------------------------------*/
364 SNDEXResult
SNDEXi_GetDSPMixRate(u8 * rate)365 SNDEXi_GetDSPMixRate (u8* rate)
366 {
367 SNDEXResult result;
368 OSMessageQueue msgQ;
369 OSMessage msg[1];
370
371 /* Calling this from an exception handler is prohibited */
372 if (OS_GetCurrentThread() == NULL)
373 {
374 SNDEXi_Warning("%s: Syncronous API could not process in exception handler.\n", __FUNCTION__);
375 return SNDEX_RESULT_ILLEGAL_STATE;
376 }
377
378 /* Initialize the message queue used for synchronization */
379 OS_InitMessageQueue(&msgQ, msg, 1);
380
381 /* Execute the asynchronous function and idle the callback */
382 result = SNDEXi_GetDSPMixRateAsync(rate, SyncCallback, (void*)(&msgQ));
383 if (result == SNDEX_RESULT_SUCCESS)
384 {
385 (void)OS_ReceiveMessage(&msgQ, (OSMessage*)(&result), OS_MESSAGE_BLOCK);
386 }
387 return result;
388 }
389
390 /*---------------------------------------------------------------------------*
391 Name: SNDEXi_GetVolumeAsync
392
393 Description: Gets the audio output volume information. Minimum volume: 0, maximum: 7.
394 Because the writing of results to the results buffer is asynchronous compared to the function call, the buffer should not be used for other purposes until the asynchronous process completes.
395
396
397 Arguments: volume: Specifies the buffer used to get the volume information.
398 callback: Specifies the callback function that notifies of the results when the asynchronous process is completed.
399
400 arg: Specifies parameter passed to the callback function.
401 eightlv: Gets the volume as one of eight levels.
402 keep: Gets the amount of volume reserved for changes in volume. If there is no amount reserved, gets the current value.
403
404 Returns: SNDEXResult: Returns processing results.
405 When returning SNDEX_RESULT_SUCCESS, the actual processing results are notified to the function registered to the callback after the asynchronous process is complete.
406
407 *---------------------------------------------------------------------------*/
408 SNDEXResult
SNDEXi_GetVolumeAsync(u8 * volume,SNDEXCallback callback,void * arg,BOOL eightlv,BOOL keep)409 SNDEXi_GetVolumeAsync (u8* volume, SNDEXCallback callback, void* arg, BOOL eightlv, BOOL keep)
410 {
411 /* No parameter restrictions */
412
413 /* Confirm status */
414 {
415 SNDEXResult result = CheckState();
416 if (result != SNDEX_RESULT_SUCCESS)
417 {
418 return result;
419 }
420 }
421
422 /* Register asynchronous process */
423 SetSndexWork(callback, arg, (void*)volume, SNDEX_PXI_COMMAND_GET_VOLUME);
424
425 /* Issue command to ARM7 */
426 if (FALSE == SendCommand(sndexWork.command,
427 (u8)((keep << SNDEX_PXI_PARAMETER_SHIFT_VOL_KEEP) | (eightlv << SNDEX_PXI_PARAMETER_SHIFT_VOL_8LV))))
428 {
429 return SNDEX_RESULT_PXI_SEND_ERROR;
430 }
431 return SNDEX_RESULT_SUCCESS;
432 }
433
434 /*---------------------------------------------------------------------------*
435 Name: SNDEXi_GetVolume
436
437 Description: Gets the audio output volume information. Minimum volume: 0, maximum: 7.
438 This is a synchronous function, so calling from within an interrupt handler is prohibited.
439
440 Arguments: volume: Specifies the buffer used to get the volume information.
441 eightlv: Gets the volume as one of eight levels.
442 keep: Gets the amount of volume reserved for changes in volume. If there is no amount reserved, gets the current value.
443
444 Returns: SNDEXResult: Returns processing results.
445 *---------------------------------------------------------------------------*/
446 SNDEXResult
SNDEXi_GetVolume(u8 * volume,BOOL eightlv,BOOL keep)447 SNDEXi_GetVolume (u8* volume, BOOL eightlv, BOOL keep)
448 {
449 SNDEXResult result;
450 OSMessageQueue msgQ;
451 OSMessage msg[1];
452
453 /* Calling this from an exception handler is prohibited */
454 if (OS_GetCurrentThread() == NULL)
455 {
456 SNDEXi_Warning("%s: Syncronous API could not process in exception handler.\n", __FUNCTION__);
457 return SNDEX_RESULT_ILLEGAL_STATE;
458 }
459
460 /* Initialize the message queue used for synchronization */
461 OS_InitMessageQueue(&msgQ, msg, 1);
462
463 /* Execute the asynchronous function and idle the callback */
464 result = SNDEXi_GetVolumeAsync(volume, SyncCallback, (void*)(&msgQ), eightlv, keep);
465 if (result == SNDEX_RESULT_SUCCESS)
466 {
467 (void)OS_ReceiveMessage(&msgQ, (OSMessage*)(&result), OS_MESSAGE_BLOCK);
468 }
469 return result;
470 }
471
472 /*---------------------------------------------------------------------------*
473 Name: SNDEXi_GetVolumeExAsync
474
475 Description: Gets the audio output volume information. Minimum volume: 0, maximum: 31.
476 Because the writing of results to the results buffer is asynchronous compared to the function call, the buffer should not be used for other purposes until the asynchronous process completes.
477
478
479 Arguments: volume: Specifies the buffer used to get the volume information.
480 callback: Specifies the callback function that notifies of the results when the asynchronous process is completed.
481
482 arg: Specifies parameter passed to the callback function.
483
484 Returns: SNDEXResult: Returns processing results.
485 When returning SNDEX_RESULT_SUCCESS, the actual processing results are notified to the function registered to the callback after the asynchronous process is complete.
486
487 *---------------------------------------------------------------------------*/
488 SNDEXResult
SNDEXi_GetVolumeExAsync(u8 * volume,SNDEXCallback callback,void * arg)489 SNDEXi_GetVolumeExAsync (u8* volume, SNDEXCallback callback, void* arg)
490 {
491 if (!OS_IsRunOnTwl())
492 {
493 return SNDEX_RESULT_ILLEGAL_STATE;
494 }
495
496 return SNDEXi_GetVolumeAsync(volume, callback, arg, FALSE, TRUE);
497 }
498
499 /*---------------------------------------------------------------------------*
500 Name: SNDEXi_GetVolumeEx
501
502 Description: Gets the audio output volume information. Minimum volume: 0, maximum: 31.
503 This is a synchronous function, so calling from within an interrupt handler is prohibited.
504
505 Arguments: volume: Specifies the buffer used to get the volume information.
506
507 Returns: SNDEXResult: Returns processing results.
508 *---------------------------------------------------------------------------*/
509 SNDEXResult
SNDEXi_GetVolumeEx(u8 * volume)510 SNDEXi_GetVolumeEx (u8* volume)
511 {
512 if (!OS_IsRunOnTwl())
513 {
514 return SNDEX_RESULT_ILLEGAL_STATE;
515 }
516
517 return SNDEXi_GetVolume(volume, FALSE, TRUE);
518 }
519
520 /*---------------------------------------------------------------------------*
521 Name: SNDEXi_GetCurrentVolumeEx[Async]
522
523 Description: Gets the audio output volume information. Minimum volume: 0, maximum: 31.
524 If this is the synchronous function, calling it from within an interrupt handler is prohibited.
525 If this is the asynchronous function, the writing of results to the results buffer is asynchronous compared to the function call, so the buffer should not be used for other purposes until the asynchronous process completes.
526
527
528 Arguments: volume: Specifies the buffer used to get the volume information.
529 [callback: Specifies the callback function that notifies the results when the asynchronous processing is completed ]
530 [arg: Specifies parameters passed to the callback function.]
531
532 Returns: SNDEXResult: Returns processing results.
533 *---------------------------------------------------------------------------*/
534 SNDEXResult
SNDEXi_GetCurrentVolumeExAsync(u8 * volume,SNDEXCallback callback,void * arg)535 SNDEXi_GetCurrentVolumeExAsync (u8* volume, SNDEXCallback callback, void* arg)
536 {
537 if (!OS_IsRunOnTwl())
538 {
539 return SNDEX_RESULT_ILLEGAL_STATE;
540 }
541
542 return SNDEXi_GetVolumeAsync(volume, callback, arg, FALSE, FALSE);
543 }
544
545 SNDEXResult
SNDEXi_GetCurrentVolumeEx(u8 * volume)546 SNDEXi_GetCurrentVolumeEx (u8* volume)
547 {
548 if (!OS_IsRunOnTwl())
549 {
550 return SNDEX_RESULT_ILLEGAL_STATE;
551 }
552
553 return SNDEXi_GetVolume(volume, FALSE, FALSE);
554 }
555
556 /*---------------------------------------------------------------------------*
557 Name: SNDEXi_GetDeviceAsync
558
559 Description: Gets the audio output device setting information.
560 Because the writing of results to the results buffer is asynchronous compared to the function call, the buffer should not be used for other purposes until the asynchronous process completes.
561
562
563 Arguments: device: Specifies the buffer used to get the output device information.
564 callback: Specifies the callback function that notifies of the results when the asynchronous process is completed.
565
566 arg: Specifies parameter passed to the callback function.
567
568 Returns: SNDEXResult: Returns processing results.
569 When returning SNDEX_RESULT_SUCCESS, the actual processing results are notified to the function registered to the callback after the asynchronous process is complete.
570
571 *---------------------------------------------------------------------------*/
572 SNDEXResult
SNDEXi_GetDeviceAsync(SNDEXDevice * device,SNDEXCallback callback,void * arg)573 SNDEXi_GetDeviceAsync (SNDEXDevice* device, SNDEXCallback callback, void* arg)
574 {
575 /* No parameter restrictions */
576
577 /* Confirm status */
578 {
579 SNDEXResult result = CheckState();
580 if (result != SNDEX_RESULT_SUCCESS)
581 {
582 return result;
583 }
584 }
585
586 /* Register asynchronous process */
587 SetSndexWork(callback, arg, (void*)device, SNDEX_PXI_COMMAND_GET_SND_DEVICE);
588
589 /* Issue command to ARM7 */
590 if (FALSE == SendCommand(sndexWork.command, 0))
591 {
592 return SNDEX_RESULT_PXI_SEND_ERROR;
593 }
594 return SNDEX_RESULT_SUCCESS;
595 }
596
597 /*---------------------------------------------------------------------------*
598 Name: SNDEXi_GetDevice
599
600 Description: Gets the audio output device setting information.
601 This is a synchronous function, so calling from within an interrupt handler is prohibited.
602
603 Arguments: device: Specifies the buffer used to get the output device information.
604
605 Returns: SNDEXResult: Returns processing results.
606 *---------------------------------------------------------------------------*/
607 SNDEXResult
SNDEXi_GetDevice(SNDEXDevice * device)608 SNDEXi_GetDevice (SNDEXDevice* device)
609 {
610 SNDEXResult result;
611 OSMessageQueue msgQ;
612 OSMessage msg[1];
613
614 /* Calling this from an exception handler is prohibited */
615 if (OS_GetCurrentThread() == NULL)
616 {
617 SNDEXi_Warning("%s: Syncronous API could not process in exception handler.\n", __FUNCTION__);
618 return SNDEX_RESULT_ILLEGAL_STATE;
619 }
620
621 /* Initialize the message queue used for synchronization */
622 OS_InitMessageQueue(&msgQ, msg, 1);
623
624 /* Execute the asynchronous function and idle the callback */
625 result = SNDEXi_GetDeviceAsync(device, SyncCallback, (void*)(&msgQ));
626 if (result == SNDEX_RESULT_SUCCESS)
627 {
628 (void)OS_ReceiveMessage(&msgQ, (OSMessage*)(&result), OS_MESSAGE_BLOCK);
629 }
630 return result;
631 }
632
633 /*---------------------------------------------------------------------------*
634 Name: SNDEXi_SetMuteAsync
635
636 Description: Changes the mute status of the audio output.
637
638 Arguments: mute: Specifies mute setting status.
639 callback: Specifies the callback function that notifies of the results when the asynchronous process is completed.
640
641 arg: Specifies parameter passed to the callback function.
642
643 Returns: SNDEXResult: Returns processing results.
644 When returning SNDEX_RESULT_SUCCESS, the actual processing results are notified to the function registered to the callback after the asynchronous process is complete.
645
646 *---------------------------------------------------------------------------*/
647 SNDEXResult
SNDEXi_SetMuteAsync(SNDEXMute mute,SNDEXCallback callback,void * arg)648 SNDEXi_SetMuteAsync (SNDEXMute mute, SNDEXCallback callback, void* arg)
649 {
650 /* Parameter restriction check */
651 if (mute >= SNDEX_MUTE_MAX)
652 {
653 SNDEXi_Warning("%s: Invalid parameter (mute: %d)\n", __FUNCTION__, mute);
654 return SNDEX_RESULT_INVALID_PARAM;
655 }
656
657 /* Confirm status */
658 {
659 SNDEXResult result = CheckState();
660 if (result != SNDEX_RESULT_SUCCESS)
661 {
662 return result;
663 }
664 }
665
666 /* Register asynchronous process */
667 SetSndexWork(callback, arg, NULL, SNDEX_PXI_COMMAND_SET_SMIX_MUTE);
668
669 /* Issue command to ARM7 */
670 if (FALSE == SendCommand(sndexWork.command, (u8)mute))
671 {
672 return SNDEX_RESULT_PXI_SEND_ERROR;
673 }
674 return SNDEX_RESULT_SUCCESS;
675 }
676
677 /*---------------------------------------------------------------------------*
678 Name: SNDEXi_SetMute
679
680 Description: Changes the mute status of the audio output.
681 This is a synchronous function, so calling from within an interrupt handler is prohibited.
682
683 Arguments: mute: Specifies mute setting status.
684
685 Returns: SNDEXResult: Returns processing results.
686 *---------------------------------------------------------------------------*/
687 SNDEXResult
SNDEXi_SetMute(SNDEXMute mute)688 SNDEXi_SetMute (SNDEXMute mute)
689 {
690 SNDEXResult result;
691 OSMessageQueue msgQ;
692 OSMessage msg[1];
693
694 /* Calling this from an exception handler is prohibited */
695 if (OS_GetCurrentThread() == NULL)
696 {
697 SNDEXi_Warning("%s: Syncronous API could not process in exception handler.\n", __FUNCTION__);
698 return SNDEX_RESULT_ILLEGAL_STATE;
699 }
700
701 /* Initialize the message queue used for synchronization */
702 OS_InitMessageQueue(&msgQ, msg, 1);
703
704 /* Execute the asynchronous function and idle the callback */
705 result = SNDEXi_SetMuteAsync(mute, SyncCallback, (void*)(&msgQ));
706 if (result == SNDEX_RESULT_SUCCESS)
707 {
708 (void)OS_ReceiveMessage(&msgQ, (OSMessage*)(&result), OS_MESSAGE_BLOCK);
709 }
710 return result;
711 }
712
713 /*---------------------------------------------------------------------------*
714 Name: SNDEXi_SetI2SFrequencyAsync
715
716 Description: Changes the I2S frequency.
717
718 Arguments: freq: Specifies the frequency.
719 callback: Specifies the callback function that notifies of the results when the asynchronous process is completed.
720
721 arg: Specifies parameter passed to the callback function.
722
723 Returns: SNDEXResult: Returns processing results.
724 When returning SNDEX_RESULT_SUCCESS, the actual processing results are notified to the function registered to the callback after the asynchronous process is complete.
725
726 *---------------------------------------------------------------------------*/
727 SNDEXResult
SNDEXi_SetI2SFrequencyAsync(SNDEXFrequency freq,SNDEXCallback callback,void * arg)728 SNDEXi_SetI2SFrequencyAsync (SNDEXFrequency freq, SNDEXCallback callback, void* arg)
729 {
730 /* Parameter restriction check */
731 if (freq >= SNDEX_FREQUENCY_MAX)
732 {
733 SNDEXi_Warning("%s: Invalid parameter (freq: %d)\n", __FUNCTION__, freq);
734 return SNDEX_RESULT_INVALID_PARAM;
735 }
736
737 /* Check CODEC operating mode */
738 if (OSi_IsCodecTwlMode() == FALSE)
739 {
740 return SNDEX_RESULT_ILLEGAL_STATE;
741 }
742
743 /* Confirm status */
744 {
745 SNDEXResult result = CheckState();
746 if (result != SNDEX_RESULT_SUCCESS)
747 {
748 return result;
749 }
750 }
751
752 /* Register asynchronous process */
753 SetSndexWork(callback, arg, NULL, SNDEX_PXI_COMMAND_SET_SMIX_FREQ);
754
755 /* Issue command to ARM7 */
756 if (FALSE == SendCommand(sndexWork.command, (u8)freq))
757 {
758 return SNDEX_RESULT_PXI_SEND_ERROR;
759 }
760 return SNDEX_RESULT_SUCCESS;
761 }
762
763 /*---------------------------------------------------------------------------*
764 Name: SNDEXi_SetI2SFrequency
765
766 Description: Changes the I2S frequency.
767 This is a synchronous function, so calling from within an interrupt handler is prohibited.
768
769 Arguments: freq: Specifies the frequency.
770
771 Returns: SNDEXResult: Returns processing results.
772 *---------------------------------------------------------------------------*/
773 SNDEXResult
SNDEXi_SetI2SFrequency(SNDEXFrequency freq)774 SNDEXi_SetI2SFrequency (SNDEXFrequency freq)
775 {
776 SNDEXResult result;
777 OSMessageQueue msgQ;
778 OSMessage msg[1];
779
780 /* Calling this from an exception handler is prohibited */
781 if (OS_GetCurrentThread() == NULL)
782 {
783 SNDEXi_Warning("%s: Syncronous API could not process in exception handler.\n", __FUNCTION__);
784 return SNDEX_RESULT_ILLEGAL_STATE;
785 }
786
787 /* Initialize the message queue used for synchronization */
788 OS_InitMessageQueue(&msgQ, msg, 1);
789
790 /* Execute the asynchronous function and idle the callback */
791 result = SNDEXi_SetI2SFrequencyAsync(freq, SyncCallback, (void*)(&msgQ));
792 if (result == SNDEX_RESULT_SUCCESS)
793 {
794 (void)OS_ReceiveMessage(&msgQ, (OSMessage*)(&result), OS_MESSAGE_BLOCK);
795 }
796 return result;
797 }
798
799 /*---------------------------------------------------------------------------*
800 Name: SNDEXi_SetDSPMixRateAsync
801
802 Description: Changes the audio output mix rate for the CPU and DSP.
803 Minimum mix rate: 0 (DSP 100%), maximum: 8 (CPU 100%).
804
805 Arguments: rate: Specifies the mix rate with a numeral from 0 to 8.
806 callback: Specifies the callback function that notifies of the results when the asynchronous process is completed.
807
808 arg: Specifies parameter passed to the callback function.
809
810 Returns: SNDEXResult: Returns processing results.
811 When returning SNDEX_RESULT_SUCCESS, the actual processing results are notified to the function registered to the callback after the asynchronous process is complete.
812
813 *---------------------------------------------------------------------------*/
814 SNDEXResult
SNDEXi_SetDSPMixRateAsync(u8 rate,SNDEXCallback callback,void * arg)815 SNDEXi_SetDSPMixRateAsync (u8 rate, SNDEXCallback callback, void* arg)
816 {
817 /* Check CODEC operating mode */
818 if (OSi_IsCodecTwlMode() == FALSE)
819 {
820 SNDEXi_Warning("%s: Illegal state\n", __FUNCTION__);
821 return SNDEX_RESULT_ILLEGAL_STATE;
822 }
823
824 /* Parameter restriction check */
825 if (rate > SNDEX_DSP_MIX_RATE_MAX)
826 {
827 SNDEXi_Warning("%s: Invalid parameter (rate: %u)\n", __FUNCTION__, rate);
828 return SNDEX_RESULT_INVALID_PARAM;
829 }
830
831 /* Confirm status */
832 {
833 SNDEXResult result = CheckState();
834 if (result != SNDEX_RESULT_SUCCESS)
835 {
836 return result;
837 }
838 }
839
840 /* Register asynchronous process */
841 SetSndexWork(callback, arg, NULL, SNDEX_PXI_COMMAND_SET_SMIX_DSP);
842
843 /* Issue command to ARM7 */
844 if (FALSE == SendCommand(sndexWork.command, (u8)rate))
845 {
846 return SNDEX_RESULT_PXI_SEND_ERROR;
847 }
848 return SNDEX_RESULT_SUCCESS;
849 }
850
851 /*---------------------------------------------------------------------------*
852 Name: SNDEXi_SetDSPMixRate
853
854 Description: Changes the audio output mix rate for the CPU and DSP.
855 Minimum mix rate: 0 (DSP 100%), maximum: 8 (CPU 100%).
856 This is a synchronous function, so calling from within an interrupt handler is prohibited.
857
858 Arguments: rate: Specifies the mix rate with a numeral from 0 to 8.
859
860 Returns: SNDEXResult: Returns processing results.
861 *---------------------------------------------------------------------------*/
862 SNDEXResult
SNDEXi_SetDSPMixRate(u8 rate)863 SNDEXi_SetDSPMixRate (u8 rate)
864 {
865 SNDEXResult result;
866 OSMessageQueue msgQ;
867 OSMessage msg[1];
868
869 /* Calling this from an exception handler is prohibited */
870 if (OS_GetCurrentThread() == NULL)
871 {
872 SNDEXi_Warning("%s: Syncronous API could not process in exception handler.\n", __FUNCTION__);
873 return SNDEX_RESULT_ILLEGAL_STATE;
874 }
875
876 /* Initialize the message queue used for synchronization */
877 OS_InitMessageQueue(&msgQ, msg, 1);
878
879 /* Execute the asynchronous function and idle the callback */
880 result = SNDEXi_SetDSPMixRateAsync(rate, SyncCallback, (void*)(&msgQ));
881 if (result == SNDEX_RESULT_SUCCESS)
882 {
883 (void)OS_ReceiveMessage(&msgQ, (OSMessage*)(&result), OS_MESSAGE_BLOCK);
884 }
885 return result;
886 }
887
888 /*---------------------------------------------------------------------------*
889 Name: SNDEXi_SetVolumeAsync
890
891 Description: Changes the audio output volume. Minimum volume: 0, maximum: 7.
892
893 Arguments: volume: Specifies the volume as a numeral from 0 to 7.
894 callback: Specifies the callback function that notifies of the results when the asynchronous process is completed.
895
896 arg: Specifies parameter passed to the callback function.
897 eightlv: Sets the volume as one of eight levels.
898
899 Returns: SNDEXResult: Returns processing results.
900 When returning SNDEX_RESULT_SUCCESS, the actual processing results are notified to the function registered to the callback after the asynchronous process is complete.
901
902 *---------------------------------------------------------------------------*/
903 SNDEXResult
SNDEXi_SetVolumeAsync(u8 volume,SNDEXCallback callback,void * arg,BOOL eightlv)904 SNDEXi_SetVolumeAsync (u8 volume, SNDEXCallback callback, void* arg, BOOL eightlv)
905 {
906 /* Parameter restriction check */
907 if (volume > (eightlv ? SNDEX_VOLUME_MAX : SNDEX_VOLUME_MAX_EX))
908 {
909 SNDEXi_Warning("%s: Invalid parameter (volume: %u)\n", __FUNCTION__, volume);
910 return SNDEX_RESULT_INVALID_PARAM;
911 }
912
913 /* Confirm status */
914 {
915 SNDEXResult result = CheckState();
916 if (result != SNDEX_RESULT_SUCCESS)
917 {
918 return result;
919 }
920 }
921
922 /* Register asynchronous process */
923 SetSndexWork(callback, arg, NULL, SNDEX_PXI_COMMAND_SET_VOLUME);
924
925 /* Issue command to ARM7 */
926 if (FALSE == SendCommand(sndexWork.command,
927 (u8)((eightlv << SNDEX_PXI_PARAMETER_SHIFT_VOL_8LV) | (SNDEX_PXI_PARAMETER_MASK_VOL_VALUE & volume))))
928 {
929 return SNDEX_RESULT_PXI_SEND_ERROR;
930 }
931 return SNDEX_RESULT_SUCCESS;
932 }
933
934 /*---------------------------------------------------------------------------*
935 Name: SNDEXi_SetVolume
936
937 Description: Changes the audio output volume. Minimum volume: 0, maximum: 7.
938 This is a synchronous function, so calling from within an interrupt handler is prohibited.
939
940 Arguments: volume: Specifies the volume as a numeral from 0 to 7.
941
942 Returns: SNDEXResult: Returns processing results.
943 *---------------------------------------------------------------------------*/
944 SNDEXResult
SNDEXi_SetVolume(u8 volume,BOOL eightlv)945 SNDEXi_SetVolume (u8 volume, BOOL eightlv)
946 {
947 SNDEXResult result;
948 OSMessageQueue msgQ;
949 OSMessage msg[1];
950
951 /* Calling this from an exception handler is prohibited */
952 if (OS_GetCurrentThread() == NULL)
953 {
954 SNDEXi_Warning("%s: Syncronous API could not process in exception handler.\n", __FUNCTION__);
955 return SNDEX_RESULT_ILLEGAL_STATE;
956 }
957
958 /* Initialize the message queue used for synchronization */
959 OS_InitMessageQueue(&msgQ, msg, 1);
960
961 /* Execute the asynchronous function and idle the callback */
962 result = SNDEXi_SetVolumeAsync(volume, SyncCallback, (void*)(&msgQ), eightlv);
963 if (result == SNDEX_RESULT_SUCCESS)
964 {
965 (void)OS_ReceiveMessage(&msgQ, (OSMessage*)(&result), OS_MESSAGE_BLOCK);
966 }
967 return result;
968 }
969
970 /*---------------------------------------------------------------------------*
971 Name: SNDEXi_SetVolumeExAsync
972
973 Description: Changes the audio output volume. Minimum volume: 0, maximum: 31.
974
975 Arguments: volume: Specifies the volume as a numeral from 0 to 31.
976 callback: Specifies the callback function that notifies of the results when the asynchronous process is completed.
977
978 arg: Specifies parameter passed to the callback function.
979
980 Returns: SNDEXResult: Returns processing results.
981 When returning SNDEX_RESULT_SUCCESS, the actual processing results are notified to the function registered to the callback after the asynchronous process is complete.
982
983 *---------------------------------------------------------------------------*/
984 SNDEXResult
SNDEXi_SetVolumeExAsync(u8 volume,SNDEXCallback callback,void * arg)985 SNDEXi_SetVolumeExAsync (u8 volume, SNDEXCallback callback, void* arg)
986 {
987 if (!OS_IsRunOnTwl())
988 {
989 return SNDEX_RESULT_ILLEGAL_STATE;
990 }
991
992 return SNDEXi_SetVolumeAsync(volume, callback, arg, FALSE);
993 }
994
995 /*---------------------------------------------------------------------------*
996 Name: SNDEXi_SetVolumeEx
997
998 Description: Changes the audio output volume. Minimum volume: 0, maximum: 31.
999 This is a synchronous function, so calling from within an interrupt handler is prohibited.
1000
1001 Arguments: volume: Specifies the volume as a numeral from 0 to 31.
1002
1003 Returns: SNDEXResult: Returns processing results.
1004 *---------------------------------------------------------------------------*/
1005 SNDEXResult
SNDEXi_SetVolumeEx(u8 volume)1006 SNDEXi_SetVolumeEx (u8 volume)
1007 {
1008 if (!OS_IsRunOnTwl())
1009 {
1010 return SNDEX_RESULT_ILLEGAL_STATE;
1011 }
1012
1013 return SNDEXi_SetVolume(volume, FALSE);
1014 }
1015
1016 /*---------------------------------------------------------------------------*
1017 Name: SNDEXi_SetDeviceAsync
1018
1019 Description: Changes the audio output device setting.
1020
1021 Arguments: device: Specifies the output device setting.
1022 callback: Specifies the callback function that notifies of the results when the asynchronous process is completed.
1023
1024 arg: Specifies parameter passed to the callback function.
1025
1026 Returns: SNDEXResult: Returns processing results.
1027 When returning SNDEX_RESULT_SUCCESS, the actual processing results are notified to the function registered to the callback after the asynchronous process is complete.
1028
1029 *---------------------------------------------------------------------------*/
1030 SNDEXResult
SNDEXi_SetDeviceAsync(SNDEXDevice device,SNDEXCallback callback,void * arg)1031 SNDEXi_SetDeviceAsync (SNDEXDevice device, SNDEXCallback callback, void* arg)
1032 {
1033 /* Parameter restriction check */
1034 if (device >= SNDEX_DEVICE_MAX)
1035 {
1036 SNDEXi_Warning("%s: Invalid parameter (device: %d)\n", __FUNCTION__, device);
1037 return SNDEX_RESULT_INVALID_PARAM;
1038 }
1039
1040 /* Check CODEC operating mode */
1041 if (OSi_IsCodecTwlMode() == FALSE)
1042 {
1043 return SNDEX_RESULT_ILLEGAL_STATE;
1044 }
1045
1046 /* Confirm status */
1047 {
1048 SNDEXResult result = CheckState();
1049 if (result != SNDEX_RESULT_SUCCESS)
1050 {
1051 return result;
1052 }
1053 }
1054
1055 /* Register asynchronous process */
1056 SetSndexWork(callback, arg, NULL, SNDEX_PXI_COMMAND_SET_SND_DEVICE);
1057
1058 /* Issue command to ARM7 */
1059 if (FALSE == SendCommand(sndexWork.command, (u8)device))
1060 {
1061 return SNDEX_RESULT_PXI_SEND_ERROR;
1062 }
1063 return SNDEX_RESULT_SUCCESS;
1064 }
1065
1066 /*---------------------------------------------------------------------------*
1067 Name: SNDEXi_SetDevice
1068
1069 Description: Changes the audio output device setting.
1070 This is a synchronous function, so calling from within an interrupt handler is prohibited.
1071
1072 Arguments: device: Specifies the output device setting.
1073
1074 Returns: SNDEXResult: Returns processing results.
1075 *---------------------------------------------------------------------------*/
1076 SNDEXResult
SNDEXi_SetDevice(SNDEXDevice device)1077 SNDEXi_SetDevice (SNDEXDevice device)
1078 {
1079 SNDEXResult result;
1080 OSMessageQueue msgQ;
1081 OSMessage msg[1];
1082
1083 /* Calling this from an exception handler is prohibited */
1084 if (OS_GetCurrentThread() == NULL)
1085 {
1086 SNDEXi_Warning("%s: Syncronous API could not process in exception handler.\n", __FUNCTION__);
1087 return SNDEX_RESULT_ILLEGAL_STATE;
1088 }
1089
1090 /* Initialize the message queue used for synchronization */
1091 OS_InitMessageQueue(&msgQ, msg, 1);
1092
1093 /* Execute the asynchronous function and idle the callback */
1094 result = SNDEXi_SetDeviceAsync(device, SyncCallback, (void*)(&msgQ));
1095 if (result == SNDEX_RESULT_SUCCESS)
1096 {
1097 (void)OS_ReceiveMessage(&msgQ, (OSMessage*)(&result), OS_MESSAGE_BLOCK);
1098 }
1099 return result;
1100 }
1101
1102 /*---------------------------------------------------------------------------*
1103 Name: SNDEX_SetIirFilterAsync
1104
1105 Description: Asynchronously sets the IIR filter (Biquad) parameters.
1106
1107 !! CAUTION!!: Because it is not possible to pass all parameters to ARM7 with one PXI transmission, this uses multiple back-to-back transfers.
1108 However, if it simply makes several transfers back-to-back, sometimes the previously sent parameters will not yet be processed when the next set arrives. For this reason, this function also waits before each PXI transfer until the previous transfer's parameters are processed.
1109
1110
1111
1112 Arguments: target:
1113 pParam:
1114
1115 Returns: None.
1116 *---------------------------------------------------------------------------*/
1117 SNDEXResult
SNDEXi_SetIirFilterAsync(SNDEXIirFilterTarget target,const SNDEXIirFilterParam * pParam,SNDEXCallback callback,void * arg)1118 SNDEXi_SetIirFilterAsync(SNDEXIirFilterTarget target, const SNDEXIirFilterParam* pParam, SNDEXCallback callback, void* arg)
1119 {
1120 // Return an error if already processing SetIirFilterAsync
1121 if (isIirFilterSetting)
1122 {
1123 return SNDEX_RESULT_EXCLUSIVE;
1124 }
1125 isIirFilterSetting = TRUE;
1126
1127 /* Check CODEC operating mode */
1128 if (OSi_IsCodecTwlMode() == FALSE)
1129 {
1130 SNDEXi_Warning("%s: Illegal state\n", __FUNCTION__);
1131 isIirFilterSetting = FALSE;
1132 return SNDEX_RESULT_ILLEGAL_STATE;
1133 }
1134
1135 /* Confirm status */
1136 {
1137 SNDEXResult result = CheckState();
1138 if (result != SNDEX_RESULT_SUCCESS)
1139 {
1140 isIirFilterSetting = FALSE;
1141 return result;
1142 }
1143 }
1144
1145 /* Target */
1146 /* Register asynchronous process */
1147 SetSndexWork(NULL, NULL, NULL, SNDEX_PXI_COMMAND_SET_IIRFILTER_TARGET);
1148 /* Issue command to ARM7 */
1149 if (FALSE == SendCommandEx(sndexWork.command, (u16)target))
1150 {
1151 isIirFilterSetting = FALSE;
1152 return SNDEX_RESULT_PXI_SEND_ERROR;
1153 }
1154 // Wait for the callback by idling in an empty loop so that there is time for the CheckState function's Warning suppression
1155 OS_SpinWait(67 * 1000); //Approximately 1 ms
1156
1157 // Wait until the previous PXI transfer's processing ends
1158 while ( CheckState() != SNDEX_RESULT_SUCCESS )
1159 {
1160 OS_SpinWait(67 * 1000); //Approximately 1 ms
1161 }
1162
1163 /* Filter parameter */
1164 // n0
1165 SetSndexWork(NULL, NULL, NULL, SNDEX_PXI_COMMAND_SET_IIRFILTER_PARAM_N0);
1166 /* Issue command to ARM7 */
1167 if (FALSE == SendCommandEx(sndexWork.command, pParam->n0))
1168 {
1169 isIirFilterSetting = FALSE;
1170 return SNDEX_RESULT_PXI_SEND_ERROR;
1171 }
1172 OS_SpinWait(67 * 1000); //Approximately 1 ms
1173
1174 // Wait until the previous PXI transfer's processing ends
1175 while ( CheckState() != SNDEX_RESULT_SUCCESS )
1176 {
1177 OS_SpinWait(67 * 1000); //Approximately 1 ms
1178 }
1179
1180 // n1
1181 SetSndexWork(NULL, NULL, NULL, SNDEX_PXI_COMMAND_SET_IIRFILTER_PARAM_N1);
1182 /* Issue command to ARM7 */
1183 if (FALSE == SendCommandEx(sndexWork.command, pParam->n1))
1184 {
1185 isIirFilterSetting = FALSE;
1186 return SNDEX_RESULT_PXI_SEND_ERROR;
1187 }
1188 OS_SpinWait(67 * 1000); //Approximately 1 ms
1189
1190 // Wait until the previous PXI transfer's processing ends
1191 while ( CheckState() != SNDEX_RESULT_SUCCESS )
1192 {
1193 OS_SpinWait(67 * 1000); //Approximately 1 ms
1194 }
1195
1196 // n2
1197 SetSndexWork(NULL, NULL, NULL, SNDEX_PXI_COMMAND_SET_IIRFILTER_PARAM_N2);
1198 /* Issue command to ARM7 */
1199 if (FALSE == SendCommandEx(sndexWork.command, pParam->n2))
1200 {
1201 isIirFilterSetting = FALSE;
1202 return SNDEX_RESULT_PXI_SEND_ERROR;
1203 }
1204 OS_SpinWait(67 * 1000); //Approximately 1 ms
1205
1206 // Wait until the previous PXI transfer's processing ends
1207 while ( CheckState() != SNDEX_RESULT_SUCCESS )
1208 {
1209 OS_SpinWait(67 * 1000); //Approximately 1 ms
1210 }
1211
1212 // d1
1213 SetSndexWork(NULL, NULL, NULL, SNDEX_PXI_COMMAND_SET_IIRFILTER_PARAM_D1);
1214 /* Issue command to ARM7 */
1215 if (FALSE == SendCommandEx(sndexWork.command, pParam->d1))
1216 {
1217 isIirFilterSetting = FALSE;
1218 return SNDEX_RESULT_PXI_SEND_ERROR;
1219 }
1220 OS_SpinWait(67 * 1000); //Approximately 1 ms
1221
1222 // Wait until the previous PXI transfer's processing ends
1223 while ( CheckState() != SNDEX_RESULT_SUCCESS )
1224 {
1225 OS_SpinWait(67 * 1000); //Approximately 1 ms
1226 }
1227
1228 // d2
1229 SetSndexWork(NULL, NULL, NULL, SNDEX_PXI_COMMAND_SET_IIRFILTER_PARAM_D2);
1230 /* Issue command to ARM7 */
1231 if (FALSE == SendCommandEx(sndexWork.command, pParam->d2))
1232 {
1233 isIirFilterSetting = FALSE;
1234 return SNDEX_RESULT_PXI_SEND_ERROR;
1235 }
1236 OS_SpinWait(67 * 1000); //Approximately 1 ms
1237
1238 // Wait until the previous PXI transfer's processing ends
1239 while ( CheckState() != SNDEX_RESULT_SUCCESS )
1240 {
1241 OS_SpinWait(67 * 1000); //Approximately 1 ms
1242 }
1243
1244 /* Set the target and the filter parameters */
1245 SetSndexWork(callback, arg, NULL, SNDEX_PXI_COMMAND_SET_IIRFILTER);
1246 /* Issue command to ARM7 */
1247 if (FALSE == SendCommandEx(sndexWork.command, 0))
1248 {
1249 isIirFilterSetting = FALSE;
1250 return SNDEX_RESULT_PXI_SEND_ERROR;
1251 }
1252
1253 return SNDEX_RESULT_SUCCESS;
1254 }
1255
1256 /*---------------------------------------------------------------------------*
1257 Name: SNDEXi_SetIirFilter
1258
1259 Description: Sets the IIR filter (Biquad) parameters.
1260
1261 Arguments: target:
1262 pParam:
1263
1264 Returns: None.
1265 *---------------------------------------------------------------------------*/
1266 SNDEXResult
SNDEXi_SetIirFilter(SNDEXIirFilterTarget target,const SNDEXIirFilterParam * pParam)1267 SNDEXi_SetIirFilter(SNDEXIirFilterTarget target, const SNDEXIirFilterParam* pParam)
1268 {
1269 SNDEXResult result;
1270 OSMessageQueue msgQ;
1271 OSMessage msg[1];
1272
1273 /* Calling this from an exception handler is prohibited */
1274 if (OS_GetCurrentThread() == NULL)
1275 {
1276 SNDEXi_Warning("%s: Syncronous API could not process in exception handler.\n", __FUNCTION__);
1277 return SNDEX_RESULT_ILLEGAL_STATE;
1278 }
1279
1280 /* Initialize the message queue used for synchronization */
1281 OS_InitMessageQueue(&msgQ, msg, 1);
1282
1283 result = SNDEXi_SetIirFilterAsync(target, pParam, SyncCallback, (void*)(&msgQ));
1284 if (result == SNDEX_RESULT_SUCCESS)
1285 {
1286 (void)OS_ReceiveMessage(&msgQ, (OSMessage*)(&result), OS_MESSAGE_BLOCK);
1287 }
1288
1289 // Assume that the SPI_Lock was ended by SetIirFilter, and lower the flag
1290 isLockSpi = FALSE;
1291
1292 isIirFilterSetting = FALSE;
1293
1294 return result;
1295 }
1296
1297 /*---------------------------------------------------------------------------*
1298 Name: SNDEX_IsConnectedHeadphoneAsync
1299
1300 Description: Gets whether headphones are connected.
1301
1302 Arguments: hp: Specifies the buffer used to get headphone connection status.
1303 callback: Specifies the callback function that notifies of the results when the asynchronous process is completed.
1304
1305 arg: Specifies parameter passed to the callback function.
1306
1307 Returns: SNDEXResult: Returns processing results.
1308 When returning SNDEX_RESULT_SUCCESS, the actual processing results are notified to the function registered to the callback after the asynchronous process is complete.
1309
1310 *---------------------------------------------------------------------------*/
1311 SNDEXResult
SNDEXi_IsConnectedHeadphoneAsync(SNDEXHeadphone * hp,SNDEXCallback callback,void * arg)1312 SNDEXi_IsConnectedHeadphoneAsync(SNDEXHeadphone *hp, SNDEXCallback callback, void* arg)
1313 {
1314 /* Confirm status */
1315 {
1316 SNDEXResult result = CheckState();
1317 if (result != SNDEX_RESULT_SUCCESS)
1318 {
1319 return result;
1320 }
1321 }
1322
1323 /* Register asynchronous process */
1324 SetSndexWork(callback, arg, (void*)hp, SNDEX_PXI_COMMAND_HP_CONNECT);
1325
1326 /* Issue command to ARM7 */
1327 if (FALSE == SendCommand(sndexWork.command, 0))
1328 {
1329 return SNDEX_RESULT_PXI_SEND_ERROR;
1330 }
1331 return SNDEX_RESULT_SUCCESS;
1332 }
1333
1334 /*---------------------------------------------------------------------------*
1335 Name: SNDEX_IsConnectedHeadphone
1336
1337 Description: Gets whether headphones are connected.�B
1338
1339 Arguments: hp: Specifies the buffer used to get headphone connection status.
1340
1341 Returns: SNDEXResult: Returns processing results.
1342 When returning SNDEX_RESULT_SUCCESS, the actual processing results are notified to the function registered to the callback after the asynchronous process is complete.
1343
1344 *---------------------------------------------------------------------------*/
1345 SNDEXResult
SNDEXi_IsConnectedHeadphone(SNDEXHeadphone * hp)1346 SNDEXi_IsConnectedHeadphone(SNDEXHeadphone *hp)
1347 {
1348 SNDEXResult result;
1349 OSMessageQueue msgQ;
1350 OSMessage msg[1];
1351
1352 /* Calling this from an exception handler is prohibited */
1353 if (OS_GetCurrentThread() == NULL)
1354 {
1355 SNDEXi_Warning("%s: Syncronous API could not process in exception handler.\n", __FUNCTION__);
1356 return SNDEX_RESULT_ILLEGAL_STATE;
1357 }
1358
1359 /* Initialize the message queue used for synchronization */
1360 OS_InitMessageQueue(&msgQ, msg, 1);
1361
1362 /* Execute the asynchronous function and idle the callback */
1363 result = SNDEXi_IsConnectedHeadphoneAsync(hp, SyncCallback, (void*)(&msgQ));
1364 if (result == SNDEX_RESULT_SUCCESS)
1365 {
1366 (void)OS_ReceiveMessage(&msgQ, (OSMessage*)(&result), OS_MESSAGE_BLOCK);
1367 }
1368 return result;
1369 }
1370
1371 /*---------------------------------------------------------------------------*
1372 Name: SNDEXi_SetVolumeSwitchCallback
1373
1374 Description: Sets the callback function that is called when the volume button is pressed.
1375
1376 Arguments: callback: Specifies the callback function called when the volume button is pressed.
1377 arg: Specifies parameter passed to the callback function.
1378
1379 Returns: None.
1380 *---------------------------------------------------------------------------*/
SNDEXi_SetVolumeSwitchCallback(SNDEXCallback callback,void * arg)1381 void SNDEXi_SetVolumeSwitchCallback(SNDEXCallback callback, void* arg)
1382 {
1383 SNDEXi_VolumeSwitchCallbackInfo.callback = callback;
1384 SNDEXi_VolumeSwitchCallbackInfo.cbArg = arg;
1385 }
1386
1387 /*---------------------------------------------------------------------------*
1388 Name: SNDEXi_SetIgnoreHWVolume
1389
1390 Description: If you need to play a sound (such as the clock's alarm tone) at a specified volume regardless of the value set for the system volume at the time, you must change the volume without user input.
1391 This function saves the volume before changing it.
1392
1393
1394
1395 Arguments: volume: The value to change the volume to.
1396
1397 Returns: SNDEXResult: Returns processing results. This is the result of an SNDEX function called internally.
1398 *---------------------------------------------------------------------------*/
SNDEXi_SetIgnoreHWVolume(u8 volume,BOOL eightlv)1399 SNDEXResult SNDEXi_SetIgnoreHWVolume(u8 volume, BOOL eightlv)
1400 {
1401 SNDEXResult result;
1402 result = eightlv ? SNDEX_GetVolume(&storeVolume) : SNDEXi_GetVolumeEx(&storeVolume);
1403 if (result != SNDEX_RESULT_SUCCESS)
1404 {
1405 return result;
1406 }
1407
1408 // Change the volume to the specified value
1409 result = eightlv ? SNDEX_SetVolume(volume) : SNDEXi_SetVolumeEx(volume);
1410 if (result != SNDEX_RESULT_SUCCESS)
1411 {
1412 return result;
1413 }
1414
1415 isStoreVolume = TRUE;
1416 return result; // SNDEX_RESULT_SUCCESS
1417 }
1418
1419 /*---------------------------------------------------------------------------*
1420 Name: SNDEXi_ResetIgnoreHWVolume
1421
1422 Description: Restores the volume to its value before changed by SNDEX_SetIgnoreHWVolume.
1423 This removes the registered termination callback at the same time.
1424
1425 Arguments: None.
1426
1427 Returns: SNDEXResult: Returns processing results.
1428 *---------------------------------------------------------------------------*/
SNDEXi_ResetIgnoreHWVolume(void)1429 SNDEXResult SNDEXi_ResetIgnoreHWVolume(void)
1430 {
1431 SNDEXResult result;
1432 if ((result = SNDEX_SetVolume(storeVolume)) != SNDEX_RESULT_SUCCESS)
1433 {
1434 return result;
1435 }
1436
1437 isStoreVolume = FALSE;
1438 return result; // SNDEX_RESULT_SUCCESS
1439 }
1440
1441 /*---------------------------------------------------------------------------*
1442 Name: SNDEXi_PreProcessForShutterSound
1443
1444 Description: Function that performs all the preprocessing necessary for shutter sound playback.
1445 This is a synchronous function, so calling from within an interrupt handler is prohibited.
1446
1447 Arguments: None.
1448
1449 Returns: Returns SNDEX_RESULT_SUCCESS if successful.
1450 *---------------------------------------------------------------------------*/
1451 SNDEXResult
SNDEXi_PreProcessForShutterSound(void)1452 SNDEXi_PreProcessForShutterSound (void)
1453 {
1454 SNDEXResult result;
1455 OSMessageQueue msgQ;
1456 OSMessage msg[1];
1457
1458 /* Check CODEC operating mode */
1459 if (OSi_IsCodecTwlMode() == FALSE)
1460 {
1461 return SNDEX_RESULT_ILLEGAL_STATE;
1462 }
1463
1464 /* Calling this from an exception handler is prohibited */
1465 if (OS_GetCurrentThread() == NULL)
1466 {
1467 SNDEXi_Warning("%s: Syncronous API could not process in exception handler.\n", __FUNCTION__);
1468 return SNDEX_RESULT_ILLEGAL_STATE;
1469 }
1470
1471 /* Skip CheckState if SNDEXi_PreProcessForShutterSound() has already been called. */
1472 if (sndexState != SNDEX_STATE_PLAY_SHUTTER)
1473 {
1474 /* Confirm status */
1475 result = CheckState();
1476 if (result != SNDEX_RESULT_SUCCESS)
1477 {
1478 return result;
1479 }
1480 }
1481 else if (sndexState == SNDEX_STATE_POST_PROC_SHUTTER)
1482 {
1483 return SNDEX_RESULT_EXCLUSIVE;
1484 }
1485
1486 /* Initialize the message queue used for synchronization */
1487 OS_InitMessageQueue(&msgQ, msg, 1);
1488
1489
1490 /* Register process */
1491 SetSndexWork(SyncCallback, (void*)(&msgQ), NULL, SNDEX_PXI_COMMAND_PRE_PROC_SHUTTER);
1492
1493 /* Issue command to ARM7 */
1494 if (FALSE == SendCommand(sndexWork.command, 0))
1495 {
1496 return SNDEX_RESULT_PXI_SEND_ERROR;
1497 }
1498
1499 /* Wait for reply */
1500 (void)OS_ReceiveMessage(&msgQ, (OSMessage*)(&result), OS_MESSAGE_BLOCK);
1501
1502 return result;
1503 }
1504
1505 /*---------------------------------------------------------------------------*
1506 Name: SNDEXi_PostProcessCallbackForShutterSound
1507
1508 Description: Executes postprocessing for shutter sound playback.
1509 This is executed asynchronously because it is executed within an interrupt.
1510
1511 Arguments: callback: Specifies the callback function called when the postprocessing completes.
1512 arg: Specifies parameter passed to the callback function.
1513
1514 Returns: Returns SNDEX_RESULT_SUCCESS if successful.
1515 *---------------------------------------------------------------------------*/
1516 SNDEXResult
SNDEXi_PostProcessForShutterSound(SNDEXCallback callback,void * arg)1517 SNDEXi_PostProcessForShutterSound (SNDEXCallback callback, void* arg)
1518 {
1519 /* Check CODEC operating mode */
1520 // When this function is called, it is presumed to be after execution of SNDEXi_PreProcessCallbackForShutterSound
1521 if (OSi_IsCodecTwlMode() == FALSE || sndexState != SNDEX_STATE_PLAY_SHUTTER)
1522 {
1523 return SNDEX_RESULT_ILLEGAL_STATE;
1524 }
1525
1526 /* Transition the state to postprocessing (maximum priority) */
1527 sndexState = SNDEX_STATE_POST_PROC_SHUTTER;
1528
1529 /* Register asynchronous process */
1530 SetSndexWork(callback, arg, NULL, SNDEX_PXI_COMMAND_POST_PROC_SHUTTER);
1531
1532 /* Issue command to ARM7 */
1533 if (FALSE == SendCommand(sndexWork.command, 0))
1534 {
1535 return SNDEX_RESULT_PXI_SEND_ERROR;
1536 }
1537
1538 return SNDEX_RESULT_SUCCESS;
1539 }
1540
1541 /*---------------------------------------------------------------------------*
1542 Name: CommonCallback
1543
1544 Description: PXI FIFO reception callback function for processes related to the extended sound features.
1545
1546 Arguments: tag: PXI message type
1547 data: Message content from ARM7
1548 err: PXI transfer error flag
1549
1550 Returns: None.
1551 *---------------------------------------------------------------------------*/
1552 static void
CommonCallback(PXIFifoTag tag,u32 data,BOOL err)1553 CommonCallback (PXIFifoTag tag, u32 data, BOOL err)
1554 {
1555 u8 command = (u8)((data & SNDEX_PXI_COMMAND_MASK) >> SNDEX_PXI_COMMAND_SHIFT);
1556 u8 result = (u8)((data & SNDEX_PXI_RESULT_MASK) >> SNDEX_PXI_RESULT_SHIFT);
1557 u8 param = (u8)((data & SNDEX_PXI_PARAMETER_MASK) >> SNDEX_PXI_PARAMETER_SHIFT);
1558
1559 /* If the command received from ARM7 is a notification that the system volume switch was pressed, try locking */
1560 if (command == SNDEX_PXI_COMMAND_PRESS_VOLSWITCH)
1561 {
1562 SNDEXResult result = CheckState();
1563 if (result != SNDEX_RESULT_SUCCESS)
1564 {
1565 return;
1566 }
1567 // Set the sndexWork structure
1568 SetSndexWork(NULL, NULL, NULL, SNDEX_PXI_COMMAND_PRESS_VOLSWITCH);
1569 }
1570
1571 /* Confirm status */
1572 if ((tag != PXI_FIFO_TAG_SNDEX) || (err == TRUE)
1573 || (sndexState != SNDEX_STATE_LOCKED && sndexState != SNDEX_STATE_PLAY_SHUTTER && sndexState != SNDEX_STATE_POST_PROC_SHUTTER)
1574 || (sndexWork.command != command))
1575 {
1576 /* Logically, execution will never be able to pass through here, but output a warning just in case */
1577 OS_TWarning("SNDEX: Library state is inconsistent.\n");
1578 ReplyCallback(SNDEX_RESULT_FATAL_ERROR);
1579 return;
1580 }
1581
1582 /* Parse the process results */
1583 switch (result)
1584 {
1585 case SNDEX_PXI_RESULT_SUCCESS:
1586 /* Perform completion processing in accordance with the command */
1587 switch (command)
1588 {
1589 case SNDEX_PXI_COMMAND_GET_SMIX_MUTE:
1590 if (sndexWork.dest != NULL)
1591 {
1592 *((SNDEXMute*)sndexWork.dest) = (SNDEXMute)param;
1593 }
1594 break;
1595 case SNDEX_PXI_COMMAND_GET_SMIX_FREQ:
1596 if (sndexWork.dest != NULL)
1597 {
1598 *((SNDEXFrequency*)sndexWork.dest) = (SNDEXFrequency)param;
1599 }
1600 break;
1601 case SNDEX_PXI_COMMAND_GET_SMIX_DSP:
1602 case SNDEX_PXI_COMMAND_GET_VOLUME:
1603 if (sndexWork.dest != NULL)
1604 {
1605 *((u8*)sndexWork.dest) = param;
1606 }
1607 break;
1608 case SNDEX_PXI_COMMAND_GET_SND_DEVICE:
1609 if (sndexWork.dest != NULL)
1610 {
1611 *((SNDEXDevice*)sndexWork.dest) = (SNDEXDevice)param;
1612 }
1613 break;
1614 case SNDEX_PXI_COMMAND_PRESS_VOLSWITCH:
1615 /* Notification from ARM7 that the volume button was pressed */
1616 if (SNDEXi_VolumeSwitchCallbackInfo.callback != NULL)
1617 {
1618 (SNDEXi_VolumeSwitchCallbackInfo.callback)((SNDEXResult)result, SNDEXi_VolumeSwitchCallbackInfo.cbArg);
1619 }
1620 break;
1621 case SNDEX_PXI_COMMAND_HP_CONNECT:
1622 if (sndexWork.dest != NULL)
1623 {
1624 *((SNDEXHeadphone*)sndexWork.dest) = (SNDEXHeadphone)param;
1625 }
1626 break;
1627 }
1628 ReplyCallback(SNDEX_RESULT_SUCCESS);
1629 break;
1630 case SNDEX_PXI_RESULT_INVALID_PARAM:
1631 ReplyCallback(SNDEX_RESULT_INVALID_PARAM);
1632 break;
1633 case SNDEX_PXI_RESULT_EXCLUSIVE:
1634 ReplyCallback(SNDEX_RESULT_EXCLUSIVE);
1635 break;
1636 case SNDEX_PXI_RESULT_ILLEGAL_STATE:
1637 ReplyCallback(SNDEX_RESULT_ILLEGAL_STATE);
1638 break;
1639 case SNDEX_PXI_RESULT_DEVICE_ERROR:
1640 if (command == SNDEX_PXI_COMMAND_GET_VOLUME)
1641 {
1642 if (sndexWork.dest != NULL)
1643 {
1644 *((u8*)sndexWork.dest) = SNDEX_VOLUME_MIN;
1645 }
1646 }
1647 ReplyCallback(SNDEX_RESULT_DEVICE_ERROR);
1648 break;
1649 case SNDEX_PXI_RESULT_INVALID_COMMAND:
1650 default:
1651 ReplyCallback(SNDEX_RESULT_FATAL_ERROR);
1652 break;
1653 }
1654 }
1655
1656 /*---------------------------------------------------------------------------*
1657 Name: SyncCallback
1658
1659 Description: Shared callback function for synchronous function control.
1660
1661 Arguments: result: Result of asynchronous processing.
1662 arg: Message being blocked by the synchronous function while it waits for reception.
1663 Pointer to queue control structure.
1664
1665 Returns: None.
1666 *---------------------------------------------------------------------------*/
1667 static void
SyncCallback(SNDEXResult result,void * arg)1668 SyncCallback (SNDEXResult result, void* arg)
1669 {
1670 SDK_NULL_ASSERT(arg);
1671
1672 if (FALSE == OS_SendMessage((OSMessageQueue*)arg, (OSMessage)result, OS_MESSAGE_NOBLOCK))
1673 {
1674 /* Logically, execution will never be able to pass through here, but output a warning just in case */
1675 OS_TWarning("SNDEX: Temporary message queue is full.\n");
1676 }
1677 }
1678
1679 /*---------------------------------------------------------------------------*
1680 Name: SendCommand
1681
1682 Description: Issues an extended sound feature operation command to ARM7 via PXI.
1683
1684 Arguments: command: Command type.
1685 param: Parameter associated with the command.
1686
1687 Returns: BOOL: Returns TRUE if PXI transmission was successful.
1688 *---------------------------------------------------------------------------*/
1689 static BOOL
SendCommand(u8 command,u8 param)1690 SendCommand (u8 command, u8 param)
1691 {
1692 OSIntrMode e = OS_DisableInterrupts();
1693 u32 packet = (u32)(((command << SNDEX_PXI_COMMAND_SHIFT) & SNDEX_PXI_COMMAND_MASK)
1694 | ((param << SNDEX_PXI_PARAMETER_SHIFT) & SNDEX_PXI_PARAMETER_MASK));
1695
1696 if (0 > PXI_SendWordByFifo(PXI_FIFO_TAG_SNDEX, packet, 0))
1697 {
1698 /* Lift exclusion controls if transmission failed */
1699 sndexState = SNDEX_STATE_INITIALIZED;
1700 (void)OS_RestoreInterrupts(e);
1701 SNDEXi_Warning("SNDEX: Failed to send PXI command.\n");
1702 return FALSE;
1703 }
1704
1705 (void)OS_RestoreInterrupts(e);
1706 return TRUE;
1707 }
1708
1709 /*---------------------------------------------------------------------------*
1710 Name: SendCommand
1711
1712 Description: Issues an extended sound feature operation command to ARM7 via PXI.
1713
1714 Arguments: command: Command type.
1715 param: Parameter associated with the command (16 bits because of the IirFilter parameter).
1716
1717 Returns: BOOL: Returns TRUE if PXI transmission was successful.
1718 *---------------------------------------------------------------------------*/
1719 static BOOL
SendCommandEx(u8 command,u16 param)1720 SendCommandEx (u8 command, u16 param)
1721 {
1722 OSIntrMode e = OS_DisableInterrupts();
1723 u32 packet = (u32)(((command << SNDEX_PXI_COMMAND_SHIFT) & SNDEX_PXI_COMMAND_MASK)
1724 | ((param << SNDEX_PXI_PARAMETER_SHIFT) & SNDEX_PXI_PARAMETER_MASK_IIR));
1725
1726 if (0 > PXI_SendWordByFifo(PXI_FIFO_TAG_SNDEX, packet, 0))
1727 {
1728 /* Lift exclusion controls if transmission failed */
1729 sndexState = SNDEX_STATE_INITIALIZED;
1730 (void)OS_RestoreInterrupts(e);
1731 SNDEXi_Warning("SNDEX: Failed to send PXI command.\n");
1732 return FALSE;
1733 }
1734 if( command == SNDEX_PXI_COMMAND_SET_IIRFILTER )
1735 {
1736 isLockSpi = TRUE;
1737 }
1738
1739 (void)OS_RestoreInterrupts(e);
1740 return TRUE;
1741 }
1742
1743 /*---------------------------------------------------------------------------*
1744 Name: CheckState
1745
1746 Description: Checks whether the internal state is one where an asynchronous process can start, and if so, locks the SNDEX library.
1747
1748
1749 Arguments: None.
1750
1751 Returns: None.
1752 *---------------------------------------------------------------------------*/
1753 static SNDEXResult
CheckState(void)1754 CheckState (void)
1755 {
1756 OSIntrMode e = OS_DisableInterrupts();
1757
1758 /* Check internal state */
1759 switch (sndexState)
1760 {
1761 case SNDEX_STATE_BEFORE_INIT:
1762 case SNDEX_STATE_INITIALIZING:
1763 (void)OS_RestoreInterrupts(e);
1764 SNDEXi_Warning("SNDEX: Library is not initialized yet.\n");
1765 return SNDEX_RESULT_BEFORE_INIT;
1766 case SNDEX_STATE_LOCKED:
1767 case SNDEX_STATE_PLAY_SHUTTER:
1768 case SNDEX_STATE_POST_PROC_SHUTTER:
1769 (void)OS_RestoreInterrupts(e);
1770 SNDEXi_Warning("SNDEX: Another request is in progress.\n");
1771 return SNDEX_RESULT_EXCLUSIVE;
1772 }
1773
1774 /* Transition to state where exclusion control is in effect */
1775 sndexState = SNDEX_STATE_LOCKED;
1776 (void)OS_RestoreInterrupts(e);
1777 return SNDEX_RESULT_SUCCESS;
1778 }
1779
1780 /*---------------------------------------------------------------------------*
1781 Name: ReplyCallback
1782
1783 Description: Sends notification of the completion of asynchronous processing.
1784 Updates the internal sate and also lifts the exclusion state.
1785
1786 Arguments: result: Asynchronous processing result to notify to the callback function.
1787
1788 Returns: None.
1789 *---------------------------------------------------------------------------*/
1790 static void
ReplyCallback(SNDEXResult result)1791 ReplyCallback (SNDEXResult result)
1792 {
1793 OSIntrMode e = OS_DisableInterrupts();
1794 SNDEXCallback callback = sndexWork.callback;
1795 void* cbArg = sndexWork.cbArg;
1796 u8 command = sndexWork.command;
1797
1798 // Assume that the SPI_Lock was ended by SetIirFilterAsync, and lower the flag
1799 if (sndexWork.command == SNDEX_PXI_COMMAND_SET_IIRFILTER)
1800 {
1801 isLockSpi = FALSE;
1802 isIirFilterSetting = FALSE;
1803 }
1804
1805 /* Reset state */
1806 SetSndexWork(NULL, NULL, NULL, 0);
1807 // If currently preprocessing the shutter sound playback, do not unlock until postprocessing begins
1808 if (command == SNDEX_PXI_COMMAND_PRE_PROC_SHUTTER)
1809 {
1810 // Anything other than the SNDEXi_PostProcessForShutterSound() function, which performs shutter sound playback postprocessing, is considered locked and is excluded.
1811 //
1812 sndexState = SNDEX_STATE_PLAY_SHUTTER;
1813 }
1814 else
1815 {
1816 sndexState = SNDEX_STATE_INITIALIZED;
1817 }
1818 (void)OS_RestoreInterrupts(e);
1819
1820 /* Call the registered callback function */
1821 if (callback != NULL)
1822 {
1823 callback(result, cbArg);
1824 }
1825 }
1826
1827 /*---------------------------------------------------------------------------*
1828 Name: SetSndexWork
1829
1830 Description: Sets parameters for sndexWork.
1831
1832 Arguments: cb: Pointer to the callback function.
1833 cbarg: Argument to pass to 'cb'.
1834 dst: Pointer to a variable to store the command's processing results.
1835 command: Command to send to ARM7.
1836
1837 Returns: None.
1838 *---------------------------------------------------------------------------*/
1839 static void
SetSndexWork(SNDEXCallback cb,void * cbarg,void * dst,u8 command)1840 SetSndexWork (SNDEXCallback cb, void* cbarg, void* dst, u8 command)
1841 {
1842 sndexWork.callback = cb;
1843 sndexWork.cbArg = cbarg;
1844 sndexWork.dest = dst;
1845 sndexWork.command = command;
1846 }
1847
1848 /*---------------------------------------------------------------------------*
1849 Name: SndexSleepAndExitCallback
1850
1851 Description: This callback function is invoked at hardware reset, shutdown or transitioning to sleep.
1852
1853
1854 Arguments: arg
1855
1856 Returns: None.
1857 *---------------------------------------------------------------------------*/
1858 static void
SndexSleepAndExitCallback(void * arg)1859 SndexSleepAndExitCallback (void *arg)
1860 {
1861 #pragma unused( arg )
1862 // Always wait for IIR filter processing to finish first, because while it is running other SNDEX functions may be exclusively locked in the SNDEX library.
1863 //
1864 WaitIirFilterSetting();
1865
1866 ResetTempVolume();
1867 }
1868
1869 /*---------------------------------------------------------------------------*
1870 Name: WaitIirFilterSetting
1871
1872 Description: Waits for SNDEX_SetIirFilter[Async] to end.
1873
1874 Arguments: None.
1875
1876 Returns: None.
1877 *---------------------------------------------------------------------------*/
1878 static void
WaitIirFilterSetting(void)1879 WaitIirFilterSetting (void)
1880 {
1881 // Continue waiting until the SPI_Lock within SNDEX_SetIirFilter[Async] ends
1882 while (isLockSpi)
1883 {
1884 OS_SpinWait(67 * 1000); //Approximately 1 ms
1885 PXIi_HandlerRecvFifoNotEmpty();
1886 }
1887 }
1888
1889 /*---------------------------------------------------------------------------*
1890 Name: ResetTempVolume
1891
1892 Description: Reverts to the volume that was temporarily saved by SNDEXi_SetIgnoreHWVolume.
1893
1894 Arguments: None.
1895
1896 Returns: None.
1897 *---------------------------------------------------------------------------*/
1898 static void
ResetTempVolume(void)1899 ResetTempVolume (void)
1900 {
1901 if (isStoreVolume)
1902 {
1903 // Revert to the volume that was temporarily saved by SNDEXi_SetIgnoreHWVolume
1904 // Repeats until the volume is successfully changed
1905 while (SNDEX_SetVolume(storeVolume) != SNDEX_RESULT_SUCCESS) {}
1906 isStoreVolume = FALSE;
1907 }
1908 }
1909
1910