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
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: