twl_wrapsdk/build/libraries/mic/ARM7/src/twl_mic_api.c
kamikawa e7bc2d65d4 肝心の新規マイクライブラリを追加
git-svn-id: file:///Users/lillianskinner/Downloads/platinum/twl/twl_wrapsdk/trunk@289 4ee2a332-4b2b-5046-8439-1ba90f034370
2007-09-28 11:03:00 +00:00

482 lines
14 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*---------------------------------------------------------------------------*
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起動方式 ★★
ブロック転送サイズ  :8ワード
インターバル     :0
転送ワード      :8ワード
総転送ワード     :バッファサイズ
コンティニュアスモード:OFF
<解説>
FIFOに半分データが溜まる度にDMA起動要求がかかり
8ワード転送される。
バッファサイズ分の転送が完了後に割り込みがかかるので
そこでDMAを再設定。
<メリット>
・FIFOとDMAのタイミングがきっちりと合う。
・色々な周波数に対応しやすい。
<デメリット>
・DMAがどこまで進んだか分からないためMIC_GetLastSamplingAddress
 で正確なアドレスが取れない。チックを使用して大体の位置を
 予測することは可能。
★★ インターバル方式 ★★
ブロック転送サイズ  :8ワード
インターバル     :適切値
転送ワード      :バッファサイズ
総転送ワード     :バッファサイズ
コンティニュアスモード:ON
<解説>
周波数から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 );
}