diff --git a/Application/Inc/ADC.hpp b/Application/Inc/ADC.hpp index 8bebe18..d2f95ec 100644 --- a/Application/Inc/ADC.hpp +++ b/Application/Inc/ADC.hpp @@ -1,23 +1,25 @@ #ifndef APPLICATION_INC_ADC #define APPLICATION_INC_ADC +#include "array" +#include "cmath" #include "main.h" +#ifndef ADC_BUFFER +#define ADC_BUFFER 10 +#endif + class CustomADC { public: - CustomADC(); - virtual ~CustomADC(); - void setPort(ADC_HandleTypeDef *); + CustomADC(); + virtual ~CustomADC(); - uint32_t sample(); - uint32_t getValue(); - double getVolt(); + void saveSample(uint8_t); - uint32_t m_buffer; + std::array m_buffer; - private: - uint32_t m_value{}; - ADC_HandleTypeDef *m_port; + // Public Data + uint32_t volt_from_dac{}; }; -#endif /* APPLICATION_INC_ADC */ +#endif /* APPLICATION_INC_ADC */ diff --git a/Application/Inc/CLI.hpp b/Application/Inc/CLI.hpp index b7b98c2..ee5e8a1 100644 --- a/Application/Inc/CLI.hpp +++ b/Application/Inc/CLI.hpp @@ -17,7 +17,8 @@ class CLI { static int32_t cmd_help(int32_t, char**); static int32_t cmd_led(int32_t, char**); static int32_t cmd_flash(int32_t, char**); - static int32_t cmd_motor(int32_t, char**); + static int32_t cmd_idle(int32_t, char**); + static int32_t cmd_dac(int32_t, char**); static int32_t cmd_show(int32_t, char**); private: diff --git a/Application/Inc/Flash_STM32G431KB.hpp b/Application/Inc/Flash_STM32G431KB.hpp index 9320e70..9b0330d 100644 --- a/Application/Inc/Flash_STM32G431KB.hpp +++ b/Application/Inc/Flash_STM32G431KB.hpp @@ -18,7 +18,7 @@ class Flash { private: // Update config_arr_size according to the sizeof(config)/sizeof(uint64_t) // ------------------- MUST EDIT ------------------- -#define config_arr_size 50 +#define config_arr_size 10 union Config_Arr { struct Config { uint32_t led_level; diff --git a/Application/Inc/FreeRTOSConfig.h b/Application/Inc/FreeRTOSConfig.h index 1bafd65..5322050 100644 --- a/Application/Inc/FreeRTOSConfig.h +++ b/Application/Inc/FreeRTOSConfig.h @@ -64,7 +64,7 @@ #define configTICK_RATE_HZ ((TickType_t)1000) #define configMAX_PRIORITIES ( 7 ) #define configMINIMAL_STACK_SIZE ((uint16_t)64) -#define configTOTAL_HEAP_SIZE ((size_t)7500) +#define configTOTAL_HEAP_SIZE ((size_t)14000) #define configMAX_TASK_NAME_LEN ( 16 ) #define configUSE_16_BIT_TICKS 0 #define configUSE_MUTEXES 1 diff --git a/Application/Inc/Instances.hpp b/Application/Inc/Instances.hpp index f11e98d..3f04e8e 100644 --- a/Application/Inc/Instances.hpp +++ b/Application/Inc/Instances.hpp @@ -17,10 +17,10 @@ extern SerialCOM serialCOM; extern CLI cli; extern Thread thread; extern Flash flash; -extern CustomDAC motor_dac; -extern CustomADC sensor_adc; +extern CustomDAC dac; +extern CustomADC adc; extern sml::sm stream_sm; -extern sml::sm main_sm; +extern sml::sm> main_sm; #endif /* APPLICATION_INC_INSTANCES */ diff --git a/Application/Inc/State.hpp b/Application/Inc/State.hpp index 3d86d51..d6fc35f 100644 --- a/Application/Inc/State.hpp +++ b/Application/Inc/State.hpp @@ -17,25 +17,31 @@ struct shutting_down {}; // Events struct start {}; struct stop {}; +struct toggle {}; struct oneshot {}; struct next {}; struct finish {}; struct shutdown {}; -struct toggle {}; -struct sub_endded {}; +struct function_ended {}; +struct sub_transit {}; + +// Application Events +struct dac_update {}; struct Idle { auto operator()() { using namespace sml; // State Machine Actions - auto act_delay = []() { vTaskDelay(1000); }; - auto act_start = [](Thread *thread) { + auto act_delay = []() { vTaskDelay(3000); }; + auto act_start = [](Thread *thread, SerialCOM *serial) { thread->idling_start(); - vTaskResume(thread->idling_handle); + vTaskResume(thread->idle_handle); + serial->sendString("ideling act_start completed\n"); }; - auto act_shutdown = [](Thread *thread) { - vTaskSuspend(thread->idling_handle); + auto act_shutdown = [](Thread *thread, SerialCOM *serial) { + vTaskSuspend(thread->idle_handle); + serial->sendString("ideling act_shutdown completed\n"); }; // State Machine Logics @@ -44,7 +50,7 @@ struct Idle { *state / act_start = state, state + event / act_delay = state, state + event / act_shutdown = state, - state / process(sub_endded{}) = X + state / process(function_ended{}) = X ); // clang-format on } @@ -54,14 +60,16 @@ struct DACState { auto operator()() { using namespace sml; - auto act_delay = []() { vTaskDelay(1000); }; - auto act_start = [](Thread *thread) { - thread->constant_run_start(); - vTaskResume(thread->constant_run_handle); + auto act_delay = []() { vTaskDelay(3000); }; + auto act_start = [](Thread *thread, SerialCOM *serial) { + thread->dac_start(); + vTaskResume(thread->dac_handle); + serial->sendString("dac act_start completed\n"); }; - auto act_shutdown = [](Thread *thread) { - thread->constant_run_shutdown(); - vTaskSuspend(thread->constant_run_handle); + auto act_shutdown = [](Thread *thread, SerialCOM *serial) { + thread->dac_shutdown(); + vTaskSuspend(thread->dac_handle); + serial->sendString("dac act_shutdown completed\n"); }; // State Machine Logics @@ -70,7 +78,7 @@ struct DACState { *state / act_start = state, state + event / act_delay = state, state + event / act_shutdown = state, - state / process(sub_endded{}) = X, + state / process(function_ended{}) = X, state + event / act_shutdown = state, state + event = state ); @@ -82,19 +90,24 @@ struct MainState { auto operator()() { using namespace sml; - auto act_start = [](Thread thread) {}; - auto act_shutdown = [](Thread thread) {}; + auto act_idle = [](Thread *thread, SerialCOM *serial) { + // thread->idling_start(); + // vTaskResume(thread->idle_handle); + serial->sendString("MainState act_idle completed\n"); + }; + auto act_dac = [](Thread *thread, SerialCOM *serial) { + // thread->dac_start(); + // xTaskResumeFromISR(thread->dac_handle); + serial->sendString("MainState act_dac completed\n"); + }; // State Machine Logics // clang-format off return make_transition_table( *state + event / act_idle = state, - state + event / process(shutdown{}), - state + event / act_constant = state, - state + event / process(shutdown{}), - state + event / act_breathing = state, - state + event / process(shutdown{}), - state + event / act_idle = state + state + event / (act_dac, process(start{})) = state, + state + event / state + ); // clang-format on } @@ -105,22 +118,24 @@ struct StreamState { using namespace sml; // State Machine Actions - auto act_on = [](Thread *thread) { + auto act_on = [](Thread *thread, SerialCOM *serial) { xTaskResumeFromISR(thread->telemetry_human_handle); }; - auto act_off = [](Thread *thread) { + auto act_off = [](Thread *thread, SerialCOM *serial) { vTaskSuspend(thread->telemetry_human_handle); }; - auto act_delay = [](Thread *thread) { vTaskDelay(thread->m_stream_freq); }; + auto act_delay = [](Thread *thread, SerialCOM *serial) { vTaskDelay(thread->m_stream_freq); }; // State Machine Logics // clang-format off return make_transition_table( *state + event / act_on = state, + state + event / act_on = state, state + event / act_on = state, state + event / act_off = state, state + event / act_delay = state, - state + event / act_off = state + state + event / act_off = state, + state + event / act_off = state ); // clang-format on } diff --git a/Application/Inc/Thread.hpp b/Application/Inc/Thread.hpp index 102f3c3..2a5e1d0 100644 --- a/Application/Inc/Thread.hpp +++ b/Application/Inc/Thread.hpp @@ -1,8 +1,8 @@ #ifndef APPLICATION_INC_THREAD #define APPLICATION_INC_THREAD -#include "main.h" #include "FreeRTOS.h" +#include "main.h" #include "task.h" class Thread { @@ -10,20 +10,29 @@ class Thread { Thread(); virtual ~Thread(); - TaskHandle_t parse_handle; - void parse(); + TaskHandle_t telemetry_human_handle; + void telemetry_human(); - TaskHandle_t telemetry_human_handle; - void telemetry_human(); + /*--------------------------------------------------------------------------- - TaskHandle_t init_handle; - void init(); + Applications + + ---------------------------------------------------------------------------*/ + + TaskHandle_t idle_handle; + void idle(); + + TaskHandle_t dac_handle; + void dacUpdate(); + + /*--------------------------------------------------------------------------- - TaskHandle_t utilities_handle; - void utilities(); + System initialization and periodic update - TaskHandle_t app_dac_handle; - void app_dac(); + ---------------------------------------------------------------------------*/ + + TaskHandle_t init_handle; + void init(); TaskHandle_t schedule_20Hz_handle; void schedule_20Hz(); @@ -31,9 +40,20 @@ class Thread { TaskHandle_t serial_send_handle; void serial_send(); + TaskHandle_t parse_handle; + void parse(); + + /*--------------------------------------------------------------------------- + + Thread Settings + + ---------------------------------------------------------------------------*/ + + void idling_start(); + void dac_start(); + void dac_shutdown(); - // Settings - uint16_t m_stream_freq{500}; + uint16_t m_stream_freq{2000}; }; -#endif /* APPLICATION_INC_THREAD */ +#endif /* APPLICATION_INC_THREAD */ diff --git a/Application/Src/ADC.cpp b/Application/Src/ADC.cpp index 09aa9ff..ae33e7d 100644 --- a/Application/Src/ADC.cpp +++ b/Application/Src/ADC.cpp @@ -5,13 +5,17 @@ CustomADC::CustomADC() {} CustomADC::~CustomADC() {} -void CustomADC::setPort(ADC_HandleTypeDef *port) { m_port = port; } - -uint32_t CustomADC::sample() { - m_value = m_buffer; - return m_value; +void CustomADC::saveSample(uint8_t port) { + switch (port) { + // hadc1 + case 1: + break; + // hadc2 + case 2: + volt_from_dac = m_buffer.at(0); + break; + default: + break; + } } -uint32_t CustomADC::getValue() { return m_value; } - -double CustomADC::getVolt() { return static_cast(m_value) / 4096 * 3.3; } diff --git a/Application/Src/CLI.cpp b/Application/Src/CLI.cpp index f9f411f..7d95eeb 100644 --- a/Application/Src/CLI.cpp +++ b/Application/Src/CLI.cpp @@ -13,7 +13,8 @@ void CLI::init() { lwshell_register_cmd("help", &CLI::cmd_help, NULL); lwshell_register_cmd("led", &CLI::cmd_led, NULL); lwshell_register_cmd("flash", &CLI::cmd_flash, NULL); - lwshell_register_cmd("dac", &CLI::cmd_motor, NULL); + lwshell_register_cmd("idle", &CLI::cmd_idle, NULL); + lwshell_register_cmd("dac", &CLI::cmd_dac, NULL); lwshell_register_cmd("show", &CLI::cmd_show, NULL); } @@ -116,7 +117,17 @@ int32_t CLI::cmd_flash(int32_t argc, char** argv) { return 0; } -int32_t CLI::cmd_motor(int32_t argc, char** argv) { +int32_t CLI::cmd_idle(int32_t argc, char** argv) { + + if (argc == 1) { + main_sm.process_event(shutdown{}); + main_sm.process_event(start{}); + } else { + serialCOM.sendString("Unknown Command\n"); + } + return 0; } + +int32_t CLI::cmd_dac(int32_t argc, char** argv) { // Detailed Menu const char* help_text = "\nDAC Functions:\n" @@ -125,28 +136,27 @@ int32_t CLI::cmd_motor(int32_t argc, char** argv) { " add #value\tIncrease or Decrease DAC level\n\n"; // Sub Command - if (argc == 2) { + if (argc ==1) { + main_sm.process_event(shutdown{}); + main_sm.process_event(dac_update{}); + } else if (argc == 2) { if (!strcmp(argv[1], "help")) { serialCOM.sendString(help_text); } else if (!strcmp(argv[1], "on")) { - motor_dac.on(); + dac.on(); } else if (!strcmp(argv[1], "off")) { - motor_dac.off(); + dac.off(); } else if (!strcmp(argv[1], "breath")) { - motor_dac.breath(); - } else if (!strcmp(argv[1], "stream_on")) { - xTaskResumeFromISR(thread.utilities_handle); - } else if (!strcmp(argv[1], "stream_off")) { - vTaskSuspend(thread.utilities_handle); + dac.breath(); } else { serialCOM.sendString("Unknown Command\n"); } } if (argc == 3) { if (!strcmp(argv[1], "level")) { - motor_dac.setLevel(atof(argv[2])); + dac.setLevel(atof(argv[2])); } else if (!strcmp(argv[1], "add")) { - motor_dac.addLevel(atof(argv[2])); + dac.addLevel(atof(argv[2])); } else serialCOM.sendString("Unknown Command\n"); } @@ -158,19 +168,19 @@ int32_t CLI::cmd_show(int32_t argc, char** argv) { // Detailed Menu const char* help_text = "\nShow Telemetry:\n" - " one \tShow Telemetry Once\n" - " all \tStream All Telemetry\n" - " blower \tStream Blower Telemetry\n" - " off \tStop Stream\n\n"; - - if (!strcmp(argv[1], "help")) { - serialCOM.sendString(help_text); - } else if (!strcmp(argv[1], "all")) { - stream_sm.process_event(start{}); - } else if (!strcmp(argv[1], "off")) { - stream_sm.process_event(stop{}); - } else if (!strcmp(argv[1], "one")) { - stream_sm.process_event(oneshot{}); + " Stream Telemetry\n" + " one \tShow Telemetry Once\n\n"; + + if (argc == 1) { + stream_sm.process_event(toggle{}); + } else if (argc == 2) { + if (!strcmp(argv[1], "help")) { + serialCOM.sendString(help_text); + } else if (!strcmp(argv[1], "one")) { + stream_sm.process_event(oneshot{}); + } else { + serialCOM.sendString("Unknown Command\n"); + } } else { serialCOM.sendString("Unknown Command\n"); } @@ -190,7 +200,7 @@ int32_t CLI::cmd_help(int32_t argc, char** argv) { "\n" "\tdac\t[help] [level *] [add *]\n" "\n" - "\tshow\n"; + "\tshow\t[help] [one]\n"; serialCOM.sendString(help_menu); return 0; } diff --git a/Application/Src/Flash_STM32G431KB.cpp b/Application/Src/Flash_STM32G431KB.cpp index ad8d535..dbe32c3 100644 --- a/Application/Src/Flash_STM32G431KB.cpp +++ b/Application/Src/Flash_STM32G431KB.cpp @@ -18,7 +18,7 @@ void Flash::Save() { config.list.led_level = led_user.getLevel(); config.list.led_scale = led_user.getScale(); config.list.led_state = led_user.getState(); - config.list.dac_level = motor_dac.getLevel(); + config.list.dac_level = dac.getLevel(); // Save config object aligned into uint64_t array into flash Write(config.config_arr, config_arr_size); @@ -39,7 +39,7 @@ void Flash::Load() { led_user.setLevel(config.list.led_level); led_user.setScale(config.list.led_scale); led_user.setState(config.list.led_state); - motor_dac.setLevel(config.list.dac_level); + dac.setLevel(config.list.dac_level); } diff --git a/Application/Src/Thread.cpp b/Application/Src/Thread.cpp index 263fb2b..9db244b 100644 --- a/Application/Src/Thread.cpp +++ b/Application/Src/Thread.cpp @@ -9,31 +9,45 @@ Thread::Thread() { // auto _task = [](void *arg) { static_cast(arg)->(); }; // xTaskCreate(_task, "", 512, this, 2, &_Handle); - auto t1 = [](void *arg) { static_cast(arg)->telemetry_human(); }; - xTaskCreate(t1, "telemetry_human", 128, this, 1, &telemetry_human_handle); - vTaskSuspend(telemetry_human_handle); + auto t1 = [](void *arg) { static_cast(arg)->telemetry_human(); }; + xTaskCreate(t1, "telemetry_human", 150, this, 2, &telemetry_human_handle); + vTaskSuspend(telemetry_human_handle); - auto t3 = [](void *arg) { static_cast(arg)->utilities(); }; - xTaskCreate(t3, "utilities", 128, this, 1, &utilities_handle); + auto a1 = [](void *arg) { static_cast(arg)->idle(); }; + xTaskCreate(a1, "idle", 300, this, 2, &idle_handle); + vTaskSuspend(idle_handle); - auto a2 = [](void *arg) { static_cast(arg)->app_dac(); }; - xTaskCreate(a2, "dac + adc", 64, this, 0, &app_dac_handle); + auto a2 = [](void *arg) { static_cast(arg)->dacUpdate(); }; + xTaskCreate(a2, "dacUpdate", 300, this, 2, &dac_handle); + vTaskSuspend(dac_handle); auto s0 = [](void *arg) { static_cast(arg)->init(); }; - xTaskCreate(s0, "system init", 256, this, 6, &init_handle); + xTaskCreate(s0, "system init", 500, this, 6, &init_handle); auto s1 = [](void *arg) { static_cast(arg)->schedule_20Hz(); }; - xTaskCreate(s1, "schedule 20Hz", 64, this, 5, &schedule_20Hz_handle); + xTaskCreate(s1, "schedule 20Hz", 128, this, 5, &schedule_20Hz_handle); auto s11 = [](void *arg) { static_cast(arg)->serial_send(); }; xTaskCreate(s11, "serial send out", 64, this, 0, &serial_send_handle); auto s12 = [](void *arg) { static_cast(arg)->parse(); }; - xTaskCreate(s12, "cli parsing", 512, this, 2, &parse_handle); + xTaskCreate(s12, "cli parsing", 400, this, 3, &parse_handle); } Thread::~Thread() {} +void Thread::telemetry_human() { + while (1) { + serialCOM.sendString("\n\n\n\n\n\n\n\n"); + serialCOM.sendString("\nDAC Target Value:\t"); + serialCOM.sendNumber(dac.getLevel()); + serialCOM.sendString("\nADC Sensing Value:\t"); + serialCOM.sendNumber(adc.volt_from_dac); + serialCOM.sendLn(); + + stream_sm.process_event(finish{}); + } +} /*--------------------------------------------------------------------------- @@ -41,28 +55,23 @@ Thread::~Thread() {} ---------------------------------------------------------------------------*/ - -void Thread::utilities() { +void Thread::idle() { while (1) { - serialCOM.sendString("\nDAC Target Value: "); - serialCOM.sendNumber(motor_dac.getLevel()); - serialCOM.sendString("\nADC Sensing Value: "); - serialCOM.sendNumber(sensor_adc.getVolt()); - serialCOM.sendLn(); - // vTaskSuspend(NULL); - vTaskDelay(1000); + serialCOM.sendString("idling\n"); + dac.setLevel(0); + dac.off(); + main_sm.process_event(finish{}); } } -void Thread::app_dac() { +void Thread::dacUpdate() { while (1) { - motor_dac.schedule(); - // vTaskSuspend(NULL); - vTaskDelay(1000); + serialCOM.sendString("dac updating\n"); + dac.schedule(); + main_sm.process_event(finish{}); } } - /*--------------------------------------------------------------------------- System initialization and periodic update @@ -71,10 +80,14 @@ void Thread::app_dac() { void Thread::init() { while (1) { + serialCOM.sendString("RTOS Init\n"); cli.init(); - motor_dac.init(); + dac.init(); flash.Load(); - vTaskSuspend(utilities_handle); + + main_sm.process_event(start{}); + main_sm.process_event(start{}); + vTaskSuspend(NULL); } } @@ -97,4 +110,15 @@ void Thread::parse() { ulTaskNotifyTake(pdTRUE, portMAX_DELAY); cli.parse(); } -} \ No newline at end of file +} + +void Thread::idling_start() { serialCOM.sendString("ideling start function called\n"); } + +void Thread::dac_start() { + serialCOM.sendString("dac start function called\n"); + dac.breath(); +} +void Thread::dac_shutdown() { + serialCOM.sendString("dac shutdown function called\n"); + dac.off(); +} diff --git a/Application/Src/main.cpp b/Application/Src/main.cpp index 2483055..4c22aff 100644 --- a/Application/Src/main.cpp +++ b/Application/Src/main.cpp @@ -15,11 +15,11 @@ Thread thread{}; LED led_user{1000}; SerialCOM serialCOM{}; Flash flash{}; -CustomDAC motor_dac{}; -CustomADC sensor_adc{}; +CustomDAC dac{}; +CustomADC adc{}; sml::sm stream_sm{&thread}; -sml::sm main_sm{&thread}; +sml::sm> main_sm{&thread, &serialCOM}; /** * @brief The application entry point. @@ -40,15 +40,25 @@ int main(void) { MX_TIM2_Init(); MX_TIM4_Init(); - HAL_TIM_PWM_Start_IT(&htim8, TIM_CHANNEL_2); - HAL_UARTEx_ReceiveToIdle_IT(&huart2, serialCOM.m_rx_data, UART_BUFFER); - HAL_ADC_Start_DMA(&hadc2, &sensor_adc.m_buffer, 1); - // Instances Dependency Injection serialCOM.setPort(&huart2); led_user.setPort(&htim8.Instance->CCR2); - motor_dac.setPort(&hdac1, DAC_CHANNEL_2); - sensor_adc.setPort(&hadc2); + dac.setPort(&hdac1, DAC_CHANNEL_2); + + serialCOM.sendString("Instance dependency injection complete\n"); + + // PWM Output Start + HAL_TIM_PWM_Start_IT(&htim8, TIM_CHANNEL_2); + serialCOM.sendString("PWM output Start\n"); + + // Serial Communication Start + HAL_UARTEx_ReceiveToIdle_IT(&huart2, serialCOM.m_rx_data, UART_BUFFER); + serialCOM.sendString("Serial communication Start\n"); + + // ADC Calibration and Start + HAL_ADCEx_Calibration_Start(&hadc2, ADC_SINGLE_ENDED); + HAL_ADC_Start_DMA(&hadc2, adc.m_buffer.data(), 1); + serialCOM.sendString("ADC calibration and start\n"); // FreeRTOS Start vTaskStartScheduler(); @@ -74,7 +84,9 @@ void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size) { } } -void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc) { sensor_adc.sample(); } +void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc) { + if (hadc->Instance == ADC2) adc.saveSample(2); +} void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if (htim->Instance == TIM17) {