📄 dallasdate.c
字号:
/* * dallasdate.c: * Code to support the DALLAS DS1743W Timekeeping RAM plus the hooks to * allow TFS to timestamp files. The function tfsTimeEnable() must be * called to setup the connection between TFS and the DS1743W. * * Applicable to DS1743W and DS1746WP. Probably also works with other * Dallas timekeepers, but the above two are the only ones I've tested * it with. This code is assumed to be compiled with the DATEREGBASE * value defined elsewhere. This value is the address at which the code * is to access the 8-byte register map that contains the time/date * information. * * General notice: * This code is part of a boot-monitor package developed as a generic base * platform for embedded system designs. As such, it is likely to be * distributed to various projects beyond the control of the original * author. Please notify the author of any enhancements made or bugs found * so that all may benefit from the changes. In addition, notification back * to the author will allow the new user to pick up changes that may have * been made by other users after this version of the code was distributed. * * Note1: the majority of this code was edited with 4-space tabs. * Note2: as more and more contributions are accepted, the term "author" * is becoming a mis-representation of credit. * * Original author: Ed Sutter * Email: esutter@lucent.com * Phone: 908-582-2351 */#include "config.h"#include "stddefs.h"#include "genlib.h"#include "tfs.h"#include "tfsprivate.h"#include "cli.h"#ifndef DATEREGBASE#error DATEREGBASE not defined#endif#define WRITE 0x80 /* part of 'cent' member */#define READ 0x40 /* part of 'cent' member */#define BF 0x80 /* part of 'wday' member */#define FT 0x40 /* part of 'wday' member */#define OSC_OFF 0x80 /* part of 'sec' member *//* Masks for various portions of the time/date... */#define YEAR10_MASK 0xf0#define MONTH10_MASK 0x10#define DATE10_MASK 0x30#define DAY10_MASK 0x00#define HOUR10_MASK 0x30#define MINUTE10_MASK 0x70#define SECOND10_MASK 0x70#define CENTURY10_MASK 0x30#define YEAR_MASK 0x0f /* Year is 0-99 */#define MONTH_MASK 0x0f /* Month is 1-12 */#define DATE_MASK 0x0f /* Date is 1-31 */#define DAY_MASK 0x07 /* Day is 1-7 */#define HOUR_MASK 0x0f /* Hour is 0-23 */#define MINUTE_MASK 0x0f /* Minutes is 0-59 */#define SECOND_MASK 0x0f /* Seconds is 0-59 */#define CENTURY_MASK 0x0f /* Century is 0-39 */struct dsdate { uchar cent; /* B7=W, B6=R, B5-4=10cent, B3-0=cent (00-39) */ uchar sec; /* B7=OSC; B6-4=10secs; B3-0=sec (0-59) */ uchar min; /* B6-4=10mins; B3-0=min (0-59) */ uchar hour; /* B4-5=10hour; B3-0=hour (0-23) */ uchar wday; /* B7=BF, B6=FT B2-0=day (1-7) */ uchar mday; /* B4-5=10date; B3-0=date (1-31) */ uchar month; /* B4=10mo; B3-0=month (1-12) */ uchar year; /* MS-nibble=10Year; LS-nibble=year (0-99) */};#define DS1743REGS ((struct dsdate *)DATEREGBASE)#define DS_century (DS1743REGS->cent)#define DS_second (DS1743REGS->sec)#define DS_minute (DS1743REGS->min)#define DS_hour (DS1743REGS->hour)#define DS_wday (DS1743REGS->wday)#define DS_mday (DS1743REGS->mday)#define DS_month (DS1743REGS->month)#define DS_year (DS1743REGS->year)#define SECONDS_IN_DAY 86400static charDaysInMonth[] = { 31, 28, 31, 30, 31, 30, /* Jan, Feb, Mar, Apr, May, Jun */ 31, 31, 30, 31, 30, 31 /* Jul, Aug, Sep, Oct, Nov, Dec */};/* rangecheck(): Return 0 if value is outside the range of high and low; else 1.*/static intrangecheck(int value, char *name, int low, int high){ if ((value < low) || (value > high)) { printf("%s outside valid range of %d - %d\n", name,low,high); return(0); } return(1);}/* to_dsdatefmt(): * Take an incoming integer and convert it to the dallas time date * format using a 10-multiplier for the upper nibble. */static unsigned charto_dsdatefmt(int value){ int tens; tens = 0; while (value >= 10) { tens++; value -= 10; } return((tens << 4) | value);}static intfrom_dsdatefmt(unsigned char value, unsigned char mask10){ int newvalue; newvalue = value & 0x0f; newvalue += 10 * ((value & mask10) >> 4); return(newvalue);}static voidshowDate(void){ int day, date, month, year, hour, minute, second, century; DS_century |= READ; /* Set READ bit */ century = from_dsdatefmt(DS_century,CENTURY10_MASK); second = from_dsdatefmt(DS_second,SECOND10_MASK); minute = from_dsdatefmt(DS_minute,MINUTE10_MASK); hour = from_dsdatefmt(DS_hour,HOUR10_MASK); day = from_dsdatefmt(DS_wday,DAY10_MASK); date = from_dsdatefmt(DS_mday,DATE10_MASK); month = from_dsdatefmt(DS_month,MONTH10_MASK); year = (((DS_year & 0xf0) >> 4) * 10) + (DS_year & 0x0f); DS_century &= ~READ; /* Clear READ bit */ printf("%02d/%02d/%02d%02d @ %02d:%02d:%02d\n", month,date,century,year,hour,minute,second);}#if INCLUDE_TFSstatic intYearIsLeap(int year){ if (year % 4) /* if year not divisible by 4... */ return(0); /* it's not leap */ if (year < 1582) /* all years divisible by 4 were */ return(1); /* leap prior to 1582 */ if (year % 100) /* if year divisible by 4, */ return(1); /* but not by 100, it's leap */ if (year % 400) /* if year divisible by 100, */ return(0); /* but not by 400, it's not leap */ else return(1); /* if divisible by 400, it's leap */}/* GetAtime(): * Build a string based on the incoming long value as described in * GetLtime()... * Used by TFS to keep track of file time. */static char *GetAtime(long tval, char *buf, int bsize){ int year; /* Actual year */ int doy; /* Day of year */ int sid; /* Seconds in day */ int leapyear; /* Set if year is leap */ int month, hour, minute; if ((bsize < 18) || (tval == TIME_UNDEFINED)) { *buf = 0; return(buf); } /* Break down the basic bitfields: */ year = 2000 + ((tval >> 26) & 0x3f); leapyear = YearIsLeap(year); doy = ((tval >> 17) & 0x1ff); sid = tval & 0x1ffff; /* Now build the date from the bit fields: */ hour = sid / 3600; sid -= (hour*3600); minute = sid/60; sid -= (minute*60); month = 0; while(doy > DaysInMonth[month]) { doy -= DaysInMonth[month]; if ((month == 1) && (leapyear)) doy--; month++; } sprintf(buf,"%02d/%02d/%02d@%02d:%02d:%02d", month+1,doy,year,hour,minute,sid); return(buf);}/* GetLtime(): * Build a long with the following format.... * * B31-26 year since 2000 (0-127 yep, this breaks in 2128) * B25-17 day of year (1-365) * B16-0 seconds in day (0-86400) * * Used by TFS to keep track of file time. */static longGetLtime(void){ long tval; int year, month, mday, seconds, doy, leapyear; DS_century |= READ; /* Set READ bit */ year = from_dsdatefmt(DS_year,YEAR10_MASK); /* 00=2000 */ month = from_dsdatefmt(DS_month,MONTH10_MASK)-1; /* 0-11 */ mday = from_dsdatefmt(DS_mday,DATE10_MASK); /* 1-31 */ leapyear = YearIsLeap(year+2000); if ((month > 11) || (month < 0) || (mday < 1) || (mday > 31)) return(TIME_UNDEFINED); /* Determine current day of year... */ doy = mday; while(month > 0) { doy += DaysInMonth[month-1]; if ((month == 1) && leapyear) doy++; month--; } /* Determine current second of day... */ seconds = (from_dsdatefmt(DS_hour,HOUR10_MASK) * 3600); seconds += (from_dsdatefmt(DS_minute,MINUTE10_MASK) * 60); seconds += from_dsdatefmt(DS_second,SECOND10_MASK); DS_century &= ~READ; /* Clear READ bit */ tval = (((year & 0x3f) << 26) | ((doy & 0x1ff) << 17) | (seconds & 0x1ffff)); return(tval);}/* tfsTimeEnable(): * Hook the file timestamping in TFS to the DS1743 device... */voidtfsTimeEnable(void){ tfsctrl(TFS_TIMEFUNCS,(long)GetLtime,(long)GetAtime);}#endifchar *DateHelp[] = { "Display (mm/dd/yyyy@hh:mm:ss) or modify time and date.", "[{day date month year hour min sec}]", "Where...", " day: 1-7 (sun=1)", " date: 1-31", " month: 1-12", " year: 0-3899", " hour: 0-23", " min: 0-59", " sec: 0-59", "Note: 'date off' disables the oscillator", 0};intDate(int argc,char *argv[]){ int day, date, month, year, hour, minute, second, century, rngchk; if ((DS_wday & BF) == 0) printf("Warning: battery dead.\n"); if (argc == 1) { if (DS_second & OSC_OFF) printf("Warning: oscillator disabled.\n"); showDate(); return(CMD_SUCCESS); } else if ((argc == 2) && !strcmp(argv[1],"off")) { DS_century |= WRITE; /* Disable the oscillator */ DS_second = OSC_OFF; /* to save battery life. */ DS_century &= ~WRITE; return(CMD_SUCCESS); } else if (argc != 8) return(CMD_PARAM_ERROR); day = atoi(argv[1]); date = atoi(argv[2]); month = atoi(argv[3]); year = atoi(argv[4]); hour = atoi(argv[5]); minute = atoi(argv[6]); second = atoi(argv[7]); rngchk = 0; rngchk += rangecheck(day,"day",1,7); rngchk += rangecheck(date,"date",1,31); rngchk += rangecheck(month,"month",1,12); rngchk += rangecheck(year,"year",0,3899); rngchk += rangecheck(hour,"hour",0,23); rngchk += rangecheck(minute,"minute",0,59); rngchk += rangecheck(second,"second",0,59); if (rngchk != 7) return(CMD_PARAM_ERROR); DS_century = WRITE; /* Set WRITE bit */ DS_second = to_dsdatefmt(second) & ~OSC_OFF; DS_minute = to_dsdatefmt(minute); DS_hour = to_dsdatefmt(hour); DS_wday = day; DS_mday = to_dsdatefmt(date); DS_month = to_dsdatefmt(month); century = year / 100; year = year % 100; DS_year = to_dsdatefmt(year); DS_century = (to_dsdatefmt(century)&(CENTURY_MASK|CENTURY10_MASK))|WRITE; DS_century &= ~WRITE; /* Clear WRITE bit */ return(CMD_SUCCESS);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -