Gordons Projects

--> Projects Top-Level GIT

wiringPi Version 2 - First commit (of v2)
[wiringPi] / wiringPi / mcp23s08.c
1 /*
2  * mcp23s08.c:
3  *      Extend wiringPi with the MCP 23s08 SPI 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 <stdint.h>
27
28 #include "wiringPi.h"
29 #include "wiringPiSPI.h"
30 #include "mcp23x0817.h"
31
32 #include "mcp23s08.h"
33
34 #define MCP_SPEED       4000000
35
36
37
38 /*
39  * writeByte:
40  *      Write a byte to a register on the MCP23s08 on the SPI bus.
41  *********************************************************************************
42  */
43
44 static void writeByte (uint8_t spiPort, uint8_t devId, uint8_t reg, uint8_t data)
45 {
46   uint8_t spiData [4] ;
47
48   spiData [0] = CMD_WRITE | ((devId & 7) << 1) ;
49   spiData [1] = reg ;
50   spiData [2] = data ;
51
52   wiringPiSPIDataRW (spiPort, spiData, 3) ;
53 }
54
55 /*
56  * readByte:
57  *      Read a byte from a register on the MCP23s08 on the SPI bus.
58  *********************************************************************************
59  */
60
61 static uint8_t readByte (uint8_t spiPort, uint8_t devId, uint8_t reg)
62 {
63   uint8_t spiData [4] ;
64
65   spiData [0] = CMD_READ | ((devId & 7) << 1) ;
66   spiData [1] = reg ;
67
68   wiringPiSPIDataRW (spiPort, spiData, 3) ;
69
70   return spiData [2] ;
71 }
72
73
74 /*
75  * myPinMode:
76  *********************************************************************************
77  */
78
79 static void myPinMode (struct wiringPiNodeStruct *node, int pin, int mode)
80 {
81   int mask, old, reg ;
82
83   reg  = MCP23x08_IODIR ;
84   mask = 1 << (pin - node->pinBase) ;
85   old  = readByte (node->data0, node->data1, reg) ;
86
87   if (mode == OUTPUT)
88     old &= (~mask) ;
89   else
90     old |=   mask ;
91
92   writeByte (node->data0, node->data1, reg, old) ;
93 }
94
95
96 /*
97  * myPullUpDnControl:
98  *********************************************************************************
99  */
100
101 static void myPullUpDnControl (struct wiringPiNodeStruct *node, int pin, int mode)
102 {
103   int mask, old, reg ;
104
105   reg  = MCP23x08_GPPU ;
106   mask = 1 << (pin - node->pinBase) ;
107
108   old  = readByte (node->data0, node->data1, reg) ;
109
110   if (mode == PUD_UP)
111     old |=   mask ;
112   else
113     old &= (~mask) ;
114
115   writeByte (node->data0, node->data1, reg, old) ;
116 }
117
118
119 /*
120  * myDigitalWrite:
121  *********************************************************************************
122  */
123
124 static void myDigitalWrite (struct wiringPiNodeStruct *node, int pin, int value)
125 {
126   int bit, old ;
127
128   bit  = 1 << ((pin - node->pinBase) & 7) ;
129
130   old = node->data2 ;
131   if (value == LOW)
132     old &= (~bit) ;
133   else
134     old |=   bit ;
135
136   writeByte (node->data0, node->data1, MCP23x08_GPIO, old) ;
137   node->data2 = old ;
138 }
139
140
141 /*
142  * myDigitalRead:
143  *********************************************************************************
144  */
145
146 static int myDigitalRead (struct wiringPiNodeStruct *node, int pin)
147 {
148   int mask, value ;
149
150   mask  = 1 << ((pin - node->pinBase) & 7) ;
151   value = readByte (node->data0, node->data1, MCP23x08_GPIO) ;
152
153   if ((value & mask) == 0)
154     return LOW ;
155   else 
156     return HIGH ;
157 }
158
159
160 /*
161  * mcp23s08Setup:
162  *      Create a new instance of an MCP23s08 SPI GPIO interface. We know it
163  *      has 8 pins, so all we need to know here is the SPI address and the
164  *      user-defined pin base.
165  *********************************************************************************
166  */
167
168 int mcp23s08Setup (const int pinBase, const int spiPort, const int devId)
169 {
170   int    x ;
171   struct wiringPiNodeStruct *node ;
172
173   if ((x = wiringPiSPISetup (spiPort, MCP_SPEED)) < 0)
174     return x ;
175
176   writeByte (spiPort, devId, MCP23x08_IOCON, IOCON_INIT) ;
177
178   node = wiringPiNewNode (pinBase, 8) ;
179
180   node->data0           = spiPort ;
181   node->data1           = devId ;
182   node->pinMode         = myPinMode ;
183   node->pullUpDnControl = myPullUpDnControl ;
184   node->digitalRead     = myDigitalRead ;
185   node->digitalWrite    = myDigitalWrite ;
186   node->data2           = readByte (spiPort, devId, MCP23x08_OLAT) ;
187
188   return 0 ;
189 }