From 61b0cfe9df810db4fbca78e5f880d61c5063f324 Mon Sep 17 00:00:00 2001 From: Leo C Date: Sat, 23 Aug 2014 19:34:22 +0200 Subject: [PATCH] Add date rtc i2c --- avr/Tupfile | 6 +- avr/cmd_date.c | 188 ++++++++++++++++++++++ avr/command_tbl.c | 10 ++ avr/date.c | 139 +++++++++++++++++ avr/debug.c | 71 ++------- avr/i2c.c | 389 ++++++++++++++++++++++++++++++++++++++++++++++ avr/main.c | 13 +- avr/pcf8583.c | 106 +++++++++++++ include/cmd_mem.h | 2 - include/common.h | 10 +- include/config.h | 6 + include/crc.h | 4 +- include/debug.h | 4 + include/i2c.h | 63 ++++++++ include/rtc.h | 49 ++++++ 15 files changed, 979 insertions(+), 81 deletions(-) create mode 100644 avr/cmd_date.c create mode 100644 avr/date.c create mode 100644 avr/i2c.c create mode 100644 avr/pcf8583.c create mode 100644 include/i2c.h create mode 100644 include/rtc.h diff --git a/avr/Tupfile b/avr/Tupfile index 60022d6..d0bed48 100644 --- a/avr/Tupfile +++ b/avr/Tupfile @@ -3,9 +3,9 @@ include_rules PROG = stamp-test SRC = main.c SRC += cli.c cli_readline.c command.c command_tbl.c -SRC += cmd_help.c cmd_echo.c cmd_mem.c cmd_boot.c -SRC += env.c xmalloc.c -SRC += timer.c con-utils.c serial.c +SRC += cmd_help.c cmd_echo.c cmd_date.c cmd_mem.c cmd_boot.c +SRC += env.c xmalloc.c date.c +SRC += timer.c con-utils.c serial.c i2c.c pcf8583.c SRC += background.c z180-serv.c z80-if.c SRC_Z = ../z180/hdrom.c diff --git a/avr/cmd_date.c b/avr/cmd_date.c new file mode 100644 index 0000000..bc93efc --- /dev/null +++ b/avr/cmd_date.c @@ -0,0 +1,188 @@ +/* + * (C) Copyright 2001 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * RTC, Date & Time support: get and set date & time + */ +#include +#include +#include +#include +#include +#include + + +static const char * const weekdays[] = { + "Sun", "Mon", "Tues", "Wednes", "Thurs", "Fri", "Satur", +}; + +int mk_date (const char *, struct rtc_time *); + +command_ret_t do_date(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + struct rtc_time tm; + int rcode = CMD_RET_SUCCESS; + + (void) cmdtp; (void) flag; + + switch (argc) { + case 2: /* set date & time */ + if (strcmp_P(argv[1],PSTR("reset")) == 0) { + my_puts_P(PSTR("Reset RTC...\n")); + rtc_reset (); + } else { + /* initialize tm with current time */ + rcode = rtc_get (&tm); + + if(!rcode) { + /* insert new date & time */ + if (mk_date (argv[1], &tm) != 0) { + my_puts_P(PSTR("## Bad date format\n")); + break; + } + /* and write to RTC */ + rcode = rtc_set (&tm); + if(rcode) + my_puts_P(PSTR("## Set date failed\n")); + } else { + my_puts_P(PSTR("## Get date failed\n")); + } + } + /* FALL TROUGH */ + case 1: /* get date & time */ + rcode = rtc_get (&tm); + + if (rcode) { + my_puts_P(PSTR("## Get date failed\n")); + break; + } + /* TODO: flash */ + printf_P(PSTR("Date: %4d-%02d-%02d (%sday) Time: %2d:%02d:%02d\n"), + tm.tm_year, tm.tm_mon, tm.tm_mday, + (tm.tm_wday<0 || tm.tm_wday>6) ? + "unknown " : weekdays[tm.tm_wday], + tm.tm_hour, tm.tm_min, tm.tm_sec); + + break; + default: + rcode = CMD_RET_USAGE; + } + + return rcode; +} + +/* + * simple conversion of two-digit string with error checking + */ +static int cnvrt2 (const char *str, int *valp) +{ + int val; + + if ((*str < '0') || (*str > '9')) + return (-1); + + val = *str - '0'; + + ++str; + + if ((*str < '0') || (*str > '9')) + return (-1); + + *valp = 10 * val + (*str - '0'); + + return (0); +} + +/* + * Convert date string: MMDDhhmm[[CC]YY][.ss] + * + * Some basic checking for valid values is done, but this will not catch + * all possible error conditions. + */ +int mk_date (const char *datestr, struct rtc_time *tmp) +{ + int len, val; + char *ptr; + + ptr = strchr (datestr,'.'); + len = strlen (datestr); + + /* Set seconds */ + if (ptr) { + int sec; + + *ptr++ = '\0'; + if ((len - (ptr - datestr)) != 2) + return (-1); + + len = strlen (datestr); + + if (cnvrt2 (ptr, &sec)) + return (-1); + + tmp->tm_sec = sec; + } else { + tmp->tm_sec = 0; + } + + if (len == 12) { /* MMDDhhmmCCYY */ + int year, century; + + if (cnvrt2 (datestr+ 8, ¢ury) || + cnvrt2 (datestr+10, &year) ) { + return (-1); + } + tmp->tm_year = 100 * century + year; + } else if (len == 10) { /* MMDDhhmmYY */ + int year, century; + + century = tmp->tm_year / 100; + if (cnvrt2 (datestr+ 8, &year)) + return (-1); + tmp->tm_year = 100 * century + year; + } + + switch (len) { + case 8: /* MMDDhhmm */ + /* fall thru */ + case 10: /* MMDDhhmmYY */ + /* fall thru */ + case 12: /* MMDDhhmmCCYY */ + if (cnvrt2 (datestr+0, &val) || + val > 12) { + break; + } + tmp->tm_mon = val; + if (cnvrt2 (datestr+2, &val) || + val > ((tmp->tm_mon==2) ? 29 : 31)) { + break; + } + tmp->tm_mday = val; + + if (cnvrt2 (datestr+4, &val) || + val > 23) { + break; + } + tmp->tm_hour = val; + + if (cnvrt2 (datestr+6, &val) || + val > 59) { + break; + } + tmp->tm_min = val; + + /* calculate day of week */ + GregorianDay (tmp); + + return (0); + default: + break; + } + + return (-1); +} + diff --git a/avr/command_tbl.c b/avr/command_tbl.c index 2fb41b9..6fcbee7 100644 --- a/avr/command_tbl.c +++ b/avr/command_tbl.c @@ -16,10 +16,20 @@ extern command_ret_t do_restart(cmd_tbl_t *, int, int, char * const []); extern command_ret_t do_dump_mem(cmd_tbl_t *, int, int, char * const []); extern command_ret_t do_eep_cp(cmd_tbl_t *, int, int, char * const []); extern command_ret_t do_busreq_pulse(cmd_tbl_t *, int, int, char * const []); +extern command_ret_t do_date(cmd_tbl_t *, int, int, char * const []); cmd_tbl_t cmd_tbl[] = { +CMD_TBL_ITEM( + date, 2, 1, do_date, + "get/set/reset date & time", + "[MMDDhhmm[[CC]YY][.ss]]\ndate reset\n" + " - without arguments: print date & time\n" + " - with numeric argument: set the system date & time\n" + " - with 'reset' argument: reset the RTC" +), + #ifdef DEBUG CMD_TBL_ITEM( !mdr, 3, 1, do_dump_mem, diff --git a/avr/date.c b/avr/date.c new file mode 100644 index 0000000..c85361f --- /dev/null +++ b/avr/date.c @@ -0,0 +1,139 @@ +/* + * (C) Copyright 2001 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * Date & Time support for RTC + */ + +#include +#include +#include + + +#define FEBRUARY 2 +#define STARTOFTIME 1970 +#define SECDAY 86400L +#define SECYR (SECDAY * 365) +#define leapyear(year) ((year) % 4 == 0) +#define days_in_year(a) (leapyear(a) ? 366 : 365) +#define days_in_month(a) (month_days[(a) - 1]) + + +static const FLASH int MonthOffset[] = { + 0,31,59,90,120,151,181,212,243,273,304,334 +}; + +/* + * This only works for the Gregorian calendar - i.e. after 1752 (in the UK) + */ +void GregorianDay(struct rtc_time * tm) +{ + int leapsToDate; + int lastYear; + int day; + + lastYear=tm->tm_year-1; + + /* + * Number of leap corrections to apply up to end of last year + */ + leapsToDate = lastYear/4 - lastYear/100 + lastYear/400; + + /* + * This year is a leap year if it is divisible by 4 except when it is + * divisible by 100 unless it is divisible by 400 + * + * e.g. 1904 was a leap year, 1900 was not, 1996 is, and 2000 will be + */ + if((tm->tm_year%4==0) && + ((tm->tm_year%100!=0) || (tm->tm_year%400==0)) && + (tm->tm_mon>2)) { + /* + * We are past Feb. 29 in a leap year + */ + day=1; + } else { + day=0; + } + + day += lastYear*365 + leapsToDate + MonthOffset[tm->tm_mon-1] + tm->tm_mday; + + tm->tm_wday=day%7; +} + +void to_tm(unsigned long tim, struct rtc_time * tm) +{ + char month_days[12] = {31,28,31,30,31,30,31,31,30,31,30,31}; + register int i; + register long hms, day; + + day = tim / SECDAY; + hms = tim % SECDAY; + + /* Hours, minutes, seconds are easy */ + tm->tm_hour = hms / 3600; + tm->tm_min = (hms % 3600) / 60; + tm->tm_sec = (hms % 3600) % 60; + + /* Number of years in days */ + for (i = STARTOFTIME; day >= days_in_year(i); i++) { + day -= days_in_year(i); + } + tm->tm_year = i; + + /* Number of months in days left */ + if (leapyear(tm->tm_year)) { + days_in_month(FEBRUARY) = 29; + } + for (i = 1; day >= days_in_month(i); i++) { + day -= days_in_month(i); + } + days_in_month(FEBRUARY) = 28; + tm->tm_mon = i; + + /* Days are what is left over (+1) from all that. */ + tm->tm_mday = day + 1; + + /* + * Determine the day of week + */ + GregorianDay(tm); +} + +/* Converts Gregorian date to seconds since 1970-01-01 00:00:00. + * Assumes input in normal date format, i.e. 1980-12-31 23:59:59 + * => year=1980, mon=12, day=31, hour=23, min=59, sec=59. + * + * [For the Julian calendar (which was used in Russia before 1917, + * Britain & colonies before 1752, anywhere else before 1582, + * and is still in use by some communities) leave out the + * -year/100+year/400 terms, and add 10.] + * + * This algorithm was first published by Gauss (I think). + * + * WARNING: this function will overflow on 2106-02-07 06:28:16 on + * machines were long is 32-bit! (However, as time_t is signed, we + * will already get problems at other places on 2038-01-19 03:14:08) + */ +unsigned long +mktime (unsigned int year, unsigned int mon, + unsigned int day, unsigned int hour, + unsigned int min, unsigned int sec) +{ + if (0 >= (int) (mon -= 2)) { /* 1..12 -> 11,12,1..10 */ + mon += 12; /* Puts Feb last since it has leap day */ + year -= 1; + } + + return ((( + (unsigned long) (year/4 - year/100 + year/400 + 367*mon/12 + day) + + year*365 - 719499 + )*24 + hour /* now have hours */ + )*60 + min /* now have minutes */ + )*60 + sec; /* finally seconds */ +} + diff --git a/avr/debug.c b/avr/debug.c index fcbd2c1..16df702 100644 --- a/avr/debug.c +++ b/avr/debug.c @@ -12,8 +12,6 @@ */ #ifdef DEBUG -//uint8_t eeprom_read_byte (const uint8_t *__p) - static void print_blanks(uint_fast8_t count) { while(count--) @@ -29,14 +27,17 @@ void dump_mem(const uint8_t *startaddr, int len, uint8_t (*readfkt)(const uint8_t *), char *title) { uint8_t buf[16]; + char *indent = NULL; uint8_t llen = 16; uint8_t pre = (size_t) startaddr % 16; const uint8_t *addr = (uint8_t *) ((size_t) startaddr & ~0x0f); len += pre; uint8_t i; - if (title && *title) + if (title && *title) { printf_P(PSTR("%s\n"),title); + indent = " "; + } while (len) { if (len < 16) @@ -45,7 +46,7 @@ void dump_mem(const uint8_t *startaddr, int len, for (i = pre; i < llen; i++) buf[i] = readfkt(addr + i); - printf_P(PSTR("%04x:"), addr); + printf_P(PSTR("%s%04x:"),indent, addr); for (i = 0; i < llen; i++) { if ((i % 8) == 0) putchar(' '); @@ -67,37 +68,17 @@ void dump_mem(const uint8_t *startaddr, int len, } } -#if 0 -void dump_ram(const uint8_t *startaddr, int len, char *title) +void dump_eep(const uint8_t *addr, unsigned int len, char *title) { - uint8_t llen = 16; - uint8_t pre = (size_t) startaddr % 16; - const uint8_t *addr = (uint8_t *) ((size_t) startaddr & ~0x0f); - len += pre; - uint8_t i; - - if (title && *title) - printf_P(PSTR("%s\n"),title); + dump_mem(addr, len, eeprom_read_byte, title); +} - while (len) { - if (len < 16) - llen = len; +void dump_ram(const uint8_t *addr, unsigned int len, char *title) +{ + dump_mem(addr, len, ram_read_byte, title); +} - printf_P(PSTR(" %.4x:"), (size_t) addr); - print_blanks(3 * pre); - for (i = pre; i < llen; i++) - printf_P(PSTR(" %.2x"), addr[i]); - print_blanks(3 * (16 - i + 1) + pre); - for (i = pre; i < llen; i++) - printf_P(PSTR("%c"), isprint(addr[i]) ? addr[i] : '.'); - putchar('\n'); - pre = 0; - addr += 16; - len -= llen; - } -} -#endif #if 0 void dump_heap(void) { @@ -109,35 +90,9 @@ void dump_heap(void) } #endif -#if 0 -/* TODO: combine with dump_ram() */ -void dump_eep(const uint8_t *addr, unsigned int len, - uint8_t (*readfkt)(const uint8_t *)) -{ - uint_fast8_t i; - uint8_t buf[16]; - - printf_P(PSTR("eeprom dump:")); - while (len) { - printf_P(PSTR("\n 0x%.4x:"), (unsigned int) addr); - for (i = 0; i<16; i++) - buf[i] = readfkt(addr + i); - for (i = 0; i<16; i++) - printf_P(PSTR(" %.2x"), buf[i]); - printf_P(PSTR(" ")); - for (i = 0; i<16; i++) - printf_P(PSTR("%c"), isprint(buf[i]) ? buf[i] : '.'); - - addr += 16; - len -= len > 16 ? 16 : len; - } - putchar('\n'); -} -#endif - /* - * EEPROM Display + * Memory Display * md addr {len} */ command_ret_t do_dump_mem(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) diff --git a/avr/i2c.c b/avr/i2c.c new file mode 100644 index 0000000..df97fea --- /dev/null +++ b/avr/i2c.c @@ -0,0 +1,389 @@ + +/* + * I2C (TWI) master interface. + */ + +#include "common.h" +#include +#include +#include + +#include "config.h" +#include "timer.h" +#include "debug.h" +#include "i2c.h" + +#ifdef DEBUG +//# define DEBUG_I2C +#endif + +/* General TWI Master status codes */ +#define TWI_START 0x08 /* START has been transmitted */ +#define TWI_REP_START 0x10 /* Repeated START has been transmitted */ +#define TWI_ARB_LOST 0x38 /* Arbitration lost */ + +/* TWI Master Transmitter status codes */ +#define TWI_MTX_ADR_ACK 0x18 /* SLA+W has been transmitted and ACK received */ +#define TWI_MTX_ADR_NACK 0x20 /* SLA+W has been transmitted and NACK received */ +#define TWI_MTX_DATA_ACK 0x28 /* Data byte has been transmitted and ACK received */ +#define TWI_MTX_DATA_NACK 0x30 /* Data byte has been transmitted and NACK received */ + +/* TWI Master Receiver status codes */ +#define TWI_MRX_ADR_ACK 0x40 /* SLA+R has been transmitted and ACK received */ +#define TWI_MRX_ADR_NACK 0x48 /* SLA+R has been transmitted and NACK received */ +#define TWI_MRX_DATA_ACK 0x50 /* Data byte has been received and ACK transmitted */ +#define TWI_MRX_DATA_NACK 0x58 /* Data byte has been received and NACK transmitted */ + +/* TWI Miscellaneous status codes */ +#define TWI_NO_STATE 0xF8 /* No relevant state information available */ +#define TWI_BUS_ERROR 0x00 /* Bus error due to an illegal START or STOP condition */ + + +/* + * TWINT: TWI Interrupt Flag + * TWEA: TWI Enable Acknowledge Bit + * TWSTA: TWI START Condition Bit + * TWSTO: TWI STOP Condition Bit + * TWEN: TWI Enable Bit + * TWIE: TWI Interrupt Enable + * + * (1< 255) { + tmptwbr >>= 4; + twps += 1; + } + debug_cond((twps > 3), "TWCLK too low: %lu Hz\n", speed); + + twbr = (uint8_t) tmptwbr; + _init(); +} + + +int_fast8_t i2c_waitready(void) +{ + uint32_t timer = get_timer(0); + uint8_t timeout = 0; + + do { + if (get_timer(timer) >= 30) { + timeout = TIMEOUT; + _init(); + } + } while ((TWCR & ((1<>= 8; + } + for (n = len + i; i < n; i++) + xmit.buf[i] = *buffer++; + xmit.len = i; + +#ifdef DEBUG_I2C + dump_ram((uint8_t *) &xmit, 0x20, "=== i2c_send"); + _delay_ms(30); +#endif + /* Enable TWI, TWI int and initiate start condition */ + TWCR = (1< 2) || (1 + alen + len > CONFIG_SYS_I2C_BUFSIZE)) { + debug("** i2c_write: buffer overflow, alen: %u, len: %u\n", + alen, len); + return -1; + } + + i2c_send(chip, addr, alen, buffer, len); + rc = i2c_waitready(); + debug("** i2c_write: result=0x%02x\n",rc); + + return (rc & XMIT_DONE) != 0; +} + +int i2c_read(uint8_t chip, unsigned int addr, uint_fast8_t alen, + uint8_t *buffer, uint_fast8_t len) +{ + int rc; + + if ((alen > 2) || (1 + len > CONFIG_SYS_I2C_BUFSIZE)) { + debug("** i2c_read: parameter error: alen: %u, len: %u\n", + alen, len); + return -1; + } + + if (alen != 0) { + i2c_send(chip, addr, alen, NULL, 0); + } + rc = i2c_recv(chip, buffer, len); + debug("** i2c_read: result=0x%02x\n",rc); + + return !((rc & (XMIT_DONE|DATA_ACK)) == (XMIT_DONE|DATA_ACK)); +} + + + diff --git a/avr/main.c b/avr/main.c index c6a0f00..9103ddc 100644 --- a/avr/main.c +++ b/avr/main.c @@ -5,22 +5,14 @@ #include "common.h" #include -//#include -//#include #include -//#include -//#include -//#include - -#include - #include #include - #include "config.h" #include "debug.h" #include "z80-if.h" +#include "i2c.h" #include "con-utils.h" #include "serial.h" #include "timer.h" @@ -92,7 +84,7 @@ void print_reset_reason(void) uint8_t r = mcusr & 0x1f; const FLASH char * const FLASH *p = rreasons; - printf_P(PSTR("Reset reason(s): ")); + printf_P(PSTR("Reset reason(s): %s"), r ? "" : "none"); for ( ; r; p++, r >>= 1) { if (r & 1) { my_puts_P(*p); @@ -217,6 +209,7 @@ int main(void) #endif env_init(); + i2c_init(34920); printf_P(PSTR("\n(ATMEGA1281+HD64180)_stamp Tester\n")); diff --git a/avr/pcf8583.c b/avr/pcf8583.c new file mode 100644 index 0000000..d33c9b0 --- /dev/null +++ b/avr/pcf8583.c @@ -0,0 +1,106 @@ +/* + * Date & Time support for Philips PCF8583 RTC + */ + +/* #define DEBUG */ + +#include "common.h" +#include +#include "debug.h" +#include "command.h" +#include "rtc.h" +#include "i2c.h" + +#define REG_CS 0x00 /* control/status */ +#define REG_CSEC 0x01 /* hundredth of a second */ +#define REG_SEC 0x02 /* seconds */ +#define REG_MIN 0x03 /* minutes */ +#define REG_HOUR 0x04 /* hours */ +#define REG_YRDATE 0x05 /* year/date */ +#define REG_WDMON 0x06 /* weekdays/months */ +#define NR_OF_REGS 7 + + +/* ------------------------------------------------------------------------- */ + +static uint_fast8_t bcd2bin(uint8_t val) +{ + return (val >> 4) * 10 + (val & 0x0f); +} + +static uint8_t bin2bcd (uint_fast8_t val) +{ + div_t d = div(val, 10); + + return (d.quot << 4) | d.rem; +} + + +int rtc_get (struct rtc_time *tmp) +{ + int rel = 0; + uint8_t rtcbuf[NR_OF_REGS]; + uint16_t year; + + i2c_read(CONFIG_SYS_I2C_RTC_ADDR, 0, 1, rtcbuf, NR_OF_REGS); + i2c_read(CONFIG_SYS_I2C_RTC_ADDR, 0x10, 1, (uint8_t *) &year, 2); + + debug("Get RTC year: %u, year/date: %02x, wdays/month: %02x, " + "hour: %02x, min: %02x, sec: %02x, (stat: %02x)\n", year, + rtcbuf[6], rtcbuf[5], rtcbuf[4], rtcbuf[3], rtcbuf[2], rtcbuf[0]); + + tmp->tm_sec = bcd2bin (rtcbuf[REG_SEC] & 0x7F); + tmp->tm_min = bcd2bin (rtcbuf[REG_MIN] & 0x7F); + tmp->tm_hour = bcd2bin (rtcbuf[REG_HOUR] & 0x3F); + tmp->tm_mday = bcd2bin (rtcbuf[REG_YRDATE] & 0x3F); + tmp->tm_mon = bcd2bin (rtcbuf[REG_WDMON] & 0x1F); + while (year%4 < (rtcbuf[REG_YRDATE]>>6)) { + year++; + /* TODO: update RTC ram */ + } + tmp->tm_year = year; + tmp->tm_wday = rtcbuf[REG_WDMON] >> 5; + tmp->tm_yday = 0; + tmp->tm_isdst= 0; + + + debug ( "Get DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n", + tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday, + tmp->tm_hour, tmp->tm_min, tmp->tm_sec); + + return rel; +} + +int rtc_set (struct rtc_time *tmp) +{ + uint8_t rtcbuf[NR_OF_REGS]; + + debug ( "Set DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n", + tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday, + tmp->tm_hour, tmp->tm_min, tmp->tm_sec); + + rtcbuf[REG_CS] = 0x84; + rtcbuf[REG_CSEC] = 0x00; + rtcbuf[REG_WDMON ] = bin2bcd(tmp->tm_mon) | ((tmp->tm_wday) << 5); + rtcbuf[REG_YRDATE] = ((tmp->tm_year % 4) << 6) | bin2bcd(tmp->tm_mday); + rtcbuf[REG_HOUR ] = bin2bcd(tmp->tm_hour); + rtcbuf[REG_MIN ] = bin2bcd(tmp->tm_min); + rtcbuf[REG_SEC ] = bin2bcd(tmp->tm_sec); + + i2c_write(CONFIG_SYS_I2C_RTC_ADDR, 0, 1, rtcbuf, NR_OF_REGS); + i2c_write(CONFIG_SYS_I2C_RTC_ADDR, 0x10, 1, (uint8_t *) &tmp->tm_year, 2); + rtcbuf[REG_CS] = 0x04; + i2c_write(CONFIG_SYS_I2C_RTC_ADDR, 0, 1, rtcbuf, 1); + + + return 0; +} + +void rtc_reset (void) +{ + uint8_t c = 0; + + i2c_write(CONFIG_SYS_I2C_RTC_ADDR, 0, 1, &c, 1); +} + + diff --git a/include/cmd_mem.h b/include/cmd_mem.h index cf379ce..1802338 100644 --- a/include/cmd_mem.h +++ b/include/cmd_mem.h @@ -1,8 +1,6 @@ #ifndef CMD_MEM_H #define CMD_MEM_H -//#include "common.h" - #include "command.h" #include "cmd_mem.h" diff --git a/include/common.h b/include/common.h index a92f62c..e8879a6 100644 --- a/include/common.h +++ b/include/common.h @@ -43,19 +43,15 @@ void my_puts(const char *s) fputs(s, stdout); } -#ifdef __AVR__ static inline void my_puts_P(const char *s) { +#ifdef __AVR__ fputs_P(s, stdout); -} - #else -static inline -void my_puts_P(const char *s) -{ fputs(s, stdout); -} #endif /* __AVR__ */ +} + #endif /* COMMON_H */ diff --git a/include/config.h b/include/config.h index 08d97bd..91b1fae 100644 --- a/include/config.h +++ b/include/config.h @@ -12,6 +12,12 @@ //#define CONFIG_CMD_MEMTEST //#define CONFIG_MX_CYCLIC +#define CONFIG_CMD_DATE 1 + +#define CONFIG_SYS_I2C_RTC_ADDR 0x50 +#define CONFIG_SYS_I2C_BUFSIZE 64 +#define CONFIG_SYS_I2C_CLOCK 100000L /* 100kHz */ + #define CONFIG_SYS_CBSIZE 250 #define CONFIG_SYS_ENV_NAMELEN 16 #define CONFIG_SYS_MAXARGS 8 diff --git a/include/crc.h b/include/crc.h index c38bae4..927b5ff 100644 --- a/include/crc.h +++ b/include/crc.h @@ -1,12 +1,14 @@ #ifndef CRC_H #define CRC_H +#ifdef __AVR__ #include - static inline uint16_t crc16(uint16_t crc, uint8_t data) { return _crc_ccitt_update(crc, data); } +#else /* !__AVR__ */ +#endif /* __AVR__ */ #endif /* CRC_H */ diff --git a/include/debug.h b/include/debug.h index 7c19e40..8fdc830 100644 --- a/include/debug.h +++ b/include/debug.h @@ -3,7 +3,9 @@ #define DEBUG_H_ #include "common.h" +#ifdef __AVR__ #include +#endif #ifdef DEBUG #define _DEBUG 1 @@ -31,6 +33,8 @@ #endif /* 0 */ +void dump_eep(const uint8_t *addr, unsigned int len, char *title); +void dump_ram(const uint8_t *addr, unsigned int len, char *title); void printfreelist(const char * title); diff --git a/include/i2c.h b/include/i2c.h new file mode 100644 index 0000000..50b1fd0 --- /dev/null +++ b/include/i2c.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2009 Sergey Kubushyn + * Copyright (C) 2009 - 2013 Heiko Schocher + * Changes for multibus/multiadapter I2C support. + * + * (C) Copyright 2001 + * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com. + * + * SPDX-License-Identifier: GPL-2.0+ + * + * The original I2C interface was + * (C) 2000 by Paolo Scaffardi (arsenio@tin.it) + * AIRVENT SAM s.p.a - RIMINI(ITALY) + * but has been changed substantially. + */ + +#ifndef _I2C_H_ +#define _I2C_H_ + +/* + * Configuration items. + */ +/* TODO: config.h? */ +#define I2C_RXTX_LEN 128 /* maximum tx/rx buffer length */ + + +/* + * Initialization, must be called once on start up, may be called + * repeatedly to change the speed. + */ +void i2c_init(uint32_t speed); + +/* + * Probe the given I2C chip address. Returns 0 if a chip responded, + * not 0 on failure. + */ +int i2c_probe(uint8_t chip); + +/* + * Read/Write interface: + * chip: I2C chip address, range 0..127 + * addr: Memory (register) address within the chip + * alen: Number of bytes to use for addr (typically 1, 2 for larger + * memories, 0 for register type devices with only one + * register) + * buffer: Where to read/write the data + * len: How many bytes to read/write + * + * Returns: 0 on success, not 0 on failure + */ +int i2c_read(uint8_t chip, unsigned int addr, uint_fast8_t alen, + uint8_t *buffer, uint_fast8_t len); +int i2c_write(uint8_t chip, unsigned int addr, uint_fast8_t alen, + uint8_t *buffer, uint_fast8_t len); + +/* + * Utility routines to read/write registers. + */ +uint8_t i2c_reg_read(uint8_t addr, uint8_t reg); + +void i2c_reg_write(uint8_t addr, uint8_t reg, uint8_t val); + +#endif /* _I2C_H_*/ diff --git a/include/rtc.h b/include/rtc.h new file mode 100644 index 0000000..15215a9 --- /dev/null +++ b/include/rtc.h @@ -0,0 +1,49 @@ +/* + * (C) Copyright 2001 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * Generic RTC interface. + */ +#ifndef _RTC_H_ +#define _RTC_H_ + + +/* + * The struct used to pass data from the generic interface code to + * the hardware dependend low-level code ande vice versa. Identical + * to struct rtc_time used by the Linux kernel. + * + * Note that there are small but significant differences to the + * common "struct time": + * + * struct time: struct rtc_time: + * tm_mon 0 ... 11 1 ... 12 + * tm_year years since 1900 years since 0 + */ + +struct rtc_time { + int tm_sec; + int tm_min; + int tm_hour; + int tm_mday; + int tm_mon; + int tm_year; + int tm_wday; + int tm_yday; + int tm_isdst; +}; + +int rtc_get (struct rtc_time *); +int rtc_set (struct rtc_time *); +void rtc_reset (void); + +void GregorianDay (struct rtc_time *); +void to_tm (unsigned long, struct rtc_time *); +unsigned long mktime (unsigned int, unsigned int, unsigned int, + unsigned int, unsigned int, unsigned int); + +#endif /* _RTC_H_ */ -- 2.39.2