#include "rtc_thread.h"
#include "r_i2c_api.h"
#include "r_rtc_api.h"
#include <stdio.h>
#define SEMI_HOSTING
#define BQ32000__CAL_S          0x05
#ifdef SEMI_HOSTING
    #ifdef __GNUC__
    extern void initialise_monitor_handles(void);
    #endif
#endif
    void periodicIrqRate( );
#define BQ32000_CAL_CFG1        0x07
#define BQ32K_TCH2              0x08    /* Trickle charge enable */
#define BQ32K_CFG2              0x09    /* Trickle charger control */



#define BQ32K_SECONDS       0x00    /* Seconds register address */
#define BQ32K_SECONDS_MASK  0x7F    /* Mask over seconds value */
#define BQ32K_STOP      0x80    /* Oscillator Stop flat */

#define BQ32K_MINUTES       0x01    /* Minutes register address */
#define BQ32K_MINUTES_MASK  0x7F    /* Mask over minutes value */
#define BQ32K_OF        0x80    /* Oscillator Failure flag */

#define BQ32K_HOURS_MASK    0x3F    /* Mask over hours value */
#define BQ32K_CENT      0x40    /* Century flag */
#define BQ32K_CENT_EN       0x80    /* Century flag enable bit */

static const unsigned char rtc_days_in_month[] = {
    31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};

static inline bool is_leap_year(unsigned int year)
{
    return (!(year % 4) && (year % 100)) || !(year % 400);
}

#if 0
#define BQ32K_CENT_HOURS       0x02    /* CENT_HOURS register address */
#define BQ32K_DAY              0x03    /* DAY register address */
#define BQ32K_DATE             0x04    /* DATE register address */
#define BQ32K_MONTH            0x05    /* MONTH register address */
#define BQ32K_YEARS            0x06    /* YEARS register address */
#define BQ32K_CAL_CFG1         0x07    /* CENT_HOURS register address */
#define BQ32K_CFG2             0x08    /* CENT_HOURS register address */
#endif
struct bq32k_regs {
    uint8_t     seconds;
    uint8_t     minutes;
    uint8_t     cent_hours;
    uint8_t     day;
    uint8_t     date;
    uint8_t     month;
    uint8_t     years;
};

const i2c_master_instance_t g_i2c2;
void bq32kinitialize();
int bq32kRead(uint8_t reg, void *buf, uint8_t count );
int bq32kWrite(void *data, uint8_t off, uint8_t len);
int bq32kinit();
unsigned bcd2bin(unsigned char val);
unsigned char bin2bcd(unsigned val);
int rtc_valid_tm(struct tm *tm);
int rtc_month_days(unsigned int month, unsigned int year);
static int bq32k_rtc_set_time(struct tm *tm1);
static int bq32k_rtc_set_time(struct tm *tm1);
bool setIRQLevel(bool level);
bool setCalibration(int8_t value);

int bq32kRead(uint8_t reg, void *buf, uint8_t count )
{

  R_BSP_SoftwareDelay(100,BSP_DELAY_UNITS_MICROSECONDS);
  g_i2c2.p_api->write(g_i2c2.p_ctrl, &reg, 1 , true);

  R_BSP_SoftwareDelay(100,BSP_DELAY_UNITS_MICROSECONDS);
  g_i2c2.p_api->read(g_i2c2.p_ctrl, buf, count , false);
  return 0;




}

int bq32kWrite(void *data, uint8_t off, uint8_t len)
{
    uint8_t buffer[len + 1];

        buffer[0] = off;
        memcpy(&buffer[1], data, len);
    R_BSP_SoftwareDelay(100,BSP_DELAY_UNITS_MICROSECONDS);
  g_i2c2.p_api->write(g_i2c2.p_ctrl, buffer, (uint32_t)len+1 , false);
   return 0;

}

int bq32kinit()
{
    int error;
    uint8_t reg=0;
    unsigned char regbat;

#ifdef SEMI_HOSTING
#ifdef __GNUC__
    if (CoreDebug->DHCSR & CoreDebug_DHCSR_C_DEBUGEN_Msk)
    {
        initialise_monitor_handles();
    }
#endif
#endif

    error = bq32kRead(BQ32K_SECONDS,&reg, 1);

#ifdef SEMI_HOSTING
    if (CoreDebug->DHCSR & CoreDebug_DHCSR_C_DEBUGEN_Msk)
    {
        printf("reg: %d\t\t\r\n", reg);
        printf("\r\nCalendar Set_time\r\n");
        printf("error: %d\t\t\r\n", error);
    }
#endif

    /* Check Oscillator Stop flag */



    if (!error && (reg & BQ32K_STOP))
    {
        /*Oscillator was halted. Restarting...*/
            reg &= (uint8_t)~BQ32K_STOP;

            error = bq32kWrite(&reg, BQ32K_SECONDS, 1);
    }
    if (error)
            return error;
#ifdef SEMI_HOSTING
    if (CoreDebug->DHCSR & CoreDebug_DHCSR_C_DEBUGEN_Msk)
    {
        printf("reg: %d\t\t\r\n", reg);
        printf("error: %d\t\t\r\n", error);
    }
#endif


    /* Check Oscillator Failure flag */
    error = bq32kRead(BQ32K_MINUTES,&reg, 1);
    if (!error && (reg & BQ32K_OF))
    {
        /*Oscillator Failure. Check RTC battery*/
        reg &= (uint8_t)~BQ32K_OF;
        error = bq32kWrite(&reg, BQ32K_MINUTES, 1);
    }
        if (error)
                return error;
#ifdef SEMI_HOSTING
    if (CoreDebug->DHCSR & CoreDebug_DHCSR_C_DEBUGEN_Msk)
    {
        printf("error: %d\t\t\r\n", error);
    }
#endif


   /* regbat = 0x45; //This enables charging without the diode - we don't need no stinkin' diodes!
    error = bq32kWrite(&regbat, BQ32K_CFG2, 1);
    if (error)
            return error;
    regbat = 0x20;
    error = bq32kWrite(&regbat, BQ32K_TCH2, 1);
    if (error)
            return error;*/

        return 0;

}

unsigned bcd2bin(unsigned char val)
{
    return (unsigned int)((val & 0x0f) + (val >> 4) * 10);
}

int rtc_month_days(unsigned int month, unsigned int year)
{
    return rtc_days_in_month[month] + (is_leap_year(year) && month == 1);
}
int rtc_valid_tm(struct tm *tm)
{
    if (tm->tm_year < 70
        || ((unsigned)tm->tm_mon) >= 12
        || tm->tm_mday < 1
        || tm->tm_mday > rtc_month_days((unsigned int)tm->tm_mon, (unsigned int)tm->tm_year + 1900)
        || ((unsigned)tm->tm_hour) >= 24
        || ((unsigned)tm->tm_min) >= 60
        || ((unsigned)tm->tm_sec) >= 60)
        return -1;

    return 0;
}

static int bq32k_rtc_read_time(struct tm *tm1)
{

    int error;
    //rtc_time_t  read_time;
    struct bq32k_regs regs;

    error = (int) bq32kRead( &regs, 0 , sizeof(regs));
    if (error)
        return error;

    tm1->tm_sec  =  (int) bcd2bin(regs.seconds & BQ32K_SECONDS_MASK);
    tm1->tm_min  =  (int) bcd2bin(regs.minutes & BQ32K_MINUTES_MASK);
    tm1->tm_hour =  (int) bcd2bin(regs.cent_hours & BQ32K_HOURS_MASK);
    tm1->tm_mday =  (int) bcd2bin(regs.date);
    tm1->tm_wday =  (int) bcd2bin(regs.day) - 1;
    tm1->tm_mon  =  (int) bcd2bin(regs.month) - 1;
#ifdef SEMI_HOSTING
    if (CoreDebug->DHCSR & CoreDebug_DHCSR_C_DEBUGEN_Msk)
    {
        printf("\r\nREad rtime\r\n");
        printf("Hour: %x\tMin: %x\tSec: %x\t\r\n", tm1->tm_hour, tm1->tm_min, tm1->tm_sec);
    }
#endif


    tm1->tm_year =  (int) bcd2bin(regs.years) +
                ((regs.cent_hours & BQ32K_CENT) ? 100 : 0);


    return rtc_valid_tm(tm1);
}

unsigned char bin2bcd(unsigned val)
{
    return ((val / 10) << 4) + val % 10;
}

static int bq32k_rtc_set_time(struct tm *tm1)
{

    struct bq32k_regs regs;

    regs.seconds = bin2bcd((unsigned int)tm1->tm_sec);
        regs.minutes = bin2bcd((unsigned int)tm1->tm_min);
        regs.cent_hours = bin2bcd((unsigned int)tm1->tm_hour) | BQ32K_CENT_EN;
        regs.day = bin2bcd((unsigned int)tm1->tm_wday + 1);
        regs.date = bin2bcd((unsigned int)tm1->tm_mday);
        regs.month = bin2bcd((unsigned int)tm1->tm_mon + 1);

    if ((unsigned int)tm1->tm_year >= 100) {
        regs.cent_hours |= BQ32K_CENT;
        regs.years = bin2bcd((unsigned int)tm1->tm_year - 100);
    } else
        regs.years = bin2bcd((unsigned int)tm1->tm_year);

#ifdef SEMI_HOSTING
    if (CoreDebug->DHCSR & CoreDebug_DHCSR_C_DEBUGEN_Msk)
    {
        printf("\r\nwrite_time\r\n");
        printf("Hour: %x\tMin: %x\tSec: %x\t\r\n", regs.cent_hours, regs.minutes, regs.seconds);
        //R_BSP_SoftwareDelay(10,BSP_DELAY_UNITS_SECONDS);
        printf("hour1: %x\tMin1: %x\sec1: %x\t\r\n", tm1->tm_hour, tm1->tm_min,tm1->tm_sec);
    }
#endif

    return bq32kWrite( &regs, 0, sizeof(regs));
}

void bq32kinitialize()
{
    struct tm tm12={0};
    struct tm *tm1;
    tm1 = &tm12;
    struct tm tm123={0};
    struct tm *tm2;
    tm2 = &tm123;

    tm1->tm_hour =0x5;
    tm1->tm_min =0x8;
    tm1->tm_sec=0x16;
    int error1=0;
    uint8_t reg=0;
    g_i2c2.p_api->open(g_i2c2.p_ctrl, g_i2c2.p_cfg);
    R_BSP_SoftwareDelay(100,BSP_DELAY_UNITS_MILLISECONDS);
    g_i2c2.p_api->reset(g_i2c2.p_ctrl);
    R_BSP_SoftwareDelay(100,BSP_DELAY_UNITS_MILLISECONDS);



    bq32kinit();


#ifdef SEMI_HOSTING
    if (CoreDebug->DHCSR & CoreDebug_DHCSR_C_DEBUGEN_Msk)
    {
        printf("\r\n  reg error1 =%d\r\n",reg);

    }
#endif

    bq32k_rtc_read_time(tm2);
    tm123.tm_sec = 0;
    tm123.tm_min = 0;
    tm123.tm_hour = 0;
    tm123.tm_mday = 0;
    tm123.tm_mon = 0;
    tm123.tm_year = 0;
    tm123.tm_wday = 0;
    tm123.tm_yday = 0;
    tm123.tm_isdst = 0;

    bq32k_rtc_set_time(tm1);
    tm123.tm_sec = 0;
    tm123.tm_min = 0;
    tm123.tm_hour = 0;
    tm123.tm_mday = 0;
    tm123.tm_mon = 0;
    tm123.tm_year = 0;
    tm123.tm_wday = 0;
    tm123.tm_yday = 0;
    tm123.tm_isdst = 0;



    while (1)
        {
        tm123.tm_sec = 0;
        tm123.tm_min = 0;
        tm123.tm_hour = 0;
        tm123.tm_mday = 0;
        tm123.tm_mon = 0;
        tm123.tm_year = 0;
        tm123.tm_wday = 0;
        tm123.tm_yday = 0;
        tm123.tm_isdst = 0;

        bq32k_rtc_read_time(tm2);

        }


}

/* rtc Thread entry function */
void rtc_thread_entry(void)
{
    /* TODO: add your own code here */

    bq32kinitialize();
    while (1)
    {
        tx_thread_sleep (1);
    }
}






