diff options
Diffstat (limited to 'keyboard')
| -rw-r--r-- | keyboard/ergodox/Makefile | 139 | ||||
| -rw-r--r-- | keyboard/ergodox/README.md | 56 | ||||
| -rw-r--r-- | keyboard/ergodox/backlight.c | 61 | ||||
| -rw-r--r-- | keyboard/ergodox/config.h | 88 | ||||
| -rw-r--r-- | keyboard/ergodox/ergodox.c | 121 | ||||
| -rw-r--r-- | keyboard/ergodox/ergodox.h | 145 | ||||
| -rw-r--r-- | keyboard/ergodox/i2cmaster.h | 178 | ||||
| -rw-r--r-- | keyboard/ergodox/keymaps/keymap_default.c | 76 | ||||
| -rw-r--r-- | keyboard/ergodox/matrix.c | 405 | ||||
| -rw-r--r-- | keyboard/ergodox/twimaster.c | 208 | ||||
| -rw-r--r-- | keyboard/planck/config.h | 69 | ||||
| -rw-r--r-- | keyboard/planck/config_definitions.h | 51 | ||||
| -rw-r--r-- | keyboard/planck/planck.c | 6 |
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). | ||
| 42 | TARGET = ergodox | ||
| 43 | |||
| 44 | |||
| 45 | # Directory common source filess exist | ||
| 46 | TOP_DIR = ../.. | ||
| 47 | |||
| 48 | # Directory keyboard dependent files exist | ||
| 49 | TARGET_DIR = . | ||
| 50 | |||
| 51 | # # project specific files | ||
| 52 | SRC = ergodox.c \ | ||
| 53 | twimaster.c \ | ||
| 54 | backlight.c | ||
| 55 | |||
| 56 | ifdef KEYMAP | ||
| 57 | SRC := keymaps/keymap_$(KEYMAP).c $(SRC) | ||
| 58 | else | ||
| 59 | SRC := keymaps/keymap_default.c $(SRC) | ||
| 60 | endif | ||
| 61 | |||
| 62 | CONFIG_H = config.h | ||
| 63 | |||
| 64 | # MCU name | ||
| 65 | #MCU = at90usb1287 | ||
| 66 | MCU = 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. | ||
| 79 | F_CPU = 16000000 | ||
| 80 | |||
| 81 | |||
| 82 | # | ||
| 83 | # LUFA specific | ||
| 84 | # | ||
| 85 | # Target architecture (see library "Board Types" documentation). | ||
| 86 | ARCH = 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. | ||
| 99 | F_USB = $(F_CPU) | ||
| 100 | |||
| 101 | # Interrupt driven control endpoint task(+60) | ||
| 102 | OPT_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 | ||
| 111 | OPT_DEFS += -DBOOTLOADER_SIZE=4096 | ||
| 112 | |||
| 113 | |||
| 114 | # Build Options | ||
| 115 | # comment out to disable the options. | ||
| 116 | # | ||
| 117 | BOOTMAGIC_ENABLE = yes # Virtual DIP switch configuration(+1000) | ||
| 118 | MOUSEKEY_ENABLE = yes # Mouse keys(+4700) | ||
| 119 | EXTRAKEY_ENABLE = yes # Audio control and System control(+450) | ||
| 120 | CONSOLE_ENABLE = yes # Console for debug(+400) | ||
| 121 | COMMAND_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 | ||
| 135 | VPATH += $(TARGET_DIR) | ||
| 136 | VPATH += $(TOP_DIR) | ||
| 137 | |||
| 138 | include $(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 | |||
| 30 | Q: Where to get binaries? | ||
| 31 | A: | ||
| 32 | |||
| 33 | Q: Where to get sources? | ||
| 34 | A: | ||
| 35 | |||
| 36 | Q: How to compile? | ||
| 37 | A: | ||
| 38 | |||
| 39 | |||
| 40 | # Layouts | ||
| 41 | |||
| 42 | description 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 | |||
| 7 | void 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 | |||
| 33 | void 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 | /* | ||
| 2 | Copyright 2012 Jun Wako <wakojun@gmail.com> | ||
| 3 | Copyright 2013 Oleg Kostyuk <cub.uanic@gmail.com> | ||
| 4 | |||
| 5 | This program is free software: you can redistribute it and/or modify | ||
| 6 | it under the terms of the GNU General Public License as published by | ||
| 7 | the Free Software Foundation, either version 2 of the License, or | ||
| 8 | (at your option) any later version. | ||
| 9 | |||
| 10 | This program is distributed in the hope that it will be useful, | ||
| 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | GNU General Public License for more details. | ||
| 14 | |||
| 15 | You should have received a copy of the GNU General Public License | ||
| 16 | along 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 | |||
| 4 | bool i2c_initialized = 0; | ||
| 5 | uint8_t mcp23018_status = 0x20; | ||
| 6 | |||
| 7 | bool ergodox_left_led_1 = 0; // left top | ||
| 8 | bool ergodox_left_led_2 = 0; // left middle | ||
| 9 | bool ergodox_left_led_3 = 0; // left bottom | ||
| 10 | |||
| 11 | void * matrix_init_user(void) { | ||
| 12 | |||
| 13 | }; | ||
| 14 | |||
| 15 | void * matrix_scan_user(void) { | ||
| 16 | |||
| 17 | }; | ||
| 18 | |||
| 19 | void * 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 | |||
| 44 | void * matrix_scan_kb(void) { | ||
| 45 | |||
| 46 | if (matrix_scan_user) { | ||
| 47 | (*matrix_scan_user)(); | ||
| 48 | } | ||
| 49 | }; | ||
| 50 | |||
| 51 | |||
| 52 | void 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 | |||
| 61 | uint8_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 | |||
| 90 | out: | ||
| 91 | i2c_stop(); | ||
| 92 | |||
| 93 | if (!mcp23018_status) mcp23018_status = ergodox_left_leds_update(); | ||
| 94 | |||
| 95 | return mcp23018_status; | ||
| 96 | } | ||
| 97 | |||
| 98 | uint8_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 | |||
| 117 | out: | ||
| 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 | |||
| 30 | extern uint8_t mcp23018_status; | ||
| 31 | |||
| 32 | void init_ergodox(void); | ||
| 33 | void ergodox_blink_all_leds(void); | ||
| 34 | uint8_t init_mcp23018(void); | ||
| 35 | uint8_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 | |||
| 44 | extern bool ergodox_left_led_1; // left top | ||
| 45 | extern bool ergodox_left_led_2; // left middle | ||
| 46 | extern bool ergodox_left_led_3; // left bottom | ||
| 47 | |||
| 48 | inline void ergodox_board_led_on(void) { DDRD |= (1<<6); PORTD |= (1<<6); } | ||
| 49 | inline void ergodox_right_led_1_on(void) { DDRB |= (1<<5); PORTB |= (1<<5); } | ||
| 50 | inline void ergodox_right_led_2_on(void) { DDRB |= (1<<6); PORTB |= (1<<6); } | ||
| 51 | inline void ergodox_right_led_3_on(void) { DDRB |= (1<<7); PORTB |= (1<<7); } | ||
| 52 | inline void ergodox_left_led_1_on(void) { ergodox_left_led_1 = 1; } | ||
| 53 | inline void ergodox_left_led_2_on(void) { ergodox_left_led_2 = 1; } | ||
| 54 | inline void ergodox_left_led_3_on(void) { ergodox_left_led_3 = 1; } | ||
| 55 | |||
| 56 | inline void ergodox_board_led_off(void) { DDRD &= ~(1<<6); PORTD &= ~(1<<6); } | ||
| 57 | inline void ergodox_right_led_1_off(void) { DDRB &= ~(1<<5); PORTB &= ~(1<<5); } | ||
| 58 | inline void ergodox_right_led_2_off(void) { DDRB &= ~(1<<6); PORTB &= ~(1<<6); } | ||
| 59 | inline void ergodox_right_led_3_off(void) { DDRB &= ~(1<<7); PORTB &= ~(1<<7); } | ||
| 60 | inline void ergodox_left_led_1_off(void) { ergodox_left_led_1 = 0; } | ||
| 61 | inline void ergodox_left_led_2_off(void) { ergodox_left_led_2 = 0; } | ||
| 62 | inline void ergodox_left_led_3_off(void) { ergodox_left_led_3 = 0; } | ||
| 63 | |||
| 64 | inline 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 | |||
| 76 | inline 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 | |||
| 88 | inline void ergodox_right_led_1_set(uint8_t n) { OCR1A = n; } | ||
| 89 | inline void ergodox_right_led_2_set(uint8_t n) { OCR1B = n; } | ||
| 90 | inline void ergodox_right_led_3_set(uint8_t n) { OCR1C = n; } | ||
| 91 | |||
| 92 | inline 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 | |||
| 140 | void * matrix_init_user(void); | ||
| 141 | void * 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 | */ | ||
| 102 | extern 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 | */ | ||
| 110 | extern 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 | */ | ||
| 120 | extern 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 | */ | ||
| 130 | extern 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 | */ | ||
| 140 | extern 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 | */ | ||
| 149 | extern 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 | */ | ||
| 156 | extern 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 | */ | ||
| 162 | extern 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 | */ | ||
| 173 | extern 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 | |||
| 10 | const 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 | |||
| 53 | const 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 | |||
| 63 | const 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 | /* | ||
| 2 | Copyright 2013 Oleg Kostyuk <cub.uanic@gmail.com> | ||
| 3 | |||
| 4 | This program is free software: you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation, either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along 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 | ||
| 39 | static uint8_t debouncing = DEBOUNCE; | ||
| 40 | |||
| 41 | /* matrix state(1:on, 0:off) */ | ||
| 42 | static matrix_row_t matrix[MATRIX_ROWS]; | ||
| 43 | static matrix_row_t matrix_debouncing[MATRIX_ROWS]; | ||
| 44 | |||
| 45 | static matrix_row_t read_cols(uint8_t row); | ||
| 46 | static void init_cols(void); | ||
| 47 | static void unselect_rows(); | ||
| 48 | static void select_row(uint8_t row); | ||
| 49 | |||
| 50 | static uint8_t mcp23018_reset_loop; | ||
| 51 | |||
| 52 | #ifdef DEBUG_MATRIX_SCAN_RATE | ||
| 53 | uint32_t matrix_timer; | ||
| 54 | uint32_t matrix_scan_count; | ||
| 55 | #endif | ||
| 56 | |||
| 57 | |||
| 58 | __attribute__ ((weak)) | ||
| 59 | void * matrix_init_kb(void) { | ||
| 60 | }; | ||
| 61 | |||
| 62 | __attribute__ ((weak)) | ||
| 63 | void * matrix_scan_kb(void) { | ||
| 64 | }; | ||
| 65 | |||
| 66 | inline | ||
| 67 | uint8_t matrix_rows(void) | ||
| 68 | { | ||
| 69 | return MATRIX_ROWS; | ||
| 70 | } | ||
| 71 | |||
| 72 | inline | ||
| 73 | uint8_t matrix_cols(void) | ||
| 74 | { | ||
| 75 | return MATRIX_COLS; | ||
| 76 | } | ||
| 77 | |||
| 78 | void 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 | |||
| 105 | uint8_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 | |||
| 230 | bool matrix_is_modified(void) | ||
| 231 | { | ||
| 232 | if (debouncing) return false; | ||
| 233 | return true; | ||
| 234 | } | ||
| 235 | |||
| 236 | inline | ||
| 237 | bool matrix_is_on(uint8_t row, uint8_t col) | ||
| 238 | { | ||
| 239 | return (matrix[row] & ((matrix_row_t)1<<col)); | ||
| 240 | } | ||
| 241 | |||
| 242 | inline | ||
| 243 | matrix_row_t matrix_get_row(uint8_t row) | ||
| 244 | { | ||
| 245 | return matrix[row]; | ||
| 246 | } | ||
| 247 | |||
| 248 | void 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 | |||
| 258 | uint8_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 | */ | ||
| 277 | static 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 | |||
| 288 | static 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 | */ | ||
| 327 | static 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 | |||
| 353 | static 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 | *************************************************************************/ | ||
| 27 | void 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 | *************************************************************************/ | ||
| 47 | unsigned 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 | *************************************************************************/ | ||
| 83 | void 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 | *************************************************************************/ | ||
| 134 | unsigned 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 | *************************************************************************/ | ||
| 144 | void 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 | *************************************************************************/ | ||
| 162 | unsigned 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 | *************************************************************************/ | ||
| 186 | unsigned 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 | *************************************************************************/ | ||
| 201 | unsigned 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)) | ||
| 3 | void * matrix_init_user(void) { | 4 | void * matrix_init_user(void) { |
| 4 | 5 | ||
| 5 | }; | 6 | }; |
| 6 | 7 | ||
| 8 | __attribute__ ((weak)) | ||
| 7 | void * matrix_scan_user(void) { | 9 | void * matrix_scan_user(void) { |
| 8 | 10 | ||
| 9 | }; | 11 | }; |
| 10 | 12 | ||
| 11 | void *matrix_init_kb(void) { | 13 | void * 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 | ||
| 25 | void *matrix_scan_kb(void) { | 27 | void * matrix_scan_kb(void) { |
| 26 | if (matrix_scan_user) { | 28 | if (matrix_scan_user) { |
| 27 | (*matrix_scan_user)(); | 29 | (*matrix_scan_user)(); |
| 28 | } | 30 | } |
