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-29#$
14 $Rev: 10832 $
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 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 = 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
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 = SNDEXi_SetVolumeEx(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: Performs all the preprocessing necessary for shutter sound playback.
1445 This is a synchronous function, so calling from inside 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 the SNDEXi_PreProcessForShutterSound function 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 inside an interrupt.
1510
1511 Arguments: callback: Callback function called when the postprocessing completes
1512 arg: 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. Updates the internal sate and also lifts the exclusion state.
1784
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 transition to Sleep Mode.
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 in SNDEX_SetIirFilter[Async] ends
1882 while (isLockSpi)
1883 {
1884 OS_SpinWait(67 * 1000); //Approximately 1 ms
1885 PXIi_HandlerRecvFifoNotEmpty();
1886 }
1887 }
1888
1889 static void
WaitResetSoundCallback(SNDEXResult result,void * arg)1890 WaitResetSoundCallback(SNDEXResult result, void* arg)
1891 {
1892 static u32 i = 0; // Retry up to 5 times
1893 #pragma unused(arg)
1894 if (result != SNDEX_RESULT_SUCCESS && i < 5)
1895 {
1896 (void)SNDEXi_SetVolumeExAsync(storeVolume, WaitResetSoundCallback, NULL);
1897 i++;
1898 return;
1899 }
1900 isStoreVolume = FALSE;
1901 }
1902
1903 /*---------------------------------------------------------------------------*
1904 Name: ResetTempVolume
1905
1906 Description: Reverts to the volume that was temporarily saved by SNDEXi_SetIgnoreHWVolume.
1907
1908 Arguments: None.
1909
1910 Returns: None.
1911 *---------------------------------------------------------------------------*/
1912 static void
ResetTempVolume(void)1913 ResetTempVolume (void)
1914 {
1915 if (isStoreVolume)
1916 {
1917 static i = 0; // Retry up to 5 times
1918 // Revert to the volume that was temporarily saved by SNDEXi_SetIgnoreHWVolume
1919 // Repeat until the asynchronous function runs successfully
1920 // The callback will handle retries based on the result of changing the volume
1921 while( SNDEX_RESULT_SUCCESS != SNDEXi_SetVolumeExAsync(storeVolume, WaitResetSoundCallback, NULL) && i < 5)
1922 {
1923 i++;
1924 }
1925 while (isStoreVolume)
1926 {
1927 OS_SpinWait(67 * 1000); //Approximately 1 ms
1928 PXIi_HandlerRecvFifoNotEmpty();
1929 }
1930 }
1931 }
1932