- fixed some includes (`uint8_t` comes from a header, not the language)
- put code from some of the .h files into .c files
- now using open drain logic (hi-Z or GND) on both chips instead of
  driving the row pins high on the teensy, or using a pull-up resistor
  on the row pins with the mcp23018
- put `return 0;` at the end of some functions that weren't void
- fixed/updated some documentation; esp. the row assignments for the
  mcp23018
- generalized the unused/row/column pin assignment and init code using
  macros, so they'll be much easier to move around if necessary
- fixed a redefinition error in "lib/usb/keyboard-usage-page.h"
partial-rewrite
Ben Blazak 2012-04-05 03:08:20 -07:00
parent f41502ba3c
commit 2dce6e4066
14 changed files with 170 additions and 104 deletions

View File

@ -13,6 +13,6 @@
// TODO
void main(void) {
int main(void) {
}

View File

@ -1,5 +1,5 @@
/* ----------------------------------------------------------------------------
* ergoDOX layout
* ergoDOX layout specific exports
* ----------------------------------------------------------------------------
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
* Released under The MIT License (MIT) (see "license.md")
@ -9,38 +9,13 @@
#ifndef LAYOUT_h
#define LAYOUT_h
#include "lib/usb/keyboard-usage-page.h"
#include "lib/data-types.h"
#include "matrix.h"
#define KB_LAYERS 1 // anything >= 1, as long as there's memory
#if KB_ROWS != 12 || KB_COLUMNS != 7
#error "Expecting different keyboard dimensions"
#endif
extern const uint8_t kb_layout[KB_LAYERS][KB_ROWS][KB_COLUMNS] = {
// TODO (before release): put more effort into this
// ------- layer 0: default -------
// --- right hand ---
/* 0 -------------------------- 1 -------------------------- 2 -------------------------- 3 -------------------------- 4 -------------------------- 5 -------------------------- 6 -------------------------- */
/* 0 */ 0, KEY_6_Caret, KEY_7_Ampersand, KEY_8_Asterisk, KEY_9_LeftParenthesis, KEY_0_RightParenthesis, KEY_Dash_Underscore, /* 0 */
/* 1 */ 0, KEY_y_Y, KEY_u_U, KEY_i_I, KEY_o_O, KEY_p_P, KEY_LeftBracket_LeftBrace, /* 1 */
/* 2 */ 0,/*unused*/ KEY_h_H, KEY_j_J, KEY_k_K, KEY_l_L, KEY_Semicolon_Colon, KEY_SingleQuote_DoubleQuote, /* 2 */
/* 3 */ 0, KEY_n_N, KEY_m_M, KEY_Comma_LessThan, KEY_Period_GreaterThan, KEY_Slash_Question, KEY_RightShift, /* 3 */
/* 4 */ 0,/*unused*/ 0,/*unused*/ KEY_UpArrow, KEY_DownArrow, KEY_Backslash_Pipe, KEY_RightBracket_RightBrace, 0, /* 4 */
/* 5 */ 0,/*unused*/ KEY_RightControl, KEY_RightAlt, KEY_PageUp, KEY_PageDown, KEY_ReturnEnter, KEY_Spacebar, /* 5 */
/* 0 -------------------------- 1 -------------------------- 2 -------------------------- 3 -------------------------- 4 -------------------------- 5 -------------------------- 6 -------------------------- */
// --- left hand ---
/* 0 -------------------------- 1 -------------------------- 2 -------------------------- 3 -------------------------- 4 -------------------------- 5 -------------------------- 6 -------------------------- */
/* 6 */ KEY_Equal_Plus, KEY_1_Exclamation, KEY_2_At, KEY_3_Pound, KEY_4_Dollar, KEY_5_Percent, 0, /* 6 */
/* 7 */ KEY_Tab, KEY_q_Q, KEY_w_W, KEY_e_E, KEY_r_R, KEY_t_T, 0, /* 7 */
/* 8 */ KEY_CapsLock, KEY_a_A, KEY_s_S, KEY_d_D, KEY_f_F, KEY_g_G, 0,/*unused*/ /* 8 */
/* 9 */ KEY_LeftShift, KEY_z_Z, KEY_x_X, KEY_c_C, KEY_v_V, KEY_b_B, 0, /* 9 */
/* A */ 0, KEY_GraveAccent_Tilde, KEY_Backslash_Pipe, KEY_LeftArrow, KEY_RightArrow, 0,/*unused*/ 0,/*unused*/ /* A */
/* B */ KEY_DeleteBackspace, KEY_DeleteForward, KEY_End, KEY_Home, KEY_LeftAlt, KEY_LeftControl, 0, 0 /*unused*/ /* B */
/* 0 -------------------------- 1 -------------------------- 2 -------------------------- 3 -------------------------- 4 -------------------------- 5 -------------------------- 6 -------------------------- */
}
extern uint8_t const kb_layout[KB_LAYERS][KB_ROWS][KB_COLUMNS];
#endif

View File

@ -15,7 +15,7 @@
#define KB_ROWS 12 // must match real life
#define KB_COLUMNS 7 // must match real life
extern bool kb_is_pressed[KB_ROWS][KB_COLUMNS] = {false};
extern bool kb_is_pressed[KB_ROWS][KB_COLUMNS];
#endif

View File

@ -1,11 +1,10 @@
# Documentation : Keyboard Matrix
## Matrix [row.column] assignments
## Matrix [row##column] assignments
* row and column numbers are in hex
* coordinates without brackets are unused
* left and right hands are mostly the same, except that `row += 6` for left
hand rows
* row and column numbers are in hex
* coordinates without brackets are unused
* left and right hands are mostly the same except that `row += 6` for the left
....... rows x columns = positions; assigned, unassigned .......
....... per hand: 6 x 7 = 42; 38, 4 .......

View File

@ -33,12 +33,6 @@
#define TWI_ADDR_READ ( (MCP23018_TWI_ADDRESS<<1) | TW_READ )
// error check
#if KB_ROWS != 12 || KB_COLUMNS != 7
#error "Expecting different keyboard dimensions"
#endif
/*
* returns:
* - success: 0
@ -69,36 +63,37 @@ uint8_t mcp23018_init(void) {
twi_send(0b11111111); // IODIRB
// set pull-up
// - unused : on : 1
// - rows : on : 1
// - columns : on : 1
// - unused : on : 1
// - rows : off : 0
// - columns : on : 1
twi_start();
twi_send(TWI_ADDR_WRITE);
twi_send(GPPUA);
twi_send(0b11111111); // GPPUA
twi_send(0b11000000); // GPPUA
twi_send(0b11111111); // GPPUB
// set output pins high
// - unused : low : 0
// - rows : high : 1
// - columns : low : 0
// set logical value (doesn't matter on inputs)
// - unused : high (hi-Z) : 1
// - rows : high (hi-Z) : 1
// - columns : high (hi-Z) : 1
twi_start();
twi_send(TWI_ADDR_WRITE);
twi_send(GPIOA);
twi_send(0b00111111); //GPIOA
twi_send(0b00000000); //GPIOB
twi_send(0b11111111); //GPIOA
twi_send(0b11111111); //GPIOB
twi_stop();
return 0; // success
}
/* args:
* - `matrix[][]`: `KB_ROWS` and `KB_COLUMNS` must be what we're expecting (see
* 'error check' in the `#include` section)
*
* returns:
/* returns:
* - success: 0
* - failure: twi status code
*/
#if KB_ROWS != 12 || KB_COLUMNS != 7
#error "Expecting different keyboard dimensions"
#endif
uint8_t mcp23018_update_matrix(uint8_t matrix[KB_ROWS][KB_COLUMNS]) {
uint8_t ret, data;
@ -129,5 +124,7 @@ uint8_t mcp23018_update_matrix(uint8_t matrix[KB_ROWS][KB_COLUMNS]) {
}
twi_stop();
return 0; // success
}

View File

@ -10,6 +10,8 @@
#ifndef MCP23018_h
#define MCP23018_h
#include "lib/data-types.h"
#ifdef MCP23018_h_INCLUDE_PRIVATE
#define MCP23018_TWI_ADDRESS 0b0100000

View File

@ -43,13 +43,14 @@
* notes:
* ADDR (pin15): Set slave address to `0b0100000` by connecting to Vss(GND).
(The user-defined bits are the three least significant).
* RESET (pin16) must be externally biased.Since we're not going to trigger it
ourselves, we'll tie it high.
* 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.
* <http://davidn.org/wp/?p=89>
* <http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1293498979>
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
@ -77,10 +78,10 @@
* 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.
* Outputs are open drain, so we want pull-up resistors set for everything.
* We want the row pins set as output high initially, and the column pins set
as input. We'll cycle through driving the row pins low and checking the
column pins in the update function.
* We want the row pins set as output high (hi-Z) without pull-ups initially,
and the column pins set as input with pull-ups. We'll cycle through
driving the row pins low and checking the column pins in the update
function.
* abbreviations:
* IODIR = I/O Direction Register

View File

@ -9,6 +9,8 @@
#include <avr/io.h>
#include "lib/data-types.h"
#define TEENSY_2_0_h_INCLUDE_PRIVATE
#include "teensy-2-0.h"
@ -26,6 +28,54 @@
#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 pins listed in those catagories 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".
*/
// --- helpers
#define TEENSYPIN_WRITE(register, operation, pin) \
_TEENSYPIN_WRITE(register, operation, pin)
#define _TEENSYPIN_WRITE(register, operation, pin_letter, pin_number) \
((register##pin_letter) operation (1<<(pin_number)))
#define TEENSYPIN_READ(pin) \
_TEENSYPIN_READ(pin)
#define _TEENSYPIN_READ(pin_letter, pin_number) \
((PIN##pin_letter) & (1<<(pin_number)))
#define SET |=
#define CLEAR &=~
// --- unused
#define UNUSED_0 B, 1 // SPI pin
#define UNUSED_1 B, 2 // SPI pin
#define UNUSED_2 B, 3 // SPI pin
#define UNUSED_3 D, 4 // hard to use with breadboard (on the end)
#define UNUSED_4 D, 5 // hard to use with breadboard (on the end)
#define UNUSED_5 E, 6 // hard to use with breadboard (internal)
// --- rows
#define ROW_0 F, 0
#define ROW_1 F, 1
#define ROW_2 F, 4
#define ROW_3 F, 5
#define ROW_4 F, 6
#define ROW_5 F, 7
// --- columns
#define COLUMN_0 B, 4
#define COLUMN_1 C, 6
#define COLUMN_2 C, 7
#define COLUMN_3 D, 2
#define COLUMN_4 D, 3
#define COLUMN_5 D, 7
#define COLUMN_6 B, 0
/* returns:
* - success: 0
* + will never return failure
@ -33,34 +83,68 @@
uint8_t teensy_init(void) {
CPU_PRESCALE(CPU_16MHz); // speed should match F_CPU in makefile
// unused pins
DDRB &= ~0b00001110; // set B(3,2,1) as input
PORTB |= 0b00001110; // set B(3,2,1) internal pull-up enabled
DDRD &= ~0b01110000; // set D(6,5,4) as input
PORTD |= 0b00110000; // set D( 5,4) internal pull-up enabled
DDRE &= ~0b01000000; // set E(6) as input
PORTE |= 0b01000000; // set E(6) internal pull-up enabled
// onboard LED
DDRD &= ~(1<<6); // set D(6) as input
PORTD &= ~(1<<6); // set D(6) internal pull-up disabled
// LEDs (see "PWM on ports OC1(A|B|C)" in "teensy-2-0.md")
// keyboard LEDs (see "PWM on ports OC1(A|B|C)" in "teensy-2-0.md")
DDRB |= 0b11100000; // set B(7,6,5) as output
TCCR1A = 0b10101001; // set and configure fast PWM
TCCR1B = 0b00001001; // set and configure fast PWM
// I2C (TWI)
// on pins D(1,0); leave them alone here so the TWI library can do as
// it wishes
// unused pins
// --- set as input
TEENSYPIN_WRITE(DDR, CLEAR, UNUSED_0);
TEENSYPIN_WRITE(DDR, CLEAR, UNUSED_1);
TEENSYPIN_WRITE(DDR, CLEAR, UNUSED_2);
TEENSYPIN_WRITE(DDR, CLEAR, UNUSED_3);
TEENSYPIN_WRITE(DDR, CLEAR, UNUSED_4);
TEENSYPIN_WRITE(DDR, CLEAR, UNUSED_5);
// --- set internal pull-up enabled
TEENSYPIN_WRITE(PORT, SET, UNUSED_0);
TEENSYPIN_WRITE(PORT, SET, UNUSED_1);
TEENSYPIN_WRITE(PORT, SET, UNUSED_2);
TEENSYPIN_WRITE(PORT, SET, UNUSED_3);
TEENSYPIN_WRITE(PORT, SET, UNUSED_4);
TEENSYPIN_WRITE(PORT, SET, UNUSED_5);
// rows
DDRF |= 0b11110011; // set F(7,6,5,4,1,0) as output
PORTF |= 0b11110011; // set F(7,6,5,4,1,0) drive high
// --- set as input (hi-Z)
TEENSYPIN_WRITE(DDR, CLEAR, ROW_0);
TEENSYPIN_WRITE(DDR, CLEAR, ROW_1);
TEENSYPIN_WRITE(DDR, CLEAR, ROW_2);
TEENSYPIN_WRITE(DDR, CLEAR, ROW_3);
TEENSYPIN_WRITE(DDR, CLEAR, ROW_4);
TEENSYPIN_WRITE(DDR, CLEAR, ROW_5);
// --- set internal pull-up disabled
TEENSYPIN_WRITE(PORT, CLEAR, ROW_0);
TEENSYPIN_WRITE(PORT, CLEAR, ROW_1);
TEENSYPIN_WRITE(PORT, CLEAR, ROW_2);
TEENSYPIN_WRITE(PORT, CLEAR, ROW_3);
TEENSYPIN_WRITE(PORT, CLEAR, ROW_4);
TEENSYPIN_WRITE(PORT, CLEAR, ROW_5);
// columns
DDRB &= ~0b00010001; // set B(4,0) as input
PORTB |= 0b00010001; // set B(4,0) internal pull-up enabled
DDRC &= ~0b11000000; // set C(7,6) as input
PORTC |= 0b11000000; // set C(7,6) internal pull-up enabled
DDRD &= ~0b10001100; // set D(7,3,2) as input
PORTD |= 0b10001100; // set D(7,3,2) internal pull-up enabled
// I2C (TWI)
// on pins D(1,0); leave them alone here, so the TWI library can do as
// it wishes
// --- set as input
TEENSYPIN_WRITE(DDR, CLEAR, COLUMN_0);
TEENSYPIN_WRITE(DDR, CLEAR, COLUMN_1);
TEENSYPIN_WRITE(DDR, CLEAR, COLUMN_2);
TEENSYPIN_WRITE(DDR, CLEAR, COLUMN_3);
TEENSYPIN_WRITE(DDR, CLEAR, COLUMN_4);
TEENSYPIN_WRITE(DDR, CLEAR, COLUMN_5);
TEENSYPIN_WRITE(DDR, CLEAR, COLUMN_6);
// --- set internal pull-up enabled
TEENSYPIN_WRITE(PORT, SET, COLUMN_0);
TEENSYPIN_WRITE(PORT, SET, COLUMN_1);
TEENSYPIN_WRITE(PORT, SET, COLUMN_2);
TEENSYPIN_WRITE(PORT, SET, COLUMN_3);
TEENSYPIN_WRITE(PORT, SET, COLUMN_4);
TEENSYPIN_WRITE(PORT, SET, COLUMN_5);
TEENSYPIN_WRITE(PORT, SET, COLUMN_6);
return 0; // success
}

View File

@ -12,6 +12,8 @@
#include <avr/io.h> // for the register macros
#include "lib/data-types.h"
// LED control
#define KB_LED1_ON (DDRB |= (1<<5))
#define KB_LED1_OFF (DDRB &= ~(1<<5))

View File

@ -28,12 +28,12 @@
### Teensy 2.0 Pin Assignments
power_negative GND +---.....---+ Vcc power_positive
column6 PB0 + + PF0 row6
o + PF1 row7
o + PF4 row8
o o o + PF5 row9
LED3 OC1C + + PF6 rowA
I2C SCL + + PF7 rowB
column6 PB0 + + PF0 row0
o + PF1 row1
o + PF4 row2
o o o + PF5 row3
LED3 OC1C + + PF6 row4
I2C SCL + + PF7 row5
I2C SDA + + OC1B LED2
column3 PD2 + + OC1A LED1
column4 PD3 + + PB4 column0
@ -63,12 +63,16 @@
* notes:
* Unused pins should be set as input with internal pullup enabled (see
datasheet section 10.2.6) in order to give them a defined level.
* PD6 already has a defined level (low) since it's hooked up to the onboard
LED, so there's no reason to set internal pull-up enabled on it. If we
do, it will source current to the LED, which is fine, but unnecessary.
* We want the row pins 'drive high' initially, and the column pins set as
input with internal pull-up. We'll cycle through driving the row pins low
and checking the column pins in the update function.
* PD6 already has a defined level (low) since it's hooked up to the onboard
LED, so there's no reason to set internal pull-up enabled on it. If we do,
it will source current to the LED, which is fine, but unnecessary.
* We want the row pins 'hi-Z' initially (set as input with pull-up disabled),
and the column pins set as input with internal pull-up enabled. We'll
cycle through driving the row pins low (setting them as output) and
checking the column pins in the update function.
* Switching the row pins between hi-Z and drive low (treating them as if
they were open drain) seems just as good as, and a little safer than,
driving them high when the row's not active.
### PWM on ports OC1(A|B|C) (see datasheet section 14.10)

View File

@ -10,13 +10,11 @@
#ifndef DATA_TYPES_h
#define DATA_TYPES_h
// --------------------------------------------------------------------
#define bool _Bool
#include <stdint.h>
#define bool _Bool
#define true ((bool)1)
#define false ((bool)0)
// --------------------------------------------------------------------
#endif

View File

@ -42,6 +42,7 @@ uint8_t twi_start(void) {
if (! (TW_STATUS == TW_START) ||
(TW_STATUS == TW_REP_START) )
return TW_STATUS; // error
return 0; // success
}
void twi_stop(void) {
@ -63,6 +64,7 @@ uint8_t twi_send(uint8_t data) {
(TW_STATUS == TW_MT_DATA_ACK)||
(TW_STATUS == TW_MR_SLA_ACK) )
return TW_STATUS; // error
return 0; // success
}
uint8_t twi_read(uint8_t * data) {
@ -71,9 +73,10 @@ uint8_t twi_read(uint8_t * data) {
// wait for transmission to complete
while (!(TWCR & (1<<TWINT)));
// set data variable
data = TWDR;
*data = TWDR;
// if it didn't work, return the status code (else return 0)
if (TW_STATUS != TW_MR_DATA_ACK)
return TW_STATUS; // error
return 0; // success
}

View File

@ -164,7 +164,7 @@
#define KEY_LockingScrollLock 0x84 // - - √ -
#define KEYPAD_Comma 0x85 // - - - -
#define KEYPAD_Equal 0x86 // - - - -
#define KEYPAD_EqualSign 0x86 // - - - -
#define KEY_International1 0x87 // - - - -
#define KEY_International2 0x88 // - - - -

View File

@ -30,4 +30,5 @@ all:
clean:
$(TEENSY_MAKE) clean
git clean -X