101{
102 static_assert(std::is_integral_v<WordType> && std::is_unsigned_v<WordType>,
103 "WordType must be an unsigned integral type");
104
105 constexpr int bits_per_word = std::numeric_limits<WordType>::digits;
106
107 static_assert(BitsPerADC > 0 && BitsPerADC <= bits_per_word);
108 static_assert(ADCSPerChannel * NChannels * BitsPerADC == NWords * bits_per_word);
109
110 if (i_channel < 0 || i_channel >= NChannels) {
111 throw std::out_of_range(
112 std::format("Requested channel of {} is out of channel range 0-{}", i_channel, NChannels - 1));
113 }
114
115 if (i_adc < 0 || i_adc >= ADCSPerChannel) {
116 throw std::out_of_range(std::format("Requested ADC index of {} is out of range 0-{}", i_adc, ADCSPerChannel - 1));
117 }
118
119 if constexpr (BitsPerADC < bits_per_word) {
120 if (adc_val >= (static_cast<WordType>(1) << BitsPerADC)) {
121 throw std::out_of_range(std::format(
122 "Requested ADC value of {} exceeds max value of {}", adc_val, (static_cast<WordType>(1) << BitsPerADC) - 1));
123 }
124 }
125
126
127 int i_abs = i_adc * NChannels + i_channel;
128
129 if constexpr (BitsPerADC == bits_per_word) {
130 adc_matrix[i_abs] = adc_val;
131 } else {
132
133
134 int i_word = BitsPerADC * i_abs / bits_per_word;
135 assert(i_word < NWords);
136
137
138 int first_bit_position = (BitsPerADC * i_abs) % bits_per_word;
139
140
141 int bits_in_first_word = std::min(BitsPerADC, bits_per_word - first_bit_position);
142
143 WordType
mask = ((
static_cast<WordType
>(1) << bits_in_first_word) - 1) << first_bit_position;
144
145 adc_matrix[i_word] = (adc_matrix[i_word] & ~mask) | ((static_cast<WordType>(adc_val) << first_bit_position) & mask);
146
147
148 if (bits_in_first_word < BitsPerADC) {
149 assert(i_word < NWords - 1);
150 int bits_in_second_word = BitsPerADC - bits_in_first_word;
151 WordType mask2 = (static_cast<WordType>(1) << bits_in_second_word) - 1;
152 adc_matrix[i_word + 1] = (adc_matrix[i_word + 1] & ~mask2) | ((adc_val >> bits_in_first_word) & mask2);
153 }
154 }
155}