5x5
This commit is contained in:
parent
9c5db97f32
commit
36c5a8f8ca
171
keyboard/25/Makefile
Normal file
171
keyboard/25/Makefile
Normal file
@ -0,0 +1,171 @@
|
||||
#----------------------------------------------------------------------------
|
||||
# On command line:
|
||||
#
|
||||
# make all = Make software.
|
||||
#
|
||||
# make clean = Clean out built project files.
|
||||
#
|
||||
# make coff = Convert ELF to AVR COFF.
|
||||
#
|
||||
# make extcoff = Convert ELF to AVR Extended COFF.
|
||||
#
|
||||
# make program = Download the hex file to the device.
|
||||
# Please customize your programmer settings(PROGRAM_CMD)
|
||||
#
|
||||
# make teensy = Download the hex file to the device, using teensy_loader_cli.
|
||||
# (must have teensy_loader_cli installed).
|
||||
#
|
||||
# make dfu = Download the hex file to the device, using dfu-programmer (must
|
||||
# have dfu-programmer installed).
|
||||
#
|
||||
# make flip = Download the hex file to the device, using Atmel FLIP (must
|
||||
# have Atmel FLIP installed).
|
||||
#
|
||||
# make dfu-ee = Download the eeprom file to the device, using dfu-programmer
|
||||
# (must have dfu-programmer installed).
|
||||
#
|
||||
# make flip-ee = Download the eeprom file to the device, using Atmel FLIP
|
||||
# (must have Atmel FLIP installed).
|
||||
#
|
||||
# make debug = Start either simulavr or avarice as specified for debugging,
|
||||
# with avr-gdb or avr-insight as the front end for debugging.
|
||||
#
|
||||
# make filename.s = Just compile filename.c into the assembler code only.
|
||||
#
|
||||
# make filename.i = Create a preprocessed source file for use in submitting
|
||||
# bug reports to the GCC project.
|
||||
#
|
||||
# To rebuild project do "make clean" then "make all".
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
# Target file name (without extension).
|
||||
TARGET = 25
|
||||
|
||||
# Directory common source filess exist
|
||||
TMK_DIR = ../../tmk_core
|
||||
|
||||
# Directory keyboard dependent files exist
|
||||
TARGET_DIR = .
|
||||
|
||||
# project specific files
|
||||
SRC = matrix.c \
|
||||
i2c.c \
|
||||
serial.c \
|
||||
split-util.c \
|
||||
led.c
|
||||
|
||||
CONFIG_H = config.h
|
||||
|
||||
# MCU name
|
||||
MCU = atmega32u4
|
||||
|
||||
COM_PORT=/dev/ttyACM0
|
||||
PROGRAM_CMD=sleep 3; avrdude -p atmega32u4 -P $(COM_PORT) -c avr109 -U flash:w:$(TARGET).hex
|
||||
|
||||
# Processor frequency.
|
||||
# This will define a symbol, F_CPU, in all source code files equal to the
|
||||
# processor frequency in Hz. You can then use this symbol in your source code to
|
||||
# calculate timings. Do NOT tack on a 'UL' at the end, this will be done
|
||||
# automatically to create a 32-bit value in your source code.
|
||||
#
|
||||
# This will be an integer division of F_USB below, as it is sourced by
|
||||
# F_USB after it has run through any CPU prescalers. Note that this value
|
||||
# does not *change* the processor frequency - it should merely be updated to
|
||||
# reflect the processor speed set externally so that the code can use accurate
|
||||
# software delays.
|
||||
F_CPU = 16000000
|
||||
|
||||
|
||||
#
|
||||
# LUFA specific
|
||||
#
|
||||
# Target architecture (see library "Board Types" documentation).
|
||||
ARCH = AVR8
|
||||
|
||||
# Input clock frequency.
|
||||
# This will define a symbol, F_USB, in all source code files equal to the
|
||||
# input clock frequency (before any prescaling is performed) in Hz. This value may
|
||||
# differ from F_CPU if prescaling is used on the latter, and is required as the
|
||||
# raw input clock is fed directly to the PLL sections of the AVR for high speed
|
||||
# clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL'
|
||||
# at the end, this will be done automatically to create a 32-bit value in your
|
||||
# source code.
|
||||
#
|
||||
# If no clock division is performed on the input clock inside the AVR (via the
|
||||
# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU.
|
||||
F_USB = $(F_CPU)
|
||||
|
||||
# Interrupt driven control endpoint task(+60)
|
||||
OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
|
||||
|
||||
|
||||
# Boot Section Size in *bytes*
|
||||
# Teensy halfKay 512
|
||||
# Teensy++ halfKay 1024
|
||||
# Atmel DFU loader 4096
|
||||
# LUFA bootloader 4096
|
||||
# USBaspLoader 2048
|
||||
OPT_DEFS += -DBOOTLOADER_SIZE=4096
|
||||
|
||||
# Changes some bootmagic settings for when the space is on the left half
|
||||
OPT_DEFS += -DSPACE_ON_LEFT_HALF
|
||||
|
||||
# # Use I2C for communication between the halves of the keyboard
|
||||
# OPT_DEFS += -DUSE_I2C
|
||||
|
||||
# Build Options
|
||||
# comment out to disable the options.
|
||||
#
|
||||
BOOTMAGIC_ENABLE = yes # Virtual DIP switch configuration(+1000)
|
||||
MOUSEKEY_ENABLE = yes # Mouse keys(+4700)
|
||||
EXTRAKEY_ENABLE = yes # Audio control and System control(+450)
|
||||
CONSOLE_ENABLE = yes # Console for debug(+400)
|
||||
COMMAND_ENABLE = yes # Commands for debug and configuration
|
||||
SLEEP_LED_ENABLE = yes # Breathing sleep LED during USB suspend
|
||||
NKRO_ENABLE = yes # USB Nkey Rollover
|
||||
ACTIONMAP_ENABLE = yes # Use 16bit action codes in keymap instead of 8bit keycodes
|
||||
|
||||
|
||||
ifdef ACTIONMAP_ENABLE
|
||||
KEYMAP_FILE = actionmap
|
||||
else
|
||||
KEYMAP_FILE = keymap
|
||||
SRC := keymap_common.c $(SRC)
|
||||
endif
|
||||
ifdef KEYMAP
|
||||
SRC := $(KEYMAP_FILE)_$(KEYMAP).c $(SRC)
|
||||
else
|
||||
SRC := $(KEYMAP_FILE)_plain.c $(SRC)
|
||||
endif
|
||||
|
||||
|
||||
#PS2_MOUSE_ENABLE = yes # PS/2 mouse(TrackPoint) support
|
||||
#PS2_USE_BUSYWAIT = yes # uses primitive reference code
|
||||
#PS2_USE_INT = yes # uses external interrupt for falling edge of PS/2 clock pin
|
||||
#PS2_USE_USART = yes # uses hardware USART engine for PS/2 signal receive(recomened)
|
||||
|
||||
|
||||
# Search Path
|
||||
VPATH += $(TARGET_DIR)
|
||||
VPATH += $(TMK_DIR)
|
||||
|
||||
# Un comment this line if you want to use pjrc protocol
|
||||
# include $(TMK_DIR)/protocol/pjrc.mk
|
||||
|
||||
include $(TMK_DIR)/protocol/lufa.mk
|
||||
include $(TMK_DIR)/common.mk
|
||||
include $(TMK_DIR)/rules.mk
|
||||
|
||||
|
||||
debug-on: EXTRAFLAGS += -DDEBUG -DDEBUG_ACTION
|
||||
debug-on: all
|
||||
|
||||
debug-off: EXTRAFLAGS += -DNO_DEBUG -DNO_PRINT
|
||||
debug-off: OPT_DEFS := $(filter-out -DCONSOLE_ENABLE,$(OPT_DEFS))
|
||||
debug-off: all
|
||||
|
||||
eeprom-left:
|
||||
sleep 3; avrdude -p atmega32u4 -P $(COM_PORT) -c avr109 -U eeprom:w:eeprom-lefthand.eep
|
||||
|
||||
eeprom-right:
|
||||
sleep 3; avrdude -p atmega32u4 -P $(COM_PORT) -c avr109 -U eeprom:w:eeprom-righthand.eep
|
104
keyboard/25/README.md
Normal file
104
keyboard/25/README.md
Normal file
@ -0,0 +1,104 @@
|
||||
This is a modification of the TMK firmware by ahtn found here https://github.com/ahtn/tmk_keyboard/tree/master/keyboard/split_keyboard
|
||||
|
||||
COL_PINS { F4, F5, F6, F7, B1 }
|
||||
|
||||
ROW_PINS { D4, C6, D7, E6, B4 }
|
||||
|
||||
|
||||
Custom split keyboard firmware
|
||||
======
|
||||
|
||||
Split keyboard firmware for Arduino Pro Micro or other ATmega32u4
|
||||
based boards.
|
||||
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
Some features supported by the firmware:
|
||||
|
||||
* Either half can connect to the computer via USB, or both halves can be used
|
||||
independently.
|
||||
* You only need 3 wires to connect the two halves. Two for VCC and GND and one
|
||||
for serial communication.
|
||||
* Optional support for I2C connection between the two halves if for some
|
||||
reason you require a faster connection between the two halves. Note this
|
||||
requires an extra wire between halves and pull-up resistors on the data lines.
|
||||
|
||||
Required Hardware
|
||||
-----------------
|
||||
|
||||
Apart from diodes and key switches for the keyboard matrix in each half, you
|
||||
will need:
|
||||
|
||||
* 2 Arduino Pro Micro's. You can find theses on aliexpress for ≈3.50USD each.
|
||||
* 2 TRS sockets
|
||||
* 1 TRS cable.
|
||||
|
||||
Alternatively, you can use any sort of cable and socket that has at least 3
|
||||
wires. If you want to use I2C to communicate between halves, you will need a
|
||||
cable with at least 4 wires and 2x 4.7kΩ pull-up resistors
|
||||
|
||||
|
||||
Wiring
|
||||
------
|
||||
|
||||
The 3 wires of the TRS cable need to connect GND, VCC, and digital pin 3 (i.e.
|
||||
`PD0` on the ATmega32u4) between the two Pro Micros.
|
||||
|
||||
Then wire your key matrix to any of the remaining 17 IO pins of the pro micro
|
||||
and modify the `MATRIX_COL_PINS` and `MATRIX_ROW_PINS` in `config.h` accordingly.
|
||||
|
||||
The wiring for serial:
|
||||
|
||||
![serial wiring](imgs/split-keyboard-serial-schematic.png)
|
||||
|
||||
The wiring for i2c:
|
||||
|
||||
![i2c wiring](imgs/split-keyboard-i2c-schematic.png)
|
||||
|
||||
The pull-up resistors may be placed on either half. It is also possible
|
||||
to use 4 resistors and have the pull-ups in both halves, but this is
|
||||
unnecessary in simple use cases.
|
||||
|
||||
Notes on Software Configuration
|
||||
-------------------------------
|
||||
|
||||
Configuring the firmware is similar to any other TMK project. One thing
|
||||
to note is that `MATIX_ROWS` in `config.h` is the total number of rows between
|
||||
the two halves, i.e. if your split keyboard has 4 rows in each half, then
|
||||
`MATRIX_ROWS=8`.
|
||||
|
||||
Also the current implementation assumes a maximum of 8 columns, but it would
|
||||
not be very difficult to adapt it to support more if required.
|
||||
|
||||
|
||||
Flashing
|
||||
--------
|
||||
|
||||
Before you go to flash the program memory for the first time, you will need to
|
||||
EEPROM for the left and right halves. The EEPROM is used to store whether the
|
||||
half is left handed or right handed. This makes it so that the same firmware
|
||||
file will run on both hands instead of having to flash left and right handed
|
||||
versions of the firmware to each half. To flash the EEPROM file for the left
|
||||
half run:
|
||||
```
|
||||
make eeprom-left
|
||||
```
|
||||
and similarly for right half
|
||||
```
|
||||
make eeprom-right
|
||||
```
|
||||
|
||||
After you have flashed the EEPROM for the first time, you then need to program
|
||||
the flash memory:
|
||||
```
|
||||
make program
|
||||
```
|
||||
Note that you need to program both halves, but you have the option of using
|
||||
different keymaps for each half. You could program the left half with a QWERTY
|
||||
layout and the right half with a Colemak layout. Then if you connect the left
|
||||
half to a computer by USB the keyboard will use QWERTY and Colemak when the
|
||||
right half is connected.
|
||||
|
||||
|
29
keyboard/25/actionmap_common.h
Normal file
29
keyboard/25/actionmap_common.h
Normal file
@ -0,0 +1,29 @@
|
||||
#ifndef ACTIONMAP_COMMON_H
|
||||
#define ACTIONMAP_COMMON_H
|
||||
|
||||
#define ACTIONMAP( \
|
||||
K00, K01, K02, K03, K04, \
|
||||
K10, K11, K12, K13, K14, \
|
||||
K20, K21, K22, K23, K24, \
|
||||
K30, K31, K32, K33, K34, \
|
||||
K40, K41, K42, K43, K44, \
|
||||
\
|
||||
K50, K51, K52, K53, K54, \
|
||||
K60, K61, K62, K63, K64, \
|
||||
K70, K71, K72, K73, K74, \
|
||||
K80, K81, K82, K83, K84, \
|
||||
K90, K91, K92, K93, K94 \
|
||||
) { \
|
||||
{ AC_##K00, AC_##K01, AC_##K02, AC_##K03, AC_##K04 }, \
|
||||
{ AC_##K10, AC_##K11, AC_##K12, AC_##K13, AC_##K14 }, \
|
||||
{ AC_##K20, AC_##K21, AC_##K22, AC_##K23, AC_##K24 }, \
|
||||
{ AC_##K30, AC_##K31, AC_##K32, AC_##K33, AC_##K34 }, \
|
||||
{ AC_##K40, AC_##K41, AC_##K42, AC_##K43, AC_##K44 }, \
|
||||
\
|
||||
{ AC_##K54, AC_##K53, AC_##K52, AC_##K51, AC_##K50 }, \
|
||||
{ AC_##K64, AC_##K63, AC_##K62, AC_##K61, AC_##K60 }, \
|
||||
{ AC_##K74, AC_##K73, AC_##K72, AC_##K71, AC_##K70 }, \
|
||||
{ AC_##K84, AC_##K83, AC_##K82, AC_##K81, AC_##K80 }, \
|
||||
{ AC_##K94, AC_##K93, AC_##K92, AC_##K91, AC_##K90 } \
|
||||
}
|
||||
#endif
|
121
keyboard/25/actionmap_plain.c
Normal file
121
keyboard/25/actionmap_plain.c
Normal file
@ -0,0 +1,121 @@
|
||||
#include "actionmap.h"
|
||||
#include "action_code.h"
|
||||
#include "actionmap_common.h"
|
||||
|
||||
|
||||
/*
|
||||
* Actions
|
||||
*/
|
||||
#define AC_BLD ACTION_BACKLIGHT_DECREASE()
|
||||
#define AC_BLI ACTION_BACKLIGHT_INCREASE()
|
||||
#define AC_TL1 ACTION_LAYER_TAP_KEY(1, KC_SPACE)
|
||||
#define AC_TL2 ACTION_LAYER_TAP_KEY(2, KC_BSPACE)
|
||||
#define AC_TL3 ACTION_LAYER_TAP_KEY(3, KC_C)
|
||||
#define AC_TL4 ACTION_LAYER_TAP_KEY(4, KC_V)
|
||||
#define AC_TL5 ACTION_LAYER_TAP_KEY(5, KC_B)
|
||||
#define AC_TM1 ACTION_MODS_TAP_KEY(MOD_RSFT, KC_ENT)
|
||||
#define AC_TM2 ACTION_MODS_TAP_KEY(MOD_LCTL, KC_Z)
|
||||
#define AC_TM3 ACTION_MODS_TAP_KEY(MOD_LALT, KC_X)
|
||||
#define AC_TM4 ACTION_MODS_TAP_KEY(MOD_RALT, KC_N)
|
||||
#define AC_TM5 ACTION_MODS_TAP_KEY(MOD_RCTL, KC_M)
|
||||
#define AC_S01 ACTION_MODS_KEY(MOD_LSFT, KC_1)
|
||||
#define AC_S02 ACTION_MODS_KEY(MOD_LSFT, KC_2)
|
||||
#define AC_S03 ACTION_MODS_KEY(MOD_LSFT, KC_3)
|
||||
#define AC_S04 ACTION_MODS_KEY(MOD_LSFT, KC_4)
|
||||
#define AC_S05 ACTION_MODS_KEY(MOD_LSFT, KC_5)
|
||||
#define AC_S06 ACTION_MODS_KEY(MOD_LSFT, KC_6)
|
||||
#define AC_S07 ACTION_MODS_KEY(MOD_LSFT, KC_7)
|
||||
#define AC_S08 ACTION_MODS_KEY(MOD_LSFT, KC_8)
|
||||
#define AC_S09 ACTION_MODS_KEY(MOD_LSFT, KC_9)
|
||||
#define AC_S10 ACTION_MODS_KEY(MOD_LSFT, KC_0)
|
||||
#define AC_S11 ACTION_MODS_KEY(MOD_LSFT, KC_MINS)
|
||||
#define AC_S12 ACTION_MODS_KEY(MOD_LSFT, KC_EQL)
|
||||
#define AC_S13 ACTION_MODS_KEY(MOD_LSFT, KC_LBRC)
|
||||
#define AC_S14 ACTION_MODS_KEY(MOD_LSFT, KC_RBRC)
|
||||
#define AC_S15 ACTION_MODS_KEY(MOD_LSFT, KC_BSLS)
|
||||
#define AC_S16 ACTION_MODS_KEY(MOD_LSFT, KC_COMM)
|
||||
#define AC_S17 ACTION_MODS_KEY(MOD_LSFT, KC_DOT)
|
||||
#define AC_S18 ACTION_MODS_KEY(MOD_LSFT, KC_SLSH)
|
||||
#define AC_S19 ACTION_MODS_KEY(MOD_LSFT, KC_SCLN)
|
||||
#define AC_S20 ACTION_MODS_KEY(MOD_LSFT, KC_QUOT)
|
||||
|
||||
const action_t PROGMEM actionmaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||
[0] = ACTIONMAP(
|
||||
F1, F2, F3, F4, F5,
|
||||
1, 2, 3, 4, 5,
|
||||
Q, W, E, R, T,
|
||||
A, S, D, F, G,
|
||||
TM2, TM3, TL3, TL4, TL2,
|
||||
|
||||
F6, F7, F8, F9, F10,
|
||||
6, 7, 8, 9, 0,
|
||||
Y, U, I, O, P,
|
||||
H, J, K, L, ESC,
|
||||
TL1, TL5, TM4, TM5, TM1),
|
||||
|
||||
[1] = ACTIONMAP(
|
||||
TRNS, TRNS, TRNS, TRNS, TRNS,
|
||||
TRNS, TRNS, TRNS, TRNS, TRNS,
|
||||
1, 2, 3, 4, 5,
|
||||
F1, F2, F3, F4, F5,
|
||||
TRNS, TRNS, TRNS, TRNS, DEL,
|
||||
|
||||
TRNS, TRNS, TRNS, TRNS, TRNS,
|
||||
TRNS, TRNS, TRNS, TRNS, TRNS,
|
||||
6, 7, 8, 9, 0,
|
||||
F6, F7, F8, F9, F10,
|
||||
TRNS, TRNS, TRNS, TRNS, TRNS),
|
||||
|
||||
[2] = ACTIONMAP(
|
||||
TRNS, TRNS, TRNS, TRNS, TRNS,
|
||||
TRNS, TRNS, TRNS, TRNS, TRNS,
|
||||
S01, S02, S03, S04, S05,
|
||||
F11, F12, TRNS, TRNS, TRNS,
|
||||
TRNS, TRNS, TRNS, TRNS, TRNS,
|
||||
|
||||
TRNS, TRNS, TRNS, TRNS, TRNS,
|
||||
TRNS, TRNS, TRNS, TRNS, TRNS,
|
||||
S06, S07, S08, S09, S10,
|
||||
TRNS, TRNS, TRNS, TRNS, GRV,
|
||||
TRNS, TRNS, TRNS, TRNS, TRNS),
|
||||
|
||||
[3] = ACTIONMAP(
|
||||
TRNS, TRNS, TRNS, TRNS, TRNS,
|
||||
TRNS, TRNS, TRNS, TRNS, TRNS,
|
||||
TRNS, TRNS, TRNS, TRNS, TRNS,
|
||||
TAB, TRNS, TRNS, TRNS, TRNS,
|
||||
TRNS, TRNS, TRNS, TRNS, TRNS,
|
||||
|
||||
TRNS, TRNS, TRNS, TRNS, TRNS,
|
||||
TRNS, TRNS, TRNS, TRNS, TRNS,
|
||||
MINS, EQL, LBRC, RBRC, BSLS,
|
||||
COMM, DOT, SLSH, SCLN, QUOT,
|
||||
TRNS, LEFT, DOWN, UP, RGHT),
|
||||
|
||||
[4] = ACTIONMAP(
|
||||
TRNS, TRNS, TRNS, TRNS, TRNS,
|
||||
TRNS, TRNS, TRNS, TRNS, TRNS,
|
||||
TRNS, TRNS, TRNS, TRNS, TRNS,
|
||||
TAB, TRNS, TRNS, TRNS, TRNS,
|
||||
TRNS, TRNS, TRNS, TRNS, TRNS,
|
||||
|
||||
TRNS, TRNS, TRNS, TRNS, TRNS,
|
||||
TRNS, TRNS, TRNS, TRNS, TRNS,
|
||||
S11, S12, S13, S14, S15,
|
||||
S16, S17, S18, S19, S20,
|
||||
TRNS, HOME, PGDN, PGUP, END),
|
||||
|
||||
[5] = ACTIONMAP(
|
||||
TRNS, TRNS, TRNS, TRNS, TRNS,
|
||||
TRNS, TRNS, TRNS, TRNS, TRNS,
|
||||
CALC, WHOM, MAIL, MYCM, TRNS,
|
||||
TRNS, TRNS, TRNS, TRNS, TRNS,
|
||||
TRNS, TRNS, TRNS, TRNS, BTLD,
|
||||
|
||||
TRNS, TRNS, TRNS, TRNS, TRNS,
|
||||
TRNS, TRNS, TRNS, TRNS, TRNS,
|
||||
TRNS, TRNS, TRNS, TRNS, PSCR,
|
||||
TRNS, TRNS, TRNS, BLD, BLI,
|
||||
TRNS, TRNS, TRNS, TRNS, TRNS),
|
||||
};
|
||||
|
113
keyboard/25/config.h
Normal file
113
keyboard/25/config.h
Normal file
@ -0,0 +1,113 @@
|
||||
/*
|
||||
Copyright 2012 Jun Wako <wakojun@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_H
|
||||
#define CONFIG_H
|
||||
|
||||
|
||||
/* USB Device descriptor parameter */
|
||||
|
||||
#define VENDOR_ID 0xFEED
|
||||
#define PRODUCT_ID 0x0A0C
|
||||
#define DEVICE_VER 0x0F25
|
||||
#define MANUFACTURER di0ib
|
||||
#define PRODUCT The 5x5 Keyboard
|
||||
#define DESCRIPTION A split 50 key keyboard
|
||||
|
||||
/* key matrix size */
|
||||
#define ROWS_PER_HAND 5
|
||||
#define MATRIX_COLS 5
|
||||
|
||||
#define MATRIX_ROWS ROWS_PER_HAND*2
|
||||
|
||||
#define MATRIX_COL_PINS { F4, F5, F6, F7, B1 }
|
||||
#define MATRIX_ROW_PINS { D4, C6, D7, E6, B4 }
|
||||
|
||||
|
||||
/* use i2c instead of serial */
|
||||
//#define USE_I2C
|
||||
|
||||
//#define I2C_WRITE_TEST_CODE
|
||||
|
||||
/* define if matrix has ghost */
|
||||
//#define MATRIX_HAS_GHOST
|
||||
|
||||
/* Set 0 if debouncing isn't needed */
|
||||
#define DEBOUNCE 5
|
||||
|
||||
/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
|
||||
#define LOCKING_SUPPORT_ENABLE
|
||||
/* Locking resynchronize hack */
|
||||
#define LOCKING_RESYNC_ENABLE
|
||||
|
||||
/*
|
||||
* Feature disable options
|
||||
* These options are also useful to firmware size reduction.
|
||||
*/
|
||||
|
||||
/* disable debug print */
|
||||
//#define NO_DEBUG
|
||||
|
||||
/* disable print */
|
||||
//#define NO_PRINT
|
||||
|
||||
/* disable action features */
|
||||
//#define NO_ACTION_LAYER
|
||||
//#define NO_ACTION_TAPPING
|
||||
//#define NO_ACTION_ONESHOT
|
||||
//#define NO_ACTION_MACRO
|
||||
//#define NO_ACTION_FUNCTION
|
||||
|
||||
/* key combination for command */
|
||||
#define IS_COMMAND() ( \
|
||||
keyboard_report->mods == (MOD_BIT(KC_LCTL) | MOD_BIT(KC_LALT) | MOD_BIT(KC_LGUI)) \
|
||||
)
|
||||
|
||||
/* boot magic key */
|
||||
#define BOOTMAGIC_KEY_SALT KC_Q
|
||||
|
||||
#ifdef SPACE_ON_LEFT_HALF
|
||||
#define BOOTMAGIC_KEY_DEFAULT_LAYER_0 KC_Z
|
||||
#define BOOTMAGIC_KEY_DEFAULT_LAYER_1 KC_X
|
||||
#define BOOTMAGIC_KEY_DEFAULT_LAYER_2 KC_C
|
||||
#define BOOTMAGIC_HOST_NKRO KC_V
|
||||
#else
|
||||
#define BOOTMAGIC_KEY_DEFAULT_LAYER_0 KC_M
|
||||
#define BOOTMAGIC_KEY_DEFAULT_LAYER_1 KC_COMM
|
||||
#define BOOTMAGIC_KEY_DEFAULT_LAYER_2 KC_DOT
|
||||
#define BOOTMAGIC_HOST_NKRO KC_N
|
||||
#endif
|
||||
|
||||
/* Mousekey settings */
|
||||
#define MOUSEKEY_MOVE_MAX 127 // default 127
|
||||
#define MOUSEKEY_WHEEL_MAX 127 // default 127
|
||||
#define MOUSEKEY_MOVE_DELTA 5 // default 5
|
||||
#define MOUSEKEY_WHEEL_DELTA 1 // default 1
|
||||
#define MOUSEKEY_DELAY 300 // default 300
|
||||
#define MOUSEKEY_INTERVAL 50 // default 50
|
||||
#define MOUSEKEY_MAX_SPEED 5 // default 10
|
||||
#define MOUSEKEY_TIME_TO_MAX 10 // default 20
|
||||
#define MOUSEKEY_WHEEL_MAX_SPEED 8 // default 8
|
||||
#define MOUSEKEY_WHEEL_TIME_TO_MAX 40 // default 40
|
||||
|
||||
/* Action tapping settings */
|
||||
#define TAPPING_TERM 200 // default 200
|
||||
/* #define TAPPING_TOGGLE 2 // default 5 */
|
||||
/* #define ONESHOT_TIMEOUT 5000 // default undefined */
|
||||
#define ONESHOT_TAP_TOGGLE 2
|
||||
|
||||
#endif
|
223
keyboard/25/i2c.c
Normal file
223
keyboard/25/i2c.c
Normal file
@ -0,0 +1,223 @@
|
||||
#include <util/twi.h>
|
||||
#include <avr/io.h>
|
||||
#include <stdlib.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <util/twi.h>
|
||||
#include <stdbool.h>
|
||||
#include "i2c.h"
|
||||
|
||||
#define I2C_READ 1
|
||||
#define I2C_WRITE 0
|
||||
|
||||
#define I2C_ACK 1
|
||||
#define I2C_NACK 0
|
||||
|
||||
// Limits the amount of we wait for any one i2c transaction.
|
||||
// Since were running SCL line 100kHz (=> 10μs/bit), and each transactions is
|
||||
// 9 bits, a single transaction will take around 90μs to complete.
|
||||
//
|
||||
// (F_CPU/SCL_CLOCK) => # of mcu cycles to transfer a bit
|
||||
// poll loop takes at least 8 clock cycles to execute
|
||||
#define I2C_LOOP_TIMEOUT (9+1)*(F_CPU/SCL_CLOCK)/8
|
||||
|
||||
#define BUFFER_POS_INC() (slave_buffer_pos = (slave_buffer_pos+1)%SLAVE_BUFFER_SIZE)
|
||||
|
||||
static volatile uint8_t i2c_slave_buffer[SLAVE_BUFFER_SIZE] = {0};
|
||||
|
||||
static volatile uint8_t slave_buffer_pos;
|
||||
static volatile bool slave_has_register_set = false;
|
||||
|
||||
static uint8_t i2c_start(uint8_t address);
|
||||
static void i2c_stop(void);
|
||||
static uint8_t i2c_write(uint8_t data);
|
||||
static uint8_t i2c_read(uint8_t ack);
|
||||
|
||||
// Wait for an i2c operation to finish
|
||||
inline static
|
||||
void i2c_delay(void) {
|
||||
uint16_t lim = 0;
|
||||
while(!(TWCR & (1<<TWINT)) && lim < I2C_LOOP_TIMEOUT)
|
||||
lim++;
|
||||
|
||||
// easier way, but will wait slightly longer
|
||||
// _delay_us(100);
|
||||
}
|
||||
|
||||
// i2c_device_addr: the i2c device to communicate with
|
||||
// addr: the memory address to read from the i2c device
|
||||
// dest: pointer to where read data is saved
|
||||
// len: the number of bytes to read
|
||||
//
|
||||
// NOTE: on error, the data in dest may have been modified
|
||||
bool i2c_master_read(uint8_t i2c_device_addr, uint8_t addr, uint8_t *dest, uint8_t len) {
|
||||
bool err;
|
||||
if (len == 0) return 0;
|
||||
|
||||
err = i2c_start(i2c_device_addr + I2C_WRITE);
|
||||
if (err) return err;
|
||||
err = i2c_write(addr);
|
||||
if (err) return err;
|
||||
|
||||
err = i2c_start(i2c_device_addr + I2C_READ);
|
||||
if (err) return err;
|
||||
|
||||
for (uint8_t i = 0; i < len-1; ++i) {
|
||||
dest[i] = i2c_read(I2C_ACK);
|
||||
}
|
||||
dest[len-1] = i2c_read(I2C_NACK);
|
||||
i2c_stop();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// i2c_device_addr: the i2c device to communicate with
|
||||
// addr: the memory address at which to write in the i2c device
|
||||
// data: the data to be written
|
||||
// len: the number of bytes to write
|
||||
bool i2c_master_write(uint8_t i2c_device_addr, uint8_t addr, uint8_t *data, uint8_t len) {
|
||||
bool err;
|
||||
|
||||
if (len == 0) return 0;
|
||||
|
||||
err = i2c_start(i2c_device_addr + I2C_WRITE);
|
||||
if (err) return err;
|
||||
err = i2c_write(addr);
|
||||
if (err) return err;
|
||||
|
||||
for (uint8_t i = 0; i < len; ++i) {
|
||||
err = i2c_write(data[i]);
|
||||
if (err) return err;
|
||||
}
|
||||
i2c_stop();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void i2c_slave_write(uint8_t addr, uint8_t data) {
|
||||
i2c_slave_buffer[addr] = data;
|
||||
}
|
||||
|
||||
uint8_t i2c_slave_read(uint8_t addr) {
|
||||
return i2c_slave_buffer[addr];
|
||||
}
|
||||
|
||||
// Setup twi to run at 100kHz
|
||||
void i2c_master_init(void) {
|
||||
// no prescaler
|
||||
TWSR = 0;
|
||||
// Set TWI clock frequency to SCL_CLOCK. Need TWBR>10.
|
||||
// Check datasheets for more info.
|
||||
TWBR = ((F_CPU/SCL_CLOCK)-16)/2;
|
||||
}
|
||||
|
||||
// Start a transaction with the given i2c slave address. The direction of the
|
||||
// transfer is set with I2C_READ and I2C_WRITE.
|
||||
// returns: 0 => success
|
||||
// 1 => error
|
||||
uint8_t i2c_start(uint8_t address) {
|
||||
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTA);
|
||||
|
||||
i2c_delay();
|
||||
|
||||
// check that we started successfully
|
||||
if ( (TW_STATUS != TW_START) && (TW_STATUS != TW_REP_START))
|
||||
return 1;
|
||||
|
||||
TWDR = address;
|
||||
TWCR = (1<<TWINT) | (1<<TWEN);
|
||||
|
||||
i2c_delay();
|
||||
|
||||
if ( (TW_STATUS != TW_MT_SLA_ACK) && (TW_STATUS != TW_MR_SLA_ACK) )
|
||||
return 1; // slave did not acknowledge
|
||||
else
|
||||
return 0; // success
|
||||
}
|
||||
|
||||
|
||||
// Finish the i2c transaction.
|
||||
void i2c_stop(void) {
|
||||
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
|
||||
|
||||
uint16_t lim = 0;
|
||||
while(!(TWCR & (1<<TWSTO)) && lim < I2C_LOOP_TIMEOUT)
|
||||
lim++;
|
||||
}
|
||||
|
||||
// Write one byte to the i2c slave.
|
||||
// returns 0 => slave ACK
|
||||
// 1 => slave NACK
|
||||
uint8_t i2c_write(uint8_t data) {
|
||||
TWDR = data;
|
||||
TWCR = (1<<TWINT) | (1<<TWEN);
|
||||
|
||||
i2c_delay();
|
||||
|
||||
// check if the slave acknowledged us
|
||||
return (TW_STATUS == TW_MT_DATA_ACK) ? 0 : 1;
|
||||
}
|
||||
|
||||
// Read one byte from the i2c slave. If ack=1 the slave is acknowledged,
|
||||
// if ack=0 the acknowledge bit is not set.
|
||||
// returns: byte read from i2c device
|
||||
uint8_t i2c_read(uint8_t ack) {
|
||||
TWCR = (1<<TWINT) | (1<<TWEN) | (ack<<TWEA);
|
||||
|
||||
i2c_delay();
|
||||
return TWDR;
|
||||
}
|
||||
|
||||
void i2c_slave_init(uint8_t address) {
|
||||
TWAR = address << 0; // slave i2c address
|
||||
// TWEN - twi enable
|
||||
// TWEA - enable address acknowledgement
|
||||
// TWINT - twi interrupt flag
|
||||
// TWIE - enable the twi interrupt
|
||||
TWCR = (1<<TWIE) | (1<<TWEA) | (1<<TWINT) | (1<<TWEN);
|
||||
}
|
||||
|
||||
ISR(TWI_vect);
|
||||
|
||||
ISR(TWI_vect) {
|
||||
uint8_t ack = 1;
|
||||
switch(TW_STATUS) {
|
||||
case TW_SR_SLA_ACK:
|
||||
// this device has been addressed as a slave receiver
|
||||
slave_has_register_set = false;
|
||||
break;
|
||||
|
||||
case TW_SR_DATA_ACK:
|
||||
// this device has received data as a slave receiver
|
||||
// The first byte that we receive in this transaction sets the location
|
||||
// of the read/write location of the slaves memory that it exposes over
|
||||
// i2c. After that, bytes will be written at slave_buffer_pos, incrementing
|
||||
// slave_buffer_pos after each write.
|
||||
if(!slave_has_register_set) {
|
||||
slave_buffer_pos = TWDR;
|
||||
// don't acknowledge the master if this memory loctaion is out of bounds
|
||||
if ( slave_buffer_pos >= SLAVE_BUFFER_SIZE ) {
|
||||
ack = 0;
|
||||
slave_buffer_pos = 0;
|
||||
}
|
||||
slave_has_register_set = true;
|
||||
} else {
|
||||
i2c_slave_buffer[slave_buffer_pos] = TWDR;
|
||||
BUFFER_POS_INC();
|
||||
}
|
||||
break;
|
||||
|
||||
case TW_ST_SLA_ACK:
|
||||
case TW_ST_DATA_ACK:
|
||||
// master has addressed this device as a slave transmitter and is
|
||||
// requesting data.
|
||||
TWDR = i2c_slave_buffer[slave_buffer_pos];
|
||||
BUFFER_POS_INC();
|
||||
break;
|
||||
|
||||
case TW_BUS_ERROR: // something went wrong, reset twi state
|
||||
TWCR = 0;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// Reset everything, so we are ready for the next TWI interrupt
|
||||
TWCR |= (1<<TWIE) | (1<<TWINT) | (ack<<TWEA) | (1<<TWEN);
|
||||
}
|
21
keyboard/25/i2c.h
Normal file
21
keyboard/25/i2c.h
Normal file
@ -0,0 +1,21 @@
|
||||
#ifndef I2C_H
|
||||
#define I2C_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define SLAVE_BUFFER_SIZE 0x40
|
||||
|
||||
// i2c SCL clock frequency
|
||||
#define SCL_CLOCK 100000L
|
||||
|
||||
|
||||
void i2c_master_init(void);
|
||||
void i2c_slave_init(uint8_t address);
|
||||
|
||||
bool i2c_master_write(uint8_t i2c_device_addr, uint8_t addr, uint8_t *dest, uint8_t len);
|
||||
bool i2c_master_read(uint8_t i2c_device_addr, uint8_t addr, uint8_t *data, uint8_t len);
|
||||
|
||||
void i2c_slave_write(uint8_t addr, uint8_t data);
|
||||
uint8_t i2c_slave_read(uint8_t addr);
|
||||
|
||||
#endif
|
BIN
keyboard/25/imgs/split-keyboard-i2c-schematic.png
Normal file
BIN
keyboard/25/imgs/split-keyboard-i2c-schematic.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 26 KiB |
BIN
keyboard/25/imgs/split-keyboard-serial-schematic.png
Normal file
BIN
keyboard/25/imgs/split-keyboard-serial-schematic.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 19 KiB |
24
keyboard/25/led.c
Normal file
24
keyboard/25/led.c
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
Copyright 2012 Jun Wako <wakojun@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <avr/io.h>
|
||||
#include "stdint.h"
|
||||
#include "led.h"
|
||||
|
||||
void led_set(uint8_t usb_led)
|
||||
{
|
||||
}
|
298
keyboard/25/matrix.c
Normal file
298
keyboard/25/matrix.c
Normal file
@ -0,0 +1,298 @@
|
||||
/*
|
||||
Copyright 2012 Jun Wako <wakojun@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* scan matrix
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <avr/io.h>
|
||||
#include <avr/wdt.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <util/delay.h>
|
||||
#include "print.h"
|
||||
#include "debug.h"
|
||||
#include "util.h"
|
||||
#include "timer.h"
|
||||
#include "matrix.h"
|
||||
#include "i2c.h"
|
||||
#include "serial.h"
|
||||
#include "split-util.h"
|
||||
#include "pro-micro.h"
|
||||
#include "config.h"
|
||||
|
||||
#include "pin_defs.h"
|
||||
|
||||
#ifndef DEBOUNCE
|
||||
# define DEBOUNCE 5
|
||||
#endif
|
||||
|
||||
#define ERROR_DISCONNECT_COUNT 5
|
||||
|
||||
#define I2C_MATRIX_ADDR 0x00
|
||||
#define I2C_LED_ADDR ROWS_PER_HAND
|
||||
|
||||
static uint8_t debouncing = DEBOUNCE;
|
||||
static uint8_t error_count = 0;
|
||||
|
||||
/* matrix state(1:on, 0:off) */
|
||||
static matrix_row_t matrix[MATRIX_ROWS];
|
||||
static matrix_row_t matrix_debouncing[MATRIX_ROWS];
|
||||
|
||||
static const uint8_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
|
||||
static const uint8_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
|
||||
|
||||
static matrix_row_t read_cols(void);
|
||||
static void init_cols(void);
|
||||
static void unselect_rows(void);
|
||||
static void select_row(uint8_t row);
|
||||
|
||||
inline
|
||||
uint8_t matrix_rows(void)
|
||||
{
|
||||
return MATRIX_ROWS;
|
||||
}
|
||||
|
||||
inline
|
||||
uint8_t matrix_cols(void)
|
||||
{
|
||||
return MATRIX_COLS;
|
||||
}
|
||||
|
||||
void matrix_init(void)
|
||||
{
|
||||
// To use PORTF disable JTAG with writing JTD bit twice within four cycles.
|
||||
MCUCR |= (1<<JTD);
|
||||
MCUCR |= (1<<JTD);
|
||||
|
||||
debug_enable = true;
|
||||
debug_matrix = true;
|
||||
debug_mouse = true;
|
||||
// initialize row and col
|
||||
unselect_rows();
|
||||
init_cols();
|
||||
|
||||
TX_RX_LED_INIT;
|
||||
//Turn LEDs off by default
|
||||
RXLED0;
|
||||
TXLED0;
|
||||
|
||||
// initialize matrix state: all keys off
|
||||
for (uint8_t i=0; i < MATRIX_ROWS; i++) {
|
||||
matrix[i] = 0;
|
||||
matrix_debouncing[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t _matrix_scan(void)
|
||||
{
|
||||
// Right hand is stored after the left in the matirx so, we need to offset it
|
||||
int offset = isLeftHand ? 0 : (ROWS_PER_HAND);
|
||||
|
||||
for (uint8_t i = 0; i < ROWS_PER_HAND; i++) {
|
||||
select_row(i);
|
||||
_delay_us(30); // without this wait read unstable value.
|
||||
matrix_row_t cols = read_cols();
|
||||
if (matrix_debouncing[i+offset] != cols) {
|
||||
matrix_debouncing[i+offset] = cols;
|
||||
debouncing = DEBOUNCE;
|
||||
}
|
||||
unselect_rows();
|
||||
}
|
||||
|
||||
if (debouncing) {
|
||||
if (--debouncing) {
|
||||
_delay_ms(1);
|
||||
} else {
|
||||
for (uint8_t i = 0; i < ROWS_PER_HAND; i++) {
|
||||
matrix[i+offset] = matrix_debouncing[i+offset];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Get rows from other half over i2c
|
||||
int i2c_transaction(void) {
|
||||
bool err = false;
|
||||
int slaveOffset = (isLeftHand) ? (ROWS_PER_HAND) : 0;
|
||||
|
||||
err = i2c_master_read(
|
||||
SLAVE_I2C_ADDRESS, // i2c address of other half
|
||||
I2C_MATRIX_ADDR, // read the slaves matrix data
|
||||
matrix+slaveOffset, // store in correct position in master's matrix
|
||||
ROWS_PER_HAND // number of bytes to read
|
||||
);
|
||||
|
||||
#ifdef I2C_WRITE_TEST_CODE
|
||||
// controls the RX led on the slave and toggles it every second
|
||||
uint8_t test_data = (timer_read() / 1000) % 2;
|
||||
|
||||
err |= i2c_master_write(
|
||||
SLAVE_I2C_ADDRESS, // i2c address of other half
|
||||
I2C_LED_ADDR, // address for led control
|
||||
&test_data, // data to send
|
||||
sizeof(test_data) // size of test data
|
||||
);
|
||||
#endif
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int serial_transaction(void) {
|
||||
int slaveOffset = (isLeftHand) ? (ROWS_PER_HAND) : 0;
|
||||
|
||||
if (serial_update_buffers()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (int i = 0; i < ROWS_PER_HAND; ++i) {
|
||||
matrix[slaveOffset+i] = serial_slave_buffer[i];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t matrix_scan(void)
|
||||
{
|
||||
int ret = _matrix_scan();
|
||||
|
||||
|
||||
|
||||
#ifdef USE_I2C
|
||||
if( i2c_transaction() ) {
|
||||
#else
|
||||
if( serial_transaction() ) {
|
||||
#endif
|
||||
// turn on the indicator led when halves are disconnected
|
||||
TXLED1;
|
||||
|
||||
error_count++;
|
||||
|
||||
if (error_count > ERROR_DISCONNECT_COUNT) {
|
||||
// reset other half if disconnected
|
||||
int slaveOffset = (isLeftHand) ? (ROWS_PER_HAND) : 0;
|
||||
for (int i = 0; i < ROWS_PER_HAND; ++i) {
|
||||
matrix[slaveOffset+i] = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// turn off the indicator led on no error
|
||||
TXLED0;
|
||||
error_count = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void matrix_slave_scan(void) {
|
||||
_matrix_scan();
|
||||
|
||||
int offset = (isLeftHand) ? 0 : (MATRIX_ROWS / 2);
|
||||
|
||||
#ifdef USE_I2C
|
||||
for (int i = 0; i < ROWS_PER_HAND; ++i) {
|
||||
i2c_slave_write(I2C_MATRIX_ADDR+i, matrix[offset+i]);
|
||||
}
|
||||
|
||||
#ifdef I2C_WRITE_TEST_CODE
|
||||
// control the pro micro RX LED based on what the
|
||||
// i2c master has sent us
|
||||
uint8_t led_state = i2c_slave_read(I2C_LED_ADDR);
|
||||
if (led_state == 1) {
|
||||
RXLED1;
|
||||
} else if(led_state == 0) {
|
||||
RXLED0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#else
|
||||
for (int i = 0; i < ROWS_PER_HAND; ++i) {
|
||||
serial_slave_buffer[i] = matrix[offset+i];
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
bool matrix_is_modified(void)
|
||||
{
|
||||
if (debouncing) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline
|
||||
bool matrix_is_on(uint8_t row, uint8_t col)
|
||||
{
|
||||
return (matrix[row] & ((matrix_row_t)1<<col));
|
||||
}
|
||||
|
||||
inline
|
||||
matrix_row_t matrix_get_row(uint8_t row)
|
||||
{
|
||||
return matrix[row];
|
||||
}
|
||||
|
||||
void matrix_print(void)
|
||||
{
|
||||
print("\nr/c 0123456789ABCDEF\n");
|
||||
for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
|
||||
phex(row); print(": ");
|
||||
pbin_reverse16(matrix_get_row(row));
|
||||
print("\n");
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t matrix_key_count(void)
|
||||
{
|
||||
uint8_t count = 0;
|
||||
for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
|
||||
count += bitpop16(matrix[i]);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
static void init_cols(void)
|
||||
{
|
||||
for(int x = 0; x < MATRIX_COLS; x++) {
|
||||
_SFR_IO8((col_pins[x] >> 4) + 1) &= ~_BV(col_pins[x] & 0xF);
|
||||
_SFR_IO8((col_pins[x] >> 4) + 2) |= _BV(col_pins[x] & 0xF);
|
||||
}
|
||||
}
|
||||
|
||||
static matrix_row_t read_cols(void)
|
||||
{
|
||||
matrix_row_t result = 0;
|
||||
for(int x = 0; x < MATRIX_COLS; x++) {
|
||||
result |= (_SFR_IO8(col_pins[x] >> 4) & _BV(col_pins[x] & 0xF)) ? 0 : (1 << x);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static void unselect_rows(void)
|
||||
{
|
||||
for(int x = 0; x < ROWS_PER_HAND; x++) {
|
||||
_SFR_IO8((row_pins[x] >> 4) + 1) &= ~_BV(row_pins[x] & 0xF);
|
||||
_SFR_IO8((row_pins[x] >> 4) + 2) |= _BV(row_pins[x] & 0xF);
|
||||
}
|
||||
}
|
||||
|
||||
static void select_row(uint8_t row)
|
||||
{
|
||||
_SFR_IO8((row_pins[row] >> 4) + 1) |= _BV(row_pins[row] & 0xF);
|
||||
_SFR_IO8((row_pins[row] >> 4) + 2) &= ~_BV(row_pins[row] & 0xF);
|
||||
}
|
58
keyboard/25/pin_defs.h
Normal file
58
keyboard/25/pin_defs.h
Normal file
@ -0,0 +1,58 @@
|
||||
#ifndef PIN_DEFS_H
|
||||
#define PIN_DEFS_H
|
||||
|
||||
/* diode directions */
|
||||
#define COL2ROW 0
|
||||
#define ROW2COL 1
|
||||
|
||||
/* I/O pins */
|
||||
#define B0 0x30
|
||||
#define B1 0x31
|
||||
#define B2 0x32
|
||||
#define B3 0x33
|
||||
#define B4 0x34
|
||||
#define B5 0x35
|
||||
#define B6 0x36
|
||||
#define B7 0x37
|
||||
#define C0 0x60
|
||||
#define C1 0x61
|
||||
#define C2 0x62
|
||||
#define C3 0x63
|
||||
#define C4 0x64
|
||||
#define C5 0x65
|
||||
#define C6 0x66
|
||||
#define C7 0x67
|
||||
#define D0 0x90
|
||||
#define D1 0x91
|
||||
#define D2 0x92
|
||||
#define D3 0x93
|
||||
#define D4 0x94
|
||||
#define D5 0x95
|
||||
#define D6 0x96
|
||||
#define D7 0x97
|
||||
#define E0 0xC0
|
||||
#define E1 0xC1
|
||||
#define E2 0xC2
|
||||
#define E3 0xC3
|
||||
#define E4 0xC4
|
||||
#define E5 0xC5
|
||||
#define E6 0xC6
|
||||
#define E7 0xC7
|
||||
#define F0 0xF0
|
||||
#define F1 0xF1
|
||||
#define F2 0xF2
|
||||
#define F3 0xF3
|
||||
#define F4 0xF4
|
||||
#define F5 0xF5
|
||||
#define F6 0xF6
|
||||
#define F7 0xF7
|
||||
#define A0 0x00
|
||||
#define A1 0x01
|
||||
#define A2 0x02
|
||||
#define A3 0x03
|
||||
#define A4 0x04
|
||||
#define A5 0x05
|
||||
#define A6 0x06
|
||||
#define A7 0x07
|
||||
|
||||
#endif
|
362
keyboard/25/pro-micro.h
Normal file
362
keyboard/25/pro-micro.h
Normal file
@ -0,0 +1,362 @@
|
||||
/*
|
||||
pins_arduino.h - Pin definition functions for Arduino
|
||||
Part of Arduino - http://www.arduino.cc/
|
||||
|
||||
Copyright (c) 2007 David A. Mellis
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General
|
||||
Public License along with this library; if not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
Boston, MA 02111-1307 USA
|
||||
|
||||
$Id: wiring.h 249 2007-02-03 16:52:51Z mellis $
|
||||
*/
|
||||
|
||||
#ifndef Pins_Arduino_h
|
||||
#define Pins_Arduino_h
|
||||
|
||||
#include <avr/pgmspace.h>
|
||||
|
||||
// Workaround for wrong definitions in "iom32u4.h".
|
||||
// This should be fixed in the AVR toolchain.
|
||||
#undef UHCON
|
||||
#undef UHINT
|
||||
#undef UHIEN
|
||||
#undef UHADDR
|
||||
#undef UHFNUM
|
||||
#undef UHFNUML
|
||||
#undef UHFNUMH
|
||||
#undef UHFLEN
|
||||
#undef UPINRQX
|
||||
#undef UPINTX
|
||||
#undef UPNUM
|
||||
#undef UPRST
|
||||
#undef UPCONX
|
||||
#undef UPCFG0X
|
||||
#undef UPCFG1X
|
||||
#undef UPSTAX
|
||||
#undef UPCFG2X
|
||||
#undef UPIENX
|
||||
#undef UPDATX
|
||||
#undef TCCR2A
|
||||
#undef WGM20
|
||||
#undef WGM21
|
||||
#undef COM2B0
|
||||
#undef COM2B1
|
||||
#undef COM2A0
|
||||
#undef COM2A1
|
||||
#undef TCCR2B
|
||||
#undef CS20
|
||||
#undef CS21
|
||||
#undef CS22
|
||||
#undef WGM22
|
||||
#undef FOC2B
|
||||
#undef FOC2A
|
||||
#undef TCNT2
|
||||
#undef TCNT2_0
|
||||
#undef TCNT2_1
|
||||
#undef TCNT2_2
|
||||
#undef TCNT2_3
|
||||
#undef TCNT2_4
|
||||
#undef TCNT2_5
|
||||
#undef TCNT2_6
|
||||
#undef TCNT2_7
|
||||
#undef OCR2A
|
||||
#undef OCR2_0
|
||||
#undef OCR2_1
|
||||
#undef OCR2_2
|
||||
#undef OCR2_3
|
||||
#undef OCR2_4
|
||||
#undef OCR2_5
|
||||
#undef OCR2_6
|
||||
#undef OCR2_7
|
||||
#undef OCR2B
|
||||
#undef OCR2_0
|
||||
#undef OCR2_1
|
||||
#undef OCR2_2
|
||||
#undef OCR2_3
|
||||
#undef OCR2_4
|
||||
#undef OCR2_5
|
||||
#undef OCR2_6
|
||||
#undef OCR2_7
|
||||
|
||||
#define NUM_DIGITAL_PINS 30
|
||||
#define NUM_ANALOG_INPUTS 12
|
||||
|
||||
#define TX_RX_LED_INIT DDRD |= (1<<5), DDRB |= (1<<0)
|
||||
#define TXLED0 PORTD |= (1<<5)
|
||||
#define TXLED1 PORTD &= ~(1<<5)
|
||||
#define RXLED0 PORTB |= (1<<0)
|
||||
#define RXLED1 PORTB &= ~(1<<0)
|
||||
|
||||
static const uint8_t SDA = 2;
|
||||
static const uint8_t SCL = 3;
|
||||
#define LED_BUILTIN 13
|
||||
|
||||
// Map SPI port to 'new' pins D14..D17
|
||||
static const uint8_t SS = 17;
|
||||
static const uint8_t MOSI = 16;
|
||||
static const uint8_t MISO = 14;
|
||||
static const uint8_t SCK = 15;
|
||||
|
||||
// Mapping of analog pins as digital I/O
|
||||
// A6-A11 share with digital pins
|
||||
static const uint8_t A0 = 18;
|
||||
static const uint8_t A1 = 19;
|
||||
static const uint8_t A2 = 20;
|
||||
static const uint8_t A3 = 21;
|
||||
static const uint8_t A4 = 22;
|
||||
static const uint8_t A5 = 23;
|
||||
static const uint8_t A6 = 24; // D4
|
||||
static const uint8_t A7 = 25; // D6
|
||||
static const uint8_t A8 = 26; // D8
|
||||
static const uint8_t A9 = 27; // D9
|
||||
static const uint8_t A10 = 28; // D10
|
||||
static const uint8_t A11 = 29; // D12
|
||||
|
||||
#define digitalPinToPCICR(p) ((((p) >= 8 && (p) <= 11) || ((p) >= 14 && (p) <= 17) || ((p) >= A8 && (p) <= A10)) ? (&PCICR) : ((uint8_t *)0))
|
||||
#define digitalPinToPCICRbit(p) 0
|
||||
#define digitalPinToPCMSK(p) ((((p) >= 8 && (p) <= 11) || ((p) >= 14 && (p) <= 17) || ((p) >= A8 && (p) <= A10)) ? (&PCMSK0) : ((uint8_t *)0))
|
||||
#define digitalPinToPCMSKbit(p) ( ((p) >= 8 && (p) <= 11) ? (p) - 4 : ((p) == 14 ? 3 : ((p) == 15 ? 1 : ((p) == 16 ? 2 : ((p) == 17 ? 0 : (p - A8 + 4))))))
|
||||
|
||||
// __AVR_ATmega32U4__ has an unusual mapping of pins to channels
|
||||
extern const uint8_t PROGMEM analog_pin_to_channel_PGM[];
|
||||
#define analogPinToChannel(P) ( pgm_read_byte( analog_pin_to_channel_PGM + (P) ) )
|
||||
|
||||
#define digitalPinToInterrupt(p) ((p) == 0 ? 2 : ((p) == 1 ? 3 : ((p) == 2 ? 1 : ((p) == 3 ? 0 : ((p) == 7 ? 4 : NOT_AN_INTERRUPT)))))
|
||||
|
||||
#ifdef ARDUINO_MAIN
|
||||
|
||||
// On the Arduino board, digital pins are also used
|
||||
// for the analog output (software PWM). Analog input
|
||||
// pins are a separate set.
|
||||
|
||||
// ATMEL ATMEGA32U4 / ARDUINO LEONARDO
|
||||
//
|
||||
// D0 PD2 RXD1/INT2
|
||||
// D1 PD3 TXD1/INT3
|
||||
// D2 PD1 SDA SDA/INT1
|
||||
// D3# PD0 PWM8/SCL OC0B/SCL/INT0
|
||||
// D4 A6 PD4 ADC8
|
||||
// D5# PC6 ??? OC3A/#OC4A
|
||||
// D6# A7 PD7 FastPWM #OC4D/ADC10
|
||||
// D7 PE6 INT6/AIN0
|
||||
//
|
||||
// D8 A8 PB4 ADC11/PCINT4
|
||||
// D9# A9 PB5 PWM16 OC1A/#OC4B/ADC12/PCINT5
|
||||
// D10# A10 PB6 PWM16 OC1B/0c4B/ADC13/PCINT6
|
||||
// D11# PB7 PWM8/16 0C0A/OC1C/#RTS/PCINT7
|
||||
// D12 A11 PD6 T1/#OC4D/ADC9
|
||||
// D13# PC7 PWM10 CLK0/OC4A
|
||||
//
|
||||
// A0 D18 PF7 ADC7
|
||||
// A1 D19 PF6 ADC6
|
||||
// A2 D20 PF5 ADC5
|
||||
// A3 D21 PF4 ADC4
|
||||
// A4 D22 PF1 ADC1
|
||||
// A5 D23 PF0 ADC0
|
||||
//
|
||||
// New pins D14..D17 to map SPI port to digital pins
|
||||
//
|
||||
// MISO D14 PB3 MISO,PCINT3
|
||||
// SCK D15 PB1 SCK,PCINT1
|
||||
// MOSI D16 PB2 MOSI,PCINT2
|
||||
// SS D17 PB0 RXLED,SS/PCINT0
|
||||
//
|
||||
// Connected LEDs on board for TX and RX
|
||||
// TXLED D24 PD5 XCK1
|
||||
// RXLED D17 PB0
|
||||
// HWB PE2 HWB
|
||||
|
||||
// these arrays map port names (e.g. port B) to the
|
||||
// appropriate addresses for various functions (e.g. reading
|
||||
// and writing)
|
||||
const uint16_t PROGMEM port_to_mode_PGM[] = {
|
||||
NOT_A_PORT,
|
||||
NOT_A_PORT,
|
||||
(uint16_t) &DDRB,
|
||||
(uint16_t) &DDRC,
|
||||
(uint16_t) &DDRD,
|
||||
(uint16_t) &DDRE,
|
||||
(uint16_t) &DDRF,
|
||||
};
|
||||
|
||||
const uint16_t PROGMEM port_to_output_PGM[] = {
|
||||
NOT_A_PORT,
|
||||
NOT_A_PORT,
|
||||
(uint16_t) &PORTB,
|
||||
(uint16_t) &PORTC,
|
||||
(uint16_t) &PORTD,
|
||||
(uint16_t) &PORTE,
|
||||
(uint16_t) &PORTF,
|
||||
};
|
||||
|
||||
const uint16_t PROGMEM port_to_input_PGM[] = {
|
||||
NOT_A_PORT,
|
||||
NOT_A_PORT,
|
||||
(uint16_t) &PINB,
|
||||
(uint16_t) &PINC,
|
||||
(uint16_t) &PIND,
|
||||
(uint16_t) &PINE,
|
||||
(uint16_t) &PINF,
|
||||
};
|
||||
|
||||
const uint8_t PROGMEM digital_pin_to_port_PGM[] = {
|
||||
PD, // D0 - PD2
|
||||
PD, // D1 - PD3
|
||||
PD, // D2 - PD1
|
||||
PD, // D3 - PD0
|
||||
PD, // D4 - PD4
|
||||
PC, // D5 - PC6
|
||||
PD, // D6 - PD7
|
||||
PE, // D7 - PE6
|
||||
|
||||
PB, // D8 - PB4
|
||||
PB, // D9 - PB5
|
||||
PB, // D10 - PB6
|
||||
PB, // D11 - PB7
|
||||
PD, // D12 - PD6
|
||||
PC, // D13 - PC7
|
||||
|
||||
PB, // D14 - MISO - PB3
|
||||
PB, // D15 - SCK - PB1
|
||||
PB, // D16 - MOSI - PB2
|
||||
PB, // D17 - SS - PB0
|
||||
|
||||
PF, // D18 - A0 - PF7
|
||||
PF, // D19 - A1 - PF6
|
||||
PF, // D20 - A2 - PF5
|
||||
PF, // D21 - A3 - PF4
|
||||
PF, // D22 - A4 - PF1
|
||||
PF, // D23 - A5 - PF0
|
||||
|
||||
PD, // D24 - PD5
|
||||
PD, // D25 / D6 - A7 - PD7
|
||||
PB, // D26 / D8 - A8 - PB4
|
||||
PB, // D27 / D9 - A9 - PB5
|
||||
PB, // D28 / D10 - A10 - PB6
|
||||
PD, // D29 / D12 - A11 - PD6
|
||||
};
|
||||
|
||||
const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] = {
|
||||
_BV(2), // D0 - PD2
|
||||
_BV(3), // D1 - PD3
|
||||
_BV(1), // D2 - PD1
|
||||
_BV(0), // D3 - PD0
|
||||
_BV(4), // D4 - PD4
|
||||
_BV(6), // D5 - PC6
|
||||
_BV(7), // D6 - PD7
|
||||
_BV(6), // D7 - PE6
|
||||
|
||||
_BV(4), // D8 - PB4
|
||||
_BV(5), // D9 - PB5
|
||||
_BV(6), // D10 - PB6
|
||||
_BV(7), // D11 - PB7
|
||||
_BV(6), // D12 - PD6
|
||||
_BV(7), // D13 - PC7
|
||||
|
||||
_BV(3), // D14 - MISO - PB3
|
||||
_BV(1), // D15 - SCK - PB1
|
||||
_BV(2), // D16 - MOSI - PB2
|
||||
_BV(0), // D17 - SS - PB0
|
||||
|
||||
_BV(7), // D18 - A0 - PF7
|
||||
_BV(6), // D19 - A1 - PF6
|
||||
_BV(5), // D20 - A2 - PF5
|
||||
_BV(4), // D21 - A3 - PF4
|
||||
_BV(1), // D22 - A4 - PF1
|
||||
_BV(0), // D23 - A5 - PF0
|
||||
|
||||
_BV(5), // D24 - PD5
|
||||
_BV(7), // D25 / D6 - A7 - PD7
|
||||
_BV(4), // D26 / D8 - A8 - PB4
|
||||
_BV(5), // D27 / D9 - A9 - PB5
|
||||
_BV(6), // D28 / D10 - A10 - PB6
|
||||
_BV(6), // D29 / D12 - A11 - PD6
|
||||
};
|
||||
|
||||
const uint8_t PROGMEM digital_pin_to_timer_PGM[] = {
|
||||
NOT_ON_TIMER,
|
||||
NOT_ON_TIMER,
|
||||
NOT_ON_TIMER,
|
||||
TIMER0B, /* 3 */
|
||||
NOT_ON_TIMER,
|
||||
TIMER3A, /* 5 */
|
||||
TIMER4D, /* 6 */
|
||||
NOT_ON_TIMER,
|
||||
|
||||
NOT_ON_TIMER,
|
||||
TIMER1A, /* 9 */
|
||||
TIMER1B, /* 10 */
|
||||
TIMER0A, /* 11 */
|
||||
|
||||
NOT_ON_TIMER,
|
||||
TIMER4A, /* 13 */
|
||||
|
||||
NOT_ON_TIMER,
|
||||
NOT_ON_TIMER,
|
||||
NOT_ON_TIMER,
|
||||
NOT_ON_TIMER,
|
||||
NOT_ON_TIMER,
|
||||
NOT_ON_TIMER,
|
||||
|
||||
NOT_ON_TIMER,
|
||||
NOT_ON_TIMER,
|
||||
NOT_ON_TIMER,
|
||||
NOT_ON_TIMER,
|
||||
NOT_ON_TIMER,
|
||||
NOT_ON_TIMER,
|
||||
NOT_ON_TIMER,
|
||||
NOT_ON_TIMER,
|
||||
NOT_ON_TIMER,
|
||||
NOT_ON_TIMER,
|
||||
};
|
||||
|
||||
const uint8_t PROGMEM analog_pin_to_channel_PGM[] = {
|
||||
7, // A0 PF7 ADC7
|
||||
6, // A1 PF6 ADC6
|
||||
5, // A2 PF5 ADC5
|
||||
4, // A3 PF4 ADC4
|
||||
1, // A4 PF1 ADC1
|
||||
0, // A5 PF0 ADC0
|
||||
8, // A6 D4 PD4 ADC8
|
||||
10, // A7 D6 PD7 ADC10
|
||||
11, // A8 D8 PB4 ADC11
|
||||
12, // A9 D9 PB5 ADC12
|
||||
13, // A10 D10 PB6 ADC13
|
||||
9 // A11 D12 PD6 ADC9
|
||||
};
|
||||
|
||||
#endif /* ARDUINO_MAIN */
|
||||
|
||||
// These serial port names are intended to allow libraries and architecture-neutral
|
||||
// sketches to automatically default to the correct port name for a particular type
|
||||
// of use. For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN,
|
||||
// the first hardware serial port whose RX/TX pins are not dedicated to another use.
|
||||
//
|
||||
// SERIAL_PORT_MONITOR Port which normally prints to the Arduino Serial Monitor
|
||||
//
|
||||
// SERIAL_PORT_USBVIRTUAL Port which is USB virtual serial
|
||||
//
|
||||
// SERIAL_PORT_LINUXBRIDGE Port which connects to a Linux system via Bridge library
|
||||
//
|
||||
// SERIAL_PORT_HARDWARE Hardware serial port, physical RX & TX pins.
|
||||
//
|
||||
// SERIAL_PORT_HARDWARE_OPEN Hardware serial ports which are open for use. Their RX & TX
|
||||
// pins are NOT connected to anything by default.
|
||||
#define SERIAL_PORT_MONITOR Serial
|
||||
#define SERIAL_PORT_USBVIRTUAL Serial
|
||||
#define SERIAL_PORT_HARDWARE Serial1
|
||||
#define SERIAL_PORT_HARDWARE_OPEN Serial1
|
||||
|
||||
#endif /* Pins_Arduino_h */
|
225
keyboard/25/serial.c
Normal file
225
keyboard/25/serial.c
Normal file
@ -0,0 +1,225 @@
|
||||
/*
|
||||
* WARNING: be careful changing this code, it is very timing dependent
|
||||
*/
|
||||
|
||||
#ifndef F_CPU
|
||||
#define F_CPU 16000000
|
||||
#endif
|
||||
|
||||
#include <avr/io.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <util/delay.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "serial.h"
|
||||
|
||||
// Serial pulse period in microseconds. Its probably a bad idea to lower this
|
||||
// value.
|
||||
#define SERIAL_DELAY 24
|
||||
|
||||
uint8_t volatile serial_slave_buffer[SERIAL_SLAVE_BUFFER_LENGTH] = {0};
|
||||
uint8_t volatile serial_master_buffer[SERIAL_MASTER_BUFFER_LENGTH] = {0};
|
||||
|
||||
#define SLAVE_DATA_CORRUPT (1<<0)
|
||||
volatile uint8_t status = 0;
|
||||
|
||||
inline static
|
||||
void serial_delay(void) {
|
||||
_delay_us(SERIAL_DELAY);
|
||||
}
|
||||
|
||||
inline static
|
||||
void serial_output(void) {
|
||||
SERIAL_PIN_DDR |= SERIAL_PIN_MASK;
|
||||
}
|
||||
|