Skip to content

Commit

Permalink
QtClient support for split keyboard
Browse files Browse the repository at this point in the history
  • Loading branch information
thefloweringash authored and chrisandreae committed Dec 1, 2020
1 parent 5899983 commit 2fae988
Show file tree
Hide file tree
Showing 6 changed files with 301 additions and 28 deletions.
94 changes: 66 additions & 28 deletions qtclient/devicemock.cc
Original file line number Diff line number Diff line change
Expand Up @@ -53,35 +53,73 @@ static const unsigned char ergodox_default_mapping[152] = {
0xe8, 0xe9, 0xe6, 0xe4, 0x4b, 0x4e, 0x28, 0x2c
};

static const unsigned char ugboard_default_mapping[192] = {
0x2c, 0xe4, 0x28, 0xe7, 0xe5, 0xe6, 0xff, 0x23,
0x1c, 0x0b, 0x11, 0xff, 0x3e, 0x24, 0x18, 0x0d,
0x10, 0x52, 0x3f, 0x25, 0x0c, 0x0e, 0x36, 0x51,
0x40, 0x26, 0x12, 0x0f, 0x37, 0x2f, 0x41, 0x27,
0x13, 0x33, 0x38, 0x30, 0xfe, 0x2d, 0x31, 0x34,
0x4b, 0x4e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x2a, 0xe0, 0x4c, 0xe3, 0xe1, 0xe2, 0xff, 0x22,
0x17, 0x0a, 0x05, 0xff, 0x3d, 0x21, 0x15, 0x09,
0x19, 0x4f, 0x3c, 0x20, 0x08, 0x07, 0x06, 0x50,
0x3b, 0x1f, 0x1a, 0x16, 0x1b, 0x39, 0x3a, 0x1e,
0x14, 0x04, 0x1d, 0x35, 0x29, 0x2e, 0x2b, 0xfc,
0x4a, 0x4d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xe4, 0xe6, 0xe5, 0xe7, 0x2c, 0x28, 0xff, 0x23,
0x1c, 0x0b, 0x11, 0xff, 0x3f, 0x24, 0x18, 0x0d,
0x10, 0x52, 0x40, 0x25, 0x0c, 0x0e, 0x36, 0x51,
0x41, 0x26, 0x12, 0x0f, 0x37, 0x2f, 0x42, 0x27,
0x13, 0x33, 0x38, 0x30, 0x43, 0x2d, 0x31, 0x34,
0xfc, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xe4, 0xe6, 0xe5, 0xe7, 0x2c, 0x28, 0xff, 0x23,
0x1c, 0x0b, 0x11, 0xff, 0x3f, 0x24, 0x18, 0x0d,
0x10, 0x52, 0x40, 0x25, 0x0c, 0x0e, 0x36, 0x51,
0x41, 0x26, 0x12, 0x0f, 0x37, 0x2f, 0x42, 0x27,
0x13, 0x33, 0x38, 0x30, 0x43, 0x2d, 0x31, 0x34,
0xfc, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};


static void append_mock(KeyboardComm::DeviceList *target, QSharedPointer<Device> mockKeyboard) {
mockKeyboard->newSession()->resetFully();
target->push_back(mockKeyboard);
}

void DeviceMock::enumerateTo(KeyboardComm::DeviceList *target) {
QSharedPointer<Device> mockKinesis = QSharedPointer<Device>(
new DeviceMock("Mock Kinesis",
1, // layout
172, // mapping size
6, 1024, // programs
300, 1024, 4, // macros
QByteArray(reinterpret_cast<const char*>(&kinesis_default_mapping[0]),
sizeof(kinesis_default_mapping))));
{
QSharedPointer<DeviceSession> session = mockKinesis->newSession();
session->resetFully();
}

QSharedPointer<Device> mockErgodox = QSharedPointer<Device>(
new DeviceMock("Mock Ergodox",
2, // layout
152, // mapping size
6, 1024, // programs
300, 1024, 4, // macros
QByteArray(reinterpret_cast<const char*>(&ergodox_default_mapping[0]),
sizeof(ergodox_default_mapping))));
{
QSharedPointer<DeviceSession> session = mockErgodox->newSession();
session->resetFully();
}

target->push_back(mockKinesis);
target->push_back(mockErgodox);
append_mock(target,
QSharedPointer<Device>{
new DeviceMock(
"Mock Kinesis",
1, // layout
sizeof(kinesis_default_mapping), // mapping size
6, 1024, // programs
300, 1024, 4, // macros
QByteArray(reinterpret_cast<const char*>(&kinesis_default_mapping[0]),
sizeof(kinesis_default_mapping)))});

append_mock(target,
QSharedPointer<Device>{
new DeviceMock(
"Mock Ergodox",
2, // layout
sizeof(ergodox_default_mapping), // mapping size
6, 1024, // programs
300, 1024, 4, // macros
QByteArray(reinterpret_cast<const char*>(&ergodox_default_mapping[0]),
sizeof(ergodox_default_mapping)))});


append_mock(target,
QSharedPointer<Device>{
new DeviceMock(
"Mock UgBoard",
3, // layout
sizeof(ugboard_default_mapping), // mapping size
2, 256, // programs
60, 256, 4, // macros
QByteArray(reinterpret_cast<const char*>(&ugboard_default_mapping[0]),
sizeof(ugboard_default_mapping)))});
}

uint8_t DeviceSessionMock::getLayoutID() {
Expand Down
1 change: 1 addition & 0 deletions qtclient/deviceusb.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ static const struct {
} valid_ids[] = {
{0x16c0, 0x27db}, // VUSB IDs used by Kinesis modification
{0x1d50, 0x6028}, // IDs used by Ergodox
{0x16c0, 0x27dc}, // VUSB IDs used by ugboard
};

bool DeviceUSB::isValidID(const uint16_t vid, const uint16_t pid) {
Expand Down
98 changes: 98 additions & 0 deletions qtclient/layout/3.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
<keyboard layout="ugboard" layoutid="3" image="ugboard.png"><layout>
<key name="k1" w="50" h="50" x="600" y="350"/>
<key name="k2" w="50" h="50" x="600" y="300"/>
<key name="k3" w="50" h="50" x="550" y="350"/>
<key name="k4" w="50" h="50" x="550" y="300"/>
<key name="k5" w="50" h="50" x="500" y="350"/>
<key name="k6" w="50" h="50" x="500" y="300"/>
<key name="k7" w="50" h="50" x="600" y="0"/>
<key name="k8" w="50" h="50" x="600" y="50"/>
<key name="k9" w="50" h="50" x="600" y="100"/>
<key name="k10" w="50" h="50" x="600" y="150"/>
<key name="k11" w="50" h="50" x="600" y="200"/>
<key name="k12" w="50" h="50" x="600" y="250"/>
<key name="k13" w="50" h="50" x="650" y="0"/>
<key name="k14" w="50" h="50" x="650" y="50"/>
<key name="k15" w="50" h="50" x="650" y="100"/>
<key name="k16" w="50" h="50" x="650" y="150"/>
<key name="k17" w="50" h="50" x="650" y="200"/>
<key name="k18" w="50" h="50" x="650" y="250"/>
<key name="k19" w="50" h="50" x="700" y="0"/>
<key name="k20" w="50" h="50" x="700" y="50"/>
<key name="k21" w="50" h="50" x="700" y="100"/>
<key name="k22" w="50" h="50" x="700" y="150"/>
<key name="k23" w="50" h="50" x="700" y="200"/>
<key name="k24" w="50" h="50" x="700" y="250"/>
<key name="k25" w="50" h="50" x="750" y="0"/>
<key name="k26" w="50" h="50" x="750" y="50"/>
<key name="k27" w="50" h="50" x="750" y="100"/>
<key name="k28" w="50" h="50" x="750" y="150"/>
<key name="k29" w="50" h="50" x="750" y="200"/>
<key name="k30" w="50" h="50" x="750" y="250"/>
<key name="k31" w="50" h="50" x="800" y="0"/>
<key name="k32" w="50" h="50" x="800" y="50"/>
<key name="k33" w="50" h="50" x="800" y="100"/>
<key name="k34" w="50" h="50" x="800" y="150"/>
<key name="k35" w="50" h="50" x="800" y="200"/>
<key name="k36" w="50" h="50" x="800" y="250"/>
<key name="k37" w="50" h="50" x="850" y="0"/>
<key name="k38" w="50" h="50" x="850" y="50"/>
<key name="k39" w="50" h="50" x="850" y="100"/>
<key name="k40" w="50" h="50" x="850" y="150"/>
<key name="k41" w="50" h="50" x="850" y="200"/>
<key name="k42" w="50" h="50" x="850" y="250"/>
<key name="k43" w="50" h="50" x="900" y="0"/>
<key name="k44" w="50" h="50" x="900" y="50"/>
<key name="k45" w="50" h="50" x="900" y="100"/>
<key name="k46" w="50" h="50" x="900" y="150"/>
<key name="k47" w="50" h="50" x="900" y="200"/>
<key name="k48" w="50" h="50" x="900" y="250"/>
<key name="k49" w="50" h="50" x="300" y="350"/>
<key name="k50" w="50" h="50" x="300" y="300"/>
<key name="k51" w="50" h="50" x="350" y="350"/>
<key name="k52" w="50" h="50" x="350" y="300"/>
<key name="k53" w="50" h="50" x="400" y="350"/>
<key name="k54" w="50" h="50" x="400" y="300"/>
<key name="k55" w="50" h="50" x="300" y="0"/>
<key name="k56" w="50" h="50" x="300" y="50"/>
<key name="k57" w="50" h="50" x="300" y="100"/>
<key name="k58" w="50" h="50" x="300" y="150"/>
<key name="k59" w="50" h="50" x="300" y="200"/>
<key name="k60" w="50" h="50" x="300" y="250"/>
<key name="k61" w="50" h="50" x="250" y="0"/>
<key name="k62" w="50" h="50" x="250" y="50"/>
<key name="k63" w="50" h="50" x="250" y="100"/>
<key name="k64" w="50" h="50" x="250" y="150"/>
<key name="k65" w="50" h="50" x="250" y="200"/>
<key name="k66" w="50" h="50" x="250" y="250"/>
<key name="k67" w="50" h="50" x="200" y="0"/>
<key name="k68" w="50" h="50" x="200" y="50"/>
<key name="k69" w="50" h="50" x="200" y="100"/>
<key name="k70" w="50" h="50" x="200" y="150"/>
<key name="k71" w="50" h="50" x="200" y="200"/>
<key name="k72" w="50" h="50" x="200" y="250"/>
<key name="k73" w="50" h="50" x="150" y="0"/>
<key name="k74" w="50" h="50" x="150" y="50"/>
<key name="k75" w="50" h="50" x="150" y="100"/>
<key name="k76" w="50" h="50" x="150" y="150"/>
<key name="k77" w="50" h="50" x="150" y="200"/>
<key name="k78" w="50" h="50" x="150" y="250"/>
<key name="k79" w="50" h="50" x="100" y="0"/>
<key name="k80" w="50" h="50" x="100" y="50"/>
<key name="k81" w="50" h="50" x="100" y="100"/>
<key name="k82" w="50" h="50" x="100" y="150"/>
<key name="k83" w="50" h="50" x="100" y="200"/>
<key name="k84" w="50" h="50" x="100" y="250"/>
<key name="k85" w="50" h="50" x="50" y="0"/>
<key name="k86" w="50" h="50" x="50" y="50"/>
<key name="k87" w="50" h="50" x="50" y="100"/>
<key name="k88" w="50" h="50" x="50" y="150"/>
<key name="k89" w="50" h="50" x="50" y="200"/>
<key name="k90" w="50" h="50" x="50" y="250"/>
<key name="k91" w="50" h="50" x="0" y="0"/>
<key name="k92" w="50" h="50" x="0" y="50"/>
<key name="k93" w="50" h="50" x="0" y="100"/>
<key name="k94" w="50" h="50" x="0" y="150"/>
<key name="k95" w="50" h="50" x="0" y="200"/>
<key name="k96" w="50" h="50" x="0" y="250"/>
</layout></keyboard>
134 changes: 134 additions & 0 deletions qtclient/layout/make-3.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
#!/usr/bin/env ruby
# -*- indent-tabs-mode: nil -*-

Hitbox = Struct.new(:x, :y, :w, :h)
Key = Struct.new(:hitbox) do
def initialize(args)
super
@id = "k#{self.class.next_id}"
end

def image
end

def layout_entry
%Q{<key name="#{@id}" w="#{hitbox.w}" h="#{hitbox.h}" x="#{hitbox.x}" y="#{hitbox.y}"/>}
end

@gensym_id = 0
def self.next_id
@gensym_id += 1
end
end

class KeyBucket
def initialize
@keys = []
end

def <<(key)
@keys << key
end

def layout
['<keyboard layout="ugboard" layoutid="3" image="ugboard.png"><layout>'] +
@keys.map(&:layout_entry) +
['</layout></keyboard>']
end
end

class Layout
def layout_file
bucket.layout
end

private def bucket
@bucket ||= KeyBucket.new.tap { |b| build(b) }
end

class MatrixBuilder
def square_matrix(rows, cols,
row_start: 0, row_stride: 1,
col_start: 0, col_stride: 1,
order: :rows)

row = row_start
col = col_start

rows_left = rows
cols_left = cols

while rows_left > 0 && cols_left > 0
matrix_key!(row, col)

case order
when :rows
col += col_stride
cols_left -= 1
if cols_left == 0
col = col_start
cols_left = cols
row += row_stride
rows_left -= 1
end

when :cols
row += row_stride
rows_left -= 1
if rows_left == 0
row = row_start
rows_left = rows
col += col_stride
cols_left -= 1
end
end
end
end
end
end

class UgBoardLayout < Layout
class UgBuilder < MatrixBuilder
KEY_SIZE = 50

def initialize(bucket)
@bucket = bucket
end

def build!
right_thumb
right_keywell
left_thumb
left_keywell
end

def matrix_key!(row, col)
@bucket << Key.new(Hitbox.new((KEY_SIZE) * col, (KEY_SIZE) * row, KEY_SIZE, KEY_SIZE))
end

private

def left_keywell
square_matrix(6, 7, col_start: 6, col_stride: -1, order: :cols)
end

def left_thumb
square_matrix(2, 3, col_start: 6, row_start: 7, row_stride: -1, order: :cols)
end

def right_thumb
square_matrix(2, 3, col_start: 12, row_start: 7, row_stride: -1, col_stride: -1, order: :cols)
end

def right_keywell
square_matrix(6, 7, col_start: 12, order: :cols)
end
end

private def build(b)
UgBuilder.new(b).build!
end
end

layout = UgBoardLayout.new
File.open('3.xml', 'w') { |f| f.puts(layout.layout_file) }
Binary file added qtclient/layout/ugboard.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions qtclient/qtclient.qrc
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,7 @@
<file>layout/kinesis.png</file>
<file>layout/2.xml</file>
<file>layout/ergodox.png</file>
<file>layout/3.xml</file>
<file>layout/ugboard.png</file>
</qresource>
</RCC>

0 comments on commit 2fae988

Please sign in to comment.