dip_switch.c (4841B)
1 /* 2 * Copyright 2018 Jack Humbert <jack.humb@gmail.com> 3 * Copyright 2019 Drashna Jaelre (Christopher Courtney) <drashna@live.com> 4 * 5 * This program is free software: you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation, either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 */ 18 19 #include <string.h> // for memcpy 20 21 #include "dip_switch.h" 22 23 #ifdef SPLIT_KEYBOARD 24 # include "split_common/split_util.h" 25 #endif 26 27 #if !defined(DIP_SWITCH_PINS) && !defined(DIP_SWITCH_MATRIX_GRID) 28 # error "Either DIP_SWITCH_PINS or DIP_SWITCH_MATRIX_GRID must be defined." 29 #endif 30 31 #if defined(DIP_SWITCH_PINS) && defined(DIP_SWITCH_MATRIX_GRID) 32 # error "Both DIP_SWITCH_PINS and DIP_SWITCH_MATRIX_GRID are defined." 33 #endif 34 35 #ifdef DIP_SWITCH_PINS 36 static pin_t dip_switch_pad[] = DIP_SWITCH_PINS; 37 #endif 38 39 #ifdef DIP_SWITCH_MATRIX_GRID 40 static matrix_intersection_t dip_switch_pad[] = DIP_SWITCH_MATRIX_GRID; 41 extern bool peek_matrix(uint8_t row_index, uint8_t col_index, bool read_raw); 42 static uint16_t scan_count; 43 #endif /* DIP_SWITCH_MATRIX_GRID */ 44 45 static bool dip_switch_state[NUM_DIP_SWITCHES] = {0}; 46 static bool last_dip_switch_state[NUM_DIP_SWITCHES] = {0}; 47 48 __attribute__((weak)) bool dip_switch_update_user(uint8_t index, bool active) { 49 return true; 50 } 51 52 __attribute__((weak)) bool dip_switch_update_kb(uint8_t index, bool active) { 53 return dip_switch_update_user(index, active); 54 } 55 56 __attribute__((weak)) bool dip_switch_update_mask_user(uint32_t state) { 57 return true; 58 } 59 60 __attribute__((weak)) bool dip_switch_update_mask_kb(uint32_t state) { 61 return dip_switch_update_mask_user(state); 62 } 63 64 #ifdef DIP_SWITCH_MAP_ENABLE 65 # include "keymap_introspection.h" 66 # include "action.h" 67 # include "wait.h" 68 69 # ifndef DIP_SWITCH_MAP_KEY_DELAY 70 # define DIP_SWITCH_MAP_KEY_DELAY TAP_CODE_DELAY 71 # endif 72 73 static void dip_switch_exec_mapping(uint8_t index, bool on) { 74 // The delays below cater for Windows and its wonderful requirements. 75 action_exec(on ? MAKE_DIPSWITCH_ON_EVENT(index, true) : MAKE_DIPSWITCH_OFF_EVENT(index, true)); 76 # if DIP_SWITCH_MAP_KEY_DELAY > 0 77 wait_ms(DIP_SWITCH_MAP_KEY_DELAY); 78 # endif // DIP_SWITCH_MAP_KEY_DELAY > 0 79 80 action_exec(on ? MAKE_DIPSWITCH_ON_EVENT(index, false) : MAKE_DIPSWITCH_OFF_EVENT(index, false)); 81 # if DIP_SWITCH_MAP_KEY_DELAY > 0 82 wait_ms(DIP_SWITCH_MAP_KEY_DELAY); 83 # endif // DIP_SWITCH_MAP_KEY_DELAY > 0 84 } 85 #endif // DIP_SWITCH_MAP_ENABLE 86 87 void dip_switch_init(void) { 88 #ifdef DIP_SWITCH_PINS 89 # if defined(SPLIT_KEYBOARD) && defined(DIP_SWITCH_PINS_RIGHT) 90 if (!isLeftHand) { 91 const pin_t dip_switch_pad_right[] = DIP_SWITCH_PINS_RIGHT; 92 for (uint8_t i = 0; i < NUM_DIP_SWITCHES; i++) { 93 dip_switch_pad[i] = dip_switch_pad_right[i]; 94 } 95 } 96 # endif 97 for (uint8_t i = 0; i < NUM_DIP_SWITCHES; i++) { 98 gpio_set_pin_input_high(dip_switch_pad[i]); 99 } 100 dip_switch_read(true); 101 #endif 102 #ifdef DIP_SWITCH_MATRIX_GRID 103 scan_count = 0; 104 #endif 105 } 106 107 void dip_switch_read(bool forced) { 108 bool has_dip_state_changed = false; 109 uint32_t dip_switch_mask = 0; 110 111 #ifdef DIP_SWITCH_MATRIX_GRID 112 bool read_raw = false; 113 114 if (scan_count < 500) { 115 scan_count++; 116 if (scan_count == 10) { 117 read_raw = true; 118 forced = true; /* First reading of the dip switch */ 119 } else { 120 return; 121 } 122 } 123 #endif 124 125 for (uint8_t i = 0; i < NUM_DIP_SWITCHES; i++) { 126 #ifdef DIP_SWITCH_PINS 127 dip_switch_state[i] = !gpio_read_pin(dip_switch_pad[i]); 128 #endif 129 #ifdef DIP_SWITCH_MATRIX_GRID 130 dip_switch_state[i] = peek_matrix(dip_switch_pad[i].row, dip_switch_pad[i].col, read_raw); 131 #endif 132 dip_switch_mask |= dip_switch_state[i] << i; 133 if (last_dip_switch_state[i] != dip_switch_state[i] || forced) { 134 has_dip_state_changed = true; 135 #ifndef DIP_SWITCH_MAP_ENABLE 136 dip_switch_update_kb(i, dip_switch_state[i]); 137 #else 138 dip_switch_exec_mapping(i, dip_switch_state[i]); 139 #endif 140 } 141 } 142 if (has_dip_state_changed) { 143 #ifndef DIP_SWITCH_MAP_ENABLE 144 dip_switch_update_mask_kb(dip_switch_mask); 145 #endif 146 memcpy(last_dip_switch_state, dip_switch_state, sizeof(dip_switch_state)); 147 } 148 } 149 150 void dip_switch_task(void) { 151 dip_switch_read(false); 152 }