mirror of
https://github.com/transistorfet/moa.git
synced 2024-06-10 22:29:41 +00:00
Updated sn76489
This commit is contained in:
parent
54bf7a3085
commit
061c13fdc7
|
@ -10,7 +10,7 @@ use moa::system::System;
|
||||||
use moa::host::gfx::Frame;
|
use moa::host::gfx::Frame;
|
||||||
use moa::devices::{ClockElapsed, Address, Addressable, Steppable, Transmutable, TransmutableBox, wrap_transmutable};
|
use moa::devices::{ClockElapsed, Address, Addressable, Steppable, Transmutable, TransmutableBox, wrap_transmutable};
|
||||||
use moa::host::keys::{Key};
|
use moa::host::keys::{Key};
|
||||||
use moa::host::traits::{Host, HostData, KeyboardUpdater};
|
use moa::host::traits::{Host, KeyboardUpdater};
|
||||||
|
|
||||||
|
|
||||||
pub struct SynthControlsUpdater(mpsc::Sender<(Key, bool)>);
|
pub struct SynthControlsUpdater(mpsc::Sender<(Key, bool)>);
|
||||||
|
@ -48,6 +48,7 @@ impl Steppable for SynthControl {
|
||||||
system.get_bus().write_u8(0x10, 0x0F)?;
|
system.get_bus().write_u8(0x10, 0x0F)?;
|
||||||
system.get_bus().write_u8(0x10, if state { 0x90 } else { 0x9F })?;
|
system.get_bus().write_u8(0x10, if state { 0x90 } else { 0x9F })?;
|
||||||
},
|
},
|
||||||
|
|
||||||
_ => { },
|
_ => { },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,13 +9,13 @@ use crate::host::traits::{Host, Audio};
|
||||||
const DEV_NAME: &'static str = "sn76489";
|
const DEV_NAME: &'static str = "sn76489";
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Channel {
|
pub struct ToneGenerator {
|
||||||
on: bool,
|
on: bool,
|
||||||
attenuation: f32,
|
attenuation: f32,
|
||||||
wave: SquareWave,
|
wave: SquareWave,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Channel {
|
impl ToneGenerator {
|
||||||
pub fn new(sample_rate: usize) -> Self {
|
pub fn new(sample_rate: usize) -> Self {
|
||||||
Self {
|
Self {
|
||||||
on: false,
|
on: false,
|
||||||
|
@ -31,13 +31,13 @@ impl Channel {
|
||||||
self.on = true;
|
self.on = true;
|
||||||
self.attenuation = (attenuation << 1) as f32;
|
self.attenuation = (attenuation << 1) as f32;
|
||||||
}
|
}
|
||||||
println!("set attenuation to {} {}", self.attenuation, self.on);
|
info!("set attenuation to {} {}", self.attenuation, self.on);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_counter(&mut self, count: usize) {
|
pub fn set_counter(&mut self, count: usize) {
|
||||||
let frequency = 3_579_545.0 / (count as f32 * 32.0);
|
let frequency = 3_579_545.0 / (count as f32 * 32.0);
|
||||||
self.wave.set_frequency(frequency);
|
self.wave.set_frequency(frequency);
|
||||||
println!("set frequency to {}", frequency);
|
info!("set frequency to {}", frequency);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_sample(&mut self) -> f32 {
|
pub fn get_sample(&mut self) -> f32 {
|
||||||
|
@ -46,11 +46,49 @@ impl Channel {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct NoiseGenerator {
|
||||||
|
on: bool,
|
||||||
|
attenuation: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NoiseGenerator {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
on: false,
|
||||||
|
attenuation: 0.0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_attenuation(&mut self, attenuation: u8) {
|
||||||
|
if attenuation == 0x0F {
|
||||||
|
self.on = false;
|
||||||
|
} else {
|
||||||
|
self.on = true;
|
||||||
|
self.attenuation = (attenuation << 1) as f32;
|
||||||
|
}
|
||||||
|
info!("set attenuation to {} {}", self.attenuation, self.on);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_control(&mut self, bits: u8) {
|
||||||
|
//let frequency = 3_579_545.0 / (count as f32 * 32.0);
|
||||||
|
//self.wave.set_frequency(frequency);
|
||||||
|
//debug!("set frequency to {}", frequency);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_sample(&mut self) -> f32 {
|
||||||
|
// TODO this isn't implemented yet
|
||||||
|
0.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
pub struct Sn76489 {
|
pub struct Sn76489 {
|
||||||
pub regs: [u8; 8],
|
|
||||||
pub first_byte: Option<u8>,
|
pub first_byte: Option<u8>,
|
||||||
pub source: Box<dyn Audio>,
|
pub source: Box<dyn Audio>,
|
||||||
pub channels: Vec<Channel>,
|
pub tones: Vec<ToneGenerator>,
|
||||||
|
pub noise: NoiseGenerator,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sn76489 {
|
impl Sn76489 {
|
||||||
|
@ -59,10 +97,10 @@ impl Sn76489 {
|
||||||
let sample_rate = source.samples_per_second();
|
let sample_rate = source.samples_per_second();
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
regs: [0; 8],
|
|
||||||
first_byte: None,
|
first_byte: None,
|
||||||
source,
|
source,
|
||||||
channels: vec![Channel::new(sample_rate); 3],
|
tones: vec![ToneGenerator::new(sample_rate); 3],
|
||||||
|
noise: NoiseGenerator::new(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -81,12 +119,17 @@ impl Steppable for Sn76489 {
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
|
|
||||||
for ch in 0..3 {
|
for ch in 0..3 {
|
||||||
if self.channels[ch].on {
|
if self.tones[ch].on {
|
||||||
sample += self.channels[ch].get_sample();
|
sample += self.tones[ch].get_sample();
|
||||||
count += 1;
|
count += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self.noise.on {
|
||||||
|
sample += self.noise.get_sample();
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
if count > 0 {
|
if count > 0 {
|
||||||
buffer[i] = sample / count as f32;
|
buffer[i] = sample / count as f32;
|
||||||
}
|
}
|
||||||
|
@ -116,25 +159,25 @@ impl Addressable for Sn76489 {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data[0] & 0x80) == 0 {
|
if (data[0] & 0x80) != 0 {
|
||||||
|
let reg = (data[0] & 0x70) >> 4;
|
||||||
|
let value = data[0] & 0x0F;
|
||||||
|
match reg {
|
||||||
|
1 => self.tones[0].set_attenuation(value),
|
||||||
|
3 => self.tones[1].set_attenuation(value),
|
||||||
|
5 => self.tones[2].set_attenuation(value),
|
||||||
|
6 => self.noise.set_control(value),
|
||||||
|
7 => self.noise.set_attenuation(value),
|
||||||
|
_ => { self.first_byte = Some(data[0]); },
|
||||||
|
}
|
||||||
|
} else {
|
||||||
let first = self.first_byte.unwrap_or(0);
|
let first = self.first_byte.unwrap_or(0);
|
||||||
let reg = (first & 0x70) >> 4;
|
let reg = (first & 0x70) >> 4;
|
||||||
let value = ((data[0] as usize & 0x3F) << 4) | (first as usize & 0x0F);
|
let value = ((data[0] as usize & 0x3F) << 4) | (first as usize & 0x0F);
|
||||||
match reg {
|
match reg {
|
||||||
0 => self.channels[0].set_counter(value),
|
0 => self.tones[0].set_counter(value),
|
||||||
2 => self.channels[1].set_counter(value),
|
2 => self.tones[1].set_counter(value),
|
||||||
4 => self.channels[2].set_counter(value),
|
4 => self.tones[2].set_counter(value),
|
||||||
_ => { },
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let reg = (data[0] & 0x70) >> 4;
|
|
||||||
self.first_byte = Some(data[0]);
|
|
||||||
//self.regs[reg as usize] = data[0] & 0x0F;
|
|
||||||
let attenuation = data[0] & 0x0F;
|
|
||||||
match reg {
|
|
||||||
1 => self.channels[0].set_attenuation(attenuation),
|
|
||||||
3 => self.channels[1].set_attenuation(attenuation),
|
|
||||||
5 => self.channels[2].set_attenuation(attenuation),
|
|
||||||
_ => { },
|
_ => { },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -143,7 +186,6 @@ impl Addressable for Sn76489 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl Transmutable for Sn76489 {
|
impl Transmutable for Sn76489 {
|
||||||
fn as_addressable(&mut self) -> Option<&mut dyn Addressable> {
|
fn as_addressable(&mut self) -> Option<&mut dyn Addressable> {
|
||||||
Some(self)
|
Some(self)
|
||||||
|
@ -154,4 +196,3 @@ impl Transmutable for Sn76489 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user