use std::env;
use std::fs::OpenOptions;
use std::io::Write;
use std::path::Path;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
enum ADC {
ADC1(i32),
ADC2(i32),
NOADC,
}
macro_rules! print {
($file:ident, $to_write:expr) => {
$file.write(format!($to_write).as_bytes()).unwrap()
};
}
fn main() {
embuild::espidf::sysenv::output();
let esp32_pins: Vec<(i32, ADC)> = vec![
(0, ADC::ADC2(1)),
(1, ADC::NOADC),
(2, ADC::ADC2(2)),
(3, ADC::NOADC),
(4, ADC::ADC2(0)),
(5, ADC::NOADC),
(6, ADC::NOADC),
(7, ADC::NOADC),
(8, ADC::NOADC),
(9, ADC::NOADC),
(10, ADC::NOADC),
(11, ADC::NOADC),
(12, ADC::ADC2(5)),
(13, ADC::ADC2(4)),
(14, ADC::ADC2(6)),
(15, ADC::ADC2(3)),
(16, ADC::NOADC),
(17, ADC::NOADC),
(18, ADC::NOADC),
(19, ADC::NOADC),
(21, ADC::NOADC),
(22, ADC::NOADC),
(23, ADC::NOADC),
(25, ADC::ADC2(8)),
(26, ADC::ADC2(9)),
(27, ADC::ADC2(7)),
(32, ADC::ADC1(4)),
(33, ADC::ADC1(5)),
(34, ADC::ADC1(6)),
(35, ADC::ADC1(7)),
(36, ADC::ADC1(0)),
(37, ADC::ADC1(1)),
(38, ADC::ADC1(2)),
(39, ADC::ADC1(3)),
];
let esp32s2_pins: Vec<(i32, ADC)> = vec![
(0, ADC::NOADC),
(1, ADC::ADC1(0)),
(2, ADC::ADC1(1)),
(3, ADC::ADC1(2)),
(4, ADC::ADC1(3)),
(5, ADC::ADC1(4)),
(6, ADC::ADC1(5)),
(7, ADC::ADC1(6)),
(8, ADC::ADC1(7)),
(9, ADC::ADC1(8)),
(10, ADC::ADC1(9)),
(11, ADC::ADC2(0)),
(12, ADC::ADC2(1)),
(13, ADC::ADC2(2)),
(14, ADC::ADC2(3)),
(15, ADC::ADC2(4)),
(16, ADC::ADC2(5)),
(17, ADC::ADC2(6)),
(18, ADC::ADC2(7)),
(19, ADC::ADC2(8)),
(20, ADC::ADC2(9)),
(21, ADC::NOADC),
(26, ADC::NOADC),
(27, ADC::NOADC),
(28, ADC::NOADC),
(29, ADC::NOADC),
(30, ADC::NOADC),
(31, ADC::NOADC),
(32, ADC::NOADC),
(33, ADC::NOADC),
(34, ADC::NOADC),
(35, ADC::NOADC),
(36, ADC::NOADC),
(37, ADC::NOADC),
(38, ADC::NOADC),
(39, ADC::NOADC),
(40, ADC::NOADC),
(41, ADC::NOADC),
(42, ADC::NOADC),
(43, ADC::NOADC),
(44, ADC::NOADC),
(45, ADC::NOADC),
(46, ADC::NOADC),
(47, ADC::NOADC),
(48, ADC::NOADC),
];
let mut pins_opt = None;
let args = embuild::espidf::sysenv::cfg_args().unwrap().args;
if args.contains(&"esp32".to_string()) {
pins_opt = Some(esp32_pins);
} else if args.contains(&"esp32s3".to_string()) || args.contains(&"esp32s3".to_string()) {
pins_opt = Some(esp32s2_pins);
}
let pins = pins_opt.expect("SoC not supported");
let out_dir = env::var_os("OUT_DIR").unwrap();
let dest_path = Path::new(&out_dir).join("adc.rs");
let mut file = OpenOptions::new()
.create(true)
.truncate(true)
.write(true)
.open(dest_path.clone())
.unwrap();
for (pin, adc) in pins.iter() {
let adc_driver = match adc {
ADC::ADC1(_) => "adc1_driver",
ADC::ADC2(_) => "adc2_driver",
ADC::NOADC => "None",
};
let adc_str = match adc {
ADC::ADC1(_) => "ADC1",
ADC::ADC2(_) => "ADC2",
ADC::NOADC => "None",
};
print!(
file,
"
struct GpioPin{pin}<'a> {{
pub(crate) pin: Gpio{pin},
adc1_driver: Arc<Mutex<Option<AdcDriver<'a, hal::adc::ADC1>>>>,
adc2_driver: Arc<Mutex<Option<AdcDriver<'a, hal::adc::ADC2>>>>,
}}
impl Debug for GpioPin{pin}<'static> {{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {{
todo!()
}}
}}
impl<'a> GpioPin{pin}<'a> {{
fn new(
pin: Gpio{pin},
adc1_driver: Arc<Mutex<Option<AdcDriver<'a, hal::adc::ADC1>>>>,
adc2_driver: Arc<Mutex<Option<AdcDriver<'a, hal::adc::ADC2>>>>,
) -> Self {{
GpioPin{pin} {{
pin,
adc1_driver,
adc2_driver,
}}
}}
}}
unsafe impl Send for GpioPin{pin}<'_> {{}}
unsafe impl Sync for GpioPin{pin}<'_> {{}}
#[async_trait]
impl GpioPin for GpioPin{pin}<'static> {{"
);
if *adc != ADC::NOADC {
print!(file, "
async fn get_adc(&mut self) -> Result<u16, GpioWrapperError> {{
let mut adc_driver = self.{adc_driver}.lock().await;
if adc_driver.is_some() {{
let mut adc_channel_driver: AdcChannelDriver<
{{ hal::adc::attenuation::DB_11 }},
Gpio{pin},
> = AdcChannelDriver::new((&mut self.pin).into_ref()).unwrap();
let readout = adc_driver
.as_mut()
.unwrap()
.read(&mut adc_channel_driver)
.map_err(GpioWrapperError::from);
return readout;
}}
return Err(GpioWrapperError::AdcNotOwned);
}}
async fn get_adc_averaged( &mut self, measurement: MeasurementConfig) -> Result<f32, GpioWrapperError> {{
if measurement.to_measure == 0 {{
return Ok(f32::NAN);
}}
let mut adc_driver = self.{adc_driver}.lock().await;
if adc_driver.is_some() {{
fn helper<const N: u32>(
pin: &mut Gpio{pin},
adc_driver: &mut tokio::sync::MutexGuard<Option<AdcDriver<{adc_str}>>>,
measurement: MeasurementConfig,
) -> Result<f32, GpioWrapperError> {{
let mut adc_channel_driver: AdcChannelDriver<{{ N }}, Gpio{pin}> =
AdcChannelDriver::new((pin).into_ref()).unwrap();
let reader = adc_driver.as_mut().unwrap();
let mut sum = 0.0;
for _ in 0..measurement.to_measure {{
sum += reader
.read(&mut adc_channel_driver)
.map_err(GpioWrapperError::from)? as f32;
}}
return Ok(sum as f32 / measurement.to_measure as f32);
}}
const DB_0: u32 = hal::sys::adc_atten_t_ADC_ATTEN_DB_0;
const DB_2_5: u32 = hal::sys::adc_atten_t_ADC_ATTEN_DB_2_5;
const DB_6: u32 = hal::sys::adc_atten_t_ADC_ATTEN_DB_6;
const DB_11: u32 = hal::sys::adc_atten_t_ADC_ATTEN_DB_11;
const DB_12: u32 = hal::sys::adc_atten_t_ADC_ATTEN_DB_12; //not used
match measurement.attenuation {{
Attenuation::DB0 => {{
return helper::<DB_0>(&mut self.pin, &mut adc_driver, measurement);
//cannot use the constant directly, wtf rust???
}}
Attenuation::DB2_5 => {{
return helper::<DB_2_5>(&mut self.pin, &mut adc_driver, measurement);
}}
Attenuation::DB6 => {{
return helper::<DB_6>(&mut self.pin, &mut adc_driver, measurement);
}}
Attenuation::DB11 => {{
return helper::<DB_11>(&mut self.pin, &mut adc_driver, measurement);
}}
}}
}}
return Err(GpioWrapperError::AdcNotOwned);
}}
"
);
} else {
print!(file, "
async fn get_adc(&mut self) -> Result<u16, GpioWrapperError> {{
Err(GpioWrapperError::NotAnAdcPin)
}}
async fn get_adc_averaged( &mut self, measurement: MeasurementConfig) -> Result<f32, GpioWrapperError> {{
Err(GpioWrapperError::NotAnAdcPin)
}}
");
}
print!(
file,
"
}}
"
);
}
print!(file, "
fn pins_vec(adc1: Option<ADC1>, adc2: Option<ADC2>, pins: Pins) -> Vec<Arc<Mutex<Option<Box<dyn GpioPin>>>>> {{
let adc1_driver = adc1.map(|adc1| {{
AdcDriver::new(adc1, &hal::adc::config::Config::new().calibration(true)).unwrap()
}});
let adc2_driver = adc2.map(|adc2| {{
AdcDriver::new(adc2, &hal::adc::config::Config::new().calibration(true)).unwrap()
}});
let adc1_ref: Arc<Mutex<Option<AdcDriver<ADC1>>>> = Arc::new(Mutex::new(adc1_driver));
let adc2_ref = Arc::new(Mutex::new(adc2_driver));
vec![
");
for i in 0..pins.last().unwrap().0 {
if pins.iter().any(|(pin, _)| *pin == i) {
print!(
file,
"
Arc::new(Mutex::new(Some(Box::new(GpioPin{i}::new(
pins.gpio{i},
adc1_ref.clone(),
adc2_ref.clone(),
))))),"
);
} else {
print!(
file,
"
Arc::new(Mutex::new(None)),"
);
}
}
print!(
file,
"
]
}}
impl GpioWrapper {{
"
);
for (pin, _) in pins.iter() {
print!(
file,
"
pub async fn release_pin{pin}(&mut self) -> Result<Gpio{pin}, GpioWrapperError> {{
let wrapper = self.get_pin({pin}).unwrap();
let mut pin = wrapper.pin.lock().await;
return if let Some(boxed) = pin.take() {{
let x: Box<GpioPin{pin}> = boxed.downcast().unwrap();
Ok(x.pin)
}} else {{
Err(GpioWrapperError::PinNotOwned)
}}
}}
"
);
}
print!(
file,
"
}}
"
);
println!("cargo::rerun-if-changed=build.rs");
}