shithub: util

Download patch

ref: 7ad5e3ef8905ce04b9cdb3dca8e11732ec932ba9
parent: 64d934dd3248b39915c703630a07396885604a36
author: eli <eli@singularity>
date: Fri Oct 3 16:46:52 EDT 2025

mcp7940x

--- /dev/null
+++ b/mcp7940x.c
@@ -1,0 +1,295 @@
+#include <u.h>
+#include <libc.h>
+#include <fcall.h>
+#include <thread.h>
+#include <9p.h>
+
+#define CTL "%s/i2c.6f.ctl"
+#define DATA "%s/i2c.6f.data"
+
+char *i2cdir = "/dev/i2c1";
+
+enum {
+	/* registers */
+	Seconds=	0,
+	Minutes=	1,
+	Hours=		2,
+	Weekday=	3,
+	Mday=		4,
+	Month=		5,
+	Year=		6,
+	Nbcd=		7,
+
+	/* Hours register may be in 12-hour or 24-hour mode */
+	Twelvehr=	0x40,
+	Pm=			0x20,
+
+	Start=		0x80,
+	Vbaten=		0x08,
+};
+
+typedef struct Rtc	Rtc;
+
+struct Rtc
+{
+	int	sec;
+	int	min;
+	int	hour;
+	int	mday;
+	int	mon;
+	int	year;
+};
+
+#define SEC2MIN 60L
+#define SEC2HOUR (60L*SEC2MIN)
+#define SEC2DAY (24L*SEC2HOUR)
+
+/*
+ *  days per month plus days/year
+ */
+static	int	dmsize[] =
+{
+	365, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+};
+static	int	ldmsize[] =
+{
+	366, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+};
+
+/*
+ *  return the days/month for the given year
+ */
+static int*
+yrsize(int y)
+{
+	if((y%4) == 0 && ((y%100) != 0 || (y%400) == 0))
+		return ldmsize;
+	else
+		return dmsize;
+}
+
+/*
+ *  compute seconds since Jan 1 1970
+ */
+static ulong
+rtc2sec(Rtc *rtc)
+{
+	ulong secs;
+	int i;
+	int *d2m;
+
+	secs = 0;
+
+	/*
+	 *  seconds per year
+	 */
+	for(i = 1970; i < rtc->year; i++){
+		d2m = yrsize(i);
+		secs += d2m[0] * SEC2DAY;
+	}
+
+	/*
+	 *  seconds per month
+	 */
+	d2m = yrsize(rtc->year);
+	for(i = 1; i < rtc->mon; i++)
+		secs += d2m[i] * SEC2DAY;
+
+	secs += (rtc->mday-1) * SEC2DAY;
+	secs += rtc->hour * SEC2HOUR;
+	secs += rtc->min * SEC2MIN;
+	secs += rtc->sec;
+
+	return secs;
+}
+
+/*
+ *  compute rtc from seconds since Jan 1 1970
+ */
+static void
+sec2rtc(ulong secs, Rtc *rtc)
+{
+	int d;
+	long hms, day;
+	int *d2m;
+
+	/*
+	 * break initial number into days
+	 */
+	hms = secs % SEC2DAY;
+	day = secs / SEC2DAY;
+	if(hms < 0) {
+		hms += SEC2DAY;
+		day -= 1;
+	}
+
+	/*
+	 * generate hours:minutes:seconds
+	 */
+	rtc->sec = hms % 60;
+	d = hms / 60;
+	rtc->min = d % 60;
+	d /= 60;
+	rtc->hour = d;
+
+	/*
+	 * year number
+	 */
+	if(day >= 0)
+		for(d = 1970; day >= *yrsize(d); d++)
+			day -= *yrsize(d);
+	else
+		for (d = 1970; day < 0; d--)
+			day += *yrsize(d-1);
+	rtc->year = d;
+
+	/*
+	 * generate month
+	 */
+	d2m = yrsize(rtc->year);
+	for(d = 1; day >= d2m[d]; d++)
+		day -= d2m[d];
+	rtc->mday = day + 1;
+	rtc->mon = d;
+
+	return;
+}
+
+void
+ctl(char *s)
+{
+	char *ctl = smprint(CTL, i2cdir);
+	if (ctl == nil)
+		sysfatal("smprint: %r");
+	int fd = open(ctl, OWRITE);
+	if (fd < 0)
+		sysfatal("open: %r");
+	free(ctl);
+	write(fd, s, strlen(s));
+	close(fd);
+}
+
+static int
+bcd(int n)
+{
+	return (n & 0xF) + (10 * (n >> 4));
+}
+
+void
+fsread(Req *r)
+{
+	int fd;
+	uchar clk[Nbcd];
+	Rtc rtc;
+	char buf[256];
+	ulong t;
+	char *data;
+
+	clk[0] = 0;
+
+	if ((intptr)(r->fid->file->aux) == 173) {
+		data = smprint(DATA, i2cdir);
+		if (data == nil)
+			sysfatal("smprint: %r");
+		fd = open(data, ORDWR);
+		if (fd < 0)
+			sysfatal("open: %r");
+		free(data);
+		write(fd, clk, 1);
+		read(fd, clk, Nbcd);
+		close(fd);
+
+		rtc.sec = bcd(clk[Seconds] & 0x7F);
+		rtc.min = bcd(clk[Minutes] & 0x7F);
+		rtc.hour = bcd(clk[Hours] & 0x3F);
+		if(clk[Hours] & Twelvehr){
+			rtc.hour = bcd(clk[Hours] & 0x1F);
+			if(clk[Hours] & Pm)
+				rtc.hour += 12;
+		}
+		rtc.mday = bcd(clk[Mday] & 0x3F);
+		rtc.mon = bcd(clk[Month] & 0x1F);
+		rtc.year = bcd(clk[Year]);
+
+		if(rtc.year < 70)
+			rtc.year += 2000;
+		else
+			rtc.year += 1900;
+
+		t = rtc2sec(&rtc);
+		snprint(buf, 256, "%12lud", t);
+		readstr(r, buf);
+		respond(r, nil);
+	} else {
+		respond(r, "file not found");
+	}
+}
+
+#define PUTBCD(n,o) bcdclock[1+o] = (n % 10) | (((n / 10) % 10)<<4)
+
+void
+fswrite(Req *r)
+{
+	Rtc rtc;
+	ulong secs;
+	uchar bcdclock[1+Nbcd];
+	char *p, *ep;
+	int fd;
+	char *data;
+
+	if ((intptr)(r->fid->file->aux) == 173) {
+		p = r->ifcall.data;
+		ep = p + r->ifcall.count;
+
+		while(p < ep)
+			if (*p >= '0' && *p <= '9')
+				break;
+			else
+				p++;
+
+		secs = strtoul(p, 0, 0);
+		sec2rtc(secs, &rtc);
+		PUTBCD(rtc.sec, Seconds);
+		PUTBCD(rtc.min, Minutes);	/* forces 24 hour mode */
+		PUTBCD(rtc.hour, Hours);
+		PUTBCD(0, Weekday);		/* hope no other OS uses this */
+		PUTBCD(rtc.mday, Mday);
+		PUTBCD(rtc.mon, Month);
+		PUTBCD(rtc.year, Year);
+
+		bcdclock[0] = 0;
+
+		bcdclock[1+Seconds] |= Start;
+		bcdclock[1+Weekday] |= Vbaten;
+
+		data = smprint(DATA, i2cdir);
+		if (data == nil)
+			sysfatal("smprint: %r");
+		fd = open(data, OWRITE);
+		if (fd < 0)
+			sysfatal("open: %r");
+		free(data);
+		write(fd, bcdclock, 1+Nbcd);
+		close(fd);
+
+		respond(r, nil);
+	} else {
+		respond(r, "file not found");
+	}
+}
+
+Srv fs = {
+.read	= fsread,
+.write	= fswrite,
+};
+
+void
+main()
+{
+	ctl("size 10");
+	ctl("subaddress 0");
+
+	fs.tree = alloctree("mcp7940x", "mcp7940x", DMDIR|0555, nil);
+	createfile(fs.tree->root, "rtc", "mcp7940x", 0666, (void*)173);
+	postmountsrv(&fs, "mcp7940x", "/dev", MBEFORE);
+}
--- a/rtc7940fs.c
+++ /dev/null
@@ -1,279 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <fcall.h>
-#include <thread.h>
-#include <9p.h>
-
-#define CTL "/dev/i2c1/i2c.6f.ctl"
-#define DATA "/dev/i2c1/i2c.6f.data"
-
-enum {
-	/* registers */
-	Seconds=	0,
-	Minutes=	1,
-	Hours=		2,
-	Weekday=	3,
-	Mday=		4,
-	Month=		5,
-	Year=		6,
-	Nbcd=		7,
-
-	/* Hours register may be in 12-hour or 24-hour mode */
-	Twelvehr=	0x40,
-	Pm=			0x20,
-
-	Start=		0x80,
-	Vbaten=		0x08,
-};
-
-typedef struct Rtc	Rtc;
-
-struct Rtc
-{
-	int	sec;
-	int	min;
-	int	hour;
-	int	mday;
-	int	mon;
-	int	year;
-};
-
-#define SEC2MIN 60L
-#define SEC2HOUR (60L*SEC2MIN)
-#define SEC2DAY (24L*SEC2HOUR)
-
-/*
- *  days per month plus days/year
- */
-static	int	dmsize[] =
-{
-	365, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
-};
-static	int	ldmsize[] =
-{
-	366, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
-};
-
-/*
- *  return the days/month for the given year
- */
-static int*
-yrsize(int y)
-{
-	if((y%4) == 0 && ((y%100) != 0 || (y%400) == 0))
-		return ldmsize;
-	else
-		return dmsize;
-}
-
-/*
- *  compute seconds since Jan 1 1970
- */
-static ulong
-rtc2sec(Rtc *rtc)
-{
-	ulong secs;
-	int i;
-	int *d2m;
-
-	secs = 0;
-
-	/*
-	 *  seconds per year
-	 */
-	for(i = 1970; i < rtc->year; i++){
-		d2m = yrsize(i);
-		secs += d2m[0] * SEC2DAY;
-	}
-
-	/*
-	 *  seconds per month
-	 */
-	d2m = yrsize(rtc->year);
-	for(i = 1; i < rtc->mon; i++)
-		secs += d2m[i] * SEC2DAY;
-
-	secs += (rtc->mday-1) * SEC2DAY;
-	secs += rtc->hour * SEC2HOUR;
-	secs += rtc->min * SEC2MIN;
-	secs += rtc->sec;
-
-	return secs;
-}
-
-/*
- *  compute rtc from seconds since Jan 1 1970
- */
-static void
-sec2rtc(ulong secs, Rtc *rtc)
-{
-	int d;
-	long hms, day;
-	int *d2m;
-
-	/*
-	 * break initial number into days
-	 */
-	hms = secs % SEC2DAY;
-	day = secs / SEC2DAY;
-	if(hms < 0) {
-		hms += SEC2DAY;
-		day -= 1;
-	}
-
-	/*
-	 * generate hours:minutes:seconds
-	 */
-	rtc->sec = hms % 60;
-	d = hms / 60;
-	rtc->min = d % 60;
-	d /= 60;
-	rtc->hour = d;
-
-	/*
-	 * year number
-	 */
-	if(day >= 0)
-		for(d = 1970; day >= *yrsize(d); d++)
-			day -= *yrsize(d);
-	else
-		for (d = 1970; day < 0; d--)
-			day += *yrsize(d-1);
-	rtc->year = d;
-
-	/*
-	 * generate month
-	 */
-	d2m = yrsize(rtc->year);
-	for(d = 1; day >= d2m[d]; d++)
-		day -= d2m[d];
-	rtc->mday = day + 1;
-	rtc->mon = d;
-
-	return;
-}
-
-void
-ctl(char *s)
-{
-	int fd = open(CTL, OWRITE);
-	if (fd < 0)
-		sysfatal("open: %r");
-	write(fd, s, strlen(s));
-	close(fd);
-}
-
-static int
-bcd(int n)
-{
-	return (n & 0xF) + (10 * (n >> 4));
-}
-
-void
-fsread(Req *r)
-{
-	int fd;
-	uchar clk[Nbcd];
-	Rtc rtc;
-	char buf[256];
-	ulong t;
-
-	clk[0] = 0;
-
-	if ((intptr)(r->fid->file->aux) == 173) {
-		fd = open(DATA, ORDWR);
-		if (fd < 0)
-			sysfatal("open: %r");
-		write(fd, clk, 1);
-		read(fd, clk, Nbcd);
-		close(fd);
-
-		rtc.sec = bcd(clk[Seconds] & 0x7F);
-		rtc.min = bcd(clk[Minutes] & 0x7F);
-		rtc.hour = bcd(clk[Hours] & 0x3F);
-		if(clk[Hours] & Twelvehr){
-			rtc.hour = bcd(clk[Hours] & 0x1F);
-			if(clk[Hours] & Pm)
-				rtc.hour += 12;
-		}
-		rtc.mday = bcd(clk[Mday] & 0x3F);
-		rtc.mon = bcd(clk[Month] & 0x1F);
-		rtc.year = bcd(clk[Year]);
-
-		if(rtc.year < 70)
-			rtc.year += 2000;
-		else
-			rtc.year += 1900;
-
-		t = rtc2sec(&rtc);
-		snprint(buf, 256, "%12lud", t);
-		readstr(r, buf);
-		respond(r, nil);
-	} else {
-		respond(r, "file not found");
-	}
-}
-
-#define PUTBCD(n,o) bcdclock[1+o] = (n % 10) | (((n / 10) % 10)<<4)
-
-void
-fswrite(Req *r)
-{
-	Rtc rtc;
-	ulong secs;
-	uchar bcdclock[1+Nbcd];
-	char *p, *ep;
-	int fd;
-
-	if ((intptr)(r->fid->file->aux) == 173) {
-		p = r->ifcall.data;
-		ep = p + r->ifcall.count;
-
-		while(p < ep)
-			if (*p >= '0' && *p <= '9')
-				break;
-			else
-				p++;
-
-		secs = strtoul(p, 0, 0);
-		sec2rtc(secs, &rtc);
-		PUTBCD(rtc.sec, Seconds);
-		PUTBCD(rtc.min, Minutes);	/* forces 24 hour mode */
-		PUTBCD(rtc.hour, Hours);
-		PUTBCD(0, Weekday);		/* hope no other OS uses this */
-		PUTBCD(rtc.mday, Mday);
-		PUTBCD(rtc.mon, Month);
-		PUTBCD(rtc.year, Year);
-
-		bcdclock[0] = 0;
-
-		bcdclock[1+Seconds] |= Start;
-		bcdclock[1+Weekday] |= Vbaten;
-
-		fd = open(DATA, OWRITE);
-		if (fd < 0)
-			sysfatal("open: %r");
-		write(fd, bcdclock, 1+Nbcd);
-		close(fd);
-
-		respond(r, nil);
-	} else {
-		respond(r, "file not found");
-	}
-}
-
-Srv fs = {
-.read	= fsread,
-.write	= fswrite,
-};
-
-void
-main()
-{
-	ctl("size 10");
-	ctl("subaddress 0");
-
-	fs.tree = alloctree("rtcfs", "rtcfs", DMDIR|0555, nil);
-	createfile(fs.tree->root, "rtc", "rtcfs", 0666, (void*)173);
-	postmountsrv(&fs, "rtc", "/dev", MBEFORE);
-}
--