diff --git a/Centipede.cpp b/Centipede.cpp index b1862de..eb506de 100644 --- a/Centipede.cpp +++ b/Centipede.cpp @@ -10,6 +10,9 @@ #include uint8_t CSDataArray[2] = {0}; +#ifdef CS_CACHE +uint8_t CSDataCacheArray[16] = {0}; +#endif #define CSAddress 0b0100000 @@ -41,6 +44,13 @@ void Centipede::initialize() } +#ifdef CS_CACHE +void Centipede::StoreCache(int port) { + CSDataCacheArray[port] = CSDataArray[0]; + CSDataCacheArray[port+1] = CSDataArray[1]; +} +#endif + void Centipede::WriteRegisters(int port, int startregister, int quantity) { Wire.beginTransmission(CSAddress + port); @@ -131,14 +141,24 @@ void Centipede::digitalWrite(int pin, int level) { } -int Centipede::digitalRead(int pin) { +// While the cache parameter is always taken in input, it will be effective only once CS_CACHE is defined in Centipede.h file +int Centipede::digitalRead(int pin, int cache) { int port = pin >> 4; int subregister = (pin & 8) >> 3; +#ifdef CS_CACHE + if ( !cache ) { + ReadRegisters(port, 0x12 + subregister, 1); + StoreCache(port); + } + + int returnval = (CSDataCacheArray[port] >> (pin - ((port << 1) + subregister)*8)) & 1; +#else ReadRegisters(port, 0x12 + subregister, 1); int returnval = (CSDataArray[0] >> (pin - ((port << 1) + subregister)*8)) & 1; +#endif return returnval; @@ -217,6 +237,10 @@ int Centipede::portRead(int port) { ReadRegisters(port, 0x12, 2); +#ifdef CS_CACHE + StoreCache(port); +#endif + int receivedval = CSDataArray[0]; receivedval |= CSDataArray[1] << 8; diff --git a/Centipede.h b/Centipede.h index f44da08..f8307ac 100644 --- a/Centipede.h +++ b/Centipede.h @@ -4,6 +4,8 @@ #ifndef Centipede_h #define Centipede_h +#define CS_CACHE + #if defined(ARDUINO) && ARDUINO >= 100 #include "Arduino.h" #else @@ -11,6 +13,9 @@ #endif extern uint8_t CSDataArray[2]; +#ifdef CS_CACHE +extern uint8_t CSDataCacheArray[16]; +#endif class Centipede { @@ -19,7 +24,7 @@ class Centipede void pinMode(int pin, int mode); void pinPullup(int pin, int mode); void digitalWrite(int pin, int level); - int digitalRead(int pin); + int digitalRead(int pin, int cache = false); void portMode(int port, int value); void portPullup(int port, int value); void portWrite(int port, int value); @@ -33,6 +38,9 @@ class Centipede void WriteRegisters(int port, int startregister, int quantity); void ReadRegisters(int port, int startregister, int quantity); void WriteRegisterPin(int port, int regpin, int subregister, int level); +#ifdef CS_CACHE + void StoreCache(int port); +#endif }; #endif diff --git a/README.md b/README.md index 60d707c..cb78305 100644 --- a/README.md +++ b/README.md @@ -1 +1,28 @@ # Centipede Shield Library + +## Reference + +The main documentation is reported in [macetech wiki](https://docs.macetech.com/doku.php/centipede_shield) + +Nevertheless this could be outdated (eg .getIntF is missing in the wiki currently). + +## Methods + +* .digitalWrite([0...127], [LOW...HIGH]) - Acts like normal digitalWrite +* .digitalRead([0...127]) - Acts like normal digitalRead +* .pinMode([0...127], [INPUT...OUTPUT]) - Acts like normal pinMode +* .pinPullup([0...127], [LOW...HIGH]) - Activates internal 100K pullups on inputs when HIGH. +* .portWrite([0...7], [0...65535]) - Writes 16-bit value to one port (chip). Useful for writing 16 outputs at the same time. +* .portRead([0...7]) - Reads 16-bit value from one port (chip) +* .portMode([0...7], [0...65535]) - Write I/O mask to one port (chip). In binary, a 0 means output and a 1 means input. Easier to use than a long list of pinMode() commands. +* .portPullup([0...7], [0...65535]) - Sets pullups on one port (chip). In binary, a 0 means no pullup and a 1 means pullup is active. +* .portInterrupts([0...7],[0...65535],[0...65535],[0...65535]) - Configure interrupts +* [device number],[use interrupt on pin],[default value],[interrupt when != default] +* .portCaptureRead(0...7) - Reads 16-bit value registers as they were when interrupt occurred +* .getIntF(0..7) - These return an interrupt flag state that allows you to determine which port (device) produced an interrupt (and it could be more than one device). +* .init() - Sets all registers to initial values + +## Compile Options + +if `CS_CACHE` is defined, the library will use sightly more memory, but will allow `.digitalRead([0-127, [TRUE|FALSE])` where the latter parametet will define if to return the value cached or if has to be taken fresh from the port. +If you read all the 127 input from i2c, this should br faster, at the price of 512 byte of memory. diff --git a/examples/sample.ino b/examples/sample.ino new file mode 100644 index 0000000..c758f86 --- /dev/null +++ b/examples/sample.ino @@ -0,0 +1,63 @@ +// Example code for Centipede Library +// Works with Centipede Shield or MCP23017 on Arduino I2C port + +#include +#include + + +/* Available commands + .digitalWrite([0...127], [LOW...HIGH]) - Acts like normal digitalWrite + .digitalRead([0...127]) - Acts like normal digitalRead + .pinMode([0...127], [INPUT...OUTPUT]) - Acts like normal pinMode + .portWrite([0...7], [0...65535]) - Writes 16-bit value to one port (chip) + .portRead([0...7]) - Reads 16-bit value from one port (chip) + .portMode([0...7], [0...65535]) - Write I/O mask to one port (chip) + .pinPullup([0...127], [LOW...HIGH]) - Sets pullup on input pin + .portPullup([0...7], [0...65535]) - Sets pullups on one port (chip) + .portInterrupts([0...7],[0...65535],[0...65535],[0...65535]) - Configure interrupts + [device number],[use interrupt on pin],[default value],[interrupt when != default] + .portCaptureRead(0...7) - Reads 16-bit value registers as they were when interrupt occurred + .init() - Sets all registers to initial values + + Examples + CS.init(); + CS.pinMode(0,OUTPUT); + CS.digitalWrite(0, HIGH); + int recpin = CS.digitalRead(0); + CS.portMode(0, 0b0111111001111110); // 0 = output, 1 = input + CS.portWrite(0, 0b1000000110000001); // 0 = LOW, 1 = HIGH + int recport = CS.portRead(0); + CS.pinPullup(1,HIGH); + CS.portPullup(0, 0b0111111001111110); // 0 = no pullup, 1 = pullup + CS.portInterrupts(0,0b0000000000000001,0b0000000000000000,0b0000000000000001); +*/ + +Centipede CS; // create Centipede object + + +void setup() +{ + Wire.begin(); // start I2C + + CS.initialize(); // set all registers to default + + CS.portMode(0, 0b0000000000000000); // set all pins on chip 0 to output (0 to 15) + //CS.portMode(1, 0b0000000000000000); // set all pins on chip 1 to output (16 to 31) + + //TWBR = 12; // uncomment for 400KHz I2C (on 16MHz Arduinos) + +} + + +void loop() +{ + for (int i = 0; i < 16; i++) { + CS.digitalWrite(i, HIGH); + delay(10); + } + + for (int i = 0; i < 16; i++) { + CS.digitalWrite(i, LOW); + delay(10); + } +}