#include "cs1237.h"

// GPIO操作宏
//#define SCLK_H()  gpio_bits_set(CS1237_GPIO_PORT, CS1237_SCLK_PIN)
//#define SCLK_L()  gpio_bits_reset(CS1237_GPIO_PORT, CS1237_SCLK_PIN)
//#define DOUT_READ()  gpio_input_data_bit_read(CS1237_GPIO_PORT, CS1237_DOUT_PIN)



//Data   PC2  //Data被配置为开漏模式，需要外部硬件上拉。OK
//CLK    PC1  //推挽
//#define  GPIO_CLK_ENABLE()              do{ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE); }while(0)
#define  CS1237_Data_PORT GPIOB
#define  CS1237_Data_PIN  GPIO_PINS_14
#define  CS1237_Data_PIN_STATE()        gpio_input_data_bit_read(CS1237_Data_PORT,CS1237_Data_PIN)

#define  CS1237_CLK_PORT  GPIOB
#define  CS1237_CLK_PIN   GPIO_PINS_15
//*************************************************************************************************************
#define  delay_us wk_delay_us
#define  GPIO_SetBits     gpio_bits_set
#define  GPIO_ResetBits   gpio_bits_reset


static void CS1237_Data_HIGH(void)
{
    GPIO_SetBits(CS1237_Data_PORT, CS1237_Data_PIN);
}

static void CS1237_Data_LOW(void)
{
    GPIO_ResetBits(CS1237_Data_PORT, CS1237_Data_PIN);
}

////
static void CS1237_SCLK_HIHG(void)
{
    GPIO_SetBits(CS1237_CLK_PORT, CS1237_CLK_PIN);
}

static void CS1237_SCLK_LOW(void)
{
    GPIO_ResetBits(CS1237_CLK_PORT, CS1237_CLK_PIN);
}

//*************************************************************************************************************

//初始化ADC相关参数
uint8_t Init_CS1237(void)
{
    Config_CS1237();
    C1237_WriteReg(CS_CON);

    if (CS1237_ReadReg() != CS_CON) //如果读取的ADC配置出错，则错误处理
    {
         return 0;
    }

    return 1;
}

//单位：mV  电压采集
//输入信号: (+0.5Vref/Gain)/(2的23次方 -1 )   理想输出: 000001H
double Volt_CS1237(void)
{
    uint8_t i = 0;
    uint32_t getValue, oldValue = 0;
    double Volt = 0.0;
    float alpha = 0.0001f;

    getValue =  C1237_ReadResult();

    for (i = 0; i < 10; i++)
    {
        getValue =  C1237_ReadResult();

        if (i == 0)
        {
            oldValue = getValue;
        }
        else  //一阶低通滤波
        {
            getValue = (uint32_t)(getValue * alpha + oldValue * (1 - alpha));
            oldValue = getValue;
        }
    }

    Volt = ((double)((complement_to_decimal(getValue)/ 8388607.0)) * (3.3f * 0.5 / 1.0) * 1000.0);
    // 5.0为Vref;   1.0是PGA=1;   *1000是转换为mV;  (自行更改)
    //complement_to_decimal(getValue)是得到的ADC值;     8388607.0 为0X7FFFFF,一定要带小数点;   0.5是固定的;

    return Volt;
}

//24位补码 转换为 有符号数
static int32_t complement_to_decimal(uint32_t adc_data)
{
    int32_t decimal = 0;

    if ((adc_data & 0x800000) == 0)
    {
        //正数或零,直接返回
        decimal = adc_data & 0xFFFFFF;
    }
    else
    {
        int32_t original = ((~adc_data) & 0xFFFFFF) + 1;//取反＋1  //一定要先取反, 再& 0xFFFFFF
        //返回负数
        decimal = -original;
    }

    return decimal;
}

//*************************************************************************************************************

static void C1237_OneClk(void)
{
    CS1237_SCLK_HIHG();
    delay_us(CLK_TIME);
    CS1237_SCLK_LOW();
    delay_us(CLK_TIME);
}

static void Config_CS1237(void)
{
    gpio_init_type gpio_init_struct;
    gpio_default_para_init(&gpio_init_struct);
    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;
    gpio_init_struct.gpio_out_type = GPIO_OUTPUT_OPEN_DRAIN;
    gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
    gpio_init_struct.gpio_pins = GPIO_PINS_14;
    gpio_init_struct.gpio_pull = GPIO_PULL_UP;
    gpio_init(GPIOB, &gpio_init_struct);

    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;
    gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
    gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
    gpio_init_struct.gpio_pins = GPIO_PINS_15;
    gpio_init_struct.gpio_pull = GPIO_PULL_UP;
    gpio_init(GPIOB, &gpio_init_struct);

    CS1237_SCLK_LOW();
    CS1237_Data_HIGH();
}

uint8_t CS1237_ReadReg(void)
{
    uint8_t i = 0;
    uint8_t tem = 0;

    CS1237_SCLK_LOW();
    delay_us(50);//Wakeup MCU
    CS1237_Data_HIGH(); //输入模式

    while (CS1237_Data_PIN_STATE()) {}; //需要实际工程使用需要加入超时

    for (i = 0; i < 26; i++) // 1-26th CLK
        C1237_OneClk();

    CS1237_Data_HIGH();//Force High
    C1237_OneClk(); //27th CLK
    CS1237_Data_HIGH();//cs1237 direction input
    C1237_OneClk(); //28th CLK
    C1237_OneClk(); //29th CLK
    //
    tem = 0xAC; // PIN out  //读命令(0x56)左移1位

    for (i = 0; i < 7; i++) // 30~36th CLK
    {
        if (tem & 0x80)
            CS1237_Data_HIGH();
        else
            CS1237_Data_LOW();

        tem <<= 1;
        C1237_OneClk();
    }

    CS1237_Data_HIGH(); // cs1237 change to output direction
    C1237_OneClk(); // 37th CLK

    for (i = 0; i < 8; i++) // 38~45th CLK
    {
        tem <<= 1;
        C1237_OneClk();

        if (CS1237_Data_PIN_STATE())
            tem++;
    }

    CS1237_Data_HIGH();
    C1237_OneClk();// 46th CLK

    return tem;
}

void C1237_WriteReg(uint8_t mData)
{
    uint8_t i = 0;
    uint8_t tem = 0;

    CS1237_SCLK_LOW();
    delay_us(50);//Wakeup MCU
    CS1237_Data_HIGH();

    while (CS1237_Data_PIN_STATE()) {}; //需要实际工程使用需要加入超时

    for (i = 0; i < 26; i++) // 1~26th CLK
        C1237_OneClk();

    CS1237_Data_HIGH();//置高
    C1237_OneClk();// 27th CLK
    CS1237_Data_HIGH();//输入模式
    C1237_OneClk(); // 28th CLK
    C1237_OneClk(); // 29th CLK
    tem = 0xCA;//写命令(0x65)左移1位

    for (i = 0; i < 7; i++) // 30~36th CLK
    {
        if (tem & 0x80)
            CS1237_Data_HIGH();
        else
            CS1237_Data_LOW();

        tem <<= 1;
        C1237_OneClk();
    }

    CS1237_Data_HIGH();       // direction chage to intput direction
    C1237_OneClk();           // 37th CLK

    for (i = 0; i < 8; i++)   // 38~45th CLK
    {
        if (mData & 0x80)
            CS1237_Data_HIGH();
        else
            CS1237_Data_LOW();

        mData <<= 1;
        C1237_OneClk();
    }

    CS1237_Data_HIGH();
    C1237_OneClk(); // 46th CLK
}

uint32_t C1237_ReadResult(void)
{
    uint8_t i;
    uint32_t rdata = 0;

    CS1237_SCLK_LOW();
    delay_us(50);//Wakeup MCU
    CS1237_Data_HIGH();

    while (CS1237_Data_PIN_STATE()) {}; //waite ADC finish

    for (i = 0; i < 24; i++)
    {
        rdata <<= 1;
        C1237_OneClk();

        if (CS1237_Data_PIN_STATE()) // read data
            rdata++;
    }

    C1237_OneClk();
    C1237_OneClk();
    C1237_OneClk();
    return rdata;
}








