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

・レジスタ書き込みでの強制ボリュームセット実装 ・パナソニックのバッテリパラメータをダミーから差し替え(まだ機能してない) ・フルカラーお知らせ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
1018 lines
26 KiB
C
1018 lines
26 KiB
C
/* ========================================================
|
||
対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. 150~600ms待つ。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で電池切れ
|
||
|
||
}
|