@@ -1012,6 +1012,89 @@ Return the upper byte of PMBUS_VERSION (98h). The datasheet value is 0x22.
10121012pmbus_version (dev:: DACDevice ) =
10131013 UInt8 ((read_reg (dev, PMBUS_VERSION_ADDR) >> 8 ) & 0xFF )
10141014
1015+ #= ============================================================================
1016+ Bulk slave-address configuration (datasheet §8.5.2.1.1)
1017+ =============================================================================#
1018+
1019+ """
1020+ set_dac_addresses(bus, pairs) -> Dict{UInt8, DACDevice}
1021+
1022+ Walk through datasheet §8.5.2.1.1 to assign distinct I²C slave addresses to up
1023+ to four DAC43701s sharing a bus, then snapshot each device's registers to NVM
1024+ so the new address survives power cycles.
1025+
1026+ Each entry of `pairs` is `desired_address => gpi_with`, where `desired_address`
1027+ is a 7-bit I²C address in 0x48..0x4B and `gpi_with(callback)` drives that
1028+ device's GPI line high, invokes the zero-arg `callback`, and then drives the
1029+ GPI line back low — for example:
1030+
1031+ 0x49 => function (cb)
1032+ set_high(line)
1033+ try; cb(); finally; set_low(line); end
1034+ end
1035+
1036+ Returns a `Dict` mapping each assigned 7-bit address to a freshly-opened
1037+ `DACDevice`. The bulk steps (arming GPI, writing SLAVE_ADDRESS, restoring GPI
1038+ defaults) all go through the broadcast address 0x47, so the function assumes
1039+ every device's GPI pin is held low at entry and that CONFIG2 sits at its reset
1040+ value on every device — a broadcast CONFIG2 write rewrites the whole register,
1041+ so non-default alarm-timing fields would be clobbered.
1042+ """
1043+ function set_dac_addresses (bus:: Integer , pairs)
1044+ for (addr, _) in pairs
1045+ (UInt8 (addr) >> 2 ) == 0x12 || throw (ArgumentError (
1046+ " address 0x$(string (UInt8 (addr), base= 16 , pad= 2 )) is not a valid " *
1047+ " DAC43701 slave address (must be 0x48..0x4B)" ))
1048+ end
1049+
1050+ bcast = DACDevice (I2C. open_device (Int (bus), DAC43701_ADDR_BROADCAST))
1051+ result = Dict {UInt8, DACDevice} ()
1052+ try
1053+ # Step 2: route GPI to the slave-address-program function on every
1054+ # device.
1055+ bcast. c2. GPI_CONFIG = UInt8 (GPI_SLAVE_ADDR)
1056+ flush_config2 (bcast)
1057+
1058+ # Step 3: arm GPI. Broadcast is write-only so we can't RMW TRIGGER;
1059+ # write a fully specified value with every action bit cleared.
1060+ write_reg (bcast, TRIGGER_ADDR,
1061+ as_word (TRIGGER (SW_RESET_NOOP, 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 )))
1062+
1063+ # Steps 4-7: caller raises GPI on one device, we broadcast the new
1064+ # SLAVE_ADDRESS (only that device latches it), caller drops GPI again.
1065+ for (desired_addr, gpi_with) in pairs
1066+ gpi_with () do
1067+ bcast. c2. SLAVE_ADDRESS = UInt8 (desired_addr) & 0x03
1068+ flush_config2 (bcast)
1069+ end
1070+ end
1071+
1072+ # Step 8: GPI_EN back to 0.
1073+ write_reg (bcast, TRIGGER_ADDR,
1074+ as_word (TRIGGER (SW_RESET_NOOP, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 )))
1075+ # Step 9: restore GPI_CONFIG to its reset value.
1076+ bcast. c2. GPI_CONFIG = UInt8 (GPI_PD_HIZ)
1077+ flush_config2 (bcast)
1078+
1079+ # Step 10: snapshot each device's registers into NVM. Done per-device
1080+ # at its new address so we can poll NVM_BUSY — broadcast can't read.
1081+ # `probe` confirms the address change actually landed before we touch
1082+ # NVM; otherwise a missing/mis-addressed device would silently fall
1083+ # through to the next bus participant.
1084+ for (desired_addr, _) in pairs
1085+ addr = UInt8 (desired_addr)
1086+ dev = DACDevice (I2C. open_device (Int (bus), addr))
1087+ probe (dev)
1088+ refresh_cache! (dev)
1089+ program_nvm (dev)
1090+ result[addr] = dev
1091+ end
1092+ finally
1093+ close_dac (bcast)
1094+ end
1095+ return result
1096+ end
1097+
10151098#= ============================================================================
10161099 Cleanup
10171100=============================================================================#
@@ -1053,6 +1136,8 @@ export
10531136 configure_gpi, enable_gpi, disable_gpi,
10541137 trigger_margin_high, trigger_margin_low,
10551138 # PMBus
1056- enable_pmbus, pmbus_operation, pmbus_status, clear_pmbus_cml, pmbus_version
1139+ enable_pmbus, pmbus_operation, pmbus_status, clear_pmbus_cml, pmbus_version,
1140+ # Bulk slave-address assignment
1141+ set_dac_addresses
10571142
10581143end # module DAC43701
0 commit comments