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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
// Generic register type for builder style register interaction
// Copyright 2018 Ryan Kurte

use core::ptr::{read_volatile, write_volatile};
use core::ops::{Add, Sub, Not, BitAnd, BitOr, Shl, Shr, BitAndAssign, BitOrAssign};

// Zero trait for RegisterType implementations
#[doc = "Zero trait allows types to be created with a value of zero"]
pub trait Zero {
    fn zero() -> Self;
}

// One trait for RegisterType implementations
#[doc = "One trait allows types to be created with a value of one"]
pub trait One {
    fn one() -> Self;
}

#[doc = "RegisterType trait allows register implementations to be generic over unsigned integer types"]
pub trait RegisterType<T>: Zero + One
                    + Not<Output=T> + Add<T, Output=T> + Sub<T, Output=T>
                    + BitAnd<T, Output=T> + BitOr<T, Output=T> + BitAndAssign<T> + BitOrAssign<T> 
                    + Shl<T, Output=T> + Shr<T, Output=T>
                    + Clone + Copy + Default + PartialEq {}

#[doc = "Helper macro to generate RegisterType implementations for a given type"]
#[macro_export]
macro_rules! register_impl {
    ($t: ty) => {
        impl RegisterType<$t> for $t {}
        impl One for $t {
            fn one() -> $t { 1 }
        }
        impl Zero for $t {
            fn zero() -> $t { 0 }
        }
    }
}

// RegisterType implementations for viable register types
register_impl!(u8);
register_impl!(u16);
register_impl!(u32);
register_impl!(u64);

// Register helper structure
// This uses an internal value and builder approach to simplify interacting with registers.
#[derive(Debug, PartialEq, Clone)]
pub struct Register<T: RegisterType<T>> (pub(crate) usize, pub(crate) T);

impl <T: RegisterType<T>>Register<T> {
    #[doc = "Creates a new register of the provided type with the specified address"]
    #[doc = "Note that `impl RegisterType<T> for T {}` is required for unimplemented types"]
    pub fn new(addr: usize) -> Register<T> {
        Register(addr, T::default())
    }

    #[doc = "Creates a new 16-bit ride register"]
    pub fn u16(addr: usize) -> Register<u16> {
        Register::<u16>::new(addr)
    }

    #[doc = "Creates a new 32-bit register"]
    pub fn u32(addr: usize) -> Register<u32> {
        Register::<u32>::new(addr)
    }

    #[doc = "Reads the register value and returns a new instance with internal value set."]
    pub fn read(&mut self) -> Register<T> {
        let mut reg = self.clone();
        unsafe {
            reg.1 = read_volatile(self.0 as *const T)
        }
        reg
    }

    #[doc = "clears the internal register value"]
    pub fn zero(&mut self) -> Register<T>  {
        let mut reg = self.clone();
        reg.1 = T::zero();
        reg
    }

    #[doc = "returns the register value"]
    pub fn value(&self) -> T {
        self.1.clone()
    }

    #[doc = "sets the internal value of the register"]
    pub fn set(mut self, val: T) -> Register<T>  {
        self.1 = val;
        self
    }

    #[doc = "boolean and the provided and current values"]
    pub fn and(mut self, val: T) -> Register<T> {
        self.1 = self.1 & val;
        self
    }

    #[doc = "ors the provided and current values"]
    pub fn or(mut self, val: T) -> Register<T> {
        self.1 |= val;
        self
    }

    #[doc = "clears the masked area of the provided value"]
    pub fn clear(mut self, mask: T) -> Register<T> {
        self.1 &= !mask;
        self
    }

    #[doc = "returns a boolean consisting to the indexed bit"]
    pub fn get_bit(&self, i: T) -> bool {
        self.1.clone() & (T::one() << i) != T::zero()
    }

    #[doc = "Sets a bit in the current value"]
    pub fn set_bit(mut self, i: T, v: bool) -> Register<T> {
        self.1 = match v {
            true => self.1 | (T::one() << i),
            false => self.1 & !(T::one() << i),
        };
        self
    }

    #[doc = "Fetches a value with the provided mask and shift"]
    #[doc = "Note that shift is applied prior to masking, so mask should always start at 0b1"]
    pub fn get_masked(&self, shift: T, mask: T) -> T  {
        read_masked!(self.1, shift, mask)
    }

    #[doc = "Sets a value with a provided mask and shift"]
    #[doc = "Note that mask is applied before shifting, so mask should always start at 0b1"]
    pub fn set_masked(mut self, shift: T, mask: T, val: T) -> Register<T>  {
        //self.clear(mask.clone()).or((val & mask) << shift);
        write_masked!(self.1, shift, mask, val);
        self
    }

    #[doc = "Writes the internal value to the register"]
    pub fn write(self) {
        unsafe {
            write_volatile(self.0 as *mut T, self.1)
        }
    }
}

#[cfg(test)]
mod tests {
    use ::register::Register;

    #[test]
    fn set() {
        let mut r = Register::<u16>(0, 0);
        assert_eq!(0, r.value());
        r = r.set(100);
        assert_eq!(100, r.value());
    }

    #[test]
    fn zero() {
        let mut r = Register::<u16>(0, 100);
        assert_eq!(100, r.value());
        r = r.zero();
        assert_eq!(0, r.value());
    }

    #[test]
    fn and() {
        let mut r = Register::<u16>(0, 0xFFFF);
        r = r.and(0xF0F0);
        assert_eq!(0xF0F0, r.value());
    }

    #[test]
    fn or() {
        let mut r = Register::<u16>(0, 0xF0F0);
        r = r.or(0x0F00);
        assert_eq!(0xFFF0, r.value());
    }

    #[test]
    fn clear() {
        let mut r = Register::<u16>(0, 0xF0F0);
        r = r.clear(0xF000);
        assert_eq!(0x00F0, r.value());
    }

    #[test]
    fn get_bit() {
        let r = Register::<u16>(0, 0b0101);
        assert_eq!(true,  r.get_bit(0));
        assert_eq!(false, r.get_bit(1));
        assert_eq!(true,  r.get_bit(2));
        assert_eq!(false, r.get_bit(3));
    }

    #[test]
    fn set_bit() {
        let mut r = Register::<u16>(0, 0b0001);
        r = r.set_bit(2, true);
        assert_eq!(0b0101, r.value());
        r = r.set_bit(2, false);
        assert_eq!(0b0001, r.value());
    }

    #[test]
    fn get_masked() {
        let mut r = Register::<u16>(0, 0xFAF0);
        assert_eq!(0x00, r.get_masked(0, 0xf));
        assert_eq!(0x0F, r.get_masked(4, 0xf));
        assert_eq!(0xFA, r.get_masked(8, 0xff));
    }

    #[test]
    fn set_masked() {
        let mut r = Register::<u16>(0, 0x0000);
        r = r.set_masked(0, 0xFF, 0xF0);
        assert_eq!(0x00F0, r.value());
        r = r.set_masked(8, 0xF, 0xA);
        assert_eq!(0x0AF0, r.value());
        r = r.set_masked(12, 0xF, 0xB);
        assert_eq!(0xBAF0, r.value());
    }
}