Skip to content

Commit

Permalink
Add ADC example, simplify OneShot implementation
Browse files Browse the repository at this point in the history
The previous generic implementation of OneShot would force you to always define the type of the output to disambiguate. Since `adc_get_result()` always returns a u16 just implement OneShot for u16.
  • Loading branch information
RossPorter506 committed Jan 16, 2025
1 parent 218832c commit 670d7a3
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 4 deletions.
68 changes: 68 additions & 0 deletions examples/adc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#![no_main]
#![no_std]

use embedded_hal::{adc::OneShot, digital::v2::*};
use msp430_rt::entry;
use msp430fr2x5x_hal::{
adc::{AdcConfig, ClockDivider, Predivider, Resolution, SampleTime, SamplingRate},
gpio::Batch,
pmm::Pmm,
watchdog::Wdt,
};
use nb::block;
use panic_msp430 as _;

// If pin 1.1 is between 1V and 2V, the LED on pin 1.0 should light up.
#[entry]
fn main() -> ! {
// Take peripherals and disable watchdog
let periph = msp430fr2355::Peripherals::take().unwrap();
let _wdt = Wdt::constrain(periph.WDT_A);

// Configure GPIO
let pmm = Pmm::new(periph.PMM);
let port1 = Batch::new(periph.P1).split(&pmm);
let mut led = port1.pin0.to_output();
let mut adc_pin = port1.pin1.to_alternate3();

// ADC setup
let mut adc = AdcConfig::new(
ClockDivider::_1,
Predivider::_1,
Resolution::_8BIT,
SamplingRate::_50KSPS,
SampleTime::_4,
)
.use_modclk()
.configure(periph.ADC);

adc.enable();

loop {
// Get ADC count
// .read() is infallible besides nb::WouldBlock, so it's safe to unwrap after block!()
let count = block!( adc.read(&mut adc_pin) ).unwrap();
let reading_mv = count_to_mv_8bit(count);

// Turn on LED if voltage between 1000 and 2000mV
if (1000..=2000).contains(&reading_mv) {
led.set_high().ok();
} else {
led.set_low().ok();
}
}
}

fn count_to_mv_8bit(count: u16) -> u16 {
const REF_MV: u32 = 3300;
const RESOLUTION: u32 = 256;
((count as u32 * REF_MV) / RESOLUTION) as u16
}

// The compiler will emit calls to the abort() compiler intrinsic if debug assertions are
// enabled (default for dev profile). MSP430 does not actually have meaningful abort() support
// so for now, we create our own in each application where debug assertions are present.
#[no_mangle]
extern "C" fn abort() -> ! {
panic!();
}
7 changes: 3 additions & 4 deletions src/adc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -374,23 +374,22 @@ fn disable_adc_reg(adc: &mut ADC) {
}
}

impl<WORD, PIN> OneShot<Adc, WORD, PIN> for Adc
impl<PIN> OneShot<Adc, u16, PIN> for Adc
where
WORD: From<u16>,
PIN: Channel<Self, ID = u8>,
{
type Error = Infallible; // Only returns WouldBlock

/// Begins a single ADC conversion if one is not already underway.
///
/// If the result is ready it is returned, otherwise returns `WouldBlock`
fn read(&mut self, pin: &mut PIN) -> nb::Result<WORD, Self::Error> {
fn read(&mut self, pin: &mut PIN) -> nb::Result<u16, Self::Error> {
if self.is_waiting {
if self.adc_is_busy() {
return Err(nb::Error::WouldBlock);
} else {
self.is_waiting = false;
return Ok(self.adc_get_result().into());
return Ok(self.adc_get_result());
}
}
self.disable();
Expand Down

0 comments on commit 670d7a3

Please sign in to comment.