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/
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.
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.
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 ***********************************************************************
29 #include "wiringPiSPI.h"
30 #include "mcp23x0817.h"
34 #define MCP_SPEED 4000000
40 * Write a byte to a register on the MCP23s08 on the SPI bus.
41 *********************************************************************************
44 static void writeByte (uint8_t spiPort, uint8_t devId, uint8_t reg, uint8_t data)
48 spiData [0] = CMD_WRITE | ((devId & 7) << 1) ;
52 wiringPiSPIDataRW (spiPort, spiData, 3) ;
57 * Read a byte from a register on the MCP23s08 on the SPI bus.
58 *********************************************************************************
61 static uint8_t readByte (uint8_t spiPort, uint8_t devId, uint8_t reg)
65 spiData [0] = CMD_READ | ((devId & 7) << 1) ;
68 wiringPiSPIDataRW (spiPort, spiData, 3) ;
76 *********************************************************************************
79 static void myPinMode (struct wiringPiNodeStruct *node, int pin, int mode)
83 reg = MCP23x08_IODIR ;
84 mask = 1 << (pin - node->pinBase) ;
85 old = readByte (node->data0, node->data1, reg) ;
92 writeByte (node->data0, node->data1, reg, old) ;
98 *********************************************************************************
101 static void myPullUpDnControl (struct wiringPiNodeStruct *node, int pin, int mode)
105 reg = MCP23x08_GPPU ;
106 mask = 1 << (pin - node->pinBase) ;
108 old = readByte (node->data0, node->data1, reg) ;
115 writeByte (node->data0, node->data1, reg, old) ;
121 *********************************************************************************
124 static void myDigitalWrite (struct wiringPiNodeStruct *node, int pin, int value)
128 bit = 1 << ((pin - node->pinBase) & 7) ;
136 writeByte (node->data0, node->data1, MCP23x08_GPIO, old) ;
143 *********************************************************************************
146 static int myDigitalRead (struct wiringPiNodeStruct *node, int pin)
150 mask = 1 << ((pin - node->pinBase) & 7) ;
151 value = readByte (node->data0, node->data1, MCP23x08_GPIO) ;
153 if ((value & mask) == 0)
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 *********************************************************************************
168 int mcp23s08Setup (const int pinBase, const int spiPort, const int devId)
171 struct wiringPiNodeStruct *node ;
173 if ((x = wiringPiSPISetup (spiPort, MCP_SPEED)) < 0)
176 writeByte (spiPort, devId, MCP23x08_IOCON, IOCON_INIT) ;
178 node = wiringPiNewNode (pinBase, 8) ;
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) ;