diff --git a/api/python/arrus/utils/imaging.py b/api/python/arrus/utils/imaging.py index b1721a144..a732a6dfa 100644 --- a/api/python/arrus/utils/imaging.py +++ b/api/python/arrus/utils/imaging.py @@ -1963,12 +1963,16 @@ def prepare(self, const_metadata: arrus.metadata.ConstMetadata): # TODO constant memory self._frame_offsets = cp.asarray(frame_offsets) # For each us4OEM, get number of physical frames this us4OEM gathers. - # Note: this is the max number of us4OEM IN USE. + # Note: this is the max number of us4OEMs IN USE. n_us4oems = cp.max(self._fcm_us4oems).get()+1 n_frames_us4oems = [] for us4oem in range(n_us4oems): - n_frames_us4oem = cp.max(self._fcm_frames[self._fcm_us4oems == us4oem]) - n_frames_us4oems.append(n_frames_us4oem) + us4oem_frames = self._fcm_frames[self._fcm_us4oems == us4oem] + if us4oem_frames.size == 0: + n_frames_us4oems.append(0) + else: + n_frames_us4oem = cp.max(us4oem_frames).get().item() + n_frames_us4oems.append(n_frames_us4oem) # TODO constant memory self._n_frames_us4oems = cp.asarray(n_frames_us4oems, dtype=cp.uint32)+1 diff --git a/arrus/cfg/default.dict b/arrus/cfg/default.dict index 9bcb7a64e..678febb6a 100644 --- a/arrus/cfg/default.dict +++ b/arrus/cfg/default.dict @@ -140,41 +140,73 @@ probe_adapter_models: [ } ] }, - - { - id: { - manufacturer: "us4us" - name: "esaote3-us4r6" - } - n_channels: 192 - channel_mapping_regions: [ - { - us4oem: 0, - region: {begin: 0, end: 31} - }, - { - us4oem: 3, - region: {begin: 0, end: 31} - }, - { - us4oem: 1, - region: {begin: 0, end: 31} - }, - { - us4oem: 4, - region: {begin: 0, end: 31} - }, - { - us4oem: 2, - region: {begin: 0, end: 31} - }, - { - us4oem: 5, - region: {begin: 0, end: 31} - } - ] - }, - + { + # DEPRECATED, use esaote3-us4r + id: { + manufacturer: "us4us" + name: "esaote3-us4r6" + } + n_channels: 192 + channel_mapping_regions: [ + { + us4oem: 0, + region: {begin: 0, end: 31} + }, + { + us4oem: 3, + region: {begin: 0, end: 31} + }, + { + us4oem: 1, + region: {begin: 0, end: 31} + }, + { + us4oem: 4, + region: {begin: 0, end: 31} + }, + { + us4oem: 2, + region: {begin: 0, end: 31} + }, + { + us4oem: 5, + region: {begin: 0, end: 31} + } + ] + }, + { + id: { + manufacturer: "us4us" + name: "esaote3-us4r" + } + n_channels: 192 + channel_mapping_regions: [ + { + us4oem: 0, + region: {begin: 0, end: 31} + }, + { + us4oem: 3, + region: {begin: 0, end: 31} + }, + { + us4oem: 1, + region: {begin: 0, end: 31} + }, + { + us4oem: 4, + region: {begin: 0, end: 31} + }, + { + us4oem: 2, + region: {begin: 0, end: 31} + }, + { + us4oem: 5, + region: {begin: 0, end: 31} + } + ] + }, { id: { manufacturer: "us4us" @@ -283,35 +315,36 @@ probe_adapter_models: [ channel_mapping_regions: [ { us4oem: 0 - channels: [31, 30, 29, 28, 27, 26, 25, 24, - 23, 22, 21, 20, 19, 18, 17, 15, - 16, 14, 13, 12, 11, 10, 9, 8, - 7, 6, 5, 4, 3, 2, 1, 0] + channels: [31, 30, 29, 28, 27, 26, 25, 24, + 23, 22, 21, 20, 19, 18, 17, 15, + 16, 14, 13, 12, 11, 10, 9, 8, + 7, 6, 5, 4, 3, 2, 1, 0] }, { us4oem: 1 channels: [32, 33, 34, 35, 36, 37, 38, 39, - 40, 41, 42, 43, 44, 45, 46, 48, - 47, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63] + 40, 41, 42, 43, 44, 45, 46, 48, + 47, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63] }, { us4oem: 0 channels: [95, 94, 93, 92, 91, 90, 89, 88, - 87, 86, 85, 84, 83, 82, 81, 79, - 80, 78, 77, 76, 75, 74, 73, 72, - 71, 70, 69, 68, 67, 66, 65, 64] + 87, 86, 85, 84, 83, 82, 81, 79, + 80, 78, 77, 76, 75, 74, 73, 72, + 71, 70, 69, 68, 67, 66, 65, 64] }, { us4oem: 1 channels: [96, 97, 98, 99, 100, 101, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 112, - 111, 113, 114, 115, 116, 117, 118, 119, - 120, 121, 122, 123, 124, 125, 126, 127] + 104, 105, 106, 107, 108, 109, 110, 112, + 111, 113, 114, 115, 116, 117, 118, 119, + 120, 121, 122, 123, 124, 125, 126, 127] } ] }, { + # DEPRECATED, use atl/philips-us4r id: { manufacturer: "us4us" name: "atl/philips-us4r4" @@ -351,6 +384,381 @@ probe_adapter_models: [ 7, 6, 5, 4, 3, 2, 1, 0] } ] + }, + { + id: { + manufacturer: "us4us" + name: "atl/philips-us4r" + } + n_channels: 128 + channel_mapping_regions: [ + { + # BLUE, A + us4oem: 0 + channels: [31, 30, 29, 28, 27, 26, 25, 24, + 23, 22, 21, 20, 19, 18, 17, 15, + 16, 14, 13, 12, 11, 10, 9, 8, + 7, 6, 5, 4, 3, 2, 1, 0] + }, + { + # BLUE, C + us4oem: 1 + channels: [31, 30, 29, 28, 27, 26, 25, 24, + 23, 22, 21, 20, 19, 18, 17, 15, + 16, 14, 13, 12, 11, 10, 9, 8, + 7, 6, 5, 4, 3, 2, 1, 0] + }, + { + # GREEN, F + us4oem: 2 + channels: [31, 30, 29, 28, 27, 26, 25, 24, + 23, 22, 21, 20, 19, 18, 17, 15, + 16, 14, 13, 12, 11, 10, 9, 8, + 7, 6, 5, 4, 3, 2, 1, 0] + }, + { + # GREEN, H + us4oem: 3 + channels: [31, 30, 29, 28, 27, 26, 25, 24, + 23, 22, 21, 20, 19, 18, 17, 15, + 16, 14, 13, 12, 11, 10, 9, 8, + 7, 6, 5, 4, 3, 2, 1, 0] + } + ] + }, + { + id: { + manufacturer: "us4us" + name: "ultrasonix-us4r" + } + n_channels: 128 + channel_mapping_regions: [ + { + us4oem: 0 + channels: [0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31] + }, + { + us4oem: 1 + channels: [31, 30, 29, 28, 27, 26, 25, 24, + 23, 22, 21, 20, 19, 18, 17, 16, + 15, 14, 13, 12, 11, 10, 9, 8, + 7, 6, 5, 4, 3, 2, 1, 0] + }, + { + us4oem: 2 + channels: [0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31] + }, + { + us4oem: 3 + channels: [31, 30, 29, 28, 27, 26, 25, 24, + 23, 22, 21, 20, 19, 18, 17, 16, + 15, 14, 13, 12, 11, 10, 9, 8, + 7, 6, 5, 4, 3, 2, 1, 0] + } + ] + }, + { + id: { + manufacturer: "us4us" + name: "3d" + } + n_channels: 1024 + channel_mapping_regions: [ + { + us4oem: 7 + channels: [ + 117, 119, 121, 125, 127, 96, 98, 100, + 102, 104, 115, 126, 123, 106, 107, 103, + 108, 97, 124, 113, 116, 112, 111, 105, + 101, 110, 99, 122, 120, 118, 114, 109 + ] + }, + { + us4oem: 5 + channels: [ + 117, 119, 121, 125, 127, 96, 98, 100, + 102, 104, 115, 126, 123, 106, 107, 103, + 108, 97, 124, 113, 116, 112, 111, 105, + 101, 110, 99, 122, 120, 118, 114, 109 + ] + }, + { + us4oem: 3 + channels: [ + 117, 119, 121, 125, 127, 96, 98, 100, + 102, 104, 115, 126, 123, 106, 107, 103, + 108, 97, 124, 113, 116, 112, 111, 105, + 101, 110, 99, 122, 120, 118, 114, 109 + ] + }, + { + us4oem: 1 + channels: [ + 117, 119, 121, 125, 127, 96, 98, 100, + 102, 104, 115, 126, 123, 106, 107, 103, + 108, 97, 124, 113, 116, 112, 111, 105, + 101, 110, 99, 122, 120, 118, 114, 109 + ] + }, + { + us4oem: 6 + channels: [ + 126, 127, 125, 122, 99, 98, 96, 121, + 124, 123, 101, 103, 100, 97, 108, 117, + 112, 118, 120, 102, 105, 109, 106, 113, + 115, 119, 114, 116, 107, 104, 111, 110 + ] + }, + { + us4oem: 4 + channels: [ + 126, 127, 125, 122, 99, 98, 96, 121, + 124, 123, 101, 103, 100, 97, 108, 117, + 112, 118, 120, 102, 105, 109, 106, 113, + 115, 119, 114, 116, 107, 104, 111, 110 + ] + }, + { + us4oem: 2 + channels: [ + 126, 127, 125, 122, 99, 98, 96, 121, + 124, 123, 101, 103, 100, 97, 108, 117, + 112, 118, 120, 102, 105, 109, 106, 113, + 115, 119, 114, 116, 107, 104, 111, 110 + ] + }, + { + us4oem: 0 + channels: [ + 126, 127, 125, 122, 99, 98, 96, 121, + 124, 123, 101, 103, 100, 97, 108, 117, + 112, 118, 120, 102, 105, 109, 106, 113, + 115, 119, 114, 116, 107, 104, 111, 110 + ] + }, + { + us4oem: 7 + channels: [ + 65, 67, 69, 71, 86, 95, 88, 92, + 94, 75, 66, 73, 64, 91, 93, 89, + 90, 78, 76, 74, 70, 68, 87, 82, + 80, 79, 77, 72, 84, 85, 83, 81 + ] + }, + { + us4oem: 5 + channels: [ + 65, 67, 69, 71, 86, 95, 88, 92, + 94, 75, 66, 73, 64, 91, 93, 89, + 90, 78, 76, 74, 70, 68, 87, 82, + 80, 79, 77, 72, 84, 85, 83, 81 + ] + }, + { + us4oem: 3 + channels: [ + 65, 67, 69, 71, 86, 95, 88, 92, + 94, 75, 66, 73, 64, 91, 93, 89, + 90, 78, 76, 74, 70, 68, 87, 82, + 80, 79, 77, 72, 84, 85, 83, 81 + ] + }, + { + us4oem: 1 + channels: [ + 65, 67, 69, 71, 86, 95, 88, 92, + 94, 75, 66, 73, 64, 91, 93, 89, + 90, 78, 76, 74, 70, 68, 87, 82, + 80, 79, 77, 72, 84, 85, 83, 81 + ] + }, + { + us4oem: 6 + channels: [ + 66, 64, 88, 95, 94, 68, 70, 67, + 76, 81, 82, 89, 92, 90, 65, 74, + 73, 75, 80, 84, 86, 93, 72, 69, + 71, 78, 77, 79, 83, 85, 87, 91 + ] + }, + { + us4oem: 4 + channels: [ + 66, 64, 88, 95, 94, 68, 70, 67, + 76, 81, 82, 89, 92, 90, 65, 74, + 73, 75, 80, 84, 86, 93, 72, 69, + 71, 78, 77, 79, 83, 85, 87, 91 + ] + }, + { + us4oem: 2 + channels: [ + 66, 64, 88, 95, 94, 68, 70, 67, + 76, 81, 82, 89, 92, 90, 65, 74, + 73, 75, 80, 84, 86, 93, 72, 69, + 71, 78, 77, 79, 83, 85, 87, 91 + ] + }, + { + us4oem: 0 + channels: [ + 66, 64, 88, 95, 94, 68, 70, 67, + 76, 81, 82, 89, 92, 90, 65, 74, + 73, 75, 80, 84, 86, 93, 72, 69, + 71, 78, 77, 79, 83, 85, 87, 91 + ] + }, + { + us4oem: 7 + channels: [ + 55, 56, 57, 60, 62, 32, 34, 37, + 38, 39, 52, 54, 58, 63, 33, 36, + 40, 41, 48, 50, 53, 59, 61, 35, + 43, 47, 45, 51, 49, 46, 44, 42 + ] + }, + { + us4oem: 5 + channels: [ + 55, 56, 57, 60, 62, 32, 34, 37, + 38, 39, 52, 54, 58, 63, 33, 36, + 40, 41, 48, 50, 53, 59, 61, 35, + 43, 47, 45, 51, 49, 46, 44, 42 + ] + }, + { + us4oem: 3 + channels: [ + 55, 56, 57, 60, 62, 32, 34, 37, + 38, 39, 52, 54, 58, 63, 33, 36, + 40, 41, 48, 50, 53, 59, 61, 35, + 43, 47, 45, 51, 49, 46, 44, 42 + ] + }, + { + us4oem: 1 + channels: [ + 55, 56, 57, 60, 62, 32, 34, 37, + 38, 39, 52, 54, 58, 63, 33, 36, + 40, 41, 48, 50, 53, 59, 61, 35, + 43, 47, 45, 51, 49, 46, 44, 42 + ] + }, + { + us4oem: 6 + channels: [ + 61, 60, 59, 58, 32, 37, 63, 62, + 57, 56, 39, 36, 34, 35, 33, 40, + 51, 54, 55, 41, 38, 45, 47, 48, + 49, 50, 52, 53, 43, 42, 44, 46 + ] + }, + { + us4oem: 4 + channels: [ + 61, 60, 59, 58, 32, 37, 63, 62, + 57, 56, 39, 36, 34, 35, 33, 40, + 51, 54, 55, 41, 38, 45, 47, 48, + 49, 50, 52, 53, 43, 42, 44, 46 + ] + }, + { + us4oem: 2 + channels: [ + 61, 60, 59, 58, 32, 37, 63, 62, + 57, 56, 39, 36, 34, 35, 33, 40, + 51, 54, 55, 41, 38, 45, 47, 48, + 49, 50, 52, 53, 43, 42, 44, 46 + ] + }, + { + us4oem: 0 + channels: [ + 61, 60, 59, 58, 32, 37, 63, 62, + 57, 56, 39, 36, 34, 35, 33, 40, + 51, 54, 55, 41, 38, 45, 47, 48, + 49, 50, 52, 53, 43, 42, 44, 46 + ] + }, + { + us4oem: 7 + channels: [ + 0, 1, 2, 4, 27, 28, 29, 30, + 31, 9, 3, 5, 6, 25, 24, 20, + 26, 14, 13, 11, 7, 8, 23, 19, + 16, 15, 12, 10, 22, 21, 18, 17 + ] + }, + { + us4oem: 5 + channels: [ + 0, 1, 2, 4, 27, 28, 29, 30, + 31, 9, 3, 5, 6, 25, 24, 20, + 26, 14, 13, 11, 7, 8, 23, 19, + 16, 15, 12, 10, 22, 21, 18, 17 + ] + }, + { + us4oem: 3 + channels: [ + 0, 1, 2, 4, 27, 28, 29, 30, + 31, 9, 3, 5, 6, 25, 24, 20, + 26, 14, 13, 11, 7, 8, 23, 19, + 16, 15, 12, 10, 22, 21, 18, 17 + ] + }, + { + us4oem: 1 + channels: [ + 0, 1, 2, 4, 27, 28, 29, 30, + 31, 9, 3, 5, 6, 25, 24, 20, + 26, 14, 13, 11, 7, 8, 23, 19, + 16, 15, 12, 10, 22, 21, 18, 17 + ] + }, + { + us4oem: 6 + channels: [ + 0, 1, 31, 27, 29, 2, 3, 5, + 14, 15, 22, 21, 30, 25, 4, 8, + 12, 11, 18, 17, 19, 23, 6, 7, + 10, 9, 13, 16, 20, 24, 26, 28 + ] + }, + { + us4oem: 4 + channels: [ + 0, 1, 31, 27, 29, 2, 3, 5, + 14, 15, 22, 21, 30, 25, 4, 8, + 12, 11, 18, 17, 19, 23, 6, 7, + 10, 9, 13, 16, 20, 24, 26, 28 + ] + }, + { + us4oem: 2 + channels: [ + 0, 1, 31, 27, 29, 2, 3, 5, + 14, 15, 22, 21, 30, 25, 4, 8, + 12, 11, 18, 17, 19, 23, 6, 7, + 10, 9, 13, 16, 20, 24, 26, 28 + ] + }, + { + us4oem: 0 + channels: [ + 0, 1, 31, 27, 29, 2, 3, 5, + 14, 15, 22, 21, 30, 25, 4, 8, + 12, 11, 18, 17, 19, 23, 6, 7, + 10, 9, 13, 16, 20, 24, 26, 28 + ] + } + ] } ] probe_models: [ @@ -500,6 +908,22 @@ probe_models: [ end: 15 } }, + { + id: { + manufacturer: "vermon" + name: "mat-3d" + } + n_elements: 1024, + pitch: 0.1e-3, + tx_frequency_range: { + begin: 1e6, + end: 10e6 + }, + voltage_range: { + begin: 0, + end: 10 + } + }, { id: { manufacturer: "atl/philips" @@ -612,6 +1036,10 @@ probe_to_adapter_connections: [ { manufacturer: "us4us" name: "esaote3-us4r6" + }, + { + manufacturer: "us4us" + name: "esaote3-us4r" } ] channel_mapping_ranges: { @@ -644,6 +1072,10 @@ probe_to_adapter_connections: [ { manufacturer: "us4us" name: "esaote3-us4r6" + }, + { + manufacturer: "us4us" + name: "esaote3-us4r" } ] channel_mapping_ranges: { @@ -657,7 +1089,7 @@ probe_to_adapter_connections: [ name: "ac2541" } probe_adapter_model_id: [ - { + { manufacturer: "us4us" name: "esaote" }, @@ -665,9 +1097,13 @@ probe_to_adapter_connections: [ manufacturer: "us4us" name: "esaote2" }, - { + { manufacturer: "us4us" name: "esaote3" + }, + { + manufacturer: "us4us" + name: "esaote3-us4r" } ] channel_mapping_ranges: { @@ -689,10 +1125,10 @@ probe_to_adapter_connections: [ manufacturer: "us4us" name: "esaote2" }, - { - manufacturer: "us4us" - name: "esaote3" - } + { + manufacturer: "us4us" + name: "esaote3" + } ] channel_mapping_ranges: [ { @@ -714,6 +1150,10 @@ probe_to_adapter_connections: [ { manufacturer: "us4us" name: "ultrasonix" + }, + { + manufacturer: "us4us" + name: "ultrasonix-us4r" } ] channel_mapping_ranges: { @@ -753,6 +1193,22 @@ probe_to_adapter_connections: [ end: 127 } }, + { + probe_model_id: { + manufacturer: "vermon" + name: "mat-3d" + } + probe_adapter_model_id: [ + { + manufacturer: "us4us" + name: "3d" + } + ] + channel_mapping_ranges: { + begin: 0 + end: 1023 + } + }, { probe_model_id: { manufacturer: "atl/philips" @@ -766,6 +1222,10 @@ probe_to_adapter_connections: [ { manufacturer: "us4us" name: "atl/philips-us4r4" + }, + { + manufacturer: "us4us" + name: "atl/philips-us4r" } ] channel_mapping_ranges: { diff --git a/arrus/core/api/devices/us4r/Us4RSettings.h b/arrus/core/api/devices/us4r/Us4RSettings.h index 6fec901f1..9e91459a4 100644 --- a/arrus/core/api/devices/us4r/Us4RSettings.h +++ b/arrus/core/api/devices/us4r/Us4RSettings.h @@ -18,8 +18,11 @@ class Us4RSettings { public: using ReprogrammingMode = Us4OEMSettings::ReprogrammingMode; - explicit Us4RSettings(std::vector us4OemSettings, std::optional hvSettings) - : us4oemSettings(std::move(us4OemSettings)), hvSettings(std::move(hvSettings)) {} + explicit Us4RSettings(std::vector us4OemSettings, std::optional hvSettings, + std::optional nUs4OEMs = std::nullopt, + std::vector adapterToUs4RModuleNumber = {}) + : us4oemSettings(std::move(us4OemSettings)), hvSettings(std::move(hvSettings)), + nUs4OEMs(nUs4OEMs), adapterToUs4RModuleNumber(std::move(adapterToUs4RModuleNumber)){} Us4RSettings( ProbeAdapterSettings probeAdapterSettings, @@ -28,14 +31,19 @@ class Us4RSettings { std::optional hvSettings, std::vector channelsMask, std::vector> us4oemChannelsMask, - ReprogrammingMode reprogrammingMode = ReprogrammingMode::SEQUENTIAL) - : probeAdapterSettings(std::move(probeAdapterSettings)), + ReprogrammingMode reprogrammingMode = ReprogrammingMode::SEQUENTIAL, + std::optional nUs4OEMs = std::nullopt, + std::vector adapterToUs4RModuleNumber = {} + ) : probeAdapterSettings(std::move(probeAdapterSettings)), probeSettings(std::move(probeSettings)), rxSettings(std::move(rxSettings)), hvSettings(std::move(hvSettings)), channelsMask(std::move(channelsMask)), us4oemChannelsMask(std::move(us4oemChannelsMask)), - reprogrammingMode(reprogrammingMode) {} + reprogrammingMode(reprogrammingMode), + nUs4OEMs(nUs4OEMs), + adapterToUs4RModuleNumber(std::move(adapterToUs4RModuleNumber)) + {} const std::vector &getUs4OEMSettings() const { return us4oemSettings; @@ -70,6 +78,14 @@ class Us4RSettings { return reprogrammingMode; } + const std::optional &getNumberOfUs4oems() const { + return nUs4OEMs; + } + + const std::vector &getAdapterToUs4RModuleNumber() const { + return adapterToUs4RModuleNumber; + } + private: /* A list of settings for Us4OEMs. * First element configures Us4OEM:0, second: Us4OEM:1, etc. */ @@ -94,8 +110,18 @@ class Us4RSettings { * the system us4r channels, and this way we reduce the chance of mistake. */ std::vector> us4oemChannelsMask; /** Reprogramming mode applied to all us4OEMs. - * See Us4OEMSettings::ReprogrammingMode docs for more information.*/ + * See Us4OEMSettings::ReprogrammingMode docs for more information. */ ReprogrammingMode reprogrammingMode; + /** Number of us4OEMs in the us4R system. Optional, if is std::nullopt, + * the number of us4oems is determined based on the probe adapter mapping + * (equal to the maximum ordinal number of us4OEM). Optional, if set to + * std::nullopt, the number of us4OEMs will be determined based on the + * probe adapter mapping (as the maximum of us4OEM module ordinal numbers). */ + std::optional nUs4OEMs = std::nullopt; + /** The mapping from the us4OEM ordinal number in the probe adapter mapping + * and the actual ordinal number of us4OEM. Optional, empty vector means that + * no mapping should be applied (identity mapping). */ + std::vector adapterToUs4RModuleNumber = {}; }; } diff --git a/arrus/core/common/collections.h b/arrus/core/common/collections.h index 8e5534a1d..a1510b881 100644 --- a/arrus/core/common/collections.h +++ b/arrus/core/common/collections.h @@ -80,9 +80,9 @@ zip(const std::vector &a, const std::vector &b) { throw std::runtime_error("Zipped vectors should have the same size."); } std::vector> res; - res.reserve(a.size()); - for(const auto &[x, y] : boost::combine(a, b)) { - res.emplace_back(x, y); + res.resize(a.size()); + for(size_t i = 0; i < res.size(); ++i) { + res[i] = std::make_pair(a[i], b[i]); } return res; } @@ -204,6 +204,32 @@ inline V getUnique(const std::vector &input, std::function acces return *std::begin(values); } +template +std::vector rank(const std::vector &values) { + using ValueWithPos = std::pair; + std::vector values_sorted(values.size()); + std::vector result(values.size()); + + if (values.empty()) { + return result; + } + + for(size_t i = 0; i < values.size(); ++i) { + values_sorted[i] = std::make_pair(values[i], i); + } + std::sort(std::begin(values_sorted), std::end(values_sorted), + [](const ValueWithPos &a, const ValueWithPos &b){return a.first < b.first;}); + ValueWithPos prev{values_sorted[0].first, static_cast(0)}; + for(size_t i = 0; i < result.size(); ++i) { + auto &v = values_sorted[i]; + if(prev.first != v.first) { + prev = std::make_pair(v.first, i); + } + result[v.second] = prev.second; + } + return result; +} + } #endif //ARRUS_CORE_COMMON_COLLECTIONS_H diff --git a/arrus/core/devices/probe/ProbeFactory.h b/arrus/core/devices/probe/ProbeFactory.h index e9c6825c3..d24815082 100644 --- a/arrus/core/devices/probe/ProbeFactory.h +++ b/arrus/core/devices/probe/ProbeFactory.h @@ -7,9 +7,8 @@ namespace arrus::devices { class ProbeFactory { public: - virtual ProbeImplBase::Handle - getProbe(const ProbeSettings &settings, - ProbeAdapterImplBase::RawHandle adapter) = 0; + virtual ProbeImplBase::Handle getProbe(const ProbeSettings &settings,ProbeAdapterImplBase::RawHandle adapter) = 0; + virtual ~ProbeFactory() = default; }; } diff --git a/arrus/core/devices/us4r/Us4RFactory.h b/arrus/core/devices/us4r/Us4RFactory.h index c7b634b6e..6b3cc3d30 100644 --- a/arrus/core/devices/us4r/Us4RFactory.h +++ b/arrus/core/devices/us4r/Us4RFactory.h @@ -10,8 +10,9 @@ class Us4RFactory { public: using Handle = std::unique_ptr; - virtual Us4R::Handle - getUs4R(Ordinal ordinal, const Us4RSettings &settings) = 0; + virtual Us4R::Handle getUs4R(Ordinal ordinal, const Us4RSettings &settings) = 0; + + virtual ~Us4RFactory() = default; }; } diff --git a/arrus/core/devices/us4r/Us4RFactoryImpl.h b/arrus/core/devices/us4r/Us4RFactoryImpl.h index 76d160dc3..415205848 100644 --- a/arrus/core/devices/us4r/Us4RFactoryImpl.h +++ b/arrus/core/devices/us4r/Us4RFactoryImpl.h @@ -43,6 +43,7 @@ class Us4RFactoryImpl : public Us4RFactory { DeviceId id(DeviceType::Us4R, ordinal); // Validate us4r settings (general). + // TODO validate nus4oems and mapping Us4RSettingsValidator validator(ordinal); validator.validate(settings); validator.throwOnErrors(); @@ -64,7 +65,10 @@ class Us4RFactoryImpl : public Us4RFactory { auto[us4OEMSettings, adapterSettings] = us4RSettingsConverter->convertToUs4OEMSettings( probeAdapterSettings, probeSettings, rxSettings, settings.getChannelsMask(), - settings.getReprogrammingMode()); + settings.getReprogrammingMode(), + settings.getNumberOfUs4oems(), + settings.getAdapterToUs4RModuleNumber() + ); // verify if the generated us4oemSettings.channelsMask is equal to us4oemChannelsMask field validateChannelsMasks(us4OEMSettings, settings.getUs4OEMChannelsMask()); @@ -95,21 +99,16 @@ class Us4RFactoryImpl : public Us4RFactory { ARRUS_REQUIRES_TRUE_E( us4oemSettings.size() == us4oemChannelsMasks.size(), ::arrus::IllegalArgumentException( - ::arrus::format("There should be exactly {} us4oem channels masks " - "in the system configuration.", us4oemSettings.size()) - ) + format("There should be exactly {} us4oem channels masks in the system configuration.", + us4oemSettings.size())) ); - for (unsigned i = 0; i < us4oemSettings.size(); ++i) { auto &setting = us4oemSettings[i]; - std::unordered_set us4oemMask(std::begin(us4oemChannelsMasks[i]), std::end(us4oemChannelsMasks[i])); - ARRUS_REQUIRES_TRUE_E( setting.getChannelsMask() == us4oemMask, ::arrus::IllegalArgumentException( - ::arrus::format( - "The provided us4r channels masks does not match the provided us4oem channels masks, " + format("The provided us4r channels masks does not match the provided us4oem channels masks, " "for us4oem {}", i)) ); } @@ -140,6 +139,7 @@ class Us4RFactoryImpl : public Us4RFactory { ArrusException("Values are not equal: ius4oem size, us4oem settings size")); for (unsigned i = 0; i < ius4oems.size(); ++i) { + // TODO(Us4R-10) use ius4oem->GetDeviceID() as an ordinal number, instead of value of i us4oems.push_back(us4oemFactory->getUs4OEM(static_cast(i), ius4oems[i], us4oemCfgs[i])); } return {std::move(us4oems), master}; diff --git a/arrus/core/devices/us4r/Us4RSettingsConverter.h b/arrus/core/devices/us4r/Us4RSettingsConverter.h index 7686bade1..d9eadd6e6 100644 --- a/arrus/core/devices/us4r/Us4RSettingsConverter.h +++ b/arrus/core/devices/us4r/Us4RSettingsConverter.h @@ -27,7 +27,11 @@ class Us4RSettingsConverter { const ProbeSettings &probeSettings, const RxSettings &rxSettings, const std::vector &channelsMask, - Us4OEMSettings::ReprogrammingMode reprogrammingMode) = 0; + Us4OEMSettings::ReprogrammingMode reprogrammingMode, + std::optional nUs4OEMs, + const std::vector &adapterToUs4RModuleNr) = 0; + + virtual ~Us4RSettingsConverter() = default; }; } diff --git a/arrus/core/devices/us4r/Us4RSettingsConverterImpl.h b/arrus/core/devices/us4r/Us4RSettingsConverterImpl.h index 1aa290d16..7a91c88f1 100644 --- a/arrus/core/devices/us4r/Us4RSettingsConverterImpl.h +++ b/arrus/core/devices/us4r/Us4RSettingsConverterImpl.h @@ -10,25 +10,39 @@ namespace arrus::devices { class Us4RSettingsConverterImpl : public Us4RSettingsConverter { public: + std::pair, ProbeAdapterSettings> convertToUs4OEMSettings(const ProbeAdapterSettings &probeAdapterSettings, const ProbeSettings &probeSettings, const RxSettings &rxSettings, const std::vector &channelsMask, - Us4OEMSettings::ReprogrammingMode reprogrammingMode) override { - + Us4OEMSettings::ReprogrammingMode reprogrammingMode, + std::optional nUs4OEMsSetting, + const std::vector &adapterToUs4RModuleNr) override { + typedef ProbeAdapterSettings PAS; // Assumption: // for each module there is N_RX_CHANNELS*k elements in mapping // each group of N_RX_CHANNELS contains elements grouped to a single bucket (i*32, (i+1)*32) - const auto &adapterSettingsMapping = - probeAdapterSettings.getChannelMapping(); - const auto &probeSettingsMapping = probeSettings.getChannelMapping(); + PAS::ChannelMapping adapterMapping; + Ordinal nUs4OEMs = 0; + const auto &probeMapping = probeSettings.getChannelMapping(); - // get number of us4oems from the probe adapter mapping - // Determined based on ADAPTER MAPPINGS - Ordinal nUs4OEMs = getNumberOfModules(adapterSettingsMapping); - // Convert to list of us4oem mappings and active channel groups + if(! adapterToUs4RModuleNr.empty()) { + adapterMapping = remapUs4OEMs(probeAdapterSettings.getChannelMapping(), adapterToUs4RModuleNr); + } + else { + adapterMapping = probeAdapterSettings.getChannelMapping(); + } + if(nUs4OEMsSetting.has_value()) { + nUs4OEMs = nUs4OEMsSetting.value(); + } + else { + // get number of us4oems from the probe adapter mapping + // Determined based on ADAPTER MAPPINGS + nUs4OEMs = getNumberOfModules(adapterMapping); + } + // Convert to list of us4oem mappings and active channel groups auto const nRx = Us4OEMImpl::N_RX_CHANNELS; auto const nTx = Us4OEMImpl::N_TX_CHANNELS; auto const actChSize = Us4OEMImpl::ACTIVE_CHANNEL_GROUP_SIZE; @@ -54,7 +68,7 @@ class Us4RSettingsConverterImpl : public Us4RSettingsConverter { // Map settings to: // - internal us4oem mapping, // - adapter channel mapping - for(auto[module, channel] : probeAdapterSettings.getChannelMapping()) { + for(auto[module, channel] : adapterMapping) { // Channel mapping const auto group = channel / nRx; const auto element = currentRxGroupElement[module]; @@ -63,22 +77,17 @@ class Us4RSettingsConverterImpl : public Us4RSettingsConverter { currentRxGroup[module] = (ChannelIdx) group; } else { // Safety condition - ARRUS_REQUIRES_TRUE(group == currentRxGroup[module], - "Invalid probe adapter Rx channel mapping: " - "inconsistent groups of channel " - "(consecutive elements of N_RX_CHANNELS " - "are required)"); + ARRUS_REQUIRES_TRUE( + group == currentRxGroup[module], + "Invalid probe adapter Rx channel mapping: inconsistent groups of channel " + "(consecutive elements of N_RX_CHANNELS are required)"); } auto logicalChannel = group * nRx + element; us4oemChannelMapping[module][logicalChannel] = channel; - adapterChannelMapping.emplace_back(module, - ChannelIdx(logicalChannel)); - - currentRxGroupElement[module] = - (currentRxGroupElement[module] + 1) % nRx; + adapterChannelMapping.emplace_back(module, ChannelIdx(logicalChannel)); + currentRxGroupElement[module] = (currentRxGroupElement[module] + 1) % nRx; } - // Active channel groups for us4oems std::vector activeChannelGroups; // Initialize masks @@ -86,14 +95,13 @@ class Us4RSettingsConverterImpl : public Us4RSettingsConverter { // all groups turned off activeChannelGroups.emplace_back(nActChGroups); } - for(const auto adapterChannel : probeSettingsMapping) { + for(const auto adapterChannel : probeMapping) { auto[module, logicalChannel] = adapterChannelMapping[adapterChannel]; auto us4oemChannel = us4oemChannelMapping[module][logicalChannel]; // When at least one channel in group has mapping, the whole // group of channels has to be active activeChannelGroups[module][us4oemChannel / actChSize] = true; } - // CHANNELS MASKS PRODUCTION // convert probe channels masks to adapter channels mask: // - for each masked channel find the adapter's channel @@ -101,48 +109,34 @@ class Us4RSettingsConverterImpl : public Us4RSettingsConverter { // - for each masked channel n the adapter find module, channel // (note that we need use here logical channels of the us4oem // because we set tx apertures with logical channel (the physical channel is mapped by the IUs4OEM) - std::vector> channelsMasks(nUs4OEMs); // probe channel -> adapter channel -> [module, us4oem LOGICAL channel] for(const auto offProbeChannel : channelsMask) { - ARRUS_REQUIRES_TRUE_E(offProbeChannel < probeSettings.getModel().getNumberOfElements().product(), - ::arrus::IllegalArgumentException( - ::arrus::format("Channels mask element {} cannot exceed " - "the number of probe elements {}", - offProbeChannel, probeSettings.getModel(). - getNumberOfElements().product()) - )); - auto offAdapterChannel = probeSettingsMapping[offProbeChannel]; + ARRUS_REQUIRES_TRUE_E( + offProbeChannel < probeSettings.getModel().getNumberOfElements().product(), + ::arrus::IllegalArgumentException( + format("Channels mask element {} cannot exceed the number of probe elements {}", + offProbeChannel, probeSettings.getModel(). getNumberOfElements().product()))); + auto offAdapterChannel = probeMapping[offProbeChannel]; auto[module, offUs4OEMLogicalChannel] = adapterChannelMapping[offAdapterChannel]; channelsMasks[module].emplace(ARRUS_SAFE_CAST(offUs4OEMLogicalChannel, uint8)); } // END OF THE MASKS PRODUCTION - - for(int i = 0; i < nUs4OEMs; ++i) { - result.push_back( - Us4OEMSettings( - us4oemChannelMapping[i], - activeChannelGroups[i], - rxSettings, - channelsMasks[i], - reprogrammingMode) - ); + result.push_back(Us4OEMSettings(us4oemChannelMapping[i], activeChannelGroups[i], rxSettings, + channelsMasks[i], reprogrammingMode)); } - return {result, ProbeAdapterSettings( - probeAdapterSettings.getModelId(), - probeAdapterSettings.getNumberOfChannels(), - adapterChannelMapping - )}; + return {result, + ProbeAdapterSettings( + probeAdapterSettings.getModelId(), + probeAdapterSettings.getNumberOfChannels(), + adapterChannelMapping)}; } private: - static Ordinal - getNumberOfModules( - const ProbeAdapterSettings::ChannelMapping &adapterMapping) { - std::vector mask( - std::numeric_limits::max()); + static Ordinal getNumberOfModules(const ProbeAdapterSettings::ChannelMapping &adapterMapping) { + std::vector mask(std::numeric_limits::max()); Ordinal count = 0; for(auto &moduleChannel : adapterMapping) { auto module = moduleChannel.first; @@ -154,6 +148,16 @@ class Us4RSettingsConverterImpl : public Us4RSettingsConverter { return count; } + ProbeAdapterSettings::ChannelMapping remapUs4OEMs(const ProbeAdapterSettings::ChannelMapping &input, + const std::vector &map) { + ProbeAdapterSettings::ChannelMapping result(input.size()); + for(size_t i = 0; i < input.size(); ++i) { + auto [module, channel] = input[i]; + result[i] = {map[module], channel}; + } + return result; + } + }; } diff --git a/arrus/core/devices/us4r/Us4RSettingsConverterImplTest.cpp b/arrus/core/devices/us4r/Us4RSettingsConverterImplTest.cpp index 42e730c49..eec9ac03f 100644 --- a/arrus/core/devices/us4r/Us4RSettingsConverterImplTest.cpp +++ b/arrus/core/devices/us4r/Us4RSettingsConverterImplTest.cpp @@ -17,6 +17,7 @@ using namespace arrus; using namespace arrus::devices; using ChannelAddress = ProbeAdapterSettings::ChannelAddress; +using ChannelMapping = ProbeAdapterSettings::ChannelMapping; // -------- Mappings @@ -72,38 +73,26 @@ TEST_P(MappingsTest, CorrectlyConvertsMappingsToUs4OEMSettings) { ProbeAdapterSettings adapterSettings( ProbeAdapterModelId("test", "test"), mappings.adapterMapping.size(), - mappings.adapterMapping - ); + mappings.adapterMapping); ProbeSettings probeSettings( - ProbeModel(ProbeModelId("test", "test"), - {32}, - {0.3e-3}, {1e6, 10e6}, {0, 90}, 0.0), - getRange(0, 32) - ); + ProbeModel(ProbeModelId("test", "test"), {32}, {0.3e-3}, {1e6, 10e6}, {0, 90}, 0.0), + getRange(0, 32)); RxSettings rxSettings({}, 24, 24, {}, 10e6, {}); - auto[us4oemSettings, newAdapterSettings] = - converter.convertToUs4OEMSettings(adapterSettings, probeSettings, - rxSettings, std::vector(), - Us4OEMSettings::ReprogrammingMode::SEQUENTIAL); - -// std::cerr << "output probe adapter settings: " << std::endl; -// for(auto [m, ch] : newAdapterSettings.getChannelMapping()) { -// std::cerr << "(" << m << "," << ch << ")"; -// } -// std::cerr << std::endl; + auto[us4oemSettings, newAdapterSettings] = converter.convertToUs4OEMSettings( + adapterSettings, probeSettings, + rxSettings, std::vector(), + Us4OEMSettings::ReprogrammingMode::SEQUENTIAL, std::nullopt, {}); EXPECT_EQ(us4oemSettings.size(), mappings.expectedUs4OEMMappings.size()); for(int i = 0; i < us4oemSettings.size(); ++i) { - EXPECT_EQ(us4oemSettings[i].getChannelMapping(), - mappings.expectedUs4OEMMappings[i]); + EXPECT_EQ(us4oemSettings[i].getChannelMapping(), mappings.expectedUs4OEMMappings[i]); } - EXPECT_EQ(newAdapterSettings.getChannelMapping(), - mappings.expectedAdapterMapping); + EXPECT_EQ(newAdapterSettings.getChannelMapping(), mappings.expectedAdapterMapping); } INSTANTIATE_TEST_CASE_P @@ -378,8 +367,7 @@ struct ActiveChannels { std::vector expectedUs4OEMMasks; - friend std::ostream & - operator<<(std::ostream &os, const ActiveChannels &mappings) { + friend std::ostream & operator<<(std::ostream &os, const ActiveChannels &mappings) { os << "adapterMapping: "; for(const auto &address : mappings.adapterMapping) { os << "(" << address.first << ", " << address.second << ") "; @@ -420,24 +408,19 @@ TEST_P(ActiveChannelsTest, CorrectlyGeneratesActiveChannelGroups) { ); ProbeSettings probeSettings( - ProbeModel(ProbeModelId("test", "test"), - {32}, - {0.3e-3}, {1e6, 10e6}, {0, 90}, 0.0), - testCase.probeMapping - ); + ProbeModel(ProbeModelId("test", "test"), {32}, {0.3e-3}, {1e6, 10e6}, {0, 90}, 0.0), testCase.probeMapping); RxSettings rxSettings({}, 24, 24, {}, 10e6, {}); - auto[us4oemSettings, newAdapterSettings] = - converter.convertToUs4OEMSettings(adapterSettings, probeSettings, - rxSettings, std::vector(), - Us4OEMSettings::ReprogrammingMode::SEQUENTIAL); + auto[us4oemSettings, newAdapterSettings] = converter.convertToUs4OEMSettings( + adapterSettings, probeSettings, + rxSettings, std::vector(), + Us4OEMSettings::ReprogrammingMode::SEQUENTIAL, std::nullopt, {}); EXPECT_EQ(us4oemSettings.size(), testCase.expectedUs4OEMMasks.size()); for(int i = 0; i < us4oemSettings.size(); ++i) { - EXPECT_EQ(us4oemSettings[i].getActiveChannelGroups(), - testCase.expectedUs4OEMMasks[i]); + EXPECT_EQ(us4oemSettings[i].getActiveChannelGroups(), testCase.expectedUs4OEMMasks[i]); } } @@ -530,6 +513,10 @@ std::vector getSL1543ChannelMapping() { return ::arrus::getRange(0, 192); } +std::vector getAtlLikeProbeChannelMapping() { + return ::arrus::getRange(0, 128); +} + std::vector getEsaotePhaseArrayProbeMapping() { std::vector result; for(int i = 0; i < 48; ++i) { @@ -552,7 +539,30 @@ ProbeAdapterSettings::ChannelMapping getEsaote3ChannelMapping() { auto module = group % 2; auto channel = i % 32 + 32*(i/64); mapping.push_back({module, channel}); -// std::cerr << i << ", " << module << ", " << channel << std::endl; + } + return mapping; +} + +ProbeAdapterSettings::ChannelMapping getEsaote3Us4RChannelMapping() { + // 6 modules used + ProbeAdapterSettings::ChannelMapping mapping; + for(int i = 0; i < 192; ++i) { + auto group = i / 32; + auto module = group; + auto channel = i % 32; + mapping.push_back({module, channel}); + } + return mapping; +} + +ProbeAdapterSettings::ChannelMapping getAtlUs4RLikeChannelMapping() { + // 6 modules used + ProbeAdapterSettings::ChannelMapping mapping; + for(int i = 0; i < 128; ++i) { + auto group = i / 32; + auto module = group; + auto channel = i % 32; + mapping.push_back({module, channel}); } return mapping; } @@ -622,15 +632,15 @@ TEST_P(ChannelMaskingTest, CorrectlyMasksChannels) { ProbeModelId("test", "test"), {(ChannelIdx)mappings.probeMapping.size()}, {0.3e-3}, {1e6, 10e6}, {0, 90}, 0.0), - mappings.probeMapping + mappings.probeMapping ); RxSettings rxSettings({}, 24, 24, {}, 10e6, {}); - auto[us4oemSettings, newAdapterSettings] = - converter.convertToUs4OEMSettings(adapterSettings, probeSettings, - rxSettings, mappings.channelsMask, - Us4OEMSettings::ReprogrammingMode::SEQUENTIAL); + auto[us4oemSettings, newAdapterSettings] = converter.convertToUs4OEMSettings( + adapterSettings, probeSettings, + rxSettings, mappings.channelsMask, + Us4OEMSettings::ReprogrammingMode::SEQUENTIAL, std::nullopt, {}); std::vector> channelsMasks; std::transform( @@ -736,11 +746,125 @@ TEST(ChannelsMaskingTest, ChecksIfChannelMaskElementsDoNotExceedNumberOfProbeEle std::vector channelsMask({10, 20, 192}); - EXPECT_THROW(converter.convertToUs4OEMSettings(adapterSettings, probeSettings, - rxSettings, channelsMask, - Us4OEMSettings::ReprogrammingMode::SEQUENTIAL), + EXPECT_THROW(converter.convertToUs4OEMSettings( + adapterSettings, probeSettings, rxSettings, channelsMask, + Us4OEMSettings::ReprogrammingMode::SEQUENTIAL, std::nullopt, {}), ::arrus::IllegalArgumentException); +} + +TEST(Us4OEMRemappingTest, CorrectlyRemapsUs4OEMNumbersEsaote) { + Us4RSettingsConverterImpl converter; + + auto probeMapping = getSL1543ChannelMapping(); + auto adapterMapping = getEsaote3Us4RChannelMapping(); + ChannelIdx nChannels = probeMapping.size(); + ProbeAdapterSettings adapterSettings( + ProbeAdapterModelId("test", "test"), + adapterMapping.size(), + adapterMapping + ); + ProbeSettings probeSettings( + ProbeModel(ProbeModelId("test", "test"), {nChannels}, {0.3e-3}, {1e6, 10e6}, {0, 90}, 0.0), probeMapping + ); + RxSettings rxSettings({}, 24, 24, {}, 10e6, {}); + Ordinal nUs4OEMs = 8; + std::vector adapterToUs4R = { + /* Adapter Us4OEM: 0 -> Us4R Us4OEM: */ 0, + /* Adapter Us4OEM: 1 -> US4R Us4OEM: */ 1, + /* Adapter Us4OEM: 2 -> Us4R Us4OEM: */ 2, + /* Adapter Us4OEM: 3 -> Us4R Us4OEM: */ 4, + /* Adapter Us4OEM: 4 -> Us4R Us4OEM: */ 5, + /* Adapter Us4OEM: 5 -> Us4R Us4OEM: */ 6, + }; + + auto [us4oemCfg, adapterCfg] = converter.convertToUs4OEMSettings( + adapterSettings, probeSettings, rxSettings, {}, + Us4OEMSettings::ReprogrammingMode::SEQUENTIAL, nUs4OEMs, adapterToUs4R); + // Adapter mapping + auto &actualAdapterMapping = adapterCfg.getChannelMapping(); + ChannelMapping expectedAdapterMapping = concat( + { + zip(getNTimes(0, 32), getRange(0, 32)), + zip(getNTimes(1, 32), getRange(0, 32)), + zip(getNTimes(2, 32), getRange(0, 32)), + zip(getNTimes(4, 32), getRange(0, 32)), + zip(getNTimes(5, 32), getRange(0, 32)), + zip(getNTimes(6, 32), getRange(0, 32)), + } + ); + // Probe adapter mapping. + ASSERT_EQ(actualAdapterMapping, expectedAdapterMapping); + // Us4OEM mapping. + for(auto &us4oem: us4oemCfg) { + ASSERT_EQ(us4oem.getChannelMapping(), getRange(0, 128)); + } + + std::vector groupsAllOff = getNTimes(false, 16); + std::vector groups32 = getNTimes(false, 16); + groups32[0] = groups32[1] = groups32[2] = groups32[3] = true; + for(int i : {0, 1, 2, 4, 5, 6}) { + ASSERT_EQ(us4oemCfg[i].getActiveChannelGroups(), groups32); + } + for(int i : {3, 7}) { + ASSERT_EQ(us4oemCfg[i].getActiveChannelGroups(), groupsAllOff); + } } + +TEST(Us4OEMRemappingTest, CorrectlyRemapsUs4OEMNumbersAtl) { + Us4RSettingsConverterImpl converter; + + auto probeMapping = getAtlLikeProbeChannelMapping(); + auto adapterMapping = getAtlUs4RLikeChannelMapping(); + ChannelIdx nChannels = probeMapping.size(); + + ProbeAdapterSettings adapterSettings( + ProbeAdapterModelId("test", "test"), + adapterMapping.size(), + adapterMapping + ); + ProbeSettings probeSettings( + ProbeModel(ProbeModelId("test", "test"), {nChannels}, {0.3e-3}, {1e6, 10e6}, {0, 90}, 0.0), probeMapping + ); + RxSettings rxSettings({}, 24, 24, {}, 10e6, {}); + Ordinal nUs4OEMs = 8; + std::vector adapterToUs4R = { + /* Adapter Us4OEM: 0 -> Us4R Us4OEM: */ 0, + /* Adapter Us4OEM: 1 -> US4R Us4OEM: */ 2, + /* Adapter Us4OEM: 2 -> Us4R Us4OEM: */ 5, + /* Adapter Us4OEM: 3 -> Us4R Us4OEM: */ 7, + }; + + auto [us4oemCfg, adapterCfg] = converter.convertToUs4OEMSettings( + adapterSettings, probeSettings, rxSettings, {}, + Us4OEMSettings::ReprogrammingMode::SEQUENTIAL, nUs4OEMs, adapterToUs4R); + // Adapter mapping + auto &actualAdapterMapping = adapterCfg.getChannelMapping(); + ChannelMapping expectedAdapterMapping = concat( + { + zip(getNTimes(0, 32), getRange(0, 32)), + zip(getNTimes(2, 32), getRange(0, 32)), + zip(getNTimes(5, 32), getRange(0, 32)), + zip(getNTimes(7, 32), getRange(0, 32)), + } + ); + // Probe adapter mapping. + ASSERT_EQ(actualAdapterMapping, expectedAdapterMapping); + // Us4OEM mapping. + for(auto &us4oem: us4oemCfg) { + ASSERT_EQ(us4oem.getChannelMapping(), getRange(0, 128)); + } + + std::vector groupsAllOff = getNTimes(false, 16); + std::vector groups32 = getNTimes(false, 16); + groups32[0] = groups32[1] = groups32[2] = groups32[3] = true; + for(int i : {0, 2, 5, 7}) { + ASSERT_EQ(us4oemCfg[i].getActiveChannelGroups(), groups32); + } + for(int i : {1, 3, 4, 6}) { + ASSERT_EQ(us4oemCfg[i].getActiveChannelGroups(), groupsAllOff); + } +} + } diff --git a/arrus/core/devices/us4r/Us4RSettingsValidator.h b/arrus/core/devices/us4r/Us4RSettingsValidator.h index b23f94d6f..6910ff113 100644 --- a/arrus/core/devices/us4r/Us4RSettingsValidator.h +++ b/arrus/core/devices/us4r/Us4RSettingsValidator.h @@ -22,6 +22,30 @@ class Us4RSettingsValidator : public SettingsValidator { expectTrue("tgc settings", obj.getRxSettings().has_value(), "Us4R TGC settings must be provided."); + if(hasErrors()) { + return; + } + auto &adapterMapping = obj.getProbeAdapterSettings()->getChannelMapping(); + Ordinal nus4oemsAdapter = std::max_element( + std::begin(adapterMapping), std::end(adapterMapping), + [] (auto &a, auto &b) {return a.first < b.first;} )->first; + nus4oemsAdapter += 1; // The above starts from 0 + if(obj.getNumberOfUs4oems().has_value()) { + expectTrue( + "nus4oems", + obj.getNumberOfUs4oems() >= nus4oemsAdapter, + "The declared number of us4oems should not be less than the number of us4oems used in the probe " + "adapter channel mapping" + ); + } + if(! obj.getAdapterToUs4RModuleNumber().empty()) { + expectTrue( + "adapter to us4R module number", + obj.getAdapterToUs4RModuleNumber().size() == nus4oemsAdapter, + "The size of the mapping should be equal to the number of us4oems used in the probe adapter " + "channel mapping" + ); + } } else { expectFalse( "probe adapter settings", @@ -34,6 +58,13 @@ class Us4RSettingsValidator : public SettingsValidator { obj.getProbeSettings().has_value(), "Probe settings should not be set " "(at least one custom Us4OEM setting was detected)."); + if(obj.getNumberOfUs4oems().has_value()) { + expectTrue( + "us4r settings", + obj.getNumberOfUs4oems().value() == obj.getUs4OEMSettings().size(), + "The declared number of us4OEMs should be equal to the number of provided Us4OEM settings" + ); + } } // The exact TGC settings should be verified by the underlying Us4OEMs. } diff --git a/arrus/core/devices/us4r/external/ius4oem/IUs4OEMFactory.h b/arrus/core/devices/us4r/external/ius4oem/IUs4OEMFactory.h index 15635c0f2..f6024cc25 100644 --- a/arrus/core/devices/us4r/external/ius4oem/IUs4OEMFactory.h +++ b/arrus/core/devices/us4r/external/ius4oem/IUs4OEMFactory.h @@ -19,6 +19,7 @@ class IUs4OEMFactory { public: virtual IUs4OEMHandle getIUs4OEM(unsigned index) = 0; virtual std::vector getModules(Ordinal nModules) = 0; + virtual ~IUs4OEMFactory() = default; }; diff --git a/arrus/core/devices/us4r/external/ius4oem/IUs4OEMInitializer.h b/arrus/core/devices/us4r/external/ius4oem/IUs4OEMInitializer.h index 5350e8b61..14c1025bb 100644 --- a/arrus/core/devices/us4r/external/ius4oem/IUs4OEMInitializer.h +++ b/arrus/core/devices/us4r/external/ius4oem/IUs4OEMInitializer.h @@ -11,8 +11,8 @@ class IUs4OEMInitializer { /** * Sorts the given list of us4oems (by device id) and initializes them. */ - virtual void - initModules(std::vector &ius4oems) = 0; + virtual void initModules(std::vector &ius4oems) = 0; + virtual ~IUs4OEMInitializer() = default; }; } diff --git a/arrus/core/devices/us4r/hv/HighVoltageSupplierFactory.h b/arrus/core/devices/us4r/hv/HighVoltageSupplierFactory.h index ce93166aa..49273a7cf 100644 --- a/arrus/core/devices/us4r/hv/HighVoltageSupplierFactory.h +++ b/arrus/core/devices/us4r/hv/HighVoltageSupplierFactory.h @@ -11,6 +11,7 @@ namespace arrus::devices { class HighVoltageSupplierFactory { public: virtual HighVoltageSupplier::Handle getHighVoltageSupplier(const HVSettings &settings, IUs4OEM *master) = 0; + virtual ~HighVoltageSupplierFactory() = default; }; } diff --git a/arrus/core/devices/us4r/probeadapter/ProbeAdapterFactory.h b/arrus/core/devices/us4r/probeadapter/ProbeAdapterFactory.h index 3799e6b12..ef4a8b64f 100644 --- a/arrus/core/devices/us4r/probeadapter/ProbeAdapterFactory.h +++ b/arrus/core/devices/us4r/probeadapter/ProbeAdapterFactory.h @@ -12,8 +12,8 @@ namespace arrus::devices { class ProbeAdapterFactory { public: virtual ProbeAdapterImplBase::Handle - getProbeAdapter(const ProbeAdapterSettings &settings, - const std::vector &us4oems) = 0; + getProbeAdapter(const ProbeAdapterSettings &settings, const std::vector &us4oems) = 0; + virtual ~ProbeAdapterFactory() = default; }; } diff --git a/arrus/core/devices/us4r/probeadapter/ProbeAdapterFactoryImpl.h b/arrus/core/devices/us4r/probeadapter/ProbeAdapterFactoryImpl.h index 785946d30..e6e278d26 100644 --- a/arrus/core/devices/us4r/probeadapter/ProbeAdapterFactoryImpl.h +++ b/arrus/core/devices/us4r/probeadapter/ProbeAdapterFactoryImpl.h @@ -20,8 +20,6 @@ class ProbeAdapterFactoryImpl : public ProbeAdapterFactory { validator.validate(settings); validator.throwOnErrors(); - assertCorrectNumberOfUs4OEMs(settings, us4oems); - return std::make_unique( id, settings.getModelId(), @@ -29,20 +27,6 @@ class ProbeAdapterFactoryImpl : public ProbeAdapterFactory { settings.getNumberOfChannels(), settings.getChannelMapping()); } - -private: - static void assertCorrectNumberOfUs4OEMs( - const ProbeAdapterSettings &settings, - const std::vector &us4oems) { - std::unordered_set ordinals; - for(auto value : settings.getChannelMapping()) { - ordinals.insert(value.first); - } - ARRUS_REQUIRES_TRUE(ordinals.size() == us4oems.size(), - arrus::format("Incorrect number of us4oems " - "(provided {}, from settings {})", - us4oems.size(), ordinals.size())); - } }; } diff --git a/arrus/core/devices/us4r/probeadapter/ProbeAdapterImpl.cpp b/arrus/core/devices/us4r/probeadapter/ProbeAdapterImpl.cpp index 756fee17a..0e13575c4 100644 --- a/arrus/core/devices/us4r/probeadapter/ProbeAdapterImpl.cpp +++ b/arrus/core/devices/us4r/probeadapter/ProbeAdapterImpl.cpp @@ -14,10 +14,8 @@ namespace arrus::devices { using namespace ::arrus::ops::us4r; using ::arrus::ops::us4r::Scheme; -ProbeAdapterImpl::ProbeAdapterImpl(DeviceId deviceId, - ProbeAdapterModelId modelId, - std::vector us4oems, - ChannelIdx numberOfChannels, +ProbeAdapterImpl::ProbeAdapterImpl(DeviceId deviceId, ProbeAdapterModelId modelId, + std::vector us4oems, ChannelIdx numberOfChannels, ChannelMapping channelMapping) : ProbeAdapterImplBase(deviceId), logger(getLoggerFactory()->getLogger()), modelId(std::move(modelId)), @@ -61,14 +59,10 @@ class ProbeAdapterTxRxValidator : public Validator { }; std::tuple -ProbeAdapterImpl::setTxRxSequence(const std::vector &seq, - const ops::us4r::TGCCurve &tgcSamples, - uint16 rxBufferSize, - uint16 batchSize, std::optional sri, - bool triggerSync) { +ProbeAdapterImpl::setTxRxSequence(const std::vector &seq, const ops::us4r::TGCCurve &tgcSamples, + uint16 rxBufferSize, uint16 batchSize, std::optional sri, bool triggerSync) { // Validate input sequence - ProbeAdapterTxRxValidator validator(::arrus::format("{} tx rx sequence", getDeviceId().toString()), - numberOfChannels); + ProbeAdapterTxRxValidator validator(::arrus::format("{} tx rx sequence", getDeviceId().toString()), numberOfChannels); validator.validate(seq); validator.throwOnErrors(); @@ -105,30 +99,29 @@ ProbeAdapterImpl::setTxRxSequence(const std::vector &seq, // Split Tx, Rx apertures and tx delays into sub-apertures specific for each us4oem module. uint32 opNumber = 0; - uint32 frameNumber = 0; for(const auto &op : seq) { logger->log(LogSeverity::TRACE, arrus::format("Setting tx/rx {}", ::arrus::toString(op))); - const auto &txAperture = op.getTxAperture(); const auto &rxAperture = op.getRxAperture(); const auto &txDelays = op.getTxDelays(); - ARRUS_REQUIRES_TRUE(txAperture.size() == rxAperture.size() && txAperture.size() == numberOfChannels, - format("TX and RX apertures should have a size: {}", numberOfChannels)); + std::vector> us4oemChannels(us4oems.size()); + std::vector> adapterChannels(us4oems.size()); - for(Ordinal ordinal = 0; ordinal < us4oems.size(); ++ordinal) { - txApertures[ordinal][opNumber].resize(Us4OEMImpl::N_ADDR_CHANNELS); - rxApertures[ordinal][opNumber].resize(Us4OEMImpl::N_ADDR_CHANNELS); - txDelaysList[ordinal][opNumber].resize(Us4OEMImpl::N_ADDR_CHANNELS); + // TODO change the below to an 'assert' + ARRUS_REQUIRES_TRUE(txAperture.size() == rxAperture.size() && txAperture.size() == numberOfChannels, + format("Tx and Rx apertures should have a size: {}", numberOfChannels)); + for (Ordinal ordinal = 0; ordinal < us4oems.size(); ++ordinal) { + txApertures[ordinal][opNumber].resize(Us4OEMImpl::N_ADDR_CHANNELS, false); + rxApertures[ordinal][opNumber].resize(Us4OEMImpl::N_ADDR_CHANNELS, false); + txDelaysList[ordinal][opNumber].resize(Us4OEMImpl::N_ADDR_CHANNELS, 0.0f); } size_t activeAdapterCh = 0; bool isRxNop = true; - std::vector activeUs4oemCh(us4oems.size(), 0); // SPLIT tx/rx/delays between modules for(size_t ach = 0; ach < numberOfChannels; ++ach) { - // tx/rx/delays mapping stuff auto cm = channelMapping[ach]; Ordinal dstModule = cm.first; @@ -141,9 +134,23 @@ ProbeAdapterImpl::setTxRxSequence(const std::vector &seq, if(op.getRxAperture()[ach]) { isRxNop = false; frameModule(frameNumber, activeAdapterCh+op.getRxPadding()[0]) = dstModule; - frameChannel(frameNumber, activeAdapterCh+op.getRxPadding()[0]) = (int32)(activeUs4oemCh[dstModule]); + // This will be processed further later. + us4oemChannels[dstModule].push_back(static_cast(dstChannel)); + adapterChannels[dstModule].push_back(activeAdapterCh+op.getRxPadding()[0]); ++activeAdapterCh; - ++activeUs4oemCh[dstModule]; + } + } + // FCM + // Compute rank of each us4oem RX channel (to get the "aperture" channel number). + // The rank is needed, as the further code decomposes each op into 32-rx element ops + // assuming, that the first 32 channels of rx aperture will be used in the first + // op, the next 32 channels in the second op and so on. + for(Ordinal ordinal = 0; ordinal < us4oems.size(); ++ordinal) { + auto &uChannels = us4oemChannels[ordinal]; + auto &aChannels = adapterChannels[ordinal]; + auto rxApertureChannels = ::arrus::rank(uChannels); + for(size_t c = 0; c < uChannels.size(); ++c) { + frameChannel(frameNumber, aChannels[c]) = static_cast(rxApertureChannels[c]); } } if(!isRxNop) { @@ -157,7 +164,6 @@ ProbeAdapterImpl::setTxRxSequence(const std::vector &seq, for(Ordinal us4oemOrdinal = 0; us4oemOrdinal < us4oems.size(); ++us4oemOrdinal) { auto &us4oemSeq = seqs[us4oemOrdinal]; - uint16 i = 0; for(const auto &op : seq) { // Convert tx aperture to us4oem tx aperture @@ -186,7 +192,7 @@ ProbeAdapterImpl::setTxRxSequence(const std::vector &seq, // section -> us4oem -> transfer std::vector> outputTransfers; uint32 currentFrameOffset = 0; - std::vector frameOffsets{static_cast(us4oems.size()), 0}; + std::vector frameOffsets(static_cast(us4oems.size()), 0); Us4RBufferBuilder us4RBufferBuilder; for(Ordinal us4oemOrdinal = 0; us4oemOrdinal < us4oems.size(); ++us4oemOrdinal) { @@ -279,7 +285,6 @@ void ProbeAdapterImpl::registerOutputBuffer(Us4ROutputBuffer *buffer, const Us4R if(transferRegistrar.size() < us4oems.size()) { transferRegistrar.resize(us4oems.size()); } - for(auto &us4oem: us4oems) { auto us4oemBuffer = us4rBuffer->getUs4oemBuffer(us4oemOrdinal); registerOutputBuffer(buffer, us4oemBuffer, us4oem, workMode); @@ -386,4 +391,4 @@ void ProbeAdapterImpl::unregisterOutputBuffer() { } } -} \ No newline at end of file +} diff --git a/arrus/core/devices/us4r/probeadapter/ProbeAdapterSettingsValidator.h b/arrus/core/devices/us4r/probeadapter/ProbeAdapterSettingsValidator.h index ef90ea494..1ce74ff98 100644 --- a/arrus/core/devices/us4r/probeadapter/ProbeAdapterSettingsValidator.h +++ b/arrus/core/devices/us4r/probeadapter/ProbeAdapterSettingsValidator.h @@ -19,8 +19,7 @@ class ProbeAdapterSettingsValidator public: explicit ProbeAdapterSettingsValidator(const Ordinal ordinal) - : SettingsValidator( - DeviceId(DeviceType::ProbeAdapter, ordinal)) {} + : SettingsValidator(DeviceId(DeviceType::ProbeAdapter, ordinal)) {} void validate(const ProbeAdapterSettings &obj) override { auto &id = obj.getModelId(); @@ -34,53 +33,30 @@ class ProbeAdapterSettingsValidator const auto N_RX = Us4OEMImpl::N_RX_CHANNELS; // Make sure, that the number of channels is equal to // the number of channel mapping elements. - expectEqual("channel mapping", - static_cast(obj.getChannelMapping().size()), + expectEqual("channel mapping", static_cast(obj.getChannelMapping().size()), obj.getNumberOfChannels(), " (size, compared to nChannels)"); // Get the number of us4oems - std::vector modules; + std::set modules; for(auto &moduleChannel : obj.getChannelMapping()) { auto us4oem = moduleChannel.first; - modules.push_back(us4oem); + modules.insert(us4oem); } - - // Check if contains consecutive ordinal numbers. - // Us4OEMs should have exactly ordinals: 0, 1, ... nmodules-1 - std::unordered_set modulesSet{std::begin(modules), - std::end(modules)}; - ARRUS_REQUIRES_TRUE( - modulesSet.size() >= std::numeric_limits::min() - && modulesSet.size() <= std::numeric_limits::max(), - arrus::format("Us4OEMs count should be in range {}, {}", - std::numeric_limits::min(), - std::numeric_limits::max())); - - for(Ordinal i = 0; i < (Ordinal) modulesSet.size(); ++i) { - expectTrue("channel mapping", - setContains(modulesSet, i), - arrus::format("Missing Us4OEM: {}", i)); - } - - if(hasErrors()) { - // Do not continue here, some errors may impact further validation - // correctness. - return; - } - - auto nModules = modulesSet.size(); - + auto maxModuleNr = *std::max_element(std::begin(modules), std::end(modules)); // Split to us4oem channel mappings - std::vector us4oemMappings(nModules); + std::vector us4oemMappings(maxModuleNr+1); for(auto[module, channel] : obj.getChannelMapping()) { us4oemMappings[module].emplace_back(channel); } unsigned us4oemOrdinal = 0; - for(auto &mapping : us4oemMappings) { + if(mapping.empty()) { + // This module is not used and has no mapping available. + continue; + } // Make sure that the number of channels for each module is // multiple of nRx expectDivisible("channel mapping", @@ -101,7 +77,7 @@ class ProbeAdapterSettingsValidator " (number of unique channel indices " "for Us4OEM: {}, " "for input range [{}, {}))", - us4oemOrdinal, i*N_RX, (i+1)*N_RX)); + us4oemOrdinal, i*N_RX, (i+1)*N_RX)); // Make sure, the mapping contains [0,31)*i*32 groups // (where i can be 0, 1, 2, 3) diff --git a/arrus/core/devices/us4r/probeadapter/Us4OEMDataTransferRegistrar.h b/arrus/core/devices/us4r/probeadapter/Us4OEMDataTransferRegistrar.h index 74a239103..546f0d010 100644 --- a/arrus/core/devices/us4r/probeadapter/Us4OEMDataTransferRegistrar.h +++ b/arrus/core/devices/us4r/probeadapter/Us4OEMDataTransferRegistrar.h @@ -6,6 +6,7 @@ #include "arrus/core/devices/us4r/Us4ROutputBuffer.h" #include "arrus/core/api/common/types.h" #include "arrus/core/common/logging.h" +#include "arrus/common/compiler.h" namespace arrus::devices { @@ -34,7 +35,7 @@ class Us4OEMDataTransferRegistrar { static constexpr size_t MAX_TRANSFER_SIZE = Us4OEMImpl::MAX_TRANSFER_SIZE; Us4OEMDataTransferRegistrar(Us4ROutputBuffer *dst, const Us4OEMBuffer *src, Us4OEMImplBase *us4oem) - : logger(loggerFactory->getLogger()), dstBuffer(dst), srcBuffer(src), us4oem(us4oem) { + : logger(loggerFactory->getLogger()), dstBuffer(dst), srcBuffer(src) { ARRUS_INIT_COMPONENT_LOGGER(logger, "Us4OEMDataTransferRegistrar"); if (dst->getNumberOfElements() % src->getNumberOfElements() != 0) { throw IllegalArgumentException("Host buffer should have multiple of rx buffer elements."); @@ -173,7 +174,9 @@ class Us4OEMDataTransferRegistrar { #define ARRUS_ON_NEW_DATA_CALLBACK(signal, strategy) \ [=, currentDstIdx = srcIdx, currentTransferIdx = transferIdx] () mutable { \ - try { \ + IGNORE_UNUSED(currentTransferIdx); \ + IGNORE_UNUSED(currentDstIdx); \ + try { \ ius4oem->MarkEntriesAsReadyForReceive(transferFirstFiring, transferLastFiring); \ ARRUS_ON_NEW_DATA_CALLBACK_strategy_##strategy \ ARRUS_ON_NEW_DATA_CALLBACK_signal_##signal \ @@ -232,7 +235,6 @@ class Us4OEMDataTransferRegistrar { Logger::Handle logger; Us4ROutputBuffer *dstBuffer{nullptr}; const Us4OEMBuffer *srcBuffer{nullptr}; - Us4OEMImplBase *us4oem{nullptr}; // All derived parameters IUs4OEM *ius4oem{nullptr}; Ordinal us4oemOrdinal{0}; @@ -244,9 +246,7 @@ class Us4OEMDataTransferRegistrar { size_t srcNTransfers{0}; // Number of transfer dst points. size_t dstNTransfers{0}; - bool reprogramTransfers{false}; int strategy{0}; - bool triggerOnRelease{false}; }; diff --git a/arrus/core/devices/us4r/us4oem/Us4OEMFactory.h b/arrus/core/devices/us4r/us4oem/Us4OEMFactory.h index 765d23e59..aca33b1ab 100644 --- a/arrus/core/devices/us4r/us4oem/Us4OEMFactory.h +++ b/arrus/core/devices/us4r/us4oem/Us4OEMFactory.h @@ -17,8 +17,8 @@ namespace arrus::devices { class Us4OEMFactory { public: virtual Us4OEMImplBase::Handle - getUs4OEM(Ordinal ordinal, IUs4OEMHandle &handle, - const Us4OEMSettings &settings) = 0; + getUs4OEM(Ordinal ordinal, IUs4OEMHandle &handle, const Us4OEMSettings &settings) = 0; + virtual ~Us4OEMFactory() = default; }; } diff --git a/arrus/core/devices/us4r/us4oem/Us4OEMImpl.h b/arrus/core/devices/us4r/us4oem/Us4OEMImpl.h index c20814e33..244afa733 100644 --- a/arrus/core/devices/us4r/us4oem/Us4OEMImpl.h +++ b/arrus/core/devices/us4r/us4oem/Us4OEMImpl.h @@ -51,8 +51,7 @@ class Us4OEMImpl : public Us4OEMImplBase { static constexpr ChannelIdx N_RX_CHANNELS = 32; static constexpr ChannelIdx N_ADDR_CHANNELS = N_TX_CHANNELS; static constexpr ChannelIdx ACTIVE_CHANNEL_GROUP_SIZE = 8; - static constexpr ChannelIdx N_ACTIVE_CHANNEL_GROUPS = - N_TX_CHANNELS / ACTIVE_CHANNEL_GROUP_SIZE; + static constexpr ChannelIdx N_ACTIVE_CHANNEL_GROUPS = N_TX_CHANNELS / ACTIVE_CHANNEL_GROUP_SIZE; static constexpr float MIN_TX_DELAY = 0.0f; static constexpr float MAX_TX_DELAY = 16.96e-6f; diff --git a/arrus/core/io/proto/devices/us4r/Us4RSettings.proto b/arrus/core/io/proto/devices/us4r/Us4RSettings.proto index b0aa359db..6132a5b78 100644 --- a/arrus/core/io/proto/devices/us4r/Us4RSettings.proto +++ b/arrus/core/io/proto/devices/us4r/Us4RSettings.proto @@ -27,7 +27,6 @@ message Us4RSettings { message ChannelsMask { // The channel number of the probe that should be turned of. - // The number refers to repeated uint32 channels = 1; } @@ -39,4 +38,8 @@ message Us4RSettings { repeated ChannelsMask us4oem_channels_mask = 10; Us4OEMSettings.ReprogrammingMode reprogramming_mode = 11; + oneof optional_nus4ems { + uint32 nus4oems = 12; + } + repeated uint32 adapterToUs4RModuleNr = 13; } \ No newline at end of file diff --git a/arrus/core/io/settings.cpp b/arrus/core/io/settings.cpp index 65873cc34..9baa5b740 100644 --- a/arrus/core/io/settings.cpp +++ b/arrus/core/io/settings.cpp @@ -193,8 +193,7 @@ readDictionary(const ap::Dictionary *proto) { std::unordered_multimap connections; for(const ap::ProbeToAdapterConnection &conn : proto->probe_to_adapter_connections()) { - std::string key = - SettingsDictionary::convertProtoIdToString(conn.probe_model_id()); + std::string key = SettingsDictionary::convertProtoIdToString(conn.probe_model_id()); const ap::ProbeToAdapterConnection *ptr = &conn; connections.emplace(key, ptr); } @@ -203,21 +202,15 @@ readDictionary(const ap::Dictionary *proto) { for(auto const &probe : proto->probe_models()) { const ProbeModel probeModel = readProbeModel(probe); result.insertProbeModel(probeModel); - - std::string key = - SettingsDictionary::convertProtoIdToString(probe.id()); + std::string key = SettingsDictionary::convertProtoIdToString(probe.id()); auto range = connections.equal_range(key); for(auto it = range.first; it != range.second; ++it) { auto conn = it->second; - std::vector channelMapping = - readProbeConnectionChannelMapping(*conn); + std::vector channelMapping = readProbeConnectionChannelMapping(*conn); for(auto const &adapterProtoId : conn->probe_adapter_model_id()) { - const ProbeAdapterModelId adapterId( - adapterProtoId.manufacturer(), - adapterProtoId.name()); - result.insertProbeSettings( - ProbeSettings(probeModel, channelMapping), adapterId); + const ProbeAdapterModelId adapterId(adapterProtoId.manufacturer(), adapterProtoId.name()); + result.insertProbeSettings(ProbeSettings(probeModel, channelMapping), adapterId); } } } @@ -269,9 +262,7 @@ ProbeSettings readOrGetProbeSettings(const proto::Us4RSettings &us4r, const SettingsDictionary &dictionary) { if(us4r.has_probe()) { ProbeModel model = readProbeModel(us4r.probe()); - std::vector channelMapping = - readProbeConnectionChannelMapping( - us4r.probe_to_adapter_connection()); + std::vector channelMapping = readProbeConnectionChannelMapping(us4r.probe_to_adapter_connection()); return ProbeSettings(model, channelMapping); } else if(us4r.has_probe_id()) { ProbeModelId id{us4r.probe_id().manufacturer(), us4r.probe_id().name()}; @@ -283,18 +274,14 @@ ProbeSettings readOrGetProbeSettings(const proto::Us4RSettings &us4r, ProbeModel model = dictionary.getProbeModel(id); return ProbeSettings(model, channelMapping); } catch(std::out_of_range &) { - throw IllegalArgumentException( - arrus::format("Probe with id {} not found.", - id.toString())); + throw IllegalArgumentException(format("Probe with id {} not found.", id.toString())); } } else { try { return dictionary.getProbeSettings(id, adapterId); } catch(std::out_of_range &) { - throw IllegalArgumentException( - arrus::format( - "Probe settings for probe with id {}" - " adapter with id {} not found.", id.toString())); + throw IllegalArgumentException(format( + "Probe settings for probe with id {} adapter with id {} not found.", id.toString())); } } } else { @@ -321,9 +308,12 @@ std::vector readChannelsMask(const proto::Us4RSettings_ChannelsMask &mask) { } Us4OEMSettings::ReprogrammingMode convertToReprogrammingMode(proto::Us4OEMSettings_ReprogrammingMode mode); + Us4RSettings readUs4RSettings(const proto::Us4RSettings &us4r, const SettingsDictionary &dictionary) { std::optional hvSettings; + std::optional nUs4OEMs; + std::vector adapterToUs4RModuleNr; if(us4r.has_hv()) { auto &manufacturer = us4r.hv().model_id().manufacturer(); auto &name = us4r.hv().model_id().name(); @@ -331,6 +321,14 @@ Us4RSettings readUs4RSettings(const proto::Us4RSettings &us4r, ARRUS_REQUIRES_NON_EMPTY_IAE(name); hvSettings = HVSettings(HVModelId(manufacturer, name)); } + if(us4r.optional_nus4ems_case() != proto::Us4RSettings::OPTIONAL_NUS4EMS_NOT_SET) { + nUs4OEMs = us4r.nus4oems(); + } + if(!us4r.adaptertous4rmodulenr().empty()) { + auto &adapter2Us4RModule = us4r.adaptertous4rmodulenr(); + std::copy(std::begin(adapter2Us4RModule), std::end(adapter2Us4RModule), + std::back_inserter(adapterToUs4RModuleNr)); + } if(!us4r.us4oems().empty()) { // Us4OEMs are provided. std::vector us4oemSettings; @@ -338,19 +336,15 @@ Us4RSettings readUs4RSettings(const proto::Us4RSettings &us4r, std::vector> us4oemChannelsMask; us4oemChannelsMask.resize(us4r.us4oems().size()); - if(!us4r.us4oem_channels_mask().empty() - && us4r.us4oems().size() != us4r.us4oem_channels_mask().size()) { - throw ::arrus::IllegalArgumentException( - "The number of us4oem channels " - "masks should be the same as the number of us4oems."); + if(!us4r.us4oem_channels_mask().empty() && us4r.us4oems().size() != us4r.us4oem_channels_mask().size()) { + throw ::arrus::IllegalArgumentException("The number of us4oem channels masks should be the " + "same as the number of us4oems."); } int i = 0; for(auto &mask: us4r.us4oem_channels_mask()) { auto channelsMask = readChannelsMask(mask); - - us4oemChannelsMask[i] = std::unordered_set( - std::begin(channelsMask), std::end(channelsMask)); + us4oemChannelsMask[i] = std::unordered_set(std::begin(channelsMask), std::end(channelsMask)); ++i; } @@ -368,12 +362,10 @@ Us4RSettings readUs4RSettings(const proto::Us4RSettings &us4r, channelMapping, activeChannelGroups, rxSettings, us4oemChannelsMask[i], reprogrammingMode); } - return Us4RSettings(us4oemSettings, hvSettings); + return Us4RSettings(us4oemSettings, hvSettings, nUs4OEMs, adapterToUs4RModuleNr); } else { - ProbeAdapterSettings adapterSettings = - readOrGetAdapterSettings(us4r, dictionary); - ProbeSettings probeSettings = readOrGetProbeSettings( - us4r, adapterSettings.getModelId(), dictionary); + ProbeAdapterSettings adapterSettings =readOrGetAdapterSettings(us4r, dictionary); + ProbeSettings probeSettings = readOrGetProbeSettings(us4r, adapterSettings.getModelId(), dictionary); RxSettings rxSettings = readRxSettings(us4r.rx_settings()); // ensure that user provided channels mask @@ -391,17 +383,16 @@ Us4RSettings readUs4RSettings(const proto::Us4RSettings &us4r, "to turn of channel masking."); } - std::vector channelsMask = - readChannelsMask(us4r.channels_mask()); + std::vector channelsMask = readChannelsMask(us4r.channels_mask()); std::vector> us4oemChannelsMask; for(auto &mask: us4r.us4oem_channels_mask()) { us4oemChannelsMask.push_back(readChannelsMask(mask)); } auto reprogrammingMode = convertToReprogrammingMode(us4r.reprogramming_mode()); - return Us4RSettings(adapterSettings, probeSettings, rxSettings, - hvSettings, channelsMask, us4oemChannelsMask, - reprogrammingMode); + return {adapterSettings, probeSettings, rxSettings, + hvSettings, channelsMask, us4oemChannelsMask, + reprogrammingMode, nUs4OEMs, adapterToUs4RModuleNr}; } } Us4OEMSettings::ReprogrammingMode convertToReprogrammingMode(proto::Us4OEMSettings_ReprogrammingMode mode) { diff --git a/arrus/core/io/settingsTest.cpp b/arrus/core/io/settingsTest.cpp index f4b5b7297..c529e1354 100644 --- a/arrus/core/io/settingsTest.cpp +++ b/arrus/core/io/settingsTest.cpp @@ -30,6 +30,10 @@ TEST(ReadingProtoTxtFile, readsUs4RPrototxtSettingsCorrectly) { auto const &us4rSettings = settings.getUs4RSettings(); EXPECT_TRUE(us4rSettings.getUs4OEMSettings().empty()); + EXPECT_EQ(us4rSettings.getNumberOfUs4oems(), 2); + std::vector expectedAdapterToUs4RMapping = {1, 0}; + EXPECT_EQ(us4rSettings.getAdapterToUs4RModuleNumber(), expectedAdapterToUs4RMapping); + EXPECT_EQ(us4rSettings.getChannelsMask(), std::vector({})); EXPECT_EQ(us4rSettings.getUs4OEMChannelsMask(), std::vector>({{}, {}})); diff --git a/arrus/core/io/test-data/us4oems.prototxt b/arrus/core/io/test-data/us4oems.prototxt index ec2c19b3f..01131a0c2 100644 --- a/arrus/core/io/test-data/us4oems.prototxt +++ b/arrus/core/io/test-data/us4oems.prototxt @@ -1,3 +1,5 @@ +dictionary_file: "dictionary.prototxt" + us4r: { us4oems: [ { diff --git a/arrus/core/io/test-data/us4r.prototxt b/arrus/core/io/test-data/us4r.prototxt index 3aa31d7a5..d5fb46d21 100644 --- a/arrus/core/io/test-data/us4r.prototxt +++ b/arrus/core/io/test-data/us4r.prototxt @@ -1,4 +1,4 @@ -dictionary_file: "dictionary.prototxt" +# dictionary_file: "dictionary.prototxt" us4r: { probe_id: { @@ -32,6 +32,8 @@ us4r: { {}, {} ] + nus4oems: 2 + adapterToUs4RModuleNr: [1, 0] }