ftdi_transfer: add command line parsing

This commit is contained in:
Zack Buhman 2024-11-01 13:09:27 -05:00
parent a3794d8718
commit 8027c591e8
11 changed files with 1113 additions and 610 deletions

15
burn.sh
View File

@ -1,2 +1,13 @@
cdrecord -speed=8 -v dev=/dev/sr0 -dao -multi taudio01.wav #!/bin/sh
cdrecord -eject -overburn -speed=8 -v dev=/dev/sr0 -tao -xa tdata02.iso
filename="$1"
if [ -z "$filename" ]; then
echo "usage: ./$0 [filename]"
exit 1
fi
set -ex
cdrecord -speed=8 -v dev=/dev/sr0 -dao -multi track1.wav
cdrecord -eject -overburn -speed=8 -v dev=/dev/sr0 -tao -xa "$filename"

View File

@ -66,10 +66,7 @@ sine.pcm: common.mk
synth 100s sin 700 vol -10dB synth 100s sin 700 vol -10dB
mv $@.raw $@ mv $@.raw $@
%.scramble: %.bin %.iso: %.bin ip.bin
./scramble $< $@
%.iso: %.scramble ip.bin
mkisofs \ mkisofs \
-C 0,11702 \ -C 0,11702 \
-sysid "SEGA SEGAKATANA" \ -sysid "SEGA SEGAKATANA" \
@ -95,9 +92,6 @@ sine.pcm: common.mk
/=./pcm/ELEC.PCM \ /=./pcm/ELEC.PCM \
/=./pcm/ECCLESIA.PCM /=./pcm/ECCLESIA.PCM
%.cdi: %.iso
./cdi4dc $< $@ >/dev/null
include headers.mk include headers.mk
clean: clean:

View File

@ -5,499 +5,624 @@
#include "../float_uint32.hpp" #include "../float_uint32.hpp"
namespace id { namespace id {
constexpr uint32_t device_id(uint32_t reg) { return (reg >> 16) & 0xffff; } constexpr uint32_t device_id(uint32_t reg) { return (reg >> 16) & 0xffff; }
constexpr uint32_t vendor_id(uint32_t reg) { return (reg >> 0) & 0xffff; } constexpr uint32_t vendor_id(uint32_t reg) { return (reg >> 0) & 0xffff; }
} }
namespace revision { namespace revision {
constexpr uint32_t chip_revision(uint32_t reg) { return (reg >> 0) & 0xffff; } constexpr uint32_t chip_revision(uint32_t reg) { return (reg >> 0) & 0xffff; }
} }
namespace softreset { namespace softreset {
constexpr uint32_t sdram_if_soft_reset = 1 << 2; constexpr uint32_t sdram_if_soft_reset = 1 << 2;
constexpr uint32_t pipeline_soft_reset = 1 << 1;
constexpr uint32_t ta_soft_reset = 1 << 0; constexpr uint32_t pipeline_soft_reset = 1 << 1;
constexpr uint32_t ta_soft_reset = 1 << 0;
} }
namespace startrender { namespace startrender {
constexpr uint32_t start_render = 1 << 0; constexpr uint32_t start_render = 1 << 0;
} }
namespace test_select { namespace test_select {
constexpr uint32_t diagdb_data(uint32_t reg) { return (reg >> 5) & 0x1f; } constexpr uint32_t diagdb_data(uint32_t reg) { return (reg >> 5) & 0x1f; }
constexpr uint32_t diagda_data(uint32_t reg) { return (reg >> 0) & 0x1f; } constexpr uint32_t diagda_data(uint32_t reg) { return (reg >> 0) & 0x1f; }
} }
namespace param_base { namespace param_base {
constexpr uint32_t base_address(uint32_t num) { return (num & 0xf00000) << 0; } constexpr uint32_t base_address(uint32_t num) { return (num & 0xf00000) << 0; }
} }
namespace region_base { namespace region_base {
constexpr uint32_t base_address(uint32_t num) { return (num & 0xfffffc) << 0; } constexpr uint32_t base_address(uint32_t num) { return (num & 0xfffffc) << 0; }
} }
namespace span_sort_cfg { namespace span_sort_cfg {
constexpr uint32_t cache_bypass = 1 << 16; constexpr uint32_t cache_bypass = 1 << 16;
constexpr uint32_t offset_sort_enable = 1 << 8;
constexpr uint32_t span_sort_enable = 1 << 0; constexpr uint32_t offset_sort_enable = 1 << 8;
constexpr uint32_t span_sort_enable = 1 << 0;
} }
namespace vo_border_col { namespace vo_border_col {
constexpr uint32_t chroma(uint32_t num) { return (num & 0x1) << 24; } constexpr uint32_t chroma(uint32_t num) { return (num & 0x1) << 24; }
constexpr uint32_t red(uint32_t num) { return (num & 0xff) << 16; } constexpr uint32_t red(uint32_t num) { return (num & 0xff) << 16; }
constexpr uint32_t green(uint32_t num) { return (num & 0xff) << 8; } constexpr uint32_t green(uint32_t num) { return (num & 0xff) << 8; }
constexpr uint32_t blue(uint32_t num) { return (num & 0xff) << 0; } constexpr uint32_t blue(uint32_t num) { return (num & 0xff) << 0; }
} }
namespace fb_r_ctrl { namespace fb_r_ctrl {
namespace vclk_div { namespace vclk_div {
constexpr uint32_t pclk_vclk_2 = 0 << 23; constexpr uint32_t pclk_vclk_2 = 0 << 23;
constexpr uint32_t pclk_vclk_1 = 1 << 23;
constexpr uint32_t bit_mask = 0x1 << 23; constexpr uint32_t pclk_vclk_1 = 1 << 23;
}
constexpr uint32_t fb_strip_buf_en = 1 << 22;
constexpr uint32_t fb_stripsize(uint32_t num) { return (num & 0x3e) << 16; }
constexpr uint32_t fb_chroma_threshold(uint32_t num) { return (num & 0xff) << 8; }
constexpr uint32_t fb_concat(uint32_t num) { return (num & 0x3) << 4; }
namespace fb_depth { constexpr uint32_t bit_mask = 0x1 << 23;
constexpr uint32_t _0555_rgb_16bit = 0 << 2;
constexpr uint32_t _0565_rgb_16bit = 1 << 2;
constexpr uint32_t _888_rgb_24bit_packed = 2 << 2;
constexpr uint32_t _0888_rgb_32bit = 3 << 2;
constexpr uint32_t bit_mask = 0x3 << 2; }
}
constexpr uint32_t fb_strip_buf_en = 1 << 22;
constexpr uint32_t fb_stripsize(uint32_t num) { return (num & 0x3e) << 16; }
constexpr uint32_t fb_chroma_threshold(uint32_t num) { return (num & 0xff) << 8; }
constexpr uint32_t fb_concat(uint32_t num) { return (num & 0x3) << 4; }
namespace fb_depth {
constexpr uint32_t _0555_rgb_16bit = 0 << 2;
constexpr uint32_t _0565_rgb_16bit = 1 << 2;
constexpr uint32_t _888_rgb_24bit_packed = 2 << 2;
constexpr uint32_t _0888_rgb_32bit = 3 << 2;
constexpr uint32_t bit_mask = 0x3 << 2;
}
constexpr uint32_t fb_line_double = 1 << 1;
constexpr uint32_t fb_enable = 1 << 0;
constexpr uint32_t fb_line_double = 1 << 1;
constexpr uint32_t fb_enable = 1 << 0;
} }
namespace fb_w_ctrl { namespace fb_w_ctrl {
constexpr uint32_t fb_alpha_threshold(uint32_t num) { return (num & 0xff) << 16; } constexpr uint32_t fb_alpha_threshold(uint32_t num) { return (num & 0xff) << 16; }
constexpr uint32_t fb_kval(uint32_t num) { return (num & 0xff) << 8; } constexpr uint32_t fb_kval(uint32_t num) { return (num & 0xff) << 8; }
constexpr uint32_t fb_dither = 1 << 3; constexpr uint32_t fb_dither = 1 << 3;
namespace fb_packmode {
constexpr uint32_t _0555_krgb_16bit = 0 << 0;
constexpr uint32_t _565_rgb_16bit = 1 << 0;
constexpr uint32_t _4444_argb_16bit = 2 << 0;
constexpr uint32_t _1555_argb_16bit = 3 << 0;
constexpr uint32_t _888_rgb_24bit_packed = 4 << 0;
constexpr uint32_t _0888_krgb_32bit = 5 << 0;
constexpr uint32_t _8888_argb_32bit = 6 << 0;
constexpr uint32_t bit_mask = 0x7 << 0; namespace fb_packmode {
} constexpr uint32_t _0555_krgb_16bit = 0 << 0;
constexpr uint32_t _565_rgb_16bit = 1 << 0;
constexpr uint32_t _4444_argb_16bit = 2 << 0;
constexpr uint32_t _1555_argb_16bit = 3 << 0;
constexpr uint32_t _888_rgb_24bit_packed = 4 << 0;
constexpr uint32_t _0888_krgb_32bit = 5 << 0;
constexpr uint32_t _8888_argb_32bit = 6 << 0;
constexpr uint32_t bit_mask = 0x7 << 0;
}
} }
namespace fb_w_linestride { namespace fb_w_linestride {
constexpr uint32_t fb_line_stride(uint32_t num) { return (num & 0xff) << 0; } constexpr uint32_t fb_line_stride(uint32_t num) { return (num & 0xff) << 0; }
} }
namespace fb_r_sof1 { namespace fb_r_sof1 {
constexpr uint32_t frame_buffer_read_address_frame_1(uint32_t num) { return (num & 0xfffffc) << 0; } constexpr uint32_t frame_buffer_read_address_frame_1(uint32_t num) { return (num & 0xfffffc) << 0; }
} }
namespace fb_r_sof2 { namespace fb_r_sof2 {
constexpr uint32_t frame_buffer_read_address_frame_2(uint32_t num) { return (num & 0xfffffc) << 0; } constexpr uint32_t frame_buffer_read_address_frame_2(uint32_t num) { return (num & 0xfffffc) << 0; }
} }
namespace fb_r_size { namespace fb_r_size {
constexpr uint32_t fb_modulus(uint32_t num) { return (num & 0x3ff) << 20; } constexpr uint32_t fb_modulus(uint32_t num) { return (num & 0x3ff) << 20; }
constexpr uint32_t fb_y_size(uint32_t num) { return (num & 0x3ff) << 10; } constexpr uint32_t fb_y_size(uint32_t num) { return (num & 0x3ff) << 10; }
constexpr uint32_t fb_x_size(uint32_t num) { return (num & 0x3ff) << 0; } constexpr uint32_t fb_x_size(uint32_t num) { return (num & 0x3ff) << 0; }
} }
namespace fb_w_sof1 { namespace fb_w_sof1 {
constexpr uint32_t frame_buffer_write_address_frame_1(uint32_t num) { return (num & 0x1fffffc) << 0; } constexpr uint32_t frame_buffer_write_address_frame_1(uint32_t num) { return (num & 0x1fffffc) << 0; }
} }
namespace fb_w_sof2 { namespace fb_w_sof2 {
constexpr uint32_t frame_buffer_write_address_frame_2(uint32_t num) { return (num & 0x1fffffc) << 0; } constexpr uint32_t frame_buffer_write_address_frame_2(uint32_t num) { return (num & 0x1fffffc) << 0; }
} }
namespace fb_x_clip { namespace fb_x_clip {
constexpr uint32_t fb_x_clip_max(uint32_t num) { return (num & 0x7ff) << 16; } constexpr uint32_t fb_x_clip_max(uint32_t num) { return (num & 0x7ff) << 16; }
constexpr uint32_t fb_x_clip_min(uint32_t num) { return (num & 0x7ff) << 0; } constexpr uint32_t fb_x_clip_min(uint32_t num) { return (num & 0x7ff) << 0; }
} }
namespace fb_y_clip { namespace fb_y_clip {
constexpr uint32_t fb_y_clip_max(uint32_t num) { return (num & 0x3ff) << 16; } constexpr uint32_t fb_y_clip_max(uint32_t num) { return (num & 0x3ff) << 16; }
constexpr uint32_t fb_y_clip_min(uint32_t num) { return (num & 0x3ff) << 0; } constexpr uint32_t fb_y_clip_min(uint32_t num) { return (num & 0x3ff) << 0; }
} }
namespace fpu_shad_scale { namespace fpu_shad_scale {
namespace simple_shadow_enable { namespace simple_shadow_enable {
constexpr uint32_t parameter_selection_volume_mode = 0 << 8; constexpr uint32_t parameter_selection_volume_mode = 0 << 8;
constexpr uint32_t intensity_volume_mode = 1 << 8;
constexpr uint32_t bit_mask = 0x1 << 8; constexpr uint32_t intensity_volume_mode = 1 << 8;
}
constexpr uint32_t scale_factor_for_shadows(uint32_t num) { return (num & 0xff) << 0; }
constexpr uint32_t bit_mask = 0x1 << 8;
}
constexpr uint32_t scale_factor_for_shadows(uint32_t num) { return (num & 0xff) << 0; }
} }
namespace fpu_cull_val { namespace fpu_cull_val {
inline uint32_t culling_comparison_value(float num) { return _i(__builtin_fabsf(num));; } inline uint32_t culling_comparison_value(float num) { return _i(__builtin_fabsf(num));; }
} }
namespace fpu_param_cfg { namespace fpu_param_cfg {
namespace region_header_type { namespace region_header_type {
constexpr uint32_t type_1 = 0 << 21; constexpr uint32_t type_1 = 0 << 21;
constexpr uint32_t type_2 = 1 << 21;
constexpr uint32_t bit_mask = 0x1 << 21; constexpr uint32_t type_2 = 1 << 21;
}
constexpr uint32_t tsp_parameter_burst_threshold(uint32_t num) { return (num & 0x3f) << 14; }
constexpr uint32_t isp_parameter_burst_threshold(uint32_t num) { return (num & 0x3f) << 8; } constexpr uint32_t bit_mask = 0x1 << 21;
constexpr uint32_t pointer_burst_size(uint32_t num) { return (num & 0xf) << 4; }
constexpr uint32_t pointer_first_burst_size(uint32_t num) { return (num & 0xf) << 0; } }
constexpr uint32_t tsp_parameter_burst_threshold(uint32_t num) { return (num & 0x3f) << 14; }
constexpr uint32_t isp_parameter_burst_threshold(uint32_t num) { return (num & 0x3f) << 8; }
constexpr uint32_t pointer_burst_size(uint32_t num) { return (num & 0xf) << 4; }
constexpr uint32_t pointer_first_burst_size(uint32_t num) { return (num & 0xf) << 0; }
} }
namespace half_offset { namespace half_offset {
namespace tsp_texel_sampling_position { namespace tsp_texel_sampling_position {
constexpr uint32_t top_left = 1 << 2; constexpr uint32_t top_left = 1 << 2;
constexpr uint32_t center = 1 << 2;
constexpr uint32_t bit_mask = 0x1 << 2; constexpr uint32_t center = 1 << 2;
}
namespace tsp_pixel_sampling_position {
constexpr uint32_t top_left = 1 << 1;
constexpr uint32_t center = 1 << 1;
constexpr uint32_t bit_mask = 0x1 << 1; constexpr uint32_t bit_mask = 0x1 << 2;
}
namespace fpu_pixel_sampling_position { }
constexpr uint32_t top_left = 1 << 0;
constexpr uint32_t center = 1 << 0;
constexpr uint32_t bit_mask = 0x1 << 0; namespace tsp_pixel_sampling_position {
} constexpr uint32_t top_left = 1 << 1;
constexpr uint32_t center = 1 << 1;
constexpr uint32_t bit_mask = 0x1 << 1;
}
namespace fpu_pixel_sampling_position {
constexpr uint32_t top_left = 1 << 0;
constexpr uint32_t center = 1 << 0;
constexpr uint32_t bit_mask = 0x1 << 0;
}
} }
namespace fpu_perp_val { namespace fpu_perp_val {
inline uint32_t perpendicular_triangle_compare(float num) { return _i(__builtin_fabsf(num));; } inline uint32_t perpendicular_triangle_compare(float num) { return _i(__builtin_fabsf(num));; }
} }
namespace isp_backgnd_d { namespace isp_backgnd_d {
inline uint32_t background_plane_depth(float num) { return _i(num) & 0xfffffff0; } inline uint32_t background_plane_depth(float num) { return _i(num) & 0xfffffff0; }
} }
namespace isp_backgnd_t { namespace isp_backgnd_t {
constexpr uint32_t cache_bypass = 1 << 28; constexpr uint32_t cache_bypass = 1 << 28;
constexpr uint32_t shadow = 1 << 27;
constexpr uint32_t skip(uint32_t num) { return (num & 0x7) << 24; } constexpr uint32_t shadow = 1 << 27;
constexpr uint32_t tag_address(uint32_t num) { return (num & 0x1fffff) << 3; }
constexpr uint32_t tag_offset(uint32_t num) { return (num & 0x7) << 0; } constexpr uint32_t skip(uint32_t num) { return (num & 0x7) << 24; }
constexpr uint32_t tag_address(uint32_t num) { return (num & 0x1fffff) << 3; }
constexpr uint32_t tag_offset(uint32_t num) { return (num & 0x7) << 0; }
} }
namespace isp_feed_cfg { namespace isp_feed_cfg {
constexpr uint32_t cache_size_for_translucency(uint32_t num) { return (num & 0x3ff) << 14; } constexpr uint32_t cache_size_for_translucency(uint32_t num) { return (num & 0x3ff) << 14; }
constexpr uint32_t punch_through_chunk_size(uint32_t num) { return (num & 0x3ff) << 4; } constexpr uint32_t punch_through_chunk_size(uint32_t num) { return (num & 0x3ff) << 4; }
constexpr uint32_t discard_mode = 1 << 3; constexpr uint32_t discard_mode = 1 << 3;
constexpr uint32_t pre_sort_mode = 1 << 0;
constexpr uint32_t pre_sort_mode = 1 << 0;
} }
namespace sdram_refresh { namespace sdram_refresh {
constexpr uint32_t refresh_counter_value(uint32_t num) { return (num & 0xff) << 0; } constexpr uint32_t refresh_counter_value(uint32_t num) { return (num & 0xff) << 0; }
} }
namespace sdram_arb_cfg { namespace sdram_arb_cfg {
namespace override_value { namespace override_value {
constexpr uint32_t priority_only = 0x0 << 18; constexpr uint32_t priority_only = 0x0 << 18;
constexpr uint32_t rendered_data = 0x1 << 18;
constexpr uint32_t texture_vq_index = 0x2 << 18;
constexpr uint32_t texture_normal_data_and_vq_codebook = 0x3 << 18;
constexpr uint32_t tile_accelerator_isp_tsp_data = 0x4 << 18;
constexpr uint32_t tile_accelerator_pointers = 0x5 << 18;
constexpr uint32_t sh4 = 0x6 << 18;
constexpr uint32_t tsp_parameters = 0x7 << 18;
constexpr uint32_t tsp_region_data = 0x8 << 18;
constexpr uint32_t isp_pointer_data = 0x9 << 18;
constexpr uint32_t isp_parameters = 0xa << 18;
constexpr uint32_t crt_controller = 0xb << 18;
constexpr uint32_t bit_mask = 0xf << 18; constexpr uint32_t rendered_data = 0x1 << 18;
}
namespace arbiter_priority_control { constexpr uint32_t texture_vq_index = 0x2 << 18;
constexpr uint32_t priority_arbitration_only = 0x0 << 16;
constexpr uint32_t override_value_field = 0x1 << 16;
constexpr uint32_t round_robin_counter = 0x2 << 16;
constexpr uint32_t bit_mask = 0x3 << 16; constexpr uint32_t texture_normal_data_and_vq_codebook = 0x3 << 18;
}
constexpr uint32_t arbiter_crt_page_break_latency_count_value(uint32_t num) { return (num & 0xff) << 8; } constexpr uint32_t tile_accelerator_isp_tsp_data = 0x4 << 18;
constexpr uint32_t arbiter_page_break_latency_count_value(uint32_t num) { return (num & 0xff) << 0; }
constexpr uint32_t tile_accelerator_pointers = 0x5 << 18;
constexpr uint32_t sh4 = 0x6 << 18;
constexpr uint32_t tsp_parameters = 0x7 << 18;
constexpr uint32_t tsp_region_data = 0x8 << 18;
constexpr uint32_t isp_pointer_data = 0x9 << 18;
constexpr uint32_t isp_parameters = 0xa << 18;
constexpr uint32_t crt_controller = 0xb << 18;
constexpr uint32_t bit_mask = 0xf << 18;
}
namespace arbiter_priority_control {
constexpr uint32_t priority_arbitration_only = 0x0 << 16;
constexpr uint32_t override_value_field = 0x1 << 16;
constexpr uint32_t round_robin_counter = 0x2 << 16;
constexpr uint32_t bit_mask = 0x3 << 16;
}
constexpr uint32_t arbiter_crt_page_break_latency_count_value(uint32_t num) { return (num & 0xff) << 8; }
constexpr uint32_t arbiter_page_break_latency_count_value(uint32_t num) { return (num & 0xff) << 0; }
} }
namespace sdram_cfg { namespace sdram_cfg {
constexpr uint32_t read_command_to_returned_data_delay(uint32_t num) { return (num & 0x7) << 26; } constexpr uint32_t read_command_to_returned_data_delay(uint32_t num) { return (num & 0x7) << 26; }
constexpr uint32_t cas_latency_value(uint32_t num) { return (num & 0x7) << 23; } constexpr uint32_t cas_latency_value(uint32_t num) { return (num & 0x7) << 23; }
constexpr uint32_t activate_to_activate_period(uint32_t num) { return (num & 0x3) << 21; } constexpr uint32_t activate_to_activate_period(uint32_t num) { return (num & 0x3) << 21; }
constexpr uint32_t read_to_write_period(uint32_t num) { return (num & 0x7) << 18; } constexpr uint32_t read_to_write_period(uint32_t num) { return (num & 0x7) << 18; }
constexpr uint32_t refresh_to_activate_period(uint32_t num) { return (num & 0xf) << 14; } constexpr uint32_t refresh_to_activate_period(uint32_t num) { return (num & 0xf) << 14; }
constexpr uint32_t pre_charge_to_activate_period(uint32_t num) { return (num & 0x3) << 10; } constexpr uint32_t pre_charge_to_activate_period(uint32_t num) { return (num & 0x3) << 10; }
constexpr uint32_t activate_to_pre_charge_period(uint32_t num) { return (num & 0xf) << 6; } constexpr uint32_t activate_to_pre_charge_period(uint32_t num) { return (num & 0xf) << 6; }
constexpr uint32_t activate_to_read_write_command_period(uint32_t num) { return (num & 0x3) << 4; } constexpr uint32_t activate_to_read_write_command_period(uint32_t num) { return (num & 0x3) << 4; }
constexpr uint32_t write_to_pre_charge_period(uint32_t num) { return (num & 0x3) << 2; } constexpr uint32_t write_to_pre_charge_period(uint32_t num) { return (num & 0x3) << 2; }
constexpr uint32_t read_to_pre_charge_period(uint32_t num) { return (num & 0x3) << 0; } constexpr uint32_t read_to_pre_charge_period(uint32_t num) { return (num & 0x3) << 0; }
} }
namespace fog_col_ram { namespace fog_col_ram {
constexpr uint32_t red(uint32_t num) { return (num & 0xff) << 16; } constexpr uint32_t red(uint32_t num) { return (num & 0xff) << 16; }
constexpr uint32_t green(uint32_t num) { return (num & 0xff) << 8; } constexpr uint32_t green(uint32_t num) { return (num & 0xff) << 8; }
constexpr uint32_t blue(uint32_t num) { return (num & 0xff) << 0; } constexpr uint32_t blue(uint32_t num) { return (num & 0xff) << 0; }
} }
namespace fog_col_vert { namespace fog_col_vert {
constexpr uint32_t red(uint32_t num) { return (num & 0xff) << 16; } constexpr uint32_t red(uint32_t num) { return (num & 0xff) << 16; }
constexpr uint32_t green(uint32_t num) { return (num & 0xff) << 8; } constexpr uint32_t green(uint32_t num) { return (num & 0xff) << 8; }
constexpr uint32_t blue(uint32_t num) { return (num & 0xff) << 0; } constexpr uint32_t blue(uint32_t num) { return (num & 0xff) << 0; }
} }
namespace fog_density { namespace fog_density {
constexpr uint32_t fog_scale_mantissa(uint32_t num) { return (num & 0xff) << 8; } constexpr uint32_t fog_scale_mantissa(uint32_t num) { return (num & 0xff) << 8; }
constexpr uint32_t fog_scale_exponent(uint32_t num) { return (num & 0xff) << 0; } constexpr uint32_t fog_scale_exponent(uint32_t num) { return (num & 0xff) << 0; }
} }
namespace fog_clamp_max { namespace fog_clamp_max {
constexpr uint32_t alpha(uint32_t num) { return (num & 0xff) << 24; } constexpr uint32_t alpha(uint32_t num) { return (num & 0xff) << 24; }
constexpr uint32_t red(uint32_t num) { return (num & 0xff) << 16; } constexpr uint32_t red(uint32_t num) { return (num & 0xff) << 16; }
constexpr uint32_t green(uint32_t num) { return (num & 0xff) << 8; } constexpr uint32_t green(uint32_t num) { return (num & 0xff) << 8; }
constexpr uint32_t blue(uint32_t num) { return (num & 0xff) << 0; } constexpr uint32_t blue(uint32_t num) { return (num & 0xff) << 0; }
} }
namespace fog_clamp_min { namespace fog_clamp_min {
constexpr uint32_t alpha(uint32_t num) { return (num & 0xff) << 24; } constexpr uint32_t alpha(uint32_t num) { return (num & 0xff) << 24; }
constexpr uint32_t red(uint32_t num) { return (num & 0xff) << 16; } constexpr uint32_t red(uint32_t num) { return (num & 0xff) << 16; }
constexpr uint32_t green(uint32_t num) { return (num & 0xff) << 8; } constexpr uint32_t green(uint32_t num) { return (num & 0xff) << 8; }
constexpr uint32_t blue(uint32_t num) { return (num & 0xff) << 0; } constexpr uint32_t blue(uint32_t num) { return (num & 0xff) << 0; }
} }
namespace spg_trigger_pos { namespace spg_trigger_pos {
constexpr uint32_t trigger_v_count(uint32_t reg) { return (reg >> 16) & 0x3ff; } constexpr uint32_t trigger_v_count(uint32_t reg) { return (reg >> 16) & 0x3ff; }
constexpr uint32_t trigger_h_count(uint32_t reg) { return (reg >> 0) & 0x3ff; } constexpr uint32_t trigger_h_count(uint32_t reg) { return (reg >> 0) & 0x3ff; }
} }
namespace spg_hblank_int { namespace spg_hblank_int {
constexpr uint32_t hblank_in_interrupt(uint32_t reg) { return (reg >> 16) & 0x3ff; } constexpr uint32_t hblank_in_interrupt(uint32_t reg) { return (reg >> 16) & 0x3ff; }
namespace hblank_int_mode { namespace hblank_int_mode {
constexpr uint32_t output_equal_line_comp_val = 0x0 << 12; constexpr uint32_t output_equal_line_comp_val = 0x0 << 12;
constexpr uint32_t output_every_line_comp_val = 0x1 << 12;
constexpr uint32_t output_every_line = 0x2 << 12;
constexpr uint32_t bit_mask = 0x3 << 12; constexpr uint32_t output_every_line_comp_val = 0x1 << 12;
}
constexpr uint32_t line_comp_val(uint32_t num) { return (num & 0x3ff) << 0; } constexpr uint32_t output_every_line = 0x2 << 12;
constexpr uint32_t bit_mask = 0x3 << 12;
}
constexpr uint32_t line_comp_val(uint32_t num) { return (num & 0x3ff) << 0; }
} }
namespace spg_vblank_int { namespace spg_vblank_int {
constexpr uint32_t vblank_out_interrupt_line_number(uint32_t num) { return (num & 0x3ff) << 16; } constexpr uint32_t vblank_out_interrupt_line_number(uint32_t num) { return (num & 0x3ff) << 16; }
constexpr uint32_t vblank_in_interrupt_line_number(uint32_t num) { return (num & 0x3ff) << 0; } constexpr uint32_t vblank_in_interrupt_line_number(uint32_t num) { return (num & 0x3ff) << 0; }
} }
namespace spg_control { namespace spg_control {
namespace csync_on_h { namespace csync_on_h {
constexpr uint32_t hsync = 0 << 9; constexpr uint32_t hsync = 0 << 9;
constexpr uint32_t csync = 1 << 9;
constexpr uint32_t bit_mask = 0x1 << 9; constexpr uint32_t csync = 1 << 9;
}
namespace sync_direction {
constexpr uint32_t input = 0 << 8;
constexpr uint32_t output = 1 << 8;
constexpr uint32_t bit_mask = 0x1 << 8; constexpr uint32_t bit_mask = 0x1 << 9;
}
constexpr uint32_t pal = 1 << 7; }
constexpr uint32_t ntsc = 1 << 6;
constexpr uint32_t force_field2 = 1 << 5;
constexpr uint32_t interlace = 1 << 4;
constexpr uint32_t spg_lock = 1 << 3;
namespace mcsync_pol { namespace sync_direction {
constexpr uint32_t active_low = 0 << 2; constexpr uint32_t input = 0 << 8;
constexpr uint32_t active_high = 1 << 2;
constexpr uint32_t bit_mask = 0x1 << 2; constexpr uint32_t output = 1 << 8;
}
namespace mvsync_pol {
constexpr uint32_t active_low = 0 << 1;
constexpr uint32_t active_high = 1 << 1;
constexpr uint32_t bit_mask = 0x1 << 1; constexpr uint32_t bit_mask = 0x1 << 8;
}
namespace mhsync_pol { }
constexpr uint32_t active_low = 0 << 0;
constexpr uint32_t active_high = 1 << 0;
constexpr uint32_t bit_mask = 0x1 << 0; constexpr uint32_t pal = 1 << 7;
}
constexpr uint32_t ntsc = 1 << 6;
constexpr uint32_t force_field2 = 1 << 5;
constexpr uint32_t interlace = 1 << 4;
constexpr uint32_t spg_lock = 1 << 3;
namespace mcsync_pol {
constexpr uint32_t active_low = 0 << 2;
constexpr uint32_t active_high = 1 << 2;
constexpr uint32_t bit_mask = 0x1 << 2;
}
namespace mvsync_pol {
constexpr uint32_t active_low = 0 << 1;
constexpr uint32_t active_high = 1 << 1;
constexpr uint32_t bit_mask = 0x1 << 1;
}
namespace mhsync_pol {
constexpr uint32_t active_low = 0 << 0;
constexpr uint32_t active_high = 1 << 0;
constexpr uint32_t bit_mask = 0x1 << 0;
}
} }
namespace spg_hblank { namespace spg_hblank {
constexpr uint32_t hbend(uint32_t num) { return (num & 0x3ff) << 16; } constexpr uint32_t hbend(uint32_t num) { return (num & 0x3ff) << 16; }
constexpr uint32_t hbstart(uint32_t num) { return (num & 0x3ff) << 0; } constexpr uint32_t hbstart(uint32_t num) { return (num & 0x3ff) << 0; }
} }
namespace spg_load { namespace spg_load {
constexpr uint32_t vcount(uint32_t num) { return (num & 0x3ff) << 16; } constexpr uint32_t vcount(uint32_t num) { return (num & 0x3ff) << 16; }
constexpr uint32_t hcount(uint32_t num) { return (num & 0x3ff) << 0; } constexpr uint32_t hcount(uint32_t num) { return (num & 0x3ff) << 0; }
} }
namespace spg_vblank { namespace spg_vblank {
constexpr uint32_t vbend(uint32_t num) { return (num & 0x3ff) << 16; } constexpr uint32_t vbend(uint32_t num) { return (num & 0x3ff) << 16; }
constexpr uint32_t vbstart(uint32_t num) { return (num & 0x3ff) << 0; } constexpr uint32_t vbstart(uint32_t num) { return (num & 0x3ff) << 0; }
} }
namespace spg_width { namespace spg_width {
constexpr uint32_t eqwidth(uint32_t num) { return (num & 0x3ff) << 22; } constexpr uint32_t eqwidth(uint32_t num) { return (num & 0x3ff) << 22; }
constexpr uint32_t bpwidth(uint32_t num) { return (num & 0x3ff) << 12; } constexpr uint32_t bpwidth(uint32_t num) { return (num & 0x3ff) << 12; }
constexpr uint32_t vswidth(uint32_t num) { return (num & 0xf) << 8; } constexpr uint32_t vswidth(uint32_t num) { return (num & 0xf) << 8; }
constexpr uint32_t hswidth(uint32_t num) { return (num & 0x7f) << 0; } constexpr uint32_t hswidth(uint32_t num) { return (num & 0x7f) << 0; }
} }
namespace text_control { namespace text_control {
namespace code_book_endian { namespace code_book_endian {
constexpr uint32_t little_endian = 0 << 17; constexpr uint32_t little_endian = 0 << 17;
constexpr uint32_t big_endian = 1 << 17;
constexpr uint32_t bit_mask = 0x1 << 17; constexpr uint32_t big_endian = 1 << 17;
}
namespace index_endian {
constexpr uint32_t little_endian = 0 << 16;
constexpr uint32_t big_endian = 1 << 16;
constexpr uint32_t bit_mask = 0x1 << 16; constexpr uint32_t bit_mask = 0x1 << 17;
}
constexpr uint32_t bank_bit(uint32_t num) { return (num & 0x1f) << 8; } }
constexpr uint32_t stride(uint32_t num) { return (num & 0x1f) << 0; }
namespace index_endian {
constexpr uint32_t little_endian = 0 << 16;
constexpr uint32_t big_endian = 1 << 16;
constexpr uint32_t bit_mask = 0x1 << 16;
}
constexpr uint32_t bank_bit(uint32_t num) { return (num & 0x1f) << 8; }
constexpr uint32_t stride(uint32_t num) { return (num & 0x1f) << 0; }
} }
namespace vo_control { namespace vo_control {
constexpr uint32_t pclk_delay_reset = 1 << 21; constexpr uint32_t pclk_delay_reset = 1 << 21;
constexpr uint32_t pclk_delay(uint32_t num) { return (num & 0x1f) << 16; }
constexpr uint32_t pixel_double = 1 << 8;
namespace field_mode { constexpr uint32_t pclk_delay(uint32_t num) { return (num & 0x1f) << 16; }
constexpr uint32_t use_field_flag_from_spg = 0x0 << 4; constexpr uint32_t pixel_double = 1 << 8;
constexpr uint32_t use_inverse_of_field_flag_from_spg = 0x1 << 4;
constexpr uint32_t field_1_fixed = 0x2 << 4;
constexpr uint32_t field_2_fixed = 0x3 << 4;
constexpr uint32_t field_1_when_the_active_edges_of_hsync_and_vsync_match = 0x4 << 4;
constexpr uint32_t field_2_when_the_active_edges_of_hsync_and_vsync_match = 0x5 << 4;
constexpr uint32_t field_1_when_hsync_becomes_active_in_the_middle_of_the_vsync_active_edge = 0x6 << 4;
constexpr uint32_t field_2_when_hsync_becomes_active_in_the_middle_of_the_vsync_active_edge = 0x7 << 4;
constexpr uint32_t inverted_at_the_active_edge_of_vsync = 0x8 << 4;
constexpr uint32_t bit_mask = 0xf << 4;
}
constexpr uint32_t blank_video = 1 << 3; namespace field_mode {
constexpr uint32_t use_field_flag_from_spg = 0x0 << 4;
namespace blank_pol { constexpr uint32_t use_inverse_of_field_flag_from_spg = 0x1 << 4;
constexpr uint32_t active_low = 0 << 2;
constexpr uint32_t active_high = 1 << 2;
constexpr uint32_t bit_mask = 0x1 << 2; constexpr uint32_t field_1_fixed = 0x2 << 4;
}
namespace vsync_pol { constexpr uint32_t field_2_fixed = 0x3 << 4;
constexpr uint32_t active_low = 0 << 1;
constexpr uint32_t active_high = 1 << 1;
constexpr uint32_t bit_mask = 0x1 << 1; constexpr uint32_t field_1_when_the_active_edges_of_hsync_and_vsync_match = 0x4 << 4;
}
namespace hsync_pol { constexpr uint32_t field_2_when_the_active_edges_of_hsync_and_vsync_match = 0x5 << 4;
constexpr uint32_t active_low = 0 << 0;
constexpr uint32_t active_high = 1 << 0;
constexpr uint32_t bit_mask = 0x1 << 0; constexpr uint32_t field_1_when_hsync_becomes_active_in_the_middle_of_the_vsync_active_edge = 0x6 << 4;
}
constexpr uint32_t field_2_when_hsync_becomes_active_in_the_middle_of_the_vsync_active_edge = 0x7 << 4;
constexpr uint32_t inverted_at_the_active_edge_of_vsync = 0x8 << 4;
constexpr uint32_t bit_mask = 0xf << 4;
}
constexpr uint32_t blank_video = 1 << 3;
namespace blank_pol {
constexpr uint32_t active_low = 0 << 2;
constexpr uint32_t active_high = 1 << 2;
constexpr uint32_t bit_mask = 0x1 << 2;
}
namespace vsync_pol {
constexpr uint32_t active_low = 0 << 1;
constexpr uint32_t active_high = 1 << 1;
constexpr uint32_t bit_mask = 0x1 << 1;
}
namespace hsync_pol {
constexpr uint32_t active_low = 0 << 0;
constexpr uint32_t active_high = 1 << 0;
constexpr uint32_t bit_mask = 0x1 << 0;
}
} }
namespace vo_startx { namespace vo_startx {
constexpr uint32_t horizontal_start_position(uint32_t num) { return (num & 0x3ff) << 0; } constexpr uint32_t horizontal_start_position(uint32_t num) { return (num & 0x3ff) << 0; }
} }
namespace vo_starty { namespace vo_starty {
constexpr uint32_t vertical_start_position_on_field_2(uint32_t num) { return (num & 0x3ff) << 16; } constexpr uint32_t vertical_start_position_on_field_2(uint32_t num) { return (num & 0x3ff) << 16; }
constexpr uint32_t vertical_start_position_on_field_1(uint32_t num) { return (num & 0x3ff) << 0; } constexpr uint32_t vertical_start_position_on_field_1(uint32_t num) { return (num & 0x3ff) << 0; }
} }
namespace scaler_ctl { namespace scaler_ctl {
namespace field_select { namespace field_select {
constexpr uint32_t field_1 = 0 << 18; constexpr uint32_t field_1 = 0 << 18;
constexpr uint32_t field_2 = 1 << 18;
constexpr uint32_t bit_mask = 0x1 << 18; constexpr uint32_t field_2 = 1 << 18;
}
constexpr uint32_t interlace = 1 << 17;
constexpr uint32_t horizontal_scaling_enable = 1 << 16; constexpr uint32_t bit_mask = 0x1 << 18;
constexpr uint32_t vertical_scale_factor(uint32_t num) { return (num & 0xffff) << 0; }
}
constexpr uint32_t interlace = 1 << 17;
constexpr uint32_t horizontal_scaling_enable = 1 << 16;
constexpr uint32_t vertical_scale_factor(uint32_t num) { return (num & 0xffff) << 0; }
} }
namespace pal_ram_ctrl { namespace pal_ram_ctrl {
namespace pixel_format { namespace pixel_format {
constexpr uint32_t argb1555 = 0 << 0; constexpr uint32_t argb1555 = 0 << 0;
constexpr uint32_t rgb565 = 1 << 0;
constexpr uint32_t argb4444 = 2 << 0;
constexpr uint32_t argb8888 = 3 << 0;
constexpr uint32_t bit_mask = 0x3 << 0; constexpr uint32_t rgb565 = 1 << 0;
}
constexpr uint32_t argb4444 = 2 << 0;
constexpr uint32_t argb8888 = 3 << 0;
constexpr uint32_t bit_mask = 0x3 << 0;
}
} }
namespace spg_status { namespace spg_status {
constexpr uint32_t vsync(uint32_t reg) { return (reg >> 13) & 0x1; } constexpr uint32_t vsync(uint32_t reg) { return (reg >> 13) & 0x1; }
constexpr uint32_t hsync(uint32_t reg) { return (reg >> 12) & 0x1; } constexpr uint32_t hsync(uint32_t reg) { return (reg >> 12) & 0x1; }
constexpr uint32_t blank(uint32_t reg) { return (reg >> 11) & 0x1; } constexpr uint32_t blank(uint32_t reg) { return (reg >> 11) & 0x1; }
constexpr uint32_t fieldnum(uint32_t reg) { return (reg >> 10) & 0x1; } constexpr uint32_t fieldnum(uint32_t reg) { return (reg >> 10) & 0x1; }
constexpr uint32_t scanline(uint32_t reg) { return (reg >> 0) & 0x3ff; } constexpr uint32_t scanline(uint32_t reg) { return (reg >> 0) & 0x3ff; }
} }
namespace fb_burstctrl { namespace fb_burstctrl {
constexpr uint32_t wr_burst(uint32_t num) { return (num & 0xf) << 16; } constexpr uint32_t wr_burst(uint32_t num) { return (num & 0xf) << 16; }
constexpr uint32_t vid_lat(uint32_t num) { return (num & 0x7f) << 8; } constexpr uint32_t vid_lat(uint32_t num) { return (num & 0x7f) << 8; }
constexpr uint32_t vid_burst(uint32_t num) { return (num & 0x3f) << 0; } constexpr uint32_t vid_burst(uint32_t num) { return (num & 0x3f) << 0; }
} }
namespace fb_c_sof { namespace fb_c_sof {
constexpr uint32_t frame_buffer_current_read_address(uint32_t reg) { return (reg >> 0) & 0xffffff; } constexpr uint32_t frame_buffer_current_read_address(uint32_t reg) { return (reg >> 0) & 0xffffff; }
} }
namespace y_coeff { namespace y_coeff {
constexpr uint32_t coefficient_1(uint32_t num) { return (num & 0xff) << 8; } constexpr uint32_t coefficient_1(uint32_t num) { return (num & 0xff) << 8; }
constexpr uint32_t coefficient_0_2(uint32_t num) { return (num & 0xff) << 0; } constexpr uint32_t coefficient_0_2(uint32_t num) { return (num & 0xff) << 0; }
} }
namespace pt_alpha_ref { namespace pt_alpha_ref {
constexpr uint32_t alpha_reference_for_punch_through(uint32_t num) { return (num & 0xff) << 0; } constexpr uint32_t alpha_reference_for_punch_through(uint32_t num) { return (num & 0xff) << 0; }
} }
namespace fog_table { namespace fog_table {
constexpr uint32_t fog_table_data(uint32_t num) { return (num & 0xffff) << 0; } constexpr uint32_t fog_table_data(uint32_t num) { return (num & 0xffff) << 0; }
} }
namespace palette_ram { namespace palette_ram {
constexpr uint32_t palette_data(uint32_t num) { return (num & 0xffffffff) << 0; } constexpr uint32_t palette_data(uint32_t num) { return (num & 0xffffffff) << 0; }
} }

View File

@ -1,5 +1,5 @@
namespace video_output { namespace video_output {
const struct mode vga = { const struct mode vga = {
.fb_r_ctrl = fb_r_ctrl::vclk_div::pclk_vclk_1 .fb_r_ctrl = fb_r_ctrl::vclk_div::pclk_vclk_1
, ,
.spg_load = spg_load::vcount(0x20c) .spg_load = spg_load::vcount(0x20c)
@ -30,8 +30,9 @@ namespace video_output {
.spg_vblank_int = spg_vblank_int::vblank_out_interrupt_line_number(0x015) .spg_vblank_int = spg_vblank_int::vblank_out_interrupt_line_number(0x015)
| spg_vblank_int::vblank_in_interrupt_line_number(0x208) | spg_vblank_int::vblank_in_interrupt_line_number(0x208)
, ,
}; };
const struct mode ntsc_ni = {
const struct mode ntsc_ni = {
.fb_r_ctrl = fb_r_ctrl::vclk_div::pclk_vclk_2 .fb_r_ctrl = fb_r_ctrl::vclk_div::pclk_vclk_2
, ,
.spg_load = spg_load::vcount(0x106) .spg_load = spg_load::vcount(0x106)
@ -64,8 +65,9 @@ namespace video_output {
.spg_vblank_int = spg_vblank_int::vblank_out_interrupt_line_number(0x015) .spg_vblank_int = spg_vblank_int::vblank_out_interrupt_line_number(0x015)
| spg_vblank_int::vblank_in_interrupt_line_number(0x102) | spg_vblank_int::vblank_in_interrupt_line_number(0x102)
, ,
}; };
const struct mode ntsc_i = {
const struct mode ntsc_i = {
.fb_r_ctrl = fb_r_ctrl::vclk_div::pclk_vclk_2 .fb_r_ctrl = fb_r_ctrl::vclk_div::pclk_vclk_2
, ,
.spg_load = spg_load::vcount(0x20c) .spg_load = spg_load::vcount(0x20c)
@ -99,8 +101,9 @@ namespace video_output {
.spg_vblank_int = spg_vblank_int::vblank_out_interrupt_line_number(0x015) .spg_vblank_int = spg_vblank_int::vblank_out_interrupt_line_number(0x015)
| spg_vblank_int::vblank_in_interrupt_line_number(0x102) | spg_vblank_int::vblank_in_interrupt_line_number(0x102)
, ,
}; };
const struct mode pal_ni = {
const struct mode pal_ni = {
.fb_r_ctrl = fb_r_ctrl::vclk_div::pclk_vclk_2 .fb_r_ctrl = fb_r_ctrl::vclk_div::pclk_vclk_2
, ,
.spg_load = spg_load::vcount(0x138) .spg_load = spg_load::vcount(0x138)
@ -133,8 +136,9 @@ namespace video_output {
.spg_vblank_int = spg_vblank_int::vblank_out_interrupt_line_number(0x015) .spg_vblank_int = spg_vblank_int::vblank_out_interrupt_line_number(0x015)
| spg_vblank_int::vblank_in_interrupt_line_number(0x134) | spg_vblank_int::vblank_in_interrupt_line_number(0x134)
, ,
}; };
const struct mode pal_i = {
const struct mode pal_i = {
.fb_r_ctrl = fb_r_ctrl::vclk_div::pclk_vclk_2 .fb_r_ctrl = fb_r_ctrl::vclk_div::pclk_vclk_2
, ,
.spg_load = spg_load::vcount(0x270) .spg_load = spg_load::vcount(0x270)
@ -168,5 +172,6 @@ namespace video_output {
.spg_vblank_int = spg_vblank_int::vblank_out_interrupt_line_number(0x015) .spg_vblank_int = spg_vblank_int::vblank_out_interrupt_line_number(0x015)
| spg_vblank_int::vblank_in_interrupt_line_number(0x134) | spg_vblank_int::vblank_in_interrupt_line_number(0x134)
, ,
}; };
} }

View File

@ -3,75 +3,114 @@
#include <cstdint> #include <cstdint>
namespace host_instruction { namespace host_instruction {
constexpr uint32_t end_flag = 1 << 31; constexpr uint32_t end_flag = 1 << 31;
namespace port_select {
constexpr uint32_t a = 0 << 16;
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 port_select {
} constexpr uint32_t a = 0 << 16;
namespace pattern { constexpr uint32_t b = 1 << 16;
constexpr uint32_t normal = 0b000 << 8;
constexpr uint32_t light_gun_mode = 0b010 << 8;
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 c = 2 << 16;
}
constexpr uint32_t transfer_length(uint32_t num) { return (num & 0xff) << 0; } constexpr uint32_t d = 3 << 16;
constexpr uint32_t bit_mask = 0x3 << 16;
}
namespace pattern {
constexpr uint32_t normal = 0b000 << 8;
constexpr uint32_t light_gun_mode = 0b010 << 8;
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 { namespace receive_data_storage_address {
constexpr uint32_t address(uint32_t num) { return (num & 0x1fffffff) << 0; } constexpr uint32_t address(uint32_t num) { return (num & 0x1fffffff) << 0; }
} }
namespace ap { namespace ap {
namespace port_select { namespace port_select {
constexpr uint32_t a = 0b00 << 6; 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; constexpr uint32_t b = 0b01 << 6;
}
namespace de { constexpr uint32_t c = 0b10 << 6;
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; constexpr uint32_t d = 0b11 << 6;
}
namespace lm_bus {
constexpr uint32_t _4 = 0b10000 << 0;
constexpr uint32_t _3 = 0b01000 << 0;
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; 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 {
constexpr uint32_t _4 = 0b10000 << 0;
constexpr uint32_t _3 = 0b01000 << 0;
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;
}
} }
namespace function_type { namespace function_type {
constexpr uint32_t camera = 1 << 11; constexpr uint32_t camera = 1 << 11;
constexpr uint32_t exchange_media = 1 << 10;
constexpr uint32_t pointing = 1 << 9; constexpr uint32_t exchange_media = 1 << 10;
constexpr uint32_t vibration = 1 << 8;
constexpr uint32_t light_gun = 1 << 7; constexpr uint32_t pointing = 1 << 9;
constexpr uint32_t keyboard = 1 << 6;
constexpr uint32_t ar_gun = 1 << 5; constexpr uint32_t vibration = 1 << 8;
constexpr uint32_t audio_input = 1 << 4;
constexpr uint32_t timer = 1 << 3; constexpr uint32_t light_gun = 1 << 7;
constexpr uint32_t bw_lcd = 1 << 2;
constexpr uint32_t storage = 1 << 1; constexpr uint32_t keyboard = 1 << 6;
constexpr uint32_t controller = 1 << 0;
constexpr uint32_t ar_gun = 1 << 5;
constexpr uint32_t audio_input = 1 << 4;
constexpr uint32_t timer = 1 << 3;
constexpr uint32_t bw_lcd = 1 << 2;
constexpr uint32_t storage = 1 << 1;
constexpr uint32_t controller = 1 << 0;
} }

View File

@ -98,12 +98,7 @@ void recv(uint8_t c)
if (state.buf.cmd == command::read) prestart_read(); if (state.buf.cmd == command::read) prestart_read();
return; return;
} else { } else {
/* // do nothing
union command_reply reply = crc_error_reply(crc);
serial::string(reply.u8, 16);
state.len = 0;
return;
*/
} }
} }
} }
@ -181,8 +176,8 @@ void tick()
// cautiously re-initialize serial; it is possible the called // cautiously re-initialize serial; it is possible the called
// function modified serial state // function modified serial state
serial::init(state.speed);
sh7091.DMAC.CHCR1 = 0; sh7091.DMAC.CHCR1 = 0;
serial::init(state.speed);
// transition to next state // transition to next state
state.fsm_state = fsm_state::idle; state.fsm_state = fsm_state::idle;
@ -190,6 +185,12 @@ void tick()
break; break;
case fsm_state::speed: case fsm_state::speed:
{ {
using namespace scif;
// wait for serial transmission to end
constexpr uint32_t transmission_end = scfsr2::tend::bit_mask | scfsr2::tdfe::bit_mask;
if ((sh7091.SCIF.SCFSR2 & transmission_end) != transmission_end)
return;
const uint32_t speed = state.buf.arg[0]; const uint32_t speed = state.buf.arg[0];
state.speed = speed & 0xff; state.speed = speed & 0xff;
serial::init(state.speed); serial::init(state.speed);

View File

@ -9,7 +9,7 @@
namespace serial { namespace serial {
static inline void init_wait() void init_wait()
{ {
sh7091.TMU.TSTR &= (~tmu::tstr::str1::counter_start) & 0xff; // stop TCNT1 sh7091.TMU.TSTR &= (~tmu::tstr::str1::counter_start) & 0xff; // stop TCNT1
sh7091.TMU.TOCR = tmu::tocr::tcoe::tclk_is_external_clock_or_input_capture; sh7091.TMU.TOCR = tmu::tocr::tcoe::tclk_is_external_clock_or_input_capture;

View File

@ -4,6 +4,8 @@
namespace serial { namespace serial {
void init_wait();
void reset_txrx(); void reset_txrx();
void init(uint8_t bit_rate); void init(uint8_t bit_rate);

View File

@ -1,3 +1,4 @@
#include <inttypes.h>
#include <assert.h> #include <assert.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
@ -5,6 +6,8 @@
#include <stdbool.h> #include <stdbool.h>
#include <time.h> #include <time.h>
#include <string.h> #include <string.h>
#include <math.h>
#include <errno.h>
#include <ftdi.h> #include <ftdi.h>
#include <libusb.h> #include <libusb.h>
@ -12,53 +15,66 @@
#include "crc32.h" #include "crc32.h"
#include "serial_protocol.hpp" #include "serial_protocol.hpp"
extern int convert_baudrate_UT_export(int baudrate, struct ftdi_context *ftdi, extern "C" int convert_baudrate_UT_export(int baudrate, struct ftdi_context *ftdi,
unsigned short *value, unsigned short *index); unsigned short *value, unsigned short *index);
int dreamcast_rates[] = { double dreamcast_rate(int cks, int scbrr)
1562500, // 0 {
781250, // 1 assert(cks >= 0 && cks <= 3);
520833, // 2 assert(scbrr >= 0 && scbrr <= 255);
390625, // 3
312500, // 4
260416, // 5
223214, // 6
195312, // 7
173611, // 8
156250, // 9
142045, // 10
130208, // 11
120192 // 12
};
int init_ftdi_context(struct ftdi_context * ftdi) double div = 1.0;
for (; cks > 0; cks--) { div *= 4; };
return 1562500.0 / (div * ((double)scbrr + 1.0));
}
int init_ftdi_context(struct ftdi_context * ftdi, uint32_t scbrr)
{ {
ftdi_set_interface(ftdi, INTERFACE_ANY); ftdi_set_interface(ftdi, INTERFACE_ANY);
struct ftdi_device_list * devlist; struct ftdi_device_list * devlist;
int res; int num_devices;
if ((res = ftdi_usb_find_all(ftdi, &devlist, 0, 0)) < 0) { num_devices = ftdi_usb_find_all(ftdi, &devlist, 0, 0);
fprintf(stderr, "ftdi_usb_find_all\n"); if (num_devices < 0) {
fprintf(stderr, "ftdi_usb_find_all: %d\n", num_devices);
return -1; return -1;
} } else if (num_devices == 0) {
fprintf(stderr, "ftdi_usb_find_all: zero matching devices\n");
if (res == 0) {
fprintf(stderr, "no device\n");
return -1; return -1;
} }
struct libusb_device_descriptor desc; struct libusb_device_descriptor desc;
struct ftdi_device_list * devlist_item = devlist; struct ftdi_device_list * devlist_item = devlist;
for (int i = 0; i < res; i++) { struct libusb_device * dev = devlist_item->dev;
int res;
for (int i = 0; i < num_devices; i++) {
res = libusb_get_device_descriptor(devlist_item->dev, &desc); res = libusb_get_device_descriptor(devlist_item->dev, &desc);
if (res < 0) { if (res < 0) {
fprintf(stderr, "libusb_get_device_descriptor\n"); fprintf(stderr, "libusb_get_device_descriptor: %d\n", res);
return -1; return -1;
} }
fprintf(stdout, "idVendor: %04x; idProduct: %04x;\n", desc.idVendor, desc.idProduct); fprintf(stderr, "[%d]\n", i);
fprintf(stdout, "bNumConfigurations: %d;\n", desc.bNumConfigurations); fprintf(stderr, " idVendor: %04x; idProduct: %04x;\n", desc.idVendor, desc.idProduct);
uint8_t port_numbers[7];
res = libusb_get_port_numbers(devlist_item->dev,
port_numbers,
(sizeof (port_numbers)));
if (res < 0) {
fprintf(stderr, "libusb_get_port_numbers: %d\n", res);
return -1;
}
fprintf(stderr, " libusb port number: ");
for (int i = 0; i < res; i++) {
if (i != 0) fprintf(stderr, ":");
fprintf(stderr, "%o", port_numbers[i]);
}
fprintf(stderr, "\n");
devlist_item = devlist_item->next; devlist_item = devlist_item->next;
} }
assert(dev != NULL);
res = ftdi_usb_open_dev(ftdi, devlist->dev); res = ftdi_usb_open_dev(ftdi, devlist->dev);
if (res < 0) { if (res < 0) {
fprintf(stderr, "ftdi_usb_open_dev\n"); fprintf(stderr, "ftdi_usb_open_dev\n");
@ -66,19 +82,8 @@ int init_ftdi_context(struct ftdi_context * ftdi)
} }
ftdi_list_free(&devlist); ftdi_list_free(&devlist);
/* constexpr uint32_t cks = 0;
unsigned short value; res = ftdi_set_baudrate(ftdi, round(dreamcast_rate(cks, scbrr)));
unsigned short index;
for (unsigned int i = 0; i < (sizeof (dreamcast_rates)) / (sizeof (dreamcast_rates[0])); i++) {
int baud = convert_baudrate_UT_export(dreamcast_rates[i], ftdi, &value, &index);
float baudf = baud;
float ratef = dreamcast_rates[i];
float error = (baudf > ratef) ? ratef / baudf : baudf / ratef;
fprintf(stdout, "%d: best: %d, error: %f\n", dreamcast_rates[i], baud, (1.f - error) * 100.f);
}
*/
res = ftdi_set_baudrate(ftdi, dreamcast_rates[0]);
if (res < 0) { if (res < 0) {
fprintf(stderr, "ftdi_set_baudrate\n"); fprintf(stderr, "ftdi_set_baudrate\n");
return -1; return -1;
@ -116,6 +121,10 @@ int init_ftdi_context(struct ftdi_context * ftdi)
return -1; return -1;
} }
uint8_t discard[1024];
res = ftdi_read_data(ftdi, discard, (sizeof (discard)));
assert(res >= 0);
(void)discard;
return 0; return 0;
} }
@ -221,12 +230,16 @@ int read_reply(struct ftdi_context * ftdi, uint32_t expected_cmd, union serial_l
return 0; return 0;
} }
int do_write(struct ftdi_context * ftdi, const uint8_t * buf, const uint32_t size) int do_write(struct ftdi_context * ftdi, const uint32_t dest, const uint8_t * buf, const uint32_t size)
{ {
fprintf(stderr, "do_write\n");
int res; int res;
const uint32_t dest = 0xac010000; if (size > 0xffffff) {
fprintf(stderr, "write: invalid size %d (bytes)\n", size);
fprintf(stderr, "write size must be less than or equal to 16777215 bytes\n");
return -1;
}
union serial_load::command_reply command = serial_load::write_command(dest, size); union serial_load::command_reply command = serial_load::write_command(dest, size);
res = ftdi_write_data(ftdi, command.u8, (sizeof (command))); res = ftdi_write_data(ftdi, command.u8, (sizeof (command)));
assert(res == (sizeof (command))); assert(res == (sizeof (command)));
@ -235,9 +248,10 @@ int do_write(struct ftdi_context * ftdi, const uint8_t * buf, const uint32_t siz
if (res != 0) { if (res != 0) {
return -2; return -2;
} }
fprintf(stderr, "remote: dest: %08x size: %08x\n", reply.arg[0], reply.arg[1]); if (reply.arg[0] != command.arg[0] || reply.arg[1] != command.arg[1]) {
if (reply.arg[0] != dest || reply.arg[1] != size) { fprintf(stderr, "write: argument mismatch: (%08x, %08x) != (%08x, %08x)\n",
fprintf(stderr, "dest or size mismatch\n"); reply.arg[0], reply.arg[1],
command.arg[0], command.arg[1]);
return -1; return -1;
} }
@ -264,13 +278,10 @@ int do_write(struct ftdi_context * ftdi, const uint8_t * buf, const uint32_t siz
return 0; return 0;
} }
int do_jump(struct ftdi_context * ftdi) int do_jump(struct ftdi_context * ftdi, const uint32_t dest)
{ {
fprintf(stderr, "do_jump\n");
int res; int res;
const uint32_t dest = 0xac010000;
union serial_load::command_reply command = serial_load::jump_command(dest); union serial_load::command_reply command = serial_load::jump_command(dest);
res = ftdi_write_data(ftdi, command.u8, (sizeof (command))); res = ftdi_write_data(ftdi, command.u8, (sizeof (command)));
assert(res == (sizeof (command))); assert(res == (sizeof (command)));
@ -280,19 +291,69 @@ int do_jump(struct ftdi_context * ftdi)
if (res != 0) { if (res != 0) {
return -2; return -2;
} }
fprintf(stderr, "remote: jump: %08x\n", reply.arg[0]); if (reply.arg[0] != command.arg[0] || reply.arg[1] != command.arg[1]) {
if (reply.arg[0] != dest || reply.arg[1] != 0) { fprintf(stderr, "jump: argument mismatch: (%08x, %08x) != (%08x, %08x)\n",
reply.arg[0], reply.arg[1],
command.arg[0], command.arg[1]);
return -1; return -1;
} }
return 0; return 0;
} }
int read_file(const char * filename, uint8_t ** buf, uint32_t * size) int do_show_baudrate_error(struct ftdi_context * ftdi, uint32_t rows)
{
/*
B = (390625 * 4^(1 - n)) / (N + 1)
*/
fprintf(stderr, "\n");
fprintf(stderr, " SH7091 baud | FTDI baud | error \n");
fprintf(stderr, " ------------|-------------|---------\n");
unsigned short value;
unsigned short index;
rows = min(rows, 256);
for (uint32_t i = 0; i < rows; i++) {
int baud = convert_baudrate_UT_export(dreamcast_rate(0, i), ftdi, &value, &index);
if (baud < 0) {
fprintf(stderr, "ftdi_convert_baudrate: %d\n", baud);
return -1;
}
double baudf = baud;
double ratef = dreamcast_rate(0, i);
double error = (baudf - ratef) / ratef * 100.0;
fprintf(stderr, " %11.00f %11.00f % 02.03f%%\n", round(ratef), baudf, error);
}
fprintf(stderr, "\n \"\n Note: As far as possible, the setting should be made so that the\n error is within 1%%.\n \"\n");
fprintf(stderr, " - SH7091 Hardware Manual, 03/02/1999, page 486\n");
return 0;
}
int do_list_baudrates(struct ftdi_context * ftdi, uint32_t rows)
{
(void)ftdi;
fprintf(stderr, " scbrr | cks 0 | cks 1 | cks 2 | cks 3\n");
fprintf(stderr, "---------------------------------------------------------\n");
rows = min(rows, 256);
for (uint32_t i = 0; i < rows; i++) {
fprintf(stderr, " 0x%02x % 11.2f % 11.2f % 11.2f % 11.2f\n",
i,
dreamcast_rate(0, i),
dreamcast_rate(1, i),
dreamcast_rate(2, i),
dreamcast_rate(3, i));
}
return 0;
}
int read_file(const char * filename, uint8_t ** buf, uint32_t * size_out)
{ {
FILE * file = fopen(filename, "rb"); FILE * file = fopen(filename, "rb");
if (file == NULL) { if (file == NULL) {
fprintf(stderr, "fopen\n"); fprintf(stderr, "fopen(\"%s\", \"rb\"): %s\n", filename, strerror(errno));
return -1; return -1;
} }
@ -303,7 +364,12 @@ int read_file(const char * filename, uint8_t ** buf, uint32_t * size)
return -1; return -1;
} }
long off = ftell(file); long offset = ftell(file);
if (offset < 0) {
fprintf(stderr, "ftell");
return -1;
}
size_t size = offset;
ret = fseek(file, 0L, SEEK_SET); ret = fseek(file, 0L, SEEK_SET);
if (ret < 0) { if (ret < 0) {
@ -311,15 +377,11 @@ int read_file(const char * filename, uint8_t ** buf, uint32_t * size)
return -1; return -1;
} }
fprintf(stderr, "%s size %ld\n", filename, off); fprintf(stderr, "%s size %ld\n", filename, size);
*buf = (uint8_t *)malloc(off); *buf = (uint8_t *)malloc(size);
ssize_t fread_size = fread(*buf, 1, off, file); size_t fread_size = fread(*buf, 1, size, file);
if (fread_size < 0) { if (fread_size != size) {
fprintf(stderr, "fread error"); fprintf(stderr, "fread `%s` short read: %" PRIu64 " ; expected: %" PRIu64 "\n", filename, fread_size, size);
return -1;
}
if (fread_size != off) {
fprintf(stderr, "fread short read: %ld ; expected: %ld\n", fread_size, off);
return -1; return -1;
} }
@ -329,18 +391,44 @@ int read_file(const char * filename, uint8_t ** buf, uint32_t * size)
return -1; return -1;
} }
*size = off; *size_out = size;
return 0; return 0;
} }
int do_read(struct ftdi_context * ftdi, uint8_t * buf, const uint32_t size) int write_file(const char * filename, uint8_t * buf, uint32_t size)
{ {
fprintf(stderr, "do_read\n"); FILE * file = fopen(filename, "wb");
if (file == NULL) {
fprintf(stderr, "fopen(\"%s\", \"wb\"): %s\n", filename, strerror(errno));
return -1;
}
size_t fwrite_size = fwrite(buf, 1, size, file);
if (fwrite_size != size) {
fprintf(stderr, "fwrite `%s` short write: %" PRIu64 " ; expected: %" PRIu32 "\n", filename, fwrite_size, size);
return -1;
}
int ret = fclose(file);
if (ret < 0) {
fprintf(stderr, "fclose");
return -1;
}
return 0;
}
int do_read(struct ftdi_context * ftdi, const uint32_t src, uint8_t * buf, const uint32_t size)
{
int res; int res;
const uint32_t src = 0xac010000; if (size > 0xffffff) {
fprintf(stderr, "read: invalid size %d (bytes)\n", size);
fprintf(stderr, "read size must be less than or equal to 16777215 bytes\n");
return -1;
}
union serial_load::command_reply command = serial_load::read_command(src, size); union serial_load::command_reply command = serial_load::read_command(src, size);
res = ftdi_write_data(ftdi, command.u8, (sizeof (command))); res = ftdi_write_data(ftdi, command.u8, (sizeof (command)));
assert(res == (sizeof (command))); assert(res == (sizeof (command)));
@ -349,8 +437,10 @@ int do_read(struct ftdi_context * ftdi, uint8_t * buf, const uint32_t size)
if (res != 0) { if (res != 0) {
return -2; return -2;
} }
fprintf(stderr, "remote: src: %08x size: %08x\n", reply.arg[0], reply.arg[1]); if (reply.arg[0] != command.arg[0] || reply.arg[1] != command.arg[1]) {
if (reply.arg[0] != src || reply.arg[1] != size) { fprintf(stderr, "read: argument mismatch: (%08x, %08x) != (%08x, %08x)\n",
reply.arg[0], reply.arg[1],
command.arg[0], command.arg[1]);
return -1; return -1;
} }
@ -376,7 +466,60 @@ int do_read(struct ftdi_context * ftdi, uint8_t * buf, const uint32_t size)
return 0; return 0;
} }
void console(struct ftdi_context * ftdi) int do_speed(struct ftdi_context * ftdi, uint32_t scbrr)
{
int res;
if (scbrr > 255) {
fprintf(stderr, "speed: invalid speed %d\n", scbrr);
fprintf(stderr, "speed is expressed as a raw SCBRR value; see `list_baudrates`\n");
return -1;
}
union serial_load::command_reply command = serial_load::speed_command(scbrr);
res = ftdi_write_data(ftdi, command.u8, (sizeof (command)));
assert(res == (sizeof (command)));
union serial_load::command_reply reply;
res = read_reply(ftdi, serial_load::reply::speed, reply);
if (res != 0) {
return -2;
}
if (reply.arg[0] != command.arg[0] || reply.arg[1] != command.arg[1]) {
fprintf(stderr, "speed: argument mismatch: (%08x, %08x) != (%08x, %08x)\n",
reply.arg[0], reply.arg[1],
command.arg[0], command.arg[1]);
return -1;
}
res = ftdi_set_baudrate(ftdi, round(dreamcast_rate(0, scbrr)));
if (res < 0) {
fprintf(stderr, "ftdi_set_baudrate\n");
return -1;
}
res = ftdi_tciflush(ftdi);
if (res < 0) {
fprintf(stderr, "ftdi_tciflush\n");
return -1;
}
res = ftdi_tcoflush(ftdi);
if (res < 0) {
fprintf(stderr, "ftdi_tcoflush\n");
return -1;
}
uint8_t discard[1024];
res = ftdi_read_data(ftdi, discard, (sizeof (discard)));
assert(res >= 0);
(void)discard;
return 0;
}
void do_console(struct ftdi_context * ftdi)
{ {
int res; int res;
@ -387,18 +530,186 @@ void console(struct ftdi_context * ftdi)
while (1) { while (1) {
res = ftdi_read_data(ftdi, read_buf, ftdi->readbuffer_chunksize); res = ftdi_read_data(ftdi, read_buf, ftdi->readbuffer_chunksize);
if (res > 0) { if (res > 0) {
fwrite(read_buf, 1, res, stderr); fwrite(read_buf, 1, res, stdout);
fflush(stdout);
} }
} }
} }
int main(int argc, char * argv[]) enum struct argument_type {
string,
integer
};
struct cli_command {
const char * name;
int num_arguments;
void * func;
};
struct cli_command commands[] = {
{ "read" , 3, (void *)&do_read },
{ "write" , 2, (void *)&do_write },
{ "jump" , 1, (void *)&do_jump },
{ "speed" , 1, (void *)&do_speed },
{ "list_baudrates" , 1, (void *)&do_list_baudrates },
{ "show_baudrate_error", 1, (void *)&do_show_baudrate_error },
{ "console" , 0, (void *)&do_console },
};
constexpr int commands_length = (sizeof (commands)) / (sizeof (commands[0]));
typedef int (*func_0_arg)(struct ftdi_context *);
typedef int (*func_1_arg)(struct ftdi_context *, uint32_t);
typedef int (*func_2_arg)(struct ftdi_context *, uint32_t, uint8_t *, uint32_t);
typedef int (*func_3_arg)(struct ftdi_context *, uint32_t, uint32_t, uint8_t *, uint32_t);
int parse_integer(const char * s, uint32_t * value)
{ {
if (argc < 2) { if (s[0] == '0' && s[1] == 'x') {
fprintf(stderr, "argc\n"); s = &s[2];
return EXIT_FAILURE;
} }
uint32_t n = 0;
while (*s != 0) {
char c = *s++;
n = n << 4;
switch (c) {
case '0': n += 0; break;
case '1': n += 1; break;
case '2': n += 2; break;
case '3': n += 3; break;
case '4': n += 4; break;
case '5': n += 5; break;
case '6': n += 6; break;
case '7': n += 7; break;
case '8': n += 8; break;
case '9': n += 9; break;
case 'A': [[fallthrough]];
case 'a': n += 0xa; break;
case 'B': [[fallthrough]];
case 'b': n += 0xb; break;
case 'C': [[fallthrough]];
case 'c': n += 0xc; break;
case 'D': [[fallthrough]];
case 'd': n += 0xd; break;
case 'E': [[fallthrough]];
case 'e': n += 0xe; break;
case 'F': [[fallthrough]];
case 'f': n += 0xf; break;
default:
return -1;
}
}
*value = n;
return 0;
}
#define CHECK_ARGC(__name__) \
if (arg_index >= argc) { \
fprintf(stderr, "while processing command `%s` expected argument `%s`\n", name, #__name__); \
return -1; \
}
#define INTEGER_ARGUMENT(__name__) \
CHECK_ARGC(__name__); \
uint32_t __name__; \
const char * __name__##str = argv[arg_index++]; \
{ int res = parse_integer(__name__##str, &__name__); \
if (res < 0) { \
fprintf(stderr, "while processing command `%s` expected integer at `%s`", name, __name__##str); \
return -1; \
} }
#define STRING_ARGUMENT(__name__) \
CHECK_ARGC(__name__); \
const char * __name__ = argv[arg_index++];
int handle_command(int argc, const char * argv[], struct ftdi_context * ftdi)
{
assert(argc >= 1);
int arg_index = 0;
const char * name = argv[arg_index++];
int func_ret;
for (int i = 0; i < commands_length; i++) {
if (strcmp(commands[i].name, name) == 0) {
switch (commands[i].num_arguments) {
case 0:
{
fprintf(stderr, "handle command: %s ()\n", commands[i].name);
func_0_arg func = (func_0_arg)commands[i].func;
func_ret = func(ftdi);
}
break;
case 1:
{
INTEGER_ARGUMENT(arg0);
fprintf(stderr, "handle command: %s (0x%08x)\n", commands[i].name, arg0);
func_1_arg func = (func_1_arg)commands[i].func;
func_ret = func(ftdi, arg0);
}
break;
case 2:
{
INTEGER_ARGUMENT(dest_addr);
STRING_ARGUMENT(filename);
uint8_t * buf = NULL;
uint32_t write_size;
int res = read_file(filename, &buf, &write_size);
if (res < 0) {
return -1;
}
fprintf(stderr, "handle command: %s (0x%08x, %s)\n", commands[i].name, dest_addr, filename);
func_2_arg func = (func_2_arg)commands[i].func;
func_ret = func(ftdi, dest_addr, buf, write_size);
assert(buf != NULL);
free(buf);
}
break;
case 3:
{
INTEGER_ARGUMENT(src_addr);
INTEGER_ARGUMENT(read_size);
STRING_ARGUMENT(filename);
uint8_t * buf = (uint8_t *)malloc(read_size);
fprintf(stderr, "handle command %s (0x%08x, 0x%08x) → %s\n", commands[i].name, src_addr, read_size, filename);
func_2_arg func = (func_2_arg)commands[i].func;
func_ret = func(ftdi, src_addr, buf, read_size);
int res = write_file(filename, buf, read_size);
if (res < 0) {
return -1;
}
assert(buf != NULL);
free(buf);
}
break;
default:
assert(false); // unimplemented
}
if (func_ret < 0)
return func_ret;
else
return arg_index;
}
}
fprintf(stderr, "unknown command `%s`\n", name);
return -1;
}
int main(int argc, const char * argv[])
{
struct ftdi_context * ftdi; struct ftdi_context * ftdi;
ftdi = ftdi_new(); ftdi = ftdi_new();
@ -408,25 +719,24 @@ int main(int argc, char * argv[])
} }
int res; int res;
res = init_ftdi_context(ftdi); res = init_ftdi_context(ftdi, 0);
if (res < 0) { if (res < 0) {
return EXIT_FAILURE; return EXIT_FAILURE;
} }
int return_code = EXIT_SUCCESS; assert(argc >= 1);
argc--;
uint8_t * buf; argv++;
uint32_t size; while (argc > 0) {
res = read_file(argv[1], &buf, &size); res = handle_command(argc, argv, ftdi);
if (res < 0) { if (res < 0) {
return EXIT_FAILURE; return -1;
}
argc -= res;
argv += res;
} }
uint8_t discard[1024]; /*
res = ftdi_read_data(ftdi, discard, (sizeof (discard)));
assert(res >= 0);
(void)discard;
struct timespec start; struct timespec start;
struct timespec end; struct timespec end;
res = clock_gettime(CLOCK_MONOTONIC, &start); res = clock_gettime(CLOCK_MONOTONIC, &start);
@ -447,6 +757,7 @@ int main(int argc, char * argv[])
res = clock_gettime(CLOCK_MONOTONIC, &end); res = clock_gettime(CLOCK_MONOTONIC, &end);
assert(res >= 0); assert(res >= 0);
fprintf(stderr, "total time: %.03f\n", timespec_difference(&end, &start)); fprintf(stderr, "total time: %.03f\n", timespec_difference(&end, &start));
*/
return return_code; return 0;
} }

15
tools/ftdi_transfer.sh Normal file
View File

@ -0,0 +1,15 @@
#!/bin/sh
filename="$1"
if [ -z "$filename" ]; then
echo "usage: ./$0 [filename]"
exit 1
fi
set -ex
./ftdi_transfer \
write 0xac010000 "$filename" \
jump 0xac010000 \
console

BIN
track1.wav Normal file

Binary file not shown.