/* ======================================================== 対SoC 新規チャンネル I2C通信 藤田@開技.nintendo '09 Apr ======================================================== */ #include "incs.h" #ifdef _MCU_BSR_ // #ifdef _MODEL_TS0_ || _MODEL_WM0_ // ワーキングモデルはI2Cが逆 // TEGは回路図でテレコ #define ACKD ACKD1 #define ACKE ACKE1 #define COI COI1 #define IICAEN IICA1EN #define IICRSV IICRSV1 #define IICA IICA1 #define IICAIF IICAIF1 #define IICAMK IICAMK1 #define IICAPR0 IICAPR11 #define IICAPR1 IICAPR01 #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 #define TRC TRC1 #define SMC SMC1 #endif // ============================================== extern bit irq_readed; // いずれかのIRQレジスタが読まれた /* ======================================================== ======================================================== */ 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 = IIC_IDLE; static u8 reg_adrs; static u8 reg_adrs_internal; static u8 trx_buf; EI(); if( SPD ) { state = IIC_IDLE; SPIE = 0; // I2C終了時に何かする物 // rtc_unlock( ); return; } // 読み出し終了 if( !ACKD ) { state = IIC_IDLE; SPIE = 0; LREL = 1; rtc_unlock( ); // レジスタリードで、割り込みピンをネゲート // まだ読まれてない割り込みがあれば、再度アサート if( irq_readed ) { IRQ0_neg; irq_readed = 0; if( !( ( vreg_ctr[VREG_C_IRQ0] == 0 ) && ( vreg_ctr[VREG_C_IRQ1] == 0 ) && ( vreg_ctr[VREG_C_IRQ2] == 0 ) && ( vreg_ctr[VREG_C_IRQ3] == 0 ) ) ) { while( !IRQ0 ){;} // 時間稼ぎ不要かも IRQ0_ast; } } return; } if( STD ) { if( ( state == IIC_TX ) || ( state == IIC_RX ) ) { state = IIC_IDLE; rtc_unlock( ); } } switch ( state ) { case ( IIC_IDLE ): // 自局呼び出しに応答。 // 初期化など SPIE = 1; WREL = 1; // ウェイト解除 state = IIC_RCV_REG_ADRS; break; case ( IIC_RCV_REG_ADRS ): // レジスタアドレス受信 reg_adrs = IICA; WREL = 1; trx_buf = vreg_ctr_read( reg_adrs ); // データの準備をしておく state = IIC_TX_OR_RX; break; case ( IIC_TX_OR_RX ): // if( TRC ){ // 送信方向フラグ if( STD ) { // スタートコンディション検出フラグ // リードされる if( COI ) { // アドレス一致フラグ state = IIC_TX; // no break, no return // } else { // リスタートで違うデバイスが呼ばれた! state = IIC_IDLE; // 終了処理 SPIE = 0; LREL = 1; // ウェイト解除? return; } } else { state = IIC_RX; // データ1バイト受信の割り込みだった // no break, no return // } default: if( state == IIC_TX ) { // 送信 IICA = trx_buf; vreg_ctr_after_read( reg_adrs ); // 読んだらクリアなどの処理 } else { // RX trx_buf = IICA; vreg_ctr_write( reg_adrs, trx_buf ); WREL = 1; } reg_adrs += 1; if( state == IIC_TX ) { trx_buf = vreg_ctr_read( reg_adrs ); } break; } } // ======================================================== void IIC_ctr_Init( void ) { IICAEN = 1; IICE = 0; /* IICA disable */ IICAMK = 1; /* INTIICA disable */ IICAIF = 0; /* clear INTIICA interrupt flag */ IICAPR0 = 1; /* 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を開放しないといけない IICWH = 8; IICWL = 10; // L期間の長さ SMC = 1; // 高速モード 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; }