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}