A feature complete driver for the ISL1208 real time clock from Intersil.

Dependents:   ISL1208_HelloWorld

Files at this revision

API Documentation at this revision

Comitter:
neilt6
Date:
Mon Sep 09 19:32:41 2013 +0000
Child:
1:c951ff6da740
Commit message:
Initial commit

Changed in this revision

ISL1208.cpp Show annotated file Show diff for this revision Revisions of this file
ISL1208.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ISL1208.cpp	Mon Sep 09 19:32:41 2013 +0000
@@ -0,0 +1,513 @@
+/* ISL1208 Driver Library
+ * Copyright (c) 2013 Neil Thiessen
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ISL1208.h"
+
+ISL1208::ISL1208(PinName sda, PinName scl) : m_I2C(sda, scl)
+{
+    //Nothing else to initialize
+}
+
+bool ISL1208::open(OscillatorMode mode)
+{
+    //Probe for the ISL1208 using a Zero Length Transfer
+    if (!m_I2C.write(m_ADDR, NULL, 0)) {
+        //Read the current status register
+        char sr = read8(REG_CTL_SR);
+
+        //Configure the oscillator mode
+        if (mode == OSCILLATOR_CRYSTAL)
+            sr &= ~(1 << 6);
+        else
+            sr |= (1 << 6);
+
+        //Disable auto reset for BAT and ALM bits
+        sr &= ~(1 << 7);
+
+        //Write the new status register
+        write8(REG_CTL_SR, sr);
+
+        //Return success
+        return true;
+    } else {
+        //Return failure
+        return false;
+    }
+}
+
+time_t ISL1208::time(void)
+{
+    //Setup a tm structure based on the RTC
+    struct tm timeinfo;
+    timeinfo.tm_sec = bcd2bin(read8(REG_RTC_SC));
+    timeinfo.tm_min = bcd2bin(read8(REG_RTC_MN));
+
+    //Make sure we get the proper hour regardless of the mode
+    char hours = read8(REG_RTC_HR);
+    if (hours & (1 << 7)) {
+        //RTC is in 24-hour mode
+        timeinfo.tm_hour = bcd2bin(hours & 0x3F);
+    } else {
+        //RTC is in 12-hour mode
+        timeinfo.tm_hour = bcd2bin(hours & 0x1F);
+
+        //Check for the PM flag
+        if (hours & (1 << 5))
+            timeinfo.tm_hour += 12;
+    }
+
+    //Continue reading the registers
+    timeinfo.tm_mday = bcd2bin(read8(REG_RTC_DT));
+    timeinfo.tm_mon = bcd2bin(read8(REG_RTC_MO)) - 1;
+    timeinfo.tm_year = bcd2bin(read8(REG_RTC_YR)) + 100;
+    timeinfo.tm_wday = bcd2bin(read8(REG_RTC_DW));
+
+    //Return as a timestamp
+    return mktime(&timeinfo);
+}
+
+void ISL1208::time(time_t t)
+{
+    //Convert the time to a tm
+    struct tm *timeinfo = localtime(&t);
+
+    /* The clock has an 8 bit wide bcd-coded register (they never learn)
+     * for the year. tm_year is an offset from 1900 and we are interested
+     * in the 2000-2099 range, so any value less than 100 is invalid.
+     */
+    if (timeinfo->tm_year < 100)
+        return;
+
+    //Read the old SR register value
+    char sr = read8(REG_CTL_SR);
+
+    //Enable RTC writing
+    write8(REG_CTL_SR, sr | (1 << 4));
+
+    //Write the current time
+    write8(REG_RTC_SC, bin2bcd(timeinfo->tm_sec));
+    write8(REG_RTC_MN, bin2bcd(timeinfo->tm_min));
+    write8(REG_RTC_HR, bin2bcd(timeinfo->tm_hour) | (1 << 7));    //24-hour mode
+    write8(REG_RTC_DT, bin2bcd(timeinfo->tm_mday));
+    write8(REG_RTC_MO, bin2bcd(timeinfo->tm_mon + 1));
+    write8(REG_RTC_YR, bin2bcd(timeinfo->tm_year - 100));
+    write8(REG_RTC_DW, bin2bcd(timeinfo->tm_wday & 7));
+
+    //Disable RTC writing
+    write8(REG_CTL_SR, sr);
+}
+
+bool ISL1208::powerFailed(void)
+{
+    //Read the 8-bit register value
+    char value = read8(REG_CTL_SR);
+
+    //Return the status of the RTCF bit
+    if (value & (1 << 0))
+        return true;
+    else
+        return false;
+}
+
+bool ISL1208::batteryFlag(void)
+{
+    //Read the 8-bit register value
+    char value = read8(REG_CTL_SR);
+
+    //Return the status of the BAT bit
+    if (value & (1 << 1))
+        return true;
+    else
+        return false;
+}
+
+void ISL1208::clearBatteryFlag(void)
+{
+    //Read the current 8-bit register value
+    char value = read8(REG_CTL_SR);
+
+    //Clear the BAT bit
+    value &= ~(1 << 1);
+
+    //Write the value back out
+    write8(REG_CTL_SR, value);
+}
+
+bool ISL1208::alarmFlag(void)
+{
+    //Read the 8-bit register value
+    char value = read8(REG_CTL_SR);
+
+    //Return the status of the ALM bit
+    if (value & (1 << 2))
+        return true;
+    else
+        return false;
+}
+
+void ISL1208::clearAlarmFlag(void)
+{
+    //Read the current 8-bit register value
+    char value = read8(REG_CTL_SR);
+
+    //Clear the ALM bit
+    value &= ~(1 << 2);
+
+    //Write the value back out
+    write8(REG_CTL_SR, value);
+}
+
+ISL1208::OutputFrequency ISL1208::foutFrequency(void)
+{
+    //Read the 8-bit register value
+    char value = read8(REG_CTL_INT);
+
+    //Return the lower nibble
+    return (OutputFrequency)(value & 0x0F);
+}
+
+void ISL1208::foutFrequency(OutputFrequency freq)
+{
+    //Read the current 8-bit register value
+    char value = read8(REG_CTL_INT);
+
+    //Clear the old frequency bits
+    value &= 0xF0;
+
+    //Set the new frequency bits
+    value |= freq;
+
+    //Write the value back out
+    write8(REG_CTL_INT, value);
+}
+
+bool ISL1208::outputOnBattery(void)
+{
+    //Read the 8-bit register value
+    char value = read8(REG_CTL_INT);
+
+    //Return the status of the FOBATB bit
+    if (value & (1 << 4))
+        return false;
+    else
+        return true;
+}
+
+void ISL1208::outputOnBattery(bool output)
+{
+    //Read the current 8-bit register value
+    char value = read8(REG_CTL_INT);
+
+    //Set or clear the FOBATB bit
+    if (output)
+        value &= ~(1 << 4);
+    else
+        value |= (1 << 4);
+
+    //Write the value back out
+    write8(REG_CTL_INT, value);
+}
+
+ISL1208::PowerMode ISL1208::powerMode(void)
+{
+    //Read the 8-bit register value
+    char value = read8(REG_CTL_INT);
+
+    //Return the status of the LPMODE bit
+    if (value & (1 << 5))
+        return POWER_LPMODE;
+    else
+        return POWER_NORMAL;
+}
+
+void ISL1208::powerMode(PowerMode mode)
+{
+    //Read the current 8-bit register value
+    char value = read8(REG_CTL_INT);
+
+    //Set or clear the LPMODE bit
+    if (mode == POWER_LPMODE)
+        value |= (1 << 5);
+    else
+        value &= ~(1 << 5);
+
+    //Write the value back out
+    write8(REG_CTL_INT, value);
+}
+
+ISL1208::AlarmMode ISL1208::alarmMode(void)
+{
+    //Read the 8-bit register value
+    char value = read8(REG_CTL_INT);
+
+    //Return the status of the ALME and IM bits
+    if (value & (1 << 6)) {
+        if (value & (1 << 7))
+            return ALARM_INTERRUPT;
+        else
+            return ALARM_SINGLE;
+    } else
+        return ALARM_DISABLED;
+}
+
+void ISL1208::alarmMode(AlarmMode mode)
+{
+    //Read the current 8-bit register value
+    char value = read8(REG_CTL_INT);
+
+    //Set or clear the ALME and IM bit
+    if (mode != ALARM_DISABLED) {
+        value |= (1 << 6);
+        if (mode == ALARM_INTERRUPT)
+            value |= (1 << 7);
+        else
+            value &= ~(1 << 7);
+    } else
+        value &= ~(1 << 6);
+
+    //Write the value back out
+    write8(REG_CTL_INT, value);
+}
+
+float ISL1208::analogTrim(void)
+{
+    //Read the 8-bit register value
+    char value = read8(REG_CTL_ATR);
+
+    //Mask off the top 2 bits
+    value &= 0x3F;
+
+    //Invert bit 5
+    value ^= 1 << 5;
+
+    //Add an offset of 4.5pF (unit[atr] = 0.25pF)
+    value += 2 * 9;
+
+    //Return the analog trim in pF
+    return value * 0.25;
+}
+
+void ISL1208::analogTrim(float trim)
+{
+    //Range limit trim
+    if (trim < 4.5)
+        trim = 4.5;
+    else if (trim > 20.25)
+        trim = 20.25;
+
+    //Convert the analog trim value to a 6-bit integer
+    char value = (char)(trim / 0.25);
+
+    //Remove the offset of 4.5pF (unit[atr] = 0.25pF)
+    value -= 2 * 9;
+
+    //Invert bit 5
+    value ^= 1 << 5;
+
+    //Read the current 8-bit register value
+    char reg = read8(REG_CTL_ATR);
+
+    //Clear the old ATR bits
+    reg &= 0xC0;
+
+    //Add the new ATR bits
+    reg |= value;
+
+    //Write the value back out
+    write8(REG_CTL_ATR, reg);
+}
+
+ISL1208::BatteryModeATR ISL1208::batteryModeATR(void)
+{
+    //Read the 8-bit register value
+    char value = read8(REG_CTL_ATR);
+
+    //Shift out the ATR bits
+    value >>= 6;
+
+    //Return the value as a BatteryModeATR enum
+    return (BatteryModeATR)value;
+}
+
+void ISL1208::batteryModeATR(BatteryModeATR atr)
+{
+    //Read the current 8-bit register value
+    char value = read8(REG_CTL_ATR);
+
+    //Clear the old battery mode ATR bits
+    value &= 0x3F;
+
+    //Add the new battery mode ATR bits
+    value |= (atr << 6);
+
+    //Write the value back out
+    write8(REG_CTL_ATR, value);
+}
+
+ISL1208::DigitalTrim ISL1208::digitalTrim(void)
+{
+    //Read the 8-bit register value
+    char value = read8(REG_CTL_DTR);
+
+    //Mask off the reserved bit
+    value &= ~(1 << 7);
+
+    //Return the value as a DigitalTrim enum
+    return (DigitalTrim)value;
+}
+
+void ISL1208::digitalTrim(DigitalTrim dtr)
+{
+    //Read the current 8-bit register value (to preserve the reserved bit)
+    char value = read8(REG_CTL_DTR);
+
+    //Clear the old DTR bits
+    value &= 0xF8;
+
+    //Add the new DTR bits
+    value |= dtr;
+
+    //Write the value back out
+    write8(REG_CTL_DTR, value);
+}
+
+time_t ISL1208::alarmTime(void)
+{
+    //Setup a tm structure based on the RTC
+    struct tm timeinfo;
+
+    //MSB of each alarm register is an enable bit
+    timeinfo.tm_sec = bcd2bin(read8(REG_ALM_SCA) & 0x7F);
+    timeinfo.tm_min = bcd2bin(read8(REG_ALM_MNA) & 0x7F);
+    timeinfo.tm_hour = bcd2bin(read8(REG_ALM_HRA) & 0x3F);
+    timeinfo.tm_mday = bcd2bin(read8(REG_ALM_DTA) & 0x3F);
+    timeinfo.tm_mon = bcd2bin(read8(REG_ALM_MOA) & 0x1F) - 1;
+    timeinfo.tm_wday = bcd2bin(read8(REG_ALM_DWA) & 0x03);
+
+    //The alarm doesn't store the year, so get it from the RTC section
+    timeinfo.tm_year = bcd2bin(read8(REG_RTC_YR)) + 100;
+
+    //Return as a timestamp
+    return mktime(&timeinfo);
+}
+
+void ISL1208::alarmTime(time_t t, bool sc, bool mn, bool hr, bool dt, bool mo, bool dw)
+{
+    //Convert the time to a tm
+    struct tm *timeinfo = localtime(&t);
+
+    //Write the new alarm time components (if enabled)
+    if (sc)
+        write8(REG_ALM_SCA, bin2bcd(timeinfo->tm_sec) | 0x80);
+    else
+        write8(REG_ALM_SCA, 0x0);
+    if (mn)
+        write8(REG_ALM_MNA, bin2bcd(timeinfo->tm_min) | 0x80);
+    else
+        write8(REG_ALM_MNA, 0x0);
+    if (hr)
+        write8(REG_ALM_HRA, bin2bcd(timeinfo->tm_hour) | 0x80);
+    else
+        write8(REG_ALM_HRA, 0x0);
+    if (hr)
+        write8(REG_ALM_DTA, bin2bcd(timeinfo->tm_mday) | 0x80);
+    else
+        write8(REG_ALM_DTA, 0x0);
+    if (mo)
+        write8(REG_ALM_MOA, bin2bcd(timeinfo->tm_mon + 1) | 0x80);
+    else
+        write8(REG_ALM_MOA, 0x0);
+    if (dw)
+        write8(REG_ALM_DWA, bin2bcd(timeinfo->tm_wday & 7) | 0x80);
+    else
+        write8(REG_ALM_DWA, 0x0);
+}
+
+unsigned short ISL1208::sram(void)
+{
+    //Return the complete contents of the SRAM
+    return read16(REG_USR_USR1);
+}
+
+void ISL1208::sram(unsigned short data)
+{
+    //Write the complete contents of the SRAM
+    write16(REG_USR_USR1, data);
+}
+
+char ISL1208::read8(char reg)
+{
+    //Select the register
+    m_I2C.write(m_ADDR, &reg, 1);
+
+    //Read the 8-bit register
+    m_I2C.read(m_ADDR, &reg, 1);
+
+    //Return the byte
+    return reg;
+}
+
+void ISL1208::write8(char reg, char data)
+{
+    //Create a temporary buffer
+    char buff[2];
+
+    //Load the register address and 8-bit data
+    buff[0] = reg;
+    buff[1] = data;
+
+    //Write the data
+    m_I2C.write(m_ADDR, buff, 2);
+}
+
+unsigned short ISL1208::read16(char reg)
+{
+    //Create a temporary buffer
+    char buff[2];
+
+    //Select the register
+    m_I2C.write(m_ADDR, &reg, 1);
+
+    //Read the 16-bit register
+    m_I2C.read(m_ADDR, buff, 2);
+
+    //Return the combined 16-bit value
+    return (buff[0] << 8) | buff[1];
+}
+
+void ISL1208::write16(char reg, unsigned short data)
+{
+    //Create a temporary buffer
+    char buff[3];
+
+    //Load the register address and 16-bit data
+    buff[0] = reg;
+    buff[1] = data >> 8;
+    buff[2] = data;
+
+    //Write the data
+    m_I2C.write(m_ADDR, buff, 3);
+}
+
+unsigned int ISL1208::bcd2bin(unsigned char val)
+{
+    return (val & 0x0F) + (val >> 4) * 10;
+}
+
+char ISL1208::bin2bcd(unsigned int val)
+{
+    return ((val / 10) << 4) + val % 10;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ISL1208.h	Mon Sep 09 19:32:41 2013 +0000
@@ -0,0 +1,341 @@
+/* ISL1208 Driver Library
+ * Copyright (c) 2013 Neil Thiessen
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ISL1208_H
+#define ISL1208_H
+
+#include "mbed.h"
+
+/** ISL1208 class.
+ *  Used for controlling an ISL1208 real time clock connected via I2C.
+ *
+ * Example:
+ * @code
+ * #include "mbed.h"
+ * #include "ISL1208.h"
+ *
+ * ISL1208 rtc(p28, p27);
+ *
+ * int main()
+ * {
+ *     //Try to open the ISL1208
+ *     if (rtc.open(ISL1208::OSCILLATOR_CRYSTAL)) {
+ *         printf("Device detected!\n");
+ *
+ *         //Check if we need to reset the time
+ *         if (rtc.powerFailed()) {
+ *             //The time has been lost due to a power complete power failure
+ *             printf("Device has lost power! Resetting time...\n");
+ *
+ *             //Set RTC time to Wed, 28 Oct 2009 11:35:37
+ *             rtc.time(1256729737);
+ *         }
+ *
+ *         while(1) {
+ *             //Get the current time
+ *             time_t seconds = rtc.time();
+ *
+ *             //Print the time in various formats
+ *             printf("\nTime as seconds since January 1, 1970 = %d\n", seconds);
+ *             printf("Time as a basic string = %s", ctime(&seconds));
+ *             char buffer[32];
+ *             strftime(buffer, 32, "%I:%M %p\n", localtime(&seconds));
+ *             printf("Time as a custom formatted string = %s", buffer);
+ *
+ *             //Delay for 1.0 seconds
+ *             wait(1.0);
+ *         }
+ *     } else {
+ *         printf("Device not detected!\n");
+ *     }
+ * }
+ * @endcode
+ */
+class ISL1208
+{
+public:
+    /** Represents the different oscillator modes for the ISL1208
+     */
+    enum OscillatorMode {
+        OSCILLATOR_CRYSTAL,  /**< The internal crystal oscillator is enabled */
+        OSCILLATOR_EXTERNAL  /**< The internal crystal oscillator is disabled, an external 32kHz oscillator is connected to X1 */
+    };
+
+    /** Represents the different output frequencies for the IRQ/fOUT pin on the ISL1208
+     */
+    enum OutputFrequency {
+        FOUT_DISABLED = 0,  /**< Disable frequency generation on the IRQ/fOUT pin */
+        FOUT_32768_HZ,      /**< Generate 32.768kHz on the IRQ/fOUT pin */
+        FOUT_4096_HZ,       /**< Generate 4.096kHz on the IRQ/fOUT pin */
+        FOUT_1024_HZ,       /**< Generate 1.024kHz on the IRQ/fOUT pin */
+        FOUT_64_HZ,         /**< Generate 64Hz on the IRQ/fOUT pin */
+        FOUT_32_HZ,         /**< Generate 32Hz on the IRQ/fOUT pin */
+        FOUT_16_HZ,         /**< Generate 16Hz on the IRQ/fOUT pin */
+        FOUT_8_HZ,          /**< Generate 8Hz on the IRQ/fOUT pin */
+        FOUT_4_HZ,          /**< Generate 4Hz on the IRQ/fOUT pin */
+        FOUT_2_HZ,          /**< Generate 2Hz on the IRQ/fOUT pin */
+        FOUT_1_HZ,          /**< Generate 1Hz on the IRQ/fOUT pin */
+        FOUT_1_2_HZ,        /**< Generate 1/2Hz on the IRQ/fOUT pin */
+        FOUT_1_4_HZ,        /**< Generate 1/4Hz on the IRQ/fOUT pin */
+        FOUT_1_8_HZ,        /**< Generate 1/8Hz on the IRQ/fOUT pin */
+        FOUT_1_16_HZ,       /**< Generate 1/16Hz on the IRQ/fOUT pin */
+        FOUT_1_32_HZ        /**< Generate 1/32Hz on the IRQ/fOUT pin */
+    };
+
+    /** Represents the power mode of the ISL1208
+     */
+    enum PowerMode {
+        POWER_NORMAL,   /**< VBAT supply will be used when VDD < VBAT - VBATHYS and VDD < VTRIP */
+        POWER_LPMODE    /**< VBAT supply will be used when VDD < VBAT - VBATHYS */
+    };
+
+    /** Represents the alarm mode of the ISL1208
+     */
+    enum AlarmMode {
+        ALARM_DISABLED, /**< The alarm function is disabled */
+        ALARM_SINGLE,   /**< Only a one-time match will be made between the RTC and alarm registers, and the IRQ/fOUT pin will pull low until the alarm flag is cleared */
+        ALARM_INTERRUPT /**< Every time an alarm match is made the IRQ/fOUT pin will pull low for 250ms, the alarm flag does not have to be cleared */
+    };
+
+    /** Represents the different battery mode ATR selections of the ISL1208
+     */
+    enum BatteryModeATR {
+        BMATR_ZERO = 0,     /**< Delta capacitance = 0pF */
+        BMATR_MINUS_0_5,    /**< Delta capacitance = -0.5pF (≈ +2ppm) */
+        BMATR_PLUS_0_5,     /**< Delta capacitance = +0.5pF (≈ -2ppm) */
+        BMATR_PLUS_1_0      /**< Delta capacitance = +1pF (≈ -4ppm) */
+    };
+
+    /** Represents the different digital trim selections of the ISL1208
+     */
+    enum DigitalTrim {
+        DTR_ZERO = 0,       /**< Digital trim = 0ppm */
+        DTR_PLUS_20,        /**< Digital trim = ≈ +20ppm */
+        DTR_PLUS_40,        /**< Digital trim = ≈ +40ppm */
+        DTR_PLUS_60,        /**< Digital trim = ≈ +60ppm */
+        DTR_MINUS_20 = 5,   /**< Digital trim = ≈ -20ppm */
+        DTR_MINUS_40,       /**< Digital trim = ≈ -40ppm */
+        DTR_MINUS_60        /**< Digital trim = ≈ -60ppm */
+    };
+
+    /** Create a ISL1208 object connected to the specified I2C pins
+     *
+     * @param sda The I2C data pin.
+     * @param scl The I2C clock pin.
+     */
+    ISL1208(PinName sda, PinName scl);
+
+    /** Probe for the ISL1208 and configures the oscillator mode if present
+     *
+     * @param mode The oscillator mode.
+     * @returns
+     *   'true' if the device exists on the bus,
+     *   'false' if the device doesn't exist on the bus.
+     */
+    bool open(OscillatorMode mode);
+
+    /** Get the current time from the ISL1208
+     *
+     * @returns The current time as a Unix timestamp.
+     */
+    time_t time(void);
+
+    /** Set the current time on the ISL1208 from a Unix timestamp
+     *
+     * @param t The current time as a Unix timestamp.
+     */
+    void time(time_t t);
+
+    /** Determine whether the RTC has completely lost power (and hence the time and SRAM)
+     *
+     * @returns Whether or not the RTC has completely lost power.
+     */
+    bool powerFailed(void);
+
+    /** Determine whether the RTC has been on battery backup
+     *
+     * @returns Whether or not the RTC has been on battery backup.
+     */
+    bool batteryFlag(void);
+
+    /** Clear the battery backup flag
+     */
+    void clearBatteryFlag(void);
+
+    /** Determine whether the alarm has matched the RTC
+     *
+     * @returns Whether or not the alarm has matched the RTC.
+     */
+    bool alarmFlag(void);
+
+    /** Clear the alarm flag
+     */
+    void clearAlarmFlag(void);
+
+    /** Get the current output frequency on the IRQ/fOUT pin
+     *
+     * @returns The current output frequency.
+     */
+    ISL1208::OutputFrequency foutFrequency(void);
+
+    /** Set the output frequency on the IRQ/fOUT pin
+     *
+     * @param freq The new output frequency.
+     */
+    void foutFrequency(OutputFrequency freq);
+
+    /** Determine whether or not the IRQ/fOUT pin will continue to output on battery power
+     *
+     * @returns Whether or not the IRQ/fOUT pin will continue to output on battery power.
+     */
+    bool outputOnBattery(void);
+
+    /** Set whether or not the IRQ/fOUT pin should continue to output on battery power
+     *
+     * @param output Whether or not the IRQ/fOUT pin should continue to output on battery power.
+     */
+    void outputOnBattery(bool output);
+
+    /** Get the current power mode of the ISL1208
+     *
+     * @returns The current power mode as a PowerMode enum.
+     */
+    ISL1208::PowerMode powerMode(void);
+
+    /** Set the power mode of the ISL1208
+     *
+     * @param mode The new power mode as a PowerMode enum.
+     */
+    void powerMode(PowerMode mode);
+
+    /** Get the current alarm mode of the ISL1208
+     *
+     * @returns The current alarm mode as an AlarmMode enum.
+     */
+    ISL1208::AlarmMode alarmMode(void);
+
+    /** Set the alarm mode of the ISL1208
+     *
+     * @param mode The new alarm mode as an AlarmMode enum.
+     */
+    void alarmMode(AlarmMode mode);
+
+    /** Get the current analog trim of the ISL1208
+     *
+     * @returns The current analog trim in pF.
+     */
+    float analogTrim(void);
+
+    /** Set the analog trim of the ISL1208
+     *
+     * @param trim The new analog trim in pF (valid range 4.5pF to 20.25pF in 0.25pF steps).
+     */
+    void analogTrim(float trim);
+
+    /** Get the current battery mode analog trim of the ISL1208
+     *
+     * @returns The current battery mode analog trim as a BatteryModeATR enum.
+     */
+    ISL1208::BatteryModeATR batteryModeATR(void);
+
+    /** Set the battery mode analog trim of the ISL1208
+     *
+     * @param mode The new battery mode analog trim as a BatteryModeATR enum.
+     */
+    void batteryModeATR(BatteryModeATR atr);
+
+    /** Get the current digital trim of the ISL1208
+     *
+     * @returns The current digital trim as a DigitalTrim enum.
+     */
+    ISL1208::DigitalTrim digitalTrim(void);
+
+    /** Set the digital trim of the ISL1208
+     *
+     * @param mode The new digital trim as a DigitalTrim enum.
+     */
+    void digitalTrim(DigitalTrim dtr);
+
+    /** Get the alarm time from the ISL1208
+     *
+     * @returns The current alarm time as a Unix timestamp (with the current year)
+     */
+    time_t alarmTime(void);
+
+    /** Set the alarm time on the ISL1208 from a Unix timestamp
+     *
+     * @param t The alarm time as a Unix timestamp.
+     * @param sc Enable or disable seconds matching.
+     * @param mn Enable or disable minutes matching.
+     * @param hr Enable or disable hours matching.
+     * @param dt Enable or disable date matching.
+     * @param mo Enable or disable month matching.
+     * @param dw Enable or disable day of week matching.
+     */
+    void alarmTime(time_t t, bool sc = true, bool mn = true, bool hr = true, bool dt = true, bool mo = true, bool dw = true);
+
+    /** Read the contents of the battery-backed SRAM
+     *
+     * @returns The current contents of the SRAM.
+     */
+    unsigned short sram(void);
+
+    /** Write new data to the battery-backed SRAM
+     *
+     * @param data The new data for the SRAM.
+     */
+    void sram(unsigned short data);
+
+private:
+    //I2C register addresses
+    enum Register {
+        REG_RTC_SC  = 0x00,
+        REG_RTC_MN,
+        REG_RTC_HR,
+        REG_RTC_DT,
+        REG_RTC_MO,
+        REG_RTC_YR,
+        REG_RTC_DW,
+        REG_CTL_SR,
+        REG_CTL_INT,
+        REG_CTL_ATR = 0x0A,
+        REG_CTL_DTR,
+        REG_ALM_SCA,
+        REG_ALM_MNA,
+        REG_ALM_HRA,
+        REG_ALM_DTA,
+        REG_ALM_MOA,
+        REG_ALM_DWA,
+        REG_USR_USR1,
+        REG_USR_USR2
+    };
+
+    //Member constants
+    static const int m_ADDR = (0x6F << 1);
+
+    //Member variables
+    I2C m_I2C;
+
+    //Internal functions
+    char read8(char reg);
+    void write8(char reg, char data);
+    unsigned short read16(char reg);
+    void write16(char reg, unsigned short data);
+    unsigned int bcd2bin(unsigned char val);
+    char bin2bcd(unsigned int val);
+};
+
+#endif