#include "at32f403a_407.h"
#include "ms5192t.h"
#include "FreeRTOS.h"
#include "task.h"
#include "settings_api.h"
#include "io_utils.h"
#include "adc_transport.h"
#include "misc.h"
#include "utility.h"
#include <stdio.h>



//
void adc_gpio_init(void)
{
    gpio_init_type gpio_initstructure;
    spi_init_type spi_init_struct;
  
    crm_periph_clock_enable(CRM_IOMUX_PERIPH_CLOCK, TRUE);
    crm_periph_clock_enable(CRM_GPIOE_PERIPH_CLOCK, TRUE);
    
    gpio_pin_remap_config(SPI4_GMUX_0001, TRUE);
  
    // SCK
    gpio_initstructure.gpio_out_type       = GPIO_OUTPUT_PUSH_PULL;  
    gpio_initstructure.gpio_pull           = GPIO_PULL_DOWN;  
    gpio_initstructure.gpio_mode           = GPIO_MODE_MUX;  
    gpio_initstructure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
    gpio_initstructure.gpio_pins           = GPIO_PINS_11;
    gpio_init(GPIOE, &gpio_initstructure);
  
    // MISO
    gpio_initstructure.gpio_pull           = GPIO_PULL_UP;  
    gpio_initstructure.gpio_mode           = GPIO_MODE_INPUT;  
    gpio_initstructure.gpio_pins           = GPIO_PINS_13;
    gpio_init(GPIOE, &gpio_initstructure);
    
    // MOSI
    gpio_initstructure.gpio_pull           = GPIO_PULL_UP;  
    gpio_initstructure.gpio_mode           = GPIO_MODE_MUX; 
    gpio_initstructure.gpio_pins           = GPIO_PINS_14;
    gpio_init(GPIOE, &gpio_initstructure);
     
    // CS
    gpio_initstructure.gpio_out_type       = GPIO_OUTPUT_PUSH_PULL;  
    gpio_initstructure.gpio_pull           = GPIO_PULL_UP;  
    gpio_initstructure.gpio_mode           = GPIO_MODE_OUTPUT;  
    gpio_initstructure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
    gpio_initstructure.gpio_pins           = GPIO_PINS_12;
    gpio_init(GPIOE, &gpio_initstructure);
    
    
    MS5192T_CS_HIGH;

    crm_periph_clock_enable(CRM_SPI4_PERIPH_CLOCK, TRUE);
    
    spi_default_para_init(&spi_init_struct);
    spi_init_struct.transmission_mode = SPI_TRANSMIT_FULL_DUPLEX;
    spi_init_struct.master_slave_mode = SPI_MODE_MASTER;
    spi_init_struct.mclk_freq_division = SPI_MCLK_DIV_32; //SPI_MCLK_DIV_2;
    spi_init_struct.first_bit_transmission = SPI_FIRST_BIT_MSB;
    spi_init_struct.frame_bit_num = SPI_FRAME_8BIT;
    spi_init_struct.clock_polarity = SPI_CLOCK_POLARITY_HIGH;
    spi_init_struct.clock_phase = SPI_CLOCK_PHASE_2EDGE;
    spi_init_struct.cs_mode_selection = SPI_CS_SOFTWARE_MODE;
    
    spi_init(MS5192T_SPI, &spi_init_struct);
 
    //spi_hardware_cs_output_enable(SPI3, TRUE);
    
    spi_enable(MS5192T_SPI, TRUE);
}
 
    
//
flag_status adc_get_rdy(void)
{
    return gpio_input_data_bit_read(GPIOE, GPIO_PINS_13);
}



/***************************************************************************//**
 * @brief Initializes the SPI communication peripheral.
 *
 * @param lsbFirst - Transfer format (0 or 1).
 *                   Example: 0x0 - MSB first.
 *                            0x1 - LSB first.
 * @param clockFreq - SPI clock frequency (Hz).
 *                    Example: 1000 - SPI clock frequency is 1 kHz.
 * @param clockPol - SPI clock polarity (0 or 1).
 *                   Example: 0x0 - idle state for SPI clock is low.
 *	                          0x1 - idle state for SPI clock is high.
 * @param clockPha - SPI clock phase (0 or 1).
 *                   Example: 0x0 - data is latched on the leading edge of SPI
 *                                  clock and data changes on trailing edge.
 *                            0x1 - data is latched on the trailing edge of SPI
 *                                  clock and data changes on the leading edge.
 *
 * @return 0 - Initialization failed, 1 - Initialization succeeded.
*******************************************************************************/
unsigned char SPI_Init(unsigned char lsbFirst,
                       unsigned long clockFreq,
                       unsigned char clockPol,
                       unsigned char clockPha)
{
/*  
    ST7579_CS_PIN_OUT;
    ST7579_CS_HIGH;
    ADI_PART_CS_PIN_OUT;
    ADI_PART_CS_HIGH;
    R_CSI10_Start();
*/
    return(1);
}


/***************************************************************************//**
 * @brief Writes data to SPI.
 *
 * @param data - Write data buffer:
 *               - first byte is the chip select number;
 *               - from the second byte onwards are located data bytes to write.
 * @param bytesNumber - Number of bytes to write.
 *
 * @return Number of written bytes.
*******************************************************************************/
unsigned char SPI_Write(unsigned char* data, unsigned char bytesNumber)
{
    unsigned char chipSelect   = data[0];
    unsigned char writeData[4] = {0, 0, 0, 0};
    unsigned char readData[4]  = {0, 0, 0, 0};
    
    if (chipSelect == 1)
        MS5192T_CS_LOW;
    
    for (unsigned char byte = 0; byte < bytesNumber; byte++)
    {
        writeData[byte] = data[byte + 1];
    }
    
    for (int i = 0; i < bytesNumber; i++)
    {
        while (spi_i2s_flag_get(MS5192T_SPI, SPI_I2S_TDBE_FLAG) == RESET);
        MS5192T_SPI->dt = writeData[i];
  
        while (spi_i2s_flag_get(MS5192T_SPI, SPI_I2S_RDBF_FLAG) == RESET);
        readData[i] = MS5192T_SPI->dt;
    }  
    
    if (chipSelect == 1)
        MS5192T_CS_HIGH;
    
    return bytesNumber;
}


/***************************************************************************//**
 * @brief Reads data from SPI.
 *
 * @param data - As an input parameter, data represents the write buffer:
 *               - first byte is the chip select number;
 *               - from the second byte onwards are located data bytes to write.
 *               As an output parameter, data represents the read buffer:
 *               - from the first byte onwards are located the read data bytes. 
 * @param bytesNumber - Number of bytes to write.
 *
 * @return Number of written bytes.
*******************************************************************************/
unsigned char SPI_Read(unsigned char* data, unsigned char bytesNumber)
{
    unsigned char chipSelect   = data[0];
    unsigned char writeData[4] = {0, 0, 0, 0};
    unsigned char readData[4]  = {0, 0, 0, 0};
    unsigned char byte         = 0;
    
    for (byte = 0; byte < bytesNumber; byte++)
    {
        writeData[byte] = data[byte + 1];
        data[byte + 1] = 0;
    }
    
    if (chipSelect == 1)
        MS5192T_CS_LOW;
    
    for (byte = 0; byte < bytesNumber; byte++)
    {
        while (spi_i2s_flag_get(MS5192T_SPI, SPI_I2S_TDBE_FLAG) == RESET);
        MS5192T_SPI->dt = writeData[byte];
  
        while (spi_i2s_flag_get(MS5192T_SPI, SPI_I2S_RDBF_FLAG) == RESET);
        readData[byte] = MS5192T_SPI->dt;
    }
    
    if (chipSelect == 1)
        MS5192T_CS_HIGH;
    
    for (byte = 0; byte < bytesNumber; byte++)
    {
        data[byte] = readData[byte];
    }  
      
    return bytesNumber;  
}

// Базовая инициализацияч ADC MS5192
bool adc_init(void)
{
    uint8_t ret;
    
    adc_gpio_init();

    for (uint32_t i = 0; i < 20; i++) {
        MS5192T_Reset();
        ret = MS5192T_Init();
        printf("ADC init status: %s\r\n", ret == 1 ? "OK" : "FAILED");
        if (ret == 1)
            break;
        vTaskDelay(10);
    }
    return true;
}

#if 0
//
void adc_task(void *params)
{
    bool state = false;
    unsigned long value;
    uint8_t ret;
    
    vTaskDelay(1000);
    
    adc_gpio_init();
    
    for (uint32_t i = 0; i < 100; i++) {
        MS5192T_Reset();
        ret = MS5192T_Init();
        printf("ADC init status: %s\r\n", ret == 1 ? "OK" : "FAILED");
        if (ret == 1)
           break;
        vTaskDelay(10);
    }
        
    // Запрос регистра конфигурации для (0x710 - значение по умолчанию)
    value = MS5192T_GetRegisterValue(MS5192T_REG_CONF, 2, 1);
    printf("ADC cfg reg: 0x%X: ", value);
    print_binary_half_word((uint16_t)value);

    // Коэф-т усиления: 1
    printf("ADC. Set gain rate 1\r\n");
    MS5192T_SetGain(MS5192T_GAIN_1);
    value = MS5192T_GetRegisterValue(MS5192T_REG_CONF, 2, 1);
    printf("ADC cfg reg: 0x%X: ", value);
    print_binary_half_word((uint16_t)value);
    
    // Униполярный режим
    printf("Set unipolar input mode...\r\n");
    MS5192T_SetPolar(MS5192T_CONF_UNIPOLAR);
    value = MS5192T_GetRegisterValue(MS5192T_REG_CONF, 2, 1);
    printf("ADC cfg reg: 0x%X: ", value);
    print_binary_half_word((uint16_t)value);
    
    // Регистр статуса
    value = MS5192T_GetRegisterValue(MS5192T_REG_STAT, 1, 1);
    printf("ADC status reg: 0x%X: ", value);
    print_binary_byte((uint8_t)value);
    
    // Установка внутреннего опорного напряжения
    MS5192T_SetIntReference(MS5192T_REFSEL_INT); // select internal 1.17V reference
    value = MS5192T_GetRegisterValue(MS5192T_REG_CONF, 2, 1);
    printf("ADC cfg reg: 0x%X: ", value);
    print_binary_half_word((uint16_t)value);
      
    // Регистр режима (MODE register)
    value = MS5192T_GetRegisterValue(MS5192T_REG_MODE, 2, 1);
    printf("ADC mode reg: 0x%X: ", value);
    print_binary_half_word((uint16_t)value);
    
    // Установить update rate
    printf("Set update rate.\r\n");
    MS5192T_SetUpdateRate(MS5192T_UP_RATE_500);
    value = MS5192T_GetRegisterValue(MS5192T_REG_MODE, 2, 1);
    printf("ADC mode reg: 0x%X: ", value);
    print_binary_half_word((uint16_t)value);
    
    // Калибровка 
    
    // 1 - ый канал
    MS5192T_Calibrate(MS5192T_MODE_CAL_INT_ZERO, MS5192T_CH_AIN1P_AIN1M); 
    MS5192T_Calibrate(MS5192T_MODE_CAL_INT_FULL, MS5192T_CH_AIN1P_AIN1M); 
    
    // 2 - ой канал
    MS5192T_Calibrate(MS5192T_MODE_CAL_INT_ZERO, MS5192T_CH_AIN2P_AIN2M); 
    MS5192T_Calibrate(MS5192T_MODE_CAL_INT_FULL, MS5192T_CH_AIN2P_AIN2M); 
    
    MS5192T_SetChannel(MS5192T_CH_AIN1P_AIN1M);
        
    for (;;)
    {
        value = MS5192T_SingleConversion();
        //printf("ADC data raw: 0x%X, %f\r\n", value, (double)value*0.00001785305);
        printf("ADC data raw: 0x%X, %f\r\n", value, (double)value*0.00001785305/0.0961538);
        
        
        
#if 0      
        if (state == false) 
        {
            if (MS5192T_Init() == 1) 
            {
                vTaskDelay(2000);
                MS5192T_SetGain(MS5192T_GAIN_1);
                vTaskDelay(2000);
                MS5192T_SetIntReference(MS5192T_REFSEL_INT);    // select internal 1.17V reference
                vTaskDelay(2000);
                MS5192T_Calibrate(MS5192T_MODE_CAL_INT_ZERO, MS5192T_CH_AIN1P_AIN1M); // Internal Zero-Scale Calibration
                vTaskDelay(2000);
                value = MS5192T_ContinuousReadAvg(20);
                vTaskDelay(2000);
                state = true;
                vTaskDelay(100);
                continue;
            }
        }
        
        value = MS5192T_SingleConversion();
      
        if (value > 0x800000)
        {
            value -= 0x800000;
            value = ((value * 1170) >> 15);
        }
        else
        {
            value = 0x800000 - value;
            value = ((value * 1170) >> 15);
        }
        
        printf("Value: %u\r\n", value);
#endif        
        vTaskDelay(1000);
    }
}
#endif




