📄 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 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; /* 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 86400
static char
DaysInMonth[] = {
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 int
rangecheck(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 char
to_dsdatefmt(int value)
{
int tens;
tens = 0;
while (value >= 10) {
tens++;
value -= 10;
}
return((tens << 4) | value);
}
static int
from_dsdatefmt(unsigned char value, unsigned char mask10)
{
int newvalue;
newvalue = value & 0x0f;
newvalue += 10 * ((value & mask10) >> 4);
return(newvalue);
}
int
showDate(int center)
{
int (*pfunc)(char *, ...);
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 */
if (center)
pfunc = cprintf;
else
pfunc = printf;
pfunc("%02d/%02d/%02d%02d @ %02d:%02d:%02d\n",
month,date,century,year,hour,minute,second);
return(0);
}
#if INCLUDE_TFS
static int
YearIsLeap(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 long
GetLtime(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...
*/
void
tfsTimeEnable(void)
{
tfsctrl(TFS_TIMEFUNCS,(long)GetLtime,(long)GetAtime);
}
#endif
char *DateHelp[] = {
"Display (mm/dd/yyyy@hh:mm:ss) or modify time and date.",
"[{day date month year hour min sec}]",
#if INCLUDE_VERBOSEHELP
"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",
#endif
0
};
int
Date(int argc,char *argv[])
{
int day, date, month, year, hour, minute, second, century, rngchk;
if (argc == 1) {
if (DS_second & OSC_OFF)
printf("Warning: oscillator disabled.\n");
showDate(0);
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 + -