diff options
Diffstat (limited to 'src/Platform/Event.cpp')
-rw-r--r-- | src/Platform/Event.cpp | 192 |
1 files changed, 145 insertions, 47 deletions
diff --git a/src/Platform/Event.cpp b/src/Platform/Event.cpp index ddc17eb6..5cf95a67 100644 --- a/src/Platform/Event.cpp +++ b/src/Platform/Event.cpp @@ -7,78 +7,176 @@ #include <Platform/Event.h> #include <RepRapFirmware.h> +#include <ObjectModel/ObjectModel.h> +#include <ObjectModel/Variable.h> -Event::Event(Event *p_next, EventType et, EventParameter p_param, CanAddress p_ba, uint8_t devNum) noexcept - : next(p_next), param(p_param), type(et), boardAddress(p_ba), deviceNumber(devNum) +Event *_ecv_null Event::eventsPending = nullptr; + +inline Event::Event(Event *_ecv_null pnext, EventType et, uint16_t p_param, uint8_t devNum, CanAddress p_ba, const char *_ecv_array format, va_list vargs) noexcept + : next(pnext), param(p_param), type(et), boardAddress(p_ba), deviceNumber(devNum), isBeingProcessed(false) { + text.vprintf(format, vargs); } -void Event::AppendText(const StringRef &str) const noexcept +// Queue an event unless we have a similar event pending already. Returns true if the event was added. +// The event list is held in priority order, lowest numbered (highest priority) events first. +/*static*/ bool Event::AddEvent(EventType et, uint16_t p_param, uint8_t devNum, CanAddress p_ba, const char *_ecv_array format, va_list vargs) noexcept { - // First append the event type with underscores changed to spaces - const char *p = type.ToString(); - while (*p != 0) - { - str.cat((*p == '_') ? ' ' : *p); - ++p; - } + // Search for similar events already pending or being processed. + // An event is 'similar' if it has the same type, device number and parameter even if the text is different. + TaskCriticalSectionLocker lock; - // Now append further details of the event - switch (type.ToBaseType()) + Event** pe = &eventsPending; + while (*pe != nullptr && (et >= (*pe)->type || (*pe)->isBeingProcessed)) // while the next event in the list has same or higher priority than the new one { - case EventType::Heater_fault: - str.catf("on heater %u: %s", deviceNumber, HeaterFaultType(param.heaterFaultStatus).ToString()); - break; - - case EventType::Driver_error: - case EventType::Driver_warning: + if (et == (*pe)->type && devNum == (*pe)->deviceNumber #if SUPPORT_CAN_EXPANSION - str.catf(" on %u.%u", boardAddress, deviceNumber); -#else - str.catf(" on %u", deviceNumber); + && p_ba == (*pe)->boardAddress #endif - param.driverStatus.AppendText(str, (type == EventType::Driver_error) ? 2 : 1); - break; + ) + { + return false; // there is a similar event already in the queue + } + pe = &((*pe)->next); + } + + // We didn't find a similar event, so add the new one + *pe = new Event(*pe, et, p_param, p_ba, devNum, format, vargs); + return true; +} - case EventType::Filament_error: - str.catf(" on extruder %u: %s", deviceNumber, FilamentSensorStatus(param.filamentStatus).ToString()); - break; +// Get the highest priority event and mark it as being serviced +/*static*/ bool Event::StartProcessing() noexcept +{ + TaskCriticalSectionLocker lock; - case EventType::Main_board_power_failure: - break; + Event * const ev = eventsPending; + if (ev == nullptr) + { + return false; + } + ev->isBeingProcessed = true; + return true; +} - case EventType::Trigger: - str.catf(" %u activated", deviceNumber); - break; +// Get the name of the macro that we run when this event occurs +/*static*/ void Event::GetMacroFileName(const StringRef& fname) noexcept +{ + const Event * const ep = eventsPending; + if (ep != nullptr && ep->isBeingProcessed) + { + fname.copy(ep->type.ToString()); + fname.cat(".g"); + } +} - case EventType::Mcu_temperature_warning: +// Get the macro parameters for the current event, excluding the S parameter which the caller will add +/*static*/ void Event::GetParameters(VariableSet& vars) noexcept +{ + const Event * const ep = eventsPending; + if (ep != nullptr && ep->isBeingProcessed) + { + vars.InsertNewParameter("D", ExpressionValue((int32_t)(ep->deviceNumber))); #if SUPPORT_CAN_EXPANSION - str.catf("on board %u: temperature %.1fC", boardAddress, (double)param.fVal); -#else - str.catf(": temperature %.1fC", (double)param.fVal); + vars.InsertNewParameter("B", ExpressionValue((int32_t)(ep->boardAddress))); #endif - break; + vars.InsertNewParameter("P", ExpressionValue((int32_t)(ep->param))); } } -// Append the name of the macro that we run when this event occurs -void Event::GetMacroFileName(const StringRef& fname) const noexcept +// Get the default action for the current event +/*static*/ Event::DefaultAction Event::GetDefaultAction() noexcept { - const char *p = type.ToString(); - fname.cat((char)tolower(*p++)); - while (*p != 0) + const Event * const ep = eventsPending; + if (ep != nullptr && ep->isBeingProcessed) { - if (*p == '_' && p[1] != 0) + switch (ep->type.RawValue()) { - fname.cat(toupper(p[1])); - p += 2; + case EventType::heater_fault: + case EventType::filament_error: + return DefaultAction::pauseWithMacro; + + case EventType::driver_error: + return DefaultAction::pauseNoMacro; + + default: + break; } - else + } + return DefaultAction::none; +} + +// Mark the highest priority event as completed +/*static*/ void Event::FinishedProcessing() noexcept +{ + TaskCriticalSectionLocker lock; + + const Event *ev = eventsPending; + if (ev != nullptr && ev->isBeingProcessed) + { + eventsPending = ev->next; + delete ev; + } +} + +// Get a description of the current event +/*static*/ MessageType Event::GetTextDescription(const StringRef& str) noexcept +{ + const Event * const ep = eventsPending; + if (ep != nullptr && ep->isBeingProcessed) + { + switch (ep->type.RawValue()) { - fname.cat(*p++); + case EventType::heater_fault: + { + const char *_ecv_array heaterFaultText = HeaterFaultText[max<size_t>(ep->param, ARRAY_SIZE(HeaterFaultText) - 1)]; + str.printf("Heater %u fault: %s%s", ep->deviceNumber, heaterFaultText, ep->text.c_str()); + } + return ErrorMessage; + + case EventType::filament_error: + str.printf("Filament error on extruder %u: %s", ep->deviceNumber, FilamentSensorStatus(ep->param).ToString()); + return ErrorMessage; + + case EventType::driver_error: +#if SUPPORT_CAN_EXPANSION + str.printf("Driver %u.%u error: %s", ep->boardAddress, ep->deviceNumber, ep->text.c_str()); +#else + str.printf("Driver %u error: %s", deviceNumber, ep->text.c_str()); +#endif + return ErrorMessage; + + case EventType::driver_warning: +#if SUPPORT_CAN_EXPANSION + str.printf("Driver %u.%u warning: %s", ep->boardAddress, ep->deviceNumber, ep->text.c_str()); +#else + str.printf("Driver %u warning: %s", deviceNumber, ep->text.c_str()); +#endif + return WarningMessage; + + case EventType::driver_stall: +#if SUPPORT_CAN_EXPANSION + str.printf("Driver %u.%u stall", ep->boardAddress, ep->deviceNumber); +#else + str.printf("Driver %u stall", ep->deviceNumber); +#endif + return WarningMessage; + + case EventType::main_board_power_fail: + // This does not currently generate an event, so no text + return ErrorMessage; + + case EventType::mcu_temperature_warning: +#if SUPPORT_CAN_EXPANSION + str.printf("MCU temperature warning from board %u: temperature %.1fC", ep->boardAddress, (double)((float)ep->param/10)); +#else + str.printf("MCU temperature warning: temperature %.1fC", (double)((float)ep->param/10)); +#endif + return WarningMessage; } } - fname.cat(".g"); + str.copy("Internal error in Event"); + return ErrorMessage; } // End |