# Documentation : MCP23018

## Pinout and Pin assignments

* `+` indicates connected pin
* `o` indicates unconnected pin
* `=` is used to list other things the pin is connected to
* `-`s inserted between some of the pin functions for readability

### MCP23018
                         Vss(GND) +01---.---28+ NC
                               NC +02       27+ GPA7
                             GPB0 +03       26+ GPA6
                             GPB1 +04       25+ GPA5
                             GPB2 +05       24+ GPA4
                             GPB3 +06       23+ GPA3
                             GPB4 +07       22+ GPA2
                             GPB5 +08       21+ GPA1
                             GPB6 +09       20+ GPA0
                             GPB7 +10       19+ INTA
                         Vdd(Vcc) +11       18+ INTB
                              SCL +12       17+ NC
                              SDA +13       16+ RESET
                               NC +14-------15+ ADDR

### MCP23018 Pin Assignments

         power_negative  Vss(GND) +01---.---28o NC
                               NC o02       27o GPA7
                  row_5      GPB0 +03       26+ GPA6   column_6
                  row_4      GPB1 +04       25+ GPA5   column_5
                  row_3      GPB2 +05       24+ GPA4   column_4
                  row_2      GPB3 +06       23+ GPA3   column_3
                  row_1      GPB4 +07       22+ GPA2   column_2
                  row_0      GPB5 +08       21+ GPA1   column_1
                             GPB6 o09       20+ GPA0   column_0
                             GPB7 o10       19o INTA
         power_positive  Vdd(Vcc) +11       18o INTB
                    I2C       SCL +12       17o NC
                    I2C       SDA +13       16+ RESET  = Vdd(Vcc) (see note)
                               NC o14-------15+ ADDR   = Vss(GND) (see note)

* notes:
    * Row and column assignments are to matrix positions, which may or may
      or may not correspond to the physical position of the key: e.g. the key
      where `row_4` and `column_2` cross will be scanned into the matrix at
      `[4][2]`, wherever it happens to be located on the keyboard.  Mapping
      from one to the other (which only matters for defining layouts) is
      handled elsewhere.
    * ADDR (pin15): Set slave address to `0b0100000` by connecting to Vss(GND).
        * The user-defined bits are the three least significant
        * I2C addresses are 7 bits long (the last bit in the byte is used for
          indicating read/write)
    * RESET (pin16) must be externally biased.  Since we're not going to
      trigger it ourselves, we can tie it high.
        * This is not noted in the I2C Pinout Description section of the
          MCP23018 datasheet, but it's true (empirically), and it is noted in
          the SPI Pinout Description section, and in the MCP23017 datasheet.
        * I'm not the first person who's failed to notice ;)
            * <http://davidn.org/wp/?p=89>
            * <http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1293498979>

## Notes about Registers

    register  address  function (for all bits)
    --------  -------  -----------------------
    IODIRA    0x00     \ 1: set corresponding pin as input
    IODIRB    0x01     / 0: set ................. as output
    GPPUA     0x0C     \ 1: set corresponding pin internal pull-up on
    GPPUB     0x0D     / 0: set .......................... pull-up off
    GPIOA     0x12     \ read: returns the value on the port
    GPIOB     0x13     / write: modifies the OLAT register
    OLATA     0x14     \ read: returns the value of this register
    OLATB     0x15     / write: modifies the output latches that control the
                                pins configured as output

* IOCON register (see datasheet section 1.6, table 1-5, register 1-8)
    * BANK: bit 7; read/write; default = 0
        * 1: The registers associated with each port are separated into
          different banks
        * 0: The registers are in the same bank (addresses are sequential)
    * SEQOP: bit 5; read/write; default = 0
        * 1: Sequential operation disabled, address pointer does not increment
        * 0: Sequential operation enabled, address pointer increments

* notes:
    * All addresses given for IOCON.BANK = 0, since that's the default value of
      the bit, and that's what we'll be using.
    * Initially, we want either columns or rows (see <../options.h>) set as
      hi-Z without pull-ups, and the other set of pins set as input with
      pull-ups.  During the update function, we'll cycle through setting the
      first set low and checking each pin in the second set.

* abbreviations:
    * IODIR = I/O Direction Register
    * IOCON = I/O Control Register
    * GPPU = GPIO Pull-Up Resistor Register
    * GPIO = General Purpose I/O Port Register
    * OLAT = Output Latch Register

## I&sup2;C Device Protocol (see datasheet section 1.3, figure 1-1)

    S  : Start       OP   : Device opcode
    SR : Restart     ADDR : Device address
    P  : Stop        Dout : Data out from MCP23018
    W  : Write       Din  : Data in to MCP23018
    R  : Read


    S OP W ADDR ----> Din ... Din --> P
                 |
                 |--> SR OP R Dout ... Dout ---> P
                 |<--------------------------|
                 |
                 |--> SR OP W ADDR ... Din --> P
                 |
                 |--> P

    S OP R ----> Dout ... Dout --> P
            |
            |--> SR OP R Dout ... Dout ---> P
            |<--------------------------|
            |
            |--> SR OP W ADDR Din ... Din --> P
            |
            |--> P

    Byte and Sequential Write
    -------------------------
            Byte : S OP W ADDR --> Din --> P
      Sequential : S OP W ADDR --> Din ... Din --> P

    Byte and Sequential Read
    ------------------------
            Byte : S OP W ADDR --> SR OP R Dout --> P
      Sequential : S OP W ADDR --> SR OP R Dout ... Dout --> P

* notes:
    * We'll be using sequential mode (ICON.SEQOP = 0; default) (see datasheet
      section 1.3.1).

-------------------------------------------------------------------------------

Copyright &copy; 2012 Ben Blazak <benblazak.dev@gmail.com>  
Released under The MIT License (MIT) (see "license.md")  
Project located at <https://github.com/benblazak/ergodox-firmware>

