xref: /aosp_15_r20/external/pigweed/pw_i2c/register_device_test.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1 // Copyright 2021 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 #include "pw_i2c/register_device.h"
15 
16 #include <cstring>
17 
18 #include "pw_assert/check.h"
19 #include "pw_bytes/byte_builder.h"
20 #include "pw_unit_test/framework.h"
21 
22 namespace pw {
23 namespace i2c {
24 namespace {
25 
26 using ::pw::Status;
27 using namespace std::literals::chrono_literals;
28 
29 constexpr uint8_t kErrorValue = 0x11;
30 constexpr Address kTestDeviceAddress = Address::SevenBit<0x3F>();
31 
32 constexpr chrono::SystemClock::duration kTimeout =
33     std::chrono::duration_cast<chrono::SystemClock::duration>(100ms);
34 
35 // Default test object. Mimics closely to I2c devices.
36 class TestInitiator : public Initiator {
37  public:
TestInitiator()38   explicit TestInitiator() {}
39 
GetWriteBuffer()40   ByteBuilder& GetWriteBuffer() { return write_buffer_; }
41 
SetReadData(ByteSpan read_data)42   void SetReadData(ByteSpan read_data) {
43     read_buffer_.append(read_data.data(), read_data.size());
44   }
45 
46  private:
DoWriteReadFor(Address,ConstByteSpan tx_data,ByteSpan rx_data,chrono::SystemClock::duration)47   Status DoWriteReadFor(Address,
48                         ConstByteSpan tx_data,
49                         ByteSpan rx_data,
50                         chrono::SystemClock::duration) override {
51     // Write
52     if (!tx_data.empty()) {
53       write_buffer_.append(tx_data.data(), tx_data.size());
54     }
55 
56     // Read
57     if (!rx_data.empty()) {
58       PW_CHECK_UINT_EQ(
59           read_buffer_.size(), rx_data.size(), "Buffer to read is too big");
60       for (uint32_t i = 0; i < rx_data.size(); i++) {
61         rx_data[i] = read_buffer_.data()[i];
62       }
63     }
64 
65     return OkStatus();
66   }
67 
68   ByteBuffer<10> write_buffer_;
69   ByteBuffer<10> read_buffer_;
70 };
71 
TEST(RegisterDevice,Construction)72 TEST(RegisterDevice, Construction) {
73   TestInitiator initiator;
74   RegisterDevice device(initiator,
75                         kTestDeviceAddress,
76                         endian::little,
77                         RegisterAddressSize::k1Byte);
78 }
79 
TEST(RegisterDevice,WriteRegisters8With2RegistersAnd1ByteAddress)80 TEST(RegisterDevice, WriteRegisters8With2RegistersAnd1ByteAddress) {
81   TestInitiator initiator;
82   RegisterDevice device(initiator,
83                         kTestDeviceAddress,
84                         endian::little,
85                         RegisterAddressSize::k1Byte);
86 
87   std::array<std::byte, 2> register_data = {std::byte{0xCD}, std::byte{0xEF}};
88   std::array<std::byte, 3> builder;
89   constexpr uint32_t kRegisterAddress = 0xAB;
90   EXPECT_EQ(
91       device.WriteRegisters(kRegisterAddress, register_data, builder, kTimeout),
92       pw::OkStatus());
93 
94   ByteBuilder& test_device_builder = initiator.GetWriteBuffer();
95   EXPECT_EQ(sizeof(builder), test_device_builder.size());
96 
97   // Check address.
98   EXPECT_EQ(kRegisterAddress,
99             static_cast<uint32_t>(test_device_builder.data()[0]));
100 
101   // Check data.
102   constexpr uint32_t kAddressSize =
103       static_cast<uint32_t>(RegisterAddressSize::k1Byte);
104   for (uint32_t i = 0; i < test_device_builder.size() - kAddressSize; i++) {
105     EXPECT_EQ(register_data[i], test_device_builder.data()[i + kAddressSize]);
106   }
107 }
108 
TEST(RegisterDevice,WriteRegisters8With2RegistersAnd2ByteAddress)109 TEST(RegisterDevice, WriteRegisters8With2RegistersAnd2ByteAddress) {
110   TestInitiator initiator;
111   RegisterDevice device(initiator,
112                         kTestDeviceAddress,
113                         endian::little,
114                         RegisterAddressSize::k2Bytes);
115 
116   constexpr uint32_t kRegisterAddress = 0x89AB;
117   std::byte register_data[2] = {std::byte{0xCD}, std::byte{0xEF}};
118   std::array<std::byte, 4> builder;
119   EXPECT_EQ(
120       device.WriteRegisters(kRegisterAddress, register_data, builder, kTimeout),
121       pw::OkStatus());
122 
123   ByteBuilder& test_device_builder = initiator.GetWriteBuffer();
124   EXPECT_EQ(sizeof(builder), test_device_builder.size());
125 
126   // Check address.
127   uint16_t kActualAddress;
128   std::memcpy(
129       &kActualAddress, test_device_builder.data(), sizeof(kActualAddress));
130   EXPECT_EQ(kRegisterAddress, kActualAddress);
131 
132   // Check data.
133   constexpr uint32_t kAddressSize =
134       static_cast<uint32_t>(RegisterAddressSize::k2Bytes);
135   for (uint32_t i = 0; i < test_device_builder.size() - kAddressSize; i++) {
136     EXPECT_EQ(register_data[i], test_device_builder.data()[i + kAddressSize]);
137   }
138 }
139 
TEST(RegisterDevice,WriteRegisters16With2RegistersAnd2ByteAddress)140 TEST(RegisterDevice, WriteRegisters16With2RegistersAnd2ByteAddress) {
141   TestInitiator initiator;
142   RegisterDevice device(initiator,
143                         kTestDeviceAddress,
144                         endian::little,
145                         RegisterAddressSize::k2Bytes);
146 
147   constexpr uint32_t kRegisterAddress = 0x89AB;
148   std::array<uint16_t, 2> register_data = {0xCDEF, 0x1234};
149   std::array<std::byte, 6> builder;
150   EXPECT_EQ(device.WriteRegisters16(
151                 kRegisterAddress, register_data, builder, kTimeout),
152             pw::OkStatus());
153 
154   ByteBuilder& test_device_builder = initiator.GetWriteBuffer();
155   EXPECT_EQ(sizeof(builder), test_device_builder.size());
156 
157   // Check address.
158   uint16_t kActualAddress;
159   std::memcpy(
160       &kActualAddress, test_device_builder.data(), sizeof(kActualAddress));
161   EXPECT_EQ(kRegisterAddress, kActualAddress);
162 
163   // Check data.
164   constexpr uint32_t kAddressSize =
165       static_cast<uint32_t>(RegisterAddressSize::k2Bytes);
166 
167   for (uint32_t i = kAddressSize, j = 0; i < test_device_builder.size();
168        i += kAddressSize, j++) {
169     uint16_t actualData;
170     std::memcpy(
171         &actualData, &test_device_builder.data()[i], sizeof(actualData));
172     EXPECT_EQ(register_data[j], actualData);
173   }
174 }
175 
TEST(RegisterDevice,WriteRegisters16With2RegistersAnd2ByteAddressBigEndian)176 TEST(RegisterDevice, WriteRegisters16With2RegistersAnd2ByteAddressBigEndian) {
177   TestInitiator initiator;
178   RegisterDevice device(
179       initiator, kTestDeviceAddress, endian::big, RegisterAddressSize::k2Bytes);
180 
181   constexpr uint32_t kRegisterAddress = 0x89AB;
182   std::array<uint16_t, 2> register_data = {0xCDEF, 0x1234};
183   std::array<std::byte, 6> builder;
184   EXPECT_EQ(device.WriteRegisters16(
185                 kRegisterAddress, register_data, builder, kTimeout),
186             pw::OkStatus());
187 
188   ByteBuilder& test_device_builder = initiator.GetWriteBuffer();
189   EXPECT_EQ(sizeof(builder), test_device_builder.size());
190 
191   // Check address.
192   uint16_t kActualAddress;
193   std::memcpy(
194       &kActualAddress, test_device_builder.data(), sizeof(kActualAddress));
195   EXPECT_EQ(bytes::ReadInOrder<uint16_t>(endian::big, &kRegisterAddress),
196             kActualAddress);
197 
198   // Check data.
199   constexpr uint32_t kAddressSize =
200       static_cast<uint32_t>(RegisterAddressSize::k2Bytes);
201 
202   for (uint32_t i = kAddressSize, j = 0; i < test_device_builder.size();
203        i += kAddressSize, j++) {
204     uint16_t actualData;
205     std::memcpy(
206         &actualData, &test_device_builder.data()[i], sizeof(actualData));
207     EXPECT_EQ(bytes::ReadInOrder<uint16_t>(endian::big, &register_data[j]),
208               actualData);
209   }
210 }
211 
TEST(RegisterDevice,WriteRegisters8BufferTooSmall)212 TEST(RegisterDevice, WriteRegisters8BufferTooSmall) {
213   TestInitiator initiator;
214   RegisterDevice device(initiator,
215                         kTestDeviceAddress,
216                         endian::little,
217                         RegisterAddressSize::k2Bytes);
218 
219   constexpr uint32_t kRegisterAddress = 0x89AB;
220   std::array<std::byte, 2> register_data = {std::byte{0xCD}, std::byte{0xEF}};
221   std::array<std::byte, 2> builder;
222   EXPECT_EQ(
223       device.WriteRegisters(kRegisterAddress, register_data, builder, kTimeout),
224       pw::Status::OutOfRange());
225 }
226 
TEST(RegisterDevice,WriteRegister16With1ByteAddress)227 TEST(RegisterDevice, WriteRegister16With1ByteAddress) {
228   TestInitiator initiator;
229   RegisterDevice device(initiator,
230                         kTestDeviceAddress,
231                         endian::little,
232                         RegisterAddressSize::k1Byte);
233 
234   constexpr uint32_t kRegisterAddress = 0xAB;
235   constexpr uint16_t kRegisterData = 0xBCDE;
236   EXPECT_EQ(device.WriteRegister16(kRegisterAddress, kRegisterData, kTimeout),
237             pw::OkStatus());
238 
239   constexpr uint32_t kAddressSize =
240       static_cast<uint32_t>(RegisterAddressSize::k1Byte);
241   ByteBuilder& test_device_builder = initiator.GetWriteBuffer();
242   EXPECT_EQ(test_device_builder.size(), kAddressSize + sizeof(kRegisterData));
243 
244   // Check address.
245   EXPECT_EQ(kRegisterAddress,
246             static_cast<uint32_t>(test_device_builder.data()[0]));
247 
248   // Check data.
249   for (uint32_t i = 0; i < test_device_builder.size() - kAddressSize; i++) {
250     EXPECT_EQ(
251         (kRegisterData >> (8 * i)) & 0xFF,
252         static_cast<uint16_t>(test_device_builder.data()[i + kAddressSize]));
253   }
254 }
255 
TEST(RegisterDevice,WriteRegister32With1ByteAddress)256 TEST(RegisterDevice, WriteRegister32With1ByteAddress) {
257   TestInitiator initiator;
258   RegisterDevice device(initiator,
259                         kTestDeviceAddress,
260                         endian::little,
261                         RegisterAddressSize::k1Byte);
262 
263   constexpr uint32_t kRegisterAddress = 0xAB;
264   constexpr uint32_t kRegisterData = 0xBCCDDEEF;
265   EXPECT_EQ(device.WriteRegister32(kRegisterAddress, kRegisterData, kTimeout),
266             pw::OkStatus());
267 
268   constexpr uint32_t kAddressSize =
269       static_cast<uint32_t>(RegisterAddressSize::k1Byte);
270   ByteBuilder& test_device_builder = initiator.GetWriteBuffer();
271   EXPECT_EQ(test_device_builder.size(), kAddressSize + sizeof(kRegisterData));
272 
273   // Check address.
274   EXPECT_EQ(kRegisterAddress,
275             static_cast<uint32_t>(test_device_builder.data()[0]));
276 
277   // Check data.
278   for (uint32_t i = 0; i < test_device_builder.size() - kAddressSize; i++) {
279     EXPECT_EQ(
280         (kRegisterData >> (8 * i)) & 0xFF,
281         static_cast<uint32_t>(test_device_builder.data()[i + kAddressSize]));
282   }
283 }
284 
TEST(RegisterDevice,WriteRegister16with2ByteAddress)285 TEST(RegisterDevice, WriteRegister16with2ByteAddress) {
286   TestInitiator initiator;
287   RegisterDevice device(initiator,
288                         kTestDeviceAddress,
289                         endian::little,
290                         RegisterAddressSize::k2Bytes);
291 
292   constexpr uint32_t kRegisterAddress = 0xAB23;
293   constexpr uint16_t kRegisterData = 0xBCDD;
294   EXPECT_EQ(device.WriteRegister16(kRegisterAddress, kRegisterData, kTimeout),
295             pw::OkStatus());
296 
297   constexpr uint32_t kAddressSize =
298       static_cast<uint32_t>(RegisterAddressSize::k2Bytes);
299   ByteBuilder& test_device_builder = initiator.GetWriteBuffer();
300   EXPECT_EQ(test_device_builder.size(), kAddressSize + sizeof(kRegisterData));
301 
302   // Check address.
303   uint16_t kActualAddress;
304   std::memcpy(
305       &kActualAddress, test_device_builder.data(), sizeof(kActualAddress));
306   EXPECT_EQ(kRegisterAddress, kActualAddress);
307 
308   // Check data.
309   for (uint32_t i = 0; i < test_device_builder.size() - kAddressSize; i++) {
310     EXPECT_EQ(
311         (kRegisterData >> (8 * i)) & 0xFF,
312         static_cast<uint16_t>(test_device_builder.data()[i + kAddressSize]));
313   }
314 }
315 
TEST(RegisterDevice,WriteRegister16With1ByteAddressAndBigEndian)316 TEST(RegisterDevice, WriteRegister16With1ByteAddressAndBigEndian) {
317   TestInitiator initiator;
318   RegisterDevice device(
319       initiator, kTestDeviceAddress, endian::big, RegisterAddressSize::k1Byte);
320 
321   constexpr uint32_t kRegisterAddress = 0xAB;
322   constexpr uint16_t kRegisterData = 0xBCDE;
323   EXPECT_EQ(device.WriteRegister16(kRegisterAddress, kRegisterData, kTimeout),
324             pw::OkStatus());
325 
326   constexpr uint32_t kAddressSize =
327       static_cast<uint32_t>(RegisterAddressSize::k1Byte);
328   ByteBuilder& test_device_builder = initiator.GetWriteBuffer();
329   EXPECT_EQ(test_device_builder.size(), kAddressSize + sizeof(kRegisterData));
330 
331   // Check address.
332   EXPECT_EQ(kRegisterAddress,
333             static_cast<uint32_t>(test_device_builder.data()[0]));
334 
335   // Check data.
336   for (uint32_t i = 0; i < test_device_builder.size() - kAddressSize; i++) {
337     const uint32_t shift = test_device_builder.size() - kAddressSize - (i + 1);
338     EXPECT_EQ(
339         (kRegisterData >> (8 * shift)) & 0xFF,
340         static_cast<uint16_t>(test_device_builder.data()[i + kAddressSize]));
341   }
342 }
343 
TEST(RegisterDevice,WriteRegister32With1ByteAddressAndBigEndian)344 TEST(RegisterDevice, WriteRegister32With1ByteAddressAndBigEndian) {
345   TestInitiator initiator;
346   RegisterDevice device(
347       initiator, kTestDeviceAddress, endian::big, RegisterAddressSize::k1Byte);
348 
349   constexpr uint32_t kRegisterAddress = 0xAB;
350   constexpr uint32_t kRegisterData = 0xBCCDDEEF;
351   EXPECT_EQ(device.WriteRegister32(kRegisterAddress, kRegisterData, kTimeout),
352             pw::OkStatus());
353 
354   constexpr uint32_t kAddressSize =
355       static_cast<uint32_t>(RegisterAddressSize::k1Byte);
356   ByteBuilder& test_device_builder = initiator.GetWriteBuffer();
357   EXPECT_EQ(test_device_builder.size(), kAddressSize + sizeof(kRegisterData));
358 
359   // Check address.
360   EXPECT_EQ(kRegisterAddress,
361             static_cast<uint32_t>(test_device_builder.data()[0]));
362 
363   // Check data.
364   for (uint32_t i = 0; i < test_device_builder.size() - kAddressSize; i++) {
365     const uint32_t shift = test_device_builder.size() - kAddressSize - (i + 1);
366     EXPECT_EQ(
367         (kRegisterData >> (8 * shift)) & 0xFF,
368         static_cast<uint32_t>(test_device_builder.data()[i + kAddressSize]));
369   }
370 }
371 
TEST(RegisterDevice,WriteRegister16With2ByteAddressAndBigEndian)372 TEST(RegisterDevice, WriteRegister16With2ByteAddressAndBigEndian) {
373   TestInitiator initiator;
374   RegisterDevice device(
375       initiator, kTestDeviceAddress, endian::big, RegisterAddressSize::k2Bytes);
376 
377   constexpr uint32_t kRegisterAddress = 0xAB11;
378   constexpr uint16_t kRegisterData = 0xBCDF;
379   EXPECT_EQ(device.WriteRegister16(kRegisterAddress, kRegisterData, kTimeout),
380             pw::OkStatus());
381 
382   constexpr uint32_t kAddressSize =
383       static_cast<uint32_t>(RegisterAddressSize::k2Bytes);
384   ByteBuilder& test_device_builder = initiator.GetWriteBuffer();
385   EXPECT_EQ(test_device_builder.size(), kAddressSize + sizeof(kRegisterData));
386 
387   // Check address.
388   uint16_t kActualAddress;
389   std::memcpy(
390       &kActualAddress, test_device_builder.data(), sizeof(kActualAddress));
391   EXPECT_EQ(bytes::ReadInOrder<uint16_t>(endian::big, &kRegisterAddress),
392             kActualAddress);
393 
394   // Check data.
395   for (uint32_t i = 0; i < test_device_builder.size() - kAddressSize; i++) {
396     const uint32_t shift = test_device_builder.size() - kAddressSize - (i + 1);
397     EXPECT_EQ(
398         (kRegisterData >> (8 * shift)) & 0xFF,
399         static_cast<uint16_t>(test_device_builder.data()[i + kAddressSize]));
400   }
401 }
402 
TEST(RegisterDevice,ReadRegisters8ByteWith2RegistersAnd1ByteAddress)403 TEST(RegisterDevice, ReadRegisters8ByteWith2RegistersAnd1ByteAddress) {
404   TestInitiator initiator;
405   RegisterDevice device(initiator,
406                         kTestDeviceAddress,
407                         endian::little,
408                         RegisterAddressSize::k1Byte);
409 
410   std::array<std::byte, 2> register_data = {std::byte{0xCD}, std::byte{0xEF}};
411   initiator.SetReadData(register_data);
412 
413   std::array<std::byte, 2> buffer;
414   constexpr uint32_t kRegisterAddress = 0xAB;
415   EXPECT_EQ(device.ReadRegisters(kRegisterAddress, buffer, kTimeout),
416             pw::OkStatus());
417 
418   // Check address.
419   ByteBuilder& address_buffer = initiator.GetWriteBuffer();
420   EXPECT_EQ(static_cast<uint32_t>(RegisterAddressSize::k1Byte),
421             address_buffer.size());
422 
423   const uint8_t kActualAddress = *(reinterpret_cast<uint8_t*>(
424       const_cast<std::byte*>(address_buffer.data())));
425   EXPECT_EQ(kRegisterAddress, kActualAddress);
426 
427   // Check data.
428   for (uint32_t i = 0; i < sizeof(buffer); i++) {
429     EXPECT_EQ(buffer[i], register_data[i]);
430   }
431 }
432 
TEST(RegisterDevice,ReadRegisters8IntWith2RegistersAnd1ByteAddress)433 TEST(RegisterDevice, ReadRegisters8IntWith2RegistersAnd1ByteAddress) {
434   TestInitiator initiator;
435   RegisterDevice device(initiator,
436                         kTestDeviceAddress,
437                         endian::little,
438                         RegisterAddressSize::k1Byte);
439 
440   std::array<uint8_t, 2> register_data = {0xCD, 0xEF};
441   initiator.SetReadData(
442       as_writable_bytes(span(register_data.data(), register_data.size())));
443 
444   std::array<uint8_t, 2> buffer;
445   constexpr uint32_t kRegisterAddress = 0xAB;
446   EXPECT_EQ(device.ReadRegisters8(kRegisterAddress, buffer, kTimeout),
447             pw::OkStatus());
448 
449   // Check address.
450   ByteBuilder& address_buffer = initiator.GetWriteBuffer();
451   EXPECT_EQ(static_cast<uint32_t>(RegisterAddressSize::k1Byte),
452             address_buffer.size());
453 
454   const uint8_t kActualAddress = *(reinterpret_cast<uint8_t*>(
455       const_cast<std::byte*>(address_buffer.data())));
456   EXPECT_EQ(kRegisterAddress, kActualAddress);
457 
458   // Check data.
459   for (uint32_t i = 0; i < sizeof(buffer); i++) {
460     EXPECT_EQ(buffer[i], register_data[i]);
461   }
462 }
463 
TEST(RegisterDevice,ReadRegisters8ByteWith2RegistersAnd2ByteAddress)464 TEST(RegisterDevice, ReadRegisters8ByteWith2RegistersAnd2ByteAddress) {
465   TestInitiator initiator;
466   RegisterDevice device(initiator,
467                         kTestDeviceAddress,
468                         endian::little,
469                         RegisterAddressSize::k2Bytes);
470 
471   std::array<std::byte, 2> register_data = {std::byte{0xCD}, std::byte{0xEF}};
472   initiator.SetReadData(register_data);
473 
474   std::array<std::byte, 2> buffer;
475   constexpr uint32_t kRegisterAddress = 0xABBA;
476   EXPECT_EQ(device.ReadRegisters(kRegisterAddress, buffer, kTimeout),
477             pw::OkStatus());
478 
479   // Check address.
480   ByteBuilder& address_buffer = initiator.GetWriteBuffer();
481   EXPECT_EQ(static_cast<uint32_t>(RegisterAddressSize::k2Bytes),
482             address_buffer.size());
483 
484   uint16_t kActualAddress;
485   std::memcpy(&kActualAddress, address_buffer.data(), sizeof(kActualAddress));
486   EXPECT_EQ(kRegisterAddress, kActualAddress);
487 
488   // Check data.
489   for (uint32_t i = 0; i < sizeof(buffer); i++) {
490     EXPECT_EQ(buffer[i], register_data[i]);
491   }
492 }
493 
TEST(RegisterDevice,ReadRegisters16With2RegistersAnd2ByteAddress)494 TEST(RegisterDevice, ReadRegisters16With2RegistersAnd2ByteAddress) {
495   TestInitiator initiator;
496   RegisterDevice device(initiator,
497                         kTestDeviceAddress,
498                         endian::little,
499                         RegisterAddressSize::k2Bytes);
500 
501   std::array<uint16_t, 2> register_data = {0xCDEF, 0x1234};
502   initiator.SetReadData(
503       as_writable_bytes(span(register_data.data(), register_data.size())));
504 
505   std::array<uint16_t, 2> buffer;
506   constexpr uint32_t kRegisterAddress = 0xAB;
507   EXPECT_EQ(device.ReadRegisters16(kRegisterAddress, buffer, kTimeout),
508             pw::OkStatus());
509 
510   // Check address.
511   ByteBuilder& address_buffer = initiator.GetWriteBuffer();
512   EXPECT_EQ(static_cast<uint32_t>(RegisterAddressSize::k2Bytes),
513             address_buffer.size());
514 
515   uint16_t kActualAddress;
516   std::memcpy(&kActualAddress, address_buffer.data(), sizeof(kActualAddress));
517   EXPECT_EQ(kRegisterAddress, kActualAddress);
518 
519   // Check data.
520   for (uint32_t i = 0; i < buffer.size(); i++) {
521     EXPECT_EQ(buffer[i], register_data[i]);
522   }
523 }
524 
TEST(RegisterDevice,ReadRegisters16With2RegistersAnd2ByteAddressBigEndian)525 TEST(RegisterDevice, ReadRegisters16With2RegistersAnd2ByteAddressBigEndian) {
526   TestInitiator initiator;
527   RegisterDevice device(
528       initiator, kTestDeviceAddress, endian::big, RegisterAddressSize::k2Bytes);
529 
530   std::array<uint16_t, 2> register_data = {0xCDEF, 0x1234};
531   initiator.SetReadData(
532       as_writable_bytes(span(register_data.data(), register_data.size())));
533 
534   std::array<uint16_t, 2> buffer;
535   constexpr uint32_t kRegisterAddress = 0xAB;
536   EXPECT_EQ(device.ReadRegisters16(kRegisterAddress, buffer, kTimeout),
537             pw::OkStatus());
538 
539   // Check address.
540   ByteBuilder& address_buffer = initiator.GetWriteBuffer();
541   EXPECT_EQ(static_cast<uint32_t>(RegisterAddressSize::k2Bytes),
542             address_buffer.size());
543 
544   uint16_t kActualAddress;
545   std::memcpy(&kActualAddress, address_buffer.data(), sizeof(kActualAddress));
546   EXPECT_EQ(bytes::ReadInOrder<uint16_t>(endian::big, &kRegisterAddress),
547             kActualAddress);
548 
549   // Check data.
550   for (uint32_t i = 0; i < buffer.size(); i++) {
551     EXPECT_EQ(bytes::ReadInOrder<uint16_t>(endian::big, &register_data[i]),
552               buffer[i]);
553   }
554 }
555 
TEST(RegisterDevice,ReadRegister16With1ByteAddress)556 TEST(RegisterDevice, ReadRegister16With1ByteAddress) {
557   TestInitiator initiator;
558   RegisterDevice device(initiator,
559                         kTestDeviceAddress,
560                         endian::little,
561                         RegisterAddressSize::k1Byte);
562 
563   std::array<std::byte, 2> register_data = {std::byte{0xCD}, std::byte{0xEF}};
564   initiator.SetReadData(register_data);
565 
566   constexpr uint32_t kRegisterAddress = 0xAB;
567   Result<uint16_t> result = device.ReadRegister16(kRegisterAddress, kTimeout);
568   EXPECT_TRUE(result.ok());
569   uint16_t read_data = result.value_or(kErrorValue);
570 
571   // Check address.
572   ByteBuilder& address_buffer = initiator.GetWriteBuffer();
573   EXPECT_EQ(static_cast<uint32_t>(RegisterAddressSize::k1Byte),
574             address_buffer.size());
575 
576   const uint8_t kActualAddress = *(reinterpret_cast<uint8_t*>(
577       const_cast<std::byte*>(address_buffer.data())));
578   EXPECT_EQ(kRegisterAddress, kActualAddress);
579 
580   // Check data.
581   uint8_t* read_pointer = reinterpret_cast<uint8_t*>(&read_data);
582   for (uint32_t i = 0; i < sizeof(read_data); i++) {
583     EXPECT_EQ(read_pointer[i], static_cast<uint8_t>(register_data[i]));
584   }
585 }
586 
TEST(RegisterDevice,ReadRegister32With1ByteAddress)587 TEST(RegisterDevice, ReadRegister32With1ByteAddress) {
588   TestInitiator initiator;
589   RegisterDevice device(initiator,
590                         kTestDeviceAddress,
591                         endian::little,
592                         RegisterAddressSize::k1Byte);
593 
594   std::array<std::byte, 4> register_data = {
595       std::byte{0x98}, std::byte{0x76}, std::byte{0x54}, std::byte{0x32}};
596   initiator.SetReadData(register_data);
597 
598   constexpr uint32_t kRegisterAddress = 0xAB;
599   Result<uint32_t> result = device.ReadRegister32(kRegisterAddress, kTimeout);
600   EXPECT_TRUE(result.ok());
601   uint32_t read_data = result.value_or(kErrorValue);
602 
603   // Check address.
604   ByteBuilder& address_buffer = initiator.GetWriteBuffer();
605   EXPECT_EQ(static_cast<uint32_t>(RegisterAddressSize::k1Byte),
606             address_buffer.size());
607 
608   const uint8_t kActualAddress = *(reinterpret_cast<uint8_t*>(
609       const_cast<std::byte*>(address_buffer.data())));
610   EXPECT_EQ(kRegisterAddress, kActualAddress);
611 
612   // Check data.
613   uint8_t* read_pointer = reinterpret_cast<uint8_t*>(&read_data);
614   for (uint32_t i = 0; i < sizeof(read_data); i++) {
615     EXPECT_EQ(read_pointer[i], static_cast<uint8_t>(register_data[i]));
616   }
617 }
618 
TEST(RegisterDevice,ReadRegister16With2ByteAddress)619 TEST(RegisterDevice, ReadRegister16With2ByteAddress) {
620   TestInitiator initiator;
621   RegisterDevice device(initiator,
622                         kTestDeviceAddress,
623                         endian::little,
624                         RegisterAddressSize::k2Bytes);
625 
626   std::array<std::byte, 2> register_data = {std::byte{0x98}, std::byte{0x76}};
627   initiator.SetReadData(register_data);
628 
629   constexpr uint32_t kRegisterAddress = 0xA4AB;
630   Result<uint16_t> result = device.ReadRegister16(kRegisterAddress, kTimeout);
631   EXPECT_TRUE(result.ok());
632   uint16_t read_data = result.value_or(kErrorValue);
633 
634   // Check address.
635   ByteBuilder& address_buffer = initiator.GetWriteBuffer();
636   EXPECT_EQ(static_cast<uint32_t>(RegisterAddressSize::k2Bytes),
637             address_buffer.size());
638 
639   uint16_t kActualAddress;
640   std::memcpy(&kActualAddress, address_buffer.data(), sizeof(kActualAddress));
641   EXPECT_EQ(kRegisterAddress, kActualAddress);
642 
643   // Check data.
644   uint8_t* read_pointer = reinterpret_cast<uint8_t*>(&read_data);
645   for (uint32_t i = 0; i < sizeof(read_data); i++) {
646     EXPECT_EQ(read_pointer[i], static_cast<uint8_t>(register_data[i]));
647   }
648 }
649 
TEST(RegisterDevice,ReadRegister16With1ByteAddressAndBigEndian)650 TEST(RegisterDevice, ReadRegister16With1ByteAddressAndBigEndian) {
651   TestInitiator initiator;
652   RegisterDevice device(
653       initiator, kTestDeviceAddress, endian::big, RegisterAddressSize::k1Byte);
654 
655   std::array<std::byte, 2> register_data = {std::byte{0x98}, std::byte{0x76}};
656   initiator.SetReadData(register_data);
657 
658   constexpr uint32_t kRegisterAddress = 0xAB;
659   Result<uint16_t> result = device.ReadRegister16(kRegisterAddress, kTimeout);
660   EXPECT_TRUE(result.ok());
661   uint16_t read_data = result.value_or(kErrorValue);
662 
663   // Check address.
664   ByteBuilder& address_buffer = initiator.GetWriteBuffer();
665   EXPECT_EQ(static_cast<uint32_t>(RegisterAddressSize::k1Byte),
666             address_buffer.size());
667 
668   const uint8_t kActualAddress = *(reinterpret_cast<uint8_t*>(
669       const_cast<std::byte*>(address_buffer.data())));
670   EXPECT_EQ(kRegisterAddress, kActualAddress);
671 
672   // Check data.
673   uint8_t* read_pointer = reinterpret_cast<uint8_t*>(&read_data);
674   for (uint32_t i = 0; i < sizeof(read_data); i++) {
675     const uint32_t kReadPointerIndex = sizeof(read_data) - 1 - i;
676     EXPECT_EQ(read_pointer[kReadPointerIndex],
677               static_cast<uint8_t>(register_data[i]));
678   }
679 }
680 
TEST(RegisterDevice,ReadRegister32With1ByteAddressAndBigEndian)681 TEST(RegisterDevice, ReadRegister32With1ByteAddressAndBigEndian) {
682   TestInitiator initiator;
683   RegisterDevice device(
684       initiator, kTestDeviceAddress, endian::big, RegisterAddressSize::k1Byte);
685 
686   std::array<std::byte, 4> register_data = {
687       std::byte{0x98}, std::byte{0x76}, std::byte{0x54}, std::byte{0x32}};
688   initiator.SetReadData(register_data);
689 
690   constexpr uint32_t kRegisterAddress = 0xAB;
691   Result<uint32_t> result = device.ReadRegister32(kRegisterAddress, kTimeout);
692   EXPECT_TRUE(result.ok());
693   uint32_t read_data = result.value_or(kErrorValue);
694 
695   // Check address.
696   ByteBuilder& address_buffer = initiator.GetWriteBuffer();
697   EXPECT_EQ(static_cast<uint32_t>(RegisterAddressSize::k1Byte),
698             address_buffer.size());
699 
700   const uint8_t kActualAddress = *(reinterpret_cast<uint8_t*>(
701       const_cast<std::byte*>(address_buffer.data())));
702   EXPECT_EQ(kRegisterAddress, kActualAddress);
703 
704   // Check data.
705   uint8_t* read_pointer = reinterpret_cast<uint8_t*>(&read_data);
706   for (uint32_t i = 0; i < sizeof(read_data); i++) {
707     const uint32_t kReadPointerIndex = sizeof(read_data) - 1 - i;
708     EXPECT_EQ(read_pointer[kReadPointerIndex],
709               static_cast<uint8_t>(register_data[i]));
710   }
711 }
712 
TEST(RegisterDevice,ReadRegister16With2ByteAddressAndBigEndian)713 TEST(RegisterDevice, ReadRegister16With2ByteAddressAndBigEndian) {
714   TestInitiator initiator;
715   RegisterDevice device(
716       initiator, kTestDeviceAddress, endian::big, RegisterAddressSize::k2Bytes);
717 
718   std::array<std::byte, 2> register_data = {std::byte{0x98}, std::byte{0x76}};
719   initiator.SetReadData(register_data);
720 
721   constexpr uint32_t kRegisterAddress = 0xABEF;
722   Result<uint16_t> result = device.ReadRegister16(kRegisterAddress, kTimeout);
723   EXPECT_TRUE(result.ok());
724   uint16_t read_data = result.value_or(kErrorValue);
725 
726   // Check address.
727   ByteBuilder& address_buffer = initiator.GetWriteBuffer();
728   EXPECT_EQ(static_cast<uint32_t>(RegisterAddressSize::k2Bytes),
729             address_buffer.size());
730 
731   uint16_t kActualAddress;
732   std::memcpy(&kActualAddress, address_buffer.data(), sizeof(kActualAddress));
733   EXPECT_EQ(bytes::ReadInOrder<uint16_t>(endian::big, &kRegisterAddress),
734             kActualAddress);
735 
736   // Check data.
737   uint8_t* read_pointer = reinterpret_cast<uint8_t*>(&read_data);
738   for (uint32_t i = 0; i < sizeof(read_data); i++) {
739     const uint32_t kReadPointerIndex = sizeof(read_data) - 1 - i;
740     EXPECT_EQ(read_pointer[kReadPointerIndex],
741               static_cast<uint8_t>(register_data[i]));
742   }
743 }
744 
TEST(RegisterDevice,ReadRegister16With2ByteBigEndianAddress)745 TEST(RegisterDevice, ReadRegister16With2ByteBigEndianAddress) {
746   TestInitiator initiator;
747   RegisterDevice device(initiator,
748                         kTestDeviceAddress,
749                         endian::big,
750                         endian::little,
751                         RegisterAddressSize::k2Bytes);
752 
753   std::array<std::byte, 2> register_data = {std::byte{0x98}, std::byte{0x76}};
754   initiator.SetReadData(register_data);
755 
756   constexpr uint32_t kRegisterAddress = 0xABEF;
757   Result<uint16_t> result = device.ReadRegister16(kRegisterAddress, kTimeout);
758   EXPECT_TRUE(result.ok());
759   uint16_t read_data = result.value_or(kErrorValue);
760 
761   // Check address.
762   ByteBuilder& address_buffer = initiator.GetWriteBuffer();
763   EXPECT_EQ(static_cast<uint32_t>(RegisterAddressSize::k2Bytes),
764             address_buffer.size());
765 
766   uint16_t kActualAddress;
767   std::memcpy(&kActualAddress, address_buffer.data(), sizeof(kActualAddress));
768   EXPECT_EQ(bytes::ReadInOrder<uint16_t>(endian::big, &kRegisterAddress),
769             kActualAddress);
770 
771   // Check data.
772   uint8_t* read_pointer = reinterpret_cast<uint8_t*>(&read_data);
773   for (uint32_t i = 0; i < sizeof(read_data); i++) {
774     EXPECT_EQ(read_pointer[i], static_cast<uint8_t>(register_data[i]));
775   }
776 }
777 
TEST(RegisterDevice,WriteRegister16with2ByteBigEndianAddress)778 TEST(RegisterDevice, WriteRegister16with2ByteBigEndianAddress) {
779   TestInitiator initiator;
780   RegisterDevice device(initiator,
781                         kTestDeviceAddress,
782                         endian::big,
783                         endian::little,
784                         RegisterAddressSize::k2Bytes);
785 
786   constexpr uint32_t kRegisterAddress = 0xAB11;
787   constexpr uint16_t kRegisterData = 0xBCDF;
788   EXPECT_EQ(device.WriteRegister16(kRegisterAddress, kRegisterData, kTimeout),
789             pw::OkStatus());
790 
791   constexpr uint32_t kAddressSize =
792       static_cast<uint32_t>(RegisterAddressSize::k2Bytes);
793   ByteBuilder& test_device_builder = initiator.GetWriteBuffer();
794   EXPECT_EQ(test_device_builder.size(), kAddressSize + sizeof(kRegisterData));
795 
796   // Check address.
797   uint16_t kActualAddress;
798   std::memcpy(
799       &kActualAddress, test_device_builder.data(), sizeof(kActualAddress));
800   EXPECT_EQ(bytes::ReadInOrder<uint16_t>(endian::big, &kRegisterAddress),
801             kActualAddress);
802 
803   // Check data.
804   for (uint32_t i = 0; i < test_device_builder.size() - kAddressSize; i++) {
805     EXPECT_EQ(
806         (kRegisterData >> (8 * i)) & 0xFF,
807         static_cast<uint16_t>(test_device_builder.data()[i + kAddressSize]));
808   }
809 }
810 
811 }  // namespace
812 }  // namespace i2c
813 }  // namespace pw
814