1use crate::PSG_MASTER_CLOCK_HZ as PSG_CLOCK_U32;
7
8const PSG_MASTER_CLOCK_F32: f32 = PSG_CLOCK_U32 as f32;
10
11const PERIOD_DENOMINATOR: f32 = 16.0;
12
13#[inline]
15#[must_use]
16pub fn channel_period(lo: u8, hi: u8) -> Option<u16> {
17 let period = (((hi as u16) & 0x0F) << 8) | (lo as u16);
18 if period == 0 { None } else { Some(period) }
19}
20
21#[inline]
23#[must_use]
24pub fn period_to_frequency(period: u16) -> f32 {
25 period_to_frequency_with_clock(PSG_MASTER_CLOCK_F32, period)
26}
27
28#[inline]
30#[must_use]
31pub fn period_to_frequency_with_clock(master_clock_hz: f32, period: u16) -> f32 {
32 if period == 0 {
33 0.0
34 } else {
35 master_clock_hz / (PERIOD_DENOMINATOR * period as f32)
36 }
37}
38
39#[inline]
41#[must_use]
42pub fn channel_frequencies(registers: &[u8; 16]) -> [Option<f32>; 3] {
43 channel_frequencies_with_clock(registers, PSG_MASTER_CLOCK_F32)
44}
45
46#[inline]
48#[must_use]
49pub fn channel_frequencies_with_clock(
50 registers: &[u8; 16],
51 master_clock_hz: f32,
52) -> [Option<f32>; 3] {
53 [
54 channel_period(registers[0], registers[1])
55 .map(|period| period_to_frequency_with_clock(master_clock_hz, period)),
56 channel_period(registers[2], registers[3])
57 .map(|period| period_to_frequency_with_clock(master_clock_hz, period)),
58 channel_period(registers[4], registers[5])
59 .map(|period| period_to_frequency_with_clock(master_clock_hz, period)),
60 ]
61}