M5UnitUnified 0.4.4 git rev:306ddd5
Loading...
Searching...
No Matches
test_template.hpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2024 M5Stack Technology CO LTD
3 *
4 * SPDX-License-Identifier: MIT
5 */
11#ifndef M5_UNIT_COMPONENT_GOOGLETEST_TEMPLATE_HPP
12#define M5_UNIT_COMPONENT_GOOGLETEST_TEMPLATE_HPP
13
15#include <type_traits>
16#include <Wire.h>
17#include <SPI.h>
18#include <esp32-hal-i2c.h>
19#include <M5Unified.h>
20
21namespace m5 {
22namespace unit {
27namespace googletest {
28
38template <typename U>
39class I2CComponentTestBase : public ::testing::Test {
40 static_assert(std::is_base_of<m5::unit::Component, U>::value, "U must be derived from Component");
41
42protected:
43 virtual void SetUp() override
44 {
45 unit.reset(get_instance());
46 if (!unit) {
47 FAIL() << "Failed to get_instance";
48 return;
49 }
50 ustr = m5::utility::formatString("%s", unit->deviceName());
51 if (!begin()) {
52 FAIL() << "Failed to begin " << ustr;
53 }
54 }
55
56 virtual void TearDown() override
57 {
58 }
59
60 virtual bool begin()
61 {
62 auto board = M5.getBoard();
63 if (board == m5::board_t::board_ArduinoNessoN1) {
64 // NessoN1: GROVE is port_b (GPIO 5/4). SoftwareI2C via M5HAL
65 auto sda = M5.getPin(m5::pin_name_t::port_b_out);
66 auto scl = M5.getPin(m5::pin_name_t::port_b_in);
67 return begin_with_software_i2c(sda, scl);
68 }
69 if (board == m5::board_t::board_M5NanoC6) {
70 // NanoC6: Use Ex_I2C (avoids Wire/Ex_I2C dual-driver conflict)
71 return begin_with_ex_i2c();
72 }
73 // Standard boards: Wire (initialized here with unit's clock)
74 return begin_with_wire(Wire);
75 }
76
77 bool begin_with_wire(TwoWire& wire, uint32_t wnum = 0)
78 {
79 auto pin_num_sda = M5.getPin(m5::pin_name_t::port_a_sda);
80 auto pin_num_scl = M5.getPin(m5::pin_name_t::port_a_scl);
81 auto freq = unit->component_config().clock;
82 if (i2cIsInit(wnum)) {
83 M5_LOGD("Already initialized Wire%u. Terminate and restart FREQ %u", wnum, freq);
84 wire.end();
85 }
86 M5_LOGI("Wire begin SDA:%u SCL:%u FREQ:%u", pin_num_sda, pin_num_scl, freq);
87 wire.begin(pin_num_sda, pin_num_scl, freq);
88 return Units.add(*unit, wire) && Units.begin();
89 }
90
91 bool begin_with_ex_i2c()
92 {
93 M5_LOGI("Using Ex_I2C");
94 return Units.add(*unit, M5.Ex_I2C) && Units.begin();
95 }
96
97 bool begin_with_software_i2c(int8_t sda, int8_t scl)
98 {
99 m5::hal::bus::I2CBusConfig i2c_cfg;
100 i2c_cfg.pin_sda = m5::hal::gpio::getPin(sda);
101 i2c_cfg.pin_scl = m5::hal::gpio::getPin(scl);
102 auto i2c_bus = m5::hal::bus::i2c::getBus(i2c_cfg);
103 M5_LOGI("Using M5HAL SDA:%u SCL:%u", sda, scl);
104 return Units.add(*unit, i2c_bus ? i2c_bus.value() : nullptr) && Units.begin();
105 }
106
108 virtual U* get_instance() = 0;
109
110 std::string ustr{};
111 std::unique_ptr<U> unit{};
113};
114
120template <typename U>
121class GPIOComponentTestBase : public ::testing::Test {
122 static_assert(std::is_base_of<m5::unit::Component, U>::value, "U must be derived from Component");
123
124protected:
125 virtual void SetUp() override
126 {
127 unit.reset(get_instance());
128 if (!unit) {
129 FAIL() << "Failed to get_instance";
130 return;
131 }
132 ustr = m5::utility::formatString("%s:GPIO", unit->deviceName());
133 if (!begin()) {
134 FAIL() << "Failed to begin " << ustr;
135 }
136 }
137
138 virtual void TearDown() override
139 {
140 }
141
142 virtual bool begin()
143 {
144 auto pin_num_gpio_in = M5.getPin(m5::pin_name_t::port_b_in);
145 auto pin_num_gpio_out = M5.getPin(m5::pin_name_t::port_b_out);
146 if (pin_num_gpio_in < 0 || pin_num_gpio_out < 0) {
147 M5_LOGW("PortB is not available");
148 Wire.end();
149 pin_num_gpio_in = M5.getPin(m5::pin_name_t::port_a_pin1);
150 pin_num_gpio_out = M5.getPin(m5::pin_name_t::port_a_pin2);
151 }
152 M5_LOGI("getPin: %d,%d", pin_num_gpio_in, pin_num_gpio_out);
153 return Units.add(*unit, pin_num_gpio_in, pin_num_gpio_out) && Units.begin();
154 }
155
157 virtual U* get_instance() = 0;
158
159 std::string ustr{};
160 std::unique_ptr<U> unit{};
162};
163
169template <typename U>
170class UARTComponentTestBase : public ::testing::Test {
171 static_assert(std::is_base_of<m5::unit::Component, U>::value, "U must be derived from Component");
172
173protected:
174 virtual void SetUp() override
175 {
176 unit.reset(get_instance());
177 if (!unit) {
178 FAIL() << "Failed to get_instance";
179 return;
180 }
181 ustr = m5::utility::formatString("%s:UART", unit->deviceName());
182 if (!begin()) {
183 FAIL() << "Failed to begin " << ustr;
184 }
185 }
186
187 virtual void TearDown() override
188 {
189 }
190
191 virtual bool begin()
192 {
193 serial = init_serial();
194 return serial && Units.add(*unit, *serial) && Units.begin();
195 }
196
198 virtual U* get_instance() = 0;
200 virtual HardwareSerial* init_serial() = 0;
201
202 std::string ustr{};
203 std::unique_ptr<U> unit{};
205 HardwareSerial* serial{};
206};
207
213template <typename U>
214class SPIComponentTestBase : public ::testing::Test {
215 static_assert(std::is_base_of<m5::unit::Component, U>::value, "U must be derived from Component");
216
217protected:
218 virtual void SetUp() override
219 {
220 unit.reset(get_instance());
221 if (!unit) {
222 FAIL() << "Failed to get_instance";
223 return;
224 }
225 ustr = m5::utility::formatString("%s:SPI", unit->deviceName());
226 if (!begin()) {
227 FAIL() << "Failed to begin " << ustr;
228 }
229 }
230
231 virtual void TearDown() override
232 {
233 }
234
235 virtual bool begin()
236 {
237 return Units.add(*unit, get_spi(), get_spi_settings()) && Units.begin();
238 }
239
241 virtual U* get_instance() = 0;
243 virtual SPISettings get_spi_settings() = 0;
245 virtual SPIClass& get_spi()
246 {
247 return SPI;
248 }
249
250 std::string ustr{};
251 std::unique_ptr<U> unit{};
253};
254
255} // namespace googletest
256} // namespace unit
257} // namespace m5
258#endif
Main header of M5UnitComponent.
For managing and leading units.
bool begin()
Begin of all units under management.
Definition M5UnitUnified.cpp:169
bool add(Component &u, TwoWire &wire)
Adding unit to be managed (I2C)
Definition M5UnitUnified.cpp:41
UnitComponent derived class for testing (GPIO)
Definition test_template.hpp:121
virtual U * get_instance()=0
return m5::unit::Component-derived class instance
UnitComponent derived class for testing (I2C)
Definition test_template.hpp:39
virtual U * get_instance()=0
return m5::unit::Component-derived class instance
UnitComponent derived class for testing (SPI)
Definition test_template.hpp:214
virtual U * get_instance()=0
return m5::unit::Component-derived class instance
virtual SPIClass & get_spi()
return SPIClass to be used (default: SPI)
Definition test_template.hpp:245
virtual SPISettings get_spi_settings()=0
return SPISettings for the unit under test
UnitComponent derived class for testing (UART)
Definition test_template.hpp:170
virtual HardwareSerial * init_serial()=0
Initialize the serial to be used.
virtual U * get_instance()=0
return m5::unit::Component-derived class instance
For GoogleTest.
Top level namespace of M5stack.
Definition test_helper.hpp:20
Unit-related namespace.