/* ======================================================== 対SoC 新規チャンネル I2C通信 藤田@開技.nintendo '09 Apr ======================================================== */ #include "incs.h" // u16 tot; #ifdef _MCU_BSR_ #ifdef _MODEL_WM0_ // ワーキングモデルはI2Cが逆 #define ACKD ACKD1 #define ACKE ACKE1 #define COI COI1 #define IICAEN IICA1EN #define IICAPR0 IICAPR10 #define IICRSV IICRSV1 #define IICA IICA1 #define IICAEN IICA1EN #define IICAIF IICAIF1 #define IICAMK IICAMK1 #define IICAPR1 IICAPR11 #define IICCTL0 IICCTL10 #define IICE IICE1 #define IICF IICF1 #define IICS IICS1 #define IICWH IICWH1 #define IICWL IICWL1 #define LREL LREL1 #define SPD SPD1 #define SPIE SPIE1 #define STCEN STCEN1 #define STD STD1 #define SVA SVA1 #define WREL WREL1 #define WTIM WTIM1 #else #define ACKD ACKD0 #define ACKE ACKE0 #define COI COI0 #define IICAEN IICA0EN #define IICAPR0 IICAPR00 #define IICRSV IICRSV0 #define IICA IICA0 #define IICAEN IICA0EN #define IICAIF IICAIF0 #define IICAMK IICAMK0 #define IICAPR1 IICAPR10 #define IICCTL0 IICCTL00 #define IICE IICE0 #define IICF IICF0 #define IICS IICS0 #define IICWH IICWH0 #define IICWL IICWL0 #define LREL LREL0 #define SPD SPD0 #define SPIE SPIE0 #define STCEN STCEN0 #define STD STD0 #define SVA SVA0 #define WREL WREL0 #define WTIM WTIM0 #endif #endif /* ======================================================== ======================================================== */ enum{ IIC_IDLE = 0, IIC_RCV_REG_ADRS, IIC_TX_OR_RX, IIC_TX, IIC_RX }; /* // 1バイト送受の度に割り込みが発生するバージョン __interrupt void int_iic_ctr(){ static u8 state = 0; static u8 reg_adrs; static u8 reg_adrs_internal; static u8 temp; if( SPD ){ state = IIC_IDLE; SPIE = 0; return; } if( ACKD == 0 ){ LREL = 1; state = IIC_IDLE; return; } DBG_P_n = 1; switch( state ){ case( IIC_IDLE ): // 自局呼び出しに応答。 // 初期化など WREL = 1; // ウェイト解除 SPIE = 1; state = IIC_RCV_REG_ADRS; break; case( IIC_RCV_REG_ADRS ): // レジスタアドレス受信 reg_adrs = IICA & 0x1F; WREL = 1; reg_adrs_internal = adrs_table_ctr_ext2int( reg_adrs ); temp = vreg_ctr_read( reg_adrs_internal ); // temp = vreg_ctr[ reg_adrs ]; state = IIC_TX_OR_RX; break; case( IIC_TX_OR_RX ): if( STD ){ // リードされる if( !COI ){ // リスタートで違うデバイスが呼ばれた! WREL = 1; // ウェイト解除? state = IIC_IDLE; // 終了処理 SPIE = 0; }else{ state = IIC_TX; } }else{ state = IIC_RX; } // no break; default: if( state == IIC_TX ){ IICA = temp; }else{ temp = IICA; WREL = 1; vreg_ctr_write( reg_adrs_internal, temp ); // vreg_ctr[ reg_adrs ] = temp; } reg_adrs = ( reg_adrs + 1 ) & 0x1F; reg_adrs_internal = adrs_table_ctr_ext2int( reg_adrs ); if( state == IIC_TX ){ temp = vreg_ctr_read( reg_adrs_internal ); // temp = vreg_ctr[ reg_adrs ]; } break; } DBG_P_n = 0; } */ //#if 0 //一度通信が始まったら終わるまで戻らないバージョン __interrupt void int_iic_ctr(){ static u8 state = 0; static u8 reg_adrs; static u8 reg_adrs_internal; static u8 trx_buf; // EI(); // 自局呼び出しに応答。 // 初期化など WREL = 1; // ウェイト解除 while( !IICAIF ){;} IICAIF = 0; // レジスタアドレス受信 reg_adrs = IICA; WREL = 1; trx_buf = vreg_ctr_read( reg_adrs ); // データの準備をしておく while( !IICAIF ){;} IICAIF = 0; if( STD ){ // リスタートコンディション // リードされる if( !COI ){ // リスタートで違うデバイスが呼ばれた! WREL = 1; // ウェイト解除? state = IIC_IDLE; // 終了処理 SPIE = 0; return; }else{ state = IIC_TX; } }else{ // ライト続行 state = IIC_RX; } if( state == IIC_TX ){ // 送信 // do{ IICA = trx_buf; vreg_ctr_after_read( reg_adrs ); // 読んだらクリアなどの処理 reg_adrs += 1; trx_buf = vreg_ctr_read( reg_adrs ); while( !IICAIF ){;} IICAIF = 0; }while( ACKD ); LREL = 1; }else{ // 受信 // SPIE = 1; do{ trx_buf = IICA; WREL = 1; vreg_ctr_write( reg_adrs, trx_buf ); reg_adrs += 1; while( !IICAIF ){;} IICAIF = 0; }while( !SPD ); SPIE = 0; } vreg_c_iic_release(); state = IIC_IDLE; } //#endif // ======================================================== void IIC_ctr_Init( void ){ IICAEN = 1; IICE = 0; /* IICA disable */ IICAMK = 1; /* INTIICA disable */ IICAIF = 0; /* clear INTIICA interrupt flag */ IICAPR0 = 0; /* set INTIICA high priority */ IICAPR1 = 0; /* set INTIICA high priority */ #ifdef _MODEL_WM0_ P20 &= ~0x3; #else P6 &= ~0x3; #endif SVA = IIC_C_SLAVEADDRESS; IICF = 0x01; STCEN = 1; // リスタートの許可 IICRSV = 1; // 通信予約をさせない:スレーブに徹する SPIE = 0; // ストップコンディションでの割り込みを禁止 WTIM = 1; // 自動でACKを返した後clkをLに固定する ACKE = 1; // ダメCPUは無視して次の通信をはじめるかもしれないんで早くclkを開放しないといけない IICWL = 6; // L期間の長さ(?) IICWH = 5; IICAMK = 0; // 割り込みを許可 IICE = 1; #ifdef _MODEL_WM0_ PM20 &= ~0x3; /* set clock pin for IICA */ #else PM6 &= ~0x3; /* set clock pin for IICA */ #endif } // ======================================================== void IIC_ctr_Stop( void ){ IICE = 0; /* IICA disable */ IICAEN = 0; }