/*******************************************************************************
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.
*******************************************************************************/

// DOM-IGNORE-BEGIN
/*******************************************************************************
Copyright (c) 2013-2014 released Microchip Technology Inc. All rights reserved.

Microchip licenses to you the right to use, modify, copy and distribute
Software only when embedded on a Microchip microcontroller or digital signal
controller that is integrated into your product or third party product
(pursuant to the sublicense terms in the accompanying license agreement).

You should refer to the license agreement accompanying this Software for
additional information regarding your rights and obligations.

SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE.
IN NO EVENT SHALL MICROCHIP OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER
CONTRACT, NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR
OTHER LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE OR
CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT OF
SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
(INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
*******************************************************************************/
// DOM-IGNORE-END


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

#include "app.h"

#include "stdio.h"
#include "1lcd_lib_XC32.h"

//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バッファへ書き込み
{
//SPI2の場合
while(!PLIB_SPI_TransmitBufferIsEmpty(SPI_ID_2));//送信バッファーが空になるまで待つ
// while(!SPI2STATbits.SPITBE); //送信バッファーが空になるまで待つ

PLIB_SPI_BufferWrite(SPI_ID_2,data); //送受信バッファにデータを書き込む
// SPI2BUF = data; //送受信バッファにデータを書き込む

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

return;
}


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

//SPI2の場合
spiData = PLIB_SPI_BufferRead(SPI_ID_2); //送受信バッファのデータを読込む
// spiData = SPI2BUF; //送受信バッファのデータを読込む

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, unsigned char *pData, unsigned short nCount) //文字列書き込み
{
unsigned int addr;
unsigned 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, unsigned 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();
}






// *****************************************************************************
// *****************************************************************************
// 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.
*/



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);


PLIB_SPI_Enable(SPI_ID_2); //SPIモジュール イネーブル
// SPI2CONbits.ON = 1; //SPI2 有効

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
*/