/********************************************/
/*71V30 Dual Port RAM Driver Code           */
/*dsPIC33CK512MP608                         */
/*Auto Semaphore version                    */
/********************************************/

    /*     Flag Table        */
    //Flag 000 = address 0000 - 03ff
    //Flag 001 = address 0400 - 07ff
    //Flag 010 = address 0800 - 0bff
    //Flag 011 = address 0c00 - 0fff
    //Flag 100 = address 1000 - 13ff
    //Flag 101 = address 1400 - 17ff
    //Flag 110 = address 1800 - 1bff
    //Flag 110 = address 1c00 - 1fff
    
#include "xc.h"
#include <stdbool.h>
#include "MainMotion.h"

uint16_t address_70V05;
uint8_t volatile mdata_70V05;
int sram_test;
int sram_test_data[1000];
int sram_lock;
int sram_block;
uint8_t flag = 0;
int sram_fail_count = 0;

void dsPIC33_REN70V05_Init(void)
{    
    //SEM
    ANSELE = 0;
    TRISEbits.TRISE3 = 0;
    PORTEbits.RE3 = 1;   
    
    //RE13 = /OE
    TRISEbits.TRISE13 = 0;
    PORTEbits.RE13 = 1;

    //RB5 = SRAM /CS (output)
    ANSELB = 0;
    TRISBbits.TRISB5 = 0;
    PORTBbits.RB5 = 1;

    //Configure SRAM INT pin RE0 (input)
    TRISEbits.TRISE0 = 1;
    ANSELEbits.ANSELE0 = 0;

    //Configure SRAM BUSY pin RE1 (output) and pull high
    TRISEbits.TRISE1 = 0;
    ANSELEbits.ANSELE1 = 0;
    PORTEbits.RE1 = 1;
    
    //SRAM Semaphore Initialization
    /************************************************************************
    Since any semaphore request flag which contains a zero must be reset to a 
    one, all semaphores on both sides should have a one written into them at
    initialization from both sides to assure that they will be free when
    needed.
     
    The Motion Board accesses addresses 0-3ffh so only Flag 0 is used.
    *************************************************************************/
    
    PMADDR = 0;

    //pull SEML low
    PORTEbits.RE3 = 0;

    while(PMMODEbits.BUSY == 1);
    PMDIN1 = 1;
    while(PMMODEbits.BUSY == 1);

    //pull SEML high
    PORTEbits.RE3 = 1;
}

bool dsPIC33_REN70V05_WR(uint16_t address_70V05, uint8_t mdata_70V05)
{     
    uint8_t flag = 1;
    PMADDR = 0;
    
    ///CE
    PORTBbits.RB5 = 1;
    
    //First we must use the semaphore to check and get access
    //pull SEML low
    PORTEbits.RE3 = 0;

    while(PMMODEbits.BUSY == 1);
    PMDIN1 = 0;
    while(PMMODEbits.BUSY == 1);

    //pull SEML high
    PORTEbits.RE3 = 1;

    //read the latch
    //pull SEML low
    PORTEbits.RE3 = 0;

    //dummy read
    while(PMMODEbits.BUSY == 1);
    flag = PMDIN1;
    while(PMMODEbits.BUSY == 1);

    while(PMMODEbits.BUSY == 1);
    flag = PMDIN1;
    while(PMMODEbits.BUSY == 1);

    //Set SEMR
    PORTEbits.RE3 = 1;
    
    if(flag > 0)
    {
        PMADDR = 0;
        
        //Release SRAM
        //pull SEML low
        PORTEbits.RE3 = 0;

        //Write a one
        while(PMMODEbits.BUSY == 1);
        PMDIN1 = 1;
        while(PMMODEbits.BUSY == 1);

        //Set SEMR
        PORTEbits.RE3 = 1;

        return false;
    }
    PMADDR = address_70V05;

    ///CE    
    PORTBbits.RB5 = 0;

    while(PMMODEbits.BUSY == 1);
    PMDIN1 = mdata_70V05;
    while(PMMODEbits.BUSY == 1);

    ///CE
    PORTBbits.RB5 = 1;
        
    //Release SRAM
    PMADDR = 0;
    //pull SEML low
    PORTEbits.RE3 = 0;
    
    //Write a one
    while(PMMODEbits.BUSY == 1);
    PMDIN1 = 1;
    while(PMMODEbits.BUSY == 1);
    
    //Set SEMR
    PORTEbits.RE3 = 1;
            
    return true;
}

uint8_t dsPIC33_REN70V05_RD(uint16_t address_70V05)
{  
    // /CS1
    PORTBbits.RB5 = 0;

    PMADDR = address_70V05;
    
    //dummy read
    mdata_70V05 = PMDIN1;
    while(PMMODEbits.BUSY == 1);
   
    mdata_70V05 = PMDIN1;
    while(PMMODEbits.BUSY == 1);

    // /CS1
    PORTBbits.RB5 = 1;

    return mdata_70V05;
}

void ReleaseSRAM(void)
{
    int i;
    
    //Now we release the SRAM so the Peripherals can access it
    //pull SEMR low to access the flags
    //SEML
    PORTEbits.RE3 = 0;  
    
    //write 1s to flags to release
    for(i=0;i<8;i++)
    {
        PMADDR = i;
        
        PMDIN1 = 1;
        while(PMMODEbits.BUSY == 1);
    }
    
    //Set SEMR
    PORTEbits.RE3 = 1;

}

void dsPIC33_memtest_REN70V05(void)
{
    int a;
    int b;
    /////////////////////////////
    //SRAM write all zeros
    ////////////////////////////
    b = 0;
    for(a=0;a<1024;a++)
    {
        PMADDR = a;
        // /CS1 
        PORTBbits.RB5 = 0;

        mdata_70V05 = b;
        PMDIN1 = mdata_70V05;
        while(PMMODEbits.BUSY == 1);

        // /CS1
        PORTBbits.RB5 = 1;
    }
    /////////////////////////////
    
    //SRAM read and verify 
    for(a=0;a<1024;a++)
    {
        PMADDR = a;
        address_70V05 = a;
        mdata_70V05 = 0;
        // /CS1
        PORTBbits.RB5 = 0;

        //dummy read
        mdata_70V05 = PMDIN1;
        while(PMMODEbits.BUSY == 1);

        mdata_70V05 = PMDIN1;
        while(PMMODEbits.BUSY == 1);

        if(mdata_70V05 != b)
        {
            sram_test = 0;
            sram_test_data[a] = 0;
        }
        else
        {
            sram_test = 1;
            sram_test_data[a] = 1;
        }
        // /CS1
        PORTBbits.RB5 = 1;
    }

    return;
}
