aboutsummaryrefslogtreecommitdiff
path: root/examples/rp/src/bin/uart_r503.rs
blob: a25d45b1825795890b46a9ef7d2f8ffec56e284f (plain)
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
#![no_std]
#![no_main]

use defmt::{debug, error, info};
use embassy_executor::Spawner;
use embassy_rp::bind_interrupts;
use embassy_rp::peripherals::UART0;
use embassy_rp::uart::{Config, DataBits, InterruptHandler as UARTInterruptHandler, Parity, StopBits, Uart};
use embassy_time::{Duration, Timer, with_timeout};
use heapless::Vec;
use {defmt_rtt as _, panic_probe as _};

bind_interrupts!(pub struct Irqs {
    UART0_IRQ  => UARTInterruptHandler<UART0>;
});

const START: u16 = 0xEF01;
const ADDRESS: u32 = 0xFFFFFFFF;

// ================================================================================

// Data package format
// Name     Length          Description
// ==========================================================================================================
// Start    2 bytes         Fixed value of 0xEF01; High byte transferred first.
// Address  4 bytes         Default value is 0xFFFFFFFF, which can be modified by command.
//                          High byte transferred first and at wrong adder value, module
//                          will reject to transfer.
// PID      1 byte          01H     Command packet;
//                          02H     Data packet; Data packet shall not appear alone in executing
//                                  processs, must follow command packet or acknowledge packet.
//                          07H     Acknowledge packet;
//                          08H     End of Data packet.
// LENGTH   2 bytes         Refers to the length of package content (command packets and data packets)
//                          plus the length of Checksum (2 bytes). Unit is byte. Max length is 256 bytes.
//                          And high byte is transferred first.
// DATA     -               It can be commands, data, command’s parameters, acknowledge result, etc.
//                          (fingerprint character value, template are all deemed as data);
// SUM      2 bytes         The arithmetic sum of package identifier, package length and all package
//                          contens. Overflowing bits are omitted. high byte is transferred first.

// ================================================================================

// Checksum is calculated on 'length (2 bytes) + data (??)'.
fn compute_checksum(buf: Vec<u8, 32>) -> u16 {
    let mut checksum = 0u16;

    let check_end = buf.len();
    let checked_bytes = &buf[6..check_end];
    for byte in checked_bytes {
        checksum += (*byte) as u16;
    }
    return checksum;
}

#[embassy_executor::main]
async fn main(_spawner: Spawner) {
    info!("Start");

    let p = embassy_rp::init(Default::default());

    // Initialize the fingerprint scanner.
    let mut config = Config::default();
    config.baudrate = 57600;
    config.stop_bits = StopBits::STOP1;
    config.data_bits = DataBits::DataBits8;
    config.parity = Parity::ParityNone;

    let (uart, tx_pin, tx_dma, rx_pin, rx_dma) = (p.UART0, p.PIN_16, p.DMA_CH0, p.PIN_17, p.DMA_CH1);
    let uart = Uart::new(uart, tx_pin, rx_pin, Irqs, tx_dma, rx_dma, config);
    let (mut tx, mut rx) = uart.split();

    let mut vec_buf: Vec<u8, 32> = heapless::Vec::new();
    let mut data: Vec<u8, 32> = heapless::Vec::new();

    let mut speeds: Vec<u8, 3> = heapless::Vec::new();
    let _ = speeds.push(0xC8); // Slow
    let _ = speeds.push(0x20); // Medium
    let _ = speeds.push(0x02); // Fast

    // Cycle through the three colours Red, Blue and Purple forever.
    loop {
        for colour in 1..=3 {
            for speed in &speeds {
                // Set the data first, because the length is dependent on that.
                // However, we write the length bits before we do the data.
                data.clear();
                let _ = data.push(0x01); // ctrl=Breathing light
                let _ = data.push(*speed);
                let _ = data.push(colour as u8); // colour=Red, Blue, Purple
                let _ = data.push(0x00); // times=Infinite

                // Clear buffers
                vec_buf.clear();

                // START
                let _ = vec_buf.extend_from_slice(&START.to_be_bytes()[..]);

                // ADDRESS
                let _ = vec_buf.extend_from_slice(&ADDRESS.to_be_bytes()[..]);

                // PID
                let _ = vec_buf.extend_from_slice(&[0x01]);

                // LENGTH
                let len: u16 = (1 + data.len() + 2).try_into().unwrap();
                let _ = vec_buf.extend_from_slice(&len.to_be_bytes()[..]);

                // COMMAND
                let _ = vec_buf.push(0x35); // Command: AuraLedConfig

                // DATA
                let _ = vec_buf.extend_from_slice(&data);

                // SUM
                let chk = compute_checksum(vec_buf.clone());
                let _ = vec_buf.extend_from_slice(&chk.to_be_bytes()[..]);

                // =====

                // Send command buffer.
                let data_write: [u8; 16] = vec_buf.clone().into_array().unwrap();
                debug!("  write='{:?}'", data_write[..]);
                match tx.write(&data_write).await {
                    Ok(..) => info!("Write successful."),
                    Err(e) => error!("Write error: {:?}", e),
                }

                // =====

                // Read command buffer.
                let mut read_buf: [u8; 1] = [0; 1]; // Can only read one byte at a time!
                let mut data_read: Vec<u8, 32> = heapless::Vec::new(); // Save buffer.

                info!("Attempting read.");
                loop {
                    // Some commands, like `Img2Tz()` needs longer, but we hard-code this to 200ms
                    // for this command.
                    match with_timeout(Duration::from_millis(200), rx.read(&mut read_buf)).await {
                        Ok(..) => {
                            // Extract and save read byte.
                            debug!("  r='{=u8:#04x}H' ({:03}D)", read_buf[0], read_buf[0]);
                            let _ = data_read.push(read_buf[0]).unwrap();
                        }
                        Err(..) => break, // TimeoutError -> Ignore.
                    }
                }
                info!("Read successful");
                debug!("  read='{:?}'", data_read[..]);

                Timer::after_secs(3).await;
                info!("Changing speed.");
            }

            info!("Changing colour.");
        }
    }
}