/******************************************************************************
 * @file     main.c
 * @brief    Main program body
 * @version  V4.0.1
 * @date     30-July-2026
 *
 * @note
 * Copyright (C) 2022 Spintrol Electronic Technology (Shanghai) Co., Ltd.. All rights reserved.
 *
 * @attention
 * THIS SOFTWARE JUST PROVIDES CUSTOMERS WITH CODING INFORMATION REGARDING
 * THEIR PRODUCTS, WHICH AIMS AT SAVING TIME FOR THEM. SPINTROL SHALL NOT BE
 * LIABLE FOR THE USE OF THE SOFTWARE. SPINTROL DOES NOT GUARANTEE THE
 * CORRECTNESS OF THIS SOFTWARE AND RESERVES THE RIGHT TO MODIFY THE SOFTWARE
 * WITHOUT NOTIFICATION.
 *
 ******************************************************************************/

#include "common.h"
#include <stdio.h>



/* Jump address and Function pointer for Jumping */
uint32_t JumpAddress;
pFunction Jump_To_Application;





/******************************************************************************
 * @brief      Initialize the IAP: Configure UART and GPIOs
 *
 * @param[in]  none
 *
 * @return     none
 *
 ******************************************************************************/
void IAP_Init(void)
{
    volatile uint32_t dummy;

#if RS485_INTERFACE_ENABLED > 0
    /* Configure RS485 Tx/Rx control pin */
    GPIO_SetPinAsGPIO(RS485_CONTROL_PIN);

    GPIO_SetPinDir(RS485_CONTROL_PIN, GPIO_OUTPUT);

    /* RS485 Rx Enable */
    GPIO_WritePin(RS485_CONTROL_PIN, GPIO_LEVEL_HIGH);
#endif

    GPIO_SetPinChannel(GPIO_34, GPIO34_UART_TXD);
    GPIO_SetPinChannel(GPIO_35, GPIO35_UART_RXD);

    UART_Init(UART, 38400);

    /* Enable FIFO */
    UART_ClearTxFIFO(UART, UART_RXFIFO_1BYTE_OR_MORE, UART_TXFIFO_EMPTY);
    UART_ClearRxFIFO(UART, UART_RXFIFO_1BYTE_OR_MORE, UART_TXFIFO_EMPTY);
    UART_SetFIFOTriggerThreshold(UART, UART_RXFIFO_1BYTE_OR_MORE, UART_TXFIFO_EMPTY);

    /* Disable UART Interrupts */
    UART_DisableInt(UART);
    UART_DisableRxDataAvailableInt(UART);
    UART_DisableTxDataRequestInt(UART);

    /* Dummy read to clear status */
    dummy = UART->UARTIIR_UARTFCR.UARTIIR.all;
}




int main(void)
{
    uint8_t u8Key = 0;

    /* Set Flash timing parameters */
    FLASH_WALLOW();

#if defined(SPC1158)
    FLASH_SetTiming(100000000);
    FLASH_WDIS();
    CLOCK_InitWithRCO(CLOCK_HCLK_100MHZ);
#else
    FLASH_SetTiming(200000000);
    FLASH_WDIS();
    CLOCK_InitWithRCO(CLOCK_HCLK_200MHZ);
#endif

    /* Delay Init */
    Delay_Init();


    /* IAP Init */
    IAP_Init();


    while (1)
    {
#if RS485_INTERFACE_ENABLED > 0
        /* RS485 Tx Enable */
        GPIO_WritePin(RS485_CONTROL_PIN, GPIO_LEVEL_LOW);
#endif

        printf("\r\n================== Main Menu ============================\r\n\n");
        printf("  Download Image To the Chip Internal Flash ------------ 1\r\n\n");
        printf("  Upload Image From the Chip Internal Flash ------------ 2\r\n\n");
        printf("  Jump and Execute the Program ------------------------- 3\r\n\n");
        printf("==========================================================\r\n\n");

#if RS485_INTERFACE_ENABLED > 0
        /* RS485 Rx Enable */
        GPIO_WritePin(RS485_CONTROL_PIN, GPIO_LEVEL_HIGH);
#endif

        /* Get a key from the PC terminal */
        u8Key = GetKey();

        if (u8Key == '1')
        {
            /* Enable Flash controller register write access */
            FLASH_WALLOW();

            /* Download user application in the Flash */
            SerialDownload();

            /* Disable Flash controller register write access */
            FLASH_WDIS();
        }
        else if (u8Key == '2')
        {
            /* Upload user application from the Flash */
            SerialUpload();
        }
        else if (u8Key == '3')
        {
            /* Get Entry Address */
            JumpAddress = *(__IO uint32_t *)(APPLICATION_ADDR + 4);

            Jump_To_Application = (pFunction)(JumpAddress);

            /* Initialize user application's Stack Pointer */
            __set_MSP(*(__IO uint32_t *)APPLICATION_ADDR);


            /* Jump to user application */
            Jump_To_Application();
        }
        else
        {
#if RS485_INTERFACE_ENABLED > 0
            /* RS485 Tx Enable */
            GPIO_WritePin(RS485_CONTROL_PIN, GPIO_LEVEL_LOW);
#endif

            printf("Invalid Number %c ! ==> The number should be either 1, 2 or 3\r\n\n", u8Key);

#if RS485_INTERFACE_ENABLED > 0
            /* RS485 Rx Enable */
            GPIO_WritePin(RS485_CONTROL_PIN, GPIO_LEVEL_HIGH);
#endif
        }
    }
}

