Skip to content

fix: Command_TurnIndicator default-mode encoding is swapped vs the project's DBC#66

Open
94xhn wants to merge 1 commit into
ToyotaInfoTech:mainfrom
94xhn:fix/turnindicator-default-endianness
Open

fix: Command_TurnIndicator default-mode encoding is swapped vs the project's DBC#66
94xhn wants to merge 1 commit into
ToyotaInfoTech:mainfrom
94xhn:fix/turnindicator-default-endianness

Conversation

@94xhn

@94xhn 94xhn commented Jul 18, 2026

Copy link
Copy Markdown

Command_TurnIndicator's non-J1939 (default) encode/decode goes through the shared PACK_SIGNAL/UNPACK_SIGNAL macros, and under USE_BIG_ENDIAN_CAN (unconditionally on in ramn_config.h) those macros byte-swap any signal masked with 0xFFFF. That's the right thing to do for a genuine 16-bit value like brake/accel/steering, but COMMAND_TURNINDICATOR_MASK is also 0xFFFF even though the value isn't really one 16-bit number -- it's two independent 1-bit flags, high byte for Left and low byte for Right (that's the convention RAMN_Encode_Command_TurnIndicator_J1939 already uses and comments on).

I checked this against misc/busmaster_ramn.dbc with cantools: CAN ID 0x1A7 (TurnIndicators) has Right at byte 0 bit 0 and Left at byte 1 bit 0. Because of the swap, encoding "Left only" in default mode actually puts the bit in byte 0 and clears byte 1, so anything decoding the frame against the project's own DBC reads it as Right active / Left inactive -- backwards. Since RAMN's own encode and decode use the same swapped convention, this is invisible from RAMN's own software (it round-trips fine internally) and only shows up once you decode real traffic against the published DBC, which is exactly what this testbed is for.

This is the same bug class as the Command_Lights fix from a few weeks ago (RAMN_Encode_Command_Lights_Default / #55) -- I used the same fix: write the two bytes directly instead of going through the macro, so nothing gets swapped.

I built ramn_can_database.c with -DUSE_BIG_ENDIAN_CAN (matching the real firmware config) into a small shared lib and drove it with ctypes: before the fix, encoding "Left only" produced wire bytes that cantools decodes against the DBC as Right=1/Left=0; after the fix it decodes as Left=1/Right=0 as intended, same for the Right-only case. Encode/decode roundtrip still holds across the full uint16 range. Added scripts/tests/test_turnindicator_encoding.py, same shape as the existing lighting-switch test, checking the byte placement and the roundtrip.

The non-J1939 encode/decode for Command_TurnIndicator went through the
shared PACK_SIGNAL/UNPACK_SIGNAL macros, which byte-swap any 0xFFFF-masked
signal under USE_BIG_ENDIAN_CAN (unconditionally defined in ramn_config.h).
That swap is correct for a genuine 16-bit value, but TurnIndicator is really
two independent 1-bit flags (high byte = Left, low byte = Right, per
RAMN_Encode_Command_TurnIndicator_J1939's own convention), so the swap
lands them in the wrong bytes.

Checked against the project's own misc/busmaster_ramn.dbc (CAN ID 0x1A7),
Right belongs in byte 0 and Left in byte 1. With the swap, encoding
'Left only' actually puts the bit in byte 0, which a DBC-based decoder
reads back as Right active / Left inactive -- exactly backwards. This is
the same class of bug already fixed for Command_Lights (see
RAMN_Encode_Command_Lights_Default), so I applied the same fix here:
write the two bytes directly instead of going through PACK_SIGNAL.

Added scripts/tests/test_turnindicator_encoding.py (same style as the
existing lighting-switch test) that builds the codec with
USE_BIG_ENDIAN_CAN and checks the byte placement plus roundtrip.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant