example: add maple_controller

This broke maple_wink. I have not yet found why this happened.
This commit is contained in:
Zack Buhman 2023-12-15 17:13:53 +08:00
parent af07742575
commit 2689ad4011
11 changed files with 227 additions and 68 deletions

View File

@ -2,7 +2,7 @@ MAKEFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST)))
DIR := $(dir $(MAKEFILE_PATH))
LIB ?= .
OPT ?= -O0
OPT ?= -Os
DEBUG ?= -g -gdwarf-4
GENERATED ?=

View File

@ -54,6 +54,15 @@ CUBE_OBJ = \
example/cube.elf: LDSCRIPT = $(LIB)/alt.lds
example/cube.elf: $(START_OBJ) $(CUBE_OBJ)
MAPLE_CONTROLLER_OBJ = \
example/maple_controller.o \
vga.o \
serial.o \
maple/maple.o
example/maple_controller.elf: LDSCRIPT = $(LIB)/alt.lds
example/maple_controller.elf: $(START_OBJ) $(MAPLE_CONTROLLER_OBJ)
MAPLE_WINK_OBJ = \
example/maple_wink.o \
vga.o \

View 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 = ((sizeof (struct maple::command_response<device_status::data_fields>)) + 31) & ~31;
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);
}

View File

@ -1,6 +1,7 @@
#include <cstdint>
#include "maple/maple.hpp"
#include "maple/maple_bus_bits.hpp"
#include "vga.hpp"
#include "align.hpp"
#include "serial.hpp"
@ -30,18 +31,25 @@ void main()
constexpr int height = 32;
constexpr int pixels_per_byte = 8;
uint32_t wink_buf[width * height / pixels_per_byte];
uint32_t __attribute__((aligned(4))) wink_buf[(width * height / pixels_per_byte + 32) / 4];
make_wink(wink_buf);
if ((((uint32_t)wink_buf) & 3) != 0) serial::string("misaligned\n");
uint32_t _command_buf[128 / 4];
uint32_t _receive_buf[128 / 4];
uint32_t _command_buf[(1024 + 32) / 4];
uint32_t _receive_buf[(1024 + 32) / 4];
uint32_t * command_buf = align_32byte(_command_buf);
uint32_t * receive_buf = align_32byte(_receive_buf);
if ((((uint32_t)command_buf) & 31) != 0) serial::string("misaligned\n");
if ((((uint32_t)receive_buf) & 31) != 0) serial::string("misaligned\n");
maple::init_block_write(command_buf, receive_buf, wink_buf);
maple::init_block_write(command_buf, receive_buf,
host_instruction::port_select::a,
ap::de::expansion_device | ap::port_select::a | ap::lm_bus::_0,
wink_buf,
192);
maple::dma_start(command_buf);
for (int i = 0; i < 32; i++) {
for (int i = 0; i < 1; i++) {
serial::integer<uint32_t>(receive_buf[i]);
}

View File

@ -13,32 +13,73 @@
namespace maple {
void init_host_command(uint32_t * buf, uint32_t * receive_buf, uint8_t command_code, uint8_t data_size)
void init_host_command(uint32_t * command_buf, uint32_t * receive_buf,
uint32_t destination_port,
uint8_t destination_ap, uint8_t command_code, uint8_t data_size,
bool end_flag)
{
// this function does not care about the template instantiation of
// host_command--data_fields is not manipulated here.
auto host_command = reinterpret_cast<struct host_command<uint32_t> *>(buf);
auto host_command = reinterpret_cast<struct host_command<uint8_t[0]> *>(command_buf);
host_command->host_instruction = host_instruction::end_flag
| host_instruction::port_select::a
host_command->host_instruction = (end_flag ? host_instruction::end_flag : 0)
| (destination_port & host_instruction::port_select::bit_mask) // host_instruction::port_select::a
| host_instruction::transfer_length((data_size / 4));
host_command->receive_data_storage_address = reinterpret_cast<uint32_t>(receive_buf) & 0x1fff'ffff;
host_command->receive_data_storage_address = receive_data_storage_address::address(reinterpret_cast<uint32_t>(receive_buf));
host_command->bus_data.command_code = command_code;
host_command->bus_data.destination_ap = ap::de::expansion_device | ap::port_select::a | ap::lm_bus::_0;
host_command->bus_data.source_ap = ap::port_select::a;
host_command->bus_data.destination_ap = destination_ap; //ap::de::expansion_device | ap::port_select::a | ap::lm_bus::_0
host_command->bus_data.source_ap = destination_ap & ap::port_select::bit_mask;
host_command->bus_data.data_size = data_size / 4;
}
void init_device_request(uint32_t * buf, uint32_t * receive_buf)
void init_host_command_all_ports(uint32_t * buf, uint32_t * receive_buf,
uint8_t command_code, uint32_t command_data_size, uint32_t response_data_size)
{
init_host_command(buf, receive_buf, device_request::command_code, (sizeof (struct device_request::data_fields)));
const uint32_t command_size = (((sizeof (struct host_command<uint8_t[0]>)) + command_data_size));
const uint32_t response_size = (((sizeof (struct command_response<uint8_t[0]>)) + response_data_size) + 31) & ~31;
init_host_command(&buf[(command_size / 4) * 0], &receive_buf[(response_size / 4) * 0],
host_instruction::port_select::a, // destination_port
ap::de::device | ap::port_select::a, command_code, command_data_size,
false); // end_flag
init_host_command(&buf[(command_size / 4) * 1], &receive_buf[(response_size / 4) * 1],
host_instruction::port_select::b, // destination_port
ap::de::device | ap::port_select::b, command_code, command_data_size,
false); // end_flag
init_host_command(&buf[(command_size / 4) * 2], &receive_buf[(response_size / 4) * 2],
host_instruction::port_select::c, // destination_port
ap::de::device | ap::port_select::c, command_code, command_data_size,
false); // end_flag
init_host_command(&buf[(command_size / 4) * 3], &receive_buf[(response_size / 4) * 3],
host_instruction::port_select::d, // destination_port
ap::de::device | ap::port_select::d, command_code, command_data_size,
true); // end_flag
}
void init_get_condition(uint32_t * buf, uint32_t * receive_buf)
void init_device_request(uint32_t * buf, uint32_t * receive_buf,
uint32_t destination_port,
uint8_t destination_ap)
{
init_host_command(buf, receive_buf, get_condition::command_code, (sizeof (struct get_condition::data_fields)));
init_host_command(buf, receive_buf,
destination_port,
destination_ap, device_request::command_code, (sizeof (struct device_request::data_fields)),
true);
}
void init_get_condition(uint32_t * buf, uint32_t * receive_buf,
uint32_t destination_port,
uint8_t destination_ap)
{
init_host_command(buf, receive_buf,
destination_port,
destination_ap, get_condition::command_code, (sizeof (struct get_condition::data_fields)),
true);
auto host_command = reinterpret_cast<struct host_command<get_condition::data_fields> *>(buf);
@ -47,11 +88,18 @@ void init_get_condition(uint32_t * buf, uint32_t * receive_buf)
fields.function_type = std::byteswap(function_type::controller);
}
void init_block_write(uint32_t * buf, uint32_t * receive_buf, uint32_t * data)
void init_block_write(uint32_t * command_buf, uint32_t * receive_buf,
uint32_t destination_port,
uint8_t destination_ap,
uint32_t * data,
uint32_t data_size)
{
init_host_command(buf, receive_buf, block_write::command_code, (sizeof (struct block_write::data_fields<uint32_t[192 / 4]>)));
init_host_command(command_buf, receive_buf,
destination_port,
destination_ap, block_write::command_code, (sizeof (struct block_write::data_fields<uint8_t[0]>)) + data_size,
true);
auto host_command = reinterpret_cast<struct host_command<block_write::data_fields<uint32_t[192 / 4]>> *>(buf);
auto host_command = reinterpret_cast<struct host_command<block_write::data_fields<uint8_t[0]>> *>(command_buf);
auto& fields = host_command->bus_data.data_fields;
// BW LCD function type
@ -66,16 +114,16 @@ void init_block_write(uint32_t * buf, uint32_t * receive_buf, uint32_t * data)
// plane 0 (2 total levels of gradation)
fields.block_no = std::byteswap(0x0000);
for (uint32_t i = 0; i < (192 / 4); i++) {
for (uint32_t i = 0; i < (data_size / 4); i++) {
fields.written_data[i] = data[i];
}
}
void dma_start(uint32_t * command_buf)
{
sh7091.DMAC.DMAOR = DMAOR__DDT /* on-demand data transfer mode */
| DMAOR__PR__CH2_CH0_CH1_CH3 /* priority mode; CH2 > CH0 > CH1 > CH3 */
| DMAOR__DME; /* DMAC master enable */
sh7091.DMAC.DMAOR = DMAOR__DDT // on-demand data transfer mode
| DMAOR__PR__CH2_CH0_CH1_CH3 // priority mode; CH2 > CH0 > CH1 > CH3
| DMAOR__DME; // DMAC master enable
// clear maple-DMA end status
system.ISTNRM = ISTNRM__END_OF_DMA_MAPLE_DMA;
@ -90,8 +138,8 @@ void dma_start(uint32_t * command_buf)
maple_if.MSYS = msys::time_out_counter(one_msec)
| msys::sending_rate::_2M;
/* top address: the first/lowest address
bottom address: the last/highest address */
// top address: the first/lowest address
// bottom address: the last/highest address
maple_if.MDAPRO = mdapro::security_code
| mdapro::top_address(0x00)
| mdapro::bottom_address(0x7f);

View File

@ -17,11 +17,39 @@ struct host_command {
} bus_data;
};
void init_host_command(uint32_t * command_buf, uint32_t * receive_buf);
void init_device_request(uint32_t * command_buf, uint32_t * receive_buf);
void init_get_condition(uint32_t * command_buf, uint32_t * receive_buf);
void init_block_write(uint32_t * command_buf, uint32_t * receive_buf, uint32_t * data);
template <typename T>
struct command_response {
struct bus_data {
uint8_t command_code;
uint8_t destination_ap;
uint8_t source_ap;
uint8_t data_size;
T data_fields;
} bus_data;
};
void init_host_command(uint32_t * buf, uint32_t * receive_buf,
uint32_t destination_port,
uint8_t destination_ap, uint8_t command_code, uint8_t data_size,
bool end_flag);
void init_host_command_all_ports(uint32_t * buf, uint32_t * receive_buf,
uint8_t command_code, uint32_t command_data_size, uint32_t response_data_size);
void init_device_request(uint32_t * buf, uint32_t * receive_buf,
uint32_t destination_port,
uint8_t destination_ap);
void init_get_condition(uint32_t * buf, uint32_t * receive_buf,
uint32_t destination_port,
uint8_t destination_ap);
void init_block_write(uint32_t * buf, uint32_t * receive_buf,
uint32_t destination_port,
uint8_t destination_ap,
uint32_t * data,
uint32_t data_size);
void dma_start(uint32_t * command_buf);
}

View File

@ -10,6 +10,8 @@ namespace host_instruction {
constexpr uint32_t b = 1 << 16;
constexpr uint32_t c = 2 << 16;
constexpr uint32_t d = 3 << 16;
constexpr uint32_t bit_mask = 0x3 << 16;
}
namespace pattern {
@ -18,23 +20,33 @@ namespace host_instruction {
constexpr uint32_t reset = 0b011 << 8;
constexpr uint32_t return_from_light_gun_mode = 0b100 << 8;
constexpr uint32_t nop = 0b111 << 8;
constexpr uint32_t bit_mask = 0x7 << 8;
}
constexpr uint32_t transfer_length(uint32_t num) { return (num & 0xff) << 0; }
}
namespace receive_data_storage_address {
constexpr uint32_t address(uint32_t num) { return (num & 0x1fffffff) << 0; }
}
namespace ap {
namespace port_select {
constexpr uint32_t a = 0b00 << 6;
constexpr uint32_t b = 0b01 << 6;
constexpr uint32_t c = 0b10 << 6;
constexpr uint32_t d = 0b11 << 6;
constexpr uint32_t bit_mask = 0x3 << 6;
}
namespace de {
constexpr uint32_t device = 1 << 5;
constexpr uint32_t expansion_device = 0 << 5;
constexpr uint32_t port = 0 << 5;
constexpr uint32_t bit_mask = 0x1 << 5;
}
namespace lm_bus {
@ -43,6 +55,8 @@ namespace ap {
constexpr uint32_t _2 = 0b00100 << 0;
constexpr uint32_t _1 = 0b00010 << 0;
constexpr uint32_t _0 = 0b00001 << 0;
constexpr uint32_t bit_mask = 0x1f << 0;
}
}

View File

@ -128,6 +128,8 @@ namespace block_write {
};
static_assert((sizeof (struct data_fields<char[0]>)) == 8);
static_assert((offsetof (struct data_fields<char[0]>, written_data)) == 8);
static_assert((offsetof (struct data_fields<char[192 / 4]>, written_data)) == 8);
}
namespace get_last_error {
@ -229,4 +231,3 @@ namespace ar_error {
static_assert((sizeof (struct data_fields)) == 4);
}

View File

@ -175,10 +175,22 @@ def render_defs(bit_def):
else:
yield from render_read_only(bit_def)
def render_enum_mask(enum_def):
all_bits = set(bit_def["bits"] for bit_def in enum_def.defs)
assert len(all_bits) == 1
assert all(bit_def["bit_name"] != "bit_mask" for bit_def in enum_def.defs), bit_def
_bits = next(iter(all_bits))
bits = parse_bit_range(_bits)
mask_value = mask_from_bits(bits)
bit_ix = min(bits)
yield ""
yield f"constexpr uint32_t bit_mask = {hex(mask_value)} << {bit_ix};"
def render_enum(enum_def):
yield f"namespace {enum_def.name.lower()} {{"
for bit_def in enum_def.defs:
yield from render_defs(bit_def)
yield from render_enum_mask(enum_def)
yield "}"
def render_register(register):

View File

@ -14,6 +14,8 @@
,,,,,,
"host_instruction",,"7-0","transfer_length",,"0xff",
,,,,,,
"receive_data_storage_address",,"31-0","address",,"0x1fff_ffff",
,,,,,,
"ap","port_select","7-6","a","0b00",,
"ap","port_select","7-6","b","0b01",,
"ap","port_select","7-6","c","0b10",,

1 register_name enum_name bits bit_name value mask description
14
15 host_instruction 7-0 transfer_length 0xff
16
17 receive_data_storage_address 31-0 address 0x1fff_ffff
18
19 ap port_select 7-6 a 0b00
20 ap port_select 7-6 b 0b01
21 ap port_select 7-6 c 0b10

Binary file not shown.