1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - libraries - mic
3 File: micex.c
4
5 Copyright 2007-2008 Nintendo. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain
8 proprietary information of Nintendo of America Inc. and/or Nintendo
9 Company Ltd., and are protected by Federal copyright law. They may
10 not be disclosed to third parties or copied or duplicated in any form,
11 in whole or in part, without the prior written consent of Nintendo.
12
13 $Date:: 2008-09-17#$
14 $Rev: 8556 $
15 $Author: okubata_ryoma $
16 *---------------------------------------------------------------------------*/
17
18 #include <nitro/os.h>
19 #include <nitro/spi.h>
20 #include "micex.h"
21
22 #include <twl/spi/common/mic_common.h>
23
24 /*---------------------------------------------------------------------------*
25 Internal Function Definitions
26 *---------------------------------------------------------------------------*/
27 static void MicexSyncCallback(MICResult result, void* arg);
28 static BOOL MicexStartLimitedSampling(void* buf, u32 size, u32 rate, u8 flags);
29 static BOOL MicexStopLimitedSampling(void);
30 static BOOL MicexAdjustLimitedSampling(u32 rate);
31
32 /*---------------------------------------------------------------------------*
33 Name: MICEXi_StartLimitedSampling
34 Description: Starts sampling rate limited microphone auto-sampling.
35 This is a synchronous function, so calling from within an interrupt handler is prohibited.
36 Arguments: param: - Pointer to a structure that specifies auto sampling settings
37 Returns: MICResult: Returns synchronous processing results.
38 *---------------------------------------------------------------------------*/
39 MICResult
MICEXi_StartLimitedSampling(const MICAutoParam * param)40 MICEXi_StartLimitedSampling(const MICAutoParam* param)
41 {
42 MICResult result;
43 OSMessageQueue msgQ;
44 OSMessage msg[1];
45
46 /* Calling this from within an interrupt handler is prohibited */
47 if (OS_GetCurrentThread() == NULL)
48 {
49 #ifdef SDK_DEBUG
50 OS_TWarning("%s: Could not process in exception handler.\n", __FUNCTION__);
51 #endif
52 return MIC_RESULT_ILLEGAL_STATUS;
53 }
54
55 /* Initialize the message queue for getting responses */
56 OS_InitMessageQueue(&msgQ, msg, 1);
57
58 /* Execute the asynchronous function and idle the callback */
59 result = MICEXi_StartLimitedSamplingAsync(param, MicexSyncCallback, (void*)(&msgQ));
60 if (result == MIC_RESULT_SUCCESS)
61 {
62 (void)OS_ReceiveMessage(&msgQ, (OSMessage*)(&result), OS_MESSAGE_BLOCK);
63 }
64 return result;
65 }
66
67 /*---------------------------------------------------------------------------*
68 Name: MICEXi_StartLimitedSamplingAsync
69 Description: Starts sampling rate limited microphone auto-sampling.
70 This is an asynchronous function, so the actual processing results are passed when the callback is called.
71 Arguments: param: Pointer to a structure that specifies auto-sampling settings.
72 callback: Specifies the callback function to call when asynchronous processing is completed.
73 arg: Specifies parameter passed to the callback function.
74 Returns: MICResult: Returns the results of starting the asynchronous process.
75 *---------------------------------------------------------------------------*/
76 MICResult
MICEXi_StartLimitedSamplingAsync(const MICAutoParam * param,MICCallback callback,void * arg)77 MICEXi_StartLimitedSamplingAsync(const MICAutoParam* param, MICCallback callback, void* arg)
78 {
79 OSIntrMode e;
80 MICWork* w = MICi_GetSysWork();
81 u8 flags;
82
83 SDK_NULL_ASSERT(callback);
84 SDK_NULL_ASSERT(param->buffer);
85
86 /* Confirms parameters */
87 {
88 /* Buffer size */
89 if (param->size <= 0)
90 {
91 #ifdef SDK_DEBUG
92 OS_TWarning("%s: Illegal desination buffer size. (%d)\n", __FUNCTION__, param->size);
93 #endif
94 return MIC_RESULT_ILLEGAL_PARAMETER;
95 }
96 /* 32-byte buffer alignment */
97 if (((u32)(param->buffer) % HW_CACHE_LINE_SIZE != 0) || ((param->size % HW_CACHE_LINE_SIZE) != 0))
98 {
99 #ifdef SDK_DEBUG
100 OS_TWarning("%s: Destination buffer (%p - %p) is not aligned on %d bytes boundary.\n",
101 __FUNCTION__, param->buffer, (void*)((u32)param->buffer + param->size), HW_CACHE_LINE_SIZE);
102 #endif
103 return MIC_RESULT_ILLEGAL_PARAMETER;
104 }
105 /* AD conversion bit width */
106 switch (param->type)
107 {
108 case MIC_SAMPLING_TYPE_8BIT:
109 flags = SPI_MIC_SAMPLING_TYPE_8BIT;
110 break;
111 case MIC_SAMPLING_TYPE_12BIT:
112 flags = SPI_MIC_SAMPLING_TYPE_12BIT;
113 break;
114 case MIC_SAMPLING_TYPE_SIGNED_8BIT:
115 flags = SPI_MIC_SAMPLING_TYPE_S8BIT;
116 break;
117 case MIC_SAMPLING_TYPE_SIGNED_12BIT:
118 flags = SPI_MIC_SAMPLING_TYPE_S12BIT;
119 break;
120 case MIC_SAMPLING_TYPE_12BIT_FILTER_OFF:
121 flags = (SPI_MIC_SAMPLING_TYPE_12BIT | SPI_MIC_SAMPLING_TYPE_FILTER_OFF);
122 break;
123 case MIC_SAMPLING_TYPE_SIGNED_12BIT_FILTER_OFF:
124 flags = (SPI_MIC_SAMPLING_TYPE_S12BIT | SPI_MIC_SAMPLING_TYPE_FILTER_OFF);
125 break;
126 default:
127 #ifdef SDK_DEBUG
128 OS_TWarning("%s: Illegal sampling type. (%d)\n", __FUNCTION__, param->type);
129 #endif
130 return MIC_RESULT_ILLEGAL_PARAMETER;
131 }
132 /* sampling period */
133 switch (param->rate)
134 {
135 case MIC_SAMPLING_RATE_32730: case MIC_SAMPLING_RATE_16360:
136 case MIC_SAMPLING_RATE_10910: case MIC_SAMPLING_RATE_8180:
137 case MIC_SAMPLING_RATE_47610: case MIC_SAMPLING_RATE_23810:
138 case MIC_SAMPLING_RATE_15870: case MIC_SAMPLING_RATE_11900:
139 break;
140 default:
141 #ifdef SDK_TWL
142 OS_TWarning("%s: Illegal sampling rate. (%d)\n", __FUNCTION__, param->rate);
143 #endif
144 return MIC_RESULT_ILLEGAL_PARAMETER;
145 }
146 /* Enable/disable loop */
147 if (param->loop_enable)
148 {
149 flags = (u8)((flags & ~SPI_MIC_SAMPLING_TYPE_LOOP_MASK) | SPI_MIC_SAMPLING_TYPE_LOOP_ON);
150 }
151 else
152 {
153 flags = (u8)((flags & ~SPI_MIC_SAMPLING_TYPE_LOOP_MASK) | SPI_MIC_SAMPLING_TYPE_LOOP_OFF);
154 }
155 /* Correction flag for expansions */
156 flags = (u8)((flags & ~SPI_MIC_SAMPLING_TYPE_CORRECT_MASK) | SPI_MIC_SAMPLING_TYPE_CORRECT_OFF);
157 }
158
159 /* Check exclusion lock */
160 e = OS_DisableInterrupts();
161 if (w->lock != MIC_LOCK_OFF)
162 {
163 (void)OS_RestoreInterrupts(e);
164 return MIC_RESULT_BUSY;
165 }
166 w->lock = MIC_LOCK_ON;
167 (void)OS_RestoreInterrupts(e);
168
169 /* Send command for restricted auto-sampling start */
170 w->callback = callback;
171 w->callbackArg = arg;
172 w->full = param->full_callback;
173 w->fullArg = param->full_arg;
174 if (MicexStartLimitedSampling(param->buffer, param->size, param->rate, flags))
175 {
176 return MIC_RESULT_SUCCESS;
177 }
178 w->lock = MIC_LOCK_OFF;
179 return MIC_RESULT_SEND_ERROR;
180 }
181
182 /*---------------------------------------------------------------------------*
183 Name: MICEXi_StopLimitedSampling
184 Description: Stops sampling rate limited microphone auto-sampling.
185 This is a synchronous function, so calling from within an interrupt handler is prohibited.
186 Arguments: None.
187 Returns: MICResult: Returns synchronous processing results.
188 *---------------------------------------------------------------------------*/
189 MICResult
MICEXi_StopLimitedSampling(void)190 MICEXi_StopLimitedSampling(void)
191 {
192 MICResult result;
193 OSMessageQueue msgQ;
194 OSMessage msg[1];
195
196 /* Calling this from within an interrupt handler is prohibited */
197 if (OS_GetCurrentThread() == NULL)
198 {
199 #ifdef SDK_DEBUG
200 OS_TWarning("%s: Could not process in exception handler.\n", __FUNCTION__);
201 #endif
202 return MIC_RESULT_ILLEGAL_STATUS;
203 }
204
205 /* Initialize the message queue for getting responses */
206 OS_InitMessageQueue(&msgQ, msg, 1);
207
208 /* Execute the asynchronous function and idle the callback */
209 result = MICEXi_StopLimitedSamplingAsync(MicexSyncCallback, (void*)(&msgQ));
210 if (result == MIC_RESULT_SUCCESS)
211 {
212 (void)OS_ReceiveMessage(&msgQ, (OSMessage*)(&result), OS_MESSAGE_BLOCK);
213 }
214 return result;
215 }
216
217 /*---------------------------------------------------------------------------*
218 Name: MICEXi_StopLimitedSamplingAsync
219 Description: Stops sampling rate limited microphone auto-sampling.
220 This is an asynchronous function, so the actual processing results are passed when the callback is called.
221 Arguments: callback: Specifies the callback function to call when asynchronous processing is completed.
222 arg: Specifies parameter passed to the callback function.
223 Returns: MICResult: Returns the results of starting the asynchronous process.
224 *---------------------------------------------------------------------------*/
225 MICResult
MICEXi_StopLimitedSamplingAsync(MICCallback callback,void * arg)226 MICEXi_StopLimitedSamplingAsync(MICCallback callback, void* arg)
227 {
228 OSIntrMode e;
229 MICWork* w = MICi_GetSysWork();
230
231 SDK_NULL_ASSERT(callback);
232
233 /* Check exclusion lock */
234 e = OS_DisableInterrupts();
235 if (w->lock != MIC_LOCK_OFF)
236 {
237 (void)OS_RestoreInterrupts(e);
238 return MIC_RESULT_BUSY;
239 }
240 w->lock = MIC_LOCK_ON;
241 (void)OS_RestoreInterrupts(e);
242
243 /* Send command to stop restricted auto-sampling */
244 w->callback = callback;
245 w->callbackArg = arg;
246 if (MicexStopLimitedSampling())
247 {
248 return MIC_RESULT_SUCCESS;
249 }
250 w->lock = MIC_LOCK_OFF;
251 return MIC_RESULT_SEND_ERROR;
252 }
253
254 /*---------------------------------------------------------------------------*
255 Name: MICEXi_AdjustLimitedSampling
256 Description: Adjusts the sampling intervals used in sampling rate limited microphone auto-sampling.
257
258 This is a synchronous function, so calling from within an interrupt handler is prohibited.
259 Arguments: rate: Specifies the sampling interval in ARM7 CPU clock units.
260 Returns: MICResult: Returns synchronous processing results.
261 *---------------------------------------------------------------------------*/
262 MICResult
MICEXi_AdjustLimitedSampling(u32 rate)263 MICEXi_AdjustLimitedSampling(u32 rate)
264 {
265 MICResult result;
266 OSMessageQueue msgQ;
267 OSMessage msg[1];
268
269 /* Calling this from within an interrupt handler is prohibited */
270 if (OS_GetCurrentThread() == NULL)
271 {
272 #ifdef SDK_DEBUG
273 OS_TWarning("%s: Could not process in exception handler.\n", __FUNCTION__);
274 #endif
275 return MIC_RESULT_ILLEGAL_STATUS;
276 }
277
278 /* Initialize the message queue for getting responses */
279 OS_InitMessageQueue(&msgQ, msg, 1);
280
281 /* Execute the asynchronous function and idle the callback */
282 result = MICEXi_AdjustLimitedSamplingAsync(rate, MicexSyncCallback, (void*)(&msgQ));
283 if (result == MIC_RESULT_SUCCESS)
284 {
285 (void)OS_ReceiveMessage(&msgQ, (OSMessage*)(&result), OS_MESSAGE_BLOCK);
286 }
287 return result;
288 }
289
290 /*---------------------------------------------------------------------------*
291 Name: MICEXi_AdjustLimitedSamplingAsync
292 Description: Adjusts the sampling intervals used in sampling rate limited microphone auto-sampling.
293
294 This is an asynchronous function, so the actual processing results are passed when the callback is called.
295 Arguments: rate: Specifies the sampling interval in ARM7 CPU clock units.
296 callback: Specifies the callback function to call when asynchronous processing is completed.
297 arg: Specifies parameter passed to the callback function.
298 Returns: MICResult: Returns the results of starting the asynchronous process.
299 *---------------------------------------------------------------------------*/
300 MICResult
MICEXi_AdjustLimitedSamplingAsync(u32 rate,MICCallback callback,void * arg)301 MICEXi_AdjustLimitedSamplingAsync(u32 rate, MICCallback callback, void* arg)
302 {
303 OSIntrMode e;
304 MICWork* w = MICi_GetSysWork();
305
306 SDK_NULL_ASSERT(callback);
307
308 /* Confirms parameters */
309 switch (rate)
310 {
311 case MIC_SAMPLING_RATE_32730: case MIC_SAMPLING_RATE_16360:
312 case MIC_SAMPLING_RATE_10910: case MIC_SAMPLING_RATE_8180:
313 case MIC_SAMPLING_RATE_47610: case MIC_SAMPLING_RATE_23810:
314 case MIC_SAMPLING_RATE_15870: case MIC_SAMPLING_RATE_11900:
315 break;
316 default:
317 #ifdef SDK_DEBUG
318 OS_TWarning("%s: Illegal sampling rate. (%d)\n", __FUNCTION__, rate);
319 #endif
320 return MIC_RESULT_ILLEGAL_PARAMETER;
321 }
322
323 /* Check exclusion lock */
324 e = OS_DisableInterrupts();
325 if (w->lock != MIC_LOCK_OFF)
326 {
327 (void)OS_RestoreInterrupts(e);
328 return MIC_RESULT_BUSY;
329 }
330 w->lock = MIC_LOCK_ON;
331 (void)OS_RestoreInterrupts(e);
332
333 /* Send command to adjust restricted auto-sampling */
334 w->callback = callback;
335 w->callbackArg = arg;
336 if (MicexAdjustLimitedSampling(rate))
337 {
338 return MIC_RESULT_SUCCESS;
339 }
340 w->lock = MIC_LOCK_OFF;
341 return MIC_RESULT_SEND_ERROR;
342 }
343
344 /*---------------------------------------------------------------------------*
345 Name: MicexSyncCallback
346 Description: Shared callback function for synchronous functions. Makes inactive threads recover to an operable state by sending them the asynchronous processing results.
347
348 Arguments: result: Passes the microphone operation asynchronous processing results.
349 arg: Passes a pointer to the message queue which the thread which calls synchronous functions is waiting to receive.
350
351 Returns: None.
352 *---------------------------------------------------------------------------*/
353 static void
MicexSyncCallback(MICResult result,void * arg)354 MicexSyncCallback(MICResult result, void* arg)
355 {
356 SDK_NULL_ASSERT(arg);
357
358 (void)OS_SendMessage((OSMessageQueue*)arg, (OSMessage)result, OS_MESSAGE_NOBLOCK);
359 }
360
361 /*---------------------------------------------------------------------------*
362 Name: MicexStartLimitedSampling
363 Description: Issues start command for restricted auto-sampling to ARM7.
364 Arguments: buf: Address of buffer storing sampled data.
365 size: Specifies the buffer size in bytes.
366 rate: Specifies the sampling interval in ARM7 CPU clock units.
367 flags - Specifies the AD conversion bit width, enabling/disabling of loops, and enabling/disabling of correction
368 Returns: BOOL: Returns TRUE when the command was successfully sent via PXI and FALSE on failure.
369
370 *---------------------------------------------------------------------------*/
371 static BOOL
MicexStartLimitedSampling(void * buf,u32 size,u32 rate,u8 flags)372 MicexStartLimitedSampling(void* buf, u32 size, u32 rate, u8 flags)
373 {
374 /* PXI Packet [0] */
375 if (0 > PXI_SendWordByFifo(PXI_FIFO_TAG_MIC,
376 SPI_PXI_START_BIT | (0 << SPI_PXI_INDEX_SHIFT) | (SPI_PXI_COMMAND_MIC_LTDAUTO_ON << 8) | (u32)flags, 0))
377 {
378 return FALSE;
379 }
380
381 /* PXI Packet [1] */
382 if (0 > PXI_SendWordByFifo(PXI_FIFO_TAG_MIC,
383 (1 << SPI_PXI_INDEX_SHIFT) | ((u32)buf >> 16), 0))
384 {
385 return FALSE;
386 }
387
388 /* PXI Packet [2] */
389 if (0 > PXI_SendWordByFifo(PXI_FIFO_TAG_MIC,
390 (2 << SPI_PXI_INDEX_SHIFT) | ((u32)buf & 0x0000ffff), 0))
391 {
392 return FALSE;
393 }
394
395 /* PXI Packet [3] */
396 if (0 > PXI_SendWordByFifo(PXI_FIFO_TAG_MIC,
397 (3 << SPI_PXI_INDEX_SHIFT) | (size >> 16), 0))
398 {
399 return FALSE;
400 }
401
402 /* PXI Packet [4] */
403 if (0 > PXI_SendWordByFifo(PXI_FIFO_TAG_MIC,
404 (4 << SPI_PXI_INDEX_SHIFT) | (size & 0x0000ffff), 0))
405 {
406 return FALSE;
407 }
408
409 /* PXI Packet [5] */
410 if (0 > PXI_SendWordByFifo(PXI_FIFO_TAG_MIC,
411 (5 << SPI_PXI_INDEX_SHIFT) | (rate >> 16), 0))
412 {
413 return FALSE;
414 }
415
416 /* PXI Packet [6] */
417 if (0 > PXI_SendWordByFifo(PXI_FIFO_TAG_MIC,
418 SPI_PXI_END_BIT | (6 << SPI_PXI_INDEX_SHIFT) | (rate & 0x0000ffff), 0))
419 {
420 return FALSE;
421 }
422 return TRUE;
423 }
424
425 /*---------------------------------------------------------------------------*
426 Name: MicexStopLimitedSampling
427 Description: Issues stop command for restricted auto-sampling to ARM7.
428 Arguments: None.
429 Returns: BOOL: Returns TRUE when the command was successfully sent via PXI and FALSE on failure.
430
431 *---------------------------------------------------------------------------*/
432 static BOOL
MicexStopLimitedSampling(void)433 MicexStopLimitedSampling(void)
434 {
435 /* PXI Packet [0] */
436 if (0 > PXI_SendWordByFifo(PXI_FIFO_TAG_MIC,
437 SPI_PXI_START_BIT | SPI_PXI_END_BIT | (0 << SPI_PXI_INDEX_SHIFT) | (SPI_PXI_COMMAND_MIC_LTDAUTO_OFF << 8), 0))
438 {
439 return FALSE;
440 }
441 return TRUE;
442 }
443
444 /*---------------------------------------------------------------------------*
445 Name: MicexAdjustLimitedSampling
446 Description: Issues change command for restricted auto-sampling to ARM7.
447 Arguments: rate: Specifies the sampling interval in ARM7 CPU clock units.
448 Returns: BOOL: Returns TRUE when the command was successfully sent via PXI and FALSE on failure.
449
450 *---------------------------------------------------------------------------*/
451 static BOOL
MicexAdjustLimitedSampling(u32 rate)452 MicexAdjustLimitedSampling(u32 rate)
453 {
454 /* PXI Packet [0] */
455 if (0 > PXI_SendWordByFifo(PXI_FIFO_TAG_MIC,
456 SPI_PXI_START_BIT | (0 << SPI_PXI_INDEX_SHIFT) | (SPI_PXI_COMMAND_MIC_LTDAUTO_ADJUST << 8), 0))
457 {
458 return FALSE;
459 }
460
461 /* PXI Packet [1] */
462 if (0 > PXI_SendWordByFifo(PXI_FIFO_TAG_MIC,
463 (1 << SPI_PXI_INDEX_SHIFT) | (rate >> 16), 0))
464 {
465 return FALSE;
466 }
467
468 /* PXI Packet [2] */
469 if (0 > PXI_SendWordByFifo(PXI_FIFO_TAG_MIC,
470 SPI_PXI_END_BIT | (2 << SPI_PXI_INDEX_SHIFT) | (rate & 0x0000ffff), 0))
471 {
472 return FALSE;
473 }
474 return TRUE;
475 }
476