rustduino 0.2.2

A generic HAL implementation for Arduino Boards in Rust
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
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
# Introduction 


The Universal Synchronous and Asynchronous serial Receiver and Transmitter (USART) is a highly flexible serial
communication device. Embedded systems, microcontrollers, and computers mostly use USART as a form of device-to-device hardware communication protocol. By definition, USART is a hardware communication protocol that uses synchronous or asynchronous
serial communication with configurable speed and Data Format. Asynchronous communication does not use a clock to validate data.

## Introduction to Serial and Asynchronous Communication


In Serial Communication, the data which is recieved in bytes is transmitted 
bit by bit in a sequenced manner, through the Bus or communication channel, and on
reaching the destination UART it is re assembled in bytes.

UART uses asynchronous communication for recieving data as it is not validated by a 
clock, or in other words, data is transmitted intermittently rather than in a steady
stream. In asynchronous transmission, data is sent one byte at a time and each byte is
preceded by start bit and stop bit.

To ensure the correct transmission the transmission and the reciever pins need to 
have same settings like Transmission Speed, Data length in bits, how is the Start and
Stop bit. To understand UART in more Detail click [here](https://www.analog.com/en/analog-dialogue/articles/uart-a-hardware-communication-protocol.html#) to access online resources. Read the Atmel manual [here](https://ww1.microchip.com/downloads/en/devicedoc/atmel-2549-8-bit-avr-microcontroller-atmega640-1280-1281-2560-2561_datasheet.pdf) .

## Functioning of USART in atmega 2560p


### Initialization of USART


In atmega2560p we have four USART's which are USART0, USART1, USART2, and USART3. The
USART has to be initialized before any communication can take place. To initialize
we have to set Baud Rate, Set the Frame Format and enable Transmitter or Receiver
depending on the usage. For interrupt driven USART operation, the Global Interrupt
Flag should be cleared (and interrupts globally disabled) when doing the
initialization. 

```rust
 /// Function to disable global interrupts for smooth non-interrupted functioning of USART.
    fn disable(&mut self) {
        unsafe {
            // Disable global interrupts.
            interrupts::GlobalInterrupts::disable(&mut interrupts::GlobalInterrupts::new());
        }
    }
/// Function to re-enable global interrupts.
    fn enable(&mut self) {
        unsafe {
            // Enable global interrupts.
            interrupts::GlobalInterrupts::enable(&mut interrupts::GlobalInterrupts::new());
        }
    }
```

In case, You want to re-initialize the USART make sure that no transmission is on 
going during the peroid the registers are changed for USART, which can be done using
the TXCn(for the transmission) and the RXC (to check if the recieve buffer is
empty). 

**Note** that the TXCn Flag must be cleared before each transmission (before UDRn
is written) if it is used for this purpose. 

Clock Generation is one of the initialization steps for the USART. If the USART is in Asynchronous mode or Master Synchronous mode then a internal clock generator is used while for Slave Synchronous mode we will use a external clock generator. Set the baud rate frequency for USART.Baud rate settings is used to set the clock for USART.

``` rust
fn set_clock(&mut self, baud: i64, mode: UsartModes) {
        let ubrr: u32;
        match mode {
            UsartModes::Normasync => {
                ubrr = (((F_OSC * MULTIPLY) / (16.00 * baud as f64)) - 1.00) as u32;
            }
            UsartModes::Douasync => {
                ubrr = (((F_OSC * MULTIPLY) / (8.00 * baud as f64)) - 1.00) as u32;
            }
            UsartModes::Mastersync => {
                ubrr = (((F_OSC * MULTIPLY) / (2.00 * baud as f64)) - 1.00) as u32;
            }
            _ => unreachable!(),
        }
        self.ubrrl.update(|ubrrl| {
            for i in 0..8 {
                ubrrl.set_bit(i, ubrr.get_bit(i));
            }
        });
        self.ubrrh.update(|ubrrh| {
            for i in 0..4 {
                ubrrh.set_bit(i, ubrr.get_bit(i + 8));
            }
        });
    }
```

The UCSZn2 in UCSRnB bits combined with the UCSZn1 bit in UCSRnC sets the number of data bits in a
frame the Receiver and Transmitter use. UCSZn2 is 1 for 9 bit data else 0 for 5,6,7,8 bit data. See sction 22.10.3 and 22.10.4 in Atmel manual.

 | UCSZn2 | UCSZn1 | UCSZn0 |  Character Size |
 |--------|--------|--------|-----------------|
 |  0     |   0    |   0    |  5-bit          |
 |  0     |   0    |   1    |  6-bit          |
 |  0     |   1    |   0    |  7-bit          |
 |  0     |   1    |   1    |  8-bit          |
 |  1     |   1    |   1    |  9-bit          |

<details>
  <summary>Click to expand code</summary>

``` rust
fn set_size(&mut self, size: UsartDataSize) {
        match size {
            UsartDataSize::Five
            | UsartDataSize::Six
            | UsartDataSize::Seven
            | UsartDataSize::Eight => {
                self.ucsrb.update(|srb| {
                    srb.set_bit(2, false);
                });
            }
            UsartDataSize::Nine => {
                self.ucsrb.update(|srb| {
                    srb.set_bit(2, true);
                });
            }
        }
        match size {
            UsartDataSize::Five | UsartDataSize::Six => {
                self.ucsrc.update(|src| {
                    src.set_bit(2, false);
                });
            }
            UsartDataSize::Nine | UsartDataSize::Seven | UsartDataSize::Eight => {
                self.ucsrc.update(|src| {
                    src.set_bit(2, true);
                });
            }
        }
        match size {
            UsartDataSize::Five | UsartDataSize::Seven => {
                self.ucsrc.update(|src| {
                    src.set_bit(1, false);
                });
            }
            UsartDataSize::Nine | UsartDataSize::Six | UsartDataSize::Eight => {
                self.ucsrc.update(|src| {
                    src.set_bit(1, true);
                });
            }
        }
    }
```
</details>

Parity is optional i.e. can be odd, even or no parity bit. Check section 22.10.4 in atmael manual.

``` rust
 fn set_parity(&mut self, parity: UsartParity) {
        match parity {
            UsartParity::No => {
                self.ucsrc.update(|src| {
                    src.set_bit(4, false);
                    src.set_bit(5, false);
                });
            }
            UsartParity::Even => {
                self.ucsrc.update(|src| {
                    src.set_bit(4, false);
                    src.set_bit(5, true);
                });
            }
            UsartParity::Odd => {
                self.ucsrc.update(|src| {
                    src.set_bit(4, true);
                    src.set_bit(5, true);
                });
            }
        }
    }
```
Stop bit can be one bit or two bit.

 ``` rust
  /// Function to set the number of stop bits in the USART.
    fn set_stop(&mut self, stop: UsartStop) {
        match stop {
            UsartStop::One => {
                self.ucsrc.update(|src| {
                    src.set_bit(3, false);
                });
            }
            UsartStop::Two => {
                self.ucsrc.update(|src| {
                    src.set_bit(3, true);
                });
            }
        }
    }
```
 Set the frame format for USART. A serial frame is defined to be one character of data bits with synchronization bits (start and stop bits), and optionally a parity bit for error checking. The USART accepts all 30 combinations of the following as valid frame formats.
   -  1 start bit
   -  5, 6, 7, 8, or 9 data bits
   -  no, even or odd parity bit
   -  1 or 2 stop bits
 
 ``` rust 
    fn set_frame(&mut self, stop: UsartStop, size: UsartDataSize, parity: UsartParity) {
        self.set_size(size);
        self.set_parity(parity);
        self.set_stop(stop);
    }
```
Following is the cumulative function for initializing a particular USART and it will take all the necessary details about the mode in which the USART pin is to be used.

```rust
    pub fn initialize(
        &mut self,
        mode: UsartModes,
        baud: i64,
        stop: UsartStop,
        size: UsartDataSize,
        parity: UsartParity,
    ) {
        // Check that recieve and transmit buffers are completely cleared
        // and no transmission or recieve of data is already in process.
        let mut i: i32 = 10;
        while self.check_ongoing() == false {
            if i != 0 {
                delay_ms(1000);
                i = i - 1;
            } else {
                unreachable!()
            }
        }

        self.disable(); //  Disable Global interrupts.
        let num: UsartNum = self.get_num();

        self.set_power(num); //  Set Power reduction register.

        self.mode_select(mode); //  Set the USART at the given mode.

        //  Set the clock for USART according to user input.
        match mode {
            UsartModes::Slavesync => {}
            _ => {
                self.set_clock(baud, mode);
            }
        }

        //  Set the frame format according to input.
        self.set_frame(stop, size, parity);

        self.enable(); //  Enable Global interrupts.
    }
```


### Data Transmission


To Transmit data the you need to enable the USART Transmitter, which is enabled by
setting the Transmit Enable(TXEN) bit to 1 in the UCSRnB Register. When the Transmitter
is enabled the TxDn functions as the Transmitter's serial output. Initialization
should be done before transmission.

``` rust
    pub unsafe fn transmit_enable(&mut self) {
        (*self.usart).ucsrb.update(|srb| {
            srb.set_bit(3, true);
        });
    }

```

For sending Frames with **5-8 Data bits** Transmission is initiated by loading the
data to the transmit buffer,which can be done by writing to the UDRn I/O location.
Buffered Data will be moved to Shift Register if the shift Register is in Idle state
or just after the stop bit of an transmitting frame. Upon filling the shift Register
it transmits one frame at the Baud rate, U2X bit.
For sending Frames with **9 Data Bits** we have to store the 9th bit in the TXB8 in
UCSRnB, before the low byte character is written to the UDRn.

Following is the code for transmitting data string byte by byte.
``` rust
    pub fn transmit_data(&mut self, data: u8) {
        let mut ucsra = unsafe { (*self.usart).ucsra.read() };
        let mut udre = ucsra.get_bit(5);

        let mut i: i32 = 100;
        while udre == false {
            ucsra = unsafe { (*self.usart).ucsra.read() };
            udre = ucsra.get_bit(5);

            if i != 0 {
                delay_ms(1000);
                i = i - 1;
            } else {
                unreachable!();
            }
        }

        unsafe { (*self.usart).udr.write(data) };
    }

    pub fn write_string(&mut self, data: &'static str) {
        let mut vec: FixedSliceVec<u8> = FixedSliceVec::new(&mut []);

        for c in data.chars() {
            vec.push(c as u8);
        }

        for i in 0..(vec.len()) {
            self.transmit_data(vec[i]);
        }
    }

```

Usart Transmitter has two Flags, **USART Data Register Empty**(UDREn) and 
**Tranfer Complete** (TXCn), to indicate its state. The **UDREn** Flag indicates the
state of Transfer Buffer, it is set when the Transfer Buffer is empty and is cleared
when the transfer buffer has data that has not yet been transffered to shift register.
The **TXCn** is Flag bit is set 1 when entire frame in the transmit shift register
has been shifted out and no new data is present in the transmit buffer it can
automatically br cleared if a interrupt is set up or by writing 1 to its bit.

Parity generator calculates the parity for a serial data Frame and if parity bit(UPMn1 bit) is
set 1 transmitter control logic automatically inserts parity in serial frame.

To disable the Transmitter, shift register and transmit buffer must not contain any data to be transmitted which is
checked by the TXCn and UDREn bit in UCSRnA register respectively.Once disabled, it will no longer override TxDn
pin.

``` rust 

    pub fn transmit_disable(&mut self) {
        let ucsra = unsafe { (*self.usart).ucsra.read() };
        let mut uscra6 = ucsra.get_bit(6);
        let mut uscra5 = ucsra.get_bit(5);
        let mut i: i32 = 100;

        while uscra6 == false || uscra5 == false {
            uscra6 = ucsra.get_bit(6);
            uscra5 = ucsra.get_bit(5);
            if i != 0 {
                delay_ms(1000);
                i = i - 1;
            } else {
                unreachable!()
            }
        }

        unsafe {
            (*self.usart).ucsrb.update(|srb| {
                srb.set_bit(3, false);
            });
        }
    }
```

### Data Receiving


USART Receiver function similar to Transmitter except for some features like error
detection. To enable Data Receiver, write 1 to Receive Enable (RXENn) bit i.e BIT 4 in the
UCSRnB Register. Then the RxDn pin functions as Receiver's serial input.

``` rust
/// This function enables the reciever function of microcontroller, whithout enabling it no communication is possible.
    pub fn recieve_enable(&mut self) {
        self.ucsrb.update(|ucsrb| {
            ucsrb.set_bit(4, true);
        });
    }
```

**Note**  Initialization should be done before any reception can take place.

For Frames with **5-8 Data bits**, the Data reception begins when a **VALID** start
bit is detected. Each bit following start bit will be sampled at baud rate and
shifted to Receive Shift Register until first stop bit is detected, the second stop
bit is Ignored. Once the first stop bit is recieved then the data of Shift Register 
is send to Recieve Buffer which Can be Read from UDRn. For Frames **9 Data bits**,
the 9th bit is Read from the RXB8n bit in UCSRnB before reading the low bits from the
UDRn.
``` rust
   pub fn recieve_data(&mut self) -> Option<u32> {
        let ucsrc = self.ucsrc.read();
        let ucsrb = self.ucsrb.read();

        let mut i: i32 = 10;
        while self.available() == false {
            if i != 0 {
                delay_ms(1000);
                i = i - 1;
            } else {
                unreachable!()
            }
        }

        //  Case when there is 9 bits mode.
        if ucsrc.get_bits(1..3) == 0b11 && ucsrb.get_bit(2) == true {
            let ucsra = self.ucsra.read();
            let mut udr: u32 = self.udr.read() as u32;
            if ucsra.get_bits(2..5) != 0b000 {
                None
            } else {
                let rxb8: u32 = ucsrb.get_bits(1..2) as u32;
                udr.set_bits(8..9, rxb8);
                Some(udr)
            }
        }
        //  Case when there is a case of 5 to 8 bits.
        else {
            let ucsra = self.ucsra.read();
            let udr: u32 = self.udr.read() as u32;
            if ucsra.get_bits(2..5) != 0b000 {
                None
            } else {
                Some(udr)
            }
        }
    }
 ```
The Receiver has one flag to indicate its state, which is Receive complete(RXCn), it
is one if unread data exist in Receive buffer and zero if no unread data in Receive
buffer. If Receiver is disabled so the Receive buffer is flushed and this flag
becomes 0. 
The USART Receiver has three error flags which are Frame Error(FEn), Data OverRun
(DORn) and Parity Error(UPEn). The **Frame Error** indicates the state of the first
stop bit in the next readable Frame in ppresent in the receive buffer, it is one when
stop bit read is zero and it is zero when stop bit read is 1. The **Data OverRun**
occurs due to receive buffer full condition. If the DORn Flag is set there was one or
more serial frame lost between the frame last read from UDRn, and the next frame read
from UDRn. The DORn Flag is cleared when the frame received was successfully moved
from the Shift Register to the receive buffer.The **Parity Error** (UPEn) bit is set
if next character to be read from the recieve buffer had parity error and Parity
checking is enabled at that point (UPMn1 = 1). This bit is valid until the receive
buffer (UDRn) is read.

<details>
  <summary>Click to expand code</summary>

``` rust  
 pub fn error_check(&mut self) -> bool {
        let ucsra = self.ucsra.read();
        if ucsra.get_bits(3..5) != 0b00 {
            true
        } else {
            false
        }
    }

    /// This function can be used to check parity error.
    /// It returns true if error occurs else false.
    pub fn parity_check(&mut self) -> bool {
        let ucsra = self.ucsra.read();
        if ucsra.get_bit(2) == true {
            true
        } else {
            false
        }
    }

    /// This function disables the reciever function of microcontroller.
    pub fn recieve_disable(&mut self) {
        self.ucsrb.update(|ucsrb| {
            ucsrb.set_bit(4, false);
        });
    }

    /// This function clears the unread data in the receive buffer by flushing it
    pub fn flush_recieve(&mut self) {
        let mut _udr = self.udr.read();
        let mut ucsra = self.ucsra.read();
        let mut i: i32 = 100;
        while ucsra.get_bit(7) == true {
            ucsra = self.ucsra.read();
            _udr = self.udr.read();
            if i != 0 {
                delay_ms(1000);
                i = i - 1;
            } else {
                unreachable!()
            }
        }

        self.ucsra.update(|ucsra| {
            ucsra.set_bit(7, false);
        });
    }
```
</details>

Unlike Transmitter, Disabling Receiver is immediate. Data from ongoing Reception is
lost forever, and disabled receiver will no longer override the RxD pin.
In case ,if an frame error or parity error occurs, this function returns -1.

<details>
  <summary>Click to expand code</summary>

``` rust
   pub fn read(&mut self) -> Option<u32> {
        let ucsrc = self.ucsrc.read();
        let ucsrb = self.ucsrb.read();

        let mut i: i32 = 10;
        while self.available() == false {
            if i != 0 {
                delay_ms(1000);
                i = i - 1;
            } else {
                unreachable!()
            }
        }

        if ucsrc.get_bits(1..3) == 0b11 && ucsrb.get_bit(2) == true {
            let ucsra = self.ucsra.read();
            let ucsrb = self.ucsrb.read();
            let mut udr: u32 = self.udr.read() as u32;
            if ucsra.get_bits(2..5) != 0b000 {
                None
            } else {
                let rxb8: u32 = ucsrb.get_bits(1..2) as u32;
                udr.set_bits(8..9, rxb8);
                Some(udr)
            }
        } else {
            let ucsra = self.ucsra.read();
            let udr: u32 = self.udr.read() as u32;
            if ucsra.get_bits(2..5) != 0b000 {
                None
            } else {
                Some(udr)
            }
        }
    }
```
</details>

### Asynchronous Data Reception


USART includes a clock and Data recovery unit for handling the asynchronous data
reception. The **clock recovery** logic synchronizes internal clock to the incoming
serial frames. It detects the first high to low transition and check if the signal was
a valid signal or just a noise spike. In **Data recovery** unit, the decision of the
logic level of the received bit is taken by doing a majority voting of the logic
value to the three samples in the center of the received bit. A majority voting
process acts as a low pass filter for the incoming signal on the RxDn pin.
The recovery process is then repeated until a complete frame is received. Including
the first stop bit. A new high to low transition indicating the start bit of a new
frame can come right after the last of the bits used for majority voting. 

Operational Range is the maximum and minimum mismatch in the Baud Rate which Receiver
can tolerate. There are two sources of Errors one is due to clock synchronization and
other is due to Baud Rate Generator error in calculation in the baud rate, however
latter can be minimized by using a low error baud rate in UBRR.

The more detailed information for the USART can be found in chapter 22-23 in the
Manual for atmega 2560p.


# Introduction