#!/usr/bin/env python3 """Diagnostic build: make the radio show what its SMS assembler actually sees. Three counters are surfaced on screen, so we can tell where reception stops: RX - data bursts handed to the assembler by the driver HDR - data headers parsed (with the announced block count) ASM - completed assemblies (all blocks collected) If RX stays at zero the bursts never reach the module and the problem is in the driver-side capture conditions. If RX counts up but HDR does not, header parsing is rejecting them. If HDR appears but ASM does not, blocks are being lost. """ W = "/home/viktor/ogd77rel/uv_src/OpenGD77_MDUV380_DM1701_20260130/MDUV380_firmware/application" # ---------------------------------------------------------------- sms.h p = W + "/include/functions/sms.h" s = open(p).read() if "smsGetDiagCounters" not in s: a = "bool smsHasUnread(void);\n" assert a in s s = s.replace(a, a + """ // Diagnostics: how many bursts reached the assembler, how many headers were parsed, // and how many messages assembled completely. void smsGetDiagCounters(uint16_t *bursts, uint16_t *headers, uint16_t *assembled, uint8_t *lastBlocks); """, 1) open(p, "w").write(s) print("sms.h: diagnostics declared") # ---------------------------------------------------------------- sms.c p = W + "/source/functions/sms.c" s = open(p).read() if "diagBursts" in s: print("sms.c: already instrumented") else: a = "static bool unread = false;\n" assert a in s s = s.replace(a, a + """ static volatile uint16_t diagBursts = 0; static uint16_t diagHeaders = 0; static uint16_t diagAssembled = 0; static uint8_t diagLastBlocks = 0; """, 1) # count every burst the driver hands us a = "\tmemcpy((uint8_t *)rxQueue[rxQueueWrite], payload, SMS_BLOCK_LENGTH);\n" assert a in s s = s.replace(a, "\tdiagBursts++;\n" + a, 1) # count parsed headers, remembering the announced block count a = "\tblocksExpected = (uint8_t)(hdr[8] & 0x7FU);\n" assert a in s s = s.replace(a, a + "\tdiagHeaders++;\n\tdiagLastBlocks = blocksExpected;\n", 1) # count completed assemblies a = "static void finishAssembly(void)\n{\n" assert a in s s = s.replace(a, a + "\tdiagAssembled++;\n", 1) s += """ void smsGetDiagCounters(uint16_t *bursts, uint16_t *headers, uint16_t *assembled, uint8_t *lastBlocks) { *bursts = diagBursts; *headers = diagHeaders; *assembled = diagAssembled; *lastBlocks = diagLastBlocks; } """ open(p, "w").write(s) print("sms.c: counters added") # ------------------------------------------------------- applicationMain.c p = W + "/source/applicationMain.c" s = open(p).read() if "smsGetDiagCounters" in s: print("applicationMain.c: already showing diagnostics") else: a = "\t\tif (smsHasUnread())\n" assert a in s, "unread check not found" s = s.replace(a, """\t\t{ \t\t\t// Diagnostics: show the assembler counters whenever they change, so we can see \t\t\t// how far a received message gets even when no text is produced. \t\t\tstatic uint16_t lastShownBursts = 0; \t\t\tstatic uint16_t lastShownHeaders = 0; \t\t\tuint16_t dBursts, dHeaders, dAssembled; \t\t\tuint8_t dBlocks; \t\t\tsmsGetDiagCounters(&dBursts, &dHeaders, &dAssembled, &dBlocks); \t\t\tif ((dBursts != lastShownBursts) || (dHeaders != lastShownHeaders)) \t\t\t{ \t\t\t\tchar diagLine[40]; \t\t\t\tlastShownBursts = dBursts; \t\t\t\tlastShownHeaders = dHeaders; \t\t\t\tsnprintf(diagLine, sizeof(diagLine), "RX%u HDR%u/%u ASM%u", \t\t\t\t\t\t(unsigned int)dBursts, (unsigned int)dHeaders, \t\t\t\t\t\t(unsigned int)dBlocks, (unsigned int)dAssembled); \t\t\t\tuiNotificationShow(NOTIFICATION_TYPE_MESSAGE, NOTIFICATION_ID_MESSAGE, 8000, diagLine, true); \t\t\t\tsoundSetMelody(MELODY_KEY_BEEP); \t\t\t} \t\t} """ + a, 1) open(p, "w").write(s) print("applicationMain.c: diagnostics displayed")