From dfb0a512a0f9d22c1bd7cadc519422a09cf378de Mon Sep 17 00:00:00 2001 From: jpetermans Date: Thu, 6 Apr 2017 13:43:22 -0700 Subject: [PATCH 001/238] Added personal configs and keymap to infinity60/keymaps --- keyboards/infinity60/config.h | 2 +- .../infinity60/keymaps/jpetermans/Makefile | 6 + .../infinity60/keymaps/jpetermans/config.h | 11 ++ .../infinity60/keymaps/jpetermans/keymap.c | 145 ++++++++++++++++++ 4 files changed, 163 insertions(+), 1 deletion(-) create mode 100644 keyboards/infinity60/keymaps/jpetermans/Makefile create mode 100644 keyboards/infinity60/keymaps/jpetermans/config.h create mode 100644 keyboards/infinity60/keymaps/jpetermans/keymap.c diff --git a/keyboards/infinity60/config.h b/keyboards/infinity60/config.h index f8346fe16..83930901c 100644 --- a/keyboards/infinity60/config.h +++ b/keyboards/infinity60/config.h @@ -54,7 +54,7 @@ along with this program. If not, see . //#define INFINITY_PROTOTYPE /* Keymap for Infinity 1.1a (first revision with LED support) */ -//#define INFINITY_LED +#define INFINITY_LED /* * Feature disable options diff --git a/keyboards/infinity60/keymaps/jpetermans/Makefile b/keyboards/infinity60/keymaps/jpetermans/Makefile new file mode 100644 index 000000000..225e4cad4 --- /dev/null +++ b/keyboards/infinity60/keymaps/jpetermans/Makefile @@ -0,0 +1,6 @@ +#BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality +#BOOTMAGIC_ENABLE = yes + +ifndef QUANTUM_DIR + include ../../../../Makefile +endif diff --git a/keyboards/infinity60/keymaps/jpetermans/config.h b/keyboards/infinity60/keymaps/jpetermans/config.h new file mode 100644 index 000000000..72a2ed081 --- /dev/null +++ b/keyboards/infinity60/keymaps/jpetermans/config.h @@ -0,0 +1,11 @@ +#ifndef CONFIG_USER_H +#define CONFIG_USER_H + + +#include "../../config.h" + +//overrides +#undef TAPPING_TOGGLE +#define TAPPING_TOGGLE 2 + +#endif diff --git a/keyboards/infinity60/keymaps/jpetermans/keymap.c b/keyboards/infinity60/keymaps/jpetermans/keymap.c new file mode 100644 index 000000000..be0bee544 --- /dev/null +++ b/keyboards/infinity60/keymaps/jpetermans/keymap.c @@ -0,0 +1,145 @@ +#include "infinity60.h" +#include "backlight.h" + +//Helpful Defines +#define _______ KC_TRNS + +//Define Layer Names +#define _BASE 0 +#define _NUMPAD 1 +#define _FNAV 2 +#define _MEDIA 3 +#define _TILDE 4 + +const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + /* Layer 0: Default Layer + * ,-----------------------------------------------------------. + * |Esc| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =| Backs| + * |-----------------------------------------------------------| + * |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \| + * |-----------------------------------------------------------| + * |CapsLo| A| S| D| F| G| H| J| K| L| ;| '|Enter | + * |-----------------------------------------------------------| + * |Shif| | Z| X| C| V| B| N| M| ,| .| /|Shift | + * |-----------------------------------------------------------| + * |Ctrl|Gui |Alt | Space |Alt |Gui | FN | Ctrl | + * `-----------------------------------------------------------' + */ + /* default */ + [_BASE] = KEYMAP( \ + KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS,KC_EQL, KC_BSLS,KC_NO,\ + KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC,KC_RBRC,KC_BSPC, \ + TT(_FNAV), KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN,KC_QUOT,KC_ENT, \ + F(1), KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM,KC_DOT, KC_SLSH,KC_RSFT,KC_NO, \ + KC_LCTL, KC_LGUI,KC_LALT, KC_SPC, KC_RALT,TG(_NUMPAD),MO(_MEDIA), KC_RCTL \ + ), + + /* F-, arrow, and media keys */ + [_FNAV] = KEYMAP( \ + KC_GRV, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, _______,KC_NO,\ + KC_CAPS,_______,_______,_______,_______,_______,_______,KC_PGUP,KC_UP,KC_PGDN,KC_PSCR,_______,_______,KC_DEL, \ + _______,M(0),KC_BTN2,_______,_______,_______,KC_HOME,KC_LEFT,KC_DOWN,KC_RGHT,KC_INS,_______,_______, \ + _______,KC_APP,KC_BTN1,KC_CALC,_______,_______,KC_END,_______,_______,_______,_______,_______,KC_NO, \ + _______,_______,_______, _______, F(0),KC_NLCK,_______,_______ \ + ), + + /* numpad */ + [_NUMPAD] = KEYMAP( \ + _______,_______,_______,_______,_______,_______,_______, KC_P7, KC_P8, KC_P9, KC_PSLS, _______,_______,_______,KC_NO,\ + _______,_______,_______,_______,_______,_______,_______, KC_P4, KC_P5, KC_P6, KC_PAST, _______,_______,_______, \ + MO(_FNAV),_______,_______,_______,_______,_______,_______, KC_P1, KC_P2, KC_P3, KC_PMNS, _______,_______, \ + _______,_______,_______,_______,_______,_______,_______, KC_P0,KC_COMM,KC_PDOT,KC_PPLS, _______,KC_NO, \ + _______,_______,_______, MO(_BASE), _______,_______,_______,_______ \ + ), + + /* media */ + [_MEDIA] = KEYMAP( \ + _______,_______,_______,_______,_______,_______,_______, _______, _______, _______,KC_MUTE, KC_VOLD, KC_VOLU,_______,KC_NO,\ + _______,_______,_______,_______,_______,_______,_______, _______, _______, _______,_______, _______,_______,_______,\ + _______,_______,_______,_______,_______,_______,_______, _______, _______, _______,_______, _______,_______, \ + _______,_______,F(2),M(1),_______,_______,_______, _______, KC_MPRV, KC_MNXT,KC_MSTP, _______,KC_NO, \ + _______,_______,_______, KC_MPLY, _______,_______, _______,_______ \ + ), + /* ~ */ + [_TILDE] = KEYMAP( \ + KC_GRV,_______,_______,_______,_______,_______,_______, _______, _______, _______,_______, _______,_______,_______,KC_NO,\ + _______,_______,_______,_______,_______,_______,_______, _______, _______, _______,_______, _______,_______,_______,\ + _______,_______,_______,_______,_______,_______,_______, _______, _______, _______,_______, _______,_______, \ + _______,_______,_______,_______,_______,_______,_______, _______, _______, _______,_______, _______,KC_NO, \ + _______,_______,_______, _______, _______,_______, _______,_______ \ + ), + /* template */ + [5] = KEYMAP( \ + _______,_______,_______,_______,_______,_______,_______, _______, _______, _______,_______, _______,_______,_______,KC_NO,\ + _______,_______,_______,_______,_______,_______,_______, _______, _______, _______,_______, _______,_______,_______,\ + _______,_______,_______,_______,_______,_______,_______, _______, _______, _______,_______, _______,_______, \ + _______,_______,_______,_______,_______,_______,_______, _______, _______, _______,_______, _______,KC_NO, \ + _______,_______,_______, _______, _______,_______, _______,_______ \ + ), +}; + +//id for user defined functions and macros +enum function_id { + NONE, +}; + +enum macro_id { + ACTION_LEDS_ALL, +}; + +const uint16_t fn_actions[] = { + [0] = ACTION_KEY(LALT(LCTL(KC_DEL))), + [1] = ACTION_LAYER_MODS(_TILDE, MOD_LSFT), + [2] = ACTION_BACKLIGHT_TOGGLE() +/* [1] = ACTION_FUNCTION(ACTION_LEDS_GAME), + + [4] = ACTION_USAGE_CONSUMER(0x1B4), + [5] = ACTION_USAGE_CONSUMER(0x196), + [6] = ACTION_USAGE_CONSUMER(0x1A6), + [7] = ACTION_USAGE_CONSUMER(0x1A0) +*/ +}; + +/* custom action function */ +/* +void action_function(keyrecord_t *record, uint8_t id, uint8_t opt) { + (void)opt; + switch(id) { + case 1: + if(record->event.pressed) { + // signal the LED controller thread + chMBPost(&led_mailbox, LED_MSG_GAME_TOGGLE, TIME_IMMEDIATE); + } + break; + } + +} +*/ + +const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) +{ + switch(id) { + case 0: + if (record->event.pressed) { + return MACRO( I(5), END); + } + break; + case 1: + if (record->event.pressed) { + } + break; + } + return MACRO_NONE; +}; + + +// Runs just one time when the keyboard initializes. +void matrix_init_user(void) { + +}; + +// Runs constantly in the background, in a loop. +void matrix_scan_user(void) { + +}; + From b73c935d3652df58fc573c83986424ab47a2ba14 Mon Sep 17 00:00:00 2001 From: jpetermans Date: Thu, 6 Apr 2017 13:45:15 -0700 Subject: [PATCH 002/238] Added tmk whitefox led files --- keyboards/infinity60/led.c | 28 +- keyboards/infinity60/led_controller.c | 354 ++++++++++++++++++++++++++ keyboards/infinity60/led_controller.h | 93 +++++++ 3 files changed, 474 insertions(+), 1 deletion(-) create mode 100644 keyboards/infinity60/led_controller.c create mode 100644 keyboards/infinity60/led_controller.h diff --git a/keyboards/infinity60/led.c b/keyboards/infinity60/led.c index aed66c7c0..e17a5dd0d 100644 --- a/keyboards/infinity60/led.c +++ b/keyboards/infinity60/led.c @@ -1,5 +1,5 @@ /* -Copyright 2012 Jun Wako +Copyright 2015 Jun Wako 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 @@ -19,6 +19,32 @@ along with this program. If not, see . #include "led.h" +#include "led_controller.h" +/* WARNING! This function needs to be callable from + * both regular threads and ISRs, unlocked (during resume-from-sleep). + * In particular, I2C functions (interrupt-driven) should NOT be called from here. + */ void led_set(uint8_t usb_led) { +/* + // PTA5: LED (1:on/0:off) + GPIOA->PDDR |= (1<<1); + PORTA->PCR[5] |= PORTx_PCRn_DSE | PORTx_PCRn_MUX(1); + if (usb_led & (1<PSOR |= (1<<5); + } else { + GPIOA->PCOR |= (1<<5); + } + */ + if (usb_led & (1< + +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 . +*/ + +/* + * LED controller code + * WF uses IS31FL3731C matrix LED driver from ISSI + * datasheet: http://www.issi.com/WW/pdf/31FL3731C.pdf + */ + +#include "ch.h" +#include "hal.h" + +#include "led_controller.h" + +#include "hook.h" +#include "suspend.h" + +#include "usb_main.h" + +/* WF LED MAP + - digits mean "row" and "col", i.e. 45 means C4-5 in the IS31 datasheet, matrix A + + 11 12 13 14 15 16 17 18 21 22 23 24 25 26 27 28 + 31 32 33 34 35 36 37 38 41 42 43 44 45 46 47 + 48 51 52 53 54 55 56 57 58 61 62 63 64 65 66 + 67 68 71 72 73 74 75 76 77 78 81 82 83 84 85 + 86 87 88 91 92 93 (94) 95 96 97 +*/ + +/* + each page has 0xB4 bytes + 0 - 0x11: LED control (on/off): + order: CA1, CB1, CA2, CB2, .... (CA - matrix A, CB - matrix B) + CAn controls Cn-8 .. Cn-1 (LSbit) + 0x12 - 0x23: blink control (like "LED control") + 0x24 - 0xB3: PWM control: byte per LED, 0xFF max on + order same as above (CA 1st row (8bytes), CB 1st row (8bytes), ...) +*/ + +/* Which LED should be used for CAPS LOCK indicator + * The usual Caps Lock position is C4-8, so the address is + * 0x24 + (4-1)*0x10 + (8-1) = 0x5B */ +#if !defined(CAPS_LOCK_LED_ADDRESS) +#define CAPS_LOCK_LED_ADDRESS 0x5B +#endif + +/* Which LED should breathe during sleep */ +#if !defined(BREATHE_LED_ADDRESS) +#define BREATHE_LED_ADDRESS CAPS_LOCK_LED_ADDRESS +#endif + +/* ================= + * ChibiOS I2C setup + * ================= */ +static const I2CConfig i2ccfg = { + 400000 // clock speed (Hz); 400kHz max for IS31 +}; + +/* ============== + * variables + * ============== */ +// internal communication buffers +uint8_t tx[2] __attribute__((aligned(2))); +uint8_t rx[1] __attribute__((aligned(2))); + +// buffer for sending the whole page at once (used also as a temp buffer) +uint8_t full_page[0xB4+1] = {0}; + +// LED mask (which LEDs are present, selected by bits) +const uint8_t is31_wf_leds_mask[0x12] = { + 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, + 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x7F, 0x00 +}; + +/* ============================ + * communication functions + * ============================ */ +msg_t is31_select_page(uint8_t page) { + tx[0] = IS31_COMMANDREGISTER; + tx[1] = page; + return i2cMasterTransmitTimeout(&I2CD1, IS31_ADDR_DEFAULT, tx, 2, NULL, 0, US2ST(IS31_TIMEOUT)); +} + +msg_t is31_write_data(uint8_t page, uint8_t *buffer, uint8_t size) { + is31_select_page(page); + return i2cMasterTransmitTimeout(&I2CD1, IS31_ADDR_DEFAULT, buffer, size, NULL, 0, US2ST(IS31_TIMEOUT)); +} + +msg_t is31_write_register(uint8_t page, uint8_t reg, uint8_t data) { + is31_select_page(page); + tx[0] = reg; + tx[1] = data; + return i2cMasterTransmitTimeout(&I2CD1, IS31_ADDR_DEFAULT, tx, 2, NULL, 0, US2ST(IS31_TIMEOUT)); +} + +msg_t is31_read_register(uint8_t b, uint8_t reg, uint8_t *result) { + is31_select_page(b); + + tx[0] = reg; + return i2cMasterTransmitTimeout(&I2CD1, IS31_ADDR_DEFAULT, tx, 1, result, 1, US2ST(IS31_TIMEOUT)); +} + +/* ======================== + * initialise the IS31 chip + * ======================== */ +void is31_init(void) { + // just to be sure that it's all zeroes + __builtin_memset(full_page,0,0xB4+1); + // zero function page, all registers (assuming full_page is all zeroes) + is31_write_data(IS31_FUNCTIONREG, full_page, 0xD + 1); + // disable hardware shutdown + palSetPadMode(GPIOB, 16, PAL_MODE_OUTPUT_PUSHPULL); + palSetPad(GPIOB, 16); + chThdSleepMilliseconds(10); + // software shutdown + is31_write_register(IS31_FUNCTIONREG, IS31_REG_SHUTDOWN, 0); + chThdSleepMilliseconds(10); + // zero function page, all registers + is31_write_data(IS31_FUNCTIONREG, full_page, 0xD + 1); + chThdSleepMilliseconds(10); + // software shutdown disable (i.e. turn stuff on) + is31_write_register(IS31_FUNCTIONREG, IS31_REG_SHUTDOWN, IS31_REG_SHUTDOWN_ON); + chThdSleepMilliseconds(10); + // zero all LED registers on all 8 pages + uint8_t i; + for(i=0; i<8; i++) { + is31_write_data(i, full_page, 0xB4 + 1); + chThdSleepMilliseconds(1); + } +} + +/* ================== + * LED control thread + * ================== */ +#define LED_MAILBOX_NUM_MSGS 5 +static msg_t led_mailbox_queue[LED_MAILBOX_NUM_MSGS]; +mailbox_t led_mailbox; +static THD_WORKING_AREA(waLEDthread, 256); +static THD_FUNCTION(LEDthread, arg) { + (void)arg; + chRegSetThreadName("LEDthread"); + + uint8_t temp; + uint8_t save_page, save_breath1, save_breath2; + msg_t msg, retval; + + while(true) { + // wait for a message (asynchronous) + // (messages are queued (up to LED_MAILBOX_NUM_MSGS) if they can't + // be processed right away) + chMBFetch(&led_mailbox, &msg, TIME_INFINITE); + + // process 'msg' here + switch(msg) { + case LED_MSG_CAPS_ON: + // turn caps on on pages 1 and 2 + is31_write_register(0, CAPS_LOCK_LED_ADDRESS, 0xFF); + is31_write_register(1, CAPS_LOCK_LED_ADDRESS, 0xFF); + is31_write_register(2, CAPS_LOCK_LED_ADDRESS, 0xFF); + break; + case LED_MSG_CAPS_OFF: + // turn caps off on pages 1 and 2 + is31_write_register(0, CAPS_LOCK_LED_ADDRESS, 0); + is31_write_register(1, CAPS_LOCK_LED_ADDRESS, 0); + is31_write_register(2, CAPS_LOCK_LED_ADDRESS, 0); + break; + case LED_MSG_SLEEP_LED_ON: + // save current settings + is31_read_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, &save_page); + is31_read_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL1, &save_breath1); + is31_read_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL2, &save_breath2); + // use pages 7 and 8 for (hardware) breathing (assuming they're empty) + is31_write_register(6, BREATHE_LED_ADDRESS, 0xFF); + is31_write_register(7, BREATHE_LED_ADDRESS, 0x00); + is31_write_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL1, (6<<4)|6); + is31_write_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL2, IS31_REG_BREATHCTRL2_ENABLE|3); + retval = MSG_TIMEOUT; + temp = 6; + while(retval == MSG_TIMEOUT) { + // switch to the other page + is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, temp); + temp = (temp == 6 ? 7 : 6); + // the times should be sufficiently long for IS31 to finish switching pages + retval = chMBFetch(&led_mailbox, &msg, MS2ST(temp == 6 ? 4000 : 6000)); + } + // received a message (should be a wakeup), so restore previous state + chThdSleepMilliseconds(3000); // need to wait until the page change finishes + // note: any other messages are queued + is31_write_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL1, save_breath1); + is31_write_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL2, save_breath2); + is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, save_page); + break; + case LED_MSG_SLEEP_LED_OFF: + // should not get here; wakeup should be received in the branch above + break; + case LED_MSG_ALL_TOGGLE: + // read current page into 'temp' + is31_read_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, &temp); + chThdSleepMilliseconds(1); + // switch to 'the other' page + if(temp==2) { + is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, 0); + } else { + is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, 2); + } + break; + case LED_MSG_GAME_TOGGLE: + // read current page into 'temp' + is31_read_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, &temp); + chThdSleepMilliseconds(1); + // switch to 'the other' page + if(temp==1) { + is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, 0); + } else { + is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, 1); + } + break; + } + } +} + +/* LED game mode */ +const uint8_t led_game[83] = { + 0x24, + 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x34, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x44, + 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x54, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x64, + 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x74, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x84, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x94, + 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0xA4, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, +}; + +/* ALL LEDs */ +const uint8_t led_all[83] = { + 0x24, + 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, + 0x34, + 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, + 0x44, + 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, + 0x54, + 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, + 0x64, + 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, + 0x74, + 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, + 0x84, + 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, + 0x94, + 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, + 0xA4, + 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, +}; + +/* ============= + * hook into TMK + * ============= */ +void hook_early_init(void) { + uint8_t i; + + /* initialise I2C */ + /* I2C pins */ + palSetPadMode(GPIOB, 0, PAL_MODE_ALTERNATIVE_2); // PTB0/I2C0/SCL + palSetPadMode(GPIOB, 1, PAL_MODE_ALTERNATIVE_2); // PTB1/I2C0/SDA + /* start I2C */ + i2cStart(&I2CD1, &i2ccfg); + // try high drive (from kiibohd) + I2CD1.i2c->C2 |= I2Cx_C2_HDRS; + // try glitch fixing (from kiibohd) + I2CD1.i2c->FLT = 4; + + chThdSleepMilliseconds(10); + + /* initialise IS31 chip */ + is31_init(); + + /* enable WF LEDs on all pages */ + full_page[0] = 0; + __builtin_memcpy(full_page+1, is31_wf_leds_mask, 0x12); + for(i=0; i<8; i++) { + is31_write_data(i, full_page, 1+0x12); + } + + /* enable breathing when the displayed page changes */ + // Fade-in Fade-out, time = 26ms * 2^N, N=3 + is31_write_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL1, (3<<4)|3); + is31_write_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL2, IS31_REG_BREATHCTRL2_ENABLE|3); + + /* Write pages */ + for(i=0; i<9; i++) { + is31_write_data(1,(uint8_t *)(led_game+(9*i)),9); + chThdSleepMilliseconds(5); + is31_write_data(2,(uint8_t *)(led_all+(9*i)),9); + chThdSleepMilliseconds(5); + } + + // clean up the capslock LED + is31_write_register(1, CAPS_LOCK_LED_ADDRESS, 0); + is31_write_register(2, CAPS_LOCK_LED_ADDRESS, 0); + + /* more time consuming LED processing should be offloaded into + * a thread, with asynchronous messaging. */ + chMBObjectInit(&led_mailbox, led_mailbox_queue, LED_MAILBOX_NUM_MSGS); + chThdCreateStatic(waLEDthread, sizeof(waLEDthread), LOWPRIO, LEDthread, NULL); +} + +void hook_usb_suspend_entry(void) { +#ifdef SLEEP_LED_ENABLE + chSysLockFromISR(); + chMBPostI(&led_mailbox, LED_MSG_SLEEP_LED_ON); + chSysUnlockFromISR(); +#endif /* SLEEP_LED_ENABLE */ +} + +void hook_usb_suspend_loop(void) { + chThdSleepMilliseconds(100); + /* Remote wakeup */ + if((USB_DRIVER.status & 2) && suspend_wakeup_condition()) { + send_remote_wakeup(&USB_DRIVER); + } +} + +void hook_usb_wakeup(void) { +#ifdef SLEEP_LED_ENABLE + chSysLockFromISR(); + chMBPostI(&led_mailbox, LED_MSG_SLEEP_LED_OFF); + chSysUnlockFromISR(); +#endif /* SLEEP_LED_ENABLE */ +} diff --git a/keyboards/infinity60/led_controller.h b/keyboards/infinity60/led_controller.h new file mode 100644 index 000000000..dcf346e04 --- /dev/null +++ b/keyboards/infinity60/led_controller.h @@ -0,0 +1,93 @@ +/* +Copyright 2016 flabbergast + +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 . +*/ + +#ifndef _LED_CONTROLLER_H_ +#define _LED_CONTROLLER_H_ + +/* ========================= + * communication functions + * ========================= */ + +msg_t is31_write_data(uint8_t page, uint8_t *buffer, uint8_t size); +msg_t is31_write_register(uint8_t page, uint8_t reg, uint8_t data); +msg_t is31_read_register(uint8_t page, uint8_t reg, uint8_t *result); + +/* ============================= + * IS31 chip related definitions + * ============================= */ + +#define IS31_ADDR_DEFAULT 0x74 + +#define IS31_REG_CONFIG 0x00 +// bits in reg +#define IS31_REG_CONFIG_PICTUREMODE 0x00 +#define IS31_REG_CONFIG_AUTOPLAYMODE 0x08 +#define IS31_REG_CONFIG_AUDIOPLAYMODE 0x18 +// D2:D0 bits are starting frame for autoplay mode + +#define IS31_REG_PICTDISP 0x01 // D2:D0 frame select for picture mode + +#define IS31_REG_AUTOPLAYCTRL1 0x02 +// D6:D4 number of loops (000=infty) +// D2:D0 number of frames to be used + +#define IS31_REG_AUTOPLAYCTRL2 0x03 // D5:D0 delay time (*11ms) + +#define IS31_REG_DISPLAYOPT 0x05 +#define IS31_REG_DISPLAYOPT_INTENSITY_SAME 0x20 // same intensity for all frames +#define IS31_REG_DISPLAYOPT_BLINK_ENABLE 0x8 +// D2:D0 bits blink period time (*0.27s) + +#define IS31_REG_AUDIOSYNC 0x06 +#define IS31_REG_AUDIOSYNC_ENABLE 0x1 + +#define IS31_REG_FRAMESTATE 0x07 + +#define IS31_REG_BREATHCTRL1 0x08 +// D6:D4 fade out time (26ms*2^i) +// D2:D0 fade in time (26ms*2^i) + +#define IS31_REG_BREATHCTRL2 0x09 +#define IS31_REG_BREATHCTRL2_ENABLE 0x10 +// D2:D0 extinguish time (3.5ms*2^i) + +#define IS31_REG_SHUTDOWN 0x0A +#define IS31_REG_SHUTDOWN_ON 0x1 + +#define IS31_REG_AGCCTRL 0x0B +#define IS31_REG_ADCRATE 0x0C + +#define IS31_COMMANDREGISTER 0xFD +#define IS31_FUNCTIONREG 0x0B // helpfully called 'page nine' + +#define IS31_TIMEOUT 10000 // needs to be long enough to write a whole page + +/* ============================== + * LED Thread related definitions + * ============================== */ + +extern mailbox_t led_mailbox; + +// constants for signaling the LED controller thread +#define LED_MSG_CAPS_ON 1 +#define LED_MSG_CAPS_OFF 2 +#define LED_MSG_SLEEP_LED_ON 3 +#define LED_MSG_SLEEP_LED_OFF 4 +#define LED_MSG_ALL_TOGGLE 5 +#define LED_MSG_GAME_TOGGLE 6 + +#endif /* _LED_CONTROLLER_H_ */ From da4c2d2e3e4cd566ccf0c5a468f1a544c4b2be55 Mon Sep 17 00:00:00 2001 From: jpetermans Date: Thu, 6 Apr 2017 13:46:54 -0700 Subject: [PATCH 003/238] Adjust led_controller.c matrix sttings and init function --- keyboards/infinity60/led_controller.c | 123 ++++++++++++++------------ 1 file changed, 65 insertions(+), 58 deletions(-) diff --git a/keyboards/infinity60/led_controller.c b/keyboards/infinity60/led_controller.c index bc501d9f2..c5303a3e7 100644 --- a/keyboards/infinity60/led_controller.c +++ b/keyboards/infinity60/led_controller.c @@ -23,22 +23,24 @@ along with this program. If not, see . #include "ch.h" #include "hal.h" +#include "print.h" #include "led_controller.h" -#include "hook.h" #include "suspend.h" #include "usb_main.h" -/* WF LED MAP +/* Infinity60 LED MAP - digits mean "row" and "col", i.e. 45 means C4-5 in the IS31 datasheet, matrix A - 11 12 13 14 15 16 17 18 21 22 23 24 25 26 27 28 - 31 32 33 34 35 36 37 38 41 42 43 44 45 46 47 - 48 51 52 53 54 55 56 57 58 61 62 63 64 65 66 - 67 68 71 72 73 74 75 76 77 78 81 82 83 84 85 - 86 87 88 91 92 93 (94) 95 96 97 + 11 12 13 14 15 16 17 18 21 22 23 24 25 26 27* + 28 31 32 33 34 35 36 37 38 41 42 43 44 45 + 46 47 48 51 52 53 54 55 56 57 58 61 62 + 63 64 65 66 67 68 71 72 73 74 75 76 77* + 78 81 82 83 84 85 86 87 + +*Unused in Alphabet Layout */ /* @@ -52,10 +54,10 @@ along with this program. If not, see . */ /* Which LED should be used for CAPS LOCK indicator - * The usual Caps Lock position is C4-8, so the address is - * 0x24 + (4-1)*0x10 + (8-1) = 0x5B */ + * The usual Caps Lock position is C4-6, so the address is + * 0x24 + (4-1)*0x10 + (8-1) = 0x59 */ #if !defined(CAPS_LOCK_LED_ADDRESS) -#define CAPS_LOCK_LED_ADDRESS 0x5B +#define CAPS_LOCK_LED_ADDRESS 0x59 #endif /* Which LED should breathe during sleep */ @@ -81,9 +83,12 @@ uint8_t rx[1] __attribute__((aligned(2))); uint8_t full_page[0xB4+1] = {0}; // LED mask (which LEDs are present, selected by bits) -const uint8_t is31_wf_leds_mask[0x12] = { +// See page comment above, control alternates CA matrix/CB matrix +// IC60 pcb uses only CA matrix. +// Each byte is a control pin for 8 leds 8-1 +const uint8_t is31_ic60_leds_mask[0x12] = { 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, - 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x7F, 0x00 + 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x7F, 0x00, 0x00, 0x00 }; /* ============================ @@ -233,56 +238,55 @@ static THD_FUNCTION(LEDthread, arg) { } } +//These relate to the LED map above, row and column +//0x24 = first byte (CA1) of PWM page, 0x34 is 17th byte (CA2) /* LED game mode */ -const uint8_t led_game[83] = { +const uint8_t led_game[72] = { 0x24, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, - 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x64, - 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, - 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, - 0xA4, - 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; /* ALL LEDs */ -const uint8_t led_all[83] = { +const uint8_t led_all[72] = { 0x24, - 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x34, - 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, - 0x44, - 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0x44, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x54, - 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x64, - 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x74, - 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x84, - 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x94, - 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, - 0xA4, - 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }; /* ============= * hook into TMK * ============= */ -void hook_early_init(void) { +void led_controller_init(void) { uint8_t i; + xprintf("led_controller_init"); /* initialise I2C */ /* I2C pins */ palSetPadMode(GPIOB, 0, PAL_MODE_ALTERNATIVE_2); // PTB0/I2C0/SCL @@ -299,9 +303,9 @@ void hook_early_init(void) { /* initialise IS31 chip */ is31_init(); - /* enable WF LEDs on all pages */ + /* enable LEDs on all pages */ full_page[0] = 0; - __builtin_memcpy(full_page+1, is31_wf_leds_mask, 0x12); + __builtin_memcpy(full_page+1, is31_ic60_leds_mask, 0x12); for(i=0; i<8; i++) { is31_write_data(i, full_page, 1+0x12); } @@ -312,7 +316,7 @@ void hook_early_init(void) { is31_write_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL2, IS31_REG_BREATHCTRL2_ENABLE|3); /* Write pages */ - for(i=0; i<9; i++) { + for(i=0; i<8; i++) { is31_write_data(1,(uint8_t *)(led_game+(9*i)),9); chThdSleepMilliseconds(5); is31_write_data(2,(uint8_t *)(led_all+(9*i)),9); @@ -329,26 +333,29 @@ void hook_early_init(void) { chThdCreateStatic(waLEDthread, sizeof(waLEDthread), LOWPRIO, LEDthread, NULL); } -void hook_usb_suspend_entry(void) { -#ifdef SLEEP_LED_ENABLE - chSysLockFromISR(); - chMBPostI(&led_mailbox, LED_MSG_SLEEP_LED_ON); - chSysUnlockFromISR(); -#endif /* SLEEP_LED_ENABLE */ -} - -void hook_usb_suspend_loop(void) { - chThdSleepMilliseconds(100); - /* Remote wakeup */ - if((USB_DRIVER.status & 2) && suspend_wakeup_condition()) { - send_remote_wakeup(&USB_DRIVER); - } -} - -void hook_usb_wakeup(void) { -#ifdef SLEEP_LED_ENABLE - chSysLockFromISR(); - chMBPostI(&led_mailbox, LED_MSG_SLEEP_LED_OFF); - chSysUnlockFromISR(); -#endif /* SLEEP_LED_ENABLE */ -} +//TODO: Don't know equivalent QMK hooks for these +// +//void hook_usb_suspend_entry(void) { +//#ifdef SLEEP_LED_ENABLE +// chSysLockFromISR(); +// chMBPostI(&led_mailbox, LED_MSG_SLEEP_LED_ON); +// chSysUnlockFromISR(); +//#endif /* SLEEP_LED_ENABLE */ +//} +// +//void hook_usb_suspend_loop(void) { +// chThdSleepMilliseconds(100); +// /* Remote wakeup */ +// if((USB_DRIVER.status & 2) && suspend_wakeup_condition()) { +// send_remote_wakeup(&USB_DRIVER); +// } +//} +// +//void hook_usb_wakeup(void) { +//#ifdef SLEEP_LED_ENABLE +// chSysLockFromISR(); +// chMBPostI(&led_mailbox, LED_MSG_SLEEP_LED_OFF); +// chSysUnlockFromISR(); +//#endif /* SLEEP_LED_ENABLE */ +//} +//*/ From f66361d678047af31d9d48ca6c22afcc48756882 Mon Sep 17 00:00:00 2001 From: jpetermans Date: Thu, 6 Apr 2017 13:48:31 -0700 Subject: [PATCH 004/238] add led init function to header for use in keymap.c --- keyboards/infinity60/led_controller.h | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/keyboards/infinity60/led_controller.h b/keyboards/infinity60/led_controller.h index dcf346e04..7db02389f 100644 --- a/keyboards/infinity60/led_controller.h +++ b/keyboards/infinity60/led_controller.h @@ -26,6 +26,12 @@ msg_t is31_write_data(uint8_t page, uint8_t *buffer, uint8_t size); msg_t is31_write_register(uint8_t page, uint8_t reg, uint8_t data); msg_t is31_read_register(uint8_t page, uint8_t reg, uint8_t *result); +/* ========================= + * init functions + * ========================= */ + +void led_controller_init(void); + /* ============================= * IS31 chip related definitions * ============================= */ @@ -83,11 +89,13 @@ msg_t is31_read_register(uint8_t page, uint8_t reg, uint8_t *result); extern mailbox_t led_mailbox; // constants for signaling the LED controller thread -#define LED_MSG_CAPS_ON 1 -#define LED_MSG_CAPS_OFF 2 -#define LED_MSG_SLEEP_LED_ON 3 -#define LED_MSG_SLEEP_LED_OFF 4 -#define LED_MSG_ALL_TOGGLE 5 -#define LED_MSG_GAME_TOGGLE 6 +enum led_msg_t { + LED_MSG_CAPS_ON, + LED_MSG_CAPS_OFF, + LED_MSG_SLEEP_LED_ON, + LED_MSG_SLEEP_LED_OFF, + LED_MSG_ALL_TOGGLE, + LED_MSG_GAME_TOGGLE +}; #endif /* _LED_CONTROLLER_H_ */ From 02ef122cbbf7b9f94de5f1248fd7f8ec0351f4b4 Mon Sep 17 00:00:00 2001 From: jpetermans Date: Thu, 6 Apr 2017 13:51:33 -0700 Subject: [PATCH 005/238] Add led_controller.h to user keymap.c --- .../infinity60/keymaps/jpetermans/keymap.c | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/keyboards/infinity60/keymaps/jpetermans/keymap.c b/keyboards/infinity60/keymaps/jpetermans/keymap.c index be0bee544..2c38068fe 100644 --- a/keyboards/infinity60/keymaps/jpetermans/keymap.c +++ b/keyboards/infinity60/keymaps/jpetermans/keymap.c @@ -1,5 +1,5 @@ #include "infinity60.h" -#include "backlight.h" +#include "led_controller.h" //Helpful Defines #define _______ KC_TRNS @@ -57,7 +57,7 @@ const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS] = { _______,_______,_______,_______,_______,_______,_______, _______, _______, _______,KC_MUTE, KC_VOLD, KC_VOLU,_______,KC_NO,\ _______,_______,_______,_______,_______,_______,_______, _______, _______, _______,_______, _______,_______,_______,\ _______,_______,_______,_______,_______,_______,_______, _______, _______, _______,_______, _______,_______, \ - _______,_______,F(2),M(1),_______,_______,_______, _______, KC_MPRV, KC_MNXT,KC_MSTP, _______,KC_NO, \ + _______,_______,F(2),F(3),_______,_______,_______, _______, KC_MPRV, KC_MNXT,KC_MSTP, _______,KC_NO, \ _______,_______,_______, KC_MPLY, _______,_______, _______,_______ \ ), /* ~ */ @@ -85,12 +85,15 @@ enum function_id { enum macro_id { ACTION_LEDS_ALL, + ACTION_LEDS_GAME }; const uint16_t fn_actions[] = { [0] = ACTION_KEY(LALT(LCTL(KC_DEL))), [1] = ACTION_LAYER_MODS(_TILDE, MOD_LSFT), - [2] = ACTION_BACKLIGHT_TOGGLE() + [2] = ACTION_FUNCTION(ACTION_LEDS_ALL), + [3] = ACTION_FUNCTION(ACTION_LEDS_GAME) + /* [1] = ACTION_FUNCTION(ACTION_LEDS_GAME), [4] = ACTION_USAGE_CONSUMER(0x1B4), @@ -101,27 +104,29 @@ const uint16_t fn_actions[] = { }; /* custom action function */ -/* void action_function(keyrecord_t *record, uint8_t id, uint8_t opt) { (void)opt; switch(id) { - case 1: + case ACTION_LEDS_ALL: if(record->event.pressed) { // signal the LED controller thread chMBPost(&led_mailbox, LED_MSG_GAME_TOGGLE, TIME_IMMEDIATE); } - break; - } - + break; + case ACTION_LEDS_GAME: + if(record->event.pressed) { + // signal the LED controller thread + chMBPost(&led_mailbox, LED_MSG_ALL_TOGGLE, TIME_IMMEDIATE); + } + break; + } } -*/ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { switch(id) { case 0: if (record->event.pressed) { - return MACRO( I(5), END); } break; case 1: @@ -135,7 +140,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) // Runs just one time when the keyboard initializes. void matrix_init_user(void) { - + led_controller_init(); }; // Runs constantly in the background, in a loop. From 91f2e9fb5ec03aa4f8aee3a8a181ed0283170cf3 Mon Sep 17 00:00:00 2001 From: jpetermans Date: Thu, 6 Apr 2017 13:53:18 -0700 Subject: [PATCH 006/238] match hal settings to whitefox, fix make rules --- keyboards/infinity60/halconf.h | 4 ++-- keyboards/infinity60/rules.mk | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/keyboards/infinity60/halconf.h b/keyboards/infinity60/halconf.h index 46b37a4f4..f89dfc2e1 100644 --- a/keyboards/infinity60/halconf.h +++ b/keyboards/infinity60/halconf.h @@ -76,7 +76,7 @@ * @brief Enables the I2C subsystem. */ #if !defined(HAL_USE_I2C) || defined(__DOXYGEN__) -#define HAL_USE_I2C FALSE +#define HAL_USE_I2C TRUE #endif /** @@ -139,7 +139,7 @@ * @brief Enables the SERIAL over USB subsystem. */ #if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__) -#define HAL_USE_SERIAL_USB TRUE +#define HAL_USE_SERIAL_USB FALSE #endif /** diff --git a/keyboards/infinity60/rules.mk b/keyboards/infinity60/rules.mk index 56d6470b5..f58bb2642 100644 --- a/keyboards/infinity60/rules.mk +++ b/keyboards/infinity60/rules.mk @@ -1,6 +1,7 @@ # project specific files SRC = matrix.c \ - led.c + led.c \ + led_controller.c ## chip/board settings # - the next two should match the directories in @@ -63,4 +64,4 @@ CONSOLE_ENABLE ?= yes # Console for debug COMMAND_ENABLE ?= yes # Commands for debug and configuration SLEEP_LED_ENABLE ?= yes # Breathing sleep LED during USB suspend NKRO_ENABLE ?= yes # USB Nkey Rollover -CUSTOM_MATRIX ?= yes # Custom matrix file \ No newline at end of file +CUSTOM_MATRIX ?= yes # Custom matrix file From 56be3007570a3b6b2e2f78f500cea4fb22430459 Mon Sep 17 00:00:00 2001 From: jpetermans Date: Thu, 6 Apr 2017 14:23:14 -0700 Subject: [PATCH 007/238] Add Kinetis_i2c settings consistent with whitefox mcuconf --- keyboards/infinity60/mcuconf.h | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/keyboards/infinity60/mcuconf.h b/keyboards/infinity60/mcuconf.h index f453304b7..6af85d079 100644 --- a/keyboards/infinity60/mcuconf.h +++ b/keyboards/infinity60/mcuconf.h @@ -47,9 +47,12 @@ * USB driver settings */ #define KINETIS_USB_USE_USB0 TRUE -/* Need to redefine this, since the default is for K20x */ -/* This is for Teensy LC; you should comment it out (or change to 5) - * for Teensy 3.x */ -#define KINETIS_USB_USB0_IRQ_PRIORITY 2 +#define KINETIS_USB_USB0_IRQ_PRIORITY 5 + +/* + * I2C driver settings + */ +#define KINETIS_I2C_USE_I2C0 TRUE +#define KINETIS_I2C_I2C0_PRIORITY 4 #endif /* _MCUCONF_H_ */ From d89114400c398b900e27bf324a7973d1e0f25e58 Mon Sep 17 00:00:00 2001 From: jpetermans Date: Thu, 6 Apr 2017 15:22:13 -0700 Subject: [PATCH 008/238] Small keymap tweak and clean up. --- keyboards/infinity60/keymaps/jpetermans/keymap.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/keyboards/infinity60/keymaps/jpetermans/keymap.c b/keyboards/infinity60/keymaps/jpetermans/keymap.c index 2c38068fe..d6c2b7bb5 100644 --- a/keyboards/infinity60/keymaps/jpetermans/keymap.c +++ b/keyboards/infinity60/keymaps/jpetermans/keymap.c @@ -55,8 +55,8 @@ const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS] = { /* media */ [_MEDIA] = KEYMAP( \ _______,_______,_______,_______,_______,_______,_______, _______, _______, _______,KC_MUTE, KC_VOLD, KC_VOLU,_______,KC_NO,\ - _______,_______,_______,_______,_______,_______,_______, _______, _______, _______,_______, _______,_______,_______,\ - _______,_______,_______,_______,_______,_______,_______, _______, _______, _______,_______, _______,_______, \ + _______,_______,_______,_______,_______,_______,_______, _______, KC_UP, _______,_______, _______,_______,_______,\ + _______,_______,_______,_______,_______,_______,_______, KC_LEFT, KC_DOWN, KC_RGHT,_______, _______,_______, \ _______,_______,F(2),F(3),_______,_______,_______, _______, KC_MPRV, KC_MNXT,KC_MSTP, _______,KC_NO, \ _______,_______,_______, KC_MPLY, _______,_______, _______,_______ \ ), @@ -93,14 +93,6 @@ const uint16_t fn_actions[] = { [1] = ACTION_LAYER_MODS(_TILDE, MOD_LSFT), [2] = ACTION_FUNCTION(ACTION_LEDS_ALL), [3] = ACTION_FUNCTION(ACTION_LEDS_GAME) - -/* [1] = ACTION_FUNCTION(ACTION_LEDS_GAME), - - [4] = ACTION_USAGE_CONSUMER(0x1B4), - [5] = ACTION_USAGE_CONSUMER(0x196), - [6] = ACTION_USAGE_CONSUMER(0x1A6), - [7] = ACTION_USAGE_CONSUMER(0x1A0) -*/ }; /* custom action function */ From af13e9a12d64f74873e5bf429fdedcda37b3036a Mon Sep 17 00:00:00 2001 From: jpetermans Date: Thu, 6 Apr 2017 16:27:51 -0700 Subject: [PATCH 009/238] Moved led page arrays to keymap.c and added keymap header to define individual led addresses --- .../infinity60/keymaps/jpetermans/keymap.c | 80 +++++++++++++++++-- .../keymaps/jpetermans/keymap_jpetermans.h | 78 ++++++++++++++++++ keyboards/infinity60/led_controller.c | 51 +----------- 3 files changed, 152 insertions(+), 57 deletions(-) create mode 100644 keyboards/infinity60/keymaps/jpetermans/keymap_jpetermans.h diff --git a/keyboards/infinity60/keymaps/jpetermans/keymap.c b/keyboards/infinity60/keymaps/jpetermans/keymap.c index 2c38068fe..7b90bc8ed 100644 --- a/keyboards/infinity60/keymaps/jpetermans/keymap.c +++ b/keyboards/infinity60/keymaps/jpetermans/keymap.c @@ -1,5 +1,6 @@ #include "infinity60.h" #include "led_controller.h" +#include "keymap_jpetermans.h" //Helpful Defines #define _______ KC_TRNS @@ -86,6 +87,66 @@ enum function_id { enum macro_id { ACTION_LEDS_ALL, ACTION_LEDS_GAME +//TODO: ACTION_LED_LAYER which reads current layer and turns on appropriate LED +}; + +/* + Configuring led control can be done + 1. full keyboard at a time - define led array, or + 2. individual - send specific led address (defined in keymap.h) + + The arrays relate to the mcu's LED pages (8 available) desribed in led_controller.c + 0x24 (pcb row 1) is first byte of PWM portion of LED page + 0x34 (pcb row 2) is 17th byte of PWM portion of LED page + array translates to row and column positions + + + Infinity60 LED MAP + 11 12 13 14 15 16 17 18 21 22 23 24 25 26 27* + 28 31 32 33 34 35 36 37 38 41 42 43 44 45 + 46 47 48 51 52 53 54 55 56 57 58 61 62 + 63 64 65 66 67 68 71 72 73 74 75 76 77* + 78 81 82 83 84 85 86 87 +*Unused in Alphabet Layout +*/ + +//"WASD" +const uint8_t led_game[72] = { + 0x24, + 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x34, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x44, + 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x54, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, + 0x64, + 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x74, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x84, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x94, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +const uint8_t led_all[72] = { + 0x24, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x34, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x44, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x54, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x64, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x74, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x84, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x94, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }; const uint16_t fn_actions[] = { @@ -94,13 +155,6 @@ const uint16_t fn_actions[] = { [2] = ACTION_FUNCTION(ACTION_LEDS_ALL), [3] = ACTION_FUNCTION(ACTION_LEDS_GAME) -/* [1] = ACTION_FUNCTION(ACTION_LEDS_GAME), - - [4] = ACTION_USAGE_CONSUMER(0x1B4), - [5] = ACTION_USAGE_CONSUMER(0x196), - [6] = ACTION_USAGE_CONSUMER(0x1A6), - [7] = ACTION_USAGE_CONSUMER(0x1A0) -*/ }; /* custom action function */ @@ -140,7 +194,19 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) // Runs just one time when the keyboard initializes. void matrix_init_user(void) { + uint8_t j; + led_controller_init(); + +//TODO: do pages need to be written at init or ok on demand? + /* Write pages */ + for(j=0; j<8; j++) { + is31_write_data(1,(uint8_t *)(led_game+(9*j)),9); + chThdSleepMilliseconds(5); + is31_write_data(2,(uint8_t *)(led_all+(9*j)),9); + chThdSleepMilliseconds(5); + } + }; // Runs constantly in the background, in a loop. diff --git a/keyboards/infinity60/keymaps/jpetermans/keymap_jpetermans.h b/keyboards/infinity60/keymaps/jpetermans/keymap_jpetermans.h new file mode 100644 index 000000000..240374423 --- /dev/null +++ b/keyboards/infinity60/keymaps/jpetermans/keymap_jpetermans.h @@ -0,0 +1,78 @@ +/* LED layout mainly based on default Standard configuration + * ,-----------------------------------------------------------. + * |Esc| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =| \ | ` | + * |-----------------------------------------------------------| + * |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| Bksp| + * |-----------------------------------------------------------| + * |Caps | A| S| D| F| G| H| J| K| L| ;| '|Enter | + * |-----------------------------------------------------------| + * |Shift | Z| X| C| V| B| N| M| ,| .| /|Shift |Fn0| + * |-----------------------------------------------------------' + * | LCtl|LGui|LAlt | Space | RAlt|RGui|RMenu|RCtl| + * `-----------------------------------------------------------' +*/ + + +#define ADDR_LED_ESC 0x24 +#define ADDR_LED_1 0x25 +#define ADDR_LED_2 0x26 +#define ADDR_LED_3 0x27 +#define ADDR_LED_4 0x28 +#define ADDR_LED_5 0x29 +#define ADDR_LED_6 0x2A +#define ADDR_LED_7 0x2B +#define ADDR_LED_8 0x34 +#define ADDR_LED_9 0x35 +#define ADDR_LED_0 0x36 +#define ADDR_LED_MINS 0x37 +#define ADDR_LED_EQL 0x38 +#define ADDR_LED_BSLS 0x39 +//#define ADDR_LED_GRV 0x3A //not used by Alphabet layout +#define ADDR_LED_TAB 0x3B +#define ADDR_LED_Q 0x44 +#define ADDR_LED_W 0x45 +#define ADDR_LED_E 0x46 +#define ADDR_LED_R 0x47 +#define ADDR_LED_T 0x48 +#define ADDR_LED_Y 0x49 +#define ADDR_LED_U 0x4A +#define ADDR_LED_I 0x4B +#define ADDR_LED_O 0x54 +#define ADDR_LED_P 0x55 +#define ADDR_LED_LBRC 0x56 +#define ADDR_LED_RBRC 0x57 +#define ADDR_LED_BSPC 0x58 +#define ADDR_LED_CAPS 0x59 +#define ADDR_LED_A 0x5A +#define ADDR_LED_S 0x5B +#define ADDR_LED_D 0x64 +#define ADDR_LED_F 0x65 +#define ADDR_LED_G 0x66 +#define ADDR_LED_H 0x67 +#define ADDR_LED_J 0x68 +#define ADDR_LED_K 0x69 +#define ADDR_LED_L 0x6A +#define ADDR_LED_SCLN 0x6B +#define ADDR_LED_QUOT 0x74 +#define ADDR_LED_ENT 0x75 +#define ADDR_LED_LSFT 0x76 +#define ADDR_LED_Z 0x77 +#define ADDR_LED_X 0x78 +#define ADDR_LED_C 0x79 +#define ADDR_LED_V 0x7A +#define ADDR_LED_B 0x7B +#define ADDR_LED_N 0x84 +#define ADDR_LED_M 0x85 +#define ADDR_LED_COMM 0x86 +#define ADDR_LED_DOT 0x87 +#define ADDR_LED_SLSH 0x88 +#define ADDR_LED_RSFT 0x89 +//#define ADDR_LED_FN0 0x8A //not used by Alphabet layout +#define ADDR_LED_LCTL 0x8B +#define ADDR_LED_LGUI 0x94 +#define ADDR_LED_LALT 0x95 +#define ADDR_LED_SPC 0x96 +#define ADDR_LED_RALT 0x97 +#define ADDR_LED_RGUI 0x98 +#define ADDR_LED_MENU 0x99 +#define ADDR_LED_RCTL 0x9A diff --git a/keyboards/infinity60/led_controller.c b/keyboards/infinity60/led_controller.c index c5303a3e7..9579bc08b 100644 --- a/keyboards/infinity60/led_controller.c +++ b/keyboards/infinity60/led_controller.c @@ -171,6 +171,7 @@ static THD_FUNCTION(LEDthread, arg) { // process 'msg' here switch(msg) { +//TODO: make this generic and able to turn on/off any address and loop through all(or current) pages case LED_MSG_CAPS_ON: // turn caps on on pages 1 and 2 is31_write_register(0, CAPS_LOCK_LED_ADDRESS, 0xFF); @@ -238,48 +239,6 @@ static THD_FUNCTION(LEDthread, arg) { } } -//These relate to the LED map above, row and column -//0x24 = first byte (CA1) of PWM page, 0x34 is 17th byte (CA2) -/* LED game mode */ -const uint8_t led_game[72] = { - 0x24, - 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x34, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x44, - 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x54, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, - 0x64, - 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x74, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x84, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x94, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; - -/* ALL LEDs */ -const uint8_t led_all[72] = { - 0x24, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x34, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0x44, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x54, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x64, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x74, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x84, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x94, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -}; - /* ============= * hook into TMK * ============= */ @@ -315,14 +274,6 @@ void led_controller_init(void) { is31_write_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL1, (3<<4)|3); is31_write_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL2, IS31_REG_BREATHCTRL2_ENABLE|3); - /* Write pages */ - for(i=0; i<8; i++) { - is31_write_data(1,(uint8_t *)(led_game+(9*i)),9); - chThdSleepMilliseconds(5); - is31_write_data(2,(uint8_t *)(led_all+(9*i)),9); - chThdSleepMilliseconds(5); - } - // clean up the capslock LED is31_write_register(1, CAPS_LOCK_LED_ADDRESS, 0); is31_write_register(2, CAPS_LOCK_LED_ADDRESS, 0); From a2ac8837790030b771744402aac8d8ab0e1967aa Mon Sep 17 00:00:00 2001 From: jpetermans Date: Fri, 7 Apr 2017 15:58:17 -0700 Subject: [PATCH 010/238] add ability to toggle individual led by address --- .../infinity60/keymaps/jpetermans/keymap.c | 76 +++++---- keyboards/infinity60/led.c | 3 + keyboards/infinity60/led_controller.c | 148 +++++++++--------- 3 files changed, 127 insertions(+), 100 deletions(-) diff --git a/keyboards/infinity60/keymaps/jpetermans/keymap.c b/keyboards/infinity60/keymaps/jpetermans/keymap.c index 7b90bc8ed..c7145ed78 100644 --- a/keyboards/infinity60/keymaps/jpetermans/keymap.c +++ b/keyboards/infinity60/keymaps/jpetermans/keymap.c @@ -12,6 +12,10 @@ #define _MEDIA 3 #define _TILDE 4 +/* ================================== + * KEYMAPS + * ==================================*/ + const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS] = { /* Layer 0: Default Layer * ,-----------------------------------------------------------. @@ -58,7 +62,7 @@ const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS] = { _______,_______,_______,_______,_______,_______,_______, _______, _______, _______,KC_MUTE, KC_VOLD, KC_VOLU,_______,KC_NO,\ _______,_______,_______,_______,_______,_______,_______, _______, _______, _______,_______, _______,_______,_______,\ _______,_______,_______,_______,_______,_______,_______, _______, _______, _______,_______, _______,_______, \ - _______,_______,F(2),F(3),_______,_______,_______, _______, KC_MPRV, KC_MNXT,KC_MSTP, _______,KC_NO, \ + _______,_______,F(2),F(3),F(4),_______,_______, _______, KC_MPRV, KC_MNXT,KC_MSTP, _______,KC_NO, \ _______,_______,_______, KC_MPLY, _______,_______, _______,_______ \ ), /* ~ */ @@ -86,28 +90,35 @@ enum function_id { enum macro_id { ACTION_LEDS_ALL, - ACTION_LEDS_GAME -//TODO: ACTION_LED_LAYER which reads current layer and turns on appropriate LED + ACTION_LEDS_GAME, + ACTION_LED_1 }; + +/* ================================== + * LED MAPPING + * ==================================*/ + +//TODO: ACTION_LED_LAYER which reads current layer and turns on appropriate LED /* - Configuring led control can be done + Configuring led control can be done as 1. full keyboard at a time - define led array, or - 2. individual - send specific led address (defined in keymap.h) + 2. individual led - send specific led address (defined in keymap.h) - The arrays relate to the mcu's LED pages (8 available) desribed in led_controller.c + Infinity60 LED MAP + 11 12 13 14 15 16 17 18 21 22 23 24 25 26 27* + 28 31 32 33 34 35 36 37 38 41 42 43 44 45 + 46 47 48 51 52 53 54 55 56 57 58 61 62 + 63 64 65 66 67 68 71 72 73 74 75 76 77* + 78 81 82 83 84 85 86 87 + *Unused in Alphabet Layout + + The full keyboard arrays map to the mcu's LED pages + (8 available) desribed in led_controller.c + 0x24 (pcb row 1) is first byte of PWM portion of LED page 0x34 (pcb row 2) is 17th byte of PWM portion of LED page array translates to row and column positions - - - Infinity60 LED MAP - 11 12 13 14 15 16 17 18 21 22 23 24 25 26 27* - 28 31 32 33 34 35 36 37 38 41 42 43 44 45 - 46 47 48 51 52 53 54 55 56 57 58 61 62 - 63 64 65 66 67 68 71 72 73 74 75 76 77* - 78 81 82 83 84 85 86 87 -*Unused in Alphabet Layout */ //"WASD" @@ -153,7 +164,8 @@ const uint16_t fn_actions[] = { [0] = ACTION_KEY(LALT(LCTL(KC_DEL))), [1] = ACTION_LAYER_MODS(_TILDE, MOD_LSFT), [2] = ACTION_FUNCTION(ACTION_LEDS_ALL), - [3] = ACTION_FUNCTION(ACTION_LEDS_GAME) + [3] = ACTION_FUNCTION(ACTION_LEDS_GAME), + [4] = ACTION_FUNCTION(ACTION_LED_1) }; @@ -162,15 +174,21 @@ void action_function(keyrecord_t *record, uint8_t id, uint8_t opt) { (void)opt; switch(id) { case ACTION_LEDS_ALL: - if(record->event.pressed) { - // signal the LED controller thread - chMBPost(&led_mailbox, LED_MSG_GAME_TOGGLE, TIME_IMMEDIATE); - } + if(record->event.pressed) { + // signal the LED controller thread + chMBPost(&led_mailbox, 1, TIME_IMMEDIATE); + } break; case ACTION_LEDS_GAME: if(record->event.pressed) { // signal the LED controller thread - chMBPost(&led_mailbox, LED_MSG_ALL_TOGGLE, TIME_IMMEDIATE); + chMBPost(&led_mailbox, 2, TIME_IMMEDIATE); + } + break; + case ACTION_LED_1: + if(record->event.pressed) { + // signal the LED controller thread + chMBPost(&led_mailbox, ADDR_LED_1, TIME_IMMEDIATE); } break; } @@ -179,14 +197,14 @@ void action_function(keyrecord_t *record, uint8_t id, uint8_t opt) { const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { switch(id) { - case 0: - if (record->event.pressed) { - } - break; - case 1: - if (record->event.pressed) { - } - break; + case 0: + if (record->event.pressed) { + } + break; + case 1: + if (record->event.pressed) { + } + break; } return MACRO_NONE; }; diff --git a/keyboards/infinity60/led.c b/keyboards/infinity60/led.c index e17a5dd0d..815a529fc 100644 --- a/keyboards/infinity60/led.c +++ b/keyboards/infinity60/led.c @@ -36,6 +36,9 @@ void led_set(uint8_t usb_led) { GPIOA->PCOR |= (1<<5); } */ +//TODO: How does this test if led is set +//usb_led --> led_set(usb_led) <-- chibios/host_keyboard_leds <-- keyboard_leds from usbSetupTransfer +//keyboard_leds is enum'd in chibios/main.c if (usb_led & (1<= 0x24) { + xprintf("Power pre-read\ntemp: %X - msg: %X - pwm: %X\n", temp, msg, pwm); + is31_read_register(0, msg, &temp); + chThdSleepMilliseconds(10); + xprintf("Post-read\ntemp: %X - msg: %X - pwm: %X\n", temp, msg, pwm); + chThdSleepMilliseconds(10); + pwm = (temp > 0x00 ? 0x00 : 0xFF); + xprintf("pwm after: %X\n", pwm); + chThdSleepMilliseconds(10); + for(i=0; i<8; i++) { + is31_write_register(i, msg, pwm); + } + xprintf("Power post-change\ntemp: %X - msg: %X - pwm: %X\n", temp, msg, pwm); + chThdSleepMilliseconds(10); + } + break; + } } + xprintf("--------------------\n"); } } - -/* ============= - * hook into TMK - * ============= */ +/* ===================== + * hook into user keymap + * ===================== */ void led_controller_init(void) { uint8_t i; From dda858c437e2fd0336f070ccb5d1f6e412815d9a Mon Sep 17 00:00:00 2001 From: jpetermans Date: Mon, 10 Apr 2017 17:36:47 -0700 Subject: [PATCH 011/238] revised led controller code to allow for more options unable to switch picture displays --- .../infinity60/keymaps/jpetermans/keymap.c | 105 +++--- keyboards/infinity60/led.c | 4 +- keyboards/infinity60/led_controller.c | 335 ++++++++++++++---- keyboards/infinity60/led_controller.h | 33 +- 4 files changed, 342 insertions(+), 135 deletions(-) diff --git a/keyboards/infinity60/keymaps/jpetermans/keymap.c b/keyboards/infinity60/keymaps/jpetermans/keymap.c index c7145ed78..cfc288916 100644 --- a/keyboards/infinity60/keymaps/jpetermans/keymap.c +++ b/keyboards/infinity60/keymaps/jpetermans/keymap.c @@ -98,8 +98,6 @@ enum macro_id { * LED MAPPING * ==================================*/ -//TODO: ACTION_LED_LAYER which reads current layer and turns on appropriate LED - /* Configuring led control can be done as 1. full keyboard at a time - define led array, or @@ -121,43 +119,50 @@ enum macro_id { array translates to row and column positions */ -//"WASD" -const uint8_t led_game[72] = { - 0x24, - 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x34, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x44, - 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x54, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, - 0x64, - 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x74, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x84, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x94, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +//LED Layer indicator (1 per layer 3-7) +const uint8_t led_single_layer[5] = { + 12,13,14,15,16 }; - -const uint8_t led_all[72] = { - 0x24, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x34, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x44, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x54, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x64, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x74, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x84, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x94, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +//LED Page 1 - All off +//LED Page 2 - All on +//LED Page 3 - _Nav +const uint8_t led_nav[33] = { + 11,12,13,14,15,16,17,18,21,22,23,24,25, + 28, 37,38,41,42,45, + 46,47,48, 54,55,56,57,58, + 64,65,66, 71, + 84,85 +}; +//LED Page 4 - _Numpad +const uint8_t led_numpad[17] = { + 18,21,22,23, + 37,38,41,42, + 55,56,57,58, + 72,73,74,75, + 85 +}; +//LED Page 5 - _Media +const uint8_t led_media[12] = { + 23,24,25, + 38, + 55,56,57, + 73,74,75, + 83, 86 +}; +//LED Page 6 - _Game +const uint8_t led_game[5] = { + //row 1 + 11, + //row 2 + //row 3 + 32, + //row 4 + 47, 48, + //row 5 + 51 + //row 6 + //row 7 + //row 8 }; const uint16_t fn_actions[] = { @@ -172,17 +177,20 @@ const uint16_t fn_actions[] = { /* custom action function */ void action_function(keyrecord_t *record, uint8_t id, uint8_t opt) { (void)opt; + msg_t msg; switch(id) { case ACTION_LEDS_ALL: if(record->event.pressed) { // signal the LED controller thread - chMBPost(&led_mailbox, 1, TIME_IMMEDIATE); + msg=(TOGGLE_LED << 8) | 12; + chMBPost(&led_mailbox, msg, TIME_IMMEDIATE); } break; case ACTION_LEDS_GAME: if(record->event.pressed) { // signal the LED controller thread - chMBPost(&led_mailbox, 2, TIME_IMMEDIATE); + msg=(TOGGLE_LAYER_LEDS << 8) | 5; + chMBPost(&led_mailbox, msg, TIME_IMMEDIATE); } break; case ACTION_LED_1: @@ -212,19 +220,22 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) // Runs just one time when the keyboard initializes. void matrix_init_user(void) { - uint8_t j; led_controller_init(); //TODO: do pages need to be written at init or ok on demand? - /* Write pages */ - for(j=0; j<8; j++) { - is31_write_data(1,(uint8_t *)(led_game+(9*j)),9); +/* Write pages */ + write_led_page(3, led_nav, 33); chThdSleepMilliseconds(5); - is31_write_data(2,(uint8_t *)(led_all+(9*j)),9); - chThdSleepMilliseconds(5); - } + write_led_page(4, led_numpad, 17); + chThdSleepMilliseconds(5); + + write_led_page(5, led_media, 12); + chThdSleepMilliseconds(5); + + write_led_page(6, led_game, 5); + chThdSleepMilliseconds(5); }; // Runs constantly in the background, in a loop. diff --git a/keyboards/infinity60/led.c b/keyboards/infinity60/led.c index 815a529fc..d2f554549 100644 --- a/keyboards/infinity60/led.c +++ b/keyboards/infinity60/led.c @@ -42,12 +42,12 @@ void led_set(uint8_t usb_led) { if (usb_led & (1<. * The usual Caps Lock position is C4-6, so the address is * 0x24 + (4-1)*0x10 + (8-1) = 0x59 */ #if !defined(CAPS_LOCK_LED_ADDRESS) -#define CAPS_LOCK_LED_ADDRESS 0x59 +#define CAPS_LOCK_LED_ADDRESS 0x46 +#endif + +#if !defined(NUM_LOCK_LED_ADDRESS) +#define NUM_LOCK_LED_ADDRESS 0x85 #endif /* Which LED should breathe during sleep */ @@ -85,12 +89,21 @@ uint8_t full_page[0xB4+1] = {0}; // LED mask (which LEDs are present, selected by bits) // See page comment above, control alternates CA matrix/CB matrix // IC60 pcb uses only CA matrix. -// Each byte is a control pin for 8 leds 8-1 +// Each byte is a control pin for 8 leds ordered 8-1 const uint8_t is31_ic60_leds_mask[0x12] = { 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x7F, 0x00, 0x00, 0x00 }; +// array to hold brightness pwm steps +const uint8_t pwm_levels[5] = { + 0x00, 0x16, 0x4E, 0xA1, 0xFF +}; + +// array to write to pwm register +uint8_t pwm_reg_array[9] = {0}; + + /* ============================ * communication functions * ============================ */ @@ -109,6 +122,7 @@ msg_t is31_write_register(uint8_t page, uint8_t reg, uint8_t data) { is31_select_page(page); tx[0] = reg; tx[1] = data; + xprintf("page display: %X\n", page); return i2cMasterTransmitTimeout(&I2CD1, IS31_ADDR_DEFAULT, tx, 2, NULL, 0, US2ST(IS31_TIMEOUT)); } @@ -160,98 +174,267 @@ static THD_FUNCTION(LEDthread, arg) { (void)arg; chRegSetThreadName("LEDthread"); - uint8_t i; - uint8_t temp, pwm; - uint8_t save_page, save_breath1, save_breath2; + uint8_t i, page; + + //persistent status variables + uint8_t backlight_status, lock_status, led_step, active_layer; + uint8_t led_control_reg[0x13] = {0};//led control register start address + 0x12 bytes + + //mailbox variables + uint8_t temp, msg_type, msg_led; + msg_t msg; + +/* //control register variables + uint8_t page, save_page, save_breath1, save_breath2; msg_t msg, retval; +*/ + +// initialize persistent variables +backlight_status = 0; +lock_status = 0;//TODO: does keyboard remember locks? +led_step = 4; //full brightness +active_layer = 0; while(true) { // wait for a message (asynchronous) // (messages are queued (up to LED_MAILBOX_NUM_MSGS) if they can't // be processed right away) chMBFetch(&led_mailbox, &msg, TIME_INFINITE); + msg_type = (msg >> 8) & 0xFF; //first byte is msg type + msg_led = (msg) & 0xFF; //second byte is action information - // process 'msg' here - // if msg between 0-7, then process as page#, otherwise a specific LED address xprintf("--------------------\n"); - xprintf("mailbox fetch\ntemp: %X - msg: %X\n", temp, msg); - if (msg < 8) { + xprintf("mailbox fetch\nmsg: %X\n", msg); + xprintf("type: %X - led: %X\n", msg_type, msg_led); //test if msg_type is 1 or 2 bytes after mask + switch (msg_type){ + case KEY_LIGHT: + //TODO: lighting key led on keypress + break; + + case TOGGLE_LED: + //TODO: toggle existing indicator off, or let user do this, but write frame 7 for every led change + //turn on single led, msg_led = row/col of led + set_led_bit(led_control_reg, msg_led, 1); - // read current page into 'temp' - is31_read_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, &temp); - chThdSleepMilliseconds(1); - // If page is already in layer, switch off (layer 0) - xprintf("Layer: post-read\ntemp: %X\n", temp); - if(temp == msg) { - is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, 0); - } else { - is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, msg); - } - xprintf("Layer: post-change\ntemp: %X\n", temp); + is31_write_data (7, led_control_reg, 0x12+1); + is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, 7); + active_layer = 7; + is31_read_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, &temp); + xprintf("page display: %X\n", temp); + break; - } else { + case TOGGLE_ALL: + xprintf("TOGGLE_ALL\n"); + //msg_led = unused, TODO: consider using msg_led to toggle layer display + is31_read_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, &temp); - switch(msg) { -//TODO: make this generic and able to turn on/off any address and loop through all(or current) pages -//TODO: set number of layers somewhere and loop through all when setting specific led - case LED_MSG_SLEEP_LED_ON: - // save current settings - is31_read_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, &save_page); - is31_read_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL1, &save_breath1); - is31_read_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL2, &save_breath2); - // use pages 7 and 8 for (hardware) breathing (assuming they're empty) - is31_write_register(6, BREATHE_LED_ADDRESS, 0xFF); - is31_write_register(7, BREATHE_LED_ADDRESS, 0x00); - is31_write_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL1, (6<<4)|6); - is31_write_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL2, IS31_REG_BREATHCTRL2_ENABLE|3); - retval = MSG_TIMEOUT; - temp = 6; - while(retval == MSG_TIMEOUT) { - // switch to the other page - is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, temp); - temp = (temp == 6 ? 7 : 6); - // the times should be sufficiently long for IS31 to finish switching pages - retval = chMBFetch(&led_mailbox, &msg, MS2ST(temp == 6 ? 4000 : 6000)); - } - // received a message (should be a wakeup), so restore previous state - chThdSleepMilliseconds(3000); // need to wait until the page change finishes - // note: any other messages are queued - is31_write_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL1, save_breath1); - is31_write_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL2, save_breath2); - is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, save_page); - break; - case LED_MSG_SLEEP_LED_OFF: - // should not get here; wakeup should be received in the branch above break; - break; - default: - if(msg >= 0x24) { - xprintf("Power pre-read\ntemp: %X - msg: %X - pwm: %X\n", temp, msg, pwm); - is31_read_register(0, msg, &temp); - chThdSleepMilliseconds(10); - xprintf("Post-read\ntemp: %X - msg: %X - pwm: %X\n", temp, msg, pwm); - chThdSleepMilliseconds(10); - pwm = (temp > 0x00 ? 0x00 : 0xFF); - xprintf("pwm after: %X\n", pwm); - chThdSleepMilliseconds(10); - for(i=0; i<8; i++) { - is31_write_register(i, msg, pwm); - } - xprintf("Power post-change\ntemp: %X - msg: %X - pwm: %X\n", temp, msg, pwm); - chThdSleepMilliseconds(10); - } - break; + xprintf("temp: %X\n", temp); + //if LED_ALL is on then toggle off, any other layer, turn on LED_ALL + if(temp == 1) { + xprintf("page display true: %X\n", temp); + is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, 0); + } else { + xprintf("page display false: %X\n", temp); + is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, 1); } + is31_read_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, &temp); + xprintf("page display: %X\n", temp); + break; + + case TOGGLE_BACKLIGHT: + //msg_led = unused + backlight_status ^= 1; + is31_read_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, &temp); + active_layer = temp; + + page = backlight_status == 0 ? 0 : active_layer; + is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, page); + break; + + case TOGGLE_LAYER_LEDS://show layer indicator or full map of layer keys. + //TODO: change so user can flag which they want, indiv or full map in fn_actions + //msg_led = layer to toggle on + is31_read_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, &temp); + + if(temp == msg_led) { + is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, 7); + active_layer = 7; + } else { + is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, msg_led); + active_layer = msg_led; + } + break; + + case TOGGLE_LOCK_LED: + //msg_led = 0-3 for lock flags + lock_status ^= msg_led; //TODO: confirm toggling works and doesn't get out of sync + set_lock_leds(led_control_reg, lock_status); + break; + + case MODE_BREATH: + break; + case STEP_BRIGHTNESS: + //pwm_levels[] bounds checking, loop through array + //TODO: find a cleaner way to walk through this logic + if (msg_led == 0) { + if (led_step == 0) { + led_step = 4; + } else { + led_step--; + } + } else { + if (led_step == 4) { + led_step = 0; + } else { + led_step++; + } + } + + //TODO: this seems a messy way to populate the pwm register + //populate the 9 byte rows to be written to each pin, first byte is register (pin) address + for(i=1; i<9; i++) { + pwm_reg_array[i]=pwm_levels[led_step]; + } + for(i=0; i<8; i++) { + pwm_reg_array[0] = 0x24 + (i * 0x10);//first byte of 9 bytes must be register address + is31_write_data(0, pwm_reg_array, 9); + chThdSleepMilliseconds(5); + } + break; + +/* case LED_MSG_SLEEP_LED_ON: + // save current settings + is31_read_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, &save_page); + is31_read_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL1, &save_breath1); + is31_read_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL2, &save_breath2); + // use pages 7 and 8 for (hardware) breathing (assuming they're empty) + is31_write_register(6, BREATHE_LED_ADDRESS, 0xFF); + is31_write_register(7, BREATHE_LED_ADDRESS, 0x00); + is31_write_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL1, (6<<4)|6); + is31_write_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL2, IS31_REG_BREATHCTRL2_ENABLE|3); + retval = MSG_TIMEOUT; + temp = 6; + while(retval == MSG_TIMEOUT) { + // switch to the other page + is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, temp); + temp = (temp == 6 ? 7 : 6); + // the times should be sufficiently long for IS31 to finish switching pages + retval = chMBFetch(&led_mailbox, &msg, MS2ST(temp == 6 ? 4000 : 6000)); + } + // received a message (should be a wakeup), so restore previous state + chThdSleepMilliseconds(3000); // need to wait until the page change finishes + // note: any other messages are queued + is31_write_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL1, save_breath1); + is31_write_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL2, save_breath2); + is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, save_page); + break; + case LED_MSG_SLEEP_LED_OFF: + // should not get here; wakeup should be received in the branch above break; + break; + default: + //TODO: individual led state unchanged if page arrays are selected in code above + //avoidable if full pages are written on the fly + //or use pg8 for individual leds, have pointer to currently on led address for toggling + if (msg == 0x59 || msg == 0x84) { + //toggle lock keys on all layers + for (i=0,i<8,i++) { + is31_read_register(0, msg, &temp); + pwm = (temp > 0x00 ? 0x00 : 0xFF); + is31_write_register(i,msg,pwm); + } + + } else if(msg >= 0x24) { + xprintf("Power pre-read\ntemp: %X - msg: %X - pwm: %X\n", temp, msg, pwm); + is31_read_register(7, msg, &temp); + xprintf("Post-read\ntemp: %X - msg: %X - pwm: %X\n", temp, msg, pwm); + if (msg == active_led) { + //toggle led power + pwm = (temp > 0x00 ? 0x00 : 0xFF); + + //Use 8th led page for individual led indicators + is31_write_register(7, msg, pwm); + } else { + is31_write_register(7, active_led, 0x00); + is31_write_register(7, msg, 0xFF); + } + xprintf("Power post-change\ntemp: %X - msg: %X - pwm: %X\n", temp, msg, pwm); + is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, 7); + } + break; +*/ } xprintf("--------------------\n"); } } + + +/* ======================== + * led bit processing + * ======================== */ +void set_led_bit (uint8_t *led_control_reg, uint8_t msg_led, uint8_t toggle_on) { + uint8_t row_byte, column_bit; + //msg_led tens column is pin#, A-control register is every other 8 bits + //ones column is bit position in 8-bit mask + //control register will be one bit shifted into position along register's full 0x12 bytes + ////first byte is register address 0x00 + row_byte = ((msg_led / 10) % 10 - 1 ) * 2 + 1; + column_bit = 1<<(msg_led % 10 - 1); + + if (toggle_on) { + led_control_reg[row_byte] |= 1<<(column_bit); + } else { + led_control_reg[row_byte] &= ~1<<(column_bit); + } +} + +void set_lock_leds(uint8_t *led_control_reg, uint8_t lock_status) { + uint8_t i; + + switch (lock_status) { + case 1: + set_led_bit(led_control_reg, CAPS_LOCK_LED_ADDRESS, 1);//TODO: define lock addresses by matrix#, and loop for all frames + set_led_bit(led_control_reg, NUM_LOCK_LED_ADDRESS, 0); + break; + case 2: + set_led_bit(led_control_reg, CAPS_LOCK_LED_ADDRESS, 0); + set_led_bit(led_control_reg, NUM_LOCK_LED_ADDRESS, 1); + break; + case 3: + set_led_bit(led_control_reg, NUM_LOCK_LED_ADDRESS, 1); + set_led_bit(led_control_reg, CAPS_LOCK_LED_ADDRESS, 1); + break; + } + + for(i=1; i<8; i++) { //keep LED_OFF layer all off, including locks + is31_write_data (i, led_control_reg, 0x12+1); + chThdSleepMilliseconds(5); + } +} + +void write_led_page (uint8_t page, const uint8_t *led_array, uint8_t led_count) { +//TODO: init function that accepts array of led addresses and sets them by row + uint8_t i; + uint8_t row, col; + uint8_t temp_control_reg[0x13] = {0};//led control register start address + 0x12 bytes + xprintf("-------------\n"); + xprintf("write page %X\n", page); + + for(i=0;i Date: Mon, 10 Apr 2017 22:23:45 -0700 Subject: [PATCH 012/238] led init code missing pwm writes for Frame 1 --- .../infinity60/keymaps/jpetermans/keymap.c | 32 ++++++++++++++----- keyboards/infinity60/led_controller.c | 25 ++++++++++----- 2 files changed, 41 insertions(+), 16 deletions(-) diff --git a/keyboards/infinity60/keymaps/jpetermans/keymap.c b/keyboards/infinity60/keymaps/jpetermans/keymap.c index cfc288916..87a1afc3e 100644 --- a/keyboards/infinity60/keymaps/jpetermans/keymap.c +++ b/keyboards/infinity60/keymaps/jpetermans/keymap.c @@ -62,7 +62,7 @@ const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS] = { _______,_______,_______,_______,_______,_______,_______, _______, _______, _______,KC_MUTE, KC_VOLD, KC_VOLU,_______,KC_NO,\ _______,_______,_______,_______,_______,_______,_______, _______, _______, _______,_______, _______,_______,_______,\ _______,_______,_______,_______,_______,_______,_______, _______, _______, _______,_______, _______,_______, \ - _______,_______,F(2),F(3),F(4),_______,_______, _______, KC_MPRV, KC_MNXT,KC_MSTP, _______,KC_NO, \ + _______,_______,F(2),F(3),F(4),F(5),F(6),F(7), KC_MPRV, KC_MNXT,KC_MSTP, _______,KC_NO, \ _______,_______,_______, KC_MPLY, _______,_______, _______,_______ \ ), /* ~ */ @@ -91,7 +91,9 @@ enum function_id { enum macro_id { ACTION_LEDS_ALL, ACTION_LEDS_GAME, - ACTION_LED_1 + ACTION_LEDS_NAV, + ACTION_LEDS_MEDIA, + ACTION_LEDS_NUMPAD }; /* ================================== @@ -170,7 +172,9 @@ const uint16_t fn_actions[] = { [1] = ACTION_LAYER_MODS(_TILDE, MOD_LSFT), [2] = ACTION_FUNCTION(ACTION_LEDS_ALL), [3] = ACTION_FUNCTION(ACTION_LEDS_GAME), - [4] = ACTION_FUNCTION(ACTION_LED_1) + [4] = ACTION_FUNCTION(ACTION_LEDS_MEDIA), + [5] = ACTION_FUNCTION(ACTION_LEDS_NAV), + [6] = ACTION_FUNCTION(ACTION_LEDS_NUMPAD) }; @@ -182,23 +186,35 @@ void action_function(keyrecord_t *record, uint8_t id, uint8_t opt) { case ACTION_LEDS_ALL: if(record->event.pressed) { // signal the LED controller thread - msg=(TOGGLE_LED << 8) | 12; + msg=(TOGGLE_ALL << 8) | 0; chMBPost(&led_mailbox, msg, TIME_IMMEDIATE); } break; case ACTION_LEDS_GAME: if(record->event.pressed) { // signal the LED controller thread - msg=(TOGGLE_LAYER_LEDS << 8) | 5; + msg=(TOGGLE_LED << 8) | 11; chMBPost(&led_mailbox, msg, TIME_IMMEDIATE); } break; - case ACTION_LED_1: + case ACTION_LEDS_NAV: if(record->event.pressed) { // signal the LED controller thread - chMBPost(&led_mailbox, ADDR_LED_1, TIME_IMMEDIATE); + msg=(TOGGLE_LAYER_LEDS << 8) | 3; + chMBPost(&led_mailbox, msg, TIME_IMMEDIATE); + } + case ACTION_LEDS_NUMPAD: + if(record->event.pressed) { + // signal the LED controller thread + msg=(TOGGLE_LAYER_LEDS << 8) | 4; + chMBPost(&led_mailbox, msg, TIME_IMMEDIATE); + } + case ACTION_LEDS_MEDIA: + if(record->event.pressed) { + // signal the LED controller thread + msg=(TOGGLE_LAYER_LEDS << 8) | 5; + chMBPost(&led_mailbox, msg, TIME_IMMEDIATE); } - break; } } diff --git a/keyboards/infinity60/led_controller.c b/keyboards/infinity60/led_controller.c index 03f061a20..2a7431a4c 100644 --- a/keyboards/infinity60/led_controller.c +++ b/keyboards/infinity60/led_controller.c @@ -122,7 +122,6 @@ msg_t is31_write_register(uint8_t page, uint8_t reg, uint8_t data) { is31_select_page(page); tx[0] = reg; tx[1] = data; - xprintf("page display: %X\n", page); return i2cMasterTransmitTimeout(&I2CD1, IS31_ADDR_DEFAULT, tx, 2, NULL, 0, US2ST(IS31_TIMEOUT)); } @@ -379,6 +378,8 @@ void set_led_bit (uint8_t *led_control_reg, uint8_t msg_led, uint8_t toggle_on) ////first byte is register address 0x00 row_byte = ((msg_led / 10) % 10 - 1 ) * 2 + 1; column_bit = 1<<(msg_led % 10 - 1); + xprintf("row %X\n", row_byte); + xprintf("col %X\n", column_bit); if (toggle_on) { led_control_reg[row_byte] |= 1<<(column_bit); @@ -451,16 +452,24 @@ void led_controller_init(void) { /* initialise IS31 chip */ is31_init(); - /* enable LEDs on all pages */ - full_page[0] = 0; - __builtin_memcpy(full_page+1, is31_ic60_leds_mask, 0x12); - for(i=0; i<8; i++) { - is31_write_data(i, full_page, 1+0x12); - } - //set Display Option Register so all pwm intensity is controlled from Frame 1 is31_write_register(IS31_FUNCTIONREG, IS31_REG_DISPLAYOPT, IS31_REG_DISPLAYOPT_INTENSITY_SAME); + /* set full pwm on Frame 1 */ + for(i=1; i<9; i++) { + pwm_reg_array[i]=0xFF; + } + for(i=0; i<8; i++) { + pwm_reg_array[0] = 0x24 + (i * 0x10);//first byte of 9 bytes must be register address + is31_write_data(0, pwm_reg_array, 9); + chThdSleepMilliseconds(5); + } + + //set all led bits on for Frame 2 LEDS_ALL + full_page[0] = 0; + __builtin_memcpy(full_page+1, is31_ic60_leds_mask, 0x12); + is31_write_data(1, full_page, 1+0x12); + /* enable breathing when the displayed page changes */ // Fade-in Fade-out, time = 26ms * 2^N, N=3 is31_write_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL1, (3<<4)|3); From 0881f2dbfa6887347afad577def01c246050df61 Mon Sep 17 00:00:00 2001 From: jpetermans Date: Tue, 11 Apr 2017 23:33:48 -0700 Subject: [PATCH 013/238] fixed write_led_page col shift, added option for lock led display --- .../infinity60/keymaps/jpetermans/keymap.c | 24 +++- keyboards/infinity60/led_controller.c | 109 ++++++------------ keyboards/infinity60/led_controller.h | 1 + 3 files changed, 53 insertions(+), 81 deletions(-) diff --git a/keyboards/infinity60/keymaps/jpetermans/keymap.c b/keyboards/infinity60/keymaps/jpetermans/keymap.c index 87a1afc3e..2eb66b506 100644 --- a/keyboards/infinity60/keymaps/jpetermans/keymap.c +++ b/keyboards/infinity60/keymaps/jpetermans/keymap.c @@ -93,7 +93,8 @@ enum macro_id { ACTION_LEDS_GAME, ACTION_LEDS_NAV, ACTION_LEDS_MEDIA, - ACTION_LEDS_NUMPAD + ACTION_LEDS_NUMPAD, + ACTION_LEDS_TEST }; /* ================================== @@ -174,7 +175,9 @@ const uint16_t fn_actions[] = { [3] = ACTION_FUNCTION(ACTION_LEDS_GAME), [4] = ACTION_FUNCTION(ACTION_LEDS_MEDIA), [5] = ACTION_FUNCTION(ACTION_LEDS_NAV), - [6] = ACTION_FUNCTION(ACTION_LEDS_NUMPAD) + [6] = ACTION_FUNCTION(ACTION_LEDS_NUMPAD), + [7] = ACTION_FUNCTION(ACTION_LEDS_TEST) + }; @@ -193,7 +196,14 @@ void action_function(keyrecord_t *record, uint8_t id, uint8_t opt) { case ACTION_LEDS_GAME: if(record->event.pressed) { // signal the LED controller thread - msg=(TOGGLE_LED << 8) | 11; + msg=(TOGGLE_LAYER_LEDS << 8) | 6; + chMBPost(&led_mailbox, msg, TIME_IMMEDIATE); + } + break; + case ACTION_LEDS_MEDIA: + if(record->event.pressed) { + // signal the LED controller thread + msg=(TOGGLE_LAYER_LEDS << 8) | 5; chMBPost(&led_mailbox, msg, TIME_IMMEDIATE); } break; @@ -203,18 +213,21 @@ void action_function(keyrecord_t *record, uint8_t id, uint8_t opt) { msg=(TOGGLE_LAYER_LEDS << 8) | 3; chMBPost(&led_mailbox, msg, TIME_IMMEDIATE); } + break; case ACTION_LEDS_NUMPAD: if(record->event.pressed) { // signal the LED controller thread msg=(TOGGLE_LAYER_LEDS << 8) | 4; chMBPost(&led_mailbox, msg, TIME_IMMEDIATE); } - case ACTION_LEDS_MEDIA: + break; + case ACTION_LEDS_TEST: if(record->event.pressed) { // signal the LED controller thread - msg=(TOGGLE_LAYER_LEDS << 8) | 5; + msg=(TOGGLE_LED << 8) | 12; chMBPost(&led_mailbox, msg, TIME_IMMEDIATE); } + break; } } @@ -236,6 +249,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) // Runs just one time when the keyboard initializes. void matrix_init_user(void) { + xprintf("init start"); led_controller_init(); diff --git a/keyboards/infinity60/led_controller.c b/keyboards/infinity60/led_controller.c index 2a7431a4c..89c477ee7 100644 --- a/keyboards/infinity60/led_controller.c +++ b/keyboards/infinity60/led_controller.c @@ -101,7 +101,7 @@ const uint8_t pwm_levels[5] = { }; // array to write to pwm register -uint8_t pwm_reg_array[9] = {0}; +uint8_t pwm_register_array[9] = {0}; /* ============================ @@ -147,10 +147,6 @@ void is31_init(void) { // software shutdown is31_write_register(IS31_FUNCTIONREG, IS31_REG_SHUTDOWN, 0); chThdSleepMilliseconds(10); - // TODO: This already done above, remove? - // zero function page, all registers - is31_write_data(IS31_FUNCTIONREG, full_page, 0xD + 1); - chThdSleepMilliseconds(10); // software shutdown disable (i.e. turn stuff on) is31_write_register(IS31_FUNCTIONREG, IS31_REG_SHUTDOWN, IS31_REG_SHUTDOWN_ON); chThdSleepMilliseconds(10); @@ -176,7 +172,7 @@ static THD_FUNCTION(LEDthread, arg) { uint8_t i, page; //persistent status variables - uint8_t backlight_status, lock_status, led_step, active_layer; + uint8_t backlight_status, lock_status, led_step_status, layer_status; uint8_t led_control_reg[0x13] = {0};//led control register start address + 0x12 bytes //mailbox variables @@ -191,8 +187,8 @@ static THD_FUNCTION(LEDthread, arg) { // initialize persistent variables backlight_status = 0; lock_status = 0;//TODO: does keyboard remember locks? -led_step = 4; //full brightness -active_layer = 0; +led_step_status = 4; //full brightness +layer_status = 0; while(true) { // wait for a message (asynchronous) @@ -213,13 +209,13 @@ active_layer = 0; case TOGGLE_LED: //TODO: toggle existing indicator off, or let user do this, but write frame 7 for every led change //turn on single led, msg_led = row/col of led + xprintf("TOGGLE_LED\n"); set_led_bit(led_control_reg, msg_led, 1); is31_write_data (7, led_control_reg, 0x12+1); is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, 7); - active_layer = 7; + layer_status = 7; is31_read_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, &temp); - xprintf("page display: %X\n", temp); break; case TOGGLE_ALL: @@ -227,40 +223,39 @@ active_layer = 0; //msg_led = unused, TODO: consider using msg_led to toggle layer display is31_read_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, &temp); - xprintf("temp: %X\n", temp); //if LED_ALL is on then toggle off, any other layer, turn on LED_ALL if(temp == 1) { - xprintf("page display true: %X\n", temp); is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, 0); } else { - xprintf("page display false: %X\n", temp); is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, 1); } is31_read_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, &temp); - xprintf("page display: %X\n", temp); break; case TOGGLE_BACKLIGHT: //msg_led = unused + //TODO: consider Frame 0 as on/off layer and toggle led control register here + xprintf("TOGGLE_BACKLIGHT\n"); backlight_status ^= 1; is31_read_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, &temp); - active_layer = temp; + layer_status = temp; - page = backlight_status == 0 ? 0 : active_layer; + page = backlight_status == 0 ? 0 : layer_status; is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, page); break; case TOGGLE_LAYER_LEDS://show layer indicator or full map of layer keys. //TODO: change so user can flag which they want, indiv or full map in fn_actions //msg_led = layer to toggle on + xprintf("TOGGLE_LAYER_LEDS\n"); is31_read_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, &temp); if(temp == msg_led) { is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, 7); - active_layer = 7; + layer_status = 7; } else { is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, msg_led); - active_layer = msg_led; + layer_status = msg_led; } break; @@ -275,29 +270,27 @@ active_layer = 0; case STEP_BRIGHTNESS: //pwm_levels[] bounds checking, loop through array //TODO: find a cleaner way to walk through this logic - if (msg_led == 0) { - if (led_step == 0) { - led_step = 4; - } else { - led_step--; - } + if (msg_led == 0 && led_step_status == 0) { + led_step_status = 4; } else { - if (led_step == 4) { - led_step = 0; - } else { - led_step++; - } + led_step_status--; + } + + if (msg_led == 1 && led_step_status == 4) { + led_step_status = 0; + } else { + led_step_status++; } //TODO: this seems a messy way to populate the pwm register + //mimic whitefox init which uses memcpy //populate the 9 byte rows to be written to each pin, first byte is register (pin) address for(i=1; i<9; i++) { - pwm_reg_array[i]=pwm_levels[led_step]; + pwm_register_array[i]=pwm_levels[led_step_status]; } for(i=0; i<8; i++) { - pwm_reg_array[0] = 0x24 + (i * 0x10);//first byte of 9 bytes must be register address - is31_write_data(0, pwm_reg_array, 9); - chThdSleepMilliseconds(5); + pwm_register_array[0] = 0x24 + (i * 0x10);//first byte of 9 bytes must be register address + is31_write_data(0, pwm_register_array, 9);//first page controls pwm in all pages (init Display Option register) } break; @@ -330,36 +323,6 @@ active_layer = 0; case LED_MSG_SLEEP_LED_OFF: // should not get here; wakeup should be received in the branch above break; break; - default: - //TODO: individual led state unchanged if page arrays are selected in code above - //avoidable if full pages are written on the fly - //or use pg8 for individual leds, have pointer to currently on led address for toggling - if (msg == 0x59 || msg == 0x84) { - //toggle lock keys on all layers - for (i=0,i<8,i++) { - is31_read_register(0, msg, &temp); - pwm = (temp > 0x00 ? 0x00 : 0xFF); - is31_write_register(i,msg,pwm); - } - - } else if(msg >= 0x24) { - xprintf("Power pre-read\ntemp: %X - msg: %X - pwm: %X\n", temp, msg, pwm); - is31_read_register(7, msg, &temp); - xprintf("Post-read\ntemp: %X - msg: %X - pwm: %X\n", temp, msg, pwm); - if (msg == active_led) { - //toggle led power - pwm = (temp > 0x00 ? 0x00 : 0xFF); - - //Use 8th led page for individual led indicators - is31_write_register(7, msg, pwm); - } else { - is31_write_register(7, active_led, 0x00); - is31_write_register(7, msg, 0xFF); - } - xprintf("Power post-change\ntemp: %X - msg: %X - pwm: %X\n", temp, msg, pwm); - is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, 7); - } - break; */ } xprintf("--------------------\n"); @@ -378,8 +341,6 @@ void set_led_bit (uint8_t *led_control_reg, uint8_t msg_led, uint8_t toggle_on) ////first byte is register address 0x00 row_byte = ((msg_led / 10) % 10 - 1 ) * 2 + 1; column_bit = 1<<(msg_led % 10 - 1); - xprintf("row %X\n", row_byte); - xprintf("col %X\n", column_bit); if (toggle_on) { led_control_reg[row_byte] |= 1<<(column_bit); @@ -393,7 +354,7 @@ void set_lock_leds(uint8_t *led_control_reg, uint8_t lock_status) { switch (lock_status) { case 1: - set_led_bit(led_control_reg, CAPS_LOCK_LED_ADDRESS, 1);//TODO: define lock addresses by matrix#, and loop for all frames + set_led_bit(led_control_reg, CAPS_LOCK_LED_ADDRESS, 1); set_led_bit(led_control_reg, NUM_LOCK_LED_ADDRESS, 0); break; case 2: @@ -406,9 +367,8 @@ void set_lock_leds(uint8_t *led_control_reg, uint8_t lock_status) { break; } - for(i=1; i<8; i++) { //keep LED_OFF layer all off, including locks + for(i=BACKLIGHT_OFF_LOCK_LED_OFF; i<8; i++) { //set in led_controller.h is31_write_data (i, led_control_reg, 0x12+1); - chThdSleepMilliseconds(5); } } @@ -417,18 +377,15 @@ void write_led_page (uint8_t page, const uint8_t *led_array, uint8_t led_count) uint8_t i; uint8_t row, col; uint8_t temp_control_reg[0x13] = {0};//led control register start address + 0x12 bytes - xprintf("-------------\n"); - xprintf("write page %X\n", page); for(i=0;i Date: Wed, 12 Apr 2017 23:32:38 -0700 Subject: [PATCH 014/238] Updated lock led init --- keyboards/infinity60/led.c | 28 ++++++-- keyboards/infinity60/led_controller.c | 100 +++++++++++++++++--------- keyboards/infinity60/led_controller.h | 11 +-- 3 files changed, 95 insertions(+), 44 deletions(-) diff --git a/keyboards/infinity60/led.c b/keyboards/infinity60/led.c index d2f554549..c78e2d119 100644 --- a/keyboards/infinity60/led.c +++ b/keyboards/infinity60/led.c @@ -16,6 +16,7 @@ along with this program. If not, see . */ #include "hal.h" +#include "print.h" #include "led.h" @@ -26,6 +27,7 @@ along with this program. If not, see . * In particular, I2C functions (interrupt-driven) should NOT be called from here. */ void led_set(uint8_t usb_led) { + msg_t msg; /* // PTA5: LED (1:on/0:off) GPIOA->PDDR |= (1<<1); @@ -36,18 +38,32 @@ void led_set(uint8_t usb_led) { GPIOA->PCOR |= (1<<5); } */ -//TODO: How does this test if led is set -//usb_led --> led_set(usb_led) <-- chibios/host_keyboard_leds <-- keyboard_leds from usbSetupTransfer -//keyboard_leds is enum'd in chibios/main.c - if (usb_led & (1<. #include "ch.h" #include "hal.h" #include "print.h" +#include "led.h" #include "led_controller.h" @@ -57,11 +58,11 @@ along with this program. If not, see . * The usual Caps Lock position is C4-6, so the address is * 0x24 + (4-1)*0x10 + (8-1) = 0x59 */ #if !defined(CAPS_LOCK_LED_ADDRESS) -#define CAPS_LOCK_LED_ADDRESS 0x46 +#define CAPS_LOCK_LED_ADDRESS 46 #endif #if !defined(NUM_LOCK_LED_ADDRESS) -#define NUM_LOCK_LED_ADDRESS 0x85 +#define NUM_LOCK_LED_ADDRESS 85 #endif /* Which LED should breathe during sleep */ @@ -215,7 +216,6 @@ layer_status = 0; is31_write_data (7, led_control_reg, 0x12+1); is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, 7); layer_status = 7; - is31_read_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, &temp); break; case TOGGLE_ALL: @@ -259,12 +259,18 @@ layer_status = 0; } break; - case TOGGLE_LOCK_LED: - //msg_led = 0-3 for lock flags - lock_status ^= msg_led; //TODO: confirm toggling works and doesn't get out of sync - set_lock_leds(led_control_reg, lock_status); + case TOGGLE_NUM_LOCK: + //msg_led = 0 or 1, off/on + //TODO: confirm toggling works and doesn't get out of sync + set_lock_leds(USB_LED_NUM_LOCK, msg_led); break; + case TOGGLE_CAPS_LOCK: + //msg_led = 0 or 1, off/on + //TODO: confirm toggling works and doesn't get out of sync + set_lock_leds(USB_LED_CAPS_LOCK, msg_led); + break; + case MODE_BREATH: break; case STEP_BRIGHTNESS: @@ -335,11 +341,10 @@ layer_status = 0; * ======================== */ void set_led_bit (uint8_t *led_control_reg, uint8_t msg_led, uint8_t toggle_on) { uint8_t row_byte, column_bit; - //msg_led tens column is pin#, A-control register is every other 8 bits + //msg_led tens column is pin# //ones column is bit position in 8-bit mask - //control register will be one bit shifted into position along register's full 0x12 bytes - ////first byte is register address 0x00 - row_byte = ((msg_led / 10) % 10 - 1 ) * 2 + 1; + //first byte is register address 0x00 + row_byte = ((msg_led / 10) % 10 - 1 ) * 2 + 1;// A register is every other 8 bits column_bit = 1<<(msg_led % 10 - 1); if (toggle_on) { @@ -349,31 +354,61 @@ void set_led_bit (uint8_t *led_control_reg, uint8_t msg_led, uint8_t toggle_on) } } -void set_lock_leds(uint8_t *led_control_reg, uint8_t lock_status) { - uint8_t i; +//TODO: not toggling off correctly +//TODO: confirm led_off page still has FF pwm for all +void set_lock_leds(uint8_t lock_type, uint8_t lock_status) { + uint8_t page; + uint8_t led_addr, temp; + uint8_t control_reg[2] = {0};//register address and led bits - switch (lock_status) { - case 1: - set_led_bit(led_control_reg, CAPS_LOCK_LED_ADDRESS, 1); - set_led_bit(led_control_reg, NUM_LOCK_LED_ADDRESS, 0); - break; - case 2: - set_led_bit(led_control_reg, CAPS_LOCK_LED_ADDRESS, 0); - set_led_bit(led_control_reg, NUM_LOCK_LED_ADDRESS, 1); - break; - case 3: - set_led_bit(led_control_reg, NUM_LOCK_LED_ADDRESS, 1); - set_led_bit(led_control_reg, CAPS_LOCK_LED_ADDRESS, 1); - break; - } + switch(lock_type) { + case USB_LED_NUM_LOCK: + led_addr = NUM_LOCK_LED_ADDRESS; + break; + case USB_LED_CAPS_LOCK: + led_addr = CAPS_LOCK_LED_ADDRESS; + break; + #ifdef SCROLL_LOCK_LED_ADDRESS + case USB_LED_SCROLL_LOCK: + led_addr = SCROLL_LOCK_LED_ADDRESS; + break; + #endif + #ifdef COMPOSE_LED_ADDRESS + case USB_LED_COMPOSE: + led_addr = COMPOSE_LED_ADDRESS; + break; + #endif + #ifdef SCROLL_LOCK_LED_ADDRESS + case USB_LED_KANA: + led_addr = KANA_LED_ADDRESS; + break; + #endif + } + xprintf("led_addr: %X\n", led_addr); + chThdSleepMilliseconds(30); + control_reg[0] = ((led_addr / 10) % 10 - 1 ) * 0x02;// A-register is every other byte + xprintf("control_reg: %X\n", control_reg[0]); + chThdSleepMilliseconds(30); - for(i=BACKLIGHT_OFF_LOCK_LED_OFF; i<8; i++) { //set in led_controller.h - is31_write_data (i, led_control_reg, 0x12+1); + for(page=BACKLIGHT_OFF_LOCK_LED_OFF; page<8; page++) { //set in led_controller.h + is31_read_register(page,control_reg[0],&temp);//need to maintain status of leds in this row (1 byte) + chThdSleepMilliseconds(30); + xprintf("1lock byte: %X\n", temp); + chThdSleepMilliseconds(30); + if (lock_status) { + temp |= 1<<(led_addr % 10 - 1); + } else { + temp &= ~1<<(led_addr % 10 - 1); + } + chThdSleepMilliseconds(30); + xprintf("2lock byte: %X\n", temp); + chThdSleepMilliseconds(30); + control_reg[1] = temp; + is31_write_data (page, control_reg, 0x02); } } void write_led_page (uint8_t page, const uint8_t *led_array, uint8_t led_count) { -//TODO: init function that accepts array of led addresses and sets them by row uint8_t i; uint8_t row, col; uint8_t temp_control_reg[0x13] = {0};//led control register start address + 0x12 bytes @@ -433,9 +468,8 @@ void led_controller_init(void) { is31_write_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL2, IS31_REG_BREATHCTRL2_ENABLE|3); // clean up the lock LEDs - //TODO: adjust for new addressing and additional frames - //is31_write_register(1, CAPS_LOCK_LED_ADDRESS, 0); - //is31_write_register(2, CAPS_LOCK_LED_ADDRESS, 0); + set_lock_leds(USB_LED_NUM_LOCK, 0); + set_lock_leds(USB_LED_CAPS_LOCK, 0); /* more time consuming LED processing should be offloaded into * a thread, with asynchronous messaging. */ diff --git a/keyboards/infinity60/led_controller.h b/keyboards/infinity60/led_controller.h index e9d897303..740862018 100644 --- a/keyboards/infinity60/led_controller.h +++ b/keyboards/infinity60/led_controller.h @@ -32,9 +32,9 @@ msg_t is31_read_register(uint8_t page, uint8_t reg, uint8_t *result); void led_controller_init(void); -#define CAPS_LOCK_LED_ADDRESS 0x46 -#define NUM_LOCK_LED_ADDRESS 0x85 -#define BACKLIGHT_OFF_LOCK_LED_OFF 1 //set to 0 to show lock leds even if backlight off +#define CAPS_LOCK_LED_ADDRESS 46 +#define NUM_LOCK_LED_ADDRESS 85 +#define BACKLIGHT_OFF_LOCK_LED_OFF 0 //set to 0 to show lock leds even if backlight off /* ============================= * IS31 chip related definitions @@ -93,7 +93,7 @@ void led_controller_init(void); extern mailbox_t led_mailbox; void set_led_bit (uint8_t *led_control_reg, uint8_t led_msg, uint8_t toggle_on); -void set_lock_leds (uint8_t *led_control_reg, uint8_t lock_status); +void set_lock_leds (uint8_t lock_type, uint8_t lock_status); void write_led_page (uint8_t page, const uint8_t *led_array, uint8_t led_count); // constants for signaling the LED controller thread @@ -103,7 +103,8 @@ enum led_msg_t { TOGGLE_ALL, TOGGLE_BACKLIGHT, TOGGLE_LAYER_LEDS, - TOGGLE_LOCK_LED, + TOGGLE_NUM_LOCK, + TOGGLE_CAPS_LOCK, MODE_BREATH, STEP_BRIGHTNESS }; From 1b1adf35bb746a875c2b846e1b1b405075c94847 Mon Sep 17 00:00:00 2001 From: jpetermans Date: Thu, 13 Apr 2017 17:15:24 -0700 Subject: [PATCH 015/238] more flexible led processing functions, all and on/off/toggle functioning --- .../infinity60/keymaps/jpetermans/keymap.c | 4 +- keyboards/infinity60/led.c | 14 +- keyboards/infinity60/led_controller.c | 145 +++++++++++------- keyboards/infinity60/led_controller.h | 10 +- 4 files changed, 96 insertions(+), 77 deletions(-) diff --git a/keyboards/infinity60/keymaps/jpetermans/keymap.c b/keyboards/infinity60/keymaps/jpetermans/keymap.c index 2eb66b506..6f14b66cb 100644 --- a/keyboards/infinity60/keymaps/jpetermans/keymap.c +++ b/keyboards/infinity60/keymaps/jpetermans/keymap.c @@ -210,14 +210,14 @@ void action_function(keyrecord_t *record, uint8_t id, uint8_t opt) { case ACTION_LEDS_NAV: if(record->event.pressed) { // signal the LED controller thread - msg=(TOGGLE_LAYER_LEDS << 8) | 3; + msg=(OFF_LED << 8) | 12; chMBPost(&led_mailbox, msg, TIME_IMMEDIATE); } break; case ACTION_LEDS_NUMPAD: if(record->event.pressed) { // signal the LED controller thread - msg=(TOGGLE_LAYER_LEDS << 8) | 4; + msg=(ON_LED << 8) | 12; chMBPost(&led_mailbox, msg, TIME_IMMEDIATE); } break; diff --git a/keyboards/infinity60/led.c b/keyboards/infinity60/led.c index c78e2d119..92069dc59 100644 --- a/keyboards/infinity60/led.c +++ b/keyboards/infinity60/led.c @@ -16,7 +16,6 @@ along with this program. If not, see . */ #include "hal.h" -#include "print.h" #include "led.h" @@ -28,16 +27,7 @@ along with this program. If not, see . */ void led_set(uint8_t usb_led) { msg_t msg; -/* - // PTA5: LED (1:on/0:off) - GPIOA->PDDR |= (1<<1); - PORTA->PCR[5] |= PORTx_PCRn_DSE | PORTx_PCRn_MUX(1); - if (usb_led & (1<PSOR |= (1<<5); - } else { - GPIOA->PCOR |= (1<<5); - } - */ + if (usb_led & (1< 0) {//check current led page to prevent double blink + is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, 7); + } + layer_status = 7; + break; + case ON_LED: + xprintf("ON_LED\n"); + set_led_bit(7, control_register_word, msg_led, 1); + is31_write_data (7, control_register_word, 0x02); + if (layer_status > 7) { + is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, 7); + } + layer_status = 7; + break; case TOGGLE_LED: - //TODO: toggle existing indicator off, or let user do this, but write frame 7 for every led change - //turn on single led, msg_led = row/col of led xprintf("TOGGLE_LED\n"); - set_led_bit(led_control_reg, msg_led, 1); + set_led_bit(7, control_register_word, msg_led, 2); - is31_write_data (7, led_control_reg, 0x12+1); - is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, 7); + is31_write_data (7, control_register_word, 0x02); + if (layer_status > 7) { + is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, 7); + } layer_status = 7; break; case TOGGLE_ALL: xprintf("TOGGLE_ALL\n"); //msg_led = unused, TODO: consider using msg_led to toggle layer display - is31_read_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, &temp); - //if LED_ALL is on then toggle off, any other layer, turn on LED_ALL - if(temp == 1) { - is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, 0); + is31_read_register(0, 0x00, &temp);//if first byte is on, then toggle frame 1 off + + led_control_reg[0] = 0; + if (temp==0) { + xprintf("all leds on"); + __builtin_memcpy(led_control_reg+1, all_on_leds_mask, 0x12); } else { - is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, 1); + xprintf("all leds off"); + __builtin_memset(led_control_reg+1, 0, 0x12); } - is31_read_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, &temp); + + is31_write_data(0, led_control_reg, 0x13); + if (layer_status > 0) { + is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, 0); + } + layer_status=0; + //TODO: Double blink when all on break; case TOGGLE_BACKLIGHT: //msg_led = unused //TODO: consider Frame 0 as on/off layer and toggle led control register here + //TODO: need to test tracking of active layer with layer_state from qmk xprintf("TOGGLE_BACKLIGHT\n"); backlight_status ^= 1; is31_read_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, &temp); @@ -274,6 +303,7 @@ layer_status = 0; case MODE_BREATH: break; case STEP_BRIGHTNESS: + //TEST: Step brightness code //pwm_levels[] bounds checking, loop through array //TODO: find a cleaner way to walk through this logic if (msg_led == 0 && led_step_status == 0) { @@ -336,30 +366,42 @@ layer_status = 0; } -/* ======================== - * led bit processing - * ======================== */ -void set_led_bit (uint8_t *led_control_reg, uint8_t msg_led, uint8_t toggle_on) { - uint8_t row_byte, column_bit; - //msg_led tens column is pin# - //ones column is bit position in 8-bit mask - //first byte is register address 0x00 - row_byte = ((msg_led / 10) % 10 - 1 ) * 2 + 1;// A register is every other 8 bits - column_bit = 1<<(msg_led % 10 - 1); +/* ============================== + * led processing functions + * ============================== */ - if (toggle_on) { - led_control_reg[row_byte] |= 1<<(column_bit); - } else { - led_control_reg[row_byte] &= ~1<<(column_bit); +void set_led_bit (uint8_t page, uint8_t *led_control_reg, uint8_t led_addr, uint8_t action) { + //returns 2 bytes led control register address and byte mask to write + + uint8_t control_reg_addr, column_bit, column_byte, temp; + //first byte is led control register address 0x00 + //msg_led tens column is pin#, ones column is bit position in 8-bit mask + control_reg_addr = ((led_addr / 10) % 10 - 1 ) * 0x02;// A-register is every other byte + column_bit = 1<<(led_addr % 10 - 1); + + is31_read_register(page,control_reg_addr,&temp);//need to maintain status of leds in this row (1 byte) + column_byte = temp; + + switch(action) { + case 0: + column_byte &= ~1<<(column_bit); + break; + case 1: + column_byte |= 1<<(column_bit); + break; + case 2: + column_byte ^= 1<<(column_bit); + break; } + + led_control_reg[0] = control_reg_addr; + led_control_reg[1] = column_byte; } -//TODO: not toggling off correctly -//TODO: confirm led_off page still has FF pwm for all -void set_lock_leds(uint8_t lock_type, uint8_t lock_status) { - uint8_t page; - uint8_t led_addr, temp; - uint8_t control_reg[2] = {0};//register address and led bits +void set_lock_leds(uint8_t lock_type, uint8_t led_on) { + uint8_t page, led_addr; + uint8_t led_control_write[2] = {0}; + //TODO: consolidate control register to top level array vs. three scattered around switch(lock_type) { case USB_LED_NUM_LOCK: @@ -384,44 +426,30 @@ void set_lock_leds(uint8_t lock_type, uint8_t lock_status) { break; #endif } - xprintf("led_addr: %X\n", led_addr); - chThdSleepMilliseconds(30); - control_reg[0] = ((led_addr / 10) % 10 - 1 ) * 0x02;// A-register is every other byte - xprintf("control_reg: %X\n", control_reg[0]); - chThdSleepMilliseconds(30); for(page=BACKLIGHT_OFF_LOCK_LED_OFF; page<8; page++) { //set in led_controller.h - is31_read_register(page,control_reg[0],&temp);//need to maintain status of leds in this row (1 byte) - chThdSleepMilliseconds(30); - xprintf("1lock byte: %X\n", temp); - chThdSleepMilliseconds(30); - if (lock_status) { - temp |= 1<<(led_addr % 10 - 1); - } else { - temp &= ~1<<(led_addr % 10 - 1); - } - chThdSleepMilliseconds(30); - xprintf("2lock byte: %X\n", temp); - chThdSleepMilliseconds(30); - control_reg[1] = temp; - is31_write_data (page, control_reg, 0x02); + //TODO: check if frame2 (or frame1, first byte all on), and ignore if true + //also if BACKLIGHT_OFF_LOCK_LED_OFF set + set_led_bit(page,led_control_write,led_addr,led_on); + is31_write_data (page, led_control_write, 0x02); } } void write_led_page (uint8_t page, const uint8_t *led_array, uint8_t led_count) { uint8_t i; uint8_t row, col; - uint8_t temp_control_reg[0x13] = {0};//led control register start address + 0x12 bytes + uint8_t led_control_register[0x13] = {0};//led control register start address + 0x12 bytes for(i=0;i Date: Thu, 13 Apr 2017 17:51:37 -0700 Subject: [PATCH 016/238] fixed bit shift in led_set_bit --- keyboards/infinity60/led_controller.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/keyboards/infinity60/led_controller.c b/keyboards/infinity60/led_controller.c index eb3ccafc1..e98d8de50 100644 --- a/keyboards/infinity60/led_controller.c +++ b/keyboards/infinity60/led_controller.c @@ -376,26 +376,40 @@ void set_led_bit (uint8_t page, uint8_t *led_control_reg, uint8_t led_addr, uint uint8_t control_reg_addr, column_bit, column_byte, temp; //first byte is led control register address 0x00 //msg_led tens column is pin#, ones column is bit position in 8-bit mask + chThdSleepMilliseconds(10); + xprintf("led_addr: %d ", led_addr); control_reg_addr = ((led_addr / 10) % 10 - 1 ) * 0x02;// A-register is every other byte column_bit = 1<<(led_addr % 10 - 1); is31_read_register(page,control_reg_addr,&temp);//need to maintain status of leds in this row (1 byte) + chThdSleepMilliseconds(10); + xprintf("col_bit: %X ", column_bit); column_byte = temp; + chThdSleepMilliseconds(10); + xprintf("action: %X ", action); switch(action) { case 0: - column_byte &= ~1<<(column_bit); + xprintf("off-"); + chThdSleepMilliseconds(10); + column_byte &= ~column_bit; break; case 1: - column_byte |= 1<<(column_bit); + xprintf("on-"); + chThdSleepMilliseconds(10); + column_byte |= column_bit; break; case 2: - column_byte ^= 1<<(column_bit); + xprintf("toggle-"); + chThdSleepMilliseconds(10); + column_byte ^= column_bit; break; } led_control_reg[0] = control_reg_addr; led_control_reg[1] = column_byte; + chThdSleepMilliseconds(10); + xprintf("set_bit row: %X set_bit col: %X\n", led_control_reg[0], led_control_reg[1]); } void set_lock_leds(uint8_t lock_type, uint8_t led_on) { @@ -427,11 +441,13 @@ void set_lock_leds(uint8_t lock_type, uint8_t led_on) { #endif } - for(page=BACKLIGHT_OFF_LOCK_LED_OFF; page<8; page++) { //set in led_controller.h + for(page=0; page<8; page++) { //set in led_controller.h //TODO: check if frame2 (or frame1, first byte all on), and ignore if true //also if BACKLIGHT_OFF_LOCK_LED_OFF set set_led_bit(page,led_control_write,led_addr,led_on); - is31_write_data (page, led_control_write, 0x02); + xprintf("lock_led row: %X lock_led col%X\n", led_control_write[0], led_control_write[1]); + is31_write_data(page, led_control_write, 0x02); + chThdSleepMilliseconds(10); } } From c0ec1756afda7a49848faff23781bf54cd9fa3c3 Mon Sep 17 00:00:00 2001 From: jpetermans Date: Fri, 14 Apr 2017 18:20:12 -0700 Subject: [PATCH 017/238] Added backlight step functionality --- keyboards/infinity60/led_controller.c | 340 +++++++++++++------------- keyboards/infinity60/led_controller.h | 2 +- 2 files changed, 169 insertions(+), 173 deletions(-) diff --git a/keyboards/infinity60/led_controller.c b/keyboards/infinity60/led_controller.c index e98d8de50..cb91f9f35 100644 --- a/keyboards/infinity60/led_controller.c +++ b/keyboards/infinity60/led_controller.c @@ -170,12 +170,12 @@ static THD_FUNCTION(LEDthread, arg) { (void)arg; chRegSetThreadName("LEDthread"); - uint8_t i, page; - uint8_t control_register_word[2] = {0}; + uint8_t i, j, page; + uint8_t control_register_word[2] = {0};//register address - byte to write uint8_t led_control_reg[0x13] = {0};//led control register start address + 0x12 bytes //persistent status variables - uint8_t backlight_status, led_step_status, layer_status; + uint8_t backlight_status, pwm_step_status, layer_status; //mailbox variables uint8_t temp, msg_type, msg_led; @@ -187,9 +187,9 @@ static THD_FUNCTION(LEDthread, arg) { */ // initialize persistent variables -backlight_status = 0; -led_step_status = 4; //full brightness -layer_status = 0; +backlight_status = 0; //start backlight off +pwm_step_status = 4; //full brightness +layer_status = 0; //start frame 0 (all off/on) while(true) { // wait for a message (asynchronous) @@ -202,170 +202,172 @@ layer_status = 0; xprintf("--------------------\n"); xprintf("mailbox fetch\nmsg: %X\n", msg); xprintf("type: %X - led: %X\n", msg_type, msg_led); //test if msg_type is 1 or 2 bytes after mask - switch (msg_type){ - case KEY_LIGHT: - //TODO: lighting key led on keypress - break; - - //turn on/off/toggle single led, msg_led = row/col of led - case OFF_LED: - xprintf("OFF_LED\n"); - set_led_bit(7, control_register_word, msg_led, 0); - is31_write_data (7, control_register_word, 0x02); - if (layer_status > 0) {//check current led page to prevent double blink - is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, 7); - } - layer_status = 7; - break; - case ON_LED: - xprintf("ON_LED\n"); - set_led_bit(7, control_register_word, msg_led, 1); - is31_write_data (7, control_register_word, 0x02); - if (layer_status > 7) { - is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, 7); - } - layer_status = 7; - break; - case TOGGLE_LED: - xprintf("TOGGLE_LED\n"); - set_led_bit(7, control_register_word, msg_led, 2); - is31_write_data (7, control_register_word, 0x02); - if (layer_status > 7) { - is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, 7); - } - layer_status = 7; - break; - - case TOGGLE_ALL: - xprintf("TOGGLE_ALL\n"); - //msg_led = unused, TODO: consider using msg_led to toggle layer display - - is31_read_register(0, 0x00, &temp);//if first byte is on, then toggle frame 1 off - - led_control_reg[0] = 0; - if (temp==0) { - xprintf("all leds on"); - __builtin_memcpy(led_control_reg+1, all_on_leds_mask, 0x12); - } else { - xprintf("all leds off"); - __builtin_memset(led_control_reg+1, 0, 0x12); - } - - is31_write_data(0, led_control_reg, 0x13); - if (layer_status > 0) { - is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, 0); - } - layer_status=0; - //TODO: Double blink when all on - break; - - case TOGGLE_BACKLIGHT: - //msg_led = unused - //TODO: consider Frame 0 as on/off layer and toggle led control register here - //TODO: need to test tracking of active layer with layer_state from qmk - xprintf("TOGGLE_BACKLIGHT\n"); - backlight_status ^= 1; - is31_read_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, &temp); - layer_status = temp; - - page = backlight_status == 0 ? 0 : layer_status; - is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, page); - break; - - case TOGGLE_LAYER_LEDS://show layer indicator or full map of layer keys. - //TODO: change so user can flag which they want, indiv or full map in fn_actions - //msg_led = layer to toggle on - xprintf("TOGGLE_LAYER_LEDS\n"); - is31_read_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, &temp); - - if(temp == msg_led) { - is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, 7); - layer_status = 7; - } else { - is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, msg_led); - layer_status = msg_led; - } + switch (msg_type){ + case KEY_LIGHT: + //TODO: lighting key led on keypress break; - case TOGGLE_NUM_LOCK: - //msg_led = 0 or 1, off/on - //TODO: confirm toggling works and doesn't get out of sync - set_lock_leds(USB_LED_NUM_LOCK, msg_led); - break; - - case TOGGLE_CAPS_LOCK: - //msg_led = 0 or 1, off/on - //TODO: confirm toggling works and doesn't get out of sync - set_lock_leds(USB_LED_CAPS_LOCK, msg_led); - break; - - case MODE_BREATH: - break; - case STEP_BRIGHTNESS: - //TEST: Step brightness code - //pwm_levels[] bounds checking, loop through array - //TODO: find a cleaner way to walk through this logic - if (msg_led == 0 && led_step_status == 0) { - led_step_status = 4; - } else { - led_step_status--; - } - - if (msg_led == 1 && led_step_status == 4) { - led_step_status = 0; - } else { - led_step_status++; - } - - //TODO: this seems a messy way to populate the pwm register - //mimic whitefox init which uses memcpy - //populate the 9 byte rows to be written to each pin, first byte is register (pin) address - for(i=1; i<9; i++) { - pwm_register_array[i]=pwm_levels[led_step_status]; - } - for(i=0; i<8; i++) { - pwm_register_array[0] = 0x24 + (i * 0x10);//first byte of 9 bytes must be register address - is31_write_data(0, pwm_register_array, 9);//first page controls pwm in all pages (init Display Option register) - } - break; - -/* case LED_MSG_SLEEP_LED_ON: - // save current settings - is31_read_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, &save_page); - is31_read_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL1, &save_breath1); - is31_read_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL2, &save_breath2); - // use pages 7 and 8 for (hardware) breathing (assuming they're empty) - is31_write_register(6, BREATHE_LED_ADDRESS, 0xFF); - is31_write_register(7, BREATHE_LED_ADDRESS, 0x00); - is31_write_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL1, (6<<4)|6); - is31_write_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL2, IS31_REG_BREATHCTRL2_ENABLE|3); - retval = MSG_TIMEOUT; - temp = 6; - while(retval == MSG_TIMEOUT) { - // switch to the other page - is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, temp); - temp = (temp == 6 ? 7 : 6); - // the times should be sufficiently long for IS31 to finish switching pages - retval = chMBFetch(&led_mailbox, &msg, MS2ST(temp == 6 ? 4000 : 6000)); + //turn on/off/toggle single led, msg_led = row/col of led + case OFF_LED: + xprintf("OFF_LED\n"); + set_led_bit(7, control_register_word, msg_led, 0); + is31_write_data (7, control_register_word, 0x02); + if (layer_status > 0) {//check current led page to prevent double blink + is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, 7); } - // received a message (should be a wakeup), so restore previous state - chThdSleepMilliseconds(3000); // need to wait until the page change finishes - // note: any other messages are queued - is31_write_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL1, save_breath1); - is31_write_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL2, save_breath2); - is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, save_page); + layer_status = 7; break; - case LED_MSG_SLEEP_LED_OFF: - // should not get here; wakeup should be received in the branch above break; + case ON_LED: + xprintf("ON_LED\n"); + set_led_bit(7, control_register_word, msg_led, 1); + is31_write_data (7, control_register_word, 0x02); + if (layer_status > 7) { + is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, 7); + } + layer_status = 7; break; -*/ + case TOGGLE_LED: + xprintf("TOGGLE_LED\n"); + set_led_bit(7, control_register_word, msg_led, 2); + + is31_write_data (7, control_register_word, 0x02); + if (layer_status > 7) { + is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, 7); + } + layer_status = 7; + break; + + case TOGGLE_ALL: + xprintf("TOGGLE_ALL\n"); + //msg_led = unused + + is31_read_register(0, 0x00, &temp);//if first byte is on, then toggle frame 1 off + + led_control_reg[0] = 0; + if (temp==0) { + xprintf("all leds on"); + __builtin_memcpy(led_control_reg+1, all_on_leds_mask, 0x12); + } else { + xprintf("all leds off"); + __builtin_memset(led_control_reg+1, 0, 0x12); + } + + is31_write_data(0, led_control_reg, 0x13); + if (layer_status > 0) { + is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, 0); + } + layer_status=0; + break; + + case TOGGLE_BACKLIGHT: + //msg_led = unused + //TODO: need to test tracking of active layer with layer_state from qmk + xprintf("TOGGLE_BACKLIGHT\n"); + backlight_status ^= 1; + is31_read_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, &temp); + layer_status = temp; + + page = backlight_status == 0 ? 0 : layer_status; + is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, page); + break; + + case TOGGLE_PAGE_LEDS://show single layer indicator or full map of layer + //msg_led = page to toggle on + xprintf("TOGGLE_LAYER_LEDS\n"); + is31_read_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, &temp); + + if(temp == msg_led) { + is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, 7); + layer_status = 7; + } else { + is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, msg_led); + layer_status = msg_led; + } + break; + + case TOGGLE_NUM_LOCK: + //msg_led = 0 or 1, off/on + set_lock_leds(USB_LED_NUM_LOCK, msg_led); + break; + + case TOGGLE_CAPS_LOCK: + //msg_led = 0 or 1, off/on + set_lock_leds(USB_LED_CAPS_LOCK, msg_led); + break; + + case MODE_BREATH: + break; + case STEP_BRIGHTNESS: + xprintf("TOGGLE_BACKLIGHT\n"); + //led_msg = step pwm up or down + //TODO: test step brightness code + //pwm_levels[] bounds checking, loop through array + switch (msg_led) { + case 0: + if (pwm_step_status == 0) { + pwm_step_status = 4; + } else { + pwm_step_status--; + } + break; + + case 1: + if (pwm_step_status == 4) { + pwm_step_status = 0; + } else { + pwm_step_status++; + } + break; + } + + //populate the 9 byte rows to be written to each pin, first byte is register (pin) address + __builtin_memset(pwm_register_array+1, pwm_levels[pwm_step_status], 8); + + for(i=0; i<8; i++) { + //first byte is register address, every 0x10 9 bytes is A-register pwm pins + pwm_register_array[0] = 0x24 + (i * 0x10); + for(j=0; j<9; j++) { + } + is31_write_data(0,pwm_register_array,9); + } + break; + +/* case LED_MSG_SLEEP_LED_ON: + // save current settings + is31_read_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, &save_page); + is31_read_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL1, &save_breath1); + is31_read_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL2, &save_breath2); + // use pages 7 and 8 for (hardware) breathing (assuming they're empty) + is31_write_register(6, BREATHE_LED_ADDRESS, 0xFF); + is31_write_register(7, BREATHE_LED_ADDRESS, 0x00); + is31_write_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL1, (6<<4)|6); + is31_write_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL2, IS31_REG_BREATHCTRL2_ENABLE|3); + retval = MSG_TIMEOUT; + temp = 6; + while(retval == MSG_TIMEOUT) { + // switch to the other page + is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, temp); + temp = (temp == 6 ? 7 : 6); + // the times should be sufficiently long for IS31 to finish switching pages + retval = chMBFetch(&led_mailbox, &msg, MS2ST(temp == 6 ? 4000 : 6000)); + } + // received a message (should be a wakeup), so restore previous state + chThdSleepMilliseconds(3000); // need to wait until the page change finishes + // note: any other messages are queued + is31_write_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL1, save_breath1); + is31_write_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL2, save_breath2); + is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, save_page); + break; + case LED_MSG_SLEEP_LED_OFF: + // should not get here; wakeup should be received in the branch above break; + break; +*/ + xprintf("--------------------\n"); } - xprintf("--------------------\n"); } } - /* ============================== * led processing functions * ============================== */ @@ -451,14 +453,14 @@ void set_lock_leds(uint8_t lock_type, uint8_t led_on) { } } -void write_led_page (uint8_t page, const uint8_t *led_array, uint8_t led_count) { +void write_led_page (uint8_t page, const uint8_t *user_led_array, uint8_t led_count) { uint8_t i; uint8_t row, col; uint8_t led_control_register[0x13] = {0};//led control register start address + 0x12 bytes for(i=0;i Date: Sat, 15 Apr 2017 14:37:55 -0700 Subject: [PATCH 018/238] more stable lock led process, added debugging code --- keyboards/infinity60/led_controller.c | 117 +++++++++++++++----------- 1 file changed, 70 insertions(+), 47 deletions(-) diff --git a/keyboards/infinity60/led_controller.c b/keyboards/infinity60/led_controller.c index cb91f9f35..d88ae14b1 100644 --- a/keyboards/infinity60/led_controller.c +++ b/keyboards/infinity60/led_controller.c @@ -70,6 +70,8 @@ along with this program. If not, see . #define BREATHE_LED_ADDRESS CAPS_LOCK_LED_ADDRESS #endif +#define DEBUG_ENABLED 1 + /* ================= * ChibiOS I2C setup * ================= */ @@ -171,11 +173,11 @@ static THD_FUNCTION(LEDthread, arg) { chRegSetThreadName("LEDthread"); uint8_t i, j, page; - uint8_t control_register_word[2] = {0};//register address - byte to write + uint8_t control_register_word[2] = {0};//2 bytes: register address, byte to write uint8_t led_control_reg[0x13] = {0};//led control register start address + 0x12 bytes //persistent status variables - uint8_t backlight_status, pwm_step_status, layer_status; + uint8_t backlight_status, pwm_step_status, page_status; //mailbox variables uint8_t temp, msg_type, msg_led; @@ -189,7 +191,7 @@ static THD_FUNCTION(LEDthread, arg) { // initialize persistent variables backlight_status = 0; //start backlight off pwm_step_status = 4; //full brightness -layer_status = 0; //start frame 0 (all off/on) +page_status = 0; //start frame 0 (all off/on) while(true) { // wait for a message (asynchronous) @@ -201,74 +203,89 @@ layer_status = 0; //start frame 0 (all off/on) xprintf("--------------------\n"); xprintf("mailbox fetch\nmsg: %X\n", msg); - xprintf("type: %X - led: %X\n", msg_type, msg_led); //test if msg_type is 1 or 2 bytes after mask + xprintf("type: %X - led: %X\n", msg_type, msg_led); switch (msg_type){ case KEY_LIGHT: //TODO: lighting key led on keypress break; - //turn on/off/toggle single led, msg_led = row/col of led case OFF_LED: + //on/off/toggle single led, msg_led = row/col of led xprintf("OFF_LED\n"); set_led_bit(7, control_register_word, msg_led, 0); is31_write_data (7, control_register_word, 0x02); - if (layer_status > 0) {//check current led page to prevent double blink + + if (page_status < 7) { is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, 7); } - layer_status = 7; + page_status = 7; break; + case ON_LED: xprintf("ON_LED\n"); set_led_bit(7, control_register_word, msg_led, 1); is31_write_data (7, control_register_word, 0x02); - if (layer_status > 7) { + + if (page_status < 7) {//check current led page to prevent double blink is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, 7); } - layer_status = 7; + page_status = 7; break; + case TOGGLE_LED: xprintf("TOGGLE_LED\n"); set_led_bit(7, control_register_word, msg_led, 2); is31_write_data (7, control_register_word, 0x02); - if (layer_status > 7) { + if (page_status > 7) { is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, 7); } - layer_status = 7; + page_status = 7; break; case TOGGLE_ALL: xprintf("TOGGLE_ALL\n"); //msg_led = unused - is31_read_register(0, 0x00, &temp);//if first byte is on, then toggle frame 1 off + is31_read_register(0, 0x00, &temp);//if first byte is on, then toggle frame 0 off led_control_reg[0] = 0; - if (temp==0) { - xprintf("all leds on"); + if (temp==0 || page_status > 0) { + xprintf("all leds on"); __builtin_memcpy(led_control_reg+1, all_on_leds_mask, 0x12); } else { - xprintf("all leds off"); + xprintf("all leds off"); __builtin_memset(led_control_reg+1, 0, 0x12); } is31_write_data(0, led_control_reg, 0x13); - if (layer_status > 0) { + if (page_status > 0) { is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, 0); } - layer_status=0; + + //maintain lock leds + if (host_keyboard_leds() & (1<0 || BACKLIGHT_OFF_LOCK_LED_OFF) ? 1 : 0; + + for(page=start; page<8; page++) { set_led_bit(page,led_control_write,led_addr,led_on); - xprintf("lock_led row: %X lock_led col%X\n", led_control_write[0], led_control_write[1]); is31_write_data(page, led_control_write, 0x02); - chThdSleepMilliseconds(10); } } @@ -458,8 +479,10 @@ void write_led_page (uint8_t page, const uint8_t *user_led_array, uint8_t led_co uint8_t row, col; uint8_t led_control_register[0x13] = {0};//led control register start address + 0x12 bytes + __builtin_memset(led_control_register,0,13); + for(i=0;i Date: Tue, 18 Apr 2017 09:46:07 -0500 Subject: [PATCH 019/238] small changes --- keyboards/ergodox/keymaps/familiar/README.md | 4 ++-- keyboards/ergodox/keymaps/familiar/keymap.c | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/keyboards/ergodox/keymaps/familiar/README.md b/keyboards/ergodox/keymaps/familiar/README.md index e4336d9b5..8db9a7712 100644 --- a/keyboards/ergodox/keymaps/familiar/README.md +++ b/keyboards/ergodox/keymaps/familiar/README.md @@ -1,5 +1,5 @@ # ErgoDox Familiar Layout -Familiar layout for those who regularly switch back and forth from ErgoDox to regular QWERTY. +Familiar layout for those who regularly switch back and forth from ErgoDox to "normal" QWERTY. [![License: GPL v3](https://img.shields.io/badge/License-GPL%20v3-blue.svg)](../../../../license_GPLv3.md../../../../license_GPLv3.md) [![standard-readme compliant](https://img.shields.io/badge/readme%20style-standard-brightgreen.svg)](https://github.com/RichardLitt/standard-readme) @@ -50,7 +50,7 @@ $ make ergodox-ez-familiar-teensy ### Layers 1. Base Layer: QWERTY, with arrow keys at bottom right. 1. UCIS Layer: US-International symbols layer, plus —. Accessed by toggling the `INTL` layer using the UCIS key (bottom of left thumb cluster). -1. UCIS-Shifted Layer: Making shift work for UCIS characters. An ugly workaround. Any ideas? Accessed through holding shift while the UCIS layer is active (toggles the `INSF` layer). +1. UCIS-Shifted Layer: Making shift work for UCIS characters. An ugly workaround. Any ideas? Accessed by holding shift while the UCIS layer is active (toggles the `INSF` layer). 1. Numpad Layer: Right hand number pad. Accessed by toggling the `NUMP` layer using the NPAD key (bottom of right thumb cluster). 1. Function Layer: F1-F12, arrows on ESDF and HJKL, media player controls. Accessed by holding either FN key (center key of each thumb cluster), which toggles the `ARRW` layer. I know, I need to work on my naming conventions. diff --git a/keyboards/ergodox/keymaps/familiar/keymap.c b/keyboards/ergodox/keymaps/familiar/keymap.c index c5f94afda..0e3958de0 100644 --- a/keyboards/ergodox/keymaps/familiar/keymap.c +++ b/keyboards/ergodox/keymaps/familiar/keymap.c @@ -31,7 +31,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { * | LCTRL | LGUI | MENU | ' | " | | [ | ] | LEFT | DOWN | RIGHT | * `------------------------------------' `------------------------------------' * ,-------------. ,-------------. - * | VOL- | VOL+ | | | | + * | VOL- | VOL+ | |PRTSCR| | * ,------|------|------| |------+------+------. * | SPC/ |SLASH/| MUTE | |NUMLCK|WHACK/| SPC/ | * | ALT | MO(1)|------| |------|MO(1) | ALT | @@ -54,7 +54,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_ENTER, KC_PGDN, KC_N, KC_M, KC_COMM, KC_DOT, KC_UP, KC_RSPC, KC_LBRC, KC_RBRC, KC_LEFT, KC_DOWN, KC_RGHT, - _______, _______, + KC_PSCR, _______, KC_NLCK, TG(NUMP), LT(ARRW,KC_BSLS), ALT_T(KC_SPC) ), @@ -202,7 +202,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { * | | | | | | | | | HOME | PGDN | END | * `------------------------------------' `------------------------------------' * ,-------------. ,-------------. - * | | PAUSE| | | | + * | | PAUSE| |SYSREQ| | * ,------|------|------| |------+------+------. * | | | | |SCRLK | | | * | | |------| |------| | | @@ -225,7 +225,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { KC_LEFT, KC_DOWN, KC_UP, KC_RGHT, _______, _______, _______, _______, _______, _______, _______, KC_PGUP, _______, _______, _______, KC_HOME, KC_PGDN, KC_END, - _______, _______, + KC_SYSREQ, _______, KC_SLCK, _______, _______, _______ ), From b3945c103cfa4c8f30a656d626dba75ad7f0af85 Mon Sep 17 00:00:00 2001 From: jpetermans Date: Wed, 26 Apr 2017 23:12:25 -0700 Subject: [PATCH 020/238] Simplified processing in led_controller; more control at user level. --- keyboards/infinity60/led_controller.c | 214 +++++++++++++++----------- keyboards/infinity60/led_controller.h | 5 +- 2 files changed, 123 insertions(+), 96 deletions(-) diff --git a/keyboards/infinity60/led_controller.c b/keyboards/infinity60/led_controller.c index d88ae14b1..4dc9b9234 100644 --- a/keyboards/infinity60/led_controller.c +++ b/keyboards/infinity60/led_controller.c @@ -25,6 +25,8 @@ along with this program. If not, see . #include "hal.h" #include "print.h" #include "led.h" +#include "action_layer.h" +#include "host.h" #include "led_controller.h" @@ -70,7 +72,7 @@ along with this program. If not, see . #define BREATHE_LED_ADDRESS CAPS_LOCK_LED_ADDRESS #endif -#define DEBUG_ENABLED 1 +#define DEBUG_ENABLED 0 /* ================= * ChibiOS I2C setup @@ -172,12 +174,12 @@ static THD_FUNCTION(LEDthread, arg) { (void)arg; chRegSetThreadName("LEDthread"); - uint8_t i, j, page; + uint8_t i; uint8_t control_register_word[2] = {0};//2 bytes: register address, byte to write uint8_t led_control_reg[0x13] = {0};//led control register start address + 0x12 bytes //persistent status variables - uint8_t backlight_status, pwm_step_status, page_status; + uint8_t pwm_step_status, page_status; //mailbox variables uint8_t temp, msg_type, msg_led; @@ -189,7 +191,6 @@ static THD_FUNCTION(LEDthread, arg) { */ // initialize persistent variables -backlight_status = 0; //start backlight off pwm_step_status = 4; //full brightness page_status = 0; //start frame 0 (all off/on) @@ -202,68 +203,63 @@ page_status = 0; //start frame 0 (all off/on) msg_led = (msg) & 0xFF; //second byte is action information xprintf("--------------------\n"); + chThdSleepMilliseconds(10); xprintf("mailbox fetch\nmsg: %X\n", msg); + chThdSleepMilliseconds(10); xprintf("type: %X - led: %X\n", msg_type, msg_led); + chThdSleepMilliseconds(10); switch (msg_type){ case KEY_LIGHT: //TODO: lighting key led on keypress break; + //TODO: custom page that is written using keypresses + //TODO: BLINK_ON/OFF_LED + case OFF_LED: //on/off/toggle single led, msg_led = row/col of led xprintf("OFF_LED\n"); + chThdSleepMilliseconds(10); set_led_bit(7, control_register_word, msg_led, 0); is31_write_data (7, control_register_word, 0x02); - - if (page_status < 7) { - is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, 7); - } - page_status = 7; break; case ON_LED: xprintf("ON_LED\n"); + chThdSleepMilliseconds(10); set_led_bit(7, control_register_word, msg_led, 1); is31_write_data (7, control_register_word, 0x02); - - if (page_status < 7) {//check current led page to prevent double blink - is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, 7); - } - page_status = 7; break; case TOGGLE_LED: xprintf("TOGGLE_LED\n"); + chThdSleepMilliseconds(10); set_led_bit(7, control_register_word, msg_led, 2); - is31_write_data (7, control_register_word, 0x02); - if (page_status > 7) { - is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, 7); - } - page_status = 7; break; case TOGGLE_ALL: xprintf("TOGGLE_ALL\n"); + chThdSleepMilliseconds(10); //msg_led = unused - is31_read_register(0, 0x00, &temp);//if first byte is on, then toggle frame 0 off - led_control_reg[0] = 0; if (temp==0 || page_status > 0) { xprintf("all leds on"); + chThdSleepMilliseconds(10); __builtin_memcpy(led_control_reg+1, all_on_leds_mask, 0x12); } else { xprintf("all leds off"); + chThdSleepMilliseconds(10); __builtin_memset(led_control_reg+1, 0, 0x12); } - is31_write_data(0, led_control_reg, 0x13); + if (page_status > 0) { is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, 0); } - + //maintain lock leds if (host_keyboard_leds() & (1< 90 || led_addr % 10 > 8) { + xprintf("Invalid address: %d\n", led_addr); + return; + } + //first byte is led control register address 0x00 //msg_led tens column is pin#, ones column is bit position in 8-bit mask control_reg_addr = ((led_addr / 10) % 10 - 1 ) * 0x02;// A-register is every other byte column_bit = 1<<(led_addr % 10 - 1); - is31_read_register(page,control_reg_addr,&temp);//need to maintain status of leds in this row (1 byte) + is31_read_register(page, control_reg_addr, &temp);//maintain status of leds on this byte column_byte = temp; switch(action) { @@ -437,9 +460,11 @@ void set_led_bit (uint8_t page, uint8_t *led_control_reg, uint8_t led_addr, uint void set_lock_leds(uint8_t lock_type, uint8_t led_on) { uint8_t page, led_addr, start, temp; - uint8_t led_control_write[2] = {0}; - //TODO: consolidate control register to top level array vs. three scattered around + uint8_t led_control_word[2] = {0}; + //TODO: this function call could send led address vs lock_type. + //however, the switch/case allows for additional steps, like audio, depending on type + led_addr = 0; switch(lock_type) { case USB_LED_NUM_LOCK: led_addr = NUM_LOCK_LED_ADDRESS; @@ -465,16 +490,18 @@ void set_lock_leds(uint8_t lock_type, uint8_t led_on) { } //ignore frame0 if all leds are on or if option set in led_controller.h + //TODO: blink of all leds are on, clear blink register if not is31_read_register(0, 0x00, &temp); - start = (temp>0 || BACKLIGHT_OFF_LOCK_LED_OFF) ? 1 : 0; + led_addr += temp == 0 ? 0 : 0x12;//send bit to blink register instead + start = BACKLIGHT_OFF_LOCK_LED_OFF ? 1 : 0; for(page=start; page<8; page++) { - set_led_bit(page,led_control_write,led_addr,led_on); - is31_write_data(page, led_control_write, 0x02); + set_led_bit(page,led_control_word,led_addr,led_on); + is31_write_data(page, led_control_word, 0x02); } } -void write_led_page (uint8_t page, const uint8_t *user_led_array, uint8_t led_count) { +void write_led_page (uint8_t page, uint8_t *user_led_array, uint8_t led_count) { uint8_t i; uint8_t row, col; uint8_t led_control_register[0x13] = {0};//led control register start address + 0x12 bytes @@ -516,7 +543,6 @@ void led_controller_init(void) { //set Display Option Register so all pwm intensity is controlled from Frame 0 is31_write_register(IS31_FUNCTIONREG, IS31_REG_DISPLAYOPT, IS31_REG_DISPLAYOPT_INTENSITY_SAME); - //TODO: test new init pwm loop /* set full pwm on Frame 1 */ pwm_register_array[0] = 0; __builtin_memset(pwm_register_array+1, 0xFF, 8); diff --git a/keyboards/infinity60/led_controller.h b/keyboards/infinity60/led_controller.h index 151100471..b06113b07 100644 --- a/keyboards/infinity60/led_controller.h +++ b/keyboards/infinity60/led_controller.h @@ -94,7 +94,7 @@ extern mailbox_t led_mailbox; void set_led_bit (uint8_t page, uint8_t *led_control_reg, uint8_t led_addr, uint8_t action); void set_lock_leds (uint8_t lock_type, uint8_t led_on); -void write_led_page (uint8_t page, const uint8_t *led_array, uint8_t led_count); +void write_led_page (uint8_t page, uint8_t *led_array, uint8_t led_count); // constants for signaling the LED controller thread enum led_msg_t { @@ -104,7 +104,8 @@ enum led_msg_t { TOGGLE_LED, TOGGLE_ALL, TOGGLE_BACKLIGHT, - TOGGLE_PAGE_LEDS, + DISPLAY_PAGE, + RESET_PAGE, TOGGLE_NUM_LOCK, TOGGLE_CAPS_LOCK, MODE_BREATH, From ff6beeb7a313953c589defb6af1f9ae461cba03a Mon Sep 17 00:00:00 2001 From: jpetermans Date: Sat, 29 Apr 2017 09:22:40 -0700 Subject: [PATCH 021/238] simplified lock led function --- keyboards/infinity60/led_controller.c | 57 ++++++++------------------- keyboards/infinity60/led_controller.h | 2 +- 2 files changed, 17 insertions(+), 42 deletions(-) diff --git a/keyboards/infinity60/led_controller.c b/keyboards/infinity60/led_controller.c index 4dc9b9234..707b4e0df 100644 --- a/keyboards/infinity60/led_controller.c +++ b/keyboards/infinity60/led_controller.c @@ -262,10 +262,10 @@ page_status = 0; //start frame 0 (all off/on) //maintain lock leds if (host_keyboard_leds() & (1< Date: Sun, 30 Apr 2017 16:27:46 -0700 Subject: [PATCH 022/238] Testing initial blink support --- keyboards/infinity60/led_controller.c | 254 ++++++++++++++++++-------- keyboards/infinity60/led_controller.h | 7 +- 2 files changed, 180 insertions(+), 81 deletions(-) diff --git a/keyboards/infinity60/led_controller.c b/keyboards/infinity60/led_controller.c index 4dc9b9234..59ca833b6 100644 --- a/keyboards/infinity60/led_controller.c +++ b/keyboards/infinity60/led_controller.c @@ -72,7 +72,7 @@ along with this program. If not, see . #define BREATHE_LED_ADDRESS CAPS_LOCK_LED_ADDRESS #endif -#define DEBUG_ENABLED 0 +#define DEBUG_ENABLED 1 /* ================= * ChibiOS I2C setup @@ -214,44 +214,58 @@ page_status = 0; //start frame 0 (all off/on) //TODO: lighting key led on keypress break; - //TODO: custom page that is written using keypresses //TODO: BLINK_ON/OFF_LED + break; case OFF_LED: //on/off/toggle single led, msg_led = row/col of led - xprintf("OFF_LED\n"); + xprintf("OFF_LED: %d\n", msg_led); chThdSleepMilliseconds(10); set_led_bit(7, control_register_word, msg_led, 0); is31_write_data (7, control_register_word, 0x02); break; - case ON_LED: - xprintf("ON_LED\n"); + xprintf("ON_LED: %d\n", msg_led); chThdSleepMilliseconds(10); set_led_bit(7, control_register_word, msg_led, 1); is31_write_data (7, control_register_word, 0x02); break; - case TOGGLE_LED: - xprintf("TOGGLE_LED\n"); + xprintf("TOGGLE_LED: %d\n", msg_led); chThdSleepMilliseconds(10); set_led_bit(7, control_register_word, msg_led, 2); is31_write_data (7, control_register_word, 0x02); break; + case BLINK_OFF_LED: + //on/off/toggle single led, msg_led = row/col of led + xprintf("BLINK_ON: %d\n", msg_led); + chThdSleepMilliseconds(10); + set_led_bit(7, control_register_word, msg_led, 4); + is31_write_data (7, control_register_word, 0x02); + break; + case BLINK_ON_LED: + xprintf("BLINK_OFF: %d\n", msg_led); + chThdSleepMilliseconds(10); + set_led_bit(7, control_register_word, msg_led, 5); + is31_write_data (7, control_register_word, 0x02); + break; + case BLINK_TOGGLE_LED: + xprintf("BLINK_TOGGLE: %d\n", msg_led); + chThdSleepMilliseconds(10); + set_led_bit(7, control_register_word, msg_led, 6); + is31_write_data (7, control_register_word, 0x02); + case TOGGLE_ALL: - xprintf("TOGGLE_ALL\n"); + xprintf("TOGGLE_ALL: %d\n", msg_led); chThdSleepMilliseconds(10); //msg_led = unused is31_read_register(0, 0x00, &temp);//if first byte is on, then toggle frame 0 off led_control_reg[0] = 0; + if (temp==0 || page_status > 0) { - xprintf("all leds on"); - chThdSleepMilliseconds(10); __builtin_memcpy(led_control_reg+1, all_on_leds_mask, 0x12); } else { - xprintf("all leds off"); - chThdSleepMilliseconds(10); __builtin_memset(led_control_reg+1, 0, 0x12); } is31_write_data(0, led_control_reg, 0x13); @@ -292,15 +306,19 @@ page_status = 0; //start frame 0 (all off/on) case DISPLAY_PAGE://show single layer indicator or full map of layer //msg_led = page to toggle on - xprintf("DISPLAY_PAGE\n"); + xprintf("DISPLAY_PAGE"); chThdSleepMilliseconds(10); if (page_status != msg_led) { + xprintf(" - new page\n"); + chThdSleepMilliseconds(10); is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, msg_led); } page_status = msg_led; break; case RESET_PAGE: + xprintf("RESET_PAGE\n"); + chThdSleepMilliseconds(10); //led_msg = page to reset led_control_reg[0] = 0; __builtin_memset(led_control_reg+1, 0, 0x12); @@ -317,19 +335,23 @@ page_status = 0; //start frame 0 (all off/on) case TOGGLE_NUM_LOCK: //msg_led = 0 or 1, off/on - set_lock_leds(USB_LED_NUM_LOCK, msg_led); + xprintf("NUMLOCK: %d\n", msg_led); + chThdSleepMilliseconds(10); + set_lock_leds(NUM_LOCK_LED_ADDRESS, msg_led); break; case TOGGLE_CAPS_LOCK: + xprintf("CAPSLOCK: %d\n", msg_led); + chThdSleepMilliseconds(10); //msg_led = 0 or 1, off/on - set_lock_leds(USB_LED_CAPS_LOCK, msg_led); + set_lock_leds(CAPS_LOCK_LED_ADDRESS, msg_led); break; //TODO: MODE_BREATH case MODE_BREATH: break; case STEP_BRIGHTNESS: - xprintf("TOGGLE_BACKLIGHT\n"); + xprintf("STEP_BACKLIGHT\n"); chThdSleepMilliseconds(10); //led_msg = step pwm up or down switch (msg_led) { @@ -394,27 +416,101 @@ page_status = 0; //start frame 0 (all off/on) chThdSleepMilliseconds(10); } #if DEBUG_ENABLED - uint8_t j, page; + uint8_t j; + uint8_t pages[3]={0x00, 0x07}; //debugging code - print full led/blink/pwm registers on each frame xprintf("----layer state----: %X\n", layer_state); - for(i=0;i<8;i++) { - xprintf("page: %d", i); + for(i=0;i<2;i++) { + xprintf("page: %d\n", pages[i]); chThdSleepMilliseconds(2); - for(j=0;j<0xB4;j++){ - is31_read_register(i,j,&temp); - chThdSleepMilliseconds(2); - xprintf("%02X, ", temp); - if(j % 9 == 0){ + for(j=0;j<0x24;j++){ + if(j > 0 && j % 9 == 0){ xprintf("\n"); - if(j % 18 ==0){ - xprintf("register"); - xprintf("\n"); - } + } + switch (j) { + case 0: + xprintf("\n--on-off--\n"); + chThdSleepMilliseconds(2); + break; + case 0x12: + xprintf("\n--blink--\n"); + chThdSleepMilliseconds(2); + break; } - chThdSleepMilliseconds(1); + is31_read_register(pages[i],j,&temp); + xprintf("%02X, ", temp); + chThdSleepMilliseconds(2); } + + xprintf("\n--pwm--\n"); + chThdSleepMilliseconds(2); + for(j=0x24;j<0xB4;j++) { + is31_read_register(pages[i],j,&temp); + xprintf("%02X, ", temp); + chThdSleepMilliseconds(2); + if(j > 0x24 && (j-4) % 8 == 0){ xprintf("\n"); + } + } + xprintf("\n"); } + + //Function Register + xprintf("\n--FUNCTION--\n"); + chThdSleepMilliseconds(2); + for(j=0;j<0x0D;j++) { + is31_read_register(0x0B,j,&temp); + switch(j) { + case 0: + xprintf("Config %02X", temp); + chThdSleepMilliseconds(2); + break; + case 1: + xprintf(" - Pict %02X\n", temp); + chThdSleepMilliseconds(2); + break; + case 2: + xprintf("Auto1 %02X", temp); + chThdSleepMilliseconds(2); + break; + case 3: + xprintf(" - Auto2 %02X\n", temp); + chThdSleepMilliseconds(2); + break; + case 5: + xprintf("Disp %02X", temp); + chThdSleepMilliseconds(2); + break; + case 6: + xprintf(" - Audio %02X\n", temp); + chThdSleepMilliseconds(2); + break; + case 7: + xprintf("Frame %02X", temp); + chThdSleepMilliseconds(2); + break; + case 8: + xprintf(" - Breath1 %02X\n", temp); + chThdSleepMilliseconds(2); + break; + case 9: + xprintf("Breath2 %02X - ", temp); + chThdSleepMilliseconds(2); + break; + case 10: + xprintf(" - Shut %02X\n", temp); + chThdSleepMilliseconds(2); + break; + case 11: + xprintf("AGC %02X", temp); + chThdSleepMilliseconds(2); + break; + case 12: + xprintf(" - ADC %02X\n", temp); + chThdSleepMilliseconds(2); + break; + } + } #endif } } @@ -425,22 +521,39 @@ page_status = 0; //start frame 0 (all off/on) void set_led_bit (uint8_t page, uint8_t *led_control_reg, uint8_t led_addr, uint8_t action) { //returns 2 bytes led control register address and byte to write + //0 - bit off, 1 - bit on, 2 - toggle bit + + uint8_t control_reg_addr, column_bit, column_byte, temp, blink_on; - uint8_t control_reg_addr, column_bit, column_byte, temp; //check for valid led address - if (led_addr < 0 || led_addr > 90 || led_addr % 10 > 8) { + if (led_addr < 0 || led_addr > 87 || led_addr % 10 > 8) { xprintf("Invalid address: %d\n", led_addr); return; } + xprintf("set_led_bit: %d\n", led_addr); + xprintf("action: %d\n", action); + chThdSleepMilliseconds(10); + //check blink bit + blink_on = action>>2; + action &= ~(1<<2); //strip blink bit + //first byte is led control register address 0x00 //msg_led tens column is pin#, ones column is bit position in 8-bit mask control_reg_addr = ((led_addr / 10) % 10 - 1 ) * 0x02;// A-register is every other byte + xprintf("pre-reg_addr: %X\n", control_reg_addr); + chThdSleepMilliseconds(10); + control_reg_addr += blink_on == 1 ? 0x12 : 0x00;//shift 12 bytes to blink register + xprintf("blink-reg_addr: %X\n", control_reg_addr); + chThdSleepMilliseconds(10); + column_bit = 1<<(led_addr % 10 - 1); is31_read_register(page, control_reg_addr, &temp);//maintain status of leds on this byte column_byte = temp; + xprintf("column_byte read: %X\n", column_byte); + chThdSleepMilliseconds(10); switch(action) { case 0: column_byte &= ~column_bit; @@ -452,72 +565,58 @@ void set_led_bit (uint8_t page, uint8_t *led_control_reg, uint8_t led_addr, uint column_byte ^= column_bit; break; } + xprintf("column_byte write: %X\n", column_byte); + chThdSleepMilliseconds(10); //return word to be written in register led_control_reg[0] = control_reg_addr; led_control_reg[1] = column_byte; } -void set_lock_leds(uint8_t lock_type, uint8_t led_on) { - uint8_t page, led_addr, start, temp; - uint8_t led_control_word[2] = {0}; - //TODO: this function call could send led address vs lock_type. - //however, the switch/case allows for additional steps, like audio, depending on type +void write_led_byte (uint8_t page, uint8_t row, uint8_t led_byte) { + uint8_t led_control_word[2] = {0};//register address and led on/off mask - led_addr = 0; - switch(lock_type) { - case USB_LED_NUM_LOCK: - led_addr = NUM_LOCK_LED_ADDRESS; - break; - case USB_LED_CAPS_LOCK: - led_addr = CAPS_LOCK_LED_ADDRESS; - break; - #ifdef SCROLL_LOCK_LED_ADDRESS - case USB_LED_SCROLL_LOCK: - led_addr = SCROLL_LOCK_LED_ADDRESS; - break; - #endif - #ifdef COMPOSE_LED_ADDRESS - case USB_LED_COMPOSE: - led_addr = COMPOSE_LED_ADDRESS; - break; - #endif - #ifdef SCROLL_LOCK_LED_ADDRESS - case USB_LED_KANA: - led_addr = KANA_LED_ADDRESS; - break; - #endif - } - - //ignore frame0 if all leds are on or if option set in led_controller.h - //TODO: blink of all leds are on, clear blink register if not - is31_read_register(0, 0x00, &temp); - led_addr += temp == 0 ? 0 : 0x12;//send bit to blink register instead - start = BACKLIGHT_OFF_LOCK_LED_OFF ? 1 : 0; - - for(page=start; page<8; page++) { - set_led_bit(page,led_control_word,led_addr,led_on); - is31_write_data(page, led_control_word, 0x02); - } + led_control_word[0] = (row - 1 ) * 0x02;// A-register is every other byte + led_control_word[1] = led_byte;// A-register is every other byte + is31_write_data(page, led_control_word, 0x13); } void write_led_page (uint8_t page, uint8_t *user_led_array, uint8_t led_count) { uint8_t i; - uint8_t row, col; + uint8_t pin, col; uint8_t led_control_register[0x13] = {0};//led control register start address + 0x12 bytes __builtin_memset(led_control_register,0,13); for(i=0;i Date: Mon, 8 May 2017 11:57:40 -0700 Subject: [PATCH 023/238] small code cleanup --- keyboards/infinity60/MEMO.txt | 385 ------------------------- keyboards/infinity60/led_controller.c | 389 ++++++++++++++------------ keyboards/infinity60/led_controller.h | 16 +- 3 files changed, 212 insertions(+), 578 deletions(-) delete mode 100644 keyboards/infinity60/MEMO.txt diff --git a/keyboards/infinity60/MEMO.txt b/keyboards/infinity60/MEMO.txt deleted file mode 100644 index e2886aa00..000000000 --- a/keyboards/infinity60/MEMO.txt +++ /dev/null @@ -1,385 +0,0 @@ -flabbergast's TMK/ChibiOS port -============================== -2015/10/16 - - -Build ------ -$ git clone -b chibios https://github.com/flabbergast/tmk_keyboard.git - -$ cd tmk_keyboard -$ git submodule add -f -b kinetis https://github.com/flabbergast/ChibiOS.git tmk_core/tool/chibios/chibios -or -$ cd tmk_keyboard/tmk_core/tool/chibios -$ git clone -b kinetis https://github.com/flabbergast/ChibiOS.git tmk_core/tool/chibios/chibios - -$ cd tmk_keyboard/keyboard/infinity_chibios -$ make - - - - -Chibios Configuration ---------------------- -halconf.h: for HAL configuration - placed in project directory - read in chibios/os/hal/hal.mk - included in chibios/os/hal/include/hal.h -mcuconf.h: for MCU configuration - placed in project directory - included in halconf.h - - -Chibios Term ------------- -PAL = Port Abstraction Layer - palWritePad - palReadPad - palSetPad - chibios/os/hal/include/pal.h - -LLD = Low Level Driver - - -Makefile --------- - # /os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES) - MCU_FAMILY = KINETIS - MCU_SERIES = KL2x - - # - it should exist either in /os/common/ports/ARMCMx/compilers/GCC/ld/ - # or /ld/ - MCU_LDSCRIPT = MKL26Z64 - - # - it should exist in /os/common/ports/ARMCMx/compilers/GCC/mk/ - MCU_STARTUP = kl2x - - # Board: it should exist either in /os/hal/boards/ - # or /boards - BOARD = PJRC_TEENSY_LC - - MCU = cortex-m0 - - # ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7 - ARMV = 6 - - -halconf.h ---------- - - -mcuconf.h ---------- - - -chconf.h --------- - - -ld script ---------- ---- ../../tmk_core/tool/chibios/chibios/os/common/ports/ARMCMx/compilers/GCC/ld/MKL26Z64.ld 2015-10-15 09:08:58.732904304 +0900 -+++ ld/MKL26Z64.ld 2015-10-15 08:48:06.430215496 +0900 -@@ -27,7 +27,8 @@ - { - flash0 : org = 0x00000000, len = 0xc0 - flashcfg : org = 0x00000400, len = 0x10 -- flash : org = 0x00000410, len = 64k - 0x410 -+ flash : org = 0x00000410, len = 62k - 0x410 -+ eeprom_emu : org = 0x0000F800, len = 2k - ram : org = 0x1FFFF800, len = 8k - } - -@@ -35,6 +36,10 @@ - __ram_size__ = LENGTH(ram); - __ram_end__ = __ram_start__ + __ram_size__; - -+__eeprom_workarea_start__ = ORIGIN(eeprom_emu); -+__eeprom_workarea_size__ = LENGTH(eeprom_emu); -+__eeprom_workarea_end__ = __eeprom_workarea_start__ + __eeprom_workarea_size__; -+ - SECTIONS - { - . = 0; - - - -Configuration/Startup for Infinity 60% --------------------------------------- -Configuration: - - -Clock: -Inifinity - FEI(FLL Engaged Internal) mode with core clock:48MHz, bus clock:48MHz, flash clock:24MHz - Clock dividor: - SIM_CLKDIV1[OUTDIV1] = 0 divide-by-1 for core clock - SIM_CLKDIV1[OUTDIV2] = 0 divide-by-1 for bus clock - SIM_CLKDIV1[OUTDIV4] = 1 divide-by-2 for flash clock - Internal reference clock: - MCG_C1[IREFS] = 1 Internal Reference Select for clock source for FLL - MCG_C1[IRCLKEN] = 1 Internal Reference Clock Enable - FLL multipilication: - MCG_C4[DMX32] = 1 - MCG_C4[DRST_DRS] = 01 FLL factor 1464 * 32.768kHz = 48MHz - -chibios/os/hal/ports/KINETIS/K20x/hal_lld.c - k20x_clock_init(): called in __early_init() defined in board.c - disable watchdog and configure clock - - configurable macros: - KINETIS_NO_INIT: whether init or not - KINETIS_MCG_MODE: clock mode - KINETIS_MCG_MODE_FEI - KINETIS_MCG_MODE_PEE - hal/ports/KINETIS/K20x/hal_lld.h - - -chibios/os/hal/boards/FREESCALE_FREEDOM_K20D50M/board.h - PALConfig pal_default_config - boardInit() - __early_init() - macro definitions for board infos, freq and mcu type - -chibios/os/hal/boards/FREESCALE_FREEDOM_K20D50M/board.c - -USB - - -Startup -------- - common/ports/ARMCMx/GCC/crt0_v[67]m.s - Reset_Handler: startup code - common/ports/ARMCMx/GCC/crt1.c - __core_init(): weak - __early_init(): weak - __late_init(): weak - __default_exit(): weak - called from Reset_Handler of crt0 - common/ports/ARMCMx/GCC/vector.c - common/ports/ARMCMx/GCC/ld/*.ld - -chibios/os/common/ports/ARMCMx/compilers/GCC/ -├── crt0_v6m.s -├── crt0_v7m.s -├── crt1.c -├── ld -│   ├── MK20DX128BLDR3.ld -│   ├── MK20DX128BLDR4.ld -│   ├── MK20DX128.ld -│   ├── MK20DX256.ld -│   ├── MKL25Z128.ld -│   ├── MKL26Z128.ld -│   ├── MKL26Z64.ld -│   └── STM32L476xG.ld -├── mk -│   ├── startup_k20x5.mk -│   ├── startup_k20x7.mk -│   ├── startup_k20x.mk -│   ├── startup_kl2x.mk -│   └── startup_stm32l4xx.mk -├── rules.ld -├── rules.mk -└── vectors.c - -chibios/os/hal/ -├── boards -│   ├── FREESCALE_FREEDOM_K20D50M -│   │   ├── board.c -│   │   ├── board.h -│   │   └── board.mk -│   ├── MCHCK_K20 -│   │   ├── board.c -│   │   ├── board.h -│   │   └── board.mk -│   ├── PJRC_TEENSY_3 -│   │   ├── board.c -│   │   ├── board.h -│   │   └── board.mk -│   ├── PJRC_TEENSY_3_1 -│   │   ├── board.c -│   │   ├── board.h -│   │   └── board.mk -│   ├── PJRC_TEENSY_LC -│   │   ├── board.c -│   │   ├── board.h -│   │   └── board.mk -│   ├── readme.txt -│   ├── simulator -│   │   ├── board.c -│   │   ├── board.h -│   │   └── board.mk -│   ├── ST_NUCLEO_F030R8 -│   │   ├── board.c -│   │   ├── board.h -│   │   ├── board.mk -│   │   └── cfg -│   │   └── board.chcfg -├── hal.mk -├── include -│   ├── adc.h -│   ├── can.h -│   ├── dac.h -│   ├── ext.h -│   ├── gpt.h -│   ├── hal_channels.h -│   ├── hal_files.h -│   ├── hal.h -│   ├── hal_ioblock.h -│   ├── hal_mmcsd.h -│   ├── hal_queues.h -│   ├── hal_streams.h -│   ├── i2c.h -│   ├── i2s.h -│   ├── icu.h -│   ├── mac.h -│   ├── mii.h -│   ├── mmc_spi.h -│   ├── pal.h -│   ├── pwm.h -│   ├── rtc.h -│   ├── sdc.h -│   ├── serial.h -│   ├── serial_usb.h -│   ├── spi.h -│   ├── st.h -│   ├── uart.h -│   └── usb.h -├── lib -│   └── streams -│   ├── chprintf.c -│   ├── chprintf.h -│   ├── memstreams.c -│   ├── memstreams.h -│   ├── nullstreams.c -│   └── nullstreams.h -├── osal -│   ├── nil -│   │   ├── osal.c -│   │   ├── osal.h -│   │   └── osal.mk -│   ├── os-less -│   │   └── ARMCMx -│   │   ├── osal.c -│   │   ├── osal.h -│   │   └── osal.mk -│   └── rt -│   ├── osal.c -│   ├── osal.h -│   └── osal.mk -├── ports -│   ├── AVR -│   ├── common -│   │   └── ARMCMx -│   │   ├── mpu.h -│   │   ├── nvic.c -│   │   └── nvic.h -│   ├── KINETIS -│   │   ├── K20x -│   │   │   ├── hal_lld.c -│   │   │   ├── hal_lld.h -│   │   │   ├── kinetis_registry.h -│   │   │   ├── platform.dox -│   │   │   ├── platform.mk -│   │   │   ├── pwm_lld.c -│   │   │   ├── pwm_lld.h -│   │   │   ├── spi_lld.c -│   │   │   └── spi_lld.h -│   │   ├── KL2x -│   │   │   ├── hal_lld.c -│   │   │   ├── hal_lld.h -│   │   │   ├── kinetis_registry.h -│   │   │   ├── platform.mk -│   │   │   ├── pwm_lld.c -│   │   │   └── pwm_lld.h -│   │   ├── LLD -│   │   │   ├── adc_lld.c -│   │   │   ├── adc_lld.h -│   │   │   ├── ext_lld.c -│   │   │   ├── ext_lld.h -│   │   │   ├── gpt_lld.c -│   │   │   ├── gpt_lld.h -│   │   │   ├── i2c_lld.c -│   │   │   ├── i2c_lld.h -│   │   │   ├── pal_lld.c -│   │   │   ├── pal_lld.h -│   │   │   ├── serial_lld.c -│   │   │   ├── serial_lld.h -│   │   │   ├── st_lld.c -│   │   │   ├── st_lld.h -│   │   │   ├── usb_lld.c -│   │   │   └── usb_lld.h -│   │   └── README.md -│   ├── LPC -│   ├── simulator -│   └── STM32 -├── src -│   ├── adc.c -│   ├── can.c -│   ├── dac.c -│   ├── ext.c -│   ├── gpt.c -│   ├── hal.c -│   ├── hal_mmcsd.c -│   ├── hal_queues.c -│   ├── i2c.c -│   ├── i2s.c -│   ├── icu.c -│   ├── mac.c -│   ├── mmc_spi.c -│   ├── pal.c -│   ├── pwm.c -│   ├── rtc.c -│   ├── sdc.c -│   ├── serial.c -│   ├── serial_usb.c -│   ├── spi.c -│   ├── st.c -│   ├── uart.c -│   └── usb.c -└── templates - ├── adc_lld.c - ├── adc_lld.h - ├── can_lld.c - ├── can_lld.h - ├── dac_lld.c - ├── dac_lld.h - ├── ext_lld.c - ├── ext_lld.h - ├── gpt_lld.c - ├── gpt_lld.h - ├── halconf.h - ├── hal_lld.c - ├── hal_lld.h - ├── i2c_lld.c - ├── i2c_lld.h - ├── i2s_lld.c - ├── i2s_lld.h - ├── icu_lld.c - ├── icu_lld.h - ├── mac_lld.c - ├── mac_lld.h - ├── mcuconf.h - ├── osal - │   ├── osal.c - │   ├── osal.h - │   └── osal.mk - ├── pal_lld.c - ├── pal_lld.h - ├── platform.mk - ├── pwm_lld.c - ├── pwm_lld.h - ├── rtc_lld.c - ├── rtc_lld.h - ├── sdc_lld.c - ├── sdc_lld.h - ├── serial_lld.c - ├── serial_lld.h - ├── spi_lld.c - ├── spi_lld.h - ├── st_lld.c - ├── st_lld.h - ├── uart_lld.c - ├── uart_lld.h - ├── usb_lld.c - └── usb_lld.h diff --git a/keyboards/infinity60/led_controller.c b/keyboards/infinity60/led_controller.c index 59ca833b6..c162e9a8f 100644 --- a/keyboards/infinity60/led_controller.c +++ b/keyboards/infinity60/led_controller.c @@ -72,8 +72,6 @@ along with this program. If not, see . #define BREATHE_LED_ADDRESS CAPS_LOCK_LED_ADDRESS #endif -#define DEBUG_ENABLED 1 - /* ================= * ChibiOS I2C setup * ================= */ @@ -145,7 +143,6 @@ void is31_init(void) { __builtin_memset(full_page,0,0xB4+1); // zero function page, all registers (assuming full_page is all zeroes) is31_write_data(IS31_FUNCTIONREG, full_page, 0xD + 1); - // disable hardware shutdown palSetPadMode(GPIOB, 16, PAL_MODE_OUTPUT_PUSHPULL); palSetPad(GPIOB, 16); chThdSleepMilliseconds(10); @@ -182,7 +179,7 @@ static THD_FUNCTION(LEDthread, arg) { uint8_t pwm_step_status, page_status; //mailbox variables - uint8_t temp, msg_type, msg_led; + uint8_t temp, msg_type, msg_pin, msg_col, msg_led; msg_t msg; /* //control register variables @@ -199,14 +196,17 @@ page_status = 0; //start frame 0 (all off/on) // (messages are queued (up to LED_MAILBOX_NUM_MSGS) if they can't // be processed right away) chMBFetch(&led_mailbox, &msg, TIME_INFINITE); - msg_type = (msg >> 8) & 0xFF; //first byte is msg type - msg_led = (msg) & 0xFF; //second byte is action information + msg_col = (msg >> 24) & 0xFF;//if needed + msg_pin = (msg >> 16) & 0XFF;//if needed (SET_FULL_ROW) + msg_type = (msg >> 8) & 0xFF; //second byte is msg type + msg_led = (msg) & 0xFF; //first byte is action information xprintf("--------------------\n"); - chThdSleepMilliseconds(10); xprintf("mailbox fetch\nmsg: %X\n", msg); - chThdSleepMilliseconds(10); - xprintf("type: %X - led: %X\n", msg_type, msg_led); + chThdSleepMilliseconds(20); + xprintf("type: %X - pin: %X\n", msg_type, msg_pin); + chThdSleepMilliseconds(20); + xprintf("col: %X - led: %X\n", msg_col, msg_led); chThdSleepMilliseconds(10); switch (msg_type){ @@ -214,8 +214,12 @@ page_status = 0; //start frame 0 (all off/on) //TODO: lighting key led on keypress break; - //TODO: BLINK_ON/OFF_LED - break; + case SET_FULL_ROW: + //write full byte to pin address, msg_pin = pin #, msg_led = byte to write + //writes only to current page + xprintf("SET_FULL_ROW\n"); + write_led_byte(page_status,msg_pin,msg_led); + break; case OFF_LED: //on/off/toggle single led, msg_led = row/col of led @@ -255,6 +259,7 @@ page_status = 0; //start frame 0 (all off/on) chThdSleepMilliseconds(10); set_led_bit(7, control_register_word, msg_led, 6); is31_write_data (7, control_register_word, 0x02); + break; case TOGGLE_ALL: xprintf("TOGGLE_ALL: %d\n", msg_led); @@ -272,17 +277,12 @@ page_status = 0; //start frame 0 (all off/on) if (page_status > 0) { is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, 0); - } - //maintain lock leds - if (host_keyboard_leds() & (1< 0 && j % 9 == 0){ - xprintf("\n"); - } - switch (j) { - case 0: - xprintf("\n--on-off--\n"); - chThdSleepMilliseconds(2); - break; - case 0x12: - xprintf("\n--blink--\n"); - chThdSleepMilliseconds(2); - break; - } - is31_read_register(pages[i],j,&temp); - xprintf("%02X, ", temp); - chThdSleepMilliseconds(2); - } + } +} - xprintf("\n--pwm--\n"); - chThdSleepMilliseconds(2); - for(j=0x24;j<0xB4;j++) { - is31_read_register(pages[i],j,&temp); - xprintf("%02X, ", temp); - chThdSleepMilliseconds(2); - if(j > 0x24 && (j-4) % 8 == 0){ - xprintf("\n"); - } - } - xprintf("\n"); - } - - //Function Register - xprintf("\n--FUNCTION--\n"); - chThdSleepMilliseconds(2); - for(j=0;j<0x0D;j++) { - is31_read_register(0x0B,j,&temp); - switch(j) { - case 0: - xprintf("Config %02X", temp); - chThdSleepMilliseconds(2); - break; - case 1: - xprintf(" - Pict %02X\n", temp); - chThdSleepMilliseconds(2); - break; - case 2: - xprintf("Auto1 %02X", temp); - chThdSleepMilliseconds(2); - break; - case 3: - xprintf(" - Auto2 %02X\n", temp); - chThdSleepMilliseconds(2); - break; - case 5: - xprintf("Disp %02X", temp); - chThdSleepMilliseconds(2); - break; - case 6: - xprintf(" - Audio %02X\n", temp); - chThdSleepMilliseconds(2); - break; - case 7: - xprintf("Frame %02X", temp); - chThdSleepMilliseconds(2); - break; - case 8: - xprintf(" - Breath1 %02X\n", temp); - chThdSleepMilliseconds(2); - break; - case 9: - xprintf("Breath2 %02X - ", temp); - chThdSleepMilliseconds(2); - break; - case 10: - xprintf(" - Shut %02X\n", temp); - chThdSleepMilliseconds(2); - break; - case 11: - xprintf("AGC %02X", temp); - chThdSleepMilliseconds(2); - break; - case 12: - xprintf(" - ADC %02X\n", temp); - chThdSleepMilliseconds(2); - break; - } +/* ============================== + * debug function + * ============================== */ +void print_debug(uint8_t page) { + uint8_t j, debug_temp; + //debugging code - print full led/blink/pwm registers on each frame + xprintf("----layer state----: %X\n", layer_state); + xprintf("page: %d\n", page); + chThdSleepMilliseconds(10); + for(j=0;j<0x24;j++){ + if(j > 0 && j % 9 == 0){ + xprintf("\n"); + } + switch (j) { + case 0: + xprintf("\n--on-off--\n"); + chThdSleepMilliseconds(10); + break; + case 0x12: + xprintf("\n--blink--\n"); + chThdSleepMilliseconds(10); + break; + } + is31_read_register(page,j,&debug_temp); + xprintf("%02X, ", debug_temp); + chThdSleepMilliseconds(10); + } + + xprintf("\n--pwm--\n"); + chThdSleepMilliseconds(10); + for(j=0x24;j<0xB4;j++) { + is31_read_register(page,j,&debug_temp); + xprintf("%02X, ", debug_temp); + chThdSleepMilliseconds(10); + if(j > 0x24 && (j-3) % 8 == 0){ + xprintf("\n"); + } + } + xprintf("\n"); + + //Function Register + xprintf("\n--FUNCTION--\n"); + chThdSleepMilliseconds(10); + for(j=0;j<0x0D;j++) { + is31_read_register(0x0B,j,&debug_temp); + switch(j) { + case 0: + xprintf("Config %02X", debug_temp); + chThdSleepMilliseconds(2); + break; + case 1: + xprintf(" - Pict %02X\n", debug_temp); + chThdSleepMilliseconds(2); + break; + case 2: + xprintf("Auto1 %02X", debug_temp); + chThdSleepMilliseconds(2); + break; + case 3: + xprintf(" - Auto2 %02X\n", debug_temp); + chThdSleepMilliseconds(2); + break; + case 5: + xprintf("Disp %02X", debug_temp); + chThdSleepMilliseconds(2); + break; + case 6: + xprintf(" - Audio %02X\n", debug_temp); + chThdSleepMilliseconds(2); + break; + case 7: + xprintf("Frame %02X", debug_temp); + chThdSleepMilliseconds(2); + break; + case 8: + xprintf(" - Breath1 %02X\n", debug_temp); + chThdSleepMilliseconds(2); + break; + case 9: + xprintf("Breath2 %02X - ", debug_temp); + chThdSleepMilliseconds(2); + break; + case 10: + xprintf(" - Shut %02X\n", debug_temp); + chThdSleepMilliseconds(2); + break; + case 11: + xprintf("AGC %02X", debug_temp); + chThdSleepMilliseconds(2); + break; + case 12: + xprintf(" - ADC %02X\n", debug_temp); + chThdSleepMilliseconds(2); + break; } -#endif } } @@ -523,7 +518,7 @@ void set_led_bit (uint8_t page, uint8_t *led_control_reg, uint8_t led_addr, uint //returns 2 bytes led control register address and byte to write //0 - bit off, 1 - bit on, 2 - toggle bit - uint8_t control_reg_addr, column_bit, column_byte, temp, blink_on; + uint8_t control_reg_addr, column_bit, column_byte, bit_temp, blink_on; //check for valid led address if (led_addr < 0 || led_addr > 87 || led_addr % 10 > 8) { @@ -541,18 +536,28 @@ void set_led_bit (uint8_t page, uint8_t *led_control_reg, uint8_t led_addr, uint //first byte is led control register address 0x00 //msg_led tens column is pin#, ones column is bit position in 8-bit mask control_reg_addr = ((led_addr / 10) % 10 - 1 ) * 0x02;// A-register is every other byte - xprintf("pre-reg_addr: %X\n", control_reg_addr); + xprintf("pre-reg_addr: %2X\n", control_reg_addr); chThdSleepMilliseconds(10); control_reg_addr += blink_on == 1 ? 0x12 : 0x00;//shift 12 bytes to blink register - xprintf("blink-reg_addr: %X\n", control_reg_addr); + xprintf("blink-reg_addr: %2X\n", control_reg_addr); + chThdSleepMilliseconds(10); + xprintf("page: %2X\n", page); chThdSleepMilliseconds(10); + + is31_read_register(page, 0x06, &bit_temp);//maintain status of leds on this byte + xprintf("reg 06: %2X\n", bit_temp); + is31_read_register(page, 0x17, &bit_temp);//maintain status of leds on this byte + xprintf("reg 17: %2X\n", bit_temp); + is31_read_register(page, 0x18, &bit_temp);//maintain status of leds on this byte + xprintf("reg 18: %2X\n", bit_temp); + is31_read_register(page, 0x19, &bit_temp);//maintain status of leds on this byte + xprintf("reg 19: %2X\n", bit_temp); + is31_read_register(page, control_reg_addr, &bit_temp);//maintain status of leds on this byte column_bit = 1<<(led_addr % 10 - 1); + column_byte = bit_temp; - is31_read_register(page, control_reg_addr, &temp);//maintain status of leds on this byte - column_byte = temp; - - xprintf("column_byte read: %X\n", column_byte); + xprintf("column_byte read: %2X\n", column_byte); chThdSleepMilliseconds(10); switch(action) { case 0: @@ -565,7 +570,7 @@ void set_led_bit (uint8_t page, uint8_t *led_control_reg, uint8_t led_addr, uint column_byte ^= column_bit; break; } - xprintf("column_byte write: %X\n", column_byte); + xprintf("column_byte write: %2X\n", column_byte); chThdSleepMilliseconds(10); //return word to be written in register @@ -574,47 +579,59 @@ void set_led_bit (uint8_t page, uint8_t *led_control_reg, uint8_t led_addr, uint } void write_led_byte (uint8_t page, uint8_t row, uint8_t led_byte) { - uint8_t led_control_word[2] = {0};//register address and led on/off mask + uint8_t led_control_word[2] = {0};//register address and on/off byte led_control_word[0] = (row - 1 ) * 0x02;// A-register is every other byte - led_control_word[1] = led_byte;// A-register is every other byte - is31_write_data(page, led_control_word, 0x13); + led_control_word[1] = led_byte; + is31_write_data(page, led_control_word, 0x02); } void write_led_page (uint8_t page, uint8_t *user_led_array, uint8_t led_count) { uint8_t i; uint8_t pin, col; - uint8_t led_control_register[0x13] = {0};//led control register start address + 0x12 bytes + uint8_t led_control_register[0x13] = {0};//control register start address + 0x12 bytes __builtin_memset(led_control_register,0,13); for(i=0;i Date: Mon, 8 May 2017 14:35:08 -0700 Subject: [PATCH 024/238] CLeaned out debug code --- keyboards/infinity60/led.c | 4 - keyboards/infinity60/led_controller.c | 273 ++------------------------ keyboards/infinity60/led_controller.h | 1 - 3 files changed, 13 insertions(+), 265 deletions(-) diff --git a/keyboards/infinity60/led.c b/keyboards/infinity60/led.c index 92069dc59..d60c76fd8 100644 --- a/keyboards/infinity60/led.c +++ b/keyboards/infinity60/led.c @@ -29,26 +29,22 @@ void led_set(uint8_t usb_led) { msg_t msg; if (usb_led & (1<. /* * LED controller code - * WF uses IS31FL3731C matrix LED driver from ISSI + * IS31FL3731C matrix LED driver from ISSI * datasheet: http://www.issi.com/WW/pdf/31FL3731C.pdf */ @@ -56,9 +56,7 @@ along with this program. If not, see . order same as above (CA 1st row (8bytes), CB 1st row (8bytes), ...) */ -/* Which LED should be used for CAPS LOCK indicator - * The usual Caps Lock position is C4-6, so the address is - * 0x24 + (4-1)*0x10 + (8-1) = 0x59 */ +// Which LED should be used for CAPS LOCK indicator #if !defined(CAPS_LOCK_LED_ADDRESS) #define CAPS_LOCK_LED_ADDRESS 46 #endif @@ -90,7 +88,6 @@ uint8_t rx[1] __attribute__((aligned(2))); uint8_t full_page[0xB4+1] = {0}; // LED mask (which LEDs are present, selected by bits) -// See page comment above, control alternates CA matrix/CB matrix // IC60 pcb uses only CA matrix. // Each byte is a control pin for 8 leds ordered 8-1 const uint8_t all_on_leds_mask[0x12] = { @@ -182,11 +179,6 @@ static THD_FUNCTION(LEDthread, arg) { uint8_t temp, msg_type, msg_pin, msg_col, msg_led; msg_t msg; -/* //control register variables - uint8_t page, save_page, save_breath1, save_breath2; - msg_t msg, retval; -*/ - // initialize persistent variables pwm_step_status = 4; //full brightness page_status = 0; //start frame 0 (all off/on) @@ -197,77 +189,51 @@ page_status = 0; //start frame 0 (all off/on) // be processed right away) chMBFetch(&led_mailbox, &msg, TIME_INFINITE); msg_col = (msg >> 24) & 0xFF;//if needed - msg_pin = (msg >> 16) & 0XFF;//if needed (SET_FULL_ROW) + msg_pin = (msg >> 16) & 0XFF;//if needed (e.g. SET_FULL_ROW) msg_type = (msg >> 8) & 0xFF; //second byte is msg type msg_led = (msg) & 0xFF; //first byte is action information - xprintf("--------------------\n"); - xprintf("mailbox fetch\nmsg: %X\n", msg); - chThdSleepMilliseconds(20); - xprintf("type: %X - pin: %X\n", msg_type, msg_pin); - chThdSleepMilliseconds(20); - xprintf("col: %X - led: %X\n", msg_col, msg_led); - chThdSleepMilliseconds(10); - switch (msg_type){ - case KEY_LIGHT: - //TODO: lighting key led on keypress - break; - case SET_FULL_ROW: //write full byte to pin address, msg_pin = pin #, msg_led = byte to write //writes only to current page - xprintf("SET_FULL_ROW\n"); write_led_byte(page_status,msg_pin,msg_led); break; case OFF_LED: //on/off/toggle single led, msg_led = row/col of led - xprintf("OFF_LED: %d\n", msg_led); - chThdSleepMilliseconds(10); set_led_bit(7, control_register_word, msg_led, 0); is31_write_data (7, control_register_word, 0x02); break; case ON_LED: - xprintf("ON_LED: %d\n", msg_led); - chThdSleepMilliseconds(10); set_led_bit(7, control_register_word, msg_led, 1); is31_write_data (7, control_register_word, 0x02); break; case TOGGLE_LED: - xprintf("TOGGLE_LED: %d\n", msg_led); - chThdSleepMilliseconds(10); set_led_bit(7, control_register_word, msg_led, 2); is31_write_data (7, control_register_word, 0x02); break; case BLINK_OFF_LED: //on/off/toggle single led, msg_led = row/col of led - xprintf("BLINK_ON: %d\n", msg_led); - chThdSleepMilliseconds(10); set_led_bit(7, control_register_word, msg_led, 4); is31_write_data (7, control_register_word, 0x02); break; case BLINK_ON_LED: - xprintf("BLINK_OFF: %d\n", msg_led); - chThdSleepMilliseconds(10); set_led_bit(7, control_register_word, msg_led, 5); is31_write_data (7, control_register_word, 0x02); break; case BLINK_TOGGLE_LED: - xprintf("BLINK_TOGGLE: %d\n", msg_led); - chThdSleepMilliseconds(10); set_led_bit(7, control_register_word, msg_led, 6); is31_write_data (7, control_register_word, 0x02); break; case TOGGLE_ALL: - xprintf("TOGGLE_ALL: %d\n", msg_led); - chThdSleepMilliseconds(10); //msg_led = unused - is31_read_register(0, 0x00, &temp);//if first byte is on, then toggle frame 0 off + is31_read_register(0, 0x00, &temp); led_control_reg[0] = 0; + //if first byte is on, then toggle frame 0 off if (temp==0 || page_status > 0) { __builtin_memcpy(led_control_reg+1, all_on_leds_mask, 0x12); } else { @@ -287,8 +253,6 @@ page_status = 0; //start frame 0 (all off/on) case TOGGLE_BACKLIGHT: //msg_led = on/off - xprintf("TOGGLE_BACKLIGHT\n"); - chThdSleepMilliseconds(10); //populate the 9 byte rows to be written to each pin, first byte is register (pin) address if (msg_led == 1) { @@ -304,13 +268,9 @@ page_status = 0; //start frame 0 (all off/on) } break; - case DISPLAY_PAGE://show single layer indicator or full map of layer - //msg_led = page to toggle on - xprintf("DISPLAY_PAGE\n"); - chThdSleepMilliseconds(10); + case DISPLAY_PAGE: + //msg_led = page to toggle on if (page_status != msg_led) { - xprintf(" - new page\n"); - chThdSleepMilliseconds(10); is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, msg_led); page_status = msg_led; @@ -321,33 +281,22 @@ page_status = 0; //start frame 0 (all off/on) case RESET_PAGE: //led_msg = page to reset - xprintf("RESET_PAGE\n"); - chThdSleepMilliseconds(10); led_control_reg[0] = 0; __builtin_memset(led_control_reg+1, 0, 0x12); is31_write_data(msg_led, led_control_reg, 0x13); break; case TOGGLE_NUM_LOCK: - //msg_led = 0 or 1, off/on - xprintf("NUMLOCK: %d\n", msg_led); - chThdSleepMilliseconds(10); + //msg_led = 0 or 1, off/on set_lock_leds(NUM_LOCK_LED_ADDRESS, msg_led, page_status); break; - case TOGGLE_CAPS_LOCK: - xprintf("CAPSLOCK: %d\n", msg_led); - chThdSleepMilliseconds(10); - //msg_led = 0 or 1, off/on + //msg_led = 0 or 1, off/on set_lock_leds(CAPS_LOCK_LED_ADDRESS, msg_led, page_status); break; - //TODO: MODE_BREATH - case STEP_BRIGHTNESS: - xprintf("STEP_BACKLIGHT\n"); - chThdSleepMilliseconds(10); - //led_msg = step pwm up or down + //led_msg = step pwm up or down switch (msg_led) { case 0: if (pwm_step_status == 0) { @@ -375,137 +324,6 @@ page_status = 0; //start frame 0 (all off/on) is31_write_data(0,pwm_register_array,9); } break; - -/* case LED_MSG_SLEEP_LED_ON: - // save current settings - is31_read_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, &save_page); - is31_read_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL1, &save_breath1); - is31_read_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL2, &save_breath2); - // use pages 7 and 8 for (hardware) breathing (assuming they're empty) - is31_write_register(6, BREATHE_LED_ADDRESS, 0xFF); - is31_write_register(7, BREATHE_LED_ADDRESS, 0x00); - is31_write_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL1, (6<<4)|6); - is31_write_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL2, IS31_REG_BREATHCTRL2_ENABLE|3); - retval = MSG_TIMEOUT; - temp = 6; - while(retval == MSG_TIMEOUT) { - // switch to the other page - is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, temp); - temp = (temp == 6 ? 7 : 6); - // the times should be sufficiently long for IS31 to finish switching pages - retval = chMBFetch(&led_mailbox, &msg, MS2ST(temp == 6 ? 4000 : 6000)); - } - // received a message (should be a wakeup), so restore previous state - chThdSleepMilliseconds(3000); // need to wait until the page change finishes - // note: any other messages are queued - is31_write_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL1, save_breath1); - is31_write_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL2, save_breath2); - is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, save_page); - break; - case LED_MSG_SLEEP_LED_OFF: - // should not get here; wakeup should be received in the branch above break; - break; -*/ - xprintf("--------------------\n"); - chThdSleepMilliseconds(10); - } - } -} - -/* ============================== - * debug function - * ============================== */ -void print_debug(uint8_t page) { - uint8_t j, debug_temp; - //debugging code - print full led/blink/pwm registers on each frame - xprintf("----layer state----: %X\n", layer_state); - xprintf("page: %d\n", page); - chThdSleepMilliseconds(10); - for(j=0;j<0x24;j++){ - if(j > 0 && j % 9 == 0){ - xprintf("\n"); - } - switch (j) { - case 0: - xprintf("\n--on-off--\n"); - chThdSleepMilliseconds(10); - break; - case 0x12: - xprintf("\n--blink--\n"); - chThdSleepMilliseconds(10); - break; - } - is31_read_register(page,j,&debug_temp); - xprintf("%02X, ", debug_temp); - chThdSleepMilliseconds(10); - } - - xprintf("\n--pwm--\n"); - chThdSleepMilliseconds(10); - for(j=0x24;j<0xB4;j++) { - is31_read_register(page,j,&debug_temp); - xprintf("%02X, ", debug_temp); - chThdSleepMilliseconds(10); - if(j > 0x24 && (j-3) % 8 == 0){ - xprintf("\n"); - } - } - xprintf("\n"); - - //Function Register - xprintf("\n--FUNCTION--\n"); - chThdSleepMilliseconds(10); - for(j=0;j<0x0D;j++) { - is31_read_register(0x0B,j,&debug_temp); - switch(j) { - case 0: - xprintf("Config %02X", debug_temp); - chThdSleepMilliseconds(2); - break; - case 1: - xprintf(" - Pict %02X\n", debug_temp); - chThdSleepMilliseconds(2); - break; - case 2: - xprintf("Auto1 %02X", debug_temp); - chThdSleepMilliseconds(2); - break; - case 3: - xprintf(" - Auto2 %02X\n", debug_temp); - chThdSleepMilliseconds(2); - break; - case 5: - xprintf("Disp %02X", debug_temp); - chThdSleepMilliseconds(2); - break; - case 6: - xprintf(" - Audio %02X\n", debug_temp); - chThdSleepMilliseconds(2); - break; - case 7: - xprintf("Frame %02X", debug_temp); - chThdSleepMilliseconds(2); - break; - case 8: - xprintf(" - Breath1 %02X\n", debug_temp); - chThdSleepMilliseconds(2); - break; - case 9: - xprintf("Breath2 %02X - ", debug_temp); - chThdSleepMilliseconds(2); - break; - case 10: - xprintf(" - Shut %02X\n", debug_temp); - chThdSleepMilliseconds(2); - break; - case 11: - xprintf("AGC %02X", debug_temp); - chThdSleepMilliseconds(2); - break; - case 12: - xprintf(" - ADC %02X\n", debug_temp); - chThdSleepMilliseconds(2); - break; } } } @@ -515,50 +333,29 @@ void print_debug(uint8_t page) { * ============================== */ void set_led_bit (uint8_t page, uint8_t *led_control_reg, uint8_t led_addr, uint8_t action) { - //returns 2 bytes led control register address and byte to write + //returns 2 bytes: led control register address and byte to write //0 - bit off, 1 - bit on, 2 - toggle bit uint8_t control_reg_addr, column_bit, column_byte, bit_temp, blink_on; //check for valid led address if (led_addr < 0 || led_addr > 87 || led_addr % 10 > 8) { - xprintf("Invalid address: %d\n", led_addr); return; } - xprintf("set_led_bit: %d\n", led_addr); - xprintf("action: %d\n", action); - chThdSleepMilliseconds(10); - //check blink bit + //check for blink bit blink_on = action>>2; action &= ~(1<<2); //strip blink bit //first byte is led control register address 0x00 //msg_led tens column is pin#, ones column is bit position in 8-bit mask control_reg_addr = ((led_addr / 10) % 10 - 1 ) * 0x02;// A-register is every other byte - xprintf("pre-reg_addr: %2X\n", control_reg_addr); - chThdSleepMilliseconds(10); control_reg_addr += blink_on == 1 ? 0x12 : 0x00;//shift 12 bytes to blink register - xprintf("blink-reg_addr: %2X\n", control_reg_addr); - chThdSleepMilliseconds(10); - xprintf("page: %2X\n", page); - chThdSleepMilliseconds(10); - - is31_read_register(page, 0x06, &bit_temp);//maintain status of leds on this byte - xprintf("reg 06: %2X\n", bit_temp); - is31_read_register(page, 0x17, &bit_temp);//maintain status of leds on this byte - xprintf("reg 17: %2X\n", bit_temp); - is31_read_register(page, 0x18, &bit_temp);//maintain status of leds on this byte - xprintf("reg 18: %2X\n", bit_temp); - is31_read_register(page, 0x19, &bit_temp);//maintain status of leds on this byte - xprintf("reg 19: %2X\n", bit_temp); is31_read_register(page, control_reg_addr, &bit_temp);//maintain status of leds on this byte column_bit = 1<<(led_addr % 10 - 1); column_byte = bit_temp; - xprintf("column_byte read: %2X\n", column_byte); - chThdSleepMilliseconds(10); switch(action) { case 0: column_byte &= ~column_bit; @@ -570,8 +367,6 @@ void set_led_bit (uint8_t page, uint8_t *led_control_reg, uint8_t led_addr, uint column_byte ^= column_bit; break; } - xprintf("column_byte write: %2X\n", column_byte); - chThdSleepMilliseconds(10); //return word to be written in register led_control_reg[0] = control_reg_addr; @@ -589,7 +384,7 @@ void write_led_byte (uint8_t page, uint8_t row, uint8_t led_byte) { void write_led_page (uint8_t page, uint8_t *user_led_array, uint8_t led_count) { uint8_t i; uint8_t pin, col; - uint8_t led_control_register[0x13] = {0};//control register start address + 0x12 bytes + uint8_t led_control_register[0x13] = {0}; __builtin_memset(led_control_register,0,13); @@ -607,30 +402,15 @@ void set_lock_leds(uint8_t led_addr, uint8_t led_action, uint8_t page) { uint8_t lock_temp; uint8_t led_control_word[2] = {0}; - xprintf("---set lock---\n"); - chThdSleepMilliseconds(10); - //blink if all leds are on if (page == 0) { is31_read_register(0, 0x00, &lock_temp); - xprintf("AllOnReg: %2X\n", lock_temp); - chThdSleepMilliseconds(10); if (lock_temp == 0xFF) { - xprintf("AllOntrue\n"); - chThdSleepMilliseconds(10); led_action |= (1<<2); //set blink bit - } else { - xprintf("AllOnfalse\n"); - chThdSleepMilliseconds(10); } } set_led_bit(page,led_control_word,led_addr,led_action); - - xprintf("led_word: %2X", led_control_word[0]); - xprintf("%X\n", led_control_word[1]); - chThdSleepMilliseconds(10); - is31_write_data(page, led_control_word, 0x02); } @@ -679,30 +459,3 @@ void led_controller_init(void) { chMBObjectInit(&led_mailbox, led_mailbox_queue, LED_MAILBOX_NUM_MSGS); chThdCreateStatic(waLEDthread, sizeof(waLEDthread), LOWPRIO, LEDthread, NULL); } - -//TODO: Don't know equivalent QMK hooks for these -// -//void hook_usb_suspend_entry(void) { -//#ifdef SLEEP_LED_ENABLE -// chSysLockFromISR(); -// chMBPostI(&led_mailbox, LED_MSG_SLEEP_LED_ON); -// chSysUnlockFromISR(); -//#endif /* SLEEP_LED_ENABLE */ -//} -// -//void hook_usb_suspend_loop(void) { -// chThdSleepMilliseconds(100); -// /* Remote wakeup */ -// if((USB_DRIVER.status & 2) && suspend_wakeup_condition()) { -// send_remote_wakeup(&USB_DRIVER); -// } -//} -// -//void hook_usb_wakeup(void) { -//#ifdef SLEEP_LED_ENABLE -// chSysLockFromISR(); -// chMBPostI(&led_mailbox, LED_MSG_SLEEP_LED_OFF); -// chSysUnlockFromISR(); -//#endif /* SLEEP_LED_ENABLE */ -//} -//*/ diff --git a/keyboards/infinity60/led_controller.h b/keyboards/infinity60/led_controller.h index 7bdef7ae6..457b21a92 100644 --- a/keyboards/infinity60/led_controller.h +++ b/keyboards/infinity60/led_controller.h @@ -31,7 +31,6 @@ msg_t is31_read_register(uint8_t page, uint8_t reg, uint8_t *result); * ============================*/ void led_controller_init(void); -void print_debug (uint8_t page); #define CAPS_LOCK_LED_ADDRESS 46 //pin matrix location #define NUM_LOCK_LED_ADDRESS 85 From f1d81d2cc6f257925d8582da630aadf5170bd878 Mon Sep 17 00:00:00 2001 From: jpetermans Date: Mon, 8 May 2017 14:55:57 -0700 Subject: [PATCH 025/238] minor change on lock leds --- keyboards/infinity60/led_controller.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/keyboards/infinity60/led_controller.c b/keyboards/infinity60/led_controller.c index 707b4e0df..75806d54b 100644 --- a/keyboards/infinity60/led_controller.c +++ b/keyboards/infinity60/led_controller.c @@ -317,19 +317,19 @@ page_status = 0; //start frame 0 (all off/on) case TOGGLE_NUM_LOCK: //msg_led = 0 or 1, off/on - set_lock_leds(NUM_LOCK_LED_ADDRESS, msg_led); + set_lock_leds(NUM_LOCK_LED_ADDRESS, 1); break; case TOGGLE_CAPS_LOCK: //msg_led = 0 or 1, off/on - set_lock_leds(CAPS_LOCK_LED_ADDRESS, msg_led); + set_lock_leds(CAPS_LOCK_LED_ADDRESS, 1); break; //TODO: MODE_BREATH case MODE_BREATH: break; case STEP_BRIGHTNESS: - xprintf("STEP_BACKLIGHT\n"); + xprintf("TOGGLE_BACKLIGHT\n"); chThdSleepMilliseconds(10); //led_msg = step pwm up or down switch (msg_led) { @@ -459,10 +459,8 @@ void set_led_bit (uint8_t page, uint8_t *led_control_reg, uint8_t led_addr, uint } void set_lock_leds(uint8_t led_addr, uint8_t led_action) { - uint8_t page, temp; + uint8_t page; uint8_t led_control_word[2] = {0}; - //TODO: this function call could send led address vs lock_type. - //however, the switch/case allows for additional steps, like audio, depending on type //ignore frame0 if all leds are on or if option set in led_controller.h //TODO: blink of all leds are on, clear blink register if not From 5df74f3ba73f18f6bbd13b82a3a960c86fa592e1 Mon Sep 17 00:00:00 2001 From: jpetermans Date: Mon, 8 May 2017 15:13:02 -0700 Subject: [PATCH 026/238] updated keymap for new led functions --- .../infinity60/keymaps/jpetermans/Makefile | 2 - .../infinity60/keymaps/jpetermans/keymap.c | 284 ++++++++++-------- .../keymaps/jpetermans/keymap_jpetermans.h | 78 ----- .../infinity60/keymaps/jpetermans/readme.md | 79 +++++ 4 files changed, 242 insertions(+), 201 deletions(-) delete mode 100644 keyboards/infinity60/keymaps/jpetermans/keymap_jpetermans.h create mode 100644 keyboards/infinity60/keymaps/jpetermans/readme.md diff --git a/keyboards/infinity60/keymaps/jpetermans/Makefile b/keyboards/infinity60/keymaps/jpetermans/Makefile index 225e4cad4..df3d1e952 100644 --- a/keyboards/infinity60/keymaps/jpetermans/Makefile +++ b/keyboards/infinity60/keymaps/jpetermans/Makefile @@ -1,5 +1,3 @@ -#BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality -#BOOTMAGIC_ENABLE = yes ifndef QUANTUM_DIR include ../../../../Makefile diff --git a/keyboards/infinity60/keymaps/jpetermans/keymap.c b/keyboards/infinity60/keymaps/jpetermans/keymap.c index 6f14b66cb..1afb7c067 100644 --- a/keyboards/infinity60/keymaps/jpetermans/keymap.c +++ b/keyboards/infinity60/keymaps/jpetermans/keymap.c @@ -1,6 +1,5 @@ #include "infinity60.h" #include "led_controller.h" -#include "keymap_jpetermans.h" //Helpful Defines #define _______ KC_TRNS @@ -12,8 +11,33 @@ #define _MEDIA 3 #define _TILDE 4 +//IS31 chip has 8 available led pages, using 0 for all leds and 7 for single toggles +#define max_pages 6 + +enum ic60_keycodes { + NUMPAD, + FNAV, + MEDIA, + TILDE, + CTLALTDEL, + BACKLIGHT, + BRIGHT, + DIM, + BREATH, + ALL, + GAME, + MODE_SINGLE, + MODE_PAGE, + MODE_FLASH +}; + +uint8_t current_layer_global = 0; +uint8_t led_mode_global = MODE_SINGLE; +uint8_t backlight_status_global = 1; //init on/off state of backlight +uint32_t led_layer_state = 0; + /* ================================== - * KEYMAPS + * KEYMAPS * ==================================*/ const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS] = { @@ -35,19 +59,10 @@ const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS] = { KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS,KC_EQL, KC_BSLS,KC_NO,\ KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC,KC_RBRC,KC_BSPC, \ TT(_FNAV), KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN,KC_QUOT,KC_ENT, \ - F(1), KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM,KC_DOT, KC_SLSH,KC_RSFT,KC_NO, \ + KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM,KC_DOT, KC_SLSH,F(TILDE),KC_NO, \ KC_LCTL, KC_LGUI,KC_LALT, KC_SPC, KC_RALT,TG(_NUMPAD),MO(_MEDIA), KC_RCTL \ ), - /* F-, arrow, and media keys */ - [_FNAV] = KEYMAP( \ - KC_GRV, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, _______,KC_NO,\ - KC_CAPS,_______,_______,_______,_______,_______,_______,KC_PGUP,KC_UP,KC_PGDN,KC_PSCR,_______,_______,KC_DEL, \ - _______,M(0),KC_BTN2,_______,_______,_______,KC_HOME,KC_LEFT,KC_DOWN,KC_RGHT,KC_INS,_______,_______, \ - _______,KC_APP,KC_BTN1,KC_CALC,_______,_______,KC_END,_______,_______,_______,_______,_______,KC_NO, \ - _______,_______,_______, _______, F(0),KC_NLCK,_______,_______ \ - ), - /* numpad */ [_NUMPAD] = KEYMAP( \ _______,_______,_______,_______,_______,_______,_______, KC_P7, KC_P8, KC_P9, KC_PSLS, _______,_______,_______,KC_NO,\ @@ -57,12 +72,21 @@ const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS] = { _______,_______,_______, MO(_BASE), _______,_______,_______,_______ \ ), + /* F-, arrow, and media keys */ + [_FNAV] = KEYMAP( \ + KC_GRV, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, _______,KC_NO,\ + KC_CAPS,_______,_______,_______,_______,_______,_______,KC_PGUP,KC_UP,KC_PGDN,KC_PSCR,_______,_______,KC_DEL, \ + _______,M(0),KC_BTN2,_______,_______,_______,KC_HOME,KC_LEFT,KC_DOWN,KC_RGHT,KC_INS,_______,_______, \ + _______,KC_APP,KC_BTN1,KC_CALC,_______,_______,KC_END,_______,_______,_______,_______,_______,KC_NO, \ + _______,_______,_______, _______, F(CTLALTDEL),KC_NLCK,_______,_______ \ + ), + /* media */ [_MEDIA] = KEYMAP( \ - _______,_______,_______,_______,_______,_______,_______, _______, _______, _______,KC_MUTE, KC_VOLD, KC_VOLU,_______,KC_NO,\ + _______,F(MODE_SINGLE),F(MODE_PAGE),F(MODE_FLASH),_______,_______,_______, _______, _______, _______,KC_MUTE, KC_VOLD, KC_VOLU,_______,KC_NO,\ _______,_______,_______,_______,_______,_______,_______, _______, _______, _______,_______, _______,_______,_______,\ - _______,_______,_______,_______,_______,_______,_______, _______, _______, _______,_______, _______,_______, \ - _______,_______,F(2),F(3),F(4),F(5),F(6),F(7), KC_MPRV, KC_MNXT,KC_MSTP, _______,KC_NO, \ + _______,_______,_______,_______,_______,F(GAME),_______, _______, _______, _______,_______, _______,_______, \ + _______,_______,F(ALL) ,F(BRIGHT),F(DIM),F(BACKLIGHT),_______, _______, KC_MPRV, KC_MNXT,KC_MSTP, _______,KC_NO, \ _______,_______,_______, KC_MPLY, _______,_______, _______,_______ \ ), /* ~ */ @@ -91,21 +115,20 @@ enum function_id { enum macro_id { ACTION_LEDS_ALL, ACTION_LEDS_GAME, - ACTION_LEDS_NAV, - ACTION_LEDS_MEDIA, - ACTION_LEDS_NUMPAD, - ACTION_LEDS_TEST + ACTION_LEDS_BACKLIGHT, + ACTION_LEDS_BRIGHT, + ACTION_LEDS_DIM, + ACTION_LEDS_BREATH, + ACTION_LEDS_SINGLE, + ACTION_LEDS_PAGE, + ACTION_LEDS_FLASH, }; - + /* ================================== - * LED MAPPING + * LED MAPPING * ==================================*/ /* - Configuring led control can be done as - 1. full keyboard at a time - define led array, or - 2. individual led - send specific led address (defined in keymap.h) - Infinity60 LED MAP 11 12 13 14 15 16 17 18 21 22 23 24 25 26 27* 28 31 32 33 34 35 36 37 38 41 42 43 44 45 @@ -113,163 +136,182 @@ enum macro_id { 63 64 65 66 67 68 71 72 73 74 75 76 77* 78 81 82 83 84 85 86 87 *Unused in Alphabet Layout - - The full keyboard arrays map to the mcu's LED pages - (8 available) desribed in led_controller.c - - 0x24 (pcb row 1) is first byte of PWM portion of LED page - 0x34 (pcb row 2) is 17th byte of PWM portion of LED page - array translates to row and column positions */ -//LED Layer indicator (1 per layer 3-7) -const uint8_t led_single_layer[5] = { - 12,13,14,15,16 -}; -//LED Page 1 - All off -//LED Page 2 - All on -//LED Page 3 - _Nav -const uint8_t led_nav[33] = { - 11,12,13,14,15,16,17,18,21,22,23,24,25, - 28, 37,38,41,42,45, - 46,47,48, 54,55,56,57,58, - 64,65,66, 71, - 84,85 -}; -//LED Page 4 - _Numpad -const uint8_t led_numpad[17] = { +//======== full page arrays ========= +//LED Page 1 - _Numpad +//any change in array size needs to be mirrored in matrix_init_user +uint8_t led_numpad[16] = { 18,21,22,23, 37,38,41,42, 55,56,57,58, - 72,73,74,75, - 85 + 72,73,74,75 }; -//LED Page 5 - _Media -const uint8_t led_media[12] = { - 23,24,25, - 38, - 55,56,57, - 73,74,75, - 83, 86 +//LED Page 2 - _Nav +uint8_t led_nav[12] = { + 38, + 47,48, 55,56,57, + 64,65,66 }; -//LED Page 6 - _Game -const uint8_t led_game[5] = { - //row 1 +//LED Page 3 - _Media +uint8_t led_media[15] = { + 12,13,14, 23,24,25, + 65,66,67,68, 73,74,75, + 83, 86 +}; +//LED Page 4 - _Game "WASD" +uint8_t led_game[5] = { 11, - //row 2 - //row 3 - 32, - //row 4 - 47, 48, - //row 5 - 51 - //row 6 - //row 7 - //row 8 + 32, + 47,48,51 }; +//======== qmk functions ========= const uint16_t fn_actions[] = { - [0] = ACTION_KEY(LALT(LCTL(KC_DEL))), - [1] = ACTION_LAYER_MODS(_TILDE, MOD_LSFT), - [2] = ACTION_FUNCTION(ACTION_LEDS_ALL), - [3] = ACTION_FUNCTION(ACTION_LEDS_GAME), - [4] = ACTION_FUNCTION(ACTION_LEDS_MEDIA), - [5] = ACTION_FUNCTION(ACTION_LEDS_NAV), - [6] = ACTION_FUNCTION(ACTION_LEDS_NUMPAD), - [7] = ACTION_FUNCTION(ACTION_LEDS_TEST) - - + [CTLALTDEL] = ACTION_KEY(LALT(LCTL(KC_DEL))), + [TILDE] = ACTION_LAYER_MODS(_TILDE, MOD_LSFT), + [ALL] = ACTION_FUNCTION(ACTION_LEDS_ALL), + [GAME] = ACTION_FUNCTION(ACTION_LEDS_GAME), + [BACKLIGHT] = ACTION_FUNCTION(ACTION_LEDS_BACKLIGHT), + [BRIGHT] = ACTION_FUNCTION(ACTION_LEDS_BRIGHT), + [DIM] = ACTION_FUNCTION(ACTION_LEDS_DIM), + [BREATH] = ACTION_FUNCTION(ACTION_LEDS_BREATH), + [MODE_SINGLE] = ACTION_FUNCTION(ACTION_LEDS_SINGLE), + [MODE_PAGE] = ACTION_FUNCTION(ACTION_LEDS_PAGE), + [MODE_FLASH] = ACTION_FUNCTION(ACTION_LEDS_FLASH), }; /* custom action function */ void action_function(keyrecord_t *record, uint8_t id, uint8_t opt) { - (void)opt; msg_t msg; + switch(id) { case ACTION_LEDS_ALL: if(record->event.pressed) { - // signal the LED controller thread + led_mode_global = led_mode_global == ALL ? MODE_SINGLE : ALL; msg=(TOGGLE_ALL << 8) | 0; chMBPost(&led_mailbox, msg, TIME_IMMEDIATE); } break; + + case ACTION_LEDS_BACKLIGHT: + if(record->event.pressed) { + backlight_status_global ^= 1; + msg=(TOGGLE_BACKLIGHT << 8) | (backlight_status_global); + chMBPost(&led_mailbox, msg, TIME_IMMEDIATE); + } + break; + case ACTION_LEDS_GAME: if(record->event.pressed) { - // signal the LED controller thread - msg=(TOGGLE_LAYER_LEDS << 8) | 6; + led_mode_global = led_mode_global == GAME ? MODE_SINGLE : GAME; + + msg=(DISPLAY_PAGE << 8) | 4; chMBPost(&led_mailbox, msg, TIME_IMMEDIATE); } break; - case ACTION_LEDS_MEDIA: + + case ACTION_LEDS_BRIGHT: if(record->event.pressed) { - // signal the LED controller thread - msg=(TOGGLE_LAYER_LEDS << 8) | 5; + msg=(STEP_BRIGHTNESS << 8) | 1; chMBPost(&led_mailbox, msg, TIME_IMMEDIATE); } break; - case ACTION_LEDS_NAV: + + case ACTION_LEDS_DIM: if(record->event.pressed) { - // signal the LED controller thread - msg=(OFF_LED << 8) | 12; + msg=(STEP_BRIGHTNESS << 8) | 0; chMBPost(&led_mailbox, msg, TIME_IMMEDIATE); } break; - case ACTION_LEDS_NUMPAD: + + case ACTION_LEDS_BREATH: if(record->event.pressed) { - // signal the LED controller thread - msg=(ON_LED << 8) | 12; + msg=(TOGGLE_BREATH << 8) | 0; chMBPost(&led_mailbox, msg, TIME_IMMEDIATE); } break; - case ACTION_LEDS_TEST: - if(record->event.pressed) { - // signal the LED controller thread - msg=(TOGGLE_LED << 8) | 12; - chMBPost(&led_mailbox, msg, TIME_IMMEDIATE); - } + + //set led_mode for matrix_scan to toggle leds + case ACTION_LEDS_SINGLE: + led_mode_global = MODE_SINGLE; break; + case ACTION_LEDS_PAGE: + led_mode_global = MODE_PAGE; + break; + case ACTION_LEDS_FLASH: + led_mode_global = MODE_FLASH; + break; + } } const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { - switch(id) { - case 0: - if (record->event.pressed) { - } - break; - case 1: - if (record->event.pressed) { - } - break; - } return MACRO_NONE; }; +bool process_record_user (uint16_t keycode, keyrecord_t *record) { + return true; +} + // Runs just one time when the keyboard initializes. void matrix_init_user(void) { xprintf("init start"); led_controller_init(); -//TODO: do pages need to be written at init or ok on demand? -/* Write pages */ - write_led_page(3, led_nav, 33); - chThdSleepMilliseconds(5); + // Write predefined led pages. + write_led_page(_NUMPAD, led_numpad, 16); + chThdSleepMilliseconds(10); - write_led_page(4, led_numpad, 17); - chThdSleepMilliseconds(5); + write_led_page(_FNAV, led_nav, 12); + chThdSleepMilliseconds(10); - write_led_page(5, led_media, 12); - chThdSleepMilliseconds(5); + write_led_page(_MEDIA, led_media, 15); + chThdSleepMilliseconds(10); - write_led_page(6, led_game, 5); - chThdSleepMilliseconds(5); + write_led_page(4, led_game, 5); + chThdSleepMilliseconds(1000); }; -// Runs constantly in the background, in a loop. +// Loops constantly in the background. void matrix_scan_user(void) { + uint8_t page; + uint8_t led_pin_byte; + msg_t msg; -}; + if (backlight_status_global == 0) {//backlight is off, skip the rest + return; + } + + if (led_layer_state != layer_state && led_mode_global != GAME && led_mode_global != ALL) { + //check mode + //Turn on layer indicator or page depending on mode + switch(led_mode_global) { + case MODE_FLASH: //flash preset page leds then single indicator + page = biton32(layer_state) > max_pages ? 7 : biton32(layer_state); + msg=(DISPLAY_PAGE << 8) | (page); + chMBPost(&led_mailbox, msg, TIME_IMMEDIATE); + chThdSleepMilliseconds(500); + //flow to display single layer leds + + case MODE_SINGLE: //light layer indicators for all active layers + led_pin_byte = layer_state & 0xFF; + msg=(DISPLAY_PAGE << 8) | 7; + chMBPost(&led_mailbox, msg, TIME_IMMEDIATE); + msg=(1<<16) | (SET_FULL_ROW << 8) | (led_pin_byte); + chMBPost(&led_mailbox, msg, TIME_IMMEDIATE); + break; + + case MODE_PAGE: //display pre-defined led page + page = biton32(layer_state) > max_pages ? 7 : biton32(layer_state); + msg=(DISPLAY_PAGE << 8) | (page); + chMBPost(&led_mailbox, msg, TIME_IMMEDIATE); + break; + } + led_layer_state = layer_state; + } +} diff --git a/keyboards/infinity60/keymaps/jpetermans/keymap_jpetermans.h b/keyboards/infinity60/keymaps/jpetermans/keymap_jpetermans.h deleted file mode 100644 index 240374423..000000000 --- a/keyboards/infinity60/keymaps/jpetermans/keymap_jpetermans.h +++ /dev/null @@ -1,78 +0,0 @@ -/* LED layout mainly based on default Standard configuration - * ,-----------------------------------------------------------. - * |Esc| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =| \ | ` | - * |-----------------------------------------------------------| - * |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| Bksp| - * |-----------------------------------------------------------| - * |Caps | A| S| D| F| G| H| J| K| L| ;| '|Enter | - * |-----------------------------------------------------------| - * |Shift | Z| X| C| V| B| N| M| ,| .| /|Shift |Fn0| - * |-----------------------------------------------------------' - * | LCtl|LGui|LAlt | Space | RAlt|RGui|RMenu|RCtl| - * `-----------------------------------------------------------' -*/ - - -#define ADDR_LED_ESC 0x24 -#define ADDR_LED_1 0x25 -#define ADDR_LED_2 0x26 -#define ADDR_LED_3 0x27 -#define ADDR_LED_4 0x28 -#define ADDR_LED_5 0x29 -#define ADDR_LED_6 0x2A -#define ADDR_LED_7 0x2B -#define ADDR_LED_8 0x34 -#define ADDR_LED_9 0x35 -#define ADDR_LED_0 0x36 -#define ADDR_LED_MINS 0x37 -#define ADDR_LED_EQL 0x38 -#define ADDR_LED_BSLS 0x39 -//#define ADDR_LED_GRV 0x3A //not used by Alphabet layout -#define ADDR_LED_TAB 0x3B -#define ADDR_LED_Q 0x44 -#define ADDR_LED_W 0x45 -#define ADDR_LED_E 0x46 -#define ADDR_LED_R 0x47 -#define ADDR_LED_T 0x48 -#define ADDR_LED_Y 0x49 -#define ADDR_LED_U 0x4A -#define ADDR_LED_I 0x4B -#define ADDR_LED_O 0x54 -#define ADDR_LED_P 0x55 -#define ADDR_LED_LBRC 0x56 -#define ADDR_LED_RBRC 0x57 -#define ADDR_LED_BSPC 0x58 -#define ADDR_LED_CAPS 0x59 -#define ADDR_LED_A 0x5A -#define ADDR_LED_S 0x5B -#define ADDR_LED_D 0x64 -#define ADDR_LED_F 0x65 -#define ADDR_LED_G 0x66 -#define ADDR_LED_H 0x67 -#define ADDR_LED_J 0x68 -#define ADDR_LED_K 0x69 -#define ADDR_LED_L 0x6A -#define ADDR_LED_SCLN 0x6B -#define ADDR_LED_QUOT 0x74 -#define ADDR_LED_ENT 0x75 -#define ADDR_LED_LSFT 0x76 -#define ADDR_LED_Z 0x77 -#define ADDR_LED_X 0x78 -#define ADDR_LED_C 0x79 -#define ADDR_LED_V 0x7A -#define ADDR_LED_B 0x7B -#define ADDR_LED_N 0x84 -#define ADDR_LED_M 0x85 -#define ADDR_LED_COMM 0x86 -#define ADDR_LED_DOT 0x87 -#define ADDR_LED_SLSH 0x88 -#define ADDR_LED_RSFT 0x89 -//#define ADDR_LED_FN0 0x8A //not used by Alphabet layout -#define ADDR_LED_LCTL 0x8B -#define ADDR_LED_LGUI 0x94 -#define ADDR_LED_LALT 0x95 -#define ADDR_LED_SPC 0x96 -#define ADDR_LED_RALT 0x97 -#define ADDR_LED_RGUI 0x98 -#define ADDR_LED_MENU 0x99 -#define ADDR_LED_RCTL 0x9A diff --git a/keyboards/infinity60/keymaps/jpetermans/readme.md b/keyboards/infinity60/keymaps/jpetermans/readme.md new file mode 100644 index 000000000..9c5b89173 --- /dev/null +++ b/keyboards/infinity60/keymaps/jpetermans/readme.md @@ -0,0 +1,79 @@ +Backlight for Infinity60 +======================== + +## Led Controller Specs + +The Infinity60 pcb uses the IS31FL3731C matrix LED driver from ISSI [datasheet](http://www.issi.com/WW/pdf/31FL3731C.pdf). The IS31 has the ability to control two led matrices (A & B), each matrix controlling 9 pins, each pin controlling 8 leds. The Infinity only utilizes matrix A. + +Infinity60 LED MAP: +digits mean "row" and "col", i.e. 45 means C4-5 in the IS31 datasheet, matrix A +```c + 11 12 13 14 15 16 17 18 21 22 23 24 25 26 27* + 28 31 32 33 34 35 36 37 38 41 42 43 44 45 + 46 47 48 51 52 53 54 55 56 57 58 61 62 + 63 64 65 66 67 68 71 72 73 74 75 76 77* + 78 81 82 83 84 85 86 87 +``` +*Unused in Alphabet Layout + +The IS31 includes 8 pages (or frames) 0-7 and each page consists of 0xB4 (144) bytes +- **0 - 17** LED control (on/off). 18 pins which alternate between A and B matrices (CA1, CB1, CA2, CB2, ..). Each byte controls the 8 leds on that pin with bits (8 to 1). +- **18 - 35** Blink control. Same as LED control above, but sets blink on/off. +- **36 - 143** PWM control. One byte per LED, sets PWM from 0 to 255. Same as above, the register alternates bytes between the A & B matrices. + +## Led Controller Code +led_controller.c sets up ability to write led layers at startup or control leds on demand as part of fn_actions. By default led_controller.c assumes page 0 will be used for full on/off and page 7 for controlling individual leds. The remaining 6 pages (1-6) are free to preset led maps at init or on demand. Communication with the IS31 is primarily done through the led_mailbox using chMBPost described further below under "Sending messages in Keymap.c" + +One function is available to directly control leds: +``` +write_led_page(page#, array of leds by address, # of leds in array) +``` +This function saves a full page using a supplied array of led locations such as: +``` +uint8_t led_numpad[16] = { + 18,21,22,23, + 37,38,41,42, + 55,56,57,58, + 72,73,74,75 +} +write_led_page(5, led_numpad, 16); +``` + +Remaining led control is done through the led mailbox using these message types. +- **SET_FULL_ROW** - 3 bytes: row#, message type, 8-bit mask. Sets all leds on one pin per the bit mask. +- **OFF_LED** - 2 bytes: message type, led address. Turn off specific led. +- **ON_LED** - 2 bytes: message type, led address. Turn on specific led. +- **TOGGLE_LED** - 2 bytes: message type, led address. Toggle specific led on/off. +- **BLINK_OFF_LED** - 2 bytes: message type, led address. Set blink off for specific led. +- **BLINK_ON_LED** - 2 bytes: message type, led address. Set blink on for specific led. +- **BLINK_TOGGLE_LED** - 2 bytes: message type, led address. Toggle blink for specific led. +- **TOGGLE_ALL** - 2 bytes: message type, not used. Turn on/off full backlight. +- **TOGGLE_BACKLIGHT** - 2 bytes: message type, on/off. Sets backlight completely off, no leds will display. +- **DISPLAY_PAGE** - 2 bytes: message type, page to display. Switch to specific pre-set page. +- **RESET_PAGE** - 2 bytes: message type, page to reset. Reset/erase specific page. +- **TOGGLE_NUM_LOCK** - 2 bytes: message type, on/off (NUM_LOCK_LED_ADDRESS). Toggle numlock on/off. Usually run with the `set_leds` function to check state of numlock or capslock. If all leds are on (e.i. TOGGLE_ALL) then this sets numlock to blink instead (this is still a little buggy if toggling on/off quickly). +- **TOGGLE_CAPS_LOCK** - 2 bytes: message type, on/off (CAPS_LOCK_LED_ADDRESS). Same as numlock. +- **STEP_BRIGHTNESS** - 2 bytes: message type, and step up (1) or step down (0). Increase or decrease led brightness. + +## Sending messages in Keymap.c +Sending an action to the led mailbox is done using chMBPost with the following form. +``` +chMBPost(&led_mailbox, message, timeout); +``` +- &led_mailbox - pointer to led mailbox +- message - up to 4 bytes but most messages use only 2. First byte (LSB) is the message to process, the second byte is type. The third is only used to pass row information in SET_FULL_ROW. The fourth byte is currently unused. +-timeout is usually TIME_IMMEDIATE + +An example: +1. set the message to be sent. First byte (LSB) is the led address, and second is the message type +`msg=(ON_LED << 8) | 42;` +2. send msg to the led mailbox +`chMBPost(&led_mailbox, msg, TIME_IMMEDIATE);` + +Another: +`msg=(BLINK_TOGGLE_LED << 8) | 46;` +`chMBPost(&led_mailbox, msg, TIME_IMMEDIATE);` + +Finally, SET_FULL_ROW requires an extra byte with row information in the message so sending this message looks like: +`msg=(row<<16) | (SET_FULL_ROW << 8) | (led_pin_byte);` +`chMBPost(&led_mailbox, msg, TIME_IMMEDIATE);` From 821f72eae94ce4f1b93bab1376b2187698206b65 Mon Sep 17 00:00:00 2001 From: jpetermans Date: Mon, 8 May 2017 16:15:20 -0700 Subject: [PATCH 027/238] documentation cleanup --- .../infinity60/keymaps/jpetermans/readme.md | 69 ++++++++++--------- keyboards/infinity60/led_controller.c | 6 +- 2 files changed, 41 insertions(+), 34 deletions(-) diff --git a/keyboards/infinity60/keymaps/jpetermans/readme.md b/keyboards/infinity60/keymaps/jpetermans/readme.md index 9c5b89173..fcad4b140 100644 --- a/keyboards/infinity60/keymaps/jpetermans/readme.md +++ b/keyboards/infinity60/keymaps/jpetermans/readme.md @@ -3,10 +3,10 @@ Backlight for Infinity60 ## Led Controller Specs -The Infinity60 pcb uses the IS31FL3731C matrix LED driver from ISSI [datasheet](http://www.issi.com/WW/pdf/31FL3731C.pdf). The IS31 has the ability to control two led matrices (A & B), each matrix controlling 9 pins, each pin controlling 8 leds. The Infinity only utilizes matrix A. +The Infinity60 (revision 1.1a) pcb uses the IS31FL3731C matrix LED driver from ISSI [(datasheet)](http://www.issi.com/WW/pdf/31FL3731C.pdf). The IS31 has the ability to control two led matrices (A & B), each matrix controlling 9 pins, each pin controlling 8 leds. The Infinity only utilizes matrix A. -Infinity60 LED MAP: -digits mean "row" and "col", i.e. 45 means C4-5 in the IS31 datasheet, matrix A +Infinity60 LED Map: +digits mean "row" and "col", i.e. 45 means pin 4, column 5 in the IS31 datasheet ```c 11 12 13 14 15 16 17 18 21 22 23 24 25 26 27* 28 31 32 33 34 35 36 37 38 41 42 43 44 45 @@ -17,19 +17,26 @@ digits mean "row" and "col", i.e. 45 means C4-5 in the IS31 datasheet, matrix A *Unused in Alphabet Layout The IS31 includes 8 pages (or frames) 0-7 and each page consists of 0xB4 (144) bytes -- **0 - 17** LED control (on/off). 18 pins which alternate between A and B matrices (CA1, CB1, CA2, CB2, ..). Each byte controls the 8 leds on that pin with bits (8 to 1). -- **18 - 35** Blink control. Same as LED control above, but sets blink on/off. -- **36 - 143** PWM control. One byte per LED, sets PWM from 0 to 255. Same as above, the register alternates bytes between the A & B matrices. +- **0 - 17** + * LED control (on/off). + * 18 pins which alternate between A and B matrices (CA1, CB1, CA2, CB2, ..). + * Each byte controls the 8 leds on that pin with bits (8 to 1). +- **18 - 35** + * Blink control. + * Same as LED control above, but sets blink on/off. +- **36 - 143** + * PWM control. One byte per LED, sets PWM from 0 to 255. + * Same as above, the register alternates, every 8 *bytes* (not bits) between the A & B matrices. ## Led Controller Code -led_controller.c sets up ability to write led layers at startup or control leds on demand as part of fn_actions. By default led_controller.c assumes page 0 will be used for full on/off and page 7 for controlling individual leds. The remaining 6 pages (1-6) are free to preset led maps at init or on demand. Communication with the IS31 is primarily done through the led_mailbox using chMBPost described further below under "Sending messages in Keymap.c" +In the Infinity60 project folder, led_controller.c sets up ability to write led layers at startup or control leds on demand as part of fn_actions. By default led_controller.c assumes page 0 will be used for full on/off and page 7 for controlling individual leds. The remaining 6 pages (1-6) are free to preset led maps at init or on demand. Communication with the IS31 is primarily done through the led_mailbox using chMBPost described further below under "Sending messages in Keymap.c" -One function is available to directly control leds: +One function is available to directly set leds without the mailbox: ``` write_led_page(page#, array of leds by address, # of leds in array) ``` This function saves a full page using a supplied array of led locations such as: -``` +```c uint8_t led_numpad[16] = { 18,21,22,23, 37,38,41,42, @@ -39,24 +46,24 @@ uint8_t led_numpad[16] = { write_led_page(5, led_numpad, 16); ``` -Remaining led control is done through the led mailbox using these message types. -- **SET_FULL_ROW** - 3 bytes: row#, message type, 8-bit mask. Sets all leds on one pin per the bit mask. -- **OFF_LED** - 2 bytes: message type, led address. Turn off specific led. -- **ON_LED** - 2 bytes: message type, led address. Turn on specific led. -- **TOGGLE_LED** - 2 bytes: message type, led address. Toggle specific led on/off. -- **BLINK_OFF_LED** - 2 bytes: message type, led address. Set blink off for specific led. -- **BLINK_ON_LED** - 2 bytes: message type, led address. Set blink on for specific led. -- **BLINK_TOGGLE_LED** - 2 bytes: message type, led address. Toggle blink for specific led. -- **TOGGLE_ALL** - 2 bytes: message type, not used. Turn on/off full backlight. -- **TOGGLE_BACKLIGHT** - 2 bytes: message type, on/off. Sets backlight completely off, no leds will display. -- **DISPLAY_PAGE** - 2 bytes: message type, page to display. Switch to specific pre-set page. -- **RESET_PAGE** - 2 bytes: message type, page to reset. Reset/erase specific page. -- **TOGGLE_NUM_LOCK** - 2 bytes: message type, on/off (NUM_LOCK_LED_ADDRESS). Toggle numlock on/off. Usually run with the `set_leds` function to check state of numlock or capslock. If all leds are on (e.i. TOGGLE_ALL) then this sets numlock to blink instead (this is still a little buggy if toggling on/off quickly). -- **TOGGLE_CAPS_LOCK** - 2 bytes: message type, on/off (CAPS_LOCK_LED_ADDRESS). Same as numlock. -- **STEP_BRIGHTNESS** - 2 bytes: message type, and step up (1) or step down (0). Increase or decrease led brightness. +Remaining led control is done through the led mailbox using these message types: +- **SET_FULL_ROW** (3 bytes) - row#, message type, 8-bit mask. Sets all leds on one pin per the bit mask. +- **OFF_LED** (2 bytes) - message type, led address. Turn off specific led. +- **ON_LED** (2 bytes) - message type, led address. Turn on specific led. +- **TOGGLE_LED** (2 bytes) - message type, led address. Toggle specific led on/off. +- **BLINK_OFF_LED** (2 bytes) - message type, led address. Set blink off for specific led. +- **BLINK_ON_LED** (2 bytes) - message type, led address. Set blink on for specific led. +- **BLINK_TOGGLE_LED** (2 bytes) - message type, led address. Toggle blink for specific led. +- **TOGGLE_ALL** (2 bytes) - message type, not used. Turn on/off full backlight. +- **TOGGLE_BACKLIGHT** (2 bytes) - message type, on/off. Sets backlight completely off, no leds will display. +- **DISPLAY_PAGE** (2 bytes) - message type, page to display. Switch to specific pre-set page. +- **RESET_PAGE** (2 bytes) - message type, page to reset. Reset/erase specific page. +- **TOGGLE_NUM_LOCK** (2 bytes) - message type, on/off (NUM_LOCK_LED_ADDRESS). Toggle numlock on/off. Usually run with the `set_leds` function to check state of numlock or capslock. If all leds are on (e.i. TOGGLE_ALL) then this sets numlock to blink instead (this is still a little buggy if toggling on/off quickly). +- **TOGGLE_CAPS_LOCK** (2 bytes) - message type, on/off (CAPS_LOCK_LED_ADDRESS). Same as numlock. +- **STEP_BRIGHTNESS** (2 bytes) - message type, and step up (1) or step down (0). Increase or decrease led brightness. ## Sending messages in Keymap.c -Sending an action to the led mailbox is done using chMBPost with the following form. +Sending an action to the led mailbox is done using chMBPost: ``` chMBPost(&led_mailbox, message, timeout); ``` @@ -66,14 +73,14 @@ chMBPost(&led_mailbox, message, timeout); An example: 1. set the message to be sent. First byte (LSB) is the led address, and second is the message type -`msg=(ON_LED << 8) | 42;` + *`msg=(ON_LED << 8) | 42;` 2. send msg to the led mailbox -`chMBPost(&led_mailbox, msg, TIME_IMMEDIATE);` + *`chMBPost(&led_mailbox, msg, TIME_IMMEDIATE);` Another: -`msg=(BLINK_TOGGLE_LED << 8) | 46;` -`chMBPost(&led_mailbox, msg, TIME_IMMEDIATE);` + *`msg=(BLINK_TOGGLE_LED << 8) | 46;` + *`chMBPost(&led_mailbox, msg, TIME_IMMEDIATE);` Finally, SET_FULL_ROW requires an extra byte with row information in the message so sending this message looks like: -`msg=(row<<16) | (SET_FULL_ROW << 8) | (led_pin_byte);` -`chMBPost(&led_mailbox, msg, TIME_IMMEDIATE);` + *`msg=(row<<16) | (SET_FULL_ROW << 8) | (led_pin_byte);` + *`chMBPost(&led_mailbox, msg, TIME_IMMEDIATE);` diff --git a/keyboards/infinity60/led_controller.c b/keyboards/infinity60/led_controller.c index d4ad0559b..d776b4fcf 100644 --- a/keyboards/infinity60/led_controller.c +++ b/keyboards/infinity60/led_controller.c @@ -186,7 +186,7 @@ page_status = 0; //start frame 0 (all off/on) while(true) { // wait for a message (asynchronous) // (messages are queued (up to LED_MAILBOX_NUM_MSGS) if they can't - // be processed right away) + // be processed right away chMBFetch(&led_mailbox, &msg, TIME_INFINITE); msg_col = (msg >> 24) & 0xFF;//if needed msg_pin = (msg >> 16) & 0XFF;//if needed (e.g. SET_FULL_ROW) @@ -229,7 +229,7 @@ page_status = 0; //start frame 0 (all off/on) break; case TOGGLE_ALL: - //msg_led = unused + //msg_led = unused is31_read_register(0, 0x00, &temp); led_control_reg[0] = 0; @@ -315,7 +315,7 @@ page_status = 0; //start frame 0 (all off/on) break; } - //populate 8 byte rows to write on each pin + //populate 8 byte arrays to write on each pin //first byte is register address, every 0x10 9 bytes are A-register pwm pins __builtin_memset(pwm_register_array+1, pwm_levels[pwm_step_status], 8); From d1ff2bb9db68b899dbd02d1cdf036551b38dccdc Mon Sep 17 00:00:00 2001 From: jpetermans Date: Mon, 8 May 2017 16:17:40 -0700 Subject: [PATCH 028/238] readme fix --- keyboards/infinity60/keymaps/jpetermans/readme.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/keyboards/infinity60/keymaps/jpetermans/readme.md b/keyboards/infinity60/keymaps/jpetermans/readme.md index fcad4b140..4657a84c0 100644 --- a/keyboards/infinity60/keymaps/jpetermans/readme.md +++ b/keyboards/infinity60/keymaps/jpetermans/readme.md @@ -73,14 +73,14 @@ chMBPost(&led_mailbox, message, timeout); An example: 1. set the message to be sent. First byte (LSB) is the led address, and second is the message type - *`msg=(ON_LED << 8) | 42;` + * `msg=(ON_LED << 8) | 42;` 2. send msg to the led mailbox - *`chMBPost(&led_mailbox, msg, TIME_IMMEDIATE);` + * `chMBPost(&led_mailbox, msg, TIME_IMMEDIATE);` Another: - *`msg=(BLINK_TOGGLE_LED << 8) | 46;` - *`chMBPost(&led_mailbox, msg, TIME_IMMEDIATE);` + * `msg=(BLINK_TOGGLE_LED << 8) | 46;` + * `chMBPost(&led_mailbox, msg, TIME_IMMEDIATE);` Finally, SET_FULL_ROW requires an extra byte with row information in the message so sending this message looks like: - *`msg=(row<<16) | (SET_FULL_ROW << 8) | (led_pin_byte);` - *`chMBPost(&led_mailbox, msg, TIME_IMMEDIATE);` + * `msg=(row<<16) | (SET_FULL_ROW << 8) | (led_pin_byte);` + * `chMBPost(&led_mailbox, msg, TIME_IMMEDIATE);` From 5fc5661147e4e8bec8a52a8691ac1df2fedd3558 Mon Sep 17 00:00:00 2001 From: jpetermans Date: Mon, 8 May 2017 16:19:11 -0700 Subject: [PATCH 029/238] third readme fix attempt --- keyboards/infinity60/keymaps/jpetermans/readme.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/keyboards/infinity60/keymaps/jpetermans/readme.md b/keyboards/infinity60/keymaps/jpetermans/readme.md index 4657a84c0..2e0edeacd 100644 --- a/keyboards/infinity60/keymaps/jpetermans/readme.md +++ b/keyboards/infinity60/keymaps/jpetermans/readme.md @@ -78,9 +78,9 @@ An example: * `chMBPost(&led_mailbox, msg, TIME_IMMEDIATE);` Another: - * `msg=(BLINK_TOGGLE_LED << 8) | 46;` - * `chMBPost(&led_mailbox, msg, TIME_IMMEDIATE);` +- `msg=(BLINK_TOGGLE_LED << 8) | 46;` +- `chMBPost(&led_mailbox, msg, TIME_IMMEDIATE);` Finally, SET_FULL_ROW requires an extra byte with row information in the message so sending this message looks like: - * `msg=(row<<16) | (SET_FULL_ROW << 8) | (led_pin_byte);` - * `chMBPost(&led_mailbox, msg, TIME_IMMEDIATE);` +- `msg=(row<<16) | (SET_FULL_ROW << 8) | (led_pin_byte);` +- `chMBPost(&led_mailbox, msg, TIME_IMMEDIATE);` From 16774333ad47ada2367b5ca283d0af5060ff8415 Mon Sep 17 00:00:00 2001 From: jpetermans Date: Mon, 8 May 2017 16:28:04 -0700 Subject: [PATCH 030/238] last readme fix --- keyboards/infinity60/keymaps/jpetermans/readme.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/keyboards/infinity60/keymaps/jpetermans/readme.md b/keyboards/infinity60/keymaps/jpetermans/readme.md index 2e0edeacd..7e60a7f0d 100644 --- a/keyboards/infinity60/keymaps/jpetermans/readme.md +++ b/keyboards/infinity60/keymaps/jpetermans/readme.md @@ -78,9 +78,13 @@ An example: * `chMBPost(&led_mailbox, msg, TIME_IMMEDIATE);` Another: -- `msg=(BLINK_TOGGLE_LED << 8) | 46;` -- `chMBPost(&led_mailbox, msg, TIME_IMMEDIATE);` +```c +msg=(BLINK_TOGGLE_LED << 8) | 46; +chMBPost(&led_mailbox, msg, TIME_IMMEDIATE); +``` Finally, SET_FULL_ROW requires an extra byte with row information in the message so sending this message looks like: -- `msg=(row<<16) | (SET_FULL_ROW << 8) | (led_pin_byte);` -- `chMBPost(&led_mailbox, msg, TIME_IMMEDIATE);` +```c +msg=(row<<16) | (SET_FULL_ROW << 8) | (led_pin_byte); +chMBPost(&led_mailbox, msg, TIME_IMMEDIATE); +``` From a144968807f5bf98b2c41cfe153f3df780ed4eaa Mon Sep 17 00:00:00 2001 From: jpetermans Date: Mon, 8 May 2017 16:38:44 -0700 Subject: [PATCH 031/238] remove breath functions from keymap --- keyboards/infinity60/keymaps/jpetermans/keymap.c | 10 ---------- keyboards/infinity60/keymaps/jpetermans/readme.md | 11 +++++++---- 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/keyboards/infinity60/keymaps/jpetermans/keymap.c b/keyboards/infinity60/keymaps/jpetermans/keymap.c index 1afb7c067..630105017 100644 --- a/keyboards/infinity60/keymaps/jpetermans/keymap.c +++ b/keyboards/infinity60/keymaps/jpetermans/keymap.c @@ -23,7 +23,6 @@ enum ic60_keycodes { BACKLIGHT, BRIGHT, DIM, - BREATH, ALL, GAME, MODE_SINGLE, @@ -118,7 +117,6 @@ enum macro_id { ACTION_LEDS_BACKLIGHT, ACTION_LEDS_BRIGHT, ACTION_LEDS_DIM, - ACTION_LEDS_BREATH, ACTION_LEDS_SINGLE, ACTION_LEDS_PAGE, ACTION_LEDS_FLASH, @@ -175,7 +173,6 @@ const uint16_t fn_actions[] = { [BACKLIGHT] = ACTION_FUNCTION(ACTION_LEDS_BACKLIGHT), [BRIGHT] = ACTION_FUNCTION(ACTION_LEDS_BRIGHT), [DIM] = ACTION_FUNCTION(ACTION_LEDS_DIM), - [BREATH] = ACTION_FUNCTION(ACTION_LEDS_BREATH), [MODE_SINGLE] = ACTION_FUNCTION(ACTION_LEDS_SINGLE), [MODE_PAGE] = ACTION_FUNCTION(ACTION_LEDS_PAGE), [MODE_FLASH] = ACTION_FUNCTION(ACTION_LEDS_FLASH), @@ -225,13 +222,6 @@ void action_function(keyrecord_t *record, uint8_t id, uint8_t opt) { } break; - case ACTION_LEDS_BREATH: - if(record->event.pressed) { - msg=(TOGGLE_BREATH << 8) | 0; - chMBPost(&led_mailbox, msg, TIME_IMMEDIATE); - } - break; - //set led_mode for matrix_scan to toggle leds case ACTION_LEDS_SINGLE: led_mode_global = MODE_SINGLE; diff --git a/keyboards/infinity60/keymaps/jpetermans/readme.md b/keyboards/infinity60/keymaps/jpetermans/readme.md index 7e60a7f0d..f50bee617 100644 --- a/keyboards/infinity60/keymaps/jpetermans/readme.md +++ b/keyboards/infinity60/keymaps/jpetermans/readme.md @@ -72,10 +72,13 @@ chMBPost(&led_mailbox, message, timeout); -timeout is usually TIME_IMMEDIATE An example: -1. set the message to be sent. First byte (LSB) is the led address, and second is the message type - * `msg=(ON_LED << 8) | 42;` -2. send msg to the led mailbox - * `chMBPost(&led_mailbox, msg, TIME_IMMEDIATE);` +```c +//set the message to be sent. First byte (LSB) is the led address, and second is the message type +msg=(ON_LED << 8) | 42; + +//send msg to the led mailbox +chMBPost(&led_mailbox, msg, TIME_IMMEDIATE); +``` Another: ```c From 164a6c994b797b66634f7a1c12fcaffd0ffd7506 Mon Sep 17 00:00:00 2001 From: jpetermans Date: Wed, 10 May 2017 15:53:59 -0700 Subject: [PATCH 032/238] reorder mailbox msg data; formatting --- .../infinity60/keymaps/jpetermans/keymap.c | 28 ++-- .../infinity60/keymaps/jpetermans/readme.md | 38 ++--- keyboards/infinity60/led.c | 8 +- keyboards/infinity60/led_controller.c | 144 +++++++++--------- 4 files changed, 104 insertions(+), 114 deletions(-) diff --git a/keyboards/infinity60/keymaps/jpetermans/keymap.c b/keyboards/infinity60/keymaps/jpetermans/keymap.c index 630105017..8d19834b2 100644 --- a/keyboards/infinity60/keymaps/jpetermans/keymap.c +++ b/keyboards/infinity60/keymaps/jpetermans/keymap.c @@ -12,7 +12,7 @@ #define _TILDE 4 //IS31 chip has 8 available led pages, using 0 for all leds and 7 for single toggles -#define max_pages 6 +#define max_pages 6 enum ic60_keycodes { NUMPAD, @@ -75,7 +75,7 @@ const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS] = { [_FNAV] = KEYMAP( \ KC_GRV, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, _______,KC_NO,\ KC_CAPS,_______,_______,_______,_______,_______,_______,KC_PGUP,KC_UP,KC_PGDN,KC_PSCR,_______,_______,KC_DEL, \ - _______,M(0),KC_BTN2,_______,_______,_______,KC_HOME,KC_LEFT,KC_DOWN,KC_RGHT,KC_INS,_______,_______, \ + _______,_______,KC_BTN2,_______,_______,_______,KC_HOME,KC_LEFT,KC_DOWN,KC_RGHT,KC_INS,_______,_______, \ _______,KC_APP,KC_BTN1,KC_CALC,_______,_______,KC_END,_______,_______,_______,_______,_______,KC_NO, \ _______,_______,_______, _______, F(CTLALTDEL),KC_NLCK,_______,_______ \ ), @@ -119,7 +119,7 @@ enum macro_id { ACTION_LEDS_DIM, ACTION_LEDS_SINGLE, ACTION_LEDS_PAGE, - ACTION_LEDS_FLASH, + ACTION_LEDS_FLASH }; /* ================================== @@ -137,9 +137,8 @@ enum macro_id { */ //======== full page arrays ========= -//LED Page 1 - _Numpad //any change in array size needs to be mirrored in matrix_init_user -uint8_t led_numpad[16] = { +uint8_t led_numpad[16] = { 18,21,22,23, 37,38,41,42, 55,56,57,58, @@ -186,7 +185,7 @@ void action_function(keyrecord_t *record, uint8_t id, uint8_t opt) { case ACTION_LEDS_ALL: if(record->event.pressed) { led_mode_global = led_mode_global == ALL ? MODE_SINGLE : ALL; - msg=(TOGGLE_ALL << 8) | 0; + msg=TOGGLE_ALL; chMBPost(&led_mailbox, msg, TIME_IMMEDIATE); } break; @@ -194,7 +193,7 @@ void action_function(keyrecord_t *record, uint8_t id, uint8_t opt) { case ACTION_LEDS_BACKLIGHT: if(record->event.pressed) { backlight_status_global ^= 1; - msg=(TOGGLE_BACKLIGHT << 8) | (backlight_status_global); + msg=(backlight_status_global << 8) | TOGGLE_BACKLIGHT; chMBPost(&led_mailbox, msg, TIME_IMMEDIATE); } break; @@ -203,21 +202,21 @@ void action_function(keyrecord_t *record, uint8_t id, uint8_t opt) { if(record->event.pressed) { led_mode_global = led_mode_global == GAME ? MODE_SINGLE : GAME; - msg=(DISPLAY_PAGE << 8) | 4; + msg=(4 << 8) | DISPLAY_PAGE; chMBPost(&led_mailbox, msg, TIME_IMMEDIATE); } break; case ACTION_LEDS_BRIGHT: if(record->event.pressed) { - msg=(STEP_BRIGHTNESS << 8) | 1; + msg=(1 << 8) | STEP_BRIGHTNESS; chMBPost(&led_mailbox, msg, TIME_IMMEDIATE); } break; case ACTION_LEDS_DIM: if(record->event.pressed) { - msg=(STEP_BRIGHTNESS << 8) | 0; + msg=(0 << 8) | STEP_BRIGHTNESS; chMBPost(&led_mailbox, msg, TIME_IMMEDIATE); } break; @@ -282,26 +281,25 @@ void matrix_scan_user(void) { switch(led_mode_global) { case MODE_FLASH: //flash preset page leds then single indicator page = biton32(layer_state) > max_pages ? 7 : biton32(layer_state); - msg=(DISPLAY_PAGE << 8) | (page); + msg=(page << 8) | DISPLAY_PAGE; chMBPost(&led_mailbox, msg, TIME_IMMEDIATE); chThdSleepMilliseconds(500); //flow to display single layer leds case MODE_SINGLE: //light layer indicators for all active layers led_pin_byte = layer_state & 0xFF; - msg=(DISPLAY_PAGE << 8) | 7; + msg=(7 << 8) | DISPLAY_PAGE; chMBPost(&led_mailbox, msg, TIME_IMMEDIATE); - msg=(1<<16) | (SET_FULL_ROW << 8) | (led_pin_byte); + msg=(1<<16) | (led_pin_byte << 8) | SET_FULL_ROW; chMBPost(&led_mailbox, msg, TIME_IMMEDIATE); break; case MODE_PAGE: //display pre-defined led page page = biton32(layer_state) > max_pages ? 7 : biton32(layer_state); - msg=(DISPLAY_PAGE << 8) | (page); + msg=(page << 8) | DISPLAY_PAGE; chMBPost(&led_mailbox, msg, TIME_IMMEDIATE); break; } led_layer_state = layer_state; } } - diff --git a/keyboards/infinity60/keymaps/jpetermans/readme.md b/keyboards/infinity60/keymaps/jpetermans/readme.md index f50bee617..63fd88ec2 100644 --- a/keyboards/infinity60/keymaps/jpetermans/readme.md +++ b/keyboards/infinity60/keymaps/jpetermans/readme.md @@ -16,26 +16,24 @@ digits mean "row" and "col", i.e. 45 means pin 4, column 5 in the IS31 datasheet ``` *Unused in Alphabet Layout -The IS31 includes 8 pages (or frames) 0-7 and each page consists of 0xB4 (144) bytes -- **0 - 17** - * LED control (on/off). - * 18 pins which alternate between A and B matrices (CA1, CB1, CA2, CB2, ..). +The IS31 includes 8 pages (or frames) 0-7 and each page consists of 144 bytes +- **bytes 0 - 17** - LED control (on/off). + * 18 pins which alternate between A and B matrices (CA1, CB1, CA2, CB2, ..). * Each byte controls the 8 leds on that pin with bits (8 to 1). -- **18 - 35** - * Blink control. +- **bytes 8 - 35** - Blink control. * Same as LED control above, but sets blink on/off. -- **36 - 143** - * PWM control. One byte per LED, sets PWM from 0 to 255. +- **bytes 36 - 143** - PWM control. + * One byte per LED, sets PWM from 0 to 255. * Same as above, the register alternates, every 8 *bytes* (not bits) between the A & B matrices. ## Led Controller Code -In the Infinity60 project folder, led_controller.c sets up ability to write led layers at startup or control leds on demand as part of fn_actions. By default led_controller.c assumes page 0 will be used for full on/off and page 7 for controlling individual leds. The remaining 6 pages (1-6) are free to preset led maps at init or on demand. Communication with the IS31 is primarily done through the led_mailbox using chMBPost described further below under "Sending messages in Keymap.c" +In the Infinity60 project folder, led_controller.c sets up ability to write led layers at startup or control leds on demand as part of fn_actions. By default led_controller.c assumes page 0 will be used for full on/off. The remaining 7 pages (1-7) are free for preset led maps or single led actions at init or on demand. Communication with the IS31 is primarily done through the led_mailbox using chMBPost described further below under "Sending messages in Keymap.c". This code is based on work matt3o and flabbergast did for tmk firmware on the [whitefox](https://github.com/tmk/whitefox). One function is available to directly set leds without the mailbox: ``` write_led_page(page#, array of leds by address, # of leds in array) ``` -This function saves a full page using a supplied array of led locations such as: +This function saves a full page to the controller using a supplied array of led locations such as: ```c uint8_t led_numpad[16] = { 18,21,22,23, @@ -48,13 +46,9 @@ write_led_page(5, led_numpad, 16); Remaining led control is done through the led mailbox using these message types: - **SET_FULL_ROW** (3 bytes) - row#, message type, 8-bit mask. Sets all leds on one pin per the bit mask. -- **OFF_LED** (2 bytes) - message type, led address. Turn off specific led. -- **ON_LED** (2 bytes) - message type, led address. Turn on specific led. -- **TOGGLE_LED** (2 bytes) - message type, led address. Toggle specific led on/off. -- **BLINK_OFF_LED** (2 bytes) - message type, led address. Set blink off for specific led. -- **BLINK_ON_LED** (2 bytes) - message type, led address. Set blink on for specific led. -- **BLINK_TOGGLE_LED** (2 bytes) - message type, led address. Toggle blink for specific led. -- **TOGGLE_ALL** (2 bytes) - message type, not used. Turn on/off full backlight. +- **OFF_LED, ON_LED, TOGGLE_LED** (3 bytes) - message type, led address, and page#. Off/on/toggle specific led. +- **BLINK_OFF_LED, BLINK_ON_LED, BLINK_OFF_LED** (3 bytes) - message type, led address, and page#. Set blink Off/on/toggle for specific led. +- **TOGGLE_ALL** (1 byte) - Turn on/off full backlight. - **TOGGLE_BACKLIGHT** (2 bytes) - message type, on/off. Sets backlight completely off, no leds will display. - **DISPLAY_PAGE** (2 bytes) - message type, page to display. Switch to specific pre-set page. - **RESET_PAGE** (2 bytes) - message type, page to reset. Reset/erase specific page. @@ -68,13 +62,13 @@ Sending an action to the led mailbox is done using chMBPost: chMBPost(&led_mailbox, message, timeout); ``` - &led_mailbox - pointer to led mailbox -- message - up to 4 bytes but most messages use only 2. First byte (LSB) is the message to process, the second byte is type. The third is only used to pass row information in SET_FULL_ROW. The fourth byte is currently unused. --timeout is usually TIME_IMMEDIATE +- message - up to 4 bytes but most messages use only 2. First byte (LSB) is the message type, the remaining three bytes are the message to process. +- timeout is TIME_IMMEDIATE An example: ```c //set the message to be sent. First byte (LSB) is the led address, and second is the message type -msg=(ON_LED << 8) | 42; +msg=(42 << 8) | ON_LED //send msg to the led mailbox chMBPost(&led_mailbox, msg, TIME_IMMEDIATE); @@ -82,12 +76,12 @@ chMBPost(&led_mailbox, msg, TIME_IMMEDIATE); Another: ```c -msg=(BLINK_TOGGLE_LED << 8) | 46; +msg=(46 << 8) | BLINK_TOGGLE_LED chMBPost(&led_mailbox, msg, TIME_IMMEDIATE); ``` Finally, SET_FULL_ROW requires an extra byte with row information in the message so sending this message looks like: ```c -msg=(row<<16) | (SET_FULL_ROW << 8) | (led_pin_byte); +msg=(row<<16) | (led_pin_byte << 8) | SET_FULL_ROW; chMBPost(&led_mailbox, msg, TIME_IMMEDIATE); ``` diff --git a/keyboards/infinity60/led.c b/keyboards/infinity60/led.c index d60c76fd8..53147a78a 100644 --- a/keyboards/infinity60/led.c +++ b/keyboards/infinity60/led.c @@ -30,23 +30,23 @@ void led_set(uint8_t usb_led) { if (usb_led & (1<> 24) & 0xFF;//if needed - msg_pin = (msg >> 16) & 0XFF;//if needed (e.g. SET_FULL_ROW) - msg_type = (msg >> 8) & 0xFF; //second byte is msg type - msg_led = (msg) & 0xFF; //first byte is action information + msg_type = msg & 0xFF; //first byte is action information + msg_args[0] = (msg >> 8) & 0xFF; + msg_args[1] = (msg >> 16) & 0XFF; + msg_args[2] = (msg >> 24) & 0xFF; switch (msg_type){ case SET_FULL_ROW: - //write full byte to pin address, msg_pin = pin #, msg_led = byte to write - //writes only to current page - write_led_byte(page_status,msg_pin,msg_led); - break; - - case OFF_LED: - //on/off/toggle single led, msg_led = row/col of led - set_led_bit(7, control_register_word, msg_led, 0); - is31_write_data (7, control_register_word, 0x02); - break; - case ON_LED: - set_led_bit(7, control_register_word, msg_led, 1); - is31_write_data (7, control_register_word, 0x02); - break; - case TOGGLE_LED: - set_led_bit(7, control_register_word, msg_led, 2); - is31_write_data (7, control_register_word, 0x02); + //write full byte to pin address, msg_args[1] = pin #, msg_args[0] = 8 bits to write + //writes only to currently displayed page + write_led_byte(page_status, msg_args[1], msg_args[0]); break; - case BLINK_OFF_LED: - //on/off/toggle single led, msg_led = row/col of led - set_led_bit(7, control_register_word, msg_led, 4); - is31_write_data (7, control_register_word, 0x02); + case OFF_LED: + //on/off/toggle single led, msg_args[0] = row/col of led + set_led_bit(msg_args[1], control_register_word, msg_args[0], 0); + is31_write_data (msg_args[1], control_register_word, 0x02); break; - case BLINK_ON_LED: - set_led_bit(7, control_register_word, msg_led, 5); - is31_write_data (7, control_register_word, 0x02); + case ON_LED: + set_led_bit(msg_args[1], control_register_word, msg_args[0], 1); + is31_write_data (msg_args[1], control_register_word, 0x02); break; - case BLINK_TOGGLE_LED: - set_led_bit(7, control_register_word, msg_led, 6); - is31_write_data (7, control_register_word, 0x02); + case TOGGLE_LED: + set_led_bit(msg_args[1], control_register_word, msg_args[0], 2); + is31_write_data (msg_args[1], control_register_word, 0x02); + break; + + case BLINK_OFF_LED: + //on/off/toggle single led, msg_args[0] = row/col of led + set_led_bit(msg_args[1], control_register_word, msg_args[0], 4); + is31_write_data (msg_args[1], control_register_word, 0x02); + break; + case BLINK_ON_LED: + set_led_bit(msg_args[1], control_register_word, msg_args[0], 5); + is31_write_data (msg_args[1], control_register_word, 0x02); + break; + case BLINK_TOGGLE_LED: + set_led_bit(msg_args[1], control_register_word, msg_args[0], 6); + is31_write_data (msg_args[1], control_register_word, 0x02); break; case TOGGLE_ALL: - //msg_led = unused + //turn on/off all leds, msg_args = unused is31_read_register(0, 0x00, &temp); led_control_reg[0] = 0; - //if first byte is on, then toggle frame 0 off + //if first leds are already on, toggle frame 0 off if (temp==0 || page_status > 0) { __builtin_memcpy(led_control_reg+1, all_on_leds_mask, 0x12); } else { @@ -252,27 +250,27 @@ page_status = 0; //start frame 0 (all off/on) break; case TOGGLE_BACKLIGHT: - //msg_led = on/off + //msg_args[0] = on/off - //populate the 9 byte rows to be written to each pin, first byte is register (pin) address - if (msg_led == 1) { + //populate 9 byte rows to be written to each pin, first byte is register (pin) address + if (msg_args[0] == 1) { __builtin_memset(pwm_register_array+1, pwm_levels[pwm_step_status], 8); } else { __builtin_memset(pwm_register_array+1, 0, 8); } for(i=0; i<8; i++) { - //first byte is register address, every 0x10 9 bytes is A-register pwm pins + //first byte is register address, every 0x10 9 bytes is A-matrix pwm pins pwm_register_array[0] = 0x24 + (i * 0x10); is31_write_data(0,pwm_register_array,9); } break; case DISPLAY_PAGE: - //msg_led = page to toggle on - if (page_status != msg_led) { - is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, msg_led); - page_status = msg_led; + //msg_args[0] = page to toggle on + if (page_status != msg_args[0]) { + is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, msg_args[0]); + page_status = msg_args[0]; //maintain lock leds led_set(host_keyboard_leds()); @@ -280,24 +278,24 @@ page_status = 0; //start frame 0 (all off/on) break; case RESET_PAGE: - //led_msg = page to reset + //led_args[0] = page to reset led_control_reg[0] = 0; __builtin_memset(led_control_reg+1, 0, 0x12); - is31_write_data(msg_led, led_control_reg, 0x13); + is31_write_data(msg_args[0], led_control_reg, 0x13); break; - + case TOGGLE_NUM_LOCK: - //msg_led = 0 or 1, off/on - set_lock_leds(NUM_LOCK_LED_ADDRESS, msg_led, page_status); + //msg_args[0] = 0 or 1, off/on + set_lock_leds(NUM_LOCK_LED_ADDRESS, msg_args[0], page_status); break; case TOGGLE_CAPS_LOCK: - //msg_led = 0 or 1, off/on - set_lock_leds(CAPS_LOCK_LED_ADDRESS, msg_led, page_status); + //msg_args[0] = 0 or 1, off/on + set_lock_leds(CAPS_LOCK_LED_ADDRESS, msg_args[0], page_status); break; case STEP_BRIGHTNESS: - //led_msg = step pwm up or down - switch (msg_led) { + //led_args[0] = step up (1) or down (0) + switch (msg_args[0]) { case 0: if (pwm_step_status == 0) { pwm_step_status = 4; @@ -305,7 +303,7 @@ page_status = 0; //start frame 0 (all off/on) pwm_step_status--; } break; - + case 1: if (pwm_step_status == 4) { pwm_step_status = 0; @@ -316,7 +314,7 @@ page_status = 0; //start frame 0 (all off/on) } //populate 8 byte arrays to write on each pin - //first byte is register address, every 0x10 9 bytes are A-register pwm pins + //first byte is register address, every 0x10 9 bytes are A-matrix pwm pins __builtin_memset(pwm_register_array+1, pwm_levels[pwm_step_status], 8); for(i=0; i<8; i++) { @@ -334,9 +332,9 @@ page_status = 0; //start frame 0 (all off/on) void set_led_bit (uint8_t page, uint8_t *led_control_reg, uint8_t led_addr, uint8_t action) { //returns 2 bytes: led control register address and byte to write - //0 - bit off, 1 - bit on, 2 - toggle bit + //action: 0 - off, 1 - on, 2 - toggle, 4 - blink on, 5 - blink off, 6 - toggle blink - uint8_t control_reg_addr, column_bit, column_byte, bit_temp, blink_on; + uint8_t control_reg_addr, column_bit, column_byte, temp, blink_bit; //check for valid led address if (led_addr < 0 || led_addr > 87 || led_addr % 10 > 8) { @@ -344,17 +342,17 @@ void set_led_bit (uint8_t page, uint8_t *led_control_reg, uint8_t led_addr, uint } //check for blink bit - blink_on = action>>2; + blink_bit = action>>2; action &= ~(1<<2); //strip blink bit //first byte is led control register address 0x00 - //msg_led tens column is pin#, ones column is bit position in 8-bit mask - control_reg_addr = ((led_addr / 10) % 10 - 1 ) * 0x02;// A-register is every other byte - control_reg_addr += blink_on == 1 ? 0x12 : 0x00;//shift 12 bytes to blink register + //led_addr tens column is pin#, ones column is bit position in 8-bit mask + control_reg_addr = ((led_addr / 10) % 10 - 1 ) * 0x02;// A-matrix is every other byte + control_reg_addr += blink_bit == 1 ? 0x12 : 0x00;//if blink_bit, shift 12 bytes to blink register - is31_read_register(page, control_reg_addr, &bit_temp);//maintain status of leds on this byte + is31_read_register(page, control_reg_addr, &temp);//maintain status of leds on this byte column_bit = 1<<(led_addr % 10 - 1); - column_byte = bit_temp; + column_byte = temp; switch(action) { case 0: @@ -376,7 +374,7 @@ void set_led_bit (uint8_t page, uint8_t *led_control_reg, uint8_t led_addr, uint void write_led_byte (uint8_t page, uint8_t row, uint8_t led_byte) { uint8_t led_control_word[2] = {0};//register address and on/off byte - led_control_word[0] = (row - 1 ) * 0x02;// A-register is every other byte + led_control_word[0] = (row - 1 ) * 0x02;// A-matrix is every other byte led_control_word[1] = led_byte; is31_write_data(page, led_control_word, 0x02); } @@ -389,7 +387,7 @@ void write_led_page (uint8_t page, uint8_t *user_led_array, uint8_t led_count) { __builtin_memset(led_control_register,0,13); for(i=0;i Date: Sun, 14 May 2017 16:07:44 -0400 Subject: [PATCH 033/238] Initial push of my keymap --- keyboards/s60_x/keymaps/bluebear/Makefile | 18 +++ keyboards/s60_x/keymaps/bluebear/config.h | 122 ++++++++++++++++ keyboards/s60_x/keymaps/bluebear/keymap.c | 154 +++++++++++++++++++++ keyboards/s60_x/keymaps/bluebear/readme.md | 25 ++++ 4 files changed, 319 insertions(+) create mode 100644 keyboards/s60_x/keymaps/bluebear/Makefile create mode 100644 keyboards/s60_x/keymaps/bluebear/config.h create mode 100644 keyboards/s60_x/keymaps/bluebear/keymap.c create mode 100644 keyboards/s60_x/keymaps/bluebear/readme.md diff --git a/keyboards/s60_x/keymaps/bluebear/Makefile b/keyboards/s60_x/keymaps/bluebear/Makefile new file mode 100644 index 000000000..dfefad39d --- /dev/null +++ b/keyboards/s60_x/keymaps/bluebear/Makefile @@ -0,0 +1,18 @@ +BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration(+1000) +MOUSEKEY_ENABLE = yes # 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 = yes # 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 this with audio at the same time. +SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend +TAP_DANCE_ENABLE = no # Enable tap dancing keys + +ifndef QUANTUM_DIR + include ../../../../Makefile +endif diff --git a/keyboards/s60_x/keymaps/bluebear/config.h b/keyboards/s60_x/keymaps/bluebear/config.h new file mode 100644 index 000000000..2cf96383c --- /dev/null +++ b/keyboards/s60_x/keymaps/bluebear/config.h @@ -0,0 +1,122 @@ +/* +Copyright 2012 Jun Wako + +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 . +*/ + +#ifndef CONFIG_H +#define CONFIG_H + +#include "config_common.h" + +/* USB Device descriptor parameter */ +#define VENDOR_ID 0xFEED +#define PRODUCT_ID 0x6060 +#define DEVICE_VER 0x0003 +#define MANUFACTURER Sentraq +#define PRODUCT S60-RGB +#define DESCRIPTION QMK keyboard firmware for Sentraq S60-RGB + +/* key matrix size */ +#define MATRIX_ROWS 5 +#define MATRIX_COLS 15 + +// ROWS: Top to bottom, COLS: Left to right + +#define MATRIX_ROW_PINS { B5, B4, D7, D6, D4 } +#define MATRIX_COL_PINS { D0, D1, D2, D3, D5, B6, C6, C7, F1, F0, E6, B3, B2, B1, B0 } +#define UNUSED_PINS + +#define BACKLIGHT_PIN B7 + +/* COL2ROW or ROW2COL */ +#define DIODE_DIRECTION COL2ROW + +/* define if matrix has ghost */ +//#define MATRIX_HAS_GHOST + +/* 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 + +/* key combination for command */ +#define IS_COMMAND() ( \ + keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \ +) + +/* Backlight configuration + */ +#define BACKLIGHT_LEVELS 3 + +/* Underlight configuration + */ + +#define RGB_DI_PIN F6 +#define RGBLIGHT_TIMER +#define RGBLED_NUM 10 // Number of LEDs +#define RGBLIGHT_HUE_STEP 10 +#define RGBLIGHT_SAT_STEP 17 +#define RGBLIGHT_VAL_STEP 17 + +/* + * 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 + +// For Tap Dancing + +#define TAPPING_TOGGLE 1 +#define TAPPING_TERM 300 + +/* + * MIDI options + */ + +/* Prevent use of disabled MIDI features in the keymap */ +#define MIDI_ENABLE_STRICT 1 + +/* enable basic MIDI features: + - MIDI notes can be sent when in Music mode is on +*/ +#define MIDI_BASIC + +/* enable advanced MIDI features: + - MIDI notes can be added to the keymap + - Octave shift and transpose + - Virtual sustain, portamento, and modulation wheel + - etc. +*/ +#define MIDI_ADVANCED + +/* override number of MIDI tone keycodes (each octave adds 12 keycodes and allocates 12 bytes) */ +#define MIDI_TONE_KEYCODE_OCTAVES 2 + +#endif diff --git a/keyboards/s60_x/keymaps/bluebear/keymap.c b/keyboards/s60_x/keymaps/bluebear/keymap.c new file mode 100644 index 000000000..3861ad04f --- /dev/null +++ b/keyboards/s60_x/keymaps/bluebear/keymap.c @@ -0,0 +1,154 @@ +#include "s60_x.h" + +// Keyboard Layers + +enum keyboard_layers { + BASE = 0, //Base Layer + ARROW, //Arrow/FN Layer + MOUSE, //Mouse Layer + MIDI, //Midi Layer +}; + +// Midi Chord Keycodes + +enum midi_chord_keycodes { + + //Major Chords + + MI_CH_C = SAFE_RANGE, + MI_CH_Cs, + MI_CH_Db = MI_CH_Cs, + MI_CH_D, + MI_CH_Ds, + MI_CH_Eb = MI_CH_Ds, + MI_CH_E, + MI_CH_F, + MI_CH_Fs, + MI_CH_Gb = MI_CH_Fs, + MI_CH_G, + MI_CH_Gs, + MI_CH_Ab = MI_CH_Gs, + MI_CH_A, + MI_CH_As, + MI_CH_Bb = MI_CH_As, + MI_CH_B, + + //Minor Chords + + MI_CH_Cm, + MI_CH_Csm, + MI_CH_Dbm = MI_CH_Csm, + MI_CH_Dm, + MI_CH_Dsm, + MI_CH_Ebm = MI_CH_Dsm, + MI_CH_Em, + MI_CH_Fm, + MI_CH_Fsm, + MI_CH_Gbm = MI_CH_Fsm, + MI_CH_Gm, + MI_CH_Gsm, + MI_CH_Abm = MI_CH_Gsm, + MI_CH_Am, + MI_CH_Asm, + MI_CH_Bbm = MI_CH_Asm, + MI_CH_Bm, +}; + +//Keymaps + +const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + + /* 0: Custom Dvorak/HHKBish Base Layer + + ┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐ + │ ESC │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ [ │ ] │ \ │ ` │ + ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ + │ TAB │ ' │ , │ . │ P │ Y │ F │ G │ C │ R │ L │ / │ = │BSPC │█████│ + ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ + │CT/ES│ A │ O │ E │ U │ I │ D │ H │ T │ N │ S │ - │▒▒▒▒▒│CT/EN│█████│ + ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ + │LSPO │▒▒▒▒▒│ ; │ Q │ J │ K │ X │ B │ M │ W │ V │ Z │▒▒▒▒▒│RSPC │▒▒▒▒▒│ + ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ + │MO(2)│L_GUI│L_ALT│█████│█████│█████│SPFN1│█████│█████│█████│AG/AP│R_GUI│CT|S │CT|AL│█████│ + └─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┘ + */ + + [BASE] = KEYMAP( + KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_LBRC, KC_RBRC, KC_BSLS, KC_GRV, \ + KC_TAB, KC_QUOT, KC_COMM, KC_DOT, KC_P, KC_Y, KC_F, KC_G, KC_C, KC_R, KC_L, KC_SLSH, KC_EQL, KC_BSPC, \ + CTL_T(KC_ESC), KC_A, KC_O, KC_E, KC_U, KC_I, KC_D, KC_H, KC_T, KC_N, KC_S, KC_MINS, KC_NO, MT(MOD_RCTL, KC_ENT), \ + KC_LSPO, KC_NO, KC_SCLN, KC_Q, KC_J, KC_K, KC_X, KC_B, KC_M, KC_W, KC_V, KC_Z, KC_NO, KC_RSPC, KC_NO, \ + MO(2), KC_LGUI, KC_LALT, LT(1, KC_SPACE), ALGR_T(KC_APP), KC_RGUI, OSM(MOD_LCTL | MOD_LSFT), OSM(MOD_LCTL | MOD_LALT) + ), + + /* 1: Arrow/Missing Keys Layer + + ┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐ + │TG(3)│ F1 │ F2 │ F3 │ F4 │ F5 │ F6 │ F7 │ F8 │ F9 │ F10 │ F11 │ F12 │ │ │ + ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ + │CAPS │ │ │ │ │ │ │PGUP │ UP │HOME │ END │ │ INS │ DEL │█████│ + ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ + │ │ │ │ │ │ │ │LEFT │DOWN │RIGHT│ │ │▒▒▒▒▒│ │█████│ + ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ + │ │▒▒▒▒▒│ │ │ │ │ │SPACE│PGDN │PSCR │SLCK │PAUSE│▒▒▒▒▒│ │▒▒▒▒▒│ + ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ + │ │ │ │█████│█████│█████│ │█████│█████│█████│ │ │ │ │█████│ + └─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┘ + */ + + [ARROW] = KEYMAP( + TG(3), KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_NO, KC_NO, \ + KC_CAPS, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_PGUP, KC_UP, KC_HOME, KC_END, KC_NO, KC_INS, KC_DEL, \ + KC_TRNS, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_LEFT, KC_DOWN, KC_RIGHT, KC_NO, KC_NO, KC_NO, KC_TRNS, \ + KC_TRNS, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_SPACE, KC_PGDN, KC_PSCR, KC_SLCK, KC_PAUS, KC_NO, KC_TRNS, KC_NO, \ + KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS + ), + + /* 2: Mouse Keys Layer + + ┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐ + │RESET│ F1 │ F2 │ F3 │ F4 │ F5 │ F6 │ F7 │ F8 │ F9 │ F10 │ │ │ │ │ + ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ + │ │ │ │ │ │ │ │BTN1 │MS_UP│BTN2 │WH_UP│ │ │ │█████│ + ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ + │ │ │ │ │ │ │ │MS_LT│MS_DN│MS_RT│WH_DN│BTN3 │▒▒▒▒▒│ │█████│ + ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ + │ │▒▒▒▒▒│ │ │ │ │ │ │ │ │ │ │▒▒▒▒▒│ │▒▒▒▒▒│ + ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ + │ │ │ │█████│█████│█████│ PWR │█████│█████│█████│ │ │ │ │█████│ + └─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┘ + */ + + [MOUSE] = KEYMAP( + + RESET, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_NO, KC_NO, \ + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_BTN1, KC_MS_UP, KC_BTN2, KC_WH_U, KC_NO, KC_NO, KC_NO, \ + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_MS_LEFT, KC_MS_DOWN, KC_MS_RIGHT, KC_WH_D, KC_BTN3, KC_NO, KC_NO, \ + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, \ + KC_TRNS, KC_NO, KC_NO, KC_POWER, KC_NO, KC_NO, KC_NO, KC_NO + ), + + /* 3: Midi Layer + + ┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐ + │TG(0)│ Cmaj│ Gmaj│ Dmaj│ Amaj│ Emaj│ Bmaj│Gbmaj│Dbmaj│Abmaj│Ebmaj│Bbmaj│ Fmaj│ │ │ + ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ + │ │ │ C# │ D# │ │ F# │ G# │ A# │ │ C# │ D# │ │ │ │█████│ + ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ + │OCT- │ C │ D │ E │ F │ G │ A │ B │ C │ D │ E │ F │▒▒▒▒▒│OCT+ │█████│ + ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ + │ Am │▒▒▒▒▒│ Em │ Bm │ F#m │ C#m │ G#m │ D#m │ Bbm │ Fm │ Cm │ Gm │▒▒▒▒▒│ Dm │▒▒▒▒▒│ + ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ + │ │ │ │█████│█████│█████│A-OFF│█████│█████│█████│ │ │ │ │█████│ + └─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┘ + */ + + [MIDI] = KEYMAP( + TO(0), MI_CH_C, MI_CH_G, MI_CH_D, MI_CH_A, MI_CH_E, MI_CH_B, MI_CH_Gb, MI_CH_Db, MI_CH_Ab, MI_CH_Eb, MI_CH_Bb, MI_CH_F, KC_NO, KC_NO, \ + KC_NO, KC_NO, MI_Cs, MI_Ds, KC_NO, MI_Fs, MI_Gs, MI_As, KC_NO, MI_Cs_1, MI_Ds_1, KC_NO, KC_NO, KC_NO, \ + MI_OCTD, MI_C, MI_D, MI_E, MI_F, MI_G, MI_A, MI_B, MI_C_1, MI_D_1, MI_E_1, MI_F_1, KC_NO, MI_OCTU, \ + MI_CH_Am, KC_NO, MI_CH_Em, MI_CH_Bm, MI_CH_Fsm, MI_CH_Csm, MI_CH_Gsm, MI_CH_Dsm, MI_CH_Bbm, MI_CH_Fm, MI_CH_Cm, MI_CH_Gm, KC_NO, MI_CH_Dm, KC_NO, \ + KC_NO, KC_NO, KC_NO, MI_ALLOFF, KC_NO, KC_NO, KC_NO, KC_NO + ), + +}; diff --git a/keyboards/s60_x/keymaps/bluebear/readme.md b/keyboards/s60_x/keymaps/bluebear/readme.md new file mode 100644 index 000000000..579683abc --- /dev/null +++ b/keyboards/s60_x/keymaps/bluebear/readme.md @@ -0,0 +1,25 @@ +## Bluebear’s custom S60X layout + +Custom keyboard layout for my S60X, my first ever custom mechanical keyboard kit. + +This layout was inspired in part by the HHKB line of keyboards and a quest to find the perfect ergonomic, logical layout for what I do. If you like this layout, please feel free to use it, modify it and share it. + +## Base Layer + +-Hold left control key for LCTL, and tap it for ESC +-Hold enter key for RCTL and tap for ENT +-Hold the space key to momentarily switch to [ARROW] layer +-Left bottom key acts as momentary switch to the [MOUSE] layer +-Hold right alt key for AltGr and tap for APP(which I have mapped to Compose in OS) +-Hold left shift key for LSFT and tap for ( (Space Cadet style) +-Hold right shift key for RSFT and tap for ) (Space Cadet style) +-Tap key on bottom row, second from the right (where APP usually is) to get CTL-Shift (one shot modifier - next key pressed will be modified by ctl-shift) +-Tap key on bottom right to get CTL-Alt (one shot modifier - next key pressed will be modified by ctl-alt) + +## Mouse Layer + +-Hitting the escape key in this layer will give RESET, which puts the controller into dfu mode for flashing firmware onto it +-Hitting the space key in this layer is like hitting power button on computer + + + From ee0b34feaf99debbc47fe736001181dffa3cd6b1 Mon Sep 17 00:00:00 2001 From: Ante Laurijssen Date: Sun, 14 May 2017 20:07:35 -0400 Subject: [PATCH 034/238] Started working on custom midi chord function --- keyboards/s60_x/keymaps/bluebear/keymap.c | 68 +++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/keyboards/s60_x/keymaps/bluebear/keymap.c b/keyboards/s60_x/keymaps/bluebear/keymap.c index 3861ad04f..f963043c1 100644 --- a/keyboards/s60_x/keymaps/bluebear/keymap.c +++ b/keyboards/s60_x/keymaps/bluebear/keymap.c @@ -11,6 +11,13 @@ enum keyboard_layers { // Midi Chord Keycodes +bool midi_chord(uint8_t mode, uint16_t root); + +enum midi_chord_modes { + major = 0, + minor, +}; + enum midi_chord_keycodes { //Major Chords @@ -152,3 +159,64 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { ), }; + +// Midi Chord Function + +bool midi_chord(uint8_t mode, uint16_t root) { + switch (mode) { + case 0: + uint8_t channel = midi_config.channel; + uint8_t tone = root - MIDI_TONE_MIN; + uint8_t velocity = compute_velocity(midi_config.velocity); + if (record->event.pressed) { + uint8_t root_note = midi_compute_note(root); + uint8_t major_third = midi_compute_note(root) + 4; + uint8_t fifth = midi_compute_note(root) + 7; + midi_send_noteon(&midi_device, channel, root_note, velocity); + midi_send_noteon(&midi_device, channel, major_third, velocity); + midi_send_noteon(&midi_device, channel, fifth, velocity); + tone_status[tone] = root_note; + } + else { + uint8_t root_note = tone_status[tone]; + uint8_t major_third = root_note + 4; + uint8_t fifth = root_note + 7; + if (root_note != MIDI_INVALID_NOTE) + { + midi_send_noteoff(&midi_device, channel, root_note, velocity); + midi_send_noteoff(&midi_device, channel, major_third, velocity); + midi_send_noteoff(&midi_device, channel, fifth, velocity); + } + tone_status[tone] = MIDI_INVALID_NOTE; + } + return false; + case 1: + uint8_t channel = midi_config.channel; + uint8_t tone = root - MIDI_TONE_MIN; + uint8_t velocity = compute_velocity(midi_config.velocity); + if (record->event.pressed) { + uint8_t root_note = midi_compute_note(root); + uint8_t minor_third = midi_compute_note(root) + 3; + uint8_t fifth = midi_compute_note(root) + 7; + midi_send_noteon(&midi_device, channel, root_note, velocity); + midi_send_noteon(&midi_device, channel, major_third, velocity); + midi_send_noteon(&midi_device, channel, fifth, velocity); + tone_status[tone] = root_note; + } + else { + uint8_t root_note = tone_status[tone]; + uint8_t minor_third = root_note + 3; + uint8_t fifth = root_note + 7; + if (root_note != MIDI_INVALID_NOTE) + { + midi_send_noteoff(&midi_device, channel, root_note, velocity); + midi_send_noteoff(&midi_device, channel, minor_third, velocity); + midi_send_noteoff(&midi_device, channel, fifth, velocity); + } + tone_status[tone] = MIDI_INVALID_NOTE; + } + return false; + }; + return true; +}; + From 814b570ba1f2f9a12996c50844b7c8861ec1e919 Mon Sep 17 00:00:00 2001 From: Ante Laurijssen Date: Mon, 15 May 2017 22:56:33 -0400 Subject: [PATCH 035/238] Working on keymap.c file... --- keyboards/s60_x/keymaps/bluebear/keymap.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/keyboards/s60_x/keymaps/bluebear/keymap.c b/keyboards/s60_x/keymaps/bluebear/keymap.c index f963043c1..124c482b2 100644 --- a/keyboards/s60_x/keymaps/bluebear/keymap.c +++ b/keyboards/s60_x/keymaps/bluebear/keymap.c @@ -9,15 +9,16 @@ enum keyboard_layers { MIDI, //Midi Layer }; -// Midi Chord Keycodes +// Midi Chord Keycodes +/* bool midi_chord(uint8_t mode, uint16_t root); enum midi_chord_modes { major = 0, minor, }; - +*/ enum midi_chord_keycodes { //Major Chords @@ -160,6 +161,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { }; +/* // Midi Chord Function bool midi_chord(uint8_t mode, uint16_t root) { @@ -199,7 +201,7 @@ bool midi_chord(uint8_t mode, uint16_t root) { uint8_t minor_third = midi_compute_note(root) + 3; uint8_t fifth = midi_compute_note(root) + 7; midi_send_noteon(&midi_device, channel, root_note, velocity); - midi_send_noteon(&midi_device, channel, major_third, velocity); + midi_send_noteon(&midi_device, channel, minor_third, velocity); midi_send_noteon(&midi_device, channel, fifth, velocity); tone_status[tone] = root_note; } @@ -219,4 +221,4 @@ bool midi_chord(uint8_t mode, uint16_t root) { }; return true; }; - +*/ From 26c6f6a85c9c16a3be27e6c61609b3da99ec3f73 Mon Sep 17 00:00:00 2001 From: Ante Laurijssen Date: Tue, 16 May 2017 22:08:45 -0400 Subject: [PATCH 036/238] Added Space Cadet Rollover Disable to config.h --- keyboards/s60_x/keymaps/bluebear/config.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/keyboards/s60_x/keymaps/bluebear/config.h b/keyboards/s60_x/keymaps/bluebear/config.h index 2cf96383c..94438bdc9 100644 --- a/keyboards/s60_x/keymaps/bluebear/config.h +++ b/keyboards/s60_x/keymaps/bluebear/config.h @@ -119,4 +119,7 @@ along with this program. If not, see . /* override number of MIDI tone keycodes (each octave adds 12 keycodes and allocates 12 bytes) */ #define MIDI_TONE_KEYCODE_OCTAVES 2 +// Space Cadet Rollover - if set, allows to tap opposite shift key to cancel erroneous press +#define DISABLE_SPACE_CADET_ROLLOVER + #endif From b766407cbe07e78f5cf5ce2ec77694541d598e0e Mon Sep 17 00:00:00 2001 From: Ante Laurijssen Date: Sun, 21 May 2017 08:40:42 -0400 Subject: [PATCH 037/238] Continuing work on keymap.c --- keyboards/s60_x/keymaps/bluebear/keymap.c | 450 ++++++++++++++++++++-- 1 file changed, 416 insertions(+), 34 deletions(-) diff --git a/keyboards/s60_x/keymaps/bluebear/keymap.c b/keyboards/s60_x/keymaps/bluebear/keymap.c index 124c482b2..0b3b8b65b 100644 --- a/keyboards/s60_x/keymaps/bluebear/keymap.c +++ b/keyboards/s60_x/keymaps/bluebear/keymap.c @@ -4,62 +4,140 @@ enum keyboard_layers { BASE = 0, //Base Layer - ARROW, //Arrow/FN Layer + ARROWFN, //Arrow/FN Layer MOUSE, //Mouse Layer MIDI, //Midi Layer + MORSE, //Morse Code Layer }; +// Midi Chords -// Midi Chord Keycodes -/* -bool midi_chord(uint8_t mode, uint16_t root); - -enum midi_chord_modes { +enum midi_chord_modes { //ACTION_FUNCTION id major = 0, minor, }; -*/ + +enum midi_chord_root { //ACTION_FUNCTION opt + C = 0, + Cs, + Db = Cs, + D, + Ds, + Eb = Ds, + E, + F, + Fs, + Gb = Fs, + G, + Gs, + Ab = Gs, + A, + As, + Bb = As, + B, +}; + enum midi_chord_keycodes { //Major Chords - MI_CH_C = SAFE_RANGE, - MI_CH_Cs, + MI_CH_C = ACTION_FUNCTION(0, 0), + MI_CH_Cs = ACTION_FUNCTION(0, 1), MI_CH_Db = MI_CH_Cs, - MI_CH_D, - MI_CH_Ds, + MI_CH_D = ACTION_FUNCTION(0, 2), + MI_CH_Ds = ACTION_FUNCTION(0, 3), MI_CH_Eb = MI_CH_Ds, - MI_CH_E, - MI_CH_F, - MI_CH_Fs, + MI_CH_E = ACTION_FUNCTION(0, 4), + MI_CH_F = ACTION_FUNCTION(0, 5), + MI_CH_Fs = ACTION_FUNCTION(0, 6), MI_CH_Gb = MI_CH_Fs, - MI_CH_G, - MI_CH_Gs, + MI_CH_G = ACTION_FUNCTION(0, 7), + MI_CH_Gs = ACTION_FUNCTION(0, 8), MI_CH_Ab = MI_CH_Gs, - MI_CH_A, - MI_CH_As, + MI_CH_A = ACTION_FUNCTION(0, 9), + MI_CH_As = ACTION_FUNCTION(0, 10), MI_CH_Bb = MI_CH_As, - MI_CH_B, + MI_CH_B = ACTION_FUNCTION(0, 11), //Minor Chords - MI_CH_Cm, - MI_CH_Csm, + MI_CH_Cm = ACTION_FUNCTION(1, 0), + MI_CH_Csm = ACTION_FUNCTION(1, 1), MI_CH_Dbm = MI_CH_Csm, - MI_CH_Dm, - MI_CH_Dsm, + MI_CH_Dm = ACTION_FUNCTION(1, 2), + MI_CH_Dsm = ACTION_FUNCTION(1, 3), MI_CH_Ebm = MI_CH_Dsm, - MI_CH_Em, - MI_CH_Fm, - MI_CH_Fsm, + MI_CH_Em = ACTION_FUNCTION(1, 4), + MI_CH_Fm = ACTION_FUNCTION(1, 5), + MI_CH_Fsm = ACTION_FUNCTION(1, 6), MI_CH_Gbm = MI_CH_Fsm, - MI_CH_Gm, - MI_CH_Gsm, + MI_CH_Gm = ACTION_FUNCTION(1, 7), + MI_CH_Gsm= ACTION_FUNCTION(1, 8), MI_CH_Abm = MI_CH_Gsm, - MI_CH_Am, - MI_CH_Asm, + MI_CH_Am = ACTION_FUNCTION(1, 9), + MI_CH_Asm = ACTION_FUNCTION(1, 10), MI_CH_Bbm = MI_CH_Asm, - MI_CH_Bm, + MI_CH_Bm = ACTION_FUNCTION(1, 11), +}; + +//Morse Code Macro Keys + +enum morse_macros { + MC_0 = M(0), + MC_1 = M(1), + MC_2 = M(2), + MC_3 = M(3), + MC_4 = M(4), + MC_5 = M(5), + MC_6 = M(6), + MC_7 = M(7), + MC_8 = M(8), + MC_9 = M(9), + MC_A = M(10), + MC_B = M(11), + MC_C = M(12), + MC_D = M(13), + MC_E = M(14), + MC_F = M(15), + MC_G = M(16), + MC_H = M(17), + MC_I = M(18), + MC_J = M(19), + MC_K = M(20), + MC_L = M(21), + MC_M = M(22), + MC_N = M(23), + MC_O = M(24), + MC_P = M(25), + MC_Q = M(26), + MC_R = M(27), + MC_S = M(28), + MC_T = M(29), + MC_U = M(30), + MC_V = M(31), + MC_W = M(32), + MC_X = M(33), + MC_Y = M(34), + MC_Z = M(35), + MC_DOT = M(36), + MC_COMM = M(37), + MC_QUES = M(38), + MC_APOS = M(39), + MC_EXCL = M(40), + MC_SLSH = M(41), + MC_PARO = M(42), + MC_PARC = M(43), + MC_AMP = M(44), + MC_COL = M(45), + MC_SCLN = M(46), + MC_EQL = M(47), + MC_PLUS = M(48), + MC_MINS = M(49), + MC_QUOT = M(50), + MC_DOLR = M(51), + MC_AT = M(52), + MC_UNDS = M(53), + MC_SPACE = M(54), }; //Keymaps @@ -89,7 +167,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { MO(2), KC_LGUI, KC_LALT, LT(1, KC_SPACE), ALGR_T(KC_APP), KC_RGUI, OSM(MOD_LCTL | MOD_LSFT), OSM(MOD_LCTL | MOD_LALT) ), - /* 1: Arrow/Missing Keys Layer + /* 1: Arrow/FN Layer ┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐ │TG(3)│ F1 │ F2 │ F3 │ F4 │ F5 │ F6 │ F7 │ F8 │ F9 │ F10 │ F11 │ F12 │ │ │ @@ -104,7 +182,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { └─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┘ */ - [ARROW] = KEYMAP( + [ARROWFN] = KEYMAP( TG(3), KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_NO, KC_NO, \ KC_CAPS, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_PGUP, KC_UP, KC_HOME, KC_END, KC_NO, KC_INS, KC_DEL, \ KC_TRNS, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_LEFT, KC_DOWN, KC_RIGHT, KC_NO, KC_NO, KC_NO, KC_TRNS, \ @@ -159,12 +237,316 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { KC_NO, KC_NO, KC_NO, MI_ALLOFF, KC_NO, KC_NO, KC_NO, KC_NO ), + /* 4: Morse Code Layer + + ┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐ + │ │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ │ │ │ │ + ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ + │ │ ' │ , │ . │ P │ Y │ F │ G │ C │ R │ L │ / │ = │BSPC │█████│ + ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ + │ │ A │ O │ E │ U │ I │ D │ H │ T │ N │ S │ - │▒▒▒▒▒│ENTER│█████│ + ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ + │SHIFT│▒▒▒▒▒│ ; │ Q │ J │ K │ X │ B │ M │ W │ V │ Z │▒▒▒▒▒│SHIFT│▒▒▒▒▒│ + ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ + │ │ │ │█████│█████│█████│SPACE│█████│█████│█████│ │ │ │ │█████│ + └─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┘ + */ + + [MORSE] = KEYMAP( + KC_NO, MC_1, MC_2, MC_3, MC_4, MC_5, MC_6, MC_7, MC_8, MC_9, MC_0, KC_NO, KC_NO, KC_NO, KC_NO, \ + KC_NO, MC_APOS, MC_COMM, MC_DOT, MC_P, MC_Y, MC_F, MC_G, MC_C, MC_R, MC_L, MC_SLSH, MC_EQL, KC_BSPC, \ + KC_NO, MC_A, MC_O, MC_E, MC_U, MC_I, MC_D, MC_H, MC_T, MC_N, MC_S, MC_MINS, KC_NO, KC_ENT, \ + KC_LSFT, KC_NO, MC_SCLN, MC_Q, MC_J, MC_K, MC_X, MC_B, MC_M, MC_W, MC_V, MC_Z, KC_NO, KC_RSFT, KC_NO, \ + KC_NO, KC_NO, KC_NO, MC_SPACE, KC_NO, KC_NO, KC_NO, KC_NO + ), + +}; + +// Morse Code Macros + +const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) +{ + switch(id) { + case 0: //Number 0 + if (record->event.pressed) { + return MACRO(T(MINS), T(MINS), T(MINS), T(MINS), T(MINS), T(SPACE), END); //----- + } + break; + case 1: //Number 1 + if (record->event.pressed) { + return MACRO(T(DOT), T(MINS), T(MINS), T(MINS), T(MINS), T(SPACE), END); //.---- + } + break; + case 2: //Number 2 + if (record->event.pressed) { + return MACRO(T(DOT), T(DOT), T(MINS), T(MINS), T(MINS), T(SPACE), END); //..--- + } + break; + case 3: // Number 3 + if (record->event.pressed) { + return MACRO(T(DOT), T(DOT), T(DOT), T(MINS), T(MINS), T(SPACE), END); //...-- + } + break; + case 4: //Number 4 + if (record->event.pressed) { + return MACRO(T(DOT), T(DOT), T(DOT), T(DOT), T(MINS), T(SPACE), END); //....- + } + break; + case 5: //Number 5 + if (record->event.pressed) { + return MACRO(T(DOT), T(DOT), T(DOT), T(DOT), T(DOT), T(SPACE), END); //..... + } + break; + case 6: //Number 6 + if (record->event.pressed) { + return MACRO(T(MINS), T(DOT), T(DOT), T(DOT), T(DOT), T(SPACE), END); //-.... + } + break; + case 7: //Number 7 + if (record->event.pressed) { + return MACRO(T(MINS), T(MINS), T(DOT), T(DOT), T(DOT), T(SPACE), END); //--... + } + break; + case 8: //Number 8 + if (record->event.pressed) { + return MACRO(T(MINS), T(MINS), T(MINS), T(DOT), T(DOT), T(SPACE), END); //---.. + } + break; + case 9: //Number 9 + if (record->event.pressed) { + return MACRO(T(MINS), T(MINS), T(MINS), T(MINS), T(DOT), T(SPACE), END); //----. + } + break; + case 10: //Letter A + if (record->event.pressed) { + return MACRO(T(DOT), T(MINS), T(SPACE), END); //.- + } + break; + case 11: //Letter B + if (record->event.pressed) { + return MACRO(T(MINS), T(DOT), T(DOT), T(DOT), T(SPACE), END); //-... + } + break; + case 12: //Letter C + if (record->event.pressed) { + return MACRO(T(MINS), T(DOT), T(MINS), T(DOT), T(SPACE), END); //-.-. + } + break; + case 13: //Letter D + if (record->event.pressed) { + return MACRO(T(MINS), T(DOT), T(DOT), T(SPACE), END); //-.. + } + break; + case 14: //Letter E + if (record->event.pressed) { + return MACRO(T(DOT), T(SPACE), END); //. + } + break; + case 15: //Letter F + if (record->event.pressed) { + return MACRO(T(DOT), T(DOT), T(MINS), T(DOT), T(SPACE), END); //..-. + } + break; + case 16: //Letter G + if (record->event.pressed) { + return MACRO(T(MINS), T(MINS), T(DOT), T(SPACE), END); //--. + } + break; + case 17: //Letter H + if (record->event.pressed) { + return MACRO(T(DOT), T(DOT), T(DOT), T(DOT), T(SPACE), END); //.... + } + break; + case 18: //Letter I + if (record->event.pressed) { + return MACRO(T(DOT), T(DOT), T(SPACE), END); //.. + } + break; + case 19: //Letter J + if (record->event.pressed) { + return MACRO(T(DOT), T(MINS), T(MINS), T(MINS), T(SPACE), END); //.--- + } + break; + case 20: //Letter K + if (record->event.pressed) { + return MACRO(T(MINS), T(DOT), T(MINS), T(SPACE), END); //-.- + } + break; + case 21: //Letter L + if (record->event.pressed) { + return MACRO(T(DOT), T(MINS), T(DOT), T(DOT), T(SPACE), END); //.-.. + } + break; + case 22: //Letter M + if (record->event.pressed) { + return MACRO(T(MINS), T(MINS), T(SPACE), END); //-- + } + break; + case 23: //Letter N + if (record->event.pressed) { + return MACRO(T(MINS), T(DOT), T(SPACE), END); //-. + } + break; + case 24: //Letter O + if (record->event.pressed) { + return MACRO(T(MINS), T(MINS), T(MINS), T(SPACE), END); //--- + } + break; + case 25: //Letter P + if (record->event.pressed) { + return MACRO(T(DOT), T(MINS), T(MINS), T(DOT), T(SPACE), END); //.--. + } + break; + case 26: //Letter Q + if (record->event.pressed) { + return MACRO(T(MINS), T(MINS), T(DOT), T(MINS), T(SPACE), END); //--.- + } + break; + case 27: //Letter R + if (record->event.pressed) { + return MACRO(T(DOT), T(MINS), T(DOT), T(SPACE), END); //.-. + } + break; + case 28: //Letter S + if (record->event.pressed) { + return MACRO(T(DOT), T(DOT), T(DOT), T(SPACE), END); //... + } + break; + case 29: //Letter T + if (record->event.pressed) { + return MACRO(T(MINS), T(SPACE), END); //- + } + break; + case 30: //Letter U + if (record->event.pressed) { + return MACRO(T(DOT), T(DOT), T(MINS), T(SPACE), END); //..- + } + break; + case 31: //Letter V + if (record->event.pressed) { + return MACRO(T(DOT), T(DOT), T(DOT), T(MINS), T(SPACE), END); //...- + } + break; + case 32: //Letter W + if (record->event.pressed) { + return MACRO(T(DOT), T(MINS), T(MINS), T(SPACE), END); //.-- + } + break; + case 33: //Letter X + if (record->event.pressed) { + return MACRO(T(MINS), T(DOT), T(DOT), T(MINS), T(SPACE), END); //-..- + } + break; + case 34: //Letter Y + if (record->event.pressed) { + return MACRO(T(MINS), T(DOT), T(MINS), T(MINS), T(SPACE), END); //-.-- + } + break; + case 35: //Letter Z + if (record->event.pressed) { + return MACRO(T(MINS), T(MINS), T(DOT), T(DOT), T(SPACE), END); //--.. + } + break; + case 36: //Punctuation . + if (record->event.pressed) { + return MACRO(T(DOT), T(MINS), T(DOT), T(MINS), T(DOT), T(MINS), T(SPACE), END); //.-.-.- + } + break; + case 37: //Punctuation , + if (record->event.pressed) { + return MACRO(T(MINS), T(MINS), T(DOT), T(DOT), T(MINS), T(MINS), T(SPACE), END); //--..-- + } + break; + case 38: //Punctuation ? + if (record->event.pressed) { + return MACRO(T(DOT), T(DOT), T(MINS), T(MINS), T(DOT), T(DOT), T(SPACE), END); //..--.. + } + break; + case 39: //Punctuation ' + if (record->event.pressed) { + return MACRO(T(DOT), T(MINS), T(MINS), T(MINS), T(MINS), T(DOT), T(SPACE), END); //-....- + } + break; + case 40: //Punctuation ! + if (record->event.pressed) { + return MACRO(T(MINS), T(DOT), T(MINS), T(DOT), T(MINS), T(MINS), T(SPACE), END); //-.-.-- + } + break; + case 41: //Punctuation / + if (record->event.pressed) { + return MACRO(T(MINS), T(DOT), T(DOT), T(MINS), T(DOT), T(SPACE), END); //-..-. + } + break; + case 42: //Punctuation ( + if (record->event.pressed) { + return MACRO(T(MINS), T(DOT), T(MINS), T(MINS), T(DOT), T(SPACE), END); //-.--. + } + break; + case 43: //Punctuation ) + if (record->event.pressed) { + return MACRO(T(MINS), T(DOT), T(MINS), T(MINS), T(DOT), T(MINS), T(SPACE), END); //-.--.- + } + break; + case 44: //Punctuation & + if (record->event.pressed) { + return MACRO(T(DOT), T(MINS), T(DOT), T(DOT), T(DOT), T(SPACE), END); //.-... + } + break; + case 45: //Punctuation : + if (record->event.pressed) { + return MACRO(T(MINS), T(MINS), T(MINS), T(DOT), T(DOT), T(DOT), T(SPACE), END); //---... + } + break; + case 46: //Punctuation ; + if (record->event.pressed) { + return MACRO(T(MINS), T(DOT), T(MINS), T(DOT), T(MINS), T(DOT), T(SPACE), END); //-.-.-. + } + break; + case 47: //Punctuation = + if (record->event.pressed) { + return MACRO(T(MINS), T(DOT), T(DOT), T(DOT), T(MINS), T(SPACE), END); //-...- + } + break; + case 48: //Punctuation + + if (record->event.pressed) { + return MACRO(T(DOT), T(MINS), T(DOT), T(MINS), T(DOT), T(SPACE), END); //.-.-. + } + break; + case 49: //Punctuation - + if (record->event.pressed) { + return MACRO(T(MINS), T(DOT), T(DOT), T(DOT), T(DOT), T(MINS), T(SPACE), END); //-....- + } + break; + case 50: //Punctuation " + if (record->event.pressed) { + return MACRO(T(DOT), T(MINS), T(DOT), T(DOT), T(MINS), T(DOT), T(SPACE), END); //.-..-. + } + break; + case 51: //Punctuation $ + if (record->event.pressed) { + return MACRO(T(DOT), T(DOT), T(DOT), T(MINS), T(DOT), T(DOT), T(MINS), T(SPACE), END); //...-..- + } + break; + case 52: //Punctuation @ + if (record->event.pressed) { + return MACRO(T(DOT), T(MINS), T(MINS), T(DOT), T(MINS), T(DOT), T(SPACE), END); //.--.-. + } + break; + case 53: //Punctuation _ + if (record->event.pressed) { + return MACRO(T(DOT), T(DOT), T(MINS), T(MINS), T(DOT), T(MINS), T(SPACE), END); //..--.- + case 54: //Morse Space + if (record->event.pressed) { + return MACRO(T(BSLS), T(SPACE), END); //When pressed, this sends a slash followed by a space, making it easier to distinguish words in Morse + } + break; + } + return MACRO_NONE; }; /* // Midi Chord Function -bool midi_chord(uint8_t mode, uint16_t root) { switch (mode) { case 0: uint8_t channel = midi_config.channel; From 06433eb1a0563fe8c17bdd31c42d5f6b94a6e508 Mon Sep 17 00:00:00 2001 From: Ante Laurijssen Date: Sun, 21 May 2017 22:37:20 -0400 Subject: [PATCH 038/238] More work on keymap.c and config.h --- keyboards/s60_x/keymaps/bluebear/config.h | 5 +- keyboards/s60_x/keymaps/bluebear/keymap.c | 296 ++++++++++++++-------- 2 files changed, 197 insertions(+), 104 deletions(-) diff --git a/keyboards/s60_x/keymaps/bluebear/config.h b/keyboards/s60_x/keymaps/bluebear/config.h index 94438bdc9..5c0d08833 100644 --- a/keyboards/s60_x/keymaps/bluebear/config.h +++ b/keyboards/s60_x/keymaps/bluebear/config.h @@ -121,5 +121,8 @@ along with this program. If not, see . // Space Cadet Rollover - if set, allows to tap opposite shift key to cancel erroneous press #define DISABLE_SPACE_CADET_ROLLOVER - + +// Prevent stuck modifiers +#define PREVENT_STUCK_MODIFIERS + #endif diff --git a/keyboards/s60_x/keymaps/bluebear/keymap.c b/keyboards/s60_x/keymaps/bluebear/keymap.c index 0b3b8b65b..d383d2e28 100644 --- a/keyboards/s60_x/keymaps/bluebear/keymap.c +++ b/keyboards/s60_x/keymaps/bluebear/keymap.c @@ -3,7 +3,7 @@ // Keyboard Layers enum keyboard_layers { - BASE = 0, //Base Layer + BASE, //Base Layer ARROWFN, //Arrow/FN Layer MOUSE, //Mouse Layer MIDI, //Midi Layer @@ -13,12 +13,12 @@ enum keyboard_layers { // Midi Chords enum midi_chord_modes { //ACTION_FUNCTION id - major = 0, + major, minor, }; enum midi_chord_root { //ACTION_FUNCTION opt - C = 0, + C, Cs, Db = Cs, D, @@ -41,43 +41,43 @@ enum midi_chord_keycodes { //Major Chords - MI_CH_C = ACTION_FUNCTION(0, 0), - MI_CH_Cs = ACTION_FUNCTION(0, 1), + MI_CH_C = ACTION_FUNCTION_OPT(major,C), + MI_CH_Cs = ACTION_FUNCTION_OPT(major,Cs), MI_CH_Db = MI_CH_Cs, - MI_CH_D = ACTION_FUNCTION(0, 2), - MI_CH_Ds = ACTION_FUNCTION(0, 3), + MI_CH_D = ACTION_FUNCTION_OPT(major,D), + MI_CH_Ds = ACTION_FUNCTION_OPT(major,Ds), MI_CH_Eb = MI_CH_Ds, - MI_CH_E = ACTION_FUNCTION(0, 4), - MI_CH_F = ACTION_FUNCTION(0, 5), - MI_CH_Fs = ACTION_FUNCTION(0, 6), + MI_CH_E = ACTION_FUNCTION_OPT(major,E), + MI_CH_F = ACTION_FUNCTION_OPT(major,F), + MI_CH_Fs = ACTION_FUNCTION_OPT(major,Fs), MI_CH_Gb = MI_CH_Fs, - MI_CH_G = ACTION_FUNCTION(0, 7), - MI_CH_Gs = ACTION_FUNCTION(0, 8), + MI_CH_G = ACTION_FUNCTION_OPT(major,G), + MI_CH_Gs = ACTION_FUNCTION_OPT(major,Gs), MI_CH_Ab = MI_CH_Gs, - MI_CH_A = ACTION_FUNCTION(0, 9), - MI_CH_As = ACTION_FUNCTION(0, 10), + MI_CH_A = ACTION_FUNCTION_OPT(major,A), + MI_CH_As = ACTION_FUNCTION_OPT(major,As), MI_CH_Bb = MI_CH_As, - MI_CH_B = ACTION_FUNCTION(0, 11), + MI_CH_B = ACTION_FUNCTION_OPT(major,B), //Minor Chords - MI_CH_Cm = ACTION_FUNCTION(1, 0), - MI_CH_Csm = ACTION_FUNCTION(1, 1), + MI_CH_Cm = ACTION_FUNCTION_OPT(minor,C), + MI_CH_Csm = ACTION_FUNCTION_OPT(minor,Cs), MI_CH_Dbm = MI_CH_Csm, - MI_CH_Dm = ACTION_FUNCTION(1, 2), - MI_CH_Dsm = ACTION_FUNCTION(1, 3), + MI_CH_Dm = ACTION_FUNCTION_OPT(minor,D), + MI_CH_Dsm = ACTION_FUNCTION_OPT(minor,Ds), MI_CH_Ebm = MI_CH_Dsm, - MI_CH_Em = ACTION_FUNCTION(1, 4), - MI_CH_Fm = ACTION_FUNCTION(1, 5), - MI_CH_Fsm = ACTION_FUNCTION(1, 6), + MI_CH_Em = ACTION_FUNCTION_OPT(minor,E), + MI_CH_Fm = ACTION_FUNCTION_OPT(minor,F), + MI_CH_Fsm = ACTION_FUNCTION_OPT(minor,Fs), MI_CH_Gbm = MI_CH_Fsm, - MI_CH_Gm = ACTION_FUNCTION(1, 7), - MI_CH_Gsm= ACTION_FUNCTION(1, 8), + MI_CH_Gm = ACTION_FUNCTION_OPT(minor,G), + MI_CH_Gsm= ACTION_FUNCTION_OPT(minor,Gs), MI_CH_Abm = MI_CH_Gsm, - MI_CH_Am = ACTION_FUNCTION(1, 9), - MI_CH_Asm = ACTION_FUNCTION(1, 10), + MI_CH_Am = ACTION_FUNCTION_OPT(minor,A), + MI_CH_Asm = ACTION_FUNCTION_OPT(minor,As), MI_CH_Bbm = MI_CH_Asm, - MI_CH_Bm = ACTION_FUNCTION(1, 11), + MI_CH_Bm = ACTION_FUNCTION_OPT(minor,B), }; //Morse Code Macro Keys @@ -166,11 +166,11 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { KC_LSPO, KC_NO, KC_SCLN, KC_Q, KC_J, KC_K, KC_X, KC_B, KC_M, KC_W, KC_V, KC_Z, KC_NO, KC_RSPC, KC_NO, \ MO(2), KC_LGUI, KC_LALT, LT(1, KC_SPACE), ALGR_T(KC_APP), KC_RGUI, OSM(MOD_LCTL | MOD_LSFT), OSM(MOD_LCTL | MOD_LALT) ), - + /* 1: Arrow/FN Layer ┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐ - │TG(3)│ F1 │ F2 │ F3 │ F4 │ F5 │ F6 │ F7 │ F8 │ F9 │ F10 │ F11 │ F12 │ │ │ + │ │ F1 │ F2 │ F3 │ F4 │ F5 │ F6 │ F7 │ F8 │ F9 │ F10 │ F11 │ F12 │TO(3)│TO(4)│ ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ │CAPS │ │ │ │ │ │ │PGUP │ UP │HOME │ END │ │ INS │ DEL │█████│ ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ @@ -183,17 +183,17 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { */ [ARROWFN] = KEYMAP( - TG(3), KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_NO, KC_NO, \ - KC_CAPS, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_PGUP, KC_UP, KC_HOME, KC_END, KC_NO, KC_INS, KC_DEL, \ - KC_TRNS, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_LEFT, KC_DOWN, KC_RIGHT, KC_NO, KC_NO, KC_NO, KC_TRNS, \ - KC_TRNS, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_SPACE, KC_PGDN, KC_PSCR, KC_SLCK, KC_PAUS, KC_NO, KC_TRNS, KC_NO, \ - KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS - ), + KC_NO, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, TO(3), TO(4), \ + KC_CAPS, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_PGUP, KC_UP, KC_HOME, KC_END, KC_NO, KC_INS, KC_DEL, \ + KC_TRNS, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_LEFT, KC_DOWN, KC_RIGHT, KC_NO, KC_NO, KC_NO, KC_TRNS, \ + KC_TRNS, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_SPACE, KC_PGDN, KC_PSCR, KC_SLCK, KC_PAUS, KC_NO, KC_TRNS, KC_NO, \ + KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS + ), /* 2: Mouse Keys Layer ┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐ - │RESET│ F1 │ F2 │ F3 │ F4 │ F5 │ F6 │ F7 │ F8 │ F9 │ F10 │ │ │ │ │ + │RESET│ F1 │ F2 │ F3 │ F4 │ F5 │ F6 │ F7 │ F8 │ F9 │ F10 │ F11 │ F12 │ │ │ ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ │ │ │ │ │ │ │ │BTN1 │MS_UP│BTN2 │WH_UP│ │ │ │█████│ ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ @@ -217,7 +217,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { /* 3: Midi Layer ┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐ - │TG(0)│ Cmaj│ Gmaj│ Dmaj│ Amaj│ Emaj│ Bmaj│Gbmaj│Dbmaj│Abmaj│Ebmaj│Bbmaj│ Fmaj│ │ │ + │TO(0)│ Cmaj│ Gmaj│ Dmaj│ Amaj│ Emaj│ Bmaj│Gbmaj│Dbmaj│Abmaj│Ebmaj│Bbmaj│ Fmaj│ │ │ ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ │ │ │ C# │ D# │ │ F# │ G# │ A# │ │ C# │ D# │ │ │ │█████│ ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ @@ -240,7 +240,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { /* 4: Morse Code Layer ┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐ - │ │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ │ │ │ │ + │TO(0)│ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ │ │ │ │ ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ │ │ ' │ , │ . │ P │ Y │ F │ G │ C │ R │ L │ / │ = │BSPC │█████│ ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ @@ -253,19 +253,18 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { */ [MORSE] = KEYMAP( - KC_NO, MC_1, MC_2, MC_3, MC_4, MC_5, MC_6, MC_7, MC_8, MC_9, MC_0, KC_NO, KC_NO, KC_NO, KC_NO, \ - KC_NO, MC_APOS, MC_COMM, MC_DOT, MC_P, MC_Y, MC_F, MC_G, MC_C, MC_R, MC_L, MC_SLSH, MC_EQL, KC_BSPC, \ - KC_NO, MC_A, MC_O, MC_E, MC_U, MC_I, MC_D, MC_H, MC_T, MC_N, MC_S, MC_MINS, KC_NO, KC_ENT, \ - KC_LSFT, KC_NO, MC_SCLN, MC_Q, MC_J, MC_K, MC_X, MC_B, MC_M, MC_W, MC_V, MC_Z, KC_NO, KC_RSFT, KC_NO, \ - KC_NO, KC_NO, KC_NO, MC_SPACE, KC_NO, KC_NO, KC_NO, KC_NO - ), + TO(0), MC_1, MC_2, MC_3, MC_4, MC_5, MC_6, MC_7, MC_8, MC_9, MC_0, KC_NO, KC_NO, KC_NO, KC_NO, \ + KC_TAB, MC_APOS, MC_COMM, MC_DOT, MC_P, MC_Y, MC_F, MC_G, MC_C, MC_R, MC_L, MC_SLSH, MC_EQL, KC_BSPC, \ + KC_NO, MC_A, MC_O, MC_E, MC_U, MC_I, MC_D, MC_H, MC_T, MC_N, MC_S, MC_MINS, KC_NO, KC_ENT, \ + KC_LSFT, KC_NO, MC_SCLN, MC_Q, MC_J, MC_K, MC_X, MC_B, MC_M, MC_W, MC_V, MC_Z, KC_NO, KC_RSFT, KC_NO, \ + KC_NO, KC_NO, KC_NO, MC_SPACE, KC_NO, KC_NO, KC_NO, KC_NO + ), }; // Morse Code Macros -const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) -{ +const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { switch(id) { case 0: //Number 0 if (record->event.pressed) { @@ -319,131 +318,209 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) break; case 10: //Letter A if (record->event.pressed) { + if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + } return MACRO(T(DOT), T(MINS), T(SPACE), END); //.- } break; case 11: //Letter B if (record->event.pressed) { + if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + } return MACRO(T(MINS), T(DOT), T(DOT), T(DOT), T(SPACE), END); //-... } break; case 12: //Letter C if (record->event.pressed) { + if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + } return MACRO(T(MINS), T(DOT), T(MINS), T(DOT), T(SPACE), END); //-.-. } break; case 13: //Letter D if (record->event.pressed) { + if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + } return MACRO(T(MINS), T(DOT), T(DOT), T(SPACE), END); //-.. } break; case 14: //Letter E if (record->event.pressed) { + if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + } return MACRO(T(DOT), T(SPACE), END); //. } break; case 15: //Letter F if (record->event.pressed) { + if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + } return MACRO(T(DOT), T(DOT), T(MINS), T(DOT), T(SPACE), END); //..-. } break; case 16: //Letter G if (record->event.pressed) { + if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + } return MACRO(T(MINS), T(MINS), T(DOT), T(SPACE), END); //--. } break; case 17: //Letter H - if (record->event.pressed) { - return MACRO(T(DOT), T(DOT), T(DOT), T(DOT), T(SPACE), END); //.... + if (record->event.pressed) { + if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); } + return MACRO(T(DOT), T(DOT), T(DOT), T(DOT), T(SPACE), END); //.... + } break; case 18: //Letter I if (record->event.pressed) { + if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + } return MACRO(T(DOT), T(DOT), T(SPACE), END); //.. } break; case 19: //Letter J if (record->event.pressed) { + if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + } return MACRO(T(DOT), T(MINS), T(MINS), T(MINS), T(SPACE), END); //.--- } break; case 20: //Letter K if (record->event.pressed) { + if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + } return MACRO(T(MINS), T(DOT), T(MINS), T(SPACE), END); //-.- } break; case 21: //Letter L if (record->event.pressed) { + if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + } return MACRO(T(DOT), T(MINS), T(DOT), T(DOT), T(SPACE), END); //.-.. } break; case 22: //Letter M if (record->event.pressed) { + if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + } return MACRO(T(MINS), T(MINS), T(SPACE), END); //-- } break; case 23: //Letter N if (record->event.pressed) { + if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + } return MACRO(T(MINS), T(DOT), T(SPACE), END); //-. } break; case 24: //Letter O if (record->event.pressed) { + if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + } return MACRO(T(MINS), T(MINS), T(MINS), T(SPACE), END); //--- } break; case 25: //Letter P if (record->event.pressed) { + if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + } return MACRO(T(DOT), T(MINS), T(MINS), T(DOT), T(SPACE), END); //.--. } break; case 26: //Letter Q if (record->event.pressed) { + if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + } return MACRO(T(MINS), T(MINS), T(DOT), T(MINS), T(SPACE), END); //--.- } break; case 27: //Letter R if (record->event.pressed) { + if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + } return MACRO(T(DOT), T(MINS), T(DOT), T(SPACE), END); //.-. } break; case 28: //Letter S if (record->event.pressed) { + if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + } return MACRO(T(DOT), T(DOT), T(DOT), T(SPACE), END); //... } break; case 29: //Letter T if (record->event.pressed) { + if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + } return MACRO(T(MINS), T(SPACE), END); //- } break; case 30: //Letter U if (record->event.pressed) { + if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + } return MACRO(T(DOT), T(DOT), T(MINS), T(SPACE), END); //..- } break; case 31: //Letter V if (record->event.pressed) { + if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + } return MACRO(T(DOT), T(DOT), T(DOT), T(MINS), T(SPACE), END); //...- } break; case 32: //Letter W if (record->event.pressed) { + if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + } return MACRO(T(DOT), T(MINS), T(MINS), T(SPACE), END); //.-- } break; case 33: //Letter X if (record->event.pressed) { + if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + } return MACRO(T(MINS), T(DOT), T(DOT), T(MINS), T(SPACE), END); //-..- } break; case 34: //Letter Y if (record->event.pressed) { + if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + } return MACRO(T(MINS), T(DOT), T(MINS), T(MINS), T(SPACE), END); //-.-- } break; case 35: //Letter Z if (record->event.pressed) { + if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + } return MACRO(T(MINS), T(MINS), T(DOT), T(DOT), T(SPACE), END); //--.. } break; @@ -535,6 +612,8 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) case 53: //Punctuation _ if (record->event.pressed) { return MACRO(T(DOT), T(DOT), T(MINS), T(MINS), T(DOT), T(MINS), T(SPACE), END); //..--.- + } + break; case 54: //Morse Space if (record->event.pressed) { return MACRO(T(BSLS), T(SPACE), END); //When pressed, this sends a slash followed by a space, making it easier to distinguish words in Morse @@ -547,60 +626,71 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) /* // Midi Chord Function - switch (mode) { - case 0: - uint8_t channel = midi_config.channel; - uint8_t tone = root - MIDI_TONE_MIN; - uint8_t velocity = compute_velocity(midi_config.velocity); - if (record->event.pressed) { - uint8_t root_note = midi_compute_note(root); - uint8_t major_third = midi_compute_note(root) + 4; - uint8_t fifth = midi_compute_note(root) + 7; - midi_send_noteon(&midi_device, channel, root_note, velocity); - midi_send_noteon(&midi_device, channel, major_third, velocity); - midi_send_noteon(&midi_device, channel, fifth, velocity); - tone_status[tone] = root_note; - } - else { - uint8_t root_note = tone_status[tone]; - uint8_t major_third = root_note + 4; - uint8_t fifth = root_note + 7; - if (root_note != MIDI_INVALID_NOTE) - { - midi_send_noteoff(&midi_device, channel, root_note, velocity); - midi_send_noteoff(&midi_device, channel, major_third, velocity); - midi_send_noteoff(&midi_device, channel, fifth, velocity); - } - tone_status[tone] = MIDI_INVALID_NOTE; - } - return false; - case 1: - uint8_t channel = midi_config.channel; - uint8_t tone = root - MIDI_TONE_MIN; - uint8_t velocity = compute_velocity(midi_config.velocity); - if (record->event.pressed) { - uint8_t root_note = midi_compute_note(root); - uint8_t minor_third = midi_compute_note(root) + 3; - uint8_t fifth = midi_compute_note(root) + 7; - midi_send_noteon(&midi_device, channel, root_note, velocity); - midi_send_noteon(&midi_device, channel, minor_third, velocity); - midi_send_noteon(&midi_device, channel, fifth, velocity); - tone_status[tone] = root_note; - } - else { - uint8_t root_note = tone_status[tone]; - uint8_t minor_third = root_note + 3; - uint8_t fifth = root_note + 7; - if (root_note != MIDI_INVALID_NOTE) - { - midi_send_noteoff(&midi_device, channel, root_note, velocity); - midi_send_noteoff(&midi_device, channel, minor_third, velocity); - midi_send_noteoff(&midi_device, channel, fifth, velocity); - } - tone_status[tone] = MIDI_INVALID_NOTE; - } - return false; - }; - return true; +void action_function(keyrecord_t *record, uint8_t id, uint8_t opt) { +uint16_t root_note; +uint8_t channel = midi_config.channel; +uint8_t velocity = compute_velocity(midi_config.velocity); +switch (opt) { +case 0: //Root note C +root_note = MI_C; +case 1: //Root note C#/Db +root_note = MI_Cs; +case 2: // Root note D +root_note = MI_D; +case 3: // Root note D#/Eb +root_note = MI_Ds; +case 4: // Root note E +root_note = MI_E; +case 5: // Root note F +root_note = MI_F; +case 6: // Root note F#/Gb +root_note = MI_Fs; +case 7: // Root note G +root_note = MI_G; +case 8: // Root note G#/Ab +root_note = MI_Gs; +case 9: // Root note A +root_note = MI_A; +case 10: // Root note A#/Bb +root_note = MI_As; +case 11: // Root note B +root_note = MI_B; +switch (id) { +uint8_t tone = root_note - MIDI_TONE_MIN; +uint8_t root = midi_compute_note(root_note); +uint8_t major_third = midi_compute_note(root_note) + 4; +uint8_t minor_third = midi_compute_note(root_note) + 3; +uint8_t fifth = midi_compute_note(root_note) + 7; +case 0: //Major chord +if (record->event.pressed) { +midi_send_noteon(&midi_device, channel, root, velocity); +midi_send_noteon(&midi_device, channel, major_third, velocity); +midi_send_noteon(&midi_device, channel, fifth, velocity); +tone_status[tone] = root; +} +else { +uint8_t root = tone_status[tone]; +if (root != MIDI_INVALID_NOTE) +{ +midi_send_noteoff(&midi_device, channel, root, velocity); +} +tone_status[tone] = MIDI_INVALID_NOTE; +} +case 1: //Minor chord +if (record->event.pressed) { +midi_send_noteon(&midi_device, channel, root_note, velocity); +midi_send_noteon(&midi_device, channel, minor_third, velocity); +midi_send_noteon(&midi_device, channel, fifth, velocity); +} +else { +uint8_t root = tone_status[tone]; +if (root != MIDI_INVALID_NOTE) +{ +midi_send_noteoff(&midi_device, channel, root, velocity); +} +tone_status[tone] = MIDI_INVALID_NOTE; +} +} +} }; */ From 4d783d0e69444a660c53c95e83bf6ca011bc6c8e Mon Sep 17 00:00:00 2001 From: Ante Laurijssen Date: Mon, 22 May 2017 23:30:25 -0400 Subject: [PATCH 039/238] More work on my keymap.c and added .png images of my different layers. --- .../bluebear/S60X-Bluebear-ARROWFN-Layer.png | Bin 0 -> 17938 bytes .../bluebear/S60X-Bluebear-BASE-Layer.png | Bin 0 -> 28068 bytes .../bluebear/S60X-Bluebear-MIDI-Layer.png | Bin 0 -> 21329 bytes .../bluebear/S60X-Bluebear-MORSE-Layer.png | Bin 0 -> 14330 bytes .../bluebear/S60X-Bluebear-MOUSE-Layer.png | Bin 0 -> 16119 bytes keyboards/s60_x/keymaps/bluebear/keymap.c | 219 ++++++++++-------- 6 files changed, 120 insertions(+), 99 deletions(-) create mode 100644 keyboards/s60_x/keymaps/bluebear/S60X-Bluebear-ARROWFN-Layer.png create mode 100644 keyboards/s60_x/keymaps/bluebear/S60X-Bluebear-BASE-Layer.png create mode 100644 keyboards/s60_x/keymaps/bluebear/S60X-Bluebear-MIDI-Layer.png create mode 100644 keyboards/s60_x/keymaps/bluebear/S60X-Bluebear-MORSE-Layer.png create mode 100644 keyboards/s60_x/keymaps/bluebear/S60X-Bluebear-MOUSE-Layer.png diff --git a/keyboards/s60_x/keymaps/bluebear/S60X-Bluebear-ARROWFN-Layer.png b/keyboards/s60_x/keymaps/bluebear/S60X-Bluebear-ARROWFN-Layer.png new file mode 100644 index 0000000000000000000000000000000000000000..a7c6df504412616e24c67efae9d5b18e5097d222 GIT binary patch literal 17938 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 literal 0 HcmV?d00001 diff --git a/keyboards/s60_x/keymaps/bluebear/S60X-Bluebear-BASE-Layer.png b/keyboards/s60_x/keymaps/bluebear/S60X-Bluebear-BASE-Layer.png new file mode 100644 index 0000000000000000000000000000000000000000..e77287a0f145f18a6ce5425cfbfc60d470c0092b GIT binary patch literal 28068 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 CJ-;#l literal 0 HcmV?d00001 diff --git a/keyboards/s60_x/keymaps/bluebear/S60X-Bluebear-MIDI-Layer.png b/keyboards/s60_x/keymaps/bluebear/S60X-Bluebear-MIDI-Layer.png new file mode 100644 index 0000000000000000000000000000000000000000..c8df0a9e9e7c0ae12beeb972a4c3ad0adec9c420 GIT binary patch literal 21329 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 AqyPW_ literal 0 HcmV?d00001 diff --git a/keyboards/s60_x/keymaps/bluebear/S60X-Bluebear-MORSE-Layer.png b/keyboards/s60_x/keymaps/bluebear/S60X-Bluebear-MORSE-Layer.png new file mode 100644 index 0000000000000000000000000000000000000000..0e72d103263d0b2aa83a06682ca5e11dec96bc78 GIT binary patch literal 14330 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 u>d&Jn4b9oN)CNu|BJ9A1!A^F6Wd;bH2BSuXC literal 0 HcmV?d00001 diff --git a/keyboards/s60_x/keymaps/bluebear/keymap.c b/keyboards/s60_x/keymaps/bluebear/keymap.c index d383d2e28..32a65a593 100644 --- a/keyboards/s60_x/keymaps/bluebear/keymap.c +++ b/keyboards/s60_x/keymaps/bluebear/keymap.c @@ -121,23 +121,12 @@ enum morse_macros { MC_Z = M(35), MC_DOT = M(36), MC_COMM = M(37), - MC_QUES = M(38), - MC_APOS = M(39), - MC_EXCL = M(40), - MC_SLSH = M(41), - MC_PARO = M(42), - MC_PARC = M(43), - MC_AMP = M(44), - MC_COL = M(45), - MC_SCLN = M(46), - MC_EQL = M(47), - MC_PLUS = M(48), - MC_MINS = M(49), - MC_QUOT = M(50), - MC_DOLR = M(51), - MC_AT = M(52), - MC_UNDS = M(53), - MC_SPACE = M(54), + MC_APOS = M(38), + MC_SLSH = M(39), + MC_SCLN = M(40), + MC_EQL = M(41), + MC_MINS = M(42), + MC_SPACE = M(43), }; //Keymaps @@ -183,11 +172,11 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { */ [ARROWFN] = KEYMAP( - KC_NO, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, TO(3), TO(4), \ + KC_TRNS, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, TO(3), TO(4), \ KC_CAPS, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_PGUP, KC_UP, KC_HOME, KC_END, KC_NO, KC_INS, KC_DEL, \ - KC_TRNS, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_LEFT, KC_DOWN, KC_RIGHT, KC_NO, KC_NO, KC_NO, KC_TRNS, \ - KC_TRNS, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_SPACE, KC_PGDN, KC_PSCR, KC_SLCK, KC_PAUS, KC_NO, KC_TRNS, KC_NO, \ - KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_LEFT, KC_DOWN, KC_RIGHT, KC_NO, KC_NO, KC_NO, KC_TRNS, \ + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_SPACE, KC_PGDN, KC_PSCR, KC_SLCK, KC_PAUS, KC_NO, KC_NO, KC_NO, \ + KC_NO, KC_NO, KC_NO, KC_TRNS, KC_NO, KC_NO, KC_NO, KC_TRNS ), /* 2: Mouse Keys Layer @@ -266,54 +255,102 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { switch(id) { - case 0: //Number 0 + case 0: //Number 0-) if (record->event.pressed) { - return MACRO(T(MINS), T(MINS), T(MINS), T(MINS), T(MINS), T(SPACE), END); //----- + if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + return MACRO(T(MINS), T(DOT), T(MINS), T(MINS), T(DOT), T(MINS), T(SPACE), END); //-.--.- + } + else { + return MACRO(T(MINS), T(MINS), T(MINS), T(MINS), T(MINS), T(SPACE), END); //----- + } } break; - case 1: //Number 1 + case 1: //Number 1-! if (record->event.pressed) { - return MACRO(T(DOT), T(MINS), T(MINS), T(MINS), T(MINS), T(SPACE), END); //.---- + if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + return MACRO(T(MINS), T(DOT), T(MINS), T(DOT), T(MINS), T(MINS), T(SPACE), END); //-.-.-- + } + else { + return MACRO(T(DOT), T(MINS), T(MINS), T(MINS), T(MINS), T(SPACE), END); //.---- + } } break; - case 2: //Number 2 + case 2: //Number 2-@ if (record->event.pressed) { - return MACRO(T(DOT), T(DOT), T(MINS), T(MINS), T(MINS), T(SPACE), END); //..--- + if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + return MACRO(T(DOT), T(MINS), T(MINS), T(DOT), T(MINS), T(DOT), T(SPACE), END); //.--.-. + } + else { + return MACRO(T(DOT), T(DOT), T(MINS), T(MINS), T(MINS), T(SPACE), END); //..--- + } } break; case 3: // Number 3 if (record->event.pressed) { + if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + } return MACRO(T(DOT), T(DOT), T(DOT), T(MINS), T(MINS), T(SPACE), END); //...-- } break; - case 4: //Number 4 + case 4: //Number 4-$ if (record->event.pressed) { - return MACRO(T(DOT), T(DOT), T(DOT), T(DOT), T(MINS), T(SPACE), END); //....- + if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + return MACRO(T(DOT), T(DOT), T(DOT), T(MINS), T(DOT), T(DOT), T(MINS), T(SPACE), END); //...-..- + } + else { + return MACRO(T(DOT), T(DOT), T(DOT), T(DOT), T(MINS), T(SPACE), END); //....- + } } break; case 5: //Number 5 if (record->event.pressed) { + if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + } return MACRO(T(DOT), T(DOT), T(DOT), T(DOT), T(DOT), T(SPACE), END); //..... } break; case 6: //Number 6 if (record->event.pressed) { + if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + } return MACRO(T(MINS), T(DOT), T(DOT), T(DOT), T(DOT), T(SPACE), END); //-.... } break; - case 7: //Number 7 + case 7: //Number 7-& if (record->event.pressed) { - return MACRO(T(MINS), T(MINS), T(DOT), T(DOT), T(DOT), T(SPACE), END); //--... + if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + return MACRO(T(DOT), T(MINS), T(DOT), T(DOT), T(DOT), T(SPACE), END); //.-... + } + else { + return MACRO(T(MINS), T(MINS), T(DOT), T(DOT), T(DOT), T(SPACE), END); //--... + } } break; case 8: //Number 8 if (record->event.pressed) { + if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + } return MACRO(T(MINS), T(MINS), T(MINS), T(DOT), T(DOT), T(SPACE), END); //---.. } break; - case 9: //Number 9 + case 9: //Number 9-( if (record->event.pressed) { - return MACRO(T(MINS), T(MINS), T(MINS), T(MINS), T(DOT), T(SPACE), END); //----. + if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + return MACRO(T(MINS), T(DOT), T(MINS), T(MINS), T(DOT), T(SPACE), END); //-.--. + } + else { + return MACRO(T(MINS), T(MINS), T(MINS), T(MINS), T(DOT), T(SPACE), END); //----. + } } break; case 10: //Letter A @@ -526,96 +563,80 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { break; case 36: //Punctuation . if (record->event.pressed) { + if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + } return MACRO(T(DOT), T(MINS), T(DOT), T(MINS), T(DOT), T(MINS), T(SPACE), END); //.-.-.- } break; case 37: //Punctuation , if (record->event.pressed) { + if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + } return MACRO(T(MINS), T(MINS), T(DOT), T(DOT), T(MINS), T(MINS), T(SPACE), END); //--..-- } break; - case 38: //Punctuation ? + case 38: //Punctuation '-" if (record->event.pressed) { - return MACRO(T(DOT), T(DOT), T(MINS), T(MINS), T(DOT), T(DOT), T(SPACE), END); //..--.. + if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + return MACRO(T(DOT), T(MINS), T(DOT), T(DOT), T(MINS), T(DOT), T(SPACE), END); //.-..-. + } + else { + return MACRO(T(DOT), T(MINS), T(MINS), T(MINS), T(MINS), T(DOT), T(SPACE), END); //-....- + } } break; - case 39: //Punctuation ' + case 39: //Punctuation /-? if (record->event.pressed) { - return MACRO(T(DOT), T(MINS), T(MINS), T(MINS), T(MINS), T(DOT), T(SPACE), END); //-....- + if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + return MACRO(T(DOT), T(DOT), T(MINS), T(MINS), T(DOT), T(DOT), T(SPACE), END); //..--.. + } + else { + return MACRO(T(MINS), T(DOT), T(DOT), T(MINS), T(DOT), T(SPACE), END); //-..-. + } } break; - case 40: //Punctuation ! + case 40: //Punctuation ;-: if (record->event.pressed) { - return MACRO(T(MINS), T(DOT), T(MINS), T(DOT), T(MINS), T(MINS), T(SPACE), END); //-.-.-- + if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + return MACRO(T(MINS), T(MINS), T(MINS), T(DOT), T(DOT), T(DOT), T(SPACE), END); //---... + } + else { + return MACRO(T(MINS), T(DOT), T(MINS), T(DOT), T(MINS), T(DOT), T(SPACE), END); //-.-.-. + } } break; - case 41: //Punctuation / + case 41: //Punctuation =-+ if (record->event.pressed) { - return MACRO(T(MINS), T(DOT), T(DOT), T(MINS), T(DOT), T(SPACE), END); //-..-. + if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + return MACRO(T(DOT), T(MINS), T(DOT), T(MINS), T(DOT), T(SPACE), END); //.-.-. + } + else { + return MACRO(T(MINS), T(DOT), T(DOT), T(DOT), T(MINS), T(SPACE), END); //-...- + } } break; - case 42: //Punctuation ( + case 42: //Punctuation --_ if (record->event.pressed) { - return MACRO(T(MINS), T(DOT), T(MINS), T(MINS), T(DOT), T(SPACE), END); //-.--. + if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + return MACRO(T(DOT), T(DOT), T(MINS), T(MINS), T(DOT), T(MINS), T(SPACE), END); //..--.- + } + else { + return MACRO(T(MINS), T(DOT), T(DOT), T(DOT), T(DOT), T(MINS), T(SPACE), END); //-....- + } } break; - case 43: //Punctuation ) - if (record->event.pressed) { - return MACRO(T(MINS), T(DOT), T(MINS), T(MINS), T(DOT), T(MINS), T(SPACE), END); //-.--.- - } - break; - case 44: //Punctuation & - if (record->event.pressed) { - return MACRO(T(DOT), T(MINS), T(DOT), T(DOT), T(DOT), T(SPACE), END); //.-... - } - break; - case 45: //Punctuation : - if (record->event.pressed) { - return MACRO(T(MINS), T(MINS), T(MINS), T(DOT), T(DOT), T(DOT), T(SPACE), END); //---... - } - break; - case 46: //Punctuation ; - if (record->event.pressed) { - return MACRO(T(MINS), T(DOT), T(MINS), T(DOT), T(MINS), T(DOT), T(SPACE), END); //-.-.-. - } - break; - case 47: //Punctuation = - if (record->event.pressed) { - return MACRO(T(MINS), T(DOT), T(DOT), T(DOT), T(MINS), T(SPACE), END); //-...- - } - break; - case 48: //Punctuation + - if (record->event.pressed) { - return MACRO(T(DOT), T(MINS), T(DOT), T(MINS), T(DOT), T(SPACE), END); //.-.-. - } - break; - case 49: //Punctuation - - if (record->event.pressed) { - return MACRO(T(MINS), T(DOT), T(DOT), T(DOT), T(DOT), T(MINS), T(SPACE), END); //-....- - } - break; - case 50: //Punctuation " - if (record->event.pressed) { - return MACRO(T(DOT), T(MINS), T(DOT), T(DOT), T(MINS), T(DOT), T(SPACE), END); //.-..-. - } - break; - case 51: //Punctuation $ - if (record->event.pressed) { - return MACRO(T(DOT), T(DOT), T(DOT), T(MINS), T(DOT), T(DOT), T(MINS), T(SPACE), END); //...-..- - } - break; - case 52: //Punctuation @ - if (record->event.pressed) { - return MACRO(T(DOT), T(MINS), T(MINS), T(DOT), T(MINS), T(DOT), T(SPACE), END); //.--.-. - } - break; - case 53: //Punctuation _ - if (record->event.pressed) { - return MACRO(T(DOT), T(DOT), T(MINS), T(MINS), T(DOT), T(MINS), T(SPACE), END); //..--.- - } - break; - case 54: //Morse Space + case 43: //Morse Space if (record->event.pressed) { + if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + } return MACRO(T(BSLS), T(SPACE), END); //When pressed, this sends a slash followed by a space, making it easier to distinguish words in Morse } break; From f54b4771eb23027be1bd66a6fe1300713b593d58 Mon Sep 17 00:00:00 2001 From: jpetermans Date: Wed, 24 May 2017 11:20:50 -0700 Subject: [PATCH 040/238] keymap example update and tweak to set_led_bit function --- .../infinity60/keymaps/jpetermans/keymap.c | 6 ++--- .../infinity60/keymaps/jpetermans/readme.md | 12 ++++----- keyboards/infinity60/led_controller.c | 27 +++++++++---------- 3 files changed, 21 insertions(+), 24 deletions(-) diff --git a/keyboards/infinity60/keymaps/jpetermans/keymap.c b/keyboards/infinity60/keymaps/jpetermans/keymap.c index 8d19834b2..cc4633b1b 100644 --- a/keyboards/infinity60/keymaps/jpetermans/keymap.c +++ b/keyboards/infinity60/keymaps/jpetermans/keymap.c @@ -59,7 +59,7 @@ const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS] = { KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC,KC_RBRC,KC_BSPC, \ TT(_FNAV), KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN,KC_QUOT,KC_ENT, \ KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM,KC_DOT, KC_SLSH,F(TILDE),KC_NO, \ - KC_LCTL, KC_LGUI,KC_LALT, KC_SPC, KC_RALT,TG(_NUMPAD),MO(_MEDIA), KC_RCTL \ + KC_LCTL, KC_LGUI,KC_LALT, LT(_FNAV, KC_SPC), KC_RALT,TG(_NUMPAD),MO(_MEDIA), KC_RCTL \ ), /* numpad */ @@ -68,7 +68,7 @@ const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS] = { _______,_______,_______,_______,_______,_______,_______, KC_P4, KC_P5, KC_P6, KC_PAST, _______,_______,_______, \ MO(_FNAV),_______,_______,_______,_______,_______,_______, KC_P1, KC_P2, KC_P3, KC_PMNS, _______,_______, \ _______,_______,_______,_______,_______,_______,_______, KC_P0,KC_COMM,KC_PDOT,KC_PPLS, _______,KC_NO, \ - _______,_______,_______, MO(_BASE), _______,_______,_______,_______ \ + _______,_______,_______, TO(_BASE), _______,_______,_______,_______ \ ), /* F-, arrow, and media keys */ @@ -290,7 +290,7 @@ void matrix_scan_user(void) { led_pin_byte = layer_state & 0xFF; msg=(7 << 8) | DISPLAY_PAGE; chMBPost(&led_mailbox, msg, TIME_IMMEDIATE); - msg=(1<<16) | (led_pin_byte << 8) | SET_FULL_ROW; + msg=(1 << 16) | (led_pin_byte << 8) | SET_FULL_ROW; chMBPost(&led_mailbox, msg, TIME_IMMEDIATE); break; diff --git a/keyboards/infinity60/keymaps/jpetermans/readme.md b/keyboards/infinity60/keymaps/jpetermans/readme.md index 63fd88ec2..b83057ea7 100644 --- a/keyboards/infinity60/keymaps/jpetermans/readme.md +++ b/keyboards/infinity60/keymaps/jpetermans/readme.md @@ -16,9 +16,9 @@ digits mean "row" and "col", i.e. 45 means pin 4, column 5 in the IS31 datasheet ``` *Unused in Alphabet Layout -The IS31 includes 8 pages (or frames) 0-7 and each page consists of 144 bytes +The IS31 includes 8 led pages (or frames) 0-7 than can be displayed, and each page consists of 144 bytes. - **bytes 0 - 17** - LED control (on/off). - * 18 pins which alternate between A and B matrices (CA1, CB1, CA2, CB2, ..). + * 18 pins which alternate between A and B matrices (A1, B1, A2, B2, ..). * Each byte controls the 8 leds on that pin with bits (8 to 1). - **bytes 8 - 35** - Blink control. * Same as LED control above, but sets blink on/off. @@ -31,7 +31,7 @@ In the Infinity60 project folder, led_controller.c sets up ability to write led One function is available to directly set leds without the mailbox: ``` -write_led_page(page#, array of leds by address, # of leds in array) +write_led_page(page#, array of leds by address, # of addresses in array) ``` This function saves a full page to the controller using a supplied array of led locations such as: ```c @@ -45,7 +45,7 @@ write_led_page(5, led_numpad, 16); ``` Remaining led control is done through the led mailbox using these message types: -- **SET_FULL_ROW** (3 bytes) - row#, message type, 8-bit mask. Sets all leds on one pin per the bit mask. +- **SET_FULL_ROW** (3 bytes) - message type, 8-bit mask, and row#. Sets all leds on one pin per the bit mask. - **OFF_LED, ON_LED, TOGGLE_LED** (3 bytes) - message type, led address, and page#. Off/on/toggle specific led. - **BLINK_OFF_LED, BLINK_ON_LED, BLINK_OFF_LED** (3 bytes) - message type, led address, and page#. Set blink Off/on/toggle for specific led. - **TOGGLE_ALL** (1 byte) - Turn on/off full backlight. @@ -68,7 +68,7 @@ chMBPost(&led_mailbox, message, timeout); An example: ```c //set the message to be sent. First byte (LSB) is the led address, and second is the message type -msg=(42 << 8) | ON_LED +msg=(42 << 8) | ON_LED; //send msg to the led mailbox chMBPost(&led_mailbox, msg, TIME_IMMEDIATE); @@ -76,7 +76,7 @@ chMBPost(&led_mailbox, msg, TIME_IMMEDIATE); Another: ```c -msg=(46 << 8) | BLINK_TOGGLE_LED +msg=(46 << 8) | BLINK_TOGGLE_LED; chMBPost(&led_mailbox, msg, TIME_IMMEDIATE); ``` diff --git a/keyboards/infinity60/led_controller.c b/keyboards/infinity60/led_controller.c index a66edb927..04793cc01 100644 --- a/keyboards/infinity60/led_controller.c +++ b/keyboards/infinity60/led_controller.c @@ -25,7 +25,6 @@ along with this program. If not, see . #include "hal.h" #include "print.h" #include "led.h" -#include "action_layer.h" #include "host.h" #include "led_controller.h" @@ -199,31 +198,25 @@ static THD_FUNCTION(LEDthread, arg) { break; case OFF_LED: - //on/off/toggle single led, msg_args[0] = row/col of led + //on/off/toggle single led, msg_args[0] = row/col of led, msg_args[1] = page set_led_bit(msg_args[1], control_register_word, msg_args[0], 0); - is31_write_data (msg_args[1], control_register_word, 0x02); break; case ON_LED: set_led_bit(msg_args[1], control_register_word, msg_args[0], 1); - is31_write_data (msg_args[1], control_register_word, 0x02); break; case TOGGLE_LED: set_led_bit(msg_args[1], control_register_word, msg_args[0], 2); - is31_write_data (msg_args[1], control_register_word, 0x02); break; case BLINK_OFF_LED: //on/off/toggle single led, msg_args[0] = row/col of led set_led_bit(msg_args[1], control_register_word, msg_args[0], 4); - is31_write_data (msg_args[1], control_register_word, 0x02); break; case BLINK_ON_LED: set_led_bit(msg_args[1], control_register_word, msg_args[0], 5); - is31_write_data (msg_args[1], control_register_word, 0x02); break; case BLINK_TOGGLE_LED: set_led_bit(msg_args[1], control_register_word, msg_args[0], 6); - is31_write_data (msg_args[1], control_register_word, 0x02); break; case TOGGLE_ALL: @@ -282,6 +275,10 @@ static THD_FUNCTION(LEDthread, arg) { led_control_reg[0] = 0; __builtin_memset(led_control_reg+1, 0, 0x12); is31_write_data(msg_args[0], led_control_reg, 0x13); + + //repeat for blink register + led_control_reg[0] = 0x12; + is31_write_data(msg_args[0], led_control_reg, 0x13); break; case TOGGLE_NUM_LOCK: @@ -330,7 +327,7 @@ static THD_FUNCTION(LEDthread, arg) { * led processing functions * ============================== */ -void set_led_bit (uint8_t page, uint8_t *led_control_reg, uint8_t led_addr, uint8_t action) { +void set_led_bit (uint8_t page, uint8_t *led_control_word, uint8_t led_addr, uint8_t action) { //returns 2 bytes: led control register address and byte to write //action: 0 - off, 1 - on, 2 - toggle, 4 - blink on, 5 - blink off, 6 - toggle blink @@ -341,11 +338,9 @@ void set_led_bit (uint8_t page, uint8_t *led_control_reg, uint8_t led_addr, uint return; } - //check for blink bit - blink_bit = action>>2; + blink_bit = action>>2;//check for blink bit action &= ~(1<<2); //strip blink bit - //first byte is led control register address 0x00 //led_addr tens column is pin#, ones column is bit position in 8-bit mask control_reg_addr = ((led_addr / 10) % 10 - 1 ) * 0x02;// A-matrix is every other byte control_reg_addr += blink_bit == 1 ? 0x12 : 0x00;//if blink_bit, shift 12 bytes to blink register @@ -367,8 +362,9 @@ void set_led_bit (uint8_t page, uint8_t *led_control_reg, uint8_t led_addr, uint } //return word to be written in register - led_control_reg[0] = control_reg_addr; - led_control_reg[1] = column_byte; + led_control_word[0] = control_reg_addr; + led_control_word[1] = column_byte; + is31_write_data (page, led_control_word, 0x02); } void write_led_byte (uint8_t page, uint8_t row, uint8_t led_byte) { @@ -403,13 +399,14 @@ void set_lock_leds(uint8_t led_addr, uint8_t led_action, uint8_t page) { //blink if all leds are on if (page == 0) { is31_read_register(0, 0x00, &temp); + chThdSleepMilliseconds(10); + if (temp == 0xFF) { led_action |= (1<<2); //set blink bit } } set_led_bit(page,led_control_word,led_addr,led_action); - is31_write_data(page, led_control_word, 0x02); } /* ===================== From 083267680d15b5d03d31c6775b1046063c762e78 Mon Sep 17 00:00:00 2001 From: jpetermans Date: Wed, 24 May 2017 12:26:56 -0700 Subject: [PATCH 041/238] Restore deleted MEMO.txt from master --- keyboards/infinity60/MEMO.txt | 385 ++++++++++++++++++++++++++++++++++ 1 file changed, 385 insertions(+) create mode 100644 keyboards/infinity60/MEMO.txt diff --git a/keyboards/infinity60/MEMO.txt b/keyboards/infinity60/MEMO.txt new file mode 100644 index 000000000..e2886aa00 --- /dev/null +++ b/keyboards/infinity60/MEMO.txt @@ -0,0 +1,385 @@ +flabbergast's TMK/ChibiOS port +============================== +2015/10/16 + + +Build +----- +$ git clone -b chibios https://github.com/flabbergast/tmk_keyboard.git + +$ cd tmk_keyboard +$ git submodule add -f -b kinetis https://github.com/flabbergast/ChibiOS.git tmk_core/tool/chibios/chibios +or +$ cd tmk_keyboard/tmk_core/tool/chibios +$ git clone -b kinetis https://github.com/flabbergast/ChibiOS.git tmk_core/tool/chibios/chibios + +$ cd tmk_keyboard/keyboard/infinity_chibios +$ make + + + + +Chibios Configuration +--------------------- +halconf.h: for HAL configuration + placed in project directory + read in chibios/os/hal/hal.mk + included in chibios/os/hal/include/hal.h +mcuconf.h: for MCU configuration + placed in project directory + included in halconf.h + + +Chibios Term +------------ +PAL = Port Abstraction Layer + palWritePad + palReadPad + palSetPad + chibios/os/hal/include/pal.h + +LLD = Low Level Driver + + +Makefile +-------- + # /os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES) + MCU_FAMILY = KINETIS + MCU_SERIES = KL2x + + # - it should exist either in /os/common/ports/ARMCMx/compilers/GCC/ld/ + # or /ld/ + MCU_LDSCRIPT = MKL26Z64 + + # - it should exist in /os/common/ports/ARMCMx/compilers/GCC/mk/ + MCU_STARTUP = kl2x + + # Board: it should exist either in /os/hal/boards/ + # or /boards + BOARD = PJRC_TEENSY_LC + + MCU = cortex-m0 + + # ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7 + ARMV = 6 + + +halconf.h +--------- + + +mcuconf.h +--------- + + +chconf.h +-------- + + +ld script +--------- +--- ../../tmk_core/tool/chibios/chibios/os/common/ports/ARMCMx/compilers/GCC/ld/MKL26Z64.ld 2015-10-15 09:08:58.732904304 +0900 ++++ ld/MKL26Z64.ld 2015-10-15 08:48:06.430215496 +0900 +@@ -27,7 +27,8 @@ + { + flash0 : org = 0x00000000, len = 0xc0 + flashcfg : org = 0x00000400, len = 0x10 +- flash : org = 0x00000410, len = 64k - 0x410 ++ flash : org = 0x00000410, len = 62k - 0x410 ++ eeprom_emu : org = 0x0000F800, len = 2k + ram : org = 0x1FFFF800, len = 8k + } + +@@ -35,6 +36,10 @@ + __ram_size__ = LENGTH(ram); + __ram_end__ = __ram_start__ + __ram_size__; + ++__eeprom_workarea_start__ = ORIGIN(eeprom_emu); ++__eeprom_workarea_size__ = LENGTH(eeprom_emu); ++__eeprom_workarea_end__ = __eeprom_workarea_start__ + __eeprom_workarea_size__; ++ + SECTIONS + { + . = 0; + + + +Configuration/Startup for Infinity 60% +-------------------------------------- +Configuration: + + +Clock: +Inifinity + FEI(FLL Engaged Internal) mode with core clock:48MHz, bus clock:48MHz, flash clock:24MHz + Clock dividor: + SIM_CLKDIV1[OUTDIV1] = 0 divide-by-1 for core clock + SIM_CLKDIV1[OUTDIV2] = 0 divide-by-1 for bus clock + SIM_CLKDIV1[OUTDIV4] = 1 divide-by-2 for flash clock + Internal reference clock: + MCG_C1[IREFS] = 1 Internal Reference Select for clock source for FLL + MCG_C1[IRCLKEN] = 1 Internal Reference Clock Enable + FLL multipilication: + MCG_C4[DMX32] = 1 + MCG_C4[DRST_DRS] = 01 FLL factor 1464 * 32.768kHz = 48MHz + +chibios/os/hal/ports/KINETIS/K20x/hal_lld.c + k20x_clock_init(): called in __early_init() defined in board.c + disable watchdog and configure clock + + configurable macros: + KINETIS_NO_INIT: whether init or not + KINETIS_MCG_MODE: clock mode + KINETIS_MCG_MODE_FEI + KINETIS_MCG_MODE_PEE + hal/ports/KINETIS/K20x/hal_lld.h + + +chibios/os/hal/boards/FREESCALE_FREEDOM_K20D50M/board.h + PALConfig pal_default_config + boardInit() + __early_init() + macro definitions for board infos, freq and mcu type + +chibios/os/hal/boards/FREESCALE_FREEDOM_K20D50M/board.c + +USB + + +Startup +------- + common/ports/ARMCMx/GCC/crt0_v[67]m.s + Reset_Handler: startup code + common/ports/ARMCMx/GCC/crt1.c + __core_init(): weak + __early_init(): weak + __late_init(): weak + __default_exit(): weak + called from Reset_Handler of crt0 + common/ports/ARMCMx/GCC/vector.c + common/ports/ARMCMx/GCC/ld/*.ld + +chibios/os/common/ports/ARMCMx/compilers/GCC/ +├── crt0_v6m.s +├── crt0_v7m.s +├── crt1.c +├── ld +│   ├── MK20DX128BLDR3.ld +│   ├── MK20DX128BLDR4.ld +│   ├── MK20DX128.ld +│   ├── MK20DX256.ld +│   ├── MKL25Z128.ld +│   ├── MKL26Z128.ld +│   ├── MKL26Z64.ld +│   └── STM32L476xG.ld +├── mk +│   ├── startup_k20x5.mk +│   ├── startup_k20x7.mk +│   ├── startup_k20x.mk +│   ├── startup_kl2x.mk +│   └── startup_stm32l4xx.mk +├── rules.ld +├── rules.mk +└── vectors.c + +chibios/os/hal/ +├── boards +│   ├── FREESCALE_FREEDOM_K20D50M +│   │   ├── board.c +│   │   ├── board.h +│   │   └── board.mk +│   ├── MCHCK_K20 +│   │   ├── board.c +│   │   ├── board.h +│   │   └── board.mk +│   ├── PJRC_TEENSY_3 +│   │   ├── board.c +│   │   ├── board.h +│   │   └── board.mk +│   ├── PJRC_TEENSY_3_1 +│   │   ├── board.c +│   │   ├── board.h +│   │   └── board.mk +│   ├── PJRC_TEENSY_LC +│   │   ├── board.c +│   │   ├── board.h +│   │   └── board.mk +│   ├── readme.txt +│   ├── simulator +│   │   ├── board.c +│   │   ├── board.h +│   │   └── board.mk +│   ├── ST_NUCLEO_F030R8 +│   │   ├── board.c +│   │   ├── board.h +│   │   ├── board.mk +│   │   └── cfg +│   │   └── board.chcfg +├── hal.mk +├── include +│   ├── adc.h +│   ├── can.h +│   ├── dac.h +│   ├── ext.h +│   ├── gpt.h +│   ├── hal_channels.h +│   ├── hal_files.h +│   ├── hal.h +│   ├── hal_ioblock.h +│   ├── hal_mmcsd.h +│   ├── hal_queues.h +│   ├── hal_streams.h +│   ├── i2c.h +│   ├── i2s.h +│   ├── icu.h +│   ├── mac.h +│   ├── mii.h +│   ├── mmc_spi.h +│   ├── pal.h +│   ├── pwm.h +│   ├── rtc.h +│   ├── sdc.h +│   ├── serial.h +│   ├── serial_usb.h +│   ├── spi.h +│   ├── st.h +│   ├── uart.h +│   └── usb.h +├── lib +│   └── streams +│   ├── chprintf.c +│   ├── chprintf.h +│   ├── memstreams.c +│   ├── memstreams.h +│   ├── nullstreams.c +│   └── nullstreams.h +├── osal +│   ├── nil +│   │   ├── osal.c +│   │   ├── osal.h +│   │   └── osal.mk +│   ├── os-less +│   │   └── ARMCMx +│   │   ├── osal.c +│   │   ├── osal.h +│   │   └── osal.mk +│   └── rt +│   ├── osal.c +│   ├── osal.h +│   └── osal.mk +├── ports +│   ├── AVR +│   ├── common +│   │   └── ARMCMx +│   │   ├── mpu.h +│   │   ├── nvic.c +│   │   └── nvic.h +│   ├── KINETIS +│   │   ├── K20x +│   │   │   ├── hal_lld.c +│   │   │   ├── hal_lld.h +│   │   │   ├── kinetis_registry.h +│   │   │   ├── platform.dox +│   │   │   ├── platform.mk +│   │   │   ├── pwm_lld.c +│   │   │   ├── pwm_lld.h +│   │   │   ├── spi_lld.c +│   │   │   └── spi_lld.h +│   │   ├── KL2x +│   │   │   ├── hal_lld.c +│   │   │   ├── hal_lld.h +│   │   │   ├── kinetis_registry.h +│   │   │   ├── platform.mk +│   │   │   ├── pwm_lld.c +│   │   │   └── pwm_lld.h +│   │   ├── LLD +│   │   │   ├── adc_lld.c +│   │   │   ├── adc_lld.h +│   │   │   ├── ext_lld.c +│   │   │   ├── ext_lld.h +│   │   │   ├── gpt_lld.c +│   │   │   ├── gpt_lld.h +│   │   │   ├── i2c_lld.c +│   │   │   ├── i2c_lld.h +│   │   │   ├── pal_lld.c +│   │   │   ├── pal_lld.h +│   │   │   ├── serial_lld.c +│   │   │   ├── serial_lld.h +│   │   │   ├── st_lld.c +│   │   │   ├── st_lld.h +│   │   │   ├── usb_lld.c +│   │   │   └── usb_lld.h +│   │   └── README.md +│   ├── LPC +│   ├── simulator +│   └── STM32 +├── src +│   ├── adc.c +│   ├── can.c +│   ├── dac.c +│   ├── ext.c +│   ├── gpt.c +│   ├── hal.c +│   ├── hal_mmcsd.c +│   ├── hal_queues.c +│   ├── i2c.c +│   ├── i2s.c +│   ├── icu.c +│   ├── mac.c +│   ├── mmc_spi.c +│   ├── pal.c +│   ├── pwm.c +│   ├── rtc.c +│   ├── sdc.c +│   ├── serial.c +│   ├── serial_usb.c +│   ├── spi.c +│   ├── st.c +│   ├── uart.c +│   └── usb.c +└── templates + ├── adc_lld.c + ├── adc_lld.h + ├── can_lld.c + ├── can_lld.h + ├── dac_lld.c + ├── dac_lld.h + ├── ext_lld.c + ├── ext_lld.h + ├── gpt_lld.c + ├── gpt_lld.h + ├── halconf.h + ├── hal_lld.c + ├── hal_lld.h + ├── i2c_lld.c + ├── i2c_lld.h + ├── i2s_lld.c + ├── i2s_lld.h + ├── icu_lld.c + ├── icu_lld.h + ├── mac_lld.c + ├── mac_lld.h + ├── mcuconf.h + ├── osal + │   ├── osal.c + │   ├── osal.h + │   └── osal.mk + ├── pal_lld.c + ├── pal_lld.h + ├── platform.mk + ├── pwm_lld.c + ├── pwm_lld.h + ├── rtc_lld.c + ├── rtc_lld.h + ├── sdc_lld.c + ├── sdc_lld.h + ├── serial_lld.c + ├── serial_lld.h + ├── spi_lld.c + ├── spi_lld.h + ├── st_lld.c + ├── st_lld.h + ├── uart_lld.c + ├── uart_lld.h + ├── usb_lld.c + └── usb_lld.h From 1a0dfbbc96b32aeae27ace398282c18227fc4b4e Mon Sep 17 00:00:00 2001 From: Ante Laurijssen Date: Wed, 24 May 2017 21:15:41 -0400 Subject: [PATCH 042/238] More updates to keymap.c - still errors with midi when trying to compile --- keyboards/s60_x/keymaps/bluebear/keymap.c | 132 ++++++++++------------ 1 file changed, 61 insertions(+), 71 deletions(-) diff --git a/keyboards/s60_x/keymaps/bluebear/keymap.c b/keyboards/s60_x/keymaps/bluebear/keymap.c index 32a65a593..dfb0b966a 100644 --- a/keyboards/s60_x/keymaps/bluebear/keymap.c +++ b/keyboards/s60_x/keymaps/bluebear/keymap.c @@ -161,9 +161,9 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { ┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐ │ │ F1 │ F2 │ F3 │ F4 │ F5 │ F6 │ F7 │ F8 │ F9 │ F10 │ F11 │ F12 │TO(3)│TO(4)│ ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ - │CAPS │ │ │ │ │ │ │PGUP │ UP │HOME │ END │ │ INS │ DEL │█████│ + │ │ │ │ │ │ │ │PGUP │ UP │ │ │ │ INS │ DEL │█████│ ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ - │ │ │ │ │ │ │ │LEFT │DOWN │RIGHT│ │ │▒▒▒▒▒│ │█████│ + │CAPS │HOME │ │ END │ │ │ │LEFT │DOWN │RIGHT│ │ │▒▒▒▒▒│ │█████│ ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ │ │▒▒▒▒▒│ │ │ │ │ │SPACE│PGDN │PSCR │SLCK │PAUSE│▒▒▒▒▒│ │▒▒▒▒▒│ ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ @@ -173,8 +173,8 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { [ARROWFN] = KEYMAP( KC_TRNS, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, TO(3), TO(4), \ - KC_CAPS, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_PGUP, KC_UP, KC_HOME, KC_END, KC_NO, KC_INS, KC_DEL, \ - KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_LEFT, KC_DOWN, KC_RIGHT, KC_NO, KC_NO, KC_NO, KC_TRNS, \ + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_PGUP, KC_UP, KC_NO, KC_NO, KC_NO, KC_INS, KC_DEL, \ + KC_CAPS, KC_HOME, KC_NO, KC_END, KC_NO, KC_NO, KC_NO, KC_LEFT, KC_DOWN, KC_RIGHT, KC_NO, KC_NO, KC_NO, KC_TRNS, \ KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_SPACE, KC_PGDN, KC_PSCR, KC_SLCK, KC_PAUS, KC_NO, KC_NO, KC_NO, \ KC_NO, KC_NO, KC_NO, KC_TRNS, KC_NO, KC_NO, KC_NO, KC_TRNS ), @@ -644,74 +644,64 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { return MACRO_NONE; }; -/* // Midi Chord Function void action_function(keyrecord_t *record, uint8_t id, uint8_t opt) { -uint16_t root_note; -uint8_t channel = midi_config.channel; -uint8_t velocity = compute_velocity(midi_config.velocity); -switch (opt) { -case 0: //Root note C -root_note = MI_C; -case 1: //Root note C#/Db -root_note = MI_Cs; -case 2: // Root note D -root_note = MI_D; -case 3: // Root note D#/Eb -root_note = MI_Ds; -case 4: // Root note E -root_note = MI_E; -case 5: // Root note F -root_note = MI_F; -case 6: // Root note F#/Gb -root_note = MI_Fs; -case 7: // Root note G -root_note = MI_G; -case 8: // Root note G#/Ab -root_note = MI_Gs; -case 9: // Root note A -root_note = MI_A; -case 10: // Root note A#/Bb -root_note = MI_As; -case 11: // Root note B -root_note = MI_B; -switch (id) { -uint8_t tone = root_note - MIDI_TONE_MIN; -uint8_t root = midi_compute_note(root_note); -uint8_t major_third = midi_compute_note(root_note) + 4; -uint8_t minor_third = midi_compute_note(root_note) + 3; -uint8_t fifth = midi_compute_note(root_note) + 7; -case 0: //Major chord -if (record->event.pressed) { -midi_send_noteon(&midi_device, channel, root, velocity); -midi_send_noteon(&midi_device, channel, major_third, velocity); -midi_send_noteon(&midi_device, channel, fifth, velocity); -tone_status[tone] = root; + uint16_t root_note; + uint8_t channel = midi_config.channel; + uint8_t velocity = compute_velocity(midi_config.velocity); + switch (opt) { + case 0: //Root note C + root_note = MI_C; + case 1: //Root note C#/Db + root_note = MI_Cs; + case 2: // Root note D + root_note = MI_D; + case 3: // Root note D#/Eb + root_note = MI_Ds; + case 4: // Root note E + root_note = MI_E; + case 5: // Root note F + root_note = MI_F; + case 6: // Root note F#/Gb + root_note = MI_Fs; + case 7: // Root note G + root_note = MI_G; + case 8: // Root note G#/Ab + root_note = MI_Gs; + case 9: // Root note A + root_note = MI_A; + case 10: // Root note A#/Bb + root_note = MI_As; + case 11: // Root note B + root_note = MI_B; + switch (id) { + uint8_t root = midi_compute_note(root_note); + uint8_t major_third = midi_compute_note(root_note) + 4; + uint8_t minor_third = midi_compute_note(root_note) + 3; + uint8_t fifth = midi_compute_note(root_note) + 7; + case 0: //Major chord + if (record->event.pressed) { + midi_send_noteon(&midi_device, channel, root, velocity); + midi_send_noteon(&midi_device, channel, major_third, velocity); + midi_send_noteon(&midi_device, channel, fifth, velocity); + } + else { + midi_send_noteoff(&midi_device, channel, root, velocity); + midi_send_noteoff(&midi_device, channel, major_third, velocity); + midi_send_noteoff(&midi_device, channel, fifth, velocity); + } + case 1: //Minor chord + if (record->event.pressed) { + midi_send_noteon(&midi_device, channel, root_note, velocity); + midi_send_noteon(&midi_device, channel, minor_third, velocity); + midi_send_noteon(&midi_device, channel, fifth, velocity); + } + else { + midi_send_noteoff(&midi_device, channel, root, velocity); + midi_send_noteoff(&midi_device, channel, minor_third, velocity); + midi_send_noteoff(&midi_device, channel, fifth, velocity); + } + } + } } -else { -uint8_t root = tone_status[tone]; -if (root != MIDI_INVALID_NOTE) -{ -midi_send_noteoff(&midi_device, channel, root, velocity); -} -tone_status[tone] = MIDI_INVALID_NOTE; -} -case 1: //Minor chord -if (record->event.pressed) { -midi_send_noteon(&midi_device, channel, root_note, velocity); -midi_send_noteon(&midi_device, channel, minor_third, velocity); -midi_send_noteon(&midi_device, channel, fifth, velocity); -} -else { -uint8_t root = tone_status[tone]; -if (root != MIDI_INVALID_NOTE) -{ -midi_send_noteoff(&midi_device, channel, root, velocity); -} -tone_status[tone] = MIDI_INVALID_NOTE; -} -} -} -}; -*/ From ac97870801a684b228cb7a667ea423d0ec381b1e Mon Sep 17 00:00:00 2001 From: jpetermans Date: Thu, 25 May 2017 13:00:21 -0700 Subject: [PATCH 043/238] reduce recurring writes to lock leds --- keyboards/infinity60/led_controller.c | 58 ++++++++++++++++++++++++--- 1 file changed, 53 insertions(+), 5 deletions(-) diff --git a/keyboards/infinity60/led_controller.c b/keyboards/infinity60/led_controller.c index 04793cc01..5c177d26b 100644 --- a/keyboards/infinity60/led_controller.c +++ b/keyboards/infinity60/led_controller.c @@ -135,16 +135,24 @@ msg_t is31_read_register(uint8_t page, uint8_t reg, uint8_t *result) { * initialise the IS31 chip * ======================== */ void is31_init(void) { + xprintf("_is31_init\n"); // just to be sure that it's all zeroes __builtin_memset(full_page,0,0xB4+1); // zero function page, all registers (assuming full_page is all zeroes) is31_write_data(IS31_FUNCTIONREG, full_page, 0xD + 1); + // disable hardware shutdown palSetPadMode(GPIOB, 16, PAL_MODE_OUTPUT_PUSHPULL); palSetPad(GPIOB, 16); chThdSleepMilliseconds(10); - // software shutdown disable (i.e. turn stuff on) + // software shutdown is31_write_register(IS31_FUNCTIONREG, IS31_REG_SHUTDOWN, IS31_REG_SHUTDOWN_ON); chThdSleepMilliseconds(10); + // zero function page, all registers + is31_write_data(IS31_FUNCTIONREG, full_page, 0xD + 1); + chThdSleepMilliseconds(10); + // software shutdown disable (i.e. turn stuff on) + is31_write_register(IS31_FUNCTIONREG, IS31_REG_SHUTDOWN, IS31_REG_SHUTDOWN_OFF); + chThdSleepMilliseconds(10); // zero all LED registers on all 8 pages uint8_t i; for(i=0; i<8; i++) { @@ -169,7 +177,7 @@ static THD_FUNCTION(LEDthread, arg) { uint8_t led_control_reg[0x13] = {0};//led control register start address + 0x12 bytes //persistent status variables - uint8_t pwm_step_status, page_status; + uint8_t pwm_step_status, page_status, capslock_status, numlock_status; //mailbox variables uint8_t temp, msg_type; @@ -179,6 +187,8 @@ static THD_FUNCTION(LEDthread, arg) { // initialize persistent variables pwm_step_status = 4; //full brightness page_status = 0; //start frame 0 (all off/on) + numlock_status = (host_keyboard_leds() & (1<> 16) & 0XFF; msg_args[2] = (msg >> 24) & 0xFF; + xprintf("msg_type: %d-%d-%d\n", msg_type, msg_args[0], msg_args[1]); + switch (msg_type){ case SET_FULL_ROW: + xprintf("FULL ROW: %d-%d\n", msg_args[0], msg_args[1]); //write full byte to pin address, msg_args[1] = pin #, msg_args[0] = 8 bits to write //writes only to currently displayed page write_led_byte(page_status, msg_args[1], msg_args[0]); break; case OFF_LED: + xprintf("OFF: %d-%d\n", msg_args[0], msg_args[1]); //on/off/toggle single led, msg_args[0] = row/col of led, msg_args[1] = page set_led_bit(msg_args[1], control_register_word, msg_args[0], 0); break; case ON_LED: + xprintf("ON: %d-%d\n", msg_args[0], msg_args[1]); set_led_bit(msg_args[1], control_register_word, msg_args[0], 1); break; case TOGGLE_LED: + xprintf("TOGGLE: %d-%d\n", msg_args[0], msg_args[1]); set_led_bit(msg_args[1], control_register_word, msg_args[0], 2); break; case BLINK_OFF_LED: + xprintf("B_on: %d-%d\n", msg_args[0], msg_args[1]); //on/off/toggle single led, msg_args[0] = row/col of led set_led_bit(msg_args[1], control_register_word, msg_args[0], 4); break; case BLINK_ON_LED: + xprintf("B_off: %d-%d\n", msg_args[0], msg_args[1]); set_led_bit(msg_args[1], control_register_word, msg_args[0], 5); break; case BLINK_TOGGLE_LED: + xprintf("B_togg: %d-%d\n", msg_args[0], msg_args[1]); set_led_bit(msg_args[1], control_register_word, msg_args[0], 6); break; case TOGGLE_ALL: //turn on/off all leds, msg_args = unused + is31_write_register(IS31_FUNCTIONREG, IS31_REG_SHUTDOWN, IS31_REG_SHUTDOWN_ON); + chThdSleepMilliseconds(5); is31_read_register(0, 0x00, &temp); + is31_write_register(IS31_FUNCTIONREG, IS31_REG_SHUTDOWN, IS31_REG_SHUTDOWN_OFF); + xprintf("TOGGLE_ALL: %d-%d\n", msg_args[0], msg_args[1]); + xprintf("temp: %d\n", temp); + led_control_reg[0] = 0; //if first leds are already on, toggle frame 0 off @@ -243,6 +268,7 @@ static THD_FUNCTION(LEDthread, arg) { break; case TOGGLE_BACKLIGHT: + xprintf("TOGGLE_BKLT: %d-%d\n", msg_args[0], msg_args[1]); //msg_args[0] = on/off //populate 9 byte rows to be written to each pin, first byte is register (pin) address @@ -261,6 +287,7 @@ static THD_FUNCTION(LEDthread, arg) { case DISPLAY_PAGE: //msg_args[0] = page to toggle on + xprintf("DSPY_PG: %d-%d\n", msg_args[0], msg_args[1]); if (page_status != msg_args[0]) { is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, msg_args[0]); page_status = msg_args[0]; @@ -282,15 +309,24 @@ static THD_FUNCTION(LEDthread, arg) { break; case TOGGLE_NUM_LOCK: + xprintf("NMLK: %d-%d\n", msg_args[0], msg_args[1]); //msg_args[0] = 0 or 1, off/on - set_lock_leds(NUM_LOCK_LED_ADDRESS, msg_args[0], page_status); + if (numlock_status != msg_args[0]) { + set_lock_leds(NUM_LOCK_LED_ADDRESS, msg_args[0], page_status); + numlock_status = msg_args[0]; + } break; case TOGGLE_CAPS_LOCK: + xprintf("CPLK: %d-%d\n", msg_args[0], msg_args[1]); //msg_args[0] = 0 or 1, off/on - set_lock_leds(CAPS_LOCK_LED_ADDRESS, msg_args[0], page_status); + if (capslock_status != msg_args[0]) { + set_lock_leds(CAPS_LOCK_LED_ADDRESS, msg_args[0], page_status); + capslock_status = msg_args[0]; + } break; case STEP_BRIGHTNESS: + xprintf("Step: %d-%d\n", msg_args[0], msg_args[1]); //led_args[0] = step up (1) or down (0) switch (msg_args[0]) { case 0: @@ -337,6 +373,7 @@ void set_led_bit (uint8_t page, uint8_t *led_control_word, uint8_t led_addr, uin if (led_addr < 0 || led_addr > 87 || led_addr % 10 > 8) { return; } + xprintf("_set action-led: %x-%d\n", action, led_addr); blink_bit = action>>2;//check for blink bit action &= ~(1<<2); //strip blink bit @@ -344,10 +381,17 @@ void set_led_bit (uint8_t page, uint8_t *led_control_word, uint8_t led_addr, uin //led_addr tens column is pin#, ones column is bit position in 8-bit mask control_reg_addr = ((led_addr / 10) % 10 - 1 ) * 0x02;// A-matrix is every other byte control_reg_addr += blink_bit == 1 ? 0x12 : 0x00;//if blink_bit, shift 12 bytes to blink register + xprintf("_set control address: %x\n", control_reg_addr); + is31_write_register(IS31_FUNCTIONREG, IS31_REG_SHUTDOWN, IS31_REG_SHUTDOWN_ON); + chThdSleepMilliseconds(5); is31_read_register(page, control_reg_addr, &temp);//maintain status of leds on this byte + is31_write_register(IS31_FUNCTIONREG, IS31_REG_SHUTDOWN, IS31_REG_SHUTDOWN_OFF); + xprintf("_set temp_byte_mask: %x\n", temp); + column_bit = 1<<(led_addr % 10 - 1); column_byte = temp; + xprintf("_set col_byte_mask: %x\n", column_byte); switch(action) { case 0: @@ -398,13 +442,16 @@ void set_lock_leds(uint8_t led_addr, uint8_t led_action, uint8_t page) { //blink if all leds are on if (page == 0) { + is31_write_register(IS31_FUNCTIONREG, IS31_REG_SHUTDOWN, IS31_REG_SHUTDOWN_ON); + chThdSleepMilliseconds(5); is31_read_register(0, 0x00, &temp); - chThdSleepMilliseconds(10); + is31_write_register(IS31_FUNCTIONREG, IS31_REG_SHUTDOWN, IS31_REG_SHUTDOWN_OFF); if (temp == 0xFF) { led_action |= (1<<2); //set blink bit } } + xprintf("_lock action: %d\n", led_action); set_led_bit(page,led_control_word,led_addr,led_action); } @@ -415,6 +462,7 @@ void set_lock_leds(uint8_t led_addr, uint8_t led_action, uint8_t page) { void led_controller_init(void) { uint8_t i; + xprintf("led_init\n"); /* initialise I2C */ /* I2C pins */ palSetPadMode(GPIOB, 0, PAL_MODE_ALTERNATIVE_2); // PTB0/I2C0/SCL From b4b06f81b5024bb5963753edfc07f9e2e0054cfd Mon Sep 17 00:00:00 2001 From: Ante Laurijssen Date: Thu, 25 May 2017 23:03:33 -0400 Subject: [PATCH 044/238] More changes to keymap.c to try and get midi chords to work --- keyboards/s60_x/keymaps/bluebear/keymap.c | 160 ++++++++++++---------- 1 file changed, 86 insertions(+), 74 deletions(-) diff --git a/keyboards/s60_x/keymaps/bluebear/keymap.c b/keyboards/s60_x/keymaps/bluebear/keymap.c index dfb0b966a..2dc7500cd 100644 --- a/keyboards/s60_x/keymaps/bluebear/keymap.c +++ b/keyboards/s60_x/keymaps/bluebear/keymap.c @@ -258,7 +258,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { case 0: //Number 0-) if (record->event.pressed) { if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { - unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + clear_mods(); return MACRO(T(MINS), T(DOT), T(MINS), T(MINS), T(DOT), T(MINS), T(SPACE), END); //-.--.- } else { @@ -269,7 +269,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { case 1: //Number 1-! if (record->event.pressed) { if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { - unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + clear_mods(); return MACRO(T(MINS), T(DOT), T(MINS), T(DOT), T(MINS), T(MINS), T(SPACE), END); //-.-.-- } else { @@ -280,7 +280,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { case 2: //Number 2-@ if (record->event.pressed) { if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { - unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + clear_mods(); return MACRO(T(DOT), T(MINS), T(MINS), T(DOT), T(MINS), T(DOT), T(SPACE), END); //.--.-. } else { @@ -291,7 +291,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { case 3: // Number 3 if (record->event.pressed) { if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { - unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + clear_mods(); } return MACRO(T(DOT), T(DOT), T(DOT), T(MINS), T(MINS), T(SPACE), END); //...-- } @@ -299,7 +299,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { case 4: //Number 4-$ if (record->event.pressed) { if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { - unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + clear_mods(); return MACRO(T(DOT), T(DOT), T(DOT), T(MINS), T(DOT), T(DOT), T(MINS), T(SPACE), END); //...-..- } else { @@ -310,7 +310,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { case 5: //Number 5 if (record->event.pressed) { if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { - unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + clear_mods(); } return MACRO(T(DOT), T(DOT), T(DOT), T(DOT), T(DOT), T(SPACE), END); //..... } @@ -318,7 +318,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { case 6: //Number 6 if (record->event.pressed) { if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { - unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + clear_mods(); } return MACRO(T(MINS), T(DOT), T(DOT), T(DOT), T(DOT), T(SPACE), END); //-.... } @@ -326,7 +326,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { case 7: //Number 7-& if (record->event.pressed) { if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { - unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + clear_mods(); return MACRO(T(DOT), T(MINS), T(DOT), T(DOT), T(DOT), T(SPACE), END); //.-... } else { @@ -337,7 +337,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { case 8: //Number 8 if (record->event.pressed) { if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { - unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + clear_mods(); } return MACRO(T(MINS), T(MINS), T(MINS), T(DOT), T(DOT), T(SPACE), END); //---.. } @@ -345,7 +345,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { case 9: //Number 9-( if (record->event.pressed) { if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { - unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + clear_mods(); return MACRO(T(MINS), T(DOT), T(MINS), T(MINS), T(DOT), T(SPACE), END); //-.--. } else { @@ -356,7 +356,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { case 10: //Letter A if (record->event.pressed) { if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { - unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + clear_mods(); } return MACRO(T(DOT), T(MINS), T(SPACE), END); //.- } @@ -364,7 +364,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { case 11: //Letter B if (record->event.pressed) { if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { - unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + clear_mods(); } return MACRO(T(MINS), T(DOT), T(DOT), T(DOT), T(SPACE), END); //-... } @@ -372,7 +372,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { case 12: //Letter C if (record->event.pressed) { if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { - unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + clear_mods(); } return MACRO(T(MINS), T(DOT), T(MINS), T(DOT), T(SPACE), END); //-.-. } @@ -380,7 +380,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { case 13: //Letter D if (record->event.pressed) { if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { - unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + clear_mods(); } return MACRO(T(MINS), T(DOT), T(DOT), T(SPACE), END); //-.. } @@ -388,7 +388,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { case 14: //Letter E if (record->event.pressed) { if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { - unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + clear_mods(); } return MACRO(T(DOT), T(SPACE), END); //. } @@ -396,7 +396,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { case 15: //Letter F if (record->event.pressed) { if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { - unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + clear_mods(); } return MACRO(T(DOT), T(DOT), T(MINS), T(DOT), T(SPACE), END); //..-. } @@ -404,7 +404,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { case 16: //Letter G if (record->event.pressed) { if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { - unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + clear_mods(); } return MACRO(T(MINS), T(MINS), T(DOT), T(SPACE), END); //--. } @@ -412,7 +412,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { case 17: //Letter H if (record->event.pressed) { if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { - unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + clear_mods(); } return MACRO(T(DOT), T(DOT), T(DOT), T(DOT), T(SPACE), END); //.... } @@ -420,7 +420,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { case 18: //Letter I if (record->event.pressed) { if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { - unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + clear_mods(); } return MACRO(T(DOT), T(DOT), T(SPACE), END); //.. } @@ -428,7 +428,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { case 19: //Letter J if (record->event.pressed) { if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { - unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + clear_mods(); } return MACRO(T(DOT), T(MINS), T(MINS), T(MINS), T(SPACE), END); //.--- } @@ -436,7 +436,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { case 20: //Letter K if (record->event.pressed) { if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { - unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + clear_mods(); } return MACRO(T(MINS), T(DOT), T(MINS), T(SPACE), END); //-.- } @@ -444,7 +444,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { case 21: //Letter L if (record->event.pressed) { if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { - unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + clear_mods(); } return MACRO(T(DOT), T(MINS), T(DOT), T(DOT), T(SPACE), END); //.-.. } @@ -452,7 +452,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { case 22: //Letter M if (record->event.pressed) { if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { - unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + clear_mods(); } return MACRO(T(MINS), T(MINS), T(SPACE), END); //-- } @@ -460,7 +460,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { case 23: //Letter N if (record->event.pressed) { if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { - unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + clear_mods(); } return MACRO(T(MINS), T(DOT), T(SPACE), END); //-. } @@ -468,7 +468,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { case 24: //Letter O if (record->event.pressed) { if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { - unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + clear_mods(); } return MACRO(T(MINS), T(MINS), T(MINS), T(SPACE), END); //--- } @@ -476,7 +476,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { case 25: //Letter P if (record->event.pressed) { if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { - unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + clear_mods(); } return MACRO(T(DOT), T(MINS), T(MINS), T(DOT), T(SPACE), END); //.--. } @@ -484,7 +484,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { case 26: //Letter Q if (record->event.pressed) { if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { - unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + clear_mods(); } return MACRO(T(MINS), T(MINS), T(DOT), T(MINS), T(SPACE), END); //--.- } @@ -492,7 +492,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { case 27: //Letter R if (record->event.pressed) { if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { - unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + clear_mods(); } return MACRO(T(DOT), T(MINS), T(DOT), T(SPACE), END); //.-. } @@ -500,7 +500,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { case 28: //Letter S if (record->event.pressed) { if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { - unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + clear_mods(); } return MACRO(T(DOT), T(DOT), T(DOT), T(SPACE), END); //... } @@ -508,7 +508,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { case 29: //Letter T if (record->event.pressed) { if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { - unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + clear_mods(); } return MACRO(T(MINS), T(SPACE), END); //- } @@ -516,7 +516,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { case 30: //Letter U if (record->event.pressed) { if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { - unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + clear_mods(); } return MACRO(T(DOT), T(DOT), T(MINS), T(SPACE), END); //..- } @@ -524,7 +524,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { case 31: //Letter V if (record->event.pressed) { if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { - unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + clear_mods(); } return MACRO(T(DOT), T(DOT), T(DOT), T(MINS), T(SPACE), END); //...- } @@ -532,7 +532,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { case 32: //Letter W if (record->event.pressed) { if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { - unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + clear_mods(); } return MACRO(T(DOT), T(MINS), T(MINS), T(SPACE), END); //.-- } @@ -540,7 +540,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { case 33: //Letter X if (record->event.pressed) { if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { - unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + clear_mods(); } return MACRO(T(MINS), T(DOT), T(DOT), T(MINS), T(SPACE), END); //-..- } @@ -548,7 +548,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { case 34: //Letter Y if (record->event.pressed) { if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { - unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + clear_mods(); } return MACRO(T(MINS), T(DOT), T(MINS), T(MINS), T(SPACE), END); //-.-- } @@ -556,7 +556,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { case 35: //Letter Z if (record->event.pressed) { if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { - unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + clear_mods(); } return MACRO(T(MINS), T(MINS), T(DOT), T(DOT), T(SPACE), END); //--.. } @@ -564,7 +564,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { case 36: //Punctuation . if (record->event.pressed) { if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { - unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + clear_mods(); } return MACRO(T(DOT), T(MINS), T(DOT), T(MINS), T(DOT), T(MINS), T(SPACE), END); //.-.-.- } @@ -572,7 +572,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { case 37: //Punctuation , if (record->event.pressed) { if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { - unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + clear_mods(); } return MACRO(T(MINS), T(MINS), T(DOT), T(DOT), T(MINS), T(MINS), T(SPACE), END); //--..-- } @@ -580,7 +580,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { case 38: //Punctuation '-" if (record->event.pressed) { if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { - unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + clear_mods(); return MACRO(T(DOT), T(MINS), T(DOT), T(DOT), T(MINS), T(DOT), T(SPACE), END); //.-..-. } else { @@ -591,7 +591,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { case 39: //Punctuation /-? if (record->event.pressed) { if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { - unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + clear_mods(); return MACRO(T(DOT), T(DOT), T(MINS), T(MINS), T(DOT), T(DOT), T(SPACE), END); //..--.. } else { @@ -602,7 +602,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { case 40: //Punctuation ;-: if (record->event.pressed) { if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { - unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + clear_mods(); return MACRO(T(MINS), T(MINS), T(MINS), T(DOT), T(DOT), T(DOT), T(SPACE), END); //---... } else { @@ -613,7 +613,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { case 41: //Punctuation =-+ if (record->event.pressed) { if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { - unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + clear_mods(); return MACRO(T(DOT), T(MINS), T(DOT), T(MINS), T(DOT), T(SPACE), END); //.-.-. } else { @@ -624,7 +624,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { case 42: //Punctuation --_ if (record->event.pressed) { if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { - unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + clear_mods(); return MACRO(T(DOT), T(DOT), T(MINS), T(MINS), T(DOT), T(MINS), T(SPACE), END); //..--.- } else { @@ -635,7 +635,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { case 43: //Morse Space if (record->event.pressed) { if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { - unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); + clear_mods(); } return MACRO(T(BSLS), T(SPACE), END); //When pressed, this sends a slash followed by a space, making it easier to distinguish words in Morse } @@ -647,61 +647,73 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { // Midi Chord Function void action_function(keyrecord_t *record, uint8_t id, uint8_t opt) { - uint16_t root_note; - uint8_t channel = midi_config.channel; - uint8_t velocity = compute_velocity(midi_config.velocity); + uint16_t root_note = MIDI_INVALID_NOTE; switch (opt) { case 0: //Root note C root_note = MI_C; + break; case 1: //Root note C#/Db root_note = MI_Cs; + break; case 2: // Root note D root_note = MI_D; + break; case 3: // Root note D#/Eb root_note = MI_Ds; + break; case 4: // Root note E root_note = MI_E; + break; case 5: // Root note F root_note = MI_F; + break; case 6: // Root note F#/Gb root_note = MI_Fs; + break; case 7: // Root note G root_note = MI_G; + break; case 8: // Root note G#/Ab root_note = MI_Gs; + break; case 9: // Root note A root_note = MI_A; + break; case 10: // Root note A#/Bb root_note = MI_As; + break; case 11: // Root note B root_note = MI_B; - switch (id) { - uint8_t root = midi_compute_note(root_note); - uint8_t major_third = midi_compute_note(root_note) + 4; - uint8_t minor_third = midi_compute_note(root_note) + 3; - uint8_t fifth = midi_compute_note(root_note) + 7; - case 0: //Major chord - if (record->event.pressed) { - midi_send_noteon(&midi_device, channel, root, velocity); - midi_send_noteon(&midi_device, channel, major_third, velocity); - midi_send_noteon(&midi_device, channel, fifth, velocity); - } - else { - midi_send_noteoff(&midi_device, channel, root, velocity); - midi_send_noteoff(&midi_device, channel, major_third, velocity); - midi_send_noteoff(&midi_device, channel, fifth, velocity); - } - case 1: //Minor chord - if (record->event.pressed) { - midi_send_noteon(&midi_device, channel, root_note, velocity); - midi_send_noteon(&midi_device, channel, minor_third, velocity); - midi_send_noteon(&midi_device, channel, fifth, velocity); - } - else { - midi_send_noteoff(&midi_device, channel, root, velocity); - midi_send_noteoff(&midi_device, channel, minor_third, velocity); - midi_send_noteoff(&midi_device, channel, fifth, velocity); - } + break; + } + // uint8_t root = midi_compute_note(root_note); + uint8_t major_third = root_note + 4; + uint8_t minor_third = root_note + 3; + uint8_t fifth = root_note + 7; + switch (id) { + case 0: //Major chord + if (record->event.pressed) { + register_code16(root_note); + register_code16(major_third); + register_code16(fifth); } + else { + unregister_code16(root_note); + unregister_code16(major_third); + unregister_code16(fifth); + } + break; + case 1: //Minor chord + if (record->event.pressed) { + register_code16(root_note); + register_code16(minor_third); + register_code16(fifth); + } + else { + unregister_code16(root_note); + unregister_code16(minor_third); + unregister_code16(fifth); + } + break; } } From 6b1f707ce9431abfff6e6f8aa5730c77578fbc08 Mon Sep 17 00:00:00 2001 From: Ante Laurijssen Date: Fri, 26 May 2017 09:54:40 -0400 Subject: [PATCH 045/238] Still working on these MIDI CHORDS! --- keyboards/s60_x/keymaps/bluebear/Makefile | 4 +-- keyboards/s60_x/keymaps/bluebear/keymap.c | 33 +++++++---------------- 2 files changed, 11 insertions(+), 26 deletions(-) diff --git a/keyboards/s60_x/keymaps/bluebear/Makefile b/keyboards/s60_x/keymaps/bluebear/Makefile index dfefad39d..a444eeb7f 100644 --- a/keyboards/s60_x/keymaps/bluebear/Makefile +++ b/keyboards/s60_x/keymaps/bluebear/Makefile @@ -1,8 +1,8 @@ BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration(+1000) MOUSEKEY_ENABLE = yes # 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 +CONSOLE_ENABLE = yes # Console for debug(+400) +COMMAND_ENABLE = yes # 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 = yes # MIDI controls diff --git a/keyboards/s60_x/keymaps/bluebear/keymap.c b/keyboards/s60_x/keymaps/bluebear/keymap.c index 2dc7500cd..0047a87d3 100644 --- a/keyboards/s60_x/keymaps/bluebear/keymap.c +++ b/keyboards/s60_x/keymaps/bluebear/keymap.c @@ -184,7 +184,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { ┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐ │RESET│ F1 │ F2 │ F3 │ F4 │ F5 │ F6 │ F7 │ F8 │ F9 │ F10 │ F11 │ F12 │ │ │ ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ - │ │ │ │ │ │ │ │BTN1 │MS_UP│BTN2 │WH_UP│ │ │ │█████│ + │DEBUG│ │ │ │ │ │ │BTN1 │MS_UP│BTN2 │WH_UP│ │ │ │█████│ ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ │ │ │ │ │ │ │ │MS_LT│MS_DN│MS_RT│WH_DN│BTN3 │▒▒▒▒▒│ │█████│ ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ @@ -197,7 +197,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { [MOUSE] = KEYMAP( RESET, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_NO, KC_NO, \ - KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_BTN1, KC_MS_UP, KC_BTN2, KC_WH_U, KC_NO, KC_NO, KC_NO, \ + DEBUG, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_BTN1, KC_MS_UP, KC_BTN2, KC_WH_U, KC_NO, KC_NO, KC_NO, \ KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_MS_LEFT, KC_MS_DOWN, KC_MS_RIGHT, KC_WH_D, KC_BTN3, KC_NO, KC_NO, \ KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, \ KC_TRNS, KC_NO, KC_NO, KC_POWER, KC_NO, KC_NO, KC_NO, KC_NO @@ -646,7 +646,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { // Midi Chord Function -void action_function(keyrecord_t *record, uint8_t id, uint8_t opt) { +void action_function_opt(keyrecord_t *record, uint8_t id, uint8_t opt) { uint16_t root_note = MIDI_INVALID_NOTE; switch (opt) { case 0: //Root note C @@ -686,34 +686,19 @@ void action_function(keyrecord_t *record, uint8_t id, uint8_t opt) { root_note = MI_B; break; } - // uint8_t root = midi_compute_note(root_note); uint8_t major_third = root_note + 4; uint8_t minor_third = root_note + 3; uint8_t fifth = root_note + 7; switch (id) { case 0: //Major chord - if (record->event.pressed) { - register_code16(root_note); - register_code16(major_third); - register_code16(fifth); - } - else { - unregister_code16(root_note); - unregister_code16(major_third); - unregister_code16(fifth); - } + process_midi(root_note, record); + process_midi(major_third, record); + process_midi(fifth, record); break; case 1: //Minor chord - if (record->event.pressed) { - register_code16(root_note); - register_code16(minor_third); - register_code16(fifth); - } - else { - unregister_code16(root_note); - unregister_code16(minor_third); - unregister_code16(fifth); - } + process_midi(root_note, record); + process_midi(minor_third, record); + process_midi(fifth, record); break; } } From e87691fa5db011e50fa2a9a5e2881dfda9392bef Mon Sep 17 00:00:00 2001 From: ariasuni Date: Sat, 27 May 2017 00:25:35 +0200 Subject: [PATCH 046/238] Fix undefined reference errors with avr-gcc 7.1 --- keyboards/ergodox/ez/ez.c | 26 +++++++++++++++++++++++++- keyboards/gh60/gh60.c | 28 +++++++++++++++++++++------- keyboards/pegasushoof/pegasushoof.c | 8 ++++++++ keyboards/xd60/xd60.c | 8 ++++++++ 4 files changed, 62 insertions(+), 8 deletions(-) diff --git a/keyboards/ergodox/ez/ez.c b/keyboards/ergodox/ez/ez.c index 3e19f2302..d50224954 100644 --- a/keyboards/ergodox/ez/ez.c +++ b/keyboards/ergodox/ez/ez.c @@ -1,6 +1,30 @@ #include "ez.h" #include "i2cmaster.h" + +extern inline void ergodox_board_led_on(void); +extern inline void ergodox_right_led_1_on(void); +extern inline void ergodox_right_led_2_on(void); +extern inline void ergodox_right_led_3_on(void); +extern inline void ergodox_right_led_on(uint8_t led); + +extern inline void ergodox_board_led_off(void); +extern inline void ergodox_right_led_1_off(void); +extern inline void ergodox_right_led_2_off(void); +extern inline void ergodox_right_led_3_off(void); +extern inline void ergodox_right_led_off(uint8_t led); + +extern inline void ergodox_led_all_on(void); +extern inline void ergodox_led_all_off(void); + +extern inline void ergodox_right_led_1_set(uint8_t n); +extern inline void ergodox_right_led_2_set(uint8_t n); +extern inline void ergodox_right_led_3_set(uint8_t n); +extern inline void ergodox_right_led_set(uint8_t led, uint8_t n); + +extern inline void ergodox_led_all_set(uint8_t n); + + bool i2c_initialized = 0; uint8_t mcp23018_status = 0x20; @@ -57,7 +81,7 @@ uint8_t init_mcp23018(void) { // cli(); if (i2c_initialized == 0) { i2c_init(); // on pins D(1,0) - i2c_initialized++; + i2c_initialized = true; _delay_ms(1000); } diff --git a/keyboards/gh60/gh60.c b/keyboards/gh60/gh60.c index f5a158e12..441c799fa 100644 --- a/keyboards/gh60/gh60.c +++ b/keyboards/gh60/gh60.c @@ -1,25 +1,39 @@ #include "gh60.h" + +extern inline void gh60_caps_led_on(void); +extern inline void gh60_poker_leds_on(void); +extern inline void gh60_fn_led_on(void); +extern inline void gh60_esc_led_on(void); +extern inline void gh60_wasd_leds_on(void); + +extern inline void gh60_caps_led_off(void); +extern inline void gh60_poker_leds_off(void); +extern inline void gh60_fn_led_off(void); +extern inline void gh60_esc_led_off(void); +extern inline void gh60_wasd_leds_off(void); + + void led_set_kb(uint8_t usb_led) { // put your keyboard LED indicator (ex: Caps Lock LED) toggling code here - + if (usb_led & (1<. #include "pegasushoof.h" + +extern inline void ph_caps_led_on(void); +extern inline void ph_caps_led_off(void); + +extern inline void ph_sclk_led_on(void); +extern inline void ph_sclk_led_off(void); + + __attribute__ ((weak)) void matrix_init_user(void) { }; diff --git a/keyboards/xd60/xd60.c b/keyboards/xd60/xd60.c index 4307f5f59..c3b63e5ea 100644 --- a/keyboards/xd60/xd60.c +++ b/keyboards/xd60/xd60.c @@ -1,5 +1,13 @@ #include "xd60.h" + +extern inline void xd60_caps_led_on(void); +extern inline void xd60_bl_led_on(void); + +extern inline void xd60_caps_led_off(void); +extern inline void xd60_bl_led_off(void); + + void led_set_kb(uint8_t usb_led) { // put your keyboard LED indicator (ex: Caps Lock LED) toggling code here From a5846757359a27f9e5ed67cfe96f1d92e72b1b4b Mon Sep 17 00:00:00 2001 From: Ante Laurijssen Date: Sun, 28 May 2017 08:14:17 -0400 Subject: [PATCH 047/238] Midi Chord Function is now working! But some chords lag... --- keyboards/s60_x/keymaps/bluebear/Makefile | 4 +- keyboards/s60_x/keymaps/bluebear/keymap.c | 174 ++++++++++++++++------ 2 files changed, 128 insertions(+), 50 deletions(-) diff --git a/keyboards/s60_x/keymaps/bluebear/Makefile b/keyboards/s60_x/keymaps/bluebear/Makefile index a444eeb7f..dfefad39d 100644 --- a/keyboards/s60_x/keymaps/bluebear/Makefile +++ b/keyboards/s60_x/keymaps/bluebear/Makefile @@ -1,8 +1,8 @@ BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration(+1000) MOUSEKEY_ENABLE = yes # Mouse keys(+4700) EXTRAKEY_ENABLE = no # Audio control and System control(+450) -CONSOLE_ENABLE = yes # Console for debug(+400) -COMMAND_ENABLE = yes # Commands for debug and configuration +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 = yes # MIDI controls diff --git a/keyboards/s60_x/keymaps/bluebear/keymap.c b/keyboards/s60_x/keymaps/bluebear/keymap.c index 0047a87d3..3be39c3fa 100644 --- a/keyboards/s60_x/keymaps/bluebear/keymap.c +++ b/keyboards/s60_x/keymaps/bluebear/keymap.c @@ -37,47 +37,90 @@ enum midi_chord_root { //ACTION_FUNCTION opt B, }; -enum midi_chord_keycodes { +enum midi_chord_id { //ACTION_FUNCTION Progmem Id //Major Chords - MI_CH_C = ACTION_FUNCTION_OPT(major,C), - MI_CH_Cs = ACTION_FUNCTION_OPT(major,Cs), - MI_CH_Db = MI_CH_Cs, - MI_CH_D = ACTION_FUNCTION_OPT(major,D), - MI_CH_Ds = ACTION_FUNCTION_OPT(major,Ds), - MI_CH_Eb = MI_CH_Ds, - MI_CH_E = ACTION_FUNCTION_OPT(major,E), - MI_CH_F = ACTION_FUNCTION_OPT(major,F), - MI_CH_Fs = ACTION_FUNCTION_OPT(major,Fs), - MI_CH_Gb = MI_CH_Fs, - MI_CH_G = ACTION_FUNCTION_OPT(major,G), - MI_CH_Gs = ACTION_FUNCTION_OPT(major,Gs), - MI_CH_Ab = MI_CH_Gs, - MI_CH_A = ACTION_FUNCTION_OPT(major,A), - MI_CH_As = ACTION_FUNCTION_OPT(major,As), - MI_CH_Bb = MI_CH_As, - MI_CH_B = ACTION_FUNCTION_OPT(major,B), + CMajor, + CsMajor, + DbMajor = CsMajor, + DMajor, + DsMajor, + EbMajor = DsMajor, + EMajor, + FMajor, + FsMajor, + GbMajor = FsMajor, + GMajor, + GsMajor, + AbMajor = GsMajor, + AMajor, + AsMajor, + BbMajor = AsMajor, + BMajor, //Minor Chords - MI_CH_Cm = ACTION_FUNCTION_OPT(minor,C), - MI_CH_Csm = ACTION_FUNCTION_OPT(minor,Cs), + CMinor, + CsMinor, + DbMinor = CsMinor, + DMinor, + DsMinor, + EbMinor = DsMinor, + EMinor, + FMinor, + FsMinor, + GbMinor = FsMinor, + GMinor, + GsMinor, + AbMinor = GsMinor, + AMinor, + AsMinor, + BbMinor = AsMinor, + BMinor, +}; + +enum midi_chord_keycodes { //Midi Chocd Keycodes + + //Major Chord Keycodes + + MI_CH_C = F(CMajor), + MI_CH_Cs = F(CsMajor), + MI_CH_Db = MI_CH_Cs, + MI_CH_D = F(DMajor), + MI_CH_Ds = F(DsMajor), + MI_CH_Eb = MI_CH_Ds, + MI_CH_E = F(EMajor), + MI_CH_F = F(FMajor), + MI_CH_Fs = F(FsMajor), + MI_CH_Gb = MI_CH_Fs, + MI_CH_G = F(GMajor), + MI_CH_Gs = F(GsMajor), + MI_CH_Ab = MI_CH_Gs, + MI_CH_A = F(AMajor), + MI_CH_As = F(AsMajor), + MI_CH_Bb = MI_CH_As, + MI_CH_B = F(BMajor), + + //Minor Chord Keycodes + + MI_CH_Cm = F(CMinor), + MI_CH_Csm = F(CsMinor), MI_CH_Dbm = MI_CH_Csm, - MI_CH_Dm = ACTION_FUNCTION_OPT(minor,D), - MI_CH_Dsm = ACTION_FUNCTION_OPT(minor,Ds), + MI_CH_Dm = F(DMinor), + MI_CH_Dsm = F(DsMinor), MI_CH_Ebm = MI_CH_Dsm, - MI_CH_Em = ACTION_FUNCTION_OPT(minor,E), - MI_CH_Fm = ACTION_FUNCTION_OPT(minor,F), - MI_CH_Fsm = ACTION_FUNCTION_OPT(minor,Fs), + MI_CH_Em = F(EMinor), + MI_CH_Fm = F(FMinor), + MI_CH_Fsm = F(FsMinor), MI_CH_Gbm = MI_CH_Fsm, - MI_CH_Gm = ACTION_FUNCTION_OPT(minor,G), - MI_CH_Gsm= ACTION_FUNCTION_OPT(minor,Gs), + MI_CH_Gm = F(GMinor), + MI_CH_Gsm = F(GsMinor), MI_CH_Abm = MI_CH_Gsm, - MI_CH_Am = ACTION_FUNCTION_OPT(minor,A), - MI_CH_Asm = ACTION_FUNCTION_OPT(minor,As), + MI_CH_Am = F(AMinor), + MI_CH_Asm = F(AsMinor), MI_CH_Bbm = MI_CH_Asm, - MI_CH_Bm = ACTION_FUNCTION_OPT(minor,B), + MI_CH_Bm = F(BMinor), }; //Morse Code Macro Keys @@ -646,56 +689,91 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { // Midi Chord Function -void action_function_opt(keyrecord_t *record, uint8_t id, uint8_t opt) { +const uint16_t PROGMEM fn_actions[] = { + + //Major Chords + + [CMajor] = ACTION_FUNCTION_OPT(major, C), + [CsMajor] = ACTION_FUNCTION_OPT(major, Cs), + [DMajor] = ACTION_FUNCTION_OPT(major, D), + [DsMajor] = ACTION_FUNCTION_OPT(major, Ds), + [EMajor] = ACTION_FUNCTION_OPT(major, E), + [FMajor] = ACTION_FUNCTION_OPT(major, F), + [FsMajor] = ACTION_FUNCTION_OPT(major, Fs), + [GMajor] = ACTION_FUNCTION_OPT(major, G), + [GsMajor] = ACTION_FUNCTION_OPT(major, Gs), + [AMajor] = ACTION_FUNCTION_OPT(major, A), + [AsMajor] = ACTION_FUNCTION_OPT(major, As), + [BMajor] = ACTION_FUNCTION_OPT(major, B), + + //Minor Chords + + [CMinor] = ACTION_FUNCTION_OPT(minor, C), + [CsMinor] = ACTION_FUNCTION_OPT(minor, Cs), + [DMinor] = ACTION_FUNCTION_OPT(minor, D), + [DsMinor] = ACTION_FUNCTION_OPT(minor, Ds), + [EMinor] = ACTION_FUNCTION_OPT(minor, E), + [FMinor] = ACTION_FUNCTION_OPT(minor, F), + [FsMinor] = ACTION_FUNCTION_OPT(minor, Fs), + [GMinor] = ACTION_FUNCTION_OPT(minor, G), + [GsMinor] = ACTION_FUNCTION_OPT(minor, Gs), + [AMinor] = ACTION_FUNCTION_OPT(minor, A), + [AsMinor] = ACTION_FUNCTION_OPT(minor, As), + [BMinor] = ACTION_FUNCTION_OPT(minor, B), +}; + +void action_function(keyrecord_t *record, uint8_t id, uint8_t opt) { uint16_t root_note = MIDI_INVALID_NOTE; switch (opt) { - case 0: //Root note C + case C: //Root note C root_note = MI_C; break; - case 1: //Root note C#/Db + case Cs: //Root note C#/Db root_note = MI_Cs; break; - case 2: // Root note D + case D: // Root note D root_note = MI_D; break; - case 3: // Root note D#/Eb + case Ds: // Root note D#/Eb root_note = MI_Ds; break; - case 4: // Root note E + case E: // Root note E root_note = MI_E; break; - case 5: // Root note F + case F: // Root note F root_note = MI_F; break; - case 6: // Root note F#/Gb + case Fs: // Root note F#/Gb root_note = MI_Fs; break; - case 7: // Root note G + case G: // Root note G root_note = MI_G; break; - case 8: // Root note G#/Ab + case Gs: // Root note G#/Ab root_note = MI_Gs; break; - case 9: // Root note A + case A: // Root note A root_note = MI_A; break; - case 10: // Root note A#/Bb + case As: // Root note A#/Bb root_note = MI_As; break; - case 11: // Root note B + case B: // Root note B root_note = MI_B; break; } - uint8_t major_third = root_note + 4; - uint8_t minor_third = root_note + 3; - uint8_t fifth = root_note + 7; + uint16_t major_third = root_note + 4; + uint16_t minor_third = root_note + 3; + uint16_t fifth = root_note + 7; switch (id) { - case 0: //Major chord + case major: //Major chord + dprintf("Root Note:%d - Major Third:%d - Fifth:%d\n", root_note, major_third, fifth); process_midi(root_note, record); process_midi(major_third, record); process_midi(fifth, record); break; - case 1: //Minor chord + case minor: //Minor chord + dprintf("Root Note:%d - Minor Third:%d - Fifth:%d\n", root_note, minor_third, fifth); process_midi(root_note, record); process_midi(minor_third, record); process_midi(fifth, record); From 4c48c29c0e65f66f95290a6f056d0af5b3cc5ab0 Mon Sep 17 00:00:00 2001 From: Ante Laurijssen Date: Mon, 29 May 2017 22:09:06 -0400 Subject: [PATCH 048/238] Added MIDI_CHORD layer and other little fixes. Updated readme.md --- .../bluebear/S60X-Bluebear-ARROWFN-Layer.png | Bin 17938 -> 18499 bytes .../bluebear/S60X-Bluebear-MIDI-Layer.png | Bin 21329 -> 0 bytes .../bluebear/S60X-Bluebear-MOUSE-Layer.png | Bin 16119 -> 16499 bytes keyboards/s60_x/keymaps/bluebear/keymap.c | 195 +++++++++++++++--- keyboards/s60_x/keymaps/bluebear/readme.md | 60 +++++- 5 files changed, 226 insertions(+), 29 deletions(-) delete mode 100644 keyboards/s60_x/keymaps/bluebear/S60X-Bluebear-MIDI-Layer.png diff --git a/keyboards/s60_x/keymaps/bluebear/S60X-Bluebear-ARROWFN-Layer.png b/keyboards/s60_x/keymaps/bluebear/S60X-Bluebear-ARROWFN-Layer.png index a7c6df504412616e24c67efae9d5b18e5097d222..1f659d184d9816a81983cf34436995d000dab4fe 100644 GIT binary patch literal 18499 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 S;mv`zDaotKC7jlK^#1^gAcJlI literal 17938 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 diff --git a/keyboards/s60_x/keymaps/bluebear/S60X-Bluebear-MIDI-Layer.png b/keyboards/s60_x/keymaps/bluebear/S60X-Bluebear-MIDI-Layer.png deleted file mode 100644 index c8df0a9e9e7c0ae12beeb972a4c3ad0adec9c420..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21329 zcmeIaby!qe*gkB7Qqn01h@ya_Afc2rih_uQf_eo%SqIr|S)wA(6HhJE95uV~DUXJB?8CK(Xx8Hy z@n`EVMQu{0*`^=5xp7h0JzPQ|7x&ad?D;2$hgebS$|OBwo+!s`wk4 zt}QIpE!7Y7WL6n5Qc_xbYd7p+`F6g+myEIb z#EBE%#KpyJN1J(w7%AjC@WqHbDv^huW@ggv*|TSb@vxpU8C~4%+qYL^W7*3^!`DaJ zEt`eIVS{1#5e})sN&OSz;uO8S->+|aSYNODSlnq!Kn3n6t!B-=ar>wU7`Iz&tfi;N zidgx59OV=d{?m3%B=Y=8B0%CFTQ_q3InKyaECWCMG-&A3l5*|K<(N^XJdu!}c6Y z*1~Q6=t^t8!V!}>$L3)491V#pb8+e==WCZR%O)noL&D7ZmeJRpZ$PFwpb@ucd5ckfQLTZmj}RM|Dc!#H<`%(Z6w`b?>*&<`2oI3vmAq%Sk& zDC@b`d&OSmA6fO)nUgRsjco8mNyA?P;0uQ%$zVnaQ|H2}ypxg+J)Louc$t<)mHz=g zwP{k}9Z^70KVdACzX|i(>>AymGK8m-Lj~szlLj4**0P#l@>)8XEWH3 zL-ET#h>aLb93IUGR?CagxqMmROJ5lIt*QZLp>||-kgxxo&d}H9RHFS_0(Rzx5PSC; zlRN%ZQj#Dhyea`6W6Yoh7Brp_*7n$3d?aaOtpxf!UEE#NRiklkN{sk`YTd&{;WMYs zg-c92VuZSbEW@5<5RbI4U!s6=Z9=Y&EWi#+JEBU~@E`J@^1gprm+5|%h?~6|x4cas zgZB;J3=abH`Tpfqv?6U7x{M*tbJ69*)MMAqsOL%#aCS?RxdY<8i{rWy* z;T%Emq4ONg8{)k+`}#azr58B6PRrcV;n}Cpp2_EJYW)5H$PH9HQ3-)csQw_e+4?hG zM|m(cZ#y5}T$_4$i{f|!K=ZnPJ>8ZBoM9kt~D{}3-_XoVIqHu&@-3j_sl(8+^l?dNXUiVMZk3J^8k=73b@3FM8nrp) zw7>65ZS=c6_?q|c%SbpdHFn;~|^-0np8XB7PD>XC{%QNL=+rZY4t=m}I z3<6CkEK?FOWu?9@y!k89>FVu8@d5g{Yk@n>mWx-l+BCZ1>hOq&TiNDqJGx)tiKZ z=gQbvSiItS;nAg+IvRX-{;_RF(>yHr5uP*nx9LKy}%bTqrky|3*>J!H_djpn~A zAa(rs@hB0?OVwm{pOQ4wFQqy!O_bySU&=Yc7AXbT!%{)%|)}vs<2<-TN#G|3n+(nw_0(I6wBuMvM)nXmcWl zmyeHZS)z4#qW2ro#l@w)*mLb!0iA-3tn3zKbE2XGNZ6e>!BxgmY2;|Gcm+zO+il7r zEXk9dxyB8#k`G69oITS~+CMi|C*3q?-kwZZpIjze} zuibPoI9~7wRIb>#$cAA#Q`7x9R^7YO+JdL1tiU)qd3d%jElheRRjz*M@aOPgnwy^X zAmp1_SUjF%t?w@;EG*#qO1+iOo>kD$&}d((#_@1nqL0gnm7C7ElzpB45FelL{MhJd z>Fqt@>CSkg(L#Bj*#egWpF>jmd-6DX>+^&xTo$W5m9g`0urh>clx|4es{5|k)mxT& z=taE#0IE1Y4tqe=YkjenUFhlQ4O?EER()b91m7X4@k)P9}{wd*eimn8Vn|sD=dIU8hf< z4uAM?S7fbkYinzG9QgSD#o@TBp%0HDVqm3KabGkcGUfweI1+# z>jJ!DqcQo~$_LTjiuxFF+kAw5azNCbudg8$eA>9y_l+{SLiA{Gp##3-QO7$9DMZ1k(*az zU3Sz)qNv`jt*$IJb#<{hC$#qVhEYi`?{@04RqFE~bUSf4PJZ?+EtPpJX1gUYFiL36I$BgDbtdM7@QBnKm%sq6?VN0ip`S`hPSzDjt;}g48;KsmgU@}^ z6(}eDD7Yf6yAoH91PfWYw5CEqLBYo6W}2__Qd zv$W#z^7@Qu9@W~?mzul0C{&dn1*>e&$E2~)1{@t7UBv{cteczoP<;%mJx51@ynGtB zl$;+-pGJZ)2}toe;Xd*a46rLL7uVNCMQ23#UE8<$arFxq z=)SfO4h|XyH-ICHc>I_xPd`ueV*hGPWTZdG%81g-moHChYiqanirbIu?r|q{M-@g; z5}4QTIgLxG(!st@&d+DnO4j^wyTelD%Z5t(b0i-7@$}}=-hOs4Pg15dM4Z-UtxLXO zrnlwC-fVG=k@jT2cI_JP!GpKj#ucosQIva5_@tzylnnaNE0jJE(A|xY*mDQ!HC%>FIlL=dQhgVT2?hu4^_7&Ie zB}Z$#ICHCIRNmM);Z=c=FuLj6_4#kj#<5|QYGE$ipUJNsH5L3Y8y_0kqng2#rc=jC zTVpH1ur1Sdr#i-O&0{fD!PzByYw+;C9o>nhvl#v;2a@wIx^H{-I;b@^tP-}jq`TkW zTGZR+zxoF2?C49emhSA@Uez`bpmz1@f#&Asbk8-9xrK#zNNW(sfMGhvC$&5yciDS# zb}>9UIxtl?w`_bq9!%ZD#64Hbl6=9g|4oy>Bd!*{OE%A3+R5c>(|TPnAAct^5F1gmbt;;jIW={_?lhN zYSNNJp*qE@WueirvjrWMwE=BWV4!)+Lp^7i9fW}_e+??-CW~S}rXW{-WyI*Om zt5b_ueujhZPsLH0W7+v^KIqGm*p<2Sn)JTDzU^=A4v1K^-(*BPmmZ1J35#s1C>wu& zpHD_##Ec%e^6*IdVfo^_w=r=g}7;czsaeCVr!MMA1!N0k9SWRwsjM&hAum=MZ4tXpv=3B z=*Mw)qobMaYpQK{gS=odpZ!0IA0x~bV0jves?qg)U9;J_x!jVHm#?Rdx22VvW+F8r zqz9adG9#08wRk~6?~IvuHvL=BuA@AV-aLHI*QMjj-CA_XS>Z&(_-NvALB!8M7IpPP zgG*1yz;lB6nJ^c*>9^SWGwvWEvBg#F+_!(f>WFW$LVBte-)nRs%iMDR{_`CL zWs>^f0bZ!a9GZ95)Yj%caDXJqbs%_>jZ&%c+HP0zYsb+E0$)sLSzJyBMHlqAjtjg@ z3VQH>;fje#Kg1d5=|V#KjluUP6^%!eeYN+^7W87*&$Z@w_wL;m)VtMH4{{0$8Fe}$guNsdB4K74{*BD&XXNV}Wu6EL2}vKO zTEY}P!ErxoGh3q-bDHXU0zC^z)CT8$J1O5{;KiTxY{X)m2VCcpR>uJ!hZ4f z-F-0EXD?nD85nGWr*U4HZ*#zZx-P|L9oyEamgZvIo)6J?#J)}^G#Wiyz+8nKJ$5C` zTr64kSDJ|RvH&7EoUYxiuW~mJs*)FFGC`^F#IB)GM(L(v?382Mp4@&Y;z*a5XZ2BK z-L2cogTgu|DDpnWli0%`)@}JI_fGnl z?kVDgHkmD6n=E6n|JbtVaJL_QT;|mVE@5GM>*5s=j1-4z%n9G;Dv_!qp>uPiEw*33 zoPwP+obD++N5?Z$Dql!ewm3T+@!)|UoNDJnG`L(`<5Rin_wRS`fS9~ zJyu-dkQ^UloJvkB3c7cXj$bctH>!A9kll6UY02RE`NO11Nf1T2L`4}X{kOt@$=Yd( zPEMi>0+;rsM#lSi6qh$8C@FP2G8c4Ni9)U_$L@p;qQBL$cg_(BluI5YLe2++yyoWY z*~A^|=+Ft0s~T#OzD_+ZBcJxjGwn)a3oWfT?l9Qa|1~o)SvL=l5yhf1(MC z@27+x#xWN_aAPhILmRm$h%>&&2~*=fspR5j2kjX24llBNbSEQ69q&KgFv$3#uXZ>d zCFS7YU}k1Us&{c;>)iZ2=fQ(J8>H7T^4`6TjW@x0yo5T@^;*9?_=S=4$BIm-E@%|)&55I2RQcw3G=nVR&iawCTP29goo-kYz$DmBbi7R7uMei$yt*M z`;RLCJChB<%~lcwh?U(8U2)e-w|ZKZ22=IqxlhWHjd2v?3HmGAWI32Buhs(s#0TYG zOXvBCQ~YEnJQ$YS8{9j+%CP)W_}vz+HCz7#42`rfMW4S4e+X)jHtppXi&0=$PFt%D zE%q#E^;%A0^;{G0481dZHh+8e6l<<9Ll^I9ZjL2Fn9hu5O+|2nnRZ|}Jz3$i-yukt zv*|)}0g?Qz9@Do`*$+W#-2N9)a7_{VC^$ep>IyP!|wtMP$4vbLdT(aq0Gu=u4 z0Ba-@PqWr27 zniwzs)i|R|EJ%nvr-wLE-`l}YM8U2!TxQ@`&F&jC5%pN`pJ(WLs?%7!SXun2O*eht z2d{}^WH*XD2JG_!8RDKMGT>0JYDPTq*qd#Yp{$0vozJaG;9=7{C)Z)veSgp4%f=jL zIHW>2BgZSTltwqNXFU06B;ygn?g>k_Hq*a54RGN+z1L4P#;%kN-te_7n4_Wnfxd3w z#1)Sshp>qoV6q=s?MX*R$992|4rqb~GlP{@*X)I=L|dy|w%sD&zB*GRceJ z9lEHht8d|*C5(6IR{rxImCj4&a&a1(nkK~h-GNC-NiV$x%BA4J$7T|R zA@^!uZjVBFuK@*ALQK{I&Cc7}%dUaj3cq}%G2wVaBo*TooR&Mxh9BplVMDnxPd>|z zRJJL=wW;hI;fajoT?)r4mB>W6aNOt*fT8=Gn`+Gtq$1f@%9PtE~s^apmhJ=zdz_O_@2J} zGBT{g`mkm&Y>UdVKZgY#>|IxU%daZTjIMy`wmUn{*LiD*=s$S`zIxnO&mUTxMAnE9sW*GHXgsNm*uytpXfK9VSXkK4 z*|)QGVZjk_4V6hAuDLt4D);{76eYOv?B5@smWGNSCez-1>C&a}`}ckC9#F#-5_-y^ ztZZs--lD0Q0ZUY(PE%M|W@-Mtg2@J4?~il!>(qu$-3Jt2=xV)>!~)dekU`Vi>*jeK z5fcme`0)ZcIr)>kJf^hb)e{%yD~GS|+O>;(mSr-a0Tw~dDzfHp3;ktEii8{a-BABt zZM2Mui8)8Noe_m5f49==l@8f;dZIUg0F?fed&=^si_D|6_r>8On*OK3PPi@bpV!d9 zFLYX$56||0e5IlD&iT~}fJciG2C{1XpFhqUy>&W~G~gnV zdHw0ozkmIbi?FCDQhExR*4^y3Qu6SS!bs^?bY{3OIbyzzCK@*6z6O}(-LzS6Y-+al zzD_~vvDpOMkjh^L{T9x6AhEagoz8xGYGJL*3d zq@;t{R*_QLT9ynL0N{>59!R^oxiz)6`VH1bmQOm8bf>*~wX^nt05FuuR`rEO!7l*R z15_pZI^AxjuQZ%*V&o#GvhzWpv#&SyfJo%?P{+qm_rPQ_9LBYvq_KB$N`PQ|@Zdox zaP==3Kfe!;NcSo(DTz3e5SDIGy5-rkXWNR*nqIQq&K96`v7DcqL(p)Y0%zNgsu=fc zLLA>#Jn9|_^Ic(;KP)vM85XNr$61J@hL~~GJUx5n{XcP?>=H`^*#~(2sF)aOem6T& zaoldW{^`q?q)99tPKTJ(F^ZiJYMes}dUa28tPQxB6XWB#EIwx){NhA)6B|+fLkj?z zh-GJvg0R*l7lk)xBfh;#3Mwm;o#=W?%PL|~LWU|ZFr%#c{2;I>2TauqAY-M;ing{d z!{u#gH;TiNd=u^_0#dHxf2=m2kPt06L}MwnJd_J7`dANU_Uy-xAGb|8jZf#SgENvN z8GjH4QO*kQ1ZV+Wds}H|M0sF!$Npy94R+z)eq=qLb!$+j*+Ldr0(<^k(9>tm$m{F(Mm4lFH+!X| z@IRJtp#da>9pOyGvQ0ib6uz}qLy?;Y1&HC;$5*#J`GUM~I3w^gebHBAOX18JY= zNwlZ^PjusHl4w0WikFvkx!!Coc>^aQm)18oH*dTqaLHBSjlf;}_vKCCNHeQC$j!|? zarG>m({uR1D=AqR_t0F}eo1@^aVM;2nO-%2a1aJOLN?I=!J7; zmS!_DSi#oJ$8NZhFp;5hJ40i{opyA$c60!zYlFurO!O3rPprNC&5yDY3zh4+Io`HE zmU3sQsi`@NXR+4ZKkhJY7dl+QraD1!=GZ`%$I7=S4dvt-Xf%5cF$6Kr_1Vo62;5K* zUTuh_kWhqFu<@X&>!3}6WpthS1}7mr*2bW(fA#3go(wO?C0iI`S$Dou`KZ0(%4giT`PbQg zoiwajrOZ8-a?%4s;b=VRhI78;^6z2bR-E+wM-AuU7^l8@*R9shJ9g{{kBnrT6APmG zc9~i!jGf|b!@^`I93kMt@1!$oHC~rtgQdp_eKdt!*~D=Czm@+H8A#%9fP~3kvKXW=V`Mf*a(F)^P=1&5d@q>( z$4e@o5knk>x6^byiL(7i33nyM{iO@u_N^XheT4N?6`_jjzw!1=F4gECsvH@VV2{+t z0wP4sQq#Be!UAm2Uyo`=c=}s$`Y3v0Vj{eBVr1l` zmDS-1$Nc_IQR)dt@m*wOO-)TQsGS?Kr;T;Wbd9L4yx4-vv>i|c@zK2p4?xz`JX5Y` z`s}B?=~lTD9Q?fDShqgM{0ygQba}2V7eWtO<+9EWeUP)W6GGHazZ6wIdeJ09mxd*1pKU*bh5It`tGVpF*|U@N9z1Jy%gKlRN@6qP39u* zx|5oknisH%a3rDX@Utf9WaZ@eN!}4|l?Uu?L&ektSIbLOvRq~0s4>7ljYR(a>tW@p zaV?#l!TQTMMx87(>ZyWRRsKs^q-xSD#~=rz=rt?{s>jD?+rEAK_8vV-O(ik238YLE z-TMWC8>T(i++bVE37M_5)W1|G+9?HBT&P%UEKTL})(3}mM)*k2oq?}FaV_Pi%?>h0WP@+A8OqP2sokvTJEQM%Dd~$n>Uaf0M&jO zxiAV?Z_|d@P|+Uetq_d>4R#(+&D|2V)DpK!*C0t?gT>1*EZ>2sCo)Yxlo^Lf`T>Ed z#P)EbG?UZR#H=n3>*PBM0Luv;9L@XX+_@-!RXV_&`abj9avb9|jp12Ff9L`V7b=`tu@Wp_*!Elrib zzMPK~aDb^J`wx1Ef&w^@b-{>j&ubGJXg-I?jfx4*| z%GbKb$AykmL*#_qR?Ka|qT(s@B6HlAFIV&moR7|A!o%%_t=m16=D9LXoKN!%g(3pr zz!aT~Ez+=MfDl%a_v?7qfCS>_5}SlX@=qI17cE)oy|X_!GY#NUUDQ$T5h?CN}3B!JtSAK<<4Islo0uYv5n1cD5}b1oO%LL zMMSP6=i1Wr{gaZA^Ypih1OZ3}!lV&YtF3r-zJwEjRJc$mD(y5h_G+BF-?aO*8>D}v z`2$vkNu5vS{Jma}<(Ph80U^#4KsIcWI>E5F7OyKd!5>tDs0cq8sgKZNp0lE!-k|A8 zZ=jy)&5c*UyMW<9%$_OPO0{hz%qL)TsHxZUpCZJ$py$Xc*xA`-Y_Lhpl9H0uwYB9B zh0VRDKv?xdz!c}sur@=rWGq?|C09e`Da?-j;crt4uQ*dJbzF_>&!}QAhlxkrx#LyE;VCgf8lKeS+_2bX z*MNxbR37k`Lh(t#k)RWnX^8bdL!PSYz&d?mHh$Z&&vIiwTolBmj0M51riBH2{8u#Ydw%*c#}{e2k-3JvoG)<^a`CE{GSv&pn2hNpQC2r*SQIVEyRQ{_}ol~kXC@3iXTFZ;@DrpSy2fH!i$;T#V^pES4{X3p9Rt`C zU|6PkD*HCaOl<4y>A4LAaf?f|LqT2Np#2Hkv5yDK-Ln?nd90j(A^?zTb=V!^s8vRF zKlD?~G^?OEMMbsOZ}#vZ3!4;1=bM+!xP&zWDxvZ;3RM`BHOFOC4hJENR|@ubWPDtx zi{}pVfRp3nOHxiGC8nT1efm^gQv<~_6C0aPdH<0)`&^x& znHDwa`#pRQUC;|&M?OoS9w9=L5bV_gmsqU-$nko9sXNGuR#%rq3tg3Eck3;39~m2? zIrQYxvRWTtxD?EM?972`X^0%ew`6$s)MZSpGcGV(^a$uM7=qc*#U6X|9VcZS9dqW; zO?9(x=zVlK+_GHIj%ha4Iv9D|=H}o43dAAA6Z5*Q0NfH9$pOQH{4Y|n-F%v ziDg2|TfoWpVZaVgbYy}87~5%GOcB@M4G8OdC@~br&L1@~o_5 z_wL;*8K2+rChGoulWG&a?3tf3h`bFMgkKEuh?JC+MiBQw58XU`1QxQ@>qrkAmNuPq zVnF|QyO@`hI-vTv#G6Vg0F17*-^O6&+k75o@r?~w2|=7q()D9{Mv!l0bP-8u3RX!| z6R=A}-`#Ih0^bGA^~lszWxPW0vpE38c@H0^beW*%(_(Ubr^}Dl2PL7TA#7O1EHk_Oh$Y7PU zDjx-0@%^pT98tJ}9ME)P^&cdCa5ee5LysW&y|8ACU|x6r+E~*pLOtqx;SYLBnc|q zck8$LK`AU-^)^0UwiBnJrM2VHhsp%06Y5alKKkGXr1O<4R}4T*?q_|MfsT=}eDDTz zj5Mii`9=DEDN8|LnX_%p`VBi!@-R9BaQwLhfHt~)9Jslh3mBUVI6)38g9MA+SQ!-w{KHIzExtH$z0@43$Vu1 zCr>s(v)A06O~0+A`6H(aO(m{1xI_3J+y?Ofab0unL>Ik~OCH(t=> z*)l*_0z~1+n7Vi{&vN8*c4-ebrQ2*W+S-v|(cn+L!0e5UjjMCQ<_ArFOPJ&_m9_VV z^bM|O=#&**eEs^h>1YJ$`Vkenj(7Q5b3o2Y8V)LCd*r1q`HM!Crps*@!{~;5T>SfF^%pAvQ8o->qTbpsug}?Ndj5RW7Pw&ThA6)qRT5P9qZ=1K681DFK~8kcHY4esG9i+d&_j=Q#Or%Hz_n_94%W z_Mx+v(rk`*{m5azGV!GWj89QD_L z-mAW5^Y4>LC2o*!T4}nuhrbZ4+(Y_3IZoJ<0^stR6Af@V^gffnO9f^edY`^j{6aB?b#9>5h$9`QS8XXvS&+{QF4=NfqPVqt)7Ix&1_ zDUQ|?ZM+A6+@^06fOgQG2$FB_*x1&qq{s8; z?=?>2kGsyjG;|5^jg042R#U6WFs}0QfDLp6;)4I;n|&i*Y#Gj>wo=a`Nr6sag5L4y z-G2fIp!fN4lKz0szkK~M{XZ}So=7l!=-T>S3UP&ao2wM+LB-e>DVl`GMz*h4p<}4e z{zOxIJ8vP>nuy~8#15!DaLCXWr4E7T%i%}bc?}_;aq{a@62a~&Gu^a_cKy8oD9t@? z?4Mc=Y7Nj^^@M*iFTgjm7FMcgp)@t2W$qt9K(kw@XhZD?eT{?~ZY#`8iNoDzI~l`X z05&I_)OQ<0Fk+fKdPhfZ8z7{=s_U{-YN0vcq4%ngD|*;uF6c_^0sO6WY$EWxVDlBwSO;}Cim50;`3S#Mgxlq} zH+V*BcbLorTUG`jt1LUnFv~%}`Dn_RrB>9GyO>cC)&SP#e)is|x5SX#sY#GjJrcF9 z1Ve<(7noKbg5bDBTwGk3Hrj>fOGf5K^Uby2ClHPuh6X%A@WL^j~gKZ?q7i7KrZYo1&h-cmZV4c1ge1o(#R+ot>S~Y6*1*>F@UJo%*ftS52OrkbK~PyI~DP%_PgZ4 zm9ke0SYhHFEQo8W>ck(A8Eq)LSnQ#DkSkhg{zlOJ_;{;}oFeRI@;^Mb;EY{FVOi)W zUF$-VYQ2}wwLy&sIDaMPu;j{I?6Ao!;4;H*Dzn^I@GiK(1F~ofZmK0vX8heulG`LM z%-%R25EeVY7QAx-79HuMfdu_I;eB;A>C)S+aSe=Fdt;B=?Vl;&R>QY^7H|F4S_0;r z6seK2-cvFn4DpSU5>=Ze@ae1K0X_lO912|@`r1Ri2NbiDdqKo z-ALopbZv*bKPDNf4Si)nR|+WE#BKry015JOyCFFLO3rEcSp6ZK-NM90P_E!6b9?<7 zhRa`RBmy*izPv|yT(Y5dh<;Qe&51p56_)RNKZJ-q(hpI-N}h-x!AnYkH;6$0#3JtY zfKT`j6k|(g@o(O^yqJr@N4LtHxU}asyClmEj%e5^#2`O8hl*HN57E~+Oa4+%$eq6P z5`ccxJQsCXQ1Q3`2T(HELu`CGJk@uabtKSLL4XPnlmbButa4|o!vaB(;oEIh1+Yio>>|82#ouk}EeWJm_wV2Lv+k7# z^uq_*!3tbv8@syBph|zO7}q|*GLzG@xB<9KU41j~Bf(hNGdF7ocO92#Z)&;)xe_E1 z<+;{e@B?9-5)!=8G$(%wEfkcmggiL-Az1C=MP~476pXEpKxC1=9WY%+$NcV@$rjoT z#3MZYC~MsgP9J%)wtEJ7FOIO*RaRs^U3_H)7(8?-*gEI{_5A&{F@|b8JM*2=`a549 z0O>2m@q%iLBdk8V1*!91borR?$}F`wBf$zwfbJ?OVB8$V3r%$Zx0s4VQOJ@;AJfyY zDiikYFc68a^&7%oO{u-u_UTjU0RBl*(tEn^Z2=B@iY8{ERxMv$1{)(nbx7gVcn86s zr9C84rr|FU5fP;p71u;aIrm-qd0Vr)6dzDmEum>(OUv&~0}rorm3X2M*?~k>ue0`zzM^Z3w_?^v#EyBmZ8U`}FK3HmV z)=(rWw8jLAOv4rdi#kQjRqr#8Z{6AqhH%By)X21ouMo+6*vmzRNMY|MQ-I zYCw0-W$G|+6yDw&-T#t4kmA2?$b>Mi(0l_8)}Z8&Q*{b{b__7~uU~IKBQz7JbIMVk ziwI@{9bIhZZLbv|%0M9wo?dEg*$zJESe@|)5jGTZK=xoEPdfrsGYDhJ5GMMtei57V zvgfx%PcI-JZ`=?>d#=of4~NaUD6V#otf*GpG(UYrPa}%L)c8h+0p76Po{TkF5 zZNj^EEE~cC2y^ga5t+n%g-e*f=zox4w7$L^>@eP13Ql^Ofapp<_Q4sZt)mkF>OjDr z5wSJAx&RaiGu|aDpkc5A0f*;FD8dYMm1st1Lk3UcX#Z7xuHrrbrDGVzJU#T=(jokHmOz8tW^CoSDv0#fj1hsTdYfalm@RSaFva7(!< zQM;it@D7UoHcL?Ldgq+d)Lb4fUgbk_59pix-|sXGuf(8QEKq^;E=9|{&px+?E)L$5 z@dN-`AT4fbG{Q=<+7|V*8t0&hrhf^ZaxR#a{Z@4S+P6DX)N8&*)gInrdlS0%pP#*N- zt2q3@QlORA1N1>8F((M$#?y?UEQJ7oXcYE*T^^8xS1vG9{KuZ{mW}uQ51aA{H|u{$ zL%!hy^hDqd7b4wdl@=9F|1VGZ|Gm}!UBG{F{(qT8BdGJVwV}hOWG3dRFf`4vhaE^t z-vin{&u=Yp0MGx3RS1pN5fJuou?lDi=&!xmJ1vUwH)GC%2%4UHBPCsUgGU3NK(I?j zb`^w9r1mD!(xwK1wf~|`p=l7U%8Hv=z zeUEjb8zJlS6}dJXt#t@}jW_7sx&=Pb z#N>H@XW{|KI)QRS#6SRdMpLZMhx})xsCe^qz4;Yh?gM$I7uG0{58>Dhvwr8;T#X+tS)Pt>HygUB&i}jx0qo8*g9S9WM-xSV;SVE<-TZ2)PvW zP=3~Q-(L=Ch6RD5HQOZfsvQK*V=zW9AnlM(bj?ug+ZZA|@GHn269Cslr{%7}d!w#B z&|O=9(IfKho*v2{FOZ~$e{+ZxPI|5`u5H$^J#;^kWm7u5Ds$5*1y%XivIbuN2P(+= AqyPW_ diff --git a/keyboards/s60_x/keymaps/bluebear/S60X-Bluebear-MOUSE-Layer.png b/keyboards/s60_x/keymaps/bluebear/S60X-Bluebear-MOUSE-Layer.png index c74348389d9dd947bd86552851dca0c7dbb271d3..4e92a60c761c8401b667a5a8e8ac591a9b85d4ab 100644 GIT binary patch literal 16499 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 literal 16119 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 u>d&Jn4b9oN)CNu|BJ9A1!A^F6Wd;bH2BSuXC diff --git a/keyboards/s60_x/keymaps/bluebear/keymap.c b/keyboards/s60_x/keymaps/bluebear/keymap.c index 3be39c3fa..44ebb5aad 100644 --- a/keyboards/s60_x/keymaps/bluebear/keymap.c +++ b/keyboards/s60_x/keymaps/bluebear/keymap.c @@ -3,11 +3,12 @@ // Keyboard Layers enum keyboard_layers { - BASE, //Base Layer - ARROWFN, //Arrow/FN Layer - MOUSE, //Mouse Layer - MIDI, //Midi Layer - MORSE, //Morse Code Layer + BASE, //Base Layer + ARROWFN, //Arrow/FN Layer + MOUSE, //Mouse Layer + MIDI_BASE, //Midi Layer + MIDI_CHORDS, //Midi Chord Layer + MORSE, //Morse Code Layer }; // Midi Chords @@ -15,6 +16,8 @@ enum keyboard_layers { enum midi_chord_modes { //ACTION_FUNCTION id major, minor, + dom_seventh, + dim_seventh, }; enum midi_chord_root { //ACTION_FUNCTION opt @@ -78,6 +81,46 @@ enum midi_chord_id { //ACTION_FUNCTION Progmem Id AsMinor, BbMinor = AsMinor, BMinor, + + //Dominant Seventh Chords + + CDom7, + CsDom7, + DbDom7 = CsDom7, + DDom7, + DsDom7, + EbDom7 = DsDom7, + EDom7, + FDom7, + FsDom7, + GbDom7 = FsDom7, + GDom7, + GsDom7, + AbDom7 = GsDom7, + ADom7, + AsDom7, + BbDom7 = AsDom7, + BDom7, + + //Diminished Seventh Chords + + CDim7, + CsDim7, + DbDim7 = CsDim7, + DDim7, + DsDim7, + EbDim7 = DsDim7, + EDim7, + FDim7, + FsDim7, + GbDim7 = FsDim7, + GDim7, + GsDim7, + AbDim7 = GsDim7, + ADim7, + AsDim7, + BbDim7 = AsDim7, + BDim7, }; enum midi_chord_keycodes { //Midi Chocd Keycodes @@ -121,6 +164,46 @@ enum midi_chord_keycodes { //Midi Chocd Keycodes MI_CH_Asm = F(AsMinor), MI_CH_Bbm = MI_CH_Asm, MI_CH_Bm = F(BMinor), + + //Dominant Seventh Keycodes + + MI_CH_CDom7 = F(CDom7), + MI_CH_CsDom7 = F(CsDom7), + MI_CH_DbDom7 = MI_CH_CsDom7, + MI_CH_DDom7 = F(DDom7), + MI_CH_DsDom7 = F(DsDom7), + MI_CH_EbDom7 = MI_CH_DsDom7, + MI_CH_EDom7 = F(EDom7), + MI_CH_FDom7 = F(FDom7), + MI_CH_FsDom7 = F(FsDom7), + MI_CH_GbDom7 = MI_CH_FsDom7, + MI_CH_GDom7 = F(GDom7), + MI_CH_GsDom7 = F(GsDom7), + MI_CH_AbDom7 = MI_CH_GsDom7, + MI_CH_ADom7 = F(ADom7), + MI_CH_AsDom7 = F(AsDom7), + MI_CH_BbDom7 = MI_CH_AsDom7, + MI_CH_BDom7 = F(BDom7), + + //Diminished Seventh Keycodes + + MI_CH_CDim7 = F(CDim7), + MI_CH_CsDim7 = F(CsDim7), + MI_CH_DbDim7 = MI_CH_CsDim7, + MI_CH_DDim7 = F(DDim7), + MI_CH_DsDim7 = F(DsDim7), + MI_CH_EbDim7 = MI_CH_DsDim7, + MI_CH_EDim7 = F(EDim7), + MI_CH_FDim7 = F(FDim7), + MI_CH_FsDim7 = F(FsDim7), + MI_CH_GbDim7 = MI_CH_FsDim7, + MI_CH_GDim7 = F(GDim7), + MI_CH_GsDim7 = F(GsDim7), + MI_CH_AbDim7 = MI_CH_GsDim7, + MI_CH_ADim7 = F(ADim7), + MI_CH_AsDim7 = F(AsDim7), + MI_CH_BbDim7 = MI_CH_AsDim7, + MI_CH_BDim7 = F(BDim7), }; //Morse Code Macro Keys @@ -202,7 +285,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { /* 1: Arrow/FN Layer ┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐ - │ │ F1 │ F2 │ F3 │ F4 │ F5 │ F6 │ F7 │ F8 │ F9 │ F10 │ F11 │ F12 │TO(3)│TO(4)│ + │ │ F1 │ F2 │ F3 │ F4 │ F5 │ F6 │ F7 │ F8 │ F9 │ F10 │ F11 │ F12 │TO(3)│TO(5)│ ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ │ │ │ │ │ │ │ │PGUP │ UP │ │ │ │ INS │ DEL │█████│ ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ @@ -215,7 +298,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { */ [ARROWFN] = KEYMAP( - KC_TRNS, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, TO(3), TO(4), \ + KC_TRNS, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, TO(3), TO(5), \ KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_PGUP, KC_UP, KC_NO, KC_NO, KC_NO, KC_INS, KC_DEL, \ KC_CAPS, KC_HOME, KC_NO, KC_END, KC_NO, KC_NO, KC_NO, KC_LEFT, KC_DOWN, KC_RIGHT, KC_NO, KC_NO, KC_NO, KC_TRNS, \ KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_SPACE, KC_PGDN, KC_PSCR, KC_SLCK, KC_PAUS, KC_NO, KC_NO, KC_NO, \ @@ -225,7 +308,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { /* 2: Mouse Keys Layer ┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐ - │RESET│ F1 │ F2 │ F3 │ F4 │ F5 │ F6 │ F7 │ F8 │ F9 │ F10 │ F11 │ F12 │ │ │ + │RESET│ F13 │ F14 │ F15 │ F16 │ F17 │ F18 │ F19 │ F20 │ F21 │ F22 │ F23 │ F24 │ │ │ ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ │DEBUG│ │ │ │ │ │ │BTN1 │MS_UP│BTN2 │WH_UP│ │ │ │█████│ ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ @@ -239,37 +322,60 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { [MOUSE] = KEYMAP( - RESET, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_NO, KC_NO, \ + RESET, KC_F13, KC_F14, KC_F15, KC_F16, KC_F17, KC_F18, KC_F19, KC_F20, KC_F21, KC_F22, KC_F23, KC_F24, KC_NO, KC_NO, \ DEBUG, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_BTN1, KC_MS_UP, KC_BTN2, KC_WH_U, KC_NO, KC_NO, KC_NO, \ KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_MS_LEFT, KC_MS_DOWN, KC_MS_RIGHT, KC_WH_D, KC_BTN3, KC_NO, KC_NO, \ KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, \ KC_TRNS, KC_NO, KC_NO, KC_POWER, KC_NO, KC_NO, KC_NO, KC_NO ), - /* 3: Midi Layer + /* 3: Midi Base Layer ┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐ - │TO(0)│ Cmaj│ Gmaj│ Dmaj│ Amaj│ Emaj│ Bmaj│Gbmaj│Dbmaj│Abmaj│Ebmaj│Bbmaj│ Fmaj│ │ │ + │TO(0)│ Cmaj│ Gmaj│ Dmaj│ Amaj│ Emaj│ Bmaj│Gbmaj│Dbmaj│Abmaj│Ebmaj│Bbmaj│ Fmaj│ │TO(4)│ ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ - │ │ │ C# │ D# │ │ F# │ G# │ A# │ │ C# │ D# │ │ │ │█████│ + │OCT+ │ │ C# │ D# │ │ F# │ G# │ A# │ │ C# │ D# │ │ │ │█████│ ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ - │OCT- │ C │ D │ E │ F │ G │ A │ B │ C │ D │ E │ F │▒▒▒▒▒│OCT+ │█████│ + │OCT- │ C │ D │ E │ F │ G │ A │ B │ C │ D │ E │ F │▒▒▒▒▒│ │█████│ ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ - │ Am │▒▒▒▒▒│ Em │ Bm │ F#m │ C#m │ G#m │ D#m │ Bbm │ Fm │ Cm │ Gm │▒▒▒▒▒│ Dm │▒▒▒▒▒│ + │ Cm │▒▒▒▒▒│ Gm │ Dm │ Am │ Em │ Bm │ Gbm │ Dbm │ Abm │ Ebm │ Bbm │▒▒▒▒▒│ Fm │▒▒▒▒▒│ ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ │ │ │ │█████│█████│█████│A-OFF│█████│█████│█████│ │ │ │ │█████│ └─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┘ */ - [MIDI] = KEYMAP( - TO(0), MI_CH_C, MI_CH_G, MI_CH_D, MI_CH_A, MI_CH_E, MI_CH_B, MI_CH_Gb, MI_CH_Db, MI_CH_Ab, MI_CH_Eb, MI_CH_Bb, MI_CH_F, KC_NO, KC_NO, \ - KC_NO, KC_NO, MI_Cs, MI_Ds, KC_NO, MI_Fs, MI_Gs, MI_As, KC_NO, MI_Cs_1, MI_Ds_1, KC_NO, KC_NO, KC_NO, \ - MI_OCTD, MI_C, MI_D, MI_E, MI_F, MI_G, MI_A, MI_B, MI_C_1, MI_D_1, MI_E_1, MI_F_1, KC_NO, MI_OCTU, \ - MI_CH_Am, KC_NO, MI_CH_Em, MI_CH_Bm, MI_CH_Fsm, MI_CH_Csm, MI_CH_Gsm, MI_CH_Dsm, MI_CH_Bbm, MI_CH_Fm, MI_CH_Cm, MI_CH_Gm, KC_NO, MI_CH_Dm, KC_NO, \ - KC_NO, KC_NO, KC_NO, MI_ALLOFF, KC_NO, KC_NO, KC_NO, KC_NO - ), + [MIDI_BASE] = KEYMAP( + TO(0), MI_CH_C, MI_CH_G, MI_CH_D, MI_CH_A, MI_CH_E, MI_CH_B, MI_CH_Gb, MI_CH_Db, MI_CH_Ab, MI_CH_Eb, MI_CH_Bb, MI_CH_F, KC_NO, TO(4), \ + MI_OCTU, KC_NO, MI_Cs, MI_Ds, KC_NO, MI_Fs, MI_Gs, MI_As, KC_NO, MI_Cs_1, MI_Ds_1, KC_NO, KC_NO, KC_NO, \ + MI_OCTD, MI_C, MI_D, MI_E, MI_F, MI_G, MI_A, MI_B, MI_C_1, MI_D_1, MI_E_1, MI_F_1, KC_NO, KC_NO, \ + MI_CH_Cm, KC_NO, MI_CH_Gm, MI_CH_Dm, MI_CH_Am, MI_CH_Em, MI_CH_Bm, MI_CH_Gbm, MI_CH_Dbm, MI_CH_Abm, MI_CH_Ebm, MI_CH_Bbm, KC_NO, MI_CH_Fm, KC_NO, \ + KC_NO, KC_NO, KC_NO, MI_ALLOFF, KC_NO, KC_NO, KC_NO, KC_NO + ), - /* 4: Morse Code Layer + /* 4: Midi Chord Layer + + ┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐ + │TO(0)│ Cmaj│ Gmaj│ Dmaj│ Amaj│ Emaj│ Bmaj│Gbmaj│Dbmaj│Abmaj│Ebmaj│Bbmaj│ Fmaj│TO(3)│ │ + ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ + │OCT+ │ Cm │ Gm │ Dm │ Am │ Em │ Bbm │ Gbm │ Dbm │ Abm │ Ebm │ Bbm │ Fm │ │█████│ + ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ + │OCT- │Cdom7│Gdom7│Ddom7│Adom7│Edom7│Bdom7│Gbdo7│Dbdo7│Abdo7│Ebdo7│Bbdo7│▒▒▒▒▒│Fdom7│█████│ + ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ + │Cdim7│▒▒▒▒▒│Gdim7│Ddim7│Adim7│Edim7│Bdim7│Gbdi7│Dbdi7│Abdi7│Ebdi7│Bbdi7│▒▒▒▒▒│Fdim7│▒▒▒▒▒│ + ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ + │ │ │ │█████│█████│█████│A-OFF│█████│█████│█████│ │ │ │ │█████│ + └─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┘ + */ + + [MIDI_CHORDS] = KEYMAP( + TO(0), MI_CH_C, MI_CH_G, MI_CH_D, MI_CH_A, MI_CH_E, MI_CH_B, MI_CH_Gb, MI_CH_Db, MI_CH_Ab, MI_CH_Eb, MI_CH_Bb, MI_CH_F, TO(3), KC_NO, \ + MI_OCTU, MI_CH_Cm, MI_CH_Gm, MI_CH_Dm, MI_CH_Am, MI_CH_Em, MI_CH_Bbm, MI_CH_Gbm, MI_CH_Dbm, MI_CH_Abm, MI_CH_Ebm, MI_CH_Bbm, MI_CH_Fm, KC_NO, \ + MI_OCTD, MI_CH_CDom7, MI_CH_GDom7, MI_CH_DDom7, MI_CH_ADom7, MI_CH_EDom7, MI_CH_BDom7, MI_CH_GbDom7, MI_CH_DbDom7, MI_CH_AbDom7, MI_CH_EbDom7, MI_CH_BbDom7, KC_NO, MI_CH_FDom7, \ + MI_CH_CDim7, KC_NO, MI_CH_GDim7, MI_CH_DDim7, MI_CH_ADim7, MI_CH_EDim7, MI_CH_BDim7, MI_CH_GbDim7, MI_CH_DbDim7, MI_CH_AbDim7, MI_CH_EbDim7, MI_CH_BbDim7, KC_NO, MI_CH_FDim7, KC_NO, \ + KC_NO, KC_NO, KC_NO, MI_ALLOFF, KC_NO, KC_NO, KC_NO, KC_NO + ), + + /* 5: Morse Code Layer ┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐ │TO(0)│ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ │ │ │ │ @@ -720,6 +826,36 @@ const uint16_t PROGMEM fn_actions[] = { [AMinor] = ACTION_FUNCTION_OPT(minor, A), [AsMinor] = ACTION_FUNCTION_OPT(minor, As), [BMinor] = ACTION_FUNCTION_OPT(minor, B), + + //Dominant 7th + + [CDom7] = ACTION_FUNCTION_OPT(dom_seventh, C), + [CsDom7] = ACTION_FUNCTION_OPT(dom_seventh, Cs), + [DDom7] = ACTION_FUNCTION_OPT(dom_seventh, D), + [DsDom7] = ACTION_FUNCTION_OPT(dom_seventh, Ds), + [EDom7] = ACTION_FUNCTION_OPT(dom_seventh, E), + [FDom7] = ACTION_FUNCTION_OPT(dom_seventh, F), + [FsDom7] = ACTION_FUNCTION_OPT(dom_seventh, Fs), + [GDom7] = ACTION_FUNCTION_OPT(dom_seventh, G), + [GsDom7] = ACTION_FUNCTION_OPT(dom_seventh, Gs), + [ADom7] = ACTION_FUNCTION_OPT(dom_seventh, A), + [AsDom7] = ACTION_FUNCTION_OPT(dom_seventh, As), + [BDom7] = ACTION_FUNCTION_OPT(dom_seventh, B), + + //Diminished 7th + + [CDim7] = ACTION_FUNCTION_OPT(dim_seventh, C), + [CsDim7] = ACTION_FUNCTION_OPT(dim_seventh, Cs), + [DDim7] = ACTION_FUNCTION_OPT(dim_seventh, D), + [DsDim7] = ACTION_FUNCTION_OPT(dim_seventh, Ds), + [EDim7] = ACTION_FUNCTION_OPT(dim_seventh, E), + [FDim7] = ACTION_FUNCTION_OPT(dim_seventh, F), + [FsDim7] = ACTION_FUNCTION_OPT(dim_seventh, Fs), + [GDim7] = ACTION_FUNCTION_OPT(dim_seventh, G), + [GsDim7] = ACTION_FUNCTION_OPT(dim_seventh, Gs), + [ADim7] = ACTION_FUNCTION_OPT(dim_seventh, A), + [AsDim7] = ACTION_FUNCTION_OPT(dim_seventh, As), + [BDim7] = ACTION_FUNCTION_OPT(dim_seventh, B), }; void action_function(keyrecord_t *record, uint8_t id, uint8_t opt) { @@ -764,19 +900,30 @@ void action_function(keyrecord_t *record, uint8_t id, uint8_t opt) { } uint16_t major_third = root_note + 4; uint16_t minor_third = root_note + 3; + //uint16_t flat_fifth = root_note + 6; uint16_t fifth = root_note + 7; + uint16_t minor_seventh = root_note + 10; + uint16_t diminished_seventh = root_note -3; switch (id) { case major: //Major chord - dprintf("Root Note:%d - Major Third:%d - Fifth:%d\n", root_note, major_third, fifth); process_midi(root_note, record); process_midi(major_third, record); process_midi(fifth, record); break; case minor: //Minor chord - dprintf("Root Note:%d - Minor Third:%d - Fifth:%d\n", root_note, minor_third, fifth); process_midi(root_note, record); process_midi(minor_third, record); process_midi(fifth, record); break; + case dom_seventh: //Dominant Seventh chord + process_midi(root_note, record); + process_midi(major_third, record); + process_midi(minor_seventh, record); + break; + case dim_seventh: //Diminished Seventh Chord + process_midi(root_note, record); + process_midi(minor_third, record); + process_midi(diminished_seventh, record); + break; } } diff --git a/keyboards/s60_x/keymaps/bluebear/readme.md b/keyboards/s60_x/keymaps/bluebear/readme.md index 579683abc..9a70cde96 100644 --- a/keyboards/s60_x/keymaps/bluebear/readme.md +++ b/keyboards/s60_x/keymaps/bluebear/readme.md @@ -1,25 +1,75 @@ -## Bluebear’s custom S60X layout +# Bluebear’s custom S60X layout Custom keyboard layout for my S60X, my first ever custom mechanical keyboard kit. This layout was inspired in part by the HHKB line of keyboards and a quest to find the perfect ergonomic, logical layout for what I do. If you like this layout, please feel free to use it, modify it and share it. -## Base Layer +## BASE Layer +![BASE Layer](S60X-Bluebear-BASE-Layer.png) + +-Dvorak keyboard layout -Hold left control key for LCTL, and tap it for ESC -Hold enter key for RCTL and tap for ENT --Hold the space key to momentarily switch to [ARROW] layer --Left bottom key acts as momentary switch to the [MOUSE] layer +-Hold the space key to momentarily switch to ARROWFN layer +-Left bottom key acts as momentary switch to the MOUSE layer -Hold right alt key for AltGr and tap for APP(which I have mapped to Compose in OS) -Hold left shift key for LSFT and tap for ( (Space Cadet style) -Hold right shift key for RSFT and tap for ) (Space Cadet style) -Tap key on bottom row, second from the right (where APP usually is) to get CTL-Shift (one shot modifier - next key pressed will be modified by ctl-shift) -Tap key on bottom right to get CTL-Alt (one shot modifier - next key pressed will be modified by ctl-alt) -## Mouse Layer +## ARROWFN Layer +![ARROWFN Layer](S60X-Bluebear-ARROWFN-Layer.png) + +-Number row becomes F1 to F12 +-C, T, H, N keys become Up, Down, Left, Right +-Access to various other keys normally found on a full sized keyboard +-Top right button toggles MORSE layer +-Second from right, top row, toggles MIDI_BASE layer + +## MOUSE Layer + +![MOUSE Layer](S60X-Bluebear-MOUSE-Layer.png) + +-Move the mouse with mouse keys -Hitting the escape key in this layer will give RESET, which puts the controller into dfu mode for flashing firmware onto it -Hitting the space key in this layer is like hitting power button on computer +-Hitting the tab button toggles caps lock +-Number row becomes F13 to F24 + +## MIDI_BASE Layer + +![MIDI_BASE Layer](S60X-Bluebear-MIDI_BASE-Layer.png) + +This layer was inspired by the Satan Midi layout (https://github.com/qmk/qmk_firmware/tree/master/keyboards/satan/keymaps/midi) and gives access to basic MIDI notes. What I added were two layers of MIDI chords (major and minor triads) arranged in a circle of fifths pattern. Thanks to @fredizzimo for helping me with the code for these chords. + +-Top right button toggles MORSE_CHORDS layer +-Escape brings you back to the BASE layer + +## MIDI_CHORDS Layer + +![MIDI_CHORDS Layer](S60X-Bluebear-MIDI_CHORDS-Layer.png) + +After figuring out how to code my MIDI chord function, I decided to dedicate a full layer to these chords. This chord layout was inspired by the Stradella Base system (https://en.wikipedia.org/wiki/Stradella_bass_system) found on accordions. This layer is a tool for musical composition and songwriting. + +-Second from right, top row, toggles MIDI_BASE layer +-Escape brings you back to the BASE layer + +## MORSE LAYER + +![MORSE Layer](S60X-Bluebear-MORSE-Layer.png) + +This layer is really just for fun, and because I am a ham radio operator and morse code enthusiast. Hitting the alphanumerical keys in this layer will send a series of dits (.) and dahs (-) representing that character in morse code. + +-Escape brings you back to the BASE layer + +### THIS IS STILL A WORK IN PROGRESS + +This keyboard layout is still a work in progress and there are a couple of kinks left to iron out. But it is still very usable and the midi and morse code layers are lots of fun to use. Please feel free to use, share and improve all, or part of this layout. + + From 1ef911d150e361668be72e0082ade728a199e889 Mon Sep 17 00:00:00 2001 From: Ante Laurijssen Date: Mon, 29 May 2017 22:11:48 -0400 Subject: [PATCH 049/238] Added a few images --- .../bluebear/120-button_Stradella_chart.svg | 5190 +++++++++++++++++ .../S60X-Bluebear-MIDI_BASE-Layer.png | Bin 0 -> 22521 bytes .../S60X-Bluebear-MIDI_CHORD-Layer.png | Bin 0 -> 23687 bytes 3 files changed, 5190 insertions(+) create mode 100644 keyboards/s60_x/keymaps/bluebear/120-button_Stradella_chart.svg create mode 100644 keyboards/s60_x/keymaps/bluebear/S60X-Bluebear-MIDI_BASE-Layer.png create mode 100644 keyboards/s60_x/keymaps/bluebear/S60X-Bluebear-MIDI_CHORD-Layer.png diff --git a/keyboards/s60_x/keymaps/bluebear/120-button_Stradella_chart.svg b/keyboards/s60_x/keymaps/bluebear/120-button_Stradella_chart.svg new file mode 100644 index 000000000..bd878faa1 --- /dev/null +++ b/keyboards/s60_x/keymaps/bluebear/120-button_Stradella_chart.svg @@ -0,0 +1,5190 @@ + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/keyboards/s60_x/keymaps/bluebear/S60X-Bluebear-MIDI_BASE-Layer.png b/keyboards/s60_x/keymaps/bluebear/S60X-Bluebear-MIDI_BASE-Layer.png new file mode 100644 index 0000000000000000000000000000000000000000..58ad1605f0324229ff9ba3c84ac5350bb61df90b GIT binary patch literal 22521 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 TJmxv@bF$M)>WZoI`riKscXTD} literal 0 HcmV?d00001 diff --git a/keyboards/s60_x/keymaps/bluebear/S60X-Bluebear-MIDI_CHORD-Layer.png b/keyboards/s60_x/keymaps/bluebear/S60X-Bluebear-MIDI_CHORD-Layer.png new file mode 100644 index 0000000000000000000000000000000000000000..74a373ae225018269919e1f18fbebab25bf4c35e GIT binary patch literal 23687 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 Z^81DLsEu?5`jCG(BX?dlSz6om{{Wy;U(x^o literal 0 HcmV?d00001 From cd4ccee703770bf5dce977f539e53f30e139313d Mon Sep 17 00:00:00 2001 From: Ante Laurijssen Date: Mon, 29 May 2017 22:13:52 -0400 Subject: [PATCH 050/238] Corrected typo in readme.md --- keyboards/s60_x/keymaps/bluebear/readme.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/keyboards/s60_x/keymaps/bluebear/readme.md b/keyboards/s60_x/keymaps/bluebear/readme.md index 9a70cde96..50af6d835 100644 --- a/keyboards/s60_x/keymaps/bluebear/readme.md +++ b/keyboards/s60_x/keymaps/bluebear/readme.md @@ -48,9 +48,9 @@ This layer was inspired by the Satan Midi layout (https://github.com/qmk/qmk_fir -Top right button toggles MORSE_CHORDS layer -Escape brings you back to the BASE layer -## MIDI_CHORDS Layer +## MIDI_CHORD Layer -![MIDI_CHORDS Layer](S60X-Bluebear-MIDI_CHORDS-Layer.png) +![MIDI_CHORD Layer](S60X-Bluebear-MIDI_CHORDS-Layer.png) After figuring out how to code my MIDI chord function, I decided to dedicate a full layer to these chords. This chord layout was inspired by the Stradella Base system (https://en.wikipedia.org/wiki/Stradella_bass_system) found on accordions. This layer is a tool for musical composition and songwriting. From 06684555d21059e55a549fc6c24936920e35f965 Mon Sep 17 00:00:00 2001 From: Ante Laurijssen Date: Mon, 29 May 2017 22:16:17 -0400 Subject: [PATCH 051/238] Another typo... --- keyboards/s60_x/keymaps/bluebear/readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/keyboards/s60_x/keymaps/bluebear/readme.md b/keyboards/s60_x/keymaps/bluebear/readme.md index 50af6d835..6f54d4d58 100644 --- a/keyboards/s60_x/keymaps/bluebear/readme.md +++ b/keyboards/s60_x/keymaps/bluebear/readme.md @@ -50,7 +50,7 @@ This layer was inspired by the Satan Midi layout (https://github.com/qmk/qmk_fir ## MIDI_CHORD Layer -![MIDI_CHORD Layer](S60X-Bluebear-MIDI_CHORDS-Layer.png) +![MIDI_CHORD Layer](S60X-Bluebear-MIDI_CHORD-Layer.png) After figuring out how to code my MIDI chord function, I decided to dedicate a full layer to these chords. This chord layout was inspired by the Stradella Base system (https://en.wikipedia.org/wiki/Stradella_bass_system) found on accordions. This layer is a tool for musical composition and songwriting. From fbaf964a854a8fc754871730deb219ab48fd6937 Mon Sep 17 00:00:00 2001 From: Ante Laurijssen Date: Tue, 30 May 2017 21:27:00 -0400 Subject: [PATCH 052/238] Improvements to Midi and keymap --- keyboards/s60_x/keymaps/bluebear/keymap.c | 114 +++++++++++----------- 1 file changed, 57 insertions(+), 57 deletions(-) diff --git a/keyboards/s60_x/keymaps/bluebear/keymap.c b/keyboards/s60_x/keymaps/bluebear/keymap.c index 44ebb5aad..87a792a01 100644 --- a/keyboards/s60_x/keymaps/bluebear/keymap.c +++ b/keyboards/s60_x/keymaps/bluebear/keymap.c @@ -13,14 +13,14 @@ enum keyboard_layers { // Midi Chords -enum midi_chord_modes { //ACTION_FUNCTION id +enum midi_chord_modes { //ACTION_FUNCTION opt major, minor, dom_seventh, dim_seventh, }; -enum midi_chord_root { //ACTION_FUNCTION opt +enum midi_chord_root { //ACTION_FUNCTION id C, Cs, Db = Cs, @@ -301,8 +301,8 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { KC_TRNS, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, TO(3), TO(5), \ KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_PGUP, KC_UP, KC_NO, KC_NO, KC_NO, KC_INS, KC_DEL, \ KC_CAPS, KC_HOME, KC_NO, KC_END, KC_NO, KC_NO, KC_NO, KC_LEFT, KC_DOWN, KC_RIGHT, KC_NO, KC_NO, KC_NO, KC_TRNS, \ - KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_SPACE, KC_PGDN, KC_PSCR, KC_SLCK, KC_PAUS, KC_NO, KC_NO, KC_NO, \ - KC_NO, KC_NO, KC_NO, KC_TRNS, KC_NO, KC_NO, KC_NO, KC_TRNS + KC_TRNS, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_SPACE, KC_PGDN, KC_PSCR, KC_SLCK, KC_PAUS, KC_NO, KC_TRNS, KC_NO, \ + KC_NO, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS ), /* 2: Mouse Keys Layer @@ -324,9 +324,9 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { RESET, KC_F13, KC_F14, KC_F15, KC_F16, KC_F17, KC_F18, KC_F19, KC_F20, KC_F21, KC_F22, KC_F23, KC_F24, KC_NO, KC_NO, \ DEBUG, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_BTN1, KC_MS_UP, KC_BTN2, KC_WH_U, KC_NO, KC_NO, KC_NO, \ - KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_MS_LEFT, KC_MS_DOWN, KC_MS_RIGHT, KC_WH_D, KC_BTN3, KC_NO, KC_NO, \ - KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, \ - KC_TRNS, KC_NO, KC_NO, KC_POWER, KC_NO, KC_NO, KC_NO, KC_NO + KC_LCTL, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_MS_LEFT, KC_MS_DOWN, KC_MS_RIGHT, KC_WH_D, KC_BTN3, KC_NO, KC_TRNS, \ + KC_TRNS, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_TRNS, KC_NO, \ + KC_TRNS, KC_TRNS, KC_TRNS, KC_POWER, KC_TRNS, KC_TRNS, KC_NO, KC_NO ), /* 3: Midi Base Layer @@ -799,68 +799,68 @@ const uint16_t PROGMEM fn_actions[] = { //Major Chords - [CMajor] = ACTION_FUNCTION_OPT(major, C), - [CsMajor] = ACTION_FUNCTION_OPT(major, Cs), - [DMajor] = ACTION_FUNCTION_OPT(major, D), - [DsMajor] = ACTION_FUNCTION_OPT(major, Ds), - [EMajor] = ACTION_FUNCTION_OPT(major, E), - [FMajor] = ACTION_FUNCTION_OPT(major, F), - [FsMajor] = ACTION_FUNCTION_OPT(major, Fs), - [GMajor] = ACTION_FUNCTION_OPT(major, G), - [GsMajor] = ACTION_FUNCTION_OPT(major, Gs), - [AMajor] = ACTION_FUNCTION_OPT(major, A), - [AsMajor] = ACTION_FUNCTION_OPT(major, As), - [BMajor] = ACTION_FUNCTION_OPT(major, B), + [CMajor] = ACTION_FUNCTION_OPT(C, major), + [CsMajor] = ACTION_FUNCTION_OPT(Cs, major), + [DMajor] = ACTION_FUNCTION_OPT(D, major), + [DsMajor] = ACTION_FUNCTION_OPT(Ds, major), + [EMajor] = ACTION_FUNCTION_OPT(E, major), + [FMajor] = ACTION_FUNCTION_OPT(F, major), + [FsMajor] = ACTION_FUNCTION_OPT(Fs, major), + [GMajor] = ACTION_FUNCTION_OPT(G, major), + [GsMajor] = ACTION_FUNCTION_OPT(Gs, major), + [AMajor] = ACTION_FUNCTION_OPT(A, major), + [AsMajor] = ACTION_FUNCTION_OPT(As, major), + [BMajor] = ACTION_FUNCTION_OPT(B, major), //Minor Chords - [CMinor] = ACTION_FUNCTION_OPT(minor, C), - [CsMinor] = ACTION_FUNCTION_OPT(minor, Cs), - [DMinor] = ACTION_FUNCTION_OPT(minor, D), - [DsMinor] = ACTION_FUNCTION_OPT(minor, Ds), - [EMinor] = ACTION_FUNCTION_OPT(minor, E), - [FMinor] = ACTION_FUNCTION_OPT(minor, F), - [FsMinor] = ACTION_FUNCTION_OPT(minor, Fs), - [GMinor] = ACTION_FUNCTION_OPT(minor, G), - [GsMinor] = ACTION_FUNCTION_OPT(minor, Gs), - [AMinor] = ACTION_FUNCTION_OPT(minor, A), - [AsMinor] = ACTION_FUNCTION_OPT(minor, As), - [BMinor] = ACTION_FUNCTION_OPT(minor, B), + [CMinor] = ACTION_FUNCTION_OPT(C, minor), + [CsMinor] = ACTION_FUNCTION_OPT(Cs, minor), + [DMinor] = ACTION_FUNCTION_OPT(D, minor), + [DsMinor] = ACTION_FUNCTION_OPT(Ds, minor), + [EMinor] = ACTION_FUNCTION_OPT(E, minor), + [FMinor] = ACTION_FUNCTION_OPT(F, minor), + [FsMinor] = ACTION_FUNCTION_OPT(Fs, minor), + [GMinor] = ACTION_FUNCTION_OPT(G, minor), + [GsMinor] = ACTION_FUNCTION_OPT(Gs, minor), + [AMinor] = ACTION_FUNCTION_OPT(A, minor), + [AsMinor] = ACTION_FUNCTION_OPT(As, minor), + [BMinor] = ACTION_FUNCTION_OPT(B, minor), //Dominant 7th - [CDom7] = ACTION_FUNCTION_OPT(dom_seventh, C), - [CsDom7] = ACTION_FUNCTION_OPT(dom_seventh, Cs), - [DDom7] = ACTION_FUNCTION_OPT(dom_seventh, D), - [DsDom7] = ACTION_FUNCTION_OPT(dom_seventh, Ds), - [EDom7] = ACTION_FUNCTION_OPT(dom_seventh, E), - [FDom7] = ACTION_FUNCTION_OPT(dom_seventh, F), - [FsDom7] = ACTION_FUNCTION_OPT(dom_seventh, Fs), - [GDom7] = ACTION_FUNCTION_OPT(dom_seventh, G), - [GsDom7] = ACTION_FUNCTION_OPT(dom_seventh, Gs), - [ADom7] = ACTION_FUNCTION_OPT(dom_seventh, A), - [AsDom7] = ACTION_FUNCTION_OPT(dom_seventh, As), - [BDom7] = ACTION_FUNCTION_OPT(dom_seventh, B), + [CDom7] = ACTION_FUNCTION_OPT(C, dom_seventh), + [CsDom7] = ACTION_FUNCTION_OPT(Cs, dom_seventh), + [DDom7] = ACTION_FUNCTION_OPT(D, dom_seventh), + [DsDom7] = ACTION_FUNCTION_OPT(Ds, dom_seventh), + [EDom7] = ACTION_FUNCTION_OPT(E, dom_seventh), + [FDom7] = ACTION_FUNCTION_OPT(F, dom_seventh), + [FsDom7] = ACTION_FUNCTION_OPT(Fs, dom_seventh), + [GDom7] = ACTION_FUNCTION_OPT(G, dom_seventh), + [GsDom7] = ACTION_FUNCTION_OPT(Gs, dom_seventh), + [ADom7] = ACTION_FUNCTION_OPT(A, dom_seventh), + [AsDom7] = ACTION_FUNCTION_OPT(As, dom_seventh), + [BDom7] = ACTION_FUNCTION_OPT(B, dom_seventh), //Diminished 7th - [CDim7] = ACTION_FUNCTION_OPT(dim_seventh, C), - [CsDim7] = ACTION_FUNCTION_OPT(dim_seventh, Cs), - [DDim7] = ACTION_FUNCTION_OPT(dim_seventh, D), - [DsDim7] = ACTION_FUNCTION_OPT(dim_seventh, Ds), - [EDim7] = ACTION_FUNCTION_OPT(dim_seventh, E), - [FDim7] = ACTION_FUNCTION_OPT(dim_seventh, F), - [FsDim7] = ACTION_FUNCTION_OPT(dim_seventh, Fs), - [GDim7] = ACTION_FUNCTION_OPT(dim_seventh, G), - [GsDim7] = ACTION_FUNCTION_OPT(dim_seventh, Gs), - [ADim7] = ACTION_FUNCTION_OPT(dim_seventh, A), - [AsDim7] = ACTION_FUNCTION_OPT(dim_seventh, As), - [BDim7] = ACTION_FUNCTION_OPT(dim_seventh, B), + [CDim7] = ACTION_FUNCTION_OPT(C, dim_seventh), + [CsDim7] = ACTION_FUNCTION_OPT(Cs, dim_seventh), + [DDim7] = ACTION_FUNCTION_OPT(D, dim_seventh), + [DsDim7] = ACTION_FUNCTION_OPT(Ds, dim_seventh), + [EDim7] = ACTION_FUNCTION_OPT(E, dim_seventh), + [FDim7] = ACTION_FUNCTION_OPT(F, dim_seventh), + [FsDim7] = ACTION_FUNCTION_OPT(Fs, dim_seventh), + [GDim7] = ACTION_FUNCTION_OPT(G, dim_seventh), + [GsDim7] = ACTION_FUNCTION_OPT(Gs, dim_seventh), + [ADim7] = ACTION_FUNCTION_OPT(A, dim_seventh), + [AsDim7] = ACTION_FUNCTION_OPT(As, dim_seventh), + [BDim7] = ACTION_FUNCTION_OPT(B, dim_seventh), }; void action_function(keyrecord_t *record, uint8_t id, uint8_t opt) { uint16_t root_note = MIDI_INVALID_NOTE; - switch (opt) { + switch (id) { case C: //Root note C root_note = MI_C; break; @@ -904,7 +904,7 @@ void action_function(keyrecord_t *record, uint8_t id, uint8_t opt) { uint16_t fifth = root_note + 7; uint16_t minor_seventh = root_note + 10; uint16_t diminished_seventh = root_note -3; - switch (id) { + switch (opt) { case major: //Major chord process_midi(root_note, record); process_midi(major_third, record); From 9af272e4bb685faabd1d879231f2718f0c00b32d Mon Sep 17 00:00:00 2001 From: jpetermans Date: Tue, 30 May 2017 21:52:44 -0700 Subject: [PATCH 053/238] Update lock led processing and remove debug msgs --- .../infinity60/keymaps/jpetermans/keymap.c | 1 - keyboards/infinity60/led_controller.c | 32 ++++--------------- keyboards/infinity60/led_controller.h | 3 +- keyboards/infinity60/rules.mk | 2 +- 4 files changed, 10 insertions(+), 28 deletions(-) diff --git a/keyboards/infinity60/keymaps/jpetermans/keymap.c b/keyboards/infinity60/keymaps/jpetermans/keymap.c index cc4633b1b..59249ff72 100644 --- a/keyboards/infinity60/keymaps/jpetermans/keymap.c +++ b/keyboards/infinity60/keymaps/jpetermans/keymap.c @@ -247,7 +247,6 @@ bool process_record_user (uint16_t keycode, keyrecord_t *record) { // Runs just one time when the keyboard initializes. void matrix_init_user(void) { - xprintf("init start"); led_controller_init(); diff --git a/keyboards/infinity60/led_controller.c b/keyboards/infinity60/led_controller.c index 5c177d26b..21f95a9c1 100644 --- a/keyboards/infinity60/led_controller.c +++ b/keyboards/infinity60/led_controller.c @@ -135,7 +135,6 @@ msg_t is31_read_register(uint8_t page, uint8_t reg, uint8_t *result) { * initialise the IS31 chip * ======================== */ void is31_init(void) { - xprintf("_is31_init\n"); // just to be sure that it's all zeroes __builtin_memset(full_page,0,0xB4+1); // zero function page, all registers (assuming full_page is all zeroes) @@ -200,41 +199,33 @@ static THD_FUNCTION(LEDthread, arg) { msg_args[1] = (msg >> 16) & 0XFF; msg_args[2] = (msg >> 24) & 0xFF; - xprintf("msg_type: %d-%d-%d\n", msg_type, msg_args[0], msg_args[1]); switch (msg_type){ case SET_FULL_ROW: - xprintf("FULL ROW: %d-%d\n", msg_args[0], msg_args[1]); //write full byte to pin address, msg_args[1] = pin #, msg_args[0] = 8 bits to write //writes only to currently displayed page write_led_byte(page_status, msg_args[1], msg_args[0]); break; case OFF_LED: - xprintf("OFF: %d-%d\n", msg_args[0], msg_args[1]); //on/off/toggle single led, msg_args[0] = row/col of led, msg_args[1] = page set_led_bit(msg_args[1], control_register_word, msg_args[0], 0); break; case ON_LED: - xprintf("ON: %d-%d\n", msg_args[0], msg_args[1]); set_led_bit(msg_args[1], control_register_word, msg_args[0], 1); break; case TOGGLE_LED: - xprintf("TOGGLE: %d-%d\n", msg_args[0], msg_args[1]); set_led_bit(msg_args[1], control_register_word, msg_args[0], 2); break; case BLINK_OFF_LED: - xprintf("B_on: %d-%d\n", msg_args[0], msg_args[1]); //on/off/toggle single led, msg_args[0] = row/col of led set_led_bit(msg_args[1], control_register_word, msg_args[0], 4); break; case BLINK_ON_LED: - xprintf("B_off: %d-%d\n", msg_args[0], msg_args[1]); set_led_bit(msg_args[1], control_register_word, msg_args[0], 5); break; case BLINK_TOGGLE_LED: - xprintf("B_togg: %d-%d\n", msg_args[0], msg_args[1]); set_led_bit(msg_args[1], control_register_word, msg_args[0], 6); break; @@ -244,12 +235,10 @@ static THD_FUNCTION(LEDthread, arg) { chThdSleepMilliseconds(5); is31_read_register(0, 0x00, &temp); is31_write_register(IS31_FUNCTIONREG, IS31_REG_SHUTDOWN, IS31_REG_SHUTDOWN_OFF); - xprintf("TOGGLE_ALL: %d-%d\n", msg_args[0], msg_args[1]); - xprintf("temp: %d\n", temp); led_control_reg[0] = 0; - //if first leds are already on, toggle frame 0 off + //toggle led mask based on current state (temp) if (temp==0 || page_status > 0) { __builtin_memcpy(led_control_reg+1, all_on_leds_mask, 0x12); } else { @@ -262,13 +251,14 @@ static THD_FUNCTION(LEDthread, arg) { page_status=0; - //maintain lock leds + //maintain lock leds, reset to off and force recheck to blink of all leds toggled on + numlock_status = 0; + capslock_status = 0; led_set(host_keyboard_leds()); } break; case TOGGLE_BACKLIGHT: - xprintf("TOGGLE_BKLT: %d-%d\n", msg_args[0], msg_args[1]); //msg_args[0] = on/off //populate 9 byte rows to be written to each pin, first byte is register (pin) address @@ -287,12 +277,13 @@ static THD_FUNCTION(LEDthread, arg) { case DISPLAY_PAGE: //msg_args[0] = page to toggle on - xprintf("DSPY_PG: %d-%d\n", msg_args[0], msg_args[1]); if (page_status != msg_args[0]) { is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, msg_args[0]); page_status = msg_args[0]; - //maintain lock leds + //maintain lock leds, reset to off and force recheck for new page + numlock_status = 0; + capslock_status = 0; led_set(host_keyboard_leds()); } break; @@ -309,7 +300,6 @@ static THD_FUNCTION(LEDthread, arg) { break; case TOGGLE_NUM_LOCK: - xprintf("NMLK: %d-%d\n", msg_args[0], msg_args[1]); //msg_args[0] = 0 or 1, off/on if (numlock_status != msg_args[0]) { set_lock_leds(NUM_LOCK_LED_ADDRESS, msg_args[0], page_status); @@ -317,7 +307,6 @@ static THD_FUNCTION(LEDthread, arg) { } break; case TOGGLE_CAPS_LOCK: - xprintf("CPLK: %d-%d\n", msg_args[0], msg_args[1]); //msg_args[0] = 0 or 1, off/on if (capslock_status != msg_args[0]) { set_lock_leds(CAPS_LOCK_LED_ADDRESS, msg_args[0], page_status); @@ -326,7 +315,6 @@ static THD_FUNCTION(LEDthread, arg) { break; case STEP_BRIGHTNESS: - xprintf("Step: %d-%d\n", msg_args[0], msg_args[1]); //led_args[0] = step up (1) or down (0) switch (msg_args[0]) { case 0: @@ -373,7 +361,6 @@ void set_led_bit (uint8_t page, uint8_t *led_control_word, uint8_t led_addr, uin if (led_addr < 0 || led_addr > 87 || led_addr % 10 > 8) { return; } - xprintf("_set action-led: %x-%d\n", action, led_addr); blink_bit = action>>2;//check for blink bit action &= ~(1<<2); //strip blink bit @@ -381,17 +368,14 @@ void set_led_bit (uint8_t page, uint8_t *led_control_word, uint8_t led_addr, uin //led_addr tens column is pin#, ones column is bit position in 8-bit mask control_reg_addr = ((led_addr / 10) % 10 - 1 ) * 0x02;// A-matrix is every other byte control_reg_addr += blink_bit == 1 ? 0x12 : 0x00;//if blink_bit, shift 12 bytes to blink register - xprintf("_set control address: %x\n", control_reg_addr); is31_write_register(IS31_FUNCTIONREG, IS31_REG_SHUTDOWN, IS31_REG_SHUTDOWN_ON); chThdSleepMilliseconds(5); is31_read_register(page, control_reg_addr, &temp);//maintain status of leds on this byte is31_write_register(IS31_FUNCTIONREG, IS31_REG_SHUTDOWN, IS31_REG_SHUTDOWN_OFF); - xprintf("_set temp_byte_mask: %x\n", temp); column_bit = 1<<(led_addr % 10 - 1); column_byte = temp; - xprintf("_set col_byte_mask: %x\n", column_byte); switch(action) { case 0: @@ -451,7 +435,6 @@ void set_lock_leds(uint8_t led_addr, uint8_t led_action, uint8_t page) { led_action |= (1<<2); //set blink bit } } - xprintf("_lock action: %d\n", led_action); set_led_bit(page,led_control_word,led_addr,led_action); } @@ -462,7 +445,6 @@ void set_lock_leds(uint8_t led_addr, uint8_t led_action, uint8_t page) { void led_controller_init(void) { uint8_t i; - xprintf("led_init\n"); /* initialise I2C */ /* I2C pins */ palSetPadMode(GPIOB, 0, PAL_MODE_ALTERNATIVE_2); // PTB0/I2C0/SCL diff --git a/keyboards/infinity60/led_controller.h b/keyboards/infinity60/led_controller.h index 457b21a92..eb6060f26 100644 --- a/keyboards/infinity60/led_controller.h +++ b/keyboards/infinity60/led_controller.h @@ -75,7 +75,8 @@ void led_controller_init(void); // D2:D0 extinguish time (3.5ms*2^i) #define IS31_REG_SHUTDOWN 0x0A -#define IS31_REG_SHUTDOWN_ON 0x1 +#define IS31_REG_SHUTDOWN_OFF 0x1 +#define IS31_REG_SHUTDOWN_ON 0x0 #define IS31_REG_AGCCTRL 0x0B #define IS31_REG_ADCRATE 0x0C diff --git a/keyboards/infinity60/rules.mk b/keyboards/infinity60/rules.mk index f58bb2642..c19f62401 100644 --- a/keyboards/infinity60/rules.mk +++ b/keyboards/infinity60/rules.mk @@ -56,7 +56,7 @@ OPT_DEFS = -DCORTEX_VTOR_INIT=0x00001000 # Build Options # comment out to disable the options. # -BOOTMAGIC_ENABLE ?= yes # Virtual DIP switch configuration +BOOTMAGIC_ENABLE ?= no # Virtual DIP switch configuration ## (Note that for BOOTMAGIC on Teensy LC you have to use a custom .ld script.) MOUSEKEY_ENABLE ?= yes # Mouse keys EXTRAKEY_ENABLE ?= yes # Audio control and System control From 4cf17210b60eb7da77f66b8e5af1947a3d168f2f Mon Sep 17 00:00:00 2001 From: Stick Date: Fri, 2 Jun 2017 19:51:29 -0500 Subject: [PATCH 054/238] moved alt out from under space --- keyboards/ergodox/keymaps/familiar/keymap.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/keyboards/ergodox/keymaps/familiar/keymap.c b/keyboards/ergodox/keymaps/familiar/keymap.c index 0e3958de0..714118d93 100644 --- a/keyboards/ergodox/keymaps/familiar/keymap.c +++ b/keyboards/ergodox/keymaps/familiar/keymap.c @@ -28,13 +28,13 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { * |--------+------+------+------+------+------| END | | PGDN |------+------+------+------+------+--------| * | (/LSFT | Z | X | C | V | B | | | | N | M | , | . | UP | )/RSFT | * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------' - * | LCTRL | LGUI | MENU | ' | " | | [ | ] | LEFT | DOWN | RIGHT | + * | LCTRL | LGUI | MENU | ' | LALT | |[/RALT| ] | LEFT | DOWN | RIGHT | * `------------------------------------' `------------------------------------' * ,-------------. ,-------------. * | VOL- | VOL+ | |PRTSCR| | * ,------|------|------| |------+------+------. - * | SPC/ |SLASH/| MUTE | |NUMLCK|WHACK/| SPC/ | - * | ALT | MO(1)|------| |------|MO(1) | ALT | + * | |SLASH/| MUTE | |NUMLCK|WHACK/| | + * | SPC | MO(1)|------| |------|MO(1) | SPC | * | | | LAY3 | | LAY2 | | | * `--------------------' `--------------------' */ @@ -44,19 +44,19 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_HOME, KC_GRV, KC_A, KC_S, KC_D, KC_F, KC_G, KC_LSPO, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_END, - KC_LCTL, KC_LGUI, KC_MENU, KC_QUOT, S(KC_QUOT), + KC_LCTL, KC_LGUI, KC_MENU, KC_QUOT, KC_LALT, KC_VOLD, KC_VOLU, KC_MUTE, - ALT_T(KC_SPC), LT(ARRW,KC_SLSH), TG(INTL), + KC_SPC, LT(ARRW, KC_SLSH), TG(INTL), // right hand KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_PGUP, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_DEL, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_ENTER, KC_PGDN, KC_N, KC_M, KC_COMM, KC_DOT, KC_UP, KC_RSPC, - KC_LBRC, KC_RBRC, KC_LEFT, KC_DOWN, KC_RGHT, + MT(MOD_RALT, KC_LBRC), KC_RBRC, KC_LEFT, KC_DOWN, KC_RGHT, KC_PSCR, _______, KC_NLCK, - TG(NUMP), LT(ARRW,KC_BSLS), ALT_T(KC_SPC) + TG(NUMP), LT(ARRW, C_BSLS), KC_SPC ), /* layer 1: International symbols, etc From f397402e101774eedd1748b1e31c7386f927d4ed Mon Sep 17 00:00:00 2001 From: Stick Date: Fri, 2 Jun 2017 20:02:02 -0500 Subject: [PATCH 055/238] ugly workaround for ErgoDoxEZ LED bugs: turn 'em all off --- keyboards/ergodox/ez/ez.c | 42 ++++++++++---------- keyboards/ergodox/ez/matrix.c | 3 +- keyboards/ergodox/keymaps/familiar/keymap.c | 44 ++++++++++----------- 3 files changed, 44 insertions(+), 45 deletions(-) diff --git a/keyboards/ergodox/ez/ez.c b/keyboards/ergodox/ez/ez.c index 3e19f2302..55b51f6fa 100644 --- a/keyboards/ergodox/ez/ez.c +++ b/keyboards/ergodox/ez/ez.c @@ -22,30 +22,30 @@ void matrix_init_kb(void) { PORTD |= (1<<5 | 1<<4); PORTE |= (1<<6); - ergodox_blink_all_leds(); + //ergodox_blink_all_leds(); matrix_init_user(); } -void ergodox_blink_all_leds(void) -{ - ergodox_led_all_off(); - ergodox_led_all_set(LED_BRIGHTNESS_HI); - ergodox_right_led_1_on(); - _delay_ms(50); - ergodox_right_led_2_on(); - _delay_ms(50); - ergodox_right_led_3_on(); - _delay_ms(50); - ergodox_right_led_1_off(); - _delay_ms(50); - ergodox_right_led_2_off(); - _delay_ms(50); - ergodox_right_led_3_off(); - //ergodox_led_all_on(); - //_delay_ms(333); - ergodox_led_all_off(); -} +// void ergodox_blink_all_leds(void) +// { +// ergodox_led_all_off(); +// ergodox_led_all_set(LED_BRIGHTNESS_HI); +// ergodox_right_led_1_on(); +// _delay_ms(50); +// ergodox_right_led_2_on(); +// _delay_ms(50); +// ergodox_right_led_3_on(); +// _delay_ms(50); +// ergodox_right_led_1_off(); +// _delay_ms(50); +// ergodox_right_led_2_off(); +// _delay_ms(50); +// ergodox_right_led_3_off(); +// //ergodox_led_all_on(); +// //_delay_ms(333); +// ergodox_led_all_off(); +// } uint8_t init_mcp23018(void) { mcp23018_status = 0x20; @@ -57,7 +57,7 @@ uint8_t init_mcp23018(void) { // cli(); if (i2c_initialized == 0) { i2c_init(); // on pins D(1,0) - i2c_initialized++; + i2c_initialized = 1; _delay_ms(1000); } diff --git a/keyboards/ergodox/ez/matrix.c b/keyboards/ergodox/ez/matrix.c index 21b60a542..a489e5b5c 100644 --- a/keyboards/ergodox/ez/matrix.c +++ b/keyboards/ergodox/ez/matrix.c @@ -183,7 +183,7 @@ uint8_t matrix_scan(void) print("left side not responding\n"); } else { print("left side attached\n"); - ergodox_blink_all_leds(); +// ergodox_blink_all_leds(); } } } @@ -391,4 +391,3 @@ static void select_row(uint8_t row) } } } - diff --git a/keyboards/ergodox/keymaps/familiar/keymap.c b/keyboards/ergodox/keymaps/familiar/keymap.c index 714118d93..513bb5541 100644 --- a/keyboards/ergodox/keymaps/familiar/keymap.c +++ b/keyboards/ergodox/keymaps/familiar/keymap.c @@ -56,7 +56,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { MT(MOD_RALT, KC_LBRC), KC_RBRC, KC_LEFT, KC_DOWN, KC_RGHT, KC_PSCR, _______, KC_NLCK, - TG(NUMP), LT(ARRW, C_BSLS), KC_SPC + TG(NUMP), LT(ARRW, KC_BSLS), KC_SPC ), /* layer 1: International symbols, etc @@ -242,26 +242,26 @@ void matrix_init_user(void) { // Runs constantly in the background, in a loop. void matrix_scan_user(void) { - uint8_t layer = biton32(layer_state); - - ergodox_board_led_off(); - ergodox_right_led_1_off(); - ergodox_right_led_2_off(); - ergodox_right_led_3_off(); - switch (layer) { - case INTL: - case INSF: - ergodox_right_led_1_on(); - break; - case NUMP: - ergodox_right_led_2_on(); - break; - case ARRW: - ergodox_right_led_3_on(); - break; - default: - // none - break; - } + // uint8_t layer = biton32(layer_state); + // + // ergodox_board_led_off(); + // ergodox_right_led_1_off(); + // ergodox_right_led_2_off(); + // ergodox_right_led_3_off(); + // switch (layer) { + // case INTL: + // case INSF: + // ergodox_right_led_1_on(); + // break; + // case NUMP: + // ergodox_right_led_2_on(); + // break; + // case ARRW: + // ergodox_right_led_3_on(); + // break; + // default: + // // none + // break; + // } }; From 9cfa37bb3dba3a93edb47c0b08075aa05ea6b492 Mon Sep 17 00:00:00 2001 From: Ante Laurijssen Date: Fri, 2 Jun 2017 22:57:57 -0400 Subject: [PATCH 056/238] Improvements and corrections to morse code macros layer --- keyboards/s60_x/keymaps/bluebear/keymap.c | 88 +++++++++++------------ 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/keyboards/s60_x/keymaps/bluebear/keymap.c b/keyboards/s60_x/keymaps/bluebear/keymap.c index 87a792a01..c4baadfc6 100644 --- a/keyboards/s60_x/keymaps/bluebear/keymap.c +++ b/keyboards/s60_x/keymaps/bluebear/keymap.c @@ -406,7 +406,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { switch(id) { case 0: //Number 0-) if (record->event.pressed) { - if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + if (keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { clear_mods(); return MACRO(T(MINS), T(DOT), T(MINS), T(MINS), T(DOT), T(MINS), T(SPACE), END); //-.--.- } @@ -417,7 +417,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { break; case 1: //Number 1-! if (record->event.pressed) { - if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { clear_mods(); return MACRO(T(MINS), T(DOT), T(MINS), T(DOT), T(MINS), T(MINS), T(SPACE), END); //-.-.-- } @@ -428,7 +428,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { break; case 2: //Number 2-@ if (record->event.pressed) { - if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { clear_mods(); return MACRO(T(DOT), T(MINS), T(MINS), T(DOT), T(MINS), T(DOT), T(SPACE), END); //.--.-. } @@ -439,7 +439,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { break; case 3: // Number 3 if (record->event.pressed) { - if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { clear_mods(); } return MACRO(T(DOT), T(DOT), T(DOT), T(MINS), T(MINS), T(SPACE), END); //...-- @@ -447,7 +447,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { break; case 4: //Number 4-$ if (record->event.pressed) { - if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { clear_mods(); return MACRO(T(DOT), T(DOT), T(DOT), T(MINS), T(DOT), T(DOT), T(MINS), T(SPACE), END); //...-..- } @@ -458,7 +458,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { break; case 5: //Number 5 if (record->event.pressed) { - if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { clear_mods(); } return MACRO(T(DOT), T(DOT), T(DOT), T(DOT), T(DOT), T(SPACE), END); //..... @@ -466,7 +466,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { break; case 6: //Number 6 if (record->event.pressed) { - if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { clear_mods(); } return MACRO(T(MINS), T(DOT), T(DOT), T(DOT), T(DOT), T(SPACE), END); //-.... @@ -474,7 +474,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { break; case 7: //Number 7-& if (record->event.pressed) { - if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { clear_mods(); return MACRO(T(DOT), T(MINS), T(DOT), T(DOT), T(DOT), T(SPACE), END); //.-... } @@ -485,7 +485,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { break; case 8: //Number 8 if (record->event.pressed) { - if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { clear_mods(); } return MACRO(T(MINS), T(MINS), T(MINS), T(DOT), T(DOT), T(SPACE), END); //---.. @@ -493,7 +493,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { break; case 9: //Number 9-( if (record->event.pressed) { - if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { clear_mods(); return MACRO(T(MINS), T(DOT), T(MINS), T(MINS), T(DOT), T(SPACE), END); //-.--. } @@ -504,7 +504,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { break; case 10: //Letter A if (record->event.pressed) { - if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { clear_mods(); } return MACRO(T(DOT), T(MINS), T(SPACE), END); //.- @@ -512,7 +512,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { break; case 11: //Letter B if (record->event.pressed) { - if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { clear_mods(); } return MACRO(T(MINS), T(DOT), T(DOT), T(DOT), T(SPACE), END); //-... @@ -520,7 +520,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { break; case 12: //Letter C if (record->event.pressed) { - if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { clear_mods(); } return MACRO(T(MINS), T(DOT), T(MINS), T(DOT), T(SPACE), END); //-.-. @@ -528,7 +528,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { break; case 13: //Letter D if (record->event.pressed) { - if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { clear_mods(); } return MACRO(T(MINS), T(DOT), T(DOT), T(SPACE), END); //-.. @@ -536,7 +536,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { break; case 14: //Letter E if (record->event.pressed) { - if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { clear_mods(); } return MACRO(T(DOT), T(SPACE), END); //. @@ -544,7 +544,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { break; case 15: //Letter F if (record->event.pressed) { - if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { clear_mods(); } return MACRO(T(DOT), T(DOT), T(MINS), T(DOT), T(SPACE), END); //..-. @@ -552,7 +552,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { break; case 16: //Letter G if (record->event.pressed) { - if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { clear_mods(); } return MACRO(T(MINS), T(MINS), T(DOT), T(SPACE), END); //--. @@ -560,7 +560,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { break; case 17: //Letter H if (record->event.pressed) { - if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { clear_mods(); } return MACRO(T(DOT), T(DOT), T(DOT), T(DOT), T(SPACE), END); //.... @@ -568,7 +568,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { break; case 18: //Letter I if (record->event.pressed) { - if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { clear_mods(); } return MACRO(T(DOT), T(DOT), T(SPACE), END); //.. @@ -576,7 +576,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { break; case 19: //Letter J if (record->event.pressed) { - if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { clear_mods(); } return MACRO(T(DOT), T(MINS), T(MINS), T(MINS), T(SPACE), END); //.--- @@ -584,7 +584,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { break; case 20: //Letter K if (record->event.pressed) { - if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { clear_mods(); } return MACRO(T(MINS), T(DOT), T(MINS), T(SPACE), END); //-.- @@ -592,7 +592,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { break; case 21: //Letter L if (record->event.pressed) { - if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { clear_mods(); } return MACRO(T(DOT), T(MINS), T(DOT), T(DOT), T(SPACE), END); //.-.. @@ -600,7 +600,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { break; case 22: //Letter M if (record->event.pressed) { - if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { clear_mods(); } return MACRO(T(MINS), T(MINS), T(SPACE), END); //-- @@ -608,7 +608,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { break; case 23: //Letter N if (record->event.pressed) { - if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { clear_mods(); } return MACRO(T(MINS), T(DOT), T(SPACE), END); //-. @@ -616,7 +616,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { break; case 24: //Letter O if (record->event.pressed) { - if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { clear_mods(); } return MACRO(T(MINS), T(MINS), T(MINS), T(SPACE), END); //--- @@ -624,7 +624,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { break; case 25: //Letter P if (record->event.pressed) { - if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { clear_mods(); } return MACRO(T(DOT), T(MINS), T(MINS), T(DOT), T(SPACE), END); //.--. @@ -632,7 +632,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { break; case 26: //Letter Q if (record->event.pressed) { - if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { clear_mods(); } return MACRO(T(MINS), T(MINS), T(DOT), T(MINS), T(SPACE), END); //--.- @@ -640,7 +640,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { break; case 27: //Letter R if (record->event.pressed) { - if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { clear_mods(); } return MACRO(T(DOT), T(MINS), T(DOT), T(SPACE), END); //.-. @@ -648,7 +648,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { break; case 28: //Letter S if (record->event.pressed) { - if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { clear_mods(); } return MACRO(T(DOT), T(DOT), T(DOT), T(SPACE), END); //... @@ -656,7 +656,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { break; case 29: //Letter T if (record->event.pressed) { - if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { clear_mods(); } return MACRO(T(MINS), T(SPACE), END); //- @@ -664,7 +664,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { break; case 30: //Letter U if (record->event.pressed) { - if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { clear_mods(); } return MACRO(T(DOT), T(DOT), T(MINS), T(SPACE), END); //..- @@ -672,7 +672,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { break; case 31: //Letter V if (record->event.pressed) { - if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { clear_mods(); } return MACRO(T(DOT), T(DOT), T(DOT), T(MINS), T(SPACE), END); //...- @@ -680,7 +680,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { break; case 32: //Letter W if (record->event.pressed) { - if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { clear_mods(); } return MACRO(T(DOT), T(MINS), T(MINS), T(SPACE), END); //.-- @@ -688,7 +688,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { break; case 33: //Letter X if (record->event.pressed) { - if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { clear_mods(); } return MACRO(T(MINS), T(DOT), T(DOT), T(MINS), T(SPACE), END); //-..- @@ -696,7 +696,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { break; case 34: //Letter Y if (record->event.pressed) { - if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { clear_mods(); } return MACRO(T(MINS), T(DOT), T(MINS), T(MINS), T(SPACE), END); //-.-- @@ -704,7 +704,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { break; case 35: //Letter Z if (record->event.pressed) { - if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { clear_mods(); } return MACRO(T(MINS), T(MINS), T(DOT), T(DOT), T(SPACE), END); //--.. @@ -712,7 +712,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { break; case 36: //Punctuation . if (record->event.pressed) { - if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { clear_mods(); } return MACRO(T(DOT), T(MINS), T(DOT), T(MINS), T(DOT), T(MINS), T(SPACE), END); //.-.-.- @@ -720,7 +720,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { break; case 37: //Punctuation , if (record->event.pressed) { - if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { clear_mods(); } return MACRO(T(MINS), T(MINS), T(DOT), T(DOT), T(MINS), T(MINS), T(SPACE), END); //--..-- @@ -728,7 +728,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { break; case 38: //Punctuation '-" if (record->event.pressed) { - if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { clear_mods(); return MACRO(T(DOT), T(MINS), T(DOT), T(DOT), T(MINS), T(DOT), T(SPACE), END); //.-..-. } @@ -739,7 +739,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { break; case 39: //Punctuation /-? if (record->event.pressed) { - if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { clear_mods(); return MACRO(T(DOT), T(DOT), T(MINS), T(MINS), T(DOT), T(DOT), T(SPACE), END); //..--.. } @@ -750,7 +750,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { break; case 40: //Punctuation ;-: if (record->event.pressed) { - if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { clear_mods(); return MACRO(T(MINS), T(MINS), T(MINS), T(DOT), T(DOT), T(DOT), T(SPACE), END); //---... } @@ -761,7 +761,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { break; case 41: //Punctuation =-+ if (record->event.pressed) { - if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { clear_mods(); return MACRO(T(DOT), T(MINS), T(DOT), T(MINS), T(DOT), T(SPACE), END); //.-.-. } @@ -772,7 +772,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { break; case 42: //Punctuation --_ if (record->event.pressed) { - if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { clear_mods(); return MACRO(T(DOT), T(DOT), T(MINS), T(MINS), T(DOT), T(MINS), T(SPACE), END); //..--.- } @@ -783,7 +783,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { break; case 43: //Morse Space if (record->event.pressed) { - if (keyboard_report->mods & MOD_BIT(KC_LSFT) || MOD_BIT(KC_RSFT)) { + if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { clear_mods(); } return MACRO(T(BSLS), T(SPACE), END); //When pressed, this sends a slash followed by a space, making it easier to distinguish words in Morse From a916f4e8b897b6b8925d7113d84f9eac7e7b67be Mon Sep 17 00:00:00 2001 From: Fred Sundvik Date: Sat, 3 Jun 2017 14:34:50 +0300 Subject: [PATCH 057/238] Let BACKLIGHT_ENABLE control the Infinity LEDs --- build_keyboard.mk | 6 ++++-- keyboards/ergodox/infinity/animations.c | 4 ++-- keyboards/ergodox/infinity/rules.mk | 9 ++------- keyboards/ergodox/keymaps/333fred/Makefile | 2 +- quantum/visualizer/visualizer.c | 4 ++-- quantum/visualizer/visualizer.mk | 3 +-- 6 files changed, 12 insertions(+), 16 deletions(-) diff --git a/build_keyboard.mk b/build_keyboard.mk index 9fa8c3126..36eab3a9e 100644 --- a/build_keyboard.mk +++ b/build_keyboard.mk @@ -233,8 +233,10 @@ ifeq ($(strip $(LCD_ENABLE)), yes) CIE1931_CURVE = yes endif -ifeq ($(strip $(LED_ENABLE)), yes) - CIE1931_CURVE = yes +ifeq ($(strip $(BACKLIGHT_ENABLE)), yes) + ifeq ($(strip $(VISUALIZER_ENABLE)), yes) + CIE1931_CURVE = yes + endif endif ifeq ($(strip $(CIE1931_CURVE)), yes) diff --git a/keyboards/ergodox/infinity/animations.c b/keyboards/ergodox/infinity/animations.c index 4c9f6d9c8..0e732b741 100644 --- a/keyboards/ergodox/infinity/animations.c +++ b/keyboards/ergodox/infinity/animations.c @@ -25,7 +25,7 @@ #include "lcd_backlight_keyframes.h" #endif -#ifdef LED_ENABLE +#ifdef BACKLIGHT_ENABLE #include "led_keyframes.h" #endif @@ -61,7 +61,7 @@ keyframe_animation_t default_suspend_animation = { }; #endif -#if defined(LED_ENABLE) +#if defined(BACKLIGHT_ENABLE) #define CROSSFADE_TIME 1000 #define GRADIENT_TIME 3000 diff --git a/keyboards/ergodox/infinity/rules.mk b/keyboards/ergodox/infinity/rules.mk index 9e6170d89..af29ebce8 100644 --- a/keyboards/ergodox/infinity/rules.mk +++ b/keyboards/ergodox/infinity/rules.mk @@ -62,15 +62,10 @@ CUSTOM_MATRIX ?= yes # Custom matrix file SERIAL_LINK_ENABLE = yes VISUALIZER_ENABLE ?= yes LCD_ENABLE ?= yes -LED_ENABLE ?= no +BACKLIGHT_ENABLE ?= yes LCD_BACKLIGHT_ENABLE ?= yes MIDI_ENABLE = no RGBLIGHT_ENABLE = no -ifdef LCD_ENABLE include $(SUBPROJECT_PATH)/drivers/gdisp/st7565ergodox/driver.mk -endif - -ifdef LED_ENABLE -include $(SUBPROJECT_PATH)/drivers/gdisp/IS31FL3731C/driver.mk -endif \ No newline at end of file +include $(SUBPROJECT_PATH)/drivers/gdisp/IS31FL3731C/driver.mk \ No newline at end of file diff --git a/keyboards/ergodox/keymaps/333fred/Makefile b/keyboards/ergodox/keymaps/333fred/Makefile index 87985bda1..b977722a2 100644 --- a/keyboards/ergodox/keymaps/333fred/Makefile +++ b/keyboards/ergodox/keymaps/333fred/Makefile @@ -1,7 +1,7 @@ SUBPROJECT_DEFAULT = infinity LCD_BACKLIGHT_ENABLE = yes LCD_ENABLE = yes -LED_ENABLE = yes +BACKLIGHT_ENABLE = yes BACKLIGHT_ENABLE = yes NKRO_ENABLE = yes TAP_DANCE_ENABLE = yes diff --git a/quantum/visualizer/visualizer.c b/quantum/visualizer/visualizer.c index 6f134097f..cd2dff6a6 100644 --- a/quantum/visualizer/visualizer.c +++ b/quantum/visualizer/visualizer.c @@ -309,7 +309,7 @@ static DECLARE_THREAD_FUNCTION(visualizerThread, arg) { update_keyframe_animation(animations[i], &state, delta, &sleep_time); } } -#ifdef LED_ENABLE +#ifdef BACKLIGHT_ENABLE gdispGFlush(LED_DISPLAY); #endif @@ -372,7 +372,7 @@ void visualizer_init(void) { #ifdef LCD_ENABLE LCD_DISPLAY = get_lcd_display(); #endif -#ifdef LED_ENABLE +#ifdef BACKLIGHT_ENABLE LED_DISPLAY = get_led_display(); #endif diff --git a/quantum/visualizer/visualizer.mk b/quantum/visualizer/visualizer.mk index 5f710124b..6f97603bd 100644 --- a/quantum/visualizer/visualizer.mk +++ b/quantum/visualizer/visualizer.mk @@ -42,9 +42,8 @@ SRC += $(VISUALIZER_DIR)/resources/lcd_logo.c OPT_DEFS += -DLCD_BACKLIGHT_ENABLE endif -ifeq ($(strip $(LED_ENABLE)), yes) +ifeq ($(strip $(BACKLIGHT_ENABLE)), yes) SRC += $(VISUALIZER_DIR)/led_keyframes.c -OPT_DEFS += -DLED_ENABLE endif include $(GFXLIB)/gfx.mk From 0f9bfafb9e1fea118a0a61ff2baaff73b05ec157 Mon Sep 17 00:00:00 2001 From: Fred Sundvik Date: Sat, 3 Jun 2017 15:31:02 +0300 Subject: [PATCH 058/238] Turn off LED matrix by default --- .../infinity/drivers/gdisp/IS31FL3731C/gdisp_IS31FL3731C.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/keyboards/ergodox/infinity/drivers/gdisp/IS31FL3731C/gdisp_IS31FL3731C.c b/keyboards/ergodox/infinity/drivers/gdisp/IS31FL3731C/gdisp_IS31FL3731C.c index ea09c4bb0..247269446 100644 --- a/keyboards/ergodox/infinity/drivers/gdisp/IS31FL3731C/gdisp_IS31FL3731C.c +++ b/keyboards/ergodox/infinity/drivers/gdisp/IS31FL3731C/gdisp_IS31FL3731C.c @@ -173,7 +173,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) { } // software shutdown disable (i.e. turn stuff on) - write_register(g, IS31_FUNCTIONREG, IS31_REG_SHUTDOWN, IS31_REG_SHUTDOWN_ON); + write_register(g, IS31_FUNCTIONREG, IS31_REG_SHUTDOWN, IS31_REG_SHUTDOWN_OFF); gfxSleepMilliseconds(10); // Finish Init @@ -183,7 +183,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) { g->g.Width = GDISP_SCREEN_WIDTH; g->g.Height = GDISP_SCREEN_HEIGHT; g->g.Orientation = GDISP_ROTATE_0; - g->g.Powermode = powerOn; + g->g.Powermode = powerOff; g->g.Backlight = GDISP_INITIAL_BACKLIGHT; g->g.Contrast = GDISP_INITIAL_CONTRAST; return TRUE; From effffa33a503a093be4fa00b570df7a4e2996edc Mon Sep 17 00:00:00 2001 From: Fred Sundvik Date: Sat, 3 Jun 2017 21:14:26 +0300 Subject: [PATCH 059/238] Backlight level handling for the visualizer --- quantum/visualizer/visualizer.c | 30 +++++++++++++++++++++++++++++- quantum/visualizer/visualizer.h | 9 ++++++++- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/quantum/visualizer/visualizer.c b/quantum/visualizer/visualizer.c index cd2dff6a6..29db7005c 100644 --- a/quantum/visualizer/visualizer.c +++ b/quantum/visualizer/visualizer.c @@ -58,8 +58,11 @@ SOFTWARE. static visualizer_keyboard_status_t current_status = { .layer = 0xFFFFFFFF, .default_layer = 0xFFFFFFFF, - .mods = 0xFF, .leds = 0xFFFFFFFF, +#ifdef BACKLIGHT_ENABLE + .backlight_level = 0, +#endif + .mods = 0xFF, .suspended = false, #ifdef VISUALIZER_USER_DATA_SIZE .user_data = {0} @@ -72,6 +75,9 @@ static bool same_status(visualizer_keyboard_status_t* status1, visualizer_keyboa status1->mods == status2->mods && status1->leds == status2->leds && status1->suspended == status2->suspended +#ifdef BACKLIGHT_ENABLE + && status1->backlight_level == status2->backlight_level +#endif #ifdef VISUALIZER_USER_DATA_SIZE && memcmp(status1->user_data, status2->user_data, VISUALIZER_USER_DATA_SIZE) == 0 #endif @@ -279,6 +285,18 @@ static DECLARE_THREAD_FUNCTION(visualizerThread, arg) { bool enabled = visualizer_enabled; if (force_update || !same_status(&state.status, ¤t_status)) { force_update = false; + #if BACKLIGHT_ENABLE + if(current_status.backlight_level != state.status.backlight_level) { + if (current_status.backlight_level != 0) { + gdispGSetPowerMode(LED_DISPLAY, powerOn); + uint16_t percent = (uint16_t)current_status.backlight_level * 100 / 255; + gdispGSetBacklight(LED_DISPLAY, percent); + } + else { + gdispGSetPowerMode(LED_DISPLAY, powerOff); + } + } + #endif if (visualizer_enabled) { if (current_status.suspended) { stop_all_keyframe_animations(); @@ -445,6 +463,9 @@ void visualizer_update(uint32_t default_state, uint32_t state, uint8_t mods, uin .default_layer = default_state, .mods = mods, .leds = leds, +#ifdef BACKLIGHT_ENABLE + .backlight_level = current_status.backlight_level, +#endif .suspended = current_status.suspended, }; #ifdef VISUALIZER_USER_DATA_SIZE @@ -467,3 +488,10 @@ void visualizer_resume(void) { current_status.suspended = false; update_status(true); } + +#ifdef BACKLIGHT_ENABLE +void backlight_set(uint8_t level) { + current_status.backlight_level = level; + update_status(true); +} +#endif diff --git a/quantum/visualizer/visualizer.h b/quantum/visualizer/visualizer.h index d6f279e10..1c567440f 100644 --- a/quantum/visualizer/visualizer.h +++ b/quantum/visualizer/visualizer.h @@ -34,6 +34,10 @@ SOFTWARE. #include "lcd_backlight.h" #endif +#ifdef BACKLIGHT_ENABLE +#include "backlight.h" +#endif + // use this function to merge both real_mods and oneshot_mods in a uint16_t uint8_t visualizer_get_mods(void); @@ -65,9 +69,12 @@ struct keyframe_animation_t; typedef struct { uint32_t layer; uint32_t default_layer; - uint8_t mods; uint32_t leds; // See led.h for available statuses + uint8_t mods; bool suspended; +#ifdef BACKLIGHT_ENABLE + uint8_t backlight_level; +#endif #ifdef VISUALIZER_USER_DATA_SIZE uint8_t user_data[VISUALIZER_USER_DATA_SIZE]; #endif From 2a7f9a7e46e1f4350be249c267fa7c35fd6562b5 Mon Sep 17 00:00:00 2001 From: Fred Sundvik Date: Sat, 3 Jun 2017 21:30:52 +0300 Subject: [PATCH 060/238] Add backlight control to the IS31FL3731 driver --- .../drivers/gdisp/IS31FL3731C/gdisp_IS31FL3731C.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/keyboards/ergodox/infinity/drivers/gdisp/IS31FL3731C/gdisp_IS31FL3731C.c b/keyboards/ergodox/infinity/drivers/gdisp/IS31FL3731C/gdisp_IS31FL3731C.c index 247269446..0b48783d6 100644 --- a/keyboards/ergodox/infinity/drivers/gdisp/IS31FL3731C/gdisp_IS31FL3731C.c +++ b/keyboards/ergodox/infinity/drivers/gdisp/IS31FL3731C/gdisp_IS31FL3731C.c @@ -43,7 +43,7 @@ extern const uint8_t CIE1931_CURVE[]; #define GDISP_INITIAL_CONTRAST 0 #endif #ifndef GDISP_INITIAL_BACKLIGHT - #define GDISP_INITIAL_BACKLIGHT 100 + #define GDISP_INITIAL_BACKLIGHT 0 #endif #define GDISP_FLG_NEEDFLUSH (GDISP_FLG_DRIVER<<0) @@ -204,7 +204,8 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) { uint8_t* src = PRIV(g)->frame_buffer; for (int y=0;ywrite_buffer[get_led_address(g, x, y)]=CIE1931_CURVE[*src]; + uint8_t val = (uint16_t)*src * g->g.Backlight / 100; + PRIV(g)->write_buffer[get_led_address(g, x, y)]=CIE1931_CURVE[val]; ++src; } } @@ -297,8 +298,13 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) { g->g.Orientation = (orientation_t)g->p.ptr; return; - case GDISP_CONTROL_CONTRAST: - return; + case GDISP_CONTROL_BACKLIGHT: + if (g->g.Backlight == (unsigned)g->p.ptr) + return; + unsigned val = (unsigned)g->p.ptr; + g->g.Backlight = val > 255 ? 255 : val; + g->flags |= GDISP_FLG_NEEDFLUSH; + return; } } #endif // GDISP_NEED_CONTROL From b51a0db6ed03d939baad7cb9d87ed13c3653c7d2 Mon Sep 17 00:00:00 2001 From: Fred Sundvik Date: Sat, 3 Jun 2017 22:04:10 +0300 Subject: [PATCH 061/238] Add backlight support to the default Ergodox Infinity animations --- keyboards/ergodox/infinity/animations.c | 69 +++++++++++++++++++++---- quantum/visualizer/led_keyframes.c | 14 +++++ quantum/visualizer/led_keyframes.h | 3 ++ 3 files changed, 75 insertions(+), 11 deletions(-) diff --git a/keyboards/ergodox/infinity/animations.c b/keyboards/ergodox/infinity/animations.c index 0e732b741..675519e30 100644 --- a/keyboards/ergodox/infinity/animations.c +++ b/keyboards/ergodox/infinity/animations.c @@ -32,31 +32,78 @@ #include "visualizer_keyframes.h" -#if defined(LCD_ENABLE) && defined(LCD_BACKLIGHT_ENABLE) +#if defined(LCD_ENABLE) || defined(LCD_BACKLIGHT_ENABLE) || defined(BACKLIGHT_ENABLE) + +static bool keyframe_enable(keyframe_animation_t* animation, visualizer_state_t* state) { +#ifdef LCD_ENABLE + lcd_keyframe_enable(animation, state); +#endif +#ifdef LCD_BACKLIGHT_ENABLE + backlight_keyframe_enable(animation, state); +#endif +#ifdef BACKLIGHT_ENABLE + led_keyframe_enable(animation, state); +#endif + return false; +} + +static bool keyframe_disable(keyframe_animation_t* animation, visualizer_state_t* state) { +#ifdef LCD_ENABLE + lcd_keyframe_disable(animation, state); +#endif +#ifdef LCD_BACKLIGHT_ENABLE + backlight_keyframe_disable(animation, state); +#endif +#ifdef BACKLIGHT_ENABLE + led_keyframe_disable(animation, state); +#endif + return false; +} + +static bool keyframe_fade_in(keyframe_animation_t* animation, visualizer_state_t* state) { + bool ret = false; +#ifdef LCD_BACKLIGHT_ENABLE + ret |= backlight_keyframe_animate_color(animation, state); +#endif +#ifdef BACLIGHT_ENABLE + ret |= led_keyframe_fade_in_all(animation, state); +#endif + return ret; +} + +static bool keyframe_fade_out(keyframe_animation_t* animation, visualizer_state_t* state) { + bool ret = false; +#ifdef LCD_BACKLIGHT_ENABLE + ret |= backlight_keyframe_animate_color(animation, state); +#endif +#ifdef BACLIGHT_ENABLE + ret |= led_keyframe_fade_out_all(animation, state); +#endif + return ret; +} + // Don't worry, if the startup animation is long, you can use the keyboard like normal // during that time keyframe_animation_t default_startup_animation = { - .num_frames = 4, + .num_frames = 3, .loop = false, - .frame_lengths = {0, 0, 0, gfxMillisecondsToTicks(5000), 0}, + .frame_lengths = {0, 0, gfxMillisecondsToTicks(5000)}, .frame_functions = { - lcd_keyframe_enable, - backlight_keyframe_enable, + keyframe_enable, lcd_keyframe_draw_logo, - backlight_keyframe_animate_color, + keyframe_fade_in, }, }; keyframe_animation_t default_suspend_animation = { - .num_frames = 4, + .num_frames = 3, .loop = false, - .frame_lengths = {0, gfxMillisecondsToTicks(1000), 0, 0}, + .frame_lengths = {0, gfxMillisecondsToTicks(1000), 0}, .frame_functions = { lcd_keyframe_display_layer_text, - backlight_keyframe_animate_color, - lcd_keyframe_disable, - backlight_keyframe_disable, + keyframe_fade_out, + keyframe_disable, }, }; #endif diff --git a/quantum/visualizer/led_keyframes.c b/quantum/visualizer/led_keyframes.c index 2dacd990d..c14491e5e 100644 --- a/quantum/visualizer/led_keyframes.c +++ b/quantum/visualizer/led_keyframes.c @@ -127,3 +127,17 @@ bool led_keyframe_normal_orientation(keyframe_animation_t* animation, visualizer gdispGSetOrientation(LED_DISPLAY, GDISP_ROTATE_0); return false; } + +bool led_keyframe_disable(keyframe_animation_t* animation, visualizer_state_t* state) { + (void)state; + (void)animation; + gdispGSetPowerMode(LED_DISPLAY, powerOff); + return false; +} + +bool led_keyframe_enable(keyframe_animation_t* animation, visualizer_state_t* state) { + (void)state; + (void)animation; + gdispGSetPowerMode(LED_DISPLAY, powerOn); + return false; +} diff --git a/quantum/visualizer/led_keyframes.h b/quantum/visualizer/led_keyframes.h index a68943041..a59a4f37d 100644 --- a/quantum/visualizer/led_keyframes.h +++ b/quantum/visualizer/led_keyframes.h @@ -35,6 +35,9 @@ bool led_keyframe_crossfade(keyframe_animation_t* animation, visualizer_state_t* bool led_keyframe_mirror_orientation(keyframe_animation_t* animation, visualizer_state_t* state); bool led_keyframe_normal_orientation(keyframe_animation_t* animation, visualizer_state_t* state); +bool led_keyframe_disable(keyframe_animation_t* animation, visualizer_state_t* state); +bool led_keyframe_enable(keyframe_animation_t* animation, visualizer_state_t* state); + extern keyframe_animation_t led_test_animation; From 1b8ed53f21702d279dc5b5bffc2d0213943a22ad Mon Sep 17 00:00:00 2001 From: Ante Laurijssen Date: Mon, 5 Jun 2017 22:17:35 -0400 Subject: [PATCH 062/238] Added a couple of custom keys and updated layer image --- .../bluebear/S60X-Bluebear-MOUSE-Layer.png | Bin 16499 -> 18972 bytes keyboards/s60_x/keymaps/bluebear/keymap.c | 43 +++++++++++++++--- 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/keyboards/s60_x/keymaps/bluebear/S60X-Bluebear-MOUSE-Layer.png b/keyboards/s60_x/keymaps/bluebear/S60X-Bluebear-MOUSE-Layer.png index 4e92a60c761c8401b667a5a8e8ac591a9b85d4ab..f37249b8114e3520ef699850116c47dac65e3e52 100644 GIT binary patch literal 18972 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 GH~$xObxqU& literal 16499 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 diff --git a/keyboards/s60_x/keymaps/bluebear/keymap.c b/keyboards/s60_x/keymaps/bluebear/keymap.c index c4baadfc6..22356db2b 100644 --- a/keyboards/s60_x/keymaps/bluebear/keymap.c +++ b/keyboards/s60_x/keymaps/bluebear/keymap.c @@ -255,6 +255,13 @@ enum morse_macros { MC_SPACE = M(43), }; +// Custom Keys + +enum custom_keys { + MAGSYS, // Magic SysRq key - Sends Alt-PSCR + TFS = LCTL(LALT(KC_DEL)), // Three Finger Salute - Sends Ctl-Alt-Del +}; + //Keymaps const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { @@ -312,9 +319,9 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ │DEBUG│ │ │ │ │ │ │BTN1 │MS_UP│BTN2 │WH_UP│ │ │ │█████│ ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ - │ │ │ │ │ │ │ │MS_LT│MS_DN│MS_RT│WH_DN│BTN3 │▒▒▒▒▒│ │█████│ + │TFS │ │ │ │ │ │ │MS_LT│MS_DN│MS_RT│WH_DN│BTN3 │▒▒▒▒▒│ │█████│ ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ - │ │▒▒▒▒▒│ │ │ │ │ │ │ │ │ │ │▒▒▒▒▒│ │▒▒▒▒▒│ + │MAGSYS▒▒▒▒▒│ │ │ │ │ │ │ │ │ │ │▒▒▒▒▒│ │▒▒▒▒▒│ ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ │ │ │ │█████│█████│█████│ PWR │█████│█████│█████│ │ │ │ │█████│ └─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┘ @@ -324,8 +331,8 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { RESET, KC_F13, KC_F14, KC_F15, KC_F16, KC_F17, KC_F18, KC_F19, KC_F20, KC_F21, KC_F22, KC_F23, KC_F24, KC_NO, KC_NO, \ DEBUG, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_BTN1, KC_MS_UP, KC_BTN2, KC_WH_U, KC_NO, KC_NO, KC_NO, \ - KC_LCTL, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_MS_LEFT, KC_MS_DOWN, KC_MS_RIGHT, KC_WH_D, KC_BTN3, KC_NO, KC_TRNS, \ - KC_TRNS, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_TRNS, KC_NO, \ + TFS, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_MS_LEFT, KC_MS_DOWN, KC_MS_RIGHT, KC_WH_D, KC_BTN3, KC_NO, KC_TRNS, \ + MAGSYS, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_TRNS, KC_NO, \ KC_TRNS, KC_TRNS, KC_TRNS, KC_POWER, KC_TRNS, KC_TRNS, KC_NO, KC_NO ), @@ -400,13 +407,16 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { }; -// Morse Code Macros +// Macros const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { switch(id) { + + // Morse Code Macros + case 0: //Number 0-) if (record->event.pressed) { - if (keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { + if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { clear_mods(); return MACRO(T(MINS), T(DOT), T(MINS), T(MINS), T(DOT), T(MINS), T(SPACE), END); //-.--.- } @@ -791,7 +801,26 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { break; } return MACRO_NONE; -}; +} + +// Custom Keys + +bool process_record_user (uint16_t keycode, keyrecord_t *record) { + switch(keycode) { + case MAGSYS: //Magic SysRq function - Toggles key on and off depending on state of LALT key + if (record->event.pressed) { + if (keyboard_report->mods & (MOD_BIT(KC_LALT))) { + unregister_code(KC_PSCR); + unregister_code(KC_LALT); + } else { + register_code(KC_LALT); + register_code(KC_PSCR); + } + } + break; + } + return true; +} // Midi Chord Function From 8f80f35186353801b960d536339b70f43f484c46 Mon Sep 17 00:00:00 2001 From: Ante Laurijssen Date: Wed, 7 Jun 2017 22:01:28 -0400 Subject: [PATCH 063/238] Working on Morse Code Macros --- keyboards/s60_x/keymaps/bluebear/keymap.c | 33 ++++++++++++++++------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/keyboards/s60_x/keymaps/bluebear/keymap.c b/keyboards/s60_x/keymaps/bluebear/keymap.c index 22356db2b..1ecddb8d5 100644 --- a/keyboards/s60_x/keymaps/bluebear/keymap.c +++ b/keyboards/s60_x/keymaps/bluebear/keymap.c @@ -407,21 +407,36 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { }; -// Macros +// Custom Function - Check if shift is pressed + +bool check_shift(void); + +bool check_shift() { + if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT))) { + return KC_LSHIFT; + } + if (keyboard_report->mods & (MOD_BIT(KC_RSHIFT))) { + return KC_RSHIFT; + } + else { + return false; + } +} + +// Morse Code Macros const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { + uint16_t is_shift = check_shift(); switch(id) { - - // Morse Code Macros - case 0: //Number 0-) if (record->event.pressed) { - if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { - clear_mods(); - return MACRO(T(MINS), T(DOT), T(MINS), T(MINS), T(DOT), T(MINS), T(SPACE), END); //-.--.- - } + if (is_shift == false) { + return MACRO(T(MINS), T(MINS), T(MINS), T(MINS), T(MINS), T(SPACE), END); //----- + } else { - return MACRO(T(MINS), T(MINS), T(MINS), T(MINS), T(MINS), T(SPACE), END); //----- + unregister_mods(MOD_BIT(is_shift)); + return MACRO(T(MINS), T(DOT), T(MINS), T(MINS), T(DOT), T(MINS), T(SPACE), END); //-.--.- + register_code(is_shift); } } break; From 7146dfea6e564660e525c5c8280d5c73a73697f3 Mon Sep 17 00:00:00 2001 From: Ante Laurijssen Date: Wed, 7 Jun 2017 23:57:14 -0400 Subject: [PATCH 064/238] =?UTF-8?q?Created=20special=20shift=20keys=20for?= =?UTF-8?q?=20Morse=20layer=20that=20change=20variable=20value,=20enabling?= =?UTF-8?q?=20to=20send=20=E2=80=9Cshifted=E2=80=9D=20special=20morse=20co?= =?UTF-8?q?de=20characters.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- keyboards/s60_x/keymaps/bluebear/keymap.c | 172 ++++------------------ 1 file changed, 29 insertions(+), 143 deletions(-) diff --git a/keyboards/s60_x/keymaps/bluebear/keymap.c b/keyboards/s60_x/keymaps/bluebear/keymap.c index 1ecddb8d5..878a54e28 100644 --- a/keyboards/s60_x/keymaps/bluebear/keymap.c +++ b/keyboards/s60_x/keymaps/bluebear/keymap.c @@ -258,7 +258,9 @@ enum morse_macros { // Custom Keys enum custom_keys { - MAGSYS, // Magic SysRq key - Sends Alt-PSCR + MAGSYS = SAFE_RANGE, // Magic SysRq key - Sends Alt-PSCR + MC_LSFT, + MC_RSFT, TFS = LCTL(LALT(KC_DEL)), // Three Finger Salute - Sends Ctl-Alt-Del }; @@ -401,49 +403,31 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { TO(0), MC_1, MC_2, MC_3, MC_4, MC_5, MC_6, MC_7, MC_8, MC_9, MC_0, KC_NO, KC_NO, KC_NO, KC_NO, \ KC_TAB, MC_APOS, MC_COMM, MC_DOT, MC_P, MC_Y, MC_F, MC_G, MC_C, MC_R, MC_L, MC_SLSH, MC_EQL, KC_BSPC, \ KC_NO, MC_A, MC_O, MC_E, MC_U, MC_I, MC_D, MC_H, MC_T, MC_N, MC_S, MC_MINS, KC_NO, KC_ENT, \ - KC_LSFT, KC_NO, MC_SCLN, MC_Q, MC_J, MC_K, MC_X, MC_B, MC_M, MC_W, MC_V, MC_Z, KC_NO, KC_RSFT, KC_NO, \ + MC_LSFT, KC_NO, MC_SCLN, MC_Q, MC_J, MC_K, MC_X, MC_B, MC_M, MC_W, MC_V, MC_Z, KC_NO, MC_RSFT, KC_NO, \ KC_NO, KC_NO, KC_NO, MC_SPACE, KC_NO, KC_NO, KC_NO, KC_NO ), }; -// Custom Function - Check if shift is pressed - -bool check_shift(void); - -bool check_shift() { - if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT))) { - return KC_LSHIFT; - } - if (keyboard_report->mods & (MOD_BIT(KC_RSHIFT))) { - return KC_RSHIFT; - } - else { - return false; - } -} - // Morse Code Macros +int mc_shift_on = false; + const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { - uint16_t is_shift = check_shift(); switch(id) { case 0: //Number 0-) if (record->event.pressed) { - if (is_shift == false) { - return MACRO(T(MINS), T(MINS), T(MINS), T(MINS), T(MINS), T(SPACE), END); //----- - } - else { - unregister_mods(MOD_BIT(is_shift)); + if (mc_shift_on == true) { return MACRO(T(MINS), T(DOT), T(MINS), T(MINS), T(DOT), T(MINS), T(SPACE), END); //-.--.- - register_code(is_shift); + } + else { + return MACRO(T(MINS), T(MINS), T(MINS), T(MINS), T(MINS), T(SPACE), END); //----- } } break; case 1: //Number 1-! if (record->event.pressed) { - if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { - clear_mods(); + if (mc_shift_on == true) { return MACRO(T(MINS), T(DOT), T(MINS), T(DOT), T(MINS), T(MINS), T(SPACE), END); //-.-.-- } else { @@ -453,8 +437,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { break; case 2: //Number 2-@ if (record->event.pressed) { - if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { - clear_mods(); + if (mc_shift_on == true) { return MACRO(T(DOT), T(MINS), T(MINS), T(DOT), T(MINS), T(DOT), T(SPACE), END); //.--.-. } else { @@ -464,16 +447,12 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { break; case 3: // Number 3 if (record->event.pressed) { - if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { - clear_mods(); - } return MACRO(T(DOT), T(DOT), T(DOT), T(MINS), T(MINS), T(SPACE), END); //...-- } break; case 4: //Number 4-$ if (record->event.pressed) { - if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { - clear_mods(); + if (mc_shift_on == true) { return MACRO(T(DOT), T(DOT), T(DOT), T(MINS), T(DOT), T(DOT), T(MINS), T(SPACE), END); //...-..- } else { @@ -483,24 +462,17 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { break; case 5: //Number 5 if (record->event.pressed) { - if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { - clear_mods(); - } return MACRO(T(DOT), T(DOT), T(DOT), T(DOT), T(DOT), T(SPACE), END); //..... } break; case 6: //Number 6 if (record->event.pressed) { - if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { - clear_mods(); - } return MACRO(T(MINS), T(DOT), T(DOT), T(DOT), T(DOT), T(SPACE), END); //-.... } break; case 7: //Number 7-& if (record->event.pressed) { - if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { - clear_mods(); + if (mc_shift_on == true) { return MACRO(T(DOT), T(MINS), T(DOT), T(DOT), T(DOT), T(SPACE), END); //.-... } else { @@ -510,16 +482,12 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { break; case 8: //Number 8 if (record->event.pressed) { - if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { - clear_mods(); - } return MACRO(T(MINS), T(MINS), T(MINS), T(DOT), T(DOT), T(SPACE), END); //---.. } break; case 9: //Number 9-( if (record->event.pressed) { - if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { - clear_mods(); + if (mc_shift_on == true) { return MACRO(T(MINS), T(DOT), T(MINS), T(MINS), T(DOT), T(SPACE), END); //-.--. } else { @@ -529,232 +497,149 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { break; case 10: //Letter A if (record->event.pressed) { - if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { - clear_mods(); - } return MACRO(T(DOT), T(MINS), T(SPACE), END); //.- } break; case 11: //Letter B if (record->event.pressed) { - if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { - clear_mods(); - } return MACRO(T(MINS), T(DOT), T(DOT), T(DOT), T(SPACE), END); //-... } break; case 12: //Letter C if (record->event.pressed) { - if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { - clear_mods(); - } return MACRO(T(MINS), T(DOT), T(MINS), T(DOT), T(SPACE), END); //-.-. } break; case 13: //Letter D if (record->event.pressed) { - if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { - clear_mods(); - } return MACRO(T(MINS), T(DOT), T(DOT), T(SPACE), END); //-.. } break; case 14: //Letter E if (record->event.pressed) { - if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { - clear_mods(); - } return MACRO(T(DOT), T(SPACE), END); //. } break; case 15: //Letter F if (record->event.pressed) { - if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { - clear_mods(); - } return MACRO(T(DOT), T(DOT), T(MINS), T(DOT), T(SPACE), END); //..-. } break; case 16: //Letter G if (record->event.pressed) { - if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { - clear_mods(); - } return MACRO(T(MINS), T(MINS), T(DOT), T(SPACE), END); //--. } break; case 17: //Letter H if (record->event.pressed) { - if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { - clear_mods(); - } return MACRO(T(DOT), T(DOT), T(DOT), T(DOT), T(SPACE), END); //.... } break; case 18: //Letter I if (record->event.pressed) { - if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { - clear_mods(); - } return MACRO(T(DOT), T(DOT), T(SPACE), END); //.. } break; case 19: //Letter J if (record->event.pressed) { - if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { - clear_mods(); - } return MACRO(T(DOT), T(MINS), T(MINS), T(MINS), T(SPACE), END); //.--- } break; case 20: //Letter K if (record->event.pressed) { - if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { - clear_mods(); - } return MACRO(T(MINS), T(DOT), T(MINS), T(SPACE), END); //-.- } break; case 21: //Letter L if (record->event.pressed) { - if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { - clear_mods(); - } return MACRO(T(DOT), T(MINS), T(DOT), T(DOT), T(SPACE), END); //.-.. } break; case 22: //Letter M if (record->event.pressed) { - if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { - clear_mods(); - } return MACRO(T(MINS), T(MINS), T(SPACE), END); //-- } break; case 23: //Letter N if (record->event.pressed) { - if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { - clear_mods(); - } return MACRO(T(MINS), T(DOT), T(SPACE), END); //-. } break; case 24: //Letter O if (record->event.pressed) { - if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { - clear_mods(); - } return MACRO(T(MINS), T(MINS), T(MINS), T(SPACE), END); //--- } break; case 25: //Letter P if (record->event.pressed) { - if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { - clear_mods(); - } return MACRO(T(DOT), T(MINS), T(MINS), T(DOT), T(SPACE), END); //.--. } break; case 26: //Letter Q if (record->event.pressed) { - if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { - clear_mods(); - } return MACRO(T(MINS), T(MINS), T(DOT), T(MINS), T(SPACE), END); //--.- } break; case 27: //Letter R if (record->event.pressed) { - if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { - clear_mods(); - } return MACRO(T(DOT), T(MINS), T(DOT), T(SPACE), END); //.-. } break; case 28: //Letter S if (record->event.pressed) { - if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { - clear_mods(); - } return MACRO(T(DOT), T(DOT), T(DOT), T(SPACE), END); //... } break; case 29: //Letter T if (record->event.pressed) { - if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { - clear_mods(); - } return MACRO(T(MINS), T(SPACE), END); //- } break; case 30: //Letter U if (record->event.pressed) { - if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { - clear_mods(); - } return MACRO(T(DOT), T(DOT), T(MINS), T(SPACE), END); //..- } break; case 31: //Letter V if (record->event.pressed) { - if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { - clear_mods(); - } return MACRO(T(DOT), T(DOT), T(DOT), T(MINS), T(SPACE), END); //...- } break; case 32: //Letter W if (record->event.pressed) { - if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { - clear_mods(); - } return MACRO(T(DOT), T(MINS), T(MINS), T(SPACE), END); //.-- } break; case 33: //Letter X if (record->event.pressed) { - if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { - clear_mods(); - } return MACRO(T(MINS), T(DOT), T(DOT), T(MINS), T(SPACE), END); //-..- } break; case 34: //Letter Y if (record->event.pressed) { - if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { - clear_mods(); + if (mc_shift_on == true) { } return MACRO(T(MINS), T(DOT), T(MINS), T(MINS), T(SPACE), END); //-.-- } break; case 35: //Letter Z if (record->event.pressed) { - if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { - clear_mods(); - } return MACRO(T(MINS), T(MINS), T(DOT), T(DOT), T(SPACE), END); //--.. } break; case 36: //Punctuation . if (record->event.pressed) { - if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { - clear_mods(); - } return MACRO(T(DOT), T(MINS), T(DOT), T(MINS), T(DOT), T(MINS), T(SPACE), END); //.-.-.- } break; case 37: //Punctuation , if (record->event.pressed) { - if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { - clear_mods(); - } return MACRO(T(MINS), T(MINS), T(DOT), T(DOT), T(MINS), T(MINS), T(SPACE), END); //--..-- } break; case 38: //Punctuation '-" if (record->event.pressed) { - if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { - clear_mods(); + if (mc_shift_on == true) { return MACRO(T(DOT), T(MINS), T(DOT), T(DOT), T(MINS), T(DOT), T(SPACE), END); //.-..-. } else { @@ -764,8 +649,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { break; case 39: //Punctuation /-? if (record->event.pressed) { - if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { - clear_mods(); + if (mc_shift_on == true) { return MACRO(T(DOT), T(DOT), T(MINS), T(MINS), T(DOT), T(DOT), T(SPACE), END); //..--.. } else { @@ -775,8 +659,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { break; case 40: //Punctuation ;-: if (record->event.pressed) { - if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { - clear_mods(); + if (mc_shift_on == true) { return MACRO(T(MINS), T(MINS), T(MINS), T(DOT), T(DOT), T(DOT), T(SPACE), END); //---... } else { @@ -786,8 +669,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { break; case 41: //Punctuation =-+ if (record->event.pressed) { - if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { - clear_mods(); + if (mc_shift_on == true) { return MACRO(T(DOT), T(MINS), T(DOT), T(MINS), T(DOT), T(SPACE), END); //.-.-. } else { @@ -797,8 +679,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { break; case 42: //Punctuation --_ if (record->event.pressed) { - if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { - clear_mods(); + if (mc_shift_on == true) { return MACRO(T(DOT), T(DOT), T(MINS), T(MINS), T(DOT), T(MINS), T(SPACE), END); //..--.- } else { @@ -808,9 +689,6 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { break; case 43: //Morse Space if (record->event.pressed) { - if (keyboard_report->mods & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { - clear_mods(); - } return MACRO(T(BSLS), T(SPACE), END); //When pressed, this sends a slash followed by a space, making it easier to distinguish words in Morse } break; @@ -833,6 +711,14 @@ bool process_record_user (uint16_t keycode, keyrecord_t *record) { } } break; + case MC_LSFT ... MC_RSFT: + if (record->event.pressed) { + mc_shift_on = true; + } + else { + mc_shift_on = false; + } + break; } return true; } From 5a70cb30eecc8b76410e4b21a225b10c344e12c7 Mon Sep 17 00:00:00 2001 From: Stick Date: Thu, 8 Jun 2017 08:59:30 -0500 Subject: [PATCH 065/238] trying to fix LEDs --- keyboards/ergodox/keymaps/familiar/keymap.c | 42 ++++++++++----------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/keyboards/ergodox/keymaps/familiar/keymap.c b/keyboards/ergodox/keymaps/familiar/keymap.c index 513bb5541..1dd1d5cbc 100644 --- a/keyboards/ergodox/keymaps/familiar/keymap.c +++ b/keyboards/ergodox/keymaps/familiar/keymap.c @@ -242,26 +242,26 @@ void matrix_init_user(void) { // Runs constantly in the background, in a loop. void matrix_scan_user(void) { - // uint8_t layer = biton32(layer_state); - // - // ergodox_board_led_off(); - // ergodox_right_led_1_off(); - // ergodox_right_led_2_off(); - // ergodox_right_led_3_off(); - // switch (layer) { - // case INTL: - // case INSF: - // ergodox_right_led_1_on(); - // break; - // case NUMP: - // ergodox_right_led_2_on(); - // break; - // case ARRW: - // ergodox_right_led_3_on(); - // break; - // default: - // // none - // break; - // } + uint8_t layer = biton32(layer_state); + + ergodox_board_led_off(); + ergodox_right_led_1_off(); + ergodox_right_led_2_off(); + ergodox_right_led_3_off(); + switch (layer) { + case INTL: + case INSF: + ergodox_right_led_1_on(); + break; + case NUMP: + ergodox_right_led_2_on(); + break; + case ARRW: + ergodox_right_led_3_on(); + break; + default: + // none + break; + } }; From 4b50ab029d49830cf0efd0e5e0606cb39c8dabae Mon Sep 17 00:00:00 2001 From: Stick Date: Thu, 8 Jun 2017 08:59:33 -0500 Subject: [PATCH 066/238] Revert "ugly workaround for ErgoDoxEZ LED bugs: turn 'em all off" This reverts commit f397402e101774eedd1748b1e31c7386f927d4ed. --- keyboards/ergodox/ez/ez.c | 42 ++++++++++----------- keyboards/ergodox/ez/matrix.c | 3 +- keyboards/ergodox/keymaps/familiar/keymap.c | 2 +- 3 files changed, 24 insertions(+), 23 deletions(-) diff --git a/keyboards/ergodox/ez/ez.c b/keyboards/ergodox/ez/ez.c index 55b51f6fa..3e19f2302 100644 --- a/keyboards/ergodox/ez/ez.c +++ b/keyboards/ergodox/ez/ez.c @@ -22,30 +22,30 @@ void matrix_init_kb(void) { PORTD |= (1<<5 | 1<<4); PORTE |= (1<<6); - //ergodox_blink_all_leds(); + ergodox_blink_all_leds(); matrix_init_user(); } -// void ergodox_blink_all_leds(void) -// { -// ergodox_led_all_off(); -// ergodox_led_all_set(LED_BRIGHTNESS_HI); -// ergodox_right_led_1_on(); -// _delay_ms(50); -// ergodox_right_led_2_on(); -// _delay_ms(50); -// ergodox_right_led_3_on(); -// _delay_ms(50); -// ergodox_right_led_1_off(); -// _delay_ms(50); -// ergodox_right_led_2_off(); -// _delay_ms(50); -// ergodox_right_led_3_off(); -// //ergodox_led_all_on(); -// //_delay_ms(333); -// ergodox_led_all_off(); -// } +void ergodox_blink_all_leds(void) +{ + ergodox_led_all_off(); + ergodox_led_all_set(LED_BRIGHTNESS_HI); + ergodox_right_led_1_on(); + _delay_ms(50); + ergodox_right_led_2_on(); + _delay_ms(50); + ergodox_right_led_3_on(); + _delay_ms(50); + ergodox_right_led_1_off(); + _delay_ms(50); + ergodox_right_led_2_off(); + _delay_ms(50); + ergodox_right_led_3_off(); + //ergodox_led_all_on(); + //_delay_ms(333); + ergodox_led_all_off(); +} uint8_t init_mcp23018(void) { mcp23018_status = 0x20; @@ -57,7 +57,7 @@ uint8_t init_mcp23018(void) { // cli(); if (i2c_initialized == 0) { i2c_init(); // on pins D(1,0) - i2c_initialized = 1; + i2c_initialized++; _delay_ms(1000); } diff --git a/keyboards/ergodox/ez/matrix.c b/keyboards/ergodox/ez/matrix.c index a489e5b5c..21b60a542 100644 --- a/keyboards/ergodox/ez/matrix.c +++ b/keyboards/ergodox/ez/matrix.c @@ -183,7 +183,7 @@ uint8_t matrix_scan(void) print("left side not responding\n"); } else { print("left side attached\n"); -// ergodox_blink_all_leds(); + ergodox_blink_all_leds(); } } } @@ -391,3 +391,4 @@ static void select_row(uint8_t row) } } } + diff --git a/keyboards/ergodox/keymaps/familiar/keymap.c b/keyboards/ergodox/keymaps/familiar/keymap.c index 1dd1d5cbc..714118d93 100644 --- a/keyboards/ergodox/keymaps/familiar/keymap.c +++ b/keyboards/ergodox/keymaps/familiar/keymap.c @@ -56,7 +56,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { MT(MOD_RALT, KC_LBRC), KC_RBRC, KC_LEFT, KC_DOWN, KC_RGHT, KC_PSCR, _______, KC_NLCK, - TG(NUMP), LT(ARRW, KC_BSLS), KC_SPC + TG(NUMP), LT(ARRW, C_BSLS), KC_SPC ), /* layer 1: International symbols, etc From 6bd4df7a90e6137653c22b5dffa95870566eb4fd Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Sun, 11 Jun 2017 14:28:30 -0400 Subject: [PATCH 067/238] define limits to functions --- docs/key_functions.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/key_functions.md b/docs/key_functions.md index c0f06f9c8..74b80b42f 100644 --- a/docs/key_functions.md +++ b/docs/key_functions.md @@ -6,6 +6,10 @@ These functions work the same way that their `ACTION_*` functions do - they're j Instead of using `FNx` when defining `ACTION_*` functions, you can use `F(x)` - the benefit here is being able to use more than 32 function actions (up to 4096), if you happen to need them. +### Limits of these aliases + +Currently, the keycodes able to used with these functions are limited to the TMK ones, meaning you can't use keycodes like `KC_TILD`, or anything greater than 0xFF. For a full list of the keycodes able to be used, [see this list](keycode.txt). + ### Switching and toggling layers `MO(layer)` - momentary switch to *layer*. As soon as you let go of the key, the layer is deactivated and you pop back out to the previous layer. When you apply this to a key, that same key must be set as `KC_TRNS` on the destination layer. Otherwise, you won't make it back to the original layer when you release the key (and you'll get a keycode sent). You can only switch to layers *above* your current layer. If you're on layer 0 and you use `MO(1)`, that will switch to layer 1 just fine. But if you include `MO(3)` on layer 5, that won't do anything for you -- because layer 3 is lower than layer 5 on the stack. From c02f9a6ee495ede47d7726ffaf8d21271ed21642 Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Sun, 11 Jun 2017 15:36:28 -0400 Subject: [PATCH 068/238] remove most .pngs --- .gitignore | 5 + .../ergodox/keymaps/ab/keyboard-layout.png | Bin 80776 -> 0 bytes keyboards/ergodox/keymaps/ab/readme.md | 2 +- .../keymaps/absenth/absenth_highres.png | Bin 1463041 -> 0 bytes keyboards/ergodox/keymaps/absenth/readme.md | 2 +- keyboards/ergodox/keymaps/bepo/bepo.png | Bin 80249 -> 0 bytes keyboards/ergodox/keymaps/bepo/readme.md | 2 + .../colemak_osx_pc_no/keyboard-layout.png | Bin 103158 -> 0 bytes .../keymaps/colemak_osx_pc_no/readme.md | 2 +- .../ergodox/keymaps/csharp_dev/csharp_dev.png | Bin 97642 -> 0 bytes .../keymaps/csharp_dev/csharp_dev_legend.png | Bin 387797 -> 0 bytes .../ergodox/keymaps/csharp_dev/readme.md | 3 +- keyboards/ergodox/keymaps/default/default.png | Bin 193672 -> 0 bytes .../ergodox/keymaps/default/default.png.md | 1 + .../default/default_firmware_v1.2-2.png | Bin 257921 -> 0 bytes .../keymaps/default/default_highres.png | Bin 1459389 -> 0 bytes .../keymaps/default/default_highres.png.md | 1 + keyboards/ergodox/keymaps/default/readme.md | 2 +- .../default_osx/default_osx_highres.png | Bin 772418 -> 0 bytes .../ergodox/keymaps/default_osx/readme.md | 2 +- keyboards/ergodox/keymaps/dvorak/dvorak.png | Bin 87314 -> 0 bytes .../ergodox/keymaps/dvorak/dvorak.png.md | 1 + .../dvorak_intl_squisher/keyboard-layout0.png | Bin 73585 -> 0 bytes .../dvorak_intl_squisher/keyboard-layout1.png | Bin 59122 -> 0 bytes .../dvorak_intl_squisher/keyboard-layout2.png | Bin 53319 -> 0 bytes .../keymaps/dvorak_intl_squisher/readme.md | 6 +- .../keymaps/emacs_osx_dk/default_highres.png | Bin 142146 -> 0 bytes .../ergodox/keymaps/emacs_osx_dk/readme.md | 2 +- keyboards/ergodox/keymaps/familiar/README.md | 2 +- .../ergodox/keymaps/familiar/familiar.png | Bin 149846 -> 0 bytes .../keymaps/german-kinergo/layout-code.png | Bin 55386 -> 0 bytes .../keymaps/german-kinergo/layout-media.png | Bin 67634 -> 0 bytes .../ergodox/keymaps/german-kinergo/layout.png | Bin 71175 -> 0 bytes .../ergodox/keymaps/german-kinergo/readme.md | 6 +- .../ergodox/keymaps/jafo/jafo_highres.png | Bin 179460 -> 0 bytes keyboards/ergodox/keymaps/jafo/readme.md | 2 +- .../keyboard-layout.png | Bin 140077 -> 0 bytes .../norwegian_programmer_osx_pc/readme.md | 2 +- .../keyboard-layout.png | Bin 97519 -> 0 bytes .../readme.md | 2 +- .../keymaps/ordinary/ordinary-base.png | Bin 120512 -> 0 bytes .../keymaps/ordinary/ordinary-media.png | Bin 123523 -> 0 bytes .../keymaps/ordinary/ordinary-special.png | Bin 68292 -> 0 bytes .../keymaps/ordinary/ordinary-symbol.png | Bin 90642 -> 0 bytes keyboards/ergodox/keymaps/ordinary/readme.md | 8 +- .../ergodox/keymaps/osx_de/osx_de_highres.png | Bin 298446 -> 0 bytes .../keymaps/osx_de/osx_de_highres.png.md | 1 + .../osx_de_adnw_koy_highres.png | Bin 183892 -> 0 bytes .../osx_de_adnw_koy_highres.png.md | 1 + .../osx_de_experimental_highres.png | Bin 303904 -> 0 bytes .../osx_de_experimental_highres.png.md | 1 + .../osx_whiskey_tango_foxtrot_capslock.png | Bin 185064 -> 0 bytes .../readme.md | 2 +- keyboards/ergodox/keymaps/plums/plums.png | Bin 223300 -> 0 bytes keyboards/ergodox/keymaps/plums/readme.md | 2 +- .../romanzolotarev-norman-osx/readme.md | 2 +- .../romanzolotarev-norman-osx.png | Bin 96954 -> 0 bytes .../readme.md | 2 +- .../romanzolotarev-norman-plover-osx-hjkl.png | Bin 130692 -> 0 bytes .../readme.md | 2 +- .../romanzolotarev-norman-plover-osx.png | Bin 130464 -> 0 bytes .../readme.md | 2 +- .../romanzolotarev-norman-qwerty-osx.png | Bin 100627 -> 0 bytes .../ergodox/keymaps/siroken3/default.png | Bin 193672 -> 0 bytes .../ergodox/keymaps/siroken3/default.png.md | 1 + .../siroken3/default_firmware_v1.2-2.png | Bin 257921 -> 0 bytes .../keymaps/siroken3/default_highres.png | Bin 1459389 -> 0 bytes .../keymaps/siroken3/default_highres.png.md | 1 + keyboards/ergodox/keymaps/siroken3/readme.md | 2 +- .../keymaps/swissgerman/keyboard-layout.png | Bin 75633 -> 0 bytes .../swissgerman/keyboard-layout_1_2.png | Bin 58099 -> 0 bytes .../ergodox/keymaps/swissgerman/readme.md | 4 +- .../keymaps/teckinesis/ordinary-special.png | Bin 63065 -> 0 bytes .../teckinesis/ordinary-special.png.md | 1 + .../ergodox/keymaps/teckinesis/readme.md | 6 +- .../keymaps/teckinesis/teckinesis-base.png | Bin 93743 -> 0 bytes .../keymaps/teckinesis/teckinesis-media.png | Bin 112216 -> 0 bytes .../keymaps/teckinesis/teckinesis-symbol.png | Bin 97350 -> 0 bytes .../keymaps/tkuichooseyou/compiled.hex | 1137 ---------------- keyboards/ergodox/keymaps/townk_osx/readme.md | 6 +- .../keymaps/townk_osx/townk_osx_base.png | Bin 785859 -> 0 bytes .../keymaps/townk_osx/townk_osx_fn.png | Bin 390041 -> 0 bytes .../keymaps/townk_osx/townk_osx_keypad.png | Bin 424425 -> 0 bytes .../twentylives_dvorak_with_hebrew/keymap.png | Bin 119825 -> 0 bytes .../keymap2.png | Bin 292705 -> 0 bytes .../twentylives_dvorak_with_hebrew/readme.md | 4 +- .../keymaps/zweihander-osx/zweihander-osx.hex | 1151 ----------------- keyboards/ergodox/readme.md | 2 +- 88 files changed, 56 insertions(+), 2327 deletions(-) delete mode 100644 keyboards/ergodox/keymaps/ab/keyboard-layout.png delete mode 100644 keyboards/ergodox/keymaps/absenth/absenth_highres.png delete mode 100644 keyboards/ergodox/keymaps/bepo/bepo.png delete mode 100644 keyboards/ergodox/keymaps/colemak_osx_pc_no/keyboard-layout.png delete mode 100644 keyboards/ergodox/keymaps/csharp_dev/csharp_dev.png delete mode 100644 keyboards/ergodox/keymaps/csharp_dev/csharp_dev_legend.png delete mode 100644 keyboards/ergodox/keymaps/default/default.png create mode 100644 keyboards/ergodox/keymaps/default/default.png.md delete mode 100644 keyboards/ergodox/keymaps/default/default_firmware_v1.2-2.png delete mode 100644 keyboards/ergodox/keymaps/default/default_highres.png create mode 100644 keyboards/ergodox/keymaps/default/default_highres.png.md delete mode 100644 keyboards/ergodox/keymaps/default_osx/default_osx_highres.png delete mode 100644 keyboards/ergodox/keymaps/dvorak/dvorak.png create mode 100644 keyboards/ergodox/keymaps/dvorak/dvorak.png.md delete mode 100644 keyboards/ergodox/keymaps/dvorak_intl_squisher/keyboard-layout0.png delete mode 100644 keyboards/ergodox/keymaps/dvorak_intl_squisher/keyboard-layout1.png delete mode 100644 keyboards/ergodox/keymaps/dvorak_intl_squisher/keyboard-layout2.png delete mode 100644 keyboards/ergodox/keymaps/emacs_osx_dk/default_highres.png delete mode 100644 keyboards/ergodox/keymaps/familiar/familiar.png delete mode 100644 keyboards/ergodox/keymaps/german-kinergo/layout-code.png delete mode 100644 keyboards/ergodox/keymaps/german-kinergo/layout-media.png delete mode 100644 keyboards/ergodox/keymaps/german-kinergo/layout.png delete mode 100644 keyboards/ergodox/keymaps/jafo/jafo_highres.png delete mode 100644 keyboards/ergodox/keymaps/norwegian_programmer_osx_pc/keyboard-layout.png delete mode 100644 keyboards/ergodox/keymaps/norwegian_programmer_osx_pc_colemak/keyboard-layout.png delete mode 100644 keyboards/ergodox/keymaps/ordinary/ordinary-base.png delete mode 100644 keyboards/ergodox/keymaps/ordinary/ordinary-media.png delete mode 100644 keyboards/ergodox/keymaps/ordinary/ordinary-special.png delete mode 100644 keyboards/ergodox/keymaps/ordinary/ordinary-symbol.png delete mode 100644 keyboards/ergodox/keymaps/osx_de/osx_de_highres.png create mode 100644 keyboards/ergodox/keymaps/osx_de/osx_de_highres.png.md delete mode 100644 keyboards/ergodox/keymaps/osx_de_adnw_koy/osx_de_adnw_koy_highres.png create mode 100644 keyboards/ergodox/keymaps/osx_de_adnw_koy/osx_de_adnw_koy_highres.png.md delete mode 100644 keyboards/ergodox/keymaps/osx_de_experimental/osx_de_experimental_highres.png create mode 100644 keyboards/ergodox/keymaps/osx_de_experimental/osx_de_experimental_highres.png.md delete mode 100644 keyboards/ergodox/keymaps/osx_whiskey_tango_foxtrot_capslock/osx_whiskey_tango_foxtrot_capslock.png delete mode 100644 keyboards/ergodox/keymaps/plums/plums.png delete mode 100644 keyboards/ergodox/keymaps/romanzolotarev-norman-osx/romanzolotarev-norman-osx.png delete mode 100644 keyboards/ergodox/keymaps/romanzolotarev-norman-plover-osx-hjkl/romanzolotarev-norman-plover-osx-hjkl.png delete mode 100644 keyboards/ergodox/keymaps/romanzolotarev-norman-plover-osx/romanzolotarev-norman-plover-osx.png delete mode 100644 keyboards/ergodox/keymaps/romanzolotarev-norman-qwerty-osx/romanzolotarev-norman-qwerty-osx.png delete mode 100644 keyboards/ergodox/keymaps/siroken3/default.png create mode 100644 keyboards/ergodox/keymaps/siroken3/default.png.md delete mode 100644 keyboards/ergodox/keymaps/siroken3/default_firmware_v1.2-2.png delete mode 100644 keyboards/ergodox/keymaps/siroken3/default_highres.png create mode 100644 keyboards/ergodox/keymaps/siroken3/default_highres.png.md delete mode 100644 keyboards/ergodox/keymaps/swissgerman/keyboard-layout.png delete mode 100644 keyboards/ergodox/keymaps/swissgerman/keyboard-layout_1_2.png delete mode 100644 keyboards/ergodox/keymaps/teckinesis/ordinary-special.png create mode 100644 keyboards/ergodox/keymaps/teckinesis/ordinary-special.png.md delete mode 100644 keyboards/ergodox/keymaps/teckinesis/teckinesis-base.png delete mode 100644 keyboards/ergodox/keymaps/teckinesis/teckinesis-media.png delete mode 100644 keyboards/ergodox/keymaps/teckinesis/teckinesis-symbol.png delete mode 100644 keyboards/ergodox/keymaps/tkuichooseyou/compiled.hex delete mode 100644 keyboards/ergodox/keymaps/townk_osx/townk_osx_base.png delete mode 100644 keyboards/ergodox/keymaps/townk_osx/townk_osx_fn.png delete mode 100644 keyboards/ergodox/keymaps/townk_osx/townk_osx_keypad.png delete mode 100644 keyboards/ergodox/keymaps/twentylives_dvorak_with_hebrew/keymap.png delete mode 100644 keyboards/ergodox/keymaps/twentylives_dvorak_with_hebrew/keymap2.png delete mode 100644 keyboards/ergodox/keymaps/zweihander-osx/zweihander-osx.hex diff --git a/.gitignore b/.gitignore index 0b48b80e5..9381f1afe 100644 --- a/.gitignore +++ b/.gitignore @@ -34,3 +34,8 @@ CMakeLists.txt util/Win_Check_Output.txt .vscode .stfolder + +# ignore image files +*.png +*.jpg +*.gif \ No newline at end of file diff --git a/keyboards/ergodox/keymaps/ab/keyboard-layout.png b/keyboards/ergodox/keymaps/ab/keyboard-layout.png deleted file mode 100644 index 740684461e060bfd1053c1b5b6e32720fee70036..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 80776 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%0DR3O^syKUI85e1lluuxF% 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 g1oW;+Z{{Ca`yFz>% diff --git a/keyboards/ergodox/keymaps/ab/readme.md b/keyboards/ergodox/keymaps/ab/readme.md index 4ad80efe6..fde1c1726 100644 --- a/keyboards/ergodox/keymaps/ab/readme.md +++ b/keyboards/ergodox/keymaps/ab/readme.md @@ -1,7 +1,7 @@ # Beginner's keymap for Ergodox-EZ Beginner's keymap emulates standard QWERTY keyboard for beginners. Once you get comfortable with the Ergodox-EZ, you may fork this keymap and customize it for your own needs or find a suitable one from the community contributed keymaps. -![Beginner's Keymap](keyboard-layout.png) +![Beginner's Keymap](https://i.imgur.com/dAIocc8.png) #### Pros * Easier to switch between regular keyboards and Ergodox-EZ. diff --git a/keyboards/ergodox/keymaps/absenth/absenth_highres.png b/keyboards/ergodox/keymaps/absenth/absenth_highres.png deleted file mode 100644 index c07aa8803fb611caea0f87c529739c61d084d432..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1463041 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