[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
33 files changed, 3044 insertions(+), 0 deletions(-) A keyboards/claw44/claw44.c A keyboards/claw44/claw44.h A keyboards/claw44/config.h A keyboards/claw44/i2c.c A keyboards/claw44/i2c.h A keyboards/claw44/keymaps/default/config.h A keyboards/claw44/keymaps/default/keymap.c A keyboards/claw44/keymaps/yfuku/config.h A keyboards/claw44/keymaps/yfuku/keymap.c A keyboards/claw44/lib/glcdfont.c A keyboards/claw44/lib/host_led_state_reader.c A keyboards/claw44/lib/keylogger.c A keyboards/claw44/lib/layer_state_reader.c A keyboards/claw44/lib/logo_reader.c A keyboards/claw44/lib/mode_icon_reader.c A keyboards/claw44/lib/rgb_state_reader.c A keyboards/claw44/lib/timelogger.c A keyboards/claw44/readme.md A keyboards/claw44/rev1/config.h A keyboards/claw44/rev1/matrix.c A keyboards/claw44/rev1/rev1.c A keyboards/claw44/rev1/rev1.h A keyboards/claw44/rev1/rules.mk A keyboards/claw44/rev1/serial_config.h A keyboards/claw44/rev1/split_scomm.c A keyboards/claw44/rev1/split_scomm.h A keyboards/claw44/rev1/split_util.c A keyboards/claw44/rev1/split_util.h A keyboards/claw44/rules.mk A keyboards/claw44/serial.c A keyboards/claw44/serial.h A keyboards/claw44/ssd1306.c A keyboards/claw44/ssd1306.h
A keyboards/claw44/claw44.c => keyboards/claw44/claw44.c +10 -0
@@ 0,0 1,10 @@ #include "claw44.h" #include "ssd1306.h" bool process_record_kb(uint16_t keycode, keyrecord_t *record) { #ifdef SSD1306OLED return process_record_gfx(keycode,record) && process_record_user(keycode, record); #else return process_record_user(keycode, record); #endif }
A keyboards/claw44/claw44.h => keyboards/claw44/claw44.h +5 -0
A keyboards/claw44/config.h => keyboards/claw44/config.h +28 -0
@@ 0,0 1,28 @@ /* Copyright 2012 Jun Wako <wakojun@gmail.com> Copyright 2015 Jack Humbert This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ #pragma once #include "config_common.h" #include <serial_config.h> #define USE_I2C #define USE_SERIAL #define NO_ACTION_MACRO #define NO_ACTION_FUNCTION
A keyboards/claw44/i2c.c => keyboards/claw44/i2c.c +162 -0
@@ 0,0 1,162 @@ #include <util/twi.h> #include <avr/io.h> #include <stdlib.h> #include <avr/interrupt.h> #include <util/twi.h> #include <stdbool.h> #include "i2c.h" #ifdef USE_I2C // Limits the amount of we wait for any one i2c transaction. // Since were running SCL line 100kHz (=> 10μs/bit), and each transactions is // 9 bits, a single transaction will take around 90μs to complete. // // (F_CPU/SCL_CLOCK) => # of μC cycles to transfer a bit // poll loop takes at least 8 clock cycles to execute #define I2C_LOOP_TIMEOUT (9+1)*(F_CPU/SCL_CLOCK)/8 #define BUFFER_POS_INC() (slave_buffer_pos = (slave_buffer_pos+1)%SLAVE_BUFFER_SIZE) volatile uint8_t i2c_slave_buffer[SLAVE_BUFFER_SIZE]; static volatile uint8_t slave_buffer_pos; static volatile bool slave_has_register_set = false; // Wait for an i2c operation to finish inline static void i2c_delay(void) { uint16_t lim = 0; while(!(TWCR & (1<<TWINT)) && lim < I2C_LOOP_TIMEOUT) lim++; // easier way, but will wait slightly longer // _delay_us(100); } // Setup twi to run at 100kHz or 400kHz (see ./i2c.h SCL_CLOCK) void i2c_master_init(void) { // no prescaler TWSR = 0; // Set TWI clock frequency to SCL_CLOCK. Need TWBR>10. // Check datasheets for more info. TWBR = ((F_CPU/SCL_CLOCK)-16)/2; } // Start a transaction with the given i2c slave address. The direction of the // transfer is set with I2C_READ and I2C_WRITE. // returns: 0 => success // 1 => error uint8_t i2c_master_start(uint8_t address) { TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTA); i2c_delay(); // check that we started successfully if ( (TW_STATUS != TW_START) && (TW_STATUS != TW_REP_START)) return 1; TWDR = address; TWCR = (1<<TWINT) | (1<<TWEN); i2c_delay(); if ( (TW_STATUS != TW_MT_SLA_ACK) && (TW_STATUS != TW_MR_SLA_ACK) ) return 1; // slave did not acknowledge else return 0; // success } // Finish the i2c transaction. void i2c_master_stop(void) { TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO); uint16_t lim = 0; while(!(TWCR & (1<<TWSTO)) && lim < I2C_LOOP_TIMEOUT) lim++; } // Write one byte to the i2c slave. // returns 0 => slave ACK // 1 => slave NACK uint8_t i2c_master_write(uint8_t data) { TWDR = data; TWCR = (1<<TWINT) | (1<<TWEN); i2c_delay(); // check if the slave acknowledged us return (TW_STATUS == TW_MT_DATA_ACK) ? 0 : 1; } // Read one byte from the i2c slave. If ack=1 the slave is acknowledged, // if ack=0 the acknowledge bit is not set. // returns: byte read from i2c device uint8_t i2c_master_read(int ack) { TWCR = (1<<TWINT) | (1<<TWEN) | (ack<<TWEA); i2c_delay(); return TWDR; } void i2c_reset_state(void) { TWCR = 0; } void i2c_slave_init(uint8_t address) { TWAR = address << 0; // slave i2c address // TWEN - twi enable // TWEA - enable address acknowledgement // TWINT - twi interrupt flag // TWIE - enable the twi interrupt TWCR = (1<<TWIE) | (1<<TWEA) | (1<<TWINT) | (1<<TWEN); } ISR(TWI_vect); ISR(TWI_vect) { uint8_t ack = 1; switch(TW_STATUS) { case TW_SR_SLA_ACK: // this device has been addressed as a slave receiver slave_has_register_set = false; break; case TW_SR_DATA_ACK: // this device has received data as a slave receiver // The first byte that we receive in this transaction sets the location // of the read/write location of the slaves memory that it exposes over // i2c. After that, bytes will be written at slave_buffer_pos, incrementing // slave_buffer_pos after each write. if(!slave_has_register_set) { slave_buffer_pos = TWDR; // don't acknowledge the master if this memory loctaion is out of bounds if ( slave_buffer_pos >= SLAVE_BUFFER_SIZE ) { ack = 0; slave_buffer_pos = 0; } slave_has_register_set = true; } else { i2c_slave_buffer[slave_buffer_pos] = TWDR; BUFFER_POS_INC(); } break; case TW_ST_SLA_ACK: case TW_ST_DATA_ACK: // master has addressed this device as a slave transmitter and is // requesting data. TWDR = i2c_slave_buffer[slave_buffer_pos]; BUFFER_POS_INC(); break; case TW_BUS_ERROR: // something went wrong, reset twi state TWCR = 0; default: break; } // Reset everything, so we are ready for the next TWI interrupt TWCR |= (1<<TWIE) | (1<<TWINT) | (ack<<TWEA) | (1<<TWEN); } #endif
A keyboards/claw44/i2c.h => keyboards/claw44/i2c.h +46 -0
@@ 0,0 1,46 @@ #pragma once #include <stdint.h> #ifndef F_CPU #define F_CPU 16000000UL #endif #define I2C_READ 1 #define I2C_WRITE 0 #define I2C_ACK 1 #define I2C_NACK 0 #define SLAVE_BUFFER_SIZE 0x10 // i2c SCL clock frequency 400kHz #define SCL_CLOCK 400000L extern volatile uint8_t i2c_slave_buffer[SLAVE_BUFFER_SIZE]; void i2c_master_init(void); uint8_t i2c_master_start(uint8_t address); void i2c_master_stop(void); uint8_t i2c_master_write(uint8_t data); uint8_t i2c_master_read(int); void i2c_reset_state(void); void i2c_slave_init(uint8_t address); static inline unsigned char i2c_start_read(unsigned char addr) { return i2c_master_start((addr << 1) | I2C_READ); } static inline unsigned char i2c_start_write(unsigned char addr) { return i2c_master_start((addr << 1) | I2C_WRITE); } // from SSD1306 scrips extern unsigned char i2c_rep_start(unsigned char addr); extern void i2c_start_wait(unsigned char addr); extern unsigned char i2c_readAck(void); extern unsigned char i2c_readNak(void); extern unsigned char i2c_read(unsigned char ack); #define i2c_read(ack) (ack) ? i2c_readAck() : i2c_readNak();
A keyboards/claw44/keymaps/default/config.h => keyboards/claw44/keymaps/default/config.h +35 -0
@@ 0,0 1,35 @@ /* This is the c configuration file for the keymap Copyright 2012 Jun Wako <wakojun@gmail.com> Copyright 2015 Jack Humbert This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ #pragma once //#define USE_MATRIX_I2C /* Select hand configuration */ #define MASTER_LEFT // #define MASTER_RIGHT // #define EE_HANDS #define SSD1306OLED #define USE_SERIAL_PD2 #define TAPPING_TERM 200
A keyboards/claw44/keymaps/default/keymap.c => keyboards/claw44/keymaps/default/keymap.c +169 -0
@@ 0,0 1,169 @@ #include QMK_KEYBOARD_H #ifdef PROTOCOL_LUFA #include "lufa.h" #include "split_util.h" #endif #ifdef SSD1306OLED #include "ssd1306.h" #endif extern keymap_config_t keymap_config; extern uint8_t is_master; // Each layer gets a name for readability, which is then used in the keymap matrix below. // The underscores don't mean anything - you can have a layer called STUFF or any other name. // Layer names don't all need to be of the same length, obviously, and you can also skip them // entirely and just use numbers. enum custom_keycodes { QWERTY = SAFE_RANGE, LOWER, RAISE }; enum macro_keycodes { KC_SAMPLEMACRO, }; #define KC_ KC_TRNS #define KC_RST RESET #define KC_L_SPC LT(_LOWER, KC_SPC) // lower #define KC_R_ENT LT(_RAISE, KC_ENT) // raise #define KC_G_JA LGUI_T(KC_LANG1) // cmd or win #define KC_G_EN LGUI_T(KC_LANG2) // cmd or win #define KC_C_BS LCTL_T(KC_BSPC) // ctrl #define KC_A_DEL ALT_T(KC_DEL) // alt const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { [_QWERTY] = LAYOUT( \ //,--------+--------+---------+--------+---------+--------. ,--------+---------+--------+---------+--------+--------. KC_ESC , KC_Q , KC_W , KC_E , KC_R , KC_T , KC_Y , KC_U , KC_I , KC_O , KC_P , KC_MINS, //|--------+--------+---------+--------+---------+--------| |--------+---------+--------+---------+--------+--------| KC_TAB , KC_A , KC_S , KC_D , KC_F , KC_G , KC_H , KC_J , KC_K , KC_L , KC_SCLN, KC_QUOT, //|--------+--------+---------+--------+---------+--------| |--------+---------+--------+---------+--------+--------| KC_LSFT, KC_Z , KC_X , KC_C , KC_V , KC_B , KC_N , KC_M , KC_COMM, KC_DOT , KC_SLSH, KC_RSFT, //`--------+--------+---------+--------+---------+--------/ \--------+---------+--------+---------+--------+--------' KC_A_DEL, KC_G_EN, KC_L_SPC, KC_C_BS, KC_C_BS, KC_R_ENT, KC_G_JA, KC_A_DEL // `----------+--------+---------+--------' `--------+---------+--------+---------' ), // \ ^ ! & | @ = + * % - // ( # $ " ' ~ ← ↓ ↑ → ` ) // { [ ] } [_RAISE] = LAYOUT( \ //,--------+--------+--------+--------+--------+--------. ,--------+--------+--------+--------+--------+--------. _______, KC_BSLS, KC_CIRC, KC_EXLM, KC_AMPR, KC_PIPE, KC_AT , KC_EQL , KC_PLUS, KC_ASTR, KC_PERC, KC_MINS, //|--------+--------+--------+--------+--------+--------| |--------+--------+--------+--------+--------+--------| KC_LPRN, KC_HASH, KC_DLR , KC_DQT , KC_QUOT, KC_TILD, KC_LEFT, KC_DOWN, KC_UP , KC_RGHT, KC_GRV , KC_RPRN, //|--------+--------+--------+--------+--------+--------| |--------+--------+--------+--------+--------+--------| _______, _______, _______, _______, KC_LCBR, KC_LBRC, KC_RBRC, KC_RCBR, _______, _______, _______, _______, //`--------+--------+--------+--------+--------+--------/ \--------+--------+--------+--------+--------+--------' _______, _______, _______, _______, _______, _______, _______, RESET // `--------+--------+--------+--------' `--------+--------+--------+--------' ), [_LOWER] = LAYOUT( \ //,--------+--------+--------+--------+--------+--------. ,--------+--------+--------+--------+--------+--------. KC_F1 , KC_F2 , KC_F3 , KC_F4 , KC_F5 , KC_F6 , _______, KC_EQL , KC_PLUS, KC_ASTR, KC_PERC, KC_MINS, //|--------+--------+--------+--------+--------+--------| |--------+--------+--------+--------+--------+--------| _______, KC_1 , KC_2 , KC_3 , KC_4 , KC_5 , KC_6 , KC_7 , KC_8 , KC_9 , KC_0 , _______, //|--------+--------+--------+--------+--------+--------| |--------+--------+--------+--------+--------+--------| KC_F7 , KC_F8 , KC_F9 , KC_F10 , KC_F11 , KC_F12 , _______, _______, KC_COMM, KC_DOT , KC_SLSH, _______, //`--------+--------+--------+--------+--------+--------/ \--------+--------+--------+--------+--------+--------' RESET , _______, _______, _______, _______, _______, _______, _______ // `--------+--------+--------+--------' `--------+--------+--------+--------' ), }; void matrix_init_user(void) { //SSD1306 OLED init, make sure to add #define SSD1306OLED in config.h #ifdef SSD1306OLED iota_gfx_init(!has_usb()); // turns on the display #endif } //SSD1306 OLED update loop, make sure to add #define SSD1306OLED in config.h #ifdef SSD1306OLED // When add source files to SRC in rules.mk, you can use functions. const char *read_layer_state(void); const char *read_logo(void); void set_keylog(uint16_t keycode, keyrecord_t *record); const char *read_keylog(void); const char *read_keylogs(void); // const char *read_mode_icon(bool swap); // const char *read_host_led_state(void); // void set_timelog(void); // const char *read_timelog(void); void matrix_scan_user(void) { iota_gfx_task(); } void matrix_render_user(struct CharacterMatrix *matrix) { if (is_master) { // If you want to change the display of OLED, you need to change here matrix_write_ln(matrix, read_layer_state()); matrix_write_ln(matrix, read_keylog()); matrix_write_ln(matrix, read_keylogs()); //matrix_write_ln(matrix, read_mode_icon(keymap_config.swap_lalt_lgui)); //matrix_write_ln(matrix, read_host_led_state()); //matrix_write_ln(matrix, read_timelog()); } else { matrix_write(matrix, read_logo()); } } void matrix_update(struct CharacterMatrix *dest, const struct CharacterMatrix *source) { if (memcmp(dest->display, source->display, sizeof(dest->display))) { memcpy(dest->display, source->display, sizeof(dest->display)); dest->dirty = true; } } void iota_gfx_task_user(void) { struct CharacterMatrix matrix; matrix_clear(&matrix); matrix_render_user(&matrix); matrix_update(&display, &matrix); } #endif//SSD1306OLED bool process_record_user(uint16_t keycode, keyrecord_t *record) { if (record->event.pressed) { #ifdef SSD1306OLED set_keylog(keycode, record); #endif // set_timelog(); } switch (keycode) { case QWERTY: if (record->event.pressed) { set_single_persistent_default_layer(_QWERTY); } return false; break; case LOWER: if (record->event.pressed) { layer_on(_LOWER); } else { layer_off(_LOWER); } return false; break; case RAISE: if (record->event.pressed) { layer_on(_RAISE); } else { layer_off(_RAISE); } return false; break; } return true; }
A keyboards/claw44/keymaps/yfuku/config.h => keyboards/claw44/keymaps/yfuku/config.h +36 -0
@@ 0,0 1,36 @@ /* This is the c configuration file for the keymap Copyright 2012 Jun Wako <wakojun@gmail.com> Copyright 2015 Jack Humbert This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ #pragma once //#define USE_MATRIX_I2C /* Select hand configuration */ #define MASTER_LEFT // #define MASTER_RIGHT // #define EE_HANDS #define SSD1306OLED #define USE_SERIAL_PD2 #define TAPPING_TERM 180 #define IGNORE_MOD_TAP_INTERRUPT
A keyboards/claw44/keymaps/yfuku/keymap.c => keyboards/claw44/keymaps/yfuku/keymap.c +221 -0
@@ 0,0 1,221 @@ #include QMK_KEYBOARD_H #ifdef PROTOCOL_LUFA #include "lufa.h" #include "split_util.h" #endif #ifdef SSD1306OLED #include "ssd1306.h" #endif extern keymap_config_t keymap_config; extern uint8_t is_master; // Each layer gets a name for readability, which is then used in the keymap matrix below. // The underscores don't mean anything - you can have a layer called STUFF or any other name. // Layer names don't all need to be of the same length, obviously, and you can also skip them // entirely and just use numbers. enum custom_keycodes { QWERTY = SAFE_RANGE, LOWER, RAISE }; enum macro_keycodes { KC_SAMPLEMACRO, }; // common #define KC_ KC_TRNS #define KC_XXXX KC_NO #define KC_RST RESET #define KC_VD KC__VOLDOWN #define KC_VU KC__VOLUP // layer #define KC_L_SPC LT(_LOWER, KC_SPC) #define KC_R_ENT LT(_RAISE, KC_ENT) // shift_t #define KC_S_TAB LSFT_T(KC_TAB) #define KC_S_ESC LSFT_T(KC_ESC) #define KC_S_JA LSFT_T(KC_LANG1) #define KC_S_EN LSFT_T(KC_LANG2) // cmd_t #define KC_M_F LCMD_T(KC_F) #define KC_M_D LCMD_T(KC_D) #define KC_M_J LCMD_T(KC_J) #define KC_M_K LCMD_T(KC_K) // ctl_t #define KC_C_S LCTL_T(KC_S) #define KC_C_L LCTL_T(KC_L) #define KC_C_BS LCTL_T(KC_BSPC) // alt_t #define KC_A_D ALT_T(KC_D) #define KC_A_K ALT_T(KC_K) #define KC_A_Z ALT_T(KC_Z) #define KC_A_SL ALT_T(KC_SLSH) #define KC_A_DEL ALT_T(KC_DEL) // cmd+shift_t #define KC_MS_Q SCMD_T(KC_Q) #define KC_MS_A SCMD_T(KC_A) #define KC_MS_S SCMD_T(KC_S) #define KC_MS_SC SCMD_T(KC_SCLN) #define KC_MS_ESC SCMD_T(KC_ESC) // #define KC_MR RCMD(KC_R) #define KC_MF RCMD(KC_F) #define KC_MW RCMD(KC_W) #define KC_MX RCMD(KC_X) #define KC_MC RCMD(KC_C) #define KC_MV RCMD(KC_V) #define KC_MTAB RCMD(KC_TAB) #define KC_MSF RCMD(RSFT(KC_F)) #define KC_MSR RCMD(RSFT(KC_R)) #define KC_MST RCMD(RSFT(KC_T)) const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { // M_ = LCMD_T( // A_ = ALT_T( // C_ = LCTL_T( // MS_ = SMD_T( // R_ = LT(_RAISE // L_ = LT(_LOWER [_QWERTY] = LAYOUT_kc( \ //,----+----+----+----+----+----. ,----+----+----+----+----+----. ESC , Q , W , E , R , T , Y , U , I , O , P ,MINS, //|----+----+----+----+----+----| |----+----+----+----+----+----| S_TAB, A ,C_S , D ,M_F , G , H ,M_J , K ,C_L ,SCLN,S_ESC, //|----+----+----+----+----+----+ |----+----+----+----+----+----| , Z , X , C , V , B , N , M ,COMM,DOT ,SLSH, , //`----+----+----+----+----+----/ \----+----+----+----+----+----' A_DEL,S_EN,L_SPC,C_BS, C_BS,R_ENT,S_JA,A_DEL // `----+----+----+----' `----+----+----+----' ), // \ ^ ! & | @ = + * % - // ( # $ " ' ~ ← ↓ ↑ → ` ) // { [ ] } [_RAISE] = LAYOUT_kc( \ //,----+----+----+----+----+----. ,----+----+----+----+----+----. ,BSLS,CIRC,EXLM,AMPR,PIPE, AT ,EQL ,PLUS,ASTR,PERC,MINS, //|----+----+----+----+----+----| |----+----+----+----+----+----| LPRN,HASH,DLR ,DQT ,QUOT,TILD, LEFT,DOWN, UP ,RGHT,GRV ,RPRN, //|----+----+----+----+----+----| |----+----+----+----+----+----| , , , ,LCBR,LBRC, RBRC,RCBR, , , , , //`----+----+----+----+----+----/ \----+----+----+----+----+----' , ,BSPC, , , , ,RST // `----+----+----+----' `----+----+----+----' ), [_LOWER] = LAYOUT_kc( \ //,----+----+----+----+----+----. ,----+----+----+----+----+----. , , ,MSF ,MSR ,MST , ,EQL ,PLUS,ASTR,PERC,MINS, //|----+----+----+----+----+----| |----+----+----+----+----+----| , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 0 , , //|----+----+----+----+----+----| |----+----+----+----+----+----| , , , , , , , ,COMM,DOT ,SLSH, , //`----+----+----+--+-+----+----/ \----+----+----+----+----+----' RST , , , , ,DEL , , // `----+----+----+----' `----+----+----+----' ), }; void matrix_init_user(void) { //SSD1306 OLED init, make sure to add #define SSD1306OLED in config.h #ifdef SSD1306OLED iota_gfx_init(!has_usb()); // turns on the display #endif } //SSD1306 OLED update loop, make sure to add #define SSD1306OLED in config.h #ifdef SSD1306OLED // When add source files to SRC in rules.mk, you can use functions. const char *read_layer_state(void); const char *read_logo(void); void set_keylog(uint16_t keycode, keyrecord_t *record); const char *read_keylog(void); const char *read_keylogs(void); // const char *read_mode_icon(bool swap); // const char *read_host_led_state(void); // void set_timelog(void); // const char *read_timelog(void); void matrix_scan_user(void) { iota_gfx_task(); } void matrix_render_user(struct CharacterMatrix *matrix) { if (is_master) { // If you want to change the display of OLED, you need to change here matrix_write_ln(matrix, read_layer_state()); matrix_write_ln(matrix, read_keylog()); matrix_write_ln(matrix, read_keylogs()); //matrix_write_ln(matrix, read_mode_icon(keymap_config.swap_lalt_lgui)); //matrix_write_ln(matrix, read_host_led_state()); //matrix_write_ln(matrix, read_timelog()); } else { matrix_write(matrix, read_logo()); } } void matrix_update(struct CharacterMatrix *dest, const struct CharacterMatrix *source) { if (memcmp(dest->display, source->display, sizeof(dest->display))) { memcpy(dest->display, source->display, sizeof(dest->display)); dest->dirty = true; } } void iota_gfx_task_user(void) { struct CharacterMatrix matrix; matrix_clear(&matrix); matrix_render_user(&matrix); matrix_update(&display, &matrix); } #endif//SSD1306OLED bool process_record_user(uint16_t keycode, keyrecord_t *record) { if (record->event.pressed) { #ifdef SSD1306OLED set_keylog(keycode, record); #endif // set_timelog(); } switch (keycode) { case QWERTY: if (record->event.pressed) { set_single_persistent_default_layer(_QWERTY); } return false; break; case LOWER: if (record->event.pressed) { layer_on(_LOWER); } else { layer_off(_LOWER); } return false; break; case RAISE: if (record->event.pressed) { layer_on(_RAISE); } else { layer_off(_RAISE); } return false; break; } return true; }
A keyboards/claw44/lib/glcdfont.c => keyboards/claw44/lib/glcdfont.c +243 -0
@@ 0,0 1,243 @@ // This is the 'classic' fixed-space bitmap font for Adafruit_GFX since 1.0. // See gfxfont.h for newer custom bitmap font info. #ifndef FONT5X7_H #define FONT5X7_H #ifdef __AVR__ #include <avr/io.h> #include <avr/pgmspace.h> #elif defined(ESP8266) #include <pgmspace.h> #else #define PROGMEM #endif // Standard ASCII 5x7 font const unsigned char font[] PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x5B, 0x4F, 0x5B, 0x3E, 0x00, 0x3E, 0x6B, 0x4F, 0x6B, 0x3E, 0x00, 0x1C, 0x3E, 0x7C, 0x3E, 0x1C, 0x00, 0x18, 0x3C, 0x7E, 0x3C, 0x18, 0x00, 0x1C, 0x57, 0x7D, 0x57, 0x1C, 0x00, 0x1C, 0x5E, 0x7F, 0x5E, 0x1C, 0x00, 0x00, 0x18, 0x3C, 0x18, 0x00, 0x00, 0xFF, 0xE7, 0xC3, 0xE7, 0xFF, 0x00, 0x00, 0x18, 0x24, 0x18, 0x00, 0x00, 0xFF, 0xE7, 0xDB, 0xE7, 0xFF, 0x00, 0x30, 0x48, 0x3A, 0x06, 0x0E, 0x00, 0x26, 0x29, 0x79, 0x29, 0x26, 0x00, 0x40, 0x7F, 0x05, 0x05, 0x07, 0x00, 0x40, 0x7F, 0x05, 0x25, 0x3F, 0x00, 0x5A, 0x3C, 0xE7, 0x3C, 0x5A, 0x00, 0x7F, 0x3E, 0x1C, 0x1C, 0x08, 0x00, 0x08, 0x1C, 0x1C, 0x3E, 0x7F, 0x00, 0x14, 0x22, 0x7F, 0x22, 0x14, 0x00, 0x5F, 0x5F, 0x00, 0x5F, 0x5F, 0x00, 0x06, 0x09, 0x7F, 0x01, 0x7F, 0x00, 0x00, 0x66, 0x89, 0x95, 0x6A, 0x00, 0x60, 0x60, 0x60, 0x60, 0x60, 0x00, 0x94, 0xA2, 0xFF, 0xA2, 0x94, 0x00, 0x08, 0x04, 0x7E, 0x04, 0x08, 0x00, 0x10, 0x20, 0x7E, 0x20, 0x10, 0x00, 0x08, 0x08, 0x2A, 0x1C, 0x08, 0x00, 0x08, 0x1C, 0x2A, 0x08, 0x08, 0x00, 0x1E, 0x10, 0x10, 0x10, 0x10, 0x00, 0x0C, 0x1E, 0x0C, 0x1E, 0x0C, 0x00, 0x30, 0x38, 0x3E, 0x38, 0x30, 0x00, 0x06, 0x0E, 0x3E, 0x0E, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x14, 0x7F, 0x14, 0x7F, 0x14, 0x00, 0x24, 0x2A, 0x7F, 0x2A, 0x12, 0x00, 0x23, 0x13, 0x08, 0x64, 0x62, 0x00, 0x36, 0x49, 0x56, 0x20, 0x50, 0x00, 0x00, 0x08, 0x07, 0x03, 0x00, 0x00, 0x00, 0x1C, 0x22, 0x41, 0x00, 0x00, 0x00, 0x41, 0x22, 0x1C, 0x00, 0x00, 0x2A, 0x1C, 0x7F, 0x1C, 0x2A, 0x00, 0x08, 0x08, 0x3E, 0x08, 0x08, 0x00, 0x00, 0x80, 0x70, 0x30, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x60, 0x60, 0x00, 0x00, 0x20, 0x10, 0x08, 0x04, 0x02, 0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E, 0x00, 0x00, 0x42, 0x7F, 0x40, 0x00, 0x00, 0x72, 0x49, 0x49, 0x49, 0x46, 0x00, 0x21, 0x41, 0x49, 0x4D, 0x33, 0x00, 0x18, 0x14, 0x12, 0x7F, 0x10, 0x00, 0x27, 0x45, 0x45, 0x45, 0x39, 0x00, 0x3C, 0x4A, 0x49, 0x49, 0x31, 0x00, 0x41, 0x21, 0x11, 0x09, 0x07, 0x00, 0x36, 0x49, 0x49, 0x49, 0x36, 0x00, 0x46, 0x49, 0x49, 0x29, 0x1E, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x40, 0x34, 0x00, 0x00, 0x00, 0x00, 0x08, 0x14, 0x22, 0x41, 0x00, 0x14, 0x14, 0x14, 0x14, 0x14, 0x00, 0x00, 0x41, 0x22, 0x14, 0x08, 0x00, 0x02, 0x01, 0x59, 0x09, 0x06, 0x00, 0x3E, 0x41, 0x5D, 0x59, 0x4E, 0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C, 0x00, 0x7F, 0x49, 0x49, 0x49, 0x36, 0x00, 0x3E, 0x41, 0x41, 0x41, 0x22, 0x00, 0x7F, 0x41, 0x41, 0x41, 0x3E, 0x00, 0x7F, 0x49, 0x49, 0x49, 0x41, 0x00, 0x7F, 0x09, 0x09, 0x09, 0x01, 0x00, 0x3E, 0x41, 0x41, 0x51, 0x73, 0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F, 0x00, 0x00, 0x41, 0x7F, 0x41, 0x00, 0x00, 0x20, 0x40, 0x41, 0x3F, 0x01, 0x00, 0x7F, 0x08, 0x14, 0x22, 0x41, 0x00, 0x7F, 0x40, 0x40, 0x40, 0x40, 0x00, 0x7F, 0x02, 0x1C, 0x02, 0x7F, 0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F, 0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E, 0x00, 0x7F, 0x09, 0x09, 0x09, 0x06, 0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E, 0x00, 0x7F, 0x09, 0x19, 0x29, 0x46, 0x00, 0x26, 0x49, 0x49, 0x49, 0x32, 0x00, 0x03, 0x01, 0x7F, 0x01, 0x03, 0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F, 0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F, 0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F, 0x00, 0x63, 0x14, 0x08, 0x14, 0x63, 0x00, 0x03, 0x04, 0x78, 0x04, 0x03, 0x00, 0x61, 0x59, 0x49, 0x4D, 0x43, 0x00, 0x00, 0x7F, 0x41, 0x41, 0x41, 0x00, 0x02, 0x04, 0x08, 0x10, 0x20, 0x00, 0x00, 0x41, 0x41, 0x41, 0x7F, 0x00, 0x04, 0x02, 0x01, 0x02, 0x04, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x03, 0x07, 0x08, 0x00, 0x00, 0x20, 0x54, 0x54, 0x78, 0x40, 0x00, 0x7F, 0x28, 0x44, 0x44, 0x38, 0x00, 0x38, 0x44, 0x44, 0x44, 0x28, 0x00, 0x38, 0x44, 0x44, 0x28, 0x7F, 0x00, 0x38, 0x54, 0x54, 0x54, 0x18, 0x00, 0x00, 0x08, 0x7E, 0x09, 0x02, 0x00, 0x18, 0x24, 0x24, 0x1C, 0x78, 0x00, 0x7F, 0x08, 0x04, 0x04, 0x78, 0x00, 0x00, 0x44, 0x7D, 0x40, 0x00, 0x00, 0x20, 0x40, 0x40, 0x3D, 0x00, 0x00, 0x7F, 0x10, 0x28, 0x44, 0x00, 0x00, 0x00, 0x41, 0x7F, 0x40, 0x00, 0x00, 0x7C, 0x04, 0x78, 0x04, 0x78, 0x00, 0x7C, 0x08, 0x04, 0x04, 0x78, 0x00, 0x38, 0x44, 0x44, 0x44, 0x38, 0x00, 0x7C, 0x18, 0x24, 0x24, 0x18, 0x00, 0x18, 0x24, 0x24, 0x18, 0x7C, 0x00, 0x7C, 0x08, 0x04, 0x04, 0x08, 0x00, 0x48, 0x54, 0x54, 0x54, 0x24, 0x00, 0x04, 0x04, 0x3F, 0x44, 0x24, 0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C, 0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C, 0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C, 0x00, 0x44, 0x28, 0x10, 0x28, 0x44, 0x00, 0x4C, 0x90, 0x90, 0x90, 0x7C, 0x00, 0x44, 0x64, 0x54, 0x4C, 0x44, 0x00, 0x00, 0x08, 0x36, 0x41, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x00, 0x41, 0x36, 0x08, 0x00, 0x00, 0x02, 0x01, 0x02, 0x04, 0x02, 0x00, 0x3C, 0x26, 0x23, 0x26, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFC, 0xFC, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xF0, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xE0, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xF0, 0xF0, 0xF0, 0xE0, 0xEC, 0xEE, 0xF7, 0xF3, 0x70, 0x20, 0x00, 0x7C, 0x7C, 0x7C, 0x7E, 0x00, 0x7E, 0x7E, 0x7E, 0x7F, 0x7F, 0x7F, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0x7E, 0x5B, 0x4F, 0x5B, 0xFE, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0xDC, 0xD7, 0xDE, 0xDE, 0xDE, 0xD7, 0xDC, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFC, 0xFE, 0xFF, 0x1F, 0x07, 0x07, 0x07, 0x07, 0x1F, 0x1F, 0x1F, 0x1E, 0x18, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x9E, 0xDF, 0xDF, 0xCF, 0xC7, 0xE7, 0xE7, 0xE7, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x03, 0x3F, 0xFF, 0xFF, 0xFE, 0xC0, 0x00, 0xF0, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF, 0xF0, 0x00, 0xC0, 0xFC, 0xFF, 0xFF, 0x3F, 0x03, 0x00, 0xC0, 0xF0, 0xF8, 0xFE, 0x9F, 0x87, 0x83, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x80, 0x00, 0x00, 0xE0, 0xF8, 0xFC, 0xBF, 0x8F, 0x83, 0x81, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x1F, 0x3F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x3F, 0x1E, 0x0C, 0x00, 0x1F, 0x1F, 0x1F, 0x3F, 0x00, 0x3F, 0x3F, 0x3F, 0x7F, 0x7F, 0x7F, 0x00, 0x30, 0x7B, 0x7F, 0x78, 0x30, 0x20, 0x20, 0x30, 0x78, 0x7F, 0x3B, 0x00, 0x03, 0x00, 0x0F, 0x7F, 0x0F, 0x0F, 0x0F, 0x7F, 0x0F, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x1F, 0x3F, 0x7F, 0x7C, 0x78, 0x70, 0x70, 0x78, 0x7E, 0x3E, 0x3E, 0x0E, 0x06, 0x00, 0x00, 0x7F, 0x7F, 0x7F, 0x7F, 0x00, 0x00, 0x00, 0x1F, 0x3F, 0x7F, 0x7F, 0x79, 0x71, 0x70, 0x30, 0x38, 0x3F, 0x7F, 0x7F, 0x7F, 0x60, 0x00, 0x00, 0x00, 0x01, 0x1F, 0x7F, 0x7F, 0x7E, 0x7F, 0x1F, 0x01, 0x00, 0x01, 0x3F, 0x7F, 0x7E, 0x7F, 0x7F, 0x0F, 0x01, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x7F, 0x7F, 0x7F, 0x7F, 0x03, 0x03, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x7F, 0x7F, 0x7F, 0x7F, 0x07, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; #endif // FONT5X7_H
A keyboards/claw44/lib/host_led_state_reader.c => keyboards/claw44/lib/host_led_state_reader.c +15 -0
@@ 0,0 1,15 @@ #include <stdio.h> #include "claw44.h" char host_led_state_str[24]; const char *read_host_led_state(void) { uint8_t leds = host_keyboard_leds(); snprintf(host_led_state_str, sizeof(host_led_state_str), "NL:%s CL:%s SL:%s", (leds & (1 << USB_LED_NUM_LOCK)) ? "on" : "- ", (leds & (1 << USB_LED_CAPS_LOCK)) ? "on" : "- ", (leds & (1 << USB_LED_SCROLL_LOCK)) ? "on" : "- "); return host_led_state_str; }
A keyboards/claw44/lib/keylogger.c => keyboards/claw44/lib/keylogger.c +45 -0
@@ 0,0 1,45 @@ #include <stdio.h> #include "claw44.h" char keylog_str[24] = {}; char keylogs_str[21] = {}; int keylogs_str_idx = 0; const char code_to_name[60] = { ' ', ' ', ' ', ' ', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 'R', 'E', 'B', 'T', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ';', '\'', ' ', ',', '.', '/', ' ', ' ', ' '}; void set_keylog(uint16_t keycode, keyrecord_t *record) { char name = ' '; if (keycode < 60) { name = code_to_name[keycode]; } // update keylog snprintf(keylog_str, sizeof(keylog_str), "%dx%d, k%2d : %c", record->event.key.row, record->event.key.col, keycode, name); // update keylogs if (keylogs_str_idx == sizeof(keylogs_str) - 1) { keylogs_str_idx = 0; for (int i = 0; i < sizeof(keylogs_str) - 1; i++) { keylogs_str[i] = ' '; } } keylogs_str[keylogs_str_idx] = name; keylogs_str_idx++; } const char *read_keylog(void) { return keylog_str; } const char *read_keylogs(void) { return keylogs_str; }
A keyboards/claw44/lib/layer_state_reader.c => keyboards/claw44/lib/layer_state_reader.c +35 -0
@@ 0,0 1,35 @@ #include QMK_KEYBOARD_H #include <stdio.h> #include "claw44.h" #define L_BASE 0 #define L_LOWER (1<<_LOWER) #define L_RAISE (1<<_RAISE) #define L_ADJUST (1<<_ADJUST) #define L_ADJUST_TRI (L_ADJUST|L_RAISE|L_LOWER) char layer_state_str[24]; const char *read_layer_state(void) { switch (layer_state) { case L_BASE: snprintf(layer_state_str, sizeof(layer_state_str), "Layer: Default"); break; case L_RAISE: snprintf(layer_state_str, sizeof(layer_state_str), "Layer: Raise"); break; case L_LOWER: snprintf(layer_state_str, sizeof(layer_state_str), "Layer: Lower"); break; case L_ADJUST: case L_ADJUST_TRI: snprintf(layer_state_str, sizeof(layer_state_str), "Layer: Adjust"); break; default: snprintf(layer_state_str, sizeof(layer_state_str), "Layer: Undef-%ld", layer_state); } return layer_state_str; }
A keyboards/claw44/lib/logo_reader.c => keyboards/claw44/lib/logo_reader.c +11 -0
@@ 0,0 1,11 @@ #include "claw44.h" const char *read_logo(void) { static char logo[] = { 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0}; return logo; }
A keyboards/claw44/lib/mode_icon_reader.c => keyboards/claw44/lib/mode_icon_reader.c +15 -0
@@ 0,0 1,15 @@ #include <stdio.h> #include "claw44.h" char mode_icon[24]; const char *read_mode_icon(bool swap) { static char logo[][2][3] = {{{0x95, 0x96, 0}, {0xb5, 0xb6, 0}}, {{0x97, 0x98, 0}, {0xb7, 0xb8, 0}}}; if (swap == false) { snprintf(mode_icon, sizeof(mode_icon), "%s\n%s", logo[0][0], logo[0][1]); } else { snprintf(mode_icon, sizeof(mode_icon), "%s\n%s", logo[1][0], logo[1][1]); } return mode_icon; }
A keyboards/claw44/lib/rgb_state_reader.c => keyboards/claw44/lib/rgb_state_reader.c +15 -0
@@ 0,0 1,15 @@ #ifdef RGBLIGHT_ENABLE #include QMK_KEYBOARD_H #include <stdio.h> extern rgblight_config_t rgblight_config; char rbf_info_str[24]; const char *read_rgb_info(void) { snprintf(rbf_info_str, sizeof(rbf_info_str), "%s %2d h%3d s%3d v%3d", rgblight_config.enable ? "on" : "- ", rgblight_config.mode, rgblight_config.hue, rgblight_config.sat, rgblight_config.val); return rbf_info_str; } #endif
A keyboards/claw44/lib/timelogger.c => keyboards/claw44/lib/timelogger.c +16 -0
@@ 0,0 1,16 @@ #include <stdio.h> #include "claw44.h" char timelog_str[24] = {}; int last_time = 0; int elapsed_time = 0; void set_timelog(void) { elapsed_time = timer_elapsed(last_time); last_time = timer_read(); snprintf(timelog_str, sizeof(timelog_str), "lt:%5d, et:%5d", last_time, elapsed_time); } const char *read_timelog(void) { return timelog_str; }
A keyboards/claw44/readme.md => keyboards/claw44/readme.md +15 -0
@@ 0,0 1,15 @@ # Claw44  A split keyboard with 3x6 vertically staggered keys and 4 thumb keys. Keyboard Maintainer: [@yfuku_](https://twitter.com/yfuku_) Hardware Supported: Claw44 PCB, ProMicro Hardware Availability: https://yfuku.booth.pm/ Make example for this keyboard (after setting up your build environment): make claw44:default See 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).
A keyboards/claw44/rev1/config.h => keyboards/claw44/rev1/config.h +76 -0
@@ 0,0 1,76 @@ /* Copyright 2012 Jun Wako <wakojun@gmail.com> Copyright 2015 Jack Humbert This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ #pragma once /* USB Device descriptor parameter */ #define VENDOR_ID 0xFEED #define PRODUCT_ID 0x3060 #define DEVICE_VER 0x0001 #define MANUFACTURER yfuku #define PRODUCT claw44 #define DESCRIPTION A split keyboard with 3x6 vertically staggered keys and 4 thumb keys /* key matrix size */ // Rows are doubled-up #define MATRIX_ROWS 8 #define MATRIX_COLS 7 #define MATRIX_ROW_PINS { D4, C6, D7, E6 } // wiring of each half #define MATRIX_COL_PINS { F4, F5, F6, F7, B1, B3, B2 } // #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 /* define if matrix has ghost */ //#define MATRIX_HAS_GHOST /* number of backlight levels */ // #define BACKLIGHT_LEVELS 3 /* Set 0 if debouncing isn't needed */ #define DEBOUNCING_DELAY 5 /* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */ //#define LOCKING_SUPPORT_ENABLE /* Locking resynchronize hack */ //#define LOCKING_RESYNC_ENABLE /* ws2812 RGB LED */ /* #define RGB_DI_PIN D3 #define RGBLED_NUM 12 // Number of LEDs */ /* * Feature disable options * These options are also useful to firmware size reduction. */ /* disable debug print */ // #define NO_DEBUG /* disable print */ // #define NO_PRINT /* disable action features */ //#define NO_ACTION_LAYER //#define NO_ACTION_TAPPING //#define NO_ACTION_ONESHOT //#define NO_ACTION_MACRO //#define NO_ACTION_FUNCTION
A keyboards/claw44/rev1/matrix.c => keyboards/claw44/rev1/matrix.c +357 -0
@@ 0,0 1,357 @@ /* Copyright 2012 Jun Wako <wakojun@gmail.com> This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ /* * scan matrix */ #include <stdint.h> #include <stdbool.h> #include <string.h> #include <avr/io.h> #include <avr/wdt.h> #include <avr/interrupt.h> #include <util/delay.h> #include "print.h" #include "debug.h" #include "util.h" #include "matrix.h" #include "split_util.h" #include "pro_micro.h" #ifdef USE_MATRIX_I2C # include "i2c.h" #else // USE_SERIAL # include "split_scomm.h" #endif #ifndef DEBOUNCE # define DEBOUNCE 5 #endif #define ERROR_DISCONNECT_COUNT 5 static uint8_t debouncing = DEBOUNCE; static const int ROWS_PER_HAND = MATRIX_ROWS/2; static uint8_t error_count = 0; uint8_t is_master = 0 ; static const uint8_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS; static const uint8_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS; /* matrix state(1:on, 0:off) */ static matrix_row_t matrix[MATRIX_ROWS]; static matrix_row_t matrix_debouncing[MATRIX_ROWS]; static matrix_row_t read_cols(void); static void init_cols(void); static void unselect_rows(void); static void select_row(uint8_t row); static uint8_t matrix_master_scan(void); __attribute__ ((weak)) void matrix_init_kb(void) { matrix_init_user(); } __attribute__ ((weak)) void matrix_scan_kb(void) { matrix_scan_user(); } __attribute__ ((weak)) void matrix_init_user(void) { } __attribute__ ((weak)) void matrix_scan_user(void) { } inline uint8_t matrix_rows(void) { return MATRIX_ROWS; } inline uint8_t matrix_cols(void) { return MATRIX_COLS; } void matrix_init(void) { debug_enable = true; debug_matrix = true; debug_mouse = true; // initialize row and col unselect_rows(); init_cols(); TX_RX_LED_INIT; TXLED0; RXLED0; // initialize matrix state: all keys off for (uint8_t i=0; i < MATRIX_ROWS; i++) { matrix[i] = 0; matrix_debouncing[i] = 0; } is_master = has_usb(); matrix_init_quantum(); } uint8_t _matrix_scan(void) { // Right hand is stored after the left in the matirx so, we need to offset it int offset = isLeftHand ? 0 : (ROWS_PER_HAND); for (uint8_t i = 0; i < ROWS_PER_HAND; i++) { select_row(i); _delay_us(30); // without this wait read unstable value. matrix_row_t cols = read_cols(); if (matrix_debouncing[i+offset] != cols) { matrix_debouncing[i+offset] = cols; debouncing = DEBOUNCE; } unselect_rows(); } if (debouncing) { if (--debouncing) { _delay_ms(1); } else { for (uint8_t i = 0; i < ROWS_PER_HAND; i++) { matrix[i+offset] = matrix_debouncing[i+offset]; } } } return 1; } #ifdef USE_MATRIX_I2C // Get rows from other half over i2c int i2c_transaction(void) { int slaveOffset = (isLeftHand) ? (ROWS_PER_HAND) : 0; int err = i2c_master_start(SLAVE_I2C_ADDRESS + I2C_WRITE); if (err) goto i2c_error; // start of matrix stored at 0x00 err = i2c_master_write(0x00); if (err) goto i2c_error; // Start read err = i2c_master_start(SLAVE_I2C_ADDRESS + I2C_READ); if (err) goto i2c_error; if (!err) { int i; for (i = 0; i < ROWS_PER_HAND-1; ++i) { matrix[slaveOffset+i] = i2c_master_read(I2C_ACK); } matrix[slaveOffset+i] = i2c_master_read(I2C_NACK); i2c_master_stop(); } else { i2c_error: // the cable is disconnceted, or something else went wrong i2c_reset_state(); return err; } return 0; } #else // USE_SERIAL int serial_transaction(int master_changed) { int slaveOffset = (isLeftHand) ? (ROWS_PER_HAND) : 0; #ifdef SERIAL_USE_MULTI_TRANSACTION int ret=serial_update_buffers(master_changed); #else int ret=serial_update_buffers(); #endif if (ret ) { if(ret==2) RXLED1; return 1; } RXLED0; memcpy(&matrix[slaveOffset], (void *)serial_slave_buffer, SERIAL_SLAVE_BUFFER_LENGTH); return 0; } #endif uint8_t matrix_scan(void) { if (is_master) { matrix_master_scan(); }else{ matrix_slave_scan(); int offset = (isLeftHand) ? ROWS_PER_HAND : 0; memcpy(&matrix[offset], (void *)serial_master_buffer, SERIAL_MASTER_BUFFER_LENGTH); matrix_scan_quantum(); } return 1; } uint8_t matrix_master_scan(void) { int ret = _matrix_scan(); int mchanged = 1; int offset = (isLeftHand) ? 0 : ROWS_PER_HAND; #ifdef USE_MATRIX_I2C // for (int i = 0; i < ROWS_PER_HAND; ++i) { /* i2c_slave_buffer[i] = matrix[offset+i]; */ // i2c_slave_buffer[i] = matrix[offset+i]; // } #else // USE_SERIAL #ifdef SERIAL_USE_MULTI_TRANSACTION mchanged = memcmp((void *)serial_master_buffer, &matrix[offset], SERIAL_MASTER_BUFFER_LENGTH); #endif memcpy((void *)serial_master_buffer, &matrix[offset], SERIAL_MASTER_BUFFER_LENGTH); #endif #ifdef USE_MATRIX_I2C if( i2c_transaction() ) { #else // USE_SERIAL if( serial_transaction(mchanged) ) { #endif // turn on the indicator led when halves are disconnected TXLED1; error_count++; if (error_count > ERROR_DISCONNECT_COUNT) { // reset other half if disconnected int slaveOffset = (isLeftHand) ? (ROWS_PER_HAND) : 0; for (int i = 0; i < ROWS_PER_HAND; ++i) { matrix[slaveOffset+i] = 0; } } } else { // turn off the indicator led on no error TXLED0; error_count = 0; } matrix_scan_quantum(); return ret; } void matrix_slave_scan(void) { _matrix_scan(); int offset = (isLeftHand) ? 0 : ROWS_PER_HAND; #ifdef USE_MATRIX_I2C for (int i = 0; i < ROWS_PER_HAND; ++i) { /* i2c_slave_buffer[i] = matrix[offset+i]; */ i2c_slave_buffer[i] = matrix[offset+i]; } #else // USE_SERIAL #ifdef SERIAL_USE_MULTI_TRANSACTION int change = 0; #endif for (int i = 0; i < ROWS_PER_HAND; ++i) { #ifdef SERIAL_USE_MULTI_TRANSACTION if( serial_slave_buffer[i] != matrix[offset+i] ) change = 1; #endif serial_slave_buffer[i] = matrix[offset+i]; } #ifdef SERIAL_USE_MULTI_TRANSACTION slave_buffer_change_count += change; #endif #endif } bool matrix_is_modified(void) { if (debouncing) return false; return true; } inline bool matrix_is_on(uint8_t row, uint8_t col) { return (matrix[row] & ((matrix_row_t)1<<col)); } inline matrix_row_t matrix_get_row(uint8_t row) { return matrix[row]; } void matrix_print(void) { print("\nr/c 0123456789ABCDEF\n"); for (uint8_t row = 0; row < MATRIX_ROWS; row++) { phex(row); print(": "); pbin_reverse16(matrix_get_row(row)); print("\n"); } } uint8_t matrix_key_count(void) { uint8_t count = 0; for (uint8_t i = 0; i < MATRIX_ROWS; i++) { count += bitpop16(matrix[i]); } return count; } static void init_cols(void) { for(int x = 0; x < MATRIX_COLS; x++) { _SFR_IO8((col_pins[x] >> 4) + 1) &= ~_BV(col_pins[x] & 0xF); _SFR_IO8((col_pins[x] >> 4) + 2) |= _BV(col_pins[x] & 0xF); } } static matrix_row_t read_cols(void) { matrix_row_t result = 0; for(int x = 0; x < MATRIX_COLS; x++) { result |= (_SFR_IO8(col_pins[x] >> 4) & _BV(col_pins[x] & 0xF)) ? 0 : (1 << x); } return result; } static void unselect_rows(void) { for(int x = 0; x < ROWS_PER_HAND; x++) { _SFR_IO8((row_pins[x] >> 4) + 1) &= ~_BV(row_pins[x] & 0xF); _SFR_IO8((row_pins[x] >> 4) + 2) |= _BV(row_pins[x] & 0xF); } } static void select_row(uint8_t row) { _SFR_IO8((row_pins[row] >> 4) + 1) |= _BV(row_pins[row] & 0xF); _SFR_IO8((row_pins[row] >> 4) + 2) &= ~_BV(row_pins[row] & 0xF); }
A keyboards/claw44/rev1/rev1.c => keyboards/claw44/rev1/rev1.c +8 -0
@@ 0,0 1,8 @@ #include "claw44.h" #ifdef SSD1306OLED void led_set_kb(uint8_t usb_led) { // put your keyboard LED indicator (ex: Caps Lock LED) toggling code here //led_set_user(usb_led); } #endif
A keyboards/claw44/rev1/rev1.h => keyboards/claw44/rev1/rev1.h +57 -0
@@ 0,0 1,57 @@ #pragma once #include "../claw44.h" //void promicro_bootloader_jmp(bool program); #include "quantum.h" #ifdef RGBLIGHT_ENABLE //rgb led driver #include "ws2812.h" #endif #ifdef USE_I2C #include <stddef.h> #ifdef __AVR__ #include <avr/io.h> #include <avr/interrupt.h> #endif #endif //void promicro_bootloader_jmp(bool program); #define LAYOUT( \ L00, L01, L02, L03, L04, L05, R00, R01, R02, R03, R04, R05, \ L10, L11, L12, L13, L14, L15, R10, R11, R12, R13, R14, R15, \ L20, L21, L22, L23, L24, L25, R20, R21, R22, R23, R24, R25, \ L30, L31, L32, L33, R30, R31, R32, R33 \ ) \ { \ { L00, L01, L02, L03, L04, L05 }, \ { L10, L11, L12, L13, L14, L15 }, \ { L20, L21, L22, L23, L24, L25 }, \ { KC_NO, KC_NO, L30, L31, L32, L33 }, \ { R05, R04, R03, R02, R01, R00 }, \ { R15, R14, R13, R12, R11, R10 }, \ { R25, R24, R23, R22, R21, R20 }, \ { KC_NO, KC_NO, R33, R32, R31, R30 } \ } #define LAYOUT_kc( \ L00, L01, L02, L03, L04, L05, R00, R01, R02, R03, R04, R05, \ L10, L11, L12, L13, L14, L15, R10, R11, R12, R13, R14, R15, \ L20, L21, L22, L23, L24, L25, R20, R21, R22, R23, R24, R25, \ L30, L31, L32, L33, R30, R31, R32, R33 \ ) \ LAYOUT( \ KC_##L00, KC_##L01, KC_##L02, KC_##L03, KC_##L04, KC_##L05, KC_##R00, KC_##R01, KC_##R02, KC_##R03, KC_##R04, KC_##R05, \ KC_##L10, KC_##L11, KC_##L12, KC_##L13, KC_##L14, KC_##L15, KC_##R10, KC_##R11, KC_##R12, KC_##R13, KC_##R14, KC_##R15, \ KC_##L20, KC_##L21, KC_##L22, KC_##L23, KC_##L24, KC_##L25, KC_##R20, KC_##R21, KC_##R22, KC_##R23, KC_##R24, KC_##R25, \ KC_##L30, KC_##L31, KC_##L32, KC_##L33, KC_##R30, KC_##R31, KC_##R32, KC_##R33 \ ) enum layer_number { _QWERTY = 0, _LOWER, _RAISE, _ADJUST, };
A keyboards/claw44/rev1/rules.mk => keyboards/claw44/rev1/rules.mk +31 -0
@@ 0,0 1,31 @@ SRC += rev1/matrix.c SRC += rev1/split_util.c SRC += rev1/split_scomm.c # Build Options BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration(+1000) MOUSEKEY_ENABLE = no # Mouse keys(+4700) EXTRAKEY_ENABLE = no # Audio control and System control(+450) CONSOLE_ENABLE = no # Console for debug(+400) COMMAND_ENABLE = no # Commands for debug and configuration NKRO_ENABLE = no # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality MIDI_ENABLE = no # MIDI controls AUDIO_ENABLE = no # Audio output on port C6 UNICODE_ENABLE = no # Unicode BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID RGBLIGHT_ENABLE = no # Enable WS2812 RGB underlight. SWAP_HANDS_ENABLE = no # Enable one-hand typing # Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend # If you want to change the display of OLED, you need to change here SRC += ./lib/glcdfont.c \ ./lib/layer_state_reader.c \ ./lib/logo_reader.c \ ./lib/keylogger.c \ # ./lib/rgb_state_reader.c \ # ./lib/mode_icon_reader.c \ # ./lib/host_led_state_reader.c \ # ./lib/timelogger.c \
A keyboards/claw44/rev1/serial_config.h => keyboards/claw44/rev1/serial_config.h +4 -0
@@ 0,0 1,4 @@ #ifndef SOFT_SERIAL_PIN #define SOFT_SERIAL_PIN D2 #define SERIAL_USE_MULTI_TRANSACTION #endif
A keyboards/claw44/rev1/split_scomm.c => keyboards/claw44/rev1/split_scomm.c +91 -0
@@ 0,0 1,91 @@ #ifdef USE_SERIAL #ifdef SERIAL_USE_MULTI_TRANSACTION /* --- USE flexible API (using multi-type transaction function) --- */ #include <stdbool.h> #include <stdint.h> #include <stddef.h> #include <split_scomm.h> #include "serial.h" #ifdef CONSOLE_ENABLE #include <print.h> #endif uint8_t volatile serial_slave_buffer[SERIAL_SLAVE_BUFFER_LENGTH] = {0}; uint8_t volatile serial_master_buffer[SERIAL_MASTER_BUFFER_LENGTH] = {0}; uint8_t volatile status_com = 0; uint8_t volatile status1 = 0; uint8_t slave_buffer_change_count = 0; uint8_t s_change_old = 0xff; uint8_t s_change_new = 0xff; SSTD_t transactions[] = { #define GET_SLAVE_STATUS 0 /* master buffer not changed, only recive slave_buffer_change_count */ { (uint8_t *)&status_com, 0, NULL, sizeof(slave_buffer_change_count), &slave_buffer_change_count, }, #define PUT_MASTER_GET_SLAVE_STATUS 1 /* master buffer changed need send, and recive slave_buffer_change_count */ { (uint8_t *)&status_com, sizeof(serial_master_buffer), (uint8_t *)serial_master_buffer, sizeof(slave_buffer_change_count), &slave_buffer_change_count, }, #define GET_SLAVE_BUFFER 2 /* recive serial_slave_buffer */ { (uint8_t *)&status1, 0, NULL, sizeof(serial_slave_buffer), (uint8_t *)serial_slave_buffer } }; void serial_master_init(void) { soft_serial_initiator_init(transactions, TID_LIMIT(transactions)); } void serial_slave_init(void) { soft_serial_target_init(transactions, TID_LIMIT(transactions)); } // 0 => no error // 1 => slave did not respond // 2 => checksum error int serial_update_buffers(int master_update) { int status, smatstatus; static int need_retry = 0; if( s_change_old != s_change_new ) { smatstatus = soft_serial_transaction(GET_SLAVE_BUFFER); if( smatstatus == TRANSACTION_END ) { s_change_old = s_change_new; #ifdef CONSOLE_ENABLE uprintf("slave matrix = %b %b %b %b\n", serial_slave_buffer[0], serial_slave_buffer[1], serial_slave_buffer[2], serial_slave_buffer[3]); #endif } } else { // serial_slave_buffer dosen't change smatstatus = TRANSACTION_END; // dummy status } if( !master_update && !need_retry) { status = soft_serial_transaction(GET_SLAVE_STATUS); } else { status = soft_serial_transaction(PUT_MASTER_GET_SLAVE_STATUS); } if( status == TRANSACTION_END ) { s_change_new = slave_buffer_change_count; need_retry = 0; } else { need_retry = 1; } return smatstatus; } #endif // SERIAL_USE_MULTI_TRANSACTION #endif /* USE_SERIAL */
A keyboards/claw44/rev1/split_scomm.h => keyboards/claw44/rev1/split_scomm.h +24 -0
@@ 0,0 1,24 @@ #ifndef SPLIT_COMM_H #define SPLIT_COMM_H #ifndef SERIAL_USE_MULTI_TRANSACTION /* --- USE Simple API (OLD API, compatible with let's split serial.c) --- */ #include "serial.h" #else /* --- USE flexible API (using multi-type transaction function) --- */ // Buffers for master - slave communication #define SERIAL_SLAVE_BUFFER_LENGTH MATRIX_ROWS/2 #define SERIAL_MASTER_BUFFER_LENGTH MATRIX_ROWS/2 extern volatile uint8_t serial_slave_buffer[SERIAL_SLAVE_BUFFER_LENGTH]; extern volatile uint8_t serial_master_buffer[SERIAL_MASTER_BUFFER_LENGTH]; extern uint8_t slave_buffer_change_count; void serial_master_init(void); void serial_slave_init(void); int serial_update_buffers(int master_changed); #endif #endif /* SPLIT_COMM_H */
A keyboards/claw44/rev1/split_util.c => keyboards/claw44/rev1/split_util.c +70 -0
@@ 0,0 1,70 @@ #include <avr/io.h> #include <avr/wdt.h> #include <avr/power.h> #include <avr/interrupt.h> #include <util/delay.h> #include <avr/eeprom.h> #include "split_util.h" #include "matrix.h" #include "keyboard.h" #ifdef USE_MATRIX_I2C # include "i2c.h" #else # include "split_scomm.h" #endif volatile bool isLeftHand = true; static void setup_handedness(void) { #ifdef EE_HANDS isLeftHand = eeprom_read_byte(EECONFIG_HANDEDNESS); #else // I2C_MASTER_RIGHT is deprecated, use MASTER_RIGHT instead, since this works for both serial and i2c #if defined(I2C_MASTER_RIGHT) || defined(MASTER_RIGHT) isLeftHand = !has_usb(); #else isLeftHand = has_usb(); #endif #endif } static void keyboard_master_setup(void) { #ifdef USE_MATRIX_I2C i2c_master_init(); #else serial_master_init(); #endif } static void keyboard_slave_setup(void) { #ifdef USE_MATRIX_I2C i2c_slave_init(SLAVE_I2C_ADDRESS); #else serial_slave_init(); #endif } bool has_usb(void) { USBCON |= (1 << OTGPADE); //enables VBUS pad _delay_us(5); return (USBSTA & (1<<VBUS)); //checks state of VBUS } void split_keyboard_setup(void) { setup_handedness(); if (has_usb()) { keyboard_master_setup(); } else { keyboard_slave_setup(); } sei(); } // this code runs before the usb and keyboard is initialized void matrix_setup(void) { split_keyboard_setup(); }
A keyboards/claw44/rev1/split_util.h => keyboards/claw44/rev1/split_util.h +19 -0
@@ 0,0 1,19 @@ #ifndef SPLIT_KEYBOARD_UTIL_H #define SPLIT_KEYBOARD_UTIL_H #include <stdbool.h> #include "eeconfig.h" #define SLAVE_I2C_ADDRESS 0x32 extern volatile bool isLeftHand; // slave version of matix scan, defined in matrix.c void matrix_slave_scan(void); void split_keyboard_setup(void); bool has_usb(void); void matrix_master_OLED_init (void); #endif
A keyboards/claw44/rules.mk => keyboards/claw44/rules.mk +74 -0
@@ 0,0 1,74 @@ SRC += i2c.c SRC += serial.c SRC += ssd1306.c # if firmware size over limit, try this option # CFLAGS += -flto # MCU name #MCU = at90usb1287 MCU = atmega32u4 # Processor frequency. # This will define a symbol, F_CPU, in all source code files equal to the # processor frequency in Hz. You can then use this symbol in your source code to # calculate timings. Do NOT tack on a 'UL' at the end, this will be done # automatically to create a 32-bit value in your source code. # # This will be an integer division of F_USB below, as it is sourced by # F_USB after it has run through any CPU prescalers. Note that this value # does not *change* the processor frequency - it should merely be updated to # reflect the processor speed set externally so that the code can use accurate # software delays. F_CPU = 16000000 # # LUFA specific # # Target architecture (see library "Board Types" documentation). ARCH = AVR8 # Input clock frequency. # This will define a symbol, F_USB, in all source code files equal to the # input clock frequency (before any prescaling is performed) in Hz. This value may # differ from F_CPU if prescaling is used on the latter, and is required as the # raw input clock is fed directly to the PLL sections of the AVR for high speed # clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL' # at the end, this will be done automatically to create a 32-bit value in your # source code. # # If no clock division is performed on the input clock inside the AVR (via the # CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU. F_USB = $(F_CPU) # Bootloader # This definition is optional, and if your keyboard supports multiple bootloaders of # different sizes, comment this out, and the correct address will be loaded # automatically (+60). See bootloader.mk for all options. BOOTLOADER = caterina # Interrupt driven control endpoint task(+60) OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT # Build Options # change to "no" to disable the options, or define them in the Makefile in # the appropriate keymap folder that will get included automatically # BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration(+1000) MOUSEKEY_ENABLE = no # Mouse keys(+4700) EXTRAKEY_ENABLE = no # Audio control and System control(+450) CONSOLE_ENABLE = no # Console for debug(+400) COMMAND_ENABLE = no # Commands for debug and configuration NKRO_ENABLE = no # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality MIDI_ENABLE = no # MIDI controls AUDIO_ENABLE = no # Audio output on port C6 UNICODE_ENABLE = no # Unicode BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID RGBLIGHT_ENABLE = no # Enable WS2812 RGB underlight. # Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend CUSTOM_MATRIX = yes DEFAULT_FOLDER = claw44/rev1
A keyboards/claw44/serial.c => keyboards/claw44/serial.c +590 -0
@@ 0,0 1,590 @@ /* * WARNING: be careful changing this code, it is very timing dependent * * 2018-10-28 checked * avr-gcc 4.9.2 * avr-gcc 5.4.0 * avr-gcc 7.3.0 */ #ifndef F_CPU #define F_CPU 16000000 #endif #include <avr/io.h> #include <avr/interrupt.h> #include <util/delay.h> #include <stddef.h> #include <stdbool.h> #include "serial.h" //#include <pro_micro.h> #ifdef SOFT_SERIAL_PIN #ifdef __AVR_ATmega32U4__ // if using ATmega32U4 I2C, can not use PD0 and PD1 in soft serial. #ifdef USE_I2C #if SOFT_SERIAL_PIN == D0 || SOFT_SERIAL_PIN == D1 #error Using ATmega32U4 I2C, so can not use PD0, PD1 #endif #endif #if SOFT_SERIAL_PIN >= D0 && SOFT_SERIAL_PIN <= D3 #define SERIAL_PIN_DDR DDRD #define SERIAL_PIN_PORT PORTD #define SERIAL_PIN_INPUT PIND #if SOFT_SERIAL_PIN == D0 #define SERIAL_PIN_MASK _BV(PD0) #define EIMSK_BIT _BV(INT0) #define EICRx_BIT (~(_BV(ISC00) | _BV(ISC01))) #define SERIAL_PIN_INTERRUPT INT0_vect #elif SOFT_SERIAL_PIN == D1 #define SERIAL_PIN_MASK _BV(PD1) #define EIMSK_BIT _BV(INT1) #define EICRx_BIT (~(_BV(ISC10) | _BV(ISC11))) #define SERIAL_PIN_INTERRUPT INT1_vect #elif SOFT_SERIAL_PIN == D2 #define SERIAL_PIN_MASK _BV(PD2) #define EIMSK_BIT _BV(INT2) #define EICRx_BIT (~(_BV(ISC20) | _BV(ISC21))) #define SERIAL_PIN_INTERRUPT INT2_vect #elif SOFT_SERIAL_PIN == D3 #define SERIAL_PIN_MASK _BV(PD3) #define EIMSK_BIT _BV(INT3) #define EICRx_BIT (~(_BV(ISC30) | _BV(ISC31))) #define SERIAL_PIN_INTERRUPT INT3_vect #endif #elif SOFT_SERIAL_PIN == E6 #define SERIAL_PIN_DDR DDRE #define SERIAL_PIN_PORT PORTE #define SERIAL_PIN_INPUT PINE #define SERIAL_PIN_MASK _BV(PE6) #define EIMSK_BIT _BV(INT6) #define EICRx_BIT (~(_BV(ISC60) | _BV(ISC61))) #define SERIAL_PIN_INTERRUPT INT6_vect #else #error invalid SOFT_SERIAL_PIN value #endif #else #error serial.c now support ATmega32U4 only #endif //////////////// for backward compatibility //////////////////////////////// #ifndef SERIAL_USE_MULTI_TRANSACTION /* --- USE Simple API (OLD API, compatible with let's split serial.c) */ #if SERIAL_SLAVE_BUFFER_LENGTH > 0 uint8_t volatile serial_slave_buffer[SERIAL_SLAVE_BUFFER_LENGTH] = {0}; #endif #if SERIAL_MASTER_BUFFER_LENGTH > 0 uint8_t volatile serial_master_buffer[SERIAL_MASTER_BUFFER_LENGTH] = {0}; #endif uint8_t volatile status0 = 0; SSTD_t transactions[] = { { (uint8_t *)&status0, #if SERIAL_MASTER_BUFFER_LENGTH > 0 sizeof(serial_master_buffer), (uint8_t *)serial_master_buffer, #else 0, (uint8_t *)NULL, #endif #if SERIAL_SLAVE_BUFFER_LENGTH > 0 sizeof(serial_slave_buffer), (uint8_t *)serial_slave_buffer #else 0, (uint8_t *)NULL, #endif } }; void serial_master_init(void) { soft_serial_initiator_init(transactions, TID_LIMIT(transactions)); } void serial_slave_init(void) { soft_serial_target_init(transactions, TID_LIMIT(transactions)); } // 0 => no error // 1 => slave did not respond // 2 => checksum error int serial_update_buffers() { int result; result = soft_serial_transaction(); return result; } #endif // end of Simple API (OLD API, compatible with let's split serial.c) //////////////////////////////////////////////////////////////////////////// #define ALWAYS_INLINE __attribute__((always_inline)) #define NO_INLINE __attribute__((noinline)) #define _delay_sub_us(x) __builtin_avr_delay_cycles(x) // parity check #define ODD_PARITY 1 #define EVEN_PARITY 0 #define PARITY EVEN_PARITY #ifdef SERIAL_DELAY // custom setup in config.h // #define TID_SEND_ADJUST 2 // #define SERIAL_DELAY 6 // micro sec // #define READ_WRITE_START_ADJUST 30 // cycles // #define READ_WRITE_WIDTH_ADJUST 8 // cycles #else // ============ Standard setups ============ #ifndef SELECT_SOFT_SERIAL_SPEED #define SELECT_SOFT_SERIAL_SPEED 1 // 0: about 189kbps // 1: about 137kbps (default) // 2: about 75kbps // 3: about 39kbps // 4: about 26kbps // 5: about 20kbps #endif #if __GNUC__ < 6 #define TID_SEND_ADJUST 14 #else #define TID_SEND_ADJUST 2 #endif #if SELECT_SOFT_SERIAL_SPEED == 0 // Very High speed #define SERIAL_DELAY 4 // micro sec #if __GNUC__ < 6 #define READ_WRITE_START_ADJUST 33 // cycles #define READ_WRITE_WIDTH_ADJUST 3 // cycles #else #define READ_WRITE_START_ADJUST 34 // cycles #define READ_WRITE_WIDTH_ADJUST 7 // cycles #endif #elif SELECT_SOFT_SERIAL_SPEED == 1 // High speed #define SERIAL_DELAY 6 // micro sec #if __GNUC__ < 6 #define READ_WRITE_START_ADJUST 30 // cycles #define READ_WRITE_WIDTH_ADJUST 3 // cycles #else #define READ_WRITE_START_ADJUST 33 // cycles #define READ_WRITE_WIDTH_ADJUST 7 // cycles #endif #elif SELECT_SOFT_SERIAL_SPEED == 2 // Middle speed #define SERIAL_DELAY 12 // micro sec #define READ_WRITE_START_ADJUST 30 // cycles #if __GNUC__ < 6 #define READ_WRITE_WIDTH_ADJUST 3 // cycles #else #define READ_WRITE_WIDTH_ADJUST 7 // cycles #endif #elif SELECT_SOFT_SERIAL_SPEED == 3 // Low speed #define SERIAL_DELAY 24 // micro sec #define READ_WRITE_START_ADJUST 30 // cycles #if __GNUC__ < 6 #define READ_WRITE_WIDTH_ADJUST 3 // cycles #else #define READ_WRITE_WIDTH_ADJUST 7 // cycles #endif #elif SELECT_SOFT_SERIAL_SPEED == 4 // Very Low speed #define SERIAL_DELAY 36 // micro sec #define READ_WRITE_START_ADJUST 30 // cycles #if __GNUC__ < 6 #define READ_WRITE_WIDTH_ADJUST 3 // cycles #else #define READ_WRITE_WIDTH_ADJUST 7 // cycles #endif #elif SELECT_SOFT_SERIAL_SPEED == 5 // Ultra Low speed #define SERIAL_DELAY 48 // micro sec #define READ_WRITE_START_ADJUST 30 // cycles #if __GNUC__ < 6 #define READ_WRITE_WIDTH_ADJUST 3 // cycles #else #define READ_WRITE_WIDTH_ADJUST 7 // cycles #endif #else #error invalid SELECT_SOFT_SERIAL_SPEED value #endif /* SELECT_SOFT_SERIAL_SPEED */ #endif /* SERIAL_DELAY */ #define SERIAL_DELAY_HALF1 (SERIAL_DELAY/2) #define SERIAL_DELAY_HALF2 (SERIAL_DELAY - SERIAL_DELAY/2) #define SLAVE_INT_WIDTH_US 1 #ifndef SERIAL_USE_MULTI_TRANSACTION #define SLAVE_INT_RESPONSE_TIME SERIAL_DELAY #else #define SLAVE_INT_ACK_WIDTH_UNIT 2 #define SLAVE_INT_ACK_WIDTH 4 #endif static SSTD_t *Transaction_table = NULL; static uint8_t Transaction_table_size = 0; inline static void serial_delay(void) ALWAYS_INLINE; inline static void serial_delay(void) { _delay_us(SERIAL_DELAY); } inline static void serial_delay_half1(void) ALWAYS_INLINE; inline static void serial_delay_half1(void) { _delay_us(SERIAL_DELAY_HALF1); } inline static void serial_delay_half2(void) ALWAYS_INLINE; inline static void serial_delay_half2(void) { _delay_us(SERIAL_DELAY_HALF2); } inline static void serial_output(void) ALWAYS_INLINE; inline static void serial_output(void) { SERIAL_PIN_DDR |= SERIAL_PIN_MASK; } // make the serial pin an input with pull-up resistor inline static void serial_input_with_pullup(void) ALWAYS_INLINE; inline static void serial_input_with_pullup(void) { SERIAL_PIN_DDR &= ~SERIAL_PIN_MASK; SERIAL_PIN_PORT |= SERIAL_PIN_MASK; } inline static uint8_t serial_read_pin(void) ALWAYS_INLINE; inline static uint8_t serial_read_pin(void) { return !!(SERIAL_PIN_INPUT & SERIAL_PIN_MASK); } inline static void serial_low(void) ALWAYS_INLINE; inline static void serial_low(void) { SERIAL_PIN_PORT &= ~SERIAL_PIN_MASK; } inline static void serial_high(void) ALWAYS_INLINE; inline static void serial_high(void) { SERIAL_PIN_PORT |= SERIAL_PIN_MASK; } void soft_serial_initiator_init(SSTD_t *sstd_table, int sstd_table_size) { Transaction_table = sstd_table; Transaction_table_size = (uint8_t)sstd_table_size; serial_output(); serial_high(); } void soft_serial_target_init(SSTD_t *sstd_table, int sstd_table_size) { Transaction_table = sstd_table; Transaction_table_size = (uint8_t)sstd_table_size; serial_input_with_pullup(); // Enable INT0-INT3,INT6 EIMSK |= EIMSK_BIT; #if SERIAL_PIN_MASK == _BV(PE6) // Trigger on falling edge of INT6 EICRB &= EICRx_BIT; #else // Trigger on falling edge of INT0-INT3 EICRA &= EICRx_BIT; #endif } // Used by the sender to synchronize timing with the reciver. static void sync_recv(void) NO_INLINE; static void sync_recv(void) { for (uint8_t i = 0; i < SERIAL_DELAY*5 && serial_read_pin(); i++ ) { } // This shouldn't hang if the target disconnects because the // serial line will float to high if the target does disconnect. while (!serial_read_pin()); } // Used by the reciver to send a synchronization signal to the sender. static void sync_send(void) NO_INLINE; static void sync_send(void) { serial_low(); serial_delay(); serial_high(); } // Reads a byte from the serial line static uint8_t serial_read_chunk(uint8_t *pterrcount, uint8_t bit) NO_INLINE; static uint8_t serial_read_chunk(uint8_t *pterrcount, uint8_t bit) { uint8_t byte, i, p, pb; _delay_sub_us(READ_WRITE_START_ADJUST); for( i = 0, byte = 0, p = PARITY; i < bit; i++ ) { serial_delay_half1(); // read the middle of pulses if( serial_read_pin() ) { byte = (byte << 1) | 1; p ^= 1; } else { byte = (byte << 1) | 0; p ^= 0; } _delay_sub_us(READ_WRITE_WIDTH_ADJUST); serial_delay_half2(); } /* recive parity bit */ serial_delay_half1(); // read the middle of pulses pb = serial_read_pin(); _delay_sub_us(READ_WRITE_WIDTH_ADJUST); serial_delay_half2(); *pterrcount += (p != pb)? 1 : 0; return byte; } // Sends a byte with MSB ordering void serial_write_chunk(uint8_t data, uint8_t bit) NO_INLINE; void serial_write_chunk(uint8_t data, uint8_t bit) { uint8_t b, p; for( p = PARITY, b = 1<<(bit-1); b ; b >>= 1) { if(data & b) { serial_high(); p ^= 1; } else { serial_low(); p ^= 0; } serial_delay(); } /* send parity bit */ if(p & 1) { serial_high(); } else { serial_low(); } serial_delay(); serial_low(); // sync_send() / senc_recv() need raise edge } static void serial_send_packet(uint8_t *buffer, uint8_t size) NO_INLINE; static void serial_send_packet(uint8_t *buffer, uint8_t size) { for (uint8_t i = 0; i < size; ++i) { uint8_t data; data = buffer[i]; sync_send(); serial_write_chunk(data,8); } } static uint8_t serial_recive_packet(uint8_t *buffer, uint8_t size) NO_INLINE; static uint8_t serial_recive_packet(uint8_t *buffer, uint8_t size) { uint8_t pecount = 0; for (uint8_t i = 0; i < size; ++i) { uint8_t data; sync_recv(); data = serial_read_chunk(&pecount, 8); buffer[i] = data; } return pecount == 0; } inline static void change_sender2reciver(void) { sync_send(); //0 serial_delay_half1(); //1 serial_low(); //2 serial_input_with_pullup(); //2 serial_delay_half1(); //3 } inline static void change_reciver2sender(void) { sync_recv(); //0 serial_delay(); //1 serial_low(); //3 serial_output(); //3 serial_delay_half1(); //4 } static inline uint8_t nibble_bits_count(uint8_t bits) { bits = (bits & 0x5) + (bits >> 1 & 0x5); bits = (bits & 0x3) + (bits >> 2 & 0x3); return bits; } // interrupt handle to be used by the target device ISR(SERIAL_PIN_INTERRUPT) { #ifndef SERIAL_USE_MULTI_TRANSACTION serial_low(); serial_output(); SSTD_t *trans = Transaction_table; #else // recive transaction table index uint8_t tid, bits; uint8_t pecount = 0; sync_recv(); bits = serial_read_chunk(&pecount,7); tid = bits>>3; bits = (bits&7) != nibble_bits_count(tid); if( bits || pecount> 0 || tid > Transaction_table_size ) { return; } serial_delay_half1(); serial_high(); // response step1 low->high serial_output(); _delay_sub_us(SLAVE_INT_ACK_WIDTH_UNIT*SLAVE_INT_ACK_WIDTH); SSTD_t *trans = &Transaction_table[tid]; serial_low(); // response step2 ack high->low #endif // target send phase if( trans->target2initiator_buffer_size > 0 ) serial_send_packet((uint8_t *)trans->target2initiator_buffer, trans->target2initiator_buffer_size); // target switch to input change_sender2reciver(); // target recive phase if( trans->initiator2target_buffer_size > 0 ) { if (serial_recive_packet((uint8_t *)trans->initiator2target_buffer, trans->initiator2target_buffer_size) ) { *trans->status = TRANSACTION_ACCEPTED; } else { *trans->status = TRANSACTION_DATA_ERROR; } } else { *trans->status = TRANSACTION_ACCEPTED; } sync_recv(); //weit initiator output to high } ///////// // start transaction by initiator // // int soft_serial_transaction(int sstd_index) // // Returns: // TRANSACTION_END // TRANSACTION_NO_RESPONSE // TRANSACTION_DATA_ERROR // this code is very time dependent, so we need to disable interrupts #ifndef SERIAL_USE_MULTI_TRANSACTION int soft_serial_transaction(void) { SSTD_t *trans = Transaction_table; #else int soft_serial_transaction(int sstd_index) { if( sstd_index > Transaction_table_size ) return TRANSACTION_TYPE_ERROR; SSTD_t *trans = &Transaction_table[sstd_index]; #endif cli(); // signal to the target that we want to start a transaction serial_output(); serial_low(); _delay_us(SLAVE_INT_WIDTH_US); #ifndef SERIAL_USE_MULTI_TRANSACTION // wait for the target response serial_input_with_pullup(); _delay_us(SLAVE_INT_RESPONSE_TIME); // check if the target is present if (serial_read_pin()) { // target failed to pull the line low, assume not present serial_output(); serial_high(); *trans->status = TRANSACTION_NO_RESPONSE; sei(); return TRANSACTION_NO_RESPONSE; } #else // send transaction table index int tid = (sstd_index<<3) | (7 & nibble_bits_count(sstd_index)); sync_send(); _delay_sub_us(TID_SEND_ADJUST); serial_write_chunk(tid, 7); serial_delay_half1(); // wait for the target response (step1 low->high) serial_input_with_pullup(); while( !serial_read_pin() ) { _delay_sub_us(2); } // check if the target is present (step2 high->low) for( int i = 0; serial_read_pin(); i++ ) { if (i > SLAVE_INT_ACK_WIDTH + 1) { // slave failed to pull the line low, assume not present serial_output(); serial_high(); *trans->status = TRANSACTION_NO_RESPONSE; sei(); return TRANSACTION_NO_RESPONSE; } _delay_sub_us(SLAVE_INT_ACK_WIDTH_UNIT); } #endif // initiator recive phase // if the target is present syncronize with it if( trans->target2initiator_buffer_size > 0 ) { if (!serial_recive_packet((uint8_t *)trans->target2initiator_buffer, trans->target2initiator_buffer_size) ) { serial_output(); serial_high(); *trans->status = TRANSACTION_DATA_ERROR; sei(); return TRANSACTION_DATA_ERROR; } } // initiator switch to output change_reciver2sender(); // initiator send phase if( trans->initiator2target_buffer_size > 0 ) { serial_send_packet((uint8_t *)trans->initiator2target_buffer, trans->initiator2target_buffer_size); } // always, release the line when not in use sync_send(); *trans->status = TRANSACTION_END; sei(); return TRANSACTION_END; } #ifdef SERIAL_USE_MULTI_TRANSACTION int soft_serial_get_and_clean_status(int sstd_index) { SSTD_t *trans = &Transaction_table[sstd_index]; cli(); int retval = *trans->status; *trans->status = 0;; sei(); return retval; } #endif #endif // Helix serial.c history // 2018-1-29 fork from let's split and add PD2, modify sync_recv() (#2308, bceffdefc) // 2018-6-28 bug fix master to slave comm and speed up (#3255, 1038bbef4) // (adjusted with avr-gcc 4.9.2) // 2018-7-13 remove USE_SERIAL_PD2 macro (#3374, f30d6dd78) // (adjusted with avr-gcc 4.9.2) // 2018-8-11 add support multi-type transaction (#3608, feb5e4aae) // (adjusted with avr-gcc 4.9.2) // 2018-10-21 fix serial and RGB animation conflict (#4191, 4665e4fff) // (adjusted with avr-gcc 7.3.0) // 2018-10-28 re-adjust compiler depend value of delay (#4269, 8517f8a66) // (adjusted with avr-gcc 5.4.0, 7.3.0)
A keyboards/claw44/serial.h => keyboards/claw44/serial.h +84 -0
@@ 0,0 1,84 @@ #ifndef SOFT_SERIAL_H #define SOFT_SERIAL_H #include <stdbool.h> // ///////////////////////////////////////////////////////////////// // Need Soft Serial defines in config.h // ///////////////////////////////////////////////////////////////// // ex. // #define SOFT_SERIAL_PIN ?? // ?? = D0,D1,D2,D3,E6 // OPTIONAL: #define SELECT_SOFT_SERIAL_SPEED ? // ? = 1,2,3,4,5 // // 1: about 137kbps (default) // // 2: about 75kbps // // 3: about 39kbps // // 4: about 26kbps // // 5: about 20kbps // // //// USE Simple API (OLD API, compatible with let's split serial.c) // ex. // #define SERIAL_SLAVE_BUFFER_LENGTH MATRIX_ROWS/2 // #define SERIAL_MASTER_BUFFER_LENGTH 1 // // //// USE flexible API (using multi-type transaction function) // #define SERIAL_USE_MULTI_TRANSACTION // // ///////////////////////////////////////////////////////////////// #ifndef SERIAL_USE_MULTI_TRANSACTION /* --- USE Simple API (OLD API, compatible with let's split serial.c) */ #if SERIAL_SLAVE_BUFFER_LENGTH > 0 extern volatile uint8_t serial_slave_buffer[SERIAL_SLAVE_BUFFER_LENGTH]; #endif #if SERIAL_MASTER_BUFFER_LENGTH > 0 extern volatile uint8_t serial_master_buffer[SERIAL_MASTER_BUFFER_LENGTH]; #endif void serial_master_init(void); void serial_slave_init(void); int serial_update_buffers(void); #endif // USE Simple API // Soft Serial Transaction Descriptor typedef struct _SSTD_t { uint8_t *status; uint8_t initiator2target_buffer_size; uint8_t *initiator2target_buffer; uint8_t target2initiator_buffer_size; uint8_t *target2initiator_buffer; } SSTD_t; #define TID_LIMIT( table ) (sizeof(table) / sizeof(SSTD_t)) // initiator is transaction start side void soft_serial_initiator_init(SSTD_t *sstd_table, int sstd_table_size); // target is interrupt accept side void soft_serial_target_init(SSTD_t *sstd_table, int sstd_table_size); // initiator resullt #define TRANSACTION_END 0 #define TRANSACTION_NO_RESPONSE 0x1 #define TRANSACTION_DATA_ERROR 0x2 #define TRANSACTION_TYPE_ERROR 0x4 #ifndef SERIAL_USE_MULTI_TRANSACTION int soft_serial_transaction(void); #else int soft_serial_transaction(int sstd_index); #endif // target status // *SSTD_t.status has // initiator: // TRANSACTION_END // or TRANSACTION_NO_RESPONSE // or TRANSACTION_DATA_ERROR // target: // TRANSACTION_DATA_ERROR // or TRANSACTION_ACCEPTED #define TRANSACTION_ACCEPTED 0x8 #ifdef SERIAL_USE_MULTI_TRANSACTION int soft_serial_get_and_clean_status(int sstd_index); #endif #endif /* SOFT_SERIAL_H */
A keyboards/claw44/ssd1306.c => keyboards/claw44/ssd1306.c +346 -0
@@ 0,0 1,346 @@ #ifdef SSD1306OLED #include "ssd1306.h" #include "i2c.h" #include <string.h> #include "print.h" #ifdef ADAFRUIT_BLE_ENABLE #include "adafruit_ble.h" #endif #ifdef PROTOCOL_LUFA #include "lufa.h" #endif #include "sendchar.h" #include "timer.h" static const unsigned char font[] PROGMEM; // Set this to 1 to help diagnose early startup problems // when testing power-on with ble. Turn it off otherwise, // as the latency of printing most of the debug info messes // with the matrix scan, causing keys to drop. #define DEBUG_TO_SCREEN 0 //static uint16_t last_battery_update; //static uint32_t vbat; //#define BatteryUpdateInterval 10000 /* milliseconds */ // 'last_flush' is declared as uint16_t, // so this must be less than 65535 #define ScreenOffInterval 60000 /* milliseconds */ #if DEBUG_TO_SCREEN static uint8_t displaying; #endif static uint16_t last_flush; static bool force_dirty = true; // Write command sequence. // Returns true on success. static inline bool _send_cmd1(uint8_t cmd) { bool res = false; if (i2c_start_write(SSD1306_ADDRESS)) { xprintf("failed to start write to %d\n", SSD1306_ADDRESS); goto done; } if (i2c_master_write(0x0 /* command byte follows */)) { print("failed to write control byte\n"); goto done; } if (i2c_master_write(cmd)) { xprintf("failed to write command %d\n", cmd); goto done; } res = true; done: i2c_master_stop(); return res; } // Write 2-byte command sequence. // Returns true on success static inline bool _send_cmd2(uint8_t cmd, uint8_t opr) { if (!_send_cmd1(cmd)) { return false; } return _send_cmd1(opr); } // Write 3-byte command sequence. // Returns true on success static inline bool _send_cmd3(uint8_t cmd, uint8_t opr1, uint8_t opr2) { if (!_send_cmd1(cmd)) { return false; } if (!_send_cmd1(opr1)) { return false; } return _send_cmd1(opr2); } #define send_cmd1(c) if (!_send_cmd1(c)) {goto done;} #define send_cmd2(c,o) if (!_send_cmd2(c,o)) {goto done;} #define send_cmd3(c,o1,o2) if (!_send_cmd3(c,o1,o2)) {goto done;} static void clear_display(void) { matrix_clear(&display); // Clear all of the display bits (there can be random noise // in the RAM on startup) send_cmd3(PageAddr, 0, (DisplayHeight / 8) - 1); send_cmd3(ColumnAddr, 0, DisplayWidth - 1); if (i2c_start_write(SSD1306_ADDRESS)) { goto done; } if (i2c_master_write(0x40)) { // Data mode goto done; } for (uint8_t row = 0; row < MatrixRows; ++row) { for (uint8_t col = 0; col < DisplayWidth; ++col) { i2c_master_write(0); } } display.dirty = false; done: i2c_master_stop(); } #if DEBUG_TO_SCREEN #undef sendchar static int8_t capture_sendchar(uint8_t c) { sendchar(c); iota_gfx_write_char(c); if (!displaying) { iota_gfx_flush(); } return 0; } #endif bool iota_gfx_init(bool rotate) { bool success = false; i2c_master_init(); send_cmd1(DisplayOff); send_cmd2(SetDisplayClockDiv, 0x80); send_cmd2(SetMultiPlex, DisplayHeight - 1); send_cmd2(SetDisplayOffset, 0); send_cmd1(SetStartLine | 0x0); send_cmd2(SetChargePump, 0x14 /* Enable */); send_cmd2(SetMemoryMode, 0 /* horizontal addressing */); if(rotate){ // the following Flip the display orientation 180 degrees send_cmd1(SegRemap); send_cmd1(ComScanInc); }else{ // Flips the display orientation 0 degrees send_cmd1(SegRemap | 0x1); send_cmd1(ComScanDec); } send_cmd2(SetComPins, 0x2); send_cmd2(SetContrast, 0x8f); send_cmd2(SetPreCharge, 0xf1); send_cmd2(SetVComDetect, 0x40); send_cmd1(DisplayAllOnResume); send_cmd1(NormalDisplay); send_cmd1(DeActivateScroll); send_cmd1(DisplayOn); send_cmd2(SetContrast, 0); // Dim clear_display(); success = true; iota_gfx_flush(); #if DEBUG_TO_SCREEN print_set_sendchar(capture_sendchar); #endif done: return success; } bool iota_gfx_off(void) { bool success = false; send_cmd1(DisplayOff); success = true; done: return success; } bool iota_gfx_on(void) { bool success = false; send_cmd1(DisplayOn); success = true; done: return success; } void matrix_write_char_inner(struct CharacterMatrix *matrix, uint8_t c) { *matrix->cursor = c; ++matrix->cursor; if (matrix->cursor - &matrix->display[0][0] == sizeof(matrix->display)) { // We went off the end; scroll the display upwards by one line memmove(&matrix->display[0], &matrix->display[1], MatrixCols * (MatrixRows - 1)); matrix->cursor = &matrix->display[MatrixRows - 1][0]; memset(matrix->cursor, ' ', MatrixCols); } } void matrix_write_char(struct CharacterMatrix *matrix, uint8_t c) { matrix->dirty = true; if (c == '\n') { // Clear to end of line from the cursor and then move to the // start of the next line uint8_t cursor_col = (matrix->cursor - &matrix->display[0][0]) % MatrixCols; while (cursor_col++ < MatrixCols) { matrix_write_char_inner(matrix, ' '); } return; } matrix_write_char_inner(matrix, c); } void iota_gfx_write_char(uint8_t c) { matrix_write_char(&display, c); } void matrix_write(struct CharacterMatrix *matrix, const char *data) { const char *end = data + strlen(data); while (data < end) { matrix_write_char(matrix, *data); ++data; } } void matrix_write_ln(struct CharacterMatrix *matrix, const char *data) { char data_ln[strlen(data)+2]; snprintf(data_ln, sizeof(data_ln), "%s\n", data); matrix_write(matrix, data_ln); } void iota_gfx_write(const char *data) { matrix_write(&display, data); } void matrix_write_P(struct CharacterMatrix *matrix, const char *data) { while (true) { uint8_t c = pgm_read_byte(data); if (c == 0) { return; } matrix_write_char(matrix, c); ++data; } } void iota_gfx_write_P(const char *data) { matrix_write_P(&display, data); } void matrix_clear(struct CharacterMatrix *matrix) { memset(matrix->display, ' ', sizeof(matrix->display)); matrix->cursor = &matrix->display[0][0]; matrix->dirty = true; } void iota_gfx_clear_screen(void) { matrix_clear(&display); } void matrix_render(struct CharacterMatrix *matrix) { last_flush = timer_read(); iota_gfx_on(); #if DEBUG_TO_SCREEN ++displaying; #endif // Move to the home position send_cmd3(PageAddr, 0, MatrixRows - 1); send_cmd3(ColumnAddr, 0, (MatrixCols * FontWidth) - 1); if (i2c_start_write(SSD1306_ADDRESS)) { goto done; } if (i2c_master_write(0x40)) { // Data mode goto done; } for (uint8_t row = 0; row < MatrixRows; ++row) { for (uint8_t col = 0; col < MatrixCols; ++col) { const uint8_t *glyph = font + (matrix->display[row][col] * FontWidth); for (uint8_t glyphCol = 0; glyphCol < FontWidth; ++glyphCol) { uint8_t colBits = pgm_read_byte(glyph + glyphCol); i2c_master_write(colBits); } // 1 column of space between chars (it's not included in the glyph) //i2c_master_write(0); } } matrix->dirty = false; done: i2c_master_stop(); #if DEBUG_TO_SCREEN --displaying; #endif } void iota_gfx_flush(void) { matrix_render(&display); } __attribute__ ((weak)) void iota_gfx_task_user(void) { } void iota_gfx_task(void) { iota_gfx_task_user(); if (display.dirty|| force_dirty) { iota_gfx_flush(); force_dirty = false; } /* if (timer_elapsed(last_flush) > ScreenOffInterval) { iota_gfx_off(); } */ } bool process_record_gfx(uint16_t keycode, keyrecord_t *record) { force_dirty = true; return true; } #endif
A keyboards/claw44/ssd1306.h => keyboards/claw44/ssd1306.h +91 -0
@@ 0,0 1,91 @@ #pragma once #include <stdbool.h> #include <stdio.h> #include "pincontrol.h" #include "action.h" enum ssd1306_cmds { DisplayOff = 0xAE, DisplayOn = 0xAF, SetContrast = 0x81, DisplayAllOnResume = 0xA4, DisplayAllOn = 0xA5, NormalDisplay = 0xA6, InvertDisplay = 0xA7, SetDisplayOffset = 0xD3, SetComPins = 0xda, SetVComDetect = 0xdb, SetDisplayClockDiv = 0xD5, SetPreCharge = 0xd9, SetMultiPlex = 0xa8, SetLowColumn = 0x00, SetHighColumn = 0x10, SetStartLine = 0x40, SetMemoryMode = 0x20, ColumnAddr = 0x21, PageAddr = 0x22, ComScanInc = 0xc0, ComScanDec = 0xc8, SegRemap = 0xa0, SetChargePump = 0x8d, ExternalVcc = 0x01, SwitchCapVcc = 0x02, ActivateScroll = 0x2f, DeActivateScroll = 0x2e, SetVerticalScrollArea = 0xa3, RightHorizontalScroll = 0x26, LeftHorizontalScroll = 0x27, VerticalAndRightHorizontalScroll = 0x29, VerticalAndLeftHorizontalScroll = 0x2a, }; // Controls the SSD1306 128x32 OLED display via i2c #ifndef SSD1306_ADDRESS #define SSD1306_ADDRESS 0x3C #endif #define DisplayHeight 32 #define DisplayWidth 128 #define FontHeight 8 #define FontWidth 6 #define MatrixRows (DisplayHeight / FontHeight) #define MatrixCols (DisplayWidth / FontWidth) struct CharacterMatrix { uint8_t display[MatrixRows][MatrixCols]; uint8_t *cursor; bool dirty; }; struct CharacterMatrix display; bool iota_gfx_init(bool rotate); void iota_gfx_task(void); bool iota_gfx_off(void); bool iota_gfx_on(void); void iota_gfx_flush(void); void iota_gfx_write_char(uint8_t c); void iota_gfx_write(const char *data); void iota_gfx_write_P(const char *data); void iota_gfx_clear_screen(void); void iota_gfx_task_user(void); void matrix_clear(struct CharacterMatrix *matrix); void matrix_write_char_inner(struct CharacterMatrix *matrix, uint8_t c); void matrix_write_char(struct CharacterMatrix *matrix, uint8_t c); void matrix_write(struct CharacterMatrix *matrix, const char *data); void matrix_write_ln(struct CharacterMatrix *matrix, const char *data); void matrix_write_P(struct CharacterMatrix *matrix, const char *data); void matrix_render(struct CharacterMatrix *matrix); bool process_record_gfx(uint16_t keycode, keyrecord_t *record); \ No newline at end of file