ctr_mcu/trunk/adc.c
fujita_ryohei 28b5f92e98 加速度割り込み周りで取りこぼすことがあったのを救うコード追加
CTRコーデックに対応?
IRQ_0を確実にかける
I2C(TWL/CTR)の割り込み優先度修正(レジスタ名が悪いと思う)
カメラLED、TWLからの操作を追加
loader、文法ミス修正
自己アップデート後、自己リセットをかける。メーカーの回答待ちのため暫定。(セットは電源が切れ、RTCも初期化される)
RTCの初期値を変更(暫定)
バッテリ残量ICとのやりとりを修正。メーカーの推奨の手順が更新されたため。また、不正になりがちなのでリセットをかけるようにしてみた。I2C_mの2バイト書き込みがひどかったので修正
互換側I2Cれじすたの整理。エンバグ心配



git-svn-id: file:///Volumes/Transfer/gigaleak_20231201/2020-05-23%20-%20ctr.7z%20+%20svn_v1.068.zip/ctr/svn/ctr_mcu@13 013db118-44a6-b54f-8bf7-843cb86687b1
2009-10-27 04:12:36 +00:00

252 lines
6.3 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を停止します。
 タスク起動時、レジスタには前回の取り込み値が入っています。
======================================================== */
void tsk_adc( )
{
static u8 task_interval = 0;
static u8 old_tune;
static u8 sndvol_codec;
static u8 bt_temp_old;
if( ( system_status.pwr_state == ON ) || ( system_status.pwr_state == SLEEP ) )
{
if( adc_updated )
{
if( task_interval != 0 )
{
task_interval -= 1;
return;
}
else
{
task_interval = ( INTERVAL_TSK_ADC / SYS_INTERVAL_TICK );
}
#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;
u8 class;
static u8 direction = 0; // 0:上り方向
u8 comp; // 補正値
if( abs( vol_old - vreg_ctr[VREG_C_SND_VOL] ) > 3 )
{
vol_old = vreg_ctr[VREG_C_SND_VOL];
vreg_twl[ REG_TWL_INT_ADRS_VOL ] = vol_old / ( 256 / 32 );
class = vreg_ctr[VREG_C_SND_VOL] / ( 256 / 8 );
if( class != class_old )
{
class_old = class;
set_irq( VREG_C_IRQ0, REG_BIT_VR_SNDVOL_CHANGE );
}
}
}
// codecに伝える
if( vreg_ctr[VREG_C_SND_VOL] != sndvol_codec )
{
sndvol_codec = ( vreg_ctr[VREG_C_SND_VOL] / 2 + vreg_ctr[VREG_C_SND_VOL] / 4 ) / 2;
#ifndef _CODEC_CTR_
iic_mcu_write_a_byte( IIC_SLA_DCP, 0, sndvol_codec );
#else
iic_mcu_write_a_byte( IIC_SLA_CODEC, REG_ADRS_CODEC_VOL, sndvol_codec );
#endif
}
adc_updated = 0;
}
ADCEN = 1;
ADM = 0b00011011; // セレクトモード、章圧、fCLK/6 ///ここから
ADPC = 0x06; // ADCポートのセレクト
ADS = ADC_SEL_TUNE;
// NOP();
ADCS = 1; // AD開始。 /// ここまでに、1us以上開ける
ADIF = 0;
ADMK = 0;
// TUNE_LED ここかよ!
switch ( vreg_ctr[VREG_C_LED_TUNE] )
{
case ( 1 ): // 点灯
LED_duty_TUNE = vreg_ctr[VREG_C_LED_BRIGHT];
break;
case ( 2 ): //
LED_duty_TUNE = LED_BRIGHT_MAX - vreg_ctr[VREG_C_TUNE];
break;
default: // 消灯
LED_duty_TUNE = 0;
break;
}
}
}
/* ========================================================
 過去つのminでもMAXでもない値を返す
 突発的なノイズを除く。
 根本対策ではないが、これはこれで使い道がある。
======================================================== */
static u8 getmean3( u8 * hist )
{
u8 temp;
if( *hist < *( hist + 1 ) )
{
temp = *hist;
*hist = *( hist + 1 );
*( hist + 1 ) = temp;
}
if( !( *hist > *( hist + 1 ) ) )
{
return *hist;
}
else
{
if( *( hist + 1 ) > *( hist + 2 ) )
{
return *( hist + 1 );
}
else
{
return *( 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_TUNE ):
hist_tune[index] = ADCRH;
vreg_ctr[VREG_C_TUNE] = getmean3( hist_tune );
break;
case ( ADC_SEL_VOL ):
hist_snd_vol[index] = ADCRH;
vreg_ctr[VREG_C_SND_VOL] = getmean3( hist_snd_vol );
break;
case ( ADC_SEL_BATT_TEMP ):
hist_bt_temp[index] = ADCRH;
raw_adc_temperature = getmean3( hist_tune );
renge_task_immed_add( PM_bt_temp_update );
break;
case ( ADC_SEL_BATT_DET ):
// vreg_ctr[ VREG_C_DBG_BATT_DET ] = ADCRH;
break;
}
// もっとまともな書き方がありそうだ
// if( ADS == ADC_SEL_BATT_DET ){
if( ADS != ADC_SEL_BATT_TEMP )
{ // 電池判別は電源投入の一回のみ
ADS += 1; // 次のチャンネル
}
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;
ADCS = 0;
ADM = 0b00100011; // セレクトモード、章圧、fCLK/6 ///ここから
ADPC = 0x06; // ADCポートのセレクト
ADS = ch;
ADCS = 1; // AD開始。 /// ここまでに、1us以上開ける
ADMK = 0;
while( ADIF == 0 )
{;
}
temp = ADCRH;
ADCEN = 0;
return ( temp );
}