Compare commits
	
		
			11 Commits
		
	
	
		
			618ddaaa1b
			...
			Phase2
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 10b7dbc19f | |||
| 6867629a7a | |||
| c29ff3776e | |||
| 9b90756e09 | |||
| 852d58b340 | |||
| 818daaa9a0 | |||
| b4d5f8028d | |||
| 6f7ee84ea0 | |||
| d42dcb68b1 | |||
| 211f362e66 | |||
| f079714de5 | 
							
								
								
									
										8
									
								
								.github/workflows/build-test.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								.github/workflows/build-test.yml
									
									
									
									
										vendored
									
									
								
							| @@ -1,6 +1,6 @@ | |||||||
| name: Build test application | name: Build test application | ||||||
| on: | on: | ||||||
|   pull_request: |   push: | ||||||
|  |  | ||||||
| jobs: | jobs: | ||||||
|   build-cli-v1: |   build-cli-v1: | ||||||
| @@ -14,11 +14,9 @@ jobs: | |||||||
|         target: [DISCO_H747I] |         target: [DISCO_H747I] | ||||||
|         profile: [debug] |         profile: [debug] | ||||||
|         tests: [ |         tests: [ | ||||||
|           tests-simple-test-always-succeed, |  | ||||||
|           tests-simple-test-test-ptr, |  | ||||||
|           advdembsof_library-tests-sensors-hdc1000, |  | ||||||
|           tests-bike-computer-sensor-device, |           tests-bike-computer-sensor-device, | ||||||
|           tests-bike-computer-speedometer |           tests-bike-computer-speedometer, | ||||||
|  |           tests-bike-computer-bike-system, | ||||||
|         ] |         ] | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										61
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										61
									
								
								README.md
									
									
									
									
									
								
							| @@ -22,3 +22,64 @@ Test sensor libraries : | |||||||
| ```terminal | ```terminal | ||||||
| mbed test -m DISCO_H747I -t GCC_ARM -n advdembsof_library-tests-sensors-hdc1000 --compile --run | mbed test -m DISCO_H747I -t GCC_ARM -n advdembsof_library-tests-sensors-hdc1000 --compile --run | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
|  | ## Run static scheduling  | ||||||
|  | On `.mbedignore` put at the end of the file | ||||||
|  | ``` | ||||||
|  | static_scheduling_with_event/* | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | On main.cpp include `"static_scheduling/bike_system.hpp"` and use :  | ||||||
|  | ```cpp | ||||||
|  | static_scheduling::BikeSystem bikeSystem; | ||||||
|  | bikeSystem.start(); | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ## Run static scheduling with event queue | ||||||
|  | On `.mbedignore` put at the end of the file :  | ||||||
|  | ``` | ||||||
|  | static_scheduling_with_event/* | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | On main.cpp include `"static_scheduling/bike_system.hpp"` and use :  | ||||||
|  | ```cpp | ||||||
|  | static_scheduling::BikeSystem bikeSystem; | ||||||
|  | bikeSystem.startWithEventQueue(); | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ## Run static scheduling with event scheduling | ||||||
|  | On `.mbedignore` put at the end of the file | ||||||
|  | ``` | ||||||
|  | static_scheduling/* | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | On main.cpp include `"static_scheduling_with_event/bike_system.hpp"` and use :  | ||||||
|  | ```cpp | ||||||
|  | static_scheduling_with_event::BikeSystem bikeSystem; | ||||||
|  | bikeSystem.start(); | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | # Some questions | ||||||
|  | ## Question 1 | ||||||
|  | `If you print CPU statistics at the end of every major cycle (in the super-loop), what CPU usage do you observe? How can you explain the observed CPU uptime?` | ||||||
|  |  | ||||||
|  | We observe a 100% usage because on each CPU cycle it compare if time is done.  | ||||||
|  |  | ||||||
|  | ## Question 2 | ||||||
|  | `If you run the program after the change from busy wait to sleep calls, what CPU usage do you observe? How can you explain the observed CPU uptime?` | ||||||
|  |  | ||||||
|  | We can observe only a usage of 75% because the CPU is more on Idle with Thread sleep. | ||||||
|  |  | ||||||
|  | ## Question 3 | ||||||
|  | `If you run the static_scheduling_with_event program, what CPU usage do you observe? How can you explain the observed CPU uptime?` | ||||||
|  |  | ||||||
|  | We observe a light usage of 1% of CPU. The CPU is now sleeping all the time and doing small task only on event.  | ||||||
|  |  | ||||||
|  | ## Question 4 | ||||||
|  | `When you run multiple tests for computing the response time of the reset event, what do you observe? Is there an improvement as compared to the static_scheduling::BikeSystem implementation?` | ||||||
|  |  | ||||||
|  | `    - If you do not press long enough on the push button, the event may be missed and no reset happens.` | ||||||
|  |  | ||||||
|  | `Based on the program itself and on the task scheduling, explain these two behaviors. Explain also why such behaviors may be problematic.` | ||||||
|  |  | ||||||
|  | We notice, that we miss such less event when is event driven (or not at all). But with a static scheduling the response time is still long because the reset task is call with a certain period.     | ||||||
							
								
								
									
										159
									
								
								TESTS/bike-computer/bike-system/main.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										159
									
								
								TESTS/bike-computer/bike-system/main.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,159 @@ | |||||||
|  | // Copyright 2022 Haute école d'ingénierie et d'architecture de Fribourg | ||||||
|  | // | ||||||
|  | // Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  | // you may not use this file except in compliance with the License. | ||||||
|  | // You may obtain a copy of the License at | ||||||
|  | // | ||||||
|  | //     http://www.apache.org/licenses/LICENSE-2.0 | ||||||
|  | // | ||||||
|  | // Unless required by applicable law or agreed to in writing, software | ||||||
|  | // distributed under the License is distributed on an "AS IS" BASIS, | ||||||
|  | // 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. | ||||||
|  |  | ||||||
|  | /**************************************************************************** | ||||||
|  |  * @file main.cpp | ||||||
|  |  * @author Serge Ayer <serge.ayer@hefr.ch> | ||||||
|  |  * | ||||||
|  |  * @brief Bike computer test suite: scheduling | ||||||
|  |  * | ||||||
|  |  * @date 2023-08-26 | ||||||
|  |  * @version 0.1.0 | ||||||
|  |  ***************************************************************************/ | ||||||
|  |  | ||||||
|  | #include <chrono> | ||||||
|  |  | ||||||
|  | #include "static_scheduling/bike_system.hpp" | ||||||
|  | #include "static_scheduling_with_event/bike_system.hpp" | ||||||
|  |  | ||||||
|  | #include "greentea-client/test_env.h" | ||||||
|  | #include "mbed.h" | ||||||
|  | #include "task_logger.hpp" | ||||||
|  | #include "unity/unity.h" | ||||||
|  | #include "utest/utest.h" | ||||||
|  |  | ||||||
|  | using namespace utest::v1; | ||||||
|  |  | ||||||
|  | // test_bike_system handler function | ||||||
|  | static void test_bike_system() { | ||||||
|  |     // create the BikeSystem instance | ||||||
|  |     static_scheduling::BikeSystem bikeSystem; | ||||||
|  |  | ||||||
|  |     // run the bike system in a separate thread | ||||||
|  |     Thread thread; | ||||||
|  |     thread.start(callback(&bikeSystem, &static_scheduling::BikeSystem::start)); | ||||||
|  |  | ||||||
|  |     // let the bike system run for 20 secs | ||||||
|  |     ThisThread::sleep_for(20s); | ||||||
|  |  | ||||||
|  |     // stop the bike system | ||||||
|  |     bikeSystem.stop(); | ||||||
|  |  | ||||||
|  |     // check whether scheduling was correct | ||||||
|  |     // Order is kGearTaskIndex, kSpeedTaskIndex, kTemperatureTaskIndex, | ||||||
|  |     //          kResetTaskIndex, kDisplayTask1Index, kDisplayTask2Index | ||||||
|  |     constexpr std::chrono::microseconds taskComputationTimes[] = { | ||||||
|  |         100000us, 200000us, 100000us, 100000us, 200000us, 100000us}; | ||||||
|  |     constexpr std::chrono::microseconds taskPeriods[] = { | ||||||
|  |         800000us, 400000us, 1600000us, 800000us, 1600000us, 1600000us}; | ||||||
|  |  | ||||||
|  |     // allow for 2 msecs offset | ||||||
|  |     uint64_t deltaUs = 2000; | ||||||
|  |     for (uint8_t taskIndex = 0; taskIndex < advembsof::TaskLogger::kNbrOfTasks; | ||||||
|  |          taskIndex++) { | ||||||
|  |         TEST_ASSERT_UINT64_WITHIN( | ||||||
|  |             deltaUs, | ||||||
|  |             taskPeriods[taskIndex].count(), | ||||||
|  |             bikeSystem.getTaskLogger().getPeriod(taskIndex).count()); | ||||||
|  |         TEST_ASSERT_UINT64_WITHIN( | ||||||
|  |             deltaUs, | ||||||
|  |             taskComputationTimes[taskIndex].count(), | ||||||
|  |             bikeSystem.getTaskLogger().getComputationTime(taskIndex).count()); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // test_bike_system_event_queue handler function | ||||||
|  | static void test_bike_system_event_queue() { | ||||||
|  |     // create the BikeSystem instance | ||||||
|  |     static_scheduling::BikeSystem bikeSystem; | ||||||
|  |  | ||||||
|  |     // run the bike system in a separate thread | ||||||
|  |     Thread thread; | ||||||
|  |     thread.start(callback(&bikeSystem, &static_scheduling::BikeSystem::startWithEventQueue)); | ||||||
|  |  | ||||||
|  |     // let the bike system run for 20 secs | ||||||
|  |     ThisThread::sleep_for(20s); | ||||||
|  |  | ||||||
|  |     // stop the bike system | ||||||
|  |     bikeSystem.stop(); | ||||||
|  |  | ||||||
|  |     // check whether scheduling was correct | ||||||
|  |     // Order is kGearTaskIndex, kSpeedTaskIndex, kTemperatureTaskIndex, | ||||||
|  |     //          kResetTaskIndex, kDisplayTask1Index, kDisplayTask2Index | ||||||
|  |     // When we use the event queue, we do not check the computation time | ||||||
|  |     constexpr std::chrono::microseconds taskPeriods[] = { | ||||||
|  |         800000us, 400000us, 1600000us, 800000us, 1600000us, 1600000us}; | ||||||
|  |  | ||||||
|  |     // allow for 2 msecs offset (with EventQueue) | ||||||
|  |     uint64_t deltaUs = 2000; | ||||||
|  |     for (uint8_t taskIndex = 0; taskIndex < advembsof::TaskLogger::kNbrOfTasks; | ||||||
|  |          taskIndex++) { | ||||||
|  |         TEST_ASSERT_UINT64_WITHIN( | ||||||
|  |             deltaUs, | ||||||
|  |             taskPeriods[taskIndex].count(), | ||||||
|  |             bikeSystem.getTaskLogger().getPeriod(taskIndex).count()); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // test_bike_system_with_event handler function | ||||||
|  | static void test_bike_system_with_event() { | ||||||
|  |     // create the BikeSystem instance | ||||||
|  |     static_scheduling_with_event::BikeSystem bikeSystem; | ||||||
|  |  | ||||||
|  |     // run the bike system in a separate thread | ||||||
|  |     Thread thread; | ||||||
|  |     thread.start(callback(&bikeSystem, &static_scheduling_with_event::BikeSystem::start)); | ||||||
|  |  | ||||||
|  |     // let the bike system run for 20 secs | ||||||
|  |     ThisThread::sleep_for(20s); | ||||||
|  |  | ||||||
|  |     // stop the bike system | ||||||
|  |     bikeSystem.stop(); | ||||||
|  |  | ||||||
|  |     // check whether scheduling was correct | ||||||
|  |     // Order is kGearTaskIndex, kSpeedTaskIndex, kTemperatureTaskIndex, | ||||||
|  |     //          kResetTaskIndex, kDisplayTask1Index, kDisplayTask2Index | ||||||
|  |     // When we use event handling, we do not check the computation time | ||||||
|  |     constexpr std::chrono::microseconds taskPeriods[] = { | ||||||
|  |         800000us, 400000us, 1600000us, 800000us, 1600000us, 1600000us}; | ||||||
|  |  | ||||||
|  |     // allow for 2 msecs offset (with EventQueue) | ||||||
|  |     uint64_t deltaUs = 2000; | ||||||
|  |     for (uint8_t taskIndex = 0; taskIndex < advembsof::TaskLogger::kNbrOfTasks; | ||||||
|  |          taskIndex++) { | ||||||
|  |         TEST_ASSERT_UINT64_WITHIN( | ||||||
|  |             deltaUs, | ||||||
|  |             taskPeriods[taskIndex].count(), | ||||||
|  |             bikeSystem.getTaskLogger().getPeriod(taskIndex).count()); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static utest::v1::status_t greentea_setup(const size_t number_of_cases) { | ||||||
|  |     // Here, we specify the timeout (60s) and the host test (a built-in host test or the | ||||||
|  |     // name of our Python file) | ||||||
|  |     GREENTEA_SETUP(180, "default_auto"); | ||||||
|  |  | ||||||
|  |     return greentea_test_setup_handler(number_of_cases); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // List of test cases in this file | ||||||
|  | static Case cases[] = { | ||||||
|  |     Case("test bike system", test_bike_system), | ||||||
|  |     Case("test bike system with event queue", test_bike_system_event_queue), | ||||||
|  |     Case("test bike system with event handling", test_bike_system_with_event), | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | static Specification specification(greentea_setup, cases); | ||||||
|  |  | ||||||
|  | int main() { return !Harness::run(specification); } | ||||||
| @@ -51,4 +51,10 @@ static constexpr std::chrono::milliseconds kMaxPedalRotationTime = 1500ms; | |||||||
| // definition of pedal rotation time change upon acceleration/deceleration | // definition of pedal rotation time change upon acceleration/deceleration | ||||||
| static constexpr std::chrono::milliseconds kDeltaPedalRotationTime = 25ms; | static constexpr std::chrono::milliseconds kDeltaPedalRotationTime = 25ms; | ||||||
|  |  | ||||||
|  | static constexpr uint32_t kNbrOfSteps = static_cast<uint32_t>( | ||||||
|  |     ( | ||||||
|  |         bike_computer::kMaxPedalRotationTime - bike_computer::kMinPedalRotationTime | ||||||
|  |     ).count() / bike_computer::kDeltaPedalRotationTime.count() | ||||||
|  | ); | ||||||
|  |  | ||||||
| }  // namespace bike_computer | }  // namespace bike_computer | ||||||
							
								
								
									
										22
									
								
								main.cpp
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								main.cpp
									
									
									
									
									
								
							| @@ -6,19 +6,25 @@ | |||||||
| #if !MBED_TEST_MODE | #if !MBED_TEST_MODE | ||||||
|  |  | ||||||
| #include "mbed.h"  // NOLINT | #include "mbed.h"  // NOLINT | ||||||
|  | #include "mbed_trace.h" | ||||||
|  | //#include "static_scheduling/bike_system.hpp" | ||||||
|  | #include "static_scheduling_with_event/bike_system.hpp" | ||||||
|  |  | ||||||
| // Blinking rate in milliseconds | #if defined(MBED_CONF_MBED_TRACE_ENABLE) | ||||||
| #define BLINKING_RATE 500ms | #define TRACE_GROUP "MAIN" | ||||||
|  | #endif  // MBED_CONF_MBED_TRACE_ENAB | ||||||
|  |  | ||||||
| int main() { | int main() { | ||||||
|     // Initialise the digital pin LED1 as an output | #if defined(MBED_CONF_MBED_TRACE_ENABLE) | ||||||
|  |     mbed_trace_init(); | ||||||
|  | #endif | ||||||
|  |  | ||||||
|     DigitalOut led(LED1); |     //	  static_scheduling::BikeSystem bikeSystem; | ||||||
|  |     //    bikeSystem.start(); | ||||||
|  |     //    bikeSystem.startWithEventQueue(); | ||||||
|  |  | ||||||
|     while (true) { |     static_scheduling_with_event::BikeSystem bikeSystem; | ||||||
|         led = !led; |     bikeSystem.start(); | ||||||
|         ThisThread::sleep_for(BLINKING_RATE); |  | ||||||
|     } |  | ||||||
| } | } | ||||||
|  |  | ||||||
| #endif  // MBED_TEST_MODE | #endif  // MBED_TEST_MODE | ||||||
|   | |||||||
| @@ -14,6 +14,7 @@ | |||||||
|         "platform.stdio-baud-rate": 115200, |         "platform.stdio-baud-rate": 115200, | ||||||
|         "platform.default-serial-baud-rate": 115200, |         "platform.default-serial-baud-rate": 115200, | ||||||
|         "platform.stdio-buffered-serial": true, |         "platform.stdio-buffered-serial": true, | ||||||
|  |         "platform.all-stats-enabled": true, | ||||||
|         "target.printf_lib":"minimal-printf", |         "target.printf_lib":"minimal-printf", | ||||||
|         "platform.minimal-printf-enable-floating-point": true, |         "platform.minimal-printf-enable-floating-point": true, | ||||||
|         "platform.minimal-printf-set-floating-point-max-decimals": 2 |         "platform.minimal-printf-set-floating-point-max-decimals": 2 | ||||||
|   | |||||||
							
								
								
									
										308
									
								
								static_scheduling/bike_system.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										308
									
								
								static_scheduling/bike_system.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,308 @@ | |||||||
|  | // Copyright 2022 Haute école d'ingénierie et d'architecture de Fribourg | ||||||
|  | // | ||||||
|  | // Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  | // you may not use this file except in compliance with the License. | ||||||
|  | // You may obtain a copy of the License at | ||||||
|  | // | ||||||
|  | //     http://www.apache.org/licenses/LICENSE-2.0 | ||||||
|  | // | ||||||
|  | // Unless required by applicable law or agreed to in writing, software | ||||||
|  | // distributed under the License is distributed on an "AS IS" BASIS, | ||||||
|  | // 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. | ||||||
|  |  | ||||||
|  | /**************************************************************************** | ||||||
|  |  * @file bike_system.cpp | ||||||
|  |  * @author Serge Ayer <serge.ayer@hefr.ch> | ||||||
|  |  * @author Rémi Heredero <remi@heredero.ch> | ||||||
|  |  * @author Yann Sierro <yannsierro.pro@gmail.com> | ||||||
|  |  * | ||||||
|  |  * @brief Bike System implementation (static scheduling) | ||||||
|  |  * | ||||||
|  |  * @date 2023-11-15 | ||||||
|  |  * @version 1.1.0 | ||||||
|  |  ***************************************************************************/ | ||||||
|  |  | ||||||
|  | #include "bike_system.hpp" | ||||||
|  |  | ||||||
|  | #include <chrono> | ||||||
|  |  | ||||||
|  | #include "mbed_trace.h" | ||||||
|  | #if MBED_CONF_MBED_TRACE_ENABLE | ||||||
|  | #define TRACE_GROUP "BikeSystem" | ||||||
|  | #endif  // MBED_CONF_MBED_TRACE_ENABLE | ||||||
|  |  | ||||||
|  | namespace static_scheduling { | ||||||
|  |  | ||||||
|  | static constexpr std::chrono::milliseconds kGearTaskPeriod					 = 800ms; | ||||||
|  | static constexpr std::chrono::milliseconds kGearTaskDelay 					 = 0ms; | ||||||
|  | static constexpr std::chrono::milliseconds kGearTaskComputationTime 		 = 100ms; | ||||||
|  | static constexpr std::chrono::milliseconds kSpeedDistanceTaskPeriod 		 = 400ms; | ||||||
|  | static constexpr std::chrono::milliseconds kSpeedDistanceTaskDelay 			 = 0ms; // 0 or 100ms | ||||||
|  | static constexpr std::chrono::milliseconds kSpeedDistanceTaskComputationTime = 200ms; | ||||||
|  | static constexpr std::chrono::milliseconds kDisplayTask1Period 				 = 1600ms; | ||||||
|  | static constexpr std::chrono::milliseconds kDisplayTask1Delay 				 = 300ms; | ||||||
|  | static constexpr std::chrono::milliseconds kDisplayTask1ComputationTime    	 = 200ms; | ||||||
|  | static constexpr std::chrono::milliseconds kResetTaskPeriod 				 = 800ms; | ||||||
|  | static constexpr std::chrono::milliseconds kResetTaskDelay 					 = 700ms; | ||||||
|  | static constexpr std::chrono::milliseconds kResetTaskComputationTime 		 = 100ms; | ||||||
|  | static constexpr std::chrono::milliseconds kTemperatureTaskPeriod 			 = 1600ms; | ||||||
|  | static constexpr std::chrono::milliseconds kTemperatureTaskDelay 			 = 1100ms; | ||||||
|  | static constexpr std::chrono::milliseconds kTemperatureTaskComputationTime	 = 100ms; | ||||||
|  | static constexpr std::chrono::milliseconds kDisplayTask2Period 				 = 1600ms; | ||||||
|  | static constexpr std::chrono::milliseconds kDisplayTask2Delay 				 = 1200ms; | ||||||
|  | static constexpr std::chrono::milliseconds kDisplayTask2ComputationTime   	 = 100ms; | ||||||
|  | static constexpr std::chrono::milliseconds kCPUTaskPeriod 					 = 1600ms; | ||||||
|  | static constexpr std::chrono::milliseconds kCPUTaskDelay 					 = 0ms; | ||||||
|  | static constexpr std::chrono::milliseconds kCPUTaskComputationTime			 = 0ms; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | BikeSystem::BikeSystem() : | ||||||
|  | 	_gearDevice(_timer), | ||||||
|  |     _pedalDevice(_timer), | ||||||
|  |     _resetDevice(_timer), | ||||||
|  | 	_speedometer(_timer), | ||||||
|  |     _cpuLogger(_timer) | ||||||
|  | { | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void BikeSystem::start() { | ||||||
|  |     tr_info("Starting Super-Loop without event handling"); | ||||||
|  |  | ||||||
|  |     init(); | ||||||
|  |  | ||||||
|  |     while (true) { | ||||||
|  |         auto startTime = _timer.elapsed_time(); | ||||||
|  |  | ||||||
|  |         gearTask();				// 100ms :    0ms ->  100ms | ||||||
|  |         speedDistanceTask();	// 200ms :  100ms ->  300ms | ||||||
|  |         displayTask1();			// 200ms :  300ms ->  500ms | ||||||
|  |         speedDistanceTask();    // 200ms :  500ms ->  700ms | ||||||
|  |         resetTask();			// 100ms :  700ms ->  800ms | ||||||
|  |         gearTask();				// 100ms :  800ms ->  900ms | ||||||
|  |         speedDistanceTask();	// 200ms :  900ms -> 1100ms | ||||||
|  |         temperatureTask();		// 100ms : 1100ms -> 1200ms | ||||||
|  |         displayTask2();			// 100ms : 1200ms -> 1300ms | ||||||
|  |         speedDistanceTask();	// 200ms : 1300ms -> 1500ms | ||||||
|  |         resetTask();			// 100ms : 1500ms -> 1600ms | ||||||
|  |          | ||||||
|  |  | ||||||
|  |  | ||||||
|  |         // register the time at the end of the cyclic schedule period and print the | ||||||
|  |         // elapsed time for the period | ||||||
|  |         std::chrono::microseconds endTime = _timer.elapsed_time(); | ||||||
|  |         const auto cycle = | ||||||
|  |             std::chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime); | ||||||
|  |         tr_debug("Repeating cycle time is %" PRIu64 " milliseconds", cycle.count()); | ||||||
|  |  | ||||||
|  |         // TODO: implement loop exit when applicable | ||||||
|  |         // Done | ||||||
|  |         bool fStop = false; | ||||||
|  |         core_util_atomic_load(&fStop); | ||||||
|  |         if (fStop) { | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         #if !defined(MBED_TEST_MODE) | ||||||
|  |         	_cpuLogger.printStats(); | ||||||
|  |         #endif | ||||||
|  |  | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void BikeSystem::startWithEventQueue() { | ||||||
|  |  | ||||||
|  |     tr_info("Starting Super-Loop with event handling"); | ||||||
|  |  | ||||||
|  |     init(); | ||||||
|  |  | ||||||
|  |     EventQueue eventQueue; | ||||||
|  |  | ||||||
|  | 	Event<void()> gearEvent(&eventQueue, callback(this, &BikeSystem::gearTask)); | ||||||
|  | 	gearEvent.delay(kGearTaskDelay); | ||||||
|  | 	gearEvent.period(kGearTaskPeriod); | ||||||
|  | 	gearEvent.post(); | ||||||
|  |  | ||||||
|  |     Event<void()> speedDistanceEvent(&eventQueue, callback(this, &BikeSystem::speedDistanceTask)); | ||||||
|  |     speedDistanceEvent.delay(kSpeedDistanceTaskDelay); | ||||||
|  |     speedDistanceEvent.period(kSpeedDistanceTaskPeriod); | ||||||
|  |     speedDistanceEvent.post(); | ||||||
|  |  | ||||||
|  |     Event<void()> display1Event(&eventQueue, callback(this, &BikeSystem::displayTask1)); | ||||||
|  |     display1Event.delay(kDisplayTask1Delay); | ||||||
|  |     display1Event.period(kDisplayTask1Period); | ||||||
|  |     display1Event.post(); | ||||||
|  |  | ||||||
|  |     Event<void()> resetEvent(&eventQueue, callback(this, &BikeSystem::resetTask)); | ||||||
|  |     resetEvent.delay(kResetTaskDelay); | ||||||
|  |     resetEvent.period(kResetTaskPeriod); | ||||||
|  |     resetEvent.post(); | ||||||
|  |  | ||||||
|  |     Event<void()> temperatureEvent(&eventQueue, callback(this, &BikeSystem::temperatureTask)); | ||||||
|  |     temperatureEvent.delay(kTemperatureTaskDelay); | ||||||
|  |     temperatureEvent.period(kTemperatureTaskPeriod); | ||||||
|  |     temperatureEvent.post(); | ||||||
|  |  | ||||||
|  |     Event<void()> display2Event(&eventQueue, callback(this, &BikeSystem::displayTask2)); | ||||||
|  |     display2Event.delay(kDisplayTask2Delay); | ||||||
|  |     display2Event.period(kDisplayTask2Period); | ||||||
|  |     display2Event.post(); | ||||||
|  |  | ||||||
|  | 	#if !defined(MBED_TEST_MODE) | ||||||
|  |   		Event<void()> cpuEvent(&eventQueue, callback(this, &BikeSystem::cpuTask)); | ||||||
|  |   		cpuEvent.delay(kCPUTaskDelay); | ||||||
|  |   		cpuEvent.period(kCPUTaskPeriod); | ||||||
|  |   		cpuEvent.post(); | ||||||
|  | 	#endif | ||||||
|  |      | ||||||
|  | 	eventQueue.dispatch_forever(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void BikeSystem::stop() { core_util_atomic_store_bool(&_stopFlag, true); } | ||||||
|  |  | ||||||
|  | #if defined(MBED_TEST_MODE) | ||||||
|  | const advembsof::TaskLogger& BikeSystem::getTaskLogger() { return _taskLogger; } | ||||||
|  | #endif  // defined(MBED_TEST_MODE) | ||||||
|  |  | ||||||
|  | void BikeSystem::init() { | ||||||
|  |     // start the timer | ||||||
|  |     _timer.start(); | ||||||
|  |  | ||||||
|  |     // initialize the lcd display | ||||||
|  |     disco::ReturnCode rc = _displayDevice.init(); | ||||||
|  |     if (rc != disco::ReturnCode::Ok) { | ||||||
|  |         tr_error("Failed to initialized the lcd display: %d", static_cast<int>(rc)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // initialize the sensor device | ||||||
|  |     bool present = _sensorDevice.init(); | ||||||
|  |     if (!present) { | ||||||
|  |         tr_error("Sensor not present or initialization failed"); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // enable/disable task logging | ||||||
|  |     _taskLogger.enable(true); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void BikeSystem::gearTask() { | ||||||
|  |     // gear task | ||||||
|  |     auto taskStartTime = _timer.elapsed_time(); | ||||||
|  |  | ||||||
|  |     // no need to protect access to data members (single threaded) | ||||||
|  |     _currentGear     = _gearDevice.getCurrentGear(); | ||||||
|  |     _currentGearSize = _gearDevice.getCurrentGearSize(); | ||||||
|  |  | ||||||
|  |     _taskLogger.logPeriodAndExecutionTime( | ||||||
|  |         _timer, advembsof::TaskLogger::kGearTaskIndex, taskStartTime | ||||||
|  |     ); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void BikeSystem::speedDistanceTask() { | ||||||
|  |     // speed and distance task | ||||||
|  |     auto taskStartTime = _timer.elapsed_time(); | ||||||
|  |  | ||||||
|  |     const auto pedalRotationTime = _pedalDevice.getCurrentRotationTime(); | ||||||
|  |     _speedometer.setCurrentRotationTime(pedalRotationTime); | ||||||
|  |     _speedometer.setGearSize(_currentGearSize); | ||||||
|  |     // no need to protect access to data members (single threaded) | ||||||
|  |     _currentSpeed    = _speedometer.getCurrentSpeed(); | ||||||
|  |     _traveledDistance = _speedometer.getDistance(); | ||||||
|  |  | ||||||
|  |     _taskLogger.logPeriodAndExecutionTime( | ||||||
|  |         _timer, advembsof::TaskLogger::kSpeedTaskIndex, taskStartTime | ||||||
|  |     ); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void BikeSystem::temperatureTask() { | ||||||
|  |     auto taskStartTime = _timer.elapsed_time(); | ||||||
|  |  | ||||||
|  |     tr_warn("Tick1 %" PRIu64, _timer.elapsed_time().count()); | ||||||
|  |  | ||||||
|  |     // no need to protect access to data members (single threaded) | ||||||
|  |     _currentTemperature = _sensorDevice.readTemperature(); | ||||||
|  |  | ||||||
|  |     tr_warn("Tick2 %" PRIu64, _timer.elapsed_time().count()); | ||||||
|  |  | ||||||
|  |     ThisThread::sleep_for( | ||||||
|  |         std::chrono::duration_cast<std::chrono::milliseconds>( | ||||||
|  |             kTemperatureTaskComputationTime - (_timer.elapsed_time() - taskStartTime) | ||||||
|  |         ) | ||||||
|  |     ); | ||||||
|  |  | ||||||
|  |     // simulate task computation by waiting for the required task computation time | ||||||
|  |  | ||||||
|  | //    std::chrono::microseconds elapsedTime = std::chrono::microseconds::zero(); | ||||||
|  | //    while (elapsedTime < kTemperatureTaskComputationTime) { | ||||||
|  | //        elapsedTime = _timer.elapsed_time() - taskStartTime; | ||||||
|  | //    } | ||||||
|  |  | ||||||
|  |     _taskLogger.logPeriodAndExecutionTime( | ||||||
|  |         _timer, advembsof::TaskLogger::kTemperatureTaskIndex, taskStartTime); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void BikeSystem::resetTask() { | ||||||
|  |     auto taskStartTime = _timer.elapsed_time(); | ||||||
|  |  | ||||||
|  |     if (_resetDevice.checkReset()) { | ||||||
|  |         std::chrono::microseconds responseTime = | ||||||
|  |             _timer.elapsed_time() - _resetDevice.getPressTime(); | ||||||
|  |         tr_info("Reset task: response time is %" PRIu64 " usecs", responseTime.count()); | ||||||
|  |         _speedometer.reset(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     _taskLogger.logPeriodAndExecutionTime( | ||||||
|  |         _timer, advembsof::TaskLogger::kResetTaskIndex, taskStartTime); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void BikeSystem::displayTask1() { | ||||||
|  |     auto taskStartTime = _timer.elapsed_time(); | ||||||
|  |  | ||||||
|  |     _displayDevice.displayGear(_currentGear); | ||||||
|  |     _displayDevice.displaySpeed(_currentSpeed); | ||||||
|  |     _displayDevice.displayDistance(_traveledDistance); | ||||||
|  |  | ||||||
|  |     ThisThread::sleep_for( | ||||||
|  |         std::chrono::duration_cast<std::chrono::milliseconds>( | ||||||
|  |             kDisplayTask1ComputationTime - (_timer.elapsed_time() - taskStartTime) | ||||||
|  |         ) | ||||||
|  |     ); | ||||||
|  |  | ||||||
|  |     // simulate task computation by waiting for the required task computation time | ||||||
|  |  | ||||||
|  | //    std::chrono::microseconds elapsedTime = std::chrono::microseconds::zero(); | ||||||
|  | //    while (elapsedTime < kDisplayTask1ComputationTime) { | ||||||
|  | //        elapsedTime = _timer.elapsed_time() - taskStartTime; | ||||||
|  | //    } | ||||||
|  |  | ||||||
|  |     _taskLogger.logPeriodAndExecutionTime( | ||||||
|  |         _timer, advembsof::TaskLogger::kDisplayTask1Index, taskStartTime); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void BikeSystem::displayTask2() { | ||||||
|  |     auto taskStartTime = _timer.elapsed_time(); | ||||||
|  |  | ||||||
|  |     _displayDevice.displayTemperature(_currentTemperature); | ||||||
|  |  | ||||||
|  |     ThisThread::sleep_for( | ||||||
|  |         std::chrono::duration_cast<std::chrono::milliseconds>( | ||||||
|  |             kDisplayTask2ComputationTime - (_timer.elapsed_time() - taskStartTime) | ||||||
|  |         ) | ||||||
|  |     ); | ||||||
|  |  | ||||||
|  |     // simulate task computation by waiting for the required task computation time | ||||||
|  |  | ||||||
|  | //    std::chrono::microseconds elapsedTime = std::chrono::microseconds::zero(); | ||||||
|  | //    while (elapsedTime < kDisplayTask2ComputationTime) { | ||||||
|  | //        elapsedTime = _timer.elapsed_time() - taskStartTime; | ||||||
|  | //    } | ||||||
|  |     _taskLogger.logPeriodAndExecutionTime( | ||||||
|  |         _timer, advembsof::TaskLogger::kDisplayTask2Index, taskStartTime); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void BikeSystem::cpuTask() { | ||||||
|  |     _cpuLogger.printStats(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | }  // namespace static_scheduling | ||||||
							
								
								
									
										106
									
								
								static_scheduling/bike_system.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										106
									
								
								static_scheduling/bike_system.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,106 @@ | |||||||
|  | // Copyright 2022 Haute école d'ingénierie et d'architecture de Fribourg | ||||||
|  | // | ||||||
|  | // Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  | // you may not use this file except in compliance with the License. | ||||||
|  | // You may obtain a copy of the License at | ||||||
|  | // | ||||||
|  | //     http://www.apache.org/licenses/LICENSE-2.0 | ||||||
|  | // | ||||||
|  | // Unless required by applicable law or agreed to in writing, software | ||||||
|  | // distributed under the License is distributed on an "AS IS" BASIS, | ||||||
|  | // 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. | ||||||
|  |  | ||||||
|  | /**************************************************************************** | ||||||
|  |  * @file bike_system.hpp | ||||||
|  |  * @author Serge Ayer <serge.ayer@hefr.ch> | ||||||
|  |  * | ||||||
|  |  * @brief Bike System header file (static scheduling) | ||||||
|  |  * | ||||||
|  |  * @date 2023-08-20 | ||||||
|  |  * @version 1.0.0 | ||||||
|  |  ***************************************************************************/ | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | // from advembsof | ||||||
|  | #include "display_device.hpp" | ||||||
|  | #include "task_logger.hpp" | ||||||
|  | #include "cpu_logger.hpp" | ||||||
|  |  | ||||||
|  | // from common | ||||||
|  | #include "sensor_device.hpp" | ||||||
|  | #include "speedometer.hpp" | ||||||
|  |  | ||||||
|  | // local | ||||||
|  | #include "gear_device.hpp" | ||||||
|  | #include "pedal_device.hpp" | ||||||
|  | #include "reset_device.hpp" | ||||||
|  |  | ||||||
|  | namespace static_scheduling { | ||||||
|  |  | ||||||
|  | class BikeSystem { | ||||||
|  |    public: | ||||||
|  |     // constructor | ||||||
|  |     BikeSystem(); | ||||||
|  |  | ||||||
|  |     // make the class non copyable | ||||||
|  |     BikeSystem(BikeSystem&)            = delete; | ||||||
|  |     BikeSystem& operator=(BikeSystem&) = delete; | ||||||
|  |  | ||||||
|  |     // method called in main() for starting the system | ||||||
|  |     void start(); | ||||||
|  |  | ||||||
|  |     // method called in main() for starting the sysytem with the event queue | ||||||
|  |     void startWithEventQueue(); | ||||||
|  |  | ||||||
|  |     // method called for stopping the system | ||||||
|  |     void stop(); | ||||||
|  |  | ||||||
|  | #if defined(MBED_TEST_MODE) | ||||||
|  |     const advembsof::TaskLogger& getTaskLogger(); | ||||||
|  | #endif  // defined(MBED_TEST_MODE) | ||||||
|  |  | ||||||
|  |    private: | ||||||
|  |     // private methods | ||||||
|  |     void init(); | ||||||
|  |     void gearTask(); | ||||||
|  |     void speedDistanceTask(); | ||||||
|  |     void temperatureTask(); | ||||||
|  |     void resetTask(); | ||||||
|  |     void displayTask1(); | ||||||
|  |     void displayTask2(); | ||||||
|  |     void cpuTask(); | ||||||
|  |  | ||||||
|  |     // stop flag, used for stopping the super-loop (set in stop()) | ||||||
|  |     bool _stopFlag = false; | ||||||
|  |     // timer instance used for loggint task time and used by ResetDevice | ||||||
|  |     Timer _timer; | ||||||
|  |     // data member that represents the device for manipulating the gear | ||||||
|  |     GearDevice _gearDevice; | ||||||
|  |     uint8_t _currentGear = bike_computer::kMinGear; | ||||||
|  |     uint8_t _currentGearSize = bike_computer::kMinGearSize; | ||||||
|  |     // data member that represents the device for manipulating the pedal rotation | ||||||
|  |     // speed/time | ||||||
|  |     PedalDevice _pedalDevice; | ||||||
|  |     float _currentSpeed = 0.0f; | ||||||
|  |     float _traveledDistance = 0.0f; | ||||||
|  |     // data member that represents the device used for resetting | ||||||
|  |     ResetDevice _resetDevice; | ||||||
|  |     // data member that represents the device display | ||||||
|  |     advembsof::DisplayDevice _displayDevice; | ||||||
|  |     // data member that represents the device for counting wheel rotations | ||||||
|  |     bike_computer::Speedometer _speedometer; | ||||||
|  |     // data member that represents the sensor device | ||||||
|  |     bike_computer::SensorDevice _sensorDevice; | ||||||
|  |     float _currentTemperature = 0.0f; | ||||||
|  |  | ||||||
|  |     // used for logging task info | ||||||
|  |     advembsof::TaskLogger _taskLogger; | ||||||
|  |  | ||||||
|  |     // cpu logger to measure cpu usage | ||||||
|  |     advembsof::CPULogger _cpuLogger; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | }  // namespace static_scheduling | ||||||
| @@ -23,12 +23,12 @@ static constexpr uint8_t kPolarityPressed = 1; | |||||||
|  |  | ||||||
|  |  | ||||||
| #if MBED_CONF_MBED_TRACE_ENABLE | #if MBED_CONF_MBED_TRACE_ENABLE | ||||||
| #define TRACE_GROUP "PedalDevice" | #define TRACE_GROUP "ResetDevice" | ||||||
| #endif  // MBED_CONF_MBED_TRACE_ENABLE | #endif  // MBED_CONF_MBED_TRACE_ENABLE | ||||||
|  |  | ||||||
| namespace static_scheduling { | namespace static_scheduling { | ||||||
|  |  | ||||||
| 	static constexpr std::chrono::microseconds kTaskRunTime = 1000000us; | 	static constexpr std::chrono::microseconds kTaskRunTime = 100000us; | ||||||
|  |  | ||||||
| 	ResetDevice::ResetDevice(Timer& timer) : _timer(timer), _resetButton(PUSH_BUTTON) { | 	ResetDevice::ResetDevice(Timer& timer) : _timer(timer), _resetButton(PUSH_BUTTON) { | ||||||
|     	_resetButton.rise(callback(this, &ResetDevice::onRise)); |     	_resetButton.rise(callback(this, &ResetDevice::onRise)); | ||||||
|   | |||||||
							
								
								
									
										255
									
								
								static_scheduling_with_event/bike_system.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										255
									
								
								static_scheduling_with_event/bike_system.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,255 @@ | |||||||
|  | // Copyright 2022 Haute école d'ingénierie et d'architecture de Fribourg | ||||||
|  | // | ||||||
|  | // Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  | // you may not use this file except in compliance with the License. | ||||||
|  | // You may obtain a copy of the License at | ||||||
|  | // | ||||||
|  | //     http://www.apache.org/licenses/LICENSE-2.0 | ||||||
|  | // | ||||||
|  | // Unless required by applicable law or agreed to in writing, software | ||||||
|  | // distributed under the License is distributed on an "AS IS" BASIS, | ||||||
|  | // 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. | ||||||
|  |  | ||||||
|  | /**************************************************************************** | ||||||
|  |  * @file bike_system.cpp | ||||||
|  |  * @author Serge Ayer <serge.ayer@hefr.ch> | ||||||
|  |  * @author Rémi Heredero <remi@heredero.ch> | ||||||
|  |  * @author Yann Sierro <yannsierro.pro@gmail.com> | ||||||
|  |  * | ||||||
|  |  * @brief Bike System implementation (static scheduling) | ||||||
|  |  * | ||||||
|  |  * @date 2023-11-15 | ||||||
|  |  * @version 1.1.0 | ||||||
|  |  ***************************************************************************/ | ||||||
|  |  | ||||||
|  | #include "bike_system.hpp" | ||||||
|  |  | ||||||
|  | #include <chrono> | ||||||
|  |  | ||||||
|  | #include "mbed_trace.h" | ||||||
|  | #if MBED_CONF_MBED_TRACE_ENABLE | ||||||
|  | #define TRACE_GROUP "BikeSystem" | ||||||
|  | #endif  // MBED_CONF_MBED_TRACE_ENABLE | ||||||
|  |  | ||||||
|  | namespace static_scheduling_with_event { | ||||||
|  |  | ||||||
|  | static constexpr std::chrono::milliseconds kGearTaskPeriod					 =  800ms; | ||||||
|  | static constexpr std::chrono::milliseconds kGearTaskDelay 					 =    0ms; | ||||||
|  | static constexpr std::chrono::milliseconds kGearTaskComputationTime 		 =  100ms; | ||||||
|  |  | ||||||
|  | static constexpr std::chrono::milliseconds kSpeedDistanceTaskPeriod 		 =  400ms; | ||||||
|  | static constexpr std::chrono::milliseconds kSpeedDistanceTaskDelay 			 =  100ms; | ||||||
|  | static constexpr std::chrono::milliseconds kSpeedDistanceTaskComputationTime =  200ms; | ||||||
|  |  | ||||||
|  | static constexpr std::chrono::milliseconds kDisplayTask1Period 				 = 1600ms; | ||||||
|  | static constexpr std::chrono::milliseconds kDisplayTask1Delay 				 =  300ms; | ||||||
|  | static constexpr std::chrono::milliseconds kDisplayTask1ComputationTime    	 =  200ms; | ||||||
|  |  | ||||||
|  | static constexpr std::chrono::milliseconds kResetTaskPeriod 				 =  800ms; | ||||||
|  | static constexpr std::chrono::milliseconds kResetTaskDelay 					 =  700ms; | ||||||
|  | static constexpr std::chrono::milliseconds kResetTaskComputationTime 		 =  100ms; | ||||||
|  |  | ||||||
|  | static constexpr std::chrono::milliseconds kTemperatureTaskPeriod 			 = 1600ms; | ||||||
|  | static constexpr std::chrono::milliseconds kTemperatureTaskDelay 			 = 1100ms; | ||||||
|  | static constexpr std::chrono::milliseconds kTemperatureTaskComputationTime	 =  100ms; | ||||||
|  |  | ||||||
|  | static constexpr std::chrono::milliseconds kDisplayTask2Period 				 = 1600ms; | ||||||
|  | static constexpr std::chrono::milliseconds kDisplayTask2Delay 				 = 1200ms; | ||||||
|  | static constexpr std::chrono::milliseconds kDisplayTask2ComputationTime   	 =  100ms; | ||||||
|  |  | ||||||
|  | static constexpr std::chrono::milliseconds kCPUTaskPeriod 					 = 1600ms; | ||||||
|  | static constexpr std::chrono::milliseconds kCPUTaskDelay 					 = 1200ms; | ||||||
|  | static constexpr std::chrono::milliseconds kCPUTaskComputationTime			 =  100ms; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | BikeSystem::BikeSystem() : | ||||||
|  | 	_gearDevice(), | ||||||
|  |     _pedalDevice(), | ||||||
|  |     _resetDevice(callback(this, &BikeSystem::onReset)), | ||||||
|  | 	_speedometer(_timer), | ||||||
|  |     _cpuLogger(_timer) | ||||||
|  | { | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void BikeSystem::start() { | ||||||
|  |  | ||||||
|  |     tr_info("Starting Super-Loop with event handling"); | ||||||
|  |  | ||||||
|  |     init(); | ||||||
|  |  | ||||||
|  |     EventQueue eventQueue; | ||||||
|  |  | ||||||
|  | 	Event<void()> gearEvent(&eventQueue, callback(this, &BikeSystem::gearTask)); | ||||||
|  | 	gearEvent.delay(kGearTaskDelay); | ||||||
|  | 	gearEvent.period(kGearTaskPeriod); | ||||||
|  | 	gearEvent.post(); | ||||||
|  |  | ||||||
|  |     Event<void()> speedDistanceEvent(&eventQueue, callback(this, &BikeSystem::speedDistanceTask)); | ||||||
|  |     speedDistanceEvent.delay(kSpeedDistanceTaskDelay); | ||||||
|  |     speedDistanceEvent.period(kSpeedDistanceTaskPeriod); | ||||||
|  |     speedDistanceEvent.post(); | ||||||
|  |  | ||||||
|  |     Event<void()> display1Event(&eventQueue, callback(this, &BikeSystem::displayTask1)); | ||||||
|  |     display1Event.delay(kDisplayTask1Delay); | ||||||
|  |     display1Event.period(kDisplayTask1Period); | ||||||
|  |     display1Event.post(); | ||||||
|  |  | ||||||
|  |     Event<void()> resetEvent(&eventQueue, callback(this, &BikeSystem::resetTask)); | ||||||
|  |     resetEvent.delay(kResetTaskDelay); | ||||||
|  |     resetEvent.period(kResetTaskPeriod); | ||||||
|  |     resetEvent.post(); | ||||||
|  |  | ||||||
|  |     Event<void()> temperatureEvent(&eventQueue, callback(this, &BikeSystem::temperatureTask)); | ||||||
|  |     temperatureEvent.delay(kTemperatureTaskDelay); | ||||||
|  |     temperatureEvent.period(kTemperatureTaskPeriod); | ||||||
|  |     temperatureEvent.post(); | ||||||
|  |  | ||||||
|  |     Event<void()> display2Event(&eventQueue, callback(this, &BikeSystem::displayTask2)); | ||||||
|  |     display2Event.delay(kDisplayTask2Delay); | ||||||
|  |     display2Event.period(kDisplayTask2Period); | ||||||
|  |     display2Event.post(); | ||||||
|  |  | ||||||
|  | 	#if !defined(MBED_TEST_MODE) | ||||||
|  |   		Event<void()> cpuEvent(&eventQueue, callback(this, &BikeSystem::cpuTask)); | ||||||
|  |   		cpuEvent.delay(kCPUTaskDelay); | ||||||
|  |   		cpuEvent.period(kCPUTaskPeriod); | ||||||
|  |   		cpuEvent.post(); | ||||||
|  | 	#endif | ||||||
|  |      | ||||||
|  | 	eventQueue.dispatch_forever(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void BikeSystem::onReset() { | ||||||
|  |     _resetTime = _timer.elapsed_time(); | ||||||
|  |     core_util_atomic_store_bool(&_resetFlag, true); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void BikeSystem::stop() { core_util_atomic_store_bool(&_stopFlag, true); } | ||||||
|  |  | ||||||
|  | #if defined(MBED_TEST_MODE) | ||||||
|  | const advembsof::TaskLogger& BikeSystem::getTaskLogger() { return _taskLogger; } | ||||||
|  | #endif  // defined(MBED_TEST_MODE) | ||||||
|  |  | ||||||
|  | void BikeSystem::init() { | ||||||
|  |     // start the timer | ||||||
|  |     _timer.start(); | ||||||
|  |  | ||||||
|  |     // initialize the lcd display | ||||||
|  |     disco::ReturnCode rc = _displayDevice.init(); | ||||||
|  |     if (rc != disco::ReturnCode::Ok) { | ||||||
|  |         tr_error("Failed to initialized the lcd display: %d", static_cast<int>(rc)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // initialize the sensor device | ||||||
|  |     bool present = _sensorDevice.init(); | ||||||
|  |     if (!present) { | ||||||
|  |         tr_error("Sensor not present or initialization failed"); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // enable/disable task logging | ||||||
|  |     _taskLogger.enable(true); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void BikeSystem::gearTask() { | ||||||
|  |     // gear task | ||||||
|  |     auto taskStartTime = _timer.elapsed_time(); | ||||||
|  |  | ||||||
|  |     // no need to protect access to data members (single threaded) | ||||||
|  |     _currentGear     = _gearDevice.getCurrentGear(); | ||||||
|  |     _currentGearSize = _gearDevice.getCurrentGearSize(); | ||||||
|  |  | ||||||
|  |     _taskLogger.logPeriodAndExecutionTime( | ||||||
|  |         _timer, advembsof::TaskLogger::kGearTaskIndex, taskStartTime | ||||||
|  |     ); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void BikeSystem::speedDistanceTask() { | ||||||
|  |     auto taskStartTime = _timer.elapsed_time(); | ||||||
|  |  | ||||||
|  |     const auto pedalRotationTime = _pedalDevice.getCurrentRotationTime(); | ||||||
|  |     _speedometer.setCurrentRotationTime(pedalRotationTime); | ||||||
|  |     _speedometer.setGearSize(_currentGearSize); | ||||||
|  |  | ||||||
|  |     _currentSpeed    = _speedometer.getCurrentSpeed(); | ||||||
|  |     _traveledDistance = _speedometer.getDistance(); | ||||||
|  |  | ||||||
|  |     _taskLogger.logPeriodAndExecutionTime( | ||||||
|  |         _timer, advembsof::TaskLogger::kSpeedTaskIndex, taskStartTime | ||||||
|  |     ); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void BikeSystem::temperatureTask() { | ||||||
|  |     auto taskStartTime = _timer.elapsed_time(); | ||||||
|  |  | ||||||
|  |     //tr_warn("Tick1 %" PRIu64, _timer.elapsed_time().count()); | ||||||
|  |  | ||||||
|  |     // no need to protect access to data members (single threaded) | ||||||
|  |     _currentTemperature = _sensorDevice.readTemperature(); | ||||||
|  |  | ||||||
|  |     //tr_warn("Tick2 %" PRIu64, _timer.elapsed_time().count()); | ||||||
|  |  | ||||||
|  |     ThisThread::sleep_for( | ||||||
|  |         std::chrono::duration_cast<std::chrono::milliseconds>( | ||||||
|  |             kTemperatureTaskComputationTime - (_timer.elapsed_time() - taskStartTime) | ||||||
|  |         ) | ||||||
|  |     ); | ||||||
|  |  | ||||||
|  |     _taskLogger.logPeriodAndExecutionTime( | ||||||
|  |         _timer, advembsof::TaskLogger::kTemperatureTaskIndex, taskStartTime); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void BikeSystem::resetTask() { | ||||||
|  |     auto taskStartTime = _timer.elapsed_time(); | ||||||
|  |  | ||||||
|  |     if (core_util_atomic_load_bool(&_resetFlag)) { | ||||||
|  |         std::chrono::microseconds responseTime = _timer.elapsed_time() - _resetTime; | ||||||
|  |         tr_info("Reset task: response time is %" PRIu64 " usecs", responseTime.count()); | ||||||
|  |         _speedometer.reset(); | ||||||
|  |  | ||||||
|  |         core_util_atomic_store_bool(&_resetFlag, false); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     _taskLogger.logPeriodAndExecutionTime( | ||||||
|  |         _timer, advembsof::TaskLogger::kResetTaskIndex, taskStartTime); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void BikeSystem::displayTask1() { | ||||||
|  |     auto taskStartTime = _timer.elapsed_time(); | ||||||
|  |  | ||||||
|  |     _displayDevice.displayGear(_currentGear); | ||||||
|  |     _displayDevice.displaySpeed(_currentSpeed); | ||||||
|  |     _displayDevice.displayDistance(_traveledDistance); | ||||||
|  |  | ||||||
|  |     ThisThread::sleep_for( | ||||||
|  |         std::chrono::duration_cast<std::chrono::milliseconds>( | ||||||
|  |             kDisplayTask1ComputationTime - (_timer.elapsed_time() - taskStartTime) | ||||||
|  |         ) | ||||||
|  |     ); | ||||||
|  |  | ||||||
|  |     _taskLogger.logPeriodAndExecutionTime( | ||||||
|  |         _timer, advembsof::TaskLogger::kDisplayTask1Index, taskStartTime); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void BikeSystem::displayTask2() { | ||||||
|  |     auto taskStartTime = _timer.elapsed_time(); | ||||||
|  |  | ||||||
|  |     _displayDevice.displayTemperature(_currentTemperature); | ||||||
|  |  | ||||||
|  |     ThisThread::sleep_for( | ||||||
|  |         std::chrono::duration_cast<std::chrono::milliseconds>( | ||||||
|  |             kDisplayTask2ComputationTime - (_timer.elapsed_time() - taskStartTime) | ||||||
|  |         ) | ||||||
|  |     ); | ||||||
|  |  | ||||||
|  |     _taskLogger.logPeriodAndExecutionTime( | ||||||
|  |         _timer, advembsof::TaskLogger::kDisplayTask2Index, taskStartTime); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void BikeSystem::cpuTask() { | ||||||
|  |     _cpuLogger.printStats(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | }  // namespace static_scheduling | ||||||
							
								
								
									
										111
									
								
								static_scheduling_with_event/bike_system.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								static_scheduling_with_event/bike_system.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,111 @@ | |||||||
|  | // Copyright 2022 Haute école d'ingénierie et d'architecture de Fribourg | ||||||
|  | // | ||||||
|  | // Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  | // you may not use this file except in compliance with the License. | ||||||
|  | // You may obtain a copy of the License at | ||||||
|  | // | ||||||
|  | //     http://www.apache.org/licenses/LICENSE-2.0 | ||||||
|  | // | ||||||
|  | // Unless required by applicable law or agreed to in writing, software | ||||||
|  | // distributed under the License is distributed on an "AS IS" BASIS, | ||||||
|  | // 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. | ||||||
|  |  | ||||||
|  | /**************************************************************************** | ||||||
|  |  * @file bike_system.hpp | ||||||
|  |  * @author Serge Ayer <serge.ayer@hefr.ch> | ||||||
|  |  * | ||||||
|  |  * @brief Bike System header file (static scheduling) | ||||||
|  |  * | ||||||
|  |  * @date 2023-08-20 | ||||||
|  |  * @version 1.0.0 | ||||||
|  |  ***************************************************************************/ | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | // from advembsof | ||||||
|  | #include "display_device.hpp" | ||||||
|  | #include "task_logger.hpp" | ||||||
|  | #include "cpu_logger.hpp" | ||||||
|  |  | ||||||
|  | // from common | ||||||
|  | #include "sensor_device.hpp" | ||||||
|  | #include "speedometer.hpp" | ||||||
|  |  | ||||||
|  | // local | ||||||
|  | #include "gear_device.hpp" | ||||||
|  | #include "pedal_device.hpp" | ||||||
|  | #include "reset_device.hpp" | ||||||
|  |  | ||||||
|  | namespace static_scheduling_with_event { | ||||||
|  |  | ||||||
|  | class BikeSystem { | ||||||
|  |    public: | ||||||
|  |     // constructor | ||||||
|  |     BikeSystem(); | ||||||
|  |  | ||||||
|  |     // make the class non copyable | ||||||
|  |     BikeSystem(BikeSystem&)            = delete; | ||||||
|  |     BikeSystem& operator=(BikeSystem&) = delete; | ||||||
|  |  | ||||||
|  |     // method called in main() for starting the system | ||||||
|  |     void start(); | ||||||
|  |  | ||||||
|  |     // method called in main() for starting the sysytem with the event queue | ||||||
|  |     void startWithEventQueue(); | ||||||
|  |  | ||||||
|  |     // method called for stopping the system | ||||||
|  |     void stop(); | ||||||
|  |  | ||||||
|  | #if defined(MBED_TEST_MODE) | ||||||
|  |     const advembsof::TaskLogger& getTaskLogger(); | ||||||
|  | #endif  // defined(MBED_TEST_MODE) | ||||||
|  |  | ||||||
|  |    private: | ||||||
|  |     // private methods | ||||||
|  |     void init(); | ||||||
|  |     void onReset(); | ||||||
|  |     void gearTask(); | ||||||
|  |     void speedDistanceTask(); | ||||||
|  |     void temperatureTask(); | ||||||
|  |     void resetTask(); | ||||||
|  |     void displayTask1(); | ||||||
|  |     void displayTask2(); | ||||||
|  |     void cpuTask(); | ||||||
|  |  | ||||||
|  |     // stop flag, used for stopping the super-loop (set in stop()) | ||||||
|  |     bool _stopFlag = false; | ||||||
|  |  | ||||||
|  |     std::chrono::microseconds _resetTime = std::chrono::microseconds::zero(); | ||||||
|  |     volatile bool _resetFlag = false; | ||||||
|  |  | ||||||
|  |     // timer instance used for loggint task time and used by ResetDevice | ||||||
|  |     Timer _timer; | ||||||
|  |     // data member that represents the device for manipulating the gear | ||||||
|  |     GearDevice _gearDevice; | ||||||
|  |     uint8_t _currentGear = bike_computer::kMinGear; | ||||||
|  |     uint8_t _currentGearSize = bike_computer::kMinGearSize; | ||||||
|  |     // data member that represents the device for manipulating the pedal rotation | ||||||
|  |     // speed/time | ||||||
|  |     PedalDevice _pedalDevice; | ||||||
|  |     float _currentSpeed = 0.0f; | ||||||
|  |     float _traveledDistance = 0.0f; | ||||||
|  |     // data member that represents the device used for resetting | ||||||
|  |     ResetDevice _resetDevice; | ||||||
|  |     // data member that represents the device display | ||||||
|  |     advembsof::DisplayDevice _displayDevice; | ||||||
|  |     // data member that represents the device for counting wheel rotations | ||||||
|  |     bike_computer::Speedometer _speedometer; | ||||||
|  |     // data member that represents the sensor device | ||||||
|  |     bike_computer::SensorDevice _sensorDevice; | ||||||
|  |     float _currentTemperature = 0.0f; | ||||||
|  |  | ||||||
|  |     // used for logging task info | ||||||
|  |     advembsof::TaskLogger _taskLogger; | ||||||
|  |  | ||||||
|  |     // cpu logger to measure cpu usage | ||||||
|  |     advembsof::CPULogger _cpuLogger; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | }  // namespace static_scheduling | ||||||
							
								
								
									
										69
									
								
								static_scheduling_with_event/gear_device.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								static_scheduling_with_event/gear_device.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,69 @@ | |||||||
|  | // Copyright 2022 Haute école d'ingénierie et d'architecture de Fribourg | ||||||
|  | // | ||||||
|  | // Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  | // you may not use this file except in compliance with the License. | ||||||
|  | // You may obtain a copy of the License at | ||||||
|  | // | ||||||
|  | //     http://www.apache.org/licenses/LICENSE-2.0 | ||||||
|  | // | ||||||
|  | // Unless required by applicable law or agreed to in writing, software | ||||||
|  | // distributed under the License is distributed on an "AS IS" BASIS, | ||||||
|  | // 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. | ||||||
|  |  | ||||||
|  | /**************************************************************************** | ||||||
|  |  * @file gear_device.cpp | ||||||
|  |  * @author Serge Ayer <serge.ayer@hefr.ch> | ||||||
|  |  * @author Rémi Heredero <remi@heredero.ch> | ||||||
|  |  * @author Yann Sierro <yannsierro.pro@gmail.com> | ||||||
|  |  * | ||||||
|  |  * @brief Gear Device implementation (static scheduling) | ||||||
|  |  * | ||||||
|  |  * @date 2023-11-17 | ||||||
|  |  * @version 1.1.0 | ||||||
|  |  ***************************************************************************/ | ||||||
|  |  | ||||||
|  | #include "gear_device.hpp" | ||||||
|  |  | ||||||
|  | // from disco_h747i/wrappers | ||||||
|  | #include <chrono> | ||||||
|  |  | ||||||
|  | #include "joystick.hpp" | ||||||
|  | #include "mbed_trace.h" | ||||||
|  |  | ||||||
|  | #if MBED_CONF_MBED_TRACE_ENABLE | ||||||
|  | #define TRACE_GROUP "GearDevice" | ||||||
|  | #endif  // MBED_CONF_MBED_TRACE_ENABLE | ||||||
|  |  | ||||||
|  | namespace static_scheduling_with_event { | ||||||
|  |  | ||||||
|  |  | ||||||
|  | GearDevice::GearDevice() { | ||||||
|  |     disco::Joystick::getInstance().setUpCallback( | ||||||
|  |         callback(this, &GearDevice::onUp)); | ||||||
|  |     disco::Joystick::getInstance().setDownCallback( | ||||||
|  |         callback(this, &GearDevice::onDown)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | uint8_t GearDevice::getCurrentGear() { | ||||||
|  |     return core_util_atomic_load_u8(&_currentGear); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | uint8_t GearDevice::getCurrentGearSize() const { | ||||||
|  |     return bike_computer::kMaxGearSize - core_util_atomic_load_u8(&_currentGear); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void GearDevice::onUp() { | ||||||
|  |     if (_currentGear < bike_computer::kMaxGear) { | ||||||
|  |         core_util_atomic_incr_u8(&_currentGear, 1); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void GearDevice::onDown() { | ||||||
|  |     if (_currentGear > bike_computer::kMinGear) { | ||||||
|  |         core_util_atomic_decr_u8(&_currentGear, 1); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | }  // namespace static_scheduling | ||||||
							
								
								
									
										54
									
								
								static_scheduling_with_event/gear_device.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								static_scheduling_with_event/gear_device.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,54 @@ | |||||||
|  | // Copyright 2022 Haute école d'ingénierie et d'architecture de Fribourg | ||||||
|  | // | ||||||
|  | // Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  | // you may not use this file except in compliance with the License. | ||||||
|  | // You may obtain a copy of the License at | ||||||
|  | // | ||||||
|  | //     http://www.apache.org/licenses/LICENSE-2.0 | ||||||
|  | // | ||||||
|  | // Unless required by applicable law or agreed to in writing, software | ||||||
|  | // distributed under the License is distributed on an "AS IS" BASIS, | ||||||
|  | // 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. | ||||||
|  |  | ||||||
|  | /**************************************************************************** | ||||||
|  |  * @file gear_device.hpp | ||||||
|  |  * @author Serge Ayer <serge.ayer@hefr.ch> | ||||||
|  |  * @author Rémi Heredero <remi@heredero.ch> | ||||||
|  |  * @author Yann Sierro <yannsierro.pro@gmail.com> | ||||||
|  |  * | ||||||
|  |  * @brief Gear Device header file (static scheduling) | ||||||
|  |  * | ||||||
|  |  * @date 2023-11-17 | ||||||
|  |  * @version 1.1.0 | ||||||
|  |  ***************************************************************************/ | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "constants.hpp" | ||||||
|  | #include "mbed.h" | ||||||
|  |  | ||||||
|  | namespace static_scheduling_with_event { | ||||||
|  |  | ||||||
|  | class GearDevice { | ||||||
|  |    public: | ||||||
|  |     explicit GearDevice();  // NOLINT(runtime/references) | ||||||
|  |  | ||||||
|  |     // make the class non copyable | ||||||
|  |     GearDevice(GearDevice&)            = delete; | ||||||
|  |     GearDevice& operator=(GearDevice&) = delete; | ||||||
|  |  | ||||||
|  |     // method called for updating the bike system | ||||||
|  |     uint8_t getCurrentGear(); | ||||||
|  |     uint8_t getCurrentGearSize() const; | ||||||
|  |  | ||||||
|  |     void onUp(); | ||||||
|  |     void onDown(); | ||||||
|  |  | ||||||
|  |    private: | ||||||
|  |     // data members | ||||||
|  |     volatile uint8_t _currentGear = bike_computer::kMinGear; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | }  // namespace static_scheduling | ||||||
							
								
								
									
										62
									
								
								static_scheduling_with_event/pedal_device.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								static_scheduling_with_event/pedal_device.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,62 @@ | |||||||
|  | /**************************************************************************** | ||||||
|  | * @file pedal_device.cpp | ||||||
|  | * @author Rémi Heredero <remi@heredero.ch> | ||||||
|  | * @author Yann Sierro <yannsierro.pro@gmail.com> | ||||||
|  | * | ||||||
|  | * @brief Pedal Device implementation (static scheduling) | ||||||
|  | * @date 2024-11-17 | ||||||
|  | * @version 1.1.0 | ||||||
|  | ****************************************************************************/ | ||||||
|  |  | ||||||
|  | #include "pedal_device.hpp" | ||||||
|  |  | ||||||
|  | // from disco_h747i/wrappers | ||||||
|  | #include <chrono> | ||||||
|  |  | ||||||
|  | #include "joystick.hpp" | ||||||
|  | #include "mbed_trace.h" | ||||||
|  |  | ||||||
|  | #if MBED_CONF_MBED_TRACE_ENABLE | ||||||
|  | #define TRACE_GROUP "PedalDevice" | ||||||
|  | #endif  // MBED_CONF_MBED_TRACE_ENABLE | ||||||
|  |  | ||||||
|  | namespace static_scheduling_with_event { | ||||||
|  |  | ||||||
|  | 	PedalDevice::PedalDevice() { | ||||||
|  | 		disco::Joystick::getInstance().setLeftCallback( | ||||||
|  |             callback(this, &PedalDevice::onLeft) | ||||||
|  |         ); | ||||||
|  |         disco::Joystick::getInstance().setRightCallback( | ||||||
|  |             callback(this, &PedalDevice::onRight) | ||||||
|  |         ); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     std::chrono::milliseconds PedalDevice::getCurrentRotationTime() { | ||||||
|  |         uint32_t currentStep = core_util_atomic_load_u32(&_currentStep); | ||||||
|  |         return bike_computer::kMinPedalRotationTime + currentStep * bike_computer::kDeltaPedalRotationTime; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void PedalDevice::increaseRotationSpeed() { | ||||||
|  |         uint32_t currentStep = core_util_atomic_load_u32(&_currentStep); | ||||||
|  |         if (currentStep > 0) { | ||||||
|  |             core_util_atomic_decr_u32(&_currentStep, 1); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void PedalDevice::decreaseRotationSpeed() { | ||||||
|  |         uint32_t currentStep = core_util_atomic_load_u32(&_currentStep); | ||||||
|  |         if (currentStep < bike_computer::kNbrOfSteps) { | ||||||
|  |             core_util_atomic_incr_u32(&_currentStep, 1); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void PedalDevice::onLeft() { | ||||||
|  |         decreaseRotationSpeed(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void PedalDevice::onRight() { | ||||||
|  |         increaseRotationSpeed(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										60
									
								
								static_scheduling_with_event/pedal_device.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								static_scheduling_with_event/pedal_device.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,60 @@ | |||||||
|  | // Copyright 2022 Haute école d'ingénierie et d'architecture de Fribourg | ||||||
|  | // | ||||||
|  | // Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  | // you may not use this file except in compliance with the License. | ||||||
|  | // You may obtain a copy of the License at | ||||||
|  | // | ||||||
|  | //     http://www.apache.org/licenses/LICENSE-2.0 | ||||||
|  | // | ||||||
|  | // Unless required by applicable law or agreed to in writing, software | ||||||
|  | // distributed under the License is distributed on an "AS IS" BASIS, | ||||||
|  | // 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. | ||||||
|  |  | ||||||
|  | /**************************************************************************** | ||||||
|  |  * @file pedal_device.hpp | ||||||
|  |  * @author Serge Ayer <serge.ayer@hefr.ch> | ||||||
|  |  * @author Rémi Heredero <remi@heredero.ch> | ||||||
|  |  * @author Yann Sierro <yannsierro.pro@gmail.com> | ||||||
|  |  * | ||||||
|  |  * @brief Pedal System header file (static scheduling) | ||||||
|  |  * | ||||||
|  |  * @date 2023-11-17 | ||||||
|  |  * @version 1.1.0 | ||||||
|  |  ***************************************************************************/ | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "constants.hpp" | ||||||
|  | #include "mbed.h" | ||||||
|  |  | ||||||
|  | namespace static_scheduling_with_event { | ||||||
|  |  | ||||||
|  | class PedalDevice { | ||||||
|  |    public: | ||||||
|  |     PedalDevice();  // NOLINT(runtime/references) | ||||||
|  |  | ||||||
|  |     // make the class non copyable | ||||||
|  |     PedalDevice(PedalDevice&)            = delete; | ||||||
|  |     PedalDevice& operator=(PedalDevice&) = delete; | ||||||
|  |  | ||||||
|  |     // method called for updating the bike system | ||||||
|  |     std::chrono::milliseconds getCurrentRotationTime(); | ||||||
|  |  | ||||||
|  |    private: | ||||||
|  |     // private methods | ||||||
|  |     void onLeft(); | ||||||
|  |     void onRight(); | ||||||
|  |     void increaseRotationSpeed(); | ||||||
|  |     void decreaseRotationSpeed(); | ||||||
|  |  | ||||||
|  |     // data members | ||||||
|  |     volatile uint32_t _currentStep = static_cast<uint32_t>( | ||||||
|  |         ( | ||||||
|  |             bike_computer::kInitialPedalRotationTime - bike_computer::kMinPedalRotationTime | ||||||
|  |         ).count() / bike_computer::kDeltaPedalRotationTime.count() | ||||||
|  |     ); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | }  // namespace static_scheduling | ||||||
							
								
								
									
										36
									
								
								static_scheduling_with_event/reset_device.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								static_scheduling_with_event/reset_device.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | |||||||
|  | /**************************************************************************** | ||||||
|  | * @file reset_device.cpp | ||||||
|  | * @author Rémi Heredero <remi@heredero.ch> | ||||||
|  | * @author Yann Sierro <yannsierro.pro@gmail.com> | ||||||
|  | * | ||||||
|  | * @brief Reset Device implementation (static scheduling with event) | ||||||
|  | * @date 2024-11-17 | ||||||
|  | * @version 1.1.0 | ||||||
|  | ****************************************************************************/ | ||||||
|  |  | ||||||
|  | #include "reset_device.hpp" | ||||||
|  |  | ||||||
|  | // from disco_h747i/wrappers | ||||||
|  | #include <chrono> | ||||||
|  |  | ||||||
|  | #include "joystick.hpp" | ||||||
|  | #include "mbed_trace.h" | ||||||
|  |  | ||||||
|  | #if defined(TARGET_DISCO_H747I) | ||||||
|  | #define PUSH_BUTTON BUTTON1 | ||||||
|  | static constexpr uint8_t kPolarityPressed = 1; | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #if MBED_CONF_MBED_TRACE_ENABLE | ||||||
|  | #define TRACE_GROUP "ResetDevice" | ||||||
|  | #endif  // MBED_CONF_MBED_TRACE_ENABLE | ||||||
|  |  | ||||||
|  | namespace static_scheduling_with_event { | ||||||
|  |  | ||||||
|  | 	ResetDevice::ResetDevice(Callback<void()> cb) : _resetButton(PUSH_BUTTON) { | ||||||
|  |     	_resetButton.fall(cb); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										48
									
								
								static_scheduling_with_event/reset_device.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								static_scheduling_with_event/reset_device.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,48 @@ | |||||||
|  | // Copyright 2022 Haute école d'ingénierie et d'architecture de Fribourg | ||||||
|  | // | ||||||
|  | // Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  | // you may not use this file except in compliance with the License. | ||||||
|  | // You may obtain a copy of the License at | ||||||
|  | // | ||||||
|  | //     http://www.apache.org/licenses/LICENSE-2.0 | ||||||
|  | // | ||||||
|  | // Unless required by applicable law or agreed to in writing, software | ||||||
|  | // distributed under the License is distributed on an "AS IS" BASIS, | ||||||
|  | // 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. | ||||||
|  |  | ||||||
|  | /**************************************************************************** | ||||||
|  |  * @file reset_device.hpp | ||||||
|  |  * @author Serge Ayer <serge.ayer@hefr.ch> | ||||||
|  |  * @author Rémi Heredero <remi@heredero.ch> | ||||||
|  |  * @author Yann Sierro <yannsierro.pro@gmail.com> | ||||||
|  |  * | ||||||
|  |  * @brief ResetDevice header file (static scheduling with event) | ||||||
|  |  * | ||||||
|  |  * @date 2023-11-17 | ||||||
|  |  * @version 1.1.0 | ||||||
|  |  ***************************************************************************/ | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "mbed.h" | ||||||
|  |  | ||||||
|  | namespace static_scheduling_with_event { | ||||||
|  |  | ||||||
|  | class ResetDevice { | ||||||
|  |    public: | ||||||
|  |     explicit ResetDevice(Callback<void()> cb);  // NOLINT(runtime/references) | ||||||
|  |  | ||||||
|  |     // make the class non copyable | ||||||
|  |     ResetDevice(ResetDevice&)            = delete; | ||||||
|  |     ResetDevice& operator=(ResetDevice&) = delete; | ||||||
|  |  | ||||||
|  |    private: | ||||||
|  |  | ||||||
|  |     // data members | ||||||
|  |     // instance representing the reset button | ||||||
|  |     InterruptIn _resetButton; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | }  // namespace static_scheduling | ||||||
		Reference in New Issue
	
	Block a user