mcp23016.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  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. #include <stdio.h>
  25. #include <pthread.h>
  26. #include "wiringPi.h"
  27. #include "wiringPiI2C.h"
  28. #include "mcp23016.h"
  29. #include "mcp23016reg.h"
  30. /*
  31. * myPinMode:
  32. *********************************************************************************
  33. */
  34. static void myPinMode (struct wiringPiNodeStruct *node, int pin, int mode)
  35. {
  36. int mask, old, reg ;
  37. pin -= node->pinBase ;
  38. if (pin < 8) // Bank A
  39. reg = MCP23016_IODIR0 ;
  40. else
  41. {
  42. reg = MCP23016_IODIR1 ;
  43. pin &= 0x07 ;
  44. }
  45. mask = 1 << pin ;
  46. old = wiringPiI2CReadReg8 (node->fd, reg) ;
  47. if (mode == OUTPUT)
  48. old &= (~mask) ;
  49. else
  50. old |= mask ;
  51. wiringPiI2CWriteReg8 (node->fd, reg, old) ;
  52. }
  53. /*
  54. * myDigitalWrite:
  55. *********************************************************************************
  56. */
  57. static void myDigitalWrite (struct wiringPiNodeStruct *node, int pin, int value)
  58. {
  59. int bit, old ;
  60. pin -= node->pinBase ; // Pin now 0-15
  61. bit = 1 << (pin & 7) ;
  62. if (pin < 8) // Bank A
  63. {
  64. old = node->data2 ;
  65. if (value == LOW)
  66. old &= (~bit) ;
  67. else
  68. old |= bit ;
  69. wiringPiI2CWriteReg8 (node->fd, MCP23016_GP0, old) ;
  70. node->data2 = old ;
  71. }
  72. else // Bank B
  73. {
  74. old = node->data3 ;
  75. if (value == LOW)
  76. old &= (~bit) ;
  77. else
  78. old |= bit ;
  79. wiringPiI2CWriteReg8 (node->fd, MCP23016_GP1, old) ;
  80. node->data3 = old ;
  81. }
  82. }
  83. /*
  84. * myDigitalRead:
  85. *********************************************************************************
  86. */
  87. static int myDigitalRead (struct wiringPiNodeStruct *node, int pin)
  88. {
  89. int mask, value, gpio ;
  90. pin -= node->pinBase ;
  91. if (pin < 8) // Bank A
  92. gpio = MCP23016_GP0 ;
  93. else
  94. {
  95. gpio = MCP23016_GP1 ;
  96. pin &= 0x07 ;
  97. }
  98. mask = 1 << pin ;
  99. value = wiringPiI2CReadReg8 (node->fd, gpio) ;
  100. if ((value & mask) == 0)
  101. return LOW ;
  102. else
  103. return HIGH ;
  104. }
  105. /*
  106. * mcp23016Setup:
  107. * Create a new instance of an MCP23016 I2C GPIO interface. We know it
  108. * has 16 pins, so all we need to know here is the I2C address and the
  109. * user-defined pin base.
  110. *********************************************************************************
  111. */
  112. int mcp23016Setup (const int pinBase, const int i2cAddress)
  113. {
  114. int fd ;
  115. struct wiringPiNodeStruct *node ;
  116. if ((fd = wiringPiI2CSetup (i2cAddress)) < 0)
  117. return FALSE ;
  118. wiringPiI2CWriteReg8 (fd, MCP23016_IOCON0, IOCON_INIT) ;
  119. wiringPiI2CWriteReg8 (fd, MCP23016_IOCON1, IOCON_INIT) ;
  120. node = wiringPiNewNode (pinBase, 16) ;
  121. node->fd = fd ;
  122. node->pinMode = myPinMode ;
  123. node->digitalRead = myDigitalRead ;
  124. node->digitalWrite = myDigitalWrite ;
  125. node->data2 = wiringPiI2CReadReg8 (fd, MCP23016_OLAT0) ;
  126. node->data3 = wiringPiI2CReadReg8 (fd, MCP23016_OLAT1) ;
  127. return TRUE ;
  128. }