Implementation for Ergodox project
This commit is contained in:
parent
60103a12b2
commit
cfc23836e5
14 changed files with 1665 additions and 0 deletions
115
keyboard/ergodox/Makefile.pjrc
Normal file
115
keyboard/ergodox/Makefile.pjrc
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
#----------------------------------------------------------------------------
|
||||
# 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_pjrc
|
||||
|
||||
# Directory common source filess exist
|
||||
TOP_DIR = ../..
|
||||
|
||||
# Directory keyboard dependent files exist
|
||||
TARGET_DIR = .
|
||||
|
||||
# project specific files
|
||||
SRC = keymap.c \
|
||||
matrix.c \
|
||||
led.c \
|
||||
ergodox.c \
|
||||
twimaster.c
|
||||
|
||||
CONFIG_H = config.h
|
||||
|
||||
|
||||
# MCU name, you MUST set this to match the board you are using
|
||||
# type "make clean" after changing this, so all files will be rebuilt
|
||||
MCU = atmega32u4
|
||||
#MCU = at90usb1286
|
||||
|
||||
|
||||
# Processor frequency.
|
||||
# Normally the first thing your program should do is set the clock prescaler,
|
||||
# so your program will run at the correct speed. You should also set this
|
||||
# variable to same clock speed. The _delay_ms() macro uses this, and many
|
||||
# examples use this variable to calculate timings. Do not add a "UL" here.
|
||||
F_CPU = 16000000
|
||||
|
||||
|
||||
# Boot Section Size in *bytes*
|
||||
# Teensy halfKay 512
|
||||
# Atmel DFU loader 4096
|
||||
# LUFA bootloader 4096
|
||||
OPT_DEFS += -DBOOTLOADER_SIZE=512 -DFLASH_SIZE_BYTES=0x8000
|
||||
|
||||
|
||||
# Build Options
|
||||
# comment out to disable the options.
|
||||
#
|
||||
BOOTMAGIC_ENABLE = yes # Virtual DIP switch configuration(+1000)
|
||||
MOUSEKEY_ENABLE = yes # Mouse keys(+5000)
|
||||
EXTRAKEY_ENABLE = yes # Audio control and System control(+600)
|
||||
CONSOLE_ENABLE = yes # Console for debug
|
||||
COMMAND_ENABLE = yes # Commands for debug and configuration
|
||||
SLEEP_LED_ENABLE = yes # Breathing sleep LED during USB suspend
|
||||
NKRO_ENABLE = yes # USB Nkey Rollover(+500)
|
||||
#PS2_MOUSE_ENABLE = yes # PS/2 mouse(TrackPoint) support
|
||||
INVERT_NUMLOCK = yes # invert state of NumLock led
|
||||
|
||||
|
||||
# Search Path
|
||||
VPATH += $(TARGET_DIR)
|
||||
VPATH += $(TOP_DIR)
|
||||
|
||||
include $(TOP_DIR)/protocol/pjrc.mk
|
||||
include $(TOP_DIR)/common.mk
|
||||
include $(TOP_DIR)/rules.mk
|
||||
|
||||
dvorak: OPT_DEFS += -DKEYMAP_DVORAK
|
||||
dvorak: all
|
||||
|
||||
colemak: OPT_DEFS += -DKEYMAP_COLEMAK
|
||||
colemak: all
|
||||
|
||||
workman: OPT_DEFS += -DKEYMAP_WORKMAN
|
||||
workman: all
|
||||
|
||||
cub: OPT_DEFS += -DKEYMAP_CUB
|
||||
cub: all
|
||||
|
||||
|
||||
10
keyboard/ergodox/TODO
Normal file
10
keyboard/ergodox/TODO
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
1. Flash led on ~Ln keypress (for now it works only on +Ln)
|
||||
2. Flash NumLock led only when "numpad" layer is active
|
||||
3. Command (in terms of IS_COMMAND) to switch to no-leds mode
|
||||
4. Increase count of ACTION keys
|
||||
5. Check how it works with ACTION/TAP keys (layerN+key or modifier+key)
|
||||
6. Fix command_state() onboard led:
|
||||
it should flash only when kbd in some specific mode (CONSOLE || MOUSE)
|
||||
7. Fix Right TEENSY key (for now it locks kbd & system)
|
||||
8. Cleanup everything, add conditionals (ifdef/ifndef), push to github
|
||||
|
||||
75
keyboard/ergodox/config.h
Normal file
75
keyboard/ergodox/config.h
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
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/>.
|
||||
|
||||
|
||||
This work is heavily based on initial firmware for Ergodox keyboard.
|
||||
Copyright (c) 2012, 2013 Ben Blazak <benblazak.dev@gmail.com>
|
||||
Released under The MIT License (see "doc/licenses/MIT.md")
|
||||
Project located at <https://github.com/benblazak/ergodox-firmware>
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_H
|
||||
#define CONFIG_H
|
||||
|
||||
|
||||
/* USB Device descriptor parameter */
|
||||
#define VENDOR_ID 0xFEED
|
||||
#define PRODUCT_ID 0x1111
|
||||
#define DEVICE_VER 0x0001
|
||||
#define MANUFACTURER TMK/Cub
|
||||
#define PRODUCT Ergodox
|
||||
#define DESCRIPTION t.m.k. keyboard firmware for Ergodox
|
||||
|
||||
#define MATRIX_ROWS 14
|
||||
#define MATRIX_COLS 6
|
||||
|
||||
/* define if matrix has ghost */
|
||||
//#define MATRIX_HAS_GHOST
|
||||
|
||||
/* Set 0 if debouncing isn't needed */
|
||||
#define DEBOUNCE 5
|
||||
|
||||
/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
|
||||
#define LOCKING_SUPPORT_ENABLE
|
||||
/* Locking resynchronize hack */
|
||||
#define LOCKING_RESYNC_ENABLE
|
||||
|
||||
/* key combination for command */
|
||||
#define IS_COMMAND() ( \
|
||||
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
|
||||
|
||||
#endif
|
||||
121
keyboard/ergodox/ergodox.c
Normal file
121
keyboard/ergodox/ergodox.c
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
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/>.
|
||||
|
||||
|
||||
This work is heavily based on initial firmware for Ergodox keyboard.
|
||||
Copyright (c) 2012, 2013 Ben Blazak <benblazak.dev@gmail.com>
|
||||
Released under The MIT License (see "doc/licenses/MIT.md")
|
||||
Project located at <https://github.com/benblazak/ergodox-firmware>
|
||||
|
||||
Most used files are located at
|
||||
<https://github.com/benblazak/ergodox-firmware/tree/partial-rewrite/firmware/keyboard/ergodox/controller>
|
||||
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <avr/io.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <util/delay.h>
|
||||
#include "action.h"
|
||||
#include "command.h"
|
||||
#include "print.h"
|
||||
#include "debug.h"
|
||||
#include "ergodox.h"
|
||||
#include "i2cmaster.h"
|
||||
|
||||
bool i2c_initialized = 0;
|
||||
|
||||
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 init_ergodox(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);
|
||||
|
||||
// blink leds
|
||||
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) {
|
||||
uint8_t err = 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
|
||||
err = i2c_start(I2C_ADDR_WRITE); if (err) goto out;
|
||||
err = i2c_write(IODIRA); if (err) goto out;
|
||||
err = i2c_write(0b00000000); if (err) goto out;
|
||||
err = i2c_write(0b00111111); if (err) goto out;
|
||||
i2c_stop();
|
||||
// set pull-up
|
||||
// - unused : on : 1
|
||||
// - input : on : 1
|
||||
// - driving : off : 0
|
||||
err = i2c_start(I2C_ADDR_WRITE); if (err) goto out;
|
||||
err = i2c_write(GPPUA); if (err) goto out;
|
||||
err = i2c_write(0b00000000); if (err) goto out;
|
||||
err = i2c_write(0b00111111); if (err) goto out;
|
||||
i2c_stop();
|
||||
|
||||
// set logical value (doesn't matter on inputs)
|
||||
// - unused : hi-Z : 1
|
||||
// - input : hi-Z : 1
|
||||
// - driving : hi-Z : 1
|
||||
err = i2c_start(I2C_ADDR_WRITE); if (err) goto out;
|
||||
err = i2c_write(OLATA); if (err) goto out;
|
||||
err = i2c_write(0b11111111
|
||||
& ~(ergodox_left_led_3<<LEFT_LED_3_SHIFT)
|
||||
); if (err) goto out;
|
||||
err = i2c_write(0b11111111
|
||||
& ~(ergodox_left_led_2<<LEFT_LED_2_SHIFT)
|
||||
& ~(ergodox_left_led_1<<LEFT_LED_1_SHIFT)
|
||||
); if (err) goto out;
|
||||
|
||||
out:
|
||||
i2c_stop();
|
||||
return err;
|
||||
}
|
||||
|
||||
114
keyboard/ergodox/ergodox.h
Normal file
114
keyboard/ergodox/ergodox.h
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
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/>.
|
||||
|
||||
|
||||
Copyright (c) 2012, 2013 Ben Blazak <benblazak.dev@gmail.com>
|
||||
Released under The MIT License (see "doc/licenses/MIT.md")
|
||||
Project located at <https://github.com/benblazak/ergodox-firmware>
|
||||
|
||||
Most used files are located at
|
||||
<https://github.com/benblazak/ergodox-firmware/tree/partial-rewrite/firmware/keyboard/ergodox/controller>
|
||||
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <avr/io.h>
|
||||
#include "i2cmaster.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
|
||||
|
||||
void init_ergodox(void);
|
||||
uint8_t init_mcp23018(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_left_leds_update(void) { init_mcp23018(); }
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
178
keyboard/ergodox/i2cmaster.h
Normal file
178
keyboard/ergodox/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
|
||||
228
keyboard/ergodox/keymap.c
Normal file
228
keyboard/ergodox/keymap.c
Normal file
|
|
@ -0,0 +1,228 @@
|
|||
/*
|
||||
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/>.
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include <util/delay.h>
|
||||
#include "keycode.h"
|
||||
#include "action.h"
|
||||
#include "action_code.h"
|
||||
#include "action_macro.h"
|
||||
#include "bootloader.h"
|
||||
#include "report.h"
|
||||
#include "host.h"
|
||||
#include "print.h"
|
||||
#include "debug.h"
|
||||
#include "keymap.h"
|
||||
#include "ergodox.h"
|
||||
|
||||
|
||||
/* ErgoDox keymap definition macro */
|
||||
#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 */ \
|
||||
{ \
|
||||
{ KC_##k00,KC_##k10,KC_##k20,KC_##k30,KC_##k40,KC_NO }, \
|
||||
{ KC_##k01,KC_##k11,KC_##k21,KC_##k31,KC_##k41,KC_##k51}, \
|
||||
{ KC_##k02,KC_##k12,KC_##k22,KC_##k32,KC_##k42,KC_##k52}, \
|
||||
{ KC_##k03,KC_##k13,KC_##k23,KC_##k33,KC_##k43,KC_##k53}, \
|
||||
{ KC_##k04,KC_##k14,KC_##k24,KC_##k34,KC_##k44,KC_##k54}, \
|
||||
{ KC_##k05,KC_##k15,KC_##k25,KC_##k35,KC_NO, KC_##k55}, \
|
||||
{ KC_##k06,KC_##k16,KC_NO, KC_##k36,KC_NO, KC_##k56}, \
|
||||
\
|
||||
{ KC_##k07,KC_##k17,KC_NO, KC_##k37,KC_NO, KC_##k57}, \
|
||||
{ KC_##k08,KC_##k18,KC_##k28,KC_##k38,KC_NO, KC_##k58}, \
|
||||
{ KC_##k09,KC_##k19,KC_##k29,KC_##k39,KC_##k49,KC_##k59}, \
|
||||
{ KC_##k0A,KC_##k1A,KC_##k2A,KC_##k3A,KC_##k4A,KC_##k5A}, \
|
||||
{ KC_##k0B,KC_##k1B,KC_##k2B,KC_##k3B,KC_##k4B,KC_##k5B}, \
|
||||
{ KC_##k0C,KC_##k1C,KC_##k2C,KC_##k3C,KC_##k4C,KC_##k5C}, \
|
||||
{ KC_##k0D,KC_##k1D,KC_##k2D,KC_##k3D,KC_##k4D,KC_NO } \
|
||||
}
|
||||
|
||||
#if defined(KEYMAP_DVORAK)
|
||||
#include "keymap_dvorak.h"
|
||||
#elif defined(KEYMAP_COLEMAK)
|
||||
#include "keymap_colemak.h"
|
||||
#elif defined(KEYMAP_WORKMAN)
|
||||
#include "keymap_workman.h"
|
||||
#elif defined(KEYMAP_CUB)
|
||||
#include "keymap_cub.h"
|
||||
#else
|
||||
|
||||
static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||
KEYMAP( // layer 0 : default
|
||||
// left hand
|
||||
EQL, 1, 2, 3, 4, 5, ESC,
|
||||
BSLS,Q, W, E, R, T, FN2,
|
||||
TAB, A, S, D, F, G,
|
||||
LSFT,Z, X, C, V, B, FN1,
|
||||
LGUI,GRV, BSLS,LEFT,RGHT,
|
||||
LCTL,LALT,
|
||||
HOME,
|
||||
BSPC,DEL, END,
|
||||
// right hand
|
||||
FN3, 6, 7, 8, 9, 0, MINS,
|
||||
LBRC,Y, U, I, O, P, RBRC,
|
||||
H, J, K, L, SCLN,QUOT,
|
||||
FN1, N, M, COMM,DOT, SLSH,RSFT,
|
||||
LEFT,DOWN,UP, RGHT,RGUI,
|
||||
RALT,RCTL,
|
||||
PGUP,
|
||||
PGDN,ENT, SPC
|
||||
),
|
||||
|
||||
KEYMAP( // layer 1 : function and symbol keys
|
||||
// left hand
|
||||
TRNS,F1, F2, F3, F4, F5, F11,
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,FN4,
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,
|
||||
TRNS,TRNS,
|
||||
TRNS,
|
||||
TRNS,TRNS,TRNS,
|
||||
// right hand
|
||||
F12, F6, F7, F8, F9, F10, TRNS,
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,
|
||||
TRNS,TRNS,
|
||||
TRNS,
|
||||
TRNS,TRNS,TRNS
|
||||
),
|
||||
|
||||
KEYMAP( // layer 2 : keyboard functions
|
||||
// left hand
|
||||
FN0, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,
|
||||
TRNS,TRNS,
|
||||
TRNS,
|
||||
TRNS,TRNS,TRNS,
|
||||
// right hand
|
||||
FN4, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,
|
||||
TRNS,TRNS,
|
||||
TRNS,
|
||||
TRNS,TRNS,TRNS
|
||||
),
|
||||
|
||||
KEYMAP( // layer 3: numpad
|
||||
// left hand
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,
|
||||
TRNS,TRNS,
|
||||
TRNS,
|
||||
TRNS,TRNS,TRNS,
|
||||
// right hand
|
||||
SLCK,NLCK,PSLS,PAST,PAST,PMNS,BSPC,
|
||||
TRNS,NO, P7, P8, P9, PMNS,BSPC,
|
||||
NO, P4, P5, P6, PPLS,PENT,
|
||||
TRNS,NO, P1, P2, P3, PPLS,PENT,
|
||||
P0, PDOT,SLSH,PENT,PENT,
|
||||
TRNS,TRNS,
|
||||
TRNS,
|
||||
TRNS,TRNS,TRNS
|
||||
),
|
||||
|
||||
};
|
||||
|
||||
/* id for user defined functions */
|
||||
enum function_id {
|
||||
TEENSY_KEY,
|
||||
};
|
||||
|
||||
/*
|
||||
* Fn action definition
|
||||
*/
|
||||
static const uint16_t PROGMEM fn_actions[] = {
|
||||
ACTION_FUNCTION(TEENSY_KEY), // FN0 - Teensy key
|
||||
ACTION_LAYER_MOMENTARY(1), // FN1 - switch to Layer1
|
||||
ACTION_LAYER_SET(2, ON_PRESS), // FN2 - push Layer2
|
||||
ACTION_LAYER_SET(3, ON_PRESS), // FN3 - push Layer3
|
||||
ACTION_LAYER_SET(0, ON_PRESS), // FN4 - push Layer0
|
||||
};
|
||||
|
||||
void action_function(keyrecord_t *event, uint8_t id, uint8_t opt)
|
||||
{
|
||||
if (id == TEENSY_KEY) {
|
||||
clear_keyboard();
|
||||
print("\n\nJump to bootloader... ");
|
||||
_delay_ms(250);
|
||||
bootloader_jump(); // should not return
|
||||
print("not supported.\n");
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#define KEYMAPS_SIZE (sizeof(keymaps) / sizeof(keymaps[0]))
|
||||
#define FN_ACTIONS_SIZE (sizeof(fn_actions) / sizeof(fn_actions[0]))
|
||||
|
||||
/* translates key to keycode */
|
||||
uint8_t keymap_key_to_keycode(uint8_t layer, key_t key)
|
||||
{
|
||||
if (layer < KEYMAPS_SIZE) {
|
||||
return pgm_read_byte(&keymaps[(layer)][(key.row)][(key.col)]);
|
||||
} else {
|
||||
// fall back to layer 0
|
||||
return pgm_read_byte(&keymaps[0][(key.row)][(key.col)]);
|
||||
}
|
||||
}
|
||||
|
||||
/* translates Fn keycode to action */
|
||||
action_t keymap_fn_to_action(uint8_t keycode)
|
||||
{
|
||||
action_t action;
|
||||
if (FN_INDEX(keycode) < FN_ACTIONS_SIZE) {
|
||||
action.code = pgm_read_word(&fn_actions[FN_INDEX(keycode)]);
|
||||
} else {
|
||||
action.code = ACTION_NO;
|
||||
}
|
||||
return action;
|
||||
}
|
||||
|
||||
4
keyboard/ergodox/keymap_colemak.h
Normal file
4
keyboard/ergodox/keymap_colemak.h
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
#error Colemak layout is not defined yet
|
||||
static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||
};
|
||||
static const uint16_t PROGMEM fn_actions[] = {};
|
||||
227
keyboard/ergodox/keymap_cub.h
Normal file
227
keyboard/ergodox/keymap_cub.h
Normal file
|
|
@ -0,0 +1,227 @@
|
|||
static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||
/* Keymap 0: Default Layer
|
||||
*
|
||||
* ,--------------------------------------------------. ,--------------------------------------------------.
|
||||
* | ~ | 1 | 2 | 3 | 4 | 5 | \ | | ' | 6 | 7 | 8 | 9 | 0 | = |
|
||||
* |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
|
||||
* | Tab | Q | W | E | R | T | ~Fn1 | | ~Fn3 | Y | U | I | O | P | [ |
|
||||
* |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
|
||||
* | LShift | A | S | D | F | G |------| |------| H | J | K | L | ; | RShift |
|
||||
* |--------+------+------+------+------+------| Fn0 | | ~Fn4 |------+------+------+------+------+--------|
|
||||
* | LCtrl | Z | X | C | V | B | | | | N | M | , | . | / | RCtrl |
|
||||
* `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
|
||||
* | ~Fn1 | ~Fn2 | Caps | LAlt | LGui | | Lft | Up | Dn | Rght | ~Fn4 |
|
||||
* `----------------------------------' `----------------------------------'
|
||||
* ,-------------. ,-------------.
|
||||
* | +Fn2 | Home | | PgUp | Del |
|
||||
* ,------|------|------| |------+------+------.
|
||||
* | | | End | | PgDn | | |
|
||||
* | BkSp | ESC |------| |------| Enter| Space|
|
||||
* | | | Spc | | Ins | | |
|
||||
* `--------------------' `--------------------'
|
||||
*/
|
||||
|
||||
KEYMAP( // layout: layer 0: default
|
||||
// left hand
|
||||
GRV, 1, 2, 3, 4, 5, BSLS,
|
||||
TAB, Q, W, E, R, T, FN1,
|
||||
LSFT,A, S, D, F, G,
|
||||
LCTL,Z, X, C, V, B, FN0,
|
||||
FN1, FN6, CAPS,LALT,LGUI,
|
||||
FN2, HOME,
|
||||
END,
|
||||
BSPC,ESC, SPC,
|
||||
// right hand
|
||||
QUOT,6, 7, 8, 9, 0, EQL,
|
||||
FN3, Y, U, I, O, P, LBRC,
|
||||
H, J, K, L, SCLN,RSFT,
|
||||
FN4, N, M, COMM,DOT, SLSH,RCTL,
|
||||
LEFT,UP, DOWN,RGHT,FN4,
|
||||
PGUP,DEL,
|
||||
PGDN,
|
||||
INS, ENT, SPC
|
||||
),
|
||||
|
||||
KEYMAP( // layout: layer 1: F-keys instead of numbers
|
||||
// left hand
|
||||
TRNS,F1, F2, F3, F4, F5, F6,
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
|
||||
TRNS,TRNS,TRNS,LALT,LGUI,
|
||||
TRNS,TRNS,
|
||||
TRNS,
|
||||
LCTL,LSFT,TRNS,
|
||||
// right hand
|
||||
F7, F8, F9, F10, F11, F12, MINS,
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,RBRC,
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
|
||||
RGUI,RALT,TRNS,TRNS,TRNS,
|
||||
TRNS,TRNS,
|
||||
TRNS,
|
||||
TRNS,RSFT,RCTL
|
||||
),
|
||||
|
||||
KEYMAP( // layout: layer 2: mouse + numpad
|
||||
// left hand
|
||||
TRNS,NO, NO, NO, NO, PAUS,PSCR,
|
||||
TRNS,WH_L,WH_U,WH_D,WH_R,BTN2,TRNS,
|
||||
TRNS,MS_L,MS_U,MS_D,MS_R,BTN1,
|
||||
TRNS,NO, NO, NO, NO, BTN3,TRNS,
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,
|
||||
TRNS,TRNS,
|
||||
TRNS,
|
||||
TRNS,TRNS,TRNS,
|
||||
// right hand
|
||||
SLCK,NLCK,PSLS,PAST,PAST,PMNS,BSPC,
|
||||
TRNS,NO, P7, P8, P9, PMNS,BSPC,
|
||||
NO, P4, P5, P6, PPLS,PENT,
|
||||
TRNS,NO, P1, P2, P3, PPLS,PENT,
|
||||
P0, PDOT,SLSH,PENT,PENT,
|
||||
TRNS,TRNS,
|
||||
TRNS,
|
||||
TRNS,TRNS,TRNS
|
||||
),
|
||||
|
||||
KEYMAP( // layout: layer 3: F-keys only
|
||||
// left hand
|
||||
TRNS,NO, NO, NO, NO, NO, NO,
|
||||
TRNS,F13, F14, F15, F16, NO, TRNS,
|
||||
TRNS,F17, F18, F19, F20, NO,
|
||||
TRNS,F21, F22, F23, F24, NO, TRNS,
|
||||
TRNS,TRNS,TRNS,LALT,LGUI,
|
||||
TRNS,TRNS,
|
||||
TRNS,
|
||||
LCTL,LSFT,TRNS,
|
||||
// right hand
|
||||
NO, NO, NO, NO, NO, NO, TRNS,
|
||||
TRNS,NO, F1, F2, F3, F4, TRNS,
|
||||
NO, F5, F6, F7, F8, TRNS,
|
||||
TRNS,NO, F9, F10, F11, F12, TRNS,
|
||||
RGUI,RALT,TRNS,TRNS,TRNS,
|
||||
TRNS,TRNS,
|
||||
TRNS,
|
||||
TRNS,RSFT,RCTL
|
||||
),
|
||||
|
||||
KEYMAP( // layout: layer 4: F-keys + cursor
|
||||
// left hand
|
||||
TRNS,F1, F2, F3, F4, F5, F6,
|
||||
FN7, NO, PGUP,UP, PGDN,PGUP,TRNS,
|
||||
TRNS,NO, LEFT,DOWN,RGHT,PGDN,
|
||||
TRNS,NO, NO, END, HOME,NO, TRNS,
|
||||
FN5, TRNS,TRNS,LALT,LGUI,
|
||||
TRNS,TRNS,
|
||||
TRNS,
|
||||
LCTL,LSFT,TRNS,
|
||||
// right hand
|
||||
F7, F8, F9, F10, F11, F12, MINS,
|
||||
TRNS,PGUP,PGUP,UP, PGDN,NO, FN7,
|
||||
PGDN,LEFT,DOWN,RGHT,NO, TRNS,
|
||||
TRNS,NO, HOME,END, NO, NO, TRNS,
|
||||
RGUI,RALT,TRNS,TRNS,TRNS,
|
||||
TRNS,TRNS,
|
||||
TRNS,
|
||||
TRNS,RSFT,RCTL
|
||||
),
|
||||
|
||||
KEYMAP( // layout: layer 5: Workman layout
|
||||
// left hand
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
|
||||
TRNS,Q, D, R, W, B, TRNS,
|
||||
TRNS,A, S, H, T, G,
|
||||
TRNS,Z, X, M, C, V, TRNS,
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,
|
||||
TRNS,TRNS,
|
||||
TRNS,
|
||||
TRNS,TRNS,TRNS,
|
||||
// right hand
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
|
||||
TRNS,J, F, U, P, 4, TRNS,
|
||||
Y, N, E, O, I, TRNS,
|
||||
TRNS,K, L, TRNS,TRNS,TRNS,TRNS,
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,
|
||||
TRNS,TRNS,
|
||||
TRNS,
|
||||
TRNS,TRNS,TRNS
|
||||
),
|
||||
|
||||
/*
|
||||
KEYMAP( // layout: layer N: transparent on edges, all others are empty
|
||||
// left hand
|
||||
TRNS,NO, NO, NO, NO, NO, NO,
|
||||
TRNS,NO, NO, NO, NO, NO, TRNS,
|
||||
TRNS,NO, NO, NO, NO, NO,
|
||||
TRNS,NO, NO, NO, NO, NO, TRNS,
|
||||
TRNS,TRNS,TRNS,LALT,LGUI,
|
||||
TRNS,TRNS,
|
||||
TRNS,
|
||||
LCTL,LSFT,TRNS,
|
||||
// right hand
|
||||
NO, NO, NO, NO, NO, NO, TRNS,
|
||||
TRNS,NO, NO, NO, NO, NO, TRNS,
|
||||
NO, NO, NO, NO, NO, TRNS,
|
||||
TRNS,NO, NO, NO, NO, NO, TRNS,
|
||||
RGUI,RALT,TRNS,TRNS,TRNS,
|
||||
TRNS,TRNS,
|
||||
TRNS,
|
||||
TRNS,RSFT,RCTL
|
||||
),
|
||||
KEYMAP( // layout: layer N: fully transparent
|
||||
// left hand
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,
|
||||
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,TRNS,TRNS,TRNS,
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
|
||||
TRNS,TRNS,TRNS,TRNS,TRNS,
|
||||
TRNS,TRNS,
|
||||
TRNS,
|
||||
TRNS,TRNS,TRNS
|
||||
),
|
||||
*/
|
||||
|
||||
};
|
||||
|
||||
/* id for user defined functions */
|
||||
enum function_id {
|
||||
TEENSY_KEY,
|
||||
};
|
||||
|
||||
/*
|
||||
* Fn action definition
|
||||
*/
|
||||
static const uint16_t PROGMEM fn_actions[] = {
|
||||
ACTION_DEFAULT_LAYER_SET(0), // FN0 - switch to Layer0
|
||||
ACTION_LAYER_MOMENTARY(1), // FN1 - push Layer1
|
||||
ACTION_DEFAULT_LAYER_SET(2), // FN2 - switch to Layer2
|
||||
ACTION_LAYER_MOMENTARY(3), // FN3 - push Layer3
|
||||
ACTION_LAYER_MOMENTARY(4), // FN4 - push Layer4
|
||||
ACTION_DEFAULT_LAYER_SET(5), // FN5 - switch to Layer5
|
||||
ACTION_LAYER_MOMENTARY(2), // FN6 - push Layer2
|
||||
ACTION_FUNCTION(TEENSY_KEY), // FN7 - Teensy 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");
|
||||
}
|
||||
}
|
||||
|
||||
4
keyboard/ergodox/keymap_dvorak.h
Normal file
4
keyboard/ergodox/keymap_dvorak.h
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
#error Dvorak layout is not defined yet
|
||||
static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||
};
|
||||
static const uint16_t PROGMEM fn_actions[] = {};
|
||||
4
keyboard/ergodox/keymap_workman.h
Normal file
4
keyboard/ergodox/keymap_workman.h
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
#error Workman layout is not defined yet
|
||||
static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||
};
|
||||
static const uint16_t PROGMEM fn_actions[] = {};
|
||||
57
keyboard/ergodox/led.c
Normal file
57
keyboard/ergodox/led.c
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
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/>.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <avr/io.h>
|
||||
#include "print.h"
|
||||
#include "debug.h"
|
||||
#include "led.h"
|
||||
#include "ergodox.h"
|
||||
|
||||
|
||||
void led_set(uint8_t usb_led)
|
||||
{
|
||||
// topmost - NumLock
|
||||
#ifdef INVERT_NUMLOCK
|
||||
if (usb_led & (1<<USB_LED_NUM_LOCK)) {
|
||||
ergodox_right_led_1_on();
|
||||
} else {
|
||||
ergodox_right_led_1_off();
|
||||
}
|
||||
#else
|
||||
if (usb_led & (1<<USB_LED_NUM_LOCK)) {
|
||||
ergodox_right_led_1_off();
|
||||
} else {
|
||||
ergodox_right_led_1_on();
|
||||
}
|
||||
#endif
|
||||
|
||||
// middle - CapsLock
|
||||
if (usb_led & (1<<USB_LED_CAPS_LOCK)) {
|
||||
ergodox_right_led_2_on();
|
||||
} else {
|
||||
ergodox_right_led_2_off();
|
||||
}
|
||||
|
||||
// bottommost - ScrollLock
|
||||
if (usb_led & (1<<USB_LED_SCROLL_LOCK)) {
|
||||
ergodox_right_led_3_on();
|
||||
} else {
|
||||
ergodox_right_led_3_off();
|
||||
}
|
||||
}
|
||||
|
||||
326
keyboard/ergodox/matrix.c
Normal file
326
keyboard/ergodox/matrix.c
Normal file
|
|
@ -0,0 +1,326 @@
|
|||
/*
|
||||
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"
|
||||
|
||||
#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 mcp23018_status, uint8_t row);
|
||||
static void init_cols(void);
|
||||
static void unselect_rows(uint8_t mcp23018_status);
|
||||
static void select_row(uint8_t mcp23018_status, uint8_t row);
|
||||
|
||||
|
||||
inline
|
||||
uint8_t matrix_rows(void)
|
||||
{
|
||||
return MATRIX_ROWS;
|
||||
}
|
||||
|
||||
inline
|
||||
uint8_t matrix_cols(void)
|
||||
{
|
||||
return MATRIX_COLS;
|
||||
}
|
||||
|
||||
void matrix_init(void)
|
||||
{
|
||||
// initialize row and col
|
||||
init_ergodox();
|
||||
uint8_t mcp23018_status;
|
||||
mcp23018_status = init_mcp23018();
|
||||
unselect_rows(mcp23018_status);
|
||||
init_cols();
|
||||
|
||||
// initialize matrix state: all keys off
|
||||
for (uint8_t i=0; i < MATRIX_ROWS; i++) {
|
||||
matrix[i] = 0;
|
||||
matrix_debouncing[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t matrix_scan(void)
|
||||
{
|
||||
#ifdef KEYMAP_CUB
|
||||
uint8_t layer = biton32(layer_state);
|
||||
|
||||
if (layer == 1) {
|
||||
ergodox_left_led_1_on();
|
||||
ergodox_left_led_2_off();
|
||||
ergodox_left_led_3_off();
|
||||
} else if (layer == 2) {
|
||||
ergodox_left_led_1_off();
|
||||
ergodox_left_led_2_on();
|
||||
ergodox_left_led_3_off();
|
||||
} else if (layer == 3) {
|
||||
ergodox_left_led_1_off();
|
||||
ergodox_left_led_2_off();
|
||||
ergodox_left_led_3_on();
|
||||
} else if (layer == 4) {
|
||||
ergodox_left_led_1_on();
|
||||
ergodox_left_led_2_off();
|
||||
ergodox_left_led_3_on();
|
||||
} else if (layer == 5) {
|
||||
ergodox_left_led_1_on();
|
||||
ergodox_left_led_2_on();
|
||||
ergodox_left_led_3_off();
|
||||
} else if (layer == 6) {
|
||||
ergodox_left_led_1_off();
|
||||
ergodox_left_led_2_on();
|
||||
ergodox_left_led_3_on();
|
||||
} else if (layer == 7) {
|
||||
ergodox_left_led_1_on();
|
||||
ergodox_left_led_2_on();
|
||||
ergodox_left_led_3_on();
|
||||
} else {
|
||||
ergodox_left_led_1_off();
|
||||
ergodox_left_led_2_off();
|
||||
ergodox_left_led_3_off();
|
||||
}
|
||||
|
||||
// not actually needed because we already calling init_mcp23018() in next line
|
||||
// ergodox_left_leds_update();
|
||||
|
||||
#endif
|
||||
|
||||
uint8_t mcp23018_status = init_mcp23018();
|
||||
|
||||
for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
|
||||
select_row(mcp23018_status, i);
|
||||
_delay_us(30); // without this wait read unstable value.
|
||||
matrix_row_t cols = read_cols(mcp23018_status, i);
|
||||
if (matrix_debouncing[i] != cols) {
|
||||
matrix_debouncing[i] = cols;
|
||||
if (debouncing) {
|
||||
debug("bounce!: "); debug_hex(debouncing); debug("\n");
|
||||
}
|
||||
debouncing = DEBOUNCE;
|
||||
}
|
||||
unselect_rows(mcp23018_status);
|
||||
}
|
||||
|
||||
if (debouncing) {
|
||||
if (--debouncing) {
|
||||
_delay_ms(1);
|
||||
} else {
|
||||
for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
|
||||
matrix[i] = matrix_debouncing[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 mcp23018_status, uint8_t row)
|
||||
{
|
||||
if (row < 7) {
|
||||
if (mcp23018_status) { // if there was an error
|
||||
return 0;
|
||||
} else {
|
||||
uint8_t data = 0;
|
||||
uint8_t err = 0x20;
|
||||
err = i2c_start(I2C_ADDR_WRITE); if (err) goto out;
|
||||
err = i2c_write(GPIOB); if (err) goto out;
|
||||
err = i2c_start(I2C_ADDR_READ); if (err) goto out;
|
||||
data = i2c_readNak();
|
||||
data = ~data;
|
||||
out:
|
||||
i2c_stop();
|
||||
return data;
|
||||
}
|
||||
} else {
|
||||
// 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(uint8_t mcp23018_status)
|
||||
{
|
||||
// unselect on mcp23018
|
||||
if (mcp23018_status) { // if there was an error
|
||||
// do nothing
|
||||
} else {
|
||||
// set all rows hi-Z : 1
|
||||
uint8_t err = 0x20;
|
||||
err = i2c_start(I2C_ADDR_WRITE); if (err) goto out;
|
||||
err = i2c_write(GPIOA); if (err) goto out;
|
||||
err = i2c_write( 0xFF
|
||||
& ~(ergodox_left_led_3<<LEFT_LED_3_SHIFT)
|
||||
); if (err) 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 mcp23018_status, 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
|
||||
uint8_t err = 0x20;
|
||||
err = i2c_start(I2C_ADDR_WRITE); if (err) goto out;
|
||||
err = i2c_write(GPIOA); if (err) goto out;
|
||||
err = i2c_write( 0xFF & ~(1<<row)
|
||||
& ~(ergodox_left_led_3<<LEFT_LED_3_SHIFT)
|
||||
); if (err) 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
202
keyboard/ergodox/twimaster.c
Normal file
202
keyboard/ergodox/twimaster.c
Normal file
|
|
@ -0,0 +1,202 @@
|
|||
/*************************************************************************
|
||||
* 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 4000000UL
|
||||
#endif
|
||||
|
||||
/* I2C clock in Hz */
|
||||
#define SCL_CLOCK 100000L
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
Initialization of the I2C bus interface. Need to be called only once
|
||||
*************************************************************************/
|
||||
void i2c_init(void)
|
||||
{
|
||||
/* initialize TWI clock: 100 kHz clock, TWPS = 0 => prescaler = 1 */
|
||||
|
||||
TWSR = 0; /* no prescaler */
|
||||
TWBR = ((F_CPU/SCL_CLOCK)-16)/2; /* 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
Reference in a new issue