У меня сейчас, после общения с чатиком жпт выпала челюсть.
Даю ему код (это после дизассемблирования и декомпилирования + восстановлены имена функций в табличке phyFuns) и говорю буквально следующее: “Чатик, что это за магия тут и вычисления“
/* WARNING: Globals starting with '_' overlap smaller symbols at the same address */
void dc_iq_est_test(undefined1 param_1,uint param_2,int *param_3,int *param_4)
{
phyFuns *ppVar1;
int iVar2;
int iVar3;
int iVar4;
int iVar5;
int iVar6;
(*(code *)g_phyFuns->ram_iq_est_enable)(param_1,param_2 & 0xffff);
iVar2 = (param_2 & 0xffff) + 1;
memw();
iVar4 = (_DAT_6000615c >> 6) / iVar2;
*param_3 = iVar4;
memw();
iVar5 = (_DAT_60006160 >> 6) / iVar2;
param_3[1] = iVar5;
memw();
memw();
memw();
iVar6 = (_DAT_60006164 / iVar2) * 8 - (iVar4 * iVar4 + iVar5 * iVar5);
iVar3 = (_DAT_60006168 / iVar2) * 4 - iVar4 * iVar4;
iVar4 = (_DAT_6000616c / iVar2) * 4 - iVar5 * iVar5;
iVar2 = (*(code *)g_phyFuns->rom_linear_to_db)((uint)(-1 < iVar6) * iVar6,0);
*param_4 = iVar2;
param_3[2] = iVar2 + 8 >> 4;
iVar2 = (*(code *)g_phyFuns->rom_linear_to_db)((uint)(-1 < iVar3) * iVar3,0);
ppVar1 = g_phyFuns;
param_4[1] = iVar2;
iVar2 = (*(code *)ppVar1->rom_linear_to_db)((uint)(-1 < iVar4) * iVar4,0);
ppVar1 = g_phyFuns;
param_4[2] = iVar2;
(*(code *)ppVar1->rom_iq_est_disable)();
return;
}
Чатик: “да тут все просто:” (полтора кб матана). Хочешь, перепишу функцию с нормальными именами? Конечно хочу.
(Тут, надо заметить, Чатик был в курсе контекста (WiFi, регистры))
Чатик:
О, это прям вкусный кусок PHY-магии
Давай разберём, что тут происходит — на самом деле это довольно классическая процедура оценки DC offset + IQ imbalance.
Общая идея функции
dc_iq_est_test() делает примерно следующее:
-
Включает измерение IQ (
ram_iq_est_enable) -
Читает накопленные статистики из регистров
-
Нормализует их по количеству сэмплов
-
Вычисляет:
-
DC offset (I и Q)
-
мощность сигнала
-
дисбаланс I/Q
-
-
Переводит энергию в dB
-
Выключает измерение
Разбор по шагам
1. Включение измерения
…
Ну и кот прислал: Типа, улучшил.
/* WARNING: Globals starting with '_' overlap smaller symbols at the same address */
void dc_iq_est_test(undefined1 param_1,uint samples_count,int *out_DC,int *out_dB)
{
int tmp;
int I_var;
int I;
int Q;
int tot_pow_dc;
phyFuns *_phyFuns;
/* Registers:
uint32_t sum_I = _DAT_6000615c; // ΣI
uint32_t sum_Q = _DAT_60006160; // ΣQ
uint32_t sum_IQ2 = _DAT_60006164; // Σ(I² + Q²)
uint32_t sum_I2 = _DAT_60006168; // Σ(I²)
uint32_t sum_Q2 = _DAT_6000616c; // Σ(Q²) */
(*(code *)g_phyFuns->ram_iq_est_enable)(param_1,samples_count & 0xffff);
/* +1 to prevent division by zero */
tmp = (samples_count & 0xffff) + 1;
memw();
/* I_avg = sum(I) / N_samples */
I = (_DAT_6000615c >> 6) / tmp;
*out_DC = I;
memw();
/* Q_avg = sum(Q) / N_samples */
Q = (_DAT_60006160 >> 6) / tmp;
out_DC[1] = Q;
memw();
memw();
memw();
/* 0x60006164 — sum(I² + Q²)
0x60006168 - sum(I²) ?
0x6000616c - sum(Q²) ?
E[I² + Q²] - (E[I]² + E[Q]²)
total signal power without DC */
tot_pow_dc = (_DAT_60006164 / tmp) * 8 - (I * I + Q * Q);
/* I_var = E[I^2] - E[I]^2 */
I_var = (_DAT_60006168 / tmp) * 4 - I * I;
/* Real name: Q_var = E[Q^2] - E[Q]^2
reused by the compiler */
I = (_DAT_6000616c / tmp) * 4 - Q * Q;
tmp = (*(code *)g_phyFuns->rom_linear_to_db)((uint)(-1 < tot_pow_dc) * tot_pow_dc,0);
/* Total signal power */
*out_dB = tmp;
/* RSSI-like ? */
out_DC[2] = tmp + 8 >> 4;
tmp = (*(code *)g_phyFuns->rom_linear_to_db)((uint)(-1 < I_var) * I_var,0);
_phyFuns = g_phyFuns;
/* I_var dB */
out_dB[1] = tmp;
tmp = (*(code *)_phyFuns->rom_linear_to_db)((uint)(-1 < I) * I,0);
_phyFuns = g_phyFuns;
/* Q_var dB */
out_dB[2] = tmp;
(*(code *)_phyFuns->rom_iq_est_disable)();
return;
}

