This class provides simplified I2C access to a MAXIM DS130x Real-Time Clock device, even if the LPC1768 has an embedded RTC module. My objective is to share the same RTC with Microchip 18F MCU.

Files at this revision

API Documentation at this revision

Comitter:
Yann
Date:
Fri Feb 11 10:16:20 2011 +0000
Parent:
0:a1b58e3c9fdb
Commit message:
V0.0.0.2

Changed in this revision

DS130x_I2C.cpp Show annotated file Show diff for this revision Revisions of this file
DS130x_I2C.h Show annotated file Show diff for this revision Revisions of this file
diff -r a1b58e3c9fdb -r 834e9897e269 DS130x_I2C.cpp
--- a/DS130x_I2C.cpp	Wed Feb 09 13:43:21 2011 +0000
+++ b/DS130x_I2C.cpp	Fri Feb 11 10:16:20 2011 +0000
@@ -54,12 +54,12 @@
     DEBUG("CDS130X_I2C::Initialize: Set date format")
     // 1. Read hours
     unsigned char hoursRegister = 0xff;
-    if (Read(CDS130X_I2C::HoursAddress, &hoursRegister) == (unsigned char)0) {
+    if (Read(CDS130X_I2C::HoursAddress, &hoursRegister)) {
         DEBUG("CDS130X_I2C::Initialize: hours:%x", hoursRegister)
         // 2. Set bit 6 to 0
         hoursRegister &= 0xbf; // 1011 1111
         // 3. Write new value
-        if (Write(CDS130X_I2C::HoursAddress, hoursRegister)) {
+        if (!Write(CDS130X_I2C::HoursAddress, hoursRegister)) {
             DEBUG_ERROR("CDS130X_I2C::Initialize: Failed to set date format")
         }
     } else {
@@ -110,7 +110,7 @@
 } // End of method CDS130X_I2C::ControlClock
 
 bool CDS130X_I2C::Read(const RegisterEnum p_address, unsigned char * p_byte, const CDS130X_I2C::RegisterFormatEnum p_format) {
-    DEBUG_ENTER("CDS130X_I2C::Read")
+    DEBUG_ENTER("CDS130X_I2C::Read: %02x - %x", p_address, p_format)
 
     // 1. Read seconds
     char i2cBuffer[1];
@@ -122,6 +122,7 @@
         wait(0.02);
 
         // 3. Format convertion
+        DEBUG_ENTER("CDS130X_I2C::Read: check %02x - %02x", p_format, Binary)
         if (p_format == CDS130X_I2C::Binary) {
             switch ((RegisterEnum)p_address) {
                 case CDS130X_I2C::SecondsAddress:
@@ -135,7 +136,7 @@
                     *p_byte = ConvertBCDToHex(*p_byte & 0x3f); // Convert hex to BCD - See datasheet - Table 2. Timekeeper Registers
                     break;
                 case CDS130X_I2C::DayOfWeekAddress:
-                    *p_byte = ConvertBCDToHex(*p_byte & 0x03); // Convert hex to BCD - See datasheet - Table 2. Timekeeper Registers
+                    *p_byte = ConvertBCDToHex(*p_byte & 0x07); // Convert hex to BCD - See datasheet - Table 2. Timekeeper Registers
                     break;
                 case CDS130X_I2C::MonthAddress:
                     *p_byte = ConvertBCDToHex(*p_byte & 0x1f); // Convert hex to BCD - See datasheet - Table 2. Timekeeper Registers
@@ -146,17 +147,16 @@
             } // End of 'switch' statement
         } // else nothing to do
 
-        DEBUG_LEAVE("CDS130X_I2C::Read %d", (int)*p_byte)
+        DEBUG_LEAVE("CDS130X_I2C::Read %d/%02x", (int)*p_byte, *p_byte)
         return true;
     }
 
-
     DEBUG_LEAVE("CDS130X_I2C::Read (false)")
     return false;
 } // End of method CDS130X_I2C::Read
 
 bool CDS130X_I2C::Write(const RegisterEnum p_address, const unsigned char p_byte, const CDS130X_I2C::RegisterFormatEnum p_format) {
-    DEBUG_ENTER("CDS130X_I2C::Write")
+    DEBUG_ENTER("CDS130X_I2C::Write: %02x - %d - %x", p_address, (int)p_byte, p_format)
 
     // 1. Format convertion
     unsigned char value = p_byte;
@@ -173,7 +173,7 @@
                 value = ConvertHexToBCD(p_byte) & 0x3f; // Convert hex to BCD - See datasheet - Table 2. Timekeeper Registers
                 break;
             case CDS130X_I2C::DayOfWeekAddress:
-                value = ConvertHexToBCD(p_byte) & 0x03; // Convert hex to BCD - See datasheet - Table 2. Timekeeper Registers
+                value = ConvertHexToBCD(p_byte) & 0x07; // Convert hex to BCD - See datasheet - Table 2. Timekeeper Registers
                 break;
             case CDS130X_I2C::MonthAddress:
                 value = ConvertHexToBCD(p_byte) & 0x1f; // Convert hex to BCD - See datasheet - Table 2. Timekeeper Registers
@@ -182,6 +182,7 @@
                 value = ConvertHexToBCD(p_byte); // Convert hex to BCD - See datasheet - Table 2. Timekeeper Registers
                 break;
         } // End of 'switch' statement
+        DEBUG("CDS130X_I2C::Write: Convert binary %d into bcd %02x", (int)p_byte, value)
     } // else nothing to do
 
     // 2. Read seconds
@@ -210,7 +211,7 @@
     // Fill struct tm;
     struct tm t = {0};
     char wday[4] = {0};
-    scanf("%s %02d %02d %02d:%02d:%02d %04d", /* Www MM dd hh:mm:ss yyyy */
+    sscanf(p_utcTime.c_str(), "%s %2d %2d %2d:%2d:%2d %4d", /* Www MM dd hh:mm:ss yyyy, e.g. Thu 02 10 07:13:29 2011 */
           wday,
           &t.tm_mon,
           &t.tm_mday,
@@ -218,17 +219,18 @@
           &t.tm_min,
           &t.tm_sec,
           &t.tm_year);
+    DEBUG("CDS130X_I2C::SetTime: wday=%s - %d - %d - %d - %d - %d", wday, t.tm_mon, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec);
 
-    DEBUG("CDS130X_I2C::SetTime: wday=%s - tm_wday=%d", wday, _dayOfWeek.find_first_of(wday) / 3);
-    t.tm_wday = _dayOfWeek.find_first_of(wday) / 3;
+    t.tm_wday = (_dayOfWeek.find(wday) / 3) + 1;
+    DEBUG("CDS130X_I2C::SetTime: wday=%s - _dayOfWeek:%s - tm_wday=%d", wday, _dayOfWeek.c_str(), t.tm_wday);
 
-    Write(CDS130X_I2C::SecondsAddress, t.tm_sec, Binary);
-    Write(CDS130X_I2C::MinutesAddress, t.tm_min, Binary);
-    Write(CDS130X_I2C::HoursAddress, t.tm_hour, Binary);
-    Write(CDS130X_I2C::DayOfWeekAddress, t.tm_wday, Binary);
-    Write(CDS130X_I2C::DayAddress, t.tm_mday, Binary);
-    Write(CDS130X_I2C::MonthAddress, t.tm_mon, Binary);
-    Write(CDS130X_I2C::YearAddress, t.tm_year, Binary);
+    Write(CDS130X_I2C::SecondsAddress, t.tm_sec, CDS130X_I2C::Binary);
+    Write(CDS130X_I2C::MinutesAddress, t.tm_min, CDS130X_I2C::Binary);
+    Write(CDS130X_I2C::HoursAddress, t.tm_hour, CDS130X_I2C::Binary);
+    Write(CDS130X_I2C::DayOfWeekAddress, t.tm_wday, CDS130X_I2C::Binary);
+    Write(CDS130X_I2C::DayAddress, t.tm_mday, CDS130X_I2C::Binary);
+    Write(CDS130X_I2C::MonthAddress, t.tm_mon, CDS130X_I2C::Binary);
+    Write(CDS130X_I2C::YearAddress, t.tm_year - 1900, CDS130X_I2C::Binary); // Years since 1900: 2011 becomes 111
 
     return true;
 } // End of method CDS130X_I2C::SetTime
@@ -236,31 +238,23 @@
 struct tm CDS130X_I2C::GetTime() {
     DEBUG_ENTER("CDS130X_I2C::GetTime")
 
-    struct tm t;
+    struct tm t = {0};
     unsigned char value;
     // Setup time structure from RTC
-    Read(CDS130X_I2C::SecondsAddress, &value, Binary);
-    t.tm_sec = value;
-    Read(CDS130X_I2C::MinutesAddress, &value, Binary);
-    t.tm_min = value;
-    Read(CDS130X_I2C::HoursAddress, &value, Binary);
-    t.tm_hour = value;
-    Read(CDS130X_I2C::DayOfWeekAddress, &value, Binary);
-    t.tm_wday = value;
-    Read(CDS130X_I2C::DayAddress, &value, Binary);
-    t.tm_mday = value;
-    Read(CDS130X_I2C::MonthAddress, &value, Binary);
-    t.tm_mon = value;
-    Read(CDS130X_I2C::YearAddress, &value, Binary);
-    t.tm_year = value;
-    DEBUG("CDS130X_I2C::GetTime: %02d %02d %02d %02d:%02d:%02d %04d", /* ww mm dd hh:mm:ss yyyy */
-          t.tm_wday,
-          t.tm_mon,
-          t.tm_mday,
-          t.tm_hour,
-          t.tm_min,
-          t.tm_sec,
-          t.tm_year);
+    Read(CDS130X_I2C::SecondsAddress, &value, CDS130X_I2C::Binary);
+    t.tm_sec = (int)value;
+    Read(CDS130X_I2C::MinutesAddress, &value, CDS130X_I2C::Binary);
+    t.tm_min = (int)value;
+    Read(CDS130X_I2C::HoursAddress, &value, CDS130X_I2C::Binary);
+    t.tm_hour = (int)value;
+    Read(CDS130X_I2C::DayOfWeekAddress, &value, CDS130X_I2C::Binary);
+    t.tm_wday = (int)value - 1;
+    Read(CDS130X_I2C::DayAddress, &value, CDS130X_I2C::Binary);
+    t.tm_mday = (int)value;
+    Read(CDS130X_I2C::MonthAddress, &value, CDS130X_I2C::Binary);
+    t.tm_mon = (int)value;
+    Read(CDS130X_I2C::YearAddress, &value, CDS130X_I2C::Binary);
+    t.tm_year = (int)value; // Years since 1900: 111 means 2011
 
     DEBUG_LEAVE("CDS130X_I2C::GetTime")
     return t;
@@ -294,7 +288,7 @@
 } // End of method CDS130X_I2C::WriteMemory
 
 bool CDS130X_I2C::WriteMemory(const unsigned char p_address, const short p_short, const CDS130X_I2C::Mode p_mode) {
-    DEBUG_ENTER("CDS130X_I2C::WriteMemory (short): Memory address:0x%02x, Mode:%d", p_address, p_mode)
+    DEBUG_ENTER("CDS130X_I2C::WriteMemory (short): Memory address:0x%02x, p_short:%04x, Mode:%d", p_address, p_short, p_mode)
 
     // 1.Prepare buffer
     char i2cBuffer[3]; // Memory address + one short (2 bytes)
@@ -309,7 +303,7 @@
         i2cBuffer[1] = (unsigned char)((unsigned char)p_short & 0xff);
         i2cBuffer[2] = (unsigned char)(p_short >> 8);
     }
-    DEBUG("CDS130X_I2C::WriteMemory (byte): value=0x%02x%02x", i2cBuffer[1], i2cBuffer[2])
+    DEBUG("CDS130X_I2C::WriteMemory (short): value=0x%02x%02x", i2cBuffer[1], i2cBuffer[2])
 
     // 2. Send I2C start + I2C address + Memory Address + Datas + I2C stop
     int result = write(_slaveAddress, i2cBuffer, 3);
@@ -320,7 +314,7 @@
 } // End of method CDS130X_I2C::WriteMemory
 
 bool CDS130X_I2C::WriteMemory(const unsigned char p_address, const int p_int, const CDS130X_I2C::Mode p_mode) {
-    DEBUG_ENTER("CDS130X_I2C::WriteMemory (int): Memory address:0x%02x, Mode:%d", p_address, p_mode)
+    DEBUG_ENTER("CDS130X_I2C::WriteMemory (int): Memory address:0x%02x, p_int:%d, Mode:%d", p_address, p_int, p_mode)
 
     // 1.Prepare buffer
     char i2cBuffer[5]; // Memory address + one integer (4 bytes)
@@ -339,7 +333,7 @@
         i2cBuffer[3] = (unsigned char)(p_int >> 16);
         i2cBuffer[4] = (unsigned char)(p_int >> 24);
     }
-    DEBUG("CDS130X_I2C::WriteMemory (byte): value=0x%02x%02x%02x%02x", i2cBuffer[1], i2cBuffer[2], i2cBuffer[3], i2cBuffer[4])
+    DEBUG("CDS130X_I2C::WriteMemory (int): value=0x%02x%02x%02x%02x", i2cBuffer[1], i2cBuffer[2], i2cBuffer[3], i2cBuffer[4])
 
     // 2. Send I2C start + I2C address + Memory Address + Datas + I2C stop
     int result = write(_slaveAddress, i2cBuffer, 5);
@@ -491,9 +485,9 @@
 
     // 1.Prepare buffer
     unsigned char address = CDS130X_I2C::BaseMemoryAddress + p_address;
-    int length;
+    unsigned char length;
     if (p_readLengthFirst) {
-        ReadMemory(address, &length); // Read the length in big endian mode
+        ReadMemory(address, (unsigned char *)&length); // Read the length in big endian mode
         address += 1; // Skip the length value
         length -= 1; // length is the size of (string length + string)
     } else {
@@ -528,19 +522,19 @@
 } // End of method CDS130X_I2C::ReadMemory
 
 bool CDS130X_I2C::ReadMemory(const unsigned char p_address, std::string & p_string, const bool p_readLengthFirst, const int p_length2write) {
-    DEBUG_ENTER("CDS130X_I2C::ReadMemory (string): Memory address:0x%02x, readLength:%01x, Length:%d", p_address, p_readLengthFirst, p_length2write)
+    DEBUG_ENTER("CDS130X_I2C::ReadMemory (string): Memory address:0x%02x, readLength:%x, Length:%d", p_address, p_readLengthFirst, p_length2write)
 
     // 1.Prepare buffer
     unsigned char address = CDS130X_I2C::BaseMemoryAddress + p_address;
-    int length;
+    unsigned char length;
     if (p_readLengthFirst) { // The string was stored with its length
-        if (!ReadMemory(address, &length)) { // Read the length in big endian mode
+        if (!ReadMemory(p_address, (unsigned char *)&length)) { // Read the length in big endian mode
             DEBUG_ERROR("CDS130X_I2C::ReadMemory (string): Failed to read length")
             return false;
         }
         wait(0.02);
-        address += 4; // Skip the length value size
-        length -= 4; // length is the size of (string length + string)
+        address += 1; // Skip the length value size
+        length -= 1; // length is the size of (string length + string)
     } else { // The string length is provided by p_length2write parameter
         if (p_length2write == -1) {
             length = p_string.size();
@@ -552,14 +546,12 @@
     DEBUG("CDS130X_I2C::ReadMemory (string): Length=%d", length)
 
     // 2. Memory address
-    char i2cBuffer[2];
+    char i2cBuffer[1];
     i2cBuffer[0] = address;
     DEBUG("CDS130X_I2C::ReadMemory (string): pI2CBuffer[0]: 0x%02x", i2cBuffer[0])
-    i2cBuffer[1] = (unsigned char)((unsigned char)address & 0xff);
-    DEBUG("CDS130X_I2C::ReadMemory (string): pI2CBuffer[1]: 0x%02x", i2cBuffer[1])
 
     // 3. Send I2C start + memory address
-    if (write(_slaveAddress, i2cBuffer, 2, true) == 0) {
+    if (write(_slaveAddress, i2cBuffer, 1, true) == 0) {
         // 4. Read data + I2C stop
         char buffer[length];
         int result = read(_slaveAddress, (char *)buffer, length);
@@ -581,7 +573,7 @@
 
     DEBUG("CDS130X_I2C::DumpMemoryArea: Reading datas...");
     std::vector<unsigned char> datas(p_count);
-    if (!ReadMemory((unsigned char)CDS130X_I2C::BaseMemoryAddress + p_address, datas, false)) { // Read bytes, including the lenght indication, buffer size is not set before the call
+    if (!ReadMemory(p_address, datas, false)) { // Read bytes, including the lenght indication, buffer size is not set before the call
 #ifdef __DEBUG
         DEBUG_FATAL("CDS130X_I2C::DumpMemoryArea: read failed")
 #else // __DEBUG
diff -r a1b58e3c9fdb -r 834e9897e269 DS130x_I2C.h
--- a/DS130x_I2C.h	Wed Feb 09 13:43:21 2011 +0000
+++ b/DS130x_I2C.h	Fri Feb 11 10:16:20 2011 +0000
@@ -29,7 +29,7 @@
 #include "Debug.h" // Include mbed header + debug primitives. See DebugLibrary
 
 namespace DS130X_I2C {
-    /** This class provides simplified I2C access to a MAXIM DS130x Real-Time Clock device. V0.0.0.1
+    /** This class provides simplified I2C access to a MAXIM DS130x Real-Time Clock device. V0.0.0.2
      *
      * A typical use case should be the Mbed which acts as a time server with an ethernet connection, it synchronyzes a RTC circuit for all other module (Microchip/ATiny MCUs).
      *
@@ -143,7 +143,16 @@
          * @return The packed BCD value
          */
         inline unsigned char ConvertBCDToHex(const unsigned char p_bcdValue) {
-            return (unsigned char)((unsigned char)(p_bcdValue >> 4) * 10) + (unsigned char)(p_bcdValue & 0x0f);
+            /*DEBUG("ConvertBCDToHex: %02x - %02x - %02x - %02x - %d", 
+                p_bcdValue, 
+                (unsigned char)(p_bcdValue >> 4), 
+                (unsigned char)((unsigned char)(p_bcdValue >> 4) * 10), 
+                (unsigned char)(p_bcdValue & 0x0f), 
+                (int)(
+                    (unsigned char)((unsigned char)(p_bcdValue >> 4) * 10) | (unsigned char)(p_bcdValue & 0x0f)
+                 )
+            )*/
+            return (unsigned char)((unsigned char)(p_bcdValue >> 4) * 10) | (unsigned char)(p_bcdValue & 0x0f);
         }
 
         /** This methods converts an hexadecimal value < 99 into a packed BCD (e.g. 0x20 -> 0x32)
@@ -152,7 +161,8 @@
          * @return The packed BCD value
          */
         inline unsigned char ConvertHexToBCD(const unsigned char p_hexaValue) {
-            return (p_hexaValue / 10) << 4 + (p_hexaValue % 10);
+            //DEBUG("ConvertHexToBCD: %02x - %02x - %02x", p_hexaValue, (unsigned char)(p_hexaValue / 10 << 4), (unsigned char)(p_hexaValue % 10))
+            return (unsigned char)(p_hexaValue / 10 << 4) | (unsigned char)(p_hexaValue % 10);
         }
 
         /** Restart the clock