maple: write data to a VMU display

This draws a smiley-face bitmap to a VMU display on port 1.
This commit is contained in:
Zack Buhman 2023-12-11 18:07:05 +08:00
parent 25fef821b0
commit 855cbba403
7 changed files with 89 additions and 37 deletions

View File

@ -16,6 +16,7 @@ MAIN_OBJ = \
maple/maple.o \
scene.o \
macaw.data.o \
wink.data.o \
$(LIBGCC)
serial.elf: start.o serial_main.o load.o cache.o

View File

@ -1,5 +1,5 @@
LIB ?= .
OPT ?= -Os
OPT ?= -Og
DEBUG ?= -g -gdwarf-4
GENERATED ?=

View File

@ -95,33 +95,54 @@ void serial_int8(const uint8_t n)
serial_string("\n");
}
uint32_t _receive_address[(32 + 32) / 4] = {0};
uint32_t _command_buf[(32 + 32) / 4] = {0};
uint32_t _receive_address[(256 + 32) / 4] = {0};
uint32_t _command_buf[(256 + 32) / 4] = {0};
extern uint32_t _binary_wink_data_start __asm("_binary_wink_data_start");
void make_wink(uint32_t * buf)
{
const uint8_t * src = reinterpret_cast<const uint8_t *>(&_binary_wink_data_start);
uint8_t * dst = reinterpret_cast<uint8_t *>(buf);
uint32_t ix = 0;
dst[ix] = 0;
for (int i = 0; i < 48 * 32; i++) {
dst[ix] |= ((src[i] & 1) << (7 - (i % 8)));
if (i % 8 == 7) {
ix++;
dst[ix] = 0;
}
}
}
bool maple_test()
{
v_sync_out();
uint32_t * command_buf = align_32byte(_command_buf);
uint32_t * receive_address = align_32byte(_receive_address);
if ((((uint32_t)command_buf) & 31) != 0) serial_string("misaligned\n");
if ((((uint32_t)receive_address) & 31) != 0) serial_string("misaligned\n");
for (int i = 0; i < (32 / 4); i++) {
command_buf[i] = 0;
}
for (int i = 0; i < (32 / 4); i++) {
receive_address[i] = 0;
}
v_sync_out();
//maple_init_device_request(command_buf, receive_address);
maple_init_get_condition(command_buf, receive_address);
//maple_init_get_condition(command_buf, receive_address);
uint32_t wink_buf[192];
make_wink(wink_buf);
maple_init_block_write(command_buf, receive_address, wink_buf);
serial_int32(command_buf[0]);
serial_char('\n');
maple_dma_start(command_buf);
v_sync_in();
for (int i = 0; i < 32; i++) {
serial_int32(receive_address[i]);
}
/*
for (int i = 0; i < (4 + 4 + 8); i++) {
serial_int8(reinterpret_cast<volatile uint8_t *>(receive_address)[i]);
@ -149,7 +170,8 @@ void main()
vga();
v_sync_in();
maple_test();
//((void(*)(void))0xac010000)();
/*
volatile uint16_t * framebuffer = reinterpret_cast<volatile uint16_t *>(&texture_memory[0]);
@ -213,7 +235,7 @@ void main()
ta_wait_opaque_list();
core_start_render(frame);
a_pressed = maple_test();
//a_pressed = maple_test();
frame = !frame;
}

View File

@ -11,19 +11,6 @@
#include "maple_bus_commands.h"
#include "maple.h"
template <typename T>
struct maple_host_command {
uint32_t host_instruction;
uint32_t receive_data_storage_address;
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 maple_init_host_command(uint32_t * buf, uint32_t * receive_address, uint8_t command_code, uint8_t data_size)
{
// this function does not care about the template instantiation of
@ -31,13 +18,13 @@ void maple_init_host_command(uint32_t * buf, uint32_t * receive_address, uint8_t
auto host_command = reinterpret_cast<maple_host_command<uint32_t> *>(buf);
host_command->host_instruction = host_instruction::end_flag
| host_instruction::port_select::a
| host_instruction::transfer_length((data_size / 4));
| host_instruction::port_select::a
| host_instruction::transfer_length((data_size / 4));
host_command->receive_data_storage_address = reinterpret_cast<uint32_t>(receive_address) & 0x1fff'ffff;
host_command->bus_data.command_code = command_code;
host_command->bus_data.destination_ap = ap::de::device | ap::port_select::a;
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.data_size = data_size / 4;
}
@ -61,11 +48,39 @@ void maple_init_get_condition(uint32_t * buf, uint32_t * receive_address)
function_type[3] = 0x01;
}
void maple_init_block_write(uint32_t * buf, uint32_t * receive_address, uint32_t * data)
{
maple_init_host_command(buf, receive_address, block_write::command_code, (sizeof (struct block_write::data_fields<uint32_t[192 / 4]>)));
auto host_command = reinterpret_cast<maple_host_command<block_write::data_fields<uint32_t[192 / 4]>> *>(buf);
auto& fields = host_command->bus_data.data_fields;
// BW LCD function type
fields.function_type[0] = 0x00;
fields.function_type[1] = 0x00;
fields.function_type[2] = 0x00;
fields.function_type[3] = 0x04;
// lcd number 0 (1 total lcd)
fields.pt[0] = 0;
// phase 0 (from 0 to 3)
fields.phase[0] = 0;
// plane 0 (2 total levels of gradation)
fields.block_no[0] = 0x00;
fields.block_no[1] = 0x00;
for (uint32_t i = 0; i < (192 / 4); i++) {
fields.written_data[i] = data[i];
}
}
void maple_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 */
| 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;
@ -78,13 +93,13 @@ void maple_dma_start(uint32_t * command_buf)
// 20nsec * 0xc350 = 1ms
constexpr uint32_t one_msec = 0xc350;
maple_if.MSYS = msys::time_out_counter(one_msec)
| msys::sending_rate::_2M;
| msys::sending_rate::_2M;
/* 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);
| mdapro::top_address(0x00)
| mdapro::bottom_address(0x7f);
maple_if.MDTSEL = mdtsel::trigger_select::software_initiation;

View File

@ -2,7 +2,21 @@
#include <cstdint>
template <typename T>
struct maple_host_command {
uint32_t host_instruction;
uint32_t receive_data_storage_address;
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 maple_init_host_command(uint32_t * buf, uint32_t * receive_address);
void maple_init_device_request(uint32_t * buf, uint32_t * receive_address);
void maple_init_get_condition(uint32_t * buf, uint32_t * receive_address);
void maple_init_block_write(uint32_t * buf, uint32_t * receive_address, uint32_t * data);
void maple_dma_start(uint32_t * command_buf);

BIN
wink.data Normal file

Binary file not shown.

BIN
wink.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB