aboutsummaryrefslogtreecommitdiff
path: root/keyboards/ergodone
diff options
context:
space:
mode:
authorJack Humbert <jack.humb@gmail.com>2017-08-23 22:29:07 -0400
committerGitHub <noreply@github.com>2017-08-23 22:29:07 -0400
commitd2ff66a985b938e87fffe55c1d9f1dc55e356f91 (patch)
tree561b3e203033849573a17f5ac6248077ab687676 /keyboards/ergodone
parent7260fc3eef98fb7b0e2ed24d3d0d14cf2e613000 (diff)
downloadqmk_firmware-d2ff66a985b938e87fffe55c1d9f1dc55e356f91.tar.gz
qmk_firmware-d2ff66a985b938e87fffe55c1d9f1dc55e356f91.zip
Creates a layouts/ folder for keymaps shared between keyboards (#1609)
* include variables and .h files as pp directives * start layout compilation * split ergodoxes up * don't compile all layouts for everything * might seg fault * reset layouts variable * actually reset layouts * include rules.mk instead * remove includes from rules.mk * update variable setting * load visualizer from path * adds some more examples * adds more layouts * more boards added * more boards added * adds documentation for layouts * use lowercase names for LAYOUT_ * add layout.json files for each layout * add community folder, default keymaps for layouts * touch-up default layouts * touch-up layouts, some keyboard rules.mk * update documentation for layouts * fix up serial/i2c switches
Diffstat (limited to 'keyboards/ergodone')
-rw-r--r--keyboards/ergodone/Makefile3
-rw-r--r--keyboards/ergodone/config.h78
-rw-r--r--keyboards/ergodone/ergodone.c5
-rw-r--r--keyboards/ergodone/ergodone.h65
-rw-r--r--keyboards/ergodone/expander.c120
-rw-r--r--keyboards/ergodone/expander.h48
-rw-r--r--keyboards/ergodone/i2cmaster.h178
-rw-r--r--keyboards/ergodone/keymaps/default/keymap.c223
-rw-r--r--keyboards/ergodone/keymaps/default/readme.md15
-rw-r--r--keyboards/ergodone/matrix.c295
-rw-r--r--keyboards/ergodone/readme.md26
-rw-r--r--keyboards/ergodone/rules.mk95
-rw-r--r--keyboards/ergodone/twimaster.c208
13 files changed, 1359 insertions, 0 deletions
diff --git a/keyboards/ergodone/Makefile b/keyboards/ergodone/Makefile
new file mode 100644
index 000000000..bd09e5885
--- /dev/null
+++ b/keyboards/ergodone/Makefile
@@ -0,0 +1,3 @@
1ifndef MAKEFILE_INCLUDED
2 include ../../../Makefile
3endif
diff --git a/keyboards/ergodone/config.h b/keyboards/ergodone/config.h
new file mode 100644
index 000000000..d3e0f8036
--- /dev/null
+++ b/keyboards/ergodone/config.h
@@ -0,0 +1,78 @@
1#ifndef ERGODOX_ERGODONE_CONFIG_H
2#define ERGODOX_ERGODONE_CONFIG_H
3
4#include "config_common.h"
5
6/* USB Device descriptor parameter */
7#define VENDOR_ID 0xFEED
8#define PRODUCT_ID 0x1307
9#define DEVICE_VER 0x0001
10#define MANUFACTURER ErgoDone
11#define PRODUCT ErgoDone
12#define DESCRIPTION QMK keyboard firmware for ErgoDone
13
14/* key matrix size */
15#define MATRIX_ROWS 6
16#define MATRIX_COLS 14
17
18#define MOUSEKEY_INTERVAL 20
19#define MOUSEKEY_DELAY 0
20#define MOUSEKEY_TIME_TO_MAX 60
21#define MOUSEKEY_MAX_SPEED 7
22#define MOUSEKEY_WHEEL_DELAY 0
23
24#define TAPPING_TOGGLE 1
25
26/* define if matrix has ghost */
27//#define MATRIX_HAS_GHOST
28
29#define TAPPING_TERM 200
30#define IGNORE_MOD_TAP_INTERRUPT // this makes it possible to do rolling combos (zx) with keys that convert to other keys on hold (z becomes ctrl when you hold it, and when this option isn't enabled, z rapidly followed by x actually sends Ctrl-x. That's bad.)
31
32/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
33#define LOCKING_SUPPORT_ENABLE
34/* Locking resynchronize hack */
35#define LOCKING_RESYNC_ENABLE
36
37/* key combination for command */
38#define IS_COMMAND() ( \
39 keyboard_report->mods == (MOD_BIT(KC_LCTL) | MOD_BIT(KC_RCTL)) || \
40 keyboard_report->mods == (MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)) \
41)
42
43/* number of backlight levels */
44#define BACKLIGHT_LEVELS 3
45
46#define LED_BRIGHTNESS_LO 15
47#define LED_BRIGHTNESS_HI 255
48
49/* fix space cadet rollover issue */
50#define DISABLE_SPACE_CADET_ROLLOVER
51
52/* Set 0 if debouncing isn't needed */
53#define DEBOUNCE 5
54
55#define PREVENT_STUCK_MODIFIERS
56
57#define USB_MAX_POWER_CONSUMPTION 500
58
59/*
60 * Feature disable options
61 * These options are also useful to firmware size reduction.
62 */
63
64/* disable debug print */
65// #define NO_DEBUG
66
67/* disable print */
68// #define NO_PRINT
69
70/* disable action features */
71//#define NO_ACTION_LAYER
72//#define NO_ACTION_TAPPING
73//#define NO_ACTION_ONESHOT
74//#define NO_ACTION_MACRO
75//#define NO_ACTION_FUNCTION
76//#define DEBUG_MATRIX_SCAN_RATE
77
78#endif
diff --git a/keyboards/ergodone/ergodone.c b/keyboards/ergodone/ergodone.c
new file mode 100644
index 000000000..6b8d8a063
--- /dev/null
+++ b/keyboards/ergodone/ergodone.c
@@ -0,0 +1,5 @@
1#include "ergodone.h"
2
3void matrix_init_kb(void) {
4 matrix_init_user();
5}
diff --git a/keyboards/ergodone/ergodone.h b/keyboards/ergodone/ergodone.h
new file mode 100644
index 000000000..9f6c8f841
--- /dev/null
+++ b/keyboards/ergodone/ergodone.h
@@ -0,0 +1,65 @@
1#ifndef ERGODOX_ERGODONE_H
2#define ERGODOX_ERGODONE_H
3
4#include "quantum.h"
5#include <stdint.h>
6#include <stdbool.h>
7
8#define CPU_PRESCALE(n) (CLKPR = 0x80, CLKPR = (n))
9#define CPU_16MHz 0x00
10
11void init_ergodox(void);
12
13inline void ergodox_right_led_1_off(void) {}
14inline void ergodox_right_led_1_on(void) {}
15inline void ergodox_right_led_2_off(void) {}
16inline void ergodox_right_led_2_on(void) {}
17inline void ergodox_right_led_3_off(void) {}
18inline void ergodox_right_led_3_on(void) {}
19inline void ergodox_right_led_on(uint8_t l) {}
20inline void ergodox_right_led_off(uint8_t l) {}
21inline void ergodox_board_led_off(void) {}
22inline void ergodox_board_led_on(void) {}
23inline void ergodox_led_all_on(void) {}
24inline void ergodox_led_all_off(void) {}
25inline void ergodox_right_led_1_set(uint8_t n) {}
26inline void ergodox_right_led_2_set(uint8_t n) {}
27inline void ergodox_right_led_3_set(uint8_t n) {}
28inline void ergodox_right_led_set(uint8_t l, uint8_t n) {}
29inline void ergodox_led_all_set(uint8_t n) {}
30
31#define KEYMAP( \
32 \
33 /* left hand, spatial positions */ \
34 k00,k01,k02,k03,k04,k05,k06, \
35 k10,k11,k12,k13,k14,k15,k16, \
36 k20,k21,k22,k23,k24,k25, \
37 k30,k31,k32,k33,k34,k35,k36, \
38 k40,k41,k42,k43,k44, \
39 k55,k56, \
40 k54, \
41 k53,k52,k51, \
42 \
43 /* right hand, spatial positions */ \
44 k07,k08,k09,k0A,k0B,k0C,k0D, \
45 k17,k18,k19,k1A,k1B,k1C,k1D, \
46 k28,k29,k2A,k2B,k2C,k2D, \
47 k37,k38,k39,k3A,k3B,k3C,k3D, \
48 k49,k4A,k4B,k4C,k4D, \
49 k57,k58, \
50 k59, \
51 k5C,k5B,k5A ) \
52 \
53 /* matrix positions */ \
54 { \
55 { k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k0A, k0B, k0C, k0D }, \
56 { k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k1A, k1B, k1C, k1D }, \
57 { k20, k21, k22, k23, k24, k25, KC_NO, KC_NO, k28, k29, k2A, k2B, k2C, k2D }, \
58 { k30, k31, k32, k33, k34, k35, k36, k37, k38, k39, k3A, k3B, k3C, k3D }, \
59 { k40, k41, k42, k43, k44, KC_NO, KC_NO, KC_NO, KC_NO, k49, k4A, k4B, k4C, k4D }, \
60 { KC_NO, k51, k52, k53, k54, k55, k56, k57, k58, k59, k5A, k5B, k5C, KC_NO } \
61 }
62
63#define LAYOUT_ergodox KEYMAP
64
65#endif
diff --git a/keyboards/ergodone/expander.c b/keyboards/ergodone/expander.c
new file mode 100644
index 000000000..0c8a2289c
--- /dev/null
+++ b/keyboards/ergodone/expander.c
@@ -0,0 +1,120 @@
1#include <stdbool.h>
2#include "action.h"
3#include "i2cmaster.h"
4#include "expander.h"
5#include "debug.h"
6
7static uint8_t expander_status = 0;
8static uint8_t expander_input = 0;
9
10void expander_config(void);
11uint8_t expander_write(uint8_t reg, uint8_t data);
12uint8_t expander_read(uint8_t reg, uint8_t *data);
13
14void expander_init(void)
15{
16 i2c_init();
17 expander_scan();
18}
19
20void expander_scan(void)
21{
22 dprintf("expander status: %d ... ", expander_status);
23 uint8_t ret = i2c_start(EXPANDER_ADDR | I2C_WRITE);
24 if (ret == 0) {
25 i2c_stop();
26 if (expander_status == 0) {
27 dprintf("attached\n");
28 expander_status = 1;
29 expander_config();
30 clear_keyboard();
31 }
32 }
33 else {
34 if (expander_status == 1) {
35 dprintf("detached\n");
36 expander_status = 0;
37 clear_keyboard();
38 }
39 }
40 dprintf("%d\n", expander_status);
41}
42
43void expander_read_cols(void)
44{
45 expander_read(EXPANDER_REG_GPIOA, &expander_input);
46}
47
48uint8_t expander_get_col(uint8_t col)
49{
50 if (col > 4) {
51 col++;
52 }
53 return expander_input & (1<<col) ? 1 : 0;
54}
55
56matrix_row_t expander_read_row(void)
57{
58 expander_read_cols();
59
60 /* make cols */
61 matrix_row_t cols = 0;
62 for (uint8_t col = 0; col < MATRIX_COLS; col++) {
63 if (expander_get_col(col)) {
64 cols |= (1UL << (MATRIX_COLS - 1 - col));
65 }
66 }
67
68 return cols;
69}
70
71void expander_unselect_rows(void)
72{
73 expander_write(EXPANDER_REG_IODIRB, 0xFF);
74}
75
76void expander_select_row(uint8_t row)
77{
78 expander_write(EXPANDER_REG_IODIRB, ~(1<<(row+1)));
79}
80
81void expander_config(void)
82{
83 expander_write(EXPANDER_REG_IPOLA, 0xFF);
84 expander_write(EXPANDER_REG_GPPUA, 0xFF);
85 expander_write(EXPANDER_REG_IODIRB, 0xFF);
86}
87
88uint8_t expander_write(uint8_t reg, uint8_t data)
89{
90 if (expander_status == 0) {
91 return 0;
92 }
93 uint8_t ret;
94 ret = i2c_start(EXPANDER_ADDR | I2C_WRITE);
95 if (ret) goto stop;
96 ret = i2c_write(reg);
97 if (ret) goto stop;
98 ret = i2c_write(data);
99 stop:
100 i2c_stop();
101 return ret;
102}
103
104uint8_t expander_read(uint8_t reg, uint8_t *data)
105{
106 if (expander_status == 0) {
107 return 0;
108 }
109 uint8_t ret;
110 ret = i2c_start(EXPANDER_ADDR | I2C_WRITE);
111 if (ret) goto stop;
112 ret = i2c_write(reg);
113 if (ret) goto stop;
114 ret = i2c_rep_start(EXPANDER_ADDR | I2C_READ);
115 if (ret) goto stop;
116 *data = i2c_readNak();
117 stop:
118 i2c_stop();
119 return ret;
120}
diff --git a/keyboards/ergodone/expander.h b/keyboards/ergodone/expander.h
new file mode 100644
index 000000000..8676fed69
--- /dev/null
+++ b/keyboards/ergodone/expander.h
@@ -0,0 +1,48 @@
1#ifndef EXPANDER_H
2#define EXPANDER_H
3
4#include <stdint.h>
5#include "matrix.h"
6
7#define MCP23017
8#define MCP23017_A0 0
9#define MCP23017_A1 0
10#define MCP23017_A2 0
11
12#ifdef MCP23017
13#define EXPANDER_ADDR ((0x20|(MCP23017_A0<<0)|(MCP23017_A1<<1)|(MCP23017_A2<<2)) << 1)
14enum EXPANDER_REG_BANK0 {
15 EXPANDER_REG_IODIRA = 0,
16 EXPANDER_REG_IODIRB,
17 EXPANDER_REG_IPOLA,
18 EXPANDER_REG_IPOLB,
19 EXPANDER_REG_GPINTENA,
20 EXPANDER_REG_GPINTENB,
21 EXPANDER_REG_DEFVALA,
22 EXPANDER_REG_DEFVALB,
23 EXPANDER_REG_INTCONA,
24 EXPANDER_REG_INTCONB,
25 EXPANDER_REG_IOCONA,
26 EXPANDER_REG_IOCONB,
27 EXPANDER_REG_GPPUA,
28 EXPANDER_REG_GPPUB,
29 EXPANDER_REG_INTFA,
30 EXPANDER_REG_INTFB,
31 EXPANDER_REG_INTCAPA,
32 EXPANDER_REG_INTCAPB,
33 EXPANDER_REG_GPIOA,
34 EXPANDER_REG_GPIOB,
35 EXPANDER_REG_OLATA,
36 EXPANDER_REG_OLATB
37};
38#endif
39
40void expander_init(void);
41void expander_scan(void);
42void expander_read_cols(void);
43uint8_t expander_get_col(uint8_t col);
44matrix_row_t expander_read_row(void);
45void expander_unselect_rows(void);
46void expander_select_row(uint8_t row);
47
48#endif
diff --git a/keyboards/ergodone/i2cmaster.h b/keyboards/ergodone/i2cmaster.h
new file mode 100644
index 000000000..3917b9e6c
--- /dev/null
+++ b/keyboards/ergodone/i2cmaster.h
@@ -0,0 +1,178 @@
1#ifndef _I2CMASTER_H
2#define _I2CMASTER_H 1
3/*************************************************************************
4* Title: C include file for the I2C master interface
5* (i2cmaster.S or twimaster.c)
6* Author: Peter Fleury <pfleury@gmx.ch> http://jump.to/fleury
7* File: $Id: i2cmaster.h,v 1.10 2005/03/06 22:39:57 Peter Exp $
8* Software: AVR-GCC 3.4.3 / avr-libc 1.2.3
9* Target: any AVR device
10* Usage: see Doxygen manual
11**************************************************************************/
12
13#ifdef DOXYGEN
14/**
15 @defgroup pfleury_ic2master I2C Master library
16 @code #include <i2cmaster.h> @endcode
17
18 @brief I2C (TWI) Master Software Library
19
20 Basic routines for communicating with I2C slave devices. This single master
21 implementation is limited to one bus master on the I2C bus.
22
23 This I2c library is implemented as a compact assembler software implementation of the I2C protocol
24 which runs on any AVR (i2cmaster.S) and as a TWI hardware interface for all AVR with built-in TWI hardware (twimaster.c).
25 Since the API for these two implementations is exactly the same, an application can be linked either against the
26 software I2C implementation or the hardware I2C implementation.
27
28 Use 4.7k pull-up resistor on the SDA and SCL pin.
29
30 Adapt the SCL and SDA port and pin definitions and eventually the delay routine in the module
31 i2cmaster.S to your target when using the software I2C implementation !
32
33 Adjust the CPU clock frequence F_CPU in twimaster.c or in the Makfile when using the TWI hardware implementaion.
34
35 @note
36 The module i2cmaster.S is based on the Atmel Application Note AVR300, corrected and adapted
37 to GNU assembler and AVR-GCC C call interface.
38 Replaced the incorrect quarter period delays found in AVR300 with
39 half period delays.
40
41 @author Peter Fleury pfleury@gmx.ch http://jump.to/fleury
42
43 @par API Usage Example
44 The following code shows typical usage of this library, see example test_i2cmaster.c
45
46 @code
47
48 #include <i2cmaster.h>
49
50
51 #define Dev24C02 0xA2 // device address of EEPROM 24C02, see datasheet
52
53 int main(void)
54 {
55 unsigned char ret;
56
57 i2c_init(); // initialize I2C library
58
59 // write 0x75 to EEPROM address 5 (Byte Write)
60 i2c_start_wait(Dev24C02+I2C_WRITE); // set device address and write mode
61 i2c_write(0x05); // write address = 5
62 i2c_write(0x75); // write value 0x75 to EEPROM
63 i2c_stop(); // set stop conditon = release bus
64
65
66 // read previously written value back from EEPROM address 5
67 i2c_start_wait(Dev24C02+I2C_WRITE); // set device address and write mode
68
69 i2c_write(0x05); // write address = 5
70 i2c_rep_start(Dev24C02+I2C_READ); // set device address and read mode
71
72 ret = i2c_readNak(); // read one byte from EEPROM
73 i2c_stop();
74
75 for(;;);
76 }
77 @endcode
78
79*/
80#endif /* DOXYGEN */
81
82/**@{*/
83
84#if (__GNUC__ * 100 + __GNUC_MINOR__) < 304
85#error "This library requires AVR-GCC 3.4 or later, update to newer AVR-GCC compiler !"
86#endif
87
88#include <avr/io.h>
89
90/** defines the data direction (reading from I2C device) in i2c_start(),i2c_rep_start() */
91#define I2C_READ 1
92
93/** defines the data direction (writing to I2C device) in i2c_start(),i2c_rep_start() */
94#define I2C_WRITE 0
95
96
97/**
98 @brief initialize the I2C master interace. Need to be called only once
99 @param void
100 @return none
101 */
102extern void i2c_init(void);
103
104
105/**
106 @brief Terminates the data transfer and releases the I2C bus
107 @param void
108 @return none
109 */
110extern void i2c_stop(void);
111
112
113/**
114 @brief Issues a start condition and sends address and transfer direction
115
116 @param addr address and transfer direction of I2C device
117 @retval 0 device accessible
118 @retval 1 failed to access device
119 */
120extern unsigned char i2c_start(unsigned char addr);
121
122
123/**
124 @brief Issues a repeated start condition and sends address and transfer direction
125
126 @param addr address and transfer direction of I2C device
127 @retval 0 device accessible
128 @retval 1 failed to access device
129 */
130extern unsigned char i2c_rep_start(unsigned char addr);
131
132
133/**
134 @brief Issues a start condition and sends address and transfer direction
135
136 If device is busy, use ack polling to wait until device ready
137 @param addr address and transfer direction of I2C device
138 @return none
139 */
140extern void i2c_start_wait(unsigned char addr);
141
142
143/**
144 @brief Send one byte to I2C device
145 @param data byte to be transfered
146 @retval 0 write successful
147 @retval 1 write failed
148 */
149extern unsigned char i2c_write(unsigned char data);
150
151
152/**
153 @brief read one byte from the I2C device, request more data from device
154 @return byte read from I2C device
155 */
156extern unsigned char i2c_readAck(void);
157
158/**
159 @brief read one byte from the I2C device, read is followed by a stop condition
160 @return byte read from I2C device
161 */
162extern unsigned char i2c_readNak(void);
163
164/**
165 @brief read one byte from the I2C device
166
167 Implemented as a macro, which calls either i2c_readAck or i2c_readNak
168
169 @param ack 1 send ack, request more data from device<br>
170 0 send nak, read is followed by a stop condition
171 @return byte read from I2C device
172 */
173extern unsigned char i2c_read(unsigned char ack);
174#define i2c_read(ack) (ack) ? i2c_readAck() : i2c_readNak();
175
176
177/**@}*/
178#endif
diff --git a/keyboards/ergodone/keymaps/default/keymap.c b/keyboards/ergodone/keymaps/default/keymap.c
new file mode 100644
index 000000000..cbc180d6a
--- /dev/null
+++ b/keyboards/ergodone/keymaps/default/keymap.c
@@ -0,0 +1,223 @@
1#include QMK_KEYBOARD_H
2#include "debug.h"
3#include "action_layer.h"
4#include "version.h"
5
6#define BASE 0 // default layer
7#define SYMB 1 // symbols
8#define MDIA 2 // media keys
9
10enum custom_keycodes {
11 PLACEHOLDER = SAFE_RANGE, // can always be here
12 EPRM,
13 VRSN,
14 RGB_SLD
15};
16
17const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
18/* Keymap 0: Basic layer
19 *
20 * ,--------------------------------------------------. ,--------------------------------------------------.
21 * | = | 1 | 2 | 3 | 4 | 5 | LEFT | | RIGHT| 6 | 7 | 8 | 9 | 0 | - |
22 * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
23 * | Del | Q | W | E | R | T | L1 | | L1 | Y | U | I | O | P | \ |
24 * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
25 * | BkSp | A | S | D | F | G |------| |------| H | J | K | L |; / L2|' / Cmd |
26 * |--------+------+------+------+------+------| Hyper| | Meh |------+------+------+------+------+--------|
27 * | LShift |Z/Ctrl| X | C | V | B | | | | N | M | , | . |//Ctrl| RShift |
28 * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
29 * |Grv/L1| '" |AltShf| Left | Right| | Up | Down | [ | ] | ~L1 |
30 * `----------------------------------' `----------------------------------'
31 * ,-------------. ,-------------.
32 * | App | LGui | | Alt |Ctrl/Esc|
33 * ,------|------|------| |------+--------+------.
34 * | | | Home | | PgUp | | |
35 * | Space|Backsp|------| |------| Tab |Enter |
36 * | |ace | End | | PgDn | | |
37 * `--------------------' `----------------------'
38 */
39// If it accepts an argument (i.e, is a function), it doesn't need KC_.
40// Otherwise, it needs KC_*
41[BASE] = LAYOUT_ergodox( // layer 0 : default
42 // left hand
43 KC_EQL, KC_1, KC_2, KC_3, KC_4, KC_5, KC_LEFT,
44 KC_DELT, KC_Q, KC_W, KC_E, KC_R, KC_T, TG(SYMB),
45 KC_BSPC, KC_A, KC_S, KC_D, KC_F, KC_G,
46 KC_LSFT, CTL_T(KC_Z), KC_X, KC_C, KC_V, KC_B, ALL_T(KC_NO),
47 LT(SYMB,KC_GRV),KC_QUOT, LALT(KC_LSFT), KC_LEFT,KC_RGHT,
48 ALT_T(KC_APP), KC_LGUI,
49 KC_HOME,
50 KC_SPC,KC_BSPC,KC_END,
51 // right hand
52 KC_RGHT, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS,
53 TG(SYMB), KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSLS,
54 KC_H, KC_J, KC_K, KC_L, LT(MDIA, KC_SCLN),GUI_T(KC_QUOT),
55 MEH_T(KC_NO),KC_N, KC_M, KC_COMM,KC_DOT, CTL_T(KC_SLSH), KC_RSFT,
56 KC_UP, KC_DOWN,KC_LBRC,KC_RBRC, KC_FN1,
57 KC_LALT, CTL_T(KC_ESC),
58 KC_PGUP,
59 KC_PGDN,KC_TAB, KC_ENT
60 ),
61/* Keymap 1: Symbol Layer
62 *
63 * ,---------------------------------------------------. ,--------------------------------------------------.
64 * |Version | F1 | F2 | F3 | F4 | F5 | | | | F6 | F7 | F8 | F9 | F10 | F11 |
65 * |---------+------+------+------+------+------+------| |------+------+------+------+------+------+--------|
66 * | | ! | @ | { | } | | | | | | Up | 7 | 8 | 9 | * | F12 |
67 * |---------+------+------+------+------+------| | | |------+------+------+------+------+--------|
68 * | | # | $ | ( | ) | ` |------| |------| Down | 4 | 5 | 6 | + | |
69 * |---------+------+------+------+------+------| | | |------+------+------+------+------+--------|
70 * | | % | ^ | [ | ] | ~ | | | | & | 1 | 2 | 3 | \ | |
71 * `---------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
72 * | EPRM | | | | | | | . | 0 | = | |
73 * `-----------------------------------' `----------------------------------'
74 * ,-------------. ,-------------.
75 * |Animat| | |Toggle|Solid |
76 * ,------|------|------| |------+------+------.
77 * |Bright|Bright| | | |Hue- |Hue+ |
78 * |ness- |ness+ |------| |------| | |
79 * | | | | | | | |
80 * `--------------------' `--------------------'
81 */
82// SYMBOLS
83[SYMB] = LAYOUT_ergodox(
84 // left hand
85 VRSN, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_TRNS,
86 KC_TRNS,KC_EXLM,KC_AT, KC_LCBR,KC_RCBR,KC_PIPE,KC_TRNS,
87 KC_TRNS,KC_HASH,KC_DLR, KC_LPRN,KC_RPRN,KC_GRV,
88 KC_TRNS,KC_PERC,KC_CIRC,KC_LBRC,KC_RBRC,KC_TILD,KC_TRNS,
89 EPRM,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,
90 RGB_MOD,KC_TRNS,
91 KC_TRNS,
92 RGB_VAD,RGB_VAI,KC_TRNS,
93 // right hand
94 KC_TRNS, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
95 KC_TRNS, KC_UP, KC_7, KC_8, KC_9, KC_ASTR, KC_F12,
96 KC_DOWN, KC_4, KC_5, KC_6, KC_PLUS, KC_TRNS,
97 KC_TRNS, KC_AMPR, KC_1, KC_2, KC_3, KC_BSLS, KC_TRNS,
98 KC_TRNS,KC_DOT, KC_0, KC_EQL, KC_TRNS,
99 RGB_TOG, RGB_SLD,
100 KC_TRNS,
101 KC_TRNS, RGB_HUD, RGB_HUI
102),
103/* Keymap 2: Media and mouse keys
104 *
105 * ,--------------------------------------------------. ,--------------------------------------------------.
106 * | | | | | | | | | | | | | | | |
107 * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
108 * | | | | MsUp | | | | | | | | | | | |
109 * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
110 * | | |MsLeft|MsDown|MsRght| |------| |------| | | | | | Play |
111 * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
112 * | | | | | | | | | | | | Prev | Next | | |
113 * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
114 * | | | | Lclk | Rclk | |VolUp |VolDn | Mute | | |
115 * `----------------------------------' `----------------------------------'
116 * ,-------------. ,-------------.
117 * | | | | | |
118 * ,------|------|------| |------+------+------.
119 * | | | | | | |Brwser|
120 * | | |------| |------| |Back |
121 * | | | | | | | |
122 * `--------------------' `--------------------'
123 */
124// MEDIA AND MOUSE
125[MDIA] = LAYOUT_ergodox(
126 KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
127 KC_TRNS, KC_TRNS, KC_TRNS, KC_MS_U, KC_TRNS, KC_TRNS, KC_TRNS,
128 KC_TRNS, KC_TRNS, KC_MS_L, KC_MS_D, KC_MS_R, KC_TRNS,
129 KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
130 KC_TRNS, KC_TRNS, KC_TRNS, KC_BTN1, KC_BTN2,
131 KC_TRNS, KC_TRNS,
132 KC_TRNS,
133 KC_TRNS, KC_TRNS, KC_TRNS,
134 // right hand
135 KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
136 KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
137 KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MPLY,
138 KC_TRNS, KC_TRNS, KC_TRNS, KC_MPRV, KC_MNXT, KC_TRNS, KC_TRNS,
139 KC_VOLU, KC_VOLD, KC_MUTE, KC_TRNS, KC_TRNS,
140 KC_TRNS, KC_TRNS,
141 KC_TRNS,
142 KC_TRNS, KC_TRNS, KC_WBAK
143),
144};
145
146const uint16_t PROGMEM fn_actions[] = {
147 [1] = ACTION_LAYER_TAP_TOGGLE(SYMB) // FN1 - Momentary Layer 1 (Symbols)
148};
149
150const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
151{
152 // MACRODOWN only works in this function
153 switch(id) {
154 case 0:
155 if (record->event.pressed) {
156 SEND_STRING (QMK_KEYBOARD "/" QMK_KEYMAP " @ " QMK_VERSION);
157 }
158 break;
159 case 1:
160 if (record->event.pressed) { // For resetting EEPROM
161 eeconfig_init();
162 }
163 break;
164 }
165 return MACRO_NONE;
166};
167
168bool process_record_user(uint16_t keycode, keyrecord_t *record) {
169 switch (keycode) {
170 // dynamically generate these.
171 case EPRM:
172 if (record->event.pressed) {
173 eeconfig_init();
174 }
175 return false;
176 break;
177 case VRSN:
178 if (record->event.pressed) {
179 SEND_STRING (QMK_KEYBOARD "/" QMK_KEYMAP " @ " QMK_VERSION);
180 }
181 return false;
182 break;
183 case RGB_SLD:
184 if (record->event.pressed) {
185 #ifdef RGBLIGHT_ENABLE
186 rgblight_mode(1);
187 #endif
188 }
189 return false;
190 break;
191 }
192 return true;
193}
194
195// Runs just one time when the keyboard initializes.
196void matrix_init_user(void) {
197
198};
199
200
201// Runs constantly in the background, in a loop.
202void matrix_scan_user(void) {
203
204 uint8_t layer = biton32(layer_state);
205
206 ergodox_board_led_off();
207 ergodox_right_led_1_off();
208 ergodox_right_led_2_off();
209 ergodox_right_led_3_off();
210 switch (layer) {
211 // TODO: Make this relevant to the ErgoDox EZ.
212 case 1:
213 ergodox_right_led_1_on();
214 break;
215 case 2:
216 ergodox_right_led_2_on();
217 break;
218 default:
219 // none
220 break;
221 }
222
223};
diff --git a/keyboards/ergodone/keymaps/default/readme.md b/keyboards/ergodone/keymaps/default/readme.md
new file mode 100644
index 000000000..1150a4f70
--- /dev/null
+++ b/keyboards/ergodone/keymaps/default/readme.md
@@ -0,0 +1,15 @@
1# ErgoDox EZ Default Configuration
2
3## Changelog
4
5* Dec 2016:
6 * Added LED keys
7 * Refreshed layout graphic, comes from http://configure.ergodox-ez.com now.
8* Sep 22, 2016:
9 * Created a new key in layer 1 (bottom-corner key) that resets the EEPROM.
10* Feb 2, 2016 (V1.1):
11 * Made the right-hand quote key double as Cmd/Win on hold. So you get ' when you tap it, " when you tap it with Shift, and Cmd or Win when you hold it. You can then use it as a modifier, or just press and hold it for a moment (and then let go) to send a single Cmd or Win keystroke (handy for opening the Start menu on Windows).
12
13This is what we ship with out of the factory. :) The image says it all:
14
15![Default](https://i.imgur.com/Be53jH7.png) \ No newline at end of file
diff --git a/keyboards/ergodone/matrix.c b/keyboards/ergodone/matrix.c
new file mode 100644
index 000000000..2eb8f24ba
--- /dev/null
+++ b/keyboards/ergodone/matrix.c
@@ -0,0 +1,295 @@
1#include <stdint.h>
2#include <stdbool.h>
3#include <avr/io.h>
4#include "wait.h"
5#include "action_layer.h"
6#include "print.h"
7#include "debug.h"
8#include "util.h"
9#include "matrix.h"
10#include "ergodone.h"
11#include "expander.h"
12#ifdef DEBUG_MATRIX_SCAN_RATE
13#include "timer.h"
14#endif
15
16/*
17 * This constant define not debouncing time in msecs, but amount of matrix
18 * scan loops which should be made to get stable debounced results.
19 *
20 * On Ergodox matrix scan rate is relatively low, because of slow I2C.
21 * Now it's only 317 scans/second, or about 3.15 msec/scan.
22 * According to Cherry specs, debouncing time is 5 msec.
23 *
24 * And so, there is no sense to have DEBOUNCE higher than 2.
25 */
26
27#ifndef DEBOUNCE
28# define DEBOUNCE 5
29#endif
30
31/* matrix state(1:on, 0:off) */
32static matrix_row_t matrix[MATRIX_ROWS];
33
34// Debouncing: store for each key the number of scans until it's eligible to
35// change. When scanning the matrix, ignore any changes in keys that have
36// already changed in the last DEBOUNCE scans.
37static uint8_t debounce_matrix[MATRIX_ROWS * MATRIX_COLS];
38
39static matrix_row_t read_cols(uint8_t row);
40static void init_cols(void);
41static void unselect_rows(void);
42static void select_row(uint8_t row);
43
44#ifdef DEBUG_MATRIX_SCAN_RATE
45uint32_t matrix_timer;
46uint32_t matrix_scan_count;
47#endif
48
49
50__attribute__ ((weak))
51void matrix_init_user(void) {}
52
53__attribute__ ((weak))
54void matrix_scan_user(void) {}
55
56__attribute__ ((weak))
57void matrix_init_kb(void) {
58 matrix_init_user();
59}
60
61__attribute__ ((weak))
62void matrix_scan_kb(void) {
63 matrix_scan_user();
64}
65
66inline
67uint8_t matrix_rows(void)
68{
69 return MATRIX_ROWS;
70}
71
72inline
73uint8_t matrix_cols(void)
74{
75 return MATRIX_COLS;
76}
77
78void matrix_init(void)
79{
80 // disable JTAG
81 MCUCR = (1<<JTD);
82 MCUCR = (1<<JTD);
83
84 unselect_rows();
85 init_cols();
86
87 // initialize matrix state: all keys off
88 for (uint8_t i=0; i < MATRIX_ROWS; i++) {
89 matrix[i] = 0;
90 for (uint8_t j=0; j < MATRIX_COLS; ++j) {
91 debounce_matrix[i * MATRIX_COLS + j] = 0;
92 }
93 }
94
95#ifdef DEBUG_MATRIX_SCAN_RATE
96 matrix_timer = timer_read32();
97 matrix_scan_count = 0;
98#endif
99
100 matrix_init_quantum();
101
102}
103
104void matrix_power_up(void) {
105 unselect_rows();
106 init_cols();
107
108 // initialize matrix state: all keys off
109 for (uint8_t i=0; i < MATRIX_ROWS; i++) {
110 matrix[i] = 0;
111 }
112
113#ifdef DEBUG_MATRIX_SCAN_RATE
114 matrix_timer = timer_read32();
115 matrix_scan_count = 0;
116#endif
117}
118
119// Returns a matrix_row_t whose bits are set if the corresponding key should be
120// eligible to change in this scan.
121matrix_row_t debounce_mask(uint8_t row) {
122 matrix_row_t result = 0;
123 for (uint8_t j=0; j < MATRIX_COLS; ++j) {
124 if (debounce_matrix[row * MATRIX_COLS + j]) {
125 --debounce_matrix[row * MATRIX_COLS + j];
126 } else {
127 result |= (1 << j);
128 }
129 }
130 return result;
131}
132
133// Report changed keys in the given row. Resets the debounce countdowns
134// corresponding to each set bit in 'change' to DEBOUNCE.
135void debounce_report(matrix_row_t change, uint8_t row) {
136 for (uint8_t i = 0; i < MATRIX_COLS; ++i) {
137 if (change & (1 << i)) {
138 debounce_matrix[row * MATRIX_COLS + i] = DEBOUNCE;
139 }
140 }
141}
142
143uint8_t matrix_scan(void)
144{
145 expander_scan();
146
147#ifdef DEBUG_MATRIX_SCAN_RATE
148 matrix_scan_count++;
149
150 uint32_t timer_now = timer_read32();
151 if (TIMER_DIFF_32(timer_now, matrix_timer)>1000) {
152 print("matrix scan frequency: ");
153 pdec(matrix_scan_count);
154 print("\n");
155 matrix_print();
156
157 matrix_timer = timer_now;
158 matrix_scan_count = 0;
159 }
160#endif
161
162 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
163 select_row(i);
164 wait_us(30); // without this wait read unstable value.
165 matrix_row_t mask = debounce_mask(i);
166 matrix_row_t cols = (read_cols(i) & mask) | (matrix[i] & ~mask);
167 debounce_report(cols ^ matrix[i], i);
168 matrix[i] = cols;
169
170 unselect_rows();
171 }
172
173 matrix_scan_quantum();
174
175 return 1;
176}
177
178inline
179bool matrix_is_on(uint8_t row, uint8_t col)
180{
181 return (matrix[row] & ((matrix_row_t)1<<col));
182}
183
184inline
185matrix_row_t matrix_get_row(uint8_t row)
186{
187 return matrix[row];
188}
189
190void matrix_print(void)
191{
192 print("\nr/c 0123456789ABCDEF\n");
193 for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
194 phex(row); print(": ");
195 pbin_reverse16(matrix_get_row(row));
196 print("\n");
197 }
198}
199
200uint8_t matrix_key_count(void)
201{
202 uint8_t count = 0;
203 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
204 count += bitpop16(matrix[i]);
205 }
206 return count;
207}
208
209/* Column pin configuration
210 *
211 * Pro Micro: 6 5 4 3 2 1 0
212 * PD3 PD2 PD4 PC6 PD7 PE6 PB4
213 *
214 * Expander: 13 12 11 10 9 8 7
215 */
216static void init_cols(void)
217{
218 // Pro Micro
219 DDRE &= ~(1<<PE6);
220 PORTE |= (1<<PE6);
221 DDRD &= ~(1<<PD2 | 1<<PD3 | 1<<PD4 | 1<<PD7);
222 PORTD |= (1<<PD2 | 1<<PD3 | 1<<PD4 | 1<<PD7);
223 DDRC &= ~(1<<PC6);
224 PORTC |= (1<<PC6);
225 DDRB &= ~(1<<PB4);
226 PORTB |= (1<<PB4);
227
228 // MCP23017
229 expander_init();
230}
231
232static matrix_row_t read_cols(uint8_t row)
233{
234 return expander_read_row() |
235 (PIND&(1<<PD3) ? 0 : (1<<6)) |
236 (PIND&(1<<PD2) ? 0 : (1<<5)) |
237 (PIND&(1<<PD4) ? 0 : (1<<4)) |
238 (PINC&(1<<PC6) ? 0 : (1<<3)) |
239 (PIND&(1<<PD7) ? 0 : (1<<2)) |
240 (PINE&(1<<PE6) ? 0 : (1<<1)) |
241 (PINB&(1<<PB4) ? 0 : (1<<0)) ;
242}
243
244/* Row pin configuration
245 *
246 * Pro Micro: 0 1 2 3 4 5
247 * F4 F5 F6 F7 B1 B2
248 *
249 * Expander: 0 1 2 3 4 5
250 */
251static void unselect_rows(void)
252{
253 // Pro Micro
254 DDRF &= ~(1<<PF4 | 1<<PF5 | 1<<PF6 | 1<<PF7);
255 PORTF &= ~(1<<PF4 | 1<<PF5 | 1<<PF6 | 1<<PF7);
256 DDRB &= ~(1<<PB1 | 1<<PB2);
257 PORTB &= ~(1<<PB1 | 1<<PB2);
258
259 // Expander
260 expander_unselect_rows();
261}
262
263static void select_row(uint8_t row)
264{
265 // Pro Micro
266 switch (row) {
267 case 0:
268 DDRF |= (1<<PF4);
269 PORTF &= ~(1<<PF4);
270 break;
271 case 1:
272 DDRF |= (1<<PF5);
273 PORTF &= ~(1<<PF5);
274 break;
275 case 2:
276 DDRF |= (1<<PF6);
277 PORTF &= ~(1<<PF6);
278 break;
279 case 3:
280 DDRF |= (1<<PF7);
281 PORTF &= ~(1<<PF7);
282 break;
283 case 4:
284 DDRB |= (1<<PB1);
285 PORTB &= ~(1<<PB1);
286 break;
287 case 5:
288 DDRB |= (1<<PB2);
289 PORTB &= ~(1<<PB2);
290 break;
291 }
292
293 expander_select_row(row);
294}
295
diff --git a/keyboards/ergodone/readme.md b/keyboards/ergodone/readme.md
new file mode 100644
index 000000000..789819e67
--- /dev/null
+++ b/keyboards/ergodone/readme.md
@@ -0,0 +1,26 @@
1ErgoDone
2===
3
4![ErgoDone](https://i.imgur.com/QERsQGQ.jpg)
5
6ErgoDone is a modified ErgoDox with pre-soldered components made by K.T.E.C. It has different wiring and uses a Pro Micro instead of Teensy.
7
8 - Keyboard Maintainer: [Yu He](http://github.com/yuhe00)
9 - Hardware Supported:
10 - ErgoDone ver. 1.3 (tested)
11 - Hardware Availability: [KBDFans](https://kbdfans.myshopify.com/collections/pcb/products/ergodone-keyboard-pcb-1pcs-free-shipping?variant=37178300237)
12
13Make example for this keyboard (after setting up your build environment):
14
15 make ergodox-ergodone-default
16
17See [build environment setup](https://docs.qmk.fm/build_environment_setup.html) then the [make instructions](https://docs.qmk.fm/make_instructions.html) for more information.
18
19# Flashing the keyboard
20
21The ErgoDone uses an HID bootloader rather than the Teensy one, and requires a different way of flashing the firmware.
22
231. While plugging in the USB cable, hold the two right-most keys on the left half of the ErgoDone to enter FLASH mode.
242. Use the `hid_bootloader_cli` utlity from [TKG Toolkit](https://github.com/kairyu/tkg-toolkit):
25
26 hid_bootloader_cli -mmcu=atmega32u4 ergodox_ergodone_default
diff --git a/keyboards/ergodone/rules.mk b/keyboards/ergodone/rules.mk
new file mode 100644
index 000000000..bbad0ae73
--- /dev/null
+++ b/keyboards/ergodone/rules.mk
@@ -0,0 +1,95 @@
1#----------------------------------------------------------------------------
2# On command line:
3#
4# make = Make software.
5#
6# make clean = Clean out built project files.
7#
8# That's pretty much all you need. To compile, always go make clean,
9# followed by make.
10#
11# For advanced users only:
12# make teensy = Download the hex file to the device, using teensy_loader_cli.
13# (must have teensy_loader_cli installed).
14#
15#----------------------------------------------------------------------------
16
17# # project specific files
18SRC = \
19 twimaster.c \
20 matrix.c \
21 expander.c \
22
23# MCU name
24MCU = atmega32u4
25
26# Processor frequency.
27# This will define a symbol, F_CPU, in all source code files equal to the
28# processor frequency in Hz. You can then use this symbol in your source code to
29# calculate timings. Do NOT tack on a 'UL' at the end, this will be done
30# automatically to create a 32-bit value in your source code.
31#
32# This will be an integer division of F_USB below, as it is sourced by
33# F_USB after it has run through any CPU prescalers. Note that this value
34# does not *change* the processor frequency - it should merely be updated to
35# reflect the processor speed set externally so that the code can use accurate
36# software delays.
37F_CPU = 16000000
38
39#
40# LUFA specific
41#
42# Target architecture (see library "Board Types" documentation).
43ARCH = AVR8
44
45# Input clock frequency.
46# This will define a symbol, F_USB, in all source code files equal to the
47# input clock frequency (before any prescaling is performed) in Hz. This value may
48# differ from F_CPU if prescaling is used on the latter, and is required as the
49# raw input clock is fed directly to the PLL sections of the AVR for high speed
50# clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL'
51# at the end, this will be done automatically to create a 32-bit value in your
52# source code.
53#
54# If no clock division is performed on the input clock inside the AVR (via the
55# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU.
56F_USB = $(F_CPU)
57
58# Interrupt driven control endpoint task(+60)
59OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
60
61
62# Boot Section Size in *bytes*
63# Teensy halfKay 512
64# Teensy++ halfKay 1024
65# Atmel DFU loader 4096
66# LUFA bootloader 4096
67# USBaspLoader 2048
68OPT_DEFS += -DBOOTLOADER_SIZE=4096
69
70# Build Options
71# comment out to disable the options.
72#
73CUSTOM_MATRIX = yes # Custom matrix file for the ErgoDone
74UNICODE_ENABLE = yes # Unicode
75BOOTMAGIC_ENABLE = yes # Virtual DIP switch configuration(+1000)
76MOUSEKEY_ENABLE = yes # Mouse keys(+4700)
77EXTRAKEY_ENABLE = yes # Audio control and System control(+450)
78CONSOLE_ENABLE = no # Console for debug(+400)
79COMMAND_ENABLE = no # Commands for debug and configuration
80SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
81NKRO_ENABLE = yes # USB Nkey Rollover - not yet supported in LUFA
82USB_6KRO_ENABLE = no # USB 6key Rollover
83BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality
84KEYMAP_IN_EEPROM_ENABLE = no # External keymap in eeprom
85KEYMAP_SECTION_ENABLE = no # Fixed address keymap for keymap editor
86SOFTPWM_LED_ENABLE = no # Enable SoftPWM to drive backlight
87FADING_LED_ENABLE = no # Enable fading backlight
88BREATHING_LED_ENABLE = no # Enable breathing backlight
89LEDMAP_ENABLE = no # Enable LED mapping
90LEDMAP_IN_EEPROM_ENABLE = no # Read LED mapping from eeprom
91ONEHAND_ENABLE = no # Disable Onehand
92RGBLIGHT_ENABLE = no
93MIDI_ENABLE = no
94
95LAYOUTS = ergodox ergodox_80 \ No newline at end of file
diff --git a/keyboards/ergodone/twimaster.c b/keyboards/ergodone/twimaster.c
new file mode 100644
index 000000000..f91c08e6e
--- /dev/null
+++ b/keyboards/ergodone/twimaster.c
@@ -0,0 +1,208 @@
1/*************************************************************************
2* Title: I2C master library using hardware TWI interface
3* Author: Peter Fleury <pfleury@gmx.ch> http://jump.to/fleury
4* File: $Id: twimaster.c,v 1.3 2005/07/02 11:14:21 Peter Exp $
5* Software: AVR-GCC 3.4.3 / avr-libc 1.2.3
6* Target: any AVR device with hardware TWI
7* Usage: API compatible with I2C Software Library i2cmaster.h
8**************************************************************************/
9#include <inttypes.h>
10#include <compat/twi.h>
11
12#include <i2cmaster.h>
13
14
15/* define CPU frequency in Mhz here if not defined in Makefile */
16#ifndef F_CPU
17#define F_CPU 16000000UL
18#endif
19
20/* I2C clock in Hz */
21#define SCL_CLOCK 400000L
22
23
24/*************************************************************************
25 Initialization of the I2C bus interface. Need to be called only once
26*************************************************************************/
27void i2c_init(void)
28{
29 /* initialize TWI clock
30 * minimal values in Bit Rate Register (TWBR) and minimal Prescaler
31 * bits in the TWI Status Register should give us maximal possible
32 * I2C bus speed - about 444 kHz
33 *
34 * for more details, see 20.5.2 in ATmega16/32 secification
35 */
36
37 TWSR = 0; /* no prescaler */
38 TWBR = 10; /* must be >= 10 for stable operation */
39
40}/* i2c_init */
41
42
43/*************************************************************************
44 Issues a start condition and sends address and transfer direction.
45 return 0 = device accessible, 1= failed to access device
46*************************************************************************/
47unsigned char i2c_start(unsigned char address)
48{
49 uint8_t twst;
50
51 // send START condition
52 TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
53
54 // wait until transmission completed
55 while(!(TWCR & (1<<TWINT)));
56
57 // check value of TWI Status Register. Mask prescaler bits.
58 twst = TW_STATUS & 0xF8;
59 if ( (twst != TW_START) && (twst != TW_REP_START)) return 1;
60
61 // send device address
62 TWDR = address;
63 TWCR = (1<<TWINT) | (1<<TWEN);
64
65 // wail until transmission completed and ACK/NACK has been received
66 while(!(TWCR & (1<<TWINT)));
67
68 // check value of TWI Status Register. Mask prescaler bits.
69 twst = TW_STATUS & 0xF8;
70 if ( (twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK) ) return 1;
71
72 return 0;
73
74}/* i2c_start */
75
76
77/*************************************************************************
78 Issues a start condition and sends address and transfer direction.
79 If device is busy, use ack polling to wait until device is ready
80
81 Input: address and transfer direction of I2C device
82*************************************************************************/
83void i2c_start_wait(unsigned char address)
84{
85 uint8_t twst;
86
87
88 while ( 1 )
89 {
90 // send START condition
91 TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
92
93 // wait until transmission completed
94 while(!(TWCR & (1<<TWINT)));
95
96 // check value of TWI Status Register. Mask prescaler bits.
97 twst = TW_STATUS & 0xF8;
98 if ( (twst != TW_START) && (twst != TW_REP_START)) continue;
99
100 // send device address
101 TWDR = address;
102 TWCR = (1<<TWINT) | (1<<TWEN);
103
104 // wail until transmission completed
105 while(!(TWCR & (1<<TWINT)));
106
107 // check value of TWI Status Register. Mask prescaler bits.
108 twst = TW_STATUS & 0xF8;
109 if ( (twst == TW_MT_SLA_NACK )||(twst ==TW_MR_DATA_NACK) )
110 {
111 /* device busy, send stop condition to terminate write operation */
112 TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
113
114 // wait until stop condition is executed and bus released
115 while(TWCR & (1<<TWSTO));
116
117 continue;
118 }
119 //if( twst != TW_MT_SLA_ACK) return 1;
120 break;
121 }
122
123}/* i2c_start_wait */
124
125
126/*************************************************************************
127 Issues a repeated start condition and sends address and transfer direction
128
129 Input: address and transfer direction of I2C device
130
131 Return: 0 device accessible
132 1 failed to access device
133*************************************************************************/
134unsigned char i2c_rep_start(unsigned char address)
135{
136 return i2c_start( address );
137
138}/* i2c_rep_start */
139
140
141/*************************************************************************
142 Terminates the data transfer and releases the I2C bus
143*************************************************************************/
144void i2c_stop(void)
145{
146 /* send stop condition */
147 TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
148
149 // wait until stop condition is executed and bus released
150 while(TWCR & (1<<TWSTO));
151
152}/* i2c_stop */
153
154
155/*************************************************************************
156 Send one byte to I2C device
157
158 Input: byte to be transfered
159 Return: 0 write successful
160 1 write failed
161*************************************************************************/
162unsigned char i2c_write( unsigned char data )
163{
164 uint8_t twst;
165
166 // send data to the previously addressed device
167 TWDR = data;
168 TWCR = (1<<TWINT) | (1<<TWEN);
169
170 // wait until transmission completed
171 while(!(TWCR & (1<<TWINT)));
172
173 // check value of TWI Status Register. Mask prescaler bits
174 twst = TW_STATUS & 0xF8;
175 if( twst != TW_MT_DATA_ACK) return 1;
176 return 0;
177
178}/* i2c_write */
179
180
181/*************************************************************************
182 Read one byte from the I2C device, request more data from device
183
184 Return: byte read from I2C device
185*************************************************************************/
186unsigned char i2c_readAck(void)
187{
188 TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA);
189 while(!(TWCR & (1<<TWINT)));
190
191 return TWDR;
192
193}/* i2c_readAck */
194
195
196/*************************************************************************
197 Read one byte from the I2C device, read is followed by a stop condition
198
199 Return: byte read from I2C device
200*************************************************************************/
201unsigned char i2c_readNak(void)
202{
203 TWCR = (1<<TWINT) | (1<<TWEN);
204 while(!(TWCR & (1<<TWINT)));
205
206 return TWDR;
207
208}/* i2c_readNak */