2012-03-19 08:01:41 +01:00
|
|
|
/* ----------------------------------------------------------------------------
|
|
|
|
* ergoDOX controller: MCP23018 specific code
|
|
|
|
* ----------------------------------------------------------------------------
|
2012-03-27 12:06:52 +02:00
|
|
|
* Copyright (c) 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>
|
2012-03-19 08:01:41 +01:00
|
|
|
* ------------------------------------------------------------------------- */
|
|
|
|
|
2012-03-27 12:06:52 +02:00
|
|
|
|
|
|
|
#include <util/twi.h>
|
|
|
|
|
2012-04-22 21:08:32 +02:00
|
|
|
#include "lib/_data-types.h"
|
|
|
|
#include "lib/_teensy-2-0/twi.h" // `TWI_FREQ` defined in "teensy-2-0.c"
|
2012-04-02 10:59:00 +02:00
|
|
|
|
2012-04-10 10:44:27 +02:00
|
|
|
#define KEYBOARD_INCLUDE_PRIVATE
|
2012-04-02 10:59:00 +02:00
|
|
|
#include "matrix.h"
|
2012-03-27 12:06:52 +02:00
|
|
|
#include "mcp23018.h"
|
2012-03-19 08:01:41 +01:00
|
|
|
|
|
|
|
|
|
|
|
// register addresses (see "mcp23018.md")
|
|
|
|
#define IODIRA 0x00 // i/o direction register
|
|
|
|
#define IODIRB 0x01
|
|
|
|
#define GPPUA 0x0C // GPIO pull-up resistor register
|
|
|
|
#define GPPUB 0x0D
|
2012-04-10 10:44:27 +02:00
|
|
|
#define GPIOA 0x12 // general purpose i/o port register (write modifies OLAT)
|
2012-03-19 08:01:41 +01:00
|
|
|
#define GPIOB 0x13
|
|
|
|
#define OLATA 0x14 // output latch register
|
|
|
|
#define OLATB 0x15
|
|
|
|
|
2012-04-02 10:59:00 +02:00
|
|
|
// TWI aliases
|
|
|
|
#define TWI_ADDR_WRITE ( (MCP23018_TWI_ADDRESS<<1) | TW_WRITE )
|
|
|
|
#define TWI_ADDR_READ ( (MCP23018_TWI_ADDRESS<<1) | TW_READ )
|
2012-04-01 02:02:55 +02:00
|
|
|
|
|
|
|
|
2012-04-10 10:44:27 +02:00
|
|
|
/* returns:
|
2012-04-02 10:59:00 +02:00
|
|
|
* - success: 0
|
|
|
|
* - failure: twi status code
|
2012-04-10 10:44:27 +02:00
|
|
|
*
|
|
|
|
* notes:
|
2012-04-11 03:58:26 +02:00
|
|
|
* - `twi_stop()` must be called *exactly once* for each twi block, the way
|
|
|
|
* things are currently set up. this may change in the future.
|
2012-04-02 10:59:00 +02:00
|
|
|
*/
|
2012-04-11 03:58:26 +02:00
|
|
|
uint8_t mcp23018_init(void) {
|
|
|
|
uint8_t ret;
|
2012-04-01 02:02:55 +02:00
|
|
|
|
2012-04-02 10:59:00 +02:00
|
|
|
// set pin direction
|
|
|
|
// - unused : input : 1
|
|
|
|
// - rows : output : 0
|
|
|
|
// - columns : input : 1
|
|
|
|
twi_start();
|
2012-04-11 03:58:26 +02:00
|
|
|
ret = twi_send(TWI_ADDR_WRITE);
|
|
|
|
if (ret) goto out; // make sure we got an ACK
|
2012-04-02 10:59:00 +02:00
|
|
|
twi_send(IODIRA);
|
|
|
|
twi_send(0b11000000); // IODIRA
|
|
|
|
twi_send(0b11111111); // IODIRB
|
2012-04-11 03:58:26 +02:00
|
|
|
twi_stop();
|
2012-03-19 08:01:41 +01:00
|
|
|
|
2012-04-02 10:59:00 +02:00
|
|
|
// set pull-up
|
2012-04-05 12:08:20 +02:00
|
|
|
// - unused : on : 1
|
|
|
|
// - rows : off : 0
|
|
|
|
// - columns : on : 1
|
2012-04-02 10:59:00 +02:00
|
|
|
twi_start();
|
2012-04-24 21:17:06 +02:00
|
|
|
ret = twi_send(TWI_ADDR_WRITE);
|
|
|
|
if (ret) goto out; // make sure we got an ACK
|
2012-04-02 10:59:00 +02:00
|
|
|
twi_send(GPPUA);
|
2012-04-05 12:08:20 +02:00
|
|
|
twi_send(0b11000000); // GPPUA
|
2012-04-02 10:59:00 +02:00
|
|
|
twi_send(0b11111111); // GPPUB
|
2012-04-11 03:58:26 +02:00
|
|
|
twi_stop();
|
2012-03-19 08:01:41 +01:00
|
|
|
|
2012-04-05 12:08:20 +02:00
|
|
|
// set logical value (doesn't matter on inputs)
|
|
|
|
// - unused : high (hi-Z) : 1
|
|
|
|
// - rows : high (hi-Z) : 1
|
|
|
|
// - columns : high (hi-Z) : 1
|
2012-04-02 10:59:00 +02:00
|
|
|
twi_start();
|
2012-04-24 21:17:06 +02:00
|
|
|
ret = twi_send(TWI_ADDR_WRITE);
|
|
|
|
if (ret) goto out; // make sure we got an ACK
|
2012-04-10 10:44:27 +02:00
|
|
|
twi_send(OLATA);
|
|
|
|
twi_send(0b11111111); //OLATA
|
|
|
|
twi_send(0b11111111); //OLATB
|
2012-04-05 12:08:20 +02:00
|
|
|
|
2012-04-10 10:44:27 +02:00
|
|
|
out:
|
2012-04-11 03:58:26 +02:00
|
|
|
twi_stop();
|
2012-04-10 10:44:27 +02:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2012-04-05 12:08:20 +02:00
|
|
|
/* returns:
|
2012-04-02 10:59:00 +02:00
|
|
|
* - success: 0
|
|
|
|
* - failure: twi status code
|
|
|
|
*/
|
2012-04-05 12:08:20 +02:00
|
|
|
#if KB_ROWS != 12 || KB_COLUMNS != 7
|
|
|
|
#error "Expecting different keyboard dimensions"
|
|
|
|
#endif
|
2012-04-10 10:44:27 +02:00
|
|
|
uint8_t mcp23018_update_matrix(bool matrix[KB_ROWS][KB_COLUMNS]) {
|
2012-04-02 10:59:00 +02:00
|
|
|
uint8_t ret, data;
|
|
|
|
|
2012-04-11 03:58:26 +02:00
|
|
|
// initialize things, just to make sure
|
|
|
|
// - it's not appreciably faster to skip this, and it takes care of the
|
|
|
|
// case when the i/o expander isn't plugged in during the first
|
|
|
|
// init()
|
|
|
|
ret = mcp23018_init();
|
2012-04-10 10:44:27 +02:00
|
|
|
|
|
|
|
// if there was an error
|
2012-04-02 10:59:00 +02:00
|
|
|
if (ret) {
|
2012-04-12 06:05:45 +02:00
|
|
|
// clear our part of the matrix
|
2012-04-10 10:44:27 +02:00
|
|
|
for (uint8_t row=0x6; row<=0xB; row++)
|
|
|
|
for (uint8_t col=0; col<=6; col++)
|
|
|
|
matrix[row][col] = 0;
|
|
|
|
|
2012-04-02 10:59:00 +02:00
|
|
|
return ret;
|
|
|
|
}
|
2012-04-01 02:02:55 +02:00
|
|
|
|
2012-04-10 10:44:27 +02:00
|
|
|
// update our part of the matrix
|
2012-04-02 10:59:00 +02:00
|
|
|
for (uint8_t row=0x6; row<=0xB; row++) {
|
2012-04-10 10:44:27 +02:00
|
|
|
// set active row low : 0
|
|
|
|
// set other rows high (hi-Z) : 1
|
2012-04-02 10:59:00 +02:00
|
|
|
twi_start();
|
|
|
|
twi_send(TWI_ADDR_WRITE);
|
2012-04-10 10:44:27 +02:00
|
|
|
twi_send(OLATA);
|
2012-04-11 03:58:26 +02:00
|
|
|
twi_send( 0b11111111 & ~(1<<(row-6)) );
|
|
|
|
twi_stop();
|
2012-04-02 10:59:00 +02:00
|
|
|
|
2012-04-11 03:58:26 +02:00
|
|
|
// read column data
|
2012-04-02 10:59:00 +02:00
|
|
|
twi_start();
|
2012-04-10 10:44:27 +02:00
|
|
|
twi_send(TWI_ADDR_WRITE);
|
|
|
|
twi_send(GPIOB);
|
2012-04-11 03:58:26 +02:00
|
|
|
twi_start();
|
2012-04-02 10:59:00 +02:00
|
|
|
twi_send(TWI_ADDR_READ);
|
2012-04-11 03:58:26 +02:00
|
|
|
twi_read(&data);
|
|
|
|
twi_stop();
|
2012-04-02 10:59:00 +02:00
|
|
|
|
|
|
|
// update matrix
|
|
|
|
for (uint8_t col=0; col<=6; col++)
|
|
|
|
matrix[row][col] = !( data & (1<<col) );
|
|
|
|
}
|
2012-04-01 02:02:55 +02:00
|
|
|
|
2012-04-10 10:44:27 +02:00
|
|
|
// set all rows high (hi-Z) : 1
|
2012-04-06 09:19:57 +02:00
|
|
|
twi_start();
|
|
|
|
twi_send(TWI_ADDR_WRITE);
|
|
|
|
twi_send(GPIOA);
|
|
|
|
twi_send(0b11111111);
|
2012-04-02 10:59:00 +02:00
|
|
|
twi_stop();
|
2012-04-11 03:58:26 +02:00
|
|
|
|
|
|
|
return ret; // success
|
2012-03-27 12:06:52 +02:00
|
|
|
}
|
2012-04-02 10:59:00 +02:00
|
|
|
|