ctr_mcu/trunk/tasks_sys.c
fujita_ryohei 1683de10fa homeボタン対応 tuneボタン廃止(tuneボタンがhomeボタン代わりになります)
スリープ機能

git-svn-id: file:///Volumes/Transfer/gigaleak_20231201/2020-05-23%20-%20ctr.7z%20+%20svn_v1.068.zip/ctr/svn/ctr_mcu@14 013db118-44a6-b54f-8bf7-843cb86687b1
2009-10-27 23:52:17 +00:00

423 lines
11 KiB
C
Raw 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.

#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;
}