/********************************** (C) COPYRIGHT *******************************
 * File Name          : main.c
 * Author             : WCH
 * Version            : V1.0.0
 * Date               : 2023/12/25
 * Description        : Main program body.
 *********************************************************************************
 * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
 * Attention: This software (modified or not) and binary are used for 
 * microcontroller manufactured by Nanjing Qinheng Microelectronics.
 *******************************************************************************/
/*
 *@Note
 *IAP upgrade routine:
 *Support serial port for FLASH burning
 *
 *1. Use the IAP download tool to realize the download PC0 floating (default pull-up input)
 *2. After downloading the APP, connect PC0 to ground (low level input), and press the
 *reset button to run the APP program.
 *3. use WCH-LinkUtility.exe download to BOOT(adr-0x1FFFF000)
 *
 */

#include "debug.h"
#include "string.h"
#include "iap.h"

#define RSTSCKR_RMVF_Set           ((uint32_t)0x01000000)       // from ch32v00x_rcc.c

/*********************************************************************
 * @fn      IAP_2_APP
 *
 * @brief   IAP_2_APP program.
 *
 * @return  none
 */
void IAP_2_APP(void)
{
    RCC->RSTSCKR |= RSTSCKR_RMVF_Set;   // RCC_ClearFlag();

    SystemReset_StartMode(Start_Mode_USER);

    //TIM1->BDTR = 0;         // disable PWM outputs
    //TIM1->CCER = 0;         // disable PWM selects
    //TIM1->CHCTLR1 = 0;      // disable PWM mappings
    //TIM1->CTLR1 = 0;        // disable TIM1

    //RCC->APB2PCENR = 0;     // disable peripheral clocks

    NVIC_SystemReset();
}

static inline void bootloader_led_flash()
{
    uint32_t w;

    // configure bootloader LED pins
    GPIOA->BCR    = GPIO_Pin_2;            // LSENS_K
    GPIOD->BSHR   = GPIO_Pin_0;            // LSENS_A

    w = GPIOA->CFGLR & ~(0x0f << (4 * 2)); // clear PA2 config
    GPIOA->CFGLR = w | 0x0a << (4 * 2);    // and configure as AF_PP output

    w = GPIOD->CFGLR & ~(0x0f << (4 * 0)); // clear PD0 config
    GPIOD->CFGLR = w | 0x02 << (4 * 0);    // and configure as PP output

    TIM1->ATRLR   = 40 - 1;       // period
    TIM1->PSC     = 65535;        // prescaler
    TIM1->SWEVGR  = TIM_PSCReloadMode_Immediate;

    TIM1->CCER    = TIM_CC2NE;
    TIM1->CH2CVR  = 30;
    TIM1->CHCTLR1 = 0x60 << 8;  // output enabled, PWM mode 1

    TIM1->BDTR    = TIM_MOE;      // enable PWM outputs
    TIM1->CTLR1   = TIM_CKD_1 | TIM_ARPE | TIM_CEN;
}

/*********************************************************************
 * @fn      main
 *
 * @brief   Main program.
 *
 * @return  none
 */
int main(void)
{
    uint8_t w;

    RCC->APB2PCENR = RCC_APB2Periph_GPIOC;

    // configure GPIOC
    GPIOC->BCR     = GPIO_Pin_4;            // configure pull-down
    w = GPIOC->CFGLR & ~(0x0f << (4 * 4));  // clear PC4 config
    GPIOC->CFGLR = w | 0x08 << (4 * 4);     // configure PC4 as input with PU/PD

    // had some issues with spurious activation happening,
    // so spin a little bit. seems to help?
    while (TIM1->CNT) __asm("nop");

    // is button NOT pushed (active high)?
    if (!(GPIOC->INDR & GPIO_Pin_4)) {
        IAP_2_APP();
        while(1);
    }

    RCC->APB2PCENR = (RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC |
                      RCC_APB2Periph_GPIOD | RCC_APB2Periph_TIM1  |
                      RCC_APB2Periph_AFIO  | RCC_APB2Periph_USART1);

    bootloader_led_flash();
    USART1_CFG(115200);

    while(1) {
        if(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET) {
            UART_Rx_Deal();
        }
    }
}
