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:
parent
25fef821b0
commit
855cbba403
1
Makefile
1
Makefile
@ -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
|
||||
|
@ -1,5 +1,5 @@
|
||||
LIB ?= .
|
||||
OPT ?= -Os
|
||||
OPT ?= -Og
|
||||
DEBUG ?= -g -gdwarf-4
|
||||
GENERATED ?=
|
||||
|
||||
|
52
main.cpp
52
main.cpp
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user