Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ target_sources(keyboard PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/keyboard_split.c
${CMAKE_CURRENT_SOURCE_DIR}/keyboard_split_rx_dma.c
${CMAKE_CURRENT_SOURCE_DIR}/keyboard_split_tx_dma.c
${CMAKE_CURRENT_SOURCE_DIR}/keyboard_touchkey.c
${CMAKE_CURRENT_SOURCE_DIR}/matrix/col_to_row.c
${CMAKE_CURRENT_SOURCE_DIR}/matrix/row_to_col.c
${CMAKE_CURRENT_SOURCE_DIR}/matrix/touchkey_mutual.c
)

target_include_directories(keyboard INTERFACE ${CMAKE_CURRENT_BINARY_DIR})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,6 @@

GPIO_TypeDef *const GPIO_PORTS[] = {GPIOA, GPIOB, GPIOC};

typedef struct {
GPIO_TypeDef *port;
uint32_t pin;
} ch32x_gpio_t;

ch32x_gpio_t to_ch32x_gpio(keyboard_gpio_t gpio_source) {
ch32x_gpio_t result = {
.port = GPIO_PORTS[gpio_source.port],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,22 @@
#include <stdbool.h>
#include <stdint.h>

#include "ch32x035.h"

typedef struct {
// Port Source
uint8_t port;
// Pin Source
uint8_t pin;
} keyboard_gpio_t;

typedef struct {
GPIO_TypeDef *port;
uint32_t pin;
} ch32x_gpio_t;

ch32x_gpio_t to_ch32x_gpio(keyboard_gpio_t gpio_source);

void keyboard_gpio_configure_ipu(keyboard_gpio_t gpio);
void keyboard_gpio_configure_output(keyboard_gpio_t gpio);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#include "keyboard_touchkey.h"

#include "ch32x035_adc.h"
#include "ch32x035_gpio.h"
#include "ch32x035_rcc.h"

#include "keyboard_gpio.h"

void keyboard_touchkey_configure_drive(keyboard_gpio_t gpio_source) {
keyboard_gpio_configure_output(gpio_source);
keyboard_gpio_reset(gpio_source);
}

void keyboard_touchkey_configure_sense(keyboard_gpio_t gpio_source) {
ch32x_gpio_t gpio = to_ch32x_gpio(gpio_source);
GPIO_InitTypeDef gpio_init_value = {
.GPIO_Pin = gpio.pin,
.GPIO_Mode = GPIO_Mode_AIN,
};
GPIO_Init(gpio.port, &gpio_init_value);
}

void keyboard_touchkey_init(void) {
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);

ADC_CLKConfig(ADC1, ADC_CLK_Div6);

ADC_InitTypeDef adc_init_value = {
.ADC_Mode = ADC_Mode_Independent,
.ADC_ScanConvMode = DISABLE,
.ADC_ContinuousConvMode = DISABLE,
.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None,
.ADC_DataAlign = ADC_DataAlign_Right,
.ADC_NbrOfChannel = 1,
};
ADC_Init(ADC1, &adc_init_value);

ADC_Cmd(ADC1, ENABLE);

TKey1->CTLR1 |= ADC_TKENABLE;
}

uint16_t keyboard_touchkey_read(uint8_t ch) {
// TODO: allow configuration
ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_11Cycles);
TKey1->IDATAR1 = 0xFF; // Charging Time
TKey1->RDATAR = 0xFF; // Discharging Time; start read
while (!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC))
;

return (uint16_t)TKey1->RDATAR;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#pragma once

#include "keyboard_gpio.h"

void keyboard_touchkey_configure_drive(keyboard_gpio_t gpio);
void keyboard_touchkey_configure_sense(keyboard_gpio_t gpio);

void keyboard_touchkey_init(void);
uint16_t keyboard_touchkey_read(uint8_t ch);
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
#ifdef KEYBOARD_MATRIX_IMPL_TOUCHKEY_MUTUAL
#include "debug.h"

#include "ch32x035_rcc.h"

#include "keyboard_gpio.h"
#include "keyboard_matrix.h"
#include "keyboard_touchkey.h"

uint16_t tkey_baselines[KEYBOARD_MATRIX_KEY_COUNT] = {0};
uint16_t tkey_readings[KEYBOARD_MATRIX_KEY_COUNT] = {0};

// KLUDGE: hardcoded. Ideally, comes from codegen.
// for board: ch32x-tc-2x4 rev2025.1
uint8_t adc_channel_map[4] = {
// per col
4, // col 1
6, // col 2
8, // col 3
9, // col 4
};

void init_column(keyboard_gpio_t col) {
keyboard_touchkey_configure_sense(col);
}

void init_row(keyboard_gpio_t row) { keyboard_touchkey_configure_drive(row); }

void keyboard_matrix_scan_raw(bool scan_buf[KEYBOARD_MATRIX_KEY_COUNT]);

void keyboard_matrix_init(void) {
// NOTE: this implementation is for 'touchkeys' using mutual capacitance,
// driving on rows, sensing on columns.

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);

// Sense Cols
for (uint8_t i = 0; i < KEYBOARD_MATRIX_COL_COUNT; i++) {
init_column(keyboard_matrix_cols[i]);
}

// Drive Rows
for (uint8_t i = 0; i < KEYBOARD_MATRIX_ROW_COUNT; i++) {
init_row(keyboard_matrix_rows[i]);
keyboard_gpio_reset(keyboard_matrix_rows[i]);
}

keyboard_touchkey_init();

// Scan once to set ADC values
bool current_raw_scan[KEYBOARD_MATRIX_KEY_COUNT] = {false};
keyboard_matrix_scan_raw(current_raw_scan);
}

void discharge_pin(keyboard_gpio_t col) {
// Ensure col is discharged
keyboard_gpio_configure_output(col);
keyboard_gpio_reset(col);
Delay_Us(5);
keyboard_touchkey_configure_sense(col);
}

void keyboard_matrix_scan_column_for_row(
keyboard_matrix_coordinate_t index,
bool scan_buf[KEYBOARD_MATRIX_KEY_COUNT]) {
uint8_t column_index = index.column;
uint8_t row_index = index.row;
keyboard_gpio_t column = keyboard_matrix_cols[column_index];

discharge_pin(column);

uint16_t adc_value = keyboard_touchkey_read(adc_channel_map[column_index]);

uint8_t keymap_index = keymap_indices[row_index][column_index];

if (keymap_index >= 0) {
tkey_readings[keymap_index] = adc_value;

// Initialize baseline if not set
if (tkey_baselines[keymap_index] == 0) {
tkey_baselines[keymap_index] = adc_value;
}

uint16_t threshold = 150; // TODO: make configurable
if (adc_value < tkey_baselines[keymap_index] - threshold) {
scan_buf[keymap_index] = true;
} else {
scan_buf[keymap_index] = false;

// Update baseline
uint8_t n = 64;
tkey_baselines[keymap_index] =
(tkey_baselines[keymap_index] * (n - 1) / n) + (adc_value * 1 / n);
}
}
}

void keyboard_matrix_scan_row(uint8_t row_index,
bool scan_buf[KEYBOARD_MATRIX_KEY_COUNT]) {
keyboard_gpio_t row = keyboard_matrix_rows[row_index];

keyboard_gpio_set(row);
Delay_Us(5);

for (uint8_t column_index = 0; column_index < KEYBOARD_MATRIX_COL_COUNT;
column_index++) {
keyboard_matrix_coordinate_t index = {.column = column_index,
.row = row_index};
keyboard_matrix_scan_column_for_row(index, scan_buf);
}

keyboard_gpio_reset(row);
}

void keyboard_matrix_scan_raw(bool scan_buf[KEYBOARD_MATRIX_KEY_COUNT]) {
static uint16_t counter = 0;

if ((++counter) > 1000) {
printf("base: \r\n %5d %5d\r\n %5d %5d\r\n", tkey_baselines[0],
tkey_baselines[1], tkey_baselines[2], tkey_baselines[3]);
printf("read: \r\n %5d %5d\r\n %5d %5d\r\n", tkey_readings[0],
tkey_readings[1], tkey_readings[2], tkey_readings[3]);
printf("delt: \r\n %5d %5d\r\n %5d %5d\r\n",
((int32_t)(tkey_readings[0]) - (int32_t)(tkey_baselines[0])),
((int32_t)(tkey_readings[1]) - (int32_t)(tkey_baselines[1])),
((int32_t)(tkey_readings[2]) - (int32_t)(tkey_baselines[2])),
((int32_t)(tkey_readings[3]) - (int32_t)(tkey_baselines[3])));
printf("\r\n");
counter = 0;
}

for (uint8_t row_index = 0; row_index < KEYBOARD_MATRIX_ROW_COUNT;
row_index++) {
keyboard_matrix_scan_row(row_index, scan_buf);
}
}

bool keyboard_matrix_is_sw_1_1_pressed() {
return false; // TBI
}
#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
let C = import "keyboard/contracts.ncl" in

{
gpio_pins | C.GpioPins,

board | C.Board = {
matrix =
let p = gpio_pins in
{
# Sense columns
cols = [p.A4, p.A6, p.A7, p.B1],
# Drive rows
rows = [
p.A0,
p.A5,
],
key_count = 8,

implementation = "touchkey_mutual",
},

keymap_index_for_key = fun { column_index | Number, row_index | Number, .. } =>
let [
k00, k01, k02, k03,
k04, k05, k06, k07,
] = std.array.generate (fun i => 'Key i) matrix.key_count in
let NO = 'NoKey in
let matrix = [
[k00, k01, k02, k03],
[k04, k05, k06, k07],
]
in
matrix
|> std.array.at row_index
|> std.array.at column_index,

led = {
enabled = true,
pin = gpio_pins.A3,
},

# TX4 available if Col3 not used.
debug.tx = 1,
},
}