diff options
Diffstat (limited to 'examples')
| -rw-r--r-- | examples/rp/src/bin/uart_r503.rs | 158 |
1 files changed, 158 insertions, 0 deletions
diff --git a/examples/rp/src/bin/uart_r503.rs b/examples/rp/src/bin/uart_r503.rs new file mode 100644 index 000000000..085be280b --- /dev/null +++ b/examples/rp/src/bin/uart_r503.rs | |||
| @@ -0,0 +1,158 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::{debug, error, info}; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_rp::bind_interrupts; | ||
| 7 | use embassy_rp::peripherals::UART0; | ||
| 8 | use embassy_rp::uart::{Config, DataBits, InterruptHandler as UARTInterruptHandler, Parity, StopBits, Uart}; | ||
| 9 | use embassy_time::{with_timeout, Duration, Timer}; | ||
| 10 | use heapless::Vec; | ||
| 11 | use {defmt_rtt as _, panic_probe as _}; | ||
| 12 | |||
| 13 | bind_interrupts!(pub struct Irqs { | ||
| 14 | UART0_IRQ => UARTInterruptHandler<UART0>; | ||
| 15 | }); | ||
| 16 | |||
| 17 | const START: u16 = 0xEF01; | ||
| 18 | const ADDRESS: u32 = 0xFFFFFFFF; | ||
| 19 | |||
| 20 | // ================================================================================ | ||
| 21 | |||
| 22 | // Data package format | ||
| 23 | // Name Length Description | ||
| 24 | // ========================================================================================================== | ||
| 25 | // Start 2 bytes Fixed value of 0xEF01; High byte transferred first. | ||
| 26 | // Address 4 bytes Default value is 0xFFFFFFFF, which can be modified by command. | ||
| 27 | // High byte transferred first and at wrong adder value, module | ||
| 28 | // will reject to transfer. | ||
| 29 | // PID 1 byte 01H Command packet; | ||
| 30 | // 02H Data packet; Data packet shall not appear alone in executing | ||
| 31 | // processs, must follow command packet or acknowledge packet. | ||
| 32 | // 07H Acknowledge packet; | ||
| 33 | // 08H End of Data packet. | ||
| 34 | // LENGTH 2 bytes Refers to the length of package content (command packets and data packets) | ||
| 35 | // plus the length of Checksum (2 bytes). Unit is byte. Max length is 256 bytes. | ||
| 36 | // And high byte is transferred first. | ||
| 37 | // DATA - It can be commands, data, command’s parameters, acknowledge result, etc. | ||
| 38 | // (fingerprint character value, template are all deemed as data); | ||
| 39 | // SUM 2 bytes The arithmetic sum of package identifier, package length and all package | ||
| 40 | // contens. Overflowing bits are omitted. high byte is transferred first. | ||
| 41 | |||
| 42 | // ================================================================================ | ||
| 43 | |||
| 44 | // Checksum is calculated on 'length (2 bytes) + data (??)'. | ||
| 45 | fn compute_checksum(buf: Vec<u8, 32>) -> u16 { | ||
| 46 | let mut checksum = 0u16; | ||
| 47 | |||
| 48 | let check_end = buf.len(); | ||
| 49 | let checked_bytes = &buf[6..check_end]; | ||
| 50 | for byte in checked_bytes { | ||
| 51 | checksum += (*byte) as u16; | ||
| 52 | } | ||
| 53 | return checksum; | ||
| 54 | } | ||
| 55 | |||
| 56 | #[embassy_executor::main] | ||
| 57 | async fn main(_spawner: Spawner) { | ||
| 58 | info!("Start"); | ||
| 59 | |||
| 60 | let p = embassy_rp::init(Default::default()); | ||
| 61 | |||
| 62 | // Initialize the fingerprint scanner. | ||
| 63 | let mut config = Config::default(); | ||
| 64 | config.baudrate = 57600; | ||
| 65 | config.stop_bits = StopBits::STOP1; | ||
| 66 | config.data_bits = DataBits::DataBits8; | ||
| 67 | config.parity = Parity::ParityNone; | ||
| 68 | |||
| 69 | let (uart, tx_pin, tx_dma, rx_pin, rx_dma) = (p.UART0, p.PIN_16, p.DMA_CH0, p.PIN_17, p.DMA_CH1); | ||
| 70 | let uart = Uart::new(uart, tx_pin, rx_pin, Irqs, tx_dma, rx_dma, config); | ||
| 71 | let (mut tx, mut rx) = uart.split(); | ||
| 72 | |||
| 73 | let mut vec_buf: Vec<u8, 32> = heapless::Vec::new(); | ||
| 74 | let mut data: Vec<u8, 32> = heapless::Vec::new(); | ||
| 75 | |||
| 76 | let mut speeds: Vec<u8, 3> = heapless::Vec::new(); | ||
| 77 | let _ = speeds.push(0xC8); // Slow | ||
| 78 | let _ = speeds.push(0x20); // Medium | ||
| 79 | let _ = speeds.push(0x02); // Fast | ||
| 80 | |||
| 81 | // Cycle through the three colours Red, Blue and Purple forever. | ||
| 82 | loop { | ||
| 83 | for colour in 1..=3 { | ||
| 84 | for speed in &speeds { | ||
| 85 | // Set the data first, because the length is dependent on that. | ||
| 86 | // However, we write the length bits before we do the data. | ||
| 87 | data.clear(); | ||
| 88 | let _ = data.push(0x01); // ctrl=Breathing light | ||
| 89 | let _ = data.push(*speed); | ||
| 90 | let _ = data.push(colour as u8); // colour=Red, Blue, Purple | ||
| 91 | let _ = data.push(0x00); // times=Infinite | ||
| 92 | |||
| 93 | // Clear buffers | ||
| 94 | vec_buf.clear(); | ||
| 95 | |||
| 96 | // START | ||
| 97 | let _ = vec_buf.extend_from_slice(&START.to_be_bytes()[..]); | ||
| 98 | |||
| 99 | // ADDRESS | ||
| 100 | let _ = vec_buf.extend_from_slice(&ADDRESS.to_be_bytes()[..]); | ||
| 101 | |||
| 102 | // PID | ||
| 103 | let _ = vec_buf.extend_from_slice(&[0x01]); | ||
| 104 | |||
| 105 | // LENGTH | ||
| 106 | let len: u16 = (1 + data.len() + 2).try_into().unwrap(); | ||
| 107 | let _ = vec_buf.extend_from_slice(&len.to_be_bytes()[..]); | ||
| 108 | |||
| 109 | // COMMAND | ||
| 110 | let _ = vec_buf.push(0x35); // Command: AuraLedConfig | ||
| 111 | |||
| 112 | // DATA | ||
| 113 | let _ = vec_buf.extend_from_slice(&data); | ||
| 114 | |||
| 115 | // SUM | ||
| 116 | let chk = compute_checksum(vec_buf.clone()); | ||
| 117 | let _ = vec_buf.extend_from_slice(&chk.to_be_bytes()[..]); | ||
| 118 | |||
| 119 | // ===== | ||
| 120 | |||
| 121 | // Send command buffer. | ||
| 122 | let data_write: [u8; 16] = vec_buf.clone().into_array().unwrap(); | ||
| 123 | debug!(" write='{:?}'", data_write[..]); | ||
| 124 | match tx.write(&data_write).await { | ||
| 125 | Ok(..) => info!("Write successful."), | ||
| 126 | Err(e) => error!("Write error: {:?}", e), | ||
| 127 | } | ||
| 128 | |||
| 129 | // ===== | ||
| 130 | |||
| 131 | // Read command buffer. | ||
| 132 | let mut read_buf: [u8; 1] = [0; 1]; // Can only read one byte at a time! | ||
| 133 | let mut data_read: Vec<u8, 32> = heapless::Vec::new(); // Save buffer. | ||
| 134 | |||
| 135 | info!("Attempting read."); | ||
| 136 | loop { | ||
| 137 | // Some commands, like `Img2Tz()` needs longer, but we hard-code this to 200ms | ||
| 138 | // for this command. | ||
| 139 | match with_timeout(Duration::from_millis(200), rx.read(&mut read_buf)).await { | ||
| 140 | Ok(..) => { | ||
| 141 | // Extract and save read byte. | ||
| 142 | debug!(" r='{=u8:#04x}H' ({:03}D)", read_buf[0], read_buf[0]); | ||
| 143 | let _ = data_read.push(read_buf[0]).unwrap(); | ||
| 144 | } | ||
| 145 | Err(..) => break, // TimeoutError -> Ignore. | ||
| 146 | } | ||
| 147 | } | ||
| 148 | info!("Read successful"); | ||
| 149 | debug!(" read='{:?}'", data_read[..]); | ||
| 150 | |||
| 151 | Timer::after_secs(3).await; | ||
| 152 | info!("Changing speed."); | ||
| 153 | } | ||
| 154 | |||
| 155 | info!("Changing colour."); | ||
| 156 | } | ||
| 157 | } | ||
| 158 | } | ||
