ctr_mcu/trunk/pm.c
n2232 02950b0366 泣く泣く手動で、SDK0.14系からマージ
・電源LEDが青でないときに電源断を行うと、次回の起動時に問答無用で強制電源断が発生するのを修正
・モード遷移中にリセットなどでTWL側のMCUレジスタが不整合になるのを強制クリア
・アドレス 0x7F の本体情報の読み出しを、8文字以下で打ち切るとI2Cをがめてしまい、続く数文字分の通信に対して期待しない値を返してしまっていたのを修正(task_misc)
・試遊台対応
・LED_NOTIF_DATAを書くと時計が狂うのを修正


git-svn-id: file:///Volumes/Transfer/gigaleak_20231201/2020-05-23%20-%20ctr.7z%20+%20svn_v1.068.zip/ctr/svn/ctr_mcu@303 013db118-44a6-b54f-8bf7-843cb86687b1
2011-01-20 01:28:40 +00:00

1223 lines
34 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; // アダプタ差したとき、充電するしないに関わらずしばらく点灯させる
u16 bt_volt16;
bit ntr_pm_bt_low_old;
bit BT_CHG_STAT_Change;
// ========================================================
static void BT_model_detect();
static void BT_mgic_quick_start();
static void BT_mgic_init();
// ========================================================
#define swap_endian_16( x ) (unsigned int)(( x << 8 ) | ( x >> 8 ))
// ========================================================
const u8 BT_MANUF_BORDER[] = {
5, 33, 79, 123, 158, 197, 233
};
/* ========================================================
電池の管理
以下のピンは主にここで操作・監視されます。
・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 60
// ↑100だと充電エラー時にうまく点滅しないので
bit temp_zone_charge_disable; // 温度で充電停止する時にヒステリシスを付けるため
void tsk_batt( )
{
static u8 task_interval = 0;
static u8 heikinka_h,heikinka_l;
if( system_status.pwr_state != OFF_TRIG )
{
if( task_interval-- != 0 )
{
return;
}
else
{
task_interval = (u8)( INTERVAL_TSK_BATT / SYS_INTERVAL_TICK );
}
}
// アダプタステータス更新 /////////
pm_chk_adapter();
// 充電 ///////////////////////////
// 温度付きヒステリシス
if(( 75 <= raw_adc_temperature )
&& ( raw_adc_temperature <= 184 ))
{
if( heikinka_h < 40 )
{
heikinka_h++;
}
else
{
temp_zone_charge_disable = false; // 充電許可
}
}
else if(( raw_adc_temperature <= 61 )
|| ( 189 <= raw_adc_temperature ))
{
if( heikinka_l < 40 )
{
heikinka_l++;
}
else
{
temp_zone_charge_disable = true; // 充電禁止
}
}
else
{
// temp_zone_charge_disable そのまま
heikinka_h = 0;
heikinka_l = 0;
}
// WM0ではCHG_ENABLEピンは /WL_RST に配線されており、充電制御しない
if( !temp_zone_charge_disable && bt_chg_ready && !PM_EXTDC_n )
{
BT_CHG_ENABLE(); // 温度範囲OKで充電再開
}
else
{
BT_CHG_DISABLE(); // 温度危険! 充電停止
}
// 充電 //
// →割り込み。
{
static u8 anti_chatter;
if( BT_IN_CHG_n ) // 充電*してない* (論理がわかりづらいな!)
{
anti_chatter = 0;
LED_CHARGE = 0;
}
else
{
if( anti_chatter < 2 ) // 電池無しでアダプタさして、電極をさわさわ
{ // すると充電LEDががさがさするので
anti_chatter++;
}
else
{
LED_CHARGE = 1;
}
}
}
if( chg_led_override != 0 ){ // ↑から見ればわかるが、瞬間(数クロック)消える事がある。気がつく人いるかな…?
chg_led_override -= 1;
LED_CHARGE = 1;
}
// レジスタの充電中ビットはLEDに同期する
set_bit( LED_CHARGE, vreg_ctr[VREG_C_STATUS], REG_BIT_BATT_CHARGE ); // set_bitのみ。
// 割り込みはmiscが引き受ける
// 電池残量 //
if(( system_status.pwr_state != ON_CHECK )&&
( system_status.pwr_state != OFF ))
{
BT_get_left();
}
}
/********************************************************
アダプタの有無チェック
電源off中のアダプタ抜き差しで外から呼ばれるため分離
***********************************************************/
void pm_chk_adapter()
{
static u8 pm_extdc_old;
u8 temp_pm_extdc;
temp_pm_extdc = (u8)!PM_EXTDC_n; // volatileのため
if( pm_extdc_old != temp_pm_extdc )
{
pm_extdc_old = temp_pm_extdc;
if( temp_pm_extdc )
{
// 刺さった
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)( 3000 / INTERVAL_TSK_BATT );
}
else
{
u8 temp_v[2];
// 抜けた
set_bit( 0, vreg_ctr[VREG_C_STATUS], REG_BIT_POW_SUPPLY );
set_irq( VREG_C_IRQ1, REG_BIT_BT_DC_DISC );
chg_led_override = 0;
// 電池残量が1%台で、アダプタ有りの時には本体が起動し、ゲームが動くが
// 1%台に回復する前にアダプタが抜けたとき、割り込みを入れないと期待通りの
// 動作でない。特別対応のためここで
if( iic_mcu_read( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_VCELL, 2, temp_v ) == ERR_SUCCESS )
{
bt_volt16 = ( temp_v[0] * 256 + temp_v[1] );
}
if(( bt_volt16 < V_TH_ZERO ) || ( vreg_ctr[ VREG_C_BT_REMAIN ] == 0 ))
{
set_irq( VREG_C_IRQ1, REG_BIT_BT_REMAIN );
}
}
}
}
/********************************************************
電池関係の初期化
   ゲージ  | 有り     | 無し
  ーーーーーーーーーーーーーーーーーーーーーーー
   電池 有り| 実機     | ?
  ーーーーーーーーーーーーーーーーーーーーーーー
      無し| 白箱     | TS
        | 実機電池無し |
  ーーーーーーーーーーーーーーーーーーーーーーー
  ゲージ有り、電池無し の白箱/実機判別は、
 電池温度で判定する
返値: 電池無し 0xFF
電池変わってない 0
電池変わった 1
***********************************************************/
bit bt_force_update;
void BT_chk()
{
BT_VENDER battery_manufacturer_old;
battery_manufacturer_old = battery_manufacturer;
BT_model_detect();
if( system_status.model != MODEL_JIKKI )
{
bt_chg_ready = false;
return;
// おしまい
}
if(( battery_manufacturer_old != battery_manufacturer ) ||
bt_force_update )
{
bt_force_update = false;
iic_mcu_start( ); // 中で初期化フラグをもってるので呼びまくって良い こんなところに…orz
if( (( battery_manufacturer_old == BT_VENDER_OPEN ) ||
( battery_manufacturer_old == BT_VENDER_NOT_CHECKED )) &&
!system_status.reboot )
{
BT_mgic_quick_start();
}
BT_mgic_init(); // 機種判定も行います
}
bt_chg_ready = true;
renge_task_immed_add( tski_BT_temp_update ); // 電池温度監視スタート
}
void BT_model_detect()
{
u8 temp;
BT_DET_P = 1;
BT_TEMP_P = 1;
wait_ms(1); // 電圧が上がるのに時間が掛かる
raw_adc_temperature = get_adc( ADC_SEL_BATT_TEMP );
temp = get_adc( ADC_SEL_BATT_DET );
BT_DET_P = 0;
system_status.captureBox = 0;
// プラットフォーム判定 //
if( raw_adc_temperature > 0xF0 )
{
// TS //
system_status.model = MODEL_TS_BOARD;
}
else if( raw_adc_temperature < 4 )
{
// 白箱 //
system_status.model = MODEL_SHIROBAKO;
// もしかして:キャプチャボード //
if(( iic_mcu_read_a_byte( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_VERSION ) == 0x01 ) &&
( iic_mcu_result == ERR_OK ))
{
system_status.captureBox = 1;
}
}
else
{
// 実機、残量IC NACK( バッテリ無しまたは残量IC故障 )
system_status.model = MODEL_JIKKI; // バッテリ無しの時は↓で上書きする
}
// 電池メーカーの識別 //
{
BT_VENDER i;
battery_manufacturer = BT_VENDER_OPEN;
for(i=0; i<=7; i++)
{
if( temp <= BT_MANUF_BORDER[ i ] )
{
battery_manufacturer = i;
break;
/*
BT_VENDER_MAXELL; // = 0
BT_VENDER_1;
BT_VENDER_2;
BT_VENDER_3;
BT_VENDER_4;
BT_VENDER_PANA;
BT_VENDER_6;
BT_VENDER_OPEN;
*/
}
}
}
if( ( battery_manufacturer == BT_VENDER_OPEN ) &&
( system_status.model == MODEL_JIKKI ) )
{
system_status.model = MODEL_JIKKI_NOBATT;
}
}
static void BT_mgic_quick_start()
{
union{
u16 _u16; // endian 注意
struct{
u8 lsb;
u8 msb;
}chars;
}dat_16;
wait_ms( 10 ); // MGICの起動に掛かる
dat_16._u16 = swap_endian_16( 0x4000 );
// 0. バッテリ残量IC クイックスタート
iic_mcu_write( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_MODE, 2, &dat_16 );
wait_ms( 150 );
}
static void BT_mgic_init()
{
u8 temp;
u8 origParam[4];
union{
u16 _u16; // endian 注意
struct{
u8 lsb;
u8 msb;
}chars;
}dat_16;
bt_comp = BT_COMP[ battery_manufacturer ]; // バッテリパラメータ変更
/*
// -1. リセットをかけてみる
dat_16._u16 = swap_endian_16( 0x5400 ); // reset
iic_mcu_write( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_COMMAND, 2, &dat_16 ); // こいつはNACKを返す
*/
if( system_status.model != MODEL_JIKKI )
{
return;
// おしまい
}
// 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 )
{
// 残量IC NACK
vreg_ctr[ VREG_C_STATUS_1 ] |= REG_BIT_GASGAUGE_ERR;
return;
// おしまい
}
vreg_ctr[ VREG_C_STATUS_1 ] &= ~REG_BIT_GASGAUGE_ERR;
// wait_ms( 5 + 1 ); 前にウェイト入れてるので不要
// 2. 初期パラメータを一時保存
iic_mcu_read( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_RCOMP, 4, origParam );
// 3. 一時的にOCVを変更
dat_16._u16 = swap_endian_16( BT_OCV[ battery_manufacturer ] ); // マジックナンバー的なもの。メーカー指定
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.メーカー別パラメータのロード
{
// 16バイトごとに区切れとのこと
iic_mcu_set_wo_dma( );
iic_mcu_write( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_BT_PARAM, 16, &BT_PARAM[ battery_manufacturer ] );
iic_mcu_set_wo_dma( );
iic_mcu_write( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_BT_PARAM +16, 16, &BT_PARAM[ battery_manufacturer ][16] );
iic_mcu_set_wo_dma( );
iic_mcu_write( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_BT_PARAM +32, 16, &BT_PARAM[ battery_manufacturer ][32] );
iic_mcu_set_wo_dma( );
iic_mcu_write( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_BT_PARAM +48, 16, &BT_PARAM[ battery_manufacturer ][48] );
}
// 6. 150ms以上待つ
wait_ms( 150 + 15 );
// 7. OCVに「とある値」を書く
dat_16._u16 = swap_endian_16( BT_OCV[ battery_manufacturer ] ); // マジックナンバー的なもの。メーカー指定
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(( BT_VERIFY_L[ battery_manufacturer ] <= temp ) && ( temp <= BT_VERIFY_H[ battery_manufacturer ] ))
{
// カスタムモデル書き込みOK
}else{
// 失敗だったらリトライするのか?
// NOP();
}
// 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 );
}
extern u16 _dbg_rcomp;
/* ========================================================
raw_adc_temperatureに入っている値を℃に変換するとともに、
・レジスタにセット
・残量ICにセット
======================================================== */
task_status_immed tski_BT_temp_update( )
{
static u8 rawdat_old;
static s8 temperature;
s16 newrcomp;
static u8 heikinka;
/*
サーミスタ - 10kΩ分圧点の時、
常用温度では分圧比のカーブがほぼリニアで、
村田 T[℃] = 81.48 - 111.97 x ratio
TDK T = 81.406 - 111.81 x ratio
*/
if( rawdat_old != raw_adc_temperature )
{
if( heikinka < 40 )
{
heikinka++;
}
else
{
heikinka = 0;
rawdat_old = raw_adc_temperature;
// temperature = 81.45 - 111.9 * raw_adc_temperature/256.0;
// それぞれ256倍してある
temperature = (u8)(( 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;
if( newrcomp > 255 )
{
newrcomp = 255;
}
if( newrcomp < 0 )
{
newrcomp = 0;
}
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_chk()が実行されている必要があります。
**********************************************************/
void BT_get_left(){
u8 temp_fuel[2];
static u16 hysteresis;
#ifdef _DEBUG_BT_FUEL_
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 )
{
// TS //
vreg_ctr[ VREG_C_BT_REMAIN ] = 99;
vreg_ctr[ VREG_C_BT_VOLTAGE ] = 200;
}
else if( system_status.model == MODEL_SHIROBAKO )
{
// 白箱 //
// 電池残量
if( iic_mcu_read( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_SOC, 2, temp_fuel ) != ERR_SUCCESS )
{
// エミュレーション機能がおかしい
vreg_ctr[ VREG_C_BT_REMAIN ] = 99;
}
else
{
vreg_ctr[ VREG_C_BT_REMAIN ] = temp_fuel[0];
vreg_ctr[ VREG_C_BT_REMAIN_FINE ] = temp_fuel[1];
}
// 電池電圧
//*
if( iic_mcu_read( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_VCELL, 2, temp_fuel ) == ERR_SUCCESS )
{
vreg_ctr[ VREG_C_BT_VOLTAGE ] = temp_fuel[0];
}
else
//*/
{
vreg_ctr[ VREG_C_BT_VOLTAGE ] = 200;
}
}
else
{
// 実機 //
u8 temp_v[2];
u8 temp_force_fule_left;
// 残量リード
if( iic_mcu_read( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_SOC, 2, temp_fuel ) != ERR_SUCCESS )
{
// 残量ICがNACK …バッテリはずれた
vreg_ctr[ VREG_C_STATUS_1 ] |= REG_BIT_GASGAUGE_ERR;
bt_chg_ready = false;
vreg_ctr[ VREG_C_BT_REMAIN ] = 0;
system_status.force_off = true;
}
else
{
// バッテリパラメータの関係でビットシフトが必要
bt_volt16 = temp_fuel[0] * 256 + temp_fuel[1];
bt_volt16 /= BT_RCOMP_SCALE[ battery_manufacturer ];
temp_fuel[0] = (u8)(( bt_volt16 >> 8 ) & 0xFF);
if( temp_fuel[0] == 0 )
{
// 0%台の時は1.00%に上げ底
// 充電開始後もしばらくは電池残量が減るので
// 0%に到達してしまうことがあるのだ
temp_fuel[0] = 1;
temp_fuel[1] = 0;
}
else
{
temp_fuel[1] = (u8)(bt_volt16 & 0xFF);
}
// 電圧でキャップ
if( iic_mcu_read( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_VCELL, 2, temp_v ) == ERR_SUCCESS )
{
vreg_ctr[ VREG_C_BT_VOLTAGE ] = temp_v[0];
bt_volt16 = ( temp_v[0] * 256 + temp_v[1] );
if( bt_volt16 > V_TH_30 )
{
temp_force_fule_left = 100;
hysteresis = 0;
}
else if( bt_volt16 - hysteresis > V_TH_LO )
{
temp_force_fule_left = 30;
hysteresis = 0;
}
else if( bt_volt16 > V_TH_EMPTY )
{
temp_force_fule_left = BATT_TH_LO; // ここから赤
hysteresis = 500;
}
else if( bt_volt16 > V_TH_ZERO )
{
temp_force_fule_left = BATT_TH_EMPTY;
hysteresis = 500;
}
else if( bt_volt16 > V_TH_FORCE_OFF )
{
temp_force_fule_left = 0;
hysteresis = 500;
}
else
{
system_status.force_off = true;
hysteresis = 500;
}
}
}
// 充電許可(=アダプタも刺さってる)のに充電してない = 充電完了
if( !BT_CHG_Ena_n && BT_IN_CHG_n ){
vreg_ctr[ VREG_C_BT_REMAIN ] = 100;
vreg_ctr[ VREG_C_BT_REMAIN_FINE ] = 0;
}
else
{ // 少ない方にキャップ
if( temp_force_fule_left > temp_fuel[0] )
{
vreg_ctr[ VREG_C_BT_REMAIN ] = temp_fuel[0];
vreg_ctr[ VREG_C_BT_REMAIN_FINE ] = temp_fuel[1];
}
else
{
vreg_ctr[ VREG_C_BT_REMAIN ] = temp_force_fule_left;
vreg_ctr[ VREG_C_BT_REMAIN_FINE ] = 0;
}
}
}
if( system_status.taikendai_nbd )
{
vreg_ctr[ VREG_C_BT_REMAIN ] = 100;
}
}
// twlのレジスタ更新 (先にやらないと割り込みのタイミングがまずいかもしれない)
{
if (vreg_ctr[VREG_C_BT_REMAIN] > 80)
{
vreg_twl[REG_TWL_INT_ADRS_POWER_INFO] = 0x0F;
}
else if (vreg_ctr[VREG_C_BT_REMAIN] > 50)
{
vreg_twl[REG_TWL_INT_ADRS_POWER_INFO] = 0x0B;
}
else if (vreg_ctr[VREG_C_BT_REMAIN] > BATT_TH_LO)
{
vreg_twl[REG_TWL_INT_ADRS_POWER_INFO] = 0x07;
}
else if (( vreg_ctr[ VREG_C_BT_REMAIN ] > BATT_TH_EMPTY )||
!BT_CHG_Ena_n )
{ // アダプタの有無で底上げ
vreg_twl[REG_TWL_INT_ADRS_POWER_INFO] = 0x03;
}
else if (vreg_ctr[VREG_C_BT_REMAIN] > 0)
{
vreg_twl[REG_TWL_INT_ADRS_POWER_INFO] = 0x01;
}
else
{
vreg_twl[REG_TWL_INT_ADRS_POWER_INFO] = 0x00;
}
}
// 残量で割り込み。急激に減ると飛ぶことがある //
{
static u8 bt_remain_old_ctr;
if( bt_remain_old_ctr != vreg_ctr[ VREG_C_BT_REMAIN ] )
// CTRに通知
{
if( (( vreg_ctr[ VREG_C_BT_REMAIN ] <= BATT_TH_LO ) && ( BATT_TH_LO < bt_remain_old_ctr ))||
(( vreg_ctr[ VREG_C_BT_REMAIN ] <= BATT_TH_EMPTY ) && ( BATT_TH_EMPTY < bt_remain_old_ctr ))||
(( vreg_ctr[ VREG_C_BT_REMAIN ] == 0 ) && ( bt_remain_old_ctr != 0 )) )
{
set_irq( VREG_C_IRQ1, REG_BIT_BT_REMAIN );
}
}
bt_remain_old_ctr = vreg_ctr[ VREG_C_BT_REMAIN ];
}
// PMIC-NTRに電池残量を教えてあげる
{
static bit initialized;
static bit flag; // あれstaticでないとコンパイラに怒られる
if( system_status.pwr_state == OFF_TRIG )
{
initialized = false;
}
else
{
flag = (( vreg_ctr[ VREG_C_BT_REMAIN ] <= BATT_TH_LO )? NTR_PM_BT_EMPTY: NTR_PM_BT_ENOUGH ); // 1で電池切れ
if(( ntr_pm_bt_low_old != flag ) || !initialized )
{
initialized = true;
ntr_pm_bt_low_old = flag;
iic_mcu_write_a_byte_codec( CODEC_REG_BT, (u8)flag );
}
}
}
}
/* ========================================================
液晶系の電源制御
 ステータスフラグはすぐに立ててしまう。
 不感応時間があるし、
起動失敗であれば電源が落ちる
別のタスクで電源落ちは監視していて、ステータスもクリアする
======================================================== */
// 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 = (u8)PM_chk_LDSW( );
if( rv != 0 ) // 正常パス
{
// 電源起動エラーなら電源も切れてしまう。ここではケアしない
vreg_ctr[VREG_C_STATUS] |= REG_BIT_LCD_POW;
set_irq( VREG_C_IRQ3, REG_BIT_LCD_ON );
return ( ERR_SUCCESS );
}
return ( ERR_ERR );
}
// BSR //
void PM_LCD_off()
{
// BLついてたら消す
if( ( iic_mcu_read_a_byte( IIC_SLA_PMIC, PM_REG_ADRS_BL ) & 0x03 ) != 0 )
{
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 );
}
if( iic_mcu_read_a_byte( IIC_SLA_PMIC, PM_REG_ADRS_VDD_LCD ) != 0 )
{
PM_TCOM_off();
wait_ms( 1 );
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 )
{
u8 blset;
u8 intset = 0;
// RMWを行う
// Read
blset = iic_mcu_read_a_byte( IIC_SLA_PMIC, PM_REG_ADRS_BL ) ;
// 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 ); // ここでは異常チェック不要
}
/* ========================================================
液晶の対向電圧の設定を行います。
仮想レジスタの内容を送るだけ
======================================================== */
void PM_LCD_vcom_set( )
{
iic_mcu_write_a_byte( IIC_SLA_PMIC, PM_REG_ADRS_POW_DAC1, vreg_ctr[VREG_C_VCOM_T] ); // がっかりなことに、PMICはバースト書き込み不可
iic_mcu_write_a_byte( IIC_SLA_PMIC, PM_REG_ADRS_POW_DAC2, vreg_ctr[VREG_C_VCOM_B] );
return;
}
/* ========================================================
↑で、レジスタ書き込みから呼び出される時のため
 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( )
{
// 電源順次立ち上げ
// PM_reset_ast( ); 不要 PM_LDSW_onまかせ
RESET2_ast;
FCRAM_RST_ast;
GYRO_DISABLE();
PM_LDSW_on( );
wait_ms( 1 + DELAY_PM_TW_PWUP );
PM_VDD_normMode();
PM_VDD_on( );
// wait_ms( DELAY_PM_TW_PWUP ); // GYROを挟むため
wait_ms( 10 );
GYRO_ENABLE();
wait_ms( DELAY_PM_TW_PWUP - 10 );
PM_VDD50A_on( ); // 液晶電源ではなく、ledとかに使うものです
wait_ms( DELAY_PM_TW_PWUP );
// 無事電源が起動したかチェック。
if( !PM_chk_LDSW() )
{
return ( ERR_ERR ); // reset1はほっといて良い
}
PM_reset_neg();
FCRAM_RST_neg;
RESET2_neg;
codec_reg_init(); // CODEC 不定レジスタ初期化
reg_shadow = 0; //  〃 こんなところで...
return ( ERR_SUCCESS );
}
/* ========================================================
電源OFFシーケンス
======================================================== */
void PM_sys_pow_off( )
{
// 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( 20 );
PM_reset_ast();
}
RESET2_ast;
FCRAM_RST_ast;
wait_ms( 20 );
PM_off( );
PM_LDSW_off( );
return;
}
/*=========================================================
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( tski_ntr_pmic_comm );
}
}
#define _type1_
/* ========================================================
PMICからの割り込みを受けて、NTR PMIC互換レジスタからリード
======================================================== */
task_status_immed tski_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_result != 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;
vreg_ctr[ VREG_C_IRQ2 ] |= irq_work;
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_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 );
}
/**********************************************************
 reset2 で CODEC にリセットがかかり、レジスタが不定になるため
**********************************************************/
void codec_reg_init()
{
wait_ms( 100 );
ntr_pm_bt_low_old = ( vreg_ctr[ VREG_C_BT_REMAIN ] <= BATT_TH_LO )? NTR_PM_BT_EMPTY: NTR_PM_BT_ENOUGH; // 1で電池切れ
iic_mcu_write_a_byte_codec( CODEC_REG_BT, (u8)ntr_pm_bt_low_old ); // SoC から書けず
vol_reset();
// renge_task_immed_add( tski_vol_update );
vol_polling = 3;
}