/*
* (C) Copyright 2015 by fr3ts0n <erwin.scheuch-heilig@gmx.at>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
package com.fr3ts0n.ecu;
import java.util.Arrays;
import java.util.Comparator;
/**
* Collection of all known OBD data items (PIDs)
*
* @author erwin
*/
public class Pids
{
// maximum values / bitmasks per affected byte
public static final long[] valueMask =
{
0x00,
0xFF,
0xFFFF,
0xFFFFFF,
0xFFFFFFFF
};
/* PID definitions */
public static final Pid[] PIDs =
{
// pid,ofs,len, formula digits label
new Pid(0x01, 0, 1, Conversions.CNV_ID_ONETOONE, 0, "Number of Fault Codes"), // fuel_system1_status_formula // fuel_system2_status_formula
new Pid(0x02, 0, 2, Conversions.CNV_ID_OBD_CODELIST, -1, "DTC-Fault location"), // fault location conversion
new Pid(0x03, 0, 2, Conversions.CNV_ID_ONETOONE, 0, "Fuel System Status"), // fuel_system1_status_formula // fuel_system2_status_formula
new Pid(0x04, 0, 1, Conversions.CNV_ID_PERCENT, 1, "Calculated Load Value"),
new Pid(0x05, 0, 1, Conversions.CNV_ID_TEMPERATURE, 1, "Coolant Temperature"),
new Pid(0x06, 0, 2, Conversions.CNV_ID_PERCENT7_REL, 1, "Short Term Fuel Trim (Bank 1)"), // short_term_fuel_trim
new Pid(0x07, 0, 2, Conversions.CNV_ID_PERCENT7_REL, 1, "Long Term Fuel Trim (Bank 1)"), // long_term_fuel_trim
new Pid(0x08, 0, 2, Conversions.CNV_ID_PERCENT7_REL, 1, "Short Term Fuel Trim (Bank 2)"), // short_term_fuel_trim
new Pid(0x09, 0, 2, Conversions.CNV_ID_PERCENT7_REL, 1, "Long Term Fuel Trim (Bank 2)"), // long_term_fuel_trim
new Pid(0x0A, 0, 1, Conversions.CNV_ID_PRESS, 1, "Fuel Pressure (gauge)"),
new Pid(0x0B, 0, 1, Conversions.CNV_ID_PRESS_AIR, 1, "Intake Manifold Pressure"),
new Pid(0x0C, 0, 2, Conversions.CNV_ID_RPM, 0, "Engine RPM"),
new Pid(0x0D, 0, 1, Conversions.CNV_ID_VEHSPEED, 0, "Vehicle Speed"),
new Pid(0x0E, 0, 1, Conversions.CNV_ID_ANGLE, 2, "Timing Advance (Cyl. #1)"),
new Pid(0x0F, 0, 1, Conversions.CNV_ID_TEMPERATURE, 1, "Intake Air Temperature"),
new Pid(0x10, 0, 2, Conversions.CNV_ID_AIRFLOW, 2, "Air Flow Rate (MAF sensor)"),
new Pid(0x11, 0, 1, Conversions.CNV_ID_PERCENT, 1, "Absolute Throttle Position"),
new Pid(0x12, 0, 1, Conversions.CNV_ID_ONETOONE, 0, "Secondary air status"), // secondary_air_status_formula,
new Pid(0x13, 0, 1, Conversions.CNV_ID_ONETOONE, 0, "Location of O2 Sensor(s)"), // o2_sensor_formula,
new Pid(0x14, 0, 2, Conversions.CNV_ID_ONETOONE, 0, "O2 Sensor 1, Bank 1"), // o2_sensor_formula,
new Pid(0x15, 0, 2, Conversions.CNV_ID_ONETOONE, 0, "O2 Sensor 2, Bank 1"), // o2_sensor_formula,
new Pid(0x16, 0, 2, Conversions.CNV_ID_ONETOONE, 0, "O2 Sensor 3, Bank 1"), // o2_sensor_formula,
new Pid(0x17, 0, 2, Conversions.CNV_ID_ONETOONE, 0, "O2 Sensor 4, Bank 1"), // o2_sensor_formula,
new Pid(0x18, 0, 2, Conversions.CNV_ID_ONETOONE, 0, "O2 Sensor 1, Bank 2"), // o2_sensor_formula,
new Pid(0x19, 0, 2, Conversions.CNV_ID_ONETOONE, 0, "O2 Sensor 2, Bank 2"), // o2_sensor_formula,
new Pid(0x1A, 0, 2, Conversions.CNV_ID_ONETOONE, 0, "O2 Sensor 3, Bank 2"), // o2_sensor_formula,
new Pid(0x1B, 0, 2, Conversions.CNV_ID_ONETOONE, 0, "O2 Sensor 4, Bank 2"), // o2_sensor_formula,
new Pid(0x1C, 0, 1, Conversions.CNV_ID_OBD_TYPE, -1, "OBD conforms to"), // obd_requirements_formula,
new Pid(0x1D, 0, 1, Conversions.CNV_ID_ONETOONE, 0, "Location of O2 Sensor(s)"), // o2_sensor_formula,
new Pid(0x1E, 0, 1, Conversions.CNV_ID_ONETOONE, 0, "Power Take-Off Status"), // pto_status_formula,
new Pid(0x1F, 0, 2, Conversions.CNV_ID_HOURS, 2, "Time Since Engine Start"),
new Pid(0x21, 0, 2, Conversions.CNV_ID_DISTANCE, 0, "Distance since MIL activated"),
new Pid(0x22, 0, 2, Conversions.CNV_ID_PRESS_REL, 3, "FRP rel. to manifold vacuum"), // fuel rail pressure relative to manifold vacuum
new Pid(0x23, 0, 2, Conversions.CNV_ID_PRESS_WIDERANGE, 1, "Fuel Pressure (gauge)"), // fuel rail pressure (gauge), wide range
new Pid(0x24, 0, 2, Conversions.CNV_ID_VOLTAGE_HIGHRES, 3, "O2 Sensor 1, Bank 1 (WR)"), // o2_sensor_wrv_formula, // o2 sensors (wide range), voltage
new Pid(0x25, 0, 2, Conversions.CNV_ID_VOLTAGE_HIGHRES, 3, "O2 Sensor 2, Bank 1 (WR)"), // o2_sensor_wrv_formula,
new Pid(0x26, 0, 2, Conversions.CNV_ID_VOLTAGE_HIGHRES, 3, "O2 Sensor 3, Bank 1 (WR)"), // o2_sensor_wrv_formula,
new Pid(0x27, 0, 2, Conversions.CNV_ID_VOLTAGE_HIGHRES, 3, "O2 Sensor 4, Bank 1 (WR)"), // o2_sensor_wrv_formula,
new Pid(0x28, 0, 2, Conversions.CNV_ID_VOLTAGE_HIGHRES, 3, "O2 Sensor 1, Bank 2 (WR)"), // o2_sensor_wrv_formula,
new Pid(0x29, 0, 2, Conversions.CNV_ID_VOLTAGE_HIGHRES, 3, "O2 Sensor 2, Bank 2 (WR)"), // o2_sensor_wrv_formula,
new Pid(0x2A, 0, 2, Conversions.CNV_ID_VOLTAGE_HIGHRES, 3, "O2 Sensor 3, Bank 2 (WR)"), // o2_sensor_wrv_formula,
new Pid(0x2B, 0, 2, Conversions.CNV_ID_VOLTAGE_HIGHRES, 3, "O2 Sensor 4, Bank 2 (WR)"), // o2_sensor_wrv_formula,
new Pid(0x2C, 0, 1, Conversions.CNV_ID_PERCENT, 1, "Commanded EGR"),
new Pid(0x2D, 0, 1, Conversions.CNV_ID_PERCENT_REL, 2, "EGR Error"),
new Pid(0x2E, 0, 1, Conversions.CNV_ID_PERCENT, 1, "Commanded Evaporative Purge"),
new Pid(0x2F, 0, 1, Conversions.CNV_ID_PERCENT, 1, "Fuel Level Input"),
new Pid(0x30, 0, 1, Conversions.CNV_ID_ONETOONE, 0, "Warm-ups since ECU reset"),
new Pid(0x31, 0, 2, Conversions.CNV_ID_DISTANCE, 0, "Distance since ECU reset"),
new Pid(0x32, 0, 2, Conversions.CNV_ID_PRESS_VAPOR, 2, "Evap System Vapor Pressure"),
new Pid(0x33, 0, 1, Conversions.CNV_ID_PRESS_AIR, 1, "Barometric Pressure (absolute)"),
new Pid(0x34, 0, 2, Conversions.CNV_ID_RATIO_WIDERANGE, 1, "O2 Sensor 1, Bank 1 (WR)"), // o2_sensor_wrc_formula, // o2 sensors (wide range), current
new Pid(0x35, 0, 2, Conversions.CNV_ID_RATIO_WIDERANGE, 1, "O2 Sensor 2, Bank 1 (WR)"), // o2_sensor_wrc_formula,
new Pid(0x36, 0, 2, Conversions.CNV_ID_RATIO_WIDERANGE, 1, "O2 Sensor 3, Bank 1 (WR)"), // o2_sensor_wrc_formula,
new Pid(0x37, 0, 2, Conversions.CNV_ID_RATIO_WIDERANGE, 1, "O2 Sensor 4, Bank 1 (WR)"), // o2_sensor_wrc_formula,
new Pid(0x38, 0, 2, Conversions.CNV_ID_RATIO_WIDERANGE, 1, "O2 Sensor 1, Bank 2 (WR)"), // o2_sensor_wrc_formula,
new Pid(0x39, 0, 2, Conversions.CNV_ID_RATIO_WIDERANGE, 1, "O2 Sensor 2, Bank 2 (WR)"), // o2_sensor_wrc_formula,
new Pid(0x3A, 0, 2, Conversions.CNV_ID_RATIO_WIDERANGE, 1, "O2 Sensor 3, Bank 2 (WR)"), // o2_sensor_wrc_formula,
new Pid(0x3B, 0, 2, Conversions.CNV_ID_RATIO_WIDERANGE, 1, "O2 Sensor 4, Bank 2 (WR)"), // o2_sensor_wrc_formula,
new Pid(0x3C, 0, 2, Conversions.CNV_ID_TEMP_WIDERANGE, 1, "CAT Temperature, B1S1"),
new Pid(0x3D, 0, 2, Conversions.CNV_ID_TEMP_WIDERANGE, 1, "CAT Temperature, B2S1"),
new Pid(0x3E, 0, 2, Conversions.CNV_ID_TEMP_WIDERANGE, 1, "CAT Temperature, B1S2"),
new Pid(0x3F, 0, 2, Conversions.CNV_ID_TEMP_WIDERANGE, 1, "CAT Temperature, B2S2"),
new Pid(0x41, 0, 4, Conversions.CNV_ID_ONETOONE, 0, "Monitor status for current driving cycle"),
new Pid(0x42, 0, 2, Conversions.CNV_ID_VOLTAGE, 3, "ECU voltage"),
new Pid(0x43, 0, 2, Conversions.CNV_ID_PERCENT, 1, "Absolute Engine Load"),
new Pid(0x44, 0, 2, Conversions.CNV_ID_RATIO, 3, "Commanded Equivalence Ratio"),
new Pid(0x45, 0, 1, Conversions.CNV_ID_PERCENT, 1, "Relative Throttle Position"),
new Pid(0x46, 0, 1, Conversions.CNV_ID_TEMPERATURE, 1, "Ambient Air Temperature"), // same scaling as $0F
new Pid(0x47, 0, 1, Conversions.CNV_ID_PERCENT, 1, "Absolute Throttle Position B"),
new Pid(0x48, 0, 1, Conversions.CNV_ID_PERCENT, 1, "Absolute Throttle Position C"),
new Pid(0x49, 0, 1, Conversions.CNV_ID_PERCENT, 1, "Accelerator Pedal Position D"),
new Pid(0x4A, 0, 1, Conversions.CNV_ID_PERCENT, 1, "Accelerator Pedal Position E"),
new Pid(0x4B, 0, 1, Conversions.CNV_ID_PERCENT, 1, "Accelerator Pedal Position F"),
new Pid(0x4C, 0, 1, Conversions.CNV_ID_PERCENT, 1, "Comm. Throttle Actuator Cntrl"), // commanded TAC
new Pid(0x4D, 0, 2, Conversions.CNV_ID_HOURS, 2, "Engine running while MIL on"), // minutes run by the engine while MIL activated
new Pid(0x4E, 0, 2, Conversions.CNV_ID_HOURS, 2, "Time since DTCs cleared"),
new Pid(0x4F, 0, 4, Conversions.CNV_ID_ONETOONE, 0, "Maximum values for Equivalence Ratio, Oxygen Sensor Voltage, Oxygen Sensor Current and Intake Manifold Absolute Pressure"),
};
/**
* Comparator object to compare Pid objects
*/
@SuppressWarnings("rawtypes")
static Comparator pidComparator = new Comparator()
{
public int compare(Object o1, Object o2)
{
int pid1 = o1 instanceof Pid ? ((Pid) o1).pid : Integer.valueOf(String.valueOf(o1));
int pid2 = o2 instanceof Pid ? ((Pid) o2).pid : Integer.valueOf(String.valueOf(o2));
return (pid1 - pid2);
}
};
/**
* Creates a new instance of Pids
*/
@SuppressWarnings("unchecked")
public Pids()
{
// ensure Array ist sorted
Arrays.sort(PIDs, pidComparator);
}
/**
* get the Pid-Object to numeric PID
*
* @param pidNum numeric PID to get PID-Object for
* @return PID-Object or NULL if no object available for specified PID
*/
@SuppressWarnings("unchecked")
public static Pid getPid(int pidNum)
{
// default result = NOT FOUND
Pid currPid = null;
// search list
int i = Arrays.binarySearch(PIDs, pidNum, pidComparator);
// if found, set result
if (i >= 0)
{
currPid = PIDs[i];
}
// and return it
return (currPid);
}
/**
* convert memory/protocol value to physical value
*
* @param memVal value in memory/protocol format
* @param pidNum PID to use for conversion
* @return physical value
*/
public static float memToPhys(long memVal, int pidNum)
{
float result = 0;
Pid currPid = getPid(pidNum);
if (currPid != null)
{
long mskdVal = memVal & valueMask[currPid.bytes];
result = Conversions.memToPhys(mskdVal, currPid.cnv);
}
return (result);
}
/**
* convert physical value to memory/protocol value
*
* @param physVal physical value
* @param pidNum PID to use for conversion
* @return value in memory/protocol layout
*/
public static long physToMem(float physVal, int pidNum)
{
long result = 0;
Pid currPid = getPid(pidNum);
if (currPid != null)
{
result = java.lang.Math.min(Conversions.physToMem(physVal, currPid.cnv),
valueMask[currPid.bytes]);
}
return (result);
}
}