ctr_mcu/trunk/pm.c
fujita_ryohei be17613348 電池温度監視修正(未完)
動作中にPMICが異常検出でOFF/デバッガがリセットかけた の判定修正

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

742 lines
19 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.

/* ========================================================
対PMIC
藤田@開技
nintendo
'08 Dec
======================================================== */
#pragma nop
#include "incs.h"
#include "adc.h"
#include "led.h"
#include "pm.h"
// ========================================================
// -1.45 ,-3.9}
// ========================================================
static const u8 BT_BT_PARAM_PANA[64] = {
0xAD, 0x30, 0xAE, 0x70, 0xB0, 0x00, 0xB3, 0x00,
0xB4, 0x70, 0xB5, 0xA0, 0xB7, 0x80, 0xBA, 0x00,
0xBB, 0x90, 0xBD, 0x00, 0xBE, 0x00, 0xBF, 0xF0,
0xC3, 0x00, 0xC5, 0xC0, 0xC8, 0x00, 0xCA, 0xC0,
0x04, 0x00, 0x12, 0x00, 0x0C, 0x10, 0x24, 0x00,
0x10, 0xD0, 0x1B, 0xF0, 0x0A, 0xF0, 0x08, 0xE0,
0x0C, 0xF0, 0x08, 0xC0, 0x08, 0xB0, 0x07, 0xF0,
0x0B, 0x00, 0x05, 0xD0, 0x02, 0x00, 0x09, 0x00
};
static const unsigned char BT_PANA_RCOMP = 135;
static const float BT_PANA_TEMPCOUP = 0.3;
static const float BT_PANA_TEMPCODN = 0.5;
// ========================================================
u8 raw_adc_temperature;
u8 rcomp;
float temp_co_up;
float temp_co_dn;
#define _TEG_
/* ========================================================
バッテリの認証を行います。
引数 無し
返値 (ERR)ERR_SUCCESS 成功
それ以外 失敗
======================================================== */
err PM_bt_auth( )
{
/*
todo
マキシムなら Dallas-1wire 通信
SHA-1計算
*/
return ( ERR_SUCCESS );
}
/******************************************************//**
PMIC達の初期化
\n 電池メーカー識別
\n 電池残量ICのセット
\n バージョン情報の取得
\n
\n 以下のピンは主にここで操作・監視されます。
\n ・PM_BT_DET,_P
*********************************************************/
#define swap_endian_16( x ) (unsigned int)( x << 8 | x >> 8 )
void PM_init( )
{
u8 temp;
u8 origParam[4];
union{
u16 _u16; // ↓でわかるように、little endian です。注意。
struct{
u8 lsb;
u8 msb;
}chars;
}dat_16;
#if 1
wait_ms( 200 );
// -1. なんかおかしい… リセットをかけてみる
dat_16._u16 = swap_endian_16( 0x5400 ); // reset
iic_mcu_write( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_COMMAND, 2, &dat_16.chars.lsb );
#endif
wait_ms( 200 );
// 0. バッテリ残量IC クイックスタート
dat_16._u16 = swap_endian_16( 0x4000 ); // quick start
if( iic_mcu_write( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_MODE, 2, &dat_16.chars.lsb ) != ERR_SUCCESS )
{
vreg_ctr[ VREG_C_STATUS_X ] |= 0x01;
}
else
{
// 1. ロック解除
dat_16._u16 = swap_endian_16( 0x4057 ); // unlock key
iic_mcu_write( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_LOCK, 2, &dat_16.chars.lsb );
// 2. 初期パラメータを一時保存
iic_mcu_read( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_RCOMP, 4, origParam );
// 3. 一時的にOCVを変更
dat_16._u16 = swap_endian_16( 0xD4C0 ); // マジックナンバー的なもの。メーカー指定
iic_mcu_write( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_OCV, 2, &dat_16.chars.lsb );
// 4. 一時的にRCOMPを変更
dat_16._u16 = swap_endian_16( 0xFF00 );
iic_mcu_write( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_RCOMP, 2, &dat_16.chars.lsb );
// 電池メーカーの識別
BT_DET_P = 1;
temp = ( u8 ) ( get_adc( ADC_SEL_BATT_DET ) >> 6 );
BT_DET_P = 0;
iic_mcu_set_wo_dma( );
// 5.メーカー別パラメータのロード
switch ( temp )
{
// case( BT_VENDER_PANA ):
default:
iic_mcu_write( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_BT_PARAM, 64, BT_BT_PARAM_PANA );
/*
iic_mcu_write( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_BT_PARAM, 16, BT_BT_PARAM_PANA );
iic_mcu_set_wo_dma( );
iic_mcu_write( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_BT_PARAM+16, 16, &BT_BT_PARAM_PANA[16] );
iic_mcu_set_wo_dma( );
iic_mcu_write( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_BT_PARAM+16*2, 16, &BT_BT_PARAM_PANA[32] );
iic_mcu_set_wo_dma( );
iic_mcu_write( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_BT_PARAM+16*3, 16, &BT_BT_PARAM_PANA[48] );
*/
rcomp = BT_PANA_RCOMP;
temp_co_up = BT_PANA_TEMPCOUP;
temp_co_dn = BT_PANA_TEMPCODN;
break;
}
// 6. 150ms以上待つ
wait_ms( 200 );
// 7. OCVに「とある値」を書く
dat_16._u16 = swap_endian_16( 0xD4C0 );
iic_mcu_write( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_OCV, 2, &dat_16.chars.lsb );
// 8. 150600ms待つ。600msは厳守
wait_ms( 200 );
// 9. SOCを読む。ベリファイのため。
temp = iic_mcu_read_a_byte( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_SOC );
if( 0x6D == temp || temp == 0x6E || temp == 0x6F ){
// カスタムモデル書き込みOK
}else{
// 失敗だったらリトライするのか?
}
// 10.元のRCOMPとOCVを書き戻す
iic_mcu_write( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_RCOMP, 4, origParam );
// 11. ロック
dat_16._u16 = swap_endian_16( 0x0000 ); // lock key
iic_mcu_write( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_LOCK, 2, &dat_16.chars.lsb );
// おしまい //
}
// 電池温度測定
BT_TEMP_P = 1; // 電池温度監視スタート
raw_adc_temperature = get_adc( ADC_SEL_BATT_TEMP ); // 温度のtemp。
renge_task_immed_add( PM_bt_temp_update );
// PMIC バージョン読み出し
// temp = iic_mcu_read_a_byte( IIC_SLA_PMIC, PM_REG_ADRS_VER );
// vreg_ctr[ VREG_C_PM_INFO ] = temp;
}
/* ========================================================
raw_adc_temperatureに入っている値を℃に変換するとともに、
・レジスタにセット
・残量ICにセット
todo
======================================================== */
task_status_immed PM_bt_temp_update( )
{
s8 newrcomp;
static u8 temp_old = 0;
static u8 count = 0; // たまにしか書きに行かない
/*
サーミスタ - 10kΩ分圧点の時、
常用温度では分圧比のカーブがほぼリニアで、
村田 T[℃] = 81.48 - 111.97 x ratio
TDK T = 81.406 - 111.81 x ratio
*/
volatile u16 t1 = 63 * 256;
volatile u16 t2 = 224 * raw_adc_temperature;
volatile s16 t3 = ( t1 - t2 ) / 2;
vreg_ctr[VREG_C_BT_TEMP] = ((
( s16 )( ( u16 )( 163 * 256 ) - ( u16 )( 224 * raw_adc_temperature ) ) / 2 )
/ 256 );
// 時々/大きく変化があったら書きにゆく
if( ( abs( vreg_ctr[VREG_C_BT_TEMP] - temp_old ) > 3 ) || ( count == 0 ) )
{
if( ( s8 ) vreg_ctr[VREG_C_BT_TEMP] > 20 )
{
newrcomp = -( ( ( s16 ) vreg_ctr[VREG_C_BT_TEMP] - 20 ) * temp_co_up );
}
else
{
newrcomp = -( ( ( s16 ) vreg_ctr[VREG_C_BT_TEMP] - 20 ) * temp_co_dn );
}
newrcomp += rcomp;
if( iic_mcu_write
( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_RCOMP, 2, &newrcomp ) == ERR_SUCCESS )
{
temp_old = vreg_ctr[VREG_C_BT_TEMP];
}
count += 1;
}
return ( ERR_SUCCESS );
}
/* ========================================================
バックライト周り
======================================================== */
#ifdef _PMIC_TWL_
err PM_LCD_on( )
{
// PM_TEG_LCD_dis( 0 ); // 何もしない
wait_ms( DELAY_PM_TSS_50B_AND_VCOM );
wait_ms( DELAY_PM_VCOM_TO_BL );
vreg_ctr[VREG_C_STATUS] |= REG_BIT_LCD_POW;
return ( PM_chk_LDSW( ) );
}
err PM_LCD_off( )
{
// PM_TEG_LCD_dis( 1 );
wait_ms( 1 + 50 );
PM_VDDLCD_off( ); // 残ってたの全部止めます。
vreg_ctr[VREG_C_STATUS] &= ~REG_BIT_LCD_POW;
return ( ERR_SUCCESS );
}
err PM_BL_on( )
{
wait_ms( 10 );
vreg_ctr[VREG_C_STATUS] |= REG_BIT_BL;
return ( PM_chk_LDSW( ) );
}
err PM_BL_off( )
{
vreg_ctr[VREG_C_STATUS] &= ~REG_BIT_BL;
return ( ERR_SUCCESS );
}
err PM_LCD_vcom_set( )
{
return ( ERR_SUCCESS );
}
task_status_immed tski_vcom_set( )
{
PM_LCD_vcom_set( );
return ( ERR_FINISED );
}
#else
/* ========================================================
↑で、レジスタ書き込みから呼び出される時のため
 I2Cの取り合いの関係でここから呼ぶ
======================================================== */
task_status_immed tski_vcom_set( )
{
PM_LCD_vcom_set( );
return ( ERR_FINISED );
}
/* ========================================================
液晶系の電源制御
 ステータスフラグはすぐに立ててしまう。
 不感応時間があるし、
起動失敗であれば電源が落ちる
別のタスクで電源落ちは監視していて、ステータスもクリアする
======================================================== */
err PM_LCD_on( )
{
PM_VDDLCD_on( );
wait_ms( DELAY_PM_TSS_50B_AND_VCOM );
PM_TCOM_VCS_on( );
wait_ms( DELAY_PM_VCOM_TO_BL );
iic_mcu_write_a_byte( IIC_SLA_PMIC, 0x22, 0x4A ); // バグ持ちPMIC対策
vreg_ctr[VREG_C_STATUS] |= REG_BIT_LCD_POW;
SND_DEPOP = 0; // 1でミュート
return ( PM_chk_LDSW( ) );
}
err PM_LCD_off( )
{
PM_TCOM_VCS_off( );
wait_ms( DELAY_PM_LCD_OFF );
PM_VDDLCD_off( ); // 残ってたの全部止めます。
vreg_ctr[VREG_C_STATUS] &= ~REG_BIT_LCD_POW;
SND_DEPOP = 1;
return ( ERR_SUCCESS );
}
err PM_BL_on( )
{
PM_set_BL( 0x03 );
wait_ms( 10 );
vreg_ctr[VREG_C_STATUS] |= REG_BIT_BL;
return ( PM_chk_LDSW( ) );
}
err PM_BL_off( )
{
PM_set_BL( 0x00 );
vreg_ctr[VREG_C_STATUS] &= ~REG_BIT_BL;
return ( ERR_SUCCESS );
}
/* ========================================================
液晶の対向電圧の設定を行います。
仮想レジスタの内容を送るだけ
======================================================== */
err PM_LCD_vcom_set( )
{
u8 rv;
rv = iic_mcu_write_a_byte( IIC_SLA_PMIC, PM_REG_ADRS_POW_DAC1, vreg_ctr[VREG_C_VCOM_T] ); // がっかりなことに、PMICはバースト書き込み不可
rv |= iic_mcu_write_a_byte( IIC_SLA_PMIC, PM_REG_ADRS_POW_DAC2, vreg_ctr[VREG_C_VCOM_B] );
return ( rv );
}
#endif
/* ========================================================
↑の、I2Cコマンドでの実行の場合の為の、ラッパー的な物
実仕様上は大丈夫だろうけど、同じ関数がキューに2つ以上
乗らないようにしてあるし、ばらばらにしておく。
======================================================== */
task_status_immed tski_PM_LCD_on( )
{
PM_LCD_on( );
return ( ERR_FINISED );
}
task_status_immed tski_PM_BL_on( )
{
PM_BL_on( );
return ( ERR_FINISED );
}
task_status_immed tski_PM_BL_off( )
{
PM_BL_off( );
return ( ERR_FINISED );
}
task_status_immed tski_PM_LCD_off( )
{
PM_LCD_off( );
return ( ERR_FINISED );
}
/* ========================================================
シーケンスの通り電源を立ち上げてゆきます。
返値 0 最後まで正常に完了した。
1 ショートなどで電源があがりきらなかった
以下のピンは主にここで操作・監視されます。
・POW_CONT1,2 TEG電源のみ
======================================================== */
err PM_sys_pow_on( )
{
#ifndef _PMIC_TWL_
u8 temp;
// 電池温度測定
while( ADCEN != 0 )
{;
}
BT_TEMP_P = 1;
vreg_ctr[VREG_C_BT_TEMP] = get_adc( ADC_SEL_BATT_TEMP );
BT_TEMP_P = 0;
PM_bt_temp_update( ); // 温度のtemp。 残量ICに行きます
// 残量チェック
vreg_ctr[VREG_C_BT_REMAIN] = PM_get_batt_left( );
vreg_ctr[VREG_C_BT_REMAIN] = 200;
if( vreg_ctr[VREG_C_BT_REMAIN] < 0 )
{
return ( 1 );
}
// 電源順次立ち上げ
RESET2_ast;
FCRAM_RST_ast;
PM_LDSW_on( );
wait_ms( 1 );
iic_mcu_write_a_byte( IIC_SLA_PMIC, 0x22, 0xCA ); // バグ持ちPMIC対策 OVP解除
wait_ms( DELAY_PM_TW_PWUP );
PM_VDD_on( );
wait_ms( DELAY_PM_TW_PWUP );
PM_VDD50A_on( ); // 液晶電源ではなく、ledとかに使うものです
wait_ms( DELAY_PM_TW_PWUP );
iic_mcu_write_a_byte( IIC_SLA_PMIC, PM_REG_ADRS_POW_SAVE, 0x03 ); // バグ持ちPMIC対策 強制PWM
if( PM_chk_LDSW( ) == 0 )
{
return ( ERR_ERR );
}
PM_reset_neg( );
RESET2_neg;
FCRAM_RST_neg;
return ( ERR_SUCCESS );
#else
// KE3-L で開発
u8 temp;
// 電源投入
RESETs_ast;
FCRAM_RST_ast;
PM_TEG_PWSW = 1;
wait_ms( 160 );
PM_TEG_PWSW = 0;
// 残量確認
temp = PM_get_batt_left( );
temp = 200;
if( temp < ( 255 * 0.03 ) )
{
return ( ERR_ERR );
}
vreg_ctr[VREG_C_BT_REMAIN] = temp;
PM_reset_neg( );
RESET2_neg;
FCRAM_RST_neg;
wait_ms( 100 );
if( !RESET1_n )
{
// 起動失敗
RESETs_ast;
FCRAM_RST_ast;
return ( ERR_ERR );
}
return ( ERR_SUCCESS );
#endif
}
/* ========================================================
電源OFFシーケンス
todo: 電源異常断の場合
======================================================== */
err PM_sys_pow_off( )
{
#ifdef _PMIC_CTR_
PM_BL_off( );
PM_LCD_off( ); // TCOM,VCS OFF も消してきます。
PM_reset_ast( );
RESET2_ast;
FCRAM_RST_ast;
PM_off( );
PM_LDSW_off( );
#else
if( RESET1_n )
{
RESETs_ast;
FCRAM_RST_ast;
PM_TEG_PWSW = 1;
wait_ms( 250 );
wait_ms( 250 );
wait_ms( 250 );
PM_TEG_PWSW = 0;
}
RESETs_ast;
FCRAM_RST_ast;
#endif
return ( ERR_SUCCESS );
}
/* ========================================================
電池の管理
以下のピンは主にここで操作・監視されます。
・PM_BT_AUTH 現状、GPI in
・PM_CHARGE_n CCIC /CHG in
・PM_CHARGE_ERR_n /FLT in
・PM_EXTDC_n /DOK INTP4 in
・PM_CHARGE_EN_n /CEN out
以下の物は関係ありそうですが別のところで主に監視されています。
・LED_Pow R, B, Charge tsk_LED
・BT_TEMP,_P tsk_ADC
PM_EXTDCは割り込みメインにするかも
======================================================== */
#define INTERVAL_TSK_BATT 100
void tsk_batt( )
{
static u8 task_interval = 0;
static u8 charge_hys = 0; // ヒステリシスで上限下限を拡張するとき1
if( task_interval != 0 )
{
task_interval -= 1;
return;
}
else
{
task_interval = ( INTERVAL_TSK_BATT / SYS_INTERVAL_TICK );
}
// 電源周りのステータスが変化? ///
set_bit( PM_EXTDC, vreg_ctr[VREG_C_STATUS], REG_BIT_POW_SUPPLY );
set_bit( !BT_CHG_n, vreg_ctr[VREG_C_STATUS], REG_BIT_BATT_CHARGE );
// →割り込み。miscの中でよろしくやってくれている。
// 充電 ///////////////////////////
// 温度付きヒステリシス
if( ( ( 345 / 4 ) < vreg_ctr[VREG_C_BT_TEMP] ) && ( vreg_ctr[VREG_C_BT_TEMP] < ( 739 / 4 ) ) )
{
charge_hys = 1;
}
if( ( ( ( 345 - 65 ) / 4 ) < vreg_ctr[VREG_C_BT_TEMP] )
&& ( vreg_ctr[VREG_C_BT_TEMP] < ( ( 739 + 18 ) / 4 ) ) )
{
charge_hys = 0;
}
if( ( ( charge_hys == 1 )
&& ( ( ( 345 - 65 ) / 4 ) < vreg_ctr[VREG_C_BT_TEMP] )
&& ( vreg_ctr[VREG_C_BT_TEMP] < ( ( 739 + 18 ) / 4 ) ) )
||
( ( charge_hys == 0 )
&& ( ( 345 / 4 ) < vreg_ctr[VREG_C_BT_TEMP] )
&& ( vreg_ctr[VREG_C_BT_TEMP] < ( 739 / 4 ) ) ) )
{
BT_CHG_EN = 1;
}
else
{
BT_CHG_EN = 0;
}
// 充電LED
LED_duty_CHARGE = !BT_CHG_n ? vreg_ctr[VREG_C_LED_BRIGHT] : 0;
if(( vreg_ctr[ VREG_C_STATUS_X ] & 0x01 ) == 0 )
{
// 電池残量の取得
{
u8 temp;
temp = PM_get_batt_left();
vreg_ctr[ VREG_C_BT_REMAIN ] = temp;
// todo 閾値を超えたら割り込み
}
}
else
{
vreg_ctr[ VREG_C_BT_REMAIN ] = 0xFF;
}
vreg_ctr[ VREG_C_FREE0 ] = vreg_ctr[ VREG_C_BT_REMAIN ];
vreg_ctr[ VREG_C_FREE1 ] = iic_mcu_read_a_byte( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_VCELL );
return;
}
/*=========================================================
extDC割り込み
電源OFFから起こす充電の温度監視のためのみ
普段はポーリング(pm)
=========================================================*/
__interrupt void intp4_extdc( )
{
;
}
/*=========================================================
フタ開け閉め割り込み
普段はポーング(misc)
=========================================================*/
__interrupt void intp5_shell( )
{
;
}
/*=========================================================
旧PMICへのコマンド書き込み
=========================================================*/
__interrupt void intp6_PM_irq( )
{
renge_task_immed_add( ntr_pmic_comm );
}
/* ========================================================
PMICからの割り込みを受けて、NTRPMIC互換レジスタからリード
======================================================== */
task_status_immed ntr_pmic_comm( )
{
#ifdef _CODEC_CTR_
static u8 reg_shadow;
u8 reg_old;
reg_old = reg_shadow; // BL関係
reg_shadow = iic_mcu_read_a_byte( IIC_SLA_CODEC, CODEC_REG_PMCOMP );
DI( );
// offリクエスト
if( ( reg_shadow & REG_BIT_TWL_REQ_OFF_REQ ) != 0 )
{
set_irq( VREG_C_IRQ3, REG_BIT_TWL_OFF_REQ );
vreg_ctr[VREG_C_IRQ3] |= REG_BIT_TWL_OFF_REQ;
if( ( vreg_ctr[VREG_C_IRQ_MASK3] & REG_BIT_TWL_OFF_REQ ) == 0 )
{
IRQ0_ast;
}
}
// リセットリクエスト
if( ( reg_shadow & REG_BIT_TWL_REQ_RST_REQ ) != 0 )
{
vreg_ctr[VREG_C_IRQ3] |= REG_BIT_TWL_RESET_REQ;
if( ( vreg_ctr[VREG_C_IRQ_MASK3] & REG_BIT_TWL_RESET_REQ ) == 0 )
{
IRQ0_ast;
}
}
// バックライトが...
if( ( ( reg_old ^ reg_shadow ) & ~( REG_BIT_TWL_REQ_BL ) ) != 0 )
{
if( ( reg_shadow & ( REG_BIT_TWL_REQ_BL ) ) == 0x00 )
{
// 両方消された
vreg_ctr[VREG_C_IRQ3] |= REG_BIT_TWL_BL_OFF;
if( ( vreg_ctr[VREG_C_IRQ_MASK3] & REG_BIT_TWL_BL_OFF ) == 0 )
{
IRQ0_ast;
}
}
else if( ( reg_shadow & ( REG_BIT_TWL_REQ_BL ) ) == ( REG_BIT_TWL_REQ_BL ) )
{
// 両方ついた
vreg_ctr[VREG_C_IRQ3] |= REG_BIT_TWL_BL_ON;
if( ( vreg_ctr[VREG_C_IRQ_MASK3] & REG_BIT_TWL_BL_ON ) == 0 )
{
IRQ0_ast;
}
}
}
EI( );
reg_shadow &= ~( REG_BIT_TWL_REQ_BL ); // BLだけマスクして、クリアの準備
iic_mcu_write_a_byte( IIC_SLA_CODEC, CODEC_REG_PMCOMP, reg_shadow );
#endif
return ( ERR_FINISED );
}