kamilsss655/utils/main.cpp
2024-01-07 13:44:32 +01:00

455 lines
10 KiB
C++

/* Copyright 2023 OneOfEleven
* https://github.com/DualTachyon
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <vector>
// ************************************************************************
// create a front end gain table for the firmware
// <9:8> = LNA Gain Short
// 3 = 0dB < original value
// 2 = -24dB // was -11
// 1 = -30dB // was -16
// 0 = -33dB // was -19
//
// <7:5> = LNA Gain
// 7 = 0dB
// 6 = -2dB
// 5 = -4dB
// 4 = -6dB
// 3 = -9dB
// 2 = -14dB < original value
// 1 = -19dB
// 0 = -24dB
//
// <4:3> = MIXER Gain
// 3 = 0dB < original value
// 2 = -3dB
// 1 = -6dB
// 0 = -8dB
//
// <2:0> = PGA Gain
// 7 = 0dB
// 6 = -3dB < original value
// 5 = -6dB
// 4 = -9dB
// 3 = -15dB
// 2 = -21dB
// 1 = -27dB
// 0 = -33dB
typedef struct
{
uint8_t lna_short;
uint8_t lna;
uint8_t mixer;
uint8_t pga;
int16_t lna_short_dB;
int16_t lna_dB;
int16_t mixer_dB;
int16_t pga_dB;
int16_t sum_dB;
} t_gain_table;
void create_gain_table(const char *filename)
{
std::vector <t_gain_table> gain_table;
if (filename == NULL)
return;
// front end register dB values
// const int16_t lna_short_dB[4] = { (-19), (-16), (-11), (0)}; // was
const int16_t lna_short_dB[4] = { (-33), (-30), (-24), (0)}; // corrected
const int16_t lna_dB[8] = { (-24), (-19), (-14), (-9), (-6), (-4), (-2), (0)};
const int16_t mixer_dB[4] = { (-8), (-6), (-3), (0)};
const int16_t pga_dB[8] = { (-33), (-27), (-21), (-15), (-9), (-6), (-3), (0)};
const uint8_t orig_lna_short = 3;
const uint8_t orig_lna = 2;
const uint8_t orig_mixer = 3;
const uint8_t orig_pga = 6;
const int16_t orig_gain_dB =
lna_short_dB[orig_lna_short] +
lna_dB[orig_lna] +
mixer_dB[orig_mixer] +
pga_dB[orig_pga];
#if 1
// full table
const uint8_t lna_short_min = 0; // 0
const uint8_t lna_min = 0; // 0
const uint8_t mixer_min = 0; // 0
const uint8_t pga_min = 0; // 0
const uint8_t lna_short_max = 3; // 3
const uint8_t lna_max = 7; // 5
const uint8_t mixer_max = 3; // 3
const uint8_t pga_max = 7; // 7
#else
// just one register changes
const uint8_t lna_short_min = 0;
const uint8_t lna_min = 2;
const uint8_t mixer_min = 3;
const uint8_t pga_min = 6;
const uint8_t lna_short_max = 3;
const uint8_t lna_max = 2;
const uint8_t mixer_max = 3;
const uint8_t pga_max = 6;
#endif
uint8_t lna_short = lna_short_min;
uint8_t lna = lna_min;
uint8_t mixer = mixer_min;
uint8_t pga = pga_min;
unsigned int original_index = 0;
while (true)
{
t_gain_table entry;
entry.lna_short = lna_short;
entry.lna = lna;
entry.mixer = mixer;
entry.pga = pga;
entry.lna_short_dB = lna_short_dB[lna_short];
entry.lna_dB = lna_dB[lna];
entry.mixer_dB = mixer_dB[mixer];
entry.pga_dB = pga_dB[pga];
entry.sum_dB = lna_short_dB[lna_short] + lna_dB[lna] + mixer_dB[mixer] + pga_dB[pga];
if (entry.sum_dB != orig_gain_dB)
gain_table.push_back(entry);
else
if (lna_short == orig_lna_short && lna == orig_lna && mixer == orig_mixer && pga == orig_pga)
gain_table.push_back(entry);
if (++pga <= pga_max)
continue;
pga = pga_min;
if (++mixer <= mixer_max)
continue;
mixer = mixer_min;
if (++lna <= lna_max)
continue;
lna = lna_min;
if (++lna_short <= lna_short_max)
continue;
// lna_short = lna_short_min;
break;
}
// sort the table according top the sum dB
for (unsigned int i = 0; i < (gain_table.size() - 1); i++)
{
t_gain_table entry1 = gain_table[i];
for (unsigned int k = i + 1; k < gain_table.size(); k++)
{
t_gain_table entry2 = gain_table[k];
if (entry2.sum_dB < entry1.sum_dB)
{ // swap
const t_gain_table entry = entry1;
entry1 = entry2;
entry2 = entry;
gain_table[i] = entry1;
gain_table[k] = entry2;
}
}
}
{ // remove sum_dB duplicates
unsigned int i = 0;
while (i < gain_table.size())
{
const t_gain_table entry1 = gain_table[i++];
if (entry1.lna_short == orig_lna_short &&
entry1.lna == orig_lna &&
entry1.mixer == orig_mixer &&
entry1.pga == orig_pga)
continue; // leave the original inplace
while (i < gain_table.size())
{
const t_gain_table entry2 = gain_table[i];
if (entry2.lna_short == orig_lna_short &&
entry2.lna == orig_lna &&
entry2.mixer == orig_mixer &&
entry2.pga == orig_pga)
break; // leave the original inplace
if (entry2.sum_dB != entry1.sum_dB)
break;
gain_table.erase(gain_table.begin() + i, gain_table.begin() + i + 1);
}
}
}
// find the index for the original Quansheng register settings
for (int i = (int)gain_table.size() - 1; i >= 0; i--)
{
const t_gain_table entry = gain_table[i];
if (entry.sum_dB != orig_gain_dB)
continue;
if (entry.lna_short != orig_lna_short ||
entry.lna != orig_lna ||
entry.mixer != orig_mixer ||
entry.pga != orig_pga)
continue;
original_index = i;
break;
}
// ***************************
// save the table to a file
FILE *file = fopen(filename, "w");
if (file == NULL)
return;
fprintf(file, "\n");
fprintf(file, "\tstatic const t_am_fix_gain_table am_fix_gain_table[] =\n");
fprintf(file, "\t{\n");
#if 0
fprintf(file, "\t\t{.lna_short = 3, .lna = 2, .mixer = 3, .pga = 6}, // 0 0dB -14dB 0dB -3dB .. -17dB original\n\n");
for (unsigned int i = 0; i < gain_table.size(); i++)
{
char s[1024];
const t_gain_table entry = gain_table[i];
sprintf(s, "\t\t{%u, %u, %u, %u}, // %3u .. %3ddB %3ddB %2ddB %3ddB .. %3ddB",
entry.lna_short,
entry.lna,
entry.mixer,
entry.pga,
1 + i,
entry.lna_short_dB,
entry.lna_dB,
entry.mixer_dB,
entry.pga_dB,
entry.sum_dB);
if (i == original_index)
strcat(s, " original");
fprintf(file, "%s\n", s);
}
#else
{
//BK4819_WriteRegister(BK4819_REG_13, ((uint16_t)gains.lna_short << 8) | ((uint16_t)gains.lna << 5) | ((uint16_t)gains.mixer << 3) | ((uint16_t)gains.pga << 0));
uint16_t reg_val;
int16_t sum_dB;
reg_val = ((uint16_t)orig_lna_short << 8) | ((uint16_t)orig_lna << 5) | ((uint16_t)orig_mixer << 3) | ((uint16_t)orig_pga << 0);
sum_dB = lna_short_dB[orig_lna_short] + lna_dB[orig_lna] + mixer_dB[orig_mixer] + pga_dB[orig_pga];
fprintf(file, "\t\t{0x%04X, %-3d}, // 0 .. %u %u %u %u .. 0dB -14dB 0dB -3dB .. -17dB original\n\n",
reg_val,
sum_dB,
orig_lna_short,
orig_lna,
orig_mixer,
orig_pga);
for (unsigned int i = 0; i < gain_table.size(); i++)
{
char s[1024];
const t_gain_table entry = gain_table[i];
reg_val = ((uint16_t)entry.lna_short << 8) | ((uint16_t)entry.lna << 5) | ((uint16_t)entry.mixer << 3) | ((uint16_t)entry.pga << 0);
sum_dB = lna_short_dB[entry.lna_short] + lna_dB[entry.lna] + mixer_dB[entry.mixer] + pga_dB[entry.pga];
sprintf(s, "\t\t{0x%04X, %-3d}, // %3u .. %u %u %u %u .. %3ddB %3ddB %2ddB %3ddB .. %3ddB",
reg_val,
sum_dB,
1 + i,
entry.lna_short,
entry.lna,
entry.mixer,
entry.pga,
entry.lna_short_dB,
entry.lna_dB,
entry.mixer_dB,
entry.pga_dB,
entry.sum_dB);
if (i == original_index)
strcat(s, " original");
fprintf(file, "%s\n", s);
}
}
#endif
fprintf(file, "\t};\n\n");
fprintf(file, "\tstatic const unsigned int original_index = %u;\n", 1 + original_index);
fclose(file);
}
// ************************************************************************
// "rotate_font()" has nothing to do with this program at all, I just needed
// to write a bit of code to rotate some fonts I've drawn
void rotate_font(const char *filename1, const char *filename2)
{
std::vector <uint8_t> data;
if (filename1 == NULL || filename2 == NULL)
return;
// ****************************
// load the file
FILE *file = fopen(filename1, "rb");
if (file == NULL)
return;
if (fseek(file, 0, SEEK_END) != 0)
{
fclose(file);
return;
}
const size_t file_size = ftell(file);
if (file_size <= 0)
{
fclose(file);
return;
}
if (fseek(file, 0, SEEK_SET) != 0)
{
fclose(file);
return;
}
data.resize(file_size);
const size_t bytes_loaded = fread(&data[0], 1, file_size, file);
fclose(file);
if (bytes_loaded != file_size)
return;
// ***************************
// rotate the font 90-deg clockwise
for (unsigned int i = 0; i <= (data.size() - 8); i += 8)
{
uint8_t c1[8];
uint8_t c2[8];
memcpy(c1, &data[i], 8);
memset(c2, 0, 8);
for (unsigned int k = 0; k < 8; k++)
{
uint8_t b = c1[k];
for (unsigned int m = 0; m < 8; m++)
{
if (b & 0x80)
c2[m] |= 1u << k;
b <<= 1;
}
}
memcpy(&data[i], c2, 8);
}
// ***************************
// save the file
file = fopen(filename2, "wt");
if (file == NULL)
return;
fprintf(file, "const uint8_t gFontSmall[95][7] =\n");
fprintf(file, "{\n");
for (unsigned int i = 0; i < data.size(); )
{
char s[1024];
memset(s, 0, sizeof(s));
// for (unsigned int k = 0; k < 8 && i < data.size(); k++)
for (unsigned int k = 0; k < 7 && i < data.size(); k++)
{
char s2[16];
sprintf(s2, "0x%02X", data[i++]);
if (k == 0)
strcat(s, "\t{");
// if (k < 7)
if (k < 6)
{
strcat(s, s2);
strcat(s, ", ");
}
else
{
strcat(s, s2);
strcat(s, "},\n");
}
}
i++;
fprintf(file, "%s", s);
}
fprintf(file, "};\n");
fclose(file);
// ***************************
}
#pragma argsused
int main(int argc, char* argv[])
{
create_gain_table("gain_table.c");
rotate_font("uv-k5_small.bin", "uv-k5_small.c");
rotate_font("uv-k5_small_bold.bin", "uv-k5_small_bold.c");
return 0;
}