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 =====================================================================