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);
-}
--
⑨