肝心の新規マイクライブラリを追加

git-svn-id: file:///Users/lillianskinner/Downloads/platinum/twl/twl_wrapsdk/trunk@289 4ee2a332-4b2b-5046-8439-1ba90f034370
This commit is contained in:
kamikawa 2007-09-28 11:03:00 +00:00
parent e48811bca0
commit e7bc2d65d4
5 changed files with 1894 additions and 0 deletions

View File

@ -0,0 +1,56 @@
#! make -f
#----------------------------------------------------------------------------
# Project: TwlSDK - libraries - camera/ARM7
# File: Makefile
#
# Copyright 2007 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.
#
# $Log: $
# $NoKeywords: $
#----------------------------------------------------------------------------
SUBDIRS =
#----------------------------------------------------------------------------
# build ARM & THUMB libraries
TWL_CODEGEN_ALL ?= True
# Codegen for sub processer
TWL_PROC = ARM7
SRCDIR = ./src
SRCS = twl_mic_server.c twl_mic_api.c
TARGET_LIB = libtwlmic_sp$(TWL_LIBSUFFIX).a
#----------------------------------------------------------------------------
# DEBUG版ビルドの場合、RELEASE版でビルドして
# DEBUG版のライブラリを装います。
ifdef NITRO_DEBUG
NITRO_BUILD_TYPE = RELEASE
endif
include $(TWLSDK_ROOT)/build/buildtools/commondefs
INSTALL_TARGETS = $(TARGETS)
INSTALL_DIR = $(TWL_INSTALL_LIBDIR)
#----------------------------------------------------------------------------
do-build: $(TARGETS)
include $(TWLSDK_ROOT)/build/buildtools/modulerules
#===== End of Makefile =====

View File

@ -0,0 +1,481 @@
/*---------------------------------------------------------------------------*
Project: TwlSDK - library - twlmic
File: twl_mic_api.c
Copyright 2007 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.
$Log: $
$NoKeywords: $
*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*
2
 Auto Gain Control (調
 IIR Filter ( : High/Low Pass Filter
  CODEC
 
----------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*
TWLにおけるマイクデータの拾い方
FIFO Half DMA起動方式
FIFO Half DMA起動方式
  
     
      
     
FIFOに半分データが溜まる度にDMA起動要求がかかり
DMAを再設定
FIFOとDMAのタイミングがきっちりと合う
DMAがどこまで進んだか分からないためMIC_GetLastSamplingAddress
 使
 
  
     
      
     
FIFOにデータが溜まるタイミングを逆算し
使DMAを実行する
DMAとFIFOのタイミングがずれていく可能性
DMAの再設定が必要ない
DMAによりFIFOとのタイミングがずれていく可能性がある
DMAがどこまで進んだか分からないためMIC_GetLastSamplingAddress
 使
 
FIFOにデータが半分溜まる度にMIC割り込みを発生させ
FIFOからCPUでワード取得する
 MIC_GetLastSamplingAddressで正確なアドレスを返すことができる
DS時代の1/16
MIC_GetLastSamplingAddressに有用性がないならこの方式はありえない
----------------------------------------------------------------------------*/
#include <twl.h>
#include <twl/mic.h>
#include <twl/cdc.h>
#include <twl/snd/ARM7/i2s.h>
/*---------------------------------------------------------------------------*
*---------------------------------------------------------------------------*/
#define TWL_MIC_TICK_INIT_VALUE 0
/*---------------------------------------------------------------------------*
*---------------------------------------------------------------------------*/
static TWLMICParam sMicParam; // パラメータ保存用
static OSTick sMicTickStart; // サンプリング開始時Tick
static OSTick sMicTickStop; // サンプリング停止時Tick
/*---------------------------------------------------------------------------*
*---------------------------------------------------------------------------*/
static void TWL_MICi_ExDmaRecvAsync( u32 dmaNo, void *dest, u32 size );
static void TWL_MICi_ExDmaInterruptHandler( void );
static void TWL_MICi_FifoInterruptHandler( void );
/*---------------------------------------------------------------------------*
Name: TWL_MIC_DoSampling
Description: 16bit
Arguments: buffer :
Returns: None
*---------------------------------------------------------------------------*/
void
TWL_MIC_DoSampling( u16* buffer )
{
u32 word;
const u32 WAIT_MAX = 100;
u32 i;
// 引数チェック
SDK_NULL_ASSERT( buffer );
// サウンド & I2S 回路ON
SND_Enable();
// モノラルサンプリングスタート
reg_SND_MICCNT = REG_SND_MICCNT_FIFO_CLR_MASK;
reg_SND_MICCNT = (u16)(REG_SND_MICCNT_E_MASK | REG_SND_MICCNT_NR_MASK |
MIC_INTR_DISABLE | MIC_SMP_ALL );
// データが2個以上入るのを待つ
for (i=0;i<WAIT_MAX;i++)
{
if (!(reg_SND_MICCNT & REG_SND_MICCNT_FIFO_EMP_MASK))
{
break;
}
}
// FIFOはワードアクセス
word = reg_SND_MIC_FIFO;
// サンプリング停止
reg_SND_MICCNT &= ~REG_SND_MICCNT_E_MASK;
// 16bit値を格納
*buffer = (u16)(word & 0x0000ffff);
}
/*---------------------------------------------------------------------------*
Name: TWL_MIC_StartAutoSampling
Description:
Arguments: param :
Returns: None
*---------------------------------------------------------------------------*/
void
TWL_MIC_StartAutoSampling( TWLMICParam param )
{
OSIntrMode enabled;
u32 ch;
// 引数チェック
SDK_ASSERT( param.dmaNo >= MI_EXDMA_CH_MIN && param.dmaNo <= MI_EXDMA_CH_MAX );
SDK_NULL_ASSERT( param.buffer );
// DMA停止
TWL_MIC_StopAutoSampling();
// 割り込み禁止
enabled = OS_DisableInterrupts();
// サウンド & I2S 回路ON
SND_Enable();
// DMA設定
TWL_MICi_ExDmaRecvAsync( param.dmaNo, param.buffer, param.size );
// DMA割り込みの設定
ch = (u32)param.dmaNo - MI_EXDMA_CH_MIN;
OS_SetIrqFunction( OS_IE_DMA4 << ch, TWL_MICi_ExDmaInterruptHandler );
reg_OS_IF = (OS_IE_DMA4 << ch);
reg_OS_IE |= (OS_IE_DMA4 << ch);
// マイクFIFO割り込みの設定
OS_SetIrqFunction( OS_IE_MIC, TWL_MICi_FifoInterruptHandler );
reg_OS_IF2 = (OS_IE_MIC >> 32);
reg_OS_IE2 |= (OS_IE_MIC >> 32);
// スタートTick設定
sMicTickStart = OS_GetTick();
// ストップTickクリア
sMicTickStop = TWL_MIC_TICK_INIT_VALUE;
// モノラルサンプリングスタート
reg_SND_MICCNT = REG_SND_MICCNT_FIFO_CLR_MASK; //
reg_SND_MICCNT = (u16)( REG_SND_MICCNT_E_MASK | //
REG_SND_MICCNT_NR_MASK | //
MIC_INTR_OVERFLOW | // FIFO破綻で割り込み発生
param.frequency );
// パラメータ保存
sMicParam = param;
// 割り込み復帰
(void)OS_RestoreInterrupts(enabled);
}
/*---------------------------------------------------------------------------*
Name: TWL_MIC_StopAutoSampling
Description:
Arguments: None
Returns: None
*---------------------------------------------------------------------------*/
void
TWL_MIC_StopAutoSampling( void )
{
OSIntrMode enabled = OS_DisableInterrupts();
u32 dmaNo = sMicParam.dmaNo;
// ストップTick設定
sMicTickStop = OS_GetTick();
// マイク停止
reg_SND_MICCNT &= ~REG_SND_MICCNT_E_MASK;
// マイクFIFO割り込み禁止
reg_OS_IE2 &= ~(OS_IE_MIC >> 32);
reg_OS_IF2 = (OS_IE_MIC >> 32);
if ( MI_EXDMA_CH_MIN <= dmaNo && dmaNo <= MI_EXDMA_CH_MAX )
{
u32 ch = dmaNo - MI_EXDMA_CH_MIN;
// DMA停止
MIi_StopExDma( dmaNo );
// DMA割り込み禁止
reg_OS_IE &= ~(OS_IE_DMA4 << ch);
reg_OS_IF = (OS_IE_DMA4 << ch);
}
(void)OS_RestoreInterrupts(enabled);
}
/*---------------------------------------------------------------------------*
Name: TWL_MIC_GetLastSamplingAddress
Description:
FIFOからのデータ取得にはDMAを用いますが
DMAが現在どの位置を書き換え中かは知る手段がありません
Arguments: None
Returns:
*---------------------------------------------------------------------------*/
void*
TWL_MIC_GetLastSamplingAddress( void )
{
void* adress; // 最新データアドレス
OSTick past_tick; // 経過チック
u32 sampling_count; // 予想サンプリングカウント
f32 one_sampling_tick;
// サンプリング停止状態
if (sMicTickStop != TWL_MIC_TICK_INIT_VALUE)
{
past_tick = sMicTickStop - sMicTickStart;
}
// サンプリング進行状態
else
{
past_tick = OS_GetTick() - sMicTickStart;
}
/*
47.61kHzの場合
33.514MHz
Tickは64分周のタイマカウンタであるため
1
33.514MHz / 47.61kHz / 64 = 10.9988
FPGAボードではさらに半分にする必要がある
*/
switch ( I2S_GetSamplingRate() )
{
case I2S_SAMPLING_RATE_32730:
switch ( sMicParam.frequency )
{
case MIC_SMP_ALL: // 32.73 kHz
one_sampling_tick = (f32)OS_SYSTEM_CLOCK * 1 / 32730 / 64;
break;
case MIC_SMP_1_2: // 16.36 kHz
one_sampling_tick = (f32)OS_SYSTEM_CLOCK * 2 / 32730 / 64;
break;
case MIC_SMP_1_3: // 10.91 kHz
one_sampling_tick = (f32)OS_SYSTEM_CLOCK * 3 / 32730 / 64;
break;
case MIC_SMP_1_4: // 8.18 kHz
one_sampling_tick = (f32)OS_SYSTEM_CLOCK * 4 / 32730 / 64;
break;
}
break;
case I2S_SAMPLING_RATE_47610:
switch ( sMicParam.frequency )
{
case MIC_SMP_ALL: // 47.61 kHz
one_sampling_tick = (f32)OS_SYSTEM_CLOCK * 1 / 47610 / 64;
break;
case MIC_SMP_1_2: // 23.81 kHz
one_sampling_tick = (f32)OS_SYSTEM_CLOCK * 2 / 47610 / 64;
break;
case MIC_SMP_1_3: // 15.87 kHz
one_sampling_tick = (f32)OS_SYSTEM_CLOCK * 3 / 47610 / 64;
break;
case MIC_SMP_1_4: // 11.90 kHz
one_sampling_tick = (f32)OS_SYSTEM_CLOCK * 4 / 47610 / 64;
break;
}
break;
}
// 現在のサンプリング数を計算
sampling_count = (u32)(past_tick / one_sampling_tick);
// サンプリング数よりアドレスを計算
adress = (void*)((u16 *)sMicParam.buffer + sampling_count);
return adress;
}
/*---------------------------------------------------------------------------*
Name: TWL_MIC_SetAmpGain
Description: TWLモードのマイクゲイン(PGAB)
        PGABはAutoGainControlが無効になっているときのみ有効です
Arguments: gain : 0119 = 059.5dB
Returns: None
*---------------------------------------------------------------------------*/
void
TWL_MIC_SetAmpGain( u8 gain )
{
SDK_ASSERT( gain >= 0 && gain <= 119 );
CDC_SetPGAB( gain );
}
/*---------------------------------------------------------------------------*
Name: TWL_MIC_GetAmpGain
Description: TWLモードのマイクゲイン(PGAB)
Arguments: None
Returns:
*---------------------------------------------------------------------------*/
u8
TWL_MIC_GetAmpGain( void )
{
return CDC_GetPGAB();
}
/*---------------------------------------------------------------------------*
Name: TWL_MICi_ExDmaRecvAsync
Description: receive data with DMA
async version
Arguments: dmaNo : DMA channel No.
buffer : destination address
size : size (byte)
Returns: None
*---------------------------------------------------------------------------*/
static void
TWL_MICi_ExDmaRecvAsync( u32 dmaNo, void *buffer, u32 size )
{
MIi_ExDmaRecvAsyncCore(
dmaNo, // DMA番号
(void*)REG_MIC_FIFO_ADDR, // 転送元アドレス
buffer, // 転送先アドレス
(u32)size, // 総転送バイト数
(u32)32, // 転送バイト数
MI_EXDMA_BLOCK_32B, // ブロック転送サイズ
0, // インターバル
MI_EXDMA_PRESCALER_1, // プリスケール1
MI_EXDMA_CONTINUOUS_OFF, // 非コンティニュアス
MI_EXDMA_SRC_RLD_OFF, // Source Reload Don't Care
MI_EXDMA_DEST_RLD_OFF, // Destination Reload Off
MI_EXDMA_TIMING_MIC ); // マイクFIFOハーフ起動
}
/*---------------------------------------------------------------------------*
Name: TWL_MICi_ExDmaInterruptHandler
Description: interrupt handler
Arguments: None
Returns: None
*---------------------------------------------------------------------------*/
static void
TWL_MICi_ExDmaInterruptHandler( void )
{
// ループする?
if ( sMicParam.loop )
{
// DMAを再設定
TWL_MICi_ExDmaRecvAsync( sMicParam.dmaNo, sMicParam.buffer, sMicParam.size );
// スタートTick再設定
sMicTickStart = OS_GetTick();
}
// DMA完了コールバックの呼び出し
if ( sMicParam.callback )
{
sMicParam.callback( sMicParam.loop );
}
}
/*---------------------------------------------------------------------------*
Name: TWL_MICi_FifoInterruptHandler
Description: FIFO破綻時に呼び出される割り込みハンドラ
FIFOクリア後にサンプリングを再スタート
Arguments: None
Returns: None
*---------------------------------------------------------------------------*/
static void
TWL_MICi_FifoInterruptHandler( void )
{
// マイク停止
reg_SND_MICCNT &= ~REG_SND_MICCNT_E_MASK;
// マイクFIFOクリア
reg_SND_MICCNT = REG_SND_MICCNT_FIFO_CLR_MASK;
// モノラルサンプリング再スタート
reg_SND_MICCNT = (u16)( REG_SND_MICCNT_E_MASK |
REG_SND_MICCNT_NR_MASK |
MIC_INTR_OVERFLOW | // FIFO破綻で割り込み発生
sMicParam.frequency );
}

View File

@ -0,0 +1,495 @@
/*---------------------------------------------------------------------------*
Project: TwlSDK - library - twlmic
File: twl_mic_server.c
Copyright 2007 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.
$Log: $
$NoKeywords: $
*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*
TWL Mic用に勝手にARM7側スレッドを作りました
SPIスレッドなどに吸収してください
----------------------------------------------------------------------------*/
#include <twl.h>
#include <twl/mic.h>
/*---------------------------------------------------------------------------*
*---------------------------------------------------------------------------*/
// アライメント調整してコピーする
#define MIC_UNPACK_U16(d, s) \
(*(d) = (u16)((((u8*)s)[0] << 0) | (((u8*)s)[1] << 8)))
#define MIC_UNPACK_U32(d, s) \
(*(d) = (u32)((((u8*)s)[0] << 0) | (((u8*)s)[1] << 8) | (((u8*)s)[2] << 16) | (((u8*)s)[3] << 24)))
/*---------------------------------------------------------------------------*
*---------------------------------------------------------------------------*/
static BOOL micInitialized; // 初期化確認フラグ
static TWLMICServerWork micWork; // ワーク変数をまとめた構造体
/*---------------------------------------------------------------------------*
*---------------------------------------------------------------------------*/
static void TWL_MICi_PxiCallback(PXIFifoTag tag, u32 data, BOOL err);
static void TWL_MICi_ReturnResult(TWLMICPxiCommand command, TWLMICPxiResult result);
static void TWL_MICi_ReturnResultEx(TWLMICPxiCommand command, TWLMICPxiResult result, u8 size, u8* data);
static void TWL_MICi_Thread(void *arg);
static void TWL_MICi_FullCallback( u8 loop );
static BOOL TWL_MICi_SetEntry(TWLMICPxiCommand command, u16 args, ...);
/*---------------------------------------------------------------------------*
Name: TWL_MIC_InitServer
Description: ARM7側とやりとりを行うための準備を行います
Arguments: priority
Returns: None.
*---------------------------------------------------------------------------*/
void
TWL_MIC_InitServer(u32 priority)
{
// 初期化済みを確認
if (micInitialized)
{
return;
}
micInitialized = 1;
// 内部状態管理変数をクリア
micWork.status = TWL_MIC_STATUS_READY;
// PXI関連を初期化
PXI_Init();
PXI_SetFifoRecvCallback(PXI_FIFO_TAG_TWL_MIC, TWL_MICi_PxiCallback);
// 実処理を行うスレッドを作成&起動
OS_InitMessageQueue(&micWork.msgQ, micWork.msgArray, TWL_MIC_MESSAGE_ARRAY_MAX);
OS_CreateThread(&micWork.thread,
TWL_MICi_Thread,
0,
(void *)(micWork.stack + (TWL_MIC_THREAD_STACK_SIZE / sizeof(u64))),
TWL_MIC_THREAD_STACK_SIZE, priority);
OS_WakeupThreadDirect(&micWork.thread);
}
/*---------------------------------------------------------------------------*
Name: TWL_MICi_SetEntry
Description: TWL MIC
Arguments: command - IDを指定
args -
... - u32型で指定
Returns: BOOL - TRUEをFALSEを返す
*---------------------------------------------------------------------------*/
static BOOL
TWL_MICi_SetEntry(TWLMICPxiCommand command, u16 args, ...)
{
OSIntrMode e;
void *w;
va_list vlist;
s32 i;
// 引数の数をチェック
if (args > TWL_MIC_MESSAGE_ARGS_MAX)
{
return FALSE;
}
e = OS_DisableInterrupts();
micWork.entry[micWork.entryIndex].command = command;
// 指定数個の引数を追加
va_start(vlist, args);
for (i = 0; i < args; i++)
{
micWork.entry[micWork.entryIndex].arg[i] = va_arg(vlist, u32);
}
va_end(vlist);
w = &(micWork.entry[micWork.entryIndex]);
micWork.entryIndex = (u32)((micWork.entryIndex + 1) % TWL_MIC_MESSAGE_ARRAY_MAX);
(void)OS_RestoreInterrupts(e);
return OS_SendMessage(&(micWork.msgQ), w, OS_MESSAGE_NOBLOCK);
}
/*---------------------------------------------------------------------------*
Name: TWL_MICi_PxiCallback
Description: PXI経由で受信したデータを解析する
Arguments: tag - PXI種別を示すタグ
data - 26bitが有効
err - PXI通信におけるエラーフラグ
ARM9側にて同種別のPXIが初期化されていないことを示す
Returns: None.
*---------------------------------------------------------------------------*/
static void TWL_MICi_PxiCallback(PXIFifoTag tag, u32 data, BOOL err)
{
#pragma unused( tag )
// PXI通信エラーをチェック
if (err)
{
return;
}
// 先頭データ
if (data & TWL_MIC_PXI_START_BIT)
{
micWork.total = (u8)((data & TWL_MIC_PXI_DATA_NUMS_MASK) >> TWL_MIC_PXI_DATA_NUMS_SHIFT);
micWork.current = 0;
micWork.command = (TWLMICPxiCommand)((data & TWL_MIC_PXI_COMMAND_MASK) >> TWL_MIC_PXI_COMMAND_SHIFT);
micWork.data[micWork.current++] = (u8)((data & TWL_MIC_PXI_1ST_DATA_MASK) >> TWL_MIC_PXI_1ST_DATA_SHIFT);
}
// 後続データ
else
{
micWork.data[micWork.current++] = (u8)((data & 0x00FF0000) >> 16);
micWork.data[micWork.current++] = (u8)((data & 0x0000FF00) >> 8);
micWork.data[micWork.current++] = (u8)((data & 0x000000FF) >> 0);
}
// パケット完成
if (micWork.current >= micWork.total) // 最大で2バイト余分に取得する
{
// 受信したコマンドを解析
switch (micWork.command)
{
// 単発サンプリング
case TWL_MIC_PXI_COMMAND_ONE_SAMPLING:
if (micWork.status != TWL_MIC_STATUS_READY)
{
// コマンドを実行できる状態ではない
TWL_MICi_ReturnResult(micWork.command, TWL_MIC_PXI_RESULT_ILLEGAL_STATUS);
}
else
{
// TWL MIC スレッドに操作要求
if (TWL_MICi_SetEntry( micWork.command, 0 ))
{
// 状態を"単発サンプリング開始待ち"へ
micWork.status = TWL_MIC_STATUS_ONE_SAMPLING_START;
}
else
{
// エントリー失敗(メッセージキューに空き無し)
TWL_MICi_ReturnResult(micWork.command, TWL_MIC_PXI_RESULT_FATAL_ERROR);
}
}
break;
// オートサンプリング開始
case TWL_MIC_PXI_COMMAND_AUTO_START:
if (micWork.status != TWL_MIC_STATUS_READY)
{
// コマンドを実行できる状態ではない
TWL_MICi_ReturnResult(micWork.command, TWL_MIC_PXI_RESULT_ILLEGAL_STATUS);
}
else
{
u32 dmaNo, buffer, size, frequency, loop;
dmaNo = micWork.data[0];
MIC_UNPACK_U32(&buffer, &micWork.data[1]);
MIC_UNPACK_U32(&size, &micWork.data[5]);
frequency = (u32)(micWork.data[9] << REG_SND_MICCNT_FIFO_SMP_SHIFT);
loop = micWork.data[10];
// TWL MIC スレッドに操作要求
if (TWL_MICi_SetEntry( micWork.command, 5, dmaNo, buffer, size, frequency, loop ))
{
// 状態を"自動サンプリング開始待ち"へ
micWork.status = TWL_MIC_STATUS_AUTO_START;
}
else
{
// エントリー失敗(メッセージキューに空き無し)
TWL_MICi_ReturnResult(micWork.command, TWL_MIC_PXI_RESULT_FATAL_ERROR);
}
}
break;
// オートサンプリング停止
case TWL_MIC_PXI_COMMAND_AUTO_STOP:
if (micWork.status != TWL_MIC_STATUS_AUTO_SAMPLING)
{
// コマンドを実行できる状態ではない
TWL_MICi_ReturnResult(micWork.command, TWL_MIC_PXI_RESULT_ILLEGAL_STATUS);
}
else
{
// TWL MIC スレッドに操作要求
if (TWL_MICi_SetEntry( micWork.command, 0 ))
{
// 状態を"自動サンプリング停止待ち"へ
micWork.status = TWL_MIC_STATUS_AUTO_END;
}
else
{
// エントリー失敗(メッセージキューに空き無し)
TWL_MICi_ReturnResult(micWork.command, TWL_MIC_PXI_RESULT_FATAL_ERROR);
}
}
break;
// 最新サンプリングデータアドレス取得
case TWL_MIC_PXI_COMMAND_GET_LAST_SAMPLING_ADDRESS:
// TWL MIC スレッドに操作要求
if (!TWL_MICi_SetEntry( micWork.command, 0 ))
{
// エントリー失敗(メッセージキューに空き無し)
TWL_MICi_ReturnResult(micWork.command, TWL_MIC_PXI_RESULT_FATAL_ERROR);
}
break;
// プログラマブルアンプゲイン設定
case TWL_MIC_PXI_COMMAND_SET_AMP_GAIN:
{
u32 gain = micWork.data[0];
// TWL MIC スレッドに操作要求
if (!TWL_MICi_SetEntry( micWork.command, 1, gain ))
{
// エントリー失敗(メッセージキューに空き無し)
TWL_MICi_ReturnResult(micWork.command, TWL_MIC_PXI_RESULT_FATAL_ERROR);
}
}
break;
// プログラマブルアンプゲイン取得
case TWL_MIC_PXI_COMMAND_GET_AMP_GAIN:
// TWL MIC スレッドに操作要求
if (!TWL_MICi_SetEntry( micWork.command, 0 ))
{
// エントリー失敗(メッセージキューに空き無し)
TWL_MICi_ReturnResult(micWork.command, TWL_MIC_PXI_RESULT_FATAL_ERROR);
}
break;
// 未知のコマンド
default:
TWL_MICi_ReturnResult(micWork.command, TWL_MIC_PXI_RESULT_INVALID_COMMAND);
}
}
}
/*---------------------------------------------------------------------------*
Name: TWL_MICi_ReturnResult
Description: PXI経由で処理結果をARM9に送信する
Arguments: command -
result - TWLMICPxiResultのひとつ
Returns: None.
*---------------------------------------------------------------------------*/
static void
TWL_MICi_ReturnResult(TWLMICPxiCommand command, TWLMICPxiResult result)
{
u32 pxiData = (u32)(TWL_MIC_PXI_START_BIT | TWL_MIC_PXI_RESULT_BIT |
((command << TWL_MIC_PXI_COMMAND_SHIFT) & TWL_MIC_PXI_COMMAND_MASK) |
((1 << TWL_MIC_PXI_DATA_NUMS_SHIFT) & TWL_MIC_PXI_DATA_NUMS_MASK) |
((result << TWL_MIC_PXI_1ST_DATA_SHIFT) & TWL_MIC_PXI_1ST_DATA_MASK));
while (0 > PXI_SendWordByFifo(PXI_FIFO_TAG_TWL_MIC, pxiData, 0))
{
}
}
/*---------------------------------------------------------------------------*
Name: TWL_MICi_ReturnResultEx
Description: PXI経由でARM9に送信する
Arguments: command -
result - TWLMICPxiResultのひとつ
size -
data -
Returns: None.
*---------------------------------------------------------------------------*/
static void
TWL_MICi_ReturnResultEx(TWLMICPxiCommand command, TWLMICPxiResult result, u8 size, u8* data)
{
u32 pxiData = (u32)(TWL_MIC_PXI_START_BIT | TWL_MIC_PXI_RESULT_BIT |
((command << TWL_MIC_PXI_COMMAND_SHIFT) & TWL_MIC_PXI_COMMAND_MASK) |
(((size+1) << TWL_MIC_PXI_DATA_NUMS_SHIFT) & TWL_MIC_PXI_DATA_NUMS_MASK) |
((result << TWL_MIC_PXI_1ST_DATA_SHIFT) & TWL_MIC_PXI_1ST_DATA_MASK));
int i;
while (0 > PXI_SendWordByFifo(PXI_FIFO_TAG_TWL_MIC, pxiData, 0))
{
}
for (i = 0; i < size; i += 3)
{
pxiData = (u32)((data[i] << 16) | (data[i+1] << 8) | data[i+2]);
while (0 > PXI_SendWordByFifo(PXI_FIFO_TAG_TWL_MIC, pxiData, 0))
{
}
}
}
/*---------------------------------------------------------------------------*
Name: TWL_MICi_Thread
Description: MIC操作の実処理を行うスレッド
Arguments: arg - 使
Returns: None.
*---------------------------------------------------------------------------*/
static void TWL_MICi_Thread(void *arg)
{
#pragma unused( arg )
OSMessage msg;
TWLMICMessageData* entry;
while (TRUE)
{
// メッセージが発行されるまで寝る
(void)OS_ReceiveMessage(&(micWork.msgQ), &msg, OS_MESSAGE_BLOCK);
entry = (TWLMICMessageData *) msg;
// コマンドに従って各種処理を実行
switch (entry->command)
{
//--- 単発サンプリング開始
case TWL_MIC_PXI_COMMAND_ONE_SAMPLING:
if (micWork.status == TWL_MIC_STATUS_ONE_SAMPLING_START)
{
u16 temp;
TWL_MIC_DoSampling( &temp );
TWL_MICi_ReturnResultEx(entry->command, TWL_MIC_PXI_RESULT_SUCCESS,
2, (u8*)&temp ); // ARM9に処理の成功を通達
micWork.status = TWL_MIC_STATUS_READY; // 状態を"通常操作待ち"へ
}
else
{
TWL_MICi_ReturnResult(entry->command, TWL_MIC_PXI_RESULT_ILLEGAL_STATUS);
}
break;
//--- オートサンプリング開始
case TWL_MIC_PXI_COMMAND_AUTO_START:
if (micWork.status == TWL_MIC_STATUS_AUTO_START)
{
TWLMICParam param;
param.dmaNo = (u8)entry->arg[0];
param.buffer = (void *)entry->arg[1];
param.size = entry->arg[2];
param.frequency = (MICSampleRate)entry->arg[3];
param.loop = (u8)entry->arg[4];
param.callback = TWL_MICi_FullCallback;
TWL_MIC_StartAutoSampling( param );
TWL_MICi_ReturnResult(entry->command, TWL_MIC_PXI_RESULT_SUCCESS); // ARM9に処理の成功を通達
micWork.status = TWL_MIC_STATUS_AUTO_SAMPLING; // 状態を"自動サンプリング中"へ
}
else
{
TWL_MICi_ReturnResult(entry->command, TWL_MIC_PXI_RESULT_ILLEGAL_STATUS);
}
break;
//--- オートサンプリング停止
case TWL_MIC_PXI_COMMAND_AUTO_STOP:
if ((micWork.status == TWL_MIC_STATUS_AUTO_END) || (micWork.status == TWL_MIC_STATUS_END_WAIT))
{
TWL_MIC_StopAutoSampling();
// ARM9に処理の成功を通達
if (micWork.status == TWL_MIC_STATUS_AUTO_END)
{
TWL_MICi_ReturnResult(TWL_MIC_PXI_COMMAND_AUTO_STOP, TWL_MIC_PXI_RESULT_SUCCESS);
}
// 内部状態を更新
micWork.status = TWL_MIC_STATUS_READY; // 状態を"通常操作待ち"へ
}
else
{
TWL_MICi_ReturnResult(entry->command, TWL_MIC_PXI_RESULT_ILLEGAL_STATUS);
}
break;
//--- 最新サンプリングデータアドレス取得
case TWL_MIC_PXI_COMMAND_GET_LAST_SAMPLING_ADDRESS:
{
void* adress = TWL_MIC_GetLastSamplingAddress();
TWL_MICi_ReturnResultEx(entry->command, TWL_MIC_PXI_RESULT_SUCCESS,
4, (u8*)&adress ); // ARM9に処理の成功を通達
}
break;
//--- プログラマブルアンプゲイン設定
case TWL_MIC_PXI_COMMAND_SET_AMP_GAIN:
{
u8 gain = (u8)entry->arg[0];
TWL_MIC_SetAmpGain( gain );
TWL_MICi_ReturnResult(entry->command, TWL_MIC_PXI_RESULT_SUCCESS); // ARM9に処理の成功を通達
}
break;
//--- プログラマブルアンプゲイン取得
case TWL_MIC_PXI_COMMAND_GET_AMP_GAIN:
{
u8 gain = TWL_MIC_GetAmpGain();
TWL_MICi_ReturnResultEx(entry->command, TWL_MIC_PXI_RESULT_SUCCESS,
1, (u8*)&gain ); // ARM9に処理の成功を通達
}
//--- サポートしないコマンド
default:
TWL_MICi_ReturnResult(entry->command, TWL_MIC_PXI_RESULT_INVALID_COMMAND);
}
}
}
/*---------------------------------------------------------------------------*
Name: TWL_MICi_FullCallback
Description:
Arguments:
Returns: None.
*---------------------------------------------------------------------------*/
static void TWL_MICi_FullCallback( u8 loop )
{
// FULL通知
TWL_MICi_ReturnResult(TWL_MIC_PXI_COMMAND_MIC_BUFFER_FULL, TWL_MIC_PXI_RESULT_SUCCESS);
if ( !loop )
{
// 自動サンプリング停止
if (TWL_MICi_SetEntry( TWL_MIC_PXI_COMMAND_AUTO_STOP, 0 ))
{
micWork.status = TWL_MIC_STATUS_END_WAIT; // 状態を"自動サンプリング完了待ち"へ
}
else
{
TWL_MICi_ReturnResult(TWL_MIC_PXI_COMMAND_AUTO_STOP, TWL_MIC_PXI_RESULT_FATAL_ERROR);
}
}
}

View File

@ -0,0 +1,55 @@
#! make -f
#----------------------------------------------------------------------------
# Project: TwlSDK - libraries - camera/ARM9
# File: Makefile
#
# Copyright 2007 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.
#
# $Log: $
# $NoKeywords: $
#----------------------------------------------------------------------------
SUBDIRS =
#----------------------------------------------------------------------------
# build ARM & THUMB libraries
TWL_CODEGEN_ALL ?= True
SRCDIR = ../common ./src
SRCS = twl_mic_api.c \
TARGET_LIB = libtwlmic$(TWL_LIBSUFFIX).a
#----------------------------------------------------------------------------
# DEBUG版ビルドの場合、RELEASE版でビルドして
# DEBUG版のライブラリを装います。
#ifdef NITRO_DEBUG
#NITRO_BUILD_TYPE = RELEASE
#endif
include $(TWLSDK_ROOT)/build/buildtools/commondefs
INSTALL_TARGETS = $(TARGETS)
INSTALL_DIR = $(TWL_INSTALL_LIBDIR)
#----------------------------------------------------------------------------
do-build: $(TARGETS)
include $(TWLSDK_ROOT)/build/buildtools/modulerules
#===== End of Makefile =====

View File

@ -0,0 +1,807 @@
/*---------------------------------------------------------------------------*
Project: TwlSDK - library - camera
File: camera.c
Copyright 2007 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.
$Log: $
$NoKeywords: $
*---------------------------------------------------------------------------*/
#include <twl.h>
#include <twl/mic.h>
/*---------------------------------------------------------------------------*
*---------------------------------------------------------------------------*/
// 詰めてコピーする
#define MIC_PACK_U16(d, s) \
((d)[0] = (u8)((*((u16*)s) >> 0) & 0xFF), \
(d)[1] = (u8)((*((u16*)s) >> 8) & 0xFF))
#define MIC_PACK_U32(d, s) \
((d)[0] = (u8)((*((u32*)s) >> 0) & 0xFF), \
(d)[1] = (u8)((*((u32*)s) >> 8) & 0xFF), \
(d)[2] = (u8)((*((u32*)s) >> 16) & 0xFF), \
(d)[3] = (u8)((*((u32*)s) >> 24) & 0xFF))
/*---------------------------------------------------------------------------*
*---------------------------------------------------------------------------*/
typedef struct _TWLMICWork
{
BOOL lock;
TwlMicCallback callback; // 非同期関数用コールバック
void* callbackArg; // 上記関数用引数
TwlMicCallback full_callback; // 非同期関数用コールバック
void* full_arg; // 上記関数用引数
TWLMICResult result; // 先頭データだけ別枠
TWLMICPxiCommand command; // コマンド種別
TWLMICPxiResult pxiResult; // 先頭データだけ別枠
u16* pOneBuffer; // 単発サンプリングバッファ保存用
void** pLastSamplingAddress; // 最新サンプリングデータ格納アドレス
u8* pAmpGain; // アンプゲイン格納アドレス
u8 current; // 受信済みデータ個数 (バイト単位) (先頭を除く!!)
u8 total; // 最終データ個数 (1 + 後続コマンド*3)
u8 data[TWL_MIC_PXI_DATA_SIZE_MAX]; // ARM7からのデータ保存用
}
TWLMICWork;
/*---------------------------------------------------------------------------*
*---------------------------------------------------------------------------*/
static BOOL micInitialized;
static TWLMICWork micWork;
/*---------------------------------------------------------------------------*
*---------------------------------------------------------------------------*/
static BOOL TWLMICi_SendPxiCommand(TWLMICPxiCommand command, u8 size, u8 data);
static void TWLMICi_SendPxiData(u8 *pData);
static void TWLMICi_PxiCallback(PXIFifoTag tag, u32 data, BOOL err);
static void TWLMICi_CallbackAndUnlock(TWLMICResult result);
static void TWLMICi_GetResultCallback(TWLMICResult result, void *arg);
static void TWLMICi_WaitBusy(void);
/*---------------------------------------------------------------------------*
Name: TWL_MIC_Init
Description: MICライブラリを初期化する
Arguments: None.
Returns: None.
*---------------------------------------------------------------------------*/
void TWL_MIC_Init(void)
{
// 初期化済みを確認
if (micInitialized)
{
return;
}
micInitialized = 1;
// 変数初期化
micWork.lock = FALSE;
micWork.callback = NULL;
// PXI関連を初期化
PXI_Init();
while (!PXI_IsCallbackReady(PXI_FIFO_TAG_TWL_MIC, PXI_PROC_ARM7))
{
}
PXI_SetFifoRecvCallback(PXI_FIFO_TAG_TWL_MIC, TWLMICi_PxiCallback);
}
/*---------------------------------------------------------------------------*
Name: TWL_MIC_End
Description: MICライブラリを終了する
Arguments: None.
Returns: None.
*---------------------------------------------------------------------------*/
void TWL_MIC_End(void)
{
// 初期化済みを確認
if (micInitialized == 0)
{
return;
}
micInitialized = 0;
// PXI関連停止
PXI_SetFifoRecvCallback(PXI_FIFO_TAG_TWL_MIC, NULL);
}
/*---------------------------------------------------------------------------*
Name: TWL_MIC_DoSamplingAsync
Description:
Arguments:
Returns: TWLMICResult
*---------------------------------------------------------------------------*/
TWLMICResult
TWL_MIC_DoSamplingAsync(u16* buf, TwlMicCallback callback, void* callbackArg)
{
const TWLMICPxiCommand command = TWL_MIC_PXI_COMMAND_ONE_SAMPLING;
const u8 size = TWL_MIC_PXI_SIZE_ONE_SAMPLING; // バイト
OSIntrMode enabled;
// buffer NULLチェック
// ToDo: 適切なアドレスかどうかチェック
if (buf == NULL)
{
return TWL_MIC_RESULT_ILLEGAL_PARAMETER;
}
// ロック
enabled = OS_DisableInterrupts();
if (micWork.lock)
{
(void)OS_RestoreInterrupts(enabled);
return TWL_MIC_RESULT_BUSY;
}
micWork.lock = TRUE;
(void)OS_RestoreInterrupts(enabled);
// 非同期関数用コールバック設定
micWork.callback = callback;
micWork.callbackArg = callbackArg;
// バッファアドレス保存
micWork.pOneBuffer = buf;
// コマンド送信
if (TWLMICi_SendPxiCommand(command, size, 0) == FALSE)
{
return TWL_MIC_RESULT_SEND_ERROR;
}
return TWL_MIC_RESULT_SUCCESS;
}
/*---------------------------------------------------------------------------*
Name: TWL_MIC_DoSampling
Description:
Arguments:
Returns: TWLMICResult
*---------------------------------------------------------------------------*/
TWLMICResult
TWL_MIC_DoSampling(u16* buf)
{
micWork.result = TWL_MIC_DoSamplingAsync(buf, TWLMICi_GetResultCallback, 0);
if (micWork.result == TWL_MIC_RESULT_SUCCESS)
{
TWLMICi_WaitBusy();
}
return micWork.result;
}
/*---------------------------------------------------------------------------*
Name: TWL_MIC_StartAutoSamplingAsync
Description:
Arguments: mic - one of MicSelect
Returns: TWLMICResult
*---------------------------------------------------------------------------*/
TWLMICResult
TWL_MIC_StartAutoSamplingAsync(TwlMicAutoParam* param, TwlMicCallback callback, void* callbackArg)
{
const TWLMICPxiCommand command = TWL_MIC_PXI_COMMAND_AUTO_START;
const u8 size = TWL_MIC_PXI_SIZE_AUTO_START; // バイト
OSIntrMode enabled;
u8 data[size+2];
int i;
// DMA-Noチェック
if ( param->dmaNo < MI_EXDMA_CH_MIN || MI_EXDMA_CH_MAX < param->dmaNo )
{
return TWL_MIC_RESULT_ILLEGAL_PARAMETER;
}
// buffer NULLチェック & 4バイトアライメントチェック
// ToDo: 適切なアドレスかどうかチェック
if (param->buffer == NULL || (u32)param->buffer & 0x03)
{
return TWL_MIC_RESULT_ILLEGAL_PARAMETER;
}
// size 4バイトの倍数チェック
// ToDo: buffer + size が適切なメモリ範囲か
if (param->size & 0x03)
{
return TWL_MIC_RESULT_ILLEGAL_PARAMETER;
}
// frequencyチェック
if ( param->frequency > TWL_MIC_FREQUENCY_1_4 )
{
return TWL_MIC_RESULT_ILLEGAL_PARAMETER;
}
// ロック
enabled = OS_DisableInterrupts();
if (micWork.lock)
{
(void)OS_RestoreInterrupts(enabled);
return TWL_MIC_RESULT_BUSY;
}
micWork.lock = TRUE;
(void)OS_RestoreInterrupts(enabled);
// 非同期関数用コールバック設定
micWork.callback = callback;
micWork.callbackArg = callbackArg;
// FULLコールバック設定
if (param->full_callback)
{
micWork.full_callback = param->full_callback;
micWork.full_arg = param->full_arg;
}
// データ作成
data[0] = (u8)param->dmaNo;
MIC_PACK_U32(&data[1], &param->buffer);
MIC_PACK_U32(&data[5], &param->size);
data[9] = (u8)param->frequency;
data[10] = (u8)param->loop_enable;
// コマンド送信
if (TWLMICi_SendPxiCommand(command, size, data[0]) == FALSE)
{
return TWL_MIC_RESULT_SEND_ERROR;
}
for (i = 1; i < size; i+=3) {
TWLMICi_SendPxiData(&data[i]);
}
return TWL_MIC_RESULT_SUCCESS;
}
/*---------------------------------------------------------------------------*
Name: TWL_MIC_StartAutoSampling
Description:
Arguments: param
Returns: TWLMICResult
*---------------------------------------------------------------------------*/
TWLMICResult
TWL_MIC_StartAutoSampling(TwlMicAutoParam* param)
{
micWork.result = TWL_MIC_StartAutoSamplingAsync(param, TWLMICi_GetResultCallback, 0);
if (micWork.result == TWL_MIC_RESULT_SUCCESS)
{
TWLMICi_WaitBusy();
}
return micWork.result;
}
/*---------------------------------------------------------------------------*
Name: TWL_MIC_StopAutoSamplingAsync
Description:
Arguments: none
Returns: TWLMICResult
*---------------------------------------------------------------------------*/
TWLMICResult
TWL_MIC_StopAutoSamplingAsync( TwlMicCallback callback, void* callbackArg )
{
const TWLMICPxiCommand command = TWL_MIC_PXI_COMMAND_AUTO_STOP;
const u8 size = TWL_MIC_PXI_SIZE_AUTO_STOP; // バイト
OSIntrMode enabled;
// ロック
enabled = OS_DisableInterrupts();
if (micWork.lock)
{
(void)OS_RestoreInterrupts(enabled);
return TWL_MIC_RESULT_BUSY;
}
micWork.lock = TRUE;
(void)OS_RestoreInterrupts(enabled);
// コールバック設定
micWork.callback = callback;
micWork.callbackArg = callbackArg;
// コマンド送信
if (TWLMICi_SendPxiCommand(command, size, 0) == FALSE)
{
return TWL_MIC_RESULT_SEND_ERROR;
}
return TWL_MIC_RESULT_SUCCESS;
}
/*---------------------------------------------------------------------------*
Name: TWL_MIC_StopAutoSampling
Description:
Arguments: param
Returns: TWLMICResult
*---------------------------------------------------------------------------*/
TWLMICResult
TWL_MIC_StopAutoSampling( void )
{
micWork.result = TWL_MIC_StopAutoSamplingAsync(TWLMICi_GetResultCallback, 0);
if (micWork.result == TWL_MIC_RESULT_SUCCESS)
{
TWLMICi_WaitBusy();
}
return micWork.result;
}
/*---------------------------------------------------------------------------*
Name: TWL_MIC_GetLastSamplingAddressAsync
Description:
Arguments: adress :
callback :
callbackArg :
Returns: TWLMICResult
*---------------------------------------------------------------------------*/
TWLMICResult
TWL_MIC_GetLastSamplingAddressAsync( void** adress, TwlMicCallback callback, void* callbackArg )
{
const TWLMICPxiCommand command = TWL_MIC_PXI_COMMAND_GET_LAST_SAMPLING_ADDRESS;
const u8 size = TWL_MIC_PXI_SIZE_GET_LAST_SAMPLING_ADDRESS; // バイト
OSIntrMode enabled;
// ロック
enabled = OS_DisableInterrupts();
if (micWork.lock)
{
(void)OS_RestoreInterrupts(enabled);
return TWL_MIC_RESULT_BUSY;
}
micWork.lock = TRUE;
(void)OS_RestoreInterrupts(enabled);
// コールバック設定
micWork.callback = callback;
micWork.callbackArg = callbackArg;
// アドレス格納アドレス保存
micWork.pLastSamplingAddress = adress;
// コマンド送信
if (TWLMICi_SendPxiCommand(command, size, 0) == FALSE)
{
return TWL_MIC_RESULT_SEND_ERROR;
}
return TWL_MIC_RESULT_SUCCESS;
}
/*---------------------------------------------------------------------------*
Name: TWL_MIC_GetLastSamplingAddress
Description:
Arguments: adress :
Returns: TWLMICResult
*---------------------------------------------------------------------------*/
TWLMICResult
TWL_MIC_GetLastSamplingAddress( void** adress )
{
micWork.result = TWL_MIC_GetLastSamplingAddressAsync( adress, TWLMICi_GetResultCallback, 0);
if (micWork.result == TWL_MIC_RESULT_SUCCESS)
{
TWLMICi_WaitBusy();
}
return micWork.result;
}
/*---------------------------------------------------------------------------*
Name: TWL_MIC_SetAmpGainAsync
Description:
        
Arguments: gain : 0119 = 059.5dB
callback :
callbackArg :
Returns: TWLMICResult
*---------------------------------------------------------------------------*/
TWLMICResult
TWL_MIC_SetAmpGainAsync( u8 gain, TwlMicCallback callback, void* callbackArg )
{
const TWLMICPxiCommand command = TWL_MIC_PXI_COMMAND_SET_AMP_GAIN;
const u8 size = TWL_MIC_PXI_SIZE_SET_AMP_GAIN; // バイト
u8 data[size+2];
OSIntrMode enabled;
// 設定ゲイン範囲チェック
if ( gain > 119)
{
return TWL_MIC_RESULT_ILLEGAL_PARAMETER;
}
// ロック
enabled = OS_DisableInterrupts();
if (micWork.lock)
{
(void)OS_RestoreInterrupts(enabled);
return TWL_MIC_RESULT_BUSY;
}
micWork.lock = TRUE;
(void)OS_RestoreInterrupts(enabled);
// コールバック設定
micWork.callback = callback;
micWork.callbackArg = callbackArg;
// データ作成
data[0] = gain;
// コマンド送信
if (TWLMICi_SendPxiCommand(command, size, data[0]) == FALSE)
{
return TWL_MIC_RESULT_SEND_ERROR;
}
return TWL_MIC_RESULT_SUCCESS;
}
/*---------------------------------------------------------------------------*
Name: TWL_MIC_SetAmpGain
Description:
Arguments: gain : 0119 = 059.5dB
Returns: TWLMICResult
*---------------------------------------------------------------------------*/
TWLMICResult
TWL_MIC_SetAmpGain( u8 gain )
{
micWork.result = TWL_MIC_SetAmpGainAsync( gain, TWLMICi_GetResultCallback, 0);
if (micWork.result == TWL_MIC_RESULT_SUCCESS)
{
TWLMICi_WaitBusy();
}
return micWork.result;
}
/*---------------------------------------------------------------------------*
Name: TWL_MIC_GetAmpGainAsync
Description: TWLモードのマイクゲイン(PGAB)
Arguments: gain :
callback :
callbackArg :
Returns: TWLMICResult
*---------------------------------------------------------------------------*/
TWLMICResult
TWL_MIC_GetAmpGainAsync( u8* gain, TwlMicCallback callback, void* callbackArg )
{
const TWLMICPxiCommand command = TWL_MIC_PXI_COMMAND_GET_AMP_GAIN;
const u8 size = TWL_MIC_PXI_SIZE_GET_AMP_GAIN; // バイト
OSIntrMode enabled;
// NULLチェック
if ( gain == NULL)
{
return TWL_MIC_RESULT_ILLEGAL_PARAMETER;
}
// ロック
enabled = OS_DisableInterrupts();
if (micWork.lock)
{
(void)OS_RestoreInterrupts(enabled);
return TWL_MIC_RESULT_BUSY;
}
micWork.lock = TRUE;
(void)OS_RestoreInterrupts(enabled);
// コールバック設定
micWork.callback = callback;
micWork.callbackArg = callbackArg;
// ゲイン格納アドレス保存
micWork.pAmpGain = gain;
// コマンド送信
if (TWLMICi_SendPxiCommand(command, size, 0) == FALSE)
{
return TWL_MIC_RESULT_SEND_ERROR;
}
return TWL_MIC_RESULT_SUCCESS;
}
/*---------------------------------------------------------------------------*
Name: TWL_MIC_GetAmpGain
Description: TWLモードのマイクゲイン(PGAB)
Arguments: gain :
Returns: TWLMICResult
*---------------------------------------------------------------------------*/
TWLMICResult
TWL_MIC_GetAmpGain( u8* gain )
{
micWork.result = TWL_MIC_GetAmpGainAsync( gain, TWLMICi_GetResultCallback, 0);
if (micWork.result == TWL_MIC_RESULT_SUCCESS)
{
TWLMICi_WaitBusy();
}
return micWork.result;
}
/*---------------------------------------------------------------------------*
Name: TWLMICi_SendPxiCommand
Description: PXI経由でARM7に送信する
Arguments: command -
size - ()
data - (1)
Returns: BOOL - PXIに対して送信が完了した場合TRUEを
PXIによる送信に失敗した場合FALSEを返す
*---------------------------------------------------------------------------*/
static BOOL TWLMICi_SendPxiCommand(TWLMICPxiCommand command, u8 size, u8 data)
{
u32 pxiData = (u32)(TWL_MIC_PXI_START_BIT |
((command << TWL_MIC_PXI_COMMAND_SHIFT) & TWL_MIC_PXI_COMMAND_MASK) |
((size << TWL_MIC_PXI_DATA_NUMS_SHIFT) & TWL_MIC_PXI_DATA_NUMS_MASK) |
((data << TWL_MIC_PXI_1ST_DATA_SHIFT) & TWL_MIC_PXI_1ST_DATA_MASK));
if (0 > PXI_SendWordByFifo(PXI_FIFO_TAG_TWL_MIC, pxiData, 0))
{
return FALSE;
}
return TRUE;
}
/*---------------------------------------------------------------------------*
Name: TWLMICi_SendPxiData
Description: PXI経由でARM7に送信する
Arguments: pData - 3
Returns: None
*---------------------------------------------------------------------------*/
static void TWLMICi_SendPxiData(u8 *pData)
{
u32 pxiData = (u32)((pData[0] << 16) | (pData[1] << 8) | pData[2]);
while (0 > PXI_SendWordByFifo(PXI_FIFO_TAG_TWL_MIC, pxiData, 0))
{
}
}
/*---------------------------------------------------------------------------*
Name: TWLMICi_PxiCallback
Description:
Arguments: tag - PXI tag which show message type.
data - message from ARM7.
err - PXI transfer error flag.
Returns: None.
*---------------------------------------------------------------------------*/
static void TWLMICi_PxiCallback(PXIFifoTag tag, u32 data, BOOL err)
{
#pragma unused( tag )
TWLMICResult result;
// PXI通信エラーを確認
if (err)
{
// シーケンスを強制終了
TWLMICi_CallbackAndUnlock(TWL_MIC_RESULT_FATAL_ERROR);
return;
}
// 先頭データ
if (data & TWL_MIC_PXI_START_BIT)
{
// 受信データを解析
SDK_ASSERT((data & TWL_MIC_PXI_RESULT_BIT) == TWL_MIC_PXI_RESULT_BIT);
micWork.total = (u8)((data & TWL_MIC_PXI_DATA_NUMS_MASK) >> TWL_MIC_PXI_DATA_NUMS_SHIFT);
micWork.current = 0;
micWork.command = (TWLMICPxiCommand)((data & TWL_MIC_PXI_COMMAND_MASK) >> TWL_MIC_PXI_COMMAND_SHIFT);
micWork.pxiResult = (TWLMICPxiResult)((data & TWL_MIC_PXI_1ST_DATA_MASK) >> TWL_MIC_PXI_1ST_DATA_SHIFT);
}
// 後続データ
else
{
if (micWork.current < TWL_MIC_PXI_DATA_SIZE_MAX)
{
micWork.data[micWork.current++] = (u8)((data & 0xFF0000) >> 16);
}
if (micWork.current < TWL_MIC_PXI_DATA_SIZE_MAX)
{
micWork.data[micWork.current++] = (u8)((data & 0x00FF00) >> 8);
}
if (micWork.current < TWL_MIC_PXI_DATA_SIZE_MAX)
{
micWork.data[micWork.current++] = (u8)((data & 0x0000FF) >> 0);
}
}
if (micWork.current >= micWork.total-1) // > は無いはず
{
// 処理結果を確認
switch (micWork.pxiResult)
{
case TWL_MIC_PXI_RESULT_SUCCESS:
result = TWL_MIC_RESULT_SUCCESS;
break;
case TWL_MIC_PXI_RESULT_INVALID_COMMAND:
result = TWL_MIC_RESULT_INVALID_COMMAND;
break;
case TWL_MIC_PXI_RESULT_INVALID_PARAMETER:
result = TWL_MIC_RESULT_ILLEGAL_PARAMETER;
break;
case TWL_MIC_PXI_RESULT_ILLEGAL_STATUS:
result = TWL_MIC_RESULT_ILLEGAL_STATUS;
break;
case TWL_MIC_PXI_RESULT_BUSY:
result = TWL_MIC_RESULT_BUSY;
break;
default:
result = TWL_MIC_RESULT_FATAL_ERROR;
}
switch (micWork.command)
{
case TWL_MIC_PXI_COMMAND_MIC_BUFFER_FULL:
// FULLコールバックの呼び出し
if (micWork.full_callback)
{
micWork.full_callback( result, micWork.full_arg );
}
break;
case TWL_MIC_PXI_COMMAND_ONE_SAMPLING:
// 単発サンプリング結果格納
*micWork.pOneBuffer = (u16)(micWork.data[0] | (micWork.data[1] << 8));
// 非同期関数用コールバックの呼び出し&ロック解除
TWLMICi_CallbackAndUnlock(result);
break;
case TWL_MIC_PXI_COMMAND_GET_LAST_SAMPLING_ADDRESS:
// 最新サンプリングデータアドレス格納
*micWork.pLastSamplingAddress = (void *)(micWork.data[0] | (micWork.data[1] << 8) | (micWork.data[2] << 16) | (micWork.data[3] << 24));
// 非同期関数用コールバックの呼び出し&ロック解除
TWLMICi_CallbackAndUnlock(result);
break;
case TWL_MIC_PXI_COMMAND_GET_AMP_GAIN:
// アンプゲイン格納
*micWork.pAmpGain = micWork.data[0];
// 非同期関数用コールバックの呼び出し&ロック解除
TWLMICi_CallbackAndUnlock(result);
break;
default:
// 非同期関数用コールバックの呼び出し&ロック解除
TWLMICi_CallbackAndUnlock(result);
}
}
}
/*---------------------------------------------------------------------------*
Name: TWLMICi_CallbackAndUnlock
Description:
Arguments: result - ARM7から送られた結果
Returns: None.
*---------------------------------------------------------------------------*/
static void TWLMICi_CallbackAndUnlock(TWLMICResult result)
{
TwlMicCallback cb;
// ロック解除
if (micWork.lock)
{
micWork.lock = FALSE;
}
// 非同期関数用コールバック呼び出し
if (micWork.callback)
{
cb = micWork.callback;
micWork.callback = NULL;
cb(result, micWork.callbackArg);
}
}
/*---------------------------------------------------------------------------*
Name: TWLMICi_GetResultCallback
Description:
使
Arguments: result -
arg - 使
Returns: None.
*---------------------------------------------------------------------------*/
static void TWLMICi_GetResultCallback(TWLMICResult result, void *arg)
{
#pragma unused( arg )
micWork.result = result;
}
/*---------------------------------------------------------------------------*
Name: TWLMICi_WaitBusy
Description: MICの非同期処理がロックされている間待つ
Arguments: None.
Returns: None.
*---------------------------------------------------------------------------*/
#if 0
#include <nitro/code32.h>
static asm void TWLMICi_WaitBusy(void)
{
ldr r12, =micWork.lock
loop:
ldr r0, [ r12, #0 ]
cmp r0, #TRUE
beq loop
bx lr
}
#include <nitro/codereset.h>
#else
extern void PXIi_HandlerRecvFifoNotEmpty(void);
static void TWLMICi_WaitBusy(void)
{
volatile BOOL *p = &micWork.lock;
while (*p)
{
if (OS_GetCpsrIrq() == OS_INTRMODE_IRQ_DISABLE)
{
PXIi_HandlerRecvFifoNotEmpty();
}
}
}
#endif