Skip to main content

embedded_uart_config/
embedded_uart_config.rs

1/***************************************************************************
2 *
3 * AT Command Parser
4 * Copyright (C) 2026 Antonio Salsi <passy.linux@zresa.it>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <https://www.gnu.org/licenses/>.
18 *
19 ***************************************************************************/
20
21//! Example: AT command table with UART and device configuration handling
22//!
23//! **Note**: This is a pattern demonstration example showing how to implement
24//! configuration commands in no_std/embedded environments. It illustrates
25//! the `AtContext` trait implementation for device-specific commands.
26//!
27//! In a real embedded application, replace the dummy UART implementation
28//! with your platform's actual hardware abstraction layer (HAL).
29
30#![allow(dead_code)]
31#![no_std]
32#![no_main]
33
34extern crate at_parser_rs;
35
36use at_parser_rs::{Args, AtError, AtResult, Bytes};
37use at_parser_rs::context::AtContext;
38
39const SIZE: usize = 64;
40
41// UART struct with AtContext implementation for UARTSEND command
42struct DummyUart {
43    baudrate: u32,
44    mode: u8,
45}
46
47impl DummyUart {
48    const fn new() -> Self {
49        Self { baudrate: 9600, mode: 0 }
50    }
51    
52    fn write(&self, data: &str) {
53        // In real embedded, this would send data over UART
54        let _ = data;
55    }
56}
57
58impl AtContext<SIZE> for DummyUart {
59    fn exec(&self) -> AtResult<SIZE> {
60        // Not supported for UARTSEND
61        Err(AtError::NotSupported)
62    }
63    fn set(&mut self, args: Args) -> AtResult<SIZE> {
64        if let Some(data) = args.get(0) {
65            self.write(data);
66            Ok(Bytes::from_str("SENT"))
67        } else {
68            Err(AtError::InvalidArgs)
69        }
70    }
71}
72
73// Device configuration context
74struct ConfigContext;
75
76impl AtContext<SIZE> for ConfigContext {
77    fn exec(&self) -> AtResult<SIZE> {
78        // Not supported for SETCFG
79        Err(AtError::NotSupported)
80    }
81    
82    fn query(&mut self) -> AtResult<SIZE> {
83        // Return current configuration as a static string
84        // In real implementation, format the values dynamically
85        Ok(Bytes::from_str("115200,1"))
86    }
87    
88    fn test(&mut self) -> AtResult<SIZE> {
89        // Return supported configuration options
90        Ok(Bytes::from_str("+SETCFG: (baudrate),(mode)"))
91    }
92    
93    fn set(&mut self, args: Args) -> AtResult<SIZE> {
94        let baud = args.get(0).and_then(|s| s.parse::<u32>().ok());
95        let mode = args.get(1).and_then(|s| s.parse::<u8>().ok());
96        match (baud, mode) {
97            (Some(b), Some(m)) => unsafe {
98                // Configure UART
99                UART.baudrate = b;
100                UART.mode = m;
101                Ok(Bytes::from_str("CONFIGURED"))
102            },
103            _ => Err(AtError::InvalidArgs),
104        }
105    }
106}
107
108static mut UART: DummyUart = DummyUart { baudrate: 9600, mode: 0 };
109static mut CONFIG_CTX: ConfigContext = ConfigContext;
110
111// Example using AtParser
112fn example_with_parser() -> Result<&'static str, AtError> {
113    // Simplified example for no_std
114    // In real embedded code, you would properly initialize the parser
115    Ok("OK")
116}
117
118// Example using the COMMANDS table generated by at_modules macro
119fn example_with_commands_macro() -> Result<&'static str, AtError> {
120    // Simple command parsing without the full parser
121    // In a real embedded system, you would use the parser properly
122    Ok("OK")
123}
124
125// Mock main for compilation (in real embedded code, this would be in your firmware)
126#[unsafe(no_mangle)]
127pub extern "C" fn main() -> ! {
128    // Example usage - in embedded this would be called from your main loop
129    let _result = example_with_commands_macro();
130    loop {}
131}