/*******************************************************************************
  MPLAB Harmony Application Source File

  Company:
    Microchip Technology Inc.

  File Name:
    app.c

  Summary:
    This file contains the source code for the MPLAB Harmony application.

  Description:
    This file contains the source code for the MPLAB Harmony application.  It
    implements the logic of the application's state machine and it may call
    API routines of other MPLAB Harmony modules in the system, such as drivers,
    system services, and middleware.  However, it does not call any of the
    system interfaces (such as the "Initialize" and "Tasks" functions) of any of
    the modules in the system or make any assumptions about when those functions
    are called.  That is the responsibility of the configuration-specific system
    files.
 *******************************************************************************/

// *****************************************************************************
// *****************************************************************************
// Section: Included Files
// *****************************************************************************
// *****************************************************************************

#include "app.h"


#include "stdio.h"
#include "1lcd_lib_XC32.h"
#include "definitions.h"                // SYS function prototypes

DRV_HANDLE spi_Handle;
DRV_SPI_TRANSFER_HANDLE transferHandle;



//SST25VF016Bへの制御コマンド
#define ysSST25_CMD_READ  (unsigned)0x03  //Read instruction, 03H,
#define ysSST25_CMD_WRITE (unsigned)0x02  //Page-Program instruction, 02H //To program up to 256 Bytes
#define ysSST25_CMD_WREN  (unsigned)0x06  //Write-Enable (WREN) instruction, 06H,
#define ysSST25_CMD_RDSR  (unsigned)0x05  //Read-Status-Register (RDSR) instruction,05H,

#define ysSST25_CMD_EWSR  (unsigned)0x50  //64 KByte Block-Erase
#define ysSST25_CMD_SER   (unsigned)0x20  //4 KByte Sector-Erase
#define ysSST25_CMD_ERASE (unsigned)0x60  //Chip-Erase

#define ysSST25_CMD_WRSR  (unsigned)0x01  // Write Status Register

//SST25VF016BのCS制御
#define ysSST25CSLow()    LATAbits.LATA0 = 0
#define ysSST25CSHigh()   LATAbits.LATA0 = 1


//SPIフラッシュメモリ 諸元
//16 Mbit SPI Serial Flash    SST25VF016B
//Features
//. Single Voltage Read and Write Operations    2.7-3.6V
//. Serial Interface Architecture    SPI Compatible: Mode 0 and Mode 3
//. High Speed Clock Frequency   Up to 80 MHz
//. Superior Reliability    Endurance: 100,000 Cycles (typical)
//                          Greater than 100 years Data Retention
//. Low Power Consumption:    Active Read Current: 10 mA (typical)
//                            Standby Current: 5 μA (typical)
//. Flexible Erase Capability    Uniform 4 KByte sectors
//                               Uniform 32 KByte overlay blocks
//                               Uniform 64 KByte overlay blocks
// Fast Erase and Byte-Program:    Chip-Erase Time: 35 ms (typical)
//                                  Sector-/Block-Erase Time: 18 ms (typical)
//                                 Byte-Program Time: 7 μs (typical)

int delay_Clock = 200000000;   //200MHz
char Buf[32];
char Buf2[25];

unsigned int adrStr = 0x00005678;  //読み書きするSPIフラッシュの先頭アドレス
char* str;
char str_Hellow[] = "Hellow World";
char str_PIC32MZ[] = "PIC32MZ Run";
char str_SpiFlash[] = "Spi Flash";



void delay_us(volatile unsigned int usec)        //1μsec遅延
{
        volatile  int count;

        count = (int)(delay_Clock/20000000)*usec;


        do      //実測 at 200MH (Clock=200000000)
        {       //delay_us(1000):1000.4μsec  delay_us(100):100.6μsec  delay_us(10):10.5μsec  delay_us(1):1.5μsec
                asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");asm("NOP");
                asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");

                count--;
        }while(count != 0);


}



void delay_ms(volatile unsigned int msec)        //1msec遅延
{
        volatile unsigned int i;         //実測:at200MH (Clock=200000000)//delay_ms(1): 1.0006msec   delay_ms(100):100.04msec

        for(i=0; i<msec; i++)
        delay_us(1000);
}


void ysSPIPut(unsigned char data)   //SPIバッファへ書き込み
{ 
    while(!SPI2STATbits.SPITBE);    //送信バッファーが空になるまで待つ

    SPI2BUF = data;     //送受信バッファにデータを書き込む
    //SPI2_Write(&data, sizeof(data));      //★ 動作せず
    //DRV_SPI_WriteTransferAdd(spi_Handle, &data, sizeof(data), &transferHandle);   //★動作せず

    while(!SPI2STATbits.SPIRBF);    //受信完了(バッファフル)まで待つ

    return;
}


unsigned char ysSPIGet (void)   //SPIバッファの取得
 {
    unsigned char spiData = 0;

    spiData = SPI2BUF;  //送受信バッファのデータを読込む
    //DRV_SPI_ReadTransferAdd(spi_Handle, &spiData, sizeof(spiData), &transferHandle);//★動作せず
    //SPI2_Read(&spiData, sizeof(spiData));//★動作せず

    return spiData;
}


unsigned char ysSST25IsWriteBusy(void)  //ステータスレジスタSRのBUSY信号取得    //戻り値 1:書き込み中、0:非書き込み中
{
    unsigned char    temp;

    ysSST25CSLow();

    ysSPIPut(ysSST25_CMD_RDSR); //ステータスレジスタSR読み込み要求送信
    ysSPIGet();

    ysSPIPut(0);  //ダミーを送信
    temp = ysSPIGet();  //ステータスレジスタSR値取得

    ysSST25CSHigh();
    return (temp & 0x01);   //ステータスレジスタSRのBUSY(bit0)を抽出、

}



void ysSST25WriteEnable(void)   //書き込みイネーブル化
{
    ysSST25CSLow();

    ysSPIPut(ysSST25_CMD_WREN);
    ysSPIGet();
    ysSST25CSHigh();

}

void ysSST25SectorErase(unsigned int address)     //セクタ消去  //消去セクタ--> FFH    //消去するセクタは 最初に送信されるMSBにより決まる
{
    ysSST25WriteEnable();

    ysSST25CSLow();

    ysSPIPut(ysSST25_CMD_SER);  //4 KByte Sector-Erase コマンド送信
    ysSPIGet();

    ysSPIPut((unsigned char)((address & 0x00FF0000) >> 16));   //書込みアドレスの第2バイト(MSB)送信
    ysSPIGet();

    ysSPIPut((unsigned char)((address & 0x0000FF00) >> 8 ));     //書込みアドレスの第1バイト送信
    ysSPIGet();

    ysSPIPut((unsigned char)(address & 0x000000FF));             //書込みアドレスの第0バイト(LSB)送信
    ysSPIGet();

    ysSST25CSHigh();

    
    while(ysSST25IsWriteBusy());    //書き込み完了まで待つ  // Wait for write end
}





void ysSST25ChipErase(void)   //全チップ消去    //全データ --> FFH
{
    ysSST25WriteEnable();  //追加

    ysSST25CSLow();

    ysSPIPut(ysSST25_CMD_ERASE);    //Chip-Eraseコマンド送信
    ysSPIGet();

    ysSST25CSHigh();


    while(ysSST25IsWriteBusy());

}


void ysSST25ResetWriteProtection(void)  //ライトプロテクト解除
{

    ysSST25CSLow();

    ysSPIPut(ysSST25_CMD_EWSR); //書込みイネーブル  // send write enable command
                                //The Enable-Write-Status-Register (EWSR) instruction arms the Write-Status-Register (WRSR)instruction and opens the status register for alteration.
    ysSPIGet();

    ysSST25CSHigh();

    ysSST25CSLow();

    ysSPIPut(ysSST25_CMD_WRSR); //ステータスレジスタ(WRSR)書換えコマンド送信
                                //The Write-Status-Register instruction writes new values to the BP3, BP2, BP1, BP0, and BPL bits of the status register.
    ysSPIGet();

    ysSPIPut(0);    //ステータスレジスタ クリア --> BP3, BP2, BP1, BP0 = 0 --> ライトプロテクト解除
    ysSPIGet();

    ysSST25CSHigh();

    while(ysSST25IsWriteBusy());    // Wait for write end
}




unsigned char ysSST25ReadByte(unsigned int address) //1バイト読み込み
{
    unsigned char    temp;

    ysSST25CSLow();

    ysSPIPut(ysSST25_CMD_READ); //1バイト読み込みコマンド送信
    ysSPIGet();

    //読み込みアドレス送信
    ysSPIPut((unsigned char)((address & 0x00FF0000) >> 16));   //書込みアドレスの第2バイト(MSB)送信 //SPIPut(((DWORD_VAL) address).v[2]);
    ysSPIGet();

    ysSPIPut((unsigned char)((address & 0x0000FF00) >> 8 ));     //書込みアドレスの第1バイト送信 //SPIPut(((DWORD_VAL) address).v[1])
    ysSPIGet();

    ysSPIPut((unsigned char)(address & 0x000000FF));             //書込みアドレスの第0バイト(LSB)送信 //SPIPut(((DWORD_VAL) address).v[0]);
    ysSPIGet();

    ysSPIPut(0);  //ダミーを送信
    temp = ysSPIGet();

    ysSST25CSHigh();

    return (temp);

}







void ysSST25WriteByte(unsigned char data, unsigned int address) //1バイト書き込み
{
    ysSST25WriteEnable();
    ysSST25CSLow();

    ysSPIPut(ysSST25_CMD_WRITE);
    ysSPIGet();

    ysSPIPut((unsigned char)((address & 0x00FF0000) >> 16));   //書込みアドレスの第2バイト(MSB)送信 //SPIPut(((DWORD_VAL) address).v[2]);
    ysSPIGet();

    ysSPIPut((unsigned char)((address & 0x0000FF00) >> 8 ));     //書込みアドレスの第1バイト送信 //SPIPut(((DWORD_VAL) address).v[1])
    ysSPIGet();

    ysSPIPut((unsigned char)(address & 0x000000FF));             //書込みアドレスの第0バイト(LSB)送信 //SPIPut(((DWORD_VAL) address).v[0]);
    ysSPIGet();

    ysSPIPut(data);   //データ(unsigned char)を送信
    ysSPIGet();

    ysSST25CSHigh();

    // Wait for write end
    while(ysSST25IsWriteBusy());


}




unsigned char ysSST25WriteArray(unsigned int address, char *pData, unsigned short nCount)  //文字列書き込
{
    unsigned int   addr;
    char    *pD;
    unsigned short    counter;


    addr = address;
    pD = pData;

    // WRITE
    for(counter = 0; counter < nCount; counter++)
    {
        ysSST25WriteByte(*pD++, addr++);
    }


    return (1);
}

void ysSST25ReadArray(unsigned int address, char *pData, unsigned short int nCount)    //文字列読み込み
{
    ysSST25CSLow();

    ysSPIPut(ysSST25_CMD_READ);
    ysSPIGet();

    ysSPIPut((unsigned char)((address & 0x00FF0000) >> 16));   //書込みアドレスの第2バイト(MSB)送信 //SPIPut(((DWORD_VAL) address).v[2]);
    ysSPIGet();

    ysSPIPut((unsigned char)((address & 0x0000FF00) >> 8 ));     //書込みアドレスの第1バイト送信 //SPIPut(((DWORD_VAL) address).v[1])
    ysSPIGet();

    ysSPIPut((unsigned char)(address & 0x000000FF));             //書込みアドレスの第0バイト(LSB)送信 //SPIPut(((DWORD_VAL) address).v[0]);
    ysSPIGet();

    while(nCount--)
    {
        ysSPIPut(0);
        *pData++ = ysSPIGet();
    }

    ysSST25CSHigh();
}

void ysEnhancedBuffer_Disable(void) //エンハンストバッファー 無効化関数
                                        //Harmony ver.3 ではデフォルトで Enhanced Bufferがイネーブルになっている。
{
    //Enhanced Buffer mode is disabled
     SPI2CONbits.ENHBUF = 0;     //エンハンスト バッファー 無効    //b16 ENHBUF: Enhanced Buffer Enable bit
}








// *****************************************************************************
// *****************************************************************************
// Section: Global Data Definitions
// *****************************************************************************
// *****************************************************************************

// *****************************************************************************
/* Application Data

  Summary:
    Holds application data

  Description:
    This structure holds the application's data.

  Remarks:
    This structure should be initialized by the APP_Initialize function.

    Application strings and buffers are be defined outside this structure.
*/

APP_DATA appData;

// *****************************************************************************
// *****************************************************************************
// Section: Application Callback Functions
// *****************************************************************************
// *****************************************************************************

/* TODO:  Add any necessary callback functions.
*/

// *****************************************************************************
// *****************************************************************************
// Section: Application Local Functions
// *****************************************************************************
// *****************************************************************************


/* TODO:  Add any necessary local functions.
*/


// *****************************************************************************
// *****************************************************************************
// Section: Application Initialization and State Machine Functions
// *****************************************************************************
// *****************************************************************************

/*******************************************************************************
  Function:
    void APP_Initialize ( void )

  Remarks:
    See prototype in app.h.
 */

void APP_Initialize ( void )
{
    /* Place the App state machine in its initial state. */
    appData.state = APP_STATE_INIT;



    /* TODO: Initialize your application's state machine and other
     * parameters.
     */
    
//------------------------------------------------------------------------------------------    
//SPIレジスタ直接設定    
//1. 制御レジスタ     
//    SPI2CON = 0;            //必須 もってSPI1CONbits.ENHBUF= 0 の為 
    
//    SPI2CONbits.FRMEN = 0;  //b31   フレーム制御OFF
//    SPI2CONbits.MCLKSEL = 0;    //b23 ボーレートジェネレータのクロック源:PBCLK2    //0: PBCLK2 is used by the Baud Rate Generator
    
    
//    SPI2CONbits.ENHBUF = 0;     //必須                        //b16 ENHBUF: Enhanced Buffer Enable bit
//    SPI2CONbits.ON = 1;     //b15 //SPIモジュールON   //SPI Peripheral is enabled
//                            b14 未定義
//    SPI2CONbits.SIDL = 0;   //b13
//    SPI2CONbits.DISSDO = 0; //b12
//    SPI2CONbits.MODE32 = 0; //b11 //非32ビット転送 -->8ビット転送  //MODE32=0,MODE16=0,SPI1CONbits.AUDEN=0 が3つ共0なので8ビット転送
//    SPI2CONbits.MODE16 = 0; //b10 //非16ビット転送


//    SPI2CONbits.SMP = 0;    //b9  //出力データ中央でサンプリング//Input data sampled at middle of data output time
//    SPI2CONbits.CKE = 1;    //b8  //クロックがアイドル→アクティブ変化時検出 
//    SPI2CONbits.SSEN = 0;   //b7  //SSピン制御OFF
//    SPI2CONbits.CKP = 0;    //b6  //クロック:アクティブで1   //Idle state for clock is a low level; active state is a high level
//    SPI2CONbits.MSTEN = 1;  //b5  //マスターモード

    
    //    SPI2CONbits.DISSDI = 0; //b4
//    SPI2CONbits.STXISEL = 0;    //b3,b2   //SPIxTXIF is set when the last transfer is shifted out of SPISR and transmit operations are complete
//    SPI2CONbits.SRXISEL = 0;    //b1,b0   //SPIxRXIF is set when the last word in the receive buffer is read
  
////2. SPIボーレート
//    
//    SPI1BRG = 0x0031; ;   //SPIボーレート: 1MHz(= 100MHz/2 ÷ (49 + 1) ) //0x31 = 49
////                          //SPIボーレート: X MHz( = Fpbclk(100MHz)/2 ÷ (BRG<8:0> + 1) )
//-------------------------------------------------------------------------------------------    
    
    
    
    lcd_init();				// LCD初期化
    lcd_cmd(0b00001100);    // カーソル:OFF  ブリンク:OFF
        
    lcd_clear(); 
    
    delay_ms(1000);
    
    lcd_cmd(0x80);          //1目の先頭へ
    sprintf(Buf,"SPI Module           ");//
    lcd_str(Buf);                   //液晶表示
    
    delay_ms(1000);

    lcd_cmd(0xC0);          //2行目の先頭へ
    sprintf(Buf,"  Start Test 1       ");	//
    lcd_str(Buf);           // 開始メッセージ1行目表示
    
    
    delay_ms(3000);

    
//    //spi_Handle = DRV_SPI_Open(DRV_SPI_INDEX_0, DRV_IO_INTENT_WRITE);    
//    spi_Handle = DRV_SPI_Open(DRV_SPI_INDEX_0,  DRV_IO_INTENT_READWRITE);
//            
//    DRV_SPI_TRANSFER_SETUP setup;
////    setup.baudRateInHz = 1000000;
////    setup.clockPhase =  DRV_SPI_CLOCK_PHASE_VALID_LEADING_EDGE;
////    //setup.clockPhase =  DRV_SPI_CLOCK_PHASE_VALID_TRAILING_EDGE;
////    setup.clockPolarity = DRV_SPI_CLOCK_POLARITY_IDLE_LOW;
////    setup.dataBits = DRV_SPI_DATA_BITS_8;
////    setup.chipSelect = GPIO_PIN_RA0;
////    setup.csPolarity = DRV_SPI_CS_POLARITY_ACTIVE_LOW;
//    DRV_SPI_TransferSetup ( spi_Handle, &setup );

    
//    SPI2_Initialize (); 
    
    
    
    ysEnhancedBuffer_Disable(); //必須  //Enhanced Buffer mode is disabled
                                //Harmony ver.3 ではデフォルトで Enhanced Bufferがイネーブルになっている
    
    ysSST25ResetWriteProtection();  //SPIフラッシュメモリ ライトプロテクト解除

//1回目---------------------------------------------------------------------------
    ysSST25SectorErase(adrStr);  //セクタ消去
    //ysSST25ChipErase(); //チップ消去
    
    ysSST25WriteArray(adrStr, str_Hellow, sizeof(str_Hellow));   ////文字列書き込み
  
    delay_ms(100);

    lcd_cmd(0x80);          //1目の先頭へ
    sprintf(Buf,"1st                ");	//
    lcd_str(Buf);                   //液晶表示

    lcd_cmd(0xC0);          //2行目の先頭へ

    str = &Buf[0];  // ポインタにアドレスを代入
    ysSST25ReadArray(adrStr, str, 17) ; //文字列読出し

    sprintf(Buf,"%s",str);
    sprintf(Buf2,"Str=%s        ",Buf);
    lcd_str(Buf2);

    delay_ms(2000);


//2回目-----------------------------------------------------------------------------

      ysSST25SectorErase(adrStr);  //セクタ消去
    //ysSST25ChipErase(); //チップ消去

    ysSST25WriteArray(adrStr, str_PIC32MZ, sizeof(str_PIC32MZ));   ////文字列書き込み

    delay_ms(100);

    lcd_cmd(0x80);          //1目の先頭へ
    sprintf(Buf,"2nd                ");	//
    lcd_str(Buf);                   //液晶表示

    lcd_cmd(0xC0);          //2行目の先頭へ

    str = &Buf[0];  // ポインタにアドレスを代入
    ysSST25ReadArray(adrStr, str, 17) ; //文字列読出し

    sprintf(Buf,"%s",str);
    sprintf(Buf2,"Str=%s        ",Buf);
    lcd_str(Buf2);

    delay_ms(2000);

    //3回目------------------------------------------------------------------------
        ysSST25SectorErase(adrStr);  //セクタ消去
    //ysSST25ChipErase(); //チップ消去

    ysSST25WriteArray(adrStr, str_SpiFlash, sizeof(str_SpiFlash));   ////文字列書き込み

    delay_ms(100);

    lcd_cmd(0x80);          //1目の先頭へ
    sprintf(Buf,"3rd                ");	//
    lcd_str(Buf);                   //液晶表示

    lcd_cmd(0xC0);          //2行目の先頭へ

    str = &Buf[0];  // ポインタにアドレスを代入
    ysSST25ReadArray(adrStr, str, 17) ; //文字列読出し

    sprintf(Buf,"%s",str);
    sprintf(Buf2,"Str=%s        ",Buf);
    lcd_str(Buf2);

    delay_ms(2000);

}


/******************************************************************************
  Function:
    void APP_Tasks ( void )

  Remarks:
    See prototype in app.h.
 */

void APP_Tasks ( void )
{

    /* Check the application's current state. */
    switch ( appData.state )
    {
        /* Application's initial state. */
        case APP_STATE_INIT:
        {
            bool appInitialized = true;

            if (appInitialized)
            {

                appData.state = APP_STATE_SERVICE_TASKS;
            }
            break;
        }

        case APP_STATE_SERVICE_TASKS:
        {
            break;
        }

        /* TODO: implement your application state machine.*/


        /* The default state should never be executed. */
        default:
        {
            /* TODO: Handle error in application's state machine. */
            break;
        }
    }
}


/*******************************************************************************
 End of File
 */