Returned to the trace data processing, even though I wrote earlier I would skip it and write my own FPGA implementation.
To get a first working version of this open scope firmware, and have people test it, it is easier to stick with the original FPGA for now.
So I dove into the 25 and 10nS/div code. There are two functions per channel doing the work. Had to revert to my emulator to get to the bottom of the first function because the Ghidra output did not make it clear on what is being done.
This is the untouched C output
void scope_pre_process_ch1_25ns_data(void)
{
undefined2 uVar1;
int iVar2;
int iVar3;
uint *puVar4;
uint *puVar5;
uint *puVar6;
uint *puVar7;
uint **ppuVar8;
uint **ppuVar9;
byte *pbVar10;
undefined2 *puVar11;
uint uVar12;
uint uVar13;
byte bVar14;
uint uVar15;
int iVar16;
short *psVar17;
byte bVar18;
undefined2 uVar19;
uint *puVar20;
uint *puVar21;
uint uVar22;
uint uVar23;
uint uVar24;
bool bVar25;
bool bVar26;
puVar7 = DAT_8000470c;
puVar21 = DAT_80004708;
iVar16 = 0x2e8;
*(undefined2 *)((int)DAT_8000470c + 2) = *(undefined2 *)DAT_80004708;
uVar19 = *(undefined2 *)((int)puVar21 + 2);
puVar11 = (undefined2 *)((int)puVar7 + 2);
do {
uVar1 = *(undefined2 *)(puVar21 + 1);
puVar11[2] = uVar19;
uVar19 = *(undefined2 *)((int)puVar21 + 6);
iVar16 = iVar16 + -1;
puVar11 = puVar11 + 4;
*puVar11 = uVar1;
iVar3 = DAT_8000471c;
iVar2 = DAT_80004718;
puVar21 = puVar21 + 1;
} while (iVar16 != 0);
*(undefined2 *)(DAT_80004714 + 2) = *DAT_80004710;
uVar15 = DAT_80004720;
uVar12 = 0;
if (*(short *)(iVar2 + 0x1c) == 0) {
do {
uVar13 = (uint)*(ushort *)(iVar3 + uVar12 * 2);
if (*(ushort *)(iVar2 + 0x1e) < uVar13) {
puVar21 = (uint *)(uVar13 - *(ushort *)(iVar2 + 0x1e));
*(short *)(puVar7 + uVar12) = (short)puVar21;
}
else {
puVar21 = puVar7 + uVar12;
*(undefined2 *)puVar21 = 0;
}
uVar12 = uVar12 + 1 & 0xfffeffff;
} while (uVar12 < uVar15);
}
else {
do {
psVar17 = (short *)(iVar3 + uVar12 * 2);
puVar21 = puVar7 + uVar12;
uVar12 = uVar12 + 2 & 0xfffeffff;
*(short *)puVar21 = *psVar17 + *(short *)(iVar2 + 0x1e);
*(short *)(puVar21 + 1) = psVar17[1] + *(short *)(iVar2 + 0x1e);
} while (uVar12 < uVar15);
}
uVar12 = DAT_80004724;
puVar5 = DAT_80004708;
puVar7 = DAT_8000470c;
if (3 < DAT_80004724) {
puVar20 = (uint *)((uint)DAT_80004708 & 3);
uVar13 = DAT_80004724;
puVar21 = puVar20;
if (puVar20 != NULL) {
bVar14 = *(byte *)DAT_8000470c;
puVar6 = (uint *)((int)DAT_8000470c + 1);
if (puVar20 < (uint *)0x3) {
puVar6 = (uint *)((int)DAT_8000470c + 2);
puVar21 = (uint *)(uint)*(byte *)(uint *)((int)DAT_8000470c + 1);
}
puVar4 = (uint *)((int)DAT_80004708 + 1);
*(byte *)DAT_80004708 = bVar14;
puVar7 = puVar6;
if (puVar20 < (uint *)0x2) {
puVar7 = (uint *)((int)puVar6 + 1);
bVar14 = *(byte *)puVar6;
}
puVar6 = puVar4;
if (puVar20 < (uint *)0x3) {
puVar6 = (uint *)((int)puVar5 + 2);
*(byte *)puVar4 = (byte)puVar21;
}
uVar13 = (int)puVar20 + (uVar12 - 4);
puVar5 = puVar6;
if (puVar20 < (uint *)0x2) {
puVar5 = (uint *)((int)puVar6 + 1);
*(byte *)puVar6 = bVar14;
}
}
uVar15 = (uint)puVar7 & 3;
if (uVar15 == 0) {
while (uVar12 = uVar13 - 0x20, 0x1f < uVar13) {
uVar15 = puVar7[1];
uVar13 = puVar7[2];
uVar22 = puVar7[3];
*puVar5 = *puVar7;
puVar5[1] = uVar15;
puVar5[2] = uVar13;
puVar5[3] = uVar22;
uVar15 = puVar7[4];
uVar13 = puVar7[5];
uVar22 = puVar7[6];
uVar23 = puVar7[7];
puVar7 = puVar7 + 8;
puVar5[4] = uVar15;
puVar5[5] = uVar13;
puVar5[6] = uVar22;
puVar5[7] = uVar23;
puVar5 = puVar5 + 8;
uVar13 = uVar12;
}
if ((bool)((byte)(uVar12 >> 4) & 1)) {
uVar15 = *puVar7;
uVar22 = puVar7[1];
uVar23 = puVar7[2];
uVar24 = puVar7[3];
puVar7 = puVar7 + 4;
*puVar5 = uVar15;
puVar5[1] = uVar22;
puVar5[2] = uVar23;
puVar5[3] = uVar24;
puVar5 = puVar5 + 4;
}
if ((int)(uVar13 << 0x1c) < 0) {
uVar15 = *puVar7;
uVar22 = puVar7[1];
puVar7 = puVar7 + 2;
*puVar5 = uVar15;
puVar5[1] = uVar22;
puVar5 = puVar5 + 2;
}
puVar20 = puVar5;
puVar21 = puVar7;
if ((bool)((byte)(uVar12 >> 2) & 1)) {
puVar21 = puVar7 + 1;
uVar15 = *puVar7;
puVar20 = puVar5 + 1;
*puVar5 = uVar15;
}
uVar19 = (undefined2)uVar15;
if ((uVar12 & 3) != 0) {
bVar26 = (bool)((byte)(uVar12 >> 1) & 1);
uVar13 = uVar13 << 0x1f;
bVar25 = (int)uVar13 < 0;
puVar7 = puVar21;
if (bVar26) {
puVar7 = (uint *)((int)puVar21 + 2);
uVar19 = *(undefined2 *)puVar21;
}
if (bVar25) {
uVar13 = (uint)*(byte *)puVar7;
}
puVar21 = puVar20;
if (bVar26) {
puVar21 = (uint *)((int)puVar20 + 2);
*(undefined2 *)puVar20 = uVar19;
}
if (bVar25) {
*(byte *)puVar21 = (byte)uVar13;
}
return;
}
return;
}
uVar12 = uVar13 - 4;
if (3 < uVar13) {
ppuVar8 = (uint **)((int)puVar7 - uVar15);
puVar21 = *ppuVar8;
puVar7 = puVar5;
if (uVar15 == 2) {
do {
ppuVar9 = ppuVar8;
uVar15 = (uint)puVar21 >> 0x10;
ppuVar8 = ppuVar9 + 1;
puVar21 = *ppuVar8;
bVar25 = 3 < uVar12;
uVar12 = uVar12 - 4;
uVar15 = uVar15 | (int)puVar21 << 0x10;
puVar5 = puVar7 + 1;
*puVar7 = uVar15;
puVar7 = puVar5;
} while (bVar25);
puVar7 = (uint *)((int)ppuVar9 + 6);
}
else {
if (uVar15 < 3) {
do {
ppuVar9 = ppuVar8;
uVar15 = (uint)puVar21 >> 8;
ppuVar8 = ppuVar9 + 1;
puVar21 = *ppuVar8;
bVar25 = 3 < uVar12;
uVar12 = uVar12 - 4;
uVar15 = uVar15 | (int)puVar21 << 0x18;
puVar5 = puVar7 + 1;
*puVar7 = uVar15;
puVar7 = puVar5;
} while (bVar25);
puVar7 = (uint *)((int)ppuVar9 + 5);
}
else {
do {
ppuVar9 = ppuVar8;
uVar15 = (uint)puVar21 >> 0x18;
ppuVar8 = ppuVar9 + 1;
puVar21 = *ppuVar8;
bVar25 = 3 < uVar12;
uVar12 = uVar12 - 4;
uVar15 = uVar15 | (int)puVar21 << 8;
puVar5 = puVar7 + 1;
*puVar7 = uVar15;
puVar7 = puVar5;
} while (bVar25);
puVar7 = (uint *)((int)ppuVar9 + 7);
}
}
}
}
bVar18 = (byte)puVar21;
bVar14 = (byte)uVar15;
bVar26 = (bool)((byte)(uVar12 >> 1) & 1);
uVar12 = uVar12 << 0x1f;
bVar25 = (int)uVar12 < 0;
if (bVar26) {
pbVar10 = (byte *)((int)puVar7 + 1);
bVar14 = *(byte *)puVar7;
puVar7 = (uint *)((int)puVar7 + 2);
bVar18 = *pbVar10;
}
if (bVar25) {
uVar12 = (uint)*(byte *)puVar7;
}
if (bVar26) {
pbVar10 = (byte *)((int)puVar5 + 1);
*(byte *)puVar5 = bVar14;
puVar5 = (uint *)((int)puVar5 + 2);
*pbVar10 = bVar18;
}
if (bVar25) {
*(byte *)puVar5 = (byte)uVar12;
}
return;
}
And this is the assembly, which tells a bit more, but still tough to figure out.
**************************************************************
* FUNCTION *
**************************************************************
void __stdcall scope_pre_process_ch1_25ns_data(void)
void <VOID> <RETURN>
undefined4 Stack[-0x18]:4 local_18 XREF[2]: 80004614(W),
800046b0(*)
scope_pre_process_ch1_25ns_data XREF[1]: scope_get_short_timebase_data:80
8000460c e0 03 2d e9 stmdb sp!,{r5 r6 r7 r8 r9}
80004610 f0 20 9f e5 ldr r2,[DAT_80004708] = 8019D5EAh
80004614 04 40 2d e5 str r4,[sp,#local_18]!
80004618 b0 c0 d2 e1 ldrh r12,[r2,#0x0]=>DAT_8019d5ea
8000461c e8 00 9f e5 ldr r0,[DAT_8000470c] = 801AEF2Ah
80004620 ba 3f a0 e3 mov r3,#0x2e8
80004624 b2 c0 c0 e1 strh r12,[r0,#0x2]=>DAT_801aef2c
80004628 b2 c0 d2 e1 ldrh r12,[r2,#0x2]=>DAT_8019d5ec
8000462c 02 10 80 e2 add r1,r0,#0x2
LAB_80004630 XREF[1]: 80004644(j)
80004630 b4 40 f2 e1 ldrh r4,[r2,#0x4]!=>DAT_8019d5ee
80004634 b4 c0 c1 e1 strh r12,[r1,#0x4]=>DAT_801aef30
80004638 b2 c0 d2 e1 ldrh r12,[r2,#0x2]=>DAT_8019d5f0
8000463c 01 30 53 e2 subs r3,r3,#0x1
80004640 b8 40 e1 e1 strh r4,[r1,#0x8]!=>DAT_801aef34
80004644 f9 ff ff 1a bne LAB_80004630
80004648 c0 10 9f e5 ldr r1,[DAT_80004710] = 8019E18Ch
8000464c c0 c0 9f e5 ldr r12,[DAT_80004714] = 801B066Eh
80004650 b0 10 d1 e1 ldrh r1,[r1,#0x0]=>DAT_8019e18c
80004654 bc 20 9f e5 ldr r2,[DAT_80004718] = 802F18B0h
80004658 bc 50 9f e5 ldr r5,[DAT_8000471c] = 8019ED5Ah
8000465c b2 10 cc e1 strh r1,[r12,#0x2]=>DAT_801b0670
80004660 bc 11 d2 e1 ldrh r1,[r2,#0x1c]=>DAT_802f18cc
80004664 b4 30 9f e5 ldr r3,[DAT_80004720] = 000005D2h
80004668 00 00 51 e3 cmp r1,#0x0
8000466c 00 10 a0 e3 mov r1,#0x0
80004670 00 40 a0 03 moveq r4,#0x0
80004674 13 00 00 0a beq LAB_800046c8
LAB_80004678 XREF[1]: 800046ac(j)
80004678 be 71 d2 e1 ldrh r7,[r2,#0x1e]=>DAT_802f18ce
8000467c 02 60 81 e2 add r6,r1,#0x2
80004680 81 40 85 e0 add r4,r5,r1, lsl #0x1
80004684 b0 80 d4 e1 ldrh r8,[r4,#0x0]=>DAT_8019ed5a
80004688 01 c1 80 e0 add r12,r0,r1, lsl #0x2
8000468c 01 18 c6 e3 bic r1,r6,#0x10000
80004690 07 60 88 e0 add r6,r8,r7
80004694 b0 60 cc e1 strh r6,[r12,#0x0]=>DAT_801aef2a
80004698 b2 40 d4 e1 ldrh r4,[r4,#0x2]=>DAT_8019ed5c
8000469c be 61 d2 e1 ldrh r6,[r2,#0x1e]=>DAT_802f18ce
800046a0 03 00 51 e1 cmp r1,r3
800046a4 06 40 84 e0 add r4,r4,r6
800046a8 b4 40 cc e1 strh r4,[r12,#0x4]=>DAT_801aef2e
800046ac f1 ff ff 3a bcc LAB_80004678
LAB_800046b0 XREF[1]: 80004704(j)
800046b0 f0 01 bd e8 ldmia sp!,{r4 r5 r6 r7 r8}=>local_18
800046b4 68 20 9f e5 ldr r2,[DAT_80004724] = 000016A8h
800046b8 4c 10 9f e5 ldr r1,[DAT_8000470c] = 801AEF2Ah
800046bc 44 00 9f e5 ldr r0,[DAT_80004708] = 8019D5EAh
800046c0 04 90 9d e4 ldr r9,[sp],#0x4
800046c4 e4 ef ff ea b memcpy
LAB_800046c8 XREF[2]: 80004674(j), 80004700(j)
800046c8 81 c0 85 e0 add r12,r5,r1, lsl #0x1
800046cc b0 c0 dc e1 ldrh r12,[r12,#0x0]=>DAT_8019ed5a
800046d0 be 61 d2 e1 ldrh r6,[r2,#0x1e]=>DAT_802f18ce
800046d4 0c 00 56 e1 cmp r6,r12
800046d8 01 c1 80 20 addcs r12,r0,r1, lsl #0x2
800046dc b0 40 cc 21 strhcs r4,[r12,#0x0]
800046e0 03 00 00 2a bcs LAB_800046f4
800046e4 be 61 d2 e1 ldrh r6,[r2,#0x1e]=>DAT_802f18ce
800046e8 01 71 80 e0 add r7,r0,r1, lsl #0x2
800046ec 06 c0 4c e0 sub r12,r12,r6
800046f0 b0 c0 c7 e1 strh r12,[r7,#0x0]=>DAT_801aef2a
LAB_800046f4 XREF[1]: 800046e0(j)
800046f4 01 10 81 e2 add r1,r1,#0x1
800046f8 01 18 c1 e3 bic r1,r1,#0x10000
800046fc 03 00 51 e1 cmp r1,r3
80004700 f0 ff ff 3a bcc LAB_800046c8
80004704 e9 ff ff ea b LAB_800046b0
This is my commented take on it.
void scope_pre_process_ch1_25ns_data(void)
{
undefined2 uVar1;
int iVar2;
int iVar3;
uint *puVar4;
uint *puVar5;
uint *puVar6;
uint *puVar7;
uint **ppuVar8;
uint **ppuVar9;
byte *pbVar10;
undefined2 *puVar11;
uint uVar12;
uint uVar13;
byte bVar14;
uint uVar15;
int iVar16;
short *psVar17;
byte bVar18;
undefined2 uVar19;
uint *puVar20;
uint *puVar21;
uint uVar22;
uint uVar23;
uint uVar24;
bool bVar25;
bool bVar26;
puVar7 = DAT_8000470c; //0x801AEF2A = temptracebuffer1 + 4
puVar21 = DAT_80004708; //0x8019D5EA = channel1tracebuffer1 (1500 samples from most likely adc1)
iVar16 = 0x2e8; //744
//Copy a short from buffer1 to buffer2
*(undefined2 *)((int)DAT_8000470c + 2) = *(undefined2 *)DAT_80004708; //0x801aef2c = 0x8019d5ea
uVar19 = *(undefined2 *)((int)puVar21 + 2); //Get data from 0x8019d5ec
puVar11 = (undefined2 *)((int)puVar7 + 2); //point to next item in the temp buffer
//Copy data from sample buffer to temp buffer while skipping a sample in the temp buffer. (Make room for another sample???)
do
{
uVar1 = *(undefined2 *)(puVar21 + 1); //0x8019d5ee
puVar11[2] = uVar19; //0x801aef30 = 0x8019d5ec skip one item
uVar19 = *(undefined2 *)((int)puVar21 + 6); //0x8019d5f0
iVar16 = iVar16 + -1;
puVar11 = puVar11 + 4;
*puVar11 = uVar1; //0x801aef34 = 0x8019d5ee
puVar21 = puVar21 + 1;
} while (iVar16 != 0);
//Last copies done
//0x0x801B0668 = 0x8019E18A
//0x0x801B066C = 0x8019E18C
iVar3 = DAT_8000471c; //0x8019ED5A channel1tracebuffer2 (1500 samples from most likely adc2)
iVar2 = DAT_80004718; //0x802F18B0 Calibration data
*(undefined2 *)(DAT_80004714 + 2) = *DAT_80004710; //0x801B0670 = 0x8019E18C
uVar15 = DAT_80004720; //0x000005D2 = 1490
uVar12 = 0;
if (*(short *)(iVar2 + 0x1c) == 0) //0x802f18cc Either 1 or 0 based on some calibration action
{
//Trace data showed this to be zero on my scope, so this loop is done
do
{
uVar13 = (uint)*(ushort *)(iVar3 + uVar12 * 2); //First sample from 0x8019ed5a
if (*(ushort *)(iVar2 + 0x1e) < uVar13) //0x802f18ce also some calibration data (3 on my scope)
{
puVar21 = (uint *)(uVar13 - *(ushort *)(iVar2 + 0x1e));
*(short *)(puVar7 + uVar12) = (short)puVar21; //puVar7 = temp trace buffer
}
else
{
puVar21 = puVar7 + uVar12;
*(undefined2 *)puVar21 = 0;
}
uVar12 = uVar12 + 1 & 0xfffeffff;
} while (uVar12 < uVar15);
//Trace shows this
//First samples
//0x801AEF2A = 0x8019ED5A
//0x801AEF2E = 0x8019ED5C
//0x801AEF32 = 0x8019ED5E
//Last samples
//0x801B066A = 0x8019F8FA
//0x801B066E = 0x8019F8FC
}
else
{
do
{ //two samples at a time, but I miss the interleaving???? Maybe buffers or pointers defined as 32 bit items
psVar17 = (short *)(iVar3 + uVar12 * 2);
puVar21 = puVar7 + uVar12;
uVar12 = uVar12 + 2 & 0xfffeffff;
*(short *)puVar21 = *psVar17 + *(short *)(iVar2 + 0x1e);
*(short *)(puVar21 + 1) = psVar17[1] + *(short *)(iVar2 + 0x1e);
} while (uVar12 < uVar15);
//Trace shows this
//First samples
//0x801AEF2A = 0x8019ED5A
//0x801AEF2E = 0x8019ED5C
//0x801AEF32 = 0x8019ED5E
//0x801AEF36 = 0x8019ED60
//Last samples
//0x801B0662 = 0x8019F8F6
//0x801B0666 = 0x8019F8F8
//0x801B066A = 0x8019F8FA
//0x801B066E = 0x8019F8FC
}
//DAT_80004724; //0x000016A8 5800 bytes
//DAT_80004708; //0x8019D5EA first buffer destination
//DAT_8000470c; //0x801AEF2A temp buffer source
//Copy the temp buffer back to the first trace buffer
memcpy(DAT_80004708, DAT_8000470c, DAT_80004724);
}
It does confirm my thoughts on why they read a second buffer of 1500 bytes from the FPGA when in 25 or 10nS/Div setting. For the other time base settings they only sample using a single ADC. For the lowest two settings they also use the second ADC, but instead of having the FPGA do the interleaving of the two samples, they do it in the CPU.
That is all this first function does. Interleave the samples of the two reads. Only on the second set of data they do some calibration based action. In the code there is a check on a flag, if zero they use a subtract of a calibration value, if one they add the value. They probably measure the difference between the two ADC's and the flag is set based on which one is lower then the other.
This flag and value are determined in the calibration procedure and stored in the settings. This concerns the first four of the unknown calibration values found earlier. (2 per channel. Flag and value)
For this to make sense the two ADC's in one package have to have a possible mismatch. Need to look at the specifications.