twl_mcu/I2C.c
2024-12-17 04:24:29 -05:00

173 lines
4.9 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#pragma interrupt INTIIC0 MD_INTIIC0
#define ignore_NAK 0
#include "macrodriver.h"
#include "I2C.h"
#include "user_define.h"
#include "jhl_defs.h"
#include "vreg.h"
#include "I2C_selfprog.h"
#include "wdt.h"
extern u8 vregs[];
#include "PMIC_TWL2.h"
extern bit self_prog_mode;
/*****************************************************************************
低レベル向け?
*****************************************************************************/
volatile UCHAR gIic0SlaveStatusFlag;
/*****************************************************************************
プロトコル層?向け
*****************************************************************************/
extern UCHAR vregs[];
UCHAR i2c_Send_start_addr;
UCHAR i2c_accessRegAdr;
u8 vreg_adrs;
u8 rcvd_buff;
u8 pre_dat;
// 注 ↓はマクロなので、returnはメインループに戻ります。
#define wait_next { \
while( IICIF0 != 1 ){ \
if( SPD0 ){ \
LREL0 = 1; \
return; \
} \
} \
}
__interrupt void MD_INTIIC0( void ){
WREL0 = 1; // ウェイト解除して次のバイトを待つ
// フラグ1回目 スレーブアドレス,R/W
if( COI0 != 1 ){ // 被呼び出し?
LREL0 = 1; // 呼ばれたのは他のID
return;
}else{
// ACKE0 = 1; // 自動でackを返すようにする
// WREL0 = 1; // ウェイト解除して次のバイトを待つ
}
wait_next; // 1バイト受信完了を待つ
// 2回目 R/W レジスタアドレス
WREL0 = 1;
IICIF0 = 0;
vreg_adrs = adrs_table_ext2int( IIC0 );
// 3回目
// スタートコンディションか、データ受信完了フラグ待ち
while( 1 ){
if( IICIF0 == 1 ){
// 受信 //
IICIF0 = 0;
WREL0 = 1;
if( ( IIC0 == 0x4A ) && ( vreg_adrs == REG_INT_ADRS_TEMP7 ) ){
// 自己プログラム書き換えモード //
// ここで分岐は美しくない気もします...
vregs[ REG_INT_ADRS_MODE ] = 0x00; // 電源オフ時間を短くせんがため。
PM_set_VRSET();
self_programming();
// 帰ってきません
}else{
// 通常アクセス(ライト) //
LREL0 = 1;
debug_led_on;
vregs_write( vreg_adrs, IIC0 );
debug_led_off;
return; // 受信おしまい //
}
}else if( STD0 ){
// 送信 // (スタートコンディション検出)
pre_dat = vregs_read( vreg_adrs ); // mcu内部アドレスを渡す。一バイト目の準備 IIc0に書き込むとウェイト解除
// 自局をRで呼ばれるのを待つ
wait_next;
IICIF0 = 0;
if( COI0 != 1 ){ // 被呼び出し?
LREL0 = 1; // 呼ばれたのは他のIDあれ
return;
}
IIC0 = pre_dat; // データを送る
wait_next;
// 4回目。(送信データ後の、ACK/NACK後) どうしても発生してしまう。
IICIF0 = 0; // おしまい
LREL0 = 1;
return;
}else if( SPD0 ){ // 強制終了
LREL0 = 1;
return;
}
}
}
/*****************************************************************************
基本API
*****************************************************************************/
void IIC0_Init( void )
{
IICE0 = 0; /* IIC0 disable */
IICMK0 = 1; /* INTIIC0 disable */
IICIF0 = 0; /* clear INTIIC0 interrupt flag */
IICPR0 = 0; /* set INTIIC0 high priority */
PM6 &= ~0x1; /* set clock pin for IIC0 */
P6 &= ~0x1;
PM6 &= ~0x2; /* set data transfer I/O pin for IIC0 */
P6 &= ~0x2;
IICCL0 = IICCL0_INITIALVALUE | IIC0_CLOCK4; // レジスタ初期化、高速モード
IICX0 = IIC0_EXPENSION0; // 〃
SVA0 = IIC0_SLAVEADDRESS;
STCEN = 1; // リスタートの許可
IICRSV = 1; // 通信予約をさせない:スレーブに徹する
SPIE0 = 0; // ストップコンディションでの割り込みを禁止
WTIM0 = 1; // 自動でACKを返した後clkをLに固定する
ACKE0 = 1; // ダメCPUは無視して次の通信をはじめるかもしれないんで早くclkを開放しないといけない
IICMK0 = 0; // 割り込みを許可
IICE0 = 1;
}
//****************************************************************************
void IIC0_Stop( void ){
IICE0 = 0; /* IIC0 disable */
}
void IIC0_SlaveReceiveStart(){
gIic0SlaveStatusFlag = 0;
IICE0 = 1;
LREL0 = 1;
return;
}