1use core::ptr::{write_volatile, read_volatile};
2
3const FM_BASE: *mut u8 = 0xa04000 as _;
4const FM_LFO: u8 = 0x22;
5const FM_TIMER_A_HI: u8 = 0x24;
6const FM_TIMER_A_LO: u8 = 0x25;
7const FM_TIMER_B: u8 = 0x25;
8const FM_TIMER_CTRL: u8 = 0x27;
9const FM_KEY_ON: u8 = 0x28;
10const FM_DAC_DATA: u8 = 0x2a;
11const FM_DAC_ENABLE: u8 = 0x2b;
12const FM_MULTIPLY: u8 = 0x30;
13const FM_TOTAL_LEVEL: u8 = 0x40;
14const FM_ATTACK_RATE: u8 = 0x50;
15const FM_DECAY_RATE: u8 = 0x60;
16const FM_SUSTAIN_RATE: u8 = 0x70;
17const FM_RELEASE_RATE: u8 = 0x80;
18const FM_SSGEG: u8 = 0x90;
19const FM_FREQUENCY_LO: u8 = 0xa0;
20const FM_FREQUENCY_HI: u8 = 0xa4;
21const FM_ALGORITHM: u8 = 0xb0;
22const FM_PANNING: u8 = 0xb4;
23
24static FM_SPECIAL_FREQUENCY_LO: [u8; 4] = [0xa9, 0xaa, 0xa8, 0xa2];
25static FM_SPECIAL_FREQUENCY_HI: [u8; 4] = [0xad, 0xae, 0xac, 0xa6];
26
27static ALL_CHANNELS: [u8; 6] = [0, 1, 2, 4, 5, 6];
28const NUM_CHANNELS: u8 = 6;
29const NUM_OPERATORS: u8 = 4;
30
31#[repr(u8)]
33#[derive(Clone, Copy, Debug)]
34pub enum Panning {
35 None = 0b00,
36 Left = 0b10,
37 Right = 0b01,
38 Both = 0b11,
39}
40
41#[repr(u16)]
46#[derive(Clone, Copy, Debug)]
47pub enum Note {
48 C = 644,
49 CSharp = 681,
50 D = 722,
51 DSharp = 765,
52 E = 810,
53 F = 858,
54 FSharp = 910,
55 G = 964,
56 GSharp = 1021,
57 A = 1081,
58 ASharp = 1146,
59 B = 1214,
60}
61
62impl From<Note> for u16 {
63 fn from(v: Note) -> Self {
64 v as u16
65 }
66}
67
68#[repr(u8)]
70#[derive(Clone, Copy, Debug)]
71pub enum LFORate {
72 F3_82Hz = 0b000,
73 F5_33Hz = 0b001,
74 F5_77Hz = 0b010,
75 F6_11Hz = 0b011,
76 F6_60Hz = 0b100,
77 F9_23Hz = 0b101,
78 F46_11Hz = 0b110,
79 F69_22Hz = 0b111,
80}
81
82impl From<LFORate> for u8 {
83 fn from(v: LFORate) -> Self {
84 v as u8
85 }
86}
87
88#[derive(Clone, Copy, Debug)]
90pub struct TimerConfig(u8);
91
92impl TimerConfig {
93 pub fn new() -> TimerConfig {
95 TimerConfig(0)
96 }
97
98 pub fn ch3_special_mode(self, v: bool) -> TimerConfig {
100 let f = if v { 0x40 } else { 0 };
101 TimerConfig((self.0 & 0x3f) | f)
102 }
103
104 pub fn enable_timer_a(self, e: bool, r: bool) -> TimerConfig {
109 let fe = if e { 4 } else { 0 };
110 let fr = if r { 1 } else { 0 };
111 TimerConfig((self.0 & 0xfa) | fe | fr)
112 }
113
114 pub fn enable_timer_b(self, e: bool, r: bool) -> TimerConfig {
119 let fe = if e { 8 } else { 0 };
120 let fr = if r { 2 } else { 0 };
121 TimerConfig((self.0 & 0xf5) | fe | fr)
122 }
123
124 pub fn reset_timer_a(self, v: bool) -> TimerConfig {
126 let v = if v {
127 self.0 | 0x10
128 } else {
129 self.0 &! 0x10
130 };
131 TimerConfig(v)
132 }
133
134 pub fn reset_timer_b(self, v: bool) -> TimerConfig {
136 let v = if v {
137 self.0 | 0x20
138 } else {
139 self.0 &! 0x20
140 };
141 TimerConfig(v)
142 }
143}
144
145pub struct FM;
150
151impl FM {
152 pub fn new() -> FM {
157 let fm = FM;
158 fm.enable_lfo(None);
159
160 fm.configure_timers(TimerConfig::new());
162 fm.enable_dac(false);
163
164 for ch in fm.channels() {
165 ch.set_panning(Panning::None, 0, 0);
166 ch.set_key(false);
167
168 for op in ch.operators() {
169 op.set_ssgeg(0);
170 }
171 }
172
173 fm
174 }
175
176 fn write_reg_bank(&self, second: bool, addr: u8, value: u8) {
177 let reg_offset = if second { 2 } else { 0 };
178 unsafe {
179 let base = FM_BASE.offset(reg_offset);
180
181 while (read_volatile(FM_BASE) & 0x80) != 0 {}
183
184 write_volatile(base, addr);
185 write_volatile(base.offset(1), value);
186 }
187 }
188
189 fn write_reg(&self, addr: u8, value: u8) {
190 self.write_reg_bank(false, addr, value);
191 }
192
193 pub fn enable_lfo(&self, rate: Option<LFORate>) {
199 let v = rate.map_or(0, |v| 8 | (u8::from(v) & 7));
200 self.write_reg(FM_LFO, v);
201 }
202
203 pub fn enable_dac(&self, enabled: bool) {
205 let v = if enabled { 0x80 } else { 0 };
206 self.write_reg(FM_DAC_ENABLE, v);
207 }
208
209 pub fn dac_write(&self, v: u8) {
211 self.write_reg(FM_DAC_DATA, v);
212 }
213
214 pub fn set_timer_a(&self, f: u16) {
218 let hi = (f >> 2) as u8;
219 let lo = (f & 3) as u8;
220
221 self.write_reg(FM_TIMER_A_HI, hi);
222 self.write_reg(FM_TIMER_A_LO, lo);
223 }
224
225 pub fn set_timer_b(&self, f: u8) {
229 self.write_reg(FM_TIMER_B, f);
230 }
231
232 pub fn configure_timers(&self, c: TimerConfig) {
234 self.write_reg(FM_TIMER_CTRL, c.0)
235 }
236
237 pub fn timer_status(&self) -> (bool, bool) {
239 let v = unsafe { read_volatile(FM_BASE) };
240 let a = (v & 1) != 0;
241 let b = (v & 2) != 0;
242 (a, b)
243 }
244
245 pub fn channel(&self, channel: u8) -> Channel {
247 Channel(FM, channel & 7)
248 }
249
250 pub fn channels(&self) -> impl Iterator<Item=Channel> {
252 (0..NUM_CHANNELS).map(|c| Channel(FM, c))
253 }
254}
255
256pub struct Channel(FM, u8);
260
261impl Channel {
262 fn write_reg(&self, base: u8, value: u8) {
263 let channel = self.1;
264 let (channel, second) = if channel > 3 {
265 (channel - 3, true)
266 } else {
267 (channel, false)
268 };
269 let addr = base + (channel & 3);
270 self.0.write_reg_bank(second, addr, value);
271 }
272
273 pub fn set_key_raw(&self, operator_mask: u8) {
278 let v = (ALL_CHANNELS[self.1 as usize] & 7) | (operator_mask << 4);
279 self.0.write_reg(FM_KEY_ON, v);
280 }
281
282 pub fn set_key(&self, down: bool) {
284 let mask = if down { 0xf } else { 0 };
285 self.set_key_raw(mask);
286 }
287
288 pub fn set_frequency(&self, frequency: impl Into<u16>, octave: u8) {
295 let frequency = frequency.into();
296 let lo = frequency as u8;
297 let hi = (((frequency >> 8) as u8) & 7) | ((octave & 7) << 3);
298
299 self.write_reg(FM_FREQUENCY_HI, hi);
300 self.write_reg(FM_FREQUENCY_LO, lo);
301 }
302
303 pub fn set_algorithm(&self, algorithm: u8, feedback: u8) {
305 let v = (algorithm & 7) | ((feedback & 7) << 3);
306 self.write_reg(FM_ALGORITHM, v);
307 }
308
309 pub fn set_panning(&self, panning: Panning, ams: u8, fms: u8) {
311 let v = ((panning as u8) << 6) | ((ams & 3) << 4) | (fms & 7);
312 self.write_reg(FM_PANNING, v);
313 }
314
315 pub fn operator(&self, operator: u8) -> Operator {
317 Operator(FM, self.1, operator & 3)
318 }
319
320 pub fn operators(&self) -> impl Iterator<Item=Operator> {
322 let ch = self.1;
323 (0..NUM_OPERATORS).map(move |i| Operator(FM, ch, i))
324 }
325}
326
327pub struct Operator(FM, u8, u8);
331
332impl Operator {
333 fn write_reg(&self, base: u8, value: u8) {
334 let channel = self.1;
335 let op = self.2;
336 let (channel, second) = if channel > 3 {
337 (channel - 3, true)
338 } else {
339 (channel, false)
340 };
341 let addr = base | (channel & 3) | ((op & 3) << 2);
342 self.0.write_reg_bank(second, addr, value);
343 }
344
345 pub fn set_multiplier(&self, multiply: u8, detune: u8) {
349 let v = ((detune & 7) << 4) | (multiply & 0xf);
350 self.write_reg(FM_MULTIPLY, v);
351 }
352
353 pub fn set_total_level(&self, level: u8) {
357 self.write_reg(FM_TOTAL_LEVEL, level & 0x7f);
358 }
359
360 pub fn set_attack_rate(&self, attack_rate: u8, rate_scale: u8) {
368 let v = (attack_rate & 0x1f) | (rate_scale << 6);
369 self.write_reg(FM_ATTACK_RATE, v);
370 }
371
372 pub fn set_decay_rate(&self, decay_rate: u8, amon: bool) {
378 let v = ((amon as u8) << 7) | (decay_rate & 0x1f);
379 self.write_reg(FM_DECAY_RATE, v);
380 }
381
382 pub fn set_sustain_rate(&self, sustain_rate: u8) {
386 let v = sustain_rate & 0x1f;
387 self.write_reg(FM_SUSTAIN_RATE, v);
388 }
389
390 pub fn set_release_rate(&self, release_rate: u8, sustain_level: u8) {
392 let v = (release_rate & 0xf) | ((sustain_level & 0xf) << 4);
393 self.write_reg(FM_RELEASE_RATE, v);
394 }
395
396 pub fn set_frequency_special(&self, frequency: impl Into<u16>, octave: u8) {
400 let frequency = frequency.into();
401 let lo = frequency as u8;
402 let hi = (((frequency >> 8) as u8) & 7) | ((octave & 7) << 3);
403 self.0.write_reg(FM_SPECIAL_FREQUENCY_HI[self.2 as usize], hi);
404 self.0.write_reg(FM_SPECIAL_FREQUENCY_LO[self.2 as usize], lo);
405 }
406
407 fn set_ssgeg(&self, value: u8) {
411 self.write_reg(FM_SSGEG, value);
412 }
413}