maple: slightly refactor maple command initialization

This adopts a "writer" concept, vaguely inspired by the ta parameter
writer. This might turn out to be not a great idea if the
response/offsets for heterogenous commands are too inconvenient to
keep track of.

This breaks every example that uses maple--only
example/maple_controller is updated to use the new interface.
This commit is contained in:
Zack Buhman 2024-05-21 15:05:25 -05:00
parent b5ac43c109
commit 9801557535
25 changed files with 472 additions and 323 deletions

View File

@ -2,10 +2,11 @@ DEBUG = -g -gdwarf-4
AFLAGS += --fatal-warnings AFLAGS += --fatal-warnings
CFLAGS += -falign-functions=4 -ffunction-sections -fdata-sections -fshort-enums -ffreestanding -nostdlib CFLAGS += -falign-functions=4 -ffunction-sections -fdata-sections -fshort-enums -ffreestanding -nostdlib -fno-builtin -finline-stringops
CFLAGS += -Wall -Werror -Wfatal-errors CFLAGS += -Wall -Werror -Wfatal-errors
CFLAGS += -Wno-array-bounds CFLAGS += -Wno-array-bounds
#CFLAGS += -Wno-error=narrowing -Wno-error=unused-variable -Wno-error=array-bounds= #CFLAGS += -Wno-error=narrowing -Wno-error=unused-variable -Wno-error=array-bounds=
CFLAGS += -Wno-error=maybe-uninitialized
CXXFLAGS += -fno-exceptions -fno-non-call-exceptions -fno-rtti -fno-threadsafe-statics CXXFLAGS += -fno-exceptions -fno-non-call-exceptions -fno-rtti -fno-threadsafe-statics

View File

@ -2,7 +2,7 @@ MAKEFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST)))
DIR := $(dir $(MAKEFILE_PATH)) DIR := $(dir $(MAKEFILE_PATH))
LIB ?= . LIB ?= .
OPT ?= -O2 OPT ?= -Os
GENERATED ?= GENERATED ?=
AARCH = --isa=sh4 --little AARCH = --isa=sh4 --little

View File

@ -46,7 +46,7 @@ void do_get_condition(uint32_t * command_buf,
const uint32_t command_size = maple::init_host_command_all_ports<command_type, response_type>(command_buf, receive_buf, const uint32_t command_size = maple::init_host_command_all_ports<command_type, response_type>(command_buf, receive_buf,
data_fields); data_fields);
using host_response_type = struct maple::command_response<response_type::data_fields>; using host_response_type = struct maple::host_response<response_type::data_fields>;
auto host_response = reinterpret_cast<host_response_type *>(receive_buf); auto host_response = reinterpret_cast<host_response_type *>(receive_buf);
maple::dma_start(command_buf, command_size, maple::dma_start(command_buf, command_size,

View File

@ -47,9 +47,8 @@ void do_get_condition(uint32_t * command_buf,
.function_type = std::byteswap(function_type::controller) .function_type = std::byteswap(function_type::controller)
}; };
const uint32_t command_size = maple::init_host_command_all_ports<command_type, response_type>(command_buf, receive_buf, const uint32_t command_size = maple::init_host_command_all_ports<command_type, response_type>(command_buf, receive_buf, data_fields);
data_fields); using host_response_type = struct maple::host_response<response_type::data_fields>;
using host_response_type = struct maple::command_response<response_type::data_fields>;
auto host_response = reinterpret_cast<host_response_type *>(receive_buf); auto host_response = reinterpret_cast<host_response_type *>(receive_buf);
maple::dma_start(command_buf, command_size, maple::dma_start(command_buf, command_size,
receive_buf, maple::sizeof_command(host_response)); receive_buf, maple::sizeof_command(host_response));

View File

@ -51,14 +51,14 @@ void do_get_condition(uint32_t * command_buf,
const uint32_t command_size = maple::init_host_command_all_ports<command_type, response_type>(command_buf, receive_buf, const uint32_t command_size = maple::init_host_command_all_ports<command_type, response_type>(command_buf, receive_buf,
data_fields); data_fields);
using host_response_type = struct maple::command_response<response_type::data_fields>; using host_response_type = struct maple::host_response<response_type::data_fields>;
auto host_response = reinterpret_cast<host_response_type *>(receive_buf); auto host_response = reinterpret_cast<host_response_type *>(receive_buf);
maple::dma_start(command_buf, command_size, maple::dma_start(command_buf, command_size,
receive_buf, maple::sizeof_command(host_response)); receive_buf, maple::sizeof_command(host_response));
using command_response_type = struct maple::command_response<response_type::data_fields>; using host_response_type = struct maple::host_response<response_type::data_fields>;
for (uint8_t port = 0; port < 4; port++) { for (uint8_t port = 0; port < 4; port++) {
auto response = reinterpret_cast<command_response_type *>(receive_buf); auto response = reinterpret_cast<host_response_type *>(receive_buf);
auto& bus_data = response[port].bus_data; auto& bus_data = response[port].bus_data;
if (bus_data.command_code != response_type::command_code) { if (bus_data.command_code != response_type::command_code) {
return; return;

View File

@ -46,7 +46,7 @@ void do_get_condition(uint32_t * command_buf,
const uint32_t command_size = maple::init_host_command_all_ports<command_type, response_type>(command_buf, receive_buf, const uint32_t command_size = maple::init_host_command_all_ports<command_type, response_type>(command_buf, receive_buf,
data_fields); data_fields);
using host_response_type = struct maple::command_response<response_type::data_fields>; using host_response_type = struct maple::host_response<response_type::data_fields>;
auto host_response = reinterpret_cast<host_response_type *>(receive_buf); auto host_response = reinterpret_cast<host_response_type *>(receive_buf);
maple::dma_start(command_buf, command_size, maple::dma_start(command_buf, command_size,

View File

@ -5,65 +5,39 @@
#include "holly/core_bits.hpp" #include "holly/core_bits.hpp"
#include "holly/holly.hpp" #include "holly/holly.hpp"
#include "maple/maple.hpp" #include "maple/maple.hpp"
#include "maple/maple_impl.hpp" #include "maple/maple_port.hpp"
#include "maple/maple_bus_bits.hpp" #include "maple/maple_bus_bits.hpp"
#include "maple/maple_bus_commands.hpp" #include "maple/maple_bus_commands.hpp"
#include "maple/maple_bus_ft0.hpp" #include "maple/maple_bus_ft0.hpp"
#include "maple/maple_host_command_writer.hpp"
#include "sh7091/serial.hpp" #include "sh7091/serial.hpp"
uint32_t _command_buf[(1024 + 32) / 4]; #include "systembus.hpp"
uint32_t _receive_buf[(1024 + 32) / 4];
static uint32_t * command_buf; void do_get_condition()
static uint32_t * receive_buf;
void do_get_condition(uint32_t port)
{ {
uint32_t destination_port; uint32_t send_buf[1024] __attribute__((aligned(32)));
uint32_t destination_ap; uint32_t recv_buf[1024] __attribute__((aligned(32)));
switch (port) { auto writer = maple::host_command_writer(send_buf, recv_buf);
case 0:
destination_port = host_instruction::port_select::a;
destination_ap = ap::de::device | ap::port_select::a;
break;
case 1:
destination_port = host_instruction::port_select::b;
destination_ap = ap::de::device | ap::port_select::b;
break;
case 2:
destination_port = host_instruction::port_select::c;
destination_ap = ap::de::device | ap::port_select::c;
break;
case 3:
destination_port = host_instruction::port_select::d;
destination_ap = ap::de::device | ap::port_select::d;
break;
default:
return;
}
const uint32_t command_size = maple::init_get_condition(command_buf, receive_buf,
destination_port,
destination_ap,
std::byteswap(function_type::controller));
using command_type = get_condition;
using response_type = data_transfer<ft0::data_transfer::data_format>; using response_type = data_transfer<ft0::data_transfer::data_format>;
using command_response_type = struct maple::command_response<response_type::data_fields>;
auto host_response = reinterpret_cast<command_response_type *>(receive_buf);
maple::dma_start(command_buf, command_size, auto [host_command, host_response]
receive_buf, maple::sizeof_command(host_response)); = writer.append_command_all_ports<command_type, response_type>();
auto& bus_data = host_response->bus_data; maple::dma_start(send_buf, writer.send_offset,
if (bus_data.command_code != response_type::command_code) { recv_buf, writer.recv_offset);
return;
} for (uint8_t port = 0; port < 4; port++) {
auto& bus_data = host_response[port].bus_data;
auto& data_fields = bus_data.data_fields; auto& data_fields = bus_data.data_fields;
if ((data_fields.function_type & std::byteswap(function_type::controller)) == 0) {
return;
}
if (bus_data.command_code != response_type::command_code) {
//serial::string("device did not reply to get_condition: ");
//serial::integer<uint8_t>(port);
} else if ((data_fields.function_type & std::byteswap(function_type::controller)) != 0) {
bool a = ft0::data_transfer::digital_button::a(data_fields.data.digital_button); bool a = ft0::data_transfer::digital_button::a(data_fields.data.digital_button);
if (a == 0) { if (a == 0) {
serial::string("port "); serial::string("port ");
@ -71,48 +45,122 @@ void do_get_condition(uint32_t port)
serial::string(" `a` press "); serial::string(" `a` press ");
serial::integer<uint8_t>(a); serial::integer<uint8_t>(a);
} }
}
}
}
void do_lm_request(uint8_t port, uint8_t lm)
{
uint32_t send_buf[1024] __attribute__((aligned(32)));
uint32_t recv_buf[1024] __attribute__((aligned(32)));
auto writer = maple::host_command_writer(send_buf, recv_buf);
uint32_t host_port_select = host_instruction_port_select(port);
uint32_t destination_ap = ap_port_select(port) | ap::de::expansion_device | lm;
using command_type = device_request;
using response_type = device_status;
auto [host_command, host_response]
= writer.append_command<command_type, response_type>(host_port_select,
destination_ap,
true); // end_flag
maple::dma_start(send_buf, writer.send_offset,
recv_buf, writer.recv_offset);
auto& bus_data = host_response->bus_data;
auto& data_fields = bus_data.data_fields;
if (bus_data.command_code != device_status::command_code) {
serial::string("lm did not reply: ");
serial::integer<uint8_t>(port, ' ');
serial::integer<uint8_t>(lm);
} else {
serial::string(" lm: ");
serial::integer<uint8_t>(lm);
serial::string(" ft: ");
serial::integer<uint32_t>(std::byteswap(data_fields.device_id.ft));
serial::string(" fd[0]: ");
serial::integer<uint32_t>(std::byteswap(data_fields.device_id.fd[0]));
serial::string(" fd[1]: ");
serial::integer<uint32_t>(std::byteswap(data_fields.device_id.fd[1]));
serial::string(" fd[2]: ");
serial::integer<uint32_t>(std::byteswap(data_fields.device_id.fd[2]));
serial::string(" source_ap.lm_bus: ");
serial::integer<uint8_t>(bus_data.source_ap & ap::lm_bus::bit_mask);
}
}
void do_lm_requests(uint8_t port, uint8_t lm)
{
if (lm & ap::lm_bus::_0)
do_lm_request(port, lm & ap::lm_bus::_0);
if (lm & ap::lm_bus::_1)
do_lm_request(port, lm & ap::lm_bus::_1);
if (lm & ap::lm_bus::_2)
do_lm_request(port, lm & ap::lm_bus::_2);
if (lm & ap::lm_bus::_3)
do_lm_request(port, lm & ap::lm_bus::_3);
if (lm & ap::lm_bus::_4)
do_lm_request(port, lm & ap::lm_bus::_4);
} }
void do_device_request() void do_device_request()
{ {
uint32_t send_buf[1024] __attribute__((aligned(32)));
uint32_t recv_buf[1024] __attribute__((aligned(32)));
auto writer = maple::host_command_writer(send_buf, recv_buf);
using command_type = device_request; using command_type = device_request;
using response_type = device_status; using response_type = device_status;
const uint32_t command_size = maple::init_host_command_all_ports<command_type, response_type>(command_buf, receive_buf); auto [host_command, host_response]
using host_response_type = struct maple::command_response<response_type::data_fields>; = writer.append_command_all_ports<command_type, response_type>();
auto host_response = reinterpret_cast<host_response_type *>(receive_buf);
maple::dma_start(command_buf, command_size, maple::dma_start(send_buf, writer.send_offset,
receive_buf, maple::sizeof_command(host_response)); recv_buf, writer.recv_offset);
for (uint8_t port = 0; port < 4; port++) { for (uint8_t port = 0; port < 4; port++) {
auto& bus_data = host_response[port].bus_data; auto& bus_data = host_response[port].bus_data;
auto& data_fields = host_response[port].bus_data.data_fields; auto& data_fields = bus_data.data_fields;
if (bus_data.command_code != device_status::command_code) { if (bus_data.command_code != device_status::command_code) {
// the controller is disconnected serial::string("port: ");
serial::integer<uint8_t>(port);
serial::string(" disconnected\n");
} else { } else {
if ((data_fields.device_id.ft & std::byteswap(function_type::controller)) != 0) { serial::string("port: ");
//serial::string("is controller: "); serial::integer<uint8_t>(port);
//serial::integer<uint8_t>(port); serial::string(" ft: ");
do_get_condition(port); serial::integer<uint32_t>(std::byteswap(data_fields.device_id.ft));
} serial::string(" fd[0]: ");
serial::integer<uint32_t>(std::byteswap(data_fields.device_id.fd[0]));
serial::string(" fd[1]: ");
serial::integer<uint32_t>(std::byteswap(data_fields.device_id.fd[1]));
serial::string(" fd[2]: ");
serial::integer<uint32_t>(std::byteswap(data_fields.device_id.fd[2]));
serial::string(" source_ap.lm_bus: ");
serial::integer<uint8_t>(bus_data.source_ap & ap::lm_bus::bit_mask);
do_lm_requests(port,
bus_data.source_ap & ap::lm_bus::bit_mask);
} }
} }
} }
void main() void main()
{ {
command_buf = align_32byte(_command_buf);
command_buf = reinterpret_cast<uint32_t *>(reinterpret_cast<uint32_t>(command_buf) | 0xa000'0000);
receive_buf = align_32byte(_receive_buf);
// flycast needs this in HLE mode, or else it won't start the vcount // flycast needs this in HLE mode, or else it won't start the vcount
// counter. // counter.
video_output::set_mode_vga(); video_output::set_mode_vga();
do_device_request();
while (1) { while (1) {
while (!spg_status::vsync(holly.SPG_STATUS)); while (!spg_status::vsync(holly.SPG_STATUS));
while (spg_status::vsync(holly.SPG_STATUS)); while (spg_status::vsync(holly.SPG_STATUS));
do_device_request();
do_get_condition();
}; };
} }

View File

@ -18,7 +18,7 @@ void main()
uint32_t command_size = maple::init_host_command_all_ports<command_type, response_type>(command_buf, receive_buf); uint32_t command_size = maple::init_host_command_all_ports<command_type, response_type>(command_buf, receive_buf);
constexpr uint32_t host_response_size = (sizeof (maple::command_response<response_type::data_fields>)); constexpr uint32_t host_response_size = (sizeof (maple::host_response<response_type::data_fields>));
maple::dma_start(command_buf, command_size, maple::dma_start(command_buf, command_size,
receive_buf, host_response_size); receive_buf, host_response_size);

View File

@ -47,16 +47,17 @@ void do_lm_request(uint8_t port, uint8_t lm)
maple::init_host_command(command_buf, receive_buf, maple::init_host_command(command_buf, receive_buf,
destination_port, destination_port,
destination_ap, get_media_info::command_code, (sizeof (struct get_media_info::data_fields)), destination_ap, get_media_info::command_code, (sizeof (struct get_media_info::data_fields)),
true); true); // end_flag
using host_command_type = struct maple::host_command<get_media_info::data_fields>; using command_type = get_media_info;
using host_command_type = struct maple::host_command<command_type::data_fields>;
auto host_command = reinterpret_cast<host_command_type *>(command_buf); auto host_command = reinterpret_cast<host_command_type *>(command_buf);
auto& fields = host_command->bus_data.data_fields; auto& fields = host_command->bus_data.data_fields;
fields.function_type = std::byteswap(function_type::vibration); fields.function_type = std::byteswap(function_type::vibration);
fields.pt = std::byteswap(1 << 24); fields.pt = std::byteswap(1 << 24);
using response_type = data_transfer<ft8::data_transfer::data_format>; using response_type = data_transfer<ft8::data_transfer::data_format>;
using host_response_type = struct maple::command_response<response_type::data_fields>; using host_response_type = struct maple::host_response<response_type::data_fields>;
auto host_response = reinterpret_cast<host_response_type *>(receive_buf); auto host_response = reinterpret_cast<host_response_type *>(receive_buf);
serial::string("dma start\n"); serial::string("dma start\n");
@ -118,7 +119,7 @@ void do_lm_request(uint8_t port, uint8_t lm)
fields.write_in_data.freq = 0x27; fields.write_in_data.freq = 0x27;
fields.write_in_data.inc = 0x00; fields.write_in_data.inc = 0x00;
using host_response_type = struct maple::command_response<device_reply::data_fields>; using host_response_type = struct maple::host_response<device_reply::data_fields>;
auto host_response = reinterpret_cast<host_response_type *>(receive_buf); auto host_response = reinterpret_cast<host_response_type *>(receive_buf);
maple::dma_start(command_buf, maple::sizeof_command(host_command), maple::dma_start(command_buf, maple::sizeof_command(host_command),
receive_buf, maple::sizeof_command(host_response)); receive_buf, maple::sizeof_command(host_response));
@ -154,11 +155,11 @@ void do_device_request()
{ {
using command_type = device_request; using command_type = device_request;
using response_type = device_status; using response_type = device_status;
using host_response_type = struct maple::command_response<response_type::data_fields>; using host_response_type = struct maple::host_response<response_type::data_fields>;
auto host_response = reinterpret_cast<host_response_type *>(receive_buf); auto host_response = reinterpret_cast<host_response_type *>(receive_buf);
const uint32_t command_size = maple::init_host_command_all_ports<command_type, response_type>(command_buf, receive_buf); const uint32_t command_size = maple::init_host_command_all_ports<command_type, response_type>(command_buf, receive_buf);
maple::dma_start(command_buf, command_size, maple::dma_start(command_buf, command_size,
receive_buf, maple::sizeof_command(host_response)); receive_buf, maple::sizeof_command(host_response) * 4);
for (uint8_t port = 0; port < 4; port++) { for (uint8_t port = 0; port < 4; port++) {
auto& bus_data = host_response[port].bus_data; auto& bus_data = host_response[port].bus_data;
@ -193,5 +194,6 @@ void main()
while (spg_status::vsync(holly.SPG_STATUS)); while (spg_status::vsync(holly.SPG_STATUS));
} }
do_device_request(); do_device_request();
break;
}; };
} }

View File

@ -42,12 +42,12 @@ void main()
uint32_t * receive_buf = align_32byte(_receive_buf); uint32_t * receive_buf = align_32byte(_receive_buf);
const uint32_t command_size = maple::init_block_write(command_buf, receive_buf, const uint32_t command_size = maple::init_block_write(command_buf, receive_buf,
host_instruction::port_select::a, host_instruction::port_select::b,
ap::de::expansion_device | ap::port_select::a | ap::lm_bus::_0, ap::de::expansion_device | ap::port_select::b | ap::lm_bus::_0,
wink_buf, wink_buf,
wink_size); wink_size);
using response_type = device_reply; using response_type = device_reply;
using host_response_type = struct maple::command_response<response_type::data_fields>; using host_response_type = struct maple::host_response<response_type::data_fields>;
auto host_response = reinterpret_cast<host_response_type *>(receive_buf); auto host_response = reinterpret_cast<host_response_type *>(receive_buf);
maple::dma_start(command_buf, command_size, maple::dma_start(command_buf, command_size,
receive_buf, maple::sizeof_command(host_response)); receive_buf, maple::sizeof_command(host_response));
@ -56,6 +56,4 @@ void main()
serial::integer<uint8_t>(host_response->bus_data.destination_ap); serial::integer<uint8_t>(host_response->bus_data.destination_ap);
serial::integer<uint8_t>(host_response->bus_data.source_ap); serial::integer<uint8_t>(host_response->bus_data.source_ap);
serial::integer<uint8_t>(host_response->bus_data.data_size); serial::integer<uint8_t>(host_response->bus_data.data_size);
while(1);
} }

View File

@ -47,7 +47,7 @@ void do_get_condition(uint32_t * command_buf,
const uint32_t command_size = maple::init_host_command_all_ports<command_type, response_type>(command_buf, receive_buf, const uint32_t command_size = maple::init_host_command_all_ports<command_type, response_type>(command_buf, receive_buf,
data_fields); data_fields);
using host_response_type = struct maple::command_response<response_type::data_fields>; using host_response_type = struct maple::host_response<response_type::data_fields>;
auto host_response = reinterpret_cast<host_response_type *>(receive_buf); auto host_response = reinterpret_cast<host_response_type *>(receive_buf);
maple::dma_start(command_buf, command_size, maple::dma_start(command_buf, command_size,

View File

@ -244,7 +244,7 @@ void do_get_condition(uint32_t * command_buf,
const uint32_t command_size = maple::init_host_command_all_ports<command_type, response_type>(command_buf, receive_buf, const uint32_t command_size = maple::init_host_command_all_ports<command_type, response_type>(command_buf, receive_buf,
data_fields); data_fields);
using host_response_type = struct maple::command_response<response_type::data_fields>; using host_response_type = struct maple::host_response<response_type::data_fields>;
auto host_response = reinterpret_cast<host_response_type *>(receive_buf); auto host_response = reinterpret_cast<host_response_type *>(receive_buf);
maple::dma_start(command_buf, command_size, maple::dma_start(command_buf, command_size,

View File

@ -15,6 +15,7 @@
namespace maple { namespace maple {
/*
void init_host_command(uint32_t * command_buf, uint32_t * receive_buf, void init_host_command(uint32_t * command_buf, uint32_t * receive_buf,
uint32_t destination_port, uint32_t destination_port,
uint8_t destination_ap, uint8_t command_code, uint8_t data_size, uint8_t destination_ap, uint8_t command_code, uint8_t data_size,
@ -104,6 +105,7 @@ uint32_t init_block_write(uint32_t * command_buf, uint32_t * receive_buf,
return (reinterpret_cast<uint32_t>(&host_command[1]) - reinterpret_cast<uint32_t>(&host_command[0])) return (reinterpret_cast<uint32_t>(&host_command[1]) - reinterpret_cast<uint32_t>(&host_command[0]))
+ data_size; + data_size;
} }
*/
static inline void _dma_start(const uint32_t * command_buf) static inline void _dma_start(const uint32_t * command_buf)
{ {

View File

@ -22,7 +22,7 @@ static_assert((sizeof (host_command<uint8_t[0]>)) == 12);
static_assert((sizeof (host_command<uint8_t[0]>[4])) == 48); static_assert((sizeof (host_command<uint8_t[0]>[4])) == 48);
template <typename T> template <typename T>
struct command_response { struct host_response {
struct bus_data { struct bus_data {
uint8_t command_code; uint8_t command_code;
uint8_t destination_ap; uint8_t destination_ap;
@ -32,7 +32,7 @@ struct command_response {
} bus_data; } bus_data;
uint8_t _pad[align_32byte((sizeof (bus_data))) - (sizeof (bus_data))]; uint8_t _pad[align_32byte((sizeof (bus_data))) - (sizeof (bus_data))];
}; };
static_assert((sizeof (command_response<uint8_t[0]>)) == align_32byte((sizeof (command_response<uint8_t[0]>)))); static_assert((sizeof (host_response<uint8_t[0]>)) == align_32byte((sizeof (host_response<uint8_t[0]>))));
void init_host_command(uint32_t * buf, uint32_t * receive_buf, void init_host_command(uint32_t * buf, uint32_t * receive_buf,
uint32_t destination_port, uint32_t destination_port,

View File

@ -1,7 +1,9 @@
#pragma once
#include <cstdint> #include <cstdint>
namespace ft6 { namespace ft6 {
namespace scan_codes { namespace scan_code {
constexpr uint32_t no_operation = 0x0; constexpr uint32_t no_operation = 0x0;
constexpr uint32_t rollover_error = 0x1; constexpr uint32_t rollover_error = 0x1;
constexpr uint32_t post_fail = 0x2; constexpr uint32_t post_fail = 0x2;
@ -52,7 +54,7 @@ namespace ft6 {
constexpr uint32_t bracketleft_braceleft = 0x2f; constexpr uint32_t bracketleft_braceleft = 0x2f;
constexpr uint32_t bracketright_braceright = 0x30; constexpr uint32_t bracketright_braceright = 0x30;
constexpr uint32_t backslash_bar = 0x31; constexpr uint32_t backslash_bar = 0x31;
constexpr uint32_t _unknown_ = 0x32; constexpr uint32_t iso_numbersign_tilde = 0x32;
constexpr uint32_t semicolon_colon = 0x33; constexpr uint32_t semicolon_colon = 0x33;
constexpr uint32_t apostrophe_quotedbl = 0x34; constexpr uint32_t apostrophe_quotedbl = 0x34;
constexpr uint32_t grave_asciitilde = 0x35; constexpr uint32_t grave_asciitilde = 0x35;
@ -87,4 +89,69 @@ namespace ft6 {
constexpr uint32_t up_arrow = 0x52; constexpr uint32_t up_arrow = 0x52;
} }
} }
namespace ft6 {
namespace scan_code {
constexpr uint32_t last_printable = 0x38;
const uint8_t code_point[last_printable + 1][2] = {
[scan_code::no_operation] = { 0, 0 },
[scan_code::rollover_error] = { 0, 0 },
[scan_code::post_fail] = { 0, 0 },
[scan_code::undefined_error] = { 0, 0 },
[scan_code::a_A] = { 'a', 'A' },
[scan_code::b_B] = { 'b', 'B' },
[scan_code::c_C] = { 'c', 'C' },
[scan_code::d_D] = { 'd', 'D' },
[scan_code::e_E] = { 'e', 'E' },
[scan_code::f_F] = { 'f', 'F' },
[scan_code::g_G] = { 'g', 'G' },
[scan_code::h_H] = { 'h', 'H' },
[scan_code::i_I] = { 'i', 'I' },
[scan_code::j_J] = { 'j', 'J' },
[scan_code::k_K] = { 'k', 'K' },
[scan_code::l_L] = { 'l', 'L' },
[scan_code::m_M] = { 'm', 'M' },
[scan_code::n_N] = { 'n', 'N' },
[scan_code::o_O] = { 'o', 'O' },
[scan_code::p_P] = { 'p', 'P' },
[scan_code::q_Q] = { 'q', 'Q' },
[scan_code::r_R] = { 'r', 'R' },
[scan_code::s_S] = { 's', 'S' },
[scan_code::t_T] = { 't', 'T' },
[scan_code::u_U] = { 'u', 'U' },
[scan_code::v_V] = { 'v', 'V' },
[scan_code::w_W] = { 'w', 'W' },
[scan_code::x_X] = { 'x', 'X' },
[scan_code::y_Y] = { 'y', 'Y' },
[scan_code::z_Z] = { 'z', 'Z' },
[scan_code::_1_exclam] = { '1', '!' },
[scan_code::_2_at] = { '2', '@' },
[scan_code::_3_numbersign] = { '3', '#' },
[scan_code::_4_dollar] = { '4', '$' },
[scan_code::_5_percent] = { '5', '%' },
[scan_code::_6_asciicircum] = { '6', '^' },
[scan_code::_7_ampersand] = { '7', '&' },
[scan_code::_8_asterisk] = { '8', '*' },
[scan_code::_9_parenleft] = { '9', '(' },
[scan_code::_0_parenright] = { '0', ')' },
[scan_code::_return] = { 0, 0 },
[scan_code::esc] = { 0, 0 },
[scan_code::backspace] = { 0, 0 },
[scan_code::tab] = { 0, 0 },
[scan_code::spacebar] = { 0, 0 },
[scan_code::minus_underscore] = { '-', '_' },
[scan_code::equal_plus] = { '=', '+' },
[scan_code::bracketleft_braceleft] = { '[', '{' },
[scan_code::bracketright_braceright] = { ']', '}' },
[scan_code::backslash_bar] = { '\\', '|' },
[scan_code::iso_numbersign_tilde] = { '#', '~' },
[scan_code::semicolon_colon] = { ';', ':' },
[scan_code::apostrophe_quotedbl] = { '\'', '"' },
[scan_code::grave_asciitilde] = { '\'', '~' },
[scan_code::comma_less] = { ',', '<' },
[scan_code::period_greater] = { '.', '>' },
[scan_code::slash_question] = { '/', '?' },
};
}
}

View File

@ -0,0 +1,72 @@
#pragma once
#include <cstdint>
#include <tuple>
#include "maple/maple.hpp"
#include "maple/maple_bus_commands.hpp"
#include "maple/maple_bus_bits.hpp"
namespace maple {
struct host_command_writer {
uint32_t * const send_buf;
uint32_t * const recv_buf;
uint32_t send_offset;
uint32_t recv_offset;
constexpr host_command_writer(uint32_t * const send_buf,
uint32_t * const recv_buf)
: send_buf(send_buf), recv_buf(recv_buf), send_offset(0), recv_offset(0)
{ }
template <typename C, typename R, int data_fields_trailing = 0>
constexpr inline std::tuple<maple::host_command<typename C::data_fields> *,
maple::host_response<typename R::data_fields> *>
append_command(uint32_t host_port_select,
uint32_t destination_ap,
bool end_flag)
{
using command_type = maple::host_command<typename C::data_fields>;
using response_type = maple::host_response<typename R::data_fields>;
constexpr uint32_t data_size = (sizeof (typename C::data_fields)) + data_fields_trailing;
static_assert((sizeof (command_type)) % 4 == 0);
static_assert((sizeof (response_type)) % 4 == 0);
static_assert(data_size % 4 == 0);
auto host_command = reinterpret_cast<command_type *>(&send_buf[send_offset / 4]);
auto host_response = reinterpret_cast<response_type *>(&recv_buf[recv_offset / 4]);
host_command->host_instruction = (end_flag ? host_instruction::end_flag : 0)
| (host_port_select & host_instruction::port_select::bit_mask)
| host_instruction::transfer_length(data_size / 4);
host_command->receive_data_storage_address = receive_data_storage_address::address(reinterpret_cast<uint32_t>(host_response));
host_command->bus_data.command_code = C::command_code;
host_command->bus_data.destination_ap = destination_ap;
host_command->bus_data.source_ap = destination_ap & ap::port_select::bit_mask;
host_command->bus_data.data_size = data_size / 4;
send_offset += (sizeof (command_type)) + data_fields_trailing;
recv_offset += (sizeof (response_type));
return {host_command, host_response};
}
template <typename C, typename R>
constexpr inline std::tuple<maple::host_command<typename C::data_fields> *,
maple::host_response<typename R::data_fields> *>
append_command_all_ports()
{
auto ret = append_command<C, R, 0>(host_instruction::port_select::a, ap::de::device | ap::port_select::a, false);
append_command<C, R, 0>(host_instruction::port_select::b, ap::de::device | ap::port_select::b, false);
append_command<C, R, 0>(host_instruction::port_select::c, ap::de::device | ap::port_select::c, false);
append_command<C, R, 0>(host_instruction::port_select::d, ap::de::device | ap::port_select::d, true);
return ret;
}
};
}

View File

@ -1,81 +0,0 @@
#pragma once
#include <cstdint>
#include "maple/maple.hpp"
#include "maple/maple_bus_commands.hpp"
#include "maple/maple_bus_bits.hpp"
namespace maple {
template <typename C, typename R>
uint32_t init_host_command_all_ports(uint32_t * command_buf, uint32_t * receive_buf,
const typename C::data_fields& data_fields)
{
using command_type = maple::host_command<typename C::data_fields>;
using response_type = maple::command_response<typename R::data_fields>;
auto host_command = reinterpret_cast<command_type *>(command_buf);
auto response_command = reinterpret_cast<response_type *>(receive_buf);
init_host_command((uint32_t*)&host_command[0], (uint32_t*)&response_command[0],
host_instruction::port_select::a, // destination_port
ap::de::device | ap::port_select::a, C::command_code, (sizeof (typename C::data_fields)),
false); // end_flag
host_command[0].bus_data.data_fields = data_fields;
init_host_command((uint32_t*)&host_command[1], (uint32_t*)&response_command[1],
host_instruction::port_select::b, // destination_port
ap::de::device | ap::port_select::b, C::command_code, (sizeof (typename C::data_fields)),
false); // end_flag
host_command[1].bus_data.data_fields = data_fields;
init_host_command((uint32_t*)&host_command[2], (uint32_t*)&response_command[2],
host_instruction::port_select::c, // destination_port
ap::de::device | ap::port_select::c, C::command_code, (sizeof (typename C::data_fields)),
false); // end_flag
host_command[2].bus_data.data_fields = data_fields;
init_host_command((uint32_t*)&host_command[3], (uint32_t*)&response_command[3],
host_instruction::port_select::d, // destination_port
ap::de::device | ap::port_select::d, C::command_code, (sizeof (typename C::data_fields)),
true); // end_flag
host_command[3].bus_data.data_fields = data_fields;
return reinterpret_cast<uint32_t>(&host_command[4]) - reinterpret_cast<uint32_t>(&host_command[0]);
}
template <typename C, typename R>
uint32_t init_host_command_all_ports(uint32_t * command_buf, uint32_t * receive_buf)
{
using command_type = maple::host_command<typename C::data_fields>;
using response_type = maple::command_response<typename R::data_fields>;
//static_assert((sizeof (command_type)) == 12);
auto host_command = reinterpret_cast<command_type *>(command_buf);
auto response_command = reinterpret_cast<response_type *>(receive_buf);
init_host_command((uint32_t*)&host_command[0], (uint32_t*)&response_command[0],
host_instruction::port_select::a, // destination_port
ap::de::device | ap::port_select::a, C::command_code, (sizeof (typename C::data_fields)),
false); // end_flag
init_host_command((uint32_t*)&host_command[1], (uint32_t*)&response_command[1],
host_instruction::port_select::b, // destination_port
ap::de::device | ap::port_select::b, C::command_code, (sizeof (typename C::data_fields)),
false); // end_flag
init_host_command((uint32_t*)&host_command[2], (uint32_t*)&response_command[2],
host_instruction::port_select::c, // destination_port
ap::de::device | ap::port_select::c, C::command_code, (sizeof (typename C::data_fields)),
false); // end_flag
init_host_command((uint32_t*)&host_command[3], (uint32_t*)&response_command[3],
host_instruction::port_select::d, // destination_port
ap::de::device | ap::port_select::d, C::command_code, (sizeof (typename C::data_fields)),
true); // end_flag
return reinterpret_cast<uint32_t>(&host_command[1]) - reinterpret_cast<uint32_t>(&host_command[0]);
}
}

25
maple/maple_port.hpp Normal file
View File

@ -0,0 +1,25 @@
#pragma once
#include "maple_bus_bits.hpp"
constexpr inline uint32_t ap_port_select(const uint32_t port)
{
switch (port) {
default: [[fallthrough]];
case 0: return ap::port_select::a;
case 1: return ap::port_select::b;
case 2: return ap::port_select::c;
case 3: return ap::port_select::d;
}
}
constexpr inline uint32_t host_instruction_port_select(const uint32_t port)
{
switch (port) {
default: [[fallthrough]];
case 0: return host_instruction::port_select::a;
case 1: return host_instruction::port_select::b;
case 2: return host_instruction::port_select::c;
case 3: return host_instruction::port_select::d;
}
}

View File

@ -121,7 +121,7 @@ def render_format(format):
def render_formats(name, formats): def render_formats(name, formats):
yield "#pragma once" yield "#pragma once"
yield ""
yield f"namespace {name} {{" yield f"namespace {name} {{"
for format in formats: for format in formats:
yield from render_format(format) yield from render_format(format)

View File

@ -1,4 +1,5 @@
import sys import sys
import string
from csv_input import read_input from csv_input import read_input
from generate import renderer from generate import renderer
@ -9,17 +10,59 @@ def render_row(row):
yield f"constexpr uint32_t {usage} = {hex(code)};" yield f"constexpr uint32_t {usage} = {hex(code)};"
def render_rows(rows): def render_rows(rows):
yield "#include <cstdint>"
yield ""
yield "namespace ft6 {" yield "namespace ft6 {"
yield "namespace scan_codes {" yield "namespace scan_code {"
for row in rows: for row in rows:
yield from render_row(row) yield from render_row(row)
yield "}" yield "}"
yield "}" yield "}"
def code_point(s):
if not s.strip():
return '0'
elif len(s) == 1:
assert s in string.printable
if s == '\\':
return "'\\\\'"
elif s.strip() == "'":
return "'\\''"
else:
return f"'{s}'"
else:
assert False, s
last_printable = 0x38
def render_normal_shift(row):
usage = row['usage']
normal = code_point(row['normal'])
shift = code_point(row['shift'])
yield f"[scan_code::{usage}] = {{ {normal}, {shift} }},"
def render_scancode_code_point(rows):
yield "namespace ft6 {"
yield "namespace scan_code {"
yield f"constexpr uint32_t last_printable = {hex(last_printable)};"
yield ""
yield f"const uint8_t code_point[last_printable + 1][2] = {{"
for i, row in enumerate(rows):
yield from render_normal_shift(row)
if i == last_printable:
break
yield "};"
yield "}"
yield "}"
def header():
yield "#pragma once"
yield ""
yield "#include <cstdint>"
yield ""
if __name__ == "__main__": if __name__ == "__main__":
rows = read_input(sys.argv[1]) rows = read_input(sys.argv[1])
render, out = renderer() render, out = renderer()
render(header())
render(render_rows(rows)) render(render_rows(rows))
render(render_scancode_code_point(rows))
print(out.getvalue()) print(out.getvalue())

View File

@ -1,84 +1,84 @@
"code","usage", "code","usage","normal","shift"
"0x00","no_operation", "0x00","no_operation",,
"0x01","rollover_error", "0x01","rollover_error",,
"0x02","post_fail", "0x02","post_fail",,
"0x03","undefined_error", "0x03","undefined_error",,
"0x04","a_A", "0x04","a_A","a","A"
"0x05","b_B", "0x05","b_B","b","B"
"0x06","c_C", "0x06","c_C","c","C"
"0x07","d_D", "0x07","d_D","d","D"
"0x08","e_E", "0x08","e_E","e","E"
"0x09","f_F", "0x09","f_F","f","F"
"0x0a","g_G", "0x0a","g_G","g","G"
"0x0b","h_H", "0x0b","h_H","h","H"
"0x0c","i_I", "0x0c","i_I","i","I"
"0x0d","j_J", "0x0d","j_J","j","J"
"0x0e","k_K", "0x0e","k_K","k","K"
"0x0f","l_L", "0x0f","l_L","l","L"
"0x10","m_M", "0x10","m_M","m","M"
"0x11","n_N", "0x11","n_N","n","N"
"0x12","o_O", "0x12","o_O","o","O"
"0x13","p_P", "0x13","p_P","p","P"
"0x14","q_Q", "0x14","q_Q","q","Q"
"0x15","r_R", "0x15","r_R","r","R"
"0x16","s_S", "0x16","s_S","s","S"
"0x17","t_T", "0x17","t_T","t","T"
"0x18","u_U", "0x18","u_U","u","U"
"0x19","v_V", "0x19","v_V","v","V"
"0x1a","w_W", "0x1a","w_W","w","W"
"0x1b","x_X", "0x1b","x_X","x","X"
"0x1c","y_Y", "0x1c","y_Y","y","Y"
"0x1d","z_Z", "0x1d","z_Z","z","Z"
"0x1e","_1_exclam", "0x1e","_1_exclam",1,"!"
"0x1f","_2_at", "0x1f","_2_at",2,"@"
"0x20","_3_numbersign", "0x20","_3_numbersign",3,"#"
"0x21","_4_dollar", "0x21","_4_dollar",4,"$"
"0x22","_5_percent", "0x22","_5_percent",5,"%"
"0x23","_6_asciicircum", "0x23","_6_asciicircum",6,"^"
"0x24","_7_ampersand", "0x24","_7_ampersand",7,"&"
"0x25","_8_asterisk", "0x25","_8_asterisk",8,"*"
"0x26","_9_parenleft", "0x26","_9_parenleft",9,"("
"0x27","_0_parenright", "0x27","_0_parenright",0,")"
"0x28","_return", "0x28","_return",,
"0x29","esc", "0x29","esc",,
"0x2a","backspace", "0x2a","backspace",,
"0x2b","tab", "0x2b","tab",,
"0x2c","spacebar", "0x2c","spacebar",,
"0x2d","minus_underscore", "0x2d","minus_underscore","-","_"
"0x2e","equal_plus","underscore carot" "0x2e","equal_plus","=","+"
"0x2f","bracketleft_braceleft","at" "0x2f","bracketleft_braceleft","[","{"
"0x30","bracketright_braceright","braceleft" "0x30","bracketright_braceright","]","}"
"0x31","backslash_bar", "0x31","backslash_bar","\","|"
"0x32","_unknown_", "0x32","iso_numbersign_tilde","#","~"
"0x33","semicolon_colon", "0x33","semicolon_colon",";",":"
"0x34","apostrophe_quotedbl", "0x34","apostrophe_quotedbl","'",""""
"0x35","grave_asciitilde", "0x35","grave_asciitilde","'","~"
"0x36","comma_less", "0x36","comma_less",",","<"
"0x37","period_greater", "0x37","period_greater",".",">"
"0x38","slash_question", "0x38","slash_question","/","?"
"0x39","caps_lock", "0x39","caps_lock",,
"0x3a","F1", "0x3a","F1",,
"0x3b","F2", "0x3b","F2",,
"0x3c","F3", "0x3c","F3",,
"0x3d","F4", "0x3d","F4",,
"0x3e","F5", "0x3e","F5",,
"0x3f","F6", "0x3f","F6",,
"0x40","F7", "0x40","F7",,
"0x41","F8", "0x41","F8",,
"0x42","F9", "0x42","F9",,
"0x43","F10", "0x43","F10",,
"0x44","F11", "0x44","F11",,
"0x45","F12", "0x45","F12",,
"0x46","print_screen", "0x46","print_screen",,
"0x47","scroll_lock", "0x47","scroll_lock",,
"0x48","pause", "0x48","pause",,
"0x49","insert", "0x49","insert",,
"0x4a","home", "0x4a","home",,
"0x4b","page_up", "0x4b","page_up",,
"0x4c","_delete", "0x4c","_delete",,
"0x4d","end", "0x4d","end",,
"0x4e","page_down", "0x4e","page_down",,
"0x4f","right_arrow", "0x4f","right_arrow",,
"0x50","left_arrow", "0x50","left_arrow",,
"0x51","down_arrow", "0x51","down_arrow",,
"0x52","up_arrow", "0x52","up_arrow",,

1 code usage normal shift
2 0x00 no_operation
3 0x01 rollover_error
4 0x02 post_fail
5 0x03 undefined_error
6 0x04 a_A a A
7 0x05 b_B b B
8 0x06 c_C c C
9 0x07 d_D d D
10 0x08 e_E e E
11 0x09 f_F f F
12 0x0a g_G g G
13 0x0b h_H h H
14 0x0c i_I i I
15 0x0d j_J j J
16 0x0e k_K k K
17 0x0f l_L l L
18 0x10 m_M m M
19 0x11 n_N n N
20 0x12 o_O o O
21 0x13 p_P p P
22 0x14 q_Q q Q
23 0x15 r_R r R
24 0x16 s_S s S
25 0x17 t_T t T
26 0x18 u_U u U
27 0x19 v_V v V
28 0x1a w_W w W
29 0x1b x_X x X
30 0x1c y_Y y Y
31 0x1d z_Z z Z
32 0x1e _1_exclam 1 !
33 0x1f _2_at 2 @
34 0x20 _3_numbersign 3 #
35 0x21 _4_dollar 4 $
36 0x22 _5_percent 5 %
37 0x23 _6_asciicircum 6 ^
38 0x24 _7_ampersand 7 &
39 0x25 _8_asterisk 8 *
40 0x26 _9_parenleft 9 (
41 0x27 _0_parenright 0 )
42 0x28 _return
43 0x29 esc
44 0x2a backspace
45 0x2b tab
46 0x2c spacebar
47 0x2d minus_underscore - _
48 0x2e equal_plus underscore carot = +
49 0x2f bracketleft_braceleft at [ {
50 0x30 bracketright_braceright braceleft ] }
51 0x31 backslash_bar \ |
52 0x32 _unknown_ iso_numbersign_tilde # ~
53 0x33 semicolon_colon ; :
54 0x34 apostrophe_quotedbl ' "
55 0x35 grave_asciitilde ' ~
56 0x36 comma_less , <
57 0x37 period_greater . >
58 0x38 slash_question / ?
59 0x39 caps_lock
60 0x3a F1
61 0x3b F2
62 0x3c F3
63 0x3d F4
64 0x3e F5
65 0x3f F6
66 0x40 F7
67 0x41 F8
68 0x42 F9
69 0x43 F10
70 0x44 F11
71 0x45 F12
72 0x46 print_screen
73 0x47 scroll_lock
74 0x48 pause
75 0x49 insert
76 0x4a home
77 0x4b page_up
78 0x4c _delete
79 0x4d end
80 0x4e page_down
81 0x4f right_arrow
82 0x50 left_arrow
83 0x51 down_arrow
84 0x52 up_arrow

View File

@ -1,3 +1,5 @@
#pragma once
#include "string.hpp" #include "string.hpp"
namespace serial { namespace serial {

View File

@ -21,7 +21,7 @@ void keyboard_do_get_condition(uint32_t * command_buf,
}; };
const uint32_t command_size = maple::init_host_command_all_ports<command_type, response_type>(command_buf, receive_buf, data_fields); const uint32_t command_size = maple::init_host_command_all_ports<command_type, response_type>(command_buf, receive_buf, data_fields);
using host_response_type = struct maple::command_response<response_type::data_fields>; using host_response_type = struct maple::host_response<response_type::data_fields>;
auto host_response = reinterpret_cast<host_response_type *>(receive_buf); auto host_response = reinterpret_cast<host_response_type *>(receive_buf);
maple::dma_start(command_buf, command_size, maple::dma_start(command_buf, command_size,
@ -68,12 +68,21 @@ void keyboard_debug(ft6::data_transfer::data_format * keyboards, uint32_t frame_
} }
} }
static inline bool is_shifted(const uint8_t modifier_key)
{
return
(ft6::data_transfer::modifier_key::right_shift() & modifier_key) ||
(ft6::data_transfer::modifier_key::left_shift() & modifier_key);
}
void keyboard_update(ft6::data_transfer::data_format * keyboards, uint32_t frame_ix, gap_buffer& gb) void keyboard_update(ft6::data_transfer::data_format * keyboards, uint32_t frame_ix, gap_buffer& gb)
{ {
uint32_t this_frame = (frame_ix + 0) & 1; uint32_t this_frame = (frame_ix + 0) & 1;
uint32_t next_frame = (frame_ix + 1) & 1; uint32_t next_frame = (frame_ix + 1) & 1;
for (int i = 0; i < 6; i++) { for (int i = 0; i < 6; i++) {
if (i < 5 && keyboards[this_frame].scan_code_array[i + 1] != ft6::scan_codes::no_operation) if (keyboards[this_frame].scan_code_array[i] == ft6::scan_code::no_operation)
break;
if (i < 5 && keyboards[this_frame].scan_code_array[i + 1] != ft6::scan_code::no_operation)
continue; continue;
bool make = true; bool make = true;
for (int j = 0; j < 6; j++) { for (int j = 0; j < 6; j++) {
@ -85,61 +94,23 @@ void keyboard_update(ft6::data_transfer::data_format * keyboards, uint32_t frame
if (make) { if (make) {
// make // make
uint8_t scan_code = keyboards[this_frame].scan_code_array[i]; uint8_t scan_code = keyboards[this_frame].scan_code_array[i];
if (scan_code <= ft6::scan_code::last_printable) {
bool shifted = is_shifted(keyboards[this_frame].modifier_key);
char_type code_point = ft6::scan_code::code_point[scan_code][shifted];
if (code_point != 0) {
gap_append(gb, code_point);
continue;
}
}
switch (scan_code) { switch (scan_code) {
case ft6::scan_codes::a_A: [[fallthrough]]; case ft6::scan_code::_return: gap_append(gb, '\n'); break;
case ft6::scan_codes::b_B: [[fallthrough]]; case ft6::scan_code::backspace: gap_pop(gb); break;
case ft6::scan_codes::c_C: [[fallthrough]]; case ft6::scan_code::spacebar: gap_append(gb, ' '); break;
case ft6::scan_codes::d_D: [[fallthrough]];
case ft6::scan_codes::e_E: [[fallthrough]];
case ft6::scan_codes::f_F: [[fallthrough]];
case ft6::scan_codes::g_G: [[fallthrough]];
case ft6::scan_codes::h_H: [[fallthrough]];
case ft6::scan_codes::i_I: [[fallthrough]];
case ft6::scan_codes::j_J: [[fallthrough]];
case ft6::scan_codes::k_K: [[fallthrough]];
case ft6::scan_codes::l_L: [[fallthrough]];
case ft6::scan_codes::m_M: [[fallthrough]];
case ft6::scan_codes::n_N: [[fallthrough]];
case ft6::scan_codes::o_O: [[fallthrough]];
case ft6::scan_codes::p_P: [[fallthrough]];
case ft6::scan_codes::q_Q: [[fallthrough]];
case ft6::scan_codes::r_R: [[fallthrough]];
case ft6::scan_codes::s_S: [[fallthrough]];
case ft6::scan_codes::t_T: [[fallthrough]];
case ft6::scan_codes::u_U: [[fallthrough]];
case ft6::scan_codes::v_V: [[fallthrough]];
case ft6::scan_codes::w_W: [[fallthrough]];
case ft6::scan_codes::x_X: [[fallthrough]];
case ft6::scan_codes::y_Y: [[fallthrough]];
case ft6::scan_codes::z_Z:
{
char_type code_point = (scan_code - ft6::scan_codes::a_A) + 'a';
gap_append(gb, code_point);
}
break;
case ft6::scan_codes::_1_exclam: [[fallthrough]];
case ft6::scan_codes::_2_at: [[fallthrough]];
case ft6::scan_codes::_3_numbersign: [[fallthrough]];
case ft6::scan_codes::_4_dollar: [[fallthrough]];
case ft6::scan_codes::_5_percent: [[fallthrough]];
case ft6::scan_codes::_6_asciicircum: [[fallthrough]];
case ft6::scan_codes::_7_ampersand: [[fallthrough]];
case ft6::scan_codes::_8_asterisk: [[fallthrough]];
case ft6::scan_codes::_9_parenleft:
{
char_type code_point = (scan_code - ft6::scan_codes::_1_exclam) + '1';
gap_append(gb, code_point);
}
break;
case ft6::scan_codes::_0_parenright: gap_append(gb, '0'); break;
case ft6::scan_codes::_return: gap_append(gb, '\n'); break;
case ft6::scan_codes::backspace: gap_pop(gb); break;
case ft6::scan_codes::spacebar: gap_append(gb, ' '); break;
case ft6::scan_codes::left_arrow: gap_cursor_pos(gb, -1); break; case ft6::scan_code::left_arrow: gap_cursor_pos(gb, -1); break;
case ft6::scan_codes::right_arrow: gap_cursor_pos(gb, 1); break; case ft6::scan_code::right_arrow: gap_cursor_pos(gb, 1); break;
case ft6::scan_codes::up_arrow: gap_cursor_pos_line(gb, -1); break; case ft6::scan_code::up_arrow: gap_cursor_pos_line(gb, -1); break;
case ft6::scan_codes::down_arrow: gap_cursor_pos_line(gb, 1); break; case ft6::scan_code::down_arrow: gap_cursor_pos_line(gb, 1); break;
default: default:
break; break;
} }

View File

@ -80,13 +80,13 @@ void main()
constexpr uint32_t ta_alloc = ta_alloc_ctrl::pt_opb::no_list constexpr uint32_t ta_alloc = ta_alloc_ctrl::pt_opb::no_list
| ta_alloc_ctrl::tm_opb::no_list | ta_alloc_ctrl::tm_opb::no_list
//| ta_alloc_ctrl::t_opb::_16x4byte | ta_alloc_ctrl::t_opb::_16x4byte
| ta_alloc_ctrl::om_opb::no_list | ta_alloc_ctrl::om_opb::no_list
| ta_alloc_ctrl::o_opb::_16x4byte; | ta_alloc_ctrl::o_opb::_16x4byte;
constexpr struct opb_size opb_size = { .opaque = 16 * 4 constexpr struct opb_size opb_size = { .opaque = 16 * 4
, .opaque_modifier = 0 , .opaque_modifier = 0
//, .translucent = 16 * 4 , .translucent = 16 * 4
, .translucent_modifier = 0 , .translucent_modifier = 0
, .punch_through = 0 , .punch_through = 0
}; };