2012-03-19 08:01:41 +01:00
|
|
|
/* ----------------------------------------------------------------------------
|
|
|
|
* ergoDOX controller: Teensy 2.0 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 <avr/io.h>
|
2012-06-04 06:25:50 +02:00
|
|
|
#include <util/delay.h>
|
2012-04-29 08:40:00 +02:00
|
|
|
#include "lib/data-types.h"
|
2012-04-10 10:44:27 +02:00
|
|
|
#define TWI_FREQ 400000
|
2012-04-29 08:40:00 +02:00
|
|
|
#include "lib/twi.h"
|
2012-04-05 12:08:20 +02:00
|
|
|
|
2012-04-06 09:19:57 +02:00
|
|
|
#include "matrix.h"
|
2012-03-27 12:06:52 +02:00
|
|
|
#include "teensy-2-0.h"
|
bugfix (mostly): changed the way layers are handled
before, if you pressed a key, then shifted layers, then released it, the
first layer's press() would be called, and the 2nd layer's release()
would be called, causing keys to stick, and probably other errors. now,
the layer that the key was on when it was pressed is kept track of, and
the proper release() is called.
also, layers can be shifted per key now, instead of just for the whole
board at once
i also changed how keyboard-private includes are handled. "private"
stuff is now in its own file, instead of being nested in an extra
`#ifdef`.
and i think that's it. i'm pretty tired right now, so there may be
errors, but it seemed to work all right with cursory tests.
2012-06-11 12:27:34 +02:00
|
|
|
#include "teensy-2-0--private.h"
|
2012-03-27 12:06:52 +02:00
|
|
|
|
|
|
|
|
2012-03-19 08:01:41 +01:00
|
|
|
// 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
|
|
|
|
|
|
|
|
|
2012-04-05 12:08:20 +02:00
|
|
|
/* pin macros
|
|
|
|
* - note: you can move the `UNUSED`, `ROW`, and `COLUMN` pins around, but be
|
2012-04-06 09:19:57 +02:00
|
|
|
* 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.
|
2012-04-05 12:08:20 +02:00
|
|
|
* - note: if you change pin assignments, please be sure to update
|
2012-04-30 23:05:25 +02:00
|
|
|
* "teensy-2-0.md", and the '.svg' circuit diagram.
|
2012-04-05 12:08:20 +02:00
|
|
|
*/
|
|
|
|
// --- helpers
|
2012-06-04 06:12:15 +02:00
|
|
|
#define teensypin_write(register, operation, pin) do { \
|
|
|
|
_teensypin_write(register, operation, pin); \
|
|
|
|
_delay_us(1); /* allow pins time to stabalize */ \
|
|
|
|
} while(0)
|
2012-04-30 23:05:25 +02:00
|
|
|
#define _teensypin_write(register, operation, pin_letter, pin_number) \
|
2012-04-05 12:08:20 +02:00
|
|
|
((register##pin_letter) operation (1<<(pin_number)))
|
|
|
|
|
2012-04-30 23:05:25 +02:00
|
|
|
#define teensypin_read(pin) \
|
|
|
|
_teensypin_read(pin)
|
|
|
|
#define _teensypin_read(pin_letter, pin_number) \
|
2012-04-05 12:08:20 +02:00
|
|
|
((PIN##pin_letter) & (1<<(pin_number)))
|
|
|
|
|
2012-04-30 23:05:25 +02:00
|
|
|
#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); \
|
|
|
|
teensypin_write(register, operation, UNUSED_5); } \
|
|
|
|
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_0); \
|
|
|
|
teensypin_write(register, operation, COLUMN_1); \
|
|
|
|
teensypin_write(register, operation, COLUMN_2); \
|
|
|
|
teensypin_write(register, operation, COLUMN_3); \
|
|
|
|
teensypin_write(register, operation, COLUMN_4); \
|
|
|
|
teensypin_write(register, operation, COLUMN_5); \
|
|
|
|
teensypin_write(register, operation, COLUMN_6); } \
|
|
|
|
while(0)
|
|
|
|
|
2012-04-05 12:08:20 +02:00
|
|
|
#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
|
|
|
|
|
|
|
|
|
2012-04-10 10:44:27 +02:00
|
|
|
/* returns
|
2012-04-02 10:59:00 +02:00
|
|
|
* - success: 0
|
|
|
|
*/
|
2012-03-27 12:06:52 +02:00
|
|
|
uint8_t teensy_init(void) {
|
2012-03-19 08:01:41 +01:00
|
|
|
CPU_PRESCALE(CPU_16MHz); // speed should match F_CPU in makefile
|
|
|
|
|
2012-04-05 12:08:20 +02:00
|
|
|
// onboard LED
|
|
|
|
DDRD &= ~(1<<6); // set D(6) as input
|
|
|
|
PORTD &= ~(1<<6); // set D(6) internal pull-up disabled
|
|
|
|
|
|
|
|
// keyboard LEDs (see "PWM on ports OC1(A|B|C)" in "teensy-2-0.md")
|
2012-06-14 20:38:49 +02:00
|
|
|
_kb_led_all_off(); // (just to put the pins in a known state)
|
2012-03-19 08:01:41 +01:00
|
|
|
TCCR1A = 0b10101001; // set and configure fast PWM
|
|
|
|
TCCR1B = 0b00001001; // set and configure fast PWM
|
|
|
|
|
2012-04-05 12:08:20 +02:00
|
|
|
// I2C (TWI)
|
2012-04-10 10:44:27 +02:00
|
|
|
twi_init(); // on pins D(1,0)
|
2012-04-05 12:08:20 +02:00
|
|
|
|
|
|
|
// unused pins
|
2012-04-30 23:05:25 +02:00
|
|
|
teensypin_write_all_unused(DDR, CLEAR); // set as input
|
|
|
|
teensypin_write_all_unused(PORT, SET); // set internal pull-up enabled
|
2012-04-05 12:08:20 +02:00
|
|
|
|
2012-03-19 08:01:41 +01:00
|
|
|
// rows
|
2012-05-27 07:50:33 +02:00
|
|
|
teensypin_write_all_row(DDR, CLEAR); // set as input
|
|
|
|
teensypin_write_all_row(PORT, SET); // set internal pull-up enabled
|
2012-03-19 08:01:41 +01:00
|
|
|
|
|
|
|
// columns
|
2012-05-27 07:50:33 +02:00
|
|
|
teensypin_write_all_column(DDR, CLEAR); // set as input (hi-Z)
|
|
|
|
teensypin_write_all_column(PORT, CLEAR); // set internal pull-up
|
|
|
|
// disabled
|
2012-03-27 12:06:52 +02:00
|
|
|
|
|
|
|
return 0; // success
|
2012-03-19 08:01:41 +01:00
|
|
|
}
|
|
|
|
|
2012-04-10 10:44:27 +02:00
|
|
|
/* returns
|
2012-04-06 09:19:57 +02:00
|
|
|
* - success: 0
|
|
|
|
*/
|
|
|
|
#if KB_ROWS != 12 || KB_COLUMNS != 7
|
|
|
|
#error "Expecting different keyboard dimensions"
|
|
|
|
#endif
|
2012-05-27 07:50:33 +02:00
|
|
|
static inline void _update_rows(
|
|
|
|
bool matrix[KB_ROWS][KB_COLUMNS], uint8_t column ) {
|
|
|
|
matrix[0][column] = ! teensypin_read(ROW_0);
|
|
|
|
matrix[1][column] = ! teensypin_read(ROW_1);
|
|
|
|
matrix[2][column] = ! teensypin_read(ROW_2);
|
|
|
|
matrix[3][column] = ! teensypin_read(ROW_3);
|
|
|
|
matrix[4][column] = ! teensypin_read(ROW_4);
|
|
|
|
matrix[5][column] = ! teensypin_read(ROW_5);
|
2012-04-06 09:19:57 +02:00
|
|
|
}
|
2012-04-10 10:44:27 +02:00
|
|
|
uint8_t teensy_update_matrix(bool matrix[KB_ROWS][KB_COLUMNS]) {
|
2012-05-27 07:50:33 +02:00
|
|
|
teensypin_write(DDR, SET, COLUMN_0); // set col low (set as output)
|
|
|
|
_update_rows(matrix, 0); // read row 0..5 & update matrix
|
|
|
|
teensypin_write(DDR, CLEAR, COLUMN_0); // set col hi-Z (set as input)
|
2012-04-06 09:19:57 +02:00
|
|
|
|
2012-05-27 07:50:33 +02:00
|
|
|
teensypin_write(DDR, SET, COLUMN_1);
|
|
|
|
_update_rows(matrix, 1);
|
|
|
|
teensypin_write(DDR, CLEAR, COLUMN_1);
|
2012-04-06 09:19:57 +02:00
|
|
|
|
2012-05-27 07:50:33 +02:00
|
|
|
teensypin_write(DDR, SET, COLUMN_2);
|
|
|
|
_update_rows(matrix, 2);
|
|
|
|
teensypin_write(DDR, CLEAR, COLUMN_2);
|
2012-04-06 09:19:57 +02:00
|
|
|
|
2012-05-27 07:50:33 +02:00
|
|
|
teensypin_write(DDR, SET, COLUMN_3);
|
|
|
|
_update_rows(matrix, 3);
|
|
|
|
teensypin_write(DDR, CLEAR, COLUMN_3);
|
2012-04-06 09:19:57 +02:00
|
|
|
|
2012-05-27 07:50:33 +02:00
|
|
|
teensypin_write(DDR, SET, COLUMN_4);
|
|
|
|
_update_rows(matrix, 4);
|
|
|
|
teensypin_write(DDR, CLEAR, COLUMN_4);
|
2012-04-06 09:19:57 +02:00
|
|
|
|
2012-05-27 07:50:33 +02:00
|
|
|
teensypin_write(DDR, SET, COLUMN_5);
|
|
|
|
_update_rows(matrix, 5);
|
|
|
|
teensypin_write(DDR, CLEAR, COLUMN_5);
|
|
|
|
|
|
|
|
teensypin_write(DDR, SET, COLUMN_6);
|
|
|
|
_update_rows(matrix, 6);
|
|
|
|
teensypin_write(DDR, CLEAR, COLUMN_6);
|
2012-04-06 09:19:57 +02:00
|
|
|
|
|
|
|
return 0; // success
|
|
|
|
}
|
|
|
|
|