00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00080 #define NUT_DEPRECATED
00081
00082 #include <cfg/os.h>
00083 #include <cfg/eeprom.h>
00084
00085 #include <dev/twif.h>
00086 #include <sys/event.h>
00087 #include <sys/timer.h>
00088
00089 #include <time.h>
00090 #include <stdlib.h>
00091 #include <string.h>
00092 #include <memdebug.h>
00093
00094 #include <dev/x12rtc.h>
00095
00096 #if 0
00097
00098 #define X12DEBUG
00099 #endif
00100
00101 #ifdef X12DEBUG
00102 #define NUTDEBUG
00103 #include <stdio.h>
00104 #endif
00105
00106 #ifndef I2C_SLA_RTC
00107 #define I2C_SLA_RTC 0x6F
00108 #endif
00109
00110 #ifndef I2C_SLA_EEPROM
00111 #define I2C_SLA_EEPROM 0x57
00112 #endif
00113
00114 #ifndef EEPROM_PAGE_SIZE
00115 #define EEPROM_PAGE_SIZE 64
00116 #endif
00117
00118 static uint8_t rtc_chip;
00119 static uint32_t rtc_status;
00120
00129 static int X12WriteEnable(int on)
00130 {
00131 int rc;
00132 uint8_t buf[3];
00133
00134 buf[0] = 0;
00135 buf[1] = 0x3F;
00136 if (on) {
00137 buf[2] = 0x02;
00138 if ((rc = TwMasterTransact(I2C_SLA_RTC, buf, 3, 0, 0, NUT_WAIT_INFINITE)) == 0) {
00139 buf[2] = 0x06;
00140 rc = TwMasterTransact(I2C_SLA_RTC, buf, 3, 0, 0, NUT_WAIT_INFINITE);
00141 }
00142 } else {
00143 buf[2] = 0x00;
00144 rc = TwMasterTransact(I2C_SLA_RTC, buf, 3, 0, 0, NUT_WAIT_INFINITE);
00145 }
00146 return rc;
00147 }
00148
00154 static int X12WaitReady(void)
00155 {
00156 uint8_t poll;
00157 int cnt = 200;
00158
00159
00160
00161
00162
00163 while (--cnt && TwMasterTransact(I2C_SLA_EEPROM, 0, 0, &poll, 1, NUT_WAIT_INFINITE) == -1);
00164 #ifdef X12DEBUG
00165 printf("[RtcRdy:%d]", 200 - cnt);
00166 #endif
00167
00168 return cnt ? 0 : -1;
00169 }
00170
00180 int X12RtcReadRegs(uint8_t reg, uint8_t *buff, size_t cnt)
00181 {
00182 int rc = -1;
00183 uint8_t wbuf[2];
00184
00185 wbuf[0] = 0;
00186 wbuf[1] = reg;
00187 if (TwMasterTransact(I2C_SLA_RTC, wbuf, 2, buff, cnt, NUT_WAIT_INFINITE) == cnt) {
00188 #ifdef X12DEBUG
00189 printf("[Rtc$%02x>", reg);
00190 while(cnt--) {
00191 printf(" %02x", *buff++);
00192 }
00193 putchar(']');
00194 #endif
00195 rc = 0;
00196 }
00197 return rc;
00198 }
00199
00213 int X12RtcWrite(int nv, CONST uint8_t *buff, size_t cnt)
00214 {
00215 int rc;
00216
00217 if ((rc = X12WriteEnable(1)) == 0) {
00218 rc = TwMasterTransact(I2C_SLA_RTC, buff, cnt, 0, 0, NUT_WAIT_INFINITE);
00219 if (rc == 0 && nv) {
00220 rc = X12WaitReady();
00221 }
00222 X12WriteEnable(0);
00223 #ifdef X12DEBUG
00224 printf("[Rtc$%02X<", *++buff);
00225 cnt -= 2;
00226 while(cnt--) {
00227 printf(" %02x", *++buff);
00228 }
00229 putchar(']');
00230 #endif
00231 }
00232 return rc;
00233 }
00234
00245 int X12RtcGetClock(struct _tm *tm)
00246 {
00247 int rc;
00248 uint8_t data[8];
00249
00250 if ((rc = X12RtcReadRegs(X12RTC_SC, data, 8)) == 0) {
00251 tm->tm_sec = BCD2BIN(data[0]);
00252 tm->tm_min = BCD2BIN(data[1]);
00253 tm->tm_hour = BCD2BIN(data[2] & 0x3F);
00254 tm->tm_mday = BCD2BIN(data[3]);
00255 tm->tm_mon = BCD2BIN(data[4]) - 1;
00256 if (rtc_chip) {
00257 tm->tm_year = BCD2BIN(data[5]) + 100;
00258 }
00259 else {
00260 tm->tm_year = BCD2BIN(data[5]);
00261 if (data[7] == 0x20) {
00262 tm->tm_year += 100;
00263 }
00264 }
00265 tm->tm_wday = data[6];
00266 }
00267 return rc;
00268 }
00269
00282 int X12RtcSetClock(CONST struct _tm *tm)
00283 {
00284 uint8_t data[10];
00285
00286 memset(data, 0, sizeof(data));
00287 if (tm) {
00288 data[1] = X12RTC_SC;
00289 data[2] = BIN2BCD(tm->tm_sec);
00290 data[3] = BIN2BCD(tm->tm_min);
00291 data[4] = BIN2BCD(tm->tm_hour) | 0x80;
00292 data[5] = BIN2BCD(tm->tm_mday);
00293 data[6] = BIN2BCD(tm->tm_mon + 1);
00294
00295 if (rtc_chip) {
00296
00297 data[7] = BIN2BCD(tm->tm_year % 100);
00298 }
00299
00300 else if (tm->tm_year > 99) {
00301 data[7] = BIN2BCD(tm->tm_year - 100);
00302 data[9] = 0x20;
00303 }
00304 else {
00305 data[7] = BIN2BCD(tm->tm_year);
00306 data[9] = 0x19;
00307 }
00308 data[8] = tm->tm_wday;
00309 }
00310 return X12RtcWrite(0, data, 10);
00311 }
00312
00326 int X12RtcGetAlarm(int idx, struct _tm *tm, int *aflgs)
00327 {
00328 int rc;
00329 uint8_t data[8];
00330
00331 *aflgs = 0;
00332 memset(tm, 0, sizeof(struct _tm));
00333 if ((rc = X12RtcReadRegs(idx * 8, data, 8)) == 0) {
00334 if (data[0] & X12RTC_SCA_ESC) {
00335 *aflgs |= RTC_ALARM_SECOND;
00336 tm->tm_sec = BCD2BIN(data[0] & 0x7F);
00337 }
00338 if (data[1] & X12RTC_MNA_EMN) {
00339 *aflgs |= RTC_ALARM_MINUTE;
00340 tm->tm_min = BCD2BIN(data[1]);
00341 }
00342 if (data[2] & X12RTC_HRA_EHR) {
00343 *aflgs |= RTC_ALARM_HOUR;
00344 tm->tm_hour = BCD2BIN(data[2] & ~0x80);
00345 }
00346 if (data[3] & X12RTC_DTA_EDT) {
00347 *aflgs |= RTC_ALARM_MDAY;
00348 tm->tm_mday = BCD2BIN(data[3]);
00349 }
00350 if (data[4] & X12RTC_MOA_EMO) {
00351 *aflgs |= RTC_ALARM_MONTH;
00352 tm->tm_mon = BCD2BIN(data[4]) - 1;
00353 }
00354 if (data[6] & X12RTC_DWA_EDW) {
00355 *aflgs |= RTC_ALARM_WDAY;
00356 tm->tm_wday = BCD2BIN(data[6]);
00357 }
00358 }
00359 return rc;
00360 }
00361
00380 int X12RtcSetAlarm(int idx, CONST struct _tm *tm, int aflgs)
00381 {
00382 uint8_t data[10];
00383
00384 memset(data, 0, sizeof(data));
00385 data[1] = idx * 8;
00386 if (tm) {
00387 if (aflgs & RTC_ALARM_SECOND) {
00388 data[2] = BIN2BCD(tm->tm_sec) | X12RTC_SCA_ESC;
00389 }
00390 if (aflgs & RTC_ALARM_MINUTE) {
00391 data[3] = BIN2BCD(tm->tm_min) | X12RTC_MNA_EMN;
00392 }
00393 if (aflgs & RTC_ALARM_HOUR) {
00394 data[4] = BIN2BCD(tm->tm_hour) | X12RTC_HRA_EHR;
00395 }
00396 if (aflgs & RTC_ALARM_MDAY) {
00397 data[5] = BIN2BCD(tm->tm_mday) | X12RTC_DTA_EDT;
00398 }
00399 if (aflgs & RTC_ALARM_MONTH) {
00400 data[6] = BIN2BCD(tm->tm_mon + 1) | X12RTC_MOA_EMO;
00401 }
00402 if (aflgs & RTC_ALARM_WDAY) {
00403 data[8] = BIN2BCD(tm->tm_wday) | X12RTC_DWA_EDW;
00404 }
00405 }
00406 return X12RtcWrite(1, data, 10);
00407 }
00408
00421 int X12RtcGetStatus(uint32_t *sflgs)
00422 {
00423 int rc;
00424 uint8_t data;
00425
00426 if ((rc = X12RtcReadRegs(X12RTC_SR, &data, 1)) == 0) {
00427 rtc_status |= data;
00428 *sflgs = rtc_status;
00429 }
00430 return rc;
00431 }
00432
00442 int X12RtcClearStatus(uint32_t sflgs)
00443 {
00444 rtc_status &= ~sflgs;
00445
00446 return 0;
00447 }
00448
00449 NUTRTC rtcX12x6 = {
00450 X12Init,
00451 X12RtcGetClock,
00452 X12RtcSetClock,
00453 X12RtcGetAlarm,
00454 X12RtcSetAlarm,
00455 X12RtcGetStatus,
00456 X12RtcClearStatus
00457 };
00458
00459
00469 int X12EepromRead(unsigned int addr, void *buff, size_t len)
00470 {
00471 int rc = -1;
00472 uint8_t wbuf[2];
00473
00474 wbuf[0] = (uint8_t)(addr >> 8);
00475 wbuf[1] = (uint8_t)addr;
00476 if (TwMasterTransact(I2C_SLA_EEPROM, wbuf, 2, buff, len, NUT_WAIT_INFINITE) == len) {
00477 rc = 0;
00478 }
00479 return rc;
00480 }
00481
00494 int X12EepromWrite(unsigned int addr, CONST void *buff, size_t len)
00495 {
00496 int rc = 0;
00497 uint8_t *wbuf;
00498 size_t wlen;
00499 CONST uint8_t *wp = buff;
00500
00501
00502
00503
00504 while (len) {
00505
00506 wlen = EEPROM_PAGE_SIZE - (addr & (EEPROM_PAGE_SIZE - 1));
00507 if (wlen > len) {
00508 wlen = len;
00509 }
00510
00511
00512 if ((wbuf = malloc(wlen + 2)) == 0) {
00513 rc = -1;
00514 break;
00515 }
00516 wbuf[0] = (uint8_t)(addr >> 8);
00517 wbuf[1] = (uint8_t)addr;
00518 memcpy(wbuf + 2, (void *)wp, wlen);
00519
00520
00521 if ((rc = X12WriteEnable(1)) == 0) {
00522 rc = TwMasterTransact(I2C_SLA_EEPROM, wbuf, wlen + 2, 0, 0, NUT_WAIT_INFINITE);
00523 }
00524
00525
00526 free(wbuf);
00527 if (rc) {
00528 break;
00529 }
00530 len -= wlen;
00531 addr += wlen;
00532 wp += wlen;
00533
00534
00535 if ((rc = X12WaitReady()) != 0) {
00536 break;
00537 }
00538 }
00539 X12WriteEnable(0);
00540
00541 return rc;
00542 }
00543
00552 int X12Init(void)
00553 {
00554 int rc;
00555 uint32_t tmp;
00556 uint8_t data[2];
00557
00558
00559 if ((rc = TwInit(0)) == 0) {
00560
00561 if ((rc = X12RtcGetStatus(&tmp)) == 0) {
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572 X12RtcReadRegs(X128xRTC_SSEC, &data[0], 1);
00573 NutSleep(20);
00574 X12RtcReadRegs(X128xRTC_SSEC, &data[1], 1);
00575 if (data[0] != data[1]) {
00576 rtc_chip = 1;
00577 }
00578 #ifdef X12DEBUG
00579 printf("[RTC=X12%c6]", rtc_chip ? '8' : '2');
00580 #endif
00581 }
00582 }
00583 return rc;
00584 }