#pragma once // BMW E46 K-Bus command table // Ported from muki01/I-K_Bus E46_Codes.h (MIT license) // PROGMEM removed (ESP32 flash is memory-mapped), wrapped in namespace. // // Message format: [source, length, destination, command, data...] // Checksums are NOT included — IbusEsp32::write() appends them automatically. // // Length byte = count of remaining bytes including the checksum that write() adds. // So for a 7-element array, length byte (index 1) should be 0x05 (5 bytes after length). #include namespace ibus { // --- Module addresses --- constexpr uint8_t M_GM5 = 0x00; // Body control module constexpr uint8_t M_CDC = 0x18; // CD Changer constexpr uint8_t M_DIA = 0x3F; // Diagnostic computer constexpr uint8_t M_EWS = 0x44; // Immobilizer constexpr uint8_t M_MFL = 0x50; // Steering wheel controls constexpr uint8_t M_IHKA = 0x5B; // Climate control panel constexpr uint8_t M_RAD = 0x68; // Radio constexpr uint8_t M_DSP = 0x6A; // Digital Sound Processor constexpr uint8_t M_IKE = 0x80; // Instrument cluster constexpr uint8_t M_SES = 0xB0; // Speed-dependent volume constexpr uint8_t M_ALL = 0xBF; // Broadcast constexpr uint8_t M_TEL = 0xC8; // Telephone constexpr uint8_t M_LCM = 0xD0; // Light Control Module constexpr uint8_t M_ANZV = 0xE7; // Display (phone status) constexpr uint8_t M_RLS = 0xE8; // Rain/Light Sensor // --- GM5 diagnostic I/O --- constexpr uint8_t GM5_SET_IO = 0x0C; constexpr uint8_t GM5_BTN_DOME_LIGHT = 0x01; constexpr uint8_t GM5_BTN_CENTER_LOCK = 0x03; constexpr uint8_t GM5_BTN_TRUNK_OPEN = 0x05; constexpr uint8_t GM5_BTN_WINDOW_DRIVER_DOWN = 0x0A; constexpr uint8_t GM5_BTN_WINDOW_DRIVER_UP = 0x0B; constexpr uint8_t GM5_BTN_WINDOW_PASS_DOWN = 0x0C; constexpr uint8_t GM5_BTN_WINDOW_PASS_UP = 0x0D; constexpr uint8_t GM5_LED_ALARM_WARNING = 0x4E; constexpr uint8_t GM5_INPUT_STATE_DIGITAL = 0x00; constexpr uint8_t GM5_INPUT_STATE_ANALOG = 0x01; // =================================================================== // Lighting commands (DIA -> LCM or DIA -> ALL broadcast) // =================================================================== const uint8_t TurnOffLights[] = { 0x3F, 0x0F, 0xD0, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xE4, 0xFF, 0x00 }; const uint8_t ParkLights_And_Signals[] = { 0x3F, 0x0B, 0xBF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x7A, 0x48, 0x0A, 0x06 }; const uint8_t ParkLights_And_Signals_And_FogLights[] = { 0x3F, 0x0B, 0xBF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x7A, 0x48, 0x0B, 0x06 }; const uint8_t Low_Beams[] = { 0x3F, 0x0B, 0xBF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x02, 0x4E, 0x0A, 0x06 }; const uint8_t FollowMeHome[] = { 0x3F, 0x0B, 0xBF, 0x0C, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x06 }; const uint8_t GoodbyeLights[] = { 0x3F, 0x0B, 0xBF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x62, 0x08, 0xA0, 0x06 }; // --- Individual light control (DIA -> ALL, 12 bytes + checksum) --- const uint8_t Fog[] = { 0x3F, 0x0B, 0xBF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x06 }; const uint8_t LeftTail[] = { 0x3F, 0x0B, 0xBF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x06 }; const uint8_t RearLight[] = { 0x3F, 0x0B, 0xBF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x06 }; const uint8_t Brake_Above[] = { 0x3F, 0x0B, 0xBF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x06 }; const uint8_t Brake_Left[] = { 0x3F, 0x0B, 0xBF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x06 }; const uint8_t Brake_Right[] = { 0x3F, 0x0B, 0xBF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x06 }; const uint8_t FrontRightLowBeam[] = { 0x3F, 0x0B, 0xBF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x06 }; const uint8_t FrontLeftLowBeam[] = { 0x3F, 0x0B, 0xBF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x06 }; const uint8_t LowBeamDelayed[] = { 0x3F, 0x0B, 0xBF, 0x0C, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06 }; const uint8_t MainBeamLeft[] = { 0x3F, 0x0B, 0xBF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x06 }; const uint8_t HighBeamRightLow[] = { 0x3F, 0x0B, 0xBF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x06 }; const uint8_t IgnitionLowBeam[] = { 0x3F, 0x0B, 0xBF, 0x0C, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x06 }; const uint8_t LeftRearContin[] = { 0x3F, 0x0B, 0xBF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x06 }; const uint8_t RightRearContin[] = { 0x3F, 0x0B, 0xBF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x06 }; const uint8_t LeftFrontTurnContin[] = { 0x3F, 0x0B, 0xBF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x06 }; const uint8_t RightFrontTurnContin[] = { 0x3F, 0x0B, 0xBF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x06 }; const uint8_t LeftParking[] = { 0x3F, 0x0B, 0xBF, 0x0C, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x06 }; const uint8_t RightParking[] = { 0x3F, 0x0B, 0xBF, 0x0C, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x06 }; const uint8_t HazardLights[] = { 0x3F, 0x0B, 0xBF, 0x0C, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06 }; // =================================================================== // Window control (DIA -> GM5) // =================================================================== const uint8_t Window_FrontDriver_Open[] = { 0x3F, 0x05, 0x00, 0x0C, 0x52, 0x01 }; const uint8_t Window_FrontDriver_Close[] = { 0x3F, 0x05, 0x00, 0x0C, 0x53, 0x01 }; const uint8_t Window_FrontPassenger_Open[] = { 0x3F, 0x05, 0x00, 0x0C, 0x54, 0x01 }; const uint8_t Window_FrontPassenger_Close[] = { 0x3F, 0x05, 0x00, 0x0C, 0x55, 0x01 }; const uint8_t Window_RearDriver_Open[] = { 0x3F, 0x05, 0x00, 0x0C, 0x41, 0x01 }; const uint8_t Window_RearDriver_Close[] = { 0x3F, 0x05, 0x00, 0x0C, 0x42, 0x01 }; const uint8_t Window_RearPassenger_Open[] = { 0x3F, 0x05, 0x00, 0x0C, 0x44, 0x01 }; const uint8_t Window_RearPassenger_Close[] = { 0x3F, 0x05, 0x00, 0x0C, 0x43, 0x01 }; // =================================================================== // Interior lighting (DIA -> GM5) // =================================================================== const uint8_t Interior_Off[] = { 0x3F, 0x05, 0x00, 0x0C, 0x01, 0x01 }; const uint8_t Interior_Dim2[] = { 0x3F, 0x05, 0x00, 0x0C, 0x30, 0x01 }; const uint8_t Interior_On3s[] = { 0x3F, 0x05, 0x00, 0x0C, 0x60, 0x01 }; const uint8_t Interior_OffDim[] = { 0x3F, 0x05, 0x00, 0x0C, 0x68, 0x01 }; // =================================================================== // Door locks (DIA -> GM5) // =================================================================== const uint8_t Doors_Unlock_Interior[] = { 0x3F, 0x05, 0x00, 0x0C, 0x03, 0x01 }; const uint8_t Doors_Lock_Key[] = { 0x3F, 0x05, 0x00, 0x0C, 0x34, 0x01 }; const uint8_t Doors_Fuel_Trunk[] = { 0x3F, 0x05, 0x00, 0x0C, 0x46, 0x01 }; const uint8_t DriverDoor_Lock[] = { 0x3F, 0x05, 0x00, 0x0C, 0x47, 0x01 }; const uint8_t AllExceptDriver_Lock[] = { 0x3F, 0x05, 0x00, 0x0C, 0x4F, 0x01 }; const uint8_t Doors_HardLock[] = { 0x3F, 0x05, 0x00, 0x0C, 0x97, 0x01 }; // =================================================================== // Trunk (DIA -> GM5) // =================================================================== const uint8_t Trunk_Open[] = { 0x3F, 0x05, 0x00, 0x0C, 0x02, 0x01 }; const uint8_t Trunk_Open2[] = { 0x3F, 0x05, 0x00, 0x0C, 0x05, 0x01 }; const uint8_t Trunk_Open3[] = { 0x3F, 0x05, 0x00, 0x0C, 0x95, 0x01 }; // =================================================================== // Wipers and washers (DIA -> GM5) // =================================================================== const uint8_t Wipers_Front[] = { 0x3F, 0x05, 0x00, 0x0C, 0x49, 0x01 }; const uint8_t Washer_Front[] = { 0x3F, 0x05, 0x00, 0x0C, 0x62, 0x01 }; // =================================================================== // Hazard / special (DIA -> GM5) // =================================================================== const uint8_t Hazard_IKE_LCM[] = { 0x3F, 0x05, 0x00, 0x0C, 0x70, 0x01 }; const uint8_t Hazard_LCM_3s[] = { 0x3F, 0x05, 0x00, 0x0C, 0x75, 0x01 }; const uint8_t CLOWN_FLASH[] = { 0x3F, 0x05, 0x00, 0x0C, 0x4E, 0x01 }; // =================================================================== // Instrument cluster / speed (DIA -> IKE) // =================================================================== const uint8_t AvgSpeedDelete[] = { 0x3B, 0x05, 0x80, 0x41, 0x10, 0x0A }; const uint8_t RequestMileage[] = { 0xBF, 0x03, 0x80, 0x16 }; // Speed limit: last byte is speed value in km/h const uint8_t SpeedLimitBeep[] = { 0x3B, 0x06, 0x80, 0x40, 0x09, 0x00, 0x00 }; const uint8_t SpeedLimitCurrent[] = { 0x3B, 0x05, 0x80, 0x41, 0x09, 0x20 }; const uint8_t SpeedLimitDisable[] = { 0x3B, 0x05, 0x80, 0x41, 0x09, 0x08 }; // =================================================================== // Remote control events (GM5 -> ALL broadcast) // =================================================================== const uint8_t Remote_CloseButton[] = { 0x00, 0x04, 0xBF, 0x72, 0x16 }; const uint8_t Remote_OpenButton[] = { 0x00, 0x04, 0xBF, 0x72, 0x26 }; const uint8_t Remote_ReleaseButton[] = { 0x00, 0x04, 0xBF, 0x72, 0x06 }; // =================================================================== // Ignition and key state events // =================================================================== const uint8_t KEY_IN[] = { 0x44, 0x05, 0xBF, 0x74, 0x04, 0x00 }; const uint8_t KEY_OUT[] = { 0x44, 0x05, 0xBF, 0x74, 0x00, 0xFF }; const uint8_t IGNITION_OFF[] = { 0x80, 0x04, 0xBF, 0x11, 0x00 }; const uint8_t IGNITION_POS1[] = { 0x80, 0x04, 0xBF, 0x11, 0x01 }; const uint8_t IGNITION_POS2[] = { 0x80, 0x04, 0xBF, 0x11, 0x03 }; const uint8_t REMOTE_UNLOCK[] = { 0x00, 0x04, 0xBF, 0x72, 0x22 }; const uint8_t REMOTE_LOCK[] = { 0x00, 0x04, 0xBF, 0x72, 0x12 }; // =================================================================== // Steering wheel controls (MFL -> RAD/TEL) // =================================================================== const uint8_t MFL_VOL_UP[] = { 0x50, 0x04, 0x68, 0x32, 0x11 }; const uint8_t MFL_VOL_DOWN[] = { 0x50, 0x04, 0x68, 0x32, 0x10 }; const uint8_t MFL_TEL_VOL_UP[] = { 0x50, 0x04, 0xC8, 0x32, 0x11 }; const uint8_t MFL_TEL_VOL_DOWN[] = { 0x50, 0x04, 0xC8, 0x32, 0x10 }; const uint8_t MFL_SES_PRESS[] = { 0x50, 0x04, 0xB0, 0x3B, 0x80 }; const uint8_t MFL_SEND_END_PRESS[] = { 0x50, 0x04, 0xC8, 0x3B, 0x80 }; const uint8_t MFL_RT_PRESS[] = { 0x50, 0x04, 0x68, 0x3B, 0x02 }; // =================================================================== // CD changer control (RAD -> CDC) // =================================================================== const uint8_t CD_STOP[] = { 0x68, 0x05, 0x18, 0x38, 0x01, 0x00 }; const uint8_t CD_PLAY[] = { 0x68, 0x05, 0x18, 0x38, 0x03, 0x00 }; const uint8_t CD_PAUSE[] = { 0x68, 0x05, 0x18, 0x38, 0x02, 0x00 }; const uint8_t CD_STOP_STATUS[] = { 0x18, 0x0A, 0x68, 0x39, 0x00, 0x02, 0x00, 0x3F, 0x00, 0x07, 0x01 }; const uint8_t CD_PLAY_STATUS[] = { 0x18, 0x0A, 0x68, 0x39, 0x02, 0x09, 0x00, 0x3F, 0x00, 0x07, 0x01 }; const uint8_t BACK_ONE[] = { 0x68, 0x05, 0x18, 0x38, 0x08, 0x00 }; const uint8_t BACK_TWO[] = { 0x68, 0x05, 0x18, 0x38, 0x08, 0x01 }; const uint8_t LEFT[] = { 0x68, 0x05, 0x18, 0x38, 0x0A, 0x01 }; const uint8_t RIGHT[] = { 0x68, 0x05, 0x18, 0x38, 0x0A, 0x00 }; const uint8_t SELECT[] = { 0x68, 0x05, 0x18, 0x38, 0x07, 0x01 }; const uint8_t BUTTON_ONE[] = { 0x68, 0x05, 0x18, 0x38, 0x06, 0x01 }; const uint8_t BUTTON_TWO[] = { 0x68, 0x05, 0x18, 0x38, 0x06, 0x02 }; const uint8_t BUTTON_THREE[] = { 0x68, 0x05, 0x18, 0x38, 0x06, 0x03 }; const uint8_t BUTTON_FOUR[] = { 0x68, 0x05, 0x18, 0x38, 0x06, 0x04 }; const uint8_t BUTTON_FIVE[] = { 0x68, 0x05, 0x18, 0x38, 0x06, 0x05 }; const uint8_t BUTTON_SIX[] = { 0x68, 0x05, 0x18, 0x38, 0x06, 0x06 }; // =================================================================== // CDC status (CDC -> RAD or CDC -> ALL) // =================================================================== const uint8_t CDC_STATUS_REPLY_RST[] = { 0x18, 0x04, 0xFF, 0x02, 0x01 }; const uint8_t CDC_STATUS_REQUEST[] = { 0x68, 0x03, 0x18, 0x01 }; const uint8_t CDC_STATUS_REPLY[] = { 0x18, 0x04, 0xFF, 0x02, 0x00 }; const uint8_t CD_STATUS[] = { 0x18, 0x0E, 0x68, 0x39, 0x00, 0x82, 0x00, 0x3F, 0x00, 0x07, 0x00, 0x00, 0x01, 0x01, 0x01 }; const uint8_t BUTTON_PRESSED[] = { 0x68, 0x04, 0xFF, 0x3B, 0x00 }; // =================================================================== // DSP control (RAD -> DSP) // =================================================================== const uint8_t DSP_STATUS_REQUEST[] = { 0x68, 0x03, 0x6A, 0x01 }; const uint8_t DSP_STATUS_REPLY[] = { 0x6A, 0x04, 0xFF, 0x02, 0x00 }; const uint8_t DSP_STATUS_REPLY_RST[] = { 0x6A, 0x04, 0xFF, 0x02, 0x01 }; const uint8_t DSP_VOL_UP_1[] = { 0x68, 0x04, 0x6A, 0x32, 0x11 }; const uint8_t DSP_VOL_UP_2[] = { 0x68, 0x04, 0x6A, 0x32, 0x21 }; const uint8_t DSP_VOL_UP_3[] = { 0x68, 0x04, 0x6A, 0x32, 0x31 }; const uint8_t DSP_VOL_DOWN_1[] = { 0x68, 0x04, 0x6A, 0x32, 0x10 }; const uint8_t DSP_VOL_DOWN_2[] = { 0x68, 0x04, 0x6A, 0x32, 0x20 }; const uint8_t DSP_VOL_DOWN_3[] = { 0x68, 0x04, 0x6A, 0x32, 0x30 }; const uint8_t DSP_FUNC_0[] = { 0x68, 0x04, 0x6A, 0x36, 0x30 }; const uint8_t DSP_FUNC_1[] = { 0x68, 0x04, 0x6A, 0x36, 0xE1 }; const uint8_t DSP_SRCE_OFF[] = { 0x68, 0x04, 0x6A, 0x36, 0xAF }; const uint8_t DSP_SRCE_CD[] = { 0x68, 0x04, 0x6A, 0x36, 0xA0 }; const uint8_t DSP_SRCE_TUNER[] = { 0x68, 0x04, 0x6A, 0x36, 0xA1 }; // =================================================================== // Telephone (TEL -> ANZV display) // =================================================================== const uint8_t INCOMING_CALL[] = { 0xC8, 0x04, 0xE7, 0x2C, 0x05 }; const uint8_t PHONE_ON[] = { 0xC8, 0x04, 0xE7, 0x2C, 0x10 }; const uint8_t HANDSFREE_PHONE_ON[] = { 0xC8, 0x04, 0xE7, 0x2C, 0x11 }; const uint8_t ACTIVE_CALL[] = { 0xC8, 0x04, 0xE7, 0x2C, 0x33 }; // =================================================================== // Radio navigation (RAD -> misc) // =================================================================== const uint8_t GO_TO_RADIO[] = { 0x68, 0x04, 0xFF, 0x3B, 0x00 }; const uint8_t REQUEST_TIME[] = { 0x68, 0x05, 0x80, 0x41, 0x01, 0x01 }; // =================================================================== // Volume increment table (DSP volume steps, 0-63) // =================================================================== const uint8_t VOL_INCREMENT[] = { 0, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180, 182, 184, 186, 188, 190, 192 }; } // namespace ibus