source: umon/main/common/dallasdate.c @ 87db514

Last change on this file since 87db514 was 87db514, checked in by Amar Takhar <amar@…>, on 04/16/15 at 19:26:21

Initial commit of the umon repository.

Prior to this three changes were made:

  • Remove umon_ prefix from parent directories.
  • Collapse main/target/ into main/
  • Remove ports/template/flashtest.scr.ucon script.
  • Property mode set to 100644
File size: 9.6 KB
Line 
1/**************************************************************************
2 *
3 * Copyright (c) 2013 Alcatel-Lucent
4 *
5 * Alcatel Lucent licenses this file to You under the Apache License,
6 * Version 2.0 (the "License"); you may not use this file except in
7 * compliance with the License.  A copy of the License is contained the
8 * file LICENSE at the top level of this repository.
9 * You may also obtain a copy of the License at:
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 **************************************************************************
20 *
21 * dallasdate.c:
22 *
23 * Code to support the DALLAS DS1743W Timekeeping RAM plus the hooks to
24 * allow TFS to timestamp files.  The function tfsTimeEnable() must be
25 * called to setup the connection between TFS and the DS1743W.
26 *
27 * Applicable to DS1743W and DS1746WP.  Probably also works with other
28 * Dallas timekeepers, but the above two are the only ones I've tested
29 * it with.  This code is assumed to be compiled with the DATEREGBASE
30 * value defined elsewhere.  This value is the address at which the code
31 * is to access the 8-byte register map that contains the time/date
32 * information.
33 *
34 *
35 * Original author:     Ed Sutter (ed.sutter@alcatel-lucent.com)
36 *
37 */
38#include "config.h"
39#include "stddefs.h"
40#include "genlib.h"
41#include "tfs.h"
42#include "tfsprivate.h"
43#include "cli.h"
44
45#ifndef DATEREGBASE
46#error DATEREGBASE not defined
47#endif
48
49#define WRITE   0x80            /* part of 'cent' member */
50#define READ    0x40            /* part of 'cent' member */
51#define FT              0x40            /* part of 'wday' member */
52#define OSC_OFF 0x80            /* part of 'sec' member */
53
54/* Masks for various portions of the time/date... */
55#define YEAR10_MASK             0xf0
56#define MONTH10_MASK    0x10
57#define DATE10_MASK             0x30
58#define DAY10_MASK              0x00
59#define HOUR10_MASK             0x30
60#define MINUTE10_MASK   0x70
61#define SECOND10_MASK   0x70
62#define CENTURY10_MASK  0x30
63#define YEAR_MASK               0x0f    /* Year is 0-99 */
64#define MONTH_MASK              0x0f    /* Month is 1-12 */
65#define DATE_MASK               0x0f    /* Date is 1-31 */
66#define DAY_MASK                0x07    /* Day is 1-7 */
67#define HOUR_MASK               0x0f    /* Hour is 0-23 */
68#define MINUTE_MASK             0x0f    /* Minutes is 0-59 */
69#define SECOND_MASK             0x0f    /* Seconds is 0-59 */
70#define CENTURY_MASK    0x0f    /* Century is 0-39 */
71
72struct dsdate {
73        uchar cent;             /* B7=W, B6=R, B5-4=10cent, B3-0=cent (00-39) */
74        uchar sec;              /* B7=OSC; B6-4=10secs; B3-0=sec (0-59) */
75        uchar min;              /* B6-4=10mins; B3-0=min (0-59) */
76        uchar hour;             /* B4-5=10hour; B3-0=hour (0-23) */
77        uchar wday;             /* B6=FT B2-0=day (1-7) */
78        uchar mday;             /* B4-5=10date; B3-0=date (1-31) */
79        uchar month;    /* B4=10mo; B3-0=month (1-12) */
80        uchar year;             /* MS-nibble=10Year; LS-nibble=year (0-99) */
81};
82
83#define DS1743REGS              ((struct dsdate *)DATEREGBASE)
84#define DS_century              (DS1743REGS->cent)
85#define DS_second               (DS1743REGS->sec)
86#define DS_minute               (DS1743REGS->min)
87#define DS_hour                 (DS1743REGS->hour)
88#define DS_wday                 (DS1743REGS->wday)
89#define DS_mday                 (DS1743REGS->mday)
90#define DS_month                (DS1743REGS->month)
91#define DS_year                 (DS1743REGS->year)
92
93#define SECONDS_IN_DAY  86400
94
95static char
96DaysInMonth[] = {
97    31, 28, 31, 30, 31, 30,     /* Jan, Feb, Mar, Apr, May, Jun */
98    31, 31, 30, 31, 30, 31              /* Jul, Aug, Sep, Oct, Nov, Dec */
99};
100
101/* rangecheck():
102        Return 0 if value is outside the range of high and low; else 1.
103*/
104static int
105rangecheck(int value, char *name, int low, int high)
106{
107        if ((value < low) || (value > high)) {
108                printf("%s outside valid range of %d - %d\n",
109                        name,low,high);
110                return(0);
111        }
112        return(1);
113}
114
115/* to_dsdatefmt():
116 * Take an incoming integer and convert it to the dallas time date
117 * format using a 10-multiplier for the upper nibble.
118 */
119static unsigned char
120to_dsdatefmt(int value)
121{
122        int     tens;
123
124        tens = 0;
125        while (value >= 10) {
126                tens++;
127                value -= 10;
128        }
129        return((tens << 4) | value);
130}
131
132static int
133from_dsdatefmt(unsigned char value, unsigned char mask10)
134{
135        int     newvalue;
136       
137        newvalue = value & 0x0f;
138        newvalue += 10 * ((value & mask10) >> 4);
139        return(newvalue);
140}
141
142int
143showDate(int center)
144{
145        int     (*pfunc)(char *, ...);
146        int     day, date, month, year, hour, minute, second, century;
147
148        DS_century |= READ;     /* Set READ bit */
149
150        century = from_dsdatefmt(DS_century,CENTURY10_MASK);
151        second = from_dsdatefmt(DS_second,SECOND10_MASK);
152        minute = from_dsdatefmt(DS_minute,MINUTE10_MASK);
153        hour = from_dsdatefmt(DS_hour,HOUR10_MASK);
154        day = from_dsdatefmt(DS_wday,DAY10_MASK);
155        date = from_dsdatefmt(DS_mday,DATE10_MASK);
156        month = from_dsdatefmt(DS_month,MONTH10_MASK);
157        year = (((DS_year & 0xf0) >> 4) * 10) + (DS_year & 0x0f);
158
159        DS_century &= ~READ;    /* Clear READ bit */
160
161        if (center)
162                pfunc = cprintf;
163        else
164                pfunc = printf;
165
166        pfunc("%02d/%02d/%02d%02d @ %02d:%02d:%02d\n",
167                month,date,century,year,hour,minute,second);
168
169        return(0);
170}
171
172#if INCLUDE_TFS
173
174static int
175YearIsLeap(int year)
176{
177    if (year % 4)               /* if year not divisible by 4... */
178        return(0);              /* it's not leap */
179    if (year < 1582)    /* all years divisible by 4 were */
180        return(1);              /* leap prior to 1582            */
181    if (year % 100)             /* if year divisible by 4, */
182        return(1);              /* but not by 100, it's leap */
183    if (year % 400)             /* if year divisible by 100, */
184        return(0);              /* but not by 400, it's not leap */
185    else
186        return(1);              /* if divisible by 400, it's leap */
187}
188
189/* GetAtime():
190 *      Build a string based on the incoming long value as described in
191 *      GetLtime()...
192 *      Used by TFS to keep track of file time.
193 */
194static char *
195GetAtime(long tval, char *buf, int bsize)
196{
197        int     year;           /* Actual year */
198        int     doy;            /* Day of year */
199        int     sid;            /* Seconds in day */
200        int     leapyear;       /* Set if year is leap */
201        int     month, hour, minute;
202
203        if ((bsize < 18)  || (tval == TIME_UNDEFINED)) {
204                *buf = 0;
205                return(buf);
206        }
207
208        /* Break down the basic bitfields: */
209        year = 2000 + ((tval >> 26) & 0x3f);
210        leapyear = YearIsLeap(year);
211        doy = ((tval >> 17) & 0x1ff);
212        sid = tval & 0x1ffff;
213
214        /* Now build the date from the bit fields: */
215        hour = sid / 3600;
216        sid -= (hour*3600);
217        minute = sid/60;
218        sid -= (minute*60);
219
220        month = 0;
221        while(doy > DaysInMonth[month]) {
222                doy -= DaysInMonth[month];
223                if ((month == 1) && (leapyear))
224                        doy--;
225                month++;
226        }
227        sprintf(buf,"%02d/%02d/%02d@%02d:%02d:%02d",
228                month+1,doy,year,hour,minute,sid);
229        return(buf);
230}
231
232/* GetLtime():
233 *      Build a long with the following format....
234 * 
235 *      B31-26          year since 2000         (0-127 yep, this breaks in 2128)
236 *      B25-17          day of year                     (1-365)
237 *      B16-0           seconds in day          (0-86400)
238 *
239 *      Used by TFS to keep track of file time.
240 */
241static long
242GetLtime(void)
243{
244        long    tval;
245        int             year, month, mday, seconds, doy, leapyear;
246
247        DS_century |= READ;     /* Set READ bit */
248
249        year = from_dsdatefmt(DS_year,YEAR10_MASK);                     /* 00=2000 */
250        month = from_dsdatefmt(DS_month,MONTH10_MASK)-1;                /* 0-11 */
251        mday = from_dsdatefmt(DS_mday,DATE10_MASK);                     /* 1-31 */
252        leapyear = YearIsLeap(year+2000);
253
254        if ((month > 11) || (month < 0) || (mday < 1) || (mday > 31))
255                return(TIME_UNDEFINED);
256
257        /* Determine current day of year... */
258        doy = mday;
259        while(month > 0) {
260                doy += DaysInMonth[month-1];
261                if ((month == 1) && leapyear)
262                        doy++;
263                month--;
264        }
265
266        /* Determine current second of day... */
267        seconds = (from_dsdatefmt(DS_hour,HOUR10_MASK) * 3600);
268        seconds += (from_dsdatefmt(DS_minute,MINUTE10_MASK) * 60);
269        seconds += from_dsdatefmt(DS_second,SECOND10_MASK);
270
271        DS_century &= ~READ;    /* Clear READ bit */
272
273        tval = (((year & 0x3f) << 26) |
274                        ((doy & 0x1ff) << 17) |
275                        (seconds & 0x1ffff));
276        return(tval);
277}
278
279/* tfsTimeEnable():
280 *      Hook the file timestamping in TFS to the DS1743 device...
281 */
282void
283tfsTimeEnable(void)
284{
285        tfsctrl(TFS_TIMEFUNCS,(long)GetLtime,(long)GetAtime);
286}
287#endif
288
289char *DateHelp[] = {
290        "Display (mm/dd/yyyy@hh:mm:ss) or modify time and date.",
291        "[{day date month year hour min sec}]",
292#if INCLUDE_VERBOSEHELP
293        "Where...",
294        " day:   1-7 (sun=1)",
295        " date:  1-31",
296        " month: 1-12",
297        " year:  0-3899",
298        " hour:  0-23",
299        " min:   0-59",
300        " sec:   0-59",
301        "Note: 'date off' disables the oscillator",
302#endif
303        0
304};
305
306int
307Date(int argc,char *argv[])
308{
309        int     day, date, month, year, hour, minute, second, century, rngchk;
310
311        if (argc == 1) {
312                if (DS_second & OSC_OFF)
313                        printf("Warning: oscillator disabled.\n");
314                showDate(0);
315                return(CMD_SUCCESS);
316        }
317        else if ((argc == 2) && !strcmp(argv[1],"off")) {
318                DS_century |= WRITE;                    /* Disable the oscillator */
319                DS_second = OSC_OFF;                    /* to save battery life. */
320                DS_century &= ~WRITE;
321                return(CMD_SUCCESS);
322        }
323        else if (argc != 8)
324                return(CMD_PARAM_ERROR);
325
326        day = atoi(argv[1]);
327        date = atoi(argv[2]);
328        month = atoi(argv[3]);
329        year = atoi(argv[4]);
330        hour = atoi(argv[5]);
331        minute = atoi(argv[6]);
332        second = atoi(argv[7]);
333
334        rngchk = 0;
335        rngchk += rangecheck(day,"day",1,7);
336        rngchk += rangecheck(date,"date",1,31);
337        rngchk += rangecheck(month,"month",1,12);
338        rngchk += rangecheck(year,"year",0,3899);
339        rngchk += rangecheck(hour,"hour",0,23);
340        rngchk += rangecheck(minute,"minute",0,59);
341        rngchk += rangecheck(second,"second",0,59);
342
343        if (rngchk != 7)
344                return(CMD_PARAM_ERROR);
345       
346        DS_century = WRITE;             /* Set WRITE bit */
347        DS_second = to_dsdatefmt(second) & ~OSC_OFF;
348        DS_minute = to_dsdatefmt(minute);
349        DS_hour = to_dsdatefmt(hour);
350        DS_wday = day;
351        DS_mday = to_dsdatefmt(date);
352        DS_month = to_dsdatefmt(month);
353        century = year / 100;
354        year = year % 100;
355        DS_year = to_dsdatefmt(year);
356        DS_century = (to_dsdatefmt(century)&(CENTURY_MASK|CENTURY10_MASK))|WRITE;
357
358        DS_century &= ~WRITE;           /* Clear WRITE bit */
359        return(CMD_SUCCESS);
360}
361
362
Note: See TracBrowser for help on using the repository browser.