1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
// Licensed under the Apache License, Version 2.0 or the MIT License.
// SPDX-License-Identifier: Apache-2.0 OR MIT
// Copyright Tock Contributors 2022.

use crate::clocks::{phclk, Stm32f4Clocks};
use core::cell::Cell;
use kernel::hil;
use kernel::platform::chip::ClockInterface;
use kernel::utilities::cells::OptionalCell;
use kernel::utilities::registers::interfaces::{ReadWriteable, Readable};
use kernel::utilities::registers::{register_bitfields, ReadOnly, ReadWrite};
use kernel::utilities::StaticRef;
use kernel::ErrorCode;

#[repr(C)]
struct AdcRegisters {
    sr: ReadWrite<u32, SR::Register>,
    cr1: ReadWrite<u32, CR1::Register>,
    cr2: ReadWrite<u32, CR2::Register>,
    smpr1: ReadWrite<u32, SMPR1::Register>,
    smpr2: ReadWrite<u32, SMPR2::Register>,
    jofr1: ReadWrite<u32, JOFR::Register>,
    jofr2: ReadWrite<u32, JOFR::Register>,
    jofr3: ReadWrite<u32, JOFR::Register>,
    jofr4: ReadWrite<u32, JOFR::Register>,
    htr: ReadWrite<u32, HTR::Register>,
    ltr: ReadWrite<u32, LTR::Register>,
    sqr1: ReadWrite<u32, SQR1::Register>,
    sqr2: ReadWrite<u32, SQR2::Register>,
    sqr3: ReadWrite<u32, SQR3::Register>,
    jsqr: ReadWrite<u32, JSQR::Register>,
    jdr1: ReadOnly<u32, JDR::Register>,
    jdr2: ReadOnly<u32, JDR::Register>,
    jdr3: ReadOnly<u32, JDR::Register>,
    jdr4: ReadOnly<u32, JDR::Register>,
    dr: ReadOnly<u32, DR::Register>,
}

#[repr(C)]
struct AdcCommonRegisters {
    csr: ReadOnly<u32, CSR::Register>,
    ccr: ReadWrite<u32, CCR::Register>,
}

register_bitfields![u32,
    /// Status register
    SR [
        /// Overrun
        OVR OFFSET(5) NUMBITS(1) [],
        /// Regular channel start flag
        STRT OFFSET(4) NUMBITS(1) [],
        /// Injected channel start flag
        JSTRT OFFSET(3) NUMBITS(1) [],
        /// Injected channel end of conversion
        JEOC OFFSET(2) NUMBITS(1) [],
        /// Regular channel end of conversion
        EOC OFFSET(1) NUMBITS(1) [],
        /// Analog watchdog flag
        AWD OFFSET(0) NUMBITS(1) []
    ],
    /// Control register 1
    CR1 [
        /// Overrun interrupt enable
        OVRIE OFFSET(26) NUMBITS(1) [],
        /// Resolution
        RES OFFSET(24) NUMBITS(2) [],
        /// Analog watchdog enable on regular channels
        AWDEN OFFSET(23) NUMBITS(1) [],
        /// Analog watchdog enable on injected channels
        JAWDEN OFFSET(22) NUMBITS(1) [],
        /// Discontinuous mode channel count
        DISCNUM OFFSET(13) NUMBITS(3) [],
        /// Discontinuous mode on injected channels
        JDISCEN OFFSET(12) NUMBITS(1) [],
        /// Discontinuous mode on regular channels
        DISCEN OFFSET(11) NUMBITS(1) [],
        /// Automatic injected group conversion
        JAUTO OFFSET(10) NUMBITS(1) [],
        /// Enable the watchdog on a single channel in scan mode
        AWDSGL OFFSET(9) NUMBITS(1) [],
        /// Scan mode
        SCAN OFFSET(8) NUMBITS(1) [],
        /// Interrupt enable for injected channels
        JEOCIE OFFSET(7) NUMBITS(1) [],
        /// Analog watchdog interrupt enable
        AWDIE OFFSET(6) NUMBITS(1) [],
        /// Interrupt enable for EOC
        EOCIE OFFSET(5) NUMBITS(1) [],
        /// Analog watchdog channel select bits
        AWDCH OFFSET(0) NUMBITS(4) []
    ],
    /// Control register 2
    CR2 [
        /// Start conversion of regular channels
        SWSTART OFFSET(30) NUMBITS(1) [],
        /// External trigger enable for regular channels
        EXTEN OFFSET(28) NUMBITS(2) [],
        /// External event select for regular group
        EXTSEL OFFSET(24) NUMBITS(4) [],
        /// Start conversion of injected channels
        JSWSTART OFFSET(22) NUMBITS(1) [],
        /// External trigger enable for injected channels
        JEXTEN OFFSET(20) NUMBITS(2) [],
        /// External event select for injected group
        JEXTSEL OFFSET(16) NUMBITS(4) [],
        /// Data alignment
        ALIGN OFFSET(11) NUMBITS(1) [],
        /// End of conversion selection
        EOCS OFFSET(10) NUMBITS(1) [],
        /// DMA disable selection (for single ADC mode)
        DDS OFFSET(9) NUMBITS(1) [],
        /// Direct memory access mode (for single ADC mode)
        DMA OFFSET(8) NUMBITS(1) [],
        /// Continuous conversion
        CONT OFFSET(1) NUMBITS(1) [],
        /// A/D Converter ON / OFF
        ADON OFFSET(0) NUMBITS(1) []
    ],
    /// Sample time register 1
    SMPR1 [
        /// Channel x sampling time selection
        SMP18 OFFSET(24) NUMBITS(3) [],
        SMP17 OFFSET(21) NUMBITS(3) [],
        SMP16 OFFSET(18) NUMBITS(3) [],
        SMP15 OFFSET(15) NUMBITS(3) [],
        SMP14 OFFSET(12) NUMBITS(3) [],
        SMP13 OFFSET(9) NUMBITS(3) [],
        SMP12 OFFSET(6) NUMBITS(3) [],
        SMP11 OFFSET(3) NUMBITS(3) [],
        SMP10 OFFSET(0) NUMBITS(3) []
    ],
    /// Sample time register 2
    SMPR2 [
        /// Channel x sampling time selection
        SMP9 OFFSET(27) NUMBITS(3) [],
        SMP8 OFFSET(24) NUMBITS(3) [],
        SMP7 OFFSET(21) NUMBITS(3) [],
        SMP6 OFFSET(18) NUMBITS(3) [],
        SMP5 OFFSET(15) NUMBITS(3) [],
        SMP4 OFFSET(12) NUMBITS(3) [],
        SMP3 OFFSET(9) NUMBITS(3) [],
        SMP2 OFFSET(6) NUMBITS(3) [],
        SMP1 OFFSET(3) NUMBITS(3) [],
        SMP0 OFFSET(0) NUMBITS(3) []
    ],
    /// injected channel data offsetregister x
    JOFR [
        /// Data offsetfor injected channel x
        JOFFSET OFFSET(0) NUMBITS(12) []
    ],
    /// Watchdog higher threshold register
    HTR [
        /// Analog watchdog higher threshold
        HT OFFSET(0) NUMBITS(12) []
    ],
    /// Watchdog lower threshold register
    LTR [
        /// Analog watchdog lower threshold
        LT OFFSET(0) NUMBITS(12) []
    ],
    /// Regular sequence register 1
    SQR1 [
        /// Regular channel sequence length
        L OFFSET(20) NUMBITS(3) [],
        /// 16th conversion in regular sequence
        SQ16 OFFSET(15) NUMBITS(5) [],
        /// 15th conversion in regular sequence
        SQ15 OFFSET(10) NUMBITS(5) [],
        /// 14th conversion in regular sequence
        SQ14 OFFSET(5) NUMBITS(5) [],
        /// 13th conversion in regular sequence
        SQ13 OFFSET(0) NUMBITS(5) []
    ],
    /// Regular sequence register 2
    SQR2 [
        /// 12th conversion in regular sequence
        SQ12 OFFSET(25) NUMBITS(5) [],
        /// 11th conversion in regular sequence
        SQ11 OFFSET(20) NUMBITS(5) [],
        /// 10th conversion in regular sequence
        SQ10 OFFSET(15) NUMBITS(5) [],
        /// 9th conversion in regular sequence
        SQ9 OFFSET(10) NUMBITS(5) [],
        /// 8th conversion in regular sequence
        SQ8 OFFSET(5) NUMBITS(5) [],
        /// 7th conversion in regular sequence
        SQ7 OFFSET(0) NUMBITS(5) []
    ],
    /// Regular sequence register 3
    SQR3 [
        /// 6th conversion in regular sequence
        SQ6 OFFSET(25) NUMBITS(5) [],
        /// 5th conversion in regular sequence
        SQ5 OFFSET(20) NUMBITS(5) [],
        /// 4th conversion in regular sequence
        SQ4 OFFSET(15) NUMBITS(5) [],
        /// 3rd conversion in regular sequence
        SQ3 OFFSET(10) NUMBITS(5) [],
        /// 2nd conversion in regular sequence
        SQ2 OFFSET(5) NUMBITS(5) [],
        /// 1st conversion in regular sequence
        SQ1 OFFSET(0) NUMBITS(5) []
    ],
    /// Injected sequence register
    JSQR [
        /// Note:  When JL[1:0]=3 (4 injected conversions in the sequencer), the ADC converts the channels
        ///      in the following order: JSQ1[4:0], JSQ2[4:0], JSQ3[4:0], and JSQ4[4:0].
        ///      When JL=2 (3 injected conversions in the sequencer), the ADC converts the channels in the
        ///      following order: JSQ2[4:0], JSQ3[4:0], and JSQ4[4:0].
        ///      When JL=1 (2 injected conversions in the sequencer), the ADC converts the channels in
        ///      starting from JSQ3[4:0], and then JSQ4[4:0].
        ///      When JL=0 (1 injected conversion in the sequencer), the ADC converts only JSQ4[4:0]
        ///      channel.
        /// Injected sequence length
        JL OFFSET(20) NUMBITS(2) [],
        /// 4th conversion in injected sequence
        JSQ4 OFFSET(15) NUMBITS(5) [],
        /// 3rd conversion in injected sequence
        JSQ3 OFFSET(15) NUMBITS(5) [],
        /// 2nd conversion in injected sequence
        JSQ2 OFFSET(15) NUMBITS(5) [],
        /// 1st conversion in injected sequence
        JSQ1 OFFSET(15) NUMBITS(5) []
    ],
    /// Injected data register x
    JDR [
        /// Injected data
        JDATA OFFSET(0) NUMBITS(16) []
    ],
    /// Regular data register
    DR [
        /// Regular data
        DATA OFFSET(0) NUMBITS(16) []
    ],
    /// Common status register
    CSR [
        /// Overrun flag of ADC1
        OVR1 OFFSET(5) NUMBITS(1) [],
        /// Regular channel Start flag of ADC1
        STRT1 OFFSET(4) NUMBITS(1) [],
        /// Injected channel Start flag of ADC1
        JSTRT1 OFFSET(3) NUMBITS(1) [],
        /// Injected channel end of conversion of ADC1
        JEOC1 OFFSET(2) NUMBITS(1) [],
        /// End of conversion of ADC1
        EOC1 OFFSET(1) NUMBITS(1) [],
        /// Analog watchdog flag of ADC1
        AWD1 OFFSET(0) NUMBITS(1) []
    ],
    /// Common control register
    CCR [
        /// Temperature sensor and VREFINT enable
        TSVREFE OFFSET(23) NUMBITS(1) [],
        /// VBAT enable
        VBATE OFFSET(22) NUMBITS(1) [],
        /// ADC prescaler
        ADCPRE OFFSET(16) NUMBITS(2) []
    ]
];

const ADC1_BASE: StaticRef<AdcRegisters> =
    unsafe { StaticRef::new(0x4001_2000 as *const AdcRegisters) };

const ADC_COMMON_BASE: StaticRef<AdcCommonRegisters> =
    unsafe { StaticRef::new(0x4001_2300 as *const AdcCommonRegisters) };

#[allow(dead_code)]
#[repr(u32)]
#[derive(Copy, Clone, PartialEq)]
pub enum Channel {
    Channel0 = 0b00000,
    Channel1 = 0b00001,
    Channel2 = 0b00010,
    Channel3 = 0b00011,
    Channel4 = 0b00100,
    Channel5 = 0b00101,
    Channel6 = 0b00110,
    Channel7 = 0b00111,
    Channel8 = 0b01000,
    Channel9 = 0b01001,
    Channel10 = 0b01010,
    Channel11 = 0b01011,
    Channel12 = 0b01100,
    Channel13 = 0b01101,
    Channel14 = 0b01110,
    Channel15 = 0b01111,
    Channel16 = 0b10000,
    Channel17 = 0b10001,
    Channel18 = 0b10010,
}

#[allow(dead_code)]
#[repr(u32)]
enum DataResolution {
    Bit12 = 0b00,
    Bit10 = 0b01,
    Bit8 = 0b10,
    Bit6 = 0b11,
}

#[derive(Copy, Clone, PartialEq)]
enum ADCStatus {
    Idle,
    Off,
    OneSample,
}

pub struct Adc<'a> {
    registers: StaticRef<AdcRegisters>,
    common_registers: StaticRef<AdcCommonRegisters>,
    clock: AdcClock<'a>,
    status: Cell<ADCStatus>,
    client: OptionalCell<&'a dyn hil::adc::Client>,
}

impl<'a> Adc<'a> {
    pub const fn new(clocks: &'a dyn Stm32f4Clocks) -> Adc {
        Adc {
            registers: ADC1_BASE,
            common_registers: ADC_COMMON_BASE,
            clock: AdcClock(phclk::PeripheralClock::new(
                phclk::PeripheralClockType::APB2(phclk::PCLK2::ADC1),
                clocks,
            )),
            status: Cell::new(ADCStatus::Off),
            client: OptionalCell::empty(),
        }
    }

    pub fn enable(&self) {
        // Enable adc clock
        self.enable_clock();

        // Enable ADC
        self.registers.cr2.modify(CR2::ADON::SET);

        // set idle state
        self.status.set(ADCStatus::Idle);
    }

    pub fn handle_interrupt(&self) {
        // Check if regular group conversion ended
        if self.registers.sr.is_set(SR::EOC) {
            // Clear interrupt
            self.registers.cr1.modify(CR1::EOCIE::CLEAR);
            if self.status.get() == ADCStatus::OneSample {
                // set state
                self.status.set(ADCStatus::Idle);
            }
            self.client
                .map(|client| client.sample_ready((self.registers.dr.read(DR::DATA) as u16) << 4));
        }
    }

    pub fn is_enabled_clock(&self) -> bool {
        self.clock.is_enabled()
    }

    pub fn enable_clock(&self) {
        self.clock.enable();
    }

    pub fn disable_clock(&self) {
        self.clock.disable();
    }

    pub fn enable_temperature(&self) {
        self.common_registers.ccr.modify(CCR::TSVREFE::SET);
    }
}

struct AdcClock<'a>(phclk::PeripheralClock<'a>);

impl ClockInterface for AdcClock<'_> {
    fn is_enabled(&self) -> bool {
        self.0.is_enabled()
    }

    fn enable(&self) {
        self.0.enable();
    }

    fn disable(&self) {
        self.0.disable();
    }
}

impl<'a> hil::adc::Adc<'a> for Adc<'a> {
    type Channel = Channel;

    fn sample(&self, channel: &Self::Channel) -> Result<(), ErrorCode> {
        if self.status.get() == ADCStatus::Off {
            self.enable();
        }
        if *channel as u32 == 18 {
            self.enable_temperature();
        }
        if self.status.get() == ADCStatus::Idle {
            self.status.set(ADCStatus::OneSample);
            self.registers.sqr1.modify(SQR1::L.val(0b0000));
            self.registers.sqr3.modify(SQR3::SQ1.val(*channel as u32));
            self.registers.cr1.modify(CR1::EOCIE::SET);
            self.registers.cr2.modify(CR2::SWSTART::SET);
            Ok(())
        } else {
            Err(ErrorCode::BUSY)
        }
    }

    fn sample_continuous(
        &self,
        _channel: &Self::Channel,
        _frequency: u32,
    ) -> Result<(), ErrorCode> {
        Err(ErrorCode::NOSUPPORT)
    }

    fn stop_sampling(&self) -> Result<(), ErrorCode> {
        Err(ErrorCode::NOSUPPORT)
    }

    fn get_resolution_bits(&self) -> usize {
        12
    }

    fn get_voltage_reference_mv(&self) -> Option<usize> {
        Some(3300)
    }

    fn set_client(&self, client: &'a dyn hil::adc::Client) {
        self.client.set(client);
    }
}

/// Not yet supported
impl<'a> hil::adc::AdcHighSpeed<'a> for Adc<'a> {
    /// Capture buffered samples from the ADC continuously at a given
    /// frequency, calling the client whenever a buffer fills up. The client is
    /// then expected to either stop sampling or provide an additional buffer
    /// to sample into. Note that due to hardware constraints the maximum
    /// frequency range of the ADC is from 187 kHz to 23 Hz (although its
    /// precision is limited at higher frequencies due to aliasing).
    ///
    /// - `channel`: the ADC channel to sample
    /// - `frequency`: frequency to sample at
    /// - `buffer1`: first buffer to fill with samples
    /// - `length1`: number of samples to collect (up to buffer length)
    /// - `buffer2`: second buffer to fill once the first is full
    /// - `length2`: number of samples to collect (up to buffer length)
    fn sample_highspeed(
        &self,
        _channel: &Self::Channel,
        _frequency: u32,
        buffer1: &'static mut [u16],
        _length1: usize,
        buffer2: &'static mut [u16],
        _length2: usize,
    ) -> Result<(), (ErrorCode, &'static mut [u16], &'static mut [u16])> {
        Err((ErrorCode::NOSUPPORT, buffer1, buffer2))
    }

    /// Provide a new buffer to send on-going buffered continuous samples to.
    /// This is expected to be called after the `samples_ready` callback.
    ///
    /// - `buf`: buffer to fill with samples
    /// - `length`: number of samples to collect (up to buffer length)
    fn provide_buffer(
        &self,
        buf: &'static mut [u16],
        _length: usize,
    ) -> Result<(), (ErrorCode, &'static mut [u16])> {
        Err((ErrorCode::NOSUPPORT, buf))
    }

    /// Reclaim buffers after the ADC is stopped.
    /// This is expected to be called after `stop_sampling`.
    fn retrieve_buffers(
        &self,
    ) -> Result<(Option<&'static mut [u16]>, Option<&'static mut [u16]>), ErrorCode> {
        Err(ErrorCode::NOSUPPORT)
    }

    fn set_highspeed_client(&self, _client: &'a dyn hil::adc::HighSpeedClient) {}
}