#include "drivers/mss_uart/mss_uart.h"
#include "drivers/CoreGPIO/core_gpio.h"
#include "stdint.h"

#define GPIO_LED  ((uint32_t *)0x510000A0)
#define LSRAM_mem  0x50000000

uint32_t addr,data,num;
void LSRAM_write();
void LSRAM_read();
void GPIOLED();
int printnumber(int n);
void    delay(int);

size_t UART_Polled_Rx
(
    mss_uart_instance_t * this_uart,
    uint8_t * rx_buff,
    size_t buff_size
);

int main()
{

        uint8_t rx_buff[1];
        /* Initialization all necessary hardware components */
        MSS_UART_init( &g_mss_uart1,MSS_UART_57600_BAUD,MSS_UART_DATA_8_BITS | MSS_UART_NO_PARITY | MSS_UART_ONE_STOP_BIT );
        MSS_UART_polled_tx(&g_mss_uart1,(uint8_t *)"\n Welcome to SmartFusion2 FIC Tutorial \n\r",sizeof("\n Welcome to SmartFusion2 FIC Tutorial \n\r"));
        while(1)
        {

            MSS_UART_polled_tx(&g_mss_uart1,(uint8_t *)"\n Please Select the Following option\n\r",sizeof("\n Please Select the Following option\n\r"));
            MSS_UART_polled_tx(&g_mss_uart1,(uint8_t *)"1. Writing to the  LSRAM \n\r",sizeof("1. Writing to the LSRAM \n\r"));
            MSS_UART_polled_tx(&g_mss_uart1,(uint8_t *)"2. Reading from the LSRAM \n\r",sizeof("2. Reading from the LSRAM \n\r"));
            MSS_UART_polled_tx(&g_mss_uart1,(uint8_t *)"3. GPIO Blinking LED's \n\r",sizeof("3. GPIO Blinking LED's \n\r"));


            while( (!(UART_Polled_Rx ( &g_mss_uart1, rx_buff, 1 ))) )
                ;

            if(rx_buff[0] == '1')
            {

                LSRAM_write();
            }
            else if(rx_buff[0] == '2')
            {

                LSRAM_Read();
            }

            else if(rx_buff[0] == '3')
            {

                GPIOLED();
            }

            else
            {
                MSS_UART_polled_tx(&g_mss_uart1,(uint8_t *)"Incorrect option\n\r",sizeof("Incorrect option"));
            }

        }

        return 0;
    }

/**************************************************************************/
/* Write                                                                */
/**************************************************************************/
void LSRAM_write()
    {

    MSS_UART_polled_tx_string( &g_mss_uart1,(const uint8_t*)"\n Enter the Offset address between 0 to 8188 to write and press Enter\n\r" );
    addr=scannumber();
    while(addr<0 || addr>8188)
        {
            MSS_UART_polled_tx_string( &g_mss_uart1,(const uint8_t*)"\n Enter the correct address and press Enter\n\r" );
            addr=scannumber();
        }
    MSS_UART_polled_tx_string( &g_mss_uart1,(const uint8_t*)"\n Enter the data to write and press Enter\n\r" );
    data=scannumber();

    *(uint32_t *)(addr + LSRAM_mem) =  data;

    }
/**************************************************************************/
/* Read                                                                  */
/**************************************************************************/
void LSRAM_Read()
    {

    MSS_UART_polled_tx_string( &g_mss_uart1,(const uint8_t*)"\n Enter the Offset address between 0 to 8188 to read and press Enter\n\r" );
    addr=scannumber();
    while(addr<0 || addr>8188)
        {
            MSS_UART_polled_tx_string( &g_mss_uart1,(const uint8_t*)"\n Enter the correct address and press Enter\n\r" );
            addr=scannumber();
        }
     data =  *(uint32_t *)(addr + LSRAM_mem);

    MSS_UART_polled_tx_string( &g_mss_uart1,(const uint8_t*)"\n Read Data:\n\r" );
        printnumber(data);

    }
/**************************************************************************/
/* GPIO LED's                                                                  */
/**************************************************************************/
void GPIOLED()
    {

    MSS_UART_polled_tx_string( &g_mss_uart1,(const uint8_t*)"\n Enter the number between 0 to 255 and press Enter \n\r" );
    num=scannumber();
    while(num<0 || num>255)
        {
            MSS_UART_polled_tx_string( &g_mss_uart1,(const uint8_t*)"\n Enter the correct number and press Enter\n\r" );
            num=scannumber();
        }
    *(GPIO_LED ) = (uint32_t *)num;
    }

int printnumber(int n)
    {
        char ret[100];
            int numChars = 0;
            int isNegative = 0;
            int temp;
            // Determine if integer is negative

            if (n < 0) {
                n = -n;
                isNegative = 1;
                numChars++;
            }
            // Count how much space we will need for the string
            temp = n;
            do {
                numChars++;
                temp /= 10;
            } while ( temp );
            ret[numChars] = 0;
            //Add the negative sign if needed
            if (isNegative) ret[0] = '-';
            // Copy digits to string in reverse order
            int i = numChars - 1;
            do {
                ret[i--] = n%10 + '0';
                n /= 10;
            } while (n);
            MSS_UART_polled_tx( &g_mss_uart1, (const uint8_t*)ret,numChars);
            MSS_UART_polled_tx( &g_mss_uart1, (const uint8_t*)"\r\n", 2 );
            return 0;
    }

//void delay(int n)
//{
//  while(n>0)
//    n--;
//}

size_t
UART_Polled_Rx
    (
        mss_uart_instance_t * this_uart,
        uint8_t * rx_buff,
        size_t buff_size
    )
    {
        size_t rx_size = 0U;

        while( rx_size < buff_size )
        {
           while ( ((this_uart->hw_reg->LSR) & 0x1) != 0U  )
           {
               rx_buff[rx_size] = this_uart->hw_reg->RBR;
               ++rx_size;
           }
        }

        return rx_size;
    }

int scannumber()
    {
        uint8_t rxbuff,x[8]={0},i=0;//[8];
        mss_uart_instance_t * this_uart = &g_mss_uart1;
        int num;
        while(i<8)
        {
        UART_Polled_Rx( &g_mss_uart1, &rxbuff, sizeof(rxbuff) );

        if(rxbuff == '\n')
                {
                    rxbuff= this_uart->hw_reg->RBR;
                    rxbuff= this_uart->hw_reg->RBR;
                    break;
                }
                else
                    x[i++]=rxbuff;
                }
        num = atoi(x);
        return num;
    }
