Subversion Repositories Code-Repo

Rev

Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

#include "defines.h"
#include "DS3231.h"
#include "I2C1.h"

void DS3231_Init() {
    uint8_t reg[3];
    reg[0] = DS3231_CONTROL;
    
    /* Control Register (0x0E)
     * Bit 7 - !EOSC
     * Bit 6 - BBSQW
     * Bit 5 - CONV
     * Bit 4 - RS2
     * Bit 3 - RS1
     * Bit 2 - INTCN
     * Bit 1 - A2IE
     * Bit 0 - A1IE
     */
    reg[1] = 0x04;

    /* Control Register 2 (0x0F)
     * Bit 3 = EN32kHZ
     */
    reg[2] = 0x00;

    // Set the configuration registers
    I2C1_Master_Send(DS3231_ADDRESS, 3, reg);
    while (!I2C1_Get_Status());
}

uint8_t DS3231_Get_Status(void) {
    /* Status Register (0x0F)
     * Bit 7 - OSF
     * Bit 3 - EN32kHz
     * Bit 2 - BSY
     * Bit 1 - A2F
     * Bit 0 - A1F
     */
    uint8_t value;
    I2C1_Master_Restart(DS3231_ADDRESS, 0x0F, 1);
    while (!I2C1_Get_Status());
    I2C1_Read_Buffer(&value);
    return value;
}

void DS3231_Set_Time(DS3231_TIME *time) {

    // Format the data in a way that the chip expects
#ifndef DS3231_TIME_ONLY
    uint8_t output[8];
#else
    uint8_t output[4];
#endif
    output[0] = DS3231_SECONDS;
    output[1] = ((time->sec / 10) << 4) | (time->sec % 10);
    output[2] = ((time->min / 10) << 4) | (time->min % 10);
    output[3] = ((time->hour / 10) << 4) | (time->hour % 10);
#ifndef DS3231_TIME_ONLY
    if (!time->h_mil) {
        output[3] |= (time->h_am_pm) ? 0x60 : 0x40;
    }
    output[4] = time->day;
    output[5] = ((time->date / 10) << 4) | (time->date % 10);
    output[6] = ((time->month / 10) << 4) | (time->month % 10);
    output[7] = ((time->year / 10) << 4) | (time->year % 10);
#endif

    // Check the status to make sure that it isnt currently busy
    while (DS3231_Get_Status() & 0x04);

    // Write the data to the chip
#ifndef DS3231_TIME_ONLY
    I2C1_Master_Send(DS3231_ADDRESS, 8, output);
#else
    I2C1_Master_Send(DS3231_ADDRESS, 4, output);
#endif
    while (!I2C1_Get_Status());
}

void DS3231_Get_Time(DS3231_TIME *time) {

    // Check the status to make sure that it isnt currently busy
    while (DS3231_Get_Status() & 0x04);

    // Request time data from the chip
#ifndef DS3231_TIME_ONLY
    uint8_t input[7];
    I2C1_Master_Restart(DS3231_ADDRESS, 0x00, 7);
#else
    uint8_t input[3];
    I2C1_Master_Restart(DS3231_ADDRESS, 0x00, 3);
#endif
    while (!I2C1_Get_Status());
    I2C1_Read_Buffer(input);

    // Parse BCD format into decimal and return
    time->sec = ((input[0] >> 4) * 10) + (input[0] & 0x0F);
    time->min = ((input[1] >> 4) * 10) + (input[1] & 0x0F);
    if (input[2] & 0x40) {
        time->h_mil = 0;
        time->h_am_pm = (input[2] & 0x20) ? 1 : 0;
        time->hour = (((input[2] >> 4) & 0x01) * 10) + (input[2] & 0x0F);
    } else {
        time->h_mil = 1;
        time->hour = ((input[2] >> 4) * 10) + (input[2] & 0x0F);
    }
#ifndef DS3231_TIME_ONLY
    time->day = input[3];
    time->date = ((input[4] >> 4) * 10) + (input[4] & 0x0F);
    time->month = ((input[5] >> 4) * 10) + (input[5] & 0x0F);
    time->year = ((input[6] >> 4) * 10) + (input[6] & 0x0F);
#endif
}