diff --git a/firmware/console/binary/tooth_logger.h b/firmware/console/binary/tooth_logger.h index e889919a6a..e6eb3d9e1e 100644 --- a/firmware/console/binary/tooth_logger.h +++ b/firmware/console/binary/tooth_logger.h @@ -8,6 +8,7 @@ #pragma once #include "rusefi_enums.h" +#include "expected.h" #if EFI_UNIT_TEST #include "logicdata.h" diff --git a/firmware/console/binary/tunerstudio_outputs.h b/firmware/console/binary/tunerstudio_outputs.h index c5ebb9093c..feecb295ec 100644 --- a/firmware/console/binary/tunerstudio_outputs.h +++ b/firmware/console/binary/tunerstudio_outputs.h @@ -31,3 +31,5 @@ * see also TS_OUTPUT_SIZE in rusefi_config.txt */ struct TunerStudioOutputChannels : output_channels_s { }; + +TunerStudioOutputChannels *getTunerStudioOutputChannels(); diff --git a/firmware/controllers/algo/engine.cpp b/firmware/controllers/algo/engine.cpp index 7cd19389a6..0dd04c4534 100644 --- a/firmware/controllers/algo/engine.cpp +++ b/firmware/controllers/algo/engine.cpp @@ -645,4 +645,7 @@ EngineState * getEngineState() { return &engine->engineState; } +TunerStudioOutputChannels *getTunerStudioOutputChannels() { + return &engine->outputChannels; +} diff --git a/firmware/controllers/engine_cycle/main_trigger_callback.cpp b/firmware/controllers/engine_cycle/main_trigger_callback.cpp index 91fff94ae5..35cfe29bf7 100644 --- a/firmware/controllers/engine_cycle/main_trigger_callback.cpp +++ b/firmware/controllers/engine_cycle/main_trigger_callback.cpp @@ -45,6 +45,7 @@ #include "local_version_holder.h" #include "event_queue.h" #include "injector_model.h" +#include "injection_gpio.h" #if EFI_LAUNCH_CONTROL #include "launch_control.h" @@ -72,36 +73,6 @@ void endSimultaneousInjection(InjectionEvent *event) { engine->injectionEvents.addFuelEventsForCylinder(event->ownIndex); } -void InjectorOutputPin::open(efitick_t nowNt) { - // per-output counter for error detection - overlappingCounter++; - // global counter for logging - getEngineState()->fuelInjectionCounter++; - -#if FUEL_MATH_EXTREME_LOGGING - if (printFuelDebug) { - printf("InjectorOutputPin::open %s %d now=%0.1fms\r\n", name, overlappingCounter, (int)getTimeNowUs() / 1000.0); - } -#endif /* FUEL_MATH_EXTREME_LOGGING */ - - if (overlappingCounter > 1) { -// /** -// * #299 -// * this is another kind of overlap which happens in case of a small duty cycle after a large duty cycle -// */ -#if FUEL_MATH_EXTREME_LOGGING - if (printFuelDebug) { - printf("overlapping, no need to touch pin %s %d\r\n", name, (int)getTimeNowUs()); - } -#endif /* FUEL_MATH_EXTREME_LOGGING */ - } else { -#if EFI_TOOTH_LOGGER - LogTriggerInjectorState(nowNt, true); -#endif // EFI_TOOTH_LOGGER - setHigh(); - } -} - void turnInjectionPinHigh(InjectionEvent *event) { efitick_t nowNt = getTimeNowNt(); for (int i = 0;i < MAX_WIRES_COUNT;i++) { @@ -115,25 +86,27 @@ void turnInjectionPinHigh(InjectionEvent *event) { void InjectorOutputPin::setHigh() { NamedOutputPin::setHigh(); + TunerStudioOutputChannels *state = getTunerStudioOutputChannels(); // this is NASTY but what's the better option? bytes? At cost of 22 extra bytes in output status packet? switch (injectorIndex) { case 0: - engine->outputChannels.injectorState1 = true; + state->injectorState1 = true; break; case 1: - engine->outputChannels.injectorState2 = true; + state->injectorState2 = true; break; case 2: - engine->outputChannels.injectorState3 = true; + state->injectorState3 = true; break; case 3: - engine->outputChannels.injectorState4 = true; + state->injectorState4 = true; break; } } void InjectorOutputPin::setLow() { NamedOutputPin::setLow(); + TunerStudioOutputChannels *state = getTunerStudioOutputChannels(); // this is NASTY but what's the better option? bytes? At cost of 22 extra bytes in output status packet? switch (injectorIndex) { case 0: @@ -151,33 +124,6 @@ void InjectorOutputPin::setLow() { } } -void InjectorOutputPin::close(efitick_t nowNt) { -#if FUEL_MATH_EXTREME_LOGGING - if (printFuelDebug) { - printf("InjectorOutputPin::close %s %d %d\r\n", name, overlappingCounter, (int)getTimeNowUs()); - } -#endif /* FUEL_MATH_EXTREME_LOGGING */ - - overlappingCounter--; - if (overlappingCounter > 0) { -#if FUEL_MATH_EXTREME_LOGGING - if (printFuelDebug) { - printf("was overlapping, no need to touch pin %s %d\r\n", name, (int)getTimeNowUs()); - } -#endif /* FUEL_MATH_EXTREME_LOGGING */ - } else { -#if EFI_TOOTH_LOGGER - LogTriggerInjectorState(nowNt, false); -#endif // EFI_TOOTH_LOGGER - setLow(); - } - - // Don't allow negative overlap count - if (overlappingCounter < 0) { - overlappingCounter = 0; - } -} - void turnInjectionPinLow(InjectionEvent *event) { efitick_t nowNt = getTimeNowNt(); diff --git a/firmware/controllers/engine_cycle/prime_injection.cpp b/firmware/controllers/engine_cycle/prime_injection.cpp index 912a8141ab..8724e5c01f 100644 --- a/firmware/controllers/engine_cycle/prime_injection.cpp +++ b/firmware/controllers/engine_cycle/prime_injection.cpp @@ -4,7 +4,7 @@ #include "pch.h" #include "prime_injection.h" -#include "efi_gpio.h" +#include "injection_gpio.h" #include "sensor.h" diff --git a/firmware/controllers/system/efi_gpio.cpp b/firmware/controllers/system/efi_gpio.cpp index ea6b14fe6f..3a761b899d 100644 --- a/firmware/controllers/system/efi_gpio.cpp +++ b/firmware/controllers/system/efi_gpio.cpp @@ -345,12 +345,6 @@ void NamedOutputPin::setLow() { #endif /* EFI_ENGINE_SNIFFER */ } -InjectorOutputPin::InjectorOutputPin() : NamedOutputPin() { - overlappingCounter = 1; // Force update in reset - reset(); - injectorIndex = -1; -} - bool NamedOutputPin::stop() { #if EFI_GPIO_HARDWARE if (isInitialized() && getLogicValue()) { diff --git a/firmware/controllers/system/efi_gpio.h b/firmware/controllers/system/efi_gpio.h index 7fc5953fc5..9c04dbb444 100644 --- a/firmware/controllers/system/efi_gpio.h +++ b/firmware/controllers/system/efi_gpio.h @@ -12,7 +12,7 @@ #include "global.h" #include "io_pins.h" #include "engine_configuration.h" -#include "smart_gpio.h" +#include "injection_gpio.h" void initPrimaryPins(); void initOutputPins(); @@ -23,119 +23,9 @@ void turnAllPinsOff(void); #define turnAllPinsOff() {} #endif /* EFI_GPIO_HARDWARE */ -// Used if you want a function to be virtual only for unit testing purposes -#if EFI_UNIT_TEST -#define TEST_VIRTUAL virtual -#else -#define TEST_VIRTUAL -#endif #ifdef __cplusplus -/** - * @brief Single output pin reference and state - */ -class OutputPin { -public: - OutputPin(); - /** - * initializes pin & registers it in pin repository - * outputMode being a pointer allow us to change configuration (for example invert logical pin) in configuration and get resuts applied - * away, or at least I hope that's why - */ - void initPin(const char *msg, brain_pin_e brainPin, const pin_output_mode_e *outputMode, bool forceInitWithFatalError = false); - /** - * same as above, with DEFAULT_OUTPUT mode - */ - void initPin(const char *msg, brain_pin_e brainPin); - /** - * dissociates pin from this output and un-registers it in pin repository - */ - void deInit(); - - bool isInitialized(); - - bool getAndSet(int logicValue); - TEST_VIRTUAL void setValue(int logicValue); - void toggle(); - bool getLogicValue() const; - - brain_pin_diag_e getDiag() const; - -#if EFI_GPIO_HARDWARE - ioportid_t port = 0; - uint8_t pin = 0; -#endif /* EFI_GPIO_HARDWARE */ - -#if EFI_UNIT_TEST - int unitTestTurnedOnCounter = 0; -#endif - - brain_pin_e brainPin = Gpio::Unassigned; - -#if (EFI_GPIO_HARDWARE && (BOARD_EXT_GPIOCHIPS > 0)) - /* used for external pins */ - bool ext = false; -#endif /* EFI_GPIO_HARDWARE */ - - int8_t currentLogicValue = INITIAL_PIN_STATE; - /** - * we track current pin status so that we do not touch the actual hardware if we want to write new pin bit - * which is same as current pin value. This maybe helps in case of status leds, but maybe it's a total over-engineering - */ -private: - // todo: inline this method? - void setDefaultPinState(const pin_output_mode_e *defaultState); - void setOnchipValue(int electricalValue); - - // 4 byte pointer is a bit of a memory waste here - const pin_output_mode_e *modePtr = nullptr; -}; - -/** - * OutputPin which is reported on Engine Sniffer - */ -class NamedOutputPin : public virtual OutputPin { -public: - NamedOutputPin(); - explicit NamedOutputPin(const char *name); - virtual void setHigh(); - virtual void setLow(); - const char *getName() const; - const char *getShortName() const; - /** - * @return true if pin was stopped - */ - bool stop(); - // todo: char pointer is a bit of a memory waste here, we can reduce RAM usage by software-based getName() method - const char *name = nullptr; - /** - * rusEfi Engine Sniffer protocol uses these short names to reduce bytes usage - */ - const char *shortName = nullptr; -}; - -void startSimultaneousInjection(void* = nullptr); -void endSimultaneousInjectionOnlyTogglePins(); - -class InjectorOutputPin final : public NamedOutputPin { -public: - InjectorOutputPin(); - void reset(); - - void open(efitick_t nowNt); - void close(efitick_t nowNt); - void setHigh() override; - void setLow() override; - - int8_t getOverlappingCounter() const { return overlappingCounter; } - - // todo: re-implement this injectorIndex via address manipulation to reduce memory usage? - int8_t injectorIndex; - -private: - int8_t overlappingCounter; -}; class IgnitionOutputPin : public NamedOutputPin { public: diff --git a/firmware/controllers/system/system.mk b/firmware/controllers/system/system.mk index 7df36135a6..507d8c71ef 100644 --- a/firmware/controllers/system/system.mk +++ b/firmware/controllers/system/system.mk @@ -1,5 +1,7 @@ SYSTEMSRC_CPP = \ + $(PROJECT_DIR)/controllers/system/efi_output.cpp \ + $(PROJECT_DIR)/controllers/system/injection_gpio.cpp \ $(PROJECT_DIR)/controllers/system/efi_gpio.cpp \ $(PROJECT_DIR)/controllers/system/periodic_task.cpp \ $(PROJECT_DIR)/controllers/system/dc_motor.cpp \ diff --git a/firmware/hw_layer/drivers/gpio/mc33810.h b/firmware/hw_layer/drivers/gpio/mc33810.h index f8a5a4f398..e1b9d7c44f 100644 --- a/firmware/hw_layer/drivers/gpio/mc33810.h +++ b/firmware/hw_layer/drivers/gpio/mc33810.h @@ -14,6 +14,7 @@ #include "efifeatures.h" #include +#include "rusefi_types.h" #define MC33810_OUTPUTS 8 #define MC33810_DIRECT_OUTPUTS 8