~ruther/qmk_firmware

c204c735af9fc5bf2438ca4fedfc8914529d660e — Takeshi ISHII 3 years ago f30f963
Helix/pico move to split_common (#16418)

M keyboards/helix/pico/config.h => keyboards/helix/pico/config.h +2 -8
@@ 1,6 1,7 @@
/*
Copyright 2012 Jun Wako <wakojun@gmail.com>
Copyright 2015 Jack Humbert
Copyright 2018 MakotoKurauchi

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


@@ 42,12 43,6 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
// #define MASTER_RIGHT
// #define EE_HANDS

// Helix keyboard OLED support
//      see ./rules.mk: OLED_ENABLE=yes or no
#ifdef OLED_ENABLE
  #define SSD1306OLED
#endif

/* key matrix size */
// Rows are doubled-up
#define MATRIX_ROWS 8


@@ 114,8 109,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.

#if defined(RGBLIGHT_ENABLE) && !defined(IOS_DEVICE_ENABLE)
// USB_MAX_POWER_CONSUMPTION value for Helix keyboard
//  120  RGBoff, OLEDoff
//  120  OLED
//  120  RGBoff
//  330  RGB 6
//  300  RGB 32
//  310  OLED & RGB 32

M keyboards/helix/pico/keymaps/biacco/keymap.c => keyboards/helix/pico/keymaps/biacco/keymap.c +15 -20
@@ 1,24 1,19 @@
/* Copyright 2018 Biacco42
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
#include QMK_KEYBOARD_H
#include "bootloader.h"
#ifdef PROTOCOL_LUFA
#include "lufa.h"
#include "split_util.h"
#endif
#ifdef AUDIO_ENABLE
  #include "audio.h"
#endif
#ifdef SSD1306OLED
  #include "ssd1306.h"
#endif

extern keymap_config_t keymap_config;

#ifdef RGBLIGHT_ENABLE
//Following line allows macro to read current RGB settings
extern rgblight_config_t rgblight_config;
#endif

extern uint8_t is_master;

// Each layer gets a name for readability, which is then used in the keymap matrix below.
// The underscores don't mean anything - you can have a layer called STUFF or any other name.

M keyboards/helix/pico/keymaps/biacco/rules.mk => keyboards/helix/pico/keymaps/biacco/rules.mk +2 -4
@@ 10,10 10,8 @@ AUDIO_ENABLE = yes           # Audio output on port B5
LTO_ENABLE = no  # if firmware size over limit, try this option

# Helix Spacific Build Options
# you can uncomment and edit follows 6 Variables
#  jp: 以下の6つの変数を必要に応じて編集し、コメントアウトをはずします。
# OLED_ENABLE = no            # OLED_ENABLE
# LOCAL_GLCDFONT = no         # use each keymaps "helixfont.h" insted of "common/glcdfont.c"
# you can uncomment and edit follows 4 Variables
#  jp: 以下の4つの変数を必要に応じて編集し、コメントアウトをはずします。
# LED_BACK_ENABLE = no        # LED backlight (Enable WS2812 RGB underlight.)
# LED_UNDERGLOW_ENABLE = no   # LED underglow (Enable WS2812 RGB underlight.)
LED_ANIMATIONS = no           # LED animations

M keyboards/helix/pico/keymaps/default/keymap.c => keyboards/helix/pico/keymaps/default/keymap.c +15 -120
@@ 1,24 1,25 @@
/* Copyright 2018 MakotoKurauchi
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
#include QMK_KEYBOARD_H
#include "bootloader.h"
#ifdef PROTOCOL_LUFA
#include "lufa.h"
#include "split_util.h"
#endif
#ifdef AUDIO_ENABLE
  #include "audio.h"
#endif
#ifdef SSD1306OLED
  #include "ssd1306.h"
#endif


#ifdef RGBLIGHT_ENABLE
//Following line allows macro to read current RGB settings
extern rgblight_config_t rgblight_config;
#endif

extern uint8_t is_master;

// Each layer gets a name for readability, which is then used in the keymap matrix below.
// The underscores don't mean anything - you can have a layer called STUFF or any other name.
// Layer names don't all need to be of the same length, obviously, and you can also skip them


@@ 334,10 335,6 @@ void matrix_init_user(void) {
    #ifdef RGBLIGHT_ENABLE
      RGB_current_mode = rgblight_config.mode;
    #endif
    //SSD1306 OLED init, make sure to add #define SSD1306OLED in config.h
    #ifdef SSD1306OLED
        iota_gfx_init(!has_usb());   // turns on the display
    #endif
}




@@ 365,105 362,3 @@ void music_scale_user(void)
}

#endif


//SSD1306 OLED update loop, make sure to add #define SSD1306OLED in config.h
#ifdef SSD1306OLED

void matrix_scan_user(void) {
     iota_gfx_task();  // this is what updates the display continuously
}

void matrix_update(struct CharacterMatrix *dest,
                          const struct CharacterMatrix *source) {
  if (memcmp(dest->display, source->display, sizeof(dest->display))) {
    memcpy(dest->display, source->display, sizeof(dest->display));
    dest->dirty = true;
  }
}

//assign the right code to your layers for OLED display
#define L_BASE 0
#define L_LOWER (1<<_LOWER)
#define L_RAISE (1<<_RAISE)
#define L_ADJUST (1<<_ADJUST)
#define L_ADJUST_TRI (L_ADJUST|L_RAISE|L_LOWER)

static void render_logo(struct CharacterMatrix *matrix) {

  static char logo[]={
    0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,0x90,0x91,0x92,0x93,0x94,
    0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,0xb0,0xb1,0xb2,0xb3,0xb4,
    0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,0xd0,0xd1,0xd2,0xd3,0xd4,
    0};
  matrix_write(matrix, logo);
  //matrix_write_P(&matrix, PSTR(" Split keyboard kit"));
}



void render_status(struct CharacterMatrix *matrix) {

  // Render to mode icon
  static char logo[][2][3]={{{0x95,0x96,0},{0xb5,0xb6,0}},{{0x97,0x98,0},{0xb7,0xb8,0}}};
  if(keymap_config.swap_lalt_lgui==false){
    matrix_write(matrix, logo[0][0]);
    matrix_write_P(matrix, PSTR("\n"));
    matrix_write(matrix, logo[0][1]);
  }else{
    matrix_write(matrix, logo[1][0]);
    matrix_write_P(matrix, PSTR("\n"));
    matrix_write(matrix, logo[1][1]);
  }

  // Define layers here, Have not worked out how to have text displayed for each layer. Copy down the number you see and add a case for it below
  char buf[40];
  snprintf(buf,sizeof(buf), "Undef-%ld", layer_state);
  matrix_write_P(matrix, PSTR("\nLayer: "));
    switch (layer_state) {
        case L_BASE:
           matrix_write_P(matrix, PSTR("Default"));
           break;
        case L_RAISE:
           matrix_write_P(matrix, PSTR("Raise"));
           break;
        case L_LOWER:
           matrix_write_P(matrix, PSTR("Lower"));
           break;
        case L_ADJUST:
        case L_ADJUST_TRI:
           matrix_write_P(matrix, PSTR("Adjust"));
           break;
        default:
           matrix_write(matrix, buf);
    }

  // Host Keyboard LED Status
  char led[40];
    snprintf(led, sizeof(led), "\n%s  %s  %s",
            (host_keyboard_leds() & (1<<USB_LED_NUM_LOCK)) ? "NUMLOCK" : "       ",
            (host_keyboard_leds() & (1<<USB_LED_CAPS_LOCK)) ? "CAPS" : "    ",
            (host_keyboard_leds() & (1<<USB_LED_SCROLL_LOCK)) ? "SCLK" : "    ");
  matrix_write(matrix, led);
}


void iota_gfx_task_user(void) {
  struct CharacterMatrix matrix;

#if DEBUG_TO_SCREEN
  if (debug_enable) {
    return;
  }
#endif

  matrix_clear(&matrix);
  if(is_master){
    render_status(&matrix);
  }else{
    render_logo(&matrix);
  }
  matrix_update(&display, &matrix);
}

#endif

M keyboards/helix/pico/keymaps/default/readme.md => keyboards/helix/pico/keymaps/default/readme.md +2 -4
@@ 96,10 96,8 @@ see `qmk_firmware/keyboards/helix/pico/keymaps/default/rules.mk`

```
# Helix Spacific Build Options
# you can uncomment and edit follows 6 Variables
#  jp: 以下の6つの変数を必要に応じて編集し、コメントアウトをはずします。
# OLED_ENABLE = no            # OLED_ENABLE
# LOCAL_GLCDFONT = no         # use each keymaps "helixfont.h" insted of "common/glcdfont.c"
# you can uncomment and edit follows 4 Variables
#  jp: 以下の4つの変数を必要に応じて編集し、コメントアウトをはずします。
# LED_BACK_ENABLE = no        # LED backlight (Enable WS2812 RGB underlight.)
# LED_UNDERGLOW_ENABLE = no   # LED underglow (Enable WS2812 RGB underlight.)
# LED_ANIMATIONS = yes        # LED animations

M keyboards/helix/pico/keymaps/default/readme_jp.md => keyboards/helix/pico/keymaps/default/readme_jp.md +2 -12
@@ 58,16 58,13 @@

## カスタマイズ

オプションの OLED をつけたり、
RGB バックライトまたは、RGB Underglow をつけた場合は、
`qmk_firmware/keyboards/helix/pico/keymaps/default/rules.mk` の以下の部分を編集して機能を有効化してください。

```
# Helix Spacific Build Options
# you can uncomment and edit follows 6 Variables
#  jp: 以下の6つの変数を必要に応じて編集し、コメントアウトをはずします。
# OLED_ENABLE = no            # OLED_ENABLE
# LOCAL_GLCDFONT = no         # use each keymaps "helixfont.h" insted of "common/glcdfont.c"
# you can uncomment and edit follows 4 Variables
#  jp: 以下の4つの変数を必要に応じて編集し、コメントアウトをはずします。
# LED_BACK_ENABLE = no        # LED backlight (Enable WS2812 RGB underlight.)
# LED_UNDERGLOW_ENABLE = no   # LED underglow (Enable WS2812 RGB underlight.)
# LED_ANIMATIONS = yes        # LED animations


@@ 89,13 86,6 @@ rules.mk の下記の部分を編集して no を yes に変更してくださ
LED_UNDERGLOW_ENABLE = yes   # LED underglow (Enable WS2812 RGB underlight.)
```

## OLEDを有効にする

rules.mk の下記の部分を編集して no を yes に変更してください。
```
OLED_ENABLE = yes            # OLED_ENABLE
```

## iPad/iPhoneサポートを有効にする。

rules.mk の下記の部分を編集して no を yes に変更してください。

M keyboards/helix/pico/keymaps/default/rules.mk => keyboards/helix/pico/keymaps/default/rules.mk +2 -4
@@ 3,10 3,8 @@ AUDIO_ENABLE = yes          # Audio output
LTO_ENABLE = no  # if firmware size over limit, try this option

# Helix Spacific Build Options
# you can uncomment and edit follows 6 Variables
#  jp: 以下の6つの変数を必要に応じて編集し、コメントアウトをはずします。
# OLED_ENABLE = no            # OLED_ENABLE
# LOCAL_GLCDFONT = no         # use each keymaps "helixfont.h" insted of "common/glcdfont.c"
# you can uncomment and edit follows 4 Variables
#  jp: 以下の4つの変数を必要に応じて編集し、コメントアウトをはずします。
# LED_BACK_ENABLE = no        # LED backlight (Enable WS2812 RGB underlight.)
# LED_UNDERGLOW_ENABLE = no   # LED underglow (Enable WS2812 RGB underlight.)
# LED_ANIMATIONS = yes        # LED animations

M keyboards/helix/pico/keymaps/mtei/keymap.c => keyboards/helix/pico/keymaps/mtei/keymap.c +15 -148
@@ 1,31 1,23 @@
/* Copyright 2018 mtei
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
#include QMK_KEYBOARD_H
#include "bootloader.h"
#ifdef PROTOCOL_LUFA
#include "lufa.h"
#include "split_util.h"
#endif
#ifdef AUDIO_ENABLE
  #include "audio.h"
#endif
#ifdef SSD1306OLED
  #include "ssd1306.h"
#endif
#ifdef CONSOLE_ENABLE
  #include <print.h>
#endif

#define LAYOUT_wrapper(...) LAYOUT(__VA_ARGS__)
#define kc5(a,b,c,d,e) KC_##a, KC_##b, KC_##c, KC_##d, KC_##e

extern keymap_config_t keymap_config;

#ifdef RGBLIGHT_ENABLE
//Following line allows macro to read current RGB settings
extern rgblight_config_t rgblight_config;
#endif

extern uint8_t is_master;

// Each layer gets a name for readability, which is then used in the keymap matrix below.
// The underscores don't mean anything - you can have a layer called STUFF or any other name.
// Layer names don't all need to be of the same length, obviously, and you can also skip them


@@ 373,10 365,6 @@ void matrix_init_user(void) {
    #ifdef AUDIO_ENABLE
        startup_user();
    #endif
    //SSD1306 OLED init, make sure to add #define SSD1306OLED in config.h
    #ifdef SSD1306OLED
        iota_gfx_init(!has_usb());   // turns on the display
    #endif
}




@@ 404,124 392,3 @@ void music_scale_user(void)
}

#endif


//SSD1306 OLED update loop, make sure to add #define SSD1306OLED in config.h
#ifdef SSD1306OLED

void matrix_scan_user(void) {
     iota_gfx_task();  // this is what updates the display continuously
}

void matrix_update(struct CharacterMatrix *dest,
                          const struct CharacterMatrix *source) {
  if (memcmp(dest->display, source->display, sizeof(dest->display))) {
    memcpy(dest->display, source->display, sizeof(dest->display));
    dest->dirty = true;
  }
}

static void render_logo(struct CharacterMatrix *matrix) {

  static char logo[]={
    0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,0x90,0x91,0x92,0x93,0x94,
    0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,0xb0,0xb1,0xb2,0xb3,0xb4,
    0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,0xd0,0xd1,0xd2,0xd3,0xd4,
    0};
  matrix_write(matrix, logo);
#if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_ANIMATIONS)
  char buf[30];
  if(rgblight_config.enable) {
      snprintf(buf, sizeof(buf), " LED %2d: %d,%d,%d ",
               rgblight_config.mode,
               rgblight_config.hue/RGBLIGHT_HUE_STEP,
               rgblight_config.sat/RGBLIGHT_SAT_STEP,
               rgblight_config.val/RGBLIGHT_VAL_STEP);
      matrix_write(matrix, buf);
  }
#endif
  //matrix_write_P(&matrix, PSTR(" Split keyboard kit"));
}

static const char Qwerty_name[]  PROGMEM = " Qwerty";
static const char Colemak_name[] PROGMEM = " Colemak";
static const char Dvorak_name[]  PROGMEM = " Dvorak";
static const char Eucalyn_name[] PROGMEM = " Eucalyn";

static const char NumL_name[]     PROGMEM = ":NumL";
static const char NumR_name[]     PROGMEM = ":NumR";
static const char Lower_name[]   PROGMEM = ":Func";
static const char Raise_name[]   PROGMEM = ":Extra";
static const char Adjust_name[]  PROGMEM = ":Adjust";

static const char *layer_names[] = {
    [_QWERTY]  = Qwerty_name,
    [_COLEMAK] = Colemak_name,
    [_DVORAK]  = Dvorak_name,
    [_EUCALYN] = Eucalyn_name,

    [_NUML]    = NumL_name,
    [_NUMR]    = NumR_name,
    [_LOWER]   = Lower_name,
    [_RAISE]   = Raise_name,
    [_ADJUST]  = Adjust_name
};

void render_status(struct CharacterMatrix *matrix) {

  // Render to mode icon
  static char logo[][2][3]={{{0x95,0x96,0},{0xb5,0xb6,0}},{{0x97,0x98,0},{0xb7,0xb8,0}}};
  if(keymap_config.swap_lalt_lgui==false){
    matrix_write(matrix, logo[0][0]);
    matrix_write_P(matrix, PSTR("\n"));
    matrix_write(matrix, logo[0][1]);
  }else{
    matrix_write(matrix, logo[1][0]);
    matrix_write_P(matrix, PSTR("\n"));
    matrix_write(matrix, logo[1][1]);
  }

  // Define layers here, Have not worked out how to have text displayed for each layer. Copy down the number you see and add a case for it below
  int name_num;
  uint32_t lstate;
  matrix_write_P(matrix, layer_names[current_default_layer]);
  matrix_write_P(matrix, PSTR("\n"));
  for( lstate = layer_state, name_num = 0;
       lstate && name_num < sizeof(layer_names)/sizeof(char *);
       lstate >>=1, name_num++ ) {
      if( (lstate & 1) != 0 ) {
          if( layer_names[name_num] ) {
              matrix_write_P(matrix, layer_names[name_num]);
          }
      }
  }

  // Host Keyboard LED Status
  char led[40];
    snprintf(led, sizeof(led), "\n%s  %s  %s",
             (host_keyboard_leds() & (1<<USB_LED_NUM_LOCK)) ? "NUMLOCK" : "       ",
             (host_keyboard_leds() & (1<<USB_LED_CAPS_LOCK)) ? "CAPS" : "    ",
             (host_keyboard_leds() & (1<<USB_LED_SCROLL_LOCK)) ? "SCLK" : "    ");
  matrix_write(matrix, led);
}


void iota_gfx_task_user(void) {
  struct CharacterMatrix matrix;

#if DEBUG_TO_SCREEN
  if (debug_enable) {
    return;
  }
#endif

  matrix_clear(&matrix);
  if(is_master){
    render_status(&matrix);
  }else{
    render_logo(&matrix);
  }
  matrix_update(&display, &matrix);
}

#endif

M keyboards/helix/pico/keymaps/mtei/rules.mk => keyboards/helix/pico/keymaps/mtei/rules.mk +2 -4
@@ 10,10 10,8 @@ AUDIO_ENABLE = yes          # Audio output on port B5
LTO_ENABLE = no  # if firmware size over limit, try this option

# Helix Spacific Build Options
# you can uncomment and edit follows 6 Variables
#  jp: 以下の6つの変数を必要に応じて編集し、コメントアウトをはずします。
# OLED_ENABLE = no            # OLED_ENABLE
# LOCAL_GLCDFONT = no         # use each keymaps "helixfont.h" insted of "common/glcdfont.c"
# you can uncomment and edit follows 4 Variables
#  jp: 以下の4つの変数を必要に応じて編集し、コメントアウトをはずします。
# LED_BACK_ENABLE = no        # LED backlight (Enable WS2812 RGB underlight.)
# LED_UNDERGLOW_ENABLE = no   # LED underglow (Enable WS2812 RGB underlight.)
# LED_ANIMATIONS = yes        # LED animations

D keyboards/helix/pico/matrix.c => keyboards/helix/pico/matrix.c +0 -342
@@ 1,342 0,0 @@
/*
Copyright 2012 Jun Wako <wakojun@gmail.com>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

/*
 * scan matrix
 */
#include <stdint.h>
#include <stdbool.h>
#include <avr/io.h>
#include <avr/wdt.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "print.h"
#include "debug.h"
#include "util.h"
#include "matrix.h"
#include "split_util.h"
#include "quantum.h"

#ifdef USE_MATRIX_I2C
#  include "i2c.h"
#else // USE_SERIAL
#  include "serial.h"
#endif

#ifndef DEBOUNCE
#  define DEBOUNCE	5
#endif

#define ERROR_DISCONNECT_COUNT 5

static uint8_t debouncing = DEBOUNCE;
static const int ROWS_PER_HAND = MATRIX_ROWS/2;
static uint8_t error_count = 0;

static const uint8_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
static const uint8_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;

/* matrix state(1:on, 0:off) */
static matrix_row_t matrix[MATRIX_ROWS];
static matrix_row_t matrix_debouncing[MATRIX_ROWS];

static matrix_row_t read_cols(void);
static void init_cols(void);
static void unselect_rows(void);
static void select_row(uint8_t row);
static uint8_t matrix_master_scan(void);


__attribute__ ((weak))
void matrix_init_kb(void) {
    matrix_init_user();
}

__attribute__ ((weak))
void matrix_scan_kb(void) {
    matrix_scan_user();
}

__attribute__ ((weak))
void matrix_init_user(void) {
}

__attribute__ ((weak))
void matrix_scan_user(void) {
}

inline
uint8_t matrix_rows(void)
{
    return MATRIX_ROWS;
}

inline
uint8_t matrix_cols(void)
{
    return MATRIX_COLS;
}

void matrix_init(void)
{
    split_keyboard_setup();

    // initialize row and col
    unselect_rows();
    init_cols();

    setPinOutput(B0);
    setPinOutput(D5);
    writePinHigh(B0);
    writePinHigh(D5);

    // initialize matrix state: all keys off
    for (uint8_t i=0; i < MATRIX_ROWS; i++) {
        matrix[i] = 0;
        matrix_debouncing[i] = 0;
    }

    matrix_init_quantum();
}

uint8_t _matrix_scan(void)
{
    // Right hand is stored after the left in the matirx so, we need to offset it
    int offset = isLeftHand ? 0 : (ROWS_PER_HAND);

    for (uint8_t i = 0; i < ROWS_PER_HAND; i++) {
        select_row(i);
        _delay_us(30);  // without this wait read unstable value.
        matrix_row_t cols = read_cols();
        if (matrix_debouncing[i+offset] != cols) {
            matrix_debouncing[i+offset] = cols;
            debouncing = DEBOUNCE;
        }
        unselect_rows();
    }

    if (debouncing) {
        if (--debouncing) {
            _delay_ms(1);
        } else {
            for (uint8_t i = 0; i < ROWS_PER_HAND; i++) {
                matrix[i+offset] = matrix_debouncing[i+offset];
            }
        }
    }

    return 1;
}

#ifdef USE_MATRIX_I2C

// Get rows from other half over i2c
int i2c_transaction(void) {
    int slaveOffset = (isLeftHand) ? (ROWS_PER_HAND) : 0;

    int err = i2c_master_start(SLAVE_I2C_ADDRESS + I2C_WRITE);
    if (err) goto i2c_error;

    // start of matrix stored at 0x00
    err = i2c_master_write(0x00);
    if (err) goto i2c_error;

    // Start read
    err = i2c_master_start(SLAVE_I2C_ADDRESS + I2C_READ);
    if (err) goto i2c_error;

    if (!err) {
        int i;
        for (i = 0; i < ROWS_PER_HAND-1; ++i) {
            matrix[slaveOffset+i] = i2c_master_read(I2C_ACK);
        }
        matrix[slaveOffset+i] = i2c_master_read(I2C_NACK);
        i2c_master_stop();
    } else {
i2c_error: // the cable is disconnceted, or something else went wrong
        i2c_reset_state();
        return err;
    }

    return 0;
}

#else // USE_SERIAL

int serial_transaction(void) {
    int slaveOffset = (isLeftHand) ? (ROWS_PER_HAND) : 0;
    int ret=serial_update_buffers();
    if (ret ) {
        if(ret==2) writePinLow(B0);
        return 1;
    }
    writePinHigh(B0);
    for (int i = 0; i < ROWS_PER_HAND; ++i) {
        matrix[slaveOffset+i] = serial_slave_buffer[i];
    }
    return 0;
}
#endif

uint8_t matrix_scan(void)
{
    if (is_helix_master()) {
        matrix_master_scan();
    }else{
        matrix_slave_scan();

          int offset = (isLeftHand) ? ROWS_PER_HAND : 0;

          for (int i = 0; i < ROWS_PER_HAND; ++i) {
              matrix[offset+i] = serial_master_buffer[i];
          }

        matrix_scan_quantum();
    }
    return 1;
}


uint8_t matrix_master_scan(void) {

    int ret = _matrix_scan();

#ifndef KEYBOARD_helix_rev1
    int offset = (isLeftHand) ? 0 : ROWS_PER_HAND;

#ifdef USE_MATRIX_I2C
//    for (int i = 0; i < ROWS_PER_HAND; ++i) {
        /* i2c_slave_buffer[i] = matrix[offset+i]; */
//        i2c_slave_buffer[i] = matrix[offset+i];
//    }
#else // USE_SERIAL
    for (int i = 0; i < ROWS_PER_HAND; ++i) {
        serial_master_buffer[i] = matrix[offset+i];
    }
#endif
#endif

#ifdef USE_MATRIX_I2C
    if( i2c_transaction() ) {
#else // USE_SERIAL
    if( serial_transaction() ) {
#endif
        // turn on the indicator led when halves are disconnected
        writePinLow(D5);

        error_count++;

        if (error_count > ERROR_DISCONNECT_COUNT) {
            // reset other half if disconnected
            int slaveOffset = (isLeftHand) ? (ROWS_PER_HAND) : 0;
            for (int i = 0; i < ROWS_PER_HAND; ++i) {
                matrix[slaveOffset+i] = 0;
            }
        }
    } else {
        // turn off the indicator led on no error
        writePinHigh(D5);
        error_count = 0;
    }
    matrix_scan_quantum();
    return ret;
}

void matrix_slave_scan(void) {
    _matrix_scan();

    int offset = (isLeftHand) ? 0 : ROWS_PER_HAND;

#ifdef USE_MATRIX_I2C
    for (int i = 0; i < ROWS_PER_HAND; ++i) {
        /* i2c_slave_buffer[i] = matrix[offset+i]; */
        i2c_slave_buffer[i] = matrix[offset+i];
    }
#else // USE_SERIAL
    for (int i = 0; i < ROWS_PER_HAND; ++i) {
        serial_slave_buffer[i] = matrix[offset+i];
    }
#endif
}

bool matrix_is_modified(void)
{
    if (debouncing) return false;
    return true;
}

inline
bool matrix_is_on(uint8_t row, uint8_t col)
{
    return (matrix[row] & ((matrix_row_t)1<<col));
}

inline
matrix_row_t matrix_get_row(uint8_t row)
{
    return matrix[row];
}

void matrix_print(void)
{
    print("\nr/c 0123456789ABCDEF\n");
    for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
        print_hex8(row); print(": ");
        print_bin_reverse16(matrix_get_row(row));
        print("\n");
    }
}

uint8_t matrix_key_count(void)
{
    uint8_t count = 0;
    for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
        count += bitpop16(matrix[i]);
    }
    return count;
}

static void  init_cols(void)
{
    for(int x = 0; x < MATRIX_COLS; x++) {
        _SFR_IO8((col_pins[x] >> 4) + 1) &=  ~_BV(col_pins[x] & 0xF);
        _SFR_IO8((col_pins[x] >> 4) + 2) |= _BV(col_pins[x] & 0xF);
    }
}

static matrix_row_t read_cols(void)
{
    matrix_row_t result = 0;
    for(int x = 0; x < MATRIX_COLS; x++) {
        result |= (_SFR_IO8(col_pins[x] >> 4) & _BV(col_pins[x] & 0xF)) ? 0 : (1 << x);
    }
    return result;
}

static void unselect_rows(void)
{
    for(int x = 0; x < ROWS_PER_HAND; x++) {
        _SFR_IO8((row_pins[x] >> 4) + 1) &=  ~_BV(row_pins[x] & 0xF);
        _SFR_IO8((row_pins[x] >> 4) + 2) |= _BV(row_pins[x] & 0xF);
    }
}

static void select_row(uint8_t row)
{
    _SFR_IO8((row_pins[row] >> 4) + 1) |=  _BV(row_pins[row] & 0xF);
    _SFR_IO8((row_pins[row] >> 4) + 2) &= ~_BV(row_pins[row] & 0xF);
}

A keyboards/helix/pico/override_helix_options.mk-maintenance => keyboards/helix/pico/override_helix_options.mk-maintenance +42 -0
@@ 0,0 1,42 @@
#
# This file is not normally used. It is used for maintenance testing purposes.
# To use it, do the following:
#
#  $ cp override_helix_options.mk-maintenance override_helix_options.mk
#
$(info -------------------------)
$(info override_helix_options.mk)
$(info -------------------------)

define HELIX_OVERRIDE_PARSE
    ifeq ($(strip $1),back)
        LED_BACK_ENABLE = yes
        LED_UNDERGLOW_ENABLE = no
    endif
    ifeq ($(strip $1),under)
        LED_BACK_ENABLE = no
        LED_UNDERGLOW_ENABLE = yes
    endif
    ifneq ($(filter noled led-off led_off,$(strip $1)),)
        LED_BACK_ENABLE = no
        LED_UNDERGLOW_ENABLE = no
    endif
    ifneq ($(filter noaudio audio-off audio_off,$(strip $1)),)
        AUDIO_ENABLE = no
    endif
    ifneq ($(filter audio audio-on audio_on,$(strip $1)),)
        AUDIO_ENABLE = yes
    endif
    ifneq ($(filter sc split-common split_common,$(strip $1)),)
        SPLIT_KEYBOARD = yes
    endif
    ifneq ($(filter nosc no-sc no-split-common no-split_common,$(strip $1)),)
        SPLIT_KEYBOARD = no
    endif
    ifeq ($(strip $1),scan)
        DEBUG_MATRIX_SCAN_RATE_ENABLE = yes
    endif
    ifeq ($(strip $1),scan-api)
        DEBUG_MATRIX_SCAN_RATE_ENABLE = api
    endif
endef # end of HELIX_OVERRIDE_PARSE

M keyboards/helix/pico/pico.c => keyboards/helix/pico/pico.c +15 -14
@@ 1,3 1,18 @@
/* Copyright 2018 MakotoKurauchi
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
#include "helix.h"

// Each keymap.c should use is_keyboard_master() instead of 'is_master'.


@@ 5,14 20,6 @@
//  for the old keymap.c.
uint8_t is_master = false;

#ifdef SSD1306OLED
#include "ssd1306.h"

bool process_record_kb(uint16_t keycode, keyrecord_t *record) {
	return process_record_gfx(keycode,record) && process_record_user(keycode, record);
}
#endif

void matrix_init_kb(void) {
    // Each keymap.c should use is_keyboard_master() instead of is_master.
    // But keep is_master for a while for backwards compatibility


@@ 28,9 35,3 @@ void keyboard_post_init_kb(void) {
#endif
    keyboard_post_init_user();
}

#if defined(SPLIT_KEYBOARD) && defined(SSD1306OLED)
void matrix_slave_scan_user(void) {
    matrix_scan_user();
}
#endif

M keyboards/helix/pico/pico.h => keyboards/helix/pico/pico.h +15 -5
@@ 1,12 1,22 @@
/* Copyright 2018 MakotoKurauchi
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
#pragma once

#include "helix.h"

#ifndef SPLIT_KEYBOARD
  extern bool is_helix_master(void);
  #define is_keyboard_master() is_helix_master()
#endif

// Each keymap.c should use is_keyboard_master() instead of 'is_master', 'has_usb()'.
// But keep 'is_master' for a while for backwards compatibility
//  for the old keymap.c.

M keyboards/helix/pico/post_rules.mk => keyboards/helix/pico/post_rules.mk +34 -104
@@ 4,90 4,30 @@
#   Post-processing rules convert keyboard-specific shortcuts (that represent
#   combinations of standard options) into QMK standard options.
#
-include $(strip $(HELIX_TOP_DIR)/pico/override_helix_options.mk) ## File dedicated to maintenance

define HELIX_CUSTOMISE_MSG
  $(info Helix Spacific Build Options)
  $(info -  OLED_ENABLE          = $(OLED_ENABLE))
  $(info -  LED_BACK_ENABLE      = $(LED_BACK_ENABLE))
  $(info -  LED_UNDERGLOW_ENABLE = $(LED_UNDERGLOW_ENABLE))
  $(info -  LED_ANIMATIONS       = $(LED_ANIMATIONS))
  $(info -  IOS_DEVICE_ENABLE    = $(IOS_DEVICE_ENABLE))
  $(info )
endef
# Parse 'HELIX=xx,yy,zz' option
ifneq ($(strip $(HELIX)),)
    # make HELIX=ios helix/pico:AKEYMAP
    # make HELIX=no-ani helix/pico:AKEYMAP
    # make HELIX=ios,no-ani helix/pico:AKEYMAP
    define HELIX_OPTION_PARSE
        # parce 'no-ani' 'ios'
        $(if $(SHOW_PARCE),$(info parse .$1.))  #debug
        $(if $(HELIX_OVERRIDE_PARSE),$(call HELIX_OVERRIDE_PARSE,$1))

define HELIX_HELP_MSG
  $(info Helix keyboard convenient command line option)
  $(info -    make HELIX=<options> helix/pico:<keymap>)
  $(info -    option= oled | back | under | na | no-ani)
  $(info -             ios | sc | split-common | scan | verbose)
  $(info -    ex.)
  $(info -      make HELIX=oled     helix/pico:<keymap>)
  $(info -      make HELIX=back     helix/pico:<keymap>)
  $(info -      make HELIX=under    helix/pico:<keymap>)
  $(info -      make HELIX=back,na  helix/pico:<keymap>)
  $(info -      make HELIX=back,ios helix/pico:<keymap>)
  $(info )
endef
        ifeq ($(strip $1),ios)
            IOS_DEVICE_ENABLE = yes
        endif
        ifneq ($(filter na no_ani no-ani,$(strip $1)),)
            LED_ANIMATIONS = no
        endif
    endef # end of HELIX_OPTION_PARSE

  ifneq ($(strip $(HELIX)),)
    COMMA=,
    helix_option := $(subst $(COMMA), , $(HELIX))
    ifneq ($(filter help,$(helix_option)),)
      $(eval $(call HELIX_HELP_MSG))
      $(error )
    endif
    ifneq ($(filter oled,$(helix_option)),)
      OLED_ENABLE = yes
    endif
    ifneq ($(filter back,$(helix_option)),)
      LED_BACK_ENABLE = yes
    else ifneq ($(filter under,$(helix_option)),)
      LED_UNDERGLOW_ENABLE = yes
    endif
    ifneq ($(filter na,$(helix_option)),)
      LED_ANIMATIONS = no
    endif
    ifneq ($(filter no_ani,$(helix_option)),)
      LED_ANIMATIONS = no
    endif
    ifneq ($(filter no-ani,$(helix_option)),)
      LED_ANIMATIONS = no
    endif
    ifneq ($(filter ios,$(helix_option)),)
      IOS_DEVICE_ENABLE = yes
    endif
    ifneq ($(filter sc,$(helix_option)),)
      SPLIT_KEYBOARD = yes
    endif
    ifneq ($(filter split-common,$(helix_option)),)
      SPLIT_KEYBOARD = yes
    endif
    ifneq ($(filter scan,$(helix_option)),)
      # use DEBUG_MATRIX_SCAN_RATE
      # see docs/newbs_testing_debugging.md
      OPT_DEFS +=  -DDEBUG_MATRIX_SCAN_RATE
      CONSOLE_ENABLE = yes
      SHOW_VERBOSE_INFO = yes
    endif
    ifneq ($(filter verbose,$(helix_option)),)
      SHOW_VERBOSE_INFO = yes
    endif
    $(eval $(foreach A_OPTION_NAME,$(subst $(COMMA), ,$(HELIX)),  \
        $(call HELIX_OPTION_PARSE,$(A_OPTION_NAME))))
    SHOW_HELIX_OPTIONS = yes
  endif

ifneq ($(strip $(SPLIT_KEYBOARD)), yes)
  SRC += local_drivers/serial.c
  KEYBOARD_PATHS += $(HELIX_TOP_DIR)/local_drivers

  # A workaround until #7089 is merged.
  #   serial.c must not be compiled with the -lto option.
  #   The current LIB_SRC has a side effect with the -fno-lto option, so use it.
  LIB_SRC += local_drivers/serial.c

  CUSTOM_MATRIX = yes

  SRC += pico/matrix.c
  SRC += pico/split_util.c
endif

########


@@ 98,7 38,6 @@ ifeq ($(strip $(LED_BACK_ENABLE)), yes)
  RGBLIGHT_ENABLE = yes
  OPT_DEFS += -DRGBLED_BACK
  ifeq ($(strip $(LED_UNDERGLOW_ENABLE)), yes)
    $(eval $(call HELIX_CUSTOMISE_MSG))
    $(error LED_BACK_ENABLE and LED_UNDERGLOW_ENABLE both 'yes')
  endif
else ifeq ($(strip $(LED_UNDERGLOW_ENABLE)), yes)


@@ 113,35 52,26 @@ ifeq ($(strip $(LED_ANIMATIONS)), yes)
    OPT_DEFS += -DLED_ANIMATIONS
endif

ifeq ($(strip $(OLED_ENABLE)), yes)
    SRC += local_drivers/i2c.c
    SRC += local_drivers/ssd1306.c
    KEYBOARD_PATHS += $(HELIX_TOP_DIR)/local_drivers
    OPT_DEFS += -DOLED_ENABLE
    ifeq ($(strip $(LOCAL_GLCDFONT)), yes)
        OPT_DEFS += -DLOCAL_GLCDFONT
    endif
endif

ifeq ($(strip $(AUDIO_ENABLE)),yes)
  ifeq ($(strip $(RGBLIGHT_ENABLE)),yes)
    LTO_ENABLE = yes
  endif
  ifeq ($(strip $(OLED_ENABLE)),yes)
    LTO_ENABLE = yes
  endif
endif

ifneq ($(strip $(SHOW_HELIX_OPTIONS)),)
  $(eval $(call HELIX_CUSTOMISE_MSG))
  ifneq ($(strip $(SHOW_VERBOSE_INFO)),)
     $(info -- RGBLIGHT_ENABLE    = $(RGBLIGHT_ENABLE))
     $(info -- CONSOLE_ENABLE     = $(CONSOLE_ENABLE))
     $(info -- OPT_DEFS           = $(OPT_DEFS))
     $(info -- SPLIT_KEYBOARD     = $(SPLIT_KEYBOARD))
     $(info -- LTO_ENABLE         = $(LTO_ENABLE))
     $(info )
  endif
  $(info Helix Spacific Build Options)
  $(info -  LED_BACK_ENABLE      = $(LED_BACK_ENABLE))
  $(info -  LED_UNDERGLOW_ENABLE = $(LED_UNDERGLOW_ENABLE))
  $(info -  LED_ANIMATIONS       = $(LED_ANIMATIONS))
  $(info -  IOS_DEVICE_ENABLE    = $(IOS_DEVICE_ENABLE))
  $(info )
  $(info QMK Build Options)
  $(info -- SPLIT_KEYBOARD     = $(SPLIT_KEYBOARD))
  $(info -- AUDIO_ENABLE       = $(AUDIO_ENABLE))
  $(info -- RGBLIGHT_ENABLE    = $(RGBLIGHT_ENABLE))
  $(info -- CONSOLE_ENABLE     = $(CONSOLE_ENABLE))
  $(info -- OPT_DEFS           = $(OPT_DEFS))
  $(info -- LTO_ENABLE         = $(LTO_ENABLE))
  $(info -- DEBUG_MATRIX_SCAN_RATE_ENABLE = $(DEBUG_MATRIX_SCAN_RATE_ENABLE))
  $(info )
endif

OLED_ENABLE = no # disable OLED in TOP/common_features.mk

M keyboards/helix/pico/qmk_conf/rules.mk => keyboards/helix/pico/qmk_conf/rules.mk +0 -2
@@ 1,4 1,2 @@
EXTRAKEY_ENABLE = yes       # Audio control and System control
AUDIO_ENABLE = yes          # Audio output

include $(strip $(KEYBOARD_LOCAL_FEATURES_MK))

M keyboards/helix/pico/rules.mk => keyboards/helix/pico/rules.mk +2 -2
@@ 1,6 1,6 @@
SPLIT_KEYBOARD = yes

# Helix Spacific Build Options default values
OLED_ENABLE = no            # OLED_ENABLE
LOCAL_GLCDFONT = no         # use each keymaps "helixfont.h" insted of "common/glcdfont.c"
LED_BACK_ENABLE = no        # LED backlight (Enable WS2812 RGB underlight.)
LED_UNDERGLOW_ENABLE = no   # LED underglow (Enable WS2812 RGB underlight.)
LED_ANIMATIONS = yes        # LED animations

D keyboards/helix/pico/split_util.c => keyboards/helix/pico/split_util.c +0 -104
@@ 1,104 0,0 @@
#include <avr/io.h>
#include <avr/wdt.h>
#include <avr/power.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <avr/eeprom.h>
#include "split_util.h"
#include "matrix.h"
#include "keyboard.h"
#include "wait.h"

#ifdef USE_MATRIX_I2C
#  include "i2c.h"
#else
#  include "serial.h"
#endif

#ifdef EE_HANDS
#    include "eeconfig.h"
#endif

#ifndef SPLIT_USB_TIMEOUT
  #define SPLIT_USB_TIMEOUT 2500
#endif

volatile bool isLeftHand = true;

bool waitForUsb(void) {
    for (uint8_t i = 0; i < (SPLIT_USB_TIMEOUT / 100); i++) {
        // This will return true of a USB connection has been established
        if (UDADDR & _BV(ADDEN)) {
            return true;
        }
        wait_ms(100);
    }

    // Avoid NO_USB_STARTUP_CHECK - Disable USB as the previous checks seem to enable it somehow
    (USBCON &= ~(_BV(USBE) | _BV(OTGPADE)));

    return false;
}

bool is_keyboard_left(void) {
#if defined(SPLIT_HAND_PIN)
    // Test pin SPLIT_HAND_PIN for High/Low, if low it's right hand
    setPinInput(SPLIT_HAND_PIN);
    return readPin(SPLIT_HAND_PIN);
#elif defined(EE_HANDS)
    return eeconfig_read_handedness();
#elif defined(MASTER_RIGHT)
    return !is_helix_master();
#endif

    return is_helix_master();
}

bool is_helix_master(void) {
    static enum { UNKNOWN, MASTER, SLAVE } usbstate = UNKNOWN;

    // only check once, as this is called often
    if (usbstate == UNKNOWN) {
#if defined(SPLIT_USB_DETECT)
        usbstate = waitForUsb() ? MASTER : SLAVE;
#elif defined(__AVR__)
        USBCON |= (1 << OTGPADE);  // enables VBUS pad
        wait_us(5);

        usbstate = (USBSTA & (1 << VBUS)) ? MASTER : SLAVE;  // checks state of VBUS
#else
        usbstate = MASTER;
#endif
    }

    return (usbstate == MASTER);
 }

static void keyboard_master_setup(void) {

#ifdef USE_MATRIX_I2C
    i2c_master_init();
#else
    serial_master_init();
#endif
}

static void keyboard_slave_setup(void) {

#ifdef USE_MATRIX_I2C
    i2c_slave_init(SLAVE_I2C_ADDRESS);
#else
    serial_slave_init();
#endif
}

void split_keyboard_setup(void) {
   isLeftHand = is_keyboard_left();

   if (is_helix_master()) {
      keyboard_master_setup();
   } else {
      keyboard_slave_setup();
   }
   sei();
}

D keyboards/helix/pico/split_util.h => keyboards/helix/pico/split_util.h +0 -16
@@ 1,16 0,0 @@
#pragma once

#include <stdbool.h>
#include "eeconfig.h"

#define SLAVE_I2C_ADDRESS           0x32

extern volatile bool isLeftHand;

// slave version of matix scan, defined in matrix.c
void matrix_slave_scan(void);

void split_keyboard_setup(void);
bool is_helix_master(void);

void matrix_master_OLED_init (void);