copy from mbed
Revision 0:b7ac3add7d83, committed 2018-03-02
- Comitter:
- irsanjul
- Date:
- Fri Mar 02 07:01:17 2018 +0000
- Child:
- 1:41dd31bbbe6d
- Commit message:
- copy from mbed
Changed in this revision
PCF8523.cpp | Show annotated file Show diff for this revision Revisions of this file |
PCF8523.h | Show annotated file Show diff for this revision Revisions of this file |
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PCF8523.cpp Fri Mar 02 07:01:17 2018 +0000 @@ -0,0 +1,226 @@ +#include "mbed.h" +#include "PCF8523.h" + +extern Serial dbg; + +PCF8523::PCF8523(PinName sda, PinName scl) : i2c (sda, scl) +{ + i2c.frequency(100000); +} + +PCF8523::~PCF8523() +{ + +} + +bool PCF8523::write(char adr, char data) +{ + w[0] = adr; + w[1] = data; + if (i2c.write(address, w, 2) != 0) return 0; + + return true; +} + +char PCF8523::read(char adr) +{ + char start = adr; + if (i2c.write(address, &start, 1, true) != 0) return 0; + if (i2c.read(address, r, 1) != 0) return 0; + + return r[0]; +} + +time_t PCF8523::now() +{ + struct tm now; + + char buffer[6]; + + buffer [0] = read(SEC); + buffer [1] = read(MIN); + buffer [2] = read(HOUR); + buffer [3] = read(DAY); + buffer [4] = read(MONTH); + buffer [5] = read(YEAR); + + now.tm_sec = bcdToDecimal(buffer[0] & 0x7F); + now.tm_min = bcdToDecimal(buffer[1] & 0x7F); + now.tm_hour = bcdToDecimal(buffer[2] & 0x3F); + now.tm_mday = bcdToDecimal(buffer[3] & 0x3F); + now.tm_mon = bcdToDecimal(buffer[4] & 0x1F) - 1; + now.tm_year = bcdToDecimal(buffer[5] & 0xFF) + 2000 - 1900; + + return mktime(&now); +} + +bool PCF8523::set_time(time_t time) +{ + struct tm *now; + char buffer[9]; + + now = localtime(&time); + + buffer[0] = decimalToBcd(now->tm_sec) & 0x7F; // VL = 0 + buffer[1] = decimalToBcd(now->tm_min) & 0x7F; + buffer[2] = decimalToBcd(now->tm_hour) & 0x3F; + buffer[3] = decimalToBcd(now->tm_mday) & 0x3F; + buffer[4] = now->tm_wday + 1; + buffer[5] = decimalToBcd(now->tm_mon+1) & 0x1F; + buffer[6] = decimalToBcd(now->tm_year + 1900 - 2000); + + if(!write(SEC, buffer[0]))return 0; + if(!write(MIN, buffer[1]))return 0; + if(!write(HOUR, buffer[2]))return 0; + if(!write(DAY, buffer[3]))return 0; + if(!write(WDAY, buffer[4]))return 0; + if(!write(MONTH, buffer[5]))return 0; + if(!write(YEAR, buffer[6]))return 0; + + return true; +} + +bool PCF8523::IsConnected() +{ + bool ok = false; + + i2c.start(); + i2c.stop(); + + if (i2c.read(address, &data[0], 1) != 0) + { + dbg.printf("PCF8523 is not detected\r\n"); + ok = false; + } + else + { + dbg.printf("PCF8523 is detected\r\n"); + ok = true; + } + + data[0] = 0; + i2c.start(); + i2c.stop(); + + return ok; +} + +bool PCF8523::set_alarm(const struct tm &now, bool min_en, bool hour_en, bool mday_en) +{ + /* + // Alarm register | Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 | + CTRL1 = 0x00, // Ctrl 1 |Cap Sel| T | Stop | SR | 12-24 | SIE | AIE | CIE | + + MINALARM = 0x0A, // Minute | AEN_M | ( 0 - 59 ) | + HOURALARM = 0x0B, // Hour | AEN_H | X | ( 0 - 23 ) | + // Hour | AEN_H | X | AM/PM | ( 1 - 12 ) | + DAYALARM = 0x0C, // Day | AEN_D | X | ( 1 - 31 ) | + WDAYALARM = 0x0D, // Day of week | AEN_W | X | X | X | X | ( 0 - 6 ) | + + AEN_M, AEN_H, AEN_D, AEN_W => 0 = enable; 1 = disable + */ + + char buffer[3] = {0x00, 0x00, 0x00}; + +// if(now.tm_min >= 60) +// now.tm_min = 0; +// +// if(now.tm_hour >= 24) +// now.tm_hour = 0; +// +// if(now.tm_mday >= 32) +// now.tm_mday = 1; +// + if(min_en) + { + buffer[0] = (decimalToBcd(now.tm_min) & 0x7F); + if(!write(MINALARM, buffer[0]))return 0; + } + else + { + buffer[0] = (decimalToBcd(now.tm_min) | 0x80); + if(!write(MINALARM, buffer[0]))return 0; + } + + if(hour_en) + { + buffer[1] = (decimalToBcd(now.tm_hour) & 0x3F); + if(!write(HOURALARM, buffer[1]))return 0; + } + else + { + buffer[1] = (decimalToBcd(now.tm_hour) | 0x80); + if(!write(HOURALARM, buffer[1]))return 0; + } + + if(mday_en) + { + buffer[2] = (decimalToBcd(now.tm_mday) & 0x3F); + if(!write(DAYALARM, buffer[2]))return 0; + } + else + { + buffer[2] = (decimalToBcd(now.tm_mday) | 0x80); + if(!write(DAYALARM, buffer[2]))return 0; + } + return true; +} + +bool PCF8523::enable_alarm(bool enable) +{ + char buffer = read(CTRL1); + + if(enable) + { + // Disable Clockout & other Timers + if(!write(TMRCLKOUT, 0x38)) + + // Clear any existing flags + alarm_off(0x08); + + // enable AIE bit + buffer = buffer | 0x02; + } + else + { + buffer &= ~0x02; + } + + if(!write(CTRL1, buffer)) return 0; + + return true; +} + +bool PCF8523::alarm_off(char buffer) +{ + // clear AF flag + buffer = buffer - 0x08; + + if(!write(CTRL2, buffer))return 0; + + return true; +} + +bool PCF8523::check_alarm() +{ + char buffer; + + buffer = read(CTRL2); + + if(buffer & 0x08) + { + if(alarm_off(buffer)) + return true; + else return 0; + } + else return 0; +} + +bool PCF8523::software_reset() +{ + char buffer = 0x58; + + if(!write(CTRL1, buffer)) return 0; + + return 1; +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PCF8523.h Fri Mar 02 07:01:17 2018 +0000 @@ -0,0 +1,76 @@ +#ifndef PCF8523_H +#define PCF8523_H + +#include "mbed.h" + +#define address 0xD0 + +class PCF8523 +{ +public: + + enum RegisterName + { + // Control Register | Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 | + CTRL1 = 0x00, // Ctrl 1 |Cap Sel| T | Stop | SR | 12-24 | SIE | AIE | CIE | + CTRL2 = 0x01, // Ctrl 2 | WTAF | CTAF | CTBF | SF | AF | WTAIE | CTAIE | CTBIE | + CTRL3 = 0x02, // Ctrl 3 | PM [2:0] | X | BSF | BLF | BSIE | BLIE | + + // Time and Date Register + SEC = 0x03, // Second | OS | ( 0 - 59 ) | + MIN = 0x04, // Minute | X | ( 0 - 59 ) | + HOUR = 0x05, // Hour | X | X | AM/PM | ( 1 - 12 ) | + // Hour | X | X | ( 0 - 23 ) | + DAY = 0x06, // Day | X | X | ( 1 - 31 ) | + WDAY = 0x07, // Day of week | X | X | X | X | X | ( 0 - 6 ) | + MONTH = 0x08, // month | X | X | X | ( 1 - 12 ) | + YEAR = 0x09, // year | ( 0 - 99 ) | + + // Alarm register + MINALARM = 0x0A, // Minute | AEN_M | ( 0 - 59 ) | + HOURALARM = 0x0B, // Hour | AEN_H | X | ( 0 - 23 ) | + // Hour | AEN_H | X | AM/PM | ( 1 - 12 ) | + DAYALARM = 0x0C, // Day | AEN_D | X | ( 1 - 31 ) | + WDAYALARM = 0x0D, // Day of week | AEN_W | X | X | X | X | ( 0 - 6 ) | + + // Offset Control Register + OFFSET = 0x0E, // OffSet ctrl | MODE | OFFSET | + + // ClockOut adn Timer Register + TMRCLKOUT = 0x0F, // Timer Clk Out| TAM | TBM | COF | TAC | TBC | + TIMERAFR = 0x10, // Timer A Freq | X | X | X | X | X | TAQ | + TIMERARG = 0x11, // Timer A Reg | T_A [7:0] | + TIMERBFR = 0x12, // Timer B Freq | X | TBW | X | TBQ | + TIMERBRG = 0x13, // Timer B Reg | T_B [7:0] | + }; + + bool write(char adr, char data); + char read(char adr); + time_t now(); + bool set_time(time_t time); + bool set_alarm(const struct tm &now, bool min_en=false, bool hour_en=false, bool mday_en=false); + bool enable_alarm(bool enable=false); + bool alarm_off(char buffer); + bool check_alarm(); + bool IsConnected(); + bool software_reset(); + + PCF8523(PinName scl, PinName sda); + ~PCF8523(); + +private: + I2C i2c; + char data[64]; + char w[32]; + char r[32]; + + static int bcdToDecimal(int bcd) { + return ((bcd & 0xF0) >> 4) * 10 + (bcd & 0x0F); + } + + static int decimalToBcd(int dec) { + return (dec % 10) + ((dec / 10) << 4); + } +}; + +#endif \ No newline at end of file