aboutsummaryrefslogtreecommitdiff
path: root/keyboards/claw44
diff options
context:
space:
mode:
authoryfuku <30647434+yfuku@users.noreply.github.com>2019-03-31 04:16:18 +0900
committerDrashna Jaelre <drashna@live.com>2019-03-30 12:16:18 -0700
commit3654d0f080c85da3b2ae33cc035777a445cca769 (patch)
treed65ad19caa68aceb64716c04ad6bcf57ba5875c3 /keyboards/claw44
parent4f7dd9edf8cf9b546d7c21fcefb7de09f92474db (diff)
downloadqmk_firmware-3654d0f080c85da3b2ae33cc035777a445cca769.tar.gz
qmk_firmware-3654d0f080c85da3b2ae33cc035777a445cca769.zip
[Keyboard] add claw44 keyboard (#5511)
* add claw44 keyboard * Update keyboards/claw44/lib/layer_state_reader.c Co-Authored-By: yfuku <30647434+yfuku@users.noreply.github.com> * Update keyboards/claw44/lib/layer_state_reader.c Co-Authored-By: yfuku <30647434+yfuku@users.noreply.github.com> * Update keyboards/claw44/lib/layer_state_reader.c Co-Authored-By: yfuku <30647434+yfuku@users.noreply.github.com> * Update keyboards/claw44/lib/layer_state_reader.c Co-Authored-By: yfuku <30647434+yfuku@users.noreply.github.com> * Update keyboards/claw44/readme.md Co-Authored-By: yfuku <30647434+yfuku@users.noreply.github.com> * Remove unnecessary code because of default value * Move layer definition * Update keyboards/claw44/keymaps/default/keymap.c Co-Authored-By: yfuku <30647434+yfuku@users.noreply.github.com> * Update keyboards/claw44/keymaps/yfuku/keymap.c Co-Authored-By: yfuku <30647434+yfuku@users.noreply.github.com> * Update keyboards/claw44/readme.md Co-Authored-By: yfuku <30647434+yfuku@users.noreply.github.com> * default keymap. LAYOUT_kc -> LAYOUT macro * Move rules.mk from keymaps to keyboard level. * add Hardware Supported, Hardware Availability * Update keyboards/claw44/keymaps/default/keymap.c Co-Authored-By: yfuku <30647434+yfuku@users.noreply.github.com> * Update keyboards/claw44/keymaps/yfuku/keymap.c Co-Authored-By: yfuku <30647434+yfuku@users.noreply.github.com> * Remove depreciated function
Diffstat (limited to 'keyboards/claw44')
-rw-r--r--keyboards/claw44/claw44.c10
-rw-r--r--keyboards/claw44/claw44.h5
-rw-r--r--keyboards/claw44/config.h28
-rw-r--r--keyboards/claw44/i2c.c162
-rw-r--r--keyboards/claw44/i2c.h46
-rw-r--r--keyboards/claw44/keymaps/default/config.h35
-rw-r--r--keyboards/claw44/keymaps/default/keymap.c169
-rw-r--r--keyboards/claw44/keymaps/yfuku/config.h36
-rw-r--r--keyboards/claw44/keymaps/yfuku/keymap.c221
-rw-r--r--keyboards/claw44/lib/glcdfont.c243
-rw-r--r--keyboards/claw44/lib/host_led_state_reader.c15
-rw-r--r--keyboards/claw44/lib/keylogger.c45
-rw-r--r--keyboards/claw44/lib/layer_state_reader.c35
-rw-r--r--keyboards/claw44/lib/logo_reader.c11
-rw-r--r--keyboards/claw44/lib/mode_icon_reader.c15
-rw-r--r--keyboards/claw44/lib/rgb_state_reader.c15
-rw-r--r--keyboards/claw44/lib/timelogger.c16
-rw-r--r--keyboards/claw44/readme.md15
-rw-r--r--keyboards/claw44/rev1/config.h76
-rw-r--r--keyboards/claw44/rev1/matrix.c357
-rw-r--r--keyboards/claw44/rev1/rev1.c8
-rw-r--r--keyboards/claw44/rev1/rev1.h57
-rw-r--r--keyboards/claw44/rev1/rules.mk31
-rw-r--r--keyboards/claw44/rev1/serial_config.h4
-rw-r--r--keyboards/claw44/rev1/split_scomm.c91
-rw-r--r--keyboards/claw44/rev1/split_scomm.h24
-rw-r--r--keyboards/claw44/rev1/split_util.c70
-rw-r--r--keyboards/claw44/rev1/split_util.h19
-rw-r--r--keyboards/claw44/rules.mk74
-rw-r--r--keyboards/claw44/serial.c590
-rw-r--r--keyboards/claw44/serial.h84
-rw-r--r--keyboards/claw44/ssd1306.c346
-rw-r--r--keyboards/claw44/ssd1306.h91
33 files changed, 3044 insertions, 0 deletions
diff --git a/keyboards/claw44/claw44.c b/keyboards/claw44/claw44.c
new file mode 100644
index 000000000..f564fb623
--- /dev/null
+++ b/keyboards/claw44/claw44.c
@@ -0,0 +1,10 @@
1#include "claw44.h"
2#include "ssd1306.h"
3
4bool process_record_kb(uint16_t keycode, keyrecord_t *record) {
5#ifdef SSD1306OLED
6 return process_record_gfx(keycode,record) && process_record_user(keycode, record);
7#else
8 return process_record_user(keycode, record);
9#endif
10}
diff --git a/keyboards/claw44/claw44.h b/keyboards/claw44/claw44.h
new file mode 100644
index 000000000..4ca25fcb2
--- /dev/null
+++ b/keyboards/claw44/claw44.h
@@ -0,0 +1,5 @@
1#pragma once
2
3#ifdef KEYBOARD_claw44_rev1
4 #include "rev1.h"
5#endif
diff --git a/keyboards/claw44/config.h b/keyboards/claw44/config.h
new file mode 100644
index 000000000..fb1cdf396
--- /dev/null
+++ b/keyboards/claw44/config.h
@@ -0,0 +1,28 @@
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#pragma once
20
21#include "config_common.h"
22#include <serial_config.h>
23
24#define USE_I2C
25#define USE_SERIAL
26
27#define NO_ACTION_MACRO
28#define NO_ACTION_FUNCTION
diff --git a/keyboards/claw44/i2c.c b/keyboards/claw44/i2c.c
new file mode 100644
index 000000000..4bee5c639
--- /dev/null
+++ b/keyboards/claw44/i2c.c
@@ -0,0 +1,162 @@
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 or 400kHz (see ./i2c.h SCL_CLOCK)
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}
162#endif
diff --git a/keyboards/claw44/i2c.h b/keyboards/claw44/i2c.h
new file mode 100644
index 000000000..710662c7a
--- /dev/null
+++ b/keyboards/claw44/i2c.h
@@ -0,0 +1,46 @@
1#pragma once
2
3#include <stdint.h>
4
5#ifndef F_CPU
6#define F_CPU 16000000UL
7#endif
8
9#define I2C_READ 1
10#define I2C_WRITE 0
11
12#define I2C_ACK 1
13#define I2C_NACK 0
14
15#define SLAVE_BUFFER_SIZE 0x10
16
17// i2c SCL clock frequency 400kHz
18#define SCL_CLOCK 400000L
19
20extern volatile uint8_t i2c_slave_buffer[SLAVE_BUFFER_SIZE];
21
22void i2c_master_init(void);
23uint8_t i2c_master_start(uint8_t address);
24void i2c_master_stop(void);
25uint8_t i2c_master_write(uint8_t data);
26uint8_t i2c_master_read(int);
27void i2c_reset_state(void);
28void i2c_slave_init(uint8_t address);
29
30
31static inline unsigned char i2c_start_read(unsigned char addr) {
32 return i2c_master_start((addr << 1) | I2C_READ);
33}
34
35static inline unsigned char i2c_start_write(unsigned char addr) {
36 return i2c_master_start((addr << 1) | I2C_WRITE);
37}
38
39// from SSD1306 scrips
40extern unsigned char i2c_rep_start(unsigned char addr);
41extern void i2c_start_wait(unsigned char addr);
42extern unsigned char i2c_readAck(void);
43extern unsigned char i2c_readNak(void);
44extern unsigned char i2c_read(unsigned char ack);
45
46#define i2c_read(ack) (ack) ? i2c_readAck() : i2c_readNak();
diff --git a/keyboards/claw44/keymaps/default/config.h b/keyboards/claw44/keymaps/default/config.h
new file mode 100644
index 000000000..eff6ad3c7
--- /dev/null
+++ b/keyboards/claw44/keymaps/default/config.h
@@ -0,0 +1,35 @@
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#pragma once
22
23//#define USE_MATRIX_I2C
24
25/* Select hand configuration */
26
27#define MASTER_LEFT
28// #define MASTER_RIGHT
29// #define EE_HANDS
30
31#define SSD1306OLED
32
33#define USE_SERIAL_PD2
34
35#define TAPPING_TERM 200
diff --git a/keyboards/claw44/keymaps/default/keymap.c b/keyboards/claw44/keymaps/default/keymap.c
new file mode 100644
index 000000000..c34657125
--- /dev/null
+++ b/keyboards/claw44/keymaps/default/keymap.c
@@ -0,0 +1,169 @@
1#include QMK_KEYBOARD_H
2#ifdef PROTOCOL_LUFA
3 #include "lufa.h"
4 #include "split_util.h"
5#endif
6#ifdef SSD1306OLED
7 #include "ssd1306.h"
8#endif
9
10extern keymap_config_t keymap_config;
11
12extern uint8_t is_master;
13
14// Each layer gets a name for readability, which is then used in the keymap matrix below.
15// The underscores don't mean anything - you can have a layer called STUFF or any other name.
16// Layer names don't all need to be of the same length, obviously, and you can also skip them
17// entirely and just use numbers.
18
19enum custom_keycodes {
20 QWERTY = SAFE_RANGE,
21 LOWER,
22 RAISE
23};
24
25enum macro_keycodes {
26 KC_SAMPLEMACRO,
27};
28
29#define KC_ KC_TRNS
30#define KC_RST RESET
31#define KC_L_SPC LT(_LOWER, KC_SPC) // lower
32#define KC_R_ENT LT(_RAISE, KC_ENT) // raise
33#define KC_G_JA LGUI_T(KC_LANG1) // cmd or win
34#define KC_G_EN LGUI_T(KC_LANG2) // cmd or win
35#define KC_C_BS LCTL_T(KC_BSPC) // ctrl
36#define KC_A_DEL ALT_T(KC_DEL) // alt
37
38const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
39
40 [_QWERTY] = LAYOUT( \
41 //,--------+--------+---------+--------+---------+--------. ,--------+---------+--------+---------+--------+--------.
42 KC_ESC , KC_Q , KC_W , KC_E , KC_R , KC_T , KC_Y , KC_U , KC_I , KC_O , KC_P , KC_MINS,
43 //|--------+--------+---------+--------+---------+--------| |--------+---------+--------+---------+--------+--------|
44 KC_TAB , KC_A , KC_S , KC_D , KC_F , KC_G , KC_H , KC_J , KC_K , KC_L , KC_SCLN, KC_QUOT,
45 //|--------+--------+---------+--------+---------+--------| |--------+---------+--------+---------+--------+--------|
46 KC_LSFT, KC_Z , KC_X , KC_C , KC_V , KC_B , KC_N , KC_M , KC_COMM, KC_DOT , KC_SLSH, KC_RSFT,
47 //`--------+--------+---------+--------+---------+--------/ \--------+---------+--------+---------+--------+--------'
48 KC_A_DEL, KC_G_EN, KC_L_SPC, KC_C_BS, KC_C_BS, KC_R_ENT, KC_G_JA, KC_A_DEL
49 // `----------+--------+---------+--------' `--------+---------+--------+---------'
50 ),
51
52 // \ ^ ! & | @ = + * % -
53 // ( # $ " ' ~ ← ↓ ↑ → ` )
54 // { [ ] }
55
56 [_RAISE] = LAYOUT( \
57 //,--------+--------+--------+--------+--------+--------. ,--------+--------+--------+--------+--------+--------.
58 _______, KC_BSLS, KC_CIRC, KC_EXLM, KC_AMPR, KC_PIPE, KC_AT , KC_EQL , KC_PLUS, KC_ASTR, KC_PERC, KC_MINS,
59 //|--------+--------+--------+--------+--------+--------| |--------+--------+--------+--------+--------+--------|
60 KC_LPRN, KC_HASH, KC_DLR , KC_DQT , KC_QUOT, KC_TILD, KC_LEFT, KC_DOWN, KC_UP , KC_RGHT, KC_GRV , KC_RPRN,
61 //|--------+--------+--------+--------+--------+--------| |--------+--------+--------+--------+--------+--------|
62 _______, _______, _______, _______, KC_LCBR, KC_LBRC, KC_RBRC, KC_RCBR, _______, _______, _______, _______,
63 //`--------+--------+--------+--------+--------+--------/ \--------+--------+--------+--------+--------+--------'
64 _______, _______, _______, _______, _______, _______, _______, RESET
65 // `--------+--------+--------+--------' `--------+--------+--------+--------'
66 ),
67
68 [_LOWER] = LAYOUT( \
69 //,--------+--------+--------+--------+--------+--------. ,--------+--------+--------+--------+--------+--------.
70 KC_F1 , KC_F2 , KC_F3 , KC_F4 , KC_F5 , KC_F6 , _______, KC_EQL , KC_PLUS, KC_ASTR, KC_PERC, KC_MINS,
71 //|--------+--------+--------+--------+--------+--------| |--------+--------+--------+--------+--------+--------|
72 _______, KC_1 , KC_2 , KC_3 , KC_4 , KC_5 , KC_6 , KC_7 , KC_8 , KC_9 , KC_0 , _______,
73 //|--------+--------+--------+--------+--------+--------| |--------+--------+--------+--------+--------+--------|
74 KC_F7 , KC_F8 , KC_F9 , KC_F10 , KC_F11 , KC_F12 , _______, _______, KC_COMM, KC_DOT , KC_SLSH, _______,
75 //`--------+--------+--------+--------+--------+--------/ \--------+--------+--------+--------+--------+--------'
76 RESET , _______, _______, _______, _______, _______, _______, _______
77 // `--------+--------+--------+--------' `--------+--------+--------+--------'
78 ),
79};
80
81void matrix_init_user(void) {
82 //SSD1306 OLED init, make sure to add #define SSD1306OLED in config.h
83 #ifdef SSD1306OLED
84 iota_gfx_init(!has_usb()); // turns on the display
85 #endif
86}
87
88//SSD1306 OLED update loop, make sure to add #define SSD1306OLED in config.h
89#ifdef SSD1306OLED
90
91// When add source files to SRC in rules.mk, you can use functions.
92const char *read_layer_state(void);
93const char *read_logo(void);
94void set_keylog(uint16_t keycode, keyrecord_t *record);
95const char *read_keylog(void);
96const char *read_keylogs(void);
97
98// const char *read_mode_icon(bool swap);
99// const char *read_host_led_state(void);
100// void set_timelog(void);
101// const char *read_timelog(void);
102
103void matrix_scan_user(void) {
104 iota_gfx_task();
105}
106
107void matrix_render_user(struct CharacterMatrix *matrix) {
108 if (is_master) {
109 // If you want to change the display of OLED, you need to change here
110 matrix_write_ln(matrix, read_layer_state());
111 matrix_write_ln(matrix, read_keylog());
112 matrix_write_ln(matrix, read_keylogs());
113 //matrix_write_ln(matrix, read_mode_icon(keymap_config.swap_lalt_lgui));
114 //matrix_write_ln(matrix, read_host_led_state());
115 //matrix_write_ln(matrix, read_timelog());
116 } else {
117 matrix_write(matrix, read_logo());
118 }
119}
120
121void matrix_update(struct CharacterMatrix *dest, const struct CharacterMatrix *source) {
122 if (memcmp(dest->display, source->display, sizeof(dest->display))) {
123 memcpy(dest->display, source->display, sizeof(dest->display));
124 dest->dirty = true;
125 }
126}
127
128void iota_gfx_task_user(void) {
129 struct CharacterMatrix matrix;
130 matrix_clear(&matrix);
131 matrix_render_user(&matrix);
132 matrix_update(&display, &matrix);
133}
134#endif//SSD1306OLED
135
136bool process_record_user(uint16_t keycode, keyrecord_t *record) {
137 if (record->event.pressed) {
138#ifdef SSD1306OLED
139 set_keylog(keycode, record);
140#endif
141 // set_timelog();
142 }
143
144 switch (keycode) {
145 case QWERTY:
146 if (record->event.pressed) {
147 set_single_persistent_default_layer(_QWERTY);
148 }
149 return false;
150 break;
151 case LOWER:
152 if (record->event.pressed) {
153 layer_on(_LOWER);
154 } else {
155 layer_off(_LOWER);
156 }
157 return false;
158 break;
159 case RAISE:
160 if (record->event.pressed) {
161 layer_on(_RAISE);
162 } else {
163 layer_off(_RAISE);
164 }
165 return false;
166 break;
167 }
168 return true;
169}
diff --git a/keyboards/claw44/keymaps/yfuku/config.h b/keyboards/claw44/keymaps/yfuku/config.h
new file mode 100644
index 000000000..244ffa709
--- /dev/null
+++ b/keyboards/claw44/keymaps/yfuku/config.h
@@ -0,0 +1,36 @@
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#pragma once
22
23//#define USE_MATRIX_I2C
24
25/* Select hand configuration */
26
27#define MASTER_LEFT
28// #define MASTER_RIGHT
29// #define EE_HANDS
30
31#define SSD1306OLED
32
33#define USE_SERIAL_PD2
34
35#define TAPPING_TERM 180
36#define IGNORE_MOD_TAP_INTERRUPT
diff --git a/keyboards/claw44/keymaps/yfuku/keymap.c b/keyboards/claw44/keymaps/yfuku/keymap.c
new file mode 100644
index 000000000..77d459b92
--- /dev/null
+++ b/keyboards/claw44/keymaps/yfuku/keymap.c
@@ -0,0 +1,221 @@
1#include QMK_KEYBOARD_H
2#ifdef PROTOCOL_LUFA
3 #include "lufa.h"
4 #include "split_util.h"
5#endif
6#ifdef SSD1306OLED
7 #include "ssd1306.h"
8#endif
9
10extern keymap_config_t keymap_config;
11
12extern uint8_t is_master;
13
14// Each layer gets a name for readability, which is then used in the keymap matrix below.
15// The underscores don't mean anything - you can have a layer called STUFF or any other name.
16// Layer names don't all need to be of the same length, obviously, and you can also skip them
17// entirely and just use numbers.
18enum custom_keycodes {
19 QWERTY = SAFE_RANGE,
20 LOWER,
21 RAISE
22};
23
24enum macro_keycodes {
25 KC_SAMPLEMACRO,
26};
27
28// common
29#define KC_ KC_TRNS
30#define KC_XXXX KC_NO
31#define KC_RST RESET
32#define KC_VD KC__VOLDOWN
33#define KC_VU KC__VOLUP
34
35// layer
36#define KC_L_SPC LT(_LOWER, KC_SPC)
37#define KC_R_ENT LT(_RAISE, KC_ENT)
38
39// shift_t
40#define KC_S_TAB LSFT_T(KC_TAB)
41#define KC_S_ESC LSFT_T(KC_ESC)
42#define KC_S_JA LSFT_T(KC_LANG1)
43#define KC_S_EN LSFT_T(KC_LANG2)
44
45// cmd_t
46#define KC_M_F LCMD_T(KC_F)
47#define KC_M_D LCMD_T(KC_D)
48#define KC_M_J LCMD_T(KC_J)
49#define KC_M_K LCMD_T(KC_K)
50
51// ctl_t
52#define KC_C_S LCTL_T(KC_S)
53#define KC_C_L LCTL_T(KC_L)
54#define KC_C_BS LCTL_T(KC_BSPC)
55
56// alt_t
57#define KC_A_D ALT_T(KC_D)
58#define KC_A_K ALT_T(KC_K)
59#define KC_A_Z ALT_T(KC_Z)
60#define KC_A_SL ALT_T(KC_SLSH)
61#define KC_A_DEL ALT_T(KC_DEL)
62
63// cmd+shift_t
64#define KC_MS_Q SCMD_T(KC_Q)
65#define KC_MS_A SCMD_T(KC_A)
66#define KC_MS_S SCMD_T(KC_S)
67#define KC_MS_SC SCMD_T(KC_SCLN)
68#define KC_MS_ESC SCMD_T(KC_ESC)
69
70//
71#define KC_MR RCMD(KC_R)
72#define KC_MF RCMD(KC_F)
73#define KC_MW RCMD(KC_W)
74#define KC_MX RCMD(KC_X)
75#define KC_MC RCMD(KC_C)
76#define KC_MV RCMD(KC_V)
77#define KC_MTAB RCMD(KC_TAB)
78#define KC_MSF RCMD(RSFT(KC_F))
79#define KC_MSR RCMD(RSFT(KC_R))
80#define KC_MST RCMD(RSFT(KC_T))
81
82const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
83
84 // M_ = LCMD_T(
85 // A_ = ALT_T(
86 // C_ = LCTL_T(
87 // MS_ = SMD_T(
88 // R_ = LT(_RAISE
89 // L_ = LT(_LOWER
90
91 [_QWERTY] = LAYOUT_kc( \
92 //,----+----+----+----+----+----. ,----+----+----+----+----+----.
93 ESC , Q , W , E , R , T , Y , U , I , O , P ,MINS,
94 //|----+----+----+----+----+----| |----+----+----+----+----+----|
95 S_TAB, A ,C_S , D ,M_F , G , H ,M_J , K ,C_L ,SCLN,S_ESC,
96 //|----+----+----+----+----+----+ |----+----+----+----+----+----|
97 , Z , X , C , V , B , N , M ,COMM,DOT ,SLSH, ,
98 //`----+----+----+----+----+----/ \----+----+----+----+----+----'
99 A_DEL,S_EN,L_SPC,C_BS, C_BS,R_ENT,S_JA,A_DEL
100 // `----+----+----+----' `----+----+----+----'
101 ),
102
103 // \ ^ ! & | @ = + * % -
104 // ( # $ " ' ~ ← ↓ ↑ → ` )
105 // { [ ] }
106
107 [_RAISE] = LAYOUT_kc( \
108 //,----+----+----+----+----+----. ,----+----+----+----+----+----.
109 ,BSLS,CIRC,EXLM,AMPR,PIPE, AT ,EQL ,PLUS,ASTR,PERC,MINS,
110 //|----+----+----+----+----+----| |----+----+----+----+----+----|
111 LPRN,HASH,DLR ,DQT ,QUOT,TILD, LEFT,DOWN, UP ,RGHT,GRV ,RPRN,
112 //|----+----+----+----+----+----| |----+----+----+----+----+----|
113 , , , ,LCBR,LBRC, RBRC,RCBR, , , , ,
114 //`----+----+----+----+----+----/ \----+----+----+----+----+----'
115 , ,BSPC, , , , ,RST
116 // `----+----+----+----' `----+----+----+----'
117 ),
118
119 [_LOWER] = LAYOUT_kc( \
120 //,----+----+----+----+----+----. ,----+----+----+----+----+----.
121 , , ,MSF ,MSR ,MST , ,EQL ,PLUS,ASTR,PERC,MINS,
122 //|----+----+----+----+----+----| |----+----+----+----+----+----|
123 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 0 , ,
124 //|----+----+----+----+----+----| |----+----+----+----+----+----|
125 , , , , , , , ,COMM,DOT ,SLSH, ,
126 //`----+----+----+--+-+----+----/ \----+----+----+----+----+----'
127 RST , , , , ,DEL , ,
128 // `----+----+----+----' `----+----+----+----'
129 ),
130};
131
132void matrix_init_user(void) {
133 //SSD1306 OLED init, make sure to add #define SSD1306OLED in config.h
134 #ifdef SSD1306OLED
135 iota_gfx_init(!has_usb()); // turns on the display
136 #endif
137}
138
139//SSD1306 OLED update loop, make sure to add #define SSD1306OLED in config.h
140#ifdef SSD1306OLED
141
142// When add source files to SRC in rules.mk, you can use functions.
143const char *read_layer_state(void);
144const char *read_logo(void);
145void set_keylog(uint16_t keycode, keyrecord_t *record);
146const char *read_keylog(void);
147const char *read_keylogs(void);
148
149// const char *read_mode_icon(bool swap);
150// const char *read_host_led_state(void);
151// void set_timelog(void);
152// const char *read_timelog(void);
153
154void matrix_scan_user(void) {
155 iota_gfx_task();
156}
157
158void matrix_render_user(struct CharacterMatrix *matrix) {
159 if (is_master) {
160 // If you want to change the display of OLED, you need to change here
161 matrix_write_ln(matrix, read_layer_state());
162 matrix_write_ln(matrix, read_keylog());
163 matrix_write_ln(matrix, read_keylogs());
164 //matrix_write_ln(matrix, read_mode_icon(keymap_config.swap_lalt_lgui));
165 //matrix_write_ln(matrix, read_host_led_state());
166 //matrix_write_ln(matrix, read_timelog());
167 } else {
168 matrix_write(matrix, read_logo());
169 }
170}
171
172void matrix_update(struct CharacterMatrix *dest, const struct CharacterMatrix *source) {
173 if (memcmp(dest->display, source->display, sizeof(dest->display))) {
174 memcpy(dest->display, source->display, sizeof(dest->display));
175 dest->dirty = true;
176 }
177}
178
179void iota_gfx_task_user(void) {
180 struct CharacterMatrix matrix;
181 matrix_clear(&matrix);
182 matrix_render_user(&matrix);
183 matrix_update(&display, &matrix);
184}
185#endif//SSD1306OLED
186
187bool process_record_user(uint16_t keycode, keyrecord_t *record) {
188 if (record->event.pressed) {
189#ifdef SSD1306OLED
190 set_keylog(keycode, record);
191#endif
192 // set_timelog();
193 }
194
195 switch (keycode) {
196 case QWERTY:
197 if (record->event.pressed) {
198 set_single_persistent_default_layer(_QWERTY);
199 }
200 return false;
201 break;
202 case LOWER:
203 if (record->event.pressed) {
204 layer_on(_LOWER);
205 } else {
206 layer_off(_LOWER);
207 }
208 return false;
209 break;
210 case RAISE:
211 if (record->event.pressed) {
212 layer_on(_RAISE);
213 } else {
214 layer_off(_RAISE);
215 }
216 return false;
217 break;
218 }
219 return true;
220}
221
diff --git a/keyboards/claw44/lib/glcdfont.c b/keyboards/claw44/lib/glcdfont.c
new file mode 100644
index 000000000..91f53d9c2
--- /dev/null
+++ b/keyboards/claw44/lib/glcdfont.c
@@ -0,0 +1,243 @@
1// This is the 'classic' fixed-space bitmap font for Adafruit_GFX since 1.0.
2// See gfxfont.h for newer custom bitmap font info.
3
4#ifndef FONT5X7_H
5#define FONT5X7_H
6
7#ifdef __AVR__
8 #include <avr/io.h>
9 #include <avr/pgmspace.h>
10#elif defined(ESP8266)
11 #include <pgmspace.h>
12#else
13 #define PROGMEM
14#endif
15
16// Standard ASCII 5x7 font
17const unsigned char font[] PROGMEM = {
180x00, 0x00, 0x00, 0x00, 0x00, 0x00,
190x3E, 0x5B, 0x4F, 0x5B, 0x3E, 0x00,
200x3E, 0x6B, 0x4F, 0x6B, 0x3E, 0x00,
210x1C, 0x3E, 0x7C, 0x3E, 0x1C, 0x00,
220x18, 0x3C, 0x7E, 0x3C, 0x18, 0x00,
230x1C, 0x57, 0x7D, 0x57, 0x1C, 0x00,
240x1C, 0x5E, 0x7F, 0x5E, 0x1C, 0x00,
250x00, 0x18, 0x3C, 0x18, 0x00, 0x00,
260xFF, 0xE7, 0xC3, 0xE7, 0xFF, 0x00,
270x00, 0x18, 0x24, 0x18, 0x00, 0x00,
280xFF, 0xE7, 0xDB, 0xE7, 0xFF, 0x00,
290x30, 0x48, 0x3A, 0x06, 0x0E, 0x00,
300x26, 0x29, 0x79, 0x29, 0x26, 0x00,
310x40, 0x7F, 0x05, 0x05, 0x07, 0x00,
320x40, 0x7F, 0x05, 0x25, 0x3F, 0x00,
330x5A, 0x3C, 0xE7, 0x3C, 0x5A, 0x00,
340x7F, 0x3E, 0x1C, 0x1C, 0x08, 0x00,
350x08, 0x1C, 0x1C, 0x3E, 0x7F, 0x00,
360x14, 0x22, 0x7F, 0x22, 0x14, 0x00,
370x5F, 0x5F, 0x00, 0x5F, 0x5F, 0x00,
380x06, 0x09, 0x7F, 0x01, 0x7F, 0x00,
390x00, 0x66, 0x89, 0x95, 0x6A, 0x00,
400x60, 0x60, 0x60, 0x60, 0x60, 0x00,
410x94, 0xA2, 0xFF, 0xA2, 0x94, 0x00,
420x08, 0x04, 0x7E, 0x04, 0x08, 0x00,
430x10, 0x20, 0x7E, 0x20, 0x10, 0x00,
440x08, 0x08, 0x2A, 0x1C, 0x08, 0x00,
450x08, 0x1C, 0x2A, 0x08, 0x08, 0x00,
460x1E, 0x10, 0x10, 0x10, 0x10, 0x00,
470x0C, 0x1E, 0x0C, 0x1E, 0x0C, 0x00,
480x30, 0x38, 0x3E, 0x38, 0x30, 0x00,
490x06, 0x0E, 0x3E, 0x0E, 0x06, 0x00,
500x00, 0x00, 0x00, 0x00, 0x00, 0x00,
510x00, 0x00, 0x5F, 0x00, 0x00, 0x00,
520x00, 0x07, 0x00, 0x07, 0x00, 0x00,
530x14, 0x7F, 0x14, 0x7F, 0x14, 0x00,
540x24, 0x2A, 0x7F, 0x2A, 0x12, 0x00,
550x23, 0x13, 0x08, 0x64, 0x62, 0x00,
560x36, 0x49, 0x56, 0x20, 0x50, 0x00,
570x00, 0x08, 0x07, 0x03, 0x00, 0x00,
580x00, 0x1C, 0x22, 0x41, 0x00, 0x00,
590x00, 0x41, 0x22, 0x1C, 0x00, 0x00,
600x2A, 0x1C, 0x7F, 0x1C, 0x2A, 0x00,
610x08, 0x08, 0x3E, 0x08, 0x08, 0x00,
620x00, 0x80, 0x70, 0x30, 0x00, 0x00,
630x08, 0x08, 0x08, 0x08, 0x08, 0x00,
640x00, 0x00, 0x60, 0x60, 0x00, 0x00,
650x20, 0x10, 0x08, 0x04, 0x02, 0x00,
660x3E, 0x51, 0x49, 0x45, 0x3E, 0x00,
670x00, 0x42, 0x7F, 0x40, 0x00, 0x00,
680x72, 0x49, 0x49, 0x49, 0x46, 0x00,
690x21, 0x41, 0x49, 0x4D, 0x33, 0x00,
700x18, 0x14, 0x12, 0x7F, 0x10, 0x00,
710x27, 0x45, 0x45, 0x45, 0x39, 0x00,
720x3C, 0x4A, 0x49, 0x49, 0x31, 0x00,
730x41, 0x21, 0x11, 0x09, 0x07, 0x00,
740x36, 0x49, 0x49, 0x49, 0x36, 0x00,
750x46, 0x49, 0x49, 0x29, 0x1E, 0x00,
760x00, 0x00, 0x14, 0x00, 0x00, 0x00,
770x00, 0x40, 0x34, 0x00, 0x00, 0x00,
780x00, 0x08, 0x14, 0x22, 0x41, 0x00,
790x14, 0x14, 0x14, 0x14, 0x14, 0x00,
800x00, 0x41, 0x22, 0x14, 0x08, 0x00,
810x02, 0x01, 0x59, 0x09, 0x06, 0x00,
820x3E, 0x41, 0x5D, 0x59, 0x4E, 0x00,
830x7C, 0x12, 0x11, 0x12, 0x7C, 0x00,
840x7F, 0x49, 0x49, 0x49, 0x36, 0x00,
850x3E, 0x41, 0x41, 0x41, 0x22, 0x00,
860x7F, 0x41, 0x41, 0x41, 0x3E, 0x00,
870x7F, 0x49, 0x49, 0x49, 0x41, 0x00,
880x7F, 0x09, 0x09, 0x09, 0x01, 0x00,
890x3E, 0x41, 0x41, 0x51, 0x73, 0x00,
900x7F, 0x08, 0x08, 0x08, 0x7F, 0x00,
910x00, 0x41, 0x7F, 0x41, 0x00, 0x00,
920x20, 0x40, 0x41, 0x3F, 0x01, 0x00,
930x7F, 0x08, 0x14, 0x22, 0x41, 0x00,
940x7F, 0x40, 0x40, 0x40, 0x40, 0x00,
950x7F, 0x02, 0x1C, 0x02, 0x7F, 0x00,
960x7F, 0x04, 0x08, 0x10, 0x7F, 0x00,
970x3E, 0x41, 0x41, 0x41, 0x3E, 0x00,
980x7F, 0x09, 0x09, 0x09, 0x06, 0x00,
990x3E, 0x41, 0x51, 0x21, 0x5E, 0x00,
1000x7F, 0x09, 0x19, 0x29, 0x46, 0x00,
1010x26, 0x49, 0x49, 0x49, 0x32, 0x00,
1020x03, 0x01, 0x7F, 0x01, 0x03, 0x00,
1030x3F, 0x40, 0x40, 0x40, 0x3F, 0x00,
1040x1F, 0x20, 0x40, 0x20, 0x1F, 0x00,
1050x3F, 0x40, 0x38, 0x40, 0x3F, 0x00,
1060x63, 0x14, 0x08, 0x14, 0x63, 0x00,
1070x03, 0x04, 0x78, 0x04, 0x03, 0x00,
1080x61, 0x59, 0x49, 0x4D, 0x43, 0x00,
1090x00, 0x7F, 0x41, 0x41, 0x41, 0x00,
1100x02, 0x04, 0x08, 0x10, 0x20, 0x00,
1110x00, 0x41, 0x41, 0x41, 0x7F, 0x00,
1120x04, 0x02, 0x01, 0x02, 0x04, 0x00,
1130x40, 0x40, 0x40, 0x40, 0x40, 0x00,
1140x00, 0x03, 0x07, 0x08, 0x00, 0x00,
1150x20, 0x54, 0x54, 0x78, 0x40, 0x00,
1160x7F, 0x28, 0x44, 0x44, 0x38, 0x00,
1170x38, 0x44, 0x44, 0x44, 0x28, 0x00,
1180x38, 0x44, 0x44, 0x28, 0x7F, 0x00,
1190x38, 0x54, 0x54, 0x54, 0x18, 0x00,
1200x00, 0x08, 0x7E, 0x09, 0x02, 0x00,
1210x18, 0x24, 0x24, 0x1C, 0x78, 0x00,
1220x7F, 0x08, 0x04, 0x04, 0x78, 0x00,
1230x00, 0x44, 0x7D, 0x40, 0x00, 0x00,
1240x20, 0x40, 0x40, 0x3D, 0x00, 0x00,
1250x7F, 0x10, 0x28, 0x44, 0x00, 0x00,
1260x00, 0x41, 0x7F, 0x40, 0x00, 0x00,
1270x7C, 0x04, 0x78, 0x04, 0x78, 0x00,
1280x7C, 0x08, 0x04, 0x04, 0x78, 0x00,
1290x38, 0x44, 0x44, 0x44, 0x38, 0x00,
1300x7C, 0x18, 0x24, 0x24, 0x18, 0x00,
1310x18, 0x24, 0x24, 0x18, 0x7C, 0x00,
1320x7C, 0x08, 0x04, 0x04, 0x08, 0x00,
1330x48, 0x54, 0x54, 0x54, 0x24, 0x00,
1340x04, 0x04, 0x3F, 0x44, 0x24, 0x00,
1350x3C, 0x40, 0x40, 0x20, 0x7C, 0x00,
1360x1C, 0x20, 0x40, 0x20, 0x1C, 0x00,
1370x3C, 0x40, 0x30, 0x40, 0x3C, 0x00,
1380x44, 0x28, 0x10, 0x28, 0x44, 0x00,
1390x4C, 0x90, 0x90, 0x90, 0x7C, 0x00,
1400x44, 0x64, 0x54, 0x4C, 0x44, 0x00,
1410x00, 0x08, 0x36, 0x41, 0x00, 0x00,
1420x00, 0x00, 0x77, 0x00, 0x00, 0x00,
1430x00, 0x41, 0x36, 0x08, 0x00, 0x00,
1440x02, 0x01, 0x02, 0x04, 0x02, 0x00,
1450x3C, 0x26, 0x23, 0x26, 0x3C, 0x00,
146 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
147 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
148 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
149 0x00, 0x80, 0x80, 0x80, 0x80, 0x80,
150 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
151 0x00, 0xFC, 0xFC, 0xFC, 0xFC, 0x00,
152 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
153 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
154 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
155 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,
156 0x00, 0x80, 0x80, 0x80, 0x80, 0x00,
157 0x00, 0x00, 0x00, 0x00, 0x80, 0x80,
158 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
159 0x00, 0x80, 0xC0, 0xF0, 0xF8, 0xF8,
160 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00,
161 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
162 0xE0, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8,
163 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
164 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
165 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
166 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1670xE0, 0xF0, 0xF0, 0xF0, 0xE0, 0xEC,
1680xEE, 0xF7, 0xF3, 0x70, 0x20, 0x00,
1690x7C, 0x7C, 0x7C, 0x7E, 0x00, 0x7E,
1700x7E, 0x7E, 0x7F, 0x7F, 0x7F, 0x00,
1710x00, 0x80, 0xC0, 0xE0, 0x7E, 0x5B,
1720x4F, 0x5B, 0xFE, 0xC0, 0x00, 0x00,
1730xC0, 0x00, 0xDC, 0xD7, 0xDE, 0xDE,
1740xDE, 0xD7, 0xDC, 0x00, 0xC0, 0x00,
1750x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1760x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1770x00, 0x00, 0x00, 0x00, 0x00, 0x00,
178 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
179 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
180 0x00, 0x00, 0x00, 0xF8, 0xFC, 0xFE,
181 0xFF, 0x1F, 0x07, 0x07, 0x07, 0x07,
182 0x1F, 0x1F, 0x1F, 0x1E, 0x18, 0x00,
183 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
184 0x00, 0x00, 0x00, 0x9E, 0xDF, 0xDF,
185 0xCF, 0xC7, 0xE7, 0xE7, 0xE7, 0xFF,
186 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x03,
187 0x3F, 0xFF, 0xFF, 0xFE, 0xC0, 0x00,
188 0xF0, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF,
189 0xF0, 0x00, 0xC0, 0xFC, 0xFF, 0xFF,
190 0x3F, 0x03, 0x00, 0xC0, 0xF0, 0xF8,
191 0xFE, 0x9F, 0x87, 0x83, 0x80, 0xFF,
192 0xFF, 0xFF, 0xFF, 0x80, 0x80, 0x00,
193 0x00, 0xE0, 0xF8, 0xFC, 0xBF, 0x8F,
194 0x83, 0x81, 0xFF, 0xFF, 0xFF, 0xFF,
195 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,
196 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
197 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
198 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1990x0F, 0x1F, 0x3F, 0x7F, 0x7F, 0x7F,
2000x7F, 0x7F, 0x3F, 0x1E, 0x0C, 0x00,
2010x1F, 0x1F, 0x1F, 0x3F, 0x00, 0x3F,
2020x3F, 0x3F, 0x7F, 0x7F, 0x7F, 0x00,
2030x30, 0x7B, 0x7F, 0x78, 0x30, 0x20,
2040x20, 0x30, 0x78, 0x7F, 0x3B, 0x00,
2050x03, 0x00, 0x0F, 0x7F, 0x0F, 0x0F,
2060x0F, 0x7F, 0x0F, 0x00, 0x03, 0x00,
2070x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2080x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2090x00, 0x00, 0x00, 0x00, 0x00, 0x00,
210 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
211 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
212 0x00, 0x00, 0x00, 0x07, 0x1F, 0x3F,
213 0x7F, 0x7C, 0x78, 0x70, 0x70, 0x78,
214 0x7E, 0x3E, 0x3E, 0x0E, 0x06, 0x00,
215 0x00, 0x7F, 0x7F, 0x7F, 0x7F, 0x00,
216 0x00, 0x00, 0x1F, 0x3F, 0x7F, 0x7F,
217 0x79, 0x71, 0x70, 0x30, 0x38, 0x3F,
218 0x7F, 0x7F, 0x7F, 0x60, 0x00, 0x00,
219 0x00, 0x01, 0x1F, 0x7F, 0x7F, 0x7E,
220 0x7F, 0x1F, 0x01, 0x00, 0x01, 0x3F,
221 0x7F, 0x7E, 0x7F, 0x7F, 0x0F, 0x01,
222 0x00, 0x00, 0x00, 0x03, 0x03, 0x03,
223 0x03, 0x03, 0x03, 0x03, 0x03, 0x7F,
224 0x7F, 0x7F, 0x7F, 0x03, 0x03, 0x00,
225 0x00, 0x03, 0x03, 0x03, 0x03, 0x03,
226 0x03, 0x03, 0x7F, 0x7F, 0x7F, 0x7F,
227 0x07, 0x03, 0x03, 0x00, 0x00, 0x00,
228 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
229 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
230 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2310x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2320x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2330x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2340x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2350x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2360x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2370x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2380x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2390x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2400x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2410x00, 0x00, 0x00, 0x00, 0x00, 0x00,
242};
243#endif // FONT5X7_H
diff --git a/keyboards/claw44/lib/host_led_state_reader.c b/keyboards/claw44/lib/host_led_state_reader.c
new file mode 100644
index 000000000..980823b31
--- /dev/null
+++ b/keyboards/claw44/lib/host_led_state_reader.c
@@ -0,0 +1,15 @@
1#include <stdio.h>
2#include "claw44.h"
3
4char host_led_state_str[24];
5
6const char *read_host_led_state(void)
7{
8 uint8_t leds = host_keyboard_leds();
9 snprintf(host_led_state_str, sizeof(host_led_state_str), "NL:%s CL:%s SL:%s",
10 (leds & (1 << USB_LED_NUM_LOCK)) ? "on" : "- ",
11 (leds & (1 << USB_LED_CAPS_LOCK)) ? "on" : "- ",
12 (leds & (1 << USB_LED_SCROLL_LOCK)) ? "on" : "- ");
13
14 return host_led_state_str;
15}
diff --git a/keyboards/claw44/lib/keylogger.c b/keyboards/claw44/lib/keylogger.c
new file mode 100644
index 000000000..092b6929b
--- /dev/null
+++ b/keyboards/claw44/lib/keylogger.c
@@ -0,0 +1,45 @@
1#include <stdio.h>
2#include "claw44.h"
3
4char keylog_str[24] = {};
5char keylogs_str[21] = {};
6int keylogs_str_idx = 0;
7
8const char code_to_name[60] = {
9 ' ', ' ', ' ', ' ', 'a', 'b', 'c', 'd', 'e', 'f',
10 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
11 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
12 '1', '2', '3', '4', '5', '6', '7', '8', '9', '0',
13 'R', 'E', 'B', 'T', ' ', ' ', ' ', ' ', ' ', ' ',
14 ' ', ';', '\'', ' ', ',', '.', '/', ' ', ' ', ' '};
15
16void set_keylog(uint16_t keycode, keyrecord_t *record) {
17 char name = ' ';
18 if (keycode < 60) {
19 name = code_to_name[keycode];
20 }
21
22 // update keylog
23 snprintf(keylog_str, sizeof(keylog_str), "%dx%d, k%2d : %c",
24 record->event.key.row, record->event.key.col,
25 keycode, name);
26
27 // update keylogs
28 if (keylogs_str_idx == sizeof(keylogs_str) - 1) {
29 keylogs_str_idx = 0;
30 for (int i = 0; i < sizeof(keylogs_str) - 1; i++) {
31 keylogs_str[i] = ' ';
32 }
33 }
34
35 keylogs_str[keylogs_str_idx] = name;
36 keylogs_str_idx++;
37}
38
39const char *read_keylog(void) {
40 return keylog_str;
41}
42
43const char *read_keylogs(void) {
44 return keylogs_str;
45}
diff --git a/keyboards/claw44/lib/layer_state_reader.c b/keyboards/claw44/lib/layer_state_reader.c
new file mode 100644
index 000000000..d92b6df58
--- /dev/null
+++ b/keyboards/claw44/lib/layer_state_reader.c
@@ -0,0 +1,35 @@
1
2#include QMK_KEYBOARD_H
3#include <stdio.h>
4#include "claw44.h"
5
6#define L_BASE 0
7#define L_LOWER (1<<_LOWER)
8#define L_RAISE (1<<_RAISE)
9#define L_ADJUST (1<<_ADJUST)
10#define L_ADJUST_TRI (L_ADJUST|L_RAISE|L_LOWER)
11
12char layer_state_str[24];
13
14const char *read_layer_state(void) {
15 switch (layer_state)
16 {
17 case L_BASE:
18 snprintf(layer_state_str, sizeof(layer_state_str), "Layer: Default");
19 break;
20 case L_RAISE:
21 snprintf(layer_state_str, sizeof(layer_state_str), "Layer: Raise");
22 break;
23 case L_LOWER:
24 snprintf(layer_state_str, sizeof(layer_state_str), "Layer: Lower");
25 break;
26 case L_ADJUST:
27 case L_ADJUST_TRI:
28 snprintf(layer_state_str, sizeof(layer_state_str), "Layer: Adjust");
29 break;
30 default:
31 snprintf(layer_state_str, sizeof(layer_state_str), "Layer: Undef-%ld", layer_state);
32 }
33
34 return layer_state_str;
35}
diff --git a/keyboards/claw44/lib/logo_reader.c b/keyboards/claw44/lib/logo_reader.c
new file mode 100644
index 000000000..b5b437b2b
--- /dev/null
+++ b/keyboards/claw44/lib/logo_reader.c
@@ -0,0 +1,11 @@
1#include "claw44.h"
2
3const char *read_logo(void) {
4 static char logo[] = {
5 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94,
6 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4,
7 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4,
8 0};
9
10 return logo;
11}
diff --git a/keyboards/claw44/lib/mode_icon_reader.c b/keyboards/claw44/lib/mode_icon_reader.c
new file mode 100644
index 000000000..a9272bb9a
--- /dev/null
+++ b/keyboards/claw44/lib/mode_icon_reader.c
@@ -0,0 +1,15 @@
1#include <stdio.h>
2#include "claw44.h"
3
4char mode_icon[24];
5
6const char *read_mode_icon(bool swap) {
7 static char logo[][2][3] = {{{0x95, 0x96, 0}, {0xb5, 0xb6, 0}}, {{0x97, 0x98, 0}, {0xb7, 0xb8, 0}}};
8 if (swap == false) {
9 snprintf(mode_icon, sizeof(mode_icon), "%s\n%s", logo[0][0], logo[0][1]);
10 } else {
11 snprintf(mode_icon, sizeof(mode_icon), "%s\n%s", logo[1][0], logo[1][1]);
12 }
13
14 return mode_icon;
15}
diff --git a/keyboards/claw44/lib/rgb_state_reader.c b/keyboards/claw44/lib/rgb_state_reader.c
new file mode 100644
index 000000000..e0efe2e52
--- /dev/null
+++ b/keyboards/claw44/lib/rgb_state_reader.c
@@ -0,0 +1,15 @@
1#ifdef RGBLIGHT_ENABLE
2
3#include QMK_KEYBOARD_H
4#include <stdio.h>
5
6extern rgblight_config_t rgblight_config;
7char rbf_info_str[24];
8const char *read_rgb_info(void) {
9
10 snprintf(rbf_info_str, sizeof(rbf_info_str), "%s %2d h%3d s%3d v%3d",
11 rgblight_config.enable ? "on" : "- ", rgblight_config.mode,
12 rgblight_config.hue, rgblight_config.sat, rgblight_config.val);
13 return rbf_info_str;
14}
15#endif
diff --git a/keyboards/claw44/lib/timelogger.c b/keyboards/claw44/lib/timelogger.c
new file mode 100644
index 000000000..ecd4ed3ea
--- /dev/null
+++ b/keyboards/claw44/lib/timelogger.c
@@ -0,0 +1,16 @@
1#include <stdio.h>
2#include "claw44.h"
3
4char timelog_str[24] = {};
5int last_time = 0;
6int elapsed_time = 0;
7
8void set_timelog(void) {
9 elapsed_time = timer_elapsed(last_time);
10 last_time = timer_read();
11 snprintf(timelog_str, sizeof(timelog_str), "lt:%5d, et:%5d", last_time, elapsed_time);
12}
13
14const char *read_timelog(void) {
15 return timelog_str;
16}
diff --git a/keyboards/claw44/readme.md b/keyboards/claw44/readme.md
new file mode 100644
index 000000000..7e72e0897
--- /dev/null
+++ b/keyboards/claw44/readme.md
@@ -0,0 +1,15 @@
1# Claw44
2
3![Claw44](https://i.imgur.com/5a8iogl.jpg)
4
5A split keyboard with 3x6 vertically staggered keys and 4 thumb keys.
6
7Keyboard Maintainer: [@yfuku_](https://twitter.com/yfuku_)
8Hardware Supported: Claw44 PCB, ProMicro
9Hardware Availability: https://yfuku.booth.pm/
10
11Make example for this keyboard (after setting up your build environment):
12
13 make claw44: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/claw44/rev1/config.h b/keyboards/claw44/rev1/config.h
new file mode 100644
index 000000000..ba2ed4559
--- /dev/null
+++ b/keyboards/claw44/rev1/config.h
@@ -0,0 +1,76 @@
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#pragma once
20
21/* USB Device descriptor parameter */
22#define VENDOR_ID 0xFEED
23#define PRODUCT_ID 0x3060
24#define DEVICE_VER 0x0001
25#define MANUFACTURER yfuku
26#define PRODUCT claw44
27#define DESCRIPTION A split keyboard with 3x6 vertically staggered keys and 4 thumb keys
28
29/* key matrix size */
30// Rows are doubled-up
31#define MATRIX_ROWS 8
32#define MATRIX_COLS 7
33#define MATRIX_ROW_PINS { D4, C6, D7, E6 }
34
35// wiring of each half
36#define MATRIX_COL_PINS { F4, F5, F6, F7, B1, B3, B2 }
37// #define MATRIX_COL_PINS { B2, B3, B1, F7, F6, F5, F4 } //uncomment this line and comment line above if you need to reverse left-to-right key order
38
39/* define if matrix has ghost */
40//#define MATRIX_HAS_GHOST
41
42/* number of backlight levels */
43// #define BACKLIGHT_LEVELS 3
44
45/* Set 0 if debouncing isn't needed */
46#define DEBOUNCING_DELAY 5
47
48/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
49//#define LOCKING_SUPPORT_ENABLE
50/* Locking resynchronize hack */
51//#define LOCKING_RESYNC_ENABLE
52
53/* ws2812 RGB LED */
54/*
55#define RGB_DI_PIN D3
56
57#define RGBLED_NUM 12 // Number of LEDs
58*/
59
60/*
61 * Feature disable options
62 * These options are also useful to firmware size reduction.
63 */
64
65/* disable debug print */
66// #define NO_DEBUG
67
68/* disable print */
69// #define NO_PRINT
70
71/* disable action features */
72//#define NO_ACTION_LAYER
73//#define NO_ACTION_TAPPING
74//#define NO_ACTION_ONESHOT
75//#define NO_ACTION_MACRO
76//#define NO_ACTION_FUNCTION
diff --git a/keyboards/claw44/rev1/matrix.c b/keyboards/claw44/rev1/matrix.c
new file mode 100644
index 000000000..718cc5744
--- /dev/null
+++ b/keyboards/claw44/rev1/matrix.c
@@ -0,0 +1,357 @@
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 <string.h>
24#include <avr/io.h>
25#include <avr/wdt.h>
26#include <avr/interrupt.h>
27#include <util/delay.h>
28#include "print.h"
29#include "debug.h"
30#include "util.h"
31#include "matrix.h"
32#include "split_util.h"
33#include "pro_micro.h"
34
35#ifdef USE_MATRIX_I2C
36# include "i2c.h"
37#else // USE_SERIAL
38# include "split_scomm.h"
39#endif
40
41#ifndef DEBOUNCE
42# define DEBOUNCE 5
43#endif
44
45#define ERROR_DISCONNECT_COUNT 5
46
47static uint8_t debouncing = DEBOUNCE;
48static const int ROWS_PER_HAND = MATRIX_ROWS/2;
49static uint8_t error_count = 0;
50uint8_t is_master = 0 ;
51
52static const uint8_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
53static const uint8_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
54
55/* matrix state(1:on, 0:off) */
56static matrix_row_t matrix[MATRIX_ROWS];
57static matrix_row_t matrix_debouncing[MATRIX_ROWS];
58
59static matrix_row_t read_cols(void);
60static void init_cols(void);
61static void unselect_rows(void);
62static void select_row(uint8_t row);
63static uint8_t matrix_master_scan(void);
64
65
66__attribute__ ((weak))
67void matrix_init_kb(void) {
68 matrix_init_user();
69}
70
71__attribute__ ((weak))
72void matrix_scan_kb(void) {
73 matrix_scan_user();
74}
75
76__attribute__ ((weak))
77void matrix_init_user(void) {
78}
79
80__attribute__ ((weak))
81void matrix_scan_user(void) {
82}
83
84inline
85uint8_t matrix_rows(void)
86{
87 return MATRIX_ROWS;
88}
89
90inline
91uint8_t matrix_cols(void)
92{
93 return MATRIX_COLS;
94}
95
96void matrix_init(void)
97{
98 debug_enable = true;
99 debug_matrix = true;
100 debug_mouse = true;
101 // initialize row and col
102 unselect_rows();
103 init_cols();
104
105 TX_RX_LED_INIT;
106 TXLED0;
107 RXLED0;
108
109 // initialize matrix state: all keys off
110 for (uint8_t i=0; i < MATRIX_ROWS; i++) {
111 matrix[i] = 0;
112 matrix_debouncing[i] = 0;
113 }
114
115 is_master = has_usb();
116
117 matrix_init_quantum();
118}
119
120uint8_t _matrix_scan(void)
121{
122 // Right hand is stored after the left in the matirx so, we need to offset it
123 int offset = isLeftHand ? 0 : (ROWS_PER_HAND);
124
125 for (uint8_t i = 0; i < ROWS_PER_HAND; i++) {
126 select_row(i);
127 _delay_us(30); // without this wait read unstable value.
128 matrix_row_t cols = read_cols();
129 if (matrix_debouncing[i+offset] != cols) {
130 matrix_debouncing[i+offset] = cols;
131 debouncing = DEBOUNCE;
132 }
133 unselect_rows();
134 }
135
136 if (debouncing) {
137 if (--debouncing) {
138 _delay_ms(1);
139 } else {
140 for (uint8_t i = 0; i < ROWS_PER_HAND; i++) {
141 matrix[i+offset] = matrix_debouncing[i+offset];
142 }
143 }
144 }
145
146 return 1;
147}
148
149#ifdef USE_MATRIX_I2C
150
151// Get rows from other half over i2c
152int i2c_transaction(void) {
153 int slaveOffset = (isLeftHand) ? (ROWS_PER_HAND) : 0;
154
155 int err = i2c_master_start(SLAVE_I2C_ADDRESS + I2C_WRITE);
156 if (err) goto i2c_error;
157
158 // start of matrix stored at 0x00
159 err = i2c_master_write(0x00);
160 if (err) goto i2c_error;
161
162 // Start read
163 err = i2c_master_start(SLAVE_I2C_ADDRESS + I2C_READ);
164 if (err) goto i2c_error;
165
166 if (!err) {
167 int i;
168 for (i = 0; i < ROWS_PER_HAND-1; ++i) {
169 matrix[slaveOffset+i] = i2c_master_read(I2C_ACK);
170 }
171 matrix[slaveOffset+i] = i2c_master_read(I2C_NACK);
172 i2c_master_stop();
173 } else {
174i2c_error: // the cable is disconnceted, or something else went wrong
175 i2c_reset_state();
176 return err;
177 }
178
179 return 0;
180}
181
182#else // USE_SERIAL
183
184int serial_transaction(int master_changed) {
185 int slaveOffset = (isLeftHand) ? (ROWS_PER_HAND) : 0;
186#ifdef SERIAL_USE_MULTI_TRANSACTION
187 int ret=serial_update_buffers(master_changed);
188#else
189 int ret=serial_update_buffers();
190#endif
191 if (ret ) {
192 if(ret==2) RXLED1;
193 return 1;
194 }
195 RXLED0;
196 memcpy(&matrix[slaveOffset],
197 (void *)serial_slave_buffer, SERIAL_SLAVE_BUFFER_LENGTH);
198 return 0;
199}
200#endif
201
202uint8_t matrix_scan(void)
203{
204 if (is_master) {
205 matrix_master_scan();
206 }else{
207 matrix_slave_scan();
208 int offset = (isLeftHand) ? ROWS_PER_HAND : 0;
209 memcpy(&matrix[offset],
210 (void *)serial_master_buffer, SERIAL_MASTER_BUFFER_LENGTH);
211 matrix_scan_quantum();
212 }
213 return 1;
214}
215
216
217uint8_t matrix_master_scan(void) {
218
219 int ret = _matrix_scan();
220 int mchanged = 1;
221
222 int offset = (isLeftHand) ? 0 : ROWS_PER_HAND;
223
224#ifdef USE_MATRIX_I2C
225// for (int i = 0; i < ROWS_PER_HAND; ++i) {
226 /* i2c_slave_buffer[i] = matrix[offset+i]; */
227// i2c_slave_buffer[i] = matrix[offset+i];
228// }
229#else // USE_SERIAL
230 #ifdef SERIAL_USE_MULTI_TRANSACTION
231 mchanged = memcmp((void *)serial_master_buffer,
232 &matrix[offset], SERIAL_MASTER_BUFFER_LENGTH);
233 #endif
234 memcpy((void *)serial_master_buffer,
235 &matrix[offset], SERIAL_MASTER_BUFFER_LENGTH);
236#endif
237
238#ifdef USE_MATRIX_I2C
239 if( i2c_transaction() ) {
240#else // USE_SERIAL
241 if( serial_transaction(mchanged) ) {
242#endif
243 // turn on the indicator led when halves are disconnected
244 TXLED1;
245
246 error_count++;
247
248 if (error_count > ERROR_DISCONNECT_COUNT) {
249 // reset other half if disconnected
250 int slaveOffset = (isLeftHand) ? (ROWS_PER_HAND) : 0;
251 for (int i = 0; i < ROWS_PER_HAND; ++i) {
252 matrix[slaveOffset+i] = 0;
253 }
254 }
255 } else {
256 // turn off the indicator led on no error
257 TXLED0;
258 error_count = 0;
259 }
260 matrix_scan_quantum();
261 return ret;
262}
263
264void matrix_slave_scan(void) {
265 _matrix_scan();
266
267 int offset = (isLeftHand) ? 0 : ROWS_PER_HAND;
268
269#ifdef USE_MATRIX_I2C
270 for (int i = 0; i < ROWS_PER_HAND; ++i) {
271 /* i2c_slave_buffer[i] = matrix[offset+i]; */
272 i2c_slave_buffer[i] = matrix[offset+i];
273 }
274#else // USE_SERIAL
275 #ifdef SERIAL_USE_MULTI_TRANSACTION
276 int change = 0;
277 #endif
278 for (int i = 0; i < ROWS_PER_HAND; ++i) {
279 #ifdef SERIAL_USE_MULTI_TRANSACTION
280 if( serial_slave_buffer[i] != matrix[offset+i] )
281 change = 1;
282 #endif
283 serial_slave_buffer[i] = matrix[offset+i];
284 }
285 #ifdef SERIAL_USE_MULTI_TRANSACTION
286 slave_buffer_change_count += change;
287 #endif
288#endif
289}
290
291bool matrix_is_modified(void)
292{
293 if (debouncing) return false;
294 return true;
295}
296
297inline
298bool matrix_is_on(uint8_t row, uint8_t col)
299{
300 return (matrix[row] & ((matrix_row_t)1<<col));
301}
302
303inline
304matrix_row_t matrix_get_row(uint8_t row)
305{
306 return matrix[row];
307}
308
309void matrix_print(void)
310{
311 print("\nr/c 0123456789ABCDEF\n");
312 for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
313 phex(row); print(": ");
314 pbin_reverse16(matrix_get_row(row));
315 print("\n");
316 }
317}
318
319uint8_t matrix_key_count(void)
320{
321 uint8_t count = 0;
322 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
323 count += bitpop16(matrix[i]);
324 }
325 return count;
326}
327
328static void init_cols(void)
329{
330 for(int x = 0; x < MATRIX_COLS; x++) {
331 _SFR_IO8((col_pins[x] >> 4) + 1) &= ~_BV(col_pins[x] & 0xF);
332 _SFR_IO8((col_pins[x] >> 4) + 2) |= _BV(col_pins[x] & 0xF);
333 }
334}
335
336static matrix_row_t read_cols(void)
337{
338 matrix_row_t result = 0;
339 for(int x = 0; x < MATRIX_COLS; x++) {
340 result |= (_SFR_IO8(col_pins[x] >> 4) & _BV(col_pins[x] & 0xF)) ? 0 : (1 << x);
341 }
342 return result;
343}
344
345static void unselect_rows(void)
346{
347 for(int x = 0; x < ROWS_PER_HAND; x++) {
348 _SFR_IO8((row_pins[x] >> 4) + 1) &= ~_BV(row_pins[x] & 0xF);
349 _SFR_IO8((row_pins[x] >> 4) + 2) |= _BV(row_pins[x] & 0xF);
350 }
351}
352
353static void select_row(uint8_t row)
354{
355 _SFR_IO8((row_pins[row] >> 4) + 1) |= _BV(row_pins[row] & 0xF);
356 _SFR_IO8((row_pins[row] >> 4) + 2) &= ~_BV(row_pins[row] & 0xF);
357}
diff --git a/keyboards/claw44/rev1/rev1.c b/keyboards/claw44/rev1/rev1.c
new file mode 100644
index 000000000..9529636f5
--- /dev/null
+++ b/keyboards/claw44/rev1/rev1.c
@@ -0,0 +1,8 @@
1#include "claw44.h"
2
3#ifdef SSD1306OLED
4void led_set_kb(uint8_t usb_led) {
5 // put your keyboard LED indicator (ex: Caps Lock LED) toggling code here
6 //led_set_user(usb_led);
7}
8#endif
diff --git a/keyboards/claw44/rev1/rev1.h b/keyboards/claw44/rev1/rev1.h
new file mode 100644
index 000000000..f7ec2cbfe
--- /dev/null
+++ b/keyboards/claw44/rev1/rev1.h
@@ -0,0 +1,57 @@
1#pragma once
2
3#include "../claw44.h"
4
5//void promicro_bootloader_jmp(bool program);
6#include "quantum.h"
7
8#ifdef RGBLIGHT_ENABLE
9//rgb led driver
10#include "ws2812.h"
11#endif
12
13#ifdef USE_I2C
14#include <stddef.h>
15#ifdef __AVR__
16 #include <avr/io.h>
17 #include <avr/interrupt.h>
18#endif
19#endif
20
21//void promicro_bootloader_jmp(bool program);
22#define LAYOUT( \
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, R30, R31, R32, R33 \
27 ) \
28 { \
29 { L00, L01, L02, L03, L04, L05 }, \
30 { L10, L11, L12, L13, L14, L15 }, \
31 { L20, L21, L22, L23, L24, L25 }, \
32 { KC_NO, KC_NO, L30, L31, L32, L33 }, \
33 { R05, R04, R03, R02, R01, R00 }, \
34 { R15, R14, R13, R12, R11, R10 }, \
35 { R25, R24, R23, R22, R21, R20 }, \
36 { KC_NO, KC_NO, R33, R32, R31, R30 } \
37 }
38
39#define LAYOUT_kc( \
40 L00, L01, L02, L03, L04, L05, R00, R01, R02, R03, R04, R05, \
41 L10, L11, L12, L13, L14, L15, R10, R11, R12, R13, R14, R15, \
42 L20, L21, L22, L23, L24, L25, R20, R21, R22, R23, R24, R25, \
43 L30, L31, L32, L33, R30, R31, R32, R33 \
44 ) \
45 LAYOUT( \
46 KC_##L00, KC_##L01, KC_##L02, KC_##L03, KC_##L04, KC_##L05, KC_##R00, KC_##R01, KC_##R02, KC_##R03, KC_##R04, KC_##R05, \
47 KC_##L10, KC_##L11, KC_##L12, KC_##L13, KC_##L14, KC_##L15, KC_##R10, KC_##R11, KC_##R12, KC_##R13, KC_##R14, KC_##R15, \
48 KC_##L20, KC_##L21, KC_##L22, KC_##L23, KC_##L24, KC_##L25, KC_##R20, KC_##R21, KC_##R22, KC_##R23, KC_##R24, KC_##R25, \
49 KC_##L30, KC_##L31, KC_##L32, KC_##L33, KC_##R30, KC_##R31, KC_##R32, KC_##R33 \
50 )
51
52enum layer_number {
53 _QWERTY = 0,
54 _LOWER,
55 _RAISE,
56 _ADJUST,
57};
diff --git a/keyboards/claw44/rev1/rules.mk b/keyboards/claw44/rev1/rules.mk
new file mode 100644
index 000000000..ae95ec401
--- /dev/null
+++ b/keyboards/claw44/rev1/rules.mk
@@ -0,0 +1,31 @@
1SRC += rev1/matrix.c
2SRC += rev1/split_util.c
3SRC += rev1/split_scomm.c
4
5# Build Options
6BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration(+1000)
7MOUSEKEY_ENABLE = no # Mouse keys(+4700)
8EXTRAKEY_ENABLE = no # Audio control and System control(+450)
9CONSOLE_ENABLE = no # Console for debug(+400)
10COMMAND_ENABLE = no # Commands for debug and configuration
11NKRO_ENABLE = no # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
12BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality
13MIDI_ENABLE = no # MIDI controls
14AUDIO_ENABLE = no # Audio output on port C6
15UNICODE_ENABLE = no # Unicode
16BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID
17RGBLIGHT_ENABLE = no # Enable WS2812 RGB underlight.
18SWAP_HANDS_ENABLE = no # Enable one-hand typing
19
20# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
21SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
22
23# If you want to change the display of OLED, you need to change here
24SRC += ./lib/glcdfont.c \
25 ./lib/layer_state_reader.c \
26 ./lib/logo_reader.c \
27 ./lib/keylogger.c \
28 # ./lib/rgb_state_reader.c \
29 # ./lib/mode_icon_reader.c \
30 # ./lib/host_led_state_reader.c \
31 # ./lib/timelogger.c \
diff --git a/keyboards/claw44/rev1/serial_config.h b/keyboards/claw44/rev1/serial_config.h
new file mode 100644
index 000000000..4fab8e8dd
--- /dev/null
+++ b/keyboards/claw44/rev1/serial_config.h
@@ -0,0 +1,4 @@
1#ifndef SOFT_SERIAL_PIN
2#define SOFT_SERIAL_PIN D2
3#define SERIAL_USE_MULTI_TRANSACTION
4#endif
diff --git a/keyboards/claw44/rev1/split_scomm.c b/keyboards/claw44/rev1/split_scomm.c
new file mode 100644
index 000000000..a1fe6ba5b
--- /dev/null
+++ b/keyboards/claw44/rev1/split_scomm.c
@@ -0,0 +1,91 @@
1#ifdef USE_SERIAL
2#ifdef SERIAL_USE_MULTI_TRANSACTION
3/* --- USE flexible API (using multi-type transaction function) --- */
4
5#include <stdbool.h>
6#include <stdint.h>
7#include <stddef.h>
8#include <split_scomm.h>
9#include "serial.h"
10#ifdef CONSOLE_ENABLE
11 #include <print.h>
12#endif
13
14uint8_t volatile serial_slave_buffer[SERIAL_SLAVE_BUFFER_LENGTH] = {0};
15uint8_t volatile serial_master_buffer[SERIAL_MASTER_BUFFER_LENGTH] = {0};
16uint8_t volatile status_com = 0;
17uint8_t volatile status1 = 0;
18uint8_t slave_buffer_change_count = 0;
19uint8_t s_change_old = 0xff;
20uint8_t s_change_new = 0xff;
21
22SSTD_t transactions[] = {
23#define GET_SLAVE_STATUS 0
24 /* master buffer not changed, only recive slave_buffer_change_count */
25 { (uint8_t *)&status_com,
26 0, NULL,
27 sizeof(slave_buffer_change_count), &slave_buffer_change_count,
28 },
29#define PUT_MASTER_GET_SLAVE_STATUS 1
30 /* master buffer changed need send, and recive slave_buffer_change_count */
31 { (uint8_t *)&status_com,
32 sizeof(serial_master_buffer), (uint8_t *)serial_master_buffer,
33 sizeof(slave_buffer_change_count), &slave_buffer_change_count,
34 },
35#define GET_SLAVE_BUFFER 2
36 /* recive serial_slave_buffer */
37 { (uint8_t *)&status1,
38 0, NULL,
39 sizeof(serial_slave_buffer), (uint8_t *)serial_slave_buffer
40 }
41};
42
43void serial_master_init(void)
44{
45 soft_serial_initiator_init(transactions, TID_LIMIT(transactions));
46}
47
48void serial_slave_init(void)
49{
50 soft_serial_target_init(transactions, TID_LIMIT(transactions));
51}
52
53// 0 => no error
54// 1 => slave did not respond
55// 2 => checksum error
56int serial_update_buffers(int master_update)
57{
58 int status, smatstatus;
59 static int need_retry = 0;
60
61 if( s_change_old != s_change_new ) {
62 smatstatus = soft_serial_transaction(GET_SLAVE_BUFFER);
63 if( smatstatus == TRANSACTION_END ) {
64 s_change_old = s_change_new;
65#ifdef CONSOLE_ENABLE
66 uprintf("slave matrix = %b %b %b %b\n",
67 serial_slave_buffer[0], serial_slave_buffer[1],
68 serial_slave_buffer[2], serial_slave_buffer[3]);
69#endif
70 }
71 } else {
72 // serial_slave_buffer dosen't change
73 smatstatus = TRANSACTION_END; // dummy status
74 }
75
76 if( !master_update && !need_retry) {
77 status = soft_serial_transaction(GET_SLAVE_STATUS);
78 } else {
79 status = soft_serial_transaction(PUT_MASTER_GET_SLAVE_STATUS);
80 }
81 if( status == TRANSACTION_END ) {
82 s_change_new = slave_buffer_change_count;
83 need_retry = 0;
84 } else {
85 need_retry = 1;
86 }
87 return smatstatus;
88}
89
90#endif // SERIAL_USE_MULTI_TRANSACTION
91#endif /* USE_SERIAL */
diff --git a/keyboards/claw44/rev1/split_scomm.h b/keyboards/claw44/rev1/split_scomm.h
new file mode 100644
index 000000000..873d8939d
--- /dev/null
+++ b/keyboards/claw44/rev1/split_scomm.h
@@ -0,0 +1,24 @@
1#ifndef SPLIT_COMM_H
2#define SPLIT_COMM_H
3
4#ifndef SERIAL_USE_MULTI_TRANSACTION
5/* --- USE Simple API (OLD API, compatible with let's split serial.c) --- */
6#include "serial.h"
7
8#else
9/* --- USE flexible API (using multi-type transaction function) --- */
10// Buffers for master - slave communication
11#define SERIAL_SLAVE_BUFFER_LENGTH MATRIX_ROWS/2
12#define SERIAL_MASTER_BUFFER_LENGTH MATRIX_ROWS/2
13
14extern volatile uint8_t serial_slave_buffer[SERIAL_SLAVE_BUFFER_LENGTH];
15extern volatile uint8_t serial_master_buffer[SERIAL_MASTER_BUFFER_LENGTH];
16extern uint8_t slave_buffer_change_count;
17
18void serial_master_init(void);
19void serial_slave_init(void);
20int serial_update_buffers(int master_changed);
21
22#endif
23
24#endif /* SPLIT_COMM_H */
diff --git a/keyboards/claw44/rev1/split_util.c b/keyboards/claw44/rev1/split_util.c
new file mode 100644
index 000000000..e1ff8b437
--- /dev/null
+++ b/keyboards/claw44/rev1/split_util.c
@@ -0,0 +1,70 @@
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
11#ifdef USE_MATRIX_I2C
12# include "i2c.h"
13#else
14# include "split_scomm.h"
15#endif
16
17volatile bool isLeftHand = true;
18
19static void setup_handedness(void) {
20 #ifdef EE_HANDS
21 isLeftHand = eeprom_read_byte(EECONFIG_HANDEDNESS);
22 #else
23 // I2C_MASTER_RIGHT is deprecated, use MASTER_RIGHT instead, since this works for both serial and i2c
24 #if defined(I2C_MASTER_RIGHT) || defined(MASTER_RIGHT)
25 isLeftHand = !has_usb();
26 #else
27 isLeftHand = has_usb();
28 #endif
29 #endif
30}
31
32static void keyboard_master_setup(void) {
33
34#ifdef USE_MATRIX_I2C
35 i2c_master_init();
36#else
37 serial_master_init();
38#endif
39}
40
41static void keyboard_slave_setup(void) {
42
43#ifdef USE_MATRIX_I2C
44 i2c_slave_init(SLAVE_I2C_ADDRESS);
45#else
46 serial_slave_init();
47#endif
48}
49
50bool has_usb(void) {
51 USBCON |= (1 << OTGPADE); //enables VBUS pad
52 _delay_us(5);
53 return (USBSTA & (1<<VBUS)); //checks state of VBUS
54}
55
56void split_keyboard_setup(void) {
57 setup_handedness();
58
59 if (has_usb()) {
60 keyboard_master_setup();
61 } else {
62 keyboard_slave_setup();
63 }
64 sei();
65}
66
67// this code runs before the usb and keyboard is initialized
68void matrix_setup(void) {
69 split_keyboard_setup();
70}
diff --git a/keyboards/claw44/rev1/split_util.h b/keyboards/claw44/rev1/split_util.h
new file mode 100644
index 000000000..687ca19bd
--- /dev/null
+++ b/keyboards/claw44/rev1/split_util.h
@@ -0,0 +1,19 @@
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;
10
11// slave version of matix scan, defined in matrix.c
12void matrix_slave_scan(void);
13
14void split_keyboard_setup(void);
15bool has_usb(void);
16
17void matrix_master_OLED_init (void);
18
19#endif
diff --git a/keyboards/claw44/rules.mk b/keyboards/claw44/rules.mk
new file mode 100644
index 000000000..907a5c832
--- /dev/null
+++ b/keyboards/claw44/rules.mk
@@ -0,0 +1,74 @@
1SRC += i2c.c
2SRC += serial.c
3SRC += ssd1306.c
4
5# if firmware size over limit, try this option
6# CFLAGS += -flto
7
8# MCU name
9#MCU = at90usb1287
10MCU = atmega32u4
11
12# Processor frequency.
13# This will define a symbol, F_CPU, in all source code files equal to the
14# processor frequency in Hz. You can then use this symbol in your source code to
15# calculate timings. Do NOT tack on a 'UL' at the end, this will be done
16# automatically to create a 32-bit value in your source code.
17#
18# This will be an integer division of F_USB below, as it is sourced by
19# F_USB after it has run through any CPU prescalers. Note that this value
20# does not *change* the processor frequency - it should merely be updated to
21# reflect the processor speed set externally so that the code can use accurate
22# software delays.
23F_CPU = 16000000
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# Bootloader
45# This definition is optional, and if your keyboard supports multiple bootloaders of
46# different sizes, comment this out, and the correct address will be loaded
47# automatically (+60). See bootloader.mk for all options.
48BOOTLOADER = caterina
49
50# Interrupt driven control endpoint task(+60)
51OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
52
53# Build Options
54# change to "no" to disable the options, or define them in the Makefile in
55# the appropriate keymap folder that will get included automatically
56#
57BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration(+1000)
58MOUSEKEY_ENABLE = no # Mouse keys(+4700)
59EXTRAKEY_ENABLE = no # Audio control and System control(+450)
60CONSOLE_ENABLE = no # Console for debug(+400)
61COMMAND_ENABLE = no # Commands for debug and configuration
62NKRO_ENABLE = no # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
63BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality
64MIDI_ENABLE = no # MIDI controls
65AUDIO_ENABLE = no # Audio output on port C6
66UNICODE_ENABLE = no # Unicode
67BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID
68RGBLIGHT_ENABLE = no # Enable WS2812 RGB underlight.
69# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
70SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
71
72CUSTOM_MATRIX = yes
73
74DEFAULT_FOLDER = claw44/rev1
diff --git a/keyboards/claw44/serial.c b/keyboards/claw44/serial.c
new file mode 100644
index 000000000..325c29a3f
--- /dev/null
+++ b/keyboards/claw44/serial.c
@@ -0,0 +1,590 @@
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_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//////////////// for backward compatibility ////////////////////////////////
74#ifndef SERIAL_USE_MULTI_TRANSACTION
75/* --- USE Simple API (OLD API, compatible with let's split serial.c) */
76 #if SERIAL_SLAVE_BUFFER_LENGTH > 0
77 uint8_t volatile serial_slave_buffer[SERIAL_SLAVE_BUFFER_LENGTH] = {0};
78 #endif
79 #if SERIAL_MASTER_BUFFER_LENGTH > 0
80 uint8_t volatile serial_master_buffer[SERIAL_MASTER_BUFFER_LENGTH] = {0};
81 #endif
82 uint8_t volatile status0 = 0;
83
84SSTD_t transactions[] = {
85 { (uint8_t *)&status0,
86 #if SERIAL_MASTER_BUFFER_LENGTH > 0
87 sizeof(serial_master_buffer), (uint8_t *)serial_master_buffer,
88 #else
89 0, (uint8_t *)NULL,
90 #endif
91 #if SERIAL_SLAVE_BUFFER_LENGTH > 0
92 sizeof(serial_slave_buffer), (uint8_t *)serial_slave_buffer
93 #else
94 0, (uint8_t *)NULL,
95 #endif
96 }
97};
98
99void serial_master_init(void)
100{ soft_serial_initiator_init(transactions, TID_LIMIT(transactions)); }
101
102void serial_slave_init(void)
103{ soft_serial_target_init(transactions, TID_LIMIT(transactions)); }
104
105// 0 => no error
106// 1 => slave did not respond
107// 2 => checksum error
108int serial_update_buffers()
109{
110 int result;
111 result = soft_serial_transaction();
112 return result;
113}
114
115#endif // end of Simple API (OLD API, compatible with let's split serial.c)
116////////////////////////////////////////////////////////////////////////////
117
118#define ALWAYS_INLINE __attribute__((always_inline))
119#define NO_INLINE __attribute__((noinline))
120#define _delay_sub_us(x) __builtin_avr_delay_cycles(x)
121
122// parity check
123#define ODD_PARITY 1
124#define EVEN_PARITY 0
125#define PARITY EVEN_PARITY
126
127#ifdef SERIAL_DELAY
128 // custom setup in config.h
129 // #define TID_SEND_ADJUST 2
130 // #define SERIAL_DELAY 6 // micro sec
131 // #define READ_WRITE_START_ADJUST 30 // cycles
132 // #define READ_WRITE_WIDTH_ADJUST 8 // cycles
133#else
134// ============ Standard setups ============
135
136#ifndef SELECT_SOFT_SERIAL_SPEED
137#define SELECT_SOFT_SERIAL_SPEED 1
138// 0: about 189kbps
139// 1: about 137kbps (default)
140// 2: about 75kbps
141// 3: about 39kbps
142// 4: about 26kbps
143// 5: about 20kbps
144#endif
145
146#if __GNUC__ < 6
147 #define TID_SEND_ADJUST 14
148#else
149 #define TID_SEND_ADJUST 2
150#endif
151
152#if SELECT_SOFT_SERIAL_SPEED == 0
153 // Very High speed
154 #define SERIAL_DELAY 4 // micro sec
155 #if __GNUC__ < 6
156 #define READ_WRITE_START_ADJUST 33 // cycles
157 #define READ_WRITE_WIDTH_ADJUST 3 // cycles
158 #else
159 #define READ_WRITE_START_ADJUST 34 // cycles
160 #define READ_WRITE_WIDTH_ADJUST 7 // cycles
161 #endif
162#elif SELECT_SOFT_SERIAL_SPEED == 1
163 // High speed
164 #define SERIAL_DELAY 6 // micro sec
165 #if __GNUC__ < 6
166 #define READ_WRITE_START_ADJUST 30 // cycles
167 #define READ_WRITE_WIDTH_ADJUST 3 // cycles
168 #else
169 #define READ_WRITE_START_ADJUST 33 // cycles
170 #define READ_WRITE_WIDTH_ADJUST 7 // cycles
171 #endif
172#elif SELECT_SOFT_SERIAL_SPEED == 2
173 // Middle speed
174 #define SERIAL_DELAY 12 // micro sec
175 #define READ_WRITE_START_ADJUST 30 // cycles
176 #if __GNUC__ < 6
177 #define READ_WRITE_WIDTH_ADJUST 3 // cycles
178 #else
179 #define READ_WRITE_WIDTH_ADJUST 7 // cycles
180 #endif
181#elif SELECT_SOFT_SERIAL_SPEED == 3
182 // Low speed
183 #define SERIAL_DELAY 24 // micro sec
184 #define READ_WRITE_START_ADJUST 30 // cycles
185 #if __GNUC__ < 6
186 #define READ_WRITE_WIDTH_ADJUST 3 // cycles
187 #else
188 #define READ_WRITE_WIDTH_ADJUST 7 // cycles
189 #endif
190#elif SELECT_SOFT_SERIAL_SPEED == 4
191 // Very Low speed
192 #define SERIAL_DELAY 36 // micro sec
193 #define READ_WRITE_START_ADJUST 30 // cycles
194 #if __GNUC__ < 6
195 #define READ_WRITE_WIDTH_ADJUST 3 // cycles
196 #else
197 #define READ_WRITE_WIDTH_ADJUST 7 // cycles
198 #endif
199#elif SELECT_SOFT_SERIAL_SPEED == 5
200 // Ultra Low speed
201 #define SERIAL_DELAY 48 // micro sec
202 #define READ_WRITE_START_ADJUST 30 // cycles
203 #if __GNUC__ < 6
204 #define READ_WRITE_WIDTH_ADJUST 3 // cycles
205 #else
206 #define READ_WRITE_WIDTH_ADJUST 7 // cycles
207 #endif
208#else
209#error invalid SELECT_SOFT_SERIAL_SPEED value
210#endif /* SELECT_SOFT_SERIAL_SPEED */
211#endif /* SERIAL_DELAY */
212
213#define SERIAL_DELAY_HALF1 (SERIAL_DELAY/2)
214#define SERIAL_DELAY_HALF2 (SERIAL_DELAY - SERIAL_DELAY/2)
215
216#define SLAVE_INT_WIDTH_US 1
217#ifndef SERIAL_USE_MULTI_TRANSACTION
218 #define SLAVE_INT_RESPONSE_TIME SERIAL_DELAY
219#else
220 #define SLAVE_INT_ACK_WIDTH_UNIT 2
221 #define SLAVE_INT_ACK_WIDTH 4
222#endif
223
224static SSTD_t *Transaction_table = NULL;
225static uint8_t Transaction_table_size = 0;
226
227inline static void serial_delay(void) ALWAYS_INLINE;
228inline static
229void serial_delay(void) {
230 _delay_us(SERIAL_DELAY);
231}
232
233inline static void serial_delay_half1(void) ALWAYS_INLINE;
234inline static
235void serial_delay_half1(void) {
236 _delay_us(SERIAL_DELAY_HALF1);
237}
238
239inline static void serial_delay_half2(void) ALWAYS_INLINE;
240inline static
241void serial_delay_half2(void) {
242 _delay_us(SERIAL_DELAY_HALF2);
243}
244
245inline static void serial_output(void) ALWAYS_INLINE;
246inline static
247void serial_output(void) {
248 SERIAL_PIN_DDR |= SERIAL_PIN_MASK;
249}
250
251// make the serial pin an input with pull-up resistor
252inline static void serial_input_with_pullup(void) ALWAYS_INLINE;
253inline static
254void serial_input_with_pullup(void) {
255 SERIAL_PIN_DDR &= ~SERIAL_PIN_MASK;
256 SERIAL_PIN_PORT |= SERIAL_PIN_MASK;
257}
258
259inline static uint8_t serial_read_pin(void) ALWAYS_INLINE;
260inline static
261uint8_t serial_read_pin(void) {
262 return !!(SERIAL_PIN_INPUT & SERIAL_PIN_MASK);
263}
264
265inline static void serial_low(void) ALWAYS_INLINE;
266inline static
267void serial_low(void) {
268 SERIAL_PIN_PORT &= ~SERIAL_PIN_MASK;
269}
270
271inline static void serial_high(void) ALWAYS_INLINE;
272inline static
273void serial_high(void) {
274 SERIAL_PIN_PORT |= SERIAL_PIN_MASK;
275}
276
277void soft_serial_initiator_init(SSTD_t *sstd_table, int sstd_table_size)
278{
279 Transaction_table = sstd_table;
280 Transaction_table_size = (uint8_t)sstd_table_size;
281 serial_output();
282 serial_high();
283}
284
285void soft_serial_target_init(SSTD_t *sstd_table, int sstd_table_size)
286{
287 Transaction_table = sstd_table;
288 Transaction_table_size = (uint8_t)sstd_table_size;
289 serial_input_with_pullup();
290
291 // Enable INT0-INT3,INT6
292 EIMSK |= EIMSK_BIT;
293#if SERIAL_PIN_MASK == _BV(PE6)
294 // Trigger on falling edge of INT6
295 EICRB &= EICRx_BIT;
296#else
297 // Trigger on falling edge of INT0-INT3
298 EICRA &= EICRx_BIT;
299#endif
300}
301
302// Used by the sender to synchronize timing with the reciver.
303static void sync_recv(void) NO_INLINE;
304static
305void sync_recv(void) {
306 for (uint8_t i = 0; i < SERIAL_DELAY*5 && serial_read_pin(); i++ ) {
307 }
308 // This shouldn't hang if the target disconnects because the
309 // serial line will float to high if the target does disconnect.
310 while (!serial_read_pin());
311}
312
313// Used by the reciver to send a synchronization signal to the sender.
314static void sync_send(void) NO_INLINE;
315static
316void sync_send(void) {
317 serial_low();
318 serial_delay();
319 serial_high();
320}
321
322// Reads a byte from the serial line
323static uint8_t serial_read_chunk(uint8_t *pterrcount, uint8_t bit) NO_INLINE;
324static uint8_t serial_read_chunk(uint8_t *pterrcount, uint8_t bit) {
325 uint8_t byte, i, p, pb;
326
327 _delay_sub_us(READ_WRITE_START_ADJUST);
328 for( i = 0, byte = 0, p = PARITY; i < bit; i++ ) {
329 serial_delay_half1(); // read the middle of pulses
330 if( serial_read_pin() ) {
331 byte = (byte << 1) | 1; p ^= 1;
332 } else {
333 byte = (byte << 1) | 0; p ^= 0;
334 }
335 _delay_sub_us(READ_WRITE_WIDTH_ADJUST);
336 serial_delay_half2();
337 }
338 /* recive parity bit */
339 serial_delay_half1(); // read the middle of pulses
340 pb = serial_read_pin();
341 _delay_sub_us(READ_WRITE_WIDTH_ADJUST);
342 serial_delay_half2();
343
344 *pterrcount += (p != pb)? 1 : 0;
345
346 return byte;
347}
348
349// Sends a byte with MSB ordering
350void serial_write_chunk(uint8_t data, uint8_t bit) NO_INLINE;
351void serial_write_chunk(uint8_t data, uint8_t bit) {
352 uint8_t b, p;
353 for( p = PARITY, b = 1<<(bit-1); b ; b >>= 1) {
354 if(data & b) {
355 serial_high(); p ^= 1;
356 } else {
357 serial_low(); p ^= 0;
358 }
359 serial_delay();
360 }
361 /* send parity bit */
362 if(p & 1) { serial_high(); }
363 else { serial_low(); }
364 serial_delay();
365
366 serial_low(); // sync_send() / senc_recv() need raise edge
367}
368
369static void serial_send_packet(uint8_t *buffer, uint8_t size) NO_INLINE;
370static
371void serial_send_packet(uint8_t *buffer, uint8_t size) {
372 for (uint8_t i = 0; i < size; ++i) {
373 uint8_t data;
374 data = buffer[i];
375 sync_send();
376 serial_write_chunk(data,8);
377 }
378}
379
380static uint8_t serial_recive_packet(uint8_t *buffer, uint8_t size) NO_INLINE;
381static
382uint8_t serial_recive_packet(uint8_t *buffer, uint8_t size) {
383 uint8_t pecount = 0;
384 for (uint8_t i = 0; i < size; ++i) {
385 uint8_t data;
386 sync_recv();
387 data = serial_read_chunk(&pecount, 8);
388 buffer[i] = data;
389 }
390 return pecount == 0;
391}
392
393inline static
394void change_sender2reciver(void) {
395 sync_send(); //0
396 serial_delay_half1(); //1
397 serial_low(); //2
398 serial_input_with_pullup(); //2
399 serial_delay_half1(); //3
400}
401
402inline static
403void change_reciver2sender(void) {
404 sync_recv(); //0
405 serial_delay(); //1
406 serial_low(); //3
407 serial_output(); //3
408 serial_delay_half1(); //4
409}
410
411static inline uint8_t nibble_bits_count(uint8_t bits)
412{
413 bits = (bits & 0x5) + (bits >> 1 & 0x5);
414 bits = (bits & 0x3) + (bits >> 2 & 0x3);
415 return bits;
416}
417
418// interrupt handle to be used by the target device
419ISR(SERIAL_PIN_INTERRUPT) {
420
421#ifndef SERIAL_USE_MULTI_TRANSACTION
422 serial_low();
423 serial_output();
424 SSTD_t *trans = Transaction_table;
425#else
426 // recive transaction table index
427 uint8_t tid, bits;
428 uint8_t pecount = 0;
429 sync_recv();
430 bits = serial_read_chunk(&pecount,7);
431 tid = bits>>3;
432 bits = (bits&7) != nibble_bits_count(tid);
433 if( bits || pecount> 0 || tid > Transaction_table_size ) {
434 return;
435 }
436 serial_delay_half1();
437
438 serial_high(); // response step1 low->high
439 serial_output();
440 _delay_sub_us(SLAVE_INT_ACK_WIDTH_UNIT*SLAVE_INT_ACK_WIDTH);
441 SSTD_t *trans = &Transaction_table[tid];
442 serial_low(); // response step2 ack high->low
443#endif
444
445 // target send phase
446 if( trans->target2initiator_buffer_size > 0 )
447 serial_send_packet((uint8_t *)trans->target2initiator_buffer,
448 trans->target2initiator_buffer_size);
449 // target switch to input
450 change_sender2reciver();
451
452 // target recive phase
453 if( trans->initiator2target_buffer_size > 0 ) {
454 if (serial_recive_packet((uint8_t *)trans->initiator2target_buffer,
455 trans->initiator2target_buffer_size) ) {
456 *trans->status = TRANSACTION_ACCEPTED;
457 } else {
458 *trans->status = TRANSACTION_DATA_ERROR;
459 }
460 } else {
461 *trans->status = TRANSACTION_ACCEPTED;
462 }
463
464 sync_recv(); //weit initiator output to high
465}
466
467/////////
468// start transaction by initiator
469//
470// int soft_serial_transaction(int sstd_index)
471//
472// Returns:
473// TRANSACTION_END
474// TRANSACTION_NO_RESPONSE
475// TRANSACTION_DATA_ERROR
476// this code is very time dependent, so we need to disable interrupts
477#ifndef SERIAL_USE_MULTI_TRANSACTION
478int soft_serial_transaction(void) {
479 SSTD_t *trans = Transaction_table;
480#else
481int soft_serial_transaction(int sstd_index) {
482 if( sstd_index > Transaction_table_size )
483 return TRANSACTION_TYPE_ERROR;
484 SSTD_t *trans = &Transaction_table[sstd_index];
485#endif
486 cli();
487
488 // signal to the target that we want to start a transaction
489 serial_output();
490 serial_low();
491 _delay_us(SLAVE_INT_WIDTH_US);
492
493#ifndef SERIAL_USE_MULTI_TRANSACTION
494 // wait for the target response
495 serial_input_with_pullup();
496 _delay_us(SLAVE_INT_RESPONSE_TIME);
497
498 // check if the target is present
499 if (serial_read_pin()) {
500 // target failed to pull the line low, assume not present
501 serial_output();
502 serial_high();
503 *trans->status = TRANSACTION_NO_RESPONSE;
504 sei();
505 return TRANSACTION_NO_RESPONSE;
506 }
507
508#else
509 // send transaction table index
510 int tid = (sstd_index<<3) | (7 & nibble_bits_count(sstd_index));
511 sync_send();
512 _delay_sub_us(TID_SEND_ADJUST);
513 serial_write_chunk(tid, 7);
514 serial_delay_half1();
515
516 // wait for the target response (step1 low->high)
517 serial_input_with_pullup();
518 while( !serial_read_pin() ) {
519 _delay_sub_us(2);
520 }
521
522 // check if the target is present (step2 high->low)
523 for( int i = 0; serial_read_pin(); i++ ) {
524 if (i > SLAVE_INT_ACK_WIDTH + 1) {
525 // slave failed to pull the line low, assume not present
526 serial_output();
527 serial_high();
528 *trans->status = TRANSACTION_NO_RESPONSE;
529 sei();
530 return TRANSACTION_NO_RESPONSE;
531 }
532 _delay_sub_us(SLAVE_INT_ACK_WIDTH_UNIT);
533 }
534#endif
535
536 // initiator recive phase
537 // if the target is present syncronize with it
538 if( trans->target2initiator_buffer_size > 0 ) {
539 if (!serial_recive_packet((uint8_t *)trans->target2initiator_buffer,
540 trans->target2initiator_buffer_size) ) {
541 serial_output();
542 serial_high();
543 *trans->status = TRANSACTION_DATA_ERROR;
544 sei();
545 return TRANSACTION_DATA_ERROR;
546 }
547 }
548
549 // initiator switch to output
550 change_reciver2sender();
551
552 // initiator send phase
553 if( trans->initiator2target_buffer_size > 0 ) {
554 serial_send_packet((uint8_t *)trans->initiator2target_buffer,
555 trans->initiator2target_buffer_size);
556 }
557
558 // always, release the line when not in use
559 sync_send();
560
561 *trans->status = TRANSACTION_END;
562 sei();
563 return TRANSACTION_END;
564}
565
566#ifdef SERIAL_USE_MULTI_TRANSACTION
567int soft_serial_get_and_clean_status(int sstd_index) {
568 SSTD_t *trans = &Transaction_table[sstd_index];
569 cli();
570 int retval = *trans->status;
571 *trans->status = 0;;
572 sei();
573 return retval;
574}
575#endif
576
577#endif
578
579// Helix serial.c history
580// 2018-1-29 fork from let's split and add PD2, modify sync_recv() (#2308, bceffdefc)
581// 2018-6-28 bug fix master to slave comm and speed up (#3255, 1038bbef4)
582// (adjusted with avr-gcc 4.9.2)
583// 2018-7-13 remove USE_SERIAL_PD2 macro (#3374, f30d6dd78)
584// (adjusted with avr-gcc 4.9.2)
585// 2018-8-11 add support multi-type transaction (#3608, feb5e4aae)
586// (adjusted with avr-gcc 4.9.2)
587// 2018-10-21 fix serial and RGB animation conflict (#4191, 4665e4fff)
588// (adjusted with avr-gcc 7.3.0)
589// 2018-10-28 re-adjust compiler depend value of delay (#4269, 8517f8a66)
590// (adjusted with avr-gcc 5.4.0, 7.3.0)
diff --git a/keyboards/claw44/serial.h b/keyboards/claw44/serial.h
new file mode 100644
index 000000000..7e0c0847a
--- /dev/null
+++ b/keyboards/claw44/serial.h
@@ -0,0 +1,84 @@
1#ifndef SOFT_SERIAL_H
2#define SOFT_SERIAL_H
3
4#include <stdbool.h>
5
6// /////////////////////////////////////////////////////////////////
7// Need Soft Serial defines in config.h
8// /////////////////////////////////////////////////////////////////
9// ex.
10// #define SOFT_SERIAL_PIN ?? // ?? = D0,D1,D2,D3,E6
11// OPTIONAL: #define SELECT_SOFT_SERIAL_SPEED ? // ? = 1,2,3,4,5
12// // 1: about 137kbps (default)
13// // 2: about 75kbps
14// // 3: about 39kbps
15// // 4: about 26kbps
16// // 5: about 20kbps
17//
18// //// USE Simple API (OLD API, compatible with let's split serial.c)
19// ex.
20// #define SERIAL_SLAVE_BUFFER_LENGTH MATRIX_ROWS/2
21// #define SERIAL_MASTER_BUFFER_LENGTH 1
22//
23// //// USE flexible API (using multi-type transaction function)
24// #define SERIAL_USE_MULTI_TRANSACTION
25//
26// /////////////////////////////////////////////////////////////////
27
28
29#ifndef SERIAL_USE_MULTI_TRANSACTION
30/* --- USE Simple API (OLD API, compatible with let's split serial.c) */
31#if SERIAL_SLAVE_BUFFER_LENGTH > 0
32extern volatile uint8_t serial_slave_buffer[SERIAL_SLAVE_BUFFER_LENGTH];
33#endif
34#if SERIAL_MASTER_BUFFER_LENGTH > 0
35extern volatile uint8_t serial_master_buffer[SERIAL_MASTER_BUFFER_LENGTH];
36#endif
37
38void serial_master_init(void);
39void serial_slave_init(void);
40int serial_update_buffers(void);
41
42#endif // USE Simple API
43
44// Soft Serial Transaction Descriptor
45typedef struct _SSTD_t {
46 uint8_t *status;
47 uint8_t initiator2target_buffer_size;
48 uint8_t *initiator2target_buffer;
49 uint8_t target2initiator_buffer_size;
50 uint8_t *target2initiator_buffer;
51} SSTD_t;
52#define TID_LIMIT( table ) (sizeof(table) / sizeof(SSTD_t))
53
54// initiator is transaction start side
55void soft_serial_initiator_init(SSTD_t *sstd_table, int sstd_table_size);
56// target is interrupt accept side
57void soft_serial_target_init(SSTD_t *sstd_table, int sstd_table_size);
58
59// initiator resullt
60#define TRANSACTION_END 0
61#define TRANSACTION_NO_RESPONSE 0x1
62#define TRANSACTION_DATA_ERROR 0x2
63#define TRANSACTION_TYPE_ERROR 0x4
64#ifndef SERIAL_USE_MULTI_TRANSACTION
65int soft_serial_transaction(void);
66#else
67int soft_serial_transaction(int sstd_index);
68#endif
69
70// target status
71// *SSTD_t.status has
72// initiator:
73// TRANSACTION_END
74// or TRANSACTION_NO_RESPONSE
75// or TRANSACTION_DATA_ERROR
76// target:
77// TRANSACTION_DATA_ERROR
78// or TRANSACTION_ACCEPTED
79#define TRANSACTION_ACCEPTED 0x8
80#ifdef SERIAL_USE_MULTI_TRANSACTION
81int soft_serial_get_and_clean_status(int sstd_index);
82#endif
83
84#endif /* SOFT_SERIAL_H */
diff --git a/keyboards/claw44/ssd1306.c b/keyboards/claw44/ssd1306.c
new file mode 100644
index 000000000..781c72263
--- /dev/null
+++ b/keyboards/claw44/ssd1306.c
@@ -0,0 +1,346 @@
1#ifdef SSD1306OLED
2
3#include "ssd1306.h"
4#include "i2c.h"
5#include <string.h>
6#include "print.h"
7#ifdef ADAFRUIT_BLE_ENABLE
8#include "adafruit_ble.h"
9#endif
10#ifdef PROTOCOL_LUFA
11#include "lufa.h"
12#endif
13#include "sendchar.h"
14#include "timer.h"
15
16static const unsigned char font[] PROGMEM;
17
18// Set this to 1 to help diagnose early startup problems
19// when testing power-on with ble. Turn it off otherwise,
20// as the latency of printing most of the debug info messes
21// with the matrix scan, causing keys to drop.
22#define DEBUG_TO_SCREEN 0
23
24//static uint16_t last_battery_update;
25//static uint32_t vbat;
26//#define BatteryUpdateInterval 10000 /* milliseconds */
27
28// 'last_flush' is declared as uint16_t,
29// so this must be less than 65535
30#define ScreenOffInterval 60000 /* milliseconds */
31#if DEBUG_TO_SCREEN
32static uint8_t displaying;
33#endif
34static uint16_t last_flush;
35
36static bool force_dirty = true;
37
38// Write command sequence.
39// Returns true on success.
40static inline bool _send_cmd1(uint8_t cmd) {
41 bool res = false;
42
43 if (i2c_start_write(SSD1306_ADDRESS)) {
44 xprintf("failed to start write to %d\n", SSD1306_ADDRESS);
45 goto done;
46 }
47
48 if (i2c_master_write(0x0 /* command byte follows */)) {
49 print("failed to write control byte\n");
50
51 goto done;
52 }
53
54 if (i2c_master_write(cmd)) {
55 xprintf("failed to write command %d\n", cmd);
56 goto done;
57 }
58 res = true;
59done:
60 i2c_master_stop();
61 return res;
62}
63
64// Write 2-byte command sequence.
65// Returns true on success
66static inline bool _send_cmd2(uint8_t cmd, uint8_t opr) {
67 if (!_send_cmd1(cmd)) {
68 return false;
69 }
70 return _send_cmd1(opr);
71}
72
73// Write 3-byte command sequence.
74// Returns true on success
75static inline bool _send_cmd3(uint8_t cmd, uint8_t opr1, uint8_t opr2) {
76 if (!_send_cmd1(cmd)) {
77 return false;
78 }
79 if (!_send_cmd1(opr1)) {
80 return false;
81 }
82 return _send_cmd1(opr2);
83}
84
85#define send_cmd1(c) if (!_send_cmd1(c)) {goto done;}
86#define send_cmd2(c,o) if (!_send_cmd2(c,o)) {goto done;}
87#define send_cmd3(c,o1,o2) if (!_send_cmd3(c,o1,o2)) {goto done;}
88
89static void clear_display(void) {
90 matrix_clear(&display);
91
92 // Clear all of the display bits (there can be random noise
93 // in the RAM on startup)
94 send_cmd3(PageAddr, 0, (DisplayHeight / 8) - 1);
95 send_cmd3(ColumnAddr, 0, DisplayWidth - 1);
96
97 if (i2c_start_write(SSD1306_ADDRESS)) {
98 goto done;
99 }
100 if (i2c_master_write(0x40)) {
101 // Data mode
102 goto done;
103 }
104 for (uint8_t row = 0; row < MatrixRows; ++row) {
105 for (uint8_t col = 0; col < DisplayWidth; ++col) {
106 i2c_master_write(0);
107 }
108 }
109
110 display.dirty = false;
111
112done:
113 i2c_master_stop();
114}
115
116#if DEBUG_TO_SCREEN
117#undef sendchar
118static int8_t capture_sendchar(uint8_t c) {
119 sendchar(c);
120 iota_gfx_write_char(c);
121
122 if (!displaying) {
123 iota_gfx_flush();
124 }
125 return 0;
126}
127#endif
128
129bool iota_gfx_init(bool rotate) {
130 bool success = false;
131
132 i2c_master_init();
133 send_cmd1(DisplayOff);
134 send_cmd2(SetDisplayClockDiv, 0x80);
135 send_cmd2(SetMultiPlex, DisplayHeight - 1);
136
137 send_cmd2(SetDisplayOffset, 0);
138
139
140 send_cmd1(SetStartLine | 0x0);
141 send_cmd2(SetChargePump, 0x14 /* Enable */);
142 send_cmd2(SetMemoryMode, 0 /* horizontal addressing */);
143
144 if(rotate){
145 // the following Flip the display orientation 180 degrees
146 send_cmd1(SegRemap);
147 send_cmd1(ComScanInc);
148 }else{
149 // Flips the display orientation 0 degrees
150 send_cmd1(SegRemap | 0x1);
151 send_cmd1(ComScanDec);
152 }
153
154 send_cmd2(SetComPins, 0x2);
155 send_cmd2(SetContrast, 0x8f);
156 send_cmd2(SetPreCharge, 0xf1);
157 send_cmd2(SetVComDetect, 0x40);
158 send_cmd1(DisplayAllOnResume);
159 send_cmd1(NormalDisplay);
160 send_cmd1(DeActivateScroll);
161 send_cmd1(DisplayOn);
162
163 send_cmd2(SetContrast, 0); // Dim
164
165 clear_display();
166
167 success = true;
168
169 iota_gfx_flush();
170
171#if DEBUG_TO_SCREEN
172 print_set_sendchar(capture_sendchar);
173#endif
174
175done:
176 return success;
177}
178
179bool iota_gfx_off(void) {
180 bool success = false;
181
182 send_cmd1(DisplayOff);
183 success = true;
184
185done:
186 return success;
187}
188
189bool iota_gfx_on(void) {
190 bool success = false;
191
192 send_cmd1(DisplayOn);
193 success = true;
194
195done:
196 return success;
197}
198
199void matrix_write_char_inner(struct CharacterMatrix *matrix, uint8_t c) {
200 *matrix->cursor = c;
201 ++matrix->cursor;
202
203 if (matrix->cursor - &matrix->display[0][0] == sizeof(matrix->display)) {
204 // We went off the end; scroll the display upwards by one line
205 memmove(&matrix->display[0], &matrix->display[1],
206 MatrixCols * (MatrixRows - 1));
207 matrix->cursor = &matrix->display[MatrixRows - 1][0];
208 memset(matrix->cursor, ' ', MatrixCols);
209 }
210}
211
212void matrix_write_char(struct CharacterMatrix *matrix, uint8_t c) {
213 matrix->dirty = true;
214
215 if (c == '\n') {
216 // Clear to end of line from the cursor and then move to the
217 // start of the next line
218 uint8_t cursor_col = (matrix->cursor - &matrix->display[0][0]) % MatrixCols;
219
220 while (cursor_col++ < MatrixCols) {
221 matrix_write_char_inner(matrix, ' ');
222 }
223 return;
224 }
225
226 matrix_write_char_inner(matrix, c);
227}
228
229void iota_gfx_write_char(uint8_t c) {
230 matrix_write_char(&display, c);
231}
232
233void matrix_write(struct CharacterMatrix *matrix, const char *data) {
234 const char *end = data + strlen(data);
235 while (data < end) {
236 matrix_write_char(matrix, *data);
237 ++data;
238 }
239}
240
241void matrix_write_ln(struct CharacterMatrix *matrix, const char *data) {
242 char data_ln[strlen(data)+2];
243 snprintf(data_ln, sizeof(data_ln), "%s\n", data);
244 matrix_write(matrix, data_ln);
245}
246
247void iota_gfx_write(const char *data) {
248 matrix_write(&display, data);
249}
250
251void matrix_write_P(struct CharacterMatrix *matrix, const char *data) {
252 while (true) {
253 uint8_t c = pgm_read_byte(data);
254 if (c == 0) {
255 return;
256 }
257 matrix_write_char(matrix, c);
258 ++data;
259 }
260}
261
262void iota_gfx_write_P(const char *data) {
263 matrix_write_P(&display, data);
264}
265
266void matrix_clear(struct CharacterMatrix *matrix) {
267 memset(matrix->display, ' ', sizeof(matrix->display));
268 matrix->cursor = &matrix->display[0][0];
269 matrix->dirty = true;
270}
271
272void iota_gfx_clear_screen(void) {
273 matrix_clear(&display);
274}
275
276void matrix_render(struct CharacterMatrix *matrix) {
277 last_flush = timer_read();
278 iota_gfx_on();
279#if DEBUG_TO_SCREEN
280 ++displaying;
281#endif
282
283 // Move to the home position
284 send_cmd3(PageAddr, 0, MatrixRows - 1);
285 send_cmd3(ColumnAddr, 0, (MatrixCols * FontWidth) - 1);
286
287 if (i2c_start_write(SSD1306_ADDRESS)) {
288 goto done;
289 }
290 if (i2c_master_write(0x40)) {
291 // Data mode
292 goto done;
293 }
294
295 for (uint8_t row = 0; row < MatrixRows; ++row) {
296 for (uint8_t col = 0; col < MatrixCols; ++col) {
297 const uint8_t *glyph = font + (matrix->display[row][col] * FontWidth);
298
299 for (uint8_t glyphCol = 0; glyphCol < FontWidth; ++glyphCol) {
300 uint8_t colBits = pgm_read_byte(glyph + glyphCol);
301 i2c_master_write(colBits);
302 }
303
304 // 1 column of space between chars (it's not included in the glyph)
305 //i2c_master_write(0);
306 }
307 }
308
309 matrix->dirty = false;
310
311done:
312 i2c_master_stop();
313#if DEBUG_TO_SCREEN
314 --displaying;
315#endif
316}
317
318void iota_gfx_flush(void) {
319 matrix_render(&display);
320}
321
322__attribute__ ((weak))
323void iota_gfx_task_user(void) {
324}
325
326void iota_gfx_task(void) {
327 iota_gfx_task_user();
328
329 if (display.dirty|| force_dirty) {
330 iota_gfx_flush();
331 force_dirty = false;
332 }
333
334 /*
335 if (timer_elapsed(last_flush) > ScreenOffInterval) {
336 iota_gfx_off();
337 }
338 */
339}
340
341bool process_record_gfx(uint16_t keycode, keyrecord_t *record) {
342 force_dirty = true;
343 return true;
344}
345
346#endif
diff --git a/keyboards/claw44/ssd1306.h b/keyboards/claw44/ssd1306.h
new file mode 100644
index 000000000..ea8c92328
--- /dev/null
+++ b/keyboards/claw44/ssd1306.h
@@ -0,0 +1,91 @@
1#pragma once
2
3#include <stdbool.h>
4#include <stdio.h>
5#include "pincontrol.h"
6#include "action.h"
7
8enum ssd1306_cmds {
9 DisplayOff = 0xAE,
10 DisplayOn = 0xAF,
11
12 SetContrast = 0x81,
13 DisplayAllOnResume = 0xA4,
14
15 DisplayAllOn = 0xA5,
16 NormalDisplay = 0xA6,
17 InvertDisplay = 0xA7,
18 SetDisplayOffset = 0xD3,
19 SetComPins = 0xda,
20 SetVComDetect = 0xdb,
21 SetDisplayClockDiv = 0xD5,
22 SetPreCharge = 0xd9,
23 SetMultiPlex = 0xa8,
24 SetLowColumn = 0x00,
25 SetHighColumn = 0x10,
26 SetStartLine = 0x40,
27
28 SetMemoryMode = 0x20,
29 ColumnAddr = 0x21,
30 PageAddr = 0x22,
31
32 ComScanInc = 0xc0,
33 ComScanDec = 0xc8,
34 SegRemap = 0xa0,
35 SetChargePump = 0x8d,
36 ExternalVcc = 0x01,
37 SwitchCapVcc = 0x02,
38
39 ActivateScroll = 0x2f,
40 DeActivateScroll = 0x2e,
41 SetVerticalScrollArea = 0xa3,
42 RightHorizontalScroll = 0x26,
43 LeftHorizontalScroll = 0x27,
44 VerticalAndRightHorizontalScroll = 0x29,
45 VerticalAndLeftHorizontalScroll = 0x2a,
46};
47
48// Controls the SSD1306 128x32 OLED display via i2c
49
50#ifndef SSD1306_ADDRESS
51#define SSD1306_ADDRESS 0x3C
52#endif
53
54#define DisplayHeight 32
55#define DisplayWidth 128
56
57#define FontHeight 8
58#define FontWidth 6
59
60#define MatrixRows (DisplayHeight / FontHeight)
61#define MatrixCols (DisplayWidth / FontWidth)
62
63struct CharacterMatrix {
64 uint8_t display[MatrixRows][MatrixCols];
65 uint8_t *cursor;
66 bool dirty;
67};
68
69struct CharacterMatrix display;
70
71bool iota_gfx_init(bool rotate);
72void iota_gfx_task(void);
73bool iota_gfx_off(void);
74bool iota_gfx_on(void);
75void iota_gfx_flush(void);
76void iota_gfx_write_char(uint8_t c);
77void iota_gfx_write(const char *data);
78void iota_gfx_write_P(const char *data);
79void iota_gfx_clear_screen(void);
80
81void iota_gfx_task_user(void);
82
83void matrix_clear(struct CharacterMatrix *matrix);
84void matrix_write_char_inner(struct CharacterMatrix *matrix, uint8_t c);
85void matrix_write_char(struct CharacterMatrix *matrix, uint8_t c);
86void matrix_write(struct CharacterMatrix *matrix, const char *data);
87void matrix_write_ln(struct CharacterMatrix *matrix, const char *data);
88void matrix_write_P(struct CharacterMatrix *matrix, const char *data);
89void matrix_render(struct CharacterMatrix *matrix);
90
91bool process_record_gfx(uint16_t keycode, keyrecord_t *record); \ No newline at end of file