parent
46e7fb2d3c
commit
35a81f5b8b
@ -0,0 +1,139 @@ |
|||||||
|
#----------------------------------------------------------------------------
|
||||||
|
# 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 = ergodox
|
||||||
|
|
||||||
|
|
||||||
|
# Directory common source filess exist
|
||||||
|
TOP_DIR = ../..
|
||||||
|
|
||||||
|
# Directory keyboard dependent files exist
|
||||||
|
TARGET_DIR = .
|
||||||
|
|
||||||
|
# # project specific files
|
||||||
|
SRC = ergodox.c \
|
||||||
|
twimaster.c \
|
||||||
|
backlight.c
|
||||||
|
|
||||||
|
ifdef KEYMAP |
||||||
|
SRC := keymaps/keymap_$(KEYMAP).c $(SRC)
|
||||||
|
else |
||||||
|
SRC := keymaps/keymap_default.c $(SRC)
|
||||||
|
endif |
||||||
|
|
||||||
|
CONFIG_H = config.h
|
||||||
|
|
||||||
|
# MCU name
|
||||||
|
#MCU = at90usb1287
|
||||||
|
MCU = atmega32u4
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
|
||||||
|
# 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
|
||||||
|
# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
|
||||||
|
# SLEEP_LED_ENABLE = yes # Breathing sleep LED during USB suspend
|
||||||
|
# NKRO_ENABLE = yes # USB Nkey Rollover - not yet supported in LUFA
|
||||||
|
# BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality
|
||||||
|
# MIDI_ENABLE = YES # MIDI controls
|
||||||
|
# UNICODE_ENABLE = YES # Unicode
|
||||||
|
# BLUETOOTH_ENABLE = yes # Enable Bluetooth with the Adafruit EZ-Key HID
|
||||||
|
|
||||||
|
|
||||||
|
# Optimize size but this may cause error "relocation truncated to fit"
|
||||||
|
#EXTRALDFLAGS = -Wl,--relax
|
||||||
|
|
||||||
|
# Search Path
|
||||||
|
VPATH += $(TARGET_DIR)
|
||||||
|
VPATH += $(TOP_DIR)
|
||||||
|
|
||||||
|
include $(TOP_DIR)/quantum.mk |
||||||
|
|
@ -0,0 +1,56 @@ |
|||||||
|
# TMK Generic |
||||||
|
|
||||||
|
* I'm not sure what the Magic + H does. |
||||||
|
Is this a menu that will pop up regardless of what platform and program is open? |
||||||
|
|
||||||
|
Yes, this is sort of debugging. |
||||||
|
Use PJRC's [hid_listen](https://www.pjrc.com/teensy/hid_listen.html) to see debug messages. |
||||||
|
|
||||||
|
# TMK/Ergodox specific |
||||||
|
|
||||||
|
* I would like to configure my leds to indicate the active layer. |
||||||
|
I read that can be done, but I haven't seen an example for this firmware. |
||||||
|
Can someone please post an example or a link? |
||||||
|
|
||||||
|
TMK for Ergodox have support for seven (!) led's: |
||||||
|
- three on right |
||||||
|
- three on left (see http://geekhack.org/index.php?topic=22780.msg873819#msg873819 for more details) |
||||||
|
- Teensy onboard led as well |
||||||
|
|
||||||
|
Any of these leds can be used as layer indicator or NumLock/CapsLock/ScrollLock led. |
||||||
|
|
||||||
|
[Here is example](https://github.com/cub-uanic/tmk_keyboard/blob/cub_layout/keyboard/ergodox/matrix.c#L121-167) |
||||||
|
how you can assign some meaning to each led. |
||||||
|
In this code only left leds are used to show layers, but you can |
||||||
|
[change `led_set()`](https://github.com/cub-uanic/tmk_keyboard/blob/cub_layout/keyboard/ergodox/led.c) |
||||||
|
and do anything you want with all leds. |
||||||
|
|
||||||
|
# Firmware |
||||||
|
|
||||||
|
Q: Where to get binaries? |
||||||
|
A: |
||||||
|
|
||||||
|
Q: Where to get sources? |
||||||
|
A: |
||||||
|
|
||||||
|
Q: How to compile? |
||||||
|
A: |
||||||
|
|
||||||
|
|
||||||
|
# Layouts |
||||||
|
|
||||||
|
description of layouts in base firmware binaries |
||||||
|
|
||||||
|
|
||||||
|
# Things TO-DO |
||||||
|
|
||||||
|
- [ ] Flash NumLock led only when "numpad" layer is active |
||||||
|
- [ ] Command (in terms of IS_COMMAND) to switch to no-leds mode |
||||||
|
- [ ] Increase count of ACTION keys |
||||||
|
- [ ] Fix command_state() onboard led: it should flash only when kbd in some specific mode (CONSOLE || MOUSE) |
||||||
|
- [ ] ergodox_blink_all_leds() should save current state of leds, and restore after blink. initial state of all leds == off |
||||||
|
- [ ] add support for pseudo-backlight (reversed LEDs) + docs/photo |
||||||
|
- [ ] command to debug all LEDs (on/off/blink) |
||||||
|
- [ ] proper (in-core) implementation of DEBUG_MATRIX_SCAN_RATE (non-Ergodox specific) |
||||||
|
- [ ] proper (in-core) support for per-layer fn_actions[] |
||||||
|
|
@ -0,0 +1,61 @@ |
|||||||
|
|
||||||
|
#include <avr/io.h> |
||||||
|
#include "backlight.h" |
||||||
|
|
||||||
|
#define CHANNEL OCR1C |
||||||
|
|
||||||
|
void backlight_init_ports() |
||||||
|
{ |
||||||
|
|
||||||
|
// Setup PB7 as output and output low.
|
||||||
|
DDRB |= (1<<7); |
||||||
|
PORTB &= ~(1<<7); |
||||||
|
|
||||||
|
// Use full 16-bit resolution.
|
||||||
|
ICR1 = 0xFFFF; |
||||||
|
|
||||||
|
// I could write a wall of text here to explain... but TL;DW
|
||||||
|
// Go read the ATmega32u4 datasheet.
|
||||||
|
// And this: http://blog.saikoled.com/post/43165849837/secret-konami-cheat-code-to-high-resolution-pwm-on
|
||||||
|
|
||||||
|
// Pin PB7 = OCR1C (Timer 1, Channel C)
|
||||||
|
// Compare Output Mode = Clear on compare match, Channel C = COM1C1=1 COM1C0=0
|
||||||
|
// (i.e. start high, go low when counter matches.)
|
||||||
|
// WGM Mode 14 (Fast PWM) = WGM13=1 WGM12=1 WGM11=1 WGM10=0
|
||||||
|
// Clock Select = clk/1 (no prescaling) = CS12=0 CS11=0 CS10=1
|
||||||
|
|
||||||
|
TCCR1A = _BV(COM1C1) | _BV(WGM11); // = 0b00001010;
|
||||||
|
TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10); // = 0b00011001;
|
||||||
|
|
||||||
|
backlight_init(); |
||||||
|
} |
||||||
|
|
||||||
|
void backlight_set(uint8_t level) |
||||||
|
{ |
||||||
|
if ( level == 0 ) |
||||||
|
{ |
||||||
|
// Turn off PWM control on PB7, revert to output low.
|
||||||
|
TCCR1A &= ~(_BV(COM1C1)); |
||||||
|
CHANNEL = 0x0; |
||||||
|
// Prevent backlight blink on lowest level
|
||||||
|
PORTB &= ~(_BV(PORTB7)); |
||||||
|
} |
||||||
|
else if ( level == BACKLIGHT_LEVELS ) |
||||||
|
{ |
||||||
|
// Prevent backlight blink on lowest level
|
||||||
|
PORTB &= ~(_BV(PORTB7)); |
||||||
|
// Turn on PWM control of PB7
|
||||||
|
TCCR1A |= _BV(COM1C1); |
||||||
|
// Set the brightness
|
||||||
|
CHANNEL = 0xFFFF; |
||||||
|
} |
||||||
|
else
|
||||||
|
{ |
||||||
|
// Prevent backlight blink on lowest level
|
||||||
|
PORTB &= ~(_BV(PORTB7)); |
||||||
|
// Turn on PWM control of PB7
|
||||||
|
TCCR1A |= _BV(COM1C1); |
||||||
|
// Set the brightness
|
||||||
|
CHANNEL = 0xFFFF >> ((BACKLIGHT_LEVELS - level) * ((BACKLIGHT_LEVELS + 1) / 2)); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,88 @@ |
|||||||
|
/*
|
||||||
|
Copyright 2012 Jun Wako <wakojun@gmail.com> |
||||||
|
Copyright 2013 Oleg Kostyuk <cub.uanic@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 |
||||||
|
|
||||||
|
#include "config_common.h" |
||||||
|
|
||||||
|
/* USB Device descriptor parameter */ |
||||||
|
#define VENDOR_ID 0xFEED |
||||||
|
#define PRODUCT_ID 0x1307 |
||||||
|
#define DEVICE_VER 0x0001 |
||||||
|
#define MANUFACTURER ErgoDox EZ |
||||||
|
#define PRODUCT ErgoDox EZ |
||||||
|
#define DESCRIPTION t.m.k. keyboard firmware for Ergodox |
||||||
|
|
||||||
|
/* key matrix size */ |
||||||
|
#define MATRIX_ROWS 14 |
||||||
|
#define MATRIX_COLS 6 |
||||||
|
|
||||||
|
#define MOUSEKEY_DELAY 100 |
||||||
|
#define MOUSEKEY_INTERVAL 20 |
||||||
|
#define MOUSEKEY_MAX_SPEED 3 |
||||||
|
#define MOUSEKEY_TIME_TO_MAX 10 |
||||||
|
|
||||||
|
#define COLS (int []){ F1, F0, B0, C7, F4, F5, F6, F7, D4, D6, B4, D7 } |
||||||
|
#define ROWS (int []){ D0, D5, B5, B6 } |
||||||
|
|
||||||
|
/* COL2ROW or ROW2COL */ |
||||||
|
#define DIODE_DIRECTION COL2ROW |
||||||
|
|
||||||
|
/* define if matrix has ghost */ |
||||||
|
//#define MATRIX_HAS_GHOST
|
||||||
|
|
||||||
|
/* number of backlight levels */ |
||||||
|
#define BACKLIGHT_LEVELS 3 |
||||||
|
|
||||||
|
/* Set 0 if debouncing isn't needed */ |
||||||
|
#define DEBOUNCE 2 |
||||||
|
#define TAPPING_TERM 230 |
||||||
|
#define TAPPING_TOGGLE 2 |
||||||
|
|
||||||
|
/* 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 |
||||||
|
|
||||||
|
/* key combination for command */ |
||||||
|
#define IS_COMMAND() ( \ |
||||||
|
keyboard_report->mods == (MOD_BIT(KC_LCTL) | MOD_BIT(KC_RCTL)) || \
|
||||||
|
keyboard_report->mods == (MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)) \
|
||||||
|
) |
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
//#define DEBUG_MATRIX_SCAN_RATE
|
||||||
|
|
||||||
|
#endif |
@ -0,0 +1,121 @@ |
|||||||
|
#include "ergodox.h" |
||||||
|
#include "i2cmaster.h" |
||||||
|
|
||||||
|
bool i2c_initialized = 0; |
||||||
|
uint8_t mcp23018_status = 0x20; |
||||||
|
|
||||||
|
bool ergodox_left_led_1 = 0; // left top
|
||||||
|
bool ergodox_left_led_2 = 0; // left middle
|
||||||
|
bool ergodox_left_led_3 = 0; // left bottom
|
||||||
|
|
||||||
|
void * matrix_init_user(void) { |
||||||
|
|
||||||
|
}; |
||||||
|
|
||||||
|
void * matrix_scan_user(void) { |
||||||
|
|
||||||
|
}; |
||||||
|
|
||||||
|
void * matrix_init_kb(void) { |
||||||
|
// keyboard LEDs (see "PWM on ports OC1(A|B|C)" in "teensy-2-0.md")
|
||||||
|
TCCR1A = 0b10101001; // set and configure fast PWM
|
||||||
|
TCCR1B = 0b00001001; // set and configure fast PWM
|
||||||
|
|
||||||
|
// (tied to Vcc for hardware convenience)
|
||||||
|
DDRB &= ~(1<<4); // set B(4) as input
|
||||||
|
PORTB &= ~(1<<4); // set B(4) internal pull-up disabled
|
||||||
|
|
||||||
|
// unused pins - C7, D4, D5, D7, E6
|
||||||
|
// set as input with internal pull-ip enabled
|
||||||
|
DDRC &= ~(1<<7); |
||||||
|
DDRD &= ~(1<<7 | 1<<5 | 1<<4); |
||||||
|
DDRE &= ~(1<<6); |
||||||
|
PORTC |= (1<<7); |
||||||
|
PORTD |= (1<<7 | 1<<5 | 1<<4); |
||||||
|
PORTE |= (1<<6); |
||||||
|
|
||||||
|
ergodox_blink_all_leds(); |
||||||
|
|
||||||
|
if (matrix_init_user) { |
||||||
|
(*matrix_init_user)(); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
void * matrix_scan_kb(void) { |
||||||
|
|
||||||
|
if (matrix_scan_user) { |
||||||
|
(*matrix_scan_user)(); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
void ergodox_blink_all_leds(void) |
||||||
|
{ |
||||||
|
ergodox_led_all_off(); |
||||||
|
ergodox_led_all_set(LED_BRIGHTNESS_HI); |
||||||
|
ergodox_led_all_on(); |
||||||
|
_delay_ms(333); |
||||||
|
ergodox_led_all_off(); |
||||||
|
} |
||||||
|
|
||||||
|
uint8_t init_mcp23018(void) { |
||||||
|
mcp23018_status = 0x20; |
||||||
|
|
||||||
|
// I2C subsystem
|
||||||
|
if (i2c_initialized == 0) { |
||||||
|
i2c_init(); // on pins D(1,0)
|
||||||
|
i2c_initialized++; |
||||||
|
_delay_ms(1000); |
||||||
|
} |
||||||
|
|
||||||
|
// set pin direction
|
||||||
|
// - unused : input : 1
|
||||||
|
// - input : input : 1
|
||||||
|
// - driving : output : 0
|
||||||
|
mcp23018_status = i2c_start(I2C_ADDR_WRITE); if (mcp23018_status) goto out; |
||||||
|
mcp23018_status = i2c_write(IODIRA); if (mcp23018_status) goto out; |
||||||
|
mcp23018_status = i2c_write(0b00000000); if (mcp23018_status) goto out; |
||||||
|
mcp23018_status = i2c_write(0b00111111); if (mcp23018_status) goto out; |
||||||
|
i2c_stop(); |
||||||
|
|
||||||
|
// set pull-up
|
||||||
|
// - unused : on : 1
|
||||||
|
// - input : on : 1
|
||||||
|
// - driving : off : 0
|
||||||
|
mcp23018_status = i2c_start(I2C_ADDR_WRITE); if (mcp23018_status) goto out; |
||||||
|
mcp23018_status = i2c_write(GPPUA); if (mcp23018_status) goto out; |
||||||
|
mcp23018_status = i2c_write(0b00000000); if (mcp23018_status) goto out; |
||||||
|
mcp23018_status = i2c_write(0b00111111); if (mcp23018_status) goto out; |
||||||
|
|
||||||
|
out: |
||||||
|
i2c_stop(); |
||||||
|
|
||||||
|
if (!mcp23018_status) mcp23018_status = ergodox_left_leds_update(); |
||||||
|
|
||||||
|
return mcp23018_status; |
||||||
|
} |
||||||
|
|
||||||
|
uint8_t ergodox_left_leds_update(void) { |
||||||
|
if (mcp23018_status) { // if there was an error
|
||||||
|
return mcp23018_status; |
||||||
|
} |
||||||
|
|
||||||
|
// set logical value (doesn't matter on inputs)
|
||||||
|
// - unused : hi-Z : 1
|
||||||
|
// - input : hi-Z : 1
|
||||||
|
// - driving : hi-Z : 1
|
||||||
|
mcp23018_status = i2c_start(I2C_ADDR_WRITE); if (mcp23018_status) goto out; |
||||||
|
mcp23018_status = i2c_write(OLATA); if (mcp23018_status) goto out; |
||||||
|
mcp23018_status = i2c_write(0b11111111 |
||||||
|
& ~(ergodox_left_led_3<<LEFT_LED_3_SHIFT) |
||||||
|
); if (mcp23018_status) goto out; |
||||||
|
mcp23018_status = i2c_write(0b11111111 |
||||||
|
& ~(ergodox_left_led_2<<LEFT_LED_2_SHIFT) |
||||||
|
& ~(ergodox_left_led_1<<LEFT_LED_1_SHIFT) |
||||||
|
); if (mcp23018_status) goto out; |
||||||
|
|
||||||
|
out: |
||||||
|
i2c_stop(); |
||||||
|
return mcp23018_status; |
||||||
|
} |
||||||
|
|
@ -0,0 +1,145 @@ |
|||||||
|
#ifndef PLANCK_H |
||||||
|
#define PLANCK_H |
||||||
|
|
||||||
|
#include "matrix.h" |
||||||
|
#include "keymap_common.h" |
||||||
|
#include "backlight.h" |
||||||
|
#include <stddef.h> |
||||||
|
#include <stdint.h> |
||||||
|
#include <stdbool.h> |
||||||
|
#include <avr/io.h> |
||||||
|
#include "i2cmaster.h" |
||||||
|
#include <util/delay.h> |
||||||
|
|
||||||
|
#define CPU_PRESCALE(n) (CLKPR = 0x80, CLKPR = (n)) |
||||||
|
#define CPU_16MHz 0x00 |
||||||
|
|
||||||
|
// I2C aliases and register addresses (see "mcp23018.md")
|
||||||
|
#define I2C_ADDR 0b0100000 |
||||||
|
#define I2C_ADDR_WRITE ( (I2C_ADDR<<1) | I2C_WRITE ) |
||||||
|
#define I2C_ADDR_READ ( (I2C_ADDR<<1) | I2C_READ ) |
||||||
|
#define IODIRA 0x00 // i/o direction register
|
||||||
|
#define IODIRB 0x01 |
||||||
|
#define GPPUA 0x0C // GPIO pull-up resistor register
|
||||||
|
#define GPPUB 0x0D |
||||||
|
#define GPIOA 0x12 // general purpose i/o port register (write modifies OLAT)
|
||||||
|
#define GPIOB 0x13 |
||||||
|
#define OLATA 0x14 // output latch register
|
||||||
|
#define OLATB 0x15 |
||||||
|
|
||||||
|
extern uint8_t mcp23018_status; |
||||||
|
|
||||||
|
void init_ergodox(void); |
||||||
|
void ergodox_blink_all_leds(void); |
||||||
|
uint8_t init_mcp23018(void); |
||||||
|
uint8_t ergodox_left_leds_update(void); |
||||||
|
|
||||||
|
#define LED_BRIGHTNESS_LO 31 |
||||||
|
#define LED_BRIGHTNESS_HI 255 |
||||||
|
|
||||||
|
#define LEFT_LED_1_SHIFT 7 // in MCP23018 port B
|
||||||
|
#define LEFT_LED_2_SHIFT 6 // in MCP23018 port B
|
||||||
|
#define LEFT_LED_3_SHIFT 7 // in MCP23018 port A
|
||||||
|
|
||||||
|
extern bool ergodox_left_led_1; // left top
|
||||||
|
extern bool ergodox_left_led_2; // left middle
|
||||||
|
extern bool ergodox_left_led_3; // left bottom
|
||||||
|
|
||||||
|
inline void ergodox_board_led_on(void) { DDRD |= (1<<6); PORTD |= (1<<6); } |
||||||
|
inline void ergodox_right_led_1_on(void) { DDRB |= (1<<5); PORTB |= (1<<5); } |
||||||
|
inline void ergodox_right_led_2_on(void) { DDRB |= (1<<6); PORTB |= (1<<6); } |
||||||
|
inline void ergodox_right_led_3_on(void) { DDRB |= (1<<7); PORTB |= (1<<7); } |
||||||
|
inline void ergodox_left_led_1_on(void) { ergodox_left_led_1 = 1; } |
||||||
|
inline void ergodox_left_led_2_on(void) { ergodox_left_led_2 = 1; } |
||||||
|
inline void ergodox_left_led_3_on(void) { ergodox_left_led_3 = 1; } |
||||||
|
|
||||||
|
inline void ergodox_board_led_off(void) { DDRD &= ~(1<<6); PORTD &= ~(1<<6); } |
||||||
|
inline void ergodox_right_led_1_off(void) { DDRB &= ~(1<<5); PORTB &= ~(1<<5); } |
||||||
|
inline void ergodox_right_led_2_off(void) { DDRB &= ~(1<<6); PORTB &= ~(1<<6); } |
||||||
|
inline void ergodox_right_led_3_off(void) { DDRB &= ~(1<<7); PORTB &= ~(1<<7); } |
||||||
|
inline void ergodox_left_led_1_off(void) { ergodox_left_led_1 = 0; } |
||||||
|
inline void ergodox_left_led_2_off(void) { ergodox_left_led_2 = 0; } |
||||||
|
inline void ergodox_left_led_3_off(void) { ergodox_left_led_3 = 0; } |
||||||
|
|
||||||
|
inline void ergodox_led_all_on(void) |
||||||
|
{ |
||||||
|
ergodox_board_led_on(); |
||||||
|
ergodox_right_led_1_on(); |
||||||
|
ergodox_right_led_2_on(); |
||||||
|
ergodox_right_led_3_on(); |
||||||
|
ergodox_left_led_1_on(); |
||||||
|
ergodox_left_led_2_on(); |
||||||
|
ergodox_left_led_3_on(); |
||||||
|
ergodox_left_leds_update(); |
||||||
|
} |
||||||
|
|
||||||
|
inline void ergodox_led_all_off(void) |
||||||
|
{ |
||||||
|
ergodox_board_led_off(); |
||||||
|
ergodox_right_led_1_off(); |
||||||
|
ergodox_right_led_2_off(); |
||||||
|
ergodox_right_led_3_off(); |
||||||
|
ergodox_left_led_1_off(); |
||||||
|
ergodox_left_led_2_off(); |
||||||
|
ergodox_left_led_3_off(); |
||||||
|
ergodox_left_leds_update(); |
||||||
|
} |
||||||
|
|
||||||
|
inline void ergodox_right_led_1_set(uint8_t n) { OCR1A = n; } |
||||||
|
inline void ergodox_right_led_2_set(uint8_t n) { OCR1B = n; } |
||||||
|
inline void ergodox_right_led_3_set(uint8_t n) { OCR1C = n; } |
||||||
|
|
||||||
|
inline void ergodox_led_all_set(uint8_t n) |
||||||
|
{ |
||||||
|
ergodox_right_led_1_set(n); |
||||||
|
ergodox_right_led_2_set(n); |
||||||
|
ergodox_right_led_3_set(n); |
||||||
|
} |
||||||
|
|
||||||
|
#define KEYMAP( \ |
||||||
|
\
|
||||||
|
/* left hand, spatial positions */ \
|
||||||
|
k00,k01,k02,k03,k04,k05,k06, \
|
||||||
|
k10,k11,k12,k13,k14,k15,k16, \
|
||||||
|
k20,k21,k22,k23,k24,k25, \
|
||||||
|
k30,k31,k32,k33,k34,k35,k36, \
|
||||||
|
k40,k41,k42,k43,k44, \
|
||||||
|
k55,k56, \
|
||||||
|
k54, \
|
||||||
|
k53,k52,k51, \
|
||||||
|
\
|
||||||
|
/* right hand, spatial positions */ \
|
||||||
|
k07,k08,k09,k0A,k0B,k0C,k0D, \
|
||||||
|
k17,k18,k19,k1A,k1B,k1C,k1D, \
|
||||||
|
k28,k29,k2A,k2B,k2C,k2D, \
|
||||||
|
k37,k38,k39,k3A,k3B,k3C,k3D, \
|
||||||
|
k49,k4A,k4B,k4C,k4D, \
|
||||||
|
k57,k58, \
|
||||||
|
k59, \
|
||||||
|
k5C,k5B,k5A ) \
|
||||||
|
\
|
||||||
|
/* matrix positions */ \
|
||||||
|
{ \
|
||||||
|
{ k00, k10, k20, k30, k40, KC_NO }, \
|
||||||
|
{ k01, k11, k21, k31, k41, k51 }, \
|
||||||
|
{ k02, k12, k22, k32, k42, k52 }, \
|
||||||
|
{ k03, k13, k23, k33, k43, k53 }, \
|
||||||
|
{ k04, k14, k24, k34, k44, k54 }, \
|
||||||
|
{ k05, k15, k25, k35, KC_NO, k55 }, \
|
||||||
|
{ k06, k16, KC_NO, k36, KC_NO, k56 }, \
|
||||||
|
\
|
||||||
|
{ k07, k17, KC_NO, k37,KC_NO, k57 }, \
|
||||||
|
{ k08, k18, k28, k38,KC_NO, k58 }, \
|
||||||
|
{ k09, k19, k29, k39, k49, k59 }, \
|
||||||
|
{ k0A, k1A, k2A, k3A, k4A, k5A }, \
|
||||||
|
{ k0B, k1B, k2B, k3B, k4B, k5B }, \
|
||||||
|
{ k0C, k1C, k2C, k3C, k4C, k5C }, \
|
||||||
|
{ k0D, k1D, k2D, k3D, k4D, KC_NO } \
|
||||||
|
} |
||||||
|
|
||||||
|
void * matrix_init_user(void); |
||||||
|
void * matrix_scan_user(void); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif |
@ -0,0 +1,178 @@ |
|||||||
|
#ifndef _I2CMASTER_H |
||||||
|
#define _I2CMASTER_H 1 |
||||||
|
/*************************************************************************
|
||||||
|
* Title: C include file for the I2C master interface
|
||||||
|
* (i2cmaster.S or twimaster.c) |
||||||
|
* Author: Peter Fleury <pfleury@gmx.ch> http://jump.to/fleury
|
||||||
|
* File: $Id: i2cmaster.h,v 1.10 2005/03/06 22:39:57 Peter Exp $ |
||||||
|
* Software: AVR-GCC 3.4.3 / avr-libc 1.2.3 |
||||||
|
* Target: any AVR device |
||||||
|
* Usage: see Doxygen manual |
||||||
|
**************************************************************************/ |
||||||
|
|
||||||
|
#ifdef DOXYGEN |
||||||
|
/**
|
||||||
|
@defgroup pfleury_ic2master I2C Master library |
||||||
|
@code #include <i2cmaster.h> @endcode |
||||||
|
|
||||||
|
@brief I2C (TWI) Master Software Library |
||||||
|
|
||||||
|
Basic routines for communicating with I2C slave devices. This single master
|
||||||
|
implementation is limited to one bus master on the I2C bus.
|
||||||
|
|
||||||
|
This I2c library is implemented as a compact assembler software implementation of the I2C protocol
|
||||||
|
which runs on any AVR (i2cmaster.S) and as a TWI hardware interface for all AVR with built-in TWI hardware (twimaster.c). |
||||||
|
Since the API for these two implementations is exactly the same, an application can be linked either against the |
||||||
|
software I2C implementation or the hardware I2C implementation. |
||||||
|
|
||||||
|
Use 4.7k pull-up resistor on the SDA and SCL pin. |
||||||
|
|
||||||
|
Adapt the SCL and SDA port and pin definitions and eventually the delay routine in the module
|
||||||
|
i2cmaster.S to your target when using the software I2C implementation !
|
||||||
|
|
||||||
|
Adjust the CPU clock frequence F_CPU in twimaster.c or in the Makfile when using the TWI hardware implementaion. |
||||||
|
|
||||||
|
@note
|
||||||
|
The module i2cmaster.S is based on the Atmel Application Note AVR300, corrected and adapted
|
||||||
|
to GNU assembler and AVR-GCC C call interface. |
||||||
|
Replaced the incorrect quarter period delays found in AVR300 with
|
||||||
|
half period delays.
|
||||||
|
|
||||||
|
@author Peter Fleury pfleury@gmx.ch http://jump.to/fleury
|
||||||
|
|
||||||
|
@par API Usage Example |
||||||
|
The following code shows typical usage of this library, see example test_i2cmaster.c |
||||||
|
|
||||||
|
@code |
||||||
|
|
||||||
|
#include <i2cmaster.h> |
||||||
|
|
||||||
|
|
||||||
|
#define Dev24C02 0xA2 // device address of EEPROM 24C02, see datasheet
|
||||||
|
|
||||||
|
int main(void) |
||||||
|
{ |
||||||
|
unsigned char ret; |
||||||
|
|
||||||
|
i2c_init(); // initialize I2C library
|
||||||
|
|
||||||
|
// write 0x75 to EEPROM address 5 (Byte Write)
|
||||||
|
i2c_start_wait(Dev24C02+I2C_WRITE); // set device address and write mode
|
||||||
|
i2c_write(0x05); // write address = 5
|
||||||
|
i2c_write(0x75); // write value 0x75 to EEPROM
|
||||||
|
i2c_stop(); // set stop conditon = release bus
|
||||||
|
|
||||||
|
|
||||||
|
// read previously written value back from EEPROM address 5
|
||||||
|
i2c_start_wait(Dev24C02+I2C_WRITE); // set device address and write mode
|
||||||
|
|
||||||
|
i2c_write(0x05); // write address = 5
|
||||||
|
i2c_rep_start(Dev24C02+I2C_READ); // set device address and read mode
|
||||||
|
|
||||||
|
ret = i2c_readNak(); // read one byte from EEPROM
|
||||||
|
i2c_stop(); |
||||||
|
|
||||||
|
for(;;); |
||||||
|
} |
||||||
|
@endcode |
||||||
|
|
||||||
|
*/ |
||||||
|
#endif /* DOXYGEN */ |
||||||
|
|
||||||
|
/**@{*/ |
||||||
|
|
||||||
|
#if (__GNUC__ * 100 + __GNUC_MINOR__) < 304 |
||||||
|
#error "This library requires AVR-GCC 3.4 or later, update to newer AVR-GCC compiler !" |
||||||
|
#endif |
||||||
|
|
||||||
|
#include <avr/io.h> |
||||||
|
|
||||||
|
/** defines the data direction (reading from I2C device) in i2c_start(),i2c_rep_start() */ |
||||||
|
#define I2C_READ 1 |
||||||
|
|
||||||
|
/** defines the data direction (writing to I2C device) in i2c_start(),i2c_rep_start() */ |
||||||
|
#define I2C_WRITE 0 |
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief initialize the I2C master interace. Need to be called only once
|
||||||
|
@param void |
||||||
|
@return none |
||||||
|
*/ |
||||||
|
extern void i2c_init(void); |
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Terminates the data transfer and releases the I2C bus
|
||||||
|
@param void |
||||||
|
@return none |
||||||
|
*/ |
||||||
|
extern void i2c_stop(void); |
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Issues a start condition and sends address and transfer direction
|
||||||
|
|
||||||
|
@param addr address and transfer direction of I2C device |
||||||
|
@retval 0 device accessible
|
||||||
|
@retval 1 failed to access device
|
||||||
|
*/ |
||||||
|
extern unsigned char i2c_start(unsigned char addr); |
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Issues a repeated start condition and sends address and transfer direction
|
||||||
|
|
||||||
|
@param addr address and transfer direction of I2C device |
||||||
|
@retval 0 device accessible |
||||||
|
@retval 1 failed to access device |
||||||
|
*/ |
||||||
|
extern unsigned char i2c_rep_start(unsigned char addr); |
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Issues a start condition and sends address and transfer direction
|
||||||
|
|
||||||
|
If device is busy, use ack polling to wait until device ready
|
||||||
|
@param addr address and transfer direction of I2C device |
||||||
|
@return none |
||||||
|
*/ |
||||||
|
extern void i2c_start_wait(unsigned char addr); |
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Send one byte to I2C device |
||||||
|
@param data byte to be transfered |
||||||
|
@retval 0 write successful |
||||||
|
@retval 1 write failed |
||||||
|
*/ |
||||||
|
extern unsigned char i2c_write(unsigned char data); |
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief read one byte from the I2C device, request more data from device
|
||||||
|
@return byte read from I2C device |
||||||
|
*/ |
||||||
|
extern unsigned char i2c_readAck(void); |
||||||
|
|
||||||
|
/**
|
||||||
|
@brief read one byte from the I2C device, read is followed by a stop condition
|
||||||
|
@return byte read from I2C device |
||||||
|
*/ |
||||||
|
extern unsigned char i2c_readNak(void); |
||||||
|
|
||||||
|
/**
|
||||||
|
@brief read one byte from the I2C device |
||||||
|
|
||||||
|
Implemented as a macro, which calls either i2c_readAck or i2c_readNak |
||||||
|
|
||||||
|
@param ack 1 send ack, request more data from device<br> |
||||||
|
0 send nak, read is followed by a stop condition
|
||||||
|
@return byte read from I2C device |
||||||
|
*/ |
||||||
|
extern unsigned char i2c_read(unsigned char ack); |
||||||
|
#define i2c_read(ack) (ack) ? i2c_readAck() : i2c_readNak(); |
||||||
|
|
||||||
|
|
||||||
|
/**@}*/ |
||||||
|
#endif |
@ -0,0 +1,76 @@ |
|||||||
|
#include "ergodox.h" |
||||||
|
#include "debug.h" |
||||||
|
|
||||||
|
#define DEFAULT_LAYER 0 |
||||||
|
#define COLEMAK_LAYER 1 |
||||||
|
#define DVORAK_LAYER 2 |
||||||
|
#define LOWER_LAYER 1 |
||||||
|
#define RAISE_LAYER 4 |
||||||
|
|
||||||
|
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { |
||||||
|
[DEFAULT_LAYER] = KEYMAP( // layer 0 : default
|
||||||
|
// left hand
|
||||||
|
KC_EQL, KC_1, KC_2, KC_3, KC_4, KC_5, KC_ESC, |
||||||
|
KC_BSLS,KC_Q, KC_W, KC_E, KC_R, KC_T, KC_FN2, |
||||||
|
KC_TAB, KC_A, KC_S, KC_D, KC_F, KC_G, |
||||||
|
KC_LSFT,KC_Z, KC_X, KC_C, KC_V, KC_B, KC_FN1, |
||||||
|
KC_LGUI,KC_GRV, KC_BSLS,KC_LEFT,KC_RGHT, |
||||||
|
KC_LCTL,KC_LALT, |
||||||
|
KC_HOME, |
||||||
|
KC_BSPC,KC_DEL, KC_END, |
||||||
|
// right hand
|
||||||
|
KC_FN3, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, |
||||||
|
KC_LBRC,KC_Y, KC_U, KC_I, KC_O, KC_P, KC_RBRC, |
||||||
|
KC_H, KC_J, KC_K, KC_L, KC_SCLN,KC_QUOT, |
||||||
|
KC_FN1, KC_N, KC_M, KC_COMM,KC_DOT, KC_SLSH,KC_RSFT, |
||||||
|
KC_LEFT,KC_DOWN,KC_UP, KC_RGHT,KC_RGUI, |
||||||
|
KC_RALT,KC_RCTL, |
||||||
|
KC_PGUP, |
||||||
|
KC_PGDN,KC_ENT, KC_SPC |
||||||
|
), |
||||||
|
[LOWER_LAYER] = KEYMAP( // layer 0 : default
|
||||||
|
// left hand
|
||||||
|
KC_EQL, KC_1, KC_2, KC_3, LALT(KC_TAB), KC_5, KC_ESC, |
||||||
|
KC_BSLS,KC_Q, S(KC_W), KC_E, KC_R, KC_T, KC_FN2, |
||||||
|
KC_TAB, KC_A, KC_S, KC_D, KC_F, KC_G, |
||||||
|
KC_LSFT,KC_Z, KC_X, KC_C, KC_V, KC_B, KC_FN1, |
||||||
|
KC_LGUI,KC_GRV, KC_BSLS,KC_LEFT,KC_RGHT, |
||||||
|
KC_LCTL,KC_LALT, |
||||||
|
KC_HOME, |
||||||
|
KC_BSPC,KC_DEL, KC_END, |
||||||
|
// right hand
|
||||||
|
KC_FN3, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, |
||||||
|
KC_LBRC,KC_Y, KC_U, KC_I, KC_O, KC_P, KC_RBRC, |
||||||
|
KC_H, KC_J, KC_K, KC_L, KC_SCLN,KC_QUOT, |
||||||
|
KC_FN1, KC_N, KC_M, KC_COMM,KC_DOT, KC_SLSH,KC_RSFT, |
||||||
|
KC_LEFT,KC_DOWN,KC_UP, KC_RGHT,KC_RGUI, |
||||||
|
KC_RALT,KC_RCTL, |
||||||
|
KC_PGUP, |
||||||
|
KC_PGDN,KC_ENT, KC_SPC |
||||||
|
) |
||||||
|
}; |
||||||
|
|
||||||
|
const uint16_t PROGMEM fn_actions[] = { |
||||||
|
|
||||||
|
[1] = ACTION_LAYER_MOMENTARY(LOWER_LAYER), // to RAISE
|
||||||
|
[2] = ACTION_LAYER_MOMENTARY(LOWER_LAYER), // to LOWER
|
||||||
|
|
||||||
|
[3] = ACTION_DEFAULT_LAYER_SET(DEFAULT_LAYER), |
||||||
|
[4] = ACTION_DEFAULT_LAYER_SET(COLEMAK_LAYER), |
||||||
|
[5] = ACTION_DEFAULT_LAYER_SET(DVORAK_LAYER), |
||||||
|
}; |
||||||
|
|
||||||
|
const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) |
||||||
|
{ |
||||||
|
// MACRODOWN only works in this function
|
||||||
|
switch(id) { |
||||||
|
case 0: |
||||||
|
if (record->event.pressed) { |
||||||
|
register_code(KC_RSFT); |
||||||
|
} else { |
||||||
|
unregister_code(KC_RSFT); |
||||||
|
} |
||||||
|
break; |
||||||
|
} |
||||||
|
return MACRO_NONE; |
||||||
|
}; |
@ -0,0 +1,405 @@ |
|||||||
|
/*
|
||||||
|
Copyright 2013 Oleg Kostyuk <cub.uanic@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 <util/delay.h> |
||||||
|
#include "action_layer.h" |
||||||
|
#include "print.h" |
||||||
|
#include "debug.h" |
||||||
|
#include "util.h" |
||||||
|
#include "matrix.h" |
||||||
|
#include "ergodox.h" |
||||||
|
#include "i2cmaster.h" |
||||||
|
#ifdef DEBUG_MATRIX_SCAN_RATE |
||||||
|
#include "timer.h" |
||||||
|
#endif |
||||||
|
|
||||||
|
#ifndef DEBOUNCE |
||||||
|
# define DEBOUNCE 5 |
||||||
|
#endif |
||||||
|
static uint8_t debouncing = DEBOUNCE; |
||||||
|
|
||||||
|
/* matrix state(1:on, 0:off) */ |
||||||
|
static matrix_row_t matrix[MATRIX_ROWS]; |
||||||
|
static matrix_row_t matrix_debouncing[MATRIX_ROWS]; |
||||||
|
|
||||||
|
static matrix_row_t read_cols(uint8_t row); |
||||||
|
static void init_cols(void); |
||||||
|
static void unselect_rows(); |
||||||
|
static void select_row(uint8_t row); |
||||||
|
|
||||||
|
static uint8_t mcp23018_reset_loop; |
||||||
|
|
||||||
|
#ifdef DEBUG_MATRIX_SCAN_RATE |
||||||
|
uint32_t matrix_timer; |
||||||
|
uint32_t matrix_scan_count; |
||||||
|
#endif |
||||||
|
|
||||||
|
|
||||||
|
__attribute__ ((weak)) |
||||||
|
void * matrix_init_kb(void) { |
||||||
|
}; |
||||||
|
|
||||||
|
__attribute__ ((weak)) |
||||||
|
void * matrix_scan_kb(void) { |
||||||
|
}; |
||||||
|
|
||||||
|
inline |
||||||
|
uint8_t matrix_rows(void) |
||||||
|
{ |
||||||
|
return MATRIX_ROWS; |
||||||
|
} |
||||||
|
|
||||||
|
inline |
||||||
|
uint8_t matrix_cols(void) |
||||||
|
{ |
||||||
|
return MATRIX_COLS; |
||||||
|
} |
||||||
|
|
||||||
|
void matrix_init(void) |
||||||
|
{ |
||||||
|
// initialize row and col
|
||||||
|
|
||||||
|
mcp23018_status = init_mcp23018(); |
||||||
|
|
||||||
|
|
||||||
|
unselect_rows(); |
||||||
|
init_cols(); |
||||||
|
|
||||||
|
// initialize matrix state: all keys off
|
||||||
|
for (uint8_t i=0; i < MATRIX_ROWS; i++) { |
||||||
|
matrix[i] = 0; |
||||||
|
matrix_debouncing[i] = 0; |
||||||
|
} |
||||||
|
|
||||||
|
#ifdef DEBUG_MATRIX_SCAN_RATE |
||||||
|
matrix_timer = timer_read32(); |
||||||
|
matrix_scan_count = 0; |
||||||
|
#endif |
||||||
|
|
||||||
|
if (matrix_init_kb) { |
||||||
|
(*matrix_init_kb)(); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
uint8_t matrix_scan(void) |
||||||
|
{ |
||||||
|
if (mcp23018_status) { // if there was an error
|
||||||
|
if (++mcp23018_reset_loop == 0) { |
||||||
|
// since mcp23018_reset_loop is 8 bit - we'll try to reset once in 255 matrix scans
|
||||||
|
// this will be approx bit more frequent than once per second
|
||||||
|
print("trying to reset mcp23018\n"); |
||||||
|
mcp23018_status = init_mcp23018(); |
||||||
|
if (mcp23018_status) { |
||||||
|
print("left side not responding\n"); |
||||||
|
} else { |
||||||
|
print("left side attached\n"); |
||||||
|
ergodox_blink_all_leds(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#ifdef DEBUG_MATRIX_SCAN_RATE |
||||||
|
matrix_scan_count++; |
||||||
|
|
||||||
|
uint32_t timer_now = timer_read32(); |
||||||
|
if (TIMER_DIFF_32(timer_now, matrix_timer)>1000) { |
||||||
|
print("matrix scan frequency: "); |
||||||
|
pdec(matrix_scan_count); |
||||||
|
print("\n"); |
||||||
|
|
||||||
|
matrix_timer = timer_now; |
||||||
|
matrix_scan_count = 0; |
||||||
|
} |
||||||
|
#endif |
||||||
|
|
||||||
|
#ifdef KEYMAP_CUB |
||||||
|
uint8_t layer = biton32(layer_state); |
||||||
|
|
||||||
|
ergodox_board_led_off(); |
||||||
|
ergodox_left_led_1_off(); |
||||||
|
ergodox_left_led_2_off(); |
||||||
|
ergodox_left_led_3_off(); |
||||||
|
switch (layer) { |
||||||
|
case 1: |
||||||
|
// all
|
||||||
|
ergodox_left_led_1_on(); |
||||||
|
ergodox_left_led_2_on(); |
||||||
|
ergodox_left_led_3_on(); |
||||||
|
break; |
||||||
|
case 2: |
||||||
|
// blue
|
||||||
|
ergodox_left_led_2_on(); |
||||||
|
break; |
||||||
|
case 8: |
||||||
|
// blue and green
|
||||||
|
ergodox_left_led_2_on(); |
||||||
|
// break missed intentionally
|
||||||
|
case 3: |
||||||
|
// green
|
||||||
|
ergodox_left_led_3_on(); |
||||||
|
break; |
||||||
|
case 6: |
||||||
|
ergodox_board_led_on(); |
||||||
|
// break missed intentionally
|
||||||
|
case 4: |
||||||
|
case 5: |
||||||
|
case 7: |
||||||
|
// white
|
||||||
|
ergodox_left_led_1_on(); |
||||||
|
break; |
||||||
|
case 9: |
||||||
|
// white+green
|
||||||
|
ergodox_left_led_1_on(); |
||||||
|
ergodox_left_led_3_on(); |
||||||
|
break; |
||||||
|
default: |
||||||
|
// none
|
||||||
|
break; |
||||||
|
} |
||||||
|
|
||||||
|
mcp23018_status = ergodox_left_leds_update(); |
||||||
|
#endif |
||||||
|
|
||||||
|
#ifdef KEYMAP_SIMON |
||||||
|
uint8_t layer = biton32(layer_state); |
||||||
|
|
||||||
|
ergodox_board_led_off(); |
||||||
|
switch (layer) { |
||||||
|
case 0: |
||||||
|
// none
|
||||||
|
|
||||||
|
break; |
||||||
|
default: |
||||||
|
ergodox_board_led_on(); |
||||||
|
break; |
||||||
|
} |
||||||
|
#endif |
||||||
|
|
||||||
|
for (uint8_t i = 0; i < MATRIX_ROWS; i++) { |
||||||
|
select_row(i); |
||||||
|
matrix_row_t cols = read_cols(i); |
||||||
|
if (matrix_debouncing[i] != cols) { |
||||||
|
matrix_debouncing[i] = cols; |
||||||
|
if (debouncing) { |
||||||
|
debug("bounce!: "); debug_hex(debouncing); debug("\n"); |
||||||
|
} |
||||||
|
debouncing = DEBOUNCE; |
||||||
|
} |
||||||
|
unselect_rows(); |
||||||
|
} |
||||||
|
|
||||||
|
if (debouncing) { |
||||||
|
if (--debouncing) { |
||||||
|
_delay_ms(1); |
||||||
|
} else { |
||||||
|
for (uint8_t i = 0; i < MATRIX_ROWS; i++) { |
||||||
|
matrix[i] = matrix_debouncing[i]; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
if (matrix_scan_kb) { |
||||||
|
(*matrix_scan_kb)(); |
||||||
|
} |
||||||
|
|
||||||
|
return 1; |
||||||
|
} |
||||||
|
|
||||||
|
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; |
||||||
|
} |
||||||
|
|
||||||
|
/* Column pin configuration
|
||||||
|
* |
||||||
|
* Teensy |
||||||
|
* col: 0 1 2 3 4 5 |
||||||
|
* pin: F0 F1 F4 F5 F6 F7
|
||||||
|
* |
||||||
|
* MCP23018 |
||||||
|
* col: 0 1 2 3 4 5 |
||||||
|
* pin: B5 B4 B3 B2 B1 B0
|
||||||
|
*/ |
||||||
|
static void init_cols(void) |
||||||
|
{ |
||||||
|
// init on mcp23018
|
||||||
|
// not needed, already done as part of init_mcp23018()
|
||||||
|
|
||||||
|
// init on teensy
|
||||||
|
// Input with pull-up(DDR:0, PORT:1)
|
||||||
|
DDRF &= ~(1<<7 | 1<<6 | 1<<5 | 1<<4 | 1<<1 | 1<<0); |
||||||
|
PORTF |= (1<<7 | 1<<6 | 1<<5 | 1<<4 | 1<<1 | 1<<0); |
||||||
|
} |
||||||
|
|
||||||
|
static matrix_row_t read_cols(uint8_t row) |
||||||
|
{ |
||||||
|
if (row < 7) { |
||||||
|
if (mcp23018_status) { // if there was an error
|
||||||
|
return 0; |
||||||
|
} else { |
||||||
|
uint8_t data = 0; |
||||||
|
mcp23018_status = i2c_start(I2C_ADDR_WRITE); if (mcp23018_status) goto out; |
||||||
|
mcp23018_status = i2c_write(GPIOB); if (mcp23018_status) goto out; |
||||||
|
mcp23018_status = i2c_start(I2C_ADDR_READ); if (mcp23018_status) goto out; |
||||||
|
data = i2c_readNak(); |
||||||
|
data = ~data; |
||||||
|
out: |
||||||
|
i2c_stop(); |
||||||
|
return data; |
||||||
|
} |
||||||
|
} else { |
||||||
|
_delay_us(30); // without this wait read unstable value.
|
||||||
|
// read from teensy
|
||||||
|
return |
||||||
|
(PINF&(1<<0) ? 0 : (1<<0)) | |
||||||
|
(PINF&(1<<1) ? 0 : (1<<1)) | |
||||||
|
(PINF&(1<<4) ? 0 : (1<<2)) | |
||||||
|
(PINF&(1<<5) ? 0 : (1<<3)) | |
||||||
|
(PINF&(1<<6) ? 0 : (1<<4)) | |
||||||
|
(PINF&(1<<7) ? 0 : (1<<5)) ; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/* Row pin configuration
|
||||||
|
* |
||||||
|
* Teensy |
||||||
|
* row: 7 8 9 10 11 12 13 |
||||||
|
* pin: B0 B1 B2 B3 D2 D3 C6 |
||||||
|
* |
||||||
|
* MCP23018 |
||||||
|
* row: 0 1 2 3 4 5 6 |
||||||
|
* pin: A0 A1 A2 A3 A4 A5 A6 |
||||||
|
*/ |
||||||
|
static void unselect_rows(void) |
||||||
|
{ |
||||||
|
// unselect on mcp23018
|
||||||
|
if (mcp23018_status) { // if there was an error
|
||||||
|
// do nothing
|
||||||
|
} else { |
||||||
|
// set all rows hi-Z : 1
|
||||||
|
mcp23018_status = i2c_start(I2C_ADDR_WRITE); if (mcp23018_status) goto out; |
||||||
|
mcp23018_status = i2c_write(GPIOA); if (mcp23018_status) goto out; |
||||||
|
mcp23018_status = i2c_write( 0xFF |
||||||
|
& ~(ergodox_left_led_3<<LEFT_LED_3_SHIFT) |
||||||
|
); if (mcp23018_status) goto out; |
||||||
|
out: |
||||||
|
i2c_stop(); |
||||||
|
} |
||||||
|
|
||||||
|
// unselect on teensy
|
||||||
|
// Hi-Z(DDR:0, PORT:0) to unselect
|
||||||
|
DDRB &= ~(1<<0 | 1<<1 | 1<<2 | 1<<3); |
||||||
|
PORTB &= ~(1<<0 | 1<<1 | 1<<2 | 1<<3); |
||||||
|
DDRD &= ~(1<<2 | 1<<3); |
||||||
|
PORTD &= ~(1<<2 | 1<<3); |
||||||
|
DDRC &= ~(1<<6); |
||||||
|
PORTC &= ~(1<<6); |
||||||
|
} |
||||||
|
|
||||||
|
static void select_row(uint8_t row) |
||||||
|
{ |
||||||
|
if (row < 7) { |
||||||
|
// select on mcp23018
|
||||||
|
if (mcp23018_status) { // if there was an error
|
||||||
|
// do nothing
|
||||||
|
} else { |
||||||
|
// set active row low : 0
|
||||||
|
// set other rows hi-Z : 1
|
||||||
|
mcp23018_status = i2c_start(I2C_ADDR_WRITE); if (mcp23018_status) goto out; |
||||||
|
mcp23018_status = i2c_write(GPIOA); if (mcp23018_status) goto out; |
||||||
|
mcp23018_status = i2c_write( 0xFF & ~(1<<row)
|
||||||
|
& ~(ergodox_left_led_3<<LEFT_LED_3_SHIFT) |
||||||
|
); if (mcp23018_status) goto out; |
||||||
|
out: |
||||||
|
i2c_stop(); |
||||||
|
} |
||||||
|
} else { |
||||||
|
// select on teensy
|
||||||
|
// Output low(DDR:1, PORT:0) to select
|
||||||
|
switch (row) { |
||||||
|
case 7: |
||||||
|
DDRB |= (1<<0); |
||||||
|
PORTB &= ~(1<<0); |
||||||
|
break; |
||||||
|
case 8: |
||||||
|
DDRB |= (1<<1); |
||||||
|
PORTB &= ~(1<<1); |
||||||
|
break; |
||||||
|
case 9: |
||||||
|
DDRB |= (1<<2); |
||||||
|
PORTB &= ~(1<<2); |
||||||
|
break; |
||||||
|
case 10: |
||||||
|
DDRB |= (1<<3); |
||||||
|
PORTB &= ~(1<<3); |
||||||
|
break; |
||||||
|
case 11: |
||||||
|
DDRD |= (1<<2); |
||||||
|
PORTD &= ~(1<<3); |
||||||
|
break; |
||||||
|
case 12: |
||||||
|
DDRD |= (1<<3); |
||||||
|
PORTD &= ~(1<<3); |
||||||
|
break; |
||||||
|
case 13: |
||||||
|
DDRC |= (1<<6); |
||||||
|
PORTC &= ~(1<<6); |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
@ -0,0 +1,208 @@ |
|||||||
|
/*************************************************************************
|
||||||
|
* Title: I2C master library using hardware TWI interface |
||||||
|
* Author: Peter Fleury <pfleury@gmx.ch> http://jump.to/fleury
|
||||||
|
* File: $Id: twimaster.c,v 1.3 2005/07/02 11:14:21 Peter Exp $ |
||||||
|
* Software: AVR-GCC 3.4.3 / avr-libc 1.2.3 |
||||||
|
* Target: any AVR device with hardware TWI
|
||||||
|
* Usage: API compatible with I2C Software Library i2cmaster.h |
||||||
|
**************************************************************************/ |
||||||
|
#include <inttypes.h> |
||||||
|
#include <compat/twi.h> |
||||||
|
|
||||||
|
#include <i2cmaster.h> |
||||||
|
|
||||||
|
|
||||||
|
/* define CPU frequency in Mhz here if not defined in Makefile */ |
||||||
|
#ifndef F_CPU |
||||||
|
#define F_CPU 16000000UL |
||||||
|
#endif |
||||||
|
|
||||||
|
/* I2C clock in Hz */ |
||||||
|
#define SCL_CLOCK 400000L |
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
Initialization of the I2C bus interface. Need to be called only once |
||||||
|
*************************************************************************/ |
||||||
|
void i2c_init(void) |
||||||
|
{ |
||||||
|
/* initialize TWI clock
|
||||||
|
* minimal values in Bit Rate Register (TWBR) and minimal Prescaler |
||||||
|
* bits in the TWI Status Register should give us maximal possible |
||||||
|
* I2C bus speed - about 444 kHz |
||||||
|
* |
||||||
|
* for more details, see 20.5.2 in ATmega16/32 secification |
||||||
|
*/ |
||||||
|
|
||||||
|
TWSR = 0; /* no prescaler */ |
||||||
|
TWBR = 10; /* must be >= 10 for stable operation */ |
||||||
|
|
||||||
|
}/* i2c_init */ |
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
Issues a start condition and sends address and transfer direction. |
||||||
|
return 0 = device accessible, 1= failed to access device |
||||||
|
*************************************************************************/ |
||||||
|
unsigned char i2c_start(unsigned char address) |
||||||
|
{ |
||||||
|
uint8_t twst; |
||||||
|
|
||||||
|
// send START condition
|
||||||
|
TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); |
||||||
|
|
||||||
|
// wait until transmission completed
|
||||||
|
while(!(TWCR & (1<<TWINT))); |
||||||
|
|
||||||
|
// check value of TWI Status Register. Mask prescaler bits.
|
||||||
|
twst = TW_STATUS & 0xF8; |
||||||
|
if ( (twst != TW_START) && (twst != TW_REP_START)) return 1; |
||||||
|
|
||||||
|
// send device address
|
||||||
|
TWDR = address; |
||||||
|
TWCR = (1<<TWINT) | (1<<TWEN); |
||||||
|
|
||||||
|
// wail until transmission completed and ACK/NACK has been received
|
||||||
|
while(!(TWCR & (1<<TWINT))); |
||||||
|
|
||||||
|
// check value of TWI Status Register. Mask prescaler bits.
|
||||||
|
twst = TW_STATUS & 0xF8; |
||||||
|
if ( (twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK) ) return 1; |
||||||
|
|
||||||
|
return 0; |
||||||
|
|
||||||
|
}/* i2c_start */ |
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
Issues a start condition and sends address and transfer direction. |
||||||
|
If device is busy, use ack polling to wait until device is ready |
||||||
|
|
||||||
|
Input: address and transfer direction of I2C device |
||||||
|
*************************************************************************/ |
||||||
|
void i2c_start_wait(unsigned char address) |
||||||
|
{ |
||||||
|
uint8_t twst; |
||||||
|
|
||||||
|
|
||||||
|
while ( 1 ) |
||||||
|
{ |
||||||
|
// send START condition
|
||||||
|
TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); |
||||||
|
|
||||||
|
// wait until transmission completed
|
||||||
|
while(!(TWCR & (1<<TWINT))); |
||||||
|
|
||||||
|
// check value of TWI Status Register. Mask prescaler bits.
|
||||||
|
twst = TW_STATUS & 0xF8; |
||||||
|
if ( (twst != TW_START) && (twst != TW_REP_START)) continue; |
||||||
|
|
||||||
|
// send device address
|
||||||
|
TWDR = address; |
||||||
|
TWCR = (1<<TWINT) | (1<<TWEN); |
||||||
|
|
||||||
|
// wail until transmission completed
|
||||||
|
while(!(TWCR & (1<<TWINT))); |
||||||
|
|
||||||
|
// check value of TWI Status Register. Mask prescaler bits.
|
||||||
|
twst = TW_STATUS & 0xF8; |
||||||
|
if ( (twst == TW_MT_SLA_NACK )||(twst ==TW_MR_DATA_NACK) )
|
||||||
|
{
|
||||||
|
/* device busy, send stop condition to terminate write operation */ |
||||||
|
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO); |
||||||
|
|
||||||
|
// wait until stop condition is executed and bus released
|
||||||
|
while(TWCR & (1<<TWSTO)); |
||||||
|
|
||||||
|
continue; |
||||||
|
} |
||||||
|
//if( twst != TW_MT_SLA_ACK) return 1;
|
||||||
|
break; |
||||||
|
} |
||||||
|
|
||||||
|
}/* i2c_start_wait */ |
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
Issues a repeated start condition and sends address and transfer direction
|
||||||
|
|
||||||
|
Input: address and transfer direction of I2C device |
||||||
|
|
||||||
|
Return: 0 device accessible |
||||||
|
1 failed to access device |
||||||
|
*************************************************************************/ |
||||||
|
unsigned char i2c_rep_start(unsigned char address) |
||||||
|
{ |
||||||
|
return i2c_start( address ); |
||||||
|
|
||||||
|
}/* i2c_rep_start */ |
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
Terminates the data transfer and releases the I2C bus |
||||||
|
*************************************************************************/ |
||||||
|
void i2c_stop(void) |
||||||
|
{ |
||||||
|
/* send stop condition */ |
||||||
|
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO); |
||||||
|
|
||||||
|
// wait until stop condition is executed and bus released
|
||||||
|
while(TWCR & (1<<TWSTO)); |
||||||
|
|
||||||
|
}/* i2c_stop */ |
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
Send one byte to I2C device |
||||||
|
|
||||||
|
Input: byte to be transfered |
||||||
|
Return: 0 write successful
|
||||||
|
1 write failed |
||||||
|
*************************************************************************/ |
||||||
|
unsigned char i2c_write( unsigned char data ) |
||||||
|
{
|
||||||
|
uint8_t twst; |
||||||
|
|
||||||
|
// send data to the previously addressed device
|
||||||
|
TWDR = data; |
||||||
|
TWCR = (1<<TWINT) | (1<<TWEN); |
||||||
|
|
||||||
|
// wait until transmission completed
|
||||||
|
while(!(TWCR & (1<<TWINT))); |
||||||
|
|
||||||
|
// check value of TWI Status Register. Mask prescaler bits
|
||||||
|
twst = TW_STATUS & 0xF8; |
||||||
|
if( twst != TW_MT_DATA_ACK) return 1; |
||||||
|
return 0; |
||||||
|
|
||||||
|
}/* i2c_write */ |
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
Read one byte from the I2C device, request more data from device
|
||||||
|
|
||||||
|
Return: byte read from I2C device |
||||||
|
*************************************************************************/ |
||||||
|
unsigned char i2c_readAck(void) |
||||||
|
{ |
||||||
|
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA); |
||||||
|
while(!(TWCR & (1<<TWINT)));
|
||||||
|
|
||||||
|
return TWDR; |
||||||
|
|
||||||
|
}/* i2c_readAck */ |
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
Read one byte from the I2C device, read is followed by a stop condition
|
||||||
|
|
||||||
|
Return: byte read from I2C device |
||||||
|
*************************************************************************/ |
||||||
|
unsigned char i2c_readNak(void) |
||||||
|
{ |
||||||
|
TWCR = (1<<TWINT) | (1<<TWEN); |
||||||
|
while(!(TWCR & (1<<TWINT))); |
||||||
|
|
||||||
|
return TWDR; |
||||||
|
|
||||||
|
}/* i2c_readNak */ |
@ -1,51 +0,0 @@ |
|||||||
#ifndef CONFIG_DEFINITIONS_H |
|
||||||
#define CONFIG_DEFINITIONS_H |
|
||||||
|
|
||||||
#define B0 0x20 |
|
||||||
#define B1 0x21 |
|
||||||
#define B2 0x22 |
|
||||||
#define B3 0x23 |
|
||||||
#define B4 0x24 |
|
||||||
#define B5 0x25 |
|
||||||
#define B6 0x26 |
|
||||||
#define B7 0x27 |
|
||||||
#define C0 0x30 |
|
||||||
#define C1 0x31 |
|
||||||
#define C2 0x32 |
|
||||||
#define C3 0x33 |
|
||||||
#define C4 0x34 |
|
||||||
#define C5 0x35 |
|
||||||
#define C6 0x36 |
|
||||||
#define C7 0x37 |
|
||||||
#define D0 0x40 |
|
||||||
#define D1 0x41 |
|
||||||
#define D2 0x42 |
|
||||||
#define D3 0x43 |
|
||||||
#define D4 0x44 |
|
||||||
#define D5 0x45 |
|
||||||
#define D6 0x46 |
|
||||||
#define D7 0x47 |
|
||||||
#define E0 0x50 |
|
||||||
#define E1 0x51 |
|
||||||
#define E2 0x52 |
|
||||||
#define E3 0x53 |
|
||||||
#define E4 0x54 |
|
||||||
#define E5 0x55 |
|
||||||
#define E6 0x56 |
|
||||||
#define E7 0x57 |
|
||||||
#define F0 0x60 |
|
||||||
#define F1 0x61 |
|
||||||
#define F2 0x62 |
|
||||||
#define F3 0x63 |
|
||||||
#define F4 0x64 |
|
||||||
#define F5 0x65 |
|
||||||
#define F6 0x66 |
|
||||||
#define F7 0x67 |
|
||||||
|
|
||||||
#define COL2ROW 0x0 |
|
||||||
#define ROW2COL 0x1 |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif |
|
||||||
|
|
@ -0,0 +1,116 @@ |
|||||||
|
#ifndef CONFIG_DEFINITIONS_H |
||||||
|
#define CONFIG_DEFINITIONS_H |
||||||
|
|
||||||
|
#define B0 0x20 |
||||||
|
#define B1 0x21 |
||||||
|
#define B2 0x22 |
||||||
|
#define B3 0x23 |
||||||
|
#define B4 0x24 |
||||||
|
#define B5 0x25 |
||||||
|
#define B6 0x26 |
||||||
|
#define B7 0x27 |
||||||
|
#define C0 0x30 |
||||||
|
#define C1 0x31 |
||||||
|
#define C2 0x32 |
||||||
|
#define C3 0x33 |
||||||
|
#define C4 0x34 |
||||||
|
#define C5 0x35 |
||||||
|
#define C6 0x36 |
||||||
|
#define C7 0x37 |
||||||
|
#define D0 0x40 |
||||||
|
#define D1 0x41 |
||||||
|
#define D2 0x42 |
||||||
|
#define D3 0x43 |
||||||
|
#define D4 0x44 |
||||||
|
#define D5 0x45 |
||||||
|
#define D6 0x46 |
||||||
|
#define D7 0x47 |
||||||
|
#define E0 0x50 |
||||||
|
#define E1 0x51 |
||||||
|
#define E2 0x52 |
||||||
|
#define E3 0x53 |
||||||
|
#define E4 0x54 |
||||||
|
#define E5 0x55 |
||||||
|
#define E6 0x56 |
||||||
|
#define E7 0x57 |
||||||
|
#define F0 0x60 |
||||||
|
#define F1 0x61 |
||||||
|
#define F2 0x62 |
||||||
|
#define F3 0x63 |
||||||
|
#define F4 0x64 |
||||||
|
#define F5 0x65 |
||||||
|
#define F6 0x66 |
||||||
|
#define F7 0x67 |
||||||
|
|
||||||
|
#define COL2ROW 0x0 |
||||||
|
#define ROW2COL 0x1 |
||||||
|
|
||||||
|
#ifdef BLUETOOTH_ENABLE |
||||||
|
#ifdef __AVR_ATmega32U4__ |
||||||
|
#define SERIAL_UART_BAUD 9600 |
||||||
|
#define SERIAL_UART_DATA UDR1 |
||||||
|
#define SERIAL_UART_UBRR ((F_CPU/(16UL*SERIAL_UART_BAUD))-1) |
||||||
|
#define SERIAL_UART_RXD_VECT USART1_RX_vect |
||||||
|
#define SERIAL_UART_TXD_READY (UCSR1A&(1<<UDRE1)) |
||||||
|
#define SERIAL_UART_INIT() do { \ |
||||||
|
UBRR1L = (uint8_t) SERIAL_UART_UBRR; /* baud rate */ \
|
||||||
|
UBRR1H = (uint8_t) (SERIAL_UART_UBRR>>8); /* baud rate */ \
|
||||||
|
UCSR1B = (1<<TXEN1); /* TX: enable */ \
|
||||||
|
UCSR1C = (0<<UPM11) | (0<<UPM10) | /* parity: none(00), even(01), odd(11) */ \
|
||||||
|
(0<<UCSZ12) | (1<<UCSZ11) | (1<<UCSZ10); /* data-8bit(011) */ \
|
||||||
|
sei(); \
|
||||||
|
} while(0) |
||||||
|
#else |
||||||
|
# error "USART configuration is needed." |
||||||
|
#endif |
||||||
|
|
||||||
|
|
||||||
|
// I'm fairly sure these aren't needed, but oh well - Jack
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PS/2 Interrupt configuration |
||||||
|
*/ |
||||||
|
#ifdef PS2_USE_INT |
||||||
|
/* uses INT1 for clock line(ATMega32U4) */ |
||||||
|
#define PS2_CLOCK_PORT PORTD |
||||||
|
#define PS2_CLOCK_PIN PIND |
||||||
|
#define PS2_CLOCK_DDR DDRD |
||||||
|
#define PS2_CLOCK_BIT 1 |
||||||
|
|
||||||
|
#define PS2_DATA_PORT PORTD |
||||||
|
#define PS2_DATA_PIN PIND |
||||||
|
#define PS2_DATA_DDR DDRD |
||||||
|
#define PS2_DATA_BIT 0 |
||||||
|
|
||||||
|
#define PS2_INT_INIT() do { \ |
||||||
|
EICRA |= ((1<<ISC11) | \
|
||||||
|
(0<<ISC10)); \
|
||||||
|
} while (0) |
||||||
|
#define PS2_INT_ON() do { \ |
||||||
|
EIMSK |= (1<<INT1); \
|
||||||
|
} while (0) |
||||||
|
#define PS2_INT_OFF() do { \ |
||||||
|
EIMSK &= ~(1<<INT1); \
|
||||||
|
} while (0) |
||||||
|
#define PS2_INT_VECT INT1_vect |
||||||
|
#endif |
||||||
|
|
||||||
|
/*
|
||||||
|
* PS/2 Busywait configuration |
||||||
|
*/ |
||||||
|
#ifdef PS2_USE_BUSYWAIT |
||||||
|
#define PS2_CLOCK_PORT PORTD |
||||||
|
#define PS2_CLOCK_PIN PIND |
||||||
|
#define PS2_CLOCK_DDR DDRD |
||||||
|
#define PS2_CLOCK_BIT 1 |
||||||
|
|
||||||
|
#define PS2_DATA_PORT PORTD |
||||||
|
#define PS2_DATA_PIN PIND |
||||||
|
#define PS2_DATA_DDR DDRD |
||||||
|
#define PS2_DATA_BIT 0 |
||||||
|
#endif |
||||||
|
|
||||||
|
#endif |
||||||
|
|
||||||
|
#endif |
||||||
|
|
Loading…
Reference in new issue