mirror of
https://github.com/ClusterM/fdskey.git
synced 2025-12-18 01:16:09 +01:00
417 lines
11 KiB
C
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, §or_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;
|
|
}
|
|
|