    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
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134

    #![allow(unused_imports)]
    /// Create a space for Progmem variable
    /// ## Example
    /// ```
    /// //for text
    /// progmem!(
    ///     static text: [u8; _] = *b"I'm a PROGMEM Text\0";
    /// );
    /// //for tone sequence
    /// progmem!(
    ///     static tone: [u16; _] = [
    ///         NOTE_E4, 400, NOTE_D4, 200, NOTE_C4, 400, NOTE_D4, 200, NOTE_C4, 300, NOTE_REST,
    ///     ];
    /// );
    /// //for for bitmap
    /// progmem!(
    ///     static image: [u8; _] = [8, 8, 0x81, 0x00, 0x12, 0x40, 0x04, 0x11, 0x00, 0x04];
    /// );
    ///
    /// // for a Vector
    /// progmem!(
    ///     static mut walls: Vec<Player, 100> = Vec::new();
    /// );
    /// ```
    #[macro_export]
    macro_rules! progmem {
        (
            $( #[$attr:meta] )*
            $v:vis $id:ident $name:ident: [$ty:ty; _] = $value:expr;
            $($rest:tt)*
        ) => {
            $( #[$attr] )*
            #[link_section = ".progmem.data"]
            $v $id $name: [$ty; $value.len()] = $value;
            $crate::progmem!{
    			$($rest)*
    		}
        };
        (
            $( #[$attr:meta] )*
            $v:vis $id:ident mut $name:ident: [$ty:ty; _] = $value:expr;
            $($rest:tt)*
        ) => {
            $( #[$attr] )*
            #[link_section = ".progmem.data"]
            $v $id mut $name: [$ty; $value.len()] = $value;
            $crate::progmem!{
    			$($rest)*
    		}
        };
        (
            $( #[$attr:meta] )*
            $v:vis $id:ident $name:ident: $ty:ty = $value:expr;
            $($rest:tt)*
        ) => {
            $( #[$attr] )*
            #[link_section = ".progmem.data"]
            $v $id $name: $ty = $value;
            $crate::progmem!{
    			$($rest)*
    		}
        };
        (
            $( #[$attr:meta] )*
            $v:vis $id:ident mut $name:ident: $ty:ty = $value:expr;
            $($rest:tt)*
        ) => {
            $( #[$attr] )*
            #[link_section = ".progmem.data"]
            $v $id mut $name: $ty = $value;
            $crate::progmem!{
    			$($rest)*
    		}
        };
        () => ()
    }

    pub(super) use progmem;
    ///Create a `const` raw pointer to a sprite as u8, without creating an intermediate reference.
    #[macro_export]
    macro_rules! get_sprite_addr {
        ( $s:expr ) => {
            addr_of!($s) as *const u8
        };
    }
    pub(super) use get_sprite_addr;

    ///Create a `const` raw pointer to a sprite as u16, without creating an intermediate reference.
    #[macro_export]
    macro_rules! get_tones_addr {
        ( $s:expr ) => {
            addr_of!($s) as *const u16
        };
    }
    pub(super) use get_tones_addr;

    ///Create a `const` raw pointer to a \[u8;_] that saves text, without creating an intermediate reference.
    #[macro_export]
    macro_rules! get_string_addr {
        ( $s:expr ) => {
            Pstring {
                pointer: addr_of!($s) as *const i8,
            }
        };
    }
    pub(super) use get_string_addr;
    ///This is the way to go if you want print some random text
    ///
    /// This doesn't waste the 2kb ram it saves to progmem (28kb)
    /// This automatically saves the given text to the Progmem.
    /// ## Example
    /// ```
    /// arduboy.print(f!(b"Random text to print\0"))
    /// ```
    #[macro_export]
    macro_rules! f {
        ($string_literal:literal) => {{
            progmem!(
                static local: [u8; _] = *$string_literal;
            );

            get_string_addr!(local)
        }};
    }
    pub(super) use f;

    /// This struct is important for the Progmem functionality.
    ///
    /// Typically you will never use this by your self.
    /// It will be used by the get_string_addr macro in combination with a print command.
    #[derive(Copy, Clone)]
    pub struct Pstring {
        pub pointer: *const i8,
    }