1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
/* stdout.rs
*
* Developed by Tim Walls <tim.walls@snowgoons.com>
* Copyright (c) All Rights Reserved, Tim Walls
*/
//! Simple macros and container for a static reference to a global
//! SerialPort instance, so we can use print!()/println!() style macros.
//!
//! `format!()` style printing is provided by the wonderful `ufmt` crate,
//! and we provide a couple of `print!`/`println!` macros that use this,
//! so you can write your code in a familar Rusty way.
//!
//! Note that these macros are infallible - any errors will be swallowed
//! whole and ignored.
//!
//! # Usage
//! Before you can use the `print!`/`println!` macros, you need to use the
//! `set_stdout` (or `set_stdout_wrapped`) function to pass a reference to the
//! serial port you wish to use. (Actually, anything that implements Write
//! will do, but this will typically be a serial port.)
//!
//! ```rust,no_run
//! #![no_std]
//! #![no_main]
//! use avr_oxide::hal::generic::serial::{BaudRate, DataBits, Parity, SerialPortMode, StopBits};
//! use avr_oxide::devices::{UsesPin, OxideSerialPort };
//! use avr_oxide::{boards::board, print, println};
//! use avr_oxide::StaticWrap;
//!
//! #[avr_oxide::main(chip="atmega4809")]
//! pub fn main() -> ! {
//! let supervisor = avr_oxide::oxide::instance();
//!
//! let mut serial= StaticWrap::new(OxideSerialPort::using_port_and_pins(board::usb_serial(),
//! board::usb_serial_pins().0,
//! board::usb_serial_pins().1).mode(SerialPortMode::Asynch(BaudRate::Baud9600, DataBits::Bits8, Parity::None, StopBits::Bits1)));
//!
//! // Set the serial port to use for STDOUT
//! avr_oxide::stdout::set_stdio(serial.borrow_mut());
//!
//! println!("Welcome to AVRoxide");
//!
//! supervisor.run();
//! }
//! ```
// Imports ===================================================================
use core::convert::Infallible;
use ufmt_write::uWrite;
use avr_oxide::AsStaticRefMut;
// Declarations ==============================================================
pub type Stdout = dyn uWrite<Error = Infallible>;
pub static mut STDIO: Option<&'static mut Stdout> = None;
// Code ======================================================================
/**
* Set a global reference that can be used by the `print!`/`println!`
* macros for easy output to serial ports.
*/
pub fn set_stdio<W: uWrite<Error = Infallible> + 'static, WR: AsStaticRefMut<W>>(mut output: WR) {
unsafe {
STDIO.replace(output.as_static_ref_mut());
}
}
/**
* Get a reference to the global STDOUT output device.
*/
pub fn get_stdout() -> Option<&'static mut Stdout> {
unsafe {
match &mut STDIO {
None => None,
Some(reference) => {
Some(*reference)
}
}
}
}
/**
* Print the given output to the standard out writer device previously set
* with the `set_stdout()` function.
*
* This method is infallible.
*/
#[macro_export]
macro_rules! print {
($($params:expr),*) => {
match avr_oxide::stdout::get_stdout(){
None => { },
Some(stdout) => {
use core::result::Result::{Ok,Err};
let _ = ufmt::uwrite!(stdout,$($params),*);
}
}
}
}
/**
* Print the given output to the standard out writer device previously set
* with the `set_stdout()` function, followed by a newline character.
*
* This method is infallible.
*/
#[macro_export]
macro_rules! println {
($($params:expr),*) => {
match avr_oxide::stdout::get_stdout(){
None => { },
Some(stdout) => {
use core::result::Result::{Ok,Err};
let _ = ufmt::uwriteln!(stdout,$($params),*);
}
}
}
}
// Tests =====================================================================