refactor
parent
8344f05b60
commit
14d0d1cad6
|
@ -35,3 +35,406 @@ uint8_t kb_update_matrix(bool matrix[KB_ROWS][KB_COLUMNS]) {
|
|||
|
||||
return 0; // success
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// check options
|
||||
#if (MCP23018__DRIVE_ROWS && MCP23018__DRIVE_COLUMNS) \
|
||||
|| !(MCP23018__DRIVE_ROWS || MCP23018__DRIVE_COLUMNS)
|
||||
#error "See 'Pin drive direction' in 'options.h'"
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// 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
|
||||
#define GPIOA 0x12 // general purpose i/o port register (write modifies OLAT)
|
||||
#define GPIOB 0x13
|
||||
#define OLATA 0x14 // output latch register
|
||||
#define OLATB 0x15
|
||||
|
||||
// TWI aliases
|
||||
#define TWI_ADDR_WRITE ( (MCP23018_TWI_ADDRESS<<1) | TW_WRITE )
|
||||
#define TWI_ADDR_READ ( (MCP23018_TWI_ADDRESS<<1) | TW_READ )
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/* returns:
|
||||
* - success: 0
|
||||
* - failure: twi status code
|
||||
*
|
||||
* notes:
|
||||
* - `twi_stop()` must be called *exactly once* for each twi block, the way
|
||||
* things are currently set up. this may change in the future.
|
||||
*/
|
||||
uint8_t mcp23018_init(void) {
|
||||
uint8_t ret;
|
||||
|
||||
// set pin direction
|
||||
// - unused : input : 1
|
||||
// - input : input : 1
|
||||
// - driving : output : 0
|
||||
twi_start();
|
||||
ret = twi_send(TWI_ADDR_WRITE);
|
||||
if (ret) goto out; // make sure we got an ACK
|
||||
twi_send(IODIRA);
|
||||
#if MCP23018__DRIVE_ROWS
|
||||
twi_send(0b11111111); // IODIRA
|
||||
twi_send(0b11000000); // IODIRB
|
||||
#elif MCP23018__DRIVE_COLUMNS
|
||||
twi_send(0b10000000); // IODIRA
|
||||
twi_send(0b11111111); // IODIRB
|
||||
#endif
|
||||
twi_stop();
|
||||
|
||||
// set pull-up
|
||||
// - unused : on : 1
|
||||
// - input : on : 1
|
||||
// - driving : off : 0
|
||||
twi_start();
|
||||
ret = twi_send(TWI_ADDR_WRITE);
|
||||
if (ret) goto out; // make sure we got an ACK
|
||||
twi_send(GPPUA);
|
||||
#if MCP23018__DRIVE_ROWS
|
||||
twi_send(0b11111111); // GPPUA
|
||||
twi_send(0b11000000); // GPPUB
|
||||
#elif MCP23018__DRIVE_COLUMNS
|
||||
twi_send(0b10000000); // GPPUA
|
||||
twi_send(0b11111111); // GPPUB
|
||||
#endif
|
||||
twi_stop();
|
||||
|
||||
// set logical value (doesn't matter on inputs)
|
||||
// - unused : hi-Z : 1
|
||||
// - input : hi-Z : 1
|
||||
// - driving : hi-Z : 1
|
||||
twi_start();
|
||||
ret = twi_send(TWI_ADDR_WRITE);
|
||||
if (ret) goto out; // make sure we got an ACK
|
||||
twi_send(OLATA);
|
||||
twi_send(0b11111111); //OLATA
|
||||
twi_send(0b11111111); //OLATB
|
||||
|
||||
out:
|
||||
twi_stop();
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* returns:
|
||||
* - success: 0
|
||||
* - failure: twi status code
|
||||
*/
|
||||
#if KB_ROWS != 6 || KB_COLUMNS != 14
|
||||
#error "Expecting different keyboard dimensions"
|
||||
#endif
|
||||
|
||||
uint8_t mcp23018_update_matrix(bool matrix[KB_ROWS][KB_COLUMNS]) {
|
||||
uint8_t ret, data;
|
||||
|
||||
// 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();
|
||||
|
||||
// if there was an error
|
||||
if (ret) {
|
||||
// clear our part of the matrix
|
||||
for (uint8_t row=0; row<=5; row++)
|
||||
for (uint8_t col=0; col<=6; col++)
|
||||
matrix[row][col] = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// update our part of the matrix
|
||||
|
||||
#if MCP23018__DRIVE_ROWS
|
||||
for (uint8_t row=0; row<=5; row++) {
|
||||
// set active row low : 0
|
||||
// set other rows hi-Z : 1
|
||||
twi_start();
|
||||
twi_send(TWI_ADDR_WRITE);
|
||||
twi_send(GPIOB);
|
||||
twi_send( 0xFF & ~(1<<(5-row)) );
|
||||
twi_stop();
|
||||
|
||||
// read column data
|
||||
twi_start();
|
||||
twi_send(TWI_ADDR_WRITE);
|
||||
twi_send(GPIOA);
|
||||
twi_start();
|
||||
twi_send(TWI_ADDR_READ);
|
||||
twi_read(&data);
|
||||
twi_stop();
|
||||
|
||||
// update matrix
|
||||
for (uint8_t col=0; col<=6; col++) {
|
||||
matrix[row][col] = !( data & (1<<col) );
|
||||
}
|
||||
}
|
||||
|
||||
// set all rows hi-Z : 1
|
||||
twi_start();
|
||||
twi_send(TWI_ADDR_WRITE);
|
||||
twi_send(GPIOB);
|
||||
twi_send(0xFF);
|
||||
twi_stop();
|
||||
|
||||
#elif MCP23018__DRIVE_COLUMNS
|
||||
for (uint8_t col=0; col<=6; col++) {
|
||||
// set active column low : 0
|
||||
// set other columns hi-Z : 1
|
||||
twi_start();
|
||||
twi_send(TWI_ADDR_WRITE);
|
||||
twi_send(GPIOA);
|
||||
twi_send( 0xFF & ~(1<<col) );
|
||||
twi_stop();
|
||||
|
||||
// read row data
|
||||
twi_start();
|
||||
twi_send(TWI_ADDR_WRITE);
|
||||
twi_send(GPIOB);
|
||||
twi_start();
|
||||
twi_send(TWI_ADDR_READ);
|
||||
twi_read(&data);
|
||||
twi_stop();
|
||||
|
||||
// update matrix
|
||||
for (uint8_t row=0; row<=5; row++) {
|
||||
matrix[row][col] = !( data & (1<<(5-row)) );
|
||||
}
|
||||
}
|
||||
|
||||
// set all columns hi-Z : 1
|
||||
twi_start();
|
||||
twi_send(TWI_ADDR_WRITE);
|
||||
twi_send(GPIOA);
|
||||
twi_send(0xFF);
|
||||
twi_stop();
|
||||
|
||||
#endif
|
||||
|
||||
// /update our part of the matrix
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
return ret; // success
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// check options
|
||||
#if (TEENSY__DRIVE_ROWS && TEENSY__DRIVE_COLUMNS) \
|
||||
|| !(TEENSY__DRIVE_ROWS || TEENSY__DRIVE_COLUMNS)
|
||||
#error "See 'Pin drive direction' in 'options.h'"
|
||||
#endif
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// processor frequency (from <http://www.pjrc.com/teensy/prescaler.html>)
|
||||
#define CPU_PRESCALE(n) (CLKPR = 0x80, CLKPR = (n))
|
||||
#define CPU_16MHz 0x00
|
||||
#define CPU_8MHz 0x01
|
||||
#define CPU_4MHz 0x02
|
||||
#define CPU_2MHz 0x03
|
||||
#define CPU_1MHz 0x04
|
||||
#define CPU_500kHz 0x05
|
||||
#define CPU_250kHz 0x06
|
||||
#define CPU_125kHz 0x07
|
||||
#define CPU_62kHz 0x08
|
||||
|
||||
|
||||
/*
|
||||
* pin macros
|
||||
* - note: you can move the `UNUSED`, `ROW`, and `COLUMN` pins around, but be
|
||||
* sure to keep the set of all the pins listed constant. other pins are not
|
||||
* movable, and either are referenced explicitly or have macros defined for
|
||||
* them elsewhere.
|
||||
* - note: if you change pin assignments, please be sure to update
|
||||
* "teensy-2-0.md", and the '.svg' circuit diagram.
|
||||
*/
|
||||
|
||||
// --- unused
|
||||
#define UNUSED_0 C, 7
|
||||
#define UNUSED_1 D, 7
|
||||
#define UNUSED_2 D, 4 // hard to use with breadboard (on the end)
|
||||
#define UNUSED_3 D, 5 // hard to use with breadboard (on the end)
|
||||
#define UNUSED_4 E, 6 // hard to use with breadboard (internal)
|
||||
|
||||
// --- rows
|
||||
#define ROW_0 F, 7
|
||||
#define ROW_1 F, 6
|
||||
#define ROW_2 F, 5
|
||||
#define ROW_3 F, 4
|
||||
#define ROW_4 F, 1
|
||||
#define ROW_5 F, 0
|
||||
|
||||
// --- columns
|
||||
#define COLUMN_7 B, 0
|
||||
#define COLUMN_8 B, 1
|
||||
#define COLUMN_9 B, 2
|
||||
#define COLUMN_A B, 3
|
||||
#define COLUMN_B D, 2
|
||||
#define COLUMN_C D, 3
|
||||
#define COLUMN_D C, 6
|
||||
|
||||
// --- helpers
|
||||
#define SET |=
|
||||
#define CLEAR &=~
|
||||
|
||||
#define _teensypin_write(register, operation, pin_letter, pin_number) \
|
||||
do { \
|
||||
((register##pin_letter) operation (1<<(pin_number))); \
|
||||
_delay_us(1); /* allow pins time to stabilize */ \
|
||||
} while(0)
|
||||
#define teensypin_write(register, operation, pin) \
|
||||
_teensypin_write(register, operation, pin)
|
||||
|
||||
#define _teensypin_read(pin_letter, pin_number) \
|
||||
((PIN##pin_letter) & (1<<(pin_number)))
|
||||
#define teensypin_read(pin) \
|
||||
_teensypin_read(pin)
|
||||
|
||||
#define teensypin_write_all_unused(register, operation) \
|
||||
do { \
|
||||
teensypin_write(register, operation, UNUSED_0); \
|
||||
teensypin_write(register, operation, UNUSED_1); \
|
||||
teensypin_write(register, operation, UNUSED_2); \
|
||||
teensypin_write(register, operation, UNUSED_3); \
|
||||
teensypin_write(register, operation, UNUSED_4); } \
|
||||
while(0)
|
||||
|
||||
#define teensypin_write_all_row(register, operation) \
|
||||
do { \
|
||||
teensypin_write(register, operation, ROW_0); \
|
||||
teensypin_write(register, operation, ROW_1); \
|
||||
teensypin_write(register, operation, ROW_2); \
|
||||
teensypin_write(register, operation, ROW_3); \
|
||||
teensypin_write(register, operation, ROW_4); \
|
||||
teensypin_write(register, operation, ROW_5); } \
|
||||
while(0)
|
||||
|
||||
#define teensypin_write_all_column(register, operation) \
|
||||
do { \
|
||||
teensypin_write(register, operation, COLUMN_7); \
|
||||
teensypin_write(register, operation, COLUMN_8); \
|
||||
teensypin_write(register, operation, COLUMN_9); \
|
||||
teensypin_write(register, operation, COLUMN_A); \
|
||||
teensypin_write(register, operation, COLUMN_B); \
|
||||
teensypin_write(register, operation, COLUMN_C); \
|
||||
teensypin_write(register, operation, COLUMN_D); } \
|
||||
while(0)
|
||||
|
||||
|
||||
/*
|
||||
* update macros
|
||||
*/
|
||||
#define update_rows_for_column(matrix, column) \
|
||||
do { \
|
||||
/* set column low (set as output) */ \
|
||||
teensypin_write(DDR, SET, COLUMN_##column); \
|
||||
/* read rows 0..5 and update matrix */ \
|
||||
matrix[0x0][0x##column] = ! teensypin_read(ROW_0); \
|
||||
matrix[0x1][0x##column] = ! teensypin_read(ROW_1); \
|
||||
matrix[0x2][0x##column] = ! teensypin_read(ROW_2); \
|
||||
matrix[0x3][0x##column] = ! teensypin_read(ROW_3); \
|
||||
matrix[0x4][0x##column] = ! teensypin_read(ROW_4); \
|
||||
matrix[0x5][0x##column] = ! teensypin_read(ROW_5); \
|
||||
/* set column hi-Z (set as input) */ \
|
||||
teensypin_write(DDR, CLEAR, COLUMN_##column); \
|
||||
} while(0)
|
||||
|
||||
#define update_columns_for_row(matrix, row) \
|
||||
do { \
|
||||
/* set row low (set as output) */ \
|
||||
teensypin_write(DDR, SET, ROW_##row); \
|
||||
/* read columns 7..D and update matrix */ \
|
||||
matrix[0x##row][0x7] = ! teensypin_read(COLUMN_7); \
|
||||
matrix[0x##row][0x8] = ! teensypin_read(COLUMN_8); \
|
||||
matrix[0x##row][0x9] = ! teensypin_read(COLUMN_9); \
|
||||
matrix[0x##row][0xA] = ! teensypin_read(COLUMN_A); \
|
||||
matrix[0x##row][0xB] = ! teensypin_read(COLUMN_B); \
|
||||
matrix[0x##row][0xC] = ! teensypin_read(COLUMN_C); \
|
||||
matrix[0x##row][0xD] = ! teensypin_read(COLUMN_D); \
|
||||
/* set row hi-Z (set as input) */ \
|
||||
teensypin_write(DDR, CLEAR, ROW_##row); \
|
||||
} while(0)
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/* returns
|
||||
* - success: 0
|
||||
*/
|
||||
uint8_t teensy_init(void) {
|
||||
// CPU speed : should match F_CPU in makefile
|
||||
#if F_CPU != 16000000
|
||||
#error "Expecting different CPU frequency"
|
||||
#endif
|
||||
CPU_PRESCALE(CPU_16MHz);
|
||||
|
||||
// onboard LED
|
||||
// (tied to GND for hardware convenience)
|
||||
DDRD &= ~(1<<6); // set D(6) as input
|
||||
PORTD &= ~(1<<6); // set D(6) internal pull-up disabled
|
||||
|
||||
// (tied to Vcc for hardware convenience)
|
||||
DDRB &= ~(1<<4); // set B(4) as input
|
||||
PORTB &= ~(1<<4); // set B(4) internal pull-up disabled
|
||||
|
||||
// keyboard LEDs (see "PWM on ports OC1(A|B|C)" in "teensy-2-0.md")
|
||||
_kb_led_all_off(); // (just to put the pins in a known state)
|
||||
TCCR1A = 0b10101001; // set and configure fast PWM
|
||||
TCCR1B = 0b00001001; // set and configure fast PWM
|
||||
|
||||
// I2C (TWI)
|
||||
twi_init(); // on pins D(1,0)
|
||||
|
||||
// unused pins
|
||||
teensypin_write_all_unused(DDR, CLEAR); // set as input
|
||||
teensypin_write_all_unused(PORT, SET); // set internal pull-up enabled
|
||||
|
||||
// rows and columns
|
||||
teensypin_write_all_row(DDR, CLEAR); // set as input (hi-Z)
|
||||
teensypin_write_all_column(DDR, CLEAR); // set as input (hi-Z)
|
||||
#if TEENSY__DRIVE_ROWS
|
||||
teensypin_write_all_row(PORT, CLEAR); // pull-up disabled
|
||||
teensypin_write_all_column(PORT, SET); // pull-up enabled
|
||||
#elif TEENSY__DRIVE_COLUMNS
|
||||
teensypin_write_all_row(PORT, SET); // pull-up enabled
|
||||
teensypin_write_all_column(PORT, CLEAR); // pull-up disabled
|
||||
#endif
|
||||
|
||||
return 0; // success
|
||||
}
|
||||
|
||||
/* returns
|
||||
* - success: 0
|
||||
*/
|
||||
#if KB_ROWS != 6 || KB_COLUMNS != 14
|
||||
#error "Expecting different keyboard dimensions"
|
||||
#endif
|
||||
|
||||
uint8_t teensy_update_matrix(bool matrix[KB_ROWS][KB_COLUMNS]) {
|
||||
#if TEENSY__DRIVE_ROWS
|
||||
update_columns_for_row(matrix, 0);
|
||||
update_columns_for_row(matrix, 1);
|
||||
update_columns_for_row(matrix, 2);
|
||||
update_columns_for_row(matrix, 3);
|
||||
update_columns_for_row(matrix, 4);
|
||||
update_columns_for_row(matrix, 5);
|
||||
#elif TEENSY__DRIVE_COLUMNS
|
||||
update_rows_for_column(matrix, 7);
|
||||
update_rows_for_column(matrix, 8);
|
||||
update_rows_for_column(matrix, 9);
|
||||
update_rows_for_column(matrix, A);
|
||||
update_rows_for_column(matrix, B);
|
||||
update_rows_for_column(matrix, C);
|
||||
update_rows_for_column(matrix, D);
|
||||
#endif
|
||||
|
||||
return 0; // success
|
||||
}
|
||||
|
|
|
@ -8,12 +8,73 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
// for "lib/twi.h"
|
||||
#define TWI_FREQ 400000
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "./controller/mcp23018.h"
|
||||
#include "./controller/teensy-2-0.h"
|
||||
#include <util/twi.h>
|
||||
#include "../lib/teensy-2-0.h"
|
||||
#include "./options.h"
|
||||
#include "./matrix.h"
|
||||
#include <avr/io.h>
|
||||
#include <util/delay.h>
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
uint8_t kb_init(void);
|
||||
uint8_t kb_update_matrix(bool matrix[KB_ROWS][KB_COLUMNS]);
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#define MCP23018_TWI_ADDRESS 0b0100000
|
||||
|
||||
uint8_t mcp23018_init(void);
|
||||
uint8_t mcp23018_update_matrix( bool matrix[KB_ROWS][KB_COLUMNS] );
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
uint8_t teensy_init(void);
|
||||
uint8_t teensy_update_matrix( bool matrix[KB_ROWS][KB_COLUMNS] );
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#define _kb_led_1_on() (DDRB |= (1<<5))
|
||||
#define _kb_led_1_off() (DDRB &= ~(1<<5))
|
||||
#define _kb_led_1_set(n) (OCR1A = (uint8_t)(n))
|
||||
#define _kb_led_1_set_percent(n) (OCR1A = (uint8_t)((n) * 0xFF))
|
||||
|
||||
#define _kb_led_2_on() (DDRB |= (1<<6))
|
||||
#define _kb_led_2_off() (DDRB &= ~(1<<6))
|
||||
#define _kb_led_2_set(n) (OCR1B = (uint8_t)(n))
|
||||
#define _kb_led_2_set_percent(n) (OCR1B = (uint8_t)((n) * 0xFF))
|
||||
|
||||
#define _kb_led_3_on() (DDRB |= (1<<7))
|
||||
#define _kb_led_3_off() (DDRB &= ~(1<<7))
|
||||
#define _kb_led_3_set(n) (OCR1C = (uint8_t)(n))
|
||||
#define _kb_led_3_set_percent(n) (OCR1C = (uint8_t)((n) * 0xFF))
|
||||
|
||||
|
||||
#define _kb_led_all_on() do { \
|
||||
_kb_led_1_on(); \
|
||||
_kb_led_2_on(); \
|
||||
_kb_led_3_on(); \
|
||||
} while(0)
|
||||
|
||||
#define _kb_led_all_off() do { \
|
||||
_kb_led_1_off(); \
|
||||
_kb_led_2_off(); \
|
||||
_kb_led_3_off(); \
|
||||
} while(0)
|
||||
|
||||
#define _kb_led_all_set(n) do { \
|
||||
_kb_led_1_set(n); \
|
||||
_kb_led_2_set(n); \
|
||||
_kb_led_3_set(n); \
|
||||
} while(0)
|
||||
|
||||
#define _kb_led_all_set_percent(n) do { \
|
||||
_kb_led_1_set_percent(n); \
|
||||
_kb_led_2_set_percent(n); \
|
||||
_kb_led_3_set_percent(n); \
|
||||
} while(0)
|
||||
|
|
|
@ -1,199 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* ergoDOX : controller: MCP23018 specific code
|
||||
* ----------------------------------------------------------------------------
|
||||
* 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>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "./mcp23018.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// check options
|
||||
#if (MCP23018__DRIVE_ROWS && MCP23018__DRIVE_COLUMNS) \
|
||||
|| !(MCP23018__DRIVE_ROWS || MCP23018__DRIVE_COLUMNS)
|
||||
#error "See 'Pin drive direction' in 'options.h'"
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// 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
|
||||
#define GPIOA 0x12 // general purpose i/o port register (write modifies OLAT)
|
||||
#define GPIOB 0x13
|
||||
#define OLATA 0x14 // output latch register
|
||||
#define OLATB 0x15
|
||||
|
||||
// TWI aliases
|
||||
#define TWI_ADDR_WRITE ( (MCP23018_TWI_ADDRESS<<1) | TW_WRITE )
|
||||
#define TWI_ADDR_READ ( (MCP23018_TWI_ADDRESS<<1) | TW_READ )
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/* returns:
|
||||
* - success: 0
|
||||
* - failure: twi status code
|
||||
*
|
||||
* notes:
|
||||
* - `twi_stop()` must be called *exactly once* for each twi block, the way
|
||||
* things are currently set up. this may change in the future.
|
||||
*/
|
||||
uint8_t mcp23018_init(void) {
|
||||
uint8_t ret;
|
||||
|
||||
// set pin direction
|
||||
// - unused : input : 1
|
||||
// - input : input : 1
|
||||
// - driving : output : 0
|
||||
twi_start();
|
||||
ret = twi_send(TWI_ADDR_WRITE);
|
||||
if (ret) goto out; // make sure we got an ACK
|
||||
twi_send(IODIRA);
|
||||
#if MCP23018__DRIVE_ROWS
|
||||
twi_send(0b11111111); // IODIRA
|
||||
twi_send(0b11000000); // IODIRB
|
||||
#elif MCP23018__DRIVE_COLUMNS
|
||||
twi_send(0b10000000); // IODIRA
|
||||
twi_send(0b11111111); // IODIRB
|
||||
#endif
|
||||
twi_stop();
|
||||
|
||||
// set pull-up
|
||||
// - unused : on : 1
|
||||
// - input : on : 1
|
||||
// - driving : off : 0
|
||||
twi_start();
|
||||
ret = twi_send(TWI_ADDR_WRITE);
|
||||
if (ret) goto out; // make sure we got an ACK
|
||||
twi_send(GPPUA);
|
||||
#if MCP23018__DRIVE_ROWS
|
||||
twi_send(0b11111111); // GPPUA
|
||||
twi_send(0b11000000); // GPPUB
|
||||
#elif MCP23018__DRIVE_COLUMNS
|
||||
twi_send(0b10000000); // GPPUA
|
||||
twi_send(0b11111111); // GPPUB
|
||||
#endif
|
||||
twi_stop();
|
||||
|
||||
// set logical value (doesn't matter on inputs)
|
||||
// - unused : hi-Z : 1
|
||||
// - input : hi-Z : 1
|
||||
// - driving : hi-Z : 1
|
||||
twi_start();
|
||||
ret = twi_send(TWI_ADDR_WRITE);
|
||||
if (ret) goto out; // make sure we got an ACK
|
||||
twi_send(OLATA);
|
||||
twi_send(0b11111111); //OLATA
|
||||
twi_send(0b11111111); //OLATB
|
||||
|
||||
out:
|
||||
twi_stop();
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* returns:
|
||||
* - success: 0
|
||||
* - failure: twi status code
|
||||
*/
|
||||
#if KB_ROWS != 6 || KB_COLUMNS != 14
|
||||
#error "Expecting different keyboard dimensions"
|
||||
#endif
|
||||
uint8_t mcp23018_update_matrix(bool matrix[KB_ROWS][KB_COLUMNS]) {
|
||||
uint8_t ret, data;
|
||||
|
||||
// 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();
|
||||
|
||||
// if there was an error
|
||||
if (ret) {
|
||||
// clear our part of the matrix
|
||||
for (uint8_t row=0; row<=5; row++)
|
||||
for (uint8_t col=0; col<=6; col++)
|
||||
matrix[row][col] = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// update our part of the matrix
|
||||
|
||||
#if MCP23018__DRIVE_ROWS
|
||||
for (uint8_t row=0; row<=5; row++) {
|
||||
// set active row low : 0
|
||||
// set other rows hi-Z : 1
|
||||
twi_start();
|
||||
twi_send(TWI_ADDR_WRITE);
|
||||
twi_send(GPIOB);
|
||||
twi_send( 0xFF & ~(1<<(5-row)) );
|
||||
twi_stop();
|
||||
|
||||
// read column data
|
||||
twi_start();
|
||||
twi_send(TWI_ADDR_WRITE);
|
||||
twi_send(GPIOA);
|
||||
twi_start();
|
||||
twi_send(TWI_ADDR_READ);
|
||||
twi_read(&data);
|
||||
twi_stop();
|
||||
|
||||
// update matrix
|
||||
for (uint8_t col=0; col<=6; col++) {
|
||||
matrix[row][col] = !( data & (1<<col) );
|
||||
}
|
||||
}
|
||||
|
||||
// set all rows hi-Z : 1
|
||||
twi_start();
|
||||
twi_send(TWI_ADDR_WRITE);
|
||||
twi_send(GPIOB);
|
||||
twi_send(0xFF);
|
||||
twi_stop();
|
||||
|
||||
#elif MCP23018__DRIVE_COLUMNS
|
||||
for (uint8_t col=0; col<=6; col++) {
|
||||
// set active column low : 0
|
||||
// set other columns hi-Z : 1
|
||||
twi_start();
|
||||
twi_send(TWI_ADDR_WRITE);
|
||||
twi_send(GPIOA);
|
||||
twi_send( 0xFF & ~(1<<col) );
|
||||
twi_stop();
|
||||
|
||||
// read row data
|
||||
twi_start();
|
||||
twi_send(TWI_ADDR_WRITE);
|
||||
twi_send(GPIOB);
|
||||
twi_start();
|
||||
twi_send(TWI_ADDR_READ);
|
||||
twi_read(&data);
|
||||
twi_stop();
|
||||
|
||||
// update matrix
|
||||
for (uint8_t row=0; row<=5; row++) {
|
||||
matrix[row][col] = !( data & (1<<(5-row)) );
|
||||
}
|
||||
}
|
||||
|
||||
// set all columns hi-Z : 1
|
||||
twi_start();
|
||||
twi_send(TWI_ADDR_WRITE);
|
||||
twi_send(GPIOA);
|
||||
twi_send(0xFF);
|
||||
twi_stop();
|
||||
|
||||
#endif
|
||||
|
||||
// /update our part of the matrix
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
return ret; // success
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* ergoDOX : controller : MCP23018 specific exports : functions
|
||||
* ----------------------------------------------------------------------------
|
||||
* 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>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <util/twi.h>
|
||||
#include "../../lib/teensy-2-0.h" // `TWI_FREQ` defined in "teensy-2-0.c"
|
||||
#include "../options.h"
|
||||
#include "../matrix.h"
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#define MCP23018_TWI_ADDRESS 0b0100000
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
uint8_t mcp23018_init(void);
|
||||
uint8_t mcp23018_update_matrix( bool matrix[KB_ROWS][KB_COLUMNS] );
|
|
@ -1,54 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* ergoDOX : controller : Teensy 2.0 specific exports : LED control
|
||||
* ----------------------------------------------------------------------------
|
||||
* 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>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <avr/io.h> // for the register macros
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#define _kb_led_1_on() (DDRB |= (1<<5))
|
||||
#define _kb_led_1_off() (DDRB &= ~(1<<5))
|
||||
#define _kb_led_1_set(n) (OCR1A = (uint8_t)(n))
|
||||
#define _kb_led_1_set_percent(n) (OCR1A = (uint8_t)((n) * 0xFF))
|
||||
|
||||
#define _kb_led_2_on() (DDRB |= (1<<6))
|
||||
#define _kb_led_2_off() (DDRB &= ~(1<<6))
|
||||
#define _kb_led_2_set(n) (OCR1B = (uint8_t)(n))
|
||||
#define _kb_led_2_set_percent(n) (OCR1B = (uint8_t)((n) * 0xFF))
|
||||
|
||||
#define _kb_led_3_on() (DDRB |= (1<<7))
|
||||
#define _kb_led_3_off() (DDRB &= ~(1<<7))
|
||||
#define _kb_led_3_set(n) (OCR1C = (uint8_t)(n))
|
||||
#define _kb_led_3_set_percent(n) (OCR1C = (uint8_t)((n) * 0xFF))
|
||||
|
||||
|
||||
#define _kb_led_all_on() do { \
|
||||
_kb_led_1_on(); \
|
||||
_kb_led_2_on(); \
|
||||
_kb_led_3_on(); \
|
||||
} while(0)
|
||||
|
||||
#define _kb_led_all_off() do { \
|
||||
_kb_led_1_off(); \
|
||||
_kb_led_2_off(); \
|
||||
_kb_led_3_off(); \
|
||||
} while(0)
|
||||
|
||||
#define _kb_led_all_set(n) do { \
|
||||
_kb_led_1_set(n); \
|
||||
_kb_led_2_set(n); \
|
||||
_kb_led_3_set(n); \
|
||||
} while(0)
|
||||
|
||||
#define _kb_led_all_set_percent(n) do { \
|
||||
_kb_led_1_set_percent(n); \
|
||||
_kb_led_2_set_percent(n); \
|
||||
_kb_led_3_set_percent(n); \
|
||||
} while(0)
|
|
@ -1,226 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* ergoDOX : controller: Teensy 2.0 specific code
|
||||
* ----------------------------------------------------------------------------
|
||||
* 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>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
// for "lib/twi.h"
|
||||
#define TWI_FREQ 400000
|
||||
|
||||
#include "./teensy-2-0.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// check options
|
||||
#if (TEENSY__DRIVE_ROWS && TEENSY__DRIVE_COLUMNS) \
|
||||
|| !(TEENSY__DRIVE_ROWS || TEENSY__DRIVE_COLUMNS)
|
||||
#error "See 'Pin drive direction' in 'options.h'"
|
||||
#endif
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// processor frequency (from <http://www.pjrc.com/teensy/prescaler.html>)
|
||||
#define CPU_PRESCALE(n) (CLKPR = 0x80, CLKPR = (n))
|
||||
#define CPU_16MHz 0x00
|
||||
#define CPU_8MHz 0x01
|
||||
#define CPU_4MHz 0x02
|
||||
#define CPU_2MHz 0x03
|
||||
#define CPU_1MHz 0x04
|
||||
#define CPU_500kHz 0x05
|
||||
#define CPU_250kHz 0x06
|
||||
#define CPU_125kHz 0x07
|
||||
#define CPU_62kHz 0x08
|
||||
|
||||
|
||||
/*
|
||||
* pin macros
|
||||
* - note: you can move the `UNUSED`, `ROW`, and `COLUMN` pins around, but be
|
||||
* sure to keep the set of all the pins listed constant. other pins are not
|
||||
* movable, and either are referenced explicitly or have macros defined for
|
||||
* them elsewhere.
|
||||
* - note: if you change pin assignments, please be sure to update
|
||||
* "teensy-2-0.md", and the '.svg' circuit diagram.
|
||||
*/
|
||||
|
||||
// --- unused
|
||||
#define UNUSED_0 C, 7
|
||||
#define UNUSED_1 D, 7
|
||||
#define UNUSED_2 D, 4 // hard to use with breadboard (on the end)
|
||||
#define UNUSED_3 D, 5 // hard to use with breadboard (on the end)
|
||||
#define UNUSED_4 E, 6 // hard to use with breadboard (internal)
|
||||
|
||||
// --- rows
|
||||
#define ROW_0 F, 7
|
||||
#define ROW_1 F, 6
|
||||
#define ROW_2 F, 5
|
||||
#define ROW_3 F, 4
|
||||
#define ROW_4 F, 1
|
||||
#define ROW_5 F, 0
|
||||
|
||||
// --- columns
|
||||
#define COLUMN_7 B, 0
|
||||
#define COLUMN_8 B, 1
|
||||
#define COLUMN_9 B, 2
|
||||
#define COLUMN_A B, 3
|
||||
#define COLUMN_B D, 2
|
||||
#define COLUMN_C D, 3
|
||||
#define COLUMN_D C, 6
|
||||
|
||||
// --- helpers
|
||||
#define SET |=
|
||||
#define CLEAR &=~
|
||||
|
||||
#define _teensypin_write(register, operation, pin_letter, pin_number) \
|
||||
do { \
|
||||
((register##pin_letter) operation (1<<(pin_number))); \
|
||||
_delay_us(1); /* allow pins time to stabilize */ \
|
||||
} while(0)
|
||||
#define teensypin_write(register, operation, pin) \
|
||||
_teensypin_write(register, operation, pin)
|
||||
|
||||
#define _teensypin_read(pin_letter, pin_number) \
|
||||
((PIN##pin_letter) & (1<<(pin_number)))
|
||||
#define teensypin_read(pin) \
|
||||
_teensypin_read(pin)
|
||||
|
||||
#define teensypin_write_all_unused(register, operation) \
|
||||
do { \
|
||||
teensypin_write(register, operation, UNUSED_0); \
|
||||
teensypin_write(register, operation, UNUSED_1); \
|
||||
teensypin_write(register, operation, UNUSED_2); \
|
||||
teensypin_write(register, operation, UNUSED_3); \
|
||||
teensypin_write(register, operation, UNUSED_4); } \
|
||||
while(0)
|
||||
|
||||
#define teensypin_write_all_row(register, operation) \
|
||||
do { \
|
||||
teensypin_write(register, operation, ROW_0); \
|
||||
teensypin_write(register, operation, ROW_1); \
|
||||
teensypin_write(register, operation, ROW_2); \
|
||||
teensypin_write(register, operation, ROW_3); \
|
||||
teensypin_write(register, operation, ROW_4); \
|
||||
teensypin_write(register, operation, ROW_5); } \
|
||||
while(0)
|
||||
|
||||
#define teensypin_write_all_column(register, operation) \
|
||||
do { \
|
||||
teensypin_write(register, operation, COLUMN_7); \
|
||||
teensypin_write(register, operation, COLUMN_8); \
|
||||
teensypin_write(register, operation, COLUMN_9); \
|
||||
teensypin_write(register, operation, COLUMN_A); \
|
||||
teensypin_write(register, operation, COLUMN_B); \
|
||||
teensypin_write(register, operation, COLUMN_C); \
|
||||
teensypin_write(register, operation, COLUMN_D); } \
|
||||
while(0)
|
||||
|
||||
|
||||
/*
|
||||
* update macros
|
||||
*/
|
||||
#define update_rows_for_column(matrix, column) \
|
||||
do { \
|
||||
/* set column low (set as output) */ \
|
||||
teensypin_write(DDR, SET, COLUMN_##column); \
|
||||
/* read rows 0..5 and update matrix */ \
|
||||
matrix[0x0][0x##column] = ! teensypin_read(ROW_0); \
|
||||
matrix[0x1][0x##column] = ! teensypin_read(ROW_1); \
|
||||
matrix[0x2][0x##column] = ! teensypin_read(ROW_2); \
|
||||
matrix[0x3][0x##column] = ! teensypin_read(ROW_3); \
|
||||
matrix[0x4][0x##column] = ! teensypin_read(ROW_4); \
|
||||
matrix[0x5][0x##column] = ! teensypin_read(ROW_5); \
|
||||
/* set column hi-Z (set as input) */ \
|
||||
teensypin_write(DDR, CLEAR, COLUMN_##column); \
|
||||
} while(0)
|
||||
|
||||
#define update_columns_for_row(matrix, row) \
|
||||
do { \
|
||||
/* set row low (set as output) */ \
|
||||
teensypin_write(DDR, SET, ROW_##row); \
|
||||
/* read columns 7..D and update matrix */ \
|
||||
matrix[0x##row][0x7] = ! teensypin_read(COLUMN_7); \
|
||||
matrix[0x##row][0x8] = ! teensypin_read(COLUMN_8); \
|
||||
matrix[0x##row][0x9] = ! teensypin_read(COLUMN_9); \
|
||||
matrix[0x##row][0xA] = ! teensypin_read(COLUMN_A); \
|
||||
matrix[0x##row][0xB] = ! teensypin_read(COLUMN_B); \
|
||||
matrix[0x##row][0xC] = ! teensypin_read(COLUMN_C); \
|
||||
matrix[0x##row][0xD] = ! teensypin_read(COLUMN_D); \
|
||||
/* set row hi-Z (set as input) */ \
|
||||
teensypin_write(DDR, CLEAR, ROW_##row); \
|
||||
} while(0)
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/* returns
|
||||
* - success: 0
|
||||
*/
|
||||
uint8_t teensy_init(void) {
|
||||
// CPU speed : should match F_CPU in makefile
|
||||
#if F_CPU != 16000000
|
||||
#error "Expecting different CPU frequency"
|
||||
#endif
|
||||
CPU_PRESCALE(CPU_16MHz);
|
||||
|
||||
// onboard LED
|
||||
// (tied to GND for hardware convenience)
|
||||
DDRD &= ~(1<<6); // set D(6) as input
|
||||
PORTD &= ~(1<<6); // set D(6) internal pull-up disabled
|
||||
|
||||
// (tied to Vcc for hardware convenience)
|
||||
DDRB &= ~(1<<4); // set B(4) as input
|
||||
PORTB &= ~(1<<4); // set B(4) internal pull-up disabled
|
||||
|
||||
// keyboard LEDs (see "PWM on ports OC1(A|B|C)" in "teensy-2-0.md")
|
||||
_kb_led_all_off(); // (just to put the pins in a known state)
|
||||
TCCR1A = 0b10101001; // set and configure fast PWM
|
||||
TCCR1B = 0b00001001; // set and configure fast PWM
|
||||
|
||||
// I2C (TWI)
|
||||
twi_init(); // on pins D(1,0)
|
||||
|
||||
// unused pins
|
||||
teensypin_write_all_unused(DDR, CLEAR); // set as input
|
||||
teensypin_write_all_unused(PORT, SET); // set internal pull-up enabled
|
||||
|
||||
// rows and columns
|
||||
teensypin_write_all_row(DDR, CLEAR); // set as input (hi-Z)
|
||||
teensypin_write_all_column(DDR, CLEAR); // set as input (hi-Z)
|
||||
#if TEENSY__DRIVE_ROWS
|
||||
teensypin_write_all_row(PORT, CLEAR); // pull-up disabled
|
||||
teensypin_write_all_column(PORT, SET); // pull-up enabled
|
||||
#elif TEENSY__DRIVE_COLUMNS
|
||||
teensypin_write_all_row(PORT, SET); // pull-up enabled
|
||||
teensypin_write_all_column(PORT, CLEAR); // pull-up disabled
|
||||
#endif
|
||||
|
||||
return 0; // success
|
||||
}
|
||||
|
||||
/* returns
|
||||
* - success: 0
|
||||
*/
|
||||
#if KB_ROWS != 6 || KB_COLUMNS != 14
|
||||
#error "Expecting different keyboard dimensions"
|
||||
#endif
|
||||
|
||||
uint8_t teensy_update_matrix(bool matrix[KB_ROWS][KB_COLUMNS]) {
|
||||
#if TEENSY__DRIVE_ROWS
|
||||
update_columns_for_row(matrix, 0);
|
||||
update_columns_for_row(matrix, 1);
|
||||
update_columns_for_row(matrix, 2);
|
||||
update_columns_for_row(matrix, 3);
|
||||
update_columns_for_row(matrix, 4);
|
||||
update_columns_for_row(matrix, 5);
|
||||
#elif TEENSY__DRIVE_COLUMNS
|
||||
update_rows_for_column(matrix, 7);
|
||||
update_rows_for_column(matrix, 8);
|
||||
update_rows_for_column(matrix, 9);
|
||||
update_rows_for_column(matrix, A);
|
||||
update_rows_for_column(matrix, B);
|
||||
update_rows_for_column(matrix, C);
|
||||
update_rows_for_column(matrix, D);
|
||||
#endif
|
||||
|
||||
return 0; // success
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* ergoDOX : controller : Teensy 2.0 specific exports : functions
|
||||
* ----------------------------------------------------------------------------
|
||||
* 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>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <avr/io.h>
|
||||
#include <util/delay.h>
|
||||
#include "../../lib/teensy-2-0.h"
|
||||
#include "../options.h"
|
||||
#include "../matrix.h"
|
||||
#include "./teensy-2-0--led.h"
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
uint8_t teensy_init(void);
|
||||
uint8_t teensy_update_matrix( bool matrix[KB_ROWS][KB_COLUMNS] );
|
|
@ -12,7 +12,7 @@
|
|||
#include <stddef.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include "../lib/keyboard.h"
|
||||
#include "../lib/key-functions/public.h"
|
||||
#include "../lib/keyfunctions.h"
|
||||
#include "./controller.h"
|
||||
|
||||
typedef void (*void_funptr_t)(void);
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
# src/lib/key-functions
|
||||
|
||||
These functions may do.. pretty much anything rational that they like. If they
|
||||
want keycodes to be sent to the host in an aggregate report, they're responsible
|
||||
for modifying the appropriate report variables.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Copyright © 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>
|
||||
|
|
@ -6,7 +6,7 @@
|
|||
* Project located at <https://github.com/benblazak/ergodox-firmware>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
#include "./public.h"
|
||||
#include "./keyfunctions.h"
|
||||
|
||||
/*
|
||||
* MediaCodeLookupTable is used to translate from enumeration in keyboard.h to
|
|
@ -12,10 +12,10 @@
|
|||
#include <util/delay.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "../../main.h"
|
||||
#include "../../keyboard/layout.h"
|
||||
#include "../../lib-other/pjrc/usb_keyboard/usb_keyboard.h"
|
||||
#include "../../lib/keyboard.h"
|
||||
#include "../main.h"
|
||||
#include "../keyboard/layout.h"
|
||||
#include "../lib-other/pjrc/usb_keyboard/usb_keyboard.h"
|
||||
#include "../lib/keyboard.h"
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
|
@ -12,7 +12,7 @@
|
|||
#include <stdint.h>
|
||||
#include <util/delay.h>
|
||||
#include "./lib-other/pjrc/usb_keyboard/usb_keyboard.h"
|
||||
#include "./lib/key-functions/public.h"
|
||||
#include "./lib/keyfunctions.h"
|
||||
#include "./keyboard/controller.h"
|
||||
#include "./keyboard/layout.h"
|
||||
|
||||
|
|
Loading…
Reference in New Issue