⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dallasdate.c

📁 umon bootloader source code, support mips cpu.
💻 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 + -