diff --git a/firmware/rust1/src/bin/heizung.rs b/firmware/rust1/src/bin/heizung.rs index a0d06aa7f474d7799d799f721a59a66c0acd4d13..9c00da0469cbbcbfdde07d0d94795e75c80f0214 100644 --- a/firmware/rust1/src/bin/heizung.rs +++ b/firmware/rust1/src/bin/heizung.rs @@ -25,7 +25,7 @@ use heapless::String; use heizung::i2c_scan::{self, ScanResultForBus}; use heizung::modbus_server::{ModbusServer, ModbusRegisters, ModbusErrorCode, ModbusAdressMatch, U16Pusher}; -use heizung::program_info::{ProgramInfoBuilder, PinFunction}; +use heizung::program_info::{ProgramInfoBuilder, PinFunction, ConstString}; use heizung::rs485::RS485; use heizung::uf2updater::UF2UpdateHandler; use heizung::watchdog::WatchdogFixed; @@ -577,47 +577,18 @@ async fn dogfeeder(watchdog: peripherals::WATCHDOG) { 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 { +const DEFAULT_MODBUS_CONFIG_STRING: ConstString<30> = { + let mut x = ConstString::new(); + x = x.append_u32(DEFAULT_MODBUS_CONFIG_BAUDRATE); + x = x.push_str(" baud, "); + x = x.push_str("8"); + x = x.push(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)) + } as u8); + x = x.push_str("1"); + x }; fn default_modbus_config() -> uart::Config { let mut uart_config = uart::Config::default(); @@ -810,7 +781,7 @@ pub static PROGRAM_INFO: [u8; 4096] = { (29, "VCC Measurement"), ]) .program_feature_group(['C', '3'], 0x27a7c59b, "Modbus") - .feature_utf8_part::<{DEFAULT_MODBUS_CONFIG_STRING.1}>(&DEFAULT_MODBUS_CONFIG_STRING.0) + .feature_utf8(&DEFAULT_MODBUS_CONFIG_STRING.to_slice::<{DEFAULT_MODBUS_CONFIG_STRING.len()}>()) .group_done() .build() }; diff --git a/firmware/rust1/src/program_info.rs b/firmware/rust1/src/program_info.rs index eddfa311caaf3d4ecf3babfc875ac7db0af84561..8ad8cd009f2ea4b9af28331536d13394c899d918 100644 --- a/firmware/rust1/src/program_info.rs +++ b/firmware/rust1/src/program_info.rs @@ -41,7 +41,7 @@ pub enum PinFunction { NULL = 0xf, } -const fn copy(mut buf: [u8; 4096], offset: usize, source: &[u8], source_offset: usize) -> [u8; 4096] { +const fn copy<const N: usize>(mut buf: [u8; N], offset: usize, source: &[u8], source_offset: usize) -> [u8; N] { if source_offset >= source.len() { buf } else { @@ -50,18 +50,6 @@ 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; @@ -416,12 +404,102 @@ impl ProgramInfoBuilderForGroup { 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 } } + + +pub struct ConstString<const N: usize> { + buf: [u8; N], + len: usize, +} + +impl<const N: usize> ConstString<N> { + pub const fn new() -> Self { + ConstString { buf: [0; N], len: 0 } + } + + pub const fn len(self: &Self) -> usize { + self.len + } + + pub const fn to_slice<const N2: usize>(self: &Self) -> [u8; N2] { + core::assert!(N2 == self.len); + + const fn copy<const N2: usize>(mut acc: [u8; N2], source: &[u8], index: usize) -> [u8; N2] { + if index >= N2 { + acc + } else { + acc[index] = source[index]; + copy::<N2>(acc, source, index+1) + } + } + + copy::<N2>([0; N2], &self.buf, 0) + } + + pub const fn push(mut self: Self, value: u8) -> Self { + self.buf[self.len] = value; + self.len += 1; + self + } + + pub const fn push_char(self: Self, value: char) -> Self { + self.push(value as u8) + } + + pub const fn push_many(mut self: Self, xs: &[u8], from: usize, len: usize) -> Self { + const fn run<const N: usize>(mut acc: [u8; N], index: usize, offset: usize, xs: &[u8], from: usize, len: usize) -> [u8; N] { + if index >= len { + acc + } else { + acc[offset + index] = xs[from + index]; + run(acc, index+1, offset, xs, from, len) + } + } + self.buf = run(self.buf, 0, self.len, xs, from, len); + self.len += len; + self + } + + pub const fn push_const_string<const N2: usize>(self: Self, value: ConstString<N2>) -> Self { + self.push_many(&value.buf, 0, value.len) + } + + pub const fn push_str(self: Self, value: &str) -> Self { + let xs = value.as_bytes(); + self.push_many(xs, 0, xs.len()) + } + + pub const fn reverse(mut self: Self) -> Self { + const fn run<const N: usize>(mut acc: ([u8; N], usize), index: usize) -> ([u8; N], 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; + run(acc, index+1) + } + } + self.buf = run((self.buf, self.len), 0).0; + self + } + + pub const fn from_u32(value: u32) -> Self { + const fn num_to_str<const N: usize>(mut acc: ConstString<N>, value: u32) -> ConstString<N> { + if value == 0 && acc.len > 0 { + acc.reverse() + } else { + acc = acc.push('0' as u8 + (value % 10) as u8); + num_to_str(acc, value/10) + } + } + num_to_str(Self::new(), value) + } + + pub const fn append_u32(self: Self, value: u32) -> Self { + self.push_const_string(Self::from_u32(value)) + } +}