#pragma SFR #pragma NOP #pragma HALT #pragma STOP #include "incs.h" #include "i2c_twl.h" #include "i2c_ctr.h" #include "led.h" #include "accero.h" #include "pm.h" #include "rtc.h" #include "sw.h" #include "adc.h" #include "self_flash.h" //========================================================= static void chk_emergencyExit(); //========================================================= extern bit infoLed_off; /* ======================================================== マイコン内部で必要なもの ・省電力に入れる  system_status.pwr_state == OFF_TRIG で、このタスクが呼ばれると、 省電力モードに入ります ======================================================== */ void tsk_sys( ) { static u8 timeout = 0; static u8 bt_status_old; switch ( system_status.pwr_state ) { case OFF: //------------------------------------------------------- // スイッチ操作などで割り込みが発生し、スリープが解除されるとここに来ます。 if( system_status.poweron_reason == NONE ) { // スイッチで電源on if( SW_pow_count != 0 ) { timeout = 0; } else { timeout += 1; } if( timeout > 100 ) { system_status.pwr_state = OFF_TRIG; // スイッチはノイズだった。寝る。 renge_task_interval_run_force = 1; return; } if( SW_pow_count < 10 ) { // もう少しスイッチの様子を見る return; } // 電源投入 system_status.poweron_reason = PWSW; } SW_pow_mask = 1; timeout = 0; // 電源投入 // BT_DET_P = 1; // チャージに時間が掛かるので、先に上げておく BT_TEMP_P = 1; iic_mcu_start( ); BT_init( ); // 実機やバッテリの判定、電池残量ICの設定 if( system_status.poweron_reason == EXT_POWER ) { system_status.pwr_state = BT_CHARGE; return; } if( system_status.model == MODEL_JIKKI_NOBATT ) { renge_task_interval_run_force = 1; system_status.pwr_state = OFF_TRIG; return; } // 残量チェック BT_get_left(); // 先に、BT_init()が実行されている必要があります。(大丈夫) if( vreg_ctr[VREG_C_BT_REMAIN] < 5 ) { renge_task_interval_run_force = 1; system_status.pwr_state = OFF_TRIG; return; } if( PM_sys_pow_on( ) != ERR_SUCCESS ) { // 電源起動不可エラー renge_task_interval_run_force = 1; system_status.pwr_state = OFF_TRIG; return; } PM_LCD_vcom_set( ); // LCDの対向電圧値など書き込み #ifdef _PMIC_TWL_ PM_TEG_LCD_dis( 0 ); #endif if( system_status.poweron_reason == PWSW ) { // 電源ボタンでのonの時は、LEDを点灯させる vreg_ctr[VREG_C_LED_POW] = LED_POW_ILM_AUTO; } else { // とりあえず、LED消灯状態で起動させる vreg_ctr[VREG_C_LED_POW] = LED_POW_ILM_OFF; } system_status.pwr_state = ON_TRIG; // ここまで来ると、電源投入確定 // break; case ON_TRIG: //------------------------------------------------------- LED_init( ); PU5 = 0b00000010; // 1:PM_CHARGE PU7 = 0b00011101; // 4:SW_WIFI 3:SW_PWSW 2:PM_IRQ 0:PM_EXTDC_n #ifdef _MODEL_CTR_ # ifdef _SW_HOME_ENABLE_ PU20 = 0b00010000; // SW_HOME # else PU20 = 0b00000000; # endif #endif IIC_ctr_Init( ); { // WDTリセット時、I2Cの初期化まで割り込み保留 // ほんとはここにべた書きしたくないが... if( ( vreg_ctr[ VREG_C_MCU_STATUS ] & REG_BIT_STATUS_WDT_RESET ) != 0 ) { set_irq( VREG_C_IRQ0, REG_BIT_IRQ_WDT_RESET ); } } IIC_twl_Init( ); RTC_32k_on( ); vreg_twl_init( ); vreg_ctr_reset( ); KRM = 0b00000000; system_status.poweron_reason = NONE; renge_task_interval_run_force = 1; MK0 = INT_MSK0_RSV; MK1 = INT_MSK1_RSV; iic_mcu_start(); #ifdef _MCU_BSR_ // MK2 = ~( INT_MSK2_IIC_TWL | INT_MSK2_WIFI_TX_BSR | INT_MSK2_CODEC_PMIRQ ); // PMK21 = 0; // wifi 使わない PMK6 = 0; // pm_irq #else MK2L = ~INT_MSK2_WIFI_TX_KE3; #endif // リブート時、ステータスを何となく更新 if( system_status.reboot ) { u8 bl_status_temp; bl_status_temp = iic_mcu_read_a_byte( IIC_SLA_PMIC, PM_REG_ADRS_BL ); vreg_ctr[ VREG_C_STATUS ] |= (( bl_status_temp & 0x03 ) << 5 ); set_bit( ( iic_mcu_read_a_byte( IIC_SLA_PMIC, PM_REG_ADRS_VDD_LCD ) != 0 ), vreg_ctr[ VREG_C_STATUS ], REG_BIT_LCD_POW ); } system_status.reboot = 0; system_status.pwr_state = ON; break; case ON: //--------------------------------------------- // PMICによる強制電源断チェック // デバッガがreset1をアサートすることもある。そのときは全部リセット chk_emergencyExit(); // SLP監視 if( SLP_REQ ){ system_status.pwr_state = SLEEP_TRIG; renge_task_interval_run_force = 1; } break; case SLEEP_TRIG: //------------------------------------- PM_VDD_ecoMode(); system_status.pwr_state = SLEEP; break; case SLEEP: //------------------------------------------ chk_emergencyExit(); // スリープから復帰 if( !SLP_REQ ){ PM_VDD_normMode(); wait_ms( 5 ); // tdly_sw #ifdef _MODEL_CTR_ SLP_ACK = 1; NOP(); // 適当ウェイト NOP(); NOP(); NOP(); SLP_ACK = 0; #endif system_status.pwr_state = ON; } break; case OFF_TRIG: //--------------------------------------- // LED消灯を待つ vreg_ctr[ VREG_C_LED_POW ] = LED_POW_ILM_OFF; vreg_ctr[ VREG_C_LED_WIFI ] = WIFI_LED_OFF; vreg_ctr[ VREG_C_LED_TUNE ] = LED_TUNE_ILM_OFF; infoLed_off = 1; if( system_status.info_fullcolor ) { if( LED_duty_pow_blu != 0 ) { return; } } else { if( LED_duty_old_pow_blu != 0 ) { return; } } LED_stop( ); IIC_ctr_Stop( ); IIC_twl_Stop( ); RTC_32k_off(); vreg_ctr[VREG_C_IRQ0] = 0; vreg_ctr[VREG_C_IRQ1] = 0; vreg_ctr[VREG_C_IRQ2] = 0; vreg_ctr[VREG_C_IRQ3] = 0; // 電源オン条件の割り込みセット // PWSW KR3 押すとL // BG24 KR4 // ふた開け INTP5 閉じるとL // ACアダプタ INTP4 アダプタありでL // RTC #ifdef _PMIC_TWL_ PM_TEG_LCD_dis( 1 ); #endif while( iic_mcu_busy ) {; } KRM = ( KR_SW_POW ); // Mask ではなく、Modeなのだそうだ。紛らわしい MK0 = ~( INT_MSK0_EXTDC ); MK1 = ~( INT_MSK1_KR | INT_MSK1_RTCALARM | INT_MSK1_RTCINTVAL ); MK2L = 0b11111111; // PU5 そのまま PU7 = 0b00001001; // PWSWI,PM_EXTTDC,( IRQ0_deactive(), PM_IRQ_deactive ) PU20 = 0x00; // SW_HOME 停止 IF0 = 0; IF1 = 0; IF2 = 0; PM_sys_pow_off( ); timeout = 0; system_status.pwr_state = BT_CHARGE; SW_pow_mask = 1; SW_pow_count = 0; // no break // case BT_CHARGE: if( !PM_EXTDC_n ) { if( !bt_status_old ){ iic_mcu_start( ); BT_init( ); // 実機やバッテリの判定、電池残量ICの設定 } bt_status_old = 1; // アダプタ有り:充電温度監視 if( SW_pow_count >= 10 ) // 電源スイッチが押されるのを待つ { // 電源投入 system_status.poweron_reason = PWSW; system_status.pwr_state = OFF; } } else { bt_status_old = 0; // 省電力へ移行 system_status.poweron_reason = NONE; PM_Chg_Stop(); while( RWST ) {;} iic_mcu_stop( ); // 割り込み待ちで寝る // RTCIMK = 1; # ifdef _MCU_BSR_ CKC = 0b00001001; OSMC = 0x00; # endif STOP( ); // 起きる // // 起きる条件は // ・KeyReturn割り込み(電源ボたん) // ・RTCアラーム // ・アダプタ挿抜 if( PM_EXTDC_n ) { SW_pow_mask = 0; } # ifdef _MCU_BSR_ OSMC = 0x01; CKC = 0b00001000; # endif RTCIMK = 0; system_status.pwr_state = OFF; BT_DET_P = 1; // チャージに時間が掛かるので、先に上げておく BT_TEMP_P = 1; } return; default: while( 1 ) { NOP( ); // あり得ないステート } } } /*******************************************************//** PMICが電源異常で止めたか確認 **********************************************************/ static void chk_emergencyExit(){ static u8 shirobako_power_control_count; if( shirobako_power_control_count == 0 ) // PM_chk_LDSW() はI2C_mを使用し、高コスト { if( !RESET1_n ) { // リセットが下がってる if( PM_chk_LDSW( ) == 0 ) { // PMICが異常終了判断をした system_status.pwr_state = OFF_TRIG; renge_task_interval_run_force = 1; } else { // 白箱の仕業 shirobako_power_control_count = 1; } } } else { if( shirobako_power_control_count == 240 ) // デバッガが何かした。reset1を解除するまでは無視 { if( RESET1_n ) { shirobako_power_control_count = 0; } }else if( shirobako_power_control_count == 200 ) // デバッガが何かしたいらしい { // 白箱は電源を切りたいらしい system_status.pwr_state = OFF_TRIG; renge_task_interval_run_force = 1; shirobako_power_control_count = 240; } else { if( !RESET1_n ) { shirobako_power_control_count += 1; } else { // リセットをかけたらしい iic_mcu_write_a_byte( IIC_SLA_PMIC, PM_REG_ADRS_BL, 0 ); vreg_ctr[VREG_C_STATUS] = ( vreg_ctr[VREG_C_STATUS] & 0b10011111 ); vreg_ctr[VREG_C_COMMAND0] |= REG_BIT_RESET1_REQ; renge_task_immed_add( do_command0 ); shirobako_power_control_count = 240; } } } } /* ======================================================== CPUからのスリープ要求  ポーリングにしました。 ======================================================== */ /* __interrupt void intp0_slp( ) { // SLP if( SLP_REQ ){ system_status.pwr_state = SLEEP_TRIG; renge_task_interval_run_force = 1; }else{ system_status.pwr_state = ON; PM_VDD_normMode(); wait_ms( 5 ); // tdly_sw #ifdef _MODEL_CTR_ SLP_ACK = 1; NOP(); // 適当ウェイト NOP(); NOP(); NOP(); SLP_ACK = 0; #endif system_status.pwr_state = ON; } } */ /*******************************************************//** 全く意味ないですが、気分的な物で... **********************************************************/ task_status_immed tski_firm_update(){ firm_update(); return( ERR_SUCCESS ); }