Gordons Projects

--> Projects Top-Level GIT

e5cc6328ebdcd8bc9d4b4c1e2b6bf452f177487d
[wiringPi] / wiringPi / mcp23016.c
1 /*
2  * mcp23016.c:
3  *      Extend wiringPi with the MCP 23016 I2C GPIO expander chip
4  *      Copyright (c) 2013 Gordon Henderson
5  ***********************************************************************
6  * This file is part of wiringPi:
7  *      https://projects.drogon.net/raspberry-pi/wiringpi/
8  *
9  *    wiringPi is free software: you can redistribute it and/or modify
10  *    it under the terms of the GNU Lesser General Public License as
11  *    published by the Free Software Foundation, either version 3 of the
12  *    License, or (at your option) any later version.
13  *
14  *    wiringPi is distributed in the hope that it will be useful,
15  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *    GNU Lesser General Public License for more details.
18  *
19  *    You should have received a copy of the GNU Lesser General Public
20  *    License along with wiringPi.
21  *    If not, see <http://www.gnu.org/licenses/>.
22  ***********************************************************************
23  */
24
25 #include <stdio.h>
26 #include <pthread.h>
27
28 #include "wiringPi.h"
29 #include "wiringPiI2C.h"
30 #include "mcp23016.h"
31
32 #include "mcp23016reg.h"
33
34
35 /*
36  * myPinMode:
37  *********************************************************************************
38  */
39
40 static void myPinMode (struct wiringPiNodeStruct *node, int pin, int mode)
41 {
42   int mask, old, reg ;
43
44   pin -= node->pinBase ;
45
46   if (pin < 8)          // Bank A
47     reg  = MCP23016_IODIR0 ;
48   else
49   {
50     reg  = MCP23016_IODIR1 ;
51     pin &= 0x07 ;
52   }
53
54   mask = 1 << pin ;
55   old  = wiringPiI2CReadReg8 (node->fd, reg) ;
56
57   if (mode == OUTPUT)
58     old &= (~mask) ;
59   else
60     old |=   mask ;
61
62   wiringPiI2CWriteReg8 (node->fd, reg, old) ;
63 }
64
65
66 /*
67  * myDigitalWrite:
68  *********************************************************************************
69  */
70
71 static void myDigitalWrite (struct wiringPiNodeStruct *node, int pin, int value)
72 {
73   int bit, old ;
74
75   pin -= node->pinBase ;        // Pin now 0-15
76
77   bit = 1 << (pin & 7) ;
78
79   if (pin < 8)                  // Bank A
80   {
81     old = node->data2 ;
82
83     if (value == LOW)
84       old &= (~bit) ;
85     else
86       old |=   bit ;
87
88     wiringPiI2CWriteReg8 (node->fd, MCP23016_GP0, old) ;
89     node->data2 = old ;
90   }
91   else                          // Bank B
92   {
93     old = node->data3 ;
94
95     if (value == LOW)
96       old &= (~bit) ;
97     else
98       old |=   bit ;
99
100     wiringPiI2CWriteReg8 (node->fd, MCP23016_GP1, old) ;
101     node->data3 = old ;
102   }
103 }
104
105
106 /*
107  * myDigitalRead:
108  *********************************************************************************
109  */
110
111 static int myDigitalRead (struct wiringPiNodeStruct *node, int pin)
112 {
113   int mask, value, gpio ;
114
115   pin -= node->pinBase ;
116
117   if (pin < 8)          // Bank A
118     gpio  = MCP23016_GP0 ;
119   else
120   {
121     gpio  = MCP23016_GP1 ;
122     pin  &= 0x07 ;
123   }
124
125   mask  = 1 << pin ;
126   value = wiringPiI2CReadReg8 (node->fd, gpio) ;
127
128   if ((value & mask) == 0)
129     return LOW ;
130   else 
131     return HIGH ;
132 }
133
134
135 /*
136  * mcp23016Setup:
137  *      Create a new instance of an MCP23016 I2C GPIO interface. We know it
138  *      has 16 pins, so all we need to know here is the I2C address and the
139  *      user-defined pin base.
140  *********************************************************************************
141  */
142
143 int mcp23016Setup (const int pinBase, const int i2cAddress)
144 {
145   int fd ;
146   struct wiringPiNodeStruct *node ;
147
148   if ((fd = wiringPiI2CSetup (i2cAddress)) < 0)
149     return fd ;
150
151   wiringPiI2CWriteReg8 (fd, MCP23016_IOCON0, IOCON_INIT) ;
152   wiringPiI2CWriteReg8 (fd, MCP23016_IOCON1, IOCON_INIT) ;
153
154   node = wiringPiNewNode (pinBase, 16) ;
155
156   node->fd              = fd ;
157   node->pinMode         = myPinMode ;
158   node->digitalRead     = myDigitalRead ;
159   node->digitalWrite    = myDigitalWrite ;
160   node->data2           = wiringPiI2CReadReg8 (fd, MCP23016_OLAT0) ;
161   node->data3           = wiringPiI2CReadReg8 (fd, MCP23016_OLAT1) ;
162
163   return 0 ;
164 }