Commit the AM1805 library

Files at this revision

API Documentation at this revision

Comitter:
marcusC
Date:
Thu Dec 24 05:25:32 2015 +0000
Commit message:
Commit the AM1805 library

Changed in this revision

AM1805.cpp Show annotated file Show diff for this revision Revisions of this file
AM1805.h Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r 5e0616a05642 AM1805.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AM1805.cpp	Thu Dec 24 05:25:32 2015 +0000
@@ -0,0 +1,607 @@
+/* AM1805 Sample code: external RTC module is used by host MCU */
+
+#include "mbed.h"
+#include "AM1805.h"
+
+#define I2C_SDA p28
+#define I2C_SCL p27
+#define AM1805_I2C_ADDRESS 0xD2
+/* Register Map */
+#define AM1805_REG_HUNDREDTHS   0x00
+#define AM1805_REG_ALM_HUN      0x08
+#define AM1805_REG_STATUS       0x0F
+#define AM1805_REG_CTRL1        0x10
+#define AM1805_REG_CTRL2        0x11
+#define AM1805_REG_INTMASK      0x12
+#define AM1805_REG_SLEEPCTRL    0x17
+#define AM1805_REG_TIM_CTRL     0x18
+#define AM1805_REG_CDTIM        0x19
+#define AM1805_REG_TIMINIT      0x1A
+#define AM1805_REG_WDT          0x1B
+#define AM1805_REG_OSCSTATUS    0x1D
+#define AM1805_REG_ID0          0x28
+#define AM1805_REG_EXTADDR_REG  0x3F
+/* Register Value */
+#define AM1805_VALUE_ID0 0x18
+
+#define AM1805_DEBUG 0
+
+I2C i2c(I2C_SDA, I2C_SCL);
+#if AM1805_DEBUG
+Serial pc(p13,p14);
+#endif
+
+static uint8_t get_extension_address(uint8_t address)
+{
+    uint8_t xadd;
+    char temp;
+
+    am1805_register_read(AM1805_REG_EXTADDR_REG, &temp, 1);
+    temp = temp & 0xC0;
+
+    if (address < 64) { xadd = 0x8; }
+    else if (address < 128) { xadd = 0x9; }
+    else if (address < 192) { xadd = 0xA; }
+    else { xadd = 0xB; }
+    return (xadd | temp);
+}
+
+/* Set one or more bits in the selected register, selected by 1's in the mask */
+static void setreg(char address, uint8_t mask)
+{
+    char temp;
+
+    am1805_register_read(address, &temp, 1);
+    temp |= mask;
+    am1805_register_write(address, temp);
+}
+
+/* Clear one or more bits in the selected register, selected by 1's in the mask */
+static void clrreg(char address, uint8_t mask)
+{
+    char temp;
+    
+    am1805_register_read(address, &temp, 1);
+    temp &= ~mask;
+    am1805_register_write(address, temp);
+}
+
+static bool am1805_verify_product_id(void)
+{
+    char who_am_i[1];
+    am1805_register_read(AM1805_REG_ID0, &who_am_i[0], 1);    
+#if AM1805_DEBUG    
+    pc.printf("ID:%x\r\n",who_am_i[0]);
+#endif    
+    if (who_am_i[0] != AM1805_VALUE_ID0) 
+        return false;
+    else 
+        return true;
+}
+
+bool am1805_init(void)
+{   
+  bool transfer_succeeded = false;
+
+  i2c.frequency(400000);
+       
+  /* Read and verify product ID */
+  transfer_succeeded = am1805_verify_product_id();
+
+  return transfer_succeeded;
+}
+
+void am1805_register_read(char register_address, char *destination, uint8_t number_of_bytes)
+{
+  i2c.write(AM1805_I2C_ADDRESS, &register_address, 1, 1);
+  i2c.read(AM1805_I2C_ADDRESS, destination, number_of_bytes);    
+}
+
+void am1805_register_write(char register_address, uint8_t value)
+{   
+    char tx_data[2];
+    
+    tx_data[0] = register_address;
+    tx_data[1] = value;
+    i2c.write(AM1805_I2C_ADDRESS, tx_data, 2);      
+
+}
+
+void am1805_burst_write(uint8_t *tx_data, uint8_t number_of_bytes)
+{
+    i2c.write(AM1805_I2C_ADDRESS, (char *)tx_data, number_of_bytes);
+}
+
+void am1805_config_input_interrupt(input_interrupt_t index_Interrupt)
+{
+    switch(index_Interrupt) {
+        case XT1_INTERRUPT:
+            /* Set input interrupt pin EX1T */
+            clrreg(AM1805_REG_STATUS,0x01);             // Clear EX1
+            setreg(AM1805_REG_INTMASK,0x01);            // Set EX1E    
+            break;
+        case XT2_INTERRUPT:
+            /* Set input interrupt pin WDI */
+            clrreg(AM1805_REG_STATUS,0x02);             // Clear EX2
+            setreg(AM1805_REG_INTMASK,0x02);            // Set EX2E       
+            break;
+        default:
+#if AM1805_DEBUG    
+            pc.printf("Wrong Input Interrupt Index\r\n");
+#endif         
+            break;        
+    }
+}
+
+
+// Read a byte from local RAM
+uint8_t am1805_read_ram(uint8_t address)
+{
+    uint8_t xadd;
+    char temp;
+    uint8_t reg_ram = 0;
+
+    xadd = get_extension_address(address);                  // Calc XADDR value from address
+    am1805_register_write(AM1805_REG_EXTADDR_REG, xadd);    // Load the XADDR register
+    reg_ram = (address & 0x3F) | 0x40;                      // Read the data
+    am1805_register_read(reg_ram, &temp, 1);
+#if AM1805_DEBUG  
+    pc.printf("Read from addr:%x Data:%x\r\n",address,temp);
+#endif    
+    return (uint8_t)temp;                
+}
+
+// Write a byte to local RAM
+void am1805_write_ram(uint8_t address, uint8_t data)
+{
+    uint8_t xadd;
+    uint8_t reg_ram = 0;
+
+    xadd = get_extension_address(address);                  // Calc XADDR value from address
+    am1805_register_write(AM1805_REG_EXTADDR_REG, xadd);    // Load the XADDR register
+    reg_ram = (address & 0x3F) | 0x40;  
+    am1805_register_write(reg_ram, data);                   // Write the data
+}
+
+/*
+ * hundredth : 0 ~ 99
+ * second : 0 ~ 59
+ * minute : 0 ~ 59
+ * weekday : 0 ~ 6
+ * month : 1 ~ 12
+ * year : 0 ~ 99
+ * mode : 0 ~ 2
+ */
+void am1805_set_time(time_reg_struct_t time_regs)
+{
+    char temp;
+    uint8_t temp_buff[9];
+
+    /* 
+     * Determine whether 12 or 24-hour timekeeping mode is being used
+     * and set the 1224 bit appropriately
+     */
+    if (time_regs.mode == 2)        // 24-hour day
+    {
+        clrreg(AM1805_REG_CTRL1, 0x40);
+    }
+    else if (time_regs.mode == 1)   // 12-hour day PM
+    {
+        time_regs.hour |= 0x20;     // Set AM/PM
+        setreg(AM1805_REG_CTRL1, 0x40);
+    }
+    else                            // 12-hour day AM
+    {
+        setreg(AM1805_REG_CTRL1, 0x40);
+    }
+
+    /* Set the WRTC bit to enable counter writes. */
+    setreg(AM1805_REG_CTRL1, 0x01);
+
+    /* Set the correct century */
+    if (time_regs.century == 0)
+    {
+        clrreg(AM1805_REG_STATUS, 0x80);
+    }
+    else
+    {
+        setreg(AM1805_REG_STATUS, 0x80);
+    }
+
+    /* Write all of the time counters */
+    temp_buff[0] = AM1805_REG_HUNDREDTHS;
+    temp_buff[1] = time_regs.hundredth;
+    temp_buff[2] = time_regs.second;
+    temp_buff[3] = time_regs.minute;
+    temp_buff[4] = time_regs.hour;
+    temp_buff[5] = time_regs.date;
+    temp_buff[6] = time_regs.month;
+    temp_buff[7] = time_regs.year;
+    temp_buff[8] = time_regs.weekday;
+
+    /* Write the values to the AM18XX */
+    am1805_burst_write(temp_buff, sizeof(temp_buff));
+
+    /* Load the final value of the WRTC bit based on the value of protect */
+    am1805_register_read(AM1805_REG_CTRL1, &temp, 1);
+    temp &= 0x7E;                   // Clear the WRTC bit and the STOP bit
+    //temp_buff[1] |= (0x01 & (~protect));    // Invert the protect bit and update WRTC
+    am1805_register_write(AM1805_REG_CTRL1, temp);
+       
+    return;    
+}
+
+void am1805_get_time(time_reg_struct_t *time_regs)
+{
+    char temp_buff[8];
+    char time_mode;
+
+    /* Read the counters. */
+    am1805_register_read(AM1805_REG_HUNDREDTHS, temp_buff, 8);
+
+    time_regs->hundredth = temp_buff[0];
+    time_regs->second = temp_buff[1];
+    time_regs->minute = temp_buff[2];
+    time_regs->hour = temp_buff[3];
+    time_regs->date = temp_buff[4];
+    time_regs->month = temp_buff[5];
+    time_regs->year = temp_buff[6];
+    time_regs->weekday = temp_buff[7];
+
+    /* Get the current hours format mode 12:24 */
+    am1805_register_read(AM1805_REG_CTRL1, &time_mode, 1);
+    if ((time_mode & 0x40) == 0)
+    {
+        /* 24-hour mode. */
+        time_regs->mode = 2;
+        time_regs->hour = time_regs->hour & 0x3F;           // Get tens:ones
+    }
+    else
+    {
+        /* 12-hour mode.  Get PM:AM. */
+        time_regs->mode = (time_regs->hour & 0x20) ? 1 : 0;  // PM : AM
+        time_regs->hour &= 0x1F;                            // Get tens:ones
+    }
+
+    time_regs->hundredth = temp_buff[0];
+    time_regs->second = temp_buff[1];
+    time_regs->minute = temp_buff[2];
+    time_regs->hour = temp_buff[3];
+    time_regs->date = temp_buff[4];
+    time_regs->month = temp_buff[5];
+    time_regs->year = temp_buff[6];
+    time_regs->weekday = temp_buff[7];
+
+#if AM1805_DEBUG 
+    pc.printf("hundredth:%x\r\n",time_regs->hundredth);
+    pc.printf("second:%x\r\n",time_regs->second);
+    pc.printf("minute:%x\r\n",time_regs->minute);
+    pc.printf("hour:%x\r\n",time_regs->hour);
+    pc.printf("date:%x\r\n",time_regs->date);
+    pc.printf("month:%x\r\n",time_regs->month);
+    pc.printf("year:%x\r\n",time_regs->year);
+    pc.printf("weekday:%x\r\n",time_regs->weekday);
+#endif     
+}
+
+void am1805_config_alarm(time_reg_struct_t time_regs, alarm_repeat_t repeat, interrupt_mode_t intmode, interrupt_pin_t pin)
+{ 
+    char temp;
+    uint8_t temp_buff[9];
+
+    /* Determine whether a 12-hour or a 24-hour time keeping mode is being used */
+    if (time_regs.mode == 1)
+    {
+        /* A 12-hour day PM */
+        time_regs.hour = time_regs.hour | 0x20;   // Set AM/PM
+    }
+
+    /* Write all of the time counters */
+    temp_buff[0] = AM1805_REG_ALM_HUN;
+    temp_buff[1] = time_regs.hundredth;
+    temp_buff[2] = time_regs.second;
+    temp_buff[3] = time_regs.minute;
+    temp_buff[4] = time_regs.hour;
+    temp_buff[5] = time_regs.date;
+    temp_buff[6] = time_regs.month;
+    temp_buff[7] = time_regs.weekday;
+
+    clrreg(AM1805_REG_TIM_CTRL, 0x1C);      // Clear the RPT field
+    clrreg(AM1805_REG_INTMASK, 0x64);       // Clear the AIE bit and IM field
+    clrreg(AM1805_REG_STATUS, 0x04);        // Clear the ALM flag
+
+    if (pin == PIN_FOUT_nIRQ)
+    {
+        /* Interrupt on FOUT/nIRQ */
+        am1805_register_read(AM1805_REG_CTRL2, &temp, 1);   // Get the Control2 Register       
+        temp = (temp & 0x03);               // Extract the OUT1S field        
+        if (temp != 0)                      // Not already selecting nIRQ
+        {
+            setreg(AM1805_REG_CTRL2, 0x03);    // Set OUT1S to 3           
+        }        
+    }
+    if (pin == PIN_PSW_nIRQ2)
+    {
+        /* Interrupt on PSW/nIRQ2 */
+        am1805_register_read(AM1805_REG_CTRL2, &temp, 1);   // Get the Control2 Register
+        temp &= 0x1C;                       // Extract the OUT2S field
+        if (temp != 0)                      // Not already selecting nIRQ
+        {
+            clrreg(AM1805_REG_CTRL2, 0x1C);    // Clear OUT2S
+            setreg(AM1805_REG_CTRL2, 0x0C);    // Set OUT2S to 3
+        }
+    }
+
+    if (repeat == ONCE_PER_10TH_SEC)
+    {
+        /* 10ths interrupt */
+        temp_buff[1] |= 0xF0;
+        repeat = ONCE_PER_SECOND;                   // Select correct RPT value
+    }
+    if (repeat == ONCE_PER_100TH_SEC)
+    {
+        /* 100ths interrupt */
+        temp_buff[1] = 0xFF;
+        repeat = ONCE_PER_SECOND;                   // Select correct RPT value
+    }
+    if (repeat != 0)                                // Don't initiate if repeat = 0
+    {
+        temp = (repeat << 2);                       // Set the RPT field to the value of repeat
+        setreg(AM1805_REG_TIM_CTRL, temp);          // Was previously cleared
+        setreg(AM1805_REG_INTMASK, (intmode << 5)); // Set the alarm interrupt mode
+        setreg(AM1805_REG_INTMASK, 0x60); // Set the alarm interrupt mode
+        am1805_burst_write(temp_buff, 8);           // Execute the burst write
+        setreg(AM1805_REG_INTMASK, 0x04);           // Set the AIE bit        
+    }
+    else
+        setreg(AM1805_REG_INTMASK, 0x60);           // Set IM field to 0x3 (reset value) to minimize current draw
+    
+    return;
+}
+
+void am1805_config_countdown_timer(count_down_range_t range, int32_t period, count_down_repeat_t repeat, interrupt_pin_t pin)
+{
+    uint8_t tm;
+    uint8_t trpt;
+    uint8_t tfs;
+    uint8_t te;
+    char temp;
+    char tctrl;
+    int32_t timer;
+    char oscmode; 
+
+    /* 0 = XT, 1 = RC */
+    am1805_register_read(AM1805_REG_OSCSTATUS, &oscmode, 1);   
+    oscmode = (oscmode & 0x10) ? 1 : 0;
+    
+    /* disable count down timer */
+    if (pin == INTERNAL_FLAG)
+    {
+        te = 0;
+    }
+    else
+    {
+        te = 1;
+        if (repeat == SINGLE_LEVEL_INTERRUPT)
+        {
+            /* Level interrupt */
+            tm = 1;                                     // Level
+            trpt = 0;                                   // No repeat
+            if (range == PERIOD_US)
+            {
+                /* Microseconds */
+                if (oscmode == 0)
+                {
+                    /* XT Mode */
+                    if (period <= 62500)                // Use 4K Hz
+                    {
+                        tfs = 0;
+                        timer = (period * 4096);
+                        timer = timer / 1000000;
+                        timer = timer - 1;
+                    }
+                    else if (period <= 16384000)        // Use 64 Hz
+                    {
+                        tfs = 1;
+                        timer = (period * 64);
+                        timer /= 1000000;
+                        timer = timer - 1;
+                    }
+                    else                                // Use 1 Hz
+                    {
+                        tfs = 2;
+                        timer = period / 1000000;
+                        timer = timer - 1;
+                    }
+                }
+                else
+                {
+                    /* RC Mode */
+                    if (period <= 2000000) {            // Use 128 Hz
+                        tfs = 0;
+                        timer = (period * 128);
+                        timer /= 1000000;
+                        timer = timer - 1;
+                    }
+                    else if (period <= 4000000) {       // Use 64 Hz
+                        tfs = 1;
+                        timer = (period * 64);
+                        timer /= 1000000;
+                        timer = timer - 1;
+                    }
+                    else {                              // Use 1 Hz
+                        tfs = 2;
+                        timer = period / 1000000;
+                        timer = timer - 1;
+                    }
+                }
+            }
+            else
+            {
+                /* Seconds */
+                if (period <= 256)
+                {
+                    /* Use 1 Hz */
+                    tfs = 2;
+                    timer = period - 1;
+                }
+                else
+                {
+                    /* Use 1/60 Hz */
+                    tfs = 3;
+                    timer = period / 60;
+                    timer = timer - 1;
+                }
+            }
+        }
+        else
+        {
+            /* Pulse interrupts */
+            tm = 0;                 // Pulse
+            trpt = repeat & 0x01;   // Set up repeat
+            if (repeat < REPEAT_PLUSE_1_128_SEC)
+            {
+                tfs = 0;
+                if (oscmode == 0)
+                {
+                        timer = (period * 4096);
+                        timer /= 1000000;
+                        timer = timer - 1;
+                }
+                else
+                {
+                        timer = (period * 128);
+                        timer /= 1000000;
+                        timer = timer - 1;
+                }
+            }
+            else if (repeat < REPEAT_PLUSE_1_64_SEC)
+            {
+                tfs = 1;
+                timer = (period * 128);
+                timer /= 1000000;
+                timer = timer - 1;
+            }
+            else if (period <= 256)
+            {
+                /* Use 1 Hz */
+                tfs = 2;
+                timer = period - 1;
+            }
+            else
+            {
+                /* Use 1/60 Hz */
+                tfs = 3;
+                timer = period / 60;
+                timer = timer - 1;
+            }
+        }
+    }
+    
+    am1805_register_read(AM1805_REG_TIM_CTRL, &tctrl, 1);               // Get TCTRL, keep RPT, clear TE
+    tctrl = tctrl & 0x1C;
+    am1805_register_write(AM1805_REG_TIM_CTRL, tctrl);
+
+    tctrl = tctrl | (te * 0x80) | (tm * 0x40) | (trpt * 0x20) | tfs;    // Merge the fields
+    
+    if (pin == PIN_FOUT_nIRQ)                                           // generate nTIRQ interrupt on FOUT/nIRQ (asserted low)
+    {
+         clrreg(AM1805_REG_CTRL2, 0x3);                                 // Clear OUT1S
+    }
+    if (pin == PIN_PSW_nIRQ2)                                           // generate nTIRQ interrupt on PSW/nIRQ2 (asserted low)
+    {
+         am1805_register_read(AM1805_REG_CTRL2, &temp, 1);              // Get OUT2S
+         if ((temp & 0x1C) != 0)
+         {
+             temp = (temp & 0xE3) | 0x14;                               // If OUT2S != 0, set OUT2S to 5
+         }
+         am1805_register_write(AM1805_REG_CTRL2, temp);                 // Write back
+    }
+    if (pin != 0)
+    {
+        clrreg(AM1805_REG_STATUS,0x08);                     // Clear TIM
+        setreg(AM1805_REG_INTMASK,0x08);                    // Set TIE
+        am1805_register_write(AM1805_REG_CDTIM, timer);     // Initialize the timer
+        am1805_register_write(AM1805_REG_TIMINIT, timer);   // Initialize the timer repeat
+        am1805_register_write(AM1805_REG_TIM_CTRL, tctrl);  // Start the timer        
+    }
+    
+    return ;    
+}
+
+/** Parameter:
+ *  timeout - minimum timeout period in 7.8 ms periods (0 to 7)
+ *  mode - sleep mode (nRST modes not available in AM08xx)
+ *      0 => nRST is pulled low in sleep mode
+ *      1 => PSW/nIRQ2 is pulled high on a sleep
+ *      2 => nRST pulled low and PSW/nIRQ2 pulled high on sleep
+ *  error ?returned value of the attempted sleep command
+ *      0 => sleep request accepted, sleep mode will be initiated in timeout seconds
+ *      1 => illegal input values
+ *      2 => sleep request declined, interrupt is currently pending
+ *      3 => sleep request declined, no sleep trigger interrupt enabled
+**/
+void am1805_set_sleep(uint8_t timeout, uint8_t mode)
+{
+    uint8_t slres = 0;
+    char temp = 0;
+
+#if AM1805_DEBUG    
+    am1805_register_read(AM1805_REG_CTRL2, &temp, 1);       // Get SLST bit (temp & 0x08)
+    
+    if ( ( temp & 0x08 ) == 0)
+    {
+        pc.printf("Previous Sleep Failed\r\n");
+    } else {
+        pc.printf("Previous Sleep Successful\r\n");    
+    }
+    clrreg(AM1805_REG_CTRL2,0x08);                     // Clear SLST
+    
+    am1805_register_read(AM1805_REG_CTRL2, &temp, 1);       // Get SLST bit (temp & 0x08)
+    
+    if ( ( temp & 0x08 ) == 0)
+    {
+        pc.printf("Clear Succ\r\n");
+    } else {
+        pc.printf("Clear Fail\r\n");    
+    }
+    clrreg(AM1805_REG_CTRL2,0x08);                     // Clear SLST   
+#endif
+ 
+    if (mode > 0)
+    {
+        /* Sleep to PSW/nIRQ2 */
+        am1805_register_read(AM1805_REG_CTRL2, &temp, 1);   // Read OUT2S
+        temp = (temp & 0xE3) | 0x18;                        // MUST NOT WRITE OUT2S WITH 000
+        am1805_register_write(AM1805_REG_CTRL2, temp);      // Write value to OUT2S
+        slres = 0;
+    } 
+    
+    temp = timeout | (slres << 6) | 0x80;                   // Assemble SLEEP register value
+    am1805_register_write(AM1805_REG_SLEEPCTRL, temp);      // Write to the register    
+
+#if AM1805_DEBUG
+    /* Determine if SLEEP was accepted */
+    am1805_register_read(AM1805_REG_CTRL2, &temp, 1);       // Get SLP bit (temp & 0x80)
+    
+    if ( ( temp & 0x80 ) == 0)
+    {
+        char reg_wdi_value = 0;
+        /* SLEEP did not happen - determine why and return reason. */
+        am1805_register_read(AM1805_REG_INTMASK, &temp, 1);         // Get status register interrupt enables
+        am1805_register_read(AM1805_REG_WDT, &reg_wdi_value, 1);    // Get WDT register
+        if ((( temp & 0x0F ) == 0) & (((reg_wdi_value & 0x7C) == 0) || ((reg_wdi_value & 0x80) == 0x80)))
+        {
+            pc.printf("No trigger interrupts enabled\r\n");
+        }
+        else
+        {
+            pc.printf("Interrupt pending\r\n");
+        }
+    }
+    else
+    {
+        pc.printf("SLEEP request successful\r\n");
+    }
+#endif
+}
diff -r 000000000000 -r 5e0616a05642 AM1805.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AM1805.h	Thu Dec 24 05:25:32 2015 +0000
@@ -0,0 +1,92 @@
+/* AM1805.h , AM1805 Sample code: external RTC module is used by host MCU */
+
+typedef struct
+{
+    uint8_t hundredth;
+    uint8_t second;
+    uint8_t minute;
+    uint8_t hour;
+    uint8_t date;
+    uint8_t weekday;
+    uint8_t month;
+    uint8_t year;
+    uint8_t century;
+    uint8_t mode;
+} time_reg_struct_t;
+
+typedef enum
+{
+    XT1_INTERRUPT = 0x01, /**< WDI input pin will generate XT1 interrupt  */
+    XT2_INTERRUPT = 0x02  /**< EXTI input pin will generate XT2 interrupt */
+} input_interrupt_t;
+
+typedef enum
+{
+    DISABLE_ALARM = 0, /**< disable alarm */
+    ONCE_PER_YEAR = 1, /**< once per year */
+    ONCE_PER_MONTH = 2, /**< once per month */
+    ONCE_PER_WEEK = 3, /**< once per week */
+    ONCE_PER_DAY = 4, /**< once per day */
+    ONCE_PER_HOUR = 5, /**< once per hour */
+    ONCE_PER_MINUTE = 6, /**< once per minute */
+    ONCE_PER_SECOND = 7, /**< once per second */
+    ONCE_PER_10TH_SEC = 8, /**< once per 10th of a second */
+    ONCE_PER_100TH_SEC = 9 /**< once per 100th of a second */
+} alarm_repeat_t;
+
+typedef enum
+{
+    PERIOD_US = 0, /**< period in us */
+    PERIOD_SEC = 1 /**< period in seconds */
+} count_down_range_t;
+
+typedef enum
+{
+    SINGLE_LEVEL_INTERRUPT = 0, /**< single level interrupt */
+    REPEAT_PULSE_1_4096_SEC = 1, /**< a repeated pulsed interrupt, 1/4096 s (XT mode), 1/128 s (RC mode) (range must be 0) */
+    SINGLE_PULSE_1_4096_SEC = 2, /**< a single pulsed interrupt, 1/4096 s (XT mode), 1/128 s (RC mode) (range must be 0) */
+    REPEAT_PLUSE_1_128_SEC = 3, /**< a repeated pulsed interrupt, 1/128 s (range must be 0) */
+    SINGLE_PLUSE_1_128_SEC = 4, /**< a single pulsed interrupt, 1/128 s (range must be 0) */
+    REPEAT_PLUSE_1_64_SEC = 5, /**< a repeated pulsed interrupt, 1/64 s (range must be 1) */
+    SINGLE_PLUSE_1_64_SEC = 6 /**< a single pulsed interrupt, 1/64 s (range must be 1) */    
+} count_down_repeat_t;
+
+typedef enum
+{
+    LEVEL_INTERRUPT = 0x00, /**< level interrupt */
+    PULSE_1_8192_SEC = 0x01, /**< pulse of 1/8192s (XT) or 1/128 s (RC) */
+    PULSE_1_64_SEC = 0x10, /**< pulse of 1/64 s  */
+    PULSE_1_4_SEC = 0x11 /**< pulse of 1/4 s  */
+} interrupt_mode_t;
+
+typedef enum
+{
+    INTERNAL_FLAG = 0, /**< internal flag only */
+    PIN_FOUT_nIRQ = 1, /**< generate the interrupt on FOUT/nIRQ */
+    PIN_PSW_nIRQ2 = 2, /**< generate the interrupt on PSW/nIRQ2 */
+    PIN_nTIRQ = 3      /**< generate the interrupt on nTIRQ (not apply to ALARM) */
+} interrupt_pin_t;
+
+bool am1805_init(void);
+
+void am1805_register_read(char register_address, char *destination, uint8_t number_of_bytes);
+
+void am1805_register_write(char register_address, uint8_t value);
+
+void am1805_burst_write(uint8_t *value, uint8_t number_of_bytes);
+
+uint8_t am1805_read_ram(uint8_t address);
+
+void am1805_write_ram(uint8_t address, uint8_t data);
+
+void am1805_config_input_interrupt(input_interrupt_t index_Interrupt);
+
+void am1805_set_time(time_reg_struct_t time_regs);
+
+void am1805_get_time(time_reg_struct_t *time_regs);
+
+void am1805_config_alarm(time_reg_struct_t time_regs, alarm_repeat_t repeat, interrupt_mode_t intmode, interrupt_pin_t pin);
+
+void am1805_config_countdown_timer(count_down_range_t range, int32_t period, count_down_repeat_t repeat, interrupt_pin_t pin);
+
+void am1805_set_sleep(uint8_t timeout, uint8_t mode);
\ No newline at end of file