/* ======================================================== スイッチ ・HOME ・POWER ・WiFi の監視タスク $Id$ ======================================================== */ #ifndef _WIN32 #pragma SFR #pragma NOP #pragma HALT #pragma STOP #endif #include "incs.h" #include "i2c_twl.h" #include "i2c_ctr.h" #include "led.h" #include "pm.h" #include "rtc.h" #include "sw.h" //========================================================= /* vreg_ctrから読みたいのでヘッダへ #define INTERVAL_TSK_SW #define CLICK_THRESHOLD #define HOLD_THREASHOLD #define FORCEOFF_THREASHOLD */ #define TIME_MUKAN ( u8)( 300 / INTERVAL_TSK_SW ) #define TIME_MUKAN_PWSW_RED_TRIAL (u16)( 15000 / INTERVAL_TSK_SW ) // 試遊台、homeマスク時間 //========================================================= u16 SW_pow_count; bit SW_pow_mask; static u8 SW_home_count, SW_wifi_count, SW_home_count_rel; static u8 sw_wifi_mukan_time; u16 off_timeout_timer; static u16 sw_pwsw_mukan_time; //========================================================= static void chk_pow_sw(); static void chk_wifi_sw(); /********************************************//** 押した時間を数える。押しっぱなしでも0に戻らない maskが非0の時は、一度離すまで無視する ***********************************************/ #define count_sw_n( sw, counter, mask ) \ { \ if( sw ){ \ mask = 0; \ counter = 0; \ }else{ \ if( mask != 0 ){ \ counter = 0; \ }else{ \ counter ++; \ if( counter == 0 ) counter = -1; \ } \ } \ } /********************************************//** クリックしたか(チャタリング除去)。必要に応じて割り込み ***********************************************/ #define chk_clicked( button, count, irq_bit_name ) \ if( !button ) \ { \ if( count < CLICK_THRESHOLD ) \ { \ count ++; \ if( count == CLICK_THRESHOLD ) \ { \ count ++; \ set_irq( VREG_C_IRQ0, irq_bit_name ); \ } \ } \ } \ else \ { \ count = 0; \ } /********************************************//** スイッチの監視 チャタリングをはねたり、長押しや、押したトリガなどの検出を行う ***********************************************/ void tsk_sw( ) { static u8 task_interval; if( system_status.pwr_state == OFF_TRIG ) { SW_pow_count = 0; // 電源投入に備えてクリア // task_interval = 0; } if( system_status.pwr_state != ON_CHECK ) // 測定時間(PWSW_POWON_TIME)が短いのでプリスケーラ無し でないとチャタ除去があまりきかない { if( task_interval != 0 ) { task_interval--; return; // おしまい } task_interval = (u8)( INTERVAL_TSK_SW / SYS_INTERVAL_TICK ) -1; // プリスケーラ代わりに使ってますね… // -1はポストデクリメントのための調整 } // 8ms 毎にきます switch( system_status.pwr_state ) { case( ON ): case( SLEEP ): chk_wifi_sw(); if( !SHELL_OPEN ) { break; } // else 節の時は fall through (蓋閉じならpwswチェックをスキップ)。 // 実装が良くない気もするが... // HOME sw // chk_clicked( SW_HOME_n, SW_home_count, REG_BIT_SW_HOME_CLICK ); chk_clicked( !SW_HOME_n, SW_home_count_rel, REG_BIT_SW_HOME_RELEASE ); /* fall through */ case( OFF ): case( ON_CHECK ): chk_pow_sw(); break; default: break; } } /********************************************//** 電源スイッチの監視 試遊台、ホームメニューには入れないようにしたくて、自動起動にしてあるそうだが mmen の不具合でホームメニューにいけてしまう事がある(市場クレーム有り) なのでマイコンでその操作をマスクする。 ***********************************************/ static void chk_pow_sw() { // 実機の場合 if( ! system_status.taikendai ) { if( SW_pow_count == ( TIME_PWSW_CLICK ) ) // クリック時間に到達 { if( is_wifi_calib_resets_ast ) // wifi キャリブレーション時なら、SoCに通知せずにoffに遷移 { system_status.pwr_state = OFF_TRIG; } 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 ); if( off_timeout_timer == 0 ) // 強制電源断カウントダウン開始、何度も発動しないように。 { off_timeout_timer = vreg_ctr[ VREG_C_OFF_DELAY ] * 16; } } if( off_timeout_timer != 0 ) // 長押し割り込み後、タイムアウトで強制オフ。 { off_timeout_timer --; if( off_timeout_timer == 0 ) { force_off = true; } } }else{ // スタンドアロン試遊台 if( SW_pow_count == ( TIME_PWSW_CLICK ) ) { if( sw_pwsw_mukan_time == 0 ) { set_irq( VREG_C_IRQ0, REG_BIT_SW_POW_CLICK ); // いやなタイミングでPWSWを押すとHOMEメニューに入れてしまうのを回避するためのマスクタイマー sw_pwsw_mukan_time = TIME_MUKAN_PWSW_RED_TRIAL; } } else if( SW_pow_count == ( HOLD_THREASHOLD ) ) { force_off = true; } if( sw_pwsw_mukan_time != 0 ) { sw_pwsw_mukan_time--; } } count_sw_n( SW_POW_n, SW_pow_count, SW_pow_mask ); // ボタン押し時間のカウント } /********************************************//** wifi スイッチの監視 最悪な実装なのはわかっているが、市場に出てしまった不良スイッチを救うため …そもそも他のスイッチも全部こうするのがいいんだろうけど ***********************************************/ static void chk_wifi_sw() { // wifi sw // if( sw_wifi_mukan_time != 0 ) { sw_wifi_mukan_time--; } else { chk_clicked( SW_WIFI_n, SW_wifi_count, REG_BIT_SW_WIFI_CLICK ); if( SW_wifi_count == CLICK_THRESHOLD +1 ) // 押した判定発生! { sw_wifi_mukan_time = TIME_MUKAN; } } }