ctr_mcu/branches/sim/adc.c
n2232 6ec42747e1 ●halの初期化を先頭の方に入れた。ファームアップデート時に電源が切れてしまうことがある。
●スタックがあふれる可能性があったので修正
・スタックをあまり使わないように(accero.c, iic_twl.c, pm.c, vreg_ctr_write からのhosu_increment_if_nesessary(), )
・iic_ctrの割り込み順位を下げた(iic_ctr_init)。iic_twl以外は一律最低に。
 mmen,DS互換で暫く波形を見たが問題なさそう。もう暫くエージング継続
・renge task_interval_runの中からtask_immed_runを呼ぶのをやめた。よーく動作確認をすること!(これは戻すかも)

●ext_infoの実装を修正(task_misc.c)
 romは減ったが、スタティックなRAMが増えた。それでもスタックを使うより安全と思う
●MGICの無い機材(白箱など)でも電池周りのHALが動くよう修正(adc.c)

●voltableを.hではなく.cへ移動

●iic_mcu_startのiic_puウェイトを1msに。別に動でもいいのだが。

○電源offからの電源投入チェック、アダプタ有無で異なるパスを通っていたが、出来るだけ共通に。テスト中



git-svn-id: file:///Volumes/Transfer/gigaleak_20231201/2020-05-23%20-%20ctr.7z%20+%20svn_v1.068.zip/ctr/svn/ctr_mcu@363 013db118-44a6-b54f-8bf7-843cb86687b1
2011-08-09 02:41:16 +00:00

445 lines
11 KiB
C
Raw Permalink 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"
#include "vreg_twl.h"
// ===================================================== //
bit adc_updated;
bit vol_changed_by_ctr;
bit vol_changed_by_twl;
u8 vol_old;
u8 adc_raw_vol;
u8 adc_raw_dep;
u8 vol_polling;
u8 vol_level_twl;
extern const u8 slider_to_codec[];
// ===================================================== //
typedef struct filter_work
{
u8* value_used;
s8 diffs; // KIKAN中の偏り具合
s8 kikan;
u8 large_diff_count;
}filter_work;
filter_work work_vr_3d = {
&vreg_ctr[ VREG_C_3D ]
};
u8 vol_data_ctr;
u8 vol_data_ctr_tmp;
filter_work work_vr_vol = {
&vol_data_ctr_tmp
};
// twl の8段階volのリニア値からの境界
/*
twl内の32 -> 8 テーブル
01,4,8,13,18,23,28,31
*/
static const u8 TWL_VOL_BOUNDARY[] = {
1, 4, 8, 13, 18, 23, 28, 31
};
// ===================================================== //
extern void nop8();
static void adc_filter( u8 new_val, filter_work* work );
static u8 adc_scaling( u8 );
static void update_twl_vol( u8 sent_index );
// ===================================================== //
#define INTERVAL_TSK_ADC 15
/* ========================================================
ADC設定と、開始
以下のピンは主にここで操作・監視されます。
・BT_TEMP,_P
・ADIN1
・VOL
関係ありそうですが別のところで管理しています
・PM_BT_DET,_P BT_chk
======================================================== */
void tsk_adc( )
{
if( adc_updated )
{
adc_updated = false;
// 3D /////////////////////////////////////////
vreg_ctr[ VREG_C_3D ] = adc_raw_dep; // 生値
// Volume /////////////////////////////////////
{
vreg_ctr[ VREG_C_VOL_ADC_RAW ] = adc_raw_vol;
adc_filter( adc_scaling( adc_raw_vol ), &work_vr_vol ); // 結果は*work_vr_volから指されるvol_data_ctr 読みにくい...
vol_data_ctr = vol_data_ctr_tmp / 4;
if( vol_old != vol_data_ctr )
{
vol_changed_by_ctr = true;
vol_old = vol_data_ctr;
vol_polling = 3;
// renge_task_immed_add( tski_vol_update ); ↓で登録
}
}
// バッテリ識別 ///////////////////////////
/* 呼ばれません */
}
// 書き忘れがあるといやなのでポーリング orz
if( vol_polling < 5 )
{
renge_task_immed_add( tski_vol_update );
vol_polling = (u8)(200 / SYS_INTERVAL_TICK) + 5; // 5回/sec
}
vol_polling --;
ADCEN = 1;
ADM = bits8(0,0,0,0, 1,0,1,1); // セレクトモード、昇圧、fCLK/6 // ここから ↓
ADPC = 0x06; // ADCポートのセレクト
ADS = ADC_SEL_3D;
nop8();
ADCS = 1; // AD開始。 // ここまで  までに1us=8clk以上開ける
ADIF = 0;
ADMK = 0;
}
void vol_reset()
{
vol_old = vol_data_ctr;
vreg_ctr[ VREG_C_SND_VOL ] = vol_data_ctr; // 64段
}
/* ========================================================
 Volを更新します。
 こんな時に登録されます。
  ・ユーザーがVolスライダを動かした
  ・Horizonに強制更新を指示された codecリセット時
  ・TWLアプリがVolをいじった
======================================================== */
task_status_immed tski_vol_update()
{
static u8 sent_index, sent_index_twl;
static bit last_modifyer_is_twl; // false = ctr
if( !( system_status.pwr_state == ON ) ||
( system_status.pwr_state == SLEEP )){
return( ERR_FINISED );
}
// どの音量にするの? //
if( vol_changed_by_ctr )
{
// スライダ
vol_changed_by_ctr = false;
last_modifyer_is_twl = false;
sent_index = vol_data_ctr;
}
else if( vol_changed_by_twl )
{
// TWLアプリ
vol_changed_by_twl = false;
last_modifyer_is_twl = true;
if( vreg_twl[ REG_TWL_INT_ADRS_VOL ] == 0 )
{
sent_index_twl = 0;
}
else
{
sent_index_twl = vreg_twl[ REG_TWL_INT_ADRS_VOL ] *2 +1;
}
sent_index = sent_index_twl;
}
else
{
// force_sliderを0にしたとき & 書きまくるとき
// スライダかTWLの最後にセットした方をセット
if( last_modifyer_is_twl )
{
sent_index = sent_index_twl;
}
else
{
sent_index = vol_data_ctr;
}
}
// レジスタの更新 //
vreg_ctr[ VREG_C_SND_VOL ] = sent_index;
// twl側更新
update_twl_vol( sent_index );
// codecに伝える
/// 同値でも書く
iic_mcu_write_a_byte_codec( CODEC_REG_VOL, slider_to_codec[ sent_index ] );
// set_irq( VREG_C_IRQ0, REG_BIT_VR_SNDVOL_CHANGE ); // 割り込み廃止
return( ERR_FINISED );
}
static void update_twl_vol( u8 sent_index )
{
// スケーリング
if( sent_index == 0 )
{
vreg_twl[ REG_TWL_INT_ADRS_VOL ] = 0;
}
else if( sent_index <= 4 )
{
vreg_twl[ REG_TWL_INT_ADRS_VOL ] = 2; // 1はミッシングで正解
}
else
{
vreg_twl[ REG_TWL_INT_ADRS_VOL ] = sent_index/2 ;
}
// 8段階のレベル化。 割り込みを入れるのに必要
{
static u8 vol_twl_old;
if( vol_twl_old != vreg_twl[ REG_TWL_INT_ADRS_VOL ] )
{
// 8段レベルに変換
u8 new_level = 31;
u8 i;
vol_twl_old = vreg_twl[ REG_TWL_INT_ADRS_VOL ];
for( i=0; i<=7; i++ )
{
if( vreg_twl[ REG_TWL_INT_ADRS_VOL ] <= TWL_VOL_BOUNDARY[ i ] )
{
new_level = i;
break;
}
}
vol_level_twl = new_level;
}
}
}
/* ========================================================
 自前で次のチャンネル
  一通り終わったら止める
======================================================== */
__interrupt void int_adc( )
{
volatile u8 adc_data = ADCRH;
switch ( ADS )
{
/*
case ( ADC_SEL_AMB_BRIT ): // 環境明るさ
vreg_ctr[ VREG_C_AMBIENT_BRIGHTNESS ] = adc_data;
break;
*/
case ( ADC_SEL_3D ):
EI();
adc_raw_dep = adc_data;
break;
case ( ADC_SEL_VOL ):
EI();
if( system_status.model == MODEL_TS_BOARD )
{
adc_raw_vol = adc_data;
}
else
{
adc_raw_vol = 255 - adc_data;
}
break;
case ( ADC_SEL_BATT_TEMP ):
EI();
if( vreg_ctr[ VREG_C_HAL_OVW_TEMPERATURE ] == 0xFF )
{
raw_adc_temperature = adc_data;
}
else
{
raw_adc_temperature = vreg_ctr[ VREG_C_HAL_OVW_TEMPERATURE ];
}
if(// (( vreg_ctr[ VREG_C_STATUS_1 ] & REG_BIT_MGIC_ERR ) == 0 ) &&
(( system_status.pwr_state == ON ) ||
( system_status.pwr_state == SLEEP )
)
)
{
renge_task_immed_add( tski_BT_temp_update );
}
break;
/* 呼ばれません
case ( ADC_SEL_BATT_DET ):
break;
*/
}
// もっとまともな書き方がありそうだ
if( ADS < ADC_SEL_BATT_DET )
{
ADS += 1; // 次のチャンネル
}
else
{
ADCEN = 0; // 止めてしまう
adc_updated = true;
}
ADIF = 0; // ←これをしないと、いっこ前のチャンネルのデータの完了で直後に割り込む可能性がある
}
/* ========================================================
tsk_adcと競合することを考慮していません。
======================================================== */
u8 get_adc( u8 ch )
{
u8 temp;
ADMK = 1;
ADIF = 0;
ADCEN = 1;
ADM = bits8(0,0,0,0, 1,0,1,1); // セレクトモード、昇圧、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 );
}
/* ========================================================
VRの可動範囲を考えてスケーリング
音量Vol専用 使い回すならそのときどうにかする
======================================================== */
static u8 adc_scaling( u8 orig_val )
{
u16 temp;
if( orig_val <= vreg_ctr[ VREG_C_VOL_CAL_MIN ] )
{
return( 0 );
}
if( orig_val >= vreg_ctr[ VREG_C_VOL_CAL_MAX ] )
{
return( 255 );
}
temp = (u16)(( orig_val - vreg_ctr[ VREG_C_VOL_CAL_MIN ] ) * 256 ) / ( vreg_ctr[ VREG_C_VOL_CAL_MAX ] - vreg_ctr[ VREG_C_VOL_CAL_MIN ] );
if( temp > 255 )
{
temp = 255;
}
return( (u8)( temp & 0xFF ) );
}
/* ========================================================
似非ヒステリシス V2
四捨五入的な動きします
======================================================== */
#define KIKAN 16
static void adc_filter( u8 new_val, filter_work *work )
{
if( abs( new_val - *( work -> value_used )) > 2 )
{
// 大きく離れた
work -> large_diff_count ++;
if( work -> large_diff_count > 16 )
{
*( work -> value_used ) = new_val;
work -> diffs = 0;
work -> kikan = KIKAN;
}
}
else
{
work -> large_diff_count = 0;
// 近所の値でも、ある期間でいっぱい偏っていたらそっちに寄せる
if( *( work -> value_used ) < new_val )
{
work -> diffs ++;
}
else if( *( work -> value_used ) > new_val )
{
work -> diffs --;
}
if( --( work -> kikan ) == 0 )
{
if( ( work -> diffs ) == KIKAN )
// if( ( work -> diffs ) > (s8)( KIKAN * 0.8 ) )
{
*( work -> value_used ) = *( work -> value_used ) + 1;
}
else if( ( work -> diffs ) == ( -1 * KIKAN ) )
// else if( ( work -> diffs ) < (s8)( -1 * KIKAN * 0.8 ) )
{
*( work -> value_used ) = *( work -> value_used ) - 1;
}
work -> diffs = 0;
work -> kikan = KIKAN;
}
}
}