Monday, December 12, 2016

Arduino and MCP23S17 Port Expander (Part 2)

Adding a Second MCP23S17 Port Expander — 
Adding a second MCP23S17 adds 16 additional pins and is not difficult to accomplish. The second (or more) chip just has to have +V and Ground connections for power, each IC chip pin 18 (Reset) needs to have the 10K resistor to +V, each of the A0, A1, and A2 pins must be either Ground or +V, the CS pin and the three SPI pins (SCK, SI, and SO) must be connected together between chips to the Arduino CS ,CLK, MOSI, and MISO pins. You now have 16 or more additional pins.
Since that was easy, we will skip ahead to building a quad MCP23S17 Port Expander backpack for the Arduino. Four MCP23S17 chips were added to a backpack expander board that fits on both an Uno and Mega 2560 Arduino. SPI on the Arduino uses 3 SPI pins (Uno pins D11, D12, D13, or on Mega 2560 pins D50, D51, D52). SPI also requires a CS pin which is used to select which SPI device is active at any given time. The default Arduino CS pin is D10 on Uno and D53 on Mega 2560. The SPI pins are connected to the Arduino ICSP pins, so with careful construction adding an ICSP 6-pin jack, the backpack will automatically work with either the Uno or Mega. The only requirement is to connect the CS pin which is not part of the ICSP configuration. Pin D10 was used for CS with this backpack. The ICSP does provide +V and Ground connections, which would allow the port expander board to be mounted separately from the Arduino, while using a 6-wire ICSP jumper for power and SPI. The 6th ICSP wire is for Reset which is not used in this application, so a 7th wire would be required for the CS connection. The Arduino pins just pass through the backpack board so that other backpacks could be placed on top. Only the SPI and CS pins, and V+ and Ground, make a connection between the boards.


Pictures: The finished backpack mounted on a Mega 2560 uses the ICSP for SPI and D10 for CS. Each MCP digital pin is brought out to an 8-pin header (Port A pins [0...7] and Port B pins [8...15]). The MCP23S17 interrupt pins (INTA and INTB x 4 chips = 8) were brought out to a separate header where they could be used for processing interrupts. The backside of the port expander backpack is a tangle of wires required to make all of the necessary connections.  An etched and drilled circuit board would have made this much easier.
MultiTest Sketch --
The following MCP23S17_MultiTest_01.ino sketch code is lengthy but it provides several different examples of using the Majenko library with the quad port expander. Each example can be turned off by commenting out the function calls in loop(). The code instantiates the 4 MCP23S17 chips on the quad backpack, various combinations of input and output pins are set, pins are read and written, 8-pin ports are read and written, and long 16-pin (Port A & Port B) words are read and written. Then, 16 pins are sequentially set and cleared with counts displayed to Serial Monitor in decimal, hex, and binary. This process is conducted for each of the four chips. The code demonstrates how to do each of these functions so they can be used in other applications.
This code does not conduct any interrupt processing. Interrupts will be covered in detail in future parts of this series.

/*
 * MCP23S17_MultiTest_01.ino
 * Library Ref: github.com/MajenkoLibraries/MCP23S17
 *
 * Lowell Bahner
 * 2016-12-11
 *
 * Hardware: Arduino UNO / Mega2560
 * IDE: Arduino 1.6.5
 *
 * Useful SPI Ref: gammon.com.au/spi
 *
 * Wire the SPI Interface common lines (Mega2560 SPI pins shown in [ ]):
 * Arduino SPI_MOSI pin 11 [51] <->   SI  MCP23S17 pin 13
 * Arduino SPI_MISO pin 12 [50] <->   SO  MCP23S17 pin 14
 * Arduino SPI_CLOCK pin 13 [52]<->   SCK MCP23S17 pin 12
 * Arduino SPI_CS pin 10 [53]   <->   SS  MCP23S17 pin 11
 * MCP23S17 VDD pin 9 to +5V
 * MCP23S17 VSS pin 10 to Gnd
 * MCP23S17 Reset pin 18 to +5V
 * MCP23S17 Interrupt pins 19-20
 * MCP23S17 A0,A1,A2 pins connect to Gnd or +5V (000 = Address 0, 100 = Address 1, 010 = Address 2, etc)
 * MCP23S17 Port A pins are chip pins 21-28
 * MCP23S17 Port B pins are chip pins 1-8
 *
 * This sketch runs a series of functions to demonstrate library capabilities.
 * This sketch does not demonstrate interrupt functionality.
 *
 * This sketch instantiates 4 MCP23S17 chips.
 * Bank1 (MCP23S17 address 1) pins are set as INPUT or INPUT_PULLUP.
 *    Normally HIGH, use switch to set a pin LOW.
 * Bank0 (MCP23S17 address 0) pins are set as OUTPUT.
 *    MCP23S17 outputs will power LEDs up to 25ma through 1000ohm resistor to ground.
 *    
 * Bank3 (MCP23S17 address 3) pins are set as INPUT or INPUT_PULLUP.
 *    Normally HIGH, use switch to set a pin LOW.
 * Bank2 (MCP23S17 address 2) pins are set as OUTPUT.
 *    MCP23S17 outputs will power LEDs up to 25ma through 1000ohm resistor to ground.
 *
 * Majenko MCP23S17 library functions (see .h,.cpp files for details):
 *
 *  bank.pinMode(uint8_t pin, uint8_t mode)
 *    where modes are:
 *      OUTPUT - sets pin HIGH
 *      INPUT  - sets pin LOW for sensing change to HIGH +V
 *      INPUT_PULLUP - sets pin HIGH for sensing change to LOW 0V
 *
 *  bank.digitalWrite(uint8_t pin, uint8_t value)
 *    if mode=OUTPUT, pin value = LOW (0) or HIGH (1)
 *    if mode=INPUT, value LOW disables pullup on pin, value HIGH enables pullup on pin
 *
 *  uint8_t value = bank.digitalRead(uint8_t pin)
 *    read the state of the pin
 *
 *  uint8_t value = bank.readPort(uint8_t port)
 *    read entire 8-bit port of all INPUT pins on Port A (port=0) or Port B (port>=1)
 *
 *  uint16_t longValue = bank.readPort()
 *    read both ports as 16-bit combined
 *
 *  bank.writePort(uint8_t port, uint8_t val)
 *    write val (0 or 1, hex example 0x55) to all OUTPUT pins on Port A (port=0) or Port B (port>=1)
 *
 *  bank.writePort(uint16_t val)
 *    write val (hex example 0x55AA) to all OUTPUT pins on Port A and Port B
 *
 *  Also, interrupt functions are defined:
 *      enableInterrupt(uint8_t pin, uint8_t type);
 *      void disableInterrupt(uint8_t pin);
 *      void setMirror(boolean m);
 *      uint16_t getInterruptPins();
 *      uint16_t getInterruptValue();
 *      void setInterruptLevel(uint8_t level);
 *      void setInterruptOD(boolean openDrain);
 *
 *
 *
 *
Run Sketch: Serial Monitor Output

 -- RWpins() --

Bank1: Switch i15: 1 (Push button switch not pushed, Bank1 INPUT pin 15 is HIGH +5V)
Bank0: Output j4:  1 (Bank0 OUTPUT pin 4 is HIGH.
                      Arduino pin 7 is set HIGH.
                      LED on pin 4 is ON. LED on pin 7 is ON.)

Bank1: Switch i15: 0 (Push button switch pushed, grounds Bank1 INPUT pin 15)
Bank0: Output j4:  0 (Bank0 OUTPUT pin 4 switches to LOW.
                      Arduino pin 7 is set LOW.
                      LED on pin 4 is OFF. LED on pin 7 is OFF.)

 -- RWport() --

Bank0: Port A BIN: 00000000
Bank0: Port B BIN: 00000000

Bank0: Port A BIN: 11110100  DEC: 244
Bank0: Port B BIN: 00001011  DEC: 11

 -- RWlongPortValue() --

Bank0: Port A & B BIN: 0000101111110100  HEX: 0x0BF4    DEC: 3060

 -- RWlongPort() --

Bank0: Port A & B BIN: 1011100101000010  HEX: 0xB942    DEC: 47426

 -- CyclePins() --

Bank0: Port A & B BIN: 0000000000000000  HEX: 0x0000    DEC: 0
Bank0: Port A & B BIN: 0000000000000001  HEX: 0x0001    DEC: 1
Bank0: Port A & B BIN: 0000000000000011  HEX: 0x0003    DEC: 3
Bank0: Port A & B BIN: 0000000000000111  HEX: 0x0007    DEC: 7
Bank0: Port A & B BIN: 0000000000001111  HEX: 0x000F    DEC: 15
Bank0: Port A & B BIN: 0000000000011111  HEX: 0x001F    DEC: 31
Bank0: Port A & B BIN: 0000000000111111  HEX: 0x003F    DEC: 63
Bank0: Port A & B BIN: 0000000001111111  HEX: 0x007F    DEC: 127
Bank0: Port A & B BIN: 0000000011111111  HEX: 0x00FF    DEC: 255
Bank0: Port A & B BIN: 0000000111111111  HEX: 0x01FF    DEC: 511
Bank0: Port A & B BIN: 0000001111111111  HEX: 0x03FF    DEC: 1023
Bank0: Port A & B BIN: 0000011111111111  HEX: 0x07FF    DEC: 2047
Bank0: Port A & B BIN: 0000111111111111  HEX: 0x0FFF    DEC: 4095
Bank0: Port A & B BIN: 0001111111111111  HEX: 0x1FFF    DEC: 8191
Bank0: Port A & B BIN: 0011111111111111  HEX: 0x3FFF    DEC: 16383
Bank0: Port A & B BIN: 0111111111111111  HEX: 0x7FFF    DEC: 32767
Bank0: Port A & B BIN: 1111111111111111  HEX: 0xFFFF    DEC: 65535

Bank0: Port A & B BIN: 1111111111111111  HEX: 0xFFFF    DEC: 65535
Bank0: Port A & B BIN: 0111111111111111  HEX: 0x7FFF    DEC: 32767
Bank0: Port A & B BIN: 0011111111111111  HEX: 0x3FFF    DEC: 16383
Bank0: Port A & B BIN: 0001111111111111  HEX: 0x1FFF    DEC: 8191
Bank0: Port A & B BIN: 0000111111111111  HEX: 0x0FFF    DEC: 4095
Bank0: Port A & B BIN: 0000011111111111  HEX: 0x07FF    DEC: 2047
Bank0: Port A & B BIN: 0000001111111111  HEX: 0x03FF    DEC: 1023
Bank0: Port A & B BIN: 0000000111111111  HEX: 0x01FF    DEC: 511
Bank0: Port A & B BIN: 0000000011111111  HEX: 0x00FF    DEC: 255
Bank0: Port A & B BIN: 0000000001111111  HEX: 0x007F    DEC: 127
Bank0: Port A & B BIN: 0000000000111111  HEX: 0x003F    DEC: 63
Bank0: Port A & B BIN: 0000000000011111  HEX: 0x001F    DEC: 31
Bank0: Port A & B BIN: 0000000000001111  HEX: 0x000F    DEC: 15
Bank0: Port A & B BIN: 0000000000000111  HEX: 0x0007    DEC: 7
Bank0: Port A & B BIN: 0000000000000011  HEX: 0x0003    DEC: 3
Bank0: Port A & B BIN: 0000000000000001  HEX: 0x0001    DEC: 1
Bank0: Port A & B BIN: 0000000000000000  HEX: 0x0000    DEC: 0
 *
 *
 *
 */

// Majenko MCP23S17 Library (revised 2017-Jan-23)
#include <MCP23S17.h>

// Arduino Library SPI.h
#include <SPI.h>

// SPI CS/SS chipselect pin can be changed by user as desired
const uint8_t chipSelect = 10; // use for Uno or Mega

// example Arduino board pin
uint8_t pin7 = 7;

// Create an object for each chip
// Bank0 is address 0. Pins A0,A1,A2 grounded.
// Bank1 is address 1. Pin A0=+5V, A1,A2 grounded.

MCP23S17 Bank0(&SPI, chipSelect, 0);
MCP23S17 Bank1(&SPI, chipSelect, 1);
MCP23S17 Bank2(&SPI, chipSelect, 2);
MCP23S17 Bank3(&SPI, chipSelect, 3);

void setup() {

  // Slow down the master a bit if desired
  // SPI.setClockDivider(SPI_CLOCK_DIV8);

  Serial.begin(9600);

  Bank0.begin();
  Bank1.begin();
  Bank2.begin();
  Bank3.begin();

  // LED connected to Arduino pin 7 to test inter-device communication
  pinMode(pin7, OUTPUT);

  //
  // Set MCP23S17 pin modes:
  // example set one pin: chip.pinMode(0, OUTPUT); // sets chip pin 0 (Port A 0) to OUTPUT mode
  //
  setChipPins(); // use loop to set individual pins
  // or, since this library does not have a setPortPinMode, do 8 pin loops
  //setPortPins(); // example: set pins on each Port on each chip to different modes.
  //

}

// Set all Chip pins to desired mode
void setChipPins() {
  // Example usage

  // Set all Bank0 pins to be OUTPUT
  for (uint8_t i = 0; i <= 15; i++)
    Bank0.pinMode(i, OUTPUT);

  // Set all Bank1 pins to be INPUT_PULLUP
  for (uint8_t i = 0; i <= 15; i++)
    //Bank1.pinMode(i, INPUT);  // unswitched pin voltages about +0.1V, switch must pull pin to +5V
    Bank1.pinMode(i, INPUT_PULLUP);  // unswitched pin voltages about +4.9V, switch must ground pin

  // Set all Bank2 pins to be OUTPUT
  for (uint8_t i = 0; i <= 15; i++)
    Bank2.pinMode(i, OUTPUT);

  // Set all Bank3 pins to be INPUT_PULLUP
  for (uint8_t i = 0; i <= 15; i++)
    //Bank3.pinMode(i, INPUT);  // unswitched pin voltages about +0.1V, switch must pull pin to +5V
    Bank3.pinMode(i, INPUT_PULLUP);  // unswitched pin voltages about +4.9V, switch must ground pin
}

// Set all Chip pins to OUTPUT mode
void setAllPins() {
  // Example usage

  // Set all Bank0 pins to be OUTPUT
  for (uint8_t i = 0; i <= 15; i++)
    Bank0.pinMode(i, OUTPUT);

  // Set all Bank1 pins to be OUTPUT
  for (uint8_t i = 0; i <= 15; i++)
    Bank1.pinMode(i, OUTPUT);

  // Set all Bank2 pins to be OUTPUT
  for (uint8_t i = 0; i <= 15; i++)
    Bank2.pinMode(i, OUTPUT);

  // Set all Bank3 pins to be OUTPUT
  for (uint8_t i = 0; i <= 15; i++)
    Bank3.pinMode(i, OUTPUT);
}

// Set Port pins to desired mode
void setPortPins() {
  // Example usage

  // Set all Bank0 Port A pins to OUTPUT
  for (uint8_t i = 0; i <= 7; i++)
    Bank0.pinMode(i, OUTPUT);

  // Set all Bank0 Port B pins to OUTPUT
  for (uint8_t i = 8; i <= 15; i++)
    Bank0.pinMode(i, OUTPUT);

  // Set all Bank1 Port A pins to be INPUT_PULLUP
  for (uint8_t i = 0; i <= 7; i++)
    Bank1.pinMode(i, INPUT_PULLUP);

  // Set all Bank1 Port B pins to be INPUT_PULLUP
  for (uint8_t i = 8; i <= 15; i++)
    Bank1.pinMode(i, INPUT_PULLUP);

  // Set all Bank2 Port A pins to OUTPUT
  for (uint8_t i = 0; i <= 7; i++)
    Bank2.pinMode(i, OUTPUT);

  // Set all Bank2 Port B pins to OUTPUT
  for (uint8_t i = 8; i <= 15; i++)
    Bank2.pinMode(i, OUTPUT);

  // Set all Bank3 Port A pins to be INPUT_PULLUP
  for (uint8_t i = 0; i <= 7; i++)
    Bank3.pinMode(i, INPUT_PULLUP);

  // Set all Bank3 Port B pins to be INPUT_PULLUP
  for (uint8_t i = 8; i <= 15; i++)
    Bank3.pinMode(i, INPUT_PULLUP);
}


//
// Change LED On/Off with button push
// 1) Switch an INPUT_PULLUP pin to ground
// 2) Read the pin value
// 3) Write the value to an OUTPUT pin
// 4) Turn LED On/Off
// Use functions digitalRead(pin) and digitalWrite(pin,value)
//
void RWpins01() {

  setChipPins();

  Serial.print("\n -- RWpins01() --"); Serial.println("");

  uint8_t b15 = 0;  // Bank1 input pin value (0 push LOW, 1 normally open HIGH) with push button switch to gnd
  uint8_t i = 15;   // Bank1 pin number
  uint8_t a4 = 0;   // Bank0 output pin value
  uint8_t j = 4;    // Bank0 pin number

  // read the switch value into b15
  b15 = Bank1.digitalRead(i);
  Serial.print("\nBank1: Switch i"); Serial.print(i); Serial.print(": ");  Serial.println(b15);

  // write the switch pin i, value b15, to the output pin j
  Bank0.digitalWrite(j, b15);

  a4 = Bank0.digitalRead(j);
  Serial.print("Bank0: Output j"); Serial.print(j); Serial.print(": ");  Serial.println(a4);

  // Turn on/off LED connected to Arduino pin 7 through resistor to ground
  digitalWrite(pin7, a4);
}

void RWpins23() {

  setChipPins();

  Serial.print("\n -- RWpins23() --"); Serial.println("");

  uint8_t b15 = 0;  // Bank1 input pin value (0 push LOW, 1 normally open HIGH) with push button switch to gnd
  uint8_t i = 15;   // Bank1 pin number
  uint8_t a4 = 0;   // Bank0 output pin value
  uint8_t j = 4;    // Bank0 pin number

  // read the switch value into b15
  b15 = Bank3.digitalRead(i);
  Serial.print("\nBank3: Switch i"); Serial.print(i); Serial.print(": ");  Serial.println(b15);

  // write the switch pin i, value b15, to the output pin j
  Bank2.digitalWrite(j, b15);

  a4 = Bank2.digitalRead(j);
  Serial.print("Bank2: Output j"); Serial.print(j); Serial.print(": ");  Serial.println(a4);

  // Turn on/off LED connected to Arduino pin 7 through resistor to ground
  digitalWrite(pin7, a4);
}


//
// Read and Write Port values
//
void RWport0() {

  Serial.print("\n -- RWport0() --"); Serial.println("");

  // set the port pin modes
  setAllPins(); // all Bank0 pins are OUTPUT but set as Ports

  // clear the port pin values to 0
  uint8_t port = 0; // Port A
  uint8_t val = 0x00; // set to 0000 0000
  Bank0.writePort(port, val);
  port = 1; // Port B
  Bank0.writePort(port, val); // set to 0000 0000

  // read the port pin values
  uint8_t valueA = Bank0.readPort(0);
  Serial.print("\nBank0: Port A BIN: "); print8Bits(valueA); Serial.println("");
  uint8_t valueB = Bank0.readPort(1);
  Serial.print("Bank0: Port B BIN: "); print8Bits(valueB); Serial.println("");

  // set the port pin values
  port = 0; // Port A
  val = 0xF4; // set to 1111 0100
  Bank0.writePort(port, val);
  port = 1; // Port B
  val = 0x0B; // set to 0000 1011
  //val = 0xB0; // set to 1011 0000
  Bank0.writePort(port, val);

  // read the port pin values
  valueA = Bank0.readPort(0);
  Serial.print("\nBank0: Port A BIN: "); print8Bits(valueA);
  Serial.print("  DEC: "); Serial.println(valueA, DEC);

  valueB = Bank0.readPort(1);
  Serial.print("Bank0: Port B BIN: "); print8Bits(valueB);
  Serial.print("  DEC: "); Serial.println(valueB, DEC);
}

void RWport1() {

  Serial.print("\n -- RWport1() --"); Serial.println("");

  // set the port pin modes
  setAllPins(); // all Bank0 pins are OUTPUT but set as Ports

  // clear the port pin values to 0
  uint8_t port = 0; // Port A
  uint8_t val = 0x00; // set to 0000 0000
  Bank1.writePort(port, val);
  port = 1; // Port B
  Bank1.writePort(port, val); // set to 0000 0000

  // read the port pin values
  uint8_t valueA = Bank1.readPort(0);
  Serial.print("\nBank1: Port A BIN: "); print8Bits(valueA); Serial.println("");
  uint8_t valueB = Bank1.readPort(1);
  Serial.print("Bank1: Port B BIN: "); print8Bits(valueB); Serial.println("");

  // set the port pin values
  port = 0; // Port A
  val = 0xF4; // set to 1111 0100
  Bank1.writePort(port, val);
  port = 1; // Port B
  val = 0x0B; // set to 0000 1011
  //val = 0xB0; // set to 1011 0000
  Bank1.writePort(port, val);

  // read the port pin values
  valueA = Bank1.readPort(0);
  Serial.print("\nBank1: Port A BIN: "); print8Bits(valueA);
  Serial.print("  DEC: "); Serial.println(valueA, DEC);

  valueB = Bank1.readPort(1);
  Serial.print("Bank1: Port B BIN: "); print8Bits(valueB);
  Serial.print("  DEC: "); Serial.println(valueB, DEC);
}

void RWport2() {

  Serial.print("\n -- RWport2() --"); Serial.println("");

  // set the port pin modes
  setAllPins(); // all Bank2 pins are OUTPUT but set as Ports

  // clear the port pin values to 0
  uint8_t port = 0; // Port A
  uint8_t val = 0x00; // set to 0000 0000
  Bank2.writePort(port, val);
  port = 1; // Port B
  Bank2.writePort(port, val); // set to 0000 0000

  // read the port pin values
  uint8_t valueA = Bank2.readPort(0);
  Serial.print("\nBank2: Port A BIN: "); print8Bits(valueA); Serial.println("");
  uint8_t valueB = Bank2.readPort(1);
  Serial.print("Bank2: Port B BIN: "); print8Bits(valueB); Serial.println("");

  // set the port pin values
  port = 0; // Port A
  val = 0xF4; // set to 1111 0100
  Bank2.writePort(port, val);
  port = 1; // Port B
  val = 0x0B; // set to 0000 1011
  //val = 0xB0; // set to 1011 0000
  Bank2.writePort(port, val);

  // read the port pin values
  valueA = Bank2.readPort(0);
  Serial.print("\nBank2: Port A BIN: "); print8Bits(valueA);
  Serial.print("  DEC: "); Serial.println(valueA, DEC);

  valueB = Bank2.readPort(1);
  Serial.print("Bank2: Port B BIN: "); print8Bits(valueB);
  Serial.print("  DEC: "); Serial.println(valueB, DEC);
}

void RWport3() {

  Serial.print("\n -- RWport3() --"); Serial.println("");

  // set the port pin modes
  setAllPins(); // all Bank3 pins are OUTPUT but set as Ports

  // clear the port pin values to 0
  uint8_t port = 0; // Port A
  uint8_t val = 0x00; // set to 0000 0000
  Bank3.writePort(port, val);
  port = 1; // Port B
  Bank3.writePort(port, val); // set to 0000 0000

  // read the port pin values
  uint8_t valueA = Bank3.readPort(0);
  Serial.print("\nBank3: Port A BIN: "); print8Bits(valueA); Serial.println("");
  uint8_t valueB = Bank3.readPort(1);
  Serial.print("Bank3: Port B BIN: "); print8Bits(valueB); Serial.println("");

  // set the port pin values
  port = 0; // Port A
  val = 0xF4; // set to 1111 0100
  Bank3.writePort(port, val);
  port = 1; // Port B
  val = 0x0B; // set to 0000 1011
  //val = 0xB0; // set to 1011 0000
  Bank3.writePort(port, val);

  // read the port pin values
  valueA = Bank3.readPort(0);
  Serial.print("\nBank3: Port A BIN: "); print8Bits(valueA);
  Serial.print("  DEC: "); Serial.println(valueA, DEC);

  valueB = Bank3.readPort(1);
  Serial.print("Bank3: Port B BIN: "); print8Bits(valueB);
  Serial.print("  DEC: "); Serial.println(valueB, DEC);
}


void RWlongPortValue0() {

  Serial.print("\n -- RWlongPortValue0() --"); Serial.println("");

  // Read the Bank0 Port pin values as a combined long value
  uint16_t valueLong = Bank0.readPort();
  Serial.print("\nBank0: Port A & B BIN: "); print16Bits(valueLong);
  Serial.print("  HEX: "); crPrintHEX(valueLong, 4);
  Serial.print("  DEC: "); Serial.println(valueLong, DEC);
}

void RWlongPortValue1() {

  Serial.print("\n -- RWlongPortValue1() --"); Serial.println("");

  // Read the Bank1 Port pin values as a combined long value
  uint16_t valueLong = Bank1.readPort();
  Serial.print("\nBank1: Port A & B BIN: "); print16Bits(valueLong);
  Serial.print("  HEX: "); crPrintHEX(valueLong, 4);
  Serial.print("  DEC: "); Serial.println(valueLong, DEC);
}

void RWlongPortValue2() {

  Serial.print("\n -- RWlongPortValue2() --"); Serial.println("");

  // Read the Bank2 Port pin values as a combined long value
  uint16_t valueLong = Bank2.readPort();
  Serial.print("\nBank2: Port A & B BIN: "); print16Bits(valueLong);
  Serial.print("  HEX: "); crPrintHEX(valueLong, 4);
  Serial.print("  DEC: "); Serial.println(valueLong, DEC);
}

void RWlongPortValue3() {

  Serial.print("\n -- RWlongPortValue3() --"); Serial.println("");

  // Read the Bank3 Port pin values as a combined long value
  uint16_t valueLong = Bank3.readPort();
  Serial.print("\nBank3: Port A & B BIN: "); print16Bits(valueLong);
  Serial.print("  HEX: "); crPrintHEX(valueLong, 4);
  Serial.print("  DEC: "); Serial.println(valueLong, DEC);
}


void RWlongPort0() {

  Serial.print("\n -- RWlongPort0() --"); Serial.println("");

  // Write the Bank0 Port pin values as a combined long value
  uint16_t valueLong = 0xB942;
  Bank0.writePort(valueLong);

  // Read the Bank0 Port pin values as a combined long value
  uint16_t valueLongIn = Bank0.readPort();
  Serial.print("\nBank0: Port A & B BIN: "); print16Bits(valueLongIn);
  Serial.print("  HEX: "); crPrintHEX(valueLongIn, 4);
  Serial.print("  DEC: "); Serial.println(valueLongIn, DEC);
}

void RWlongPort1() {

  Serial.print("\n -- RWlongPort1() --"); Serial.println("");

  // Write the Bank1 Port pin values as a combined long value
  uint16_t valueLong = 0xB942;
  Bank1.writePort(valueLong);

  // Read the Bank1 Port pin values as a combined long value
  uint16_t valueLongIn = Bank1.readPort();
  Serial.print("\nBank1: Port A & B BIN: "); print16Bits(valueLongIn);
  Serial.print("  HEX: "); crPrintHEX(valueLongIn, 4);
  Serial.print("  DEC: "); Serial.println(valueLongIn, DEC);
}

void RWlongPort2() {

  Serial.print("\n -- RWlongPort2() --"); Serial.println("");

  // Write the Bank2 Port pin values as a combined long value
  uint16_t valueLong = 0xB942;
  Bank2.writePort(valueLong);

  // Read the Bank2 Port pin values as a combined long value
  uint16_t valueLongIn = Bank2.readPort();
  Serial.print("\nBank2: Port A & B BIN: "); print16Bits(valueLongIn);
  Serial.print("  HEX: "); crPrintHEX(valueLongIn, 4);
  Serial.print("  DEC: "); Serial.println(valueLongIn, DEC);
}

void RWlongPort3() {

  Serial.print("\n -- RWlongPort3() --"); Serial.println("");

  // Write the Bank3 Port pin values as a combined long value
  uint16_t valueLong = 0xB942;
  Bank3.writePort(valueLong);

  // Read the Bank3 Port pin values as a combined long value
  uint16_t valueLongIn = Bank3.readPort();
  Serial.print("\nBank3: Port A & B BIN: "); print16Bits(valueLongIn);
  Serial.print("  HEX: "); crPrintHEX(valueLongIn, 4);
  Serial.print("  DEC: "); Serial.println(valueLongIn, DEC);
}


//
// Cycle through OUTPUT pins with count-up count-down
//
void CyclePins0() {

  Serial.print("\n -- CyclePins0() --"); Serial.println("\n");

  // Set all Bank0 pins to be OUTPUT
  for (uint8_t i = 0; i <= 15; i++)
    Bank0.pinMode(i, OUTPUT);

  // clear Bank0 using writePort
  uint16_t valueLong = 0x0000;
  Bank0.writePort(valueLong);

  // Read the Bank0 Port pin values as a combined long value
  for (int8_t i = -1; i <= 15; i++) {
    if (i >= 0) Bank0.digitalWrite(i, 1); // i=-1 allows print of 0 data
    valueLong = Bank0.readPort(); // read 16 bits
    Serial.print("Bank0: Port A & B BIN: "); print16Bits(valueLong);
    Serial.print("  HEX: "); crPrintHEX(valueLong, 4);
    Serial.print("  DEC: "); Serial.println(valueLong, DEC);
  }

  Serial.println("");

  for (int8_t i = 15; i >= -1; i--) { // i=-1 allows print of 0 data
    // decrement after the read while reading down the values
    valueLong = Bank0.readPort(); //  read 16 bits
    Serial.print("Bank0: Port A & B BIN: "); print16Bits(valueLong);
    Serial.print("  HEX: "); crPrintHEX(valueLong, 4);
    Serial.print("  DEC: "); Serial.println(valueLong, DEC);
    Bank0.digitalWrite(i, 0);
  }
}

void CyclePins1() {

  Serial.print("\n -- CyclePins1() --"); Serial.println("\n");

  // Set all Bank1 pins to be OUTPUT
  for (uint8_t i = 0; i <= 15; i++)
    Bank1.pinMode(i, OUTPUT);

  // clear Bank1 using writePort
  uint16_t valueLong = 0x0000;
  Bank1.writePort(valueLong);

  // Read the Bank1 Port pin values as a combined long value
  for (int8_t i = -1; i <= 15; i++) {
    if (i >= 0) Bank1.digitalWrite(i, 1); // i=-1 allows print of 0 data
    valueLong = Bank1.readPort(); // read 16 bits
    Serial.print("Bank1: Port A & B BIN: "); print16Bits(valueLong);
    Serial.print("  HEX: "); crPrintHEX(valueLong, 4);
    Serial.print("  DEC: "); Serial.println(valueLong, DEC);
  }

  Serial.println("");

  for (int8_t i = 15; i >= -1; i--) { // i=-1 allows print of 0 data
    // decrement after the read while reading down the values
    valueLong = Bank1.readPort(); //  read 16 bits
    Serial.print("Bank1: Port A & B BIN: "); print16Bits(valueLong);
    Serial.print("  HEX: "); crPrintHEX(valueLong, 4);
    Serial.print("  DEC: "); Serial.println(valueLong, DEC);
    Bank1.digitalWrite(i, 0);
  }
}

void CyclePins2() {

  Serial.print("\n -- CyclePins2() --"); Serial.println("\n");

  // Set all Bank2 pins to be OUTPUT
  for (uint8_t i = 0; i <= 15; i++)
    Bank2.pinMode(i, OUTPUT);

  // clear Bank2 using writePort
  uint16_t valueLong = 0x0000;
  Bank2.writePort(valueLong);

  // Read the Bank2 Port pin values as a combined long value
  for (int8_t i = -1; i <= 15; i++) {
    if (i >= 0) Bank2.digitalWrite(i, 1); // i=-1 allows print of 0 data
    valueLong = Bank2.readPort(); // read 16 bits
    Serial.print("Bank2: Port A & B BIN: "); print16Bits(valueLong);
    Serial.print("  HEX: "); crPrintHEX(valueLong, 4);
    Serial.print("  DEC: "); Serial.println(valueLong, DEC);
  }

  Serial.println("");

  for (int8_t i = 15; i >= -1; i--) { // i=-1 allows print of 0 data
    // decrement after the read while reading down the values
    valueLong = Bank2.readPort(); //  read 16 bits
    Serial.print("Bank2: Port A & B BIN: "); print16Bits(valueLong);
    Serial.print("  HEX: "); crPrintHEX(valueLong, 4);
    Serial.print("  DEC: "); Serial.println(valueLong, DEC);
    Bank2.digitalWrite(i, 0);
  }
}

void CyclePins3() {

  Serial.print("\n -- CyclePins3() --"); Serial.println("\n");

  // Set all Bank3 pins to be OUTPUT
  for (uint8_t i = 0; i <= 15; i++)
    Bank3.pinMode(i, OUTPUT);

  // clear Bank3 using writePort
  uint16_t valueLong = 0x0000;
  Bank3.writePort(valueLong);

  // Read the Bank3 Port pin values as a combined long value
  for (int8_t i = -1; i <= 15; i++) {
    if (i >= 0) Bank3.digitalWrite(i, 1); // i=-1 allows print of 0 data
    valueLong = Bank3.readPort(); // read 16 bits
    Serial.print("Bank3: Port A & B BIN: "); print16Bits(valueLong);
    Serial.print("  HEX: "); crPrintHEX(valueLong, 4);
    Serial.print("  DEC: "); Serial.println(valueLong, DEC);
  }

  Serial.println("");

  for (int8_t i = 15; i >= -1; i--) { // i=-1 allows print of 0 data
    // decrement after the read while reading down the values
    valueLong = Bank3.readPort(); //  read 16 bits
    Serial.print("Bank3: Port A & B BIN: "); print16Bits(valueLong);
    Serial.print("  HEX: "); crPrintHEX(valueLong, 4);
    Serial.print("  DEC: "); Serial.println(valueLong, DEC);
    Bank3.digitalWrite(i, 0);
  }
}


void loop() {

  // Change LED On/Off with button push
  RWpins01();
  RWpins23();

  // Read and Write Port pins as a group
  RWport0();
  RWport1();
  RWport2();
  RWport3();

  // Read the Bank0 Port pin values as a combined long value
  RWlongPortValue0();
  RWlongPortValue1();
  RWlongPortValue2();
  RWlongPortValue3();

  // Read and Write Chip 16 pins as a group
  RWlongPort0();
  RWlongPort1();
  RWlongPort2();
  RWlongPort3();

  // Cycle through OUTPUT pins with count-up count-down
  CyclePins0();
  CyclePins1();
  CyclePins2();
  CyclePins3();

  delay(1000);

}

// print 8-bit byte as 8 bit binary string
void print8Bits(uint8_t myByte) {
  for (byte mask = 0x80; mask; mask >>= 1) {
    if (mask  & myByte)
      Serial.print('1');
    else
      Serial.print('0');
  }
}

// print 16-bit word as 16 bit binary string
void print16Bits(uint16_t myWord) {
  for (uint16_t mask = 0x8000; mask; mask >>= 1) {
    if (mask  & myWord)
      Serial.print('1');
    else
      Serial.print('0');
  }
}


//---------------------------------------------------------------------------------
// crPrintHEX print value as hex with specified number of digits
//---------------------------------------------------------------------------------

void crPrintHEX(unsigned long DATA, unsigned char numChars) {
  unsigned long mask  = 0x0000000F;
  mask = mask << 4 * (numChars - 1);
  Serial.print("0x");
  for (unsigned int i = numChars; i > 0; --i) {
    Serial.print(((DATA & mask) >> (i - 1) * 4), HEX);
    mask = mask >> 4;
  }

  Serial.print("  ");
}

Useful references -

(Dec 12, 2016)

No comments:

Post a Comment