diff --git a/Doxyfile b/Doxyfile index 9ff1371..2d727a1 100644 --- a/Doxyfile +++ b/Doxyfile @@ -959,13 +959,13 @@ USE_MDFILE_AS_MAINPAGE = # also VERBATIM_HEADERS is set to NO. # The default value is: NO. -SOURCE_BROWSER = NO +SOURCE_BROWSER = YES # Setting the INLINE_SOURCES tag to YES will include the body of functions, # classes and enums directly into the documentation. # The default value is: NO. -INLINE_SOURCES = NO +INLINE_SOURCES = YES # Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any # special comment blocks from generated source code fragments. Normal C, C++ and @@ -1610,7 +1610,7 @@ EXTRA_SEARCH_MAPPINGS = # If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output. # The default value is: YES. -GENERATE_LATEX = NO +GENERATE_LATEX = YES # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of @@ -1751,7 +1751,7 @@ LATEX_HIDE_INDICES = NO # The default value is: NO. # This tag requires that the tag GENERATE_LATEX is set to YES. -LATEX_SOURCE_CODE = NO +LATEX_SOURCE_CODE = YES # The LATEX_BIB_STYLE tag can be used to specify the style to use for the # bibliography, e.g. plainnat, or ieeetr. See diff --git a/README.md b/README.md index 24d2b6d..3eba51d 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,8 @@ A Project with the Pixy cam and the STM32F4 Discovery. The project can also be r ## Documentation Take a look at our [docu.pdf](./doc/docu.pdf) (German) +Also make sure to check out the [doxygen documentation](http://t-moe.github.io/discoverpixy/) for the common folder. + ## Folder structure * *common*: device independent code and the "Application" itself diff --git a/common/app/app.c b/common/app/app.c index 21da23b..61e81fe 100644 --- a/common/app/app.c +++ b/common/app/app.c @@ -1,3 +1,32 @@ +/************************************************************************************************************************************** +* Project: discoverpixy +* Website: https://github.com/t-moe/discoverpixy +* Authors: Aaron Schmocker, Timo Lang +* Institution: BFH Bern University of Applied Sciences +* File: common/app/app.c +* +* Version History: +* Date Autor Email SHA Changes +* 2015-04-03 timolang@gmail.com 51089aa Refactored Project Structure for use with emulator +* 2015-04-03 timolang@gmail.com 1f2af9f Added more tft functions to common and emulator. Fixed eventloop. +* 2015-04-03 timolang@gmail.com cab8609 Integrated pixy into emulator. Pixy is no longer in the common/libs folder but in emulator/libs and discovery/libs +* 2015-04-03 timolang@gmail.com 1aa9194 Fixed Drawing of rects in Emulator. Got frames from pixy to emulator. Slooooow. +* 2015-04-25 timolang@gmail.com 416883c Pixy&Usb work with the new folder structure now. +* 2015-04-25 timolang@gmail.com 3d1e4b2 Simplified code a bit. Emulator does not work stable when replugging pixy. +* 2015-04-25 timolang@gmail.com 0858b0d Fixed some bugs when receiving large data. +* 2015-04-27 timolang@gmail.com 259d446 Added touch support to emulator. Implemented basic touch function. +* 2015-04-27 aaron@duckpond.ch aed90ef Drawcircle added (emulator) +* 2015-04-27 timolang@gmail.com e249fb2 Added font support +* 2015-04-27 timolang@gmail.com 7c9eabc Added button support. +* 2015-04-27 timolang@gmail.com b300ac5 Added Checkbox support +* 2015-04-27 timolang@gmail.com cf72baa Introduced a Screen (sub) module and divided app into multiple screens. +* 2015-05-10 timolang@gmail.com e2bce8f Added filesystem module, tests and implementation for it in emulator. +* 2015-05-12 aaron@duckpond.ch aec62d4 Added datasheets, updated touchsupport. +* 2015-05-28 aaron@duckpond.ch 5bda699 implemented functions to get x and y coordinates and a test function +* 2015-05-29 aaron@duckpond.ch 7d2d1a1 Implemented basic sampling and averaging of touch coordinates using timer7 +* +**************************************************************************************************************************************/ + #include "app.h" #include "tft.h" #include "system.h" @@ -5,20 +34,20 @@ #include "screen_main.h" #include "filesystem.h" -void app_init() { - system_init(); - tft_init(); - touch_init(); - filesystem_init(); +void app_init() +{ + system_init(); + tft_init(); + touch_init(); + filesystem_init(); - gui_screen_navigate(get_screen_main()); + gui_screen_navigate(get_screen_main()); } //app event loop -void app_process() { - - system_process(); //Let the system handle it's pending events - gui_screen_update(); //update the currently active screen +void app_process() +{ + + system_process(); //Let the system handle it's pending events + gui_screen_update(); //update the currently active screen } - - diff --git a/common/app/app.h b/common/app/app.h index 71d43b8..70053c3 100644 --- a/common/app/app.h +++ b/common/app/app.h @@ -1,6 +1,28 @@ +/************************************************************************************************************************************** +* Project: discoverpixy +* Website: https://github.com/t-moe/discoverpixy +* Authors: Aaron Schmocker, Timo Lang +* Institution: BFH Bern University of Applied Sciences +* File: common/app/app.h +* +* Version History: +* Date Autor Email SHA Changes +* 2015-04-03 timolang@gmail.com 51089aa Refactored Project Structure for use with emulator +* 2015-05-10 timolang@gmail.com 21edc56 Added doxyfile (doxygen) for the common folder. Started with doxygen comments for app and tft module. +* 2015-05-11 timolang@gmail.com 08d9fe0 More work on doxygen module structure +* 2015-06-08 timolang@gmail.com 73db8b5 Added doxygen mainpage comment in app.h +* +**************************************************************************************************************************************/ + #ifndef APP_H #define APP_H +/*! + \mainpage discoverpixy Doxygen Documentation + Welcome to the code-documentation for all common (and plattformindependent) code. \n + A good point to start is probably the Modules page. + */ + /** * @defgroup app Application * The App Module contains the effective, platform independent application. diff --git a/common/app/pixy_control.c b/common/app/pixy_control.c index c30418d..41b32ba 100644 --- a/common/app/pixy_control.c +++ b/common/app/pixy_control.c @@ -1,3 +1,21 @@ +/************************************************************************************************************************************** +* Project: discoverpixy +* Website: https://github.com/t-moe/discoverpixy +* Authors: Aaron Schmocker, Timo Lang +* Institution: BFH Bern University of Applied Sciences +* File: common/app/pixy_control.c +* +* Version History: +* Date Autor Email SHA Changes +* 2015-06-02 aaron@duckpond.ch e018a75 Implemented basic pi and pid controller +* 2015-06-06 aaron@duckpond.ch 8c264c2 Comment refactoring, updated PID values +* 2015-06-06 aaron@duckpond.ch a04cda9 Refactured comments and implemented a bugfix for the PID controller +* 2015-06-07 aaron@duckpond.ch 802d3df Fixed pid controller and refactored code +* 2015-06-07 aaron@duckpond.ch 3d98ca9 Minor changes +* 2015-06-07 timolang@gmail.com c87220d Renamed pixy_helper to pixy_frame. Updated docu of appliaction. added doxygen comments to pixy_{frame,control}.h +* +**************************************************************************************************************************************/ + /* * pixy_control.c * @@ -16,10 +34,11 @@ #include // PID tuning factors -#define REG_PID_KP (0.5f) +#define REG_PID_KP (0.41f) #define REG_PID_KI (0.001f) -#define REG_PID_KD (0.001f) -#define REG_PID_TA (0.01f) +#define REG_PID_KD (0.00025f) +#define REG_PID_TA (0.001f) +#define REG_PID_YKOR (0.3f) // PID controller implementatoin for the y-axis @@ -35,7 +54,7 @@ int16_t pixy_PID_Y(int16_t x, int16_t w) //----PID-control------------------------------------------------------------------------- esum = esum + e; // add e to the current sum - y += REG_PID_KP * e; // add the proportional part to the output + y += (REG_PID_KP + REG_PID_YKOR) * e; // add the proportional part to the output y += REG_PID_KI * REG_PID_TA * esum; // add the integral part to the output y += REG_PID_KD * (e - eold) / REG_PID_TA; // add the differential part to the output //---------------------------------------------------------------------------------------- diff --git a/common/app/pixy_control.h b/common/app/pixy_control.h index 708cac4..083a8ed 100644 --- a/common/app/pixy_control.h +++ b/common/app/pixy_control.h @@ -1,3 +1,20 @@ +/************************************************************************************************************************************** +* Project: discoverpixy +* Website: https://github.com/t-moe/discoverpixy +* Authors: Aaron Schmocker, Timo Lang +* Institution: BFH Bern University of Applied Sciences +* File: common/app/pixy_control.h +* +* Version History: +* Date Autor Email SHA Changes +* 2015-06-02 aaron@duckpond.ch e018a75 Implemented basic pi and pid controller +* 2015-06-06 aaron@duckpond.ch 8c264c2 Comment refactoring, updated PID values +* 2015-06-06 aaron@duckpond.ch a04cda9 Refactured comments and implemented a bugfix for the PID controller +* 2015-06-07 aaron@duckpond.ch 802d3df Fixed pid controller and refactored code +* 2015-06-07 timolang@gmail.com c87220d Renamed pixy_helper to pixy_frame. Updated docu of appliaction. added doxygen comments to pixy_{frame,control}.h +* +**************************************************************************************************************************************/ + #ifndef PIXY_CONTROL_H_ #define PIXY_CONTROL_H_ diff --git a/common/app/pixy_frame.c b/common/app/pixy_frame.c index 8c7dc0d..ea82f59 100644 --- a/common/app/pixy_frame.c +++ b/common/app/pixy_frame.c @@ -1,3 +1,16 @@ +/************************************************************************************************************************************** +* Project: discoverpixy +* Website: https://github.com/t-moe/discoverpixy +* Authors: Aaron Schmocker, Timo Lang +* Institution: BFH Bern University of Applied Sciences +* File: common/app/pixy_frame.c +* +* Version History: +* Date Autor Email SHA Changes +* 2015-06-07 timolang@gmail.com c87220d Renamed pixy_helper to pixy_frame. Updated docu of appliaction. added doxygen comments to pixy_{frame,control}.h +* +**************************************************************************************************************************************/ + #include "pixy_frame.h" #include "pixy.h" #include "tft.h" @@ -5,118 +18,113 @@ -static int renderBA81(uint16_t xpos, uint16_t ypos, uint16_t width, uint16_t height, uint32_t frameLen, uint8_t *frame); -static int saveBA81(FILE_HANDLE* handle, uint16_t width, uint16_t height, uint32_t frameLen, uint8_t *frame); +static int renderBA81(uint16_t xpos, uint16_t ypos, uint16_t width, uint16_t height, uint32_t frameLen, uint8_t* frame); +static int saveBA81(FILE_HANDLE* handle, uint16_t width, uint16_t height, uint32_t frameLen, uint8_t* frame); -int pixy_render_full_frame(uint16_t x, uint16_t y) { - return pixy_render_cropped_frame(x,y,0,0,320,200); -} - - -int pixy_render_cropped_frame(uint16_t x, uint16_t y, uint16_t xoffset, uint16_t yoffset, uint16_t width, uint16_t height) { - uint8_t* videodata; - int32_t response; - int32_t fourccc; - int8_t renderflags; - uint16_t xwidth; - uint16_t ywidth; - uint32_t size; - - - int return_value = pixy_command("cam_getFrame", // String id for remote procedure - INT8(0x21), // mode - INT16(xoffset), // xoffset - INT16(yoffset), // yoffset - INT16(width), // width - INT16(height), // height - END_OUT_ARGS, // separator - &response, // pointer to mem address for return value - &fourccc, - &renderflags, - &xwidth, - &ywidth, - &size, - &videodata, // pointer to mem address for returned frame - END_IN_ARGS); - - if(return_value==0) { - return_value = renderBA81(x,y,xwidth,ywidth,size,videodata); - } - - return return_value; -} - -int pixy_save_full_frame(FILE_HANDLE* handle) { - return pixy_save_cropped_frame(handle,0,0,320,200); -} - -int pixy_save_cropped_frame(FILE_HANDLE* handle, uint16_t xoffset, uint16_t yoffset, uint16_t width, uint16_t height) { - uint8_t* videodata; - int32_t response; - int32_t fourccc; - int8_t renderflags; - uint16_t xwidth; - uint16_t ywidth; - uint32_t size; - - - int return_value = pixy_command("cam_getFrame", // String id for remote procedure - INT8(0x21), // mode - INT16(xoffset), // xoffset - INT16(yoffset), // yoffset - INT16(width), // width - INT16(height), // height - END_OUT_ARGS, // separator - &response, // pointer to mem address for return value - &fourccc, - &renderflags, - &xwidth, - &ywidth, - &size, - &videodata, // pointer to mem address for returned frame - END_IN_ARGS); - - if(return_value==0) { - return_value = saveBA81(handle,xwidth,ywidth,size,videodata); - } - - return return_value; -} - - - - - -static void interpolateBayer(uint16_t width, uint16_t x, uint16_t y, uint8_t *pixel, uint8_t* r, uint8_t* g, uint8_t* b) +int pixy_render_full_frame(uint16_t x, uint16_t y) { - if (y&1) - { - if (x&1) - { - *r = *pixel; - *g = (*(pixel-1)+*(pixel+1)+*(pixel+width)+*(pixel-width))>>2; - *b = (*(pixel-width-1)+*(pixel-width+1)+*(pixel+width-1)+*(pixel+width+1))>>2; - } - else - { - *r = (*(pixel-1)+*(pixel+1))>>1; - *g = *pixel; - *b = (*(pixel-width)+*(pixel+width))>>1; - } + return pixy_render_cropped_frame(x, y, 0, 0, 320, 200); +} + + +int pixy_render_cropped_frame(uint16_t x, uint16_t y, uint16_t xoffset, uint16_t yoffset, uint16_t width, uint16_t height) +{ + uint8_t* videodata; + int32_t response; + int32_t fourccc; + int8_t renderflags; + uint16_t xwidth; + uint16_t ywidth; + uint32_t size; + + + int return_value = pixy_command("cam_getFrame", // String id for remote procedure + INT8(0x21), // mode + INT16(xoffset), // xoffset + INT16(yoffset), // yoffset + INT16(width), // width + INT16(height), // height + END_OUT_ARGS, // separator + &response, // pointer to mem address for return value + &fourccc, + &renderflags, + &xwidth, + &ywidth, + &size, + &videodata, // pointer to mem address for returned frame + END_IN_ARGS); + + if (return_value == 0) { + return_value = renderBA81(x, y, xwidth, ywidth, size, videodata); } - else - { - if (x&1) - { - *r = (*(pixel-width)+*(pixel+width))>>1; + + return return_value; +} + +int pixy_save_full_frame(FILE_HANDLE* handle) +{ + return pixy_save_cropped_frame(handle, 0, 0, 320, 200); +} + +int pixy_save_cropped_frame(FILE_HANDLE* handle, uint16_t xoffset, uint16_t yoffset, uint16_t width, uint16_t height) +{ + uint8_t* videodata; + int32_t response; + int32_t fourccc; + int8_t renderflags; + uint16_t xwidth; + uint16_t ywidth; + uint32_t size; + + + int return_value = pixy_command("cam_getFrame", // String id for remote procedure + INT8(0x21), // mode + INT16(xoffset), // xoffset + INT16(yoffset), // yoffset + INT16(width), // width + INT16(height), // height + END_OUT_ARGS, // separator + &response, // pointer to mem address for return value + &fourccc, + &renderflags, + &xwidth, + &ywidth, + &size, + &videodata, // pointer to mem address for returned frame + END_IN_ARGS); + + if (return_value == 0) { + return_value = saveBA81(handle, xwidth, ywidth, size, videodata); + } + + return return_value; +} + + + + + +static void interpolateBayer(uint16_t width, uint16_t x, uint16_t y, uint8_t* pixel, uint8_t* r, uint8_t* g, uint8_t* b) +{ + if (y & 1) { + if (x & 1) { + *r = *pixel; + *g = (*(pixel - 1) + * (pixel + 1) + * (pixel + width) + * (pixel - width)) >> 2; + *b = (*(pixel - width - 1) + * (pixel - width + 1) + * (pixel + width - 1) + * (pixel + width + 1)) >> 2; + } else { + *r = (*(pixel - 1) + * (pixel + 1)) >> 1; *g = *pixel; - *b = (*(pixel-1)+*(pixel+1))>>1; + *b = (*(pixel - width) + * (pixel + width)) >> 1; } - else - { - *r = (*(pixel-width-1)+*(pixel-width+1)+*(pixel+width-1)+*(pixel+width+1))>>2; - *g = (*(pixel-1)+*(pixel+1)+*(pixel+width)+*(pixel-width))>>2; + } else { + if (x & 1) { + *r = (*(pixel - width) + * (pixel + width)) >> 1; + *g = *pixel; + *b = (*(pixel - 1) + * (pixel + 1)) >> 1; + } else { + *r = (*(pixel - width - 1) + * (pixel - width + 1) + * (pixel + width - 1) + * (pixel + width + 1)) >> 2; + *g = (*(pixel - 1) + * (pixel + 1) + * (pixel + width) + * (pixel - width)) >> 2; *b = *pixel; } } @@ -128,7 +136,7 @@ static void interpolateBayer(uint16_t width, uint16_t x, uint16_t y, uint8_t *pi -static int renderBA81(uint16_t xpos, uint16_t ypos, uint16_t width, uint16_t height, uint32_t frameLen, uint8_t *frame) +static int renderBA81(uint16_t xpos, uint16_t ypos, uint16_t width, uint16_t height, uint32_t frameLen, uint8_t* frame) { uint16_t x, y; uint8_t r, g, b; @@ -140,102 +148,101 @@ static int renderBA81(uint16_t xpos, uint16_t ypos, uint16_t width, uint16_t hei // don't render top and bottom rows, and left and rightmost columns because of color // interpolation //uint32_t decodedimage[(width-2)*(height-2)]; - uint16_t* decodedimage = malloc(sizeof(uint16_t)*(width-2)*(height-2)); + uint16_t* decodedimage = malloc(sizeof(uint16_t) * (width - 2) * (height - 2)); - if(decodedimage==NULL) { //not enough free space to decode image in memory + if (decodedimage == NULL) { //not enough free space to decode image in memory //decode & render image pixel by pixel - for (y=1; yfpos; - uint32_t row_size_padded = ((width-2)*3 + 3) & (~3); //row size aligned to 4 bytes - uint32_t fpos_end = fpos + row_size_padded* (height-2); + uint32_t row_size_padded = ((width - 2) * 3 + 3) & (~3); //row size aligned to 4 bytes + uint32_t fpos_end = fpos + row_size_padded * (height - 2); // skip first line frame += width; // don't render top and bottom rows, and left and rightmost columns because of color - // interpolation + // interpolation - for (y=1; ynum_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; - } + DIRECTORY_STRUCT* dir = filesystem_dir_open("."); - filesystem_dir_close(dir); + if (dir == NULL) { + return; + } - y+=14; + for (int i = 0; i < dir->num_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; + } - 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_dir_close(dir); - } - filesystem_file_close(file); + y += 14; - image_test(); + 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); + + image_test(); } -static void leave(void* screen) { - gui_button_remove(&b_back); +static void leave(void* screen) +{ + gui_button_remove(&b_back); } -static void update(void* screen) { +static void update(void* screen) +{ } static SCREEN_STRUCT screen = { - enter, - leave, - update + enter, + leave, + update }; -SCREEN_STRUCT* get_screen_filetest() { - return &screen; +SCREEN_STRUCT* get_screen_filetest() +{ + return &screen; } -static void image_test() { +static void image_test() +{ - if(!tft_draw_bitmap_file_unscaled(250,170,"cpu.bmp")) { - tft_print_line(10,180,BLUE,TRANSPARENT,0,"Could not open cpu.bmp"); - } - tft_draw_rectangle(250-1,170-1,250-1+64,170-1+64,BLACK); + if (!tft_draw_bitmap_file_unscaled(250, 170, "cpu.bmp")) { + tft_print_line(10, 180, BLUE, TRANSPARENT, 0, "Could not open cpu.bmp"); + } + + tft_draw_rectangle(250 - 1, 170 - 1, 250 - 1 + 64, 170 - 1 + 64, BLACK); } diff --git a/common/app/screen_filetest.h b/common/app/screen_filetest.h index eec7dbf..6829d2a 100644 --- a/common/app/screen_filetest.h +++ b/common/app/screen_filetest.h @@ -1,3 +1,18 @@ +/************************************************************************************************************************************** +* Project: discoverpixy +* Website: https://github.com/t-moe/discoverpixy +* Authors: Aaron Schmocker, Timo Lang +* Institution: BFH Bern University of Applied Sciences +* File: common/app/screen_filetest.h +* +* Version History: +* Date Autor Email SHA Changes +* 2015-05-10 timolang@gmail.com e2bce8f Added filesystem module, tests and implementation for it in emulator. +* 2015-05-10 timolang@gmail.com 21edc56 Added doxyfile (doxygen) for the common folder. Started with doxygen comments for app and tft module. +* 2015-05-15 timolang@gmail.com 9a16865 Added doxgen comments to filesyste, checkbox, numupdown and screen module. And some minor changes to the other modules. +* +**************************************************************************************************************************************/ + #include "screen.h" /** diff --git a/common/app/screen_guitest.c b/common/app/screen_guitest.c index 282636e..eeee1d9 100644 --- a/common/app/screen_guitest.c +++ b/common/app/screen_guitest.c @@ -1,3 +1,21 @@ +/************************************************************************************************************************************** +* Project: discoverpixy +* Website: https://github.com/t-moe/discoverpixy +* Authors: Aaron Schmocker, Timo Lang +* Institution: BFH Bern University of Applied Sciences +* File: common/app/screen_guitest.c +* +* Version History: +* Date Autor Email SHA Changes +* 2015-04-27 timolang@gmail.com cf72baa Introduced a Screen (sub) module and divided app into multiple screens. +* 2015-04-30 timolang@gmail.com 76ea9d8 Added num up down support. +* 2015-05-09 timolang@gmail.com c652b6b Improved Emulator Gui +* 2015-05-29 aaron@duckpond.ch 7d2d1a1 Implemented basic sampling and averaging of touch coordinates using timer7 +* 2015-06-01 timolang@gmail.com eb573bc Finalized calibration. Fixed a bug in screen module. +* 2015-06-02 timolang@gmail.com da34bce Fixed all printf related problems on discovery using workarounds and newlib nano-instead of newlib +* +**************************************************************************************************************************************/ + #include "screen_guitest.h" #include "button.h" #include "tft.h" @@ -9,127 +27,138 @@ static TOUCH_AREA_STRUCT a_area; static CHECKBOX_STRUCT c_cbox; static NUMUPDOWN_STRUCT n_updown; -static void checkboxCB(void *checkbox, bool checked) { - printf("Checkbox %s\n",(checked?"checked":"unchecked")); +static void checkboxCB(void* checkbox, bool checked) +{ + printf("Checkbox %s\n", (checked ? "checked" : "unchecked")); } -static void b_back_cb(void* button) { - gui_screen_back(); +static void b_back_cb(void* button) +{ + gui_screen_back(); } -static void n_updown_cb(void* numupdown, int16_t value) { - printf("New NumUpDown Value %d\n",value); +static void n_updown_cb(void* numupdown, int16_t value) +{ + printf("New NumUpDown Value %d\n", value); } -static void touchCB(void* touchArea, TOUCH_ACTION triggeredAction) { - - switch(triggeredAction) { - case PEN_DOWN: - printf("action PEN_DOWN\n"); - break; - case PEN_UP: - printf("action PEN_UP\n"); - break; - case PEN_MOVE: - printf("action PEN_MOVE\n"); - break; - case PEN_ENTER: - printf("action PEN_ENTER\n"); - break; - case PEN_LEAVE: - printf("action PEN_LEAVE\n"); - break; - default: - printf("action %s\n",triggeredAction); - break; - } +static void touchCB(void* touchArea, TOUCH_ACTION triggeredAction) +{ + + switch (triggeredAction) { + case PEN_DOWN: + printf("action PEN_DOWN\n"); + break; + + case PEN_UP: + printf("action PEN_UP\n"); + break; + + case PEN_MOVE: + printf("action PEN_MOVE\n"); + break; + + case PEN_ENTER: + printf("action PEN_ENTER\n"); + break; + + case PEN_LEAVE: + printf("action PEN_LEAVE\n"); + break; + + default: + printf("action %s\n", triggeredAction); + break; + } } -static void enter(void* screen) { - tft_clear(HEX(0xA6FD9A)); - - //Back button - b_back.base.x1=10; //Start X of Button - b_back.base.y1=10; //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) +static void enter(void* screen) +{ + tft_clear(HEX(0xA6FD9A)); + + //Back button + b_back.base.x1 = 10; //Start X of Button + b_back.base.y1 = 10; //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"); - - - - //Area test - a_area.hookedActions = PEN_DOWN | PEN_UP | PEN_MOVE | PEN_ENTER | PEN_LEAVE; - a_area.x1 = 130; - a_area.y1 = 30; - a_area.x2 = 200; - a_area.y2 = 60; - a_area.callback = touchCB; - touch_register_area(&a_area); + //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"); - //Checkbox test - c_cbox.base.x1=220; - c_cbox.base.y1=45; - c_cbox.base.x2=c_cbox.base.x1+16; - c_cbox.base.y2=c_cbox.base.y1+16; - c_cbox.fgcolor = GREEN; - c_cbox.checked = true; - c_cbox.callback = checkboxCB; - gui_checkbox_add(&c_cbox); - + //Area test + a_area.hookedActions = PEN_DOWN | PEN_UP | PEN_MOVE | PEN_ENTER | PEN_LEAVE; + a_area.x1 = 130; + a_area.y1 = 30; + a_area.x2 = 200; + a_area.y2 = 60; + a_area.callback = touchCB; + touch_register_area(&a_area); - //Num up down test - n_updown.x=200; - n_updown.y=120; - n_updown.fgcolor=RED; - n_updown.value = -3; - n_updown.max=11; - n_updown.min =-5; - n_updown.callback=n_updown_cb; - gui_numupdown_add(&n_updown); + + + //Checkbox test + c_cbox.base.x1 = 220; + c_cbox.base.y1 = 45; + c_cbox.base.x2 = c_cbox.base.x1 + 16; + c_cbox.base.y2 = c_cbox.base.y1 + 16; + c_cbox.fgcolor = GREEN; + c_cbox.checked = true; + c_cbox.callback = checkboxCB; + gui_checkbox_add(&c_cbox); + + + //Num up down test + n_updown.x = 200; + n_updown.y = 120; + n_updown.fgcolor = RED; + n_updown.value = -3; + n_updown.max = 11; + n_updown.min = -5; + n_updown.callback = n_updown_cb; + gui_numupdown_add(&n_updown); } -static void leave(void* screen) { - gui_button_remove(&b_back); - gui_checkbox_remove(&c_cbox); - gui_numupdown_remove(&n_updown); - touch_unregister_area(&a_area); +static void leave(void* screen) +{ + gui_button_remove(&b_back); + gui_checkbox_remove(&c_cbox); + gui_numupdown_remove(&n_updown); + touch_unregister_area(&a_area); } -static void update(void* screen) { - //gui_button_redraw(&b_back); //only needed if button is overdrawn by others - //.... for the other elements as well +static void update(void* screen) +{ + //gui_button_redraw(&b_back); //only needed if button is overdrawn by others + //.... for the other elements as well } static SCREEN_STRUCT screen = { - enter, - leave, - update + enter, + leave, + update }; -SCREEN_STRUCT* get_screen_guitest() { - return &screen; +SCREEN_STRUCT* get_screen_guitest() +{ + return &screen; } - - diff --git a/common/app/screen_guitest.h b/common/app/screen_guitest.h index 82a9d49..8a06117 100644 --- a/common/app/screen_guitest.h +++ b/common/app/screen_guitest.h @@ -1,3 +1,18 @@ +/************************************************************************************************************************************** +* Project: discoverpixy +* Website: https://github.com/t-moe/discoverpixy +* Authors: Aaron Schmocker, Timo Lang +* Institution: BFH Bern University of Applied Sciences +* File: common/app/screen_guitest.h +* +* Version History: +* Date Autor Email SHA Changes +* 2015-04-27 timolang@gmail.com cf72baa Introduced a Screen (sub) module and divided app into multiple screens. +* 2015-05-10 timolang@gmail.com 21edc56 Added doxyfile (doxygen) for the common folder. Started with doxygen comments for app and tft module. +* 2015-05-15 timolang@gmail.com 9a16865 Added doxgen comments to filesyste, checkbox, numupdown and screen module. And some minor changes to the other modules. +* +**************************************************************************************************************************************/ + #include "screen.h" diff --git a/common/app/screen_main.c b/common/app/screen_main.c index 24cfd68..d099ea9 100644 --- a/common/app/screen_main.c +++ b/common/app/screen_main.c @@ -1,3 +1,21 @@ +/************************************************************************************************************************************** +* Project: discoverpixy +* Website: https://github.com/t-moe/discoverpixy +* Authors: Aaron Schmocker, Timo Lang +* Institution: BFH Bern University of Applied Sciences +* File: common/app/screen_main.c +* +* Version History: +* Date Autor Email SHA Changes +* 2015-04-27 timolang@gmail.com cf72baa Introduced a Screen (sub) module and divided app into multiple screens. +* 2015-05-10 timolang@gmail.com e2bce8f Added filesystem module, tests and implementation for it in emulator. +* 2015-05-15 timolang@gmail.com 27c09ba Redesigned main menu. Moved stuff from pixytest to a new helper file and to the new "photo mode"-screen. +* 2015-05-16 timolang@gmail.com e46314b Added Tracking Screen and implemented "Reference Tracking" and "Color Region Selection" +* 2015-06-01 aaron@duckpond.ch caa7b5c Added IRQ for user button, fixed some touchproblems. +* 2015-06-01 timolang@gmail.com 3155f42 Fixed mainscreen layout. +* +**************************************************************************************************************************************/ + #include "screen_main.h" #include "screen_guitest.h" #include "screen_pixytest.h" @@ -17,157 +35,165 @@ BUTTON_STRUCT b_ref_tracking; BUTTON_STRUCT b_photo_mode; -static void b_our_tracking_cb(void* button) { - tracking_set_mode(OUR_TRACKING); - gui_screen_navigate(get_screen_tracking()); +static void b_our_tracking_cb(void* button) +{ + tracking_set_mode(OUR_TRACKING); + gui_screen_navigate(get_screen_tracking()); } -static void b_ref_tracking_cb(void* button) { - tracking_set_mode(REFERENCE_TRACKING); - gui_screen_navigate(get_screen_tracking()); +static void b_ref_tracking_cb(void* button) +{ + tracking_set_mode(REFERENCE_TRACKING); + gui_screen_navigate(get_screen_tracking()); } -static void b_photo_mode_cb(void* button) { - gui_screen_navigate(get_screen_photomode()); +static void b_photo_mode_cb(void* button) +{ + gui_screen_navigate(get_screen_photomode()); } -static void b_guitest_cb(void* button) { - gui_screen_navigate(get_screen_guitest()); +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_filetest_cb(void* button) +{ + gui_screen_navigate(get_screen_filetest()); } -static void b_pixytest_cb(void* button) { - gui_screen_navigate(get_screen_pixytest()); +static void b_pixytest_cb(void* button) +{ + gui_screen_navigate(get_screen_pixytest()); } -static void enter(void* screen) { - tft_clear(WHITE); +static void enter(void* screen) +{ + tft_clear(WHITE); - //Heading - tft_print_line(10,10,BLUE,TRANSPARENT,1,"Discoverpixy"); - tft_draw_line(0,40,319,40,BLACK); + //Heading + tft_print_line(10, 10, BLUE, TRANSPARENT, 1, "Discoverpixy"); + tft_draw_line(0, 40, 319, 40, BLACK); - #define X_TAB 97 - #define BUTTON_SPACING 7 +#define X_TAB 97 +#define BUTTON_SPACING 7 - //First line of buttons - #define Y_FIRST 60 - tft_print_line(10,Y_FIRST,BLACK,TRANSPARENT,0,"Tracking:"); + //First line of buttons +#define Y_FIRST 60 + tft_print_line(10, Y_FIRST, BLACK, TRANSPARENT, 0, "Tracking:"); - b_our_tracking.base.x1=X_TAB; //Start X of Button - b_our_tracking.base.y1=Y_FIRST-3; //Start Y of Button - b_our_tracking.base.x2=AUTO; //Auto Calculate X2 with String Width - b_our_tracking.base.y2=AUTO; //Auto Calculate Y2 with String Height - b_our_tracking.txtcolor=WHITE; //Set foreground color - b_our_tracking.bgcolor=HEX(0xE30535); //Set background color (Don't take 255 or 0 on at least one channel, to make shadows possible) - b_our_tracking.font=0; //Select Font - b_our_tracking.text="Our Tracking"; //Set Text (For formatted strings take sprintf) - b_our_tracking.callback=b_our_tracking_cb; //Call b_our_tracking when the button get's pressed - gui_button_add(&b_our_tracking); //Register Button (and run the callback from now on) + b_our_tracking.base.x1 = X_TAB; //Start X of Button + b_our_tracking.base.y1 = Y_FIRST - 3; //Start Y of Button + b_our_tracking.base.x2 = AUTO; //Auto Calculate X2 with String Width + b_our_tracking.base.y2 = AUTO; //Auto Calculate Y2 with String Height + b_our_tracking.txtcolor = WHITE; //Set foreground color + b_our_tracking.bgcolor = HEX(0xE30535); //Set background color (Don't take 255 or 0 on at least one channel, to make shadows possible) + b_our_tracking.font = 0; //Select Font + b_our_tracking.text = "Our Tracking"; //Set Text (For formatted strings take sprintf) + b_our_tracking.callback = b_our_tracking_cb; //Call b_our_tracking when the button get's pressed + gui_button_add(&b_our_tracking); //Register Button (and run the callback from now on) - b_ref_tracking.base.x1=b_our_tracking.base.x2+BUTTON_SPACING; - b_ref_tracking.base.y1=Y_FIRST-3; - b_ref_tracking.base.x2=AUTO; - b_ref_tracking.base.y2=AUTO; - b_ref_tracking.txtcolor=WHITE; - b_ref_tracking.bgcolor=HEX(0xFF2151); - b_ref_tracking.font=0; - b_ref_tracking.text="Ref Tracking"; - b_ref_tracking.callback=b_ref_tracking_cb; - gui_button_add(&b_ref_tracking); + b_ref_tracking.base.x1 = b_our_tracking.base.x2 + BUTTON_SPACING; + b_ref_tracking.base.y1 = Y_FIRST - 3; + b_ref_tracking.base.x2 = AUTO; + b_ref_tracking.base.y2 = AUTO; + b_ref_tracking.txtcolor = WHITE; + b_ref_tracking.bgcolor = HEX(0xFF2151); + b_ref_tracking.font = 0; + b_ref_tracking.text = "Ref Tracking"; + b_ref_tracking.callback = b_ref_tracking_cb; + gui_button_add(&b_ref_tracking); - //Second line of buttons - #define Y_SECOND Y_FIRST+25 - tft_print_line(10,Y_SECOND,BLACK,TRANSPARENT,0,"Photo mode:"); + //Second line of buttons +#define Y_SECOND Y_FIRST+25 + tft_print_line(10, Y_SECOND, BLACK, TRANSPARENT, 0, "Photo mode:"); - b_photo_mode.base.x1=X_TAB; - b_photo_mode.base.y1=Y_SECOND-3; - b_photo_mode.base.x2=AUTO; - b_photo_mode.base.y2=AUTO; - b_photo_mode.txtcolor=WHITE; - b_photo_mode.bgcolor=HEX(0x21B1FF); - b_photo_mode.font=0; - b_photo_mode.text="Photo Mode"; - b_photo_mode.callback=b_photo_mode_cb; - gui_button_add(&b_photo_mode); + b_photo_mode.base.x1 = X_TAB; + b_photo_mode.base.y1 = Y_SECOND - 3; + b_photo_mode.base.x2 = AUTO; + b_photo_mode.base.y2 = AUTO; + b_photo_mode.txtcolor = WHITE; + b_photo_mode.bgcolor = HEX(0x21B1FF); + b_photo_mode.font = 0; + b_photo_mode.text = "Photo Mode"; + b_photo_mode.callback = b_photo_mode_cb; + gui_button_add(&b_photo_mode); - //Third line of buttons - #define Y_THIRD Y_SECOND+25 - tft_print_line(10,Y_THIRD,BLACK,TRANSPARENT,0,"Tests:"); + //Third line of buttons +#define Y_THIRD Y_SECOND+25 + tft_print_line(10, Y_THIRD, BLACK, TRANSPARENT, 0, "Tests:"); - b_guitest.base.x1=X_TAB; - b_guitest.base.y1=Y_THIRD-3; - b_guitest.base.x2=AUTO; - b_guitest.base.y2=AUTO; - b_guitest.txtcolor=BLACK; - b_guitest.bgcolor=HEX(0x00FA21); - b_guitest.font=0; - b_guitest.text="Gui & Tft"; - b_guitest.callback=b_guitest_cb; - gui_button_add(&b_guitest); + b_guitest.base.x1 = X_TAB; + b_guitest.base.y1 = Y_THIRD - 3; + b_guitest.base.x2 = AUTO; + b_guitest.base.y2 = AUTO; + b_guitest.txtcolor = BLACK; + b_guitest.bgcolor = HEX(0x00FA21); + b_guitest.font = 0; + b_guitest.text = "Gui & Tft"; + b_guitest.callback = b_guitest_cb; + gui_button_add(&b_guitest); - b_pixytest.base.x1=b_guitest.base.x2+BUTTON_SPACING; - b_pixytest.base.y1=Y_THIRD-3; - b_pixytest.base.x2=AUTO; - b_pixytest.base.y2=AUTO; - b_pixytest.txtcolor=BLACK; - b_pixytest.bgcolor=HEX(0x00FA96); - b_pixytest.font=0; - b_pixytest.text="Pixy"; - b_pixytest.callback=b_pixytest_cb; - gui_button_add(&b_pixytest); + b_pixytest.base.x1 = b_guitest.base.x2 + BUTTON_SPACING; + b_pixytest.base.y1 = Y_THIRD - 3; + b_pixytest.base.x2 = AUTO; + b_pixytest.base.y2 = AUTO; + b_pixytest.txtcolor = BLACK; + b_pixytest.bgcolor = HEX(0x00FA96); + b_pixytest.font = 0; + b_pixytest.text = "Pixy"; + b_pixytest.callback = b_pixytest_cb; + gui_button_add(&b_pixytest); - b_filetest.base.x1=b_pixytest.base.x2+BUTTON_SPACING; - b_filetest.base.y1=Y_THIRD-3; - b_filetest.base.x2=AUTO; - b_filetest.base.y2=AUTO; - b_filetest.txtcolor=BLACK; - b_filetest.bgcolor=HEX(0x00FAC4); - b_filetest.font=0; - b_filetest.text="File"; - b_filetest.callback=b_filetest_cb; - gui_button_add(&b_filetest); + b_filetest.base.x1 = b_pixytest.base.x2 + BUTTON_SPACING; + b_filetest.base.y1 = Y_THIRD - 3; + b_filetest.base.x2 = AUTO; + b_filetest.base.y2 = AUTO; + b_filetest.txtcolor = BLACK; + b_filetest.bgcolor = HEX(0x00FAC4); + b_filetest.font = 0; + b_filetest.text = "File"; + b_filetest.callback = b_filetest_cb; + gui_button_add(&b_filetest); - //Bottom line - tft_draw_line(0,145,319,145,BLACK); - tft_print_line(10,150,BLUE,TRANSPARENT,0,"Powered by"); - tft_draw_bitmap_file_unscaled(10,165,"pixy_small.bmp"); - tft_draw_bitmap_file_unscaled(165,165,"stm_small.bmp"); + //Bottom line + tft_draw_line(0, 145, 319, 145, BLACK); + tft_print_line(10, 150, BLUE, TRANSPARENT, 0, "Powered by"); + tft_draw_bitmap_file_unscaled(10, 165, "pixy_small.bmp"); + tft_draw_bitmap_file_unscaled(165, 165, "stm_small.bmp"); } -static void leave(void* screen) { - gui_button_remove(&b_our_tracking); - gui_button_remove(&b_ref_tracking); - gui_button_remove(&b_photo_mode); - gui_button_remove(&b_guitest); - gui_button_remove(&b_pixytest); - gui_button_remove(&b_filetest); +static void leave(void* screen) +{ + gui_button_remove(&b_our_tracking); + gui_button_remove(&b_ref_tracking); + gui_button_remove(&b_photo_mode); + gui_button_remove(&b_guitest); + gui_button_remove(&b_pixytest); + gui_button_remove(&b_filetest); } -static void update(void* screen) { - //gui_button_redraw(&b_guitest); //only needed if button is overdrawn by others +static void update(void* screen) +{ + //gui_button_redraw(&b_guitest); //only needed if button is overdrawn by others } static SCREEN_STRUCT screen = { - enter, - leave, - update + enter, + leave, + update }; -SCREEN_STRUCT* get_screen_main() { - return &screen; +SCREEN_STRUCT* get_screen_main() +{ + return &screen; } - - diff --git a/common/app/screen_main.h b/common/app/screen_main.h index 8cc9bff..f166187 100644 --- a/common/app/screen_main.h +++ b/common/app/screen_main.h @@ -1,3 +1,20 @@ +/************************************************************************************************************************************** +* Project: discoverpixy +* Website: https://github.com/t-moe/discoverpixy +* Authors: Aaron Schmocker, Timo Lang +* Institution: BFH Bern University of Applied Sciences +* File: common/app/screen_main.h +* +* Version History: +* Date Autor Email SHA Changes +* 2015-04-27 timolang@gmail.com cf72baa Introduced a Screen (sub) module and divided app into multiple screens. +* 2015-05-10 timolang@gmail.com 21edc56 Added doxyfile (doxygen) for the common folder. Started with doxygen comments for app and tft module. +* 2015-05-11 timolang@gmail.com 08d9fe0 More work on doxygen module structure +* 2015-05-12 timolang@gmail.com 1402598 Added doxygen stuff for button module and some minor changes to touch, screen_main and tft module. +* 2015-05-15 timolang@gmail.com 9a16865 Added doxgen comments to filesyste, checkbox, numupdown and screen module. And some minor changes to the other modules. +* +**************************************************************************************************************************************/ + #include "screen.h" /** diff --git a/common/app/screen_photomode.c b/common/app/screen_photomode.c index 01232f4..872e354 100644 --- a/common/app/screen_photomode.c +++ b/common/app/screen_photomode.c @@ -1,3 +1,18 @@ +/************************************************************************************************************************************** +* Project: discoverpixy +* Website: https://github.com/t-moe/discoverpixy +* Authors: Aaron Schmocker, Timo Lang +* Institution: BFH Bern University of Applied Sciences +* File: common/app/screen_photomode.c +* +* Version History: +* Date Autor Email SHA Changes +* 2015-05-15 timolang@gmail.com 27c09ba Redesigned main menu. Moved stuff from pixytest to a new helper file and to the new "photo mode"-screen. +* 2015-05-16 timolang@gmail.com 62006e0 Documented pixy_helper and implemented/finished photo-mode screens! Snap some shots! +* 2015-06-07 timolang@gmail.com c87220d Renamed pixy_helper to pixy_frame. Updated docu of appliaction. added doxygen comments to pixy_{frame,control}.h +* +**************************************************************************************************************************************/ + #include "screen_photomode.h" #include "screen_photomode_save.h" #include "button.h" @@ -12,155 +27,182 @@ static bool pixy_connected = false; //Whether or not the pixy cam is currently c static BUTTON_STRUCT b_back; //Button to navigate back static BUTTON_STRUCT b_save; //Button to save the current image static TOUCH_AREA_STRUCT a_area; //Touch Area, where the frame is drawn. Used to drag the image around -static bool subMenu=false; //Whether or not we left the current screen for a submenu +static bool subMenu = false; //Whether or not we left the current screen for a submenu //Callback for when the user presses the "back" button -static void b_back_cb(void* button) { - subMenu = false; //we're not entering a submenu - gui_screen_back(); //navigate back to the previous screen +static void b_back_cb(void* button) +{ + subMenu = false; //we're not entering a submenu + gui_screen_back(); //navigate back to the previous screen } //Callback for when the user presses the "save" button -static void b_save_cb(void* button) { - subMenu = true; //we're entering a submenu - gui_screen_navigate(get_screen_photomodesave()); //navigate to the save screen +static void b_save_cb(void* button) +{ + subMenu = true; //we're entering a submenu + gui_screen_navigate(get_screen_photomodesave()); //navigate to the save screen } static POINT_STRUCT pixy_pos; //The current position of pixy's servos static POINT_STRUCT old_pos; //The last touch position on the screen //Callback for when the user drags the image around -static void touchCB(void* touchArea, TOUCH_ACTION triggeredAction) { - POINT_STRUCT p = touch_get_last_point(); //get the last touched point - switch(triggeredAction) { - case PEN_ENTER: - case PEN_DOWN: - old_pos = p; //If the user "newly" enters the touch area, we set the "last" position to the current - break; - case PEN_MOVE: //the user is moving around, he entered the screen a while ago (old_pos is set) - { - int16_t deltaX = p.x - old_pos.x; //Calculate x difference between last and current touch - int16_t deltaY = p.y - old_pos.y; //Calculate y difference between last and current touch - old_pos=p; //store the current touch point for the next time - //printf("%d %d\n",deltaX,deltaY); - if(pixy_connected) { - //Calculate new servo coordinates. 2 is just a proportional factor - int16_t new_x = pixy_pos.x+deltaX*2; - int16_t new_y = pixy_pos.y-deltaY*2; +static void touchCB(void* touchArea, TOUCH_ACTION triggeredAction) +{ + POINT_STRUCT p = touch_get_last_point(); //get the last touched point - //check limits - if(new_x<0) new_x=0; - if(new_x>1000) new_x=1000; - if(new_y<0) new_y=0; - if(new_y>1000) new_y=1000; - - //set pixy_pos so that the main routine can send it to the servos - pixy_pos.x = new_x; - pixy_pos.y= new_y; - } - } + switch (triggeredAction) { + case PEN_ENTER: + case PEN_DOWN: + old_pos = p; //If the user "newly" enters the touch area, we set the "last" position to the current break; - case PEN_UP: - case PEN_LEAVE: - //printf("Leave/up\n"); - break; - default: break; - } - + + case PEN_MOVE: { //the user is moving around, he entered the screen a while ago (old_pos is set) + int16_t deltaX = p.x - old_pos.x; //Calculate x difference between last and current touch + int16_t deltaY = p.y - old_pos.y; //Calculate y difference between last and current touch + old_pos = p; //store the current touch point for the next time + + //printf("%d %d\n",deltaX,deltaY); + if (pixy_connected) { + //Calculate new servo coordinates. 2 is just a proportional factor + int16_t new_x = pixy_pos.x + deltaX * 2; + int16_t new_y = pixy_pos.y - deltaY * 2; + + //check limits + if (new_x < 0) { + new_x = 0; + } + + if (new_x > 1000) { + new_x = 1000; + } + + if (new_y < 0) { + new_y = 0; + } + + if (new_y > 1000) { + new_y = 1000; + } + + //set pixy_pos so that the main routine can send it to the servos + pixy_pos.x = new_x; + pixy_pos.y = new_y; + } + } + break; + + case PEN_UP: + case PEN_LEAVE: + //printf("Leave/up\n"); + break; + + default: + break; + } + } //Callback for when the screen is entered/loaded -static void enter(void* screen) { - tft_clear(WHITE); - - tft_print_line(5,5,BLACK,TRANSPARENT,0,"Drag the image around and "); +static void enter(void* screen) +{ + tft_clear(WHITE); - //Back button - b_back.base.x1=5; //Start X of Button - b_back.base.y1=19; //Start Y of Button - b_back.base.x2=AUTO; //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_print_line(5, 5, BLACK, TRANSPARENT, 0, "Drag the image around and "); - //Save button - b_save.base.x1=190; - b_save.base.y1=3; - b_save.base.x2=AUTO; - b_save.base.y2=AUTO; - b_save.txtcolor=WHITE; - b_save.bgcolor=HEX(0x1010AE); - b_save.font=0; - b_save.text="Save it!"; - b_save.callback=b_save_cb; - gui_button_add(&b_save); + //Back button + b_back.base.x1 = 5; //Start X of Button + b_back.base.y1 = 19; //Start Y of Button + b_back.base.x2 = AUTO; //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) - //Frame Coordinates: topleft = (1,40); bottomright = (318,238) - //Leave a 10px border for the area + //Save button + b_save.base.x1 = 190; + b_save.base.y1 = 3; + b_save.base.x2 = AUTO; + b_save.base.y2 = AUTO; + b_save.txtcolor = WHITE; + b_save.bgcolor = HEX(0x1010AE); + b_save.font = 0; + b_save.text = "Save it!"; + b_save.callback = b_save_cb; + gui_button_add(&b_save); - //Area to drag the image around - a_area.hookedActions = PEN_DOWN | PEN_MOVE | PEN_ENTER | PEN_UP | PEN_LEAVE; - a_area.x1 = 11; - a_area.y1 = 50; - a_area.x2 = 308; - a_area.y2 = 228; - a_area.callback = touchCB; - touch_register_area(&a_area); + //Frame Coordinates: topleft = (1,40); bottomright = (318,238) + //Leave a 10px border for the area - //Pixy stuff - pixy_connected = (pixy_init()==0); //try to connect to pixy - if(pixy_connected && !subMenu) { //pixy is connected, but we are not coming from a submenu - pixy_pos.x=pixy_pos.y=500; //reset servo positions to center - } + //Area to drag the image around + a_area.hookedActions = PEN_DOWN | PEN_MOVE | PEN_ENTER | PEN_UP | PEN_LEAVE; + a_area.x1 = 11; + a_area.y1 = 50; + a_area.x2 = 308; + a_area.y2 = 228; + a_area.callback = touchCB; + touch_register_area(&a_area); + + //Pixy stuff + pixy_connected = (pixy_init() == 0); //try to connect to pixy + + if (pixy_connected && !subMenu) { //pixy is connected, but we are not coming from a submenu + pixy_pos.x = pixy_pos.y = 500; //reset servo positions to center + } } //Callback for when the screen is left/unloaded -static void leave(void* screen) { - //remove buttons and touch area. - gui_button_remove(&b_back); - gui_button_remove(&b_save); - touch_unregister_area(&a_area); +static void leave(void* screen) +{ + //remove buttons and touch area. + gui_button_remove(&b_back); + gui_button_remove(&b_save); + touch_unregister_area(&a_area); } //Callback for when the screen should be updated //This is the main loop of the screen. This method will be called repeatedly -static void update(void* screen) { - //Note: The only way to detect that pixy has been disconnected is if a command fails. There's no pixy_is_connected method yet :'( +static void update(void* screen) +{ + //Note: The only way to detect that pixy has been disconnected is if a command fails. There's no pixy_is_connected method yet :'( - if(!pixy_connected) { //Pixy not connected - pixy_close(); //Ensure that all pixy resources are freed (failsafe) - if(pixy_init()==0) { //try to connect to pixy - pixy_connected=true; - if(!subMenu) { //we're not coming from a submenu - pixy_pos.x=pixy_pos.y=500; //reset servo positions to center - } - printf("pixy (re)initialized\n"); - } - } + if (!pixy_connected) { //Pixy not connected + pixy_close(); //Ensure that all pixy resources are freed (failsafe) - if(pixy_connected) { //If we are connected (now) - pixy_service(); //Handle pending pixy events (e.g. color info retrival) + if (pixy_init() == 0) { //try to connect to pixy + pixy_connected = true; - pixy_render_full_frame(1,40); //render the pixy video at point (1,40) - - //set the servo positions to the coordinates form the touch interrupt - pixy_rcs_set_position(0,pixy_pos.x); - pixy_rcs_set_position(1,pixy_pos.y); - } + if (!subMenu) { //we're not coming from a submenu + pixy_pos.x = pixy_pos.y = 500; //reset servo positions to center + } + + printf("pixy (re)initialized\n"); + } + } + + if (pixy_connected) { //If we are connected (now) + pixy_service(); //Handle pending pixy events (e.g. color info retrival) + + pixy_render_full_frame(1, 40); //render the pixy video at point (1,40) + + //set the servo positions to the coordinates form the touch interrupt + pixy_rcs_set_position(0, pixy_pos.x); + pixy_rcs_set_position(1, pixy_pos.y); + } } //Declare screen callbacks static SCREEN_STRUCT screen = { - enter, - leave, - update + enter, + leave, + update }; -SCREEN_STRUCT* get_screen_photomode() { - return &screen; +SCREEN_STRUCT* get_screen_photomode() +{ + return &screen; } diff --git a/common/app/screen_photomode.h b/common/app/screen_photomode.h index 19545ac..bdccb4f 100644 --- a/common/app/screen_photomode.h +++ b/common/app/screen_photomode.h @@ -1,3 +1,16 @@ +/************************************************************************************************************************************** +* Project: discoverpixy +* Website: https://github.com/t-moe/discoverpixy +* Authors: Aaron Schmocker, Timo Lang +* Institution: BFH Bern University of Applied Sciences +* File: common/app/screen_photomode.h +* +* Version History: +* Date Autor Email SHA Changes +* 2015-05-15 timolang@gmail.com 27c09ba Redesigned main menu. Moved stuff from pixytest to a new helper file and to the new "photo mode"-screen. +* +**************************************************************************************************************************************/ + #include "screen.h" /** diff --git a/common/app/screen_photomode_save.c b/common/app/screen_photomode_save.c index e00f8dd..6add4f3 100644 --- a/common/app/screen_photomode_save.c +++ b/common/app/screen_photomode_save.c @@ -1,3 +1,17 @@ +/************************************************************************************************************************************** +* Project: discoverpixy +* Website: https://github.com/t-moe/discoverpixy +* Authors: Aaron Schmocker, Timo Lang +* Institution: BFH Bern University of Applied Sciences +* File: common/app/screen_photomode_save.c +* +* Version History: +* Date Autor Email SHA Changes +* 2015-05-16 timolang@gmail.com 62006e0 Documented pixy_helper and implemented/finished photo-mode screens! Snap some shots! +* 2015-06-07 timolang@gmail.com c87220d Renamed pixy_helper to pixy_frame. Updated docu of appliaction. added doxygen comments to pixy_{frame,control}.h +* +**************************************************************************************************************************************/ + #include "screen_photomode_save.h" #include "filesystem.h" #include "button.h" @@ -13,8 +27,9 @@ static BUTTON_STRUCT b_back; //Button to navigate back static TOUCH_AREA_STRUCT a_area; //Touch area to select the save-file //Callback for when the user presses the "back" button -static void b_back_cb(void* button) { - gui_screen_back(); +static void b_back_cb(void* button) +{ + gui_screen_back(); } static int num_files_ok; //number of files into which we can write the image (size, flags ok) @@ -24,46 +39,51 @@ static int liststart; //The y-Coordinate of the Start of the File-List static const char* picked_file; //The filename picked by the user, to save the image to //Linked list structure to save all files which are suitable for saving. -typedef struct FILE_LIST_ENTRY_S{ - char* filename; //Name of the file - struct FILE_LIST_ENTRY_S* next; //Pointer to the next entry in the list or NULL +typedef struct FILE_LIST_ENTRY_S { + char* filename; //Name of the file + struct FILE_LIST_ENTRY_S* next; //Pointer to the next entry in the list or NULL } FILE_LIST_ENTRY; static FILE_LIST_ENTRY* files_ok; //Pointer to the head of the list //Callback for when the user selects a file to save the image into -static void touchCB(void* touchArea, TOUCH_ACTION triggeredAction) { +static void touchCB(void* touchArea, TOUCH_ACTION triggeredAction) +{ - int y = touch_get_last_point().y-liststart; //Calculate the y-Coordinate of the touch point relative to the start of the file-list - int elem = y/fontheight; //Calculate the file index - if(elem<0 | elem>= num_files_ok) return; //Check if the file index is valid (0,1,..,num_files_ok-1) + int y = touch_get_last_point().y - liststart; //Calculate the y-Coordinate of the touch point relative to the start of the file-list + int elem = y / fontheight; //Calculate the file index - //Search for the corresponding entry in the linked list - FILE_LIST_ENTRY* current_entry = files_ok; //Start walking through the list, starting by the head of the list - for(int i=0; inext; //traverse to the next file - } + if (elem < 0 | elem >= num_files_ok) { + return; //Check if the file index is valid (0,1,..,num_files_ok-1) + } - picked_file = current_entry->filename; //save the picked filename. It will be used by the statemachine in the main loop - touch_unregister_area(&a_area); //unregister the touch area, we no longer need it. No more interrupts will be fired. - state=saving; //Change the state of the statemachine + //Search for the corresponding entry in the linked list + FILE_LIST_ENTRY* current_entry = files_ok; //Start walking through the list, starting by the head of the list + + for (int i = 0; i < elem; i++) { //Until we have reached the file (index) + current_entry = current_entry->next; //traverse to the next file + } + + picked_file = current_entry->filename; //save the picked filename. It will be used by the statemachine in the main loop + touch_unregister_area(&a_area); //unregister the touch area, we no longer need it. No more interrupts will be fired. + state = saving; //Change the state of the statemachine } //Text-Lines to show if we have no matching files (num_files_ok==0) static const char* nomatch_text [] = { - "Due to limitations of the filesystem", - "implementation you can only write to", - "existing files.", - "", - "The files need to have a .bmp", - "extension and must be at least", - "189410 bytes (185kb) large.", - "Unfortunately there were no such", - "files found in the root directory.", - "", - "Please create some files and come", - "back again.", - NULL + "Due to limitations of the filesystem", + "implementation you can only write to", + "existing files.", + "", + "The files need to have a .bmp", + "extension and must be at least", + "189410 bytes (185kb) large.", + "Unfortunately there were no such", + "files found in the root directory.", + "", + "Please create some files and come", + "back again.", + NULL }; @@ -71,231 +91,251 @@ static const char* nomatch_text [] = { //This header has been taken from a white bitmap saved with gimp. //Wikipedia has a pretty good description on the header: http://de.wikipedia.org/wiki/Windows_Bitmap static unsigned char bmpheader_data[0x7A] = { - 0x42, 0x4d, 0xe2, 0xe3, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x00, - 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x3e, 0x01, 0x00, 0x00, 0xc6, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0xe3, - 0x02, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x47, 0x52, 0x73, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00 + 0x42, 0x4d, 0xe2, 0xe3, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x00, + 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x3e, 0x01, 0x00, 0x00, 0xc6, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0xe3, + 0x02, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x47, 0x52, 0x73, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00 }; //Callback for when the screen is entered/loaded -static void enter(void* screen) { - tft_clear(WHITE); +static void enter(void* screen) +{ + tft_clear(WHITE); - #define X_OFS 5 +#define X_OFS 5 - //Back button - b_back.base.x1=X_OFS; //Start X of Button - b_back.base.y1=210; //Start Y of Button - b_back.base.x2=AUTO; //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) + //Back button + b_back.base.x1 = X_OFS; //Start X of Button + b_back.base.y1 = 210; //Start Y of Button + b_back.base.x2 = AUTO; //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) - state =init; //Start with the init state - fontheight = tft_font_height(0)+2; //Save the height of the used font, for fast access - files_ok = NULL; //initialize the linked list with 0 elements - num_files_ok = 0; //we have zero! elements + state = init; //Start with the init state + fontheight = tft_font_height(0) + 2; //Save the height of the used font, for fast access + files_ok = NULL; //initialize the linked list with 0 elements + num_files_ok = 0; //we have zero! elements } //Callback for when the screen should be updated //This is the main loop of the screen. This method will be called repeatedly -static void update(void* screen) { - switch(state) { - case init: //Init State: The user just entered the screen - { - DIRECTORY_STRUCT* dir = filesystem_dir_open("."); //open root directory - if(dir==NULL) { //error while opening root directory - tft_print_line(X_OFS,5,BLACK,TRANSPARENT,0,"Error accessing Filesystem"); - state=error; - break; - } +static void update(void* screen) +{ + switch (state) { + case init: { //Init State: The user just entered the screen + DIRECTORY_STRUCT* dir = filesystem_dir_open("."); //open root directory - bool nomatch= true; //whether or not we have zero files which are suitable for saving + if (dir == NULL) { //error while opening root directory + tft_print_line(X_OFS, 5, BLACK, TRANSPARENT, 0, "Error accessing Filesystem"); + state = error; + break; + } - for(int i=0; inum_files; i++) { //walk through all files in the directory - FILE_STRUCT* file = &(dir->files[i]); //Pointer to the current file/subdirectory + bool nomatch = true; //whether or not we have zero files which are suitable for saving - //Ignore directories, archives, hidden files, system files and files we cannot write to - if(file->fattrib&(F_SYS|F_HID|F_ARC|F_DIR|F_RDO)) continue; + for (int i = 0; i < dir->num_files; i++) { //walk through all files in the directory + FILE_STRUCT* file = &(dir->files[i]); //Pointer to the current file/subdirectory - //ignore files which are not large enough - if(file->fsize<189410) continue; //size taken from an example bitmap (318x198x24) + //Ignore directories, archives, hidden files, system files and files we cannot write to + if (file->fattrib & (F_SYS | F_HID | F_ARC | F_DIR | F_RDO)) { + continue; + } - nomatch=false; //at least one file matches - break; - } + //ignore files which are not large enough + if (file->fsize < 189410) { + continue; //size taken from an example bitmap (318x198x24) + } - if(nomatch) { //not one file is suitable for writing - int y=5; //y-Coordinate where to start writing the error text - int i=0; - while(nomatch_text[i]!=NULL) { //for every line in the big error array - //Write the line's text and go to the next line - tft_print_line(X_OFS,y+i*fontheight,BLACK,TRANSPARENT,0,nomatch_text[i]); - i++; - } - state = error; - } else { //we have a least one suitable file - state = showlist; - } + nomatch = false; //at least one file matches + break; + } - filesystem_dir_close(dir); //free directory struct - } - break; + if (nomatch) { //not one file is suitable for writing + int y = 5; //y-Coordinate where to start writing the error text + int i = 0; - case showlist: //Show List State: Where we load and present the suitable file's to the user in a list - { - DIRECTORY_STRUCT* dir2 = filesystem_dir_open("."); //Open the directory again - if(dir2==NULL) return; //Error on opening? This should never happen, since it's handled in the previous state + while (nomatch_text[i] != NULL) { //for every line in the big error array + //Write the line's text and go to the next line + tft_print_line(X_OFS, y + i * fontheight, BLACK, TRANSPARENT, 0, nomatch_text[i]); + i++; + } - int y = 5; //y-Coordinate where to start drawing/writing text/list-elements + state = error; + } else { //we have a least one suitable file + state = showlist; + } - tft_print_line(X_OFS,y,BLACK,TRANSPARENT,0,"Pick a file to save the image to"); - y+=fontheight+5; + filesystem_dir_close(dir); //free directory struct + } + break; - tft_print_line(X_OFS,y,BLUE,TRANSPARENT,0,"Name Modified Size"); - y+=fontheight; + case showlist: { //Show List State: Where we load and present the suitable file's to the user in a list + DIRECTORY_STRUCT* dir2 = filesystem_dir_open("."); //Open the directory again - liststart = y; //store the y coordinate of the start of the list away (used in toucharea callback) - num_files_ok = 0; //we start with 0 matching files + if (dir2 == NULL) { + return; //Error on opening? This should never happen, since it's handled in the previous state + } - FILE_LIST_ENTRY* current_entry = NULL; //We start with an empty list - for(int i=0; inum_files && num_files_ok<10; i++) { //go through all the files of the directory, abort if we have 10 matches - FILE_STRUCT* file = &(dir2->files[i]); + int y = 5; //y-Coordinate where to start drawing/writing text/list-elements - //Ignore directories, archives, hidden files, system files and files we cannot write to - if(file->fattrib&(F_SYS|F_HID|F_ARC|F_DIR|F_RDO)) continue; + tft_print_line(X_OFS, y, BLACK, TRANSPARENT, 0, "Pick a file to save the image to"); + y += fontheight + 5; - //ignore files which are not large enough - if(file->fsize<189410) continue; //size taken from an example bitmap (318x198x24) + tft_print_line(X_OFS, y, BLUE, TRANSPARENT, 0, "Name Modified Size"); + y += fontheight; - //Print out filename, modified date,time and file size - tft_print_formatted(X_OFS,y,BLACK, - TRANSPARENT,0,"%-16s %02u.%02u.%02u %02u:%02u:%02u %u", - file->fname, - file->fdate.day, - file->fdate.month, - (file->fdate.year+1980)%100, - file->ftime.hour, - file->ftime.min, - file->ftime.sec*2, - file->fsize); + liststart = y; //store the y coordinate of the start of the list away (used in toucharea callback) + num_files_ok = 0; //we start with 0 matching files - if(current_entry==NULL) { //The list is empty - current_entry = malloc(sizeof(FILE_LIST_ENTRY)); //create new entry - files_ok = current_entry; //assign it to the list head - } else { //there's a least one entry in the list - current_entry->next = malloc(sizeof(FILE_LIST_ENTRY)); //append entry to previous entry - current_entry = current_entry->next; //newly created entry is the current now. - } - current_entry->next = NULL; //we're at the end of the list (for now) - current_entry->filename = malloc(strlen(file->fname)+1); //allocate space for the filename + zero-termination - strcpy(current_entry->filename,file->fname); //copy filename (so that we can close the directory after scanning) + FILE_LIST_ENTRY* current_entry = NULL; //We start with an empty list - //since we have found a suitable file we need to increment the position in the list - num_files_ok++; - y+=fontheight; - } + for (int i = 0; i < dir2->num_files && num_files_ok < 10; i++) { //go through all the files of the directory, abort if we have 10 matches + FILE_STRUCT* file = &(dir2->files[i]); - //Touch area for file-selection (in the list) - a_area.hookedActions = PEN_UP; //we're only interested in PEN_UP events - a_area.x1 = X_OFS; //Left border - a_area.y1 = liststart; //Start where the list started - a_area.x2 = 320-X_OFS; //Right border - a_area.y2 = liststart+fontheight*num_files_ok; //stop at the end of the list - a_area.callback = touchCB; //execute our callback when PEN_UP occurs - touch_register_area(&a_area); //register the touch area and receive events from now on + //Ignore directories, archives, hidden files, system files and files we cannot write to + if (file->fattrib & (F_SYS | F_HID | F_ARC | F_DIR | F_RDO)) { + continue; + } - filesystem_dir_close(dir2); //we no longer need the directory struct, since we have our own linked list now + //ignore files which are not large enough + if (file->fsize < 189410) { + continue; //size taken from an example bitmap (318x198x24) + } - state=picking; - } - break; + //Print out filename, modified date,time and file size + tft_print_formatted(X_OFS, y, BLACK, + TRANSPARENT, 0, "%-16s %02u.%02u.%02u %02u:%02u:%02u %u", + file->fname, + file->fdate.day, + file->fdate.month, + (file->fdate.year + 1980) % 100, + file->ftime.hour, + file->ftime.min, + file->ftime.sec * 2, + file->fsize); - case picking: //Picking State: Where we wait on the users file choice - pixy_service(); //Handle pending pixy events - //do nothing and wait on user to pick a file - break; + if (current_entry == NULL) { //The list is empty + current_entry = malloc(sizeof(FILE_LIST_ENTRY)); //create new entry + files_ok = current_entry; //assign it to the list head + } else { //there's a least one entry in the list + current_entry->next = malloc(sizeof(FILE_LIST_ENTRY)); //append entry to previous entry + current_entry = current_entry->next; //newly created entry is the current now. + } - case saving: //Saving State: Where we save the image to the selected file - { - FILE_HANDLE* file = filesystem_file_open(picked_file); //try to open the selected file - if(file==NULL) { //opening the file failed - tft_print_formatted(X_OFS,190,BLUE,TRANSPARENT,0,"Could not open %s",picked_file); - state=error; - break; - } + current_entry->next = NULL; //we're at the end of the list (for now) + current_entry->filename = malloc(strlen(file->fname) + 1); //allocate space for the filename + zero-termination + strcpy(current_entry->filename, file->fname); //copy filename (so that we can close the directory after scanning) - filesystem_file_seek(file,0); //seek to the start of the file (optional?) - if(filesystem_file_write(file,bmpheader_data,0x7A)!=F_OK) { //Writing the header failed - tft_print_formatted(X_OFS,190,BLUE,TRANSPARENT,0,"Error while writing to %s",picked_file); - filesystem_file_close(file); - state=error; - break; - } + //since we have found a suitable file we need to increment the position in the list + num_files_ok++; + y += fontheight; + } - if(pixy_save_full_frame(file)!=0) { //Writing the imagedata failed - tft_print_formatted(X_OFS,190,BLUE,TRANSPARENT,0,"Error while writing to %s",picked_file); - filesystem_file_close(file); - state=error; - break; - } + //Touch area for file-selection (in the list) + a_area.hookedActions = PEN_UP; //we're only interested in PEN_UP events + a_area.x1 = X_OFS; //Left border + a_area.y1 = liststart; //Start where the list started + a_area.x2 = 320 - X_OFS; //Right border + a_area.y2 = liststart + fontheight * num_files_ok; //stop at the end of the list + a_area.callback = touchCB; //execute our callback when PEN_UP occurs + touch_register_area(&a_area); //register the touch area and receive events from now on - //if we reach this point, we have written all data out successfully + filesystem_dir_close(dir2); //we no longer need the directory struct, since we have our own linked list now - filesystem_file_close(file); //close/finalize the file - tft_print_formatted(X_OFS,190,BLUE,TRANSPARENT,0,"Image saved to %s",picked_file); - state = done; - } - break; + state = picking; + } + break; - case error: //Error State: Where we show an error message and leave the user no other choice than to click the backbutton - case done: //Done State: When saving the file was successful - pixy_service(); //Handle pending pixy events - //wait on user to click the back button - break; + case picking: //Picking State: Where we wait on the users file choice + pixy_service(); //Handle pending pixy events + //do nothing and wait on user to pick a file + break; - } + case saving: { //Saving State: Where we save the image to the selected file + FILE_HANDLE* file = filesystem_file_open(picked_file); //try to open the selected file + + if (file == NULL) { //opening the file failed + tft_print_formatted(X_OFS, 190, BLUE, TRANSPARENT, 0, "Could not open %s", picked_file); + state = error; + break; + } + + filesystem_file_seek(file, 0); //seek to the start of the file (optional?) + + if (filesystem_file_write(file, bmpheader_data, 0x7A) != F_OK) { //Writing the header failed + tft_print_formatted(X_OFS, 190, BLUE, TRANSPARENT, 0, "Error while writing to %s", picked_file); + filesystem_file_close(file); + state = error; + break; + } + + if (pixy_save_full_frame(file) != 0) { //Writing the imagedata failed + tft_print_formatted(X_OFS, 190, BLUE, TRANSPARENT, 0, "Error while writing to %s", picked_file); + filesystem_file_close(file); + state = error; + break; + } + + //if we reach this point, we have written all data out successfully + + filesystem_file_close(file); //close/finalize the file + tft_print_formatted(X_OFS, 190, BLUE, TRANSPARENT, 0, "Image saved to %s", picked_file); + state = done; + } + break; + + case error: //Error State: Where we show an error message and leave the user no other choice than to click the backbutton + case done: //Done State: When saving the file was successful + pixy_service(); //Handle pending pixy events + //wait on user to click the back button + break; + + } } //Callback for when the screen is left/unloaded -static void leave(void* screen) { - gui_button_remove(&b_back); //Remove/Free the back button +static void leave(void* screen) +{ + gui_button_remove(&b_back); //Remove/Free the back button - if(state==picking){ //The user left the screen in the "picking"-phase - touch_unregister_area(&a_area); //remove the touch area (for the list) - } + if (state == picking) { //The user left the screen in the "picking"-phase + touch_unregister_area(&a_area); //remove the touch area (for the list) + } - if(state==picking|| state==saving || state==done) { //the user left the screen after we created the linked list - //Iterate through the linked list and free all resources - FILE_LIST_ENTRY* current_entry = files_ok; //start with the list head - while(current_entry!=NULL) { //while we're not at the end - FILE_LIST_ENTRY* temp = current_entry->next; //save the next pointer because we free the current element on the next line - free((void*)(current_entry->filename)); //free filename - free(current_entry); //free element itself - current_entry= temp; //advance - } - } + if (state == picking || state == saving || state == done) { //the user left the screen after we created the linked list + //Iterate through the linked list and free all resources + FILE_LIST_ENTRY* current_entry = files_ok; //start with the list head + + while (current_entry != NULL) { //while we're not at the end + FILE_LIST_ENTRY* temp = current_entry->next; //save the next pointer because we free the current element on the next line + free((void*)(current_entry->filename)); //free filename + free(current_entry); //free element itself + current_entry = temp; //advance + } + } } //Declare screen callbacks static SCREEN_STRUCT screen = { - enter, - leave, - update + enter, + leave, + update }; -SCREEN_STRUCT* get_screen_photomodesave() { - return &screen; +SCREEN_STRUCT* get_screen_photomodesave() +{ + return &screen; } diff --git a/common/app/screen_photomode_save.h b/common/app/screen_photomode_save.h index 6f71fa0..5b7814e 100644 --- a/common/app/screen_photomode_save.h +++ b/common/app/screen_photomode_save.h @@ -1,3 +1,16 @@ +/************************************************************************************************************************************** +* Project: discoverpixy +* Website: https://github.com/t-moe/discoverpixy +* Authors: Aaron Schmocker, Timo Lang +* Institution: BFH Bern University of Applied Sciences +* File: common/app/screen_photomode_save.h +* +* Version History: +* Date Autor Email SHA Changes +* 2015-05-16 timolang@gmail.com 62006e0 Documented pixy_helper and implemented/finished photo-mode screens! Snap some shots! +* +**************************************************************************************************************************************/ + #include "screen.h" /** @@ -20,4 +33,3 @@ SCREEN_STRUCT* get_screen_photomodesave(); /*@}*/ /*@}*/ - diff --git a/common/app/screen_pixytest.c b/common/app/screen_pixytest.c index 8b7b4cd..b39e718 100644 --- a/common/app/screen_pixytest.c +++ b/common/app/screen_pixytest.c @@ -1,3 +1,23 @@ +/************************************************************************************************************************************** +* Project: discoverpixy +* Website: https://github.com/t-moe/discoverpixy +* Authors: Aaron Schmocker, Timo Lang +* Institution: BFH Bern University of Applied Sciences +* File: common/app/screen_pixytest.c +* +* Version History: +* Date Autor Email SHA Changes +* 2015-04-27 timolang@gmail.com cf72baa Introduced a Screen (sub) module and divided app into multiple screens. +* 2015-05-02 timolang@gmail.com 3281616 Added some more touch functions. Improved pixy test. Drag the Image around! +* 2015-05-09 timolang@gmail.com 0b5173e Added reference tracking. +* 2015-05-15 timolang@gmail.com 27c09ba Redesigned main menu. Moved stuff from pixytest to a new helper file and to the new "photo mode"-screen. +* 2015-05-25 timolang@gmail.com 6a61769 Reimplemented pixytest screen. Added a lot of Test-Buttons. +* 2015-06-01 aaron@duckpond.ch caa7b5c Added IRQ for user button, fixed some touchproblems. +* 2015-06-03 timolang@gmail.com 74aa186 Made pixy_test screen working again. Had to disable pixy_service. Recalibrated initial touch values. +* 2015-06-07 timolang@gmail.com c87220d Renamed pixy_helper to pixy_frame. Updated docu of appliaction. added doxygen comments to pixy_{frame,control}.h +* +**************************************************************************************************************************************/ + #include "screen_pixytest.h" #include "button.h" #include "numupdown.h" @@ -7,7 +27,7 @@ #include "system.h" #include "pixy_frame.h" -static volatile enum {detecting, idle,update_servos, update_ledcolor, update_ledcurrent} state; //Current state of the screen state machine +static volatile enum {detecting, idle, update_servos, update_ledcolor, update_ledcurrent} state; //Current state of the screen state machine static BUTTON_STRUCT b_back; @@ -30,313 +50,328 @@ static uint32_t led_maxcurrent; static NUMUPDOWN_STRUCT n_led_powerlimit; -static void b_back_cb(void* button) { - gui_screen_back(); +static void b_back_cb(void* button) +{ + gui_screen_back(); } -static void b_servos_center_cb(void* button) { - if(state==idle) { - servo_x=500; - servo_y=500; - state=update_servos; - } +static void b_servos_center_cb(void* button) +{ + if (state == idle) { + servo_x = 500; + servo_y = 500; + state = update_servos; + } } -static void b_servos_topleft_cb(void* button) { - if(state==idle) { - servo_x=0; - servo_y=0; - state=update_servos; - } +static void b_servos_topleft_cb(void* button) +{ + if (state == idle) { + servo_x = 0; + servo_y = 0; + state = update_servos; + } } -static void b_servos_topright_cb(void* button) { - if(state==idle) { - servo_x=1000; - servo_y=0; - state=update_servos; - } +static void b_servos_topright_cb(void* button) +{ + if (state == idle) { + servo_x = 1000; + servo_y = 0; + state = update_servos; + } } -static void b_servos_bottomleft_cb(void* button) { - if(state==idle) { - servo_x=0; - servo_y=1000; - state=update_servos; - } +static void b_servos_bottomleft_cb(void* button) +{ + if (state == idle) { + servo_x = 0; + servo_y = 1000; + state = update_servos; + } } -static void b_servos_bottomright_cb(void* button) { - if(state==idle) { - servo_x=1000; - servo_y=1000; - state=update_servos; - } +static void b_servos_bottomright_cb(void* button) +{ + if (state == idle) { + servo_x = 1000; + servo_y = 1000; + state = update_servos; + } } -static void b_led_off_cb(void* button) { - if(state==idle) { - led_color=0x000000; - state=update_ledcolor; - } +static void b_led_off_cb(void* button) +{ + if (state == idle) { + led_color = 0x000000; + state = update_ledcolor; + } } -static void b_led_white_cb(void* button) { - if(state==idle) { - led_color=0xFFFFFF; - state=update_ledcolor; - } +static void b_led_white_cb(void* button) +{ + if (state == idle) { + led_color = 0xFFFFFF; + state = update_ledcolor; + } } -static void b_led_red_cb(void* button) { - if(state==idle) { - led_color=0xFF0000; - state=update_ledcolor; - } +static void b_led_red_cb(void* button) +{ + if (state == idle) { + led_color = 0xFF0000; + state = update_ledcolor; + } } -static void b_led_green_cb(void* button) { - if(state==idle) { - led_color=0x00FF00; - state=update_ledcolor; - } +static void b_led_green_cb(void* button) +{ + if (state == idle) { + led_color = 0x00FF00; + state = update_ledcolor; + } } -static void b_led_blue_cb(void* button) { - if(state==idle) { - led_color=0x0000FF; - state=update_ledcolor; - } +static void b_led_blue_cb(void* button) +{ + if (state == idle) { + led_color = 0x0000FF; + state = update_ledcolor; + } } -static void n_led_powerlimit_cb(void* numupdown, int16_t value) { - if(state==idle) { - led_maxcurrent=value; - state=update_ledcurrent; - } +static void n_led_powerlimit_cb(void* numupdown, int16_t value) +{ + if (state == idle) { + led_maxcurrent = value; + state = update_ledcurrent; + } } -static void enter(void* screen) { - tft_clear(WHITE); - - //Back button - b_back.base.x1=10; //Start X of Button - b_back.base.y1=210; //Start Y of Button - b_back.base.x2=AUTO; //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) +static void enter(void* screen) +{ + tft_clear(WHITE); + + //Back button + b_back.base.x1 = 10; //Start X of Button + b_back.base.y1 = 210; //Start Y of Button + b_back.base.x2 = AUTO; //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) - //Servo stuff - #define SERVO_BUTTON_Y 10 - #define SERVO_BUTTON_SPACING 5 - tft_print_line(5,SERVO_BUTTON_Y,BLACK,TRANSPARENT,0,"Servos:"); + //Servo stuff +#define SERVO_BUTTON_Y 10 +#define SERVO_BUTTON_SPACING 5 + tft_print_line(5, SERVO_BUTTON_Y, BLACK, TRANSPARENT, 0, "Servos:"); - b_servos_center.base.x1=55; - b_servos_center.base.y1=SERVO_BUTTON_Y-3; - b_servos_center.base.x2=AUTO; - b_servos_center.base.y2=AUTO; - b_servos_center.txtcolor=WHITE; - b_servos_center.bgcolor=HEX(0xAE1010); - b_servos_center.font=0; - b_servos_center.text="Center"; - b_servos_center.callback=b_servos_center_cb; - gui_button_add(&b_servos_center); + b_servos_center.base.x1 = 55; + b_servos_center.base.y1 = SERVO_BUTTON_Y - 3; + b_servos_center.base.x2 = AUTO; + b_servos_center.base.y2 = AUTO; + b_servos_center.txtcolor = WHITE; + b_servos_center.bgcolor = HEX(0xAE1010); + b_servos_center.font = 0; + b_servos_center.text = "Center"; + b_servos_center.callback = b_servos_center_cb; + gui_button_add(&b_servos_center); - b_servos_topleft.base.x1=b_servos_center.base.x2+SERVO_BUTTON_SPACING; - b_servos_topleft.base.y1=SERVO_BUTTON_Y-3; - b_servos_topleft.base.x2=AUTO; - b_servos_topleft.base.y2=AUTO; - b_servos_topleft.txtcolor=WHITE; - b_servos_topleft.bgcolor=HEX(0xAE1010); - b_servos_topleft.font=0; - b_servos_topleft.text="ToLe"; - b_servos_topleft.callback=b_servos_topleft_cb; - gui_button_add(&b_servos_topleft); + b_servos_topleft.base.x1 = b_servos_center.base.x2 + SERVO_BUTTON_SPACING; + b_servos_topleft.base.y1 = SERVO_BUTTON_Y - 3; + b_servos_topleft.base.x2 = AUTO; + b_servos_topleft.base.y2 = AUTO; + b_servos_topleft.txtcolor = WHITE; + b_servos_topleft.bgcolor = HEX(0xAE1010); + b_servos_topleft.font = 0; + b_servos_topleft.text = "ToLe"; + b_servos_topleft.callback = b_servos_topleft_cb; + gui_button_add(&b_servos_topleft); - b_servos_topright.base.x1=b_servos_topleft.base.x2+SERVO_BUTTON_SPACING; - b_servos_topright.base.y1=SERVO_BUTTON_Y-3; - b_servos_topright.base.x2=AUTO; - b_servos_topright.base.y2=AUTO; - b_servos_topright.txtcolor=WHITE; - b_servos_topright.bgcolor=HEX(0xAE1010); - b_servos_topright.font=0; - b_servos_topright.text="ToRi"; - b_servos_topright.callback=b_servos_topright_cb; - gui_button_add(&b_servos_topright); + b_servos_topright.base.x1 = b_servos_topleft.base.x2 + SERVO_BUTTON_SPACING; + b_servos_topright.base.y1 = SERVO_BUTTON_Y - 3; + b_servos_topright.base.x2 = AUTO; + b_servos_topright.base.y2 = AUTO; + b_servos_topright.txtcolor = WHITE; + b_servos_topright.bgcolor = HEX(0xAE1010); + b_servos_topright.font = 0; + b_servos_topright.text = "ToRi"; + b_servos_topright.callback = b_servos_topright_cb; + gui_button_add(&b_servos_topright); - b_servos_bottomleft.base.x1=b_servos_topright.base.x2+SERVO_BUTTON_SPACING; - b_servos_bottomleft.base.y1=SERVO_BUTTON_Y-3; - b_servos_bottomleft.base.x2=AUTO; - b_servos_bottomleft.base.y2=AUTO; - b_servos_bottomleft.txtcolor=WHITE; - b_servos_bottomleft.bgcolor=HEX(0xAE1010); - b_servos_bottomleft.font=0; - b_servos_bottomleft.text="BoLe"; - b_servos_bottomleft.callback=b_servos_bottomleft_cb; - gui_button_add(&b_servos_bottomleft); + b_servos_bottomleft.base.x1 = b_servos_topright.base.x2 + SERVO_BUTTON_SPACING; + b_servos_bottomleft.base.y1 = SERVO_BUTTON_Y - 3; + b_servos_bottomleft.base.x2 = AUTO; + b_servos_bottomleft.base.y2 = AUTO; + b_servos_bottomleft.txtcolor = WHITE; + b_servos_bottomleft.bgcolor = HEX(0xAE1010); + b_servos_bottomleft.font = 0; + b_servos_bottomleft.text = "BoLe"; + b_servos_bottomleft.callback = b_servos_bottomleft_cb; + gui_button_add(&b_servos_bottomleft); - b_servos_bottomright.base.x1=b_servos_bottomleft.base.x2+SERVO_BUTTON_SPACING; - b_servos_bottomright.base.y1=SERVO_BUTTON_Y-3; - b_servos_bottomright.base.x2=AUTO; - b_servos_bottomright.base.y2=AUTO; - b_servos_bottomright.txtcolor=WHITE; - b_servos_bottomright.bgcolor=HEX(0xAE1010); - b_servos_bottomright.font=0; - b_servos_bottomright.text="BoRi"; - b_servos_bottomright.callback=b_servos_bottomright_cb; - gui_button_add(&b_servos_bottomright); + b_servos_bottomright.base.x1 = b_servos_bottomleft.base.x2 + SERVO_BUTTON_SPACING; + b_servos_bottomright.base.y1 = SERVO_BUTTON_Y - 3; + b_servos_bottomright.base.x2 = AUTO; + b_servos_bottomright.base.y2 = AUTO; + b_servos_bottomright.txtcolor = WHITE; + b_servos_bottomright.bgcolor = HEX(0xAE1010); + b_servos_bottomright.font = 0; + b_servos_bottomright.text = "BoRi"; + b_servos_bottomright.callback = b_servos_bottomright_cb; + gui_button_add(&b_servos_bottomright); - //Led Color stuff - #define LED_COLOR_BUTTON_Y 35 - #define LED_COLOR_BUTTON_SPACING 5 - tft_print_line(5,LED_COLOR_BUTTON_Y,BLACK,TRANSPARENT,0,"Led Color:"); + //Led Color stuff +#define LED_COLOR_BUTTON_Y 35 +#define LED_COLOR_BUTTON_SPACING 5 + tft_print_line(5, LED_COLOR_BUTTON_Y, BLACK, TRANSPARENT, 0, "Led Color:"); - b_led_off.base.x1=85; - b_led_off.base.y1=LED_COLOR_BUTTON_Y-3; - b_led_off.base.x2=AUTO; - b_led_off.base.y2=AUTO; - b_led_off.txtcolor=WHITE; - b_led_off.bgcolor=BLACK; - b_led_off.font=0; - b_led_off.text="Off"; - b_led_off.callback=b_led_off_cb; - gui_button_add(&b_led_off); + b_led_off.base.x1 = 85; + b_led_off.base.y1 = LED_COLOR_BUTTON_Y - 3; + b_led_off.base.x2 = AUTO; + b_led_off.base.y2 = AUTO; + b_led_off.txtcolor = WHITE; + b_led_off.bgcolor = BLACK; + b_led_off.font = 0; + b_led_off.text = "Off"; + b_led_off.callback = b_led_off_cb; + gui_button_add(&b_led_off); - b_led_white.base.x1=b_led_off.base.x2+LED_COLOR_BUTTON_SPACING; - b_led_white.base.y1=LED_COLOR_BUTTON_Y-3; - b_led_white.base.x2=AUTO; - b_led_white.base.y2=AUTO; - b_led_white.txtcolor=BLACK; - b_led_white.bgcolor=HEX(0xEEEEEE); - b_led_white.font=0; - b_led_white.text="White"; - b_led_white.callback=b_led_white_cb; - gui_button_add(&b_led_white); + b_led_white.base.x1 = b_led_off.base.x2 + LED_COLOR_BUTTON_SPACING; + b_led_white.base.y1 = LED_COLOR_BUTTON_Y - 3; + b_led_white.base.x2 = AUTO; + b_led_white.base.y2 = AUTO; + b_led_white.txtcolor = BLACK; + b_led_white.bgcolor = HEX(0xEEEEEE); + b_led_white.font = 0; + b_led_white.text = "White"; + b_led_white.callback = b_led_white_cb; + gui_button_add(&b_led_white); - b_led_red.base.x1=b_led_white.base.x2+LED_COLOR_BUTTON_SPACING; - b_led_red.base.y1=LED_COLOR_BUTTON_Y-3; - b_led_red.base.x2=AUTO; - b_led_red.base.y2=AUTO; - b_led_red.txtcolor=WHITE; - b_led_red.bgcolor=HEX(0xEE0000); - b_led_red.font=0; - b_led_red.text="Red"; - b_led_red.callback=b_led_red_cb; - gui_button_add(&b_led_red); + b_led_red.base.x1 = b_led_white.base.x2 + LED_COLOR_BUTTON_SPACING; + b_led_red.base.y1 = LED_COLOR_BUTTON_Y - 3; + b_led_red.base.x2 = AUTO; + b_led_red.base.y2 = AUTO; + b_led_red.txtcolor = WHITE; + b_led_red.bgcolor = HEX(0xEE0000); + b_led_red.font = 0; + b_led_red.text = "Red"; + b_led_red.callback = b_led_red_cb; + gui_button_add(&b_led_red); - b_led_green.base.x1=b_led_red.base.x2+LED_COLOR_BUTTON_SPACING; - b_led_green.base.y1=LED_COLOR_BUTTON_Y-3; - b_led_green.base.x2=AUTO; - b_led_green.base.y2=AUTO; - b_led_green.txtcolor=WHITE; - b_led_green.bgcolor=HEX(0x00EE00); - b_led_green.font=0; - b_led_green.text="Green"; - b_led_green.callback=b_led_green_cb; - gui_button_add(&b_led_green); + b_led_green.base.x1 = b_led_red.base.x2 + LED_COLOR_BUTTON_SPACING; + b_led_green.base.y1 = LED_COLOR_BUTTON_Y - 3; + b_led_green.base.x2 = AUTO; + b_led_green.base.y2 = AUTO; + b_led_green.txtcolor = WHITE; + b_led_green.bgcolor = HEX(0x00EE00); + b_led_green.font = 0; + b_led_green.text = "Green"; + b_led_green.callback = b_led_green_cb; + gui_button_add(&b_led_green); - b_led_blue.base.x1=b_led_green.base.x2+LED_COLOR_BUTTON_SPACING; - b_led_blue.base.y1=LED_COLOR_BUTTON_Y-3; - b_led_blue.base.x2=AUTO; - b_led_blue.base.y2=AUTO; - b_led_blue.txtcolor=WHITE; - b_led_blue.bgcolor=HEX(0x0000EE); - b_led_blue.font=0; - b_led_blue.text="Blue"; - b_led_blue.callback=b_led_blue_cb; - gui_button_add(&b_led_blue); + b_led_blue.base.x1 = b_led_green.base.x2 + LED_COLOR_BUTTON_SPACING; + b_led_blue.base.y1 = LED_COLOR_BUTTON_Y - 3; + b_led_blue.base.x2 = AUTO; + b_led_blue.base.y2 = AUTO; + b_led_blue.txtcolor = WHITE; + b_led_blue.bgcolor = HEX(0x0000EE); + b_led_blue.font = 0; + b_led_blue.text = "Blue"; + b_led_blue.callback = b_led_blue_cb; + gui_button_add(&b_led_blue); - //Led MaxPower stuff - #define LED_POWER_BUTTON_Y 70 - tft_print_line(5,LED_POWER_BUTTON_Y,BLACK,TRANSPARENT,0,"Led Maximum Current:"); + //Led MaxPower stuff +#define LED_POWER_BUTTON_Y 70 + tft_print_line(5, LED_POWER_BUTTON_Y, BLACK, TRANSPARENT, 0, "Led Maximum Current:"); - //Num up down test - n_led_powerlimit.x=160; - n_led_powerlimit.y=LED_POWER_BUTTON_Y-7; - n_led_powerlimit.fgcolor=WHITE; - n_led_powerlimit.value = 10; - n_led_powerlimit.max=40; - n_led_powerlimit.min =0; - n_led_powerlimit.callback=n_led_powerlimit_cb; - gui_numupdown_add(&n_led_powerlimit); + //Num up down test + n_led_powerlimit.x = 160; + n_led_powerlimit.y = LED_POWER_BUTTON_Y - 7; + n_led_powerlimit.fgcolor = WHITE; + n_led_powerlimit.value = 10; + n_led_powerlimit.max = 40; + n_led_powerlimit.min = 0; + n_led_powerlimit.callback = n_led_powerlimit_cb; + gui_numupdown_add(&n_led_powerlimit); - state=detecting; + state = detecting; } -static void leave(void* screen) { - gui_button_remove(&b_back); - gui_button_remove(&b_servos_center); - gui_button_remove(&b_servos_topleft); - gui_button_remove(&b_servos_topright); - gui_button_remove(&b_servos_bottomleft); - gui_button_remove(&b_servos_bottomright); - gui_button_remove(&b_led_off); - gui_button_remove(&b_led_white); - gui_button_remove(&b_led_red); - gui_button_remove(&b_led_green); - gui_button_remove(&b_led_blue); - gui_numupdown_remove(&n_led_powerlimit); +static void leave(void* screen) +{ + gui_button_remove(&b_back); + gui_button_remove(&b_servos_center); + gui_button_remove(&b_servos_topleft); + gui_button_remove(&b_servos_topright); + gui_button_remove(&b_servos_bottomleft); + gui_button_remove(&b_servos_bottomright); + gui_button_remove(&b_led_off); + gui_button_remove(&b_led_white); + gui_button_remove(&b_led_red); + gui_button_remove(&b_led_green); + gui_button_remove(&b_led_blue); + gui_numupdown_remove(&n_led_powerlimit); } -static void update(void* screen) { - switch(state) { - case detecting: //Detecting State: Where we try to connect to the pixy - if(pixy_init()==0) { //Pixy connection ok - int32_t response; - int return_value; - return_value = pixy_command("stop", END_OUT_ARGS, &response, END_IN_ARGS); - pixy_led_set_max_current(10); +static void update(void* screen) +{ + switch (state) { + case detecting: //Detecting State: Where we try to connect to the pixy + if (pixy_init() == 0) { //Pixy connection ok + int32_t response; + int return_value; + return_value = pixy_command("stop", END_OUT_ARGS, &response, END_IN_ARGS); + pixy_led_set_max_current(10); - state = idle; //Go to next state - } - break; - case idle: - pixy_service(); - break; - case update_servos: - pixy_rcs_set_position(0,servo_x); - pixy_rcs_set_position(1,servo_y); - state = idle; - break; + state = idle; //Go to next state + } - case update_ledcolor: - { - int32_t response; - int return_value; - return_value = pixy_command("led_set", INT32(led_color), END_OUT_ARGS, &response, END_IN_ARGS); - state = idle; - } - break; + break; - case update_ledcurrent: - pixy_led_set_max_current(led_maxcurrent); - state = idle; - break; - } + case idle: + pixy_service(); + break; + + case update_servos: + pixy_rcs_set_position(0, servo_x); + pixy_rcs_set_position(1, servo_y); + state = idle; + break; + + case update_ledcolor: { + int32_t response; + int return_value; + return_value = pixy_command("led_set", INT32(led_color), END_OUT_ARGS, &response, END_IN_ARGS); + state = idle; + } + break; + + case update_ledcurrent: + pixy_led_set_max_current(led_maxcurrent); + state = idle; + break; + } } static SCREEN_STRUCT screen = { - enter, - leave, - update + enter, + leave, + update }; -SCREEN_STRUCT* get_screen_pixytest() { - return &screen; +SCREEN_STRUCT* get_screen_pixytest() +{ + return &screen; } - - - diff --git a/common/app/screen_pixytest.h b/common/app/screen_pixytest.h index b92df49..b711d0b 100644 --- a/common/app/screen_pixytest.h +++ b/common/app/screen_pixytest.h @@ -1,3 +1,18 @@ +/************************************************************************************************************************************** +* Project: discoverpixy +* Website: https://github.com/t-moe/discoverpixy +* Authors: Aaron Schmocker, Timo Lang +* Institution: BFH Bern University of Applied Sciences +* File: common/app/screen_pixytest.h +* +* Version History: +* Date Autor Email SHA Changes +* 2015-04-27 timolang@gmail.com cf72baa Introduced a Screen (sub) module and divided app into multiple screens. +* 2015-05-10 timolang@gmail.com 21edc56 Added doxyfile (doxygen) for the common folder. Started with doxygen comments for app and tft module. +* 2015-05-15 timolang@gmail.com 9a16865 Added doxgen comments to filesyste, checkbox, numupdown and screen module. And some minor changes to the other modules. +* +**************************************************************************************************************************************/ + #include "screen.h" /** diff --git a/common/app/screen_tracking.c b/common/app/screen_tracking.c index cf6af59..974d4e7 100644 --- a/common/app/screen_tracking.c +++ b/common/app/screen_tracking.c @@ -1,3 +1,22 @@ +/************************************************************************************************************************************** +* Project: discoverpixy +* Website: https://github.com/t-moe/discoverpixy +* Authors: Aaron Schmocker, Timo Lang +* Institution: BFH Bern University of Applied Sciences +* File: common/app/screen_tracking.c +* +* Version History: +* Date Autor Email SHA Changes +* 2015-05-16 timolang@gmail.com e46314b Added Tracking Screen and implemented "Reference Tracking" and "Color Region Selection" +* 2015-05-25 timolang@gmail.com 8088014 Updated Tracking Screen so that the implementations are separated into different method groups. +* 2015-06-06 aaron@duckpond.ch 8c264c2 Comment refactoring, updated PID values +* 2015-06-06 aaron@duckpond.ch a04cda9 Refactured comments and implemented a bugfix for the PID controller +* 2015-06-07 aaron@duckpond.ch 802d3df Fixed pid controller and refactored code +* 2015-06-07 aaron@duckpond.ch 3d98ca9 Minor changes +* 2015-06-07 timolang@gmail.com c87220d Renamed pixy_helper to pixy_frame. Updated docu of appliaction. added doxygen comments to pixy_{frame,control}.h +* +**************************************************************************************************************************************/ + #include "screen_tracking.h" #include "pixy_control.h" #include "button.h" @@ -14,14 +33,16 @@ static CHECKBOX_STRUCT c_frame_toggle; //Checkbox to toggle video data on/off static TOUCH_AREA_STRUCT a_area; //Touch area for the color region selection //Callback for when the user presses the "back" button -static void b_back_cb(void* button) { - gui_screen_back(); //navigate back to the previous screen +static void b_back_cb(void* button) +{ + gui_screen_back(); //navigate back to the previous screen } static volatile bool frame_visible = false; //Whether or not the video data should be displayed -static void c_frame_toggle_cb(void *checkbox, bool checked) { - frame_visible=checked; //Set the visibility of the frame to the checked state of the checkbox - //Frame will be drawn in the main loop below +static void c_frame_toggle_cb(void* checkbox, bool checked) +{ + frame_visible = checked; //Set the visibility of the frame to the checked state of the checkbox + //Frame will be drawn in the main loop below } static enum {detecting, init, tracking, preselecting, abortselecting, selecting, selected, error} state; //Current state of the screen state machine @@ -31,12 +52,13 @@ static POINT_STRUCT point2; //End point of the rectangle selected by the user (c static bool point1_valid; //Whether or not we have a valid first point //Callback for when the user presses the "select color" button -static void b_select_cb(void* button) { - if(state==selecting) { //we're currently selecting a color region - state = abortselecting; //Abort selecting!! - } else if (state==tracking) { //we're currently watching the tracking - state = preselecting; //start selecting - } +static void b_select_cb(void* button) +{ + if (state == selecting) { //we're currently selecting a color region + state = abortselecting; //Abort selecting!! + } else if (state == tracking) { //we're currently watching the tracking + state = preselecting; //start selecting + } } //Video Region properties @@ -50,34 +72,38 @@ static void b_select_cb(void* button) { //Callback for when the user touches the frame area to select a color region. //Note: It doesn't matter in which direction the user draws the rectangle, we'll normalize the coordinates later -static void touchCB(void* touchArea, TOUCH_ACTION triggeredAction) { - POINT_STRUCT p = touch_get_last_point(); - switch(triggeredAction) { - case PEN_DOWN: //The user just put down the pen - point1.x = p.x-FRAME_START_X; //Calculate x-Coordinate relative to frame start - point1.y = p.y-FRAME_START_Y; //Calculate y-Coordinate relative to frame start - point1_valid= true; //The point1 is now valid - break; - case PEN_UP: //The user took the pen away - if(point1_valid) { //only execute if point1 is valid - point2.x = p.x-FRAME_START_X; //Calculate x-Coordinate relative to frame start - point2.y = p.y-FRAME_START_Y; //Calculate y-Coordinate relative to frame start - state = selected; - } - break; - } +static void touchCB(void* touchArea, TOUCH_ACTION triggeredAction) +{ + POINT_STRUCT p = touch_get_last_point(); + + switch (triggeredAction) { + case PEN_DOWN: //The user just put down the pen + point1.x = p.x - FRAME_START_X; //Calculate x-Coordinate relative to frame start + point1.y = p.y - FRAME_START_Y; //Calculate y-Coordinate relative to frame start + point1_valid = true; //The point1 is now valid + break; + + case PEN_UP: //The user took the pen away + if (point1_valid) { //only execute if point1 is valid + point2.x = p.x - FRAME_START_X; //Calculate x-Coordinate relative to frame start + point2.y = p.y - FRAME_START_Y; //Calculate y-Coordinate relative to frame start + state = selected; + } + + break; + } } //Prototype for tracking start/stop methods typedef void (*TRACKING_VOID_CALLBACK)(void* tracking_config); //Prototype for tracking update method -typedef void (*TRACKING_BLOCK_CALLBACK)(void* tracking_config, struct Block* blocks, int num_blocks ); +typedef void (*TRACKING_BLOCK_CALLBACK)(void* tracking_config, struct Block* blocks, int num_blocks); //Structure to save callbacks and settings of a tracking implementation typedef struct { - TRACKING_VOID_CALLBACK start; - TRACKING_VOID_CALLBACK stop; - TRACKING_BLOCK_CALLBACK update; + TRACKING_VOID_CALLBACK start; + TRACKING_VOID_CALLBACK stop; + TRACKING_BLOCK_CALLBACK update; } TRACKING_CONFIG_STRUCT; //Methods for our tracking implementation ahead @@ -85,45 +111,48 @@ static int16_t servo_x = 0; static int16_t servo_y = 0; //Method/Callback to start our tracking -void tracking_our_start(void* tracking_config) { - //Activate pixy's data send program - int32_t response; - int return_value; +void tracking_our_start(void* tracking_config) +{ + //Activate pixy's data send program + int32_t response; + int return_value; servo_x = servo_y = 500; // set a default value of 500 - pixy_rcs_set_position(0, servo_x); // set default + pixy_rcs_set_position(0, servo_x); // set default pixy_rcs_set_position(1, servo_y); // set default - return_value = pixy_command("runprog", INT8(0), END_OUT_ARGS, &response, END_IN_ARGS); + return_value = pixy_command("runprog", INT8(0), END_OUT_ARGS, &response, END_IN_ARGS); } //Method/Callback to stop our tracking -void tracking_our_stop(void* tracking_config) { - //Stop pixy's data send programm - int32_t response; - int return_value; - return_value = pixy_command("stop", END_OUT_ARGS, &response, END_IN_ARGS); +void tracking_our_stop(void* tracking_config) +{ + //Stop pixy's data send programm + int32_t response; + int return_value; + return_value = pixy_command("stop", END_OUT_ARGS, &response, END_IN_ARGS); } //Method/Callback to calculate one step of our tracking -void tracking_our_update(void* tracking_config, struct Block* blocks, int num_blocks) { +void tracking_our_update(void* tracking_config, struct Block* blocks, int num_blocks) +{ - if(num_blocks <= 0){ // Check if there are blocks available + if (num_blocks <= 0) { // Check if there are blocks available return; // When there are none, do nothing } - + uint16_t x = blocks[0].x; // Get x coordinate of the biggest object uint16_t y = blocks[0].y; // Get y coordinate of the biggest object - int16_t xset = 0; + int16_t xset = 0; int16_t yset = 0; xset = (servo_x + pixy_PID_X((FRAME_WIDTH / 2), x)); // calculate the PID output for x yset = (servo_y - pixy_PID_Y((FRAME_HEIGHT / 2), y)); // calculate the PID output for y - + xset = (xset < 0) ? 0 : xset; // x lower boundary check xset = (xset > 1000) ? 1000 : xset; // x upper boundary check - + yset = (yset < 0) ? 0 : yset; // y lower boundary check yset = (yset > 1000) ? 1000 : yset; // y upper boundary check @@ -136,245 +165,257 @@ void tracking_our_update(void* tracking_config, struct Block* blocks, int num_bl //Variable which stores all the callbacks and settings for our tracking implementation static TRACKING_CONFIG_STRUCT tracking_our = { - tracking_our_start, - tracking_our_stop, - tracking_our_update + tracking_our_start, + tracking_our_stop, + tracking_our_update }; //Methods for reference tracking implementation ahead //Method/Callback to start reference tracking -void tracking_reference_start(void* tracking_config) { - //Run reference tracking - int32_t response; - int return_value; - return_value = pixy_command("runprog", INT8(2), END_OUT_ARGS, &response, END_IN_ARGS); +void tracking_reference_start(void* tracking_config) +{ + //Run reference tracking + int32_t response; + int return_value; + return_value = pixy_command("runprog", INT8(2), END_OUT_ARGS, &response, END_IN_ARGS); } //Method/Callback to stop reference tracking -void tracking_reference_stop(void* tracking_config) { - //Stop reference tracking - int32_t response; - int return_value; - return_value = pixy_command("stop", END_OUT_ARGS, &response, END_IN_ARGS); +void tracking_reference_stop(void* tracking_config) +{ + //Stop reference tracking + int32_t response; + int return_value; + return_value = pixy_command("stop", END_OUT_ARGS, &response, END_IN_ARGS); } //Method/Callback to calculate one step of the reference tracking -void tracking_reference_update(void* tracking_config, struct Block* blocks, int num_blocks) { - //Nothing to do here. Pixy does it all. +void tracking_reference_update(void* tracking_config, struct Block* blocks, int num_blocks) +{ + //Nothing to do here. Pixy does it all. } //Variable which stores all the callbacks and settings for the reference tracking implementation static TRACKING_CONFIG_STRUCT tracking_reference = { - tracking_reference_start, - tracking_reference_stop, - tracking_reference_update + tracking_reference_start, + tracking_reference_stop, + tracking_reference_update }; //Pointer to the currently active tracking implementation. See also tracking_set_mode static TRACKING_CONFIG_STRUCT* tracking_current; //Method to set the current tracking implementation. This function is exported and should be called before getting the screen -void tracking_set_mode(enum Tracking_Implementation impl) { - //Depending on the enum value let tracking_current point to a different setting/callback structure - switch(impl) { - case OUR_TRACKING: - tracking_current = &tracking_our; - break; - case REFERENCE_TRACKING: - tracking_current = &tracking_reference; - break; - default: - tracking_current=NULL; - break; - } +void tracking_set_mode(enum Tracking_Implementation impl) +{ + //Depending on the enum value let tracking_current point to a different setting/callback structure + switch (impl) { + case OUR_TRACKING: + tracking_current = &tracking_our; + break; + + case REFERENCE_TRACKING: + tracking_current = &tracking_reference; + break; + + default: + tracking_current = NULL; + break; + } } //Callback for when the screen is entered/loaded -static void enter(void* screen) { - tft_clear(WHITE); - - //"Back" button - b_back.base.x1=5; //Start X of Button - b_back.base.y1=5; //Start Y of Button - b_back.base.x2=AUTO; //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) +static void enter(void* screen) +{ + tft_clear(WHITE); + + //"Back" button + b_back.base.x1 = 5; //Start X of Button + b_back.base.y1 = 5; //Start Y of Button + b_back.base.x2 = AUTO; //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) - //"Select color" button - b_select.base.x1=150; - b_select.base.y1=5; - b_select.base.x2=AUTO; - b_select.base.y2=AUTO; - b_select.txtcolor=WHITE; - b_select.bgcolor=HEX(0xAE1010); - b_select.font=0; - b_select.text="Select Color"; - b_select.callback=b_select_cb; - gui_button_add(&b_select); + //"Select color" button + b_select.base.x1 = 150; + b_select.base.y1 = 5; + b_select.base.x2 = AUTO; + b_select.base.y2 = AUTO; + b_select.txtcolor = WHITE; + b_select.bgcolor = HEX(0xAE1010); + b_select.font = 0; + b_select.text = "Select Color"; + b_select.callback = b_select_cb; + gui_button_add(&b_select); - //"Frame visible" checkbox - c_frame_toggle.base.x1 = 50; - c_frame_toggle.base.x2 = 50+16; - c_frame_toggle.base.y1 = 5; - c_frame_toggle.base.y2 = 5+16; - c_frame_toggle.checked = frame_visible; - c_frame_toggle.fgcolor = CHECKBOX_WIN_FG_COLOR; - c_frame_toggle.callback = c_frame_toggle_cb; - gui_checkbox_add(&c_frame_toggle); - tft_print_line(73,8,BLACK,TRANSPARENT,0,"Show Video"); + //"Frame visible" checkbox + c_frame_toggle.base.x1 = 50; + c_frame_toggle.base.x2 = 50 + 16; + c_frame_toggle.base.y1 = 5; + c_frame_toggle.base.y2 = 5 + 16; + c_frame_toggle.checked = frame_visible; + c_frame_toggle.fgcolor = CHECKBOX_WIN_FG_COLOR; + c_frame_toggle.callback = c_frame_toggle_cb; + gui_checkbox_add(&c_frame_toggle); + tft_print_line(73, 8, BLACK, TRANSPARENT, 0, "Show Video"); - //Area to select a "color region" - a_area.hookedActions = PEN_DOWN | PEN_UP; - a_area.x1 = FRAME_START_X; - a_area.y1 = FRAME_START_Y; - a_area.x2 = FRAME_END_X; - a_area.y2 = FRAME_END_Y; - a_area.callback = touchCB; + //Area to select a "color region" + a_area.hookedActions = PEN_DOWN | PEN_UP; + a_area.x1 = FRAME_START_X; + a_area.y1 = FRAME_START_Y; + a_area.x2 = FRAME_END_X; + a_area.y2 = FRAME_END_Y; + a_area.callback = touchCB; //Do not register it here, we do that later - if(tracking_current==NULL) { - state = error; - } else { - state = detecting; //Start with the detecting state - } + if (tracking_current == NULL) { + state = error; + } else { + state = detecting; //Start with the detecting state + } } //Callback for when the screen is left/unloaded -static void leave(void* screen) { - //Remove buttons and checkbox - gui_button_remove(&b_back); - gui_button_remove(&b_select); - gui_checkbox_remove(&c_frame_toggle); +static void leave(void* screen) +{ + //Remove buttons and checkbox + gui_button_remove(&b_back); + gui_button_remove(&b_select); + gui_checkbox_remove(&c_frame_toggle); - if(state==selecting) { //the user left the screen in the "selecting" phase - touch_unregister_area(&a_area); //remove the touch area - } + if (state == selecting) { //the user left the screen in the "selecting" phase + touch_unregister_area(&a_area); //remove the touch area + } - if(state==tracking) { //the user left the screen in the "tracking" phase - tracking_current->stop(tracking_current); //stop tracking - pixy_led_set_RGB(0,0,0); - } + if (state == tracking) { //the user left the screen in the "tracking" phase + tracking_current->stop(tracking_current); //stop tracking + pixy_led_set_RGB(0, 0, 0); + } } //Callback for when the screen should be updated //This is the main loop of the screen. This method will be called repeatedly -static void update(void* screen) { - switch(state) { - case detecting: //Detecting State: Where we try to connect to the pixy - if(pixy_init()==0) { //Pixy connection ok - state = init; //Go to next state - } - break; +static void update(void* screen) +{ + switch (state) { + case detecting: //Detecting State: Where we try to connect to the pixy + if (pixy_init() == 0) { //Pixy connection ok + state = init; //Go to next state + } - case init: //Init State: Where we start the tracking - tracking_current->start(tracking_current); - state=tracking; - break; + break; - case tracking: //Tracking state: Where we render the frame and the tracked objects - pixy_service(); //Receive events (e.g. block-data) from pixy + case init: //Init State: Where we start the tracking + tracking_current->start(tracking_current); + state = tracking; + break; - if(pixy_blocks_are_new()) { //There are new blocks available - if(frame_visible) { //If the user want's us to draw the video data - pixy_render_full_frame(FRAME_START_X,FRAME_START_Y); - } else { //the user want's a colored background - tft_fill_rectangle(FRAME_START_X,FRAME_START_Y,FRAME_END_X,FRAME_END_Y,RGB(200,200,200)); - } + case tracking: //Tracking state: Where we render the frame and the tracked objects + pixy_service(); //Receive events (e.g. block-data) from pixy - #define BLOCK_BUFFER_SIZE 5 //The maximum amount of blocks that we want to receive - struct Block blocks[BLOCK_BUFFER_SIZE]; //Storage to receive blocks from pixy - int blocks_received= pixy_get_blocks(BLOCK_BUFFER_SIZE,blocks); //Try to receive up to BLOCK_BUFFER_SIZE Blocks from pixy + if (pixy_blocks_are_new()) { //There are new blocks available + if (frame_visible) { //If the user want's us to draw the video data + pixy_render_full_frame(FRAME_START_X, FRAME_START_Y); + } else { //the user want's a colored background + tft_fill_rectangle(FRAME_START_X, FRAME_START_Y, FRAME_END_X, FRAME_END_Y, RGB(200, 200, 200)); + } - if(blocks_received>=0) { //block receiving ok - tracking_current->update(tracking_current,blocks,blocks_received); //apply tracking +#define BLOCK_BUFFER_SIZE 5 //The maximum amount of blocks that we want to receive + struct Block blocks[BLOCK_BUFFER_SIZE]; //Storage to receive blocks from pixy + int blocks_received = pixy_get_blocks(BLOCK_BUFFER_SIZE, blocks); //Try to receive up to BLOCK_BUFFER_SIZE Blocks from pixy - //Draw blocks - for(int i=0; ix-1+FRAME_START_X -block->width/2; //Calculate x-Coordinate on the display - uint16_t y = block->y-1+FRAME_START_Y -block->height/2; //Calculate y-Coordinate on the display - tft_draw_rectangle(x,y,x+block->width-1, y+block->height-1,WHITE); //Draw a white rectangle - } - } - } - break; + if (blocks_received >= 0) { //block receiving ok + tracking_current->update(tracking_current, blocks, blocks_received); //apply tracking - case preselecting: //Pre-Selecting State: Where we set up the color region selection - { - tracking_current->stop(tracking_current); //Stop tracking + //Draw blocks + for (int i = 0; i < blocks_received; i++) { //for each received block + struct Block* block = &(blocks[i]); + //block.x and block.y are the center coordinates of the object relative to the camera origin. + uint16_t x = block->x - 1 + FRAME_START_X - block->width / 2; //Calculate x-Coordinate on the display + uint16_t y = block->y - 1 + FRAME_START_Y - block->height / 2; //Calculate y-Coordinate on the display + tft_draw_rectangle(x, y, x + block->width - 1, y + block->height - 1, WHITE); //Draw a white rectangle + } + } + } - pixy_render_full_frame(FRAME_START_X,FRAME_START_Y); //Render one frame + break; - touch_register_area(&a_area); //Register touch area and receive events from now on - point1_valid=false; //we start with an invalid point1 + case preselecting: { //Pre-Selecting State: Where we set up the color region selection + tracking_current->stop(tracking_current); //Stop tracking - b_select.text="Abort"; //Change the button text to "Abort" - gui_button_redraw(&b_select); //redraw button + pixy_render_full_frame(FRAME_START_X, FRAME_START_Y); //Render one frame - state = selecting; //The user can now select a region - } - break; + touch_register_area(&a_area); //Register touch area and receive events from now on + point1_valid = false; //we start with an invalid point1 - case selected: //Selected State: Where we send the users selection to pixy - { - //Ensure that (x1,y1) represent the top-left point and (x2,y2) the bottom-right. - unsigned int tmp; - if(point1.x > point2.x){ - tmp = point1.x; - point1.x = point2.x; - point2.x = tmp; - } + b_select.text = "Abort"; //Change the button text to "Abort" + gui_button_redraw(&b_select); //redraw button - if(point1.y > point2.y){ - tmp = point1.y; - point1.y = point2.y; - point2.y = tmp; - } - //Send pixy the selected region - pixy_cc_set_region(1,point1.x,point1.y,point2.x-point1.x,point2.y-point1.y); - } - //no break here: We want the following code to be executed as well + state = selecting; //The user can now select a region + } + break; - case abortselecting: //Abort-Selecting State: Where we deinitialize the stuff we used for region selection - { - touch_unregister_area(&a_area); //Remove the touch area. We'll no longer receive touch events + case selected: { //Selected State: Where we send the users selection to pixy + //Ensure that (x1,y1) represent the top-left point and (x2,y2) the bottom-right. + unsigned int tmp; - b_select.text="Select Color"; //Change the button text back to "Select Color" - gui_button_redraw(&b_select); //redraw button + if (point1.x > point2.x) { + tmp = point1.x; + point1.x = point2.x; + point2.x = tmp; + } - tracking_current->start(tracking_current); //Start tracking again - state=tracking; - } - break; + if (point1.y > point2.y) { + tmp = point1.y; + point1.y = point2.y; + point2.y = tmp; + } - case selecting: //Selecting State: Where we wait on the user to select a color region - pixy_service(); //receive pixy events - //wait on user to select the image area - break; + //Send pixy the selected region + pixy_cc_set_region(1, point1.x, point1.y, point2.x - point1.x, point2.y - point1.y); + } - case error: //Error State: Where we show an error message and leave the user no other choice than to click the backbutton - //wait on user to click the back button - break; - } + //no break here: We want the following code to be executed as well + + case abortselecting: { //Abort-Selecting State: Where we deinitialize the stuff we used for region selection + touch_unregister_area(&a_area); //Remove the touch area. We'll no longer receive touch events + + b_select.text = "Select Color"; //Change the button text back to "Select Color" + gui_button_redraw(&b_select); //redraw button + + tracking_current->start(tracking_current); //Start tracking again + state = tracking; + } + break; + + case selecting: //Selecting State: Where we wait on the user to select a color region + pixy_service(); //receive pixy events + //wait on user to select the image area + break; + + case error: //Error State: Where we show an error message and leave the user no other choice than to click the backbutton + //wait on user to click the back button + break; + } } //Declare screen callbacks static SCREEN_STRUCT screen = { - enter, - leave, - update + enter, + leave, + update }; -SCREEN_STRUCT* get_screen_tracking() { - return &screen; +SCREEN_STRUCT* get_screen_tracking() +{ + return &screen; } diff --git a/common/app/screen_tracking.h b/common/app/screen_tracking.h index 5a2dbde..77b3d87 100644 --- a/common/app/screen_tracking.h +++ b/common/app/screen_tracking.h @@ -1,3 +1,16 @@ +/************************************************************************************************************************************** +* Project: discoverpixy +* Website: https://github.com/t-moe/discoverpixy +* Authors: Aaron Schmocker, Timo Lang +* Institution: BFH Bern University of Applied Sciences +* File: common/app/screen_tracking.h +* +* Version History: +* Date Autor Email SHA Changes +* 2015-05-16 timolang@gmail.com e46314b Added Tracking Screen and implemented "Reference Tracking" and "Color Region Selection" +* +**************************************************************************************************************************************/ + #include "screen.h" /** @@ -16,8 +29,8 @@ * Enum which contains the available tracking implementations */ enum Tracking_Implementation { - OUR_TRACKING, //!< Our own tracking PID implementation - REFERENCE_TRACKING//!< Pixy's internal tracking implementation + OUR_TRACKING, //!< Our own tracking PID implementation + REFERENCE_TRACKING//!< Pixy's internal tracking implementation }; /** diff --git a/common/filesystem/filesystem.c b/common/filesystem/filesystem.c index 9d88b3b..555c667 100644 --- a/common/filesystem/filesystem.c +++ b/common/filesystem/filesystem.c @@ -1,38 +1,56 @@ +/************************************************************************************************************************************** +* Project: discoverpixy +* Website: https://github.com/t-moe/discoverpixy +* Authors: Aaron Schmocker, Timo Lang +* Institution: BFH Bern University of Applied Sciences +* File: common/filesystem/filesystem.c +* +* Version History: +* Date Autor Email SHA Changes +* 2015-05-10 timolang@gmail.com e2bce8f Added filesystem module, tests and implementation for it in emulator. +* 2015-05-15 timolang@gmail.com 9a16865 Added doxgen comments to filesyste, checkbox, numupdown and screen module. And some minor changes to the other modules. +* +**************************************************************************************************************************************/ + #include "filesystem.h" #include "ll_filesystem.h" -bool filesystem_init() { - return ll_filesystem_init(); +bool filesystem_init() +{ + return ll_filesystem_init(); } -DIRECTORY_STRUCT* filesystem_dir_open(const char* path) { - return ll_filesystem_dir_open(path); +DIRECTORY_STRUCT* filesystem_dir_open(const char* path) +{ + return ll_filesystem_dir_open(path); } -void filesystem_dir_close(DIRECTORY_STRUCT* dir) { - ll_filesystem_dir_close(dir); +void filesystem_dir_close(DIRECTORY_STRUCT* dir) +{ + ll_filesystem_dir_close(dir); } -FILE_HANDLE* filesystem_file_open(const char* filename) { - return ll_filesystem_file_open(filename); +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); +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_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_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); +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 bb7b413..3a63f68 100644 --- a/common/filesystem/filesystem.h +++ b/common/filesystem/filesystem.h @@ -1,3 +1,18 @@ +/************************************************************************************************************************************** +* Project: discoverpixy +* Website: https://github.com/t-moe/discoverpixy +* Authors: Aaron Schmocker, Timo Lang +* Institution: BFH Bern University of Applied Sciences +* File: common/filesystem/filesystem.h +* +* Version History: +* Date Autor Email SHA Changes +* 2015-04-03 timolang@gmail.com 51089aa Refactored Project Structure for use with emulator +* 2015-05-10 timolang@gmail.com e2bce8f Added filesystem module, tests and implementation for it in emulator. +* 2015-05-15 timolang@gmail.com 9a16865 Added doxgen comments to filesyste, checkbox, numupdown and screen module. And some minor changes to the other modules. +* +**************************************************************************************************************************************/ + #ifndef FILESYSTEM_H #define FILESYSTEM_H @@ -15,57 +30,57 @@ * See http://en.wikipedia.org/wiki/Design_of_the_FAT_file_system#attributes for detailed description */ typedef enum { - F_RDO=0x01,//!< File is readonly. You cannot write to it - F_HID=0x02,//!< File is hidden - F_SYS=0x04,//!< File is a system file - F_DIR=0x10,//!< It's a directory and not a file - F_ARC=0x20 //!< File has the archive flag set (probably unused) + F_RDO = 0x01, //!< File is readonly. You cannot write to it + F_HID = 0x02, //!< File is hidden + F_SYS = 0x04, //!< File is a system file + F_DIR = 0x10, //!< It's a directory and not a file + F_ARC = 0x20 //!< File has the archive flag set (probably unused) } FILE_ATTRIBUTES; /** * Structure which represents last modified date of a file / directory */ typedef struct { - unsigned year : 7; //!< year from 1980 (0..127) - unsigned month: 4; //!< month (1..12) - unsigned day: 5; //!< day (1..31) + unsigned year : 7; //!< year from 1980 (0..127) + unsigned month: 4; //!< month (1..12) + unsigned day: 5; //!< day (1..31) } FILE_DATE_STRUCT; /** * Structure which represents last modified time of a file / directory */ typedef struct { - unsigned hour : 5; //!< hour (0..23) - unsigned min: 6; //!< minute (0..59 - unsigned sec: 5; //!< second/2 (0..29) + unsigned hour : 5; //!< hour (0..23) + unsigned min: 6; //!< minute (0..59 + unsigned sec: 5; //!< second/2 (0..29) } FILE_TIME_STRUCT; /** * Structure which represents a file/directory entry. \sa DIRECTORY_STRUCT */ typedef struct { - uint32_t fsize; //!< File size in bytes. 0 for directories - FILE_DATE_STRUCT fdate; //!< Last modified date - FILE_TIME_STRUCT ftime; //!< Last modified time - uint8_t fattrib; //!< File/Directory Attributes - char* fname; //!< File/Directory name + uint32_t fsize; //!< File size in bytes. 0 for directories + FILE_DATE_STRUCT fdate; //!< Last modified date + FILE_TIME_STRUCT ftime; //!< Last modified time + uint8_t fattrib; //!< File/Directory Attributes + char* fname; //!< File/Directory name } FILE_STRUCT; /** * Structure which represents an open directory with all it's entries. \sa filesystem_dir_open */ typedef struct { - const char* path; //!< Directory path (absolute) - uint16_t num_files; //!< Number of files/directories in this directory - FILE_STRUCT* files; //!< An array with \ref num_files FILE_STRUCT entries + const char* path; //!< Directory path (absolute) + uint16_t num_files; //!< Number of files/directories in this directory + FILE_STRUCT* files; //!< An array with \ref num_files FILE_STRUCT entries } DIRECTORY_STRUCT; /** * Structure which represents an open file. \sa filesystem_file_open */ typedef struct { - const char* fname; //!< The absolute file name - uint32_t fpos; //!< The current byte-position in the file. \sa filesystem_file_seek + const char* fname; //!< The absolute file name + uint32_t fpos; //!< The current byte-position in the file. \sa filesystem_file_seek uint32_t fsize; //!< The total file size in bytes } FILE_HANDLE; @@ -73,11 +88,11 @@ typedef struct { * Enum to represent the success or error-code of the filesystem_file_* functions */ typedef enum { - F_OK, //!< Everything ok - F_EOF, //!< The write/read operation tried to write/read past the end of the file. This is not a fatal error. - F_EACCESS, //!< The file can not be read/written due to access problems. This is a fatal error. - F_INVALIDPARAM,//!< You passed invalid parameters to the function - F_DISKERROR //!< A lowlevel disk-error occoured. This is a fatal error. + F_OK, //!< Everything ok + F_EOF, //!< The write/read operation tried to write/read past the end of the file. This is not a fatal error. + F_EACCESS, //!< The file can not be read/written due to access problems. This is a fatal error. + F_INVALIDPARAM,//!< You passed invalid parameters to the function + F_DISKERROR //!< A lowlevel disk-error occoured. This is a fatal error. } FILE_STATUS; /** @@ -144,4 +159,3 @@ FILE_STATUS filesystem_file_write(FILE_HANDLE* handle, uint8_t* buf, uint32_t si /*@}*/ #endif /* FILESYSTEM_H */ - diff --git a/common/gui/button.c b/common/gui/button.c index 8abffcb..07a5d53 100644 --- a/common/gui/button.c +++ b/common/gui/button.c @@ -1,154 +1,188 @@ -#include "tft.h" -#include "touch.h" -#include "button.h" -#include - -/* The Idea is as follows: - * When the user add's a button we create a touch area for that region and wait for PEN_DOWN events. - * Once the user puts the pen down in this area we'll redraw the button with different shadows (feedback) - * and we'll now wait on PEN_UP or PEN_LEAVE events. - * If the user takes the pen away while in the area (PEN_UP), we call the provided user callback - * Otherwise (PEN_LEAVE) we only restore the initial shadows - */ - -/* Possible improvements: - * Move the button by 1 pixel while he is pressed, to create a "full 3d" experience - * Add events for the case when the button is pressed for a long time, without release - */ - -//Method to calculate the shadow colors used to create the "3d" effect -void calculate_shadows(uint16_t bgcolor, uint16_t* light_shadow, uint16_t* dark_shadow) { - #define BRIGHTNESS_VAL 3 //How much the Brightness is in/decreased for button shadows (3 -> Add/Subtract 1/3 off Full Value) - - uint16_t c_light,c_dark; //c_light and c_dark will be filled with a lighter and a darker color as the background color (for the shadows) - uint8_t r,g,b; - - //separate the channels of the 16-bit rgb565 color - r=(bgcolor&0xF800)>>11; - g=(bgcolor&0x07E0)>>5; - b=(bgcolor&0x001F)>>0; - - //For the light shadow color: - if((r + 0x1F/BRIGHTNESS_VAL) > 0x1F) //Adding one third would exceed the maximum of the red channel - c_light=0xF800; //Use full red - else //adding one third to the red channel is fine - c_light=(r+0x1F/BRIGHTNESS_VAL)<<11; //Use same red as in the background, but add one third - if((g + 0x3F/BRIGHTNESS_VAL) > 0x3F) //same for the green channel - c_light|=0x07E0; - else - c_light|=(g+0x3F/BRIGHTNESS_VAL)<<5; - if((b + 0x1F/BRIGHTNESS_VAL) > 0x1F) //and the blue channel - c_light|=0x0018; - else - c_light|=(b+0x1F/BRIGHTNESS_VAL)<<0; - - //For the dark shadow color - if(r > (0x1F/BRIGHTNESS_VAL)) //Subtracting one third would NOT exceed the minimum of the red channel - c_dark=(r-0x1F/BRIGHTNESS_VAL)<<11; //Use same red as in the background, but subtract one third - else //Subtracting one third would give us a number below zero - c_dark=0x0000; //use no red channel - if(g > (0x3F/BRIGHTNESS_VAL)) //Same for the green channel - c_dark|=(g-0x3F/BRIGHTNESS_VAL)<<5; - if(b > (0x1F/BRIGHTNESS_VAL)) //and the blue channel - c_dark|=(b-0x1F/BRIGHTNESS_VAL)<<0; - - //Assign the calculated shadows to out parameters - if(light_shadow!=NULL) *light_shadow = c_light; - if(dark_shadow!=NULL) *dark_shadow = c_dark; - -} - -//Callback which is called when the user touches the touch-area we created for the button -void buttons_cb(void* touchArea, TOUCH_ACTION triggeredAction) -{ - TOUCH_AREA_STRUCT * area = (TOUCH_AREA_STRUCT*)touchArea; - BUTTON_STRUCT* button = (BUTTON_STRUCT*)touchArea; - - uint16_t c_light,c_dark; //c_light and c_dark will be filled with a lighter and a darker color as the background color (for the shadows) - calculate_shadows(button->bgcolor,&c_light,&c_dark); - - switch(triggeredAction) - { - case PEN_DOWN: //If the user touches the area for the "first time" - area->hookedActions=PEN_UP|PEN_LEAVE; //for the future we only want PEN_UP and PEN_LEAVE events - - //Draw shadows - tft_draw_line(button->base.x1+1,button->base.y1,button->base.x2-1,button->base.y1,c_dark); //North - tft_draw_line(button->base.x1,button->base.y1+1,button->base.x1,button->base.y2-1,c_dark);//West - tft_draw_line(button->base.x1+1,button->base.y2,button->base.x2-1,button->base.y2,c_light); //South - tft_draw_line(button->base.x2,button->base.y1+1,button->base.x2,button->base.y2-1,c_light); //East - break; - case PEN_UP: //If the user took the pen away, while in the area (=button pressed!) - case PEN_LEAVE: //or the user "slided out" of the area - area->hookedActions=PEN_DOWN; //for the future we only want PEN_DOWN events - - //Draw inverse shadows - tft_draw_line(button->base.x1+1,button->base.y1,button->base.x2-1,button->base.y1,c_light); //North - tft_draw_line(button->base.x1,button->base.y1+1,button->base.x1,button->base.y2-1,c_light);//West - tft_draw_line(button->base.x1+1,button->base.y2,button->base.x2-1,button->base.y2,c_dark); //South - tft_draw_line(button->base.x2,button->base.y1+1,button->base.x2,button->base.y2-1,c_dark); //East - - if(triggeredAction==PEN_UP && button->callback!=NULL) //If the button got "pressed" instead of left, and the user provided a callback - button->callback(button); //execute the user callback - break; - default:break; - } -} - - -bool gui_button_add(BUTTON_STRUCT* button) -{ - if(touch_have_empty(1)) //Check if the touch module can handle one additional area - { - //Calculate width and height of the button text - unsigned int strwidth=tft_font_width(button->font)*strlen(button->text); - unsigned char strheight=tft_font_height(button->font); - - button->base.hookedActions=PEN_DOWN; //At first we are interested in PEN_DOWN events - button->base.callback = buttons_cb; //Use our own callback for the touch area events - - if(button->base.x2==AUTO) { //The user wants us to calculate the button width automatically - //Use string width + half of a character width as button width - button->base.x2= button->base.x1 -1 + strwidth+(tft_font_width(button->font)/2); - } else if((button->base.x2-button->base.x1+1)<(strwidth+2)) { //the provided width is too small to fit the entire text - return false; //report error - } - - if(button->base.y2==AUTO) { //The user wants us to calculate the button height automatically - //Use one and a half character heights as button height - button->base.y2=button->base.y1 -1 +strheight+(strheight/2); - } else if((button->base.y2-button->base.y1+1)<(strheight+2)) { //the provided height is too small to fit the text - return false; - } - gui_button_redraw(button); //call the redraw method, which will take care of drawing the entire button - return touch_register_area(&button->base); //Register the touch area and receive events for this button, from now on - } - - return false; //no more touch areas left -} - -void gui_button_redraw(BUTTON_STRUCT* button) -{ - //Calculate text dimensions and shadow colors - unsigned int strwidth=tft_font_width(button->font)*strlen(button->text); - unsigned char strheight=tft_font_height(button->font); - uint16_t c_light,c_dark; - calculate_shadows(button->bgcolor,&c_light,&c_dark); - - //Draw the background and the 4 lines (shadow colors) - tft_fill_rectangle(button->base.x1+1,button->base.y1+1,button->base.x2-1,button->base.y2-1,button->bgcolor); - tft_draw_line(button->base.x1+1,button->base.y1,button->base.x2-1,button->base.y1,c_light); //North - tft_draw_line(button->base.x1,button->base.y1+1,button->base.x1,button->base.y2-1,c_light);//West - tft_draw_line(button->base.x1+1,button->base.y2,button->base.x2-1,button->base.y2,c_dark); //South - tft_draw_line(button->base.x2,button->base.y1+1,button->base.x2,button->base.y2-1,c_dark); //East - - //Draw the text - tft_print_line(button->base.x1+(button->base.x2-button->base.x1+1-strwidth)/2,button->base.y1+(button->base.y2-button->base.y1+1-strheight)/2,button->txtcolor,button->bgcolor,button->font,button->text); - -} - -void gui_button_remove(BUTTON_STRUCT* button) -{ - //We only need to unregister the touch area, as we have not allocated anything else - touch_unregister_area((TOUCH_AREA_STRUCT*)button); -} +/************************************************************************************************************************************** +* Project: discoverpixy +* Website: https://github.com/t-moe/discoverpixy +* Authors: Aaron Schmocker, Timo Lang +* Institution: BFH Bern University of Applied Sciences +* File: common/gui/button.c +* +* Version History: +* Date Autor Email SHA Changes +* 2015-04-27 timolang@gmail.com 7c9eabc Added button support. +* 2015-05-17 timolang@gmail.com 2d46336 Improved comments in implementation of button, checkbox, numupdown, tft, touch and screen modules/submodules. +* +**************************************************************************************************************************************/ + +#include "tft.h" +#include "touch.h" +#include "button.h" +#include + +/* The Idea is as follows: + * When the user add's a button we create a touch area for that region and wait for PEN_DOWN events. + * Once the user puts the pen down in this area we'll redraw the button with different shadows (feedback) + * and we'll now wait on PEN_UP or PEN_LEAVE events. + * If the user takes the pen away while in the area (PEN_UP), we call the provided user callback + * Otherwise (PEN_LEAVE) we only restore the initial shadows + */ + +/* Possible improvements: + * Move the button by 1 pixel while he is pressed, to create a "full 3d" experience + * Add events for the case when the button is pressed for a long time, without release + */ + +//Method to calculate the shadow colors used to create the "3d" effect +void calculate_shadows(uint16_t bgcolor, uint16_t* light_shadow, uint16_t* dark_shadow) +{ +#define BRIGHTNESS_VAL 3 //How much the Brightness is in/decreased for button shadows (3 -> Add/Subtract 1/3 off Full Value) + + uint16_t c_light, c_dark; //c_light and c_dark will be filled with a lighter and a darker color as the background color (for the shadows) + uint8_t r, g, b; + + //separate the channels of the 16-bit rgb565 color + r = (bgcolor & 0xF800) >> 11; + g = (bgcolor & 0x07E0) >> 5; + b = (bgcolor & 0x001F) >> 0; + + //For the light shadow color: + if ((r + 0x1F / BRIGHTNESS_VAL) > 0x1F) { //Adding one third would exceed the maximum of the red channel + c_light = 0xF800; //Use full red + } else { //adding one third to the red channel is fine + c_light = (r + 0x1F / BRIGHTNESS_VAL) << 11; //Use same red as in the background, but add one third + } + + if ((g + 0x3F / BRIGHTNESS_VAL) > 0x3F) { //same for the green channel + c_light |= 0x07E0; + } else { + c_light |= (g + 0x3F / BRIGHTNESS_VAL) << 5; + } + + if ((b + 0x1F / BRIGHTNESS_VAL) > 0x1F) { //and the blue channel + c_light |= 0x0018; + } else { + c_light |= (b + 0x1F / BRIGHTNESS_VAL) << 0; + } + + //For the dark shadow color + if (r > (0x1F / BRIGHTNESS_VAL)) { //Subtracting one third would NOT exceed the minimum of the red channel + c_dark = (r - 0x1F / BRIGHTNESS_VAL) << 11; //Use same red as in the background, but subtract one third + } else { //Subtracting one third would give us a number below zero + c_dark = 0x0000; //use no red channel + } + + if (g > (0x3F / BRIGHTNESS_VAL)) { //Same for the green channel + c_dark |= (g - 0x3F / BRIGHTNESS_VAL) << 5; + } + + if (b > (0x1F / BRIGHTNESS_VAL)) { //and the blue channel + c_dark |= (b - 0x1F / BRIGHTNESS_VAL) << 0; + } + + //Assign the calculated shadows to out parameters + if (light_shadow != NULL) { + *light_shadow = c_light; + } + + if (dark_shadow != NULL) { + *dark_shadow = c_dark; + } + +} + +//Callback which is called when the user touches the touch-area we created for the button +void buttons_cb(void* touchArea, TOUCH_ACTION triggeredAction) +{ + TOUCH_AREA_STRUCT* area = (TOUCH_AREA_STRUCT*)touchArea; + BUTTON_STRUCT* button = (BUTTON_STRUCT*)touchArea; + + uint16_t c_light, c_dark; //c_light and c_dark will be filled with a lighter and a darker color as the background color (for the shadows) + calculate_shadows(button->bgcolor, &c_light, &c_dark); + + switch (triggeredAction) { + case PEN_DOWN: //If the user touches the area for the "first time" + area->hookedActions = PEN_UP | PEN_LEAVE; //for the future we only want PEN_UP and PEN_LEAVE events + + //Draw shadows + tft_draw_line(button->base.x1 + 1, button->base.y1, button->base.x2 - 1, button->base.y1, c_dark); //North + tft_draw_line(button->base.x1, button->base.y1 + 1, button->base.x1, button->base.y2 - 1, c_dark); //West + tft_draw_line(button->base.x1 + 1, button->base.y2, button->base.x2 - 1, button->base.y2, c_light); //South + tft_draw_line(button->base.x2, button->base.y1 + 1, button->base.x2, button->base.y2 - 1, c_light); //East + break; + + case PEN_UP: //If the user took the pen away, while in the area (=button pressed!) + case PEN_LEAVE: //or the user "slided out" of the area + area->hookedActions = PEN_DOWN; //for the future we only want PEN_DOWN events + + //Draw inverse shadows + tft_draw_line(button->base.x1 + 1, button->base.y1, button->base.x2 - 1, button->base.y1, c_light); //North + tft_draw_line(button->base.x1, button->base.y1 + 1, button->base.x1, button->base.y2 - 1, c_light); //West + tft_draw_line(button->base.x1 + 1, button->base.y2, button->base.x2 - 1, button->base.y2, c_dark); //South + tft_draw_line(button->base.x2, button->base.y1 + 1, button->base.x2, button->base.y2 - 1, c_dark); //East + + if (triggeredAction == PEN_UP && button->callback != NULL) { //If the button got "pressed" instead of left, and the user provided a callback + button->callback(button); //execute the user callback + } + + break; + + default: + break; + } +} + + +bool gui_button_add(BUTTON_STRUCT* button) +{ + if (touch_have_empty(1)) { //Check if the touch module can handle one additional area + //Calculate width and height of the button text + unsigned int strwidth = tft_font_width(button->font) * strlen(button->text); + unsigned char strheight = tft_font_height(button->font); + + button->base.hookedActions = PEN_DOWN; //At first we are interested in PEN_DOWN events + button->base.callback = buttons_cb; //Use our own callback for the touch area events + + if (button->base.x2 == AUTO) { //The user wants us to calculate the button width automatically + //Use string width + half of a character width as button width + button->base.x2 = button->base.x1 - 1 + strwidth + (tft_font_width(button->font) / 2); + } else if ((button->base.x2 - button->base.x1 + 1) < (strwidth + 2)) { //the provided width is too small to fit the entire text + return false; //report error + } + + if (button->base.y2 == AUTO) { //The user wants us to calculate the button height automatically + //Use one and a half character heights as button height + button->base.y2 = button->base.y1 - 1 + strheight + (strheight / 2); + } else if ((button->base.y2 - button->base.y1 + 1) < (strheight + 2)) { //the provided height is too small to fit the text + return false; + } + + gui_button_redraw(button); //call the redraw method, which will take care of drawing the entire button + return touch_register_area(&button->base); //Register the touch area and receive events for this button, from now on + } + + return false; //no more touch areas left +} + +void gui_button_redraw(BUTTON_STRUCT* button) +{ + //Calculate text dimensions and shadow colors + unsigned int strwidth = tft_font_width(button->font) * strlen(button->text); + unsigned char strheight = tft_font_height(button->font); + uint16_t c_light, c_dark; + calculate_shadows(button->bgcolor, &c_light, &c_dark); + + //Draw the background and the 4 lines (shadow colors) + tft_fill_rectangle(button->base.x1 + 1, button->base.y1 + 1, button->base.x2 - 1, button->base.y2 - 1, button->bgcolor); + tft_draw_line(button->base.x1 + 1, button->base.y1, button->base.x2 - 1, button->base.y1, c_light); //North + tft_draw_line(button->base.x1, button->base.y1 + 1, button->base.x1, button->base.y2 - 1, c_light); //West + tft_draw_line(button->base.x1 + 1, button->base.y2, button->base.x2 - 1, button->base.y2, c_dark); //South + tft_draw_line(button->base.x2, button->base.y1 + 1, button->base.x2, button->base.y2 - 1, c_dark); //East + + //Draw the text + tft_print_line(button->base.x1 + (button->base.x2 - button->base.x1 + 1 - strwidth) / 2, button->base.y1 + (button->base.y2 - button->base.y1 + 1 - strheight) / 2, button->txtcolor, button->bgcolor, button->font, button->text); + +} + +void gui_button_remove(BUTTON_STRUCT* button) +{ + //We only need to unregister the touch area, as we have not allocated anything else + touch_unregister_area((TOUCH_AREA_STRUCT*)button); +} diff --git a/common/gui/button.h b/common/gui/button.h index 14aff59..2a8d3a1 100644 --- a/common/gui/button.h +++ b/common/gui/button.h @@ -1,71 +1,89 @@ -#ifndef BUTTON_H -#define BUTTON_H - -#include "touch.h" - -/** - * @defgroup gui Gui - * The Gui Module - */ -/*@{*/ - -/** - * @defgroup button Button - * The Button Gui-Element is a clickable, rectangular box with a label inside. - * When it is pressed and released you will be notified via the provided callback. - */ - -/*@}*/ - -/** - * @addtogroup button - */ -/*@{*/ - - -/** - * Prototype for Event Listeners (called when the button is pressed) - * \note You should NOT execute long running things in this callback nor should you update the gui. But you can call gui_screen_navigate() for instance. - * @param button The pointer to the BUTTON_STRUCT where to corresponding Button was pressed - */ -typedef void (*BUTTON_CALLBACK)(void *button); - - -/** - * Structure to configure the Button - */ -typedef struct { - TOUCH_AREA_STRUCT base; //!< Basic geometry of the button. You only need to set the x1, y1, x2, y2 members of this struct. - uint16_t bgcolor; //!< The 16-bit background color of the button - BUTTON_CALLBACK callback; //!< Callback which is executed when the button is pressed - uint16_t txtcolor; //!< The 16-bit text color - uint8_t font; //!< The number of the font to use - const char *text; //!< The label of the button -} BUTTON_STRUCT; - - -#define AUTO 0 //!< Use this value instead of x2, y2 in the BUTTON_STRUCT to autocalculate the button width/height - -/** - * Adds a button. Your Callback will be called from now on, if the button was pressed - * @param button A Pointer to the preinitialized BUTTON_STRUCT - * @return true on success - */ -bool gui_button_add(BUTTON_STRUCT* button); - -/** - * Removes the button. You will no longer receive events for this button. This function will not overdraw the region where the button was located. - * @param button A Pointer to the BUTTON_STRUCT - */ -void gui_button_remove(BUTTON_STRUCT* button); - -/** - * Redraws the button. Call this method if you have to redraw the entire screen or if you want to draw a button on top of an image. - * @param button A Pointer to the BUTTON_STRUCT - */ -void gui_button_redraw(BUTTON_STRUCT* button); - - -/*@}*/ - -#endif /* BUTTON_H */ +/************************************************************************************************************************************** +* Project: discoverpixy +* Website: https://github.com/t-moe/discoverpixy +* Authors: Aaron Schmocker, Timo Lang +* Institution: BFH Bern University of Applied Sciences +* File: common/gui/button.h +* +* Version History: +* Date Autor Email SHA Changes +* 2015-04-27 timolang@gmail.com 7c9eabc Added button support. +* 2015-04-27 timolang@gmail.com cf72baa Introduced a Screen (sub) module and divided app into multiple screens. +* 2015-05-11 timolang@gmail.com 08d9fe0 More work on doxygen module structure +* 2015-05-12 timolang@gmail.com 1402598 Added doxygen stuff for button module and some minor changes to touch, screen_main and tft module. +* 2015-05-15 timolang@gmail.com 9a16865 Added doxgen comments to filesyste, checkbox, numupdown and screen module. And some minor changes to the other modules. +* 2015-05-17 timolang@gmail.com 2d46336 Improved comments in implementation of button, checkbox, numupdown, tft, touch and screen modules/submodules. +* +**************************************************************************************************************************************/ + +#ifndef BUTTON_H +#define BUTTON_H + +#include "touch.h" + +/** + * @defgroup gui Gui + * The Gui Module + */ +/*@{*/ + +/** + * @defgroup button Button + * The Button Gui-Element is a clickable, rectangular box with a label inside. + * When it is pressed and released you will be notified via the provided callback. + */ + +/*@}*/ + +/** + * @addtogroup button + */ +/*@{*/ + + +/** + * Prototype for Event Listeners (called when the button is pressed) + * \note You should NOT execute long running things in this callback nor should you update the gui. But you can call gui_screen_navigate() for instance. + * @param button The pointer to the BUTTON_STRUCT where to corresponding Button was pressed + */ +typedef void (*BUTTON_CALLBACK)(void* button); + + +/** + * Structure to configure the Button + */ +typedef struct { + TOUCH_AREA_STRUCT base; //!< Basic geometry of the button. You only need to set the x1, y1, x2, y2 members of this struct. + uint16_t bgcolor; //!< The 16-bit background color of the button + BUTTON_CALLBACK callback; //!< Callback which is executed when the button is pressed + uint16_t txtcolor; //!< The 16-bit text color + uint8_t font; //!< The number of the font to use + const char* text; //!< The label of the button +} BUTTON_STRUCT; + + +#define AUTO 0 //!< Use this value instead of x2, y2 in the BUTTON_STRUCT to autocalculate the button width/height + +/** + * Adds a button. Your Callback will be called from now on, if the button was pressed + * @param button A Pointer to the preinitialized BUTTON_STRUCT + * @return true on success + */ +bool gui_button_add(BUTTON_STRUCT* button); + +/** + * Removes the button. You will no longer receive events for this button. This function will not overdraw the region where the button was located. + * @param button A Pointer to the BUTTON_STRUCT + */ +void gui_button_remove(BUTTON_STRUCT* button); + +/** + * Redraws the button. Call this method if you have to redraw the entire screen or if you want to draw a button on top of an image. + * @param button A Pointer to the BUTTON_STRUCT + */ +void gui_button_redraw(BUTTON_STRUCT* button); + + +/*@}*/ + +#endif /* BUTTON_H */ diff --git a/common/gui/checkbox.c b/common/gui/checkbox.c index 3f0cb8a..c2878be 100644 --- a/common/gui/checkbox.c +++ b/common/gui/checkbox.c @@ -1,121 +1,144 @@ -#include "tft.h" -#include "touch.h" -#include "checkbox.h" -#include - -/* The idea is as follows: - * When the user creates a checkbox we create a touch area for that region and wait for PEN_DOWN events. - * Once the user puts the pen down in this area we'll redraw the checkbox with different shadows (feedback) - * and we'll now wait on PEN_UP or PEN_LEAVE events. - * If the user takes the pen away while in the area (PEN_UP), we toggle the checkbox and we call the provided user callback - * Otherwise (PEN_LEAVE) we only restore the initial shadows - */ - - -#define ACTIVE_COLOR RGB(251,208,123) //shadow color (inside of border) -#define BORDER_COLOR RGB(29,82,129) //1px border color -#define BACKGROUND_COLOR WHITE //Background color - -//Callback which is called when the user touches the touch-area we created for the checkbox -void checkboxes_cb(void* touchArea, TOUCH_ACTION triggeredAction) -{ - TOUCH_AREA_STRUCT * area = (TOUCH_AREA_STRUCT*)touchArea; - CHECKBOX_STRUCT* checkbox = (CHECKBOX_STRUCT*)touchArea; - switch(triggeredAction) - { - case PEN_DOWN: //If the user touches the area for the "first time" - area->hookedActions=PEN_UP|PEN_LEAVE; //for the future we only want PEN_UP and PEN_LEAVE events - - //Draw active shadows - tft_draw_rectangle(checkbox->base.x1+1,checkbox->base.y1+1,checkbox->base.x2-1,checkbox->base.y2-1,ACTIVE_COLOR); - tft_draw_rectangle(checkbox->base.x1+2,checkbox->base.y1+2,checkbox->base.x2-2,checkbox->base.y2-2,ACTIVE_COLOR); - break; - case PEN_UP: //If the user took the pen away, while in the area (=toggle checkbox!) - checkbox->checked=!checkbox->checked; //Toggle checkbox state - gui_checkbox_update(checkbox); //redraw/overdraw tickmark - if(checkbox->callback!=NULL) { //The user provided a callback - checkbox->callback(checkbox,checkbox->checked); //Call the provided callback with the new checked state - } - // no break statement here! - case PEN_LEAVE: //if the user "slided out" of the area - area->hookedActions=PEN_DOWN; //for the future we only want PEN_DOWN events - - //Draw inactive shadows - tft_draw_rectangle(checkbox->base.x1+1,checkbox->base.y1+1,checkbox->base.x2-1,checkbox->base.y2-1,BACKGROUND_COLOR); - tft_draw_rectangle(checkbox->base.x1+2,checkbox->base.y1+2,checkbox->base.x2-2,checkbox->base.y2-2,BACKGROUND_COLOR); - break; - default:break; - } -} - -bool gui_checkbox_add(CHECKBOX_STRUCT* checkbox) -{ - if(touch_have_empty(1)) //Check if the touch module can handle one additional area - { - unsigned char size=0; - checkbox->base.hookedActions=PEN_DOWN; //At first we are interested in PEN_DOWN events - checkbox->base.callback = checkboxes_cb; //Use our own callback for the touch area events - - //Check the size of the checkbox - if(checkbox->base.x2>checkbox->base.x1) - size = checkbox->base.x2 - checkbox->base.x1; //use width a as size - if(checkbox->base.y2>checkbox->base.y1) - { - if((checkbox->base.y2 - checkbox->base.y1)>size) //height is larger than size - size = checkbox->base.y2 - checkbox->base.y1; //use height as size - } - if(size==0) { //no size found (maybe swap x2 and x1 or y2 and y1 ?) - return false; //signal error - } - if((size&0x01)) //the size is an odd number - size++; //make size an even number - - //Correct x2,y2 so that the checkbox is quadratic - checkbox->base.x2 = checkbox->base.x1 + size; - checkbox->base.y2 = checkbox->base.y1 + size; - - gui_checkbox_redraw(checkbox);//Call redraw method, which will take care of the drawing of the entire checkbox - - return touch_register_area(&checkbox->base); //Register the touch area and receive events for this checkbox, from now on - } - - return false; //no more touch areas left -} - -void gui_checkbox_redraw(CHECKBOX_STRUCT* checkbox) -{ - //Draw background and border - tft_fill_rectangle(checkbox->base.x1+1,checkbox->base.y1+1,checkbox->base.x2-1,checkbox->base.y2-1,BACKGROUND_COLOR); - tft_draw_rectangle(checkbox->base.x1,checkbox->base.y1,checkbox->base.x2,checkbox->base.y2,BORDER_COLOR); - - if(checkbox->checked) { //checkbox is currently checked - gui_checkbox_update(checkbox); //Call update method which will draw the tickmark - } -} - -void gui_checkbox_remove(CHECKBOX_STRUCT* checkbox) -{ - //We only need to unregister the touch area, as we have not allocated anything else - touch_unregister_area((TOUCH_AREA_STRUCT*)checkbox); -} - -void gui_checkbox_update(CHECKBOX_STRUCT* checkbox) -{ - unsigned int c = (checkbox->checked)? checkbox->fgcolor:BACKGROUND_COLOR; //color to use for the tickmark - - //helper points inside the checkbox - unsigned int xcent = checkbox->base.x1+(checkbox->base.x2-checkbox->base.x1)*6/14; - unsigned int yleft = checkbox->base.y2 - (xcent- checkbox->base.x1) - 1 ; - unsigned int yright = checkbox->base.y2 - (checkbox->base.x2 - xcent) - 1 ; - unsigned int ybot = checkbox->base.y2 - 4; - - //Draw tickmark as a 3pixel wide line - tft_draw_line(checkbox->base.x1+3,yleft-1,xcent,ybot -1,c); - tft_draw_line(checkbox->base.x1+3,yleft,xcent,ybot ,c); - tft_draw_line(checkbox->base.x1+3,yleft+1,xcent,ybot + 1,c); - xcent++; - ybot--; - tft_draw_line(xcent,ybot-1,checkbox->base.x2-3,yright-1,c); - tft_draw_line(xcent,ybot,checkbox->base.x2-3,yright+0,c); - tft_draw_line(xcent,ybot+1,checkbox->base.x2-3,yright+1,c); -} +/************************************************************************************************************************************** +* Project: discoverpixy +* Website: https://github.com/t-moe/discoverpixy +* Authors: Aaron Schmocker, Timo Lang +* Institution: BFH Bern University of Applied Sciences +* File: common/gui/checkbox.c +* +* Version History: +* Date Autor Email SHA Changes +* 2015-04-27 timolang@gmail.com b300ac5 Added Checkbox support +* 2015-05-17 timolang@gmail.com 2d46336 Improved comments in implementation of button, checkbox, numupdown, tft, touch and screen modules/submodules. +* +**************************************************************************************************************************************/ + +#include "tft.h" +#include "touch.h" +#include "checkbox.h" +#include + +/* The idea is as follows: + * When the user creates a checkbox we create a touch area for that region and wait for PEN_DOWN events. + * Once the user puts the pen down in this area we'll redraw the checkbox with different shadows (feedback) + * and we'll now wait on PEN_UP or PEN_LEAVE events. + * If the user takes the pen away while in the area (PEN_UP), we toggle the checkbox and we call the provided user callback + * Otherwise (PEN_LEAVE) we only restore the initial shadows + */ + + +#define ACTIVE_COLOR RGB(251,208,123) //shadow color (inside of border) +#define BORDER_COLOR RGB(29,82,129) //1px border color +#define BACKGROUND_COLOR WHITE //Background color + +//Callback which is called when the user touches the touch-area we created for the checkbox +void checkboxes_cb(void* touchArea, TOUCH_ACTION triggeredAction) +{ + TOUCH_AREA_STRUCT* area = (TOUCH_AREA_STRUCT*)touchArea; + CHECKBOX_STRUCT* checkbox = (CHECKBOX_STRUCT*)touchArea; + + switch (triggeredAction) { + case PEN_DOWN: //If the user touches the area for the "first time" + area->hookedActions = PEN_UP | PEN_LEAVE; //for the future we only want PEN_UP and PEN_LEAVE events + + //Draw active shadows + tft_draw_rectangle(checkbox->base.x1 + 1, checkbox->base.y1 + 1, checkbox->base.x2 - 1, checkbox->base.y2 - 1, ACTIVE_COLOR); + tft_draw_rectangle(checkbox->base.x1 + 2, checkbox->base.y1 + 2, checkbox->base.x2 - 2, checkbox->base.y2 - 2, ACTIVE_COLOR); + break; + + case PEN_UP: //If the user took the pen away, while in the area (=toggle checkbox!) + checkbox->checked = !checkbox->checked; //Toggle checkbox state + gui_checkbox_update(checkbox); //redraw/overdraw tickmark + + if (checkbox->callback != NULL) { //The user provided a callback + checkbox->callback(checkbox, checkbox->checked); //Call the provided callback with the new checked state + } + + // no break statement here! + case PEN_LEAVE: //if the user "slided out" of the area + area->hookedActions = PEN_DOWN; //for the future we only want PEN_DOWN events + + //Draw inactive shadows + tft_draw_rectangle(checkbox->base.x1 + 1, checkbox->base.y1 + 1, checkbox->base.x2 - 1, checkbox->base.y2 - 1, BACKGROUND_COLOR); + tft_draw_rectangle(checkbox->base.x1 + 2, checkbox->base.y1 + 2, checkbox->base.x2 - 2, checkbox->base.y2 - 2, BACKGROUND_COLOR); + break; + + default: + break; + } +} + +bool gui_checkbox_add(CHECKBOX_STRUCT* checkbox) +{ + if (touch_have_empty(1)) { //Check if the touch module can handle one additional area + unsigned char size = 0; + checkbox->base.hookedActions = PEN_DOWN; //At first we are interested in PEN_DOWN events + checkbox->base.callback = checkboxes_cb; //Use our own callback for the touch area events + + //Check the size of the checkbox + if (checkbox->base.x2 > checkbox->base.x1) { + size = checkbox->base.x2 - checkbox->base.x1; //use width a as size + } + + if (checkbox->base.y2 > checkbox->base.y1) { + if ((checkbox->base.y2 - checkbox->base.y1) > size) { //height is larger than size + size = checkbox->base.y2 - checkbox->base.y1; //use height as size + } + } + + if (size == 0) { //no size found (maybe swap x2 and x1 or y2 and y1 ?) + return false; //signal error + } + + if ((size & 0x01)) { //the size is an odd number + size++; //make size an even number + } + + //Correct x2,y2 so that the checkbox is quadratic + checkbox->base.x2 = checkbox->base.x1 + size; + checkbox->base.y2 = checkbox->base.y1 + size; + + gui_checkbox_redraw(checkbox);//Call redraw method, which will take care of the drawing of the entire checkbox + + return touch_register_area(&checkbox->base); //Register the touch area and receive events for this checkbox, from now on + } + + return false; //no more touch areas left +} + +void gui_checkbox_redraw(CHECKBOX_STRUCT* checkbox) +{ + //Draw background and border + tft_fill_rectangle(checkbox->base.x1 + 1, checkbox->base.y1 + 1, checkbox->base.x2 - 1, checkbox->base.y2 - 1, BACKGROUND_COLOR); + tft_draw_rectangle(checkbox->base.x1, checkbox->base.y1, checkbox->base.x2, checkbox->base.y2, BORDER_COLOR); + + if (checkbox->checked) { //checkbox is currently checked + gui_checkbox_update(checkbox); //Call update method which will draw the tickmark + } +} + +void gui_checkbox_remove(CHECKBOX_STRUCT* checkbox) +{ + //We only need to unregister the touch area, as we have not allocated anything else + touch_unregister_area((TOUCH_AREA_STRUCT*)checkbox); +} + +void gui_checkbox_update(CHECKBOX_STRUCT* checkbox) +{ + unsigned int c = (checkbox->checked) ? checkbox->fgcolor : BACKGROUND_COLOR; //color to use for the tickmark + + //helper points inside the checkbox + unsigned int xcent = checkbox->base.x1 + (checkbox->base.x2 - checkbox->base.x1) * 6 / 14; + unsigned int yleft = checkbox->base.y2 - (xcent - checkbox->base.x1) - 1 ; + unsigned int yright = checkbox->base.y2 - (checkbox->base.x2 - xcent) - 1 ; + unsigned int ybot = checkbox->base.y2 - 4; + + //Draw tickmark as a 3pixel wide line + tft_draw_line(checkbox->base.x1 + 3, yleft - 1, xcent, ybot - 1, c); + tft_draw_line(checkbox->base.x1 + 3, yleft, xcent, ybot , c); + tft_draw_line(checkbox->base.x1 + 3, yleft + 1, xcent, ybot + 1, c); + xcent++; + ybot--; + tft_draw_line(xcent, ybot - 1, checkbox->base.x2 - 3, yright - 1, c); + tft_draw_line(xcent, ybot, checkbox->base.x2 - 3, yright + 0, c); + tft_draw_line(xcent, ybot + 1, checkbox->base.x2 - 3, yright + 1, c); +} diff --git a/common/gui/checkbox.h b/common/gui/checkbox.h index 9165f6c..60c06ef 100644 --- a/common/gui/checkbox.h +++ b/common/gui/checkbox.h @@ -1,70 +1,86 @@ -#ifndef CHECKBOX_H -#define CHECKBOX_H - -#include "touch.h" - -/** - * @addtogroup gui - */ -/*@{*/ - -/** - * @defgroup checkbox Checkbox - * The Checkbox Gui-Element is a clickable, rectangular box with an optional tickmark inside of it. - * When the checkbox is pressed and released it's tick state changes and you will be notified via the provided callback. - */ -/*@}*/ - -/** - * @addtogroup checkbox - */ -/*@{*/ - -/** - * Prototype for Event Listeners (called when the checkbox state has changed) - * \note You should NOT execute long running things in this callback nor should you update the gui. But you can call gui_screen_navigate() for instance. - * @param checkbox The pointer to the CHECKBOX_STRUCT where to corresponding Checkbox has changed the state - * @param checked A boolean which indicates whether the checkbox is now checked or not. - */ -typedef void (*CHECKBOX_CALLBACK)(void *checkbox, bool checked); - -/** - * Structure to configure the Checkbox - */ -typedef struct { - TOUCH_AREA_STRUCT base; //!< Basic geometry of the Checkbox. You only need to set the x1, y1, x2, y2 members of this struct. - uint16_t fgcolor; //!< The 16-bit color of the tickmark - bool checked; //!< A boolean which indicates whether or not the checkbox is currently checked. - CHECKBOX_CALLBACK callback; //!< Callback which is executed when the checkbox changes state -} CHECKBOX_STRUCT; - -/** - * Adds a checkbox. Your Callback will be called from now on, if the checkbox changes state - * @param checkbox A Pointer to the preinitialized CHECKBOX_STRUCT - * @return true on success - */ -bool gui_checkbox_add(CHECKBOX_STRUCT* checkbox); - -/** - * Removes the checkbox. You will no longer receive events for this checkbox. This function will not overdraw the region where the checkbox was located. - * @param checkbox A Pointer to the CHECKBOX_STRUCT - */ -void gui_checkbox_remove(CHECKBOX_STRUCT* checkbox); - -/** - * Updates the checkbox. Call this function when you change the state of the checkbox through code. - * @param checkbox A Pointer to the CHECKBOX_STRUCT - */ -void gui_checkbox_update(CHECKBOX_STRUCT* checkbox); - -/** - * Redraws the checkbox. Call this method if you have to redraw the entire screen or if you want to draw a checkbox on top of an image. - * @param checkbox A Pointer to the CHECKBOX_STRUCT - */ -void gui_checkbox_redraw(CHECKBOX_STRUCT* checkbox); - -#define CHECKBOX_WIN_FG_COLOR RGB(32,161,34) - -/*@}*/ - -#endif /* CHECKBOX_H */ +/************************************************************************************************************************************** +* Project: discoverpixy +* Website: https://github.com/t-moe/discoverpixy +* Authors: Aaron Schmocker, Timo Lang +* Institution: BFH Bern University of Applied Sciences +* File: common/gui/checkbox.h +* +* Version History: +* Date Autor Email SHA Changes +* 2015-04-27 timolang@gmail.com b300ac5 Added Checkbox support +* 2015-05-11 timolang@gmail.com 08d9fe0 More work on doxygen module structure +* 2015-05-15 timolang@gmail.com 9a16865 Added doxgen comments to filesyste, checkbox, numupdown and screen module. And some minor changes to the other modules. +* 2015-05-17 timolang@gmail.com 2d46336 Improved comments in implementation of button, checkbox, numupdown, tft, touch and screen modules/submodules. +* +**************************************************************************************************************************************/ + +#ifndef CHECKBOX_H +#define CHECKBOX_H + +#include "touch.h" + +/** + * @addtogroup gui + */ +/*@{*/ + +/** + * @defgroup checkbox Checkbox + * The Checkbox Gui-Element is a clickable, rectangular box with an optional tickmark inside of it. + * When the checkbox is pressed and released it's tick state changes and you will be notified via the provided callback. + */ +/*@}*/ + +/** + * @addtogroup checkbox + */ +/*@{*/ + +/** + * Prototype for Event Listeners (called when the checkbox state has changed) + * \note You should NOT execute long running things in this callback nor should you update the gui. But you can call gui_screen_navigate() for instance. + * @param checkbox The pointer to the CHECKBOX_STRUCT where to corresponding Checkbox has changed the state + * @param checked A boolean which indicates whether the checkbox is now checked or not. + */ +typedef void (*CHECKBOX_CALLBACK)(void* checkbox, bool checked); + +/** + * Structure to configure the Checkbox + */ +typedef struct { + TOUCH_AREA_STRUCT base; //!< Basic geometry of the Checkbox. You only need to set the x1, y1, x2, y2 members of this struct. + uint16_t fgcolor; //!< The 16-bit color of the tickmark + bool checked; //!< A boolean which indicates whether or not the checkbox is currently checked. + CHECKBOX_CALLBACK callback; //!< Callback which is executed when the checkbox changes state +} CHECKBOX_STRUCT; + +/** + * Adds a checkbox. Your Callback will be called from now on, if the checkbox changes state + * @param checkbox A Pointer to the preinitialized CHECKBOX_STRUCT + * @return true on success + */ +bool gui_checkbox_add(CHECKBOX_STRUCT* checkbox); + +/** + * Removes the checkbox. You will no longer receive events for this checkbox. This function will not overdraw the region where the checkbox was located. + * @param checkbox A Pointer to the CHECKBOX_STRUCT + */ +void gui_checkbox_remove(CHECKBOX_STRUCT* checkbox); + +/** + * Updates the checkbox. Call this function when you change the state of the checkbox through code. + * @param checkbox A Pointer to the CHECKBOX_STRUCT + */ +void gui_checkbox_update(CHECKBOX_STRUCT* checkbox); + +/** + * Redraws the checkbox. Call this method if you have to redraw the entire screen or if you want to draw a checkbox on top of an image. + * @param checkbox A Pointer to the CHECKBOX_STRUCT + */ +void gui_checkbox_redraw(CHECKBOX_STRUCT* checkbox); + +#define CHECKBOX_WIN_FG_COLOR RGB(32,161,34) + +/*@}*/ + +#endif /* CHECKBOX_H */ diff --git a/common/gui/numupdown.c b/common/gui/numupdown.c index e17a48b..bc6ed42 100644 --- a/common/gui/numupdown.c +++ b/common/gui/numupdown.c @@ -1,143 +1,169 @@ -#include "tft.h" -#include "touch.h" -#include "button.h" -#include "numupdown.h" -#include //for sprintf -#include //for offsetof macro -#include //for abs - -/* The idea is as follows: - * When the user add's a numupdown we create two buttons, one with a plus and one with a minus sign in it - * When the user presses one of the buttons we check and increase the value and execute the provided user callback - */ - - -#define BASE_COLOR RGB(90,90,90) //Background color for the whole element - -//Callback which is called when the user presses the "plus" button -void button_up_cb(void* button) -{ - //Get the pointer to the numupdown: subtract the offset of the buttonUp member in the struct from the button pointer - NUMUPDOWN_STRUCT* element = button-offsetof(NUMUPDOWN_STRUCT,buttonUp); - - if(element->valuemax) { //old value lies below the maximum - element->value++; //let's increase the value - gui_numupdown_update(element); //and redraw everything - if(element->callback!=NULL) { //the user provided a callback - element->callback(element,element->value); //Call the user callback with the new value - } - } -} - -//Callback which is called when the user presses the "minus" button -void button_down_cb(void* button) -{ - //Get the pointer to the numupdown: subtract the offset of the buttonDown member in the struct from the button pointer - NUMUPDOWN_STRUCT* element = button-offsetof(NUMUPDOWN_STRUCT,buttonDown); - - if(element->value>element->min) { //old value lies above the minimum - element->value--; //let's decrease the value - gui_numupdown_update(element); //and redraw everything - if(element->callback!=NULL) { //the user provided a callback - element->callback(element,element->value); //Call the user callback with the new value - } - } -} - -//Method to calculate the number of characters needed to print the provided number in decimal notation (with optional sign) -static uint8_t calc_text_width(int16_t val) { - uint8_t width = 1 + (val<0); //1 if positive, 2 if negative (to let space for sign) - val=abs(val); //Make the number positive - while(val>=10) { //while we have two or more digits - val/=10; //remove one digit - width++; //add one character - } - return width; -} - - -bool gui_numupdown_add(NUMUPDOWN_STRUCT* numupdown) -{ - if(touch_have_empty(2)) //Check if the touch module can handle two additional areas - { - if(numupdown->min > numupdown->max) { //min is bigger than max? - return false; //invalid parameter - } - - if(numupdown->value < numupdown->min) { //value is smaller than min? - numupdown->value = numupdown->min; //normalize value - } else if(numupdown->value > numupdown->max) { //value is bigger than max? - numupdown->value = numupdown->max; //normalize value - } - - uint8_t tw1 = calc_text_width(numupdown->max); //Calculate character width to render maximum value - uint8_t tw2 = calc_text_width(numupdown->min); //Calculate character width to render minimum value - if(tw2 > tw1) tw1 = tw2; //ensure tw1 contains the larger number of the two - uint8_t width= tft_font_width(0)*(tw1+1); //Calculate width of the number area - - //Add "minus" button to the left side of the number area - numupdown->buttonDown.base.x1=numupdown->x; - numupdown->buttonDown.base.y1=numupdown->y; - numupdown->buttonDown.base.x2=AUTO; - numupdown->buttonDown.base.y2=numupdown->y+tft_font_height(0)*2; - numupdown->buttonDown.text="-"; - numupdown->buttonDown.font=0; - numupdown->buttonDown.bgcolor=BASE_COLOR; - numupdown->buttonDown.txtcolor=WHITE; - numupdown->buttonDown.callback = button_down_cb; - gui_button_add(&numupdown->buttonDown); - - //Add "plus" button to the right side of the number area - numupdown->buttonUp.base.x1=numupdown->buttonDown.base.x2+width+2; - numupdown->buttonUp.base.y1=numupdown->y; - numupdown->buttonUp.base.x2=AUTO; - numupdown->buttonUp.base.y2=numupdown->y +tft_font_height(0)*2; - numupdown->buttonUp.text="+"; - numupdown->buttonUp.font=0; - numupdown->buttonUp.bgcolor=BASE_COLOR; - numupdown->buttonUp.txtcolor=WHITE; - numupdown->buttonUp.callback = button_up_cb; - gui_button_add(&numupdown->buttonUp); - - //Draw background and label of the number area - tft_fill_rectangle(numupdown->buttonDown.base.x2+2,numupdown->y,numupdown->buttonDown.base.x2+width,numupdown->buttonUp.base.y2,BASE_COLOR); - tft_print_formatted(numupdown->buttonDown.base.x2+2+tft_font_width(0)/2,numupdown->y+tft_font_height(0)/2,numupdown->fgcolor,BASE_COLOR,0,"%*d",tw1,numupdown->value); - - return true; - } - - return false; //not enough touch areas left - } - -void gui_numupdown_remove(NUMUPDOWN_STRUCT* numupdown) -{ - //remove the two buttons, we have no other allocated resources - gui_button_remove(&numupdown->buttonUp); - gui_button_remove(&numupdown->buttonDown); -} - - -void gui_numupdown_redraw(NUMUPDOWN_STRUCT* numupdown) -{ - //redraw the two buttons - gui_button_redraw(&numupdown->buttonUp); - gui_button_redraw(&numupdown->buttonDown); - - //call update method which will take care of the number-area rendering - gui_numupdown_update(numupdown); -} - -void gui_numupdown_update(NUMUPDOWN_STRUCT* numupdown) -{ - //Calculate the number area width again (see above) - uint8_t tw1 = calc_text_width(numupdown->max); - uint8_t tw2 = calc_text_width(numupdown->min); - if(tw2 > tw1) tw1 = tw2; - uint8_t width= tft_font_width(0)*(tw1+1); - - //Draw background and label of the number area - tft_fill_rectangle(numupdown->buttonDown.base.x2+2,numupdown->y,numupdown->buttonDown.base.x2+width,numupdown->buttonUp.base.y2,BASE_COLOR); - tft_print_formatted(numupdown->buttonDown.base.x2+2+tft_font_width(0)/2,numupdown->y+tft_font_height(0)/2,numupdown->fgcolor,BASE_COLOR,0,"%*d",tw1,numupdown->value); -} - - +/************************************************************************************************************************************** +* Project: discoverpixy +* Website: https://github.com/t-moe/discoverpixy +* Authors: Aaron Schmocker, Timo Lang +* Institution: BFH Bern University of Applied Sciences +* File: common/gui/numupdown.c +* +* Version History: +* Date Autor Email SHA Changes +* 2015-04-30 timolang@gmail.com 76ea9d8 Added num up down support. +* 2015-04-30 timolang@gmail.com b491b78 Made numupdown horizontal +* 2015-05-15 timolang@gmail.com 9a16865 Added doxgen comments to filesyste, checkbox, numupdown and screen module. And some minor changes to the other modules. +* 2015-05-17 timolang@gmail.com 2d46336 Improved comments in implementation of button, checkbox, numupdown, tft, touch and screen modules/submodules. +* +**************************************************************************************************************************************/ + +#include "tft.h" +#include "touch.h" +#include "button.h" +#include "numupdown.h" +#include //for sprintf +#include //for offsetof macro +#include //for abs + +/* The idea is as follows: + * When the user add's a numupdown we create two buttons, one with a plus and one with a minus sign in it + * When the user presses one of the buttons we check and increase the value and execute the provided user callback + */ + + +#define BASE_COLOR RGB(90,90,90) //Background color for the whole element + +//Callback which is called when the user presses the "plus" button +void button_up_cb(void* button) +{ + //Get the pointer to the numupdown: subtract the offset of the buttonUp member in the struct from the button pointer + NUMUPDOWN_STRUCT* element = button - offsetof(NUMUPDOWN_STRUCT, buttonUp); + + if (element->value < element->max) { //old value lies below the maximum + element->value++; //let's increase the value + gui_numupdown_update(element); //and redraw everything + + if (element->callback != NULL) { //the user provided a callback + element->callback(element, element->value); //Call the user callback with the new value + } + } +} + +//Callback which is called when the user presses the "minus" button +void button_down_cb(void* button) +{ + //Get the pointer to the numupdown: subtract the offset of the buttonDown member in the struct from the button pointer + NUMUPDOWN_STRUCT* element = button - offsetof(NUMUPDOWN_STRUCT, buttonDown); + + if (element->value > element->min) { //old value lies above the minimum + element->value--; //let's decrease the value + gui_numupdown_update(element); //and redraw everything + + if (element->callback != NULL) { //the user provided a callback + element->callback(element, element->value); //Call the user callback with the new value + } + } +} + +//Method to calculate the number of characters needed to print the provided number in decimal notation (with optional sign) +static uint8_t calc_text_width(int16_t val) +{ + uint8_t width = 1 + (val < 0); //1 if positive, 2 if negative (to let space for sign) + val = abs(val); //Make the number positive + + while (val >= 10) { //while we have two or more digits + val /= 10; //remove one digit + width++; //add one character + } + + return width; +} + + +bool gui_numupdown_add(NUMUPDOWN_STRUCT* numupdown) +{ + if (touch_have_empty(2)) { //Check if the touch module can handle two additional areas + if (numupdown->min > numupdown->max) { //min is bigger than max? + return false; //invalid parameter + } + + if (numupdown->value < numupdown->min) { //value is smaller than min? + numupdown->value = numupdown->min; //normalize value + } else if (numupdown->value > numupdown->max) { //value is bigger than max? + numupdown->value = numupdown->max; //normalize value + } + + uint8_t tw1 = calc_text_width(numupdown->max); //Calculate character width to render maximum value + uint8_t tw2 = calc_text_width(numupdown->min); //Calculate character width to render minimum value + + if (tw2 > tw1) { + tw1 = tw2; //ensure tw1 contains the larger number of the two + } + + uint8_t width = tft_font_width(0) * (tw1 + 1); //Calculate width of the number area + + //Add "minus" button to the left side of the number area + numupdown->buttonDown.base.x1 = numupdown->x; + numupdown->buttonDown.base.y1 = numupdown->y; + numupdown->buttonDown.base.x2 = AUTO; + numupdown->buttonDown.base.y2 = numupdown->y + tft_font_height(0) * 2; + numupdown->buttonDown.text = "-"; + numupdown->buttonDown.font = 0; + numupdown->buttonDown.bgcolor = BASE_COLOR; + numupdown->buttonDown.txtcolor = WHITE; + numupdown->buttonDown.callback = button_down_cb; + gui_button_add(&numupdown->buttonDown); + + //Add "plus" button to the right side of the number area + numupdown->buttonUp.base.x1 = numupdown->buttonDown.base.x2 + width + 2; + numupdown->buttonUp.base.y1 = numupdown->y; + numupdown->buttonUp.base.x2 = AUTO; + numupdown->buttonUp.base.y2 = numupdown->y + tft_font_height(0) * 2; + numupdown->buttonUp.text = "+"; + numupdown->buttonUp.font = 0; + numupdown->buttonUp.bgcolor = BASE_COLOR; + numupdown->buttonUp.txtcolor = WHITE; + numupdown->buttonUp.callback = button_up_cb; + gui_button_add(&numupdown->buttonUp); + + //Draw background and label of the number area + tft_fill_rectangle(numupdown->buttonDown.base.x2 + 2, numupdown->y, numupdown->buttonDown.base.x2 + width, numupdown->buttonUp.base.y2, BASE_COLOR); + tft_print_formatted(numupdown->buttonDown.base.x2 + 2 + tft_font_width(0) / 2, numupdown->y + tft_font_height(0) / 2, numupdown->fgcolor, BASE_COLOR, 0, "%*d", tw1, numupdown->value); + + return true; + } + + return false; //not enough touch areas left +} + +void gui_numupdown_remove(NUMUPDOWN_STRUCT* numupdown) +{ + //remove the two buttons, we have no other allocated resources + gui_button_remove(&numupdown->buttonUp); + gui_button_remove(&numupdown->buttonDown); +} + + +void gui_numupdown_redraw(NUMUPDOWN_STRUCT* numupdown) +{ + //redraw the two buttons + gui_button_redraw(&numupdown->buttonUp); + gui_button_redraw(&numupdown->buttonDown); + + //call update method which will take care of the number-area rendering + gui_numupdown_update(numupdown); +} + +void gui_numupdown_update(NUMUPDOWN_STRUCT* numupdown) +{ + //Calculate the number area width again (see above) + uint8_t tw1 = calc_text_width(numupdown->max); + uint8_t tw2 = calc_text_width(numupdown->min); + + if (tw2 > tw1) { + tw1 = tw2; + } + + uint8_t width = tft_font_width(0) * (tw1 + 1); + + //Draw background and label of the number area + tft_fill_rectangle(numupdown->buttonDown.base.x2 + 2, numupdown->y, numupdown->buttonDown.base.x2 + width, numupdown->buttonUp.base.y2, BASE_COLOR); + tft_print_formatted(numupdown->buttonDown.base.x2 + 2 + tft_font_width(0) / 2, numupdown->y + tft_font_height(0) / 2, numupdown->fgcolor, BASE_COLOR, 0, "%*d", tw1, numupdown->value); +} diff --git a/common/gui/numupdown.h b/common/gui/numupdown.h index 5734787..80716b9 100644 --- a/common/gui/numupdown.h +++ b/common/gui/numupdown.h @@ -1,73 +1,88 @@ -#ifndef NUMUPDOWN_H -#define NUMUPDOWN_H - -#include "button.h" - -/** - * @addtogroup gui - */ -/*@{*/ - -/** - * @defgroup numupdown NummericUpDown - * The NummericUpDown Gui Element - */ -/*@}*/ - -/** - * @addtogroup numupdown - */ -/*@{*/ - -/** - * Prototype for Event Listeners (called when the NummericUpDown value has changed) - * \note You should NOT execute long running things in this callback nor should you update the gui. But you can call gui_screen_navigate() for instance. - * @param numupdown The pointer to the NUMUPDOWN_STRUCT where to corresponding NummericUpDown has changed it's value - * @param value The new value of the NummericUpDown - */ -typedef void (*NUMUPDOWN_CALLBACK)(void *numupdown, int16_t value); - -/** - * Structure to configure the NummericUpDown - */ -typedef struct { - uint16_t x; //!< The x-Coordinate of the Top-Left Starting Point. - uint16_t y; //!< The y-Coordinate of the Top-Left Starting Point. - uint16_t fgcolor; //!< The 16-bit color of the value-text - int16_t value; //!< The current/default value - int16_t min; //!< The minimum possible value (inclusive) - int16_t max; //!< The maximum possible value (inclusive) - NUMUPDOWN_CALLBACK callback; //!< Callback which is executed when the value changes - - BUTTON_STRUCT buttonUp; //!< For internal use, don't change, don't initialize - BUTTON_STRUCT buttonDown; //!< For internal use, don't change, don't initialize -} NUMUPDOWN_STRUCT; - -/** - * Adds a NummericUpDown. Your Callback will be called from now on, if the numupdown's value changes - * @param numupdown A Pointer to the preinitialized NUMUPDOWN_STRUCT - * @return true on success - */ -bool gui_numupdown_add(NUMUPDOWN_STRUCT* numupdown); - -/** - * Removes the NummericUpDown. You will no longer receive events for this numupdown. This function will not overdraw the region where the numupdown was located. - * @param numupdown A Pointer to the NUMUPDOWN_STRUCT - */ -void gui_numupdown_remove(NUMUPDOWN_STRUCT* numupdown); - -/** - * Updates the NummericUpDown. Call this function when you change the value/min/max of the numupdown through code. - * @param numupdown A Pointer to the NUMUPDOWN_STRUCT - */ -void gui_numupdown_update(NUMUPDOWN_STRUCT* numupdown); - -/** - * Redraws the NummericUpDown. Call this method if you have to redraw the entire screen or if you want to draw a numupdown on top of an image. - * @param numupdown A Pointer to the NUMUPDOWN_STRUCT - */ -void gui_numupdown_redraw(NUMUPDOWN_STRUCT* numupdown); - -/*@}*/ - -#endif /* NUMUPDOWN_H */ +/************************************************************************************************************************************** +* Project: discoverpixy +* Website: https://github.com/t-moe/discoverpixy +* Authors: Aaron Schmocker, Timo Lang +* Institution: BFH Bern University of Applied Sciences +* File: common/gui/numupdown.h +* +* Version History: +* Date Autor Email SHA Changes +* 2015-04-30 timolang@gmail.com 76ea9d8 Added num up down support. +* 2015-05-11 timolang@gmail.com 08d9fe0 More work on doxygen module structure +* 2015-05-15 timolang@gmail.com 9a16865 Added doxgen comments to filesyste, checkbox, numupdown and screen module. And some minor changes to the other modules. +* +**************************************************************************************************************************************/ + +#ifndef NUMUPDOWN_H +#define NUMUPDOWN_H + +#include "button.h" + +/** + * @addtogroup gui + */ +/*@{*/ + +/** + * @defgroup numupdown NummericUpDown + * The NummericUpDown Gui Element + */ +/*@}*/ + +/** + * @addtogroup numupdown + */ +/*@{*/ + +/** + * Prototype for Event Listeners (called when the NummericUpDown value has changed) + * \note You should NOT execute long running things in this callback nor should you update the gui. But you can call gui_screen_navigate() for instance. + * @param numupdown The pointer to the NUMUPDOWN_STRUCT where to corresponding NummericUpDown has changed it's value + * @param value The new value of the NummericUpDown + */ +typedef void (*NUMUPDOWN_CALLBACK)(void* numupdown, int16_t value); + +/** + * Structure to configure the NummericUpDown + */ +typedef struct { + uint16_t x; //!< The x-Coordinate of the Top-Left Starting Point. + uint16_t y; //!< The y-Coordinate of the Top-Left Starting Point. + uint16_t fgcolor; //!< The 16-bit color of the value-text + int16_t value; //!< The current/default value + int16_t min; //!< The minimum possible value (inclusive) + int16_t max; //!< The maximum possible value (inclusive) + NUMUPDOWN_CALLBACK callback; //!< Callback which is executed when the value changes + + BUTTON_STRUCT buttonUp; //!< For internal use, don't change, don't initialize + BUTTON_STRUCT buttonDown; //!< For internal use, don't change, don't initialize +} NUMUPDOWN_STRUCT; + +/** + * Adds a NummericUpDown. Your Callback will be called from now on, if the numupdown's value changes + * @param numupdown A Pointer to the preinitialized NUMUPDOWN_STRUCT + * @return true on success + */ +bool gui_numupdown_add(NUMUPDOWN_STRUCT* numupdown); + +/** + * Removes the NummericUpDown. You will no longer receive events for this numupdown. This function will not overdraw the region where the numupdown was located. + * @param numupdown A Pointer to the NUMUPDOWN_STRUCT + */ +void gui_numupdown_remove(NUMUPDOWN_STRUCT* numupdown); + +/** + * Updates the NummericUpDown. Call this function when you change the value/min/max of the numupdown through code. + * @param numupdown A Pointer to the NUMUPDOWN_STRUCT + */ +void gui_numupdown_update(NUMUPDOWN_STRUCT* numupdown); + +/** + * Redraws the NummericUpDown. Call this method if you have to redraw the entire screen or if you want to draw a numupdown on top of an image. + * @param numupdown A Pointer to the NUMUPDOWN_STRUCT + */ +void gui_numupdown_redraw(NUMUPDOWN_STRUCT* numupdown); + +/*@}*/ + +#endif /* NUMUPDOWN_H */ diff --git a/common/gui/screen.c b/common/gui/screen.c index 8eb3072..2f97f98 100644 --- a/common/gui/screen.c +++ b/common/gui/screen.c @@ -1,3 +1,21 @@ +/************************************************************************************************************************************** +* Project: discoverpixy +* Website: https://github.com/t-moe/discoverpixy +* Authors: Aaron Schmocker, Timo Lang +* Institution: BFH Bern University of Applied Sciences +* File: common/gui/screen.c +* +* Version History: +* Date Autor Email SHA Changes +* 2015-04-27 timolang@gmail.com cf72baa Introduced a Screen (sub) module and divided app into multiple screens. +* 2015-04-27 timolang@gmail.com 77e6d0e Fixed screen implementation. +* 2015-05-10 timolang@gmail.com b6ab7c8 Fixed compiler warning in tft and screen module. +* 2015-05-17 timolang@gmail.com 2d46336 Improved comments in implementation of button, checkbox, numupdown, tft, touch and screen modules/submodules. +* 2015-06-01 timolang@gmail.com eb573bc Finalized calibration. Fixed a bug in screen module. +* 2015-06-06 timolang@gmail.com c06661d Fixed some outdated comments in source code. Documented Gui Module in docu. +* +**************************************************************************************************************************************/ + #include "screen.h" /* The idea is as follows: @@ -14,62 +32,79 @@ static SCREEN_STRUCT* screen_list = NULL; //Head of the linked list which stores static SCREEN_STRUCT* screen_current = NULL; //Pointer to the current screen (= tail of the list) static volatile SCREEN_STRUCT* screen_goto = NULL; //Screen we should navigate to once we enter the gui_screen_update() method again -SCREEN_STRUCT* gui_screen_get_current() { - return screen_current; +SCREEN_STRUCT* gui_screen_get_current() +{ + return screen_current; } -void gui_screen_update() { - if(screen_goto!=NULL) { //we received the task to switch the screen - SCREEN_STRUCT* go = (SCREEN_STRUCT*) screen_goto; //Backup volatile variable - screen_goto=NULL; //reset the "goto instruction", since we're processing it now - if(go->next!=NULL) { //The screen is not the last in the list, so we're going back - if(go->next!=screen_current) { //this condition should always be false - return; //list corrupted? - } - screen_current->on_leave(screen_current); //let the current screen free/unregister it's resources - go->next=NULL; //remove the current screen from the list - } else { //we're going forward (to a new screen) - if(screen_current!=NULL) { //this is not the first screen - screen_current->on_leave(screen_current); //let the current screen free/unregister it's resources - screen_current->next = go; //append the new screen to the end of the list - } else { //first screen ever seen - screen_list=go; //set the new screen as list-head - } - } - go->on_enter(go); //let the new screen allocate/register it's resources - screen_current = go; //the new screen is now the current screen. Transition done - } +void gui_screen_update() +{ + if (screen_goto != NULL) { //we received the task to switch the screen + SCREEN_STRUCT* go = (SCREEN_STRUCT*) screen_goto; //Backup volatile variable + screen_goto = NULL; //reset the "goto instruction", since we're processing it now - if(screen_current!=NULL) { //A screen has been set - screen_current->on_update(screen_current); //Update current screen - } + if (go->next != NULL) { //The screen is not the last in the list, so we're going back + if (go->next != screen_current) { //this condition should always be false + return; //list corrupted? + } + + screen_current->on_leave(screen_current); //let the current screen free/unregister it's resources + go->next = NULL; //remove the current screen from the list + } else { //we're going forward (to a new screen) + if (screen_current != NULL) { //this is not the first screen + screen_current->on_leave(screen_current); //let the current screen free/unregister it's resources + screen_current->next = go; //append the new screen to the end of the list + } else { //first screen ever seen + screen_list = go; //set the new screen as list-head + } + } + + go->on_enter(go); //let the new screen allocate/register it's resources + screen_current = go; //the new screen is now the current screen. Transition done + } + + if (screen_current != NULL) { //A screen has been set + screen_current->on_update(screen_current); //Update current screen + } } -bool gui_screen_navigate(SCREEN_STRUCT* screen) { - if(screen==NULL || screen==screen_current || screen==screen_goto) { //invalid argument passed - return false; - } - screen->next = NULL; //this will become the new tail of the list, so the next pointer must be NULL - screen_goto=screen; //"send message" to main loop, to switch the screen - return true; +bool gui_screen_navigate(SCREEN_STRUCT* screen) +{ + if (screen == NULL || screen == screen_current || screen == screen_goto) { //invalid argument passed + return false; + } + + screen->next = NULL; //this will become the new tail of the list, so the next pointer must be NULL + screen_goto = screen; //"send message" to main loop, to switch the screen + return true; } -bool gui_screen_back() { - if(screen_list==NULL) { //the list head is emtpy, nothing to go back to - return false; - } - SCREEN_STRUCT* current = screen_list; - SCREEN_STRUCT* last = NULL; - //Find second last element in list - while(current->next != NULL) { - last = current; - current = current->next; - } - if(last==NULL) return false; //There's only a single screen, there's no going back here - if(current!=screen_current) return false; //The last entry in the list is not the current screen. List corrupted? - screen_goto=last; //"send message" to main loop, to switch the screen - return true; +bool gui_screen_back() +{ + if (screen_list == NULL) { //the list head is emtpy, nothing to go back to + return false; + } + + SCREEN_STRUCT* current = screen_list; + SCREEN_STRUCT* last = NULL; + + //Find second last element in list + while (current->next != NULL) { + last = current; + current = current->next; + } + + if (last == NULL) { + return false; //There's only a single screen, there's no going back here + } + + if (current != screen_current) { + return false; //The last entry in the list is not the current screen. List corrupted? + } + + screen_goto = last; //"send message" to main loop, to switch the screen + return true; } diff --git a/common/gui/screen.h b/common/gui/screen.h index 8ef82a2..f14a0b5 100644 --- a/common/gui/screen.h +++ b/common/gui/screen.h @@ -1,3 +1,21 @@ +/************************************************************************************************************************************** +* Project: discoverpixy +* Website: https://github.com/t-moe/discoverpixy +* Authors: Aaron Schmocker, Timo Lang +* Institution: BFH Bern University of Applied Sciences +* File: common/gui/screen.h +* +* Version History: +* Date Autor Email SHA Changes +* 2015-04-27 timolang@gmail.com cf72baa Introduced a Screen (sub) module and divided app into multiple screens. +* 2015-04-27 timolang@gmail.com 77e6d0e Fixed screen implementation. +* 2015-05-11 timolang@gmail.com 08d9fe0 More work on doxygen module structure +* 2015-05-15 timolang@gmail.com 9a16865 Added doxgen comments to filesyste, checkbox, numupdown and screen module. And some minor changes to the other modules. +* 2015-05-17 timolang@gmail.com 2d46336 Improved comments in implementation of button, checkbox, numupdown, tft, touch and screen modules/submodules. +* 2015-06-06 timolang@gmail.com c06661d Fixed some outdated comments in source code. Documented Gui Module in docu. +* +**************************************************************************************************************************************/ + #ifndef SCREEN_H #define SCREEN_H @@ -12,7 +30,7 @@ /** * @defgroup screen Screen * The Screen Submodule provides an api to navigate between different "screens" on the UI. - * Each screen must provide an enter, update and a leave method; which will be called from this module at the right time. + * Each screen must provide an enter, update and a leave method; which will be called from this module at the right time. * The implemented screens of the application are documented in the \ref screens module. */ /*@}*/ @@ -31,12 +49,12 @@ typedef void (*SCREEN_CALLBACK)(void* screen); /** * Structure to configure the Screen */ -typedef struct SCREEN_S{ - SCREEN_CALLBACK on_enter; //!< The Callback which is called when the screen is entered. Add/Register all UI-Elements here - SCREEN_CALLBACK on_leave; //!< The Callback which is called when the screen is left. Remove/Unregister all UI-Elements here - SCREEN_CALLBACK on_update; //!< The Callback which is called repeatedly when the screen should be updated. Update/Redraw all UI-Elements here +typedef struct SCREEN_S { + SCREEN_CALLBACK on_enter; //!< The Callback which is called when the screen is entered. Add/Register all UI-Elements here + SCREEN_CALLBACK on_leave; //!< The Callback which is called when the screen is left. Remove/Unregister all UI-Elements here + SCREEN_CALLBACK on_update; //!< The Callback which is called repeatedly when the screen should be updated. Update/Redraw all UI-Elements here - struct SCREEN_S* next; //!< Used internally. do not modify, do not initialize + struct SCREEN_S* next; //!< Used internally. do not modify, do not initialize } SCREEN_STRUCT; diff --git a/common/lowlevel/ll_filesystem.h b/common/lowlevel/ll_filesystem.h index 8833b1f..e1d2f08 100644 --- a/common/lowlevel/ll_filesystem.h +++ b/common/lowlevel/ll_filesystem.h @@ -1,3 +1,17 @@ +/************************************************************************************************************************************** +* Project: discoverpixy +* Website: https://github.com/t-moe/discoverpixy +* Authors: Aaron Schmocker, Timo Lang +* Institution: BFH Bern University of Applied Sciences +* File: common/lowlevel/ll_filesystem.h +* +* Version History: +* Date Autor Email SHA Changes +* 2015-05-10 timolang@gmail.com e2bce8f Added filesystem module, tests and implementation for it in emulator. +* 2015-05-15 timolang@gmail.com 9a16865 Added doxgen comments to filesyste, checkbox, numupdown and screen module. And some minor changes to the other modules. +* +**************************************************************************************************************************************/ + #include "filesystem.h" /** diff --git a/common/lowlevel/ll_system.h b/common/lowlevel/ll_system.h index be422fb..6166283 100644 --- a/common/lowlevel/ll_system.h +++ b/common/lowlevel/ll_system.h @@ -1,3 +1,21 @@ +/************************************************************************************************************************************** +* Project: discoverpixy +* Website: https://github.com/t-moe/discoverpixy +* Authors: Aaron Schmocker, Timo Lang +* Institution: BFH Bern University of Applied Sciences +* File: common/lowlevel/ll_system.h +* +* Version History: +* Date Autor Email SHA Changes +* 2015-04-03 timolang@gmail.com 1f2af9f Added more tft functions to common and emulator. Fixed eventloop. +* 2015-04-03 timolang@gmail.com cab8609 Integrated pixy into emulator. Pixy is no longer in the common/libs folder but in emulator/libs and discovery/libs +* 2015-04-03 timolang@gmail.com 9a1d12a Refactored discovery, to use new project structure. Almost ready. +* 2015-04-25 timolang@gmail.com 3d1e4b2 Simplified code a bit. Emulator does not work stable when replugging pixy. +* 2015-04-25 timolang@gmail.com 0858b0d Fixed some bugs when receiving large data. +* 2015-05-15 timolang@gmail.com 9a16865 Added doxgen comments to filesyste, checkbox, numupdown and screen module. And some minor changes to the other modules. +* +**************************************************************************************************************************************/ + #include #include diff --git a/common/lowlevel/ll_tft.h b/common/lowlevel/ll_tft.h index d7ac730..52a5168 100644 --- a/common/lowlevel/ll_tft.h +++ b/common/lowlevel/ll_tft.h @@ -1,3 +1,24 @@ +/************************************************************************************************************************************** +* Project: discoverpixy +* Website: https://github.com/t-moe/discoverpixy +* Authors: Aaron Schmocker, Timo Lang +* Institution: BFH Bern University of Applied Sciences +* File: common/lowlevel/ll_tft.h +* +* Version History: +* Date Autor Email SHA Changes +* 2015-04-03 timolang@gmail.com 51089aa Refactored Project Structure for use with emulator +* 2015-04-03 timolang@gmail.com 1f2af9f Added more tft functions to common and emulator. Fixed eventloop. +* 2015-04-03 timolang@gmail.com 9a1d12a Refactored discovery, to use new project structure. Almost ready. +* 2015-04-03 timolang@gmail.com 1aa9194 Fixed Drawing of rects in Emulator. Got frames from pixy to emulator. Slooooow. +* 2015-04-27 aaron@duckpond.ch aed90ef Drawcircle added (emulator) +* 2015-04-27 timolang@gmail.com e249fb2 Added font support +* 2015-04-27 aaron@duckpond.ch f0a6c3b Implemented init functions for gpio, fsmc and display +* 2015-04-27 aaron@duckpond.ch 0b61f21 Fixed misplacement of prototypes in ll_tft.h and implemented a propper init function. +* 2015-05-15 timolang@gmail.com 9a16865 Added doxgen comments to filesyste, checkbox, numupdown and screen module. And some minor changes to the other modules. +* +**************************************************************************************************************************************/ + #include #include @@ -24,10 +45,10 @@ bool ll_tft_init(); // draw functions void ll_tft_clear(uint16_t color); void ll_tft_draw_line(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color); -void ll_tft_draw_pixel(uint16_t x,uint16_t y,uint16_t color); -void ll_tft_draw_rectangle(uint16_t x1,uint16_t y1,uint16_t x2,uint16_t y2, uint16_t color); -void ll_tft_fill_rectangle(uint16_t x1,uint16_t y1,uint16_t x2,uint16_t y2, uint16_t color); -void ll_tft_draw_bitmap_unscaled(uint16_t x, uint16_t y, uint16_t width, uint16_t height, const uint16_t *dat); +void ll_tft_draw_pixel(uint16_t x, uint16_t y, uint16_t color); +void ll_tft_draw_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color); +void ll_tft_fill_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color); +void ll_tft_draw_bitmap_unscaled(uint16_t x, uint16_t y, uint16_t width, uint16_t height, const uint16_t* dat); void ll_tft_draw_circle(uint16_t x, uint16_t y, uint16_t r, uint16_t color); @@ -37,5 +58,3 @@ uint8_t ll_tft_font_width(uint8_t fontnum); void ll_tft_draw_char(uint16_t x, uint16_t y, uint16_t color, uint16_t bgcolor, uint8_t font, char c); /*@}*/ - - diff --git a/common/lowlevel/ll_touch.h b/common/lowlevel/ll_touch.h index c61b42e..4c5237b 100644 --- a/common/lowlevel/ll_touch.h +++ b/common/lowlevel/ll_touch.h @@ -1,3 +1,17 @@ +/************************************************************************************************************************************** +* Project: discoverpixy +* Website: https://github.com/t-moe/discoverpixy +* Authors: Aaron Schmocker, Timo Lang +* Institution: BFH Bern University of Applied Sciences +* File: common/lowlevel/ll_touch.h +* +* Version History: +* Date Autor Email SHA Changes +* 2015-04-27 timolang@gmail.com 259d446 Added touch support to emulator. Implemented basic touch function. +* 2015-05-15 timolang@gmail.com 9a16865 Added doxgen comments to filesyste, checkbox, numupdown and screen module. And some minor changes to the other modules. +* +**************************************************************************************************************************************/ + #include #include diff --git a/common/system/system.c b/common/system/system.c index f7a88cb..48d84d0 100644 --- a/common/system/system.c +++ b/common/system/system.c @@ -1,19 +1,39 @@ +/************************************************************************************************************************************** +* Project: discoverpixy +* Website: https://github.com/t-moe/discoverpixy +* Authors: Aaron Schmocker, Timo Lang +* Institution: BFH Bern University of Applied Sciences +* File: common/system/system.c +* +* Version History: +* Date Autor Email SHA Changes +* 2015-04-03 timolang@gmail.com 1f2af9f Added more tft functions to common and emulator. Fixed eventloop. +* 2015-04-03 timolang@gmail.com cab8609 Integrated pixy into emulator. Pixy is no longer in the common/libs folder but in emulator/libs and discovery/libs +* 2015-04-25 timolang@gmail.com 3d1e4b2 Simplified code a bit. Emulator does not work stable when replugging pixy. +* 2015-04-25 timolang@gmail.com 0858b0d Fixed some bugs when receiving large data. +* +**************************************************************************************************************************************/ + #include "system.h" #include "ll_system.h" -bool system_init() { - return ll_system_init(); +bool system_init() +{ + return ll_system_init(); } -void system_delay(uint32_t msec) { - ll_system_delay(msec); +void system_delay(uint32_t msec) +{ + ll_system_delay(msec); } -void system_process() { - ll_system_process(); +void system_process() +{ + ll_system_process(); } -void system_toggle_led() { - ll_system_toggle_led(); +void system_toggle_led() +{ + ll_system_toggle_led(); } diff --git a/common/system/system.h b/common/system/system.h index 7c22a68..53a06c3 100644 --- a/common/system/system.h +++ b/common/system/system.h @@ -1,3 +1,21 @@ +/************************************************************************************************************************************** +* Project: discoverpixy +* Website: https://github.com/t-moe/discoverpixy +* Authors: Aaron Schmocker, Timo Lang +* Institution: BFH Bern University of Applied Sciences +* File: common/system/system.h +* +* Version History: +* Date Autor Email SHA Changes +* 2015-04-03 timolang@gmail.com 1f2af9f Added more tft functions to common and emulator. Fixed eventloop. +* 2015-04-03 timolang@gmail.com cab8609 Integrated pixy into emulator. Pixy is no longer in the common/libs folder but in emulator/libs and discovery/libs +* 2015-04-25 timolang@gmail.com 3d1e4b2 Simplified code a bit. Emulator does not work stable when replugging pixy. +* 2015-04-25 timolang@gmail.com 0858b0d Fixed some bugs when receiving large data. +* 2015-05-11 timolang@gmail.com 08d9fe0 More work on doxygen module structure +* 2015-05-15 timolang@gmail.com 9a16865 Added doxgen comments to filesyste, checkbox, numupdown and screen module. And some minor changes to the other modules. +* +**************************************************************************************************************************************/ + #ifndef SYSTEM_H #define SYSTEM_H diff --git a/common/tft/tft.c b/common/tft/tft.c index 0b5679a..6b6f4d0 100644 --- a/common/tft/tft.c +++ b/common/tft/tft.c @@ -1,3 +1,24 @@ +/************************************************************************************************************************************** +* Project: discoverpixy +* Website: https://github.com/t-moe/discoverpixy +* Authors: Aaron Schmocker, Timo Lang +* Institution: BFH Bern University of Applied Sciences +* File: common/tft/tft.c +* +* Version History: +* Date Autor Email SHA Changes +* 2015-04-03 timolang@gmail.com 51089aa Refactored Project Structure for use with emulator +* 2015-04-03 timolang@gmail.com 1f2af9f Added more tft functions to common and emulator. Fixed eventloop. +* 2015-04-03 timolang@gmail.com 1aa9194 Fixed Drawing of rects in Emulator. Got frames from pixy to emulator. Slooooow. +* 2015-04-27 aaron@duckpond.ch aed90ef Drawcircle added (emulator) +* 2015-04-27 timolang@gmail.com e249fb2 Added font support +* 2015-04-30 timolang@gmail.com 76ea9d8 Added num up down support. +* 2015-05-10 timolang@gmail.com b6ab7c8 Fixed compiler warning in tft and screen module. +* 2015-05-15 timolang@gmail.com b08a897 Added tft method to draw a bmp from filesystem. Added another font to emulator. +* 2015-05-17 timolang@gmail.com 2d46336 Improved comments in implementation of button, checkbox, numupdown, tft, touch and screen modules/submodules. +* +**************************************************************************************************************************************/ + #include "tft.h" #include "ll_tft.h" #include @@ -15,129 +36,148 @@ * For formatted printing implement putchar, instead of writing into a buffer and drawing that buffer afterwards */ -bool tft_init() { - return ll_tft_init(); +bool tft_init() +{ + return ll_tft_init(); } -void tft_clear(uint16_t color) { - ll_tft_clear(color); +void tft_clear(uint16_t color) +{ + ll_tft_clear(color); } -void tft_draw_line(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color) { - ll_tft_draw_line(x1,y1,x2,y2,color); +void tft_draw_line(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color) +{ + ll_tft_draw_line(x1, y1, x2, y2, color); } -void tft_draw_pixel(uint16_t x,uint16_t y,uint16_t color) { - ll_tft_draw_pixel(x,y,color); +void tft_draw_pixel(uint16_t x, uint16_t y, uint16_t color) +{ + ll_tft_draw_pixel(x, y, color); } -void tft_draw_rectangle(uint16_t x1,uint16_t y1,uint16_t x2,uint16_t y2, uint16_t color) { - //could be implemented with 4 lines instead of introducing a ll func - ll_tft_draw_rectangle(x1,y1,x2,y2,color); +void tft_draw_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color) +{ + //could be implemented with 4 lines instead of introducing a ll func + ll_tft_draw_rectangle(x1, y1, x2, y2, color); } -void tft_fill_rectangle(uint16_t x1,uint16_t y1,uint16_t x2,uint16_t y2, uint16_t color) { - ll_tft_fill_rectangle(x1,y1,x2,y2,color); +void tft_fill_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color) +{ + ll_tft_fill_rectangle(x1, y1, x2, y2, color); } -void tft_draw_bitmap_unscaled(uint16_t x, uint16_t y, uint16_t width, uint16_t height, const uint16_t* dat) { - ll_tft_draw_bitmap_unscaled(x,y,width,height,dat); +void tft_draw_bitmap_unscaled(uint16_t x, uint16_t y, uint16_t width, uint16_t height, const uint16_t* dat) +{ + ll_tft_draw_bitmap_unscaled(x, y, width, height, dat); } -void tft_draw_circle(uint16_t x, uint16_t y, uint16_t r, uint16_t color) { +void tft_draw_circle(uint16_t x, uint16_t y, uint16_t r, uint16_t color) +{ ll_tft_draw_circle(x, y, r, color); } -uint8_t tft_num_fonts() { - return ll_tft_num_fonts(); +uint8_t tft_num_fonts() +{ + return ll_tft_num_fonts(); } -uint8_t tft_font_height(uint8_t fontnum) { - return ll_tft_font_height(fontnum); +uint8_t tft_font_height(uint8_t fontnum) +{ + return ll_tft_font_height(fontnum); } -uint8_t tft_font_width(uint8_t fontnum) { - return ll_tft_font_width(fontnum); +uint8_t tft_font_width(uint8_t fontnum) +{ + return ll_tft_font_width(fontnum); } //Print line can be done with multiple calls to draw_char -void tft_print_line(uint16_t x, uint16_t y, uint16_t color, uint16_t bgcolor, uint8_t font, const char* text) { - if(font>=ll_tft_num_fonts()) return; //invalid font index - for(int i=0; i= ll_tft_num_fonts()) { + return; //invalid font index + } + + for (int i = 0; i < strlen(text); i++) { //for each char in the line + ll_tft_draw_char(x, y, color, bgcolor, font, text[i]); //draw the char + x += ll_tft_font_width(font); //and increase the x position + } } //Printing a formatted line can be done by printing the line in a buffer using "sprintf" and then calling print_line -void tft_print_formatted(uint16_t x, uint16_t y, uint16_t color, uint16_t bgcolor, uint8_t font, const char* format, ...) { - static char buffer[128]; //buffer to save the formatted text into +void tft_print_formatted(uint16_t x, uint16_t y, uint16_t color, uint16_t bgcolor, uint8_t font, const char* format, ...) +{ + static char buffer[128]; //buffer to save the formatted text into - //Since we have variable arguments, we need to forward them. We have to use vsprintf instead of sprintf for that. - va_list args; - va_start (args, format); //start the varg-list - vsprintf(buffer,format,args); //let vsprintf render the formatted string - tft_print_line(x,y,color,bgcolor,font,buffer); //print the string as normal text - va_end(args); //end the varg-list + //Since we have variable arguments, we need to forward them. We have to use vsprintf instead of sprintf for that. + va_list args; + va_start(args, format); //start the varg-list + vsprintf(buffer, format, args); //let vsprintf render the formatted string + tft_print_line(x, y, color, bgcolor, font, buffer); //print the string as normal text + va_end(args); //end the varg-list } -bool tft_draw_bitmap_file_unscaled(uint16_t x, uint16_t y, const char* filename) { - //This method reads a .bmp file from the filesystem and tries to draw it. - //Note: The bmp implementation is not complete, it has some limitations and it makes assumptions. See doxygen comment for this method. - //Source Copied and adapted from: http://stackoverflow.com/a/17040962/2606757 +bool tft_draw_bitmap_file_unscaled(uint16_t x, uint16_t y, const char* filename) +{ + //This method reads a .bmp file from the filesystem and tries to draw it. + //Note: The bmp implementation is not complete, it has some limitations and it makes assumptions. See doxygen comment for this method. + //Source Copied and adapted from: http://stackoverflow.com/a/17040962/2606757 - FILE_HANDLE* file = filesystem_file_open(filename); //try to open the file - if(file==NULL) { //file opening failed - return false; - } + FILE_HANDLE* file = filesystem_file_open(filename); //try to open the file - unsigned char info[54]; - if(filesystem_file_read(file,info,54)!=F_OK) { //try to read the 54 byte header - filesystem_file_close(file); - return false; //reading the header failed - } + if (file == NULL) { //file opening failed + return false; + } - // extract image height and width from header - uint32_t width = *(uint32_t*)&info[18]; //width in pixel - uint32_t height = *(uint32_t*)&info[22]; //height in pixel - uint16_t depth = *(uint16_t*)&info[28]; //bit's per pixel (color depth) - depth/=8; //we want the number of bytes per pixel + unsigned char info[54]; - filesystem_file_seek(file,*(uint32_t*)&info[10]); //seek to the place where img data begins + if (filesystem_file_read(file, info, 54) != F_OK) { //try to read the 54 byte header + filesystem_file_close(file); + return false; //reading the header failed + } - uint32_t row_padded = (width*depth + 3) & (~3); //row size must be aligned to 4 bytes + // extract image height and width from header + uint32_t width = *(uint32_t*)&info[18]; //width in pixel + uint32_t height = *(uint32_t*)&info[22]; //height in pixel + uint16_t depth = *(uint16_t*)&info[28]; //bit's per pixel (color depth) + depth /= 8; //we want the number of bytes per pixel - unsigned char data [row_padded]; //allocate space for one row (incl. padding) + filesystem_file_seek(file, *(uint32_t*)&info[10]); //seek to the place where img data begins - for(int i = 0; i < height; i++) //for each row - { - filesystem_file_read(file,data,row_padded); //read row into buffer - for(int j = 0; j < width*depth; j += depth) //for each pixel - { - unsigned char a,r,g,b; - if(depth==4) { //a,r,g,b 8bit each - a = data[j]; - r = data[j+1]; - g = data[j+2]; - b = data[j+3]; - } else if (depth==3) { // b,g,r, 8bit each - a = 255; - r = data[j+2]; - g = data[j+1]; - b = data[j]; - } + uint32_t row_padded = (width * depth + 3) & (~3); //row size must be aligned to 4 bytes - if(a!=0) { - //bmp's are stored "bottom-up", so we start drawing at the bottom - tft_draw_pixel(x+j/depth,y+height-1-i,RGB(r,g,b)); - } - } - } + unsigned char data [row_padded]; //allocate space for one row (incl. padding) - filesystem_file_close(file); + for (int i = 0; i < height; i++) { //for each row + filesystem_file_read(file, data, row_padded); //read row into buffer - return true; + for (int j = 0; j < width * depth; j += depth) { //for each pixel + unsigned char a, r, g, b; + + if (depth == 4) { //a,r,g,b 8bit each + a = data[j]; + r = data[j + 1]; + g = data[j + 2]; + b = data[j + 3]; + } else if (depth == 3) { // b,g,r, 8bit each + a = 255; + r = data[j + 2]; + g = data[j + 1]; + b = data[j]; + } + + if (a != 0) { + //bmp's are stored "bottom-up", so we start drawing at the bottom + tft_draw_pixel(x + j / depth, y + height - 1 - i, RGB(r, g, b)); + } + } + } + + filesystem_file_close(file); + + return true; } diff --git a/common/tft/tft.h b/common/tft/tft.h index 40157d2..51a05ba 100644 --- a/common/tft/tft.h +++ b/common/tft/tft.h @@ -1,3 +1,28 @@ +/************************************************************************************************************************************** +* Project: discoverpixy +* Website: https://github.com/t-moe/discoverpixy +* Authors: Aaron Schmocker, Timo Lang +* Institution: BFH Bern University of Applied Sciences +* File: common/tft/tft.h +* +* Version History: +* Date Autor Email SHA Changes +* 2015-04-03 timolang@gmail.com 51089aa Refactored Project Structure for use with emulator +* 2015-04-03 timolang@gmail.com 1f2af9f Added more tft functions to common and emulator. Fixed eventloop. +* 2015-04-03 timolang@gmail.com 1aa9194 Fixed Drawing of rects in Emulator. Got frames from pixy to emulator. Slooooow. +* 2015-04-27 aaron@duckpond.ch aed90ef Drawcircle added (emulator) +* 2015-04-27 timolang@gmail.com e249fb2 Added font support +* 2015-04-30 timolang@gmail.com 76ea9d8 Added num up down support. +* 2015-05-04 aaron@duckpond.ch c224d40 Changed display init +* 2015-05-10 timolang@gmail.com 21edc56 Added doxyfile (doxygen) for the common folder. Started with doxygen comments for app and tft module. +* 2015-05-11 timolang@gmail.com a175a2f Added doxygen docu for touch module +* 2015-05-11 timolang@gmail.com 08d9fe0 More work on doxygen module structure +* 2015-05-12 timolang@gmail.com 1402598 Added doxygen stuff for button module and some minor changes to touch, screen_main and tft module. +* 2015-05-15 timolang@gmail.com 9a16865 Added doxgen comments to filesyste, checkbox, numupdown and screen module. And some minor changes to the other modules. +* 2015-05-15 timolang@gmail.com b08a897 Added tft method to draw a bmp from filesystem. Added another font to emulator. +* +**************************************************************************************************************************************/ + #ifndef TFT_H #define TFT_H @@ -69,7 +94,7 @@ void tft_draw_line(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t * @param y The y-Coordinate of the pixel * @param color The 16-bit color to draw the pixel with */ -void tft_draw_pixel(uint16_t x,uint16_t y,uint16_t color); +void tft_draw_pixel(uint16_t x, uint16_t y, uint16_t color); /** * Draws the outline of a rectangle onto the display. @@ -80,7 +105,7 @@ void tft_draw_pixel(uint16_t x,uint16_t y,uint16_t color); * @param y2 The y-Coordinate of the end-point * @param color The 16-bit color to draw the pixel with */ -void tft_draw_rectangle(uint16_t x1,uint16_t y1,uint16_t x2,uint16_t y2, uint16_t color); +void tft_draw_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color); /** * Draws a filled rectangle onto the display. The start,end points are inclusive @@ -90,7 +115,7 @@ void tft_draw_rectangle(uint16_t x1,uint16_t y1,uint16_t x2,uint16_t y2, uint16_ * @param y2 The y-Coordinate of the end-point * @param color The 16-bit color to draw the pixel with */ -void tft_fill_rectangle(uint16_t x1,uint16_t y1,uint16_t x2,uint16_t y2, uint16_t color); +void tft_fill_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color); /** * Draws a bitmap onto the display without scaling/cropping. diff --git a/common/touch/screen_calibrate.c b/common/touch/screen_calibrate.c index c19a7bd..e38cabd 100644 --- a/common/touch/screen_calibrate.c +++ b/common/touch/screen_calibrate.c @@ -1,3 +1,17 @@ +/************************************************************************************************************************************** +* Project: discoverpixy +* Website: https://github.com/t-moe/discoverpixy +* Authors: Aaron Schmocker, Timo Lang +* Institution: BFH Bern University of Applied Sciences +* File: common/touch/screen_calibrate.c +* +* Version History: +* Date Autor Email SHA Changes +* 2015-06-01 timolang@gmail.com 06227da Added calibrate screen (WIP). fixed bug in emulator drawing. +* 2015-06-01 timolang@gmail.com eb573bc Finalized calibration. Fixed a bug in screen module. +* +**************************************************************************************************************************************/ + #include "screen_calibrate.h" #include "tft.h" #include "touch.h" @@ -6,90 +20,102 @@ extern volatile bool calibration; //from touch.c -static void enter(void* screen) { - tft_clear(BLACK); +static void enter(void* screen) +{ + tft_clear(BLACK); } -static void leave(void* screen) { +static void leave(void* screen) +{ } -static void update(void* screen) { - int x1,y1,x2,y2,dx,dy; +static void update(void* screen) +{ + int x1, y1, x2, y2, dx, dy; - tft_print_line(50,50,WHITE,BLACK,1,"Calibration:"); - tft_print_line(50,120,WHITE,BLACK,0,"Hit the markers exactly!"); - //-----------------First Point-------------------- - tft_draw_line(CCENTER,CBEGIN,CCENTER,CEND,WHITE); //Draw Cross - tft_draw_line(CBEGIN,CCENTER,CEND,CCENTER,WHITE); //Draw Cross - calibration=1; //TouchX + TouchY Values will not be converted to Pixels - while(calibration); //Wait on PenUp - POINT_STRUCT p1 = touch_get_last_point(); - x1=p1.x; - y1=p1.y; - tft_fill_rectangle(CBEGIN,CBEGIN,CEND,CEND,BLACK); //Clear Cross + tft_print_line(50, 50, WHITE, BLACK, 1, "Calibration:"); + tft_print_line(50, 120, WHITE, BLACK, 0, "Hit the markers exactly!"); + //-----------------First Point-------------------- + tft_draw_line(CCENTER, CBEGIN, CCENTER, CEND, WHITE); //Draw Cross + tft_draw_line(CBEGIN, CCENTER, CEND, CCENTER, WHITE); //Draw Cross + calibration = 1; //TouchX + TouchY Values will not be converted to Pixels - //-----------------Second Point------------------- - tft_draw_line(DWIDTH-CCENTER,DHEIGHT-CBEGIN,DWIDTH-CCENTER,DHEIGHT-CEND,WHITE); - tft_draw_line(DWIDTH-CBEGIN,DHEIGHT-CCENTER,DWIDTH-CEND,DHEIGHT-CCENTER,WHITE); - calibration=1; - while(calibration); - POINT_STRUCT p2 = touch_get_last_point(); - x2=p2.x; - y2=p2.y; - tft_fill_rectangle(DWIDTH-CBEGIN,DHEIGHT-CBEGIN,DWIDTH-CEND,DHEIGHT-CEND,BLACK); + while (calibration); //Wait on PenUp - //-----------------Third Point-------------------- - tft_draw_line(CCENTER,DHEIGHT-CBEGIN,CCENTER,DHEIGHT-CEND,WHITE); - tft_draw_line(CBEGIN,DHEIGHT-CCENTER,CEND,DHEIGHT-CCENTER,WHITE); - calibration=1; - while(calibration); - POINT_STRUCT p3 = touch_get_last_point(); - x1+=p3.x; //Add(!) values. We'll build the average later - y2+=p3.y; - tft_fill_rectangle(CBEGIN,DHEIGHT-CBEGIN,CEND,DHEIGHT-CEND,BLACK); + POINT_STRUCT p1 = touch_get_last_point(); + x1 = p1.x; + y1 = p1.y; + tft_fill_rectangle(CBEGIN, CBEGIN, CEND, CEND, BLACK); //Clear Cross - //------------------4. Point--------------------- - tft_draw_line(DWIDTH-CCENTER,CBEGIN,DWIDTH-CCENTER,CEND,WHITE); - tft_draw_line(DWIDTH-CBEGIN,CCENTER,DWIDTH-CEND,CCENTER,WHITE); - calibration=1; - while(calibration); - POINT_STRUCT p4 = touch_get_last_point(); - x2+=p4.x; - y1+=p4.y; - tft_fill_rectangle(DWIDTH-CBEGIN,CBEGIN,DWIDTH-CEND,CEND,BLACK); - //-------------------Calculation--------------------- - x1++; //Add 1 and divide by 2 later = +0.5 (for correct rounding) - y1++; - x2++; - y2++; - x1>>=1; //Divide by 2 - y1>>=1; - x2>>=1; - y2>>=1; - dx = (x2-x1); //Build the Difference - dy = (y2-y1); + //-----------------Second Point------------------- + tft_draw_line(DWIDTH - CCENTER, DHEIGHT - CBEGIN, DWIDTH - CCENTER, DHEIGHT - CEND, WHITE); + tft_draw_line(DWIDTH - CBEGIN, DHEIGHT - CCENTER, DWIDTH - CEND, DHEIGHT - CCENTER, WHITE); + calibration = 1; - touch_set_calibration_values(x1,dx,y1,dy); - tft_print_line(50,120,WHITE,BLACK,0,"Calibration Done. Press anywhere"); + while (calibration); - calibration=1; - while(calibration); - gui_screen_back(); + POINT_STRUCT p2 = touch_get_last_point(); + x2 = p2.x; + y2 = p2.y; + tft_fill_rectangle(DWIDTH - CBEGIN, DHEIGHT - CBEGIN, DWIDTH - CEND, DHEIGHT - CEND, BLACK); + + //-----------------Third Point-------------------- + tft_draw_line(CCENTER, DHEIGHT - CBEGIN, CCENTER, DHEIGHT - CEND, WHITE); + tft_draw_line(CBEGIN, DHEIGHT - CCENTER, CEND, DHEIGHT - CCENTER, WHITE); + calibration = 1; + + while (calibration); + + POINT_STRUCT p3 = touch_get_last_point(); + x1 += p3.x; //Add(!) values. We'll build the average later + y2 += p3.y; + tft_fill_rectangle(CBEGIN, DHEIGHT - CBEGIN, CEND, DHEIGHT - CEND, BLACK); + + //------------------4. Point--------------------- + tft_draw_line(DWIDTH - CCENTER, CBEGIN, DWIDTH - CCENTER, CEND, WHITE); + tft_draw_line(DWIDTH - CBEGIN, CCENTER, DWIDTH - CEND, CCENTER, WHITE); + calibration = 1; + + while (calibration); + + POINT_STRUCT p4 = touch_get_last_point(); + x2 += p4.x; + y1 += p4.y; + tft_fill_rectangle(DWIDTH - CBEGIN, CBEGIN, DWIDTH - CEND, CEND, BLACK); + //-------------------Calculation--------------------- + x1++; //Add 1 and divide by 2 later = +0.5 (for correct rounding) + y1++; + x2++; + y2++; + x1 >>= 1; //Divide by 2 + y1 >>= 1; + x2 >>= 1; + y2 >>= 1; + dx = (x2 - x1); //Build the Difference + dy = (y2 - y1); + + touch_set_calibration_values(x1, dx, y1, dy); + tft_print_line(50, 120, WHITE, BLACK, 0, "Calibration Done. Press anywhere"); + + calibration = 1; + + while (calibration); + + gui_screen_back(); } static SCREEN_STRUCT screen = { - enter, - leave, - update + enter, + leave, + update }; -SCREEN_STRUCT* get_screen_calibrate() { - return &screen; +SCREEN_STRUCT* get_screen_calibrate() +{ + return &screen; } - - diff --git a/common/touch/screen_calibrate.h b/common/touch/screen_calibrate.h index 107ce06..f1cbf7f 100644 --- a/common/touch/screen_calibrate.h +++ b/common/touch/screen_calibrate.h @@ -1,3 +1,17 @@ +/************************************************************************************************************************************** +* Project: discoverpixy +* Website: https://github.com/t-moe/discoverpixy +* Authors: Aaron Schmocker, Timo Lang +* Institution: BFH Bern University of Applied Sciences +* File: common/touch/screen_calibrate.h +* +* Version History: +* Date Autor Email SHA Changes +* 2015-06-01 timolang@gmail.com 06227da Added calibrate screen (WIP). fixed bug in emulator drawing. +* 2015-06-01 timolang@gmail.com eb573bc Finalized calibration. Fixed a bug in screen module. +* +**************************************************************************************************************************************/ + #include "screen.h" /** diff --git a/common/touch/touch.c b/common/touch/touch.c index fbd9d5f..0b74b57 100644 --- a/common/touch/touch.c +++ b/common/touch/touch.c @@ -1,3 +1,21 @@ +/************************************************************************************************************************************** +* Project: discoverpixy +* Website: https://github.com/t-moe/discoverpixy +* Authors: Aaron Schmocker, Timo Lang +* Institution: BFH Bern University of Applied Sciences +* File: common/touch/touch.c +* +* Version History: +* Date Autor Email SHA Changes +* 2015-04-27 timolang@gmail.com 259d446 Added touch support to emulator. Implemented basic touch function. +* 2015-05-02 timolang@gmail.com 3281616 Added some more touch functions. Improved pixy test. Drag the Image around! +* 2015-05-17 timolang@gmail.com 2d46336 Improved comments in implementation of button, checkbox, numupdown, tft, touch and screen modules/submodules. +* 2015-06-01 timolang@gmail.com 06227da Added calibrate screen (WIP). fixed bug in emulator drawing. +* 2015-06-01 timolang@gmail.com eb573bc Finalized calibration. Fixed a bug in screen module. +* 2015-06-06 timolang@gmail.com c06661d Fixed some outdated comments in source code. Documented Gui Module in docu. +* +**************************************************************************************************************************************/ + #include "touch.h" #include "ll_touch.h" #include "screen_calibrate.h" @@ -18,184 +36,179 @@ TOUCH_AREA_STRUCT* areas[NUM_AREAS] = {NULL}; //list with pointers to all managed touch area's volatile POINT_STRUCT pos; //the last touch point -volatile TOUCH_STATE oldState=TOUCH_UP; //the last touch state +volatile TOUCH_STATE oldState = TOUCH_UP; //the last touch state volatile bool calibration = false; //whether or not we're currently calibrating -bool use_calibration=false; //Whether or not the current platform needs calibration and recalc of the values +bool use_calibration = false; //Whether or not the current platform needs calibration and recalc of the values //Calibration parameters (dummy values). -int cal_xs=10; -int cal_dx=100; -int cal_ys=10; -int cal_dy=100; +int cal_xs = 10; +int cal_dx = 100; +int cal_ys = 10; +int cal_dy = 100; -void touch_set_calibration_values(int xs, int dx, int ys, int dy) { - cal_xs = xs; - cal_ys = ys; - cal_dx = dx; - cal_dy = dy; +void touch_set_calibration_values(int xs, int dx, int ys, int dy) +{ + cal_xs = xs; + cal_ys = ys; + cal_dx = dx; + cal_dy = dy; } -bool touch_init() { - return ll_touch_init(); +bool touch_init() +{ + return ll_touch_init(); } -void touch_set_value_convert_mode(bool uc) { - use_calibration=uc; +void touch_set_value_convert_mode(bool uc) +{ + use_calibration = uc; } -bool touch_add_raw_event(uint16_t touchX, uint16_t touchY, TOUCH_STATE state) { - //Update current and old position/state - bool penDown = (state==TOUCH_DOWN); - bool oldPenDown = (oldState==TOUCH_DOWN); - oldState=state; +bool touch_add_raw_event(uint16_t touchX, uint16_t touchY, TOUCH_STATE state) +{ + //Update current and old position/state + bool penDown = (state == TOUCH_DOWN); + bool oldPenDown = (oldState == TOUCH_DOWN); + oldState = state; - if(calibration) //If in Calibration mode - { - if(penDown) - { - pos.x=touchX; - pos.y=touchY; - } - else - { - if(oldPenDown) //Run only if we got at least one pen down - calibration=0; //Calibration finish (Touch X and Y are the values from the last measure, where the pen was down) - } - return true; - } + if (calibration) { //If in Calibration mode + if (penDown) { + pos.x = touchX; + pos.y = touchY; + } else { + if (oldPenDown) { //Run only if we got at least one pen down + calibration = 0; //Calibration finish (Touch X and Y are the values from the last measure, where the pen was down) + } + } - //If we reach this point we're not in calibration mode and we need to process the event and call the registred handlers.. + return true; + } - if(use_calibration) { //the underlying touch hardware uses calibration - //Calculate the real touch position out of the passed ones, and the calibration values - pos.x=touchX=(((long)(DWIDTH-2*CCENTER)*2*(long)((long)touchX-cal_xs)/cal_dx+1)>>1)+CCENTER; - pos.y=touchY=(((long)(DHEIGHT-2*CCENTER)*2*(long)((long)touchY-cal_ys)/cal_dy+1)>>1)+CCENTER; - } else { //no conversion needed for the underlying hardware - pos.x=touchX; - pos.y=touchY; - } + //If we reach this point we're not in calibration mode and we need to process the event and call the registred handlers.. - if(penDown) //pen is down now - { - //tft_draw_pixel(touchX,touchY,WHITE); - if(!oldPenDown) //pen wasn't down before (positive edge) => First Touch - { - for(int z=0; z < NUM_AREAS; z++) // For every touch area - { - //Check if pos is inside area - if(areas[z]!=NULL && touchX >= areas[z]->x1 && touchX <= areas[z]->x2 && touchY >= areas[z]->y1 && touchY <= areas[z]->y2 ) - { - areas[z]->flags=1; //Save PenInside=1 - if(areas[z]->hookedActions & PEN_DOWN) //The user wants to receive pen down events - areas[z]->callback(areas[z],PEN_DOWN); //Send event to user callback - } - } - } - else //Pen was down before => Second, Third event in row - { - for(int z=0; z < NUM_AREAS; z++) // For every touch area - { - if(areas[z]!=NULL ) - { - //Check if pos is inside area - if(touchX >= areas[z]->x1 && touchX <= areas[z]->x2 && touchY >= areas[z]->y1 && touchY <= areas[z]->y2) - { - if(areas[z]->flags==0) //Pen was not inside before (PenInside==0) - { - areas[z]->flags=1; //Pen is inside now (PenInside=1) - if(areas[z]->hookedActions & PEN_ENTER) //The user wants to receive pen enter events - areas[z]->callback(areas[z],PEN_ENTER); - } - } - else if(areas[z]->flags) //Pos not inside area, but it was before (PenInside==1) - { - areas[z]->flags=0; //Pen is no longer inside (PenInside=0) - if(areas[z]->hookedActions & PEN_LEAVE) //The user wants to receive pen leave events - areas[z]->callback(areas[z],PEN_LEAVE); - } - } - } - } - for(int z=0; z < NUM_AREAS; z++) // For every touch area - { - if(areas[z]!=NULL && (areas[z]->hookedActions&PEN_MOVE)) //User want's to receive pen move events - { - //Check if pos is inside area - if(touchX >= areas[z]->x1 && touchX <= areas[z]->x2 && touchY >= areas[z]->y1 && touchY <= areas[z]->y2) - { - areas[z]->callback(areas[z],PEN_MOVE); - } - } - } - } - else //pen is not down now - { - if(oldPenDown) //but it was down before (negative edge) - { - for(int z=0; z < NUM_AREAS; z++) // For every touch area - { - //Check if pos is inside area - if(areas[z]!=NULL && touchX >= areas[z]->x1 && touchX <= areas[z]->x2 && touchY >= areas[z]->y1 && touchY <= areas[z]->y2 ) - { - areas[z]->flags=0; //The pen is no longer inside (PenInside = 0); - if(areas[z]->hookedActions & PEN_UP) //user want's to receive pen up events - areas[z]->callback(areas[z],PEN_UP); - } - } - } - } - return true; + if (use_calibration) { //the underlying touch hardware uses calibration + //Calculate the real touch position out of the passed ones, and the calibration values + pos.x = touchX = (((long)(DWIDTH - 2 * CCENTER) * 2 * (long)((long)touchX - cal_xs) / cal_dx + 1) >> 1) + CCENTER; + pos.y = touchY = (((long)(DHEIGHT - 2 * CCENTER) * 2 * (long)((long)touchY - cal_ys) / cal_dy + 1) >> 1) + CCENTER; + } else { //no conversion needed for the underlying hardware + pos.x = touchX; + pos.y = touchY; + } + + if (penDown) { //pen is down now + //tft_draw_pixel(touchX,touchY,WHITE); + if (!oldPenDown) { //pen wasn't down before (positive edge) => First Touch + for (int z = 0; z < NUM_AREAS; z++) { // For every touch area + //Check if pos is inside area + if (areas[z] != NULL && touchX >= areas[z]->x1 && touchX <= areas[z]->x2 && touchY >= areas[z]->y1 && touchY <= areas[z]->y2) { + areas[z]->flags = 1; //Save PenInside=1 + + if (areas[z]->hookedActions & PEN_DOWN) { //The user wants to receive pen down events + areas[z]->callback(areas[z], PEN_DOWN); //Send event to user callback + } + } + } + } else { //Pen was down before => Second, Third event in row + for (int z = 0; z < NUM_AREAS; z++) { // For every touch area + if (areas[z] != NULL) { + //Check if pos is inside area + if (touchX >= areas[z]->x1 && touchX <= areas[z]->x2 && touchY >= areas[z]->y1 && touchY <= areas[z]->y2) { + if (areas[z]->flags == 0) { //Pen was not inside before (PenInside==0) + areas[z]->flags = 1; //Pen is inside now (PenInside=1) + + if (areas[z]->hookedActions & PEN_ENTER) { //The user wants to receive pen enter events + areas[z]->callback(areas[z], PEN_ENTER); + } + } + } else if (areas[z]->flags) { //Pos not inside area, but it was before (PenInside==1) + areas[z]->flags = 0; //Pen is no longer inside (PenInside=0) + + if (areas[z]->hookedActions & PEN_LEAVE) { //The user wants to receive pen leave events + areas[z]->callback(areas[z], PEN_LEAVE); + } + } + } + } + } + + for (int z = 0; z < NUM_AREAS; z++) { // For every touch area + if (areas[z] != NULL && (areas[z]->hookedActions & PEN_MOVE)) { //User want's to receive pen move events + //Check if pos is inside area + if (touchX >= areas[z]->x1 && touchX <= areas[z]->x2 && touchY >= areas[z]->y1 && touchY <= areas[z]->y2) { + areas[z]->callback(areas[z], PEN_MOVE); + } + } + } + } else { //pen is not down now + if (oldPenDown) { //but it was down before (negative edge) + for (int z = 0; z < NUM_AREAS; z++) { // For every touch area + //Check if pos is inside area + if (areas[z] != NULL && touchX >= areas[z]->x1 && touchX <= areas[z]->x2 && touchY >= areas[z]->y1 && touchY <= areas[z]->y2) { + areas[z]->flags = 0; //The pen is no longer inside (PenInside = 0); + + if (areas[z]->hookedActions & PEN_UP) { //user want's to receive pen up events + areas[z]->callback(areas[z], PEN_UP); + } + } + } + } + } + + return true; } bool touch_have_empty(unsigned char num) { - //go through pointer array and check for free spaces - for(unsigned char i=0; iflags=0; //we start with empty flags (PenInside=0) - areas[i]=area; //save pointer into list - return true; - } - } - return false; //no free space found + //go through pointer array and check for free space + for (unsigned char i = 0; i < NUM_AREAS; i++) { + if (areas[i] == NULL) { //free space found + area->flags = 0; //we start with empty flags (PenInside=0) + areas[i] = area; //save pointer into list + return true; + } + } + + return false; //no free space found } void touch_unregister_area(TOUCH_AREA_STRUCT* area) { - if(area==NULL) return; + if (area == NULL) { + return; + } - //go through pointer array and find the area to remove - for(unsigned char i=0; i -// SmallFont.c +// SmallFont.c // Font Size : 8x12 // Memory usage : 1216 bytes // # characters : 101 -const char small_font[1216] = { -0x08,0x0C,0x20,0x65, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // -0x00,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00,0x00, // ! -0x00,0x28,0x50,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // " -0x00,0x00,0x28,0x28,0xFC,0x28,0x50,0xFC,0x50,0x50,0x00,0x00, // # -0x00,0x20,0x78,0xA8,0xA0,0x60,0x30,0x28,0xA8,0xF0,0x20,0x00, // $ -0x00,0x00,0x48,0xA8,0xB0,0x50,0x28,0x34,0x54,0x48,0x00,0x00, // % -0x00,0x00,0x20,0x50,0x50,0x78,0xA8,0xA8,0x90,0x6C,0x00,0x00, // & -0x00,0x40,0x40,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ' -0x00,0x04,0x08,0x10,0x10,0x10,0x10,0x10,0x10,0x08,0x04,0x00, // ( -0x00,0x40,0x20,0x10,0x10,0x10,0x10,0x10,0x10,0x20,0x40,0x00, // ) -0x00,0x00,0x00,0x20,0xA8,0x70,0x70,0xA8,0x20,0x00,0x00,0x00, // * -0x00,0x00,0x20,0x20,0x20,0xF8,0x20,0x20,0x20,0x00,0x00,0x00, // + -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x40,0x80, // , -0x00,0x00,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00,0x00,0x00, // - -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00, // . -0x00,0x08,0x10,0x10,0x10,0x20,0x20,0x40,0x40,0x40,0x80,0x00, // / -0x00,0x00,0x70,0x88,0x88,0x88,0x88,0x88,0x88,0x70,0x00,0x00, // 0 -0x00,0x00,0x20,0x60,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00, // 1 -0x00,0x00,0x70,0x88,0x88,0x10,0x20,0x40,0x80,0xF8,0x00,0x00, // 2 -0x00,0x00,0x70,0x88,0x08,0x30,0x08,0x08,0x88,0x70,0x00,0x00, // 3 -0x00,0x00,0x10,0x30,0x50,0x50,0x90,0x78,0x10,0x18,0x00,0x00, // 4 -0x00,0x00,0xF8,0x80,0x80,0xF0,0x08,0x08,0x88,0x70,0x00,0x00, // 5 -0x00,0x00,0x70,0x90,0x80,0xF0,0x88,0x88,0x88,0x70,0x00,0x00, // 6 -0x00,0x00,0xF8,0x90,0x10,0x20,0x20,0x20,0x20,0x20,0x00,0x00, // 7 -0x00,0x00,0x70,0x88,0x88,0x70,0x88,0x88,0x88,0x70,0x00,0x00, // 8 -0x00,0x00,0x70,0x88,0x88,0x88,0x78,0x08,0x48,0x70,0x00,0x00, // 9 -0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x20,0x00,0x00, // : -0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x20,0x00, // ; -0x00,0x04,0x08,0x10,0x20,0x40,0x20,0x10,0x08,0x04,0x00,0x00, // < -0x00,0x00,0x00,0x00,0xF8,0x00,0x00,0xF8,0x00,0x00,0x00,0x00, // = -0x00,0x40,0x20,0x10,0x08,0x04,0x08,0x10,0x20,0x40,0x00,0x00, // > -0x00,0x00,0x70,0x88,0x88,0x10,0x20,0x20,0x00,0x20,0x00,0x00, // ? -0x00,0x00,0x70,0x88,0x98,0xA8,0xA8,0xB8,0x80,0x78,0x00,0x00, // @ -0x00,0x00,0x20,0x20,0x30,0x50,0x50,0x78,0x48,0xCC,0x00,0x00, // A -0x00,0x00,0xF0,0x48,0x48,0x70,0x48,0x48,0x48,0xF0,0x00,0x00, // B -0x00,0x00,0x78,0x88,0x80,0x80,0x80,0x80,0x88,0x70,0x00,0x00, // C -0x00,0x00,0xF0,0x48,0x48,0x48,0x48,0x48,0x48,0xF0,0x00,0x00, // D -0x00,0x00,0xF8,0x48,0x50,0x70,0x50,0x40,0x48,0xF8,0x00,0x00, // E -0x00,0x00,0xF8,0x48,0x50,0x70,0x50,0x40,0x40,0xE0,0x00,0x00, // F -0x00,0x00,0x38,0x48,0x80,0x80,0x9C,0x88,0x48,0x30,0x00,0x00, // G -0x00,0x00,0xCC,0x48,0x48,0x78,0x48,0x48,0x48,0xCC,0x00,0x00, // H -0x00,0x00,0xF8,0x20,0x20,0x20,0x20,0x20,0x20,0xF8,0x00,0x00, // I -0x00,0x00,0x7C,0x10,0x10,0x10,0x10,0x10,0x10,0x90,0xE0,0x00, // J -0x00,0x00,0xEC,0x48,0x50,0x60,0x50,0x50,0x48,0xEC,0x00,0x00, // K -0x00,0x00,0xE0,0x40,0x40,0x40,0x40,0x40,0x44,0xFC,0x00,0x00, // L -0x00,0x00,0xD8,0xD8,0xD8,0xD8,0xA8,0xA8,0xA8,0xA8,0x00,0x00, // M -0x00,0x00,0xDC,0x48,0x68,0x68,0x58,0x58,0x48,0xE8,0x00,0x00, // N -0x00,0x00,0x70,0x88,0x88,0x88,0x88,0x88,0x88,0x70,0x00,0x00, // O -0x00,0x00,0xF0,0x48,0x48,0x70,0x40,0x40,0x40,0xE0,0x00,0x00, // P -0x00,0x00,0x70,0x88,0x88,0x88,0x88,0xE8,0x98,0x70,0x18,0x00, // Q -0x00,0x00,0xF0,0x48,0x48,0x70,0x50,0x48,0x48,0xEC,0x00,0x00, // R -0x00,0x00,0x78,0x88,0x80,0x60,0x10,0x08,0x88,0xF0,0x00,0x00, // S -0x00,0x00,0xF8,0xA8,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00, // T -0x00,0x00,0xCC,0x48,0x48,0x48,0x48,0x48,0x48,0x30,0x00,0x00, // U -0x00,0x00,0xCC,0x48,0x48,0x50,0x50,0x30,0x20,0x20,0x00,0x00, // V -0x00,0x00,0xA8,0xA8,0xA8,0x70,0x50,0x50,0x50,0x50,0x00,0x00, // W -0x00,0x00,0xD8,0x50,0x50,0x20,0x20,0x50,0x50,0xD8,0x00,0x00, // X -0x00,0x00,0xD8,0x50,0x50,0x20,0x20,0x20,0x20,0x70,0x00,0x00, // Y -0x00,0x00,0xF8,0x90,0x10,0x20,0x20,0x40,0x48,0xF8,0x00,0x00, // Z -0x00,0x38,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x38,0x00, // [ -0x00,0x40,0x40,0x40,0x20,0x20,0x10,0x10,0x10,0x08,0x00,0x00, // -0x00,0x70,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x70,0x00, // ] -0x00,0x20,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ^ -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC, // _ -0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ' -0x00,0x00,0x00,0x00,0x00,0x30,0x48,0x38,0x48,0x3C,0x00,0x00, // a -0x00,0x00,0xC0,0x40,0x40,0x70,0x48,0x48,0x48,0x70,0x00,0x00, // b -0x00,0x00,0x00,0x00,0x00,0x38,0x48,0x40,0x40,0x38,0x00,0x00, // c -0x00,0x00,0x18,0x08,0x08,0x38,0x48,0x48,0x48,0x3C,0x00,0x00, // d -0x00,0x00,0x00,0x00,0x00,0x30,0x48,0x78,0x40,0x38,0x00,0x00, // e -0x00,0x00,0x1C,0x20,0x20,0x78,0x20,0x20,0x20,0x78,0x00,0x00, // f -0x00,0x00,0x00,0x00,0x00,0x3C,0x48,0x30,0x40,0x78,0x44,0x38, // g -0x00,0x00,0xC0,0x40,0x40,0x70,0x48,0x48,0x48,0xEC,0x00,0x00, // h -0x00,0x00,0x20,0x00,0x00,0x60,0x20,0x20,0x20,0x70,0x00,0x00, // i -0x00,0x00,0x10,0x00,0x00,0x30,0x10,0x10,0x10,0x10,0x10,0xE0, // j -0x00,0x00,0xC0,0x40,0x40,0x5C,0x50,0x70,0x48,0xEC,0x00,0x00, // k -0x00,0x00,0xE0,0x20,0x20,0x20,0x20,0x20,0x20,0xF8,0x00,0x00, // l -0x00,0x00,0x00,0x00,0x00,0xF0,0xA8,0xA8,0xA8,0xA8,0x00,0x00, // m -0x00,0x00,0x00,0x00,0x00,0xF0,0x48,0x48,0x48,0xEC,0x00,0x00, // n -0x00,0x00,0x00,0x00,0x00,0x30,0x48,0x48,0x48,0x30,0x00,0x00, // o -0x00,0x00,0x00,0x00,0x00,0xF0,0x48,0x48,0x48,0x70,0x40,0xE0, // p -0x00,0x00,0x00,0x00,0x00,0x38,0x48,0x48,0x48,0x38,0x08,0x1C, // q -0x00,0x00,0x00,0x00,0x00,0xD8,0x60,0x40,0x40,0xE0,0x00,0x00, // r -0x00,0x00,0x00,0x00,0x00,0x78,0x40,0x30,0x08,0x78,0x00,0x00, // s -0x00,0x00,0x00,0x20,0x20,0x70,0x20,0x20,0x20,0x18,0x00,0x00, // t -0x00,0x00,0x00,0x00,0x00,0xD8,0x48,0x48,0x48,0x3C,0x00,0x00, // u -0x00,0x00,0x00,0x00,0x00,0xEC,0x48,0x50,0x30,0x20,0x00,0x00, // v -0x00,0x00,0x00,0x00,0x00,0xA8,0xA8,0x70,0x50,0x50,0x00,0x00, // w -0x00,0x00,0x00,0x00,0x00,0xD8,0x50,0x20,0x50,0xD8,0x00,0x00, // x -0x00,0x00,0x00,0x00,0x00,0xEC,0x48,0x50,0x30,0x20,0x20,0xC0, // y -0x00,0x00,0x00,0x00,0x00,0x78,0x10,0x20,0x20,0x78,0x00,0x00, // z -0x00,0x18,0x10,0x10,0x10,0x20,0x10,0x10,0x10,0x10,0x18,0x00, // { -0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10, // | -0x00,0x60,0x20,0x20,0x20,0x10,0x20,0x20,0x20,0x20,0x60,0x00, // } -0x40,0xA4,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ~ -0x50,0x00,0x20,0x20,0x30,0x50,0x50,0x78,0x48,0xCC,0x00,0x00, // Ä -0x50,0x00,0x70,0x88,0x88,0x88,0x88,0x88,0x88,0x70,0x00,0x00, // Ö -0x48,0x00,0xCC,0x48,0x48,0x48,0x48,0x48,0x48,0x30,0x00,0x00, // Ü -0x00,0x00,0x00,0x48,0x00,0x30,0x48,0x38,0x48,0x3C,0x00,0x00, // ä -0x00,0x00,0x00,0x48,0x00,0x30,0x48,0x48,0x48,0x30,0x00,0x00, // ö -0x00,0x00,0x00,0x48,0x00,0xD8,0x48,0x48,0x48,0x3C,0x00,0x00 // ü -}; +const char small_font[1216] = { + 0x08, 0x0C, 0x20, 0x65, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x20, 0x00, 0x00, // ! + 0x00, 0x28, 0x50, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // " + 0x00, 0x00, 0x28, 0x28, 0xFC, 0x28, 0x50, 0xFC, 0x50, 0x50, 0x00, 0x00, // # + 0x00, 0x20, 0x78, 0xA8, 0xA0, 0x60, 0x30, 0x28, 0xA8, 0xF0, 0x20, 0x00, // $ + 0x00, 0x00, 0x48, 0xA8, 0xB0, 0x50, 0x28, 0x34, 0x54, 0x48, 0x00, 0x00, // % + 0x00, 0x00, 0x20, 0x50, 0x50, 0x78, 0xA8, 0xA8, 0x90, 0x6C, 0x00, 0x00, // & + 0x00, 0x40, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ' + 0x00, 0x04, 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x08, 0x04, 0x00, // ( + 0x00, 0x40, 0x20, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x40, 0x00, // ) + 0x00, 0x00, 0x00, 0x20, 0xA8, 0x70, 0x70, 0xA8, 0x20, 0x00, 0x00, 0x00, // * + 0x00, 0x00, 0x20, 0x20, 0x20, 0xF8, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, // + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x80, // , + 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // - + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, // . + 0x00, 0x08, 0x10, 0x10, 0x10, 0x20, 0x20, 0x40, 0x40, 0x40, 0x80, 0x00, // / + 0x00, 0x00, 0x70, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00, 0x00, // 0 + 0x00, 0x00, 0x20, 0x60, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x00, 0x00, // 1 + 0x00, 0x00, 0x70, 0x88, 0x88, 0x10, 0x20, 0x40, 0x80, 0xF8, 0x00, 0x00, // 2 + 0x00, 0x00, 0x70, 0x88, 0x08, 0x30, 0x08, 0x08, 0x88, 0x70, 0x00, 0x00, // 3 + 0x00, 0x00, 0x10, 0x30, 0x50, 0x50, 0x90, 0x78, 0x10, 0x18, 0x00, 0x00, // 4 + 0x00, 0x00, 0xF8, 0x80, 0x80, 0xF0, 0x08, 0x08, 0x88, 0x70, 0x00, 0x00, // 5 + 0x00, 0x00, 0x70, 0x90, 0x80, 0xF0, 0x88, 0x88, 0x88, 0x70, 0x00, 0x00, // 6 + 0x00, 0x00, 0xF8, 0x90, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, // 7 + 0x00, 0x00, 0x70, 0x88, 0x88, 0x70, 0x88, 0x88, 0x88, 0x70, 0x00, 0x00, // 8 + 0x00, 0x00, 0x70, 0x88, 0x88, 0x88, 0x78, 0x08, 0x48, 0x70, 0x00, 0x00, // 9 + 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, // : + 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x20, 0x00, // ; + 0x00, 0x04, 0x08, 0x10, 0x20, 0x40, 0x20, 0x10, 0x08, 0x04, 0x00, 0x00, // < + 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, // = + 0x00, 0x40, 0x20, 0x10, 0x08, 0x04, 0x08, 0x10, 0x20, 0x40, 0x00, 0x00, // > + 0x00, 0x00, 0x70, 0x88, 0x88, 0x10, 0x20, 0x20, 0x00, 0x20, 0x00, 0x00, // ? + 0x00, 0x00, 0x70, 0x88, 0x98, 0xA8, 0xA8, 0xB8, 0x80, 0x78, 0x00, 0x00, // @ + 0x00, 0x00, 0x20, 0x20, 0x30, 0x50, 0x50, 0x78, 0x48, 0xCC, 0x00, 0x00, // A + 0x00, 0x00, 0xF0, 0x48, 0x48, 0x70, 0x48, 0x48, 0x48, 0xF0, 0x00, 0x00, // B + 0x00, 0x00, 0x78, 0x88, 0x80, 0x80, 0x80, 0x80, 0x88, 0x70, 0x00, 0x00, // C + 0x00, 0x00, 0xF0, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0xF0, 0x00, 0x00, // D + 0x00, 0x00, 0xF8, 0x48, 0x50, 0x70, 0x50, 0x40, 0x48, 0xF8, 0x00, 0x00, // E + 0x00, 0x00, 0xF8, 0x48, 0x50, 0x70, 0x50, 0x40, 0x40, 0xE0, 0x00, 0x00, // F + 0x00, 0x00, 0x38, 0x48, 0x80, 0x80, 0x9C, 0x88, 0x48, 0x30, 0x00, 0x00, // G + 0x00, 0x00, 0xCC, 0x48, 0x48, 0x78, 0x48, 0x48, 0x48, 0xCC, 0x00, 0x00, // H + 0x00, 0x00, 0xF8, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xF8, 0x00, 0x00, // I + 0x00, 0x00, 0x7C, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x90, 0xE0, 0x00, // J + 0x00, 0x00, 0xEC, 0x48, 0x50, 0x60, 0x50, 0x50, 0x48, 0xEC, 0x00, 0x00, // K + 0x00, 0x00, 0xE0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x44, 0xFC, 0x00, 0x00, // L + 0x00, 0x00, 0xD8, 0xD8, 0xD8, 0xD8, 0xA8, 0xA8, 0xA8, 0xA8, 0x00, 0x00, // M + 0x00, 0x00, 0xDC, 0x48, 0x68, 0x68, 0x58, 0x58, 0x48, 0xE8, 0x00, 0x00, // N + 0x00, 0x00, 0x70, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00, 0x00, // O + 0x00, 0x00, 0xF0, 0x48, 0x48, 0x70, 0x40, 0x40, 0x40, 0xE0, 0x00, 0x00, // P + 0x00, 0x00, 0x70, 0x88, 0x88, 0x88, 0x88, 0xE8, 0x98, 0x70, 0x18, 0x00, // Q + 0x00, 0x00, 0xF0, 0x48, 0x48, 0x70, 0x50, 0x48, 0x48, 0xEC, 0x00, 0x00, // R + 0x00, 0x00, 0x78, 0x88, 0x80, 0x60, 0x10, 0x08, 0x88, 0xF0, 0x00, 0x00, // S + 0x00, 0x00, 0xF8, 0xA8, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x00, 0x00, // T + 0x00, 0x00, 0xCC, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x30, 0x00, 0x00, // U + 0x00, 0x00, 0xCC, 0x48, 0x48, 0x50, 0x50, 0x30, 0x20, 0x20, 0x00, 0x00, // V + 0x00, 0x00, 0xA8, 0xA8, 0xA8, 0x70, 0x50, 0x50, 0x50, 0x50, 0x00, 0x00, // W + 0x00, 0x00, 0xD8, 0x50, 0x50, 0x20, 0x20, 0x50, 0x50, 0xD8, 0x00, 0x00, // X + 0x00, 0x00, 0xD8, 0x50, 0x50, 0x20, 0x20, 0x20, 0x20, 0x70, 0x00, 0x00, // Y + 0x00, 0x00, 0xF8, 0x90, 0x10, 0x20, 0x20, 0x40, 0x48, 0xF8, 0x00, 0x00, // Z + 0x00, 0x38, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x38, 0x00, // [ + 0x00, 0x40, 0x40, 0x40, 0x20, 0x20, 0x10, 0x10, 0x10, 0x08, 0x00, 0x00, // + 0x00, 0x70, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x70, 0x00, // ] + 0x00, 0x20, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ^ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, // _ + 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ' + 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x48, 0x38, 0x48, 0x3C, 0x00, 0x00, // a + 0x00, 0x00, 0xC0, 0x40, 0x40, 0x70, 0x48, 0x48, 0x48, 0x70, 0x00, 0x00, // b + 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x48, 0x40, 0x40, 0x38, 0x00, 0x00, // c + 0x00, 0x00, 0x18, 0x08, 0x08, 0x38, 0x48, 0x48, 0x48, 0x3C, 0x00, 0x00, // d + 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x48, 0x78, 0x40, 0x38, 0x00, 0x00, // e + 0x00, 0x00, 0x1C, 0x20, 0x20, 0x78, 0x20, 0x20, 0x20, 0x78, 0x00, 0x00, // f + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x48, 0x30, 0x40, 0x78, 0x44, 0x38, // g + 0x00, 0x00, 0xC0, 0x40, 0x40, 0x70, 0x48, 0x48, 0x48, 0xEC, 0x00, 0x00, // h + 0x00, 0x00, 0x20, 0x00, 0x00, 0x60, 0x20, 0x20, 0x20, 0x70, 0x00, 0x00, // i + 0x00, 0x00, 0x10, 0x00, 0x00, 0x30, 0x10, 0x10, 0x10, 0x10, 0x10, 0xE0, // j + 0x00, 0x00, 0xC0, 0x40, 0x40, 0x5C, 0x50, 0x70, 0x48, 0xEC, 0x00, 0x00, // k + 0x00, 0x00, 0xE0, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xF8, 0x00, 0x00, // l + 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xA8, 0xA8, 0xA8, 0xA8, 0x00, 0x00, // m + 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x48, 0x48, 0x48, 0xEC, 0x00, 0x00, // n + 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x48, 0x48, 0x48, 0x30, 0x00, 0x00, // o + 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x48, 0x48, 0x48, 0x70, 0x40, 0xE0, // p + 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x48, 0x48, 0x48, 0x38, 0x08, 0x1C, // q + 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x60, 0x40, 0x40, 0xE0, 0x00, 0x00, // r + 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x40, 0x30, 0x08, 0x78, 0x00, 0x00, // s + 0x00, 0x00, 0x00, 0x20, 0x20, 0x70, 0x20, 0x20, 0x20, 0x18, 0x00, 0x00, // t + 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x48, 0x48, 0x48, 0x3C, 0x00, 0x00, // u + 0x00, 0x00, 0x00, 0x00, 0x00, 0xEC, 0x48, 0x50, 0x30, 0x20, 0x00, 0x00, // v + 0x00, 0x00, 0x00, 0x00, 0x00, 0xA8, 0xA8, 0x70, 0x50, 0x50, 0x00, 0x00, // w + 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x50, 0x20, 0x50, 0xD8, 0x00, 0x00, // x + 0x00, 0x00, 0x00, 0x00, 0x00, 0xEC, 0x48, 0x50, 0x30, 0x20, 0x20, 0xC0, // y + 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x10, 0x20, 0x20, 0x78, 0x00, 0x00, // z + 0x00, 0x18, 0x10, 0x10, 0x10, 0x20, 0x10, 0x10, 0x10, 0x10, 0x18, 0x00, // { + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, // | + 0x00, 0x60, 0x20, 0x20, 0x20, 0x10, 0x20, 0x20, 0x20, 0x20, 0x60, 0x00, // } + 0x40, 0xA4, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ~ + 0x50, 0x00, 0x20, 0x20, 0x30, 0x50, 0x50, 0x78, 0x48, 0xCC, 0x00, 0x00, // Ä + 0x50, 0x00, 0x70, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00, 0x00, // Ö + 0x48, 0x00, 0xCC, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x30, 0x00, 0x00, // Ü + 0x00, 0x00, 0x00, 0x48, 0x00, 0x30, 0x48, 0x38, 0x48, 0x3C, 0x00, 0x00, // ä + 0x00, 0x00, 0x00, 0x48, 0x00, 0x30, 0x48, 0x48, 0x48, 0x30, 0x00, 0x00, // ö + 0x00, 0x00, 0x00, 0x48, 0x00, 0xD8, 0x48, 0x48, 0x48, 0x3C, 0x00, 0x00 // ü +}; // BigFont.c (C)2010 by Henning Karlsen // Font Size : 16x16 // Memory usage : 3236 bytes // # characters : 101 -const char big_font[3236] = { -0x10,0x10,0x20,0x65, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // -0x00,0x00,0x00,0x00,0x07,0x00,0x0F,0x80,0x0F,0x80,0x0F,0x80,0x0F,0x80,0x0F,0x80,0x07,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x00,0x00, // ! -0x00,0x00,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x06,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // " -0x00,0x00,0x0C,0x30,0x0C,0x30,0x0C,0x30,0x7F,0xFE,0x7F,0xFE,0x0C,0x30,0x0C,0x30,0x0C,0x30,0x0C,0x30,0x7F,0xFE,0x7F,0xFE,0x0C,0x30,0x0C,0x30,0x0C,0x30,0x00,0x00, // # -0x00,0x00,0x02,0x40,0x02,0x40,0x0F,0xF8,0x1F,0xF8,0x1A,0x40,0x1A,0x40,0x1F,0xF0,0x0F,0xF8,0x02,0x58,0x02,0x58,0x1F,0xF8,0x1F,0xF0,0x02,0x40,0x02,0x40,0x00,0x00, // $ -0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x10,0x0E,0x30,0x0E,0x70,0x00,0xE0,0x01,0xC0,0x03,0x80,0x07,0x00,0x0E,0x70,0x0C,0x70,0x08,0x70,0x00,0x00,0x00,0x00,0x00,0x00, // % -0x00,0x00,0x00,0x00,0x0F,0x00,0x19,0x80,0x19,0x80,0x19,0x80,0x0F,0x00,0x0F,0x08,0x0F,0x98,0x19,0xF8,0x18,0xF0,0x18,0xE0,0x19,0xF0,0x0F,0x98,0x00,0x00,0x00,0x00, // & -0x00,0x00,0x00,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ' -0x00,0x00,0x00,0x00,0x00,0xF0,0x01,0xC0,0x03,0x80,0x07,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x07,0x00,0x03,0x80,0x01,0xC0,0x00,0xF0,0x00,0x00,0x00,0x00, // ( -0x00,0x00,0x00,0x00,0x0F,0x00,0x03,0x80,0x01,0xC0,0x00,0xE0,0x00,0x70,0x00,0x70,0x00,0x70,0x00,0x70,0x00,0xE0,0x01,0xC0,0x03,0x80,0x0F,0x00,0x00,0x00,0x00,0x00, // ) -0x00,0x00,0x00,0x00,0x01,0x80,0x11,0x88,0x09,0x90,0x07,0xE0,0x07,0xE0,0x3F,0xFC,0x3F,0xFC,0x07,0xE0,0x07,0xE0,0x09,0x90,0x11,0x88,0x01,0x80,0x00,0x00,0x00,0x00, // * -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x01,0x80,0x01,0x80,0x0F,0xF0,0x0F,0xF0,0x01,0x80,0x01,0x80,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // + -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x0E,0x00,0x00,0x00, // , -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0xF8,0x1F,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // - -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x00,0x00,0x00,0x00, // , -0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x06,0x00,0x0E,0x00,0x1C,0x00,0x38,0x00,0x70,0x00,0xE0,0x01,0xC0,0x03,0x80,0x07,0x00,0x0E,0x00,0x1C,0x00,0x00,0x00,0x00,0x00, // / +const char big_font[3236] = { + 0x10, 0x10, 0x20, 0x65, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x0F, 0x80, 0x0F, 0x80, 0x0F, 0x80, 0x0F, 0x80, 0x0F, 0x80, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, // ! + 0x00, 0x00, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x06, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // " + 0x00, 0x00, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x7F, 0xFE, 0x7F, 0xFE, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x7F, 0xFE, 0x7F, 0xFE, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x00, 0x00, // # + 0x00, 0x00, 0x02, 0x40, 0x02, 0x40, 0x0F, 0xF8, 0x1F, 0xF8, 0x1A, 0x40, 0x1A, 0x40, 0x1F, 0xF0, 0x0F, 0xF8, 0x02, 0x58, 0x02, 0x58, 0x1F, 0xF8, 0x1F, 0xF0, 0x02, 0x40, 0x02, 0x40, 0x00, 0x00, // $ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x10, 0x0E, 0x30, 0x0E, 0x70, 0x00, 0xE0, 0x01, 0xC0, 0x03, 0x80, 0x07, 0x00, 0x0E, 0x70, 0x0C, 0x70, 0x08, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // % + 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x19, 0x80, 0x19, 0x80, 0x19, 0x80, 0x0F, 0x00, 0x0F, 0x08, 0x0F, 0x98, 0x19, 0xF8, 0x18, 0xF0, 0x18, 0xE0, 0x19, 0xF0, 0x0F, 0x98, 0x00, 0x00, 0x00, 0x00, // & + 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ' + 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x01, 0xC0, 0x03, 0x80, 0x07, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x07, 0x00, 0x03, 0x80, 0x01, 0xC0, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, // ( + 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x03, 0x80, 0x01, 0xC0, 0x00, 0xE0, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0xE0, 0x01, 0xC0, 0x03, 0x80, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, // ) + 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x11, 0x88, 0x09, 0x90, 0x07, 0xE0, 0x07, 0xE0, 0x3F, 0xFC, 0x3F, 0xFC, 0x07, 0xE0, 0x07, 0xE0, 0x09, 0x90, 0x11, 0x88, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, // * + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x0F, 0xF0, 0x0F, 0xF0, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x0E, 0x00, 0x00, 0x00, // , + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xF8, 0x1F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // - + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, // , + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x06, 0x00, 0x0E, 0x00, 0x1C, 0x00, 0x38, 0x00, 0x70, 0x00, 0xE0, 0x01, 0xC0, 0x03, 0x80, 0x07, 0x00, 0x0E, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, // / -0x00,0x00,0x00,0x00,0x0F,0xF0,0x1C,0x38,0x1C,0x78,0x1C,0xF8,0x1C,0xF8,0x1D,0xB8,0x1D,0xB8,0x1F,0x38,0x1F,0x38,0x1E,0x38,0x1C,0x38,0x0F,0xF0,0x00,0x00,0x00,0x00, // 0 -0x00,0x00,0x00,0x00,0x01,0x80,0x01,0x80,0x03,0x80,0x1F,0x80,0x1F,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x1F,0xF0,0x00,0x00,0x00,0x00, // 1 -0x00,0x00,0x00,0x00,0x0F,0xE0,0x1C,0x70,0x1C,0x38,0x00,0x38,0x00,0x70,0x00,0xE0,0x01,0xC0,0x03,0x80,0x07,0x00,0x0E,0x38,0x1C,0x38,0x1F,0xF8,0x00,0x00,0x00,0x00, // 2 -0x00,0x00,0x00,0x00,0x0F,0xE0,0x1C,0x70,0x1C,0x38,0x00,0x38,0x00,0x70,0x03,0xC0,0x03,0xC0,0x00,0x70,0x00,0x38,0x1C,0x38,0x1C,0x70,0x0F,0xE0,0x00,0x00,0x00,0x00, // 3 -0x00,0x00,0x00,0x00,0x00,0xE0,0x01,0xE0,0x03,0xE0,0x06,0xE0,0x0C,0xE0,0x18,0xE0,0x1F,0xF8,0x1F,0xF8,0x00,0xE0,0x00,0xE0,0x00,0xE0,0x03,0xF8,0x00,0x00,0x00,0x00, // 4 -0x00,0x00,0x00,0x00,0x1F,0xF8,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x1F,0xE0,0x1F,0xF0,0x00,0x78,0x00,0x38,0x1C,0x38,0x1C,0x70,0x0F,0xE0,0x00,0x00,0x00,0x00, // 5 -0x00,0x00,0x00,0x00,0x03,0xE0,0x07,0x00,0x0E,0x00,0x1C,0x00,0x1C,0x00,0x1F,0xF0,0x1F,0xF8,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x0F,0xF0,0x00,0x00,0x00,0x00, // 6 -0x00,0x00,0x00,0x00,0x1F,0xFC,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x00,0x1C,0x00,0x38,0x00,0x70,0x00,0xE0,0x01,0xC0,0x03,0x80,0x03,0x80,0x03,0x80,0x00,0x00,0x00,0x00, // 7 -0x00,0x00,0x00,0x00,0x0F,0xF0,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1F,0x38,0x07,0xE0,0x07,0xE0,0x1C,0xF8,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x0F,0xF0,0x00,0x00,0x00,0x00, // 8 -0x00,0x00,0x00,0x00,0x0F,0xF0,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1F,0xF8,0x0F,0xF8,0x00,0x38,0x00,0x38,0x00,0x70,0x00,0xE0,0x07,0xC0,0x00,0x00,0x00,0x00, // 9 -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x80,0x03,0x80,0x03,0x80,0x00,0x00,0x00,0x00,0x03,0x80,0x03,0x80,0x03,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // : -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x80,0x03,0x80,0x03,0x80,0x00,0x00,0x00,0x00,0x03,0x80,0x03,0x80,0x03,0x80,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ; -0x00,0x00,0x00,0x70,0x00,0xE0,0x01,0xC0,0x03,0x80,0x07,0x00,0x0E,0x00,0x1C,0x00,0x1C,0x00,0x0E,0x00,0x07,0x00,0x03,0x80,0x01,0xC0,0x00,0xE0,0x00,0x70,0x00,0x00, // < -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xFC,0x3F,0xFC,0x00,0x00,0x00,0x00,0x3F,0xFC,0x3F,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // = -0x00,0x00,0x1C,0x00,0x0E,0x00,0x07,0x00,0x03,0x80,0x01,0xC0,0x00,0xE0,0x00,0x70,0x00,0x70,0x00,0xE0,0x01,0xC0,0x03,0x80,0x07,0x00,0x0E,0x00,0x1C,0x00,0x00,0x00, // > -0x00,0x00,0x03,0xC0,0x0F,0xF0,0x1E,0x78,0x18,0x38,0x00,0x38,0x00,0x70,0x00,0xE0,0x01,0xC0,0x01,0xC0,0x00,0x00,0x00,0x00,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x00,0x00, // ? + 0x00, 0x00, 0x00, 0x00, 0x0F, 0xF0, 0x1C, 0x38, 0x1C, 0x78, 0x1C, 0xF8, 0x1C, 0xF8, 0x1D, 0xB8, 0x1D, 0xB8, 0x1F, 0x38, 0x1F, 0x38, 0x1E, 0x38, 0x1C, 0x38, 0x0F, 0xF0, 0x00, 0x00, 0x00, 0x00, // 0 + 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x01, 0x80, 0x03, 0x80, 0x1F, 0x80, 0x1F, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x1F, 0xF0, 0x00, 0x00, 0x00, 0x00, // 1 + 0x00, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x1C, 0x70, 0x1C, 0x38, 0x00, 0x38, 0x00, 0x70, 0x00, 0xE0, 0x01, 0xC0, 0x03, 0x80, 0x07, 0x00, 0x0E, 0x38, 0x1C, 0x38, 0x1F, 0xF8, 0x00, 0x00, 0x00, 0x00, // 2 + 0x00, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x1C, 0x70, 0x1C, 0x38, 0x00, 0x38, 0x00, 0x70, 0x03, 0xC0, 0x03, 0xC0, 0x00, 0x70, 0x00, 0x38, 0x1C, 0x38, 0x1C, 0x70, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, // 3 + 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x01, 0xE0, 0x03, 0xE0, 0x06, 0xE0, 0x0C, 0xE0, 0x18, 0xE0, 0x1F, 0xF8, 0x1F, 0xF8, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x03, 0xF8, 0x00, 0x00, 0x00, 0x00, // 4 + 0x00, 0x00, 0x00, 0x00, 0x1F, 0xF8, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x1F, 0xE0, 0x1F, 0xF0, 0x00, 0x78, 0x00, 0x38, 0x1C, 0x38, 0x1C, 0x70, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, // 5 + 0x00, 0x00, 0x00, 0x00, 0x03, 0xE0, 0x07, 0x00, 0x0E, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x1F, 0xF0, 0x1F, 0xF8, 0x1C, 0x38, 0x1C, 0x38, 0x1C, 0x38, 0x1C, 0x38, 0x0F, 0xF0, 0x00, 0x00, 0x00, 0x00, // 6 + 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFC, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x00, 0x1C, 0x00, 0x38, 0x00, 0x70, 0x00, 0xE0, 0x01, 0xC0, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, // 7 + 0x00, 0x00, 0x00, 0x00, 0x0F, 0xF0, 0x1C, 0x38, 0x1C, 0x38, 0x1C, 0x38, 0x1F, 0x38, 0x07, 0xE0, 0x07, 0xE0, 0x1C, 0xF8, 0x1C, 0x38, 0x1C, 0x38, 0x1C, 0x38, 0x0F, 0xF0, 0x00, 0x00, 0x00, 0x00, // 8 + 0x00, 0x00, 0x00, 0x00, 0x0F, 0xF0, 0x1C, 0x38, 0x1C, 0x38, 0x1C, 0x38, 0x1C, 0x38, 0x1F, 0xF8, 0x0F, 0xF8, 0x00, 0x38, 0x00, 0x38, 0x00, 0x70, 0x00, 0xE0, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, // 9 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // : + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ; + 0x00, 0x00, 0x00, 0x70, 0x00, 0xE0, 0x01, 0xC0, 0x03, 0x80, 0x07, 0x00, 0x0E, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x0E, 0x00, 0x07, 0x00, 0x03, 0x80, 0x01, 0xC0, 0x00, 0xE0, 0x00, 0x70, 0x00, 0x00, // < + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFC, 0x3F, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFC, 0x3F, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // = + 0x00, 0x00, 0x1C, 0x00, 0x0E, 0x00, 0x07, 0x00, 0x03, 0x80, 0x01, 0xC0, 0x00, 0xE0, 0x00, 0x70, 0x00, 0x70, 0x00, 0xE0, 0x01, 0xC0, 0x03, 0x80, 0x07, 0x00, 0x0E, 0x00, 0x1C, 0x00, 0x00, 0x00, // > + 0x00, 0x00, 0x03, 0xC0, 0x0F, 0xF0, 0x1E, 0x78, 0x18, 0x38, 0x00, 0x38, 0x00, 0x70, 0x00, 0xE0, 0x01, 0xC0, 0x01, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x00, 0x00, // ? -0x00,0x00,0x0F,0xF8,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0xFC,0x1C,0xFC,0x1C,0xFC,0x1C,0xFC,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x1F,0xF0,0x07,0xF8,0x00,0x00, // @ -0x00,0x00,0x00,0x00,0x03,0xC0,0x07,0xE0,0x0E,0x70,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1F,0xF8,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x00,0x00,0x00,0x00, // A -0x00,0x00,0x00,0x00,0x1F,0xF0,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x0F,0xF0,0x0F,0xF0,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x1F,0xF0,0x00,0x00,0x00,0x00, // B -0x00,0x00,0x00,0x00,0x07,0xF0,0x0E,0x38,0x1C,0x38,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x1C,0x38,0x0E,0x38,0x07,0xF0,0x00,0x00,0x00,0x00, // C -0x00,0x00,0x00,0x00,0x1F,0xE0,0x0E,0x70,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x0E,0x70,0x1F,0xE0,0x00,0x00,0x00,0x00, // D -0x00,0x00,0x00,0x00,0x1F,0xF8,0x0E,0x18,0x0E,0x08,0x0E,0x00,0x0E,0x30,0x0F,0xF0,0x0F,0xF0,0x0E,0x30,0x0E,0x00,0x0E,0x08,0x0E,0x18,0x1F,0xF8,0x00,0x00,0x00,0x00, // E -0x00,0x00,0x00,0x00,0x1F,0xF8,0x0E,0x18,0x0E,0x08,0x0E,0x00,0x0E,0x30,0x0F,0xF0,0x0F,0xF0,0x0E,0x30,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x1F,0x00,0x00,0x00,0x00,0x00, // F -0x00,0x00,0x00,0x00,0x07,0xF0,0x0E,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x1C,0xF8,0x1C,0x38,0x1C,0x38,0x0E,0x38,0x07,0xF8,0x00,0x00,0x00,0x00, // G -0x00,0x00,0x00,0x00,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1F,0xF0,0x1F,0xF0,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x00,0x00,0x00,0x00, // H -0x00,0x00,0x00,0x00,0x0F,0xE0,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x0F,0xE0,0x00,0x00,0x00,0x00, // I -0x00,0x00,0x00,0x00,0x01,0xFC,0x00,0x70,0x00,0x70,0x00,0x70,0x00,0x70,0x00,0x70,0x00,0x70,0x38,0x70,0x38,0x70,0x38,0x70,0x38,0x70,0x0F,0xE0,0x00,0x00,0x00,0x00, // J -0x00,0x00,0x00,0x00,0x1E,0x38,0x0E,0x38,0x0E,0x70,0x0E,0xE0,0x0F,0xC0,0x0F,0x80,0x0F,0x80,0x0F,0xC0,0x0E,0xE0,0x0E,0x70,0x0E,0x38,0x1E,0x38,0x00,0x00,0x00,0x00, // K -0x00,0x00,0x00,0x00,0x1F,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x08,0x0E,0x18,0x0E,0x38,0x1F,0xF8,0x00,0x00,0x00,0x00, // L -0x00,0x00,0x00,0x00,0x1C,0x1C,0x1E,0x3C,0x1F,0x7C,0x1F,0xFC,0x1F,0xFC,0x1D,0xDC,0x1C,0x9C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x00,0x00,0x00,0x00, // M -0x00,0x00,0x00,0x00,0x1C,0x1C,0x1C,0x1C,0x1E,0x1C,0x1F,0x1C,0x1F,0x9C,0x1D,0xDC,0x1C,0xFC,0x1C,0x7C,0x1C,0x3C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x00,0x00,0x00,0x00, // N -0x00,0x00,0x00,0x00,0x03,0xE0,0x07,0xF0,0x0E,0x38,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x0E,0x38,0x07,0xF0,0x03,0xE0,0x00,0x00,0x00,0x00, // O + 0x00, 0x00, 0x0F, 0xF8, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0xFC, 0x1C, 0xFC, 0x1C, 0xFC, 0x1C, 0xFC, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x1F, 0xF0, 0x07, 0xF8, 0x00, 0x00, // @ + 0x00, 0x00, 0x00, 0x00, 0x03, 0xC0, 0x07, 0xE0, 0x0E, 0x70, 0x1C, 0x38, 0x1C, 0x38, 0x1C, 0x38, 0x1C, 0x38, 0x1F, 0xF8, 0x1C, 0x38, 0x1C, 0x38, 0x1C, 0x38, 0x1C, 0x38, 0x00, 0x00, 0x00, 0x00, // A + 0x00, 0x00, 0x00, 0x00, 0x1F, 0xF0, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0F, 0xF0, 0x0F, 0xF0, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x1F, 0xF0, 0x00, 0x00, 0x00, 0x00, // B + 0x00, 0x00, 0x00, 0x00, 0x07, 0xF0, 0x0E, 0x38, 0x1C, 0x38, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x38, 0x0E, 0x38, 0x07, 0xF0, 0x00, 0x00, 0x00, 0x00, // C + 0x00, 0x00, 0x00, 0x00, 0x1F, 0xE0, 0x0E, 0x70, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x70, 0x1F, 0xE0, 0x00, 0x00, 0x00, 0x00, // D + 0x00, 0x00, 0x00, 0x00, 0x1F, 0xF8, 0x0E, 0x18, 0x0E, 0x08, 0x0E, 0x00, 0x0E, 0x30, 0x0F, 0xF0, 0x0F, 0xF0, 0x0E, 0x30, 0x0E, 0x00, 0x0E, 0x08, 0x0E, 0x18, 0x1F, 0xF8, 0x00, 0x00, 0x00, 0x00, // E + 0x00, 0x00, 0x00, 0x00, 0x1F, 0xF8, 0x0E, 0x18, 0x0E, 0x08, 0x0E, 0x00, 0x0E, 0x30, 0x0F, 0xF0, 0x0F, 0xF0, 0x0E, 0x30, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, // F + 0x00, 0x00, 0x00, 0x00, 0x07, 0xF0, 0x0E, 0x38, 0x1C, 0x38, 0x1C, 0x38, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0xF8, 0x1C, 0x38, 0x1C, 0x38, 0x0E, 0x38, 0x07, 0xF8, 0x00, 0x00, 0x00, 0x00, // G + 0x00, 0x00, 0x00, 0x00, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x1F, 0xF0, 0x1F, 0xF0, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x00, 0x00, 0x00, 0x00, // H + 0x00, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, // I + 0x00, 0x00, 0x00, 0x00, 0x01, 0xFC, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x38, 0x70, 0x38, 0x70, 0x38, 0x70, 0x38, 0x70, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, // J + 0x00, 0x00, 0x00, 0x00, 0x1E, 0x38, 0x0E, 0x38, 0x0E, 0x70, 0x0E, 0xE0, 0x0F, 0xC0, 0x0F, 0x80, 0x0F, 0x80, 0x0F, 0xC0, 0x0E, 0xE0, 0x0E, 0x70, 0x0E, 0x38, 0x1E, 0x38, 0x00, 0x00, 0x00, 0x00, // K + 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x08, 0x0E, 0x18, 0x0E, 0x38, 0x1F, 0xF8, 0x00, 0x00, 0x00, 0x00, // L + 0x00, 0x00, 0x00, 0x00, 0x1C, 0x1C, 0x1E, 0x3C, 0x1F, 0x7C, 0x1F, 0xFC, 0x1F, 0xFC, 0x1D, 0xDC, 0x1C, 0x9C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x00, 0x00, 0x00, 0x00, // M + 0x00, 0x00, 0x00, 0x00, 0x1C, 0x1C, 0x1C, 0x1C, 0x1E, 0x1C, 0x1F, 0x1C, 0x1F, 0x9C, 0x1D, 0xDC, 0x1C, 0xFC, 0x1C, 0x7C, 0x1C, 0x3C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x00, 0x00, 0x00, 0x00, // N + 0x00, 0x00, 0x00, 0x00, 0x03, 0xE0, 0x07, 0xF0, 0x0E, 0x38, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x0E, 0x38, 0x07, 0xF0, 0x03, 0xE0, 0x00, 0x00, 0x00, 0x00, // O -0x00,0x00,0x00,0x00,0x1F,0xF0,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x0F,0xF0,0x0F,0xF0,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x1F,0x00,0x00,0x00,0x00,0x00, // P -0x00,0x00,0x00,0x00,0x03,0xE0,0x0F,0x78,0x0E,0x38,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x7C,0x1C,0xFC,0x0F,0xF8,0x0F,0xF8,0x00,0x38,0x00,0xFC,0x00,0x00, // Q -0x00,0x00,0x00,0x00,0x1F,0xF0,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x0F,0xF0,0x0F,0xF0,0x0E,0x70,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x1E,0x38,0x00,0x00,0x00,0x00, // R -0x00,0x00,0x00,0x00,0x0F,0xF0,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x00,0x0F,0xE0,0x07,0xF0,0x00,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x0F,0xF0,0x00,0x00,0x00,0x00, // S -0x00,0x00,0x00,0x00,0x1F,0xFC,0x19,0xCC,0x11,0xC4,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x07,0xF0,0x00,0x00,0x00,0x00, // T -0x00,0x00,0x00,0x00,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x0F,0xE0,0x00,0x00,0x00,0x00, // U -0x00,0x00,0x00,0x00,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x0E,0xE0,0x07,0xC0,0x03,0x80,0x00,0x00,0x00,0x00, // V -0x00,0x00,0x00,0x00,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x9C,0x1C,0x9C,0x1C,0x9C,0x0F,0xF8,0x0F,0xF8,0x07,0x70,0x07,0x70,0x00,0x00,0x00,0x00, // W -0x00,0x00,0x00,0x00,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x0E,0xE0,0x07,0xC0,0x03,0x80,0x03,0x80,0x07,0xC0,0x0E,0xE0,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x00,0x00,0x00,0x00, // X -0x00,0x00,0x00,0x00,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x0E,0xE0,0x07,0xC0,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x0F,0xE0,0x00,0x00,0x00,0x00, // Y -0x00,0x00,0x00,0x00,0x1F,0xF8,0x1C,0x38,0x18,0x38,0x10,0x70,0x00,0xE0,0x01,0xC0,0x03,0x80,0x07,0x00,0x0E,0x08,0x1C,0x18,0x1C,0x38,0x1F,0xF8,0x00,0x00,0x00,0x00, // Z -0x00,0x00,0x00,0x00,0x07,0xF0,0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x07,0xF0,0x00,0x00,0x00,0x00, // [ -0x00,0x00,0x00,0x00,0x10,0x00,0x18,0x00,0x1C,0x00,0x0E,0x00,0x07,0x00,0x03,0x80,0x01,0xC0,0x00,0xE0,0x00,0x70,0x00,0x38,0x00,0x1C,0x00,0x07,0x00,0x00,0x00,0x00, // -0x00,0x00,0x00,0x00,0x07,0xF0,0x00,0x70,0x00,0x70,0x00,0x70,0x00,0x70,0x00,0x70,0x00,0x70,0x00,0x70,0x00,0x70,0x00,0x70,0x00,0x70,0x07,0xF0,0x00,0x00,0x00,0x00, // ] -0x00,0x00,0x01,0x80,0x03,0xC0,0x07,0xE0,0x0E,0x70,0x1C,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ^ -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xFF,0x7F,0xFF, // _ + 0x00, 0x00, 0x00, 0x00, 0x1F, 0xF0, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0F, 0xF0, 0x0F, 0xF0, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, // P + 0x00, 0x00, 0x00, 0x00, 0x03, 0xE0, 0x0F, 0x78, 0x0E, 0x38, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x7C, 0x1C, 0xFC, 0x0F, 0xF8, 0x0F, 0xF8, 0x00, 0x38, 0x00, 0xFC, 0x00, 0x00, // Q + 0x00, 0x00, 0x00, 0x00, 0x1F, 0xF0, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0F, 0xF0, 0x0F, 0xF0, 0x0E, 0x70, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x1E, 0x38, 0x00, 0x00, 0x00, 0x00, // R + 0x00, 0x00, 0x00, 0x00, 0x0F, 0xF0, 0x1C, 0x38, 0x1C, 0x38, 0x1C, 0x38, 0x1C, 0x00, 0x0F, 0xE0, 0x07, 0xF0, 0x00, 0x38, 0x1C, 0x38, 0x1C, 0x38, 0x1C, 0x38, 0x0F, 0xF0, 0x00, 0x00, 0x00, 0x00, // S + 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFC, 0x19, 0xCC, 0x11, 0xC4, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x07, 0xF0, 0x00, 0x00, 0x00, 0x00, // T + 0x00, 0x00, 0x00, 0x00, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, // U + 0x00, 0x00, 0x00, 0x00, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x0E, 0xE0, 0x07, 0xC0, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, // V + 0x00, 0x00, 0x00, 0x00, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x9C, 0x1C, 0x9C, 0x1C, 0x9C, 0x0F, 0xF8, 0x0F, 0xF8, 0x07, 0x70, 0x07, 0x70, 0x00, 0x00, 0x00, 0x00, // W + 0x00, 0x00, 0x00, 0x00, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x0E, 0xE0, 0x07, 0xC0, 0x03, 0x80, 0x03, 0x80, 0x07, 0xC0, 0x0E, 0xE0, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x00, 0x00, 0x00, 0x00, // X + 0x00, 0x00, 0x00, 0x00, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x0E, 0xE0, 0x07, 0xC0, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, // Y + 0x00, 0x00, 0x00, 0x00, 0x1F, 0xF8, 0x1C, 0x38, 0x18, 0x38, 0x10, 0x70, 0x00, 0xE0, 0x01, 0xC0, 0x03, 0x80, 0x07, 0x00, 0x0E, 0x08, 0x1C, 0x18, 0x1C, 0x38, 0x1F, 0xF8, 0x00, 0x00, 0x00, 0x00, // Z + 0x00, 0x00, 0x00, 0x00, 0x07, 0xF0, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x00, 0x00, // [ + 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x18, 0x00, 0x1C, 0x00, 0x0E, 0x00, 0x07, 0x00, 0x03, 0x80, 0x01, 0xC0, 0x00, 0xE0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1C, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x07, 0xF0, 0x00, 0x00, 0x00, 0x00, // ] + 0x00, 0x00, 0x01, 0x80, 0x03, 0xC0, 0x07, 0xE0, 0x0E, 0x70, 0x1C, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ^ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0x7F, 0xFF, // _ -0x00,0x00,0x00,0x00,0x1C,0x00,0x1C,0x00,0x07,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ' -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xE0,0x00,0x70,0x00,0x70,0x0F,0xF0,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x0F,0xD8,0x00,0x00,0x00,0x00, // a -0x00,0x00,0x00,0x00,0x1E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0F,0xF0,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x1B,0xF0,0x00,0x00,0x00,0x00, // b -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xE0,0x1C,0x70,0x1C,0x70,0x1C,0x00,0x1C,0x00,0x1C,0x70,0x1C,0x70,0x0F,0xE0,0x00,0x00,0x00,0x00, // c -0x00,0x00,0x00,0x00,0x00,0xF8,0x00,0x70,0x00,0x70,0x00,0x70,0x0F,0xF0,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x0F,0xD8,0x00,0x00,0x00,0x00, // d -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xE0,0x1C,0x70,0x1C,0x70,0x1F,0xF0,0x1C,0x00,0x1C,0x70,0x1C,0x70,0x0F,0xE0,0x00,0x00,0x00,0x00, // e -0x00,0x00,0x00,0x00,0x03,0xE0,0x07,0x70,0x07,0x70,0x07,0x00,0x07,0x00,0x1F,0xE0,0x1F,0xE0,0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x1F,0xC0,0x00,0x00,0x00,0x00, // f -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xD8,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x0F,0xF0,0x07,0xF0,0x00,0x70,0x1C,0x70,0x0F,0xE0, // g -0x00,0x00,0x00,0x00,0x1E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0xF0,0x0F,0x38,0x0F,0x38,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x1E,0x38,0x00,0x00,0x00,0x00, // h -0x00,0x00,0x00,0x00,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x00,0x00,0x0F,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x0F,0xF8,0x00,0x00,0x00,0x00, // i -0x00,0x00,0x00,0x00,0x00,0x70,0x00,0x70,0x00,0x70,0x00,0x00,0x03,0xF0,0x00,0x70,0x00,0x70,0x00,0x70,0x00,0x70,0x00,0x70,0x00,0x70,0x1C,0x70,0x0C,0xF0,0x07,0xE0, // j -0x00,0x00,0x00,0x00,0x1E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x38,0x0E,0x70,0x0E,0xE0,0x0F,0xC0,0x0E,0xE0,0x0E,0x70,0x0E,0x38,0x1E,0x38,0x00,0x00,0x00,0x00, // k -0x00,0x00,0x00,0x00,0x0F,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x0F,0xF8,0x00,0x00,0x00,0x00, // l -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0xF8,0x1C,0x9C,0x1C,0x9C,0x1C,0x9C,0x1C,0x9C,0x1C,0x9C,0x1C,0x9C,0x1C,0x9C,0x00,0x00,0x00,0x00, // m -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0xE0,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x00,0x00,0x00,0x00, // n -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xE0,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x0F,0xE0,0x00,0x00,0x00,0x00, // o + 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ' + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x70, 0x00, 0x70, 0x0F, 0xF0, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x0F, 0xD8, 0x00, 0x00, 0x00, 0x00, // a + 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0F, 0xF0, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x1B, 0xF0, 0x00, 0x00, 0x00, 0x00, // b + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x00, 0x1C, 0x00, 0x1C, 0x70, 0x1C, 0x70, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, // c + 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x0F, 0xF0, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x0F, 0xD8, 0x00, 0x00, 0x00, 0x00, // d + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x1C, 0x70, 0x1C, 0x70, 0x1F, 0xF0, 0x1C, 0x00, 0x1C, 0x70, 0x1C, 0x70, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, // e + 0x00, 0x00, 0x00, 0x00, 0x03, 0xE0, 0x07, 0x70, 0x07, 0x70, 0x07, 0x00, 0x07, 0x00, 0x1F, 0xE0, 0x1F, 0xE0, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x00, 0x00, // f + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xD8, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x0F, 0xF0, 0x07, 0xF0, 0x00, 0x70, 0x1C, 0x70, 0x0F, 0xE0, // g + 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0xF0, 0x0F, 0x38, 0x0F, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x1E, 0x38, 0x00, 0x00, 0x00, 0x00, // h + 0x00, 0x00, 0x00, 0x00, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x0F, 0xF8, 0x00, 0x00, 0x00, 0x00, // i + 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x1C, 0x70, 0x0C, 0xF0, 0x07, 0xE0, // j + 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x38, 0x0E, 0x70, 0x0E, 0xE0, 0x0F, 0xC0, 0x0E, 0xE0, 0x0E, 0x70, 0x0E, 0x38, 0x1E, 0x38, 0x00, 0x00, 0x00, 0x00, // k + 0x00, 0x00, 0x00, 0x00, 0x0F, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x0F, 0xF8, 0x00, 0x00, 0x00, 0x00, // l + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xF8, 0x1C, 0x9C, 0x1C, 0x9C, 0x1C, 0x9C, 0x1C, 0x9C, 0x1C, 0x9C, 0x1C, 0x9C, 0x1C, 0x9C, 0x00, 0x00, 0x00, 0x00, // m + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xE0, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x00, 0x00, 0x00, 0x00, // n + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, // o -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1B,0xF0,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x0F,0xF0,0x0E,0x00,0x0E,0x00,0x1F,0x00, // p -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0xB0,0x38,0xE0,0x38,0xE0,0x38,0xE0,0x38,0xE0,0x38,0xE0,0x1F,0xE0,0x00,0xE0,0x00,0xE0,0x01,0xF0, // q -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0xF0,0x0F,0xF8,0x0F,0x38,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x1F,0x00,0x00,0x00,0x00,0x00, // r -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xE0,0x1C,0x30,0x1C,0x30,0x0F,0x80,0x03,0xE0,0x18,0x70,0x18,0x70,0x0F,0xE0,0x00,0x00,0x00,0x00, // s -0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x00,0x07,0x00,0x1F,0xF0,0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x70,0x07,0x70,0x03,0xE0,0x00,0x00,0x00,0x00, // t -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x0F,0xD8,0x00,0x00,0x00,0x00, // u -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x0E,0xE0,0x07,0xC0,0x03,0x80,0x00,0x00,0x00,0x00, // v -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x9C,0x1C,0x9C,0x0F,0xF8,0x07,0x70,0x07,0x70,0x00,0x00,0x00,0x00, // w -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0xE0,0x1C,0xE0,0x0F,0xC0,0x07,0x80,0x07,0x80,0x0F,0xC0,0x1C,0xE0,0x1C,0xE0,0x00,0x00,0x00,0x00, // x -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x07,0xF0,0x03,0xE0,0x00,0xE0,0x01,0xC0,0x1F,0x80, // y -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0xE0,0x18,0xE0,0x11,0xC0,0x03,0x80,0x07,0x00,0x0E,0x20,0x1C,0x60,0x1F,0xE0,0x00,0x00,0x00,0x00, // z -0x00,0x00,0x00,0x00,0x01,0xF8,0x03,0x80,0x03,0x80,0x03,0x80,0x07,0x00,0x1C,0x00,0x1C,0x00,0x07,0x00,0x03,0x80,0x03,0x80,0x03,0x80,0x01,0xF8,0x00,0x00,0x00,0x00, // { -0x00,0x00,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x00,0x00, // | -0x00,0x00,0x00,0x00,0x1F,0x80,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x00,0xE0,0x00,0x38,0x00,0x38,0x00,0xE0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x1F,0x80,0x00,0x00,0x00,0x00, // } -0x00,0x00,0x00,0x00,0x1F,0x1C,0x3B,0x9C,0x39,0xDC,0x38,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ~ -0x0C,0x30,0x0C,0x30,0x03,0xC0,0x07,0xE0,0x0E,0x70,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1F,0xF8,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x00,0x00,0x00,0x00, // Ä + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0xF0, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0F, 0xF0, 0x0E, 0x00, 0x0E, 0x00, 0x1F, 0x00, // p + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xB0, 0x38, 0xE0, 0x38, 0xE0, 0x38, 0xE0, 0x38, 0xE0, 0x38, 0xE0, 0x1F, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x01, 0xF0, // q + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0xF0, 0x0F, 0xF8, 0x0F, 0x38, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, // r + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x1C, 0x30, 0x1C, 0x30, 0x0F, 0x80, 0x03, 0xE0, 0x18, 0x70, 0x18, 0x70, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, // s + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03, 0x00, 0x07, 0x00, 0x1F, 0xF0, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x70, 0x07, 0x70, 0x03, 0xE0, 0x00, 0x00, 0x00, 0x00, // t + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x0F, 0xD8, 0x00, 0x00, 0x00, 0x00, // u + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x0E, 0xE0, 0x07, 0xC0, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, // v + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x9C, 0x1C, 0x9C, 0x0F, 0xF8, 0x07, 0x70, 0x07, 0x70, 0x00, 0x00, 0x00, 0x00, // w + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0xE0, 0x1C, 0xE0, 0x0F, 0xC0, 0x07, 0x80, 0x07, 0x80, 0x0F, 0xC0, 0x1C, 0xE0, 0x1C, 0xE0, 0x00, 0x00, 0x00, 0x00, // x + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x07, 0xF0, 0x03, 0xE0, 0x00, 0xE0, 0x01, 0xC0, 0x1F, 0x80, // y + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xE0, 0x18, 0xE0, 0x11, 0xC0, 0x03, 0x80, 0x07, 0x00, 0x0E, 0x20, 0x1C, 0x60, 0x1F, 0xE0, 0x00, 0x00, 0x00, 0x00, // z + 0x00, 0x00, 0x00, 0x00, 0x01, 0xF8, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x07, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x07, 0x00, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x01, 0xF8, 0x00, 0x00, 0x00, 0x00, // { + 0x00, 0x00, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x00, 0x00, // | + 0x00, 0x00, 0x00, 0x00, 0x1F, 0x80, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x00, 0xE0, 0x00, 0x38, 0x00, 0x38, 0x00, 0xE0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00, // } + 0x00, 0x00, 0x00, 0x00, 0x1F, 0x1C, 0x3B, 0x9C, 0x39, 0xDC, 0x38, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ~ + 0x0C, 0x30, 0x0C, 0x30, 0x03, 0xC0, 0x07, 0xE0, 0x0E, 0x70, 0x1C, 0x38, 0x1C, 0x38, 0x1C, 0x38, 0x1C, 0x38, 0x1F, 0xF8, 0x1C, 0x38, 0x1C, 0x38, 0x1C, 0x38, 0x1C, 0x38, 0x00, 0x00, 0x00, 0x00, // Ä -0x0C,0x18,0x0C,0x18,0x03,0xE0,0x07,0xF0,0x0E,0x38,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x0E,0x38,0x07,0xF0,0x03,0xE0,0x00,0x00,0x00,0x00, // Ö -0x0C,0x60,0x0C,0x60,0x00,0x00,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x0F,0xE0,0x00,0x00,0x00,0x00, // Ü -0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x60,0x0C,0x60,0x00,0x00,0x0F,0xE0,0x00,0x70,0x00,0x70,0x0F,0xF0,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x0F,0xD8,0x00,0x00,0x00,0x00, // ä -0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x60,0x0C,0x60,0x00,0x00,0x0F,0xE0,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x0F,0xE0,0x00,0x00,0x00,0x00, // o -0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x60,0x0C,0x60,0x00,0x00,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x0F,0xD8,0x00,0x00,0x00,0x00 // u -}; + 0x0C, 0x18, 0x0C, 0x18, 0x03, 0xE0, 0x07, 0xF0, 0x0E, 0x38, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x0E, 0x38, 0x07, 0xF0, 0x03, 0xE0, 0x00, 0x00, 0x00, 0x00, // Ö + 0x0C, 0x60, 0x0C, 0x60, 0x00, 0x00, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, // Ü + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x60, 0x0C, 0x60, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x70, 0x00, 0x70, 0x0F, 0xF0, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x0F, 0xD8, 0x00, 0x00, 0x00, 0x00, // ä + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x60, 0x0C, 0x60, 0x00, 0x00, 0x0F, 0xE0, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, // o + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x60, 0x0C, 0x60, 0x00, 0x00, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x1C, 0x70, 0x0F, 0xD8, 0x00, 0x00, 0x00, 0x00 // u +}; // SevenSegNumFont.c // Font Size : 32x50 // Memory usage : 2004 bytes // # characters : 10 -const char seven_seg_num_font[2004] = { -0x20,0x32,0x30,0x0A, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFE,0x00,0x01,0xFF,0xFF,0x00,0x03,0xFF,0xFF,0x80,0x01,0xFF,0xFF,0x60,0x0C,0xFF,0xFE,0xF0,0x1E,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3E,0x00,0x00,0x78,0x38,0x00,0x00,0x18,0x20,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x38,0x00,0x00,0x18,0x3E,0x00,0x00,0x78,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x1E,0x00,0x00,0xF0,0x0C,0xFF,0xFE,0x60,0x01,0xFF,0xFF,0x00,0x03,0xFF,0xFF,0x80,0x01,0xFF,0xFF,0x00,0x00,0xFF,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 0 -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0xF0,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x78,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 1 -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFE,0x00,0x01,0xFF,0xFF,0x00,0x03,0xFF,0xFF,0x80,0x01,0xFF,0xFF,0x60,0x00,0xFF,0xFE,0xF0,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x00,0x78,0x01,0xFF,0xFE,0x18,0x03,0xFF,0xFF,0x88,0x0F,0xFF,0xFF,0xE0,0x27,0xFF,0xFF,0xC0,0x39,0xFF,0xFF,0x00,0x3E,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x1E,0x00,0x00,0x00,0x0C,0xFF,0xFE,0x00,0x01,0xFF,0xFF,0x00,0x03,0xFF,0xFF,0x80,0x01,0xFF,0xFF,0x00,0x00,0xFF,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 2 -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFE,0x00,0x01,0xFF,0xFF,0x00,0x03,0xFF,0xFF,0x80,0x01,0xFF,0xFF,0x60,0x00,0xFF,0xFE,0xF0,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x00,0x78,0x01,0xFF,0xFE,0x18,0x03,0xFF,0xFF,0x88,0x0F,0xFF,0xFF,0xE0,0x07,0xFF,0xFF,0xC0,0x01,0xFF,0xFF,0x18,0x00,0x00,0x00,0x78,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x00,0xF0,0x00,0xFF,0xFE,0x60,0x01,0xFF,0xFF,0x00,0x03,0xFF,0xFF,0x80,0x01,0xFF,0xFF,0x00,0x00,0xFF,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 3 -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x0C,0x00,0x00,0xF0,0x1E,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3E,0x00,0x00,0x78,0x39,0xFF,0xFE,0x18,0x23,0xFF,0xFF,0x88,0x0F,0xFF,0xFF,0xE0,0x07,0xFF,0xFF,0xC0,0x01,0xFF,0xFF,0x18,0x00,0x00,0x00,0x78,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 4 -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFE,0x00,0x01,0xFF,0xFF,0x00,0x03,0xFF,0xFF,0x80,0x01,0xFF,0xFF,0x00,0x0C,0xFF,0xFE,0x00,0x1E,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3E,0x00,0x00,0x00,0x39,0xFF,0xFE,0x00,0x23,0xFF,0xFF,0x80,0x0F,0xFF,0xFF,0xE0,0x07,0xFF,0xFF,0xC0,0x01,0xFF,0xFF,0x18,0x00,0x00,0x00,0x78,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x00,0xF0,0x00,0xFF,0xFE,0x60,0x01,0xFF,0xFF,0x00,0x03,0xFF,0xFF,0x80,0x01,0xFF,0xFF,0x00,0x00,0xFF,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 5 -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFE,0x00,0x01,0xFF,0xFF,0x00,0x03,0xFF,0xFF,0x80,0x01,0xFF,0xFF,0x00,0x0C,0xFF,0xFE,0x00,0x1E,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3E,0x00,0x00,0x00,0x39,0xFF,0xFE,0x00,0x23,0xFF,0xFF,0x80,0x0F,0xFF,0xFF,0xE0,0x27,0xFF,0xFF,0xC0,0x39,0xFF,0xFF,0x18,0x3E,0x00,0x00,0x78,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x1E,0x00,0x00,0xF0,0x0C,0xFF,0xFE,0x60,0x01,0xFF,0xFF,0x00,0x03,0xFF,0xFF,0x80,0x01,0xFF,0xFF,0x00,0x00,0xFF,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 6 -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFE,0x00,0x01,0xFF,0xFF,0x00,0x03,0xFF,0xFF,0x80,0x01,0xFF,0xFF,0x60,0x00,0xFF,0xFE,0xF0,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x78,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 7 -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFE,0x00,0x01,0xFF,0xFF,0x00,0x03,0xFF,0xFF,0x80,0x01,0xFF,0xFF,0x60,0x0C,0xFF,0xFE,0xF0,0x1E,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3E,0x00,0x00,0x78,0x39,0xFF,0xFE,0x18,0x23,0xFF,0xFF,0x88,0x0F,0xFF,0xFF,0xE0,0x27,0xFF,0xFF,0xC0,0x39,0xFF,0xFF,0x18,0x3E,0x00,0x00,0x78,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x1E,0x00,0x00,0xF0,0x0C,0xFF,0xFE,0x60,0x01,0xFF,0xFF,0x00,0x03,0xFF,0xFF,0x80,0x01,0xFF,0xFF,0x00,0x00,0xFF,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 8 -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFE,0x00,0x01,0xFF,0xFF,0x00,0x03,0xFF,0xFF,0x80,0x01,0xFF,0xFF,0x60,0x0C,0xFF,0xFE,0xF0,0x1E,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3E,0x00,0x00,0x78,0x39,0xFF,0xFE,0x18,0x23,0xFF,0xFF,0x88,0x0F,0xFF,0xFF,0xE0,0x07,0xFF,0xFF,0xC0,0x01,0xFF,0xFF,0x18,0x00,0x00,0x00,0x78,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x00,0xF0,0x00,0xFF,0xFE,0x60,0x01,0xFF,0xFF,0x00,0x03,0xFF,0xFF,0x80,0x01,0xFF,0xFF,0x00,0x00,0xFF,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 9 +const char seven_seg_num_font[2004] = { + 0x20, 0x32, 0x30, 0x0A, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x60, 0x0C, 0xFF, 0xFE, 0xF0, 0x1E, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3E, 0x00, 0x00, 0x78, 0x38, 0x00, 0x00, 0x18, 0x20, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x18, 0x3E, 0x00, 0x00, 0x78, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x1E, 0x00, 0x00, 0xF0, 0x0C, 0xFF, 0xFE, 0x60, 0x01, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 1 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x60, 0x00, 0xFF, 0xFE, 0xF0, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x00, 0x78, 0x01, 0xFF, 0xFE, 0x18, 0x03, 0xFF, 0xFF, 0x88, 0x0F, 0xFF, 0xFF, 0xE0, 0x27, 0xFF, 0xFF, 0xC0, 0x39, 0xFF, 0xFF, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x0C, 0xFF, 0xFE, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 2 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x60, 0x00, 0xFF, 0xFE, 0xF0, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x00, 0x78, 0x01, 0xFF, 0xFE, 0x18, 0x03, 0xFF, 0xFF, 0x88, 0x0F, 0xFF, 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0xC0, 0x01, 0xFF, 0xFF, 0x18, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x00, 0xF0, 0x00, 0xFF, 0xFE, 0x60, 0x01, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 3 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x0C, 0x00, 0x00, 0xF0, 0x1E, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3E, 0x00, 0x00, 0x78, 0x39, 0xFF, 0xFE, 0x18, 0x23, 0xFF, 0xFF, 0x88, 0x0F, 0xFF, 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0xC0, 0x01, 0xFF, 0xFF, 0x18, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 4 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x00, 0x0C, 0xFF, 0xFE, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x39, 0xFF, 0xFE, 0x00, 0x23, 0xFF, 0xFF, 0x80, 0x0F, 0xFF, 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0xC0, 0x01, 0xFF, 0xFF, 0x18, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x00, 0xF0, 0x00, 0xFF, 0xFE, 0x60, 0x01, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 5 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x00, 0x0C, 0xFF, 0xFE, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x39, 0xFF, 0xFE, 0x00, 0x23, 0xFF, 0xFF, 0x80, 0x0F, 0xFF, 0xFF, 0xE0, 0x27, 0xFF, 0xFF, 0xC0, 0x39, 0xFF, 0xFF, 0x18, 0x3E, 0x00, 0x00, 0x78, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x1E, 0x00, 0x00, 0xF0, 0x0C, 0xFF, 0xFE, 0x60, 0x01, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 6 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x60, 0x00, 0xFF, 0xFE, 0xF0, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 7 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x60, 0x0C, 0xFF, 0xFE, 0xF0, 0x1E, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3E, 0x00, 0x00, 0x78, 0x39, 0xFF, 0xFE, 0x18, 0x23, 0xFF, 0xFF, 0x88, 0x0F, 0xFF, 0xFF, 0xE0, 0x27, 0xFF, 0xFF, 0xC0, 0x39, 0xFF, 0xFF, 0x18, 0x3E, 0x00, 0x00, 0x78, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x1E, 0x00, 0x00, 0xF0, 0x0C, 0xFF, 0xFE, 0x60, 0x01, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 8 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x60, 0x0C, 0xFF, 0xFE, 0xF0, 0x1E, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3E, 0x00, 0x00, 0x78, 0x39, 0xFF, 0xFE, 0x18, 0x23, 0xFF, 0xFF, 0x88, 0x0F, 0xFF, 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0xC0, 0x01, 0xFF, 0xFF, 0x18, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x00, 0xF0, 0x00, 0xFF, 0xFE, 0x60, 0x01, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 9 }; diff --git a/discovery/src/font.h b/discovery/src/font.h index ca0035a..d95d3a1 100644 --- a/discovery/src/font.h +++ b/discovery/src/font.h @@ -1,3 +1,16 @@ +/************************************************************************************************************************************** +* Project: discoverpixy +* Website: https://github.com/t-moe/discoverpixy +* Authors: Aaron Schmocker, Timo Lang +* Institution: BFH Bern University of Applied Sciences +* File: discovery/src/font.h +* +* Version History: +* Date Autor Email SHA Changes +* 2015-05-11 aaron@duckpond.ch 21fddc3 Implemented new functions +* +**************************************************************************************************************************************/ + const char small_font[1216]; const char big_font[3236]; const char seven_seg_num_font[2004]; diff --git a/discovery/src/ll_filesystem.c b/discovery/src/ll_filesystem.c index fda6515..0be8986 100644 --- a/discovery/src/ll_filesystem.c +++ b/discovery/src/ll_filesystem.c @@ -1,38 +1,56 @@ +/************************************************************************************************************************************** +* Project: discoverpixy +* Website: https://github.com/t-moe/discoverpixy +* Authors: Aaron Schmocker, Timo Lang +* Institution: BFH Bern University of Applied Sciences +* File: discovery/src/ll_filesystem.c +* +* Version History: +* Date Autor Email SHA Changes +* 2015-05-10 timolang@gmail.com e2bce8f Added filesystem module, tests and implementation for it in emulator. +* +**************************************************************************************************************************************/ + #include "ll_filesystem.h" #include -bool ll_filesystem_init() { - return false; +bool ll_filesystem_init() +{ + return false; } -DIRECTORY_STRUCT* ll_filesystem_dir_open(const char* path) { - return NULL; +DIRECTORY_STRUCT* ll_filesystem_dir_open(const char* path) +{ + return NULL; } -void ll_filesystem_dir_close(DIRECTORY_STRUCT* dir) { - +void ll_filesystem_dir_close(DIRECTORY_STRUCT* dir) +{ + } -FILE_HANDLE* ll_filesystem_file_open(const char* filename) { - return NULL; +FILE_HANDLE* ll_filesystem_file_open(const char* filename) +{ + return NULL; } -void ll_filesystem_file_close(FILE_HANDLE* handle) { - +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_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_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; +FILE_STATUS ll_filesystem_file_write(FILE_HANDLE* handle, uint8_t* buf, uint32_t size) +{ + return F_DISKERROR; } - - - diff --git a/discovery/src/ll_system.c b/discovery/src/ll_system.c index 3b93a6f..ca91429 100644 --- a/discovery/src/ll_system.c +++ b/discovery/src/ll_system.c @@ -1,60 +1,80 @@ -#include "ll_system.h" -#include "stm32f4xx.h" -#include "stm32f4_discovery.h" -#include - -#include "usb_hcd_int.h" -#include "usbh_usr.h" -#include "usbh_core.h" -#include "usbh_msc_core.h" - -USB_OTG_CORE_HANDLE USB_OTG_Core; -USBH_HOST USB_Host; -RCC_ClocksTypeDef RCC_Clocks; - -void SysTick_Handler(void) -{ - USBH_LL_systick(); -} - -void TIM2_IRQHandler(void) -{ - USB_OTG_BSP_TimerIRQ(); -} - -void OTG_FS_IRQHandler(void) -{ - USBH_OTG_ISR_Handler(&USB_OTG_Core); -} - -bool ll_system_init(void) -{ - /* Initialize LEDS */ - STM_EVAL_LEDInit(LED3); - STM_EVAL_LEDInit(LED4); - //LED5 and LED6 can not be used because of pin conflict. See docu - - STM_EVAL_PBInit(BUTTON_USER, BUTTON_MODE_GPIO); - - - /* SysTick end of count event each 1ms */ - RCC_GetClocksFreq(&RCC_Clocks); //we run at 168mhz :) - SysTick_Config(RCC_Clocks.HCLK_Frequency / 1000); - - /* Init Host Library */ - USBH_Init(&USB_OTG_Core, USB_OTG_FS_CORE_ID, &USB_Host, &USBH_MSC_cb, &USR_Callbacks); - - return true; -} - -void ll_system_process() { - USBH_Process(&USB_OTG_Core, &USB_Host); -} - -void ll_system_delay(uint32_t msec) { - USB_OTG_BSP_mDelay(msec); -} - -void ll_system_toggle_led() { - //no led's free :( -} +/************************************************************************************************************************************** +* Project: discoverpixy +* Website: https://github.com/t-moe/discoverpixy +* Authors: Aaron Schmocker, Timo Lang +* Institution: BFH Bern University of Applied Sciences +* File: discovery/src/ll_system.c +* +* Version History: +* Date Autor Email SHA Changes +* 2015-04-03 timolang@gmail.com 9a1d12a Refactored discovery, to use new project structure. Almost ready. +* 2015-04-25 timolang@gmail.com 3d1e4b2 Simplified code a bit. Emulator does not work stable when replugging pixy. +* 2015-04-25 timolang@gmail.com 0858b0d Fixed some bugs when receiving large data. +* 2015-04-27 aaron@duckpond.ch 0b61f21 Fixed misplacement of prototypes in ll_tft.h and implemented a propper init function. +* 2015-06-02 timolang@gmail.com 16bfdad Removed conflicting led usage from usb code. +* +**************************************************************************************************************************************/ + +#include "ll_system.h" +#include "stm32f4xx.h" +#include "stm32f4_discovery.h" +#include + +#include "usb_hcd_int.h" +#include "usbh_usr.h" +#include "usbh_core.h" +#include "usbh_msc_core.h" + +USB_OTG_CORE_HANDLE USB_OTG_Core; +USBH_HOST USB_Host; +RCC_ClocksTypeDef RCC_Clocks; + +void SysTick_Handler(void) +{ + USBH_LL_systick(); +} + +void TIM2_IRQHandler(void) +{ + USB_OTG_BSP_TimerIRQ(); +} + +void OTG_FS_IRQHandler(void) +{ + USBH_OTG_ISR_Handler(&USB_OTG_Core); +} + +bool ll_system_init(void) +{ + /* Initialize LEDS */ + STM_EVAL_LEDInit(LED3); + STM_EVAL_LEDInit(LED4); + //LED5 and LED6 can not be used because of pin conflict. See docu + + STM_EVAL_PBInit(BUTTON_USER, BUTTON_MODE_GPIO); + + + /* SysTick end of count event each 1ms */ + RCC_GetClocksFreq(&RCC_Clocks); //we run at 168mhz :) + SysTick_Config(RCC_Clocks.HCLK_Frequency / 1000); + + /* Init Host Library */ + USBH_Init(&USB_OTG_Core, USB_OTG_FS_CORE_ID, &USB_Host, &USBH_MSC_cb, &USR_Callbacks); + + return true; +} + +void ll_system_process() +{ + USBH_Process(&USB_OTG_Core, &USB_Host); +} + +void ll_system_delay(uint32_t msec) +{ + USB_OTG_BSP_mDelay(msec); +} + +void ll_system_toggle_led() +{ + //no led's free :( +} diff --git a/discovery/src/ll_tft.c b/discovery/src/ll_tft.c index 0b25998..8d8756a 100644 --- a/discovery/src/ll_tft.c +++ b/discovery/src/ll_tft.c @@ -1,5 +1,31 @@ +/************************************************************************************************************************************** +* Project: discoverpixy +* Website: https://github.com/t-moe/discoverpixy +* Authors: Aaron Schmocker, Timo Lang +* Institution: BFH Bern University of Applied Sciences +* File: discovery/src/ll_tft.c +* +* Version History: +* Date Autor Email SHA Changes +* 2015-04-03 timolang@gmail.com 9a1d12a Refactored discovery, to use new project structure. Almost ready. +* 2015-04-03 timolang@gmail.com 1aa9194 Fixed Drawing of rects in Emulator. Got frames from pixy to emulator. Slooooow. +* 2015-04-27 aaron@duckpond.ch aed90ef Drawcircle added (emulator) +* 2015-04-27 timolang@gmail.com e249fb2 Added font support +* 2015-04-27 aaron@duckpond.ch f0a6c3b Implemented init functions for gpio, fsmc and display +* 2015-04-27 aaron@duckpond.ch 0b61f21 Fixed misplacement of prototypes in ll_tft.h and implemented a propper init function. +* 2015-04-28 aaron@duckpond.ch a413591 Implemented ll_tft_fill_rectange and ll_tft_set_window +* 2015-05-04 aaron@duckpond.ch c224d40 Changed display init +* 2015-05-11 aaron@duckpond.ch 21fddc3 Implemented new functions +* 2015-05-12 aaron@duckpond.ch aec62d4 Added datasheets, updated touchsupport. +* 2015-06-01 aaron@duckpond.ch caa7b5c Added IRQ for user button, fixed some touchproblems. +* 2015-06-01 timolang@gmail.com 60c2895 Fixed lowlevel tft discovery functions for draw_char and fill_rect. +* 2015-06-02 timolang@gmail.com da34bce Fixed all printf related problems on discovery using workarounds and newlib nano-instead of newlib +* 2015-06-06 aaron@duckpond.ch a04cda9 Refactured comments and implemented a bugfix for the PID controller +* +**************************************************************************************************************************************/ + /* TFT lowlevel functions - * + * * Pinout: * ---------------------------------------- * PB0 -> LCD_Backlight PE3 -> LCD_RS @@ -42,17 +68,18 @@ static void tft_set_backlight(bool state); static void tft_reset(bool state); static void tft_write_reg(uint8_t reg_adr, uint16_t reg_value); static uint16_t tft_read_reg(uint8_t reg_adr); -static void tft_set_window(uint16_t xstart, uint16_t ystart, uint16_t xend, uint16_t yend);void tft_reset_window(); +static void tft_set_window(uint16_t xstart, uint16_t ystart, uint16_t xend, uint16_t yend); +void tft_reset_window(); /* draw functions */ void ll_tft_draw_line(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color); -void ll_tft_draw_pixel(uint16_t x,uint16_t y,uint16_t color); +void ll_tft_draw_pixel(uint16_t x, uint16_t y, uint16_t color); void ll_tft_draw_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color); void ll_tft_draw_bitmap_unscaled(uint16_t x, uint16_t y, uint16_t width, uint16_t height, const uint16_t* dat); void ll_tft_draw_circle(uint16_t x, uint16_t y, uint16_t r, uint16_t color); /* font functions */ -static const char *get_font(uint8_t font); +static const char* get_font(uint8_t font); uint8_t ll_tft_num_fonts(); uint8_t ll_tft_font_height(uint8_t fontnum); uint8_t ll_tft_font_width(uint8_t fontnum); @@ -73,7 +100,7 @@ void ll_tft_draw_char(uint16_t x, uint16_t y, uint16_t color, uint16_t bgcolo #define DISPLAY_COLOR_YELLOW 0xFFE0 #define DISPLAY_COLOR_GREY 0xF7DE -// FSMC adresses +// FSMC adresses #define TFT_REG (*((volatile unsigned short *) 0x60000000)) // RS = 0 #define TFT_RAM (*((volatile unsigned short *) 0x60100000)) // RS = 1 #define TFT_RAM_ADR 0x60100000 // RAM adress @@ -115,105 +142,105 @@ bool ll_tft_init() fsmc = fsmc_init(); // init fsmc system_delay(TFT_INIT_TIMEOUT); // delay display = display_init(); // init display - + return (gpio & fsmc & display); } -static bool display_init() +static bool display_init() { tft_reset(true); // toggle reset system_delay(TFT_INIT_TIMEOUT); tft_reset(false); - tft_write_reg(0x0007,0x0021); + tft_write_reg(0x0007, 0x0021); system_delay(TFT_INIT_TIMEOUT); - tft_write_reg(0x0000,0x0001); + tft_write_reg(0x0000, 0x0001); system_delay(TFT_INIT_TIMEOUT); - tft_write_reg(0x0007,0x0023); + tft_write_reg(0x0007, 0x0023); system_delay(TFT_INIT_TIMEOUT); - tft_write_reg(0x0010,0x0000); + tft_write_reg(0x0010, 0x0000); system_delay(TFT_INIT_TIMEOUT); - tft_write_reg(0x0007,0x0033); + tft_write_reg(0x0007, 0x0033); system_delay(TFT_INIT_TIMEOUT); - tft_write_reg(TFT_SSD1289_REG_11,0x6018); // set mode (landscape, portrait) + tft_write_reg(TFT_SSD1289_REG_11, 0x6018); // set mode (landscape, portrait) system_delay(TFT_INIT_TIMEOUT); - tft_write_reg(0x0002,0x0600); + tft_write_reg(0x0002, 0x0600); system_delay(TFT_INIT_TIMEOUT); //tft_write_reg(0x0012,0x6CEB); system_delay(TFT_INIT_TIMEOUT); - tft_write_reg(0x0003,0xA8A4); + tft_write_reg(0x0003, 0xA8A4); system_delay(TFT_INIT_TIMEOUT); - tft_write_reg(0x000C,0x0000); + tft_write_reg(0x000C, 0x0000); system_delay(TFT_INIT_TIMEOUT); - tft_write_reg(0x000D,0x080C); + tft_write_reg(0x000D, 0x080C); system_delay(TFT_INIT_TIMEOUT); - tft_write_reg(0x000E,0x2B00); + tft_write_reg(0x000E, 0x2B00); system_delay(TFT_INIT_TIMEOUT); - tft_write_reg(0x001E,0x00B0); + tft_write_reg(0x001E, 0x00B0); system_delay(TFT_INIT_TIMEOUT); - tft_write_reg(0x0001,0x2b3F); + tft_write_reg(0x0001, 0x2b3F); system_delay(TFT_INIT_TIMEOUT); - tft_write_reg(0x0005,0x0000); + tft_write_reg(0x0005, 0x0000); system_delay(TFT_INIT_TIMEOUT); - tft_write_reg(0x0006,0x0000); + tft_write_reg(0x0006, 0x0000); system_delay(TFT_INIT_TIMEOUT); - tft_write_reg(0x0016,0xEF1C); + tft_write_reg(0x0016, 0xEF1C); system_delay(TFT_INIT_TIMEOUT); - tft_write_reg(0x0017,0x0103); + tft_write_reg(0x0017, 0x0103); system_delay(TFT_INIT_TIMEOUT); - tft_write_reg(0x000B,0x0000); + tft_write_reg(0x000B, 0x0000); system_delay(TFT_INIT_TIMEOUT); - tft_write_reg(0x000F,0x0000); + tft_write_reg(0x000F, 0x0000); system_delay(TFT_INIT_TIMEOUT); - tft_write_reg(0x0041,0x0000); + tft_write_reg(0x0041, 0x0000); system_delay(TFT_INIT_TIMEOUT); - tft_write_reg(0x0042,0x0000); + tft_write_reg(0x0042, 0x0000); system_delay(TFT_INIT_TIMEOUT); - tft_write_reg(0x0048,0x0000); + tft_write_reg(0x0048, 0x0000); system_delay(TFT_INIT_TIMEOUT); - tft_write_reg(0x0049,0x013F); + tft_write_reg(0x0049, 0x013F); system_delay(TFT_INIT_TIMEOUT); - tft_write_reg(0x004A,0x0000); + tft_write_reg(0x004A, 0x0000); system_delay(TFT_INIT_TIMEOUT); - tft_write_reg(0x004B,0x0000); + tft_write_reg(0x004B, 0x0000); system_delay(TFT_INIT_TIMEOUT); - tft_write_reg(0x0044,0xEF00); // horizontal start and end + tft_write_reg(0x0044, 0xEF00); // horizontal start and end system_delay(TFT_INIT_TIMEOUT); - tft_write_reg(0x0045,0x0000); // vertical start + tft_write_reg(0x0045, 0x0000); // vertical start system_delay(TFT_INIT_TIMEOUT); - tft_write_reg(0x0046,0x013F); // vertical end + tft_write_reg(0x0046, 0x013F); // vertical end system_delay(TFT_INIT_TIMEOUT); - tft_write_reg(0x0030,0x0707); + tft_write_reg(0x0030, 0x0707); system_delay(TFT_INIT_TIMEOUT); - tft_write_reg(0x0031,0x0204); + tft_write_reg(0x0031, 0x0204); system_delay(TFT_INIT_TIMEOUT); - tft_write_reg(0x0032,0x0204); + tft_write_reg(0x0032, 0x0204); system_delay(TFT_INIT_TIMEOUT); - tft_write_reg(0x0033,0x0502); + tft_write_reg(0x0033, 0x0502); system_delay(TFT_INIT_TIMEOUT); - tft_write_reg(0x0034,0x0507); + tft_write_reg(0x0034, 0x0507); system_delay(TFT_INIT_TIMEOUT); - tft_write_reg(0x0035,0x0204); + tft_write_reg(0x0035, 0x0204); system_delay(TFT_INIT_TIMEOUT); - tft_write_reg(0x0036,0x0204); + tft_write_reg(0x0036, 0x0204); system_delay(TFT_INIT_TIMEOUT); - tft_write_reg(0x0037,0x0502); + tft_write_reg(0x0037, 0x0502); system_delay(TFT_INIT_TIMEOUT); - tft_write_reg(0x003A,0x0302); + tft_write_reg(0x003A, 0x0302); system_delay(TFT_INIT_TIMEOUT); //tft_write_reg(0x002F,0x12BE); system_delay(TFT_INIT_TIMEOUT); - tft_write_reg(0x003B,0x0302); + tft_write_reg(0x003B, 0x0302); system_delay(TFT_INIT_TIMEOUT); - tft_write_reg(0x0023,0x0000); + tft_write_reg(0x0023, 0x0000); system_delay(TFT_INIT_TIMEOUT); - tft_write_reg(0x0024,0x0000); + tft_write_reg(0x0024, 0x0000); system_delay(TFT_INIT_TIMEOUT); - tft_write_reg(0x0025,0x8000); + tft_write_reg(0x0025, 0x8000); system_delay(TFT_INIT_TIMEOUT); - tft_write_reg(0x004f,0x0000); + tft_write_reg(0x004f, 0x0000); system_delay(TFT_INIT_TIMEOUT); - tft_write_reg(0x004e,0x0000); + tft_write_reg(0x004e, 0x0000); system_delay(TFT_INIT_TIMEOUT); TFT_REG = TFT_SSD1289_REG_22; @@ -225,11 +252,11 @@ static bool fsmc_init() // generate init structures FSMC_NORSRAMInitTypeDef FSMC_NORSRAMInitStructure; FSMC_NORSRAMTimingInitTypeDef FSMC_NORSRAMTimingInitStructure; - - // clock enable - RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_FSMC, ENABLE); - - // prepare timing struct + + // clock enable + RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_FSMC, ENABLE); + + // prepare timing struct FSMC_NORSRAMTimingInitStructure.FSMC_AddressSetupTime = TFT_SSD1289_FSMC_AST; FSMC_NORSRAMTimingInitStructure.FSMC_AddressHoldTime = 1; FSMC_NORSRAMTimingInitStructure.FSMC_DataSetupTime = TFT_SSD1289_FSMC_DST; @@ -237,26 +264,26 @@ static bool fsmc_init() FSMC_NORSRAMTimingInitStructure.FSMC_CLKDivision = 0; FSMC_NORSRAMTimingInitStructure.FSMC_DataLatency = 0; FSMC_NORSRAMTimingInitStructure.FSMC_AccessMode = FSMC_AccessMode_A; - + // bank-1 / PSRAM-1 FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM1; FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable; FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_SRAM; FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b; FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable; - FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait = FSMC_AsynchronousWait_Disable; - FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low; - FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable; - FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState; - FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable; - FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable; - FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable; - FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable; - FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &FSMC_NORSRAMTimingInitStructure; + FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait = FSMC_AsynchronousWait_Disable; + FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low; + FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable; + FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState; + FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable; + FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable; + FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable; + FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable; + FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &FSMC_NORSRAMTimingInitStructure; FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &FSMC_NORSRAMTimingInitStructure; - + // config FSMC - FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure); + FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure); // enable Bank-1 / PSRAM-1 FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM1, ENABLE); @@ -269,19 +296,19 @@ static bool gpio_init() GPIO_InitTypeDef GPIO_InitStructure; // clock enable PORT_B, PORT_D, PORT_E - RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE); - RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD,ENABLE); - RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE,ENABLE); - - // PORT_B init - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE); + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE); + + // PORT_B init + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // configure PORT_B - GPIO_Init(GPIOB, &GPIO_InitStructure); - + GPIO_Init(GPIOB, &GPIO_InitStructure); + // PORT_D init GPIO_PinAFConfig(GPIOD, GPIO_PinSource0, GPIO_AF_FSMC); // PD0=FSMC_D2 -> DB2 GPIO_PinAFConfig(GPIOD, GPIO_PinSource1, GPIO_AF_FSMC); // PD1=FSMC_D3 -> DB3 @@ -290,25 +317,25 @@ static bool gpio_init() GPIO_PinAFConfig(GPIOD, GPIO_PinSource7, GPIO_AF_FSMC); // PD7=FSMC_NE1 -> CS GPIO_PinAFConfig(GPIOD, GPIO_PinSource8, GPIO_AF_FSMC); // PD8=FSMC_D13 -> DB15 GPIO_PinAFConfig(GPIOD, GPIO_PinSource9, GPIO_AF_FSMC); // PD9=FSMC_D14 -> DB16 - GPIO_PinAFConfig(GPIOD, GPIO_PinSource10, GPIO_AF_FSMC); // PD10=FSMC_D15 -> DB17 + GPIO_PinAFConfig(GPIOD, GPIO_PinSource10, GPIO_AF_FSMC); // PD10=FSMC_D15 -> DB17 GPIO_PinAFConfig(GPIOD, GPIO_PinSource14, GPIO_AF_FSMC); // PD14=FSMC_D0 -> DB0 GPIO_PinAFConfig(GPIOD, GPIO_PinSource15, GPIO_AF_FSMC); // PD15=FSMC_D1 -> DB1 // PORT_D struct GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5 | - GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | - GPIO_Pin_14 | GPIO_Pin_15; + GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | + GPIO_Pin_14 | GPIO_Pin_15; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; // configure PORT_D - GPIO_Init(GPIOD, &GPIO_InitStructure); - + GPIO_Init(GPIOD, &GPIO_InitStructure); + // PORT_E init GPIO_PinAFConfig(GPIOE, GPIO_PinSource3, GPIO_AF_FSMC); // PE3=FSMC_A19 -> RS GPIO_PinAFConfig(GPIOE, GPIO_PinSource7, GPIO_AF_FSMC); // PE7=FSMC_D4 -> DB4 - GPIO_PinAFConfig(GPIOE, GPIO_PinSource8, GPIO_AF_FSMC); // PE8=FSMC_D5 -> DB5 + GPIO_PinAFConfig(GPIOE, GPIO_PinSource8, GPIO_AF_FSMC); // PE8=FSMC_D5 -> DB5 GPIO_PinAFConfig(GPIOE, GPIO_PinSource9, GPIO_AF_FSMC); // PE9=FSMC_D6 -> DB6 GPIO_PinAFConfig(GPIOE, GPIO_PinSource10, GPIO_AF_FSMC); // PE10=FSMC_D7 -> DB7 GPIO_PinAFConfig(GPIOE, GPIO_PinSource11, GPIO_AF_FSMC); // PE11=FSMC_D8 -> DB10 @@ -316,17 +343,17 @@ static bool gpio_init() GPIO_PinAFConfig(GPIOE, GPIO_PinSource13, GPIO_AF_FSMC); // PE13=FSMC_D10 -> DB12 GPIO_PinAFConfig(GPIOE, GPIO_PinSource14, GPIO_AF_FSMC); // PE14=FSMC_D11 -> DB13 GPIO_PinAFConfig(GPIOE, GPIO_PinSource15, GPIO_AF_FSMC); // PE15=FSMC_D12 -> DB14 - + // PORT_E struct GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | - GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | - GPIO_Pin_14 | GPIO_Pin_15; + GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | + GPIO_Pin_14 | GPIO_Pin_15; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; - + // configure PORT_E GPIO_Init(GPIOE, &GPIO_InitStructure); @@ -338,14 +365,14 @@ static bool gpio_init() */ // Clear the whole screen by filling it with a specifig color -void ll_tft_clear(uint16_t color) +void ll_tft_clear(uint16_t color) { uint32_t n = 0; - + // set cursor to 0 - tft_set_cursor(0,0); - - for(n = 0; n < TFT_PIXEL; n++) { + tft_set_cursor(0, 0); + + for (n = 0; n < TFT_PIXEL; n++) { TFT_RAM = color; } } @@ -355,24 +382,24 @@ static void tft_set_cursor(uint16_t xpos, uint16_t ypos) { // set cursor tft_write_reg(TFT_SSD1289_REG_4E, ypos); - tft_write_reg(TFT_SSD1289_REG_4F, 319-xpos); + tft_write_reg(TFT_SSD1289_REG_4F, 319 - xpos); TFT_REG = TFT_SSD1289_REG_22; } // Enable / Disable the backlight -static void tft_set_backlight(bool state) +static void tft_set_backlight(bool state) { - if(state){ // if state is true + if (state) { // if state is true GPIOB->BSRRH = GPIO_Pin_0; // set the backlight output } else { // else - GPIOB->BSRRL = GPIO_Pin_0; // reset the backlight + GPIOB->BSRRL = GPIO_Pin_0; // reset the backlight } } // Port operations on the screen RS PIN -static void tft_reset(bool state) +static void tft_reset(bool state) { - if(state){ // if state is ture + if (state) { // if state is ture GPIOB->BSRRH = GPIO_Pin_0; // Set the reset pin } else { // else GPIOB->BSRRL = GPIO_Pin_0; // reset the reset pin @@ -396,16 +423,16 @@ static uint16_t tft_read_reg(uint8_t reg_adr) // This sets a window for current draw functions static void tft_set_window(uint16_t xstart, uint16_t ystart, uint16_t xend, uint16_t yend) { - uint16_t start,end; + uint16_t start, end; uint16_t ystart_end; start = (ystart & 0x00FF); // Start adress of the window end = ((yend & 0x00FF) << 8); // End adress of the window - ystart_end = (start | end); // Calculate y endpoint + ystart_end = (start | end); // Calculate y endpoint tft_write_reg(TFT_SSD1289_REG_44, ystart_end); // Send y size - tft_write_reg(TFT_SSD1289_REG_45, 319-xend); // Send x start - tft_write_reg(TFT_SSD1289_REG_46, 319-xstart); // Send x end + tft_write_reg(TFT_SSD1289_REG_45, 319 - xend); // Send x start + tft_write_reg(TFT_SSD1289_REG_46, 319 - xstart); // Send x end } // Reset a Window @@ -422,79 +449,64 @@ void tft_reset_window() */ // Draw a line on the given coordinates -void ll_tft_draw_line(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color) +void ll_tft_draw_line(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color) { - if(abs(x2-x1) > abs(y2-y1)) //line has more distance in x than y => iterate over x distance - { + if (abs(x2 - x1) > abs(y2 - y1)) { //line has more distance in x than y => iterate over x distance //Without floating point! - int deltax = ((int)x2-(int)x1); - int deltay = ((int)y2-(int)y1)<<1; + int deltax = ((int)x2 - (int)x1); + int deltay = ((int)y2 - (int)y1) << 1; int x = 0; - if (x1>x2) - { - do - { - tft_set_cursor(x1+x,y1+ (((long)deltay*(long)x/deltax+1)>>1)); + + if (x1 > x2) { + do { + tft_set_cursor(x1 + x, y1 + (((long)deltay * (long)x / deltax + 1) >> 1)); TFT_RAM = color; - } - while(x--!=deltax); + } while (x-- != deltax); + } else { + do { + tft_set_cursor(x1 + x, y1 + (((long)deltay * (long)x / deltax + 1) >> 1)); + TFT_RAM = color; + } while (x++ != deltax); } - else - { - do - { - tft_set_cursor(x1+x,y1+ (((long)deltay*(long)x/deltax+1)>>1)); + } else { // => iterate over y distance + int deltax = ((int)x2 - (int)x1) << 1; + int deltay = ((int)y2 - (int)y1); + int y = 0; + + if (y1 > y2) { + do { + tft_set_cursor(x1 + (((long)deltax * (long)y / deltay + 1) >> 1), y1 + y); TFT_RAM = color; - } - while(x++!=deltax); + } while (y-- != deltay); + } else { + do { + tft_set_cursor(x1 + (((long)deltax * (long)y / deltay + 1) >> 1), y1 + y); + TFT_RAM = color; + } while (y++ != deltay); } } - else // => iterate over y distance - { - int deltax = ((int)x2-(int)x1)<<1; - int deltay = ((int)y2-(int)y1); - int y = 0; - if (y1>y2) - { - do - { - tft_set_cursor(x1+ (((long)deltax*(long)y/deltay+1)>>1),y1+ y); - TFT_RAM = color; - } - while(y--!=deltay); - } - else - { - do - { - tft_set_cursor(x1+ (((long)deltax*(long)y/deltay+1)>>1),y1+ y); - TFT_RAM = color; - } - while(y++!=deltay); - } - } } // Draw a single pixel on (x,y) with the given color -void ll_tft_draw_pixel(uint16_t x,uint16_t y,uint16_t color) +void ll_tft_draw_pixel(uint16_t x, uint16_t y, uint16_t color) { - tft_set_cursor(x,y); // Set the cursor position + tft_set_cursor(x, y); // Set the cursor position TFT_RAM = color; // Draw the pixel } // Draw a rectangle at the given coordinates with the given color -void ll_tft_draw_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color) +void ll_tft_draw_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color) { unsigned int tmp; unsigned int i; - if(x1 > x2){ + if (x1 > x2) { tmp = x1; x1 = x2; x2 = tmp; } - if(y1 > y2){ + if (y1 > y2) { tmp = y1; y1 = y2; y2 = tmp; @@ -503,13 +515,20 @@ void ll_tft_draw_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, u i = x1; //Drawing the two horizontal lines tft_set_cursor(x1, y1); - while(i++ != x2) TFT_RAM = color; - tft_set_cursor(x1,y2); - while(i-- != x1) TFT_RAM = color; - - + + while (i++ != x2) { + TFT_RAM = color; + } + + tft_set_cursor(x1, y2); + + while (i-- != x1) { + TFT_RAM = color; + } + + /* - //uncommented because tft_write_reg seems to fail sometimes so it's safer to use draw line instead (below) + //uncommented because tft_write_reg seems to fail sometimes so it's safer to use draw line instead (below) i = y1; tft_write_reg(0x11,0x6030); // Change adresspointer direction tft_set_cursor(x2, y1); @@ -518,42 +537,42 @@ void ll_tft_draw_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, u while(i-- != y1) TFT_RAM = color; tft_write_reg(0x11,0x6018); // Set adresspointer direction normal again */ - tft_draw_line(x1,y1,x1,y2,color); - tft_draw_line(x2,y1,x2,y2,color); - + tft_draw_line(x1, y1, x1, y2, color); + tft_draw_line(x2, y1, x2, y2, color); + } // Draw a filled rectangle at the given coordinates with the given color -void ll_tft_fill_rectangle(uint16_t x1,uint16_t y1,uint16_t x2,uint16_t y2, uint16_t color) +void ll_tft_fill_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color) { uint16_t area; uint32_t n; unsigned int tmp; - if(x1 > x2){ + if (x1 > x2) { tmp = x1; x1 = x2; x2 = tmp; } - if(y1 > y2){ + if (y1 > y2) { tmp = y1; y1 = y2; y2 = tmp; - } + } - // set window + // set window tft_set_window(x1, y1, x2, y2); tft_set_cursor(x1, y1); // calculate area - area = (x2 - x1 + 1) * (y2 - y1 + 1); + area = (x2 - x1 + 1) * (y2 - y1 + 1); // fill area - for(n = 0; n < area; n++) { + for (n = 0; n < area; n++) { TFT_RAM = color; } - + tft_reset_window(); } @@ -571,77 +590,82 @@ void ll_tft_draw_circle(uint16_t x, uint16_t y, uint16_t r, uint16_t color) * ---------------------- font functions ----------------------------------------------------------- */ -static const char *get_font(uint8_t font) +static const char* get_font(uint8_t font) { - switch(font){ - case 0: return small_font; - case 1: return big_font; - case 2: return seven_seg_num_font; + switch (font) { + case 0: + return small_font; + + case 1: + return big_font; + + case 2: + return seven_seg_num_font; } } -uint8_t ll_tft_num_fonts() +uint8_t ll_tft_num_fonts() { - return 3; + return 3; } -uint8_t ll_tft_font_height(uint8_t fontnum) +uint8_t ll_tft_font_height(uint8_t fontnum) { - const char *font = get_font(fontnum); + const char* font = get_font(fontnum); return (uint8_t) font[1]; } -uint8_t ll_tft_font_width(uint8_t fontnum) +uint8_t ll_tft_font_width(uint8_t fontnum) { - const char *font = get_font(fontnum); + const char* font = get_font(fontnum); return (uint8_t) font[0]; } -void ll_tft_draw_char(uint16_t x, uint16_t y, uint16_t color, uint16_t bgcolor, uint8_t fontnum, char c) +void ll_tft_draw_char(uint16_t x, uint16_t y, uint16_t color, uint16_t bgcolor, uint8_t fontnum, char c) { - const char *font = get_font(fontnum); + const char* font = get_font(fontnum); unsigned char width = (uint8_t) font[0]; unsigned char height = (uint8_t) font[1]; unsigned char offset = (uint8_t) font[2]; - unsigned int ind = ((c-offset) * ((width / 8) * height)) + 4; + unsigned int ind = ((c - offset) * ((width / 8) * height)) + 4; unsigned int cnt = 0; unsigned char bitm = 0; bool bgIsTrans = (bgcolor == TRANSPARENT); - unsigned char xadd=0; - unsigned char yadd=0; + unsigned char xadd = 0; + unsigned char yadd = 0; tft_set_window(x, y, x + width - 1, y + height - 1); - tft_set_cursor(x, y); - - for(cnt = (width / 8) * height; cnt > 0; cnt--){ - for(bitm = 0x80; bitm > 0; bitm >>= 1){ - if((font[ind]) & bitm){ - if(bgIsTrans) { - tft_set_cursor(x+xadd,y+yadd); + tft_set_cursor(x, y); + + for (cnt = (width / 8) * height; cnt > 0; cnt--) { + for (bitm = 0x80; bitm > 0; bitm >>= 1) { + if ((font[ind]) & bitm) { + if (bgIsTrans) { + tft_set_cursor(x + xadd, y + yadd); } + TFT_RAM = color; - + } else { - if(!bgIsTrans) { + if (!bgIsTrans) { TFT_RAM = bgcolor; - } + } + } + + if (bgIsTrans) { + xadd++; + + if (xadd == width) { + xadd = 0; + yadd++; + } } - - if(bgIsTrans) - { - xadd++; - if(xadd==width) - { - xadd=0; - yadd++; - } - } } - + ind++; } - + tft_reset_window(); } diff --git a/discovery/src/ll_touch.c b/discovery/src/ll_touch.c index 7d5d21a..9370d24 100644 --- a/discovery/src/ll_touch.c +++ b/discovery/src/ll_touch.c @@ -1,3 +1,28 @@ +/************************************************************************************************************************************** +* Project: discoverpixy +* Website: https://github.com/t-moe/discoverpixy +* Authors: Aaron Schmocker, Timo Lang +* Institution: BFH Bern University of Applied Sciences +* File: discovery/src/ll_touch.c +* +* Version History: +* Date Autor Email SHA Changes +* 2015-04-27 timolang@gmail.com 259d446 Added touch support to emulator. Implemented basic touch function. +* 2015-05-12 aaron@duckpond.ch 3b2ef30 Added PID source code and Pinmap +* 2015-05-12 aaron@duckpond.ch 5e374f4 Added datasheet and touch template +* 2015-05-12 aaron@duckpond.ch aec62d4 Added datasheets, updated touchsupport. +* 2015-05-13 aaron@duckpond.ch 1396d24 Working touchcontroller communication +* 2015-05-28 aaron@duckpond.ch 5bda699 implemented functions to get x and y coordinates and a test function +* 2015-05-28 aaron@duckpond.ch 9b1020c Working PENIRQ +* 2015-05-28 aaron@duckpond.ch 30197bf recent changes +* 2015-05-29 aaron@duckpond.ch 7d2d1a1 Implemented basic sampling and averaging of touch coordinates using timer7 +* 2015-06-01 aaron@duckpond.ch dff2e76 Touch recognition working +* 2015-06-01 aaron@duckpond.ch caa7b5c Added IRQ for user button, fixed some touchproblems. +* 2015-06-01 timolang@gmail.com eb573bc Finalized calibration. Fixed a bug in screen module. +* 2015-06-03 timolang@gmail.com 74aa186 Made pixy_test screen working again. Had to disable pixy_service. Recalibrated initial touch values. +* +**************************************************************************************************************************************/ + #include "ll_touch.h" #include "screen.h" #include "screen_calibrate.h" @@ -22,8 +47,8 @@ /* Globals ----------------------------------------------------------- */ volatile bool pen_state = false; // PenDown = True; PenUp = False; volatile bool tim_flag = false; -volatile uint16_t x_samples[NSAMPLE-1]; -volatile uint16_t y_samples[NSAMPLE-1]; +volatile uint16_t x_samples[NSAMPLE - 1]; +volatile uint16_t y_samples[NSAMPLE - 1]; volatile int i; /* Prototypes -------------------------------------------------------- */ @@ -42,11 +67,11 @@ static uint16_t avg_vals(volatile uint16_t samples[], uint16_t len) uint16_t j = 0; uint32_t tmp = 0; - for(j = 0; j < len; j++){ - tmp += samples[j]; + for (j = 0; j < len; j++) { + tmp += samples[j]; } - return (uint16_t)(tmp/len); + return (uint16_t)(tmp / len); } static uint16_t touch_get_x_coord() @@ -54,8 +79,8 @@ static uint16_t touch_get_x_coord() uint16_t buf_x = 0; CLEAR_CS; // clear chipselect touch_send(REQ_X_COORD); // request x coordinate - - buf_x = ((uint16_t) touch_send(REQ_1_DATAB)) << 5; + + buf_x = ((uint16_t) touch_send(REQ_1_DATAB)) << 5; buf_x |= touch_send(REQ_1_DATAB) >> 3; SET_CS; // set chipselect @@ -69,7 +94,7 @@ static uint16_t touch_get_y_coord() CLEAR_CS; // clear chipselect touch_send(REQ_Y_COORD); // request y coordinate - + buf_y = ((uint16_t) touch_send(REQ_1_DATAB)) << 5; buf_y |= touch_send(REQ_1_DATAB) >> 3; @@ -80,10 +105,13 @@ static uint16_t touch_get_y_coord() static uint8_t touch_send(uint8_t dat) { - SPI_I2S_SendData(SPI2, dat); - while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY) != RESET); - while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET); - return SPI_I2S_ReceiveData(SPI2); + SPI_I2S_SendData(SPI2, dat); + + while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY) != RESET); + + while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET); + + return SPI_I2S_ReceiveData(SPI2); } void touch_test(uint16_t x, uint16_t y) @@ -100,12 +128,12 @@ void touch_test(uint16_t x, uint16_t y) tft_print_line(10, 30, WHITE, TRANSPARENT, 0, (const char*)ys); } -bool ll_touch_init() +bool ll_touch_init() { touch_set_value_convert_mode(true); //Tell the touch module that we need converted values and display calibration touch_set_calibration_values(526, 2922, 588, 2736); //set calibration values (copied from memory using the debugger) - - + + //We have a ADS7843 Touch controller //Datasheet: http://www.ti.com/lit/ds/symlink/ads7843.pdf @@ -124,13 +152,13 @@ bool ll_touch_init() GPIO_SPI2_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_SPI2_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOB, &GPIO_SPI2_InitStructure); - + SET_CS; // set chip select /* fill gpio init struct and init gpio */ GPIO_StructInit(&GPIO_SPI2_InitStructure); GPIO_SPI2_InitStructure.GPIO_Pin = GPIO_Pin_9; // 9 = SPI2_CS - GPIO_SPI2_InitStructure.GPIO_Mode = GPIO_Mode_OUT; + GPIO_SPI2_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_SPI2_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_SPI2_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_SPI2_InitStructure); @@ -139,7 +167,7 @@ bool ll_touch_init() GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_SPI2); GPIO_PinAFConfig(GPIOB, GPIO_PinSource14, GPIO_AF_SPI2); GPIO_PinAFConfig(GPIOB, GPIO_PinSource15, GPIO_AF_SPI2); - + SPI_I2S_DeInit(SPI2); // Clear spi initialisation /* fill spi init structure */ @@ -184,9 +212,9 @@ static void init_exti() gpio.GPIO_PuPd = GPIO_PuPd_UP; gpio.GPIO_Speed = GPIO_Speed_100MHz; GPIO_Init(GPIOC, &gpio); - + SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC, EXTI_PinSource1); // Bind Exti_line1 to PC1 - + /* Set GPIOA0 as input */ gpio.GPIO_Mode = GPIO_Mode_IN; gpio.GPIO_OType = GPIO_OType_OD; @@ -201,10 +229,10 @@ static void init_exti() EXTI_StructInit(&exti); exti.EXTI_Line = EXTI_Line1; exti.EXTI_Mode = EXTI_Mode_Interrupt; - exti.EXTI_Trigger = EXTI_Trigger_Falling; // Trigger on falling edge (PENIRQ) + exti.EXTI_Trigger = EXTI_Trigger_Falling; // Trigger on falling edge (PENIRQ) exti.EXTI_LineCmd = ENABLE; EXTI_Init(&exti); - + /* EXTI on PA0 */ EXTI_StructInit(&exti); exti.EXTI_Line = EXTI_Line0; @@ -219,7 +247,7 @@ static void init_exti() nvic.NVIC_IRQChannelSubPriority = 0x00; // Set sub priority nvic.NVIC_IRQChannelCmd = ENABLE; // Enable interrupt NVIC_Init(&nvic); // Config NVIC - + /* Add IRQ vector to NVIC */ nvic.NVIC_IRQChannel = EXTI0_IRQn; // PA0 -> EXTI_Line0 -> EXTI0_IRQn vector nvic.NVIC_IRQChannelPreemptionPriority = 0x00; // Set priority @@ -232,7 +260,7 @@ static void init_timer() { TIM_TimeBaseInitTypeDef t; const int APB1_CLK = 42E6; - + RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7, ENABLE); // Enable clock for TIM6 /* Timer 7 configuration */ @@ -263,16 +291,16 @@ void EXTI1_IRQHandler() void TIM7_IRQHandler() { - if(TIM_GetFlagStatus(TIM7, TIM_IT_Update) == SET){ // Make sure the interrupt flag is set - + if (TIM_GetFlagStatus(TIM7, TIM_IT_Update) == SET) { // Make sure the interrupt flag is set + TIM_Cmd(TIM7, DISABLE); // Disable the timer during the measuring - if(PENIRQ){ // Only do this if the PENIRQ line is still low - for(i = 0; i < (NSAMPLE-1); i++){ // Sample 16 times + if (PENIRQ) { // Only do this if the PENIRQ line is still low + for (i = 0; i < (NSAMPLE - 1); i++) { // Sample 16 times x_samples[i] = touch_get_x_coord(); y_samples[i] = touch_get_y_coord(); } - + touch_add_raw_event(avg_vals(x_samples, NSAMPLE), avg_vals(y_samples, NSAMPLE), TOUCH_DOWN); // Update position //tft_draw_pixel(avg_vals(x_samples, NSAMPLE), avg_vals(y_samples, NSAMPLE), RED); TIM_Cmd(TIM7, ENABLE); // Reenable timer @@ -281,8 +309,8 @@ void TIM7_IRQHandler() touch_add_raw_event(avg_vals(x_samples, NSAMPLE), avg_vals(y_samples, NSAMPLE), TOUCH_UP); // Update position one last time //tft_draw_pixel(avg_vals(x_samples, NSAMPLE), avg_vals(y_samples, NSAMPLE), RED); TIM_Cmd(TIM7, DISABLE); // Disable timer - } + } TIM_ClearFlag(TIM7, TIM_IT_Update); // Clear timer interrupt flag - } + } } diff --git a/discovery/src/main.c b/discovery/src/main.c index 4429e45..98ada12 100644 --- a/discovery/src/main.c +++ b/discovery/src/main.c @@ -1,12 +1,27 @@ -#include "app.h" - -int main(void) -{ - app_init(); - - while (1) - { - app_process(); - } - -} +/************************************************************************************************************************************** +* Project: discoverpixy +* Website: https://github.com/t-moe/discoverpixy +* Authors: Aaron Schmocker, Timo Lang +* Institution: BFH Bern University of Applied Sciences +* File: discovery/src/main.c +* +* Version History: +* Date Autor Email SHA Changes +* 2015-04-03 timolang@gmail.com 21dd1e2 Starting to integrate usb branch. Optimized Makefiles +* 2015-04-03 timolang@gmail.com 9a1d12a Refactored discovery, to use new project structure. Almost ready. +* 2015-04-25 timolang@gmail.com 416883c Pixy&Usb work with the new folder structure now. +* 2015-04-25 timolang@gmail.com 3d1e4b2 Simplified code a bit. Emulator does not work stable when replugging pixy. +* +**************************************************************************************************************************************/ + +#include "app.h" + +int main(void) +{ + app_init(); + + while (1) { + app_process(); + } + +} diff --git a/discovery/src/newlib_stubs.c b/discovery/src/newlib_stubs.c index a936be2..b46cb47 100644 --- a/discovery/src/newlib_stubs.c +++ b/discovery/src/newlib_stubs.c @@ -1,3 +1,16 @@ +/************************************************************************************************************************************** +* Project: discoverpixy +* Website: https://github.com/t-moe/discoverpixy +* Authors: Aaron Schmocker, Timo Lang +* Institution: BFH Bern University of Applied Sciences +* File: discovery/src/newlib_stubs.c +* +* Version History: +* Date Autor Email SHA Changes +* 2015-04-03 timolang@gmail.com 21dd1e2 Starting to integrate usb branch. Optimized Makefiles +* +**************************************************************************************************************************************/ + /* * newlib_stubs.c * @@ -32,26 +45,30 @@ extern int errno; A pointer to a list of environment variables and their values. For a minimal environment, this empty list is adequate: */ -char *__env[1] = { 0 }; -char **environ = __env; +char* __env[1] = { 0 }; +char** environ = __env; -int _write(int file, char *ptr, int len); +int _write(int file, char* ptr, int len); -void _exit(int status) { +void _exit(int status) +{ _write(1, "exit", 4); + while (1) { ; } } -int _close(int file) { +int _close(int file) +{ return -1; } /* execve Transfer control to a new process. Minimal implementation (for a system without processes): */ -int _execve(char *name, char **argv, char **env) { +int _execve(char* name, char** argv, char** env) +{ errno = ENOMEM; return -1; } @@ -60,7 +77,8 @@ int _execve(char *name, char **argv, char **env) { Create a new process. Minimal implementation (for a system without processes): */ -int _fork() { +int _fork() +{ errno = EAGAIN; return -1; } @@ -70,7 +88,8 @@ int _fork() { all files are regarded as character special devices. The `sys/stat.h' header file required is distributed in the `include' subdirectory for this C library. */ -int _fstat(int file, struct stat *st) { +int _fstat(int file, struct stat* st) +{ st->st_mode = S_IFCHR; return 0; } @@ -80,7 +99,8 @@ int _fstat(int file, struct stat *st) { Process-ID; this is sometimes used to generate strings unlikely to conflict with other processes. Minimal implementation, for a system without processes: */ -int _getpid() { +int _getpid() +{ return 1; } @@ -88,12 +108,14 @@ int _getpid() { isatty Query whether output stream is a terminal. For consistency with the other minimal implementations, */ -int _isatty(int file) { - switch (file){ +int _isatty(int file) +{ + switch (file) { case STDOUT_FILENO: case STDERR_FILENO: case STDIN_FILENO: return 1; + default: //errno = ENOTTY; errno = EBADF; @@ -106,7 +128,8 @@ int _isatty(int file) { kill Send a signal. Minimal implementation: */ -int _kill(int pid, int sig) { +int _kill(int pid, int sig) +{ errno = EINVAL; return (-1); } @@ -116,7 +139,8 @@ int _kill(int pid, int sig) { Establish a new name for an existing file. Minimal implementation: */ -int _link(char *old, char *new) { +int _link(char* old, char* new) +{ errno = EMLINK; return -1; } @@ -125,7 +149,8 @@ int _link(char *old, char *new) { lseek Set position in a file. Minimal implementation: */ -int _lseek(int file, int ptr, int dir) { +int _lseek(int file, int ptr, int dir) +{ return 0; } @@ -134,25 +159,27 @@ int _lseek(int file, int ptr, int dir) { Increase program data space. Malloc and related functions depend on this */ -caddr_t _sbrk(int incr) { +caddr_t _sbrk(int incr) +{ extern char _ebss; // Defined by the linker - static char *heap_end; - char *prev_heap_end; + static char* heap_end; + char* prev_heap_end; if (heap_end == 0) { heap_end = &_ebss; } + prev_heap_end = heap_end; -char * stack = (char*) __get_MSP(); - if (heap_end + incr > stack) - { - _write (STDERR_FILENO, "Heap and stack collision\n", 25); - errno = ENOMEM; - return (caddr_t) -1; - //abort (); - } + char* stack = (char*) __get_MSP(); + + if (heap_end + incr > stack) { + _write(STDERR_FILENO, "Heap and stack collision\n", 25); + errno = ENOMEM; + return (caddr_t) - 1; + //abort (); + } heap_end += incr; return (caddr_t) prev_heap_end; @@ -161,10 +188,10 @@ char * stack = (char*) __get_MSP(); -int _open(char *path, int flags, ...) +int _open(char* path, int flags, ...) { - /* Pretend like we always fail */ - return -1; + /* Pretend like we always fail */ + return -1; } /* @@ -174,30 +201,33 @@ int _open(char *path, int flags, ...) */ -int _read(int file, char *ptr, int len) { +int _read(int file, char* ptr, int len) +{ int n; int num = 0; + switch (file) { - /*case STDIN_FILENO: - for (n = 0; n < len; n++) { -#if STDIN_USART == 1 - while ((USART1->SR & USART_FLAG_RXNE) == (uint16_t)RESET) {} - char c = (char)(USART1->DR & (uint16_t)0x01FF); -#elif STDIN_USART == 2 - while ((USART2->SR & USART_FLAG_RXNE) == (uint16_t) RESET) {} - char c = (char) (USART2->DR & (uint16_t) 0x01FF); -#elif STDIN_USART == 3 - while ((USART3->SR & USART_FLAG_RXNE) == (uint16_t)RESET) {} - char c = (char)(USART3->DR & (uint16_t)0x01FF); -#endif - *ptr++ = c; - num++; - } - break; - default:*/ + /*case STDIN_FILENO: + for (n = 0; n < len; n++) { + #if STDIN_USART == 1 + while ((USART1->SR & USART_FLAG_RXNE) == (uint16_t)RESET) {} + char c = (char)(USART1->DR & (uint16_t)0x01FF); + #elif STDIN_USART == 2 + while ((USART2->SR & USART_FLAG_RXNE) == (uint16_t) RESET) {} + char c = (char) (USART2->DR & (uint16_t) 0x01FF); + #elif STDIN_USART == 3 + while ((USART3->SR & USART_FLAG_RXNE) == (uint16_t)RESET) {} + char c = (char)(USART3->DR & (uint16_t)0x01FF); + #endif + *ptr++ = c; + num++; + } + break; + default:*/ errno = EBADF; return -1; } + return num; } @@ -207,7 +237,8 @@ int _read(int file, char *ptr, int len) { int _EXFUN(stat,( const char *__path, struct stat *__sbuf )); */ -int _stat(const char *filepath, struct stat *st) { +int _stat(const char* filepath, struct stat* st) +{ st->st_mode = S_IFCHR; return 0; } @@ -217,7 +248,8 @@ int _stat(const char *filepath, struct stat *st) { Timing information for current process. Minimal implementation: */ -clock_t _times(struct tms *buf) { +clock_t _times(struct tms* buf) +{ return -1; } @@ -225,7 +257,8 @@ clock_t _times(struct tms *buf) { unlink Remove a file's directory entry. Minimal implementation: */ -int _unlink(char *name) { +int _unlink(char* name) +{ errno = ENOENT; return -1; } @@ -234,7 +267,8 @@ int _unlink(char *name) { wait Wait for a child process. Minimal implementation: */ -int _wait(int *status) { +int _wait(int* status) +{ errno = ECHILD; return -1; } @@ -244,42 +278,61 @@ int _wait(int *status) { Write a character to a file. `libc' subroutines will use this system routine for output to all files, including stdout Returns -1 on error or number of bytes sent */ -int _write(int file, char *ptr, int len) { +int _write(int file, char* ptr, int len) +{ int n; + switch (file) { case STDOUT_FILENO: /*stdout*/ for (n = 0; n < len; n++) { #if STDOUT_USART == 1 + while ((USART1->SR & USART_FLAG_TC) == (uint16_t)RESET) {} + USART1->DR = (*ptr++ & (uint16_t)0x01FF); #elif STDOUT_USART == 2 + while ((USART2->SR & USART_FLAG_TC) == (uint16_t) RESET) { } + USART2->DR = (*ptr++ & (uint16_t) 0x01FF); #elif STDOUT_USART == 3 + while ((USART3->SR & USART_FLAG_TC) == (uint16_t)RESET) {} + USART3->DR = (*ptr++ & (uint16_t)0x01FF); #endif } + break; + case STDERR_FILENO: /* stderr */ for (n = 0; n < len; n++) { #if STDERR_USART == 1 + while ((USART1->SR & USART_FLAG_TC) == (uint16_t)RESET) {} + USART1->DR = (*ptr++ & (uint16_t)0x01FF); #elif STDERR_USART == 2 + while ((USART2->SR & USART_FLAG_TC) == (uint16_t) RESET) { } + USART2->DR = (*ptr++ & (uint16_t) 0x01FF); #elif STDERR_USART == 3 + while ((USART3->SR & USART_FLAG_TC) == (uint16_t)RESET) {} + USART3->DR = (*ptr++ & (uint16_t)0x01FF); #endif } + break; + default: errno = EBADF; return -1; } + return len; } diff --git a/discovery/src/system_stm32f4xx.c b/discovery/src/system_stm32f4xx.c index 429d56b..6520543 100644 --- a/discovery/src/system_stm32f4xx.c +++ b/discovery/src/system_stm32f4xx.c @@ -1,545 +1,551 @@ -/** - ****************************************************************************** - * @file system_stm32f4xx.c - * @author MCD Application Team - * @version V1.0.0 - * @date 19-September-2011 - * @brief CMSIS Cortex-M4 Device Peripheral Access Layer System Source File. - * This file contains the system clock configuration for STM32F4xx devices, - * and is generated by the clock configuration tool - * stm32f4xx_Clock_Configuration_V1.0.0.xls - * - * 1. This file provides two functions and one global variable to be called from - * user application: - * - SystemInit(): Setups the system clock (System clock source, PLL Multiplier - * and Divider factors, AHB/APBx prescalers and Flash settings), - * depending on the configuration made in the clock xls tool. - * This function is called at startup just after reset and - * before branch to main program. This call is made inside - * the "startup_stm32f4xx.s" file. - * - * - SystemCoreClock variable: Contains the core clock (HCLK), it can be used - * by the user application to setup the SysTick - * timer or configure other parameters. - * - * - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must - * be called whenever the core clock is changed - * during program execution. - * - * 2. After each device reset the HSI (16 MHz) is used as system clock source. - * Then SystemInit() function is called, in "startup_stm32f4xx.s" file, to - * configure the system clock before to branch to main program. - * - * 3. If the system clock source selected by user fails to startup, the SystemInit() - * function will do nothing and HSI still used as system clock source. User can - * add some code to deal with this issue inside the SetSysClock() function. - * - * 4. The default value of HSE crystal is set to 8 MHz, refer to "HSE_VALUE" define - * in "stm32f4xx.h" file. When HSE is used as system clock source, directly or - * through PLL, and you are using different crystal you have to adapt the HSE - * value to your own configuration. - * - * 5. This file configures the system clock as follows: - *============================================================================= - *============================================================================= - * Supported STM32F4xx device revision | Rev A - *----------------------------------------------------------------------------- - * System Clock source | PLL (HSE) - *----------------------------------------------------------------------------- - * SYSCLK(Hz) | 168000000 - *----------------------------------------------------------------------------- - * HCLK(Hz) | 168000000 - *----------------------------------------------------------------------------- - * AHB Prescaler | 1 - *----------------------------------------------------------------------------- - * APB1 Prescaler | 4 - *----------------------------------------------------------------------------- - * APB2 Prescaler | 2 - *----------------------------------------------------------------------------- - * HSE Frequency(Hz) | 8000000 - *----------------------------------------------------------------------------- - * PLL_M | 8 - *----------------------------------------------------------------------------- - * PLL_N | 336 - *----------------------------------------------------------------------------- - * PLL_P | 2 - *----------------------------------------------------------------------------- - * PLL_Q | 7 - *----------------------------------------------------------------------------- - * PLLI2S_N | NA - *----------------------------------------------------------------------------- - * PLLI2S_R | NA - *----------------------------------------------------------------------------- - * I2S input clock | NA - *----------------------------------------------------------------------------- - * VDD(V) | 3.3 - *----------------------------------------------------------------------------- - * High Performance mode | Enabled - *----------------------------------------------------------------------------- - * Flash Latency(WS) | 5 - *----------------------------------------------------------------------------- - * Prefetch Buffer | OFF - *----------------------------------------------------------------------------- - * Instruction cache | ON - *----------------------------------------------------------------------------- - * Data cache | ON - *----------------------------------------------------------------------------- - * Require 48MHz for USB OTG FS, | Enabled - * SDIO and RNG clock | - *----------------------------------------------------------------------------- - *============================================================================= - ****************************************************************************** - * @attention - * - * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS - * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE - * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY - * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING - * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE - * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. - * - *

© COPYRIGHT 2011 STMicroelectronics

- ****************************************************************************** - */ - -/** @addtogroup CMSIS - * @{ - */ - -/** @addtogroup stm32f4xx_system - * @{ - */ - -/** @addtogroup STM32F4xx_System_Private_Includes - * @{ - */ - -#include "stm32f4xx.h" - -/** - * @} - */ - -/** @addtogroup STM32F4xx_System_Private_TypesDefinitions - * @{ - */ - -/** - * @} - */ - -/** @addtogroup STM32F4xx_System_Private_Defines - * @{ - */ - -/*!< Uncomment the following line if you need to use external SRAM mounted - on STM324xG_EVAL board as data memory */ -/* #define DATA_IN_ExtSRAM */ - -/*!< Uncomment the following line if you need to relocate your vector Table in - Internal SRAM. */ -/* #define VECT_TAB_SRAM */ -#define VECT_TAB_OFFSET 0x00 /*!< Vector Table base offset field. - This value must be a multiple of 0x200. */ - - -/* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N */ -#define PLL_M 8 -#define PLL_N 336 - -/* SYSCLK = PLL_VCO / PLL_P */ -#define PLL_P 2 - -/* USB OTG FS, SDIO and RNG Clock = PLL_VCO / PLLQ */ -#define PLL_Q 7 - -/** - * @} - */ - -/** @addtogroup STM32F4xx_System_Private_Macros - * @{ - */ - -/** - * @} - */ - -/** @addtogroup STM32F4xx_System_Private_Variables - * @{ - */ - - uint32_t SystemCoreClock = 168000000; - - __I uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; - -/** - * @} - */ - -/** @addtogroup STM32F4xx_System_Private_FunctionPrototypes - * @{ - */ - -static void SetSysClock(void); -#ifdef DATA_IN_ExtSRAM - static void SystemInit_ExtMemCtl(void); -#endif /* DATA_IN_ExtSRAM */ - -/** - * @} - */ - -/** @addtogroup STM32F4xx_System_Private_Functions - * @{ - */ - -/** - * @brief Setup the microcontroller system - * Initialize the Embedded Flash Interface, the PLL and update the - * SystemFrequency variable. - * @param None - * @retval None - */ -void SystemInit(void) -{ - /* Reset the RCC clock configuration to the default reset state ------------*/ - /* Set HSION bit */ - RCC->CR |= (uint32_t)0x00000001; - - /* Reset CFGR register */ - RCC->CFGR = 0x00000000; - - /* Reset HSEON, CSSON and PLLON bits */ - RCC->CR &= (uint32_t)0xFEF6FFFF; - - /* Reset PLLCFGR register */ - RCC->PLLCFGR = 0x24003010; - - /* Reset HSEBYP bit */ - RCC->CR &= (uint32_t)0xFFFBFFFF; - - /* Disable all interrupts */ - RCC->CIR = 0x00000000; - -#ifdef DATA_IN_ExtSRAM - SystemInit_ExtMemCtl(); -#endif /* DATA_IN_ExtSRAM */ - - /* Configure the System clock source, PLL Multiplier and Divider factors, - AHB/APBx prescalers and Flash settings ----------------------------------*/ - SetSysClock(); - - /* Configure the Vector Table location add offset address ------------------*/ -#ifdef VECT_TAB_SRAM - SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */ -#else - SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */ -#endif -} - -/** - * @brief Update SystemCoreClock variable according to Clock Register Values. - * The SystemCoreClock variable contains the core clock (HCLK), it can - * be used by the user application to setup the SysTick timer or configure - * other parameters. - * - * @note Each time the core clock (HCLK) changes, this function must be called - * to update SystemCoreClock variable value. Otherwise, any configuration - * based on this variable will be incorrect. - * - * @note - The system frequency computed by this function is not the real - * frequency in the chip. It is calculated based on the predefined - * constant and the selected clock source: - * - * - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*) - * - * - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(**) - * - * - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**) - * or HSI_VALUE(*) multiplied/divided by the PLL factors. - * - * (*) HSI_VALUE is a constant defined in stm32f4xx.h file (default value - * 16 MHz) but the real value may vary depending on the variations - * in voltage and temperature. - * - * (**) HSE_VALUE is a constant defined in stm32f4xx.h file (default value - * 25 MHz), user has to ensure that HSE_VALUE is same as the real - * frequency of the crystal used. Otherwise, this function may - * have wrong result. - * - * - The result of this function could be not correct when using fractional - * value for HSE crystal. - * - * @param None - * @retval None - */ -void SystemCoreClockUpdate(void) -{ - uint32_t tmp = 0, pllvco = 0, pllp = 2, pllsource = 0, pllm = 2; - - /* Get SYSCLK source -------------------------------------------------------*/ - tmp = RCC->CFGR & RCC_CFGR_SWS; - - switch (tmp) - { - case 0x00: /* HSI used as system clock source */ - SystemCoreClock = HSI_VALUE; - break; - case 0x04: /* HSE used as system clock source */ - SystemCoreClock = HSE_VALUE; - break; - case 0x08: /* PLL used as system clock source */ - - /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N - SYSCLK = PLL_VCO / PLL_P - */ - pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) >> 22; - pllm = RCC->PLLCFGR & RCC_PLLCFGR_PLLM; - - if (pllsource != 0) - { - /* HSE used as PLL clock source */ - pllvco = (HSE_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6); - } - else - { - /* HSI used as PLL clock source */ - pllvco = (HSI_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6); - } - - pllp = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLP) >>16) + 1 ) *2; - SystemCoreClock = pllvco/pllp; - break; - default: - SystemCoreClock = HSI_VALUE; - break; - } - /* Compute HCLK frequency --------------------------------------------------*/ - /* Get HCLK prescaler */ - tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)]; - /* HCLK frequency */ - SystemCoreClock >>= tmp; -} - -/** - * @brief Configures the System clock source, PLL Multiplier and Divider factors, - * AHB/APBx prescalers and Flash settings - * @Note This function should be called only once the RCC clock configuration - * is reset to the default reset state (done in SystemInit() function). - * @param None - * @retval None - */ -static void SetSysClock(void) -{ -/******************************************************************************/ -/* PLL (clocked by HSE) used as System clock source */ -/******************************************************************************/ - __IO uint32_t StartUpCounter = 0, HSEStatus = 0; - - /* Enable HSE */ - RCC->CR |= ((uint32_t)RCC_CR_HSEON); - - /* Wait till HSE is ready and if Time out is reached exit */ - do - { - HSEStatus = RCC->CR & RCC_CR_HSERDY; - StartUpCounter++; - } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT)); - - if ((RCC->CR & RCC_CR_HSERDY) != RESET) - { - HSEStatus = (uint32_t)0x01; - } - else - { - HSEStatus = (uint32_t)0x00; - } - - if (HSEStatus == (uint32_t)0x01) - { - /* Enable high performance mode, System frequency up to 168 MHz */ - RCC->APB1ENR |= RCC_APB1ENR_PWREN; - PWR->CR |= PWR_CR_PMODE; - - /* HCLK = SYSCLK / 1*/ - RCC->CFGR |= RCC_CFGR_HPRE_DIV1; - - /* PCLK2 = HCLK / 2*/ - RCC->CFGR |= RCC_CFGR_PPRE2_DIV2; - - /* PCLK1 = HCLK / 4*/ - RCC->CFGR |= RCC_CFGR_PPRE1_DIV4; - - /* Configure the main PLL */ - RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) | - (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24); - - /* Enable the main PLL */ - RCC->CR |= RCC_CR_PLLON; - - /* Wait till the main PLL is ready */ - while((RCC->CR & RCC_CR_PLLRDY) == 0) - { - } - - /* Configure Flash prefetch, Instruction cache, Data cache and wait state */ - FLASH->ACR = FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS; - - /* Select the main PLL as system clock source */ - RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW)); - RCC->CFGR |= RCC_CFGR_SW_PLL; - - /* Wait till the main PLL is used as system clock source */ - while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL); - { - } - } - else - { /* If HSE fails to start-up, the application will have wrong clock - configuration. User can add here some code to deal with this error */ - } - -} - -/** - * @brief Setup the external memory controller. Called in startup_stm32f4xx.s - * before jump to __main - * @param None - * @retval None - */ -#ifdef DATA_IN_ExtSRAM -/** - * @brief Setup the external memory controller. - * Called in startup_stm32f4xx.s before jump to main. - * This function configures the external SRAM mounted on STM324xG_EVAL board - * This SRAM will be used as program data memory (including heap and stack). - * @param None - * @retval None - */ -void SystemInit_ExtMemCtl(void) -{ -/*-- GPIOs Configuration -----------------------------------------------------*/ -/* - +-------------------+--------------------+------------------+------------------+ - + SRAM pins assignment + - +-------------------+--------------------+------------------+------------------+ - | PD0 <-> FSMC_D2 | PE0 <-> FSMC_NBL0 | PF0 <-> FSMC_A0 | PG0 <-> FSMC_A10 | - | PD1 <-> FSMC_D3 | PE1 <-> FSMC_NBL1 | PF1 <-> FSMC_A1 | PG1 <-> FSMC_A11 | - | PD4 <-> FSMC_NOE | PE3 <-> FSMC_A19 | PF2 <-> FSMC_A2 | PG2 <-> FSMC_A12 | - | PD5 <-> FSMC_NWE | PE4 <-> FSMC_A20 | PF3 <-> FSMC_A3 | PG3 <-> FSMC_A13 | - | PD8 <-> FSMC_D13 | PE7 <-> FSMC_D4 | PF4 <-> FSMC_A4 | PG4 <-> FSMC_A14 | - | PD9 <-> FSMC_D14 | PE8 <-> FSMC_D5 | PF5 <-> FSMC_A5 | PG5 <-> FSMC_A15 | - | PD10 <-> FSMC_D15 | PE9 <-> FSMC_D6 | PF12 <-> FSMC_A6 | PG9 <-> FSMC_NE2 | - | PD11 <-> FSMC_A16 | PE10 <-> FSMC_D7 | PF13 <-> FSMC_A7 |------------------+ - | PD12 <-> FSMC_A17 | PE11 <-> FSMC_D8 | PF14 <-> FSMC_A8 | - | PD13 <-> FSMC_A18 | PE12 <-> FSMC_D9 | PF15 <-> FSMC_A9 | - | PD14 <-> FSMC_D0 | PE13 <-> FSMC_D10 |------------------+ - | PD15 <-> FSMC_D1 | PE14 <-> FSMC_D11 | - | | PE15 <-> FSMC_D12 | - +-------------------+--------------------+ -*/ - /* Enable GPIOD, GPIOE, GPIOF and GPIOG interface clock */ - RCC->AHB1ENR = 0x00000078; - - /* Connect PDx pins to FSMC Alternate function */ - GPIOD->AFR[0] = 0x00cc00cc; - GPIOD->AFR[1] = 0xcc0ccccc; - /* Configure PDx pins in Alternate function mode */ - GPIOD->MODER = 0xaaaa0a0a; - /* Configure PDx pins speed to 100 MHz */ - GPIOD->OSPEEDR = 0xffff0f0f; - /* Configure PDx pins Output type to push-pull */ - GPIOD->OTYPER = 0x00000000; - /* No pull-up, pull-down for PDx pins */ - GPIOD->PUPDR = 0x00000000; - - /* Connect PEx pins to FSMC Alternate function */ - GPIOE->AFR[0] = 0xc00cc0cc; - GPIOE->AFR[1] = 0xcccccccc; - /* Configure PEx pins in Alternate function mode */ - GPIOE->MODER = 0xaaaa828a; - /* Configure PEx pins speed to 100 MHz */ - GPIOE->OSPEEDR = 0xffffc3cf; - /* Configure PEx pins Output type to push-pull */ - GPIOE->OTYPER = 0x00000000; - /* No pull-up, pull-down for PEx pins */ - GPIOE->PUPDR = 0x00000000; - - /* Connect PFx pins to FSMC Alternate function */ - GPIOF->AFR[0] = 0x00cccccc; - GPIOF->AFR[1] = 0xcccc0000; - /* Configure PFx pins in Alternate function mode */ - GPIOF->MODER = 0xaa000aaa; - /* Configure PFx pins speed to 100 MHz */ - GPIOF->OSPEEDR = 0xff000fff; - /* Configure PFx pins Output type to push-pull */ - GPIOF->OTYPER = 0x00000000; - /* No pull-up, pull-down for PFx pins */ - GPIOF->PUPDR = 0x00000000; - - /* Connect PGx pins to FSMC Alternate function */ - GPIOG->AFR[0] = 0x00cccccc; - GPIOG->AFR[1] = 0x000000c0; - /* Configure PGx pins in Alternate function mode */ - GPIOG->MODER = 0x00080aaa; - /* Configure PGx pins speed to 100 MHz */ - GPIOG->OSPEEDR = 0x000c0fff; - /* Configure PGx pins Output type to push-pull */ - GPIOG->OTYPER = 0x00000000; - /* No pull-up, pull-down for PGx pins */ - GPIOG->PUPDR = 0x00000000; - -/*-- FSMC Configuration ------------------------------------------------------*/ - /* Enable the FSMC interface clock */ - RCC->AHB3ENR = 0x00000001; - - /* Configure and enable Bank1_SRAM2 */ - FSMC_Bank1->BTCR[2] = 0x00001015; - FSMC_Bank1->BTCR[3] = 0x00010603;//0x00010400; - FSMC_Bank1E->BWTR[2] = 0x0fffffff; -/* - Bank1_SRAM2 is configured as follow: - - p.FSMC_AddressSetupTime = 3;//0; - p.FSMC_AddressHoldTime = 0; - p.FSMC_DataSetupTime = 6;//4; - p.FSMC_BusTurnAroundDuration = 1; - p.FSMC_CLKDivision = 0; - p.FSMC_DataLatency = 0; - p.FSMC_AccessMode = FSMC_AccessMode_A; - - FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM2; - FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable; - FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_PSRAM; - FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b; - FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable; - FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait = FSMC_AsynchronousWait_Disable; - FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low; - FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable; - FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState; - FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable; - FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable; - FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable; - FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable; - FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &p; - FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &p; -*/ - -} -#endif /* DATA_IN_ExtSRAM */ - - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ -/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ - +/************************************************************************************************************************************** +* Project: discoverpixy +* Website: https://github.com/t-moe/discoverpixy +* Authors: Aaron Schmocker, Timo Lang +* Institution: BFH Bern University of Applied Sciences +* File: discovery/src/system_stm32f4xx.c +* +* Version History: +* Date Autor Email SHA Changes +* 2015-04-03 timolang@gmail.com 21dd1e2 Starting to integrate usb branch. Optimized Makefiles +* +**************************************************************************************************************************************/ + +/** + ****************************************************************************** + * @file system_stm32f4xx.c + * @author MCD Application Team + * @version V1.0.0 + * @date 19-September-2011 + * @brief CMSIS Cortex-M4 Device Peripheral Access Layer System Source File. + * This file contains the system clock configuration for STM32F4xx devices, + * and is generated by the clock configuration tool + * stm32f4xx_Clock_Configuration_V1.0.0.xls + * + * 1. This file provides two functions and one global variable to be called from + * user application: + * - SystemInit(): Setups the system clock (System clock source, PLL Multiplier + * and Divider factors, AHB/APBx prescalers and Flash settings), + * depending on the configuration made in the clock xls tool. + * This function is called at startup just after reset and + * before branch to main program. This call is made inside + * the "startup_stm32f4xx.s" file. + * + * - SystemCoreClock variable: Contains the core clock (HCLK), it can be used + * by the user application to setup the SysTick + * timer or configure other parameters. + * + * - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must + * be called whenever the core clock is changed + * during program execution. + * + * 2. After each device reset the HSI (16 MHz) is used as system clock source. + * Then SystemInit() function is called, in "startup_stm32f4xx.s" file, to + * configure the system clock before to branch to main program. + * + * 3. If the system clock source selected by user fails to startup, the SystemInit() + * function will do nothing and HSI still used as system clock source. User can + * add some code to deal with this issue inside the SetSysClock() function. + * + * 4. The default value of HSE crystal is set to 8 MHz, refer to "HSE_VALUE" define + * in "stm32f4xx.h" file. When HSE is used as system clock source, directly or + * through PLL, and you are using different crystal you have to adapt the HSE + * value to your own configuration. + * + * 5. This file configures the system clock as follows: + *============================================================================= + *============================================================================= + * Supported STM32F4xx device revision | Rev A + *----------------------------------------------------------------------------- + * System Clock source | PLL (HSE) + *----------------------------------------------------------------------------- + * SYSCLK(Hz) | 168000000 + *----------------------------------------------------------------------------- + * HCLK(Hz) | 168000000 + *----------------------------------------------------------------------------- + * AHB Prescaler | 1 + *----------------------------------------------------------------------------- + * APB1 Prescaler | 4 + *----------------------------------------------------------------------------- + * APB2 Prescaler | 2 + *----------------------------------------------------------------------------- + * HSE Frequency(Hz) | 8000000 + *----------------------------------------------------------------------------- + * PLL_M | 8 + *----------------------------------------------------------------------------- + * PLL_N | 336 + *----------------------------------------------------------------------------- + * PLL_P | 2 + *----------------------------------------------------------------------------- + * PLL_Q | 7 + *----------------------------------------------------------------------------- + * PLLI2S_N | NA + *----------------------------------------------------------------------------- + * PLLI2S_R | NA + *----------------------------------------------------------------------------- + * I2S input clock | NA + *----------------------------------------------------------------------------- + * VDD(V) | 3.3 + *----------------------------------------------------------------------------- + * High Performance mode | Enabled + *----------------------------------------------------------------------------- + * Flash Latency(WS) | 5 + *----------------------------------------------------------------------------- + * Prefetch Buffer | OFF + *----------------------------------------------------------------------------- + * Instruction cache | ON + *----------------------------------------------------------------------------- + * Data cache | ON + *----------------------------------------------------------------------------- + * Require 48MHz for USB OTG FS, | Enabled + * SDIO and RNG clock | + *----------------------------------------------------------------------------- + *============================================================================= + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/** @addtogroup CMSIS + * @{ + */ + +/** @addtogroup stm32f4xx_system + * @{ + */ + +/** @addtogroup STM32F4xx_System_Private_Includes + * @{ + */ + +#include "stm32f4xx.h" + +/** + * @} + */ + +/** @addtogroup STM32F4xx_System_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32F4xx_System_Private_Defines + * @{ + */ + +/*!< Uncomment the following line if you need to use external SRAM mounted + on STM324xG_EVAL board as data memory */ +/* #define DATA_IN_ExtSRAM */ + +/*!< Uncomment the following line if you need to relocate your vector Table in + Internal SRAM. */ +/* #define VECT_TAB_SRAM */ +#define VECT_TAB_OFFSET 0x00 /*!< Vector Table base offset field. + This value must be a multiple of 0x200. */ + + +/* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N */ +#define PLL_M 8 +#define PLL_N 336 + +/* SYSCLK = PLL_VCO / PLL_P */ +#define PLL_P 2 + +/* USB OTG FS, SDIO and RNG Clock = PLL_VCO / PLLQ */ +#define PLL_Q 7 + +/** + * @} + */ + +/** @addtogroup STM32F4xx_System_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32F4xx_System_Private_Variables + * @{ + */ + +uint32_t SystemCoreClock = 168000000; + +__I uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; + +/** + * @} + */ + +/** @addtogroup STM32F4xx_System_Private_FunctionPrototypes + * @{ + */ + +static void SetSysClock(void); +#ifdef DATA_IN_ExtSRAM +static void SystemInit_ExtMemCtl(void); +#endif /* DATA_IN_ExtSRAM */ + +/** + * @} + */ + +/** @addtogroup STM32F4xx_System_Private_Functions + * @{ + */ + +/** + * @brief Setup the microcontroller system + * Initialize the Embedded Flash Interface, the PLL and update the + * SystemFrequency variable. + * @param None + * @retval None + */ +void SystemInit(void) +{ + /* Reset the RCC clock configuration to the default reset state ------------*/ + /* Set HSION bit */ + RCC->CR |= (uint32_t)0x00000001; + + /* Reset CFGR register */ + RCC->CFGR = 0x00000000; + + /* Reset HSEON, CSSON and PLLON bits */ + RCC->CR &= (uint32_t)0xFEF6FFFF; + + /* Reset PLLCFGR register */ + RCC->PLLCFGR = 0x24003010; + + /* Reset HSEBYP bit */ + RCC->CR &= (uint32_t)0xFFFBFFFF; + + /* Disable all interrupts */ + RCC->CIR = 0x00000000; + +#ifdef DATA_IN_ExtSRAM + SystemInit_ExtMemCtl(); +#endif /* DATA_IN_ExtSRAM */ + + /* Configure the System clock source, PLL Multiplier and Divider factors, + AHB/APBx prescalers and Flash settings ----------------------------------*/ + SetSysClock(); + + /* Configure the Vector Table location add offset address ------------------*/ +#ifdef VECT_TAB_SRAM + SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */ +#else + SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */ +#endif +} + +/** + * @brief Update SystemCoreClock variable according to Clock Register Values. + * The SystemCoreClock variable contains the core clock (HCLK), it can + * be used by the user application to setup the SysTick timer or configure + * other parameters. + * + * @note Each time the core clock (HCLK) changes, this function must be called + * to update SystemCoreClock variable value. Otherwise, any configuration + * based on this variable will be incorrect. + * + * @note - The system frequency computed by this function is not the real + * frequency in the chip. It is calculated based on the predefined + * constant and the selected clock source: + * + * - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*) + * + * - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(**) + * + * - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**) + * or HSI_VALUE(*) multiplied/divided by the PLL factors. + * + * (*) HSI_VALUE is a constant defined in stm32f4xx.h file (default value + * 16 MHz) but the real value may vary depending on the variations + * in voltage and temperature. + * + * (**) HSE_VALUE is a constant defined in stm32f4xx.h file (default value + * 25 MHz), user has to ensure that HSE_VALUE is same as the real + * frequency of the crystal used. Otherwise, this function may + * have wrong result. + * + * - The result of this function could be not correct when using fractional + * value for HSE crystal. + * + * @param None + * @retval None + */ +void SystemCoreClockUpdate(void) +{ + uint32_t tmp = 0, pllvco = 0, pllp = 2, pllsource = 0, pllm = 2; + + /* Get SYSCLK source -------------------------------------------------------*/ + tmp = RCC->CFGR & RCC_CFGR_SWS; + + switch (tmp) { + case 0x00: /* HSI used as system clock source */ + SystemCoreClock = HSI_VALUE; + break; + + case 0x04: /* HSE used as system clock source */ + SystemCoreClock = HSE_VALUE; + break; + + case 0x08: /* PLL used as system clock source */ + + /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N + SYSCLK = PLL_VCO / PLL_P + */ + pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) >> 22; + pllm = RCC->PLLCFGR & RCC_PLLCFGR_PLLM; + + if (pllsource != 0) { + /* HSE used as PLL clock source */ + pllvco = (HSE_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6); + } else { + /* HSI used as PLL clock source */ + pllvco = (HSI_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6); + } + + pllp = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLP) >> 16) + 1) * 2; + SystemCoreClock = pllvco / pllp; + break; + + default: + SystemCoreClock = HSI_VALUE; + break; + } + + /* Compute HCLK frequency --------------------------------------------------*/ + /* Get HCLK prescaler */ + tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)]; + /* HCLK frequency */ + SystemCoreClock >>= tmp; +} + +/** + * @brief Configures the System clock source, PLL Multiplier and Divider factors, + * AHB/APBx prescalers and Flash settings + * @Note This function should be called only once the RCC clock configuration + * is reset to the default reset state (done in SystemInit() function). + * @param None + * @retval None + */ +static void SetSysClock(void) +{ + /******************************************************************************/ + /* PLL (clocked by HSE) used as System clock source */ + /******************************************************************************/ + __IO uint32_t StartUpCounter = 0, HSEStatus = 0; + + /* Enable HSE */ + RCC->CR |= ((uint32_t)RCC_CR_HSEON); + + /* Wait till HSE is ready and if Time out is reached exit */ + do { + HSEStatus = RCC->CR & RCC_CR_HSERDY; + StartUpCounter++; + } while ((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT)); + + if ((RCC->CR & RCC_CR_HSERDY) != RESET) { + HSEStatus = (uint32_t)0x01; + } else { + HSEStatus = (uint32_t)0x00; + } + + if (HSEStatus == (uint32_t)0x01) { + /* Enable high performance mode, System frequency up to 168 MHz */ + RCC->APB1ENR |= RCC_APB1ENR_PWREN; + PWR->CR |= PWR_CR_PMODE; + + /* HCLK = SYSCLK / 1*/ + RCC->CFGR |= RCC_CFGR_HPRE_DIV1; + + /* PCLK2 = HCLK / 2*/ + RCC->CFGR |= RCC_CFGR_PPRE2_DIV2; + + /* PCLK1 = HCLK / 4*/ + RCC->CFGR |= RCC_CFGR_PPRE1_DIV4; + + /* Configure the main PLL */ + RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) - 1) << 16) | + (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24); + + /* Enable the main PLL */ + RCC->CR |= RCC_CR_PLLON; + + /* Wait till the main PLL is ready */ + while ((RCC->CR & RCC_CR_PLLRDY) == 0) { + } + + /* Configure Flash prefetch, Instruction cache, Data cache and wait state */ + FLASH->ACR = FLASH_ACR_ICEN | FLASH_ACR_DCEN | FLASH_ACR_LATENCY_5WS; + + /* Select the main PLL as system clock source */ + RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW)); + RCC->CFGR |= RCC_CFGR_SW_PLL; + + /* Wait till the main PLL is used as system clock source */ + while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL); + + { + } + } else { + /* If HSE fails to start-up, the application will have wrong clock + configuration. User can add here some code to deal with this error */ + } + +} + +/** + * @brief Setup the external memory controller. Called in startup_stm32f4xx.s + * before jump to __main + * @param None + * @retval None + */ +#ifdef DATA_IN_ExtSRAM +/** + * @brief Setup the external memory controller. + * Called in startup_stm32f4xx.s before jump to main. + * This function configures the external SRAM mounted on STM324xG_EVAL board + * This SRAM will be used as program data memory (including heap and stack). + * @param None + * @retval None + */ +void SystemInit_ExtMemCtl(void) +{ + /*-- GPIOs Configuration -----------------------------------------------------*/ + /* + +-------------------+--------------------+------------------+------------------+ + + SRAM pins assignment + + +-------------------+--------------------+------------------+------------------+ + | PD0 <-> FSMC_D2 | PE0 <-> FSMC_NBL0 | PF0 <-> FSMC_A0 | PG0 <-> FSMC_A10 | + | PD1 <-> FSMC_D3 | PE1 <-> FSMC_NBL1 | PF1 <-> FSMC_A1 | PG1 <-> FSMC_A11 | + | PD4 <-> FSMC_NOE | PE3 <-> FSMC_A19 | PF2 <-> FSMC_A2 | PG2 <-> FSMC_A12 | + | PD5 <-> FSMC_NWE | PE4 <-> FSMC_A20 | PF3 <-> FSMC_A3 | PG3 <-> FSMC_A13 | + | PD8 <-> FSMC_D13 | PE7 <-> FSMC_D4 | PF4 <-> FSMC_A4 | PG4 <-> FSMC_A14 | + | PD9 <-> FSMC_D14 | PE8 <-> FSMC_D5 | PF5 <-> FSMC_A5 | PG5 <-> FSMC_A15 | + | PD10 <-> FSMC_D15 | PE9 <-> FSMC_D6 | PF12 <-> FSMC_A6 | PG9 <-> FSMC_NE2 | + | PD11 <-> FSMC_A16 | PE10 <-> FSMC_D7 | PF13 <-> FSMC_A7 |------------------+ + | PD12 <-> FSMC_A17 | PE11 <-> FSMC_D8 | PF14 <-> FSMC_A8 | + | PD13 <-> FSMC_A18 | PE12 <-> FSMC_D9 | PF15 <-> FSMC_A9 | + | PD14 <-> FSMC_D0 | PE13 <-> FSMC_D10 |------------------+ + | PD15 <-> FSMC_D1 | PE14 <-> FSMC_D11 | + | | PE15 <-> FSMC_D12 | + +-------------------+--------------------+ + */ + /* Enable GPIOD, GPIOE, GPIOF and GPIOG interface clock */ + RCC->AHB1ENR = 0x00000078; + + /* Connect PDx pins to FSMC Alternate function */ + GPIOD->AFR[0] = 0x00cc00cc; + GPIOD->AFR[1] = 0xcc0ccccc; + /* Configure PDx pins in Alternate function mode */ + GPIOD->MODER = 0xaaaa0a0a; + /* Configure PDx pins speed to 100 MHz */ + GPIOD->OSPEEDR = 0xffff0f0f; + /* Configure PDx pins Output type to push-pull */ + GPIOD->OTYPER = 0x00000000; + /* No pull-up, pull-down for PDx pins */ + GPIOD->PUPDR = 0x00000000; + + /* Connect PEx pins to FSMC Alternate function */ + GPIOE->AFR[0] = 0xc00cc0cc; + GPIOE->AFR[1] = 0xcccccccc; + /* Configure PEx pins in Alternate function mode */ + GPIOE->MODER = 0xaaaa828a; + /* Configure PEx pins speed to 100 MHz */ + GPIOE->OSPEEDR = 0xffffc3cf; + /* Configure PEx pins Output type to push-pull */ + GPIOE->OTYPER = 0x00000000; + /* No pull-up, pull-down for PEx pins */ + GPIOE->PUPDR = 0x00000000; + + /* Connect PFx pins to FSMC Alternate function */ + GPIOF->AFR[0] = 0x00cccccc; + GPIOF->AFR[1] = 0xcccc0000; + /* Configure PFx pins in Alternate function mode */ + GPIOF->MODER = 0xaa000aaa; + /* Configure PFx pins speed to 100 MHz */ + GPIOF->OSPEEDR = 0xff000fff; + /* Configure PFx pins Output type to push-pull */ + GPIOF->OTYPER = 0x00000000; + /* No pull-up, pull-down for PFx pins */ + GPIOF->PUPDR = 0x00000000; + + /* Connect PGx pins to FSMC Alternate function */ + GPIOG->AFR[0] = 0x00cccccc; + GPIOG->AFR[1] = 0x000000c0; + /* Configure PGx pins in Alternate function mode */ + GPIOG->MODER = 0x00080aaa; + /* Configure PGx pins speed to 100 MHz */ + GPIOG->OSPEEDR = 0x000c0fff; + /* Configure PGx pins Output type to push-pull */ + GPIOG->OTYPER = 0x00000000; + /* No pull-up, pull-down for PGx pins */ + GPIOG->PUPDR = 0x00000000; + + /*-- FSMC Configuration ------------------------------------------------------*/ + /* Enable the FSMC interface clock */ + RCC->AHB3ENR = 0x00000001; + + /* Configure and enable Bank1_SRAM2 */ + FSMC_Bank1->BTCR[2] = 0x00001015; + FSMC_Bank1->BTCR[3] = 0x00010603;//0x00010400; + FSMC_Bank1E->BWTR[2] = 0x0fffffff; + /* + Bank1_SRAM2 is configured as follow: + + p.FSMC_AddressSetupTime = 3;//0; + p.FSMC_AddressHoldTime = 0; + p.FSMC_DataSetupTime = 6;//4; + p.FSMC_BusTurnAroundDuration = 1; + p.FSMC_CLKDivision = 0; + p.FSMC_DataLatency = 0; + p.FSMC_AccessMode = FSMC_AccessMode_A; + + FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM2; + FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable; + FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_PSRAM; + FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b; + FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable; + FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait = FSMC_AsynchronousWait_Disable; + FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low; + FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable; + FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState; + FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable; + FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable; + FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable; + FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable; + FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &p; + FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &p; + */ + +} +#endif /* DATA_IN_ExtSRAM */ + + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/discovery/src/usb_bsp.c b/discovery/src/usb_bsp.c index 6d4ed62..bcd8ed8 100644 --- a/discovery/src/usb_bsp.c +++ b/discovery/src/usb_bsp.c @@ -1,460 +1,468 @@ - -/* Includes ------------------------------------------------------------------*/ -#include "usb_bsp.h" -#include "stm32f4_discovery.h" - -#define USE_ACCURATE_TIME -#define TIM_MSEC_DELAY 0x01 -#define TIM_USEC_DELAY 0x02 -#define HOST_OVRCURR_PORT GPIOD -#define HOST_OVRCURR_LINE GPIO_Pin_5 -#define HOST_OVRCURR_PORT_SOURCE GPIO_PortSourceGPIOD -#define HOST_OVRCURR_PIN_SOURCE GPIO_PinSourceD -#define HOST_OVRCURR_PORT_RCC RCC_APB2Periph_GPIOD -#define HOST_OVRCURR_EXTI_LINE EXTI_Line5 -#define HOST_OVRCURR_IRQn EXTI9_5_IRQn - - -#define HOST_POWERSW_PORT_RCC RCC_AHB1Periph_GPIOC -#define HOST_POWERSW_PORT GPIOC -#define HOST_POWERSW_VBUS GPIO_Pin_0 - -/* Private macros ------------------------------------------------------------*/ -/* Private variables ---------------------------------------------------------*/ -ErrorStatus HSEStartUpStatus; -#ifdef USE_ACCURATE_TIME - __IO uint32_t BSP_delay = 0; -#endif - -/* Private function prototypes -----------------------------------------------*/ -/* Private functions ---------------------------------------------------------*/ -#ifdef USE_ACCURATE_TIME - static void BSP_SetTime(uint8_t Unit); - static void BSP_Delay(uint32_t nTime, uint8_t Unit); - static void USB_OTG_BSP_TimeInit ( void ); -#endif - -/** - * @brief BSP_Init - * board user initializations - * @param None - * @retval None - */ -void BSP_Init(void) -{ - /* Configure PA0 pin: User Key pin */ -} - - -/** - * @brief USB_OTG_BSP_Init - * Initilizes BSP configurations - * @param None - * @retval None - */ -void USB_OTG_BSP_Init(USB_OTG_CORE_HANDLE *pdev) -{ - /* Note: On STM32F4-Discovery board only USB OTG FS core is supported. */ - - GPIO_InitTypeDef GPIO_InitStructure; - #ifdef USE_USB_OTG_FS - - RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOA , ENABLE); - - /* Configure SOF VBUS ID DM DP Pins */ - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | - GPIO_Pin_11 | - GPIO_Pin_12; - - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; - GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; - GPIO_Init(GPIOA, &GPIO_InitStructure); - - GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_OTG1_FS) ; - GPIO_PinAFConfig(GPIOA,GPIO_PinSource11,GPIO_AF_OTG1_FS) ; - GPIO_PinAFConfig(GPIOA,GPIO_PinSource12,GPIO_AF_OTG1_FS) ; - - /* this for ID line debug */ - - - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; - GPIO_InitStructure.GPIO_OType = GPIO_OType_OD; - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP ; - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; - GPIO_Init(GPIOA, &GPIO_InitStructure); - GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_OTG1_FS) ; - - - RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); - RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_OTG_FS, ENABLE) ; - #else // USE_USB_OTG_HS - - #ifdef USE_ULPI_PHY // ULPI - RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | - RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOH | - RCC_AHB1Periph_GPIOI, ENABLE); - - - GPIO_PinAFConfig(GPIOA,GPIO_PinSource3, GPIO_AF_OTG2_HS) ; // D0 - GPIO_PinAFConfig(GPIOA,GPIO_PinSource5, GPIO_AF_OTG2_HS) ; // CLK - GPIO_PinAFConfig(GPIOB,GPIO_PinSource0, GPIO_AF_OTG2_HS) ; // D1 - GPIO_PinAFConfig(GPIOB,GPIO_PinSource1, GPIO_AF_OTG2_HS) ; // D2 - GPIO_PinAFConfig(GPIOB,GPIO_PinSource5, GPIO_AF_OTG2_HS) ; // D7 - GPIO_PinAFConfig(GPIOB,GPIO_PinSource10,GPIO_AF_OTG2_HS) ; // D3 - GPIO_PinAFConfig(GPIOB,GPIO_PinSource11,GPIO_AF_OTG2_HS) ; // D4 - GPIO_PinAFConfig(GPIOB,GPIO_PinSource12,GPIO_AF_OTG2_HS) ; // D5 - GPIO_PinAFConfig(GPIOB,GPIO_PinSource13,GPIO_AF_OTG2_HS) ; // D6 - GPIO_PinAFConfig(GPIOH,GPIO_PinSource4, GPIO_AF_OTG2_HS) ; // NXT - GPIO_PinAFConfig(GPIOI,GPIO_PinSource11,GPIO_AF_OTG2_HS) ; // DIR - GPIO_PinAFConfig(GPIOC,GPIO_PinSource0, GPIO_AF_OTG2_HS) ; // STP - - // CLK - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 ; - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; - GPIO_Init(GPIOA, &GPIO_InitStructure); - - // D0 - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 ; - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; - GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; - GPIO_Init(GPIOA, &GPIO_InitStructure); - - - - // D1 D2 D3 D4 D5 D6 D7 - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | - GPIO_Pin_5 | GPIO_Pin_10 | - GPIO_Pin_11| GPIO_Pin_12 | - GPIO_Pin_13 ; - - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; - GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; - GPIO_Init(GPIOB, &GPIO_InitStructure); - - - // STP - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 ; - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; - GPIO_Init(GPIOC, &GPIO_InitStructure); - - //NXT - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; - GPIO_Init(GPIOH, &GPIO_InitStructure); - - - //DIR - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 ; - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; - GPIO_Init(GPIOI, &GPIO_InitStructure); - - - RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_OTG_HS | - RCC_AHB1Periph_OTG_HS_ULPI, ENABLE) ; - - #else - - #ifdef USE_I2C_PHY - RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOB , ENABLE); - /* Configure RESET INTN SCL SDA (Phy/I2C) Pins */ - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | - GPIO_Pin_1 | - GPIO_Pin_10 | - GPIO_Pin_11; - - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; - GPIO_Init(GPIOB, &GPIO_InitStructure); - - GPIO_PinAFConfig(GPIOB,GPIO_PinSource0,GPIO_AF_OTG2_FS) ; - GPIO_PinAFConfig(GPIOB,GPIO_PinSource1,GPIO_AF_OTG2_FS) ; - GPIO_PinAFConfig(GPIOB,GPIO_PinSource10,GPIO_AF_OTG2_FS) ; - GPIO_PinAFConfig(GPIOB,GPIO_PinSource11,GPIO_AF_OTG2_FS); - RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_OTG_HS, ENABLE) ; - - #else - - RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB , ENABLE); - - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | - GPIO_Pin_13 | - GPIO_Pin_14 | - GPIO_Pin_15; - - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; - GPIO_Init(GPIOB, &GPIO_InitStructure); - - GPIO_PinAFConfig(GPIOB,GPIO_PinSource12, GPIO_AF_OTG2_FS) ; - GPIO_PinAFConfig(GPIOB,GPIO_PinSource13,GPIO_AF_OTG2_FS) ; - GPIO_PinAFConfig(GPIOB,GPIO_PinSource14,GPIO_AF_OTG2_FS) ; - GPIO_PinAFConfig(GPIOB,GPIO_PinSource15,GPIO_AF_OTG2_FS) ; - RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_OTG_HS, ENABLE) ; - #endif - #endif - #endif //USB_OTG_HS - - /* Intialize Timer for delay function */ - USB_OTG_BSP_TimeInit(); -} - -/** - * @brief USB_OTG_BSP_EnableInterrupt - * Configures USB Global interrupt - * @param None - * @retval None - */ -void USB_OTG_BSP_EnableInterrupt(USB_OTG_CORE_HANDLE *pdev) -{ - - NVIC_InitTypeDef NVIC_InitStructure; - /* Enable USB Interrupt */ - NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); - - NVIC_InitStructure.NVIC_IRQChannel = OTG_FS_IRQn; - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; - NVIC_Init(&NVIC_InitStructure); - - /* Enable the Overcurrent Interrupt */ - NVIC_InitStructure.NVIC_IRQChannel = HOST_OVRCURR_IRQn; - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; - - NVIC_Init(&NVIC_InitStructure); -} - -/** - * @brief BSP_Drive_VBUS - * Drives the Vbus signal through IO - * @param state : VBUS states - * @retval None - */ -void USB_OTG_BSP_DriveVBUS(USB_OTG_CORE_HANDLE *pdev, uint8_t state) -{ - /* - On-chip 5 V VBUS generation is not supported. For this reason, a charge pump - or, if 5 V are available on the application board, a basic power switch, must - be added externally to drive the 5 V VBUS line. The external charge pump can - be driven by any GPIO output. When the application decides to power on VBUS - using the chosen GPIO, it must also set the port power bit in the host port - control and status register (PPWR bit in OTG_FS_HPRT). - - Bit 12 PPWR: Port power - The application uses this field to control power to this port, and the core - clears this bit on an overcurrent condition. - */ - if (0 == state) - { - /* DISABLE is needed on output of the Power Switch */ - GPIO_SetBits(HOST_POWERSW_PORT, HOST_POWERSW_VBUS); - } - else - { - /*ENABLE the Power Switch by driving the Enable LOW */ - GPIO_ResetBits(HOST_POWERSW_PORT, HOST_POWERSW_VBUS); - } -} - -/** - * @brief USB_OTG_BSP_ConfigVBUS - * Configures the IO for the Vbus and OverCurrent - * @param None - * @retval None - */ -void USB_OTG_BSP_ConfigVBUS(USB_OTG_CORE_HANDLE *pdev) -{ - GPIO_InitTypeDef GPIO_InitStructure; - - - RCC_AHB1PeriphClockCmd(HOST_POWERSW_PORT_RCC, ENABLE); - - - /* Configure Power Switch Vbus Pin */ - GPIO_InitStructure.GPIO_Pin = HOST_POWERSW_VBUS; - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; - GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; - - GPIO_Init(HOST_POWERSW_PORT, &GPIO_InitStructure); - - /* By Default, DISABLE is needed on output of the Power Switch */ - GPIO_SetBits(HOST_POWERSW_PORT, HOST_POWERSW_VBUS); - - USB_OTG_BSP_mDelay(200); /* Delay is need for stabilising the Vbus Low - in Reset Condition, when Vbus=1 and Reset-button is pressed by user */ - -} - -/** - * @brief USB_OTG_BSP_TimeInit - * Initializes delay unit using Timer2 - * @param None - * @retval None - */ -static void USB_OTG_BSP_TimeInit (void) -{ -#ifdef USE_ACCURATE_TIME - NVIC_InitTypeDef NVIC_InitStructure; - - /* Set the Vector Table base address at 0x08000000 */ -// NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x00); - - /* Configure the Priority Group to 2 bits */ - NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); - - /* Enable the TIM2 gloabal Interrupt */ - NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; - - NVIC_Init(&NVIC_InitStructure); - - RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); -#endif -} - -/** - * @brief USB_OTG_BSP_uDelay - * This function provides delay time in micro sec - * @param usec : Value of delay required in micro sec - * @retval None - */ -void USB_OTG_BSP_uDelay (const uint32_t usec) -{ - -#ifdef USE_ACCURATE_TIME - BSP_Delay(usec, TIM_USEC_DELAY); -#else - __IO uint32_t count = 0; - const uint32_t utime = (120 * usec / 7); - do - { - if ( ++count > utime ) - { - return ; - } - } - while (1); -#endif - -} - -/** - * @brief USB_OTG_BSP_mDelay - * This function provides delay time in milli sec - * @param msec : Value of delay required in milli sec - * @retval None - */ -void USB_OTG_BSP_mDelay (const uint32_t msec) -{ -#ifdef USE_ACCURATE_TIME - BSP_Delay(msec, TIM_MSEC_DELAY); -#else - USB_OTG_BSP_uDelay(msec * 1000); -#endif - -} - -/** - * @brief USB_OTG_BSP_TimerIRQ - * Time base IRQ - * @param None - * @retval None - */ -void USB_OTG_BSP_TimerIRQ (void) -{ -#ifdef USE_ACCURATE_TIME - if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) - { - TIM_ClearITPendingBit(TIM2, TIM_IT_Update); - if (BSP_delay > 0x00) - { - BSP_delay--; - } - else - { - TIM_Cmd(TIM2, DISABLE); - } - } -#endif -} - -#ifdef USE_ACCURATE_TIME - -/** - * @brief BSP_Delay - * Delay routine based on TIM2 - * @param nTime : Delay Time - * @param unit : Delay Time unit : mili sec / micro sec - * @retval None - */ -static void BSP_Delay(uint32_t nTime, uint8_t unit) -{ - - BSP_delay = nTime; - BSP_SetTime(unit); - while (BSP_delay != 0); - TIM_Cmd(TIM2, DISABLE); -} - -/** - * @brief BSP_SetTime - * Configures TIM2 for delay routine based on TIM2 - * @param unit : msec /usec - * @retval None - */ -static void BSP_SetTime(uint8_t unit) -{ - TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; - - TIM_Cmd(TIM2, DISABLE); - TIM_ITConfig(TIM2, TIM_IT_Update, DISABLE); - - - if (unit == TIM_USEC_DELAY) - { - TIM_TimeBaseStructure.TIM_Period = 11; - } - else if (unit == TIM_MSEC_DELAY) - { - TIM_TimeBaseStructure.TIM_Period = 11999; - } - TIM_TimeBaseStructure.TIM_Prescaler = 5; - TIM_TimeBaseStructure.TIM_ClockDivision = 0; - TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; - - TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); - TIM_ClearITPendingBit(TIM2, TIM_IT_Update); - - TIM_ARRPreloadConfig(TIM2, ENABLE); - - /* TIM IT enable */ - TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); - - /* TIM2 enable counter */ - TIM_Cmd(TIM2, ENABLE); -} - -#endif - -/** -* @} -*/ - - -/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ +/************************************************************************************************************************************** +* Project: discoverpixy +* Website: https://github.com/t-moe/discoverpixy +* Authors: Aaron Schmocker, Timo Lang +* Institution: BFH Bern University of Applied Sciences +* File: discovery/src/usb_bsp.c +* +* Version History: +* Date Autor Email SHA Changes +* 2015-04-03 timolang@gmail.com 21dd1e2 Starting to integrate usb branch. Optimized Makefiles +* +**************************************************************************************************************************************/ + + +/* Includes ------------------------------------------------------------------*/ +#include "usb_bsp.h" +#include "stm32f4_discovery.h" + +#define USE_ACCURATE_TIME +#define TIM_MSEC_DELAY 0x01 +#define TIM_USEC_DELAY 0x02 +#define HOST_OVRCURR_PORT GPIOD +#define HOST_OVRCURR_LINE GPIO_Pin_5 +#define HOST_OVRCURR_PORT_SOURCE GPIO_PortSourceGPIOD +#define HOST_OVRCURR_PIN_SOURCE GPIO_PinSourceD +#define HOST_OVRCURR_PORT_RCC RCC_APB2Periph_GPIOD +#define HOST_OVRCURR_EXTI_LINE EXTI_Line5 +#define HOST_OVRCURR_IRQn EXTI9_5_IRQn + + +#define HOST_POWERSW_PORT_RCC RCC_AHB1Periph_GPIOC +#define HOST_POWERSW_PORT GPIOC +#define HOST_POWERSW_VBUS GPIO_Pin_0 + +/* Private macros ------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +ErrorStatus HSEStartUpStatus; +#ifdef USE_ACCURATE_TIME +__IO uint32_t BSP_delay = 0; +#endif + +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ +#ifdef USE_ACCURATE_TIME +static void BSP_SetTime(uint8_t Unit); +static void BSP_Delay(uint32_t nTime, uint8_t Unit); +static void USB_OTG_BSP_TimeInit(void); +#endif + +/** + * @brief BSP_Init + * board user initializations + * @param None + * @retval None + */ +void BSP_Init(void) +{ + /* Configure PA0 pin: User Key pin */ +} + + +/** + * @brief USB_OTG_BSP_Init + * Initilizes BSP configurations + * @param None + * @retval None + */ +void USB_OTG_BSP_Init(USB_OTG_CORE_HANDLE* pdev) +{ + /* Note: On STM32F4-Discovery board only USB OTG FS core is supported. */ + + GPIO_InitTypeDef GPIO_InitStructure; +#ifdef USE_USB_OTG_FS + + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA , ENABLE); + + /* Configure SOF VBUS ID DM DP Pins */ + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | + GPIO_Pin_11 | + GPIO_Pin_12; + + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; + GPIO_Init(GPIOA, &GPIO_InitStructure); + + GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_OTG1_FS) ; + GPIO_PinAFConfig(GPIOA, GPIO_PinSource11, GPIO_AF_OTG1_FS) ; + GPIO_PinAFConfig(GPIOA, GPIO_PinSource12, GPIO_AF_OTG1_FS) ; + + /* this for ID line debug */ + + + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; + GPIO_InitStructure.GPIO_OType = GPIO_OType_OD; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP ; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; + GPIO_Init(GPIOA, &GPIO_InitStructure); + GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_OTG1_FS) ; + + + RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); + RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_OTG_FS, ENABLE) ; +#else // USE_USB_OTG_HS + +#ifdef USE_ULPI_PHY // ULPI + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | + RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOH | + RCC_AHB1Periph_GPIOI, ENABLE); + + + GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_OTG2_HS) ; // D0 + GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_OTG2_HS) ; // CLK + GPIO_PinAFConfig(GPIOB, GPIO_PinSource0, GPIO_AF_OTG2_HS) ; // D1 + GPIO_PinAFConfig(GPIOB, GPIO_PinSource1, GPIO_AF_OTG2_HS) ; // D2 + GPIO_PinAFConfig(GPIOB, GPIO_PinSource5, GPIO_AF_OTG2_HS) ; // D7 + GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_OTG2_HS) ; // D3 + GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_OTG2_HS) ; // D4 + GPIO_PinAFConfig(GPIOB, GPIO_PinSource12, GPIO_AF_OTG2_HS) ; // D5 + GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_OTG2_HS) ; // D6 + GPIO_PinAFConfig(GPIOH, GPIO_PinSource4, GPIO_AF_OTG2_HS) ; // NXT + GPIO_PinAFConfig(GPIOI, GPIO_PinSource11, GPIO_AF_OTG2_HS) ; // DIR + GPIO_PinAFConfig(GPIOC, GPIO_PinSource0, GPIO_AF_OTG2_HS) ; // STP + + // CLK + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 ; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; + GPIO_Init(GPIOA, &GPIO_InitStructure); + + // D0 + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 ; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; + GPIO_Init(GPIOA, &GPIO_InitStructure); + + + + // D1 D2 D3 D4 D5 D6 D7 + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | + GPIO_Pin_5 | GPIO_Pin_10 | + GPIO_Pin_11 | GPIO_Pin_12 | + GPIO_Pin_13 ; + + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; + GPIO_Init(GPIOB, &GPIO_InitStructure); + + + // STP + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 ; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; + GPIO_Init(GPIOC, &GPIO_InitStructure); + + //NXT + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; + GPIO_Init(GPIOH, &GPIO_InitStructure); + + + //DIR + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 ; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; + GPIO_Init(GPIOI, &GPIO_InitStructure); + + + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_OTG_HS | + RCC_AHB1Periph_OTG_HS_ULPI, ENABLE) ; + +#else + +#ifdef USE_I2C_PHY + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB , ENABLE); + /* Configure RESET INTN SCL SDA (Phy/I2C) Pins */ + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | + GPIO_Pin_1 | + GPIO_Pin_10 | + GPIO_Pin_11; + + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; + GPIO_Init(GPIOB, &GPIO_InitStructure); + + GPIO_PinAFConfig(GPIOB, GPIO_PinSource0, GPIO_AF_OTG2_FS) ; + GPIO_PinAFConfig(GPIOB, GPIO_PinSource1, GPIO_AF_OTG2_FS) ; + GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_OTG2_FS) ; + GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_OTG2_FS); + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_OTG_HS, ENABLE) ; + +#else + + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB , ENABLE); + + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | + GPIO_Pin_13 | + GPIO_Pin_14 | + GPIO_Pin_15; + + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; + GPIO_Init(GPIOB, &GPIO_InitStructure); + + GPIO_PinAFConfig(GPIOB, GPIO_PinSource12, GPIO_AF_OTG2_FS) ; + GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_OTG2_FS) ; + GPIO_PinAFConfig(GPIOB, GPIO_PinSource14, GPIO_AF_OTG2_FS) ; + GPIO_PinAFConfig(GPIOB, GPIO_PinSource15, GPIO_AF_OTG2_FS) ; + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_OTG_HS, ENABLE) ; +#endif +#endif +#endif //USB_OTG_HS + + /* Intialize Timer for delay function */ + USB_OTG_BSP_TimeInit(); +} + +/** + * @brief USB_OTG_BSP_EnableInterrupt + * Configures USB Global interrupt + * @param None + * @retval None + */ +void USB_OTG_BSP_EnableInterrupt(USB_OTG_CORE_HANDLE* pdev) +{ + + NVIC_InitTypeDef NVIC_InitStructure; + /* Enable USB Interrupt */ + NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); + + NVIC_InitStructure.NVIC_IRQChannel = OTG_FS_IRQn; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; + NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; + NVIC_Init(&NVIC_InitStructure); + + /* Enable the Overcurrent Interrupt */ + NVIC_InitStructure.NVIC_IRQChannel = HOST_OVRCURR_IRQn; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; + NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; + + NVIC_Init(&NVIC_InitStructure); +} + +/** + * @brief BSP_Drive_VBUS + * Drives the Vbus signal through IO + * @param state : VBUS states + * @retval None + */ +void USB_OTG_BSP_DriveVBUS(USB_OTG_CORE_HANDLE* pdev, uint8_t state) +{ + /* + On-chip 5 V VBUS generation is not supported. For this reason, a charge pump + or, if 5 V are available on the application board, a basic power switch, must + be added externally to drive the 5 V VBUS line. The external charge pump can + be driven by any GPIO output. When the application decides to power on VBUS + using the chosen GPIO, it must also set the port power bit in the host port + control and status register (PPWR bit in OTG_FS_HPRT). + + Bit 12 PPWR: Port power + The application uses this field to control power to this port, and the core + clears this bit on an overcurrent condition. + */ + if (0 == state) { + /* DISABLE is needed on output of the Power Switch */ + GPIO_SetBits(HOST_POWERSW_PORT, HOST_POWERSW_VBUS); + } else { + /*ENABLE the Power Switch by driving the Enable LOW */ + GPIO_ResetBits(HOST_POWERSW_PORT, HOST_POWERSW_VBUS); + } +} + +/** + * @brief USB_OTG_BSP_ConfigVBUS + * Configures the IO for the Vbus and OverCurrent + * @param None + * @retval None + */ +void USB_OTG_BSP_ConfigVBUS(USB_OTG_CORE_HANDLE* pdev) +{ + GPIO_InitTypeDef GPIO_InitStructure; + + + RCC_AHB1PeriphClockCmd(HOST_POWERSW_PORT_RCC, ENABLE); + + + /* Configure Power Switch Vbus Pin */ + GPIO_InitStructure.GPIO_Pin = HOST_POWERSW_VBUS; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; + + GPIO_Init(HOST_POWERSW_PORT, &GPIO_InitStructure); + + /* By Default, DISABLE is needed on output of the Power Switch */ + GPIO_SetBits(HOST_POWERSW_PORT, HOST_POWERSW_VBUS); + + USB_OTG_BSP_mDelay(200); /* Delay is need for stabilising the Vbus Low + in Reset Condition, when Vbus=1 and Reset-button is pressed by user */ + +} + +/** + * @brief USB_OTG_BSP_TimeInit + * Initializes delay unit using Timer2 + * @param None + * @retval None + */ +static void USB_OTG_BSP_TimeInit(void) +{ +#ifdef USE_ACCURATE_TIME + NVIC_InitTypeDef NVIC_InitStructure; + + /* Set the Vector Table base address at 0x08000000 */ +// NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x00); + + /* Configure the Priority Group to 2 bits */ + NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); + + /* Enable the TIM2 gloabal Interrupt */ + NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; + NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; + + NVIC_Init(&NVIC_InitStructure); + + RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); +#endif +} + +/** + * @brief USB_OTG_BSP_uDelay + * This function provides delay time in micro sec + * @param usec : Value of delay required in micro sec + * @retval None + */ +void USB_OTG_BSP_uDelay(const uint32_t usec) +{ + +#ifdef USE_ACCURATE_TIME + BSP_Delay(usec, TIM_USEC_DELAY); +#else + __IO uint32_t count = 0; + const uint32_t utime = (120 * usec / 7); + + do { + if (++count > utime) { + return ; + } + } while (1); + +#endif + +} + +/** + * @brief USB_OTG_BSP_mDelay + * This function provides delay time in milli sec + * @param msec : Value of delay required in milli sec + * @retval None + */ +void USB_OTG_BSP_mDelay(const uint32_t msec) +{ +#ifdef USE_ACCURATE_TIME + BSP_Delay(msec, TIM_MSEC_DELAY); +#else + USB_OTG_BSP_uDelay(msec * 1000); +#endif + +} + +/** + * @brief USB_OTG_BSP_TimerIRQ + * Time base IRQ + * @param None + * @retval None + */ +void USB_OTG_BSP_TimerIRQ(void) +{ +#ifdef USE_ACCURATE_TIME + + if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) { + TIM_ClearITPendingBit(TIM2, TIM_IT_Update); + + if (BSP_delay > 0x00) { + BSP_delay--; + } else { + TIM_Cmd(TIM2, DISABLE); + } + } + +#endif +} + +#ifdef USE_ACCURATE_TIME + +/** + * @brief BSP_Delay + * Delay routine based on TIM2 + * @param nTime : Delay Time + * @param unit : Delay Time unit : mili sec / micro sec + * @retval None + */ +static void BSP_Delay(uint32_t nTime, uint8_t unit) +{ + + BSP_delay = nTime; + BSP_SetTime(unit); + + while (BSP_delay != 0); + + TIM_Cmd(TIM2, DISABLE); +} + +/** + * @brief BSP_SetTime + * Configures TIM2 for delay routine based on TIM2 + * @param unit : msec /usec + * @retval None + */ +static void BSP_SetTime(uint8_t unit) +{ + TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; + + TIM_Cmd(TIM2, DISABLE); + TIM_ITConfig(TIM2, TIM_IT_Update, DISABLE); + + + if (unit == TIM_USEC_DELAY) { + TIM_TimeBaseStructure.TIM_Period = 11; + } else if (unit == TIM_MSEC_DELAY) { + TIM_TimeBaseStructure.TIM_Period = 11999; + } + + TIM_TimeBaseStructure.TIM_Prescaler = 5; + TIM_TimeBaseStructure.TIM_ClockDivision = 0; + TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; + + TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); + TIM_ClearITPendingBit(TIM2, TIM_IT_Update); + + TIM_ARRPreloadConfig(TIM2, ENABLE); + + /* TIM IT enable */ + TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); + + /* TIM2 enable counter */ + TIM_Cmd(TIM2, ENABLE); +} + +#endif + +/** +* @} +*/ + + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/discovery/src/usbh_msc_core.c b/discovery/src/usbh_msc_core.c index 28d99e6..2a3cda3 100644 --- a/discovery/src/usbh_msc_core.c +++ b/discovery/src/usbh_msc_core.c @@ -1,250 +1,276 @@ - -#include "usbh_msc_core.h" -#include "usbh_core.h" - - -static USBH_Status USBH_MSC_InterfaceInit (USB_OTG_CORE_HANDLE *pdev , - void *phost); - -static void USBH_MSC_InterfaceDeInit (USB_OTG_CORE_HANDLE *pdev , - void *phost); - -static USBH_Status USBH_MSC_Handle(USB_OTG_CORE_HANDLE *pdev , - void *phost); - -static USBH_Status USBH_MSC_ClassRequest(USB_OTG_CORE_HANDLE *pdev , - void *phost); - - -extern USB_OTG_CORE_HANDLE USB_OTG_Core; -extern USBH_HOST USB_Host; - - - -USBH_Class_cb_TypeDef USBH_MSC_cb = -{ - USBH_MSC_InterfaceInit, - USBH_MSC_InterfaceDeInit, - USBH_MSC_ClassRequest, - USBH_MSC_Handle, -}; - - -typedef struct -{ - uint8_t hc_num_in; - uint8_t hc_num_out; - uint8_t MSBulkOutEp; - uint8_t MSBulkInEp; - uint16_t MSBulkInEpSize; - uint16_t MSBulkOutEpSize; -} -MSC_Machine_TypeDef; -MSC_Machine_TypeDef MSC_Machine; - - -static USBH_Status USBH_MSC_InterfaceInit ( USB_OTG_CORE_HANDLE *pdev, - void *phost) -{ - USBH_HOST *pphost = phost; - - - - if((pphost->device_prop.Itf_Desc[1].bInterfaceClass == 255) && - (pphost->device_prop.Itf_Desc[1].bInterfaceProtocol == 0) && - (pphost->device_prop.Itf_Desc[1].bInterfaceSubClass == 1)) - { - if(pphost->device_prop.Ep_Desc[0][0].bEndpointAddress & 0x80) - { - MSC_Machine.MSBulkInEp = (pphost->device_prop.Ep_Desc[0][0].bEndpointAddress); - MSC_Machine.MSBulkInEpSize = pphost->device_prop.Ep_Desc[0][0].wMaxPacketSize; - } - else - { - MSC_Machine.MSBulkOutEp = (pphost->device_prop.Ep_Desc[0][0].bEndpointAddress); - MSC_Machine.MSBulkOutEpSize = pphost->device_prop.Ep_Desc[0][0].wMaxPacketSize; - } - - if(pphost->device_prop.Ep_Desc[0][1].bEndpointAddress & 0x80) - { - MSC_Machine.MSBulkInEp = (pphost->device_prop.Ep_Desc[0][1].bEndpointAddress); - MSC_Machine.MSBulkInEpSize = pphost->device_prop.Ep_Desc[0][1].wMaxPacketSize; - } - else - { - MSC_Machine.MSBulkOutEp = (pphost->device_prop.Ep_Desc[0][1].bEndpointAddress); - MSC_Machine.MSBulkOutEpSize = pphost->device_prop.Ep_Desc[0][1].wMaxPacketSize; - } - - MSC_Machine.hc_num_out = USBH_Alloc_Channel(pdev,MSC_Machine.MSBulkOutEp); - MSC_Machine.hc_num_in = USBH_Alloc_Channel(pdev,MSC_Machine.MSBulkInEp); - - USBH_Open_Channel (pdev, - MSC_Machine.hc_num_out, - pphost->device_prop.address, - pphost->device_prop.speed, - EP_TYPE_BULK, - MSC_Machine.MSBulkOutEpSize); - - USBH_Open_Channel (pdev, - MSC_Machine.hc_num_in, - pphost->device_prop.address, - pphost->device_prop.speed, - EP_TYPE_BULK, - MSC_Machine.MSBulkInEpSize); - - } - - else - { - pphost->usr_cb->USBH_USR_DeviceNotSupported(); - } - - return USBH_OK ; - -} - -void USBH_MSC_InterfaceDeInit ( USB_OTG_CORE_HANDLE *pdev, - void *phost) -{ - if ( MSC_Machine.hc_num_out) - { - USB_OTG_HC_Halt(pdev, MSC_Machine.hc_num_out); - USBH_Free_Channel (pdev, MSC_Machine.hc_num_out); - MSC_Machine.hc_num_out = 0; - } - - if ( MSC_Machine.hc_num_in) - { - USB_OTG_HC_Halt(pdev, MSC_Machine.hc_num_in); - USBH_Free_Channel (pdev, MSC_Machine.hc_num_in); - MSC_Machine.hc_num_in = 0; - } -} - -static USBH_Status USBH_MSC_ClassRequest(USB_OTG_CORE_HANDLE *pdev , - void *phost) -{ - - USBH_Status status = USBH_OK ; - return status; -} - -static USBH_Status USBH_MSC_Handle(USB_OTG_CORE_HANDLE *pdev , - void *phost) -{ - USBH_HOST *pphost = phost; - - USBH_Status status = USBH_BUSY; - - if(HCD_IsDeviceConnected(pdev)) - { - int appliStatus = pphost->usr_cb->USBH_USR_MSC_Application(); - if(appliStatus != 0) - { - status = USBH_APPLY_DEINIT; - } - } - return status; - -} - - -volatile uint32_t cnt; -volatile uint32_t cnt_int; -void USBH_LL_systick() { - cnt++; - cnt_int++; -} - - -void USBH_LL_setTimer() { - cnt=0; -} - -uint32_t USBH_LL_getTimer() { - return cnt; -} - - -int USBH_LL_open() { - int timeoutDetect=100; - int timeoutStartup=3000; - cnt_int=0; //reset timer - - while(USB_Host.gState!=HOST_CLASS && cnt_int < timeoutDetect) { - USBH_Process(&USB_OTG_Core, &USB_Host); - } - - if(USB_Host.gState!=HOST_CLASS) { - return -5; // = LIBUSB_ERROR_NOT_FOUND - } - - - cnt_int=0; - while(cnt_int0 && cnt_int>=timeoutMs) { - STM_EVAL_LEDOn(LED3); - return -7; //timeout (error code like with libusb) - - } - return -1; - } - return len; -} - -int USBH_LL_receive(uint8_t *data, uint32_t len, uint16_t timeoutMs) { - - USB_OTG_CORE_HANDLE *pdev = &USB_OTG_Core; - - if(!HCD_IsDeviceConnected(pdev)) return -1; - - USBH_BulkReceiveData (pdev, - data, - len , - MSC_Machine.hc_num_in); - - URB_STATE state; - cnt_int=0; //reset timer - if(timeoutMs==0) timeoutMs=1000; //Force 1s timeout (testwise) - - while((state=HCD_GetURB_State(pdev , MSC_Machine.hc_num_in)) == URB_IDLE && - (timeoutMs==0 || cnt_int < timeoutMs)); - - if(state!=URB_DONE) { - if(timeoutMs>0 && cnt_int>=timeoutMs) { - STM_EVAL_LEDOn(LED3); - return -7; //timeout (error code like with libusb) - } - return -1; - } - return len; -} +/************************************************************************************************************************************** +* Project: discoverpixy +* Website: https://github.com/t-moe/discoverpixy +* Authors: Aaron Schmocker, Timo Lang +* Institution: BFH Bern University of Applied Sciences +* File: discovery/src/usbh_msc_core.c +* +* Version History: +* Date Autor Email SHA Changes +* 2015-04-03 timolang@gmail.com 21dd1e2 Starting to integrate usb branch. Optimized Makefiles +* 2015-04-25 timolang@gmail.com 416883c Pixy&Usb work with the new folder structure now. +* 2015-04-25 timolang@gmail.com 3d1e4b2 Simplified code a bit. Emulator does not work stable when replugging pixy. +* +**************************************************************************************************************************************/ + + +#include "usbh_msc_core.h" +#include "usbh_core.h" + + +static USBH_Status USBH_MSC_InterfaceInit(USB_OTG_CORE_HANDLE* pdev , + void* phost); + +static void USBH_MSC_InterfaceDeInit(USB_OTG_CORE_HANDLE* pdev , + void* phost); + +static USBH_Status USBH_MSC_Handle(USB_OTG_CORE_HANDLE* pdev , + void* phost); + +static USBH_Status USBH_MSC_ClassRequest(USB_OTG_CORE_HANDLE* pdev , + void* phost); + + +extern USB_OTG_CORE_HANDLE USB_OTG_Core; +extern USBH_HOST USB_Host; + + + +USBH_Class_cb_TypeDef USBH_MSC_cb = { + USBH_MSC_InterfaceInit, + USBH_MSC_InterfaceDeInit, + USBH_MSC_ClassRequest, + USBH_MSC_Handle, +}; + + +typedef struct { + uint8_t hc_num_in; + uint8_t hc_num_out; + uint8_t MSBulkOutEp; + uint8_t MSBulkInEp; + uint16_t MSBulkInEpSize; + uint16_t MSBulkOutEpSize; +} +MSC_Machine_TypeDef; +MSC_Machine_TypeDef MSC_Machine; + + +static USBH_Status USBH_MSC_InterfaceInit(USB_OTG_CORE_HANDLE* pdev, + void* phost) +{ + USBH_HOST* pphost = phost; + + + + if ((pphost->device_prop.Itf_Desc[1].bInterfaceClass == 255) && + (pphost->device_prop.Itf_Desc[1].bInterfaceProtocol == 0) && + (pphost->device_prop.Itf_Desc[1].bInterfaceSubClass == 1)) { + if (pphost->device_prop.Ep_Desc[0][0].bEndpointAddress & 0x80) { + MSC_Machine.MSBulkInEp = (pphost->device_prop.Ep_Desc[0][0].bEndpointAddress); + MSC_Machine.MSBulkInEpSize = pphost->device_prop.Ep_Desc[0][0].wMaxPacketSize; + } else { + MSC_Machine.MSBulkOutEp = (pphost->device_prop.Ep_Desc[0][0].bEndpointAddress); + MSC_Machine.MSBulkOutEpSize = pphost->device_prop.Ep_Desc[0][0].wMaxPacketSize; + } + + if (pphost->device_prop.Ep_Desc[0][1].bEndpointAddress & 0x80) { + MSC_Machine.MSBulkInEp = (pphost->device_prop.Ep_Desc[0][1].bEndpointAddress); + MSC_Machine.MSBulkInEpSize = pphost->device_prop.Ep_Desc[0][1].wMaxPacketSize; + } else { + MSC_Machine.MSBulkOutEp = (pphost->device_prop.Ep_Desc[0][1].bEndpointAddress); + MSC_Machine.MSBulkOutEpSize = pphost->device_prop.Ep_Desc[0][1].wMaxPacketSize; + } + + MSC_Machine.hc_num_out = USBH_Alloc_Channel(pdev, MSC_Machine.MSBulkOutEp); + MSC_Machine.hc_num_in = USBH_Alloc_Channel(pdev, MSC_Machine.MSBulkInEp); + + USBH_Open_Channel(pdev, + MSC_Machine.hc_num_out, + pphost->device_prop.address, + pphost->device_prop.speed, + EP_TYPE_BULK, + MSC_Machine.MSBulkOutEpSize); + + USBH_Open_Channel(pdev, + MSC_Machine.hc_num_in, + pphost->device_prop.address, + pphost->device_prop.speed, + EP_TYPE_BULK, + MSC_Machine.MSBulkInEpSize); + + } + + else { + pphost->usr_cb->USBH_USR_DeviceNotSupported(); + } + + return USBH_OK ; + +} + +void USBH_MSC_InterfaceDeInit(USB_OTG_CORE_HANDLE* pdev, + void* phost) +{ + if (MSC_Machine.hc_num_out) { + USB_OTG_HC_Halt(pdev, MSC_Machine.hc_num_out); + USBH_Free_Channel(pdev, MSC_Machine.hc_num_out); + MSC_Machine.hc_num_out = 0; + } + + if (MSC_Machine.hc_num_in) { + USB_OTG_HC_Halt(pdev, MSC_Machine.hc_num_in); + USBH_Free_Channel(pdev, MSC_Machine.hc_num_in); + MSC_Machine.hc_num_in = 0; + } +} + +static USBH_Status USBH_MSC_ClassRequest(USB_OTG_CORE_HANDLE* pdev , + void* phost) +{ + + USBH_Status status = USBH_OK ; + return status; +} + +static USBH_Status USBH_MSC_Handle(USB_OTG_CORE_HANDLE* pdev , + void* phost) +{ + USBH_HOST* pphost = phost; + + USBH_Status status = USBH_BUSY; + + if (HCD_IsDeviceConnected(pdev)) { + int appliStatus = pphost->usr_cb->USBH_USR_MSC_Application(); + + if (appliStatus != 0) { + status = USBH_APPLY_DEINIT; + } + } + + return status; + +} + + +volatile uint32_t cnt; +volatile uint32_t cnt_int; +void USBH_LL_systick() +{ + cnt++; + cnt_int++; +} + + +void USBH_LL_setTimer() +{ + cnt = 0; +} + +uint32_t USBH_LL_getTimer() +{ + return cnt; +} + + +int USBH_LL_open() +{ + int timeoutDetect = 100; + int timeoutStartup = 3000; + cnt_int = 0; //reset timer + + while (USB_Host.gState != HOST_CLASS && cnt_int < timeoutDetect) { + USBH_Process(&USB_OTG_Core, &USB_Host); + } + + if (USB_Host.gState != HOST_CLASS) { + return -5; // = LIBUSB_ERROR_NOT_FOUND + } + + + cnt_int = 0; + + while (cnt_int < timeoutStartup) { //let pixy's led flashing pass + USBH_Process(&USB_OTG_Core, &USB_Host); + } + + return 0; //ok +} + +int USBH_LL_close() +{ + USBH_Process(&USB_OTG_Core, &USB_Host); + return 0; +} + +int USBH_LL_send(const uint8_t* data, uint32_t len, uint16_t timeoutMs) +{ + USB_OTG_CORE_HANDLE* pdev = &USB_OTG_Core; + + if (!HCD_IsDeviceConnected(pdev)) { + return -1; + } + + USBH_BulkSendData(pdev, + (uint8_t*)data, + len , + MSC_Machine.hc_num_out); + + URB_STATE state; + cnt_int = 0; //reset timer + + if (timeoutMs == 0) { + timeoutMs = 1000; //Force 1s timeout (testwise) + } + + while ((state = HCD_GetURB_State(pdev , MSC_Machine.hc_num_out)) == URB_IDLE && + (timeoutMs == 0 || cnt_int < timeoutMs)); + + if (state != URB_DONE) { + if (timeoutMs > 0 && cnt_int >= timeoutMs) { + STM_EVAL_LEDOn(LED3); + return -7; //timeout (error code like with libusb) + + } + + return -1; + } + + return len; +} + +int USBH_LL_receive(uint8_t* data, uint32_t len, uint16_t timeoutMs) +{ + + USB_OTG_CORE_HANDLE* pdev = &USB_OTG_Core; + + if (!HCD_IsDeviceConnected(pdev)) { + return -1; + } + + USBH_BulkReceiveData(pdev, + data, + len , + MSC_Machine.hc_num_in); + + URB_STATE state; + cnt_int = 0; //reset timer + + if (timeoutMs == 0) { + timeoutMs = 1000; //Force 1s timeout (testwise) + } + + while ((state = HCD_GetURB_State(pdev , MSC_Machine.hc_num_in)) == URB_IDLE && + (timeoutMs == 0 || cnt_int < timeoutMs)); + + if (state != URB_DONE) { + if (timeoutMs > 0 && cnt_int >= timeoutMs) { + STM_EVAL_LEDOn(LED3); + return -7; //timeout (error code like with libusb) + } + + return -1; + } + + return len; +} diff --git a/discovery/src/usbh_msc_core.h b/discovery/src/usbh_msc_core.h index 1762829..80616cd 100644 --- a/discovery/src/usbh_msc_core.h +++ b/discovery/src/usbh_msc_core.h @@ -1,27 +1,38 @@ - -/* Define to prevent recursive ----------------------------------------------*/ -#ifndef __USBH_MSC_CORE_H -#define __USBH_MSC_CORE_H - -/* Includes ------------------------------------------------------------------*/ -#include "usbh_core.h" -#include "usbh_stdreq.h" -#include "usb_bsp.h" -#include "usbh_ioreq.h" -#include "usbh_hcs.h" - - -extern USBH_Class_cb_TypeDef USBH_MSC_cb; - -void USBH_LL_systick(); -int USBH_LL_open(); -int USBH_LL_close(); -int USBH_LL_send(const uint8_t *data, uint32_t len, uint16_t timeoutMs); -int USBH_LL_receive(uint8_t *data, uint32_t len, uint16_t timeoutMs); -void USBH_LL_setTimer(); -uint32_t USBH_LL_getTimer(); - - -#endif /* __USBH_MSC_CORE_H */ - - +/************************************************************************************************************************************** +* Project: discoverpixy +* Website: https://github.com/t-moe/discoverpixy +* Authors: Aaron Schmocker, Timo Lang +* Institution: BFH Bern University of Applied Sciences +* File: discovery/src/usbh_msc_core.h +* +* Version History: +* Date Autor Email SHA Changes +* 2015-04-03 timolang@gmail.com 21dd1e2 Starting to integrate usb branch. Optimized Makefiles +* +**************************************************************************************************************************************/ + + +/* Define to prevent recursive ----------------------------------------------*/ +#ifndef __USBH_MSC_CORE_H +#define __USBH_MSC_CORE_H + +/* Includes ------------------------------------------------------------------*/ +#include "usbh_core.h" +#include "usbh_stdreq.h" +#include "usb_bsp.h" +#include "usbh_ioreq.h" +#include "usbh_hcs.h" + + +extern USBH_Class_cb_TypeDef USBH_MSC_cb; + +void USBH_LL_systick(); +int USBH_LL_open(); +int USBH_LL_close(); +int USBH_LL_send(const uint8_t* data, uint32_t len, uint16_t timeoutMs); +int USBH_LL_receive(uint8_t* data, uint32_t len, uint16_t timeoutMs); +void USBH_LL_setTimer(); +uint32_t USBH_LL_getTimer(); + + +#endif /* __USBH_MSC_CORE_H */ diff --git a/discovery/src/usbh_usr.c b/discovery/src/usbh_usr.c index 1d8f8a3..a99d4ce 100644 --- a/discovery/src/usbh_usr.c +++ b/discovery/src/usbh_usr.c @@ -1,229 +1,245 @@ -#include "usbh_usr.h" -#include -#include - - -USBH_Usr_cb_TypeDef USR_Callbacks = -{ - USBH_USR_Init, - USBH_USR_DeInit, - USBH_USR_DeviceAttached, - USBH_USR_ResetDevice, - USBH_USR_DeviceDisconnected, - USBH_USR_OverCurrentDetected, - USBH_USR_DeviceSpeedDetected, - USBH_USR_Device_DescAvailable, - USBH_USR_DeviceAddressAssigned, - USBH_USR_Configuration_DescAvailable, - USBH_USR_Manufacturer_String, - USBH_USR_Product_String, - USBH_USR_SerialNum_String, - USBH_USR_EnumerationDone, - USBH_USR_UserInput, - USBH_USR_MSC_Application, - USBH_USR_DeviceNotSupported, - USBH_USR_UnrecoveredError -}; - - -/* Private function prototypes -----------------------------------------------*/ -/* Private functions ---------------------------------------------------------*/ -bool manufacturer_ok; -bool product_ok; -bool serial_ok; - -/** - * @brief USBH_USR_Init - * @param None - * @retval None - */ -void USBH_USR_Init(void) -{ -} - -/** - * @brief USBH_USR_DeviceAttached - * @param None - * @retval None - */ -void USBH_USR_DeviceAttached(void) -{ - manufacturer_ok=false; - product_ok= false; - serial_ok=false; - - STM_EVAL_LEDOff(LED3); - STM_EVAL_LEDOn(LED4); -} - -/** - * @brief USBH_USR_UnrecoveredError - * @param None - * @retval None - */ -void USBH_USR_UnrecoveredError (void) -{ -} - -/** - * @brief USBH_DisconnectEvent - * Device disconnect event - * @param None - * @retval Staus - */ -void USBH_USR_DeviceDisconnected (void) -{ - STM_EVAL_LEDOff(LED4); -} - -/** - * @brief USBH_USR_ResetUSBDevice - * @param None - * @retval None - */ -void USBH_USR_ResetDevice(void) -{ - /* callback for USB-Reset */ -} - - -/** - * @brief USBH_USR_DeviceSpeedDetected - * Displays the message on LCD for device speed - * @param Device speed: - * @retval None - */ -void USBH_USR_DeviceSpeedDetected(uint8_t DeviceSpeed) -{ -} - -/** - * @brief USBH_USR_Device_DescAvailable - * @param device descriptor - * @retval None - */ -void USBH_USR_Device_DescAvailable(void *DeviceDesc) -{ - /* callback for device descriptor */ -} - -/** - * @brief USBH_USR_DeviceAddressAssigned - * USB device is successfully assigned the Address - * @param None - * @retval None - */ -void USBH_USR_DeviceAddressAssigned(void) -{ - /* callback for device successfully assigned the Address */ -} - -/** - * @brief USBH_USR_Conf_Desc - * @param Configuration descriptor - * @retval None - */ -void USBH_USR_Configuration_DescAvailable(USBH_CfgDesc_TypeDef * cfgDesc, - USBH_InterfaceDesc_TypeDef *itfDesc, - USBH_EpDesc_TypeDef *epDesc) -{ - /* callback for configuration descriptor */ -} - -/** - * @brief USBH_USR_Manufacturer_String - * @param Manufacturer String - * @retval None - */ -void USBH_USR_Manufacturer_String(void *ManufacturerString) -{ - manufacturer_ok = strcmp((char*)ManufacturerString,"Charmed Labs") == 0; -} - -/** - * @brief USBH_USR_Product_String - * @param Product String - * @retval None - */ -void USBH_USR_Product_String(void *ProductString) -{ - product_ok = strcmp((char*)ProductString,"Pixy") == 0; -} - -/** - * @brief USBH_USR_SerialNum_String - * @param SerialNum_String - * @retval None - */ -void USBH_USR_SerialNum_String(void *SerialNumString) -{ - serial_ok = strcmp((char*)SerialNumString,"DEMO 0.0") == 0; -} - -/** - * @brief EnumerationDone - * User response request is displayed to ask application jump to class - * @param None - * @retval None - */ -void USBH_USR_EnumerationDone(void) -{ - -} - -/** - * @brief USBH_USR_DeviceNotSupported - * Device is not supported - * @param None - * @retval None - */ -void USBH_USR_DeviceNotSupported(void) -{ -} - - -/** - * @brief USBH_USR_UserInput - * User Action for application state entry - * @param None - * @retval USBH_USR_Status : User response for key button - */ -USBH_USR_Status USBH_USR_UserInput(void) -{ - if(product_ok&&manufacturer_ok&&serial_ok) { - return USBH_USR_RESP_OK; - } - return USBH_USR_NO_RESP; -} - -/** - * @brief USBH_USR_OverCurrentDetected - * Over Current Detected on VBUS - * @param None - * @retval None - */ -void USBH_USR_OverCurrentDetected (void) -{ -} - -/** - * @brief USBH_USR_MSC_Application - * @param None - * @retval Staus - */ -int USBH_USR_MSC_Application(void) -{ - return 0; -} - -/** - * @brief USBH_USR_DeInit - * Deint User state and associated variables - * @param None - * @retval None - */ -void USBH_USR_DeInit(void) -{ - -} - +/************************************************************************************************************************************** +* Project: discoverpixy +* Website: https://github.com/t-moe/discoverpixy +* Authors: Aaron Schmocker, Timo Lang +* Institution: BFH Bern University of Applied Sciences +* File: discovery/src/usbh_usr.c +* +* Version History: +* Date Autor Email SHA Changes +* 2015-04-03 timolang@gmail.com 21dd1e2 Starting to integrate usb branch. Optimized Makefiles +* 2015-04-03 timolang@gmail.com 9a1d12a Refactored discovery, to use new project structure. Almost ready. +* 2015-04-25 timolang@gmail.com 416883c Pixy&Usb work with the new folder structure now. +* 2015-04-25 timolang@gmail.com 3d1e4b2 Simplified code a bit. Emulator does not work stable when replugging pixy. +* 2015-06-02 timolang@gmail.com 16bfdad Removed conflicting led usage from usb code. +* +**************************************************************************************************************************************/ + +#include "usbh_usr.h" +#include +#include + + +USBH_Usr_cb_TypeDef USR_Callbacks = { + USBH_USR_Init, + USBH_USR_DeInit, + USBH_USR_DeviceAttached, + USBH_USR_ResetDevice, + USBH_USR_DeviceDisconnected, + USBH_USR_OverCurrentDetected, + USBH_USR_DeviceSpeedDetected, + USBH_USR_Device_DescAvailable, + USBH_USR_DeviceAddressAssigned, + USBH_USR_Configuration_DescAvailable, + USBH_USR_Manufacturer_String, + USBH_USR_Product_String, + USBH_USR_SerialNum_String, + USBH_USR_EnumerationDone, + USBH_USR_UserInput, + USBH_USR_MSC_Application, + USBH_USR_DeviceNotSupported, + USBH_USR_UnrecoveredError +}; + + +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ +bool manufacturer_ok; +bool product_ok; +bool serial_ok; + +/** + * @brief USBH_USR_Init + * @param None + * @retval None + */ +void USBH_USR_Init(void) +{ +} + +/** + * @brief USBH_USR_DeviceAttached + * @param None + * @retval None + */ +void USBH_USR_DeviceAttached(void) +{ + manufacturer_ok = false; + product_ok = false; + serial_ok = false; + + STM_EVAL_LEDOff(LED3); + STM_EVAL_LEDOn(LED4); +} + +/** + * @brief USBH_USR_UnrecoveredError + * @param None + * @retval None + */ +void USBH_USR_UnrecoveredError(void) +{ +} + +/** + * @brief USBH_DisconnectEvent + * Device disconnect event + * @param None + * @retval Staus + */ +void USBH_USR_DeviceDisconnected(void) +{ + STM_EVAL_LEDOff(LED4); +} + +/** + * @brief USBH_USR_ResetUSBDevice + * @param None + * @retval None + */ +void USBH_USR_ResetDevice(void) +{ + /* callback for USB-Reset */ +} + + +/** + * @brief USBH_USR_DeviceSpeedDetected + * Displays the message on LCD for device speed + * @param Device speed: + * @retval None + */ +void USBH_USR_DeviceSpeedDetected(uint8_t DeviceSpeed) +{ +} + +/** + * @brief USBH_USR_Device_DescAvailable + * @param device descriptor + * @retval None + */ +void USBH_USR_Device_DescAvailable(void* DeviceDesc) +{ + /* callback for device descriptor */ +} + +/** + * @brief USBH_USR_DeviceAddressAssigned + * USB device is successfully assigned the Address + * @param None + * @retval None + */ +void USBH_USR_DeviceAddressAssigned(void) +{ + /* callback for device successfully assigned the Address */ +} + +/** + * @brief USBH_USR_Conf_Desc + * @param Configuration descriptor + * @retval None + */ +void USBH_USR_Configuration_DescAvailable(USBH_CfgDesc_TypeDef* cfgDesc, + USBH_InterfaceDesc_TypeDef* itfDesc, + USBH_EpDesc_TypeDef* epDesc) +{ + /* callback for configuration descriptor */ +} + +/** + * @brief USBH_USR_Manufacturer_String + * @param Manufacturer String + * @retval None + */ +void USBH_USR_Manufacturer_String(void* ManufacturerString) +{ + manufacturer_ok = strcmp((char*)ManufacturerString, "Charmed Labs") == 0; +} + +/** + * @brief USBH_USR_Product_String + * @param Product String + * @retval None + */ +void USBH_USR_Product_String(void* ProductString) +{ + product_ok = strcmp((char*)ProductString, "Pixy") == 0; +} + +/** + * @brief USBH_USR_SerialNum_String + * @param SerialNum_String + * @retval None + */ +void USBH_USR_SerialNum_String(void* SerialNumString) +{ + serial_ok = strcmp((char*)SerialNumString, "DEMO 0.0") == 0; +} + +/** + * @brief EnumerationDone + * User response request is displayed to ask application jump to class + * @param None + * @retval None + */ +void USBH_USR_EnumerationDone(void) +{ + +} + +/** + * @brief USBH_USR_DeviceNotSupported + * Device is not supported + * @param None + * @retval None + */ +void USBH_USR_DeviceNotSupported(void) +{ +} + + +/** + * @brief USBH_USR_UserInput + * User Action for application state entry + * @param None + * @retval USBH_USR_Status : User response for key button + */ +USBH_USR_Status USBH_USR_UserInput(void) +{ + if (product_ok && manufacturer_ok && serial_ok) { + return USBH_USR_RESP_OK; + } + + return USBH_USR_NO_RESP; +} + +/** + * @brief USBH_USR_OverCurrentDetected + * Over Current Detected on VBUS + * @param None + * @retval None + */ +void USBH_USR_OverCurrentDetected(void) +{ +} + +/** + * @brief USBH_USR_MSC_Application + * @param None + * @retval Staus + */ +int USBH_USR_MSC_Application(void) +{ + return 0; +} + +/** + * @brief USBH_USR_DeInit + * Deint User state and associated variables + * @param None + * @retval None + */ +void USBH_USR_DeInit(void) +{ + +} diff --git a/discovery/src/usbh_usr.h b/discovery/src/usbh_usr.h index 3579dee..1da61c5 100644 --- a/discovery/src/usbh_usr.h +++ b/discovery/src/usbh_usr.h @@ -1,51 +1,60 @@ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __USH_USR_H__ -#define __USH_USR_H__ - -#ifdef __cplusplus - extern "C" { -#endif - -/* Includes ------------------------------------------------------------------*/ -#include "stm32f4_discovery.h" -#include "usbh_core.h" -#include - - -/* Exported macros -----------------------------------------------------------*/ -/* Exported variables --------------------------------------------------------*/ -extern USBH_Usr_cb_TypeDef USR_Callbacks; - -/* Exported functions ------------------------------------------------------- */ -void USBH_USR_Init(void); -void USBH_USR_DeviceAttached(void); -void USBH_USR_ResetDevice(void); -void USBH_USR_DeviceDisconnected (void); -void USBH_USR_OverCurrentDetected (void); -void USBH_USR_DeviceSpeedDetected(uint8_t DeviceSpeed); -void USBH_USR_Device_DescAvailable(void *); -void USBH_USR_DeviceAddressAssigned(void); -void USBH_USR_Configuration_DescAvailable(USBH_CfgDesc_TypeDef * cfgDesc, - USBH_InterfaceDesc_TypeDef *itfDesc, - USBH_EpDesc_TypeDef *epDesc); -void USBH_USR_Manufacturer_String(void *); -void USBH_USR_Product_String(void *); -void USBH_USR_SerialNum_String(void *); -void USBH_USR_EnumerationDone(void); -USBH_USR_Status USBH_USR_UserInput(void); -int USBH_USR_MSC_Application(void); -void USBH_USR_DeInit(void); -void USBH_USR_DeviceNotSupported(void); -void USBH_USR_UnrecoveredError(void); -#ifdef __cplusplus -} -#endif - -#endif /*__USH_USR_H__*/ - -/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ - - - - +/************************************************************************************************************************************** +* Project: discoverpixy +* Website: https://github.com/t-moe/discoverpixy +* Authors: Aaron Schmocker, Timo Lang +* Institution: BFH Bern University of Applied Sciences +* File: discovery/src/usbh_usr.h +* +* Version History: +* Date Autor Email SHA Changes +* 2015-04-03 timolang@gmail.com 21dd1e2 Starting to integrate usb branch. Optimized Makefiles +* +**************************************************************************************************************************************/ + + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USH_USR_H__ +#define __USH_USR_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4_discovery.h" +#include "usbh_core.h" +#include + + +/* Exported macros -----------------------------------------------------------*/ +/* Exported variables --------------------------------------------------------*/ +extern USBH_Usr_cb_TypeDef USR_Callbacks; + +/* Exported functions ------------------------------------------------------- */ +void USBH_USR_Init(void); +void USBH_USR_DeviceAttached(void); +void USBH_USR_ResetDevice(void); +void USBH_USR_DeviceDisconnected(void); +void USBH_USR_OverCurrentDetected(void); +void USBH_USR_DeviceSpeedDetected(uint8_t DeviceSpeed); +void USBH_USR_Device_DescAvailable(void*); +void USBH_USR_DeviceAddressAssigned(void); +void USBH_USR_Configuration_DescAvailable(USBH_CfgDesc_TypeDef* cfgDesc, + USBH_InterfaceDesc_TypeDef* itfDesc, + USBH_EpDesc_TypeDef* epDesc); +void USBH_USR_Manufacturer_String(void*); +void USBH_USR_Product_String(void*); +void USBH_USR_SerialNum_String(void*); +void USBH_USR_EnumerationDone(void); +USBH_USR_Status USBH_USR_UserInput(void); +int USBH_USR_MSC_Application(void); +void USBH_USR_DeInit(void); +void USBH_USR_DeviceNotSupported(void); +void USBH_USR_UnrecoveredError(void); +#ifdef __cplusplus +} +#endif + +#endif /*__USH_USR_H__*/ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/doc/.gitignore b/doc/.gitignore index 8709cfb..fa8d7aa 100644 --- a/doc/.gitignore +++ b/doc/.gitignore @@ -1,2 +1,3 @@ *.*~ html/ +latex/ diff --git a/doc/docu.odt b/doc/docu.odt index e400a42..f227209 100644 Binary files a/doc/docu.odt and b/doc/docu.odt differ diff --git a/doc/docu.pdf b/doc/docu.pdf index 4e45d7d..3afa8cb 100644 Binary files a/doc/docu.pdf and b/doc/docu.pdf differ diff --git a/doc/refman.pdf b/doc/refman.pdf new file mode 100644 index 0000000..d4f6076 Binary files /dev/null and b/doc/refman.pdf differ diff --git a/emulator/qt/ll_filesystem.cpp b/emulator/qt/ll_filesystem.cpp index 8d1d47f..03f476c 100644 --- a/emulator/qt/ll_filesystem.cpp +++ b/emulator/qt/ll_filesystem.cpp @@ -1,5 +1,19 @@ +/************************************************************************************************************************************** +* Project: discoverpixy +* Website: https://github.com/t-moe/discoverpixy +* Authors: Aaron Schmocker, Timo Lang +* Institution: BFH Bern University of Applied Sciences +* File: emulator/qt/ll_filesystem.cpp +* +* Version History: +* Date Autor Email SHA Changes +* 2015-05-10 timolang@gmail.com e2bce8f Added filesystem module, tests and implementation for it in emulator. +* 2015-06-07 timolang@gmail.com 4b5768c Improved Comments in whole emulator. Finalized emulator section in docu. +* +**************************************************************************************************************************************/ + extern "C" { - #include "ll_filesystem.h" +#include "ll_filesystem.h" } #include #include @@ -7,69 +21,78 @@ extern "C" { #include #include -QDir rootdir ("./emulated"); //Create a QDir which points to the "root" of the emulated filesystem +QDir rootdir("./emulated"); //Create a QDir which points to the "root" of the emulated filesystem -bool ll_filesystem_init() { - if(!rootdir.exists()) { //if our root dir is nonexistent +bool ll_filesystem_init() +{ + if (!rootdir.exists()) { //if our root dir is nonexistent qWarning() << "Filesystem can not be emulated because the 'emulated' folder does not exist"; return false; //mark an error } + return true; } -DIRECTORY_STRUCT* ll_filesystem_dir_open(const char* path) { +DIRECTORY_STRUCT* ll_filesystem_dir_open(const char* path) +{ QDir d(rootdir); //Make a copy of the rootdir QDir instance d.cd(path); //Change the directory to the passed path - if(!d.exists()) { + + if (!d.exists()) { return NULL; //mark an error } DIRECTORY_STRUCT* directory = new DIRECTORY_STRUCT(); //get all files and directories which are important to us. Filter out . and .. symlinks (linux) - QFileInfoList entries = d.entryInfoList(QDir::NoDotAndDotDot|QDir::Files|QDir::Dirs|QDir::Readable|QDir::Writable|QDir::Hidden|QDir::System); + QFileInfoList entries = d.entryInfoList(QDir::NoDotAndDotDot | QDir::Files | QDir::Dirs | QDir::Readable | QDir::Writable | QDir::Hidden | QDir::System); //Fill the directory structure for the user directory->path = path; directory->num_files = entries.count(); directory->files = new FILE_STRUCT[directory->num_files]; //allocate array of file structs - for(int i=0; ifiles[i]); //get the pointer to the current filestruct (which should be filled) entry->fattrib = 0; - entry->fname = new char[fi.fileName().length()+1]; //reserve memory for filename - strcpy(entry->fname,fi.fileName().toStdString().c_str()); //copy filename into struct - if(fi.isDir()) { //it's a direcory - entry->fattrib|=F_DIR; //set directory attribute + entry->fname = new char[fi.fileName().length() + 1]; //reserve memory for filename + strcpy(entry->fname, fi.fileName().toStdString().c_str()); //copy filename into struct + + if (fi.isDir()) { //it's a direcory + entry->fattrib |= F_DIR; //set directory attribute entry->fsize = 0; } else { //it's a file entry->fsize = fi.size(); //set filesize } - if(fi.isHidden()) { //the file is hidden - entry->fattrib|=F_HID; + + if (fi.isHidden()) { //the file is hidden + entry->fattrib |= F_HID; } - if(!fi.isWritable()) { //the file is not writable - entry->fattrib|=F_RDO; //set readonly attribue + + if (!fi.isWritable()) { //the file is not writable + entry->fattrib |= F_RDO; //set readonly attribue } //Set date & time of file in structure QDateTime dt = fi.lastModified(); - entry->fdate.year = dt.date().year()-1980; //year is realtive to 1980 + entry->fdate.year = dt.date().year() - 1980; //year is realtive to 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; + entry->ftime.sec = dt.time().second() / 2; } return directory; //return filled directory struct } -void ll_filesystem_dir_close(DIRECTORY_STRUCT* dir) { - if(dir!=NULL) { //passed handle is valid - for(int i=0; inum_files; i++) { //foreach file +void ll_filesystem_dir_close(DIRECTORY_STRUCT* dir) +{ + if (dir != NULL) { //passed handle is valid + for (int i = 0; i < dir->num_files; i++) { //foreach file delete dir->files[i].fname; //delete filename buffer } + delete[] dir->files; //delete file array delete dir; //delete structure itself } @@ -81,17 +104,20 @@ struct QT_FILE_HANDLE : FILE_HANDLE { //..derived from the FILE_HANDLE (of the F }; -FILE_HANDLE* ll_filesystem_file_open(const char* filename) { - if(!rootdir.exists()) { +FILE_HANDLE* ll_filesystem_file_open(const char* filename) +{ + if (!rootdir.exists()) { return NULL; } + QString filepath = rootdir.absoluteFilePath(filename); //get the absolute path to the requested file QFile* f = new QFile(filepath); //create a QFile instance to the requested file - if(!f->exists()) { //File does not exist + + if (!f->exists()) { //File does not exist return NULL; //mark error } - if(!f->open(QFile::ReadWrite)) { //try to open the file, it it fails then ... + if (!f->open(QFile::ReadWrite)) { //try to open the file, it it fails then ... return NULL; //... mark error } @@ -100,35 +126,42 @@ FILE_HANDLE* ll_filesystem_file_open(const char* filename) { QT_FILE_HANDLE* fh = new QT_FILE_HANDLE(); //Create Structure to return to user fh->file = f; fh->fname = filename; - fh->fpos =0; + fh->fpos = 0; fh->fsize = f->size(); return fh; } -void ll_filesystem_file_close(FILE_HANDLE* handle) { - if(handle!=NULL) { //passed handle is valid +void ll_filesystem_file_close(FILE_HANDLE* handle) +{ + if (handle != NULL) { //passed handle is valid QT_FILE_HANDLE* fh = static_cast(handle); //cast pointer to QT_FILE_HANDLE - if(fh->file->isOpen()) { //if the file is still open + + if (fh->file->isOpen()) { //if the file is still open fh->file->close(); //close the file } + delete fh->file; //delete QFile instance delete fh; //delete the fle } } -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); //cast pointer to QT_FILE_HANDLE - if(!fh->file->isOpen()) { //file is not open - return F_DISKERROR; - } - if(offset>=fh->file->size()) { //offset exeeds filesize +FILE_STATUS ll_filesystem_file_seek(FILE_HANDLE* handle, uint32_t offset) +{ + if (handle == NULL) { return F_INVALIDPARAM; } - if(fh->file->seek(offset)) { //try to seek to desired offset + QT_FILE_HANDLE* fh = static_cast(handle); //cast pointer to QT_FILE_HANDLE + + if (!fh->file->isOpen()) { //file is not open + return F_DISKERROR; + } + + if (offset >= fh->file->size()) { //offset exeeds filesize + return F_INVALIDPARAM; + } + + if (fh->file->seek(offset)) { //try to seek to desired offset fh->fpos = offset; //update offset in FILE_HANDLE (for user) return F_OK; } else { //seek failed @@ -136,49 +169,64 @@ 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) { - if(handle==NULL || buf==NULL) { +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); //cast pointer to QT_FILE_HANDLE - if(!fh->file->isOpen()) { //file is not open + + if (!fh->file->isOpen()) { //file is not open return F_DISKERROR; } - if(!fh->file->isReadable()) { //file is not readable + + if (!fh->file->isReadable()) { //file is not readable return F_EACCESS; } - qint64 bytesRead = fh->file->read((char*)buf,size); //try to read desired amount of bytes - if(bytesRead<0) { //read failed + + qint64 bytesRead = fh->file->read((char*)buf, size); //try to read desired amount of bytes + + if (bytesRead < 0) { //read failed return F_DISKERROR; } - fh->fpos+=bytesRead; //increase file position (for user) - if(bytesRead!=size) { //we got less bytes than expected + + fh->fpos += bytesRead; //increase file position (for user) + + if (bytesRead != size) { //we got less bytes than expected return F_EOF; //we reached the end of the file } else { return F_OK; } } -FILE_STATUS ll_filesystem_file_write(FILE_HANDLE* handle, uint8_t* buf, uint32_t size) { - if(handle==NULL) { +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); //cast pointer to QT_FILE_HANDLE - if(!fh->file->isOpen()) { //file is not open + + if (!fh->file->isOpen()) { //file is not open return F_DISKERROR; } - if(!fh->file->isWritable()) { //file is not writable + + if (!fh->file->isWritable()) { //file is not writable return F_EACCESS; } - qint64 bytesWritten = fh->file->write((char*)buf,size); //try to write desired amount of bytes - if(bytesWritten<0) { //write failed + + qint64 bytesWritten = fh->file->write((char*)buf, size); //try to write desired amount of bytes + + if (bytesWritten < 0) { //write failed return F_DISKERROR; } - fh->fpos+=bytesWritten; //increase file position (for user) - if(bytesWritten!=size) { //we wrote less bytes than expected + + fh->fpos += bytesWritten; //increase file position (for user) + + if (bytesWritten != size) { //we wrote less bytes than expected return F_EOF; //we reached the end of the file } else { return F_OK; } } - diff --git a/emulator/qt/ll_system.cpp b/emulator/qt/ll_system.cpp index 68efd72..7b0734c 100644 --- a/emulator/qt/ll_system.cpp +++ b/emulator/qt/ll_system.cpp @@ -1,3 +1,21 @@ +/************************************************************************************************************************************** +* Project: discoverpixy +* Website: https://github.com/t-moe/discoverpixy +* Authors: Aaron Schmocker, Timo Lang +* Institution: BFH Bern University of Applied Sciences +* File: emulator/qt/ll_system.cpp +* +* Version History: +* Date Autor Email SHA Changes +* 2015-04-03 timolang@gmail.com 1f2af9f Added more tft functions to common and emulator. Fixed eventloop. +* 2015-04-03 timolang@gmail.com cab8609 Integrated pixy into emulator. Pixy is no longer in the common/libs folder but in emulator/libs and discovery/libs +* 2015-04-25 timolang@gmail.com 3d1e4b2 Simplified code a bit. Emulator does not work stable when replugging pixy. +* 2015-04-25 timolang@gmail.com 0858b0d Fixed some bugs when receiving large data. +* 2015-05-09 timolang@gmail.com c652b6b Improved Emulator Gui +* 2015-06-07 timolang@gmail.com 4b5768c Improved Comments in whole emulator. Finalized emulator section in docu. +* +**************************************************************************************************************************************/ + #include #include @@ -5,19 +23,23 @@ extern "C" { #include "ll_system.h" } -bool ll_system_init() { +bool ll_system_init() +{ return true; //nothing to initialize here, apart from the stuff which is done in the main method. } -void ll_system_delay(uint32_t msec) { - QThread::msleep(msec); //Let the app_process() Thread sleep +void ll_system_delay(uint32_t msec) +{ + QThread::msleep(msec); //Let the app_process() Thread sleep } -void ll_system_process() { - QApplication::processEvents(); //Process pending qt events - QThread::msleep(1); //Sleep for 1ms, to keep the cpu load down +void ll_system_process() +{ + QApplication::processEvents(); //Process pending qt events + QThread::msleep(1); //Sleep for 1ms, to keep the cpu load down } -void ll_system_toggle_led() { +void ll_system_toggle_led() +{ //No led emulated :( } diff --git a/emulator/qt/ll_tft.cpp b/emulator/qt/ll_tft.cpp index 5963104..7003991 100644 --- a/emulator/qt/ll_tft.cpp +++ b/emulator/qt/ll_tft.cpp @@ -1,3 +1,22 @@ +/************************************************************************************************************************************** +* Project: discoverpixy +* Website: https://github.com/t-moe/discoverpixy +* Authors: Aaron Schmocker, Timo Lang +* Institution: BFH Bern University of Applied Sciences +* File: emulator/qt/ll_tft.cpp +* +* Version History: +* Date Autor Email SHA Changes +* 2015-04-03 timolang@gmail.com 51089aa Refactored Project Structure for use with emulator +* 2015-04-03 timolang@gmail.com 1f2af9f Added more tft functions to common and emulator. Fixed eventloop. +* 2015-04-03 timolang@gmail.com 1aa9194 Fixed Drawing of rects in Emulator. Got frames from pixy to emulator. Slooooow. +* 2015-04-27 aaron@duckpond.ch aed90ef Drawcircle added (emulator) +* 2015-04-27 timolang@gmail.com e249fb2 Added font support +* 2015-05-15 timolang@gmail.com b08a897 Added tft method to draw a bmp from filesystem. Added another font to emulator. +* 2015-06-07 timolang@gmail.com 4b5768c Improved Comments in whole emulator. Finalized emulator section in docu. +* +**************************************************************************************************************************************/ + #include "mainwindow.h" extern "C" { @@ -6,50 +25,60 @@ extern "C" { MainWindow* mainwindow; -bool ll_tft_init() { - mainwindow = new MainWindow(); //create the designed window - mainwindow->show(); //open it (non blocking) - return true; +bool ll_tft_init() +{ + mainwindow = new MainWindow(); //create the designed window + mainwindow->show(); //open it (non blocking) + return true; } //the following functions redirect the call to the mainwindow, to a function with the same signature -void ll_tft_draw_line(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color) { - mainwindow->draw_line(x1,y1,x2,y2,color); +void ll_tft_draw_line(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color) +{ + mainwindow->draw_line(x1, y1, x2, y2, color); } -void ll_tft_clear(uint16_t color) { +void ll_tft_clear(uint16_t color) +{ mainwindow->clear(color); } -void ll_tft_draw_pixel(uint16_t x,uint16_t y,uint16_t color) { - mainwindow->draw_pixel(x,y,color); +void ll_tft_draw_pixel(uint16_t x, uint16_t y, uint16_t color) +{ + mainwindow->draw_pixel(x, y, color); } -void ll_tft_draw_rectangle(uint16_t x1,uint16_t y1,uint16_t x2,uint16_t y2, uint16_t color) { - mainwindow->draw_rectangle(x1,y1,x2,y2,color); +void ll_tft_draw_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color) +{ + mainwindow->draw_rectangle(x1, y1, x2, y2, color); } -void ll_tft_fill_rectangle(uint16_t x1,uint16_t y1,uint16_t x2,uint16_t y2, uint16_t color) { - mainwindow->fill_rectangle(x1,y1,x2,y2,color); +void ll_tft_fill_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color) +{ + mainwindow->fill_rectangle(x1, y1, x2, y2, color); } -void ll_tft_draw_bitmap_unscaled(uint16_t x, uint16_t y, uint16_t width, uint16_t height, const uint16_t* dat) { - mainwindow->draw_bitmap_unscaled(x,y,width,height,dat); +void ll_tft_draw_bitmap_unscaled(uint16_t x, uint16_t y, uint16_t width, uint16_t height, const uint16_t* dat) +{ + mainwindow->draw_bitmap_unscaled(x, y, width, height, dat); } -void ll_tft_draw_circle(uint16_t x, uint16_t y, uint16_t r, uint16_t color) { - mainwindow->draw_circle(x,y,r,color); +void ll_tft_draw_circle(uint16_t x, uint16_t y, uint16_t r, uint16_t color) +{ + mainwindow->draw_circle(x, y, r, color); } -uint8_t ll_tft_num_fonts() { +uint8_t ll_tft_num_fonts() +{ return 2; //we have two fonts (see below) } //Helper function to get the QFont to the corresponding font number //Note: only return monospaced fonts!!! -QFont get_font(uint8_t fontnum) { +QFont get_font(uint8_t fontnum) +{ switch(fontnum) { case 0: return QFont("Courier New",8); @@ -61,23 +90,37 @@ QFont get_font(uint8_t fontnum) { } -uint8_t ll_tft_font_height(uint8_t fontnum) { +uint8_t ll_tft_font_height(uint8_t fontnum) +{ QFont f = get_font(fontnum); - if(f == QFont()) return -1; + + if (f == QFont()) { + return -1; + } + QFontMetrics m(f); //use font metcris object to calculate height of font return m.height(); } -uint8_t ll_tft_font_width(uint8_t fontnum) { +uint8_t ll_tft_font_width(uint8_t fontnum) +{ QFont f = get_font(fontnum); - if(f == QFont()) return -1; + + if (f == QFont()) { + return -1; + } + QFontMetrics m(f); //use font metcris object to calculate width of font return m.averageCharWidth(); } -void ll_tft_draw_char(uint16_t x, uint16_t y, uint16_t color, uint16_t bgcolor, uint8_t font, char c) { +void ll_tft_draw_char(uint16_t x, uint16_t y, uint16_t color, uint16_t bgcolor, uint8_t font, char c) +{ QFont f = get_font(font); - if(f == QFont()) return; //if the font is the default-font, we want to abort. - mainwindow->draw_char(x,y,color,bgcolor,f,c); -} + if (f == QFont()) { + return; //if the font is the default-font, we want to abort. + } + + mainwindow->draw_char(x, y, color, bgcolor, f, c); +} diff --git a/emulator/qt/ll_touch.cpp b/emulator/qt/ll_touch.cpp index cf978d9..996d3a6 100644 --- a/emulator/qt/ll_touch.cpp +++ b/emulator/qt/ll_touch.cpp @@ -1,10 +1,25 @@ +/************************************************************************************************************************************** +* Project: discoverpixy +* Website: https://github.com/t-moe/discoverpixy +* Authors: Aaron Schmocker, Timo Lang +* Institution: BFH Bern University of Applied Sciences +* File: emulator/qt/ll_touch.cpp +* +* Version History: +* Date Autor Email SHA Changes +* 2015-04-27 timolang@gmail.com 259d446 Added touch support to emulator. Implemented basic touch function. +* 2015-06-01 timolang@gmail.com eb573bc Finalized calibration. Fixed a bug in screen module. +* +**************************************************************************************************************************************/ + extern "C" { #include "ll_touch.h" #include "touch.h" } -bool ll_touch_init() { +bool ll_touch_init() +{ touch_set_value_convert_mode(false); //tell the touch module that we don't need calibration or value conversion return true; } diff --git a/emulator/qt/main.cpp b/emulator/qt/main.cpp index 96937c1..9a73892 100644 --- a/emulator/qt/main.cpp +++ b/emulator/qt/main.cpp @@ -1,3 +1,21 @@ +/************************************************************************************************************************************** +* Project: discoverpixy +* Website: https://github.com/t-moe/discoverpixy +* Authors: Aaron Schmocker, Timo Lang +* Institution: BFH Bern University of Applied Sciences +* File: emulator/qt/main.cpp +* +* Version History: +* Date Autor Email SHA Changes +* 2015-04-03 timolang@gmail.com 51089aa Refactored Project Structure for use with emulator +* 2015-04-03 timolang@gmail.com 1f2af9f Added more tft functions to common and emulator. Fixed eventloop. +* 2015-04-03 timolang@gmail.com cab8609 Integrated pixy into emulator. Pixy is no longer in the common/libs folder but in emulator/libs and discovery/libs +* 2015-04-07 timolang@gmail.com 383fc86 Simplified Emulator (main) +* 2015-04-25 timolang@gmail.com 3d1e4b2 Simplified code a bit. Emulator does not work stable when replugging pixy. +* 2015-06-07 timolang@gmail.com 4b5768c Improved Comments in whole emulator. Finalized emulator section in docu. +* +**************************************************************************************************************************************/ + #include #include @@ -7,19 +25,18 @@ extern "C" { void app_process(); //Processes one eventloop of the app } -void app_loop() { - while(!QApplication::closingDown()) { //as long as the application is not terminating +void app_loop() +{ + while (!QApplication::closingDown()) { //as long as the application is not terminating app_process(); //let the application process it's events } } -int main(int argc, char* argv[]) { - QApplication app(argc,argv); //Process qt-specific commandline arguments and create event loop +int main(int argc, char* argv[]) +{ + QApplication app(argc, argv); //Process qt-specific commandline arguments and create event loop app_init(); //Let the application initialize it self QtConcurrent::run(&app_loop); //Start a thread that executes app_loop return app.exec(); //Run the event loop until the last window is closed. } - - - diff --git a/emulator/qt/mainwindow.cpp b/emulator/qt/mainwindow.cpp index 99b2ae2..d04e133 100644 --- a/emulator/qt/mainwindow.cpp +++ b/emulator/qt/mainwindow.cpp @@ -1,3 +1,29 @@ +/************************************************************************************************************************************** +* Project: discoverpixy +* Website: https://github.com/t-moe/discoverpixy +* Authors: Aaron Schmocker, Timo Lang +* Institution: BFH Bern University of Applied Sciences +* File: emulator/qt/mainwindow.cpp +* +* Version History: +* Date Autor Email SHA Changes +* 2015-04-03 timolang@gmail.com 51089aa Refactored Project Structure for use with emulator +* 2015-04-03 timolang@gmail.com 1f2af9f Added more tft functions to common and emulator. Fixed eventloop. +* 2015-04-03 timolang@gmail.com c570bda Fixed bug in color conversion +* 2015-04-03 timolang@gmail.com 867f766 Some gui changes. +* 2015-04-03 timolang@gmail.com 1aa9194 Fixed Drawing of rects in Emulator. Got frames from pixy to emulator. Slooooow. +* 2015-04-04 timolang@gmail.com 0636381 Improved tff_draw_bitmap_unscaled in emulator. +* 2015-04-27 timolang@gmail.com 259d446 Added touch support to emulator. Implemented basic touch function. +* 2015-04-27 aaron@duckpond.ch aed90ef Drawcircle added (emulator) +* 2015-04-27 timolang@gmail.com e249fb2 Added font support +* 2015-05-09 timolang@gmail.com c652b6b Improved Emulator Gui +* 2015-05-25 timolang@gmail.com 911760e Added "Mouse Position"-Label to Emulator. +* 2015-06-01 timolang@gmail.com 06227da Added calibrate screen (WIP). fixed bug in emulator drawing. +* 2015-06-07 timolang@gmail.com 4b5768c Improved Comments in whole emulator. Finalized emulator section in docu. +* 2015-06-07 timolang@gmail.com 8752356 Started with tests in docu. fixed a small bug in emulator when drawing a rectangle. +* +**************************************************************************************************************************************/ + #include "mainwindow.h" #include "ui_mainwindow.h" #include @@ -6,33 +32,36 @@ #include extern "C" { - #include "touch.h" - #include "tft.h" +#include "touch.h" +#include "tft.h" } #define DISPLAY_WIDTH 320 #define DISPLAY_HEIGHT 240 //function to calculate QColor out of a RGB565 16bit color -QColor QColorFromRGB565(uint16_t color) { +QColor QColorFromRGB565(uint16_t color) +{ //interpolate colors - int R8 = (int) floor( (color>>(5+6)) * 255.0 / 31.0 + 0.5); - int G8 = (int) floor( ((color>>5)&0x3F) * 255.0 / 63.0 + 0.5); - int B8 = (int) floor( (color&0x1F) * 255.0 / 31.0 + 0.5); - return QColor::fromRgb(R8,G8,B8); + int R8 = (int) floor((color >> (5 + 6)) * 255.0 / 31.0 + 0.5); + int G8 = (int) floor(((color >> 5) & 0x3F) * 255.0 / 63.0 + 0.5); + int B8 = (int) floor((color & 0x1F) * 255.0 / 31.0 + 0.5); + return QColor::fromRgb(R8, G8, B8); } //function to calculate QRgb out of a RGB565 16bit color -QRgb QRgbFromRGB565(uint16_t color) { +QRgb QRgbFromRGB565(uint16_t color) +{ //interpolate colors - int R8 = (int) floor( (color>>(5+6)) * 255.0 / 31.0 + 0.5); - int G8 = (int) floor( ((color>>5)&0x3F) * 255.0 / 63.0 + 0.5); - int B8 = (int) floor( (color&0x1F) * 255.0 / 31.0 + 0.5); - return qRgb(R8,G8,B8); + int R8 = (int) floor((color >> (5 + 6)) * 255.0 / 31.0 + 0.5); + int G8 = (int) floor(((color >> 5) & 0x3F) * 255.0 / 63.0 + 0.5); + int B8 = (int) floor((color & 0x1F) * 255.0 / 31.0 + 0.5); + return qRgb(R8, G8, B8); } -MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), image(DISPLAY_WIDTH,DISPLAY_HEIGHT, QImage::Format_RGB16), ui(new Ui::MainWindow){ +MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), image(DISPLAY_WIDTH, DISPLAY_HEIGHT, QImage::Format_RGB16), ui(new Ui::MainWindow) +{ ui->setupUi(this); image.fill(Qt::black); //clear display buffer currentScale = 1; //start with scale factor 1 @@ -44,13 +73,13 @@ void MainWindow::draw_line(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, u { QPainter painter(&(image)); painter.setPen(QColorFromRGB565(color)); - painter.drawLine(x1,y1,x2,y2); + painter.drawLine(x1, y1, x2, y2); update(); } void MainWindow::draw_pixel(uint16_t x, uint16_t y, uint16_t color) { - image.setPixel(x,y,QRgbFromRGB565(color)); + image.setPixel(x, y, QRgbFromRGB565(color)); update(); } @@ -64,31 +93,32 @@ void MainWindow::draw_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t { QPainter painter(&(image)); painter.setPen(QColorFromRGB565(color)); - painter.drawRect(qMin(x1,x2),qMin(y1,y2),abs((int)x2-(int)x1),abs((int)y2-(int)y1)); + painter.drawRect(qMin(x1, x2), qMin(y1, y2), abs((int)x2 - (int)x1), abs((int)y2 - (int)y1)); update(); } void MainWindow::fill_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color) { QPainter painter(&(image)); - painter.fillRect(qMin(x1,x2),qMin(y1,y2),abs((int)x2-(int)x1)+1,abs((int)y2-(int)y1)+1,QColorFromRGB565(color)); + painter.fillRect(qMin(x1, x2), qMin(y1, y2), abs((int)x2 - (int)x1) + 1, abs((int)y2 - (int)y1) + 1, QColorFromRGB565(color)); update(); } -void MainWindow::draw_bitmap_unscaled(uint16_t x, uint16_t y, uint16_t width, uint16_t height, const uint16_t *dat) +void MainWindow::draw_bitmap_unscaled(uint16_t x, uint16_t y, uint16_t width, uint16_t height, const uint16_t* dat) { //Creating a new image and access it directly is faster than setPixel - QImage img(width,height,QImage::Format_RGB32); //create a new image + QImage img(width, height, QImage::Format_RGB32); //create a new image - for(int yi=0; yiwidgetDisplay->geometry().topLeft(),QSizeF(DISPLAY_WIDTH*currentScale,DISPLAY_HEIGHT*currentScale)); + //Create a QRectF which represents the rectangle to draw the buffered image to + QRectF imgRect(ui->widgetDisplay->geometry().topLeft(), QSizeF(DISPLAY_WIDTH * currentScale, DISPLAY_HEIGHT * currentScale)); - painter.drawImage(imgRect,image); //draw buffer - painter.setPen(QPen(Qt::green,2)); //set border color - painter.drawRect(imgRect.adjusted(-1,-1,1,1)); //draw border + painter.drawImage(imgRect, image); //draw buffer + painter.setPen(QPen(Qt::green, 2)); //set border color + painter.drawRect(imgRect.adjusted(-1, -1, 1, 1)); //draw border } -void MainWindow::mousePressEvent(QMouseEvent *evt) +void MainWindow::mousePressEvent(QMouseEvent* evt) { //the mouse was pressed - checkAndSendEvent(evt->pos(),true); + checkAndSendEvent(evt->pos(), true); } -void MainWindow::mouseReleaseEvent(QMouseEvent *evt) +void MainWindow::mouseReleaseEvent(QMouseEvent* evt) { //the mouse was released - checkAndSendEvent(evt->pos(),false); + checkAndSendEvent(evt->pos(), false); } -void MainWindow::mouseMoveEvent(QMouseEvent *evt) +void MainWindow::mouseMoveEvent(QMouseEvent* evt) { //the mouse was released - checkAndSendEvent(evt->pos(),true); + checkAndSendEvent(evt->pos(), true); } -bool MainWindow::eventFilter(QObject *obj, QEvent *evt) +bool MainWindow::eventFilter(QObject* obj, QEvent* evt) { - if(obj==ui->widgetDisplay) { //we received a redirect event from the target rectangle - switch(evt->type()) { - case QEvent::MouseMove: //it's a mouse move event - { - QMouseEvent* mouseEvent = static_cast(evt); //get mouse event - QPoint p = (mouseEvent->pos()-QPoint(1,1))/currentScale; //calculate correct corrdinates (undo scale) - if(p.x()txtMousePos->setText(QString("Mouse Position: (%1,%2)").arg(p.x()).arg(p.y())); - } + if (obj == ui->widgetDisplay) { //we received a redirect event from the target rectangle + switch (evt->type()) { + case QEvent::MouseMove: { //it's a mouse move event + QMouseEvent* mouseEvent = static_cast(evt); //get mouse event + QPoint p = (mouseEvent->pos() - QPoint(1, 1)) / currentScale; //calculate correct corrdinates (undo scale) + + if (p.x() < DISPLAY_WIDTH && p.y() < DISPLAY_HEIGHT) { //mouse position not out of bounds + //set mouse position text + ui->txtMousePos->setText(QString("Mouse Position: (%1,%2)").arg(p.x()).arg(p.y())); } - break; - default: break; } - } - return false; + break; + + default: + break; + } + } + + return false; } @@ -177,15 +210,18 @@ MainWindow::~MainWindow() void MainWindow::checkAndSendEvent(QPoint pos, bool down) { QPoint p = pos - ui->widgetDisplay->geometry().topLeft(); //make coordinate relative to target area (0,0) - p/=currentScale; //undo scaling - if(p.x()<0 || p.y()<0 || p.x() >= DISPLAY_WIDTH || p.y() >= DISPLAY_HEIGHT) return; //abort if out of bounds + p /= currentScale; //undo scaling - touch_add_raw_event(p.x(),p.y(),down?TOUCH_DOWN:TOUCH_UP); //submit touch event to touch module (common) + if (p.x() < 0 || p.y() < 0 || p.x() >= DISPLAY_WIDTH || p.y() >= DISPLAY_HEIGHT) { + return; //abort if out of bounds + } + + touch_add_raw_event(p.x(), p.y(), down ? TOUCH_DOWN : TOUCH_UP); //submit touch event to touch module (common) } void MainWindow::on_cboZoom_currentIndexChanged(int index) { - currentScale=index+1; //zoom factor 1 is the 0th entry, zoom factor 2 is the 1st entry, zoom factor 3 is the 2nd entry + currentScale = index + 1; //zoom factor 1 is the 0th entry, zoom factor 2 is the 1st entry, zoom factor 3 is the 2nd entry update(); //force redraw } diff --git a/emulator/qt/mainwindow.h b/emulator/qt/mainwindow.h index 7c0f845..719178a 100644 --- a/emulator/qt/mainwindow.h +++ b/emulator/qt/mainwindow.h @@ -1,3 +1,24 @@ +/************************************************************************************************************************************** +* Project: discoverpixy +* Website: https://github.com/t-moe/discoverpixy +* Authors: Aaron Schmocker, Timo Lang +* Institution: BFH Bern University of Applied Sciences +* File: emulator/qt/mainwindow.h +* +* Version History: +* Date Autor Email SHA Changes +* 2015-04-03 timolang@gmail.com 51089aa Refactored Project Structure for use with emulator +* 2015-04-03 timolang@gmail.com 1f2af9f Added more tft functions to common and emulator. Fixed eventloop. +* 2015-04-03 timolang@gmail.com 1aa9194 Fixed Drawing of rects in Emulator. Got frames from pixy to emulator. Slooooow. +* 2015-04-27 timolang@gmail.com 259d446 Added touch support to emulator. Implemented basic touch function. +* 2015-04-27 aaron@duckpond.ch aed90ef Drawcircle added (emulator) +* 2015-04-27 timolang@gmail.com e249fb2 Added font support +* 2015-05-09 timolang@gmail.com c652b6b Improved Emulator Gui +* 2015-05-25 timolang@gmail.com 911760e Added "Mouse Position"-Label to Emulator. +* 2015-06-07 timolang@gmail.com 4b5768c Improved Comments in whole emulator. Finalized emulator section in docu. +* +**************************************************************************************************************************************/ + #ifndef MAINWINDOW_H #define MAINWINDOW_H @@ -5,7 +26,8 @@ #include #include -namespace Ui { +namespace Ui +{ class MainWindow; } @@ -14,33 +36,33 @@ class MainWindow : public QMainWindow Q_OBJECT public: - explicit MainWindow(QWidget *parent = 0); + explicit MainWindow(QWidget* parent = 0); void draw_line(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color); - void draw_pixel(uint16_t x,uint16_t y,uint16_t color); + void draw_pixel(uint16_t x, uint16_t y, uint16_t color); void clear(uint16_t color); void draw_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color); void fill_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color); - void draw_bitmap_unscaled(uint16_t x, uint16_t y, uint16_t width, uint16_t height, const uint16_t *dat); + void draw_bitmap_unscaled(uint16_t x, uint16_t y, uint16_t width, uint16_t height, const uint16_t* dat); void draw_circle(uint16_t x, uint16_t y, uint16_t r, uint16_t color); void draw_char(uint16_t x, uint16_t y, uint16_t color, uint16_t bgcolor, QFont font, char c); protected: - bool eventFilter(QObject * obj , QEvent * env); - void paintEvent(QPaintEvent * evt); - void mousePressEvent(QMouseEvent* evt); - void mouseReleaseEvent(QMouseEvent* evt); - void mouseMoveEvent(QMouseEvent* evt); + bool eventFilter(QObject* obj , QEvent* env); + void paintEvent(QPaintEvent* evt); + void mousePressEvent(QMouseEvent* evt); + void mouseReleaseEvent(QMouseEvent* evt); + void mouseMoveEvent(QMouseEvent* evt); ~MainWindow(); private slots: - void on_cboZoom_currentIndexChanged(int index); //slot that is called when the zoomlevel changed + void on_cboZoom_currentIndexChanged(int index); //slot that is called when the zoomlevel changed private: QImage image; //Display buffer int currentScale; //current scale factor void checkAndSendEvent(QPoint pos, bool down); - Ui::MainWindow *ui; + Ui::MainWindow* ui; }; #endif // MAINWINDOW_H diff --git a/utils/genheader.sh b/utils/genheader.sh index 26ee24b..b6145a7 100755 --- a/utils/genheader.sh +++ b/utils/genheader.sh @@ -2,6 +2,7 @@ echo "/**************************************************************************************************************************************" echo "* Project: discoverpixy" +echo "* Website: https://github.com/t-moe/discoverpixy" echo "* Authors: Aaron Schmocker, Timo Lang" echo "* Institution: BFH Bern University of Applied Sciences" echo "* File: $1"