mirror of
https://github.com/mytechnotalent/Embedded-Hacking.git
synced 2026-05-17 21:44:45 +02:00
124 lines
3.4 KiB
Rust
124 lines
3.4 KiB
Rust
//! @file adc.rs
|
||
//! @brief Implementation of the 12-bit ADC driver (pure-logic helpers)
|
||
//! @author Kevin Thomas
|
||
//! @date 2025
|
||
//!
|
||
//! MIT License
|
||
//!
|
||
//! Copyright (c) 2025 Kevin Thomas
|
||
//!
|
||
//! Permission is hereby granted, free of charge, to any person obtaining a copy
|
||
//! of this software and associated documentation files (the "Software"), to deal
|
||
//! in the Software without restriction, including without limitation the rights
|
||
//! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||
//! copies of the Software, and to permit persons to whom the Software is
|
||
//! furnished to do so, subject to the following conditions:
|
||
//!
|
||
//! The above copyright notice and this permission notice shall be included in
|
||
//! all copies or substantial portions of the Software.
|
||
//!
|
||
//! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
//! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
//! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||
//! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||
//! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||
//! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||
//! SOFTWARE.
|
||
|
||
/// ADC reference voltage in millivolts.
|
||
pub const ADC_VREF_MV: u32 = 3300;
|
||
|
||
/// ADC full-scale value for 12-bit resolution.
|
||
pub const ADC_FULL_SCALE: u32 = 4095;
|
||
|
||
/// Convert a raw 12-bit ADC value to millivolts.
|
||
///
|
||
/// Scales the raw value linearly against the 3.3 V reference.
|
||
///
|
||
/// # Arguments
|
||
///
|
||
/// * `raw` - 12-bit ADC conversion result (0–4095).
|
||
///
|
||
/// # Returns
|
||
///
|
||
/// Equivalent voltage in millivolts (0–3300).
|
||
pub fn raw_to_mv(raw: u16) -> u32 {
|
||
raw as u32 * ADC_VREF_MV / ADC_FULL_SCALE
|
||
}
|
||
|
||
/// Convert a raw temperature-sensor ADC value to degrees Celsius.
|
||
///
|
||
/// Applies the RP2350 datasheet formula:
|
||
/// T = 27 - (V - 0.706) / 0.001721
|
||
///
|
||
/// # Arguments
|
||
///
|
||
/// * `raw` - 12-bit ADC result from the internal temperature sensor (channel 4).
|
||
///
|
||
/// # Returns
|
||
///
|
||
/// Die temperature in degrees Celsius.
|
||
pub fn raw_to_celsius(raw: u16) -> f32 {
|
||
let voltage = raw as f32 * 3.3f32 / ADC_FULL_SCALE as f32;
|
||
27.0f32 - (voltage - 0.706f32) / 0.001721f32
|
||
}
|
||
|
||
#[cfg(test)]
|
||
mod tests {
|
||
use super::*;
|
||
|
||
#[test]
|
||
fn raw_to_mv_zero() {
|
||
assert_eq!(raw_to_mv(0), 0);
|
||
}
|
||
|
||
#[test]
|
||
fn raw_to_mv_full_scale() {
|
||
assert_eq!(raw_to_mv(4095), 3300);
|
||
}
|
||
|
||
#[test]
|
||
fn raw_to_mv_half() {
|
||
let mv = raw_to_mv(2048);
|
||
assert!(mv >= 1649 && mv <= 1651);
|
||
}
|
||
|
||
#[test]
|
||
fn raw_to_mv_quarter() {
|
||
let mv = raw_to_mv(1024);
|
||
assert!(mv >= 824 && mv <= 826);
|
||
}
|
||
|
||
#[test]
|
||
fn raw_to_celsius_room_temp() {
|
||
let temp = raw_to_celsius(876);
|
||
assert!(temp > 20.0 && temp < 35.0);
|
||
}
|
||
|
||
#[test]
|
||
fn raw_to_celsius_known_voltage() {
|
||
let raw = (0.706f32 / 3.3f32 * ADC_FULL_SCALE as f32 + 0.5f32) as u16;
|
||
let temp = raw_to_celsius(raw);
|
||
assert!((temp - 27.0).abs() < 1.0);
|
||
}
|
||
|
||
#[test]
|
||
fn raw_to_celsius_higher_voltage() {
|
||
let temp_low = raw_to_celsius(1000);
|
||
let temp_high = raw_to_celsius(800);
|
||
assert!(temp_high > temp_low);
|
||
}
|
||
|
||
#[test]
|
||
fn raw_to_mv_one_count() {
|
||
assert_eq!(raw_to_mv(1), 0);
|
||
}
|
||
|
||
#[test]
|
||
fn raw_to_mv_ten_counts() {
|
||
assert_eq!(raw_to_mv(10), 8);
|
||
}
|
||
}
|
||
|
||
// End of file
|