/*---------------------------------------------------------------------------* Project: TwlSDK - libraries - mic File: micex.c Copyright 2007-2008 Nintendo. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Date:: 2008-09-17#$ $Rev: 8556 $ $Author: okubata_ryoma $ *---------------------------------------------------------------------------*/ #include #include #include "micex.h" #include /*---------------------------------------------------------------------------* Internal Function Definitions *---------------------------------------------------------------------------*/ static void MicexSyncCallback(MICResult result, void* arg); static BOOL MicexStartLimitedSampling(void* buf, u32 size, u32 rate, u8 flags); static BOOL MicexStopLimitedSampling(void); static BOOL MicexAdjustLimitedSampling(u32 rate); /*---------------------------------------------------------------------------* Name: MICEXi_StartLimitedSampling Description: Starts sampling rate limited microphone auto-sampling. This is a synchronous function, so calling from within an interrupt handler is prohibited. Arguments: param: - Pointer to a structure that specifies auto sampling settings Returns: MICResult: Returns synchronous processing results. *---------------------------------------------------------------------------*/ MICResult MICEXi_StartLimitedSampling(const MICAutoParam* param) { MICResult result; OSMessageQueue msgQ; OSMessage msg[1]; /* Calling this from within an interrupt handler is prohibited */ if (OS_GetCurrentThread() == NULL) { #ifdef SDK_DEBUG OS_TWarning("%s: Could not process in exception handler.\n", __FUNCTION__); #endif return MIC_RESULT_ILLEGAL_STATUS; } /* Initialize the message queue for getting responses */ OS_InitMessageQueue(&msgQ, msg, 1); /* Execute the asynchronous function and idle the callback */ result = MICEXi_StartLimitedSamplingAsync(param, MicexSyncCallback, (void*)(&msgQ)); if (result == MIC_RESULT_SUCCESS) { (void)OS_ReceiveMessage(&msgQ, (OSMessage*)(&result), OS_MESSAGE_BLOCK); } return result; } /*---------------------------------------------------------------------------* Name: MICEXi_StartLimitedSamplingAsync Description: Starts sampling rate limited microphone auto-sampling. This is an asynchronous function, so the actual processing results are passed when the callback is called. Arguments: param: Pointer to a structure that specifies auto-sampling settings. callback: Specifies the callback function to call when asynchronous processing is completed. arg: Specifies parameter passed to the callback function. Returns: MICResult: Returns the results of starting the asynchronous process. *---------------------------------------------------------------------------*/ MICResult MICEXi_StartLimitedSamplingAsync(const MICAutoParam* param, MICCallback callback, void* arg) { OSIntrMode e; MICWork* w = MICi_GetSysWork(); u8 flags; SDK_NULL_ASSERT(callback); SDK_NULL_ASSERT(param->buffer); /* Confirms parameters */ { /* Buffer size */ if (param->size <= 0) { #ifdef SDK_DEBUG OS_TWarning("%s: Illegal desination buffer size. (%d)\n", __FUNCTION__, param->size); #endif return MIC_RESULT_ILLEGAL_PARAMETER; } /* 32-byte buffer alignment */ if (((u32)(param->buffer) % HW_CACHE_LINE_SIZE != 0) || ((param->size % HW_CACHE_LINE_SIZE) != 0)) { #ifdef SDK_DEBUG OS_TWarning("%s: Destination buffer (%p - %p) is not aligned on %d bytes boundary.\n", __FUNCTION__, param->buffer, (void*)((u32)param->buffer + param->size), HW_CACHE_LINE_SIZE); #endif return MIC_RESULT_ILLEGAL_PARAMETER; } /* AD conversion bit width */ switch (param->type) { case MIC_SAMPLING_TYPE_8BIT: flags = SPI_MIC_SAMPLING_TYPE_8BIT; break; case MIC_SAMPLING_TYPE_12BIT: flags = SPI_MIC_SAMPLING_TYPE_12BIT; break; case MIC_SAMPLING_TYPE_SIGNED_8BIT: flags = SPI_MIC_SAMPLING_TYPE_S8BIT; break; case MIC_SAMPLING_TYPE_SIGNED_12BIT: flags = SPI_MIC_SAMPLING_TYPE_S12BIT; break; case MIC_SAMPLING_TYPE_12BIT_FILTER_OFF: flags = (SPI_MIC_SAMPLING_TYPE_12BIT | SPI_MIC_SAMPLING_TYPE_FILTER_OFF); break; case MIC_SAMPLING_TYPE_SIGNED_12BIT_FILTER_OFF: flags = (SPI_MIC_SAMPLING_TYPE_S12BIT | SPI_MIC_SAMPLING_TYPE_FILTER_OFF); break; default: #ifdef SDK_DEBUG OS_TWarning("%s: Illegal sampling type. (%d)\n", __FUNCTION__, param->type); #endif return MIC_RESULT_ILLEGAL_PARAMETER; } /* sampling period */ switch (param->rate) { case MIC_SAMPLING_RATE_32730: case MIC_SAMPLING_RATE_16360: case MIC_SAMPLING_RATE_10910: case MIC_SAMPLING_RATE_8180: case MIC_SAMPLING_RATE_47610: case MIC_SAMPLING_RATE_23810: case MIC_SAMPLING_RATE_15870: case MIC_SAMPLING_RATE_11900: break; default: #ifdef SDK_TWL OS_TWarning("%s: Illegal sampling rate. (%d)\n", __FUNCTION__, param->rate); #endif return MIC_RESULT_ILLEGAL_PARAMETER; } /* Enable/disable loop */ if (param->loop_enable) { flags = (u8)((flags & ~SPI_MIC_SAMPLING_TYPE_LOOP_MASK) | SPI_MIC_SAMPLING_TYPE_LOOP_ON); } else { flags = (u8)((flags & ~SPI_MIC_SAMPLING_TYPE_LOOP_MASK) | SPI_MIC_SAMPLING_TYPE_LOOP_OFF); } /* Correction flag for expansions */ flags = (u8)((flags & ~SPI_MIC_SAMPLING_TYPE_CORRECT_MASK) | SPI_MIC_SAMPLING_TYPE_CORRECT_OFF); } /* Check exclusion lock */ e = OS_DisableInterrupts(); if (w->lock != MIC_LOCK_OFF) { (void)OS_RestoreInterrupts(e); return MIC_RESULT_BUSY; } w->lock = MIC_LOCK_ON; (void)OS_RestoreInterrupts(e); /* Send command for restricted auto-sampling start */ w->callback = callback; w->callbackArg = arg; w->full = param->full_callback; w->fullArg = param->full_arg; if (MicexStartLimitedSampling(param->buffer, param->size, param->rate, flags)) { return MIC_RESULT_SUCCESS; } w->lock = MIC_LOCK_OFF; return MIC_RESULT_SEND_ERROR; } /*---------------------------------------------------------------------------* Name: MICEXi_StopLimitedSampling Description: Stops sampling rate limited microphone auto-sampling. This is a synchronous function, so calling from within an interrupt handler is prohibited. Arguments: None. Returns: MICResult: Returns synchronous processing results. *---------------------------------------------------------------------------*/ MICResult MICEXi_StopLimitedSampling(void) { MICResult result; OSMessageQueue msgQ; OSMessage msg[1]; /* Calling this from within an interrupt handler is prohibited */ if (OS_GetCurrentThread() == NULL) { #ifdef SDK_DEBUG OS_TWarning("%s: Could not process in exception handler.\n", __FUNCTION__); #endif return MIC_RESULT_ILLEGAL_STATUS; } /* Initialize the message queue for getting responses */ OS_InitMessageQueue(&msgQ, msg, 1); /* Execute the asynchronous function and idle the callback */ result = MICEXi_StopLimitedSamplingAsync(MicexSyncCallback, (void*)(&msgQ)); if (result == MIC_RESULT_SUCCESS) { (void)OS_ReceiveMessage(&msgQ, (OSMessage*)(&result), OS_MESSAGE_BLOCK); } return result; } /*---------------------------------------------------------------------------* Name: MICEXi_StopLimitedSamplingAsync Description: Stops sampling rate limited microphone auto-sampling. This is an asynchronous function, so the actual processing results are passed when the callback is called. Arguments: callback: Specifies the callback function to call when asynchronous processing is completed. arg: Specifies parameter passed to the callback function. Returns: MICResult: Returns the results of starting the asynchronous process. *---------------------------------------------------------------------------*/ MICResult MICEXi_StopLimitedSamplingAsync(MICCallback callback, void* arg) { OSIntrMode e; MICWork* w = MICi_GetSysWork(); SDK_NULL_ASSERT(callback); /* Check exclusion lock */ e = OS_DisableInterrupts(); if (w->lock != MIC_LOCK_OFF) { (void)OS_RestoreInterrupts(e); return MIC_RESULT_BUSY; } w->lock = MIC_LOCK_ON; (void)OS_RestoreInterrupts(e); /* Send command to stop restricted auto-sampling */ w->callback = callback; w->callbackArg = arg; if (MicexStopLimitedSampling()) { return MIC_RESULT_SUCCESS; } w->lock = MIC_LOCK_OFF; return MIC_RESULT_SEND_ERROR; } /*---------------------------------------------------------------------------* Name: MICEXi_AdjustLimitedSampling Description: Adjusts the sampling intervals used in sampling rate limited microphone auto-sampling. This is a synchronous function, so calling from within an interrupt handler is prohibited. Arguments: rate: Specifies the sampling interval in ARM7 CPU clock units. Returns: MICResult: Returns synchronous processing results. *---------------------------------------------------------------------------*/ MICResult MICEXi_AdjustLimitedSampling(u32 rate) { MICResult result; OSMessageQueue msgQ; OSMessage msg[1]; /* Calling this from within an interrupt handler is prohibited */ if (OS_GetCurrentThread() == NULL) { #ifdef SDK_DEBUG OS_TWarning("%s: Could not process in exception handler.\n", __FUNCTION__); #endif return MIC_RESULT_ILLEGAL_STATUS; } /* Initialize the message queue for getting responses */ OS_InitMessageQueue(&msgQ, msg, 1); /* Execute the asynchronous function and idle the callback */ result = MICEXi_AdjustLimitedSamplingAsync(rate, MicexSyncCallback, (void*)(&msgQ)); if (result == MIC_RESULT_SUCCESS) { (void)OS_ReceiveMessage(&msgQ, (OSMessage*)(&result), OS_MESSAGE_BLOCK); } return result; } /*---------------------------------------------------------------------------* Name: MICEXi_AdjustLimitedSamplingAsync Description: Adjusts the sampling intervals used in sampling rate limited microphone auto-sampling. This is an asynchronous function, so the actual processing results are passed when the callback is called. Arguments: rate: Specifies the sampling interval in ARM7 CPU clock units. callback: Specifies the callback function to call when asynchronous processing is completed. arg: Specifies parameter passed to the callback function. Returns: MICResult: Returns the results of starting the asynchronous process. *---------------------------------------------------------------------------*/ MICResult MICEXi_AdjustLimitedSamplingAsync(u32 rate, MICCallback callback, void* arg) { OSIntrMode e; MICWork* w = MICi_GetSysWork(); SDK_NULL_ASSERT(callback); /* Confirms parameters */ switch (rate) { case MIC_SAMPLING_RATE_32730: case MIC_SAMPLING_RATE_16360: case MIC_SAMPLING_RATE_10910: case MIC_SAMPLING_RATE_8180: case MIC_SAMPLING_RATE_47610: case MIC_SAMPLING_RATE_23810: case MIC_SAMPLING_RATE_15870: case MIC_SAMPLING_RATE_11900: break; default: #ifdef SDK_DEBUG OS_TWarning("%s: Illegal sampling rate. (%d)\n", __FUNCTION__, rate); #endif return MIC_RESULT_ILLEGAL_PARAMETER; } /* Check exclusion lock */ e = OS_DisableInterrupts(); if (w->lock != MIC_LOCK_OFF) { (void)OS_RestoreInterrupts(e); return MIC_RESULT_BUSY; } w->lock = MIC_LOCK_ON; (void)OS_RestoreInterrupts(e); /* Send command to adjust restricted auto-sampling */ w->callback = callback; w->callbackArg = arg; if (MicexAdjustLimitedSampling(rate)) { return MIC_RESULT_SUCCESS; } w->lock = MIC_LOCK_OFF; return MIC_RESULT_SEND_ERROR; } /*---------------------------------------------------------------------------* Name: MicexSyncCallback Description: Shared callback function for synchronous functions. Makes inactive threads recover to an operable state by sending them the asynchronous processing results. Arguments: result: Passes the microphone operation asynchronous processing results. arg: Passes a pointer to the message queue which the thread which calls synchronous functions is waiting to receive. Returns: None. *---------------------------------------------------------------------------*/ static void MicexSyncCallback(MICResult result, void* arg) { SDK_NULL_ASSERT(arg); (void)OS_SendMessage((OSMessageQueue*)arg, (OSMessage)result, OS_MESSAGE_NOBLOCK); } /*---------------------------------------------------------------------------* Name: MicexStartLimitedSampling Description: Issues start command for restricted auto-sampling to ARM7. Arguments: buf: Address of buffer storing sampled data. size: Specifies the buffer size in bytes. rate: Specifies the sampling interval in ARM7 CPU clock units. flags - Specifies the AD conversion bit width, enabling/disabling of loops, and enabling/disabling of correction Returns: BOOL: Returns TRUE when the command was successfully sent via PXI and FALSE on failure. *---------------------------------------------------------------------------*/ static BOOL MicexStartLimitedSampling(void* buf, u32 size, u32 rate, u8 flags) { /* PXI Packet [0] */ if (0 > PXI_SendWordByFifo(PXI_FIFO_TAG_MIC, SPI_PXI_START_BIT | (0 << SPI_PXI_INDEX_SHIFT) | (SPI_PXI_COMMAND_MIC_LTDAUTO_ON << 8) | (u32)flags, 0)) { return FALSE; } /* PXI Packet [1] */ if (0 > PXI_SendWordByFifo(PXI_FIFO_TAG_MIC, (1 << SPI_PXI_INDEX_SHIFT) | ((u32)buf >> 16), 0)) { return FALSE; } /* PXI Packet [2] */ if (0 > PXI_SendWordByFifo(PXI_FIFO_TAG_MIC, (2 << SPI_PXI_INDEX_SHIFT) | ((u32)buf & 0x0000ffff), 0)) { return FALSE; } /* PXI Packet [3] */ if (0 > PXI_SendWordByFifo(PXI_FIFO_TAG_MIC, (3 << SPI_PXI_INDEX_SHIFT) | (size >> 16), 0)) { return FALSE; } /* PXI Packet [4] */ if (0 > PXI_SendWordByFifo(PXI_FIFO_TAG_MIC, (4 << SPI_PXI_INDEX_SHIFT) | (size & 0x0000ffff), 0)) { return FALSE; } /* PXI Packet [5] */ if (0 > PXI_SendWordByFifo(PXI_FIFO_TAG_MIC, (5 << SPI_PXI_INDEX_SHIFT) | (rate >> 16), 0)) { return FALSE; } /* PXI Packet [6] */ if (0 > PXI_SendWordByFifo(PXI_FIFO_TAG_MIC, SPI_PXI_END_BIT | (6 << SPI_PXI_INDEX_SHIFT) | (rate & 0x0000ffff), 0)) { return FALSE; } return TRUE; } /*---------------------------------------------------------------------------* Name: MicexStopLimitedSampling Description: Issues stop command for restricted auto-sampling to ARM7. Arguments: None. Returns: BOOL: Returns TRUE when the command was successfully sent via PXI and FALSE on failure. *---------------------------------------------------------------------------*/ static BOOL MicexStopLimitedSampling(void) { /* PXI Packet [0] */ if (0 > PXI_SendWordByFifo(PXI_FIFO_TAG_MIC, SPI_PXI_START_BIT | SPI_PXI_END_BIT | (0 << SPI_PXI_INDEX_SHIFT) | (SPI_PXI_COMMAND_MIC_LTDAUTO_OFF << 8), 0)) { return FALSE; } return TRUE; } /*---------------------------------------------------------------------------* Name: MicexAdjustLimitedSampling Description: Issues change command for restricted auto-sampling to ARM7. Arguments: rate: Specifies the sampling interval in ARM7 CPU clock units. Returns: BOOL: Returns TRUE when the command was successfully sent via PXI and FALSE on failure. *---------------------------------------------------------------------------*/ static BOOL MicexAdjustLimitedSampling(u32 rate) { /* PXI Packet [0] */ if (0 > PXI_SendWordByFifo(PXI_FIFO_TAG_MIC, SPI_PXI_START_BIT | (0 << SPI_PXI_INDEX_SHIFT) | (SPI_PXI_COMMAND_MIC_LTDAUTO_ADJUST << 8), 0)) { return FALSE; } /* PXI Packet [1] */ if (0 > PXI_SendWordByFifo(PXI_FIFO_TAG_MIC, (1 << SPI_PXI_INDEX_SHIFT) | (rate >> 16), 0)) { return FALSE; } /* PXI Packet [2] */ if (0 > PXI_SendWordByFifo(PXI_FIFO_TAG_MIC, SPI_PXI_END_BIT | (2 << SPI_PXI_INDEX_SHIFT) | (rate & 0x0000ffff), 0)) { return FALSE; } return TRUE; }