rusEFI
The most advanced open source ECU
Loading...
Searching...
No Matches
Public Member Functions | Data Fields | Private Member Functions | Private Attributes
OutputPin Class Reference

Single output pin reference and state. More...

#include <efi_output.h>

Inheritance diagram for OutputPin:
Inheritance graph
[legend]
Collaboration diagram for OutputPin:
Collaboration graph
[legend]

Public Member Functions

void initPin (const char *msg, brain_pin_e brainPin, pin_output_mode_e outputMode, bool forceInitWithFatalError=false)
 
void initPin (const char *msg, brain_pin_e brainPin)
 
void deInit ()
 
bool isInitialized () const
 
bool getAndSet (int logicValue)
 
void setValue (const char *msg, int logicValue, bool isForce=false)
 
TEST_VIRTUAL void setValue (int logicValue, bool isForce=false)
 
void toggle ()
 
bool getLogicValue () const
 
brain_pin_diag_e getDiag () const
 
void resetToggleStats ()
 

Data Fields

ioportid_t m_port = 0
 
uint8_t m_pin = 0
 
int pinToggleCounter = 0
 
Timer pinToggleTimer
 
uint32_t durationsInStateMs [2]
 
brain_pin_e brainPin = Gpio::Unassigned
 
bool ext = false
 
int8_t currentLogicValue = INITIAL_PIN_STATE
 

Private Member Functions

void setDefaultPinState (pin_output_mode_e mode)
 
void setOnchipValue (int electricalValue)
 

Private Attributes

pin_output_mode_e mode = OM_DEFAULT
 

Detailed Description

Single output pin reference and state.

Definition at line 49 of file efi_output.h.

Member Function Documentation

◆ deInit()

void OutputPin::deInit ( )

Definition at line 802 of file efi_gpio.cpp.

802 {
803 efiPrintf("unregistering %s", hwPortname(brainPin));
804
805 // Unregister under lock - we don't want other threads mucking with the pin while we're trying to turn it off
806 chibios_rt::CriticalSectionLocker csl;
807
808 // nothing to do if not registered in the first place
810 return;
811 }
812
813#if (BOARD_EXT_GPIOCHIPS > 0)
814 ext = false;
815#endif // (BOARD_EXT_GPIOCHIPS > 0)
816
817#if EFI_GPIO_HARDWARE && EFI_PROD_CODE
819#endif /* EFI_GPIO_HARDWARE */
820
821 // Clear the pin so that it won't get set any more
823}
brain_pin_e brainPin
Definition efi_output.h:86
@ Unassigned
void efiSetPadUnused(brain_pin_e brainPin)
Definition io_pins.cpp:20
const char * hwPortname(brain_pin_e brainPin)
bool isBrainPinValid(brain_pin_e brainPin)

Referenced by initPin(), luaDeInitPins(), stopTriggerEmulatorPins(), stopVvtControlPins(), and RegisteredOutputPin::unregister().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ getAndSet()

bool OutputPin::getAndSet ( int  logicValue)

Definition at line 575 of file efi_gpio.cpp.

575 {
576 bool oldValue = getLogicValue();
577 setValue(logicValue);
578 return oldValue;
579}
bool getLogicValue() const
Definition efi_gpio.cpp:667
void setValue(const char *msg, int logicValue, bool isForce=false)
Definition efi_gpio.cpp:604

Referenced by disengageStarterIfNeeded(), and doStartCranking().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ getDiag()

brain_pin_diag_e OutputPin::getDiag ( ) const

Definition at line 678 of file efi_gpio.cpp.

678 {
679#if EFI_PROD_CODE
680#if BOARD_EXT_GPIOCHIPS > 0
683 }
684#endif
685#endif /* EFI_PROD_CODE */
686 // TODO: add hook to board code for custom diagnostic, like it is done on S105
687 return PIN_UNKNOWN;
688}
brain_pin_diag_e gpiochips_getDiag(brain_pin_e pin)
Get diagnostic for given gpio.
Definition core.cpp:381
bool brain_pin_is_onchip(brain_pin_e brainPin)

Referenced by benchOff(), and SensorChecker::onSlowCallback().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ getLogicValue()

bool OutputPin::getLogicValue ( ) const

Definition at line 667 of file efi_gpio.cpp.

667 {
668 // Compare against 1 since it could also be INITIAL_PIN_STATE (which means logical 0, but we haven't initialized the pin yet)
669 return currentLogicValue == 1;
670}
int8_t currentLogicValue
Definition efi_output.h:93

Referenced by canDashboardHaltech(), configureRusefiLuaHooks(), getAndSet(), getHellenBoardEnabled(), IdleController::getIdlePosition(), IdleController::getRunningOpenLoop(), Engine::isMainRelayEnabled(), populateFrame(), slowStartStopButtonCallback(), NamedOutputPin::stop(), toggle(), updateFlags(), and updateTunerStudioState().

Here is the caller graph for this function:

◆ initPin() [1/2]

void OutputPin::initPin ( const char msg,
brain_pin_e  brainPin 
)

Definition at line 707 of file efi_gpio.cpp.

707 {
708 initPin(p_msg, p_brainPin, OM_DEFAULT);
709}
void initPin(const char *msg, brain_pin_e brainPin, pin_output_mode_e outputMode, bool forceInitWithFatalError=false)
Definition efi_gpio.cpp:711
Here is the call graph for this function:

◆ initPin() [2/2]

void OutputPin::initPin ( const char msg,
brain_pin_e  brainPin,
pin_output_mode_e  outputMode,
bool  forceInitWithFatalError = false 
)

Definition at line 711 of file efi_gpio.cpp.

711 {
712#if EFI_UNIT_TEST
714#endif
715
716 if (!isBrainPinValid(p_brainPin)) {
717 return;
718 }
719
720 // Enter a critical section so that other threads can't change the pin state out from underneath us
721 chibios_rt::CriticalSectionLocker csl;
722
723 if (!forceInitWithFatalError && hasFirmwareError()) {
724 // Don't allow initializing more pins if we have a fatal error.
725 // Pins should have just been reset, so we shouldn't try to init more.
726 return;
727 }
728
729 // Check that this OutputPin isn't already assigned to another pin (reinit is allowed to change mode)
730 // To avoid this error, call deInit() first
731 if (isBrainPinValid(brainPin) && brainPin != p_brainPin) {
732 firmwareError(ObdCode::CUSTOM_OBD_PIN_CONFLICT, "outputPin [%s] already assigned, cannot reassign without unregister first", msg);
733 return;
734 }
735
736 if (outputMode > OM_OPENDRAIN_INVERTED) {
737 firmwareError(ObdCode::CUSTOM_INVALID_MODE_SETTING, "%s invalid pin_output_mode_e %d %s",
738 msg,
739 outputMode,
740 hwPortname(p_brainPin)
741 );
742 return;
743 }
744
745#if EFI_GPIO_HARDWARE && EFI_PROD_CODE
746 iomode_t l_mode = (outputMode == OM_DEFAULT || outputMode == OM_INVERTED) ?
747 PAL_MODE_OUTPUT_PUSHPULL : PAL_MODE_OUTPUT_OPENDRAIN;
748
749 #if (BOARD_EXT_GPIOCHIPS > 0)
750 this->ext = false;
751 #endif
752 if (brain_pin_is_onchip(p_brainPin)) {
753 m_port = getHwPort(msg, p_brainPin);
754 m_pin = getHwPin(msg, p_brainPin);
755
756 // Validate port
757 if (!m_port) {
758 criticalError("OutputPin::initPin got invalid port for pin idx %d", static_cast<int>(p_brainPin));
759 return;
760 }
761 }
762 #if (BOARD_EXT_GPIOCHIPS > 0)
763 else {
764 this->ext = true;
765 }
766 #endif
767#endif // briefly leave the include guard because we need to set default state in tests
768
769 brainPin = p_brainPin;
770
771 // The order of the next two calls may look strange, which is a good observation.
772 // We call them in this order so that the pin is set to a known state BEFORE
773 // it's enabled. Enabling the pin then setting it could result in a (brief)
774 // mystery state being driven on the pin (potentially dangerous).
775 setDefaultPinState(outputMode);
776
777#if EFI_GPIO_HARDWARE && EFI_PROD_CODE
778 efiSetPadMode(msg, brainPin, l_mode);
780 // todo: handle OM_OPENDRAIN and OM_OPENDRAIN_INVERTED as well
781 if (outputMode == OM_DEFAULT || outputMode == OM_INVERTED) {
782#ifndef DISABLE_PIN_STATE_VALIDATION
783 int actualValue = palReadPad(m_port, m_pin);
784 // we had enough drama with pin configuration in board.h and else that we shall self-check
785
786 const int logicalValue =
787 (outputMode == OM_INVERTED)
788 ? !actualValue
789 : actualValue;
790
791 // if the pin was set to logical 1, then set an error and disable the pin so that things don't catch fire
792 if (logicalValue) {
793 criticalError("HARDWARE VALIDATION FAILED %s: unexpected startup pin state %s actual value=%d logical value=%d mode=%s", msg, hwPortname(brainPin), actualValue, logicalValue, getPin_output_mode_e(outputMode));
795 }
796#endif
797 }
798 }
799#endif /* EFI_GPIO_HARDWARE */
800}
const char * getPin_output_mode_e(pin_output_mode_e value)
void efiSetPadMode(const char *msg, brain_pin_e brainPin, iomode_t mode)
void deInit()
Definition efi_gpio.cpp:802
ioportid_t m_port
Definition efi_output.h:71
int pinToggleCounter
Definition efi_output.h:76
uint8_t m_pin
Definition efi_output.h:72
void setDefaultPinState(pin_output_mode_e mode)
Definition efi_gpio.cpp:672
ioportid_t getHwPort(const char *msg, brain_pin_e brainPin)
ioportmask_t getHwPin(const char *msg, brain_pin_e brainPin)
void firmwareError(ObdCode code, const char *fmt,...)
uint32_t iomode_t
Digital I/O modes.
Definition hal_pal_lld.h:83
@ CUSTOM_INVALID_MODE_SETTING
@ CUSTOM_OBD_PIN_CONFLICT

Referenced by alphax_2chan_boardInitHardware(), alphax_4chan_boardInitHardware(), alphax_4kGDI_boardInitHardware(), alphax_8chan_boardInitHardware(), alphax_8chan_reva_boardInitHardware(), alphax_gold_boardInitHardware(), alphax_silver_boardInitHardware(), alphax_silver_revA_boardInitHardware(), board_init_ext_gpios(), configureHellenCanTerminator(), hellen154hyundai_f7_boardInitHardware(), hellenMegaAccelerometerPreInitCS2Pin(), RegisteredOutputPin::init(), SimpleTransmissionController::init(), Generic4TransmissionController::init(), Gm4l6xTransmissionController::init(), initAccelerometer(), initErrorLed(), initGpPwm(), StepDirectionStepper::initialize(), initMiscOutputPins(), initPin(), initStatusLeds(), initWarningRunningPins(), nm_bus_init(), portInitAdc(), setHellenEnPin(), DcHardware::start(), EnginePins::startAuxValves(), EnginePins::startIgnitionPins(), EnginePins::startInjectionPins(), startSimplePwmExt(), startSmartCsPins(), and startTriggerEmulatorPins().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ isInitialized()

bool OutputPin::isInitialized ( ) const

Definition at line 559 of file efi_gpio.cpp.

559 {
560#if EFI_GPIO_HARDWARE && EFI_PROD_CODE
561#if (BOARD_EXT_GPIOCHIPS > 0)
562 if (ext)
563 return true;
564#endif /* (BOARD_EXT_GPIOCHIPS > 0) */
565 return m_port != NULL;
566#else /* EFI_GPIO_HARDWARE */
567 return true;
568#endif /* EFI_GPIO_HARDWARE */
569}

Referenced by assertPinAssigned(), hellenMegaAccelerometerPreInitCS2Pin(), initAccelerometer(), isGdiEngine(), HpfpController::onFastCallback(), HpfpController::scheduleNextCycle(), NamedOutputPin::stop(), and InjectionEvent::update().

Here is the caller graph for this function:

◆ resetToggleStats()

void OutputPin::resetToggleStats ( )

Definition at line 598 of file efi_gpio.cpp.

598 {
601}
uint32_t durationsInStateMs[2]
Definition efi_output.h:81

Referenced by resetPinStats().

Here is the caller graph for this function:

◆ setDefaultPinState()

void OutputPin::setDefaultPinState ( pin_output_mode_e  mode)
private

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

Definition at line 672 of file efi_gpio.cpp.

672 {
673 assertOMode(mode);
674 this->mode = outputMode;
675 setValue(false, /*force*/true); // initial state
676}
pin_output_mode_e mode
Definition efi_output.h:104

Referenced by initPin().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ setOnchipValue()

void OutputPin::setOnchipValue ( int  electricalValue)
private

Definition at line 583 of file efi_gpio.cpp.

583 {
585 // todo: make 'setOnchipValue' or 'reportsetOnchipValueError' virtual and override for NamedOutputPin?
586 warning(ObdCode::CUSTOM_ERR_6586, "attempting to change unassigned pin");
587 return;
588 }
589 palWritePad(m_port, m_pin, electricalValue);
590}
@ Invalid
bool warning(ObdCode code, const char *fmt,...)
@ CUSTOM_ERR_6586

Referenced by setValue().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ setValue() [1/2]

void OutputPin::setValue ( const char msg,
int  logicValue,
bool  isForce = false 
)

Definition at line 604 of file efi_gpio.cpp.

604 {
605 UNUSED(msg);
606 if ((isHwQcMode() || getOutputOnTheBenchTest() == this) && !isForce) {
607 return;
608 }
609
610#if ENABLE_PERF_TRACE
611// todo: https://github.com/rusefi/rusefi/issues/1638
612// ScopePerf perf(PE::OutputPinSetValue);
613#endif // ENABLE_PERF_TRACE
614
615#if EFI_UNIT_TEST
616 if (currentLogicValue != logicValue) {
618 }
619#endif // EFI_UNIT_TEST
620
621#if EFI_SIMULATOR
622 if (currentLogicValue != logicValue) {
623 if (pinToggleCounter > 0) {
625 durationsInStateMs[1] = pinToggleTimer.getElapsedUs() / 1000;
626 }
628 pinToggleTimer.reset();
629 }
630#endif // EFI_SIMULATOR
631
632#if EFI_UNIT_TEST
633 if (verboseMode) {
634 efiPrintf("pin goes %d", logicValue);
635 }
636#endif // EFI_UNIT_TEST
637
638 // Always store the current logical value of the pin (so it can be
639 // used internally even if not connected to a real hardware pin)
640 currentLogicValue = logicValue;
641
642 // Nothing else to do if not configured
644 return;
645 }
646
647 efiAssertVoid(ObdCode::CUSTOM_ERR_6622, mode <= OM_OPENDRAIN_INVERTED, "invalid pin_output_mode_e");
648 int electricalValue = getElectricalValue(logicValue, mode);
649
650#if EFI_PROD_CODE
651 #if (BOARD_EXT_GPIOCHIPS > 0)
652 if (!this->ext) {
653 setOnchipValue(electricalValue);
654 } else {
655 /* external pin */
656 gpiochips_writePad(this->brainPin, logicValue);
657 /* TODO: check return value */
658 }
659 #else
660 setOnchipValue(electricalValue);
661 #endif
662#else /* EFI_PROD_CODE */
663 setMockState(brainPin, electricalValue);
664#endif /* EFI_PROD_CODE */
665}
const OutputPin * getOutputOnTheBenchTest()
bool isHwQcMode()
Timer pinToggleTimer
Definition efi_output.h:80
void setOnchipValue(int electricalValue)
Definition efi_gpio.cpp:583
int gpiochips_writePad(brain_pin_e pin, int value)
Set value to gpio of gpiochip.
Definition core.cpp:336
void setMockState(brain_pin_e pin, bool state)
Definition io_pins.cpp:132
UNUSED(samplingTimeSeconds)
@ CUSTOM_ERR_6622
bool verboseMode

Referenced by alphax_4kGDI_boardInitHardware(), applyPinState(), PwmConfig::applyPwmValue(), benchOff(), benchOn(), blink_digits(), board_init_ext_gpios(), boardOnConfigurationChange(), configureHellenCanTerminator(), TwoPinDcMotor::disable(), TwoPinDcMotor::enable(), errorHandlerWriteReportFile(), firmwareErrorV(), getAndSet(), hellen154hyundai_f7_boardInitHardware(), hellenMegaAccelerometerPreInitCS2Pin(), StepDirectionStepper::initialize(), nm_bus_init(), AcController::onSlowCallback(), HarleyAcr::onSlowCallback(), MainRelayController::onSlowCallback(), NitrousController::onSlowCallback(), FuelPumpController::onSlowCallback(), VvlController::onSlowCallback(), Engine::OnTriggerSynchronization(), Engine::periodicSlowCallback(), StepDirectionStepper::pulse(), readSlowAnalogInputs(), InjectorOutputPin::reset(), TwoPinDcMotor::set(), setDefaultPinState(), StepDirectionStepper::setDirection(), setHellenEnValue(), NamedOutputPin::setHigh(), NamedOutputPin::setLow(), GppwmChannel::setOutput(), PwmWrapper::setSimplePwmDutyCycle(), Generic4TransmissionController::setTccState(), setValue(), slowAdcEndCB(), DcHardware::start(), startSmartCsPins(), NamedOutputPin::stop(), toggle(), turnAllPinsOff(), and SimpleTransmissionController::update().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ setValue() [2/2]

void OutputPin::setValue ( int  logicValue,
bool  isForce = false 
)

Definition at line 593 of file efi_gpio.cpp.

593 {
594 setValue(nullptr, logicValue, isForce);
595}
Here is the call graph for this function:

◆ toggle()

void OutputPin::toggle ( )

Definition at line 571 of file efi_gpio.cpp.

571 {
572 setValue("toggle", !getLogicValue());
573}

Referenced by TriggerDecoderBase::decodeTriggerEvent().

Here is the call graph for this function:
Here is the caller graph for this function:

Field Documentation

◆ brainPin

brain_pin_e OutputPin::brainPin = Gpio::Unassigned

◆ currentLogicValue

int8_t OutputPin::currentLogicValue = INITIAL_PIN_STATE

◆ durationsInStateMs

uint32_t OutputPin::durationsInStateMs[2]

Definition at line 81 of file efi_output.h.

Referenced by resetToggleStats(), runBench(), and setValue().

◆ ext

bool OutputPin::ext = false

Definition at line 90 of file efi_output.h.

Referenced by deInit(), initPin(), isInitialized(), and setValue().

◆ m_pin

uint8_t OutputPin::m_pin = 0

Definition at line 72 of file efi_output.h.

Referenced by initPin(), nm_bus_init(), and setOnchipValue().

◆ m_port

ioportid_t OutputPin::m_port = 0

Definition at line 71 of file efi_output.h.

Referenced by initPin(), isInitialized(), nm_bus_init(), and setOnchipValue().

◆ mode

pin_output_mode_e OutputPin::mode = OM_DEFAULT
private

Definition at line 104 of file efi_output.h.

Referenced by setDefaultPinState(), and setValue().

◆ pinToggleCounter

int OutputPin::pinToggleCounter = 0

Definition at line 76 of file efi_output.h.

Referenced by initPin(), resetToggleStats(), runBench(), and setValue().

◆ pinToggleTimer

Timer OutputPin::pinToggleTimer

Definition at line 80 of file efi_output.h.

Referenced by setValue().


The documentation for this class was generated from the following files: