From 39b0dbf61b1296259e5ad0950a92ac897b986563 Mon Sep 17 00:00:00 2001 From: Benjamin Koch <bbbsnowball@gmail.com> Date: Sun, 11 Jun 2023 04:36:54 +0200 Subject: [PATCH] put default Modbus settings into program info --- firmware/rust1/src/bin/heizung.rs | 69 ++++++++++++++++++++++++------ firmware/rust1/src/program_info.rs | 38 +++++++++++++++- 2 files changed, 93 insertions(+), 14 deletions(-) diff --git a/firmware/rust1/src/bin/heizung.rs b/firmware/rust1/src/bin/heizung.rs index 4aa316a..a0d06aa 100644 --- a/firmware/rust1/src/bin/heizung.rs +++ b/firmware/rust1/src/bin/heizung.rs @@ -573,6 +573,60 @@ async fn dogfeeder(watchdog: peripherals::WATCHDOG) { WatchdogFixed::new(watchdog).start_and_feed_continuously().await; } +// use 19200 baud in 8E1 mode - not great but it's the Modbus default +const DEFAULT_MODBUS_CONFIG_BAUDRATE: u32 = 19200; +//const DEFAULT_MODBUS_CONFIG_BAUD = 115200*2; +const DEFAULT_MODBUS_CONFIG_PARITY: Parity = Parity::ParityEven; +const DEFAULT_MODBUS_CONFIG_STRING: ([u8; 30], usize) = { + let mut x = [0 as u8; 30]; + x[0] = '8' as u8; + x[1] = match DEFAULT_MODBUS_CONFIG_PARITY { + Parity::ParityEven => 'E', + Parity::ParityOdd => 'O', + Parity::ParityNone => 'N', + } as u8; + x[2] = '1' as u8; + x[3] = ',' as u8; + x[4] = ' ' as u8; + + const fn reverse(mut acc: ([u8; 30], usize), index: usize) -> ([u8; 30], usize) { + if index >= acc.1/2 { + acc + } else { + let x = acc.0[index]; + acc.0[index] = acc.0[acc.1-index-1]; + acc.0[acc.1-index-1] = x; + reverse(acc, index+1) + } + } + const fn num_to_str(mut acc: [u8; 30], index: usize, value: u32) -> ([u8; 30], usize) { + if value == 0 && index > 0 { + reverse((acc, index), 0) + } else { + acc[index] = '0' as u8 + (value % 10) as u8; + num_to_str(acc, index+1, value/10) + } + } + const fn append(mut acc: ([u8; 30], usize), index: usize, source: ([u8; 30], usize)) -> ([u8; 30], usize) { + if index >= source.1 { + acc + } else { + acc.0[acc.1] = source.0[index]; + acc.1 += 1; + append(acc, index+1, source) + } + } + + append((x, 5), 0, num_to_str([0 as u8; 30], 0, DEFAULT_MODBUS_CONFIG_BAUDRATE)) +}; +fn default_modbus_config() -> uart::Config { + let mut uart_config = uart::Config::default(); + uart_config.baudrate = DEFAULT_MODBUS_CONFIG_BAUDRATE; + //uart_config.baudrate = 115200*2; + uart_config.parity = DEFAULT_MODBUS_CONFIG_PARITY; + uart_config +} + //#[embassy_executor::main] async fn main2(spawner: Spawner) { let p = embassy_rp::init(Default::default()); @@ -621,13 +675,8 @@ async fn main2(spawner: Spawner) { static OUTPUTS_ACTIVE: AtomicU8 = AtomicU8::new(0); unwrap!(spawner.spawn(adc_task(&ADC_DATA, p.ADC, en_measure_current, analog_in1, current2, current1, measure_vcc, &OUTPUTS_ACTIVE))); - // use 19200 baud in 8E1 mode - not great but it's the Modbus default - let mut uart_config = uart::Config::default(); - uart_config.baudrate = 19200; - //uart_config.baudrate = 115200*2; - uart_config.parity = Parity::ParityEven; let rs485 = RS485::new( - p.UART0, rx, tx, tx_en, interrupt::take!(UART0_IRQ), p.DMA_CH1, uart_config, + p.UART0, rx, tx, tx_en, interrupt::take!(UART0_IRQ), p.DMA_CH1, default_modbus_config(), p.PIO0, p.DMA_CH0, p.DMA_CH2, ModbusServer::new(ModBusRegs { led_g, @@ -760,12 +809,8 @@ pub static PROGRAM_INFO: [u8; 4096] = { (28, "Current Measurement Channel 1"), (29, "VCC Measurement"), ]) - .program_feature("abc") - .program_feature("abc2") - .program_feature("abc 3") - .program_feature_group_with_flags(['C', '3'], 2, "def", heizung::program_info::GroupFlags::ADVANCED) - .feature("abc 4") - .feature("abc 5") + .program_feature_group(['C', '3'], 0x27a7c59b, "Modbus") + .feature_utf8_part::<{DEFAULT_MODBUS_CONFIG_STRING.1}>(&DEFAULT_MODBUS_CONFIG_STRING.0) .group_done() .build() }; diff --git a/firmware/rust1/src/program_info.rs b/firmware/rust1/src/program_info.rs index 737d355..eddfa31 100644 --- a/firmware/rust1/src/program_info.rs +++ b/firmware/rust1/src/program_info.rs @@ -50,6 +50,18 @@ const fn copy(mut buf: [u8; 4096], offset: usize, source: &[u8], source_offset: } } +const fn copy2<const N: usize, const N2: usize>(mut acc: [u8; N], source: &[u8], index: usize) -> [u8; N] { + if index >= N2 { + acc + } else { + acc[index] = source[index]; + copy2::<N, N2>(acc, source, index+1) + } +} +const fn copy3<const N: usize, const N2: usize>(source: &[u8]) -> [u8; N] { + copy2::<N, N2>([0; N], source, 0) +} + impl ProgramInfoBuilder { pub const fn new(addr: u32, info_table_size: u32, copy_table_size: u32) -> Self { let copy_table_size = copy_table_size as usize; @@ -181,7 +193,7 @@ impl ProgramInfoBuilder { } //NOTE This will push the address and then add the string so this must be the last item of the data record. - const fn push_string(mut self: Self, value: &str) -> Self { + const fn push_string_utf8(mut self: Self, value: &[u8]) -> Self { if self.data_pos - self.info_pos < value.len() + 1 { core::panic!("ProgramInfoBuilder: too much data") } @@ -190,7 +202,7 @@ impl ProgramInfoBuilder { let x1 = self.data_pos; self = self.push_u32(0); - let (self2, addr) = self.push_extra_data(value.as_bytes()); + let (self2, addr) = self.push_extra_data(value); self = self2; (self, _) = self.push_extra_data(&[0]); @@ -203,6 +215,11 @@ impl ProgramInfoBuilder { self } + //NOTE This will push the address and then add the string so this must be the last item of the data record. + const fn push_string(self: Self, value: &str) -> Self { + self.push_string_utf8(value.as_bytes()) + } + const fn append_to_last_string(mut self: Self, value: &str) -> Self { if self.data_pos - self.info_pos < value.len() { core::panic!("ProgramInfoBuilder: too much data") @@ -231,6 +248,14 @@ impl ProgramInfoBuilder { .push_string(value) } + const fn bi_string_utf8(self: Self, tag: [char; 2], id: u32, value: &[u8]) -> Self { + self.push_current_info_ptr() + .push_u16(Self::BINARY_INFO_TYPE_ID_AND_STRING) + .push_tag(tag) + .push_u32(id) + .push_string_utf8(value) + } + const fn bi_named_group(self: Self, tag: [char; 2], id: u32, flags: u16, group_tag: [char; 2], group_id: u32, label: &str) -> Self { self.push_current_info_ptr() .push_u16(Self::BINARY_INFO_TYPE_NAMED_GROUP) @@ -387,6 +412,15 @@ impl ProgramInfoBuilderForGroup { self.builder = self.builder.bi_string(self.tag, self.id, name); self } + pub const fn feature_utf8(mut self: Self, name: &[u8]) -> Self { + self.builder = self.builder.bi_string_utf8(self.tag, self.id, name); + self + } + pub const fn feature_utf8_part<const N: usize>(mut self: Self, name: &[u8]) -> Self { + let name: [u8; N] = copy3::<N, N>(name); + self.builder = self.builder.bi_string_utf8(self.tag, self.id, &name); + self + } pub const fn group_done(self: Self) -> ProgramInfoBuilder { self.builder } -- GitLab