[Jack & Erez] Comments + tiny updates and cleanup
This commit is contained in:
parent
cc1c32671e
commit
0c47e8b008
19 changed files with 65 additions and 1512 deletions
114
keyboard/ergodox_ez/Makefile
Normal file
114
keyboard/ergodox_ez/Makefile
Normal file
|
@ -0,0 +1,114 @@
|
|||
#----------------------------------------------------------------------------
|
||||
# On command line:
|
||||
#
|
||||
# make = Make software.
|
||||
#
|
||||
# make clean = Clean out built project files.
|
||||
#
|
||||
# That's pretty much all you need. To compile, always go make clean,
|
||||
# followed by make.
|
||||
#
|
||||
# For advanced users only:
|
||||
# make teensy = Download the hex file to the device, using teensy_loader_cli.
|
||||
# (must have teensy_loader_cli installed).
|
||||
#
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
# Target file name (without extension).
|
||||
TARGET = ergodox_ez
|
||||
|
||||
|
||||
# Directory common source filess exist
|
||||
TOP_DIR = ../..
|
||||
|
||||
# Directory keyboard dependent files exist
|
||||
TARGET_DIR = .
|
||||
|
||||
# # project specific files
|
||||
SRC = ergodox_ez.c \
|
||||
twimaster.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
|
||||
|
1
keyboard/ergodox_ez/README.md
Normal file
1
keyboard/ergodox_ez/README.md
Normal file
|
@ -0,0 +1 @@
|
|||
// TODO: Make up a proper readme for the ErgoDox EZ.
|
87
keyboard/ergodox_ez/config.h
Normal file
87
keyboard/ergodox_ez/config.h
Normal file
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
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 100
|
||||
|
||||
/* 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
|
123
keyboard/ergodox_ez/ergodox_ez.c
Normal file
123
keyboard/ergodox_ez/ergodox_ez.c
Normal file
|
@ -0,0 +1,123 @@
|
|||
#include "ergodox_ez.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
|
||||
|
||||
__attribute__ ((weak))
|
||||
void * matrix_init_user(void) {
|
||||
|
||||
};
|
||||
|
||||
__attribute__ ((weak))
|
||||
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;
|
||||
}
|
||||
|
145
keyboard/ergodox_ez/ergodox_ez.h
Normal file
145
keyboard/ergodox_ez/ergodox_ez.h
Normal file
|
@ -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
|
178
keyboard/ergodox_ez/i2cmaster.h
Normal file
178
keyboard/ergodox_ez/i2cmaster.h
Normal file
|
@ -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
|
133
keyboard/ergodox_ez/keymaps/keymap_default.c
Normal file
133
keyboard/ergodox_ez/keymaps/keymap_default.c
Normal file
|
@ -0,0 +1,133 @@
|
|||
#include "ergodox_ez.h"
|
||||
#include "debug.h"
|
||||
#include "action_layer.h"
|
||||
|
||||
// TODO: Define layer names that make sense for the ErgoDox EZ.
|
||||
#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;
|
||||
};
|
||||
|
||||
// Runs just one time when the keyboard initializes.
|
||||
void * matrix_init_user(void) {
|
||||
|
||||
};
|
||||
|
||||
// Runs constantly in the background, in a loop.
|
||||
void * matrix_scan_user(void) {
|
||||
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) {
|
||||
// TODO: Make this relevant to the ErgoDox EZ.
|
||||
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();
|
||||
};
|
211
keyboard/ergodox_ez/keymaps/keymap_ergodox_ez.c
Normal file
211
keyboard/ergodox_ez/keymaps/keymap_ergodox_ez.c
Normal file
|
@ -0,0 +1,211 @@
|
|||
// TODO: Move all of this stuff into the default keymap, and then get rid of this file.
|
||||
#include "action_util.h"
|
||||
#include "action_layer.h"
|
||||
#define KC_SW0 KC_FN0
|
||||
#define DEBUG_ACTION
|
||||
|
||||
static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||
|
||||
/* Keymap 0: Basic layer
|
||||
*
|
||||
* ,--------------------------------------------------. ,--------------------------------------------------.
|
||||
* | = | 1 | 2 | 3 | 4 | 5 | LEFT | | RIGHT| 6 | 7 | 8 | 9 | 0 | - |
|
||||
* |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
|
||||
* | Del | Q | W | E | R | T | Up | | Up | Y | U | I | O | P | \ |
|
||||
* |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
|
||||
* | BkSp | A | S | D | F | G |------| |------| H | J | K | L |; / L2| ' |
|
||||
* |--------+------+------+------+------+------| L1 | | L1 |------+------+------+------+------+--------|
|
||||
* | LShift |Z/Ctrl| X | C | V | B | | | | N | M | , | . |//Ctrl| RShift |
|
||||
* `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
|
||||
* |Grv/L1| ~L1 | TAB | Left | Right| | Up | Down | [ | ] | ~L1 |
|
||||
* `----------------------------------' `----------------------------------'
|
||||
* ,-------------. ,-------------.
|
||||
* | Rclk | LGui | | Alt |Ctrl/Esc|
|
||||
* ,------|------|------| |------+--------+------.
|
||||
* | | | Home | | PgUp | | |
|
||||
* | Space| Enter|------| |------| Tab |Enter |
|
||||
* | | | End | | PgDn | | |
|
||||
* `--------------------' `----------------------'
|
||||
*/
|
||||
|
||||
|
||||
// Basic layer
|
||||
|
||||
KEYMAP(
|
||||
EQL, 1, 2, 3, 4, 5, LEFT,
|
||||
DEL, Q, W, E, R, T, UP,
|
||||
BSPC, A, S, D, F, G,
|
||||
LSFT, FN29, X, C, V, B, FN1,
|
||||
FN30, FN4, TAB, LEFT, RIGHT,
|
||||
|
||||
BTN2,LGUI,
|
||||
HOME,
|
||||
SPC, ENT, END,
|
||||
//RIGHT
|
||||
RIGHT,6, 7, 8, 9, 0, MINS,
|
||||
UP, Y, U, I, O, P, BSLS,
|
||||
H, J, K, L, FN31, QUOT,
|
||||
FN1, N, M, COMM, DOT, FN28, RSFT,
|
||||
UP, DOWN, LBRC, RBRC, FN4,
|
||||
LALT, FN27,
|
||||
PGUP,
|
||||
PGDN, TAB, ENT
|
||||
),
|
||||
|
||||
/* Keymap 1: Symbol Layer
|
||||
*
|
||||
* ,--------------------------------------------------. ,--------------------------------------------------.
|
||||
* | Flash | F1 | F2 | F3 | F4 | F5 | | | | F6 | F7 | F8 | F9 | F10 | F11 |
|
||||
* |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
|
||||
* | | ! | @ | { | } | | | | | | Up | 7 | 8 | 9 | * | F12 |
|
||||
* |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
|
||||
* | : | # | $ | ( | ) | ` |------| |------| Down | 4 | 5 | 6 | + | |
|
||||
* |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
|
||||
* | | % | ^ | [ | ] | ~ | | | | & | 1 | 2 | 3 | \ | |
|
||||
* `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
|
||||
* | | | | | | | | . | 0 | = | |
|
||||
* `----------------------------------' `----------------------------------'
|
||||
* ,-------------. ,-------------.
|
||||
* | | | | | |
|
||||
* ,------|------|------| |------+------+------.
|
||||
* | | | | | | | |
|
||||
* | | |------| |------| | |
|
||||
* | | | | | | | |
|
||||
* `--------------------' `--------------------'
|
||||
*/
|
||||
// SYMBOLS
|
||||
KEYMAP(
|
||||
FN0, F1, F2, F3, F4, F5, TRNS,
|
||||
TRNS, FN7, FN8, FN23, FN24, FN18, TRNS,
|
||||
FN22, FN9, FN10, FN15, FN16, GRV,
|
||||
TRNS, FN11, FN12, LBRC, RBRC, FN17, TRNS,
|
||||
TRNS, TRNS, TRNS, TRNS, TRNS,
|
||||
|
||||
TRNS, TRNS,
|
||||
TRNS,
|
||||
TRNS, TRNS, TRNS,
|
||||
// right hand
|
||||
TRNS, F6, F7, F8, F9, F10, F11,
|
||||
TRNS, UP, 7, 8, 9, FN14, F12,
|
||||
DOWN, 4, 5, 6, FN26, TRNS,
|
||||
TRNS, FN13, 1, 2, 3, BSLS, TRNS,
|
||||
TRNS,DOT, 0, EQL, TRNS,
|
||||
TRNS, TRNS,
|
||||
TRNS,
|
||||
TRNS, TRNS, TRNS
|
||||
),
|
||||
/* Keymap 2: Media and mouse keys
|
||||
*
|
||||
* ,--------------------------------------------------. ,--------------------------------------------------.
|
||||
* | | | | | | | | | | | | | | | |
|
||||
* |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
|
||||
* | | | MsUp | | | | | | | | | | | | |
|
||||
* |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
|
||||
* | |MsLeft|MsDown|MsRght| | |------| |------| | | | Play | | |
|
||||
* |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
|
||||
* | | | | | | | | | | | | Prev | Next | | |
|
||||
* `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
|
||||
* | | | | Lclk | Rclk | |VolUp |VolDn | | | |
|
||||
* `----------------------------------' `----------------------------------'
|
||||
* ,-------------. ,-------------.
|
||||
* | | | | | |
|
||||
* ,------|------|------| |------+------+------.
|
||||
* | | | | | | | |
|
||||
* | | |------| |------| | |
|
||||
* | | | | | | | |
|
||||
* `--------------------' `--------------------'
|
||||
*/
|
||||
// MEDIA AND MOUSE
|
||||
KEYMAP(
|
||||
TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS,
|
||||
TRNS, TRNS, MS_U, TRNS, TRNS, TRNS, TRNS,
|
||||
TRNS, MS_L, MS_D, MS_R, TRNS, TRNS,
|
||||
TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS,
|
||||
TRNS, TRNS, TRNS, BTN3, BTN2,
|
||||
|
||||
TRNS, TRNS,
|
||||
TRNS,
|
||||
TRNS, TRNS, TRNS,
|
||||
// right hand
|
||||
TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS,
|
||||
TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS,
|
||||
TRNS, TRNS, TRNS, MPLY, TRNS, TRNS,
|
||||
TRNS, TRNS, TRNS, MPRV, MNXT, TRNS, TRNS,
|
||||
VOLU, VOLD, TRNS, TRNS, TRNS,
|
||||
TRNS, TRNS,
|
||||
TRNS,
|
||||
TRNS, TRNS, WBAK
|
||||
),
|
||||
};
|
||||
|
||||
/* id for user defined functions */
|
||||
enum function_id {
|
||||
TEENSY_KEY,
|
||||
};
|
||||
|
||||
/*
|
||||
* Fn action definition
|
||||
*/
|
||||
static const uint16_t PROGMEM fn_actions[] = {
|
||||
[0] = ACTION_FUNCTION(TEENSY_KEY), // FN0 - Teensy key
|
||||
[1] = ACTION_LAYER_INVERT(1, ON_RELEASE), // FN1 - Toggle 1
|
||||
[2] = ACTION_LAYER_TOGGLE(2), // FN2 - Toggle 2
|
||||
[3] = ACTION_LAYER_TOGGLE(3), // FN3 - Toggle 3
|
||||
[4] = ACTION_LAYER_TAP_TOGGLE(1), // FN4 - Momentary Layer 1
|
||||
[5] = ACTION_LAYER_MOMENTARY(2), // FN5 - Momentary L2
|
||||
|
||||
// SYMBOLS
|
||||
ACTION_MODS_KEY(MOD_LSFT, KC_QUOT), // FN6 - "
|
||||
ACTION_MODS_KEY(MOD_LSFT, KC_1), // FN7 - !
|
||||
ACTION_MODS_KEY(MOD_LSFT, KC_2), // FN8 - @
|
||||
ACTION_MODS_KEY(MOD_LSFT, KC_3), // FN9 - #
|
||||
ACTION_MODS_KEY(MOD_LSFT, KC_4), // FN10 - $
|
||||
ACTION_MODS_KEY(MOD_LSFT, KC_5), // FN11 - %
|
||||
ACTION_MODS_KEY(MOD_LSFT, KC_6), // FN12 - ^
|
||||
ACTION_MODS_KEY(MOD_LSFT, KC_7), // FN13 - &
|
||||
ACTION_MODS_KEY(MOD_LSFT, KC_8), // FN14 - *
|
||||
ACTION_MODS_KEY(MOD_LSFT, KC_9), // FN15 - (
|
||||
ACTION_MODS_KEY(MOD_LSFT, KC_0), // FN16 - )
|
||||
ACTION_MODS_KEY(MOD_LSFT, KC_GRV), // FN17 - ~
|
||||
ACTION_MODS_KEY(MOD_LSFT, KC_BSLS), // FN18 - |
|
||||
ACTION_MODS_KEY(MOD_LSFT, KC_MINS), // FN19 - _
|
||||
ACTION_MODS_KEY(MOD_LSFT, KC_COMM), // FN20 - <
|
||||
ACTION_MODS_KEY(MOD_LSFT, KC_DOT), // FN21 - >
|
||||
ACTION_MODS_KEY(MOD_LSFT, KC_SCLN), // FN22 - :
|
||||
ACTION_MODS_KEY(MOD_LSFT, KC_LBRC), // FN23 - {
|
||||
ACTION_MODS_KEY(MOD_LSFT, KC_RBRC), // FN24 - }
|
||||
ACTION_MODS_KEY(MOD_LSFT, KC_SLSH), // FN25 - ?
|
||||
ACTION_MODS_KEY(MOD_LSFT, KC_EQL), // FN26 - +
|
||||
|
||||
ACTION_MODS_TAP_KEY(MOD_LCTL, KC_ESC), // FN27 - Control/esc on tap
|
||||
ACTION_MODS_TAP_KEY(MOD_LCTL, KC_SLSH), // FN28 - slash becomes Ctrl when held (right pinky)
|
||||
ACTION_MODS_TAP_KEY(MOD_LCTL, KC_Z), // FN29 - z becomes Ctrl when held (left pinky)
|
||||
|
||||
// Fancy tapping/toggling
|
||||
ACTION_LAYER_TAP_KEY(1, KC_GRV), // FN30 - Layer 1 when holding backtick key
|
||||
ACTION_LAYER_TAP_KEY(2, KC_SCLN), // FN31 - Layer 2 when holding semicolon key
|
||||
|
||||
|
||||
};
|
||||
|
||||
void action_function(keyrecord_t *event, uint8_t id, uint8_t opt)
|
||||
{
|
||||
print("action_function called\n");
|
||||
print("id = "); phex(id); print("\n");
|
||||
print("opt = "); phex(opt); print("\n");
|
||||
if (id == TEENSY_KEY) {
|
||||
clear_keyboard();
|
||||
print("\n\nJump to bootloader... ");
|
||||
_delay_ms(250);
|
||||
bootloader_jump(); // should not return
|
||||
print("not supported.\n");
|
||||
}
|
||||
}
|
||||
|
||||
void * matrix_init_user(void) {
|
||||
|
||||
};
|
||||
|
||||
void * matrix_scan_user(void) {
|
||||
|
||||
};
|
348
keyboard/ergodox_ez/matrix.c
Normal file
348
keyboard/ergodox_ez/matrix.c
Normal file
|
@ -0,0 +1,348 @@
|
|||
/*
|
||||
|
||||
Note for ErgoDox EZ customizers: Here be dragons!
|
||||
This is not a file you want to be messing with.
|
||||
All of the interesting stuff for you is under keymaps/ :)
|
||||
Love, Erez
|
||||
|
||||
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_ez.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
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
208
keyboard/ergodox_ez/twimaster.c
Normal file
208
keyboard/ergodox_ez/twimaster.c
Normal file
|
@ -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 */
|
Loading…
Add table
Add a link
Reference in a new issue