diff options
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | .gitmodules | 5 | ||||
-rw-r--r-- | main/CMakeLists.txt | 1 | ||||
-rw-r--r-- | readme.md | 20 | ||||
-rw-r--r-- | shared/FSM.cpp | 3 | ||||
-rw-r--r-- | shared/FSM.h | 50 | ||||
-rw-r--r-- | shared/FSM.hpp | 68 | ||||
-rw-r--r-- | shared/IBehaviouralState.hpp | 25 | ||||
-rw-r--r-- | test/.gitignore | 1 | ||||
-rw-r--r-- | test/CMakeLists.txt | 23 | ||||
-rw-r--r-- | test/ExampleTest.cpp | 7 | ||||
m--------- | test/lib/googletest | 0 |
12 files changed, 204 insertions, 1 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0902ca8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +build +.vscode/**
\ No newline at end of file diff --git a/.gitmodules b/.gitmodules index 3711bef..c951407 100644 --- a/.gitmodules +++ b/.gitmodules @@ -3,3 +3,8 @@ url = https://github.com/raspberrypi/pico-sdk branch = 1.5.1 shallow = true +[submodule "test/lib/googletest"] + path = test/lib/googletest + url = https://github.com/google/googletest + branch = v1.14.0 + shallow = true diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 59d1156..e24d9a5 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -20,4 +20,3 @@ pico_enable_stdio_usb(main 1) pico_add_extra_outputs(main) target_include_directories(main PRIVATE ${CMAKE_CURRENT_LIST_DIR}) target_link_libraries(main pico_cyw43_arch_lwip_threadsafe_background pico_stdlib) - @@ -0,0 +1,20 @@ +# puzzle box + +Avans University of Applied Sciences project puzzle box. + +## Tests + +``` +mkdir -p test/build +cd test/build +cmake .. +make +make test +``` + +## ESP +1. Install ESP-IDF extension in vscode +2. Install using 'express' option +3. Install ESP-IDF v5.2.1 (release version) +4. For windows: https://docs.espressif.com/projects/esp-idf/en/stable/esp32/get-started/windows-setup.html#get-started-windows-first-steps +5. For Linux: https://docs.espressif.com/projects/esp-idf/en/stable/esp32/get-started/linux-macos-setup.html#get-started-linux-macos-first-steps diff --git a/shared/FSM.cpp b/shared/FSM.cpp new file mode 100644 index 0000000..fad7fb3 --- /dev/null +++ b/shared/FSM.cpp @@ -0,0 +1,3 @@ +#include "FSM.h" + +#include "IBehaviouralState.hpp"
\ No newline at end of file diff --git a/shared/FSM.h b/shared/FSM.h new file mode 100644 index 0000000..792a44f --- /dev/null +++ b/shared/FSM.h @@ -0,0 +1,50 @@ +#ifndef _FSM_H_ +#define _FSM_H_ + +#include <map> +#include <memory> + +#include "IBehaviouralState.hpp" + +/// <summary> +/// +/// </summary> +/// <typeparam name="TState">IBehaviouralState is the only accepted +/// class.</typeparam> +template <class TState> class FSM { +public: + template <class... TPState> FSM(TPState &...args) { + int i = 0; + + ((void)_states.emplace(i++, args), ...); + } + + /// <summary> + /// Implement with FSM::act() + /// </summary> + void act(); + + /// <summary> + /// Used to check current state. + /// </summary> + /// <returns>Current state.</returns> + std::shared_ptr<TState> &get_state() { return _currentState; } + + /// <summary> + /// Used to get all states. + /// </summary> + /// <returns>Current states.</returns> + std::map<int, std::shared_ptr<TState>> get_states(); + + /// <summary> + /// Sets current state, calls appropiate functions. + /// </summary> + /// <param name="">State to transition into.</param> + void set_state(std::shared_ptr<TState>); + +private: + std::map<int, std::shared_ptr<TState>> _states; + std::shared_ptr<TState> _currentState; +}; + +#endif // _FSM_H_
\ No newline at end of file diff --git a/shared/FSM.hpp b/shared/FSM.hpp new file mode 100644 index 0000000..c86ed80 --- /dev/null +++ b/shared/FSM.hpp @@ -0,0 +1,68 @@ +#ifndef _FSM_HPP_ +#define _FSM_HPP_ + +#include "FSM.h" + +#include <iostream> + +/// <summary> +/// This is a generic update method, unknown classes are not supported. +/// </summary> +/// <typeparam name="TState">IBehaviouralState is the only accepted +/// class.</typeparam> +template <class TState> void FSM<TState>::act() { + // No implementation for unknown class. + std::cout << "No implementation for unknown class" << std::endl; +} +// +///// <summary> +///// Calls the IBehaviouralState act method. +///// </summary> +///// <typeparam name="TState">IBehaviouralState is the only accepted +/// class.</typeparam> +template <> inline void FSM<IBehaviouralState>::act() { _currentState->act(); } + +/// <summary> +/// This is a generic return of the type. +/// </summary> +/// <typeparam name="TState">Any class type works with this return.</typeparam> +/// <returns>The current IBehaviouralState map.</returns> +template <class TState> +std::map<int, std::shared_ptr<TState>> FSM<TState>::get_states() { + return _states; +} + +///// <summary> +///// State transitioning from current state to newState. +///// Calls Exit on the current state and Enter on the new state. +///// </summary> +///// <typeparam name="TState">IBehaviouralState is the only accepted +/// class.</typeparam> +///// <param name="newState">New state to transition into.</param> +template <> +inline void +FSM<IBehaviouralState>::set_state(std::shared_ptr<IBehaviouralState> newState) { + // We can guarantee all statemachines are based on IBehaviouralState + if (_currentState != nullptr) + _currentState->exit(); + + _currentState = nullptr; + _currentState = newState; + _currentState->enter(); +} + +/// <summary> +/// State transitioning from current state to newState. +/// Calls Exit on the current state and Enter on the new state. +/// </summary> +/// <typeparam name="TState">IBehaviouralState is the only accepted +/// class.</typeparam> <param name="newState">New state to transition +/// into.</param> +template <class TState> +void FSM<TState>::set_state(std::shared_ptr<TState> newState) { + // We can guarantee all statemachines are based on IBehaviouralState + // No implementation for an unknown state change class. + std::cout << "No implementation for unknown state change class" << std::endl; +} + +#endif // _FSM_HPP_
\ No newline at end of file diff --git a/shared/IBehaviouralState.hpp b/shared/IBehaviouralState.hpp new file mode 100644 index 0000000..c41fef3 --- /dev/null +++ b/shared/IBehaviouralState.hpp @@ -0,0 +1,25 @@ +#ifndef _FSM_IBEHAVIOURALSTATE_HPP_ +#define _FSM_IBEHAVIOURALSTATE_HPP_ + +/// <summary> +/// Sub class used to define methods implemented by behavioural specific states. +/// </summary> +class IBehaviouralState { +public: + /// <summary> + /// Enters the current state. Used for setup. + /// </summary> + virtual void enter() = 0; + + /// <summary> + /// Updates the current state, used for physics, etc. + /// </summary> + virtual void act() = 0; + + /// <summary> + /// Exits the state, used for cleanup. + /// </summary> + virtual void exit() = 0; +}; + +#endif // _FSM_IBEHAVIOURALSTATE_HPP_
\ No newline at end of file diff --git a/test/.gitignore b/test/.gitignore new file mode 100644 index 0000000..c795b05 --- /dev/null +++ b/test/.gitignore @@ -0,0 +1 @@ +build
\ No newline at end of file diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000..a0bd099 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,23 @@ +cmake_minimum_required(VERSION 3.29) + +project(puzzlebox_test C CXX ASM) + +set(CMAKE_C_STANDARD 11) +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_EXPORT_COMPILE_COMMANDS 1) + +add_executable(tests + ExampleTest.cpp +) + +enable_testing() + +add_subdirectory(lib/googletest) + +target_include_directories(tests PRIVATE ${CMAKE_CURRENT_LIST_DIR}) +target_link_libraries(tests PRIVATE gtest_main) + +add_test( + NAME tests + COMMAND tests +)
\ No newline at end of file diff --git a/test/ExampleTest.cpp b/test/ExampleTest.cpp new file mode 100644 index 0000000..a3909f5 --- /dev/null +++ b/test/ExampleTest.cpp @@ -0,0 +1,7 @@ +#include <gtest/gtest.h> + +class ExampleTest : public testing::Test { +protected: +}; + +TEST_F(ExampleTest, Test) { EXPECT_EQ(5, 5); }
\ No newline at end of file diff --git a/test/lib/googletest b/test/lib/googletest new file mode 160000 +Subproject 5197b1a8e6a1ef9f214f4aa537b0be17cbf9194 |