Skip to content

Commit

Permalink
Merge pull request #47 from picoruby/init_matrix_pins
Browse files Browse the repository at this point in the history
Duplex matrix
  • Loading branch information
hasumikin authored Jan 22, 2022
2 parents e0ee514 + fcc439c commit cbb9502
Show file tree
Hide file tree
Showing 12 changed files with 337 additions and 105 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Change log

## 0.9.11 on 2022/01/21
### Duplex matrix 😎
- Now we encourage you to make a duplex matrix keyboard with Seeed XIAO RP2040
Check details of the API here: [https://github.com/picoruby/prk_firmware/wiki/Keyscan-matrix#duplex-and-round-robin-matrix](https://github.com/picoruby/prk_firmware/wiki/Keyscan-matrix#duplex-and-round-robin-matrix)

## 0.9.10 on 2022/01/06
### Keyboard#define_composite_key

Expand Down
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ add_definitions(
-DMRBC_USE_HAL_USER_RESERVED
-DMRBC_REQUIRE_32BIT_ALIGNMENT
-DMAX_REGS_SIZE=256
-DMAX_SYMBOLS_COUNT=600
-DMAX_SYMBOLS_COUNT=700
-DMAX_VM_COUNT=10
-DMRBC_CONVERT_CRLF
)
Expand All @@ -27,7 +27,7 @@ pico_sdk_init()

execute_process (COMMAND date +%Y%m%d OUTPUT_VARIABLE CMAKE_BUILDDATE OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process (COMMAND git rev-parse --short HEAD OUTPUT_VARIABLE CMAKE_REVISION OUTPUT_STRIP_TRAILING_WHITESPACE)
set (PRK_VERSION 0.9.10)
set (PRK_VERSION 0.9.11)
set (PRK_BUILDDATE ${CMAKE_BUILDDATE})
set (PRK_REVISION ${CMAKE_REVISION})
configure_file ("${CMAKE_CURRENT_SOURCE_DIR}/src/version.h.in" "${CMAKE_CURRENT_SOURCE_DIR}/src/version.h")
Expand Down
27 changes: 24 additions & 3 deletions src/gpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,21 @@

#include "hardware/gpio.h"

// GPIO_IN 0b000 (defined in the SDK)
#define GPIO_IN_PULLUP 0b010
#define GPIO_IN_PULLDOWN 0b110
// GPIO_OUT 0b001 (defined in the SDK)
#define GPIO_OUT_LO 0b011
#define GPIO_OUT_HI 0b101

void
c_gpio_get(mrb_vm *vm, mrb_value *v, int argc)
{
int gpio = GET_INT_ARG(1);
if (gpio_get(gpio)) {
SET_INT_RETURN(1);
SET_TRUE_RETURN();
} else {
SET_INT_RETURN(0);
SET_FALSE_RETURN();
}
}

Expand All @@ -22,7 +29,21 @@ c_gpio_init(mrb_vm *vm, mrb_value *v, int argc)
void
c_gpio_set_dir(mrb_vm *vm, mrb_value *v, int argc)
{
gpio_set_dir(GET_INT_ARG(1), GET_INT_ARG(2));
if (GET_INT_ARG(2)&1 == GPIO_OUT) {
gpio_set_dir(GET_INT_ARG(1), true);
if (GET_INT_ARG(2) == GPIO_OUT_LO) {
gpio_put(GET_INT_ARG(1), 0);
} else if (GET_INT_ARG(2) == GPIO_OUT_HI) {
gpio_put(GET_INT_ARG(1), 1);
}
} else {
gpio_set_dir(GET_INT_ARG(1), false);
if (GET_INT_ARG(2) == GPIO_IN_PULLUP) {
gpio_pull_up(GET_INT_ARG(1));
} else if (GET_INT_ARG(2) == GPIO_IN_PULLDOWN) {
gpio_pull_down(GET_INT_ARG(1));
}
}
}

void
Expand Down
1 change: 1 addition & 0 deletions src/ruby/Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ GEM
zeitwerk (2.5.3)

PLATFORMS
ruby
x86_64-linux

DEPENDENCIES
Expand Down
2 changes: 1 addition & 1 deletion src/ruby/Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@ namespace :steep do
end

task :test do
exec %q(CFLAGS=-DMAX_SYMBOLS_COUNT=600 bundle exec mrubyc-test)
exec %q(CFLAGS=-DMAX_SYMBOLS_COUNT=1000 bundle exec mrubyc-test)
end
213 changes: 135 additions & 78 deletions src/ruby/app/models/keyboard.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
class Keyboard
GPIO_OUT = 1
GPIO_IN = 0

HI = 1
LO = 0
GPIO_IN = 0b000
GPIO_IN_PULLUP = 0b010
GPIO_IN_PULLDOWN = 0b110
GPIO_OUT = 0b001
GPIO_OUT_LO = 0b011
GPIO_OUT_HI = 0b101

MOD_KEYCODE = {
KC_LCTL: 0b00000001,
Expand Down Expand Up @@ -435,7 +436,8 @@ class Keyboard
RIGHT_SIDE_FLIPPED_SPLIT = :right_side_flipped_split

def initialize
puts "Initializing Keyboard ..."
puts "Initializing Keyboard."
sleep_ms 500
# mruby/c VM doesn't work with a CONSTANT to make another CONSTANT
# steep doesn't allow dynamic assignment of CONSTANT
@SHIFT_LETTER_THRESHOLD_A = LETTER.index('A').to_i
Expand All @@ -460,6 +462,7 @@ def initialize
@macro_keycodes = Array.new
@buffer = Buffer.new("picoirb")
@scan_mode = :matrix
@skip_positions = Array.new
end

attr_accessor :split, :uart_pin
Expand Down Expand Up @@ -521,40 +524,84 @@ def set_scan_mode(mode)
end
end

def init_pins(rows, cols)
puts "Initializing GPIO ..."
if @split
print "Configured as a split-type"
@anchor = tud_mounted?
if @anchor
uart_anchor_init(@uart_pin)
puts " Anchor"
else
uart_partner_init(@uart_pin)
puts " Partner"
end
def init_uart
return unless @split
print "Configured as a split-type"
@anchor = tud_mounted?
if @anchor
puts " Anchor"
sleep_ms 500
uart_anchor_init(@uart_pin)
else
puts " Partner"
uart_partner_init(@uart_pin)
end
sleep_ms 500
@rows = rows
@cols = cols
@rows.each do |pin|
gpio_init(pin)
gpio_set_dir(pin, GPIO_OUT);
gpio_put(pin, HI);
end

def init_matrix_pins(matrix)
puts "Initializing GPIO."
sleep_ms 500
init_uart
@cols_size = 0
@matrix = Hash.new
matrix.each do |cols|
@cols_size = [cols.size, @cols_size].max.to_i
cols.each do |cell|
if cell.is_a?(Array)
@matrix[cell[0]] = Hash.new unless @matrix[cell[0]]
end
end
end
@cols.each do |pin|
gpio_init(pin)
gpio_set_dir(pin, GPIO_IN);
gpio_pull_up(pin);
matrix.each_with_index do |rows, row_index|
rows.each_with_index do |cell, col_index|
if cell.is_a?(Array)
@matrix[cell[0]][cell[1]] = [row_index, col_index]
gpio_init(cell[0])
gpio_set_dir(cell[0], GPIO_IN_PULLUP)
gpio_init(cell[1])
gpio_set_dir(cell[1], GPIO_IN_PULLUP)
else # should be nil
@skip_positions << [row_index, col_index]
end
end
end
@offset_a = (@cols_size / 2.0).ceil_to_i
@offset_b = @cols_size * 2 - @offset_a - 1
end

def init_pins(rows, cols)
matrix = Array.new
rows.each do |row|
line = Array.new
cols.each do |col|
line << [row, col]
end
matrix << line
end
# for split type
@offset_a = (@cols.size / 2.0).ceil_to_i
@offset_b = @cols.size * 2 - @offset_a - 1
init_matrix_pins matrix
end

def init_direct_pins(pins)
set_scan_mode :direct
init_pins([], pins)
pins.each do |pin|
gpio_init(pin)
gpio_set_dir(pin, GPIO_IN_PULLUP)
end
@direct_pins = pins
end

def skip_position?(row, col)
col2 = if col < @cols_size
col
else
if @split_style == RIGHT_SIDE_FLIPPED_SPLIT
col - @cols_size
else # STANDARD_SPLIT
(col - @cols_size + 1) * -1 + @cols_size
end
end
@skip_positions.include?([row, col2])
end

# Input
Expand All @@ -563,12 +610,25 @@ def init_direct_pins(pins)
# Result
# layer: { default: [ [ -0x04, -0x05, 0b00000001, :MACRO_1 ],... ] }
def add_layer(name, map)
new_map = Array.new(@rows.size)
new_map = Array.new
new_map[0] = Array.new
row_index = 0
col_index = 0
@entire_cols_size = @split ? @cols.size * 2 : @cols.size
map.each do |key|
new_map[row_index] = Array.new(@cols.size) if col_index == 0
if entire_cols_size <= col_index
row_index += 1
col_index = 0
new_map[row_index] = Array.new
end
while skip_position?(row_index, col_index)
new_map[row_index][calculate_col_position(col_index)] = 0
col_index += 1
if entire_cols_size <= col_index
row_index += 1
col_index = 0
new_map[row_index] = Array.new
end
end
col_position = calculate_col_position(col_index)
case key.class
when Symbol
Expand All @@ -586,29 +646,32 @@ def add_layer(name, map)
switch: [row_index, col_position]
}
end
if col_index == @entire_cols_size - 1
col_index = 0
row_index += 1
else
col_index += 1
end
col_index += 1
end
@keymaps[name] = new_map
@layer_names << name
end

def entire_cols_size
@entire_cols_size ||= @split ? @cols_size * 2 : @cols_size
end

def calculate_col_position(col_index)
return col_index unless @split

case @split_style
# `when STANDARD_SPLIT` can be deleted after fixing a picoruby's bug
# https://github.com/picoruby/picoruby/issues/74
when STANDARD_SPLIT
col_index
when RIGHT_SIDE_FLIPPED_SPLIT
if col_index < @cols.size
if col_index < @cols_size
col_index
else
@entire_cols_size - (col_index - @cols.size) - 1
entire_cols_size - (col_index - @cols_size) - 1
end
else
# Should not happen but be guarded to pass steep check.
col_index
end
end

Expand Down Expand Up @@ -823,7 +886,7 @@ def start!
# To avoid unintentional report on startup
# which happens only on Sparkfun Pro Micro RP2040
if @split && @anchor
sleep_ms 100
sleep_ms 500
while true
data = uart_anchor(0)
break if data == 0xFFFFFF
Expand All @@ -839,7 +902,7 @@ def start!
@switches.clear
@modifier = 0

@switches = @scan_mode == :matrix ? scan_matrix! : scan_direct!
@scan_mode == :matrix ? scan_matrix! : scan_direct!

# TODO: more features
$rgb.fifo_push(true) if $rgb && !@switches.empty?
Expand Down Expand Up @@ -1019,47 +1082,41 @@ def start!
end

def scan_matrix!
switches = []
# detect physical switches that are pushed
@rows.each_with_index do |row_pin, row|
gpio_put(row_pin, LO)
@cols.each_with_index do |col_pin, col|
if gpio_get(col_pin) == LO
col_data = if @anchor_left
if @anchor
# left
col
else
# right
(col - @offset_a) * -1 + @offset_b
end
else # right side is the anchor
unless @anchor
# left
col
else
# right
(col - @offset_a) * -1 + @offset_b
end
end
switches << [row, col_data]
@matrix.each do |out_pin, in_pins|
gpio_set_dir(out_pin, GPIO_OUT_LO)
in_pins.each do |in_pin, switch|
unless gpio_get(in_pin)
col = if @anchor_left
if @anchor
# left
switch[1]
else
# right
(switch[1] - @offset_a) * -1 + @offset_b
end
else # right side is the anchor
unless @anchor
# left
switch[1]
else
# right
(switch[1] - @offset_a) * -1 + @offset_b
end
end
@switches << [switch[0], col]
end
# @type break: nil
break if switches.size >= @cols.size
end
gpio_put(row_pin, HI)
gpio_set_dir(out_pin, GPIO_IN_PULLUP)
end
return switches
end

def scan_direct!
switches = []
@cols.each_with_index do |col_pin, col|
if gpio_get(col_pin) == LO
switches << [0, col]
@direct_pins.each_with_index do |col_pin, col|
if gpio_get(col_pin)
@switches << [0, col]
end
end
return switches
end

#
Expand Down
Loading

0 comments on commit cbb9502

Please sign in to comment.