Skip to main content

ym2149_core/
register.rs

1/// One of the 16 registers (0-15) of the YM2149 sound chip.
2///
3/// Used to select which register to write / read.
4/// Each register controls different aspects of tone generation, noise, mixing,
5/// amplitude, and envelope.
6///
7/// Check the datasheet / docs for detailed information.
8#[repr(u8)]
9#[derive(Debug, Clone, Copy)]
10pub enum Register {
11    /// Frequency of channel A: 8 bit fine tone adjustment
12    AFreq8bitFinetone,
13    /// Frequency of channel A: 4 bit rough tone adjustment
14    ///
15    /// `Mask: 0x0F`
16    AFreq4bitRoughtone,
17
18    /// Frequency of channel B: 8 bit fine tone adjustment
19    BFreq8bitFinetone,
20    /// Frequency of channel B: 4 bit rough tone adjustment
21    ///
22    /// `Mask: 0x0F`
23    BFreq4bitRoughtone,
24
25    /// Frequency of channel C: 8 bit fine tone adjustment
26    CFreq8bitFinetone,
27    /// Frequency of channel C: 4 bit rough tone adjustment
28    ///
29    /// `Mask: 0x0F`
30    CFreq4bitRoughtone,
31
32    /// Frequency of noise: 5 bit noise frequency
33    ///
34    /// `Mask: 0x1F`
35    NoiseFreq5bit,
36
37    /// **I/O Port and mixer settings**
38    ///
39    /// From the datasheet:
40    /// - Sound is output when '0' is written to the register.
41    /// - Selection of input/output for the I/O ports is determined by bits B7 and B6 of register R7.
42    /// - Input is selected when '0' is written to the register bits.
43    ///
44    /// Bit:    | B7  | B6  | B5  | B4  | B3  | B2  | B1  | B0  |
45    /// --------|-----|-----|-----|-----|-----|-----|-----|-----|
46    /// Type:   | I/O | I/O |Noise|Noise|Noise|Tone |Tone |Tone |
47    /// Channel:| IOB | IOA |  C  |  B  |  A  |  C  |  B  |  A  |
48    ///
49    ///
50    /// **Example:**
51    /// ```no_run
52    /// // Enables only channel A, with IOA and IOB functioning as outputs.
53    /// use ym2149_core::{
54    ///     command::{Command, CommandOutput},
55    ///     register::Register,
56    ///     chip::YM2149
57    /// };
58    ///
59    /// struct DebugWriter;
60    ///
61    /// impl CommandOutput for DebugWriter {
62    ///     fn execute(&mut self, command: Command) {
63    ///         let arr = command.as_array();
64    ///         println!("Writing 0b{:08b} to register 0b{:08b}.", arr[0], arr[1]);
65    ///     }
66    /// }
67    ///
68    /// let mut chip = YM2149::new(
69    ///     DebugWriter{},
70    ///     2_000_000,
71    /// ).expect("Error building chip");
72    ///
73    /// chip.command(
74    ///     Register::IoPortMixerSettings,
75    ///     0b11111110
76    /// );
77    /// ```
78    IoPortMixerSettings,
79
80    /// **Level of channel A**
81    /// ---
82    /// **Level control** (formats identical for ALevel, BLevel and CLevel)
83    ///
84    /// From the datasheet:
85    /// - Mode M selects whether the level is fixed (when M = 0) or variable (M = 1).
86    /// - When M = 0, the level is determined from one of 16 by level selection signals L3, L2, L1, and L0 which compromise the lower four bits.
87    /// - When M = 1, the level is determined by the 5 bit output of E4, E3, E2, E1, and E0 of the envelope generator of the SSG.
88    ///
89    /// | B7 (MSB)  | B6  | B5  | B4  | B3  | B2  | B1  | B0  |
90    /// |-----------|-----|-----|-----|-----|-----|-----|-----|
91    /// | N/A       | N/A | N/A |  M  | L3  | L2  | L1  | L0  |
92    ALevel,
93
94    /// **Level of channel B**
95    ///
96    /// Same format as [ALevel](#alevel)
97    BLevel,
98
99    /// **Level of channel C**
100    ///
101    /// Same format as [ALevel](#alevel)
102    CLevel,
103
104    /// Frequency of envelope: 8 bit fine adjustment
105    EFreq8bitFineAdj,
106    /// Frequency of envelope: 8 bit rough adjustment
107    EFreq8bitRoughAdj,
108    /// Shape of envelope
109    EShape,
110    /// Data of I/O port A
111    DataIoA,
112    /// Data of I/O port B
113    DataIoB,
114}
115
116/// Helper const, used to get a level register from an index in range 0..2.
117pub const LEVEL_REGS: [Register; 3] = [Register::ALevel, Register::BLevel, Register::CLevel];
118
119/// Helper trait implemented for u8 and crate::Register to make writing to registers easier.
120pub trait ValidRegister {
121    fn address(self) -> u8;
122}
123
124impl ValidRegister for u8 {
125    fn address(self) -> u8 {
126        self.clamp(0, 15)
127    }
128}
129
130impl ValidRegister for Register {
131    fn address(self) -> u8 {
132        (self as u8).clamp(0, 15)
133    }
134}