ctr_mcu/branches/1.05(sdk_0_12)/pm.c

1128 lines
32 KiB
C
Raw Permalink 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; // アダプタ差したとき、充電するしないに関わらずしばらく点灯させる
// ========================================================
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 ))
/* ========================================================
電池の管理
以下のピンは主にここで操作・監視されます。
・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 100
bit temp_zone_charge_disable; // 温度で充電停止する時にヒステリシスを付けるため
void tsk_batt( )
{
static u8 task_interval = 0;
static u8 heikinka_h,heikinka_l;
if( task_interval-- != 0 )
{
return;
}
else
{
task_interval = (u8)( INTERVAL_TSK_BATT / SYS_INTERVAL_TICK );
}
// アダプタステータス更新 /////////
{
static u8 pm_extdc_old;
u8 temp_pm_extdc;
temp_pm_extdc = !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)( 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 );
chg_led_override = 0;
}
}
}
// 充電 ///////////////////////////
// 温度付きヒステリシス
if(( 75 <= raw_adc_temperature )
&& ( raw_adc_temperature <= 184 ))
{
if( heikinka_h < 40 )
{
heikinka_h++;
}
else
{
temp_zone_charge_disable = 0; // 充電許可
}
}
else if(( raw_adc_temperature <= 61 )
|| ( 189 <= raw_adc_temperature ))
{
if( heikinka_l < 40 )
{
heikinka_l++;
}
else
{
temp_zone_charge_disable = 1; // 充電禁止
}
}
else
{
// temp_zone_charge_disable そのまま
heikinka_h = 0;
heikinka_l = 0;
}
#ifndef _MODEL_WM0_
// WM0ではCHG_ENABLEピンは /WL_RST に配線されており、充電制御しない
if( !temp_zone_charge_disable && bt_chg_ready && !PM_EXTDC_n )
{
BT_CHG_ENABLE(); // 温度範囲OKで充電再開
}
else
{
BT_CHG_DISABLE(); // 温度危険! 充電停止
}
#endif
// 充電 //
// →割り込み。
{
static u8 anti_chatter;
u8 temp_CHARGE;
temp_CHARGE = !BT_IN_CHG_n; // volatileのため。このピンはチャタらない。
if( !temp_CHARGE )
{
anti_chatter = 0;
set_bit( 0, vreg_ctr[VREG_C_STATUS], REG_BIT_BATT_CHARGE ); // set_bitのみ。
/// 割り込みはmiscが引き受ける
LED_CHARGE = 0;
}
else
{
if( anti_chatter < 2 ) // 電池無しでアダプタさして、電極をさわさわ
{ // すると充電LEDががさがさするので
anti_chatter++;
}
else
{
set_bit( 1, vreg_ctr[VREG_C_STATUS], REG_BIT_BATT_CHARGE );
LED_CHARGE = 1;
}
}
}
if( chg_led_override != 0 ){ // 気がつく人いるかな…?
chg_led_override -= 1;
LED_CHARGE = 1;
}
// 電池残量 //
if(( system_status.pwr_state == ON )||
( system_status.pwr_state == SLEEP ))
{
BT_get_left();
}
}
/********************************************************
電池関係の初期化
   ゲージ  | 有り     | 無し
  ーーーーーーーーーーーーーーーーーーーーーーー
   電池 有り| 実機     | ?
  ーーーーーーーーーーーーーーーーーーーーーーー
      無し| 白箱     | 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 = 0;
return;
// おしまい
}
if(( battery_manufacturer_old != battery_manufacturer ) ||
bt_force_update )
{
bt_force_update = 0;
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 = 1;
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;
}
// 電池メーカーの識別 //
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 == 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.メーカー別パラメータのロード
{
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 = ( 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];
}
vreg_ctr[ VREG_C_BT_VOLTAGE ] = 200;
}
else
{
// 実機 //
u8 temp_v[2];
u8 temp_force_fule_left;
u16 temp16;
// 残量リード
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 = 0;
vreg_ctr[ VREG_C_BT_REMAIN ] = 0;
system_status.force_off = 1; // 強制電源断フラグ(カウンタ)
}
else
{
// バッテリパラメータの関係でビットシフトが必要
temp16 = ( temp_fuel[0] << 8 ) + temp_fuel[1];
temp16 /= BT_RCOMP_SCALE[ battery_manufacturer ];
temp_fuel[0] = ( temp16 >> 8 ) & 0xFF;
temp_fuel[1] = temp16 & 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];
temp16 = ( temp_v[0] << 8 ) + temp_v[1];
if( temp16 > V_TH_30 )
{
temp_force_fule_left = 100;
hysteresis = 0;
}
else if( temp16 > V_TH_LO + hysteresis )
{
temp_force_fule_left = 30;
hysteresis = 0;
}
else if( temp16 > V_TH_EMPTY )
{
temp_force_fule_left = BATT_TH_LO; // ここから赤
hysteresis = 500;
}
else if( temp16 > V_TH_ZERO )
{
temp_force_fule_left = BATT_TH_EMPTY;
hysteresis = 500;
}
else
{
// temp_force_fule_left = 0;
system_status.force_off = 1; // 強制電源断フラグ(カウンタ)
}
}
}
// 充電許可(=アダプタも刺さってる)のに充電してない = 充電完了
if( BT_CHG_Ena && !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;
}
}
}
}
// 残量で割り込み。急激に減ると飛ぶことがある //
{
static u8 bt_remain_old_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 );
}
if( system_status.pwr_state == OFF_TRIG )
{
bt_remain_old_ctr = 100;
}
// twlに教えてあげる
if( bt_remain_old_ctr != vreg_ctr[ VREG_C_BT_REMAIN ] )
{
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 ){
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;
}
}
bt_remain_old_ctr = vreg_ctr[ VREG_C_BT_REMAIN ];
}
// PMIC-NTRに電池残量を教えてあげる
{
static u8 bt_remain_old_ntr;
u8 flag;
if( system_status.pwr_state != ON )
{
bt_remain_old_ntr = NTR_PM_BT_ENOUGH;
}
flag = (( vreg_ctr[ VREG_C_BT_REMAIN ] <= BATT_TH_LO )? NTR_PM_BT_EMPTY: NTR_PM_BT_ENOUGH ); // 1で電池切れ
if( bt_remain_old_ntr != flag )
{
bt_remain_old_ntr = flag;
iic_mcu_write_a_byte_codec( CODEC_REG_BT, 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 = 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 );
}
return ( ERR_SUCCESS );
}
// BSR //
void PM_LCD_off()
{
SND_DEPOP_SND_MUTE;
// 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_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 ); // ここでは異常チェック不要
}
/* ========================================================
液晶の対向電圧の設定を行います。
仮想レジスタの内容を送るだけ
======================================================== */
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( )
{
// 電源順次立ち上げ
// 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;
{
wait_ms( 100 );
// CODEC 不定レジスタ初期化
iic_mcu_write_a_byte_codec( CODEC_REG_PM, 0 );
iic_mcu_write_a_byte_codec( CODEC_REG_PM+1, 0 );
iic_mcu_write_a_byte_codec( CODEC_REG_PM+2, 0 );
reg_shadow = 0; // こんなところで...
}
return ( ERR_SUCCESS );
}
/* ========================================================
電源OFFシーケンス
======================================================== */
err 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;
PM_off( );
PM_LDSW_off( );
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_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 );
}