mirror of
https://github.com/rvtr/ctr_mcu.git
synced 2025-06-18 16:45:33 -04:00

VolをTWLからも書けるように スライダとの後着優先になる Codecの「書いたVolと違う値にセットされる(MAX?)」バグワークアラウンドのため、ポーリングするように再度変更 TWLからも書けるのと併せ、そのつもりで作っていたかったので修正箇所が多い スライダのレジスタの値を読み出されるのでスライダのアソビを考えてスケーリングするよう変更 テーブル引きのテーブルをいじるのでは対応出来ない ADCのフィルタの誤り。閾値付近でふらふらしてしまっていた。フィルタの意味なし 電池残量0時のデフォルトパターンを設定。 ほぼすっからかんな電池をセットされたときなどでSoCから何も書かれてない状態の時、消灯で不便なため 電源LED autoでホタルにしない用にした。 ホタル消そうか… ファームが壊れ、バックアップからも復帰できないときに赤LEDを ぴぴっ、ぴぴっ と点滅させるように変更 ファームバックアップ後、新ファーム書き込み中のある期間で電源を落とすとバックアップが消える? todo:デバッグコードが残っている MGICにバッテリーパラメータを書くタイミングを変更(パラメータ転送~に時間が掛かるため) 1)電池交換を検出したとき 2)電源を入れようとしたときに万が一電池がすり替わってたとき 電圧で電池残量をキャップする 分解能20mVではあまりよろしい結果が得られなかったのでMGICより下位バイトも取得するように変更 比較部をリファクタリング wait_msを違うモジュールに ROM上のbootブロックに置きたかったため Vol更新コマンド ビットの自動クリアを忘れていた バッテリ残量パラメータ更新 ビットシフトが必要になったので対応 残念なコードに 電源LED赤とカメラLEDがひっくり返っていた VOLテーブルを-10dbに更新 git-svn-id: file:///Volumes/Transfer/gigaleak_20231201/2020-05-23%20-%20ctr.7z%20+%20svn_v1.068.zip/ctr/svn/ctr_mcu@200 013db118-44a6-b54f-8bf7-843cb86687b1
547 lines
13 KiB
C
547 lines
13 KiB
C
/* ========================================================
|
||
藤田@開技
|
||
nintendo
|
||
'09 Apr
|
||
======================================================== */
|
||
#include "incs.h"
|
||
#include "adc.h"
|
||
#include "pm.h"
|
||
|
||
#include "led.h"
|
||
|
||
|
||
//#define _4db_
|
||
//#define _15db_
|
||
#define _10db_
|
||
#include "voltable.h"
|
||
|
||
|
||
// ===================================================== //
|
||
bit adc_updated;
|
||
|
||
|
||
u8 adc_raw_vol;
|
||
u8 adc_raw_dep;
|
||
u8 vol_written_ctr;
|
||
|
||
bit vol_by_twl;
|
||
|
||
|
||
typedef struct filter_work
|
||
{
|
||
u8* value_used;
|
||
s8 diffs; // KIKAN中の偏り具合
|
||
s8 kikan;
|
||
}filter_work;
|
||
|
||
|
||
filter_work work_vr_3d = {
|
||
&vreg_ctr[ VREG_C_TUNE ]
|
||
};
|
||
|
||
|
||
u8 vol_data_ctr;
|
||
u8 vol_data_ctr_tmp;
|
||
filter_work work_vr_vol = {
|
||
&vol_data_ctr_tmp
|
||
};
|
||
|
||
|
||
// ===================================================== //
|
||
extern void nop8();
|
||
static void adc_filter( u8 new_val, filter_work* work );
|
||
static u8 adc_scaling( u8 );
|
||
|
||
|
||
|
||
// ===================================================== //
|
||
#define INTERVAL_TSK_ADC 15
|
||
|
||
|
||
|
||
/* ========================================================
|
||
ADC設定と、開始
|
||
|
||
以下のピンは主にここで操作・監視されます。
|
||
・BT_TEMP,_P
|
||
・ADIN1
|
||
・VOL
|
||
|
||
関係ありそうですが別のところで管理しています
|
||
・PM_BT_DET,_P BT_init
|
||
|
||
・8tics毎に呼ばれ、3チャンネル分取り込むとADCを停止します。
|
||
タスク起動時、レジスタには前回の取り込み値が入っています。
|
||
======================================================== */
|
||
|
||
|
||
|
||
|
||
void tsk_adc( )
|
||
{
|
||
static u8 task_interval = 0;
|
||
static u8 old_tune;
|
||
static u8 sndvol_codec;
|
||
static u8 bt_temp_old;
|
||
|
||
#if 0
|
||
// debug
|
||
{
|
||
static u16 loop;
|
||
static u8 dat_old;
|
||
static bit interval;
|
||
/*
|
||
// VOL書き頻度を半分にする
|
||
interval++;
|
||
if( !interval )
|
||
{
|
||
return;
|
||
}
|
||
*/
|
||
if( system_status.pwr_state == ON )
|
||
{
|
||
loop++;
|
||
if( loop == 499 ){
|
||
// vol_written_ctr = 0;
|
||
}
|
||
else if( loop == 500 ){
|
||
vol_written_ctr = 0;
|
||
loop = 0;
|
||
}
|
||
else
|
||
{
|
||
vol_written_ctr = slider_to_codec[ vol_data_ctr ];
|
||
}
|
||
}
|
||
renge_task_immed_add( tski_vol_update );
|
||
}
|
||
//*/
|
||
#endif
|
||
|
||
renge_task_immed_add( tski_vol_update ); // T = 2ms polling
|
||
|
||
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 /////////////////////////////////////////
|
||
adc_filter( adc_scaling( adc_raw_dep ), &work_vr_3d );
|
||
|
||
// Volume /////////////////////////////////////
|
||
{
|
||
static u8 vol_old;
|
||
|
||
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(( vreg_ctr[ VREG_C_VOL_DIGITAL ] & REG_BIT_VOL_FORCE_REG ) != 0 )
|
||
{
|
||
// レジスタから強制セット
|
||
vol_data_ctr = ( vreg_ctr[ VREG_C_VOL_DIGITAL ] & ~( REG_BIT_VOL_RESET | REG_BIT_VOL_FORCE_REG ) );
|
||
}
|
||
|
||
if( vol_old != vol_data_ctr )
|
||
{
|
||
vol_old = vol_data_ctr;
|
||
vol_by_twl = 0;
|
||
vreg_ctr[ VREG_C_SND_VOL ] = vol_data_ctr; // 64段
|
||
vol_written_ctr = slider_to_codec[ vol_data_ctr ];
|
||
vreg_twl[ REG_TWL_INT_ADRS_VOL ] = vol_data_ctr / 2;
|
||
// renge_task_immed_add( tski_vol_update ); 2ms後でいいでしょう...
|
||
}
|
||
}
|
||
|
||
// バッテリ識別 ///////////////////////////
|
||
/* 呼ばれません */
|
||
}
|
||
}
|
||
|
||
ADCEN = 1;
|
||
ADM = 0b00001011; // セレクトモード、昇圧、fCLK/6 ///ここから ↓
|
||
|
||
ADPC = 0x06; // ADCポートのセレクト
|
||
ADS = ADC_SEL_TUNE;
|
||
nop8();
|
||
ADCS = 1; // AD開始。 /// ここまで ↑ までに1us=8clk以上開ける
|
||
|
||
ADIF = 0;
|
||
ADMK = 0;
|
||
}
|
||
|
||
|
||
|
||
|
||
/* ========================================================
|
||
Volを更新します。
|
||
こんな時に登録されます。
|
||
・ユーザーがVolスライダを動かした
|
||
・Horizonに強制更新を指示された (codecリセット時)
|
||
・TWLアプリがVolをいじった
|
||
======================================================== */
|
||
task_status_immed tski_vol_update()
|
||
{
|
||
u8 vol_scaled;
|
||
u8 temp;
|
||
u8 i;
|
||
|
||
// SPIでかくテスト todo
|
||
// return( ERR_FINISED );
|
||
|
||
if( vol_by_twl )
|
||
{
|
||
temp = slider_to_codec[ vreg_twl[ REG_TWL_INT_ADRS_VOL ] * 2 ];
|
||
}
|
||
else
|
||
{
|
||
temp = vol_written_ctr;
|
||
}
|
||
|
||
// debug todo
|
||
iic_mcu_read_a_byte( IIC_SLA_CODEC, CODEC_REG_VOL );
|
||
|
||
// codecに伝える
|
||
iic_mcu_write_a_byte( IIC_SLA_CODEC, CODEC_REG_VOL, temp );
|
||
|
||
// debug todo
|
||
iic_mcu_read_a_byte( IIC_SLA_CODEC, CODEC_REG_VOL );
|
||
|
||
#ifndef _MODEL_CTR_
|
||
iic_mcu_write_a_byte( IIC_SLA_DCP, 0, slider_to_codec[ ( 255 - vol_data ) / 4 ] );
|
||
#endif
|
||
// set_irq( VREG_C_IRQ0, REG_BIT_VR_SNDVOL_CHANGE ); // 割り込み廃止
|
||
return( ERR_FINISED );
|
||
}
|
||
|
||
|
||
|
||
|
||
/* ========================================================
|
||
過去3つの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 ):
|
||
EI();
|
||
#ifdef _MODEL_WM0_
|
||
adc_raw_dep = 255 - adc_data;
|
||
#else
|
||
adc_raw_dep = adc_data;
|
||
#endif
|
||
break;
|
||
|
||
case ( ADC_SEL_VOL ):
|
||
EI();
|
||
#ifdef _MODEL_CTR_
|
||
if( system_status.model == MODEL_TS_BOARD )
|
||
{
|
||
adc_raw_vol = adc_data;
|
||
}
|
||
else
|
||
{
|
||
adc_raw_vol = 255 - adc_data;
|
||
}
|
||
#else
|
||
adc_raw_vol = adc_data;
|
||
#endif
|
||
|
||
break;
|
||
|
||
case ( ADC_SEL_BATT_TEMP ):
|
||
EI();
|
||
raw_adc_temperature = adc_data;
|
||
#ifdef _DEBUG_BT_TEMP_
|
||
if( vreg_ctr[ VREG_C_COMMAND3 ] == 't' )
|
||
{
|
||
raw_adc_temperature = vreg_ctr[ VREG_C_DBG01 ];
|
||
}
|
||
#endif
|
||
|
||
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( tski_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 );
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
/* ========================================================
|
||
VRの可動範囲を考えてスケーリング
|
||
======================================================== */
|
||
#define ASOBI 10
|
||
static u8 adc_scaling( u8 orig_val )
|
||
{
|
||
u16 temp;
|
||
|
||
if( orig_val > ( 255 - ASOBI ))
|
||
{
|
||
return( 255 );
|
||
}
|
||
|
||
if( orig_val <= ASOBI )
|
||
{
|
||
return( 0 );
|
||
}
|
||
|
||
orig_val -= ASOBI;
|
||
temp = (u16)( orig_val * 256 ) / ( 256 - ( 2 * ASOBI ));
|
||
|
||
return( (u8)( temp & 0xFF ) );
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
/* ========================================================
|
||
似非ヒステリシス V2
|
||
四捨五入的な動きします
|
||
======================================================== */
|
||
#define KIKAN 16
|
||
static void adc_filter( u8 new_val, filter_work *work )
|
||
{
|
||
u8 temp;
|
||
|
||
if( abs( new_val - *( work -> value_used )) > 2 )
|
||
{
|
||
// 大きく離れた
|
||
*( work -> value_used ) = new_val;
|
||
work -> diffs = 0;
|
||
work -> kikan = KIKAN;
|
||
}
|
||
else
|
||
{
|
||
// 近所の値でも、ある期間でいっぱい偏っていたらそっちに寄せる
|
||
if( *( work -> value_used ) < new_val )
|
||
{
|
||
work -> diffs += 1;
|
||
}
|
||
else if( *( work -> value_used ) > new_val )
|
||
{
|
||
work -> diffs -= 1;
|
||
}
|
||
|
||
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;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
#if 0
|
||
// getmean使用 //
|
||
__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( tski_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 ); // ノイズ取りの配列インデックス
|
||
}
|
||
}
|
||
|
||
|
||
|
||
#endif
|