File Coverage

MCP23017.xs
Criterion Covered Total %
statement 0 104 0.0
branch 0 48 0.0
condition n/a
subroutine n/a
pod n/a
total 0 152 0.0


line stmt bran cond sub pod time code
1             #include "EXTERN.h"
2             #include "perl.h"
3             #include "XSUB.h"
4              
5             #include
6             #include
7             #include
8             #include
9             #include
10             #include
11             #include
12             #include
13             #include
14             #include
15             #include "mcp23017.h"
16             #include "bit.h"
17              
18             /* setup functions */
19              
20 0           int GPIO_getFd (int expanderAddr){
21              
22             int fd;
23              
24 0 0         if ((fd = open("/dev/i2c-1", O_RDWR)) < 0) {
25 0           close(fd);
26 0           printf("Couldn't open the device: %s\n", strerror(errno));
27 0           croak("...this is a fatal error\n");
28             }
29              
30 0 0         if (ioctl(fd, I2C_SLAVE_FORCE, expanderAddr) < 0) {
31 0           close(fd);
32 0           printf(
33             "Couldn't find device at addr %d: %s\n",
34             expanderAddr,
35 0           strerror(errno)
36             );
37 0           exit(-1);
38             }
39              
40 0           _establishI2C(fd);
41              
42 0           return fd;
43             }
44              
45 0           void _establishI2C (int fd){
46              
47 0           int buf[1] = { 0x00 };
48              
49 0 0         if (write(fd, buf, 1) != 1){
50 0           close(fd);
51 0           printf("Error: Received no ACK bit, couldn't establish connection!");
52 0           exit(-1);
53             }
54 0           }
55              
56             /* register operations */
57              
58 0           void _checkRegisterReadOnly (uint8_t reg){
59 0           uint8_t readOnlyRegisters[6] = {0x0A, 0X0B, 0x0E, 0x0F, 0x10, 0x11};
60              
61 0 0         for (int i=0; i < sizeof(readOnlyRegisters); i++){
62 0 0         if (reg == readOnlyRegisters[i]){
63 0           warn("error: register 0x%x is read-only...\n", reg);
64 0           croak("Attempt to write to read-only register failed\n");
65             }
66             }
67 0           }
68              
69 0           int _skipRegisterReadOnly (uint8_t reg){
70 0           uint8_t readOnlyRegisters[6] = {0x0A, 0X0B, 0x0E, 0x0F, 0x10, 0x11};
71              
72 0 0         for (int i=0; i < sizeof(readOnlyRegisters); i++){
73 0 0         if (reg == readOnlyRegisters[i]){
74 0           return 1;
75             }
76             }
77 0           return 0;
78             }
79              
80 0           int GPIO_getRegister (int fd, int reg){
81              
82             uint8_t buf[1];
83 0           buf[0] = reg;
84              
85 0 0         if ((write(fd, buf, 1)) != 1){
86 0           close(fd);
87 0           croak(
88             "Could not write register pointer %d: %s\n",
89             reg,
90 0           strerror(errno)
91             );
92             }
93              
94 0 0         if ((read(fd, buf, 1)) != 1){
95 0           close(fd);
96 0           croak("Could not read register %d: %s\n", reg, strerror(errno));
97             }
98              
99 0           return buf[0];
100             }
101              
102 0           int GPIO_getRegisterBit (int fd, int reg, int bit){
103 0           bit = GPIO__pinBit(bit);
104 0           int regData = GPIO_getRegister(fd, (int) reg);
105 0           return bitGet(regData, bit, bit);
106             }
107              
108 0           int GPIO_getRegisterBits (int fd, int reg, int msb, int lsb){
109 0           return bitGet(GPIO_getRegister(fd, reg), msb, lsb);
110             }
111              
112 0           int GPIO_setRegister(int fd, int reg, int value, char* name){
113 0           _checkRegisterReadOnly(reg);
114              
115 0           uint8_t buf[2] = {reg, value};
116              
117 0 0         if ((write(fd, buf, sizeof(buf))) != 2){
118 0           close(fd);
119 0           printf(
120             "Could not write to the %s register: %s\n",
121             name,
122 0           strerror(errno)
123             );
124 0           exit(-1);
125             }
126              
127 0           return 0;
128             }
129              
130             /* pin functions */
131              
132 0           int GPIO__pinBit (int pin){
133 0 0         if (pin < 0 || pin > 15){
    0          
134 0           croak("pin '%d' is out of bounds. Pins 0-15 are available\n");
135             }
136              
137             // since we're dealing with a register per bank,
138             // We need to know where in the double register to
139             // look
140              
141 0 0         return pin < 8 ? pin : pin - 8;
142             }
143              
144 0           bool GPIO_readPin (int fd, int pin){
145 0 0         int reg = pin < 8 ? reg = MCP23017_GPIOA : MCP23017_GPIOB;
146 0           int bit = GPIO__pinBit(pin);
147              
148 0           return (bool) GPIO_getRegisterBit(fd, reg, bit);
149             }
150              
151 0           void GPIO_writePin (int fd, int pin, bool state){
152 0 0         int reg = pin < 8 ? reg = MCP23017_GPIOA : MCP23017_GPIOB;
153 0           int bit = GPIO__pinBit(pin);
154             int value;
155              
156 0 0         if (state == HIGH){
157 0           value = bitOn(GPIO_getRegister(fd, reg), bit);
158             }
159             else {
160 0           value = bitOff(GPIO_getRegister(fd, reg), bit);
161             }
162              
163 0           GPIO_setRegister(fd, reg, value, "writePin()");
164 0           }
165              
166 0           void GPIO_pinMode (int fd, int pin, int mode){
167 0           int reg = pin < 8 ? (int) MCP23017_IODIRA : (int) MCP23017_IODIRB;
168 0           int bit = GPIO__pinBit(pin);
169             int value;
170              
171 0 0         if (mode == INPUT){
172 0           value = bitOn(GPIO_getRegister(fd, reg), bit);
173              
174             }
175             else {
176 0           value = bitOff(GPIO_getRegister(fd, reg), bit);
177             }
178              
179 0           GPIO_setRegister(fd, reg, value, "pinMode()");
180 0           }
181              
182 0           void GPIO_pullUp (int fd, int pin, int state){
183 0 0         int reg = pin < 8 ? MCP23017_GPPUA : MCP23017_GPPUB;
184 0           int bit = GPIO__pinBit(pin);
185             int value;
186              
187 0 0         if (state == HIGH){
188 0           value = bitOn(GPIO_getRegister(fd, reg), bit);
189             }
190             else {
191 0           value = bitOff(GPIO_getRegister(fd, reg), bit);
192             }
193              
194 0           GPIO_setRegister(fd, reg, value, "pullUp()");
195 0           }
196              
197             /* operational functions */
198              
199 0           void GPIO_clean (int fd){
200              
201 0 0         for (int i = 0; i < 0x16; i++){
202 0 0         if (_skipRegisterReadOnly(i)){
203 0           continue;
204             }
205              
206 0 0         if (i == MCP23017_IODIRA || i == MCP23017_IODIRB){
    0          
207             // direction registers get set back to INPUT
208 0           GPIO_setRegister(fd, (int) i, (int) 0xFF, "IODIR");
209 0           continue;
210             }
211 0           GPIO_setRegister(fd, i, 0x00, "rest");
212             }
213 0           }
214              
215             MODULE = RPi::GPIOExpander::MCP23017 PACKAGE = RPi::GPIOExpander::MCP23017 PREFIX = GPIO_
216              
217             PROTOTYPES: DISABLE
218              
219             # setup functions
220              
221             int
222             GPIO_getFd (expanderAddr)
223             int expanderAddr
224              
225             # register functions
226              
227             int
228             GPIO_getRegister (fd, reg)
229             int fd
230             int reg
231              
232             int
233             GPIO_getRegisterBit (fd, reg, bit)
234             int fd
235             int reg
236             int bit
237              
238             int
239             GPIO_getRegisterBits (fd, reg, msb, lsb)
240             int fd
241             int reg
242             int msb
243             int lsb
244              
245             int
246             GPIO_setRegister (fd, reg, value, name)
247             int fd
248             int reg
249             int value
250             char* name
251              
252             # pin functions
253              
254             int
255             GPIO__pinBit (pin)
256             int pin
257              
258             int
259             GPIO_readPin (fd, pin)
260             int fd
261             int pin
262              
263             void
264             GPIO_writePin (fd, pin, state)
265             int fd
266             int pin
267             int state
268              
269             void
270             GPIO_pinMode (fd, pin, mode)
271             int fd
272             int pin
273             int mode
274              
275             void
276             GPIO_pullUp (fd, pin, state)
277             int fd
278             int pin
279             int state
280              
281             # operational functions
282              
283             void
284             GPIO_clean (fd)
285             int fd
286             PREINIT:
287             I32* temp;
288             PPCODE:
289 0           temp = PL_markstack_ptr++;
290 0           GPIO_clean(fd);
291 0 0         if (PL_markstack_ptr != temp) {
292 0           PL_markstack_ptr = temp;
293 0           XSRETURN_EMPTY;
294             }
295 0           return;