diff options
| -rw-r--r-- | examples/rp/src/bin/uart_r503.rs | 182 |
1 files changed, 104 insertions, 78 deletions
diff --git a/examples/rp/src/bin/uart_r503.rs b/examples/rp/src/bin/uart_r503.rs index c0676750c..085be280b 100644 --- a/examples/rp/src/bin/uart_r503.rs +++ b/examples/rp/src/bin/uart_r503.rs | |||
| @@ -1,12 +1,12 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | 3 | ||
| 4 | use defmt::info; | 4 | use defmt::{debug, error, info}; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_rp::bind_interrupts; | 6 | use embassy_rp::bind_interrupts; |
| 7 | use embassy_rp::peripherals::UART0; | 7 | use embassy_rp::peripherals::UART0; |
| 8 | use embassy_rp::uart::{Config, DataBits, InterruptHandler as UARTInterruptHandler, Parity, StopBits, Uart}; | 8 | use embassy_rp::uart::{Config, DataBits, InterruptHandler as UARTInterruptHandler, Parity, StopBits, Uart}; |
| 9 | use embassy_time::Timer; | 9 | use embassy_time::{with_timeout, Duration, Timer}; |
| 10 | use heapless::Vec; | 10 | use heapless::Vec; |
| 11 | use {defmt_rtt as _, panic_probe as _}; | 11 | use {defmt_rtt as _, panic_probe as _}; |
| 12 | 12 | ||
| @@ -14,15 +14,34 @@ bind_interrupts!(pub struct Irqs { | |||
| 14 | UART0_IRQ => UARTInterruptHandler<UART0>; | 14 | UART0_IRQ => UARTInterruptHandler<UART0>; |
| 15 | }); | 15 | }); |
| 16 | 16 | ||
| 17 | const ADDRESS: u32 = 0xFFFFFFFF; | ||
| 18 | const START: u16 = 0xEF01; | 17 | const START: u16 = 0xEF01; |
| 18 | const ADDRESS: u32 = 0xFFFFFFFF; | ||
| 19 | 19 | ||
| 20 | // ================================================================================ | 20 | // ================================================================================ |
| 21 | 21 | ||
| 22 | fn write_cmd_bytes(buf: &mut Vec<u8, 32>, bytes: &[u8]) { | 22 | // Data package format |
| 23 | let _ = buf.extend_from_slice(bytes); | 23 | // Name Length Description |
| 24 | } | 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. | ||
| 25 | 41 | ||
| 42 | // ================================================================================ | ||
| 43 | |||
| 44 | // Checksum is calculated on 'length (2 bytes) + data (??)'. | ||
| 26 | fn compute_checksum(buf: Vec<u8, 32>) -> u16 { | 45 | fn compute_checksum(buf: Vec<u8, 32>) -> u16 { |
| 27 | let mut checksum = 0u16; | 46 | let mut checksum = 0u16; |
| 28 | 47 | ||
| @@ -52,81 +71,88 @@ async fn main(_spawner: Spawner) { | |||
| 52 | let (mut tx, mut rx) = uart.split(); | 71 | let (mut tx, mut rx) = uart.split(); |
| 53 | 72 | ||
| 54 | let mut vec_buf: Vec<u8, 32> = heapless::Vec::new(); | 73 | let mut vec_buf: Vec<u8, 32> = heapless::Vec::new(); |
| 55 | 74 | let mut data: Vec<u8, 32> = heapless::Vec::new(); | |
| 56 | // Cycle through the three colours Red, Blue and Purple. | 75 | |
| 57 | for colour in 1..=3 { | 76 | let mut speeds: Vec<u8, 3> = heapless::Vec::new(); |
| 58 | // Clear buffers | 77 | let _ = speeds.push(0xC8); // Slow |
| 59 | vec_buf.clear(); | 78 | let _ = speeds.push(0x20); // Medium |
| 60 | 79 | let _ = speeds.push(0x02); // Fast | |
| 61 | // START | 80 | |
| 62 | let _ = write_cmd_bytes(&mut vec_buf, &START.to_be_bytes()[..]); | 81 | // Cycle through the three colours Red, Blue and Purple forever. |
| 63 | 82 | loop { | |
| 64 | // ADDRESS | 83 | for colour in 1..=3 { |
| 65 | let _ = write_cmd_bytes(&mut vec_buf, &ADDRESS.to_be_bytes()[..]); | 84 | for speed in &speeds { |
| 66 | 85 | // Set the data first, because the length is dependent on that. | |
| 67 | // PID | 86 | // However, we write the length bits before we do the data. |
| 68 | let _ = vec_buf.push(0x01); | 87 | data.clear(); |
| 69 | 88 | let _ = data.push(0x01); // ctrl=Breathing light | |
| 70 | // LENGTH | 89 | let _ = data.push(*speed); |
| 71 | let len = <usize as TryInto<u16>>::try_into(vec_buf.len()).unwrap() as u16; | 90 | let _ = data.push(colour as u8); // colour=Red, Blue, Purple |
| 72 | let _ = write_cmd_bytes(&mut vec_buf, &len.to_be_bytes()[..]); | 91 | let _ = data.push(0x00); // times=Infinite |
| 73 | 92 | ||
| 74 | // COMMAND | 93 | // Clear buffers |
| 75 | let _ = vec_buf.push(0x35); // AuraLedConfig | 94 | vec_buf.clear(); |
| 76 | 95 | ||
| 77 | // DATA | 96 | // START |
| 78 | let _ = vec_buf.push(0x01); // ctrl=Breathing light | 97 | let _ = vec_buf.extend_from_slice(&START.to_be_bytes()[..]); |
| 79 | let _ = vec_buf.push(0x50); // speed=80 | 98 | |
| 80 | let _ = vec_buf.push(colour as u8); // colour=Red, Blue, Purple | 99 | // ADDRESS |
| 81 | let _ = vec_buf.push(0x00); // times=Infinite | 100 | let _ = vec_buf.extend_from_slice(&ADDRESS.to_be_bytes()[..]); |
| 82 | 101 | ||
| 83 | // SUM | 102 | // PID |
| 84 | let chk = compute_checksum(vec_buf.clone()); | 103 | let _ = vec_buf.extend_from_slice(&[0x01]); |
| 85 | let _ = write_cmd_bytes(&mut vec_buf, &chk.to_be_bytes()[..]); | 104 | |
| 86 | 105 | // LENGTH | |
| 87 | // ===== | 106 | let len: u16 = (1 + data.len() + 2).try_into().unwrap(); |
| 88 | 107 | let _ = vec_buf.extend_from_slice(&len.to_be_bytes()[..]); | |
| 89 | // Send command buffer. | 108 | |
| 90 | let data_write: [u8; 16] = vec_buf.clone().into_array().unwrap(); | 109 | // COMMAND |
| 91 | info!("write ({})='{:?}'", colour, data_write); | 110 | let _ = vec_buf.push(0x35); // Command: AuraLedConfig |
| 92 | match tx.write(&data_write).await { | 111 | |
| 93 | Ok(..) => info!("Write successful."), | 112 | // DATA |
| 94 | Err(e) => info!("Write error: {:?}", e), | 113 | let _ = vec_buf.extend_from_slice(&data); |
| 95 | } | 114 | |
| 96 | 115 | // SUM | |
| 97 | // ===== | 116 | let chk = compute_checksum(vec_buf.clone()); |
| 98 | 117 | let _ = vec_buf.extend_from_slice(&chk.to_be_bytes()[..]); | |
| 99 | // Read command buffer. | 118 | |
| 100 | let mut read_buf: [u8; 1] = [0; 1]; // Can only read one byte at a time! | 119 | // ===== |
| 101 | let mut data_read: Vec<u8, 32> = heapless::Vec::new(); // Return buffer. | 120 | |
| 102 | let mut cnt: u8 = 0; // Keep track of how many packages we've received. | 121 | // Send command buffer. |
| 103 | 122 | let data_write: [u8; 16] = vec_buf.clone().into_array().unwrap(); | |
| 104 | info!("Attempting read."); | 123 | debug!(" write='{:?}'", data_write[..]); |
| 105 | loop { | 124 | match tx.write(&data_write).await { |
| 106 | match rx.read(&mut read_buf).await { | 125 | Ok(..) => info!("Write successful."), |
| 107 | Ok(..) => (), | 126 | Err(e) => error!("Write error: {:?}", e), |
| 108 | Err(e) => info!(" Read error: {:?}", e), | 127 | } |
| 109 | } | 128 | |
| 110 | 129 | // ===== | |
| 111 | match cnt { | 130 | |
| 112 | _ => data_read.push(read_buf[0]).unwrap(), | 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."); | ||
| 113 | } | 153 | } |
| 114 | 154 | ||
| 115 | if cnt > 10 { | ||
| 116 | info!("read ({})='{:?}'", colour, data_read[..]); | ||
| 117 | break; | ||
| 118 | } | ||
| 119 | |||
| 120 | cnt = cnt + 1; | ||
| 121 | } | ||
| 122 | |||
| 123 | // ===== | ||
| 124 | |||
| 125 | if colour != 3 { | ||
| 126 | Timer::after_secs(2).await; | ||
| 127 | info!("Changing colour."); | 155 | info!("Changing colour."); |
| 128 | } | 156 | } |
| 129 | } | 157 | } |
| 130 | |||
| 131 | info!("All done.."); | ||
| 132 | } | 158 | } |
