/******************************(i2c_EEPROM.c)************
* I2C接続EEPROM(24FC1025)読み書きライブラリ
**********************************************************/
#define DEVICE 0x50 // Blk0=0x50,Blk1=0x54
#define MBFSIZE 78 // メモリ操作用バッファーサイズ
#include "i2cEEPROM.h"
//=== グローバル変数 ============
char Dlm[] = ","; // 文字列区切りデリミタ
char SBuf[20]; // 文字列処理用バッファー
//--- I2Cメモリー用
static uint8_t BlkNum = 0; // メモリブロック番号
static uint16_t CrtAdr = 0; // カレントアドレス
static uint8_t DBuf[MBFSIZE]; // ページメモリ用バッファー
static uint8_t SqMode = 0; // シーケンスモードフラグ
static char lstCmd; // 最終コマンド
/*************************************
* I2C EEPROM function
**************************************/
//----- アドレスadrから、1バイトを読み出す
uint8_t I2C_Mem_Read(uint16_t adr){
uint8_t bf[2];
bf[0] = adr >> 8;
bf[1] = (uint8_t)adr;
#if I2C == 1
I2C1_WriteNBytes(DEVICE + BlkNum,bf,2);
I2C1_ReadNBytes(DEVICE + BlkNum,bf,1);
#elif I2C == 2
I2C2_WriteNBytes(DEVICE + BlkNum,bf,2);
I2C2_ReadNBytes(DEVICE + BlkNum,bf,1);
#else
I2C_WriteNBytes(DEVICE + BlkNum,bf,2);
I2C_ReadNBytes(DEVICE + BlkNum,bf,1);
#endif
return bf[0];
}
//----- アドレスadrに、1バイトdtを書き込む
void I2C_Mem_Write(uint16_t adr, uint8_t dt){
uint8_t bf[3];
bf[0] = adr >> 8;
bf[1] = (uint8_t)adr; // アドレスセット
bf[2] = dt; // データセット
#if I2C == 1
I2C1_WriteNBytes(DEVICE + BlkNum,bf,3); //書き込む
#elif I2C == 2
I2C2_WriteNBytes(DEVICE + BlkNum,bf,3); //書き込む
#else
I2C_WriteNBytes(DEVICE + BlkNum,bf,3); //書き込む
#endif __delay_ms(5);
}
//----- アドレスadrからnバイトをary[]に読み出す
void I2C_Mem_NRead(uint16_t adr, uint8_t *ary, uint8_t n){
uint8_t bf[2];
bf[0] = adr >> 8;
bf[1] = (uint8_t) adr;
if(n > MBFSIZE) n = MBFSIZE; // 配列要素数以内
#if I2C == 1
I2C1_WriteNBytes(DEVICE+BlkNum,bf,2); // アドレス送信
I2C1_ReadNBytes(DEVICE+BlkNum,ary,n); // データ読込
#elif I2C == 2
I2C2_WriteNBytes(DEVICE+BlkNum,bf,2); // アドレス送信
I2C2_ReadNBytes(DEVICE+BlkNum,ary,n); // データ読込
#else
I2C_WriteNBytes(DEVICE+BlkNum,bf,2); // アドレス送信
I2C_ReadNBytes(DEVICE+BlkNum,ary,n); // データ読込
#endif
}
//----- アドレスadrからary[]のnバイトを書き込む
void I2C_Mem_NWrite(uint16_t adr, uint8_t *ary, uint8_t n){
uint8_t bf[MBFSIZE + 2];
bf[0] = adr >> 8; // アドレスセット
bf[1] = (uint8_t) adr; // ページ境界に注意!
if(n > MBFSIZE) n = MBFSIZE;
memcpy(bf+2,ary,n); // ary[]をbf[]にコピー
#if I2C == 1
I2C1_WriteNBytes(DEVICE+BlkNum,bf,n+2);
#elif I2C == 2
I2C2_WriteNBytes(DEVICE+BlkNum,bf,n+2);
#else
I2C_WriteNBytes(DEVICE+BlkNum,bf,n+2);
#endif __delay_ms(5);
}
//---- ページバッファープリント
void prt_PBf(){
uint8_t i;
for(i = 0; i < 64; i++){ // 16x4文字表示
#ifdef VBA
if(i % 16 == 0) printf("\r");
#else
if(i % 16 == 0) printf("\n\r");
#endif
printf(" %02X",DBuf[i]);
}
puts("\r");
}
//---- 16進文字列を10進数に変換
int32_t my_xtoi(char *str){
uint32_t dec;
dec = strtoul(str,NULL,16);
return (int32_t)dec;
}
/************************************
* コマンドアクション
************************************/
//----- Wコマンド W[aaaa][,[d0,・・[,]]]
uint16_t i2cRom_cmd_W(char *str){
char *pt; // 文字列操作用ポインタ
uint8_t last; // 文字列の最後の位置
int32_t res = 0; // Hex文字数値変換結果
uint8_t dt = 0; // 書き込むバイトデータ
uint16_t cnt = 0; // 実際に書き込んだバイト数
lstCmd = str[0];
if(strlen(str)==1){ // 'W'のみなら
SqMode = 1; // 連続書込モードにセット
#ifndef VBA
puts("SqMode ON\n\r");
#endif
return 0; // データは書き込まない
}
last = (uint8_t)strlen(str)-1; // 文字列の行末位置を取得
if(str[last] == ','){ // 行末がコンマなら
SqMode = 1; // 連続書込モードにセット
#ifndef VBA
puts("SqMode ON\n\r");
#endif
str[last]='\0'; // 行末のコンマを消す
}
if(str[1]!=','){ // 第2文字がコンマか?
pt = strtok(str+1,Dlm); // コマンドの次文字から
if(pt != NULL){ // アドレスデータがある
res = my_xtoi(pt);
CrtAdr = (uint16_t)res;
}
pt = strtok(NULL,Dlm); // 次文字列取込
}else{
pt = strtok(str+1,Dlm); // 文字列取込
}
do{
if(pt != NULL){ // データがあるか?
res = my_xtoi(pt);
if(res < 0) return cnt;
dt = (uint8_t)res;
if(lstCmd=='W'){
I2C_Mem_Write(CrtAdr,dt); // データを書込む
}else if(lstCmd == 'S'){
DBuf[CrtAdr & 0x3F]= dt;
}
sprintf(SBuf,"%d:%04X < %02X",BlkNum,CrtAdr,dt);
#ifdef VBA
printf("%s\r",SBuf);
#else
printf("%s\n\r",SBuf);
#endif
LCD_cursor(1,1); LCD_str(SBuf);
CrtAdr++; cnt++;
pt = strtok(NULL,Dlm); // 次文字へ
}
}while(pt != NULL); // データがあるだけ繰り返す
return cnt; // 書き込んだ文字数を返す
}
//---- Rコマンド R[aaaa][,n]
uint16_t i2cRom_cmd_R(char *str){
char *pt; // 文字列操作用ポインタ
uint16_t n = 1; // 指定された読込バイト数
int32_t res = 0; // Hex文字数値変換結果
uint8_t dt; // 読み込んだバイトデータ
uint16_t cnt = 0; // 実際に読み出されたバイト数
uint8_t i; // ループ変数
lstCmd = str[0];
if(strlen(str) > 1){
if(str[1]==','){
pt = strtok(str+2,Dlm);
if(pt != NULL){ // データ無し?
res = my_xtoi(pt);
n = (uint16_t)res;
}
}else{
pt = strtok(str+1,Dlm);
if(pt != NULL){ // addressがある?
res = my_xtoi(pt);
CrtAdr = (uint16_t)res;
}
pt = strtok(NULL,Dlm); // 次文字へ
if(pt != NULL){ // データ無し?
res = my_xtoi(pt);
n = (uint16_t)res;
}
}
}
for(i = 0; i < n;i++ ){
dt = I2C_Mem_Read(CrtAdr); // データを読み出す
sprintf(SBuf,"%d:%04X > %02X",BlkNum,CrtAdr,dt);
#ifdef VBA
printf("%s\r",SBuf);
#else
printf("%s\n\r",SBuf);
#endif
LCD_cursor(1,1); LCD_str(SBuf);
CrtAdr++; cnt++;
}
SqMode = 0;
return cnt; // 読み込んだデータ数を返す
}
//---- WSQ (連続書込モード)
uint16_t i2cRom_cmd_WSQ(char *str){
char *pt; // 文字列操作用ポインタ
uint8_t dt; // 書き込むバイトデータ
int32_t res; // Hex文字数値変換結果
uint16_t cnt = 0; // 実際に読み出されたバイト数
pt = strtok(str,Dlm);
while(pt != NULL){ // データがあるだけ繰り返す
res = my_xtoi(pt);
dt = (uint8_t)res;
if(lstCmd == 'W'){
I2C_Mem_Write(CrtAdr,dt); // データを書き込む
}else if(lstCmd=='S'){
DBuf[CrtAdr & 0x3F]= dt;
}
#ifdef VBA
printf("%d:%04X < %02X\r",BlkNum,CrtAdr,dt);
#else
printf("%d:%04X < %02X\n\r",BlkNum,CrtAdr,dt);
#endif
CrtAdr++; cnt++;
pt = strtok(NULL,Dlm); // 次文字列へ
}
return cnt; // 書き込んだデータ数を返す
}
//---- MBコマンド MBn (メモリバンクの指定)
int i2cRom_cmd_M(char *str){
char *pt; // 文字列操作用ポインタ
uint8_t b; // メモリバンク番号
lstCmd = str[0];
if(str[1] != 'B') return -1; // 第2文字がBか?
pt = strtok(str+2,Dlm);
if(pt==NULL) return -1; // 文字列変換エラー
b = atoi(pt) & 0x01;
#ifdef VBA
printf("Bank %d selected\r",b);
#else
printf("Bank %d selected\n\r",b);
#endif
BlkNum = b * 4; // Blk = bit2
CrtAdr = 0; // 現在アドレスは0に
SqMode = 0;
// puts("SqMode OFF\r");
return b;
}
//---- Qコマンド(連続書込モードの解除) Q
void i2cRom_cmd_Q(char *str){
lstCmd = str[0];
SqMode = 0;
#ifndef VBA
puts("SqMode OFF\r");
#endif
}
//---- U(dump)コマンド U[aaaa]
// (64バイトのデータをDBuf[]に読み出す)
int i2cRom_cmd_U(char *str){
char *pt; // 文字列操作用ポインタ
int32_t res; // Hex文字数値変換結果
uint16_t ad; // 指定アドレス
lstCmd = str[0];
pt = strtok(str+1,Dlm);
if(pt != NULL){ // アドレス有り?
res = my_xtoi(pt);
CrtAdr = (uint16_t)res;
}
ad = CrtAdr & 0xFFC0; // 64バイト単位に
I2C_Mem_NRead(ad,DBuf,64); // 64バイトをDBuf[]に読出
printf("%d:%04X - %04X",BlkNum,ad,ad+63);
prt_PBf();
SqMode = 0;
return 0;
}
//---- P(Page)コマンド PW[aaaa]
// (DBuf[]の64バイトの読み書き)
int i2cRom_cmd_P(char *str){
char *pt; // 文字列操作用ポインタ
int32_t res; // Hex文字数値変換結果
uint16_t ad; // 指定アドレス
lstCmd = str[0];
if(strlen(str)==1){
printf("PageBuffer");
prt_PBf();
return 0;
}
if(str[1]=='R'){ // 第2文字がR?
i2cRom_cmd_U(str+1);
return 0;
}
if(str[1] != 'W') return -1; // 第2文字がW?
pt = strtok(str+2,Dlm);
if(pt != NULL){ // アドレス有り?
res = my_xtoi(pt);
CrtAdr = (uint16_t)res;
}
ad = CrtAdr & 0xFFC0; // 64バイト単位に
I2C_Mem_NWrite(ad,DBuf,64); // DBuf[]の64バイト書込
#ifdef VBA
printf("Page Write %d:%04X - %04X\r",BlkNum,ad,ad+63);
#else
printf("Page Write %d:%04X - %04X\n\r",BlkNum,ad,ad+63);
#endif
SqMode = 0;
return 0;
}
//---- シーケンスモードの確認
uint8_t i2cRom_SqMode(){
return SqMode;
}
/******* End of File ********/
|