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
*/
2018-09-16 19:26:57 -07:00
# include "global.h"
2017-04-21 12:14:37 -07:00
# include "engine.h"
2019-03-29 06:11:13 -07:00
# include "efi_gpio.h"
2020-12-18 14:18:12 -08:00
# include "os_access.h"
2019-04-10 05:43:54 -07:00
# include "drivers/gpio/gpio_ext.h"
2019-10-11 17:43:21 -07:00
# include "perf_trace.h"
2020-11-18 19:47:40 -08:00
# include "engine_controller.h"
2015-07-10 06:01:56 -07:00
2019-04-12 19:07:03 -07:00
# if EFI_GPIO_HARDWARE
2018-12-18 20:50:29 -08:00
# include "pin_repository.h"
2017-04-21 12:14:37 -07:00
# include "io_pins.h"
# endif /* EFI_GPIO_HARDWARE */
2015-07-10 06:01:56 -07:00
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 12:14:37 -07:00
EXTERN_ENGINE ;
2015-07-10 06:01:56 -07:00
2019-04-12 19:07:03 -07:00
# if EFI_ENGINE_SNIFFER
2017-04-21 16:23:20 -07:00
# include "engine_sniffer.h"
extern WaveChart waveChart ;
# endif /* EFI_ENGINE_SNIFFER */
2017-04-21 13:36:50 -07:00
// todo: clean this mess, this should become 'static'/private
EnginePins enginePins ;
2021-02-06 09:22:57 -08:00
pin_output_mode_e DEFAULT_OUTPUT = OM_DEFAULT ;
2020-09-09 15:18:59 -07:00
pin_output_mode_e INVERTED_OUTPUT = OM_INVERTED ;
2016-09-03 21:03:27 -07:00
2020-03-29 16:07:07 -07:00
static const char * sparkNames [ ] = { " Coil 1 " , " Coil 2 " , " Coil 3 " , " Coil 4 " , " Coil 5 " , " Coil 6 " , " Coil 7 " , " Coil 8 " ,
" Coil 9 " , " Coil 10 " , " Coil 11 " , " Coil 12 " } ;
2019-05-15 01:26:41 -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 } ;
2019-05-15 01:26:41 -07:00
// these short names are part of engine sniffer protocol
2019-08-18 12:04:02 -07:00
static const char * sparkShortNames [ ] = { PROTOCOL_COIL1_SHORT_NAME , " c2 " , " c3 " , " c4 " , " c5 " , " c6 " , " c7 " , " c8 " ,
2016-09-27 08:01:57 -07:00
" c9 " , " cA " , " cB " , " cD " } ;
2020-03-29 16:07:07 -07:00
static const char * injectorNames [ ] = { " Injector 1 " , " Injector 2 " , " Injector 3 " , " Injector 4 " , " Injector 5 " , " Injector 6 " ,
" Injector 7 " , " Injector 8 " , " Injector 9 " , " Injector 10 " , " Injector 11 " , " Injector 12 " } ;
2019-05-15 01:26:41 -07:00
2019-08-18 12:27:10 -07:00
static const char * injectorShortNames [ ] = { PROTOCOL_INJ1_SHORT_NAME , " i2 " , " i3 " , " i4 " , " i5 " , " i6 " , " i7 " , " i8 " ,
2016-09-27 08:01:57 -07:00
" j9 " , " iA " , " iB " , " iC " } ;
2019-06-10 12:11:53 -07:00
static const char * 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
2020-11-09 18:10:48 -08:00
RegisteredNamedOutputPin : : RegisteredNamedOutputPin ( const char * name , short pinOffset ,
short pinModeOffset ) : RegisteredOutputPin ( name , pinOffset , pinModeOffset ) {
}
RegisteredOutputPin : : RegisteredOutputPin ( const char * registrationName , short pinOffset ,
2020-09-17 16:35:43 -07:00
short pinModeOffset ) {
2020-11-09 18:10:48 -08:00
this - > registrationName = registrationName ;
2020-09-17 16:35:43 -07:00
this - > pinOffset = pinOffset ;
this - > pinModeOffset = pinModeOffset ;
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
this - > next = registeredOutputHead ;
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
2020-09-18 10:01:09 -07:00
brain_pin_e curPin = * ( brain_pin_e * ) ( ( void * ) ( & ( ( char * ) & activeConfiguration ) [ pinOffset ] ) ) ;
brain_pin_e newPin = * ( brain_pin_e * ) ( ( void * ) ( & ( ( char * ) engineConfiguration ) [ pinOffset ] ) ) ;
2020-09-18 10:29:17 -07:00
pin_output_mode_e curMode = * ( pin_output_mode_e * ) ( ( void * ) ( & ( ( char * ) & activeConfiguration ) [ pinModeOffset ] ) ) ;
pin_output_mode_e newMode = * ( pin_output_mode_e * ) ( ( void * ) ( & ( ( char * ) engineConfiguration ) [ pinModeOffset ] ) ) ;
2020-11-05 14:23:09 -08:00
return curPin ! = newPin | | curMode ! = newMode ;
# 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
2020-11-18 19:47:40 -08:00
void RegisteredOutputPin : : init ( DECLARE_ENGINE_PARAMETER_SIGNATURE ) {
2020-11-05 14:23:09 -08:00
brain_pin_e newPin = * ( brain_pin_e * ) ( ( void * ) ( & ( ( char * ) engineConfiguration ) [ pinOffset ] ) ) ;
2020-11-05 15:42:45 -08:00
pin_output_mode_e * newMode = ( pin_output_mode_e * ) ( ( void * ) ( & ( ( char * ) engineConfiguration ) [ pinModeOffset ] ) ) ;
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
2020-09-26 02:04:27 -07:00
# define CONFIG_OFFSET(x) x##_offset
// 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)
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 ) ) ,
acRelay ( " A/C Relay " , CONFIG_PIN_OFFSETS ( acRelay ) ) ,
fuelPumpRelay ( " Fuel pump Relay " , CONFIG_PIN_OFFSETS ( fuelPump ) ) ,
2020-11-05 14:23:09 -08:00
boostPin ( " Boost " , CONFIG_PIN_OFFSETS ( boostControl ) ) ,
idleSolenoidPin ( " Idle Valve " , idle_solenoidPin_offset , idle_solenoidPinMode_offset ) ,
secondIdleSolenoidPin ( " Idle Valve#2 " , CONFIG_OFFSET ( secondSolenoidPin ) , idle_solenoidPinMode_offset ) ,
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 ) ) ,
2021-03-20 05:40:36 -07:00
triggerDecoderErrorPin ( " led: trigger debug " , CONFIG_PIN_OFFSETS ( triggerError ) )
2020-09-17 16:35:43 -07:00
{
2019-08-18 12:04:02 -07:00
tachOut . name = PROTOCOL_TACH_NAME ;
2020-11-09 18:41:13 -08:00
hpfpValve . name = PROTOCOL_HPFP_NAME ;
2016-09-27 08:01:57 -07:00
2020-09-27 04:22:09 -07:00
static_assert ( efi : : size ( sparkNames ) > = IGNITION_PIN_COUNT , " Too many ignition pins " ) ;
2016-09-27 08:01:57 -07:00
for ( int i = 0 ; i < IGNITION_PIN_COUNT ; i + + ) {
enginePins . coils [ i ] . name = sparkNames [ i ] ;
2019-05-15 01:26:41 -07:00
enginePins . coils [ i ] . shortName = sparkShortNames [ 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 ( injectorNames ) > = INJECTION_PIN_COUNT , " Too many injection pins " ) ;
2020-03-29 16:07:07 -07:00
for ( int i = 0 ; i < INJECTION_PIN_COUNT ; i + + ) {
2016-11-30 15:02:19 -08:00
enginePins . injectors [ i ] . injectorIndex = i ;
2016-09-27 08:01:57 -07:00
enginePins . injectors [ i ] . name = injectorNames [ i ] ;
2019-05-15 01:26:41 -07:00
enginePins . injectors [ i ] . shortName = injectorShortNames [ 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 + + ) {
2019-05-15 01:26:41 -07:00
enginePins . auxValve [ i ] . name = 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 .
*/
2017-06-04 13:35:13 -07:00
# if EFI_PROD_CODE
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
} \
}
2017-04-21 13:52:02 -07:00
# endif /* EFI_PROD_CODE */
2016-11-03 20:02:58 -07:00
bool EnginePins : : stopPins ( ) {
bool result = false ;
for ( int i = 0 ; i < IGNITION_PIN_COUNT ; i + + ) {
result | = coils [ i ] . stop ( ) ;
}
for ( int i = 0 ; i < INJECTION_PIN_COUNT ; i + + ) {
result | = injectors [ i ] . stop ( ) ;
}
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 ;
}
2017-06-04 13:35:13 -07:00
void EnginePins : : unregisterPins ( ) {
2020-11-02 21:46:03 -08:00
stopInjectionPins ( ) ;
stopIgnitionPins ( ) ;
2021-02-17 05:57:18 -08:00
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 */
2019-04-12 19:07:03 -07:00
# if EFI_PROD_CODE
2020-09-27 04:22:09 -07:00
// todo: add pinMode
2019-12-11 14:48:55 -08:00
unregisterOutputIfPinChanged ( sdCsPin , sdCardCsPin ) ;
2019-11-24 21:02:53 -08:00
unregisterOutputIfPinChanged ( accelerometerCs , LIS302DLCsPin ) ;
2017-06-04 15:29:57 -07:00
2017-06-25 23:14:31 -07:00
for ( int i = 0 ; i < FSIO_COMMAND_COUNT ; i + + ) {
2019-12-11 14:48:55 -08:00
unregisterOutputIfPinChanged ( fsioOutputs [ i ] , fsioOutputPins [ i ] ) ;
2017-06-04 15:29:57 -07:00
}
2020-12-18 14:18:12 -08:00
# endif /* EFI_PROD_CODE */
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 ( ) {
# if EFI_PROD_CODE
RegisteredOutputPin * pin = registeredOutputHead ;
while ( pin ! = nullptr ) {
2021-04-21 09:53:13 -07:00
efiPrintf ( " %s %d " , pin - > registrationName , pin - > currentLogicValue ) ;
2020-11-19 20:57:06 -08:00
pin = pin - > next ;
}
# endif // EFI_PROD_CODE
}
2020-11-03 07:51:54 -08:00
void EnginePins : : startPins ( DECLARE_ENGINE_PARAMETER_SIGNATURE ) {
2020-11-02 21:46:03 -08:00
# if EFI_ENGINE_CONTROL
2020-03-26 05:03:55 -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 ) {
2020-11-18 19:47:40 -08:00
pin - > init ( PASS_ENGINE_PARAMETER_SIGNATURE ) ;
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 ( ) {
2016-11-01 06:02:29 -07:00
for ( int i = 0 ; i < INJECTION_PIN_COUNT ; i + + ) {
injectors [ i ] . reset ( ) ;
}
for ( int i = 0 ; i < IGNITION_PIN_COUNT ; i + + ) {
coils [ i ] . reset ( ) ;
}
}
2017-06-04 15:53:43 -07:00
void EnginePins : : stopIgnitionPins ( void ) {
2019-04-12 19:07:03 -07:00
# if EFI_PROD_CODE
2017-06-04 15:53:43 -07:00
for ( int i = 0 ; i < IGNITION_PIN_COUNT ; i + + ) {
2019-12-11 14:48:55 -08:00
unregisterOutputIfPinOrModeChanged ( enginePins . coils [ i ] , ignitionPins [ i ] , ignitionPinMode ) ;
2017-06-04 15:53:43 -07:00
}
# endif /* EFI_PROD_CODE */
}
void EnginePins : : stopInjectionPins ( void ) {
2019-04-12 19:07:03 -07:00
# if EFI_PROD_CODE
2017-06-04 15:53:43 -07:00
for ( int i = 0 ; i < INJECTION_PIN_COUNT ; i + + ) {
2019-12-11 14:48:55 -08:00
unregisterOutputIfPinOrModeChanged ( enginePins . injectors [ i ] , injectionPins [ i ] , injectionPinMode ) ;
2017-06-04 15:53:43 -07:00
}
# endif /* EFI_PROD_CODE */
}
2021-02-17 05:57:18 -08:00
void EnginePins : : stopAuxValves ( void ) {
# if EFI_PROD_CODE
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 ( ) ;
}
}
# endif /* EFI_PROD_CODE */
}
2017-11-26 19:30:37 -08:00
void EnginePins : : startAuxValves ( void ) {
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 ] ) ) {
output - > initPin ( output - > name , engineConfiguration - > auxValves [ i ] ) ;
}
2017-11-26 19:30:37 -08:00
}
# endif /* EFI_PROD_CODE */
}
2017-06-04 15:53:43 -07:00
void EnginePins : : startIgnitionPins ( void ) {
2019-04-12 19:07:03 -07:00
# if EFI_PROD_CODE
2021-03-20 05:40:36 -07:00
for ( size_t i = 0 ; i < engineConfiguration - > specs . cylindersCount ; i + + ) {
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 ) ) {
output - > initPin ( output - > name , CONFIG ( ignitionPins ) [ i ] , & CONFIG ( ignitionPinMode ) ) ;
2017-06-04 15:53:43 -07:00
}
}
# endif /* EFI_PROD_CODE */
}
void EnginePins : : startInjectionPins ( void ) {
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?
2021-03-20 05:40:36 -07:00
for ( size_t i = 0 ; i < engineConfiguration - > specs . 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 ) ) {
output - > initPin ( output - > name , CONFIG ( injectionPins ) [ i ] ,
& CONFIG ( injectionPinMode ) ) ;
2017-06-04 15:53:43 -07:00
}
}
# endif /* EFI_PROD_CODE */
}
2017-04-21 12:14:37 -07:00
NamedOutputPin : : NamedOutputPin ( ) : OutputPin ( ) {
2020-11-09 18:10:48 -08:00
}
NamedOutputPin : : NamedOutputPin ( const char * name ) : OutputPin ( ) {
this - > name = 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 ;
}
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
}
2017-04-21 16:23:20 -07:00
void NamedOutputPin : : setHigh ( ) {
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
setValue ( true ) ;
2019-04-12 19:07:03 -07:00
# if EFI_ENGINE_SNIFFER
2019-08-18 12:04:02 -07:00
addEngineSnifferEvent ( getShortName ( ) , PROTOCOL_ES_UP ) ;
2017-04-21 16:23:20 -07:00
# endif /* EFI_ENGINE_SNIFFER */
}
void NamedOutputPin : : setLow ( ) {
// turn off the output
setValue ( false ) ;
2019-04-12 19:07:03 -07:00
# if EFI_ENGINE_SNIFFER
2019-08-18 12:04:02 -07:00
addEngineSnifferEvent ( getShortName ( ) , PROTOCOL_ES_DOWN ) ;
2017-04-21 16:23:20 -07:00
# endif /* EFI_ENGINE_SNIFFER */
}
2017-04-21 12:14:37 -07:00
InjectorOutputPin : : InjectorOutputPin ( ) : NamedOutputPin ( ) {
reset ( ) ;
injectorIndex = - 1 ;
}
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 ( ) ) {
setValue ( 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 ;
setValue ( 0 ) ;
}
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 ( ) ;
}
void IgnitionOutputPin : : reset ( ) {
2016-11-01 20:01:54 -07:00
outOfOrder = false ;
signalFallSparkId = 0 ;
2016-10-31 19:02:12 -07:00
}
2015-07-10 06:01:56 -07:00
OutputPin : : OutputPin ( ) {
2017-04-21 15:11:36 -07:00
modePtr = & DEFAULT_OUTPUT ;
2015-07-10 06:01:56 -07:00
}
2016-01-11 14:01:33 -08:00
bool OutputPin : : isInitialized ( ) {
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) */
2015-07-10 06:01:56 -07:00
return 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 ( ) {
2018-01-28 08:08:37 -08:00
setValue ( ! 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 ) {
palWritePad ( port , 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
2015-07-10 06:01:56 -07:00
void OutputPin : : setValue ( int logicValue ) {
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
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 ;
}
2019-04-10 05:43:54 -07:00
efiAssertVoid ( CUSTOM_ERR_6621 , modePtr ! = NULL , " pin mode not initialized " ) ;
pin_output_mode_e mode = * modePtr ;
efiAssertVoid ( 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
}
2019-01-16 05:24:37 -08:00
void OutputPin : : setDefaultPinState ( const pin_output_mode_e * outputMode ) {
2015-07-10 06:01:56 -07:00
pin_output_mode_e mode = * outputMode ;
2019-03-08 04:01:15 -08:00
/* may be*/ UNUSED ( mode ) ;
2015-07-10 06:01:56 -07:00
assertOMode ( mode ) ;
this - > modePtr = outputMode ;
setValue ( false ) ; // initial state
}
2019-09-19 18:41:52 -07:00
void initOutputPins ( DECLARE_ENGINE_PARAMETER_SIGNATURE ) {
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
2020-03-29 16:07:07 -07:00
enginePins . sdCsPin . initPin ( " SD CS " , CONFIG ( 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
enginePins . debugTriggerSync . initPin ( " debug: sync " , CONFIG ( debugTriggerSync ) ) ;
# endif // EFI_SHAFT_POSITION_INPUT
2020-11-02 21:09:42 -08:00
enginePins . o2heater . initPin ( " O2 heater " , CONFIG ( o2heaterPin ) ) ;
2017-04-21 12:14:37 -07:00
# endif /* EFI_GPIO_HARDWARE */
}
2017-04-21 15:11:36 -07:00
void OutputPin : : initPin ( const char * msg , brain_pin_e brainPin ) {
initPin ( msg , brainPin , & DEFAULT_OUTPUT ) ;
2017-04-21 14:50:28 -07:00
}
2019-01-16 05:24:37 -08:00
void OutputPin : : initPin ( const char * msg , brain_pin_e brainPin , const pin_output_mode_e * outputMode ) {
2021-01-08 17:01:26 -08:00
if ( ! isBrainPinValid ( 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 ;
// Check that this OutputPin isn't already assigned to another pin (reinit is allowed to change mode)
// To avoid this error, call deInit() first
2021-01-08 17:01:26 -08:00
if ( isBrainPinValid ( this - > brainPin ) & & this - > brainPin ! = brainPin ) {
2020-12-18 14:18:12 -08:00
firmwareError ( 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
2020-03-05 18:16:45 -08:00
if ( * outputMode > OM_OPENDRAIN_INVERTED ) {
2020-12-17 17:22:04 -08:00
firmwareError ( CUSTOM_INVALID_MODE_SETTING , " %s invalid pin_output_mode_e %d %s " ,
msg ,
* outputMode ,
hwPortname ( brainPin )
) ;
2020-03-05 18:16:45 -08:00
return ;
}
2020-12-18 14:18:12 -08:00
# if EFI_GPIO_HARDWARE && EFI_PROD_CODE
2017-04-21 12:14:37 -07:00
iomode_t 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
if ( brain_pin_is_onchip ( brainPin ) ) {
ioportid_t port = getHwPort ( msg , brainPin ) ;
int pin = getHwPin ( msg , brainPin ) ;
2020-12-18 14:18:12 -08:00
// Validate port
2019-04-10 05:43:54 -07:00
if ( port = = GPIO_NULL ) {
2020-12-18 14:18:12 -08:00
firmwareError ( OBD_PCM_Processor_Fault , " OutputPin::initPin got invalid port for pin idx %d " , static_cast < int > ( brainPin ) ) ;
2019-04-10 05:43:54 -07:00
return ;
}
this - > port = port ;
this - > pin = pin ;
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
2020-12-18 14:18:12 -08:00
this - > brainPin = brainPin ;
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
2019-07-03 00:18:04 -07:00
efiSetPadMode ( msg , brainPin , mode ) ;
2020-11-25 20:38:43 -08:00
if ( brain_pin_is_onchip ( brainPin ) ) {
int actualValue = palReadPad ( port , pin ) ;
// we had enough drama with pin configuration in board.h and else that we shall self-check
2020-12-10 16:18:14 -08:00
2020-11-25 20:38:43 -08:00
// todo: handle OM_OPENDRAIN and OM_OPENDRAIN_INVERTED as well
if ( * outputMode = = OM_DEFAULT | | * outputMode = = OM_INVERTED ) {
2020-12-10 16:18:14 -08:00
const int logicalValue =
( * outputMode = = OM_INVERTED )
? ! actualValue
: 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 ) {
firmwareError ( OBD_PCM_Processor_Fault , " %s: startup pin state %s actual value=%d logical value=%d mode=%s " , msg , hwPortname ( brainPin ) , actualValue , logicalValue , getPin_output_mode_e ( * outputMode ) ) ;
2020-12-18 14:18:12 -08:00
OutputPin : : deInit ( ) ;
2020-11-25 20:38:43 -08: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
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
# ifndef LED_ERROR_BRAIN_PIN_MODE
# define LED_ERROR_BRAIN_PIN_MODE DEFAULT_OUTPUT
# endif /* LED_ERROR_BRAIN_PIN_MODE */
2019-09-09 18:44:48 -07:00
2021-04-21 09:53:13 -07:00
void initPrimaryPins ( ) {
2019-09-19 18:41:52 -07:00
# if EFI_PROD_CODE
2020-09-09 15:23:04 -07:00
enginePins . errorLedPin . initPin ( " led: CRITICAL status " , LED_CRITICAL_ERROR_BRAIN_PIN , & ( LED_ERROR_BRAIN_PIN_MODE ) ) ;
2020-05-11 15:22:51 -07:00
criticalErrorLedPort = getHwPort ( " CRITICAL " , LED_CRITICAL_ERROR_BRAIN_PIN ) ;
criticalErrorLedPin = getHwPin ( " CRITICAL " , LED_CRITICAL_ERROR_BRAIN_PIN ) ;
2020-09-09 15:23:04 -07:00
criticalErrorLedState = ( LED_ERROR_BRAIN_PIN_MODE = = INVERTED_OUTPUT ) ? 0 : 1 ;
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 .
* Please note that worst case scenario the pins might get re - enabled by some other code : (
* The whole method is pretty naive , but that ' s at least something .
*/
void turnAllPinsOff ( void ) {
for ( int i = 0 ; i < INJECTION_PIN_COUNT ; i + + ) {
enginePins . injectors [ i ] . setValue ( false ) ;
}
for ( int i = 0 ; i < IGNITION_PIN_COUNT ; i + + ) {
enginePins . coils [ i ] . setValue ( false ) ;
}
}
2017-04-21 12:14:37 -07:00
# endif /* EFI_GPIO_HARDWARE */