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