Skip to content

Commit dd7404e

Browse files
Cipulotkeyboard-magpiedrashna
authored andcommitted
RF R1 8-9Xu PCB (qmk#20048)
Co-authored-by: Tom Barnes <[email protected]> Co-authored-by: Drashna Jaelre <[email protected]>
1 parent fdd9046 commit dd7404e

File tree

17 files changed

+1261
-0
lines changed

17 files changed

+1261
-0
lines changed
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/* Copyright 2023 Cipulot
2+
*
3+
* This program is free software: you can redistribute it and/or modify
4+
* it under the terms of the GNU General Public License as published by
5+
* the Free Software Foundation, either version 2 of the License, or
6+
* (at your option) any later version.
7+
*
8+
* This program is distributed in the hope that it will be useful,
9+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+
* GNU General Public License for more details.
12+
*
13+
* You should have received a copy of the GNU General Public License
14+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
15+
*/
16+
17+
#pragma once
18+
19+
#define MATRIX_ROWS 6
20+
#define MATRIX_COLS 16
21+
22+
/* Custom matrix pins and port select array */
23+
#define MATRIX_ROW_PINS \
24+
{ B15, A8, B13, B12, B14, B0 }
25+
#define MATRIX_COL_CHANNELS \
26+
{ 3, 0, 1, 2, 4, 6, 7, 5 }
27+
#define MUX_SEL_PINS \
28+
{ B4, B5, B6 }
29+
30+
/* Hardware peripherals pins */
31+
#define APLEX_EN_PIN_0 B7
32+
#define APLEX_EN_PIN_1 A6
33+
#define DISCHARGE_PIN A4
34+
#define ANALOG_PORT A3
35+
36+
/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
37+
#define LOCKING_SUPPORT_ENABLE
38+
39+
/* Locking resynchronize hack */
40+
#define LOCKING_RESYNC_ENABLE
41+
42+
#define DEFAULT_ACTUATION_LEVEL 700
43+
#define DEFAULT_RELEASE_LEVEL 650
44+
45+
#define DISCHARGE_TIME 10
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
/* Copyright 2023 Cipulot
2+
*
3+
* This program is free software: you can redistribute it and/or modify
4+
* it under the terms of the GNU General Public License as published by
5+
* the Free Software Foundation, either version 2 of the License, or
6+
* (at your option) any later version.
7+
*
8+
* This program is distributed in the hope that it will be useful,
9+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+
* GNU General Public License for more details.
12+
*
13+
* You should have received a copy of the GNU General Public License
14+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
15+
*/
16+
17+
#include "ec_switch_matrix.h"
18+
#include "analog.h"
19+
#include "atomic_util.h"
20+
#include "print.h"
21+
#include "wait.h"
22+
23+
/* Pin and port array */
24+
const uint32_t row_pins[] = MATRIX_ROW_PINS;
25+
const uint8_t col_channels[] = MATRIX_COL_CHANNELS;
26+
const uint32_t mux_sel_pins[] = MUX_SEL_PINS;
27+
28+
static ecsm_config_t config;
29+
static uint16_t ecsm_sw_value[MATRIX_ROWS][MATRIX_COLS];
30+
31+
static adc_mux adcMux;
32+
33+
static inline void discharge_capacitor(void) {
34+
writePinLow(DISCHARGE_PIN);
35+
}
36+
static inline void charge_capacitor(uint8_t row) {
37+
writePinHigh(DISCHARGE_PIN);
38+
writePinHigh(row_pins[row]);
39+
}
40+
41+
static inline void init_mux_sel(void) {
42+
for (int idx = 0; idx < 3; idx++) {
43+
setPinOutput(mux_sel_pins[idx]);
44+
}
45+
}
46+
47+
static inline void select_mux(uint8_t col) {
48+
uint8_t ch = col_channels[col];
49+
writePin(mux_sel_pins[0], ch & 1);
50+
writePin(mux_sel_pins[1], ch & 2);
51+
writePin(mux_sel_pins[2], ch & 4);
52+
}
53+
54+
static inline void init_row(void) {
55+
for (int idx = 0; idx < MATRIX_ROWS; idx++) {
56+
setPinOutput(row_pins[idx]);
57+
writePinLow(row_pins[idx]);
58+
}
59+
}
60+
61+
/* Initialize the peripherals pins */
62+
int ecsm_init(ecsm_config_t const* const ecsm_config) {
63+
// Initialize config
64+
config = *ecsm_config;
65+
66+
palSetLineMode(ANALOG_PORT, PAL_MODE_INPUT_ANALOG);
67+
adcMux = pinToMux(ANALOG_PORT);
68+
69+
//Dummy call to make sure that adcStart() has been called in the appropriate state
70+
adc_read(adcMux);
71+
72+
// Initialize discharge pin as discharge mode
73+
writePinLow(DISCHARGE_PIN);
74+
setPinOutputOpenDrain(DISCHARGE_PIN);
75+
76+
// Initialize drive lines
77+
init_row();
78+
79+
// Initialize multiplexer select pin
80+
init_mux_sel();
81+
82+
// Enable AMUX
83+
setPinOutput(APLEX_EN_PIN_0);
84+
writePinLow(APLEX_EN_PIN_0);
85+
setPinOutput(APLEX_EN_PIN_1);
86+
writePinLow(APLEX_EN_PIN_1);
87+
88+
return 0;
89+
}
90+
91+
int ecsm_update(ecsm_config_t const* const ecsm_config) {
92+
// Save config
93+
config = *ecsm_config;
94+
return 0;
95+
}
96+
97+
// Read the capacitive sensor value
98+
uint16_t ecsm_readkey_raw(uint8_t channel, uint8_t row, uint8_t col) {
99+
uint16_t sw_value = 0;
100+
101+
// Select the multiplexer
102+
if (channel == 0) {
103+
writePinHigh(APLEX_EN_PIN_0);
104+
select_mux(col);
105+
writePinLow(APLEX_EN_PIN_0);
106+
} else {
107+
writePinHigh(APLEX_EN_PIN_1);
108+
select_mux(col);
109+
writePinLow(APLEX_EN_PIN_1);
110+
}
111+
112+
// Set strobe pins to low state
113+
writePinLow(row_pins[row]);
114+
ATOMIC_BLOCK_FORCEON {
115+
// Set the row pin to high state and have capacitor charge
116+
charge_capacitor(row);
117+
// Read the ADC value
118+
sw_value = adc_read(adcMux);
119+
}
120+
// Discharge peak hold capacitor
121+
discharge_capacitor();
122+
// Waiting for the ghost capacitor to discharge fully
123+
wait_us(DISCHARGE_TIME);
124+
125+
return sw_value;
126+
}
127+
128+
// Update press/release state of key
129+
bool ecsm_update_key(matrix_row_t* current_row, uint8_t row, uint8_t col, uint16_t sw_value) {
130+
bool current_state = (*current_row >> col) & 1;
131+
132+
// Press to release
133+
if (current_state && sw_value < config.ecsm_actuation_threshold) {
134+
*current_row &= ~(1 << col);
135+
return true;
136+
}
137+
138+
// Release to press
139+
if ((!current_state) && sw_value > config.ecsm_release_threshold) {
140+
*current_row |= (1 << col);
141+
return true;
142+
}
143+
144+
return false;
145+
}
146+
147+
// Scan key values and update matrix state
148+
bool ecsm_matrix_scan(matrix_row_t current_matrix[]) {
149+
bool updated = false;
150+
151+
// Disable AMUX of channel 1
152+
writePinHigh(APLEX_EN_PIN_1);
153+
for (int col = 0; col < sizeof(col_channels); col++) {
154+
for (int row = 0; row < MATRIX_ROWS; row++) {
155+
ecsm_sw_value[row][col] = ecsm_readkey_raw(0, row, col);
156+
updated |= ecsm_update_key(&current_matrix[row], row, col, ecsm_sw_value[row][col]);
157+
}
158+
}
159+
160+
// Disable AMUX of channel 1
161+
writePinHigh(APLEX_EN_PIN_0);
162+
for (int col = 0; col < sizeof(col_channels); col++) {
163+
for (int row = 0; row < MATRIX_ROWS; row++) {
164+
ecsm_sw_value[row][col + 8] = ecsm_readkey_raw(1, row, col);
165+
updated |= ecsm_update_key(&current_matrix[row], row, col + 8, ecsm_sw_value[row][col + 8]);
166+
}
167+
}
168+
return updated;
169+
}
170+
171+
// Debug print key values
172+
void ecsm_print_matrix(void) {
173+
for (int row = 0; row < MATRIX_ROWS; row++) {
174+
for (int col = 0; col < MATRIX_COLS; col++) {
175+
uprintf("%4d", ecsm_sw_value[row][col]);
176+
if (col < (MATRIX_COLS - 1)) {
177+
print(",");
178+
}
179+
}
180+
print("\n");
181+
}
182+
print("\n");
183+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/* Copyright 2023 Cipulot
2+
*
3+
* This program is free software: you can redistribute it and/or modify
4+
* it under the terms of the GNU General Public License as published by
5+
* the Free Software Foundation, either version 2 of the License, or
6+
* (at your option) any later version.
7+
*
8+
* This program is distributed in the hope that it will be useful,
9+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+
* GNU General Public License for more details.
12+
*
13+
* You should have received a copy of the GNU General Public License
14+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
15+
*/
16+
17+
#pragma once
18+
19+
#include <stdint.h>
20+
#include <stdbool.h>
21+
22+
#include "matrix.h"
23+
24+
typedef struct {
25+
uint16_t ecsm_actuation_threshold; // threshold for key release
26+
uint16_t ecsm_release_threshold; // threshold for key press
27+
} ecsm_config_t;
28+
29+
ecsm_config_t ecsm_config;
30+
31+
int ecsm_init(ecsm_config_t const* const ecsm_config);
32+
int ecsm_update(ecsm_config_t const* const ecsm_config);
33+
bool ecsm_matrix_scan(matrix_row_t current_matrix[]);
34+
uint16_t ecsm_readkey_raw(uint8_t channel, uint8_t row, uint8_t col);
35+
bool ecsm_update_key(matrix_row_t* current_row, uint8_t row, uint8_t col, uint16_t sw_value);
36+
void ecsm_print_matrix(void);
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/* Copyright 2023 Cipulot
2+
*
3+
* This program is free software: you can redistribute it and/or modify
4+
* it under the terms of the GNU General Public License as published by
5+
* the Free Software Foundation, either version 2 of the License, or
6+
* (at your option) any later version.
7+
*
8+
* This program is distributed in the hope that it will be useful,
9+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+
* GNU General Public License for more details.
12+
*
13+
* You should have received a copy of the GNU General Public License
14+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
15+
*/
16+
17+
#pragma once
18+
19+
#define HAL_USE_ADC TRUE
20+
21+
#include_next <halconf.h>

0 commit comments

Comments
 (0)