aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorai03 <sarcaphx510@gmail.com>2019-03-10 19:57:36 -0700
committerDrashna Jaelre <drashna@live.com>2019-03-10 19:57:36 -0700
commit9bea41c9b239916ae8786e7df02c29fad79ef459 (patch)
treeb9b4b3cdacd87156ebc29e70a79e846cb32e8679
parentad12acd3c049e1eef02ac21bb749eda375e09cec (diff)
downloadqmk_firmware-9bea41c9b239916ae8786e7df02c29fad79ef459.tar.gz
qmk_firmware-9bea41c9b239916ae8786e7df02c29fad79ef459.zip
[Keyboard] Add Orbit keyboard (#5306)
* Get things working except indicators * Attempt to get things working * hmm * Compiles but doesn't run * Make data transfer work * Get all indicators working * Remove old transport * Prepare for pullreq * Revert keymap from testing to production * Final error checking for pull request * Remove autogenerated is_command from config.h * Rewrite pin toggles using qmk functions
-rw-r--r--keyboards/ai03/orbit/config.h249
-rw-r--r--keyboards/ai03/orbit/info.json0
-rw-r--r--keyboards/ai03/orbit/keymaps/default/keymap.c91
-rw-r--r--keyboards/ai03/orbit/keymaps/default/readme.md3
-rw-r--r--keyboards/ai03/orbit/matrix.c328
-rw-r--r--keyboards/ai03/orbit/matrix.h3
-rw-r--r--keyboards/ai03/orbit/orbit.c228
-rw-r--r--keyboards/ai03/orbit/orbit.h65
-rw-r--r--keyboards/ai03/orbit/readme.md15
-rw-r--r--keyboards/ai03/orbit/rules.mk92
-rw-r--r--keyboards/ai03/orbit/serial.c546
-rw-r--r--keyboards/ai03/orbit/serial.h62
-rw-r--r--keyboards/ai03/orbit/split_flags.c5
-rw-r--r--keyboards/ai03/orbit/split_flags.h15
-rw-r--r--keyboards/ai03/orbit/split_util.c87
-rw-r--r--keyboards/ai03/orbit/split_util.h10
-rw-r--r--keyboards/ai03/orbit/transport.c238
-rw-r--r--keyboards/ai03/orbit/transport.h42
18 files changed, 2079 insertions, 0 deletions
diff --git a/keyboards/ai03/orbit/config.h b/keyboards/ai03/orbit/config.h
new file mode 100644
index 000000000..f4dc4fd63
--- /dev/null
+++ b/keyboards/ai03/orbit/config.h
@@ -0,0 +1,249 @@
1/*
2Copyright 2018 Ryota Goto
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#pragma once
19
20#include "config_common.h"
21
22/* USB Device descriptor parameter */
23#define VENDOR_ID 0xA103
24#define PRODUCT_ID 0x0003
25#define DEVICE_VER 0x0003
26#define MANUFACTURER ai03 Keyboard Designs
27#define PRODUCT Orbit
28#define DESCRIPTION Split ergonomic keyboard
29
30/* key matrix size */
31#define MATRIX_ROWS 10 // Double rows for split keyboards. Orbit has 5, so define 10
32#define MATRIX_COLS 7
33
34/*
35 * Keyboard Matrix Assignments
36 *
37 * Change this to how you wired your keyboard
38 * COLS: AVR pins used for columns, left to right
39 * ROWS: AVR pins used for rows, top to bottom
40 * DIODE_DIRECTION: COL2ROW = COL = Anode (+), ROW = Cathode (-, marked on diode)
41 * ROW2COL = ROW = Anode (+), COL = Cathode (-, marked on diode)
42 *
43*/
44#define MATRIX_ROW_PINS { F7, F6, F5, F4, D3 }
45#define MATRIX_COL_PINS { C7, B4, D7, D6, D4, F1, F0 }
46#define MATRIX_ROW_PINS_RIGHT { B6, B5, B4, D7, E6 }
47#define MATRIX_COL_PINS_RIGHT { D4, D6, F1, F0, F4, F5, C6 }
48
49#define SPLIT_HAND_PIN D5
50
51//#define USE_I2C
52
53#define SELECT_SOFT_SERIAL_SPEED 1
54
55#define UNUSED_PINS
56
57/* COL2ROW, ROW2COL, or CUSTOM_MATRIX */
58#define DIODE_DIRECTION COL2ROW
59
60/*
61 * Split Keyboard specific options, make sure you have 'SPLIT_KEYBOARD = yes' in your rules.mk, and define SOFT_SERIAL_PIN.
62 */
63#define SOFT_SERIAL_PIN D0 // or D1, D2, D3, E6
64
65#define BACKLIGHT_PIN B7
66// #define BACKLIGHT_BREATHING
67#define BACKLIGHT_LEVELS 3
68
69// #define RGB_DI_PIN E2
70// #ifdef RGB_DI_PIN
71// #define RGBLED_NUM 16
72// #define RGBLIGHT_HUE_STEP 8
73// #define RGBLIGHT_SAT_STEP 8
74// #define RGBLIGHT_VAL_STEP 8
75// #define RGBLIGHT_LIMIT_VAL 255 /* The maximum brightness level */
76// #define RGBLIGHT_SLEEP /* If defined, the RGB lighting will be switched off when the host goes to sleep */
77// /*== all animations enable ==*/
78// #define RGBLIGHT_ANIMATIONS
79// /*== or choose animations ==*/
80// #define RGBLIGHT_EFFECT_BREATHING
81// #define RGBLIGHT_EFFECT_RAINBOW_MOOD
82// #define RGBLIGHT_EFFECT_RAINBOW_SWIRL
83// #define RGBLIGHT_EFFECT_SNAKE
84// #define RGBLIGHT_EFFECT_KNIGHT
85// #define RGBLIGHT_EFFECT_CHRISTMAS
86// #define RGBLIGHT_EFFECT_STATIC_GRADIENT
87// #define RGBLIGHT_EFFECT_RGB_TEST
88// #define RGBLIGHT_EFFECT_ALTERNATING
89// #endif
90
91/* Debounce reduces chatter (unintended double-presses) - set 0 if debouncing is not needed */
92#define DEBOUNCING_DELAY 5
93
94/* define if matrix has ghost (lacks anti-ghosting diodes) */
95//#define MATRIX_HAS_GHOST
96
97/* number of backlight levels */
98
99/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
100#define LOCKING_SUPPORT_ENABLE
101/* Locking resynchronize hack */
102#define LOCKING_RESYNC_ENABLE
103
104/* If defined, GRAVE_ESC will always act as ESC when CTRL is held.
105 * This is userful for the Windows task manager shortcut (ctrl+shift+esc).
106 */
107// #define GRAVE_ESC_CTRL_OVERRIDE
108
109/*
110 * Force NKRO
111 *
112 * Force NKRO (nKey Rollover) to be enabled by default, regardless of the saved
113 * state in the bootmagic EEPROM settings. (Note that NKRO must be enabled in the
114 * makefile for this to work.)
115 *
116 * If forced on, NKRO can be disabled via magic key (default = LShift+RShift+N)
117 * until the next keyboard reset.
118 *
119 * NKRO may prevent your keystrokes from being detected in the BIOS, but it is
120 * fully operational during normal computer usage.
121 *
122 * For a less heavy-handed approach, enable NKRO via magic key (LShift+RShift+N)
123 * or via bootmagic (hold SPACE+N while plugging in the keyboard). Once set by
124 * bootmagic, NKRO mode will always be enabled until it is toggled again during a
125 * power-up.
126 *
127 */
128//#define FORCE_NKRO
129
130/*
131 * Magic Key Options
132 *
133 * Magic keys are hotkey commands that allow control over firmware functions of
134 * the keyboard. They are best used in combination with the HID Listen program,
135 * found here: https://www.pjrc.com/teensy/hid_listen.html
136 *
137 * The options below allow the magic key functionality to be changed. This is
138 * useful if your keyboard/keypad is missing keys and you want magic key support.
139 *
140 */
141
142/* control how magic key switches layers */
143//#define MAGIC_KEY_SWITCH_LAYER_WITH_FKEYS true
144//#define MAGIC_KEY_SWITCH_LAYER_WITH_NKEYS true
145//#define MAGIC_KEY_SWITCH_LAYER_WITH_CUSTOM false
146
147/* override magic key keymap */
148//#define MAGIC_KEY_SWITCH_LAYER_WITH_FKEYS
149//#define MAGIC_KEY_SWITCH_LAYER_WITH_NKEYS
150//#define MAGIC_KEY_SWITCH_LAYER_WITH_CUSTOM
151//#define MAGIC_KEY_HELP1 H
152//#define MAGIC_KEY_HELP2 SLASH
153//#define MAGIC_KEY_DEBUG D
154//#define MAGIC_KEY_DEBUG_MATRIX X
155//#define MAGIC_KEY_DEBUG_KBD K
156//#define MAGIC_KEY_DEBUG_MOUSE M
157//#define MAGIC_KEY_VERSION V
158//#define MAGIC_KEY_STATUS S
159//#define MAGIC_KEY_CONSOLE C
160//#define MAGIC_KEY_LAYER0_ALT1 ESC
161//#define MAGIC_KEY_LAYER0_ALT2 GRAVE
162//#define MAGIC_KEY_LAYER0 0
163//#define MAGIC_KEY_LAYER1 1
164//#define MAGIC_KEY_LAYER2 2
165//#define MAGIC_KEY_LAYER3 3
166//#define MAGIC_KEY_LAYER4 4
167//#define MAGIC_KEY_LAYER5 5
168//#define MAGIC_KEY_LAYER6 6
169//#define MAGIC_KEY_LAYER7 7
170//#define MAGIC_KEY_LAYER8 8
171//#define MAGIC_KEY_LAYER9 9
172//#define MAGIC_KEY_BOOTLOADER PAUSE
173//#define MAGIC_KEY_LOCK CAPS
174//#define MAGIC_KEY_EEPROM E
175//#define MAGIC_KEY_NKRO N
176//#define MAGIC_KEY_SLEEP_LED Z
177
178/*
179 * Feature disable options
180 * These options are also useful to firmware size reduction.
181 */
182
183/* disable debug print */
184//#define NO_DEBUG
185
186/* disable print */
187//#define NO_PRINT
188
189/* disable action features */
190//#define NO_ACTION_LAYER
191//#define NO_ACTION_TAPPING
192//#define NO_ACTION_ONESHOT
193//#define NO_ACTION_MACRO
194//#define NO_ACTION_FUNCTION
195
196/*
197 * MIDI options
198 */
199
200/* Prevent use of disabled MIDI features in the keymap */
201//#define MIDI_ENABLE_STRICT 1
202
203/* enable basic MIDI features:
204 - MIDI notes can be sent when in Music mode is on
205*/
206//#define MIDI_BASIC
207
208/* enable advanced MIDI features:
209 - MIDI notes can be added to the keymap
210 - Octave shift and transpose
211 - Virtual sustain, portamento, and modulation wheel
212 - etc.
213*/
214//#define MIDI_ADVANCED
215
216/* override number of MIDI tone keycodes (each octave adds 12 keycodes and allocates 12 bytes) */
217//#define MIDI_TONE_KEYCODE_OCTAVES 1
218
219/*
220 * HD44780 LCD Display Configuration
221 */
222/*
223#define LCD_LINES 2 //< number of visible lines of the display
224#define LCD_DISP_LENGTH 16 //< visibles characters per line of the display
225
226#define LCD_IO_MODE 1 //< 0: memory mapped mode, 1: IO port mode
227
228#if LCD_IO_MODE
229#define LCD_PORT PORTB //< port for the LCD lines
230#define LCD_DATA0_PORT LCD_PORT //< port for 4bit data bit 0
231#define LCD_DATA1_PORT LCD_PORT //< port for 4bit data bit 1
232#define LCD_DATA2_PORT LCD_PORT //< port for 4bit data bit 2
233#define LCD_DATA3_PORT LCD_PORT //< port for 4bit data bit 3
234#define LCD_DATA0_PIN 4 //< pin for 4bit data bit 0
235#define LCD_DATA1_PIN 5 //< pin for 4bit data bit 1
236#define LCD_DATA2_PIN 6 //< pin for 4bit data bit 2
237#define LCD_DATA3_PIN 7 //< pin for 4bit data bit 3
238#define LCD_RS_PORT LCD_PORT //< port for RS line
239#define LCD_RS_PIN 3 //< pin for RS line
240#define LCD_RW_PORT LCD_PORT //< port for RW line
241#define LCD_RW_PIN 2 //< pin for RW line
242#define LCD_E_PORT LCD_PORT //< port for Enable line
243#define LCD_E_PIN 1 //< pin for Enable line
244#endif
245*/
246
247/* Bootmagic Lite key configuration */
248// #define BOOTMAGIC_LITE_ROW 0
249// #define BOOTMAGIC_LITE_COLUMN 0
diff --git a/keyboards/ai03/orbit/info.json b/keyboards/ai03/orbit/info.json
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/keyboards/ai03/orbit/info.json
diff --git a/keyboards/ai03/orbit/keymaps/default/keymap.c b/keyboards/ai03/orbit/keymaps/default/keymap.c
new file mode 100644
index 000000000..4c8c39fb0
--- /dev/null
+++ b/keyboards/ai03/orbit/keymaps/default/keymap.c
@@ -0,0 +1,91 @@
1/* Copyright 2018 Ryota Goto
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16#include QMK_KEYBOARD_H
17
18// Defines the keycodes used by our macros in process_record_user
19enum custom_keycodes {
20 MANUAL = SAFE_RANGE,
21 DBLZERO
22};
23
24const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
25 [0] = LAYOUT( /* Base */
26 TO(1), KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_LBRC, KC_BSPC, \
27 TO(1), KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_RBRC, KC_BSLS, \
28 KC_NO, KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT, \
29 KC_NO, KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_PSCR, KC_DEL, \
30 KC_LCTL, KC_LCTL, KC_LGUI, KC_LALT, MO(1), KC_SPC, KC_SPC, MO(2), KC_GRV, KC_MENU, KC_MINS, KC_EQL
31 ),
32 [1] = LAYOUT( /* Fn, Arrowkeys, Media control, Backlight */
33 TO(2), _______, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_VOLU, _______, \
34 TO(2), _______, _______, KC_PGUP, _______, _______, KC_F11, KC_F12, _______, KC_UP, _______, _______, KC_VOLD, BL_STEP, \
35 TO(0), _______, KC_HOME, KC_PGDN, KC_END, _______, _______, _______, KC_LEFT, KC_DOWN, KC_RGHT, _______, KC_MPLY, _______, \
36 TO(0), _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_INS, \
37 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______
38 ),
39 [2] = LAYOUT( /* Mousekeys and Numpad */
40 KC_NO, _______, _______, _______, _______, _______, _______, KC_NLCK, KC_P7, KC_P8, KC_P9, KC_PSLS, _______, _______, \
41 KC_NO, _______, KC_BTN1, KC_MS_U, KC_BTN2, KC_WH_U, _______, _______, KC_P4, KC_P5, KC_P6, KC_PAST, _______, _______, \
42 TO(1), _______, KC_MS_L, KC_MS_D, KC_MS_R, KC_WH_D, _______, _______, KC_P1, KC_P2, KC_P3, KC_PMNS, _______, _______, \
43 TO(1), _______, KC_ACL0, KC_ACL1, KC_ACL2, KC_BTN3, _______, DBLZERO, KC_P0, KC_PDOT, KC_PENT, KC_PPLS, _______, MANUAL, \
44 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______
45 )
46};
47
48bool process_record_user(uint16_t keycode, keyrecord_t *record) {
49 switch (keycode) {
50 case MANUAL:
51 if (record->event.pressed)
52 {
53 // Keypress
54 SEND_STRING("https://kb.ai03.me/redir/orbit");
55 }
56 else
57 {
58 // Key release
59 }
60 break;
61 case DBLZERO:
62 if (record->event.pressed)
63 {
64 // Keypress
65 SEND_STRING("00");
66 }
67 else
68 {
69 // Key release
70 }
71 break;
72 }
73 return true;
74}
75
76void matrix_init_user(void) {
77
78}
79
80void matrix_scan_user(void) {
81
82}
83
84void led_set_user(uint8_t usb_led) {
85
86}
87
88uint32_t layer_state_set_user(uint32_t state) {
89
90 return state;
91}
diff --git a/keyboards/ai03/orbit/keymaps/default/readme.md b/keyboards/ai03/orbit/keymaps/default/readme.md
new file mode 100644
index 000000000..63c528abf
--- /dev/null
+++ b/keyboards/ai03/orbit/keymaps/default/readme.md
@@ -0,0 +1,3 @@
1# The default keymap for Orbit
2
3[KLE of layout](http://www.keyboard-layout-editor.com/#/gists/53ebf59524de12515cb7e2e6de94f0d6) \ No newline at end of file
diff --git a/keyboards/ai03/orbit/matrix.c b/keyboards/ai03/orbit/matrix.c
new file mode 100644
index 000000000..a1509666c
--- /dev/null
+++ b/keyboards/ai03/orbit/matrix.c
@@ -0,0 +1,328 @@
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 "wait.h"
24#include "util.h"
25#include "matrix.h"
26#include "split_util.h"
27#include "config.h"
28#include "split_flags.h"
29#include "quantum.h"
30#include "debounce.h"
31#include "transport.h"
32
33#if (MATRIX_COLS <= 8)
34# define print_matrix_header() print("\nr/c 01234567\n")
35# define print_matrix_row(row) print_bin_reverse8(matrix_get_row(row))
36# define matrix_bitpop(i) bitpop(matrix[i])
37# define ROW_SHIFTER ((uint8_t)1)
38#elif (MATRIX_COLS <= 16)
39# define print_matrix_header() print("\nr/c 0123456789ABCDEF\n")
40# define print_matrix_row(row) print_bin_reverse16(matrix_get_row(row))
41# define matrix_bitpop(i) bitpop16(matrix[i])
42# define ROW_SHIFTER ((uint16_t)1)
43#elif (MATRIX_COLS <= 32)
44# define print_matrix_header() print("\nr/c 0123456789ABCDEF0123456789ABCDEF\n")
45# define print_matrix_row(row) print_bin_reverse32(matrix_get_row(row))
46# define matrix_bitpop(i) bitpop32(matrix[i])
47# define ROW_SHIFTER ((uint32_t)1)
48#endif
49
50#define ERROR_DISCONNECT_COUNT 5
51
52//#define ROWS_PER_HAND (MATRIX_ROWS / 2)
53
54#ifdef DIRECT_PINS
55static pin_t direct_pins[MATRIX_ROWS][MATRIX_COLS] = DIRECT_PINS;
56#else
57static pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
58static pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
59#endif
60
61/* matrix state(1:on, 0:off) */
62static matrix_row_t matrix[MATRIX_ROWS];
63static matrix_row_t raw_matrix[ROWS_PER_HAND];
64
65// row offsets for each hand
66uint8_t thisHand, thatHand;
67
68// user-defined overridable functions
69
70__attribute__((weak)) void matrix_init_kb(void) { matrix_init_user(); }
71
72__attribute__((weak)) void matrix_scan_kb(void) { matrix_scan_user(); }
73
74__attribute__((weak)) void matrix_init_user(void) {}
75
76__attribute__((weak)) void matrix_scan_user(void) {}
77
78__attribute__((weak)) void matrix_slave_scan_user(void) {}
79
80// helper functions
81
82inline uint8_t matrix_rows(void) { return MATRIX_ROWS; }
83
84inline uint8_t matrix_cols(void) { return MATRIX_COLS; }
85
86bool matrix_is_modified(void) {
87 if (debounce_active()) return false;
88 return true;
89}
90
91inline bool matrix_is_on(uint8_t row, uint8_t col) { return (matrix[row] & ((matrix_row_t)1 << col)); }
92
93inline matrix_row_t matrix_get_row(uint8_t row) { return matrix[row]; }
94
95void matrix_print(void) {
96 print_matrix_header();
97
98 for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
99 phex(row);
100 print(": ");
101 print_matrix_row(row);
102 print("\n");
103 }
104}
105
106uint8_t matrix_key_count(void) {
107 uint8_t count = 0;
108 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
109 count += matrix_bitpop(i);
110 }
111 return count;
112}
113
114// matrix code
115
116#ifdef DIRECT_PINS
117
118static void init_pins(void) {
119 for (int row = 0; row < MATRIX_ROWS; row++) {
120 for (int col = 0; col < MATRIX_COLS; col++) {
121 pin_t pin = direct_pins[row][col];
122 if (pin != NO_PIN) {
123 setPinInputHigh(pin);
124 }
125 }
126 }
127}
128
129static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) {
130 matrix_row_t last_row_value = current_matrix[current_row];
131 current_matrix[current_row] = 0;
132
133 for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) {
134 pin_t pin = direct_pins[current_row][col_index];
135 if (pin != NO_PIN) {
136 current_matrix[current_row] |= readPin(pin) ? 0 : (ROW_SHIFTER << col_index);
137 }
138 }
139
140 return (last_row_value != current_matrix[current_row]);
141}
142
143#elif (DIODE_DIRECTION == COL2ROW)
144
145static void select_row(uint8_t row) {
146 setPinOutput(row_pins[row]);
147 writePinLow(row_pins[row]);
148}
149
150static void unselect_row(uint8_t row) { setPinInputHigh(row_pins[row]); }
151
152static void unselect_rows(void) {
153 for (uint8_t x = 0; x < ROWS_PER_HAND; x++) {
154 setPinInputHigh(row_pins[x]);
155 }
156}
157
158static void init_pins(void) {
159 unselect_rows();
160 for (uint8_t x = 0; x < MATRIX_COLS; x++) {
161 setPinInputHigh(col_pins[x]);
162 }
163}
164
165static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) {
166 // Store last value of row prior to reading
167 matrix_row_t last_row_value = current_matrix[current_row];
168
169 // Clear data in matrix row
170 current_matrix[current_row] = 0;
171
172 // Select row and wait for row selecton to stabilize
173 select_row(current_row);
174 wait_us(30);
175
176 // For each col...
177 for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) {
178 // Populate the matrix row with the state of the col pin
179 current_matrix[current_row] |= readPin(col_pins[col_index]) ? 0 : (ROW_SHIFTER << col_index);
180 }
181
182 // Unselect row
183 unselect_row(current_row);
184
185 return (last_row_value != current_matrix[current_row]);
186}
187
188#elif (DIODE_DIRECTION == ROW2COL)
189
190static void select_col(uint8_t col) {
191 setPinOutput(col_pins[col]);
192 writePinLow(col_pins[col]);
193}
194
195static void unselect_col(uint8_t col) { setPinInputHigh(col_pins[col]); }
196
197static void unselect_cols(void) {
198 for (uint8_t x = 0; x < MATRIX_COLS; x++) {
199 setPinInputHigh(col_pins[x]);
200 }
201}
202
203static void init_pins(void) {
204 unselect_cols();
205 for (uint8_t x = 0; x < ROWS_PER_HAND; x++) {
206 setPinInputHigh(row_pins[x]);
207 }
208}
209
210static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) {
211 bool matrix_changed = false;
212
213 // Select col and wait for col selecton to stabilize
214 select_col(current_col);
215 wait_us(30);
216
217 // For each row...
218 for (uint8_t row_index = 0; row_index < ROWS_PER_HAND; row_index++) {
219 // Store last value of row prior to reading
220 matrix_row_t last_row_value = current_matrix[row_index];
221
222 // Check row pin state
223 if (readPin(row_pins[row_index])) {
224 // Pin HI, clear col bit
225 current_matrix[row_index] &= ~(ROW_SHIFTER << current_col);
226 } else {
227 // Pin LO, set col bit
228 current_matrix[row_index] |= (ROW_SHIFTER << current_col);
229 }
230
231 // Determine if the matrix changed state
232 if ((last_row_value != current_matrix[row_index]) && !(matrix_changed)) {
233 matrix_changed = true;
234 }
235 }
236
237 // Unselect col
238 unselect_col(current_col);
239
240 return matrix_changed;
241}
242
243#endif
244
245void matrix_init(void) {
246 debug_enable = true;
247 debug_matrix = true;
248 debug_mouse = true;
249
250 // Set pinout for right half if pinout for that half is defined
251 if (!isLeftHand) {
252#ifdef MATRIX_ROW_PINS_RIGHT
253 const uint8_t row_pins_right[MATRIX_ROWS] = MATRIX_ROW_PINS_RIGHT;
254 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
255 row_pins[i] = row_pins_right[i];
256 }
257#endif
258#ifdef MATRIX_COL_PINS_RIGHT
259 const uint8_t col_pins_right[MATRIX_COLS] = MATRIX_COL_PINS_RIGHT;
260 for (uint8_t i = 0; i < MATRIX_COLS; i++) {
261 col_pins[i] = col_pins_right[i];
262 }
263#endif
264 }
265
266 thisHand = isLeftHand ? 0 : (ROWS_PER_HAND);
267 thatHand = ROWS_PER_HAND - thisHand;
268
269 // initialize key pins
270 init_pins();
271
272 // initialize matrix state: all keys off
273 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
274 matrix[i] = 0;
275 }
276
277 debounce_init(ROWS_PER_HAND);
278
279 matrix_init_quantum();
280}
281
282uint8_t _matrix_scan(void) {
283 bool changed = false;
284
285#if defined(DIRECT_PINS) || (DIODE_DIRECTION == COL2ROW)
286 // Set row, read cols
287 for (uint8_t current_row = 0; current_row < ROWS_PER_HAND; current_row++) {
288 changed |= read_cols_on_row(raw_matrix, current_row);
289 }
290#elif (DIODE_DIRECTION == ROW2COL)
291 // Set col, read rows
292 for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) {
293 changed |= read_rows_on_col(raw_matrix, current_col);
294 }
295#endif
296
297 debounce(raw_matrix, matrix + thisHand, ROWS_PER_HAND, changed);
298
299 return 1;
300}
301
302uint8_t matrix_scan(void) {
303 uint8_t ret = _matrix_scan();
304
305 if (is_keyboard_master()) {
306 static uint8_t error_count;
307
308 if (!transport_master(matrix + thatHand)) {
309 error_count++;
310
311 if (error_count > ERROR_DISCONNECT_COUNT) {
312 // reset other half if disconnected
313 for (int i = 0; i < ROWS_PER_HAND; ++i) {
314 matrix[thatHand + i] = 0;
315 }
316 }
317 } else {
318 error_count = 0;
319 }
320
321 matrix_scan_quantum();
322 } else {
323 transport_slave(matrix + thisHand);
324 matrix_slave_scan_user();
325 }
326
327 return ret;
328}
diff --git a/keyboards/ai03/orbit/matrix.h b/keyboards/ai03/orbit/matrix.h
new file mode 100644
index 000000000..c2bdd3098
--- /dev/null
+++ b/keyboards/ai03/orbit/matrix.h
@@ -0,0 +1,3 @@
1#pragma once
2
3#include <common/matrix.h>
diff --git a/keyboards/ai03/orbit/orbit.c b/keyboards/ai03/orbit/orbit.c
new file mode 100644
index 000000000..2f149875b
--- /dev/null
+++ b/keyboards/ai03/orbit/orbit.c
@@ -0,0 +1,228 @@
1/* Copyright 2018 Ryota Goto
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16#include "orbit.h"
17#include "split_util.h"
18#include "transport.h"
19
20
21// Call led_toggle to set LEDs easily
22// LED IDs:
23//
24// (LEFT) 0 1 2 | 3 4 5 (RIGHT)
25
26void led_toggle(int id, bool on) {
27
28 if (isLeftHand) {
29 switch(id) {
30 case 0:
31 // Left hand C6
32 if (on)
33 //PORTC |= (1<<6);
34 writePinHigh(C6);
35 else
36 //PORTC &= ~(1<<6);
37 writePinLow(C6);
38 break;
39 case 1:
40 // Left hand B6
41 if (on)
42 //PORTB |= (1<<6);
43 writePinHigh(B6);
44 else
45 //PORTB &= ~(1<<6);
46 writePinLow(B6);
47 break;
48 case 2:
49 // Left hand B5
50 if (on)
51 //PORTB |= (1<<5);
52 writePinHigh(B5);
53 else
54 //PORTB &= ~(1<<5);
55 writePinLow(B5);
56 break;
57 default:
58 break;
59 }
60 } else {
61 switch(id) {
62 case 3:
63 // Right hand F6
64 if (on)
65 //PORTF |= (1<<6);
66 writePinHigh(F6);
67 else
68 //PORTF &= ~(1<<6);
69 writePinLow(F6);
70 break;
71 case 4:
72 // Right hand F7
73 if (on)
74 //PORTF |= (1<<7);
75 writePinHigh(F7);
76 else
77 //PORTF &= ~(1<<7);
78 writePinLow(F7);
79 break;
80 case 5:
81 // Right hand C7
82 if (on)
83 //PORTC |= (1<<7);
84 writePinHigh(C7);
85 else
86 //PORTC &= ~(1<<7);
87 writePinLow(C7);
88 break;
89 default:
90 break;
91 }
92 }
93}
94
95// Set all LEDs at once using an array of 6 booleans
96// LED IDs:
97//
98// (LEFT) 0 1 2 | 3 4 5 (RIGHT)
99//
100// Ex. set_all_leds({ false, false, false, true, true, true }) would turn off left hand, turn on right hand
101
102void set_all_leds(bool leds[6]) {
103 for (int i = 0; i < 6; i++) {
104 led_toggle(i, leds[i]);
105 }
106}
107
108void set_layer_indicators(uint8_t layer) {
109
110 switch (layer)
111 {
112 case 0:
113 led_toggle(0, true);
114 led_toggle(1, false);
115 led_toggle(2, false);
116 break;
117 case 1:
118 led_toggle(0, true);
119 led_toggle(1, true);
120 led_toggle(2, false);
121 break;
122 case 2:
123 led_toggle(0, true);
124 led_toggle(1, true);
125 led_toggle(2, true);
126 break;
127 case 3:
128 led_toggle(0, false);
129 led_toggle(1, true);
130 led_toggle(2, true);
131 break;
132 case 4:
133 led_toggle(0, false);
134 led_toggle(1, false);
135 led_toggle(2, true);
136 break;
137 default:
138 led_toggle(0, true);
139 led_toggle(1, false);
140 led_toggle(2, true);
141 break;
142 }
143
144}
145
146void matrix_init_kb(void) {
147 // put your keyboard start-up code here
148 // runs once when the firmware starts up
149
150 // Initialize indicator LEDs to output
151 if (isLeftHand)
152 {
153 setPinOutput(C6);
154 setPinOutput(B6);
155 setPinOutput(B5);
156 //DDRC |= (1<<6);
157 //DDRB |= (1<<6);
158 //DDRB |= (1<<5);
159 }
160 else
161 {
162 setPinOutput(F6);
163 setPinOutput(F7);
164 setPinOutput(C7);
165 //DDRF |= (1<<6);
166 //DDRF |= (1<<7);
167 //DDRC |= (1<<7);
168 }
169
170 set_layer_indicators(0);
171
172 matrix_init_user();
173}
174
175void matrix_scan_kb(void) {
176 // put your looping keyboard code here
177 // runs every cycle (a lot)
178
179 matrix_scan_user();
180}
181
182bool process_record_kb(uint16_t keycode, keyrecord_t *record) {
183 // put your per-action keyboard code here
184 // runs for every action, just before processing by the firmware
185
186 return process_record_user(keycode, record);
187}
188
189void led_set_kb(uint8_t usb_led) {
190 // put your keyboard LED indicator (ex: Caps Lock LED) toggling code here
191
192 if (is_keyboard_master()) {
193
194 serial_m2s_buffer.nlock_led = IS_LED_ON(usb_led, USB_LED_NUM_LOCK);
195 serial_m2s_buffer.clock_led = IS_LED_ON(usb_led, USB_LED_CAPS_LOCK);
196 serial_m2s_buffer.slock_led = IS_LED_ON(usb_led, USB_LED_SCROLL_LOCK);
197
198 led_toggle(3, IS_LED_ON(usb_led, USB_LED_NUM_LOCK));
199 led_toggle(4, IS_LED_ON(usb_led, USB_LED_CAPS_LOCK));
200 led_toggle(5, IS_LED_ON(usb_led, USB_LED_SCROLL_LOCK));
201
202 }
203
204 led_set_user(usb_led);
205}
206
207uint32_t layer_state_set_kb(uint32_t state) {
208
209 if (is_keyboard_master())
210 {
211
212 current_layer = biton32(state);
213 serial_m2s_buffer.current_layer = biton32(state);
214
215 // If left half, do the LED toggle thing
216 if (isLeftHand)
217 {
218 set_layer_indicators(biton32(state));
219 }
220
221 }
222 // NOTE: Do not set slave LEDs here.
223 // This is not called on slave
224
225 return layer_state_set_user(state);
226}
227
228
diff --git a/keyboards/ai03/orbit/orbit.h b/keyboards/ai03/orbit/orbit.h
new file mode 100644
index 000000000..211b9ebca
--- /dev/null
+++ b/keyboards/ai03/orbit/orbit.h
@@ -0,0 +1,65 @@
1/* Copyright 2018 Ryota Goto
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16#ifndef ORBIT_H
17#define ORBIT_H
18
19#include "quantum.h"
20
21/* This a shortcut to help you visually see your layout.
22 *
23 * The first section contains all of the arguments representing the physical
24 * layout of the board and position of the keys.
25 *
26 * The second converts the arguments into a two-dimensional array which
27 * represents the switch matrix.
28 */
29
30#ifdef USE_I2C
31#include <stddef.h>
32#ifdef __AVR__
33 #include <avr/io.h>
34 #include <avr/interrupt.h>
35#endif
36#endif
37
38
39#define LAYOUT( \
40 L00, L01, L02, L03, L04, L05, L06, R00, R01, R02, R03, R04, R05, R06, \
41 L10, L11, L12, L13, L14, L15, L16, R10, R11, R12, R13, R14, R15, R16, \
42 L20, L21, L22, L23, L24, L25, L26, R20, R21, R22, R23, R24, R25, R26, \
43 L30, L31, L32, L33, L34, L35, L36, R30, R31, R32, R33, R34, R35, R36, \
44 L41, L42, L43, L44, L45, L46, R40, R41, R42, R43, R44, R45 \
45) \
46{ \
47 { L00, L01, L02, L03, L04, L05, L06 }, \
48 { L10, L11, L12, L13, L14, L15, L16 }, \
49 { L20, L21, L22, L23, L24, L25, L26 }, \
50 { L30, L31, L32, L33, L34, L35, L36 }, \
51 { KC_NO, L41, L42, L43, L44, L45, L46 }, \
52 { R00, R01, R02, R03, R04, R05, R06 }, \
53 { R10, R11, R12, R13, R14, R15, R16 }, \
54 { R20, R21, R22, R23, R24, R25, R26 }, \
55 { R30, R31, R32, R33, R34, R35, R36 }, \
56 { R40, R41, R42, R43, R44, R45, KC_NO } \
57}
58
59uint8_t current_layer;
60
61extern void led_toggle(int id, bool on);
62void set_all_leds(bool leds[6]);
63extern void set_layer_indicators(uint8_t layer);
64
65#endif
diff --git a/keyboards/ai03/orbit/readme.md b/keyboards/ai03/orbit/readme.md
new file mode 100644
index 000000000..58ba2079d
--- /dev/null
+++ b/keyboards/ai03/orbit/readme.md
@@ -0,0 +1,15 @@
1# Orbit
2
3![Orbit](https://raw.githubusercontent.com/ai03-2725/Orbit/master/Images/PCB-R2.0.jpg)
4
5A split ergonomic keyboard project.
6
7Keyboard Maintainer: [ai03](https://github.com/ai03-2725)
8Hardware Supported: The [Orbit PCB](https://github.com/ai03-2725/Orbit)
9Hardware Availability: [This repository](https://github.com/ai03-2725/Orbit) has PCB files. Case group buy orders are currently closed.
10
11Make example for this keyboard (after setting up your build environment):
12
13 make ai03/orbit:default
14
15See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs).
diff --git a/keyboards/ai03/orbit/rules.mk b/keyboards/ai03/orbit/rules.mk
new file mode 100644
index 000000000..4b40e47cb
--- /dev/null
+++ b/keyboards/ai03/orbit/rules.mk
@@ -0,0 +1,92 @@
1SRC += split_util.c \
2 split_flags.c \
3 serial.c \
4 transport.c \
5 matrix.c
6
7# MCU name
8#MCU = at90usb1286
9MCU = atmega32u4
10
11# Processor frequency.
12# This will define a symbol, F_CPU, in all source code files equal to the
13# processor frequency in Hz. You can then use this symbol in your source code to
14# calculate timings. Do NOT tack on a 'UL' at the end, this will be done
15# automatically to create a 32-bit value in your source code.
16#
17# This will be an integer division of F_USB below, as it is sourced by
18# F_USB after it has run through any CPU prescalers. Note that this value
19# does not *change* the processor frequency - it should merely be updated to
20# reflect the processor speed set externally so that the code can use accurate
21# software delays.
22F_CPU = 16000000
23
24
25#
26# LUFA specific
27#
28# Target architecture (see library "Board Types" documentation).
29ARCH = AVR8
30
31# Input clock frequency.
32# This will define a symbol, F_USB, in all source code files equal to the
33# input clock frequency (before any prescaling is performed) in Hz. This value may
34# differ from F_CPU if prescaling is used on the latter, and is required as the
35# raw input clock is fed directly to the PLL sections of the AVR for high speed
36# clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL'
37# at the end, this will be done automatically to create a 32-bit value in your
38# source code.
39#
40# If no clock division is performed on the input clock inside the AVR (via the
41# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU.
42F_USB = $(F_CPU)
43
44# Interrupt driven control endpoint task(+60)
45OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
46
47
48# Bootloader selection
49# Teensy halfkay
50# Pro Micro caterina
51# Atmel DFU atmel-dfu
52# LUFA DFU lufa-dfu
53# QMK DFU qmk-dfu
54# atmega32a bootloadHID
55BOOTLOADER = atmel-dfu
56
57
58# If you don't know the bootloader type, then you can specify the
59# Boot Section Size in *bytes* by uncommenting out the OPT_DEFS line
60# Teensy halfKay 512
61# Teensy++ halfKay 1024
62# Atmel DFU loader 4096
63# LUFA bootloader 4096
64# USBaspLoader 2048
65# OPT_DEFS += -DBOOTLOADER_SIZE=4096
66
67
68# Build Options
69# change yes to no to disable
70#
71BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration(+1000)
72MOUSEKEY_ENABLE = yes # Mouse keys(+4700)
73EXTRAKEY_ENABLE = yes # Audio control and System control(+450)
74CONSOLE_ENABLE = no # Console for debug(+400)
75COMMAND_ENABLE = no # Commands for debug and configuration
76# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
77SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
78# if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
79NKRO_ENABLE = yes # USB Nkey Rollover
80BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality on B7 by default
81RGBLIGHT_ENABLE = no # Enable keyboard RGB underglow
82MIDI_ENABLE = no # MIDI support (+2400 to 4200, depending on config)
83UNICODE_ENABLE = no # Unicode
84BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID
85AUDIO_ENABLE = no # Audio output on port C6
86FAUXCLICKY_ENABLE = no # Use buzzer to emulate clicky switches
87HD44780_ENABLE = no # Enable support for HD44780 based LCDs (+400)
88USE_I2C = no # I2C for split communication
89CUSTOM_MATRIX = yes # For providing custom matrix.c (in this case, override regular matrix.c with split matrix.c)
90# SPLIT_KEYBOARD = yes # Split keyboard flag disabled as manual edits had to be done to the split common files
91
92
diff --git a/keyboards/ai03/orbit/serial.c b/keyboards/ai03/orbit/serial.c
new file mode 100644
index 000000000..1315377a3
--- /dev/null
+++ b/keyboards/ai03/orbit/serial.c
@@ -0,0 +1,546 @@
1/*
2 * WARNING: be careful changing this code, it is very timing dependent
3 *
4 * 2018-10-28 checked
5 * avr-gcc 4.9.2
6 * avr-gcc 5.4.0
7 * avr-gcc 7.3.0
8 */
9
10#ifndef F_CPU
11#define F_CPU 16000000
12#endif
13
14#include <avr/io.h>
15#include <avr/interrupt.h>
16#include <util/delay.h>
17#include <stddef.h>
18#include <stdbool.h>
19#include "serial.h"
20//#include <pro_micro.h>
21
22#ifdef SOFT_SERIAL_PIN
23
24#ifdef __AVR_ATmega32U4__
25 // if using ATmega32U4 I2C, can not use PD0 and PD1 in soft serial.
26 #ifdef USE_AVR_I2C
27 #if SOFT_SERIAL_PIN == D0 || SOFT_SERIAL_PIN == D1
28 #error Using ATmega32U4 I2C, so can not use PD0, PD1
29 #endif
30 #endif
31
32 #if SOFT_SERIAL_PIN >= D0 && SOFT_SERIAL_PIN <= D3
33 #define SERIAL_PIN_DDR DDRD
34 #define SERIAL_PIN_PORT PORTD
35 #define SERIAL_PIN_INPUT PIND
36 #if SOFT_SERIAL_PIN == D0
37 #define SERIAL_PIN_MASK _BV(PD0)
38 #define EIMSK_BIT _BV(INT0)
39 #define EICRx_BIT (~(_BV(ISC00) | _BV(ISC01)))
40 #define SERIAL_PIN_INTERRUPT INT0_vect
41 #elif SOFT_SERIAL_PIN == D1
42 #define SERIAL_PIN_MASK _BV(PD1)
43 #define EIMSK_BIT _BV(INT1)
44 #define EICRx_BIT (~(_BV(ISC10) | _BV(ISC11)))
45 #define SERIAL_PIN_INTERRUPT INT1_vect
46 #elif SOFT_SERIAL_PIN == D2
47 #define SERIAL_PIN_MASK _BV(PD2)
48 #define EIMSK_BIT _BV(INT2)
49 #define EICRx_BIT (~(_BV(ISC20) | _BV(ISC21)))
50 #define SERIAL_PIN_INTERRUPT INT2_vect
51 #elif SOFT_SERIAL_PIN == D3
52 #define SERIAL_PIN_MASK _BV(PD3)
53 #define EIMSK_BIT _BV(INT3)
54 #define EICRx_BIT (~(_BV(ISC30) | _BV(ISC31)))
55 #define SERIAL_PIN_INTERRUPT INT3_vect
56 #endif
57 #elif SOFT_SERIAL_PIN == E6
58 #define SERIAL_PIN_DDR DDRE
59 #define SERIAL_PIN_PORT PORTE
60 #define SERIAL_PIN_INPUT PINE
61 #define SERIAL_PIN_MASK _BV(PE6)
62 #define EIMSK_BIT _BV(INT6)
63 #define EICRx_BIT (~(_BV(ISC60) | _BV(ISC61)))
64 #define SERIAL_PIN_INTERRUPT INT6_vect
65 #else
66 #error invalid SOFT_SERIAL_PIN value
67 #endif
68
69#else
70 #error serial.c now support ATmega32U4 only
71#endif
72
73#define ALWAYS_INLINE __attribute__((always_inline))
74#define NO_INLINE __attribute__((noinline))
75#define _delay_sub_us(x) __builtin_avr_delay_cycles(x)
76
77// parity check
78#define ODD_PARITY 1
79#define EVEN_PARITY 0
80#define PARITY EVEN_PARITY
81
82#ifdef SERIAL_DELAY
83 // custom setup in config.h
84 // #define TID_SEND_ADJUST 2
85 // #define SERIAL_DELAY 6 // micro sec
86 // #define READ_WRITE_START_ADJUST 30 // cycles
87 // #define READ_WRITE_WIDTH_ADJUST 8 // cycles
88#else
89// ============ Standard setups ============
90
91#ifndef SELECT_SOFT_SERIAL_SPEED
92#define SELECT_SOFT_SERIAL_SPEED 1
93// 0: about 189kbps (Experimental only)
94// 1: about 137kbps (default)
95// 2: about 75kbps
96// 3: about 39kbps
97// 4: about 26kbps
98// 5: about 20kbps
99#endif
100
101#if __GNUC__ < 6
102 #define TID_SEND_ADJUST 14
103#else
104 #define TID_SEND_ADJUST 2
105#endif
106
107#if SELECT_SOFT_SERIAL_SPEED == 0
108 // Very High speed
109 #define SERIAL_DELAY 4 // micro sec
110 #if __GNUC__ < 6
111 #define READ_WRITE_START_ADJUST 33 // cycles
112 #define READ_WRITE_WIDTH_ADJUST 3 // cycles
113 #else
114 #define READ_WRITE_START_ADJUST 34 // cycles
115 #define READ_WRITE_WIDTH_ADJUST 7 // cycles
116 #endif
117#elif SELECT_SOFT_SERIAL_SPEED == 1
118 // High speed
119 #define SERIAL_DELAY 6 // micro sec
120 #if __GNUC__ < 6
121 #define READ_WRITE_START_ADJUST 30 // cycles
122 #define READ_WRITE_WIDTH_ADJUST 3 // cycles
123 #else
124 #define READ_WRITE_START_ADJUST 33 // cycles
125 #define READ_WRITE_WIDTH_ADJUST 7 // cycles
126 #endif
127#elif SELECT_SOFT_SERIAL_SPEED == 2
128 // Middle speed
129 #define SERIAL_DELAY 12 // micro sec
130 #define READ_WRITE_START_ADJUST 30 // cycles
131 #if __GNUC__ < 6
132 #define READ_WRITE_WIDTH_ADJUST 3 // cycles
133 #else
134 #define READ_WRITE_WIDTH_ADJUST 7 // cycles
135 #endif
136#elif SELECT_SOFT_SERIAL_SPEED == 3
137 // Low speed
138 #define SERIAL_DELAY 24 // micro sec
139 #define READ_WRITE_START_ADJUST 30 // cycles
140 #if __GNUC__ < 6
141 #define READ_WRITE_WIDTH_ADJUST 3 // cycles
142 #else
143 #define READ_WRITE_WIDTH_ADJUST 7 // cycles
144 #endif
145#elif SELECT_SOFT_SERIAL_SPEED == 4
146 // Very Low speed
147 #define SERIAL_DELAY 36 // micro sec
148 #define READ_WRITE_START_ADJUST 30 // cycles
149 #if __GNUC__ < 6
150 #define READ_WRITE_WIDTH_ADJUST 3 // cycles
151 #else
152 #define READ_WRITE_WIDTH_ADJUST 7 // cycles
153 #endif
154#elif SELECT_SOFT_SERIAL_SPEED == 5
155 // Ultra Low speed
156 #define SERIAL_DELAY 48 // micro sec
157 #define READ_WRITE_START_ADJUST 30 // cycles
158 #if __GNUC__ < 6
159 #define READ_WRITE_WIDTH_ADJUST 3 // cycles
160 #else
161 #define READ_WRITE_WIDTH_ADJUST 7 // cycles
162 #endif
163#else
164#error invalid SELECT_SOFT_SERIAL_SPEED value
165#endif /* SELECT_SOFT_SERIAL_SPEED */
166#endif /* SERIAL_DELAY */
167
168#define SERIAL_DELAY_HALF1 (SERIAL_DELAY/2)
169#define SERIAL_DELAY_HALF2 (SERIAL_DELAY - SERIAL_DELAY/2)
170
171#define SLAVE_INT_WIDTH_US 1
172#ifndef SERIAL_USE_MULTI_TRANSACTION
173 #define SLAVE_INT_RESPONSE_TIME SERIAL_DELAY
174#else
175 #define SLAVE_INT_ACK_WIDTH_UNIT 2
176 #define SLAVE_INT_ACK_WIDTH 4
177#endif
178
179static SSTD_t *Transaction_table = NULL;
180static uint8_t Transaction_table_size = 0;
181
182inline static void serial_delay(void) ALWAYS_INLINE;
183inline static
184void serial_delay(void) {
185 _delay_us(SERIAL_DELAY);
186}
187
188inline static void serial_delay_half1(void) ALWAYS_INLINE;
189inline static
190void serial_delay_half1(void) {
191 _delay_us(SERIAL_DELAY_HALF1);
192}
193
194inline static void serial_delay_half2(void) ALWAYS_INLINE;
195inline static
196void serial_delay_half2(void) {
197 _delay_us(SERIAL_DELAY_HALF2);
198}
199
200inline static void serial_output(void) ALWAYS_INLINE;
201inline static
202void serial_output(void) {
203 SERIAL_PIN_DDR |= SERIAL_PIN_MASK;
204}
205
206// make the serial pin an input with pull-up resistor
207inline static void serial_input_with_pullup(void) ALWAYS_INLINE;
208inline static
209void serial_input_with_pullup(void) {
210 SERIAL_PIN_DDR &= ~SERIAL_PIN_MASK;
211 SERIAL_PIN_PORT |= SERIAL_PIN_MASK;
212}
213
214inline static uint8_t serial_read_pin(void) ALWAYS_INLINE;
215inline static
216uint8_t serial_read_pin(void) {
217 return !!(SERIAL_PIN_INPUT & SERIAL_PIN_MASK);
218}
219
220inline static void serial_low(void) ALWAYS_INLINE;
221inline static
222void serial_low(void) {
223 SERIAL_PIN_PORT &= ~SERIAL_PIN_MASK;
224}
225
226inline static void serial_high(void) ALWAYS_INLINE;
227inline static
228void serial_high(void) {
229 SERIAL_PIN_PORT |= SERIAL_PIN_MASK;
230}
231
232void soft_serial_initiator_init(SSTD_t *sstd_table, int sstd_table_size)
233{
234 Transaction_table = sstd_table;
235 Transaction_table_size = (uint8_t)sstd_table_size;
236 serial_output();
237 serial_high();
238}
239
240void soft_serial_target_init(SSTD_t *sstd_table, int sstd_table_size)
241{
242 Transaction_table = sstd_table;
243 Transaction_table_size = (uint8_t)sstd_table_size;
244 serial_input_with_pullup();
245
246 // Enable INT0-INT3,INT6
247 EIMSK |= EIMSK_BIT;
248#if SERIAL_PIN_MASK == _BV(PE6)
249 // Trigger on falling edge of INT6
250 EICRB &= EICRx_BIT;
251#else
252 // Trigger on falling edge of INT0-INT3
253 EICRA &= EICRx_BIT;
254#endif
255}
256
257// Used by the sender to synchronize timing with the reciver.
258static void sync_recv(void) NO_INLINE;
259static
260void sync_recv(void) {
261 for (uint8_t i = 0; i < SERIAL_DELAY*5 && serial_read_pin(); i++ ) {
262 }
263 // This shouldn't hang if the target disconnects because the
264 // serial line will float to high if the target does disconnect.
265 while (!serial_read_pin());
266}
267
268// Used by the reciver to send a synchronization signal to the sender.
269static void sync_send(void) NO_INLINE;
270static
271void sync_send(void) {
272 serial_low();
273 serial_delay();
274 serial_high();
275}
276
277// Reads a byte from the serial line
278static uint8_t serial_read_chunk(uint8_t *pterrcount, uint8_t bit) NO_INLINE;
279static uint8_t serial_read_chunk(uint8_t *pterrcount, uint8_t bit) {
280 uint8_t byte, i, p, pb;
281
282 _delay_sub_us(READ_WRITE_START_ADJUST);
283 for( i = 0, byte = 0, p = PARITY; i < bit; i++ ) {
284 serial_delay_half1(); // read the middle of pulses
285 if( serial_read_pin() ) {
286 byte = (byte << 1) | 1; p ^= 1;
287 } else {
288 byte = (byte << 1) | 0; p ^= 0;
289 }
290 _delay_sub_us(READ_WRITE_WIDTH_ADJUST);
291 serial_delay_half2();
292 }
293 /* recive parity bit */
294 serial_delay_half1(); // read the middle of pulses
295 pb = serial_read_pin();
296 _delay_sub_us(READ_WRITE_WIDTH_ADJUST);
297 serial_delay_half2();
298
299 *pterrcount += (p != pb)? 1 : 0;
300
301 return byte;
302}
303
304// Sends a byte with MSB ordering
305void serial_write_chunk(uint8_t data, uint8_t bit) NO_INLINE;
306void serial_write_chunk(uint8_t data, uint8_t bit) {
307 uint8_t b, p;
308 for( p = PARITY, b = 1<<(bit-1); b ; b >>= 1) {
309 if(data & b) {
310 serial_high(); p ^= 1;
311 } else {
312 serial_low(); p ^= 0;
313 }
314 serial_delay();
315 }
316 /* send parity bit */
317 if(p & 1) { serial_high(); }
318 else { serial_low(); }
319 serial_delay();
320
321 serial_low(); // sync_send() / senc_recv() need raise edge
322}
323
324static void serial_send_packet(uint8_t *buffer, uint8_t size) NO_INLINE;
325static
326void serial_send_packet(uint8_t *buffer, uint8_t size) {
327 for (uint8_t i = 0; i < size; ++i) {
328 uint8_t data;
329 data = buffer[i];
330 sync_send();
331 serial_write_chunk(data,8);
332 }
333}
334
335static uint8_t serial_recive_packet(uint8_t *buffer, uint8_t size) NO_INLINE;
336static
337uint8_t serial_recive_packet(uint8_t *buffer, uint8_t size) {
338 uint8_t pecount = 0;
339 for (uint8_t i = 0; i < size; ++i) {
340 uint8_t data;
341 sync_recv();
342 data = serial_read_chunk(&pecount, 8);
343 buffer[i] = data;
344 }
345 return pecount == 0;
346}
347
348inline static
349void change_sender2reciver(void) {
350 sync_send(); //0
351 serial_delay_half1(); //1
352 serial_low(); //2
353 serial_input_with_pullup(); //2
354 serial_delay_half1(); //3
355}
356
357inline static
358void change_reciver2sender(void) {
359 sync_recv(); //0
360 serial_delay(); //1
361 serial_low(); //3
362 serial_output(); //3
363 serial_delay_half1(); //4
364}
365
366static inline uint8_t nibble_bits_count(uint8_t bits)
367{
368 bits = (bits & 0x5) + (bits >> 1 & 0x5);
369 bits = (bits & 0x3) + (bits >> 2 & 0x3);
370 return bits;
371}
372
373// interrupt handle to be used by the target device
374ISR(SERIAL_PIN_INTERRUPT) {
375
376#ifndef SERIAL_USE_MULTI_TRANSACTION
377 serial_low();
378 serial_output();
379 SSTD_t *trans = Transaction_table;
380#else
381 // recive transaction table index
382 uint8_t tid, bits;
383 uint8_t pecount = 0;
384 sync_recv();
385 bits = serial_read_chunk(&pecount,7);
386 tid = bits>>3;
387 bits = (bits&7) != nibble_bits_count(tid);
388 if( bits || pecount> 0 || tid > Transaction_table_size ) {
389 return;
390 }
391 serial_delay_half1();
392
393 serial_high(); // response step1 low->high
394 serial_output();
395 _delay_sub_us(SLAVE_INT_ACK_WIDTH_UNIT*SLAVE_INT_ACK_WIDTH);
396 SSTD_t *trans = &Transaction_table[tid];
397 serial_low(); // response step2 ack high->low
398#endif
399
400 // target send phase
401 if( trans->target2initiator_buffer_size > 0 )
402 serial_send_packet((uint8_t *)trans->target2initiator_buffer,
403 trans->target2initiator_buffer_size);
404 // target switch to input
405 change_sender2reciver();
406
407 // target recive phase
408 if( trans->initiator2target_buffer_size > 0 ) {
409 if (serial_recive_packet((uint8_t *)trans->initiator2target_buffer,
410 trans->initiator2target_buffer_size) ) {
411 *trans->status = TRANSACTION_ACCEPTED;
412 } else {
413 *trans->status = TRANSACTION_DATA_ERROR;
414 }
415 } else {
416 *trans->status = TRANSACTION_ACCEPTED;
417 }
418
419 sync_recv(); //weit initiator output to high
420}
421
422/////////
423// start transaction by initiator
424//
425// int soft_serial_transaction(int sstd_index)
426//
427// Returns:
428// TRANSACTION_END
429// TRANSACTION_NO_RESPONSE
430// TRANSACTION_DATA_ERROR
431// this code is very time dependent, so we need to disable interrupts
432#ifndef SERIAL_USE_MULTI_TRANSACTION
433int soft_serial_transaction(void) {
434 SSTD_t *trans = Transaction_table;
435#else
436int soft_serial_transaction(int sstd_index) {
437 if( sstd_index > Transaction_table_size )
438 return TRANSACTION_TYPE_ERROR;
439 SSTD_t *trans = &Transaction_table[sstd_index];
440#endif
441 cli();
442
443 // signal to the target that we want to start a transaction
444 serial_output();
445 serial_low();
446 _delay_us(SLAVE_INT_WIDTH_US);
447
448#ifndef SERIAL_USE_MULTI_TRANSACTION
449 // wait for the target response
450 serial_input_with_pullup();
451 _delay_us(SLAVE_INT_RESPONSE_TIME);
452
453 // check if the target is present
454 if (serial_read_pin()) {
455 // target failed to pull the line low, assume not present
456 serial_output();
457 serial_high();
458 *trans->status = TRANSACTION_NO_RESPONSE;
459 sei();
460 return TRANSACTION_NO_RESPONSE;
461 }
462
463#else
464 // send transaction table index
465 int tid = (sstd_index<<3) | (7 & nibble_bits_count(sstd_index));
466 sync_send();
467 _delay_sub_us(TID_SEND_ADJUST);
468 serial_write_chunk(tid, 7);
469 serial_delay_half1();
470
471 // wait for the target response (step1 low->high)
472 serial_input_with_pullup();
473 while( !serial_read_pin() ) {
474 _delay_sub_us(2);
475 }
476
477 // check if the target is present (step2 high->low)
478 for( int i = 0; serial_read_pin(); i++ ) {
479 if (i > SLAVE_INT_ACK_WIDTH + 1) {
480 // slave failed to pull the line low, assume not present
481 serial_output();
482 serial_high();
483 *trans->status = TRANSACTION_NO_RESPONSE;
484 sei();
485 return TRANSACTION_NO_RESPONSE;
486 }
487 _delay_sub_us(SLAVE_INT_ACK_WIDTH_UNIT);
488 }
489#endif
490
491 // initiator recive phase
492 // if the target is present syncronize with it
493 if( trans->target2initiator_buffer_size > 0 ) {
494 if (!serial_recive_packet((uint8_t *)trans->target2initiator_buffer,
495 trans->target2initiator_buffer_size) ) {
496 serial_output();
497 serial_high();
498 *trans->status = TRANSACTION_DATA_ERROR;
499 sei();
500 return TRANSACTION_DATA_ERROR;
501 }
502 }
503
504 // initiator switch to output
505 change_reciver2sender();
506
507 // initiator send phase
508 if( trans->initiator2target_buffer_size > 0 ) {
509 serial_send_packet((uint8_t *)trans->initiator2target_buffer,
510 trans->initiator2target_buffer_size);
511 }
512
513 // always, release the line when not in use
514 sync_send();
515
516 *trans->status = TRANSACTION_END;
517 sei();
518 return TRANSACTION_END;
519}
520
521#ifdef SERIAL_USE_MULTI_TRANSACTION
522int soft_serial_get_and_clean_status(int sstd_index) {
523 SSTD_t *trans = &Transaction_table[sstd_index];
524 cli();
525 int retval = *trans->status;
526 *trans->status = 0;;
527 sei();
528 return retval;
529}
530#endif
531
532#endif
533
534// Helix serial.c history
535// 2018-1-29 fork from let's split and add PD2, modify sync_recv() (#2308, bceffdefc)
536// 2018-6-28 bug fix master to slave comm and speed up (#3255, 1038bbef4)
537// (adjusted with avr-gcc 4.9.2)
538// 2018-7-13 remove USE_SERIAL_PD2 macro (#3374, f30d6dd78)
539// (adjusted with avr-gcc 4.9.2)
540// 2018-8-11 add support multi-type transaction (#3608, feb5e4aae)
541// (adjusted with avr-gcc 4.9.2)
542// 2018-10-21 fix serial and RGB animation conflict (#4191, 4665e4fff)
543// (adjusted with avr-gcc 7.3.0)
544// 2018-10-28 re-adjust compiler depend value of delay (#4269, 8517f8a66)
545// (adjusted with avr-gcc 5.4.0, 7.3.0)
546// 2018-12-17 copy to TOP/quantum/split_common/ and remove backward compatibility code (#4669)
diff --git a/keyboards/ai03/orbit/serial.h b/keyboards/ai03/orbit/serial.h
new file mode 100644
index 000000000..1c1e64006
--- /dev/null
+++ b/keyboards/ai03/orbit/serial.h
@@ -0,0 +1,62 @@
1#pragma once
2
3#include <stdbool.h>
4
5// /////////////////////////////////////////////////////////////////
6// Need Soft Serial defines in config.h
7// /////////////////////////////////////////////////////////////////
8// ex.
9// #define SOFT_SERIAL_PIN ?? // ?? = D0,D1,D2,D3,E6
10// OPTIONAL: #define SELECT_SOFT_SERIAL_SPEED ? // ? = 1,2,3,4,5
11// // 1: about 137kbps (default)
12// // 2: about 75kbps
13// // 3: about 39kbps
14// // 4: about 26kbps
15// // 5: about 20kbps
16//
17// //// USE simple API (using signle-type transaction function)
18// /* nothing */
19// //// USE flexible API (using multi-type transaction function)
20// #define SERIAL_USE_MULTI_TRANSACTION
21//
22// /////////////////////////////////////////////////////////////////
23
24// Soft Serial Transaction Descriptor
25typedef struct _SSTD_t {
26 uint8_t *status;
27 uint8_t initiator2target_buffer_size;
28 uint8_t *initiator2target_buffer;
29 uint8_t target2initiator_buffer_size;
30 uint8_t *target2initiator_buffer;
31} SSTD_t;
32#define TID_LIMIT( table ) (sizeof(table) / sizeof(SSTD_t))
33
34// initiator is transaction start side
35void soft_serial_initiator_init(SSTD_t *sstd_table, int sstd_table_size);
36// target is interrupt accept side
37void soft_serial_target_init(SSTD_t *sstd_table, int sstd_table_size);
38
39// initiator resullt
40#define TRANSACTION_END 0
41#define TRANSACTION_NO_RESPONSE 0x1
42#define TRANSACTION_DATA_ERROR 0x2
43#define TRANSACTION_TYPE_ERROR 0x4
44#ifndef SERIAL_USE_MULTI_TRANSACTION
45int soft_serial_transaction(void);
46#else
47int soft_serial_transaction(int sstd_index);
48#endif
49
50// target status
51// *SSTD_t.status has
52// initiator:
53// TRANSACTION_END
54// or TRANSACTION_NO_RESPONSE
55// or TRANSACTION_DATA_ERROR
56// target:
57// TRANSACTION_DATA_ERROR
58// or TRANSACTION_ACCEPTED
59#define TRANSACTION_ACCEPTED 0x8
60#ifdef SERIAL_USE_MULTI_TRANSACTION
61int soft_serial_get_and_clean_status(int sstd_index);
62#endif
diff --git a/keyboards/ai03/orbit/split_flags.c b/keyboards/ai03/orbit/split_flags.c
new file mode 100644
index 000000000..1f5825d65
--- /dev/null
+++ b/keyboards/ai03/orbit/split_flags.c
@@ -0,0 +1,5 @@
1#include "split_flags.h"
2
3volatile bool RGB_DIRTY = false;
4
5volatile bool BACKLIT_DIRTY = false; \ No newline at end of file
diff --git a/keyboards/ai03/orbit/split_flags.h b/keyboards/ai03/orbit/split_flags.h
new file mode 100644
index 000000000..aaac474a7
--- /dev/null
+++ b/keyboards/ai03/orbit/split_flags.h
@@ -0,0 +1,15 @@
1#pragma once
2
3#include <stdbool.h>
4#include <stdint.h>
5
6/**
7* Global Flags
8**/
9
10//RGB Stuff
11extern volatile bool RGB_DIRTY;
12
13
14//Backlight Stuff
15extern volatile bool BACKLIT_DIRTY;
diff --git a/keyboards/ai03/orbit/split_util.c b/keyboards/ai03/orbit/split_util.c
new file mode 100644
index 000000000..5095cb8fd
--- /dev/null
+++ b/keyboards/ai03/orbit/split_util.c
@@ -0,0 +1,87 @@
1#include "split_util.h"
2#include "matrix.h"
3#include "keyboard.h"
4#include "config.h"
5#include "timer.h"
6#include "split_flags.h"
7#include "transport.h"
8#include "quantum.h"
9
10#ifdef EE_HANDS
11# include "tmk_core/common/eeprom.h"
12# include "eeconfig.h"
13#endif
14
15volatile bool isLeftHand = true;
16
17__attribute__((weak))
18bool is_keyboard_left(void) {
19 #ifdef SPLIT_HAND_PIN
20 // Test pin SPLIT_HAND_PIN for High/Low, if low it's right hand
21 setPinInput(SPLIT_HAND_PIN);
22 return readPin(SPLIT_HAND_PIN);
23 #else
24 #ifdef EE_HANDS
25 return eeprom_read_byte(EECONFIG_HANDEDNESS);
26 #else
27 #ifdef MASTER_RIGHT
28 return !is_keyboard_master();
29 #else
30 return is_keyboard_master();
31 #endif
32 #endif
33 #endif
34}
35
36bool is_keyboard_master(void)
37{
38#ifdef __AVR__
39 static enum { UNKNOWN, MASTER, SLAVE } usbstate = UNKNOWN;
40
41 // only check once, as this is called often
42 if (usbstate == UNKNOWN)
43 {
44 USBCON |= (1 << OTGPADE); // enables VBUS pad
45 wait_us(5);
46
47 usbstate = (USBSTA & (1 << VBUS)) ? MASTER : SLAVE; // checks state of VBUS
48 }
49
50 return (usbstate == MASTER);
51#else
52 return true;
53#endif
54}
55
56static void keyboard_master_setup(void) {
57#if defined(USE_I2C) || defined(EH)
58 #ifdef SSD1306OLED
59 matrix_master_OLED_init ();
60 #endif
61#endif
62 transport_master_init();
63
64 // For master the Backlight info needs to be sent on startup
65 // Otherwise the salve won't start with the proper info until an update
66 BACKLIT_DIRTY = true;
67}
68
69static void keyboard_slave_setup(void)
70{
71 transport_slave_init();
72}
73
74// this code runs before the usb and keyboard is initialized
75void matrix_setup(void)
76{
77 isLeftHand = is_keyboard_left();
78
79 if (is_keyboard_master())
80 {
81 keyboard_master_setup();
82 }
83 else
84 {
85 keyboard_slave_setup();
86 }
87}
diff --git a/keyboards/ai03/orbit/split_util.h b/keyboards/ai03/orbit/split_util.h
new file mode 100644
index 000000000..20f7535bf
--- /dev/null
+++ b/keyboards/ai03/orbit/split_util.h
@@ -0,0 +1,10 @@
1#pragma once
2
3#include <stdbool.h>
4#include <stdint.h>
5#include <stdio.h>
6#include <stdlib.h>
7
8extern volatile bool isLeftHand;
9
10void matrix_master_OLED_init (void);
diff --git a/keyboards/ai03/orbit/transport.c b/keyboards/ai03/orbit/transport.c
new file mode 100644
index 000000000..adedf2432
--- /dev/null
+++ b/keyboards/ai03/orbit/transport.c
@@ -0,0 +1,238 @@
1
2#include "transport.h"
3
4#include "config.h"
5#include "matrix.h"
6#include "quantum.h"
7
8#include "orbit.h"
9
10#define ROWS_PER_HAND (MATRIX_ROWS/2)
11
12#ifdef RGBLIGHT_ENABLE
13# include "rgblight.h"
14#endif
15
16#ifdef BACKLIGHT_ENABLE
17# include "backlight.h"
18 extern backlight_config_t backlight_config;
19#endif
20
21#if defined(USE_I2C) || defined(EH)
22
23#include "i2c.h"
24
25#ifndef SLAVE_I2C_ADDRESS
26# define SLAVE_I2C_ADDRESS 0x32
27#endif
28
29#if (MATRIX_COLS > 8)
30# error "Currently only supports 8 COLS"
31#endif
32
33// Get rows from other half over i2c
34bool transport_master(matrix_row_t matrix[]) {
35 int err = 0;
36
37 // write backlight info
38#ifdef BACKLIGHT_ENABLE
39 if (BACKLIT_DIRTY) {
40 err = i2c_master_start(SLAVE_I2C_ADDRESS + I2C_WRITE);
41 if (err) { goto i2c_error; }
42
43 // Backlight location
44 err = i2c_master_write(I2C_BACKLIT_START);
45 if (err) { goto i2c_error; }
46
47 // Write backlight
48 i2c_master_write(get_backlight_level());
49
50 BACKLIT_DIRTY = false;
51 }
52#endif
53
54 err = i2c_master_start(SLAVE_I2C_ADDRESS + I2C_WRITE);
55 if (err) { goto i2c_error; }
56
57 // start of matrix stored at I2C_KEYMAP_START
58 err = i2c_master_write(I2C_KEYMAP_START);
59 if (err) { goto i2c_error; }
60
61 // Start read
62 err = i2c_master_start(SLAVE_I2C_ADDRESS + I2C_READ);
63 if (err) { goto i2c_error; }
64
65 if (!err) {
66 int i;
67 for (i = 0; i < ROWS_PER_HAND-1; ++i) {
68 matrix[i] = i2c_master_read(I2C_ACK);
69 }
70 matrix[i] = i2c_master_read(I2C_NACK);
71 i2c_master_stop();
72 } else {
73i2c_error: // the cable is disconnceted, or something else went wrong
74 i2c_reset_state();
75 return false;
76 }
77
78#ifdef RGBLIGHT_ENABLE
79 if (RGB_DIRTY) {
80 err = i2c_master_start(SLAVE_I2C_ADDRESS + I2C_WRITE);
81 if (err) { goto i2c_error; }
82
83 // RGB Location
84 err = i2c_master_write(I2C_RGB_START);
85 if (err) { goto i2c_error; }
86
87 uint32_t dword = eeconfig_read_rgblight();
88
89 // Write RGB
90 err = i2c_master_write_data(&dword, 4);
91 if (err) { goto i2c_error; }
92
93 RGB_DIRTY = false;
94 i2c_master_stop();
95 }
96#endif
97
98 return true;
99}
100
101void transport_slave(matrix_row_t matrix[]) {
102
103 for (int i = 0; i < ROWS_PER_HAND; ++i)
104 {
105 i2c_slave_buffer[I2C_KEYMAP_START + i] = matrix[i];
106 }
107 // Read Backlight Info
108 #ifdef BACKLIGHT_ENABLE
109 if (BACKLIT_DIRTY)
110 {
111 backlight_set(i2c_slave_buffer[I2C_BACKLIT_START]);
112 BACKLIT_DIRTY = false;
113 }
114 #endif
115 #ifdef RGBLIGHT_ENABLE
116 if (RGB_DIRTY)
117 {
118 // Disable interupts (RGB data is big)
119 cli();
120 // Create new DWORD for RGB data
121 uint32_t dword;
122
123 // Fill the new DWORD with the data that was sent over
124 uint8_t * dword_dat = (uint8_t *)(&dword);
125 for (int i = 0; i < 4; i++)
126 {
127 dword_dat[i] = i2c_slave_buffer[I2C_RGB_START + i];
128 }
129
130 // Update the RGB now with the new data and set RGB_DIRTY to false
131 rgblight_update_dword(dword);
132 RGB_DIRTY = false;
133 // Re-enable interupts now that RGB is set
134 sei();
135 }
136 #endif
137}
138
139void transport_master_init(void) {
140 i2c_master_init();
141}
142
143void transport_slave_init(void) {
144 i2c_slave_init(SLAVE_I2C_ADDRESS);
145}
146
147#else // USE_SERIAL
148
149#include "serial.h"
150
151
152
153volatile Serial_s2m_buffer_t serial_s2m_buffer = {};
154volatile Serial_m2s_buffer_t serial_m2s_buffer = {};
155uint8_t volatile status0 = 0;
156
157SSTD_t transactions[] = {
158 { (uint8_t *)&status0,
159 sizeof(serial_m2s_buffer), (uint8_t *)&serial_m2s_buffer,
160 sizeof(serial_s2m_buffer), (uint8_t *)&serial_s2m_buffer
161 }
162};
163
164uint8_t slave_layer_cache;
165uint8_t slave_nlock_cache;
166uint8_t slave_clock_cache;
167uint8_t slave_slock_cache;
168
169void transport_master_init(void)
170{ soft_serial_initiator_init(transactions, TID_LIMIT(transactions)); }
171
172void transport_slave_init(void)
173{
174 soft_serial_target_init(transactions, TID_LIMIT(transactions));
175 slave_layer_cache = 255;
176 slave_nlock_cache = 255;
177 slave_clock_cache = 255;
178 slave_slock_cache = 255;
179}
180
181bool transport_master(matrix_row_t matrix[]) {
182
183 if (soft_serial_transaction()) {
184 return false;
185 }
186
187 // TODO: if MATRIX_COLS > 8 change to unpack()
188 for (int i = 0; i < ROWS_PER_HAND; ++i) {
189 matrix[i] = serial_s2m_buffer.smatrix[i];
190 }
191
192 #if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
193 // Code to send RGB over serial goes here (not implemented yet)
194 #endif
195
196 #ifdef BACKLIGHT_ENABLE
197 // Write backlight level for slave to read
198 serial_m2s_buffer.backlight_level = backlight_config.enable ? backlight_config.level : 0;
199 #endif
200
201 return true;
202}
203
204void transport_slave(matrix_row_t matrix[]) {
205
206 // TODO: if MATRIX_COLS > 8 change to pack()
207 for (int i = 0; i < ROWS_PER_HAND; ++i)
208 {
209 serial_s2m_buffer.smatrix[i] = matrix[i];
210 }
211 #ifdef BACKLIGHT_ENABLE
212 backlight_set(serial_m2s_buffer.backlight_level);
213 #endif
214 #if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
215 // Add serial implementation for RGB here
216 #endif
217
218 if (slave_layer_cache != serial_m2s_buffer.current_layer) {
219 slave_layer_cache = serial_m2s_buffer.current_layer;
220 set_layer_indicators(slave_layer_cache);
221 }
222
223 if (slave_nlock_cache != serial_m2s_buffer.nlock_led) {
224 slave_nlock_cache = serial_m2s_buffer.nlock_led;
225 led_toggle(3, slave_nlock_cache);
226 }
227 if (slave_clock_cache != serial_m2s_buffer.clock_led) {
228 slave_clock_cache = serial_m2s_buffer.clock_led;
229 led_toggle(4, slave_clock_cache);
230 }
231 if (slave_slock_cache != serial_m2s_buffer.slock_led) {
232 slave_slock_cache = serial_m2s_buffer.slock_led;
233 led_toggle(5, slave_slock_cache);
234 }
235
236}
237
238#endif
diff --git a/keyboards/ai03/orbit/transport.h b/keyboards/ai03/orbit/transport.h
new file mode 100644
index 000000000..422e2ecb9
--- /dev/null
+++ b/keyboards/ai03/orbit/transport.h
@@ -0,0 +1,42 @@
1#pragma once
2
3#include <common/matrix.h>
4
5#define ROWS_PER_HAND (MATRIX_ROWS/2)
6
7typedef struct _Serial_s2m_buffer_t {
8 // TODO: if MATRIX_COLS > 8 change to uint8_t packed_matrix[] for pack/unpack
9 matrix_row_t smatrix[ROWS_PER_HAND];
10} Serial_s2m_buffer_t;
11
12typedef struct _Serial_m2s_buffer_t {
13#ifdef BACKLIGHT_ENABLE
14 uint8_t backlight_level;
15#endif
16#if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
17 rgblight_config_t rgblight_config; //not yet use
18 //
19 // When MCUs on both sides drive their respective RGB LED chains,
20 // it is necessary to synchronize, so it is necessary to communicate RGB information.
21 // In that case, define the RGBLIGHT_SPLIT macro.
22 //
23 // Otherwise, if the master side MCU drives both sides RGB LED chains,
24 // there is no need to communicate.
25#endif
26
27 uint8_t current_layer;
28 uint8_t nlock_led;
29 uint8_t clock_led;
30 uint8_t slock_led;
31
32} Serial_m2s_buffer_t;
33
34extern volatile Serial_s2m_buffer_t serial_s2m_buffer;
35extern volatile Serial_m2s_buffer_t serial_m2s_buffer;
36
37void transport_master_init(void);
38void transport_slave_init(void);
39
40// returns false if valid data not received from slave
41bool transport_master(matrix_row_t matrix[]);
42void transport_slave(matrix_row_t matrix[]);