1 // Copyright 2020 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 #pragma once
15 
16 #include <cstdint>
17 
18 namespace pw::i2c {
19 
20 // The Address is a helper class which represents I2C addresses which is
21 // used by pw::i2c APIs.
22 //
23 // Example usage:
24 //   constexpr Address foo = Address::SevenBit<0x42>();
25 //   uint8_t foo_raw_address = foo.GetSevenBit();
26 //
27 //   const Address bar(0x200);  // 10 bit address.
28 //   uint16_t bar_raw_address = bar.GetTenBit();
29 //   // Note that bar.GetSevenBit() would assert here.
30 //
31 class Address {
32  public:
33   static constexpr uint8_t kMaxSevenBitAddress = (1 << 7) - 1;
34   static constexpr uint16_t kMaxTenBitAddress = (1 << 10) - 1;
35 
36   // Helper constructor to ensure the address fits in the address space at
37   // compile time, skipping the construction time assert.
38   template <uint16_t kAddress>
TenBit()39   static constexpr Address TenBit() {
40     static_assert(kAddress <= kMaxTenBitAddress);
41     return Address(kAddress, kAlreadyCheckedAddress);
42   }
43 
44   // Helper constructor to ensure the address fits in the address space at
45   // compile time, skipping the construction time assert.
46   template <uint8_t kAddress>
SevenBit()47   static constexpr Address SevenBit() {
48     static_assert(kAddress <= kMaxSevenBitAddress);
49     return Address(kAddress, kAlreadyCheckedAddress);
50   }
51 
52   // Precondition: The address is at least a valid ten bit address.
53   explicit Address(uint16_t address);
54 
55   // Precondition: The address is a valid 7 bit address.
56   uint8_t GetSevenBit() const;
57 
GetTenBit()58   uint16_t GetTenBit() const { return address_; }
59 
60  private:
61   enum AlreadyCheckedAddress { kAlreadyCheckedAddress };
Address(uint16_t address,AlreadyCheckedAddress)62   constexpr Address(uint16_t address, AlreadyCheckedAddress)
63       : address_(address) {}
64 
65   uint16_t address_;
66 };
67 
68 }  // namespace pw::i2c
69