2024-02-24 21:02:09 +00:00
|
|
|
use femtos::{Instant, Duration, Frequency};
|
|
|
|
|
2022-09-25 06:14:03 +00:00
|
|
|
use moa_peripherals_yamaha::{Ym2612, Sn76489};
|
|
|
|
|
2024-03-02 05:17:09 +00:00
|
|
|
use moa_host::{self, Host, Frame, FrameSender, PixelEncoding, Key, KeyEvent, EventReceiver};
|
2024-02-24 21:02:09 +00:00
|
|
|
use moa_core::{System, Error, Address, Addressable, Steppable, Transmutable, Device};
|
2022-01-19 04:24:18 +00:00
|
|
|
|
2023-05-06 17:04:44 +00:00
|
|
|
const SCREEN_WIDTH: u32 = 384;
|
|
|
|
const SCREEN_HEIGHT: u32 = 128;
|
2022-10-03 03:39:02 +00:00
|
|
|
|
2022-01-19 04:24:18 +00:00
|
|
|
struct SynthControl {
|
2023-05-06 17:04:44 +00:00
|
|
|
key_receiver: EventReceiver<KeyEvent>,
|
|
|
|
frame_sender: FrameSender,
|
2022-01-19 04:24:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl SynthControl {
|
2023-05-06 17:04:44 +00:00
|
|
|
pub fn new(key_receiver: EventReceiver<KeyEvent>, frame_sender: FrameSender) -> Self {
|
2022-01-19 04:24:18 +00:00
|
|
|
Self {
|
2023-05-06 17:04:44 +00:00
|
|
|
key_receiver,
|
|
|
|
frame_sender,
|
2022-01-19 04:24:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Steppable for SynthControl {
|
2024-02-24 21:02:09 +00:00
|
|
|
fn step(&mut self, system: &System) -> Result<Duration, Error> {
|
2023-05-06 17:04:44 +00:00
|
|
|
if let Some(event) = self.key_receiver.receive() {
|
2022-10-03 03:39:02 +00:00
|
|
|
match event.key {
|
2022-01-26 19:12:09 +00:00
|
|
|
Key::Enter => {
|
2023-04-24 01:49:40 +00:00
|
|
|
system.get_bus().write_u8(system.clock, 0x00, 0x28)?;
|
2024-03-17 18:03:52 +00:00
|
|
|
system
|
|
|
|
.get_bus()
|
|
|
|
.write_u8(system.clock, 0x01, if event.state { 0xF0 } else { 0x00 })?;
|
2022-01-26 19:12:09 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
Key::A => {
|
2023-04-24 01:49:40 +00:00
|
|
|
system.get_bus().write_u8(system.clock, 0x10, 0x84)?;
|
|
|
|
system.get_bus().write_u8(system.clock, 0x10, 0x0F)?;
|
2024-03-17 18:03:52 +00:00
|
|
|
system
|
|
|
|
.get_bus()
|
|
|
|
.write_u8(system.clock, 0x10, if event.state { 0x90 } else { 0x9F })?;
|
2022-01-26 19:12:09 +00:00
|
|
|
},
|
2022-01-27 03:15:46 +00:00
|
|
|
|
2024-03-17 18:03:52 +00:00
|
|
|
_ => {},
|
2022-01-26 19:12:09 +00:00
|
|
|
}
|
2022-01-19 04:24:18 +00:00
|
|
|
}
|
|
|
|
|
2023-05-06 17:04:44 +00:00
|
|
|
let frame = Frame::new(SCREEN_WIDTH, SCREEN_HEIGHT, PixelEncoding::RGBA);
|
|
|
|
self.frame_sender.add(system.clock, frame);
|
2022-10-02 20:07:15 +00:00
|
|
|
|
2024-02-24 21:02:09 +00:00
|
|
|
Ok(Duration::from_micros(100))
|
2022-01-19 04:24:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Transmutable for SynthControl {
|
|
|
|
fn as_steppable(&mut self) -> Option<&mut dyn Steppable> {
|
|
|
|
Some(self)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn set_register(device: &mut dyn Addressable, bank: u8, reg: u8, data: u8) -> Result<(), Error> {
|
|
|
|
let addr = (bank as Address) * 2;
|
2024-02-24 21:02:09 +00:00
|
|
|
device.write_u8(Instant::START, addr, reg)?;
|
|
|
|
device.write_u8(Instant::START, addr + 1, data)?;
|
2022-01-19 04:24:18 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2023-06-11 00:39:20 +00:00
|
|
|
fn initialize_ym(ym_sound: Device) -> Result<(), Error> {
|
2022-01-19 04:24:18 +00:00
|
|
|
let mut borrow = ym_sound.borrow_mut();
|
|
|
|
let device = borrow.as_addressable().unwrap();
|
|
|
|
|
|
|
|
set_register(device, 0, 0x30, 0x71)?;
|
|
|
|
set_register(device, 0, 0x34, 0x0D)?;
|
|
|
|
set_register(device, 0, 0x38, 0x33)?;
|
2022-09-09 02:51:29 +00:00
|
|
|
set_register(device, 0, 0x3C, 0x00)?;
|
2022-01-19 04:24:18 +00:00
|
|
|
|
|
|
|
set_register(device, 0, 0xA4, 0x22)?;
|
|
|
|
set_register(device, 0, 0xA0, 0x69)?;
|
|
|
|
set_register(device, 0, 0xB0, 0x30)?;
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn main() {
|
2024-03-17 18:03:52 +00:00
|
|
|
let matches = moa_minifb::new("YM2612 Tester/Synth").get_matches();
|
2022-01-19 04:24:18 +00:00
|
|
|
|
|
|
|
moa_minifb::run(matches, |host| {
|
2023-03-06 04:19:49 +00:00
|
|
|
let mut system = System::default();
|
2022-01-19 04:24:18 +00:00
|
|
|
|
2024-03-02 05:17:09 +00:00
|
|
|
let (frame_sender, frame_receiver) = moa_host::frame_queue(SCREEN_WIDTH, SCREEN_HEIGHT);
|
|
|
|
let (key_sender, key_receiver) = moa_host::event_queue();
|
2023-06-11 00:39:20 +00:00
|
|
|
let control = Device::new(SynthControl::new(key_receiver, frame_sender));
|
2022-01-19 04:24:18 +00:00
|
|
|
system.add_device("control", control)?;
|
|
|
|
|
2023-06-11 00:39:20 +00:00
|
|
|
let ym_sound = Device::new(Ym2612::new(host, Frequency::from_hz(7_670_454))?);
|
2022-01-19 04:24:18 +00:00
|
|
|
initialize_ym(ym_sound.clone())?;
|
|
|
|
system.add_addressable_device(0x00, ym_sound)?;
|
|
|
|
|
2023-06-11 00:39:20 +00:00
|
|
|
let sn_sound = Device::new(Sn76489::new(host, Frequency::from_hz(3_579_545))?);
|
2022-01-26 19:12:09 +00:00
|
|
|
system.add_addressable_device(0x10, sn_sound)?;
|
|
|
|
|
2023-05-06 17:04:44 +00:00
|
|
|
host.add_video_source(frame_receiver)?;
|
|
|
|
host.register_keyboard(key_sender)?;
|
2022-01-19 04:24:18 +00:00
|
|
|
|
|
|
|
Ok(system)
|
|
|
|
});
|
|
|
|
}
|