/** * * @param delay the number of ticks before the output signal * immediate output if delay is zero * @param dwell the number of ticks of output duration * */ void scheduleOutput(OutputSignal *signal, float delayMs, float durationMs) { if (durationMs < 0) { firmwareError("duration cannot be negative: %d", durationMs); return; } if (cisnan(durationMs)) { firmwareError("NaN in scheduleOutput", durationMs); return; } int index = getRevolutionCounter() % 2; scheduling_s * sUp = &signal->signalTimerUp[index]; scheduling_s * sDown = &signal->signalTimerDown[index]; scheduleTask("out up", sUp, (int)MS2US(delayMs), (schfunc_t) &turnPinHigh, (void *) signal->io_pin); scheduleTask("out down", sDown, (int)MS2US(delayMs + durationMs), (schfunc_t) &turnPinLow, (void*) signal->io_pin); }
//Nullable static digital_input_s * finddigital_input_s(ICUDriver *driver) { for (int i = 0; i < registeredIcus.size; i++) { if (registeredIcus.elements[i].driver == driver) { return ®isteredIcus.elements[i]; } } firmwareError(CUSTOM_ERR_ICU, "reader not found"); return (digital_input_s *) NULL; }
/** * @brief Reset histogram_s to orignal state */ void initHistogram(histogram_s *h, const char *name) { if (efiStrlen(name) > sizeof(h->name) - 1) { firmwareError(ERROR_HISTO_NAME, "Histogram name [%s] too long", name); } strcpy(h->name, name); h->total_value = 0; h->total_count = 0; memset(h->values, 0, sizeof(h->values)); }
void efiIcuStart(const char *msg, ICUDriver *icup, const ICUConfig *config) { if (icup->state != ICU_STOP && icup->state != ICU_READY) { static char icuError[30]; sprintf(icuError, "ICU already used %s", msg); firmwareError(CUSTOM_ERR_6679, icuError); return; } icuStart(icup, config); }
void resetLogging(Logging *logging) { char *buffer = logging->buffer; if (buffer == NULL) { firmwareError("Null buffer: %s", logging->name); return; } logging->linePointer = buffer; logging->linePointer[0] = 0; }
ioportid_t getHwPort(const char *msg, brain_pin_e brainPin) { if (brainPin == GPIO_UNASSIGNED || brainPin == GPIO_INVALID) return GPIO_NULL; if (brainPin < GPIOA_0 || brainPin > GPIOH_15) { firmwareError(CUSTOM_ERR_INVALID_PIN, "%s: Invalid brain_pin_e: %d", msg, brainPin); return GPIO_NULL; } return PORTS[(brainPin - GPIOA_0)/ PORT_SIZE]; }
ioportmask_t getHwPin(brain_pin_e brainPin) { if (brainPin == GPIO_UNASSIGNED) return EFI_ERROR_CODE; if (brainPin > GPIO_UNASSIGNED || brainPin < 0) { firmwareError("Invalid brain_pin_e: %d", brainPin); return EFI_ERROR_CODE; } return brainPin % PORT_SIZE; }
/** * @brief Reset histogram_s to orignal state */ void initHistogram(histogram_s *h, const char *name) { if (efiStrlen(name) > sizeof(h->name) - 1) { firmwareError(OBD_PCM_Processor_Fault, "Histogram name [%s] too long", name); } strcpy(h->name, name); h->total_value = 0; h->total_count = 0; memset(h->values, 0, sizeof(h->values)); }
GPIO_TypeDef * getHwPort(brain_pin_e brainPin) { if (brainPin == GPIO_UNASSIGNED) return GPIO_NULL; if (brainPin > GPIO_UNASSIGNED || brainPin < 0) { firmwareError("Invalid brain_pin_e: %d", brainPin); return GPIO_NULL; } return PORTS[brainPin / PORT_SIZE]; }
ioportid_t getHwPort(brain_pin_e brainPin) { if (brainPin == GPIO_UNASSIGNED) return GPIO_NULL; if (brainPin > GPIO_UNASSIGNED || brainPin < 0) { firmwareError(CUSTOM_ERR_INVALID_PIN, "Invalid brain_pin_e: %d", brainPin); return GPIO_NULL; } return PORTS[brainPin / PORT_SIZE]; }
void lcd_HD44780_init(Logging *sharedLogger) { logger = sharedLogger; addConsoleAction("lcdinfo", lcdInfo); if (engineConfiguration->displayMode > DM_HD44780_OVER_PCF8574) { firmwareError("Unexpected displayMode %d", engineConfiguration->displayMode); return; } printMsg(logger, "lcd_HD44780_init %d", engineConfiguration->displayMode); if (engineConfiguration->displayMode == DM_HD44780) { // initialize hardware lines mySetPadMode2("lcd RS", boardConfiguration->HD44780_rs, PAL_MODE_OUTPUT_PUSHPULL); mySetPadMode2("lcd E", boardConfiguration->HD44780_e, PAL_MODE_OUTPUT_PUSHPULL); mySetPadMode2("lcd DB4", boardConfiguration->HD44780_db4, PAL_MODE_OUTPUT_PUSHPULL); mySetPadMode2("lcd DB6", boardConfiguration->HD44780_db5, PAL_MODE_OUTPUT_PUSHPULL); mySetPadMode2("lcd DB7", boardConfiguration->HD44780_db6, PAL_MODE_OUTPUT_PUSHPULL); mySetPadMode2("lcd DB8", boardConfiguration->HD44780_db7, PAL_MODE_OUTPUT_PUSHPULL); // and zero values palWritePad(getHwPort(boardConfiguration->HD44780_rs), getHwPin(boardConfiguration->HD44780_rs), 0); palWritePad(getHwPort(boardConfiguration->HD44780_e), getHwPin(boardConfiguration->HD44780_e), 0); palWritePad(getHwPort(boardConfiguration->HD44780_db4), getHwPin(boardConfiguration->HD44780_db4), 0); palWritePad(getHwPort(boardConfiguration->HD44780_db5), getHwPin(boardConfiguration->HD44780_db5), 0); palWritePad(getHwPort(boardConfiguration->HD44780_db6), getHwPin(boardConfiguration->HD44780_db6), 0); palWritePad(getHwPort(boardConfiguration->HD44780_db7), getHwPin(boardConfiguration->HD44780_db7), 0); } chThdSleepMilliseconds(20); // LCD needs some time to wake up lcd_HD44780_write(LCD_HD44780_RESET); // reset 1x chThdSleepMilliseconds(1); lcd_HD44780_write(LCD_HD44780_RESET); // reset 2x lcd_HD44780_write(LCD_HD44780_RESET); // reset 3x lcd_HD44780_write(LCD_HD44780_4_BIT_BUS); // 4 bit, 2 line chThdSleepMicroseconds(40); lcd_HD44780_write(LCD_HD44780_4_BIT_BUS); // 4 bit, 2 line lcd_HD44780_write(0x80); chThdSleepMicroseconds(40); lcd_HD44780_write_command(0x08); // display and cursor control chThdSleepMicroseconds(40); lcd_HD44780_write_command(LCD_HD44780_DISPLAY_CLEAR); chThdSleepMilliseconds(2); lcd_HD44780_write_command(LCD_HD44780_SHIFT_CURSOR_RIGHT); chThdSleepMilliseconds(2); lcd_HD44780_write_command(LCD_HD44780_DISPLAY_ON); lcd_HD44780_set_position(0, 0); printMsg(logger, "lcd_HD44780_init() done"); }
void startTunerStudioConnectivity(void) { if (sizeof(persistent_config_s) != getTunerStudioPageSize(0)) firmwareError("TS page size mismatch: %d/%d", sizeof(persistent_config_s), getTunerStudioPageSize(0)); if (sizeof(TunerStudioOutputChannels) != TS_OUTPUT_SIZE) firmwareError("TS outputs size mismatch: %d/%d", sizeof(TunerStudioOutputChannels), TS_OUTPUT_SIZE); memset(&tsState, 0, sizeof(tsState)); syncTunerStudioCopy(); addConsoleAction("tsinfo", printTsStats); addConsoleAction("reset_ts", resetTs); addConsoleActionI("set_ts_speed", setTsSpeed); tsChannel.channel = getTsSerialDevice(); tsChannel.writeBuffer = tsCrcWriteBuffer; chThdCreateStatic(tsThreadStack, sizeof(tsThreadStack), NORMALPRIO, tsThreadEntryPoint, NULL); }
static uint32_t doFindTrigger(TriggerStimulatorHelper *helper, trigger_shape_s * shape, trigger_config_s const*triggerConfig, TriggerState *state) { for (int i = 0; i < 4 * PWM_PHASE_MAX_COUNT; i++) { helper->nextStep(state, shape, i, triggerConfig); if (state->shaft_is_synchronized) return i; } firmwareError("findTriggerZeroEventIndex() failed"); return EFI_ERROR_CODE; }
static void doAddAction(const char *token, action_type_e type, Void callback, void *param) { for (uint32_t i = 0; i < efiStrlen(token);i++) { char ch = token[i]; if (ch != mytolower(ch)) { firmwareError(CUSTOM_ERR_COMMAND_LOWER_CASE_EXPECTED, "lowerCase expected [%s]", token); } } for (int i = 0; i < consoleActionCount; i++) { if (strcmp(token, consoleActions[i].token) == 0 /* zero result means strings are equal */) { firmwareError(CUSTOM_SAME_TWICE, "Same action twice [%s]", token); } } efiAssertVoid(CUSTOM_CONSOLE_TOO_MANY, consoleActionCount < CONSOLE_MAX_ACTIONS, "Too many console actions"); TokenCallback *current = &consoleActions[consoleActionCount++]; current->token = token; current->parameterType = type; current->callback = callback; current->param = param; }
/** * @returns true if data does not fit into this buffer */ static bool validateBuffer(Logging *logging, uint32_t extraLen) { if (logging->buffer == NULL) { firmwareError("Logging not initialized: %s", logging->name); return true; } if (remainingSize(logging) < extraLen + 1) { warning(OBD_PCM_Processor_Fault, "buffer overflow %s", logging->name); return true; } return false; }
static void addChannel(const char *name, adc_channel_e setting, adc_channel_mode_e mode) { if (setting == EFI_ADC_NONE) { return; } if (adcHwChannelEnabled[setting] != ADC_OFF) { getPinNameByAdcChannel(name, setting, errorMsgBuff); firmwareError(CUSTOM_ERR_ADC_USED, "ADC mapping error: input %s for %s already used by %s?", errorMsgBuff, name, adcHwChannelUsage[setting]); } adcHwChannelUsage[setting] = name; adcHwChannelEnabled[setting] = mode; }
OutputSignal * OutputSignalList::add(io_pin_e ioPin) { if (size == OUTPUT_SIGNAL_MAX_SIZE) { firmwareError("Too many signals, adding %d", ioPin); return NULL; } OutputSignal *signal = &signals[size++]; initOutputSignal(signal, ioPin); return signal; }
/** * this method acquires system lock to guard the shared intermediateLoggingBuffer memory stream */ void vappendPrintf(Logging *logging, const char *fmt, va_list arg) { efiAssertVoid(getRemainingStack(chThdSelf()) > 128, "lowstck#5b"); if (!intermediateLoggingBufferInited) { firmwareError("intermediateLoggingBufferInited not inited!"); return; } int wasLocked = lockAnyContext(); vappendPrintfI(logging, fmt, arg); if (!wasLocked) { unlockAnyContext(); } }
static void usTimerWatchDog(void) { if (getTimeNowNt() >= lastSetTimerTimeNt + 2 * CORE_CLOCK) { strcpy(buff, "no_event"); itoa10(&buff[8], lastSetTimerValue); firmwareError(OBD_PCM_Processor_Fault, buff); return; } msg = isTimerPending ? "No_cb too long" : "Timer not awhile"; // 2 seconds of inactivity would not look right efiAssertVoid(getTimeNowNt() < lastSetTimerTimeNt + 2 * CORE_CLOCK, msg); }
void PeriodicTask(efitime_t nowNt) override { if (nowNt >= lastSetTimerTimeNt + 2 * CORE_CLOCK) { strcpy(buff, "no_event"); itoa10(&buff[8], lastSetTimerValue); firmwareError(CUSTOM_ERR_SCHEDULING_ERROR, buff); return; } msg = isTimerPending ? "No_cb too long" : "Timer not awhile"; // 2 seconds of inactivity would not look right efiAssertVoid(CUSTOM_ERR_6682, nowNt < lastSetTimerTimeNt + 2 * CORE_CLOCK, msg); }
/** * Number of injections into each cylinder per engine cycle */ static int getNumberOfInjections(injection_mode_e mode DECLARE_ENGINE_PARAMETER_S) { switch (mode) { case IM_SIMULTANEOUS: return engineConfiguration->specs.cylindersCount; case IM_SEQUENTIAL: return 1; case IM_BATCH: return engineConfiguration->specs.cylindersCount / 2; default: firmwareError("Unexpected getFuelMultiplier %d", mode); return 1; } }
/* * Return current TPS position based on configured ADC levels, and adc * * */ float getTpsValue(int adc) { if (adc < engineConfiguration->tpsMin) { return 0.0f; } if (adc > engineConfiguration->tpsMax) { return 100.0f; } // todo: double comparison using EPS if (engineConfiguration->tpsMin == engineConfiguration->tpsMax) { firmwareError("Invalid TPS configuration: same value"); return 0.0f; } return interpolate(engineConfiguration->tpsMin, 0, engineConfiguration->tpsMax, 100, adc); }
/** * @returns true if data does not fit into this buffer */ static INLINE bool validateBuffer(Logging *logging, uint32_t extraLen) { if (logging->buffer == NULL) { firmwareError("Logging not initialized: %s", logging->name); return true; } if (remainingSize(logging) < extraLen + 1) { #if EFI_PROD_CODE warning(OBD_PCM_Processor_Fault, "output overflow %s", logging->name); #endif return true; } return false; }
/** * @brief Initialize the hardware output pin while also assigning it a logical name */ void initOutputPinExt(const char *msg, OutputPin *outputPin, ioportid_t port, uint32_t pinNumber, iomode_t mode) { if (outputPin->port != NULL && (outputPin->port != port || outputPin->pin != pinNumber)) { /** * here we check if another physical pin is already assigned to this logical output */ // todo: need to clear '&outputs' in io_pins.c firmwareError(OBD_PCM_Processor_Fault, "outputPin [%s] already assigned to %x%d", msg, outputPin->port, outputPin->pin); return; } outputPin->currentLogicValue = INITIAL_PIN_STATE; outputPin->port = port; outputPin->pin = pinNumber; mySetPadMode(msg, port, pinNumber, mode); }
void EventQueue::insertTask(scheduling_s *scheduling, uint64_t nowUs, int delayUs, schfunc_t callback, void *param) { if (callback == NULL) firmwareError("NULL callback"); uint64_t time = nowUs + delayUs; int alreadyPending = checkIfPending(scheduling); if (alreadyPending || hasFirmwareError()) return; scheduling->momentUs = time; scheduling->callback = callback; scheduling->param = param; LL_PREPEND(head, scheduling); }
static const char *getPinShortName(io_pin_e pin) { switch (pin) { case ALTERNATOR_SWITCH: return "AL"; case FUEL_PUMP_RELAY: return "FP"; case FAN_RELAY: return "FN"; case O2_HEATER: return "O2H"; default: firmwareError("No short name for %d", (int) pin); return ""; } }
/** * Schedules a callback 'angle' degree of crankshaft from now. * The callback would be executed once after the duration of time which * it takes the crankshaft to rotate to the specified angle. */ void scheduleByAngle(int rpm, scheduling_s *timer, angle_t angle, schfunc_t callback, void *param) { if (!isValidRpm(rpm)) { /** * this might happen in case of a single trigger event after a pause - this is normal, so no * warning here */ return; } float delayUs = getOneDegreeTimeUs(rpm) * angle; if (cisnan(delayUs)) { firmwareError("NaN delay?"); return; } scheduleTask("by angle", timer, (int) delayUs, callback, param); }
//Nullable ICUDriver * getInputCaptureDriver(const char *msg, brain_pin_e hwPin) { if (hwPin == GPIO_UNASSIGNED || hwPin == GPIO_INVALID) { return NULL; } #if STM32_ICU_USE_TIM1 if (hwPin == GPIOA_8 || hwPin == GPIOA_9 || hwPin == GPIOE_9 || hwPin == GPIOE_11) { return &ICUD1; } #endif #if STM32_ICU_USE_TIM2 if (hwPin == GPIOA_1 || hwPin == GPIOA_5 || hwPin == GPIOA_15 || hwPin == GPIOB_3) { return &ICUD2; } #endif #if STM32_ICU_USE_TIM3 if (hwPin == GPIOA_6 || hwPin == GPIOA_7 || hwPin == GPIOB_4 || hwPin == GPIOB_5 || hwPin == GPIOC_6 || hwPin == GPIOC_7) { return &ICUD3; } #endif #if STM32_ICU_USE_TIM8 if (hwPin == GPIOC_6 || hwPin == GPIOC_7) { return &ICUD8; } #endif #if STM32_ICU_USE_TIM9 if (hwPin == GPIOA_2 || hwPin == GPIOA_3 || hwPin == GPIOE_5 || hwPin == GPIOE_6) { return &ICUD9; } #endif firmwareError(CUSTOM_ERR_NOT_INPUT_PIN, "%s: Not input pin %s", msg, hwPortname(hwPin)); return (ICUDriver *) NULL; }
void initializeIgnitionActions(float advance, float dwellAngle, engine_configuration_s *engineConfiguration, engine_configuration2_s *engineConfiguration2, IgnitionEventList *list) { efiAssertVoid(engineConfiguration->cylindersCount > 0, "cylindersCount"); list->resetEventList(); switch (engineConfiguration->ignitionMode) { case IM_ONE_COIL: for (int i = 0; i < engineConfiguration->cylindersCount; i++) { // todo: extract method float localAdvance = advance + 720.0f * i / engineConfiguration->cylindersCount; registerSparkEvent(engineConfiguration, &engineConfiguration2->triggerShape, list, SPARKOUT_1_OUTPUT, localAdvance, dwellAngle); } break; case IM_WASTED_SPARK: for (int i = 0; i < engineConfiguration->cylindersCount; i++) { float localAdvance = advance + 720.0f * i / engineConfiguration->cylindersCount; int wastedIndex = i % (engineConfiguration->cylindersCount / 2); int id = getCylinderId(engineConfiguration->firingOrder, wastedIndex) - 1; io_pin_e ioPin = (io_pin_e) (SPARKOUT_1_OUTPUT + id); registerSparkEvent(engineConfiguration, &engineConfiguration2->triggerShape, list, ioPin, localAdvance, dwellAngle); } break; case IM_INDIVIDUAL_COILS: for (int i = 0; i < engineConfiguration->cylindersCount; i++) { float localAdvance = advance + 720.0f * i / engineConfiguration->cylindersCount; io_pin_e pin = (io_pin_e) ((int) SPARKOUT_1_OUTPUT + getCylinderId(engineConfiguration->firingOrder, i) - 1); registerSparkEvent(engineConfiguration, &engineConfiguration2->triggerShape, list, pin, localAdvance, dwellAngle); } break; default: firmwareError("unsupported ignitionMode %d in initializeIgnitionActions()", engineConfiguration->ignitionMode); } }
/** * @param index from zero to cylindersCount - 1 * @return cylinderId from one to cylindersCount */ int getCylinderId(firing_order_e firingOrder, int index) { switch (firingOrder) { case FO_ONE_CYLINDER: return 1; case FO_1_THEN_3_THEN_4_THEN2: return order_1_THEN_3_THEN_4_THEN2[index]; case FO_1_THEN_5_THEN_3_THEN_6_THEN_2_THEN_4: return order_1_THEN_5_THEN_3_THEN_6_THEN_2_THEN_4[index]; case FO_1_8_4_3_6_5_7_2: return order_1_8_4_3_6_5_7_2[index]; default: firmwareError("getCylinderId not supported for %d", firingOrder); } return -1; }