ctr_mcu/trunk/pm.c
fujita_ryohei 604432135f V0.25的な物。 自己アップデータの確認で一時的に巻き戻したいため。
git-svn-id: file:///Volumes/Transfer/gigaleak_20231201/2020-05-23%20-%20ctr.7z%20+%20svn_v1.068.zip/ctr/svn/ctr_mcu@6 013db118-44a6-b54f-8bf7-843cb86687b1
2009-09-02 10:35:20 +00:00

652 lines
16 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_TWL2 I2C通信
藤田@開技
nintendo
'08 Dec
======================================================== */
#pragma nop
#include "incs_loader.h"
#include "adc.h"
#include "led.h"
#include "pm.h"
// ========================================================
#define BT_GAUGE_UNLOCK_ADRS 0x3E
#define BT_BT_PARAM_ADRS 0x40
#define BT_BT_PARAM_PANA_RCOMP_ADRS 0x0C
// -1.45 ,-3.9}
// ========================================================
static const u8 BT_BT_PARAM_PANA[64] = {
0xEA, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F };
#define BT_PANA_RCOMP 158
u16 BT_PANA_TEMPCOUP = 1.45*8;
u16 BT_PANA_TEMPCODN = 3.90*8;
// ========================================================
u16 raw_adc_temperature;
u8 starting_rcomp;
u16 temp_co_up;
u16 temp_co_dn;
#define _TEG_
/* ========================================================
バッテリの認証を行います。
引数 無し
返値 (ERR)ERR_SUCCESS 成功
それ以外 失敗
======================================================== */
err PM_bt_auth(){
/*
todo
マキシムなら Dallas-1wire 通信
SHA-1計算
*/
return( ERR_SUCCESS );
}
/* ========================================================
バッテリ固有のパラメータをセット
 ・64バイトのパラメータを直接ROM領域においておきたかったのだが、
  なんと、DMAがROMRAM領域からしか持ってこられないので
  ランタイムルーチンにスタックにコピーしてもらう orz
・スタックが不安なので、ベンダの数だけ関数を作る
引数 無し
返値 無し
======================================================== */
static void BT_set_batt_vend1(){
u8 dat[2];
iic_mcu_set_wo_dma();
iic_mcu_write( IIC_SLA_BT_GAUGE,
BT_BT_PARAM_ADRS,
sizeof( BT_BT_PARAM_PANA ),
BT_BT_PARAM_PANA
);
iic_mcu_read( IIC_SLA_BT_GAUGE,
BT_GAUGE_REG_OCV,
2,
dat
);
/*
ベリファイしなさいと書いてあるが意味がわからないです
todo あとで
The host must then verify that the model was written properly to the device. The MAX17040 does not allow the
user to read the model directly. In order to verify the model, the host should write the maximum OCV point from
the model to the OCV register (memory location 0x0Eh) and verify that the SOC register (memory location 0x04)
matches the desired SOC value from the model. Before updating the OCV register, the host should read the OCV
register, so that the original value can be rewritten to the device after the model is verified.
//Read Original OCV Register
START
Send Slave Address (0x6Ch)
Send Memory Location (0x0Eh)
RESTART
Send Slave Address (0x6Dh)
Send Memory Location (0x0Eh)
Read Data Byte OriginalOCV1
Read Data Byte OriginalOCV2
STOP
*/
iic_mcu_read( IIC_SLA_BT_GAUGE,
BT_GAUGE_REG_OCV,
2,
dat
);
/*
//Write OCV Register
START
Send Slave Address (0x6Ch)
Send Memory Location (0x0Eh)
Send Data Byte (0xh)
Send Data Byte (0xh)
STOP
*/
/*
iic_mcu_write( IIC_SLA_BT_GAUGE,
BT_GAUGE_REG_OCV,
2,
??
);
*/
/*
//Read SOC Register
START
Send Slave Address (0x6Ch)
Send Memory Location (0x04h)
RESTART
Send Slave Address (0x6Dh)
Send Memory Location (0x04h)
Read Data Byte SOC1
Read Data Byte SOC2
STOP
*/
iic_mcu_read( IIC_SLA_BT_GAUGE,
BT_GAUGE_REG_SOC,
2,
dat
);
/*
//Compare value
//Write OCV Register back to original
START
Send Slave Address (0x6Ch)
Send Memory Location (0x0Eh)
Send Data Byte (OriginalOCV1)
Send Data Byte (OriginalOCV2)
STOP
*/
iic_mcu_write( IIC_SLA_BT_GAUGE,
BT_GAUGE_REG_OCV,
2,
dat
);
/*
To lock the model the host software must write 0x00h to memory location 0x3Eh and 0x00h to memory location
0x3Fh.
//Lock Model Access
START
Send Slave Address (0x6Ch)
Send Memory Location (0x3Eh)
Send Data Byte (0x00h)
Send Data Byte (0x00h)
STOP
*/
dat[0] = dat[1] = 0;
iic_mcu_write( IIC_SLA_BT_GAUGE,
BT_GAUGE_REG_LOCK,
2,
dat
);
starting_rcomp = BT_PANA_RCOMP;
temp_co_up = BT_PANA_TEMPCOUP;
temp_co_dn = BT_PANA_TEMPCODN;
return;
}
/* ========================================================
PMICにリセットコマンドを送る
電池接続時に一回だけ
======================================================== */
err PM_reset(){
iic_mcu_start();
return( iic_mcu_write_a_byte( IIC_SLA_PMIC, PM_REG_ADRS_CONT, 0x00 ) );
}
/* ========================================================
PMIC達の初期化
電池メーカー識別
電池残量ICのセット
バージョン情報の取得
以下のピンは主にここで操作・監視されます。
・PM_BT_DET,_P
======================================================== */
void PM_init(){
u8 temp;
u8 result;
u8 BT_GAUGE_UNLOCK_KEY[2] = { 0x4A, 0x57 };
u8 BT_GAUGE_QUICK_START[2] = { 0x40, 0x00 };
// バッテリ残量ICクイックスタート
iic_mcu_write( IIC_SLA_BT_GAUGE,
BT_GAUGE_REG_MODE,
2,
BT_GAUGE_QUICK_START[0] );
// 電池固有パラメータの書き込み下準備
iic_mcu_write( IIC_SLA_BT_GAUGE,
BT_GAUGE_UNLOCK_ADRS,
sizeof( BT_GAUGE_UNLOCK_KEY ),
BT_GAUGE_UNLOCK_KEY );
// 電池メーカーの判別とセット
BT_DET_P = 1;
temp = (u8)( get_adc( ADC_SEL_BATT_DET ) >> 6 );
BT_DET_P = 0;
switch( temp ){
// case( BT_VENDER_PANA ):
default:
BT_set_batt_vend1();
break;
}
// 電池温度測定
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;
/*
LCD DACの値のセット
*/
}
/* ========================================================
raw_adc_temperatureに入っている値を℃に変換するとともに、
・レジスタにセット
・残量ICにセット
======================================================== */
task_status_immed PM_bt_temp_update(){
u16 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
*/
vreg_ctr[ VREG_C_BT_TEMP ] = (u8)( (s16)(( 163 - ( 224 * ( raw_adc_temperature )) ) / 2 ) >> 8 );
// 時々/大きく変化があったら書きにゆく
if(( abs(vreg_ctr[ VREG_C_BT_TEMP ] - temp_old ) > 3 )
|| ( count == 0 )){
count += 1;
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 += starting_rcomp;
/*
If Temperature > 20 Then
NewRCOMP = StartingRCOMP + ((Temperature - 20) * TempCoUp)
ElseIf Temp < 20 Then
NewRCOMP = StartingRCOMP + ((Temperature - 20) * TempCoDown)
Else
NewRCOMP = StartingRCOMP
End If
*/
return( iic_mcu_write( IIC_SLA_BT_GAUGE, BT_BT_PARAM_PANA_RCOMP_ADRS, 2, newrcomp ) );
}
return( ERR_SUCCESS );
}
/* ========================================================
バックライト周り
======================================================== */
#ifdef _PMIC_TWL_
err PM_LCD_on(){
PM_TEG_LCD_OFF = 0;
return( PM_chk_LDSW() );
}
err PM_BL_on(){ return( PM_chk_LDSW() ); }
err PM_BL_off(){ return( PM_chk_LDSW() ); }
err PM_LCD_off(){
PM_TEG_LCD_OFF = 1;
return( PM_chk_LDSW() );
}
err PM_LCD_vcom_set(){
return( ERR_SUCCESS );
}
task_status_immed tski_vcom_set(){
PM_LCD_vcom_set();
return( ERR_FINISED );
}
#else
/* ========================================================
液晶の対向電圧の設定を行います。
仮想レジスタの内容を送るだけ
======================================================== */
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 );
}
/* ========================================================
↑で、レジスタ書き込みから呼び出される時のため
 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 );
PM_TCOM_VCS_on();
return( PM_chk_LDSW() );
}
err PM_BL_on(){
PM_set_BL( 0x03 );
wait_ms( 10 );
return( PM_chk_LDSW() );
}
err PM_BL_off(){
PM_set_BL( 0x00 );
return( ERR_SUCCESS );
}
err PM_LCD_off(){
PM_TCOM_VCS_off();
wait_ms( 1 + 50 );
PM_VDDLCD_off(); // 残ってたの全部止めます。
return( ERR_SUCCESS );
}
#endif
/* ========================================================
シーケンスの通り電源を立ち上げてゆきます。
返値 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;
temp = vreg_ctr[ VREG_C_BT_TEMP ];
PM_set_batt_temp( temp ); // 温度のtemp。 残量ICに行きます
// 残量チェック
if( PM_get_batt_left() < 0 ){
return( 1 );
}
// 電源順次立ち上げ
PM_LDSW_on();
wait_ms( DELAY_PM_TW_PWUP );
PM_VDD_on();
wait_ms( DELAY_PM_TW_PWUP );
PM_VDD50A_on();
wait_ms( DELAY_PM_TW_PWUP );
if( PM_chk_LDSW() == 0 ){
return( ERR_ERR );
}
PM_reset_neg();
RESET2_ngt;
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;
RESET1_ngt;
RESET2_ngt;
FCRAM_RST_ngt;
wait_ms( 100 );
if( !RESET1_n ){
// 起動失敗
RESETs_ast;
FCRAM_RST_ast;
return( ERR_ERR );
}
return( ERR_SUCCESS );
#endif
}
/* ========================================================
電源OFFシーケンス
======================================================== */
err PM_sys_pow_off(){
#ifdef _PMIC_CTR_
RSTB
TCOM,VCS OFF
(1ms)
(50ms)
->PM LCD系電源OFF
PM_LCD_off();
RST1,2,fcramアサート
->OFF
PM_off();
OFF
PM_LDSW_off();
#else
wait_ms( 50 );
if( RESET1_n ){ // 異常終了から来た場合
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 );
}
/* ========================================================
スリープシーケンス
======================================================== */
err to_sleep(){
PM_LCD_off();
return 0;
}
/* ========================================================
電池の管理
以下のピンは主にここで操作・監視されます。
・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は割り込みメインにするかも
======================================================== */
task_interval tsk_batt(){
static u8 bt_stat = 0;
static u8 charge_hys = 0; // ヒステリシスで上限下限を拡張するとき1
// 電源周りのステータスが変化?
set_bit( PM_EXTDC, vreg_ctr[ VREG_C_STATUS ], REG_BIT_POW_SUPPLY );
set_bit( !BT_CHG_ERR_n, vreg_ctr[ VREG_C_STATUS ], REG_BIT_BATT_CHARGE_ERR );
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;
return( 50 );
}
/*=========================================================
extDC割り込み
電源OFFから起こす充電の温度監視のためのみ
普段はポーリング(pm)
=========================================================*/
__interrupt void intp4_extdc(){
;
}
/*=========================================================
フタ開け閉め割り込み
電源OFFから起こす充電の温度監視のためのみ
普段はポーング(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();
if(( reg_shadow & ( 1 << 6 )) != 0 ){
// offリクエスト
vreg_ctr[ VREG_C_IRQ1 ] |= REG_BIT_TWL_OFF_REQ;
IRQ0_ast;
}
if(( reg_shadow & ( 1 << 0 )) != 0 ){
// リセットリクエスト
vreg_ctr[ VREG_C_IRQ1 ] |= REG_BIT_TWL_RESET_REQ;
IRQ0_ast;
}
if( (( reg_old ^ reg_shadow ) & ~( 0x03 << 2 )) != 0 ){
if(( reg_shadow & ( 0x03 << 2 )) == 0x00 ){
// バックライトが両方消された
vreg_ctr[ VREG_C_IRQ1 ] |= REG_BIT_STAT_CHANGE;
vreg_ctr[ VREG_C_STATUS ] &= ~0x01;
IRQ0_ast;
}else if(( reg_shadow & ( 0x03 << 2 )) == ( 0x03 << 2 )){
// バックライトが両方ついた
vreg_ctr[ VREG_C_IRQ1 ] |= REG_BIT_STAT_CHANGE;
vreg_ctr[ VREG_C_STATUS ] |= 0x01;
IRQ0_ast;
}
}
EI();
reg_shadow &= ~( 0x03 << 3 ); // BLだけマスクして、クリアの準備
iic_mcu_write_a_byte( IIC_SLA_CODEC, CODEC_REG_PMCOMP, reg_shadow );
#endif
return( ERR_FINISED );
}