 #include "Memory.h"

void spi_init(){ // set B8 as digital output
    SPI1CONbits.ON = 0; // make sure hardware is off
    //SPI3CONbits.MODE32 = 1; // set to 32 bit mode
    SPI1CONbits.MCLKSEL = 0;
    SPI1BRG = 0; // divide PBCLK (20 MHz) by 2 to get 10 MHz
    SPI1CONbits.MSTEN = 1; // master mode enable bit set high
    SPI1CONbits.SMP = 1;
    SPI1CONbits.CKP = 0;
    SPI1CONbits.CKE = 1;
    //SPI4CONbits.SRXISEL = 0b00; // SPIxRXIF flag set when last word in receive buffer is read
    SPI1STATCLR = 1<<6; // clear overflow flag bit
    SPI1CONbits.ON = 1;// turn SPI hardware on
}

unsigned char spi_sends(unsigned char data){
    // clear SPI3RXIF flag
    IFS1bits.SPI1RXIF = 0;
    // send byte out
    SPI1BUF = data;
    // wait for data to be shifted out and shifted in
    while (!IFS1bits.SPI1RXIF);
    IFS1bits.SPI1RXIF = 0;
    // return byte that comes in
    return SPI1BUF;

}

void spi_write_flash(unsigned char data, unsigned long addr){
    // wait till EEPROM is available
    //EEPROM_available();

    LATBbits.LATB0 = 0; // set !CS low
    spi_sends(WREN_FLASH); // send WREN instruction
    LATBbits.LATB0 = 1; // set !CS high to set write enable latch
    LATBbits.LATB0 = 0; // set !CS low for WRITE instruction
    spi_sends(PP); // send WRITE instruction
    spi_sends(addr >> 16);
    spi_sends(addr >> 8);
    spi_sends(addr);
    spi_sends(data);// send 24-bit address to write to
    LATBbits.LATB0 = 1; // set !CS high after last bit has been clocked in
    // check to see if write has been completed
    spi_write_complete();
}
/*
void spi_AAI_write_flash(unsigned char data, unsigned long addr){
    LATBbits.LATB0 = 0;
    spi_sends(WREN_FLASH);
    LATBbits.LATB0 = 1;
    LATBbits.LATB0 = 0;
    spi_sends(AAI_WORD_PROG);
    spi_sends(addr >> 16);
    spi_sends(addr >> 8);
    spi_sends(addr);
    spi_sends('A');
    spi_sends('B');
    LATBbits.LATB0 = 1;
    spi_write_complete();
    LATBbits.LATB0 = 0;
    spi_sends(AAI_WORD_PROG);
    spi_sends('C');
    spi_sends('D');
    LATBbits.LATB0 = 1;
    spi_write_complete(); //
    LATBbits.LATB0 = 0;
    spi_sends(WRDI_FLASH);
    LATBbits.LATB0 = 1;
    spi_write_complete();
}
*/
unsigned char spi_read_flash(unsigned long addr) {
    // wait till EEPROM is available
    //EEPROM_available();
    // select device by setting !CS low
    LATBbits.LATB0 = 0;
    // read instruction
    spi_sends(READ_FLASH);
    // send 16-bit addr
    spi_sends(addr >> 16);
    spi_sends(addr >> 8);
    spi_sends(addr);
    unsigned char mem_data = spi_sends(0x00);
    // raise !CS pin
    LATBbits.LATB0 = 1;

    return mem_data;

}

void spi_write_complete(void){
    char status;
    LATBbits.LATB0 = 0;
    do {
    //status = 0;
    //LATBbits.LATB8 = 0;
    spi_sends(RDSR1_FLASH);
    status = spi_sends(0x00);
    //LATBbits.LATB8 = 1;}
    } while((status & 0x01));
    LATBbits.LATB0 = 1;
}
/*
void spi_WRSR_flash(unsigned char status){
    LATBbits.LATB0 = 0;
    spi_sends(EWSR_FLASH);
    LATBbits.LATB0 = 1;
    LATBbits.LATB0 = 0;
    spi_sends(WRSR_FLASH);
    spi_sends(status);
    LATBbits.LATB0 = 1;
    spi_write_complete();
}
*/
void spi_erase_flash(void){
     LATBbits.LATB0 = 0;
     spi_sends(WREN_FLASH);
     LATBbits.LATB0 = 1;
     LATBbits.LATB0 = 0;
     spi_sends(BULK_ERASE);
     LATBbits.LATB0 = 1;
     spi_write_complete();
}

/* SPI Logic Analyzer Pins MOSI: F5; MISO: F4; SCK: B14; CE: B8*/

