/*
 * emif_init.c
 *
 *  Created on: 20 нояб. 2023 г.
 *      Author: seklyuts
 */

#include "f28x_project.h"

#ifdef CPU1

#define TEST_PASS            0xABCDABCD
#define TEST_FAIL            0xDEADDEAD
#define ASRAM_CS2_START_ADDR 0x100000
#define ASRAM_CS3_START_ADDR 0x300000
#define ASRAM_CS2_SIZE       0x1

#define EMIF1                0
#define EMIF2                1
#define MEM_D_WIDTH          1            // 16Bit Memory Interface
#define TURN_AROUND_TIME     0            // Turn Around time of 2 Emif Clock
#define RD_SETUP_TIME        0            // Read Setup time of 1 Emif Clock
#define RD_STROBE_TIME       3            // Read Strobe time of 4 Emif Clock
#define RD_HOLD_TIME         0            // Read Hold time of 1 Emif Clock
#define WR_SETUP_TIME        0            // Write Hold time of 1 Emif Clock
#define WR_STROBE_TIME       0            // Write Setup time of 1 Emif Clock
#define WR_HOLD_TIME         0            // Write Hold time of 1 Emif Clock
#define EXTEND_WAIT          0            // Disable Extended Wait
#define STROBE_SEL           0            // Disable Strobe Mode.
#define WAIT_POLAR_INV       0
#define WAIT_COUNT           0

//
// Globals
//
Uint16  ErrCount = 0;
Uint32  TEST_STATUS;
int i;


//
// Function Prototypes
//
//extern void setup_emif1_pinmux_async_16bit(Uint16);


//#define DEBUG_BOARD

#ifdef    DEBUG_BOARD

void flash_gpio_debug_board(Uint32 addr, Uint16 data)
{
    EALLOW;
    GpioDataRegs.GPADAT.bit.GPIO17 = (addr>>4) & 1;
    GpioDataRegs.GPADAT.bit.GPIO17 = (addr>>4) & 1;
    GpioDataRegs.GPADAT.bit.GPIO17 = (addr>>4) & 1;
    asm (" NOP");
    asm (" NOP");
    GpioDataRegs.GPADAT.bit.GPIO18 = (addr>>6) & 1;
    GpioDataRegs.GPADAT.bit.GPIO18 = (addr>>6) & 1;
    GpioDataRegs.GPADAT.bit.GPIO18 = (addr>>6) & 1;
    asm (" NOP");
    asm (" NOP");
    GpioDataRegs.GPADAT.bit.GPIO19 = (addr>>7) & 1;
    GpioDataRegs.GPADAT.bit.GPIO19 = (addr>>7) & 1;
    GpioDataRegs.GPADAT.bit.GPIO19 = (addr>>7) & 1;
    asm (" NOP");
    asm (" NOP");
    GpioDataRegs.GPADAT.bit.GPIO16 = (data>>9) & 1;
    GpioDataRegs.GPADAT.bit.GPIO16 = (data>>9) & 1;
    GpioDataRegs.GPADAT.bit.GPIO16 = (data>>9) & 1;
    EDIS;
}
#endif




void emif1_gpio_init_pinmux_async_16bit(Uint16 cpu_sel)
{
    Uint16 i;

//Addr

    for (i=38; i<=41; i++)
    {
            GPIO_SetupPinMux(i,cpu_sel,2);//A0 - A3
    }

    GPIO_SetupPinMux(45,cpu_sel,2);//A5

#ifdef    DEBUG_BOARD
    EALLOW;

    GpioCtrlRegs.GPAMUX2.bit.GPIO17 = 0;
    GpioCtrlRegs.GPAGMUX2.bit.GPIO17 = 0;
    GpioCtrlRegs.GPADIR.bit.GPIO17 = 1;
    GpioDataRegs.GPADAT.bit.GPIO17 = 0;

    GpioCtrlRegs.GPAMUX2.bit.GPIO18 = 0;
    GpioCtrlRegs.GPAGMUX2.bit.GPIO18 = 0;
    GpioCtrlRegs.GPADIR.bit.GPIO18 = 1;
    GpioDataRegs.GPADAT.bit.GPIO18 = 0;

    GpioCtrlRegs.GPAMUX2.bit.GPIO19 = 0;
    GpioCtrlRegs.GPAGMUX2.bit.GPIO19 = 0;
    GpioCtrlRegs.GPADIR.bit.GPIO19 = 1;
    GpioDataRegs.GPADAT.bit.GPIO19 = 0;
    EDIS;

#else
    GPIO_SetupPinMux(44,cpu_sel,2);//A4
    GPIO_SetupPinMux(46,cpu_sel,2);//A6
    GPIO_SetupPinMux(47,cpu_sel,2);//A7
#endif

    for (i=48; i<=52; i++)
    {
            GPIO_SetupPinMux(i,cpu_sel,2);//A8 - A12
    }

    for (i=86; i<=92; i++) //86 to 92
    {
        {
            GPIO_SetupPinMux(i,cpu_sel,2);//A13 - A19
        }
    }

//Data
    for (i=69; i<=74; i++) //69 to 82
    {
        {
            GPIO_SetupPinMux(i,cpu_sel,2);//D10 - D15
        }
    }

#ifdef    DEBUG_BOARD

    EALLOW;
    GpioCtrlRegs.GPAMUX2.bit.GPIO16 = 0;
    GpioCtrlRegs.GPAGMUX2.bit.GPIO16 = 0;
    GpioCtrlRegs.GPADIR.bit.GPIO16 = 1;
    GpioDataRegs.GPADAT.bit.GPIO16 = 0;
    EDIS;
#else
    GPIO_SetupPinMux(75,cpu_sel,2);//D9
#endif

    for (i=76; i<=82; i++) //69 to 82
    {
        {
            GPIO_SetupPinMux(i,cpu_sel,2);//D2 - D8
        }
    }
    GPIO_SetupPinMux(55,cpu_sel,9);//D0
    GPIO_SetupPinMux(56,cpu_sel,9);//D1

//Cntrl

    GPIO_SetupPinMux(26,cpu_sel,0);//RST
    GPIO_SetupPinMux(27,cpu_sel,0);//BYTE

    EALLOW;
    GpioCtrlRegs.GPADIR.bit.GPIO26 = 1;
    GpioDataRegs.GPADAT.bit.GPIO26 = 1;

    GpioCtrlRegs.GPADIR.bit.GPIO27 = 1;
    GpioDataRegs.GPADAT.bit.GPIO27 = 1;//word mode
    EDIS;
    GPIO_SetupPinMux(29,cpu_sel,9);//CS3
    GPIO_SetupPinMux(31,cpu_sel,2);//WEN
    GPIO_SetupPinMux(36,cpu_sel,2);//WAIT
    GPIO_SetupPinMux(37,cpu_sel,2);//OEn

    //
    // setup async mode and enable pull-ups for Data pins
    //
    for (i=69; i<=82; i++)
    {
            GPIO_SetupPinOptions(i,0,0x31); // GPIO_ASYNC||GPIO_PULLUP
    }
    GPIO_SetupPinOptions(55,0,0x31); // GPIO_ASYNC||GPIO_PULLUP
    GPIO_SetupPinOptions(56,0,0x31); // GPIO_ASYNC||GPIO_PULLUP
}

//
// mem_read_write - This function performs simple read/write word accesses
//                  to memory.
//
Uint32 ArrWriteAdr[3] = {0x555, 0x2AA, 0x555};
Uint16 ArrWriteData[3] = {0xAA, 0x55, 0xA0};

void MX29LV160D_emif_start_write_command(void)
{
    long *XMEM_ps;

#ifdef    DEBUG_BOARD
    flash_gpio_debug_board(ArrWriteAdr[0], ArrWriteData[0]);
#endif

    XMEM_ps = (long *)(ASRAM_CS3_START_ADDR & ArrWriteAdr[0]);
    *XMEM_ps = ArrWriteData[0];

#ifdef    DEBUG_BOARD
    flash_gpio_debug_board(ArrWriteAdr[1], ArrWriteData[1]);
#endif

    XMEM_ps = (long *)(ASRAM_CS3_START_ADDR & ArrWriteAdr[1]);
    *XMEM_ps = ArrWriteData[1];

#ifdef    DEBUG_BOARD
    flash_gpio_debug_board(ArrWriteAdr[2], ArrWriteData[2]);
#endif

    XMEM_ps = (long *)(ASRAM_CS3_START_ADDR & ArrWriteAdr[2]);
    *XMEM_ps = ArrWriteData[2];
}

Uint32 ArrEraseAdr[3] = {0x555, 0x2AA, 0x555};
Uint16 ArrEraseData[3] = {0xAA, 0x55, 0x80};

void MX29LV160D_emif_start_erase_command(void)
{
    long *XMEM_ps;

#ifdef    DEBUG_BOARD
    flash_gpio_debug_board(ArrEraseAdr[0], ArrEraseData[0]);
#endif

    XMEM_ps = (long *)(ASRAM_CS3_START_ADDR & ArrEraseAdr[0]);
    *XMEM_ps = ArrEraseData[0];

#ifdef    DEBUG_BOARD
    flash_gpio_debug_board(ArrEraseAdr[1], ArrEraseData[1]);
#endif

    XMEM_ps = (long *)(ASRAM_CS3_START_ADDR & ArrEraseAdr[1]);
    *XMEM_ps = ArrEraseData[1];

#ifdef    DEBUG_BOARD
    flash_gpio_debug_board(ArrEraseAdr[2], ArrEraseData[2]);
#endif

    XMEM_ps = (long *)(ASRAM_CS3_START_ADDR & ArrEraseAdr[2]);
    *XMEM_ps = ArrEraseData[2];

#ifdef    DEBUG_BOARD
    flash_gpio_debug_board(ArrEraseAdr[0], ArrEraseData[0]);
#endif

    XMEM_ps = (long *)(ASRAM_CS3_START_ADDR & ArrEraseAdr[0]);
    *XMEM_ps = ArrEraseData[0];

#ifdef    DEBUG_BOARD
    flash_gpio_debug_board(ArrEraseAdr[1], ArrEraseData[1]);
#endif

    XMEM_ps = (long *)(ASRAM_CS3_START_ADDR & ArrEraseAdr[1]);
    *XMEM_ps = ArrEraseData[1];
}




Uint16 data_polling_alg(Uint32 addr, Uint16 data_sharp)
{
    Uint16 data;
    long *XMEM_ps;

    XMEM_ps = (long *)(addr);

    do
    {
        data = *XMEM_ps & 0xFF;
        if( ((data>>7) & 1) != data_sharp) return 0;
    }
    while( ((data>>5) & 1) != 1);

    data = *XMEM_ps & 0xFF;

    if( ((data>>7) & 1) != data_sharp )  return 0;
    else return 1;
}

Uint16 toggle_bit_alg(Uint32 addr)
{
    Uint16 data[2];
    long *XMEM_ps;

    XMEM_ps = (long *)(addr);

    do
    {
        data[0] = *XMEM_ps & 0xFF;
        data[1] = *XMEM_ps & 0xFF;
        if( ((data[0]>>6) & 1) == ((data[0]>>6) & 1) ) return 0;
    }
    while( ((data[1]>>5) & 1) != 1);

    data[0] = *XMEM_ps & 0xFF;
    data[1] = *XMEM_ps & 0xFF;

    if( ((data[0]>>6) & 1) != ((data[0]>>6) & 1) )  return 0;
    else return 1;
}



uint16_t Arr1[ASRAM_CS2_SIZE], Arr2[ASRAM_CS2_SIZE];

char mem_read_write(Uint32 start_addr, Uint32 mem_size)
{
    volatile Uint16 mem_rds;
    volatile Uint16 mem_wds;
    volatile Uint16 Err;
    long *XMEM_ps;
//    Uint32 i;



    XMEM_ps = (long *)(start_addr+0x8000);

    Arr1[0] =  *XMEM_ps++;
    Arr1[1] =  *XMEM_ps++;
    Arr1[2] =  *XMEM_ps;

    //
    //Write data
    //
    MX29LV160D_emif_start_write_command();
    //
    //Fill memory
    //
    XMEM_ps = (long *)(start_addr+0x8000);
    mem_wds = 0x012;
//    for (i=0; i < mem_size; i++)
//    {
#ifdef    DEBUG_BOARD
        flash_gpio_debug_board((Uint32)XMEM_ps, mem_wds);
#endif
        *XMEM_ps = mem_wds;
//        if(i < ASRAM_CS2_SIZE) Arr1[i] = mem_wds & 0x0FF;
//        XMEM_ps ++;
//        mem_wds += 0x11;
//    }


//    do
//    {
        Err = toggle_bit_alg((Uint32)XMEM_ps);

    //
    //Verify memory
    //
        mem_wds = 0x012;
        XMEM_ps = (long *)(start_addr+0x8000);
//    for (i=0; i < mem_size; i++)
//    {
#ifdef    DEBUG_BOARD
        flash_gpio_debug_board((Uint32)XMEM_ps, mem_wds);
#endif
        mem_rds = *XMEM_ps;
//        if(i < ASRAM_CS2_SIZE) Arr2[i] = mem_rds & 0xFF;
//    }
//    while((mem_rds & 0xFF) != (mem_wds & 0xFF));

//        if( (mem_rds & 0xFF) != (mem_wds & 0xFF) )
//        {
//            Err++;
//        }



//        XMEM_ps++;
//        mem_wds += 0x11;
//    }
    return(0);
}

//
//  mem_data_walk - This function performs a walking 0 & 1 on data lines for
//                  SRAM RD & WR
//
char mem_data_walk(Uint32 start_addr, Uint32 mem_size)
{
    unsigned long sram_rd;
    unsigned long sram_wd;
    unsigned long i;
    int k;
    int m;
    unsigned long  *XM_p;
    unsigned long  *XMEM_p;

    XM_p = (unsigned long *)start_addr;

    for (i=0; i < mem_size; i=i+64)
    {
        for (m=0; m < 2; m++)
        {
            //
            //Write loop
            //
            XMEM_p = XM_p;
            sram_wd = 0x01;
            for (k=0; k < 32; k++)
            {
                if(m==0)
                {
                    *XMEM_p++ =  sram_wd;
                }
                else
                {
                    *XMEM_p++ = ~sram_wd;
                }
                sram_wd   = sram_wd<<1;
            }

            //
            //Read loop
            //
            XMEM_p = XM_p;
            sram_wd = 0x01;
            for (k=0; k < 32; k++)
            {
                sram_rd = *XMEM_p;
                if(m==1)
                {
                    sram_rd = ~sram_rd;
                }
                if(sram_rd != sram_wd)
                {
                    return(1);
                }
                XMEM_p++;
                sram_wd=sram_wd<<1;
            }
        }
        XM_p = XMEM_p;
    }
    return(0);
}

//
// mem_addr_walk - This function performs a toggle on each address bit.
//
char mem_addr_walk(Uint32 start_addr, Uint32 addr_size)
{
    unsigned long sram_rd;
    unsigned long sram_wd;
    unsigned int k;
    unsigned long xshift;
    unsigned long  *XM_p;
    unsigned long  *XMEM_p;

    XM_p = (unsigned long *)start_addr;

    //
    //Write loop
    //
    xshift = 0x00000001;
    sram_wd = 0x00;
    for (k=0; k < addr_size; k++)
    {
        XMEM_p = (unsigned long *)(start_addr + xshift);
        *XMEM_p = sram_wd++;
        xshift = xshift<<1;
    }

    //
    //Read loop
    //
    XMEM_p = XM_p;
    xshift = 0x00000001;
    sram_wd = 0x00;
    for (k=0; k < addr_size; k++)
    {
        XMEM_p = (unsigned long *)(start_addr + xshift);
        sram_rd = *XMEM_p;
       if(sram_rd != sram_wd)
       {
           return(1);
       }

       xshift = xshift<<1;
       sram_wd++;
    }
    return(0);
}

//
// mem_data_size - This function performs different data type
//                (HALFWORD/WORD) access.
//
char mem_data_size(Uint32 start_addr, Uint32 size_to_check)
{
    unsigned short mem_rds;
    unsigned long  mem_rdl;
    unsigned short mem_wds;
    unsigned long  mem_wdl;
    int i;

    short *XMEM_ps;
    long  *XMEM_pl;

    //
    //Write data short
    //
    XMEM_ps = (short *)start_addr;
    mem_wds = 0x0605;

    for (i=0; i < 2; i++)
    {
        *XMEM_ps++ = mem_wds;
        mem_wds += 0x0202;
    }

    //
    //Write data long
    //
    XMEM_pl = (long *)XMEM_ps;
    mem_wdl = 0x0C0B0A09;
    for (i=0; i < 2; i++)
    {
        *XMEM_pl++ = mem_wdl;
        mem_wdl += 0x04040404;
    }

    //
    //Read data short
    //
    XMEM_ps = (short *)start_addr;
    mem_wds = 0x0605;
    for (i=0; i < 6; i++)
    {
        mem_rds = *XMEM_ps;
        if( mem_rds != mem_wds)
        {
            return(1);
        }
        XMEM_ps++;
        mem_wds += 0x0202;
    }

    //
    //Read data long
    //
    XMEM_pl = (long *)start_addr;
    mem_wdl = 0x08070605;
    for (i=0; i < 3; i++)
    {
        mem_rdl = *XMEM_pl;
        if(mem_rdl != mem_wdl)
        {
            return(1);
        }
        XMEM_pl++;
        mem_wdl += 0x04040404;
    }
    return(0);
}

void emif_init(void)
{
    char ErrCount_local;
    //
    //Configure to run EMIF1 on full Rate (EMIF1CLK = CPU1SYSCLK)
    //
      EALLOW;
      ClkCfgRegs.PERCLKDIVSEL.bit.EMIF1CLKDIV = 0x0;
      EDIS;

      EALLOW;
    //
    // Grab EMIF1 For CPU1
    //
      Emif1ConfigRegs.EMIF1MSEL.all = 0x93A5CE71;
      if(Emif1ConfigRegs.EMIF1MSEL.all != 0x1)
      {
          ErrCount++;
      }

    //
    //Disable Access Protection (CPU_FETCH/CPU_WR/DMA_WR)
    //
      Emif1ConfigRegs.EMIF1ACCPROT0.all = 0x0;
      if(Emif1ConfigRegs.EMIF1ACCPROT0.all != 0x0)
      {
          ErrCount++;
      }

    //
    // Commit the configuration related to protection. Till this bit remains set
    // content of EMIF1ACCPROT0 register can't be changed.
    //
      Emif1ConfigRegs.EMIF1COMMIT.all = 0x1;
      if(Emif1ConfigRegs.EMIF1COMMIT.all != 0x1)
      {
         ErrCount++;
      }

    //
    // Lock the configuration so that EMIF1COMMIT register can't be
    // changed any more.
    //
      Emif1ConfigRegs.EMIF1LOCK.all = 0x1;
      if(Emif1ConfigRegs.EMIF1LOCK.all != 1)
      {
          ErrCount++;
      }

      EDIS;

    //
    //Configure GPIO pins for EMIF1
    //
      emif1_gpio_init_pinmux_async_16bit(0);

     Emif1Regs.ASYNC_WCCR.bit.WP0 = 0;

    //
    //Configure the access timing for CS3 space
    //
      Emif1Regs.ASYNC_CS3_CR.all =  (EMIF_ASYNC_ASIZE_16    | // 16Bit Memory
                                                              // Interface
                                     EMIF_ASYNC_TA_1        | // Turn Around time
                                                              // of 2 Emif Clock
                                     EMIF_ASYNC_RHOLD_1     | // Read Hold time
                                                              // of 1 Emif Clock
                                     EMIF_ASYNC_RSTROBE_4   | // Read Strobe time
                                                              // of 4 Emif Clock
                                     EMIF_ASYNC_RSETUP_1    | // Read Setup time
                                                              // of 1 Emif Clock
                                     EMIF_ASYNC_WHOLD_8     | // Write Hold time
                                                              // of 1 Emif Clock
                                     EMIF_ASYNC_WSTROBE_32   | // Write Strobe time
                                                              // of 1 Emif Clock
                                     EMIF_ASYNC_WSETUP_1    | // Write Setup time
                                                              // of 1 Emif Clock
                                     EMIF_ASYNC_EW_ENABLE  | // Extended Wait
                                                              // Enable.
                                     EMIF_ASYNC_SS_ENABLE    // Strobe Select Mode
                                                              // Enable.
                                    );

    //
    //Check basic RD/WR access to CS2 space
    //
      ErrCount_local = mem_read_write(ASRAM_CS3_START_ADDR, ASRAM_CS2_SIZE);
      ErrCount = ErrCount + ErrCount_local;

    //
    //Address walk checks (Tested for Memory with address width of 16bit)
    //
//      ErrCount_local = mem_addr_walk(ASRAM_CS3_START_ADDR, 16);
//      ErrCount = ErrCount + ErrCount_local;

    //
    //Data walk checks
    //
//      ErrCount_local = mem_data_walk(ASRAM_CS3_START_ADDR, ASRAM_CS2_SIZE);
//      ErrCount = ErrCount + ErrCount_local;

    //
    //Data size checks
    //
//      ErrCount_local = mem_data_size(ASRAM_CS3_START_ADDR, 4);
 //     ErrCount = ErrCount + ErrCount_local;

      if (ErrCount == 0x0)
      {
          TEST_STATUS = TEST_PASS;
      }
}

void emif_run(void)
{
    mem_read_write(ASRAM_CS3_START_ADDR, ASRAM_CS2_SIZE);

}
#endif
