Skip to content

Commit

Permalink
🎨 Use libhal_test_and_make_library
Browse files Browse the repository at this point in the history
- Simplifies building libhal libraries and packages
- By using the standard cmake utilities, upgrades are easily installed
  by bumping the libhal-cmake-util version number
- Utilizes clang-tidy
  • Loading branch information
Khalil Estell authored and kammce committed Oct 1, 2023
1 parent e172e6e commit 3f8f229
Show file tree
Hide file tree
Showing 9 changed files with 65 additions and 143 deletions.
51 changes: 36 additions & 15 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,28 +11,49 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

cmake_minimum_required(VERSION 3.15)

project(libhal-soft VERSION 0.0.1 LANGUAGES CXX)

find_package(libhal REQUIRED CONFIG)
find_package(libhal-util REQUIRED CONFIG)
project(libhal-soft LANGUAGES CXX)

if(NOT BUILD_TESTING STREQUAL OFF)
add_subdirectory(tests)
endif()
libhal_test_and_make_library(
LIBRARY_NAME libhal-soft

add_library(libhal-soft
SOURCES
src/rc_servo.cpp
src/i2c_minimum_speed.cpp
src/adc_mux.cpp)
src/adc_mux.cpp

TEST_SOURCES
tests/inert_drivers/inert_accelerometer.test.cpp
tests/inert_drivers/inert_adc.test.cpp
tests/inert_drivers/inert_dac.test.cpp
tests/inert_drivers/inert_distance_sensor.test.cpp
tests/inert_drivers/inert_gyroscope.test.cpp
tests/inert_drivers/inert_input_pin.test.cpp
tests/inert_drivers/inert_interrupt_pin.test.cpp
tests/inert_drivers/inert_magnetometer.test.cpp
tests/inert_drivers/inert_motor.test.cpp
tests/inert_drivers/inert_pwm.test.cpp
tests/inert_drivers/inert_rotation_sensor.test.cpp
tests/inert_drivers/inert_steady_clock.test.cpp
tests/inert_drivers/inert_temperature_sensor.test.cpp
tests/inert_drivers/inert_timer.test.cpp
tests/adc_mux.test.cpp
tests/i2c_minimum_speed.test.cpp
tests/rc_servo.test.cpp
tests/main.test.cpp

PACKAGES
libhal
libhal-util

target_include_directories(libhal-soft PUBLIC include)
target_compile_features(libhal-soft PRIVATE cxx_std_20)
target_link_libraries(libhal-soft PRIVATE
LINK_LIBRARIES
libhal::libhal
libhal::util
)

install(TARGETS libhal-soft)
TEST_PACKAGES
libhal-mock

TEST_LINK_LIBRARIES
libhal::mock
)
24 changes: 4 additions & 20 deletions conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

class libhal_soft_conan(ConanFile):
name = "libhal-soft"
version = "3.0.1"
version = "3.0.2"
license = "Apache-2.0"
url = "https://github.com/conan-io/conan-center-index"
homepage = "https://libhal.github.io/libhal-soft"
Expand All @@ -48,15 +48,13 @@ def _compilers_minimum_version(self):
"apple-clang": "14.0.0"
}

@property
def _bare_metal(self):
return self.settings.os == "baremetal"

def validate(self):
if self.settings.get_safe("compiler.cppstd"):
check_min_cppstd(self, self._min_cppstd)

def build_requirements(self):
self.tool_requires("cmake/3.27.1")
self.tool_requires("libhal-cmake-util/2.1.1")
self.test_requires("libhal-mock/[^2.0.0]")
self.test_requires("boost-ext-ut/1.1.9")

Expand All @@ -68,24 +66,10 @@ def layout(self):
cmake_layout(self)

def build(self):
run_test = not self.conf.get("tools.build:skip_test", default=False)

cmake = CMake(self)
if self.settings.os == "Windows":
cmake.configure()
elif self._bare_metal:
cmake.configure(variables={
"BUILD_TESTING": "OFF"
})
else:
cmake.configure(variables={"ENABLE_ASAN": True})

cmake.configure()
cmake.build()

if run_test and not self._bare_metal:
test_folder = os.path.join("tests")
self.run(os.path.join(test_folder, "unit_test"))

def package(self):
copy(self,
"LICENSE",
Expand Down
12 changes: 7 additions & 5 deletions include/libhal-soft/rc_servo.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,20 +70,22 @@ class rc_servo : public hal::servo
static result<rc_servo> create(hal::pwm& p_pwm, settings p_settings);

private:
struct ranges
{
std::pair<float, float> percent;
std::pair<float, float> angle;
};
// Constructor is private to only be accessed from the factory function.
// Use p_ prefix for function parameters.
constexpr rc_servo(hal::pwm& p_pwm,
std::pair<float, float> p_percent_range,
std::pair<float, float> p_angle_range);
constexpr rc_servo(hal::pwm& p_pwm, ranges p_ranges);

result<position_t> driver_position(hal::degrees p_position) override;

// Use m_ prefix for private/protected class members.
// Use a pointer here rather than a reference, because member references
// implicitly delete move constructors
hal::pwm* m_pwm;
std::pair<float, float> m_percent_range;
std::pair<float, float> m_angle_range;
ranges m_ranges;
};
// Comment the end of the namespace and end the file with an extra line.
} // namespace hal::soft
2 changes: 1 addition & 1 deletion src/adc_mux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ adc_multiplexer adc_multiplexer::create(
hal::adc& p_source_pin,
hal::steady_clock& p_clock)
{
return adc_multiplexer(p_signal_pins, p_source_pin, p_clock);
return { p_signal_pins, p_source_pin, p_clock };
}

int adc_multiplexer::get_max_channel()
Expand Down
26 changes: 13 additions & 13 deletions src/rc_servo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,14 @@ result<rc_servo> rc_servo::create(hal::pwm& p_pwm, settings p_settings)
// signal. The float is calculated by using the minimum width of the
// signal in microseconds divided by the wavelength to get the decimal
// representation of the float.
auto min_percent = float(p_settings.min_microseconds / wavelength);
auto min_percent =
static_cast<float>(p_settings.min_microseconds) / wavelength;
// max_percent represents the maximum float to be used with the pwm
// signal. The float is calculated by using the maximum width of the
// signal in microseconds divided by the wavelength to get the decimal
// representation of the float.
auto max_percent = float(p_settings.max_microseconds / wavelength);
auto max_percent =
static_cast<float>(p_settings.max_microseconds) / wavelength;
// percent_range holds float value of min_percent and max_percent for use
// with map function used in position().
auto percent_range = std::make_pair(min_percent, max_percent);
Expand All @@ -45,16 +47,14 @@ result<rc_servo> rc_servo::create(hal::pwm& p_pwm, settings p_settings)
auto angle_range = std::make_pair(static_cast<float>(p_settings.min_angle),
static_cast<float>(p_settings.max_angle));
// If no errors happen, call the constructor with verified parameters
return rc_servo(p_pwm, percent_range, angle_range);
return rc_servo(p_pwm,
ranges{ .percent = percent_range, .angle = angle_range });
}

// Use an initializer list to initialize private members.
constexpr rc_servo::rc_servo(hal::pwm& p_pwm,
std::pair<float, float> p_percent_range,
std::pair<float, float> p_angle_range)
constexpr rc_servo::rc_servo(hal::pwm& p_pwm, ranges p_ranges)
: m_pwm(&p_pwm)
, m_percent_range(p_percent_range)
, m_angle_range(p_angle_range)
, m_ranges(std::move(p_ranges))
{
}

Expand All @@ -65,12 +65,12 @@ result<servo::position_t> rc_servo::driver_position(hal::degrees p_position)
// The angle of p_position should be within the min and max angles of the
// servo. If the provided position is out of the provided range, an
// invalid_argument error is thrown.
if (p_position < std::get<0>(m_angle_range) ||
p_position > std::get<1>(m_angle_range)) {
if (p_position < std::get<0>(m_ranges.angle) ||
p_position > std::get<1>(m_ranges.angle)) {
return hal::new_error(std::errc::invalid_argument,
hal::servo::range_error{
.min = std::get<0>(m_angle_range),
.max = std::get<1>(m_angle_range),
.min = std::get<0>(m_ranges.angle),
.max = std::get<1>(m_ranges.angle),
});
}
// The range of p_position should be within the servo's angle range that was
Expand All @@ -89,7 +89,7 @@ result<servo::position_t> rc_servo::driver_position(hal::degrees p_position)
// float(0.15) = position(float(90.0))
// float(0.20) = position(float(135.0))
// float(0.25) = position(float(180.0))
auto scaled_percent_raw = map(p_position, m_angle_range, m_percent_range);
auto scaled_percent_raw = map(p_position, m_ranges.angle, m_ranges.percent);
auto scaled_percent = float(scaled_percent_raw);
// Set the duty cycle of the pwm with the scaled percent.
HAL_CHECK(m_pwm->duty_cycle(scaled_percent));
Expand Down
2 changes: 1 addition & 1 deletion test_package/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ add_executable(${PROJECT_NAME} main.cpp)
target_include_directories(${PROJECT_NAME} PUBLIC .)
target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_20)

if(BAREMETAL)
if(${CMAKE_CROSSCOMPILING})
target_link_options(${PROJECT_NAME} PRIVATE --oslib=semihost)
endif()

Expand Down
6 changes: 1 addition & 5 deletions test_package/conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,6 @@ class TestPackageConan(ConanFile):
settings = "os", "arch", "compiler", "build_type"
generators = "CMakeToolchain", "CMakeDeps", "VirtualRunEnv"

@property
def _bare_metal(self):
return self.settings.os == "baremetal"

def build_requirements(self):
self.tool_requires("cmake/3.27.1")

Expand All @@ -37,7 +33,7 @@ def layout(self):

def build(self):
cmake = CMake(self)
cmake.configure(variables={"BAREMETAL": self._bare_metal})
cmake.configure()
cmake.build()

def test(self):
Expand Down
81 changes: 0 additions & 81 deletions tests/CMakeLists.txt

This file was deleted.

4 changes: 2 additions & 2 deletions tests/i2c_minimum_speed.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ struct fake_i2c : public hal::i2c
spy_transaction;

private:
hal::status driver_configure(const settings& p_settings)
hal::status driver_configure(const settings& p_settings) final
{
return spy_configure.record(p_settings);
}
Expand All @@ -46,7 +46,7 @@ struct fake_i2c : public hal::i2c
[[maybe_unused]] hal::byte p_address,
[[maybe_unused]] std::span<const hal::byte> p_data_out,
[[maybe_unused]] std::span<hal::byte> p_data_in,
[[maybe_unused]] hal::function_ref<hal::timeout_function> p_timeout)
[[maybe_unused]] hal::function_ref<hal::timeout_function> p_timeout) final
{
HAL_CHECK(
spy_transaction.record(p_address, p_data_out, p_data_in, p_timeout));
Expand Down

0 comments on commit 3f8f229

Please sign in to comment.