I interact with a device using “registers” at specific “addresses”.
I respresent each address as an enum (RegisterMap) and each register as a packed struct.
pub const RegisterMap = enum(u16) {
DL_information = 0x0000,
station_address = 0x0010,
DL_control = 0x0100,
DL_control_enable_alias_address = 0x0103,
DL_status = 0x0110,
AL_control = 0x0120,
AL_status = 0x0130,
PDI_control = 0x0140,
// many more ...
}
pub const DLStatusRegister = packed struct {
pdi_operational: bool,
watchdog_ok: bool,
exteded_link_detection: bool,
reserved: u1 = 0,
port0_link_status: bool,
port1_link_status: bool,
port2_link_status: bool,
port3_link_status: bool,
port0_loop_active: bool,
port0_rx_signal_det: bool,
port1_loop_active: bool,
port1_rx_signal_det: bool,
port2_loop_active: bool,
port2_rx_signal_det: bool,
port3_loop_active: bool,
port3_rx_signal_det: bool,
};
Then I use a generic function (that only accepts packed structs) to write to the register, here is an example:
pub fn assignStationAddress(port: *Port, station_address: u16, ring_position: u16, recv_timeout_us: u32) Port.SendDatagramWkcError!void {
const autoinc_address = Subdevice.autoincAddressFromRingPos(ring_position);
try port.apwrPackWkc(
esc.ConfiguredStationAddressRegister{
.configured_station_address = station_address,
},
telegram.PositionAddress{
.autoinc_address = autoinc_address,
.offset = @intFromEnum(esc.RegisterMap.station_address),
},
recv_timeout_us,
1,
);
}
Here are some issues I have:
- There is nothing stopping me from writing to the wrong address accidentally.
DL_status = 0x0110is not tied toDLStatusRegister. - I don’t love the idea of adding a magic decl to the packed structs, like
pub const _address = 0x0110. This would likely work but I am wondering if there is a better, more type safe, and more explicit way to accomplish what I want.
The magic decl option:
pub const DLStatusRegister = packed struct {
pub const _address: u16 = 0x0110;
pdi_operational: bool,
watchdog_ok: bool,
exteded_link_detection: bool,
reserved: u1 = 0,
port0_link_status: bool,
port1_link_status: bool,
//...
}