Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

qf_ssi_ai_app SD card data save added auto qlsm file management #134

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
207 changes: 196 additions & 11 deletions Libraries/riff_file/src/riff_file_fatfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,15 @@
#include "ql_riff.h"
#include "riff_internal.h"
#include <string.h>
#include <stdio.h>
#include <limits.h>
#include <stdlib.h>
#include "dbg_uart.h"

#if (RIFF_AUTO_SEQUENCE_FILENAMES == 1)
void riff_delete_oldest_qlsm(void);
#endif

/* list of all known RIFF files */
static struct riff_file all_riff_files[ RIFF_MAX_FILES ];

Expand Down Expand Up @@ -132,7 +139,7 @@ int RIFF_file_write_object( struct riff_object *pObject )
size_t fileSize = f_size(pObject->pFile->pFile);
if (fileSize > RIFF_FILE_SIZE_MAX)
{
dbg_str_int("riff file size limit reached", fileSize);
//dbg_str_int("riff file size limit reached", fileSize);
uint32_t sticks, eticks;
sticks = xTaskGetTickCount();
f_close(pObject->pFile->pFile);
Expand All @@ -143,8 +150,10 @@ int RIFF_file_write_object( struct riff_object *pObject )
{
dbg_str_str("datafile", nextfilename);
}
// Now delete the oldest file
riff_delete_oldest_qlsm();
eticks = xTaskGetTickCount();
dbg_str_int("f_close + f_open took", eticks-sticks);
//dbg_str_int("f_close + f_open took", eticks-sticks);
}
#endif
/* update the actual bytes in the riff header */
Expand Down Expand Up @@ -175,11 +184,164 @@ int RIFF_file_write_object( struct riff_object *pObject )
}

#if (RIFF_AUTO_SEQUENCE_FILENAMES == 1)
#include <stdbool.h>
#define RIFF_FILE_COUNT_MAX (10)
#define RIFF_FILE_BASENAME ("data_")
/* Hold the file numbers (in sorted order) that are present on the card
* (data_<file number>.qlsm). A 0 indicates there is no file with that number
*/
static int riff_file_num_buff[RIFF_FILE_COUNT_MAX] = {0};
static int sfilenumHead = -1; // new/next file number to be created
static int sfilenumTail = -1; // oldest file number to be deleted

static bool riff_file_num_buff_init_done = false;
static int riff_file_count = 0;
static char riff_file_basename[64]= "data_";
static char riff_file_basename[64]= RIFF_FILE_BASENAME;
static char riff_file_nextname[64];
static char riff_file_oldname[64];
/* File number management */
void riff_filenum_print_buf(void)
{
char tmpb[16];
dbg_str("File numbers: ");
for (int k = 0; k < RIFF_FILE_COUNT_MAX; k++)
{
dbg_str(itoa(riff_file_num_buff[k], tmpb, 10));
dbg_str(", ");
}
dbg_str_int_noln("Head", sfilenumHead);
dbg_str_int_noln(", Tail", sfilenumTail);
dbg_str("\n");
}

/** @brief Get head and tail of file numbers
*
* riff_file_num_buff[] contains the file numbers currently on the
* SD card. Scan for a gap to identify the new filename to be created
* and the oldest file that needs to be deleted.
*
* If scan identifies following file numbers
* 001, 002, 003, 004, 005, 008, 009, 010
* then delete 008 and create 006 as in the below
* 001, 002, 003, 004, 005, 006, 009, 010
*
*/
int riff_filenum_get_head_tail(int *pfilenumTail)
{
int filenumHead, filenumTail;
filenumHead = -1;
filenumTail = -1;

for (int k = 1; k <= RIFF_FILE_COUNT_MAX; k++)
{
if (riff_file_num_buff[k-1] == 0)
{ // first break
if (riff_file_num_buff[(k%RIFF_FILE_COUNT_MAX)] == 0)
{
// we have a break
filenumHead = k; // new file name will be k
filenumTail = (k+1)%(RIFF_FILE_COUNT_MAX) + 1; // old filename to delete
}
else if (k==1)
{
filenumHead = RIFF_FILE_COUNT_MAX;
filenumTail = 2;
}
else
{ // there is an error, force a break
filenumHead = k; // new file name will be k
// delete the file (k+1)
sfilenumTail = k%(RIFF_FILE_COUNT_MAX) + 1; // delete the extra file
riff_delete_oldest_qlsm();
filenumTail = (k+1)%(RIFF_FILE_COUNT_MAX) + 1; // old filename to delete
}
break;
}
}

*pfilenumTail = filenumTail;
return filenumHead;
}

/** @brief Search a directory for to identify new file number to be created and
* oldest *.qlsm file to be deleted. The new file number is returned
* and the oldest file number is stored at the address `pfilenumTail`
*
* @param pdir directory to be searched
* @param pfilenumTail address to store the oldest file number to be deleted
*
* @return new file number to be created
*/
int riff_file_scan_qlsm_files (TCHAR *pdir, int *pfilenumTail)
{
FRESULT fr; /* Return value */
DIR dj; /* Directory object */
FILINFO fno; /* File information */
FILINFO oldest_fno;
int ifilenum, tot_count, nitems;
int filenumHead, filenumTail, filenumOffset;

if (riff_file_num_buff_init_done == false)
{
for (int k = 0; k < RIFF_FILE_COUNT_MAX; k++)
riff_file_num_buff[k] = 0;
tot_count = 0;
fr = f_findfirst(&dj, &fno, pdir, "?*.qlsm"); /* Start to search for QLSM files */

while (fr == FR_OK && fno.fname[0]) { /* Repeat while an item is found */
ifilenum = 0;
nitems = 0;
filenumOffset = strlen(riff_file_basename);
if (strncmp (fno.fname, riff_file_basename, filenumOffset) == 0)
{
nitems = sscanf(fno.fname+filenumOffset, "%d.qlsm", &ifilenum); /* scan for the file number */
}
if (nitems <= 0)
continue;
if ((ifilenum > 0) && (ifilenum <= RIFF_FILE_COUNT_MAX)) {
tot_count++;
riff_file_num_buff[ifilenum-1] = ifilenum;
}
fr = f_findnext(&dj, &fno); /* Search for next item */
}

f_closedir(&dj);
}

filenumHead = riff_filenum_get_head_tail(&filenumTail);
*pfilenumTail = filenumTail;
return filenumHead;
}

void riff_filenum_init(void)
{
sfilenumHead = riff_file_scan_qlsm_files("", &sfilenumTail);
return;
}

/** @brief Delete oldest file identified by the file number in sfilenumTail
* static variable
*/
void riff_delete_oldest_qlsm(void)
{
int filenum;

filenum = sfilenumTail;
snprintf(riff_file_oldname, sizeof(riff_file_oldname), "%s%08d.qlsm", riff_file_basename, filenum);
dbg_str_str_nonl("Deleting", riff_file_oldname);
if (f_unlink(riff_file_oldname) == FR_OK)
{
dbg_str(" Successful\n");
}
else
{
dbg_str(" Failed\n");
}
riff_file_num_buff[filenum-1] = 0;

/** @brief RIFF fileformat initialization function using the
}

/** @brief RIFF file format initialization function using the
* user provided basename and the initial file number integer
* New riff filenames will be constructed in the format
* basenameIIIIIIII.qlsm where IIIIIIII is an integer
Expand All @@ -189,24 +351,47 @@ static char riff_file_nextname[64];
*/
void riff_filename_format_init(char *basename, int ifilenum)
{
strncpy(riff_file_basename, basename, sizeof(riff_file_basename));
riff_file_count = ifilenum;
extern int riff_file_scan_qlsm_files (TCHAR *pdir, int *pfilenumTail);
if (riff_file_num_buff_init_done == true)
return;

strncpy(riff_file_basename, basename, sizeof(riff_file_basename));
riff_filenum_init();
riff_file_num_buff_init_done = true;
}

/** @brief Get a new RIFF filename for storing the sensor data
* A new filename of the format
* @param[out] newfilename pointer a char array of atleast 64 bytes
* A new filename of the format: <basename><NNNNNNNN>.qlsm where
* <basename> is the file basename specified in riff_file_basename
* and <NNNNNNNN> is the new file number
*
* @return newfilename pointer to a char array of atleast 64 bytes
*
*/
char *riff_get_newfilename(void)
{
riff_file_count++;
snprintf(riff_file_nextname, sizeof(riff_file_nextname), "%s%08d.qlsm", riff_file_basename, riff_file_count);
return riff_file_nextname;
extern int riff_file_scan_qlsm_files (TCHAR *pdir, int *pfilenumTail);

int k, filenumHead, filenumTail;
if (riff_file_num_buff_init_done == false)
riff_filename_format_init(riff_file_basename, 0);

sfilenumHead = riff_file_scan_qlsm_files("", &sfilenumTail);
riff_filenum_print_buf();
riff_file_count = sfilenumHead;
snprintf(riff_file_nextname, sizeof(riff_file_nextname), "%s%08d.qlsm", riff_file_basename, riff_file_count);
dbg_str_str_nonl("Next filename", riff_file_nextname);
riff_file_num_buff[riff_file_count-1] = riff_file_count;
dbg_str("\n");

return riff_file_nextname;
}

size_t RIFF_get_filesize(void)
{

}


#endif /* RIFF_AUTO_SEQUENCE_FILENAMES */
#endif /* USE_FATFS_APIS */
3 changes: 3 additions & 0 deletions Tasks/fs_monitor/inc/fs_monitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@

#include "Fw_global_config.h"

// Set this to 1 to print disk usage at monitor intervals
#define FS_MONITOR_ENABLE_PRINTS (1)

// Default low threshold value of available free space as a percentage of total available space
// Override in Fw_global_config.h to set a different value
#ifndef FS_MONITOR_LOW_DISK_SPACE_THRESHOLD
Expand Down
13 changes: 9 additions & 4 deletions Tasks/fs_monitor/src/fs_monitor.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
#include "dbg_uart.h"
#include "fs_monitor.h"

#include <stdio.h>

#if (USE_FATFS_APIS == 1)
#include "ff.h"
#else
Expand All @@ -48,6 +50,9 @@ __attribute__ ((weak)) void riff_low_disk_space(void)
*/
void fs_monitor_task(void *pParameter)
{
#if FS_MONITOR_ENABLE_PRINTS == 1
char buff[256];
#endif /* FS_MONITOR_ENABLE_PRINTS */
while (1)
{
vTaskDelay(1000 * pdMS_TO_TICKS(FS_MONITOR_INTERVAL));
Expand All @@ -58,10 +63,10 @@ void fs_monitor_task(void *pParameter)
totsect = (pfs->n_fatent - 2) * pfs->csize;
nsect = nclust * pfs->csize;
iperc = (nsect * 100L) / totsect ;
//dbg_str_int_noln("Free space: ", nsect/2);
//dbg_str_int_noln(" Total space: ", totsect/2);
//dbg_str_int_noln(" ", iperc);
//dbg_str("% disk space available\n");
#if FS_MONITOR_ENABLE_PRINTS == 1
snprintf(buff, 256, "%10d kB [%3d%%] free of %10d kB total\n", nsect, iperc, totsect);
dbg_str(buff);
#endif
if ( iperc <= FS_MONITOR_LOW_DISK_SPACE_THRESHOLD)
{
riff_low_disk_space();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ FS_MONITOR_SRCS:=$(wildcard $(FS_MONITOR_DIR)/*.c)
SRCS:=$(notdir $(FS_MONITOR_SRCS))
OBJS:=$(addprefix $(OUTPUT_PATH)/,$(SRCS:.c=.o))
SRC_PATH:= $(FS_MONITOR_DIR)
$(info FS_MONITOR_SRCS = ${FS_MONITOR_SRCS}, SRCS=${SRCS})

include $(COMMON_STUB)

25 changes: 24 additions & 1 deletion qf_apps/qf_ssi_ai_app/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ to use a new file each time the size reaches the limit specified in this macro.
::

/* Select the maximum file size for storing the sensor data */
#define RIFF_FILE_SIZE_MAX (1024*4*25) // 100KB
#define RIFF_FILE_SIZE_MAX (1024*4*256*1024) // 1GB

Filename conventions
~~~~~~~~~~~
Expand All @@ -119,6 +119,29 @@ source file `Fw_global_config.h <inc/Fw_global_config.h>`__.
#define USE_DCL_FILENAME_ONLY (0)


When RIFF_AUTO_SEQUENCE_FILENAMES is selected, filenames are auto sequenced
from the set of { data_00000001, data_00000002, ..., data_<RIFF_FILE_MAX_COUNT>}, where
the macro RIFF_FILE_MAX_COUNT defined `riff_file_fatfs.c <Libraries/riff_file/src/riff_file_fatfs.c>`__
is the number of files that would be managed by this application. When the
count approaches this maximum value, old files are removed a new file is
created. As an example, for RIFF_FILE_MAX_COUNT=10, if the current set of
files on the SD card are as below:

::

{ data_00000001.qlsm, data_00000002.qlsm, data_00000003.qlsm, data_00000004.qlsm, data_00000005.qlsm,
data_00000008.qlsm, data_00000009.qlsm, data_00000010.qlsm }

the applicaion would remove the file data_00000008.qlsm and create data_00000006.qlsm,
resulting in the following list of files:

::

{ data_00000001.qlsm, data_00000002.qlsm, data_00000003.qlsm, data_00000004.qlsm, data_00000005.qlsm,
data_00000006.qlsm, data_00000009.qlsm, data_00000010.qlsm }



1. Verify that the following macros is set for saving data to SD card

To save recognition results to the SD card, enable the macro S3AI_FIRMWARE_DATASAVE in
Expand Down
6 changes: 3 additions & 3 deletions qf_apps/qf_ssi_ai_app/inc/app_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@
/*######################## DATA CAPTURE METHOD ################################*/


#define S3AI_FIRMWARE_LIVESTREAM 0 /* Enable livestream via SSI Interface (supports sensor or recognition) */
#define S3AI_FIRMWARE_DATASAVE 1 /* Enable SD card for collection (supports sensor and recognition) */
#define S3AI_FIRMWARE_LIVESTREAM 1 /* Enable livestream via SSI Interface (supports sensor or recognition) */
#define S3AI_FIRMWARE_DATASAVE 0 /* Enable SD card for collection (supports sensor and recognition) */



Expand Down Expand Up @@ -103,4 +103,4 @@ typedef struct st_fw_global_config
#error "Enable only one of S3AI_FIRMWARE_IS_COLLECTION and S3AI_FIRMWARE_IS_RECOGNITION for S3AI_FIRMWARE_LIVESTREAM"
#endif

#endif
#endif
18 changes: 17 additions & 1 deletion qf_apps/qf_ssi_ai_app/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,23 @@ int main(void)
((SSI_SENSOR_SELECT_AUDIO == 1) && (SENSOR_AUDIO_LIVESTREAM_ENABLED == 1)) )
StartSimpleStreamingInterfaceTask();
#endif
xTaskSet_uSecCount(1546300800ULL * 1000ULL * 1000ULL); // start at 2019-01-01 00:00:00 UTC time
// set current date and time
struct tm curtim;
char currtimeStr[32] = "2021-07-15 00:00:00";
sscanf(currtimeStr, "%d-%d-%d %d:%d:%d",
&curtim.tm_year, &curtim.tm_mon, &curtim.tm_mday,
&curtim.tm_hour, &curtim.tm_min, &curtim.tm_sec);
curtim.tm_year -= 1900;
curtim.tm_mon--;
snprintf(currtimeStr, 32, "%04d-%02d-%02d %02d:%02d:%02d ",
curtim.tm_year+1900, curtim.tm_mon+1, curtim.tm_mday,
curtim.tm_hour, curtim.tm_min, curtim.tm_sec);
dbg_str(currtimeStr);

uint32_t unixTime = 1546300800UL;
unixTime = mktime(&curtim);
ql_sys_settime(unixTime);
xTaskSet_uSecCount((uint64_t)unixTime * 1000ULL * 1000ULL); // start at 2019-01-01 00:00:00 UTC time

#if (S3AI_FIRMWARE_DATASAVE == 1)
start_fs_monitor_task();
Expand Down