홈으로 돌아가기

BCD4 큐 디스플레이 프로토콜 역공학

이 기사는 BCD4 인코딩과 체크섬의 캐리를 사용하는 독점 전자 대기열 디스플레이 프로토콜의 역공학을 설명합니다. 패킷 구조, Python 패킷 조립 코드, HTTP와 COM 포트를 통한 웹 시스템 통합이 제공됩니다. 레거시 장비 작업에 유용합니다.

대기열 디스플레이의 BCD4와 캐리 역공학
Advertisement 728x90

큐 디스플레이 프로토콜 리버스 엔지니어링: BCD4 인코딩과 캐리 연산

한 엔지니어가 문서 없이 독점 큐 디스플레이 프로토콜을 리버스 엔지니어링했습니다. 이 프로토콜은 BCD4 인코딩을 사용하며, 각 데이터 비트는 1200 보드의 긴 RS-232 라인에서 노이즈 내성을 위해 전체 바이트를 차지합니다. 패킷 구조는 33바이트로, 마커, 숫자 자릿수, 창 번호, 캐리가 포함된 체크섬 필드로 구성됩니다.

BCD4: 신뢰할 수 있는 전송을 위한 인코딩

프로토콜은 노이즈 방지를 위한 하드웨어 방식을 사용합니다: 숫자(0–15)의 각 비트는 바이트로 인코딩됩니다. 0x7F는 1을 나타내고(명확한 펄스를 위해 7개의 1), 0x00은 0을 나타냅니다. 이는 4비트 값을 4바이트로 확장합니다.

인코딩 예시:

Google AdInline article slot

| 숫자 | 비트 | BCD4 바이트 |

|--------|--------|------------------|

| 0 | 0000 | 00 00 00 00 |

Google AdInline article slot

| 1 | 0001 | 7F 00 00 00 |

| 2 | 0010 | 00 7F 00 00 |

| 5 | 0101 | 7F 00 7F 00 |

Google AdInline article slot

| 9 | 1001 | 7F 00 00 7F |

| 12 | 1100 | 00 00 7F 7F |

Python 구현:

def _bcd4(value: int) -> bytes:
    return bytes([0x7F if value & (1 << i) else 0x00 for i in range(4)])

print(_bcd4(5).hex(' '))  # 7f 00 7f 00
print(_bcd4(9).hex(' '))  # 7f 00 00 7f

1200 보드 속도는 처리량을 희생하면서 신뢰성을 보장합니다.

숫자 디스플레이를 위한 패킷 구조

33바이트 패킷은 창에 숫자를 표시합니다:

  • 바이트 0: 0x55 — 시작 마커.
  • 바이트 1–4: 모드 헤더.
  • 바이트 5–8: BCD4(일의 자리).
  • 바이트 9–12: BCD4(십의 자리).
  • 바이트 13–16: BCD4(백의 자리).
  • 바이트 17–20: BCD4(창 일의 자리).
  • 바이트 21–24: BCD4(창 십의 자리).
  • 바이트 25–28: BCD4(c1) — 하위 체크섬 부분.
  • 바이트 29–32: BCD4(c2) — 캐리가 포함된 상위 부분.

숫자 487을 창 19에 표시하는 예시:

55 00 7F 00 00          # 헤더
7F 7F 7F 00             # BCD4(7)
00 00 00 7F             # BCD4(8)
00 00 7F 00             # BCD4(4)
7F 00 00 7F             # BCD4(9)
7F 00 00 00             # BCD4(1)
[체크섬 필드]

캐리를 사용한 체크섬 계산

체크섬 필드 c1과 c2는 캐리 메커니즘을 가진 8비트 값을 형성합니다:

  • 패킷 필드의 선형 조합으로 raw_c1을 계산합니다.
  • raw_c1 >= 16이면: carry = 1, c1 = raw_c1 - 16.
  • 그렇지 않으면: carry = 0, c1 = raw_c1.
  • c2는 다른 필드의 캐리로 계산됩니다.

캐리는 창에 따라 80–90과 같은 숫자에서 발생합니다. AI(Claude)는 가설을 정제한 후 30개 패킷 예시에서 패턴을 식별했습니다: 산술에서처럼 캐리가 있는 두 개의 4비트 니블.

"모든 창" 모드(25바이트)에서는 캐리가 없고 공식이 더 간단합니다.

창 프로그래밍 모드는 곱셈과 상수를 사용한 두 개의 독립적인 캐리 체인을 사용합니다:

  • 체인 A: W_lo에서 raw_A, carry_A = raw_A >> 4, field_A1 = raw_A & 0xF, field_A2는 W_hi와 carry_A에서.
  • 체인 B: 다른 선형 함수에 대해 유사하게.

패킷 조립 및 전송

패킷 조립 함수:

def build_window_packet(window: int, number: int) -> bytes:
    d1 = number % 10
    d2 = (number // 10) % 10
    d3 = (number // 100) % 10
    w_lo = window % 10
    w_hi = window // 10

    c1, c2 = _checksum(d1, d2, d3, w_lo, w_hi)

    packet = bytearray(b'\x55\x00\x7F\x00\x00')
    packet += _bcd4(d1) + _bcd4(d2) + _bcd4(d3)
    packet += _bcd4(w_lo) + _bcd4(w_hi)
    packet += _bcd4(c1) + _bcd4(c2)

    assert len(packet) == 33
    return bytes(packet)

패킷은 COM 포트로 전송됩니다.

웹 시스템 통합

Python 서버는 HTTP POST를 수락합니다:

POST / {"window": 5, "ticket": "487"}

JSON을 파싱하고, 패킷을 조립하며, 포트에 씁니다. 하트비트 메커니즘이 연결을 복원합니다:

  • 정상일 때 60초 간격.
  • 오류 시 10초.
def _heartbeat_loop():
    while True:
        ok = _try_register(...)
        was = _server_state['connected']
        _server_state['connected'] = ok
        if not was and ok:
            print("[OK] 연결 복원됨")
        elif was and not ok:
            print("[WARN] 연결 끊김")
        time.sleep(60 if ok else 10)

핵심 요약

  • BCD4 인코딩은 1200 보드에서 노이즈 내성을 위해 1비트를 바이트로 확장합니다.
  • 체크섬은 니블 c1/c2 사이의 캐리를 사용합니다.
  • AI를 통한 리버스 엔지니어링은 정확한 가설과 패킷 예시로 효과적입니다.
  • 서버는 레거시 장비를 웹과 원활하게 통합할 수 있게 합니다.
  • 프로토콜: 33바이트, 마커 0x55, 자릿수 + 창 + 체크섬.

— Editorial Team

Advertisement 728x90

다음 읽기