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