#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_wifi_count; bit SW_pow_mask, SW_home_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_home_mask = 1; SW_wifi_mask = 1; // 電源投入 // iic_mcu_start( ); // ↓で電池残量ICの起動待ちウェイトなどがあります。 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; 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; break; case ON: //--------------------------------------------- { // PMICによる強制電源断チェック static u8 count; if( !RESET1_n ) { count += 1; } else { count = 0; } if( count > 50 ){ /// コマンドで、正規にリセットをかけたときには、 /// このチェックに引っかからないので大丈夫 system_status.pwr_state = OFF_TRIG; renge_task_interval_run_force = 1; } } // SLP監視 if( SLP_REQ ){ system_status.pwr_state = SLEEP_TRIG; renge_task_interval_run_force = 1; } break; case SLEEP_TRIG: //------------------------------------- #ifdef _MODEL_CTR_ PM_VDD_ecoMode(); #endif system_status.pwr_state = SLEEP; break; case SLEEP: //------------------------------------------ if( !RESET1_n ) { system_status.pwr_state = OFF_TRIG; renge_task_interval_run_force = 1; } // スリープから復帰 if( !SLP_REQ ){ #ifdef _MODEL_CTR_ PM_VDD_normMode(); #endif wait_ms( 5 ); // tdly_sw #ifdef _MODEL_CTR_ SLP_ACK = 1; NOP(); // 適当ウェイト NOP(); NOP(); NOP(); SLP_ACK = 0; #endif system_status.pwr_state = ON_TRIG; renge_task_interval_run_force = 1; } 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) 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; break; default: while( 1 ) { NOP( ); // あり得ないステート } } } #define INTERVAL_TSK_SW 16 #define CLICK_THRESHOLD 3 #define HOLD_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 task_interval = 0; if( task_interval != 0 ) { task_interval -= 1; return; } else { task_interval = ( INTERVAL_TSK_SW / SYS_INTERVAL_TICK ); } switch ( system_status.pwr_state ) { case ( OFF_TRIG ): SW_pow_count = 0; SW_wifi_count = 0; SW_home_count = 0; cnt_force_off = 0; break; case ( ON ): case ( SLEEP ): // 電源スイッチの監視 // if( SW_POW_n ) { if( ( CLICK_THRESHOLD < SW_pow_count ) && ( SW_pow_count < HOLD_THREASHOLD ) ) { set_irq( VREG_C_IRQ0, REG_BIT_SW_POW_CLICK ); } } else if( SW_pow_count == HOLD_THREASHOLD ) { set_irq( VREG_C_IRQ0, REG_BIT_SW_POW_HOLD ); } else if( SW_pow_count == ( HOLD_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; } // 電源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; } // HOME スイッチ // if( SW_HOME_n ) { if( ( CLICK_THRESHOLD < SW_home_count ) && ( SW_home_count < HOLD_THREASHOLD ) ) { set_irq( VREG_C_IRQ0, REG_BIT_SW_HOME_CLICK ); } } else if( SW_home_count == HOLD_THREASHOLD ) { set_irq( VREG_C_IRQ0, REG_BIT_SW_HOME_HOLD ); } // wifi sw // if( SW_wifi_count == 10 ) { set_irq( VREG_C_IRQ0, REG_BIT_SW_WIFI_CLICK ); } break; } 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_HOME_n, SW_home_count, SW_home_mask ); count_sw_n( SW_WIFI_n, SW_wifi_count, SW_wifi_mask ); } return; }