diff --git a/prj/TCPClient/Middle/QDXnetworkStack/qdx_tcp_logic.c b/prj/TCPClient/Middle/QDXnetworkStack/qdx_tcp_logic.c index cd5f34f..3f14c96 100644 --- a/prj/TCPClient/Middle/QDXnetworkStack/qdx_tcp_logic.c +++ b/prj/TCPClient/Middle/QDXnetworkStack/qdx_tcp_logic.c @@ -69,7 +69,7 @@ static void tcp_stream_init(TcpStreamCtx_t *ctx, const char *label) { } static void tcp_stream_disconnect(TcpStreamCtx_t *ctx) { - DBG_LOGIC("[%s] disconnecting\r\n", ctx->label); + DBG_LOGIC("!! [%s] Disconnected\r\n", ctx->label); ctx->is_connected = 0; if (ctx->sock) { qdx_port_tcp_close(ctx->sock); @@ -90,7 +90,7 @@ static int8_t tcp_stream_connect(TcpStreamCtx_t *ctx, const char *ip, ctx->last_activity_ms = qdx_port_get_tick_ms(); ctx->last_heartbeat_ms = ctx->last_activity_ms; ctx->recv_len = 0; - DBG_LOGIC("[%s] connected OK\r\n", ctx->label); + DBG_LOGIC(">> [%s] Connected to %s:%d\r\n", ctx->label, ip, port); return 0; } @@ -121,7 +121,7 @@ static int32_t tcp_send_frame(TcpStreamCtx_t *ctx, uint8_t msg_class, } static void tcp_send_handshake(TcpStreamCtx_t *ctx) { - DBG_LOGIC("[%s] sending handshake\r\n", ctx->label); + DBG_LOGIC(">> [%s] Handshake (DevID=%d)\r\n", ctx->label, (int)g_TcpLogic.dev_id); uint8_t payload[54]; memset(payload, 0, sizeof(payload)); qdx_write_u16_le(payload + 0, 0x0200); @@ -271,6 +271,8 @@ static void parse_and_dispatch_tlv(TcpStreamCtx_t *ctx, const uint8_t *packet, case TYPE_DEVID_ASSIGN: { if (len >= sizeof(DevIDAssignment_t)) { uint16_t new_id = qdx_read_u16_le(value); + DBG_LOGIC("<< [%s] DevID assigned: %d -> %d\r\n", + ctx->label, (int)g_TcpLogic.dev_id, (int)new_id); g_TcpLogic.pending_new_dev_id = new_id; tcp_send_ack(ctx, hdr_seq, 0, 0); } @@ -283,19 +285,40 @@ static void parse_and_dispatch_tlv(TcpStreamCtx_t *ctx, const uint8_t *packet, g_TcpLogic.has_valid_config = 1; cfg_updated = 1; qdx_port_mutex_unlock(g_TcpLogic.config_mutex); + DBG_LOGIC("<< [%s] ConfigCommon: Mode=%d Tag=%d Strict=%d\r\n", + ctx->label, + (int)g_TcpLogic.cached_common.WorkMode, + (int)g_TcpLogic.cached_common.ConfigTag, + (int)g_TcpLogic.cached_common.StrictnessLevel); } break; } case TYPE_CONFIG_2D: { if (len >= sizeof(Config2D_t)) { - DBG_LOGIC("[%s] Config2D parsed OK\r\n", ctx->label); qdx_port_mutex_lock(g_TcpLogic.config_mutex); qdx_deserialize_config2d(&g_TcpLogic.cached_cfg2d, value); - g_TcpLogic.has_valid_config = 1; /* 任意配置到达即标记有效 */ + g_TcpLogic.has_valid_config = 1; cfg_updated = 1; qdx_port_mutex_unlock(g_TcpLogic.config_mutex); + DBG_LOGIC("<< [%s] Config2D: En=%d %dx%d Fps=%d " + "Trig=%d Burst=%d Intv=%d Thresh=%d " + "ROI(%d,%d,%d,%d) NGio=%d\r\n", + ctx->label, + (int)g_TcpLogic.cached_cfg2d.Enabled, + (int)g_TcpLogic.cached_cfg2d.Width, + (int)g_TcpLogic.cached_cfg2d.Height, + (int)g_TcpLogic.cached_cfg2d.Fps, + (int)g_TcpLogic.cached_cfg2d.TriggerMode, + (int)g_TcpLogic.cached_cfg2d.TriggerBurstCount, + (int)g_TcpLogic.cached_cfg2d.TriggerInternalIntervalMs, + (int)g_TcpLogic.cached_cfg2d.TriggerTemperatureThreshold, + (int)g_TcpLogic.cached_cfg2d.TriggerRoiX, + (int)g_TcpLogic.cached_cfg2d.TriggerRoiY, + (int)g_TcpLogic.cached_cfg2d.TriggerRoiW, + (int)g_TcpLogic.cached_cfg2d.TriggerRoiH, + (int)g_TcpLogic.cached_cfg2d.NGioDelay); } else { - DBG_LOGIC("[%s] ! Config2D bad len=%d (need %d)\r\n", + DBG_LOGIC("<< [%s] Config2D bad len=%d (need %d)\r\n", ctx->label, len, (int)sizeof(Config2D_t)); } break; @@ -304,34 +327,47 @@ static void parse_and_dispatch_tlv(TcpStreamCtx_t *ctx, const uint8_t *packet, if (len >= sizeof(Config1D_t)) { qdx_port_mutex_lock(g_TcpLogic.config_mutex); qdx_deserialize_config1d(&g_TcpLogic.cached_cfg1d, value); - g_TcpLogic.has_valid_config = 1; /* 任意配置到达即标记有效 */ + g_TcpLogic.has_valid_config = 1; cfg_updated = 1; qdx_port_mutex_unlock(g_TcpLogic.config_mutex); + DBG_LOGIC("<< [%s] Config1D: En=%d RunMode=%d TrigType=%d " + "BufSz=%d TempLim=%d NGio=%d\r\n", + ctx->label, + (int)g_TcpLogic.cached_cfg1d.Enabled, + (int)g_TcpLogic.cached_cfg1d.RunMode, + (int)g_TcpLogic.cached_cfg1d.TriggerType, + (int)g_TcpLogic.cached_cfg1d.BufferSize, + (int)g_TcpLogic.cached_cfg1d.TriggerTempLimit, + (int)g_TcpLogic.cached_cfg1d.NGioDelay); } break; } case TYPE_TEMP_FRAME: { + DBG_LOGIC("<< [%s] TempFrame request (len=%d)\r\n", ctx->label, (int)len); if (g_TcpLogic.temp_req_cb) { - /* If payload length is >= 18 (TemperatureFrameHeader_t), we can peek - at Is2D. Otherwise we pass 0 or a default value. For now let's pass - an indicator if Is2D is set. */ uint8_t is2d = 0; if (len >= 18) { - is2d = value[18]; /* index 18 in TemperatureFrameHeader_t is Is2D */ + is2d = value[18]; } + DBG_LOGIC(" -> callback: is2D=%d\r\n", (int)is2d); g_TcpLogic.temp_req_cb(is2d); } break; } case TYPE_DETECTION_RESULT: { - if (len >= sizeof(DetectionResult_t) && g_TcpLogic.detect_cb) { + if (len >= sizeof(DetectionResult_t)) { uint32_t frame_num = qdx_read_u32_le(value); uint8_t result_status = value[4]; - g_TcpLogic.detect_cb(frame_num, result_status); + DBG_LOGIC("<< [%s] DetectionResult: frm=%d result=%d\r\n", + ctx->label, (int)frame_num, (int)result_status); + if (g_TcpLogic.detect_cb) + g_TcpLogic.detect_cb(frame_num, result_status); } break; } default: + DBG_LOGIC("<< [%s] Unknown TLV type=0x%02x len=%d\r\n", + ctx->label, (int)type, (int)len); break; } @@ -340,9 +376,7 @@ static void parse_and_dispatch_tlv(TcpStreamCtx_t *ctx, const uint8_t *packet, } if (cfg_updated && g_TcpLogic.config_cb && g_TcpLogic.has_valid_config) { - /* Safely trigger callback. Passing pointers to cached config is ok - during the context of this thread, but user must copy if they - dispatch to another task. */ + DBG_LOGIC("<< [%s] Config updated -> notify app\r\n", ctx->label); qdx_port_mutex_lock(g_TcpLogic.config_mutex); g_TcpLogic.config_cb(&g_TcpLogic.cached_common, &g_TcpLogic.cached_cfg2d, &g_TcpLogic.cached_cfg1d); @@ -604,6 +638,11 @@ TcpLogic_BuildAndSendTemperatureFrame(TcpTxBuffer_t *io_buffer, g_TcpLogic.frame_count++; + DBG_LOGIC(">> [Data] TempFrame #%d: %dx%d type=%d is2D=%d payload=%d\r\n", + (int)processMeta->FrameNumber, + (int)processMeta->ValidWidth, (int)processMeta->ValidHeight, + (int)frameType, (int)is2D, (int)io_buffer->ValidPayloadLen); + /* We need to prepend: TLV Header (3) + TemperatureFrameHeader_t (18) */ uint32_t tlv_wrapper_len = TLV_HEADER_SIZE + sizeof(TemperatureFrameHeader_t); @@ -666,6 +705,9 @@ TcpLogic_BuildAndSendTemperatureFrame(TcpTxBuffer_t *io_buffer, uint32_t frag_count = (total_tlv_len + MAX_FRAGMENT_PAYLOAD - 1) / MAX_FRAGMENT_PAYLOAD; + DBG_LOGIC(">> [Data] Fragmented: %d frags, total=%d\r\n", + (int)frag_count, (int)total_tlv_len); + for (uint32_t i = 0; i < frag_count; i++) { uint32_t chunk_len = total_tlv_len - offset; if (chunk_len > MAX_FRAGMENT_PAYLOAD) diff --git a/prj/TCPClient/User/main.c b/prj/TCPClient/User/main.c index b3ac74f..0efc881 100644 --- a/prj/TCPClient/User/main.c +++ b/prj/TCPClient/User/main.c @@ -17,6 +17,20 @@ * ============================================================ */ #define TEST_PATTERN_MODE 1 +/* ============================================================ + * Feature Test Switches — set to 1 to enable, 0 to disable. + * Allows testing each feature independently. + * ============================================================ */ +#define TEST_ENABLE_HEARTBEAT 1 /* Periodic heartbeat debug print task */ +#define TEST_ENABLE_TRIGGER 1 /* Internal trigger + burst upload */ +#define TEST_ENABLE_NG_GPIO 1 /* NG GPIO pulse output on detection */ +#define TEST_ENABLE_TEMP_REQ 1 /* On-demand frame upload from server */ +#define TEST_ENABLE_TCP_SEND 1 /* TCP data channel sending */ + +/* Default burst parameters — used when server hasn't sent config yet */ +#define DEFAULT_BURST_COUNT 3 +#define DEFAULT_BURST_INTERVAL_MS 200 + #define MAX_TCP_PAYLOAD_SIZE 10240 uint8_t g_TxNetBuffer_A_Mem[MAX_TCP_PAYLOAD_SIZE]; uint8_t g_TxNetBuffer_B_Mem[MAX_TCP_PAYLOAD_SIZE]; @@ -41,6 +55,9 @@ void OnConfigUpdate(const ConfigCommon_t *common, const Config2D_t *cfg2d, const Preprocess_Settings_Change(cfg2d, cfg1d, common); } +extern volatile uint32_t sys_tick_ms; + +#if TEST_ENABLE_NG_GPIO /* NG output GPIO: PA8 push-pull, active-high when NG detected */ #define NG_GPIO_PORT GPIOA #define NG_GPIO_PIN GPIO_Pin_8 @@ -48,7 +65,6 @@ void OnConfigUpdate(const ConfigCommon_t *common, const Config2D_t *cfg2d, const #define NG_PULSE_MS 200 /* default NG pulse width */ static volatile uint32_t g_ng_off_time = 0; -extern volatile uint32_t sys_tick_ms; static void NG_GPIO_Init(void) { @@ -60,7 +76,9 @@ static void NG_GPIO_Init(void) GPIO_Init(NG_GPIO_PORT, &gpio); GPIO_ResetBits(NG_GPIO_PORT, NG_GPIO_PIN); } +#endif /* TEST_ENABLE_NG_GPIO */ +#if TEST_ENABLE_TEMP_REQ /* Flag set by TempFrameRequest callback; consumed by business task */ static volatile uint8_t g_temp_req_pending = 0; static volatile uint8_t g_temp_req_is2d = 1; @@ -71,7 +89,9 @@ void OnTempFrameRequest(uint8_t is2dRequest) g_temp_req_pending = 1; DBG_APP("TempFrameReq is2d=%d\r\n", (int)is2dRequest); } +#endif /* TEST_ENABLE_TEMP_REQ */ +#if TEST_ENABLE_NG_GPIO void OnDetectionResult(uint32_t frameNumber, uint8_t resultStatus) { (void)frameNumber; @@ -89,6 +109,7 @@ void OnDetectionResult(uint32_t frameNumber, uint8_t resultStatus) g_ng_off_time = sys_tick_ms + pulse_ms; } } +#endif /* TEST_ENABLE_NG_GPIO */ #define KEEPALIVE_ENABLE 1 @@ -219,6 +240,7 @@ void WCHNET_HandleGlobalInt(void) } } +#if TEST_ENABLE_HEARTBEAT /* ============================================================ * RTOS Task: Heartbeat (periodic print for debug) * ============================================================ */ @@ -240,6 +262,7 @@ static void task_heartbeat_entry(void *pvParameters) vTaskDelay(pdMS_TO_TICKS(2000)); } } +#endif /* TEST_ENABLE_HEARTBEAT */ /* ============================================================ * RTOS Task: WCHNET protocol stack driver (highest priority) @@ -261,12 +284,14 @@ static void task_wchnet_entry(void *pvParameters) /* ============================================================ * RTOS Task: Business logic (DVP + preprocess + send) * ============================================================ */ +#if TEST_ENABLE_TRIGGER /* ============================================================ * Burst capture state machine * ============================================================ */ static uint8_t burst_active = 0; /* 1 = currently in burst */ static uint8_t burst_remaining = 0; /* frames left to capture */ static uint32_t burst_next_time_ms = 0; /* next burst frame time */ +#endif /* TEST_ENABLE_TRIGGER */ #if TEST_PATTERN_MODE /* ============================================================ @@ -356,6 +381,7 @@ static void task_test_pattern_entry(void *pvParameters) } #endif /* TEST_PATTERN_MODE */ +#if TEST_ENABLE_TEMP_REQ /* ============================================================ * 1D mode: build and send a single 1D temperature frame from * the current raw image. Scans the center row and packs @@ -407,6 +433,7 @@ static void send_1d_frame_from_raw(const RawImageBuffer_t *raw, TcpTxBuffer_t *t TcpLogic_BuildAndSendTemperatureFrame(tx_buf, &meta, 0x01, 0 /* IS_1D */); } +#endif /* TEST_ENABLE_TEMP_REQ */ static void task_business_entry(void *pvParameters) { @@ -415,16 +442,19 @@ static void task_business_entry(void *pvParameters) while (1) { +#if TEST_ENABLE_NG_GPIO /* NG pulse off check */ if (g_ng_off_time && sys_tick_ms >= g_ng_off_time) { GPIO_ResetBits(NG_GPIO_PORT, NG_GPIO_PIN); g_ng_off_time = 0; } +#endif #if !TEST_PATTERN_MODE DVP_Task(); #endif +#if TEST_ENABLE_TEMP_REQ /* Handle on-demand frame request from server */ if (g_temp_req_pending) { @@ -447,6 +477,7 @@ static void task_business_entry(void *pvParameters) send_1d_frame_from_raw(&raw_img, tx_buf); } } +#endif /* TEST_ENABLE_TEMP_REQ */ if (Frame_Ready_Flag) { @@ -458,6 +489,7 @@ static void task_business_entry(void *pvParameters) raw_img.Height = SENSOR_HEIGHT; raw_img.FrameNumber = Ready_Frame_Count; +#if TEST_ENABLE_TRIGGER if (burst_active) { /* Burst mode: wait for interval, then capture & send */ @@ -477,10 +509,10 @@ static void task_business_entry(void *pvParameters) burst_active = 0; DBG_APP("Burst complete\r\n"); } else { - /* Read interval from config */ ConfigCommon_t tc; Config2D_t t2; Config1D_t t1; - uint16_t interval_ms = 0; - if (TcpLogic_GetLatestConfig(&tc, &t2, &t1) == 0) + uint16_t interval_ms = DEFAULT_BURST_INTERVAL_MS; + if (TcpLogic_GetLatestConfig(&tc, &t2, &t1) == 0 + && t2.TriggerInternalIntervalMs > 0) interval_ms = t2.TriggerInternalIntervalMs; burst_next_time_ms = sys_tick_ms + interval_ms; } @@ -506,14 +538,15 @@ static void task_business_entry(void *pvParameters) DBG_APP("PP fail ret=%d\r\n", (int)pp_ret); } - /* Determine burst count from config */ + /* Determine burst count from config (fall back to defaults) */ ConfigCommon_t tc; Config2D_t t2; Config1D_t t1; - uint8_t total_burst = 1; - uint16_t interval_ms = 0; + uint8_t total_burst = DEFAULT_BURST_COUNT; + uint16_t interval_ms = DEFAULT_BURST_INTERVAL_MS; if (TcpLogic_GetLatestConfig(&tc, &t2, &t1) == 0) { - if (t2.TriggerBurstCount > 1) + if (t2.TriggerBurstCount >= 1) total_burst = t2.TriggerBurstCount; - interval_ms = t2.TriggerInternalIntervalMs; + if (t2.TriggerInternalIntervalMs > 0) + interval_ms = t2.TriggerInternalIntervalMs; } if (total_burst > 1) { burst_active = 1; @@ -523,6 +556,7 @@ static void task_business_entry(void *pvParameters) (int)total_burst, (int)interval_ms); } } +#endif /* TEST_ENABLE_TRIGGER */ } else { @@ -536,8 +570,12 @@ int main(void) u8 i; SystemCoreClockUpdate(); Delay_Init(); - USART_Printf_Init(115200); + USART_Printf_Init(921600); printf("TCPClient Test\r\nSystemClk:%d\r\n", SystemCoreClock); + printf("=== Feature Switches ===\r\n"); + printf(" PATTERN=%d TRIGGER=%d NG_GPIO=%d TEMP_REQ=%d TCP_SEND=%d HB=%d\r\n", + TEST_PATTERN_MODE, TEST_ENABLE_TRIGGER, TEST_ENABLE_NG_GPIO, + TEST_ENABLE_TEMP_REQ, TEST_ENABLE_TCP_SEND, TEST_ENABLE_HEARTBEAT); printf("UserByte: %02x\r\n", FLASH_GetUserOptionByte() & 0xFF); Config_Flash_SRAM(FLASH_128_SRAM_192); printf("net version:%x\n", WCHNET_GetVer()); @@ -556,7 +594,9 @@ int main(void) DVP_Init(); #endif TIM2_Init(); +#if TEST_ENABLE_NG_GPIO NG_GPIO_Init(); +#endif i = ETH_LibInit(IPAddr, GWIPAddr, IPMask, MACAddr); mStopIfError(i); @@ -598,15 +638,23 @@ int main(void) TcpLogic_Init(MACAddr, NULL); TcpLogic_RegisterConfigCallback(OnConfigUpdate); +#if TEST_ENABLE_NG_GPIO TcpLogic_RegisterDetectionCallback(OnDetectionResult); +#endif +#if TEST_ENABLE_TEMP_REQ TcpLogic_RegisterTempFrameRequestCallback(OnTempFrameRequest); +#endif DBG_APP("TcpLogic_Start...\r\n"); TcpLogic_Start(); DBG_APP("Creating RTOS tasks...\r\n"); xTaskCreate(task_wchnet_entry, "wchnet", 512, NULL, 6, NULL); +#if TEST_ENABLE_TCP_SEND xTaskCreate(task_business_entry, "business", 512, NULL, 5, NULL); +#endif +#if TEST_ENABLE_HEARTBEAT xTaskCreate(task_heartbeat_entry, "hb", 256, NULL, 3, NULL); +#endif #if TEST_PATTERN_MODE xTaskCreate(task_test_pattern_entry, "testpat", 256, NULL, 4, NULL); #endif