rusefi-1/firmware/controllers/gauges/lcd_controller.cpp

349 lines
9.7 KiB
C++
Raw Normal View History

2015-07-10 06:01:56 -07:00
/**
* @file lcd_controller.cpp
*
2017-12-04 15:30:44 -08:00
* LCD is a tree-like set of menues controlled by a joystick. At the moment three actions are supported:
* "next item"
* "enter sub-menu"
* "return one level up"
*
2017-12-04 15:34:26 -08:00
* In case of a 20x4 display top three lines are three menu items you can scroll through and
* bottom line is error or warning line.
*
* By default the first line shows current RPM and time since boot in seconds.
* The "more" symbol points at the currently selected menu item.
*
2015-07-10 06:01:56 -07:00
* @date Aug 14, 2014
2020-01-13 18:57:43 -08:00
* @author Andrey Belomutskiy, (c) 2012-2020
2015-07-10 06:01:56 -07:00
*/
#include "pch.h"
2018-10-30 05:21:50 -07:00
2019-04-12 19:07:03 -07:00
#if EFI_HD44780_LCD
#include "os_access.h"
2018-10-30 05:21:50 -07:00
2015-07-10 06:01:56 -07:00
#include "lcd_controller.h"
#include "HD44780.h"
2015-07-10 06:01:56 -07:00
#include "rtc_helper.h"
#include "svnversion.h"
#include "joystick.h"
#include "utlist.h"
#include "lcd_menu_tree.h"
#include "memstreams.h"
#include "settings.h"
#include "bench_test.h"
2015-09-15 17:02:25 -07:00
#include "mmc_card.h"
2016-12-26 18:04:16 -08:00
#include "idle_thread.h"
#include "fuel_math.h"
2015-07-10 06:01:56 -07:00
static MenuItem ROOT(NULL, NULL);
static MenuTree tree(&ROOT);
2016-04-23 20:07:45 -07:00
/**
* todo: add some comment explaining how this works
*/
2015-07-10 06:01:56 -07:00
static MenuItem miRpm(tree.root, LL_RPM);
2019-01-12 01:53:06 -08:00
static MenuItem miSensors(tree.root, "SENSORS");
static MenuItem miFuelControl(tree.root, "FUEL CONTROL");
static MenuItem miBench(tree.root, "BENCH TEST");
static MenuItem miAbout(tree.root, "ABOUT");
2015-07-10 06:01:56 -07:00
static MenuItem miTriggerErrors(&miRpm, LL_TRIGGER_ERRORS);
static MenuItem miTriggerDuty(&miRpm, LL_TRIGGER_DUTY);
2017-03-06 22:52:54 -08:00
static MenuItem miFuelCltCorr(&miFuelControl, LL_FUEL_CLT_CORRECTION);
2019-01-12 01:53:06 -08:00
static MenuItem miFuelIatCorr(&miFuelControl, LL_FUEL_IAT_CORRECTION);
static MenuItem miFuelInjectorLag(&miFuelControl, LL_FUEL_INJECTOR_LAG);
2017-03-06 22:52:54 -08:00
2015-07-10 06:01:56 -07:00
static MenuItem miClt(&miSensors, LL_CLT_TEMPERATURE);
static MenuItem miIat(&miSensors, LL_IAT_TEMPERATURE);
static MenuItem miTps(&miSensors, LL_TPS);
static MenuItem miVBatt(&miSensors, LL_VBATT);
static MenuItem miMap(&miSensors, LL_MAP);
static MenuItem miAfr(&miSensors, LL_AFR);
static MenuItem miBaro(&miSensors, LL_BARO);
static MenuItem miMapV(&miSensors, LL_MAF_V);
static MenuItem miMapKgHr(&miSensors, LL_MAF_KG_HR);
2019-01-05 20:33:04 -08:00
static MenuItem miStopEngine(&miBench, "stop engine", scheduleStopEngine);
2015-07-10 06:01:56 -07:00
static MenuItem miTestFan(&miBench, "test fan", fanBench);
static MenuItem miTestFuelPump(&miBench, "test pump", fuelPumpBench);
2016-04-23 20:07:45 -07:00
static MenuItem miTestMIL(&miBench, "test MIL", milBench);
2016-12-26 18:04:16 -08:00
static MenuItem miTestIAC(&miBench, "test IAC", startIdleBench);
2016-04-23 20:07:45 -07:00
// todo: looks like these are not finished yet?
2015-07-10 06:01:56 -07:00
static MenuItem miTestSpark1(&miBench, "test spark1");
static MenuItem miTestSpark2(&miBench, "test spark2");
static MenuItem miTestSpark3(&miBench, "test spark3");
static MenuItem miTestSpark4(&miBench, "test spark4");
static MenuItem miTestInj1(&miBench, "test injector1");
static MenuItem miTestInj2(&miBench, "test injector2");
static MenuItem miTestInj3(&miBench, "test injector3");
static MenuItem miTestInj4(&miBench, "test injector4");
static MenuItem miVersion(&miAbout, LL_VERSION);
static MenuItem miConfig(&miAbout, LL_CONFIG);
static MenuItem miAlgo(&miAbout, LL_ALGORITHM);
static MenuItem miInjection(&miAbout, LL_INJECTION);
static MenuItem miIgnition(&miAbout, LL_IGNITION);
static MenuItem miInjFlow(&miAbout, LL_ING_FLOW);
#define DISP_LINES (engineConfiguration->HD44780height - 1)
static char lcdLineBuffer[30];
static MemoryStream lcdLineStream;
void onJoystick(joystick_button_e button) {
/**
* this method is invoked on EXTI IRQ thread
*/
if (button == JB_CENTER) {
tree.enterSubMenu();
} else if (button == JB_BUTTON_D) {
tree.nextItem();
} else if (button == JB_BUTTON_A) {
tree.back();
}
// actual repaint happends in the repaint loop
}
char * appendStr(char *ptr, const char *suffix) {
for (uint32_t i = 0; i < efiStrlen(suffix); i++) {
*ptr++ = suffix[i];
}
return ptr;
}
void initLcdController(void) {
tree.init(&miRpm, engineConfiguration->HD44780height - 1);
msObjectInit(&lcdLineStream, (uint8_t *) lcdLineBuffer, sizeof(lcdLineBuffer), 0);
}
static char buffer[MAX_LCD_WIDTH + 4];
static void lcdPrintf(const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
2017-05-09 09:07:52 -07:00
// todo: migrate to chsnprintf
2015-07-10 06:01:56 -07:00
lcdLineStream.eos = 0; // reset
chvprintf((BaseSequentialStream *) &lcdLineStream, fmt, ap);
lcdLineStream.buffer[lcdLineStream.eos] = 0; // terminator
va_end(ap);
lcd_HD44780_print_string(lcdLineBuffer);
}
static void showLine(lcd_line_e line, int /*screenY*/) {
static char buffer[_MAX_FILLER + 2];
2015-07-10 06:01:56 -07:00
switch (line) {
case LL_VERSION:
2019-01-12 01:53:06 -08:00
lcdPrintf("ver %s %d", VCS_VERSION, getRusEfiVersion());
2015-07-10 06:01:56 -07:00
return;
case LL_CONFIG:
2021-10-20 07:38:01 -07:00
lcdPrintf("config %s", getEngine_type_e(engineConfiguration->engineType));
2015-07-10 06:01:56 -07:00
return;
case LL_RPM:
2019-01-12 01:53:06 -08:00
{
int seconds = minI(9999, getTimeNowSeconds());
2022-01-20 19:38:08 -08:00
lcdPrintf("RPM %d %d ", (int)Sensor::getOrZero(SensorType::Rpm), seconds);
2019-01-12 01:53:06 -08:00
}
2019-04-12 19:07:03 -07:00
#if EFI_FILE_LOGGING
2015-07-10 06:01:56 -07:00
{
2015-09-15 17:02:25 -07:00
char sdState;
if (engineConfiguration->isSdCardEnabled) {
2015-09-15 17:02:25 -07:00
sdState = isSdCardAlive() ? 'L' : 'n';
} else {
sdState = 'D';
}
2019-01-12 01:53:06 -08:00
lcdPrintf("%c", sdState);
2015-07-10 06:01:56 -07:00
}
2015-10-18 08:01:34 -07:00
#endif
2015-07-10 06:01:56 -07:00
return;
case LL_CLT_TEMPERATURE:
2021-10-05 16:59:07 -07:00
lcdPrintf("Coolant %.2f", Sensor::getOrZero(SensorType::Clt));
2015-07-10 06:01:56 -07:00
return;
case LL_IAT_TEMPERATURE:
2021-10-05 16:59:07 -07:00
lcdPrintf("Intake Air %.2f", Sensor::getOrZero(SensorType::Iat));
2015-07-10 06:01:56 -07:00
return;
case LL_ALGORITHM:
2016-08-28 13:02:34 -07:00
lcdPrintf(getEngine_load_mode_e(engineConfiguration->fuelAlgorithm));
2015-07-10 06:01:56 -07:00
return;
case LL_INJECTION:
lcdPrintf(getInjection_mode_e(engineConfiguration->injectionMode));
return;
case LL_ING_FLOW:
2018-01-23 09:05:14 -08:00
lcdPrintf("Inj %.2fcc", engineConfiguration->injector.flow);
2015-07-10 06:01:56 -07:00
return;
case LL_IGNITION:
lcdPrintf(getIgnition_mode_e(engineConfiguration->ignitionMode));
return;
case LL_TPS:
getPinNameByAdcChannel("tps", engineConfiguration->tps1_1AdcChannel, buffer);
2015-07-10 06:01:56 -07:00
2021-10-05 16:59:07 -07:00
lcdPrintf("Throttle %s %.2f%%", buffer, Sensor::getOrZero(SensorType::Tps1));
2015-07-10 06:01:56 -07:00
return;
2017-03-06 22:52:54 -08:00
case LL_FUEL_CLT_CORRECTION:
lcdPrintf("CLT corr %.2f", getCltFuelCorrection());
2019-01-12 01:53:06 -08:00
return;
case LL_FUEL_IAT_CORRECTION:
lcdPrintf("IAT corr %.2f", getIatFuelCorrection());
2019-01-12 01:53:06 -08:00
return;
case LL_FUEL_INJECTOR_LAG:
lcdPrintf("ING LAG %.2f", engine->engineState.running.injectorLag);
2017-03-06 22:52:54 -08:00
return;
2015-07-10 06:01:56 -07:00
case LL_VBATT:
2021-10-05 16:59:07 -07:00
lcdPrintf("Battery %.2fv", Sensor::getOrZero(SensorType::BatteryVoltage));
2015-07-10 06:01:56 -07:00
return;
2019-04-12 19:07:03 -07:00
#if EFI_ANALOG_SENSORS
2015-07-10 06:01:56 -07:00
case LL_BARO:
if (Sensor::hasSensor(SensorType::BarometricPressure)) {
lcdPrintf("Baro: %.2f", Sensor::getOrZero(SensorType::BarometricPressure));
2015-07-10 06:01:56 -07:00
} else {
lcdPrintf("Baro: none");
}
return;
#endif
case LL_AFR:
if (Sensor::hasSensor(SensorType::Lambda1)) {
2021-10-05 16:59:07 -07:00
lcdPrintf("AFR: %.2f", Sensor::getOrZero(SensorType::Lambda1));
2015-07-10 06:01:56 -07:00
} else {
lcdPrintf("AFR: none");
}
return;
case LL_MAP:
2021-10-04 15:33:10 -07:00
if (Sensor::hasSensor(SensorType::Map)) {
2021-10-05 16:59:07 -07:00
lcdPrintf("MAP %.2f", Sensor::getOrZero(SensorType::Map));
2015-07-10 06:01:56 -07:00
} else {
lcdPrintf("MAP: none");
}
return;
case LL_MAF_V:
if (Sensor::hasSensor(SensorType::Maf)) {
lcdPrintf("MAF: %.2fv", Sensor::getRaw(SensorType::Maf));
2015-07-10 06:01:56 -07:00
} else {
lcdPrintf("MAF: none");
}
return;
case LL_MAF_KG_HR:
if (Sensor::hasSensor(SensorType::Maf)) {
2021-10-05 16:59:07 -07:00
lcdPrintf("MAF: %.2f kg/hr", Sensor::getOrZero(SensorType::Maf));
2015-07-10 06:01:56 -07:00
} else {
lcdPrintf("MAF: none");
}
return;
case LL_TRIGGER_ERRORS:
lcdPrintf("Errors");
return;
case LL_TRIGGER_DUTY:
lcdPrintf("Duty");
return;
default:
lcdPrintf("()");
}
}
static void fillWithSpaces() {
2015-07-10 06:01:56 -07:00
int column = getCurrentHD44780column();
for (int r = column; r < 20; r++) {
lcd_HD44780_print_char(' ');
}
}
2017-05-08 05:15:46 -07:00
void updateHD44780lcd(void) {
2015-07-10 06:01:56 -07:00
MenuItem *p = tree.topVisible;
int screenY = 0;
2019-10-07 22:26:35 -07:00
for (; screenY < tree.linesCount && p != nullptr; screenY++) {
2015-07-10 06:01:56 -07:00
lcd_HD44780_set_position(screenY, 0);
char firstChar;
if (p == tree.current) {
if (p->callback != NULL) {
firstChar = '!';
} else {
firstChar = p->firstChild == NULL ? '*' : '>';
}
} else {
firstChar = ' ';
}
lcd_HD44780_print_char(firstChar);
if (p->lcdLine == LL_STRING) {
lcd_HD44780_print_string(p->text);
} else {
showLine(p->lcdLine, screenY);
}
fillWithSpaces();
p = p->next;
}
for (; screenY < tree.linesCount; screenY++) {
lcd_HD44780_set_position(screenY, 0);
fillWithSpaces();
}
2016-12-30 11:02:37 -08:00
2022-04-16 14:35:59 -07:00
const char * message = hasFirmwareErrorFlag ? getCriticalErrorMessage() : getWarningMessage();
2016-12-30 11:02:37 -08:00
memcpy(buffer, message, engineConfiguration->HD44780width);
2015-07-10 06:01:56 -07:00
buffer[engineConfiguration->HD44780width] = 0;
lcd_HD44780_set_position(engineConfiguration->HD44780height - 1, 0);
lcd_HD44780_print_string(buffer);
fillWithSpaces();
//
// lcd_HD44780_set_position(0, 9);
// /**
// * this would blink so that we know the LCD is alive
// */
// if (isEven) {
// lcd_HD44780_print_char('R');
// } else {
// lcd_HD44780_print_char(' ');
// }
// lcd_HD44780_set_position(0, 10);
//
2022-01-20 19:38:08 -08:00
// char * ptr = itoa10(buffer, Sensor::getOrZero(SensorType::Rpm));
2015-07-10 06:01:56 -07:00
// ptr[0] = 0;
// int len = ptr - buffer;
// for (int i = 0; i < 6 - len; i++) {
// lcd_HD44780_print_char(' ');
// }
// lcd_HD44780_print_string(buffer);
//
// if (hasFirmwareError()) {
2022-04-16 14:35:59 -07:00
// memcpy(buffer, getCriticalErrorMessage(), LCD_WIDTH);
2015-07-10 06:01:56 -07:00
// buffer[LCD_WIDTH] = 0;
// lcd_HD44780_set_position(1, 0);
// lcd_HD44780_print_string(buffer);
// return;
// }
//
// lcd_HD44780_set_position(1, 0);
// memset(buffer, ' ', LCD_WIDTH);
2020-03-28 18:28:32 -07:00
// memcpy(buffer, getWarningMessage(), LCD_WIDTH);
2015-07-10 06:01:56 -07:00
// buffer[LCD_WIDTH] = 0;
// lcd_HD44780_print_string(buffer);
//
// if (engineConfiguration->HD44780height < 3) {
// return;
// }
//
// int index = (getTimeNowSeconds() / 2) % (NUMBER_OF_DIFFERENT_LINES / 2);
//
// prepareCurrentSecondLine(engine, index);
// buffer[LCD_WIDTH] = 0;
// lcd_HD44780_set_position(2, 0);
// lcd_HD44780_print_string(buffer);
//
// prepareCurrentSecondLine(engine, index + NUMBER_OF_DIFFERENT_LINES / 2);
// buffer[LCD_WIDTH] = 0;
// lcd_HD44780_set_position(3, 0);
// lcd_HD44780_print_string(buffer);
//
//#if EFI_PROD_CODE
// dateToString(dateBuffer);
// lcd_HD44780_set_position(1, 0);
// lcd_HD44780_print_string(dateBuffer);
//#endif /* EFI_PROD_CODE */
}
#endif