n0mjs710 / MCP23S17

Arduino Driver for Microchip MCP23S17
7 stars 0 forks source link

Patch for arduino mega and attiny85 #2

Closed mfulz closed 7 years ago

mfulz commented 9 years ago

I've worked on implementing support for attiny85 and during that also implemented support for arduino mega. For the attiny85 I'm using this library https://github.com/JChristensen/tinySPI

Would be great if you could include this patch:

diff -ru MCP23S17/MCP23S17.cpp MCP23S17-patched/MCP23S17.cpp
--- MCP23S17/MCP23S17.cpp   2014-07-25 22:31:20.000000000 +0200
+++ MCP23S17-patched/MCP23S17.cpp   2015-03-02 21:31:18.746218164 +0100
@@ -32,7 +32,11 @@
          direct and more efficient control by writing a value to a specific register pair.
 */

+#if defined(__AVR_ATtiny85__)
+#include <tinySPI.h>
+#else
 #include <SPI.h>                 // Arduino IDE SPI library - uses AVR hardware SPI features
+#endif
 #include "MCP23S17.h"            // Header files for this class

 // Defines to keep logical information symbolic go here
@@ -47,7 +51,7 @@
 // Here we have things for the SPI bus configuration

 #define    CLOCK_DIVIDER (2)           // SPI bus speed to be 1/2 of the processor clock speed - 8MHz on most Arduinos
-#define    SS            (10)          // SPI bus slave select output to pin 10 - READ ARDUINO SPI DOCS BEFORE CHANGING!!!
+#define    SS            (SS_PIN)          // SPI bus slave select output to pin 10 - READ ARDUINO SPI DOCS BEFORE CHANGING!!!

 // Control byte and configuration register information - Control Byte: "0100 A2 A1 A0 R/W" -- W=0

@@ -64,8 +68,13 @@
   _pullupCache = 0x0000;                // Default pull-up state is all off, 0x0000
   _invertCache = 0x0000;                // Default input inversion state is not inverted, 0x0000
   SPI.begin();                          // Start up the SPI busÉ crank'er up Charlie!
+#ifndef TINY_SPI
   SPI.setClockDivider(CLOCK_DIVIDER);   // Sets the SPI bus speed
   SPI.setBitOrder(MSBFIRST);            // Sets SPI bus bit order (this is the default, setting it for good form!)
+#endif
+#ifdef TINY_SPI
+  SPI_DDR_PORT |= _BV(SS_PIN);
+#endif
   SPI.setDataMode(SPI_MODE0);           // Sets the SPI bus timing mode (this is the default, setting it for good form!)
   byteWrite(IOCON, ADDR_ENABLE);
 };
@@ -73,22 +82,22 @@
 // GENERIC BYTE WRITE - will write a byte to a register, arguments are register address and the value to write

 void MCP::byteWrite(uint8_t reg, uint8_t value) {      // Accept the register and byte
-  PORTB &= 0b11111011;                                 // Direct port manipulation speeds taking Slave Select LOW before SPI action
+  PORTB &= PORTB_AND_MASK;                                 // Direct port manipulation speeds taking Slave Select LOW before SPI action
   SPI.transfer(OPCODEW | (_address << 1));             // Send the MCP23S17 opcode, chip address, and write bit
   SPI.transfer(reg);                                   // Send the register we want to write
   SPI.transfer(value);                                 // Send the byte
-  PORTB |= 0b00000100;                                 // Direct port manipulation speeds taking Slave Select HIGH after SPI action
+  PORTB |= PORTB_OR_MASK;                                 // Direct port manipulation speeds taking Slave Select HIGH after SPI action
 }

 // GENERIC WORD WRITE - will write a word to a register pair, LSB to first register, MSB to next higher value register 

 void MCP::wordWrite(uint8_t reg, unsigned int word) {  // Accept the start register and word 
-  PORTB &= 0b11111011;                                 // Direct port manipulation speeds taking Slave Select LOW before SPI action 
+  PORTB &= PORTB_AND_MASK;                                 // Direct port manipulation speeds taking Slave Select LOW before SPI action 
   SPI.transfer(OPCODEW | (_address << 1));             // Send the MCP23S17 opcode, chip address, and write bit
   SPI.transfer(reg);                                   // Send the register we want to write 
   SPI.transfer((uint8_t) (word));                      // Send the low byte (register address pointer will auto-increment after write)
   SPI.transfer((uint8_t) (word >> 8));                 // Shift the high byte down to the low byte location and send
-  PORTB |= 0b00000100;                                 // Direct port manipulation speeds taking Slave Select HIGH after SPI action
+  PORTB |= PORTB_OR_MASK;                                 // Direct port manipulation speeds taking Slave Select HIGH after SPI action
 }

 // MODE SETTING FUNCTIONS - BY PIN AND BY WORD
@@ -170,26 +179,26 @@

 unsigned int MCP::digitalRead(void) {       // This function will read all 16 bits of I/O, and return them as a word in the format 0x(portB)(portA)
   unsigned int value = 0;                   // Initialize a variable to hold the read values to be returned
-  PORTB &= 0b11111011;                      // Direct port manipulation speeds taking Slave Select LOW before SPI action
+  PORTB &= PORTB_AND_MASK;                      // Direct port manipulation speeds taking Slave Select LOW before SPI action
   SPI.transfer(OPCODER | (_address << 1));  // Send the MCP23S17 opcode, chip address, and read bit
   SPI.transfer(GPIOA);                      // Send the register we want to read
   value = SPI.transfer(0x00);               // Send any byte, the function will return the read value (register address pointer will auto-increment after write)
   value |= (SPI.transfer(0x00) << 8);       // Read in the "high byte" (portB) and shift it up to the high location and merge with the "low byte"
-  PORTB |= 0b00000100;                      // Direct port manipulation speeds taking Slave Select HIGH after SPI action
+  PORTB |= PORTB_OR_MASK;                      // Direct port manipulation speeds taking Slave Select HIGH after SPI action
   return value;                             // Return the constructed word, the format is 0x(portB)(portA)
 }

 uint8_t MCP::byteRead(uint8_t reg) {        // This function will read a single register, and return it
   uint8_t value = 0;                        // Initialize a variable to hold the read values to be returned
-  PORTB &= 0b11111011;                      // Direct port manipulation speeds taking Slave Select LOW before SPI action
+  PORTB &= PORTB_AND_MASK;                      // Direct port manipulation speeds taking Slave Select LOW before SPI action
   SPI.transfer(OPCODER | (_address << 1));  // Send the MCP23S17 opcode, chip address, and read bit
   SPI.transfer(reg);                        // Send the register we want to read
   value = SPI.transfer(0x00);               // Send any byte, the function will return the read value
-  PORTB |= 0b00000100;                      // Direct port manipulation speeds taking Slave Select HIGH after SPI action
+  PORTB |= PORTB_OR_MASK;                      // Direct port manipulation speeds taking Slave Select HIGH after SPI action
   return value;                             // Return the constructed word, the format is 0x(register value)
 }

 uint8_t MCP::digitalRead(uint8_t pin) {              // Return a single bit value, supply the necessary bit (1-16)
     if (pin < 1 | pin > 16) return 0x0;                  // If the pin value is not valid (1-16) return, do nothing and return
     return digitalRead() & (1 << (pin - 1)) ? HIGH : LOW;  // Call the word reading function, extract HIGH/LOW information from the requested pin
-}
\ No newline at end of file
+}
diff -ru MCP23S17/MCP23S17.h MCP23S17-patched/MCP23S17.h
--- MCP23S17/MCP23S17.h 2014-07-25 22:31:20.000000000 +0200
+++ MCP23S17-patched/MCP23S17.h 2015-03-02 21:31:18.746218164 +0100
@@ -76,6 +76,21 @@
 #include "WProgram.h"
 #endif

+#if defined(__AVR_ATmega2560__)
+#define SS_PIN 53
+#define PORTB_AND_MASK 0b11111110
+#define PORTB_OR_MASK 0b00000001
+#elif defined(__AVR_ATtiny85__)
+#define SS_PIN 4
+#define PORTB_AND_MASK 0b11101111
+#define PORTB_OR_MASK 0b00010000
+#define TINY_SPI
+#else
+#define SS_PIN 10
+#define PORTB_AND_MASK 0b11111011
+#define PORTB_OR_MASK 0b00000100
+#endif
+
 class MCP {
   public:
     MCP(uint8_t);                            // Constructor to instantiate a discrete IC as an object, argument is the address (0-7) of the MCP23S17
n0mjs710 commented 7 years ago

Please fork this repo with your additions if you'd like to make them, I have no interest in supporting the ATtiny85 at this time.