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 NUTDEBUG
00099 #include <stdio.h>
00100 #endif
00101
00102 #ifndef I2C_SLA_RTC
00103 #define I2C_SLA_RTC 0x6F
00104 #endif
00105
00106 #ifndef I2C_SLA_EEPROM
00107 #define I2C_SLA_EEPROM 0x57
00108 #endif
00109
00110 #ifndef EEPROM_PAGE_SIZE
00111 #define EEPROM_PAGE_SIZE 64
00112 #endif
00113
00114 static uint8_t rtc_chip;
00115 static uint32_t rtc_status;
00116
00125 static int X12WriteEnable(int on)
00126 {
00127 int rc;
00128 uint8_t buf[3];
00129
00130 buf[0] = 0;
00131 buf[1] = 0x3F;
00132 if (on) {
00133 buf[2] = 0x02;
00134 if ((rc = TwMasterTransact(I2C_SLA_RTC, buf, 3, 0, 0, NUT_WAIT_INFINITE)) == 0) {
00135 buf[2] = 0x06;
00136 rc = TwMasterTransact(I2C_SLA_RTC, buf, 3, 0, 0, NUT_WAIT_INFINITE);
00137 }
00138 } else {
00139 buf[2] = 0x00;
00140 rc = TwMasterTransact(I2C_SLA_RTC, buf, 3, 0, 0, NUT_WAIT_INFINITE);
00141 }
00142 return rc;
00143 }
00144
00150 static int X12WaitReady(void)
00151 {
00152 uint8_t poll;
00153 int cnt = 200;
00154
00155
00156
00157
00158
00159 while (--cnt && TwMasterTransact(I2C_SLA_EEPROM, 0, 0, &poll, 1, NUT_WAIT_INFINITE) == -1);
00160 #ifdef NUTDEBUG
00161 printf("[RtcRdy:%d]", 200 - cnt);
00162 #endif
00163
00164 return cnt ? 0 : -1;
00165 }
00166
00176 int X12RtcReadRegs(uint8_t reg, uint8_t *buff, size_t cnt)
00177 {
00178 int rc = -1;
00179 uint8_t wbuf[2];
00180
00181 wbuf[0] = 0;
00182 wbuf[1] = reg;
00183 if (TwMasterTransact(I2C_SLA_RTC, wbuf, 2, buff, cnt, NUT_WAIT_INFINITE) == cnt) {
00184 #ifdef NUTDEBUG
00185 printf("[Rtc$%02x>", reg);
00186 while(cnt--) {
00187 printf(" %02x", *buff++);
00188 }
00189 putchar(']');
00190 #endif
00191 rc = 0;
00192 }
00193 return rc;
00194 }
00195
00209 int X12RtcWrite(int nv, CONST uint8_t *buff, size_t cnt)
00210 {
00211 int rc;
00212
00213 if ((rc = X12WriteEnable(1)) == 0) {
00214 rc = TwMasterTransact(I2C_SLA_RTC, buff, cnt, 0, 0, NUT_WAIT_INFINITE);
00215 if (rc == 0 && nv) {
00216 rc = X12WaitReady();
00217 }
00218 X12WriteEnable(0);
00219 #ifdef NUTDEBUG
00220 printf("[Rtc$%02X<", *++buff);
00221 cnt -= 2;
00222 while(cnt--) {
00223 printf(" %02x", *++buff);
00224 }
00225 putchar(']');
00226 #endif
00227 }
00228 return rc;
00229 }
00230
00241 int X12RtcGetClock(struct _tm *tm)
00242 {
00243 int rc;
00244 uint8_t data[8];
00245
00246 if ((rc = X12RtcReadRegs(X12RTC_SC, data, 8)) == 0) {
00247 tm->tm_sec = BCD2BIN(data[0]);
00248 tm->tm_min = BCD2BIN(data[1]);
00249 tm->tm_hour = BCD2BIN(data[2] & 0x3F);
00250 tm->tm_mday = BCD2BIN(data[3]);
00251 tm->tm_mon = BCD2BIN(data[4]) - 1;
00252 if (rtc_chip) {
00253 tm->tm_year = BCD2BIN(data[5]) + 100;
00254 }
00255 else {
00256 tm->tm_year = BCD2BIN(data[5]);
00257 if (data[7] == 0x20) {
00258 tm->tm_year += 100;
00259 }
00260 }
00261 tm->tm_wday = data[6];
00262 }
00263 return rc;
00264 }
00265
00278 int X12RtcSetClock(CONST struct _tm *tm)
00279 {
00280 uint8_t data[10];
00281
00282 memset(data, 0, sizeof(data));
00283 if (tm) {
00284 data[1] = X12RTC_SC;
00285 data[2] = BIN2BCD(tm->tm_sec);
00286 data[3] = BIN2BCD(tm->tm_min);
00287 data[4] = BIN2BCD(tm->tm_hour) | 0x80;
00288 data[5] = BIN2BCD(tm->tm_mday);
00289 data[6] = BIN2BCD(tm->tm_mon + 1);
00290
00291 if (rtc_chip) {
00292
00293 data[7] = BIN2BCD(tm->tm_year % 100);
00294 }
00295
00296 else if (tm->tm_year > 99) {
00297 data[7] = BIN2BCD(tm->tm_year - 100);
00298 data[9] = 0x20;
00299 }
00300 else {
00301 data[7] = BIN2BCD(tm->tm_year);
00302 data[9] = 0x19;
00303 }
00304 data[8] = tm->tm_wday;
00305 }
00306 return X12RtcWrite(0, data, 10);
00307 }
00308
00322 int X12RtcGetAlarm(int idx, struct _tm *tm, int *aflgs)
00323 {
00324 int rc;
00325 uint8_t data[8];
00326
00327 *aflgs = 0;
00328 memset(tm, 0, sizeof(struct _tm));
00329 if ((rc = X12RtcReadRegs(idx * 8, data, 8)) == 0) {
00330 if (data[0] & X12RTC_SCA_ESC) {
00331 *aflgs |= RTC_ALARM_SECOND;
00332 tm->tm_sec = BCD2BIN(data[0] & 0x7F);
00333 }
00334 if (data[1] & X12RTC_MNA_EMN) {
00335 *aflgs |= RTC_ALARM_MINUTE;
00336 tm->tm_min = BCD2BIN(data[1]);
00337 }
00338 if (data[2] & X12RTC_HRA_EHR) {
00339 *aflgs |= RTC_ALARM_HOUR;
00340 tm->tm_hour = BCD2BIN(data[2] & ~0x80);
00341 }
00342 if (data[3] & X12RTC_DTA_EDT) {
00343 *aflgs |= RTC_ALARM_MDAY;
00344 tm->tm_mday = BCD2BIN(data[3]);
00345 }
00346 if (data[4] & X12RTC_MOA_EMO) {
00347 *aflgs |= RTC_ALARM_MONTH;
00348 tm->tm_mon = BCD2BIN(data[4]) - 1;
00349 }
00350 if (data[6] & X12RTC_DWA_EDW) {
00351 *aflgs |= RTC_ALARM_WDAY;
00352 tm->tm_wday = BCD2BIN(data[6]);
00353 }
00354 }
00355 return rc;
00356 }
00357
00376 int X12RtcSetAlarm(int idx, CONST struct _tm *tm, int aflgs)
00377 {
00378 uint8_t data[10];
00379
00380 memset(data, 0, sizeof(data));
00381 data[1] = idx * 8;
00382 if (tm) {
00383 if (aflgs & RTC_ALARM_SECOND) {
00384 data[2] = BIN2BCD(tm->tm_sec) | X12RTC_SCA_ESC;
00385 }
00386 if (aflgs & RTC_ALARM_MINUTE) {
00387 data[3] = BIN2BCD(tm->tm_min) | X12RTC_MNA_EMN;
00388 }
00389 if (aflgs & RTC_ALARM_HOUR) {
00390 data[4] = BIN2BCD(tm->tm_hour) | X12RTC_HRA_EHR;
00391 }
00392 if (aflgs & RTC_ALARM_MDAY) {
00393 data[5] = BIN2BCD(tm->tm_mday) | X12RTC_DTA_EDT;
00394 }
00395 if (aflgs & RTC_ALARM_MONTH) {
00396 data[6] = BIN2BCD(tm->tm_mon + 1) | X12RTC_MOA_EMO;
00397 }
00398 if (aflgs & RTC_ALARM_WDAY) {
00399 data[8] = BIN2BCD(tm->tm_wday) | X12RTC_DWA_EDW;
00400 }
00401 }
00402 return X12RtcWrite(1, data, 10);
00403 }
00404
00417 int X12RtcGetStatus(uint32_t *sflgs)
00418 {
00419 int rc;
00420 uint8_t data;
00421
00422 if ((rc = X12RtcReadRegs(X12RTC_SR, &data, 1)) == 0) {
00423 rtc_status |= data;
00424 *sflgs = rtc_status;
00425 }
00426 return rc;
00427 }
00428
00438 int X12RtcClearStatus(uint32_t sflgs)
00439 {
00440 rtc_status &= ~sflgs;
00441
00442 return 0;
00443 }
00444
00445 NUTRTC rtcX12x6 = {
00446 X12Init,
00447 X12RtcGetClock,
00448 X12RtcSetClock,
00449 X12RtcGetAlarm,
00450 X12RtcSetAlarm,
00451 X12RtcGetStatus,
00452 X12RtcClearStatus
00453 };
00454
00455
00465 int X12EepromRead(unsigned int addr, void *buff, size_t len)
00466 {
00467 int rc = -1;
00468 uint8_t wbuf[2];
00469
00470 wbuf[0] = (uint8_t)(addr >> 8);
00471 wbuf[1] = (uint8_t)addr;
00472 if (TwMasterTransact(I2C_SLA_EEPROM, wbuf, 2, buff, len, NUT_WAIT_INFINITE) == len) {
00473 rc = 0;
00474 }
00475 return rc;
00476 }
00477
00490 int X12EepromWrite(unsigned int addr, CONST void *buff, size_t len)
00491 {
00492 int rc = 0;
00493 uint8_t *wbuf;
00494 size_t wlen;
00495 CONST uint8_t *wp = buff;
00496
00497
00498
00499
00500 while (len) {
00501
00502 wlen = EEPROM_PAGE_SIZE - (addr & (EEPROM_PAGE_SIZE - 1));
00503 if (wlen > len) {
00504 wlen = len;
00505 }
00506
00507
00508 if ((wbuf = malloc(wlen + 2)) == 0) {
00509 rc = -1;
00510 break;
00511 }
00512 wbuf[0] = (uint8_t)(addr >> 8);
00513 wbuf[1] = (uint8_t)addr;
00514 memcpy(wbuf + 2, (void *)wp, wlen);
00515
00516
00517 if ((rc = X12WriteEnable(1)) == 0) {
00518 rc = TwMasterTransact(I2C_SLA_EEPROM, wbuf, wlen + 2, 0, 0, NUT_WAIT_INFINITE);
00519 }
00520
00521
00522 free(wbuf);
00523 if (rc) {
00524 break;
00525 }
00526 len -= wlen;
00527 addr += wlen;
00528 wp += wlen;
00529
00530
00531 if ((rc = X12WaitReady()) != 0) {
00532 break;
00533 }
00534 }
00535 X12WriteEnable(0);
00536
00537 return rc;
00538 }
00539
00548 int X12Init(void)
00549 {
00550 int rc;
00551 uint32_t tmp;
00552 uint8_t data[2];
00553
00554
00555 if ((rc = TwInit(0)) == 0) {
00556
00557 if ((rc = X12RtcGetStatus(&tmp)) == 0) {
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568 X12RtcReadRegs(X128xRTC_SSEC, &data[0], 1);
00569 NutSleep(20);
00570 X12RtcReadRegs(X128xRTC_SSEC, &data[1], 1);
00571 if (data[0] != data[1]) {
00572 rtc_chip = 1;
00573 }
00574 #ifdef NUTDEBUG
00575 printf("[RTC=X12%c6]", rtc_chip ? '8' : '2');
00576 #endif
00577 }
00578 }
00579 return rc;
00580 }