aboutsummaryrefslogtreecommitdiff
path: root/keyboards
diff options
context:
space:
mode:
authorMikkel Jeppesen <2756925+Duckle29@users.noreply.github.com>2018-05-09 18:14:30 +0200
committerDrashna Jaelre <drashna@live.com>2018-05-09 09:14:30 -0700
commit00596d55e34c003d55a530366bedfb2ea467bedc (patch)
tree95e02d77026987b9c34da8b7740f6d8dea5ba840 /keyboards
parent749916e6e233f66b554925f120c29e2ce353e90e (diff)
downloadqmk_firmware-00596d55e34c003d55a530366bedfb2ea467bedc.tar.gz
qmk_firmware-00596d55e34c003d55a530366bedfb2ea467bedc.zip
Added propper support for Lets split vitamins (#2559)
* Added support for the upcomming Lets_split vitamins included * Updated readme * Corrected header of readme * Enabled RGB * Broke everything * broke some more shit * Revert "broke some more shit" This reverts commit 6ad68e6269cc0d04c16564ce9598dfd3db1e23c1. * Revert "Broke everything" This reverts commit feeee4e40db15a726f2292b6a9406ef45c1e54a7. * Fixed USB detection, and RGB on slave * started modifying readme, to use msys2 * Added support for the upcomming Lets_split vitamins included * Updated readme * Corrected header of readme * Enabled RGB * Broke everything * broke some more shit * Revert "broke some more shit" This reverts commit 6ad68e6269cc0d04c16564ce9598dfd3db1e23c1. * Revert "Broke everything" This reverts commit feeee4e40db15a726f2292b6a9406ef45c1e54a7. * Fixed USB detection, and RGB on slave * started modifying readme, to use msys2 * Updated readme to reflect use of msys2 Added avrdude to msys path * added avrdude option to msys installer * Removed extra installation of avrdude * Renamed to vitamins_included and implemented drashnas changes * Fixed include guard * Fixed some includes, and added avrdude target to docs. * Fixed default keyboard
Diffstat (limited to 'keyboards')
-rw-r--r--keyboards/vitamins_included/config.h24
-rw-r--r--keyboards/vitamins_included/i2c.c163
-rw-r--r--keyboards/vitamins_included/i2c.h50
-rw-r--r--keyboards/vitamins_included/keymaps/default/config.h44
-rw-r--r--keyboards/vitamins_included/keymaps/default/keymap.c199
-rw-r--r--keyboards/vitamins_included/keymaps/default/rules.mk3
-rw-r--r--keyboards/vitamins_included/matrix.c510
-rw-r--r--keyboards/vitamins_included/readme.md126
-rw-r--r--keyboards/vitamins_included/rev1/config.h92
-rw-r--r--keyboards/vitamins_included/rev1/rev1.c13
-rw-r--r--keyboards/vitamins_included/rev1/rev1.h40
-rw-r--r--keyboards/vitamins_included/rev1/rules.mk5
-rw-r--r--keyboards/vitamins_included/rules.mk75
-rw-r--r--keyboards/vitamins_included/serial.c229
-rw-r--r--keyboards/vitamins_included/serial.h27
-rw-r--r--keyboards/vitamins_included/split_util.c20
-rw-r--r--keyboards/vitamins_included/split_util.h18
-rw-r--r--keyboards/vitamins_included/vitamins_included.c16
-rw-r--r--keyboards/vitamins_included/vitamins_included.h25
19 files changed, 1679 insertions, 0 deletions
diff --git a/keyboards/vitamins_included/config.h b/keyboards/vitamins_included/config.h
new file mode 100644
index 000000000..c910d8f24
--- /dev/null
+++ b/keyboards/vitamins_included/config.h
@@ -0,0 +1,24 @@
1/*
2Copyright 2012 Jun Wako <wakojun@gmail.com>
3Copyright 2015 Jack Humbert
4
5This program is free software: you can redistribute it and/or modify
6it under the terms of the GNU General Public License as published by
7the Free Software Foundation, either version 2 of the License, or
8(at your option) any later version.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19#ifndef CONFIG_H
20#define CONFIG_H
21
22#include "config_common.h"
23
24#endif
diff --git a/keyboards/vitamins_included/i2c.c b/keyboards/vitamins_included/i2c.c
new file mode 100644
index 000000000..49ada2143
--- /dev/null
+++ b/keyboards/vitamins_included/i2c.c
@@ -0,0 +1,163 @@
1#include <util/twi.h>
2#include <avr/io.h>
3#include <stdlib.h>
4#include <avr/interrupt.h>
5#include <util/twi.h>
6#include <stdbool.h>
7#include "i2c.h"
8
9#ifdef USE_I2C
10
11// Limits the amount of we wait for any one i2c transaction.
12// Since were running SCL line 100kHz (=> 10μs/bit), and each transactions is
13// 9 bits, a single transaction will take around 90μs to complete.
14//
15// (F_CPU/SCL_CLOCK) => # of μC cycles to transfer a bit
16// poll loop takes at least 8 clock cycles to execute
17#define I2C_LOOP_TIMEOUT (9+1)*(F_CPU/SCL_CLOCK)/8
18
19#define BUFFER_POS_INC() (slave_buffer_pos = (slave_buffer_pos+1)%SLAVE_BUFFER_SIZE)
20
21volatile uint8_t i2c_slave_buffer[SLAVE_BUFFER_SIZE];
22
23static volatile uint8_t slave_buffer_pos;
24static volatile bool slave_has_register_set = false;
25
26// Wait for an i2c operation to finish
27inline static
28void i2c_delay(void) {
29 uint16_t lim = 0;
30 while(!(TWCR & (1<<TWINT)) && lim < I2C_LOOP_TIMEOUT)
31 lim++;
32
33 // easier way, but will wait slightly longer
34 // _delay_us(100);
35}
36
37// Setup twi to run at 100kHz
38void i2c_master_init(void) {
39 // no prescaler
40 TWSR = 0;
41 // Set TWI clock frequency to SCL_CLOCK. Need TWBR>10.
42 // Check datasheets for more info.
43 TWBR = ((F_CPU/SCL_CLOCK)-16)/2;
44}
45
46// Start a transaction with the given i2c slave address. The direction of the
47// transfer is set with I2C_READ and I2C_WRITE.
48// returns: 0 => success
49// 1 => error
50uint8_t i2c_master_start(uint8_t address) {
51 TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTA);
52
53 i2c_delay();
54
55 // check that we started successfully
56 if ( (TW_STATUS != TW_START) && (TW_STATUS != TW_REP_START))
57 return 1;
58
59 TWDR = address;
60 TWCR = (1<<TWINT) | (1<<TWEN);
61
62 i2c_delay();
63
64 if ( (TW_STATUS != TW_MT_SLA_ACK) && (TW_STATUS != TW_MR_SLA_ACK) )
65 return 1; // slave did not acknowledge
66 else
67 return 0; // success
68}
69
70
71// Finish the i2c transaction.
72void i2c_master_stop(void) {
73 TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
74
75 uint16_t lim = 0;
76 while(!(TWCR & (1<<TWSTO)) && lim < I2C_LOOP_TIMEOUT)
77 lim++;
78}
79
80// Write one byte to the i2c slave.
81// returns 0 => slave ACK
82// 1 => slave NACK
83uint8_t i2c_master_write(uint8_t data) {
84 TWDR = data;
85 TWCR = (1<<TWINT) | (1<<TWEN);
86
87 i2c_delay();
88
89 // check if the slave acknowledged us
90 return (TW_STATUS == TW_MT_DATA_ACK) ? 0 : 1;
91}
92
93// Read one byte from the i2c slave. If ack=1 the slave is acknowledged,
94// if ack=0 the acknowledge bit is not set.
95// returns: byte read from i2c device
96uint8_t i2c_master_read(int ack) {
97 TWCR = (1<<TWINT) | (1<<TWEN) | (ack<<TWEA);
98
99 i2c_delay();
100 return TWDR;
101}
102
103void i2c_reset_state(void) {
104 TWCR = 0;
105}
106
107void i2c_slave_init(uint8_t address) {
108 TWAR = address << 0; // slave i2c address
109 // TWEN - twi enable
110 // TWEA - enable address acknowledgement
111 // TWINT - twi interrupt flag
112 // TWIE - enable the twi interrupt
113 TWCR = (1<<TWIE) | (1<<TWEA) | (1<<TWINT) | (1<<TWEN);
114}
115
116ISR(TWI_vect);
117
118ISR(TWI_vect) {
119 uint8_t ack = 1;
120 switch(TW_STATUS) {
121 case TW_SR_SLA_ACK:
122 // this device has been addressed as a slave receiver
123 slave_has_register_set = false;
124 break;
125
126 case TW_SR_DATA_ACK:
127 // this device has received data as a slave receiver
128 // The first byte that we receive in this transaction sets the location
129 // of the read/write location of the slaves memory that it exposes over
130 // i2c. After that, bytes will be written at slave_buffer_pos, incrementing
131 // slave_buffer_pos after each write.
132 if(!slave_has_register_set) {
133 slave_buffer_pos = TWDR;
134 // don't acknowledge the master if this memory loctaion is out of bounds
135 if ( slave_buffer_pos >= SLAVE_BUFFER_SIZE ) {
136 ack = 0;
137 slave_buffer_pos = 0;
138 }
139 slave_has_register_set = true;
140 } else {
141 i2c_slave_buffer[slave_buffer_pos] = TWDR;
142 BUFFER_POS_INC();
143 }
144 break;
145
146 case TW_ST_SLA_ACK:
147 case TW_ST_DATA_ACK:
148 // master has addressed this device as a slave transmitter and is
149 // requesting data.
150 TWDR = i2c_slave_buffer[slave_buffer_pos];
151 BUFFER_POS_INC();
152 break;
153
154 case TW_BUS_ERROR: // something went wrong, reset twi state
155 TWCR = 0;
156 default:
157 break;
158 }
159 // Reset everything, so we are ready for the next TWI interrupt
160 TWCR |= (1<<TWIE) | (1<<TWINT) | (ack<<TWEA) | (1<<TWEN);
161 contacted_by_master = true;
162}
163#endif
diff --git a/keyboards/vitamins_included/i2c.h b/keyboards/vitamins_included/i2c.h
new file mode 100644
index 000000000..739d134be
--- /dev/null
+++ b/keyboards/vitamins_included/i2c.h
@@ -0,0 +1,50 @@
1#ifndef I2C_H
2#define I2C_H
3
4#include <stdint.h>
5#include "split_util.h"
6
7#ifndef F_CPU
8#define F_CPU 16000000UL
9#endif
10
11#define I2C_READ 1
12#define I2C_WRITE 0
13
14#define I2C_ACK 1
15#define I2C_NACK 0
16
17#define SLAVE_BUFFER_SIZE 0x10
18
19// i2c SCL clock frequency
20#define SCL_CLOCK 400000L
21
22extern volatile uint8_t i2c_slave_buffer[SLAVE_BUFFER_SIZE];
23
24void i2c_master_init(void);
25uint8_t i2c_master_start(uint8_t address);
26void i2c_master_stop(void);
27uint8_t i2c_master_write(uint8_t data);
28uint8_t i2c_master_read(int);
29void i2c_reset_state(void);
30void i2c_slave_init(uint8_t address);
31
32
33static inline unsigned char i2c_start_read(unsigned char addr) {
34 return i2c_master_start((addr << 1) | I2C_READ);
35}
36
37static inline unsigned char i2c_start_write(unsigned char addr) {
38 return i2c_master_start((addr << 1) | I2C_WRITE);
39}
40
41// from SSD1306 scrips
42extern unsigned char i2c_rep_start(unsigned char addr);
43extern void i2c_start_wait(unsigned char addr);
44extern unsigned char i2c_readAck(void);
45extern unsigned char i2c_readNak(void);
46extern unsigned char i2c_read(unsigned char ack);
47
48#define i2c_read(ack) (ack) ? i2c_readAck() : i2c_readNak();
49
50#endif
diff --git a/keyboards/vitamins_included/keymaps/default/config.h b/keyboards/vitamins_included/keymaps/default/config.h
new file mode 100644
index 000000000..35f641a94
--- /dev/null
+++ b/keyboards/vitamins_included/keymaps/default/config.h
@@ -0,0 +1,44 @@
1/*
2This is the c configuration file for the keymap
3
4Copyright 2012 Jun Wako <wakojun@gmail.com>
5Copyright 2015 Jack Humbert
6
7This program is free software: you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation, either version 2 of the License, or
10(at your option) any later version.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this program. If not, see <http://www.gnu.org/licenses/>.
19*/
20
21#ifndef CONFIG_USER_H
22#define CONFIG_USER_H
23
24#include "../../config.h"
25
26/* Use I2C or Serial, not both */
27
28#define USE_SERIAL
29// #define USE_I2C
30
31/* Select hand configuration */
32
33//#define MASTER_LEFT
34// #define MASTER_RIGHT
35#define EE_HANDS
36
37#ifdef AUDIO_ENABLE
38 #define DEFAULT_LAYER_SONGS { SONG(QWERTY_SOUND), \
39 SONG(DVORAK_SOUND), \
40 SONG(COLEMAK_SOUND) \
41 }
42#endif
43
44#endif
diff --git a/keyboards/vitamins_included/keymaps/default/keymap.c b/keyboards/vitamins_included/keymaps/default/keymap.c
new file mode 100644
index 000000000..f25e2fd32
--- /dev/null
+++ b/keyboards/vitamins_included/keymaps/default/keymap.c
@@ -0,0 +1,199 @@
1#include QMK_KEYBOARD_H
2#include "action_layer.h"
3#include "eeconfig.h"
4
5extern keymap_config_t keymap_config;
6
7// Each layer gets a name for readability, which is then used in the keymap matrix below.
8// The underscores don't mean anything - you can have a layer called STUFF or any other name.
9// Layer names don't all need to be of the same length, obviously, and you can also skip them
10// entirely and just use numbers.
11#define _QWERTY 0
12#define _COLEMAK 1
13#define _DVORAK 2
14#define _LOWER 3
15#define _RAISE 4
16#define _ADJUST 16
17
18enum custom_keycodes {
19 QWERTY = SAFE_RANGE,
20 COLEMAK,
21 DVORAK,
22 LOWER,
23 RAISE,
24 ADJUST
25};
26
27// Fillers to make layering more clear
28#define _______ KC_TRNS
29#define XXXXXXX KC_NO
30
31const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
32
33/* Qwerty
34 * ,-----------------------------------------------------------------------------------.
35 * | Esc | Q | W | E | R | T | Y | U | I | O | P | Bksp |
36 * |------+------+------+------+------+-------------+------+------+------+------+------|
37 * | Tab | A | S | D | F | G | H | J | K | L | ; | ' |
38 * |------+------+------+------+------+------|------+------+------+------+------+------|
39 * | Shift| Z | X | C | V | B | N | M | , | . | / |Enter |
40 * |------+------+------+------+------+------+------+------+------+------+------+------|
41 * | Ctrl | GUI | Alt |Adjust|Lower |Space |Space |Raise | Left | Down | Up |Right |
42 * `-----------------------------------------------------------------------------------'
43 */
44[_QWERTY] = LAYOUT_ortho_4x12( \
45 KC_ESC, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSPC, \
46 KC_TAB, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, \
47 KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_ENT , \
48 KC_LCTRL,KC_LGUI, KC_LALT, ADJUST, LOWER, KC_SPC, KC_SPC, RAISE, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT \
49),
50
51/* Colemak
52 * ,-----------------------------------------------------------------------------------.
53 * | Tab | Q | W | F | P | G | J | L | U | Y | ; | Bksp |
54 * |------+------+------+------+------+-------------+------+------+------+------+------|
55 * | Esc | A | R | S | T | D | H | N | E | I | O | ' |
56 * |------+------+------+------+------+------|------+------+------+------+------+------|
57 * | Shift| Z | X | C | V | B | K | M | , | . | / |Enter |
58 * |------+------+------+------+------+------+------+------+------+------+------+------|
59 * |Adjust| Ctrl | Alt | GUI |Lower |Space |Space |Raise | Left | Down | Up |Right |
60 * `-----------------------------------------------------------------------------------'
61 */
62[_COLEMAK] = LAYOUT_ortho_4x12( \
63 KC_TAB, KC_Q, KC_W, KC_F, KC_P, KC_G, KC_J, KC_L, KC_U, KC_Y, KC_SCLN, KC_BSPC, \
64 KC_ESC, KC_A, KC_R, KC_S, KC_T, KC_D, KC_H, KC_N, KC_E, KC_I, KC_O, KC_QUOT, \
65 KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_K, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_ENT , \
66 ADJUST, KC_LCTL, KC_LALT, KC_LGUI, LOWER, KC_SPC, KC_SPC, RAISE, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT \
67),
68
69/* Dvorak
70 * ,-----------------------------------------------------------------------------------.
71 * | Tab | ' | , | . | P | Y | F | G | C | R | L | Bksp |
72 * |------+------+------+------+------+-------------+------+------+------+------+------|
73 * | Esc | A | O | E | U | I | D | H | T | N | S | / |
74 * |------+------+------+------+------+------|------+------+------+------+------+------|
75 * | Shift| ; | Q | J | K | X | B | M | W | V | Z |Enter |
76 * |------+------+------+------+------+------+------+------+------+------+------+------|
77 * |Adjust| Ctrl | Alt | GUI |Lower |Space |Space |Raise | Left | Down | Up |Right |
78 * `-----------------------------------------------------------------------------------'
79 */
80[_DVORAK] = LAYOUT_ortho_4x12( \
81 KC_TAB, KC_QUOT, KC_COMM, KC_DOT, KC_P, KC_Y, KC_F, KC_G, KC_C, KC_R, KC_L, KC_BSPC, \
82 KC_ESC, KC_A, KC_O, KC_E, KC_U, KC_I, KC_D, KC_H, KC_T, KC_N, KC_S, KC_SLSH, \
83 KC_LSFT, KC_SCLN, KC_Q, KC_J, KC_K, KC_X, KC_B, KC_M, KC_W, KC_V, KC_Z, KC_ENT , \
84 ADJUST, KC_LCTL, KC_LALT, KC_LGUI, LOWER, KC_SPC, KC_SPC, RAISE, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT \
85),
86
87/* Lower
88 * ,-----------------------------------------------------------------------------------.
89 * | ~ | ! | @ | # | $ | % | ^ | & | * | ( | ) | Del |
90 * |------+------+------+------+------+-------------+------+------+------+------+------|
91 * | Del | F1 | F2 | F3 | F4 | F5 | F6 | _ | + | | \ | | |
92 * |------+------+------+------+------+------|------+------+------+------+------+------|
93 * |RESET | F7 | F8 | F9 | F10 | F11 | F12 |ISO ~ |ISO | | | |Enter |
94 * |------+------+------+------+------+------+------+------+------+------+------+------|
95 * | | | | | | | | Next | Vol- | Vol+ | Play |
96 * `-----------------------------------------------------------------------------------'
97 */
98[_LOWER] = LAYOUT_ortho_4x12( \
99 KC_TILD, KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN, KC_DEL, \
100 KC_DEL, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_UNDS, KC_PLUS, KC_LCBR, KC_RCBR, KC_PIPE, \
101 RESET, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12,S(KC_NUHS),S(KC_NUBS),_______, _______, _______, \
102 _______, _______, _______, _______, _______, _______, _______, _______, KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY \
103),
104
105/* Raise
106 * ,-----------------------------------------------------------------------------------.
107 * | ` | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | Del |
108 * |------+------+------+------+------+-------------+------+------+------+------+------|
109 * | Del | F1 | F2 | F3 | F4 | F5 | F6 | - | = | [ | ] | \ |
110 * |------+------+------+------+------+------|------+------+------+------+------+------|
111 * | | F7 | F8 | F9 | F10 | F11 | F12 |ISO # |ISO / | | |RESET |
112 * |------+------+------+------+------+------+------+------+------+------+------+------|
113 * | | | | | | | | Next | Vol- | Vol+ | Play |
114 * `-----------------------------------------------------------------------------------'
115 */
116[_RAISE] = LAYOUT_ortho_4x12( \
117 KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_DEL, \
118 KC_DEL, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_MINS, KC_EQL, KC_LBRC, KC_RBRC, KC_BSLS, \
119 _______, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_NUHS, KC_NUBS, _______, _______, RESET, \
120 _______, _______, _______, _______, _______, _______, _______, _______, KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY \
121),
122
123/* Adjust (Lower + Raise)
124 * ,-----------------------------------------------------------------------------------.
125 * | | Reset| | | | | | | | | | Del |
126 * |------+------+------+------+------+-------------+------+------+------+------+------|
127 * | | | |Aud on|Audoff|AGnorm|AGswap|Qwerty|Colemk|Dvorak| | |
128 * |------+------+------+------+------+------|------+------+------+------+------+------|
129 * | | | | | | | | | | | | |
130 * |------+------+------+------+------+------+------+------+------+------+------+------|
131 * | | | | | | | | | | |RGB_MOD|
132 * `-----------------------------------------------------------------------------------'
133 */
134[_ADJUST] = LAYOUT_ortho_4x12( \
135 _______, RESET, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_DEL, \
136 _______, _______, _______, AU_ON, AU_OFF, AG_NORM, AG_SWAP, QWERTY, COLEMAK, DVORAK, _______, _______, \
137 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
138 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, RGB_MOD \
139)
140
141
142};
143
144void persistent_default_layer_set(uint16_t default_layer) {
145 eeconfig_update_default_layer(default_layer);
146 default_layer_set(default_layer);
147}
148
149bool process_record_user(uint16_t keycode, keyrecord_t *record) {
150 switch (keycode) {
151 case QWERTY:
152 if (record->event.pressed) {
153 persistent_default_layer_set(1UL<<_QWERTY);
154 }
155 return false;
156 break;
157 case COLEMAK:
158 if (record->event.pressed) {
159 persistent_default_layer_set(1UL<<_COLEMAK);
160 }
161 return false;
162 break;
163 case DVORAK:
164 if (record->event.pressed) {
165 persistent_default_layer_set(1UL<<_DVORAK);
166 }
167 return false;
168 break;
169 case LOWER:
170 if (record->event.pressed) {
171 layer_on(_LOWER);
172 update_tri_layer(_LOWER, _RAISE, _ADJUST);
173 } else {
174 layer_off(_LOWER);
175 update_tri_layer(_LOWER, _RAISE, _ADJUST);
176 }
177 return false;
178 break;
179 case RAISE:
180 if (record->event.pressed) {
181 layer_on(_RAISE);
182 update_tri_layer(_LOWER, _RAISE, _ADJUST);
183 } else {
184 layer_off(_RAISE);
185 update_tri_layer(_LOWER, _RAISE, _ADJUST);
186 }
187 return false;
188 break;
189 case ADJUST:
190 if (record->event.pressed) {
191 layer_on(_ADJUST);
192 } else {
193 layer_off(_ADJUST);
194 }
195 return false;
196 break;
197 }
198 return true;
199}
diff --git a/keyboards/vitamins_included/keymaps/default/rules.mk b/keyboards/vitamins_included/keymaps/default/rules.mk
new file mode 100644
index 000000000..457a3d01d
--- /dev/null
+++ b/keyboards/vitamins_included/keymaps/default/rules.mk
@@ -0,0 +1,3 @@
1ifndef QUANTUM_DIR
2 include ../../../../Makefile
3endif
diff --git a/keyboards/vitamins_included/matrix.c b/keyboards/vitamins_included/matrix.c
new file mode 100644
index 000000000..7079a8da9
--- /dev/null
+++ b/keyboards/vitamins_included/matrix.c
@@ -0,0 +1,510 @@
1/*
2Copyright 2012 Jun Wako <wakojun@gmail.com>
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18/*
19 * scan matrix
20 */
21#include <stdint.h>
22#include <stdbool.h>
23#include <avr/io.h>
24#include <avr/interrupt.h>
25#include <util/delay.h>
26#include "wait.h"
27#include "print.h"
28#include "debug.h"
29#include "util.h"
30#include "matrix.h"
31#include "split_util.h"
32#include "pro_micro.h"
33#include "config.h"
34#include "timer.h"
35#include <print.h>
36
37#if (defined(RGB_MIDI) | defined(RGBLIGHT_ANIMATIONS)) & defined(RGBLIGHT_ENABLE)
38 #include "rgblight.h"
39#endif
40
41
42#ifdef USE_I2C
43# include "i2c.h"
44#else // USE_SERIAL
45# include "serial.h"
46#endif
47
48#ifndef DEBOUNCING_DELAY
49# define DEBOUNCING_DELAY 5
50#endif
51
52#if (DEBOUNCING_DELAY > 0)
53 static uint16_t debouncing_time;
54 static bool debouncing = false;
55#endif
56
57#if (MATRIX_COLS <= 8)
58# define print_matrix_header() print("\nr/c 01234567\n")
59# define print_matrix_row(row) print_bin_reverse8(matrix_get_row(row))
60# define matrix_bitpop(i) bitpop(matrix[i])
61# define ROW_SHIFTER ((uint8_t)1)
62#else
63# error "Currently only supports 8 COLS"
64#endif
65static matrix_row_t matrix_debouncing[MATRIX_ROWS];
66
67#define ERROR_DISCONNECT_COUNT 5
68
69#define ROWS_PER_HAND (MATRIX_ROWS/2)
70
71static uint8_t error_count = 0;
72
73static const uint8_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
74static const uint8_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
75
76/* matrix state(1:on, 0:off) */
77static matrix_row_t matrix[MATRIX_ROWS];
78static matrix_row_t matrix_debouncing[MATRIX_ROWS];
79
80#if (DIODE_DIRECTION == COL2ROW)
81 static void init_cols(void);
82 static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row);
83 static void unselect_rows(void);
84 static void select_row(uint8_t row);
85 static void unselect_row(uint8_t row);
86#elif (DIODE_DIRECTION == ROW2COL)
87 static void init_rows(void);
88 static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col);
89 static void unselect_cols(void);
90 static void unselect_col(uint8_t col);
91 static void select_col(uint8_t col);
92#endif
93
94
95__attribute__ ((weak))
96void matrix_init_quantum(void) {
97 matrix_init_kb();
98}
99
100__attribute__ ((weak))
101void matrix_scan_quantum(void) {
102 matrix_scan_kb();
103}
104
105__attribute__ ((weak))
106void matrix_init_kb(void) {
107 matrix_init_user();
108}
109
110__attribute__ ((weak))
111void matrix_scan_kb(void) {
112 matrix_scan_user();
113}
114
115__attribute__ ((weak))
116void matrix_init_user(void) {
117}
118
119__attribute__ ((weak))
120void matrix_scan_user(void) {
121}
122
123inline
124uint8_t matrix_rows(void) {
125 return MATRIX_ROWS;
126}
127
128inline
129uint8_t matrix_cols(void) {
130 return MATRIX_COLS;
131}
132
133bool has_usb(void) {
134 return UDADDR & _BV(ADDEN); // This will return true of a USB connection has been established
135}
136
137void matrix_init(void)
138{
139#ifdef DISABLE_JTAG
140 // JTAG disable for PORT F. write JTD bit twice within four cycles.
141 MCUCR |= (1<<JTD);
142 MCUCR |= (1<<JTD);
143#endif
144
145 // initialize row and col
146#if (DIODE_DIRECTION == COL2ROW)
147 unselect_rows();
148 init_cols();
149#elif (DIODE_DIRECTION == ROW2COL)
150 unselect_cols();
151 init_rows();
152#endif
153
154 TX_RX_LED_INIT;
155
156 // initialize matrix state: all keys off
157 for (uint8_t i=0; i < MATRIX_ROWS; i++) {
158 matrix[i] = 0;
159 matrix_debouncing[i] = 0;
160 }
161
162 #ifdef RGBLIGHT_ENABLE
163 rgblight_init();
164 #endif
165
166 timer_init();
167 #ifdef USE_I2C
168 i2c_slave_init(SLAVE_I2C_ADDRESS);
169 #else
170 serial_slave_init();
171 #endif
172
173 sei();
174
175 matrix_init_quantum();
176 while(!has_usb() || contacted_by_master){
177 matrix_slave_scan();
178 }
179
180 // Set up as master
181 #ifdef USE_I2C
182 i2c_reset_state();
183 i2c_master_init();
184 #else
185 serial_master_init();
186 #endif
187}
188
189uint8_t _matrix_scan(void)
190{
191 int offset = isLeftHand ? 0 : (ROWS_PER_HAND);
192#if (DIODE_DIRECTION == COL2ROW)
193 // Set row, read cols
194 for (uint8_t current_row = 0; current_row < ROWS_PER_HAND; current_row++) {
195# if (DEBOUNCING_DELAY > 0)
196 bool matrix_changed = read_cols_on_row(matrix_debouncing+offset, current_row);
197
198 if (matrix_changed) {
199 debouncing = true;
200 debouncing_time = timer_read();
201 PORTD ^= (1 << 2);
202 }
203
204# else
205 read_cols_on_row(matrix+offset, current_row);
206# endif
207
208 }
209
210#elif (DIODE_DIRECTION == ROW2COL)
211 // Set col, read rows
212 for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) {
213# if (DEBOUNCING_DELAY > 0)
214 bool matrix_changed = read_rows_on_col(matrix_debouncing+offset, current_col);
215 if (matrix_changed) {
216 debouncing = true;
217 debouncing_time = timer_read();
218 }
219# else
220 read_rows_on_col(matrix+offset, current_col);
221# endif
222
223 }
224#endif
225
226# if (DEBOUNCING_DELAY > 0)
227 if (debouncing && (timer_elapsed(debouncing_time) > DEBOUNCING_DELAY)) {
228 for (uint8_t i = 0; i < ROWS_PER_HAND; i++) {
229 matrix[i+offset] = matrix_debouncing[i+offset];
230 }
231 debouncing = false;
232 }
233# endif
234
235 return 1;
236}
237
238#ifdef USE_I2C
239
240// Get rows from other half over i2c
241int i2c_transaction(void) {
242 int slaveOffset = (isLeftHand) ? (ROWS_PER_HAND) : 0;
243
244 int err = i2c_master_start(SLAVE_I2C_ADDRESS + I2C_WRITE);
245 if (err) goto i2c_error;
246
247 // start of matrix stored at 0x00
248 err = i2c_master_write(0x00);
249 if (err) goto i2c_error;
250
251 // Start read
252 err = i2c_master_start(SLAVE_I2C_ADDRESS + I2C_READ);
253 if (err) goto i2c_error;
254
255 if (!err) {
256 int i;
257 for (i = 0; i < ROWS_PER_HAND-1; ++i) {
258 matrix[slaveOffset+i] = i2c_master_read(I2C_ACK);
259 }
260 matrix[slaveOffset+i] = i2c_master_read(I2C_NACK);
261 i2c_master_stop();
262 } else {
263i2c_error: // the cable is disconnceted, or something else went wrong
264 i2c_reset_state();
265 return err;
266 }
267
268 return 0;
269}
270
271#else // USE_SERIAL
272
273int serial_transaction(void) {
274 int slaveOffset = (isLeftHand) ? (ROWS_PER_HAND) : 0;
275
276 if (serial_update_buffers()) {
277 return 1;
278 }
279
280 for (int i = 0; i < ROWS_PER_HAND; ++i) {
281 matrix[slaveOffset+i] = serial_slave_buffer[i];
282 }
283 return 0;
284}
285#endif
286
287uint8_t matrix_scan(void)
288{
289 uint8_t ret = _matrix_scan();
290
291#ifdef USE_I2C
292 if( i2c_transaction() ) {
293#else // USE_SERIAL
294 if( serial_transaction() ) {
295#endif
296 // turn on the indicator led when halves are disconnected
297 TXLED1;
298
299 error_count++;
300
301 if (error_count > ERROR_DISCONNECT_COUNT) {
302 // reset other half if disconnected
303 int slaveOffset = (isLeftHand) ? (ROWS_PER_HAND) : 0;
304 for (int i = 0; i < ROWS_PER_HAND; ++i) {
305 matrix[slaveOffset+i] = 0;
306 }
307 }
308 } else {
309 // turn off the indicator led on no error
310 TXLED0;
311 error_count = 0;
312 }
313 matrix_scan_quantum();
314 return ret;
315}
316
317void matrix_slave_scan(void) {
318 #if defined(RGBLIGHT_ANIMATIONS) & defined(RGBLIGHT_ENABLE)
319 rgblight_task();
320 #endif
321 _matrix_scan();
322
323 int offset = (isLeftHand) ? 0 : ROWS_PER_HAND;
324
325#ifdef USE_I2C
326 for (int i = 0; i < ROWS_PER_HAND; ++i) {
327 i2c_slave_buffer[i] = matrix[offset+i];
328 }
329#else // USE_SERIAL
330 for (int i = 0; i < ROWS_PER_HAND; ++i) {
331 serial_slave_buffer[i] = matrix[offset+i];
332 }
333#endif
334}
335
336bool matrix_is_modified(void)
337{
338 if (debouncing) return false;
339 return true;
340}
341
342inline
343bool matrix_is_on(uint8_t row, uint8_t col)
344{
345 return (matrix[row] & ((matrix_row_t)1<<col));
346}
347
348inline
349matrix_row_t matrix_get_row(uint8_t row)
350{
351 return matrix[row];
352}
353
354void matrix_print(void)
355{
356 print("\nr/c 0123456789ABCDEF\n");
357 for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
358 phex(row); print(": ");
359 pbin_reverse16(matrix_get_row(row));
360 print("\n");
361 }
362}
363
364uint8_t matrix_key_count(void)
365{
366 uint8_t count = 0;
367 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
368 count += bitpop16(matrix[i]);
369 }
370 return count;
371}
372
373#if (DIODE_DIRECTION == COL2ROW)
374
375static void init_cols(void)
376{
377 for(uint8_t x = 0; x < MATRIX_COLS; x++) {
378 uint8_t pin = col_pins[x];
379 _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
380 _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
381 }
382}
383
384static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row)
385{
386 // Store last value of row prior to reading
387 matrix_row_t last_row_value = current_matrix[current_row];
388
389 // Clear data in matrix row
390 current_matrix[current_row] = 0;
391
392 // Select row and wait for row selecton to stabilize
393 select_row(current_row);
394 wait_us(30);
395
396 // For each col...
397 for(uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) {
398
399 // Select the col pin to read (active low)
400 uint8_t pin = col_pins[col_index];
401 uint8_t pin_state = (_SFR_IO8(pin >> 4) & _BV(pin & 0xF));
402
403 // Populate the matrix row with the state of the col pin
404 current_matrix[current_row] |= pin_state ? 0 : (ROW_SHIFTER << col_index);
405 }
406
407 // Unselect row
408 unselect_row(current_row);
409
410 return (last_row_value != current_matrix[current_row]);
411}
412
413static void select_row(uint8_t row)
414{
415 uint8_t pin = row_pins[row];
416 _SFR_IO8((pin >> 4) + 1) |= _BV(pin & 0xF); // OUT
417 _SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF); // LOW
418}
419
420static void unselect_row(uint8_t row)
421{
422 uint8_t pin = row_pins[row];
423 _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
424 _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
425}
426
427static void unselect_rows(void)
428{
429 for(uint8_t x = 0; x < ROWS_PER_HAND; x++) {
430 uint8_t pin = row_pins[x];
431 _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
432 _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
433 }
434}
435
436#elif (DIODE_DIRECTION == ROW2COL)
437
438static void init_rows(void)
439{
440 for(uint8_t x = 0; x < ROWS_PER_HAND; x++) {
441 uint8_t pin = row_pins[x];
442 _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
443 _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
444 }
445}
446
447static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col)
448{
449 bool matrix_changed = false;
450
451 // Select col and wait for col selecton to stabilize
452 select_col(current_col);
453 wait_us(30);
454
455 // For each row...
456 for(uint8_t row_index = 0; row_index < ROWS_PER_HAND; row_index++)
457 {
458
459 // Store last value of row prior to reading
460 matrix_row_t last_row_value = current_matrix[row_index];
461
462 // Check row pin state
463 if ((_SFR_IO8(row_pins[row_index] >> 4) & _BV(row_pins[row_index] & 0xF)) == 0)
464 {
465 // Pin LO, set col bit
466 current_matrix[row_index] |= (ROW_SHIFTER << current_col);
467 }
468 else
469 {
470 // Pin HI, clear col bit
471 current_matrix[row_index] &= ~(ROW_SHIFTER << current_col);
472 }
473
474 // Determine if the matrix changed state
475 if ((last_row_value != current_matrix[row_index]) && !(matrix_changed))
476 {
477 matrix_changed = true;
478 }
479 }
480
481 // Unselect col
482 unselect_col(current_col);
483
484 return matrix_changed;
485}
486
487static void select_col(uint8_t col)
488{
489 uint8_t pin = col_pins[col];
490 _SFR_IO8((pin >> 4) + 1) |= _BV(pin & 0xF); // OUT
491 _SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF); // LOW
492}
493
494static void unselect_col(uint8_t col)
495{
496 uint8_t pin = col_pins[col];
497 _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
498 _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
499}
500
501static void unselect_cols(void)
502{
503 for(uint8_t x = 0; x < MATRIX_COLS; x++) {
504 uint8_t pin = col_pins[x];
505 _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
506 _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
507 }
508}
509
510#endif
diff --git a/keyboards/vitamins_included/readme.md b/keyboards/vitamins_included/readme.md
new file mode 100644
index 000000000..0163f154e
--- /dev/null
+++ b/keyboards/vitamins_included/readme.md
@@ -0,0 +1,126 @@
1Let's Split Vitamins Included
2======
3![Let's Split Vitamins included, assmebled in 3D printed case](https://i.imgur.com/btl0vNQ.jpg)
4
5This readme and most of the code are from https://github.com/ahtn/tmk_keyboard/
6
7
8**Hardware files for the Let's Split vitamins included are stored [here](http://github.com/duckle29/let-s-Split-v2/tree/onboardMCU)**
9
10## First Time Setup
11
12Clone the `qmk_firmware` repo and navigate to its top level directory. [Once your build environment is setup](https://docs.qmk.fm/getting_started_build_tools.html), you'll be able to generate the default .hex using the [build/compile instructions](https://docs.qmk.fm/build-compile-instructions) in the docs
13
14If everything worked correctly you will see a file:
15
16```bash
17lets_split_vitamins_rev1_YOUR_KEYMAP_NAME.hex
18```
19
20If you want, you can flash the hex file to the keyboard right after compilation, by adding `:avrdude` to the end of the make command like so:
21
22```bash
23make lets_split_vitamins/rev1:default:avrdude
24```
25
26This will both compile the hex, and flash the connected half.
27
28For more information on customizing keymaps, take a look at the primary documentation for [Customizing Your Keymap](/readme.md##customizing-your-keymap) in the main readme.md.
29
30
31Features
32--------
33
34For the full Quantum Mechanical Keyboard feature list, see [the parent readme.md](/readme.md).
35
36Some features supported by the firmware:
37
38* Either half can connect to the computer via USB, or both halves can be used
39 independently.
40* You only need 3 wires to connect the two halves. One for VCC, one for GND and one
41 for serial communication.
42* Optional support for I2C connection between the two halves if for some
43 reason you require a faster connection between the two halves. Note this
44 requires an extra wire between halves and pull-up resistors on the data lines.
45 This is supported on the vitamins included.
46 The extra data line can also be used for ws2812 type LEDs.
47 If neither I2C nor RGB underglow is used, a TRS cable can be used instead of the 4wire TRRS cables.
48
49Required Hardware
50-----------------
51|Amount| Description |
52|--|--|
53| 1 | PCB kit from novelkeys |
54| 48 | MX compatible switches |
55| 48 | 1U keycaps
56| 2 | Half cases. A 3D model for the left half is available [here](https://cad.onshape.com/documents/c6e5ae250d1e24fe46c9ef6c/w/d69f7049c0921df3d2b241f9/e/ecc2b176ab52a6d77bc55051). Mirror that to get a right-half case. Plate cases will be designed in the future.
57| 1 | USB-mini-B cable of your choice |
58| 1 | TRS / TRRS cable
59
60Optional Hardware
61-----------------
62
63A speaker can be hooked-up to the footprint on the PCBs. It is already enabled in the default firmware from github.
64
65A strip of WS2812 LEDs can be hooked up too, a guide will be written on how to do that once I get mine in the mail.
66The PCB and connectors can safely handle 1A of current, but the USB standard is only rated at 500mA. Keep that in mind when picking the amount of LEDs.
67
68
69## Using I2C
70
71On the left half PCB, there's two pads labled ***I2C Pullup*** if you want to use I2C, you need to bridge those two solder jumpers with a soldering iron.
72
73You can change your configuration between serial and i2c by modifying your `config.h` file.
74
75Notes on Software Configuration
76-------------------------------
77
78Configuring the firmware is similar to any other QMK project. One thing
79to note is that `MATRIX_ROWS` in `config.h` is the total number of rows between
80the two halves, so because the let's split vitamins included has 4 rows in each half, it's
81`MATRIX_ROWS=8`.
82
83Also, the current implementation assumes a maximum of 8 columns, but it would
84not be very difficult to adapt it to support more if required.
85
86
87## Entering bootloader
88If the keyboard isn't new, and has been flashed before, you need to enter bootloader.
89To enter bootloader, either use the assigned keys on the keymap, or if none have been put in the keymap, quickly short the reset to gnd twice. (Bottom pins of programming header, see image) ![Reset pins](https://i.imgur.com/LCXlv9W.png)
90
91If using the default keymap, there's a reset key-combination on each half:
92***Lower (SW23) and left-shift (SW13)*** on the left half, or
93***Raise(SW44) and Enter(SW42)*** on the right half
94It is recommended to add such reset keys to any custom keymaps. It shouldn't be necesarry to have one on each half, but the default layout has that.
95
96The board exits bootloader mode after 8 seconds, if you haven't started flashing.
97
98## EEPROM
99
100If this is the first time you're flashing the boards, you have to flash EEPROM
101
1020. If your keyboard is plugged in, unplug it
1031. Open a terminal, and navigate to the qmk_firmware folder
1042. Run `ls /dev | grep tty` Note down which ports you see
1052. Plug the keyboard in, if it's new, it should enter bootloader, if it's not new, see **Entering bootloader** on how to enter bootloader mode
1064. Right after entering bootloader, run `ls /dev | grep tty` again. There should be a new tty, this is the bootloader TTY, note it down. If nothing shows see **Entering bootloader** on how to enter bootloader mode
1076. For the left hand side, run `avrdude -c avr109 -p m32u4 -P /dev/ttyS1 -U eeprom:w:"./keyboards/lets_split_vitamins/eeprom-lefthand.eep":a`
108Replace ***/dev/ttyS1*** with the port you noted down earlier. If you're on windows using msys2, replace ***/dev/ttyS1*** with COM2, note that the number is one higher than the tty number.
109Do the same For the right hand, but change the file to ***eeprom-righthand.eep***
110
111Your EEPROM should be flashed :)
112
113In the future, you shouldn't need to flash EEPROM (it will in fact wear the eeprom memory, so don't)
114
115## Flashing
116If you haven't flashed EEPROM before, do that first.
117
118To flash keymaps onto the keyboard, use:
119```bash
120make lets_split_vitamins/rev1:[KEYMAP]:avrdude
121```
122from the qmk_firmware folder. Default being the default keymap.
123
124You can plug either half into USB and it will work. you can also remove the TRS/TRRS cable, and plug both halves in. (which is why the default layout has reset on both halves)
125
126Enjoy your keyboard! :D
diff --git a/keyboards/vitamins_included/rev1/config.h b/keyboards/vitamins_included/rev1/config.h
new file mode 100644
index 000000000..50168237b
--- /dev/null
+++ b/keyboards/vitamins_included/rev1/config.h
@@ -0,0 +1,92 @@
1/*
2Copyright 2012 Jun Wako <wakojun@gmail.com>
3Copyright 2015 Jack Humbert
4
5This program is free software: you can redistribute it and/or modify
6it under the terms of the GNU General Public License as published by
7the Free Software Foundation, either version 2 of the License, or
8(at your option) any later version.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19#ifndef REV1_CONFIG_H
20#define REV1_CONFIG_H
21
22#include "config_common.h"
23
24/* USB Device descriptor parameter */
25#define VENDOR_ID 0xBEE5
26#define PRODUCT_ID 0xF33D
27#define DEVICE_VER 0x0001
28#define MANUFACTURER Duckle29
29#define PRODUCT Lets Split sockets vitamins included
30#define DESCRIPTION A split keyboard for the cheapish makers
31
32/* key matrix size */
33// Rows are doubled-up
34#define MATRIX_ROWS 8
35#define MATRIX_COLS 6
36
37// wiring of each half
38#define MATRIX_ROW_PINS { F5, F6, C7, F7 }
39#define MATRIX_COL_PINS { F1, F4, E2, B6, D7, D6}
40
41/* define if matrix has ghost */
42//#define MATRIX_HAS_GHOST
43
44/* number of backlight levels */
45// #define BACKLIGHT_LEVELS 3
46
47/* Set 0 if debouncing isn't needed */
48#define DEBOUNCING_DELAY 5
49
50/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
51#define LOCKING_SUPPORT_ENABLE
52/* Locking resynchronize hack */
53#define LOCKING_RESYNC_ENABLE
54
55/* key combination for command */
56#define IS_COMMAND() ( \
57 keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \
58)
59
60/* ws2812 RGB LED */
61#define RGB_DI_PIN F0
62#define RGBLIGHT_TIMER
63#define RGBLED_NUM 16 // Number of LEDs
64#define ws2812_PORTREG PORTF
65#define ws2812_DDRREG DDRF
66#define RGBLIGHT_ANIMATIONS
67
68/* Audio settings */
69#ifdef AUDIO_ENABLE
70 #define C6_AUDIO // Define this to enable the buzzer
71#endif
72
73/*
74 * Feature disable options
75 * These options are also useful to firmware size reduction.
76 */
77
78/* disable debug print */
79// #define NO_DEBUG
80
81/* disable print */
82// #define NO_PRINT
83
84/* disable action features */
85//#define NO_ACTION_LAYER
86#define NO_ACTION_TAPPING
87//#define NO_ACTION_ONESHOT
88//#define NO_ACTION_MACRO
89//#define NO_ACTION_FUNCTION
90
91
92#endif
diff --git a/keyboards/vitamins_included/rev1/rev1.c b/keyboards/vitamins_included/rev1/rev1.c
new file mode 100644
index 000000000..56fbb8787
--- /dev/null
+++ b/keyboards/vitamins_included/rev1/rev1.c
@@ -0,0 +1,13 @@
1#include "rev1.h"
2
3
4#ifdef SSD1306OLED
5void led_set_kb(uint8_t usb_led) {
6 // put your keyboard LED indicator (ex: Caps Lock LED) toggling code here
7 led_set_user(usb_led);
8}
9#endif
10
11void matrix_init_kb(void) {
12 matrix_init_user();
13};
diff --git a/keyboards/vitamins_included/rev1/rev1.h b/keyboards/vitamins_included/rev1/rev1.h
new file mode 100644
index 000000000..743c341c3
--- /dev/null
+++ b/keyboards/vitamins_included/rev1/rev1.h
@@ -0,0 +1,40 @@
1#ifndef REV1_H
2#define REV1_H
3#define DISABLE_JTAG // The keyboard uses PF4, PF5 and PF7, which are used by JTAG.
4#define EE_HANDS // This isn't optional for the vitamins included
5
6#include QMK_KEYBOARD_H
7
8//void promicro_bootloader_jmp(bool program);
9#include "quantum.h"
10
11
12#ifdef USE_I2C
13#include <stddef.h>
14#ifdef __AVR__
15 #include <avr/io.h>
16 #include <avr/interrupt.h>
17#endif
18#endif
19
20//void promicro_bootloader_jmp(bool program);
21
22#define KEYMAP( \
23 L00, L01, L02, L03, L04, L05, R00, R01, R02, R03, R04, R05, \
24 L10, L11, L12, L13, L14, L15, R10, R11, R12, R13, R14, R15, \
25 L20, L21, L22, L23, L24, L25, R20, R21, R22, R23, R24, R25, \
26 L30, L31, L32, L33, L34, L35, R30, R31, R32, R33, R34, R35 \
27 ) \
28 { \
29 { L00, L01, L02, L03, L04, L05 }, \
30 { L10, L11, L12, L13, L14, L15 }, \
31 { L20, L21, L22, L23, L24, L25 }, \
32 { L30, L31, L32, L33, L34, L35 }, \
33 { R00, R01, R02, R03, R04, R05 }, \
34 { R10, R11, R12, R13, R14, R15 }, \
35 { R20, R21, R22, R23, R24, R25 }, \
36 { R30, R31, R32, R33, R34, R35 } \
37 }
38
39#define LAYOUT_ortho_4x12 KEYMAP
40#endif
diff --git a/keyboards/vitamins_included/rev1/rules.mk b/keyboards/vitamins_included/rev1/rules.mk
new file mode 100644
index 000000000..0542810ee
--- /dev/null
+++ b/keyboards/vitamins_included/rev1/rules.mk
@@ -0,0 +1,5 @@
1BACKLIGHT_ENABLE = no
2AUDIO_ENABLE = yes
3RGBLIGHT_ENABLE = yes
4DEBUG_ENABLE = no
5CONSOLE_ENABLE = no
diff --git a/keyboards/vitamins_included/rules.mk b/keyboards/vitamins_included/rules.mk
new file mode 100644
index 000000000..786f247bd
--- /dev/null
+++ b/keyboards/vitamins_included/rules.mk
@@ -0,0 +1,75 @@
1SRC += matrix.c \
2 i2c.c \
3 split_util.c \
4 serial.c \
5 ssd1306.c
6
7# MCU name
8MCU = atmega32u4
9
10# Processor frequency.
11# This will define a symbol, F_CPU, in all source code files equal to the
12# processor frequency in Hz. You can then use this symbol in your source code to
13# calculate timings. Do NOT tack on a 'UL' at the end, this will be done
14# automatically to create a 32-bit value in your source code.
15#
16# This will be an integer division of F_USB below, as it is sourced by
17# F_USB after it has run through any CPU prescalers. Note that this value
18# does not *change* the processor frequency - it should merely be updated to
19# reflect the processor speed set externally so that the code can use accurate
20# software delays.
21F_CPU = 16000000
22
23#
24# LUFA specific
25#
26# Target architecture (see library "Board Types" documentation).
27ARCH = AVR8
28
29# Input clock frequency.
30# This will define a symbol, F_USB, in all source code files equal to the
31# input clock frequency (before any prescaling is performed) in Hz. This value may
32# differ from F_CPU if prescaling is used on the latter, and is required as the
33# raw input clock is fed directly to the PLL sections of the AVR for high speed
34# clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL'
35# at the end, this will be done automatically to create a 32-bit value in your
36# source code.
37#
38# If no clock division is performed on the input clock inside the AVR (via the
39# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU.
40F_USB = $(F_CPU)
41
42# Bootloader
43# This definition is optional, and if your keyboard supports multiple bootloaders of
44# different sizes, comment this out, and the correct address will be loaded
45# automatically (+60). See bootloader.mk for all options.
46BOOTLOADER = caterina
47
48# Interrupt driven control endpoint task(+60)
49OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
50
51# Build Options
52# change to "no" to disable the options, or define them in the Makefile in
53# the appropriate keymap folder that will get included automatically
54#
55BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration(+1000)
56MOUSEKEY_ENABLE = yes # Mouse keys(+4700)
57EXTRAKEY_ENABLE = yes # Audio control and System control(+450)
58CONSOLE_ENABLE = no # Console for debug(+400)
59COMMAND_ENABLE = yes # Commands for debug and configuration
60NKRO_ENABLE = no # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
61BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality
62MIDI_ENABLE = no # MIDI controls
63AUDIO_ENABLE = no # Audio output on port C6
64UNICODE_ENABLE = no # Unicode
65BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID
66RGBLIGHT_ENABLE = no # Enable WS2812 RGB underlight. Do not enable this with audio at the same time.
67USE_I2C = no
68# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
69SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
70
71CUSTOM_MATRIX = yes
72
73LAYOUTS = ortho_4x12
74
75DEFAULT_FOLDER = vitamins_included/rev1
diff --git a/keyboards/vitamins_included/serial.c b/keyboards/vitamins_included/serial.c
new file mode 100644
index 000000000..4d37eeb8d
--- /dev/null
+++ b/keyboards/vitamins_included/serial.c
@@ -0,0 +1,229 @@
1/*
2 * WARNING: be careful changing this code, it is very timing dependent
3 */
4
5#ifndef F_CPU
6#define F_CPU 16000000
7#endif
8
9#include <avr/io.h>
10#include <avr/interrupt.h>
11#include <util/delay.h>
12#include <stdbool.h>
13#include "serial.h"
14
15#ifndef USE_I2C
16
17// Serial pulse period in microseconds. Its probably a bad idea to lower this
18// value.
19#define SERIAL_DELAY 24
20
21uint8_t volatile serial_slave_buffer[SERIAL_SLAVE_BUFFER_LENGTH] = {0};
22uint8_t volatile serial_master_buffer[SERIAL_MASTER_BUFFER_LENGTH] = {0};
23
24#define SLAVE_DATA_CORRUPT (1<<0)
25volatile uint8_t status = 0;
26
27inline static
28void serial_delay(void) {
29 _delay_us(SERIAL_DELAY);
30}
31
32inline static
33void serial_output(void) {
34 SERIAL_PIN_DDR |= SERIAL_PIN_MASK;
35}
36
37// make the serial pin an input with pull-up resistor
38inline static
39void serial_input(void) {
40 SERIAL_PIN_DDR &= ~SERIAL_PIN_MASK;
41 SERIAL_PIN_PORT |= SERIAL_PIN_MASK;
42}
43
44inline static
45uint8_t serial_read_pin(void) {
46 return !!(SERIAL_PIN_INPUT & SERIAL_PIN_MASK);
47}
48
49inline static
50void serial_low(void) {
51 SERIAL_PIN_PORT &= ~SERIAL_PIN_MASK;
52}
53
54inline static
55void serial_high(void) {
56 SERIAL_PIN_PORT |= SERIAL_PIN_MASK;
57}
58
59void serial_master_init(void) {
60 serial_output();
61 serial_high();
62}
63
64void serial_slave_init(void) {
65 serial_input();
66
67 // Enable INT0
68 EIMSK |= _BV(INT0);
69 // Trigger on falling edge of INT0
70 EICRA &= ~(_BV(ISC00) | _BV(ISC01));
71}
72
73// Used by the master to synchronize timing with the slave.
74static
75void sync_recv(void) {
76 serial_input();
77 // This shouldn't hang if the slave disconnects because the
78 // serial line will float to high if the slave does disconnect.
79 while (!serial_read_pin());
80 serial_delay();
81}
82
83// Used by the slave to send a synchronization signal to the master.
84static
85void sync_send(void) {
86 serial_output();
87
88 serial_low();
89 serial_delay();
90
91 serial_high();
92}
93
94// Reads a byte from the serial line
95static
96uint8_t serial_read_byte(void) {
97 uint8_t byte = 0;
98 serial_input();
99 for ( uint8_t i = 0; i < 8; ++i) {
100 byte = (byte << 1) | serial_read_pin();
101 serial_delay();
102 _delay_us(1);
103 }
104
105 return byte;
106}
107
108// Sends a byte with MSB ordering
109static
110void serial_write_byte(uint8_t data) {
111 uint8_t b = 8;
112 serial_output();
113 while( b-- ) {
114 if(data & (1 << b)) {
115 serial_high();
116 } else {
117 serial_low();
118 }
119 serial_delay();
120 }
121}
122
123// interrupt handle to be used by the slave device
124ISR(SERIAL_PIN_INTERRUPT) {
125 sync_send();
126
127 uint8_t checksum = 0;
128 for (int i = 0; i < SERIAL_SLAVE_BUFFER_LENGTH; ++i) {
129 serial_write_byte(serial_slave_buffer[i]);
130 sync_send();
131 checksum += serial_slave_buffer[i];
132 }
133 serial_write_byte(checksum);
134 sync_send();
135
136 // wait for the sync to finish sending
137 serial_delay();
138
139 // read the middle of pulses
140 _delay_us(SERIAL_DELAY/2);
141
142 uint8_t checksum_computed = 0;
143 for (int i = 0; i < SERIAL_MASTER_BUFFER_LENGTH; ++i) {
144 serial_master_buffer[i] = serial_read_byte();
145 sync_send();
146 checksum_computed += serial_master_buffer[i];
147 }
148 uint8_t checksum_received = serial_read_byte();
149 sync_send();
150
151 serial_input(); // end transaction
152
153 if ( checksum_computed != checksum_received ) {
154 status |= SLAVE_DATA_CORRUPT;
155 } else {
156 status &= ~SLAVE_DATA_CORRUPT;
157 }
158 contacted_by_master = true;
159}
160
161inline
162bool serial_slave_DATA_CORRUPT(void) {
163 return status & SLAVE_DATA_CORRUPT;
164}
165
166// Copies the serial_slave_buffer to the master and sends the
167// serial_master_buffer to the slave.
168//
169// Returns:
170// 0 => no error
171// 1 => slave did not respond
172int serial_update_buffers(void) {
173 // this code is very time dependent, so we need to disable interrupts
174 cli();
175
176 // signal to the slave that we want to start a transaction
177 serial_output();
178 serial_low();
179 _delay_us(1);
180
181 // wait for the slaves response
182 serial_input();
183 serial_high();
184 _delay_us(SERIAL_DELAY);
185
186 // check if the slave is present
187 if (serial_read_pin()) {
188 // slave failed to pull the line low, assume not present
189 sei();
190 return 1;
191 }
192
193 // if the slave is present syncronize with it
194 sync_recv();
195
196 uint8_t checksum_computed = 0;
197 // receive data from the slave
198 for (int i = 0; i < SERIAL_SLAVE_BUFFER_LENGTH; ++i) {
199 serial_slave_buffer[i] = serial_read_byte();
200 sync_recv();
201 checksum_computed += serial_slave_buffer[i];
202 }
203 uint8_t checksum_received = serial_read_byte();
204 sync_recv();
205
206 if (checksum_computed != checksum_received) {
207 sei();
208 return 1;
209 }
210
211 uint8_t checksum = 0;
212 // send data to the slave
213 for (int i = 0; i < SERIAL_MASTER_BUFFER_LENGTH; ++i) {
214 serial_write_byte(serial_master_buffer[i]);
215 sync_recv();
216 checksum += serial_master_buffer[i];
217 }
218 serial_write_byte(checksum);
219 sync_recv();
220
221 // always, release the line when not in use
222 serial_output();
223 serial_high();
224
225 sei();
226 return 0;
227}
228
229#endif
diff --git a/keyboards/vitamins_included/serial.h b/keyboards/vitamins_included/serial.h
new file mode 100644
index 000000000..ade7620b7
--- /dev/null
+++ b/keyboards/vitamins_included/serial.h
@@ -0,0 +1,27 @@
1#ifndef MY_SERIAL_H
2#define MY_SERIAL_H
3
4#include "config.h"
5#include <stdbool.h>
6#include "split_util.h"
7
8/* TODO: some defines for interrupt setup */
9#define SERIAL_PIN_DDR DDRD
10#define SERIAL_PIN_PORT PORTD
11#define SERIAL_PIN_INPUT PIND
12#define SERIAL_PIN_MASK _BV(PD0)
13#define SERIAL_PIN_INTERRUPT INT0_vect
14
15#define SERIAL_SLAVE_BUFFER_LENGTH MATRIX_ROWS/2
16#define SERIAL_MASTER_BUFFER_LENGTH 1
17
18// Buffers for master - slave communication
19extern volatile uint8_t serial_slave_buffer[SERIAL_SLAVE_BUFFER_LENGTH];
20extern volatile uint8_t serial_master_buffer[SERIAL_MASTER_BUFFER_LENGTH];
21
22void serial_master_init(void);
23void serial_slave_init(void);
24int serial_update_buffers(void);
25bool serial_slave_data_corrupt(void);
26
27#endif
diff --git a/keyboards/vitamins_included/split_util.c b/keyboards/vitamins_included/split_util.c
new file mode 100644
index 000000000..b86ad137b
--- /dev/null
+++ b/keyboards/vitamins_included/split_util.c
@@ -0,0 +1,20 @@
1#include <avr/io.h>
2#include <avr/wdt.h>
3#include <avr/power.h>
4#include <avr/interrupt.h>
5#include <util/delay.h>
6#include <avr/eeprom.h>
7#include "split_util.h"
8#include "matrix.h"
9#include "keyboard.h"
10#include "config.h"
11#include "timer.h"
12#include "debug.h"
13
14volatile bool isLeftHand = true;
15volatile bool contacted_by_master = false;
16
17// this code runs before the usb and keyboard is initialized
18void matrix_setup(void) {
19 isLeftHand = eeprom_read_byte(EECONFIG_HANDEDNESS);
20}
diff --git a/keyboards/vitamins_included/split_util.h b/keyboards/vitamins_included/split_util.h
new file mode 100644
index 000000000..5acf386e4
--- /dev/null
+++ b/keyboards/vitamins_included/split_util.h
@@ -0,0 +1,18 @@
1#ifndef SPLIT_KEYBOARD_UTIL_H
2#define SPLIT_KEYBOARD_UTIL_H
3
4#include <stdbool.h>
5#include "eeconfig.h"
6
7#define SLAVE_I2C_ADDRESS 0x32
8
9extern volatile bool isLeftHand;
10extern volatile bool contacted_by_master;
11
12bool has_usb(void);
13
14// slave version of matix scan, defined in matrix.c
15void matrix_slave_scan(void);
16
17
18#endif
diff --git a/keyboards/vitamins_included/vitamins_included.c b/keyboards/vitamins_included/vitamins_included.c
new file mode 100644
index 000000000..650f26001
--- /dev/null
+++ b/keyboards/vitamins_included/vitamins_included.c
@@ -0,0 +1,16 @@
1#include QMK_KEYBOARD_H
2
3#ifdef ONEHAND_ENABLE
4__attribute__ ((weak))
5const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = {
6
7 {{0, 4}, {1, 4}, {2, 4}, {3, 4}, {4, 4}, {5, 4}},
8 {{0, 5}, {1, 5}, {2, 5}, {3, 5}, {4, 5}, {5, 5}},
9 {{0, 6}, {1, 6}, {2, 6}, {3, 6}, {4, 6}, {5, 6}},
10 {{0, 7}, {1, 7}, {2, 7}, {3, 7}, {4, 7}, {5, 7}},
11 {{0, 0}, {1, 0}, {2, 0}, {3, 0}, {4, 0}, {5, 0}},
12 {{0, 1}, {1, 1}, {2, 1}, {3, 1}, {4, 1}, {5, 1}},
13 {{0, 2}, {1, 2}, {2, 2}, {3, 2}, {4, 2}, {5, 2}},
14 {{0, 3}, {1, 3}, {2, 3}, {3, 3}, {4, 3}, {5, 3}},
15};
16#endif
diff --git a/keyboards/vitamins_included/vitamins_included.h b/keyboards/vitamins_included/vitamins_included.h
new file mode 100644
index 000000000..b5fbd5294
--- /dev/null
+++ b/keyboards/vitamins_included/vitamins_included.h
@@ -0,0 +1,25 @@
1#ifndef VITAMINS_INCLUDED_H
2#define VITAMINS_INCLUDED_H
3
4#include "quantum.h"
5
6#include "rev1.h"
7
8
9// Used to create a keymap using only KC_ prefixed keys
10#define KC_KEYMAP( \
11 L00, L01, L02, L03, L04, L05, R00, R01, R02, R03, R04, R05, \
12 L10, L11, L12, L13, L14, L15, R10, R11, R12, R13, R14, R15, \
13 L20, L21, L22, L23, L24, L25, R20, R21, R22, R23, R24, R25, \
14 L30, L31, L32, L33, L34, L35, R30, R31, R32, R33, R34, R35 \
15 ) \
16 KEYMAP( \
17 KC_##L00, KC_##L01, KC_##L02, KC_##L03, KC_##L04, KC_##L05, KC_##R00, KC_##R01, KC_##R02, KC_##R03, KC_##R04, KC_##R05, \
18 KC_##L10, KC_##L11, KC_##L12, KC_##L13, KC_##L14, KC_##L15, KC_##R10, KC_##R11, KC_##R12, KC_##R13, KC_##R14, KC_##R15, \
19 KC_##L20, KC_##L21, KC_##L22, KC_##L23, KC_##L24, KC_##L25, KC_##R20, KC_##R21, KC_##R22, KC_##R23, KC_##R24, KC_##R25, \
20 KC_##L30, KC_##L31, KC_##L32, KC_##L33, KC_##L34, KC_##L35, KC_##R30, KC_##R31, KC_##R32, KC_##R33, KC_##R34, KC_##R35 \
21 )
22
23#define KC_LAYOUT_ortho_4x12 KC_KEYMAP
24
25#endif