aboutsummaryrefslogtreecommitdiff
path: root/keyboard
diff options
context:
space:
mode:
Diffstat (limited to 'keyboard')
-rw-r--r--keyboard/ergodox/Makefile139
-rw-r--r--keyboard/ergodox/README.md56
-rw-r--r--keyboard/ergodox/backlight.c61
-rw-r--r--keyboard/ergodox/config.h88
-rw-r--r--keyboard/ergodox/ergodox.c121
-rw-r--r--keyboard/ergodox/ergodox.h145
-rw-r--r--keyboard/ergodox/i2cmaster.h178
-rw-r--r--keyboard/ergodox/keymaps/keymap_default.c76
-rw-r--r--keyboard/ergodox/matrix.c405
-rw-r--r--keyboard/ergodox/twimaster.c208
-rw-r--r--keyboard/planck/config.h69
-rw-r--r--keyboard/planck/config_definitions.h51
-rw-r--r--keyboard/planck/planck.c6
13 files changed, 1482 insertions, 121 deletions
diff --git a/keyboard/ergodox/Makefile b/keyboard/ergodox/Makefile
new file mode 100644
index 000000000..f71d09678
--- /dev/null
+++ b/keyboard/ergodox/Makefile
@@ -0,0 +1,139 @@
1#----------------------------------------------------------------------------
2# On command line:
3#
4# make all = Make software.
5#
6# make clean = Clean out built project files.
7#
8# make coff = Convert ELF to AVR COFF.
9#
10# make extcoff = Convert ELF to AVR Extended COFF.
11#
12# make program = Download the hex file to the device.
13# Please customize your programmer settings(PROGRAM_CMD)
14#
15# make teensy = Download the hex file to the device, using teensy_loader_cli.
16# (must have teensy_loader_cli installed).
17#
18# make dfu = Download the hex file to the device, using dfu-programmer (must
19# have dfu-programmer installed).
20#
21# make flip = Download the hex file to the device, using Atmel FLIP (must
22# have Atmel FLIP installed).
23#
24# make dfu-ee = Download the eeprom file to the device, using dfu-programmer
25# (must have dfu-programmer installed).
26#
27# make flip-ee = Download the eeprom file to the device, using Atmel FLIP
28# (must have Atmel FLIP installed).
29#
30# make debug = Start either simulavr or avarice as specified for debugging,
31# with avr-gdb or avr-insight as the front end for debugging.
32#
33# make filename.s = Just compile filename.c into the assembler code only.
34#
35# make filename.i = Create a preprocessed source file for use in submitting
36# bug reports to the GCC project.
37#
38# To rebuild project do "make clean" then "make all".
39#----------------------------------------------------------------------------
40
41# Target file name (without extension).
42TARGET = ergodox
43
44
45# Directory common source filess exist
46TOP_DIR = ../..
47
48# Directory keyboard dependent files exist
49TARGET_DIR = .
50
51# # project specific files
52SRC = ergodox.c \
53 twimaster.c \
54 backlight.c
55
56ifdef KEYMAP
57 SRC := keymaps/keymap_$(KEYMAP).c $(SRC)
58else
59 SRC := keymaps/keymap_default.c $(SRC)
60endif
61
62CONFIG_H = config.h
63
64# MCU name
65#MCU = at90usb1287
66MCU = atmega32u4
67
68# Processor frequency.
69# This will define a symbol, F_CPU, in all source code files equal to the
70# processor frequency in Hz. You can then use this symbol in your source code to
71# calculate timings. Do NOT tack on a 'UL' at the end, this will be done
72# automatically to create a 32-bit value in your source code.
73#
74# This will be an integer division of F_USB below, as it is sourced by
75# F_USB after it has run through any CPU prescalers. Note that this value
76# does not *change* the processor frequency - it should merely be updated to
77# reflect the processor speed set externally so that the code can use accurate
78# software delays.
79F_CPU = 16000000
80
81
82#
83# LUFA specific
84#
85# Target architecture (see library "Board Types" documentation).
86ARCH = AVR8
87
88# Input clock frequency.
89# This will define a symbol, F_USB, in all source code files equal to the
90# input clock frequency (before any prescaling is performed) in Hz. This value may
91# differ from F_CPU if prescaling is used on the latter, and is required as the
92# raw input clock is fed directly to the PLL sections of the AVR for high speed
93# clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL'
94# at the end, this will be done automatically to create a 32-bit value in your
95# source code.
96#
97# If no clock division is performed on the input clock inside the AVR (via the
98# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU.
99F_USB = $(F_CPU)
100
101# Interrupt driven control endpoint task(+60)
102OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
103
104
105# Boot Section Size in *bytes*
106# Teensy halfKay 512
107# Teensy++ halfKay 1024
108# Atmel DFU loader 4096
109# LUFA bootloader 4096
110# USBaspLoader 2048
111OPT_DEFS += -DBOOTLOADER_SIZE=4096
112
113
114# Build Options
115# comment out to disable the options.
116#
117BOOTMAGIC_ENABLE = yes # Virtual DIP switch configuration(+1000)
118MOUSEKEY_ENABLE = yes # Mouse keys(+4700)
119EXTRAKEY_ENABLE = yes # Audio control and System control(+450)
120CONSOLE_ENABLE = yes # Console for debug(+400)
121COMMAND_ENABLE = yes # Commands for debug and configuration
122# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
123# SLEEP_LED_ENABLE = yes # Breathing sleep LED during USB suspend
124# NKRO_ENABLE = yes # USB Nkey Rollover - not yet supported in LUFA
125# BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality
126# MIDI_ENABLE = YES # MIDI controls
127# UNICODE_ENABLE = YES # Unicode
128# BLUETOOTH_ENABLE = yes # Enable Bluetooth with the Adafruit EZ-Key HID
129
130
131# Optimize size but this may cause error "relocation truncated to fit"
132#EXTRALDFLAGS = -Wl,--relax
133
134# Search Path
135VPATH += $(TARGET_DIR)
136VPATH += $(TOP_DIR)
137
138include $(TOP_DIR)/quantum.mk
139
diff --git a/keyboard/ergodox/README.md b/keyboard/ergodox/README.md
new file mode 100644
index 000000000..bbbc73515
--- /dev/null
+++ b/keyboard/ergodox/README.md
@@ -0,0 +1,56 @@
1# TMK Generic
2
3* I'm not sure what the Magic + H does.
4 Is this a menu that will pop up regardless of what platform and program is open?
5
6 Yes, this is sort of debugging.
7 Use PJRC's [hid_listen](https://www.pjrc.com/teensy/hid_listen.html) to see debug messages.
8
9# TMK/Ergodox specific
10
11* I would like to configure my leds to indicate the active layer.
12 I read that can be done, but I haven't seen an example for this firmware.
13 Can someone please post an example or a link?
14
15 TMK for Ergodox have support for seven (!) led's:
16 - three on right
17 - three on left (see http://geekhack.org/index.php?topic=22780.msg873819#msg873819 for more details)
18 - Teensy onboard led as well
19
20 Any of these leds can be used as layer indicator or NumLock/CapsLock/ScrollLock led.
21
22 [Here is example](https://github.com/cub-uanic/tmk_keyboard/blob/cub_layout/keyboard/ergodox/matrix.c#L121-167)
23 how you can assign some meaning to each led.
24 In this code only left leds are used to show layers, but you can
25 [change `led_set()`](https://github.com/cub-uanic/tmk_keyboard/blob/cub_layout/keyboard/ergodox/led.c)
26 and do anything you want with all leds.
27
28# Firmware
29
30Q: Where to get binaries?
31A:
32
33Q: Where to get sources?
34A:
35
36Q: How to compile?
37A:
38
39
40# Layouts
41
42description of layouts in base firmware binaries
43
44
45# Things TO-DO
46
47- [ ] Flash NumLock led only when "numpad" layer is active
48- [ ] Command (in terms of IS_COMMAND) to switch to no-leds mode
49- [ ] Increase count of ACTION keys
50- [ ] Fix command_state() onboard led: it should flash only when kbd in some specific mode (CONSOLE || MOUSE)
51- [ ] ergodox_blink_all_leds() should save current state of leds, and restore after blink. initial state of all leds == off
52- [ ] add support for pseudo-backlight (reversed LEDs) + docs/photo
53- [ ] command to debug all LEDs (on/off/blink)
54- [ ] proper (in-core) implementation of DEBUG_MATRIX_SCAN_RATE (non-Ergodox specific)
55- [ ] proper (in-core) support for per-layer fn_actions[]
56
diff --git a/keyboard/ergodox/backlight.c b/keyboard/ergodox/backlight.c
new file mode 100644
index 000000000..f69364b2a
--- /dev/null
+++ b/keyboard/ergodox/backlight.c
@@ -0,0 +1,61 @@
1
2#include <avr/io.h>
3#include "backlight.h"
4
5#define CHANNEL OCR1C
6
7void backlight_init_ports()
8{
9
10 // Setup PB7 as output and output low.
11 DDRB |= (1<<7);
12 PORTB &= ~(1<<7);
13
14 // Use full 16-bit resolution.
15 ICR1 = 0xFFFF;
16
17 // I could write a wall of text here to explain... but TL;DW
18 // Go read the ATmega32u4 datasheet.
19 // And this: http://blog.saikoled.com/post/43165849837/secret-konami-cheat-code-to-high-resolution-pwm-on
20
21 // Pin PB7 = OCR1C (Timer 1, Channel C)
22 // Compare Output Mode = Clear on compare match, Channel C = COM1C1=1 COM1C0=0
23 // (i.e. start high, go low when counter matches.)
24 // WGM Mode 14 (Fast PWM) = WGM13=1 WGM12=1 WGM11=1 WGM10=0
25 // Clock Select = clk/1 (no prescaling) = CS12=0 CS11=0 CS10=1
26
27 TCCR1A = _BV(COM1C1) | _BV(WGM11); // = 0b00001010;
28 TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10); // = 0b00011001;
29
30 backlight_init();
31}
32
33void backlight_set(uint8_t level)
34{
35 if ( level == 0 )
36 {
37 // Turn off PWM control on PB7, revert to output low.
38 TCCR1A &= ~(_BV(COM1C1));
39 CHANNEL = 0x0;
40 // Prevent backlight blink on lowest level
41 PORTB &= ~(_BV(PORTB7));
42 }
43 else if ( level == BACKLIGHT_LEVELS )
44 {
45 // Prevent backlight blink on lowest level
46 PORTB &= ~(_BV(PORTB7));
47 // Turn on PWM control of PB7
48 TCCR1A |= _BV(COM1C1);
49 // Set the brightness
50 CHANNEL = 0xFFFF;
51 }
52 else
53 {
54 // Prevent backlight blink on lowest level
55 PORTB &= ~(_BV(PORTB7));
56 // Turn on PWM control of PB7
57 TCCR1A |= _BV(COM1C1);
58 // Set the brightness
59 CHANNEL = 0xFFFF >> ((BACKLIGHT_LEVELS - level) * ((BACKLIGHT_LEVELS + 1) / 2));
60 }
61} \ No newline at end of file
diff --git a/keyboard/ergodox/config.h b/keyboard/ergodox/config.h
new file mode 100644
index 000000000..c8eaae614
--- /dev/null
+++ b/keyboard/ergodox/config.h
@@ -0,0 +1,88 @@
1/*
2Copyright 2012 Jun Wako <wakojun@gmail.com>
3Copyright 2013 Oleg Kostyuk <cub.uanic@gmail.com>
4
5This program is free software: you can redistribute it and/or modify
6it under the terms of the GNU General Public License as published by
7the Free Software Foundation, either version 2 of the License, or
8(at your option) any later version.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19#ifndef CONFIG_H
20#define CONFIG_H
21
22#include "config_common.h"
23
24/* USB Device descriptor parameter */
25#define VENDOR_ID 0xFEED
26#define PRODUCT_ID 0x1307
27#define DEVICE_VER 0x0001
28#define MANUFACTURER ErgoDox EZ
29#define PRODUCT ErgoDox EZ
30#define DESCRIPTION t.m.k. keyboard firmware for Ergodox
31
32/* key matrix size */
33#define MATRIX_ROWS 14
34#define MATRIX_COLS 6
35
36#define MOUSEKEY_DELAY 100
37#define MOUSEKEY_INTERVAL 20
38#define MOUSEKEY_MAX_SPEED 3
39#define MOUSEKEY_TIME_TO_MAX 10
40
41#define COLS (int []){ F1, F0, B0, C7, F4, F5, F6, F7, D4, D6, B4, D7 }
42#define ROWS (int []){ D0, D5, B5, B6 }
43
44/* COL2ROW or ROW2COL */
45#define DIODE_DIRECTION COL2ROW
46
47/* define if matrix has ghost */
48//#define MATRIX_HAS_GHOST
49
50/* number of backlight levels */
51#define BACKLIGHT_LEVELS 3
52
53/* Set 0 if debouncing isn't needed */
54#define DEBOUNCE 2
55#define TAPPING_TERM 230
56#define TAPPING_TOGGLE 2
57
58/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
59#define LOCKING_SUPPORT_ENABLE
60/* Locking resynchronize hack */
61#define LOCKING_RESYNC_ENABLE
62
63/* key combination for command */
64#define IS_COMMAND() ( \
65 keyboard_report->mods == (MOD_BIT(KC_LCTL) | MOD_BIT(KC_RCTL)) || \
66 keyboard_report->mods == (MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)) \
67)
68
69/*
70 * Feature disable options
71 * These options are also useful to firmware size reduction.
72 */
73
74/* disable debug print */
75// #define NO_DEBUG
76
77/* disable print */
78// #define NO_PRINT
79
80/* disable action features */
81//#define NO_ACTION_LAYER
82//#define NO_ACTION_TAPPING
83//#define NO_ACTION_ONESHOT
84//#define NO_ACTION_MACRO
85//#define NO_ACTION_FUNCTION
86//#define DEBUG_MATRIX_SCAN_RATE
87
88#endif
diff --git a/keyboard/ergodox/ergodox.c b/keyboard/ergodox/ergodox.c
new file mode 100644
index 000000000..38e9b3a8a
--- /dev/null
+++ b/keyboard/ergodox/ergodox.c
@@ -0,0 +1,121 @@
1#include "ergodox.h"
2#include "i2cmaster.h"
3
4bool i2c_initialized = 0;
5uint8_t mcp23018_status = 0x20;
6
7bool ergodox_left_led_1 = 0; // left top
8bool ergodox_left_led_2 = 0; // left middle
9bool ergodox_left_led_3 = 0; // left bottom
10
11void * matrix_init_user(void) {
12
13};
14
15void * matrix_scan_user(void) {
16
17};
18
19void * matrix_init_kb(void) {
20 // keyboard LEDs (see "PWM on ports OC1(A|B|C)" in "teensy-2-0.md")
21 TCCR1A = 0b10101001; // set and configure fast PWM
22 TCCR1B = 0b00001001; // set and configure fast PWM
23
24 // (tied to Vcc for hardware convenience)
25 DDRB &= ~(1<<4); // set B(4) as input
26 PORTB &= ~(1<<4); // set B(4) internal pull-up disabled
27
28 // unused pins - C7, D4, D5, D7, E6
29 // set as input with internal pull-ip enabled
30 DDRC &= ~(1<<7);
31 DDRD &= ~(1<<7 | 1<<5 | 1<<4);
32 DDRE &= ~(1<<6);
33 PORTC |= (1<<7);
34 PORTD |= (1<<7 | 1<<5 | 1<<4);
35 PORTE |= (1<<6);
36
37 ergodox_blink_all_leds();
38
39 if (matrix_init_user) {
40 (*matrix_init_user)();
41 }
42};
43
44void * matrix_scan_kb(void) {
45
46 if (matrix_scan_user) {
47 (*matrix_scan_user)();
48 }
49};
50
51
52void ergodox_blink_all_leds(void)
53{
54 ergodox_led_all_off();
55 ergodox_led_all_set(LED_BRIGHTNESS_HI);
56 ergodox_led_all_on();
57 _delay_ms(333);
58 ergodox_led_all_off();
59}
60
61uint8_t init_mcp23018(void) {
62 mcp23018_status = 0x20;
63
64 // I2C subsystem
65 if (i2c_initialized == 0) {
66 i2c_init(); // on pins D(1,0)
67 i2c_initialized++;
68 _delay_ms(1000);
69 }
70
71 // set pin direction
72 // - unused : input : 1
73 // - input : input : 1
74 // - driving : output : 0
75 mcp23018_status = i2c_start(I2C_ADDR_WRITE); if (mcp23018_status) goto out;
76 mcp23018_status = i2c_write(IODIRA); if (mcp23018_status) goto out;
77 mcp23018_status = i2c_write(0b00000000); if (mcp23018_status) goto out;
78 mcp23018_status = i2c_write(0b00111111); if (mcp23018_status) goto out;
79 i2c_stop();
80
81 // set pull-up
82 // - unused : on : 1
83 // - input : on : 1
84 // - driving : off : 0
85 mcp23018_status = i2c_start(I2C_ADDR_WRITE); if (mcp23018_status) goto out;
86 mcp23018_status = i2c_write(GPPUA); if (mcp23018_status) goto out;
87 mcp23018_status = i2c_write(0b00000000); if (mcp23018_status) goto out;
88 mcp23018_status = i2c_write(0b00111111); if (mcp23018_status) goto out;
89
90out:
91 i2c_stop();
92
93 if (!mcp23018_status) mcp23018_status = ergodox_left_leds_update();
94
95 return mcp23018_status;
96}
97
98uint8_t ergodox_left_leds_update(void) {
99 if (mcp23018_status) { // if there was an error
100 return mcp23018_status;
101 }
102
103 // set logical value (doesn't matter on inputs)
104 // - unused : hi-Z : 1
105 // - input : hi-Z : 1
106 // - driving : hi-Z : 1
107 mcp23018_status = i2c_start(I2C_ADDR_WRITE); if (mcp23018_status) goto out;
108 mcp23018_status = i2c_write(OLATA); if (mcp23018_status) goto out;
109 mcp23018_status = i2c_write(0b11111111
110 & ~(ergodox_left_led_3<<LEFT_LED_3_SHIFT)
111 ); if (mcp23018_status) goto out;
112 mcp23018_status = i2c_write(0b11111111
113 & ~(ergodox_left_led_2<<LEFT_LED_2_SHIFT)
114 & ~(ergodox_left_led_1<<LEFT_LED_1_SHIFT)
115 ); if (mcp23018_status) goto out;
116
117out:
118 i2c_stop();
119 return mcp23018_status;
120}
121
diff --git a/keyboard/ergodox/ergodox.h b/keyboard/ergodox/ergodox.h
new file mode 100644
index 000000000..9d0691dfe
--- /dev/null
+++ b/keyboard/ergodox/ergodox.h
@@ -0,0 +1,145 @@
1#ifndef PLANCK_H
2#define PLANCK_H
3
4#include "matrix.h"
5#include "keymap_common.h"
6#include "backlight.h"
7#include <stddef.h>
8#include <stdint.h>
9#include <stdbool.h>
10#include <avr/io.h>
11#include "i2cmaster.h"
12#include <util/delay.h>
13
14#define CPU_PRESCALE(n) (CLKPR = 0x80, CLKPR = (n))
15#define CPU_16MHz 0x00
16
17// I2C aliases and register addresses (see "mcp23018.md")
18#define I2C_ADDR 0b0100000
19#define I2C_ADDR_WRITE ( (I2C_ADDR<<1) | I2C_WRITE )
20#define I2C_ADDR_READ ( (I2C_ADDR<<1) | I2C_READ )
21#define IODIRA 0x00 // i/o direction register
22#define IODIRB 0x01
23#define GPPUA 0x0C // GPIO pull-up resistor register
24#define GPPUB 0x0D
25#define GPIOA 0x12 // general purpose i/o port register (write modifies OLAT)
26#define GPIOB 0x13
27#define OLATA 0x14 // output latch register
28#define OLATB 0x15
29
30extern uint8_t mcp23018_status;
31
32void init_ergodox(void);
33void ergodox_blink_all_leds(void);
34uint8_t init_mcp23018(void);
35uint8_t ergodox_left_leds_update(void);
36
37#define LED_BRIGHTNESS_LO 31
38#define LED_BRIGHTNESS_HI 255
39
40#define LEFT_LED_1_SHIFT 7 // in MCP23018 port B
41#define LEFT_LED_2_SHIFT 6 // in MCP23018 port B
42#define LEFT_LED_3_SHIFT 7 // in MCP23018 port A
43
44extern bool ergodox_left_led_1; // left top
45extern bool ergodox_left_led_2; // left middle
46extern bool ergodox_left_led_3; // left bottom
47
48inline void ergodox_board_led_on(void) { DDRD |= (1<<6); PORTD |= (1<<6); }
49inline void ergodox_right_led_1_on(void) { DDRB |= (1<<5); PORTB |= (1<<5); }
50inline void ergodox_right_led_2_on(void) { DDRB |= (1<<6); PORTB |= (1<<6); }
51inline void ergodox_right_led_3_on(void) { DDRB |= (1<<7); PORTB |= (1<<7); }
52inline void ergodox_left_led_1_on(void) { ergodox_left_led_1 = 1; }
53inline void ergodox_left_led_2_on(void) { ergodox_left_led_2 = 1; }
54inline void ergodox_left_led_3_on(void) { ergodox_left_led_3 = 1; }
55
56inline void ergodox_board_led_off(void) { DDRD &= ~(1<<6); PORTD &= ~(1<<6); }
57inline void ergodox_right_led_1_off(void) { DDRB &= ~(1<<5); PORTB &= ~(1<<5); }
58inline void ergodox_right_led_2_off(void) { DDRB &= ~(1<<6); PORTB &= ~(1<<6); }
59inline void ergodox_right_led_3_off(void) { DDRB &= ~(1<<7); PORTB &= ~(1<<7); }
60inline void ergodox_left_led_1_off(void) { ergodox_left_led_1 = 0; }
61inline void ergodox_left_led_2_off(void) { ergodox_left_led_2 = 0; }
62inline void ergodox_left_led_3_off(void) { ergodox_left_led_3 = 0; }
63
64inline void ergodox_led_all_on(void)
65{
66 ergodox_board_led_on();
67 ergodox_right_led_1_on();
68 ergodox_right_led_2_on();
69 ergodox_right_led_3_on();
70 ergodox_left_led_1_on();
71 ergodox_left_led_2_on();
72 ergodox_left_led_3_on();
73 ergodox_left_leds_update();
74}
75
76inline void ergodox_led_all_off(void)
77{
78 ergodox_board_led_off();
79 ergodox_right_led_1_off();
80 ergodox_right_led_2_off();
81 ergodox_right_led_3_off();
82 ergodox_left_led_1_off();
83 ergodox_left_led_2_off();
84 ergodox_left_led_3_off();
85 ergodox_left_leds_update();
86}
87
88inline void ergodox_right_led_1_set(uint8_t n) { OCR1A = n; }
89inline void ergodox_right_led_2_set(uint8_t n) { OCR1B = n; }
90inline void ergodox_right_led_3_set(uint8_t n) { OCR1C = n; }
91
92inline void ergodox_led_all_set(uint8_t n)
93{
94 ergodox_right_led_1_set(n);
95 ergodox_right_led_2_set(n);
96 ergodox_right_led_3_set(n);
97}
98
99#define KEYMAP( \
100 \
101 /* left hand, spatial positions */ \
102 k00,k01,k02,k03,k04,k05,k06, \
103 k10,k11,k12,k13,k14,k15,k16, \
104 k20,k21,k22,k23,k24,k25, \
105 k30,k31,k32,k33,k34,k35,k36, \
106 k40,k41,k42,k43,k44, \
107 k55,k56, \
108 k54, \
109 k53,k52,k51, \
110 \
111 /* right hand, spatial positions */ \
112 k07,k08,k09,k0A,k0B,k0C,k0D, \
113 k17,k18,k19,k1A,k1B,k1C,k1D, \
114 k28,k29,k2A,k2B,k2C,k2D, \
115 k37,k38,k39,k3A,k3B,k3C,k3D, \
116 k49,k4A,k4B,k4C,k4D, \
117 k57,k58, \
118 k59, \
119 k5C,k5B,k5A ) \
120 \
121 /* matrix positions */ \
122 { \
123 { k00, k10, k20, k30, k40, KC_NO }, \
124 { k01, k11, k21, k31, k41, k51 }, \
125 { k02, k12, k22, k32, k42, k52 }, \
126 { k03, k13, k23, k33, k43, k53 }, \
127 { k04, k14, k24, k34, k44, k54 }, \
128 { k05, k15, k25, k35, KC_NO, k55 }, \
129 { k06, k16, KC_NO, k36, KC_NO, k56 }, \
130 \
131 { k07, k17, KC_NO, k37,KC_NO, k57 }, \
132 { k08, k18, k28, k38,KC_NO, k58 }, \
133 { k09, k19, k29, k39, k49, k59 }, \
134 { k0A, k1A, k2A, k3A, k4A, k5A }, \
135 { k0B, k1B, k2B, k3B, k4B, k5B }, \
136 { k0C, k1C, k2C, k3C, k4C, k5C }, \
137 { k0D, k1D, k2D, k3D, k4D, KC_NO } \
138 }
139
140void * matrix_init_user(void);
141void * matrix_scan_user(void);
142
143
144
145#endif \ No newline at end of file
diff --git a/keyboard/ergodox/i2cmaster.h b/keyboard/ergodox/i2cmaster.h
new file mode 100644
index 000000000..3917b9e6c
--- /dev/null
+++ b/keyboard/ergodox/i2cmaster.h
@@ -0,0 +1,178 @@
1#ifndef _I2CMASTER_H
2#define _I2CMASTER_H 1
3/*************************************************************************
4* Title: C include file for the I2C master interface
5* (i2cmaster.S or twimaster.c)
6* Author: Peter Fleury <pfleury@gmx.ch> http://jump.to/fleury
7* File: $Id: i2cmaster.h,v 1.10 2005/03/06 22:39:57 Peter Exp $
8* Software: AVR-GCC 3.4.3 / avr-libc 1.2.3
9* Target: any AVR device
10* Usage: see Doxygen manual
11**************************************************************************/
12
13#ifdef DOXYGEN
14/**
15 @defgroup pfleury_ic2master I2C Master library
16 @code #include <i2cmaster.h> @endcode
17
18 @brief I2C (TWI) Master Software Library
19
20 Basic routines for communicating with I2C slave devices. This single master
21 implementation is limited to one bus master on the I2C bus.
22
23 This I2c library is implemented as a compact assembler software implementation of the I2C protocol
24 which runs on any AVR (i2cmaster.S) and as a TWI hardware interface for all AVR with built-in TWI hardware (twimaster.c).
25 Since the API for these two implementations is exactly the same, an application can be linked either against the
26 software I2C implementation or the hardware I2C implementation.
27
28 Use 4.7k pull-up resistor on the SDA and SCL pin.
29
30 Adapt the SCL and SDA port and pin definitions and eventually the delay routine in the module
31 i2cmaster.S to your target when using the software I2C implementation !
32
33 Adjust the CPU clock frequence F_CPU in twimaster.c or in the Makfile when using the TWI hardware implementaion.
34
35 @note
36 The module i2cmaster.S is based on the Atmel Application Note AVR300, corrected and adapted
37 to GNU assembler and AVR-GCC C call interface.
38 Replaced the incorrect quarter period delays found in AVR300 with
39 half period delays.
40
41 @author Peter Fleury pfleury@gmx.ch http://jump.to/fleury
42
43 @par API Usage Example
44 The following code shows typical usage of this library, see example test_i2cmaster.c
45
46 @code
47
48 #include <i2cmaster.h>
49
50
51 #define Dev24C02 0xA2 // device address of EEPROM 24C02, see datasheet
52
53 int main(void)
54 {
55 unsigned char ret;
56
57 i2c_init(); // initialize I2C library
58
59 // write 0x75 to EEPROM address 5 (Byte Write)
60 i2c_start_wait(Dev24C02+I2C_WRITE); // set device address and write mode
61 i2c_write(0x05); // write address = 5
62 i2c_write(0x75); // write value 0x75 to EEPROM
63 i2c_stop(); // set stop conditon = release bus
64
65
66 // read previously written value back from EEPROM address 5
67 i2c_start_wait(Dev24C02+I2C_WRITE); // set device address and write mode
68
69 i2c_write(0x05); // write address = 5
70 i2c_rep_start(Dev24C02+I2C_READ); // set device address and read mode
71
72 ret = i2c_readNak(); // read one byte from EEPROM
73 i2c_stop();
74
75 for(;;);
76 }
77 @endcode
78
79*/
80#endif /* DOXYGEN */
81
82/**@{*/
83
84#if (__GNUC__ * 100 + __GNUC_MINOR__) < 304
85#error "This library requires AVR-GCC 3.4 or later, update to newer AVR-GCC compiler !"
86#endif
87
88#include <avr/io.h>
89
90/** defines the data direction (reading from I2C device) in i2c_start(),i2c_rep_start() */
91#define I2C_READ 1
92
93/** defines the data direction (writing to I2C device) in i2c_start(),i2c_rep_start() */
94#define I2C_WRITE 0
95
96
97/**
98 @brief initialize the I2C master interace. Need to be called only once
99 @param void
100 @return none
101 */
102extern void i2c_init(void);
103
104
105/**
106 @brief Terminates the data transfer and releases the I2C bus
107 @param void
108 @return none
109 */
110extern void i2c_stop(void);
111
112
113/**
114 @brief Issues a start condition and sends address and transfer direction
115
116 @param addr address and transfer direction of I2C device
117 @retval 0 device accessible
118 @retval 1 failed to access device
119 */
120extern unsigned char i2c_start(unsigned char addr);
121
122
123/**
124 @brief Issues a repeated start condition and sends address and transfer direction
125
126 @param addr address and transfer direction of I2C device
127 @retval 0 device accessible
128 @retval 1 failed to access device
129 */
130extern unsigned char i2c_rep_start(unsigned char addr);
131
132
133/**
134 @brief Issues a start condition and sends address and transfer direction
135
136 If device is busy, use ack polling to wait until device ready
137 @param addr address and transfer direction of I2C device
138 @return none
139 */
140extern void i2c_start_wait(unsigned char addr);
141
142
143/**
144 @brief Send one byte to I2C device
145 @param data byte to be transfered
146 @retval 0 write successful
147 @retval 1 write failed
148 */
149extern unsigned char i2c_write(unsigned char data);
150
151
152/**
153 @brief read one byte from the I2C device, request more data from device
154 @return byte read from I2C device
155 */
156extern unsigned char i2c_readAck(void);
157
158/**
159 @brief read one byte from the I2C device, read is followed by a stop condition
160 @return byte read from I2C device
161 */
162extern unsigned char i2c_readNak(void);
163
164/**
165 @brief read one byte from the I2C device
166
167 Implemented as a macro, which calls either i2c_readAck or i2c_readNak
168
169 @param ack 1 send ack, request more data from device<br>
170 0 send nak, read is followed by a stop condition
171 @return byte read from I2C device
172 */
173extern unsigned char i2c_read(unsigned char ack);
174#define i2c_read(ack) (ack) ? i2c_readAck() : i2c_readNak();
175
176
177/**@}*/
178#endif
diff --git a/keyboard/ergodox/keymaps/keymap_default.c b/keyboard/ergodox/keymaps/keymap_default.c
new file mode 100644
index 000000000..7b54b481a
--- /dev/null
+++ b/keyboard/ergodox/keymaps/keymap_default.c
@@ -0,0 +1,76 @@
1#include "ergodox.h"
2#include "debug.h"
3
4#define DEFAULT_LAYER 0
5#define COLEMAK_LAYER 1
6#define DVORAK_LAYER 2
7#define LOWER_LAYER 1
8#define RAISE_LAYER 4
9
10const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
11[DEFAULT_LAYER] = KEYMAP( // layer 0 : default
12 // left hand
13 KC_EQL, KC_1, KC_2, KC_3, KC_4, KC_5, KC_ESC,
14 KC_BSLS,KC_Q, KC_W, KC_E, KC_R, KC_T, KC_FN2,
15 KC_TAB, KC_A, KC_S, KC_D, KC_F, KC_G,
16 KC_LSFT,KC_Z, KC_X, KC_C, KC_V, KC_B, KC_FN1,
17 KC_LGUI,KC_GRV, KC_BSLS,KC_LEFT,KC_RGHT,
18 KC_LCTL,KC_LALT,
19 KC_HOME,
20 KC_BSPC,KC_DEL, KC_END,
21 // right hand
22 KC_FN3, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS,
23 KC_LBRC,KC_Y, KC_U, KC_I, KC_O, KC_P, KC_RBRC,
24 KC_H, KC_J, KC_K, KC_L, KC_SCLN,KC_QUOT,
25 KC_FN1, KC_N, KC_M, KC_COMM,KC_DOT, KC_SLSH,KC_RSFT,
26 KC_LEFT,KC_DOWN,KC_UP, KC_RGHT,KC_RGUI,
27 KC_RALT,KC_RCTL,
28 KC_PGUP,
29 KC_PGDN,KC_ENT, KC_SPC
30 ),
31[LOWER_LAYER] = KEYMAP( // layer 0 : default
32 // left hand
33 KC_EQL, KC_1, KC_2, KC_3, LALT(KC_TAB), KC_5, KC_ESC,
34 KC_BSLS,KC_Q, S(KC_W), KC_E, KC_R, KC_T, KC_FN2,
35 KC_TAB, KC_A, KC_S, KC_D, KC_F, KC_G,
36 KC_LSFT,KC_Z, KC_X, KC_C, KC_V, KC_B, KC_FN1,
37 KC_LGUI,KC_GRV, KC_BSLS,KC_LEFT,KC_RGHT,
38 KC_LCTL,KC_LALT,
39 KC_HOME,
40 KC_BSPC,KC_DEL, KC_END,
41 // right hand
42 KC_FN3, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS,
43 KC_LBRC,KC_Y, KC_U, KC_I, KC_O, KC_P, KC_RBRC,
44 KC_H, KC_J, KC_K, KC_L, KC_SCLN,KC_QUOT,
45 KC_FN1, KC_N, KC_M, KC_COMM,KC_DOT, KC_SLSH,KC_RSFT,
46 KC_LEFT,KC_DOWN,KC_UP, KC_RGHT,KC_RGUI,
47 KC_RALT,KC_RCTL,
48 KC_PGUP,
49 KC_PGDN,KC_ENT, KC_SPC
50 )
51};
52
53const uint16_t PROGMEM fn_actions[] = {
54
55 [1] = ACTION_LAYER_MOMENTARY(LOWER_LAYER), // to RAISE
56 [2] = ACTION_LAYER_MOMENTARY(LOWER_LAYER), // to LOWER
57
58 [3] = ACTION_DEFAULT_LAYER_SET(DEFAULT_LAYER),
59 [4] = ACTION_DEFAULT_LAYER_SET(COLEMAK_LAYER),
60 [5] = ACTION_DEFAULT_LAYER_SET(DVORAK_LAYER),
61};
62
63const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
64{
65 // MACRODOWN only works in this function
66 switch(id) {
67 case 0:
68 if (record->event.pressed) {
69 register_code(KC_RSFT);
70 } else {
71 unregister_code(KC_RSFT);
72 }
73 break;
74 }
75 return MACRO_NONE;
76};
diff --git a/keyboard/ergodox/matrix.c b/keyboard/ergodox/matrix.c
new file mode 100644
index 000000000..cc10e2941
--- /dev/null
+++ b/keyboard/ergodox/matrix.c
@@ -0,0 +1,405 @@
1/*
2Copyright 2013 Oleg Kostyuk <cub.uanic@gmail.com>
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18/*
19 * scan matrix
20 */
21#include <stdint.h>
22#include <stdbool.h>
23#include <avr/io.h>
24#include <util/delay.h>
25#include "action_layer.h"
26#include "print.h"
27#include "debug.h"
28#include "util.h"
29#include "matrix.h"
30#include "ergodox.h"
31#include "i2cmaster.h"
32#ifdef DEBUG_MATRIX_SCAN_RATE
33#include "timer.h"
34#endif
35
36#ifndef DEBOUNCE
37# define DEBOUNCE 5
38#endif
39static uint8_t debouncing = DEBOUNCE;
40
41/* matrix state(1:on, 0:off) */
42static matrix_row_t matrix[MATRIX_ROWS];
43static matrix_row_t matrix_debouncing[MATRIX_ROWS];
44
45static matrix_row_t read_cols(uint8_t row);
46static void init_cols(void);
47static void unselect_rows();
48static void select_row(uint8_t row);
49
50static uint8_t mcp23018_reset_loop;
51
52#ifdef DEBUG_MATRIX_SCAN_RATE
53uint32_t matrix_timer;
54uint32_t matrix_scan_count;
55#endif
56
57
58__attribute__ ((weak))
59void * matrix_init_kb(void) {
60};
61
62__attribute__ ((weak))
63void * matrix_scan_kb(void) {
64};
65
66inline
67uint8_t matrix_rows(void)
68{
69 return MATRIX_ROWS;
70}
71
72inline
73uint8_t matrix_cols(void)
74{
75 return MATRIX_COLS;
76}
77
78void matrix_init(void)
79{
80 // initialize row and col
81
82 mcp23018_status = init_mcp23018();
83
84
85 unselect_rows();
86 init_cols();
87
88 // initialize matrix state: all keys off
89 for (uint8_t i=0; i < MATRIX_ROWS; i++) {
90 matrix[i] = 0;
91 matrix_debouncing[i] = 0;
92 }
93
94#ifdef DEBUG_MATRIX_SCAN_RATE
95 matrix_timer = timer_read32();
96 matrix_scan_count = 0;
97#endif
98
99 if (matrix_init_kb) {
100 (*matrix_init_kb)();
101 }
102
103}
104
105uint8_t matrix_scan(void)
106{
107 if (mcp23018_status) { // if there was an error
108 if (++mcp23018_reset_loop == 0) {
109 // since mcp23018_reset_loop is 8 bit - we'll try to reset once in 255 matrix scans
110 // this will be approx bit more frequent than once per second
111 print("trying to reset mcp23018\n");
112 mcp23018_status = init_mcp23018();
113 if (mcp23018_status) {
114 print("left side not responding\n");
115 } else {
116 print("left side attached\n");
117 ergodox_blink_all_leds();
118 }
119 }
120 }
121
122#ifdef DEBUG_MATRIX_SCAN_RATE
123 matrix_scan_count++;
124
125 uint32_t timer_now = timer_read32();
126 if (TIMER_DIFF_32(timer_now, matrix_timer)>1000) {
127 print("matrix scan frequency: ");
128 pdec(matrix_scan_count);
129 print("\n");
130
131 matrix_timer = timer_now;
132 matrix_scan_count = 0;
133 }
134#endif
135
136#ifdef KEYMAP_CUB
137 uint8_t layer = biton32(layer_state);
138
139 ergodox_board_led_off();
140 ergodox_left_led_1_off();
141 ergodox_left_led_2_off();
142 ergodox_left_led_3_off();
143 switch (layer) {
144 case 1:
145 // all
146 ergodox_left_led_1_on();
147 ergodox_left_led_2_on();
148 ergodox_left_led_3_on();
149 break;
150 case 2:
151 // blue
152 ergodox_left_led_2_on();
153 break;
154 case 8:
155 // blue and green
156 ergodox_left_led_2_on();
157 // break missed intentionally
158 case 3:
159 // green
160 ergodox_left_led_3_on();
161 break;
162 case 6:
163 ergodox_board_led_on();
164 // break missed intentionally
165 case 4:
166 case 5:
167 case 7:
168 // white
169 ergodox_left_led_1_on();
170 break;
171 case 9:
172 // white+green
173 ergodox_left_led_1_on();
174 ergodox_left_led_3_on();
175 break;
176 default:
177 // none
178 break;
179 }
180
181 mcp23018_status = ergodox_left_leds_update();
182#endif
183
184#ifdef KEYMAP_SIMON
185 uint8_t layer = biton32(layer_state);
186
187 ergodox_board_led_off();
188 switch (layer) {
189 case 0:
190// none
191
192 break;
193 default:
194 ergodox_board_led_on();
195 break;
196 }
197#endif
198
199 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
200 select_row(i);
201 matrix_row_t cols = read_cols(i);
202 if (matrix_debouncing[i] != cols) {
203 matrix_debouncing[i] = cols;
204 if (debouncing) {
205 debug("bounce!: "); debug_hex(debouncing); debug("\n");
206 }
207 debouncing = DEBOUNCE;
208 }
209 unselect_rows();
210 }
211
212 if (debouncing) {
213 if (--debouncing) {
214 _delay_ms(1);
215 } else {
216 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
217 matrix[i] = matrix_debouncing[i];
218 }
219 }
220 }
221
222
223 if (matrix_scan_kb) {
224 (*matrix_scan_kb)();
225 }
226
227 return 1;
228}
229
230bool matrix_is_modified(void)
231{
232 if (debouncing) return false;
233 return true;
234}
235
236inline
237bool matrix_is_on(uint8_t row, uint8_t col)
238{
239 return (matrix[row] & ((matrix_row_t)1<<col));
240}
241
242inline
243matrix_row_t matrix_get_row(uint8_t row)
244{
245 return matrix[row];
246}
247
248void matrix_print(void)
249{
250 print("\nr/c 0123456789ABCDEF\n");
251 for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
252 phex(row); print(": ");
253 pbin_reverse16(matrix_get_row(row));
254 print("\n");
255 }
256}
257
258uint8_t matrix_key_count(void)
259{
260 uint8_t count = 0;
261 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
262 count += bitpop16(matrix[i]);
263 }
264 return count;
265}
266
267/* Column pin configuration
268 *
269 * Teensy
270 * col: 0 1 2 3 4 5
271 * pin: F0 F1 F4 F5 F6 F7
272 *
273 * MCP23018
274 * col: 0 1 2 3 4 5
275 * pin: B5 B4 B3 B2 B1 B0
276 */
277static void init_cols(void)
278{
279 // init on mcp23018
280 // not needed, already done as part of init_mcp23018()
281
282 // init on teensy
283 // Input with pull-up(DDR:0, PORT:1)
284 DDRF &= ~(1<<7 | 1<<6 | 1<<5 | 1<<4 | 1<<1 | 1<<0);
285 PORTF |= (1<<7 | 1<<6 | 1<<5 | 1<<4 | 1<<1 | 1<<0);
286}
287
288static matrix_row_t read_cols(uint8_t row)
289{
290 if (row < 7) {
291 if (mcp23018_status) { // if there was an error
292 return 0;
293 } else {
294 uint8_t data = 0;
295 mcp23018_status = i2c_start(I2C_ADDR_WRITE); if (mcp23018_status) goto out;
296 mcp23018_status = i2c_write(GPIOB); if (mcp23018_status) goto out;
297 mcp23018_status = i2c_start(I2C_ADDR_READ); if (mcp23018_status) goto out;
298 data = i2c_readNak();
299 data = ~data;
300 out:
301 i2c_stop();
302 return data;
303 }
304 } else {
305 _delay_us(30); // without this wait read unstable value.
306 // read from teensy
307 return
308 (PINF&(1<<0) ? 0 : (1<<0)) |
309 (PINF&(1<<1) ? 0 : (1<<1)) |
310 (PINF&(1<<4) ? 0 : (1<<2)) |
311 (PINF&(1<<5) ? 0 : (1<<3)) |
312 (PINF&(1<<6) ? 0 : (1<<4)) |
313 (PINF&(1<<7) ? 0 : (1<<5)) ;
314 }
315}
316
317/* Row pin configuration
318 *
319 * Teensy
320 * row: 7 8 9 10 11 12 13
321 * pin: B0 B1 B2 B3 D2 D3 C6
322 *
323 * MCP23018
324 * row: 0 1 2 3 4 5 6
325 * pin: A0 A1 A2 A3 A4 A5 A6
326 */
327static void unselect_rows(void)
328{
329 // unselect on mcp23018
330 if (mcp23018_status) { // if there was an error
331 // do nothing
332 } else {
333 // set all rows hi-Z : 1
334 mcp23018_status = i2c_start(I2C_ADDR_WRITE); if (mcp23018_status) goto out;
335 mcp23018_status = i2c_write(GPIOA); if (mcp23018_status) goto out;
336 mcp23018_status = i2c_write( 0xFF
337 & ~(ergodox_left_led_3<<LEFT_LED_3_SHIFT)
338 ); if (mcp23018_status) goto out;
339 out:
340 i2c_stop();
341 }
342
343 // unselect on teensy
344 // Hi-Z(DDR:0, PORT:0) to unselect
345 DDRB &= ~(1<<0 | 1<<1 | 1<<2 | 1<<3);
346 PORTB &= ~(1<<0 | 1<<1 | 1<<2 | 1<<3);
347 DDRD &= ~(1<<2 | 1<<3);
348 PORTD &= ~(1<<2 | 1<<3);
349 DDRC &= ~(1<<6);
350 PORTC &= ~(1<<6);
351}
352
353static void select_row(uint8_t row)
354{
355 if (row < 7) {
356 // select on mcp23018
357 if (mcp23018_status) { // if there was an error
358 // do nothing
359 } else {
360 // set active row low : 0
361 // set other rows hi-Z : 1
362 mcp23018_status = i2c_start(I2C_ADDR_WRITE); if (mcp23018_status) goto out;
363 mcp23018_status = i2c_write(GPIOA); if (mcp23018_status) goto out;
364 mcp23018_status = i2c_write( 0xFF & ~(1<<row)
365 & ~(ergodox_left_led_3<<LEFT_LED_3_SHIFT)
366 ); if (mcp23018_status) goto out;
367 out:
368 i2c_stop();
369 }
370 } else {
371 // select on teensy
372 // Output low(DDR:1, PORT:0) to select
373 switch (row) {
374 case 7:
375 DDRB |= (1<<0);
376 PORTB &= ~(1<<0);
377 break;
378 case 8:
379 DDRB |= (1<<1);
380 PORTB &= ~(1<<1);
381 break;
382 case 9:
383 DDRB |= (1<<2);
384 PORTB &= ~(1<<2);
385 break;
386 case 10:
387 DDRB |= (1<<3);
388 PORTB &= ~(1<<3);
389 break;
390 case 11:
391 DDRD |= (1<<2);
392 PORTD &= ~(1<<3);
393 break;
394 case 12:
395 DDRD |= (1<<3);
396 PORTD &= ~(1<<3);
397 break;
398 case 13:
399 DDRC |= (1<<6);
400 PORTC &= ~(1<<6);
401 break;
402 }
403 }
404}
405
diff --git a/keyboard/ergodox/twimaster.c b/keyboard/ergodox/twimaster.c
new file mode 100644
index 000000000..f91c08e6e
--- /dev/null
+++ b/keyboard/ergodox/twimaster.c
@@ -0,0 +1,208 @@
1/*************************************************************************
2* Title: I2C master library using hardware TWI interface
3* Author: Peter Fleury <pfleury@gmx.ch> http://jump.to/fleury
4* File: $Id: twimaster.c,v 1.3 2005/07/02 11:14:21 Peter Exp $
5* Software: AVR-GCC 3.4.3 / avr-libc 1.2.3
6* Target: any AVR device with hardware TWI
7* Usage: API compatible with I2C Software Library i2cmaster.h
8**************************************************************************/
9#include <inttypes.h>
10#include <compat/twi.h>
11
12#include <i2cmaster.h>
13
14
15/* define CPU frequency in Mhz here if not defined in Makefile */
16#ifndef F_CPU
17#define F_CPU 16000000UL
18#endif
19
20/* I2C clock in Hz */
21#define SCL_CLOCK 400000L
22
23
24/*************************************************************************
25 Initialization of the I2C bus interface. Need to be called only once
26*************************************************************************/
27void i2c_init(void)
28{
29 /* initialize TWI clock
30 * minimal values in Bit Rate Register (TWBR) and minimal Prescaler
31 * bits in the TWI Status Register should give us maximal possible
32 * I2C bus speed - about 444 kHz
33 *
34 * for more details, see 20.5.2 in ATmega16/32 secification
35 */
36
37 TWSR = 0; /* no prescaler */
38 TWBR = 10; /* must be >= 10 for stable operation */
39
40}/* i2c_init */
41
42
43/*************************************************************************
44 Issues a start condition and sends address and transfer direction.
45 return 0 = device accessible, 1= failed to access device
46*************************************************************************/
47unsigned char i2c_start(unsigned char address)
48{
49 uint8_t twst;
50
51 // send START condition
52 TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
53
54 // wait until transmission completed
55 while(!(TWCR & (1<<TWINT)));
56
57 // check value of TWI Status Register. Mask prescaler bits.
58 twst = TW_STATUS & 0xF8;
59 if ( (twst != TW_START) && (twst != TW_REP_START)) return 1;
60
61 // send device address
62 TWDR = address;
63 TWCR = (1<<TWINT) | (1<<TWEN);
64
65 // wail until transmission completed and ACK/NACK has been received
66 while(!(TWCR & (1<<TWINT)));
67
68 // check value of TWI Status Register. Mask prescaler bits.
69 twst = TW_STATUS & 0xF8;
70 if ( (twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK) ) return 1;
71
72 return 0;
73
74}/* i2c_start */
75
76
77/*************************************************************************
78 Issues a start condition and sends address and transfer direction.
79 If device is busy, use ack polling to wait until device is ready
80
81 Input: address and transfer direction of I2C device
82*************************************************************************/
83void i2c_start_wait(unsigned char address)
84{
85 uint8_t twst;
86
87
88 while ( 1 )
89 {
90 // send START condition
91 TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
92
93 // wait until transmission completed
94 while(!(TWCR & (1<<TWINT)));
95
96 // check value of TWI Status Register. Mask prescaler bits.
97 twst = TW_STATUS & 0xF8;
98 if ( (twst != TW_START) && (twst != TW_REP_START)) continue;
99
100 // send device address
101 TWDR = address;
102 TWCR = (1<<TWINT) | (1<<TWEN);
103
104 // wail until transmission completed
105 while(!(TWCR & (1<<TWINT)));
106
107 // check value of TWI Status Register. Mask prescaler bits.
108 twst = TW_STATUS & 0xF8;
109 if ( (twst == TW_MT_SLA_NACK )||(twst ==TW_MR_DATA_NACK) )
110 {
111 /* device busy, send stop condition to terminate write operation */
112 TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
113
114 // wait until stop condition is executed and bus released
115 while(TWCR & (1<<TWSTO));
116
117 continue;
118 }
119 //if( twst != TW_MT_SLA_ACK) return 1;
120 break;
121 }
122
123}/* i2c_start_wait */
124
125
126/*************************************************************************
127 Issues a repeated start condition and sends address and transfer direction
128
129 Input: address and transfer direction of I2C device
130
131 Return: 0 device accessible
132 1 failed to access device
133*************************************************************************/
134unsigned char i2c_rep_start(unsigned char address)
135{
136 return i2c_start( address );
137
138}/* i2c_rep_start */
139
140
141/*************************************************************************
142 Terminates the data transfer and releases the I2C bus
143*************************************************************************/
144void i2c_stop(void)
145{
146 /* send stop condition */
147 TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
148
149 // wait until stop condition is executed and bus released
150 while(TWCR & (1<<TWSTO));
151
152}/* i2c_stop */
153
154
155/*************************************************************************
156 Send one byte to I2C device
157
158 Input: byte to be transfered
159 Return: 0 write successful
160 1 write failed
161*************************************************************************/
162unsigned char i2c_write( unsigned char data )
163{
164 uint8_t twst;
165
166 // send data to the previously addressed device
167 TWDR = data;
168 TWCR = (1<<TWINT) | (1<<TWEN);
169
170 // wait until transmission completed
171 while(!(TWCR & (1<<TWINT)));
172
173 // check value of TWI Status Register. Mask prescaler bits
174 twst = TW_STATUS & 0xF8;
175 if( twst != TW_MT_DATA_ACK) return 1;
176 return 0;
177
178}/* i2c_write */
179
180
181/*************************************************************************
182 Read one byte from the I2C device, request more data from device
183
184 Return: byte read from I2C device
185*************************************************************************/
186unsigned char i2c_readAck(void)
187{
188 TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA);
189 while(!(TWCR & (1<<TWINT)));
190
191 return TWDR;
192
193}/* i2c_readAck */
194
195
196/*************************************************************************
197 Read one byte from the I2C device, read is followed by a stop condition
198
199 Return: byte read from I2C device
200*************************************************************************/
201unsigned char i2c_readNak(void)
202{
203 TWCR = (1<<TWINT) | (1<<TWEN);
204 while(!(TWCR & (1<<TWINT)));
205
206 return TWDR;
207
208}/* i2c_readNak */
diff --git a/keyboard/planck/config.h b/keyboard/planck/config.h
index cc3a1741a..a4c711db8 100644
--- a/keyboard/planck/config.h
+++ b/keyboard/planck/config.h
@@ -18,7 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
18#ifndef CONFIG_H 18#ifndef CONFIG_H
19#define CONFIG_H 19#define CONFIG_H
20 20
21#include "config_definitions.h" 21#include "config_common.h"
22 22
23/* USB Device descriptor parameter */ 23/* USB Device descriptor parameter */
24#define VENDOR_ID 0xFEED 24#define VENDOR_ID 0xFEED
@@ -58,73 +58,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
58 keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \ 58 keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \
59) 59)
60 60
61#ifdef BLUETOOTH_ENABLE
62#ifdef __AVR_ATmega32U4__
63 #define SERIAL_UART_BAUD 9600
64 #define SERIAL_UART_DATA UDR1
65 #define SERIAL_UART_UBRR ((F_CPU/(16UL*SERIAL_UART_BAUD))-1)
66 #define SERIAL_UART_RXD_VECT USART1_RX_vect
67 #define SERIAL_UART_TXD_READY (UCSR1A&(1<<UDRE1))
68 #define SERIAL_UART_INIT() do { \
69 UBRR1L = (uint8_t) SERIAL_UART_UBRR; /* baud rate */ \
70 UBRR1H = (uint8_t) (SERIAL_UART_UBRR>>8); /* baud rate */ \
71 UCSR1B = (1<<TXEN1); /* TX: enable */ \
72 UCSR1C = (0<<UPM11) | (0<<UPM10) | /* parity: none(00), even(01), odd(11) */ \
73 (0<<UCSZ12) | (1<<UCSZ11) | (1<<UCSZ10); /* data-8bit(011) */ \
74 sei(); \
75 } while(0)
76#else
77# error "USART configuration is needed."
78#endif
79
80
81// I'm fairly sure these aren't needed, but oh well - Jack
82
83/*
84 * PS/2 Interrupt configuration
85 */
86#ifdef PS2_USE_INT
87/* uses INT1 for clock line(ATMega32U4) */
88#define PS2_CLOCK_PORT PORTD
89#define PS2_CLOCK_PIN PIND
90#define PS2_CLOCK_DDR DDRD
91#define PS2_CLOCK_BIT 1
92
93#define PS2_DATA_PORT PORTD
94#define PS2_DATA_PIN PIND
95#define PS2_DATA_DDR DDRD
96#define PS2_DATA_BIT 0
97
98#define PS2_INT_INIT() do { \
99 EICRA |= ((1<<ISC11) | \
100 (0<<ISC10)); \
101} while (0)
102#define PS2_INT_ON() do { \
103 EIMSK |= (1<<INT1); \
104} while (0)
105#define PS2_INT_OFF() do { \
106 EIMSK &= ~(1<<INT1); \
107} while (0)
108#define PS2_INT_VECT INT1_vect
109#endif
110
111/*
112 * PS/2 Busywait configuration
113 */
114#ifdef PS2_USE_BUSYWAIT
115#define PS2_CLOCK_PORT PORTD
116#define PS2_CLOCK_PIN PIND
117#define PS2_CLOCK_DDR DDRD
118#define PS2_CLOCK_BIT 1
119
120#define PS2_DATA_PORT PORTD
121#define PS2_DATA_PIN PIND
122#define PS2_DATA_DDR DDRD
123#define PS2_DATA_BIT 0
124#endif
125
126#endif
127
128/* 61/*
129 * Feature disable options 62 * Feature disable options
130 * These options are also useful to firmware size reduction. 63 * These options are also useful to firmware size reduction.
diff --git a/keyboard/planck/config_definitions.h b/keyboard/planck/config_definitions.h
deleted file mode 100644
index 2ac311265..000000000
--- a/keyboard/planck/config_definitions.h
+++ /dev/null
@@ -1,51 +0,0 @@
1#ifndef CONFIG_DEFINITIONS_H
2#define CONFIG_DEFINITIONS_H
3
4#define B0 0x20
5#define B1 0x21
6#define B2 0x22
7#define B3 0x23
8#define B4 0x24
9#define B5 0x25
10#define B6 0x26
11#define B7 0x27
12#define C0 0x30
13#define C1 0x31
14#define C2 0x32
15#define C3 0x33
16#define C4 0x34
17#define C5 0x35
18#define C6 0x36
19#define C7 0x37
20#define D0 0x40
21#define D1 0x41
22#define D2 0x42
23#define D3 0x43
24#define D4 0x44
25#define D5 0x45
26#define D6 0x46
27#define D7 0x47
28#define E0 0x50
29#define E1 0x51
30#define E2 0x52
31#define E3 0x53
32#define E4 0x54
33#define E5 0x55
34#define E6 0x56
35#define E7 0x57
36#define F0 0x60
37#define F1 0x61
38#define F2 0x62
39#define F3 0x63
40#define F4 0x64
41#define F5 0x65
42#define F6 0x66
43#define F7 0x67
44
45#define COL2ROW 0x0
46#define ROW2COL 0x1
47
48
49
50#endif
51
diff --git a/keyboard/planck/planck.c b/keyboard/planck/planck.c
index 9809a824c..b62862af0 100644
--- a/keyboard/planck/planck.c
+++ b/keyboard/planck/planck.c
@@ -1,14 +1,16 @@
1#include "planck.h" 1#include "planck.h"
2 2
3__attribute__ ((weak))
3void * matrix_init_user(void) { 4void * matrix_init_user(void) {
4 5
5}; 6};
6 7
8__attribute__ ((weak))
7void * matrix_scan_user(void) { 9void * matrix_scan_user(void) {
8 10
9}; 11};
10 12
11void *matrix_init_kb(void) { 13void * matrix_init_kb(void) {
12 #ifdef BACKLIGHT_ENABLE 14 #ifdef BACKLIGHT_ENABLE
13 backlight_init_ports(); 15 backlight_init_ports();
14 #endif 16 #endif
@@ -22,7 +24,7 @@ void *matrix_init_kb(void) {
22 } 24 }
23}; 25};
24 26
25void *matrix_scan_kb(void) { 27void * matrix_scan_kb(void) {
26 if (matrix_scan_user) { 28 if (matrix_scan_user) {
27 (*matrix_scan_user)(); 29 (*matrix_scan_user)();
28 } 30 }