- 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 // 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> * Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
* Released under The MIT License (MIT) (see "license.md") * Released under The MIT License (MIT) (see "license.md")
@ -9,38 +9,13 @@
#ifndef LAYOUT_h #ifndef LAYOUT_h
#define LAYOUT_h #define LAYOUT_h
#include "lib/usb/keyboard-usage-page.h" #include "lib/data-types.h"
#include "matrix.h" #include "matrix.h"
#define KB_LAYERS 1 // anything >= 1, as long as there's memory #define KB_LAYERS 1 // anything >= 1, as long as there's memory
#if KB_ROWS != 12 || KB_COLUMNS != 7 extern uint8_t const kb_layout[KB_LAYERS][KB_ROWS][KB_COLUMNS];
#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 -------------------------- */
}
#endif #endif

View File

@ -15,7 +15,7 @@
#define KB_ROWS 12 // must match real life #define KB_ROWS 12 // must match real life
#define KB_COLUMNS 7 // 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 #endif

View File

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

View File

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

View File

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

View File

@ -43,13 +43,14 @@
* notes: * notes:
* ADDR (pin15): Set slave address to `0b0100000` by connecting to Vss(GND). * ADDR (pin15): Set slave address to `0b0100000` by connecting to Vss(GND).
(The user-defined bits are the three least significant). (The user-defined bits are the three least significant).
* RESET (pin16) must be externally biased.Since we're not going to trigger it * RESET (pin16) must be externally biased. Since we're not going to trigger
ourselves, we'll tie it high. it ourselves, we can tie it high.
* This is not noted in the I2C Pinout Description section of the MCP23018 * 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 datasheet, but it's true (empirically), and it is noted in the SPI Pinout
Description section, and in the MCP23017 datasheet. Description section, and in the MCP23017 datasheet.
* <http://davidn.org/wp/?p=89> * I'm not the first person who's failed to notice ;)
* <http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1293498979> * <http://davidn.org/wp/?p=89>
* <http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1293498979>
## Notes about Registers ## Notes about Registers
@ -77,10 +78,10 @@
* notes: * notes:
* All addresses given for IOCON.BANK = 0, since that's the default value of * All addresses given for IOCON.BANK = 0, since that's the default value of
the bit, and that's what we'll be using. 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 (hi-Z) without pull-ups initially,
* We want the row pins set as output high initially, and the column pins set and the column pins set as input with pull-ups. We'll cycle through
as input. We'll cycle through driving the row pins low and checking the driving the row pins low and checking the column pins in the update
column pins in the update function. function.
* abbreviations: * abbreviations:
* IODIR = I/O Direction Register * IODIR = I/O Direction Register

View File

@ -9,6 +9,8 @@
#include <avr/io.h> #include <avr/io.h>
#include "lib/data-types.h"
#define TEENSY_2_0_h_INCLUDE_PRIVATE #define TEENSY_2_0_h_INCLUDE_PRIVATE
#include "teensy-2-0.h" #include "teensy-2-0.h"
@ -26,6 +28,54 @@
#define CPU_62kHz 0x08 #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: /* returns:
* - success: 0 * - success: 0
* + will never return failure * + will never return failure
@ -33,34 +83,68 @@
uint8_t teensy_init(void) { uint8_t teensy_init(void) {
CPU_PRESCALE(CPU_16MHz); // speed should match F_CPU in makefile CPU_PRESCALE(CPU_16MHz); // speed should match F_CPU in makefile
// unused pins // onboard LED
DDRB &= ~0b00001110; // set B(3,2,1) as input DDRD &= ~(1<<6); // set D(6) as input
PORTB |= 0b00001110; // set B(3,2,1) internal pull-up enabled PORTD &= ~(1<<6); // set D(6) internal pull-up disabled
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
// 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 DDRB |= 0b11100000; // set B(7,6,5) as output
TCCR1A = 0b10101001; // set and configure fast PWM TCCR1A = 0b10101001; // set and configure fast PWM
TCCR1B = 0b00001001; // 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 // rows
DDRF |= 0b11110011; // set F(7,6,5,4,1,0) as output // --- set as input (hi-Z)
PORTF |= 0b11110011; // set F(7,6,5,4,1,0) drive high 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 // columns
DDRB &= ~0b00010001; // set B(4,0) as input // --- set as input
PORTB |= 0b00010001; // set B(4,0) internal pull-up enabled TEENSYPIN_WRITE(DDR, CLEAR, COLUMN_0);
DDRC &= ~0b11000000; // set C(7,6) as input TEENSYPIN_WRITE(DDR, CLEAR, COLUMN_1);
PORTC |= 0b11000000; // set C(7,6) internal pull-up enabled TEENSYPIN_WRITE(DDR, CLEAR, COLUMN_2);
DDRD &= ~0b10001100; // set D(7,3,2) as input TEENSYPIN_WRITE(DDR, CLEAR, COLUMN_3);
PORTD |= 0b10001100; // set D(7,3,2) internal pull-up enabled TEENSYPIN_WRITE(DDR, CLEAR, COLUMN_4);
TEENSYPIN_WRITE(DDR, CLEAR, COLUMN_5);
// I2C (TWI) TEENSYPIN_WRITE(DDR, CLEAR, COLUMN_6);
// on pins D(1,0); leave them alone here, so the TWI library can do as // --- set internal pull-up enabled
// it wishes 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 return 0; // success
} }

View File

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

View File

@ -28,12 +28,12 @@
### Teensy 2.0 Pin Assignments ### Teensy 2.0 Pin Assignments
power_negative GND +---.....---+ Vcc power_positive power_negative GND +---.....---+ Vcc power_positive
column6 PB0 + + PF0 row6 column6 PB0 + + PF0 row0
o + PF1 row7 o + PF1 row1
o + PF4 row8 o + PF4 row2
o o o + PF5 row9 o o o + PF5 row3
LED3 OC1C + + PF6 rowA LED3 OC1C + + PF6 row4
I2C SCL + + PF7 rowB I2C SCL + + PF7 row5
I2C SDA + + OC1B LED2 I2C SDA + + OC1B LED2
column3 PD2 + + OC1A LED1 column3 PD2 + + OC1A LED1
column4 PD3 + + PB4 column0 column4 PD3 + + PB4 column0
@ -63,12 +63,16 @@
* notes: * notes:
* Unused pins should be set as input with internal pullup enabled (see * 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. 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 * 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 LED, so there's no reason to set internal pull-up enabled on it. If we do,
do, it will source current to the LED, which is fine, but unnecessary. 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 * We want the row pins 'hi-Z' initially (set as input with pull-up disabled),
input with internal pull-up. We'll cycle through driving the row pins low and the column pins set as input with internal pull-up enabled. We'll
and checking the column pins in the update function. 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) ### PWM on ports OC1(A|B|C) (see datasheet section 14.10)

View File

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

View File

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

View File

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

View File

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