T90 프로토콜
장비 ↔ SW 사이의 TCP 바이너리 와이어 포맷. 모든 구조체는 Little-Endian, packed (1-byte alignment).
0. 트랜스포트
프로토콜
TCP
엔디안
Little-Endian
정렬
__attribute__((packed))
프레임 경계
헤더 packet_size (8바이트 헤더 포함 총 바이트)
기본 포트
31024 (PDF 미명시 — 현장 관행)
1. 패킷 타입 상수
#define PACKET_TYPE_SCOPE_SET 0x77770010 SW→장비 SCOPE 설정
#define PACKET_TYPE_PQN_SET 0x77770020 SW→장비 PQN 설정
#define PACKET_TYPE_HW_SET 0x77770030 SW→장비 HW 설정
#define PACKET_TYPE_MSG 0x77770100 양방향 명령/상태/에러
#define PACKET_TYPE_SCOPE_DATA 0x77771000 장비→SW SCOPE 측정 데이터
#define PACKET_TYPE_PQN_DATA 0x77772000 장비→SW PQN 측정 데이터
2. MSG 코드
#define MSG_SCOPE_SET_ERROR 0x00000010 // SCOPE_SET 응답 (에러 없어도 돌아옴)
#define MSG_PQN_SET_ERROR 0x00000020 // PQN_SET 응답
#define MSG_HW_SET_ERROR 0x00000030 // HW_SET 응답
#define MSG_SEND_DATA_START 0x00000100 // 수집 시작
#define MSG_SEND_DATA_STOP 0x00000200 // 수집 중지
#define MSG_ALIVE 0x00000400 // Keep-alive (Rev 4 추가)
#define MSG_NET_CFG_SET 0x00001000 // 장비 MAC/IP 설정
#define MSG_NET_CFG_INFO 0x00002000 // 장비 MAC/IP 조회
#define MSG_SELF_SYNC_ENABLE 0x00003000 // 자체 싱크 On/Off
#define MSG_REBOOT 0x10000000 // 장비 재부팅
모든 명령 MSG 는 장비가 동일 msg 값으로 ACK한다.
SET 패킷은 대응하는 MSG_*_SET_ERROR 로 ACK 되며
에러가 없어도 돌아온다(error=0).
3. 공통 헤더
typedef struct {
unsigned int packet_type; // §1 상수 중 하나
unsigned int packet_size; // 헤더 포함 총 바이트
} __attribute__((packed)) PACKET_HEADER; // 8 byte
4. SCOPE_SET_PACKET (392 byte)
typedef struct {
unsigned int ch_group; // 0~7 기본 0
unsigned int ch_on; // 0/1 기본 1
unsigned int trig_on; // 0/1 기본 0
unsigned int trig_type; // 1~3 기본 3 bit0=H매칭, bit1=L매칭
int trig_h_lv; // -2048~2047 기본 2047
int trig_l_lv; // -2048~2047 기본 -2048
unsigned int trig_depth; // 0~2047 기본 500
unsigned int trig_pos; // 0~depth 기본 250
unsigned int filter_on; // 0/1 기본 0
unsigned int filter_type; // 0/1/2/3 기본 2 LPF/HPF/BPF/BSF
float freq; // 1.0~49.0 기본 25.0
float bandwidth; // 1.0~10.0 기본 1.0
} __attribute__((packed)) SCOPE_CH_PARAM; // 48 byte
typedef struct {
PACKET_HEADER header;
SCOPE_CH_PARAM ch_param[8];
} __attribute__((packed)) SCOPE_SET_PACKET; // 8 + 48*8 = 392 byte
5. PQN_SET_PACKET (360 byte)
typedef struct {
unsigned int ch_on;
unsigned int offset; // 0~2047 기본 0
unsigned int gating_on; // 0/1 기본 0
unsigned int gating_src; // 0~7 0~3ch=3, 4~7ch=7
unsigned int gating_thd; // 0~2047 기본 2047
unsigned int gating_prd; // 0~65535 기본 10000 단위 10ns
unsigned int pre_gating_len_sel; // 0~10 기본 10 단위 1µs
unsigned int filter_on;
unsigned int filter_type;
float freq;
float bandwidth;
} __attribute__((packed)) PQN_CH_PARAM; // 44 byte
typedef struct {
PACKET_HEADER header;
PQN_CH_PARAM ch_param[8];
} __attribute__((packed)) PQN_SET_PACKET; // 8 + 44*8 = 360 byte
6. HW_SET_PACKET (88 byte)
typedef struct {
PACKET_HEADER header;
unsigned int sync_sel; // 0=int, 1=ext 기본 0
unsigned int sync_gain; // 1~7 기본 2
float sync_freq; // 20.00~300.00 Hz 기본 60.00
unsigned int num_of_cycle; // 5~60 (1주기=256샘플) 기본 5
unsigned int adc_data_invert[8]; // 0/1 기본 0
unsigned int ch_gain[8]; // 1~60 기본 27
} __attribute__((packed)) HW_SET_PACKET; // 88 byte
7. MSG_PACKET (272 byte) — 양방향
typedef struct {
PACKET_HEADER header;
unsigned int msg; // §2 의 MSG_* 중 하나
unsigned int error; // 응답시 에러 코드, 송신시 0
char padding[256];
} __attribute__((packed)) MSG_PACKET; // 272 byte
padding 의 사용
| MSG | padding 사용 |
|---|---|
MSG_NET_CFG_SET / MSG_NET_CFG_INFO |
[0..5] = MAC, [6..9] = IP, 나머지 0 |
MSG_SELF_SYNC_ENABLE |
[0..3] = 'T','-','9','0' (84,45,57,48), [4] = 0/1, 나머지 0 |
| 그 외 | 모두 0 |
8. SCOPE_DATA_PACKET (가변 길이)
typedef struct {
PACKET_HEADER header; // packet_size = 24 + trig_depth*2
unsigned int ch_number; // 0~7
int phase; // 위상, 60Hz면 max 1_666_666 (16.67ms / 10ns), 못잡으면 -1
int cycle_index; // PQN과 매칭용
float sync_freq; // 못잡으면 -1
// 뒤에 int16 샘플 trig_depth개
} __attribute__((packed)) SCOPE_DATA_PACKET;
각도 변환
각도 = phase × (sync_freq × 360) / 156_250_000
(60Hz일 때) = phase / 1_666_666 × 360
9. PQN_DATA_PACKET (가변 길이)
typedef struct {
PACKET_HEADER header; // packet_size = 20 + buffer_size*2
unsigned int ch_number; // 0~7 입력, 8 = sync
int cycle_index;
float sync_freq;
// 뒤에 uint16 bin 데이터 buffer_size개
} __attribute__((packed)) PQN_DATA_PACKET;
중요: 8번 채널(sync)의 PQN 패킷은 PQN_CH_PARAM 에서
모든 채널의 ch_on=0 으로 설정해도 항상 SW로 전송된다.
10. ERROR 코드
#define ERROR_NO_ERR 0
// SCOPE_SET (10000~10120)
#define ERROR_SCOPE_SET_PACKET_LEN_WRONG 10000
#define ERROR_SCOPE_SET_CH_GROUP_VALUE_INVALID 10010
#define ERROR_SCOPE_SET_CH_ON_VALUE_INVALID 10020
#define ERROR_SCOPE_SET_TRIG_ON_VALUE_INVALID 10030
#define ERROR_SCOPE_SET_TRIG_TYPE_VALUE_INVALID 10040
#define ERROR_SCOPE_SET_TRIG_HIGH_LEVEL_VALUE_INVALID 10050
#define ERROR_SCOPE_SET_TRIG_LOW_LEVEL_VALUE_INVALID 10060
#define ERROR_SCOPE_SET_TRIG_DEPTH_VALUE_INVALID 10070
#define ERROR_SCOPE_SET_TRIG_POS_VALUE_INVALID 10080
#define ERROR_SCOPE_SET_FILTER_ON_VALUE_INVALID 10090
#define ERROR_SCOPE_SET_FILTER_TYPE_VALUE_INVALID 10100
#define ERROR_SCOPE_SET_FREQ_VALUE_INVALID 10110
#define ERROR_SCOPE_SET_BANDWIDTH_VALUE_INVALID 10120
// PQN_SET (20000~20110)
#define ERROR_PQN_SET_PACKET_LEN_WRONG 20000
#define ERROR_PQN_SET_CH_ON_VALUE_INVALID 20010
#define ERROR_PQN_SET_OFFSET_VALUE_INVALID 20020
// ... (가이드 PDF §6 전체 표 참조)
// HW_SET (30000~30060)
#define ERROR_HW_SET_PACKET_LEN_WRONG 30000
#define ERROR_HW_SET_SYNC_SEL_VALUE_INVALID 30010
// ...
// NET_CFG (90010~90020)
#define ERROR_NET_CFG_IP_VALUE_INVALID 90010
#define ERROR_NET_CFG_IP_CHANGE_FAILED 90020
// SELF_SYNC (100100~100120)
#define ERROR_SELF_SYNC_ENABLE_DENIED 100100
#define ERROR_SELF_SYNC_ENABLE_VALUE_INVALID 100110
#define ERROR_SELF_SYNC_ENABLE_RETURN_INVALID 100120
10.1 채널 번호 오프셋 규칙
CH_* ~ BANDWIDTH_* 범위 에러는
에러값 + 채널번호(0~7) 로 반환.
예) 3번 채널의 ch_on 값이 잘못 → ERROR_SCOPE_SET_CH_ON_VALUE_INVALID + 3 = 10023
디코드 의사코드:
base = err - (err % 10) // 10023 → 10020
ch_offset = err - base // 10023 → 3
10.2 IP 옥텟 오프셋 규칙
| 잘못된 옥텟 (a.b.c.d) | error |
|---|---|
| a | 90010 |
| b | 90011 |
| c | 90012 |
| d | 90013 |
유효성: a/b/c/d 모두 255 불가, a와 d는 0/1 불가. 허용 예 2.0.0.2.
리비전 이력
| Rev | 변경 |
|---|---|
| 0 | 초안 |
| 1 | HW_SET_PACKET 변경 / ERROR 코드 변경 |
| 2 | sync 주파수 범위 변경 / 제한값 삭제 / buffer_size → num_of_cycle / IP 변경 실패 에러값 추가 |
| 3 | sync 주파수 범위 변경 / MSG_SELF_SYNC_ENABLE 추가 |
| 3.1 | 오타 수정 |
| 4 | MSG_ALIVE 패킷 추가 |
| 5 | 오타 수정 |
원본: docs/T90패킷가이드_Rev5.pdf.
참조: Old/.../libs/network/a1protocol.h.
흐름은 → 패킷 흐름.