From 513599316a5e91005d52f6c4cadb0c82f1705460 Mon Sep 17 00:00:00 2001 From: N2232 Date: Thu, 13 May 2010 06:14:25 +0000 Subject: [PATCH] sdk0.9(0.10) git-svn-id: file:///Volumes/Transfer/gigaleak_20231201/2020-05-23%20-%20ctr.7z%20+%20svn_v1.068.zip/ctr/svn/ctr_mcu@135 013db118-44a6-b54f-8bf7-843cb86687b1 --- trunk/sdk0.9/WDT.c | 9 + trunk/sdk0.9/WDT.h | 6 +- trunk/sdk0.9/accero.c | 69 +- trunk/sdk0.9/adc.c | 168 +-- trunk/sdk0.9/batt_params.h | 116 +- trunk/sdk0.9/bsr_mcu.dr | 22 +- trunk/sdk0.9/bsr_system.h | 7 +- trunk/sdk0.9/config.h | 49 +- trunk/sdk0.9/i2c_ctr.c | 29 +- trunk/sdk0.9/i2c_mcu.c | 296 ++-- trunk/sdk0.9/i2c_mcu.h | 2 +- trunk/sdk0.9/i2c_twl.c | 7 - trunk/sdk0.9/incs.h | 3 +- trunk/sdk0.9/incs_loader.h | 4 +- trunk/sdk0.9/ini_VECT.c | 112 +- trunk/sdk0.9/jhl_defs.h | 7 +- trunk/sdk0.9/led.c | 439 +++--- trunk/sdk0.9/led.h | 82 +- trunk/sdk0.9/loader.c | 142 +- trunk/sdk0.9/loader.h | 4 + trunk/sdk0.9/magic.c | 12 +- trunk/sdk0.9/main.c | 10 +- trunk/sdk0.9/pedo_alg_thre_det2.c | 190 +-- trunk/sdk0.9/pedometer.h | 97 +- trunk/sdk0.9/pm.c | 951 ++++++------- trunk/sdk0.9/pm.h | 51 +- trunk/sdk0.9/renge/renge_defs.h | 3 +- trunk/sdk0.9/renge/renge_task_intval.h | 11 +- trunk/sdk0.9/self_flash.c | 121 +- trunk/sdk0.9/sw.c | 124 +- trunk/sdk0.9/sw.h | 4 +- trunk/sdk0.9/task_debug.c | 10 +- trunk/sdk0.9/task_misc.c | 33 +- trunk/sdk0.9/task_sys.c | 202 +-- trunk/sdk0.9/user_define.h | 89 +- trunk/sdk0.9/vreg_ctr.c | 111 +- trunk/sdk0.9/vreg_ctr.h | 46 +- trunk/sdk0.9/vreg_twl.c | 9 +- trunk/sdk0.9/vreg_twl.h | 6 +- .../yav-mcu-basara_sdk0.9.ncb | Bin 0 -> 855040 bytes .../yav-mcu-basara_sdk0.9.sln | 20 + .../yav-mcu-basara_sdk0.9.suo | Bin 0 -> 18944 bytes .../yav-mcu-basara_sdk0.9/Debug/BuildLog.htm | Bin 0 -> 76506 bytes .../yav-mcu-basara_sdk0.9/Debug/vc90.idb | Bin 0 -> 19456 bytes .../yav-mcu-basara_sdk0.9/Debug/vc90.pdb | Bin 0 -> 36864 bytes .../yav-mcu-basara_sdk0.9.vcproj | 373 +++++ ...av-mcu-basara_sdk0.9.vcproj.NCL.N2232.user | 65 + trunk/sdk0.9/yav_mcu_bsr.plg | 4 + trunk/sdk0.9/yav_mcu_bsr.pri | 169 +-- trunk/sdk0.9/yav_mcu_bsr.prj | 1238 +++++++---------- trunk/sdk0.9/yav_mcu_bsr.prk | 27 +- trunk/sdk0.9/yav_mcu_bsr.sdb | 18 +- 52 files changed, 2745 insertions(+), 2822 deletions(-) create mode 100644 trunk/sdk0.9/yav-mcu-basara_sdk0.9/yav-mcu-basara_sdk0.9.ncb create mode 100644 trunk/sdk0.9/yav-mcu-basara_sdk0.9/yav-mcu-basara_sdk0.9.sln create mode 100644 trunk/sdk0.9/yav-mcu-basara_sdk0.9/yav-mcu-basara_sdk0.9.suo create mode 100644 trunk/sdk0.9/yav-mcu-basara_sdk0.9/yav-mcu-basara_sdk0.9/Debug/BuildLog.htm create mode 100644 trunk/sdk0.9/yav-mcu-basara_sdk0.9/yav-mcu-basara_sdk0.9/Debug/vc90.idb create mode 100644 trunk/sdk0.9/yav-mcu-basara_sdk0.9/yav-mcu-basara_sdk0.9/Debug/vc90.pdb create mode 100644 trunk/sdk0.9/yav-mcu-basara_sdk0.9/yav-mcu-basara_sdk0.9/yav-mcu-basara_sdk0.9.vcproj create mode 100644 trunk/sdk0.9/yav-mcu-basara_sdk0.9/yav-mcu-basara_sdk0.9/yav-mcu-basara_sdk0.9.vcproj.NCL.N2232.user diff --git a/trunk/sdk0.9/WDT.c b/trunk/sdk0.9/WDT.c index 965b09c..c39323c 100644 --- a/trunk/sdk0.9/WDT.c +++ b/trunk/sdk0.9/WDT.c @@ -3,3 +3,12 @@ #include "incs_loader.h" + + +//========================================================= +// ウォッチドッグタイマのリスタート +// 0xACはマジック +void WDT_Restart( void ) +{ + WDTE = WDT_RESTART_MAGIC; +} diff --git a/trunk/sdk0.9/WDT.h b/trunk/sdk0.9/WDT.h index b61970a..6c6e9e4 100644 --- a/trunk/sdk0.9/WDT.h +++ b/trunk/sdk0.9/WDT.h @@ -9,12 +9,10 @@ //========================================================= -// ウォッチドッグタイマのリスタート -// void WDT_Restart( void ); -#define WDT_Restart() WDTE = WDT_RESTART_MAGIC +void WDT_Restart( void ); // 規定値以外を書くと例外でリセットがかかる -#define mcu_reset WDTE = 0xFF +#define mcu_reset WDTE = 0x5A #endif diff --git a/trunk/sdk0.9/accero.c b/trunk/sdk0.9/accero.c index 0bcb97f..fe850b5 100644 --- a/trunk/sdk0.9/accero.c +++ b/trunk/sdk0.9/accero.c @@ -14,16 +14,7 @@ #pragma MUL #pragma BCD - - -#include "config.h" -#ifdef _MCU_BSR_ -#pragma interrupt INTP23 intp23_ACC_ready RB3 // 加速度センサ、データ準備完了 -#endif - - #include "incs.h" - #include // ======================================================== @@ -74,19 +65,26 @@ task_status tsk_soft_int( ); task_status_immed tsk_cbk_accero( ) { // (疑似)isrから登録されます - - // 加速度センサデータレジスタへの反映 - if( iic_mcu_read( IIC_SLA_ACCEL, ( ACC_REG_X | 0x80 ), 6, &vreg_ctr[VREG_C_ACC_XL] ) - != ERR_SUCCESS ) +/* + if(( system_status.pwr_state == OFF ) || ( system_status.pwr_state == BT_CHARGE ) ) { - // 加速度センサが異常になったので止める - vreg_ctr[ VREG_C_ACC_CONFIG ] &= ~( VREG_BITMASK_ACC_CONF_HOSU | VREG_BITMASK_ACC_CONF_ACQ ); - acc_hosu_set(); - vreg_ctr[ VREG_C_STATUS_1 ] |= REG_BIT_ACCERO_ERR; - return ( ERR_SUCCESS ); // タスクの削除は必要 + return ( ERR_SUCCESS ); } else { +*/ + // 加速度センサデータレジスタへの反映 + if( iic_mcu_read( IIC_SLA_ACCEL, ( ACC_REG_X | 0x80 ), 6, &vreg_ctr[VREG_C_ACC_XL] ) + != ERR_SUCCESS ) + { + // 加速度センサが異常になったので止める + vreg_ctr[VREG_C_ACC_CONFIG] &= ~( VREG_BITMASK_ACC_CONF_HOSU | VREG_BITMASK_ACC_CONF_ACQ ); +// vreg_ctr[ VREG_C_STATUS_1 ] |= REG_BIT_ACCERO_ERR; + acc_hosu_set(); + return ( ERR_SUCCESS ); // タスクの削除は必要 + } + else + { // 正常時パス // // 加速度更新&割り込み if( (( vreg_ctr[VREG_C_ACC_CONFIG] & VREG_BITMASK_ACC_CONF_ACQ ) != 0 ) && @@ -106,9 +104,9 @@ task_status_immed tsk_cbk_accero( ) ( ( vreg_ctr[VREG_C_ACC_CONFIG] & VREG_BITMASK_ACC_CONF_HOSU ) != 0 ) ) { - DBG_LED_WIFI_2_on; - pedometer(); // 歩数計 - DBG_LED_WIFI_2_off; + DBG_LED_WIFI_2_on; + pedometer(); // 歩数計 + DBG_LED_WIFI_2_off; } } return ( ERR_SUCCESS ); @@ -152,7 +150,9 @@ task_status_immed acc_write( ) /*========================================================= - 加速度センサの設定 + 自動歩数カウントモードにセット + todo 他のモードだったら止めたり、復帰させたり + 割り込みルーチンなどでカウント判定が必要 ========================================================*/ task_status_immed acc_hosu_set( ) { @@ -181,30 +181,15 @@ task_status_immed acc_hosu_set( ) /// IRQ2flg latch: auto clear after read, IRQ2 conf: IRQ( fall,shock,...) /// 1 : auto clear after read, conf: data ready # endif - #else -# ifdef _MODEL_CTR_ -/* -if( system_status.model == MODEL_TS_BOARD ) - { - // TS Final SoC - str_send_buf[2] = 0x02; // 3 IRQ pol :Active HI, Drive:Pushpull, - } - else - { - // 実機&派生種、白箱 - str_send_buf[2] = 0x10; // 3 IRQ pol :Active HI, Drive:Pushpull, - } -*/ - str_send_buf[2] = 0x12; // 面倒なので両方...。 +# ifdef _MODEL_CTR_JIKKI_ + str_send_buf[2] = 0x10; # else - // TS( type T ) str_send_buf[2] = 0x02; // 3 IRQ pol :Active HI, Drive:Pushpull, /// IRQ2flg latch: auto clear after read, IRQ2 conf: IRQ( fall,shock,...) /// 1 : auto clear after read, conf: data ready # endif #endif - str_send_buf[3] = 0x80; // ctrl3 block update:enable, MSB first, scale: +-2G(default), selftest: dis if( ( vreg_ctr[VREG_C_ACC_CONFIG] & @@ -255,11 +240,11 @@ __interrupt void intp23_ACC_ready( ) { if( ( system_status.pwr_state == ON ) || ( system_status.pwr_state == SLEEP ) ) { - if( ACC_VALID == 1 ) + if( ACC_VALID ) { -// todo -// renge_task_immed_add( tsk_cbk_accero ); + renge_task_immed_add( tsk_cbk_accero ); } } } } + diff --git a/trunk/sdk0.9/adc.c b/trunk/sdk0.9/adc.c index 70bfcd5..16658cc 100644 --- a/trunk/sdk0.9/adc.c +++ b/trunk/sdk0.9/adc.c @@ -9,28 +9,12 @@ #include "led.h" - -//#define _4db_ -#define _15db_ - -// ===================================================== // bit adc_updated; u8 adc_raw_vol; u8 adc_raw_dep; - - -// ===================================================== // -extern void nop8(); - - - -// ===================================================== // #define INTERVAL_TSK_ADC 3 - - - /* ======================================================== ADC設定と、開始 @@ -40,42 +24,38 @@ extern void nop8(); ・VOL 関係ありそうですが別のところで管理しています - ・PM_BT_DET,_P BT_init + ・PM_BT_DET,_P PM_init ・8tics毎に呼ばれ、3チャンネル分取り込むとADCを停止します。  タスク起動時、レジスタには前回の取り込み値が入っています。 ======================================================== */ - -#ifdef _15db_ -// max -15db -const u8 slider_to_codec[64] = -{ - 127, 127, 127, 126, 125, 124, 123, 122, - 121, 120, 119, 118, 117, 116, 115, 114, - 113, 112, 111, 110, 109, 108, 107, 106, - 105, 104, 103, 102, 101, 100, 99, 98, - 97, 96, 95, 94, 93, 92, 91, 90, - 89, 88, 87, 86, 85, 84, 83, 82, - 81, 80, 79, 78, 77, 76, 75, 74, - 73, 72, 71, 70, 69, 68, 67, 66 -}; -#endif - -#ifdef _4db_ +/* // max -4db -const u8 slider_to_codec[64] = +static const u8 slider_to_codec[64] = { - 127, 127, 126, 125, 123, 122, 121, 119, - 118, 117, 115, 114, 112, 111, 110, 108, - 107, 106, 104, 103, 101, 100, 99, 97, - 96, 94, 93, 92, 90, 89, 88, 86, - 85, 83, 82, 81, 79, 78, 77, 75, - 74, 72, 71, 70, 68, 67, 66, 64, - 64, 63, 61, 60, 59, 57, 56, 54, - 53, 52, 50, 49, 48, 46, 44, 44 + 127, 125, 124, 123, 121, 120, 119, 117, + 116, 115, 113, 112, 111, 109, 108, 107, + 105, 104, 103, 101, 100, 99, 98, 96, + 95, 94, 92, 91, 90, 88, 87, 86, + 84, 83, 82, 80, 79, 78, 76, 75, + 74, 72, 71, 70, 69, 67, 66, 65, + 63, 62, 61, 59, 58, 57, 55, 54, + 53, 51, 50, 49, 47, 46, 45, 44 }; -#endif +*/ +// max -10db +static const u8 slider_to_codec[64] = +{ + 127, 126, 125, 124, 123, 122, 121, 120, + 119, 118, 117, 116, 115, 114, 113, 112, + 111, 110, 109, 109, 108, 107, 106, 105, + 104, 103, 102, 101, 100, 99, 98, 97, + 96, 95, 94, 93, 92, 91, 90, 89, + 88, 87, 86, 85, 84, 83, 82, 81, + 81, 80, 79, 78, 77, 76, 75, 74, + 73, 72, 71, 70, 69, 68, 67, 66 +}; void tsk_adc( ) { @@ -149,27 +129,47 @@ void tsk_adc( ) } } } + vreg_ctr[ VREG_C_DBG1 ] = vreg_ctr[ VREG_C_TUNE ]; + vreg_ctr[ VREG_C_DBG2 ] = adc_raw_dep; // dbg // Volume ///////////////////////////////////// { + // 似非ヒステリシスを付けて64段 + u8 temp; static u8 vol_old; static u8 force_update_vol; - if( ( abs( adc_raw_vol - vol_old ) >= 2 ) // 生値でこれくらいずれたら更新(似非ヒステリシス) - || ( --force_update_vol == 0 ) ) // ポーリング + if( abs( adc_raw_vol - vol_old ) >= 2 ) // 生値でこれくらいずれたら更新 { - vol_old = adc_raw_vol; - // レジスタ更新 - vreg_twl[ REG_TWL_INT_ADRS_VOL ] = vol_old / ( 256 / 32 ); // ←adc値でよい - vreg_ctr[ VREG_C_SND_VOL ] = ( vol_old / 4 ); // 64段 +// if( vreg_ctr[ VREG_C_SND_VOL ] != ( adc_raw_vol / 4 ) ) + { + vol_old = adc_raw_vol; + // レジスタ更新 + vreg_ctr[ VREG_C_SND_VOL ] = ( adc_raw_vol / 4 ); + vreg_twl[ REG_TWL_INT_ADRS_VOL ] = adc_raw_vol / ( 256 / 32 ); // ←adc値でよい - // codecに伝える - iic_mcu_write_a_byte( IIC_SLA_CODEC, CODEC_REG_VOL, slider_to_codec[ vol_old / 4 ] ); + // codecに伝える + iic_mcu_write_a_byte( IIC_SLA_CODEC, CODEC_REG_VOL, slider_to_codec[ adc_raw_vol / 4 ] ); #ifndef _MODEL_CTR_ - iic_mcu_write_a_byte( IIC_SLA_DCP, 0, slider_to_codec[ ( 255 - vol_old ) / 4 ] ); + iic_mcu_write_a_byte( IIC_SLA_DCP, 0, slider_to_codec[ ( 255 - adc_raw_vol ) / 4 ] ); // todo #endif -// set_irq( VREG_C_IRQ0, REG_BIT_VR_SNDVOL_CHANGE ); // 割り込み廃止 - force_update_vol = 200; +// set_irq( VREG_C_IRQ0, REG_BIT_VR_SNDVOL_CHANGE ); // 割り込み廃止 + force_update_vol = 100; + } + } + + { + // ポーリング + if( --force_update_vol == 0 ) + { + vol_old = adc_raw_vol; + // レジスタ更新 +// vreg_ctr[ VREG_C_SND_VOL ] = temp; +// vreg_twl[ REG_TWL_INT_ADRS_VOL ] = adc_raw_vol / ( 256 / 32 ); // ←adc値でよい + // codecに伝える + iic_mcu_write_a_byte( IIC_SLA_CODEC, CODEC_REG_VOL, slider_to_codec[ adc_raw_vol / 4 ] ); + force_update_vol = 100; + } } } @@ -180,16 +180,16 @@ void tsk_adc( ) switch ( vreg_ctr[VREG_C_LED_TUNE] ) { case LED_TUNE_ILM_ON: - LED_duty_3d = vreg_ctr[VREG_C_LED_BRIGHT]; + LED_duty_TUNE = vreg_ctr[VREG_C_LED_BRIGHT]; break; case LED_TUNE_ILM_SVR: - LED_duty_3d = vreg_ctr[VREG_C_TUNE] / 16; + LED_duty_TUNE = vreg_ctr[VREG_C_TUNE] / 16; break; case LED_TUNE_ILM_OFF: default: - LED_duty_3d = 0; + LED_duty_TUNE = 0; break; } } @@ -199,11 +199,18 @@ void tsk_adc( ) ADCEN = 1; - ADM = 0b00001011; // セレクトモード、昇圧、fCLK/6 ///ここから ↓ + ADM = 0b00011011; // セレクトモード、章圧、fCLK/6 ///ここから ↓ ADPC = 0x06; // ADCポートのセレクト ADS = ADC_SEL_TUNE; - nop8(); + NOP(); + NOP(); + NOP(); + NOP(); + NOP(); + NOP(); + NOP(); + NOP(); ADCS = 1; // AD開始。 /// ここまで ↑ までに1us=8clk以上開ける ADIF = 0; @@ -246,7 +253,6 @@ static u8 getmean3( u8 * hist ) /* ========================================================  自前で次のチャンネル   一通り終わったら止める - // todo 値が飛ぶことがある? ======================================================== */ __interrupt void int_adc( ) { @@ -259,7 +265,7 @@ __interrupt void int_adc( ) switch ( ADS ) { /* -case ( ADC_SEL_AMB_BRIT ): // 環境明るさ +case ( ADC_SEL_AMB_BRIT ): vreg_ctr[ VREG_C_AMBIENT_BRIGHTNESS ] = ADCRH; break; */ @@ -275,28 +281,24 @@ case ( ADC_SEL_AMB_BRIT ): // case ( ADC_SEL_VOL ): hist_snd_vol[index] = ADCRH; -#ifdef _MODEL_CTR_ - if( system_status.model == MODEL_TS_BOARD ) - { - adc_raw_vol = getmean3( hist_snd_vol ); - } - else - { - adc_raw_vol = ( 255 - getmean3( hist_snd_vol )); - } +#ifdef _MODEL_CTR_JIKKI_ + adc_raw_vol = ( 255 - getmean3( hist_snd_vol )); #else - adc_raw_vol = getmean3( hist_snd_vol ); + adc_raw_vol = getmean3( hist_snd_vol ); #endif + // TWL用レジスタ(32段)の更新。アトミックな処理として扱わないと不都合が。 + /// 割り込みはHorizonを通してコマンドを発行されるのを待てばよい break; case ( ADC_SEL_BATT_TEMP ): hist_bt_temp[index] = ADCRH; raw_adc_temperature = getmean3( hist_bt_temp ); - renge_task_immed_add( BT_temp_update ); + renge_task_immed_add( PM_bt_temp_update ); break; case ( ADC_SEL_BATT_DET ): - // 呼ばれない +// vreg_ctr[ VREG_C_DBG_BATT_DET ] = ADCRH; + // todo break; } @@ -306,10 +308,12 @@ case ( ADC_SEL_AMB_BRIT ): // if( ADS != ADC_SEL_BATT_TEMP ) { // 電池判別は電源投入の一回のみ ADS += 1; // 次のチャンネル + BT_TEMP_P = 1; // 電池温度監視スタート } else { ADCEN = 0; // 止めてしまう + BT_TEMP_P = 0; // 電池温度監視スタート adc_updated = 1; index = ( index == 2 ) ? 0 : ( index + 1 ); } @@ -328,19 +332,25 @@ u8 get_adc( u8 ch ) ADIF = 0; ADCEN = 1; - ADM = 0b00001011; // セレクトモード、昇圧、fCLK/6 ///ここから↓ + ADCS = 0; + ADM = 0b00100011; // セレクトモード、昇圧、fCLK/6 ///ここから↓ ADPC = 0x06; // ADCポートのセレクト ADS = ch; - - nop8(); - + NOP(); + NOP(); + NOP(); + NOP(); + NOP(); + NOP(); + NOP(); + NOP(); ADCS = 1; // AD開始。 /// ここまで↑ に、1us以上開ける + ADMK = 0; while( ADIF == 0 ){;} temp = ADCRH; ADCEN = 0; - ADMK = 0; return ( temp ); } diff --git a/trunk/sdk0.9/batt_params.h b/trunk/sdk0.9/batt_params.h index 36927a2..b18a6c4 100644 --- a/trunk/sdk0.9/batt_params.h +++ b/trunk/sdk0.9/batt_params.h @@ -1,76 +1,80 @@ -#ifndef _bt_params_h_ -#define _bt_params_h_ - /* ======================================================== 各社バッテリーパラメータ ======================================================== */ -const u8 BT_PARAM[][64] = { - // ID = 0 GND マクセル - { - 0xAD, 0x30, 0xAE, 0x70, 0xB0, 0x00, 0xB3, 0x00, - 0xB4, 0x70, 0xB5, 0xA0, 0xB7, 0x80, 0xBA, 0x00, - - 0xBB, 0x90, 0xBD, 0x00, 0xBE, 0x00, 0xBF, 0xF0, - 0xC3, 0x00, 0xC5, 0xC0, 0xC8, 0x00, 0xCA, 0xC0, - - 0x04, 0x00, 0x12, 0x00, 0x0C, 0x10, 0x24, 0x00, - 0x10, 0xD0, 0x1B, 0xF0, 0x0A, 0xF0, 0x08, 0xE0, - - 0x0C, 0xF0, 0x08, 0xC0, 0x08, 0xB0, 0x07, 0xF0, - 0x0B, 0x00, 0x05, 0xD0, 0x02, 0x00, 0x09, 0x00 - }, +enum BATT_VENDER { + BT_PANASONIC, // open + BT_UNKNOWN1, + BT_UNKNOWN2, + BT_UNKNOWN3, + BT_UNKNOWN4, + BT_UNKNOWN5, + BT_UNKNOWN6, // gnd + BT_MAXELL + }; + + +static const u8 BT_PARAM[][64] = { + // ID = 0 GND 白箱 + /// パラメータ無し { // ID = 1 120 ohm - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, { // ID = 2 360 hom - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, { // ID = 3 750 ohm - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, { // ID = 4 1.3kohm - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, { // ID = 5 2.7kohm パナ - 0xAD, 0x30, 0xAE, 0x70, 0xB0, 0x00, 0xB3, 0x00, - 0xB4, 0x70, 0xB5, 0xA0, 0xB7, 0x80, 0xBA, 0x00, + 0xAD, 0x30, 0xAE, 0x70, 0xB0, 0x00, 0xB3, 0x00, + 0xB4, 0x70, 0xB5, 0xA0, 0xB7, 0x80, 0xBA, 0x00, - 0xBB, 0x90, 0xBD, 0x00, 0xBE, 0x00, 0xBF, 0xF0, - 0xC3, 0x00, 0xC5, 0xC0, 0xC8, 0x00, 0xCA, 0xC0, + 0xBB, 0x90, 0xBD, 0x00, 0xBE, 0x00, 0xBF, 0xF0, + 0xC3, 0x00, 0xC5, 0xC0, 0xC8, 0x00, 0xCA, 0xC0, - 0x04, 0x00, 0x12, 0x00, 0x0C, 0x10, 0x24, 0x00, - 0x10, 0xD0, 0x1B, 0xF0, 0x0A, 0xF0, 0x08, 0xE0, + 0x04, 0x00, 0x12, 0x00, 0x0C, 0x10, 0x24, 0x00, + 0x10, 0xD0, 0x1B, 0xF0, 0x0A, 0xF0, 0x08, 0xE0, - 0x0C, 0xF0, 0x08, 0xC0, 0x08, 0xB0, 0x07, 0xF0, - 0x0B, 0x00, 0x05, 0xD0, 0x02, 0x00, 0x09, 0x00 - }, + 0x0C, 0xF0, 0x08, 0xC0, 0x08, 0xB0, 0x07, 0xF0, + 0x0B, 0x00, 0x05, 0xD0, 0x02, 0x00, 0x09, 0x00 + }, { // ID = 6 8.2kohm - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + }, + { // ID = 7 マクセル + 0xAD, 0x30, 0xAE, 0x70, 0xB0, 0x00, 0xB3, 0x00, + 0xB4, 0x70, 0xB5, 0xA0, 0xB7, 0x80, 0xBA, 0x00, + + 0xBB, 0x90, 0xBD, 0x00, 0xBE, 0x00, 0xBF, 0xF0, + 0xC3, 0x00, 0xC5, 0xC0, 0xC8, 0x00, 0xCA, 0xC0, + + 0x04, 0x00, 0x12, 0x00, 0x0C, 0x10, 0x24, 0x00, + 0x10, 0xD0, 0x1B, 0xF0, 0x0A, 0xF0, 0x08, 0xE0, + + 0x0C, 0xF0, 0x08, 0xC0, 0x08, 0xB0, 0x07, 0xF0, + 0x0B, 0x00, 0x05, 0xD0, 0x02, 0x00, 0x09, 0x00 } - // ID = 7 白箱 - /// パラメータ無し }; -const unsigned char BT_PANA_RCOMP = 135; -// static const float BT_PANA_TEMPCOUP = 0.3; -// static const float BT_PANA_TEMPCODN = 0.5; -// 256倍してある -const unsigned char BT_PANA_TEMPCOUP = 77; -const unsigned char BT_PANA_TEMPCODN = 128; +static const unsigned char BT_PANA_RCOMP = 135; +static const float BT_PANA_TEMPCOUP = 0.3; +static const float BT_PANA_TEMPCODN = 0.5; -#endif diff --git a/trunk/sdk0.9/bsr_mcu.dr b/trunk/sdk0.9/bsr_mcu.dr index f45329b..12fcfd0 100644 --- a/trunk/sdk0.9/bsr_mcu.dr +++ b/trunk/sdk0.9/bsr_mcu.dr @@ -9,26 +9,30 @@ MEMORY ROM : (02000H, 03000H ) ;;; セグメントの割当先設定 ; ブートブロック0に割り当てる -MERGE LDR_CODE : =BCL0 -MERGE LDR_CODL : =BCL0 -MERGE @@LCODE : =BCL0 ; スタートアップルーチン -MERGE FSL_CODE : =BCL0 ; =FSL ; 謹製フラッシュライブラリ -;MERGE @@LCODEL : =BCL0 +MERGE LDR_CODE: =BCL0 +MERGE LDR_CODL: =BCL0 +;MERGE @@LCODE : AT( 0E00H ) =BCL0 ; スタートアップルーチン +MERGE @@LCODE : =BCL0 ; スタートアップルーチン ;MERGE LDR_RINT:=BCL0 ;MERGE LDR_CNST:=BCL0 MERGE LDR_CNSL:=BCL0 - -; 通常領域に置く +; 通常領域にあてる物達 MERGE ROM_CODE:=ROM +;MERGE ROM_CNST:=ROM + + +; ちょっと、困るんですが、こうしないと初期値がセットされない MERGE @@CNST: =ROM -MERGE @@R_INIT: =ROM ; ROM以外に置きたいならスタートアップルーチンを要修正 - +MERGE @@R_INIT: =ROM +; 謹製フラッシュライブラリ +; MERGE FSL_CODE:=FSL +MERGE FSL_CODE:=BCL0 ; マジックナンバー diff --git a/trunk/sdk0.9/bsr_system.h b/trunk/sdk0.9/bsr_system.h index 59944a3..9332094 100644 --- a/trunk/sdk0.9/bsr_system.h +++ b/trunk/sdk0.9/bsr_system.h @@ -19,7 +19,6 @@ enum poweron_reason_ NONE = 0, PWSW, RTC_ALARM, - EXT_POWER }; @@ -28,12 +27,13 @@ enum model_ MODEL_JIKKI = 0, MODEL_TS_BOARD, MODEL_SHIROBAKO, - MODEL_JIKKI_NOBATT, MODEL_RESERVED1, MODEL_RESERVED2, MODEL_RESERVED3, }; + + // タスクシステムの状態情報など typedef struct { @@ -43,11 +43,12 @@ typedef struct unsigned char dipsw1:1; unsigned char dipsw2:1; unsigned char reboot:1; - enum model_ model; + enum model_ model; } system_status_; + extern system_status_ system_status; diff --git a/trunk/sdk0.9/config.h b/trunk/sdk0.9/config.h index 3420693..e5f9707 100644 --- a/trunk/sdk0.9/config.h +++ b/trunk/sdk0.9/config.h @@ -1,39 +1,49 @@ #ifndef __config__ #define __config__ -//#define _debug_ +#define _debug_ //#define _debug_led_ #define MCU_VER_MAJOR 0x00 -#define MCU_VER_MINOR 0x11 +#define MCU_VER_MINOR 0x10 #define _OVERCLOCK_ //#define PM_CCIC_TIM +// 古い(C)電源ボード +//#define _PM_BUG_ +//#define _PARRADIUM_ //#define _MODEL_TEG2_ // ↑TEG2 CPU + Type-T - -//#define _MODEL_WM0_ -//#define _MODEL_WM0_TEG2_CTRC_ - +#define _MODEL_WM0_ +#define _MODEL_WM0_TEG2_CTRC_ //#define _MODEL_TS0_ // ↑TEG2 CPU + Type-C - -#define _MODEL_CTR_ - // ↑TS board, WM1,1 TS-CTRC - -//#define _MODEL_CTR_NOTIFY_FULLCOLOR_ - // ↑TS board, WM1,1 TS-CTRC +//#define _MODEL_CTR_TS_ + // ↑FINAL SoC + Type-C +//#define _MODEL_CTR_JIKKI_ -// 特殊仕様 // //#define _SW_HOME_ENABLE_ -//#define _PARRADIUM_ 廃止 -//#define _PM_BUG_ // バグ持ち CTR PMIC 廃止 -#define _FOR_E3_ + +// ---------------------------------- // +#ifdef _MODEL_CTR_TS_ +#ifdef _MODEL_CTR_JIKKI_ +どちらか一方だけセットして下さい。 +#endif +#endif + +#ifdef _MODEL_CTR_TS_ +#define _MODEL_CTR_ +#endif + +#ifdef _MODEL_CTR_JIKKI_ +#define _MODEL_CTR_ +#endif + // ---------------------------------- // #ifdef _MODEL_TEG2_ @@ -60,11 +70,4 @@ #define _SW_HOME_ENABLE_ #endif -#ifdef _MODEL_CTR_NOTIFY_FULLCOLOR_ -#define _MODEL_CTR_ -#define _PMIC_CTR_ -#define _MCU_BSR_ -#define _SW_HOME_ENABLE_ -#endif - #endif diff --git a/trunk/sdk0.9/i2c_ctr.c b/trunk/sdk0.9/i2c_ctr.c index 7b363ae..15fde2a 100644 --- a/trunk/sdk0.9/i2c_ctr.c +++ b/trunk/sdk0.9/i2c_ctr.c @@ -3,18 +3,8 @@ 藤田@開技.nintendo '09 Apr ======================================================== */ - -#include "config.h" - -#ifdef _MCU_KE3_ -#pragma interrupt INTIICA int_iic_ctr // CTR側 -#else -// TSはマザボでテレコ、WMは回路図がテレコで結局一致… -#pragma interrupt INTIICA1 int_iic_ctr RB1 -#endif - - #include "incs.h" +#include "accero.h" #ifdef _MCU_BSR_ // #ifdef _MODEL_TS0_ || _MODEL_WM0_ @@ -189,22 +179,15 @@ __interrupt void int_iic_ctr( ) vreg_ctr_after_read( reg_adrs ); // 読んだらクリアなどの処理 } else - { // 受信 + { // 受信 rx_buf = IICA; vreg_ctr_write( reg_adrs, rx_buf ); WREL = 1; } - - // レジスタアドレスのインクリメント - /// アクセスポインタを進めない特殊なレジスタ - switch( reg_adrs ) - { - case( VREG_C_ACC_HOSU_HIST ): - case( VREG_C_INFO ): - case( VREG_C_FREE_DATA ): - case( VREG_C_LED_NOTIFY_DATA ): - break; - default: + // + if( ( reg_adrs != VREG_C_ACC_HOSU_HIST ) + && ( reg_adrs != VREG_C_INFO ) ) + { // この二つのレジスタは特殊なアクセス方法をする。アクセスポインタを進めない。 reg_adrs += 1; } diff --git a/trunk/sdk0.9/i2c_mcu.c b/trunk/sdk0.9/i2c_mcu.c index 80c48e3..fe45b74 100644 --- a/trunk/sdk0.9/i2c_mcu.c +++ b/trunk/sdk0.9/i2c_mcu.c @@ -7,7 +7,7 @@ #pragma di #pragma ei #pragma nop -#pragma inline // memcpy()をインライン展開する(の方が小さい!) +#pragma inline // memcpy()をインライン展開する #include "incs.h" #include "i2c_mcu.h" @@ -72,26 +72,28 @@ u8 iic_send_wo_dma_len; u8 iic_mcu_bus_status; // 一文字リードの時はデータを返す。 // ステータスが必要ならこっちを呼んで - - -// ======================================================== void nop8() { - // 実は nop11 位なのだが } -static err iic_mcu_is_ready() + +/* ======================================================== + スレーブからの 『1文字』 リード + 返値がデータそのものです。 + エラー判定ができません。 + ======================================================== */ +u8 iic_mcu_read_a_byte( u8 SLA, u8 adrs ) { + u8 dat; + if( iic_mcu_initialized == 0 ) { #ifdef _debug_ iic_mcu_start( ); #else - return( ERR_ERR ); while( 1 ) { - NOP(); } #endif } @@ -101,32 +103,8 @@ static err iic_mcu_is_ready() NOP( ); } iic_mcu_busy = 1; - return( ERR_SUCCESS ); -} - -/* ======================================================== - スレーブからの 『1文字』 リード - 返値がデータそのものです。 - ======================================================== */ -u8 iic_mcu_read_a_byte( u8 SLA, u8 adrs ) -{ - u8 dat; - -#if 1 - // ラッパー - if( iic_mcu_read( SLA, adrs, 1, &dat ) == ERR_SUCCESS ) - { - iic_mcu_bus_status = ERR_OK; - } - else - { - iic_mcu_bus_status = ERR_NOSLAVE; - } - return ( dat ); - -#else - iic_mcu_is_ready(); + iic_mcu_bus_status = ERR_OK; // スタートコンディションとスレーブの呼び出し、レジスタアドレスの送信 if( iic_mcu_call_slave( SLA ) != 0 ) @@ -162,7 +140,6 @@ u8 iic_mcu_read_a_byte( u8 SLA, u8 adrs ) IICIF10 = 0; // 後を濁さないこと iic_mcu_busy = 0; return ( dat ); -#endif } @@ -180,22 +157,33 @@ u8 iic_mcu_read_a_byte( u8 SLA, u8 adrs ) err iic_mcu_read( u8 slave, u8 adrs, u8 len, u8 * dest ) { -#if 1 - if( iic_mcu_is_ready() != ERR_SUCCESS ) +//* + // 使用中なら待つ + if( iic_mcu_initialized == 0 ) { - return( ERR_ERR ); - } - ; +#ifdef _debug_ + iic_mcu_start( ); #else - // 使用中なら帰る - if( iic_mcu_initialized == 0 ){ - return(0x80); - } - if( iic_mcu_busy != 0 ){ - return( 3 ); - } + while( 1 ) + { + } #endif + } + while( iic_mcu_busy ) + { + NOP( ); + } +/*/ + // 使用中なら帰る + if( iic_mcu_initialized == 0 ){ + return(0x80); + } + if( iic_mcu_busy != 0 ){ + return( 3 ); + } +//*/ + iic_mcu_busy = 1; // スタートコンディションとスレーブの呼び出し、レジスタアドレスの送信 if( iic_mcu_call_slave( slave ) != 0 ) { @@ -248,27 +236,31 @@ err iic_mcu_read( u8 slave, u8 adrs, u8 len, u8 * dest ) スレーブへ 『1バイト』 ライト 前の転送が終わるのを待って、ライトします。 返値 iic_mcu_write に同じ + ======================================================== */ err iic_mcu_write_a_byte( u8 SLA, u8 adrs, u8 dat ) { - // ラッパー - static u8 temp; // 書きっぱなしで終了を見ずに関数を抜ける(可能性が高い)のでstatic -#if 0 - - // これをしないと、立て続けに書いたときに前のデータを破壊してしまう + if( iic_mcu_initialized == 0 ) + { +#ifdef _debug_ + iic_mcu_start( ); +#else + while( 1 ) + { + } +#endif + } while( iic_mcu_busy ) { NOP( ); } - + iic_mcu_busy = 1; +#if 0 temp = dat; - iic_mcu_wo_dma = 1; return ( iic_mcu_write( SLA, adrs, 1, &temp ) ); +} #else - // 1文字の時はDMAとか起動しないでさっさと終わらせる - iic_mcu_is_ready(); - // スタートコンディションとスレーブの呼び出し... IICMK10 = 1; if( iic_mcu_call_slave( SLA ) != 0 ) @@ -303,11 +295,23 @@ err iic_mcu_write_a_byte( u8 SLA, u8 adrs, u8 dat ) ******************************************************************************/ err iic_mcu_write( u8 slave, u8 adrs, u8 len, void * src ) { - if( iic_mcu_is_ready() != ERR_SUCCESS ) +//* + // 使用中なら待つ + if( iic_mcu_initialized == 0 ) { - return( ERR_ERR ); +#ifdef _debug_ + iic_mcu_start( ); +#else + while( 1 ) + { + } +#endif } -#if 0 + while( iic_mcu_busy ) + { + NOP( ); + } +/*/ // 使用中なら帰る if( iic_mcu_initialized == 0 ){ return(0x80); @@ -315,9 +319,9 @@ err iic_mcu_write( u8 slave, u8 adrs, u8 len, void * src ) if( iic_mcu_busy != 0 ){ return( 3 ); } -#endif - - // スタートコンディションとスレーブの呼び出し... +//*/ + iic_mcu_busy = 1; + // スタートコンディションとスレーブの呼び出し... IICMK10 = 1; IICIF10 = 0; if( iic_mcu_call_slave( slave ) != 0 ) @@ -341,7 +345,7 @@ err iic_mcu_write( u8 slave, u8 adrs, u8 len, void * src ) DEN1 = 1; DSA1 = ( u8 ) ( &SIO10 ); - DRA1 = &iic_send_work[0]; + DRA1 = ( u16 ) iic_send_work; DBC1 = len; DMC1 = DRS | 8; // RAM -> SFR, 8bit, IRQ, IIC10 @@ -357,14 +361,13 @@ err iic_mcu_write( u8 slave, u8 adrs, u8 len, void * src ) // DMAを使用しない // // レジスタアドレスの送信 - IICMK10 = 0; SIO10 = adrs; + IICMK10 = 0; iic_send_wo_dma_len = len; p_iic_send_wo_dma_dat = src; // 残りは割り込みルーチン内で } - return ( ERR_SUCCESS ); } @@ -403,10 +406,34 @@ __interrupt void int_dma1( ) SOE0 = 0; // 受信の時はもっと前に「も」設定してる。(NACK出力) SO0 = 0x0000 | TAUS_MASK; // SCL nop8(); - +/* + NOP( ); + NOP( ); + NOP( ); + NOP( ); +#ifdef _OVERCLOCK_ + NOP( ); + NOP( ); + NOP( ); + NOP( ); + NOP( ); +#endif +*/ SO0 = 0x0400 | TAUS_MASK; // SCL nop8(); - +/* + NOP( ); + NOP( ); + NOP( ); + NOP( ); +#ifdef _OVERCLOCK_ + NOP( ); + NOP( ); + NOP( ); + NOP( ); + NOP( ); +#endif +*/ SO0 = 0x0404 | TAUS_MASK; } IICMK10 = 1; @@ -440,10 +467,34 @@ __interrupt void int_iic10( ) SOE0 = 0; // 受信の時はもっと前に「も」設定してる。(NACK出力) SO0 = 0x0000 | TAUS_MASK; // SCL nop8(); - +/* + NOP( ); + NOP( ); + NOP( ); + NOP( ); +#ifdef _OVERCLOCK_ + NOP( ); + NOP( ); + NOP( ); + NOP( ); + NOP( ); +#endif +*/ SO0 = 0x0400 | TAUS_MASK; // SCL nop8(); - +/* + NOP( ); + NOP( ); + NOP( ); + NOP( ); +#ifdef _OVERCLOCK_ + NOP( ); + NOP( ); + NOP( ); + NOP( ); + NOP( ); +#endif +*/ SO0 = 0x0404 | TAUS_MASK; } iic_mcu_wo_dma = 0; @@ -504,8 +555,20 @@ static err iic_mcu_send_a_byte( u8 dat ) static void iic_mcu_send_st( ) { SO0 &= ~0x0004; // SDA - nop8(); - + nop8(); +/* + NOP( ); + NOP( ); + NOP( ); + NOP( ); +#ifdef _OVERCLOCK_ + NOP( ); + NOP( ); + NOP( ); + NOP( ); + NOP( ); +#endif +*/ SO0 &= ~0x0400; // SCL SOE0 = 0x0004; // ハード制御へ @@ -522,11 +585,35 @@ static void iic_mcu_send_re_st( ) { ST0 |= 0x0004; SO0 |= 0x0400 | TAUS_MASK; // ( SDA = H ), SCL -> H - nop8(); - + nop8(); +/* + NOP( ); + NOP( ); + NOP( ); + NOP( ); +#ifdef _OVERCLOCK_ + NOP( ); + NOP( ); + NOP( ); + NOP( ); + NOP( ); +#endif +*/ SOE0 &= ~0x0004; // ( SCL = H ), SDA -> L - nop8(); - + nop8(); +/* + NOP( ); + NOP( ); + NOP( ); + NOP( ); +#ifdef _OVERCLOCK_ + NOP( ); + NOP( ); + NOP( ); + NOP( ); + NOP( ); +#endif +*/ iic_mcu_send_st( ); } @@ -541,11 +628,35 @@ static void iic_mcu_send_sp( ) ST0 = 0x0004; SOE0 = 0; // 受信の時はもっと前に「も」設定してる。(NACK出力) SO0 = 0x0000 | TAUS_MASK; // SCL - nop8(); - + nop8(); +/* + NOP( ); + NOP( ); + NOP( ); + NOP( ); +#ifdef _OVERCLOCK_ + NOP( ); + NOP( ); + NOP( ); + NOP( ); + NOP( ); +#endif +*/ SO0 = 0x0400 | TAUS_MASK; // SCL - nop8(); - + nop8(); +/* + NOP( ); + NOP( ); + NOP( ); + NOP( ); +#ifdef _OVERCLOCK_ + NOP( ); + NOP( ); + NOP( ); + NOP( ); + NOP( ); +#endif +*/ SO0 = 0x0404 | TAUS_MASK; } @@ -561,19 +672,26 @@ void iic_mcu_start( ) NOP( ); // 2clkもしくは、DSTn==0をポーリング NOP( ); DEN1 = 0; - - I2C_PU_on(); - wait_ms( 10 ); // 立ち上がるのに50us位かかる - + I2C_PU = 1; SAU0EN = 1; - nop8(); - + nop8(); +/* + NOP( ); + NOP( ); + NOP( ); + NOP( ); +#ifdef _OVERCLOCK_ + NOP( ); + NOP( ); + NOP( ); + NOP( ); + NOP( ); +#endif +*/ SPS0 = 0x0000; // シリアルユニットのクロック0。(8M/2)/1 SMR02 = bSMR0n_FIXEDBIT | bMD0n2; // 簡易I2Cに設定 #ifdef _OVERCLOCK_ -// todo -// SDR02 = 12 << 9; // ボーレート設定 8M/1/(x+1)/2 - SDR02 = 13 << 9; // ボーレート設定 (8M/2)/1/(x+1)/2 + SDR02 = 12 << 9; // ボーレート設定 (8M/2)/1/(x+1)/2 #else SDR02 = 5 << 9; // ボーレート設定 (8M/2)/1/(x+1)/2 #endif @@ -610,7 +728,7 @@ void iic_mcu_stop( ) {; } // DMA動作中はもう少し待つ iic_mcu_send_re_st( ); // SCL,SDAをLLにする - I2C_PU_off(); + I2C_PU = 0; SAU0EN = 0; iic_mcu_initialized = 0; } diff --git a/trunk/sdk0.9/i2c_mcu.h b/trunk/sdk0.9/i2c_mcu.h index 2c0b737..6cd1072 100644 --- a/trunk/sdk0.9/i2c_mcu.h +++ b/trunk/sdk0.9/i2c_mcu.h @@ -16,6 +16,7 @@ extern bit iic_mcu_wo_dma; extern u8 iic_mcu_bus_status; + // ======================================================== err iic_mcu_read( u8 SLA, u8 adrs, u8 len, u8 * dest ); u8 iic_mcu_read_a_byte( u8 SLA, u8 adrs ); @@ -23,7 +24,6 @@ u8 iic_mcu_read_a_byte( u8 SLA, u8 adrs ); err iic_mcu_write( u8 SLA, u8 adrs, u8 len, void * src ); err iic_mcu_write_a_byte( u8 SLA, u8 adrs, u8 dat ); - // ↓その通信が完了したら解除されます。 #define iic_mcu_set_wo_dma() { while( iic_mcu_busy ){;} iic_mcu_wo_dma = 1; } diff --git a/trunk/sdk0.9/i2c_twl.c b/trunk/sdk0.9/i2c_twl.c index e07b908..1df2e57 100644 --- a/trunk/sdk0.9/i2c_twl.c +++ b/trunk/sdk0.9/i2c_twl.c @@ -3,13 +3,6 @@ /*============================================================================*/ - -#include "config.h" -#ifdef _MCU_KE3_ -#else -#pragma interrupt INTIICA0 int_iic_twl RB2 -#endif - #include "incs.h" #include "i2c_twl_defs.h" diff --git a/trunk/sdk0.9/incs.h b/trunk/sdk0.9/incs.h index 120ba7a..160ca82 100644 --- a/trunk/sdk0.9/incs.h +++ b/trunk/sdk0.9/incs.h @@ -12,7 +12,6 @@ #ifndef _incs_h_ #define _incs_h_ -// ↓ 歩数計で_pc_とで切り替えてます #define _mcu_ #include "jhl_defs.h" @@ -30,8 +29,8 @@ #include "accero.h" -#include "pm.h" //========================================================= +err firm_update( ); #endif diff --git a/trunk/sdk0.9/incs_loader.h b/trunk/sdk0.9/incs_loader.h index a0cda8b..4df1329 100644 --- a/trunk/sdk0.9/incs_loader.h +++ b/trunk/sdk0.9/incs_loader.h @@ -34,5 +34,5 @@ //========================================================= -void firm_update( ); -void firm_restore( ); +err firm_update( ); +err firm_restore( ); diff --git a/trunk/sdk0.9/ini_VECT.c b/trunk/sdk0.9/ini_VECT.c index 5478f6d..f992a4c 100644 --- a/trunk/sdk0.9/ini_VECT.c +++ b/trunk/sdk0.9/ini_VECT.c @@ -20,14 +20,9 @@ //#pragma interrupt INTP7 intp21_RFTx //#endif - -/* - - acceroへ #ifdef _MCU_BSR_ -#pragma interrupt INTP23 intp23_ACC_ready RB3 // 加速度センサ、データ準備完了 +#pragma interrupt INTP23 intp23_ACC_ready // 加速度センサ、データ準備完了 #endif -*/ //#pragma interrupt INTCMP0 fn_intcmp0 //#pragma interrupt INTCMP1 fn_intcmp1 @@ -47,22 +42,15 @@ //#pragma interrupt INTSRE1 fn_intsre1 -/* -それぞれの .c へ #ifdef _MCU_KE3_ -#pragma interrupt INTIICA int_iic_ctr RB1 // CTR側 +#pragma interrupt INTIICA int_iic_ctr // CTR側 #else + // TSはマザボでテレコ、WMは回路図がテレコで結局一致… -#pragma interrupt INTIICA1 int_iic_ctr RB1 +#pragma interrupt INTIICA0 int_iic_twl +#pragma interrupt INTIICA1 int_iic_ctr #endif - -#ifdef _MCU_KE3_ -#else -#pragma interrupt INTIICA0 int_iic_twl RB2 -#endif -*/ - //#pragma interrupt INTTM00 fn_inttm00 //#pragma interrupt INTTM01 fn_inttm01 //#pragma interrupt INTTM02 fn_inttm02 @@ -79,75 +67,61 @@ //#pragma interrupt INTTM06 fn_inttm06 //#pragma interrupt INTTM07 fn_inttm07 -//#define _irq_debug_ + /****************************************************/ /* 未使用時のダミー関数定義 */ /****************************************************/ __interrupt void fn_intwdti( ) { -#ifdef _irq_debug_ while( 1 ) { NOP(); } -#endif } __interrupt void fn_intlvi( ) { -#ifdef _irq_debug_ while( 1 ) { NOP(); } -#endif } __interrupt void fn_intp0(){ -#ifdef _irq_debug_ -while( 1 ) + while( 1 ) { NOP(); } -#endif } __interrupt void fn_intp1( ) { -#ifdef _irq_debug_ while( 1 ) { NOP(); } -#endif } // __interrupt void fn_intp2( ) { -#ifdef _irq_debug_ while( 1 ) { NOP(); } -#endif } __interrupt void fn_intp3( ) { -#ifdef _irq_debug_ while( 1 ) { NOP(); } -#endif } __interrupt void intp21_RFTx( ) { -#ifdef _irq_debug_ while( 1 ) { NOP(); } -#endif } @@ -159,223 +133,151 @@ __interrupt void intp21_RFTx( ) __interrupt void fn_intcmp0( ) { -#ifdef _irq_debug_ while( 1 ) { NOP(); } -#endif } - __interrupt void fn_intcmp1( ) { -#ifdef _irq_debug_ while( 1 ) { NOP(); } -#endif } - __interrupt void fn_intdma0( ) { -#ifdef _irq_debug_ while( 1 ) { NOP(); } -#endif } //__interrupt void fn_intdma1(){} // i2c_mcu.cにある __interrupt void fn_intst0( ) { -#ifdef _irq_debug_ while( 1 ) { NOP(); } -#endif } /* __interrupt void fn_intcsi00(){} */ __interrupt void fn_intsr0( ) { -#ifdef _irq_debug_ while( 1 ) { NOP(); } -#endif } /* __interrupt void fn_intcsi01(){} */ __interrupt void fn_intsre0( ) { -#ifdef _irq_debug_ while( 1 ) { NOP(); } -#endif } __interrupt void fn_intst1( ) { -#ifdef _irq_debug_ while( 1 ) { NOP(); } -#endif } /* __interrupt void fn_intcsi10(){} */ //__interrupt void fn_intiic10(){ while(1){} } __interrupt void fn_intsr1( ) { -#ifdef _irq_debug_ while( 1 ) { NOP(); } -#endif } - __interrupt void fn_intsre1( ) { -#ifdef _irq_debug_ while( 1 ) { NOP(); } -#endif } //__interrupt void fn_intiica(){} // i2c.cにある /* __interrupt void fn_inttm00(){} *//* sub.cにて定義 */ __interrupt void fn_inttm01( ) { -#ifdef _irq_debug_ while( 1 ) { NOP(); } -#endif } __interrupt void fn_inttm02( ) { -#ifdef _irq_debug_ while( 1 ) { NOP(); } -#endif } __interrupt void fn_inttm03( ) { -#ifdef _irq_debug_ while( 1 ) { NOP(); } -#endif } //__interrupt void fn_intad(){ while(1){} } // adc.c __interrupt void fn_intrtc( ) { -#ifdef _irq_debug_ while( 1 ) { NOP(); } -#endif } //__interrupt void int_rtcint(){} // rtc.cにある //__interrupt void fn_intkr(){} // main.c __interrupt void fn_intmd( ) { -#ifdef _irq_debug_ while( 1 ) { NOP(); } -#endif } __interrupt void fn_inttm04( ) { -#ifdef _irq_debug_ while( 1 ) { NOP(); } -#endif } __interrupt void fn_inttm05( ) { -#ifdef _irq_debug_ while( 1 ) { NOP(); } -#endif } __interrupt void fn_inttm06( ) { -#ifdef _irq_debug_ while( 1 ) { NOP(); } -#endif } __interrupt void fn_inttm07( ) { -#ifdef _irq_debug_ while( 1 ) { NOP(); } -#endif } - - - -/* ======================================================== - キーリターン割り込み - ======================================================== */ -__interrupt void int_kr( ) -{ - // 起きるだけ -} - - - -/* ======================================================== - ext dc - ======================================================== */ -__interrupt void intp4( ) -{ - // 起きるだけ -} - - - -/* ======================================================== - shell close - ======================================================== */ -__interrupt void intp5( ) -{ - // 起きるだけ -} - - - diff --git a/trunk/sdk0.9/jhl_defs.h b/trunk/sdk0.9/jhl_defs.h index 8a73844..1c8afa1 100644 --- a/trunk/sdk0.9/jhl_defs.h +++ b/trunk/sdk0.9/jhl_defs.h @@ -2,12 +2,9 @@ #define __jhl_defs_h__ typedef unsigned char u8; -typedef signed char s8; +typedef signed char s8; typedef unsigned short u16; -typedef signed short s16; - -typedef unsigned short ux16; -typedef signed short sx16; +typedef signed short s16; typedef unsigned char err; diff --git a/trunk/sdk0.9/led.c b/trunk/sdk0.9/led.c index ea3ca2e..b231d0f 100644 --- a/trunk/sdk0.9/led.c +++ b/trunk/sdk0.9/led.c @@ -9,8 +9,6 @@ #include "led.h" -#ifdef _MODEL_CTR_NOTIFY_FULLCOLOR_ - // ======================================================== // TPS0 @@ -33,116 +31,9 @@ static void led_pow_hotaru( ); // ======================================================== -// お知らせLEDのパターンデータ -uni_info_LED info_LED = { - 32, // 1フレームの長さ - 32, // グラデーション時間 - 0, // 最終フレームをn回繰り返す - 0, // 予備 - { - {255, 0,0}, - {0,0,0}, - {0,0,0}, - {0,0,0}, - {0,0,0}, - {0,0,0}, - {0,0,0}, - {0,0,0}, - - {0,255,0}, - {0,0,0}, - {0,0,0}, - {0,0,0}, - {0,0,0}, - {0,0,0}, - {0,0,0}, - {0,0,0}, - - {0,0,255}, - {0,0,0}, - {0,0,0}, - {0,0,0}, - {0,0,0}, - {0,0,0}, - {0,0,0}, - {0,0,0}, - - {255,255,255}, - {0,0,0}, - {0,0,0}, - {0,0,0}, - {0,0,0}, - {0,0,0}, - {0,0,0}, - {0,0,0}, - } -}; - - -//調光可能LEDのワークというか -st_LED_dim_status LED_dim_status_pow_B; -st_LED_dim_status LED_dim_status_3D; -st_LED_dim_status LED_dim_status_WiFi; - - -// 赤LEDの電池残量LEDの点滅パターン -uni_led_red_batt_empty led_red_batt_empty; - - - -// ======================================================== -#define led_fade_to( now, goal ) now = fade_to( now, goal ) - - -/* ======================================================== - reg_ledをgoalになるまでグラデーションする - とりあえず、ステップ固定 - ====================================================== */ -u8 fade_to( u8 now, u8 goal ) -{ - if( now != goal ) - { - if( now > goal ) - { - now -= 1; - } - else - { - now += 1; - } - } - return( now ); -} - - - - -// ======================================================== -#define led_fade_to2( led, status ) \ - led = fade_to2( status ) - - -u8 fade_to2( st_LED_dim_status* status ) -{ - if( status->now != status->to ) - { - if( abs(( status->to - status->now )) > abs(status->delta) ) - { - status->now += status->delta; - } - else - { - status->now = status->to; - } - } - return( status->now / 128 ); -} - - - - -// ======================================================== - +static const char MSG_MAIL[] = { 0b11110110, 0b11011010, 0b01101110, 0b10010100 }; +#define MSG_SPD 60 +// ↑255/3以下であること! // ======================================================== void LED_init( ) @@ -186,7 +77,7 @@ void LED_init( ) if( system_status.reboot ) { vreg_ctr[VREG_C_LED_POW] = LED_POW_ILM_AUTO; - LED_duty_pow_blu = LED_BRIGHT_MAX; + LED_duty_pow_H = LED_BRIGHT_MAX; } } @@ -248,8 +139,8 @@ void tsk_led_pow( ) // 強制 case ( LED_POW_ILM_OFF ): - led_fade_to( LED_duty_pow_blu, 0 ); - LED_pow_red = 0; + LED_duty_pow_H -= ( LED_duty_pow_H == 0x0000 ) ? 0 : 1; + LED_duty_pow_L -= ( LED_duty_pow_L == 0x0000 ) ? 0 : 1; break; case ( LED_POW_ILM_HOTARU ): @@ -262,13 +153,13 @@ void tsk_led_pow( ) break; case ( LED_POW_ILM_ONLY_RED ): - led_fade_to( LED_duty_pow_blu, 0 ); - LED_pow_red = 1; + LED_duty_pow_H = 0x0000; + LED_duty_pow_L = LED_BRIGHT_MAX; break; case ( LED_POW_ILM_ONLY_BLUE ): - led_fade_to( LED_duty_pow_blu, LED_BRIGHT_MAX ); - LED_pow_red = 0; + LED_duty_pow_H = LED_BRIGHT_MAX; + LED_duty_pow_L = 0x0000; break; } @@ -282,66 +173,48 @@ void tsk_led_pow( ) static void led_pow_normal( ) { static u8 state; - static u8 red_blink_poi; - u8 temp; - - if( vreg_ctr[VREG_C_BT_REMAIN] <= BATT_TH_EMPTY ) + if( vreg_ctr[VREG_C_BT_REMAIN] < 3 ) { // 赤点滅 - led_fade_to( LED_duty_pow_blu, 0 ); -#if 0 state++; if( state < 127 ) { - LED_pow_red = 0; + LED_duty_pow_H = 0x0000; + LED_duty_pow_L = 0x0000; } else { - LED_pow_red = 1; + LED_duty_pow_L = vreg_ctr[VREG_C_LED_BRIGHT]; } return; -#endif - led_fade_to( LED_duty_notify_grn, 0 ); - led_fade_to( LED_duty_notify_blu, 0 ); - state += 1; - if( state < 16 ) - { - return; - } - state = 0; - - if( ( led_red_batt_empty.bits & ( 1 << red_blink_poi )) != 1 ) - { - LED_pow_red = 1; - LED_duty_notify_red = 255; - } - else - { - LED_pow_red = 0; - LED_duty_notify_red = 0; - } - - red_blink_poi += 1; - if( red_blink_poi >= 32 ) - { - red_blink_poi = 0; - } } - else if( vreg_ctr[VREG_C_BT_REMAIN] <= BATT_TH_LO ) + else if( vreg_ctr[VREG_C_BT_REMAIN] < 12 ) { // 赤点灯 - led_fade_to( LED_duty_pow_blu, 0 ); - LED_pow_red = 1; + if( LED_duty_pow_H != 0x0000 ) + { // 青フェードアウト + LED_duty_pow_H -= 1; + } + if( LED_duty_pow_L != vreg_ctr[VREG_C_LED_BRIGHT] ) + { // 赤フェードイン + LED_duty_pow_L += ( LED_duty_pow_L < vreg_ctr[VREG_C_LED_BRIGHT] ) ? 1 : -1; + } return; } else { // 青点灯 - led_fade_to( LED_duty_pow_blu, vreg_ctr[VREG_C_LED_BRIGHT] ); - LED_pow_red = 0; + if( LED_duty_pow_H != vreg_ctr[VREG_C_LED_BRIGHT] ) + { + LED_duty_pow_H += ( LED_duty_pow_H < vreg_ctr[VREG_C_LED_BRIGHT] ) ? 1 : -1; + } + if( LED_duty_pow_L != 0x0000 ) + { + LED_duty_pow_L -= 1; + } } return; @@ -357,14 +230,41 @@ static void led_pow_hotaru( ) static u8 delay; static u8 state; static u16 blue_to; + static u16 red_to; if( delay != 0 ) { delay -= 1; return; } + else + { + delay = 10; + } - delay = 10; + if( LED_duty_pow_L != red_to ) + { + if( LED_duty_pow_L > red_to ) + { + LED_duty_pow_L -= 1; + } + else + { + LED_duty_pow_L += 2; + } + } + + if( LED_duty_pow_H != blue_to ) + { + if( LED_duty_pow_H > blue_to ) + { + LED_duty_pow_H -= 1; + } + else + { + LED_duty_pow_H += 2; + } + } switch ( state ) { @@ -372,23 +272,24 @@ static void led_pow_hotaru( ) case ( 0 ): case ( 2 ): case ( 4 ): - if( vreg_ctr[VREG_C_BT_REMAIN] <= BATT_TH_LO ) + if( vreg_ctr[VREG_C_BT_REMAIN] < 12 ) { + // 赤いとき blue_to = 0; - LED_pow_red = 1; + red_to = vreg_ctr[VREG_C_LED_BRIGHT]; } else { blue_to = vreg_ctr[VREG_C_LED_BRIGHT]; - LED_pow_red = 0; + red_to = 0; } break; default: // フェードアウト - if( vreg_ctr[VREG_C_BT_REMAIN] <= BATT_TH_LO ) + if( vreg_ctr[VREG_C_BT_REMAIN] < 12 ) { - LED_pow_red = 0; + red_to = 2; } else { @@ -397,24 +298,10 @@ static void led_pow_hotaru( ) break; } - // LED更新 - if( LED_duty_pow_blu != blue_to ) - { - if( LED_duty_pow_blu > blue_to ) - { - LED_duty_pow_blu -= 1; - } - else - { - LED_duty_pow_blu += 2; - } - } - - if( LED_duty_pow_blu == blue_to ) + if( ( LED_duty_pow_H == blue_to ) && ( LED_duty_pow_L == red_to ) ) { state += 1; } - return; } @@ -423,7 +310,7 @@ static void led_pow_hotaru( ) /* ======================================================== * 割り込みそのものは使いません * LED_Wifi 3 - todo .old からのマージ + todo 直書きの点滅間隔など ======================================================== */ void tsk_led_wifi( ) { @@ -439,15 +326,38 @@ void tsk_led_wifi( ) } // 送信パルスのラッチ - if( WIFI_txLatch ) // 割り込みフラグそのものを使ってしまう + if( vreg_ctr[VREG_C_LED_WIFI] == WIFI_LED_TXAUTO ) + { + if( WIFI_txLatch ) { WIFI_txLatch = 0; flag_wifi_TX = 2; } + } + else + { + flag_wifi_TX = 0; + } - if( flag_wifi_TX != 0 ) + + switch ( vreg_ctr[VREG_C_LED_WIFI] ) + { + case ( WIFI_LED_OFF ): + default: + LED_duty_WiFi = 0; + state_wifi_tx = 0; + remain_wifi_tx = 0; + break; + + case ( WIFI_LED_ON ): + LED_duty_WiFi = vreg_ctr[VREG_C_LED_BRIGHT]; + state_wifi_tx = 0; + remain_wifi_tx = 0; + break; + + case ( WIFI_LED_TXAUTO ): + if( flag_wifi_TX != 0 ) // 短いパルスを捕まえるために、割り込みフラグを見る { - vreg_ctr[ VREG_C_STATUS_1 ] |= REG_BIT_WIFI_TX; // 送信パターン switch ( state_wifi_tx ) { @@ -471,17 +381,12 @@ void tsk_led_wifi( ) else { // 送信フラグ待ち - vreg_ctr[ VREG_C_STATUS_1 ] &= ~REG_BIT_WIFI_TX; - if( vreg_ctr[VREG_C_LED_WIFI] == WIFI_LED_OFF ) - { - LED_duty_WiFi = 0; - } - else - { LED_duty_WiFi = vreg_ctr[VREG_C_LED_BRIGHT]; + task_interval = 200; + return; } - task_interval = 100; - return; + break; + } } @@ -489,62 +394,123 @@ void tsk_led_wifi( ) /* ======================================================== - お知らせLED + * 割り込みそのものは使いません * + LED_Wifi2 P24 (未) ======================================================== */ void tsk_led_notify( ) { -// static u8 task_interval; - static u8 time_to_next_frame; - static u8 frame; - static st_LED_dim_status LED_dim_status_info_R, LED_dim_status_info_G, LED_dim_status_info_B; + static u8 task_interval; + static u8 flg_char_space; + static u8 state_notify_led; // 点灯パターンの進行具合 + static u8 flag_wifi_TX; - if( vreg_ctr[VREG_C_BT_REMAIN] <= BATT_TH_EMPTY ) + + if( task_interval-- != 0 ) { - // 電池切れが優先する return; } - // 次のフレームに進める? - if( time_to_next_frame == 0 ) + switch ( vreg_ctr[VREG_C_LED_NOTIFY] ) { - st_info_LED_ptn temp; + case ( NOTIFY_LED_OFF ): + default: + LED_duty_NOTIFY = 0; + state_notify_led = 0; + flg_char_space = 0; + break; - time_to_next_frame = info_LED.info_LED.term; + case ( NOTIFY_LED_ON ): + LED_duty_NOTIFY = vreg_ctr[VREG_C_LED_BRIGHT]; + state_notify_led = 0; + flg_char_space = 0; + break; - frame += 1; - // 最後のフレームリピート - if( frame > NOTIFY_LED_TERM + info_LED.info_LED.last_loop ) + case ( NOTIFY_LED_PTN0 ): + // ゆっくりバースト + switch ( state_notify_led ) { - frame = 0; + case ( 1 ): + case ( 3 ): + case ( 5 ): + LED_duty_NOTIFY = vreg_ctr[VREG_C_LED_BRIGHT]; + break; + default: + LED_duty_NOTIFY = 0; } - - if( frame < NOTIFY_LED_TERM ) + state_notify_led++; + if( state_notify_led == 16 ) { - temp = info_LED.info_LED.ptn[ frame ]; - - LED_dim_status_info_R.to = temp.red * 128; - LED_dim_status_info_G.to = temp.grn * 128; - LED_dim_status_info_B.to = temp.blu * 128; - - // グラデーションのデルタを計算 - LED_dim_status_info_R.delta = (( LED_dim_status_info_R.to - LED_dim_status_info_R.now ) ) / info_LED.info_LED.fade_time; - LED_dim_status_info_G.delta = (( LED_dim_status_info_G.to - LED_dim_status_info_G.now ) ) / info_LED.info_LED.fade_time; - LED_dim_status_info_B.delta = (( LED_dim_status_info_B.to - LED_dim_status_info_B.now ) ) / info_LED.info_LED.fade_time; + state_notify_led = 0; } + task_interval = 50; + return; + case ( NOTIFY_LED_PTN1 ): + // データテーブルに従って点滅 + { + u8 dat; + + task_interval = MSG_SPD; // 共通のため。場合によって上書き + + if( flg_char_space != 0 ) + { + LED_duty_NOTIFY = 0; + flg_char_space = 0; + return; + } + + // データバッファの見る位置の更新 + dat = ( MSG_MAIL[state_notify_led / 4] << ( ( state_notify_led % 4 ) * 2 ) ) & 0xC0; + if( dat == 0 ) + { + state_notify_led = 0; + } + else + { + state_notify_led += 1; + } + + flg_char_space = 1; + if(( dat & 0b10000000 ) != 0 ) + { + // 点灯はさせる + LED_duty_NOTIFY = vreg_ctr[VREG_C_LED_BRIGHT]; + if(( dat & 0b01000000 ) == 0 ) + { + // 短 + // nothing to do + } + else + { + // 長 + task_interval = ( MSG_SPD * 3 ); + } + // 次は単語間休み、とかの判定をさせたかったが + /// 1バイトに2ビットずつデータが並んでおり、次のバイトに + /// またがるようなときが面倒なのでやめる + return; + } + else + { + if(( dat & 0b01000000 ) == 0 ) + { + // 一文終了 + task_interval = ( MSG_SPD * 3 ); + } + else + { + // 単語間 + // nothing to do + } + return; + } + } } - time_to_next_frame -= 1; - - led_fade_to2( LED_duty_notify_red, &LED_dim_status_info_R ); - led_fade_to2( LED_duty_notify_grn, &LED_dim_status_info_G ); - led_fade_to2( LED_duty_notify_blu, &LED_dim_status_info_B ); - } - /******************************************************//** LED_Cam TO02 \n BLINK,*_PLUSE の時は、1周期分は必ずその状態になります。 @@ -569,24 +535,24 @@ void tsk_led_cam( ) { case ( CAM_LED_OFF ): default: - LED_CAM = 0; + LED_duty_CAM = 0; state_led_cam = 0; break; case ( CAM_LED_ON ): - LED_CAM = 1; + LED_duty_CAM = vreg_ctr[VREG_C_LED_BRIGHT]; state_led_cam = 0; break; case ( CAM_LED_BLINK ): if( state_led_cam == 0 ) { - LED_CAM = 1; + LED_duty_CAM = vreg_ctr[VREG_C_LED_BRIGHT]; state_led_cam = 1; } else { - LED_CAM = 0; + LED_duty_CAM = 0; state_led_cam = 0; } task_interval = 250; @@ -595,7 +561,7 @@ void tsk_led_cam( ) case ( CAM_LED_ON_PLUSE ): if( state_led_cam == 0 ) { - LED_CAM = 1; + LED_duty_CAM = vreg_ctr[VREG_C_LED_BRIGHT]; state_led_cam = 1; task_interval = 250; } @@ -608,7 +574,7 @@ void tsk_led_cam( ) case ( CAM_LED_OFF_PLUSE ): if( state_led_cam == 0 ) { - LED_CAM = 0; + LED_duty_CAM = 0; state_led_cam = 1; task_interval = 250; } @@ -621,19 +587,19 @@ void tsk_led_cam( ) case ( CAM_LED_BY_TWL ): switch ( vreg_twl[ REG_TWL_INT_ADRS_CAM ] ){ // switchのネストとか… case( TWL_CAMLED_OFF ): - LED_CAM = 0; + LED_duty_CAM = 0; state_led_cam = 0; break; case( TWL_CAMLED_BLINK ): if( state_led_cam == 0 ) { - LED_CAM = 1; + LED_duty_CAM = vreg_ctr[VREG_C_LED_BRIGHT]; state_led_cam = 1; } else { - LED_CAM = 0; + LED_duty_CAM = 0; state_led_cam = 0; } task_interval = 250; @@ -642,7 +608,7 @@ void tsk_led_cam( ) case( TWL_CAMLED_ON ): case( TWL_CAMLED_DEF_ON ): default: - LED_CAM = 1; + LED_duty_CAM = vreg_ctr[VREG_C_LED_BRIGHT]; state_led_cam = 1; break; } @@ -650,4 +616,3 @@ void tsk_led_cam( ) return; } -#endif diff --git a/trunk/sdk0.9/led.h b/trunk/sdk0.9/led.h index 311eec7..db22719 100644 --- a/trunk/sdk0.9/led.h +++ b/trunk/sdk0.9/led.h @@ -1,43 +1,22 @@ #ifndef __led__ #define __led__ + // ==================================== - -#ifdef _MODEL_CTR_NOTIFY_FULLCOLOR_ - -// LED_DUTY -#define LED_duty_pow_blu TDR06 -#define LED_duty_WiFi TDR03 -#define LED_duty_3d TDR01 -#define LED_duty_notify_red TDR07 -#define LED_duty_notify_grn TDR05 -#define LED_duty_notify_blu TDR02 - -// これらはduty変えられません -#define LED_pow_red P7.5 -#define LED_CAM P4.2 - -#else - // LED_DUTY #define LED_duty_pow_L TDR07 -#define LED_duty_pow_blu TDR06 +#define LED_duty_pow_H TDR06 #define LED_duty_WiFi TDR03 #define LED_duty_NOTIFY TDR05 #define LED_duty_CAM TDR02 -#define LED_duty_3d TDR01 +#define LED_duty_TUNE TDR01 // wifi2はPWMできません。 -#endif +#define LED_BRIGHT_MAX 0x00FF -#define NOTIFY_LED_TERM 32 - - -#define LED_BRIGHT_MAX 0x0100 - // ==================================== #ifdef _MCU_BSR_ // 電波送信パルス #define WIFI_txLatch PIF21 @@ -71,7 +50,10 @@ enum LED_MODE_TUNE enum { WIFI_LED_OFF = 0, - WIFI_LED_ON + WIFI_LED_ON, + WIFI_LED_TXAUTO, + WIFI_LED_PTN0, + WIFI_LED_PTN1 }; @@ -99,56 +81,10 @@ enum -// お知らせLED調光関係 // -typedef struct{ - u8 red; - u8 grn; - u8 blu; -}st_info_LED_ptn; - -typedef struct{ - u8 term; // 1フレーム何チック? - u8 fade_time; // 何チックで次のフレームの色に達するか - u8 last_loop; // 最終フレームを - u8 resv1; - st_info_LED_ptn ptn[ NOTIFY_LED_TERM ]; -}st_info_LED; - -typedef union{ - st_info_LED info_LED; - u8 bindata[ sizeof( st_info_LED ) ]; -}uni_info_LED; - -extern uni_info_LED info_LED; - - - -typedef struct{ - u8 dats[4]; -}st_u8s4; - -typedef union{ - unsigned long bits; - st_u8s4 dats; -}uni_led_red_batt_empty; - - -extern uni_led_red_batt_empty led_red_batt_empty; - - -/* - お知らせLED -*/ -typedef struct{ - sx16 to; - sx16 delta; - sx16 now; // 小数点以下を覚えておかなくてはならないため -}st_LED_dim_status; - // ==================================== void LED_init( ); void LED_stop( ); -extern void tsk_led_cam(); + #endif diff --git a/trunk/sdk0.9/loader.c b/trunk/sdk0.9/loader.c index 90e4366..7ec6e79 100644 --- a/trunk/sdk0.9/loader.c +++ b/trunk/sdk0.9/loader.c @@ -57,6 +57,7 @@ static fsl_u08 fsl_MK2H_bak_u08; /* } void FSL_Open( void ); void FSL_Close( void ); void hdwinit( void ); +void power_save( ); static void hdwinit2( ); extern void main_loop( ); @@ -69,49 +70,40 @@ void main( ) while( 1 ) { WDT_Restart( ); - if( RTCEN ) // これは書き替えたときにしか使えない + if( RTCEN ) { system_status.reboot = 1; } + else if( ( RESF & 0x10 ) != 0) // WDRF,WDTでリセット + { + system_status.reboot = 1; +#ifdef _PMIC_TWL_ + // 暴走してしまうので再起動させる + PM_reset_ast(); + /// hdwinit2ないでリセット解除される。続きに続行してよい(頭痛が痛い的) +#endif + vreg_ctr[ VREG_C_MCU_STATUS ] |= REG_BIT_STATUS_WDT_RESET; + // set_irq( VREG_C_IRQ0, REG_BIT_IRQ_WDT_RESET ); + // ↑I2Cの初期化後に行う + hdwinit2( ); + } else { - u8 my_resf = RESF; // ←読むと消え、生存区間の関係 - if( ( my_resf & ( 0x10 | 0x80 ) ) != 0 ) - // 0x10 : WDRF,WDTでリセット - // 0x80 : TRAP - { - if( ( my_resf & 0x10 ) != 0 ) - { - IRQ0_neg; // 一瞬上げて落とし直す。 -#ifdef _PMIC_TWL_ - // 暴走してしまうので再起動させる - PM_reset_ast(); - /// hdwinit2 内で解除する -#endif - vreg_ctr[ VREG_C_MCU_STATUS ] |= REG_BIT_STATUS_WDT_RESET; - // set_irq( VREG_C_IRQ0, REG_BIT_IRQ_WDT_RESET ); - // ↑I2Cの初期化後に行う - } - system_status.reboot = 1; - } - else - { - // 通常の電源投入 - u8 pwup_delay0 = 0; - u8 pwup_delay1 = 0; + u8 pwup_delay0 = 0; + u8 pwup_delay1 = 0; + do + { // 電池接続時、16ms待ってみる(チャタリング対策) + pwup_delay0 += 1; do - { // 電池接続時、16ms待ってみる(チャタリング対策) - pwup_delay0 += 1; - do - { - pwup_delay1 += 1; - } - while( pwup_delay1 != 0 ); // u16にするとコンパイラが怒るんだが…。 + { + pwup_delay1 += 1; } - while( pwup_delay0 != 0 ); + while( pwup_delay1 != 0 ); // u16にするとコンパイラが怒るんだが…。 } - hdwinit2( ); + while( pwup_delay0 != 0 ); + + hdwinit2( ); } // ファームの整合性チェック // @@ -126,14 +118,8 @@ void main( ) comp += ( *( __far u8 * )( MGC_LOAD + i ) == *( u8 * )( MGC_FOOT + i ) ) ? 0 : 1; } - if( *( u8 * )( MGC_FOOT ) == 0xFF ) // 消去済のまま - { - comp += 1; - } - if( comp != 0 ) { - DBG_LED_WIFI_2_on // ファームリストアを試みる firm_restore( ); // 帰ってこない。リセットをかける。 @@ -147,6 +133,30 @@ void main( ) +/* ======================================================== + キーリターン割り込み + ======================================================== */ +__interrupt void int_kr( ) +{ +} + + + +/* ======================================================== + ext dc + ======================================================== */ +__interrupt void intp4( ) +{ +} + + +/* ======================================================== + shell close + ======================================================== */ +__interrupt void intp5( ) +{ +} + // ======================================================== @@ -190,12 +200,12 @@ void hdwinit2( ) P14 = 0b00000001; #endif #ifdef _MODEL_TS0_ - P0 = 0b00000011; + P0 = 0b00000001; P3 = 0b00000111; // 簡易I2Cは出力ラッチを1にする P14 = 0b00000000; #endif #ifdef _MODEL_CTR_ - P0 = 0b00000011; + P0 = 0b00000001; P3 = 0b00000111; // 簡易I2Cは出力ラッチを1にする P14 = 0b00000000; #endif @@ -236,18 +246,14 @@ void hdwinit2( ) PM2 = 0b11101001; #ifdef _PMIC_CTR_ -# ifdef _MODEL_CTR_NOTIFY_FULLCOLOR_ - PM4 = 0b11110011; -# else PM4 = 0b11110111; -# endif #else PM4 = 0b11111011; #endif - PM5 = 0b11110010; + PM5 = 0b11110011; PM6 = 0b11111100; // I2CのラインがL出力になってしまうが、システムがOFFなのでかまわない -#ifdef _PMIC_CTR_ +#ifdef _MODEL_CTR_ PM7 = 0b01011111; #else PM7 = 0b00011111; @@ -256,7 +262,11 @@ void hdwinit2( ) PM15 = 0b11111111; #ifdef _MCU_BSR_ +#ifdef _MODEL_CTR_ + PM20 = 0b11111101; +#else PM20 = 0b11111100; +#endif #else PM8 = 0b11111111; #endif @@ -272,24 +282,21 @@ void hdwinit2( ) PU14 = 0b00000000; #ifdef _MCU_BSR_ -# ifdef _MODEL_CTR_ -# ifdef _SW_HOME_ENABLE_ +#ifdef _MODEL_CTR_ +#ifdef _SW_HOME_ENABLE_ PU20 = 0b00010001; -# else +#else PU20 = 0b00000001; -# endif -# else +#endif +#else PU20 = 0b00000000; -# endif +#endif #endif // ポート入力モード・レジスタ設定 ///////////////////// // [0:通常入力バッファ 1:TTL入力バッファ] -#if 0 -// デフォルト値 PIM3 = 0b00000000; PIM7 = 0b00000000; -#endif // ポート出力モード・レジスタ設定 // [0:通常出力モード 1:N-chオープン・ドレーン出力] @@ -314,17 +321,16 @@ void hdwinit2( ) MK2L = 0xFF; #endif -#if 0 -// デフォルト値 - PR00 = 0xFFFF; /* 割り込み優先順位、全て低位(LV3) */ - PR01 = 0xFFFF; - PR10 = 0xFFFF; - PR11 = 0xFFFE; - // PR11H = 0b11111111; - // PR11L = 0b11111110; - PR02L = 0xFF; - PR12L = 0xFF; -#endif + PR00L = 0b11111111; /* 割り込み優先順位、全て低位(LV3) */ + PR10L = 0b11111111; + PR00H = 0b11111111; + PR10H = 0b11111111; + PR01L = 0b11111111; + PR11L = 0b11111110; + PR01H = 0b11111111; + PR11H = 0b11111111; + PR02L = 0b11111111; + PR12L = 0b11111111; /*--- 外部割込の有効エッジ設定 ---*/ #ifdef _MCU_BSR_ diff --git a/trunk/sdk0.9/loader.h b/trunk/sdk0.9/loader.h index e69de29..f5f5c9c 100644 --- a/trunk/sdk0.9/loader.h +++ b/trunk/sdk0.9/loader.h @@ -0,0 +1,4 @@ +#include "jhl_defs.h" + + +err firm_update( ); diff --git a/trunk/sdk0.9/magic.c b/trunk/sdk0.9/magic.c index 6faa3f7..c012cac 100644 --- a/trunk/sdk0.9/magic.c +++ b/trunk/sdk0.9/magic.c @@ -7,13 +7,13 @@ // V0.5 (ニセ0.1改) #pragma section @@CNSTL MGC_LOAD AT 0x0FF6 -__far const unsigned char MGC_LOAD[] = __TIME__; +__far static const unsigned char MGC_LOAD[] = __TIME__; #pragma section @@CNST MGC_MIMI AT 0x2100 -const unsigned char MGC_HEAD[] = __TIME__; +static const unsigned char MGC_HEAD[] = __TIME__; #pragma section @@CNST MGC_TAIL AT 0x4FF6 -const unsigned char MGC_TAIL[] = __TIME__; +static const unsigned char MGC_TAIL[] = __TIME__; // 0Dまでこれを使用 @@ -55,11 +55,11 @@ __far static const unsigned char MGC_LOAD[] = // V0.4以降 #pragma section @@CNSTL MGC_LOAD AT 0x0FF6 -__far const unsigned char MGC_LOAD[] = __TIME__; +__far static const unsigned char MGC_LOAD[] = __TIME__; #pragma section @@CNST MGC_MIMI AT 0x2100 -const unsigned char MGC_HEAD[] = __TIME__; +static const unsigned char MGC_HEAD[] = __TIME__; #pragma section @@CNST MGC_TAIL AT 0x47F6 -const unsigned char MGC_TAIL[] = __TIME__; +static const unsigned char MGC_TAIL[] = __TIME__; */ diff --git a/trunk/sdk0.9/main.c b/trunk/sdk0.9/main.c index d752b2d..388d7e0 100644 --- a/trunk/sdk0.9/main.c +++ b/trunk/sdk0.9/main.c @@ -15,8 +15,6 @@ #include "led.h" #include "adc.h" -#include "pool.h" - // ======================================================== static void read_dipsw( ); @@ -24,9 +22,10 @@ static void read_dipsw( ); // ======================================================== system_status_ system_status; -uni_pool pool; +bit update; +u16 pool[256]; // アップデート時のワークエリア 兼 歩数計データ /* ======================================================== 本当のエントリ関数は loader.c にあります ======================================================== */ @@ -41,6 +40,8 @@ void main_loop( void ) iic_mcu_start( ); EI( ); + PM_init(); + if( system_status.reboot ) { #ifdef _PMIC_TWL_ @@ -58,6 +59,9 @@ void main_loop( void ) system_status.pwr_state = OFF_TRIG; } +#ifdef _PARRADIUM_ + system_status.pwr_state = OFF; +#endif vreg_ctr_init( ); vreg_twl_init( ); diff --git a/trunk/sdk0.9/pedo_alg_thre_det2.c b/trunk/sdk0.9/pedo_alg_thre_det2.c index 7063071..44d64cf 100644 --- a/trunk/sdk0.9/pedo_alg_thre_det2.c +++ b/trunk/sdk0.9/pedo_alg_thre_det2.c @@ -1,11 +1,11 @@ /* ******************************************************** - 歩数計 - 3軸加速度のリアルタイムデータから、ベクトルのノルムを出し、 - 閾値を超える時間、間隔、ノルムの大きさで閾値を切り替えるなど + + + + ********************************************************* */ -#pragma mul -#pragma div -#pragma bcd +#pragma MUL +#pragma BCD #include "incs.h" #include @@ -13,25 +13,13 @@ #include "accero.h" #include "pedometer.h" -#include "pedo_lpf_coeff.h" -#include "pool.h" -// ======================================================== static void hosu_increment(); - - - -// ======================================================== u16 get_long_hour(); -extern uni_pool pool; -// ======================================================== -#define _use_my_sqrt_ -#ifdef _use_my_sqrt_ -unsigned long my_sqrt(); -#endif +extern u16 pool[]; @@ -57,23 +45,19 @@ void pedometer() u8 i; + signed long temp1,temp2,temp3; + signed long temp4,temp5,temp6; + u16 sx16 = abs( (u16)vreg_ctr[VREG_C_ACC_XH] * 256 + vreg_ctr[VREG_C_ACC_XL] ); u16 sy16 = abs( (u16)vreg_ctr[VREG_C_ACC_YH] * 256 + vreg_ctr[VREG_C_ACC_YL] ); u16 sz16 = abs( (u16)vreg_ctr[VREG_C_ACC_ZH] * 256 + vreg_ctr[VREG_C_ACC_ZL] ); // ベクトルのノルム #ifdef _mcu_ -# ifndef _use_my_sqrt_ norm_hist[ hist_indx & TAP-1 ] = sqrt( (long)sx16 * ( sx16 / 2 ) + (long)sy16 * ( sy16 / 2 ) + (long)sz16 * ( sz16 / 2 ) ); -# else - norm_hist[ hist_indx & TAP-1 ] = my_sqrt( (long)sx16 * ( sx16 / 2 ) + - (long)sy16 * ( sy16 / 2 ) + - (long)sz16 * ( sz16 / 2 ) - ); -# endif #endif #ifdef _pc_ @@ -218,7 +202,6 @@ static void hosu_increment() // 空白の時間を考慮する。1時間以上放置されたなど。 u16 now_hour; u8 now_year; - u8 now_min; // 時計を止める必要が有るので↓は一気に行って下さい DI(); @@ -228,7 +211,6 @@ static void hosu_increment() last_hour = HOUR; // 履歴読み出し時に使用。BCDのままでよい last_day = DAY; last_month = MONTH; - now_min = MIN; now_hour = get_long_hour(); // RWAIT = 0; ↑で行っています // EI(); 〃 @@ -261,26 +243,13 @@ static void hosu_increment() last_hour_fny = now_hour; // 実際にインクリメント + if( pool[ p_record ] == HOSU_NODATA ) { - u8 temp; - - temp = p_record; - if( now_min < vreg_ctr[ VREG_C_ACC_HOSU_ORIGIN ] ) - { - temp -= 1; - if( PEDOMETER_LOG_SIZE >= temp ) - { - temp = PEDOMETER_LOG_SIZE -1; - } - } - if( pool.vreg_c_ext.pedo_log[ temp ] == HOSU_NODATA ) - { - pool.vreg_c_ext.pedo_log[ temp ] = 1; - } - else if( pool.vreg_c_ext.pedo_log[ temp ] != HOSU_MAX ) - { - pool.vreg_c_ext.pedo_log[ temp ] += 1; - } + pool[ p_record ] = 1; + } + else if( pool[ p_record ] != HOSU_MAX ) + { + pool[ p_record ] += 1; } } } @@ -293,20 +262,16 @@ static void hosu_increment() ======================================================== */ void fill_hosu_hist_hours( u16 hours ) { - if( hours > PEDOMETER_LOG_SIZE ) + if( hours > 255 ) { - hours = PEDOMETER_LOG_SIZE; + hours = 0; } // 空白の数時間の設定 do { p_record += 1; - if( PEDOMETER_LOG_SIZE >= p_record ) - { - p_record = 0; - } - pool.vreg_c_ext.pedo_log[ p_record ] = 0; + pool[ p_record ] = 0; hours -= 1; } while( hours != 0 ); @@ -320,11 +285,12 @@ void fill_hosu_hist_hours( u16 hours ) ======================================================== */ void clear_hosu_hist() { - u8 hours = PEDOMETER_LOG_SIZE; + u8 hours = 0; + // 空白の数時間の設定 do { + pool[ hours ] = 0xFFFF; hours -= 1; - pool.vreg_c_ext.pedo_log[ hours ] = 0xFFFF; } while( hours != 0 ); vreg_ctr[ VREG_C_ACC_HOSU_L ] = 0; @@ -383,7 +349,7 @@ u8 hosu_read( ) return( 0xAA ); // reserved. dummy default: - temp = pool.vreg_c_ext.pedo_log[ p_record_buffer ]; + temp = pool[ p_record_buffer ]; if( record_read_msb_lsb == 0 ) { dat = (u8)( temp & 0x00FF ); @@ -391,14 +357,7 @@ u8 hosu_read( ) else { dat = (u8)(( temp >> 8 ) & 0x00FF ); - if( p_record_buffer == 0 ) - { - p_record_buffer = PEDOMETER_LOG_SIZE-1; - } - else - { - p_record_buffer -= 1; - } + p_record_buffer -= 1; } record_read_msb_lsb += 1; return( dat ); @@ -412,7 +371,7 @@ u8 hosu_read( ) 引数 無し 返値 u16 long_hour ======================================================== */ -const u16 DAYS_FROM_HNY[] = { +static const u16 DAYS_FROM_HNY[] = { 0, 0, 31, 31+28, 59+31, 90+30, 120+31, 151+30, 181+31, 212+31, 243+30, @@ -450,102 +409,3 @@ u16 get_long_hour() return( long_hour ); } - -# ifdef _use_my_sqrt_ -// ======================================================== -// 高速?平方根アルゴリズム -// ======================================================== -#if 0 -// 拝借もと -// ttp://www.finetune.co.jp/~lyuka/technote/fract/sqrt_hypot.html -/* NAME - * sqrtl - square root function - * SYNOPSYS - * long - * sqrtl(long x) - * DISCRIPTIONS - * The sqrtl() function compute the non-negative square root of x. - * ERROR - * Below 1/2 LSB. - * SEE ALSO - * sqrt(3), http://www.finetune.co.jp/~lyuka/fract/sqrt_hypot.html - * COPYRIGHT - * Copyright 2002, Takayuki HOSODA. All rights reserved. - */ -unsigned long my_sqrt( unsigned long a ) -{ - unsigned long x; - unsigned long t; - unsigned long s; - unsigned char scale; - - x = a; - if (x > 0) { - scale = 0; - if (x < 0x8000) { - x <<= 16; - scale = 8; - a = x; - } - x >>= 8; - s = 8; - for (t = 0x400000L; x < t; t >>= 2) - s--; - t = 88; - t <<= s; - x *= 22; - s += 5; - x >>= s; // -3.1e-2 < err < +2.9e-2 - /* 打ち切り - s = a; - t += x; - x = s; - s /= t; - s += t; - s >>= 1; // -4.8e-4 < err <= 0 - t = x; - x /= s; - x += s; - x >>= 1; // -1.2e-7 < err <= 0 - s = x; - s++; - s *= x; - if (t > s) // adjust LSB - x++; - */ - if (scale) { - x += 127; - x >>= 8; - } - } - return x; -} -#endif - - -#if 1 -// 拝借もと -// ttp://www001.upp.so-net.ne.jp/y_yutaka/labo/math_algo/math_algo.html -unsigned long my_sqrt(unsigned long x) -{ - unsigned long s, t; - - if (x <= 0) return 0; - - s = 1; - t = x; - while (s < t) - { - s <<= 1; - t >>= 1; - } - do - { - t = s; - s = (x / s + s) >> 1; - } while (s < t); - - return t; -} -#endif -#endif diff --git a/trunk/sdk0.9/pedometer.h b/trunk/sdk0.9/pedometer.h index 40caf2a..1dd1d03 100644 --- a/trunk/sdk0.9/pedometer.h +++ b/trunk/sdk0.9/pedometer.h @@ -2,21 +2,98 @@ #define _pedo_ -// ========================================================= void hosu_read_end( ); u8 hosu_read( ); void fill_hosu_hist_hours( u16 ); void clear_hosu_hist(); + + +// ========================================================= +#define TAP 64 +#define FIL_COEFF_QUANT 10 +static const s8 lpf_coeff[]={ +/* +Window Function Algorithm LPF +Sampling Frequency = 100.0 +cutoff1 = 6.0000000 +Tap Count =64 +Kaiser Constant = 7.000000 +Quantized by 11 [bits] + */ +/* 0,// [0] + 0, + 0, + 0, + 0, + 0, + 0, + 0, +*/ + 1,// 8 + 2, + 2, + 3, + 3, + 2, + 0, + -2, + -5,// 16 + -9, + -13, + -16, + -16, + -13, + -6, + 4, + 18,// 24 + 37, + 56, + 77, + 95, + 110, + 119, + 122, + 119,// 32 + 110, + 95, + 77, + 56, + 37, + 18, + 4, + -6,// 40 + -13, + -16, + -16, + -13, + -9, + -5, + -2, + 0,// 48 + 2, + 3, + 3, + 2, + 2, + 1, +/* + 0, + 0,// 56 + 0, + 0, + 0, + 0, + 0, + 0, + 0 +*/ +}; +// */ + +// ========================================================= + void pedometer(); - - - -// ========================================================= -#define PEDOMETER_LOG_SIZE ( 24 * 7 ) - - - -// ========================================================= +static void hosu_increment(); #endif diff --git a/trunk/sdk0.9/pm.c b/trunk/sdk0.9/pm.c index 4529e33..1cee974 100644 --- a/trunk/sdk0.9/pm.c +++ b/trunk/sdk0.9/pm.c @@ -16,8 +16,7 @@ #include #include "fsl_user.h" - - +extern u16 pool[]; // ======================================================== @@ -25,20 +24,197 @@ // ======================================================== u8 raw_adc_temperature; u8 rcomp; -// float temp_co_up; -// float temp_co_dn; -// 256倍してある -unsigned char temp_co_up; -unsigned char temp_co_dn; -BT_VENDER battery_manufacturer = BT_VENDER_NOT_CHECKED; - - +float temp_co_up; +float temp_co_dn; // ======================================================== +static void PM_get_batt_left(); + + +/******************************************************//** + PMIC達の初期化 +\n 電池メーカー識別 +\n 電池残量ICのセット +\n バージョン情報の取得 +\n +\n 以下のピンは主にここで操作・監視されます。 +\n ・PM_BT_DET,_P + *********************************************************/ +#define swap_endian_16( x ) (unsigned int)( x << 8 | x >> 8 ) + +void PM_init( ) +{ + u8 temp; + u8 origParam[4]; + union{ + u16 _u16; // ↓でわかるように、little endian です。注意。 + struct{ + u8 lsb; + u8 msb; + }chars; + }dat_16; + + system_status.model = MODEL_JIKKI; + wait_ms( 150 ); + + // -1. なんかおかしい… リセットをかけてみる + dat_16._u16 = swap_endian_16( 0x5400 ); // reset + iic_mcu_write( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_COMMAND, 2, &dat_16 ); // こいつはNACKを返す + + // 0. バッテリ残量IC クイックスタート + dat_16._u16 = swap_endian_16( 0x4000 ); // quick start + if( iic_mcu_write( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_MODE, 2, &dat_16 ) != ERR_SUCCESS ) + { + vreg_ctr[ VREG_C_STATUS_1 ] |= REG_BIT_GASGAUGE_ERR; + system_status.model = MODEL_TS_BOARD; + } + else + { + // 1. ロック解除 + dat_16._u16 = swap_endian_16( 0x4057 ); // unlock key + iic_mcu_write( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_LOCK, 2, &dat_16 ); + + // 2. 初期パラメータを一時保存 + iic_mcu_read( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_RCOMP, 4, origParam ); + + // 3. 一時的にOCVを変更 + dat_16._u16 = swap_endian_16( 0xD4C0 ); // マジックナンバー的なもの。メーカー指定 + iic_mcu_write( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_OCV, 2, &dat_16 ); + + // 4. 一時的にRCOMPを変更 + dat_16._u16 = swap_endian_16( 0xFF00 ); + iic_mcu_write( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_RCOMP, 2, &dat_16 ); + + // 電池メーカーの識別 + BT_DET_P = 1; + temp = ( u8 ) ( ( get_adc( ADC_SEL_BATT_DET ) >> 5 ) -1 ); // 識別値0の白箱の分、インデックス合わせ + BT_DET_P = 0; + + iic_mcu_set_wo_dma( ); + // 5.メーカー別パラメータのロード + switch ( temp ) + { + case( BT_VENDER_SHIROBAKO ): + system_status.model = MODEL_SHIROBAKO; + break; + + case( BT_VENDER_PANA ): + case( BT_VENDER_MAXELL ): + default: + iic_mcu_write( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_BT_PARAM, 64, &BT_PARAM[0] ); + rcomp = BT_PANA_RCOMP; + temp_co_up = BT_PANA_TEMPCOUP; + temp_co_dn = BT_PANA_TEMPCODN; + break; + } + + // 6. 150ms以上待つ + wait_ms( 200 ); + + // 7. OCVに「とある値」を書く + dat_16._u16 = swap_endian_16( 0xD4C0 ); + iic_mcu_write( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_OCV, 2, &dat_16 ); + + // 8. 150〜600ms待つ。600msは厳守 + wait_ms( 200 ); + + // 9. SOCを読む。ベリファイのため。 + temp = iic_mcu_read_a_byte( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_SOC ); + + if( 0x6D == temp || temp == 0x6E || temp == 0x6F ){ + // カスタムモデル書き込みOK! + }else{ + // 失敗だったらリトライするのか? + } + + // 10.元のRCOMPとOCVを書き戻す + iic_mcu_write( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_RCOMP, 4, origParam ); + + // 11. ロック + dat_16._u16 = swap_endian_16( 0x0000 ); // lock key + iic_mcu_write( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_LOCK, 2, &dat_16 ); + + // おしまい // + } + + // 電池温度測定 + BT_TEMP_P = 1; // 電池温度監視スタート + raw_adc_temperature = get_adc( ADC_SEL_BATT_TEMP ); // 温度のtemp。 + renge_task_immed_add( PM_bt_temp_update ); + + // PMIC バージョン読み出し +// temp = iic_mcu_read_a_byte( IIC_SLA_PMIC, PM_REG_ADRS_VER ); +// vreg_ctr[ VREG_C_PM_INFO ] = temp; +// デバッグ用は別にまとめた +} + + + + + + +/* ======================================================== + raw_adc_temperatureに入っている値を℃に変換するとともに、 + ・レジスタにセット + ・残量ICにセット + todo + ======================================================== */ +task_status_immed PM_bt_temp_update( ) +{ + static u8 count = 0; // たまにしか書きに行かない + + static u8 rawdat_old; + static s16 temperature; // todo + u16 newrcomp; + +/* + サーミスタ - 10kΩ分圧点の時、 + 常用温度では分圧比のカーブがほぼリニアで、 + 村田 T[℃] = 81.48 - 111.97 x ratio + TDK T = 81.406 - 111.81 x ratio +*/ + if( rawdat_old != raw_adc_temperature ){ + DBG_P_n = 1; + temperature = 81.45 - 111.9 * raw_adc_temperature/256.0; + vreg_ctr[VREG_C_BT_TEMP] = (u8)temperature; + DBG_P_n = 0; + } + + // 時々書きにゆく + if( count == 0 ) + { + DBG_P_n = 1; + if( vreg_ctr[VREG_C_BT_TEMP] > 20 ) + { + newrcomp = -( ( temperature - 20 ) * temp_co_up ); + } + else + { + newrcomp = -( ( temperature - 20 ) * temp_co_dn ); + } + newrcomp += rcomp; + + newrcomp = swap_endian_16( (u16)newrcomp ); + DBG_P_n = 0; + + if( iic_mcu_write + ( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_RCOMP, 2, &newrcomp ) == ERR_SUCCESS ) + { + rawdat_old = raw_adc_temperature; + } + } + count += 1; + + return ( ERR_SUCCESS ); +} + + + #ifdef _PMIC_TWL_ u8 blset; #endif +#ifndef _PARRADIUM_ /* ======================================================== 液晶系の電源制御  ステータスフラグはすぐに立ててしまう。 @@ -62,6 +238,9 @@ err PM_LCD_on( ) PM_VCS_on( ); wait_ms( DELAY_PM_VCS_TO_BL ); +#ifdef _PM_BUG_ + iic_mcu_write_a_byte( IIC_SLA_PMIC, 0x22, 0x4A ); // バグ持ちPMIC対策 +#endif rv = PM_chk_LDSW( ); @@ -71,7 +250,7 @@ err PM_LCD_on( ) vreg_ctr[VREG_C_STATUS] |= REG_BIT_LCD_POW; set_irq( VREG_C_IRQ3, REG_BIT_LCD_ON ); - SND_DEPOP_SND_ENABLE; + SND_DEPOP_DEACT; // 1でミュート } #ifdef _PMIC_TWL_ @@ -84,9 +263,7 @@ err PM_LCD_on( ) // BSR // void PM_LCD_off() { - u8 temp; - - SND_DEPOP_SND_MUTE; + SND_DEPOP_ACT; // BLついてたら消す #ifdef _PMIC_TWL_ @@ -116,14 +293,12 @@ void PM_LCD_off() blset = 0; #endif - if( iic_mcu_read_a_byte( IIC_SLA_PMIC, PM_REG_ADRS_VDD_LCD ) != 0 ) - { - PM_TCOM_VCS_off( ); - wait_ms( DELAY_PM_LCD_OFF ); + PM_TCOM_VCS_off( ); + wait_ms( DELAY_PM_LCD_OFF ); + + PM_VDDLCD_off( ); // 残ってたの全部止めます。 + vreg_ctr[VREG_C_STATUS] &= ~REG_BIT_LCD_POW; - PM_VDDLCD_off( ); // 残ってたの全部止めます。 - vreg_ctr[VREG_C_STATUS] &= ~REG_BIT_LCD_POW; - } set_irq( VREG_C_IRQ3, REG_BIT_LCD_OFF ); } @@ -183,7 +358,7 @@ SoC } */ vreg_ctr[VREG_C_STATUS] = (( vreg_ctr[VREG_C_STATUS] & 0b10011111 ) - | ( (( blset << 6 ) | ( blset << 4 )) & 0b01100000 )); + | (( blset << 6 ) | ( blset << 4 )) & 0b01100000 ); // PMICのBLのビットと、MCUのSTATUSレジスタのビット位置が逆なため入れ替え { @@ -203,7 +378,7 @@ SoC if( blset != 0 ) // BLを付ける場合はウェイトを挟まないとPWMが来ておらず /// シャットダウンすることがある { - wait_ms( 16 ); + wait_ms( 10 ); } iic_mcu_write_a_byte( IIC_SLA_PMIC, PM_REG_ADRS_BL, blset ); @@ -220,13 +395,53 @@ err PM_LCD_vcom_set( ) { u8 rv; - rv = iic_mcu_write_a_byte( IIC_SLA_PMIC, PM_REG_ADRS_POW_DAC1, vreg_ctr[VREG_C_VCOM_T] ); // がっかりなことに、PMICはバースト書き込み不可 + rv = iic_mcu_write_a_byte( IIC_SLA_PMIC, PM_REG_ADRS_POW_DAC1, vreg_ctr[VREG_C_VCOM_T] ); // がっかりなことに、PMICはバースト書き込み不可 rv |= iic_mcu_write_a_byte( IIC_SLA_PMIC, PM_REG_ADRS_POW_DAC2, vreg_ctr[VREG_C_VCOM_B] ); return ( rv ); } +#else +// パラディウム上のSoCでチェックしたいとき、PMICも液晶もつながってないので +// 異常終了しないようにダミー関数にする +err PM_LCD_on( ) +{ + vreg_ctr[VREG_C_STATUS] |= REG_BIT_LCD_POW; + set_irq( VREG_C_IRQ3, REG_BIT_LCD_ON ); + SND_DEPOP_DEACT; // 1でミュート + return ( ERR_SUCCESS ); +} + + +void PM_LCD_off( ) +{ + SND_DEPOP_ACT; + vreg_ctr[VREG_C_STATUS] &= ~REG_BIT_LCD_POW; + set_irq( VREG_C_IRQ3, REG_BIT_LCD_OFF ); +} + + +err PM_BL_set( u8 ) +{ + wait_ms( 10 ); + vreg_ctr[VREG_C_STATUS] = ( vreg_ctr[VREG_C_STATUS] & ~( REG_BIT_BL_U | REG_BIT_BL_L ) + | ( command_bl_set & REG_BIT_CMD_BL_U_ON )? REG_BIT_BL_U + | ( command_bl_set & REG_BIT_CMD_BL_L_ON )? REG_BIT_BL_L + ); + return ( PM_chk_LDSW( ) ); +} + + +err PM_LCD_vcom_set( ) +{ + return ( ERR_SUCCESS ); +} + +#endif + + + /* ======================================================== ↑で、レジスタ書き込みから呼び出される時のため  I2Cの取り合いの関係でここから呼ぶ @@ -250,54 +465,65 @@ task_status_immed tski_vcom_set( ) err PM_sys_pow_on( ) { #ifdef _PMIC_CTR_ + u8 temp; + + // 電池温度測定 + while( ADCEN != 0 ) + {; + } + BT_TEMP_P = 1; + vreg_ctr[VREG_C_BT_TEMP] = get_adc( ADC_SEL_BATT_TEMP ); + BT_TEMP_P = 0; + PM_bt_temp_update( ); // 温度のtemp。 残量ICに行きます + + // 残量チェック + PM_get_batt_left(); // 先に、PM_init()が実行されている必要があります。(大丈夫) + // todo: batt remain -> volatage? + if( vreg_ctr[VREG_C_BT_REMAIN] < 0 ) + { + return ( 1 ); + } // 電源順次立ち上げ // PM_reset_ast( ); 不要 PM_LDSW_onまかせ RESET2_ast; FCRAM_RST_ast; - GYRO_CS_DISABLE(); PM_LDSW_on( ); wait_ms( 1 ); +#ifdef _PM_BUG_ + iic_mcu_write_a_byte( IIC_SLA_PMIC, 0x22, 0xCA ); // バグ持ちPMIC対策 OVP解除 +#endif wait_ms( DELAY_PM_TW_PWUP ); - PM_VDD_normMode(); PM_VDD_on( ); -// wait_ms( DELAY_PM_TW_PWUP ); // gyro_csを挟むため - wait_ms( 10 ); - GYRO_CS_ENABLE(); - wait_ms( DELAY_PM_TW_PWUP - 10 ); + wait_ms( DELAY_PM_TW_PWUP ); PM_VDD50A_on( ); // 液晶電源ではなく、ledとかに使うものです wait_ms( DELAY_PM_TW_PWUP ); - // 無事電源が起動したかチェック。 -#ifdef _PMIC_CTR_ - if( !PM_chk_LDSW() ) - { - return ( ERR_ERR ); // reset1はほっといて良い - } - PM_reset_neg(); -#else - RESET1_neg; - if( !RESET1_n ) - { - RESET1_ast; - return ( ERR_ERR ); // reset1はほっといて良い - } + PM_VDD_normMode(); +#ifdef _PM_BUG_ + iic_mcu_write_a_byte( IIC_SLA_PMIC, PM_REG_ADRS_POW_SAVE, 0x03 ); // バグ持ちPMIC対策 強制PWM #endif + if( PM_chk_LDSW( ) == 0 ) + { + return ( ERR_ERR ); + } FCRAM_RST_neg; + PM_reset_neg(); RESET2_neg; - +/* wait_ms( 100 ); { // CODEC 不定レジスタ初期化 u8 codec_reg_init[3] = { 0,0,0 }; iic_mcu_write( IIC_SLA_CODEC, CODEC_REG_PM, 3, codec_reg_init ); } +*/ #else // TWL PMIC @@ -332,11 +558,12 @@ err PM_sys_pow_on( ) FCRAM_RST_ast; return ( ERR_ERR ); } - +/* { // CODEC 不定レジスタ初期化 u8 codec_reg_init[3] = { 0,0,0 }; iic_mcu_write( IIC_SLA_CODEC, CODEC_REG_PM, 3, codec_reg_init ); } +*/ #endif return ( ERR_SUCCESS ); @@ -345,29 +572,26 @@ err PM_sys_pow_on( ) + + + /* ======================================================== 電源OFFシーケンス + todo: 電源異常断の場合 ======================================================== */ err PM_sys_pow_off( ) { #ifdef _PMIC_CTR_ -// if( RESET1_n ) - if( PM_chk_LDSW() ) - { - // 異常時は呼ばない - PM_BL_set( REG_BIT_CMD_BL_U_OFF | REG_BIT_CMD_BL_L_OFF ); - PM_LCD_off( ); // TCOM,VCS OFF も消してきます。 - wait_ms( 50 + 10 ); - - PM_reset_ast( ); - } +// PM_BL_set( REG_BIT_CMD_BL_U_OFF | REG_BIT_CMD_BL_L_OFF ); +// PM_LCD_off( ); // TCOM,VCS OFF も消してきます。 + PM_reset_ast( ); RESET2_ast; FCRAM_RST_ast; -// PM_off( ); ↓まとめて落としてしまえ - PM_LDSW_off( ); + PM_off( ); + PM_LDSW_off( ); #else if( RESET1_n ) @@ -391,6 +615,106 @@ err PM_sys_pow_off( ) +/* ======================================================== + 電池の管理 + + 以下のピンは主にここで操作・監視されます。 + ・PM_BT_AUTH 現状、GPI in + ・PM_CHARGE_n CCIC /CHG in + ・PM_CHARGE_ERR_n /FLT in + ・PM_EXTDC_n /DOK INTP4 in + ・PM_CHARGE_EN_n /CEN out + + 以下の物は関係ありそうですが別のところで主に監視されています。 + ・LED_Pow R, B, Charge tsk_LED + ・BT_TEMP,_P tsk_ADC + + PM_EXTDCは割り込みメインにするかも + ======================================================== */ +#define INTERVAL_TSK_BATT 250 + +void tsk_batt( ) +{ + static u8 task_interval = 0; + static u8 charge_hys = 0; // ヒステリシスで上限下限を拡張するとき1 + static bit pm_extdc_old; + + if( task_interval-- != 0 ) + { + return; + } + else + { + task_interval = (u8)( INTERVAL_TSK_BATT / SYS_INTERVAL_TICK ); + } + + + // アダプタ? // + if( pm_extdc_old != !PM_EXTDC_n ) + { + pm_extdc_old = !PM_EXTDC_n; + if( pm_extdc_old ) + { + set_bit( 1, vreg_ctr[VREG_C_STATUS], REG_BIT_POW_SUPPLY ); + set_irq( VREG_C_IRQ1, REG_BIT_BT_DC_CONNECT ); + } + else + { + set_bit( 0, vreg_ctr[VREG_C_STATUS], REG_BIT_POW_SUPPLY ); + set_irq( VREG_C_IRQ1, REG_BIT_BT_DC_DISC ); + } + } + + + // 充電 /////////////////////////// + // 温度付きヒステリシス + if( vreg_ctr[VREG_C_BT_TEMP] < 0x36 ) + { + charge_hys = 1; + } + + if( ( 1 < vreg_ctr[VREG_C_BT_TEMP] ) + && ( vreg_ctr[VREG_C_BT_TEMP] < 0x2C ) ) + { + charge_hys = 0; + } + + if( ( ( charge_hys == 1 ) + && ( 1 < vreg_ctr[VREG_C_BT_TEMP] ) + && ( vreg_ctr[VREG_C_BT_TEMP] < 0x2C ) ) + || + ( ( charge_hys == 0 ) + && ( vreg_ctr[VREG_C_BT_TEMP] < 0x36 ) ) ) + { +#ifndef _MODEL_WM0_ + BT_CHG_ENABLE(); // 温度範囲OKで充電再開 + } + else + { + BT_CHG_DISABLE(); // 温度危険! 充電停止 +#endif + } +#ifdef _MODEL_WM0_ +// CHG_ENABLEピンは /WL_RST に配線されているので +#endif + + // 充電 // + // →割り込み。miscの中でよろしくやってくれている。 + set_bit( !BT_CHG_n, vreg_ctr[VREG_C_STATUS], REG_BIT_BATT_CHARGE ); + LED_CHARGE = !BT_CHG_n ? 1 : 0; + + + // 電池残量 // + PM_get_batt_left(); + + // dubug monitor + + return; +} + + + + /*========================================================= extDC割り込み 電源OFFから起こす(充電の温度監視のため)のみ @@ -426,7 +750,9 @@ __interrupt void intp6_PM_irq( ) } -#define _type1_ + +extern u8 temp_debug_3; + /* ======================================================== PMICからの割り込みを受けて、NTR PMIC互換レジスタからリード ======================================================== */ @@ -450,19 +776,13 @@ task_status_immed ntr_pmic_comm( ) { if( ( reg_shadow & REG_BIT_TWL_REQ_BL_U ) == 0 ) // 消えた { -#ifdef _type1_ - irq_work = REG_BIT_TWL_BL_U_OFF; -#else +// irq_work = REG_BIT_TWL_BL_U_OFF; set_irq( VREG_C_IRQ2, REG_BIT_TWL_BL_U_OFF ); -#endif } else { -#ifdef _type1_ - irq_work = REG_BIT_TWL_BL_U_ON; -#else +// irq_work = REG_BIT_TWL_BL_U_ON; set_irq( VREG_C_IRQ2, REG_BIT_TWL_BL_U_ON ); -#endif } } @@ -471,26 +791,18 @@ task_status_immed ntr_pmic_comm( ) { if( ( reg_shadow & REG_BIT_TWL_REQ_BL_L ) == 0 ) // 消えた { -#ifdef _type1_ - irq_work |= REG_BIT_TWL_BL_L_OFF; -#else +// irq_work = REG_BIT_TWL_BL_L_OFF; set_irq( VREG_C_IRQ2, REG_BIT_TWL_BL_L_OFF ); -#endif } else { -#ifdef _type1_ - irq_work |= REG_BIT_TWL_BL_L_ON; -#else +// irq_work = REG_BIT_TWL_BL_L_ON; set_irq( VREG_C_IRQ2, REG_BIT_TWL_BL_L_ON ); -#endif } } - vreg_ctr[ VREG_C_STATUS_1 ] = ( vreg_ctr[ VREG_C_STATUS_1 ] & ~0x0C ) | ( reg_shadow & 0x0C ); // TWLバックライト情報のミラー - -#ifdef _type1_ - irq_work &= ~vreg_ctr[ VREG_C_IRQ_MASK2 ]; +#if 0 + irq_work &= ~VREG_C_IRQ_MASK2; // set_irq 相当品 if( irq_work != 0 ) { @@ -526,11 +838,10 @@ task_status_immed ntr_pmic_comm( ) // リセットリクエスト ///////////////////////////////// if( ( reg_shadow & REG_BIT_TWL_REQ_RST_REQ ) != 0 ) { -#if 0 // CODECバグ回避 // リセット単品でなかったら無視 - if( ( reg1_old ^ reg_shadow ) == REG_BIT_TWL_REQ_RST_REQ ) -#endif +// codec 修正済↓ +// if( ( reg1_old ^ reg_shadow ) == REG_BIT_TWL_REQ_RST_REQ ) { set_irq( VREG_C_IRQ2, REG_BIT_TWL_RESET_REQ ); } @@ -548,6 +859,43 @@ task_status_immed ntr_pmic_comm( ) +/********************************************************** + 電池残量ICから残量を取得し、レジスタに書き込む。 +  電池残量ICが無い・故障などの時はとりあえず残量99%とする。 +         ↑は status_1で確認可能。電源投入時にチェックしています。 +  PM_init()が実行されている必要があります。 +**********************************************************/ +static void PM_get_batt_left(){ + if(( vreg_ctr[ VREG_C_STATUS_1 ] & REG_BIT_GASGAUGE_ERR ) == 0 ) + { + // 電池残量の取得 + { + u8 temp[2]; + + iic_mcu_read( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_SOC, 2, temp ); + + vreg_ctr[ VREG_C_BT_REMAIN ] = temp[0]; + vreg_ctr[ VREG_C_BT_REMAIN_FINE ] = temp[1]; + // todo 閾値を超えたら割り込み + } + + vreg_ctr[ VREG_C_BT_VOLTAGE ] = iic_mcu_read_a_byte( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_VCELL ); + } + else + { + vreg_ctr[ VREG_C_BT_REMAIN ] = 99; + } + + // PMIC-NTRに電池残量を教えてあげる + iic_mcu_write_a_byte( IIC_SLA_CODEC, CODEC_REG_BT, + ( vreg_ctr[ VREG_C_BT_REMAIN ] < 5 )? 1 : 0 ); // 1で電池切れ + +} + + + + + /********************************************************** command2 液晶系   ラッパー的な物。ERR_SUCCESSしか返さないが… @@ -573,447 +921,10 @@ task_status_immed tski_PM_BL_set() cmd_BL = vreg_ctr[VREG_C_COMMAND2]; PM_BL_set( cmd_BL ); // マスク済み } - while( cmd_BL != vreg_ctr[VREG_C_COMMAND2] ); // <- PM_BL_setが更新する + while( cmd_BL != vreg_ctr[VREG_C_COMMAND2] ); vreg_ctr[VREG_C_COMMAND2] = 0; return( ERR_SUCCESS ); } - - - - -/* ======================================================== - 電池の管理 - - 以下のピンは主にここで操作・監視されます。 - ・PM_BT_AUTH 現状、GPI in - ・PM_CHARGE_n CCIC /CHG in - ・PM_CHARGE_ERR_n /FLT in - ・PM_EXTDC_n /DOK INTP4 in - ・PM_CHARGE_EN_n /CEN out - - 以下の物は関係ありそうですが別のところで主に監視されています。 - ・LED_Pow R, B, Charge tsk_LED - ・BT_TEMP,_P tsk_ADC - - PM_EXTDCは割り込みメインにするかも - ======================================================== */ -#define INTERVAL_TSK_BATT 250 - -void tsk_batt( ) -{ - static u8 task_interval = 0; - static u8 temp_zone_charge_enable = 0; // 温度で充電停止する時にヒステリシスを付けるため - static bit pm_extdc_old; - - if( task_interval-- != 0 ) - { - return; - } - else - { - task_interval = (u8)( INTERVAL_TSK_BATT / SYS_INTERVAL_TICK ); - } - - - // アダプタ? ///////////////////// - if( pm_extdc_old != !PM_EXTDC_n ) - { - pm_extdc_old = !PM_EXTDC_n; - if( pm_extdc_old ) - { - set_bit( 1, vreg_ctr[VREG_C_STATUS], REG_BIT_POW_SUPPLY ); - set_irq( VREG_C_IRQ1, REG_BIT_BT_DC_CONNECT ); - } - else - { - set_bit( 0, vreg_ctr[VREG_C_STATUS], REG_BIT_POW_SUPPLY ); - set_irq( VREG_C_IRQ1, REG_BIT_BT_DC_DISC ); - } - } - -#if 0 - // 充電 /////////////////////////// - // 温度付きヒステリシス - if(( 86 < vreg_ctr[VREG_C_BT_TEMP] ) - && ( vreg_ctr[VREG_C_BT_TEMP] < 185 )) - { - temp_zone_charge_enable = 1; // 充電許可 - } - else if(( vreg_ctr[VREG_C_BT_TEMP] < 70 ) - || ( 189 < vreg_ctr[VREG_C_BT_TEMP] )) - { - temp_zone_charge_enable = 0; // 充電禁止 - } - else - { - // temp_zone_charge_enable そのまま - } - - if(( temp_zone_charge_enable == 1 ) - && ( battery_manufacturer <= BT_VENDER_6 )) - { -# ifndef _MODEL_WM0_ -// CHG_ENABLEピンは /WL_RST に配線されているので - BT_CHG_ENABLE(); // 温度範囲OKで充電再開 - } - else - { - BT_CHG_DISABLE(); // 温度危険! 充電停止 -# endif - } - -#else - - // 温度無視して充電 -# ifndef _MODEL_WM0_ -// CHG_ENABLEピンは /WL_RST に配線されているので - BT_CHG_ENABLE(); // 温度範囲OKで充電再開 -# endif - -#endif - - // 充電 // - // →割り込み。miscの中でよろしくやってくれている。 - set_bit( !BT_CHG_n, vreg_ctr[VREG_C_STATUS], REG_BIT_BATT_CHARGE ); - LED_CHARGE = !BT_CHG_n ? 1 : 0; - - // 電池残量 // - if( system_status.pwr_state == ON ) - { - BT_get_left(); - } - - return; -} - - - -/******************************************************** -電池関係の初期化 - -   ゲージ  | 有り | 無し -  ーーーーーーーーーーーーーーーーーーーーーーー -   電池 有り| 実機 | 実機(ゲージ故障) -  ーーーーーーーーーーーーーーーーーーーーーーー -      無し| 白箱 | TS -        | 実機 | -  ーーーーーーーーーーーーーーーーーーーーーーー - -  ゲージ有り、電池無し の白箱/実機判別は、 - 電池温度で判定する - -***********************************************************/ -#define swap_endian_16( x ) (unsigned int)(( x << 8 ) | ( x >> 8 )) -void BT_init( ) -{ - u8 temp; - u8 origParam[4]; - union{ - u16 _u16; // ↓でわかるように、little endian です。注意。 - struct{ - u8 lsb; - u8 msb; - }chars; - }dat_16; - - - - // 電池温度測定(TS,白箱判定も兼ねる) // - while( ADCEN != 0 ) - { - NOP(); - } - raw_adc_temperature = get_adc( ADC_SEL_BATT_TEMP ); - - // 電池メーカーの識別 - temp = get_adc( ADC_SEL_BATT_DET ); - BT_DET_P = 0; - if( temp > 233 ) - battery_manufacturer = BT_VENDER_OPEN; - else if( temp > 197 ) - battery_manufacturer = BT_VENDER_6; - else if( temp > 158 ) - battery_manufacturer = BT_VENDER_PANA; - else if( temp > 123 ) - battery_manufacturer = BT_VENDER_4; - else if( temp > 79 ) - battery_manufacturer = BT_VENDER_3; - else if( temp > 33 ) - battery_manufacturer = BT_VENDER_2; - else if( temp > 5 ) - battery_manufacturer = BT_VENDER_1; - else - battery_manufacturer = BT_VENDER_MAXELL; - - - /* - // -1. なんかおかしい… リセットをかけてみる - dat_16._u16 = swap_endian_16( 0x5400 ); // reset - iic_mcu_write( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_COMMAND, 2, &dat_16 ); // こいつはNACKを返す - */ - -/* - // 0. バッテリ残量IC クイックスタート - dat_16._u16 = swap_endian_16( 0x4000 ); // quick start - iic_mcu_write( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_MODE, 2, &dat_16 ) -*/ - - // 1. ロック解除 - dat_16._u16 = swap_endian_16( 0x4A57 ); // unlock key - if( iic_mcu_write( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_LOCK, 2, &dat_16 ) == ERR_SUCCESS ) - { - vreg_ctr[ VREG_C_STATUS_1 ] &= ~REG_BIT_GASGAUGE_ERR; - // 残量IC有り // - if( battery_manufacturer < BT_VENDER_OPEN ) - { - // 電池何かしらあり // - system_status.model = MODEL_JIKKI; - } - else - { - // 電池無し // - if( raw_adc_temperature < 4 ) - { - // 白箱 // - system_status.model = MODEL_SHIROBAKO; - } - else - { - // 実機、バッテリ無し - system_status.model = MODEL_JIKKI_NOBATT; - } - } - } - else - { - vreg_ctr[ VREG_C_STATUS_1 ] |= REG_BIT_GASGAUGE_ERR; - // 残量IC NACK - if( raw_adc_temperature > 0xF0 ) - { - // TS // - system_status.model = MODEL_TS_BOARD; - } - else - { - // 実機、残量IC NACK( バッテリ無しまたは残量IC故障 ) - // 現状では、起動はさせとくが… - // todo? - system_status.model = MODEL_JIKKI; - } - } - - if( system_status.model == MODEL_JIKKI ) - { - // wait_ms( 5 + 1 ); I2C_mの初期化時にウェイト入れてるので不要 - - // 2. 初期パラメータを一時保存 - iic_mcu_read( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_RCOMP, 4, origParam ); - - // 3. 一時的にOCVを変更 - dat_16._u16 = swap_endian_16( 0xDA20 ); // マジックナンバー的なもの。メーカー指定 - iic_mcu_write( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_OCV, 2, &dat_16 ); - - // 4. 一時的にRCOMPを変更 - dat_16._u16 = swap_endian_16( 0xFF00 ); - iic_mcu_write( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_RCOMP, 2, &dat_16 ); - - // 5.メーカー別パラメータのロード - { - iic_mcu_set_wo_dma( ); - iic_mcu_write( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_BT_PARAM, 64, &BT_PARAM[ battery_manufacturer ] ); - rcomp = BT_PANA_RCOMP; - temp_co_up = BT_PANA_TEMPCOUP; - temp_co_dn = BT_PANA_TEMPCODN; - } - - // 6. 150ms以上待つ - wait_ms( 150 + 15 ); - - // 7. OCVに「とある値」を書く - dat_16._u16 = swap_endian_16( 0xDA20 ); - iic_mcu_write( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_OCV, 2, &dat_16 ); - - // 8. 150〜600ms待つ。600msは厳守 - wait_ms( 150 + 15 ); - - // 9. SOCを読む。ベリファイのため。 - temp = iic_mcu_read_a_byte( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_SOC ); - - if( 1 ){ - // カスタムモデル書き込みOK! - }else{ - // 失敗だったらリトライするのか? - } - - // 10.元のRCOMPとOCVを書き戻す - iic_mcu_write( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_RCOMP, 4, origParam ); - - // 11. ロック - dat_16._u16 = swap_endian_16( 0x0000 ); // lock key - iic_mcu_write( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_LOCK, 2, &dat_16 ); - - // おしまい // - BT_temp_update( ); // 温度のtemp。 残量ICに行きます - } - - - // どの機体で走ってても不可を同じくらいにするため、ADCタスクを登録 - // 電池温度監視スタート - raw_adc_temperature = get_adc( ADC_SEL_BATT_TEMP ); // 温度のtemp。 - renge_task_immed_add( BT_temp_update ); - - // PMIC バージョン読み出し - // temp = iic_mcu_read_a_byte( IIC_SLA_PMIC, PM_REG_ADRS_VER ); - // vreg_ctr[ VREG_C_PM_INFO ] = temp; - /// デバッグ用は別にまとめた -} - - - - - - -/* ======================================================== - raw_adc_temperatureに入っている値を℃に変換するとともに、 - ・レジスタにセット - ・残量ICにセット - todo - ======================================================== */ -task_status_immed BT_temp_update( ) -{ - static u8 count = 0; // たまにしか書きに行かない - - static u8 rawdat_old; -// static s16 temperature; // todo - static unsigned long temperature; // todo - u16 newrcomp; - -/* - サーミスタ - 10kΩ分圧点の時、 - 常用温度では分圧比のカーブがほぼリニアで、 - 村田 T[℃] = 81.48 - 111.97 x ratio - TDK T = 81.406 - 111.81 x ratio -*/ - if( rawdat_old != raw_adc_temperature ){ - DBG_P_n = 1; -// temperature = 81.45 - 111.9 * raw_adc_temperature/256.0; - // それぞれ256倍してある - temperature = 20851 - 28646 * raw_adc_temperature; - vreg_ctr[VREG_C_BT_TEMP] = (u8)temperature / 256; - DBG_P_n = 0; - } - - // 時々書きにゆく - if( count == 0 ) - { - DBG_P_n = 1; - if( vreg_ctr[VREG_C_BT_TEMP] > 20 ) - { - newrcomp = -( ( temperature - 20 ) * temp_co_up )/256; - } - else - { - newrcomp = -( ( temperature - 20 ) * temp_co_dn )/256; - } - newrcomp += rcomp; - - newrcomp = swap_endian_16( (u16)newrcomp ); - // todo - newrcomp = 0x9700; - - DBG_P_n = 0; - - if( iic_mcu_write - ( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_RCOMP, 2, &newrcomp ) == ERR_SUCCESS ) - { - rawdat_old = raw_adc_temperature; - } - } - count += 1; - - return ( ERR_SUCCESS ); -} - - - -/********************************************************** - 電池残量ICから残量を取得し、レジスタに書き込む。 -  電池残量ICが無い・故障などの時はとりあえず残量99%とする。 -         ↑は status_1で確認可能。電源投入時にチェックしています。 -  BT_init()が実行されている必要があります。 -**********************************************************/ -void BT_get_left(){ - if(( vreg_ctr[ VREG_C_STATUS_1 ] & REG_BIT_GASGAUGE_ERR ) == 0 ) - { - // 電池残量の取得 - static u8 bt_left_state; // バッテリ残量で割り込みのため - static u8 bt_voltage_low_count; // todo どうにかせんとね - u8 temp[2]; - - // 電池電圧で強制断が優先される - vreg_ctr[ VREG_C_BT_VOLTAGE ] = iic_mcu_read_a_byte( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_VCELL ); - if( vreg_ctr[ VREG_C_BT_VOLTAGE ] > ( 3100 / 16 / 1.25 ) ) - { - bt_voltage_low_count = 0; - } - else - { - bt_voltage_low_count += 1; - - if( bt_voltage_low_count == 12 ) // およそ3sec - { - vreg_ctr[ VREG_C_BT_REMAIN ] = 0; - set_irq( VREG_C_IRQ1, REG_BIT_BT_REMAIN ); - } - else if( bt_voltage_low_count == 12 + 3 * 5 ) - { // …時間切れ。強制的に切る - vreg_ctr[ VREG_C_LED_POW ] = LED_POW_ILM_ONLY_RED; - system_status.pwr_state = OFF_TRIG; - renge_task_interval_run_force = 1; - } - } - - iic_mcu_read( IIC_SLA_BT_GAUGE, BT_GAUGE_REG_SOC, 2, temp ); - vreg_ctr[ VREG_C_BT_REMAIN ] = temp[0]; - vreg_ctr[ VREG_C_BT_REMAIN_FINE ] = temp[1]; - - // 残量で割り込み - switch( bt_left_state ) - { - case( 0 ): // 前回、バッテリーは十分にあった - if( vreg_ctr[ VREG_C_BT_REMAIN ] <= BATT_TH_LO ) - { - bt_left_state = 1; // 突然バッテリ残量が減っても、Lo割り込みを入れる - set_irq( VREG_C_IRQ1, REG_BIT_BT_REMAIN ); - } - break; - - case( 1 ): - if( vreg_ctr[ VREG_C_BT_REMAIN ] <= BATT_TH_EMPTY ) - { - bt_left_state = 2; - set_irq( VREG_C_IRQ1, REG_BIT_BT_REMAIN ); - } - break; - - default: - if( vreg_ctr[ VREG_C_BT_REMAIN ] > BATT_TH_LO ) - { - bt_left_state = 0; - } - break; - } - } - else - { - vreg_ctr[ VREG_C_BT_REMAIN ] = 99; - } - - // PMIC-NTRに電池残量を教えてあげる - iic_mcu_write_a_byte( IIC_SLA_CODEC, CODEC_REG_BT, - ( vreg_ctr[ VREG_C_BT_REMAIN ] < 5 )? 1 : 0 ); // 1で電池切れ - -} diff --git a/trunk/sdk0.9/pm.h b/trunk/sdk0.9/pm.h index 35d8637..c6a68a8 100644 --- a/trunk/sdk0.9/pm.h +++ b/trunk/sdk0.9/pm.h @@ -2,20 +2,12 @@ #define __PM__ - #define IIC_SLA_PMIC 0x84 #define IIC_SLA_BT_GAUGE 0x6C - - -#define BATT_TH_LO 8 -#define BATT_TH_EMPTY 3 - #define VCOM_DEFAULT_T 92 #define VCOM_DEFAULT_B 95 - - //========================================================= enum PMIC_REG_ADRS { @@ -42,20 +34,12 @@ enum BT_GAUGE_REG_ADRS BT_GAUGE_REG_COMMAND = 0xFE }; - -typedef enum +enum BT_VENDER { - BT_VENDER_MAXELL = 0, // ショート - BT_VENDER_1, // 120 - BT_VENDER_2, // 360 - BT_VENDER_3, // 750 - BT_VENDER_4, // 1.3k - BT_VENDER_PANA = 5, // 2.7k - BT_VENDER_6, // 8.2k - BT_VENDER_OPEN = 7, // open - BT_VENDER_NOT_CHECKED = 0xFF, -}BT_VENDER; - + BT_VENDER_SHIROBAKO = 0, + BT_VENDER_PANA = 3, + BT_VENDER_MAXELL = 7 +}; //========================================================= @@ -82,7 +66,7 @@ typedef enum #define PM_REG_BIT_VDD50A ( 1 << 4 ) // 0x02 pw cnt2 -#define PM_REG_BIT_VDDLCD 0x07 +#define PM_REG_BIT_VDDLCD 0x07 #define PM_REG_BIT_LCD_VCS ( 0x01 << 4 ) #define PM_REG_BIT_LCD_TCOM ( 0x01 << 3 ) @@ -99,9 +83,9 @@ typedef enum #define PM_REG_BIT_VDD_PWM 0b00000000 -#define DELAY_PM_TW_PWUP 16 + 2 -#define DELAY_PM_TSS_50B_AND_TCOM 17 + 1 -#define DELAY_PM_5V_TO_TCOM 17 + 1 +#define DELAY_PM_TW_PWUP 16 +#define DELAY_PM_TSS_50B_AND_TCOM 17 +#define DELAY_PM_5V_TO_TCOM 17 #define DELAY_PM_TCOM_TO_VCS 3 #define DELAY_PM_VCS_TO_BL ( 17 + 5 ) #define DELAY_PM_LCD_OFF ( 50 + 1 ) @@ -109,25 +93,20 @@ typedef enum //========================================================= extern u8 raw_adc_temperature; -extern BT_VENDER battery_manufacturer; //========================================================= err PM_sys_pow_on( ); err PM_sys_pow_off( ); err PM_bt_auth( ); +void PM_init( ); err PM_LCD_vcom_set( ); err PM_LCD_on( ); void PM_LCD_off( ); err PM_BL_set( u8 ); - -void BT_init( ); -void BT_get_left(); - - -task_status_immed BT_temp_update( ); +task_status_immed PM_bt_temp_update( ); task_status_immed tski_vcom_set( ); task_status_immed tski_PM_LCD_on(); task_status_immed tski_PM_LCD_off(); @@ -156,9 +135,17 @@ task_status_immed tski_PM_BL_set(); #define PM_VDD_normMode() ( iic_mcu_write_a_byte( IIC_SLA_PMIC, PM_REG_ADRS_POW_SAVE, PM_REG_BIT_VDD1P_1R15 | PM_REG_BIT_VDD_PWM )) #define PM_VDD_ecoMode() ( iic_mcu_write_a_byte( IIC_SLA_PMIC, PM_REG_ADRS_POW_SAVE, PM_REG_BIT_VDD1P_0R90 | PM_REG_BIT_VDD_AUTO )) +#else +// 本番チップ待ち +#ifdef _PM_BUG_ +#define PM_VDD_ecoMode() ( iic_mcu_write_a_byte( IIC_SLA_PMIC, PM_REG_ADRS_POW_SAVE, PM_REG_BIT_VDD1P_0R90 | PM_REG_BIT_VDD_AUTO )) +#define PM_VDD_normMode() ( iic_mcu_write_a_byte( IIC_SLA_PMIC, PM_REG_ADRS_POW_SAVE, PM_REG_BIT_VDD1P_1R10 | PM_REG_BIT_VDD_PWM )) + #else #define PM_VDD_ecoMode() ( iic_mcu_write_a_byte( IIC_SLA_PMIC, PM_REG_ADRS_POW_SAVE, PM_REG_BIT_VDD1P_1R05 | PM_REG_BIT_VDD_AUTO )) #define PM_VDD_normMode() ( iic_mcu_write_a_byte( IIC_SLA_PMIC, PM_REG_ADRS_POW_SAVE, PM_REG_BIT_VDD1P_1R05 | PM_REG_BIT_VDD_PWM )) + +#endif #endif // ほか // diff --git a/trunk/sdk0.9/renge/renge_defs.h b/trunk/sdk0.9/renge/renge_defs.h index 8b725b7..bf0bb48 100644 --- a/trunk/sdk0.9/renge/renge_defs.h +++ b/trunk/sdk0.9/renge/renge_defs.h @@ -29,8 +29,7 @@ typedef unsigned char err; // ************************************ typedef enum{ ERR_SUCCESS = 0, - ERR_ERR, - ERR_SYSTEM_OFF + ERR_ERR }ERR; diff --git a/trunk/sdk0.9/renge/renge_task_intval.h b/trunk/sdk0.9/renge/renge_task_intval.h index e06c9e9..b5588db 100644 --- a/trunk/sdk0.9/renge/renge_task_intval.h +++ b/trunk/sdk0.9/renge/renge_task_intval.h @@ -1,11 +1,10 @@ /*スクリプトによる自動生成です。手動で書き換えない方がよいです*/ -#include "renge_defs.h" - - #ifndef __renge_task__ #define __renge_task__ +#include "renge_defs.h" + enum { TSK_SW, TSK_ADC, TSK_BATT, TSK_LED_POW, TSK_LED_WIFI, TSK_LED_NOTIFY, TSK_LED_CAM, TSK_MISC_STAT, TSK_DEBUG, TSK_DEBUG2, TSK_SYS, TSK_LAST }; @@ -22,8 +21,7 @@ extern void tsk_debug(); extern void tsk_debug2(); extern void tsk_sys(); - -const void ( *tasks[ TSK_LAST ] )() = { +static const task_status ( *tasks[ TSK_LAST ] )() = { tsk_sw, tsk_adc, tsk_batt, @@ -37,6 +35,5 @@ const void ( *tasks[ TSK_LAST ] )() = { tsk_sys, }; + #endif - - diff --git a/trunk/sdk0.9/self_flash.c b/trunk/sdk0.9/self_flash.c index 2cea8fa..3407eb5 100644 --- a/trunk/sdk0.9/self_flash.c +++ b/trunk/sdk0.9/self_flash.c @@ -15,7 +15,6 @@ #include "fsl_user.h" #include "i2c_ctr.h" -#include "pool.h" // ======================================================== @@ -25,7 +24,6 @@ const u8 fsl_low_voltage_u08 = 1; // 自己フラッシュパラメータ #define SAM_BLOCK_SIZE 1024 - // ↓256バイト以上はまとめてかけません。 #define SELF_UPDATE_BUFF_SIZE 256 #define SELF_UPDATE_SPLIT_WRITE_NUM ( SAM_BLOCK_SIZE / SELF_UPDATE_BUFF_SIZE ) #define SAM_WORD_SIZE 4 @@ -38,6 +36,8 @@ const u8 fsl_low_voltage_u08 = 1; #ifdef _MCU_BSR_ + + #define ACKD ACKD1 #define ACKE ACKE1 #define COI COI1 @@ -69,15 +69,15 @@ const u8 fsl_low_voltage_u08 = 1; // ======================================================== static void FSL_Open( void ); static void FSL_Close( void ); -void firm_restore( ); +err firm_restore( ); static err my_FSL_Init(); -static err firm_duplicate( u8 block_src, u8 block_dest ); +static err firm_duplicate( __far u8 * p_rom, u8 block_dest ); // ======================================================== -extern uni_pool pool; +extern u16 pool[]; // 0.D以降 新アップデータ向け @@ -93,7 +93,7 @@ extern uni_pool pool;     NG → 旧(現)ファームに戻して再起動 (この関数からは戻りません) ======================================================== */ -void firm_update( ) +err firm_update( ) { u8 target_block; u8 split_write_count; // ブロックへちまちま書き込むカウンタ @@ -102,12 +102,11 @@ void firm_update( ) my_FSL_Init(); /* ファームのバックアップ - 開始アドレス、書き込み先の先頭”ブロック番号” (サイズは FIRM_SIZE) 0x2000 - 0x4FFF を 0x5000 - 0x7FFF (ブロック 20 - 31) にコピー */ - firm_duplicate( FIRM_TOP, - UPDATE_BLOCK_LAST +1 ); + firm_duplicate( ( __far u8 * ) 0x2000, + ( 0x5000 / 0x0400 ) ); // 全ブロック削除 ///////////////////////////////////// // 電源断を判定するため、最初に全クラスタ消去する @@ -135,51 +134,46 @@ void firm_update( ) && ( !SPD ) ); split_write_count += 1 ) { - u8* p_buffer = &pool.self_update_work[0]; - u16 buff_written_size = 0; + u8* p_buffer = pool; + u8 buffer_fill = 0; + WDT_Restart( ); // I2Cから書き込みデータをバッファにためる do { - while( !IICAIF && !SPD ) - { - WDT_Restart( ); - } + while( !IICAIF && !SPD ){;} IICAIF = 0; *p_buffer = IICA; WREL = 1; p_buffer += 1; - buff_written_size += 1; + buffer_fill += 1; } - while( ( buff_written_size != SELF_UPDATE_BUFF_SIZE ) - && !SPD ); + while( ( buffer_fill != ( u8 ) SELF_UPDATE_BUFF_SIZE ) && !SPD ); // 書き込み // 最後だと、ゴミをパディングするが別にかまわない if( FSL_Write( ( fsl_u32 ) ( target_block * SAM_BLOCK_SIZE - + split_write_count * SELF_UPDATE_BUFF_SIZE ), - ( fsl_u08 ) ( SELF_UPDATE_BUFF_SIZE / SAM_WORD_SIZE ) ) + + + split_write_count * + SELF_UPDATE_BUFF_SIZE ), + ( fsl_u08 ) ( SELF_UPDATE_BUFF_SIZE / SAM_WORD_SIZE ) ) != FSL_OK ) { // 書き込み後のチェックエラー - // リストア - firm_duplicate( UPDATE_BLOCK_LAST +1, - FIRM_TOP ); - FSL_ForceReset(); - // 戻ってこない // + // リブートののち、リストア +// FSL_ForceReset(); // リセット + FSL_SwapBootCluster( ); +// FSL_Close( ); + return ( ERR_ERR ); } } // 1ブロック書き込み完了。内部ベリファイを行う if( FSL_IVerify( target_block ) != FSL_OK ){ - // 再度消去→書き込み ベリファイを繰り返すだけじゃダメでした... todo…? - // リストア - firm_duplicate( UPDATE_BLOCK_LAST +1, - FIRM_TOP ); - FSL_ForceReset(); - // 戻ってこない // + // todo 再度消去→書き込み ベリファイを繰り返すだけじゃダメでした... + NOP(); } if( SPD ) @@ -202,18 +196,19 @@ void firm_update( ) } if( comp == 0 ) { - // OK! FSL_InvertBootFlag( ); FSL_SwapBootCluster( ); // リセットせずに頭から。FSL_Closeは不要 + // FSL_ForceReset(); // リセット + // FSL_SwapActiveBootCluster(); // ←スワップされてしまうので、続けられず暴走! // 戻ってこない // } else { - // データ(マジックナンバーしか見てない)エラー - // リストア - firm_duplicate( UPDATE_BLOCK_LAST, - FIRM_TOP ); - FSL_ForceReset(); // リセット + // データエラー + // リブートののち、リストア +// FSL_ForceReset(); // リセット + FSL_SwapBootCluster( ); +// FSL_Close( ); // 戻ってこない // } } @@ -228,7 +223,7 @@ void firm_update( )  ここではブートスワップは不要です。 ======================================================== */ -void firm_restore( ) +err firm_restore( ) { my_FSL_Init(); @@ -236,14 +231,17 @@ void firm_restore( ) 0x4800 - 0x7FFF (ブロック 18 - 27) から 0x2000 - 0x47FF (ブロック 8 - 17) へコピー */ - firm_duplicate( UPDATE_BLOCK_LAST +1, + firm_duplicate( ( __far u8 * ) 0x5000, FIRM_TOP ); + // todo //  リストア失敗したら、LEDちかちかとかさせて、サービス送りにしてもらう // リブート - FSL_InvertBootFlag( ); + // スワップは不要です! FSL_SwapBootCluster(); +// FSL_ForceReset( ); + return ( ERR_SUCCESS ); } @@ -268,7 +266,9 @@ static void FSL_Open( void ) MK2H = FSL_MK2H_MASK; /* } */ #endif - while( DST1 ){;} // DMA停止 + // 何か前準備? + // todo DMAを止める + while( DST1 ){;} DEN1 = 0; MK0 = 0xFFFF; @@ -308,14 +308,11 @@ static void FSL_Close( void ) コピー先に書けるようにmy_FSL_Initをあらかじめ実行する必要があります。 ======================================================== */ -//static err firm_duplicate( __far u8 * p_rom, -// u8 block_dest ) -static err firm_duplicate( u8 block_src, - u8 block_dest ) +static err firm_duplicate( __far u8 * p_rom, + u8 block_dest ) { u8 target_block; u8 split_write_count; // ブロックへちまちま書き込むカウンタ - __far u8* p_src = ( __far u8* )( block_src * 0x400 ); // 書き込み先ブロックの数だけ繰り返す for( target_block = block_dest; @@ -334,28 +331,29 @@ static err firm_duplicate( u8 block_src, split_write_count < SELF_UPDATE_SPLIT_WRITE_NUM; split_write_count += 1 ) { - u16 buff_written_size; + u8 buffer_fill; u8* p_buff; // 書き込みデータをバッファにためる - buff_written_size = 0; - p_buff = &pool.self_update_work[0]; + buffer_fill = 0; + p_buff = pool; do { - *p_buff = *p_src; - p_src += 1; + *p_buff = *p_rom; + p_rom += 1; p_buff += 1; - buff_written_size +=1; + buffer_fill +=1; } - while( buff_written_size != SELF_UPDATE_BUFF_SIZE ); + while( buffer_fill != ( u8 ) SELF_UPDATE_BUFF_SIZE ); // 書き込み if( FSL_Write( ( fsl_u32 ) ( target_block * SAM_BLOCK_SIZE - + split_write_count * SELF_UPDATE_BUFF_SIZE ), - ( fsl_u08 ) ( SELF_UPDATE_BUFF_SIZE / SAM_WORD_SIZE ) ) + + + split_write_count * + SELF_UPDATE_BUFF_SIZE ), + ( fsl_u08 ) ( SELF_UPDATE_BUFF_SIZE / SAM_WORD_SIZE ) ) != FSL_OK ) { - // todo リカバリ? // FSL_Close( ); return ( ERR_ERR ); } @@ -363,7 +361,7 @@ static err firm_duplicate( u8 block_src, // 1ブロック書き込み完了。内部電圧チェックを行う while( FSL_IVerify( target_block ) != FSL_OK ){ - // todo 失敗時? + // todo ; } } @@ -383,7 +381,7 @@ static err my_FSL_Init() DI( ); FSL_Open( ); // 割り込み禁止など - FSL_Init( &pool.self_update_work[0] ); // ライブラリ初期化。割り込み中断考慮せず + FSL_Init( pool ); // ライブラリ初期化。割り込み中断考慮せず FSL_ModeCheck( ); // ライトプロテクトチェック。失敗することを考慮せず return( ERR_SUCCESS ); @@ -394,12 +392,11 @@ task_status_immed tski_mcu_reset() { // 普通に再起動 my_FSL_Init(); - FSL_SwapBootCluster(); - - FSL_ForceReset(); // リセット FSL_Close( ); +// FSL_SwapBootCluster(); + FSL_ForceReset(); // リセット // 保険? // -// WDTE = 0xAA; // WDTで再起動(テスト向け) + WDTE = 0xAA; // WDTで再起動(テスト向け) return( ERR_SUCCESS ); // no reach } diff --git a/trunk/sdk0.9/sw.c b/trunk/sdk0.9/sw.c index f63fe27..ea60fdf 100644 --- a/trunk/sdk0.9/sw.c +++ b/trunk/sdk0.9/sw.c @@ -8,30 +8,26 @@ #include "i2c_twl.h" #include "i2c_ctr.h" #include "led.h" +#include "accero.h" #include "pm.h" #include "rtc.h" //========================================================= -#define INTERVAL_TSK_SW 8 -#define CLICK_THRESHOLD 2 +#define INTERVAL_TSK_SW 16 +#define CLICK_THRESHOLD 1 +#define HOLD_THREASHOLD (u8)( 600 / INTERVAL_TSK_SW ) -#ifdef _FOR_E3_ -#define HOLD_THREASHOLD (u8)( 800 / INTERVAL_TSK_SW ) -#else -#define HOLD_THREASHOLD (u8)( 2000 / INTERVAL_TSK_SW ) -#endif //========================================================= -u8 SW_pow_count; -bit SW_pow_mask; - -u8 SW_home_count, SW_wifi_count; +u8 SW_pow_count, SW_home_count, SW_wifi_count; +bit SW_pow_mask, SW_home_mask, SW_wifi_mask; bit SW_HOME_n; + //========================================================= // 押した時間を数える。押しっぱなしでも0に戻らない // maskが非0の時は、一度離すまで無視する @@ -51,24 +47,6 @@ bit SW_HOME_n; } -#define chk_clicked( button, count, irq_bit_name ) \ - if( !button ) \ - { \ - if( count <= CLICK_THRESHOLD ) \ - { \ - count += 1; \ - } \ - if( count == CLICK_THRESHOLD ) \ - { \ - set_irq( VREG_C_IRQ0, irq_bit_name ); \ - } \ - } \ - else \ - { \ - count = 0; \ - } - - /* ======================================================== スイッチの監視 @@ -76,14 +54,24 @@ bit SW_HOME_n; ======================================================== */ void tsk_sw( ) { - static u16 cnt_force_off = 0; + static u8 cnt_force_off = 0; static u8 task_interval = 0; switch ( system_status.pwr_state ) { - case ( ON_TRIG ): + case ( OFF_TRIG ): + SW_pow_count = 0; + SW_wifi_count = 0; + SW_home_count = 0; cnt_force_off = 0; break; + + case ( ON_TRIG ): + // 電源投入 + SW_pow_mask = 1; + SW_home_mask = 1; + SW_wifi_mask = 1; + break; } if( task_interval-- != 0 ) @@ -95,6 +83,7 @@ void tsk_sw( ) task_interval = (u8)( INTERVAL_TSK_SW / SYS_INTERVAL_TICK ); } + switch ( system_status.pwr_state ) { case ( ON ): @@ -102,10 +91,9 @@ void tsk_sw( ) case ( BT_CHARGE ): case ( OFF ): // 電源スイッチの監視 // - count_sw_n( SW_POW_n, SW_pow_count, SW_pow_mask ); // ボタン押し時間のカウント if( SW_POW_n ) { - if( SW_pow_count == CLICK_THRESHOLD ) + if( ( CLICK_THRESHOLD < SW_pow_count ) && ( SW_pow_count <= HOLD_THREASHOLD ) ) { #ifdef _SW_HOME_ENABLE_ set_irq( VREG_C_IRQ0, REG_BIT_SW_POW_CLICK ); @@ -121,45 +109,81 @@ void tsk_sw( ) #else set_irq( VREG_C_IRQ0, REG_BIT_SW_HOME_HOLD ); #endif - cnt_force_off = 1; + } + else if( SW_pow_count == ( HOLD_THREASHOLD * 4 ) ) + { // todo + vreg_ctr[ VREG_C_LED_POW ] = LED_POW_ILM_ONLY_RED; + system_status.pwr_state = OFF_TRIG; + renge_task_interval_run_force = 1; } - if( cnt_force_off != 0 ) + // 電源OFF割り込みを入れたが… + if( ( vreg_ctr[VREG_C_IRQ0] & REG_BIT_SW_POW_HOLD ) != 0 ) { -#ifdef _FOR_E3_ - if( ++cnt_force_off == ( 200 / INTERVAL_TSK_SW ) ) -#else - if( ++cnt_force_off == ( 4000 / INTERVAL_TSK_SW ) ) -#endif - { - // タイムアウトによる強制OFF - cnt_force_off = 0; + cnt_force_off += 1; + if( cnt_force_off >= 13 ) + { // …返事がない。強制的に切る。 vreg_ctr[ VREG_C_LED_POW ] = LED_POW_ILM_ONLY_RED; system_status.pwr_state = OFF_TRIG; renge_task_interval_run_force = 1; } } + else + { + cnt_force_off = 0; + } -#ifdef _SW_HOME_ENABLE_ // HOME スイッチ // switch( system_status.model ) { -# ifdef _MODEL_CTR_ +#ifdef _MODEL_CTR_ case( MODEL_JIKKI ): SW_HOME_n = SW_HOME_n_JIKKI; break; -# endif +#endif case( MODEL_TS_BOARD ): case( MODEL_SHIROBAKO ): SW_HOME_n = SW_HOME_n_TSBOARD; break; default: - SW_HOME_n = 1; // 放されてる状態 + SW_HOME_n = 1; + } + + 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 ); } - chk_clicked( SW_HOME_n, SW_home_count, REG_BIT_SW_HOME_CLICK ); -#endif // wifi sw // - chk_clicked( SW_WIFI_n, SW_wifi_count, REG_BIT_SW_WIFI_CLICK ); + if( SW_wifi_count == CLICK_THRESHOLD ) + { + set_irq( VREG_C_IRQ0, REG_BIT_SW_WIFI_CLICK ); + } + + break; } + + // ボタン押し時間のカウント +/* +if( ( system_status.pwr_state == ON ) + || ( system_status.pwr_state == OFF ) + || ( system_status.pwr_state == BT_CHARGE ) ) + */ + + { + count_sw_n( SW_POW_n, SW_pow_count, SW_pow_mask ); +#ifdef _SW_HOME_ENABLE_ + count_sw_n( SW_HOME_n, SW_home_count, SW_home_mask ); +#endif + count_sw_n( SW_WIFI_n, SW_wifi_count, SW_wifi_mask ); + } + + return; } diff --git a/trunk/sdk0.9/sw.h b/trunk/sdk0.9/sw.h index 12b473e..f3bea21 100644 --- a/trunk/sdk0.9/sw.h +++ b/trunk/sdk0.9/sw.h @@ -1,7 +1,7 @@ #ifndef _sw_ #define _sw_ -extern u8 SW_pow_count; -extern bit SW_pow_mask; +extern u8 SW_pow_count, SW_home_count, SW_wifi_count; +extern bit SW_pow_mask, SW_home_mask, SW_wifi_mask; #endif diff --git a/trunk/sdk0.9/task_debug.c b/trunk/sdk0.9/task_debug.c index df4ff5d..75d3e41 100644 --- a/trunk/sdk0.9/task_debug.c +++ b/trunk/sdk0.9/task_debug.c @@ -7,6 +7,8 @@ #include "renge.h" #include "pm.h" +#include "accero.h" + /* ======================================================== ======================================================== */ @@ -19,7 +21,7 @@ void tsk_debug( ) if( system_status.pwr_state == ON_TRIG ){ #ifdef _MODEL_WM0_ - P5.0 = 1; // /WL_RST に配線されています + PM_CHG_TIMEOUT_DISABLE(); // /WL_RST に配線されています #endif #ifndef _MODEL_CTR_ iic_mcu_write_a_byte( IIC_SLA_DCP, 0x08, 0x80 ); // ACR←0x80 揮発モードへ @@ -35,16 +37,12 @@ void tsk_debug( ) return; } - - -// 7セグ 4バイト版 -# define IIC_SLA_DBG_MONITOR 0x24 +u8 temp_debug_3; void tsk_debug2( ) { u8 str[4]; - if( ( system_status.pwr_state == ON ) || ( system_status.pwr_state == SLEEP ) ) { /* diff --git a/trunk/sdk0.9/task_misc.c b/trunk/sdk0.9/task_misc.c index 9bfd678..7d379e9 100644 --- a/trunk/sdk0.9/task_misc.c +++ b/trunk/sdk0.9/task_misc.c @@ -44,16 +44,10 @@ -// ======================================================== -bit twl_ver_read; - - // ======================================================== #define INTERVAL_TSK_MISC_STAT 4 - - /* ======================================================== ステータスレジスタなど ======================================================== */ @@ -131,7 +125,7 @@ void tsk_misc_stat( ) // 割り込みの取りこぼし? if( ( vreg_ctr[VREG_C_ACC_CONFIG] & 0x03 ) != 0x00 ) { - if( ACC_VALID == 1 ) + if( ACC_VALID ) { if( renge_task_immed_add( tsk_cbk_accero ) == ERR_SUCCESS ){ NOP(); @@ -146,14 +140,6 @@ void tsk_misc_stat( ) NOP(); } } - - - if( twl_ver_read ) - { - twl_ver_read = 0; - set_irq( VREG_C_IRQ2, REG_BIT_TWL_VER_READ ); - } - return; } @@ -198,16 +184,14 @@ task_status_immed do_command0( ) FCRAM_RST_neg; PM_reset_neg(); RESET2_neg; - - // 起動時以外はリセット不要 - /* +/* // CODEC 不定レジスタ初期化 wait_ms( 100 ); { u8 codec_reg_init[3] = { 0,0,0 }; - iic_mcu_write( IIC_SLA_CODEC, CODEC_REG_PM, 3, codec_reg_init ); + iic_mcu_write( IIC_SLA_CODEC, CODEC_REG_PM, 3, codec_reg_init ); } - */ +*/ } } @@ -231,6 +215,9 @@ extern u8 iic_burst_state; ======================================================== */ task_status_immed tski_mcu_info_read() { + u8 temp; + + if( SPD ) { goto end; @@ -249,7 +236,7 @@ task_status_immed tski_mcu_info_read() { IICAIF = 0; } - + switch( iic_burst_state++ ){ case( 0 ): // 本体種類識別 IICA = (u8)system_status.model; @@ -260,7 +247,9 @@ task_status_immed tski_mcu_info_read() break; case( 2 ): // 電池メーカーの識別 - IICA = battery_manufacturer; + BT_DET_P = 1; + IICA = ( u8 ) ( get_adc( ADC_SEL_BATT_DET ) >> 5 ); + BT_DET_P = 0; break; case( 3 ): // ガスゲージバージョン diff --git a/trunk/sdk0.9/task_sys.c b/trunk/sdk0.9/task_sys.c index 74650d2..8c754f4 100644 --- a/trunk/sdk0.9/task_sys.c +++ b/trunk/sdk0.9/task_sys.c @@ -13,7 +13,7 @@ #include "rtc.h" #include "sw.h" #include "adc.h" -#include "self_flash.h" + //========================================================= @@ -40,9 +40,10 @@ void tsk_sys( ) case OFF: //------------------------------------------------------- // スイッチ操作などで割り込みが発生し、スリープが解除されるとここに来ます。 +#ifndef _PARRADIUM_ switch ( system_status.poweron_reason ) { - case( NONE ): + default: // スイッチで電源on if( SW_pow_count != 0 ) @@ -53,14 +54,14 @@ void tsk_sys( ) { timeout += 1; } - if( timeout > 100 ) + if( timeout > 127 ) { system_status.pwr_state = OFF_TRIG; // スイッチはノイズだった。寝る。 renge_task_interval_run_force = 1; return; } - if( SW_pow_count < 10 ) + if( SW_pow_count < 3 ) { // もう少しスイッチの様子を見る return; @@ -69,44 +70,32 @@ void tsk_sys( ) system_status.poweron_reason = PWSW; break; - default: + case ( RTC_ALARM ): break; } - SW_pow_mask = 1; - timeout = 0; - BT_DET_P = 1; // チャージに時間が掛かるので先に上げておく - BT_TEMP_P = 1; - // 電源投入 // iic_mcu_start( ); - BT_init( ); // 実機やバッテリの判定、電池残量ICの設定 - - 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; - } + // ↓で電池残量ICの起動待ちウェイトなどがあります。 + PM_init( ); // 電池残量ICの設定 if( PM_sys_pow_on( ) != ERR_SUCCESS ) { // 電源起動不可エラー renge_task_interval_run_force = 1; + iic_mcu_stop( ); system_status.pwr_state = OFF_TRIG; return; } + PM_CHG_TIMEOUT_ENABLE(); +// IRQ0_active; + +#else + vreg_ctr[ VREG_C_STATUS_1 ] |= REG_BIT_GASGAUGE_ERR; + system_status.poweron_reason = PWSW; +#endif // _PARADDIUM_ PM_LCD_vcom_set( ); // LCDの対向電圧値など書き込み #ifdef _PMIC_TWL_ @@ -122,24 +111,17 @@ void tsk_sys( ) { // とりあえず、LED消灯状態で起動させる vreg_ctr[VREG_C_LED_POW] = LED_POW_ILM_OFF; + // todo? } 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 + PU7 = 0b00011101; // 4:SW_WIFI 3:SW_PWSW 2:PM_IRQ 0:PM_EXTDC_n IIC_ctr_Init( ); if( ( vreg_ctr[ VREG_C_MCU_STATUS ] & REG_BIT_STATUS_WDT_RESET ) @@ -153,21 +135,6 @@ void tsk_sys( ) { set_irq( VREG_C_IRQ0, REG_BIT_IRQ_WDT_RESET ); } - { - // WDTリセット時、I2Cの初期化まで割り込み保留 - // ほんとはここにべた書きしたくないが... - if( ( vreg_ctr[ VREG_C_MCU_STATUS ] & REG_BIT_STATUS_WDT_RESET ) - /* - if( vreg_ctr[ VREG_C_IRQ0 ] - | vreg_ctr[ VREG_C_IRQ0 ] - | vreg_ctr[ VREG_C_IRQ0 ] - | vreg_ctr[ VREG_C_IRQ0 ] - */ - != 0 ) - { - set_irq( VREG_C_IRQ0, REG_BIT_IRQ_WDT_RESET ); - } - } IIC_twl_Init( ); RTC_32k_on( ); @@ -178,9 +145,6 @@ void tsk_sys( ) 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 使わない @@ -235,11 +199,12 @@ void tsk_sys( ) case OFF_TRIG: //--------------------------------------- // LED消灯を待つ vreg_ctr[VREG_C_LED_POW] = LED_POW_ILM_OFF; - if( LED_duty_pow_blu != 0 ) + if(( LED_duty_pow_H != 0 ) || ( LED_duty_pow_L != 0 )) { return; } + PM_CHG_TIMEOUT_ENABLE(); LED_stop( ); IIC_ctr_Stop( ); IIC_twl_Stop( ); @@ -260,43 +225,52 @@ void tsk_sys( ) #ifdef _PMIC_TWL_ PM_TEG_LCD_dis( 1 ); #endif - while( iic_mcu_busy ) - {; +// IRQ0_deactive; + // pullup_off(); ↓ + { + PU5 = 0b00000011; // PM_CHG,PM_CHGERR + PU7 = 0b00011001; // SW_WiFi,PWSWI,PM_EXTTDC } + PM_sys_pow_off( ); + KRM = ( KR_SW_POW ); // Mask ではなく、Modeなのだそうだ。紛らわしい + // intp20系は後ほど 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; + SW_wifi_count = 0; // no break // case BT_CHARGE: - system_status.pwr_state = OFF; if( !PM_EXTDC_n ) { // アダプタ有り:充電温度監視 BT_TEMP_P = 1; + + // 電源on? + if( ( SW_pow_count > 3 ) || ( SW_wifi_count > 3 ) + || ( system_status.poweron_reason == RTC_ALARM ) ) + { + system_status.pwr_state = OFF; // 若干抵抗有るが... + renge_task_interval_run_force = 1; + KRMK = 1; + return; + } + return; } else { // 省電力へ移行 - LED_CHARGE = 0; BT_TEMP_P = 0; while( RWST ) {;} @@ -305,29 +279,31 @@ void tsk_sys( ) // 割り込み待ちで寝る // RTCIMK = 1; +#ifndef _PARRADIUM_ -# ifdef _MCU_BSR_ +#ifdef _MCU_BSR_ CKC = 0b00001001; OSMC = 0x00; -# endif +#endif STOP( ); +#ifdef _MCU_BSR_ + OSMC = 0x01; + CKC = 0b00001000; +#endif + +#endif + RTCIMK = 0; // 起きる // + // 起きる条件は // ・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; // + renge_task_interval_run_force = 1; + KRMK = 1; + return; } - return; default: while( 1 ) @@ -345,65 +321,41 @@ void tsk_sys( ) PMICが電源異常で止めたか確認 **********************************************************/ static void chk_emergencyExit(){ - static u8 shirobako_power_control_count; +#ifndef _PARRADIUM_ + static state; - if( shirobako_power_control_count == 0 ) // PM_chk_LDSW() はI2C_mを使用し、高コスト + if( !RESET1_n ) { - if( !RESET1_n ) + if( PM_chk_LDSW( ) == 0 ) { - // リセットが下がってる - if( PM_chk_LDSW( ) == 0 ) + // PMICが異常終了判断をした + system_status.pwr_state = OFF_TRIG; + renge_task_interval_run_force = 1; + } + else + { + if( state == 0 ) { - // PMICが異常終了判断をした - system_status.pwr_state = OFF_TRIG; - renge_task_interval_run_force = 1; - } - else - { - // 白箱の仕業 - shirobako_power_control_count = 1; - } + state = 1; + // デバッガなりがリセットをかけた + 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 ); + } } } 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; - } - } + state = 0; } +#endif } + /* ======================================================== CPUからのスリープ要求  ポーリングにしました。 diff --git a/trunk/sdk0.9/user_define.h b/trunk/sdk0.9/user_define.h index 471a2f6..7bb5a5b 100644 --- a/trunk/sdk0.9/user_define.h +++ b/trunk/sdk0.9/user_define.h @@ -10,36 +10,36 @@ #ifdef _debug_ // 8ドットのLED -# define IIC_SLA_8LEDS 0x42 -# define IIC_8LEDS_REG_DO 1 -# define IIC_8LEDS_REG_DI 2 -# define IIC_8LEDS_REG_DIR 3 +#define IIC_SLA_8LEDS 0x42 +#define IIC_8LEDS_REG_DO 1 +#define IIC_8LEDS_REG_DI 2 +#define IIC_8LEDS_REG_DIR 3 // 7セグ 4バイト版 -# define IIC_SLA_DBG_MONITOR 0x44 +#define IIC_SLA_DBG_MONITOR 0x44 + #endif - #ifdef _debug_led_ -# define DBG_LED_WIFI_2_on { PM2.4 = 0; P2.4 = 1; } -# define DBG_LED_WIFI_2_off { PM2.4 = 1; P2.4 = 0; } -# define DBG_LED_WIFI_2_toggle ( P2.4 ^= 1 ) +#define DBG_LED_WIFI_2_on { PM2.4 = 0; P2.4 = 1; } +#define DBG_LED_WIFI_2_off { PM2.4 = 1; P2.4 = 0; } +#define DBG_LED_WIFI_2_toggle ( P2.4 ^= 1 ) #else -# define DBG_LED_WIFI_2_on ; -# define DBG_LED_WIFI_2_off ; -# define DBG_LED_WIFI_2_toggle ; +#define DBG_LED_WIFI_2_on ; +#define DBG_LED_WIFI_2_off ; +#define DBG_LED_WIFI_2_toggle ; #endif #ifdef _PMIC_TWL_ -# define PM_TEG_PWSW P7.5 // TEGのみ -# define PM_TEG_LCD_dis( val ) ( P7.6 = val ) // TEGのみ +#define PM_TEG_PWSW P7.5 // TEGのみ +#define PM_TEG_LCD_dis( val ) ( P7.6 = val ) // TEGのみ #else -# define SLP_ACK P7.7 +#define SLP_ACK P7.7 #endif @@ -84,7 +84,11 @@ #define RESET2_ast { P0.1 = 0; PM0.1 = 0; } #define RESET2_neg { PM0.1 = 1; } +#ifndef _PARRADIUM_ #define SLP_REQ P12.0 +#else +#define SLP_REQ 0 +#endif // FCRAM #ifdef _MODEL_TEG2_ @@ -115,11 +119,11 @@ // INTP6 #ifndef _MODEL_CTR_ -#define SND_DEPOP_SND_MUTE P7.7 = 1 -#define SND_DEPOP_SND_ENABLE P7.7 = 0 +#define SND_DEPOP_ACT P7.6 = 1 +#define SND_DEPOP_DEACT P7.6 = 0 #else -#define SND_DEPOP_SND_MUTE ; -#define SND_DEPOP_SND_ENABLE ; +#define SND_DEPOP_ACT ; +#define SND_DEPOP_DEACT ; #endif // PM @@ -135,7 +139,6 @@ // 充電せよ(out) #ifdef _PMIC_CTR_ -// 負論理です。注意。 #define BT_CHG_ENABLE() ( P4.3 = 0 ) #define BT_CHG_DISABLE() ( P4.3 = 1 ) #else @@ -143,6 +146,14 @@ #define BT_CHG_DISABLE() ( P4.2 = 1 ) #endif +#ifdef PM_CCIC_TIM +#define PM_CHG_TIMEOUT_ENABLE() ( P5.0 = 0 ) +#define PM_CHG_TIMEOUT_DISABLE() ( P5.0 = 1 ) +#else +#define PM_CHG_TIMEOUT_ENABLE() ; +#define PM_CHG_TIMEOUT_DISABLE() ; +#endif + // 充電中(in) #define BT_CHG_n P5.1 @@ -161,8 +172,10 @@ // WiFi #ifndef _TEG_ #define WL_TX P20.3 // INTP21 +#define WL_RX P20.2 // INTP20 #else #define WL_TX P20.3 // INTP21 +#define WL_RX P20.2 // INTP20 #endif //#define LED_CAM P1.0 // TO02 @@ -174,36 +187,7 @@ #define LED_CHARGE P2.4 -#ifdef _MODEL_TEG2_ -#define I2C_PU_on() P5.3 = 1 -#define I2C_PU_off() P5.3 = 0 -#endif - -#ifdef _MODEL_TS0_ -#define I2C_PU_on() P5.3 = 1 -#define I2C_PU_off() P5.3 = 0 -#endif - -#ifdef _MODEL_WM0_ -#define I2C_PU_on() P5.3 = 1 -#define I2C_PU_off() P5.3 = 0 -#endif - -#ifdef _MODEL_CTR_ -// P5.3 に加え、P5.5, P140 P141 -// P140が出力専用なので... -#define I2C_PU_on() { PM5.3 = 1; PM3.3 = 1; P14 |= 0x03; P5.3 = 1; PM5.3 = 0; P3.3 = 1; PM3.3 = 0; } -#define I2C_PU_off() { PM5.3 = 1; PM3.3 = 1; P14 &= ~0x03; P5.3 = 0; PM5.3 = 0; P3.3 = 0; PM3.3 = 0; } -#endif - -#ifdef _MODEL_CTR_ -#define GYRO_CS_ENABLE() P5.0 = 0 -#define GYRO_CS_DISABLE() P5.0 = 1 -#else -#define GYRO_CS_ENABLE() ; -#define GYRO_CS_DISABLE() ; -#endif - +#define I2C_PU P5.3 //#define I2C_M_SDA P3.1 // SDA10 //#define I2C_M_SCL P3.2 // SCL10 @@ -236,7 +220,7 @@ #define ACCEL_INT1 P2.5 #endif -#ifdef _MODEL_TS0_ +#ifdef _MODEL_TS0_ || _MODEL_CTR_ #define ACC_VALID P20.5 #define ACCEL_INT1 P2.5 #endif @@ -253,9 +237,12 @@ #endif + +#define DBG_M_n P2.1 #define DBG_P_n P2.2 + #define KR_SW_POW ( 1 << 3 ) #define KR_SW_WIFI ( 1 << 4 ) diff --git a/trunk/sdk0.9/vreg_ctr.c b/trunk/sdk0.9/vreg_ctr.c index 2afe32d..b65f0e8 100644 --- a/trunk/sdk0.9/vreg_ctr.c +++ b/trunk/sdk0.9/vreg_ctr.c @@ -9,20 +9,22 @@ CTR MCU I2C #include "led.h" #include "accero.h" #include "pm.h" -#include "pool.h" #include #include "fsl_user.h" - extern u8 mcu_info_read(); // task_misc.c -extern u8 iic_burst_state; + // ******************************************************** u8 vreg_ctr[VREG_C_ENDMARK_]; + bit irq_readed; // AAA型のため。 +extern bit update; +extern u16 pool[]; + // ******************************************************** extern task_status_immed tski_firm_update(); @@ -69,8 +71,8 @@ void vreg_ctr_write( u8 adrs, u8 data ) { case ( VREG_C_MCU_STATUS ): - vreg_twl[ REG_TWL_INT_ADRS_MODE ] = ( ( data & 0xC0 ) >> 6 ); vreg_ctr[adrs] = data; + vreg_twl[ REG_TWL_INT_ADRS_MODE ] = ( ( data & 0xC0 ) >> 6 ); break; case ( VREG_C_VCOM_T ): @@ -84,6 +86,7 @@ void vreg_ctr_write( u8 adrs, u8 data ) vreg_ctr[adrs] = data; break; case ( VREG_C_DBG3 ): + vreg_ctr[adrs] = data; if( ( vreg_ctr[VREG_C_DBG1] == 'j' ) && ( vreg_ctr[VREG_C_DBG2] == 'h' ) && ( data == 'l' ) ) @@ -91,7 +94,6 @@ void vreg_ctr_write( u8 adrs, u8 data ) renge_task_immed_add( tski_firm_update ); IICAMK = 1; } - vreg_ctr[adrs] = data; break; case ( VREG_C_IRQ_MASK0 ): @@ -103,11 +105,11 @@ void vreg_ctr_write( u8 adrs, u8 data ) break; case ( VREG_C_COMMAND0 ): + vreg_ctr[adrs] |= data; if( data != 0 ) { renge_task_immed_add( do_command0 ); } - vreg_ctr[adrs] |= data; break; case ( VREG_C_COMMAND2 ): @@ -126,8 +128,8 @@ void vreg_ctr_write( u8 adrs, u8 data ) /// 今のところさらに細かくは分けないけど… if(( data & REG_BITS_CMD_BL ) != 0 ) { - renge_task_immed_add( tski_PM_BL_set ); vreg_ctr[adrs] = ( data & REG_BITS_CMD_BL ); + renge_task_immed_add( tski_PM_BL_set ); } break; @@ -155,6 +157,25 @@ void vreg_ctr_write( u8 adrs, u8 data ) vreg_ctr[adrs] = data; break; + case ( VREG_C_FREE_0 ): + case ( VREG_C_FREE_1 ): + case ( VREG_C_FREE_2 ): + case ( VREG_C_FREE_3 ): + case ( VREG_C_FREE_4 ): + case ( VREG_C_FREE_5 ): + case ( VREG_C_FREE_6 ): + case ( VREG_C_FREE_7 ): + case ( VREG_C_FREE_8 ): + case ( VREG_C_FREE_9 ): + case ( VREG_C_FREE_A ): + case ( VREG_C_FREE_B ): + case ( VREG_C_FREE_C ): + case ( VREG_C_FREE_D ): + case ( VREG_C_FREE_E ): + case ( VREG_C_FREE_F ): + vreg_ctr[adrs] = data; + break; + case ( VREG_C_LED_BRIGHT ): vreg_ctr[adrs] = data; break; @@ -163,29 +184,10 @@ void vreg_ctr_write( u8 adrs, u8 data ) case ( VREG_C_LED_WIFI ): case ( VREG_C_LED_CAM ): case ( VREG_C_LED_TUNE ): + case ( VREG_C_LED_NOTIFY ): vreg_ctr[adrs] = data & 0x0F; break; - case ( VREG_C_LED_NOTIFY_DATA ): - if( iic_burst_state == 0 ) - { - iic_burst_state += 1; - vreg_ctr[adrs] = data; - } - else - { - if( iic_burst_state > sizeof( uni_info_LED ) ) - { - iic_burst_state = 1; - } - info_LED.bindata[ iic_burst_state -1 ] = data; - iic_burst_state += 1; - } - - case ( VREG_C_LED_NOTIFY_OPTION ): - vreg_ctr[adrs] = data; - break; - /// 非同期で動いているためここでは書かない。 // 予約するだけでstopで書く case ( VREG_C_RTC_SEC ): @@ -214,18 +216,18 @@ void vreg_ctr_write( u8 adrs, u8 data ) break; case ( VREG_C_RTC_COMP ): - SUBCUD = data; vreg_ctr[adrs] = data; + SUBCUD = data; break; case ( VREG_C_RTC_ALARM_MIN ): - rtc_alarm_dirty = 1; vreg_ctr[adrs] = ( data & 0x7F ); + rtc_alarm_dirty = 1; break; case ( VREG_C_RTC_ALARM_HOUR ): - rtc_alarm_dirty = 1; vreg_ctr[adrs] = ( data & 0x3F ); + rtc_alarm_dirty = 1; break; // 書くだけでよい @@ -243,13 +245,13 @@ void vreg_ctr_write( u8 adrs, u8 data ) case ( VREG_C_ACC_CONFIG ): - renge_task_immed_add( acc_hosu_set ); vreg_ctr[adrs] = data; + renge_task_immed_add( acc_hosu_set ); break; case ( VREG_C_ACC_R_ADRS ): - renge_task_immed_add( acc_read ); vreg_ctr[adrs] = data; + renge_task_immed_add( acc_read ); break; case ( VREG_C_ACC_W_ADRS ): @@ -257,8 +259,8 @@ void vreg_ctr_write( u8 adrs, u8 data ) break; case ( VREG_C_ACC_W_BUF ): - renge_task_immed_add( acc_write ); vreg_ctr[adrs] = data; + renge_task_immed_add( acc_write ); break; case ( VREG_C_ACC_HOSU_L ): @@ -274,49 +276,20 @@ void vreg_ctr_write( u8 adrs, u8 data ) } break; - case ( VREG_C_ACC_HOSU_ORIGIN ): - vreg_ctr[adrs] = data; - break; - - case ( VREG_C_FREE_ADRS ): - vreg_ctr[adrs] = data; - break; - - case ( VREG_C_FREE_DATA ): - if( vreg_ctr[ VREG_C_FREE_ADRS ] < VREG_C_FREE_SIZE ) - { - pool.vreg_c_ext.vreg_c_free[ vreg_ctr[ VREG_C_FREE_ADRS ] ] = data; - vreg_ctr[ VREG_C_FREE_ADRS ] += 1; - } - break; - case ( VREG_C_COMMAND3 ): + vreg_ctr[adrs] = data; switch ( data ) { case ( 'r' ): // 割り込みルーチンからFSLライブラリを呼ぶのは禁止のため - renge_task_immed_add( tski_mcu_reset ); - break; +// renge_task_immed_add( tski_mcu_reset ); +// break; case ( 'w' ): // WDTで再起動(テスト向け) WDTE = 0xAA; break; } - vreg_ctr[adrs] = data; - break; - - case( VREG_C_BATT_EMPTY_PATTERN ): - { -#ifdef _MODEL_CTR_NOTIFY_FULLCOLOR_ - if( iic_burst_state < 4 ) - { - led_red_batt_empty.dats.dats[ iic_burst_state ] = data; - iic_burst_state += 1; - } -#endif - } - break; } return; } @@ -345,10 +318,6 @@ u8 vreg_ctr_read( u8 adrs ) { return( hosu_read() ); } - else if( adrs == VREG_C_FREE_DATA ) - { - return( pool.vreg_c_ext.vreg_c_free[ vreg_ctr[VREG_C_FREE_ADRS]++ ] ); - } else if( adrs == VREG_C_RTC_SEC_FINE_L ) { rsub_temp = RSUBC; @@ -360,9 +329,6 @@ u8 vreg_ctr_read( u8 adrs ) } else if( adrs == VREG_C_INFO ) { - // I2C_mを使うので、ここからでは割り込みが使えなくて困る - // なのでタスク登録する。 - // 強制的にI2C_2割り込みをマスクする renge_task_immed_add( tski_mcu_info_read ); IICAMK = 1; return( 0x4A ); @@ -385,6 +351,7 @@ u8 vreg_ctr_read( u8 adrs ) // I2C仮想レジスタから読まれて何かするレジスタ void vreg_ctr_after_read( u8 adrs ) { + // 割り込みフラグはリードでクリア switch( adrs ) { diff --git a/trunk/sdk0.9/vreg_ctr.h b/trunk/sdk0.9/vreg_ctr.h index 86f1a7b..19c1557 100644 --- a/trunk/sdk0.9/vreg_ctr.h +++ b/trunk/sdk0.9/vreg_ctr.h @@ -4,8 +4,12 @@ #include "config.h" +#define REG_BIT__SYS_MODE0 0b01000000 +#define REG_BIT_MCU_FIRMBROKEN 0b10000000 + + // VREG_C_MCU_STATUS -#define REG_BIT_STATUS_WDT_RESET ( 1 << 1 ) +#define REG_BIT_STATUS_WDT_RESET ( 1 << 1 ) #define REG_BIT_RTC_BLACKOUT ( 1 << 0 ) @@ -23,15 +27,17 @@ // VREG_C_STATUS_X // 未使用 ( 1 << 6 ) // 未使用 ( 1 << 5 ) -#define REG_BIT_WIFI_TX ( 1 << 4 ) -// twl bl のミラー[1: ( 1 << 3 ) -// 0]( 1 << 2 ) +// 未使用 ( 1 << 4 ) +// 未使用 ( 1 << 3 ) +// 未使用 ( 1 << 2 ) #define REG_BIT_ACCERO_ERR ( 1 << 1 ) #define REG_BIT_GASGAUGE_ERR ( 1 << 0 ) + + // VREG_C_IRQ0 #define REG_BIT_VR_SNDVOL_CHANGE ( 1 << 7 ) -#define REG_BIT_IRQ_WDT_RESET ( 1 << 7 ) +#define REG_BIT_IRQ_WDT_RESET ( 1 << 7 ) #define REG_BIT_SHELL_OPEN ( 1 << 6 ) #define REG_BIT_SHELL_CLOSE ( 1 << 5 ) #define REG_BIT_SW_WIFI_CLICK ( 1 << 4 ) @@ -51,7 +57,6 @@ #define REG_BIT_BT_DC_DISC ( 1 << 0 ) // VREG_C_IRQ2 -#define REG_BIT_TWL_VER_READ ( 1 << 7 ) #define REG_BIT_TWL_SNDVOL_CHANGE ( 1 << 6 ) #define REG_BIT_TWL_BL_U_ON ( 1 << 5 ) #define REG_BIT_TWL_BL_U_OFF ( 1 << 4 ) @@ -188,9 +193,7 @@ enum VREG_C VREG_C_LED_WIFI, VREG_C_LED_CAM, VREG_C_LED_TUNE, - VREG_C_LED_NOTIFY_DATA, - VREG_C_LED_NOTIFY_OPTION, - VREG_C_LED_NOTIFY_FLAG, + VREG_C_LED_NOTIFY, VREG_C_RTC_SEC = 0x30, VREG_C_RTC_MIN, @@ -211,8 +214,6 @@ enum VREG_C VREG_C_RTC_SEC_FINE_L, VREG_C_RTC_SEC_FINE_H, - VREG_C_ACC_HOSU_ORIGIN, - VREG_C_ACC_CONFIG = 0x40, VREG_C_ACC_R_ADRS, VREG_C_ACC_RESERVE, @@ -232,16 +233,29 @@ enum VREG_C VREG_C_ACC_HOSU_SETTING, VREG_C_ACC_HOSU_HIST = 0x4F, - VREG_C_FREE_ADRS = 0x50, - VREG_C_FREE_DATA, +// VREG_C_AMBIENT_BRIGHTNESS = 0x60, - VREG_C_BATT_EMPTY_PATTERN, +// 歩数計の評価のため... + VREG_C_FREE_0 = 0x50, + VREG_C_FREE_1, + VREG_C_FREE_2, + VREG_C_FREE_3, + VREG_C_FREE_4, + VREG_C_FREE_5, + VREG_C_FREE_6, + VREG_C_FREE_7, + VREG_C_FREE_8, + VREG_C_FREE_9, + VREG_C_FREE_A, + VREG_C_FREE_B, + VREG_C_FREE_C, + VREG_C_FREE_D, + VREG_C_FREE_E, + VREG_C_FREE_F, VREG_C_ENDMARK_ }; #define VREG_C_INFO 0x7F -// VREG_C_AMBIENT_BRIGHTNESS = 0xXX, - /* VREG_C_PM_INFO, // 未使用 diff --git a/trunk/sdk0.9/vreg_twl.c b/trunk/sdk0.9/vreg_twl.c index 8b00ebd..2a162c5 100644 --- a/trunk/sdk0.9/vreg_twl.c +++ b/trunk/sdk0.9/vreg_twl.c @@ -5,11 +5,10 @@ TWL ======================================================== */ #include "incs.h" #include "jhl_defs.h" -#include "led.h" - #include "vreg_twl.h" #include "vreg_ctr.h" +#include "renge\renge_task_intval.h" // ======================================================== #define TWL_REG_VER_INFO 0x35 @@ -19,9 +18,6 @@ TWL u8 vreg_twl[_REG_TWL_INT_ADRS_ENDMARK]; -extern bit twl_ver_read; - - /* ======================================================== 仮想レジスタの初期化 ======================================================== */ @@ -95,9 +91,6 @@ u8 vreg_twl_read( u8 phy_adrs ) switch( phy_adrs ){ case( REG_TWL_INT_ADRS_VER_INFO ): -// set_irq( VREG_C_IRQ2, REG_BIT_TWL_VER_READ ); // 速度的に無理なので - twl_ver_read = 1; - return( TWL_REG_VER_INFO ); case( REG_TWL_INT_ADRS_POWER_INFO ): diff --git a/trunk/sdk0.9/vreg_twl.h b/trunk/sdk0.9/vreg_twl.h index 0dc1b35..a1325d8 100644 --- a/trunk/sdk0.9/vreg_twl.h +++ b/trunk/sdk0.9/vreg_twl.h @@ -102,12 +102,12 @@ enum REG_TWL_ADRS_INT #define reg_wifi_led_blink ( vregs[ REG_TWL_INT_ADRS_WIFI ] & 0x02 ) -typedef enum { +typedef enum twl_camLed_mode_{ TWL_CAMLED_OFF, TWL_CAMLED_ON, TWL_CAMLED_BLINK, TWL_CAMLED_DEF_ON -}twl_camLed_mode; +}camLed_mode; /* ========================================================================= */ @@ -116,7 +116,7 @@ void vreg_twl_write( u8 adrs, u8 data ); u8 adrs_table_twl_ext2int( u8 img ); u8 vreg_twl_read( u8 phy_adrs ); -extern task_status_immed command_from_twl( ); +task_status_immed command_from_twl( ); // 読んだらクリアなどの処理 diff --git a/trunk/sdk0.9/yav-mcu-basara_sdk0.9/yav-mcu-basara_sdk0.9.ncb b/trunk/sdk0.9/yav-mcu-basara_sdk0.9/yav-mcu-basara_sdk0.9.ncb new file mode 100644 index 0000000000000000000000000000000000000000..c61c6fd818880ba2a186def69a1199865f912220 GIT binary patch literal 855040 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
8w7T51}*oEsHX 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%0DARp0o4Pd3kEQK)zIx zba|dN8>+tE;=Ht8Px>Y}0C}a=vzo-s&7kM1j664|$VqkRzfMlOXV|3tEhTyJIyl$q zKt5~I;;(RZNPb$=bWqRPbbB;0mhzK%czNw;_0-JztVqUt8u}wk*}eQ}CF6biLh7RG z<78x-9D9@Y^#+p-M2U9fh&gGd0P#my2vna*@BWwDUk$V@(~^3y8k%Uzw7Z>Y5RN>(NVjQlJo<0Vg}ujBMBpYLhB^-AzI zBtteA!ngAGm+UFNE$ar zjjx{YB@JrL#}j$!y{+l%UcT(}>5|-Z=zDYSuV?72Ux24C98XU>oso^byv)=VXw8KD z)~A)-)Ris&N@?-?I+4=+#LK;q z0_CqLEp0!Sx6W+Lj~AW)akBX=L$0@CYss~NejR3I_M+kO3f;7^deu6+WtlQq7s*F% zJ{{8UBaTk_DNKu>?PR<>Lk2ppGC!?&+~jzaPr3Yfm3^73)A#4KCEhOinlVRZ)Wsh& zWG6rCX=T=OI(;~=Os`YXEuZVjy5!#(n(@&WgVwfvfjradqUy?t88kngS8kG5`It&L3BI0#K9%7wUzend?yUQ&v?iTzmYkW&E-ooc z@zqm{!^#lA2N87Z}YUY4>)%hFvo^NHhCXM3f!Kbl+c?dokA zJjow#nmo>O?c-k=vTTDa)8rwW)Hxh!`Br!Ozb}KPqR!jq>+MeUpi4%XKL=#dIU$QG z8F~9NtMg_3v6HoYtfujFiPKeCM&9!GoR;=JXLsu}b#p|yiZ@v>Un@UI*(V+k9r_o^Jw;Qs&DeootEzz zPRG51X}efI=V@v0@irgO&&5tZUuDQy=T@ZU{ehF0&bCTx7d8H*Z?`V|e_Do22E&)q z`)jNJo?7%(HI~@S`j$=7;B``JWnRagd6`B-JEt@CdF9VJnTOZgMNS4MWZ2B+4Eg*w zMLy!?-%dUkWbi%^5moYxbNBY3_r83vr_p=5vxgyha`)pLZJpdDIh}QxCYKWX6(IR` zHa`dGf8WvnXCVGP7q4?ilXQCBv~jZ6xpc{RFZY2~cLS_1?X>s{onCZCo#J)HY4yJ> zEB>~hoZwM0DqrJN`u5bGF7}<|*8#r!JHF+MJxN=vbJnn0d&rqnpiN_|TfbE-X{4@&-nFY*vxMDE z{S+DL$+w-1I%Uu(U+if#tabKsRGx0Uy?{2qI{sp+w$fS5s>|(I0o*gA+{ZFxshOg}a&38GPw-3nUEhmru8Fc9!!(`dsURt3AaVWp`$#}1`J6+j2KO!xDrn5)+ z*-wkV!0Nm-Drpq1gTpfD?iS$rCCBqC8S;KSg(vBBjpZq4&qYh4xxn$PvuM)dUvywKXFx9Ud7}N;I1DMQ5&q}u~EgwD1fAe(X zWvus|&V5Oy^>z6ar&pczlNR6C=|Jc3CF6bBRjhp4+p~C*@jn0CU3#5qn2h)7TR7Tv zZgrXrs=;?HxG!@ucqLB{KA#e+hYt3fgJe0LjtP!WogtML|E9B*TF~KbB~Ba9P1b;h znm`A}x7X+K;>&1md13uvMm^BE7-{9-=H#Ta4wLbozsgR|I+s=Px;%Zd0nI8f%2lAV zB-7HDJ2{`7!oTu*!||{4RFdgEZ}Xk4R-L5{0-^a?ZG}8HJY4NW+{psAyWW3K` ztynRuGIj1(GT!HZtD{fnG^fQ^wXzu+MP0Uy_xV?H^ba6?B`||Wh zc63HoTDd1#zB#`Gxu>NCZEi#+$v9u8Rtf72#{}P*jTk~&ZNEQ{Br=tZJ zo&A{1+tYT7)6LoBot9Q@Ue`RjeA@b!F4h(V?BWDx7bD?2EpL6l^d!RftwgwNR=tOM zHt%M3^y>2z+t9PGxVm{x2JKIv+hp0kUP-5W1oR;<$Lf3NOsq7S?d|x|nZ;@KvWUE+ z3cI;Ex-f&jK@gWlpS}%?m&I{jkK$QZ2|BwZBhO)Em_~P9r>{BKLb6PszurOnJDI4Q zSkG~6ZF<}qVY?!uT%9dm)umHUtiiN$=eoK)J}+-y7i-(RyO<-9leb$*Nb!1S$?tV3{mNRv z%8c?$r~R{hlAD)Zd-plA6n(mqdQhpw=5BLffWBIm^Fnh~hK|={(4}+J)A*{)8@L8s z)#9#m=h9@?&Gm6~HfdV?G^f+{0lTh@U7t?*rH*H5QTw}K6`Pl*qgu$fGkJICNqKeK z>U;a}JbA=2lRjcwcrb(KSplAlu+VCj=U(j`n9W^0sH!I(=|+w#b=ZPM0raq}AD+Y2}{l zcv|dq?f39`UDrY8<Qh_7n&0Ub;OAM#&m(iw+YGgDRU2;`xAlF{ z+Psp%i_WJ`m-Ru)%jTc+**wX}ooHdb$Dn(|FVS;Dd~OhXrJ|!O85U48C>laT-m> zIlEisWa{PY+viHWU9{?YNuW+tcXi@F8FcHM@wBp^wsaSitqqi|{i7;d=i8>GKgY@Q zhm5jyrg&P~YEEXqWTd?*!v-G-+F*V5Aa=KBa;KGhlWV_D2-sFt;-AQ{51ntFmhZ7n zkLIp)+fu(%XPu^{?c(I9Gvd?YpK`JqOx?+kR~@Xz+eH1g7c%I6AkTiheU;f7U1+Lg z(EVygzST3*?UqNcFSFFr+s4cY@cX3Wcgx&#S*qQ82b%nQT{7_f>`Jt%wSX?BPr1%m z&X-rjvvZuhb>4Vd{4q|K&t%x&zg_t%TbFP1HICca_6Iwey#oAKb^I?1*kCC(_!0R_ zr~dN3c~u|d^GD*oLY)lxH_eFq)alf>H@=)g`ue5w!g8Mz(Aj#Yv;E*XO)pg}&ssUn zIlviowaSP)KT!4)uIzUMHeSuyxXvq1(|2cQ5A8C_o(f<37VuX!YMrhU-e&4YHs3}o z-Rz!(qW#m$JKEV-r;PHBO2|<^v;G0S zAMW%%C69)<25OwYyLmRi`y-C``Uoy5JOA#h>TKrlyu7_m)KBPy+@vp$Bj~QW<|cSg z>eACB-jB`5b9F|#CjxTn=;U-qM%u3e^{xyHIWdEtDH(0Wd&oA)qnCrmNZKLPv^d%F z-O%ax?I?}bLLLQ)I@6PJ_rn9SIn2tYH1|`0|A!p^muJv% zZie2!4DjE<@?V;JGs6z|KrkV@IE4C?l$*CFov5afym!f0dqaiSpWa52O);|331MoX zWjQ*pxeMcb%QEvmViJbLXUintB{A;yk4{Ahd?)Hp4CLzFl87hy;*q-X%c>%tEbhL9wbZYvuoNceoDEnLV zQ%o8D^6PA+l{U=xs=wVJAiD=#`75xyH2PP#ciE4Wk&O3st1^<)*)_)y8M3ePK-u@Z zvLDId?HqI?-n>rzcT9=ZjmDLYSsIY-6jvXg$jJYK6x)~Hik$7&3+Sc2(@Tc{Z}&Og zF3zK0)}Z_=Ir=p!Uesh;*=>DiwKXqf(0&#&PwFJDowDWF=KhtDwv;lx%`2VnR~29} zs^N;&F3wv6vOUDr*JXL~^L9~a`Rir+1>|$Dlh0GwU7FoAhk`MI`dkB>d@qByi!*Go zQ6As2C$(icxQ!(uzDvrw1oVEU)B8sm<=>Jg6R#JY)u{G#*MLm!aWZ)#AoD$)%)iVi zyEXi&t@dpIL3_zgbb?2YZ?PhJXgPFSM7uUHz-K$h=k);_D|R;aLk2DP=h?omyAe{T z3uwK}FB$1KX4uAo0U6%yWcYeOhGU%!|H>%$N$8eM`Zgz)pvF+@nK1!*onhrw60Oa! zz1-S#TUVd9I3un!Bkr6)9jQqjnI4eQS|_770(=(3=a&KbjdAj;l|j?N0U5P*HuY4V zP5CyX2z$^7dhWdRcI`&@E*g!E%bvY{{JogBt@^hOGH7d>7w6kreX~p?-(;KU+lC_6 zEfw0lwdbm&?DIhVZs@+-Ud^z9xdENr<#e(+AotNu?yd9a_q@x74i3;?2-O9a{#u0a zVH2RgfusMFfc{Q*`s$|+026TIa)9uXxd)5fj#(>>aa(2@-Ko_q1OplDX zr2(DX>2xwZAlCwLSug2QaL%+6iJR%Frc(}aVQ>t&#?V-p)r|uYrR*kt!zdG%8p#w zYXY?2;b47fxJx|gM7%;|6B+IJ>O{TO&TaWk z?+NrWg9AL*bUb$m$Sg-L%Kw#s-ex+z&CbxrrU1{YEzhOVt^wL=INBx!WID>p^rXPM z<$CvS`5-|1Ku7!Df%2=n@`nUu6MsE%ZbpE=RZgc@1nO%obW|JYjK0pvu&DzA^p!dK zz6|hps^f2Ao_u`!dmZx8-krn99~LXx6UE2lJUwVn)V}vHGXpx<)#{)$_d#BJv$dVn z$@28gu8G@>xb+0#uDX;zJ|JJef`3K8wpdPYs+^GCKHn1CR_>S}Z>^Y15O1x_s*LtYT;Hlen5d4|p0pHc3afpRM` zW>ndh+uk${$n|C?*Tn&Q*u~Y!(vj(UImOB4whY>5ID5#Kxpq9|SPQctKz||hmpJ;L z&fx#r-pMHU zu7Hk5S{)BCb+=2`ab>$Als-;?=aU`JFJ{oS5}r$_ZoYrxzsYj&Tm;YRpUDSk6KF_# zu86u>Wa(&4$e5i1`dR7p^HGKzUd^C$Q%1TsGSb}@&}n7f)s?JHdzmo-npZfQ+XZ;9 z1jm&u?|Q=+^GraGJG;92eFhIVrnJpu$-d`!WykQ5={C^M>G;?{ovBZq=>h#@U!i0F z-l+oBg_i!#=Fbe;9uLT{h(1rDm0?daIUvIuoeXn#r?;gv-zt06| zE42MFy?1(=2?5!ie(mSxOe0lOUG?D9>@<6nhd{P=GJSDy6ob--S#(z4ef{-l6TW;mU+$>8^*fWEGC zw%REp?Z*(FW>fVmWYylusgr4jKGXVU&7uF8JQ;d@<($5{XV9<-8j^L_+f%&?8f4Y2 zO`nWB{&w{SQtajHNF9E)&Y*iiK<+y_xkuf%wL@w>4DCi0O!8XcG(Kit{pfDE~H$*ZG2?`4!Ly$;Pt zJ1fC^{4R_4^4Ec5tz4?hy(%y=BaiCHSN7*G|E*ug&9k>9z2@3gPj3&%@LDIsWdU8D z=ybUUbfn3#I%SB`I?$qe?5|k5#?)t~tSv1DCT1d(oy^1Ac^zk~4IDo{t*uZCBRC3Hc{&uL#){&;nNB-iyC|0(_TQz8^3T1>|~-lWSGz zkX%%TF5kY@a&&0cphv(4hdCSECBW-dj@Q=$_TPy3$pQMSS^D>go(#}`wWEJcz%Ke& zyC}`o&6BgQ16ANp_3PSzoC}a|&dOPJ@yoGE)M4Ep>eD8L*$B&VGIf*hgd1-w)5Kld6l!OV%18)w2Th*SGZ7i#7&i zdX8PCHbDDQNBjBkzU@0Z zmQiQgqD29@)N}T_Pe!@30z6&mc-k4cB-=?}r>a@Gu+J)>?;%#-rMad5pgV4R^k%7f zZOoHzkG#&CQ1+xen!QalU~VNkF`cF>ovfB;lzCWQzP@bPz;^-tO?Ud+Cm@SbCyPr1 zvea%sy@NM8`}SpeS>_n6EG7OpN1KoL@+hK)FAe0~&E=5LWp+uIXD`S1 zH^FwZE%j2Am-1dUW@XQT6G(IImyTfs>J$zH$7eJ<0KR1~66Pf+g{O7HCG-~&_u1a+{;aOwUPzwvS>tT zQb7KfI{Dv48A%#sZ%Q9gifrzgy!?H9j@-4=^7Md=TOxxY@Fy928`fRz#{{?=&&aC0 zN*3L-t-X6b)YknHkZ)%v-+cq}JcZKaO3 zr2*cKadPb+p#4%yd!bnyko!eW?rj2c@8@Lqw6lk}mTj$f%hWIEC1pI_JY9%>qpTU95wSD`zt9a(G2`C~s!0cJEnGXVnC;tID7moz}phbTe(>kknLW`cC3?auK@p*9siF9_`BZGe@KAF zMUKYz1M*ww;X5`UpCcTN$LH~=K0<_U3oMUa%;y0ej6nx`I34T&A8GZjoP1hm#9f4ajpe^4#6YvuxLN zyE)R?bRWu3t5X7;ZZw1WOcTAc z%mUNamD0epeK4l?15+GTjkNnzWsWdf3#3p_Gu=JAowd;9o1_ z5(b(@lqHS|qDE2UXePgE^6L{$g4<|5=kGu6?`!idf8U#*-QS${aSkn__2i`-2AHAf zsDKc*ji&02C17oE)& z8?roH@dBeWqD~FqP_F^O*~+HOp)G^yLh*D7Inr5&mctDvrt>HAk2e%$cS# zzl1;7yy{9_Z2rV{g_~ov>Q$kB=CU5146CBmO=ywWGRNON;1E zFe;%Y*3&%NFVbFe*+MLjcaev@p{f=e=HJXZZd~eJa)vQu#oOYwvWIb3+NEvr+JnqI z`1bkuc-CC&<+pu4UWwJ7XTC6>k+dd!9C+x)rm~HX#IMhr3z?a$QCR6*1pbNf^ zmz5Y!DV&2kbpEo(OE!kKx*vF*iCqLj&nuo)2GJykujKIJGxk?XZVb-MrR{41q}^9j z=&jC{-Y}X0B{MTCQaLKOHtpG+l%exnMc+6xyP{^@XFX2p`LE3f+s7%NHP;|9;l@Q; zo1!$onZJ$B>k_s}w5DAgY7sSrCgILBS`{UYpI}Zlj~mUIE8R#_DU$zCJ#%)n*p+aG zS-eAxJIZL5U+G4eNwmH?*I6=Y$*6cQPTSti{9<%wsq(r28g<^C^7_H-bW6-LjhpGGH%|+%Ws#ZzV zDcUX4sik`65?X7Wwx`^FGV;fw(6@HSkV3DTD_jZVj7|$xnkD8td)l4iYej0Ogq>$z zcVlY$y(e!N#gC6Jaq)Xcd)u>0g}vP9BtE68Ona@_AYuPyo^-l-%jh&T;r5PnuBJkt z+jdEzmZqy~CC5iPaZUMbN4p}=R*GL_eN`wlF49hK#qVS4MoX!o3jbjWBb`d8a1&Z5 z?Sj|SqwRTG3hfhV#U$!LlM~F-wDGE~ifL}w8OlCd(+YQtHejjB=Xmps+2AB~h`HF+ zfD4Q~$|>D9M*fi$`qs>LTpncFyP9;W>ES{zo2#83Z?%0Jm2|0T9F<4vv#6xoIHBe` zXCJQ^wJyr_>_}(hDt-}V>1;+}f3$rWVV9X}jqlAIWR8N~Goko(PJ4LMyoHqaj>bp* zE3~ikhn4;`qf;vt`p&k+s(X=nfOo`0c=7EO>0EEc?i6V^uR@m??e9})fzb@7Li5eZ z+(g9`^O5OI8inuYbZ4DAr0{;`CEI7BDWm>K<|icTOk88`L+6r)Xn)4`sg(CVkOqoD@lpl&`*uj3W;aWt)$;x^gS1{G>$wBJ^txwdtdBwm7s29d_Hh2PnF zs@H)XcRGuEi>vNDRgY~{OxgQLL?tx!tD@^qYUw|zd3|Hs{Hfu z8It#2twF!bnDlTg!r}_l`aY;g@sl3Ag zkC(OS3qg`J;wKa;;437?RpPrK4n-9`f#&7_hbuNa zxlo~{LiSLVvIjYA&WL8^SY{q`q2{zUwa}%W?MqMM5@$PWjeG;>*%Kn24yjOUBcJUG ztu!ZL;Yy?Tp}d<4`?vK2q0p2_p3M~MZrgv!=W)KbYDMzkD*PWtzQGh46v?ZPLL(z0 zt?c&0u8xITeN}WNO0mz{(>WEo#WZrc^s^pvMaOUCC{JsOZy)({hMzDS_@?+5XUge) zp}1Skr>o=8%;*9T!aZqp2Bbo5j65SN^plaFDTRhd^4_A*9#N^2$@EAkLJRkW^)07R zyGW-+D)g!K1EJ87k=`UN2(88Yw3jnv7{X&=6z*YgeETR)kysCra`UP>MM z+|8mL=q0p|M$@hz5gi#F8=V`?jdWs?crB;J(#dElp@a2*tkBO!-tiP_73mBsg}PfS zQ>fI;z9Ys>jGo{*<+D3ItDNKLh-kHw%c;?cP6n4+-)2fZB$6jkg>E!gyS&?0cuJR) zpEK);-L}5P{cu?t=B|1&Q8}nTqaMvefX9m({nGFIY$$#{u2=DQ#N7#eT(9C)8{TG= zzv`*#i_$$xVJ`p2X*#&7^M`LLz|r|Q)sZV6wQb779e{4Y5J10o2Tldf1ZD%Ow+E9# zWvYyLZc8~5!6p7;5O;b)JQbPeL5c?XLa(#U|F03F6g9DrIEA<>wA3rTXs&La<`I=p zo##Bf=~C9V64SGiQzcuo^-EGNF)#B}ddYFQ8;yVe){drAr$x(V^MkX1zpeL8;p#;4 z5u?x{k-YXOG&=Hcf+~P=qeWKf3N>1C7^zVY*g>VSWP4NilX0^z{mA`xET(9Z2~X- z8Z(SPV>Bw{^NH(ud+dRJRstW_bFKYQUu5g^aV?C;1!^bobTzo*b|*^U)ehfI;& z0RE12Va=kZaFIYqT?zzJdO)?$V17eKY9!uBNvIt-VspgRR$Rh1yhnZ;rP+ z*Mu8kkLb%4pf7!4b-?e4UY&#jp ziZ+EhRgCoZAn$=j>x6`_Z%t|_H3VwV7AHScgGQLh7NZ?hDzK*JZ@0`Hbu=vVRW$?>*`?&f%PWTCY zSxdS4dKVtAsk3WZ{0hD!839P(Ygzma<_7NjCh)Z_{(9So*d>9lWAWFS>$vw#;3182 zm-ELvErFN+xCwmGU&~#ix1Ju2+D3`xrBZ1d@YyzV?KXRX%z%y_G{s;azmn(s1zykdD{4p1mz<09v z?-MAg0B$T{RF<7#cNK8kt2-W>!rKJZ{oX! zGei>j9u}{8B<64u_?{O38Q(he#}jz1*`B~x(5KwjB=Eg0UUL)l(-ZhU7XLAQKw}ms z@H<-kN9H5$a})T!7XP97kozeKd_Rl-fG;rQpTO&@dV+bMKSnGQ_yHFGo_UY^&;)*< z#lLIb<=!QMA7t_GFx$!ZLjph8;@{@mkN0u{Kg8nS&c+i+|ia&Rye~KL2qR|Cs&uT9Lr-ZSjwqN4YOa;Ky71!;Halo_7MjkHtS^ zzm3mK;3ru8gN)l6GcAFiXz>p)qDxODf#28S@3TFgu?hTs7Jo1ElzihR@cUc*JoAMIg^?s< z=V?8Ds>R>T`T$146VD%R@hchkVl=;cMSo`65f*&E%(`{ziDkGPCEgXfjM z@JCtv>E?9qhbQnyTl{H^*Bi4}0)LFf&onc+4@%&VwRp|9qn8B!IE&Y)8TBH8Ki=X` zG$(TZx@;>w(=7f3M(d4vJ%OKY@zag&4<_(>Zi1P{AASxJc;!2RaebAuFo72x6IdT0 z{!UHcPqO%SmB626@srFX?iVNU zXIuP1M)hMx0zb>*4>YPzhbHi|Eqv$-FM>xJtK{d!EJb%p3)C8VUS-i{HtPJHMI0FR=Ld z`~T?#{(Os%zyH@H@E2J85Hp1PvIKsi#Sb=vxz9`BFSPhUc4Yg61pXq6AIO&+;|K}- z#TKuxX#6%O@QWch1pWq#Z^dW?vuz3djTRrz%iNy8udw)X zQ_fxM%Y3;jEk2$QVrrfCWM%@!ZePfbbSZ?X9JjMaS-_*E7k&vWgZz^}IW zcwVeq0)MN;$MZy*sq=K+X7TYj`fruD;%~S3c--o}1pW?-kH^tp0#DOt-#cq8J|5@R z*~mKYK|XJ_zh6E~wAVJrdZ8RCa*QzNn7PX_)+|5cI!8LksC5pH7xI0cV{}A*+j7jN zX@8W~N9I`hmt(dp$ElAwc4+31c#hGf9CIHz=KFJ;2$^F)es6PFz4l<{s4Y2aQjS`dqXy;}?aDD~lcSdAsKGgEcaEB$ zqgBY!V&rH|a*Rpk828FC-j-u*DMw3{qZP~1!sTfFa%NXx6tEkxJFo{Z8W;nN1@;8? z0>%M*1LJ{xfC<1vU|(QAV1M8M;6S^Mr#U)o5A*`Gu4g=OAaEQo-Gx2=On&?4G(UJK z_2Y2hDBxIN8gL?T5^xIeU-Y^O_yW*6zfr*Mz*oQm(k}!q1}+6I2d)H`0oMZ811o@= zfz^QO%ALU7z?+X3Z3OQ03d7El}08R!P|1o{B|fPugeU^uWd zuq&`TFb3EQ7!OPY_6H6E4hCidY7^%IivX&ES;qY)Kx4PJa=#O}7kCJG9MH2(Xz%^= zKNs_!<@f(B{{QwlpRec%rBPhBjIw=v@)^-CK9l(;;|CBw6403S_nlTtfm!eXZuwOO|m`K_&L80?iTx&6|R@pcQGY?9enveRg@)KMM1^j! zU*QV<%Z?8y^o||rQ0NmorlQcMigg)P?YNI{-`kN7g+8|5h6+7oM}HLh&h}>|{lk#H z`s~6^w_o21J!i*96#B^al=bA{JgKh`VNbW?MGAduM^qK65~+`-&~T$(u0oUTcdtT^ z+mRK8KD6&>h48{yCw}f5JN_zM@<1oT~VBg#dHMjLpp-%Q| zRH1w9_@F|6SFEh77O9UX+(0`@sL)@wpQzAaJJPGrBKr-g(Cv2AM4{Jgze}N>wui0I z#ESL0k5;VLeZr1AD0YJ#;ZW##JNBs1pGI#}$x?LaO)qRsqrQ?t9c=Gfp~9ro?^YZ2?1bxR$9@%BV!yf-y2FllD)g%zfmf(By4Ts!@%HOSxP$HZutHbZ5o(35 zv16hN{bIj%6^bH#cS$l+v9kYE*rUE~6@Qu?3!v%Y8(HJ^8p|(b{J&bH{*|7nU9lSQ zZacOi+yi#hU7_pkxRpY$7>!&i^o1RBR_IbY+NjWHW;bLfI;xPr#_)uF&uA1vp*2S1 zDGEJkMSL^Ug3_iJ!pm6SF9jhVMi5(d)JP?D)b-Q!&j)AoikAATGQU;7e)FW5w4H@ z0$1pG`wgwok*2!isMwCn2zRF)iC1Wg?E@=RuVQ~iTRSc#+{1R}QK1vyq z*pJ{eI@6AT2zQ~Kqfls>Q7>8{JcT*yYhy?LgnQPGF)H-39ko>GRr8H&EsAU}M7VPM z&8g7Nc63dl$Bg>P3YFRsQia|y>hmg8WYim1sFs=HBvduh2!wD)SFAv|%zi}(*Q#Pa zMOULQR^dk2u|I{@*-=J?p0@K)3RR8tC8kh!`^~M;K6W%lp;OHx3_`4AK;ti9U&1Fa zi17vYpBS`w0bC2heZk$xeG2zCxo;${1K~>umrtV&IDtBP9FhW#okjk0(LVTLfX*?M z{}K7d(pkb0VV!HPb7JMk7Ro!d-rC>w}}~fRrQ? z)kE)JL2K)}n5XWE$INUb|M};-5WagsdR%kj3Y+O|66eRw=Bqls2j42YxxGt+mv39P z@)i|qOgVq7vdk#E>8|N%kI2P72xehtmB_=>OVD1G!9D`rX*@6Fy`~jfJ1yTf-qUr5 zrK{X5>9K9Rmzid-C9~ehHkrRqKi}=^x}CwKwD?|8O#9mze2)pxcDs|=hCJSU*%!c9 zb0qNZjJz8LbhbM>8|8HNaYp)=17)A@%I+4>+2KxSx8%vy>kf~s{8ia+zX0#IIo?0Z zpiOI2`G@vp6e#Z6Idq208ANpv!r#9*+*_V5+m{%^CC;-kaWbs$D$|+LKo5I$cC(`(B4!`f@(dG5n%+iIw zv4D=|Ivv&f2i>v~?Id8FAz%Z$Vgn_}f1`E9xKUkO(Ds^^D!n-ie@ zTt|EJ4B9sZ1zl-r8(=N6mzEi{%?-%=P$%!d z1Nz#|>Fc)TTJayZ`;wR1QqkD}ZFB*;0o{R10j=rlOxz6Qk>o{ffiC&2x^wxqab6eY z#P`pTzxwu)fxqIFl)}mD*r4Ke88SFEpr4UYw3E}%-OIP;AKOJt*(H`Q#t|o_>!6#n zy9Y?G_ha1d#W^tS#mII!GAU;yA-3OP89WZkh*Q5f%?9SUI_byqy*y(Iw7Nd7@7*)x z^JswfdeGbnxY*IYYX*HadZyE-9#Ru?;-Nccl)nrcRiE6`?%&r_uu=7UTM)NCKx18= z=m=coXj~A`_0H&egwypifxPOFM+e|Sm)GDtn!O!2XP#kPhAcWwN|!}fXDcsJezJae zzRL~YMaVHNPVKf0N~>+^i0?1sxq-Edn}h?Aii-!=>dv+u5K- z3KZ`z-&c(5Xg9Mopqri0&2XoiLo(z#mAJI>TiAB6x*hpUv!feGrL%3B#VG!8`Boa^ zIuc8Nq0{;BN$F*DaWd+ep`XVB@;$`0wO>$nnr_PtSx!HvX2|yY4BC##s|Vg*n?tvsbM!dh@4Md0yqo!ze7#L1<$ZyZ_x_X8Y3_`? zVaLxmt|Q15Tht~h0|PRehjjS(>q&mcC10%zj^8-(x_$Y5_xM6(!xxvnx%`=AT1OM> zCFbI6MsYN6=I@%rQ2kRr%2%niM_qYUX1-IPyyCngu#xqFu4hHTaI=18oU#@(fww-O zcd-oNWZqHoQcQulVsIR)3EgohXZ&bwql%H)Uglb?MJZaFn<-N|Y|nRSFUB+bP|}_J z7OnLNY#-iQg_K@w_h7Xm)SmH(t@cikcyAT4hr)x} zZ)@+qzVu~|ygKdJ)wia%5$(upOkUo;4v=V3ZU;;tF4?yEcco~%ETi06%hTS9MCg8KwILd>MDqLvz9vOHXt5_t%f-?;quUGIp+c;lYI01DY#Vo3ke={QO6; zrAl^K*VaAN0dXx^2;15mQ4wn5Lba{u9K~{i^Y-4x4{))~Dr$WLOQ~|yGvY>Rimluf zYGgWNehSsKGEk_tm9|2Xa7+GJ2XOONIlvNEJZ`u&fv;)t@tEJD1iqHVmz#3#a}#*U zS7oS_Qxo_)7T=WBA&kl=@Y0h`AET+Z{+ql#)U$Z?MXAY&=MgtoykC1%0xvrd=QQ(1 z`}ci5G!% zTzr3D@GUGpUPrVpftOyjOO!^n;(aLl_3uWl zInldPYe!z$z)TA8F7P4n8SoYG9q=>o7m#}f%L1wab%4e|bD%ZQ5$FXB0uDm~(tQ~~ z{aMG2D}K*kM_JqA<8PdQ?!%Ak;XnQV#QXOCxj#Sd7yQ%zPu!1~&d2Sxegxw6Ri{{d zlFr!w&n(v-L%-XnbY65hRYv=ioP8W$Z23AUng(9`lsq1ha&^Y16>}{Ky!fW2U`IBw z34C1N+VIw6Eedw#`#W*HitEW_==Auw{>1g<^sUcNBTKH>zGo!xas7$g$0NZzI;X|; zC$?j~c|AU^Ke4^;zcruZ<9ZU?Q?fq9^(1aDWK&t|oyHTdwNH9Z;r#VZ-ZuSxB*avK zHo+LevR~P(Z0sgpAlg5HIL(Ntq(dAUU9k#fdc`V~m39>hjVIFIg|X@}^fe~1Qfn&n zut(EZJ=L6z&$sjNI<%0l(M9+@SMB#fy+P$EVPGn*A0|qUd z^8F6qKWJ#bdG+gv$amp-0T%aqgKDaYSg zIe*OB(*Uau`~HsZlEiSn+lIRDw!-Vu^QuV>ZGi=V^3uF%8n0)&_vq=+n-+hb`~F{q zERyk}BqHCc_WPJ~t&nB1kLG2icTwf*(rK*mf7p8qI4g_xeSGFQwZO8}(hKa;-CZsn zk^)j94GMxFA)+Xubg8J63MwF?SlG3wD0a8LHu~CuUH|L4XXfm%o@dqf|NVXc@p;er z%z5Tq&*VM#+;dMOWp!az!7z=ZL&~Fql*i=L+}czZwoAiKq%4kf6yKRTo)QSX4$Mjz z##4G{YInu)wie6^7`mH3?$|s#{%EXO#+cU%DW7gApDwn1*wbMd8oxY$)RbWi(llLY z*GiS&nL0g1kqVAdEr(%xz6s&E309A;yfbw;Mc_LJ<^mXoQ)GVXe4S@`!L1E0Nar1v z&Zier);T-Pm@ZpWmuK=#95F-Bgie(WeJdNQWwS9pZPIgnA@yweIKx*iEeOhfs;fC6 z{8C={1$(o0rlv;>@m7IZX5;@Xq#V1V9CK|s)(Z(MiZHTZmfEnm!Xs5Zxzf_E;MxO2 zBc54jl)A2v zbmkS3POhVJ^??QH#$&Ir^l1&OO@TD9#!#9^5O-ym^CS&T)XgC>YX!JH2kuuF!lxZ~ zrl!Mg2^%suJGJcX0-iX|^2B3>?( z7gC;G=BK9TIhLO96cX+pTUIX5j%KB$tXiniNOP*T4cS#6780)8!%?s-wo6&GR<9IN zhi)n)uN^|lu%6W6^nh!gQt{T=mKJqF%IP?iQzu(a6GO`B99vFr7n1f<3!&E$_)C?x z<+jcqEKnAP2f2FH^sn81nSwOkCN!<479j34l#3}tbUvkk!w50`ah0v;mrPaoew4W(y$7=JC z@;=L!_tcQGYAE#%J=;Rk{{6UP)9%J@shN?on?lky-=-~nZECvYApe^~{LZs}x8r@P zI#CSoYrxF4?#5@QE}xDlpZ2zVen&o1l`nbuGtfWPJN5zAgwS?@rR~cF^d?vDw@AIl zSoip2>!Pa%^DS>)we#5b&i^i(xA`GuH`ca$nT61|GTx<<0~c7C^?eB6Wmvvj5)yY^ z%Qss?Xmh5e&AgCu>40)+=jx564@fN^H-7KxEhbka4}3}5IQkX0Y5cMP{oVV`mi~8G z`a1uPzH@}W(900NU-tCR598k*lE3*je;0<(=VV(p-BGVn(Z48Gh+ry3rHAA#-R7-& zA!*A)zWj7EU;Jdl^bd)*h{Rh&T^^F|I#RCb!5RdTs*P!na%*eL?J(j`RX5X+0)Ees zUyObrkEznhy2Ul@K7Cx-T_$DMT6HOex1ZX1EMK^Coh|WZtGhzVZk{c>6GLc}CNzqv z=R(4tWy5bV{@8puzNrqr=~GC$UkVBLbO~3fnuXA7e@MBFvHUhJM2?f!UJHqLrj7TC zkTP$FGH+wcd{BryIp4~Y&f^W=AUgTD^}B2FC^WALee$Yrt2%DD^tt|5G~$?{3jkhBeuw4uKMUhw(El`GqU%L+*s_xq$u*BMfl=|QQGc>CFS zUkRakYtX!$-C!96g=Pyx5k@H3jnKcv;t4GuspFgB>fXi`h$icX*^ES zn60AyQm3J&t&1B&!avE<@Ag9I(>x^ZzBX=m=7=j##}gM>o>*E)UA(`Lc-w@;+e_lb zzRi$4jk7dE@uX}ATY~P*E!{hY#L?5n!To%xe#d2PxJgj`rDD*kDjaUg9~Cg+U-Z*klc@cM{@7^mC3#5b(1^J zn(5F zo$t%3>H0dGy5H0sWP|TFXr5k4+YRbg`!=q5q8YIX$=&E*E6%PHD{d z?ylr6^h2@>o$p^#Ej7=;q_68$t%k;Sc5bZKcUV_}O)9ZB~o7d8scTlkh)%Td$@%H+8q@CqveDSAM9^W#LJj^t~s!>%5QV z>QQ1p%KEBw*h*lvO)kDoa3f7O-Aj)}zEPK51j^n%vi}^spu-S2L44+$SY>xNk}BT)#+mt~2#R zaZ(LWN@Tg_9karrrRGUxq|iml{p+V{?q6qF8{Tkx*m2?<))A0%{B;w7EuRwlL8LT_ zx6N>)7|VcX#4+Tx%H1EZR`a|!V)K$a)F;ahb;gzn8V=T*@tQ7jl6%v)C3mEk(_9zB z996-2J7uiPX0nd7j)YKOO05|He?ePWR8{6h@}FBIv?XBkB8gxd8`5L|9oo26tVY ziE;F0;O5^{9JfpHEKs`2)n|bFNN;~l$~K#V>T=c|L*`l*p0-aK_Ev3?3!Y}l5bjLw zXg`?T(cVOtvr+_2meBHl;{LDs|D*SRarBJo|9{7QUw!@$-uKm0qe4h2gx~ko_kZoa zuffUtz6RmuwdWg~QusUfeTA+6n}^&nhxzLQ&HBGT-`iu>|NVKrpjqelKDhqaaLhWt zeORQ%8p3sZW11i zY&>lF*tX5W8CGXt<kb>zDmmkX{)b~F<9s#A;w!Lzph#C3Ss6lq$_#R5rfQhFhl&o8wl`AX_x`fcDhBoWE?nM5XM}7<+nUp5%81D3t z@cY>G9SteFmQr^0RjUvhH3N;BSQ?!X5=U>F2X|I$K^ktbG<;?Jv1RDSz&KXCASCP) zZ2EbYP^vPXVR<@oXX^K?X{>AKA^cRlnGJf52%-H5%bUGIXoD4_*n?aJzg5(8h4804 z+t$&=lpjx&GP(iJP)e1z(`?@U0Dq@SJCdbV7m}}u$X6WDp&>x8huJe_MSr0Ty(;*^z`fE%n*7t z2E7_udVLr|^R<@dtwMN+Jyr711tIy)v3ydpko46kB+oY$lIJT!%4wP{r*ehF*${CS z}#bj;5=HrcKq;A#qQWxS`L6lvxv7X7`2U`xKk+7em57)rP+%C$+xP z5am|imfM7oG&HtpsEhowZ1`b5T^?g1H(IDph0y+uko28m(|2nK?T1;Oc{jxWRO|n= zkhC|lX?JJP7c8GuwtPl~)W!2`T|5#J{}dbl^C9Ik)t1iginl_Wh-Wr0F`ODODSmDLhmyd9Oyn@~D8q;`mqo zIG?bbJbB7Sas0Zy$e27(hwbQ4y2`XRoI`I%xzm-qA-!mU@c+C27lTyz z{CEGaJB9wg`+rfp{vX=^I}e`Y*6??qpZ@1?;YGb=`$TJRI@Yi2Pw_=m{Y#5hbRBlM!vba#&_fPRHq3=O5?YQ`Yt5>Z`$<#67v2H`~G-D=j++7 zUsG37)KtBMnM?n@>u+^N$`Y9G`m}rM_v>xBl-g$AGmplv(b%JQOn~cXTpsy`@w3g~ zTyF+uP|_$}BYQ@$&F;f}49B=X-d0!H3~&8_dspIFf*HhT@AEUJr*A_z=-q znt3>~0{jFy!>p2rLsbGk7+*+a59e5FCbS;vJ)Eg_`GTkiZtjodY66GzJgiKtG3bRS z*AqA#$3y@(_d)W68i!{K-VJlom=p4F$`q~plzN)D)cK@i+qu#AP_dYYA@l#=Ym^wFNi#EI#Ambp$u(J>To$ zn0`mR{NnBm561*MFmo^Cr5=u{dEn+=#$_Iksd?b$UdCA--cWFJFC$kXxb!y?+}z99 z)59AJZti8Q=iy9W6O24Dy~R8njRbIWe&10rr3=5A;O1V&S3MjHAK>2T%ZELj^lbv| zl=SB61{V&?qlukg;`#}Pw-VgU`)=~^)`D~82IRYkw-G#BW#h?J5-yy!f*ZY_YeXF0 zPH=PX7FWJFyuIM2f4~(s4(}ki**{;_!>Oq^vFFqMj>_!ZcM{y3Psg<<4(}|u>926r zt(9-HsmV8i4n!^J2PEgQCRm#@8P8vAJ*9irpC(v2GYQYnJRD62 zaC5Kidmi3HaC5J%YkwF{Pr=8jad>k54%1JZ^|=XJ!`65nLi%mLDzCTTroH*|eUtxp z@0$GIyJym!N#?KD^4D>NooTiO4OhXt87E+Va5Bt)dbi_^2=i8$J7DgCc>v}im`7or zfO!Vy1(;W0UWa)LhWA18PDgh)qq}F(-J9s&jp*Ma$vYC?f&YdWsA~l?7G@R9tuSxF za9tYDyxgHNb_f2)19h1#4Q)eI8hDes#3XPe*R2sfL$M{LZJMGiqphK|Dzptsu3*a& zP9-)$WH4>b6}g?Z$+D6y3R^dD<9N8C{NtMj(z4Tbnyh4_t(T&-rmdMGpVKy8BpPjX zR53JgOy@$Z45VBknv*=McYbmeToq}x__n*E{G_d3a@E^hsT0Int2Yq~Yq3ci^Y7NU zouQ~1&{aoi(`f6OTx6mZl`M%xToOGn$BntO*6IZS#LkxXfwpYL7MZptBD0uE{-+*8 zw0Cm7T@B^V8lE6hm~R&6cGjils^Riu-?=by;Iaag zP(NH3?|g0A)o)O#$hq$0{IafHGwaxQE>7;AzI&Sqw-S^>`bWE9$N5crn(pBYi>nW* zC-VGh=bn8IcOL6u4>$U}Igj;#hf}Y1=dNz`aIh&p<{Zlv`S@%w3qIx?%LN_|D?Vm@ z?sN~Qe#;x@AOh95z~hTed&hK>J$+zM(cT$mV(D{>G0l~8+N^JBTuzR6TyT3ZDvzZ|%xzT2Y7UB}~r-ZT7z zIq+few?@aWE;7>)5ot`>RFFzw-qQ^~{ZIt#3X|<1jZy_gd0iURX^i0Lu%!f92|*$; zHab}3vkAeG!)O>}fs`?;0kT#M4!|R54&w;A2$q%?L26kgiz4`<5R>VMt~jC~`yZR) z2M`7QqQlI6Qno(NCglhMRtxiSyFTB{+i_=$bw7(wS5J7hsKc3C{^S3V9&Y4?Iq~N* z;PJ(#9x^GeK40MBq!npEDhvcpZe_jYf0i@T%X;AITG(?g+?)@?x{(V%8xacJR60&1&h#3&$y92^{L&qz)~RSkNFy5N zy+8>A5vO!qu;ezvt0`kL)StXEE}juc)~$`-rf}R^;>Z9qfCL2?;V^2Pz1@%0H5$>AXQE(Hmt<03t>4GKQSSA#D;eja(V!QU&T;HDDC&5tKz5 zlxHrIp@LEx*s&7eb(g{=kPb1V5wC6gKNfpNa9%!fJc%1VJ{kLdq4fce;|1{9d`~7F ziC^wRb?(VF92)Jp6Z0M5)I-aPVylM5p~yrkg8 zgzd_DI7^NN#S$(kBe>ty$9~5D-(lDmbDq$>n+;z61pg^Rx+0vLB}C@I?Z8bariF17 zQ=}?wW0QN4(Yje5IBCkhjS6+>F0PnfmOK41uSC;@+O!py-H65|ONKU-Mp2Zw$sA=u z2XrGwsgtmc>SAmPc>t-=0$}&D+U)t` znh{+M^kvIh9sRVL82_w=UB`?o+eXt3_R^>&S$JC;4P#40+6m`?_Qk!f1JR%1KAbVw zYcyMSMy|nLq03bs&gEueUcp`J@8A~oBe*O12P94Fh)(Dtx`Zx;Q@JbZYPyzgpd0BH zx(#;H_R{_I0DXcUs)yrz_HlZGo{Ef|jx*fn=`-~Ly-+XJ=j#=E74`~m(A)JDdZ)fx z@6-GB9r_;qpngO@rJvEy>KFBE`VIXr{f_=nf2P0JKkDCgEJzEA1|@?sLFJ%&P&23( zG!2>uU4!nyfM8HCG&nIhDL6Tp8=M;~36=%RgOx#@NbAVik@1Q8X${kwrZrD%oz^z3 zV_Fy1Nc9oO`3(rW5bWFx(r)O$PkIu!dA)Gk~?3Rwz{AhqmNmWNw zw9`)!aAFCR9CyUkKzS*hp-bzkI!D)FYSfjxFz$rZyLxE&&$Q29c(|$mW?bt7;Bok6 zJ)}Rz%D`MbaZlD0)<=fV_fbWkj>8!`(FoS1_d@^lM2rYb!x@cdVb{|IAO=5^9yKjK zLpciLNyFNRo{6ILFNNfkKz1{bUH2gcPR6!3Oc|@vI#V)x4T7r+_jU2^5R4aG9R$ae zF}R|VJN&_i*lRdR{#*5({6F(BdyQt@z*q$8fVqmhl$)_TWyT#a9Tj2Hezyxe&$+vR*RC7=$|mG9Tuq0csvUO&@2k-Dt4$@btXb zhj&9_;Rm`FlCz!WXAHce^2?W8^Yol9z0}k_lKs}@$R)=u` z`BRuyd|Q34zJ$2=1zW7sATEmO%DM`eI9oTz#`_Ms6E?gKfqp!%w=NS_yM69jA6xCjWqeX;4Nu~hoZhq>vja^=rs2!>3; zl--XwykMFl7_x^(>UiN)1_CO9fGWdQ28jERE5E{Z2pPBrp}ibf&`odJi9ksUw)4V~ zxIy7*{NLo^Oe4sOFHVsF&dBoX|3P&S|7Uo(;nh5q2Yif&lZ03`iZ9L-^l&l@PVdB5 zsdgT2D)eR8)rfIB4=+mRs4lE96+IkHG(H>gh3xZiQyn*mT=@;P&86Q^dOh|pVSkE; zXD}GFUF-1sp@*A7UJG#zx!~bO?^uJq44{&S8`7`FK2D`>^Kdde_sFln?`{t_<0I!| z?*te3s#hUk|6|&fTj^@q4<5vtBCfE#j7l-8)Y9?rfj8>t2OE$!i^s?U?V=3*X>MgSi(ulz&x{BmJcar4UW zdw4a$&HVA>9-b|@nGe3j!*c{T^T9hk99DeHeDG=yN7C?_iZ4beJshlr&lG%d7K(@0 z65Pz+^z-oAf}44o4jx`da5GQS(8KErK2D9pv!sXD6MPIB5S*BT%s9TSFZfAN^>8PU zhc^&>w9H#`4YhOMP;fKfoaf<<1UK`|+$-SRn+C$nH**h%!<&eEGk?6)!x* zY#vTorLaqX0Dif5&4t797K~cSS~>1Xba)HF`$C(<{Dp^`wyqEMri0%+yp_1`DXZ#u z4w4I}wctIVTj1m2Z3H*-)}LqRyKgJFnTLMG!`lg-t8(!?1R!2dH~+?{>r zz|Q;noE!dM0z>zF@?JmM`OL(Vc0RASxO+PPd@?+`<8zO-^U1UjFPJ9Z{XdQS|EciV z2OALJ90l+sXNDb zlK6PIKVPI4-?kBXOrxZDwwxX(2wy`x=)b@z2mosx|>nNHMZ8&`+$GkmB zk&B7N6zdUf>C$4+cD(3Nw4E#3AZ=?^Et|KEiY*4QTxpwV>nU0hZ3{%tqHU3S3~51O zfG+DqJ0-e7v7XabQZy#o=BW<0l-M6=1={j_5$X|qJ6=&kqivz0tf8%}NGaMXDznk(QMPRFoouNZ8 zk~9tL0oFkC-=Zja=q9cx%V;a6*!t1dO7tb##z;#*TQ%uJ&~}-kw4|+s3bKu@zU(F@ zHc(MU1+eiA`zb`XC`x47N{Mbx+xe;l9$B!(5qC+@n?tQNQ9GJpbiIShMUML-yrIy@ z#)FE}L5sQ2j?ab0z8bxngDMC9S$8tQyINxkc*+WGDig7?E1GS;PfIEo$aO+Vos52u`nqsCDWe9^;;3U2xd1H5z+ zF9ylq4bO+I`yxmuntR}8UFrc3PZ!+u2d?q(;)3U@Ts$xJaMGg~>fLd8uJCY(ao}bh z>sT*6#7jbUu-|c(bq@)(6siYsqxVnu@KS;sy??Zaa~z?h)%yo}IL8r6VuY|Io?SgW zQ*g6RHn2F$k$4$M-bQ#fvv^sghvN&l-xy!iD-SOxxLL1S(!)8vPzLh5KAy{Knet`$ z#4BP96Oj7M;uR5o1;LHp|B8om+@Ye?`ycgi>f;qLP*@$$10G&k@Emsa)GiOF#IC5a z@x^$ShjZMaqU|Tlv^dh42f+v2=<6dr9Ksg3(Z73mc(&k1&u;GFOh-kOJozij!B>TBp00md2w_zsY_0PP(o7Xy@F0NEd)r3x@;8({D zI$!|$IUU|TKSIUi9mNILQ2t%aU&j&_)_zoy12Ff%9E5ok<|&vLU|xfv&if7MK>BJt zizrGU+WM=87Aq=TNUWwJU1`JYoqbzUWErsm!Zoy26FEa$AK`4;s;DK_2UfS(P;hE< zG7fSg-DNBCHf=Q&r5J5})!7y+D-wxVSM_-^EvMMGkP_BML&cgvchyD4(AHV8_R&^f zPX*RTnqqAyR#)T!Z7mcf3~j9yWj$>}rB>0FqbLt)>mn@#ZNn603~epd zW;|%i6uCfK12x3PmabSwh@~smt^hW!^r2)Ydc0y?p{G8ih4DaXUovtNeUV~8PorvvVK7#!>7~a3zt||BphG*^ZjDDUA&a={Z=LPTO zI|zfKQarovTZI21jO_k`p9U~hV0cH`^9b*co6NZm>)N2d1H-eI_Tf1XrY_7q@OwAh zJqW|wiDL*F^2Uz;&%#-W(62l^ivJj4#uwU}hsOnza?E@ZOR&X;;d%(lX3vSlg z@A7cAKRoq%B7QIPaJDn-(@encvV43t+Zj$cQV*?DFDbu=5|2nf0d>pbkhV+N{zOn0 z>*CqN!`c2s>^_ZV9?teBqRc*xQ{jnpXS+%~9W|>uo~5mONbsfEf}8g6SL>d5j^Npf z?|G&q!y!)p>9#$5#lvd|ZpO_X@o-d7xHs!TZ}xChOyFjJ#g!h8stw$Xv#s}Vh#lZ& zob7B6hZVTlU-2*;x%?8(gw$Yp4z=#N&j(otZpPD&^Kj}RoPH!<@MKMfL-!~;;AWqD zWe*1n12^MuMLoQc;HLfm-lm7)G#1>9zrE+-s9p%ioGbghhog!DH|th=AyAvIJdTHF zV(Rk-JUe(esweR4@r7RI;i%5Q_u&hfMtrf+7f`i<@5LAGpode>%v9Ini}ujNIli5V z^V#>{`8zW2!r^#yrrM1!WQT`$5PTOVvmt*xyrbY-G1;!vs~*nr?Myr0_k@Rc7TnDD zUGCx3pEK>e*g6l-6?{3)n1x>H;avnb^I~Uvcvr#Ayx2?+?#cDC0 zBRsr^;OD4w@a*s5Jq14-OE=IX_V8YUoB6CWz+|p`dkb#%4UYBjK7x;w^;3O4yszLR z9_Ut@L__R`5m5j>%uuva5KMC z#luM#w=c1nhmR24^yhxGa+3Nr$G6Sx189pqoa5V>n7}9hzT)Ad1vm3M4}17Yf}8%? z^&UP(a5FEn$-~)BWZM4OG7ldsxS4-B!^6i3ZuTGYR9{Dj@q(NEhdkBZ;S&Tm{RZCB z;BdBQnYQ0>qm@gf!z97YxcwC#K3Q`X@yZMt>NdZNuj#`+N@1(&(_~z+4HF zhDNFDbI?Cw#=}g1Ua6O1>Y{O@IR)lPn2P1FcK~K5%zH4O!?1sK64F647UoA_5hybm zFco3=-_4iQ#Q)|nxiH@)pl{%rMH<6jU)cHF4l@k)Q81i0S%>^z3Nse}C&92!bxUA$ zJdLuSp;+4ipoTA3cf%fmeGnw~T19@Qo2H^6(RQ+8ouI9iXnnLzQ`bXo(zZr4P}*jx z+bp(DoeY531&aJw0k$YcGqD>8GI|MS9+n|q#R}9_rqpbvwG-UkgtQVJsMub|V9Q8`NQpsrT@VAMDBTTHY`2JRhVK_E89%3i0yCiv z&k`+!Z`pcN!=sujj1L! zz14&kgSZTDfz>H=~Vq=Z2q{ zJU6^?^4#!=$#cU`mv)~y-U^DZM}ips7DcU&wo2+Uq@C~ipSmQ`sv<>6?T#ozQ(Dxk z`EG)uW>4EGqMOjRM^S5{t+?p5wB;yjh_qEyZ0l)TD%uil*Q(Z=Onko!8W;68qWfeA4Jzhe@Ucsk;bOLu^xa2owfr+sIR16~ivk}kwP2%YfpoW5 z^f=mftAzEND}5wlQxvsM+HR2f7V=XMaAY5~(Wbqr+6Z4v`v5F8eb$CBNbR%KjVAZ# zT&dWTVpx+D+hC@qyQL|0I)=>}x>4p%=x(m)Rn3nS24w2 z6|wS)?JjLi6g4>7Mk)3YnA%b(#Yr}t#i9}N{n?7TD)VdVqPwMKrtDK<-JXD+q`3!S znqvQiVU+>To|lY^y;X)aS@8_*f1iaFuL~gm=VSZ;cAkTO4W2wZ{AD~pz&qYsb`k8^ zv(YxpfqX*e{4toBOTfv?A@hNEgV_qxd@jbx;btD}8um7Lu7Rlr`$2F7>jT<#yZ^_u z_Xj+j>17GCjIZ@@=Goy}J)G`H5x!sR;f%-O=Xp43S`JZ|QIe>H_Ww_7B8MfQb zux)CL_e>YvMUyM@Ba%0RF;tTat(a1x5lNe|F}KDg_wX1SQ)u2^eFo|YXjK8vY?yLO z&_Bf>NdR*`X#VYD%(7mBHVGzh8y2UJdu~b1&Tf3xfjREVSdK&NJk*=2z z@8x*zh1me}70gn+>xDSR!nB3?4(4LSvj^rU1sORUvi<}}V<^NEW+MN`EA=J}&)MZ! zvAhd!{y69@FpXg{`ocZTa+tX=2l`;_7Vdf1;YY9!1je&Zd6s8$*t^3|C7A06pdCeA zJ4PUWJimn*4SUzo$QMi;@y`Hu5T+S$?xCFv^D4|>yz2;a3e2^5Uk>ljfEkH*_rO#G zelGAgVY&lv0BjY^=P*AYO{GSm)rR>2=8ch%%y`}hGal)C7w)?O+XHhe?4|IW2lFEQ zeUB&4IC>rCVc47Ec@0c1{5=l0^?|L2SqJ;CFymm)?GLS}J+u&XoTh@V_rR2a{jFgb zFFX;_6Q&!mi(x*6xea)6U^8Iy5N8qO;XBx?;dwURKL=9}{=bF0!N6~Z;h1Awnfj*j za<*b%-2)ba+&7vksACln##xZu-I6!}*>qEV3+P zo6fzd|E3?z@lJ=QiF?xz=2)x4iwJJ|c^u<(cu~RI;f{FJ1>hNYQoa-u-1N7qR{*cT z@Qj31hW&$Fyr;bB4S$T6^y;E|BPXQLIM9u`B05s&N832r)y|X*N4v!v%|?S>Oda30 zll;;)LMThyNs>l}*aTWM^G$TPjPTMnTFQ(z|NO6x9l=j+q4mJ*TE?~>vZX81+!K5c zv!EB`NjJ1`-O=*(0G(kr0&fbu1@I?ejtBNO{7eFlX?@c#`2P@0pH<-P^O4@2=ug3HhAFZYGG`0U)qwqu3phFrT%!$agYYnr${s`~ znB91{A7<`q$YgZrFNA#Ief2NG-V_5-59NYZ7M!Y*v z7F7`Ea>!uVZv}QGmkQFmAZU_52a38_{UhvbnS+YJHRPr(7053I1{fSCFv3fyy z^w2?*#z}p_?h7{arH{jX4DV5|?7m<#9?QW^hbJU_Gah@3hZhmtjK}iUCFkDMPct5S znTHn__hvkHwTG7w+>FPb>*1vYH{-GMJiLtHW;}L=hnE%H%fzNq{CDt!OMkY9f9K&j9{#z9SNHHE9!|b-bf^a0(k-v1;6_h0^U(fSl0O&y z=kcU&Afg-J`JaBy1mn$ynG3`5pT8ROVVkf4dASpLLv=$hf~7}Wnj-%Pu$58R;gdvJ zisn7b-`G}LmnG1bWbL4@(&)QCZta+BRiw6Y&GIlda+a}?_vkAPDIh=7&UqB_JnhBN zKYz)(E-y8iXjzQDv9wGWEPrDoM;ROI09_WtNDS*0?HTAB@3!_*=;5$%hE+B zwf&*RALqUB#~U5)ed3Nkc0BOeg~xsHVbzQW{{6$h?|-z-6Aiu^QuV@N3+H}c@22#V zTl`p|xL$-#2(z-Cf7^Shel>?pvyTFzb~O@hjeI_Gal0 zy{4RcTC>gz?~S}SaNcz*UN}1b{*F&)oqTQQhMhmCG@)4W51!p}@Mz@8Aun_obX@a~ zD__|B-?bM!wRvIs#nqNg9#Hk^npduz|JBZQ4Jv+A<=&-VuRnU-yQSV8xb~x2?;qK4 z%JQ5Bvo9WZ>sKYGuB@@{>x;fr<6n+{UE|rt*`03QJ!^f79zVv$EmF5FnWv}4TGwBG zaq&JMZ!bBbR*z;6{#xh30dHcpIVRr_wf z_^Qu-PV9X2n;*KL^I@3{ok7Z3pyq!+|DUG7j*d%=j5R%5))ixmp(a*G)>wB;n`rWB zR_4>LQ3I=CJ(jsAw-v^?R-v(Cd+9#zj2|8fGWhz`@f49g8+F7V$22ML(TmI9-mO`BXZuWm{^l+x1WB+Uq z)_UPHe$EkOEYaE2w+$OIs;Pk)ga!o*hskdCFN!#T?RQRiOcG)r5MqWeeSDtCc)CprnjP z5i5h1BnQva!5=>FIDV{;cPA}L%{vjxqt8z_ew`n9kxy@wyPLCg@AzcA9Wm-!0_)cw z%1s^iErH>G_DxxK1^w^U=KWcPr2D)AJkR>TxJ#ffRUd}qW2wUC92D!`k&t}#LB8A^ ztxJ~+yMyGbshmqzFl+>=a>0eDz|ejDGtGaOQ>mWK++L{>(c+9M1a8fBgTThZ~+URC2mmBgmO{ zFsvJ_=kD&1xcGE@{yIWoX~h-er!7MrP1^3Wz3YtR-6F-{hOY8IeNj$4laqCr?^s4m zA@fiK^E7Qi!8FLf1mt5T>RvspTst1`m%L^&9K?u|j z+i1Hc>_&Lw&bM`8^T`}#A%zL-&so1Dbsf!to3C?C*aiLGZ0ph0A$5Vbg|aS;Kp1}g zXTJC$KVDKuyh}pr=N@h9(3k?@=BH1|IfkT%!yGN!NPaVA)IHVvc9zy9PBUqC{+V8W zjz_uQR7g2Yfg3+u`X`+Y2VK_Sjzau4D^O>g-yT+uURMaMPA?Fz%WqMMzlqF}vVAgP zYVax7?JAXx@+mHP=E>$}tS?picUzj*453Ru(B*+b@|KJ7BHL~sL^SxA{&w@7pcfLx z{=BLGy@NhTSYr=odNAS;^a9?-!;S9JJ?H`4-@lPA?z;xvfYEBY5ke4e;$=ytM>x8MFfK z@875=c=MnIaDV>>^&*TW1UOlJ*{2>qTDR_2}1N?pu?<08C zpc?SIJiMRaSwR)xH+c9!!7JfZ9gL-U={Z603PDBSKL21C8lV5}|2aqKpaKp0`22I8 z;Qwd$|6pc9|DccMpY;;&QT-iopMNeA{2To(aG!rJ5&SFtHE^GQHVgiR{t~#)KidTV zOn(mC=btMC|3rTZ+?NAa3I4JEcLDdi1V5rbDu7=r_y;)g3F~UEfesHj)=CAlAO`Vy zMZX99#j8zw0Qt6YKTxbz5d10NY!fN>ZV~)R{UqE!?%}ry{)B!4_@f?vr{It4$ALfW z;r9yun0^fSK@WdG@Wc8r@cTXdLBSu@j{?8b!ygg+5u9y>aa|98Oz=bc5b*u^`0U38 z&(nFp8-j>VoLGWFAH}Kk?`)Ckv;qa!MEtGz}tBEM}l9bHv{K7f0wUM1;0dJ z3Y>cZ9R7vi7wb*Hn|t`zf?udF0-o*RM+M)YHv%u^;XeqzPOk?(*28}me2rcUyr_r& zE;vspgFN?ejsIG$&@1u$eP@0;qk>^QX9#|- zJ`YdsO>lH5E%-uxHlCb2c6d3#=iyW}Gtcbsih|G5JZ@~T=RQmD8G0t3{XD#y;8XP} zc=q)0>Vi+wlkv>;@LGaT&=c|O;Nf)zAE(FT+1kS!3VyO4i)T|0Zz}jGJqAy?L(%eW z3&BU={5Z@Td+u8cej-kmLx04>+Y3Ha55qI+;hhCP0mn?4JtdAlT?HSc2jj_oCl2o+ z_y9c+Pr2jNrl+^y{d9jkKl9ulFL+*3 z=Rv-C_z1zf>TY;G?ct*Z&(&S zvA@N`$p>2Pz!&2;9)6nO+Z5Y@=REv$!Oc4Ir#$=&!Ogi*)c2fxo-epLALB$7t%Lhb9?trvv4&|aaLzrta8?Lz&U;$r;cEmp=RHwx zbnZ6@z6uBZnfBe`lsj6j#MiXH4!=Zjb3W8WFC5A{ja5d=;eLpRZx`IGgCF4GR|;;{ z!ME{n%4Ln6|I{z2r@44{32x4ZYV6_H3U1Das^{VR1UKvBYkBy7!Oi;k91p)maC4p% z^>Y{RZGxNgq{@5vor2r*q&)my!Oz4QlSZ$0;XEL?xxc80=l(&#&G}PN4?iThS+7s# zb>SQq+}vyQ!;XCX3Bk?&sJA`*8Nto|DC$ctoEHQ)`=F>VIs9e8%|0mVOAdccaC2T2 z^(BYDDY)4mb-=^l7Tlayb%Te$C%8GUYF<7*`+dR9I*TmeaV72h3B)7VImmv-Sv{+Zx+>AUdU>fzK! z)6|`se7DiVzYzQmoGgkpjUN7`;J54B@m%WRUkQGjCSRZJ;na`Q)B$|}&#QLkr}G=Z z&AD|QJ^Wk2&3={VcI3N1D!4fZZM%nmC%D|dqHmVE$8kF8ucL{Evoxn)iP>?3a4~!{RC!&H?zj*Yj5}+^}%|3C=K?e?Pr{*Z=eI z_bSZ0F#oBYdH%%n|0C@BP=0u&V6W``4~wf{IHX-8&tJiC!@~I|IKyQA{q+7_|DBMw z?l4UE06g9QF|c2mjdg%{o(^*+%-Jw>w-ir~tFOnC?zh2Q1#`Xq&+zEq59^<}qko2X zj}7A~JYTc+|FnF4dK4^!zgxBi{rO@36Z?N!UIlr}kJIrPWygo0)lV?4F7f~0txJC; zdkWV5|3AqT$6KzP*YCl2{Ucbh0`pJ#Hw%91z%Yyscn-8-6s&81x9$|I6a3FIAM1si zs?N>AdslZ>!oD45zxBia&sjUeOXdIX;(mQC%+KF-_g86o7wP^A#>ohV%Xr=Y!qUL7 zec8q`VmY{S?gTpx@nO4--C@5W&iJF~2f$>)RD-Dp(*%Yx(Kl^?btr~&Gho8@@cHid zpx@3l@_49272w8T34|r5d}UHE0D*k2laPw7vTTU zU|3MczT+9EH|d-79)!rWey6^&{_Ciwa6_zYA^RWYQLAr;rf ztiRI&_Vf9EtvalSUS-}tpf*|Cw=#ahv_y4RT_fOVG4uW^#-K}JKI*>JTqnbumOju& z^vC)W+%510O5q!QRPGq~S^tWA22>CP(I76j4WtJdxN)F#kQtN2+te|R;Ew>NU z4(bN=gN8w4xrLx*&^l-fp6M8L4srwDNzgOs9V|j>S+*-xQQZ*ZN}CXRIu1<@6-oBcNW*eD_8_WPuHJg^KCA7&Tgp)YlAt z1WIb}Q!l8RdKpIPIp)aFA5+X(|(^BaN8J*U6^N8lSHf@JBS6QdSwhFa?Tz3LW zb0Ih{z?}=tk+V+_K3(ombKnP6REqD5N&w3ngo{jOlB{~|k4A?hi&TFHbHmO=WxDONafGE=_j*%~>)A22i zZ-(59P+FJ4w-UZt_-5l<2j52cHpRCYzO`&DXRA!z9HWz0>5@TiFd5V!y&hK8a0LCQ zIF;>b#54rR42)1L1RYjmWNAI9u?-x*A2fLceE*nw8MOIG4!1vwgWKe(*D zu`QE%R8o8a_V+c$Na|)C2j_B^63e8bo~6rMUo!)at&>6r)SIe4ZtM6-vp3E-@6zwU z#!}@C9q-|rZGD{{aD_kJER#7>#x)NTssTnxFVa8j`TtjTABW@C@8*o&gvEHCwQnhg#$=90W#tbPPW!WO&ED%F_OuO-!DIzgG(UpQm zHm9=#_EDMA4D?OEA7^}AAtT=msSG%wQ!sX!!7IqlFXE@GO1KGy^AJqIL+VpiSFgdG z9Y?_VzN8+Z+XXl8KtBmdn4+etX*idWdzX3j$Xrl!KIpLk=Roov&2w-T=(!jXTmczF zj$H%EXt;I@S|@U@*^#;*?bA(I#dbj5h8E;5bvIV5-3!UgD;o}3&VE6?2ztDXcI;K$ zpYbLxarl>dSG}j+7moiJDg8|N{u|t^aTIOD_qZB^qskm{=4do)14pqr!p+fdj*N5E zoFnRfE#U}0NB2iTez3N1#(=X4oN3@J#5A;pToHx z&I56di1mzfOPqJw2ARbA#6~llJUr* z74O~QYzF@qL3vb0xTC<8-SBKa*HYRVzTKvFfOiYy-UlEv^7)st znbP?&w0?$*!}$0kXd{M`c|pmSpwQRKaCAOTcLqOq#kV_nxi|QjcNz`Cm-iYC1)WBK zcTdK59QbyUP+|ro=RABDqAgjB?=tW!Z#h~8UR?)1y%0Ql3BH$sKevH5uatX_c7ZGR z3P(CE)#<5Ef*+}&_&Q2KEyd_5`I-uKmDJh_Z%gv^72ccF5?`mYP;2q^7S8&x?6;{W zb?5P>#4Gb0eEq!U$TubGbm+ykQ1h3gmQ)RXhY!lL>p}fm$orR?r?`=?ih*v;0?w0b z{KM>cR}(hdc8wzFDqZ?1ss!PDvnoo=#2=U_B9BBW4v^Ghkh0|Y9g48 zRTAIQ_)bbZ8^YewZ|iq8S2qy34Q*BnNc=JZ=VKXP z0`<3EP}{~=O7FI|dvtBf5wn64);1&9Y`JV5TK=46CWH|SeY^8+hsE6&3G~(gIWb0ZTg;4)p3Cm=N}mBVzorpVlb|I&~i6{yeSeK zveYBD_kh1B-tJOWarx3B9YdV-$#Yg{|X1IiRJhFth&SY;uVy9K$| zn7qslI7gy^4^;n#jq-x+;w+?^Z6jw!neubsuLZP_YjkO}r>6p?pXD;s%J=7@Ki?X9 z$#uE{+E}hfVNULXhSUJk{TIy@EkquHj?@T}UI)!>3eE^d?=Y$Chjx`Ss0{BcXnIYc z1#Q)7XwygA_?F4a9)@!>bg))vAIb;Y5HizpR8|czhcUEFwSxZ33|_&U5CD8Ww7KF4 zi6bBL(b`vo_H`a~nqPIp;3?pw)E3BCu9jkmPin6JVQe=+=WC8OsZ{U>^l!eaugS!3n%aQ$yL1#+kXOAF#=KmR1~ zN(SCze)S+8_*{oCYC0Bkuv~$UG$mU-tvcAJ6mZfV_z4EDoK_k5c{UFYFQbZzd*Z(P zGU{mJDA@c6!r{C$PBUJD?7?0vtr)^dY|qCdf~TjY18?BrQNfF+6$d`p!x>K*m64VK ze2#}RA7xaDv=YEC1YR2d5$_4a%d3)UWr5#q-QyJHC9H+zRjIU6z(4hH`~_Y*tu!oE zE;s3<`yzsuNh0AX?{3&3jSo`N#F-O{9(Z#O*{&GjfX!i_@Trh;Nv~~Rl)NTdBEFx z_&b8%pST}*hKGMF_+5#+fd8>6KRw?Iew$p>yTii+@D29zCvJiJyS;ps6nuYTKk!u^ zUPbWh64wFm?1fWb@ZE{sz~8+%Ki)QiU!Axb_*xI|F8Geb4&ZG(e3;;uCoTv6-bMN0 zOcs1=Vk_`<9zI9#%MzCXZ|mXb3BD<@33ykJ50?vmVd6sI?_Zc7KG#2Hsr8BVz*l?t z<$|wCtO4H0!}kilGO-f)QycTc;kv9Wb$;S};L|+(kl>3Gi-DK$@aF|zlvo7(-VOQT zaNS&%T9{Y}{8SHTJ|Rj**UdKDI7DUv&j<7iov*C=YKWcvd6}&xRh}M)34VI-bw1%@2q1WvO2S zrgyuCGe24C>)>nP^F4f+;75WZzz2EwIKkft-T+?N!%r3b+2C2=N7m%WOTNrfhk`@E zZ}#vdg5Mq74g4GrUoH5J!HvLsdH98bUlUvd{Iz`jB=1tew**^&KjYz-34T#<5%5Pn ze6!%|gZ02U1MKS87Qt5qtAOwE@U4Q+4rT-AIeE_gHo<2EGl274Du?qt)+{wOm2=_cM(cw1>evRyZs_Nml2!1JN8CBrnw+g;d_7&|~ksr=&f}f4K zUUN>P3;zzmr(kr=oa5;5y96JFxdU^?qr>kJ{CL?%!t*B`ey`wNWS_@y55G_FPO_ha zXI47*_Y2-0mxP;hDjoiS;2f_-zC8DNf^(eLoC)dN9~7M9!Z`ozg8c9w6rAJ9O637} z?cGCya}3&?>E^JoMGwk z!-Bt$QBKGW&;4V9zl@Pq=szC*xZviVbe_5C!g)&Y`_z4KU)jT-75rYzlVXk3`T6dj z7yM2|efDP$e^Kx|{o;2IgXztuR-??1i}*=1!PYe*enfe-dZW>;73> zVQ~~p+pxbG?q7ws;Jm$G=`g0{tDxR7gP9QJ!O2S+>pAio&~&MJoJ+X{4mTjFt5P)@%{_{3-jZy8}$|FaYy(mkzdH-9yHs>b8n@+a)eDrsCjdGM`Kf)>aycbxia9y1) znCBWd|2_9h;jW|4+*Fi@)i<-)(=6H>^w@E${jVezI@>bNH@YQ?*fx3UQyR zd|prCK9xI{c300GAN0E8&*}R+{%`t+{z{?K^>_Gf+F!W4!@j33&$j93yD)YO!?205 z>|C4W>Y~egse1}{R{p`s0f#Lsi@!V?deD1OTM?8e}2Qc)17M|;1Tzr?n&NTA><*+-$|9r>) zeBKIk80J}+S3Ub%uzv<~)INX2GyP$N2g4`Nw{~$ctXI*;=G<|ha0X2xC+#riD{1eX zc3c|A*fs2rmanS;rgRX7DR4%0D9F&i@& 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