1use crate::pm::{self, Clock, PBAClock};
13use core::cell::Cell;
14use kernel::hil;
15use kernel::utilities::registers::interfaces::{Readable, Writeable};
16use kernel::utilities::registers::{register_bitfields, ReadOnly, ReadWrite, WriteOnly};
17use kernel::utilities::StaticRef;
18use kernel::ErrorCode;
19
20#[repr(C)]
21pub struct DacRegisters {
22    cr: WriteOnly<u32, Control::Register>, mr: ReadWrite<u32, Mode::Register>,    cdr: WriteOnly<u32, ConversionData::Register>, ier: WriteOnly<u32, InterruptEnable::Register>, idr: WriteOnly<u32, InterruptDisable::Register>, imr: ReadOnly<u32, InterruptMask::Register>, isr: ReadOnly<u32, InterruptStatus::Register>, _reserved0: [u32; 50], wpmr: ReadWrite<u32, WriteProtectMode::Register>, wpsr: ReadOnly<u32, WriteProtectStatus::Register>, _reserved1: [u32; 4], version: ReadOnly<u32, Version::Register>, }
36
37register_bitfields![u32,
38    Control [
39        SWRST 0
40    ],
41
42    Mode [
44        CLKDIV   OFFSET(16)  NUMBITS(16) [],
46        STARTUP  OFFSET( 8)  NUMBITS(8) [],
48        WORD     OFFSET( 5)  NUMBITS(1) [
50            HalfWordTransfer = 0b0,
51            FullWordTransfer = 0b1
52        ],
53        DACEN    OFFSET( 4)  NUMBITS(1) [],
55        TRGSEL   OFFSET( 1)  NUMBITS(3) [
57            ExternalTrigger = 0b000,
58            PeripheralTrigger = 0b001
59        ],
60        TRGEN    OFFSET( 0)  NUMBITS(1) [
62            InternalTrigger = 0b0,
63            ExternalTrigger = 0b1
64        ]
65    ],
66
67    ConversionData [
69        DATA OFFSET(0) NUMBITS(32) []
71    ],
72
73    InterruptEnable [
75        TXRDY 0
77    ],
78
79    InterruptDisable [
81        TXRDY 0
83    ],
84
85    InterruptMask [
87        TXRDY 0
89    ],
90
91    InterruptStatus [
93        TXRDY 0
95    ],
96
97    WriteProtectMode [
99        WPKEY OFFSET(8) NUMBITS(24) [],
101        WPEN OFFSET(0) NUMBITS(1) []
103    ],
104
105    WriteProtectStatus [
107        WPROTADDR OFFSET(8) NUMBITS(8) [],
109        WPROTERR OFFSET(0) NUMBITS(1) []
111    ],
112
113    Version [
115        VARIANT OFFSET(16) NUMBITS(3) [],
116        VERSION OFFSET( 0) NUMBITS(12) []
117    ]
118];
119
120const DAC_BASE: StaticRef<DacRegisters> =
122    unsafe { StaticRef::new(0x4003C000 as *const DacRegisters) };
123
124pub struct Dac {
125    registers: StaticRef<DacRegisters>,
126    enabled: Cell<bool>,
127}
128
129impl Dac {
130    pub const fn new() -> Self {
131        Self {
132            registers: DAC_BASE,
133            enabled: Cell::new(false),
134        }
135    }
136
137    fn initialize(&self) -> Result<(), ErrorCode> {
138        if !self.enabled.get() {
139            self.enabled.set(true);
140
141            pm::enable_clock(Clock::PBA(PBAClock::DACC));
143
144            self.registers.cr.write(Control::SWRST::SET);
146
147            let mr = Mode::WORD::HalfWordTransfer
154                + Mode::STARTUP.val(0xff)
155                + Mode::CLKDIV.val(0x60)
156                + Mode::TRGEN::InternalTrigger
157                + Mode::DACEN::SET;
158            self.registers.mr.write(mr);
159        }
160        Ok(())
161    }
162
163    pub fn handle_interrupt(&self) {}
165}
166
167impl hil::dac::DacChannel for Dac {
168    fn set_value(&self, value: usize) -> Result<(), ErrorCode> {
169        if !self.enabled.get() {
170            self.initialize()?;
171        }
172
173        if !self.registers.isr.is_set(InterruptStatus::TXRDY) {
175            return Err(ErrorCode::BUSY);
176        }
177
178        self.registers
180            .cdr
181            .write(ConversionData::DATA.val(value as u32));
182        Ok(())
183    }
184}