/* ======================================================== 対SoC 新規チャンネル I2C通信 藤田@開技.nintendo '09 Apr ======================================================== */ #include "incs.h" #include "accero.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 #define DFC DFC1 #endif // ============================================== extern bit irq_readed; // いずれかのIRQレジスタが読まれた u8 iic_burst_state; /* ======================================================== ======================================================== */ 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 tx_buf; u8 rx_buf; // EI(); // 読み出し終了 if( !ACKD ) // 割り込み要因はNAK(データ送信の最後) { state = IIC_IDLE; SPIE = 0; LREL = 1; // レジスタリードで、割り込みピンをネゲート // まだ読まれてない割り込みがあれば、再度アサート 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; } } // 歩数計読み出し終了 hosu_read_end( ); rtc_unlock( ); iic_burst_state = 0; return; } if( SPD ) // 割り込み要因はストップコンディション // 通信の最後。↑の !ACKD に来たときは割り込み来ない (SPIE = 0 のため ) { state = IIC_IDLE; SPIE = 0; // I2C終了時に何かする物 // rtc_unlock( ); return; } if( STD ) // 割り込み要因:スタートコンディション { if( ( state == IIC_TX ) || ( state == IIC_RX ) || ( state == IIC_RCV_REG_ADRS ) ) { state = IIC_IDLE; // no break // } } switch ( state ) { case ( IIC_IDLE ): // 自局呼び出しに応答。 // 初期化など SPIE = 1; state = IIC_RCV_REG_ADRS; WREL = 1; // ウェイト解除 break; case ( IIC_RCV_REG_ADRS ): // 2バイト目(レジスタアドレス)受信後に来る // レジスタアドレス受信 reg_adrs = IICA; tx_buf = vreg_ctr_read( reg_adrs ); // データの準備をしておく state = IIC_TX_OR_RX; WREL = 1; break; case ( IIC_TX_OR_RX ): // ↑の次に来る割り込み。STなら送信準備、データが来たら書き込まれ // 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: // バースト R/W でここが何回も呼ばれることになる if( state == IIC_TX ) { // 送信 IICA = tx_buf; vreg_ctr_after_read( reg_adrs ); // 読んだらクリアなどの処理 } else { // 受信 rx_buf = IICA; vreg_ctr_write( reg_adrs, rx_buf ); WREL = 1; } // if( ( reg_adrs != VREG_C_ACC_HOSU_HIST ) && ( reg_adrs != VREG_C_INFO ) ) { // この二つのレジスタは特殊なアクセス方法をする。アクセスポインタを進めない。 reg_adrs += 1; } if( state == IIC_TX ) { // さらにつぎに送るデータの準備だけシテオク。SPが来て使われないかもしれない tx_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_TEG2_ P6 &= ~0x3; #else P20 &= ~0x3; #endif SVA = IIC_C_SLAVEADDRESS; IICF = 0x01; STCEN = 1; // リスタートの許可 IICRSV = 1; // 通信予約をさせない:スレーブに徹する SPIE = 0; // ストップコンディションでの割り込みを禁止 WTIM = 1; // 自動でACKを返した後clkをLに固定する ACKE = 1; // ダメCPUは無視して次の通信をはじめるかもしれないんで早くclkを開放しないといけない IICWH = 5; IICWL = 10; // L期間の長さ SMC = 1; // 高速モード DFC = 1; // デジタルフィルタon (@fast mode) IICAMK = 0; // 割り込みを許可 IICE = 1; #ifdef _MODEL_TEG2_ PM6 &= ~0x3; /* set clock pin for IICA */ #else PM20 &= ~0x3; /* set clock pin for IICA */ #endif } // ======================================================== void IIC_ctr_Stop( void ) { IICE = 0; /* IICA disable */ IICAEN = 0; }