example: new maple "get_condition" demo
This is very barebones, and uses the serial interface to communicate the status of the "a" controller button being pressed. I'd like to make this a more interactive/graphical demo.
This commit is contained in:
parent
9bd79c6664
commit
39aa6b75a6
@ -54,6 +54,15 @@ CUBE_OBJ = \
|
||||
example/cube.elf: LDSCRIPT = $(LIB)/alt.lds
|
||||
example/cube.elf: $(START_OBJ) $(CUBE_OBJ)
|
||||
|
||||
MAPLE_DEVICE_REQUEST_OBJ = \
|
||||
example/maple_device_request.o \
|
||||
vga.o \
|
||||
serial.o \
|
||||
maple/maple.o
|
||||
|
||||
example/maple_device_request.elf: LDSCRIPT = $(LIB)/alt.lds
|
||||
example/maple_device_request.elf: $(START_OBJ) $(MAPLE_DEVICE_REQUEST_OBJ)
|
||||
|
||||
MAPLE_CONTROLLER_OBJ = \
|
||||
example/maple_controller.o \
|
||||
vga.o \
|
||||
|
@ -1,37 +1,116 @@
|
||||
#include <bit>
|
||||
|
||||
#include "vga.hpp"
|
||||
#include "align.hpp"
|
||||
|
||||
#include "maple/maple.hpp"
|
||||
#include "maple/maple_bus_bits.hpp"
|
||||
#include "maple/maple_bus_commands.hpp"
|
||||
#include "maple/maple_bus_ft0.hpp"
|
||||
#include "serial.hpp"
|
||||
|
||||
constexpr uint32_t command_data_size = (sizeof (device_request::data_fields));
|
||||
constexpr uint32_t response_data_size = (sizeof (device_status::data_fields));
|
||||
uint32_t _command_buf[1024 / 4 + 32] = {0};
|
||||
uint32_t _receive_buf[1024 / 4 + 32] = {0};
|
||||
|
||||
constexpr uint32_t host_command_size = (sizeof (struct maple::host_command<device_request::data_fields>));
|
||||
constexpr uint32_t command_response_size = align_32byte((sizeof (struct maple::command_response<device_status::data_fields>)));
|
||||
static uint32_t * command_buf;
|
||||
static uint32_t * receive_buf;
|
||||
|
||||
uint32_t _command_buf[host_command_size * 4 + 32] = {0};
|
||||
uint32_t _receive_buf[command_response_size * 4 + 32] = {0};
|
||||
struct port_state {
|
||||
bool controller_connected;
|
||||
};
|
||||
|
||||
static port_state state[4] = {0};
|
||||
|
||||
void do_get_condition(uint32_t port)
|
||||
{
|
||||
uint32_t destination_port;
|
||||
uint32_t destination_ap;
|
||||
|
||||
switch (port) {
|
||||
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;
|
||||
}
|
||||
|
||||
maple::init_get_condition(command_buf, receive_buf,
|
||||
destination_port,
|
||||
destination_ap,
|
||||
std::byteswap(function_type::controller));
|
||||
maple::dma_start(command_buf);
|
||||
|
||||
using response_type = struct maple::command_response<data_transfer::data_fields<struct ft0::data_transfer::data_format>>;
|
||||
auto response = reinterpret_cast<response_type *>(receive_buf);
|
||||
auto& bus_data = response->bus_data;
|
||||
auto& data_fields = response->bus_data.data_fields;
|
||||
if (bus_data.command_code != data_transfer::command_code) {
|
||||
return;
|
||||
}
|
||||
if ((data_fields.function_type & std::byteswap(function_type::controller)) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
state[port].controller_connected = 1;
|
||||
bool a = data_fields.data.digital_button & ft0::data_transfer::digital_button::a;
|
||||
if (a == 0) {
|
||||
serial::string("port ");
|
||||
serial::integer<uint8_t>(port);
|
||||
serial::string(" `a` press ");
|
||||
serial::integer<uint8_t>(a);
|
||||
}
|
||||
}
|
||||
|
||||
void do_device_request()
|
||||
{
|
||||
using response_type = struct maple::command_response<device_status::data_fields>;
|
||||
constexpr uint32_t response_size = align_32byte(sizeof (response_type));
|
||||
|
||||
maple::init_host_command_all_ports(command_buf, receive_buf,
|
||||
device_request::command_code,
|
||||
(sizeof (device_request::data_fields)), // command_data_size
|
||||
(sizeof (device_status::data_fields))); // response_data_size
|
||||
maple::dma_start(command_buf);
|
||||
|
||||
for (uint8_t port = 0; port < 4; port++) {
|
||||
auto response = reinterpret_cast<response_type *>(&receive_buf[response_size * port / 4]);
|
||||
|
||||
auto& bus_data = response->bus_data;
|
||||
auto& data_fields = response->bus_data.data_fields;
|
||||
if (bus_data.command_code != device_status::command_code) {
|
||||
// the controller is disconnected
|
||||
state[port].controller_connected = 0;
|
||||
} else {
|
||||
if ((data_fields.device_id.ft & std::byteswap(function_type::controller)) != 0) {
|
||||
//serial::string("is controller: ");
|
||||
//serial::integer<uint8_t>(port);
|
||||
do_get_condition(port);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
uint32_t * command_buf = align_32byte(_command_buf);
|
||||
uint32_t * receive_buf = align_32byte(_receive_buf);
|
||||
command_buf = align_32byte(_command_buf);
|
||||
receive_buf = align_32byte(_receive_buf);
|
||||
|
||||
maple::init_host_command_all_ports(command_buf, receive_buf,
|
||||
device_request::command_code, command_data_size, response_data_size);
|
||||
|
||||
maple::dma_start(command_buf);
|
||||
|
||||
uint8_t * buf = reinterpret_cast<uint8_t *>(receive_buf);
|
||||
for (uint8_t port = 0; port < 4; port++) {
|
||||
serial::string("port ");
|
||||
serial::integer<uint8_t>(port);
|
||||
for (uint32_t i = 0; i < command_response_size; i++) {
|
||||
serial::integer<uint8_t>(buf[port * command_response_size + i]);
|
||||
}
|
||||
serial::character('\n');
|
||||
}
|
||||
|
||||
while (1);
|
||||
while (1) {
|
||||
v_sync_out();
|
||||
v_sync_in();
|
||||
do_device_request();
|
||||
};
|
||||
}
|
||||
|
37
example/maple_device_request.cpp
Normal file
37
example/maple_device_request.cpp
Normal file
@ -0,0 +1,37 @@
|
||||
#include "align.hpp"
|
||||
|
||||
#include "maple/maple.hpp"
|
||||
#include "maple/maple_bus_commands.hpp"
|
||||
#include "serial.hpp"
|
||||
|
||||
constexpr uint32_t command_data_size = (sizeof (device_request::data_fields));
|
||||
constexpr uint32_t response_data_size = (sizeof (device_status::data_fields));
|
||||
|
||||
constexpr uint32_t host_command_size = (sizeof (struct maple::host_command<device_request::data_fields>));
|
||||
constexpr uint32_t command_response_size = align_32byte((sizeof (struct maple::command_response<device_status::data_fields>)));
|
||||
|
||||
uint32_t _command_buf[host_command_size * 4 + 32] = {0};
|
||||
uint32_t _receive_buf[command_response_size * 4 + 32] = {0};
|
||||
|
||||
void main()
|
||||
{
|
||||
uint32_t * command_buf = align_32byte(_command_buf);
|
||||
uint32_t * receive_buf = align_32byte(_receive_buf);
|
||||
|
||||
maple::init_host_command_all_ports(command_buf, receive_buf,
|
||||
device_request::command_code, command_data_size, response_data_size);
|
||||
|
||||
maple::dma_start(command_buf);
|
||||
|
||||
uint8_t * buf = reinterpret_cast<uint8_t *>(receive_buf);
|
||||
for (uint8_t port = 0; port < 4; port++) {
|
||||
serial::string("port ");
|
||||
serial::integer<uint8_t>(port);
|
||||
for (uint32_t i = 0; i < command_response_size; i++) {
|
||||
serial::integer<uint8_t>(buf[port * command_response_size + i]);
|
||||
}
|
||||
serial::character('\n');
|
||||
}
|
||||
|
||||
while (1);
|
||||
}
|
@ -76,7 +76,8 @@ void init_device_request(uint32_t * buf, uint32_t * receive_buf,
|
||||
|
||||
void init_get_condition(uint32_t * buf, uint32_t * receive_buf,
|
||||
uint32_t destination_port,
|
||||
uint8_t destination_ap)
|
||||
uint8_t destination_ap,
|
||||
uint32_t function_type)
|
||||
{
|
||||
init_host_command(buf, receive_buf,
|
||||
destination_port,
|
||||
@ -87,7 +88,7 @@ void init_get_condition(uint32_t * buf, uint32_t * receive_buf,
|
||||
|
||||
auto& fields = host_command->bus_data.data_fields;
|
||||
// controller function type
|
||||
fields.function_type = std::byteswap(function_type::controller);
|
||||
fields.function_type = function_type;
|
||||
}
|
||||
|
||||
void init_block_write(uint32_t * command_buf, uint32_t * receive_buf,
|
||||
|
@ -42,7 +42,8 @@ void init_device_request(uint32_t * buf, uint32_t * receive_buf,
|
||||
|
||||
void init_get_condition(uint32_t * buf, uint32_t * receive_buf,
|
||||
uint32_t destination_port,
|
||||
uint8_t destination_ap);
|
||||
uint8_t destination_ap,
|
||||
uint32_t function_type);
|
||||
|
||||
void init_block_write(uint32_t * buf, uint32_t * receive_buf,
|
||||
uint32_t destination_port,
|
||||
|
@ -1,5 +1,11 @@
|
||||
#include <cstdint>
|
||||
|
||||
struct device_id {
|
||||
uint32_t ft;
|
||||
uint32_t fd[3];
|
||||
};
|
||||
|
||||
static_assert((sizeof (struct device_id)) == 16);
|
||||
namespace device_request {
|
||||
constexpr uint32_t command_code = 0x1;
|
||||
|
||||
@ -32,7 +38,7 @@ namespace device_status {
|
||||
constexpr uint32_t command_code = 0x5;
|
||||
|
||||
struct data_fields {
|
||||
uint8_t device_id[16];
|
||||
struct device_id device_id;
|
||||
uint8_t destination_code;
|
||||
uint8_t connection_direction;
|
||||
uint8_t product_name[30];
|
||||
@ -49,7 +55,7 @@ namespace device_all_status {
|
||||
|
||||
template <typename T>
|
||||
struct data_fields {
|
||||
uint8_t device_id[16];
|
||||
struct device_id device_id;
|
||||
uint8_t destination_code;
|
||||
uint8_t connection_direction;
|
||||
uint8_t product_name[30];
|
||||
@ -229,3 +235,4 @@ namespace ar_error {
|
||||
|
||||
static_assert((sizeof (struct data_fields)) == 4);
|
||||
}
|
||||
|
||||
|
@ -37,6 +37,8 @@ def command_namespace(namespace: CommandNamespace,
|
||||
if const in {1, 2, 4}:
|
||||
bits = const * 8
|
||||
yield f"uint{bits}_t {field_name};"
|
||||
elif field_name == "device_id":
|
||||
yield f"struct device_id {field_name};"
|
||||
else:
|
||||
yield f"uint8_t {field_name}[{const}];"
|
||||
elif const == 0:
|
||||
@ -155,6 +157,11 @@ def new_aggregator():
|
||||
def headers():
|
||||
yield "#include <cstdint>"
|
||||
yield ""
|
||||
yield "struct device_id {"
|
||||
yield "uint32_t ft;"
|
||||
yield "uint32_t fd[3];"
|
||||
yield "};"
|
||||
yield "static_assert((sizeof (struct device_id)) == 16);"
|
||||
|
||||
input_file = sys.argv[1]
|
||||
rows = read_input(input_file)
|
||||
|
Loading…
x
Reference in New Issue
Block a user