File Coverage

DS3231.xs
Criterion Covered Total %
statement 0 180 0.0
branch 0 76 0.0
condition n/a
subroutine n/a
pod n/a
total 0 256 0.0


line stmt bran cond sub pod time code
1             #include "EXTERN.h"
2             #include "perl.h"
3             #include "XSUB.h"
4             #include
5             #include
6             #include
7             #include
8             #include
9             #include
10             #include
11             #include
12             #include
13             #include
14             #include "rtc.h"
15             #include "bit.h"
16              
17             /* top-level register */
18              
19             #define RTC_REG_DT 0x00
20              
21             /* sub-level registers */
22              
23             #define RTC_SEC 0x00 // 0-59
24             #define RTC_MIN 0x01 // 0-59
25             #define RTC_HOUR 0x02 // 1-12 (12-hr clock), 0-23 (24-hr clock)
26             #define RTC_WDAY 0x03 // day of week (1-7)
27             #define RTC_MDAY 0x04 // day of month (1-31)
28             #define RTC_MONTH 0x05 // 1-12
29             #define RTC_YEAR 0x06 // 1-99
30              
31             #define RTC_TEMP_MSB 0x11
32             #define RTC_TEMP_LSB 0x12
33              
34             /* sub-level register bits */
35              
36             // RTC_HOUR sub-level register bits
37              
38             #define RTC_AM_PM 0x05
39             #define RTC_12_24 0x06
40              
41 0           int getSeconds (int fd){
42 0           return bcd2dec(getRegister(fd, RTC_SEC));
43             }
44              
45 0           void setSeconds (int fd, int value){
46 0 0         if (value < 0 || value > 59){
    0          
47 0           croak("seconds parameter out of bounds. Must be between 0-59\n");
48             }
49 0           setRegister(fd, RTC_SEC, dec2bcd(value), "seconds");
50 0           }
51              
52 0           int getMinutes (int fd){
53 0           return bcd2dec(getRegister(fd, RTC_MIN));
54             }
55              
56 0           void setMinutes (int fd, int value){
57 0 0         if (value < 0 || value > 59){
    0          
58 0           croak("minutes parameter out of bounds. Must be between 0-59\n");
59             }
60 0           setRegister(fd, RTC_MIN, dec2bcd(value), "minutes");
61 0           }
62              
63 0           int getHour (int fd){
64            
65             int hour;
66              
67 0 0         if ((getRegisterBit(fd, RTC_HOUR, RTC_12_24)) == 0){
68             // 24 hr clock
69 0           hour = getRegister(fd, RTC_HOUR);
70             }
71             else {
72             // 12 hr clock
73 0           hour = getRegisterBits(fd, RTC_HOUR, 4, 0);
74             }
75 0           return bcd2dec(hour);
76             }
77              
78 0           void setHour (int fd, int value){
79              
80 0 0         if ((getRegisterBit(fd, RTC_HOUR, RTC_12_24)) != 0){
81             // 12 hour clock
82              
83 0 0         if (value > 12 || value < 1){
    0          
84 0           char* error =
85             "hour (%d) is out of bounds when in 12-hour clock " \
86             "mode. Valid values are 1-12";
87              
88 0           croak(error);
89             }
90 0           setRegisterBits(fd, RTC_HOUR, 0, 5, value, "hour");
91             }
92             else {
93             // 24 hour clock
94              
95 0 0         if (value > 23 || value < 0){
    0          
96 0           char* error =
97             "hour (%d) is out of bounds when in 24-hour clock " \
98             "mode. Valid values are 0-23";
99              
100 0           croak(error);
101             }
102 0           value = dec2bcd(value);
103 0           setRegister(fd, RTC_HOUR, value, "hour");
104             }
105 0           }
106              
107 0           const char* getDayOfWeek (int fd){
108 0           int dow = bcd2dec(getRegister(fd, RTC_WDAY));
109 0           return dayOfWeek[dow - 1];
110             }
111              
112 0           void setDayOfWeek (int fd, int value){
113              
114 0 0         if (value > 7 || value < 1){
    0          
115 0           croak("Day of week (%d) out of bounds. Must be 1-7 (Mon-Sun)\n", value);
116             }
117              
118 0           setRegister(fd, RTC_WDAY, dec2bcd(value), "wday");
119 0           }
120              
121 0           int getDayOfMonth (int fd){
122 0           return(bcd2dec(getRegister(fd, RTC_MDAY)));
123             }
124              
125 0           void setDayOfMonth (int fd, int value){
126              
127 0 0         if (value < 1 || value > 31){
    0          
128 0           croak("Month day (%d) out of range. Must be between 1-31\n", value);
129             }
130              
131 0           setRegister(fd, RTC_MDAY, dec2bcd(value), "dayofmonth");
132 0           }
133              
134 0           int getMonth (int fd){
135              
136 0           int regVal = getRegister(fd, RTC_MONTH);
137 0           int century = regVal & 0b10000000;
138 0           return bcd2dec(regVal & 0b01111111);
139             }
140              
141 0           void setMonth (int fd, int value){
142              
143 0 0         if (value < 1 || value > 12){
    0          
144 0           croak("Month (%d) out of range. Must be between 1-12\n", value);
145             }
146              
147 0           setRegisterBits(fd, RTC_MONTH, 0, 7, value, "month");
148 0           }
149              
150 0           int getYear (int fd){
151 0           return bcd2dec(getRegister(fd, RTC_YEAR)) + 2000;
152             }
153              
154 0           void setYear (int fd, int value){
155              
156 0 0         if (value < 2000 || value > 2099){
    0          
157 0           croak("Year (%d) out of range. Must be between 2000-2099\n", value);
158             }
159              
160 0           int year = value - 2000;
161              
162 0           setRegister(fd, RTC_YEAR, dec2bcd(year), "year");
163 0           }
164              
165 0           float getTemp (int fd){
166              
167 0           int msb = getRegister(fd, RTC_TEMP_MSB);
168 0           int lsb = getRegister(fd, RTC_TEMP_LSB);
169              
170 0           float celcius = ((((short)msb << 8) | (short)lsb) >> 6) / 4.0;
171              
172 0           return celcius;
173             }
174              
175 0           int getMeridien (int fd){
176              
177 0 0         if ((getRegisterBit(fd, RTC_HOUR, RTC_12_24)) == 0){
178 0           croak(
179             "AM/PM functionality not available when in 24-hour clock mode\n"
180             );
181             }
182 0           return getRegisterBit(fd, RTC_HOUR, RTC_AM_PM);
183             }
184              
185 0           void setMeridien (int fd, int value){
186              
187 0 0         if ((getRegisterBit(fd, RTC_HOUR, RTC_12_24)) == 0){
188 0           croak(
189             "AM/PM can not be set when in 24-hour clock mode\n"
190             );
191             }
192              
193 0 0         if (value == 1){
194 0           enableRegisterBit(fd, RTC_HOUR, RTC_AM_PM);
195             }
196 0 0         else if (value == 0){
197 0           disableRegisterBit(fd, RTC_HOUR, RTC_AM_PM);
198             }
199             else {
200 0           croak(
201             "AM/PM value (%d) out of bounds. Send 1 for enable, 0 for disable",
202             value
203             );
204             }
205 0           }
206              
207 0           int getMilitary (int fd){
208 0           return getRegisterBit(fd, RTC_HOUR, RTC_12_24);
209             }
210              
211 0           void setMilitary (int fd, int value){
212              
213 0           int militaryTime = getMilitary(fd);
214 0           int hour = getHour(fd);
215              
216 0 0         if (militaryTime == value){
217             // nothing to do
218 0           return;
219             }
220              
221 0 0         if (value == 1){
222             // enable 12 hr clock
223 0 0         if (hour == 0){
224             // AM, at hour zero
225 0           setHour(fd, 12);
226 0           disableRegisterBit(fd, RTC_HOUR, RTC_AM_PM);
227             }
228 0 0         else if (getHour(fd) <= 12){
229             // AM
230 0           setHour(fd, hour);
231 0           disableRegisterBit(fd, RTC_HOUR, RTC_AM_PM);
232             }
233             else {
234             // PM
235 0           setHour(fd, hour - 12);
236 0           enableRegisterBit(fd, RTC_HOUR, RTC_AM_PM);
237             }
238              
239 0           enableRegisterBit(fd, RTC_HOUR, RTC_12_24);
240             }
241             else {
242             // enable 24 hr clock
243 0           int meridien = getMeridien(fd);
244 0           disableRegisterBit(fd, RTC_HOUR, RTC_12_24);
245              
246 0 0         if (meridien == 0){
247             // AM
248 0 0         if (hour == 12){
249 0           setHour(fd, 0);
250             }
251             else {
252 0           setHour(fd, hour);
253             }
254             }
255             else {
256             // PM
257 0 0         if (hour < 12){
258 0           setHour(fd, hour + 12);
259             }
260             else {
261 0           setHour(fd, hour);
262             }
263             }
264             }
265             }
266              
267 0           int getFh (int rtcAddr){
268              
269             int fd;
270              
271 0 0         if ((fd = open("/dev/i2c-1", O_RDWR)) < 0) {
272 0           close(fd);
273 0           croak("Couldn't open the device: %s\n", strerror(errno));
274             }
275              
276 0 0         if (ioctl(fd, I2C_SLAVE_FORCE, rtcAddr) < 0) {
277 0           close(fd);
278 0           croak(
279             "Couldn't find device at addr %d: %s\n",
280             rtcAddr,
281 0           strerror(errno)
282             );
283             }
284              
285 0           _establishI2C(fd);
286              
287 0           return fd;
288             }
289              
290 0           void disableRegisterBit (int fd, int reg, int bit){
291 0           int data = bitOff(getRegister(fd, reg), bit);
292 0           setRegister(fd, reg, data, "disabling bit");
293 0           }
294              
295 0           void enableRegisterBit (int fd, int reg, int bit){
296 0           int data = bitOn(getRegister(fd, reg), bit);
297 0           setRegister(fd, reg, data, "enabling bit");
298 0           }
299              
300 0           int getRegister (int fd, int reg){
301              
302             char buf[1];
303 0           buf[0] = reg;
304              
305 0 0         if ((write(fd, buf, 1)) != 1){
306 0           close(fd);
307 0           croak(
308             "Could not write register pointer %d: %s\n",
309             reg,
310 0           strerror(errno)
311             );
312             }
313              
314 0 0         if ((read(fd, buf, 1)) != 1){
315 0           close(fd);
316 0           croak("Could not read register %d: %s\n", reg, strerror(errno));
317             }
318              
319 0           return buf[0];
320             }
321              
322 0           int getRegisterBit (int fd, int reg, int bit){
323 0           int regData = getRegister(fd, reg);
324 0           return bitGet(regData, bit, bit);
325             }
326              
327 0           int getRegisterBits (int fd, int reg, int msb, int lsb){
328 0           return bitGet(getRegister(fd, reg), msb, lsb);
329             }
330              
331 0           int setRegister(int fd, int reg, int value, char* name){
332             /*
333             always call dec2bcd(value) before sending
334             in the value to this function
335             */
336              
337 0           char buf[2] = {reg, value};
338              
339 0 0         if ((write(fd, buf, sizeof(buf))) != 2){
340 0           close(fd);
341 0           croak(
342             "Could not write to the %s register: %s\n",
343             name,
344 0           strerror(errno)
345             );
346             }
347              
348 0           return 0;
349             }
350              
351 0           int setRegisterBits(int fd, int reg, int lsb, int nbits, int value, char* name){
352             /*
353             never call dec2bcd(value) before sending
354             in the value to this function
355             */
356              
357 0           int data = getRegister(fd, reg);
358              
359 0           data = bitSet(data, lsb, nbits, value);
360              
361 0           char buf[2] = {reg, data};
362              
363 0 0         if ((write(fd, buf, sizeof(buf))) != 2){
364 0           croak(
365             "Could not write to the %s register: %s\n",
366             name,
367 0           strerror(errno)
368             );
369             }
370              
371 0           return 0;
372             }
373              
374 0           int bcd2dec (int num){
375 0           return (((num & 0xF0) >> 4) * 10) + (num & 0x0F);
376             }
377              
378 0           int dec2bcd(int num){
379 0           return((num/10) * 16 + (num%10));
380             }
381              
382 0           void _establishI2C (int fd){
383              
384 0           int buf[1] = { 0x00 };
385              
386 0 0         if (write(fd, buf, 1) != 1){
387 0           close(fd);
388 0           croak("Error: Received no ACK bit, couldn't establish connection!");
389             }
390 0           }
391              
392 0           void _close (int fd){
393 0           close(fd);
394 0           }
395              
396             MODULE = RPi::RTC::DS3231 PACKAGE = RPi::RTC::DS3231
397              
398             PROTOTYPES: DISABLE
399              
400             void
401             setSeconds (fd, value)
402             int fd
403             int value
404              
405             void
406             setMinutes (fd, value)
407             int fd
408             int value
409              
410             void
411             setMilitary (fd, value)
412             int fd
413             int value
414              
415             int
416             getMilitary (fd)
417             int fd
418              
419             void
420             setMeridien (fd, value)
421             int fd
422             int value
423              
424             int
425             getMeridien (fd)
426             int fd
427              
428             int
429             getHour (fd)
430             int fd
431              
432             int
433             getSeconds (fd)
434             int fd
435              
436             int
437             getMinutes (fd)
438             int fd
439              
440             void
441             setHour (fd, value)
442             int fd
443             int value
444              
445             const char*
446             getDayOfWeek (fd)
447             int fd
448              
449             void
450             setDayOfWeek (fd, value)
451             int fd
452             int value
453              
454             int
455             getDayOfMonth (fd)
456             int fd
457              
458             void
459             setDayOfMonth (fd, value)
460             int fd
461             int value
462              
463             int getMonth (fd)
464             int fd
465              
466             void setMonth (fd, value)
467             int fd
468             int value
469              
470             int getYear (fd)
471             int fd
472              
473             void setYear (fd, value)
474             int fd
475             int value
476              
477             float getTemp (fd)
478             int fd
479              
480             int
481             getFh (rtcAddr)
482             int rtcAddr
483              
484             void
485             disableRegisterBit (fd, reg, bit)
486             int fd
487             int reg
488             int bit
489             PREINIT:
490             I32* temp;
491             PPCODE:
492 0           temp = PL_markstack_ptr++;
493 0           disableRegisterBit(fd, reg, bit);
494 0 0         if (PL_markstack_ptr != temp) {
495 0           PL_markstack_ptr = temp;
496 0           XSRETURN_EMPTY;
497             }
498 0           return;
499              
500             void
501             enableRegisterBit (fd, reg, bit)
502             int fd
503             int reg
504             int bit
505             PREINIT:
506             I32* temp;
507             PPCODE:
508 0           temp = PL_markstack_ptr++;
509 0           enableRegisterBit(fd, reg, bit);
510 0 0         if (PL_markstack_ptr != temp) {
511 0           PL_markstack_ptr = temp;
512 0           XSRETURN_EMPTY;
513             }
514 0           return;
515              
516             int
517             getRegister (fd, reg)
518             int fd
519             int reg
520              
521             int
522             getRegisterBit (fd, reg, bit)
523             int fd
524             int reg
525             int bit
526              
527             int
528             getRegisterBits (fd, reg, msb, lsb)
529             int fd
530             int reg
531             int msb
532             int lsb
533              
534             int
535             setRegister (fd, reg, value, name)
536             int fd
537             int reg
538             int value
539             char* name
540              
541             int
542             setRegisterBits(fd, reg, lsb, nbits, value, name)
543             int fd
544             int reg
545             int lsb
546             int nbits
547             int value
548             char* name
549              
550             int
551             bcd2dec (num)
552             int num
553              
554             int
555             dec2bcd (num)
556             int num
557              
558             void
559             _establishI2C (fd)
560             int fd
561              
562             void
563             _close (fd)
564             int fd