#include "ds1302.h"
#include "main.h"

extern int ds1302_port(void);

struct ds1302 ds1302;
int ds1302_port(void)
{
    ds1302_init(&ds1302
                , EN_1302_GPIO_Port, SCLK_1302_GPIO_Port, DA_1302_GPIO_Port
                , EN_1302_Pin, SCLK_1302_Pin, DA_1302_Pin
                );
    return 0;

}

void ds1302_delay_us(int us,uint32_t system_clock_mhz)
{
    volatile uint32_t con=us*system_clock_mhz/8;
    do{
        __NOP();
    }while(con--);
}
struct ds1302* ds1302_init(struct ds1302 *ds1302,GPIO_TypeDef *gpio_ce,GPIO_TypeDef *gpio_sclk,GPIO_TypeDef *gpio_io,uint16_t pin_ce,uint16_t pin_sclk,uint16_t pin_io)
{
    if(ds1302==NULL || gpio_ce==NULL || gpio_io==NULL || gpio_sclk==NULL){
        return NULL;
    }
    ds1302->gpio_ce=gpio_ce;
    ds1302->gpio_io=gpio_io;
    ds1302->gpio_sclk=gpio_sclk;
    ds1302->pin_ce=pin_ce;
    ds1302->pin_io=pin_io;
    ds1302->pin_sclk=pin_sclk;
    return ds1302;
}
int ds1302_write_bytes(struct ds1302 *ds1302,uint8_t cmd,uint8_t addr,const uint8_t *bytes,uint8_t num)
{
    int i,j;
    uint8_t tmp;
    if(ds1302==NULL || bytes==NULL || num==0){
        return -1;
    }
    GPIO_WriteBit(ds1302->gpio_ce,ds1302->pin_ce,Bit_SET);
    tmp=cmd|addr<<1|DS1302_CMD_WRITE_MASK;
    for(j=0;j<8;j++){
        GPIO_WriteBit(ds1302->gpio_io,ds1302->pin_io,tmp&1);
        ds1302_delay_us(1,168);
        GPIO_WriteBit(ds1302->gpio_sclk,ds1302->pin_sclk,Bit_SET);
        ds1302_delay_us(1,168);
        tmp>>=1;
        GPIO_WriteBit(ds1302->gpio_sclk,ds1302->pin_sclk,Bit_RESET);
    }
    for(i=0;i<num;i++){
        tmp=bytes[i];
        for(j=0;j<8;j++){
            GPIO_WriteBit(ds1302->gpio_io,ds1302->pin_io,tmp&1);
            ds1302_delay_us(1,168);
            GPIO_WriteBit(ds1302->gpio_sclk,ds1302->pin_sclk,Bit_SET);
            ds1302_delay_us(1,168);
            tmp>>=1;
            GPIO_WriteBit(ds1302->gpio_sclk,ds1302->pin_sclk,Bit_RESET);
        }
    }
    GPIO_WriteBit(ds1302->gpio_ce,ds1302->pin_ce,Bit_RESET);
    GPIO_WriteBit(ds1302->gpio_io,ds1302->pin_io,Bit_SET);
    return 0;
}
int ds1302_read_bytes(struct ds1302 *ds1302,uint8_t cmd,uint8_t addr,uint8_t *bytes, uint8_t num)
{
    int i,j;
    uint8_t tmp;
    if(ds1302==NULL || bytes==NULL || num==0){
        return -1;
    }
    GPIO_WriteBit(ds1302->gpio_ce,ds1302->pin_ce,Bit_SET);
    tmp=cmd|addr<<1|DS1302_CMD_READ_MASK;
    for(j=0;j<8;j++){
        GPIO_WriteBit(ds1302->gpio_io,ds1302->pin_io,tmp&1);
        ds1302_delay_us(1,168);
        GPIO_WriteBit(ds1302->gpio_sclk,ds1302->pin_sclk,Bit_SET);
        ds1302_delay_us(1,168);
        tmp>>=1;
        GPIO_WriteBit(ds1302->gpio_sclk,ds1302->pin_sclk,Bit_RESET);
    }
    GPIO_WriteBit(ds1302->gpio_io,ds1302->pin_io,Bit_SET);
    for(i=0;i<num;i++){
        tmp=0;
        for(j=0;j<8;j++){
            ds1302_delay_us(1,168);
            tmp|=GPIO_ReadInputDataBit(ds1302->gpio_io,ds1302->pin_io)<<j;
            GPIO_WriteBit(ds1302->gpio_sclk,ds1302->pin_sclk,Bit_SET);
            ds1302_delay_us(1,168);
            GPIO_WriteBit(ds1302->gpio_sclk,ds1302->pin_sclk,Bit_RESET);
        }
        bytes[i]=tmp;
    }
    GPIO_WriteBit(ds1302->gpio_ce,ds1302->pin_ce,Bit_RESET);
    GPIO_WriteBit(ds1302->gpio_io,ds1302->pin_io,Bit_SET);
    return 0;
}
int ds1302_write_enable(struct ds1302 *ds1302)
{
    uint8_t data=0x00;
    return ds1302_write_bytes(ds1302,DS1302_CMD_MASK|DS1302_CMD_REG_MASK,DS1302_REG_ADDR_CONTROL,&data,1);
}
int ds1302_write_disable(struct ds1302 *ds1302)
{
    uint8_t data=0x80;
    return ds1302_write_bytes(ds1302,DS1302_CMD_MASK|DS1302_CMD_REG_MASK,DS1302_REG_ADDR_CONTROL,&data,1);
}
uint64_t ds1302_get_time_s(struct ds1302 *ds1302)
{
    uint8_t time_bcd[8];
    struct time_clock_date date;
    if(ds1302_read_bytes(ds1302,DS1302_CMD_MASK|DS1302_CMD_REG_MASK,DS1302_REG_ADDR_ALL,time_bcd,8)!=0){
        return 0;
    }
    if((time_bcd[DS1302_REG_ADDR_SECONDS]&DS1302_REG_SECONDS_CH_MASK)!=0){
        return 0;
    }
    date.sec=(time_bcd[DS1302_REG_ADDR_SECONDS]>>4)*10+(time_bcd[DS1302_REG_ADDR_SECONDS]&0x0f);
    date.min=(time_bcd[DS1302_REG_ADDR_MINUTES]>>4)*10+(time_bcd[DS1302_REG_ADDR_MINUTES]&0x0f);
    if((time_bcd[DS1302_REG_ADDR_HOUR]&DS1302_REG_HOUR_12_N24_MASK)!=0){
        date.hour=((time_bcd[DS1302_REG_ADDR_HOUR]>>4)&1)*10+(time_bcd[DS1302_REG_ADDR_HOUR]&0x0f);
        if(date.hour==12){
            date.hour-=12;
        }
        date.hour+=((time_bcd[DS1302_REG_ADDR_HOUR]>>5)&1)*12;
    }
    else{
        date.hour=(time_bcd[DS1302_REG_ADDR_HOUR]>>4)*10+(time_bcd[DS1302_REG_ADDR_HOUR]&0x0f);
    }
    date.mday=(time_bcd[DS1302_REG_ADDR_DATE]>>4)*10+(time_bcd[DS1302_REG_ADDR_DATE]&0x0f);
    date.mon=(time_bcd[DS1302_REG_ADDR_MONTH]>>4)*10+(time_bcd[DS1302_REG_ADDR_MONTH]&0x0f);
    date.wday=0;
    date.year=(time_bcd[DS1302_REG_ADDR_YEAR]>>4)*10+(time_bcd[DS1302_REG_ADDR_YEAR]&0x0f)+2000;
    return time_clock_date_to_time(&date,8);
}
int ds1302_set_time_s(struct ds1302 *ds1302,uint64_t time_s)
{
    int ret;
    uint8_t time_bcd[8];
    struct time_clock_date date;
    if((ret=ds1302_write_enable(ds1302))!=0){
        return ret;
    }
    time_clock_time_to_date(time_s,&date,8);
    time_bcd[DS1302_REG_ADDR_SECONDS]=((date.sec/10)<<4)+(date.sec%10);
    time_bcd[DS1302_REG_ADDR_MINUTES]=((date.min/10)<<4)+(date.min%10);
    time_bcd[DS1302_REG_ADDR_HOUR]=((date.hour/10)<<4)+(date.hour%10);
    time_bcd[DS1302_REG_ADDR_DATE]=((date.mday/10)<<4)+(date.mday%10);
    time_bcd[DS1302_REG_ADDR_MONTH]=((date.mon/10)<<4)+(date.mon%10);
    time_bcd[DS1302_REG_ADDR_DAY]=((date.wday/10)<<4)+(date.wday%10)+1;
    time_bcd[DS1302_REG_ADDR_YEAR]=(((date.year-2000)/10)<<4)+((date.year-2000)%10);
    time_bcd[DS1302_REG_ADDR_CONTROL]=0x80;
    ret=ds1302_write_bytes(ds1302,DS1302_CMD_MASK|DS1302_CMD_REG_MASK,DS1302_REG_ADDR_ALL,time_bcd,8);
    ds1302_write_disable(ds1302);
    return ret;
}
int ds1302_read_ram(struct ds1302 *ds1302,uint8_t addr,uint8_t *bytes,uint8_t num)
{
    return ds1302_read_bytes(ds1302,DS1302_CMD_MASK|DS1302_CMD_RAM_MASK,addr,bytes,num);
}
int ds1302_write_ram(struct ds1302 *ds1302,uint8_t addr,uint8_t *bytes,uint8_t num)
{
    int ret;
    if((ret=ds1302_write_enable(ds1302))!=0){
        return ret;
    }
    ret=ds1302_write_bytes(ds1302,DS1302_CMD_MASK|DS1302_CMD_RAM_MASK,addr,bytes,num);
    ds1302_write_disable(ds1302);
    return ret;
}
int ds1302_set_charger(struct ds1302 *ds1302,enum ds1302_trickle_charger_tcs tcs,enum ds1302_trickle_charger_ds ds,enum ds1302_trickle_charger_rs rs)
{
    int ret;
	uint8_t data=tcs|ds|rs;
    if((ret=ds1302_write_enable(ds1302))!=0){
        return ret;
    }
    ret=ds1302_write_bytes(ds1302,DS1302_CMD_MASK|DS1302_CMD_REG_MASK,DS1302_REG_ADDR_TRICKLE_CHARGER,&data,1);
    ds1302_write_disable(ds1302);
    return ret;
}


/*
    uint8_t time_bcd[8] ={0};
    log_i( "before :  %d %d %d %d %d %d %d %d " ,
          time_bcd[0] ,time_bcd[1] ,time_bcd[2] ,time_bcd[3],time_bcd[4] ,time_bcd[5] ,time_bcd[6] ,time_bcd[7]);
     int a = ds1302_read_bytes(&ds1302,DS1302_CMD_MASK|DS1302_CMD_REG_MASK,DS1302_REG_ADDR_ALL,time_bcd,8);
    // ds1302->time_base 保存了 时间戳 秒数  毫秒数
    if(a!=0){
        log_i("read error %d", a);
    }else{
        log_i("read ok");

    }
    //  修改  ds1302 时间
    a = ds1302_set_time_s(&ds1302,1669961325);
    log_i("a  = %d", a);

    uint8_t tmp;
    a = ds1302_read_ram(&ds1302,0x00,&tmp,1);
    log_i("ds1302_read_ram  = %d %d", a, tmp);

    log_i( "readout :  %d %d %d %d %d %d %d %d " ,
          time_bcd[0] ,time_bcd[1] ,time_bcd[2] ,time_bcd[3],time_bcd[4] ,time_bcd[5] ,time_bcd[6] ,time_bcd[7]);

*/