Files
fdskey/FdsKey/Core/Src/servicemenu.c
2023-08-08 00:09:13 +04:00

417 lines
11 KiB
C

#include <string.h>
#include <stdio.h>
#include "servicemenu.h"
#include "main.h"
#include "settings.h"
#include "oled.h"
#include "buttons.h"
#include "commit.h"
#include "splash.h"
#include "confirm.h"
#include "sdcard.h"
#include "blupdater.h"
FDSKEY_SERVICE_SETTINGS fdskey_service_settings;
FDSKEY_HARDWARE_VERSION fdskey_hw_version;
static uint64_t fat_free;
static uint64_t fat_total;
void service_settings_load()
{
memcpy(&fdskey_hw_version, (void*)HARDWARE_VERSION_FLASH_OFFSET, sizeof(fdskey_hw_version));
memcpy(&fdskey_service_settings, (void*)SERVICE_SETTINGS_FLASH_OFFSET, sizeof(fdskey_service_settings));
fdskey_service_settings.sig[sizeof(fdskey_service_settings.sig) - 1] = 0;
if (strcmp(fdskey_service_settings.sig, SERVICE_SETTINGS_SIGNATURE))
{
// config is empty, load defaults
memset(&fdskey_service_settings, 0, sizeof(fdskey_service_settings));
strcpy(fdskey_service_settings.sig, SERVICE_SETTINGS_SIGNATURE);
fdskey_service_settings.oled_controller = OLED_CONTROLLER_SSD1306;
}
}
HAL_StatusTypeDef service_settings_save()
{
HAL_StatusTypeDef r;
FLASH_EraseInitTypeDef erase_init_struct;
uint32_t sector_error = 0;
int i;
uint64_t buffer[sizeof(fdskey_service_settings) / sizeof(uint64_t) + 1];
// unlock flash
r = HAL_FLASH_Unlock();
if (r != HAL_OK) return r;
// erase flash page
erase_init_struct.TypeErase = FLASH_TYPEERASE_PAGES;
erase_init_struct.Banks = ((SERVICE_SETTINGS_FLASH_OFFSET - 0x08000000) / FLASH_BANK_SIZE == 0) ? FLASH_BANK_1 : FLASH_BANK_2;
erase_init_struct.Page = ((SERVICE_SETTINGS_FLASH_OFFSET - 0x08000000) / FLASH_PAGE_SIZE) % FLASH_PAGE_NB;
erase_init_struct.NbPages = 1;
r = HAL_FLASHEx_Erase(&erase_init_struct, &sector_error);
if (r != HAL_OK) return r;
// writing
memcpy(buffer, &fdskey_service_settings, sizeof(fdskey_service_settings));
for (i = 0; i < sizeof(buffer); i += sizeof(uint64_t))
{
r = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, SERVICE_SETTINGS_FLASH_OFFSET + i, buffer[i / sizeof(uint64_t)]);
if (r != HAL_OK)
return r;
}
return HAL_FLASH_Lock();
}
static void uint64_to_str(uint64_t d, char* str)
{
int len = 0, p;
uint64_t tmp;
for (tmp = d; tmp; tmp /= 10)
len++;
if (!len) len++;
len += (len - 1) / 3;
str[len] = 0;
for (p = 1; len; d /= 10, len--, p++)
{
if (p % 4 == 0)
{
str[len - 1] = '\'';
len--;
p++;
}
str[len - 1] = '0' + (d % 10);
}
}
static void draw_item(uint8_t line, SETTING_ID item, uint8_t is_selected)
{
char *parameter_name;
char value_v[32] = "";
char *value = value_v;
int l;
SD_CID cid;
switch((int)item)
{
case SERVICE_SETTING_SD_MANUFACTURER_ID:
case SERVICE_SETTING_SD_OEM_ID:
case SERVICE_SETTING_SD_PROD_NAME:
case SERVICE_SETTING_SD_PROD_REV:
case SERVICE_SETTING_SD_PROD_SN:
case SERVICE_SETTING_SD_PROD_MANUFACT_YEAR:
case SERVICE_SETTING_SD_PROD_MANUFACT_MONTH:
memset(&cid, 0, sizeof(cid));
SD_read_CID(&cid);
break;
default:
break;
}
switch ((int)item)
{
case SERVICE_SETTING_OLED_CONTROLLER:
parameter_name = "OLED controller";
sprintf(value_v, "<%s>", fdskey_service_settings.oled_controller == OLED_CONTROLLER_SSD1306 ? "SSD1306" : "SH1106");
break;
case SERVICE_SETTING_VERSION:
parameter_name = "FW version";
#ifndef INTERIM
if (!FDSKEY_VERION_SUFFIX)
sprintf(value_v, "v%d.%d", FDSKEY_VERION_MAJOR, FDSKEY_VERION_MINOR);
else
sprintf(value_v, "v%d.%d%c", FDSKEY_VERION_MAJOR, FDSKEY_VERION_MINOR, FDSKEY_VERION_SUFFIX);
#else
value = "interim";
#endif
break;
case SERVICE_SETTING_COMMIT:
parameter_name = "FW commit";
value = COMMIT;
break;
case SERVICE_SETTING_BUILD_DATE:
parameter_name = "FW build date";
value = BUILD_DATE;
break;
case SERVICE_SETTING_BUILD_TIME:
parameter_name = "FW build time";
value = BUILD_TIME;
break;
case SERVICE_SETTING_BL_COMMIT:
parameter_name = "BL commit";
value = fdskey_hw_version.bootloader_commit;
break;
case SERVICE_SETTING_SD_CAPACITY:
parameter_name = "SD size";
uint64_to_str(SD_read_capacity(), value_v);
break;
case SERVICE_SETTING_FAT_SIZE:
parameter_name = "FAT size";
uint64_to_str(fat_total, value_v);
break;
case SERVICE_SETTING_FAT_FREE:
parameter_name = "FAT free";
uint64_to_str(fat_free, value_v);
break;
case SERVICE_SETTING_FILE_SYSTEM:
parameter_name = "File system";
switch (USERFatFs.fs_type)
{
case FS_FAT12:
value = "FAT12";
break;
case FS_FAT16:
value = "FAT16";
break;
case FS_FAT32:
value = "FAT32";
break;
case FS_EXFAT:
value = "exFAT";
break;
default:
value = "Unknown";
break;
}
break; case SERVICE_SETTING_SD_SPI_SPEED:
parameter_name = "SD SPI speed";
switch (SD_get_spi_speed())
{
case SPI_BAUDRATEPRESCALER_2:
value = "/2";
break;
case SPI_BAUDRATEPRESCALER_4:
value = "/4";
break;
case SPI_BAUDRATEPRESCALER_8:
value = "/8";
break;
case SPI_BAUDRATEPRESCALER_16:
value = "/16";
break;
default:
value = "unknown";
break;
}
break;
case SERVICE_SETTING_SD_MANUFACTURER_ID:
parameter_name = "SD manufacturer ID";
sprintf(value_v, "%02X", cid.ManufacturerID);
break;
case SERVICE_SETTING_SD_OEM_ID:
parameter_name = "SD OEM ID";
value = cid.OEM_AppliID;
break;
case SERVICE_SETTING_SD_PROD_NAME:
parameter_name = "SD product name";
value = cid.ProdName;
break;
case SERVICE_SETTING_SD_PROD_REV:
parameter_name = "SD product rev.";
sprintf(value_v, "%d", cid.ProdRev);
break;
case SERVICE_SETTING_SD_PROD_SN:
parameter_name = "SD product s/n";
sprintf(value_v, "%08X", (unsigned int)cid.ProdSN);
break;
case SERVICE_SETTING_SD_PROD_MANUFACT_YEAR:
parameter_name = "SD manuf. year";
sprintf(value_v, "%d", cid.ManufactYear);
break;
case SERVICE_SETTING_SD_PROD_MANUFACT_MONTH:
parameter_name = "SD manuf. month";
sprintf(value_v, "%d", cid.ManufactMonth);
break;
case SERVICE_SETTING_SD_FORMAT:
parameter_name = "[ Format SD card ]";
break;
case SERVICE_SETTING_BL_UPDATE:
parameter_name = "[ Update bootloader ]";
break;
default:
parameter_name = "[ Save and return ]";
break;
}
oled_draw_rectangle(0, line * 8, OLED_WIDTH - 1, line * 8 + 7, 1, 0);
if (is_selected)
oled_draw_image(&IMAGE_CURSOR, 0, line * 8, 0, 0);
oled_draw_text(&SETTINGS_FONT, parameter_name,
IMAGE_CURSOR.width, line * 8,
0, 0);
l = oled_get_text_length(&SETTINGS_FONT, value);
oled_draw_text(&SETTINGS_FONT, value,
OLED_WIDTH - l - 1, line * 8,
0, 0);
oled_update(line, line);
}
static void draw_all(int line, int selection)
{
int i;
for (i = 0; i < 4; i++)
draw_item((oled_get_line() + OLED_HEIGHT) / 8 + i, line + i, line + i == selection);
oled_switch_to_invisible();
}
static void update_free_space()
{
FRESULT fr;
FATFS *fs;
DWORD fat_free_clust = 0;
fr = f_getfree("", &fat_free_clust, &fs);
if (fr != FR_OK)
{
fat_total = fat_free = 0;
} else {
fat_total = (uint64_t)(fs->n_fatent - 2) * fs->csize * FF_MIN_SS;
fat_free = (uint64_t)fat_free_clust * fs->csize * FF_MIN_SS;
}
}
void service_menu()
{
int line = 0;
int selection = 0;
int i;
show_message("Entering into\nthe service menu", 0);
HAL_Delay(1500);
update_free_space();
draw_all(line, selection);
while (1)
{
if (button_up_newpress() && selection > 0)
{
draw_item(oled_get_line() / 8 + selection - line, selection, 0);
selection--;
draw_item(oled_get_line() / 8 + selection - line, selection, 1);
}
if (button_down_newpress() && selection + 1 < SERVICE_SETTINGS_ITEM_COUNT + 1)
{
draw_item(oled_get_line() / 8 + selection - line, selection, 0);
selection++;
draw_item(oled_get_line() / 8 + selection - line, selection, 1);
}
if (button_left_newpress() || button_right_newpress())
{
switch (selection)
{
case SERVICE_SETTING_OLED_CONTROLLER:
if (fdskey_service_settings.oled_controller == OLED_CONTROLLER_SSD1306)
fdskey_service_settings.oled_controller = OLED_CONTROLLER_SH1106;
else
fdskey_service_settings.oled_controller = OLED_CONTROLLER_SSD1306;
// reinit display
oled_init(fdskey_service_settings.oled_controller, fdskey_settings.lefty_mode ? 0 : 1, fdskey_settings.invert_screen, 0xFF * fdskey_settings.brightness / SETTINGS_BRIGHTNESS_MAX);
draw_all(line, selection);
break;
case SERVICE_SETTING_VERSION:
case SERVICE_SETTING_COMMIT:
case SERVICE_SETTING_BUILD_DATE:
case SERVICE_SETTING_BUILD_TIME:
case SERVICE_SETTING_BL_COMMIT:
case SERVICE_SETTING_SD_SPI_SPEED:
case SERVICE_SETTING_SD_CAPACITY:
case SERVICE_SETTING_FAT_SIZE:
case SERVICE_SETTING_FAT_FREE:
case SERVICE_SETTING_FILE_SYSTEM:
case SERVICE_SETTING_SD_MANUFACTURER_ID:
case SERVICE_SETTING_SD_OEM_ID:
case SERVICE_SETTING_SD_PROD_NAME:
case SERVICE_SETTING_SD_PROD_REV:
case SERVICE_SETTING_SD_PROD_SN:
case SERVICE_SETTING_SD_PROD_MANUFACT_YEAR:
case SERVICE_SETTING_SD_PROD_MANUFACT_MONTH:
break;
case SERVICE_SETTING_SD_FORMAT:
sd_format();
draw_all(line, selection);
break;
case SERVICE_SETTING_BL_UPDATE:
update_bootloader();
draw_all(line, selection);
break;
default:
service_settings_save();
return;
}
draw_item(oled_get_line() / 8 + selection - line, selection, 1);
}
while (selection < line && line)
{
line--;
for (i = 0; i < 8; i++) {
oled_set_line(oled_get_line() - 1);
HAL_Delay(5);
}
}
while (selection > line + 3)
{
line++;
for (i = 0; i < 8; i++) {
oled_set_line(oled_get_line() + 1);
HAL_Delay(5);
}
}
button_check_screen_off();
HAL_Delay(1);
}
}
uint8_t sd_format()
{
FRESULT fr;
uint8_t work[32 * 1024];
// Confirm
if (!confirm("Format SD card?"))
return 0;
show_message("WARNING!\nAll data will be erased!", 1);
if (!confirm("Are you sure?"))
return 0;
show_message("Formatting...", 0);
// unmount
f_mount(0, "", 1);
fr = f_mkfs("", 0, work, sizeof(work));
if (fr != FR_OK)
{
show_error_screen_fr(fr, 0);
fr = f_mount(&USERFatFs, "", 1);
show_error_screen_fr(fr, 1);
}
// get new file system
fr = f_mount(&USERFatFs, "", 1);
if (fr != FR_OK)
show_error_screen_fr(fr, 1);
// update free space info
update_free_space();
// show new file system
switch (USERFatFs.fs_type)
{
case FS_FAT12:
show_message("Done!\nFormatted to FAT12", 1);
break;
case FS_FAT16:
show_message("Done!\nFormatted to FAT16", 1);
break;
case FS_FAT32:
show_message("Done!\nFormatted to FAT32", 1);
break;
case FS_EXFAT:
show_message("Done!\nFormatted to exFAT", 1);
break;
default:
show_message("Done!", 1);
break;
}
f_setlabel(DISK_LABEL);
return 1;
}