/* ======================================================== CTR MCU I2Cレジスタ ====================================================== */ #include "incs.h" #include "vreg_ctr.h" #include "rtc.h" #include "led.h" #include "accero.h" #include "pm.h" #include #include "fsl_user.h" extern u8 mcu_info_read(); // task_misc.c // ******************************************************** u8 vreg_ctr[VREG_C_ENDMARK_]; bit irq_readed; // AAA型のため。 extern bit update; extern u16 pool[]; // ******************************************************** extern task_status_immed tski_firm_update(); extern task_status_immed tski_mcu_info_read(); // ******************************************************** #ifdef _MCU_BSR_ #define IICAMK IICAMK1 #endif // ******************************************************** // 非ゼロの初期値の指定が必要なアドレス void vreg_ctr_init( ) { vreg_ctr[VREG_C_LED_BRIGHT] = 0xFF; #ifdef _PMIC_TWL_ vreg_ctr[VREG_C_MCU_VER_MAJOR] = MCU_VER_MAJOR; #else vreg_ctr[VREG_C_MCU_VER_MAJOR] = MCU_VER_MAJOR | 0x10; #endif vreg_ctr[VREG_C_MCU_VER_MINOR] = MCU_VER_MINOR; vreg_ctr[VREG_C_VCOM_T] = VCOM_DEFAULT_T; vreg_ctr[VREG_C_VCOM_B] = VCOM_DEFAULT_B; } // ******************************************************** // I2C仮想レジスタに書きます。 // 引数 adrs は内部アドレス //  書けないアドレスにアクセスした場合、何もしません。 // ●書き込んだ結果、I2C_mcu通信が発生する場合、renge_task_immed_add() // を使用しないと、I2C_mcu使用中でエラー終了した場合にリトライしません。 void vreg_ctr_write( u8 adrs, u8 data ) { if( adrs >= VREG_C_ENDMARK_ ) return; switch ( adrs ) { case ( VREG_C_MCU_STATUS ): vreg_ctr[adrs] = data; vreg_twl[ REG_TWL_INT_ADRS_MODE ] = ( ( data & 0xC0 ) >> 6 ); 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_DBG1 ): case ( VREG_C_DBG2 ): 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' ) ) { renge_task_immed_add( tski_firm_update ); IICAMK = 1; } break; 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 ): vreg_ctr[adrs] = data; break; case ( VREG_C_COMMAND0 ): vreg_ctr[adrs] |= data; if( data != 0 ) { renge_task_immed_add( do_command0 ); } 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 ) { vreg_ctr[adrs] = ( data & REG_BITS_CMD_BL ); renge_task_immed_add( tski_PM_BL_set ); } break; case ( VREG_C_COMMAND1 ): if( data != 0 ) { // 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 vreg_twl[REG_TWL_INT_ADRS_IRQ] |= ( ( data & REG_BIT_SEND_TWL_VOL_CLICK ) != 0 ) ? REG_BIT_TWL_IRQ_VOL_CHANGE : 0x00; //vol_changed } break; case ( VREG_C_DBG20 ): case ( VREG_C_DBG21 ): case ( VREG_C_DBG22 ): case ( VREG_C_DBG23 ): 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; case ( VREG_C_LED_POW ): 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; /// 非同期で動いているためここでは書かない。 // 予約するだけで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_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_DAY ): set_rtc( adrs - VREG_C_RTC_SEC, data & 0x3F ); 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 ): vreg_ctr[adrs] = data; SUBCUD = data; break; case ( VREG_C_RTC_ALARM_MIN ): vreg_ctr[adrs] = ( data & 0x7F ); rtc_alarm_dirty = 1; break; case ( VREG_C_RTC_ALARM_HOUR ): vreg_ctr[adrs] = ( data & 0x3F ); rtc_alarm_dirty = 1; break; // 書くだけでよい case ( VREG_C_RTC_ALARM_DAY ): vreg_ctr[adrs] = ( data & 0x3F ); break; case ( VREG_C_RTC_ALARM_MONTH ): vreg_ctr[adrs] = ( data & 0x1F ); break; case ( VREG_C_RTC_ALARM_YEAR ): vreg_ctr[adrs] = data; break; case ( VREG_C_ACC_CONFIG ): vreg_ctr[adrs] = data; renge_task_immed_add( acc_hosu_set ); break; case ( VREG_C_ACC_R_ADRS ): vreg_ctr[adrs] = data; renge_task_immed_add( acc_read ); break; case ( VREG_C_ACC_W_ADRS ): vreg_ctr[adrs] = data; break; case ( VREG_C_ACC_W_BUF ): vreg_ctr[adrs] = data; renge_task_immed_add( acc_write ); break; case ( VREG_C_ACC_HOSU_L ): case ( VREG_C_ACC_HOSU_M ): case ( VREG_C_ACC_HOSU_H ): vreg_ctr[adrs] = data; break; case ( VREG_C_ACC_HOSU_SETTING ): if( ( data & 0x01 ) != 0 ) { clear_hosu_hist(); // 履歴クリア } break; case ( VREG_C_COMMAND3 ): vreg_ctr[adrs] = data; switch ( data ) { case ( 'r' ): // 割り込みルーチンからFSLライブラリを呼ぶのは禁止のため // renge_task_immed_add( tski_mcu_reset ); // break; case ( 'w' ): // WDTで再起動(テスト向け) WDTE = 0xAA; break; } } return; } // ******************************************************** // I2C仮想レジスタから読みます。 // 戻り: xx データ // 注意:次のアドレスの準備で呼ばれる ので、 // リードされたらクリアなどは気をつける u8 vreg_ctr_read( u8 adrs ) { static u16 rsub_temp; // RTCは読み出し途中に繰り上がるのを避けるため if( ( VREG_C_RTC_SEC <= adrs ) && ( adrs <= VREG_C_RTC_YEAR ) ) { rtc_buf_reflesh( ); } else if( adrs == VREG_C_MCU_STATUS ) { return( vreg_ctr[ VREG_C_MCU_STATUS ] | ( ( vreg_twl[ REG_TWL_INT_ADRS_MODE ] & 0x03 ) << 6 ) ); } else if( adrs == VREG_C_ACC_HOSU_HIST ) { return( hosu_read() ); } 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 ) ); } else if( adrs == VREG_C_INFO ) { renge_task_immed_add( tski_mcu_info_read ); IICAMK = 1; return( 0x4A ); } #if 1 if( adrs >= VREG_C_ENDMARK_ ) { // VREG_C_INFO > VREG_C_ENDMARK_ なので // いじるときは注意 return( 0xEE ); } #endif return ( vreg_ctr[adrs] ); } // ******************************************************** // I2C仮想レジスタから読まれて何かするレジスタ void vreg_ctr_after_read( u8 adrs ) { // 割り込みフラグはリードでクリア switch( adrs ) { case VREG_C_IRQ0: case VREG_C_IRQ1: case VREG_C_IRQ2: case VREG_C_IRQ3: case VREG_C_IRQ4: vreg_ctr[ adrs ] = 0; irq_readed = 1; break; default: break; } } /****************************************************************************** 割り込みを入れる 割り込みマスクが必要と言うことでこんな事をする羽目になりました *****************************************************************************/ #if 0 // マスクされてたら、フラグは立てるが、割り込みは入れない。 #define set_irq( irqreg, bitpos ) \ { \ vreg_ctr[ irqreg ] |= bitpos; \ if( ( vreg_ctr[ irqreg+8 ] & bitpos ) == 0 ){ \ IRQ0_ast; \ } \ } #endif // マスクされてたら、フラグも立てず、割り込みも入れない。 void set_irq( u8 irqreg, u8 irq_flg ) { u8 tot; DI(); if( ( vreg_ctr[ irqreg + 8 ] & irq_flg ) == 0 ){ vreg_ctr[ irqreg ] |= irq_flg; IRQ0_neg; // 一瞬上げて落とし直す。 // EI(); tot = 0; while( !IRQ0 && ( ++tot != 0 ) ){;} // O.D.なのでちゃんとあがるのを待つ & IRQ_mcu がLに縛られてると困る(基板不良) IRQ0_ast; } EI(); }