rusEFI
The most advanced open source ECU
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 50 of file efi_output.h.

Member Function Documentation

◆ deInit()

void OutputPin::deInit ( )

Definition at line 780 of file efi_gpio.cpp.

780  {
781  // Unregister under lock - we don't want other threads mucking with the pin while we're trying to turn it off
782  chibios_rt::CriticalSectionLocker csl;
783 
784  // nothing to do if not registered in the first place
785  if (!isBrainPinValid(brainPin)) {
786  return;
787  }
788 
789 #if (BOARD_EXT_GPIOCHIPS > 0)
790  ext = false;
791 #endif // (BOARD_EXT_GPIOCHIPS > 0)
792 
793  efiPrintf("unregistering %s", hwPortname(brainPin));
794 
795 #if EFI_GPIO_HARDWARE && EFI_PROD_CODE
797 #endif /* EFI_GPIO_HARDWARE */
798 
799  // Clear the pin so that it won't get set any more
801 }
bool ext
Definition: efi_output.h:91
brain_pin_e brainPin
Definition: efi_output.h:87
@ 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(), stopHip9011_pins(), 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 552 of file efi_gpio.cpp.

552  {
553  bool oldValue = getLogicValue();
554  setValue(logicValue);
555  return oldValue;
556 }
bool getLogicValue() const
Definition: efi_gpio.cpp:645
void setValue(const char *msg, int logicValue, bool isForce=false)
Definition: efi_gpio.cpp:581

Referenced by disengageStarterIfNeeded(), and onStartStopButtonToggle().

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 656 of file efi_gpio.cpp.

656  {
657 #if EFI_PROD_CODE
658 #if BOARD_EXT_GPIOCHIPS > 0
660  return gpiochips_getDiag(brainPin);
661  }
662 #endif
663 #endif /* EFI_PROD_CODE */
664  // TODO: add hook to board code for custom diagnostic, like it is done on S105
665  return PIN_UNKNOWN;
666 }
brain_pin_diag_e gpiochips_getDiag(brain_pin_e pin)
Get diagnostic for given gpio.
Definition: core.cpp:373
bool brain_pin_is_onchip(brain_pin_e brainPin)

Referenced by benchOff().

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

◆ getLogicValue()

bool OutputPin::getLogicValue ( ) const

Definition at line 645 of file efi_gpio.cpp.

645  {
646  // Compare against 1 since it could also be INITIAL_PIN_STATE (which means logical 0, but we haven't initialized the pin yet)
647  return currentLogicValue == 1;
648 }
int8_t currentLogicValue
Definition: efi_output.h:94

Referenced by canDashboardHaltech(), getAndSet(), getHellenBoardEnabled(), IdleController::getRunningOpenLoop(), Engine::isMainRelayEnabled(), lua_fan(), 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 685 of file efi_gpio.cpp.

685  {
686  initPin(p_msg, p_brainPin, OM_DEFAULT);
687 }
void initPin(const char *msg, brain_pin_e brainPin, pin_output_mode_e outputMode, bool forceInitWithFatalError=false)
Definition: efi_gpio.cpp:689
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 689 of file efi_gpio.cpp.

689  {
690 #if EFI_UNIT_TEST
691  pinToggleCounter = 0;
692 #endif
693 
694  if (!isBrainPinValid(p_brainPin)) {
695  return;
696  }
697 
698  // Enter a critical section so that other threads can't change the pin state out from underneath us
699  chibios_rt::CriticalSectionLocker csl;
700 
701  if (!forceInitWithFatalError && hasFirmwareError()) {
702  // Don't allow initializing more pins if we have a fatal error.
703  // Pins should have just been reset, so we shouldn't try to init more.
704  return;
705  }
706 
707  // Check that this OutputPin isn't already assigned to another pin (reinit is allowed to change mode)
708  // To avoid this error, call deInit() first
709  if (isBrainPinValid(brainPin) && brainPin != p_brainPin) {
710  firmwareError(ObdCode::CUSTOM_OBD_PIN_CONFLICT, "outputPin [%s] already assigned, cannot reassign without unregister first", msg);
711  return;
712  }
713 
714  if (outputMode > OM_OPENDRAIN_INVERTED) {
715  firmwareError(ObdCode::CUSTOM_INVALID_MODE_SETTING, "%s invalid pin_output_mode_e %d %s",
716  msg,
717  outputMode,
718  hwPortname(p_brainPin)
719  );
720  return;
721  }
722 
723 #if EFI_GPIO_HARDWARE && EFI_PROD_CODE
724  iomode_t l_mode = (outputMode == OM_DEFAULT || outputMode == OM_INVERTED) ?
725  PAL_MODE_OUTPUT_PUSHPULL : PAL_MODE_OUTPUT_OPENDRAIN;
726 
727  #if (BOARD_EXT_GPIOCHIPS > 0)
728  this->ext = false;
729  #endif
730  if (brain_pin_is_onchip(p_brainPin)) {
731  m_port = getHwPort(msg, p_brainPin);
732  m_pin = getHwPin(msg, p_brainPin);
733 
734  // Validate port
735  if (m_port == GPIO_NULL) {
736  criticalError("OutputPin::initPin got invalid port for pin idx %d", static_cast<int>(p_brainPin));
737  return;
738  }
739  }
740  #if (BOARD_EXT_GPIOCHIPS > 0)
741  else {
742  this->ext = true;
743  }
744  #endif
745 #endif // briefly leave the include guard because we need to set default state in tests
746 
747  brainPin = p_brainPin;
748 
749  // The order of the next two calls may look strange, which is a good observation.
750  // We call them in this order so that the pin is set to a known state BEFORE
751  // it's enabled. Enabling the pin then setting it could result in a (brief)
752  // mystery state being driven on the pin (potentially dangerous).
753  setDefaultPinState(outputMode);
754 
755 #if EFI_GPIO_HARDWARE && EFI_PROD_CODE
756  efiSetPadMode(msg, brainPin, l_mode);
758  // todo: handle OM_OPENDRAIN and OM_OPENDRAIN_INVERTED as well
759  if (outputMode == OM_DEFAULT || outputMode == OM_INVERTED) {
760 #ifndef DISABLE_PIN_STATE_VALIDATION
761  int actualValue = palReadPad(m_port, m_pin);
762  // we had enough drama with pin configuration in board.h and else that we shall self-check
763 
764  const int logicalValue =
765  (outputMode == OM_INVERTED)
766  ? !actualValue
767  : actualValue;
768 
769  // if the pin was set to logical 1, then set an error and disable the pin so that things don't catch fire
770  if (logicalValue) {
771  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));
773  }
774 #endif
775  }
776  }
777 #endif /* EFI_GPIO_HARDWARE */
778 }
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:780
ioportid_t m_port
Definition: efi_output.h:72
int pinToggleCounter
Definition: efi_output.h:77
uint8_t m_pin
Definition: efi_output.h:73
void setDefaultPinState(pin_output_mode_e mode)
Definition: efi_gpio.cpp:650
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 board_init_ext_gpios(), boardInitHardware(), configureHellenCanTerminator(), 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(), startHip9011_pins(), 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 536 of file efi_gpio.cpp.

536  {
537 #if EFI_GPIO_HARDWARE && EFI_PROD_CODE
538 #if (BOARD_EXT_GPIOCHIPS > 0)
539  if (ext)
540  return true;
541 #endif /* (BOARD_EXT_GPIOCHIPS > 0) */
542  return m_port != NULL;
543 #else /* EFI_GPIO_HARDWARE */
544  return true;
545 #endif /* EFI_GPIO_HARDWARE */
546 }

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 575 of file efi_gpio.cpp.

575  {
577  pinToggleCounter = 0;
578 }
uint32_t durationsInStateMs[2]
Definition: efi_output.h:82

◆ 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 650 of file efi_gpio.cpp.

650  {
651  assertOMode(mode);
652  this->mode = outputMode;
653  setValue(false, /*force*/true); // initial state
654 }
pin_output_mode_e mode
Definition: efi_output.h:105

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 560 of file efi_gpio.cpp.

560  {
562  // todo: make 'setOnchipValue' or 'reportsetOnchipValueError' virtual and override for NamedOutputPin?
563  warning(ObdCode::CUSTOM_ERR_6586, "attempting to change unassigned pin");
564  return;
565  }
566  palWritePad(m_port, m_pin, electricalValue);
567 }
@ 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 581 of file efi_gpio.cpp.

581  {
582 extern bool qcDirectPinControlMode;
583  UNUSED(msg);
584  if ((qcDirectPinControlMode || getOutputOnTheBenchTest() == this) && !isForce) {
585  return;
586  }
587 
588 #if ENABLE_PERF_TRACE
589 // todo: https://github.com/rusefi/rusefi/issues/1638
590 // ScopePerf perf(PE::OutputPinSetValue);
591 #endif // ENABLE_PERF_TRACE
592 
593 #if EFI_UNIT_TEST
594  if (currentLogicValue != logicValue) {
596  }
597 #endif // EFI_UNIT_TEST
598 
599 #if EFI_SIMULATOR
600  if (currentLogicValue != logicValue) {
601  if (pinToggleCounter > 0) {
603  durationsInStateMs[1] = pinToggleTimer.getElapsedUs() / 1000;
604  }
606  pinToggleTimer.reset();
607  }
608 #endif // EFI_SIMULATOR
609 
610 #if EFI_UNIT_TEST
611  if (verboseMode) {
612  efiPrintf("pin goes %d", logicValue);
613  }
614 #endif // EFI_UNIT_TEST
615 
616  // Always store the current logical value of the pin (so it can be
617  // used internally even if not connected to a real hardware pin)
618  currentLogicValue = logicValue;
619 
620  // Nothing else to do if not configured
621  if (!isBrainPinValid(brainPin)) {
622  return;
623  }
624 
625  efiAssertVoid(ObdCode::CUSTOM_ERR_6622, mode <= OM_OPENDRAIN_INVERTED, "invalid pin_output_mode_e");
626  int electricalValue = getElectricalValue(logicValue, mode);
627 
628 #if EFI_PROD_CODE
629  #if (BOARD_EXT_GPIOCHIPS > 0)
630  if (!this->ext) {
631  setOnchipValue(electricalValue);
632  } else {
633  /* external pin */
634  gpiochips_writePad(this->brainPin, logicValue);
635  /* TODO: check return value */
636  }
637  #else
638  setOnchipValue(electricalValue);
639  #endif
640 #else /* EFI_PROD_CODE */
641  setMockState(brainPin, electricalValue);
642 #endif /* EFI_PROD_CODE */
643 }
const OutputPin * getOutputOnTheBenchTest()
Definition: bench_test.cpp:32
bool qcDirectPinControlMode
Timer pinToggleTimer
Definition: efi_output.h:81
void setOnchipValue(int electricalValue)
Definition: efi_gpio.cpp:560
int gpiochips_writePad(brain_pin_e pin, int value)
Set value to gpio of gpiochip.
Definition: core.cpp:335
bool verboseMode
void setMockState(brain_pin_e pin, bool state)
Definition: io_pins.cpp:129
UNUSED(samplingTimeSeconds)
@ CUSTOM_ERR_6622

Referenced by applyPinState(), PwmConfig::applyPwmValue(), benchOff(), benchOn(), blink_digits(), board_init_ext_gpios(), boardInitHardware(), boardOnConfigurationChange(), configureHellenCanTerminator(), TwoPinDcMotor::disable(), TwoPinDcMotor::enable(), firmwareError(), getAndSet(), hellenDisableEn(), hellenEnableEn(), hellenMegaAccelerometerPreInitCS2Pin(), hipThread(), StepDirectionStepper::initialize(), nm_bus_init(), AcController::onSlowCallback(), FuelPumpController::onSlowCallback(), HarleyAcr::onSlowCallback(), MainRelayController::onSlowCallback(), Engine::OnTriggerSynchronization(), Engine::periodicSlowCallback(), StepDirectionStepper::pulse(), readSlowAnalogInputs(), InjectorOutputPin::reset(), TwoPinDcMotor::set(), setDefaultPinState(), StepDirectionStepper::setDirection(), NamedOutputPin::setHigh(), NamedOutputPin::setLow(), GppwmChannel::setOutput(), PwmWrapper::setSimplePwmDutyCycle(), Generic4TransmissionController::setTccState(), setValue(), DcHardware::start(), startHip9011_pins(), 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 570 of file efi_gpio.cpp.

570  {
571  setValue(nullptr, logicValue, isForce);
572 }
Here is the call graph for this function:

◆ toggle()

void OutputPin::toggle ( )

Definition at line 548 of file efi_gpio.cpp.

548  {
549  setValue("toggle", !getLogicValue());
550 }

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

Definition at line 87 of file efi_output.h.

Referenced by deInit(), getDiag(), initPin(), runBench(), setOnchipValue(), setValue(), and startSimplePwm().

◆ currentLogicValue

int8_t OutputPin::currentLogicValue = INITIAL_PIN_STATE

◆ durationsInStateMs

uint32_t OutputPin::durationsInStateMs[2]

Definition at line 82 of file efi_output.h.

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

◆ ext

bool OutputPin::ext = false

Definition at line 91 of file efi_output.h.

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

◆ m_pin

uint8_t OutputPin::m_pin = 0

Definition at line 73 of file efi_output.h.

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

◆ m_port

ioportid_t OutputPin::m_port = 0

Definition at line 72 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 105 of file efi_output.h.

Referenced by setDefaultPinState(), and setValue().

◆ pinToggleCounter

int OutputPin::pinToggleCounter = 0

Definition at line 77 of file efi_output.h.

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

◆ pinToggleTimer

Timer OutputPin::pinToggleTimer

Definition at line 81 of file efi_output.h.

Referenced by setValue().


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