diff --git a/apis/peripherals/adc/src/lib.rs b/apis/peripherals/adc/src/lib.rs index 8d0e626d1..1229dfb05 100644 --- a/apis/peripherals/adc/src/lib.rs +++ b/apis/peripherals/adc/src/lib.rs @@ -22,10 +22,22 @@ impl Adc { .to_result::() .and(Ok(())) } + //Returns the number of channels + pub fn get_number_of_channels() -> Result { + S::command(DRIVER_NUM, EXISTS, 0, 0) + .to_result::() + .and_then(|number_channels| number_channels.try_into().map_err(|_| ErrorCode::Fail)) + } // Initiate a sample reading - pub fn read_single_sample() -> Result<(), ErrorCode> { - S::command(DRIVER_NUM, SINGLE_SAMPLE, 0, 0).to_result() + pub fn read_single_sample(channel: usize) -> Result<(), ErrorCode> { + S::command( + DRIVER_NUM, + SINGLE_SAMPLE, + (channel as usize).try_into().unwrap(), + 0, + ) + .to_result() } // Register a listener to be called when the ADC conversion is finished @@ -43,14 +55,14 @@ impl Adc { /// Initiates a synchronous ADC conversion /// Returns the converted ADC value or an error - pub fn read_single_sample_sync() -> Result { + pub fn read_single_sample_sync(channel: usize) -> Result { let sample: Cell> = Cell::new(None); let listener = ADCListener(|adc_val| { sample.set(Some(adc_val)); }); share::scope(|subscribe| { Self::register_listener(&listener, subscribe)?; - Self::read_single_sample()?; + Self::read_single_sample(channel)?; while sample.get().is_none() { S::yield_wait(); } @@ -63,21 +75,33 @@ impl Adc { } /// Returns the number of ADC resolution bits - pub fn get_resolution_bits() -> Result { - S::command(DRIVER_NUM, GET_RES_BITS, 0, 0).to_result() + pub fn get_resolution_bits(channel: usize) -> Result { + S::command( + DRIVER_NUM, + GET_RES_BITS, + (channel as usize).try_into().unwrap(), + 0, + ) + .to_result() } /// Returns the reference voltage in millivolts (mV) - pub fn get_reference_voltage_mv() -> Result { - S::command(DRIVER_NUM, GET_VOLTAGE_REF, 0, 0).to_result() + pub fn get_reference_voltage_mv(channel: usize) -> Result { + S::command( + DRIVER_NUM, + GET_VOLTAGE_REF, + (channel as usize).try_into().unwrap(), + 0, + ) + .to_result() } } pub struct ADCListener(pub F); impl Upcall> for ADCListener { - fn upcall(&self, adc_val: u32, _arg1: u32, _arg2: u32) { - self.0(adc_val as u16) + fn upcall(&self, _adc_mode: u32, _channel: u32, sample: u32) { + self.0(sample as u16) } } diff --git a/apis/peripherals/adc/src/tests.rs b/apis/peripherals/adc/src/tests.rs index d27ebc2a7..d54fa16fc 100644 --- a/apis/peripherals/adc/src/tests.rs +++ b/apis/peripherals/adc/src/tests.rs @@ -25,11 +25,13 @@ fn read_single_sample() { let driver = fake::Adc::new(); kernel.add_driver(&driver); - assert_eq!(Adc::read_single_sample(), Ok(())); + let ch = Adc::get_number_of_channels().unwrap(); + + assert_eq!(Adc::read_single_sample(ch), Ok(())); assert!(driver.is_busy()); - assert_eq!(Adc::read_single_sample(), Err(ErrorCode::Busy)); - assert_eq!(Adc::read_single_sample_sync(), Err(ErrorCode::Busy)); + assert_eq!(Adc::read_single_sample(ch), Err(ErrorCode::Busy)); + assert_eq!(Adc::read_single_sample_sync(ch), Err(ErrorCode::Busy)); } #[test] @@ -43,19 +45,21 @@ fn register_unregister_listener() { sample.set(Some(adc_val)); }); share::scope(|subscribe| { - assert_eq!(Adc::read_single_sample(), Ok(())); - driver.set_value(100); + let ch = Adc::get_number_of_channels().unwrap(); + + assert_eq!(Adc::read_single_sample(ch), Ok(())); + driver.set_value(ch.try_into().unwrap(), 100); assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall); assert_eq!(Adc::register_listener(&listener, subscribe), Ok(())); - assert_eq!(Adc::read_single_sample(), Ok(())); - driver.set_value(100); + assert_eq!(Adc::read_single_sample(ch), Ok(())); + driver.set_value(ch.try_into().unwrap(), 100); assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall); assert_eq!(sample.get(), Some(100)); Adc::unregister_listener(); - assert_eq!(Adc::read_single_sample(), Ok(())); - driver.set_value(100); + assert_eq!(Adc::read_single_sample(ch), Ok(())); + driver.set_value(ch.try_into().unwrap(), 100); assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall); }); } @@ -66,6 +70,8 @@ fn read_single_sample_sync() { let driver = fake::Adc::new(); kernel.add_driver(&driver); - driver.set_value_sync(1000); - assert_eq!(Adc::read_single_sample_sync(), Ok(1000)); + let ch = Adc::get_number_of_channels().unwrap(); + + driver.set_value_sync(ch.try_into().unwrap(), 1000); + assert_eq!(Adc::read_single_sample_sync(ch), Ok(1000)); } diff --git a/build_scripts/src/lib.rs b/build_scripts/src/lib.rs index e7185782c..054a322c8 100644 --- a/build_scripts/src/lib.rs +++ b/build_scripts/src/lib.rs @@ -11,7 +11,7 @@ const PLATFORMS: &[(&str, &str, &str, &str, &str)] = &[ ("hifive1" , "0x20040000", "32M" , "0x80003000", "0x01000"), ("imix" , "0x00040000", "0x0040000", "0x20008000", "62K" ), ("imxrt1050" , "0x63002000", "0x1000000", "0x20004000", "112K" ), - ("microbit_v2" , "0x00040000", "256K" , "0x20004000", "112K" ), + ("microbit_v2" , "0x00040000", "256K" , "0x20006000", "112K" ), ("msp432" , "0x00020000", "0x0020000", "0x20004000", "0x02000"), ("nano_rp2040_connect", "0x10020000", "256K" , "0x20004000", "248K" ), ("nrf52" , "0x00030000", "0x0060000", "0x20004000", "62K" ), diff --git a/examples/adc.rs b/examples/adc.rs index 954120c1f..7f3d54fcc 100644 --- a/examples/adc.rs +++ b/examples/adc.rs @@ -19,13 +19,19 @@ fn main() { writeln!(Console::writer(), "adc driver unavailable").unwrap(); return; } - + //getting the number of channels + let Ok(number_channels) = Adc::get_number_of_channels() else { + writeln!(Console::writer(), "can't get number of channels").unwrap(); + return; + }; loop { - match Adc::read_single_sample_sync() { - Ok(adc_val) => writeln!(Console::writer(), "Sample: {}\n", adc_val).unwrap(), - Err(_) => writeln!(Console::writer(), "error while reading sample",).unwrap(), - } + for i in 0..number_channels { + match Adc::read_single_sample_sync(i as usize) { + Ok(adc_val) => writeln!(Console::writer(), "Sample: {}\n", adc_val).unwrap(), + Err(_) => writeln!(Console::writer(), "error while reading sample",).unwrap(), + } - Alarm::sleep_for(Milliseconds(2000)).unwrap(); + Alarm::sleep_for(Milliseconds(2000)).unwrap(); + } } } diff --git a/unittest/src/fake/adc/mod.rs b/unittest/src/fake/adc/mod.rs index 4baf9c591..d393e7a22 100644 --- a/unittest/src/fake/adc/mod.rs +++ b/unittest/src/fake/adc/mod.rs @@ -13,7 +13,7 @@ use std::cell::Cell; // because it was impossible to schedule an upcall during the `synchronous` read in other ways. pub struct Adc { busy: Cell, - upcall_on_command: Cell>, + upcall_on_command: [Cell>; 3], share_ref: DriverShareRef, } @@ -21,7 +21,7 @@ impl Adc { pub fn new() -> std::rc::Rc { std::rc::Rc::new(Adc { busy: Cell::new(false), - upcall_on_command: Cell::new(None), + upcall_on_command: [Cell::new(None), Cell::new(None), Cell::new(None)], share_ref: Default::default(), }) } @@ -29,16 +29,18 @@ impl Adc { pub fn is_busy(&self) -> bool { self.busy.get() } - pub fn set_value(&self, value: i32) { + pub fn set_value(&self, channel: i32, sample: i32) { if self.busy.get() { self.share_ref - .schedule_upcall(0, (value as u32, 0, 0)) + .schedule_upcall(0, (0, channel as u32, sample as u32)) .expect("Unable to schedule upcall"); self.busy.set(false); } } - pub fn set_value_sync(&self, value: i32) { - self.upcall_on_command.set(Some(value)); + pub fn set_value_sync(&self, channel: i32, sample: i32) { + self.upcall_on_command[0].set(Some(0)); + self.upcall_on_command[1].set(Some(channel)); + self.upcall_on_command[2].set(Some(sample)); } } @@ -60,8 +62,12 @@ impl crate::fake::SyscallDriver for Adc { return crate::command_return::failure(ErrorCode::Busy); } self.busy.set(true); - if let Some(val) = self.upcall_on_command.take() { - self.set_value(val); + if let (Some(0), Some(channel), Some(sample)) = ( + self.upcall_on_command[0].take(), + self.upcall_on_command[1].take(), + self.upcall_on_command[2].take(), + ) { + self.set_value(channel, sample); } crate::command_return::success() } diff --git a/unittest/src/fake/adc/tests.rs b/unittest/src/fake/adc/tests.rs index c0153290c..b51ae347b 100644 --- a/unittest/src/fake/adc/tests.rs +++ b/unittest/src/fake/adc/tests.rs @@ -16,11 +16,11 @@ fn command() { Some(ErrorCode::Busy) ); - adc.set_value(100); + adc.set_value(0, 100); assert!(adc.command(SINGLE_SAMPLE, 0, 1).is_success()); - adc.set_value(100); + adc.set_value(0, 100); - adc.set_value_sync(100); + adc.set_value_sync(0, 100); assert!(adc.command(SINGLE_SAMPLE, 0, 1).is_success()); assert!(adc.command(SINGLE_SAMPLE, 0, 1).is_success()); } @@ -39,7 +39,7 @@ fn kernel_integration() { fake::Syscalls::command(DRIVER_NUM, SINGLE_SAMPLE, 0, 0).get_failure(), Some(ErrorCode::Busy) ); - adc.set_value(100); + adc.set_value(0, 100); assert!(fake::Syscalls::command(DRIVER_NUM, SINGLE_SAMPLE, 0, 1).is_success()); let listener = Cell::>::new(None); @@ -48,19 +48,18 @@ fn kernel_integration() { fake::Syscalls::subscribe::<_, _, DefaultConfig, DRIVER_NUM, 0>(subscribe, &listener), Ok(()) ); - - adc.set_value(100); + adc.set_value(0, 100); assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall); assert_eq!(listener.get(), Some((100,))); - adc.set_value(200); + adc.set_value(0, 200); assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::NoUpcall); assert!(fake::Syscalls::command(DRIVER_NUM, SINGLE_SAMPLE, 0, 1).is_success()); - adc.set_value(200); + adc.set_value(0, 200); assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall); - adc.set_value_sync(200); + adc.set_value_sync(0, 200); assert!(fake::Syscalls::command(DRIVER_NUM, SINGLE_SAMPLE, 0, 1).is_success()); assert_eq!(fake::Syscalls::yield_no_wait(), YieldNoWaitReturn::Upcall); });