/******************************(spi_EEPROM.c)***************
 *	SPI接続EEPROM(25LC1024)読み書きライブラリ
 ***********************************************************/
#include "stdlib.h"
#include "stdio.h"
#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 ********/
 
 |