2015-07-10 06:01:56 -07:00
/**
2019-03-29 06:11:13 -07:00
* @ file efi_gpio . cpp
2017-04-21 10:36:51 -07:00
* @ brief EFI - related GPIO code
2015-07-10 06:01:56 -07:00
*
* @ date Sep 26 , 2014
2020-01-13 18:57:43 -08:00
* @ author Andrey Belomutskiy , ( c ) 2012 - 2020
2015-07-10 06:01:56 -07:00
*/
2021-07-25 22:05:17 -07:00
# include "pch.h"
2023-10-16 13:04:21 -07:00
# include "bench_test.h"
2022-10-29 18:55:05 -07:00
# include "engine_sniffer.h"
2022-09-07 12:56:45 -07:00
2019-04-10 05:43:54 -07:00
# include "drivers/gpio/gpio_ext.h"
2015-07-10 06:01:56 -07:00
2022-01-16 20:03:14 -08:00
# if HW_HELLEN
# include "hellen_meta.h"
# endif // HW_HELLEN
2019-03-10 09:58:27 -07:00
# if EFI_ELECTRONIC_THROTTLE_BODY
# include "electronic_throttle.h"
# endif /* EFI_ELECTRONIC_THROTTLE_BODY */
2017-04-21 13:36:50 -07:00
// todo: clean this mess, this should become 'static'/private
EnginePins enginePins ;
2021-07-09 14:05:16 -07:00
static const char * const sparkNames [ ] = { " Coil 1 " , " Coil 2 " , " Coil 3 " , " Coil 4 " , " Coil 5 " , " Coil 6 " , " Coil 7 " , " Coil 8 " ,
2020-03-29 16:07:07 -07:00
" Coil 9 " , " Coil 10 " , " Coil 11 " , " Coil 12 " } ;
2019-05-15 01:26:41 -07:00
2021-07-09 14:05:16 -07:00
static const char * const trailNames [ ] = { " Trail 1 " , " Trail 2 " , " Trail 3 " , " Trail 4 " , " Trail 5 " , " Trail 6 " , " Trail 7 " , " Trail 8 " ,
2021-07-09 07:14:00 -07:00
" Trail 9 " , " Trail 10 " , " Trail 11 " , " Trail 12 " } ;
2021-07-21 17:51:36 -07:00
static const char * const trailShortNames [ ] = { " r1 " , " r2 " , " r3 " , " r4 " , " r5 " , " r6 " , " r7 " , " r8 " , " r9 " , " rA " , " rB " , " rD " } ;
2021-07-09 12:51:30 -07:00
2021-04-25 06:18:35 -07:00
const char * vvtNames [ ] = {
PROTOCOL_VVT1_NAME ,
PROTOCOL_VVT2_NAME ,
PROTOCOL_VVT3_NAME ,
PROTOCOL_VVT4_NAME } ;
2022-09-10 20:33:37 -07:00
const char * laNames [ ] = {
PROTOCOL_WA_CHANNEL_1 ,
PROTOCOL_WA_CHANNEL_2 ,
PROTOCOL_WA_CHANNEL_3 ,
PROTOCOL_WA_CHANNEL_4 } ;
2019-05-15 01:26:41 -07:00
// these short names are part of engine sniffer protocol
2021-07-09 14:05:16 -07:00
static const char * const sparkShortNames [ ] = { PROTOCOL_COIL1_SHORT_NAME , " c2 " , " c3 " , " c4 " , " c5 " , " c6 " , " c7 " , " c8 " ,
2016-09-27 08:01:57 -07:00
" c9 " , " cA " , " cB " , " cD " } ;
2021-07-09 14:05:16 -07:00
static const char * const injectorNames [ ] = { " Injector 1 " , " Injector 2 " , " Injector 3 " , " Injector 4 " , " Injector 5 " , " Injector 6 " ,
2020-03-29 16:07:07 -07:00
" Injector 7 " , " Injector 8 " , " Injector 9 " , " Injector 10 " , " Injector 11 " , " Injector 12 " } ;
2019-05-15 01:26:41 -07:00
2021-07-09 14:05:16 -07:00
static const char * const injectorShortNames [ ] = { PROTOCOL_INJ1_SHORT_NAME , " i2 " , " i3 " , " i4 " , " i5 " , " i6 " , " i7 " , " i8 " ,
2024-01-07 10:36:14 -08:00
" i9 " , " iA " , " iB " , " iC " } ;
2016-09-27 08:01:57 -07:00
2024-01-07 16:08:52 -08:00
static const char * const injectorStage2Names [ ] = { " Injector Second Stage 1 " , " Injector Second Stage 2 " , " Injector Second Stage 3 " , " Injector Second Stage 4 " , " Injector Second Stage 5 " , " Injector Second Stage 6 " ,
" Injector Second Stage 7 " , " Injector Second Stage 8 " , " Injector Second Stage 9 " , " Injector Second Stage 10 " , " Injector Second Stage 11 " , " Injector Second Stage 12 " } ;
static const char * const injectorStage2ShortNames [ ] = { PROTOCOL_INJ1_STAGE2_SHORT_NAME , " j2 " , " j3 " , " j4 " , " j5 " , " j6 " , " j7 " , " j8 " ,
" j9 " , " jA " , " jB " , " jC " } ;
2021-07-09 14:05:16 -07:00
static const char * const auxValveShortNames [ ] = { " a1 " , " a2 " } ;
2017-11-26 19:30:37 -08:00
2020-09-17 16:41:28 -07:00
static RegisteredOutputPin * registeredOutputHead = nullptr ;
2020-09-17 16:35:43 -07:00
2023-11-01 07:51:22 -07:00
RegisteredNamedOutputPin : : RegisteredNamedOutputPin ( const char * p_name , size_t pinOffset ,
size_t pinModeOffset ) : RegisteredOutputPin ( p_name , pinOffset , pinModeOffset ) {
2020-11-09 18:10:48 -08:00
}
2023-11-01 07:51:22 -07:00
RegisteredNamedOutputPin : : RegisteredNamedOutputPin ( const char * p_name , size_t pinOffset ) :
RegisteredOutputPin ( p_name , pinOffset ) {
2023-10-31 05:56:16 -07:00
}
2023-11-01 07:51:22 -07:00
RegisteredOutputPin : : RegisteredOutputPin ( const char * p_registrationName , size_t pinOffset ,
2022-10-23 05:25:47 -07:00
size_t pinModeOffset )
: next ( registeredOutputHead )
2023-11-01 07:51:22 -07:00
, registrationName ( p_registrationName )
2022-10-23 05:25:47 -07:00
, m_pinOffset ( static_cast < uint16_t > ( pinOffset ) )
2023-06-05 07:23:20 -07:00
, m_hasPinMode ( true )
2022-10-23 05:25:47 -07:00
, m_pinModeOffset ( static_cast < uint16_t > ( pinModeOffset ) )
2023-06-05 07:23:20 -07:00
{
// adding into head of the list is so easy and since we do not care about order that's what we shall do
registeredOutputHead = this ;
}
2023-11-01 07:51:22 -07:00
RegisteredOutputPin : : RegisteredOutputPin ( const char * p_registrationName , size_t pinOffset )
2023-06-05 07:23:20 -07:00
: next ( registeredOutputHead )
2023-11-01 07:51:22 -07:00
, registrationName ( p_registrationName )
2023-06-05 07:23:20 -07:00
, m_pinOffset ( static_cast < uint16_t > ( pinOffset ) )
, m_hasPinMode ( false )
, m_pinModeOffset ( - 1 )
{
2020-09-17 16:41:28 -07:00
// adding into head of the list is so easy and since we do not care about order that's what we shall do
registeredOutputHead = this ;
2020-09-17 16:35:43 -07:00
}
2020-11-05 14:23:09 -08:00
bool RegisteredOutputPin : : isPinConfigurationChanged ( ) {
2020-09-18 10:29:17 -07:00
# if EFI_PROD_CODE
2022-10-23 05:25:47 -07:00
brain_pin_e curPin = * ( brain_pin_e * ) ( ( void * ) ( & ( ( char * ) & activeConfiguration ) [ m_pinOffset ] ) ) ;
brain_pin_e newPin = * ( brain_pin_e * ) ( ( void * ) ( & ( ( char * ) engineConfiguration ) [ m_pinOffset ] ) ) ;
2023-06-05 07:23:20 -07:00
bool pinChanged = curPin ! = newPin ;
2020-09-18 10:01:09 -07:00
2023-06-05 07:23:20 -07:00
if ( ! m_hasPinMode ) {
return pinChanged ;
}
pin_output_mode_e curMode = * ( pin_output_mode_e * ) ( ( void * ) ( & ( ( char * ) & activeConfiguration ) [ m_pinModeOffset ] ) ) ;
pin_output_mode_e newMode = * ( pin_output_mode_e * ) ( ( void * ) ( & ( ( char * ) engineConfiguration ) [ m_pinModeOffset ] ) ) ;
return pinChanged | | curMode ! = newMode ;
2020-11-05 14:23:09 -08:00
# else
2020-11-18 19:47:40 -08:00
return true ;
2020-11-05 14:23:09 -08:00
# endif // EFI_PROD_CODE
}
2020-09-17 16:35:43 -07:00
2021-11-16 01:15:29 -08:00
void RegisteredOutputPin : : init ( ) {
2022-10-23 05:25:47 -07:00
brain_pin_e newPin = * ( brain_pin_e * ) ( ( void * ) ( & ( ( char * ) engineConfiguration ) [ m_pinOffset ] ) ) ;
2023-06-05 07:23:20 -07:00
2023-02-25 00:31:12 -08:00
pin_output_mode_e newMode ;
2023-06-05 07:23:20 -07:00
if ( m_hasPinMode ) {
2023-02-25 00:31:12 -08:00
newMode = * ( pin_output_mode_e * ) ( ( void * ) ( & ( ( char * ) engineConfiguration ) [ m_pinModeOffset ] ) ) ;
2023-06-05 07:23:20 -07:00
} else {
2023-02-25 00:31:12 -08:00
newMode = OM_DEFAULT ;
2023-06-05 07:23:20 -07:00
}
2020-11-05 14:23:09 -08:00
if ( isPinConfigurationChanged ( ) ) {
2020-11-09 18:10:48 -08:00
this - > initPin ( registrationName , newPin , newMode ) ;
2020-11-05 14:23:09 -08:00
}
}
void RegisteredOutputPin : : unregister ( ) {
2020-12-18 14:18:12 -08:00
if ( isPinConfigurationChanged ( ) ) {
OutputPin : : deInit ( ) ;
}
2020-09-18 10:01:09 -07:00
}
2020-09-17 16:35:43 -07:00
2022-10-23 13:39:18 -07:00
# define CONFIG_OFFSET(x) (offsetof(engine_configuration_s, x))
2020-09-26 02:04:27 -07:00
// todo: pin and pinMode should be combined into a composite entity
// todo: one of the impediments is code generator hints handling (we need custom hints and those are not handled nice for fields of structs?)
# define CONFIG_PIN_OFFSETS(x) CONFIG_OFFSET(x##Pin), CONFIG_OFFSET(x##PinMode)
2022-10-23 13:39:18 -07:00
// offset of X within engineConfiguration, plus offset of Y within X
// decltype(engine_configuration_s::x) resolves the typename of the struct X inside engineConfiguration
# define CONFIG_OFFSET2(x, y) (offsetof(engine_configuration_s, x) + offsetof(decltype(engine_configuration_s::x), y))
# define CONFIG_PIN_OFFSETS2(x, y) CONFIG_OFFSET2(x, y##Pin), CONFIG_OFFSET2(x, y##PinMode)
2020-09-26 02:04:27 -07:00
2020-09-17 16:35:43 -07:00
EnginePins : : EnginePins ( ) :
2020-12-17 14:00:00 -08:00
mainRelay ( " Main Relay " , CONFIG_PIN_OFFSETS ( mainRelay ) ) ,
hpfpValve ( " HPFP Valve " , CONFIG_PIN_OFFSETS ( hpfpValve ) ) ,
starterControl ( " Starter Relay " , CONFIG_PIN_OFFSETS ( starterControl ) ) ,
starterRelayDisable ( " Starter Disable Relay " , CONFIG_PIN_OFFSETS ( starterRelayDisable ) ) ,
fanRelay ( " Fan Relay " , CONFIG_PIN_OFFSETS ( fan ) ) ,
2021-06-13 05:06:45 -07:00
fanRelay2 ( " Fan Relay 2 " , CONFIG_PIN_OFFSETS ( fan2 ) ) ,
2020-12-17 14:00:00 -08:00
acRelay ( " A/C Relay " , CONFIG_PIN_OFFSETS ( acRelay ) ) ,
fuelPumpRelay ( " Fuel pump Relay " , CONFIG_PIN_OFFSETS ( fuelPump ) ) ,
2023-10-31 05:56:16 -07:00
# if EFI_HD_ACR
2023-02-25 00:13:51 -08:00
harleyAcr ( " Harley ACR " , CONFIG_OFFSET ( acrPin ) ) ,
2023-03-05 18:19:57 -08:00
harleyAcr2 ( " Harley ACR 2 " , CONFIG_OFFSET ( acrPin2 ) ) ,
2023-10-31 05:56:16 -07:00
# endif // EFI_HD_ACR
2023-02-25 00:13:51 -08:00
boostPin ( " Boost " , CONFIG_PIN_OFFSETS ( boostControl ) ) ,
2022-10-23 13:39:18 -07:00
idleSolenoidPin ( " Idle Valve " , CONFIG_OFFSET2 ( idle , solenoidPin ) , CONFIG_OFFSET2 ( idle , solenoidPinMode ) ) ,
secondIdleSolenoidPin ( " Idle Valve#2 " , CONFIG_OFFSET ( secondSolenoidPin ) , CONFIG_OFFSET2 ( idle , solenoidPinMode ) ) ,
2020-11-05 14:23:09 -08:00
alternatorPin ( " Alternator control " , CONFIG_PIN_OFFSETS ( alternatorControl ) ) ,
2020-09-27 04:22:09 -07:00
checkEnginePin ( " checkEnginePin " , CONFIG_PIN_OFFSETS ( malfunctionIndicator ) ) ,
2020-11-09 18:10:48 -08:00
tachOut ( " tachOut " , CONFIG_PIN_OFFSETS ( tachOutput ) ) ,
2023-10-15 14:59:39 -07:00
triggerDecoderErrorPin ( " led: trigger debug " , CONFIG_PIN_OFFSETS ( triggerError ) ) ,
speedoOut ( " speedoOut " , CONFIG_OFFSET ( speedometerOutputPin ) )
2020-09-17 16:35:43 -07:00
{
2023-11-01 14:54:57 -07:00
hpfpValve . setName ( PROTOCOL_HPFP_NAME ) ;
2023-10-31 05:56:16 -07:00
# if EFI_HD_ACR
2023-11-01 14:54:57 -07:00
harleyAcr . setName ( PROTOCOL_ACR_NAME ) ;
2023-10-31 05:56:16 -07:00
# endif // EFI_HD_ACR
2016-09-27 08:01:57 -07:00
2021-07-06 17:14:08 -07:00
static_assert ( efi : : size ( sparkNames ) > = MAX_CYLINDER_COUNT , " Too many ignition pins " ) ;
2021-07-09 07:14:00 -07:00
static_assert ( efi : : size ( trailNames ) > = MAX_CYLINDER_COUNT , " Too many ignition pins " ) ;
2021-07-06 17:14:08 -07:00
static_assert ( efi : : size ( injectorNames ) > = MAX_CYLINDER_COUNT , " Too many injection pins " ) ;
for ( int i = 0 ; i < MAX_CYLINDER_COUNT ; i + + ) {
2022-09-05 16:49:27 -07:00
enginePins . coils [ i ] . coilIndex = i ;
2023-11-01 14:54:57 -07:00
enginePins . coils [ i ] . setName ( sparkNames [ i ] ) ;
2019-05-15 01:26:41 -07:00
enginePins . coils [ i ] . shortName = sparkShortNames [ i ] ;
2019-11-13 05:42:16 -08:00
2023-11-01 14:54:57 -07:00
enginePins . trailingCoils [ i ] . setName ( trailNames [ i ] ) ;
2021-07-09 12:51:30 -07:00
enginePins . trailingCoils [ i ] . shortName = trailShortNames [ i ] ;
2021-07-09 07:14:00 -07:00
2016-11-30 15:02:19 -08:00
enginePins . injectors [ i ] . injectorIndex = i ;
2023-11-01 14:54:57 -07:00
enginePins . injectors [ i ] . setName ( injectorNames [ i ] ) ;
2019-05-15 01:26:41 -07:00
enginePins . injectors [ i ] . shortName = injectorShortNames [ i ] ;
2024-01-07 16:08:52 -08:00
enginePins . injectorsStage2 [ i ] . injectorIndex = i ;
2024-01-05 15:43:50 -08:00
enginePins . injectorsStage2 [ i ] . setName ( injectorStage2Names [ i ] ) ;
2024-01-07 16:08:52 -08:00
enginePins . injectorsStage2 [ i ] . shortName = injectorStage2ShortNames [ i ] ;
2016-09-27 08:01:57 -07:00
}
2019-11-13 05:42:16 -08:00
2020-09-27 04:22:09 -07:00
static_assert ( efi : : size ( auxValveShortNames ) > = AUX_DIGITAL_VALVE_COUNT , " Too many aux valve pins " ) ;
2017-11-26 19:30:37 -08:00
for ( int i = 0 ; i < AUX_DIGITAL_VALVE_COUNT ; i + + ) {
2023-11-01 14:54:57 -07:00
enginePins . auxValve [ i ] . setName ( auxValveShortNames [ i ] ) ;
2017-11-26 19:30:37 -08:00
}
2016-09-06 21:02:11 -07:00
}
2017-04-21 13:52:02 -07:00
/**
* Sets the value of the pin . On this layer the value is assigned as is , without any conversion .
*/
2019-11-24 21:02:53 -08:00
# define unregisterOutputIfPinChanged(output, pin) { \
if ( isConfigurationChanged ( pin ) ) { \
2020-12-18 14:18:12 -08:00
( output ) . deInit ( ) ; \
2019-11-24 21:02:53 -08:00
} \
}
# define unregisterOutputIfPinOrModeChanged(output, pin, mode) { \
if ( isPinOrModeChanged ( pin , mode ) ) { \
2020-12-18 14:18:12 -08:00
( output ) . deInit ( ) ; \
2019-11-24 21:02:53 -08:00
} \
}
2016-11-03 20:02:58 -07:00
bool EnginePins : : stopPins ( ) {
bool result = false ;
2021-07-06 17:14:08 -07:00
for ( int i = 0 ; i < MAX_CYLINDER_COUNT ; i + + ) {
2016-11-03 20:02:58 -07:00
result | = coils [ i ] . stop ( ) ;
result | = injectors [ i ] . stop ( ) ;
2024-01-07 16:08:52 -08:00
result | = injectorsStage2 [ i ] . stop ( ) ;
2021-07-09 07:14:00 -07:00
result | = trailingCoils [ i ] . stop ( ) ;
2016-11-03 20:02:58 -07:00
}
2017-11-26 19:30:37 -08:00
for ( int i = 0 ; i < AUX_DIGITAL_VALVE_COUNT ; i + + ) {
result | = auxValve [ i ] . stop ( ) ;
}
2016-11-03 20:02:58 -07:00
return result ;
}
2021-07-09 14:02:25 -07:00
void EnginePins : : unregisterPins ( ) {
stopInjectionPins ( ) ;
stopIgnitionPins ( ) ;
stopAuxValves ( ) ;
2020-11-02 21:46:03 -08:00
2019-03-10 09:58:27 -07:00
# if EFI_ELECTRONIC_THROTTLE_BODY
unregisterEtbPins ( ) ;
# endif /* EFI_ELECTRONIC_THROTTLE_BODY */
2021-07-09 11:43:58 -07:00
2020-09-27 04:22:09 -07:00
// todo: add pinMode
2019-12-11 14:48:55 -08:00
unregisterOutputIfPinChanged ( sdCsPin , sdCardCsPin ) ;
2023-12-13 20:59:01 -08:00
unregisterOutputIfPinChanged ( accelerometerCs , accelerometerCsPin ) ;
2017-06-04 15:29:57 -07:00
2020-09-17 16:41:28 -07:00
RegisteredOutputPin * pin = registeredOutputHead ;
2020-09-17 16:35:43 -07:00
while ( pin ! = nullptr ) {
pin - > unregister ( ) ;
pin = pin - > next ;
}
2017-06-04 13:35:13 -07:00
}
2020-11-19 20:57:06 -08:00
void EnginePins : : debug ( ) {
RegisteredOutputPin * pin = registeredOutputHead ;
while ( pin ! = nullptr ) {
2023-11-01 14:54:57 -07:00
efiPrintf ( " %s %d " , pin - > getRegistrationName ( ) , pin - > currentLogicValue ) ;
2020-11-19 20:57:06 -08:00
pin = pin - > next ;
}
}
2021-07-09 14:02:25 -07:00
void EnginePins : : startPins ( ) {
2020-11-02 21:46:03 -08:00
# if EFI_ENGINE_CONTROL
2021-07-09 14:02:25 -07:00
startInjectionPins ( ) ;
startIgnitionPins ( ) ;
startAuxValves ( ) ;
2020-11-02 21:46:03 -08:00
# endif /* EFI_ENGINE_CONTROL */
2020-11-05 14:23:09 -08:00
RegisteredOutputPin * pin = registeredOutputHead ;
while ( pin ! = nullptr ) {
2021-11-16 01:15:29 -08:00
pin - > init ( ) ;
2020-11-05 14:23:09 -08:00
pin = pin - > next ;
}
2020-03-26 05:03:55 -07:00
}
2016-11-03 20:02:58 -07:00
void EnginePins : : reset ( ) {
2021-07-06 17:14:08 -07:00
for ( int i = 0 ; i < MAX_CYLINDER_COUNT ; i + + ) {
2016-11-01 06:02:29 -07:00
injectors [ i ] . reset ( ) ;
coils [ i ] . reset ( ) ;
2021-07-09 07:14:00 -07:00
trailingCoils [ i ] . reset ( ) ;
2016-11-01 06:02:29 -07:00
}
}
2021-07-09 14:02:25 -07:00
void EnginePins : : stopIgnitionPins ( ) {
2021-07-06 17:14:08 -07:00
for ( int i = 0 ; i < MAX_CYLINDER_COUNT ; i + + ) {
2019-12-11 14:48:55 -08:00
unregisterOutputIfPinOrModeChanged ( enginePins . coils [ i ] , ignitionPins [ i ] , ignitionPinMode ) ;
2021-07-09 12:51:30 -07:00
unregisterOutputIfPinOrModeChanged ( enginePins . trailingCoils [ i ] , trailingCoilPins [ i ] , ignitionPinMode ) ;
2017-06-04 15:53:43 -07:00
}
}
2021-07-09 14:02:25 -07:00
void EnginePins : : stopInjectionPins ( ) {
2021-07-06 17:14:08 -07:00
for ( int i = 0 ; i < MAX_CYLINDER_COUNT ; i + + ) {
2019-12-11 14:48:55 -08:00
unregisterOutputIfPinOrModeChanged ( enginePins . injectors [ i ] , injectionPins [ i ] , injectionPinMode ) ;
2024-01-05 15:43:50 -08:00
unregisterOutputIfPinOrModeChanged ( enginePins . injectorsStage2 [ i ] , injectionPinsStage2 [ i ] , injectionPinMode ) ;
2017-06-04 15:53:43 -07:00
}
}
2021-07-09 14:02:25 -07:00
void EnginePins : : stopAuxValves ( ) {
2021-02-17 05:57:18 -08:00
for ( int i = 0 ; i < AUX_DIGITAL_VALVE_COUNT ; i + + ) {
NamedOutputPin * output = & enginePins . auxValve [ i ] ;
// todo: do we need auxValveMode and reuse code?
if ( isConfigurationChanged ( auxValves [ i ] ) ) {
( output ) - > deInit ( ) ;
}
}
}
2021-07-09 14:02:25 -07:00
void EnginePins : : startAuxValves ( ) {
2019-04-12 19:07:03 -07:00
# if EFI_PROD_CODE
2017-11-26 19:30:37 -08:00
for ( int i = 0 ; i < AUX_DIGITAL_VALVE_COUNT ; i + + ) {
NamedOutputPin * output = & enginePins . auxValve [ i ] ;
2021-02-17 05:57:18 -08:00
// todo: do we need auxValveMode and reuse code?
if ( isConfigurationChanged ( auxValves [ i ] ) ) {
2023-11-01 14:54:57 -07:00
output - > initPin ( output - > getName ( ) , engineConfiguration - > auxValves [ i ] ) ;
2021-02-17 05:57:18 -08:00
}
2017-11-26 19:30:37 -08:00
}
# endif /* EFI_PROD_CODE */
}
2021-07-09 14:02:25 -07:00
void EnginePins : : startIgnitionPins ( ) {
2019-04-12 19:07:03 -07:00
# if EFI_PROD_CODE
2023-03-27 00:58:18 -07:00
for ( size_t i = 0 ; i < engineConfiguration - > cylindersCount ; i + + ) {
2021-07-09 07:14:00 -07:00
NamedOutputPin * trailingOutput = & enginePins . trailingCoils [ i ] ;
if ( isPinOrModeChanged ( trailingCoilPins [ i ] , ignitionPinMode ) ) {
2023-11-01 14:54:57 -07:00
trailingOutput - > initPin ( trailingOutput - > getName ( ) , engineConfiguration - > trailingCoilPins [ i ] , engineConfiguration - > ignitionPinMode ) ;
2021-07-09 07:14:00 -07:00
}
2017-06-04 15:53:43 -07:00
NamedOutputPin * output = & enginePins . coils [ i ] ;
2019-12-11 14:48:55 -08:00
if ( isPinOrModeChanged ( ignitionPins [ i ] , ignitionPinMode ) ) {
2023-11-01 14:54:57 -07:00
output - > initPin ( output - > getName ( ) , engineConfiguration - > ignitionPins [ i ] , engineConfiguration - > ignitionPinMode ) ;
2017-06-04 15:53:43 -07:00
}
}
# endif /* EFI_PROD_CODE */
}
2021-07-09 14:02:25 -07:00
void EnginePins : : startInjectionPins ( ) {
2019-04-12 19:07:03 -07:00
# if EFI_PROD_CODE
2017-06-04 15:53:43 -07:00
// todo: should we move this code closer to the injection logic?
2023-03-27 00:58:18 -07:00
for ( size_t i = 0 ; i < engineConfiguration - > cylindersCount ; i + + ) {
2017-06-04 15:53:43 -07:00
NamedOutputPin * output = & enginePins . injectors [ i ] ;
2019-12-11 14:48:55 -08:00
if ( isPinOrModeChanged ( injectionPins [ i ] , injectionPinMode ) ) {
2023-11-01 14:54:57 -07:00
output - > initPin ( output - > getName ( ) , engineConfiguration - > injectionPins [ i ] ,
2023-02-25 00:31:12 -08:00
engineConfiguration - > injectionPinMode ) ;
2017-06-04 15:53:43 -07:00
}
2024-01-07 16:08:52 -08:00
output = & enginePins . injectorsStage2 [ i ] ;
if ( isPinOrModeChanged ( injectionPinsStage2 [ i ] , injectionPinMode ) ) {
output - > initPin ( output - > getName ( ) , engineConfiguration - > injectionPinsStage2 [ i ] ,
engineConfiguration - > injectionPinMode ) ;
}
2017-06-04 15:53:43 -07:00
}
# endif /* EFI_PROD_CODE */
}
2023-10-11 07:33:39 -07:00
OutputPin * EnginePins : : getOutputPinForBenchMode ( bench_mode_e index ) {
switch ( index ) {
2023-10-11 09:08:21 -07:00
# if EFI_VVT_PID
2023-10-11 07:33:39 -07:00
case BENCH_VVT0_VALVE :
return getVvtOutputPin ( 0 ) ;
case BENCH_VVT1_VALVE :
return getVvtOutputPin ( 1 ) ;
case BENCH_VVT2_VALVE :
return getVvtOutputPin ( 2 ) ;
case BENCH_VVT3_VALVE :
return getVvtOutputPin ( 3 ) ;
2023-10-11 09:08:21 -07:00
# endif // EFI_VVT_PID
2023-10-11 07:33:39 -07:00
case BENCH_MAIN_RELAY :
return & mainRelay ;
case BENCH_HPFP_VALVE :
return & hpfpValve ;
case BENCH_FUEL_PUMP :
return & fuelPumpRelay ;
case BENCH_STARTER_ENABLE_RELAY :
return & starterControl ;
case BENCH_CHECK_ENGINE_LIGHT :
return & checkEnginePin ;
case BENCH_AC_COMPRESSOR_RELAY :
return & acRelay ;
case BENCH_FAN_RELAY :
return & fanRelay ;
2023-10-31 09:24:26 -07:00
# if EFI_HD_ACR
case HD_ACR :
return & harleyAcr ;
case HD_ACR2 :
return & harleyAcr2 ;
# endif
2023-10-11 07:33:39 -07:00
case BENCH_IDLE_VALVE :
return & idleSolenoidPin ;
case BENCH_FAN_RELAY_2 :
return & fanRelay ;
default :
criticalError ( " Unexpected bench pin %d " , index ) ;
}
return nullptr ;
}
2017-04-21 12:14:37 -07:00
NamedOutputPin : : NamedOutputPin ( ) : OutputPin ( ) {
2020-11-09 18:10:48 -08:00
}
2023-11-01 07:51:22 -07:00
NamedOutputPin : : NamedOutputPin ( const char * p_name ) : OutputPin ( ) {
name = p_name ;
2017-04-21 12:14:37 -07:00
}
2019-06-08 06:51:36 -07:00
const char * NamedOutputPin : : getName ( ) const {
2019-05-15 01:26:41 -07:00
return name ;
}
2023-11-01 14:54:57 -07:00
void NamedOutputPin : : setName ( const char * p_name ) {
name = p_name ;
}
2019-06-08 06:51:36 -07:00
const char * NamedOutputPin : : getShortName ( ) const {
2020-11-09 18:10:48 -08:00
return shortName = = nullptr ? name : shortName ;
2017-04-21 12:14:37 -07:00
}
2021-10-01 20:50:32 -07:00
# if EFI_UNIT_TEST
extern bool verboseMode ;
# endif // EFI_UNIT_TEST
2017-04-21 16:23:20 -07:00
void NamedOutputPin : : setHigh ( ) {
2023-06-15 08:46:28 -07:00
setHigh ( nullptr ) ;
}
void NamedOutputPin : : setHigh ( const char * msg ) {
2021-10-01 20:50:32 -07:00
# if EFI_UNIT_TEST
if ( verboseMode ) {
efiPrintf ( " pin %s goes high " , name ) ;
}
# endif // EFI_UNIT_TEST
2019-04-12 19:07:03 -07:00
# if EFI_DEFAILED_LOGGING
2017-04-21 16:23:20 -07:00
// signal->hi_time = hTimeNow();
# endif /* EFI_DEFAILED_LOGGING */
// turn the output level ACTIVE
2023-06-15 12:43:35 -07:00
setValue ( msg , true ) ;
2017-04-21 16:23:20 -07:00
2019-04-12 19:07:03 -07:00
# if EFI_ENGINE_SNIFFER
2022-10-29 18:27:49 -07:00
addEngineSnifferOutputPinEvent ( this , FrontDirection : : UP ) ;
2017-04-21 16:23:20 -07:00
# endif /* EFI_ENGINE_SNIFFER */
}
void NamedOutputPin : : setLow ( ) {
2023-06-15 08:46:28 -07:00
setLow ( nullptr ) ;
}
void NamedOutputPin : : setLow ( const char * msg ) {
2021-10-01 20:50:32 -07:00
# if EFI_UNIT_TEST
if ( verboseMode ) {
efiPrintf ( " pin %s goes low " , name ) ;
}
# endif // EFI_UNIT_TEST
2017-04-21 16:23:20 -07:00
// turn off the output
2023-06-15 12:43:35 -07:00
setValue ( msg , false ) ;
2017-04-21 16:23:20 -07:00
2019-04-12 19:07:03 -07:00
# if EFI_ENGINE_SNIFFER
2022-10-29 18:27:49 -07:00
addEngineSnifferOutputPinEvent ( this , FrontDirection : : DOWN ) ;
2017-04-21 16:23:20 -07:00
# endif /* EFI_ENGINE_SNIFFER */
}
2016-11-03 20:02:58 -07:00
bool NamedOutputPin : : stop ( ) {
2019-04-12 19:07:03 -07:00
# if EFI_GPIO_HARDWARE
2016-11-03 20:02:58 -07:00
if ( isInitialized ( ) & & getLogicValue ( ) ) {
2023-06-15 12:43:35 -07:00
setValue ( " stop " , false ) ;
2021-04-21 09:53:13 -07:00
efiPrintf ( " turning off %s " , name ) ;
2016-11-03 20:02:58 -07:00
return true ;
}
2017-04-21 13:36:50 -07:00
# endif /* EFI_GPIO_HARDWARE */
2016-11-03 20:02:58 -07:00
return false ;
}
2016-09-03 21:03:27 -07:00
void InjectorOutputPin : : reset ( ) {
2020-07-16 23:55:41 -07:00
// If this injector was open, close it and reset state
if ( overlappingCounter ! = 0 ) {
overlappingCounter = 0 ;
2023-06-15 12:43:35 -07:00
setValue ( " reset " , 0 ) ;
2020-07-16 23:55:41 -07:00
}
2016-09-04 22:03:25 -07:00
// todo: this could be refactored by calling some super-reset method
2020-11-18 20:54:30 -08:00
currentLogicValue = 0 ;
2016-09-03 21:03:27 -07:00
}
2016-10-31 19:02:12 -07:00
IgnitionOutputPin : : IgnitionOutputPin ( ) {
reset ( ) ;
}
2022-09-05 16:49:27 -07:00
void IgnitionOutputPin : : setHigh ( ) {
NamedOutputPin : : setHigh ( ) ;
// this is NASTY but what's the better option? bytes? At cost of 22 extra bytes in output status packet?
switch ( coilIndex ) {
case 0 :
engine - > outputChannels . coilState1 = true ;
break ;
case 1 :
engine - > outputChannels . coilState2 = true ;
break ;
case 2 :
engine - > outputChannels . coilState3 = true ;
break ;
case 3 :
engine - > outputChannels . coilState4 = true ;
break ;
2023-02-20 20:43:58 -08:00
case 4 :
engine - > outputChannels . coilState5 = true ;
break ;
case 5 :
engine - > outputChannels . coilState6 = true ;
break ;
2022-09-05 16:49:27 -07:00
}
}
void IgnitionOutputPin : : setLow ( ) {
NamedOutputPin : : setLow ( ) ;
// this is NASTY but what's the better option? bytes? At cost of 22 extra bytes in output status packet?
switch ( coilIndex ) {
case 0 :
engine - > outputChannels . coilState1 = false ;
break ;
case 1 :
engine - > outputChannels . coilState2 = false ;
break ;
case 2 :
engine - > outputChannels . coilState3 = false ;
break ;
case 3 :
engine - > outputChannels . coilState4 = false ;
break ;
2023-02-20 20:43:58 -08:00
case 4 :
engine - > outputChannels . coilState5 = false ;
break ;
case 5 :
engine - > outputChannels . coilState6 = false ;
break ;
2022-09-05 16:49:27 -07:00
}
}
2016-10-31 19:02:12 -07:00
void IgnitionOutputPin : : reset ( ) {
2016-11-01 20:01:54 -07:00
outOfOrder = false ;
signalFallSparkId = 0 ;
2016-10-31 19:02:12 -07:00
}
2023-11-01 14:54:57 -07:00
bool OutputPin : : isInitialized ( ) const {
2019-09-19 18:41:52 -07:00
# if EFI_GPIO_HARDWARE && EFI_PROD_CODE
2019-04-13 09:02:34 -07:00
# if (BOARD_EXT_GPIOCHIPS > 0)
if ( ext )
return true ;
# endif /* (BOARD_EXT_GPIOCHIPS > 0) */
2024-03-01 16:12:19 -08:00
return m_port ! = NULL ;
2017-04-21 12:14:37 -07:00
# else /* EFI_GPIO_HARDWARE */
2017-07-10 18:43:03 -07:00
return true ;
2017-04-21 12:14:37 -07:00
# endif /* EFI_GPIO_HARDWARE */
2015-07-10 06:01:56 -07:00
}
2018-01-28 08:27:33 -08:00
void OutputPin : : toggle ( ) {
2023-06-15 12:43:35 -07:00
setValue ( " toggle " , ! getLogicValue ( ) ) ;
2020-03-30 22:06:19 -07:00
}
2018-01-28 08:08:37 -08:00
2020-03-30 22:06:19 -07:00
bool OutputPin : : getAndSet ( int logicValue ) {
2020-11-26 21:24:41 -08:00
bool oldValue = getLogicValue ( ) ;
2020-03-30 22:06:19 -07:00
setValue ( logicValue ) ;
return oldValue ;
2018-01-28 08:08:37 -08:00
}
2020-03-30 22:06:19 -07:00
2020-12-10 16:18:14 -08:00
// This function is only used on real hardware
2020-10-03 17:53:23 -07:00
# if EFI_PROD_CODE
2020-12-10 16:18:14 -08:00
void OutputPin : : setOnchipValue ( int electricalValue ) {
2022-04-28 14:32:39 -07:00
if ( brainPin = = Gpio : : Unassigned | | brainPin = = Gpio : : Invalid ) {
2022-01-16 12:34:35 -08:00
// todo: make 'setOnchipValue' or 'reportsetOnchipValueError' virtual and override for NamedOutputPin?
2023-04-28 21:13:13 -07:00
warning ( ObdCode : : CUSTOM_ERR_6586 , " attempting to change unassigned pin " ) ;
2022-01-16 12:34:35 -08:00
return ;
}
2024-03-01 16:12:19 -08:00
palWritePad ( m_port , m_pin , electricalValue ) ;
2020-10-03 17:25:37 -07:00
}
2020-12-10 16:18:14 -08:00
# endif // EFI_PROD_CODE
2020-10-03 17:25:37 -07:00
2023-08-28 21:24:46 -07:00
void OutputPin : : setValue ( int logicValue , bool isForce ) {
setValue ( nullptr , logicValue , isForce ) ;
2023-06-15 08:46:28 -07:00
}
2023-10-16 06:37:22 -07:00
# if EFI_SIMULATOR
void OutputPin : : resetToggleStats ( ) {
durationsInStateMs [ 0 ] = durationsInStateMs [ 1 ] = 0 ;
pinToggleCounter = 0 ;
}
# endif // EFI_SIMULATOR
2023-08-20 21:40:36 -07:00
extern bool qcDirectPinControlMode ;
2023-08-28 21:24:46 -07:00
void OutputPin : : setValue ( const char * msg , int logicValue , bool isForce ) {
2023-11-02 12:27:56 -07:00
UNUSED ( msg ) ;
2023-10-16 13:04:21 -07:00
if ( ( qcDirectPinControlMode | | getOutputOnTheBenchTest ( ) = = this ) & & ! isForce ) {
2023-08-20 21:40:36 -07:00
return ;
}
2020-07-25 16:04:15 -07:00
# if ENABLE_PERF_TRACE
2020-07-25 16:14:09 -07:00
// todo: https://github.com/rusefi/rusefi/issues/1638
// ScopePerf perf(PE::OutputPinSetValue);
2020-07-25 16:04:15 -07:00
# endif // ENABLE_PERF_TRACE
2019-10-13 13:14:08 -07:00
2023-10-10 18:36:33 -07:00
# if EFI_UNIT_TEST
if ( currentLogicValue ! = logicValue ) {
pinToggleCounter + + ;
}
# endif // EFI_UNIT_TEST
# if EFI_SIMULATOR
2023-09-10 21:03:10 -07:00
if ( currentLogicValue ! = logicValue ) {
2023-10-10 18:29:27 -07:00
if ( pinToggleCounter > 0 ) {
durationsInStateMs [ 0 ] = durationsInStateMs [ 1 ] ;
2023-10-10 21:07:36 -07:00
durationsInStateMs [ 1 ] = pinToggleTimer . getElapsedUs ( ) / 1000 ;
2023-10-10 18:29:27 -07:00
}
2023-09-10 21:03:10 -07:00
pinToggleCounter + + ;
2023-10-10 18:29:27 -07:00
pinToggleTimer . reset ( ) ;
2023-09-10 21:03:10 -07:00
}
2023-10-10 18:36:33 -07:00
# endif // EFI_SIMULATOR
2022-01-18 07:24:08 -08:00
2023-09-10 21:03:10 -07:00
# if EFI_UNIT_TEST
2021-10-01 20:50:32 -07:00
if ( verboseMode ) {
efiPrintf ( " pin goes %d " , logicValue ) ;
}
# endif // EFI_UNIT_TEST
2020-12-18 14:18:12 -08:00
// Always store the current logical value of the pin (so it can be
// used internally even if not connected to a real hardware pin)
currentLogicValue = logicValue ;
// Nothing else to do if not configured
2021-01-08 17:01:26 -08:00
if ( ! isBrainPinValid ( brainPin ) ) {
2020-12-18 14:18:12 -08:00
return ;
}
2023-04-28 21:13:13 -07:00
efiAssertVoid ( ObdCode : : CUSTOM_ERR_6622 , mode < = OM_OPENDRAIN_INVERTED , " invalid pin_output_mode_e " ) ;
2020-10-03 17:25:37 -07:00
int electricalValue = getElectricalValue ( logicValue , mode ) ;
2019-04-10 05:43:54 -07:00
2020-12-18 14:18:12 -08:00
# if EFI_PROD_CODE
2019-04-10 05:43:54 -07:00
# if (BOARD_EXT_GPIOCHIPS > 0)
if ( ! this - > ext ) {
2020-12-10 16:18:14 -08:00
setOnchipValue ( electricalValue ) ;
2019-04-10 05:43:54 -07:00
} else {
/* external pin */
2019-04-10 07:25:50 -07:00
gpiochips_writePad ( this - > brainPin , logicValue ) ;
2019-04-13 16:32:46 -07:00
/* TODO: check return value */
2019-04-10 05:43:54 -07:00
}
# else
2020-12-10 16:18:14 -08:00
setOnchipValue ( electricalValue ) ;
2019-04-10 05:43:54 -07:00
# endif
2017-04-21 13:52:02 -07:00
# else /* EFI_PROD_CODE */
2020-12-18 14:18:12 -08:00
setMockState ( brainPin , electricalValue ) ;
2017-04-21 13:52:02 -07:00
# endif /* EFI_PROD_CODE */
2015-07-10 06:01:56 -07:00
}
2019-06-08 06:51:36 -07:00
bool OutputPin : : getLogicValue ( ) const {
2020-12-10 16:18:14 -08:00
// Compare against 1 since it could also be INITIAL_PIN_STATE (which means logical 0, but we haven't initialized the pin yet)
2020-11-26 21:24:41 -08:00
return currentLogicValue = = 1 ;
2015-07-10 06:01:56 -07:00
}
2023-02-25 00:31:12 -08:00
void OutputPin : : setDefaultPinState ( pin_output_mode_e outputMode ) {
2015-07-10 06:01:56 -07:00
assertOMode ( mode ) ;
2023-02-25 00:31:12 -08:00
this - > mode = outputMode ;
2023-08-28 21:24:46 -07:00
setValue ( false , /*force*/ true ) ; // initial state
2015-07-10 06:01:56 -07:00
}
2022-08-01 12:41:47 -07:00
brain_pin_diag_e OutputPin : : getDiag ( ) const {
2024-02-05 00:51:08 -08:00
# if EFI_PROD_CODE
2022-08-01 12:41:47 -07:00
# if BOARD_EXT_GPIOCHIPS > 0
2024-01-28 07:35:14 -08:00
if ( ! brain_pin_is_onchip ( brainPin ) ) {
return gpiochips_getDiag ( brainPin ) ;
}
2022-08-01 12:41:47 -07:00
# endif
2024-02-05 00:51:08 -08:00
# endif /* EFI_PROD_CODE */
2024-01-28 07:35:14 -08:00
// TODO: add hook to board code for custom diagnostic, like it is done on S105
return PIN_UNKNOWN ;
2022-08-01 12:41:47 -07:00
}
2023-11-24 11:37:01 -08:00
void initMiscOutputPins ( ) {
2019-04-12 19:07:03 -07:00
# if EFI_GPIO_HARDWARE
2017-04-21 12:14:37 -07:00
2019-04-12 19:07:03 -07:00
# if HAL_USE_SPI
2021-11-17 00:54:21 -08:00
enginePins . sdCsPin . initPin ( " SD CS " , engineConfiguration - > sdCardCsPin ) ;
2017-04-21 12:14:37 -07:00
# endif /* HAL_USE_SPI */
2020-11-02 21:21:39 -08:00
# if EFI_SHAFT_POSITION_INPUT
// todo: migrate remaining OutputPin to RegisteredOutputPin in order to get consistent dynamic pin init/deinit
2021-11-17 00:54:21 -08:00
enginePins . debugTriggerSync . initPin ( " debug: sync " , engineConfiguration - > debugTriggerSync ) ;
2020-11-02 21:21:39 -08:00
# endif // EFI_SHAFT_POSITION_INPUT
2020-11-02 21:09:42 -08:00
2021-11-17 00:54:21 -08:00
enginePins . o2heater . initPin ( " O2 heater " , engineConfiguration - > o2heaterPin ) ;
2017-04-21 12:14:37 -07:00
# endif /* EFI_GPIO_HARDWARE */
}
2023-11-01 07:51:22 -07:00
void OutputPin : : initPin ( const char * p_msg , brain_pin_e p_brainPin ) {
initPin ( p_msg , p_brainPin , OM_DEFAULT ) ;
2017-04-21 14:50:28 -07:00
}
2023-11-01 07:51:22 -07:00
void OutputPin : : initPin ( const char * msg , brain_pin_e p_brainPin , pin_output_mode_e outputMode , bool forceInitWithFatalError ) {
2022-01-18 07:24:08 -08:00
# if EFI_UNIT_TEST
2023-09-10 21:03:10 -07:00
pinToggleCounter = 0 ;
2022-01-18 07:24:08 -08:00
# endif
2023-11-01 07:51:22 -07:00
if ( ! isBrainPinValid ( p_brainPin ) ) {
2020-12-18 14:18:12 -08:00
return ;
}
2020-11-18 19:47:40 -08:00
2020-12-18 14:18:12 -08:00
// Enter a critical section so that other threads can't change the pin state out from underneath us
chibios_rt : : CriticalSectionLocker csl ;
2021-07-20 14:09:52 -07:00
if ( ! forceInitWithFatalError & & hasFirmwareError ( ) ) {
2021-06-24 17:18:23 -07:00
// Don't allow initializing more pins if we have a fatal error.
// Pins should have just been reset, so we shouldn't try to init more.
return ;
}
2020-12-18 14:18:12 -08:00
// Check that this OutputPin isn't already assigned to another pin (reinit is allowed to change mode)
// To avoid this error, call deInit() first
2023-11-01 07:51:22 -07:00
if ( isBrainPinValid ( brainPin ) & & brainPin ! = p_brainPin ) {
2023-04-28 21:13:13 -07:00
firmwareError ( ObdCode : : CUSTOM_OBD_PIN_CONFLICT , " outputPin [%s] already assigned, cannot reassign without unregister first " , msg ) ;
2017-04-21 14:14:14 -07:00
return ;
2020-12-18 14:18:12 -08:00
}
2017-04-21 12:14:37 -07:00
2023-02-25 00:31:12 -08:00
if ( outputMode > OM_OPENDRAIN_INVERTED ) {
2023-04-28 21:13:13 -07:00
firmwareError ( ObdCode : : CUSTOM_INVALID_MODE_SETTING , " %s invalid pin_output_mode_e %d %s " ,
2020-12-17 17:22:04 -08:00
msg ,
2023-02-25 00:31:12 -08:00
outputMode ,
2023-11-01 07:51:22 -07:00
hwPortname ( p_brainPin )
2020-12-17 17:22:04 -08:00
) ;
2020-03-05 18:16:45 -08:00
return ;
}
2020-12-18 14:18:12 -08:00
# if EFI_GPIO_HARDWARE && EFI_PROD_CODE
2023-11-01 07:51:22 -07:00
iomode_t l_mode = ( outputMode = = OM_DEFAULT | | outputMode = = OM_INVERTED ) ?
2017-04-21 14:14:14 -07:00
PAL_MODE_OUTPUT_PUSHPULL : PAL_MODE_OUTPUT_OPENDRAIN ;
2017-04-21 12:14:37 -07:00
2019-04-10 05:43:54 -07:00
# if (BOARD_EXT_GPIOCHIPS > 0)
this - > ext = false ;
# endif
2023-11-01 07:51:22 -07:00
if ( brain_pin_is_onchip ( p_brainPin ) ) {
2024-03-01 16:12:19 -08:00
m_port = getHwPort ( msg , p_brainPin ) ;
m_pin = getHwPin ( msg , p_brainPin ) ;
2019-04-10 05:43:54 -07:00
2020-12-18 14:18:12 -08:00
// Validate port
2024-03-01 16:12:19 -08:00
if ( m_port = = GPIO_NULL ) {
2023-11-01 07:51:22 -07:00
criticalError ( " OutputPin::initPin got invalid port for pin idx %d " , static_cast < int > ( p_brainPin ) ) ;
2019-04-10 05:43:54 -07:00
return ;
}
2017-04-21 14:26:50 -07:00
}
2019-04-10 05:43:54 -07:00
# if (BOARD_EXT_GPIOCHIPS > 0)
else {
this - > ext = true ;
}
# endif
2020-12-09 22:23:24 -08:00
# endif // briefly leave the include guard because we need to set default state in tests
2023-11-01 07:51:22 -07:00
brainPin = p_brainPin ;
2020-12-18 14:18:12 -08:00
2019-07-03 00:18:04 -07:00
// The order of the next two calls may look strange, which is a good observation.
// We call them in this order so that the pin is set to a known state BEFORE
// it's enabled. Enabling the pin then setting it could result in a (brief)
// mystery state being driven on the pin (potentially dangerous).
2017-04-21 15:11:36 -07:00
setDefaultPinState ( outputMode ) ;
2020-12-09 22:23:24 -08:00
# if EFI_GPIO_HARDWARE && EFI_PROD_CODE
2023-11-01 07:51:22 -07:00
efiSetPadMode ( msg , brainPin , l_mode ) ;
2022-07-30 12:03:45 -07:00
if ( brain_pin_is_onchip ( brainPin ) ) {
// todo: handle OM_OPENDRAIN and OM_OPENDRAIN_INVERTED as well
2023-02-25 00:31:12 -08:00
if ( outputMode = = OM_DEFAULT | | outputMode = = OM_INVERTED ) {
2023-11-02 12:27:56 -07:00
# ifndef DISABLE_PIN_STATE_VALIDATION
2024-03-01 16:12:19 -08:00
int actualValue = palReadPad ( m_port , m_pin ) ;
2023-11-02 12:27:56 -07:00
// we had enough drama with pin configuration in board.h and else that we shall self-check
const int logicalValue =
2023-02-25 00:31:12 -08:00
( outputMode = = OM_INVERTED )
2023-12-13 20:59:01 -08:00
? ! actualValue
2022-07-30 12:03:45 -07:00
: actualValue ;
// if the pin was set to logical 1, then set an error and disable the pin so that things don't catch fire
if ( logicalValue ) {
2023-08-20 19:23:44 -07:00
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 ) ) ;
2022-07-30 12:03:45 -07:00
OutputPin : : deInit ( ) ;
}
2022-11-09 11:41:21 -08:00
# endif
2022-07-30 12:03:45 -07:00
}
}
2017-04-21 14:38:13 -07:00
# endif /* EFI_GPIO_HARDWARE */
}
2020-12-18 14:18:12 -08:00
void OutputPin : : deInit ( ) {
// Unregister under lock - we don't want other threads mucking with the pin while we're trying to turn it off
chibios_rt : : CriticalSectionLocker csl ;
// nothing to do if not registered in the first place
2021-01-08 17:01:26 -08:00
if ( ! isBrainPinValid ( brainPin ) ) {
2020-12-18 14:18:12 -08:00
return ;
}
# if (BOARD_EXT_GPIOCHIPS > 0)
ext = false ;
# endif // (BOARD_EXT_GPIOCHIPS > 0)
2021-04-21 09:53:13 -07:00
efiPrintf ( " unregistering %s " , hwPortname ( brainPin ) ) ;
2020-12-18 14:18:12 -08:00
2019-11-24 21:02:53 -08:00
# if EFI_GPIO_HARDWARE && EFI_PROD_CODE
2020-12-18 14:18:12 -08:00
efiSetPadUnused ( brainPin ) ;
2019-11-24 21:02:53 -08:00
# endif /* EFI_GPIO_HARDWARE */
2020-12-18 14:18:12 -08:00
// Clear the pin so that it won't get set any more
2022-04-28 14:32:39 -07:00
brainPin = Gpio : : Unassigned ;
2019-11-24 21:02:53 -08:00
}
2019-04-12 19:07:03 -07:00
# if EFI_GPIO_HARDWARE
2017-04-21 14:38:13 -07:00
2019-09-09 18:44:48 -07:00
// questionable trick: we avoid using 'getHwPort' and 'getHwPin' in case of errors in order to increase the changes of turning the LED
2019-09-19 18:41:52 -07:00
// by reducing stack requirement
2020-05-11 15:22:51 -07:00
ioportid_t criticalErrorLedPort ;
ioportmask_t criticalErrorLedPin ;
2020-09-09 15:23:04 -07:00
uint8_t criticalErrorLedState ;
2020-09-09 15:18:59 -07:00
2019-09-19 18:41:52 -07:00
# if EFI_PROD_CODE
2023-01-23 07:11:04 -08:00
static void initErrorLed ( Gpio led ) {
2023-06-04 23:32:14 -07:00
enginePins . errorLedPin . initPin ( " led: CRITICAL status " , led , ( LED_PIN_MODE ) ) ;
2023-01-23 07:11:04 -08:00
criticalErrorLedPort = getHwPort ( " CRITICAL " , led ) ;
criticalErrorLedPin = getHwPin ( " CRITICAL " , led ) ;
2023-06-04 23:32:14 -07:00
criticalErrorLedState = ( LED_PIN_MODE = = OM_INVERTED ) ? 0 : 1 ;
2023-01-23 07:11:04 -08:00
}
# endif /* EFI_PROD_CODE */
void initPrimaryPins ( ) {
# if EFI_PROD_CODE
initErrorLed ( LED_CRITICAL_ERROR_BRAIN_PIN ) ;
2020-11-19 20:57:06 -08:00
addConsoleAction ( " gpio_pins " , EnginePins : : debug ) ;
2019-09-19 18:41:52 -07:00
# endif /* EFI_PROD_CODE */
2017-04-21 12:14:37 -07:00
}
2017-04-21 12:28:47 -07:00
/**
* This method is part of fatal error handling .
* The whole method is pretty naive , but that ' s at least something .
*/
void turnAllPinsOff ( void ) {
2021-07-06 17:14:08 -07:00
for ( int i = 0 ; i < MAX_CYLINDER_COUNT ; i + + ) {
2017-04-21 12:28:47 -07:00
enginePins . injectors [ i ] . setValue ( false ) ;
enginePins . coils [ i ] . setValue ( false ) ;
2021-07-09 07:14:00 -07:00
enginePins . trailingCoils [ i ] . setValue ( false ) ;
2017-04-21 12:28:47 -07:00
}
2023-07-21 18:30:21 -07:00
enginePins . mainRelay . setValue ( false ) ;
enginePins . fuelPumpRelay . setValue ( false ) ;
enginePins . checkEnginePin . setValue ( true ) ; // yes this one can go ON
2017-04-21 12:28:47 -07:00
}
2017-04-21 12:14:37 -07:00
# endif /* EFI_GPIO_HARDWARE */
2023-05-24 05:51:24 -07:00