1
0
Fork 0
mirror of https://github.com/EdgeTX/edgetx.git synced 2025-07-23 16:25:12 +03:00
edgetx/radio/src/sdcard.cpp
Bertrand Songis c8f77fceec [Horus] SD Storage started. UI continued.
+ Some boyscout work on LCD functions
2015-10-22 07:10:19 +02:00

299 lines
8.6 KiB
C++

/*
* Authors (alphabetical order)
* - Andre Bernet <bernet.andre@gmail.com>
* - Andreas Weitl
* - Bertrand Songis <bsongis@gmail.com>
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
* - Cameron Weeks <th9xer@gmail.com>
* - Erez Raviv
* - Gabriel Birkus
* - Jean-Pierre Parisy
* - Karl Szmutny
* - Michael Blandford
* - Michal Hlavinka
* - Pat Mackenzie
* - Philip Moss
* - Rob Thomson
* - Romolo Manfredini <romolo.manfredini@gmail.com>
* - Thomas Husterer
*
* opentx is based on code named
* gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
* er9x by Erez Raviv: http://code.google.com/p/er9x/,
* and the original (and ongoing) project by
* Thomas Husterer, th9x: http://code.google.com/p/th9x/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <stdint.h>
#include "diskio.h"
#include "ff.h"
#define LIST_NONE_SD_FILE 1
const char * sdCheckAndCreateDirectory(const char * path)
{
DIR archiveFolder;
FRESULT result = f_opendir(&archiveFolder, path);
if (result != FR_OK) {
if (result == FR_NO_PATH)
result = f_mkdir(path);
if (result != FR_OK)
return SDCARD_ERROR(result);
}
else {
f_closedir(&archiveFolder);
}
return NULL;
}
bool sdListFiles(const char *path, const char *extension, const uint8_t maxlen, const char *selection, uint8_t flags=0)
{
FILINFO fno;
DIR dir;
char *fn; /* This function is assuming non-Unicode cfg. */
#if _USE_LFN
TCHAR lfn[_MAX_LFN + 1];
fno.lfname = lfn;
fno.lfsize = sizeof(lfn);
#endif
#if defined(PCBTARANIS)
s_menu_offset_type = MENU_OFFSET_EXTERNAL;
#endif
static uint16_t s_last_menu_offset = 0;
#if defined(CPUARM)
static uint8_t s_last_flags;
if (selection) {
s_last_flags = flags;
memset(reusableBuffer.modelsel.menu_bss, 0, sizeof(reusableBuffer.modelsel.menu_bss));
strcpy(reusableBuffer.modelsel.menu_bss[0], path);
strcat(reusableBuffer.modelsel.menu_bss[0], "/");
strncat(reusableBuffer.modelsel.menu_bss[0], selection, maxlen);
strcat(reusableBuffer.modelsel.menu_bss[0], extension);
if (f_stat(reusableBuffer.modelsel.menu_bss[0], &fno) != FR_OK) {
selection = NULL;
}
}
else {
flags = s_last_flags;
}
#endif
if (s_menu_offset == 0) {
s_last_menu_offset = 0;
memset(reusableBuffer.modelsel.menu_bss, 0, sizeof(reusableBuffer.modelsel.menu_bss));
}
else if (s_menu_offset == s_menu_count - MENU_MAX_DISPLAY_LINES) {
s_last_menu_offset = 0xffff;
memset(reusableBuffer.modelsel.menu_bss, 0, sizeof(reusableBuffer.modelsel.menu_bss));
}
else if (s_menu_offset == s_last_menu_offset) {
// should not happen, only there because of Murphy's law
return true;
}
else if (s_menu_offset > s_last_menu_offset) {
memmove(reusableBuffer.modelsel.menu_bss[0], reusableBuffer.modelsel.menu_bss[1], (MENU_MAX_DISPLAY_LINES-1)*MENU_LINE_LENGTH);
memset(reusableBuffer.modelsel.menu_bss[MENU_MAX_DISPLAY_LINES-1], 0xff, MENU_LINE_LENGTH);
}
else {
memmove(reusableBuffer.modelsel.menu_bss[1], reusableBuffer.modelsel.menu_bss[0], (MENU_MAX_DISPLAY_LINES-1)*MENU_LINE_LENGTH);
memset(reusableBuffer.modelsel.menu_bss[0], 0, MENU_LINE_LENGTH);
}
s_menu_count = 0;
s_menu_flags = BSS;
FRESULT res = f_opendir(&dir, path); /* Open the directory */
if (res == FR_OK) {
if (flags & LIST_NONE_SD_FILE) {
s_menu_count++;
if (selection) {
s_last_menu_offset++;
}
else if (s_menu_offset==0 || s_menu_offset < s_last_menu_offset) {
char *line = reusableBuffer.modelsel.menu_bss[0];
memset(line, 0, MENU_LINE_LENGTH);
strcpy(line, "---");
s_menu[0] = line;
}
}
for (;;) {
res = f_readdir(&dir, &fno); /* Read a directory item */
if (res != FR_OK || fno.fname[0] == 0) break; /* Break on error or end of dir */
#if _USE_LFN
fn = *fno.lfname ? fno.lfname : fno.fname;
#else
fn = fno.fname;
#endif
uint8_t len = strlen(fn);
if (len < 5 || len > maxlen+4 || strcasecmp(fn+len-4, extension) || (fno.fattrib & AM_DIR)) continue;
s_menu_count++;
fn[len-4] = '\0';
if (s_menu_offset == 0) {
if (selection && strncasecmp(fn, selection, maxlen) < 0) {
s_last_menu_offset++;
}
else {
for (uint8_t i=0; i<MENU_MAX_DISPLAY_LINES; i++) {
char *line = reusableBuffer.modelsel.menu_bss[i];
if (line[0] == '\0' || strcasecmp(fn, line) < 0) {
if (i < MENU_MAX_DISPLAY_LINES-1) memmove(reusableBuffer.modelsel.menu_bss[i+1], line, sizeof(reusableBuffer.modelsel.menu_bss[i]) * (MENU_MAX_DISPLAY_LINES-1-i));
memset(line, 0, MENU_LINE_LENGTH);
strcpy(line, fn);
break;
}
}
}
for (uint8_t i=0; i<min(s_menu_count, (uint16_t)MENU_MAX_DISPLAY_LINES); i++) {
s_menu[i] = reusableBuffer.modelsel.menu_bss[i];
}
}
else if (s_last_menu_offset == 0xffff) {
for (int i=MENU_MAX_DISPLAY_LINES-1; i>=0; i--) {
char *line = reusableBuffer.modelsel.menu_bss[i];
if (line[0] == '\0' || strcasecmp(fn, line) > 0) {
if (i > 0) memmove(reusableBuffer.modelsel.menu_bss[0], reusableBuffer.modelsel.menu_bss[1], sizeof(reusableBuffer.modelsel.menu_bss[i]) * i);
memset(line, 0, MENU_LINE_LENGTH);
strcpy(line, fn);
break;
}
}
for (uint8_t i=0; i<min(s_menu_count, (uint16_t)MENU_MAX_DISPLAY_LINES); i++) {
s_menu[i] = reusableBuffer.modelsel.menu_bss[i];
}
}
else if (s_menu_offset > s_last_menu_offset) {
if (strcasecmp(fn, reusableBuffer.modelsel.menu_bss[MENU_MAX_DISPLAY_LINES-2]) > 0 && strcasecmp(fn, reusableBuffer.modelsel.menu_bss[MENU_MAX_DISPLAY_LINES-1]) < 0) {
memset(reusableBuffer.modelsel.menu_bss[MENU_MAX_DISPLAY_LINES-1], 0, MENU_LINE_LENGTH);
strcpy(reusableBuffer.modelsel.menu_bss[MENU_MAX_DISPLAY_LINES-1], fn);
}
}
else {
if (strcasecmp(fn, reusableBuffer.modelsel.menu_bss[1]) < 0 && strcasecmp(fn, reusableBuffer.modelsel.menu_bss[0]) > 0) {
memset(reusableBuffer.modelsel.menu_bss[0], 0, MENU_LINE_LENGTH);
strcpy(reusableBuffer.modelsel.menu_bss[0], fn);
}
}
}
}
if (s_menu_offset > 0)
s_last_menu_offset = s_menu_offset;
else
s_menu_offset = s_last_menu_offset;
return s_menu_count;
}
#if defined(CPUARM) && defined(SDCARD)
const char * sdCopyFile(const char * filename, const char * srcDir, const char * destDir)
{
FIL srcFile;
FIL dstFile;
char buf[256];
UINT read = sizeof(buf);
UINT written = sizeof(buf);
char path[2*CLIPBOARD_PATH_LEN+1];
char *tmp = strAppend(path, srcDir, CLIPBOARD_PATH_LEN);
*tmp++ = '/';
strAppend(tmp, filename, CLIPBOARD_PATH_LEN);
FRESULT result = f_open(&srcFile, path, FA_OPEN_EXISTING | FA_READ);
if (result != FR_OK) {
return SDCARD_ERROR(result);
}
tmp = strAppend(path, destDir, CLIPBOARD_PATH_LEN);
*tmp++ = '/';
strAppend(tmp, filename, CLIPBOARD_PATH_LEN);
result = f_open(&dstFile, path, FA_CREATE_ALWAYS | FA_WRITE);
if (result != FR_OK) {
f_close(&srcFile);
return SDCARD_ERROR(result);
}
while (result==FR_OK && read==sizeof(buf) && written==sizeof(buf)) {
result = f_read(&srcFile, buf, sizeof(buf), &read);
if (result == FR_OK) {
result = f_write(&dstFile, buf, read, &written);
}
}
f_close(&dstFile);
f_close(&srcFile);
if (result != FR_OK) {
return SDCARD_ERROR(result);
}
return NULL;
}
#endif // #if defined(PCBTARANIS)
#if !defined(SIMU) || defined(SIMU_DISKIO)
uint32_t sdGetNoSectors()
{
static DWORD noSectors = 0;
if (noSectors == 0 ) {
disk_ioctl(0, GET_SECTOR_COUNT, &noSectors);
}
return noSectors;
}
uint32_t sdGetSize()
{
return (sdGetNoSectors() * 512) / 1000000;
}
uint32_t sdGetFreeSectors()
{
DWORD nofree;
FATFS * fat;
if (f_getfree("", &nofree, &fat) != FR_OK) {
return 0;
}
return nofree * fat->csize;
}
#else // #if !defined(SIMU) || defined(SIMU_DISKIO)
uint32_t sdGetNoSectors()
{
return 0;
}
uint32_t sdGetSize()
{
return 0;
}
uint32_t sdGetFreeSectors()
{
return 10;
}
#endif // #if !defined(SIMU) || defined(SIMU_DISKIO)