From 148f1c7a4e0aa1ddf379e7d5dfc46eabc99cfa90 Mon Sep 17 00:00:00 2001 From: occheung Date: Fri, 4 Sep 2020 17:02:05 +0800 Subject: [PATCH] scpi: customise scpi tree macro --- examples/ethernet.rs | 65 +++--------------------------- src/scpi.rs | 95 +++++++++++++++++++++++++++++++++++++++----- 2 files changed, 90 insertions(+), 70 deletions(-) diff --git a/examples/ethernet.rs b/examples/ethernet.rs index 9a6ee16..ee7d82b 100644 --- a/examples/ethernet.rs +++ b/examples/ethernet.rs @@ -76,8 +76,9 @@ use firmware::{ cpld::{ CPLD, }, - scpi::{ HelloWorldCommand, Channel1SwitchCommand }, + scpi::{ HelloWorldCommand, Channel1SwitchCommand}, Urukul, + scpi_root, recursive_scpi_tree }; use scpi::prelude::*; use scpi::ieee488::commands::*; @@ -99,7 +100,6 @@ use scpi::{ scpi_crate_version, scpi_status, scpi_system, - scpi_tree, }; /// Configure SYSTICK for 1ms timebase @@ -295,63 +295,10 @@ fn main() -> ! { .finalize(); // SCPI configs - - // TODO: String for *idn? mandated command - - // SCPI tree - let tree = scpi_tree![ - // Create default IEEE488 mandated commands - ieee488_cls!(), - ieee488_ese!(), - ieee488_esr!(), - // ieee488_idn!(b"manufacturer", b"model", b"serial", "0.1.2".as_bytes()), - ieee488_opc!(), - ieee488_rst!(), - ieee488_sre!(), - ieee488_stb!(), - ieee488_tst!(), - ieee488_wai!(), - // Create default SCPI mandated STATus subsystem - scpi_status!(), - // Create default SCPI mandated SYSTem subsystem - scpi_system!(), - // - scpi_crate_version!(), - //Test - Node { - name: b"EXAMple", - optional: true, - handler: None, - sub: &[ - Node { - name: b"HELLO", - optional: false, - handler: None, - sub: &[ - Node { - name: b"WORLD", - optional: true, - handler: Some(&HelloWorldCommand {}), - sub: &[], - } - ], - }, - ], - }, - Node { - name: b"CHANNEL1", - optional: false, - handler: None, - sub: &[ - Node { - name: b"SWitch", - optional: false, - handler: Some(&Channel1SwitchCommand {}), - sub: &[], - } - ], - } - ]; + let tree = scpi_root!( + ["EXAMple"] => {"HELLO" => {"WORLD" => HelloWorldCommand}}; + "CHANNEL1" => {"SWitch" => Channel1SwitchCommand} + ); // Device was declared in prior let mut errors = ArrayErrorQueue::<[Error; 10]>::new(); diff --git a/src/scpi.rs b/src/scpi.rs index 8593ecc..ce7a202 100644 --- a/src/scpi.rs +++ b/src/scpi.rs @@ -6,6 +6,7 @@ use scpi::prelude::*; use scpi::NumericValues; use core::convert::{TryFrom, TryInto}; +use core::str; use scpi::ieee488::commands::*; use scpi::scpi::commands::*; use scpi::{ @@ -25,7 +26,6 @@ use scpi::{ scpi_crate_version, scpi_status, scpi_system, - scpi_tree, }; use embedded_hal::blocking::spi::Transfer; @@ -33,7 +33,89 @@ use cortex_m_semihosting::hprintln; use crate::{Urukul, UrukulTraits, Error as UrukulError}; -// pub struct MyDevice; +#[macro_export] +macro_rules! recursive_scpi_tree { + // Handle optional headers (end-node) + ([$header_name: expr] => $handler: ident) => { + Node { + name: str::as_bytes($header_name), + handler: Some(&$handler{}), + sub: &[], + optional: true, + } + }; + + // Handle non-optinal header (end-node) + ($header_name: expr => $handler: ident) => { + Node { + name: str::as_bytes($header_name), + handler: Some(&$handler{}), + sub: &[], + optional: false, + } + }; + + // Handle optional header with sub-commands + ([$header_name: expr] => {$($($rest: tt)=>*);*}) => { + Node { + name: str::as_bytes($header_name), + handler: None, + sub: &[ + $( + recursive_scpi_tree!($($rest)=>*), + )* + ], + optional: true, + } + }; + + // Handle non-optional header with sub-commands + ($header_name: expr => {$($($rest: tt)=>*);*}) => { + Node { + name: str::as_bytes($header_name), + handler: None, + sub: &[ + $( + recursive_scpi_tree!($($rest)=>*), + )* + ], + optional: false, + } + }; +} + +#[macro_export] +macro_rules! scpi_root { + ($($($node: tt)=>*);*) => { + &Node { + name: b"ROOT", + optional: false, + handler: None, + sub: &[ + // Create default IEEE488 mandated commands + ieee488_cls!(), + ieee488_ese!(), + ieee488_esr!(), + ieee488_idn!(b"manufacturer", b"model", b"serial", b"0.1.2"), + ieee488_opc!(), + ieee488_rst!(), + ieee488_sre!(), + ieee488_stb!(), + ieee488_tst!(), + ieee488_wai!(), + // Create default SCPI mandated STATus subsystem + scpi_status!(), + // Create default SCPI mandated SYSTem subsystem + scpi_system!(), + // + scpi_crate_version!(), + $( + recursive_scpi_tree!($($node)=>*), + )* + ] + } + }; +} pub struct HelloWorldCommand {} impl Command for HelloWorldCommand { @@ -72,15 +154,6 @@ impl Command for Channel1SwitchCommand { } } -// pub struct SwitchCnannelCommand {} -// impl Command for SwitchChannelCommand { -// nquery!(); - -// fn event(&self, context: &mut Context, args: &mut Tokenizer) -> Result<()> { - -// } -// } - /* * Implement "Device" trait from SCPI * TODO: Implement mandatory commands