ctr_mcu/trunk/pm.c
N2232 611a0cbf84 戻り値の型が誤っているのを修正 動いているコードを触るなと言う格言もあるが…
無名な列挙型、一通り名前を付けた。VSのメンバ表示の可読を上げたいため。今更。
LED お知らせLED、リピート設定でなくても最終フレームフラグを立てる
(パターンを差し替えるときに使ってほしかったが意味ないかもとのこと)
WiFiLEDの点滅は現状(TWL同等)で良いらしい。
スリープ中だが、masterBrightnessで下げた状態にしてもらうことになりそう。
 うっすらついてるかわかるか程度なら消してしまえばいいのに...
充電停止・再開温度を変更。ただし評価を待ってまたいじられるかもしれない
 電池残量割り込みのデバッグコードを入れた。
 加速度センサが動いていると、強制オフに時間が掛かるとの事でシステムチックタイマを数えてみたが、ジッタは増えるものの、問題無いような気がするし、手元で試しても同じ気がする。条件を確認しよう
 

git-svn-id: file:///Volumes/Transfer/gigaleak_20231201/2020-05-23%20-%20ctr.7z%20+%20svn_v1.068.zip/ctr/svn/ctr_mcu@189 013db118-44a6-b54f-8bf7-843cb86687b1
2010-06-03 08:39:03 +00:00

1065 lines
27 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\renge.h"
#include "batt_params.h"
#include <fsl.h>
#include "fsl_user.h"
// ========================================================
u8 raw_adc_temperature;
BT_VENDER battery_manufacturer = BT_VENDER_NOT_CHECKED;
st_bt_comp bt_comp; // バッテリパラメータ構造体
u8 reg_shadow; // NTR PMIC レジスタミラー
bit bt_chg_ready; // バッテリパラメータ送信済。充電開始許可
u8 chg_led_override; // アダプタ差したとき、充電するしないに関わらずしばらく点灯させる
// ========================================================
#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;
return ( ERR_ERR );
}
#ifdef _PMIC_TWL_
PM_TEG_LCD_dis( 0 );
blset = ( PM_REG_BIT_BL_U | PM_REG_BIT_BL_L );
#endif
return ( ERR_SUCCESS );
}
// BSR //
void PM_LCD_off()
{
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;
}
if( blset != 0 ) // BLを付ける場合はウェイトを挟まないとPWMが来ておらず
// シャットダウンすることがある
{
wait_ms( 16 + 10 );
// wait_ms( 84 ); ミツミの1stバグ回避
}
iic_mcu_write_a_byte( IIC_SLA_PMIC, PM_REG_ADRS_BL, blset );
#if 0
// SoCがPWMを出すようレジスタをセットしてから遅延が有るため、ステータスを先に
// 更新してしまう。
#endif
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;
}
}
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( )
{
// chg_led_override = (u8)( 1000 / INTERVAL_TSK_BATT / SYS_INTERVAL_TICK );
chg_led_override = 4;
}
/*=========================================================
フタ開け閉め割り込み
普段はポーング(misc)
=========================================================*/
__interrupt void intp5_shell( )
{
;
}
/*=========================================================
旧PMICへのコマンド書き込み
=========================================================*/
__interrupt void intp6_PM_irq( )
{
EI();
if( system_status.pwr_state == ON )
{
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_FINISED );
}
task_status_immed tski_PM_LCD_off()
{
PM_LCD_off();
return( ERR_FINISED );
}
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_FINISED );
}
/* ========================================================
電池の管理
以下のピンは主にここで操作・監視されます。
・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 bit temp_zone_charge_enable; // 温度で充電停止する時にヒステリシスを付けるため
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 );
chg_led_override = (u8)( 1000 / INTERVAL_TSK_BATT / SYS_INTERVAL_TICK );
}
else
{
set_bit( 0, vreg_ctr[VREG_C_STATUS], REG_BIT_POW_SUPPLY );
set_irq( VREG_C_IRQ1, REG_BIT_BT_DC_DISC );
}
}
// 充電 ///////////////////////////
// 温度付きヒステリシス
if(( 75 <= raw_adc_temperature )
&& ( raw_adc_temperature <= 184 ))
{
temp_zone_charge_enable = 1; // 充電許可
}
else if(( raw_adc_temperature <= 61 )
|| ( 189 <= raw_adc_temperature ))
{
temp_zone_charge_enable = 0; // 充電禁止
}
else
{
// temp_zone_charge_enable そのまま
}
#ifndef _MODEL_WM0_
// WM0ではCHG_ENABLEピンは /WL_RST に配線されており、充電制御しない
if( temp_zone_charge_enable && bt_chg_ready )
{
BT_CHG_ENABLE(); // 温度範囲OKで充電再開
}
else
{
BT_CHG_DISABLE(); // 温度危険! 充電停止
}
#endif
// 充電 //
// →割り込み。miscの中でよろしくやってくれている。
if( !BT_CHG_n )
{
set_bit( 1, vreg_ctr[VREG_C_STATUS], REG_BIT_BATT_CHARGE );
LED_CHARGE = 1;
}
else
{
set_bit( 0, vreg_ctr[VREG_C_STATUS], REG_BIT_BATT_CHARGE );
LED_CHARGE = 0;
}
if( chg_led_override != 0 ){ // 気がつく人いるかな…?
chg_led_override -= 1;
LED_CHARGE = 1;
}
// 電池残量 //
if( system_status.pwr_state == ON )
{
BT_get_left();
}
}
/********************************************************
電池関係の初期化
   ゲージ  | 有り     | 無し
  ーーーーーーーーーーーーーーーーーーーーーーー
   電池 有り| 実機     | ?
  ーーーーーーーーーーーーーーーーーーーーーーー
      無し| 白箱     | TS
        | 実機電池無し |
  ーーーーーーーーーーーーーーーーーーーーーーー
  ゲージ有り、電池無し の白箱/実機判別は、
 電池温度で判定する
***********************************************************/
#define swap_endian_16( x ) (unsigned int)(( x << 8 ) | ( x >> 8 ))
void BT_chk( )
{
u8 temp;
union{
u16 _u16; // endian 注意
struct{
u8 lsb;
u8 msb;
}chars;
}dat_16;
BT_DET_P = 1;
BT_TEMP_P = 1;
wait_ms(1); // チャージに時間が掛かる
{
BT_VENDER battery_manufacturer_old = battery_manufacturer;
// 電池メーカーの識別
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;
if( battery_manufacturer != battery_manufacturer_old )
{
if( battery_manufacturer < BT_VENDER_OPEN )
{
// バッテリが変わった //
bt_comp = BT_COMP[ battery_manufacturer ]; // バッテリパラメータ変更
wait_ms( 10 );
// 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 );
bt_chg_ready = 1;
}
else
{
// 電池が外された
bt_chg_ready = 0;
}
}
}
// 電池温度監視スタート
renge_task_immed_add( BT_temp_update );
}
void BT_init( )
{
u8 temp;
u8 origParam[4];
union{
u16 _u16; // endian 注意
struct{
u8 lsb;
u8 msb;
}chars;
}dat_16;
// PMIC バージョン読み出し
// temp = iic_mcu_read_a_byte( IIC_SLA_PMIC, PM_REG_ADRS_VER );
// vreg_ctr[ VREG_C_PM_INFO ] = temp;
/// デバッグ用は別にまとめた
/*
// -1. リセットをかけてみる
dat_16._u16 = swap_endian_16( 0x5400 ); // reset
iic_mcu_write( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_COMMAND, 2, &dat_16 ); // こいつはNACKを返す
*/
// 電池温度測定(TS,白箱判定も兼ねる) //
raw_adc_temperature = get_adc( ADC_SEL_BATT_TEMP );
// 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 ] );
}
// 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(( temp >= 0x74 ) && ( temp <= 0x75 ))
{
// カスタムモデル書き込み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に行きます
}
}
extern u16 _dbg_rcomp;
/* ========================================================
raw_adc_temperatureに入っている値を℃に変換するとともに、
・レジスタにセット
・残量ICにセット
======================================================== */
task_status_immed BT_temp_update( )
{
static u8 rawdat_old;
static s8 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 )
{
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] = (u8)temperature;
newrcomp = 0;
if( temperature > 20 )
{
newrcomp = ( ( temperature - 20 ) * bt_comp.temp_co_up )/256;
}
else
{
newrcomp = ( ( temperature - 20 ) * bt_comp.temp_co_dn )/256;
}
newrcomp = bt_comp.rcomp + newrcomp;
newrcomp = 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;
}
else
{
vreg_ctr[ VREG_C_STATUS_1 ] |= REG_BIT_GASGAUGE_ERR;
}
}
return ( ERR_FINISED );
}
/**********************************************************
電池残量ICから残量を取得し、レジスタに書き込む。
 電池残量ICが無い・故障などの時はとりあえず残量99%とする。
        ↑は status_1で確認可能。電源投入時にチェックしています。
 BT_init()が実行されている必要があります。
**********************************************************/
void BT_get_left(){
u8 temp[2];
// 電池残量更新 //
#ifdef _debug_bt_irq_
if( vreg_ctr[ VREG_C_COMMAND3 ] == 'd' )
{
vreg_ctr[ VREG_C_BT_REMAIN ] = vreg_ctr[ VREG_C_DBG01 ];
}
else
#endif
{
if( system_status.model == MODEL_TS_BOARD )
{
vreg_ctr[ VREG_C_BT_REMAIN ] = 99;
}
else
{
if(( vreg_ctr[ VREG_C_STATUS_1 ] & REG_BIT_GASGAUGE_ERR ) == 0 )
{
temp[0] = iic_mcu_read_a_byte( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_VCELL );
if( iic_mcu_bus_status != ERR_SUCCESS )
{
// バッテリ残量が取れなくなった
vreg_ctr[ VREG_C_STATUS_1 ] |= REG_BIT_GASGAUGE_ERR;
bt_chg_ready = 0;
vreg_ctr[ VREG_C_BT_REMAIN ] = 0;
}
else
{
if( temp[0] < ( 3100 / 16 / 1.25 ) )
{
// 電圧が規定値になってしまったので強制off
vreg_ctr[ VREG_C_BT_REMAIN ] = 0;
}
else
{
// 電圧はまだ大丈夫、電池残量との通信もOK
vreg_ctr[ VREG_C_BT_VOLTAGE ] = temp[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];
}
}
}
// もう特に何もすること無いと思う...
}
}
// 残量で割り込み。急激に減ると飛ぶことがある //
{
static u8 bt_remain_old;
if( (( vreg_ctr[ VREG_C_BT_REMAIN ] <= BATT_TH_LO ) && ( BATT_TH_LO < bt_remain_old ))||
(( vreg_ctr[ VREG_C_BT_REMAIN ] <= BATT_TH_EMPTY ) && ( BATT_TH_EMPTY < bt_remain_old ))||
(( vreg_ctr[ VREG_C_BT_REMAIN ] == 0 ) && ( bt_remain_old != 0 )) )
{
set_irq( VREG_C_IRQ1, REG_BIT_BT_REMAIN );
}
if(( vreg_ctr[ VREG_C_BT_REMAIN ] == 0 ) && ( bt_remain_old != 0 ))
{
system_status.cnt_force_off = 1; // 強制電源断フラグ
}
bt_remain_old = vreg_ctr[ VREG_C_BT_REMAIN ];
}
// 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で電池切れ
}
static unsigned long bt_relax_timer;
#define BT_RELAX_TIME_MIN (unsigned long)30
/**********************************************************
 電池がリラックスするのを待つ
・PM_sys_power_offの時
・充電中にアダプタが抜かれたとき
**********************************************************/
void BT_set_relax_timer()
{
// RTCを使うと楽かと思ったがとんでもなかった
bt_relax_timer = (unsigned long)( BT_RELAX_TIME_MIN * 60 * 1000 / SYS_INTERVAL_TICK );
}
u8 BT_is_relaxed()
{
if( bt_relax_timer != 0 )
{
bt_relax_timer -= 1;
return( 0 );
}
else
{
return( 1 );
}
}