ctr_mcu/trunk/pm.c
N2232 2a6ddf4d26 0.17
・レジスタ書き込みでの強制ボリュームセット実装
・パナソニックのバッテリパラメータをダミーから差し替え(まだ機能してない)
・フルカラーお知らせLEDにきちんと対応
 現行の電源ボード、電源赤がPWMできたりするが実機に合わせてコードも整理
  でないと自動判別後が大変な為
・電源断時にLEDを何となくフェードアウト
・CTR側のI2Cレジスタの実装を修正。220バイト程ROMを節約
 エンバグ怖い
・I2C_mcuのモジュール初期化チェックなどの無駄を少し整理
・TWL I2Cの通信がどうにも間に合わないとき、リトライされてタイミングが悪いと0x00などを返していた。
 リトライ時にも正常に動作するように修正。エンバグ怖い
・廃止enumをちょっと整理
・I2Cレジスタの初期値・リセット時の初期化などを修正
・温度で充電停止周りを実装
・プラットフォームの判定を誤っていた。(0x7Fで読める)
・RCOMPの値の計算を間違えていた。算数もできないのか!
・デバッグコードを抜いた。(pm.c)
・rengeOSのデバッグを有効にしたままだった。I2C_TWLのパフォーマンスが全くでず不具合の嵐
・6秒で電源断を追加。(CTRレジスタから可変) デバッグで耐えられないのでまだ#ifdefでデフォルトを1秒にしてある
・電池無しからアダプタ差したり、アダプタ有りの状態から電池をつないだりで充電したりしなかったり電源はいらなかったり…を修正
・電源LEDが赤になるタイミングと、TWLへの電池残量への通知、NTRへの通知などの閾値がばらばらだったのを修正


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

1018 lines
26 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"
#include "renge.h"
#include "batt_params.h"
#include <fsl.h>
#include "fsl_user.h"
// ========================================================
// ========================================================
u8 raw_adc_temperature;
u8 rcomp;
// float temp_co_up;
// float temp_co_dn;
// 256倍してある
s16 temp_co_up;
s16 temp_co_dn;
BT_VENDER battery_manufacturer = BT_VENDER_NOT_CHECKED;
u8 reg_shadow; // NTR PMIC レジスタミラー
// ========================================================
#ifdef _PMIC_TWL_
u8 blset;
#endif
/* ========================================================
液晶系の電源制御
 ステータスフラグはすぐに立ててしまう。
 不感応時間があるし、
起動失敗であれば電源が落ちる
別のタスクで電源落ちは監視していて、ステータスもクリアする
======================================================== */
// BSR //
err PM_LCD_on( )
{
u8 rv;
PM_VDDLCD_on( );
wait_ms( DELAY_PM_TSS_50B_AND_TCOM );
PM_TCOM_on( );
wait_ms( DELAY_PM_TCOM_TO_VCS );
PM_VCS_on( );
wait_ms( DELAY_PM_VCS_TO_BL );
rv = PM_chk_LDSW( );
if( rv != 0 )
{
// 電源起動エラーなら電源も切れてしまう。ここではケアしない
vreg_ctr[VREG_C_STATUS] |= REG_BIT_LCD_POW;
set_irq( VREG_C_IRQ3, REG_BIT_LCD_ON );
SND_DEPOP_SND_ENABLE;
}
#ifdef _PMIC_TWL_
PM_TEG_LCD_dis( 0 );
blset = ( PM_REG_BIT_BL_U | PM_REG_BIT_BL_L );
#endif
return ( rv );
}
// BSR //
void PM_LCD_off()
{
u8 temp;
SND_DEPOP_SND_MUTE;
// BLついてたら消す
#ifdef _PMIC_TWL_
if( blset != 0 )
#else
if( ( iic_mcu_read_a_byte( IIC_SLA_PMIC, PM_REG_ADRS_BL ) & 0x03 ) != 0 )
#endif
{
u8 tot;
PM_BL_set( REG_BIT_CMD_BL_U_OFF | REG_BIT_CMD_BL_L_OFF );
vreg_ctr[VREG_C_STATUS] &= 0b10011111;
if( (( REG_BIT_BL_U_OFF | REG_BIT_BL_L_OFF ) & ~vreg_ctr[ VREG_C_IRQ_MASK3 ] ) != 0 )
{
vreg_ctr[ VREG_C_IRQ3 ] |= ( ( REG_BIT_BL_U_OFF | REG_BIT_BL_L_OFF ) & ~vreg_ctr[ VREG_C_IRQ_MASK3 ] );
IRQ0_neg;
tot = 0;
while( !IRQ0 && ( ++tot != 0 ) ){;}
IRQ0_ast;
}
vreg_ctr[VREG_C_COMMAND2] &= ~( REG_BIT_CMD_BL_U_OFF | REG_BIT_CMD_BL_L_OFF );
}
#ifdef _PMIC_TWL_
PM_TEG_LCD_dis( 1 );
blset = 0;
#endif
if( iic_mcu_read_a_byte( IIC_SLA_PMIC, PM_REG_ADRS_VDD_LCD ) != 0 )
{
PM_TCOM_VCS_off( );
wait_ms( DELAY_PM_LCD_OFF );
PM_VDDLCD_off( ); // 残ってたの全部止めます。
vreg_ctr[VREG_C_STATUS] &= ~REG_BIT_LCD_POW;
}
set_irq( VREG_C_IRQ3, REG_BIT_LCD_OFF );
}
/* ========================================================
 バックライトの個別on/off
 現状から on/off/維持 のフラグなので面倒
  例えば、BL on/on の状態で、on/onにしろと言われても、on/on割り込みを入れます。
======================================================== */
err PM_BL_set( u8 dat )
{
#ifndef _PMIC_TWL_
u8 blset;
#endif
u8 intset = 0;
// RMWを行う
#ifndef _PMIC_TWL_
// Read
blset = iic_mcu_read_a_byte( IIC_SLA_PMIC, PM_REG_ADRS_BL ) ;
#endif
// Modify
// ue
if(( dat & REG_BIT_CMD_BL_U_ON ) != 0 )
{
blset |= PM_REG_BIT_BL_U;
intset |= REG_BIT_BL_U_ON;
}
else if(( dat & REG_BIT_CMD_BL_U_OFF ) != 0 )
{
blset &= ~PM_REG_BIT_BL_U;
intset |= REG_BIT_BL_U_OFF;
}
// shita
if(( dat & REG_BIT_CMD_BL_L_ON ) != 0 )
{
blset |= PM_REG_BIT_BL_L;
intset |= REG_BIT_BL_L_ON;
}
else if(( dat & REG_BIT_CMD_BL_L_OFF ) != 0 )
{
blset &= ~PM_REG_BIT_BL_L;
intset |= REG_BIT_BL_L_OFF;
}
// SoCがPWMを出すようレジスタをセットしてから遅延が有るため、ステータスを先に
// 更新してしまう。
vreg_ctr[VREG_C_STATUS] = (( vreg_ctr[VREG_C_STATUS] & 0b10011111 )
| ( (( blset << 6 ) | ( blset << 4 )) & 0b01100000 ));
// PMICのBLのビットと、MCUのSTATUSレジスタのビット位置が逆なため入れ替え
{
u8 tot;
if( ( intset & ~vreg_ctr[ VREG_C_IRQ_MASK3 ] ) != 0 )
{
vreg_ctr[ VREG_C_IRQ3 ] |= ( intset & ~vreg_ctr[ VREG_C_IRQ_MASK3 ] );
IRQ0_neg;
tot = 0;
while( !IRQ0 && ( ++tot != 0 ) ){;} // 割り込みを入れ直す
IRQ0_ast;
}
}
// Write
if( blset != 0 ) // BLを付ける場合はウェイトを挟まないとPWMが来ておらず
/// シャットダウンすることがある
{
wait_ms( 16 );
// wait_ms( 84 ); ミツミの1stバグ回避
}
iic_mcu_write_a_byte( IIC_SLA_PMIC, PM_REG_ADRS_BL, blset );
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 );
}
/* ========================================================
↑で、レジスタ書き込みから呼び出される時のため
 I2Cの取り合いの関係でここから呼ぶ
======================================================== */
task_status_immed tski_vcom_set( )
{
PM_LCD_vcom_set( );
return ( ERR_FINISED );
}
/* ========================================================
シーケンスの通り電源を立ち上げてゆきます。
返値 0 最後まで正常に完了した。
1 ショートなどで電源があがりきらなかった
以下のピンは主にここで操作・監視されます。
・POW_CONT1,2 TEG電源のみ
======================================================== */
err PM_sys_pow_on( )
{
#ifdef _PMIC_CTR_
// 電源順次立ち上げ
// PM_reset_ast( ); 不要 PM_LDSW_onまかせ
RESET2_ast;
FCRAM_RST_ast;
GYRO_CS_DISABLE();
PM_LDSW_on( );
wait_ms( 1 );
wait_ms( DELAY_PM_TW_PWUP );
PM_VDD_normMode();
PM_VDD_on( );
// wait_ms( DELAY_PM_TW_PWUP ); // gyro_csを挟むため
wait_ms( 10 );
GYRO_CS_ENABLE();
wait_ms( DELAY_PM_TW_PWUP - 10 );
PM_VDD50A_on( ); // 液晶電源ではなく、ledとかに使うものです
wait_ms( DELAY_PM_TW_PWUP );
// 無事電源が起動したかチェック。
# ifdef _PMIC_CTR_
if( !PM_chk_LDSW() )
{
return ( ERR_ERR ); // reset1はほっといて良い
}
PM_reset_neg();
# else
RESET1_neg;
if( !RESET1_n )
{
RESET1_ast;
return ( ERR_ERR ); // reset1はほっといて良い
}
# endif
FCRAM_RST_neg;
RESET2_neg;
wait_ms( 100 );
#else
// TWL PMIC
u8 temp;
// 電源投入
PM_reset_ast();
RESET2_ast;
FCRAM_RST_ast;
PM_TEG_PWSW = 1;
wait_ms( 160 );
PM_TEG_PWSW = 0;
// 残量確認
temp = 99;
if( temp < 5 )
{
return ( ERR_ERR );
}
vreg_ctr[VREG_C_BT_REMAIN] = temp;
FCRAM_RST_neg;
PM_reset_neg();
RESET2_neg;
wait_ms( 100 );
if( !RESET1_n )
{
// 起動失敗
PM_reset_ast();
RESET2_ast;
FCRAM_RST_ast;
return ( ERR_ERR );
}
#endif
{
// CODEC 不定レジスタ初期化
u8 codec_reg_init[3] = { 0,0,0 };
iic_mcu_write( IIC_SLA_CODEC, CODEC_REG_PM, 3, codec_reg_init );
reg_shadow = 0; // こんなところで...
}
return ( ERR_SUCCESS );
}
/* ========================================================
電源OFFシーケンス
======================================================== */
err PM_sys_pow_off( )
{
#ifdef _PMIC_CTR_
// if( RESET1_n )
if( PM_chk_LDSW() )
{
// 異常時は呼ばない
PM_BL_set( REG_BIT_CMD_BL_U_OFF | REG_BIT_CMD_BL_L_OFF );
PM_LCD_off( ); // TCOM,VCS OFF も消してきます。
wait_ms( 50 + 10 );
PM_reset_ast( );
}
RESET2_ast;
FCRAM_RST_ast;
// PM_off( ); ↓まとめて落としてしまえ
PM_LDSW_off( );
#else
if( RESET1_n )
{
PM_reset_ast();
RESET2_ast;
FCRAM_RST_ast;
PM_TEG_PWSW = 1;
wait_ms( 250 );
wait_ms( 250 );
wait_ms( 250 );
PM_TEG_PWSW = 0;
}
PM_reset_ast();
RESET2_ast;
FCRAM_RST_ast;
#endif
return ( ERR_SUCCESS );
}
/*=========================================================
extDC割り込み
電源OFFから起こす充電の温度監視のためのみ
普段はポーリング(pm)
=========================================================*/
__interrupt void intp4_extdc( )
{
;
}
/*=========================================================
フタ開け閉め割り込み
普段はポーング(misc)
=========================================================*/
__interrupt void intp5_shell( )
{
;
}
/*=========================================================
旧PMICへのコマンド書き込み
=========================================================*/
__interrupt void intp6_PM_irq( )
{
if( system_status.pwr_state == ON )
{
EI();
renge_task_immed_add( ntr_pmic_comm );
}
}
#define _type1_
/* ========================================================
PMICからの割り込みを受けて、NTR PMIC互換レジスタからリード
======================================================== */
task_status_immed ntr_pmic_comm( )
{
u8 reg1_old;
u8 irq_work = 0;
reg1_old = reg_shadow;
reg_shadow = iic_mcu_read_a_byte( IIC_SLA_CODEC, CODEC_REG_PM );
if( iic_mcu_bus_status != ERR_SUCCESS )
{
return ( ERR_FINISED );
}
DI( );
// バックライト 上 ////////////////////////////////////
if( ( ( reg1_old ^ reg_shadow ) & REG_BIT_TWL_REQ_BL_U ) != 0 )
{
if( ( reg_shadow & REG_BIT_TWL_REQ_BL_U ) == 0 ) // 消えた
{
#ifdef _type1_
irq_work = REG_BIT_TWL_BL_U_OFF;
#else
set_irq( VREG_C_IRQ2, REG_BIT_TWL_BL_U_OFF );
#endif
}
else
{
#ifdef _type1_
irq_work = REG_BIT_TWL_BL_U_ON;
#else
set_irq( VREG_C_IRQ2, REG_BIT_TWL_BL_U_ON );
#endif
}
}
// バックライト 下
if( ( ( reg1_old ^ reg_shadow ) & REG_BIT_TWL_REQ_BL_L ) != 0 )
{
if( ( reg_shadow & REG_BIT_TWL_REQ_BL_L ) == 0 ) // 消えた
{
#ifdef _type1_
irq_work |= REG_BIT_TWL_BL_L_OFF;
#else
set_irq( VREG_C_IRQ2, REG_BIT_TWL_BL_L_OFF );
#endif
}
else
{
#ifdef _type1_
irq_work |= REG_BIT_TWL_BL_L_ON;
#else
set_irq( VREG_C_IRQ2, REG_BIT_TWL_BL_L_ON );
#endif
}
}
EI();
vreg_ctr[ VREG_C_STATUS_1 ] = ( vreg_ctr[ VREG_C_STATUS_1 ] & ~0x0C ) | ( reg_shadow & 0x0C ); // TWLバックライト情報のミラー
#ifdef _type1_
irq_work &= ~vreg_ctr[ VREG_C_IRQ_MASK2 ];
// set_irq 相当品
if( irq_work != 0 )
{
u8 tot;
DI();
vreg_ctr[ VREG_C_IRQ2 ] |= irq_work;
EI();
IRQ0_neg; // 一瞬上げてパルスを送り直す
tot = 0;
while( !IRQ0 && ( ++tot != 0 ) ){;} // O.Dなのでちゃんとあがるのを待つ IRQ_mcu がLに縛られてると困る(基板不良)
IRQ0_ast;
}
#endif
#if 0
// バックライト設定
// 勝手に消しておく
/// 今のところさらに細かくは分けないけど…
if( ( reg_shadow & ( REG_BIT_TWL_REQ_BL_U | REG_BIT_TWL_REQ_BL_U ) ) == 0 )
{
vreg_ctr[ VREG_C_COMMAND2 ] = ( REG_BIT_CMD_BL_U_OFF | REG_BIT_CMD_BL_U_OFF );
renge_task_immed_add( tski_PM_BL_set );
}
#endif
// offリクエスト //////////////////////////////////////
if( ( reg_shadow & REG_BIT_TWL_REQ_OFF_REQ ) != 0 )
{
set_irq( VREG_C_IRQ2, REG_BIT_TWL_OFF_REQ );
}
// リセットリクエスト /////////////////////////////////
if( ( reg_shadow & REG_BIT_TWL_REQ_RST_REQ ) != 0 )
{
#if 0
// CODECバグ回避
// リセット単品でなかったら無視
if( ( reg1_old ^ reg_shadow ) == REG_BIT_TWL_REQ_RST_REQ )
#endif
{
set_irq( VREG_C_IRQ2, REG_BIT_TWL_RESET_REQ );
}
}
// バックライトをマスクして書き戻す
EI( );
if( ( reg_shadow & ( REG_BIT_TWL_REQ_OFF_REQ | REG_BIT_TWL_REQ_RST_REQ )) != 0 )
{
reg_shadow &= ~( REG_BIT_TWL_REQ_OFF_REQ | REG_BIT_TWL_REQ_RST_REQ );
iic_mcu_write_a_byte( IIC_SLA_CODEC, CODEC_REG_PM, reg_shadow );
}
return ( ERR_FINISED );
}
/**********************************************************
command2 液晶系
  ラッパー的な物。ERR_SUCCESSしか返さないが…
**********************************************************/
task_status_immed tski_PM_LCD_on()
{
PM_LCD_on();
return( ERR_SUCCESS );
}
task_status_immed tski_PM_LCD_off()
{
PM_LCD_off();
return( ERR_SUCCESS );
}
task_status_immed tski_PM_BL_set()
{
u8 cmd_BL; // ↓volatileとか付けなくても大丈夫みたい
do
{
cmd_BL = vreg_ctr[VREG_C_COMMAND2];
PM_BL_set( cmd_BL ); // マスク済み
}
while( cmd_BL != vreg_ctr[VREG_C_COMMAND2] ); // <- PM_BL_setが更新する
vreg_ctr[VREG_C_COMMAND2] = 0;
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 250
void tsk_batt( )
{
static u8 task_interval = 0;
static u8 temp_zone_charge_enable = 0; // 温度で充電停止する時にヒステリシスを付けるため
static bit pm_extdc_old;
if( task_interval-- != 0 )
{
return;
}
else
{
task_interval = (u8)( INTERVAL_TSK_BATT / SYS_INTERVAL_TICK );
}
// アダプタ? /////////////////////
if( pm_extdc_old != !PM_EXTDC_n )
{
pm_extdc_old = !PM_EXTDC_n;
if( pm_extdc_old )
{
set_bit( 1, vreg_ctr[VREG_C_STATUS], REG_BIT_POW_SUPPLY );
set_irq( VREG_C_IRQ1, REG_BIT_BT_DC_CONNECT );
}
else
{
set_bit( 0, vreg_ctr[VREG_C_STATUS], REG_BIT_POW_SUPPLY );
set_irq( VREG_C_IRQ1, REG_BIT_BT_DC_DISC );
}
}
// 充電 ///////////////////////////
// 温度付きヒステリシス
if(( 86 < raw_adc_temperature )
&& ( raw_adc_temperature < 185 ))
{
temp_zone_charge_enable = 1; // 充電許可
}
else if(( raw_adc_temperature < 70 )
|| ( 189 < raw_adc_temperature ))
{
temp_zone_charge_enable = 0; // 充電禁止
}
else
{
// temp_zone_charge_enable そのまま
}
if(( temp_zone_charge_enable == 1 )
&& ( battery_manufacturer <= BT_VENDER_6 ))
{
#ifndef _MODEL_WM0_
// CHG_ENABLEピンは /WL_RST に配線されているので
BT_CHG_ENABLE(); // 温度範囲OKで充電再開
}
else
{
BT_CHG_DISABLE(); // 温度危険! 充電停止
#endif
}
// 充電 //
// →割り込み。miscの中でよろしくやってくれている。
set_bit( !BT_CHG_n, vreg_ctr[VREG_C_STATUS], REG_BIT_BATT_CHARGE );
LED_CHARGE = !BT_CHG_n ? 1 : 0;
// 電池残量 //
if( system_status.pwr_state == ON )
{
BT_get_left();
}
return;
}
/********************************************************
電池関係の初期化
   ゲージ  | 有り | 無し
  ーーーーーーーーーーーーーーーーーーーーーーー
   電池 有り| 実機 | 実機(ゲージ故障)
  ーーーーーーーーーーーーーーーーーーーーーーー
      無し| 白箱 | TS
        | 実機 |
  ーーーーーーーーーーーーーーーーーーーーーーー
  ゲージ有り、電池無し の白箱/実機判別は、
 電池温度で判定する
***********************************************************/
#define swap_endian_16( x ) (unsigned int)(( x << 8 ) | ( x >> 8 ))
void BT_init( )
{
u8 temp;
u8 origParam[4];
union{
u16 _u16; // ↓でわかるように、little endian です。注意。
struct{
u8 lsb;
u8 msb;
}chars;
}dat_16;
// BT_DET_P = 1; // チャージに時間が掛かるので、先に上げておく
// BT_TEMP_P = 1;
// 電池温度測定(TS,白箱判定も兼ねる) //
while( ADCEN != 0 )
{
NOP();
}
raw_adc_temperature = get_adc( ADC_SEL_BATT_TEMP );
// 電池メーカーの識別
temp = get_adc( ADC_SEL_BATT_DET );
BT_DET_P = 0;
if( temp > 233 )
battery_manufacturer = BT_VENDER_OPEN;
else if( temp > 197 )
battery_manufacturer = BT_VENDER_6;
else if( temp > 158 )
battery_manufacturer = BT_VENDER_PANA;
else if( temp > 123 )
battery_manufacturer = BT_VENDER_4;
else if( temp > 79 )
battery_manufacturer = BT_VENDER_3;
else if( temp > 33 )
battery_manufacturer = BT_VENDER_2;
else if( temp > 5 )
battery_manufacturer = BT_VENDER_1;
else
battery_manufacturer = BT_VENDER_MAXELL;
/*
// -1. なんかおかしい… リセットをかけてみる
dat_16._u16 = swap_endian_16( 0x5400 ); // reset
iic_mcu_write( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_COMMAND, 2, &dat_16 ); // こいつはNACKを返す
*/
/*
// 0. バッテリ残量IC クイックスタート
dat_16._u16 = swap_endian_16( 0x4000 ); // quick start
iic_mcu_write( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_MODE, 2, &dat_16 )
*/
// 1. ロック解除
dat_16._u16 = swap_endian_16( 0x4A57 ); // unlock key
if( iic_mcu_write( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_LOCK, 2, &dat_16 ) == ERR_SUCCESS )
{
vreg_ctr[ VREG_C_STATUS_1 ] &= ~REG_BIT_GASGAUGE_ERR;
// 残量IC有り //
if( battery_manufacturer < BT_VENDER_OPEN )
{
// 電池何かしらあり //
system_status.model = MODEL_JIKKI;
}
else
{
// 電池無し //
if( raw_adc_temperature < 4 )
{
// 白箱 //
system_status.model = MODEL_SHIROBAKO;
}
else
{
// 実機、バッテリ無し
system_status.model = MODEL_UNKNOWN;
}
}
}
else
{
vreg_ctr[ VREG_C_STATUS_1 ] |= REG_BIT_GASGAUGE_ERR;
// 残量IC NACK
if( raw_adc_temperature > 0xF0 )
{
// TS //
system_status.model = MODEL_TS_BOARD;
}
else
{
// 実機、残量IC NACK( バッテリ無しまたは残量IC故障 )
#ifdef _ALLOW_NOBATT_
system_status.model = MODEL_JIKKI;
#else
system_status.model = MODEL_JIKKI_NOBATT; // 起動させない
#endif
}
}
if( system_status.model == MODEL_JIKKI )
{
// wait_ms( 5 + 1 ); I2C_mの初期化時にウェイト入れてるので不要
// 2. 初期パラメータを一時保存
iic_mcu_read( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_RCOMP, 4, origParam );
// 3. 一時的にOCVを変更
dat_16._u16 = swap_endian_16( 0xDA20 ); // マジックナンバー的なもの。メーカー指定
iic_mcu_write( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_OCV, 2, &dat_16 );
// 4. 一時的にRCOMPを変更
dat_16._u16 = swap_endian_16( 0xFF00 );
iic_mcu_write( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_RCOMP, 2, &dat_16 );
// 5.メーカー別パラメータのロード
{
iic_mcu_set_wo_dma( );
iic_mcu_write( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_BT_PARAM, 64, &BT_PARAM[ battery_manufacturer ] );
rcomp = BT_PANA_RCOMP;
temp_co_up = BT_PANA_TEMPCOUP;
temp_co_dn = BT_PANA_TEMPCODN;
/*
todo
*/
}
// 6. 150ms以上待つ
wait_ms( 150 + 15 );
// 7. OCVに「とある値」を書く
dat_16._u16 = swap_endian_16( 0xDA20 );
iic_mcu_write( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_OCV, 2, &dat_16 );
// 8. 150600ms待つ。600msは厳守
wait_ms( 150 + 15 );
// 9. SOCを読む。ベリファイのため。
temp = iic_mcu_read_a_byte( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_SOC );
if( 1 ){
// カスタムモデル書き込み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 );
// おしまい //
BT_temp_update( ); // 温度のtemp。 残量ICに行きます
}
// どの機体で走ってても不可を同じくらいにするため、ADCタスクを登録
// 電池温度監視スタート
raw_adc_temperature = get_adc( ADC_SEL_BATT_TEMP ); // 温度のtemp。
renge_task_immed_add( BT_temp_update );
// PMIC バージョン読み出し
// temp = iic_mcu_read_a_byte( IIC_SLA_PMIC, PM_REG_ADRS_VER );
// vreg_ctr[ VREG_C_PM_INFO ] = temp;
/// デバッグ用は別にまとめた
}
extern u16 _dbg_rcomp;
/* ========================================================
raw_adc_temperatureに入っている値を℃に変換するとともに、
・レジスタにセット
・残量ICにセット
======================================================== */
task_status_immed BT_temp_update( )
{
static u8 count = 0; // たまにしか書きに行かない
static u8 rawdat_old;
static s16 temperature;
s16 newrcomp;
/*
サーミスタ - 10kΩ分圧点の時、
常用温度では分圧比のカーブがほぼリニアで、
村田 T[℃] = 81.48 - 111.97 x ratio
TDK T = 81.406 - 111.81 x ratio
*/
if( rawdat_old != raw_adc_temperature ){
// temperature = 81.45 - 111.9 * raw_adc_temperature/256.0;
// それぞれ256倍してある
temperature = ( 20851 - 112 * raw_adc_temperature + (256/2) ) /256;
vreg_ctr[VREG_C_BT_TEMP] = temperature;
}
// 時々書きにゆく
if( count == 0 )
{
newrcomp = 0;
if( vreg_ctr[VREG_C_BT_TEMP] > 20 )
{
newrcomp = ( ( temperature - 20 ) * temp_co_up )/256;
}
else
{
newrcomp = ( ( temperature - 20 ) * temp_co_dn )/256;
}
newrcomp = rcomp + newrcomp;
newrcomp = swap_endian_16( (u16)newrcomp );
_dbg_rcomp = newrcomp;
if( iic_mcu_write
( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_RCOMP, 2, &newrcomp ) == ERR_SUCCESS )
{
rawdat_old = raw_adc_temperature;
}
}
count += 1;
return ( ERR_SUCCESS );
}
/**********************************************************
電池残量ICから残量を取得し、レジスタに書き込む。
 電池残量ICが無い・故障などの時はとりあえず残量99%とする。
        ↑は status_1で確認可能。電源投入時にチェックしています。
 BT_init()が実行されている必要があります。
**********************************************************/
void BT_get_left(){
static u8 bt_left_state; // バッテリ残量で割り込みのため
volatile static u8 force_set;
volatile static u8 force_data;
if(( vreg_ctr[ VREG_C_STATUS_1 ] & REG_BIT_GASGAUGE_ERR ) == 0 )
{
// 電池残量の取得
static u8 bt_voltage_low_count; // todo どうにかせんとね
u8 temp[2];
// 電池電圧で強制断が優先される
vreg_ctr[ VREG_C_BT_VOLTAGE ] = iic_mcu_read_a_byte( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_VCELL );
if( vreg_ctr[ VREG_C_BT_VOLTAGE ] > ( 3100 / 16 / 1.25 ) )
{
bt_voltage_low_count = 0;
iic_mcu_read( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_SOC, 2, temp );
vreg_ctr[ VREG_C_BT_REMAIN ] = temp[0];
vreg_ctr[ VREG_C_BT_REMAIN_FINE ] = temp[1];
}
else
{
bt_voltage_low_count += 1;
if( bt_voltage_low_count == 3*4 ) // およそ3sec
{
vreg_ctr[ VREG_C_BT_REMAIN ] = 0;
set_irq( VREG_C_IRQ1, REG_BIT_BT_REMAIN );
}
else if( bt_voltage_low_count == 12 + 3 * 5 )
{ // …時間切れ。強制的に切る
system_status.pwr_state = OFF_TRIG;
renge_task_interval_run_force = 1;
}
}
}
else
{
vreg_ctr[ VREG_C_BT_REMAIN ] = 99;
}
// todo
if( force_set )
{
vreg_ctr[ VREG_C_BT_REMAIN ] = force_data;
}
// 残量で割り込み
switch( bt_left_state )
{
case( 0 ): // 前回、バッテリーは十分にあった
if( vreg_ctr[ VREG_C_BT_REMAIN ] <= BATT_TH_LO )
{
bt_left_state = 1; // 突然バッテリ残量が減っても、Lo割り込みを入れる
set_irq( VREG_C_IRQ1, REG_BIT_BT_REMAIN );
}
break;
case( 1 ):
if( vreg_ctr[ VREG_C_BT_REMAIN ] <= BATT_TH_EMPTY )
{
bt_left_state = 2;
set_irq( VREG_C_IRQ1, REG_BIT_BT_REMAIN );
}
else if( vreg_ctr[ VREG_C_BT_REMAIN ] > BATT_TH_LO )
{
bt_left_state = 0;
}
break;
default:
if( vreg_ctr[ VREG_C_BT_REMAIN ] > BATT_TH_EMPTY )
{
bt_left_state = 1;
}
break;
}
// PMIC-NTRに電池残量を教えてあげる
iic_mcu_write_a_byte( IIC_SLA_CODEC, CODEC_REG_BT,
( vreg_ctr[ VREG_C_BT_REMAIN ] <= BATT_TH_LO )? 1 : 0 ); // 1で電池切れ
}