/* ======================================================== CTR MCU I2Cレジスタ ====================================================== */ #include "incs.h" #include "vreg_ctr.h" #include "rtc.h" #include "led.h" #include "accero.h" #include "pm.h" #include "pool.h" #include #include "fsl_user.h" extern u8 extinfo_read(); // task_misc.c extern u8 iic_burst_state; // 特殊バーストアクセスする時のカウンタ extern bit info_led_pattern_updated; // お知らせLEDのパターンを先頭に戻す extern bit pedolog_overflow; extern bit reserve_pedo_increnent; // ******************************************************** #ifdef _DBG_PEDO_AUTO_ENABLE_ u8 vreg_ctr[VREG_C_ENDMARK_ + 16]; #else u8 vreg_ctr[VREG_C_ENDMARK_]; #endif static u8 vreg_free_adrs; // アドレス飛んでるのでしばらくはこれで bit irq_readed; // AAA型のため。 // ******************************************************** extern task_status_immed tski_firm_update(); extern task_status_immed tski_mcu_reset(); extern unsigned char get_ei(); extern void DI_wt_chk(); // ******************************************************** #ifdef _MCU_BSR_ #define IICAMK IICAMK1 #endif // ******************************************************** // 非ゼロの初期値の指定が必要なアドレス // マイコンリセット時に呼ばれます void vreg_ctr_init( ) { vreg_ctr[ VREG_C_VCOM_T ] = VCOM_DEFAULT_T; vreg_ctr[ VREG_C_VCOM_B ] = VCOM_DEFAULT_B; vreg_ctr[ VREG_C_OFF_DELAY ] = FORCEOFF_THREASHOLD; vreg_ctr[ VREG_C_VOL_CAL_MIN ] = 0x36; vreg_ctr[ VREG_C_VOL_CAL_MAX ] = 0xFF - 0x36; vreg_ctr[ VREG_C_RBR_CONTROL ] = REG_BIT_RESET_n; // todo | REG_BIT_FLIGHT; } // ******************************************************** // 本体の電源投入時にセットされます void vreg_ctr_reset( ) { vreg_ctr[ VREG_C_MCU_VER_MAJOR ] = MCU_VER_MAJOR | 0x10; vreg_ctr[ VREG_C_MCU_VER_MINOR ] = MCU_VER_MINOR; vreg_ctr[ VREG_C_LED_BRIGHT ] = 0xFF; vreg_ctr[ VREG_C_LED_POW ] = 0; vreg_ctr[ VREG_C_LED_WIFI ] = 0; vreg_ctr[ VREG_C_LED_CAM ] = 0; vreg_ctr[ VREG_C_LED_3D ] = 0; // vreg_ctr[ VREG_C_VOL_CAL_MIN ] = 0x36; ここで書いちゃダメ! // vreg_ctr[ VREG_C_VOL_CAL_MAX ] = 0xFF - 0x36; 電源入れるたびにデフォルト値になってしまう { u8 i; for( i = 0; i < sizeof( uni_info_LED ); i++ ) { info_LED.bindata[ i ] = 0; } } } // ******************************************************** // I2C仮想レジスタに書きます。 // 引数 adrs は内部アドレス //  書けないアドレスにアクセスした場合、何もしません。 // ●書き込んだ結果、I2C_mcu通信が発生する場合、renge_task_immed_add() // を使用しないと、I2C_mcu使用中でエラー終了した場合にリトライしません。 void vreg_ctr_write( u8 adrs, u8 data ) { switch ( adrs ) { case ( VREG_C_MCU_STATUS ): // vreg_twl[ REG_TWL_INT_ADRS_MODE ] = (u8)( ( data >> 6 ) & 0x03 ); Rでよい。その代わりリセットでクリア vreg_ctr[ VREG_C_MCU_STATUS ] &= data; // bitクリアはするがセットはしない。 // 上の方のtwlレジスタミラーは読み出され時に合成 break; case ( VREG_C_VCOM_T ): case ( VREG_C_VCOM_B ): renge_task_immed_add( tski_vcom_set ); vreg_ctr[adrs] = data; break; case ( VREG_C_DBG03 ): if( ( vreg_ctr[VREG_C_DBG01] == 'j' ) && ( vreg_ctr[VREG_C_DBG02] == 'h' ) && ( data == 'l' ) ) { renge_task_immed_add( tski_firm_update ); IICAMK = 1; } vreg_ctr[ VREG_C_DBG03 ] = data; break; case ( VREG_C_COMMAND0 ): if( data != 0 ) { renge_task_immed_add( tski_do_command0 ); vreg_ctr[ VREG_C_COMMAND0 ] |= data; } break; case ( VREG_C_COMMAND2 ): // こちらからの完了割り込みを待ってくれないそうです。 #-ω-) 何のための割り込みだ // 液晶電源 if(( data & REG_BIT_CMD_LCD_ON ) != 0 ) { renge_task_immed_add( tski_PM_LCD_on ); } else if(( data & REG_BIT_CMD_LCD_OFF ) != 0 ) { renge_task_immed_add( tski_PM_LCD_off ); } // バックライト設定 /// 今のところさらに細かくは分けないけど… if(( data & REG_BITS_CMD_BL ) != 0 ) { renge_task_immed_add( tski_PM_BL_set ); vreg_ctr[adrs] = (u8)( data & REG_BITS_CMD_BL ); } break; case ( VREG_C_COMMAND1 ): if( data != 0 ) { // u8 temp; 中間変数使ったらばかでかくなった... // TWLに割り込みを入れる /// 実際に割り込みを入れるのはSoC /// ビットの並びが違うから面倒 vreg_twl[ REG_TWL_INT_ADRS_IRQ ] = ( ( data & REG_BIT_SEND_TWL_PWSW_DET ) != 0 ) ? REG_BIT_TWL_IRQ_PWSW_DET : 0x00; //pwsw_det vreg_twl[ REG_TWL_INT_ADRS_IRQ ] |= ( ( data & REG_BIT_SEND_TWL_RESET_DET ) != 0 ) ? REG_BIT_TWL_IRQ_RESET : 0x00; //reset_req vreg_twl[ REG_TWL_INT_ADRS_IRQ ] |= ( ( data & REG_BIT_SEND_TWL_OFF_DET ) != 0 ) ? REG_BIT_TWL_IRQ_OFF : 0x00; //off_req vreg_twl[ REG_TWL_INT_ADRS_IRQ ] |= ( ( data & REG_BIT_SEND_TWL_BATT_LOW ) != 0 ) ? REG_BIT_TWL_IRQ_BT_LOW : 0x00; //batt_low vreg_twl[ REG_TWL_INT_ADRS_IRQ ] |= ( ( data & REG_BIT_SEND_TWL_BATT_EMPTY ) != 0 ) ? REG_BIT_TWL_IRQ_BT_EMPTY : 0x00; //batt_empty if(( data & REG_BIT_SEND_TWL_VOL_CLICK ) != 0 ) { vreg_twl[ REG_TWL_INT_ADRS_IRQ ] |= REG_BIT_TWL_IRQ_VOL_CHANGE; //vol_changed } } break; case ( VREG_C_LED_POW ): if( iic_burst_state == 0 ) { vreg_ctr[ VREG_C_LED_POW ] = data; iic_burst_state ++; } else if( iic_burst_state < 5 ) { led_red_batt_empty.dats[ iic_burst_state -1 ] = data; iic_burst_state ++; } break; case ( VREG_C_LED_WIFI ): case ( VREG_C_LED_CAM ): case ( VREG_C_LED_3D ): vreg_ctr[adrs] = (u8)( data & 0x0F ); break; case ( VREG_C_LED_NOTIFY_DATA ): if( iic_burst_state < sizeof( uni_info_LED ) ) { if(( iic_burst_state == 1 ) && ( data == 0 )) // fade_time == 0 禁止 { data = 1; } info_LED.bindata[ iic_burst_state ] = data; iic_burst_state ++; if( iic_burst_state > 4 ) // パターンを1文字でも書いた { info_led_pattern_updated = true; } } break; /// 非同期で動いているためここでは書かない。 // 予約するだけでstopで書く case ( VREG_C_RTC_SEC ): case ( VREG_C_RTC_MIN ): set_rtc( adrs - VREG_C_RTC_SEC, data & 0x7F ); break; case ( VREG_C_RTC_DAY ): case ( VREG_C_RTC_HOUR ): set_rtc( adrs - VREG_C_RTC_SEC, data & 0x3F ); break; case ( VREG_C_RTC_YOBI ): set_rtc( adrs - VREG_C_RTC_SEC, data & 0x07 ); break; case ( VREG_C_RTC_MONTH ): set_rtc( adrs - VREG_C_RTC_SEC, data & 0x1F ); break; case ( VREG_C_RTC_YEAR ): set_rtc( adrs - VREG_C_RTC_SEC, data ); break; case ( VREG_C_RTC_COMP ): WDT_Restart(); while(1) { RWAIT = 1; while( !RWST ){} if( SEC != 0 ) { break; } RWAIT = 0; } SUBCUD = data; RWAIT = 0; vreg_ctr[ VREG_C_RTC_COMP ] = data; break; case ( VREG_C_RTC_ALARM_MIN ): rtc_alarm_dirty = true; vreg_ctr[ VREG_C_RTC_ALARM_MIN ] = (u8)( data & 0x7F ); break; case ( VREG_C_RTC_ALARM_HOUR ): rtc_alarm_dirty = true; vreg_ctr[ VREG_C_RTC_ALARM_HOUR ] = (u8)( data & 0x3F ); break; // 書くだけでよい case ( VREG_C_RTC_ALARM_DAY ): vreg_ctr[ VREG_C_RTC_ALARM_DAY ] = (u8)( data & 0x3F ); break; case ( VREG_C_RTC_ALARM_MONTH ): vreg_ctr[ VREG_C_RTC_ALARM_MONTH ] = (u8)( data & 0x1F ); break; case ( VREG_C_ACC_CONFIG ): renge_task_immed_add( tski_acc_hosu_set ); vreg_ctr[ VREG_C_ACC_CONFIG ] = data; break; case ( VREG_C_ACC_R_ADRS ): renge_task_immed_add( tski_acc_read ); vreg_ctr[ VREG_C_ACC_R_ADRS ] = data; break; case ( VREG_C_ACC_W_BUF ): renge_task_immed_add( tski_acc_write ); vreg_ctr[ VREG_C_ACC_W_BUF ] = data; break; case ( VREG_C_ACC_HOSU_SETTING ): if( ( data & 0x01 ) != 0 ) { clear_hosu_hist(); // 履歴クリア } break; case ( VREG_CX_FREE_DATA ): if( vreg_free_adrs < VREG_C_FREE_SIZE ) { pool.vreg_c_ext.vreg_c_free[ vreg_free_adrs ] = data; vreg_free_adrs ++; } break; case ( VREG_CX_FREE_ADRS ): vreg_free_adrs = data; break; case ( VREG_C_COMMAND3 ): switch ( data ) { case ( 'r' ): // 割り込みルーチンからFSLライブラリを呼ぶのは禁止 // マイコンを再起動。 レジスタ類も初期化される。 renge_task_immed_add( tski_mcu_reset ); break; #ifdef _ENABLE_WDT_TEST_ case ( 'w' ): // WDTで再起動(テスト向け) while(1) { NOP(); } // mcu_wdt_reset; // このコマンド使ったら意味ないでしょ! break; #endif case( 'p' ): reserve_pedo_increnent = 1; // ここで増やすにはスタックが足りない。↑で予約のみ、task_misc内で処理 // hosu_increment_if_necessary(); // 今、一歩増えた break; } // vreg_ctr[ VREG_C_COMMAND3 ] = data; // 書く必要なし break; case ( VREG_C_RBR_CONTROL ): if(( data & REG_BIT_RESET_n ) != 0 ) { RBR_RESET_n = 1; } else { RBR_RESET_n = 0; } if(( data & REG_BIT_FLIGHT ) != 0 ) { RBR_FLIGHT = 1; } else { RBR_FLIGHT = 0; } vreg_ctr[ VREG_C_RBR_CONTROL ] = data; break; // read only ////////////////////////////////////////// case VREG_C_MCU_VER_MAJOR: case VREG_C_MCU_VER_MINOR: case VREG_C_3D: // すぐにリフレッシュされる case VREG_C_SND_VOL: // すぐにリフレッシュされる case VREG_C_BT_TEMP: // すぐにリフレッシュされる case VREG_C_BT_REMAIN: // すぐにリフレッシュされる case VREG_C_BT_REMAIN_FINE: // すぐにリフレッシュされる case VREG_C_BT_VOLTAGE: // すぐにリフレッシュされる case VREG_C_STATUS_1: // 適当にリフレッシュされる case VREG_C_STATUS: // 適当にリフレッシュされる case VREG_C_IRQ0: // 次のついでに割り込み起こしてほしいなら... case VREG_C_IRQ1: case VREG_C_IRQ2: case VREG_C_IRQ3: case VREG_C_IRQ4: case VREG_C_LED_NOTIFY_FLAG: // すぐリフレッシュされる case VREG_C_RTC_SEC_FINE_L: // すぐリフレッシュされる case VREG_C_RTC_SEC_FINE_H: // すぐリフレッシュされる // VREG_C_ACC_RESERVE, // 何も起きない // VREG_C_ACC_HOSU_HIST = 0x4F, case VREG_C_ACC_XH: // すぐリフレッシュされる case VREG_C_ACC_XL: case VREG_C_ACC_YH: case VREG_C_ACC_YL: case VREG_C_ACC_ZH: case VREG_C_ACC_ZL: // dbg_nop(); // return( ERROR ) break; case VREG_C_ACC_HOSU_L: // 書けてもいいけど、デバッグ用。(アドレス0x4B == mcu sla(r)) // dbg_nop(); /* FALLTHROUGH */ // 普通に書かれるだけ ///////////////////////////////// default: /* case VREG_C_IRQ_MASK0: case VREG_C_IRQ_MASK1: case VREG_C_IRQ_MASK2: case VREG_C_IRQ_MASK3: case VREG_C_IRQ_MASK4: case VREG_C_DBG01: case VREG_C_DBG02: case VREG_C_LED_BRIGHT: case VREG_C_ACC_HOSU_L: case VREG_C_ACC_HOSU_M: case VREG_C_ACC_HOSU_H: case VREG_C_ACC_HOSU_HOUR_BOUNDARY: case VREG_C_FREE_ADRS: case VREG_C_RTC_ALARM_YEAR: case VREG_C_ACC_W_ADRS: case VREG_C_OFF_DELAY: case VREG_C_HAL_OVW_CONT0: case VREG_C_HAL_OVW_DAT0: case VREG_C_HAL_OVW_CONT1: case VREG_C_HAL_OVW_DAT1: */ if( adrs < VREG_C_ENDMARK_ ) { vreg_ctr[adrs] = data; break; } else { // dbg_nop(); // 未定義アドレスに書いた なんかバグってない? // return( ERROR ) break; } } // return( SUCCESS ) return; } // ******************************************************** // I2C仮想レジスタから読みます。 // 戻り: xx データ // 注意:次のアドレスの準備で呼ばれる ので、 // リードされたらクリアなどは気をつける // ( →vreg_ctr_after_read( u8 adrs ) ) u8 vreg_ctr_read( u8 adrs ) { static u16 rsub_temp; u8 temp; // RTCは読み出し途中に繰り上がるのを避けるため if( ( VREG_C_RTC_SEC <= adrs ) && ( adrs <= VREG_C_RTC_YEAR ) ) { rtc_buf_refresh( ); } else if( adrs == VREG_C_MCU_STATUS ) { return( ( vreg_ctr[ VREG_C_MCU_STATUS ] & 0x03 ) | ( ( vreg_twl[ REG_TWL_INT_ADRS_MODE ] & 0x03 ) << 6 ) | // sys_mode ( ( vreg_twl[ REG_TWL_INT_ADRS_MODE ] & 0x80 ) >> 2 )); // vol32 } else if( adrs == VREG_C_RTC_SEC_FINE_L ) { rsub_temp = RSUBC; return( (u8)( rsub_temp & 0xFF ) ); } else if( adrs == VREG_C_RTC_SEC_FINE_H ) { return( (u8)( ( rsub_temp >> 8 ) & 0xFF ) ); } /* // debug 的な else if( adrs == VREG_C_IRQ_MASK0 ) { return( vreg_ctr[ VREG_C_IRQ_MASK0 ] & 0x7F ); // ぜ〜ったいにMSBは0。1なら通信エラー } */ else if( adrs == VREG_C_ACC_HOSU_HIST ) { return( hosu_read() ); } else if( adrs == VREG_CX_FREE_DATA ) { temp = pool.vreg_c_ext.vreg_c_free[ vreg_free_adrs ]; // vreg_free_adrs ++; // ここで加算してしまうとインデックスがずれる return( temp ); } else if( adrs == VREG_CX_INFO ) { return( extinfo_read() ); } else if( adrs == VREG_C_ACC_HOSU_SETTING ) { if( pedolog_overflow ) { return( 0x10 ); } else { return( 0 ); } } if( adrs >= VREG_C_ENDMARK_ ) { // VREG_C_INFO > VREG_C_ENDMARK_ なのでいじるとき注意 return( 0xFF ); } return ( vreg_ctr[adrs] ); } // ******************************************************** // I2C仮想レジスタから読まれて何かするレジスタ void vreg_ctr_after_read( u8 adrs, u8 data ) { // 割り込みフラグはリードでクリア switch( adrs ) { case VREG_C_IRQ0: case VREG_C_IRQ1: case VREG_C_IRQ2: case VREG_C_IRQ3: case VREG_C_IRQ4: DI_wt_chk(); vreg_ctr[ adrs ] ^= data; EI(); irq_readed = true; break; case VREG_CX_FREE_DATA: vreg_free_adrs ++; break; default: break; } } /****************************************************************************** 割り込みを入れる  マスクされてたら、フラグ「立てない」、割り込み入れない。  割り込みを入れ、読み出される前にマスクがかかったときは、SoC上の処理キュー上には IRQを読むタスクが積んであるので、読みには来る。  それと、念のため、マスクをいじるときは空読みしてもらう。 ★すでにDIかのチェック不要。  DI中に来るのはI2C_twlか、RTC_アラーム。この中で無頓着にEIして問題ない *****************************************************************************/ void set_irq( u8 irqreg, u8 irq_flg ) { u8 tot; //0 u8 ei_orig; // EIフラグ保存 if(( system_status.pwr_state == ON ) || ( system_status.pwr_state == SLEEP )) { /*0 すでにDI状態ならケアが必要かもしれない ei_orig = get_ei(); //. debug if( !ei_orig ) { dbg_nop(); } DI_wt_chk(); */ DI(); if( ( vreg_ctr[ irqreg + 8 ] & irq_flg ) == 0 ){ vreg_ctr[ irqreg ] |= irq_flg; IRQ0_neg; // 一瞬上げて... //0 if( ei_orig ) { EI(); } tot = 0; while( !IRQ0 && ( ++tot != 0 ) ){;} // O.D.なのでちゃんとあがるのを待つ & IRQ_mcu がLに縛られてると困る(基板不良) IRQ0_ast; // 落とし直す。(エッジ割り込みの為) } //0 if( ei_orig ) { EI(); } } }