DeepSeek V4.1 Flash got the same brief as UNIONALPHA: find why this firmware struggles to decode P25 Phase 1 and Phase 2 voice on the radio’s HR-C6000, and what to do about it.
I checked its claims against the code, the HR-C6000 manual and its own evidence files, and reran its executed tests.
Overall grade
C−
68 / 100 weighted
FDCBA
Right about the chip, wrong about the CPU.
DeepSeek goes where UNIONALPHA didn’t. It makes the HR-C6000 path the central question and flips the burden of proof: the I2S stream the decoder reads is most likely microphone audio.
It finds the monitor leaves the chip in an undocumented hybrid state with de-emphasis switched on. On its own, that setting leaves zero decodable voice frames in my model.
It also proposes the best experiment in either review: the chip’s documented one-layer 4FSK test mode, which hands demodulated bits to the MCU over SPI.
The trouble is precision. It calls the mbelib vocoder “not the blocker” and marks the sample-drain budget “verified adequate”, yet emulated instruction counts put IMBE synthesis at 11–16 times the radio’s 72 MHz CPU.
Neither of its executed MCU findings holds as stated, and 5 of the 30 claims I checked are wrong. That leaves it three points ahead of UNIONALPHA, not a letter grade.
Claims that check out
17 / 30
8 overstated, miscounted or doubtful · 5 wrong
Decode-critical issues found
3 of 4
misses the vocoder CPU wall
Ideas no earlier review had
4
one-layer tap · hybrid state · 8 kHz limit · executed knee
Voice frames with de-emphasis on
0 / 180
3 kHz low-pass alone: 180 / 180 (model)
Headline findings
Six things to know about this review
Holds up
It puts the chip path at the centre, and it’s right to
The MCU reads the HR-C6000’s C_SDO/I2S_TX pin. The manual gives that pin two personalities, vocoder PCM and CodecADC voice, neither of them discriminator audio.
OpenGD77 reads the same slot and calls it “Mic Audio”. Where UNIONALPHA called the route unproven “either direction”, DeepSeek flips the presumption, adds the manual’s “must be 8KHz” frame-clock limit, and names a falsification test.
The monitor never writes HR-C6000 register 0x34, so it inherits 0x3C from the FM receive setup: de-emphasis plus a 3 kHz low-pass. DeepSeek calls that plausibly destructive.
My model makes it concrete: through the firmware’s demodulator, de-emphasis alone leaves 0 of 180 frames, while the 3 kHz low-pass alone costs nothing.
It found a documented bit-level path nobody had tried
Manual §5.4.6: in one-layer test mode the HR-C6000 demodulates 4FSK and leaves 36-byte frames in RX RAM at 0x30 for the MCU to read over SPI. That bypasses the codec, I2S, de-emphasis and the resampler.
36 bytes every 30 ms is exactly 4,800 symbols per second, so contiguous frames would carry every P25 symbol. Whether the mode waits for DMR sync is the open question, and the review says so.
manual 2553–2635, Table 5.6 · 1455–1461
Critical error
It clears the vocoder that cannot run in real time
The executive verdict calls the mbelib path “the correct architecture and not the blocker”, and its evidence marks the drain budget “verified adequate” because 128 samples per 1 ms tick is a 5× margin.
That tick is a minimum, not a guarantee. Emulated counts put mbelib at 11–16 times the 72 MHz CPU, about 430 ms of CPU for a loud 20 ms frame, which overruns the 21 ms sample ring on every frame.
B4: the “lost first LDU with zero impairments” comes from starting the synthetic stream exactly on the frame sync. Add a 40-dibit lead-in and its own harness decodes 36/36.
B3: the clock-error knee is real, but the radio’s 24 kHz clock is a crystal-derived integer divide measured at exactly 24,000 Hz, so it is not the defect to fix first. Its ±0.5% gate fix would flap on 1 Hz counts quantised to ±0.67%.
Several factual slips a reviewer should have caught
DSD does skip the non-standard c0 pattern (p25p1_ldu.c:126–141). The Phase 2 sync is 20 symbols, not 12. The “1,674 references” into the codec blob are mostly the blob’s own lines; 27 lines actually reference it.
“Mic Audio” is cited in the wrong file, and “108+ PASS” doesn’t match the 78 PASS lines in its own log.
Same rubric, weights and scale as the UNIONALPHA grade, so the two scores compare directly. DeepSeek gains on coverage, root cause and originality, and gives most of it back on accuracy.
Dimension scores
Hover or focus a bar for the reasoning. Weighted total 68, grade C−.
Rubric table
Dimension
Weight
Score
Points
Why
Accuracy & evidence
30%
68
20.4
Most citations and its reading of the manual hold, but 5 of 30 checked claims are wrong, including that mbelib is not a blocker and that the drain budget is adequate, and its “executed” first-LDU loss is a harness artifact.
Coverage of decode problems
25%
66
16.5
Finds the microphone route, the de-emphasis hybrid state and the 8 kHz frame-clock limit that UNIONALPHA missed. Misses the vocoder CPU wall, the circular RRC test oracle and, in its final synthesis, the AT1846S filter set.
Root cause & prioritisation
15%
64
9.6
Rightly makes the chip path the central question and flips the burden of proof to the microphone. Then says to fix an unreachable clock-error knee first, and clears the vocoder that cannot run in real time.
Fix plan & acceptance gates
15%
74
11.1
The one-layer 4FSK experiment, a scoped I2S test with mic excitation and the M17 tap with pins are concrete and decisive. Its ±0.5% rate gate, reset suppression and restoring 0x10=0x80 would each create new failures.
Originality & attribution
10%
70
7.0
Credits UNIONALPHA and the Sep 8 review and adds genuinely new work: one-layer mode, the register-level hybrid state, the 8 kHz limit. Omits the Sep 10 review, which already had two of the deltas it claims.
Clarity & calibration
5%
68
3.4
Clear certainty labels and a falsification test, undercut by overclaims: “by anyone, ever”, a “confirmed defect that silently destroys voice”, “verified adequate”.
Weighted total
100%
68
Same rubric and scale as the UNIONALPHA grade: A ≥ 90 · B 80–89 · C+ 75–79 · C 70–74 · C− 65–69 · D 50–64 · F < 50
Receive chain
Where its findings sit
DeepSeek’s findings reach the radio front end and the chip configuration, where UNIONALPHA’s didn’t. The dashed amber route is its proposed one-layer path: the HR-C6000 demodulates the 4FSK itself and the MCU reads bits over SPI. What it missed sits on the MCU side and in the AT1846S.
B1 raised by DeepSeekM1 missed by DeepSeekpath its proposed one-layer routeGrey dashed edge: no documented connection
M2IMBE vocoder needs 11–16× the 72 MHz CPU; it calls mbelib “not the blocker”
B3±10% gate versus ±1% clamp (overstated impact)
M3RRC test waveform matches the receiver filter; its own tests reuse it
B5Capture export stages the wrong halfwords
M4Two SPI writes per decoded voice frame
B6Memory: CCM nearly full, SRAM reserved
B7One-layer 4FSK test mode as a bit-level tap
B8Fail-closed muting at the LDU cadence
B9pcm_starve never increments; MFID mutes clear calls
The chip evidence, checked
Its strongest ground, and the part it left out
DeepSeek’s register-by-register reading holds up against the code and the manual. The one gap is on the other chip: the AT1846S settings appear in its evidence file but never reach the review or the plan. They matter for its own one-layer experiment, because on this board the HR-C6000’s 4FSK demodulator is fed by the AT1846S.
What the P25 monitor leaves in place
Final register state against the stock analog-FM path and OpenGD77’s DMR receive path. The first five rows are DeepSeek’s B2; the last is from its evidence file.
Register
Monitor today
Stock FM RX (V02.03)
OpenGD77 DMR RX
What it means for P25
C6000 0x10
0x6E, DMR slot mode, behind an analog-FM front end
0x80, FM mode
0x6E
Undocumented hybrid, kept because 0x80 stopped the codec clock during bring-up
C6000 0x34
0x3C, inherited: de-emphasis on, 3 kHz low-pass
0x98: band-pass on, de-emphasis off
not written
De-emphasis alone leaves 0/180 frames in the model
C6000 0x36
0x00: feedthrough off, I2S clocks on
0x02: feedthrough on
not written
Dual role; the manual documents only the clock gate
C6000 0xE0
0xC9: mic into LineIn1
0xC9
0xC9
Same value as stock receive; consistent with microphone audio
C6000 0x40 / 0x41
0x00 / 0x00: slot engine off
not written
0xC3 / 0x50
Keeps I2S clocking continuous; forfeits the chip’s own 4FSK receive path
AT1846S 0x40, 0x58, bandwidth
0x0030, 0xBC85, 25 kHz: filters on, low-frequency audio off
not analysed
0x0031, 0x9CDD, 12.5 kHz
Missing from the review and its plan; needed for any P25 route, including one-layer mode
Standard C4FM through each HR-C6000 receive stage alone, then the firmware’s live demodulator and framer. 20 LDUs: 180 IMBE frames possible.
The 3 kHz low-pass is harmless because C4FM sits below 2.88 kHz. De-emphasis, −6 dB per octave from 300 Hz as the manual describes, is fatal on its own. The model can’t tell whether the stage sits on the I2S capture path; DeepSeek says the same.Data table
Audio stage
Noise-free frames · NIDs
Symbol errors
20 dB frames · NIDs
no audio filtering
180/180 · 20/20
0.0%
180/180 · 20/20
3 kHz low-pass only
180/180 · 20/20
0.0%
180/180 · 20/20
de-emphasis only
0/180 · 0/20
51.3%
0/180 · 0/20
de-emphasis + 3 kHz low-pass (0x34=0x3C)
0/180 · 0/20
49.8%
0/180 · 0/20
The one-layer path, and what it would take
Manual Table 5.6 as DeepSeek quotes it (verified line by line), with the questions that decide whether it can carry P25.
Register
Value
Manual description
0x01
xxxx 0000
IF receive mode
0x07 0x08 0x09
0x0B 0xD9 0x54
24-bit IF word, 455 kHz by default (OpenGD77 boots at 450 kHz)
0x10
0x02
One-layer mode, continuous receive; bit 5 for slot receive
0x40
0x40
Receive enable, test mode
0x41
0x41
Receive test enable
Output: 36 demodulated bytes per frame in RX RAM from 0x30, frame type in 0x51, system interrupt bit 0 when ready.
Rate fits exactly: 36 bytes every 30 ms is 9,600 bit/s, which is 4,800 symbols per second. Contiguous frames would lose nothing.
Open: Figure 5.15 is DMR burst geometry, so the mode may only emit frames after DMR sync. That’s the first thing to test.
Missing from its recipe: the AT1846S DMR register set, since the demodulator is fed by the AT1846S. And the vocoder still has to run in real time.
The MCU evidence, rerun
Two executed findings, one artifact, one missed wall
DeepSeek ran its own harness against the production sources, which neither earlier review did. I reran it unchanged except for one variable: whether the synthetic stream starts exactly on the first frame sync, or 40 dibits before it, as the repository’s own timing test does.
Frames decoded versus codec rate error
Its adv_chain.py harness: RRC/AWGN channel at 20 dB, decimated at the true codec rate, then the firmware’s 32-sample streaming resampler, 768/512 demodulator and framer. 4 LDUs, 36 frames possible.
Its harness: stream starts on the frame sync
Same harness with a 40-dibit lead-in
The radio’s measured clock
With a lead-in, every frame decodes within ±0.4% and the knee sits between 0.6% and 1%, so B3’s mechanism is real. Without it, the first LDU is lost at every rate, which is all B4’s “zero impairments” result shows. The radio’s clock error is ppm-level, hundreds of times inside the working range.Data table
Codec error
Starts on the sync: frames · NIDs
40-dibit lead-in: frames · NIDs
-2.0%
0/36 · 0/4
0/36 · 0/4
-1.5%
0/36 · 0/4
9/36 · 1/4
-1.0%
0/36 · 0/4
9/36 · 1/4
-0.8%
0/36 · 0/4
17/36 · 2/4
-0.6%
9/36 · 1/4
27/36 · 3/4
-0.4%
27/36 · 3/4
36/36 · 4/4
-0.2%
27/36 · 3/4
36/36 · 4/4
+0.0%
27/36 · 3/4
36/36 · 4/4
+0.2%
27/36 · 3/4
36/36 · 4/4
+0.4%
27/36 · 3/4
36/36 · 4/4
+0.6%
9/36 · 1/4
27/36 · 3/4
+0.8%
9/36 · 1/4
9/36 · 1/4
+1.0%
0/36 · 0/4
0/36 · 0/4
+1.5%
0/36 · 0/4
0/36 · 0/4
+2.0%
0/36 · 0/4
0/36 · 0/4
Where one second of decoding goes
The firmware’s streaming loop, compiled with its own GCC flags and newlib and run in an emulated Cortex-M4F over 2.2 s of input (12 LDUs, 108 IMBE frames, all decoded). Instruction counts become time by assuming one clock cycle per instruction, the optimistic end.
The demodulator fits: about 40% of the core, 60% at 1.5 cycles per instruction. The vocoder needs roughly 11 times the whole CPU, 16 times at 1.5. Building with -O2 changes these by under 1%, because the time is spent inside newlib’s prebuilt libm.Per-stage table
Stage
-Os, M instr/s
Share at 1.0 · 1.5 c/i
-O2, M instr/s
Resampler ×1.6
1.40
1.9% · 2.9%
1.32
RRC FIR, timing and level fit
28.00
38.9% · 58.3%
27.70
Framing, NID and FEC
0.74
1.0% · 1.5%
0.73
mbelib IMBE decode and synthesis
781.90
1,086.0% · 1,629.0%
781.60
Total
812.1
1,128% · 1,692%
811.4
CPU time for each 20 ms of speech
One call to mbelib’s IMBE decoder per frame, uvquality 1, FEC-valid codewords with chosen pitch and voicing, mean over 100 consecutive frames.
Every frame type misses its 20 ms deadline, from about 2× for the simplest frames to more than 20× for loud voiced ones. The cause is mbelib’s per-harmonic phase, which accumulates without wrapping (mbelib.c:306). Once a call has run for about half a second, nearly every voiced-band cosf argument exceeds about 201 radians, and newlib’s cosf takes its __kernel_rem_pio2f path at roughly 1,700 instructions per call instead of 40 to 100. The real firmware links that same path.Per-frame table
Frame type
Mean, M instr
Worst, M instr
Mean ms at 1.0 · 1.5 c/i
L=20, all bands unvoiced
3.00
5.02
42 · 62
L=20, typical (15 of 20 voiced)
9.68
10.23
134 · 202
L=30, typical (21 of 30 voiced)
13.97
14.76
194 · 291
Random pitch and voicing
15.86
26.17
220 · 330
L=56, all bands voiced
31.25
32.97
434 · 651
Claim check
30 claims, checked one by one
Seventeen hold. Eight are overstated, miscounted, miscited or doubtful. Five are wrong, and two of those steer the reader away from a real blocker.
Item
What DeepSeek V4.1 Flash claims
Where
Result
Notes
§1
The HR-C6000 docks external vocoders (AMBE3000/1000, HR_V3000, SELP, AVDS) and has no IMBE, AMBE+2 or P25 block
manual 43–49, 1181–1213
Holds
The manual never mentions P25, IMBE or DQPSK.
§1
Digital voice on this radio is a DVSI AMBE+2 blob on the STM32 at 0x0807537C
codec.h:38, 51; codec_interface.c:63, 90
Holds
Exact lines.
§1
The stock disassembly has 1,674 references into 0x08075xxx
stock-v0203.dis
Miscounted
1,639 of the 1,666 matching lines are the blob’s own code; 27 lines reference it from outside. The conclusion stands.
Exec
IMBE cannot be decoded “on the HR-C6000 — by anyone, ever”
manual
Holds
True of the die, though the wording is stronger than the point needs.
Exec
The MCU-side mbelib path “is the correct architecture and is not the blocker”
p25rx.c:105
Wrong
Emulated instruction counts put mbelib IMBE synthesis at 11–16× the 72 MHz CPU.
B1
The MCU reads the C6000’s C_SDO/I2S_TX pin, whose two documented personalities carry vocoder PCM or CodecADC voice
manual 496–506; main.c:464
Holds
The clearest statement of the microphone evidence in any review of this tree.
B1
ADCDAT is an input from an external codec; the built-in codec is mic in and line out; FM receive ends at the speaker DAC
manual 337–341, 1108–1112, 2641–2650
Holds
B1
The stock consumer labels the same stream “Mic Audio”
cited as interfaces/i2s.c:444
Wrong file
The comment is at functions/sound.c:444; i2s.c has 139 lines. B5 cites it correctly.
B2
The final chip state is a hybrid: 0x10=0x6E (DMR) with an analog-FM front end, 0x34=0x3C inherited, 0x36=0x00
The inherited 0x34=0x3C enables de-emphasis and a 3 kHz low-pass, plausibly destructive for C4FM
manual 2803–2808, 2822–2824
Holds
Model: de-emphasis alone leaves 0/180 frames; the 3 kHz low-pass alone is harmless.
B2
0x36[6]=0 keeps the I2S master clocks on, in tension with the codebase’s “FM feedthrough off” meaning
manual 1222–1223; HR-C6000.c:2971, 2976
Holds
B2
The manual says the I2S frame clock “must be 8KHz”; the 24 kHz divider math is otherwise legal
manual 1217–1221
Holds
Missed by UNIONALPHA.
B3
The resampler uses the nominal rate, the tracker clamps at ±1% and the health gate admits ±10%
p25mon.c:574–577; p25_4fsk.c:240–241
Holds
Same as UNIONALPHA’s C2.
B3
Executed: around 1% codec error gives zero frames
adv_chain.py; adv_clock_bisect.log
Holds
Rerun with a lead-in: full decode within ±0.4%, collapse by +1%.
B3
So drift, a mis-latched LRCK-only config or an unchanged codec cause silent loss that looks healthy; fix this first
p25mon.c:83, 150
Overstated
The 24 kHz clock is a crystal-derived integer divide, measured at exactly 24,000 Hz, so drift is ppm-level. 8 kHz and LRCK-only configs fall below the 12 kHz decode gate and are rejected, not accepted.
B4
Executed: LDU #1 is lost even with zero impairments, so every reset costs at least 180 ms
adv_chain.log A1
Artifact
The harness starts the stream exactly on the frame sync. With a 40-dibit lead-in the same code decodes 36/36 frames.
B5
The capture stages the first 40 L/R pairs of each row, and the second half of every row is missing
p25mon.c:462–467
Holds
Already described in the Sep 10 review.
B6
CCM has 1,160 bytes free; .bss ends at 0x2001F9FC; defaultTask stack is 8,192 bytes
MDUV380_FW.elf; main.c:74–78
Holds
Its evidence table lists the 0x600 heap and stack reservation as “free”, which it is not.
B7
One-layer 4FSK mode stores 36-byte demodulated frames at RX RAM 0x30 for SPI reads; Table 5.6 gives the register recipe
manual 2553–2635, 1455–1461
Holds
Documented and untried. The frame geometry is DMR-shaped, as the review says.
B8
One failed signalling decode demotes a clear call and mutes audio until the next LDU2 or HDU
p25rx.c:42–49, 177–181, 261–265, 274–277
Holds
B9
A non-standard-MFID group LC never establishes a clear call
p25rx.c:159–163
Holds
B9
The non-standard c0 skip is project-local; DSD has no equivalent
p25rx.c:91–104; dsd_mbe.c:94
Wrong
DSD skips the identical 23-bit pattern in p25p1_ldu.c:126–141.
B9
No end-to-end voice test exists, so a future table or mbelib-layout regression would pass every framing test
p25_selftest.c:442–448
Overstated
The suite rebuilds payload dibits through DSD’s independent interleave tables, so a table regression fails. Only audio-level regressions slip through.
B10
Phase 2 grants are not followed because 0x33 invalidates TDMA identifiers
p25_trunk.c:10–26
Holds
B10
Phase 2 has a 12-symbol sync
PHASE2_FINDINGS.md
Wrong
The Phase 2 sync is 20 symbols (DSD-FME P25P2_SYNC).
B10
H-DQPSK needs coherent IQ and is not discriminator-compatible
B10; PHASE2_FINDINGS.md
Overstated
DSD-FME, bundled in ref-sources, carries Phase 2 CQPSK options for FM-demodulated input. Harder than C4FM, not impossible.
B10
Use the vendored mbelib AMBE+2 decoder for Phase 2 voice rather than the DVSI blob
mbelib/ambe3600x2450.c
Doubtful
mbelib’s AMBE+2 path shares the synthesis routine that puts IMBE at 11–16× the CPU; the DVSI decoder already runs DMR voice in real time on this MCU.
N6
Drain budget “verified adequate”: 128 samples per 1 ms tick is a 5× margin
MCU_CHAIN_FINDINGS.md N6
Wrong
The 1 ms loop is a minimum period. One mbelib frame takes 134–458 ms of CPU, far past the 21 ms ring.
§4
The host suite gives “108+ PASS”, exit 0
run_py.log
Miscounted
Its own log has 78 PASS lines out of 104; exit 0 is right.
§5
New in this review: the 0x34 de-emphasis discovery and the half-row capture loss
Deltas section
Overstated
Both earlier reviews raised C6000 de-emphasis, and the Sep 10 review described the half-row loss. The register-level 0x34 and 0x10 analysis is new.
Provenance
What was already known, and what it added
DeepSeek was handed UNIONALPHA’s findings as a baseline and says so, which is the right way to build on earlier work. It doesn’t mention the Sep 10 review, which already had two of the deltas it claims. Its new material is real and chip-side.
Issue
P25-HARDWARE-REVIEW Sep 8
P25-PROJECT-REVIEW Sep 10
UNIONALPHA Sep 16
DeepSeek V4.1 Flash Sep 16–17
Capture export stages the wrong I2S halfwords
absent
raised F1
raised F1
raised B5
Capture parser certifies an incomplete stream
absent
raised F2
raised F2
partly in its plan
pcm_starve never increments
partly asks for underrun counts
raised F3
raised F3
raised B9
No static RAM margin
partly 648 bytes then
raised F4
raised F4
raised B6
The I2S stream is most likely microphone audio
raised cites sound.c
raised
partly “either direction”
raised B1
HR-C6000 de-emphasis on the capture path
partly code comment
partly code comment
absent
raised B2, register 0x34
AT1846S FM filters, low-frequency bit, 25 kHz
raised
raised
absent
partly evidence file only
0x10=0x6E hybrid state; 0x36 dual role
absent
absent
absent
raised new
Manual: I2S frame clock “must be 8KHz”
absent
absent
absent
raised new
One-layer 4FSK test mode as a P25 tap
absent
absent
absent
raised new
±10% health gate versus ±1% timing clamp
absent
absent
raised C2
raised B3, executed
Fail-closed muting at LDU cadence
absent
partly late entry
absent “keep fail-closed”
raised B8
Non-standard MFID mutes clear calls
absent
absent
absent
raised B9
Test waveform shares the receiver’s RRC filter missed
raised
raised F6
absent
absent reuses it
MCU runs at 72 MHz
raised
raised
absent
partly Phase 2 gate only
Vocoder needs 11–16× the 72 MHz CPU missed
absent
partly cycles per frame
partly “to measure”
absent “not the blocker”
Direct discriminator tap (M17 mod)
raised with pins
raised
partly no pins
raised with pins
Phase 2 architecture and scope
partly
partly
raised
raised with errors
Its plan
What to keep, change and add
DeepSeek’s ordering is sound: trust the instruments, settle the tap question with the documented path, then harden the MCU chain. Most of its steps survive checking; three would cause new problems, and two things any P25 route needs are missing.
Keep
Worth doing as written
Phase 0 instrument fixes: capture stride through the real DMA adapter, a strict parser, a live pcm_starve counter.
The one-layer experiment: Table 5.6 values, reads of RX RAM 0x30, 0x51 and interrupt bit 0. Gate: bits follow RF and not the microphone.
Scope the I2S pins with the speaker muted and the mic excited, and abandon the I2S route if samples follow the mic.
0x34=0x00 as the first register test; the model says de-emphasis alone is fatal.
The M17 tap fallback with pins (AT1846S pin 9 to MCU pin 18), time-boxed.
Latch a clear call through one failed signalling decode, fix MFID handling, add a known-answer IMBE audio vector.
Change
Would cause new problems
B3’s ±0.5% gate: the rate report is quantised to ±0.67% per second, so this gate would flap and reset the stream. Keep the validated nominal ratio, average over tens of seconds, and report the deviation.
B4’s reset suppression: retunes, clock changes and overruns are real discontinuities. Count and show resets instead of joining unrelated samples.
Restoring 0x10=0x80 or trying 0x40=0x43: the bring-up log shows both stop or gate the codec clock. Change 0x34 alone first.
Phase 2 voice via mbelib: it shares the synthesis routine that is 11–16× too slow here. Assess the real-time DVSI decoder’s entry points and licensing first.
Add
Missing from its plan
The AT1846S DMR register set for any P25 session: 0x40 low-frequency bit, 0x58=0x9CDD, 0x44=0x07FF, 12.5 kHz. The one-layer path and the M17 tap need it as much as I2S does.
A real-time vocoder: a per-harmonic phase accumulator with a cosine table. Without it, even a perfect tap yields no audio.
Standard C4FM test vectors (raised cosine × inverse sinc) with de-emphasis and high-pass regressions, instead of the RRC model its own harness reuses.
Set the audio path once at start, not on every decoded 20 ms frame.
Phase 2
Right on architecture, wrong on the details that decide the route
DeepSeek’s central Phase 2 points hold. The HR-C6000 decodes neither IMBE nor AMBE+2, its TDMA engine is DMR-shaped and runs at 4,800 rather than 6,000 symbols per second, and p25_trunk.c:26 means Phase 2 grants are never followed. Its work breakdown, 2–4 thousand lines plus test vectors, is a reasonable order of magnitude.
Three details are off. The Phase 2 sync is 20 symbols, not 12. “Coherent IQ only” is too strong: DSD-FME, bundled in ref-sources/, carries Phase 2 CQPSK options for FM-demodulated input, at a cost in margin. And its preferred voice route, the vendored mbelib AMBE+2 decoder, uses the same synthesis routine that puts IMBE at 11–16 times this CPU. The licensed DVSI decoder already decodes AMBE+2 in real time on this radio for DMR. Its entry points and licensing are fair open questions, but it is the route that could keep up.
Against UNIONALPHA
More useful, less careful
UNIONALPHA is the more careful review: almost every claim holds, but it spends them on tooling. DeepSeek finds the chip-side problems UNIONALPHA missed and proposes the best experiment either offers, but makes more mistakes, and one of them clears a real blocker. Neither found the vocoder CPU wall or the circular RRC test oracle.
Same rubric and weights. Hover or focus a bar for the score.
UNIONALPHA
DeepSeek V4.1 Flash
Method and limits
How this was checked
I read DEEPSEEK41_REVIEW.md and its evidence in analysis/deepseek41-review/, then checked each claim against the firmware sources, the OpenGD77 radio drivers, the translated HR-C6000 manual, the stock-firmware analysis, DSD, DSD-FME and the earlier reviews. The review’s build had touched the P25 source timestamps; the contents were confirmed unchanged.
I reran its adv_chain.py harness unchanged, varying only the lead-in before the first frame sync. The de-emphasis check and CPU figures use the same firmware-in-the-loop model and emulator measurement as the UNIONALPHA grade.
The AT1846S and HR-C6000 filter responses are modelled, not measured. Whether de-emphasis sits on the I2S capture path is unknown.
The one-layer mode is documented but untested here; nothing was flashed and no radio was touched.
CPU figures come from instruction counts in an emulator, not cycle-accurate timing on the radio.
DM1701_REPO=/path/to/DM-1701 python3 knee_rerun.py
# lead-in 0: at most 27/36 frames, even at 0% error
# lead-in 40: 36/36 within ±0.4%, 0/36 at +1.0%
DM1701_REPO=/path/to/DM-1701 python3 deemph_check.py
# 3 kHz low-pass alone 180/180 · de-emphasis alone 0/180
grep -n "non-standard c0" -A16 ref-sources/dsd-master/src/p25p1_ldu.c
grep -n P25P2_SYNC ref-sources/dsd-fme/include/dsd.h