ctr_mcu/trunk/adc.c
fujita_ryohei 889af25286 CTRとTWLのVolをアトミックに更新しなければいけないのを忘れていた
git-svn-id: file:///Volumes/Transfer/gigaleak_20231201/2020-05-23%20-%20ctr.7z%20+%20svn_v1.068.zip/ctr/svn/ctr_mcu@91 013db118-44a6-b54f-8bf7-843cb86687b1
2010-02-01 09:10:13 +00:00

293 lines
7.7 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"
bit adc_updated;
#define INTERVAL_TSK_ADC 16
/* ========================================================
ADC設定と、開始
以下のピンは主にここで操作・監視されます。
・BT_TEMP,_P
・ADIN1
・VOL
関係ありそうですが別のところで管理しています
・PM_BT_DET,_P PM_init
・8tics毎に呼ばれ、チャンネル分取り込むとADCを停止します。
 タスク起動時、レジスタには前回の取り込み値が入っています。
======================================================== */
static const u8 slider_to_codec[64] =
{
127, 125, 124, 123, 121, 120, 119, 117,
116, 115, 113, 112, 111, 109, 108, 107,
105, 104, 103, 101, 100, 99, 98, 96,
95, 94, 92, 91, 90, 88, 87, 86,
84, 83, 82, 80, 79, 78, 76, 75,
74, 72, 71, 70, 69, 67, 66, 65,
63, 62, 61, 59, 58, 57, 55, 54,
53, 51, 50, 49, 47, 46, 45, 44
};
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 )
{
if( system_status.pwr_state == ON )
{
// Tune ///////////////////////////////////////
#if 0
tune 変化では割り込みを入れない
// tune
if( abs( old_tune - vreg_ctr[VREG_TUNE] ) >= 4 )
{
old_tune = vreg_ctr[VREG_TUNE];
vreg_ctr[VREG_C_IRQ0] |= REG_BIT_VR_TUNE_CHANGE;
if( ( vreg_ctr[VREG_C_IRQ_MASK0] & REG_BIT_VR_TUNE_CHANGE ) == 0 )
{
IRQ0_ast;
}
}
#endif
// Volume /////////////////////////////////////
{
static u8 vol_old;
static u8 class_old;
static u8 hysterisis_vol;
u16 class;
// // ヒステリシスを付けておく。上に抜けた場合に閾値を少し下げることにする
// hysterisis_vol = ( vol_old <= vreg_ctr[VREG_C_SND_VOL] )? 2: 0;
// vol_old = vreg_ctr[VREG_C_SND_VOL];
/*
class = ( vreg_ctr[VREG_C_SND_VOL] + hysterisis_vol ) / ( 256 / 8 ); // 32段の割り込み
if( class != class_old )
{
class_old = class;
set_irq( VREG_C_IRQ0, REG_BIT_VR_SNDVOL_CHANGE );
}
*/
// デバイスに伝える
if( sndvol_codec != vreg_ctr[VREG_C_SND_VOL] )
{
sndvol_codec = vreg_ctr[VREG_C_SND_VOL];
// DCPにも伝えておく
iic_mcu_write_a_byte( IIC_SLA_DCP, 0,
slider_to_codec[ sndvol_codec/4 ] );
// codecに伝える
iic_mcu_write_a_byte( IIC_SLA_CODEC, CODEC_REG_VOL,
slider_to_codec[ sndvol_codec/4 ] );
}
}
// TUNE_LED ///////////////////////////////////
// ここで?仕様?
{
switch ( vreg_ctr[VREG_C_LED_TUNE] )
{
case LED_TUNE_ILM_ON:
LED_duty_TUNE = vreg_ctr[VREG_C_LED_BRIGHT];
break;
case LED_TUNE_ILM_SVR:
LED_duty_TUNE = vreg_ctr[VREG_C_TUNE] / 16;
break;
case LED_TUNE_ILM_OFF:
default:
LED_duty_TUNE = 0;
break;
}
}
adc_updated = 0;
}
}
ADCEN = 1;
ADM = 0b00011011; // セレクトモード、章圧、fCLK/6 ///ここから ↓
ADPC = 0x06; // ADCポートのセレクト
ADS = ADC_SEL_TUNE;
NOP();
NOP();
NOP();
NOP();
NOP();
NOP();
NOP();
NOP();
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;
u8 temp;
EI( );
switch ( ADS )
{
/*
case ( ADC_SEL_AMB_BRIT ):
vreg_ctr[ VREG_C_AMBIENT_BRIGHTNESS ] = ADCRH;
break;
*/
case ( ADC_SEL_TUNE ):
hist_tune[index] = ADCRH;
#ifdef _MODEL_WM0_
vreg_ctr[ VREG_C_TUNE ] = 255 - getmean3( hist_tune );
#else
vreg_ctr[ VREG_C_TUNE ] = getmean3( hist_tune );
#endif
break;
case ( ADC_SEL_VOL ):
hist_snd_vol[index] = ADCRH;
vreg_ctr[VREG_C_SND_VOL] = getmean3( hist_snd_vol );
// TWL用レジスタの更新
vreg_twl[ REG_TWL_INT_ADRS_VOL ] = vreg_ctr[VREG_C_SND_VOL] / ( 256 / 32 ); // 8段の割り込み
// 割り込みはHorizonを通してコマンドを発行されるのを待てばよい
break;
case ( ADC_SEL_BATT_TEMP ):
hist_bt_temp[index] = ADCRH;
raw_adc_temperature = getmean3( hist_bt_temp );
renge_task_immed_add( PM_bt_temp_update );
break;
case ( ADC_SEL_BATT_DET ):
// vreg_ctr[ VREG_C_DBG_BATT_DET ] = ADCRH;
// todo
break;
}
// もっとまともな書き方がありそうだ
// if( ADS == ADC_SEL_BATT_DET ){b
if( ADS != ADC_SEL_BATT_TEMP )
{ // 電池判別は電源投入の一回のみ
ADS += 1; // 次のチャンネル
BT_TEMP_P = 1; // 電池温度監視スタート
}
else
{
ADCEN = 0; // 止めてしまう
BT_TEMP_P = 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;
ADCS = 0;
ADM = 0b00100011; // セレクトモード、昇圧、fCLK/6 ///ここから↓
ADPC = 0x06; // ADCポートのセレクト
ADS = ch;
NOP();
NOP();
NOP();
NOP();
NOP();
NOP();
NOP();
NOP();
ADCS = 1; // AD開始。 /// ここまで↑ に、1us以上開ける
ADMK = 0;
while( ADIF == 0 ){;}
temp = ADCRH;
ADCEN = 0;
return ( temp );
}