/*********************************************************************
    FileName:     	Display.c
    Dependencies:	See #includes
    Processor:		PIC32MZ
    Hardware:		MainBrain32 rev 0.20
    Complier:  	    XC32 4.40, 4.45
    Author:         Larry Knight 2024

    Software License Agreement:
        This software is licensed under the Apache License Agreement

    Description:
        70V05 Dual Port RAM Driver Code
        Auto Semaphore version 

    References:

    File Description:

    Change History:

/***********************************************************************/

/*     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 "MainBrain.h"

#define SRAM_FAIL         0
#define SRAM_PASS         1

uint8_t mdata_70V05;
uint32_t address_70V05;
uint8_t flag = 0;

void REN70V05_Init(void)
{    
   //RA0 = /CS1
    TRISAbits.TRISA0 = 0;
    PORTAbits.RA0 = 1;
    
    //RG15 = /SEM
    TRISGbits.TRISG15 = 0;
    PORTGbits.RG15 = 1;
    
    //INT1 - INTR
    TRISEbits.TRISE8 = 1;
    
    //RB5 = M/S
    TRISBbits.TRISB5 = 0;    
    
    //Slave mode to disable the BUSY logic
    PORTBbits.RB5 = 0;
    
    //BUSY - BUSYR
    //Since we are in slave mode we must pull BUSY
    //high to allow writes to the port
    TRISEbits.TRISE9 = 0;
    PORTEbits.RE9 = 1;    
    
    //Set all the Flags
    for(PMWADDR=0;PMWADDR<8;PMWADDR++)
    {
        //SEM
        PORTGbits.RG15 = 0;

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

        //SEM
        PORTGbits.RG15 = 0;    
    }
    
    //verify the flags are 1
    for(PMWADDR=0;PMWADDR<8;PMWADDR++)
    {
        while(flag == 0)
        {
            //SEM
            PORTGbits.RG15 = 0;
            
            //dummy read
            while(PMMODEbits.BUSY == 1);
            flag = PMRDIN;

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

            //SEM
            PORTGbits.RG15 = 1;
        }
    }
}

int8_t REN70V05_RD(uint32_t address_70V05)
{        
    //get data
    PMRADDR = address_70V05;
    //CS1
    PORTAbits.RA0 = 0;    

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

    //CS1
    PORTAbits.RA0 = 1;    
    
    return mdata_70V05;
}

bool REN70V05_WR(uint32_t address_70V05, uint8_t mdata_70V05)
{    
    uint8_t flag;
    uint8_t sem_num = 0;
    
    PMWADDR = sem_num;
    
    //SEM
    PORTGbits.RG15 = 0;

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

    //SEM
    PORTGbits.RG15 = 1;

    //SEM
    PORTGbits.RG15 = 0;

    //dummy read
    while(PMMODEbits.BUSY == 1);
    flag = PMRDIN;
    while(PMMODEbits.BUSY == 1);
    
    while(PMMODEbits.BUSY == 1);
    flag = PMRDIN;
    while(PMMODEbits.BUSY == 1);
    
    //SEM
    PORTGbits.RG15 = 1;
 
    if(flag > 0)
    {
        //SEM
        PORTGbits.RG15 = 0;
        
        while(PMMODEbits.BUSY == 1);
        PMDOUT = 1;
        while(PMMODEbits.BUSY == 1);
        
        //SEM
        PORTGbits.RG15 = 1;

        return false;       
    }
    
    PMWADDR = address_70V05;
    
    //CS1
    PORTAbits.RA0 = 0;  
        
    while(PMMODEbits.BUSY == 1);
    PMDOUT = mdata_70V05;
    while(PMMODEbits.BUSY == 1);
        
    //CS1
    PORTAbits.RA0 = 1;    
    
    PMWADDR = sem_num;
    
    //SEM
    PORTGbits.RG15 = 0;
    
    while(PMMODEbits.BUSY == 1);
    PMDOUT = 1;
    while(PMMODEbits.BUSY == 1);
    
    //SEM
    PORTGbits.RG15 = 1;

    return true;
}

void ReleaseSRAM(void)
{
    int i;
    
    //Now we release the SRAM so the Peripherals can access it
    //pull SEMR low to access the flags
    PORTGbits.RG15 = 0;   
    
    //write 1s to flags to release
    for(i=0;i<8;i++)
    {
        PMWADDR = i;
        
        PMDOUT = 1;
        while(PMMODEbits.BUSY == 1);
    }
    
    PORTGbits.RG15 = 1;   
}


void REN70V05_RELEASE(void)

{
    //pull SEMR low to access the flags
    PORTGbits.RG15 = 0;

    //write a one to Flag    
    PMWADDR = 0;
    
    PMDOUT = 0x1;
    while(PMMODEbits.BUSY == 1);
    
    //SEM
    PORTGbits.RG15 = 1;
}

void REN70V05_LOCK(void)
{
    //pull SEMR low to access the flags
    PORTGbits.RG15 = 0;

    //write a zero to Flag    
    PMWADDR = 0;
    
    PMDOUT = 0x0;
    while(PMMODEbits.BUSY == 1);
    
    //SEM
    PORTGbits.RG15 = 1;
}

bool memtest_70V05(uint8_t test_data)
{  
    while(REN70V05_WR(0, test_data) == false);
    
    REN70V05_RD(0);
    
    if(mdata_70V05 != test_data)
    {
        return false;
    }
    else
    {
        return true;
    }
}

void SRAM_Semaphore_Test(void)
{
    //READ SEMAPHORE VALUE 
    uint8_t tp;
    
    //pull SEMR low to access the flags
    PORTGbits.RG15 = 0;

    //write a zero to Flag    
    PMWADDR = 0;
    PMDOUT = 0x0;
    while(PMMODEbits.BUSY == 1);

    ///SEM
    PORTGbits.RG15 = 1;

    //Flush PMDIN 
    PMRDIN = 0x55;
    while(PMMODEbits.BUSY == 1);

    ///SEM
    PORTGbits.RG15 = 0;

    //Read the result
    //Dummy read
    tp = PMRDIN;
    while(PMMODEbits.BUSY == 1);

    tp = PMRDIN;
    while(PMMODEbits.BUSY == 1);

    ///SEM
    PORTGbits.RG15 = 1;

    LED_Port(tp);
}

