ctr_mcu/trunk/adc.c
N2232 e7f6124f7a 1.0.1B (TWL-PMIC版は全く検証してません)
adc.c 音量が瞬間的に大きくなる対策で割り込み禁止の区間を変更。余り期間を延ばすとTWLが動かなくなるので慎重に
batt_params.h 未定義バッテリメーカーのダミー値をそれっぽいものに差し替え
pm.c アダプタ接続時、満充電でも充電禁止温度でも強制的に1秒くらい充電ランプを点ける。その状態で抜かれたときローコストにできるだけ速く消灯させる。(アダプタ接続のチェック:修理品&UIのため
pm.c 電池少ない割り込み 評価結果がきたので割り込みを入れるのを10%,5%,0%に。それと電圧で残量%の上書き
task_sys.c 電池が空っぽの時にアダプタをつないでいても電源が入らなかった。さすがに不親切なので電源は入れさせる。(変えるかも) すぐに電池切れ割り込みが入る。
vreg_ctr.c TWLのステータスレジスタ、CTR側のミラーからかけるようにした。 AGBで困るとのこと


git-svn-id: file:///Volumes/Transfer/gigaleak_20231201/2020-05-23%20-%20ctr.7z%20+%20svn_v1.068.zip/ctr/svn/ctr_mcu@190 013db118-44a6-b54f-8bf7-843cb86687b1
2010-06-09 06:56:34 +00:00

347 lines
9.2 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.

/* ========================================================
藤田@開技
nintendo
'09 Apr
======================================================== */
#include "incs.h"
#include "adc.h"
#include "pm.h"
#include "led.h"
//#define _4db_
#define _15db_
// ===================================================== //
bit adc_updated;
u8 adc_raw_vol;
u8 adc_raw_dep;
// ===================================================== //
extern void nop8();
// ===================================================== //
#define INTERVAL_TSK_ADC 15
/* ========================================================
ADC設定と、開始
以下のピンは主にここで操作・監視されます。
・BT_TEMP,_P
・ADIN1
・VOL
関係ありそうですが別のところで管理しています
・PM_BT_DET,_P BT_init
・8tics毎に呼ばれ、チャンネル分取り込むとADCを停止します。
 タスク起動時、レジスタには前回の取り込み値が入っています。
======================================================== */
#ifdef _15db_
// max -15db
const u8 slider_to_codec[64] =
{
127, 127, 127, 127, 127, 126, 125, 123,
122, 121, 120, 119, 118, 117, 116, 115,
114, 113, 112, 110, 109, 108, 107, 106,
105, 104, 103, 102, 101, 100, 99, 97,
96, 95, 94, 93, 92, 91, 90, 89,
88, 87, 86, 85, 84, 83, 82, 81,
80, 79, 78, 77, 76, 75, 74, 73,
71, 70, 69, 68, 67, 66, 66, 66
};
#endif
#ifdef _4db_
// max -4db
const u8 slider_to_codec[64] =
{
127, 127, 126, 125, 123, 122, 121, 119,
118, 117, 115, 114, 112, 111, 110, 108,
107, 106, 104, 103, 101, 100, 99, 97,
96, 94, 93, 92, 90, 89, 88, 86,
85, 83, 82, 81, 79, 78, 77, 75,
74, 72, 71, 70, 68, 67, 66, 64,
64, 63, 61, 60, 59, 57, 56, 54,
53, 52, 50, 49, 48, 46, 44, 44
};
#endif
void tsk_adc( )
{
static u8 task_interval = 0;
static u8 old_tune;
static u8 sndvol_codec;
static u8 bt_temp_old;
if( task_interval-- != 0 )
{
return;
}
else
{
task_interval = (u8)( INTERVAL_TSK_ADC / SYS_INTERVAL_TICK );
}
if( adc_updated )
{
adc_updated = 0;
if( system_status.pwr_state == ON )
{
// 3D /////////////////////////////////////////
{
// 似非ヒステリシス V2
// ガリオームには適さない
#define KIKAN 32
static u8 old_value;
static s8 diffs;
u8 temp;
if( abs( adc_raw_dep - old_value ) >= 2 )
{
// 大きく離れた
vreg_ctr[ VREG_C_TUNE ] = adc_raw_dep;
old_value = adc_raw_dep;
#if 0
割り込み入れない;
割り込みを入れるようであれば、ちゃんと変化チェックする;
set_irq( VREG_C_IRQ0, REG_BIT_VR_TUNE_CHANGE );
#endif
diffs = 0;
}
else
{
// 近所の値でも、ある期間でいっぱい偏っていたらそっちに寄せる
static u8 kikan_count = KIKAN;
if( old_value < adc_raw_dep )
{
diffs += 1;
}
else if( old_value > adc_raw_dep )
{
diffs -= 1;
}
if( --kikan_count == 0 )
{
if( diffs >= KIKAN && ( diffs < 64 ))
{
old_value += 1;
}
else if( ( diffs <= ( 256 - KIKAN )) && ( diffs > ( 128 + 64 ) )) // あらー?
{
old_value -= 1;
}
vreg_ctr[ VREG_C_TUNE ] = old_value;
kikan_count = KIKAN;
diffs = 0;
}
}
}
// Volume /////////////////////////////////////
{
static u8 vol_old;
static u8 force_update_vol;
if(( vreg_ctr[ VREG_C_VOL_DIGITAL ] & 0x80 ) != 0 )
{
// レジスタから強制セット
adc_raw_vol = ( vreg_ctr[ VREG_C_VOL_DIGITAL ] * 4 );
}
// todo debug
if( ( abs( adc_raw_vol - vol_old ) >= 2 ) // 生値でこれくらいずれたら更新(似非ヒステリシス)
|| ( --force_update_vol == 0 ) ) // ポーリング
{
vol_old = adc_raw_vol;
// レジスタ更新
vreg_twl[ REG_TWL_INT_ADRS_VOL ] = vol_old / ( 256 / 32 ); // ←adc値でよい
vreg_ctr[ VREG_C_SND_VOL ] = ( vol_old / 4 ); // 64段
// codecに伝える
iic_mcu_write_a_byte( IIC_SLA_CODEC, CODEC_REG_VOL, slider_to_codec[ ( vol_old / 4 ) & 0x3F ] );
#ifndef _MODEL_CTR_
iic_mcu_write_a_byte( IIC_SLA_DCP, 0, slider_to_codec[ ( 255 - vol_old ) / 4 ] );
#endif
// set_irq( VREG_C_IRQ0, REG_BIT_VR_SNDVOL_CHANGE ); // 割り込み廃止
force_update_vol = 10;
}
}
// バッテリ識別 ///////////////////////////
/* 呼ばれません */
}
}
ADCEN = 1;
ADM = 0b00001011; // セレクトモード、昇圧、fCLK/6 ///ここから ↓
ADPC = 0x06; // ADCポートのセレクト
ADS = ADC_SEL_TUNE;
nop8();
ADCS = 1; // AD開始。 /// ここまで  までに1us=8clk以上開ける
ADIF = 0;
ADMK = 0;
}
/* ========================================================
 過去つのminでもMAXでもない値を返す
 突発的なノイズを除く。
 根本対策ではないが、これはこれで使い道がある。
======================================================== */
static u8 getmean3( u8 * hist )
{
if( *hist > *( hist + 1 ) )
{
if( *hist > *( hist + 2 ) )
{
return( ( *( hist + 1 ) > *( hist + 2 ) ) ? *( hist + 1 ) : *( hist + 2 ) );
}
else
{
return( *hist );
}
}else{
if( *hist > *( hist + 2 ) )
{
return( *hist );
}
else
{
return( ( *( hist + 1 ) < *( hist + 2 ) ) ? *( hist + 1 ) : *( hist + 2 ) );
}
}
}
/* ========================================================
 自前で次のチャンネル
  一通り終わったら止める
======================================================== */
__interrupt void int_adc( )
{
static u8 hist_tune[3];
static u8 hist_snd_vol[3];
static u8 hist_bt_temp[3];
static u8 index;
volatile u8 adc_data;
adc_data = ADCRH;
switch ( ADS )
{
/*
case ( ADC_SEL_AMB_BRIT ): // 環境明るさ
vreg_ctr[ VREG_C_AMBIENT_BRIGHTNESS ] = adc_data;
break;
*/
case ( ADC_SEL_TUNE ):
hist_tune[index] = adc_data;
EI();
#ifdef _MODEL_WM0_
adc_raw_dep = 255 - getmean3( hist_tune );
#else
adc_raw_dep = getmean3( hist_tune );
#endif
break;
case ( ADC_SEL_VOL ):
hist_snd_vol[index] = adc_data;
EI();
#ifdef _MODEL_CTR_
if( system_status.model == MODEL_TS_BOARD )
{
adc_raw_vol = getmean3( hist_snd_vol );
}
else
{
adc_raw_vol = ( 255 - getmean3( hist_snd_vol ));
}
#else
adc_raw_vol = getmean3( hist_snd_vol );
#endif
break;
case ( ADC_SEL_BATT_TEMP ):
hist_bt_temp[index] = adc_data;
EI();
raw_adc_temperature = getmean3( hist_bt_temp );
if( (( vreg_ctr[ VREG_C_STATUS_1 ] & REG_BIT_GASGAUGE_ERR ) == 0 ) &&
(( system_status.pwr_state == ON ) ||
( system_status.pwr_state == SLEEP )
)
)
{
renge_task_immed_add( BT_temp_update );
}
break;
/* 呼ばれません
case ( ADC_SEL_BATT_DET ):
break;
*/
}
// もっとまともな書き方がありそうだ
if( ADS < ADC_SEL_BATT_DET )
{
ADS += 1; // 次のチャンネル
ADIF = 0; // ←これをしないと、いっこ前のチャンネルのデータの完了で直後に割り込む可能性がある
}
else
{
ADCEN = 0; // 止めてしまう
adc_updated = 1;
index = ( index == 2 ) ? 0 : ( index + 1 ); // ノイズ取りの配列インデックス
}
}
/* ========================================================
tsk_adcと競合することを考慮していません。
======================================================== */
u8 get_adc( u8 ch )
{
u8 temp;
ADMK = 1;
ADIF = 0;
ADCEN = 1;
ADM = 0b00001011; // セレクトモード、昇圧、fCLK/6 ///ここから↓
ADPC = 0x06; // ADCポートのセレクト
ADS = ch;
nop8();
ADCS = 1; // AD開始。 /// ここまで↑ に、1us以上開ける
ADIF = 0;
while( ADIF == 0 ){;}
temp = ADCRH;
ADCEN = 0;
ADMK = 0;
return ( temp );
}