ds1307: initial implementation of the ds1307 RTC

Signed-off-by: Jon Trulson <jtrulson@ics.com>
Signed-off-by: Sarah Knepper <sarah.knepper@intel.com>
This commit is contained in:
Jon Trulson 2014-12-04 13:50:13 -07:00 committed by Sarah Knepper
parent 66d39af6c5
commit 02156d11c8
8 changed files with 567 additions and 0 deletions

View File

@ -54,6 +54,7 @@ add_executable (am2315-example am2315.cxx)
add_executable (itg3200-example itg3200.cxx)
add_executable (enc03r-example enc03r.cxx)
add_executable (adc121c021-example adc121c021.cxx)
add_executable (ds1307-example ds1307.cxx)
include_directories (${PROJECT_SOURCE_DIR}/src/hmc5883l)
include_directories (${PROJECT_SOURCE_DIR}/src/grove)
@ -95,6 +96,7 @@ include_directories (${PROJECT_SOURCE_DIR}/src/am2315)
include_directories (${PROJECT_SOURCE_DIR}/src/itg3200)
include_directories (${PROJECT_SOURCE_DIR}/src/enc03r)
include_directories (${PROJECT_SOURCE_DIR}/src/adc121c021)
include_directories (${PROJECT_SOURCE_DIR}/src/ds1307)
target_link_libraries (hmc5883l-example hmc5883l ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries (groveled-example grove ${CMAKE_THREAD_LIBS_INIT})
@ -152,3 +154,4 @@ target_link_libraries (am2315-example am2315 ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries (itg3200-example itg3200 ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries (enc03r-example enc03r ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries (adc121c021-example adc121c021 ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries (ds1307-example ds1307 ${CMAKE_THREAD_LIBS_INIT})

77
examples/ds1307.cxx Normal file
View File

@ -0,0 +1,77 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2014 Intel Corporation.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <unistd.h>
#include <iostream>
#include "ds1307.h"
using namespace std;
void printTime(upm::DS1307 *rtc)
{
cout << "The time is: " <<
rtc->month << "/" << rtc->dayOfMonth << "/" << rtc->year << " "
<< rtc->hours << ":" << rtc->minutes << ":" << rtc->seconds;
if (rtc->amPmMode)
cout << (rtc->pm) ? " PM " : " AM ";
cout << endl;
cout << "Clock is in " << ((rtc->amPmMode) ? "AM/PM mode" : "24hr mode")
<< endl;
}
int
main(int argc, char **argv)
{
//! [Interesting]
// Instantiate a DS1037 on I2C bus 0
upm::DS1307 *rtc = new upm::DS1307(0);
// always do this first
cout << "Loading the current time... " << endl;
if (!rtc->loadTime())
{
cerr << "rtc->loadTime() failed." << endl;
return 0;
}
printTime(rtc);
// set the year as an example
cout << "setting the year to 50" << endl;
rtc->year = 50;
rtc->setTime();
// reload the time and print it
rtc->loadTime();
printTime(rtc);
//! [Interesting]
delete rtc;
return 0;
}

View File

@ -0,0 +1,68 @@
/*jslint node:true, vars:true, bitwise:true, unparam:true */
/*jshint unused:true */
/*global */
/*
* Author: Zion Orent <zorent@ics.com>
* Copyright (c) 2014 Intel Corporation.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
// Load RTC Clock module for Grove - RTC clock
var ds1307 = require('jsupm_ds1307');
// load this on i2c bus 0
var myRTCClockObj = new ds1307.DS1307(0);
// always do this first
console.log("Loading the current time... ");
var result = myRTCClockObj.loadTime();
if (!result)
{
console.log("myRTCClockObj.loadTime() failed.");
process.exit(1);
}
printTime(myRTCClockObj);
// set the year as an example
console.log("setting the year to 50");
myRTCClockObj.year = 50;
myRTCClockObj.setTime();
// reload the time and print it
myRTCClockObj.loadTime();
printTime(myRTCClockObj);
function printTime(RTCObj)
{
var timeStr = "The time is: " +
RTCObj.month + "/" + RTCObj.dayOfMonth + "/" + RTCObj.year + " " +
RTCObj.hours + ":" + RTCObj.minutes + ":" + RTCObj.seconds;
if (RTCObj.amPmMode)
timeStr += (RTCObj.pm ? " PM " : " AM ");
console.log(timeStr);
console.log("Clock is in " +
(RTCObj.amPmMode ? "AM/PM mode" : "24hr mode"));
}

View File

@ -0,0 +1,5 @@
set (libname "ds1307")
set (libdescription "upm ds1307 RTC module")
set (module_src ${libname}.cxx)
set (module_h ${libname}.h)
upm_module_init()

207
src/ds1307/ds1307.cxx Normal file
View File

@ -0,0 +1,207 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2014 Intel Corporation.
*
* Adapted from Seeed Studio library:
* https://github.com/Seeed-Studio/RTC_DS1307
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <iostream>
#include <string>
#include "ds1307.h"
using namespace upm;
using namespace std;
DS1307::DS1307(int bus)
{
// setup our i2c link
m_i2c = mraa_i2c_init(bus);
mraa_result_t ret = mraa_i2c_address(m_i2c, DS1307_I2C_ADDR);
if (ret != MRAA_SUCCESS)
cerr << "DS1307: Could not initialize i2c bus. " << endl;
}
DS1307::~DS1307()
{
mraa_i2c_stop(m_i2c);
}
mraa_result_t DS1307::writeBytes(uint8_t reg, uint8_t *buffer, unsigned int len)
{
if (!len || !buffer)
return MRAA_ERROR_INVALID_PARAMETER;
// create a buffer 1 byte larger than the supplied buffer,
// store the register in the first byte
uint8_t buf2[len + 1];
buf2[0] = reg;
// copy in the buffer after the reg byte
for (int i=1; i<(len + 1); i++)
buf2[i] = buffer[i-1];
mraa_i2c_address(m_i2c, DS1307_I2C_ADDR);
return mraa_i2c_write(m_i2c, buf2, len + 1);
}
uint8_t DS1307::readBytes(uint8_t reg, uint8_t *buffer, unsigned int len)
{
if (!len || !buffer)
return 0;
mraa_i2c_address(m_i2c, DS1307_I2C_ADDR);
mraa_i2c_write_byte(m_i2c, reg);
return mraa_i2c_read(m_i2c, buffer, len);
}
bool DS1307::loadTime()
{
// read the first 7 registers
uint8_t buffer[7];
int bytesRead = readBytes(0, buffer, 7);
if (bytesRead != 7)
{
// problem
cerr << __FUNCTION__ << ": read " << bytesRead <<
" bytes, expected 7." << endl;
return false;
}
// We need to mask some control bits off of some of these values
// and convert the result to decimal from BCD. We also need to account
// for format (AM/PM or 24hr), and if AM/PM, whether PM should be set.
// first bit here is the oscillator enable/disable bit
seconds = bcdToDec(buffer[0] & 0x7f);
minutes = bcdToDec(buffer[1]);
// check AM/PM or 24hr mode
if (buffer[2] & 0x40)
{
// We are in AM/PM mode
hours = bcdToDec(buffer[2] & 0x1f);
amPmMode = true;
pm = (buffer[2] & 0x20) ? true : false;
}
else
{
// 24hr mode
hours = bcdToDec(buffer[2] & 0x3f);
amPmMode = false;
pm = false;
}
dayOfWeek = bcdToDec(buffer[3]);
dayOfMonth = bcdToDec(buffer[4]);
month = bcdToDec(buffer[5]);
year = bcdToDec(buffer[6]);
return true;
}
bool DS1307::setTime()
{
uint8_t buffer[7];
// seconds
// we need to read in seconds first to preserve the osc enable bit
uint8_t tmpbuf;
readBytes(0, &tmpbuf, 1);
buffer[0] = decToBcd(seconds) | (tmpbuf & 0x80);
// minutes
buffer[1] = decToBcd(minutes);
// hours
if (amPmMode)
{
buffer[2] = decToBcd(hours) | 0x40;
if (pm)
buffer[2] |= 0x20;
}
else
buffer[2] = decToBcd(hours);
// day of week
buffer[3] = decToBcd(dayOfWeek);
// day of month
buffer[4] = decToBcd(dayOfMonth);
// month
buffer[5] = decToBcd(month);
// year
buffer[6] = decToBcd(year);
return writeBytes(0, buffer, 7);
}
mraa_result_t DS1307::enableClock()
{
// the oscillator enable bit is the high bit of reg 0
// so read it, clear it, and write it back.
uint8_t buf;
readBytes(0, &buf, 1);
buf &= ~0x80;
return writeBytes(0, &buf, 1);
}
mraa_result_t DS1307::disableClock()
{
// the oscillator enable bit is the high bit of reg 0
// so read it, set it, and write it back.
uint8_t buf;
readBytes(0, &buf, 1);
buf |= 0x80;
return writeBytes(0, &buf, 1);
}
// Convert decimal to BCD
uint8_t DS1307::decToBcd(unsigned int val)
{
return ( (val/10*16) + (val%10) );
}
// Convert BCD to decimal
unsigned int DS1307::bcdToDec(uint8_t val)
{
return ( (val/16*10) + (val%16) );
}

186
src/ds1307/ds1307.h Normal file
View File

@ -0,0 +1,186 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2014 Intel Corporation.
*
* Adapted from Seeed Studio library:
* https://github.com/Seeed-Studio/RTC_DS1307
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <string>
#include <mraa/i2c.h>
#define DS1307_I2C_BUS 0
#define DS1307_I2C_ADDR 0x68
// Days of the week
#define DS1307_DAY_MON 1
#define DS1307_DAY_TUE 2
#define DS1307_DAY_WED 3
#define DS1307_DAY_THU 4
#define DS1307_DAY_FRI 5
#define DS1307_DAY_SAT 6
#define DS1307_DAY_SUN 7
namespace upm {
/**
* @brief C++ API for the DS1307 Real Time CLock
*
* UPM module for the DS1307 based RTC. The clock can provide information
* about the seconds, minutes, hours, day of the week, day of the month,
* month, and year. It can operate in either 24-hour or 12-hour format.
*
* This device can also output a square wave at 1Khz, 4Khz, 8Khz, and 32Khz.
* However, this capability is not implemented in this module.
*
* @ingroup i2c ds1307 RTC
* @snippet ds1307.cxx Interesting
*/
class DS1307 {
public:
/**
* ds1307 Real Time Clock constructor
*
* @param bus i2c bus to use
*/
DS1307(int bus);
/**
* DS1307 Destructor
*/
~DS1307();
/**
* Load all of the time values
*
* @return True if time data loaded successfully
*/
bool loadTime();
/**
* Set the time. You should call loadTime() beforehand to
* maintain consistency
*
* @return True if time saved successfully
*/
bool setTime();
/**
* Enable the oscillator on the clock.
*
* @return 0 (MRAA_SUCCESS) if successful; non-zero otherwise
*/
mraa_result_t enableClock();
/**
* Disable the oscillator on the clock. This will prevent the clock
* from updating any time/date values
*
* @return 0 (MRAA_SUCCESS) if successful; non-zero otherwise
*/
mraa_result_t disableClock();
/**
* Write value(s) into registers
*
* @param reg register location to start writing into
* @param buffer buffer for data storage
* @param len number of bytes to write
* @return 0 (MRAA_SUCCESS) if successful; non-zero otherwise
*/
mraa_result_t writeBytes(uint8_t reg, uint8_t *buffer, unsigned int len);
/**
* Read value(s) from registers
*
* @param reg register location to start reading from
* @param buffer buffer for data storage
* @param len number of bytes to read
* @return number of bytes read
*/
uint8_t readBytes(uint8_t reg, uint8_t *buffer, unsigned int len);
/**
* Convert a BCD value into decimal
*
* @param val BCD value to convert
* @return the converted value in decimal
*/
unsigned int bcdToDec(uint8_t val);
/**
* Convert a decimal value into BCD
*
* @param val decimal value to convert
* @return the converted value in BCD
*/
uint8_t decToBcd(unsigned int val);
// These variables store the time data loaded with loadTime(), and
// will be the source of data when setTime() is called. It is a
// good idea call loadTime() to setup the current values before
// calling setTime() to ensure RTC data is consistent
/**
* holds the seconds
*/
unsigned int seconds;
/**
* holds the minutes
*/
unsigned int minutes;
/**
* holds the hours, 1-12 in am/pm mode, 0-23 otherwise
*/
unsigned int hours;
/**
* holds the day of the week, 1-7 where 1 is Sunday
*/
unsigned int dayOfWeek;
/**
* holds the day of the month, 1-31
*/
unsigned int dayOfMonth;
/**
* holds the month, 1-12
*/
unsigned int month;
/**
* holds the year, 0-99
*/
unsigned int year;
/**
* True if in AM/PM mode, false if 24h format.
*/
bool amPmMode;
/**
* If in AmPmMode (12-hr), then this is true if it's PM, clear if AM
*/
bool pm;
private:
mraa_i2c_context m_i2c;
};
}

View File

@ -0,0 +1,8 @@
%module jsupm_ds1307
%include "../upm.i"
%{
#include "ds1307.h"
%}
%include "ds1307.h"

13
src/ds1307/pyupm_ds1307.i Normal file
View File

@ -0,0 +1,13 @@
%module pyupm_ds1307
%include "../upm.i"
%feature("autodoc", "3");
#ifdef DOXYGEN
%include "ds1307_doc.i"
#endif
%include "ds1307.h"
%{
#include "ds1307.h"
%}