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-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-10 10:44:27 +02:00
|
|
|
#define KEYBOARD_INCLUDE_PRIVATE
|
2012-04-06 09:19:57 +02:00
|
|
|
#include "matrix.h"
|
2012-03-27 12:06:52 +02:00
|
|
|
#include "teensy-2-0.h"
|
|
|
|
|
|
|
|
|
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-04-30 23:05:25 +02:00
|
|
|
#define teensypin_write(register, operation, pin) \
|
|
|
|
_teensypin_write(register, operation, pin)
|
|
|
|
#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-01 09:50:45 +02:00
|
|
|
_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
|
|
|
|
}
|
|
|
|
|