/******************************(spi_EEPROM.c)***************
* SPI接続EEPROM(25LC1024)読み書きライブラリ
***********************************************************/
#include
#include
#include "mcc_generated_files/mcc.h"
#include "spi_EEPROM.h"
#define MBFSIZE 78 // メモリ操作用バッファーサイズ
//=== グローバル変数 ============
char Dlm[] = ","; // 文字列区切りデリミタ
char SBuf[20]; / 文字列処理用バッファー
//--- SPIメモリー用
static uint32_t CrtAdr = 0; // カレントアドレス
static uint8_t DBuf[MBFSIZE]; // ページメモリ用バッファー
static uint8_t SqMode = 0; // シーケンスモードフラグ
static char lstCmd; // 最終コマンド
/*************************************
* SPI EEPROM function
**************************************/
//---- ステータスの読み出し
uint8_t SPI_Rom_RdStat(){
uint8_t stat;
CS0_SetLow();
SPI1_ExchangeByte(SPIROM_RD_STATS);
stat = SPI1_ExchangeByte(0xAA); // 0xAAはダミー
CS0_SetHigh();
return stat;
}
//---- コマンドと24ビットアドレスを送信
void sendAdr(uint8_t cmd, uint32_t adr){
CS0_SetLow();
SPI1_ExchangeByte(cmd); // send Command
SPI1_ExchangeByte((uint8_t)(adr>>16);
SPI1_ExchangeByte((uint8_t)(adr>>8));
SPI1_ExchangeByte((uint8_t)adr);
}
//----- アドレスadrから、1バイトを読み出す
uint8_t SPI_Rom_Read(uint32_t adr){
uint8_t dat;
// CS0_SetLow();
sendAdr(SPIROM_READcmd,adr); // send Read_CMD & Address
dat = SPI1_ExchangeByte(0xAA);
CS0_SetHigh();
return dat;
}
//----- アドレスadrに、1バイトdtを書き込む
uint8_t SPI_Rom_Write(uint32_t adr, uint8_t dat){
CS0_SetLow();
SPI1_ExchangeByte(SPIROM_WR_ENABL); // Set Write Enable Bit
CS0_SetHigh();
// CS0_SetLow();
sendAdr(SPIROM_WRITEcmd,adr); // send Write_CMD & Address
SPI1_ExchangeByte(dat);
CS0_SetHigh();
__delay_ms(6);
return dat;
}
//----- アドレスadrからnバイトをary[]に読み出す
void SPI_Rom_NRead(uint32_t adr,uint8_t *ary,uint16_t cnt){
// CS0_SetLow();
sendAdr(SPIROM_READcmd,adr); // send Read_CMD & Address
// SPI1_ExchangeBlock(ary,cnt);
SPI1_ReadBlock(ary,cnt); // block read
CS0_SetHigh();
while(SPI_Rom_RdStat() & 1);
}
//----- アドレスadrからary[]のnバイトを書き込む
void SPI_Rom_NWrite(uint32_t adr,uint8_t *ary,uint16_t cnt){
CS0_SetLow();
SPI1_ExchangeByte(SPIROM_WR_ENABL); // Set Write Enable Bit
CS0_SetHigh();
__delay_us(20);
// CS0_SetLow();
sendAdr(SPIROM_WRITEcmd,adr); // send Write_CMD & Address
// SPI1_ExchangeBlock(ary,cnt); // block write
SPI1_WriteBlock(ary,cnt); // block write
CS0_SetHigh();
while(SPI_Rom_RdStat() & 1);
}
//----- チップ全体の消去
void SPI_Rom_ChipErase(){
CS0_SetLow();
SPI1_ExchangeByte(SPIROM_WR_ENABL);
CS0_SetHigh();
__delay_us(20);
CS0_SetLow();
SPI1_ExchangeByte(SPIROM_CP_ERASE);
CS0_SetHigh();
__delay_ms(15);
}
/****** 汎用サブルーチン ********************/
//---- ページバッファープリント
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進数に変換
uint32_t my_xtoi(char *str){
uint32_t dec;
dec = strtoul(str,NULL,16);
// if(errno == ERANGE) return -1; // 文字列変換エラー
return (uint32_t)dec;
}
/************************************
* コマンドアクション
************************************/
//----- Wコマンド W[aaaa][,[d0,・・[,]]]
uint16_t spiRom_cmd_W(char *str){
char *pt; // 文字列操作用ポインタ
uint8_t last; // 文字列の最後の位置
uint32_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 = res;
}
pt = strtok(NULL,Dlm); // 次文字列取込
}else{
pt = strtok(str+1,Dlm); // 文字列取込
}
do{
if(pt != NULL){ // データがあるか?
res = my_xtoi(pt);
dt = (uint8_t)res;
if(lstCmd=='W'){
SPI_Rom_Write(CrtAdr,dt); // データを書き込む
}else if(lstCmd == 'S'){
DBuf[CrtAdr & 0x3F]= dt;
}
sprintf(SBuf,"%05lX < %02X",CrtAdr,dt);
#ifdef VBA
printf("%s\r",SBuf);
#else
printf("%s\n\r",SBuf);
#endif
gLCD_clrX(0,16,0,128);
gLCD_strX(0,16,SBuf);
CrtAdr++; cnt++;
pt = strtok(NULL,Dlm); // 次文字へ
}
}while(pt != NULL); // データがあるだけ繰り返す
return cnt; // 書き込んだ文字数を返す
}
//---- Rコマンド R[aaaa][,n]
uint16_t spiRom_cmd_R(char *str){
char *pt; // 文字列操作用ポインタ
uint16_t n = 1; // 指定された読込バイト数
uint32_t res = 0; // Hex文字数値変換結果
uint8_t dt; // 読み込んだバイトデータ
uint16_t cnt = 0; // 実際に読み出されたバイト数
uint16_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 = res;
}
pt = strtok(NULL,Dlm); // 次文字へ
if(pt != NULL){ // データ無し?
res = my_xtoi(pt);
n = (uint16_t)res;
}
}
}
for(i = 0; i < n; i++ ){
dt = SPI_Rom_Read(CrtAdr); // データを読み出す
sprintf(SBuf,"%05lX > %02X",CrtAdr,dt);
#ifdef VBA
printf("%s\r",SBuf);
#else
printf("%s\n\r",SBuf);
#endif
gLCD_clrX(0,16,0,128);
gLCD_strX(0,16,SBuf);
CrtAdr++; cnt++;
}
SqMode = 0;
return cnt; // 読み込んだデータ数を返す
}
//---- WSQ (連続書込モード)
uint16_t spiRom_cmd_WSQ(char *str){
char *pt; // 文字列操作用ポインタ
uint8_t dt; // 書き込むバイトデータ
uint32_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'){
SPI_Rom_Write(CrtAdr,dt); // データを書き込む
}else if(lstCmd=='S'){
DBuf[CrtAdr & 0x3F]= dt;
}
sprintf(SBuf,"%05lX < %02X",CrtAdr,dt);
#ifdef VBA
printf("%s\r",SBuf);
#else
printf("%s\n\r",SBuf);
#endif
gLCD_clrX(0,16,0,128);
gLCD_strX(0,16,SBuf);
CrtAdr++; cnt++;
pt = strtok(NULL,Dlm); // 次文字列へ
}
return cnt; // 書き込んだデータ数を返す
}
//---- Qコマンド(連続書込モードの解除) Q
void spiRom_cmd_Q(char *str){
lstCmd = str[0];
SqMode = 0;
#ifndef VBA
puts("SqMode OFF\r");
#endif
}
//---- U(dump)コマンド U[aaaa]
// (64バイトのデータをDBuf[]に読み出す)
int spiRom_cmd_U(char *str){
char *pt; // 文字列操作用ポインタ
uint32_t res; // Hex文字数値変換結果
uint16_t ad; // 指定アドレス
lstCmd = str[0];
pt = strtok(str+1,Dlm);
if(pt != NULL){ // アドレス有り?
res = my_xtoi(pt);
CrtAdr = res;
}
ad = CrtAdr & 0xFFFFC0; // 64バイト単位に
SPI_Rom_NRead(ad, DBuf, 64); // 64バイトをDBuf[]に読出し
sprintf(SBuf,"%05lX - %05lX", ad, ad + 63);
printf("%s\r",SBuf);
gLCD_clrX(0,16,0,128);
gLCD_strX(0,16,SBuf);
prt_PBf();
SqMode = 0;
return 0;
}
//---- P(Page)コマンド PW[aaaa]
// (DBuf[]の64バイトをメモリに書き込む)
int spiRom_cmd_P(char *str){
char *pt; // 文字列操作用ポインタ
uint32_t res; // Hex文字数値変換結果
uint16_t ad; // 指定アドレス
lstCmd = str[0];
if(strlen(str)==1){
printf("PageBuffer");
prt_PBf();
return 0;
}
if(str[1]=='R'){
spiRom_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 = res;
}
ad = CrtAdr & 0xFFFFC0; // 64バイト単位に
SPI_Rom_NWrite(ad,DBuf,64); // DBuf[]の64バイト書込
sprintf(SBuf,"Page Write %05lX - %05lX",ad,ad+63);
#ifdef VBA
printf("%s\r",SBuf);
#else
printf("%s\n\r",SBuf);
#endif
gLCD_clrX(0,16,0,128);
gLCD_strX(0,16,SBuf);
SqMode = 0;
return 0;
}
//---- シーケンスモードの確認
uint8_t spiRom_SqMode(){
return SqMode;
}
/******* End of File ********/
|