From e2bce8f163a011d2eebc9b648a84c7877bd6c23a Mon Sep 17 00:00:00 2001 From: t-moe Date: Sun, 10 May 2015 01:17:58 +0200 Subject: [PATCH] Added filesystem module, tests and implementation for it in emulator. --- common/app/app.c | 3 +- common/app/screen_filetest.c | 128 ++++++++++++++++++++ common/app/screen_filetest.h | 3 + common/app/screen_main.c | 22 +++- common/filesystem/filesystem.c | 38 ++++++ common/filesystem/filesystem.h | 71 +++++++++++ common/lowlevel/ll_filesystem.h | 11 ++ discovery/src/ll_filesystem.c | 38 ++++++ emulator/emulated/.hidden | 0 emulator/emulated/dir1/subfile1.txt | 0 emulator/emulated/emtpy.txt | 0 emulator/emulated/test.txt | 1 + emulator/emulated/test2.txt | 1 + emulator/qt/emulatorqt.pro | 6 +- emulator/qt/ll_filesystem.cpp | 181 ++++++++++++++++++++++++++++ 15 files changed, 498 insertions(+), 5 deletions(-) create mode 100644 common/app/screen_filetest.c create mode 100644 common/app/screen_filetest.h create mode 100644 common/filesystem/filesystem.c create mode 100644 common/lowlevel/ll_filesystem.h create mode 100644 discovery/src/ll_filesystem.c create mode 100644 emulator/emulated/.hidden create mode 100644 emulator/emulated/dir1/subfile1.txt create mode 100644 emulator/emulated/emtpy.txt create mode 100644 emulator/emulated/test.txt create mode 100644 emulator/emulated/test2.txt create mode 100644 emulator/qt/ll_filesystem.cpp diff --git a/common/app/app.c b/common/app/app.c index cb7bcf9..6f6ee19 100644 --- a/common/app/app.c +++ b/common/app/app.c @@ -3,12 +3,13 @@ #include "system.h" #include "touch.h" #include "screen_main.h" - +#include "filesystem.h" void app_init() { system_init(); tft_init(); touch_init(); + filesystem_init(); gui_screen_navigate(get_screen_main()); } diff --git a/common/app/screen_filetest.c b/common/app/screen_filetest.c new file mode 100644 index 0000000..b381c48 --- /dev/null +++ b/common/app/screen_filetest.c @@ -0,0 +1,128 @@ +#include "screen_filetest.h" +#include "button.h" +#include "tft.h" +#include "filesystem.h" +#include + + +static BUTTON_STRUCT b_back; + + +static void b_back_cb(void* button) { + gui_screen_back(); +} + +static void enter(void* screen) { + tft_clear(HEX(0xBABECD)); + + //Back button + b_back.base.x1=10; //Start X of Button + b_back.base.y1=200; //Start Y of Button + b_back.base.x2=AUTO; //b_back.base.x1+160; //Auto Calculate X2 with String Width + b_back.base.y2=AUTO; //Auto Calculate Y2 with String Height + b_back.txtcolor=WHITE; //Set foreground color + b_back.bgcolor=HEX(0xAE1010); //Set background color (Don't take 255 or 0 on at least one channel, to make shadows possible) + b_back.font=0; //Select Font + b_back.text="Back"; //Set Text (For formatted strings take sprintf) + b_back.callback=b_back_cb; //Call b_back_cb as Callback + gui_button_add(&b_back); //Register Button (and run the callback from now on) + + +/* + //tft test + tft_draw_pixel(0,0,BLACK); + tft_draw_pixel(319,239,BLACK); + tft_draw_pixel(10,210,BLUE); + tft_draw_pixel(12,210,BLUE); + tft_draw_rectangle(40,100,60,235,BLUE); + tft_fill_rectangle(100,215,200,225,GREEN); + tft_draw_line(10,50,310,225,RGB(0xFF,0,0xFF)); + tft_draw_circle(10,10,100, RED); + tft_print_line(30, 130, RED, BLUE, 0, "Hallo"); +*/ + + tft_draw_line(10,30,310,30,BLACK); + tft_print_line(10,18,BLUE,TRANSPARENT,0,"Name D H RO Date Time Size"); + + int y = 33; + + DIRECTORY_STRUCT* dir = filesystem_dir_open("."); + if(dir==NULL) return; + + for(int i=0; inum_files; i++) { + FILE_STRUCT* file = &(dir->files[i]); + tft_print_formatted(10,y, + (file->fattrib&F_DIR)?GREEN:RED, + TRANSPARENT,0,"%-13s%c %c %s %02u%02u%02u %02u:%02u:%02u %u", + file->fname, + (file->fattrib&F_DIR)?'D':' ', + (file->fattrib&F_HID)?'H':' ', + (file->fattrib&F_RDO)?"R ":"RW", + file->fdate.day, + file->fdate.month, + (file->fdate.year+1980)%100, + file->ftime.hour, + file->ftime.min, + file->ftime.sec*2, + file->fsize); + y+=14; + } + + + y+=14; + + FILE_HANDLE* file = filesystem_file_open("test.txt"); + if(file==NULL) { + tft_print_line(10,y,BLUE,TRANSPARENT,0,"Could not open test.txt"); + } else { + char buf [30]; + int size = (file->fsize>30)?29:file->fsize-1; + FILE_STATUS st = filesystem_file_read(file,buf,size); + + if(st==F_OK) { + buf[file->fpos]='\0'; + tft_print_formatted(10,y,BLUE,TRANSPARENT,0,"test.txt contains \"%s\"",buf); + long num = strtol(&(buf[file->fpos-4]),NULL,0); + num++; + + y+=14; + + if(filesystem_file_seek(file,file->fpos-4)!=F_OK) { + tft_print_formatted(10,y,BLUE,TRANSPARENT,0,"Could not seek to %d",file->fpos-4); + } else { + sprintf(buf,"%04d",num); + if(filesystem_file_write(file,buf,4) != F_OK) { + tft_print_formatted(10,y,BLUE,TRANSPARENT,0,"Could not write new number %d",num); + } else { + tft_print_formatted(10,y,BLUE,TRANSPARENT,0,"New number written %d",num); + } + } + } else { + tft_print_line(10,y,BLUE,TRANSPARENT,0,"Could not read from test.txt"); + } + + } + filesystem_file_close(file); + +} + +static void leave(void* screen) { + gui_button_remove(&b_back); +} + +static void update(void* screen) { +} + + +static SCREEN_STRUCT screen = { + enter, + leave, + update +}; + + +SCREEN_STRUCT* get_screen_filetest() { + return &screen; +} + + diff --git a/common/app/screen_filetest.h b/common/app/screen_filetest.h new file mode 100644 index 0000000..8897b10 --- /dev/null +++ b/common/app/screen_filetest.h @@ -0,0 +1,3 @@ +#include "screen.h" + +SCREEN_STRUCT* get_screen_filetest(); diff --git a/common/app/screen_main.c b/common/app/screen_main.c index b22dde4..6baebfe 100644 --- a/common/app/screen_main.c +++ b/common/app/screen_main.c @@ -1,17 +1,22 @@ #include "screen_main.h" #include "screen_guitest.h" #include "screen_pixytest.h" +#include "screen_filetest.h" #include "button.h" #include "tft.h" BUTTON_STRUCT b_guitest; BUTTON_STRUCT b_pixytest; - +BUTTON_STRUCT b_filetest; static void b_guitest_cb(void* button) { gui_screen_navigate(get_screen_guitest()); } +static void b_filetest_cb(void* button) { + gui_screen_navigate(get_screen_filetest()); +} + static void b_pixytest_cb(void* button) { gui_screen_navigate(get_screen_pixytest()); } @@ -33,7 +38,7 @@ static void enter(void* screen) { gui_button_add(&b_guitest); //Register Button (and run the callback from now on) //button to reach pixy test - b_pixytest.base.x1=200; //Start X of Button + b_pixytest.base.x1=150; //Start X of Button b_pixytest.base.y1=45; //Start Y of Button b_pixytest.base.x2=AUTO; //b_pixytest.base.x1+160; //Auto Calculate X2 with String Width b_pixytest.base.y2=AUTO; //Auto Calculate Y2 with String Height @@ -44,6 +49,18 @@ static void enter(void* screen) { b_pixytest.callback=b_pixytest_cb; //Call b_pixytest_cb as Callback gui_button_add(&b_pixytest); //Register Button (and run the callback from now on) + //button to reach filesystem test + b_filetest.base.x1=240; //Start X of Button + b_filetest.base.y1=45; //Start Y of Button + b_filetest.base.x2=AUTO; //b_filetest.base.x1+160; //Auto Calculate X2 with String Width + b_filetest.base.y2=AUTO; //Auto Calculate Y2 with String Height + b_filetest.txtcolor=WHITE; //Set foreground color + b_filetest.bgcolor=HEX(0x501EA0); //Set background color (Don't take 255 or 0 on at least one channel, to make shadows possible) + b_filetest.font=0; //Select Font + b_filetest.text="File Test"; //Set Text (For formatted strings take sprintf) + b_filetest.callback=b_filetest_cb; //Call b_filetest_cb as Callback + gui_button_add(&b_filetest); //Register Button (and run the callback from now on) + } @@ -51,6 +68,7 @@ static void enter(void* screen) { static void leave(void* screen) { gui_button_remove(&b_guitest); gui_button_remove(&b_pixytest); + gui_button_remove(&b_filetest); } static void update(void* screen) { diff --git a/common/filesystem/filesystem.c b/common/filesystem/filesystem.c new file mode 100644 index 0000000..1cd803f --- /dev/null +++ b/common/filesystem/filesystem.c @@ -0,0 +1,38 @@ +#include "filesystem.h" +#include "ll_filesystem.h" + +bool filesystem_init() { + return ll_filesystem_init(); +} + +DIRECTORY_STRUCT* filesystem_dir_open(const char* path) { + return ll_filesystem_dir_open(path); +} + +void filesystem_dir_close(DIRECTORY_STRUCT* dir) { + filesystem_dir_close(dir); +} + +FILE_HANDLE* filesystem_file_open(const char* filename) { + return ll_filesystem_file_open(filename); +} + +void filesystem_file_close(FILE_HANDLE* handle) { + ll_filesystem_file_close(handle); +} + +FILE_STATUS filesystem_file_seek(FILE_HANDLE* handle, uint32_t offset) { + return ll_filesystem_file_seek(handle,offset); +} + +FILE_STATUS filesystem_file_read(FILE_HANDLE* handle, uint8_t* buf, uint32_t size) { + return ll_filesystem_file_read(handle,buf,size); +} + +FILE_STATUS filesystem_file_write(FILE_HANDLE* handle, uint8_t* buf, uint32_t size) { + return ll_filesystem_file_write(handle,buf,size); +} + + + + diff --git a/common/filesystem/filesystem.h b/common/filesystem/filesystem.h index e69de29..164d76e 100644 --- a/common/filesystem/filesystem.h +++ b/common/filesystem/filesystem.h @@ -0,0 +1,71 @@ +#ifndef FILESYSTEM_H +#define FILESYSTEM_H + +#include +#include + +typedef enum { + F_DIR=1, + F_RDO=2, + F_HID=4, + F_SYS=8, + F_ARC=16 +} FILE_ATTRIBUTES; + + +typedef struct { + unsigned year : 7; //year from 1980 (0..127) + unsigned month: 4; //month (1..12) + unsigned day: 5; //day (1..31) +} FILE_DATE_STRUCT; + + +typedef struct { + unsigned hour : 5; //hour (0..23) + unsigned min: 6; //minute (0..59 + unsigned sec: 5; //second/2 (0..29) +} FILE_TIME_STRUCT; + + +typedef struct { + uint32_t fsize; /* File size */ + FILE_DATE_STRUCT fdate; /* Last modified date */ + FILE_TIME_STRUCT ftime; /* Last modified time */ + uint8_t fattrib; /* Attribute */ + char* fname; /* File name */ +} FILE_STRUCT; + +typedef struct { + const char* path; + uint16_t num_files; + FILE_STRUCT* files; +} DIRECTORY_STRUCT; + +typedef struct { + const char* fname; + uint32_t fpos; + uint32_t fsize; +} FILE_HANDLE; + +typedef enum { + F_OK, + F_EOF, + F_EACCESS, + F_INVALIDPARAM, + F_DISKERROR +} FILE_STATUS; + + +bool filesystem_init(); + +DIRECTORY_STRUCT* filesystem_dir_open(const char* path); +void filesystem_dir_close(DIRECTORY_STRUCT* dir); +FILE_HANDLE* filesystem_file_open(const char* filename); +void filesystem_file_close(FILE_HANDLE* handle); +FILE_STATUS filesystem_file_seek(FILE_HANDLE* handle, uint32_t offset); +FILE_STATUS filesystem_file_read(FILE_HANDLE* handle, uint8_t* buf, uint32_t size); +FILE_STATUS filesystem_file_write(FILE_HANDLE* handle, uint8_t* buf, uint32_t size); + + +#endif /* FILESYSTEM_H */ + diff --git a/common/lowlevel/ll_filesystem.h b/common/lowlevel/ll_filesystem.h new file mode 100644 index 0000000..6190598 --- /dev/null +++ b/common/lowlevel/ll_filesystem.h @@ -0,0 +1,11 @@ +#include "filesystem.h" + +bool ll_filesystem_init(); + +DIRECTORY_STRUCT* ll_filesystem_dir_open(const char* path); +void ll_filesystem_dir_close(DIRECTORY_STRUCT* dir); +FILE_HANDLE* ll_filesystem_file_open(const char* filename); +void ll_filesystem_file_close(FILE_HANDLE* handle); +FILE_STATUS ll_filesystem_file_seek(FILE_HANDLE* handle, uint32_t offset); +FILE_STATUS ll_filesystem_file_read(FILE_HANDLE* handle, uint8_t* buf, uint32_t size); +FILE_STATUS ll_filesystem_file_write(FILE_HANDLE* handle, uint8_t* buf, uint32_t size); diff --git a/discovery/src/ll_filesystem.c b/discovery/src/ll_filesystem.c new file mode 100644 index 0000000..fda6515 --- /dev/null +++ b/discovery/src/ll_filesystem.c @@ -0,0 +1,38 @@ +#include "ll_filesystem.h" +#include + +bool ll_filesystem_init() { + return false; +} + +DIRECTORY_STRUCT* ll_filesystem_dir_open(const char* path) { + return NULL; +} + +void ll_filesystem_dir_close(DIRECTORY_STRUCT* dir) { + + +} + +FILE_HANDLE* ll_filesystem_file_open(const char* filename) { + return NULL; +} + +void ll_filesystem_file_close(FILE_HANDLE* handle) { + +} + +FILE_STATUS ll_filesystem_file_seek(FILE_HANDLE* handle, uint32_t offset) { + return F_DISKERROR; +} + +FILE_STATUS ll_filesystem_file_read(FILE_HANDLE* handle, uint8_t* buf, uint32_t size) { + return F_DISKERROR; +} + +FILE_STATUS ll_filesystem_file_write(FILE_HANDLE* handle, uint8_t* buf, uint32_t size) { + return F_DISKERROR; +} + + + diff --git a/emulator/emulated/.hidden b/emulator/emulated/.hidden new file mode 100644 index 0000000..e69de29 diff --git a/emulator/emulated/dir1/subfile1.txt b/emulator/emulated/dir1/subfile1.txt new file mode 100644 index 0000000..e69de29 diff --git a/emulator/emulated/emtpy.txt b/emulator/emulated/emtpy.txt new file mode 100644 index 0000000..e69de29 diff --git a/emulator/emulated/test.txt b/emulator/emulated/test.txt new file mode 100644 index 0000000..9bbe689 --- /dev/null +++ b/emulator/emulated/test.txt @@ -0,0 +1 @@ +Hallo Test 1241 diff --git a/emulator/emulated/test2.txt b/emulator/emulated/test2.txt new file mode 100644 index 0000000..aaaa72b --- /dev/null +++ b/emulator/emulated/test2.txt @@ -0,0 +1 @@ +hallo welt diff --git a/emulator/qt/emulatorqt.pro b/emulator/qt/emulatorqt.pro index 47b672c..c5ea145 100644 --- a/emulator/qt/emulatorqt.pro +++ b/emulator/qt/emulatorqt.pro @@ -15,14 +15,16 @@ SOURCES += \ main.cpp \ ll_tft.cpp \ ll_system.cpp \ - ll_touch.cpp + ll_touch.cpp \ + ll_filesystem.cpp HEADERS += \ mainwindow.h \ INCLUDEPATH+= ../../common/lowlevel/ \ ../../common/touch/ \ - ../../common/tft/ + ../../common/tft/ \ + ../../common/filesystem FORMS += \ diff --git a/emulator/qt/ll_filesystem.cpp b/emulator/qt/ll_filesystem.cpp new file mode 100644 index 0000000..a89e08d --- /dev/null +++ b/emulator/qt/ll_filesystem.cpp @@ -0,0 +1,181 @@ +extern "C" { + #include "ll_filesystem.h" +} +#include +#include +#include +#include +#include + +QDir rootdir ("./emulated"); + +bool ll_filesystem_init() { + if(!rootdir.exists()) { + qWarning() << "Filesystem can not be emulated because the 'emulated' folder does not exist"; + return false; + } + return true; +} + +DIRECTORY_STRUCT* ll_filesystem_dir_open(const char* path) { + QDir d(rootdir); + d.cd(path); + if(!d.exists()) { + return NULL; + } + + DIRECTORY_STRUCT* directory = new DIRECTORY_STRUCT(); + QFileInfoList entries = d.entryInfoList(QDir::NoDotAndDotDot|QDir::Files|QDir::Dirs|QDir::Readable|QDir::Writable|QDir::Hidden|QDir::System); + directory->path = path; + directory->num_files = entries.count(); + directory->files = new FILE_STRUCT[directory->num_files]; + + + for(int i=0; ifiles[i]); + entry->fattrib = 0; + entry->fname = new char[fi.fileName().length()+1]; + strcpy(entry->fname,fi.fileName().toStdString().c_str()); + if(fi.isDir()) { + entry->fattrib|=F_DIR; + entry->fsize = 0; + } else { + entry->fsize = fi.size(); + } + if(fi.isHidden()) { + entry->fattrib|=F_HID; + } + if(!fi.isWritable()) { + entry->fattrib|=F_RDO; + } + + QDateTime dt = fi.lastModified(); + entry->fdate.year = dt.date().year()-1980; + entry->fdate.month = dt.date().month(); + entry->fdate.day = dt.date().day(); + entry->ftime.hour = dt.time().hour(); + entry->ftime.min = dt.time().minute(); + entry->ftime.sec = dt.time().second()/2; + + } + + return directory; +} + +void ll_filesystem_dir_close(DIRECTORY_STRUCT* dir) { + if(dir!=NULL) { + for(int i=0; inum_files; i++) { + delete dir->files[i].fname; + } + delete[] dir->files; + delete dir; + } +} + + +struct QT_FILE_HANDLE : FILE_HANDLE { + QFile* file; +}; + + +FILE_HANDLE* ll_filesystem_file_open(const char* filename) { + if(!rootdir.exists()) { + return NULL; + } + QString filepath = rootdir.absoluteFilePath(filename); + QFile* f = new QFile(filepath); + if(!f->exists()) { + return NULL; + } + + if(!f->open(QFile::ReadWrite)) { + return NULL; + } + + QT_FILE_HANDLE* fh = new QT_FILE_HANDLE(); + fh->file = f; + fh->fname = filename; + fh->fpos =0; + fh->fsize = f->size(); + return fh; +} + +void ll_filesystem_file_close(FILE_HANDLE* handle) { + if(handle!=NULL) { + QT_FILE_HANDLE* fh = static_cast(handle); + if(fh->file->isOpen()) { + fh->file->close(); + } + delete fh; + } +} + +FILE_STATUS ll_filesystem_file_seek(FILE_HANDLE* handle, uint32_t offset) { + if(handle==NULL) { + return F_INVALIDPARAM; + } + QT_FILE_HANDLE* fh = static_cast(handle); + if(!fh->file->isOpen()) { + return F_DISKERROR; + } + if(offset>=fh->file->size()) { + return F_INVALIDPARAM; + } + + if(fh->file->seek(offset)) { + fh->fpos = offset; + return F_OK; + } else { + return F_DISKERROR; + } +} + +FILE_STATUS ll_filesystem_file_read(FILE_HANDLE* handle, uint8_t* buf, uint32_t size) { + if(handle==NULL || buf==NULL) { + return F_INVALIDPARAM; + } + QT_FILE_HANDLE* fh = static_cast(handle); + if(!fh->file->isOpen()) { + return F_DISKERROR; + } + if(!fh->file->isReadable()) { + return F_EACCESS; + } + qint64 bytesRead = fh->file->read((char*)buf,size); + if(bytesRead<0) { + return F_DISKERROR; + } + fh->fpos+=bytesRead; + if(bytesRead!=size) { + return F_EOF; + } else { + return F_OK; + } +} + +FILE_STATUS ll_filesystem_file_write(FILE_HANDLE* handle, uint8_t* buf, uint32_t size) { + if(handle==NULL) { + return F_INVALIDPARAM; + } + QT_FILE_HANDLE* fh = static_cast(handle); + if(!fh->file->isOpen()) { + return F_DISKERROR; + } + if(!fh->file->isWritable()) { + return F_EACCESS; + } + qint64 bytesWritten = fh->file->write((char*)buf,size); + if(bytesWritten<0) { + return F_DISKERROR; + } + fh->fpos+=bytesWritten; + if(bytesWritten!=size) { + return F_EOF; + } else { + return F_OK; + } +} + + +