#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" u8 SW_pow_count, SW_home_count, SW_tune_count, SW_wifi_count; bit SW_pow_mask, SW_home_mask, SW_tune_mask, SW_wifi_mask; /* ======================================================== マイコン内部で必要なもの ・省電力に入れる  system_status.pwr_state == OFF_TRIG で、このタスクが呼ばれると、 省電力モードに入ります ======================================================== */ void tsk_sys( ) { static u8 timeout = 0; RTCIMK = 0; // インターバル割り込み許可 switch ( system_status.pwr_state ) { case OFF: //------------------------------------------------------- // スイッチ操作などで割り込みが発生し、スリープが解除されるとここに来ます。 switch ( system_status.poweron_reason ) { default: // スイッチで電源on if( ( SW_pow_count != 0 ) || ( SW_wifi_count != 0 ) ) { timeout = 0; } else { timeout += 1; } if( timeout > 127 ) { system_status.pwr_state = OFF_TRIG; // スイッチはノイズだった。寝る。 renge_task_interval_run_force = 1; return; } if( ( SW_pow_count < 3 ) && ( SW_wifi_count < 3 ) ) { // もう少しスイッチの様子を見る return; } break; case ( RTC_ALARM ): break; // 何か他に電源ON要因はあるか? // 蓋開け // アダプタ(充電の温度を監視しなくてはならない) } timeout = 0; // 電源投入 SW_pow_mask = 1; SW_tune_mask = 1; SW_wifi_mask = 1; // 電源投入 // iic_mcu_start( ); PM_init( ); // 電池残量ICの設定 // todo bt_auth if( PM_bt_auth( ) != ERR_SUCCESS ) { // どうするの? renge_task_interval_run_force = 1; system_status.pwr_state = OFF_TRIG; while( 1 ) { NOP( ); } // return( 0 ); } if( PM_sys_pow_on( ) != ERR_SUCCESS ) { // 電源起動不可エラー renge_task_interval_run_force = 1; iic_mcu_stop( ); system_status.pwr_state = OFF; 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 { vreg_ctr[VREG_C_LED_POW] = LED_POW_ILM_OFF; // 他には? } // ここまで来ると、電源投入確定 system_status.pwr_state = ON_TRIG; renge_task_interval_run_force = 1; return; break; case ON_TRIG: //------------------------------------------------------- LED_init( ); { PU7 = 0b00011101; // 4:SW_WIFI 3:SW_PWSW 2:PM_IRQ 0:PM_EXTDC } // アクティブ中に使用するピン変化割り込み // I2CやDMAは個別にセットしてください // KRM = 0b00000000; MK0 = INT_MSK0_RSV; MK1 = INT_MSK1_RSV; #ifdef _MCU_BSR_ MK2 = INT_MSK2_RSV; #else MK2L = INT_MSK2L_RSV; #endif // ほか、必要ペリフェラルの初期化 IIC_ctr_Init( ); // とりあえずはここで初期化 IIC_twl_Init( ); RTC_32k_on( ); system_status.pwr_state = ON; #ifndef _CODEC_CTR_ { u8 temp; // do{ temp = iic_mcu_write_a_byte( IIC_SLA_DCP, 0x08, 0x80 ); // ACR←0x80 揮発モードへ NOP( ); // }while( temp != ERR_SUCCESS ); } #endif system_status.poweron_reason = PWSW; return; break; case ON: //--------------------------------------------- if( !RESET1_n ) { // 電源異常チェック /// コマンドで、正規にリセットをかけたときには、 /// このチェックに引っかからないので大丈夫 NOP( ); // ステータス類の設定、電源のフラグなどの整理 // system_status.pwr_state = OFF_TRIG; // renge_task_interval_run_force = 1; } return; break; case SLEEP_TRIG: //------------------------------------- system_status.pwr_state = SLEEP; // todo PMICのモード切替 // SoCとのハンドシェイク PM_BL_off( ); return; break; case SLEEP: //------------------------------------------ system_status.pwr_state = ON_TRIG; if( !RESET1_n ) { NOP( ); /* // ステータス類の設定、電源のフラグなどの整理 system_status.pwr_state = OFF_TRIG; renge_task_interval_run_force = 1; */ } return; break; case OFF_TRIG: //--------------------------------------- LED_stop( ); IIC_ctr_Stop( ); IIC_twl_Stop( ); vreg_ctr[VREG_C_IRQ0] = 0; vreg_ctr[VREG_C_IRQ1] = 0; vreg_ctr[VREG_C_IRQ2] = 0; vreg_ctr[VREG_C_IRQ3] = 0; BT_TEMP_P = 0; // 電源オン条件の割り込みセット // PWSW KR3 押すとL // BG24 KR4 // ふた開け INTP5 閉じるとL // ACアダプタ INTP4 アダプタありでL // RTC DI( ); #ifdef _PMIC_TWL_ PM_TEG_LCD_dis( 1 ); #endif PM_sys_pow_off( ); // iic_mcu_stop(); // pullup_off(); ↓ { PU5 = 0b00000011; // PM_CHG,PM_CHGERR PU7 = 0b00011001; // SW_WiFi,PWSWI,PM_EXTTDC } // KRM = ( KR_SW_POW | KR_SW_WIFI ); // Mask ではなく、Modeなのだそうだ。紛らわしい KRM = ( KR_SW_POW ); // Mask ではなく、Modeなのだそうだ。紛らわしい // intp20系は後ほど MK0 = 0b1111111110111111; // INT(EXTDC) // MK0 = 0b1111111100111111; // INT(SHELL), INT(EXTDC) MK1 = 0b1111010111111111; // KR(SW_PW,SW_WiFi,...), RTC(Alarm) MK2L = 0b11111111; IF0 = 0; IF1 = 0; IF2 = 0; timeout = 0; system_status.pwr_state = OFF; while( RWST ) {; } iic_mcu_stop( ); STOP( ); // 割り込み待ちで寝る // // while( SW_POW_n ){;} KRMK = 1; RTCIMK = 0; // インターバル割り込み許可 EI( ); renge_task_interval_run_force = 1; return; break; default: while( 1 ) { NOP( ); // あり得ないステート } } return; } #define INTERVAL_TSK_SW 16 #define CLICK_THRESHOLD 3 #define LONG_PUSH_THREASHOLD ( 800 / INTERVAL_TSK_SW ) /* ======================================================== スイッチの監視  チャタリングをはねたり、長押しや、押したトリガなどの検出など todo 必要に応じてマスク ======================================================== */ // 押した時間を数える。押しっぱなしでも0に戻らない // maskが非0の時は、一度離すまで無視する #define count_sw_n( sw, counter, mask ) \ { \ if( sw ){ \ mask = 0; \ counter = 0; \ }else{ \ if( mask != 0 ){ \ counter = 0; \ }else{ \ counter += 1; \ if( counter == 0 ) counter = 255; \ } \ } \ } void tsk_sw( ) { static u8 cnt_force_off = 0; static u8 sw_pow_old = 0; static u8 task_interval = 0; if( task_interval != 0 ) { task_interval -= 1; return; } else { task_interval = ( INTERVAL_TSK_SW / SYS_INTERVAL_TICK ); } if( ( system_status.pwr_state == ON ) || ( system_status.pwr_state == OFF ) ) { count_sw_n( SW_POW_n, SW_pow_count, SW_pow_mask ); count_sw_n( SW_WIFI_n, SW_wifi_count, SW_wifi_mask ); count_sw_n( SW_TUNE_n, SW_tune_count, SW_tune_mask ); // count_sw_n( SW_HOME_n, SW_home_count, SW_home_mask ); } switch ( system_status.pwr_state ) { case ( OFF_TRIG ): SW_pow_count = 0; SW_wifi_count = 0; SW_tune_count = 0; cnt_force_off = 0; break; case ( ON ): case ( SLEEP ): // 電源スイッチの監視 // if( SW_pow_count == 0 ) { if( ( CLICK_THRESHOLD < sw_pow_old ) && ( sw_pow_old < LONG_PUSH_THREASHOLD ) ) { set_irq( VREG_C_IRQ0, REG_BIT_SW_POW_CLICK ); } } else if( SW_pow_count == LONG_PUSH_THREASHOLD ) { set_irq( VREG_C_IRQ0, REG_BIT_SW_POW_HOLD ); } else if( SW_pow_count == ( LONG_PUSH_THREASHOLD * 4 ) ) { // todo // vreg_ctr[ VREG_C_LED_POW ] = LED_POW_ONLY_RED; system_status.pwr_state = OFF_TRIG; renge_task_interval_run_force = 1; } sw_pow_old = SW_pow_count; // 電源OFF割り込みを入れたが… if( ( vreg_ctr[VREG_C_IRQ0] & REG_BIT_SW_POW_HOLD ) != 0 ) { cnt_force_off += 1; if( cnt_force_off >= 13 ) { // …返事がない。強制的に切る。 vreg_ctr[VREG_C_LED_POW] = LED_POW_ILM_OFF; if( ( LED_duty_pow_H == 0 ) && ( LED_duty_pow_L == 0 ) ) { system_status.pwr_state = OFF_TRIG; renge_task_interval_run_force = 1; } } } else { cnt_force_off = 0; } /* todo // HOME スイッチ…だと? // if( SW_home_count == 6 ){ vreg_ctr[ VREG_C_IRQ0 ] |= REG_BIT_SW_HOME_CLICK; if( ( vreg_ctr[ VREG_C_IRQ_MASK0 ] & REG_BIT_SW_HOME_CLICK ) == 0 ){ IRQ0_ast; } }else if( SW_pow_count == 66 ){ vreg_ctr[ VREG_C_IRQ0 ] |= REG_BIT_SW_HOME_HOLD; if( ( vreg_ctr[ VREG_C_IRQ_MASK0 ] & REG_BIT_SW_HOME_HOLD ) == 0 ){ IRQ0_ast; } } */ // wifi sw if( SW_wifi_count == 10 ) { set_irq( VREG_C_IRQ0, REG_BIT_SW_WIFI_CLICK ); } // tune sw if( SW_tune_count == 10 ) { set_irq( VREG_C_IRQ0, REG_BIT_SW_TUNE_CLICK ); } break; } /* マスクのせいでできなくなった // まとめて割り込みを立てる if(( vreg_ctr[ VREG_C_IRQ0 ] & ( REG_BIT_SW_POW_CLICK | REG_BIT_SW_POW_HOLD | REG_BIT_SW_HOME_CLICK | REG_BIT_SW_HOME_HOLD | REG_BIT_SW_WIFI_CLICK | REG_BIT_SW_TUNE_CLICK ) ) != 0 ){ IRQ0_ast; } */ return; }