1use crate::clocks::{phclk, Stm32f4Clocks};
6use core::cell::Cell;
7use kernel::hil;
8use kernel::platform::chip::ClockInterface;
9use kernel::utilities::registers::interfaces::{ReadWriteable, Writeable};
10use kernel::utilities::registers::{register_bitfields, ReadWrite, WriteOnly};
11use kernel::utilities::StaticRef;
12use kernel::ErrorCode;
13
14#[repr(C)]
16pub struct DacRegisters {
17    cr: ReadWrite<u32, CR::Register>,
18    swtrigr: WriteOnly<u32, SWTRIGR::Register>,
19    dhr12r1: ReadWrite<u32, DHR12R1::Register>,
20    dhr8r1: ReadWrite<u32, DHR8R1::Register>,
21    dhr12r2: ReadWrite<u32, DHR12R2::Register>,
22    dhr12l2: ReadWrite<u32, DHR12L2::Register>,
23    dhr8r2: ReadWrite<u32, DHR8R2::Register>,
24    dhr12rd: ReadWrite<u32, DHR12RD::Register>,
25    dhr12ld: ReadWrite<u32, DHR12LD::Register>,
26    dhr8rd: ReadWrite<u32, DHR8RD::Register>,
27    dor1: ReadWrite<u32, DOR1::Register>,
28    dor2: ReadWrite<u32, DOR2::Register>,
29}
30
31register_bitfields![u32,
32        CR [
34            DMAUDRIE2 OFFSET(29) NUMBITS(1) [],
36            DMAEN2 OFFSET(28) NUMBITS(1) [],
38            MAMP2 OFFSET(24) NUMBITS(4) [],
40            WAVE2 OFFSET(22) NUMBITS(2) [],
42            TSEL2 OFFSET(19) NUMBITS(3) [],
44            TEN2 OFFSET(18) NUMBITS(1) [],
46            BOFF2 OFFSET(17) NUMBITS(1) [],
48            EN2 OFFSET(16) NUMBITS(1) [],
50            DMAUDRIE1 OFFSET(13) NUMBITS(1) [],
52            DMAEN1 OFFSET(12) NUMBITS(1) [],
54            MAMP1 OFFSET(8) NUMBITS(4) [],
56            WAVE1 OFFSET(6) NUMBITS(2) [],
58            TSEL1 OFFSET(3) NUMBITS(3) [],
60            TEN1 OFFSET(2) NUMBITS(1) [],
62            BOFF1 OFFSET(1) NUMBITS(1) [],
64            EN1 OFFSET(0) NUMBITS(1) [],
66        ],
67        SWTRIGR [
69            SWTRIG2 OFFSET(1) NUMBITS(1) [],
71            SWTRIG1 OFFSET(0) NUMBITS(1) []
73        ],
74        DHR12R1 [
76            DACC1DHR OFFSET(0) NUMBITS(12) []
78        ],
79        DHR8R1 [
81            DACC1DHR OFFSET(0) NUMBITS(8) []
83        ],
84        DHR12R2 [
86            DACC2DHR OFFSET(0) NUMBITS(12) []
88        ],
89        DHR12L2 [
91            DACC2DHR OFFSET(0) NUMBITS(12) []
93        ],
94        DHR8R2 [
96            DACC2DHR OFFSET(0) NUMBITS(8) []
98        ],
99        DHR12RD [
101            DACC2DHR OFFSET(16) NUMBITS(12) [],
103            DACC1DHR OFFSET(0) NUMBITS(12) []
105        ],
106        DHR12LD [
108            DACC2DHR OFFSET(16) NUMBITS(12) [],
110            DACC1DHR OFFSET(0) NUMBITS(12) []
112        ],
113        DHR8RD [
115            DACC2DHR OFFSET(8) NUMBITS(8) [],
117            DACC1DHR OFFSET(0) NUMBITS(8) []
119        ],
120        DOR1 [
122            DACC1DOR OFFSET(0) NUMBITS(12) []
124        ],
125        DOR2 [
127            DACC2DOR OFFSET(0) NUMBITS(12) []
129        ],
130        SR [
132            DMAUDR2 OFFSET(29) NUMBITS(1) [],
134            DMAUDR1 OFFSET(13) NUMBITS(1) []
136        ]
137];
138
139const DAC_BASE: StaticRef<DacRegisters> =
140    unsafe { StaticRef::new(0x40007400 as *const DacRegisters) };
141
142pub struct Dac<'a> {
143    registers: StaticRef<DacRegisters>,
144    clock: DacClock<'a>,
145    initialized: Cell<bool>,
146    enabled: Cell<bool>,
147}
148
149impl<'a> Dac<'a> {
150    pub const fn new(clocks: &'a dyn Stm32f4Clocks) -> Self {
151        Self {
152            registers: DAC_BASE,
153            clock: DacClock(phclk::PeripheralClock::new(
154                phclk::PeripheralClockType::APB1(phclk::PCLK1::DAC),
155                clocks,
156            )),
157            initialized: Cell::new(false),
158            enabled: Cell::new(false),
159        }
160    }
161
162    fn initialize(&self) -> Result<(), ErrorCode> {
163        if !self.is_enabled_clock() {
164            self.enable_clock();
165        }
166
167        self.registers.cr.modify(CR::BOFF1::CLEAR);
169        self.registers.cr.modify(CR::TEN1::CLEAR);
170        self.registers.cr.modify(CR::TSEL1::CLEAR);
171        self.registers.cr.modify(CR::WAVE1::CLEAR);
172        self.registers.cr.modify(CR::MAMP1::CLEAR);
173
174        self.enable();
175
176        Ok(())
177    }
178
179    fn enable(&self) {
180        self.registers.cr.modify(CR::EN1::SET);
181    }
182
183    pub fn handle_interrupt(&self) {}
185
186    fn is_enabled_clock(&self) -> bool {
187        self.clock.is_enabled()
188    }
189
190    fn enable_clock(&self) {
191        self.clock.enable();
192    }
193}
194
195struct DacClock<'a>(phclk::PeripheralClock<'a>);
196
197impl ClockInterface for DacClock<'_> {
198    fn is_enabled(&self) -> bool {
199        self.0.is_enabled()
200    }
201
202    fn enable(&self) {
203        self.0.enable();
204    }
205
206    fn disable(&self) {
207        self.0.disable();
208    }
209}
210
211impl hil::dac::DacChannel for Dac<'_> {
212    fn set_value(&self, value: usize) -> Result<(), ErrorCode> {
213        if !self.initialized.get() {
214            self.initialize()?;
215        }
216
217        if !self.enabled.get() {
218            self.enable();
219        }
220
221        self.registers
222            .dhr12r1
223            .write(DHR12R1::DACC1DHR.val(value as u32));
224        Ok(())
225    }
226}