3 Commits
master ... 0.1

Author SHA1 Message Date
t-moe
c32bfde94e Font fix for windows. 2015-06-06 14:35:01 +02:00
t-moe
129b7e0ee7 Cleaned up windows build, added readme. Added Boost binaries. 2015-06-06 14:29:37 +02:00
t-moe
0fa18290dd Changed makefile of emulator to run on windows. 2015-06-06 13:47:28 +02:00
102 changed files with 6888 additions and 6593 deletions

View File

@@ -959,13 +959,13 @@ USE_MDFILE_AS_MAINPAGE =
# also VERBATIM_HEADERS is set to NO. # also VERBATIM_HEADERS is set to NO.
# The default value is: NO. # The default value is: NO.
SOURCE_BROWSER = YES SOURCE_BROWSER = NO
# Setting the INLINE_SOURCES tag to YES will include the body of functions, # Setting the INLINE_SOURCES tag to YES will include the body of functions,
# classes and enums directly into the documentation. # classes and enums directly into the documentation.
# The default value is: NO. # The default value is: NO.
INLINE_SOURCES = YES INLINE_SOURCES = NO
# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any # 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 # 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. # If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
# The default value is: YES. # The default value is: YES.
GENERATE_LATEX = YES GENERATE_LATEX = NO
# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a # 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 # 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. # The default value is: NO.
# This tag requires that the tag GENERATE_LATEX is set to YES. # This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_SOURCE_CODE = YES LATEX_SOURCE_CODE = NO
# The LATEX_BIB_STYLE tag can be used to specify the style to use for the # The LATEX_BIB_STYLE tag can be used to specify the style to use for the
# bibliography, e.g. plainnat, or ieeetr. See # bibliography, e.g. plainnat, or ieeetr. See

View File

@@ -1,14 +1,5 @@
# discoverpixy # discoverpixy
A Project with the Pixy cam and the STM32F4 Discovery. The project can also be run on linux/windows using a qt-based emulator. Project with the Pixy cam and the STM32F4 Discovery
![Pixy Logo](doc/pixy.png)
<img src="doc/mainscreen_emulator.png" width="300">
<img src="doc/tracking_emulator.png" width="300">
## 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 ## Folder structure
* *common*: device independent code and the "Application" itself * *common*: device independent code and the "Application" itself

View File

@@ -1,32 +1,3 @@
/**************************************************************************************************************************************
* 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 "app.h"
#include "tft.h" #include "tft.h"
#include "system.h" #include "system.h"
@@ -34,20 +5,20 @@
#include "screen_main.h" #include "screen_main.h"
#include "filesystem.h" #include "filesystem.h"
void app_init() void app_init() {
{ system_init();
system_init(); tft_init();
tft_init(); touch_init();
touch_init(); filesystem_init();
filesystem_init();
gui_screen_navigate(get_screen_main()); gui_screen_navigate(get_screen_main());
} }
//app event loop //app event loop
void app_process() void app_process() {
{
system_process(); //Let the system handle it's pending events
system_process(); //Let the system handle it's pending events gui_screen_update(); //update the currently active screen
gui_screen_update(); //update the currently active screen
} }

View File

@@ -1,28 +1,6 @@
/**************************************************************************************************************************************
* 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 #ifndef APP_H
#define 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 <a href="modules.html">Modules</a> page.
*/
/** /**
* @defgroup app Application * @defgroup app Application
* The App Module contains the effective, platform independent application. * The App Module contains the effective, platform independent application.

View File

@@ -1,88 +0,0 @@
/**************************************************************************************************************************************
* 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
*
* Notation
* --------
*
* x : Sollwert (Führgrösse)
* w : Istwert (Reglergrösse)
* esum : Integralteil
* e : Regelabweichung
* y : Stellgrösse
*
*
*/
#include<pixy_control.h>
#include<stdint.h>
// PID tuning factors
#define REG_PID_KP (0.41f)
#define REG_PID_KI (0.001f)
#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
int16_t pixy_PID_Y(int16_t x, int16_t w)
{
float e = 0;
static float esum = 0;
static float eold = 0;
float y = 0;
e = (float)(x - w); // calculate the controller offset
//----PID-control-------------------------------------------------------------------------
esum = esum + e; // add e to the current sum
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
//----------------------------------------------------------------------------------------
eold = e; // save the previous value
return (int16_t)y;
}
// PID controller implementation for the x-axis
int16_t pixy_PID_X(int16_t x, int16_t w)
{
float e = 0;
static float esum = 0;
static float eold = 0;
float y = 0;
e = (float)(x - w); // calculate the controller offset
//----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_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
//----------------------------------------------------------------------------------------
eold = e; // save the previous value
return (int16_t)y;
}

View File

@@ -1,58 +0,0 @@
/**************************************************************************************************************************************
* 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_
#include<stdint.h>
/**
* @addtogroup app
*/
/*@{*/
/**
* @defgroup pixy_control Pixy Control Helper
* A collection of helper functions that contain PID Control code used for object tracking.
*/
/*@}*/
/**
* @addtogroup pixy_control
*/
/*@{*/
/**
* Execute one step of PID regulation for the Y-servo.
* @param x desired value (e.g. current y-position of the biggest block)
* @param w actual value (e.g desired y-position)
* @return The offset which needs to be added to the Y-Servo position
*/
int16_t pixy_PID_Y(int16_t x, int16_t w);
/**
* Execute one step of PID regulation for the X-servo.
* @param x desired value (e.g. current x-position of the biggest block)
* @param w actual value (e.g desired x-position)
* @return The offset which needs to be added to the X-Servo position
*/
int16_t pixy_PID_X(int16_t x, int16_t w);
/*@}*/
#endif /* PIXY_CONTROL_H_ */

View File

@@ -1,248 +0,0 @@
/**************************************************************************************************************************************
* 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"
#include <stdlib.h>
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)
{
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;
}
} 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;
}
}
}
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;
// skip first line
frame += width;
// 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));
if (decodedimage == NULL) { //not enough free space to decode image in memory
//decode & render image pixel by pixel
for (y = 1; y < height - 1; y++) {
frame++;
for (x = 1; x < width - 1; x++, frame++) {
interpolateBayer(width, x, y, frame, &r, &g, &b);
tft_draw_pixel(xpos + x - 1, ypos + y - 1, RGB(r, g, b));
}
frame++;
}
} else { //enough space
uint16_t* line = decodedimage;
for (y = 1; y < height - 1; y++) {
//line = (unsigned int *)img.scanLine(y-1);
frame++;
for (x = 1; x < width - 1; x++, frame++) {
interpolateBayer(width, x, y, frame, &r, &g, &b);
//*line++ = (0xff<<24) | (r<<16) | (g<<8) | (b<<0);
*line++ = RGB(r, g, b);
}
frame++;
}
tft_draw_bitmap_unscaled(xpos, ypos, width - 2, height - 2, decodedimage);
free(decodedimage);
}
return 0;
}
static int saveBA81(FILE_HANDLE* handle, uint16_t width, uint16_t height, uint32_t frameLen, uint8_t* frame)
{
uint16_t x, y;
uint8_t r, g, b;
uint32_t fpos = handle->fpos;
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
for (y = 1; y < height - 1; y++) {
frame++;
uint8_t rowbuf[row_size_padded];
//Bitmaps are saved "bottom-up". Seek to the right row.
if (filesystem_file_seek(handle, fpos_end - row_size_padded * y) != F_OK) {
return -1;
}
for (x = 1; x < width - 1; x++, frame++) {
interpolateBayer(width, x, y, frame, &r, &g, &b);
//bitmaps are saved in 24bit b,g,r format
rowbuf[(x - 1) * 3] = b;
rowbuf[(x - 1) * 3 + 1] = g;
rowbuf[(x - 1) * 3 + 2] = r;
}
if (filesystem_file_write(handle, rowbuf, row_size_padded) != F_OK) {
return -1;
}
frame++;
}
return 0;
}
int pixy_cc_set_region(uint8_t signum, uint16_t xoffset, uint16_t yoffset, uint16_t width, uint16_t height)
{
int32_t response;
int return_value = pixy_command("cc_setSigRegion", // String id for remote procedure
INT32(0), // type = normal color code
INT8(signum),
INT16(xoffset), // xoffset
INT16(yoffset), // yoffset
INT16(width), // width
INT16(height), // height
END_OUT_ARGS, // separator
&response, // pointer to mem address for return value
END_IN_ARGS);
return return_value;
}

241
common/app/pixy_helper.c Normal file
View File

@@ -0,0 +1,241 @@
#include "pixy_helper.h"
#include "pixy.h"
#include "tft.h"
#include <stdlib.h>
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)
{
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;
}
}
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;
}
}
}
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;
// skip first line
frame += width;
// 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));
if(decodedimage==NULL) { //not enough free space to decode image in memory
//decode & render image pixel by pixel
for (y=1; y<height-1; y++)
{
frame++;
for (x=1; x<width-1; x++, frame++)
{
interpolateBayer(width, x, y, frame, &r, &g, &b);
tft_draw_pixel(xpos+x-1,ypos+y-1,RGB(r,g,b));
}
frame++;
}
} else { //enough space
uint16_t* line = decodedimage;
for (y=1; y<height-1; y++)
{
//line = (unsigned int *)img.scanLine(y-1);
frame++;
for (x=1; x<width-1; x++, frame++)
{
interpolateBayer(width, x, y, frame, &r, &g, &b);
//*line++ = (0xff<<24) | (r<<16) | (g<<8) | (b<<0);
*line++ = RGB(r,g,b);
}
frame++;
}
tft_draw_bitmap_unscaled(xpos,ypos,width-2,height-2,decodedimage);
free(decodedimage);
}
return 0;
}
static int saveBA81(FILE_HANDLE* handle, uint16_t width, uint16_t height, uint32_t frameLen, uint8_t *frame)
{
uint16_t x, y;
uint8_t r, g, b;
uint32_t fpos = handle->fpos;
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
for (y=1; y<height-1; y++)
{
frame++;
uint8_t rowbuf[row_size_padded];
//Bitmaps are saved "bottom-up". Seek to the right row.
if(filesystem_file_seek(handle,fpos_end-row_size_padded*y)!=F_OK) {
return -1;
}
for (x=1; x<width-1; x++, frame++)
{
interpolateBayer(width, x, y, frame, &r, &g, &b);
//bitmaps are saved in 24bit b,g,r format
rowbuf[(x-1)*3] = b;
rowbuf[(x-1)*3+1] = g;
rowbuf[(x-1)*3+2] = r;
}
if(filesystem_file_write(handle,rowbuf,row_size_padded)!=F_OK) {
return -1;
}
frame++;
}
return 0;
}
int pixy_cc_set_region(uint8_t signum, uint16_t xoffset, uint16_t yoffset, uint16_t width, uint16_t height) {
int32_t response;
int return_value = pixy_command("cc_setSigRegion", // String id for remote procedure
INT32(0), // type = normal color code
INT8(signum),
INT16(xoffset), // xoffset
INT16(yoffset), // yoffset
INT16(width), // width
INT16(height), // height
END_OUT_ARGS, // separator
&response, // pointer to mem address for return value
END_IN_ARGS);
return return_value;
}

View File

@@ -1,43 +1,10 @@
/************************************************************************************************************************************** #ifndef PIXY_HELPER_H
* Project: discoverpixy #define PIXY_HELPER_H
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/app/pixy_frame.h
*
* 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
*
**************************************************************************************************************************************/
#ifndef PIXY_FRAME_H
#define PIXY_FRAME_H
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include "filesystem.h" #include "filesystem.h"
/**
* @addtogroup app
*/
/*@{*/
/**
* @defgroup pixy_helper Pixy Frame Helper
* A collection of helper functions that allow receiving and rendering a frame from pixy onto the display.
* Furthermore you can select a color in a frame, to use for tracking.
*/
/*@}*/
/**
* @addtogroup pixy_helper
*/
/*@{*/
/** /**
* Receives a fullsized frame from pixy and display's it on the display with the topleft corner at (x,y) * Receives a fullsized frame from pixy and display's it on the display with the topleft corner at (x,y)
* @param x The x-Coordinate of the top left corner * @param x The x-Coordinate of the top left corner
@@ -89,6 +56,4 @@ int pixy_save_cropped_frame(FILE_HANDLE* handle, uint16_t xoffset, uint16_t yoff
*/ */
int pixy_cc_set_region(uint8_t signum, uint16_t xoffset, uint16_t yoffset, uint16_t width, uint16_t height); int pixy_cc_set_region(uint8_t signum, uint16_t xoffset, uint16_t yoffset, uint16_t width, uint16_t height);
/*@}*/ #endif /* PIXY_HELPER_H */
#endif /* PIXY_FRAME_H */

View File

@@ -1,20 +1,3 @@
/**************************************************************************************************************************************
* 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.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-10 timolang@gmail.com 790f602 Added bitmap decoding/drawing example
* 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.
* 2015-05-15 timolang@gmail.com 85f1aee Changed filetest to use new bitmap draw method.
*
**************************************************************************************************************************************/
#include "screen_filetest.h" #include "screen_filetest.h"
#include "button.h" #include "button.h"
#include "tft.h" #include "tft.h"
@@ -24,132 +7,133 @@
static BUTTON_STRUCT b_back; static BUTTON_STRUCT b_back;
static void b_back_cb(void* button) static void b_back_cb(void* button) {
{ gui_screen_back();
gui_screen_back();
} }
static void image_test(); static void image_test();
static void enter(void* screen) static void enter(void* screen) {
{ tft_clear(HEX(0xBABECD));
tft_clear(HEX(0xBABECD));
//Back button
b_back.base.x1=10; //Start X of Button
b_back.base.y1=200; //Start Y of Button
b_back.base.x2=AUTO; //b_back.base.x1+160; //Auto Calculate X2 with String Width
b_back.base.y2=AUTO; //Auto Calculate Y2 with String Height
b_back.txtcolor=WHITE; //Set foreground color
b_back.bgcolor=HEX(0xAE1010); //Set background color (Don't take 255 or 0 on at least one channel, to make shadows possible)
b_back.font=0; //Select Font
b_back.text="Back"; //Set Text (For formatted strings take sprintf)
b_back.callback=b_back_cb; //Call b_back_cb as Callback
gui_button_add(&b_back); //Register Button (and run the callback from now on)
//Back button
b_back.base.x1 = 10; //Start X of Button
b_back.base.y1 = 200; //Start Y of Button
b_back.base.x2 = AUTO; //b_back.base.x1+160; //Auto Calculate X2 with String Width
b_back.base.y2 = AUTO; //Auto Calculate Y2 with String Height
b_back.txtcolor = WHITE; //Set foreground color
b_back.bgcolor = HEX(0xAE1010); //Set background color (Don't take 255 or 0 on at least one channel, to make shadows possible)
b_back.font = 0; //Select Font
b_back.text = "Back"; //Set Text (For formatted strings take sprintf)
b_back.callback = b_back_cb; //Call b_back_cb as Callback
gui_button_add(&b_back); //Register Button (and run the callback from now on)
tft_draw_line(10, 30, 310, 30, BLACK); /*
tft_print_line(10, 18, BLUE, TRANSPARENT, 0, "Name D H RO Date Time Size"); //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");
*/
int y = 33; tft_draw_line(10,30,310,30,BLACK);
tft_print_line(10,18,BLUE,TRANSPARENT,0,"Name D H RO Date Time Size");
int y = 33;
DIRECTORY_STRUCT* dir = filesystem_dir_open(".");
if(dir==NULL) return;
DIRECTORY_STRUCT* dir = filesystem_dir_open("."); 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;
}
if (dir == NULL) { filesystem_dir_close(dir);
return;
}
for (int i = 0; i < dir->num_files; i++) { y+=14;
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;
}
filesystem_dir_close(dir); 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");
}
y += 14; }
filesystem_file_close(file);
FILE_HANDLE* file = filesystem_file_open("test.txt"); image_test();
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) static void leave(void* screen) {
{ gui_button_remove(&b_back);
gui_button_remove(&b_back);
} }
static void update(void* screen) static void update(void* screen) {
{
} }
static SCREEN_STRUCT screen = { static SCREEN_STRUCT screen = {
enter, enter,
leave, leave,
update update
}; };
SCREEN_STRUCT* get_screen_filetest() SCREEN_STRUCT* get_screen_filetest() {
{ return &screen;
return &screen;
} }
static void image_test() static void image_test() {
{
if (!tft_draw_bitmap_file_unscaled(250, 170, "cpu.bmp")) { if(!tft_draw_bitmap_file_unscaled(250,170,"cpu.bmp")) {
tft_print_line(10, 180, BLUE, TRANSPARENT, 0, "Could not open 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);
tft_draw_rectangle(250 - 1, 170 - 1, 250 - 1 + 64, 170 - 1 + 64, BLACK);
} }

View File

@@ -1,18 +1,3 @@
/**************************************************************************************************************************************
* 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" #include "screen.h"
/** /**

View File

@@ -1,21 +1,3 @@
/**************************************************************************************************************************************
* 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 "screen_guitest.h"
#include "button.h" #include "button.h"
#include "tft.h" #include "tft.h"
@@ -27,138 +9,127 @@ static TOUCH_AREA_STRUCT a_area;
static CHECKBOX_STRUCT c_cbox; static CHECKBOX_STRUCT c_cbox;
static NUMUPDOWN_STRUCT n_updown; static NUMUPDOWN_STRUCT n_updown;
static void checkboxCB(void* checkbox, bool checked) static void checkboxCB(void *checkbox, bool checked) {
{ printf("Checkbox %s\n",(checked?"checked":"unchecked"));
printf("Checkbox %s\n", (checked ? "checked" : "unchecked"));
} }
static void b_back_cb(void* button) static void b_back_cb(void* button) {
{ gui_screen_back();
gui_screen_back();
} }
static void n_updown_cb(void* numupdown, int16_t value) static void n_updown_cb(void* numupdown, int16_t value) {
{ printf("New NumUpDown Value %d\n",value);
printf("New NumUpDown Value %d\n", value);
} }
static void touchCB(void* touchArea, TOUCH_ACTION triggeredAction) static void touchCB(void* touchArea, TOUCH_ACTION triggeredAction) {
{
switch(triggeredAction) {
switch (triggeredAction) { case PEN_DOWN:
case PEN_DOWN: printf("action PEN_DOWN\n");
printf("action PEN_DOWN\n"); break;
break; case PEN_UP:
printf("action PEN_UP\n");
case PEN_UP: break;
printf("action PEN_UP\n"); case PEN_MOVE:
break; printf("action PEN_MOVE\n");
break;
case PEN_MOVE: case PEN_ENTER:
printf("action PEN_MOVE\n"); printf("action PEN_ENTER\n");
break; break;
case PEN_LEAVE:
case PEN_ENTER: printf("action PEN_LEAVE\n");
printf("action PEN_ENTER\n"); break;
break; default:
printf("action %s\n",triggeredAction);
case PEN_LEAVE: break;
printf("action PEN_LEAVE\n"); }
break;
default:
printf("action %s\n", triggeredAction);
break;
}
} }
static void enter(void* screen) static void enter(void* screen) {
{ tft_clear(HEX(0xA6FD9A));
tft_clear(HEX(0xA6FD9A));
//Back button
//Back button b_back.base.x1=10; //Start X of Button
b_back.base.x1 = 10; //Start X of Button b_back.base.y1=10; //Start Y 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.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.base.y2 = AUTO; //Auto Calculate Y2 with String Height b_back.txtcolor=WHITE; //Set foreground color
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.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.font = 0; //Select Font b_back.text="Back"; //Set Text (For formatted strings take sprintf)
b_back.text = "Back"; //Set Text (For formatted strings take sprintf) b_back.callback=b_back_cb; //Call b_back_cb as Callback
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)
gui_button_add(&b_back); //Register Button (and run the callback from now on)
//tft test //tft test
tft_draw_pixel(0, 0, BLACK); tft_draw_pixel(0,0,BLACK);
tft_draw_pixel(319, 239, BLACK); tft_draw_pixel(319,239,BLACK);
tft_draw_pixel(10, 210, BLUE); tft_draw_pixel(10,210,BLUE);
tft_draw_pixel(12, 210, BLUE); tft_draw_pixel(12,210,BLUE);
tft_draw_rectangle(40, 100, 60, 235, BLUE); tft_draw_rectangle(40,100,60,235,BLUE);
tft_fill_rectangle(100, 215, 200, 225, GREEN); tft_fill_rectangle(100,215,200,225,GREEN);
tft_draw_line(10, 50, 310, 225, RGB(0xFF, 0, 0xFF)); tft_draw_line(10,50,310,225,RGB(0xFF,0,0xFF));
tft_draw_circle(10, 10, 100, RED); tft_draw_circle(10,10,100, RED);
tft_print_line(30, 130, RED, BLUE, 0, "Hallo"); 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);
//Area test //Checkbox test
a_area.hookedActions = PEN_DOWN | PEN_UP | PEN_MOVE | PEN_ENTER | PEN_LEAVE; c_cbox.base.x1=220;
a_area.x1 = 130; c_cbox.base.y1=45;
a_area.y1 = 30; c_cbox.base.x2=c_cbox.base.x1+16;
a_area.x2 = 200; c_cbox.base.y2=c_cbox.base.y1+16;
a_area.y2 = 60; c_cbox.fgcolor = GREEN;
a_area.callback = touchCB; c_cbox.checked = true;
touch_register_area(&a_area); c_cbox.callback = checkboxCB;
gui_checkbox_add(&c_cbox);
//Num up down test
n_updown.x=200;
//Checkbox test n_updown.y=120;
c_cbox.base.x1 = 220; n_updown.fgcolor=RED;
c_cbox.base.y1 = 45; n_updown.value = -3;
c_cbox.base.x2 = c_cbox.base.x1 + 16; n_updown.max=11;
c_cbox.base.y2 = c_cbox.base.y1 + 16; n_updown.min =-5;
c_cbox.fgcolor = GREEN; n_updown.callback=n_updown_cb;
c_cbox.checked = true; gui_numupdown_add(&n_updown);
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) static void leave(void* screen) {
{ gui_button_remove(&b_back);
gui_button_remove(&b_back); gui_checkbox_remove(&c_cbox);
gui_checkbox_remove(&c_cbox); gui_numupdown_remove(&n_updown);
gui_numupdown_remove(&n_updown); touch_unregister_area(&a_area);
touch_unregister_area(&a_area);
} }
static void update(void* screen) static void update(void* screen) {
{ //gui_button_redraw(&b_back); //only needed if button is overdrawn by others
//gui_button_redraw(&b_back); //only needed if button is overdrawn by others //.... for the other elements as well
//.... for the other elements as well
} }
static SCREEN_STRUCT screen = { static SCREEN_STRUCT screen = {
enter, enter,
leave, leave,
update update
}; };
SCREEN_STRUCT* get_screen_guitest() SCREEN_STRUCT* get_screen_guitest() {
{ return &screen;
return &screen;
} }

View File

@@ -1,18 +1,3 @@
/**************************************************************************************************************************************
* 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" #include "screen.h"

View File

@@ -1,21 +1,3 @@
/**************************************************************************************************************************************
* 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_main.h"
#include "screen_guitest.h" #include "screen_guitest.h"
#include "screen_pixytest.h" #include "screen_pixytest.h"
@@ -35,165 +17,157 @@ BUTTON_STRUCT b_ref_tracking;
BUTTON_STRUCT b_photo_mode; BUTTON_STRUCT b_photo_mode;
static void b_our_tracking_cb(void* button) static void b_our_tracking_cb(void* button) {
{ tracking_set_mode(OUR_TRACKING);
tracking_set_mode(OUR_TRACKING); gui_screen_navigate(get_screen_tracking());
gui_screen_navigate(get_screen_tracking());
} }
static void b_ref_tracking_cb(void* button) static void b_ref_tracking_cb(void* button) {
{ tracking_set_mode(REFERENCE_TRACKING);
tracking_set_mode(REFERENCE_TRACKING); gui_screen_navigate(get_screen_tracking());
gui_screen_navigate(get_screen_tracking());
} }
static void b_photo_mode_cb(void* button) static void b_photo_mode_cb(void* button) {
{ gui_screen_navigate(get_screen_photomode());
gui_screen_navigate(get_screen_photomode());
} }
static void b_guitest_cb(void* button) static void b_guitest_cb(void* button) {
{ gui_screen_navigate(get_screen_guitest());
gui_screen_navigate(get_screen_guitest());
} }
static void b_filetest_cb(void* button) static void b_filetest_cb(void* button) {
{ gui_screen_navigate(get_screen_filetest());
gui_screen_navigate(get_screen_filetest());
} }
static void b_pixytest_cb(void* button) static void b_pixytest_cb(void* button) {
{ gui_screen_navigate(get_screen_pixytest());
gui_screen_navigate(get_screen_pixytest());
} }
static void enter(void* screen) static void enter(void* screen) {
{ tft_clear(WHITE);
tft_clear(WHITE);
//Heading //Heading
tft_print_line(10, 10, BLUE, TRANSPARENT, 1, "Discoverpixy"); tft_print_line(10,10,BLUE,TRANSPARENT,1,"Discoverpixy");
tft_draw_line(0, 40, 319, 40, BLACK); tft_draw_line(0,40,319,40,BLACK);
#define X_TAB 97 #define X_TAB 97
#define BUTTON_SPACING 7 #define BUTTON_SPACING 7
//First line of buttons //First line of buttons
#define Y_FIRST 60 #define Y_FIRST 60
tft_print_line(10, Y_FIRST, BLACK, TRANSPARENT, 0, "Tracking:"); 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.x1=X_TAB; //Start X of Button
b_our_tracking.base.y1 = Y_FIRST - 3; //Start Y 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.x2=AUTO; //Auto Calculate X2 with String Width
b_our_tracking.base.y2 = AUTO; //Auto Calculate Y2 with String Height b_our_tracking.base.y2=AUTO; //Auto Calculate Y2 with String Height
b_our_tracking.txtcolor = WHITE; //Set foreground color 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.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.font=0; //Select Font
b_our_tracking.text = "Our Tracking"; //Set Text (For formatted strings take sprintf) 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 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) 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.x1=b_our_tracking.base.x2+BUTTON_SPACING;
b_ref_tracking.base.y1 = Y_FIRST - 3; b_ref_tracking.base.y1=Y_FIRST-3;
b_ref_tracking.base.x2 = AUTO; b_ref_tracking.base.x2=AUTO;
b_ref_tracking.base.y2 = AUTO; b_ref_tracking.base.y2=AUTO;
b_ref_tracking.txtcolor = WHITE; b_ref_tracking.txtcolor=WHITE;
b_ref_tracking.bgcolor = HEX(0xFF2151); b_ref_tracking.bgcolor=HEX(0xFF2151);
b_ref_tracking.font = 0; b_ref_tracking.font=0;
b_ref_tracking.text = "Ref Tracking"; b_ref_tracking.text="Ref Tracking";
b_ref_tracking.callback = b_ref_tracking_cb; b_ref_tracking.callback=b_ref_tracking_cb;
gui_button_add(&b_ref_tracking); gui_button_add(&b_ref_tracking);
//Second line of buttons //Second line of buttons
#define Y_SECOND Y_FIRST+25 #define Y_SECOND Y_FIRST+25
tft_print_line(10, Y_SECOND, BLACK, TRANSPARENT, 0, "Photo mode:"); tft_print_line(10,Y_SECOND,BLACK,TRANSPARENT,0,"Photo mode:");
b_photo_mode.base.x1 = X_TAB; b_photo_mode.base.x1=X_TAB;
b_photo_mode.base.y1 = Y_SECOND - 3; b_photo_mode.base.y1=Y_SECOND-3;
b_photo_mode.base.x2 = AUTO; b_photo_mode.base.x2=AUTO;
b_photo_mode.base.y2 = AUTO; b_photo_mode.base.y2=AUTO;
b_photo_mode.txtcolor = WHITE; b_photo_mode.txtcolor=WHITE;
b_photo_mode.bgcolor = HEX(0x21B1FF); b_photo_mode.bgcolor=HEX(0x21B1FF);
b_photo_mode.font = 0; b_photo_mode.font=0;
b_photo_mode.text = "Photo Mode"; b_photo_mode.text="Photo Mode";
b_photo_mode.callback = b_photo_mode_cb; b_photo_mode.callback=b_photo_mode_cb;
gui_button_add(&b_photo_mode); gui_button_add(&b_photo_mode);
//Third line of buttons //Third line of buttons
#define Y_THIRD Y_SECOND+25 #define Y_THIRD Y_SECOND+25
tft_print_line(10, Y_THIRD, BLACK, TRANSPARENT, 0, "Tests:"); tft_print_line(10,Y_THIRD,BLACK,TRANSPARENT,0,"Tests:");
b_guitest.base.x1 = X_TAB; b_guitest.base.x1=X_TAB;
b_guitest.base.y1 = Y_THIRD - 3; b_guitest.base.y1=Y_THIRD-3;
b_guitest.base.x2 = AUTO; b_guitest.base.x2=AUTO;
b_guitest.base.y2 = AUTO; b_guitest.base.y2=AUTO;
b_guitest.txtcolor = BLACK; b_guitest.txtcolor=BLACK;
b_guitest.bgcolor = HEX(0x00FA21); b_guitest.bgcolor=HEX(0x00FA21);
b_guitest.font = 0; b_guitest.font=0;
b_guitest.text = "Gui & Tft"; b_guitest.text="Gui & Tft";
b_guitest.callback = b_guitest_cb; b_guitest.callback=b_guitest_cb;
gui_button_add(&b_guitest); gui_button_add(&b_guitest);
b_pixytest.base.x1 = b_guitest.base.x2 + BUTTON_SPACING; b_pixytest.base.x1=b_guitest.base.x2+BUTTON_SPACING;
b_pixytest.base.y1 = Y_THIRD - 3; b_pixytest.base.y1=Y_THIRD-3;
b_pixytest.base.x2 = AUTO; b_pixytest.base.x2=AUTO;
b_pixytest.base.y2 = AUTO; b_pixytest.base.y2=AUTO;
b_pixytest.txtcolor = BLACK; b_pixytest.txtcolor=BLACK;
b_pixytest.bgcolor = HEX(0x00FA96); b_pixytest.bgcolor=HEX(0x00FA96);
b_pixytest.font = 0; b_pixytest.font=0;
b_pixytest.text = "Pixy"; b_pixytest.text="Pixy";
b_pixytest.callback = b_pixytest_cb; b_pixytest.callback=b_pixytest_cb;
gui_button_add(&b_pixytest); gui_button_add(&b_pixytest);
b_filetest.base.x1 = b_pixytest.base.x2 + BUTTON_SPACING; b_filetest.base.x1=b_pixytest.base.x2+BUTTON_SPACING;
b_filetest.base.y1 = Y_THIRD - 3; b_filetest.base.y1=Y_THIRD-3;
b_filetest.base.x2 = AUTO; b_filetest.base.x2=AUTO;
b_filetest.base.y2 = AUTO; b_filetest.base.y2=AUTO;
b_filetest.txtcolor = BLACK; b_filetest.txtcolor=BLACK;
b_filetest.bgcolor = HEX(0x00FAC4); b_filetest.bgcolor=HEX(0x00FAC4);
b_filetest.font = 0; b_filetest.font=0;
b_filetest.text = "File"; b_filetest.text="File";
b_filetest.callback = b_filetest_cb; b_filetest.callback=b_filetest_cb;
gui_button_add(&b_filetest); gui_button_add(&b_filetest);
//Bottom line //Bottom line
tft_draw_line(0, 145, 319, 145, BLACK); tft_draw_line(0,145,319,145,BLACK);
tft_print_line(10, 150, BLUE, TRANSPARENT, 0, "Powered by"); 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(10,165,"pixy_small.bmp");
tft_draw_bitmap_file_unscaled(165, 165, "stm_small.bmp"); tft_draw_bitmap_file_unscaled(165,165,"stm_small.bmp");
} }
static void leave(void* screen) static void leave(void* screen) {
{ gui_button_remove(&b_our_tracking);
gui_button_remove(&b_our_tracking); gui_button_remove(&b_ref_tracking);
gui_button_remove(&b_ref_tracking); gui_button_remove(&b_photo_mode);
gui_button_remove(&b_photo_mode); gui_button_remove(&b_guitest);
gui_button_remove(&b_guitest); gui_button_remove(&b_pixytest);
gui_button_remove(&b_pixytest); gui_button_remove(&b_filetest);
gui_button_remove(&b_filetest);
} }
static void update(void* screen) static void update(void* screen) {
{ //gui_button_redraw(&b_guitest); //only needed if button is overdrawn by others
//gui_button_redraw(&b_guitest); //only needed if button is overdrawn by others
} }
static SCREEN_STRUCT screen = { static SCREEN_STRUCT screen = {
enter, enter,
leave, leave,
update update
}; };
SCREEN_STRUCT* get_screen_main() SCREEN_STRUCT* get_screen_main() {
{ return &screen;
return &screen;
} }

View File

@@ -1,20 +1,3 @@
/**************************************************************************************************************************************
* 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" #include "screen.h"
/** /**

View File

@@ -1,18 +1,3 @@
/**************************************************************************************************************************************
* 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.h"
#include "screen_photomode_save.h" #include "screen_photomode_save.h"
#include "button.h" #include "button.h"
@@ -20,189 +5,162 @@
#include "touch.h" #include "touch.h"
#include "pixy.h" #include "pixy.h"
#include "system.h" #include "system.h"
#include "pixy_frame.h" #include "pixy_helper.h"
static bool pixy_connected = false; //Whether or not the pixy cam is currently connected static bool pixy_connected = false; //Whether or not the pixy cam is currently connected
static BUTTON_STRUCT b_back; //Button to navigate back static BUTTON_STRUCT b_back; //Button to navigate back
static BUTTON_STRUCT b_save; //Button to save the current image 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 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 //Callback for when the user presses the "back" button
static void b_back_cb(void* button) static void b_back_cb(void* button) {
{ subMenu = false; //we're not entering a submenu
subMenu = false; //we're not entering a submenu gui_screen_back(); //navigate back to the previous screen
gui_screen_back(); //navigate back to the previous screen
} }
//Callback for when the user presses the "save" button //Callback for when the user presses the "save" button
static void b_save_cb(void* button) static void b_save_cb(void* button) {
{ subMenu = true; //we're entering a submenu
subMenu = true; //we're entering a submenu gui_screen_navigate(get_screen_photomodesave()); //navigate to the save screen
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 pixy_pos; //The current position of pixy's servos
static POINT_STRUCT old_pos; //The last touch position on the screen static POINT_STRUCT old_pos; //The last touch position on the screen
//Callback for when the user drags the image around //Callback for when the user drags the image around
static void touchCB(void* touchArea, TOUCH_ACTION triggeredAction) static void touchCB(void* touchArea, TOUCH_ACTION triggeredAction) {
{ POINT_STRUCT p = touch_get_last_point(); //get the last touched point
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;
switch (triggeredAction) { //check limits
case PEN_ENTER: if(new_x<0) new_x=0;
case PEN_DOWN: if(new_x>1000) new_x=1000;
old_pos = p; //If the user "newly" enters the touch area, we set the "last" position to the current 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; break;
case PEN_UP:
case PEN_MOVE: { //the user is moving around, he entered the screen a while ago (old_pos is set) case PEN_LEAVE:
int16_t deltaX = p.x - old_pos.x; //Calculate x difference between last and current touch //printf("Leave/up\n");
int16_t deltaY = p.y - old_pos.y; //Calculate y difference between last and current touch break;
old_pos = p; //store the current touch point for the next time default: break;
}
//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 //Callback for when the screen is entered/loaded
static void enter(void* screen) static void enter(void* screen) {
{ tft_clear(WHITE);
tft_clear(WHITE);
tft_print_line(5,5,BLACK,TRANSPARENT,0,"Drag the image around and ");
tft_print_line(5, 5, BLACK, TRANSPARENT, 0, "Drag the image around and "); //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)
//Back button //Save button
b_back.base.x1 = 5; //Start X of Button b_save.base.x1=190;
b_back.base.y1 = 19; //Start Y of Button b_save.base.y1=3;
b_back.base.x2 = AUTO; //Auto Calculate X2 with String Width b_save.base.x2=AUTO;
b_back.base.y2 = AUTO; //Auto Calculate Y2 with String Height b_save.base.y2=AUTO;
b_back.txtcolor = WHITE; //Set foreground color b_save.txtcolor=WHITE;
b_back.bgcolor = HEX(0xAE1010); //Set background color (Don't take 255 or 0 on at least one channel, to make shadows possible) b_save.bgcolor=HEX(0x1010AE);
b_back.font = 0; //Select Font b_save.font=0;
b_back.text = "Back"; //Set Text (For formatted strings take sprintf) b_save.text="Save it!";
b_back.callback = b_back_cb; //Call b_back_cb as Callback b_save.callback=b_save_cb;
gui_button_add(&b_back); //Register Button (and run the callback from now on) gui_button_add(&b_save);
//Save button //Frame Coordinates: topleft = (1,40); bottomright = (318,238)
b_save.base.x1 = 190; //Leave a 10px border for the area
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);
//Frame Coordinates: topleft = (1,40); bottomright = (318,238) //Area to drag the image around
//Leave a 10px border for the area 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);
//Area to drag the image around //Pixy stuff
a_area.hookedActions = PEN_DOWN | PEN_MOVE | PEN_ENTER | PEN_UP | PEN_LEAVE; pixy_connected = (pixy_init()==0); //try to connect to pixy
a_area.x1 = 11; if(pixy_connected && !subMenu) { //pixy is connected, but we are not coming from a submenu
a_area.y1 = 50; pixy_pos.x=pixy_pos.y=500; //reset servo positions to center
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 //Callback for when the screen is left/unloaded
static void leave(void* screen) static void leave(void* screen) {
{ //remove buttons and touch area.
//remove buttons and touch area. gui_button_remove(&b_back);
gui_button_remove(&b_back); gui_button_remove(&b_save);
gui_button_remove(&b_save); touch_unregister_area(&a_area);
touch_unregister_area(&a_area);
} }
//Callback for when the screen should be updated //Callback for when the screen should be updated
//This is the main loop of the screen. This method will be called repeatedly //This is the main loop of the screen. This method will be called repeatedly
static void update(void* screen) 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 :'(
//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 if(!pixy_connected) { //Pixy not connected
pixy_close(); //Ensure that all pixy resources are freed (failsafe) 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_init() == 0) { //try to connect to pixy if(pixy_connected) { //If we are connected (now)
pixy_connected = true; pixy_service(); //Handle pending pixy events (e.g. color info retrival)
if (!subMenu) { //we're not coming from a submenu pixy_render_full_frame(1,40); //render the pixy video at point (1,40)
pixy_pos.x = pixy_pos.y = 500; //reset servo positions to center
} //set the servo positions to the coordinates form the touch interrupt
pixy_rcs_set_position(0,pixy_pos.x);
printf("pixy (re)initialized\n"); pixy_rcs_set_position(1,pixy_pos.y);
} }
}
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 //Declare screen callbacks
static SCREEN_STRUCT screen = { static SCREEN_STRUCT screen = {
enter, enter,
leave, leave,
update update
}; };
SCREEN_STRUCT* get_screen_photomode() SCREEN_STRUCT* get_screen_photomode() {
{ return &screen;
return &screen;
} }

View File

@@ -1,16 +1,3 @@
/**************************************************************************************************************************************
* 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" #include "screen.h"
/** /**

View File

@@ -1,24 +1,10 @@
/**************************************************************************************************************************************
* 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 "screen_photomode_save.h"
#include "filesystem.h" #include "filesystem.h"
#include "button.h" #include "button.h"
#include "tft.h" #include "tft.h"
#include "touch.h" #include "touch.h"
#include "pixy.h" #include "pixy.h"
#include "pixy_frame.h" #include "pixy_helper.h"
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@@ -27,9 +13,8 @@ static BUTTON_STRUCT b_back; //Button to navigate back
static TOUCH_AREA_STRUCT a_area; //Touch area to select the save-file static TOUCH_AREA_STRUCT a_area; //Touch area to select the save-file
//Callback for when the user presses the "back" button //Callback for when the user presses the "back" button
static void b_back_cb(void* button) static void b_back_cb(void* button) {
{ gui_screen_back();
gui_screen_back();
} }
static int num_files_ok; //number of files into which we can write the image (size, flags ok) static int num_files_ok; //number of files into which we can write the image (size, flags ok)
@@ -39,51 +24,46 @@ 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 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. //Linked list structure to save all files which are suitable for saving.
typedef struct FILE_LIST_ENTRY_S { typedef struct FILE_LIST_ENTRY_S{
char* filename; //Name of the file char* filename; //Name of the file
struct FILE_LIST_ENTRY_S* next; //Pointer to the next entry in the list or NULL struct FILE_LIST_ENTRY_S* next; //Pointer to the next entry in the list or NULL
} FILE_LIST_ENTRY; } FILE_LIST_ENTRY;
static FILE_LIST_ENTRY* files_ok; //Pointer to the head of the list 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 //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 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 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)
if (elem < 0 | elem >= num_files_ok) { //Search for the corresponding entry in the linked list
return; //Check if the file index is valid (0,1,..,num_files_ok-1) 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
}
//Search for the corresponding entry in the linked list picked_file = current_entry->filename; //save the picked filename. It will be used by the statemachine in the main loop
FILE_LIST_ENTRY* current_entry = files_ok; //Start walking through the list, starting by the head of the list 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
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) //Text-Lines to show if we have no matching files (num_files_ok==0)
static const char* nomatch_text [] = { static const char* nomatch_text [] = {
"Due to limitations of the filesystem", "Due to limitations of the filesystem",
"implementation you can only write to", "implementation you can only write to",
"existing files.", "existing files.",
"", "",
"The files need to have a .bmp", "The files need to have a .bmp",
"extension and must be at least", "extension and must be at least",
"189410 bytes (185kb) large.", "189410 bytes (185kb) large.",
"Unfortunately there were no such", "Unfortunately there were no such",
"files found in the root directory.", "files found in the root directory.",
"", "",
"Please create some files and come", "Please create some files and come",
"back again.", "back again.",
NULL NULL
}; };
@@ -91,251 +71,231 @@ static const char* nomatch_text [] = {
//This header has been taken from a white bitmap saved with gimp. //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 //Wikipedia has a pretty good description on the header: http://de.wikipedia.org/wiki/Windows_Bitmap
static unsigned char bmpheader_data[0x7A] = { static unsigned char bmpheader_data[0x7A] = {
0x42, 0x4d, 0xe2, 0xe3, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 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, 0x6c, 0x00, 0x00, 0x00, 0x3e, 0x01, 0x00, 0x00, 0xc6, 0x00,
0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0xe3, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0xe3,
0x02, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00, 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, 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, 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, 0x02, 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
}; };
//Callback for when the screen is entered/loaded //Callback for when the screen is entered/loaded
static void enter(void* screen) static void enter(void* screen) {
{ tft_clear(WHITE);
tft_clear(WHITE);
#define X_OFS 5 #define X_OFS 5
//Back button //Back button
b_back.base.x1 = X_OFS; //Start X of Button b_back.base.x1=X_OFS; //Start X of Button
b_back.base.y1 = 210; //Start Y 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.x2=AUTO; //Auto Calculate X2 with String Width
b_back.base.y2 = AUTO; //Auto Calculate Y2 with String Height b_back.base.y2=AUTO; //Auto Calculate Y2 with String Height
b_back.txtcolor = WHITE; //Set foreground color 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.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.font=0; //Select Font
b_back.text = "Back"; //Set Text (For formatted strings take sprintf) b_back.text="Back"; //Set Text (For formatted strings take sprintf)
b_back.callback = b_back_cb; //Call b_back_cb as Callback 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) gui_button_add(&b_back); //Register Button (and run the callback from now on)
state = init; //Start with the init state state =init; //Start with the init state
fontheight = tft_font_height(0) + 2; //Save the height of the used font, for fast access 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 files_ok = NULL; //initialize the linked list with 0 elements
num_files_ok = 0; //we have zero! elements num_files_ok = 0; //we have zero! elements
} }
//Callback for when the screen should be updated //Callback for when the screen should be updated
//This is the main loop of the screen. This method will be called repeatedly //This is the main loop of the screen. This method will be called repeatedly
static void update(void* screen) static void update(void* screen) {
{ switch(state) {
switch (state) { case init: //Init State: The user just entered the screen
case init: { //Init State: The user just entered the screen {
DIRECTORY_STRUCT* dir = filesystem_dir_open("."); //open root directory 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;
}
if (dir == NULL) { //error while opening root directory bool nomatch= true; //whether or not we have zero files which are suitable for saving
tft_print_line(X_OFS, 5, BLACK, TRANSPARENT, 0, "Error accessing Filesystem");
state = error;
break;
}
bool nomatch = true; //whether or not we have zero files which are suitable for saving 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
for (int i = 0; i < dir->num_files; i++) { //walk through all files in the directory //Ignore directories, archives, hidden files, system files and files we cannot write to
FILE_STRUCT* file = &(dir->files[i]); //Pointer to the current file/subdirectory if(file->fattrib&(F_SYS|F_HID|F_ARC|F_DIR|F_RDO)) continue;
//Ignore directories, archives, hidden files, system files and files we cannot write to //ignore files which are not large enough
if (file->fattrib & (F_SYS | F_HID | F_ARC | F_DIR | F_RDO)) { if(file->fsize<189410) continue; //size taken from an example bitmap (318x198x24)
continue;
}
//ignore files which are not large enough nomatch=false; //at least one file matches
if (file->fsize < 189410) { break;
continue; //size taken from an example bitmap (318x198x24) }
}
nomatch = false; //at least one file matches if(nomatch) { //not one file is suitable for writing
break; 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;
}
if (nomatch) { //not one file is suitable for writing filesystem_dir_close(dir); //free directory struct
int y = 5; //y-Coordinate where to start writing the error text }
int i = 0; break;
while (nomatch_text[i] != NULL) { //for every line in the big error array case showlist: //Show List State: Where we load and present the suitable file's to the user in a list
//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]); DIRECTORY_STRUCT* dir2 = filesystem_dir_open("."); //Open the directory again
i++; if(dir2==NULL) return; //Error on opening? This should never happen, since it's handled in the previous state
}
state = error; int y = 5; //y-Coordinate where to start drawing/writing text/list-elements
} else { //we have a least one suitable file
state = showlist;
}
filesystem_dir_close(dir); //free directory struct tft_print_line(X_OFS,y,BLACK,TRANSPARENT,0,"Pick a file to save the image to");
} y+=fontheight+5;
break;
case showlist: { //Show List State: Where we load and present the suitable file's to the user in a list tft_print_line(X_OFS,y,BLUE,TRANSPARENT,0,"Name Modified Size");
DIRECTORY_STRUCT* dir2 = filesystem_dir_open("."); //Open the directory again y+=fontheight;
if (dir2 == NULL) { liststart = y; //store the y coordinate of the start of the list away (used in toucharea callback)
return; //Error on opening? This should never happen, since it's handled in the previous state num_files_ok = 0; //we start with 0 matching files
}
int y = 5; //y-Coordinate where to start drawing/writing text/list-elements FILE_LIST_ENTRY* current_entry = NULL; //We start with an empty list
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]);
tft_print_line(X_OFS, y, BLACK, TRANSPARENT, 0, "Pick a file to save the image to"); //Ignore directories, archives, hidden files, system files and files we cannot write to
y += fontheight + 5; if(file->fattrib&(F_SYS|F_HID|F_ARC|F_DIR|F_RDO)) continue;
tft_print_line(X_OFS, y, BLUE, TRANSPARENT, 0, "Name Modified Size"); //ignore files which are not large enough
y += fontheight; if(file->fsize<189410) continue; //size taken from an example bitmap (318x198x24)
liststart = y; //store the y coordinate of the start of the list away (used in toucharea callback) //Print out filename, modified date,time and file size
num_files_ok = 0; //we start with 0 matching files 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);
FILE_LIST_ENTRY* current_entry = NULL; //We start with an empty list 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)
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 //since we have found a suitable file we need to increment the position in the list
FILE_STRUCT* file = &(dir2->files[i]); num_files_ok++;
y+=fontheight;
}
//Ignore directories, archives, hidden files, system files and files we cannot write to //Touch area for file-selection (in the list)
if (file->fattrib & (F_SYS | F_HID | F_ARC | F_DIR | F_RDO)) { a_area.hookedActions = PEN_UP; //we're only interested in PEN_UP events
continue; 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 files which are not large enough filesystem_dir_close(dir2); //we no longer need the directory struct, since we have our own linked list now
if (file->fsize < 189410) {
continue; //size taken from an example bitmap (318x198x24)
}
//Print out filename, modified date,time and file size state=picking;
tft_print_formatted(X_OFS, y, BLACK, }
TRANSPARENT, 0, "%-16s %02u.%02u.%02u %02u:%02u:%02u %u", break;
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);
if (current_entry == NULL) { //The list is empty case picking: //Picking State: Where we wait on the users file choice
current_entry = malloc(sizeof(FILE_LIST_ENTRY)); //create new entry pixy_service(); //Handle pending pixy events
files_ok = current_entry; //assign it to the list head //do nothing and wait on user to pick a file
} else { //there's a least one entry in the list break;
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) case saving: //Saving State: Where we save the image to the selected file
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_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;
}
//since we have found a suitable file we need to increment the position in the list filesystem_file_seek(file,0); //seek to the start of the file (optional?)
num_files_ok++; if(filesystem_file_write(file,bmpheader_data,0x7A)!=F_OK) { //Writing the header failed
y += fontheight; 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) if(pixy_save_full_frame(file)!=0) { //Writing the imagedata failed
a_area.hookedActions = PEN_UP; //we're only interested in PEN_UP events tft_print_formatted(X_OFS,190,BLUE,TRANSPARENT,0,"Error while writing to %s",picked_file);
a_area.x1 = X_OFS; //Left border filesystem_file_close(file);
a_area.y1 = liststart; //Start where the list started state=error;
a_area.x2 = 320 - X_OFS; //Right border break;
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
filesystem_dir_close(dir2); //we no longer need the directory struct, since we have our own linked list now //if we reach this point, we have written all data out successfully
state = picking; filesystem_file_close(file); //close/finalize the file
} tft_print_formatted(X_OFS,190,BLUE,TRANSPARENT,0,"Image saved to %s",picked_file);
break; state = done;
}
break;
case picking: //Picking State: Where we wait on the users file choice case error: //Error State: Where we show an error message and leave the user no other choice than to click the backbutton
pixy_service(); //Handle pending pixy events case done: //Done State: When saving the file was successful
//do nothing and wait on user to pick a file pixy_service(); //Handle pending pixy events
break; //wait on user to click the back button
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 //Callback for when the screen is left/unloaded
static void leave(void* screen) static void leave(void* screen) {
{ gui_button_remove(&b_back); //Remove/Free the back button
gui_button_remove(&b_back); //Remove/Free the back button
if (state == picking) { //The user left the screen in the "picking"-phase if(state==picking){ //The user left the screen in the "picking"-phase
touch_unregister_area(&a_area); //remove the touch area (for the list) 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 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 //Iterate through the linked list and free all resources
FILE_LIST_ENTRY* current_entry = files_ok; //start with the list head FILE_LIST_ENTRY* current_entry = files_ok; //start with the list head
while(current_entry!=NULL) { //while we're not at the end
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
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((void*)(current_entry->filename)); //free filename free(current_entry); //free element itself
free(current_entry); //free element itself current_entry= temp; //advance
current_entry = temp; //advance }
} }
}
} }
//Declare screen callbacks //Declare screen callbacks
static SCREEN_STRUCT screen = { static SCREEN_STRUCT screen = {
enter, enter,
leave, leave,
update update
}; };
SCREEN_STRUCT* get_screen_photomodesave() SCREEN_STRUCT* get_screen_photomodesave() {
{ return &screen;
return &screen;
} }

View File

@@ -1,16 +1,3 @@
/**************************************************************************************************************************************
* 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" #include "screen.h"
/** /**
@@ -33,3 +20,4 @@ SCREEN_STRUCT* get_screen_photomodesave();
/*@}*/ /*@}*/
/*@}*/ /*@}*/

View File

@@ -1,23 +1,3 @@
/**************************************************************************************************************************************
* 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 "screen_pixytest.h"
#include "button.h" #include "button.h"
#include "numupdown.h" #include "numupdown.h"
@@ -25,9 +5,9 @@
#include "touch.h" #include "touch.h"
#include "pixy.h" #include "pixy.h"
#include "system.h" #include "system.h"
#include "pixy_frame.h" #include "pixy_helper.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; static BUTTON_STRUCT b_back;
@@ -50,328 +30,313 @@ static uint32_t led_maxcurrent;
static NUMUPDOWN_STRUCT n_led_powerlimit; static NUMUPDOWN_STRUCT n_led_powerlimit;
static void b_back_cb(void* button) static void b_back_cb(void* button) {
{ gui_screen_back();
gui_screen_back();
} }
static void b_servos_center_cb(void* button) static void b_servos_center_cb(void* button) {
{ if(state==idle) {
if (state == idle) { servo_x=500;
servo_x = 500; servo_y=500;
servo_y = 500; state=update_servos;
state = update_servos; }
}
} }
static void b_servos_topleft_cb(void* button) static void b_servos_topleft_cb(void* button) {
{ if(state==idle) {
if (state == idle) { servo_x=0;
servo_x = 0; servo_y=0;
servo_y = 0; state=update_servos;
state = update_servos; }
}
} }
static void b_servos_topright_cb(void* button) static void b_servos_topright_cb(void* button) {
{ if(state==idle) {
if (state == idle) { servo_x=1000;
servo_x = 1000; servo_y=0;
servo_y = 0; state=update_servos;
state = update_servos; }
}
} }
static void b_servos_bottomleft_cb(void* button) static void b_servos_bottomleft_cb(void* button) {
{ if(state==idle) {
if (state == idle) { servo_x=0;
servo_x = 0; servo_y=1000;
servo_y = 1000; state=update_servos;
state = update_servos; }
}
} }
static void b_servos_bottomright_cb(void* button) static void b_servos_bottomright_cb(void* button) {
{ if(state==idle) {
if (state == idle) { servo_x=1000;
servo_x = 1000; servo_y=1000;
servo_y = 1000; state=update_servos;
state = update_servos; }
}
} }
static void b_led_off_cb(void* button) static void b_led_off_cb(void* button) {
{ if(state==idle) {
if (state == idle) { led_color=0x000000;
led_color = 0x000000; state=update_ledcolor;
state = update_ledcolor; }
}
} }
static void b_led_white_cb(void* button) static void b_led_white_cb(void* button) {
{ if(state==idle) {
if (state == idle) { led_color=0xFFFFFF;
led_color = 0xFFFFFF; state=update_ledcolor;
state = update_ledcolor; }
}
} }
static void b_led_red_cb(void* button) static void b_led_red_cb(void* button) {
{ if(state==idle) {
if (state == idle) { led_color=0xFF0000;
led_color = 0xFF0000; state=update_ledcolor;
state = update_ledcolor; }
}
} }
static void b_led_green_cb(void* button) static void b_led_green_cb(void* button) {
{ if(state==idle) {
if (state == idle) { led_color=0x00FF00;
led_color = 0x00FF00; state=update_ledcolor;
state = update_ledcolor; }
}
} }
static void b_led_blue_cb(void* button) static void b_led_blue_cb(void* button) {
{ if(state==idle) {
if (state == idle) { led_color=0x0000FF;
led_color = 0x0000FF; state=update_ledcolor;
state = update_ledcolor; }
}
} }
static void n_led_powerlimit_cb(void* numupdown, int16_t value) static void n_led_powerlimit_cb(void* numupdown, int16_t value) {
{ if(state==idle) {
if (state == idle) { led_maxcurrent=value;
led_maxcurrent = value; state=update_ledcurrent;
state = update_ledcurrent; }
}
} }
static void enter(void* screen) static void enter(void* screen) {
{ tft_clear(WHITE);
tft_clear(WHITE);
//Back button
//Back button b_back.base.x1=10; //Start X of Button
b_back.base.x1 = 10; //Start X of Button b_back.base.y1=210; //Start Y 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.x2 = AUTO; //Auto Calculate X2 with String Width b_back.base.y2=AUTO; //Auto Calculate Y2 with String Height
b_back.base.y2 = AUTO; //Auto Calculate Y2 with String Height b_back.txtcolor=WHITE; //Set foreground color
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.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.font = 0; //Select Font b_back.text="Back"; //Set Text (For formatted strings take sprintf)
b_back.text = "Back"; //Set Text (For formatted strings take sprintf) b_back.callback=b_back_cb; //Call b_back_cb as Callback
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)
gui_button_add(&b_back); //Register Button (and run the callback from now on)
//Servo stuff //Servo stuff
#define SERVO_BUTTON_Y 10 #define SERVO_BUTTON_Y 10
#define SERVO_BUTTON_SPACING 5 #define SERVO_BUTTON_SPACING 5
tft_print_line(5, SERVO_BUTTON_Y, BLACK, TRANSPARENT, 0, "Servos:"); tft_print_line(5,SERVO_BUTTON_Y,BLACK,TRANSPARENT,0,"Servos:");
b_servos_center.base.x1 = 55; b_servos_center.base.x1=55;
b_servos_center.base.y1 = SERVO_BUTTON_Y - 3; b_servos_center.base.y1=SERVO_BUTTON_Y-3;
b_servos_center.base.x2 = AUTO; b_servos_center.base.x2=AUTO;
b_servos_center.base.y2 = AUTO; b_servos_center.base.y2=AUTO;
b_servos_center.txtcolor = WHITE; b_servos_center.txtcolor=WHITE;
b_servos_center.bgcolor = HEX(0xAE1010); b_servos_center.bgcolor=HEX(0xAE1010);
b_servos_center.font = 0; b_servos_center.font=0;
b_servos_center.text = "Center"; b_servos_center.text="Center";
b_servos_center.callback = b_servos_center_cb; b_servos_center.callback=b_servos_center_cb;
gui_button_add(&b_servos_center); gui_button_add(&b_servos_center);
b_servos_topleft.base.x1 = b_servos_center.base.x2 + SERVO_BUTTON_SPACING; 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.y1=SERVO_BUTTON_Y-3;
b_servos_topleft.base.x2 = AUTO; b_servos_topleft.base.x2=AUTO;
b_servos_topleft.base.y2 = AUTO; b_servos_topleft.base.y2=AUTO;
b_servos_topleft.txtcolor = WHITE; b_servos_topleft.txtcolor=WHITE;
b_servos_topleft.bgcolor = HEX(0xAE1010); b_servos_topleft.bgcolor=HEX(0xAE1010);
b_servos_topleft.font = 0; b_servos_topleft.font=0;
b_servos_topleft.text = "ToLe"; b_servos_topleft.text="ToLe";
b_servos_topleft.callback = b_servos_topleft_cb; b_servos_topleft.callback=b_servos_topleft_cb;
gui_button_add(&b_servos_topleft); gui_button_add(&b_servos_topleft);
b_servos_topright.base.x1 = b_servos_topleft.base.x2 + SERVO_BUTTON_SPACING; 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.y1=SERVO_BUTTON_Y-3;
b_servos_topright.base.x2 = AUTO; b_servos_topright.base.x2=AUTO;
b_servos_topright.base.y2 = AUTO; b_servos_topright.base.y2=AUTO;
b_servos_topright.txtcolor = WHITE; b_servos_topright.txtcolor=WHITE;
b_servos_topright.bgcolor = HEX(0xAE1010); b_servos_topright.bgcolor=HEX(0xAE1010);
b_servos_topright.font = 0; b_servos_topright.font=0;
b_servos_topright.text = "ToRi"; b_servos_topright.text="ToRi";
b_servos_topright.callback = b_servos_topright_cb; b_servos_topright.callback=b_servos_topright_cb;
gui_button_add(&b_servos_topright); gui_button_add(&b_servos_topright);
b_servos_bottomleft.base.x1 = b_servos_topright.base.x2 + SERVO_BUTTON_SPACING; 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.y1=SERVO_BUTTON_Y-3;
b_servos_bottomleft.base.x2 = AUTO; b_servos_bottomleft.base.x2=AUTO;
b_servos_bottomleft.base.y2 = AUTO; b_servos_bottomleft.base.y2=AUTO;
b_servos_bottomleft.txtcolor = WHITE; b_servos_bottomleft.txtcolor=WHITE;
b_servos_bottomleft.bgcolor = HEX(0xAE1010); b_servos_bottomleft.bgcolor=HEX(0xAE1010);
b_servos_bottomleft.font = 0; b_servos_bottomleft.font=0;
b_servos_bottomleft.text = "BoLe"; b_servos_bottomleft.text="BoLe";
b_servos_bottomleft.callback = b_servos_bottomleft_cb; b_servos_bottomleft.callback=b_servos_bottomleft_cb;
gui_button_add(&b_servos_bottomleft); gui_button_add(&b_servos_bottomleft);
b_servos_bottomright.base.x1 = b_servos_bottomleft.base.x2 + SERVO_BUTTON_SPACING; 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.y1=SERVO_BUTTON_Y-3;
b_servos_bottomright.base.x2 = AUTO; b_servos_bottomright.base.x2=AUTO;
b_servos_bottomright.base.y2 = AUTO; b_servos_bottomright.base.y2=AUTO;
b_servos_bottomright.txtcolor = WHITE; b_servos_bottomright.txtcolor=WHITE;
b_servos_bottomright.bgcolor = HEX(0xAE1010); b_servos_bottomright.bgcolor=HEX(0xAE1010);
b_servos_bottomright.font = 0; b_servos_bottomright.font=0;
b_servos_bottomright.text = "BoRi"; b_servos_bottomright.text="BoRi";
b_servos_bottomright.callback = b_servos_bottomright_cb; b_servos_bottomright.callback=b_servos_bottomright_cb;
gui_button_add(&b_servos_bottomright); gui_button_add(&b_servos_bottomright);
//Led Color stuff //Led Color stuff
#define LED_COLOR_BUTTON_Y 35 #define LED_COLOR_BUTTON_Y 35
#define LED_COLOR_BUTTON_SPACING 5 #define LED_COLOR_BUTTON_SPACING 5
tft_print_line(5, LED_COLOR_BUTTON_Y, BLACK, TRANSPARENT, 0, "Led Color:"); tft_print_line(5,LED_COLOR_BUTTON_Y,BLACK,TRANSPARENT,0,"Led Color:");
b_led_off.base.x1 = 85; b_led_off.base.x1=85;
b_led_off.base.y1 = LED_COLOR_BUTTON_Y - 3; b_led_off.base.y1=LED_COLOR_BUTTON_Y-3;
b_led_off.base.x2 = AUTO; b_led_off.base.x2=AUTO;
b_led_off.base.y2 = AUTO; b_led_off.base.y2=AUTO;
b_led_off.txtcolor = WHITE; b_led_off.txtcolor=WHITE;
b_led_off.bgcolor = BLACK; b_led_off.bgcolor=BLACK;
b_led_off.font = 0; b_led_off.font=0;
b_led_off.text = "Off"; b_led_off.text="Off";
b_led_off.callback = b_led_off_cb; b_led_off.callback=b_led_off_cb;
gui_button_add(&b_led_off); gui_button_add(&b_led_off);
b_led_white.base.x1 = b_led_off.base.x2 + LED_COLOR_BUTTON_SPACING; 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.y1=LED_COLOR_BUTTON_Y-3;
b_led_white.base.x2 = AUTO; b_led_white.base.x2=AUTO;
b_led_white.base.y2 = AUTO; b_led_white.base.y2=AUTO;
b_led_white.txtcolor = BLACK; b_led_white.txtcolor=BLACK;
b_led_white.bgcolor = HEX(0xEEEEEE); b_led_white.bgcolor=HEX(0xEEEEEE);
b_led_white.font = 0; b_led_white.font=0;
b_led_white.text = "White"; b_led_white.text="White";
b_led_white.callback = b_led_white_cb; b_led_white.callback=b_led_white_cb;
gui_button_add(&b_led_white); gui_button_add(&b_led_white);
b_led_red.base.x1 = b_led_white.base.x2 + LED_COLOR_BUTTON_SPACING; 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.y1=LED_COLOR_BUTTON_Y-3;
b_led_red.base.x2 = AUTO; b_led_red.base.x2=AUTO;
b_led_red.base.y2 = AUTO; b_led_red.base.y2=AUTO;
b_led_red.txtcolor = WHITE; b_led_red.txtcolor=WHITE;
b_led_red.bgcolor = HEX(0xEE0000); b_led_red.bgcolor=HEX(0xEE0000);
b_led_red.font = 0; b_led_red.font=0;
b_led_red.text = "Red"; b_led_red.text="Red";
b_led_red.callback = b_led_red_cb; b_led_red.callback=b_led_red_cb;
gui_button_add(&b_led_red); gui_button_add(&b_led_red);
b_led_green.base.x1 = b_led_red.base.x2 + LED_COLOR_BUTTON_SPACING; 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.y1=LED_COLOR_BUTTON_Y-3;
b_led_green.base.x2 = AUTO; b_led_green.base.x2=AUTO;
b_led_green.base.y2 = AUTO; b_led_green.base.y2=AUTO;
b_led_green.txtcolor = WHITE; b_led_green.txtcolor=WHITE;
b_led_green.bgcolor = HEX(0x00EE00); b_led_green.bgcolor=HEX(0x00EE00);
b_led_green.font = 0; b_led_green.font=0;
b_led_green.text = "Green"; b_led_green.text="Green";
b_led_green.callback = b_led_green_cb; b_led_green.callback=b_led_green_cb;
gui_button_add(&b_led_green); gui_button_add(&b_led_green);
b_led_blue.base.x1 = b_led_green.base.x2 + LED_COLOR_BUTTON_SPACING; 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.y1=LED_COLOR_BUTTON_Y-3;
b_led_blue.base.x2 = AUTO; b_led_blue.base.x2=AUTO;
b_led_blue.base.y2 = AUTO; b_led_blue.base.y2=AUTO;
b_led_blue.txtcolor = WHITE; b_led_blue.txtcolor=WHITE;
b_led_blue.bgcolor = HEX(0x0000EE); b_led_blue.bgcolor=HEX(0x0000EE);
b_led_blue.font = 0; b_led_blue.font=0;
b_led_blue.text = "Blue"; b_led_blue.text="Blue";
b_led_blue.callback = b_led_blue_cb; b_led_blue.callback=b_led_blue_cb;
gui_button_add(&b_led_blue); gui_button_add(&b_led_blue);
//Led MaxPower stuff //Led MaxPower stuff
#define LED_POWER_BUTTON_Y 70 #define LED_POWER_BUTTON_Y 70
tft_print_line(5, LED_POWER_BUTTON_Y, BLACK, TRANSPARENT, 0, "Led Maximum Current:"); tft_print_line(5,LED_POWER_BUTTON_Y,BLACK,TRANSPARENT,0,"Led Maximum Current:");
//Num up down test //Num up down test
n_led_powerlimit.x = 160; n_led_powerlimit.x=160;
n_led_powerlimit.y = LED_POWER_BUTTON_Y - 7; n_led_powerlimit.y=LED_POWER_BUTTON_Y-7;
n_led_powerlimit.fgcolor = WHITE; n_led_powerlimit.fgcolor=WHITE;
n_led_powerlimit.value = 10; n_led_powerlimit.value = 10;
n_led_powerlimit.max = 40; n_led_powerlimit.max=40;
n_led_powerlimit.min = 0; n_led_powerlimit.min =0;
n_led_powerlimit.callback = n_led_powerlimit_cb; n_led_powerlimit.callback=n_led_powerlimit_cb;
gui_numupdown_add(&n_led_powerlimit); gui_numupdown_add(&n_led_powerlimit);
state = detecting; state=detecting;
} }
static void leave(void* screen) static void leave(void* screen) {
{ gui_button_remove(&b_back);
gui_button_remove(&b_back); gui_button_remove(&b_servos_center);
gui_button_remove(&b_servos_center); gui_button_remove(&b_servos_topleft);
gui_button_remove(&b_servos_topleft); gui_button_remove(&b_servos_topright);
gui_button_remove(&b_servos_topright); gui_button_remove(&b_servos_bottomleft);
gui_button_remove(&b_servos_bottomleft); gui_button_remove(&b_servos_bottomright);
gui_button_remove(&b_servos_bottomright); gui_button_remove(&b_led_off);
gui_button_remove(&b_led_off); gui_button_remove(&b_led_white);
gui_button_remove(&b_led_white); gui_button_remove(&b_led_red);
gui_button_remove(&b_led_red); gui_button_remove(&b_led_green);
gui_button_remove(&b_led_green); gui_button_remove(&b_led_blue);
gui_button_remove(&b_led_blue); gui_numupdown_remove(&n_led_powerlimit);
gui_numupdown_remove(&n_led_powerlimit);
} }
static void update(void* screen) static void update(void* screen) {
{ switch(state) {
switch (state) { case detecting: //Detecting State: Where we try to connect to the pixy
case detecting: //Detecting State: Where we try to connect to the pixy if(pixy_init()==0) { //Pixy connection ok
if (pixy_init() == 0) { //Pixy connection ok int32_t response;
int32_t response; int return_value;
int return_value; return_value = pixy_command("stop", END_OUT_ARGS, &response, END_IN_ARGS);
return_value = pixy_command("stop", END_OUT_ARGS, &response, END_IN_ARGS); pixy_led_set_max_current(10);
pixy_led_set_max_current(10);
state = idle; //Go to next state 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;
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 idle: case update_ledcurrent:
pixy_service(); pixy_led_set_max_current(led_maxcurrent);
break; state = idle;
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 = { static SCREEN_STRUCT screen = {
enter, enter,
leave, leave,
update update
}; };
SCREEN_STRUCT* get_screen_pixytest() SCREEN_STRUCT* get_screen_pixytest() {
{ return &screen;
return &screen;
} }

View File

@@ -1,18 +1,3 @@
/**************************************************************************************************************************************
* 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" #include "screen.h"
/** /**

View File

@@ -1,31 +1,11 @@
/**************************************************************************************************************************************
* 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 "screen_tracking.h"
#include "pixy_control.h"
#include "button.h" #include "button.h"
#include "checkbox.h" #include "checkbox.h"
#include "tft.h" #include "tft.h"
#include "touch.h" #include "touch.h"
#include "pixy.h" #include "pixy.h"
#include "system.h" #include "system.h"
#include "pixy_frame.h" #include "pixy_helper.h"
static BUTTON_STRUCT b_back; //Button to navigate back static BUTTON_STRUCT b_back; //Button to navigate back
static BUTTON_STRUCT b_select; //Button to start the color region selection static BUTTON_STRUCT b_select; //Button to start the color region selection
@@ -33,16 +13,14 @@ 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 static TOUCH_AREA_STRUCT a_area; //Touch area for the color region selection
//Callback for when the user presses the "back" button //Callback for when the user presses the "back" button
static void b_back_cb(void* button) static void b_back_cb(void* button) {
{ gui_screen_back(); //navigate back to the previous screen
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 volatile bool frame_visible = false; //Whether or not the video data should be displayed
static void c_frame_toggle_cb(void* checkbox, bool checked) 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_visible = checked; //Set the visibility of the frame to the checked state of the checkbox //Frame will be drawn in the main loop below
//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 static enum {detecting, init, tracking, preselecting, abortselecting, selecting, selected, error} state; //Current state of the screen state machine
@@ -52,13 +30,12 @@ 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 static bool point1_valid; //Whether or not we have a valid first point
//Callback for when the user presses the "select color" button //Callback for when the user presses the "select color" button
static void b_select_cb(void* button) static void b_select_cb(void* button) {
{ if(state==selecting) { //we're currently selecting a color region
if (state == selecting) { //we're currently selecting a color region state = abortselecting; //Abort selecting!!
state = abortselecting; //Abort selecting!! } else if (state==tracking) { //we're currently watching the tracking
} else if (state == tracking) { //we're currently watching the tracking state = preselecting; //start selecting
state = preselecting; //start selecting }
}
} }
//Video Region properties //Video Region properties
@@ -72,350 +49,301 @@ static void b_select_cb(void* button)
//Callback for when the user touches the frame area to select a color region. //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 //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) static void touchCB(void* touchArea, TOUCH_ACTION triggeredAction) {
{ POINT_STRUCT p = touch_get_last_point();
POINT_STRUCT p = touch_get_last_point(); switch(triggeredAction) {
case PEN_DOWN: //The user just put down the pen
switch (triggeredAction) { point1.x = p.x-FRAME_START_X; //Calculate x-Coordinate relative to frame start
case PEN_DOWN: //The user just put down the pen point1.y = p.y-FRAME_START_Y; //Calculate y-Coordinate relative to frame start
point1.x = p.x - FRAME_START_X; //Calculate x-Coordinate relative to frame start point1_valid= true; //The point1 is now valid
point1.y = p.y - FRAME_START_Y; //Calculate y-Coordinate relative to frame start break;
point1_valid = true; //The point1 is now valid case PEN_UP: //The user took the pen away
break; if(point1_valid) { //only execute if point1 is valid
point2.x = p.x-FRAME_START_X; //Calculate x-Coordinate relative to frame start
case PEN_UP: //The user took the pen away point2.y = p.y-FRAME_START_Y; //Calculate y-Coordinate relative to frame start
if (point1_valid) { //only execute if point1 is valid state = selected;
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 break;
state = selected; }
}
break;
}
} }
//Prototype for tracking start/stop methods //Prototype for tracking start/stop methods
typedef void (*TRACKING_VOID_CALLBACK)(void* tracking_config); typedef void (*TRACKING_VOID_CALLBACK)(void* tracking_config);
//Prototype for tracking update method //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 //Structure to save callbacks and settings of a tracking implementation
typedef struct { typedef struct {
TRACKING_VOID_CALLBACK start; TRACKING_VOID_CALLBACK start;
TRACKING_VOID_CALLBACK stop; TRACKING_VOID_CALLBACK stop;
TRACKING_BLOCK_CALLBACK update; TRACKING_BLOCK_CALLBACK update;
} TRACKING_CONFIG_STRUCT; } TRACKING_CONFIG_STRUCT;
//Methods for our tracking implementation ahead //Methods for our tracking implementation ahead
static int16_t servo_x = 0;
static int16_t servo_y = 0;
//Method/Callback to start our tracking //Method/Callback to start our tracking
void tracking_our_start(void* tracking_config) void tracking_our_start(void* tracking_config) {
{ //Activate pixy's data send program
//Activate pixy's data send program int32_t response;
int32_t response; int return_value;
int return_value; return_value = pixy_command("runprog", INT8(0), END_OUT_ARGS, &response, END_IN_ARGS);
servo_x = servo_y = 500; // set a default value of 500
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);
} }
//Method/Callback to stop our tracking //Method/Callback to stop our tracking
void tracking_our_stop(void* tracking_config) void tracking_our_stop(void* tracking_config) {
{ //Stop pixy's data send programm
//Stop pixy's data send programm int32_t response;
int32_t response; int return_value;
int return_value; return_value = pixy_command("stop", END_OUT_ARGS, &response, END_IN_ARGS);
return_value = pixy_command("stop", END_OUT_ARGS, &response, END_IN_ARGS);
} }
//Method/Callback to calculate one step of our tracking //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) {
{ //TODO: Implement tracking!
//Calculate new servo pos and set the new servo pos
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 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
servo_x = xset; // update the global, static variable for x
servo_y = yset; // update the global, statuc variable for y
pixy_rcs_set_position(0, servo_x); // set the new x position
pixy_rcs_set_position(1, servo_y); // set the new y position
} }
//Variable which stores all the callbacks and settings for our tracking implementation //Variable which stores all the callbacks and settings for our tracking implementation
static TRACKING_CONFIG_STRUCT tracking_our = { static TRACKING_CONFIG_STRUCT tracking_our = {
tracking_our_start, tracking_our_start,
tracking_our_stop, tracking_our_stop,
tracking_our_update tracking_our_update
}; };
//Methods for reference tracking implementation ahead //Methods for reference tracking implementation ahead
//Method/Callback to start reference tracking //Method/Callback to start reference tracking
void tracking_reference_start(void* tracking_config) void tracking_reference_start(void* tracking_config) {
{ //Run reference tracking
//Run reference tracking int32_t response;
int32_t response; int return_value;
int return_value; return_value = pixy_command("runprog", INT8(2), END_OUT_ARGS, &response, END_IN_ARGS);
return_value = pixy_command("runprog", INT8(2), END_OUT_ARGS, &response, END_IN_ARGS);
} }
//Method/Callback to stop reference tracking //Method/Callback to stop reference tracking
void tracking_reference_stop(void* tracking_config) void tracking_reference_stop(void* tracking_config) {
{ //Stop reference tracking
//Stop reference tracking int32_t response;
int32_t response; int return_value;
int return_value; return_value = pixy_command("stop", END_OUT_ARGS, &response, END_IN_ARGS);
return_value = pixy_command("stop", END_OUT_ARGS, &response, END_IN_ARGS);
} }
//Method/Callback to calculate one step of the reference tracking //Method/Callback to calculate one step of the reference tracking
void tracking_reference_update(void* tracking_config, struct Block* blocks, int num_blocks) void tracking_reference_update(void* tracking_config, struct Block* blocks, int num_blocks) {
{ //Nothing to do here. Pixy does it all.
//Nothing to do here. Pixy does it all.
} }
//Variable which stores all the callbacks and settings for the reference tracking implementation //Variable which stores all the callbacks and settings for the reference tracking implementation
static TRACKING_CONFIG_STRUCT tracking_reference = { static TRACKING_CONFIG_STRUCT tracking_reference = {
tracking_reference_start, tracking_reference_start,
tracking_reference_stop, tracking_reference_stop,
tracking_reference_update tracking_reference_update
}; };
//Pointer to the currently active tracking implementation. See also tracking_set_mode //Pointer to the currently active tracking implementation. See also tracking_set_mode
static TRACKING_CONFIG_STRUCT* tracking_current; 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 //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) void tracking_set_mode(enum Tracking_Implementation impl) {
{ //Depending on the enum value let tracking_current point to a different setting/callback structure
//Depending on the enum value let tracking_current point to a different setting/callback structure switch(impl) {
switch (impl) { case OUR_TRACKING:
case OUR_TRACKING: tracking_current = &tracking_our;
tracking_current = &tracking_our; break;
break; case REFERENCE_TRACKING:
tracking_current = &tracking_reference;
case REFERENCE_TRACKING: break;
tracking_current = &tracking_reference; default:
break; tracking_current=NULL;
break;
default: }
tracking_current = NULL;
break;
}
} }
//Callback for when the screen is entered/loaded //Callback for when the screen is entered/loaded
static void enter(void* screen) static void enter(void* screen) {
{ tft_clear(WHITE);
tft_clear(WHITE);
//"Back" button
//"Back" button b_back.base.x1=5; //Start X of Button
b_back.base.x1 = 5; //Start X of Button b_back.base.y1=5; //Start Y 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.x2 = AUTO; //Auto Calculate X2 with String Width b_back.base.y2=AUTO; //Auto Calculate Y2 with String Height
b_back.base.y2 = AUTO; //Auto Calculate Y2 with String Height b_back.txtcolor=WHITE; //Set foreground color
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.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.font = 0; //Select Font b_back.text="Back"; //Set Text (For formatted strings take sprintf)
b_back.text = "Back"; //Set Text (For formatted strings take sprintf) b_back.callback=b_back_cb; //Call b_back_cb as Callback
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)
gui_button_add(&b_back); //Register Button (and run the callback from now on)
//"Select color" button //"Select color" button
b_select.base.x1 = 150; b_select.base.x1=150;
b_select.base.y1 = 5; b_select.base.y1=5;
b_select.base.x2 = AUTO; b_select.base.x2=AUTO;
b_select.base.y2 = AUTO; b_select.base.y2=AUTO;
b_select.txtcolor = WHITE; b_select.txtcolor=WHITE;
b_select.bgcolor = HEX(0xAE1010); b_select.bgcolor=HEX(0xAE1010);
b_select.font = 0; b_select.font=0;
b_select.text = "Select Color"; b_select.text="Select Color";
b_select.callback = b_select_cb; b_select.callback=b_select_cb;
gui_button_add(&b_select); gui_button_add(&b_select);
//"Frame visible" checkbox //"Frame visible" checkbox
c_frame_toggle.base.x1 = 50; c_frame_toggle.base.x1 = 50;
c_frame_toggle.base.x2 = 50 + 16; c_frame_toggle.base.x2 = 50+16;
c_frame_toggle.base.y1 = 5; c_frame_toggle.base.y1 = 5;
c_frame_toggle.base.y2 = 5 + 16; c_frame_toggle.base.y2 = 5+16;
c_frame_toggle.checked = frame_visible; c_frame_toggle.checked = frame_visible;
c_frame_toggle.fgcolor = CHECKBOX_WIN_FG_COLOR; c_frame_toggle.fgcolor = CHECKBOX_WIN_FG_COLOR;
c_frame_toggle.callback = c_frame_toggle_cb; c_frame_toggle.callback = c_frame_toggle_cb;
gui_checkbox_add(&c_frame_toggle); gui_checkbox_add(&c_frame_toggle);
tft_print_line(73, 8, BLACK, TRANSPARENT, 0, "Show Video"); tft_print_line(73,8,BLACK,TRANSPARENT,0,"Show Video");
//Area to select a "color region" //Area to select a "color region"
a_area.hookedActions = PEN_DOWN | PEN_UP; a_area.hookedActions = PEN_DOWN | PEN_UP;
a_area.x1 = FRAME_START_X; a_area.x1 = FRAME_START_X;
a_area.y1 = FRAME_START_Y; a_area.y1 = FRAME_START_Y;
a_area.x2 = FRAME_END_X; a_area.x2 = FRAME_END_X;
a_area.y2 = FRAME_END_Y; a_area.y2 = FRAME_END_Y;
a_area.callback = touchCB; a_area.callback = touchCB;
//Do not register it here, we do that later //Do not register it here, we do that later
if (tracking_current == NULL) { if(tracking_current==NULL) {
state = error; state = error;
} else { } else {
state = detecting; //Start with the detecting state state = detecting; //Start with the detecting state
} }
} }
//Callback for when the screen is left/unloaded //Callback for when the screen is left/unloaded
static void leave(void* screen) static void leave(void* screen) {
{ //Remove buttons and checkbox
//Remove buttons and checkbox gui_button_remove(&b_back);
gui_button_remove(&b_back); gui_button_remove(&b_select);
gui_button_remove(&b_select); gui_checkbox_remove(&c_frame_toggle);
gui_checkbox_remove(&c_frame_toggle);
if (state == selecting) { //the user left the screen in the "selecting" phase if(state==selecting) { //the user left the screen in the "selecting" phase
touch_unregister_area(&a_area); //remove the touch area touch_unregister_area(&a_area); //remove the touch area
} }
if (state == tracking) { //the user left the screen in the "tracking" phase if(state==tracking) { //the user left the screen in the "tracking" phase
tracking_current->stop(tracking_current); //stop tracking tracking_current->stop(tracking_current); //stop tracking
pixy_led_set_RGB(0, 0, 0); pixy_led_set_RGB(0,0,0);
} }
} }
//Callback for when the screen should be updated //Callback for when the screen should be updated
//This is the main loop of the screen. This method will be called repeatedly //This is the main loop of the screen. This method will be called repeatedly
static void update(void* screen) static void update(void* screen) {
{ switch(state) {
switch (state) { case detecting: //Detecting State: Where we try to connect to the pixy
case detecting: //Detecting State: Where we try to connect to the pixy if(pixy_init()==0) { //Pixy connection ok
if (pixy_init() == 0) { //Pixy connection ok state = init; //Go to next state
state = init; //Go to next state }
} break;
break; case init: //Init State: Where we start the tracking
tracking_current->start(tracking_current);
state=tracking;
break;
case init: //Init State: Where we start the tracking case tracking: //Tracking state: Where we render the frame and the tracked objects
tracking_current->start(tracking_current); pixy_service(); //Receive events (e.g. block-data) from pixy
state = tracking;
break;
case tracking: //Tracking state: Where we render the frame and the tracked objects if(pixy_blocks_are_new()) { //There are new blocks available
pixy_service(); //Receive events (e.g. block-data) from pixy 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 (pixy_blocks_are_new()) { //There are new blocks available #define BLOCK_BUFFER_SIZE 5 //The maximum amount of blocks that we want to receive
if (frame_visible) { //If the user want's us to draw the video data struct Block blocks[BLOCK_BUFFER_SIZE]; //Storage to receive blocks from pixy
pixy_render_full_frame(FRAME_START_X, FRAME_START_Y); int blocks_received= pixy_get_blocks(BLOCK_BUFFER_SIZE,blocks); //Try to receive up to BLOCK_BUFFER_SIZE Blocks from pixy
} 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));
}
#define BLOCK_BUFFER_SIZE 5 //The maximum amount of blocks that we want to receive if(blocks_received>=0) { //block receiving ok
struct Block blocks[BLOCK_BUFFER_SIZE]; //Storage to receive blocks from pixy tracking_current->update(tracking_current,blocks,blocks_received); //apply tracking
int blocks_received = pixy_get_blocks(BLOCK_BUFFER_SIZE, blocks); //Try to receive up to BLOCK_BUFFER_SIZE Blocks from pixy
if (blocks_received >= 0) { //block receiving ok //Draw blocks
tracking_current->update(tracking_current, blocks, blocks_received); //apply tracking 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
}
}
}
break;
//Draw blocks case preselecting: //Pre-Selecting State: Where we set up the color region selection
for (int i = 0; i < blocks_received; i++) { //for each received block {
struct Block* block = &(blocks[i]); tracking_current->stop(tracking_current); //Stop tracking
//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
}
}
}
break; pixy_render_full_frame(FRAME_START_X,FRAME_START_Y); //Render one frame
case preselecting: { //Pre-Selecting State: Where we set up the color region selection touch_register_area(&a_area); //Register touch area and receive events from now on
tracking_current->stop(tracking_current); //Stop tracking point1_valid=false; //we start with an invalid point1
pixy_render_full_frame(FRAME_START_X, FRAME_START_Y); //Render one frame b_select.text="Abort"; //Change the button text to "Abort"
gui_button_redraw(&b_select); //redraw button
touch_register_area(&a_area); //Register touch area and receive events from now on state = selecting; //The user can now select a region
point1_valid = false; //we start with an invalid point1 }
break;
b_select.text = "Abort"; //Change the button text to "Abort" case selected: //Selected State: Where we send the users selection to pixy
gui_button_redraw(&b_select); //redraw button {
//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;
}
state = selecting; //The user can now select a region if(point1.y > point2.y){
} tmp = point1.y;
break; 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
case selected: { //Selected State: Where we send the users selection to pixy case abortselecting: //Abort-Selecting State: Where we deinitialize the stuff we used for region selection
//Ensure that (x1,y1) represent the top-left point and (x2,y2) the bottom-right. {
unsigned int tmp; touch_unregister_area(&a_area); //Remove the touch area. We'll no longer receive touch events
if (point1.x > point2.x) { b_select.text="Select Color"; //Change the button text back to "Select Color"
tmp = point1.x; gui_button_redraw(&b_select); //redraw button
point1.x = point2.x;
point2.x = tmp;
}
if (point1.y > point2.y) { tracking_current->start(tracking_current); //Start tracking again
tmp = point1.y; state=tracking;
point1.y = point2.y; }
point2.y = tmp; break;
}
//Send pixy the selected region case selecting: //Selecting State: Where we wait on the user to select a color region
pixy_cc_set_region(1, point1.x, point1.y, point2.x - point1.x, point2.y - point1.y); pixy_service(); //receive pixy events
} //wait on user to select the image area
break;
//no break here: We want the following code to be executed as well 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
case abortselecting: { //Abort-Selecting State: Where we deinitialize the stuff we used for region selection break;
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 //Declare screen callbacks
static SCREEN_STRUCT screen = { static SCREEN_STRUCT screen = {
enter, enter,
leave, leave,
update update
}; };
SCREEN_STRUCT* get_screen_tracking() SCREEN_STRUCT* get_screen_tracking() {
{ return &screen;
return &screen;
} }

View File

@@ -1,16 +1,3 @@
/**************************************************************************************************************************************
* 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" #include "screen.h"
/** /**
@@ -29,8 +16,8 @@
* Enum which contains the available tracking implementations * Enum which contains the available tracking implementations
*/ */
enum Tracking_Implementation { enum Tracking_Implementation {
OUR_TRACKING, //!< Our own tracking PID implementation OUR_TRACKING, //!< Our own tracking PID implementation
REFERENCE_TRACKING//!< Pixy's internal tracking implementation REFERENCE_TRACKING//!< Pixy's internal tracking implementation
}; };
/** /**

View File

@@ -1,56 +1,38 @@
/**************************************************************************************************************************************
* 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 "filesystem.h"
#include "ll_filesystem.h" #include "ll_filesystem.h"
bool filesystem_init() bool filesystem_init() {
{ return ll_filesystem_init();
return ll_filesystem_init();
} }
DIRECTORY_STRUCT* filesystem_dir_open(const char* path) DIRECTORY_STRUCT* filesystem_dir_open(const char* path) {
{ return ll_filesystem_dir_open(path);
return ll_filesystem_dir_open(path);
} }
void filesystem_dir_close(DIRECTORY_STRUCT* dir) void filesystem_dir_close(DIRECTORY_STRUCT* dir) {
{ ll_filesystem_dir_close(dir);
ll_filesystem_dir_close(dir);
} }
FILE_HANDLE* filesystem_file_open(const char* filename) FILE_HANDLE* filesystem_file_open(const char* filename) {
{ return ll_filesystem_file_open(filename);
return ll_filesystem_file_open(filename);
} }
void filesystem_file_close(FILE_HANDLE* handle) void filesystem_file_close(FILE_HANDLE* handle) {
{ ll_filesystem_file_close(handle);
ll_filesystem_file_close(handle);
} }
FILE_STATUS filesystem_file_seek(FILE_HANDLE* handle, uint32_t offset) FILE_STATUS filesystem_file_seek(FILE_HANDLE* handle, uint32_t offset) {
{ return ll_filesystem_file_seek(handle,offset);
return ll_filesystem_file_seek(handle, offset);
} }
FILE_STATUS filesystem_file_read(FILE_HANDLE* handle, uint8_t* buf, uint32_t size) FILE_STATUS filesystem_file_read(FILE_HANDLE* handle, uint8_t* buf, uint32_t size) {
{ return ll_filesystem_file_read(handle,buf,size);
return ll_filesystem_file_read(handle, buf, size);
} }
FILE_STATUS filesystem_file_write(FILE_HANDLE* handle, uint8_t* buf, uint32_t size) FILE_STATUS filesystem_file_write(FILE_HANDLE* handle, uint8_t* buf, uint32_t size) {
{ return ll_filesystem_file_write(handle,buf,size);
return ll_filesystem_file_write(handle, buf, size);
} }

View File

@@ -1,18 +1,3 @@
/**************************************************************************************************************************************
* 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 #ifndef FILESYSTEM_H
#define FILESYSTEM_H #define FILESYSTEM_H
@@ -30,57 +15,57 @@
* See http://en.wikipedia.org/wiki/Design_of_the_FAT_file_system#attributes for detailed description * See http://en.wikipedia.org/wiki/Design_of_the_FAT_file_system#attributes for detailed description
*/ */
typedef enum { typedef enum {
F_RDO = 0x01, //!< File is readonly. You cannot write to it F_RDO=0x01,//!< File is readonly. You cannot write to it
F_HID = 0x02, //!< File is hidden F_HID=0x02,//!< File is hidden
F_SYS = 0x04, //!< File is a system file F_SYS=0x04,//!< File is a system file
F_DIR = 0x10, //!< It's a directory and not a file F_DIR=0x10,//!< It's a directory and not a file
F_ARC = 0x20 //!< File has the archive flag set (probably unused) F_ARC=0x20 //!< File has the archive flag set (probably unused)
} FILE_ATTRIBUTES; } FILE_ATTRIBUTES;
/** /**
* Structure which represents last modified date of a file / directory * Structure which represents last modified date of a file / directory
*/ */
typedef struct { typedef struct {
unsigned year : 7; //!< year from 1980 (0..127) unsigned year : 7; //!< year from 1980 (0..127)
unsigned month: 4; //!< month (1..12) unsigned month: 4; //!< month (1..12)
unsigned day: 5; //!< day (1..31) unsigned day: 5; //!< day (1..31)
} FILE_DATE_STRUCT; } FILE_DATE_STRUCT;
/** /**
* Structure which represents last modified time of a file / directory * Structure which represents last modified time of a file / directory
*/ */
typedef struct { typedef struct {
unsigned hour : 5; //!< hour (0..23) unsigned hour : 5; //!< hour (0..23)
unsigned min: 6; //!< minute (0..59 unsigned min: 6; //!< minute (0..59
unsigned sec: 5; //!< second/2 (0..29) unsigned sec: 5; //!< second/2 (0..29)
} FILE_TIME_STRUCT; } FILE_TIME_STRUCT;
/** /**
* Structure which represents a file/directory entry. \sa DIRECTORY_STRUCT * Structure which represents a file/directory entry. \sa DIRECTORY_STRUCT
*/ */
typedef struct { typedef struct {
uint32_t fsize; //!< File size in bytes. 0 for directories uint32_t fsize; //!< File size in bytes. 0 for directories
FILE_DATE_STRUCT fdate; //!< Last modified date FILE_DATE_STRUCT fdate; //!< Last modified date
FILE_TIME_STRUCT ftime; //!< Last modified time FILE_TIME_STRUCT ftime; //!< Last modified time
uint8_t fattrib; //!< File/Directory Attributes uint8_t fattrib; //!< File/Directory Attributes
char* fname; //!< File/Directory name char* fname; //!< File/Directory name
} FILE_STRUCT; } FILE_STRUCT;
/** /**
* Structure which represents an open directory with all it's entries. \sa filesystem_dir_open * Structure which represents an open directory with all it's entries. \sa filesystem_dir_open
*/ */
typedef struct { typedef struct {
const char* path; //!< Directory path (absolute) const char* path; //!< Directory path (absolute)
uint16_t num_files; //!< Number of files/directories in this directory uint16_t num_files; //!< Number of files/directories in this directory
FILE_STRUCT* files; //!< An array with \ref num_files FILE_STRUCT entries FILE_STRUCT* files; //!< An array with \ref num_files FILE_STRUCT entries
} DIRECTORY_STRUCT; } DIRECTORY_STRUCT;
/** /**
* Structure which represents an open file. \sa filesystem_file_open * Structure which represents an open file. \sa filesystem_file_open
*/ */
typedef struct { typedef struct {
const char* fname; //!< The absolute file name const char* fname; //!< The absolute file name
uint32_t fpos; //!< The current byte-position in the file. \sa filesystem_file_seek uint32_t fpos; //!< The current byte-position in the file. \sa filesystem_file_seek
uint32_t fsize; //!< The total file size in bytes uint32_t fsize; //!< The total file size in bytes
} FILE_HANDLE; } FILE_HANDLE;
@@ -88,11 +73,11 @@ typedef struct {
* Enum to represent the success or error-code of the filesystem_file_* functions * Enum to represent the success or error-code of the filesystem_file_* functions
*/ */
typedef enum { typedef enum {
F_OK, //!< Everything ok 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_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_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_INVALIDPARAM,//!< You passed invalid parameters to the function
F_DISKERROR //!< A lowlevel disk-error occoured. This is a fatal error. F_DISKERROR //!< A lowlevel disk-error occoured. This is a fatal error.
} FILE_STATUS; } FILE_STATUS;
/** /**
@@ -159,3 +144,4 @@ FILE_STATUS filesystem_file_write(FILE_HANDLE* handle, uint8_t* buf, uint32_t si
/*@}*/ /*@}*/
#endif /* FILESYSTEM_H */ #endif /* FILESYSTEM_H */

View File

@@ -1,188 +1,154 @@
/************************************************************************************************************************************** #include "tft.h"
* Project: discoverpixy #include "touch.h"
* Website: https://github.com/t-moe/discoverpixy #include "button.h"
* Authors: Aaron Schmocker, Timo Lang #include <string.h>
* Institution: BFH Bern University of Applied Sciences
* File: common/gui/button.c /* 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.
* Version History: * Once the user puts the pen down in this area we'll redraw the button with different shadows (feedback)
* Date Autor Email SHA Changes * and we'll now wait on PEN_UP or PEN_LEAVE events.
* 2015-04-27 timolang@gmail.com 7c9eabc Added button support. * If the user takes the pen away while in the area (PEN_UP), we call the provided user callback
* 2015-05-17 timolang@gmail.com 2d46336 Improved comments in implementation of button, checkbox, numupdown, tft, touch and screen modules/submodules. * Otherwise (PEN_LEAVE) we only restore the initial shadows
* */
**************************************************************************************************************************************/
/* Possible improvements:
#include "tft.h" * Move the button by 1 pixel while he is pressed, to create a "full 3d" experience
#include "touch.h" * Add events for the case when the button is pressed for a long time, without release
#include "button.h" */
#include <string.h>
//Method to calculate the shadow colors used to create the "3d" effect
/* The Idea is as follows: void calculate_shadows(uint16_t bgcolor, uint16_t* light_shadow, uint16_t* dark_shadow) {
* When the user add's a button we create a touch area for that region and wait for PEN_DOWN events. #define BRIGHTNESS_VAL 3 //How much the Brightness is in/decreased for button shadows (3 -> Add/Subtract 1/3 off Full Value)
* 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. 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)
* If the user takes the pen away while in the area (PEN_UP), we call the provided user callback uint8_t r,g,b;
* Otherwise (PEN_LEAVE) we only restore the initial shadows
*/ //separate the channels of the 16-bit rgb565 color
r=(bgcolor&0xF800)>>11;
/* Possible improvements: g=(bgcolor&0x07E0)>>5;
* Move the button by 1 pixel while he is pressed, to create a "full 3d" experience b=(bgcolor&0x001F)>>0;
* Add events for the case when the button is pressed for a long time, without release
*/ //For the light shadow color:
if((r + 0x1F/BRIGHTNESS_VAL) > 0x1F) //Adding one third would exceed the maximum of the red channel
//Method to calculate the shadow colors used to create the "3d" effect c_light=0xF800; //Use full red
void calculate_shadows(uint16_t bgcolor, uint16_t* light_shadow, uint16_t* dark_shadow) 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
#define BRIGHTNESS_VAL 3 //How much the Brightness is in/decreased for button shadows (3 -> Add/Subtract 1/3 off Full Value) if((g + 0x3F/BRIGHTNESS_VAL) > 0x3F) //same for the green channel
c_light|=0x07E0;
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) else
uint8_t r, g, b; c_light|=(g+0x3F/BRIGHTNESS_VAL)<<5;
if((b + 0x1F/BRIGHTNESS_VAL) > 0x1F) //and the blue channel
//separate the channels of the 16-bit rgb565 color c_light|=0x0018;
r = (bgcolor & 0xF800) >> 11; else
g = (bgcolor & 0x07E0) >> 5; c_light|=(b+0x1F/BRIGHTNESS_VAL)<<0;
b = (bgcolor & 0x001F) >> 0;
//For the dark shadow color
//For the light shadow color: if(r > (0x1F/BRIGHTNESS_VAL)) //Subtracting one third would NOT exceed the minimum of the red channel
if ((r + 0x1F / BRIGHTNESS_VAL) > 0x1F) { //Adding one third would exceed the maximum of the red channel c_dark=(r-0x1F/BRIGHTNESS_VAL)<<11; //Use same red as in the background, but subtract one third
c_light = 0xF800; //Use full red else //Subtracting one third would give us a number below zero
} else { //adding one third to the red channel is fine c_dark=0x0000; //use no red channel
c_light = (r + 0x1F / BRIGHTNESS_VAL) << 11; //Use same red as in the background, but add one third 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
if ((g + 0x3F / BRIGHTNESS_VAL) > 0x3F) { //same for the green channel c_dark|=(b-0x1F/BRIGHTNESS_VAL)<<0;
c_light |= 0x07E0;
} else { //Assign the calculated shadows to out parameters
c_light |= (g + 0x3F / BRIGHTNESS_VAL) << 5; if(light_shadow!=NULL) *light_shadow = c_light;
} if(dark_shadow!=NULL) *dark_shadow = c_dark;
if ((b + 0x1F / BRIGHTNESS_VAL) > 0x1F) { //and the blue channel }
c_light |= 0x0018;
} else { //Callback which is called when the user touches the touch-area we created for the button
c_light |= (b + 0x1F / BRIGHTNESS_VAL) << 0; void buttons_cb(void* touchArea, TOUCH_ACTION triggeredAction)
} {
TOUCH_AREA_STRUCT * area = (TOUCH_AREA_STRUCT*)touchArea;
//For the dark shadow color BUTTON_STRUCT* button = (BUTTON_STRUCT*)touchArea;
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 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)
} else { //Subtracting one third would give us a number below zero calculate_shadows(button->bgcolor,&c_light,&c_dark);
c_dark = 0x0000; //use no red channel
} switch(triggeredAction)
{
if (g > (0x3F / BRIGHTNESS_VAL)) { //Same for the green channel case PEN_DOWN: //If the user touches the area for the "first time"
c_dark |= (g - 0x3F / BRIGHTNESS_VAL) << 5; area->hookedActions=PEN_UP|PEN_LEAVE; //for the future we only want PEN_UP and PEN_LEAVE events
}
//Draw shadows
if (b > (0x1F / BRIGHTNESS_VAL)) { //and the blue channel tft_draw_line(button->base.x1+1,button->base.y1,button->base.x2-1,button->base.y1,c_dark); //North
c_dark |= (b - 0x1F / BRIGHTNESS_VAL) << 0; 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
//Assign the calculated shadows to out parameters break;
if (light_shadow != NULL) { case PEN_UP: //If the user took the pen away, while in the area (=button pressed!)
*light_shadow = c_light; case PEN_LEAVE: //or the user "slided out" of the area
} area->hookedActions=PEN_DOWN; //for the future we only want PEN_DOWN events
if (dark_shadow != NULL) { //Draw inverse shadows
*dark_shadow = c_dark; 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
//Callback which is called when the user touches the touch-area we created for the button if(triggeredAction==PEN_UP && button->callback!=NULL) //If the button got "pressed" instead of left, and the user provided a callback
void buttons_cb(void* touchArea, TOUCH_ACTION triggeredAction) button->callback(button); //execute the user callback
{ break;
TOUCH_AREA_STRUCT* area = (TOUCH_AREA_STRUCT*)touchArea; default:break;
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);
bool gui_button_add(BUTTON_STRUCT* button)
switch (triggeredAction) { {
case PEN_DOWN: //If the user touches the area for the "first time" if(touch_have_empty(1)) //Check if the touch module can handle one additional area
area->hookedActions = PEN_UP | PEN_LEAVE; //for the future we only want PEN_UP and PEN_LEAVE events {
//Calculate width and height of the button text
//Draw shadows unsigned int strwidth=tft_font_width(button->font)*strlen(button->text);
tft_draw_line(button->base.x1 + 1, button->base.y1, button->base.x2 - 1, button->base.y1, c_dark); //North unsigned char strheight=tft_font_height(button->font);
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 button->base.hookedActions=PEN_DOWN; //At first we are interested in PEN_DOWN events
tft_draw_line(button->base.x2, button->base.y1 + 1, button->base.x2, button->base.y2 - 1, c_light); //East button->base.callback = buttons_cb; //Use our own callback for the touch area events
break;
if(button->base.x2==AUTO) { //The user wants us to calculate the button width automatically
case PEN_UP: //If the user took the pen away, while in the area (=button pressed!) //Use string width + half of a character width as button width
case PEN_LEAVE: //or the user "slided out" of the area button->base.x2= button->base.x1 -1 + strwidth+(tft_font_width(button->font)/2);
area->hookedActions = PEN_DOWN; //for the future we only want PEN_DOWN events } 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
//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 if(button->base.y2==AUTO) { //The user wants us to calculate the button height automatically
tft_draw_line(button->base.x1 + 1, button->base.y2, button->base.x2 - 1, button->base.y2, c_dark); //South //Use one and a half character heights as button height
tft_draw_line(button->base.x2, button->base.y1 + 1, button->base.x2, button->base.y2 - 1, c_dark); //East 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
if (triggeredAction == PEN_UP && button->callback != NULL) { //If the button got "pressed" instead of left, and the user provided a callback return false;
button->callback(button); //execute the user callback }
} 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
break; }
default: return false; //no more touch areas left
break; }
}
} void gui_button_redraw(BUTTON_STRUCT* button)
{
//Calculate text dimensions and shadow colors
bool gui_button_add(BUTTON_STRUCT* button) unsigned int strwidth=tft_font_width(button->font)*strlen(button->text);
{ unsigned char strheight=tft_font_height(button->font);
if (touch_have_empty(1)) { //Check if the touch module can handle one additional area uint16_t c_light,c_dark;
//Calculate width and height of the button text calculate_shadows(button->bgcolor,&c_light,&c_dark);
unsigned int strwidth = tft_font_width(button->font) * strlen(button->text);
unsigned char strheight = tft_font_height(button->font); //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);
button->base.hookedActions = PEN_DOWN; //At first we are interested in PEN_DOWN events tft_draw_line(button->base.x1+1,button->base.y1,button->base.x2-1,button->base.y1,c_light); //North
button->base.callback = buttons_cb; //Use our own callback for the touch area events 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
if (button->base.x2 == AUTO) { //The user wants us to calculate the button width automatically tft_draw_line(button->base.x2,button->base.y1+1,button->base.x2,button->base.y2-1,c_dark); //East
//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); //Draw the text
} else if ((button->base.x2 - button->base.x1 + 1) < (strwidth + 2)) { //the provided width is too small to fit the entire 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);
return false; //report error
} }
if (button->base.y2 == AUTO) { //The user wants us to calculate the button height automatically void gui_button_remove(BUTTON_STRUCT* button)
//Use one and a half character heights as button height {
button->base.y2 = button->base.y1 - 1 + strheight + (strheight / 2); //We only need to unregister the touch area, as we have not allocated anything else
} else if ((button->base.y2 - button->base.y1 + 1) < (strheight + 2)) { //the provided height is too small to fit the text touch_unregister_area((TOUCH_AREA_STRUCT*)button);
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);
}

View File

@@ -1,89 +1,71 @@
/************************************************************************************************************************************** #ifndef BUTTON_H
* Project: discoverpixy #define BUTTON_H
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang #include "touch.h"
* Institution: BFH Bern University of Applied Sciences
* File: common/gui/button.h /**
* * @defgroup gui Gui
* Version History: * The Gui Module
* 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. * @defgroup button Button
* 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. * The Button Gui-Element is a clickable, rectangular box with a label inside.
* 2015-05-17 timolang@gmail.com 2d46336 Improved comments in implementation of button, checkbox, numupdown, tft, touch and screen modules/submodules. * When it is pressed and released you will be notified via the provided callback.
* */
**************************************************************************************************************************************/
/*@}*/
#ifndef BUTTON_H
#define BUTTON_H /**
* @addtogroup button
#include "touch.h" */
/*@{*/
/**
* @defgroup gui Gui
* The Gui Module /**
*/ * 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
/** */
* @defgroup button Button typedef void (*BUTTON_CALLBACK)(void *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.
*/ /**
* 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.
* @addtogroup button 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;
* 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 #define AUTO 0 //!< Use this value instead of x2, y2 in the BUTTON_STRUCT to autocalculate the button width/height
*/
typedef void (*BUTTON_CALLBACK)(void* button); /**
* 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
* Structure to configure the Button */
*/ bool gui_button_add(BUTTON_STRUCT* 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 * Removes the button. You will no longer receive events for this button. This function will not overdraw the region where the button was located.
BUTTON_CALLBACK callback; //!< Callback which is executed when the button is pressed * @param button A Pointer to the BUTTON_STRUCT
uint16_t txtcolor; //!< The 16-bit text color */
uint8_t font; //!< The number of the font to use void gui_button_remove(BUTTON_STRUCT* button);
const char* text; //!< The label of the button
} BUTTON_STRUCT; /**
* 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
#define AUTO 0 //!< Use this value instead of x2, y2 in the BUTTON_STRUCT to autocalculate the button width/height */
void gui_button_redraw(BUTTON_STRUCT* button);
/**
* 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
*/ #endif /* BUTTON_H */
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 */

View File

@@ -1,144 +1,121 @@
/************************************************************************************************************************************** #include "tft.h"
* Project: discoverpixy #include "touch.h"
* Website: https://github.com/t-moe/discoverpixy #include "checkbox.h"
* Authors: Aaron Schmocker, Timo Lang #include <stdio.h>
* Institution: BFH Bern University of Applied Sciences
* File: common/gui/checkbox.c /* 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.
* Version History: * Once the user puts the pen down in this area we'll redraw the checkbox with different shadows (feedback)
* Date Autor Email SHA Changes * and we'll now wait on PEN_UP or PEN_LEAVE events.
* 2015-04-27 timolang@gmail.com b300ac5 Added Checkbox support * If the user takes the pen away while in the area (PEN_UP), we toggle the checkbox and we call the provided user callback
* 2015-05-17 timolang@gmail.com 2d46336 Improved comments in implementation of button, checkbox, numupdown, tft, touch and screen modules/submodules. * Otherwise (PEN_LEAVE) we only restore the initial shadows
* */
**************************************************************************************************************************************/
#include "tft.h" #define ACTIVE_COLOR RGB(251,208,123) //shadow color (inside of border)
#include "touch.h" #define BORDER_COLOR RGB(29,82,129) //1px border color
#include "checkbox.h" #define BACKGROUND_COLOR WHITE //Background color
#include <stdio.h>
//Callback which is called when the user touches the touch-area we created for the checkbox
/* The idea is as follows: void checkboxes_cb(void* touchArea, TOUCH_ACTION triggeredAction)
* 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) TOUCH_AREA_STRUCT * area = (TOUCH_AREA_STRUCT*)touchArea;
* and we'll now wait on PEN_UP or PEN_LEAVE events. CHECKBOX_STRUCT* checkbox = (CHECKBOX_STRUCT*)touchArea;
* If the user takes the pen away while in the area (PEN_UP), we toggle the checkbox and we call the provided user callback switch(triggeredAction)
* Otherwise (PEN_LEAVE) we only restore the initial shadows {
*/ 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
#define ACTIVE_COLOR RGB(251,208,123) //shadow color (inside of border) //Draw active shadows
#define BORDER_COLOR RGB(29,82,129) //1px border color tft_draw_rectangle(checkbox->base.x1+1,checkbox->base.y1+1,checkbox->base.x2-1,checkbox->base.y2-1,ACTIVE_COLOR);
#define BACKGROUND_COLOR WHITE //Background color tft_draw_rectangle(checkbox->base.x1+2,checkbox->base.y1+2,checkbox->base.x2-2,checkbox->base.y2-2,ACTIVE_COLOR);
break;
//Callback which is called when the user touches the touch-area we created for the checkbox case PEN_UP: //If the user took the pen away, while in the area (=toggle checkbox!)
void checkboxes_cb(void* touchArea, TOUCH_ACTION triggeredAction) checkbox->checked=!checkbox->checked; //Toggle checkbox state
{ gui_checkbox_update(checkbox); //redraw/overdraw tickmark
TOUCH_AREA_STRUCT* area = (TOUCH_AREA_STRUCT*)touchArea; if(checkbox->callback!=NULL) { //The user provided a callback
CHECKBOX_STRUCT* checkbox = (CHECKBOX_STRUCT*)touchArea; checkbox->callback(checkbox,checkbox->checked); //Call the provided callback with the new checked state
}
switch (triggeredAction) { // no break statement here!
case PEN_DOWN: //If the user touches the area for the "first time" case PEN_LEAVE: //if the user "slided out" of the area
area->hookedActions = PEN_UP | PEN_LEAVE; //for the future we only want PEN_UP and PEN_LEAVE events area->hookedActions=PEN_DOWN; //for the future we only want PEN_DOWN events
//Draw active shadows //Draw inactive 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+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, ACTIVE_COLOR); tft_draw_rectangle(checkbox->base.x1+2,checkbox->base.y1+2,checkbox->base.x2-2,checkbox->base.y2-2,BACKGROUND_COLOR);
break; break;
default: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
bool gui_checkbox_add(CHECKBOX_STRUCT* checkbox)
if (checkbox->callback != NULL) { //The user provided a callback {
checkbox->callback(checkbox, checkbox->checked); //Call the provided callback with the new checked state if(touch_have_empty(1)) //Check if the touch module can handle one additional area
} {
unsigned char size=0;
// no break statement here! checkbox->base.hookedActions=PEN_DOWN; //At first we are interested in PEN_DOWN events
case PEN_LEAVE: //if the user "slided out" of the area checkbox->base.callback = checkboxes_cb; //Use our own callback for the touch area events
area->hookedActions = PEN_DOWN; //for the future we only want PEN_DOWN events
//Check the size of the checkbox
//Draw inactive shadows if(checkbox->base.x2>checkbox->base.x1)
tft_draw_rectangle(checkbox->base.x1 + 1, checkbox->base.y1 + 1, checkbox->base.x2 - 1, checkbox->base.y2 - 1, BACKGROUND_COLOR); size = checkbox->base.x2 - checkbox->base.x1; //use width a as size
tft_draw_rectangle(checkbox->base.x1 + 2, checkbox->base.y1 + 2, checkbox->base.x2 - 2, checkbox->base.y2 - 2, BACKGROUND_COLOR); if(checkbox->base.y2>checkbox->base.y1)
break; {
if((checkbox->base.y2 - checkbox->base.y1)>size) //height is larger than size
default: size = checkbox->base.y2 - checkbox->base.y1; //use height as size
break; }
} if(size==0) { //no size found (maybe swap x2 and x1 or y2 and y1 ?)
} return false; //signal error
}
bool gui_checkbox_add(CHECKBOX_STRUCT* checkbox) if((size&0x01)) //the size is an odd number
{ size++; //make size an even number
if (touch_have_empty(1)) { //Check if the touch module can handle one additional area
unsigned char size = 0; //Correct x2,y2 so that the checkbox is quadratic
checkbox->base.hookedActions = PEN_DOWN; //At first we are interested in PEN_DOWN events checkbox->base.x2 = checkbox->base.x1 + size;
checkbox->base.callback = checkboxes_cb; //Use our own callback for the touch area events checkbox->base.y2 = checkbox->base.y1 + size;
//Check the size of the checkbox gui_checkbox_redraw(checkbox);//Call redraw method, which will take care of the drawing of the entire checkbox
if (checkbox->base.x2 > checkbox->base.x1) {
size = checkbox->base.x2 - checkbox->base.x1; //use width a as size return touch_register_area(&checkbox->base); //Register the touch area and receive events for this checkbox, from now on
} }
if (checkbox->base.y2 > checkbox->base.y1) { return false; //no more touch areas left
if ((checkbox->base.y2 - checkbox->base.y1) > size) { //height is larger than size }
size = checkbox->base.y2 - checkbox->base.y1; //use height as size
} void gui_checkbox_redraw(CHECKBOX_STRUCT* checkbox)
} {
//Draw background and border
if (size == 0) { //no size found (maybe swap x2 and x1 or y2 and y1 ?) tft_fill_rectangle(checkbox->base.x1+1,checkbox->base.y1+1,checkbox->base.x2-1,checkbox->base.y2-1,BACKGROUND_COLOR);
return false; //signal error tft_draw_rectangle(checkbox->base.x1,checkbox->base.y1,checkbox->base.x2,checkbox->base.y2,BORDER_COLOR);
}
if(checkbox->checked) { //checkbox is currently checked
if ((size & 0x01)) { //the size is an odd number gui_checkbox_update(checkbox); //Call update method which will draw the tickmark
size++; //make size an even number }
} }
//Correct x2,y2 so that the checkbox is quadratic void gui_checkbox_remove(CHECKBOX_STRUCT* checkbox)
checkbox->base.x2 = checkbox->base.x1 + size; {
checkbox->base.y2 = checkbox->base.y1 + size; //We only need to unregister the touch area, as we have not allocated anything else
touch_unregister_area((TOUCH_AREA_STRUCT*)checkbox);
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 void gui_checkbox_update(CHECKBOX_STRUCT* checkbox)
} {
unsigned int c = (checkbox->checked)? checkbox->fgcolor:BACKGROUND_COLOR; //color to use for the tickmark
return false; //no more touch areas left
} //helper points inside the checkbox
unsigned int xcent = checkbox->base.x1+(checkbox->base.x2-checkbox->base.x1)*6/14;
void gui_checkbox_redraw(CHECKBOX_STRUCT* checkbox) unsigned int yleft = checkbox->base.y2 - (xcent- checkbox->base.x1) - 1 ;
{ unsigned int yright = checkbox->base.y2 - (checkbox->base.x2 - xcent) - 1 ;
//Draw background and border unsigned int ybot = checkbox->base.y2 - 4;
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); //Draw tickmark as a 3pixel wide line
tft_draw_line(checkbox->base.x1+3,yleft-1,xcent,ybot -1,c);
if (checkbox->checked) { //checkbox is currently checked tft_draw_line(checkbox->base.x1+3,yleft,xcent,ybot ,c);
gui_checkbox_update(checkbox); //Call update method which will draw the tickmark 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);
void gui_checkbox_remove(CHECKBOX_STRUCT* checkbox) 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);
//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);
}

View File

@@ -1,86 +1,70 @@
/************************************************************************************************************************************** #ifndef CHECKBOX_H
* Project: discoverpixy #define CHECKBOX_H
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang #include "touch.h"
* Institution: BFH Bern University of Applied Sciences
* File: common/gui/checkbox.h /**
* * @addtogroup gui
* 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. * @defgroup checkbox Checkbox
* 2015-05-17 timolang@gmail.com 2d46336 Improved comments in implementation of button, checkbox, numupdown, tft, touch and screen modules/submodules. * 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.
**************************************************************************************************************************************/ */
/*@}*/
#ifndef CHECKBOX_H
#define CHECKBOX_H /**
* @addtogroup checkbox
#include "touch.h" */
/*@{*/
/**
* @addtogroup gui /**
*/ * 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.
* @defgroup checkbox Checkbox */
* The Checkbox Gui-Element is a clickable, rectangular box with an optional tickmark inside of it. typedef void (*CHECKBOX_CALLBACK)(void *checkbox, bool checked);
* When the checkbox is pressed and released it's tick state changes and you will be notified via the provided callback.
*/ /**
/*@}*/ * Structure to configure the Checkbox
*/
/** typedef struct {
* @addtogroup checkbox 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;
* 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 * Adds a checkbox. Your Callback will be called from now on, if the checkbox changes state
* @param checked A boolean which indicates whether the checkbox is now checked or not. * @param checkbox A Pointer to the preinitialized CHECKBOX_STRUCT
*/ * @return true on success
typedef void (*CHECKBOX_CALLBACK)(void* checkbox, bool checked); */
bool gui_checkbox_add(CHECKBOX_STRUCT* checkbox);
/**
* Structure to configure the 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.
typedef struct { * @param checkbox A Pointer to the CHECKBOX_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 void gui_checkbox_remove(CHECKBOX_STRUCT* checkbox);
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; * Updates the checkbox. Call this function when you change the state of the checkbox through code.
* @param checkbox A Pointer to the CHECKBOX_STRUCT
/** */
* Adds a checkbox. Your Callback will be called from now on, if the checkbox changes state void gui_checkbox_update(CHECKBOX_STRUCT* checkbox);
* @param checkbox A Pointer to the preinitialized CHECKBOX_STRUCT
* @return true on success /**
*/ * 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.
bool gui_checkbox_add(CHECKBOX_STRUCT* checkbox); * @param checkbox A Pointer to the CHECKBOX_STRUCT
*/
/** void gui_checkbox_redraw(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 #define CHECKBOX_WIN_FG_COLOR RGB(32,161,34)
*/
void gui_checkbox_remove(CHECKBOX_STRUCT* checkbox); /*@}*/
/** #endif /* CHECKBOX_H */
* 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 */

View File

@@ -1,169 +1,143 @@
/************************************************************************************************************************************** #include "tft.h"
* Project: discoverpixy #include "touch.h"
* Website: https://github.com/t-moe/discoverpixy #include "button.h"
* Authors: Aaron Schmocker, Timo Lang #include "numupdown.h"
* Institution: BFH Bern University of Applied Sciences #include <stdio.h> //for sprintf
* File: common/gui/numupdown.c #include <stddef.h> //for offsetof macro
* #include <stdlib.h> //for abs
* Version History:
* Date Autor Email SHA Changes /* The idea is as follows:
* 2015-04-30 timolang@gmail.com 76ea9d8 Added num up down support. * When the user add's a numupdown we create two buttons, one with a plus and one with a minus sign in it
* 2015-04-30 timolang@gmail.com b491b78 Made numupdown horizontal * When the user presses one of the buttons we check and increase the value and execute the provided user callback
* 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.
*
**************************************************************************************************************************************/ #define BASE_COLOR RGB(90,90,90) //Background color for the whole element
#include "tft.h" //Callback which is called when the user presses the "plus" button
#include "touch.h" void button_up_cb(void* button)
#include "button.h" {
#include "numupdown.h" //Get the pointer to the numupdown: subtract the offset of the buttonUp member in the struct from the button pointer
#include <stdio.h> //for sprintf NUMUPDOWN_STRUCT* element = button-offsetof(NUMUPDOWN_STRUCT,buttonUp);
#include <stddef.h> //for offsetof macro
#include <stdlib.h> //for abs if(element->value<element->max) { //old value lies below the maximum
element->value++; //let's increase the value
/* The idea is as follows: gui_numupdown_update(element); //and redraw everything
* When the user add's a numupdown we create two buttons, one with a plus and one with a minus sign in it if(element->callback!=NULL) { //the user provided a callback
* When the user presses one of the buttons we check and increase the value and execute the provided user callback element->callback(element,element->value); //Call the user callback with the new value
*/ }
}
}
#define BASE_COLOR RGB(90,90,90) //Background color for the whole element
//Callback which is called when the user presses the "minus" button
//Callback which is called when the user presses the "plus" button void button_down_cb(void* button)
void button_up_cb(void* button) {
{ //Get the pointer to the numupdown: subtract the offset of the buttonDown member in the struct from the button pointer
//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,buttonDown);
NUMUPDOWN_STRUCT* element = button - offsetof(NUMUPDOWN_STRUCT, buttonUp);
if(element->value>element->min) { //old value lies above the minimum
if (element->value < element->max) { //old value lies below the maximum element->value--; //let's decrease the value
element->value++; //let's increase the value gui_numupdown_update(element); //and redraw everything
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
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) {
//Callback which is called when the user presses the "minus" button uint8_t width = 1 + (val<0); //1 if positive, 2 if negative (to let space for sign)
void button_down_cb(void* button) val=abs(val); //Make the number positive
{ while(val>=10) { //while we have two or more digits
//Get the pointer to the numupdown: subtract the offset of the buttonDown member in the struct from the button pointer val/=10; //remove one digit
NUMUPDOWN_STRUCT* element = button - offsetof(NUMUPDOWN_STRUCT, buttonDown); width++; //add one character
}
if (element->value > element->min) { //old value lies above the minimum return width;
element->value--; //let's decrease the value }
gui_numupdown_update(element); //and redraw everything
if (element->callback != NULL) { //the user provided a callback bool gui_numupdown_add(NUMUPDOWN_STRUCT* numupdown)
element->callback(element, element->value); //Call the user callback with the new value {
} 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
//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)
{ if(numupdown->value < numupdown->min) { //value is smaller than min?
uint8_t width = 1 + (val < 0); //1 if positive, 2 if negative (to let space for sign) numupdown->value = numupdown->min; //normalize value
val = abs(val); //Make the number positive } else if(numupdown->value > numupdown->max) { //value is bigger than max?
numupdown->value = numupdown->max; //normalize value
while (val >= 10) { //while we have two or more digits }
val /= 10; //remove one digit
width++; //add one character 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
return width; 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;
bool gui_numupdown_add(NUMUPDOWN_STRUCT* numupdown) numupdown->buttonDown.base.y1=numupdown->y;
{ numupdown->buttonDown.base.x2=AUTO;
if (touch_have_empty(2)) { //Check if the touch module can handle two additional areas numupdown->buttonDown.base.y2=numupdown->y+tft_font_height(0)*2;
if (numupdown->min > numupdown->max) { //min is bigger than max? numupdown->buttonDown.text="-";
return false; //invalid parameter numupdown->buttonDown.font=0;
} numupdown->buttonDown.bgcolor=BASE_COLOR;
numupdown->buttonDown.txtcolor=WHITE;
if (numupdown->value < numupdown->min) { //value is smaller than min? numupdown->buttonDown.callback = button_down_cb;
numupdown->value = numupdown->min; //normalize value gui_button_add(&numupdown->buttonDown);
} else if (numupdown->value > numupdown->max) { //value is bigger than max?
numupdown->value = numupdown->max; //normalize value //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;
uint8_t tw1 = calc_text_width(numupdown->max); //Calculate character width to render maximum value numupdown->buttonUp.base.x2=AUTO;
uint8_t tw2 = calc_text_width(numupdown->min); //Calculate character width to render minimum value numupdown->buttonUp.base.y2=numupdown->y +tft_font_height(0)*2;
numupdown->buttonUp.text="+";
if (tw2 > tw1) { numupdown->buttonUp.font=0;
tw1 = tw2; //ensure tw1 contains the larger number of the two numupdown->buttonUp.bgcolor=BASE_COLOR;
} numupdown->buttonUp.txtcolor=WHITE;
numupdown->buttonUp.callback = button_up_cb;
uint8_t width = tft_font_width(0) * (tw1 + 1); //Calculate width of the number area gui_button_add(&numupdown->buttonUp);
//Add "minus" button to the left side of the number area //Draw background and label of the number area
numupdown->buttonDown.base.x1 = numupdown->x; tft_fill_rectangle(numupdown->buttonDown.base.x2+2,numupdown->y,numupdown->buttonDown.base.x2+width,numupdown->buttonUp.base.y2,BASE_COLOR);
numupdown->buttonDown.base.y1 = numupdown->y; 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);
numupdown->buttonDown.base.x2 = AUTO;
numupdown->buttonDown.base.y2 = numupdown->y + tft_font_height(0) * 2; return true;
numupdown->buttonDown.text = "-"; }
numupdown->buttonDown.font = 0;
numupdown->buttonDown.bgcolor = BASE_COLOR; return false; //not enough touch areas left
numupdown->buttonDown.txtcolor = WHITE; }
numupdown->buttonDown.callback = button_down_cb;
gui_button_add(&numupdown->buttonDown); void gui_numupdown_remove(NUMUPDOWN_STRUCT* numupdown)
{
//Add "plus" button to the right side of the number area //remove the two buttons, we have no other allocated resources
numupdown->buttonUp.base.x1 = numupdown->buttonDown.base.x2 + width + 2; gui_button_remove(&numupdown->buttonUp);
numupdown->buttonUp.base.y1 = numupdown->y; gui_button_remove(&numupdown->buttonDown);
numupdown->buttonUp.base.x2 = AUTO; }
numupdown->buttonUp.base.y2 = numupdown->y + tft_font_height(0) * 2;
numupdown->buttonUp.text = "+";
numupdown->buttonUp.font = 0; void gui_numupdown_redraw(NUMUPDOWN_STRUCT* numupdown)
numupdown->buttonUp.bgcolor = BASE_COLOR; {
numupdown->buttonUp.txtcolor = WHITE; //redraw the two buttons
numupdown->buttonUp.callback = button_up_cb; gui_button_redraw(&numupdown->buttonUp);
gui_button_add(&numupdown->buttonUp); gui_button_redraw(&numupdown->buttonDown);
//Draw background and label of the number area //call update method which will take care of the number-area rendering
tft_fill_rectangle(numupdown->buttonDown.base.x2 + 2, numupdown->y, numupdown->buttonDown.base.x2 + width, numupdown->buttonUp.base.y2, BASE_COLOR); gui_numupdown_update(numupdown);
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; void gui_numupdown_update(NUMUPDOWN_STRUCT* numupdown)
} {
//Calculate the number area width again (see above)
return false; //not enough touch areas left uint8_t tw1 = calc_text_width(numupdown->max);
} uint8_t tw2 = calc_text_width(numupdown->min);
if(tw2 > tw1) tw1 = tw2;
void gui_numupdown_remove(NUMUPDOWN_STRUCT* numupdown) uint8_t width= tft_font_width(0)*(tw1+1);
{
//remove the two buttons, we have no other allocated resources //Draw background and label of the number area
gui_button_remove(&numupdown->buttonUp); tft_fill_rectangle(numupdown->buttonDown.base.x2+2,numupdown->y,numupdown->buttonDown.base.x2+width,numupdown->buttonUp.base.y2,BASE_COLOR);
gui_button_remove(&numupdown->buttonDown); 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);
} }
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);
}

View File

@@ -1,88 +1,73 @@
/************************************************************************************************************************************** #ifndef NUMUPDOWN_H
* Project: discoverpixy #define NUMUPDOWN_H
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang #include "button.h"
* Institution: BFH Bern University of Applied Sciences
* File: common/gui/numupdown.h /**
* * @addtogroup gui
* 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. * @defgroup numupdown NummericUpDown
* * The NummericUpDown Gui Element
**************************************************************************************************************************************/ */
/*@}*/
#ifndef NUMUPDOWN_H
#define NUMUPDOWN_H /**
* @addtogroup numupdown
#include "button.h" */
/*@{*/
/**
* @addtogroup gui /**
*/ * 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
* @defgroup numupdown NummericUpDown */
* The NummericUpDown Gui Element typedef void (*NUMUPDOWN_CALLBACK)(void *numupdown, int16_t value);
*/
/*@}*/ /**
* Structure to configure the NummericUpDown
/** */
* @addtogroup numupdown 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
* Prototype for Event Listeners (called when the NummericUpDown value has changed) int16_t min; //!< The minimum possible value (inclusive)
* \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. int16_t max; //!< The maximum possible value (inclusive)
* @param numupdown The pointer to the NUMUPDOWN_STRUCT where to corresponding NummericUpDown has changed it's value NUMUPDOWN_CALLBACK callback; //!< Callback which is executed when the value changes
* @param value The new value of the NummericUpDown
*/ BUTTON_STRUCT buttonUp; //!< For internal use, don't change, don't initialize
typedef void (*NUMUPDOWN_CALLBACK)(void* numupdown, int16_t value); BUTTON_STRUCT buttonDown; //!< For internal use, don't change, don't initialize
} NUMUPDOWN_STRUCT;
/**
* Structure to configure the NummericUpDown /**
*/ * Adds a NummericUpDown. Your Callback will be called from now on, if the numupdown's value changes
typedef struct { * @param numupdown A Pointer to the preinitialized NUMUPDOWN_STRUCT
uint16_t x; //!< The x-Coordinate of the Top-Left Starting Point. * @return true on success
uint16_t y; //!< The y-Coordinate of the Top-Left Starting Point. */
uint16_t fgcolor; //!< The 16-bit color of the value-text bool gui_numupdown_add(NUMUPDOWN_STRUCT* numupdown);
int16_t value; //!< The current/default value
int16_t min; //!< The minimum possible value (inclusive) /**
int16_t max; //!< The maximum possible value (inclusive) * Removes the NummericUpDown. You will no longer receive events for this numupdown. This function will not overdraw the region where the numupdown was located.
NUMUPDOWN_CALLBACK callback; //!< Callback which is executed when the value changes * @param numupdown A Pointer to the NUMUPDOWN_STRUCT
*/
BUTTON_STRUCT buttonUp; //!< For internal use, don't change, don't initialize void gui_numupdown_remove(NUMUPDOWN_STRUCT* numupdown);
BUTTON_STRUCT buttonDown; //!< For internal use, don't change, don't initialize
} NUMUPDOWN_STRUCT; /**
* 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
* 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 void gui_numupdown_update(NUMUPDOWN_STRUCT* numupdown);
* @return true on success
*/ /**
bool gui_numupdown_add(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
/** */
* Removes the NummericUpDown. You will no longer receive events for this numupdown. This function will not overdraw the region where the numupdown was located. void gui_numupdown_redraw(NUMUPDOWN_STRUCT* numupdown);
* @param numupdown A Pointer to the NUMUPDOWN_STRUCT
*/ /*@}*/
void gui_numupdown_remove(NUMUPDOWN_STRUCT* numupdown);
#endif /* NUMUPDOWN_H */
/**
* 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 */

View File

@@ -1,21 +1,3 @@
/**************************************************************************************************************************************
* 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" #include "screen.h"
/* The idea is as follows: /* The idea is as follows:
@@ -24,87 +6,66 @@
* This makes it safe to change the screen from an touch interrupt (e.g. button callback) * This makes it safe to change the screen from an touch interrupt (e.g. button callback)
*/ */
/* Possible Improvements:
* Ensure that you can not navigate to a screen which is already in the history (because it will corrupt the list)
*/
static SCREEN_STRUCT* screen_list = NULL; //Head of the linked list which stores the screen history. static SCREEN_STRUCT* screen_list = NULL; //Head of the linked list which stores the screen history.
static SCREEN_STRUCT* screen_current = NULL; //Pointer to the current screen (= tail of the list) 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 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() SCREEN_STRUCT* gui_screen_get_current() {
{ return screen_current;
return screen_current;
} }
void gui_screen_update() void gui_screen_update() {
{ if(screen_goto!=NULL) { //we received the task to switch the screen
if (screen_goto != NULL) { //we received the task to switch the screen SCREEN_STRUCT* go = (SCREEN_STRUCT*) screen_goto; //Backup volatile variable
SCREEN_STRUCT* go = (SCREEN_STRUCT*) screen_goto; //Backup volatile variable screen_goto=NULL; //reset the "goto instruction", since we're processing it now
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
}
if (go->next != NULL) { //The screen is not the last in the list, so we're going back if(screen_current!=NULL) { //A screen has been set
if (go->next != screen_current) { //this condition should always be false screen_current->on_update(screen_current); //Update current screen
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) bool gui_screen_navigate(SCREEN_STRUCT* screen) {
{ if(screen==NULL || screen==screen_current || screen==screen_goto) { //invalid argument passed
if (screen == NULL || screen == screen_current || screen == screen_goto) { //invalid argument passed return false;
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
screen->next = NULL; //this will become the new tail of the list, so the next pointer must be NULL return true;
screen_goto = screen; //"send message" to main loop, to switch the screen
return true;
} }
bool gui_screen_back() bool gui_screen_back() {
{ if(screen_list==NULL) { //the list head is emtpy, nothing to go back to
if (screen_list == NULL) { //the list head is emtpy, nothing to go back to return false;
return false; }
} SCREEN_STRUCT* current = screen_list;
SCREEN_STRUCT* last = NULL;
SCREEN_STRUCT* current = screen_list; //Find second last element in list
SCREEN_STRUCT* last = NULL; while(current->next != NULL) {
last = current;
//Find second last element in list current = current->next;
while (current->next != NULL) { }
last = current; if(last==NULL) return false; //There's only a single screen, there's no going back here
current = current->next; 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;
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;
} }

View File

@@ -1,21 +1,3 @@
/**************************************************************************************************************************************
* 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 #ifndef SCREEN_H
#define SCREEN_H #define SCREEN_H
@@ -49,12 +31,12 @@ typedef void (*SCREEN_CALLBACK)(void* screen);
/** /**
* Structure to configure the Screen * Structure to configure the Screen
*/ */
typedef struct SCREEN_S { 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_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_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 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; } SCREEN_STRUCT;
@@ -62,7 +44,6 @@ typedef struct SCREEN_S {
/** /**
* Navigate to the given screen as soon as the app enters the main loop again (and gui_screen_update() is called) * Navigate to the given screen as soon as the app enters the main loop again (and gui_screen_update() is called)
* It's safe to call this method from an interrupt * It's safe to call this method from an interrupt
* @note Do not pass a screen which is already in your history of screens!
* @param screen A Pointer to the preinitialized SCREEN_STRUCT * @param screen A Pointer to the preinitialized SCREEN_STRUCT
* @return true on success * @return true on success
*/ */

View File

@@ -1,17 +1,3 @@
/**************************************************************************************************************************************
* 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" #include "filesystem.h"
/** /**

View File

@@ -1,21 +1,3 @@
/**************************************************************************************************************************************
* 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 <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>

View File

@@ -1,24 +1,3 @@
/**************************************************************************************************************************************
* 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 <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
@@ -45,10 +24,10 @@ bool ll_tft_init();
// draw functions // draw functions
void ll_tft_clear(uint16_t color); 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_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_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_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_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); void ll_tft_draw_circle(uint16_t x, uint16_t y, uint16_t r, uint16_t color);
@@ -58,3 +37,5 @@ 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); void ll_tft_draw_char(uint16_t x, uint16_t y, uint16_t color, uint16_t bgcolor, uint8_t font, char c);
/*@}*/ /*@}*/

View File

@@ -1,17 +1,3 @@
/**************************************************************************************************************************************
* 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 <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>

View File

@@ -1,39 +1,19 @@
/**************************************************************************************************************************************
* 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 "system.h"
#include "ll_system.h" #include "ll_system.h"
bool system_init() bool system_init() {
{ return ll_system_init();
return ll_system_init();
} }
void system_delay(uint32_t msec) void system_delay(uint32_t msec) {
{ ll_system_delay(msec);
ll_system_delay(msec);
} }
void system_process() void system_process() {
{ ll_system_process();
ll_system_process();
} }
void system_toggle_led() void system_toggle_led() {
{ ll_system_toggle_led();
ll_system_toggle_led();
} }

View File

@@ -1,21 +1,3 @@
/**************************************************************************************************************************************
* 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 #ifndef SYSTEM_H
#define SYSTEM_H #define SYSTEM_H

View File

@@ -1,24 +1,3 @@
/**************************************************************************************************************************************
* 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 "tft.h"
#include "ll_tft.h" #include "ll_tft.h"
#include <string.h> #include <string.h>
@@ -36,148 +15,129 @@
* For formatted printing implement putchar, instead of writing into a buffer and drawing that buffer afterwards * For formatted printing implement putchar, instead of writing into a buffer and drawing that buffer afterwards
*/ */
bool tft_init() bool tft_init() {
{ return ll_tft_init();
return ll_tft_init();
} }
void tft_clear(uint16_t color) void tft_clear(uint16_t color) {
{ ll_tft_clear(color);
ll_tft_clear(color);
} }
void tft_draw_line(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t 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);
ll_tft_draw_line(x1, y1, x2, y2, color);
} }
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) {
{ ll_tft_draw_pixel(x,y,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) 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
//could be implemented with 4 lines instead of introducing a ll func ll_tft_draw_rectangle(x1,y1,x2,y2,color);
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) 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);
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) 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);
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); ll_tft_draw_circle(x, y, r, color);
} }
uint8_t tft_num_fonts() uint8_t tft_num_fonts() {
{ return ll_tft_num_fonts();
return ll_tft_num_fonts();
} }
uint8_t tft_font_height(uint8_t fontnum) uint8_t tft_font_height(uint8_t fontnum) {
{ return ll_tft_font_height(fontnum);
return ll_tft_font_height(fontnum);
} }
uint8_t tft_font_width(uint8_t fontnum) uint8_t tft_font_width(uint8_t fontnum) {
{ return ll_tft_font_width(fontnum);
return ll_tft_font_width(fontnum);
} }
//Print line can be done with multiple calls to draw_char //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) 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
if (font >= ll_tft_num_fonts()) { for(int i=0; i<strlen(text); i++) { //for each char in the line
return; //invalid font index 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
}
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 //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, ...) 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
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. //Since we have variable arguments, we need to forward them. We have to use vsprintf instead of sprintf for that.
va_list args; va_list args;
va_start(args, format); //start the varg-list va_start (args, format); //start the varg-list
vsprintf(buffer, format, args); //let vsprintf render the formatted string 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 tft_print_line(x,y,color,bgcolor,font,buffer); //print the string as normal text
va_end(args); //end the varg-list va_end(args); //end the varg-list
} }
bool tft_draw_bitmap_file_unscaled(uint16_t x, uint16_t y, const char* filename) 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.
//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.
//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
//Source Copied and adapted from: http://stackoverflow.com/a/17040962/2606757
FILE_HANDLE* file = filesystem_file_open(filename); //try to open the file FILE_HANDLE* file = filesystem_file_open(filename); //try to open the file
if(file==NULL) { //file opening failed
return false;
}
if (file == NULL) { //file opening failed unsigned char info[54];
return false; 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
}
unsigned char info[54]; // 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
if (filesystem_file_read(file, info, 54) != F_OK) { //try to read the 54 byte header filesystem_file_seek(file,*(uint32_t*)&info[10]); //seek to the place where img data begins
filesystem_file_close(file);
return false; //reading the header failed
}
// extract image height and width from header uint32_t row_padded = (width*depth + 3) & (~3); //row size must be aligned to 4 bytes
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
filesystem_file_seek(file, *(uint32_t*)&info[10]); //seek to the place where img data begins unsigned char data [row_padded]; //allocate space for one row (incl. padding)
uint32_t row_padded = (width * depth + 3) & (~3); //row size must be aligned to 4 bytes 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];
}
unsigned char data [row_padded]; //allocate space for one row (incl. padding) 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));
}
}
}
for (int i = 0; i < height; i++) { //for each row filesystem_file_close(file);
filesystem_file_read(file, data, row_padded); //read row into buffer
for (int j = 0; j < width * depth; j += depth) { //for each pixel return true;
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;
} }

View File

@@ -1,28 +1,3 @@
/**************************************************************************************************************************************
* 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 #ifndef TFT_H
#define TFT_H #define TFT_H
@@ -94,7 +69,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 y The y-Coordinate of the pixel
* @param color The 16-bit color to draw the pixel with * @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. * Draws the outline of a rectangle onto the display.
@@ -105,7 +80,7 @@ void tft_draw_pixel(uint16_t x, uint16_t y, uint16_t color);
* @param y2 The y-Coordinate of the end-point * @param y2 The y-Coordinate of the end-point
* @param color The 16-bit color to draw the pixel with * @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 * Draws a filled rectangle onto the display. The start,end points are inclusive
@@ -115,7 +90,7 @@ void tft_draw_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint
* @param y2 The y-Coordinate of the end-point * @param y2 The y-Coordinate of the end-point
* @param color The 16-bit color to draw the pixel with * @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. * Draws a bitmap onto the display without scaling/cropping.

View File

@@ -1,17 +1,3 @@
/**************************************************************************************************************************************
* 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 "screen_calibrate.h"
#include "tft.h" #include "tft.h"
#include "touch.h" #include "touch.h"
@@ -20,102 +6,90 @@
extern volatile bool calibration; //from touch.c extern volatile bool calibration; //from touch.c
static void enter(void* screen) static void enter(void* screen) {
{ tft_clear(BLACK);
tft_clear(BLACK);
} }
static void leave(void* screen) static void leave(void* screen) {
{
} }
static void update(void* screen) static void update(void* screen) {
{ int x1,y1,x2,y2,dx,dy;
int x1, y1, x2, y2, dx, dy;
tft_print_line(50, 50, WHITE, BLACK, 1, "Calibration:"); tft_print_line(50,50,WHITE,BLACK,1,"Calibration:");
tft_print_line(50, 120, WHITE, BLACK, 0, "Hit the markers exactly!"); tft_print_line(50,120,WHITE,BLACK,0,"Hit the markers exactly!");
//-----------------First Point-------------------- //-----------------First Point--------------------
tft_draw_line(CCENTER, CBEGIN, CCENTER, CEND, WHITE); //Draw Cross tft_draw_line(CCENTER,CBEGIN,CCENTER,CEND,WHITE); //Draw Cross
tft_draw_line(CBEGIN, CCENTER, CEND, CCENTER, WHITE); //Draw Cross tft_draw_line(CBEGIN,CCENTER,CEND,CCENTER,WHITE); //Draw Cross
calibration = 1; //TouchX + TouchY Values will not be converted to Pixels 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
while (calibration); //Wait on PenUp //-----------------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);
POINT_STRUCT p1 = touch_get_last_point(); //-----------------Third Point--------------------
x1 = p1.x; tft_draw_line(CCENTER,DHEIGHT-CBEGIN,CCENTER,DHEIGHT-CEND,WHITE);
y1 = p1.y; tft_draw_line(CBEGIN,DHEIGHT-CCENTER,CEND,DHEIGHT-CCENTER,WHITE);
tft_fill_rectangle(CBEGIN, CBEGIN, CEND, CEND, BLACK); //Clear Cross 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);
//-----------------Second Point------------------- //------------------4. Point---------------------
tft_draw_line(DWIDTH - CCENTER, DHEIGHT - CBEGIN, DWIDTH - CCENTER, DHEIGHT - CEND, WHITE); tft_draw_line(DWIDTH-CCENTER,CBEGIN,DWIDTH-CCENTER,CEND,WHITE);
tft_draw_line(DWIDTH - CBEGIN, DHEIGHT - CCENTER, DWIDTH - CEND, DHEIGHT - CCENTER, WHITE); tft_draw_line(DWIDTH-CBEGIN,CCENTER,DWIDTH-CEND,CCENTER,WHITE);
calibration = 1; 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);
while (calibration); touch_set_calibration_values(x1,dx,y1,dy);
tft_print_line(50,120,WHITE,BLACK,0,"Calibration Done. Press anywhere");
POINT_STRUCT p2 = touch_get_last_point(); calibration=1;
x2 = p2.x; while(calibration);
y2 = p2.y; gui_screen_back();
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 = { static SCREEN_STRUCT screen = {
enter, enter,
leave, leave,
update update
}; };
SCREEN_STRUCT* get_screen_calibrate() SCREEN_STRUCT* get_screen_calibrate() {
{ return &screen;
return &screen;
} }

View File

@@ -1,17 +1,3 @@
/**************************************************************************************************************************************
* 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" #include "screen.h"
/** /**

View File

@@ -1,21 +1,3 @@
/**************************************************************************************************************************************
* 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 "touch.h"
#include "ll_touch.h" #include "ll_touch.h"
#include "screen_calibrate.h" #include "screen_calibrate.h"
@@ -30,185 +12,191 @@
/* Possible improvements: /* Possible improvements:
* Exchange pointer-list "areas" with a linked list. This would ensure that we can always accept new regions * Exchange pointer-list "areas" with a linked list. This would ensure that we can always accept new regions
* Implement calibration stuff, and calculate the real coordinates out of the data provided in touch_add_raw_event()
*/ */
#define NUM_AREAS 50 //Number of Touch Areas we can manage #define NUM_AREAS 50 //Number of Touch Areas we can manage
TOUCH_AREA_STRUCT* areas[NUM_AREAS] = {NULL}; //list with pointers to all managed touch area's 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 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 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). //Calibration parameters (dummy values).
int cal_xs = 10; int cal_xs=10;
int cal_dx = 100; int cal_dx=100;
int cal_ys = 10; int cal_ys=10;
int cal_dy = 100; int cal_dy=100;
void touch_set_calibration_values(int xs, int dx, int ys, int dy) void touch_set_calibration_values(int xs, int dx, int ys, int dy) {
{ cal_xs = xs;
cal_xs = xs; cal_ys = ys;
cal_ys = ys; cal_dx = dx;
cal_dx = dx; cal_dy = dy;
cal_dy = dy;
} }
bool touch_init() bool touch_init() {
{ return ll_touch_init();
return ll_touch_init();
} }
void touch_set_value_convert_mode(bool uc) void touch_set_value_convert_mode(bool uc) {
{ use_calibration=uc;
use_calibration = uc;
} }
bool touch_add_raw_event(uint16_t touchX, uint16_t touchY, TOUCH_STATE state) bool touch_add_raw_event(uint16_t touchX, uint16_t touchY, TOUCH_STATE state) {
{ //Update current and old position/state
//Update current and old position/state bool penDown = (state==TOUCH_DOWN);
bool penDown = (state == TOUCH_DOWN); bool oldPenDown = (oldState==TOUCH_DOWN);
bool oldPenDown = (oldState == TOUCH_DOWN); oldState=state;
oldState = state;
if (calibration) { //If in Calibration mode if(calibration) //If in Calibration mode
if (penDown) { {
pos.x = touchX; if(penDown)
pos.y = touchY; {
} else { pos.x=touchX;
if (oldPenDown) { //Run only if we got at least one pen down pos.y=touchY;
calibration = 0; //Calibration finish (Touch X and Y are the values from the last measure, where the pen was down) }
} 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;
}
return true; //If we reach this point we're not in calibration mode and we need to process the event and call the registred handlers..
}
//If we reach this point we're not in calibration mode and we need to process the event and call the registred handlers.. 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 (use_calibration) { //the underlying touch hardware uses calibration if(penDown) //pen is down now
//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; //tft_draw_pixel(touchX,touchY,WHITE);
pos.y = touchY = (((long)(DHEIGHT - 2 * CCENTER) * 2 * (long)((long)touchY - cal_ys) / cal_dy + 1) >> 1) + CCENTER; if(!oldPenDown) //pen wasn't down before (positive edge) => First Touch
} else { //no conversion needed for the underlying hardware {
pos.x = touchX; for(int z=0; z < NUM_AREAS; z++) // For every touch area
pos.y = touchY; {
} //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 )
if (penDown) { //pen is down now {
//tft_draw_pixel(touchX,touchY,WHITE); areas[z]->flags=1; //Save PenInside=1
if (!oldPenDown) { //pen wasn't down before (positive edge) => First Touch if(areas[z]->hookedActions & PEN_DOWN) //The user wants to receive pen down events
for (int z = 0; z < NUM_AREAS; z++) { // For every touch area areas[z]->callback(areas[z],PEN_DOWN); //Send event to user callback
//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 }
else //Pen was down before => Second, Third event in row
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 for(int z=0; z < NUM_AREAS; z++) // For every touch area
} {
} if(areas[z]!=NULL )
} {
} else { //Pen was down before => Second, Third event in row //Check if pos is inside area
for (int z = 0; z < NUM_AREAS; z++) { // For every touch area if(touchX >= areas[z]->x1 && touchX <= areas[z]->x2 && touchY >= areas[z]->y1 && touchY <= areas[z]->y2)
if (areas[z] != NULL) { {
//Check if pos is inside area if(areas[z]->flags==0) //Pen was not inside before (PenInside==0)
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)
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);
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)
} {
} 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)
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);
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
{
for (int z = 0; z < NUM_AREAS; z++) { // For every touch area //Check if pos is inside area
if (areas[z] != NULL && (areas[z]->hookedActions & PEN_MOVE)) { //User want's to receive pen move events if(touchX >= areas[z]->x1 && touchX <= areas[z]->x2 && touchY >= areas[z]->y1 && touchY <= areas[z]->y2)
//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);
areas[z]->callback(areas[z], PEN_MOVE); }
} }
} }
} }
} else { //pen is not down now 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 if(oldPenDown) //but it was down before (negative edge)
//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) { for(int z=0; z < NUM_AREAS; z++) // For every touch area
areas[z]->flags = 0; //The pen is no longer inside (PenInside = 0); {
//Check if pos is inside area
if (areas[z]->hookedActions & PEN_UP) { //user want's to receive pen up events if(areas[z]!=NULL && touchX >= areas[z]->x1 && touchX <= areas[z]->x2 && touchY >= areas[z]->y1 && touchY <= areas[z]->y2 )
areas[z]->callback(areas[z], PEN_UP); {
} 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; }
return true;
} }
bool touch_have_empty(unsigned char num) bool touch_have_empty(unsigned char num)
{ {
//go through pointer array and check for free spaces //go through pointer array and check for free spaces
for (unsigned char i = 0; i < NUM_AREAS; i++) { for(unsigned char i=0; i<NUM_AREAS; i++)
if (areas[i] == NULL) { {
num--; //a free space was found, we need one less if(areas[i]==NULL) num--; //a free space was found, we need one less
} if(num==0) return true; //enough free spaces found
}
if (num == 0) { return false; //not enough free spaces found
return true; //enough free spaces found
}
}
return false; //not enough free spaces found
} }
bool touch_register_area(TOUCH_AREA_STRUCT* area) bool touch_register_area(TOUCH_AREA_STRUCT* area)
{ {
//go through pointer array and check for free space //go through pointer array and check for free space
for (unsigned char i = 0; i < NUM_AREAS; i++) { 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) if(areas[i]==NULL) //free space found
areas[i] = area; //save pointer into list {
return true; 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 }
return false; //no free space found
} }
void touch_unregister_area(TOUCH_AREA_STRUCT* area) void touch_unregister_area(TOUCH_AREA_STRUCT* area)
{ {
if (area == NULL) { if(area==NULL) return;
return;
}
//go through pointer array and find the area to remove //go through pointer array and find the area to remove
for (unsigned char i = 0; i < NUM_AREAS; i++) { for(unsigned char i=0; i<NUM_AREAS; i++)
if (areas[i] == area) { //area found in pointer array at pos i {
areas[i] = NULL; //set pointer in list to NULL again if(areas[i]==area) //area found in pointer array at pos i
break; {
} areas[i]=NULL; //set pointer in list to NULL again
} break;
}
}
} }
POINT_STRUCT touch_get_last_point() POINT_STRUCT touch_get_last_point() {
{ return pos;
return pos;
} }

View File

@@ -1,25 +1,3 @@
/**************************************************************************************************************************************
* 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.h
*
* Version History:
* Date Autor Email SHA Changes
* 2015-04-03 timolang@gmail.com 51089aa Refactored Project Structure for use with emulator
* 2015-04-27 timolang@gmail.com 259d446 Added touch support to emulator. Implemented basic touch function.
* 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-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-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.
*
**************************************************************************************************************************************/
#ifndef TOUCH_H #ifndef TOUCH_H
#define TOUCH_H #define TOUCH_H
@@ -41,8 +19,8 @@
Enum to describe the current Touch State. \sa touch_add_raw_event Enum to describe the current Touch State. \sa touch_add_raw_event
*/ */
typedef enum { typedef enum {
TOUCH_UP, //!< The display is currently not touched TOUCH_UP, //!< The display is currently not touched
TOUCH_DOWN //!< The display is currently touched at some point TOUCH_DOWN //!< The display is currently touched at some point
} TOUCH_STATE ; } TOUCH_STATE ;
/** /**
@@ -50,12 +28,12 @@ typedef enum {
* You can OR-combine them. \sa touch_register_area * You can OR-combine them. \sa touch_register_area
*/ */
typedef enum { typedef enum {
NONE = 0x00, //!< Do not receive any events NONE=0x00, //!< Do not receive any events
PEN_DOWN = 0x01, //!< Receive an event when the pen goes down inside the region PEN_DOWN=0x01, //!< Receive an event when the pen goes down inside the region
PEN_UP = 0x02, //!< Receive an event when the pen goes up inside the region PEN_UP=0x02, //!< Receive an event when the pen goes up inside the region
PEN_ENTER = 0x04, //!< Receive an event when the pen enters the region (pen was down before) PEN_ENTER=0x04, //!< Receive an event when the pen enters the region (pen was down before)
PEN_LEAVE = 0x08, //!< Receive an event when the pen leaves the region (pen was inside region before) PEN_LEAVE=0x08, //!< Receive an event when the pen leaves the region (pen was inside region before)
PEN_MOVE = 0x10 //!< Receive an event when the pen moves inside the region (pen is down) PEN_MOVE=0x10 //!< Receive an event when the pen moves inside the region (pen is down)
} TOUCH_ACTION; } TOUCH_ACTION;
/** /**
@@ -70,13 +48,13 @@ typedef void (*TOUCH_CALLBACK)(void* touchArea, TOUCH_ACTION triggeredAction);
* Structure to configure a Touch Area * Structure to configure a Touch Area
*/ */
typedef struct { typedef struct {
TOUCH_ACTION hookedActions; //!< Actions to listen to TOUCH_ACTION hookedActions; //!< Actions to listen to
uint16_t x1; //!< Top Left X-Coordinate of Area uint16_t x1; //!< Top Left X-Coordinate of Area
uint16_t y1; //!< Top Left Y-Coordinate of Area uint16_t y1; //!< Top Left Y-Coordinate of Area
uint16_t x2; //!< Bottom Right X-Coordinate of Area uint16_t x2; //!< Bottom Right X-Coordinate of Area
uint16_t y2; //!< Bottom Right Y-Coordinate of Area uint16_t y2; //!< Bottom Right Y-Coordinate of Area
TOUCH_CALLBACK callback; //!< Callback which is executed when an event occurred in this Area. TOUCH_CALLBACK callback; //!< Callback which is executed when an event occurred in this Area.
uint8_t flags; //!< For internal use, don't change, don't initialize uint8_t flags; //!< For internal use, don't change, don't initialize
} TOUCH_AREA_STRUCT; } TOUCH_AREA_STRUCT;
@@ -84,8 +62,8 @@ typedef struct {
* Struct which represents a 2D point on the display * Struct which represents a 2D point on the display
*/ */
typedef struct { typedef struct {
uint16_t x; //!< The X-Coordinate of the point uint16_t x; //!< The X-Coordinate of the point
uint16_t y; //!< The Y-Coordinate of the point uint16_t y; //!< The Y-Coordinate of the point
} POINT_STRUCT; } POINT_STRUCT;
/** /**
@@ -104,7 +82,7 @@ bool touch_init();
* @param state Whether the pen is up or down * @param state Whether the pen is up or down
* @return True on success * @return True on success
*/ */
bool touch_add_raw_event(uint16_t x, uint16_t y, TOUCH_STATE state); bool touch_add_raw_event(uint16_t x, uint16_t y,TOUCH_STATE state);
/** /**
* Checks whether or not we have memory to manage and track additional \p num TOUCH_AREA_STRUCT%s * Checks whether or not we have memory to manage and track additional \p num TOUCH_AREA_STRUCT%s

View File

@@ -1,77 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
<storageModule moduleId="org.eclipse.cdt.core.settings">
<cconfiguration id="cdt.managedbuild.toolchain.gnu.cross.base.1368576398">
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.toolchain.gnu.cross.base.1368576398" moduleId="org.eclipse.cdt.core.settings" name="Default">
<externalSettings/>
<extensions>
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
</extensions>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<configuration artifactName="${ProjName}" buildProperties="" description="" id="cdt.managedbuild.toolchain.gnu.cross.base.1368576398" name="Default" parent="org.eclipse.cdt.build.core.emptycfg">
<folderInfo id="cdt.managedbuild.toolchain.gnu.cross.base.1368576398.357960121" name="/" resourcePath="">
<toolChain id="cdt.managedbuild.toolchain.gnu.cross.base.1769959713" name="Cross GCC" superClass="cdt.managedbuild.toolchain.gnu.cross.base">
<option id="cdt.managedbuild.option.gnu.cross.prefix.293575246" name="Prefix" superClass="cdt.managedbuild.option.gnu.cross.prefix"/>
<option id="cdt.managedbuild.option.gnu.cross.path.782624596" name="Path" superClass="cdt.managedbuild.option.gnu.cross.path"/>
<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="cdt.managedbuild.targetPlatform.gnu.cross.174263624" isAbstract="false" osList="all" superClass="cdt.managedbuild.targetPlatform.gnu.cross"/>
<builder id="cdt.managedbuild.builder.gnu.cross.1279514893" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" superClass="cdt.managedbuild.builder.gnu.cross"/>
<tool id="cdt.managedbuild.tool.gnu.cross.c.compiler.1136001261" name="Cross GCC Compiler" superClass="cdt.managedbuild.tool.gnu.cross.c.compiler">
<option id="gnu.c.compiler.option.include.paths.649992569" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/discoverpixy discovery/common}&quot;"/>
</option>
<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.1184220438" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
</tool>
<tool id="cdt.managedbuild.tool.gnu.cross.cpp.compiler.1669992748" name="Cross G++ Compiler" superClass="cdt.managedbuild.tool.gnu.cross.cpp.compiler">
<inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.564868280" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
</tool>
<tool id="cdt.managedbuild.tool.gnu.cross.c.linker.1771545603" name="Cross GCC Linker" superClass="cdt.managedbuild.tool.gnu.cross.c.linker"/>
<tool id="cdt.managedbuild.tool.gnu.cross.cpp.linker.490606250" name="Cross G++ Linker" superClass="cdt.managedbuild.tool.gnu.cross.cpp.linker">
<option id="gnu.cpp.link.option.paths.312574565" name="Library search path (-L)" superClass="gnu.cpp.link.option.paths" valueType="libPaths">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/discoverpixy discovery/libs}&quot;"/>
</option>
<inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.648346019" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
<additionalInput kind="additionalinput" paths="$(LIBS)"/>
</inputType>
</tool>
<tool id="cdt.managedbuild.tool.gnu.cross.archiver.1024233109" name="Cross GCC Archiver" superClass="cdt.managedbuild.tool.gnu.cross.archiver"/>
<tool id="cdt.managedbuild.tool.gnu.cross.assembler.1636598755" name="Cross GCC Assembler" superClass="cdt.managedbuild.tool.gnu.cross.assembler">
<inputType id="cdt.managedbuild.tool.gnu.assembler.input.1738279002" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
</tool>
</toolChain>
</folderInfo>
<sourceEntries>
<entry excluding="common" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="common"/>
</sourceEntries>
</configuration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
</cconfiguration>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<project id="example.null.999619443" name="example"/>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
<storageModule moduleId="refreshScope" versionNumber="2">
<configuration configurationName="Default">
<resource resourceType="PROJECT" workspacePath="/example"/>
</configuration>
</storageModule>
<storageModule moduleId="scannerConfiguration">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.cross.base.1368576398;cdt.managedbuild.toolchain.gnu.cross.base.1368576398.357960121;cdt.managedbuild.tool.gnu.cross.c.compiler.1136001261;cdt.managedbuild.tool.gnu.c.compiler.input.1184220438">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
</scannerConfigBuildInfo>
<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.cross.base.1368576398;cdt.managedbuild.toolchain.gnu.cross.base.1368576398.357960121;cdt.managedbuild.tool.gnu.cross.cpp.compiler.1669992748;cdt.managedbuild.tool.gnu.cpp.compiler.input.564868280">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
</scannerConfigBuildInfo>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
</cproject>

View File

@@ -1,34 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>discoverpixy discovery</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
<triggers>clean,full,incremental,</triggers>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
<triggers>full,incremental,</triggers>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.cdt.core.cnature</nature>
<nature>org.eclipse.cdt.core.ccnature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
</natures>
<linkedResources>
<link>
<name>common</name>
<type>2</type>
<location>PARENT-1-PROJECT_LOC/common</location>
</link>
</linkedResources>
</projectDescription>

View File

@@ -1,15 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project>
<configuration id="cdt.managedbuild.toolchain.gnu.cross.base.1368576398" name="Default">
<extension point="org.eclipse.cdt.core.LanguageSettingsProvider">
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
<provider copy-of="extension" id="org.eclipse.cdt.managedbuilder.core.GCCBuildCommandParser"/>
<provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="1373821771994211724" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/>
</provider>
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
</extension>
</configuration>
</project>

View File

@@ -1,256 +1,243 @@
/**************************************************************************************************************************************
* 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.c
*
* Version History:
* Date Autor Email SHA Changes
* 2015-05-11 aaron@duckpond.ch 21fddc3 Implemented new functions
*
**************************************************************************************************************************************/
#include<stdint.h> #include<stdint.h>
// SmallFont.c // SmallFont.c
// Font Size : 8x12 // Font Size : 8x12
// Memory usage : 1216 bytes // Memory usage : 1216 bytes
// # characters : 101 // # characters : 101
const char small_font[1216] = { const char small_font[1216] = {
0x08, 0x0C, 0x20, 0x65, 0x08,0x0C,0x20,0x65,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // <Space> 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // <Space>
0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x20, 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,0x28,0x50,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // "
0x00, 0x00, 0x28, 0x28, 0xFC, 0x28, 0x50, 0xFC, 0x50, 0x50, 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,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,0x48,0xA8,0xB0,0x50,0x28,0x34,0x54,0x48,0x00,0x00, // %
0x00, 0x00, 0x20, 0x50, 0x50, 0x78, 0xA8, 0xA8, 0x90, 0x6C, 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,0x40,0x40,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // '
0x00, 0x04, 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x08, 0x04, 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,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,0x00,0x20,0xA8,0x70,0x70,0xA8,0x20,0x00,0x00,0x00, // *
0x00, 0x00, 0x20, 0x20, 0x20, 0xF8, 0x20, 0x20, 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,0x00,0x00,0x00,0x00,0x40,0x40,0x80, // ,
0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // - 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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00, // .
0x00, 0x08, 0x10, 0x10, 0x10, 0x20, 0x20, 0x40, 0x40, 0x40, 0x80, 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,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,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,0x88,0x10,0x20,0x40,0x80,0xF8,0x00,0x00, // 2
0x00, 0x00, 0x70, 0x88, 0x08, 0x30, 0x08, 0x08, 0x88, 0x70, 0x00, 0x00, // 3 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,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,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,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,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,0x70,0x88,0x88,0x88,0x70,0x00,0x00, // 8
0x00, 0x00, 0x70, 0x88, 0x88, 0x88, 0x78, 0x08, 0x48, 0x70, 0x00, 0x00, // 9 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,0x20,0x00,0x00,0x00,0x00,0x20,0x00,0x00, // :
0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x20, 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,0x04,0x08,0x10,0x20,0x40,0x20,0x10,0x08,0x04,0x00,0x00, // <
0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0xF8, 0x00, 0x00, 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,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,0x88,0x10,0x20,0x20,0x00,0x20,0x00,0x00, // ?
0x00, 0x00, 0x70, 0x88, 0x98, 0xA8, 0xA8, 0xB8, 0x80, 0x78, 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,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,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,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,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,0x48,0xF8,0x00,0x00, // E
0x00, 0x00, 0xF8, 0x48, 0x50, 0x70, 0x50, 0x40, 0x40, 0xE0, 0x00, 0x00, // F 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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,0x48,0x48,0x48,0x48,0x30,0x00,0x00, // U
0x00, 0x00, 0xCC, 0x48, 0x48, 0x50, 0x50, 0x30, 0x20, 0x20, 0x00, 0x00, // V 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,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,0x50,0x50,0xD8,0x00,0x00, // X
0x00, 0x00, 0xD8, 0x50, 0x50, 0x20, 0x20, 0x20, 0x20, 0x70, 0x00, 0x00, // Y 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,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,0x38,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x38,0x00, // [
0x00, 0x40, 0x40, 0x40, 0x20, 0x20, 0x10, 0x10, 0x10, 0x08, 0x00, 0x00, // <Backslash> 0x00,0x40,0x40,0x40,0x20,0x20,0x10,0x10,0x10,0x08,0x00,0x00, // <Backslash>
0x00, 0x70, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x70, 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,0x20,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ^
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, // _ 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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,0xD8,0x60,0x40,0x40,0xE0,0x00,0x00, // r
0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x40, 0x30, 0x08, 0x78, 0x00, 0x00, // s 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,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,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,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,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,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,0xEC,0x48,0x50,0x30,0x20,0x20,0xC0, // y
0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x10, 0x20, 0x20, 0x78, 0x00, 0x00, // z 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, // { 0x00,0x18,0x10,0x10,0x10,0x20,0x10,0x10,0x10,0x10,0x18,0x00, // {
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, // | 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10, // |
0x00, 0x60, 0x20, 0x20, 0x20, 0x10, 0x20, 0x20, 0x20, 0x20, 0x60, 0x00, // } 0x00,0x60,0x20,0x20,0x20,0x10,0x20,0x20,0x20,0x20,0x60,0x00, // }
0x40, 0xA4, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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,0x20,0x20,0x30,0x50,0x50,0x78,0x48,0xCC,0x00,0x00, // Ä
0x50, 0x00, 0x70, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x70, 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, // Ü 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,0x38,0x48,0x3C,0x00,0x00, // ä
0x00, 0x00, 0x00, 0x48, 0x00, 0x30, 0x48, 0x48, 0x48, 0x30, 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 // ü 0x00,0x00,0x00,0x48,0x00,0xD8,0x48,0x48,0x48,0x3C,0x00,0x00 // ü
}; };
// BigFont.c (C)2010 by Henning Karlsen // BigFont.c (C)2010 by Henning Karlsen
// Font Size : 16x16 // Font Size : 16x16
// Memory usage : 3236 bytes // Memory usage : 3236 bytes
// # characters : 101 // # characters : 101
const char big_font[3236] = { const char big_font[3236] = {
0x10, 0x10, 0x20, 0x65, 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, // <Space> 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, // <Space>
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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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, // <Backslash> 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, // <Backslash>
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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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, // ~ 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,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,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, // Ü 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,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,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 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 // SevenSegNumFont.c
// Font Size : 32x50 // Font Size : 32x50
// Memory usage : 2004 bytes // Memory usage : 2004 bytes
// # characters : 10 // # characters : 10
const char seven_seg_num_font[2004] = { const char seven_seg_num_font[2004] = {
0x20, 0x32, 0x30, 0x0A, 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,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,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,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,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,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,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,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,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,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 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
}; };

View File

@@ -1,16 +1,3 @@
/**************************************************************************************************************************************
* 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 small_font[1216];
const char big_font[3236]; const char big_font[3236];
const char seven_seg_num_font[2004]; const char seven_seg_num_font[2004];

View File

@@ -1,56 +1,38 @@
/**************************************************************************************************************************************
* 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 "ll_filesystem.h"
#include <stdio.h> #include <stdio.h>
bool ll_filesystem_init() bool ll_filesystem_init() {
{ return false;
return false;
} }
DIRECTORY_STRUCT* ll_filesystem_dir_open(const char* path) DIRECTORY_STRUCT* ll_filesystem_dir_open(const char* path) {
{ return NULL;
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) FILE_HANDLE* ll_filesystem_file_open(const char* filename) {
{ return NULL;
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) FILE_STATUS ll_filesystem_file_seek(FILE_HANDLE* handle, uint32_t offset) {
{ return F_DISKERROR;
return F_DISKERROR;
} }
FILE_STATUS ll_filesystem_file_read(FILE_HANDLE* handle, uint8_t* buf, uint32_t size) FILE_STATUS ll_filesystem_file_read(FILE_HANDLE* handle, uint8_t* buf, uint32_t size) {
{ return F_DISKERROR;
return F_DISKERROR;
} }
FILE_STATUS ll_filesystem_file_write(FILE_HANDLE* handle, uint8_t* buf, uint32_t size) FILE_STATUS ll_filesystem_file_write(FILE_HANDLE* handle, uint8_t* buf, uint32_t size) {
{ return F_DISKERROR;
return F_DISKERROR;
} }

View File

@@ -1,80 +1,60 @@
/************************************************************************************************************************************** #include "ll_system.h"
* Project: discoverpixy #include "stm32f4xx.h"
* Website: https://github.com/t-moe/discoverpixy #include "stm32f4_discovery.h"
* Authors: Aaron Schmocker, Timo Lang #include <stdio.h>
* Institution: BFH Bern University of Applied Sciences
* File: discovery/src/ll_system.c #include "usb_hcd_int.h"
* #include "usbh_usr.h"
* Version History: #include "usbh_core.h"
* Date Autor Email SHA Changes #include "usbh_msc_core.h"
* 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. USB_OTG_CORE_HANDLE USB_OTG_Core;
* 2015-04-25 timolang@gmail.com 0858b0d Fixed some bugs when receiving large data. USBH_HOST USB_Host;
* 2015-04-27 aaron@duckpond.ch 0b61f21 Fixed misplacement of prototypes in ll_tft.h and implemented a propper init function. RCC_ClocksTypeDef RCC_Clocks;
* 2015-06-02 timolang@gmail.com 16bfdad Removed conflicting led usage from usb code.
* void SysTick_Handler(void)
**************************************************************************************************************************************/ {
USBH_LL_systick();
#include "ll_system.h" }
#include "stm32f4xx.h"
#include "stm32f4_discovery.h" void TIM2_IRQHandler(void)
#include <stdio.h> {
USB_OTG_BSP_TimerIRQ();
#include "usb_hcd_int.h" }
#include "usbh_usr.h"
#include "usbh_core.h" void OTG_FS_IRQHandler(void)
#include "usbh_msc_core.h" {
USBH_OTG_ISR_Handler(&USB_OTG_Core);
USB_OTG_CORE_HANDLE USB_OTG_Core; }
USBH_HOST USB_Host;
RCC_ClocksTypeDef RCC_Clocks; bool ll_system_init(void)
{
void SysTick_Handler(void) /* Initialize LEDS */
{ STM_EVAL_LEDInit(LED3);
USBH_LL_systick(); STM_EVAL_LEDInit(LED4);
} //LED5 and LED6 can not be used because of pin conflict. See docu
void TIM2_IRQHandler(void) STM_EVAL_PBInit(BUTTON_USER, BUTTON_MODE_GPIO);
{
USB_OTG_BSP_TimerIRQ();
} /* SysTick end of count event each 1ms */
RCC_GetClocksFreq(&RCC_Clocks); //we run at 168mhz :)
void OTG_FS_IRQHandler(void) SysTick_Config(RCC_Clocks.HCLK_Frequency / 1000);
{
USBH_OTG_ISR_Handler(&USB_OTG_Core); /* Init Host Library */
} USBH_Init(&USB_OTG_Core, USB_OTG_FS_CORE_ID, &USB_Host, &USBH_MSC_cb, &USR_Callbacks);
bool ll_system_init(void) return true;
{ }
/* Initialize LEDS */
STM_EVAL_LEDInit(LED3); void ll_system_process() {
STM_EVAL_LEDInit(LED4); USBH_Process(&USB_OTG_Core, &USB_Host);
//LED5 and LED6 can not be used because of pin conflict. See docu }
STM_EVAL_PBInit(BUTTON_USER, BUTTON_MODE_GPIO); void ll_system_delay(uint32_t msec) {
USB_OTG_BSP_mDelay(msec);
}
/* SysTick end of count event each 1ms */
RCC_GetClocksFreq(&RCC_Clocks); //we run at 168mhz :) void ll_system_toggle_led() {
SysTick_Config(RCC_Clocks.HCLK_Frequency / 1000); //no led's free :(
}
/* 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 :(
}

View File

@@ -1,31 +1,5 @@
/**************************************************************************************************************************************
* 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 /* TFT lowlevel functions
* *
* Pinout: * Pinout:
* ---------------------------------------- * ----------------------------------------
* PB0 -> LCD_Backlight PE3 -> LCD_RS * PB0 -> LCD_Backlight PE3 -> LCD_RS
@@ -68,18 +42,17 @@ static void tft_set_backlight(bool state);
static void tft_reset(bool state); static void tft_reset(bool state);
static void tft_write_reg(uint8_t reg_adr, uint16_t reg_value); static void tft_write_reg(uint8_t reg_adr, uint16_t reg_value);
static uint16_t tft_read_reg(uint8_t reg_adr); 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); static void tft_set_window(uint16_t xstart, uint16_t ystart, uint16_t xend, uint16_t yend);void tft_reset_window();
void tft_reset_window();
/* draw functions */ /* 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_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_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_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); void ll_tft_draw_circle(uint16_t x, uint16_t y, uint16_t r, uint16_t color);
/* font functions */ /* 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_num_fonts();
uint8_t ll_tft_font_height(uint8_t fontnum); uint8_t ll_tft_font_height(uint8_t fontnum);
uint8_t ll_tft_font_width(uint8_t fontnum); uint8_t ll_tft_font_width(uint8_t fontnum);
@@ -100,7 +73,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_YELLOW 0xFFE0
#define DISPLAY_COLOR_GREY 0xF7DE #define DISPLAY_COLOR_GREY 0xF7DE
// FSMC adresses // FSMC adresses
#define TFT_REG (*((volatile unsigned short *) 0x60000000)) // RS = 0 #define TFT_REG (*((volatile unsigned short *) 0x60000000)) // RS = 0
#define TFT_RAM (*((volatile unsigned short *) 0x60100000)) // RS = 1 #define TFT_RAM (*((volatile unsigned short *) 0x60100000)) // RS = 1
#define TFT_RAM_ADR 0x60100000 // RAM adress #define TFT_RAM_ADR 0x60100000 // RAM adress
@@ -142,105 +115,105 @@ bool ll_tft_init()
fsmc = fsmc_init(); // init fsmc fsmc = fsmc_init(); // init fsmc
system_delay(TFT_INIT_TIMEOUT); // delay system_delay(TFT_INIT_TIMEOUT); // delay
display = display_init(); // init display display = display_init(); // init display
return (gpio & fsmc & display); return (gpio & fsmc & display);
} }
static bool display_init() static bool display_init()
{ {
tft_reset(true); // toggle reset tft_reset(true); // toggle reset
system_delay(TFT_INIT_TIMEOUT); system_delay(TFT_INIT_TIMEOUT);
tft_reset(false); tft_reset(false);
tft_write_reg(0x0007, 0x0021); tft_write_reg(0x0007,0x0021);
system_delay(TFT_INIT_TIMEOUT); system_delay(TFT_INIT_TIMEOUT);
tft_write_reg(0x0000, 0x0001); tft_write_reg(0x0000,0x0001);
system_delay(TFT_INIT_TIMEOUT); system_delay(TFT_INIT_TIMEOUT);
tft_write_reg(0x0007, 0x0023); tft_write_reg(0x0007,0x0023);
system_delay(TFT_INIT_TIMEOUT); system_delay(TFT_INIT_TIMEOUT);
tft_write_reg(0x0010, 0x0000); tft_write_reg(0x0010,0x0000);
system_delay(TFT_INIT_TIMEOUT); system_delay(TFT_INIT_TIMEOUT);
tft_write_reg(0x0007, 0x0033); tft_write_reg(0x0007,0x0033);
system_delay(TFT_INIT_TIMEOUT); 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); system_delay(TFT_INIT_TIMEOUT);
tft_write_reg(0x0002, 0x0600); tft_write_reg(0x0002,0x0600);
system_delay(TFT_INIT_TIMEOUT); system_delay(TFT_INIT_TIMEOUT);
//tft_write_reg(0x0012,0x6CEB); //tft_write_reg(0x0012,0x6CEB);
system_delay(TFT_INIT_TIMEOUT); system_delay(TFT_INIT_TIMEOUT);
tft_write_reg(0x0003, 0xA8A4); tft_write_reg(0x0003,0xA8A4);
system_delay(TFT_INIT_TIMEOUT); system_delay(TFT_INIT_TIMEOUT);
tft_write_reg(0x000C, 0x0000); tft_write_reg(0x000C,0x0000);
system_delay(TFT_INIT_TIMEOUT); system_delay(TFT_INIT_TIMEOUT);
tft_write_reg(0x000D, 0x080C); tft_write_reg(0x000D,0x080C);
system_delay(TFT_INIT_TIMEOUT); system_delay(TFT_INIT_TIMEOUT);
tft_write_reg(0x000E, 0x2B00); tft_write_reg(0x000E,0x2B00);
system_delay(TFT_INIT_TIMEOUT); system_delay(TFT_INIT_TIMEOUT);
tft_write_reg(0x001E, 0x00B0); tft_write_reg(0x001E,0x00B0);
system_delay(TFT_INIT_TIMEOUT); system_delay(TFT_INIT_TIMEOUT);
tft_write_reg(0x0001, 0x2b3F); tft_write_reg(0x0001,0x2b3F);
system_delay(TFT_INIT_TIMEOUT); system_delay(TFT_INIT_TIMEOUT);
tft_write_reg(0x0005, 0x0000); tft_write_reg(0x0005,0x0000);
system_delay(TFT_INIT_TIMEOUT); system_delay(TFT_INIT_TIMEOUT);
tft_write_reg(0x0006, 0x0000); tft_write_reg(0x0006,0x0000);
system_delay(TFT_INIT_TIMEOUT); system_delay(TFT_INIT_TIMEOUT);
tft_write_reg(0x0016, 0xEF1C); tft_write_reg(0x0016,0xEF1C);
system_delay(TFT_INIT_TIMEOUT); system_delay(TFT_INIT_TIMEOUT);
tft_write_reg(0x0017, 0x0103); tft_write_reg(0x0017,0x0103);
system_delay(TFT_INIT_TIMEOUT); system_delay(TFT_INIT_TIMEOUT);
tft_write_reg(0x000B, 0x0000); tft_write_reg(0x000B,0x0000);
system_delay(TFT_INIT_TIMEOUT); system_delay(TFT_INIT_TIMEOUT);
tft_write_reg(0x000F, 0x0000); tft_write_reg(0x000F,0x0000);
system_delay(TFT_INIT_TIMEOUT); system_delay(TFT_INIT_TIMEOUT);
tft_write_reg(0x0041, 0x0000); tft_write_reg(0x0041,0x0000);
system_delay(TFT_INIT_TIMEOUT); system_delay(TFT_INIT_TIMEOUT);
tft_write_reg(0x0042, 0x0000); tft_write_reg(0x0042,0x0000);
system_delay(TFT_INIT_TIMEOUT); system_delay(TFT_INIT_TIMEOUT);
tft_write_reg(0x0048, 0x0000); tft_write_reg(0x0048,0x0000);
system_delay(TFT_INIT_TIMEOUT); system_delay(TFT_INIT_TIMEOUT);
tft_write_reg(0x0049, 0x013F); tft_write_reg(0x0049,0x013F);
system_delay(TFT_INIT_TIMEOUT); system_delay(TFT_INIT_TIMEOUT);
tft_write_reg(0x004A, 0x0000); tft_write_reg(0x004A,0x0000);
system_delay(TFT_INIT_TIMEOUT); system_delay(TFT_INIT_TIMEOUT);
tft_write_reg(0x004B, 0x0000); tft_write_reg(0x004B,0x0000);
system_delay(TFT_INIT_TIMEOUT); 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); system_delay(TFT_INIT_TIMEOUT);
tft_write_reg(0x0045, 0x0000); // vertical start tft_write_reg(0x0045,0x0000); // vertical start
system_delay(TFT_INIT_TIMEOUT); system_delay(TFT_INIT_TIMEOUT);
tft_write_reg(0x0046, 0x013F); // vertical end tft_write_reg(0x0046,0x013F); // vertical end
system_delay(TFT_INIT_TIMEOUT); system_delay(TFT_INIT_TIMEOUT);
tft_write_reg(0x0030, 0x0707); tft_write_reg(0x0030,0x0707);
system_delay(TFT_INIT_TIMEOUT); system_delay(TFT_INIT_TIMEOUT);
tft_write_reg(0x0031, 0x0204); tft_write_reg(0x0031,0x0204);
system_delay(TFT_INIT_TIMEOUT); system_delay(TFT_INIT_TIMEOUT);
tft_write_reg(0x0032, 0x0204); tft_write_reg(0x0032,0x0204);
system_delay(TFT_INIT_TIMEOUT); system_delay(TFT_INIT_TIMEOUT);
tft_write_reg(0x0033, 0x0502); tft_write_reg(0x0033,0x0502);
system_delay(TFT_INIT_TIMEOUT); system_delay(TFT_INIT_TIMEOUT);
tft_write_reg(0x0034, 0x0507); tft_write_reg(0x0034,0x0507);
system_delay(TFT_INIT_TIMEOUT); system_delay(TFT_INIT_TIMEOUT);
tft_write_reg(0x0035, 0x0204); tft_write_reg(0x0035,0x0204);
system_delay(TFT_INIT_TIMEOUT); system_delay(TFT_INIT_TIMEOUT);
tft_write_reg(0x0036, 0x0204); tft_write_reg(0x0036,0x0204);
system_delay(TFT_INIT_TIMEOUT); system_delay(TFT_INIT_TIMEOUT);
tft_write_reg(0x0037, 0x0502); tft_write_reg(0x0037,0x0502);
system_delay(TFT_INIT_TIMEOUT); system_delay(TFT_INIT_TIMEOUT);
tft_write_reg(0x003A, 0x0302); tft_write_reg(0x003A,0x0302);
system_delay(TFT_INIT_TIMEOUT); system_delay(TFT_INIT_TIMEOUT);
//tft_write_reg(0x002F,0x12BE); //tft_write_reg(0x002F,0x12BE);
system_delay(TFT_INIT_TIMEOUT); system_delay(TFT_INIT_TIMEOUT);
tft_write_reg(0x003B, 0x0302); tft_write_reg(0x003B,0x0302);
system_delay(TFT_INIT_TIMEOUT); system_delay(TFT_INIT_TIMEOUT);
tft_write_reg(0x0023, 0x0000); tft_write_reg(0x0023,0x0000);
system_delay(TFT_INIT_TIMEOUT); system_delay(TFT_INIT_TIMEOUT);
tft_write_reg(0x0024, 0x0000); tft_write_reg(0x0024,0x0000);
system_delay(TFT_INIT_TIMEOUT); system_delay(TFT_INIT_TIMEOUT);
tft_write_reg(0x0025, 0x8000); tft_write_reg(0x0025,0x8000);
system_delay(TFT_INIT_TIMEOUT); system_delay(TFT_INIT_TIMEOUT);
tft_write_reg(0x004f, 0x0000); tft_write_reg(0x004f,0x0000);
system_delay(TFT_INIT_TIMEOUT); system_delay(TFT_INIT_TIMEOUT);
tft_write_reg(0x004e, 0x0000); tft_write_reg(0x004e,0x0000);
system_delay(TFT_INIT_TIMEOUT); system_delay(TFT_INIT_TIMEOUT);
TFT_REG = TFT_SSD1289_REG_22; TFT_REG = TFT_SSD1289_REG_22;
@@ -252,11 +225,11 @@ static bool fsmc_init()
// generate init structures // generate init structures
FSMC_NORSRAMInitTypeDef FSMC_NORSRAMInitStructure; FSMC_NORSRAMInitTypeDef FSMC_NORSRAMInitStructure;
FSMC_NORSRAMTimingInitTypeDef FSMC_NORSRAMTimingInitStructure; FSMC_NORSRAMTimingInitTypeDef FSMC_NORSRAMTimingInitStructure;
// clock enable // clock enable
RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_FSMC, ENABLE); RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_FSMC, ENABLE);
// prepare timing struct // prepare timing struct
FSMC_NORSRAMTimingInitStructure.FSMC_AddressSetupTime = TFT_SSD1289_FSMC_AST; FSMC_NORSRAMTimingInitStructure.FSMC_AddressSetupTime = TFT_SSD1289_FSMC_AST;
FSMC_NORSRAMTimingInitStructure.FSMC_AddressHoldTime = 1; FSMC_NORSRAMTimingInitStructure.FSMC_AddressHoldTime = 1;
FSMC_NORSRAMTimingInitStructure.FSMC_DataSetupTime = TFT_SSD1289_FSMC_DST; FSMC_NORSRAMTimingInitStructure.FSMC_DataSetupTime = TFT_SSD1289_FSMC_DST;
@@ -264,26 +237,26 @@ static bool fsmc_init()
FSMC_NORSRAMTimingInitStructure.FSMC_CLKDivision = 0; FSMC_NORSRAMTimingInitStructure.FSMC_CLKDivision = 0;
FSMC_NORSRAMTimingInitStructure.FSMC_DataLatency = 0; FSMC_NORSRAMTimingInitStructure.FSMC_DataLatency = 0;
FSMC_NORSRAMTimingInitStructure.FSMC_AccessMode = FSMC_AccessMode_A; FSMC_NORSRAMTimingInitStructure.FSMC_AccessMode = FSMC_AccessMode_A;
// bank-1 / PSRAM-1 // bank-1 / PSRAM-1
FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM1; FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM1;
FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable; FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;
FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_SRAM; FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_SRAM;
FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b; FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;
FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable; FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable;
FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait = FSMC_AsynchronousWait_Disable; FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait = FSMC_AsynchronousWait_Disable;
FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low; FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;
FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable; FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable;
FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState; FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;
FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable; FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable;
FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable; FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable;
FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable; FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable;
FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable; FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable;
FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &FSMC_NORSRAMTimingInitStructure; FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &FSMC_NORSRAMTimingInitStructure;
FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &FSMC_NORSRAMTimingInitStructure; FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &FSMC_NORSRAMTimingInitStructure;
// config FSMC // config FSMC
FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure); FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure);
// enable Bank-1 / PSRAM-1 // enable Bank-1 / PSRAM-1
FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM1, ENABLE); FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM1, ENABLE);
@@ -296,20 +269,20 @@ static bool gpio_init()
GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitTypeDef GPIO_InitStructure;
// clock enable PORT_B, PORT_D, PORT_E // clock enable PORT_B, PORT_D, PORT_E
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD,ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE,ENABLE);
// PORT_B init // PORT_B init -------------------------------------------------------------------------------------
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
// configure PORT_B // configure PORT_B
GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_Init(GPIOB, &GPIO_InitStructure);
// PORT_D init // PORT_D init -------------------------------------------------------------------------------------
GPIO_PinAFConfig(GPIOD, GPIO_PinSource0, GPIO_AF_FSMC); // PD0=FSMC_D2 -> DB2 GPIO_PinAFConfig(GPIOD, GPIO_PinSource0, GPIO_AF_FSMC); // PD0=FSMC_D2 -> DB2
GPIO_PinAFConfig(GPIOD, GPIO_PinSource1, GPIO_AF_FSMC); // PD1=FSMC_D3 -> DB3 GPIO_PinAFConfig(GPIOD, GPIO_PinSource1, GPIO_AF_FSMC); // PD1=FSMC_D3 -> DB3
GPIO_PinAFConfig(GPIOD, GPIO_PinSource4, GPIO_AF_FSMC); // PD4=FSMC_NOE -> RD GPIO_PinAFConfig(GPIOD, GPIO_PinSource4, GPIO_AF_FSMC); // PD4=FSMC_NOE -> RD
@@ -317,25 +290,25 @@ static bool gpio_init()
GPIO_PinAFConfig(GPIOD, GPIO_PinSource7, GPIO_AF_FSMC); // PD7=FSMC_NE1 -> CS 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_PinSource8, GPIO_AF_FSMC); // PD8=FSMC_D13 -> DB15
GPIO_PinAFConfig(GPIOD, GPIO_PinSource9, GPIO_AF_FSMC); // PD9=FSMC_D14 -> DB16 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_PinSource14, GPIO_AF_FSMC); // PD14=FSMC_D0 -> DB0
GPIO_PinAFConfig(GPIOD, GPIO_PinSource15, GPIO_AF_FSMC); // PD15=FSMC_D1 -> DB1 GPIO_PinAFConfig(GPIOD, GPIO_PinSource15, GPIO_AF_FSMC); // PD15=FSMC_D1 -> DB1
// PORT_D struct // PORT_D struct
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5 | 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_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 |
GPIO_Pin_14 | GPIO_Pin_15; GPIO_Pin_14 | GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
// configure PORT_D // configure PORT_D
GPIO_Init(GPIOD, &GPIO_InitStructure); GPIO_Init(GPIOD, &GPIO_InitStructure);
// PORT_E init // PORT_E init --------------------------------------------------------------------------------------
GPIO_PinAFConfig(GPIOE, GPIO_PinSource3, GPIO_AF_FSMC); // PE3=FSMC_A19 -> RS 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_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_PinSource9, GPIO_AF_FSMC); // PE9=FSMC_D6 -> DB6
GPIO_PinAFConfig(GPIOE, GPIO_PinSource10, GPIO_AF_FSMC); // PE10=FSMC_D7 -> DB7 GPIO_PinAFConfig(GPIOE, GPIO_PinSource10, GPIO_AF_FSMC); // PE10=FSMC_D7 -> DB7
GPIO_PinAFConfig(GPIOE, GPIO_PinSource11, GPIO_AF_FSMC); // PE11=FSMC_D8 -> DB10 GPIO_PinAFConfig(GPIOE, GPIO_PinSource11, GPIO_AF_FSMC); // PE11=FSMC_D8 -> DB10
@@ -343,17 +316,15 @@ static bool gpio_init()
GPIO_PinAFConfig(GPIOE, GPIO_PinSource13, GPIO_AF_FSMC); // PE13=FSMC_D10 -> DB12 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_PinSource14, GPIO_AF_FSMC); // PE14=FSMC_D11 -> DB13
GPIO_PinAFConfig(GPIOE, GPIO_PinSource15, GPIO_AF_FSMC); // PE15=FSMC_D12 -> DB14 GPIO_PinAFConfig(GPIOE, GPIO_PinSource15, GPIO_AF_FSMC); // PE15=FSMC_D12 -> DB14
// PORT_E struct // PORT_E struct
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | 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_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 |
GPIO_Pin_14 | GPIO_Pin_15; GPIO_Pin_14 | GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
// configure PORT_E // configure PORT_E
GPIO_Init(GPIOE, &GPIO_InitStructure); GPIO_Init(GPIOE, &GPIO_InitStructure);
@@ -363,150 +334,152 @@ static bool gpio_init()
/* /*
* ---------------------- display control functions ------------------------------------------------------- * ---------------------- display control functions -------------------------------------------------------
*/ */
void ll_tft_clear(uint16_t color)
// Clear the whole screen by filling it with a specifig color
void ll_tft_clear(uint16_t color)
{ {
uint32_t n = 0; uint32_t n = 0;
// set cursor to 0 // set cursor to 0
tft_set_cursor(0, 0); tft_set_cursor(0,0);
for (n = 0; n < TFT_PIXEL; n++) { for(n = 0; n < TFT_PIXEL; n++) {
TFT_RAM = color; TFT_RAM = color;
} }
} }
// Set the cursorposition
static void tft_set_cursor(uint16_t xpos, uint16_t ypos) static void tft_set_cursor(uint16_t xpos, uint16_t ypos)
{ {
// set cursor // set cursor
tft_write_reg(TFT_SSD1289_REG_4E, ypos); 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; 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){
GPIOB->BSRRH = GPIO_Pin_0; // set the backlight output GPIOB->BSRRH = GPIO_Pin_0;
} else { // else } else {
GPIOB->BSRRL = GPIO_Pin_0; // reset the backlight GPIOB->BSRRL = GPIO_Pin_0;
} }
} }
// 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){
GPIOB->BSRRH = GPIO_Pin_0; // Set the reset pin GPIOB->BSRRH = GPIO_Pin_0;
} else { // else } else {
GPIOB->BSRRL = GPIO_Pin_0; // reset the reset pin GPIOB->BSRRL = GPIO_Pin_0;
} }
} }
// Send a single command to the display controller
static void tft_write_reg(uint8_t reg_adr, uint16_t reg_value) static void tft_write_reg(uint8_t reg_adr, uint16_t reg_value)
{ {
TFT_REG = reg_adr; // set adress TFT_REG = reg_adr;
TFT_RAM = reg_value; // send command TFT_RAM = reg_value;
} }
// Read a register value of the display controller
static uint16_t tft_read_reg(uint8_t reg_adr) static uint16_t tft_read_reg(uint8_t reg_adr)
{ {
TFT_REG = reg_adr; // set adress TFT_REG = reg_adr;
return TFT_RAM; // return value return TFT_RAM;
} }
// 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) 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; uint16_t ystart_end;
start = (ystart & 0x00FF); // Start adress of the window start = (ystart & 0x00FF);
end = ((yend & 0x00FF) << 8); // End adress of the window end = ((yend & 0x00FF) << 8);
ystart_end = (start | end); // Calculate y endpoint ystart_end = (start | end);
tft_write_reg(TFT_SSD1289_REG_44, ystart_end); // Send y size tft_write_reg(TFT_SSD1289_REG_44, ystart_end);
tft_write_reg(TFT_SSD1289_REG_45, 319 - xend); // Send x start tft_write_reg(TFT_SSD1289_REG_45, 319-xend);
tft_write_reg(TFT_SSD1289_REG_46, 319 - xstart); // Send x end tft_write_reg(TFT_SSD1289_REG_46, 319-xstart);
} }
// Reset a Window
void tft_reset_window() void tft_reset_window()
{ {
// Commands according to the datasheet tft_write_reg(0x44,239<<8);
tft_write_reg(0x44, 239 << 8); tft_write_reg(0x45,0);
tft_write_reg(0x45, 0); tft_write_reg(0x46,319);
tft_write_reg(0x46, 319);
} }
/* /*
* ---------------------- draw functions ----------------------------------------------------------- * ---------------------- draw functions -----------------------------------------------------------
*/ */
// 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! //Without floating point!
int deltax = ((int)x2 - (int)x1); int deltax = ((int)x2-(int)x1);
int deltay = ((int)y2 - (int)y1) << 1; int deltay = ((int)y2-(int)y1)<<1;
int x = 0; int x = 0;
if (x1>x2)
if (x1 > x2) { {
do { do
tft_set_cursor(x1 + x, y1 + (((long)deltay * (long)x / deltax + 1) >> 1)); {
tft_set_cursor(x1+x,y1+ (((long)deltay*(long)x/deltax+1)>>1));
TFT_RAM = color; TFT_RAM = color;
} while (x-- != deltax); }
} else { while(x--!=deltax);
do {
tft_set_cursor(x1 + x, y1 + (((long)deltay * (long)x / deltax + 1) >> 1));
TFT_RAM = color;
} while (x++ != deltax);
} }
} else { // => iterate over y distance else
int deltax = ((int)x2 - (int)x1) << 1; {
int deltay = ((int)y2 - (int)y1); do
int y = 0; {
tft_set_cursor(x1+x,y1+ (((long)deltay*(long)x/deltax+1)>>1));
if (y1 > y2) {
do {
tft_set_cursor(x1 + (((long)deltax * (long)y / deltay + 1) >> 1), y1 + y);
TFT_RAM = color; TFT_RAM = color;
} while (y-- != deltay); }
} else { while(x++!=deltax);
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);
TFT_RAM = color; // Draw the pixel TFT_RAM = color;
} }
// 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 tmp;
unsigned int i; unsigned int i;
if (x1 > x2) { if(x1 > x2){
tmp = x1; tmp = x1;
x1 = x2; x1 = x2;
x2 = tmp; x2 = tmp;
} }
if (y1 > y2) { if(y1 > y2){
tmp = y1; tmp = y1;
y1 = y2; y1 = y2;
y2 = tmp; y2 = tmp;
@@ -515,20 +488,13 @@ void ll_tft_draw_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, u
i = x1; i = x1;
//Drawing the two horizontal lines //Drawing the two horizontal lines
tft_set_cursor(x1, y1); tft_set_cursor(x1, y1);
while(i++ != x2) TFT_RAM = color;
while (i++ != x2) { tft_set_cursor(x1,y2);
TFT_RAM = color; while(i-- != x1) 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; i = y1;
tft_write_reg(0x11,0x6030); // Change adresspointer direction tft_write_reg(0x11,0x6030); // Change adresspointer direction
tft_set_cursor(x2, y1); tft_set_cursor(x2, y1);
@@ -537,42 +503,41 @@ void ll_tft_draw_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, u
while(i-- != y1) TFT_RAM = color; while(i-- != y1) TFT_RAM = color;
tft_write_reg(0x11,0x6018); // Set adresspointer direction normal again tft_write_reg(0x11,0x6018); // Set adresspointer direction normal again
*/ */
tft_draw_line(x1, y1, x1, y2, color); tft_draw_line(x1,y1,x1,y2,color);
tft_draw_line(x2, y1, x2, 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; uint16_t area;
uint32_t n; uint32_t n;
unsigned int tmp; unsigned int tmp;
if (x1 > x2) { if(x1 > x2){
tmp = x1; tmp = x1;
x1 = x2; x1 = x2;
x2 = tmp; x2 = tmp;
} }
if (y1 > y2) { if(y1 > y2){
tmp = y1; tmp = y1;
y1 = y2; y1 = y2;
y2 = tmp; y2 = tmp;
} }
// set window // set window
tft_set_window(x1, y1, x2, y2); tft_set_window(x1, y1, x2, y2);
tft_set_cursor(x1, y1); tft_set_cursor(x1, y1);
// calculate area // calculate area
area = (x2 - x1 + 1) * (y2 - y1 + 1); area = (x2 - x1 + 1) * (y2 - y1 + 1);
// fill area // fill area
for (n = 0; n < area; n++) { for(n = 0; n < area; n++) {
TFT_RAM = color; TFT_RAM = color;
} }
tft_reset_window(); tft_reset_window();
} }
@@ -590,82 +555,77 @@ void ll_tft_draw_circle(uint16_t x, uint16_t y, uint16_t r, uint16_t color)
* ---------------------- font functions ----------------------------------------------------------- * ---------------------- font functions -----------------------------------------------------------
*/ */
static const char* get_font(uint8_t font) static const char *get_font(uint8_t font)
{ {
switch (font) { switch(font){
case 0: case 0: return small_font;
return small_font; case 1: return big_font;
case 2: return seven_seg_num_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]; 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]; 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 width = (uint8_t) font[0];
unsigned char height = (uint8_t) font[1]; unsigned char height = (uint8_t) font[1];
unsigned char offset = (uint8_t) font[2]; 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 int cnt = 0;
unsigned char bitm = 0; unsigned char bitm = 0;
bool bgIsTrans = (bgcolor == TRANSPARENT); bool bgIsTrans = (bgcolor == TRANSPARENT);
unsigned char xadd = 0; unsigned char xadd=0;
unsigned char yadd = 0; unsigned char yadd=0;
tft_set_window(x, y, x + width - 1, y + height - 1); tft_set_window(x, y, x + width - 1, y + height - 1);
tft_set_cursor(x, y); tft_set_cursor(x, y);
for (cnt = (width / 8) * height; cnt > 0; cnt--) { for(cnt = (width / 8) * height; cnt > 0; cnt--){
for (bitm = 0x80; bitm > 0; bitm >>= 1) { for(bitm = 0x80; bitm > 0; bitm >>= 1){
if ((font[ind]) & bitm) { if((font[ind]) & bitm){
if (bgIsTrans) { if(bgIsTrans) {
tft_set_cursor(x + xadd, y + yadd); tft_set_cursor(x+xadd,y+yadd);
} }
TFT_RAM = color; TFT_RAM = color;
} else { } else {
if (!bgIsTrans) { if(!bgIsTrans) {
TFT_RAM = bgcolor; TFT_RAM = bgcolor;
} }
}
if (bgIsTrans) {
xadd++;
if (xadd == width) {
xadd = 0;
yadd++;
}
} }
if(bgIsTrans)
{
xadd++;
if(xadd==width)
{
xadd=0;
yadd++;
}
}
} }
ind++; ind++;
} }
tft_reset_window(); tft_reset_window();
} }

View File

@@ -1,28 +1,3 @@
/**************************************************************************************************************************************
* 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 "ll_touch.h"
#include "screen.h" #include "screen.h"
#include "screen_calibrate.h" #include "screen_calibrate.h"
@@ -47,8 +22,8 @@
/* Globals ----------------------------------------------------------- */ /* Globals ----------------------------------------------------------- */
volatile bool pen_state = false; // PenDown = True; PenUp = False; volatile bool pen_state = false; // PenDown = True; PenUp = False;
volatile bool tim_flag = false; volatile bool tim_flag = false;
volatile uint16_t x_samples[NSAMPLE - 1]; volatile uint16_t x_samples[NSAMPLE-1];
volatile uint16_t y_samples[NSAMPLE - 1]; volatile uint16_t y_samples[NSAMPLE-1];
volatile int i; volatile int i;
/* Prototypes -------------------------------------------------------- */ /* Prototypes -------------------------------------------------------- */
@@ -67,11 +42,11 @@ static uint16_t avg_vals(volatile uint16_t samples[], uint16_t len)
uint16_t j = 0; uint16_t j = 0;
uint32_t tmp = 0; uint32_t tmp = 0;
for (j = 0; j < len; j++) { for(j = 0; j < len; j++){
tmp += samples[j]; tmp += samples[j];
} }
return (uint16_t)(tmp / len); return (uint16_t)(tmp/len);
} }
static uint16_t touch_get_x_coord() static uint16_t touch_get_x_coord()
@@ -79,8 +54,8 @@ static uint16_t touch_get_x_coord()
uint16_t buf_x = 0; uint16_t buf_x = 0;
CLEAR_CS; // clear chipselect CLEAR_CS; // clear chipselect
touch_send(REQ_X_COORD); // request x coordinate 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; buf_x |= touch_send(REQ_1_DATAB) >> 3;
SET_CS; // set chipselect SET_CS; // set chipselect
@@ -94,7 +69,7 @@ static uint16_t touch_get_y_coord()
CLEAR_CS; // clear chipselect CLEAR_CS; // clear chipselect
touch_send(REQ_Y_COORD); // request y coordinate touch_send(REQ_Y_COORD); // request y coordinate
buf_y = ((uint16_t) touch_send(REQ_1_DATAB)) << 5; buf_y = ((uint16_t) touch_send(REQ_1_DATAB)) << 5;
buf_y |= touch_send(REQ_1_DATAB) >> 3; buf_y |= touch_send(REQ_1_DATAB) >> 3;
@@ -105,13 +80,10 @@ static uint16_t touch_get_y_coord()
static uint8_t touch_send(uint8_t dat) static uint8_t touch_send(uint8_t dat)
{ {
SPI_I2S_SendData(SPI2, dat); SPI_I2S_SendData(SPI2, dat);
while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY) != RESET);
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);
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);
return SPI_I2S_ReceiveData(SPI2);
} }
void touch_test(uint16_t x, uint16_t y) void touch_test(uint16_t x, uint16_t y)
@@ -128,12 +100,12 @@ void touch_test(uint16_t x, uint16_t y)
tft_print_line(10, 30, WHITE, TRANSPARENT, 0, (const char*)ys); 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_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) touch_set_calibration_values(526, 2922, 588, 2736); //set calibration values (copied from memory using the debugger)
//We have a ADS7843 Touch controller //We have a ADS7843 Touch controller
//Datasheet: http://www.ti.com/lit/ds/symlink/ads7843.pdf //Datasheet: http://www.ti.com/lit/ds/symlink/ads7843.pdf
@@ -152,13 +124,13 @@ bool ll_touch_init()
GPIO_SPI2_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_SPI2_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_SPI2_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_SPI2_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOB, &GPIO_SPI2_InitStructure); GPIO_Init(GPIOB, &GPIO_SPI2_InitStructure);
SET_CS; // set chip select SET_CS; // set chip select
/* fill gpio init struct and init gpio */ /* fill gpio init struct and init gpio */
GPIO_StructInit(&GPIO_SPI2_InitStructure); GPIO_StructInit(&GPIO_SPI2_InitStructure);
GPIO_SPI2_InitStructure.GPIO_Pin = GPIO_Pin_9; // 9 = SPI2_CS 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_OType = GPIO_OType_PP;
GPIO_SPI2_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_SPI2_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_SPI2_InitStructure); GPIO_Init(GPIOB, &GPIO_SPI2_InitStructure);
@@ -167,7 +139,7 @@ bool ll_touch_init()
GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_SPI2); GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_SPI2);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource14, GPIO_AF_SPI2); GPIO_PinAFConfig(GPIOB, GPIO_PinSource14, GPIO_AF_SPI2);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource15, GPIO_AF_SPI2); GPIO_PinAFConfig(GPIOB, GPIO_PinSource15, GPIO_AF_SPI2);
SPI_I2S_DeInit(SPI2); // Clear spi initialisation SPI_I2S_DeInit(SPI2); // Clear spi initialisation
/* fill spi init structure */ /* fill spi init structure */
@@ -212,9 +184,9 @@ static void init_exti()
gpio.GPIO_PuPd = GPIO_PuPd_UP; gpio.GPIO_PuPd = GPIO_PuPd_UP;
gpio.GPIO_Speed = GPIO_Speed_100MHz; gpio.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_Init(GPIOC, &gpio); GPIO_Init(GPIOC, &gpio);
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC, EXTI_PinSource1); // Bind Exti_line1 to PC1 SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC, EXTI_PinSource1); // Bind Exti_line1 to PC1
/* Set GPIOA0 as input */ /* Set GPIOA0 as input */
gpio.GPIO_Mode = GPIO_Mode_IN; gpio.GPIO_Mode = GPIO_Mode_IN;
gpio.GPIO_OType = GPIO_OType_OD; gpio.GPIO_OType = GPIO_OType_OD;
@@ -229,10 +201,10 @@ static void init_exti()
EXTI_StructInit(&exti); EXTI_StructInit(&exti);
exti.EXTI_Line = EXTI_Line1; exti.EXTI_Line = EXTI_Line1;
exti.EXTI_Mode = EXTI_Mode_Interrupt; 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.EXTI_LineCmd = ENABLE;
EXTI_Init(&exti); EXTI_Init(&exti);
/* EXTI on PA0 */ /* EXTI on PA0 */
EXTI_StructInit(&exti); EXTI_StructInit(&exti);
exti.EXTI_Line = EXTI_Line0; exti.EXTI_Line = EXTI_Line0;
@@ -247,7 +219,7 @@ static void init_exti()
nvic.NVIC_IRQChannelSubPriority = 0x00; // Set sub priority nvic.NVIC_IRQChannelSubPriority = 0x00; // Set sub priority
nvic.NVIC_IRQChannelCmd = ENABLE; // Enable interrupt nvic.NVIC_IRQChannelCmd = ENABLE; // Enable interrupt
NVIC_Init(&nvic); // Config NVIC NVIC_Init(&nvic); // Config NVIC
/* Add IRQ vector to NVIC */ /* Add IRQ vector to NVIC */
nvic.NVIC_IRQChannel = EXTI0_IRQn; // PA0 -> EXTI_Line0 -> EXTI0_IRQn vector nvic.NVIC_IRQChannel = EXTI0_IRQn; // PA0 -> EXTI_Line0 -> EXTI0_IRQn vector
nvic.NVIC_IRQChannelPreemptionPriority = 0x00; // Set priority nvic.NVIC_IRQChannelPreemptionPriority = 0x00; // Set priority
@@ -260,7 +232,7 @@ static void init_timer()
{ {
TIM_TimeBaseInitTypeDef t; TIM_TimeBaseInitTypeDef t;
const int APB1_CLK = 42E6; const int APB1_CLK = 42E6;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7, ENABLE); // Enable clock for TIM6 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7, ENABLE); // Enable clock for TIM6
/* Timer 7 configuration */ /* Timer 7 configuration */
@@ -291,16 +263,16 @@ void EXTI1_IRQHandler()
void TIM7_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 TIM_Cmd(TIM7, DISABLE); // Disable the timer during the measuring
if (PENIRQ) { // Only do this if the PENIRQ line is still low if(PENIRQ){ // Only do this if the PENIRQ line is still low
for (i = 0; i < (NSAMPLE - 1); i++) { // Sample 16 times for(i = 0; i < (NSAMPLE-1); i++){ // Sample 16 times
x_samples[i] = touch_get_x_coord(); x_samples[i] = touch_get_x_coord();
y_samples[i] = touch_get_y_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 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); //tft_draw_pixel(avg_vals(x_samples, NSAMPLE), avg_vals(y_samples, NSAMPLE), RED);
TIM_Cmd(TIM7, ENABLE); // Reenable timer TIM_Cmd(TIM7, ENABLE); // Reenable timer
@@ -309,8 +281,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 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); //tft_draw_pixel(avg_vals(x_samples, NSAMPLE), avg_vals(y_samples, NSAMPLE), RED);
TIM_Cmd(TIM7, DISABLE); // Disable timer TIM_Cmd(TIM7, DISABLE); // Disable timer
} }
TIM_ClearFlag(TIM7, TIM_IT_Update); // Clear timer interrupt flag TIM_ClearFlag(TIM7, TIM_IT_Update); // Clear timer interrupt flag
} }
} }

View File

@@ -1,27 +1,12 @@
/************************************************************************************************************************************** #include "app.h"
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy int main(void)
* Authors: Aaron Schmocker, Timo Lang {
* Institution: BFH Bern University of Applied Sciences app_init();
* File: discovery/src/main.c
* while (1)
* Version History: {
* Date Autor Email SHA Changes app_process();
* 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();
}
}

View File

@@ -1,16 +1,3 @@
/**************************************************************************************************************************************
* 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 * newlib_stubs.c
* *
@@ -45,30 +32,26 @@ extern int errno;
A pointer to a list of environment variables and their values. A pointer to a list of environment variables and their values.
For a minimal environment, this empty list is adequate: For a minimal environment, this empty list is adequate:
*/ */
char* __env[1] = { 0 }; char *__env[1] = { 0 };
char** environ = __env; 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); _write(1, "exit", 4);
while (1) { while (1) {
; ;
} }
} }
int _close(int file) int _close(int file) {
{
return -1; return -1;
} }
/* /*
execve execve
Transfer control to a new process. Minimal implementation (for a system without processes): 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; errno = ENOMEM;
return -1; return -1;
} }
@@ -77,8 +60,7 @@ int _execve(char* name, char** argv, char** env)
Create a new process. Minimal implementation (for a system without processes): Create a new process. Minimal implementation (for a system without processes):
*/ */
int _fork() int _fork() {
{
errno = EAGAIN; errno = EAGAIN;
return -1; return -1;
} }
@@ -88,8 +70,7 @@ int _fork()
all files are regarded as character special devices. 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. 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; st->st_mode = S_IFCHR;
return 0; return 0;
} }
@@ -99,8 +80,7 @@ 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: 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; return 1;
} }
@@ -108,14 +88,12 @@ int _getpid()
isatty isatty
Query whether output stream is a terminal. For consistency with the other minimal implementations, Query whether output stream is a terminal. For consistency with the other minimal implementations,
*/ */
int _isatty(int file) int _isatty(int file) {
{ switch (file){
switch (file) {
case STDOUT_FILENO: case STDOUT_FILENO:
case STDERR_FILENO: case STDERR_FILENO:
case STDIN_FILENO: case STDIN_FILENO:
return 1; return 1;
default: default:
//errno = ENOTTY; //errno = ENOTTY;
errno = EBADF; errno = EBADF;
@@ -128,8 +106,7 @@ int _isatty(int file)
kill kill
Send a signal. Minimal implementation: Send a signal. Minimal implementation:
*/ */
int _kill(int pid, int sig) int _kill(int pid, int sig) {
{
errno = EINVAL; errno = EINVAL;
return (-1); return (-1);
} }
@@ -139,8 +116,7 @@ int _kill(int pid, int sig)
Establish a new name for an existing file. Minimal implementation: Establish a new name for an existing file. Minimal implementation:
*/ */
int _link(char* old, char* new) int _link(char *old, char *new) {
{
errno = EMLINK; errno = EMLINK;
return -1; return -1;
} }
@@ -149,8 +125,7 @@ int _link(char* old, char* new)
lseek lseek
Set position in a file. Minimal implementation: 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; return 0;
} }
@@ -159,27 +134,25 @@ int _lseek(int file, int ptr, int dir)
Increase program data space. Increase program data space.
Malloc and related functions depend on this Malloc and related functions depend on this
*/ */
caddr_t _sbrk(int incr) caddr_t _sbrk(int incr) {
{
extern char _ebss; // Defined by the linker extern char _ebss; // Defined by the linker
static char* heap_end; static char *heap_end;
char* prev_heap_end; char *prev_heap_end;
if (heap_end == 0) { if (heap_end == 0) {
heap_end = &_ebss; heap_end = &_ebss;
} }
prev_heap_end = heap_end; prev_heap_end = heap_end;
char* stack = (char*) __get_MSP(); char * stack = (char*) __get_MSP();
if (heap_end + incr > stack)
if (heap_end + incr > stack) { {
_write(STDERR_FILENO, "Heap and stack collision\n", 25); _write (STDERR_FILENO, "Heap and stack collision\n", 25);
errno = ENOMEM; errno = ENOMEM;
return (caddr_t) - 1; return (caddr_t) -1;
//abort (); //abort ();
} }
heap_end += incr; heap_end += incr;
return (caddr_t) prev_heap_end; return (caddr_t) prev_heap_end;
@@ -188,10 +161,10 @@ caddr_t _sbrk(int incr)
int _open(char* path, int flags, ...) int _open(char *path, int flags, ...)
{ {
/* Pretend like we always fail */ /* Pretend like we always fail */
return -1; return -1;
} }
/* /*
@@ -201,33 +174,30 @@ 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 n;
int num = 0; int num = 0;
switch (file) { switch (file) {
/*case STDIN_FILENO: /*case STDIN_FILENO:
for (n = 0; n < len; n++) { for (n = 0; n < len; n++) {
#if STDIN_USART == 1 #if STDIN_USART == 1
while ((USART1->SR & USART_FLAG_RXNE) == (uint16_t)RESET) {} while ((USART1->SR & USART_FLAG_RXNE) == (uint16_t)RESET) {}
char c = (char)(USART1->DR & (uint16_t)0x01FF); char c = (char)(USART1->DR & (uint16_t)0x01FF);
#elif STDIN_USART == 2 #elif STDIN_USART == 2
while ((USART2->SR & USART_FLAG_RXNE) == (uint16_t) RESET) {} while ((USART2->SR & USART_FLAG_RXNE) == (uint16_t) RESET) {}
char c = (char) (USART2->DR & (uint16_t) 0x01FF); char c = (char) (USART2->DR & (uint16_t) 0x01FF);
#elif STDIN_USART == 3 #elif STDIN_USART == 3
while ((USART3->SR & USART_FLAG_RXNE) == (uint16_t)RESET) {} while ((USART3->SR & USART_FLAG_RXNE) == (uint16_t)RESET) {}
char c = (char)(USART3->DR & (uint16_t)0x01FF); char c = (char)(USART3->DR & (uint16_t)0x01FF);
#endif #endif
*ptr++ = c; *ptr++ = c;
num++; num++;
} }
break; break;
default:*/ default:*/
errno = EBADF; errno = EBADF;
return -1; return -1;
} }
return num; return num;
} }
@@ -237,8 +207,7 @@ int _read(int file, char* ptr, int len)
int _EXFUN(stat,( const char *__path, struct stat *__sbuf )); 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; st->st_mode = S_IFCHR;
return 0; return 0;
} }
@@ -248,8 +217,7 @@ int _stat(const char* filepath, struct stat* st)
Timing information for current process. Minimal implementation: Timing information for current process. Minimal implementation:
*/ */
clock_t _times(struct tms* buf) clock_t _times(struct tms *buf) {
{
return -1; return -1;
} }
@@ -257,8 +225,7 @@ clock_t _times(struct tms* buf)
unlink unlink
Remove a file's directory entry. Minimal implementation: Remove a file's directory entry. Minimal implementation:
*/ */
int _unlink(char* name) int _unlink(char *name) {
{
errno = ENOENT; errno = ENOENT;
return -1; return -1;
} }
@@ -267,8 +234,7 @@ int _unlink(char* name)
wait wait
Wait for a child process. Minimal implementation: Wait for a child process. Minimal implementation:
*/ */
int _wait(int* status) int _wait(int *status) {
{
errno = ECHILD; errno = ECHILD;
return -1; return -1;
} }
@@ -278,61 +244,42 @@ int _wait(int* status)
Write a character to a file. `libc' subroutines will use this system routine for output to all files, including stdout 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 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; int n;
switch (file) { switch (file) {
case STDOUT_FILENO: /*stdout*/ case STDOUT_FILENO: /*stdout*/
for (n = 0; n < len; n++) { for (n = 0; n < len; n++) {
#if STDOUT_USART == 1 #if STDOUT_USART == 1
while ((USART1->SR & USART_FLAG_TC) == (uint16_t)RESET) {} while ((USART1->SR & USART_FLAG_TC) == (uint16_t)RESET) {}
USART1->DR = (*ptr++ & (uint16_t)0x01FF); USART1->DR = (*ptr++ & (uint16_t)0x01FF);
#elif STDOUT_USART == 2 #elif STDOUT_USART == 2
while ((USART2->SR & USART_FLAG_TC) == (uint16_t) RESET) { while ((USART2->SR & USART_FLAG_TC) == (uint16_t) RESET) {
} }
USART2->DR = (*ptr++ & (uint16_t) 0x01FF); USART2->DR = (*ptr++ & (uint16_t) 0x01FF);
#elif STDOUT_USART == 3 #elif STDOUT_USART == 3
while ((USART3->SR & USART_FLAG_TC) == (uint16_t)RESET) {} while ((USART3->SR & USART_FLAG_TC) == (uint16_t)RESET) {}
USART3->DR = (*ptr++ & (uint16_t)0x01FF); USART3->DR = (*ptr++ & (uint16_t)0x01FF);
#endif #endif
} }
break; break;
case STDERR_FILENO: /* stderr */ case STDERR_FILENO: /* stderr */
for (n = 0; n < len; n++) { for (n = 0; n < len; n++) {
#if STDERR_USART == 1 #if STDERR_USART == 1
while ((USART1->SR & USART_FLAG_TC) == (uint16_t)RESET) {} while ((USART1->SR & USART_FLAG_TC) == (uint16_t)RESET) {}
USART1->DR = (*ptr++ & (uint16_t)0x01FF); USART1->DR = (*ptr++ & (uint16_t)0x01FF);
#elif STDERR_USART == 2 #elif STDERR_USART == 2
while ((USART2->SR & USART_FLAG_TC) == (uint16_t) RESET) { while ((USART2->SR & USART_FLAG_TC) == (uint16_t) RESET) {
} }
USART2->DR = (*ptr++ & (uint16_t) 0x01FF); USART2->DR = (*ptr++ & (uint16_t) 0x01FF);
#elif STDERR_USART == 3 #elif STDERR_USART == 3
while ((USART3->SR & USART_FLAG_TC) == (uint16_t)RESET) {} while ((USART3->SR & USART_FLAG_TC) == (uint16_t)RESET) {}
USART3->DR = (*ptr++ & (uint16_t)0x01FF); USART3->DR = (*ptr++ & (uint16_t)0x01FF);
#endif #endif
} }
break; break;
default: default:
errno = EBADF; errno = EBADF;
return -1; return -1;
} }
return len; return len;
} }

File diff suppressed because it is too large Load Diff

View File

@@ -1,468 +1,460 @@
/**************************************************************************************************************************************
* Project: discoverpixy /* Includes ------------------------------------------------------------------*/
* Website: https://github.com/t-moe/discoverpixy #include "usb_bsp.h"
* Authors: Aaron Schmocker, Timo Lang #include "stm32f4_discovery.h"
* Institution: BFH Bern University of Applied Sciences
* File: discovery/src/usb_bsp.c #define USE_ACCURATE_TIME
* #define TIM_MSEC_DELAY 0x01
* Version History: #define TIM_USEC_DELAY 0x02
* Date Autor Email SHA Changes #define HOST_OVRCURR_PORT GPIOD
* 2015-04-03 timolang@gmail.com 21dd1e2 Starting to integrate usb branch. Optimized Makefiles #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
/* Includes ------------------------------------------------------------------*/ #define HOST_OVRCURR_IRQn EXTI9_5_IRQn
#include "usb_bsp.h"
#include "stm32f4_discovery.h"
#define HOST_POWERSW_PORT_RCC RCC_AHB1Periph_GPIOC
#define USE_ACCURATE_TIME #define HOST_POWERSW_PORT GPIOC
#define TIM_MSEC_DELAY 0x01 #define HOST_POWERSW_VBUS GPIO_Pin_0
#define TIM_USEC_DELAY 0x02
#define HOST_OVRCURR_PORT GPIOD /* Private macros ------------------------------------------------------------*/
#define HOST_OVRCURR_LINE GPIO_Pin_5 /* Private variables ---------------------------------------------------------*/
#define HOST_OVRCURR_PORT_SOURCE GPIO_PortSourceGPIOD ErrorStatus HSEStartUpStatus;
#define HOST_OVRCURR_PIN_SOURCE GPIO_PinSourceD #ifdef USE_ACCURATE_TIME
#define HOST_OVRCURR_PORT_RCC RCC_APB2Periph_GPIOD __IO uint32_t BSP_delay = 0;
#define HOST_OVRCURR_EXTI_LINE EXTI_Line5 #endif
#define HOST_OVRCURR_IRQn EXTI9_5_IRQn
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
#define HOST_POWERSW_PORT_RCC RCC_AHB1Periph_GPIOC #ifdef USE_ACCURATE_TIME
#define HOST_POWERSW_PORT GPIOC static void BSP_SetTime(uint8_t Unit);
#define HOST_POWERSW_VBUS GPIO_Pin_0 static void BSP_Delay(uint32_t nTime, uint8_t Unit);
static void USB_OTG_BSP_TimeInit ( void );
/* Private macros ------------------------------------------------------------*/ #endif
/* Private variables ---------------------------------------------------------*/
ErrorStatus HSEStartUpStatus; /**
#ifdef USE_ACCURATE_TIME * @brief BSP_Init
__IO uint32_t BSP_delay = 0; * board user initializations
#endif * @param None
* @retval None
/* Private function prototypes -----------------------------------------------*/ */
/* Private functions ---------------------------------------------------------*/ void BSP_Init(void)
#ifdef USE_ACCURATE_TIME {
static void BSP_SetTime(uint8_t Unit); /* Configure PA0 pin: User Key pin */
static void BSP_Delay(uint32_t nTime, uint8_t Unit); }
static void USB_OTG_BSP_TimeInit(void);
#endif
/**
/** * @brief USB_OTG_BSP_Init
* @brief BSP_Init * Initilizes BSP configurations
* board user initializations * @param None
* @param None * @retval None
* @retval None */
*/ void USB_OTG_BSP_Init(USB_OTG_CORE_HANDLE *pdev)
void BSP_Init(void) {
{ /* Note: On STM32F4-Discovery board only USB OTG FS core is supported. */
/* Configure PA0 pin: User Key pin */
} GPIO_InitTypeDef GPIO_InitStructure;
#ifdef USE_USB_OTG_FS
/** RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOA , ENABLE);
* @brief USB_OTG_BSP_Init
* Initilizes BSP configurations /* Configure SOF VBUS ID DM DP Pins */
* @param None GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 |
* @retval None GPIO_Pin_11 |
*/ GPIO_Pin_12;
void USB_OTG_BSP_Init(USB_OTG_CORE_HANDLE* pdev)
{ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
/* Note: On STM32F4-Discovery board only USB OTG FS core is supported. */ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
#ifdef USE_USB_OTG_FS GPIO_Init(GPIOA, &GPIO_InitStructure);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA , ENABLE); GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_OTG1_FS) ;
GPIO_PinAFConfig(GPIOA,GPIO_PinSource11,GPIO_AF_OTG1_FS) ;
/* Configure SOF VBUS ID DM DP Pins */ GPIO_PinAFConfig(GPIOA,GPIO_PinSource12,GPIO_AF_OTG1_FS) ;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 |
GPIO_Pin_11 | /* this for ID line debug */
GPIO_Pin_12;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP ;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_OTG1_FS) ;
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) ; RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_OTG_FS, ENABLE) ;
/* this for ID line debug */ #else // USE_USB_OTG_HS
#ifdef USE_ULPI_PHY // ULPI
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB |
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD; RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOH |
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP ; RCC_AHB1Periph_GPIOI, ENABLE);
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_OTG1_FS) ; 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
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); GPIO_PinAFConfig(GPIOB,GPIO_PinSource1, GPIO_AF_OTG2_HS) ; // D2
RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_OTG_FS, ENABLE) ; GPIO_PinAFConfig(GPIOB,GPIO_PinSource5, GPIO_AF_OTG2_HS) ; // D7
#else // USE_USB_OTG_HS GPIO_PinAFConfig(GPIOB,GPIO_PinSource10,GPIO_AF_OTG2_HS) ; // D3
GPIO_PinAFConfig(GPIOB,GPIO_PinSource11,GPIO_AF_OTG2_HS) ; // D4
#ifdef USE_ULPI_PHY // ULPI GPIO_PinAFConfig(GPIOB,GPIO_PinSource12,GPIO_AF_OTG2_HS) ; // D5
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | GPIO_PinAFConfig(GPIOB,GPIO_PinSource13,GPIO_AF_OTG2_HS) ; // D6
RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOH | GPIO_PinAFConfig(GPIOH,GPIO_PinSource4, GPIO_AF_OTG2_HS) ; // NXT
RCC_AHB1Periph_GPIOI, ENABLE); GPIO_PinAFConfig(GPIOI,GPIO_PinSource11,GPIO_AF_OTG2_HS) ; // DIR
GPIO_PinAFConfig(GPIOC,GPIO_PinSource0, GPIO_AF_OTG2_HS) ; // STP
GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_OTG2_HS) ; // D0 // CLK
GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_OTG2_HS) ; // CLK GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 ;
GPIO_PinAFConfig(GPIOB, GPIO_PinSource0, GPIO_AF_OTG2_HS) ; // D1 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_PinAFConfig(GPIOB, GPIO_PinSource1, GPIO_AF_OTG2_HS) ; // D2 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_PinAFConfig(GPIOB, GPIO_PinSource5, GPIO_AF_OTG2_HS) ; // D7 GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_OTG2_HS) ; // D3
GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_OTG2_HS) ; // D4 // D0
GPIO_PinAFConfig(GPIOB, GPIO_PinSource12, GPIO_AF_OTG2_HS) ; // D5 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 ;
GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_OTG2_HS) ; // D6 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_PinAFConfig(GPIOH, GPIO_PinSource4, GPIO_AF_OTG2_HS) ; // NXT GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_PinAFConfig(GPIOI, GPIO_PinSource11, GPIO_AF_OTG2_HS) ; // DIR GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_PinAFConfig(GPIOC, GPIO_PinSource0, GPIO_AF_OTG2_HS) ; // STP GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// CLK
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; // D1 D2 D3 D4 D5 D6 D7
GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 |
GPIO_Pin_5 | GPIO_Pin_10 |
// D0 GPIO_Pin_11| GPIO_Pin_12 |
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 ; GPIO_Pin_13 ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// D1 D2 D3 D4 D5 D6 D7 // STP
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 ;
GPIO_Pin_5 | GPIO_Pin_10 | GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_Pin_11 | GPIO_Pin_12 | GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_Pin_13 ; GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //NXT
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_Init(GPIOH, &GPIO_InitStructure);
// STP //DIR
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 ; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_Init(GPIOC, &GPIO_InitStructure); GPIO_Init(GPIOI, &GPIO_InitStructure);
//NXT
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_OTG_HS |
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; RCC_AHB1Periph_OTG_HS_ULPI, ENABLE) ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_Init(GPIOH, &GPIO_InitStructure); #else
#ifdef USE_I2C_PHY
//DIR RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOB , ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 ; /* Configure RESET INTN SCL SDA (Phy/I2C) Pins */
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 |
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_Pin_1 |
GPIO_Init(GPIOI, &GPIO_InitStructure); GPIO_Pin_10 |
GPIO_Pin_11;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_OTG_HS | GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
RCC_AHB1Periph_OTG_HS_ULPI, ENABLE) ; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_Init(GPIOB, &GPIO_InitStructure);
#else
GPIO_PinAFConfig(GPIOB,GPIO_PinSource0,GPIO_AF_OTG2_FS) ;
#ifdef USE_I2C_PHY GPIO_PinAFConfig(GPIOB,GPIO_PinSource1,GPIO_AF_OTG2_FS) ;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB , ENABLE); GPIO_PinAFConfig(GPIOB,GPIO_PinSource10,GPIO_AF_OTG2_FS) ;
/* Configure RESET INTN SCL SDA (Phy/I2C) Pins */ GPIO_PinAFConfig(GPIOB,GPIO_PinSource11,GPIO_AF_OTG2_FS);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_OTG_HS, ENABLE) ;
GPIO_Pin_1 |
GPIO_Pin_10 | #else
GPIO_Pin_11;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB , ENABLE);
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 |
GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_Pin_13 |
GPIO_Pin_14 |
GPIO_PinAFConfig(GPIOB, GPIO_PinSource0, GPIO_AF_OTG2_FS) ; GPIO_Pin_15;
GPIO_PinAFConfig(GPIOB, GPIO_PinSource1, GPIO_AF_OTG2_FS) ;
GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_OTG2_FS) ; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_OTG2_FS); GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_OTG_HS, ENABLE) ; GPIO_Init(GPIOB, &GPIO_InitStructure);
#else GPIO_PinAFConfig(GPIOB,GPIO_PinSource12, GPIO_AF_OTG2_FS) ;
GPIO_PinAFConfig(GPIOB,GPIO_PinSource13,GPIO_AF_OTG2_FS) ;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB , ENABLE); GPIO_PinAFConfig(GPIOB,GPIO_PinSource14,GPIO_AF_OTG2_FS) ;
GPIO_PinAFConfig(GPIOB,GPIO_PinSource15,GPIO_AF_OTG2_FS) ;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_OTG_HS, ENABLE) ;
GPIO_Pin_13 | #endif
GPIO_Pin_14 | #endif
GPIO_Pin_15; #endif //USB_OTG_HS
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; /* Intialize Timer for delay function */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; USB_OTG_BSP_TimeInit();
GPIO_Init(GPIOB, &GPIO_InitStructure); }
GPIO_PinAFConfig(GPIOB, GPIO_PinSource12, GPIO_AF_OTG2_FS) ; /**
GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_OTG2_FS) ; * @brief USB_OTG_BSP_EnableInterrupt
GPIO_PinAFConfig(GPIOB, GPIO_PinSource14, GPIO_AF_OTG2_FS) ; * Configures USB Global interrupt
GPIO_PinAFConfig(GPIOB, GPIO_PinSource15, GPIO_AF_OTG2_FS) ; * @param None
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_OTG_HS, ENABLE) ; * @retval None
#endif */
#endif void USB_OTG_BSP_EnableInterrupt(USB_OTG_CORE_HANDLE *pdev)
#endif //USB_OTG_HS {
/* Intialize Timer for delay function */ NVIC_InitTypeDef NVIC_InitStructure;
USB_OTG_BSP_TimeInit(); /* Enable USB Interrupt */
} NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
/** NVIC_InitStructure.NVIC_IRQChannel = OTG_FS_IRQn;
* @brief USB_OTG_BSP_EnableInterrupt NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
* Configures USB Global interrupt NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
* @param None NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
* @retval None NVIC_Init(&NVIC_InitStructure);
*/
void USB_OTG_BSP_EnableInterrupt(USB_OTG_CORE_HANDLE* pdev) /* Enable the Overcurrent Interrupt */
{ NVIC_InitStructure.NVIC_IRQChannel = HOST_OVRCURR_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
/* Enable USB Interrupt */ NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = OTG_FS_IRQn; }
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; /**
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; * @brief BSP_Drive_VBUS
NVIC_Init(&NVIC_InitStructure); * Drives the Vbus signal through IO
* @param state : VBUS states
/* Enable the Overcurrent Interrupt */ * @retval None
NVIC_InitStructure.NVIC_IRQChannel = HOST_OVRCURR_IRQn; */
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; void USB_OTG_BSP_DriveVBUS(USB_OTG_CORE_HANDLE *pdev, uint8_t state)
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; {
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; /*
On-chip 5 V VBUS generation is not supported. For this reason, a charge pump
NVIC_Init(&NVIC_InitStructure); 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
* @brief BSP_Drive_VBUS control and status register (PPWR bit in OTG_FS_HPRT).
* Drives the Vbus signal through IO
* @param state : VBUS states Bit 12 PPWR: Port power
* @retval None The application uses this field to control power to this port, and the core
*/ clears this bit on an overcurrent condition.
void USB_OTG_BSP_DriveVBUS(USB_OTG_CORE_HANDLE* pdev, uint8_t state) */
{ if (0 == state)
/* {
On-chip 5 V VBUS generation is not supported. For this reason, a charge pump /* DISABLE is needed on output of the Power Switch */
or, if 5 V are available on the application board, a basic power switch, must GPIO_SetBits(HOST_POWERSW_PORT, HOST_POWERSW_VBUS);
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 else
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). /*ENABLE the Power Switch by driving the Enable LOW */
GPIO_ResetBits(HOST_POWERSW_PORT, HOST_POWERSW_VBUS);
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) { * @brief USB_OTG_BSP_ConfigVBUS
/* DISABLE is needed on output of the Power Switch */ * Configures the IO for the Vbus and OverCurrent
GPIO_SetBits(HOST_POWERSW_PORT, HOST_POWERSW_VBUS); * @param None
} else { * @retval None
/*ENABLE the Power Switch by driving the Enable LOW */ */
GPIO_ResetBits(HOST_POWERSW_PORT, HOST_POWERSW_VBUS); void USB_OTG_BSP_ConfigVBUS(USB_OTG_CORE_HANDLE *pdev)
} {
} GPIO_InitTypeDef GPIO_InitStructure;
/**
* @brief USB_OTG_BSP_ConfigVBUS RCC_AHB1PeriphClockCmd(HOST_POWERSW_PORT_RCC, ENABLE);
* Configures the IO for the Vbus and OverCurrent
* @param None
* @retval None /* Configure Power Switch Vbus Pin */
*/ GPIO_InitStructure.GPIO_Pin = HOST_POWERSW_VBUS;
void USB_OTG_BSP_ConfigVBUS(USB_OTG_CORE_HANDLE* pdev) GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
{ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
RCC_AHB1PeriphClockCmd(HOST_POWERSW_PORT_RCC, ENABLE); GPIO_Init(HOST_POWERSW_PORT, &GPIO_InitStructure);
/* By Default, DISABLE is needed on output of the Power Switch */
/* Configure Power Switch Vbus Pin */ GPIO_SetBits(HOST_POWERSW_PORT, HOST_POWERSW_VBUS);
GPIO_InitStructure.GPIO_Pin = HOST_POWERSW_VBUS;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; USB_OTG_BSP_mDelay(200); /* Delay is need for stabilising the Vbus Low
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; in Reset Condition, when Vbus=1 and Reset-button is pressed by user */
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; }
GPIO_Init(HOST_POWERSW_PORT, &GPIO_InitStructure); /**
* @brief USB_OTG_BSP_TimeInit
/* By Default, DISABLE is needed on output of the Power Switch */ * Initializes delay unit using Timer2
GPIO_SetBits(HOST_POWERSW_PORT, HOST_POWERSW_VBUS); * @param None
* @retval None
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 */ static void USB_OTG_BSP_TimeInit (void)
{
} #ifdef USE_ACCURATE_TIME
NVIC_InitTypeDef NVIC_InitStructure;
/**
* @brief USB_OTG_BSP_TimeInit /* Set the Vector Table base address at 0x08000000 */
* Initializes delay unit using Timer2 // NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x00);
* @param None
* @retval None /* Configure the Priority Group to 2 bits */
*/ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
static void USB_OTG_BSP_TimeInit(void)
{ /* Enable the TIM2 gloabal Interrupt */
#ifdef USE_ACCURATE_TIME NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
/* Set the Vector Table base address at 0x08000000 */ NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
// NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x00);
NVIC_Init(&NVIC_InitStructure);
/* Configure the Priority Group to 2 bits */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
#endif
/* Enable the TIM2 gloabal Interrupt */ }
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; /**
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; * @brief USB_OTG_BSP_uDelay
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; * This function provides delay time in micro sec
* @param usec : Value of delay required in micro sec
NVIC_Init(&NVIC_InitStructure); * @retval None
*/
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); void USB_OTG_BSP_uDelay (const uint32_t usec)
#endif {
}
#ifdef USE_ACCURATE_TIME
/** BSP_Delay(usec, TIM_USEC_DELAY);
* @brief USB_OTG_BSP_uDelay #else
* This function provides delay time in micro sec __IO uint32_t count = 0;
* @param usec : Value of delay required in micro sec const uint32_t utime = (120 * usec / 7);
* @retval None do
*/ {
void USB_OTG_BSP_uDelay(const uint32_t usec) if ( ++count > utime )
{ {
return ;
#ifdef USE_ACCURATE_TIME }
BSP_Delay(usec, TIM_USEC_DELAY); }
#else while (1);
__IO uint32_t count = 0; #endif
const uint32_t utime = (120 * usec / 7);
}
do {
if (++count > utime) { /**
return ; * @brief USB_OTG_BSP_mDelay
} * This function provides delay time in milli sec
} while (1); * @param msec : Value of delay required in milli sec
* @retval None
#endif */
void USB_OTG_BSP_mDelay (const uint32_t msec)
} {
#ifdef USE_ACCURATE_TIME
/** BSP_Delay(msec, TIM_MSEC_DELAY);
* @brief USB_OTG_BSP_mDelay #else
* This function provides delay time in milli sec USB_OTG_BSP_uDelay(msec * 1000);
* @param msec : Value of delay required in milli sec #endif
* @retval None
*/ }
void USB_OTG_BSP_mDelay(const uint32_t msec)
{ /**
#ifdef USE_ACCURATE_TIME * @brief USB_OTG_BSP_TimerIRQ
BSP_Delay(msec, TIM_MSEC_DELAY); * Time base IRQ
#else * @param None
USB_OTG_BSP_uDelay(msec * 1000); * @retval None
#endif */
void USB_OTG_BSP_TimerIRQ (void)
} {
#ifdef USE_ACCURATE_TIME
/** if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
* @brief USB_OTG_BSP_TimerIRQ {
* Time base IRQ TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
* @param None if (BSP_delay > 0x00)
* @retval None {
*/ BSP_delay--;
void USB_OTG_BSP_TimerIRQ(void) }
{ else
#ifdef USE_ACCURATE_TIME {
TIM_Cmd(TIM2, DISABLE);
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) { }
TIM_ClearITPendingBit(TIM2, TIM_IT_Update); }
#endif
if (BSP_delay > 0x00) { }
BSP_delay--;
} else { #ifdef USE_ACCURATE_TIME
TIM_Cmd(TIM2, DISABLE);
} /**
} * @brief BSP_Delay
* Delay routine based on TIM2
#endif * @param nTime : Delay Time
} * @param unit : Delay Time unit : mili sec / micro sec
* @retval None
#ifdef USE_ACCURATE_TIME */
static void BSP_Delay(uint32_t nTime, uint8_t unit)
/** {
* @brief BSP_Delay
* Delay routine based on TIM2 BSP_delay = nTime;
* @param nTime : Delay Time BSP_SetTime(unit);
* @param unit : Delay Time unit : mili sec / micro sec while (BSP_delay != 0);
* @retval None TIM_Cmd(TIM2, DISABLE);
*/ }
static void BSP_Delay(uint32_t nTime, uint8_t unit)
{ /**
* @brief BSP_SetTime
BSP_delay = nTime; * Configures TIM2 for delay routine based on TIM2
BSP_SetTime(unit); * @param unit : msec /usec
* @retval None
while (BSP_delay != 0); */
static void BSP_SetTime(uint8_t unit)
TIM_Cmd(TIM2, DISABLE); {
} TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
/** TIM_Cmd(TIM2, DISABLE);
* @brief BSP_SetTime TIM_ITConfig(TIM2, TIM_IT_Update, DISABLE);
* Configures TIM2 for delay routine based on TIM2
* @param unit : msec /usec
* @retval None if (unit == TIM_USEC_DELAY)
*/ {
static void BSP_SetTime(uint8_t unit) TIM_TimeBaseStructure.TIM_Period = 11;
{ }
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; else if (unit == TIM_MSEC_DELAY)
{
TIM_Cmd(TIM2, DISABLE); TIM_TimeBaseStructure.TIM_Period = 11999;
TIM_ITConfig(TIM2, TIM_IT_Update, DISABLE); }
TIM_TimeBaseStructure.TIM_Prescaler = 5;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
if (unit == TIM_USEC_DELAY) { TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_Period = 11;
} else if (unit == TIM_MSEC_DELAY) { TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
TIM_TimeBaseStructure.TIM_Period = 11999; TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
}
TIM_ARRPreloadConfig(TIM2, ENABLE);
TIM_TimeBaseStructure.TIM_Prescaler = 5;
TIM_TimeBaseStructure.TIM_ClockDivision = 0; /* TIM IT enable */
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); /* TIM2 enable counter */
TIM_ClearITPendingBit(TIM2, TIM_IT_Update); TIM_Cmd(TIM2, ENABLE);
}
TIM_ARRPreloadConfig(TIM2, ENABLE);
#endif
/* TIM IT enable */
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); /**
* @}
/* TIM2 enable counter */ */
TIM_Cmd(TIM2, ENABLE);
}
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
#endif
/**
* @}
*/
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/

View File

@@ -1,276 +1,250 @@
/**************************************************************************************************************************************
* Project: discoverpixy #include "usbh_msc_core.h"
* Website: https://github.com/t-moe/discoverpixy #include "usbh_core.h"
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: discovery/src/usbh_msc_core.c static USBH_Status USBH_MSC_InterfaceInit (USB_OTG_CORE_HANDLE *pdev ,
* void *phost);
* Version History:
* Date Autor Email SHA Changes static void USBH_MSC_InterfaceDeInit (USB_OTG_CORE_HANDLE *pdev ,
* 2015-04-03 timolang@gmail.com 21dd1e2 Starting to integrate usb branch. Optimized Makefiles void *phost);
* 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. 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);
#include "usbh_msc_core.h"
#include "usbh_core.h"
extern USB_OTG_CORE_HANDLE USB_OTG_Core;
extern USBH_HOST USB_Host;
static USBH_Status USBH_MSC_InterfaceInit(USB_OTG_CORE_HANDLE* pdev ,
void* phost);
static void USBH_MSC_InterfaceDeInit(USB_OTG_CORE_HANDLE* pdev , USBH_Class_cb_TypeDef USBH_MSC_cb =
void* phost); {
USBH_MSC_InterfaceInit,
static USBH_Status USBH_MSC_Handle(USB_OTG_CORE_HANDLE* pdev , USBH_MSC_InterfaceDeInit,
void* phost); USBH_MSC_ClassRequest,
USBH_MSC_Handle,
static USBH_Status USBH_MSC_ClassRequest(USB_OTG_CORE_HANDLE* pdev , };
void* phost);
typedef struct
extern USB_OTG_CORE_HANDLE USB_OTG_Core; {
extern USBH_HOST USB_Host; uint8_t hc_num_in;
uint8_t hc_num_out;
uint8_t MSBulkOutEp;
uint8_t MSBulkInEp;
USBH_Class_cb_TypeDef USBH_MSC_cb = { uint16_t MSBulkInEpSize;
USBH_MSC_InterfaceInit, uint16_t MSBulkOutEpSize;
USBH_MSC_InterfaceDeInit, }
USBH_MSC_ClassRequest, MSC_Machine_TypeDef;
USBH_MSC_Handle, MSC_Machine_TypeDef MSC_Machine;
};
static USBH_Status USBH_MSC_InterfaceInit ( USB_OTG_CORE_HANDLE *pdev,
typedef struct { void *phost)
uint8_t hc_num_in; {
uint8_t hc_num_out; USBH_HOST *pphost = phost;
uint8_t MSBulkOutEp;
uint8_t MSBulkInEp;
uint16_t MSBulkInEpSize;
uint16_t MSBulkOutEpSize; if((pphost->device_prop.Itf_Desc[1].bInterfaceClass == 255) &&
} (pphost->device_prop.Itf_Desc[1].bInterfaceProtocol == 0) &&
MSC_Machine_TypeDef; (pphost->device_prop.Itf_Desc[1].bInterfaceSubClass == 1))
MSC_Machine_TypeDef MSC_Machine; {
if(pphost->device_prop.Ep_Desc[0][0].bEndpointAddress & 0x80)
{
static USBH_Status USBH_MSC_InterfaceInit(USB_OTG_CORE_HANDLE* pdev, MSC_Machine.MSBulkInEp = (pphost->device_prop.Ep_Desc[0][0].bEndpointAddress);
void* phost) MSC_Machine.MSBulkInEpSize = pphost->device_prop.Ep_Desc[0][0].wMaxPacketSize;
{ }
USBH_HOST* pphost = phost; 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.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][1].bEndpointAddress & 0x80)
if (pphost->device_prop.Ep_Desc[0][0].bEndpointAddress & 0x80) { {
MSC_Machine.MSBulkInEp = (pphost->device_prop.Ep_Desc[0][0].bEndpointAddress); MSC_Machine.MSBulkInEp = (pphost->device_prop.Ep_Desc[0][1].bEndpointAddress);
MSC_Machine.MSBulkInEpSize = pphost->device_prop.Ep_Desc[0][0].wMaxPacketSize; MSC_Machine.MSBulkInEpSize = pphost->device_prop.Ep_Desc[0][1].wMaxPacketSize;
} else { }
MSC_Machine.MSBulkOutEp = (pphost->device_prop.Ep_Desc[0][0].bEndpointAddress); else
MSC_Machine.MSBulkOutEpSize = pphost->device_prop.Ep_Desc[0][0].wMaxPacketSize; {
} MSC_Machine.MSBulkOutEp = (pphost->device_prop.Ep_Desc[0][1].bEndpointAddress);
MSC_Machine.MSBulkOutEpSize = pphost->device_prop.Ep_Desc[0][1].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; MSC_Machine.hc_num_out = USBH_Alloc_Channel(pdev,MSC_Machine.MSBulkOutEp);
} else { MSC_Machine.hc_num_in = USBH_Alloc_Channel(pdev,MSC_Machine.MSBulkInEp);
MSC_Machine.MSBulkOutEp = (pphost->device_prop.Ep_Desc[0][1].bEndpointAddress);
MSC_Machine.MSBulkOutEpSize = pphost->device_prop.Ep_Desc[0][1].wMaxPacketSize; USBH_Open_Channel (pdev,
} MSC_Machine.hc_num_out,
pphost->device_prop.address,
MSC_Machine.hc_num_out = USBH_Alloc_Channel(pdev, MSC_Machine.MSBulkOutEp); pphost->device_prop.speed,
MSC_Machine.hc_num_in = USBH_Alloc_Channel(pdev, MSC_Machine.MSBulkInEp); EP_TYPE_BULK,
MSC_Machine.MSBulkOutEpSize);
USBH_Open_Channel(pdev,
MSC_Machine.hc_num_out, USBH_Open_Channel (pdev,
pphost->device_prop.address, MSC_Machine.hc_num_in,
pphost->device_prop.speed, pphost->device_prop.address,
EP_TYPE_BULK, pphost->device_prop.speed,
MSC_Machine.MSBulkOutEpSize); EP_TYPE_BULK,
MSC_Machine.MSBulkInEpSize);
USBH_Open_Channel(pdev,
MSC_Machine.hc_num_in, }
pphost->device_prop.address,
pphost->device_prop.speed, else
EP_TYPE_BULK, {
MSC_Machine.MSBulkInEpSize); pphost->usr_cb->USBH_USR_DeviceNotSupported();
}
}
return USBH_OK ;
else {
pphost->usr_cb->USBH_USR_DeviceNotSupported(); }
}
void USBH_MSC_InterfaceDeInit ( USB_OTG_CORE_HANDLE *pdev,
return USBH_OK ; void *phost)
{
} if ( MSC_Machine.hc_num_out)
{
void USBH_MSC_InterfaceDeInit(USB_OTG_CORE_HANDLE* pdev, USB_OTG_HC_Halt(pdev, MSC_Machine.hc_num_out);
void* phost) USBH_Free_Channel (pdev, MSC_Machine.hc_num_out);
{ MSC_Machine.hc_num_out = 0;
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); if ( MSC_Machine.hc_num_in)
MSC_Machine.hc_num_out = 0; {
} USB_OTG_HC_Halt(pdev, MSC_Machine.hc_num_in);
USBH_Free_Channel (pdev, MSC_Machine.hc_num_in);
if (MSC_Machine.hc_num_in) { MSC_Machine.hc_num_in = 0;
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)
{
static USBH_Status USBH_MSC_ClassRequest(USB_OTG_CORE_HANDLE* pdev ,
void* phost) USBH_Status status = USBH_OK ;
{ return status;
}
USBH_Status status = USBH_OK ;
return status; static USBH_Status USBH_MSC_Handle(USB_OTG_CORE_HANDLE *pdev ,
} void *phost)
{
static USBH_Status USBH_MSC_Handle(USB_OTG_CORE_HANDLE* pdev , USBH_HOST *pphost = phost;
void* phost)
{ USBH_Status status = USBH_BUSY;
USBH_HOST* pphost = phost;
if(HCD_IsDeviceConnected(pdev))
USBH_Status status = USBH_BUSY; {
int appliStatus = pphost->usr_cb->USBH_USR_MSC_Application();
if (HCD_IsDeviceConnected(pdev)) { if(appliStatus != 0)
int appliStatus = pphost->usr_cb->USBH_USR_MSC_Application(); {
status = USBH_APPLY_DEINIT;
if (appliStatus != 0) { }
status = USBH_APPLY_DEINIT; }
} return status;
}
}
return status;
} volatile uint32_t cnt;
volatile uint32_t cnt_int;
void USBH_LL_systick() {
volatile uint32_t cnt; cnt++;
volatile uint32_t cnt_int; cnt_int++;
void USBH_LL_systick() }
{
cnt++;
cnt_int++; void USBH_LL_setTimer() {
} cnt=0;
}
void USBH_LL_setTimer() uint32_t USBH_LL_getTimer() {
{ return cnt;
cnt = 0; }
}
uint32_t USBH_LL_getTimer() int USBH_LL_open() {
{ int timeoutDetect=100;
return cnt; int timeoutStartup=3000;
} cnt_int=0; //reset timer
while(USB_Host.gState!=HOST_CLASS && cnt_int < timeoutDetect) {
int USBH_LL_open() USBH_Process(&USB_OTG_Core, &USB_Host);
{ }
int timeoutDetect = 100;
int timeoutStartup = 3000; if(USB_Host.gState!=HOST_CLASS) {
cnt_int = 0; //reset timer return -5; // = LIBUSB_ERROR_NOT_FOUND
}
while (USB_Host.gState != HOST_CLASS && cnt_int < timeoutDetect) {
USBH_Process(&USB_OTG_Core, &USB_Host);
} cnt_int=0;
while(cnt_int<timeoutStartup) { //let pixy's led flashing pass
if (USB_Host.gState != HOST_CLASS) { USBH_Process(&USB_OTG_Core, &USB_Host);
return -5; // = LIBUSB_ERROR_NOT_FOUND }
} return 0; //ok
}
cnt_int = 0; int USBH_LL_close() {
USBH_Process(&USB_OTG_Core, &USB_Host);
while (cnt_int < timeoutStartup) { //let pixy's led flashing pass return 0;
USBH_Process(&USB_OTG_Core, &USB_Host); }
}
int USBH_LL_send(const uint8_t *data, uint32_t len, uint16_t timeoutMs) {
return 0; //ok USB_OTG_CORE_HANDLE *pdev = &USB_OTG_Core;
}
if(!HCD_IsDeviceConnected(pdev)) return -1;
int USBH_LL_close()
{ USBH_BulkSendData (pdev,
USBH_Process(&USB_OTG_Core, &USB_Host); (uint8_t*)data,
return 0; len ,
} MSC_Machine.hc_num_out);
int USBH_LL_send(const uint8_t* data, uint32_t len, uint16_t timeoutMs) URB_STATE state;
{ cnt_int=0; //reset timer
USB_OTG_CORE_HANDLE* pdev = &USB_OTG_Core; if(timeoutMs==0) timeoutMs=1000; //Force 1s timeout (testwise)
if (!HCD_IsDeviceConnected(pdev)) { while((state=HCD_GetURB_State(pdev , MSC_Machine.hc_num_out)) == URB_IDLE &&
return -1; (timeoutMs==0 || cnt_int < timeoutMs));
}
if(state!=URB_DONE) {
USBH_BulkSendData(pdev, if(timeoutMs>0 && cnt_int>=timeoutMs) {
(uint8_t*)data, STM_EVAL_LEDOn(LED3);
len , return -7; //timeout (error code like with libusb)
MSC_Machine.hc_num_out);
}
URB_STATE state; return -1;
cnt_int = 0; //reset timer }
return len;
if (timeoutMs == 0) { }
timeoutMs = 1000; //Force 1s timeout (testwise)
} int USBH_LL_receive(uint8_t *data, uint32_t len, uint16_t timeoutMs) {
while ((state = HCD_GetURB_State(pdev , MSC_Machine.hc_num_out)) == URB_IDLE && USB_OTG_CORE_HANDLE *pdev = &USB_OTG_Core;
(timeoutMs == 0 || cnt_int < timeoutMs));
if(!HCD_IsDeviceConnected(pdev)) return -1;
if (state != URB_DONE) {
if (timeoutMs > 0 && cnt_int >= timeoutMs) { USBH_BulkReceiveData (pdev,
STM_EVAL_LEDOn(LED3); data,
return -7; //timeout (error code like with libusb) len ,
MSC_Machine.hc_num_in);
}
URB_STATE state;
return -1; cnt_int=0; //reset timer
} if(timeoutMs==0) timeoutMs=1000; //Force 1s timeout (testwise)
return len; while((state=HCD_GetURB_State(pdev , MSC_Machine.hc_num_in)) == URB_IDLE &&
} (timeoutMs==0 || cnt_int < timeoutMs));
int USBH_LL_receive(uint8_t* data, uint32_t len, uint16_t timeoutMs) if(state!=URB_DONE) {
{ if(timeoutMs>0 && cnt_int>=timeoutMs) {
STM_EVAL_LEDOn(LED3);
USB_OTG_CORE_HANDLE* pdev = &USB_OTG_Core; return -7; //timeout (error code like with libusb)
}
if (!HCD_IsDeviceConnected(pdev)) { return -1;
return -1; }
} return len;
}
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;
}

View File

@@ -1,38 +1,27 @@
/**************************************************************************************************************************************
* Project: discoverpixy /* Define to prevent recursive ----------------------------------------------*/
* Website: https://github.com/t-moe/discoverpixy #ifndef __USBH_MSC_CORE_H
* Authors: Aaron Schmocker, Timo Lang #define __USBH_MSC_CORE_H
* Institution: BFH Bern University of Applied Sciences
* File: discovery/src/usbh_msc_core.h /* Includes ------------------------------------------------------------------*/
* #include "usbh_core.h"
* Version History: #include "usbh_stdreq.h"
* Date Autor Email SHA Changes #include "usb_bsp.h"
* 2015-04-03 timolang@gmail.com 21dd1e2 Starting to integrate usb branch. Optimized Makefiles #include "usbh_ioreq.h"
* #include "usbh_hcs.h"
**************************************************************************************************************************************/
extern USBH_Class_cb_TypeDef USBH_MSC_cb;
/* Define to prevent recursive ----------------------------------------------*/
#ifndef __USBH_MSC_CORE_H void USBH_LL_systick();
#define __USBH_MSC_CORE_H int USBH_LL_open();
int USBH_LL_close();
/* Includes ------------------------------------------------------------------*/ int USBH_LL_send(const uint8_t *data, uint32_t len, uint16_t timeoutMs);
#include "usbh_core.h" int USBH_LL_receive(uint8_t *data, uint32_t len, uint16_t timeoutMs);
#include "usbh_stdreq.h" void USBH_LL_setTimer();
#include "usb_bsp.h" uint32_t USBH_LL_getTimer();
#include "usbh_ioreq.h"
#include "usbh_hcs.h"
#endif /* __USBH_MSC_CORE_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 */

View File

@@ -1,245 +1,229 @@
/************************************************************************************************************************************** #include "usbh_usr.h"
* Project: discoverpixy #include <stdbool.h>
* Website: https://github.com/t-moe/discoverpixy #include <string.h>
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: discovery/src/usbh_usr.c USBH_Usr_cb_TypeDef USR_Callbacks =
* {
* Version History: USBH_USR_Init,
* Date Autor Email SHA Changes USBH_USR_DeInit,
* 2015-04-03 timolang@gmail.com 21dd1e2 Starting to integrate usb branch. Optimized Makefiles USBH_USR_DeviceAttached,
* 2015-04-03 timolang@gmail.com 9a1d12a Refactored discovery, to use new project structure. Almost ready. USBH_USR_ResetDevice,
* 2015-04-25 timolang@gmail.com 416883c Pixy&Usb work with the new folder structure now. USBH_USR_DeviceDisconnected,
* 2015-04-25 timolang@gmail.com 3d1e4b2 Simplified code a bit. Emulator does not work stable when replugging pixy. USBH_USR_OverCurrentDetected,
* 2015-06-02 timolang@gmail.com 16bfdad Removed conflicting led usage from usb code. USBH_USR_DeviceSpeedDetected,
* USBH_USR_Device_DescAvailable,
**************************************************************************************************************************************/ USBH_USR_DeviceAddressAssigned,
USBH_USR_Configuration_DescAvailable,
#include "usbh_usr.h" USBH_USR_Manufacturer_String,
#include <stdbool.h> USBH_USR_Product_String,
#include <string.h> USBH_USR_SerialNum_String,
USBH_USR_EnumerationDone,
USBH_USR_UserInput,
USBH_Usr_cb_TypeDef USR_Callbacks = { USBH_USR_MSC_Application,
USBH_USR_Init, USBH_USR_DeviceNotSupported,
USBH_USR_DeInit, USBH_USR_UnrecoveredError
USBH_USR_DeviceAttached, };
USBH_USR_ResetDevice,
USBH_USR_DeviceDisconnected,
USBH_USR_OverCurrentDetected, /* Private function prototypes -----------------------------------------------*/
USBH_USR_DeviceSpeedDetected, /* Private functions ---------------------------------------------------------*/
USBH_USR_Device_DescAvailable, bool manufacturer_ok;
USBH_USR_DeviceAddressAssigned, bool product_ok;
USBH_USR_Configuration_DescAvailable, bool serial_ok;
USBH_USR_Manufacturer_String,
USBH_USR_Product_String, /**
USBH_USR_SerialNum_String, * @brief USBH_USR_Init
USBH_USR_EnumerationDone, * @param None
USBH_USR_UserInput, * @retval None
USBH_USR_MSC_Application, */
USBH_USR_DeviceNotSupported, void USBH_USR_Init(void)
USBH_USR_UnrecoveredError {
}; }
/**
/* Private function prototypes -----------------------------------------------*/ * @brief USBH_USR_DeviceAttached
/* Private functions ---------------------------------------------------------*/ * @param None
bool manufacturer_ok; * @retval None
bool product_ok; */
bool serial_ok; void USBH_USR_DeviceAttached(void)
{
/** manufacturer_ok=false;
* @brief USBH_USR_Init product_ok= false;
* @param None serial_ok=false;
* @retval None
*/ STM_EVAL_LEDOff(LED3);
void USBH_USR_Init(void) STM_EVAL_LEDOn(LED4);
{ }
}
/**
/** * @brief USBH_USR_UnrecoveredError
* @brief USBH_USR_DeviceAttached * @param None
* @param None * @retval None
* @retval None */
*/ void USBH_USR_UnrecoveredError (void)
void USBH_USR_DeviceAttached(void) {
{ }
manufacturer_ok = false;
product_ok = false; /**
serial_ok = false; * @brief USBH_DisconnectEvent
* Device disconnect event
STM_EVAL_LEDOff(LED3); * @param None
STM_EVAL_LEDOn(LED4); * @retval Staus
} */
void USBH_USR_DeviceDisconnected (void)
/** {
* @brief USBH_USR_UnrecoveredError STM_EVAL_LEDOff(LED4);
* @param None }
* @retval None
*/ /**
void USBH_USR_UnrecoveredError(void) * @brief USBH_USR_ResetUSBDevice
{ * @param None
} * @retval None
*/
/** void USBH_USR_ResetDevice(void)
* @brief USBH_DisconnectEvent {
* Device disconnect event /* callback for USB-Reset */
* @param None }
* @retval Staus
*/
void USBH_USR_DeviceDisconnected(void) /**
{ * @brief USBH_USR_DeviceSpeedDetected
STM_EVAL_LEDOff(LED4); * Displays the message on LCD for device speed
} * @param Device speed:
* @retval None
/** */
* @brief USBH_USR_ResetUSBDevice void USBH_USR_DeviceSpeedDetected(uint8_t DeviceSpeed)
* @param None {
* @retval None }
*/
void USBH_USR_ResetDevice(void) /**
{ * @brief USBH_USR_Device_DescAvailable
/* callback for USB-Reset */ * @param device descriptor
} * @retval None
*/
void USBH_USR_Device_DescAvailable(void *DeviceDesc)
/** {
* @brief USBH_USR_DeviceSpeedDetected /* callback for device descriptor */
* Displays the message on LCD for device speed }
* @param Device speed:
* @retval None /**
*/ * @brief USBH_USR_DeviceAddressAssigned
void USBH_USR_DeviceSpeedDetected(uint8_t DeviceSpeed) * USB device is successfully assigned the Address
{ * @param None
} * @retval None
*/
/** void USBH_USR_DeviceAddressAssigned(void)
* @brief USBH_USR_Device_DescAvailable {
* @param device descriptor /* callback for device successfully assigned the Address */
* @retval None }
*/
void USBH_USR_Device_DescAvailable(void* DeviceDesc) /**
{ * @brief USBH_USR_Conf_Desc
/* callback for device descriptor */ * @param Configuration descriptor
} * @retval None
*/
/** void USBH_USR_Configuration_DescAvailable(USBH_CfgDesc_TypeDef * cfgDesc,
* @brief USBH_USR_DeviceAddressAssigned USBH_InterfaceDesc_TypeDef *itfDesc,
* USB device is successfully assigned the Address USBH_EpDesc_TypeDef *epDesc)
* @param None {
* @retval None /* callback for configuration descriptor */
*/ }
void USBH_USR_DeviceAddressAssigned(void)
{ /**
/* callback for device successfully assigned the Address */ * @brief USBH_USR_Manufacturer_String
} * @param Manufacturer String
* @retval None
/** */
* @brief USBH_USR_Conf_Desc void USBH_USR_Manufacturer_String(void *ManufacturerString)
* @param Configuration descriptor {
* @retval None manufacturer_ok = strcmp((char*)ManufacturerString,"Charmed Labs") == 0;
*/ }
void USBH_USR_Configuration_DescAvailable(USBH_CfgDesc_TypeDef* cfgDesc,
USBH_InterfaceDesc_TypeDef* itfDesc, /**
USBH_EpDesc_TypeDef* epDesc) * @brief USBH_USR_Product_String
{ * @param Product String
/* callback for configuration descriptor */ * @retval None
} */
void USBH_USR_Product_String(void *ProductString)
/** {
* @brief USBH_USR_Manufacturer_String product_ok = strcmp((char*)ProductString,"Pixy") == 0;
* @param Manufacturer String }
* @retval None
*/ /**
void USBH_USR_Manufacturer_String(void* ManufacturerString) * @brief USBH_USR_SerialNum_String
{ * @param SerialNum_String
manufacturer_ok = strcmp((char*)ManufacturerString, "Charmed Labs") == 0; * @retval None
} */
void USBH_USR_SerialNum_String(void *SerialNumString)
/** {
* @brief USBH_USR_Product_String serial_ok = strcmp((char*)SerialNumString,"DEMO 0.0") == 0;
* @param Product String }
* @retval None
*/ /**
void USBH_USR_Product_String(void* ProductString) * @brief EnumerationDone
{ * User response request is displayed to ask application jump to class
product_ok = strcmp((char*)ProductString, "Pixy") == 0; * @param None
} * @retval None
*/
/** void USBH_USR_EnumerationDone(void)
* @brief USBH_USR_SerialNum_String {
* @param SerialNum_String
* @retval None }
*/
void USBH_USR_SerialNum_String(void* SerialNumString) /**
{ * @brief USBH_USR_DeviceNotSupported
serial_ok = strcmp((char*)SerialNumString, "DEMO 0.0") == 0; * Device is not supported
} * @param None
* @retval None
/** */
* @brief EnumerationDone void USBH_USR_DeviceNotSupported(void)
* User response request is displayed to ask application jump to class {
* @param None }
* @retval None
*/
void USBH_USR_EnumerationDone(void) /**
{ * @brief USBH_USR_UserInput
* User Action for application state entry
} * @param None
* @retval USBH_USR_Status : User response for key button
/** */
* @brief USBH_USR_DeviceNotSupported USBH_USR_Status USBH_USR_UserInput(void)
* Device is not supported {
* @param None if(product_ok&&manufacturer_ok&&serial_ok) {
* @retval None return USBH_USR_RESP_OK;
*/ }
void USBH_USR_DeviceNotSupported(void) return USBH_USR_NO_RESP;
{ }
}
/**
* @brief USBH_USR_OverCurrentDetected
/** * Over Current Detected on VBUS
* @brief USBH_USR_UserInput * @param None
* User Action for application state entry * @retval None
* @param None */
* @retval USBH_USR_Status : User response for key button void USBH_USR_OverCurrentDetected (void)
*/ {
USBH_USR_Status USBH_USR_UserInput(void) }
{
if (product_ok && manufacturer_ok && serial_ok) { /**
return USBH_USR_RESP_OK; * @brief USBH_USR_MSC_Application
} * @param None
* @retval Staus
return USBH_USR_NO_RESP; */
} int USBH_USR_MSC_Application(void)
{
/** return 0;
* @brief USBH_USR_OverCurrentDetected }
* Over Current Detected on VBUS
* @param None /**
* @retval None * @brief USBH_USR_DeInit
*/ * Deint User state and associated variables
void USBH_USR_OverCurrentDetected(void) * @param None
{ * @retval None
} */
void USBH_USR_DeInit(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)
{
}

View File

@@ -1,60 +1,51 @@
/**************************************************************************************************************************************
* Project: discoverpixy /* Define to prevent recursive inclusion -------------------------------------*/
* Website: https://github.com/t-moe/discoverpixy #ifndef __USH_USR_H__
* Authors: Aaron Schmocker, Timo Lang #define __USH_USR_H__
* Institution: BFH Bern University of Applied Sciences
* File: discovery/src/usbh_usr.h #ifdef __cplusplus
* extern "C" {
* Version History: #endif
* Date Autor Email SHA Changes
* 2015-04-03 timolang@gmail.com 21dd1e2 Starting to integrate usb branch. Optimized Makefiles /* Includes ------------------------------------------------------------------*/
* #include "stm32f4_discovery.h"
**************************************************************************************************************************************/ #include "usbh_core.h"
#include <stdio.h>
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USH_USR_H__ /* Exported macros -----------------------------------------------------------*/
#define __USH_USR_H__ /* Exported variables --------------------------------------------------------*/
extern USBH_Usr_cb_TypeDef USR_Callbacks;
#ifdef __cplusplus
extern "C" { /* Exported functions ------------------------------------------------------- */
#endif void USBH_USR_Init(void);
void USBH_USR_DeviceAttached(void);
/* Includes ------------------------------------------------------------------*/ void USBH_USR_ResetDevice(void);
#include "stm32f4_discovery.h" void USBH_USR_DeviceDisconnected (void);
#include "usbh_core.h" void USBH_USR_OverCurrentDetected (void);
#include <stdio.h> void USBH_USR_DeviceSpeedDetected(uint8_t DeviceSpeed);
void USBH_USR_Device_DescAvailable(void *);
void USBH_USR_DeviceAddressAssigned(void);
/* Exported macros -----------------------------------------------------------*/ void USBH_USR_Configuration_DescAvailable(USBH_CfgDesc_TypeDef * cfgDesc,
/* Exported variables --------------------------------------------------------*/ USBH_InterfaceDesc_TypeDef *itfDesc,
extern USBH_Usr_cb_TypeDef USR_Callbacks; USBH_EpDesc_TypeDef *epDesc);
void USBH_USR_Manufacturer_String(void *);
/* Exported functions ------------------------------------------------------- */ void USBH_USR_Product_String(void *);
void USBH_USR_Init(void); void USBH_USR_SerialNum_String(void *);
void USBH_USR_DeviceAttached(void); void USBH_USR_EnumerationDone(void);
void USBH_USR_ResetDevice(void); USBH_USR_Status USBH_USR_UserInput(void);
void USBH_USR_DeviceDisconnected(void); int USBH_USR_MSC_Application(void);
void USBH_USR_OverCurrentDetected(void); void USBH_USR_DeInit(void);
void USBH_USR_DeviceSpeedDetected(uint8_t DeviceSpeed); void USBH_USR_DeviceNotSupported(void);
void USBH_USR_Device_DescAvailable(void*); void USBH_USR_UnrecoveredError(void);
void USBH_USR_DeviceAddressAssigned(void); #ifdef __cplusplus
void USBH_USR_Configuration_DescAvailable(USBH_CfgDesc_TypeDef* cfgDesc, }
USBH_InterfaceDesc_TypeDef* itfDesc, #endif
USBH_EpDesc_TypeDef* epDesc);
void USBH_USR_Manufacturer_String(void*); #endif /*__USH_USR_H__*/
void USBH_USR_Product_String(void*);
void USBH_USR_SerialNum_String(void*); /******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
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****/

View File

@@ -33,11 +33,11 @@
<intAttribute key="org.eclipse.cdt.launch.ATTR_BUILD_BEFORE_LAUNCH_ATTR" value="1"/> <intAttribute key="org.eclipse.cdt.launch.ATTR_BUILD_BEFORE_LAUNCH_ATTR" value="1"/>
<stringAttribute key="org.eclipse.cdt.launch.COREFILE_PATH" value=""/> <stringAttribute key="org.eclipse.cdt.launch.COREFILE_PATH" value=""/>
<stringAttribute key="org.eclipse.cdt.launch.PROGRAM_NAME" value="build/discoverpixy.elf"/> <stringAttribute key="org.eclipse.cdt.launch.PROGRAM_NAME" value="build/discoverpixy.elf"/>
<stringAttribute key="org.eclipse.cdt.launch.PROJECT_ATTR" value="discoverpixy discovery"/> <stringAttribute key="org.eclipse.cdt.launch.PROJECT_ATTR" value="discoverpixy"/>
<booleanAttribute key="org.eclipse.cdt.launch.PROJECT_BUILD_CONFIG_AUTO_ATTR" value="true"/> <booleanAttribute key="org.eclipse.cdt.launch.PROJECT_BUILD_CONFIG_AUTO_ATTR" value="true"/>
<stringAttribute key="org.eclipse.cdt.launch.PROJECT_BUILD_CONFIG_ID_ATTR" value="cdt.managedbuild.toolchain.gnu.cross.base.1368576398"/> <stringAttribute key="org.eclipse.cdt.launch.PROJECT_BUILD_CONFIG_ID_ATTR" value="cdt.managedbuild.toolchain.gnu.cross.base.1368576398"/>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS"> <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
<listEntry value="/discoverpixy discovery"/> <listEntry value="/discoverpixy"/>
</listAttribute> </listAttribute>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES"> <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
<listEntry value="4"/> <listEntry value="4"/>

1
doc/.gitignore vendored
View File

@@ -1,3 +1,2 @@
*.*~ *.*~
html/ html/
latex/

BIN
doc/PID_REGELUNG.tgz Normal file

Binary file not shown.

BIN
doc/PI_PD_REGELUNG.tgz Normal file

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 MiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 185 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

5
emulator/.gitignore vendored
View File

@@ -5,8 +5,9 @@ qt/*.o
qt/*.a qt/*.a
qt/ui_* qt/ui_*
qt/moc_* qt/moc_*
qt/Makefile qt/Makefile*
qt/debug
qt/release
libs/*/obj libs/*/obj
libs/*/*.a libs/*/*.a

View File

@@ -10,7 +10,7 @@ QT_DIR=./qt
COMMON_DIR=../common COMMON_DIR=../common
#Tools #Tools
CC=gcc -fdiagnostics-color=auto CC=gcc #-fdiagnostics=auto
GDB=gdb GDB=gdb
@@ -24,17 +24,22 @@ INCLUDES:=$(addprefix -I,$(INCLUDES))
QT_LIB=$(QT_DIR)/libemulatorqt.a QT_LIB=$(QT_DIR)/libemulatorqt.a
CPPFLAGS= -march=x86-64 -mtune=generic -fPIC $(INCLUDES) CPPFLAGS= -march=x86-64 -mtune=generic #-fPIC
CPPFLAGS+= $(INCLUDES)
CFLAGS= -O0 -g -std=c99 CFLAGS= -O0 -g -std=c99
LIBS= pixy usb-1.0 boost_system boost_timer boost_chrono LIBS= emulatorqt pixy usb-1.0
LIBS+=Qt5Core Qt5Gui Qt5Widgets emulatorqt m stdc++ LIBS+= boost_system-mgw49-mt-1_58 boost_timer-mgw49-mt-1_58 boost_chrono-mgw49-mt-1_58
LIBS+= Qt5Core Qt5Gui Qt5Widgets m stdc++
LDFLAGS= -static-libgcc -static-libstdc++ #-Wl,-t -Wl,--Map=a.map
LDFLAGS= -L$(QT_DIR) $(addprefix -l,$(LIBS)) LDFLAGS+= -L$(QT_DIR)
LDFLAGS+= -L$(LIB_DIR)/Pixy LDFLAGS+= -L$(LIB_DIR)/Pixy
LDFLAGS+= -L$(LIB_DIR)/boost/lib
LDFLAGS+= -LC:/Qt/5.4/mingw491_32/lib
LDFLAGS+= -L$(LIB_DIR)/Pixy/windows
LDFLAGS+= $(addprefix -l,$(LIBS))
#Finding Input files #Finding Input files
CFILES=$(shell find . -maxdepth 1 -name '*.c') CFILES=$(shell find . -maxdepth 1 -name '*.c')
@@ -58,7 +63,7 @@ debug: all
$(GDB) ./build/emulator $(GDB) ./build/emulator
$(QT_LIB): $(QT_LIB):
cd $(QT_DIR) && qmake &&make cd $(QT_DIR) && qmake && $(MAKE)
#objects to elf #objects to elf
$(BUILD_DIR)/$(TARGET): $(OBJS) $(COMMON_OBJS) $(QT_LIB) $(BUILD_DIR)/$(TARGET): $(OBJS) $(COMMON_OBJS) $(QT_LIB)
@@ -83,7 +88,7 @@ $(OBJ_DIR)/%.o: $(COMMON_DIR)/%.c
#Clean Obj files and builded stuff #Clean Obj files and builded stuff
clean: clean:
cd $(QT_DIR) && $(MAKE) clean && $(RM) Makefile && $(RM) *.a cd $(QT_DIR) && $(MAKE) clean && $(RM) Makefile* && $(RM) *.a && $(RMDIR) debug release
$(RMDIR) $(BUILD_DIR) $(OBJ_DIR) $(RMDIR) $(BUILD_DIR) $(OBJ_DIR)

View File

@@ -17,11 +17,13 @@ OBJ_DIR=./obj
#Architecture flags #Architecture flags
#Compiler, Linker Options #Compiler, Linker Options
CPPFLAGS=-I$(INC_DIR) -D__LINUX__=1 -DHOST=1 #-DDEBUG=1 CPPFLAGS=-I$(INC_DIR) -DHOST=1 #-D__LINUX__=1 -DDEBUG=1
CFLAGS=$(ARCH_FLAGS) -O0 -g #-ffunction-sections -fdata-sections -g CFLAGS=$(ARCH_FLAGS) -O0 -g #-ffunction-sections -fdata-sections -g
#CFLAGS += -mlittle-endian -mthumb -mcpu=cortex-m4 -mthumb-interwork #CFLAGS += -mlittle-endian -mthumb -mcpu=cortex-m4 -mthumb-interwork
#CFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16 #CFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16
CFLAGS+=-I/usr/include/libusb-1.0 CFLAGS+=-I/usr/include/libusb-1.0
CFLAGS+=-I../boost/include/
CFLAGS+=-I./windows/
#Finding Input files #Finding Input files
CFILES=$(shell find $(SRC_DIR) -name '*.cpp') CFILES=$(shell find $(SRC_DIR) -name '*.cpp')

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

2
emulator/libs/boost/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
include
lib

Binary file not shown.

View File

@@ -0,0 +1,2 @@
This directory is only needed on windows, and if you do not have boost installed.
Extract the rar file here, to get boost 1.58 header files and the libraries that we need for discoverpixy

View File

@@ -8,7 +8,7 @@ QT += widgets gui
TARGET = emulatorqt TARGET = emulatorqt
TEMPLATE = lib TEMPLATE = lib
CONFIG += staticlib CONFIG += staticlib debug
SOURCES += \ SOURCES += \
mainwindow.cpp \ mainwindow.cpp \
@@ -30,3 +30,6 @@ INCLUDEPATH+= ../../common/lowlevel/ \
FORMS += \ FORMS += \
mainwindow.ui mainwindow.ui
DESTDIR = $$_PRO_FILE_PWD_ #force windows to not create subfolders
#QMAKE_CXXFLAGS+= -v

View File

@@ -1,19 +1,5 @@
/**************************************************************************************************************************************
* 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" { extern "C" {
#include "ll_filesystem.h" #include "ll_filesystem.h"
} }
#include <QFile> #include <QFile>
#include <QDir> #include <QDir>
@@ -21,212 +7,175 @@ extern "C" {
#include <QFileInfoList> #include <QFileInfoList>
#include <QDateTime> #include <QDateTime>
QDir rootdir("./emulated"); //Create a QDir which points to the "root" of the emulated filesystem QDir rootdir ("./emulated");
bool ll_filesystem_init() bool ll_filesystem_init() {
{ if(!rootdir.exists()) {
if (!rootdir.exists()) { //if our root dir is nonexistent
qWarning() << "Filesystem can not be emulated because the 'emulated' folder does not exist"; qWarning() << "Filesystem can not be emulated because the 'emulated' folder does not exist";
return false; //mark an error return false;
} }
return true; return true;
} }
DIRECTORY_STRUCT* ll_filesystem_dir_open(const char* path) DIRECTORY_STRUCT* ll_filesystem_dir_open(const char* path) {
{ QDir d(rootdir);
QDir d(rootdir); //Make a copy of the rootdir QDir instance d.cd(path);
d.cd(path); //Change the directory to the passed path if(!d.exists()) {
return NULL;
if (!d.exists()) {
return NULL; //mark an error
} }
DIRECTORY_STRUCT* directory = new DIRECTORY_STRUCT(); 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->path = path;
directory->num_files = entries.count(); directory->num_files = entries.count();
directory->files = new FILE_STRUCT[directory->num_files]; //allocate array of file structs directory->files = new FILE_STRUCT[directory->num_files];
for (int i = 0; i < entries.count(); i++) { //foreach file that we found
for(int i=0; i<entries.count(); i++){
QFileInfo fi = entries.at(i); QFileInfo fi = entries.at(i);
FILE_STRUCT* entry = &(directory->files[i]); //get the pointer to the current filestruct (which should be filled) FILE_STRUCT* entry = &(directory->files[i]);
entry->fattrib = 0; entry->fattrib = 0;
entry->fname = new char[fi.fileName().length() + 1]; //reserve memory for filename entry->fname = new char[fi.fileName().length()+1];
strcpy(entry->fname, fi.fileName().toStdString().c_str()); //copy filename into struct strcpy(entry->fname,fi.fileName().toStdString().c_str());
if(fi.isDir()) {
if (fi.isDir()) { //it's a direcory entry->fattrib|=F_DIR;
entry->fattrib |= F_DIR; //set directory attribute
entry->fsize = 0; entry->fsize = 0;
} else { //it's a file } else {
entry->fsize = fi.size(); //set filesize entry->fsize = fi.size();
}
if(fi.isHidden()) {
entry->fattrib|=F_HID;
}
if(!fi.isWritable()) {
entry->fattrib|=F_RDO;
} }
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
}
//Set date & time of file in structure
QDateTime dt = fi.lastModified(); QDateTime dt = fi.lastModified();
entry->fdate.year = dt.date().year() - 1980; //year is realtive to 1980 entry->fdate.year = dt.date().year()-1980;
entry->fdate.month = dt.date().month(); entry->fdate.month = dt.date().month();
entry->fdate.day = dt.date().day(); entry->fdate.day = dt.date().day();
entry->ftime.hour = dt.time().hour(); entry->ftime.hour = dt.time().hour();
entry->ftime.min = dt.time().minute(); 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 return directory;
} }
void ll_filesystem_dir_close(DIRECTORY_STRUCT* dir) void ll_filesystem_dir_close(DIRECTORY_STRUCT* dir) {
{ if(dir!=NULL) {
if (dir != NULL) { //passed handle is valid for(int i=0; i<dir->num_files; i++) {
for (int i = 0; i < dir->num_files; i++) { //foreach file delete dir->files[i].fname;
delete dir->files[i].fname; //delete filename buffer
} }
delete[] dir->files;
delete[] dir->files; //delete file array delete dir;
delete dir; //delete structure itself
} }
} }
//Struct that represents a file handle for the emulator
struct QT_FILE_HANDLE : FILE_HANDLE { //..derived from the FILE_HANDLE (of the Filesystem modul) struct QT_FILE_HANDLE : FILE_HANDLE {
QFile* file; //Pointer to the open QFile* instance QFile* file;
}; };
FILE_HANDLE* ll_filesystem_file_open(const char* filename) FILE_HANDLE* ll_filesystem_file_open(const char* filename) {
{ if(!rootdir.exists()) {
if (!rootdir.exists()) { return NULL;
}
QString filepath = rootdir.absoluteFilePath(filename);
QFile* f = new QFile(filepath);
if(!f->exists()) {
return NULL; return NULL;
} }
QString filepath = rootdir.absoluteFilePath(filename); //get the absolute path to the requested file if(!f->open(QFile::ReadWrite)) {
QFile* f = new QFile(filepath); //create a QFile instance to the requested file return NULL;
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 ... QT_FILE_HANDLE* fh = new QT_FILE_HANDLE();
return NULL; //... mark error
}
//At this point we have a valid QFile instance, pointing to an existing file
QT_FILE_HANDLE* fh = new QT_FILE_HANDLE(); //Create Structure to return to user
fh->file = f; fh->file = f;
fh->fname = filename; fh->fname = filename;
fh->fpos = 0; fh->fpos =0;
fh->fsize = f->size(); fh->fsize = f->size();
return fh; return fh;
} }
void ll_filesystem_file_close(FILE_HANDLE* handle) void ll_filesystem_file_close(FILE_HANDLE* handle) {
{ if(handle!=NULL) {
if (handle != NULL) { //passed handle is valid QT_FILE_HANDLE* fh = static_cast<QT_FILE_HANDLE*>(handle);
QT_FILE_HANDLE* fh = static_cast<QT_FILE_HANDLE*>(handle); //cast pointer to QT_FILE_HANDLE if(fh->file->isOpen()) {
fh->file->close();
if (fh->file->isOpen()) { //if the file is still open
fh->file->close(); //close the file
} }
delete fh;
delete fh->file; //delete QFile instance
delete fh; //delete the fle
} }
} }
FILE_STATUS ll_filesystem_file_seek(FILE_HANDLE* handle, uint32_t offset) FILE_STATUS ll_filesystem_file_seek(FILE_HANDLE* handle, uint32_t offset) {
{ if(handle==NULL) {
if (handle == NULL) {
return F_INVALIDPARAM; return F_INVALIDPARAM;
} }
QT_FILE_HANDLE* fh = static_cast<QT_FILE_HANDLE*>(handle);
QT_FILE_HANDLE* fh = static_cast<QT_FILE_HANDLE*>(handle); //cast pointer to QT_FILE_HANDLE if(!fh->file->isOpen()) {
if (!fh->file->isOpen()) { //file is not open
return F_DISKERROR; return F_DISKERROR;
} }
if(offset>=fh->file->size()) {
if (offset >= fh->file->size()) { //offset exeeds filesize
return F_INVALIDPARAM; return F_INVALIDPARAM;
} }
if (fh->file->seek(offset)) { //try to seek to desired offset if(fh->file->seek(offset)) {
fh->fpos = offset; //update offset in FILE_HANDLE (for user) fh->fpos = offset;
return F_OK; return F_OK;
} else { //seek failed } else {
return F_DISKERROR; return F_DISKERROR;
} }
} }
FILE_STATUS ll_filesystem_file_read(FILE_HANDLE* handle, uint8_t* buf, uint32_t size) FILE_STATUS ll_filesystem_file_read(FILE_HANDLE* handle, uint8_t* buf, uint32_t size) {
{ if(handle==NULL || buf==NULL) {
if (handle == NULL || buf == NULL) {
return F_INVALIDPARAM; return F_INVALIDPARAM;
} }
QT_FILE_HANDLE* fh = static_cast<QT_FILE_HANDLE*>(handle);
QT_FILE_HANDLE* fh = static_cast<QT_FILE_HANDLE*>(handle); //cast pointer to QT_FILE_HANDLE if(!fh->file->isOpen()) {
if (!fh->file->isOpen()) { //file is not open
return F_DISKERROR; return F_DISKERROR;
} }
if(!fh->file->isReadable()) {
if (!fh->file->isReadable()) { //file is not readable
return F_EACCESS; return F_EACCESS;
} }
qint64 bytesRead = fh->file->read((char*)buf,size);
qint64 bytesRead = fh->file->read((char*)buf, size); //try to read desired amount of bytes if(bytesRead<0) {
if (bytesRead < 0) { //read failed
return F_DISKERROR; return F_DISKERROR;
} }
fh->fpos+=bytesRead;
fh->fpos += bytesRead; //increase file position (for user) if(bytesRead!=size) {
return F_EOF;
if (bytesRead != size) { //we got less bytes than expected
return F_EOF; //we reached the end of the file
} else { } else {
return F_OK; return F_OK;
} }
} }
FILE_STATUS ll_filesystem_file_write(FILE_HANDLE* handle, uint8_t* buf, uint32_t size) FILE_STATUS ll_filesystem_file_write(FILE_HANDLE* handle, uint8_t* buf, uint32_t size) {
{ if(handle==NULL) {
if (handle == NULL) {
return F_INVALIDPARAM; return F_INVALIDPARAM;
} }
QT_FILE_HANDLE* fh = static_cast<QT_FILE_HANDLE*>(handle);
QT_FILE_HANDLE* fh = static_cast<QT_FILE_HANDLE*>(handle); //cast pointer to QT_FILE_HANDLE if(!fh->file->isOpen()) {
if (!fh->file->isOpen()) { //file is not open
return F_DISKERROR; return F_DISKERROR;
} }
if(!fh->file->isWritable()) {
if (!fh->file->isWritable()) { //file is not writable
return F_EACCESS; return F_EACCESS;
} }
qint64 bytesWritten = fh->file->write((char*)buf,size);
qint64 bytesWritten = fh->file->write((char*)buf, size); //try to write desired amount of bytes if(bytesWritten<0) {
if (bytesWritten < 0) { //write failed
return F_DISKERROR; return F_DISKERROR;
} }
fh->fpos+=bytesWritten;
fh->fpos += bytesWritten; //increase file position (for user) if(bytesWritten!=size) {
return F_EOF;
if (bytesWritten != size) { //we wrote less bytes than expected
return F_EOF; //we reached the end of the file
} else { } else {
return F_OK; return F_OK;
} }
} }

View File

@@ -1,21 +1,3 @@
/**************************************************************************************************************************************
* 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 <QThread> #include <QThread>
#include <QApplication> #include <QApplication>
@@ -23,23 +5,19 @@ extern "C" {
#include "ll_system.h" #include "ll_system.h"
} }
bool ll_system_init() bool ll_system_init() {
{ return true;
return true; //nothing to initialize here, apart from the stuff which is done in the main method.
} }
void ll_system_delay(uint32_t msec) void ll_system_delay(uint32_t msec) {
{ QThread::msleep(msec);
QThread::msleep(msec); //Let the app_process() Thread sleep
} }
void ll_system_process() void ll_system_process() {
{ QApplication::processEvents();
QApplication::processEvents(); //Process pending qt events QThread::msleep(1);
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 :(
} }

View File

@@ -1,23 +1,5 @@
/**************************************************************************************************************************************
* 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" #include "mainwindow.h"
#include <QDebug>
extern "C" { extern "C" {
#include "ll_tft.h" #include "ll_tft.h"
@@ -25,104 +7,75 @@ extern "C" {
MainWindow* mainwindow; MainWindow* mainwindow;
bool ll_tft_init() bool ll_tft_init() {
{ qDebug() << "tft init done";
mainwindow = new MainWindow(); //create the designed window mainwindow = new MainWindow();
mainwindow->show(); //open it (non blocking) mainwindow->show();
return true; 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); mainwindow->clear(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) {
{ mainwindow->draw_pixel(x,y,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) 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);
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) 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);
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) 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);
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) void ll_tft_draw_circle(uint16_t x, uint16_t y, uint16_t r, uint16_t color) {
{ mainwindow->draw_circle(x,y,r,color);
mainwindow->draw_circle(x, y, r, color);
} }
uint8_t ll_tft_num_fonts() uint8_t ll_tft_num_fonts() {
{ return 2;
return 2; //we have two fonts (see below)
} }
//Helper function to get the QFont to the corresponding font number QFont get_font(uint8_t fontnum) {
//Note: only return monospaced fonts!!! switch(fontnum) {
QFont get_font(uint8_t fontnum) case 0:
{ return QFont("Courier New",8);
switch (fontnum) { case 1:
case 0: return QFont("Courier New",14);
return QFont("Monospace", 8); default:
case 1:
return QFont("DejaVu Sans Mono", 14);
default:
return QFont(); return QFont();
} }
} }
uint8_t ll_tft_font_height(uint8_t fontnum) uint8_t ll_tft_font_height(uint8_t fontnum) {
{
QFont f = get_font(fontnum); QFont f = get_font(fontnum);
if(f == QFont()) return -1;
if (f == QFont()) { QFontMetrics m(f);
return -1;
}
QFontMetrics m(f); //use font metcris object to calculate height of font
return m.height(); 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); QFont f = get_font(fontnum);
if(f == QFont()) return -1;
if (f == QFont()) { QFontMetrics m(f);
return -1;
}
QFontMetrics m(f); //use font metcris object to calculate width of font
return m.averageCharWidth(); 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); QFont f = get_font(font);
if(f == QFont()) return;
if (f == QFont()) { mainwindow->draw_char(x,y,color,bgcolor,f,c);
return; //if the font is the default-font, we want to abort.
}
mainwindow->draw_char(x, y, color, bgcolor, f, c);
} }

View File

@@ -1,25 +1,10 @@
/**************************************************************************************************************************************
* 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" { extern "C" {
#include "ll_touch.h" #include "ll_touch.h"
#include "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 touch_set_value_convert_mode(false); //tell the touch module that we don't need calibration or value conversion
return true; return true;
} }

View File

@@ -1,42 +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/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 <QApplication> #include <QApplication>
#include <QtConcurrent/QtConcurrent> #include <QtConcurrent/QtConcurrent>
extern "C" { extern "C" {
//Imported C Functions from the common folder //C Functions from the common folder
void app_init(); //Initializes the app void app_init(); //Initializes the app
void app_process(); //Processes one eventloop of the app void app_process(); //Processes one eventloop of the app
} }
void app_loop() void app_loop() {
{ while(!QApplication::closingDown()) {
while (!QApplication::closingDown()) { //as long as the application is not terminating app_process();
app_process(); //let the application process it's events
} }
} }
int main(int argc, char* argv[]) int main(int argc, char* argv[]) {
{ QApplication app(argc,argv);
QApplication app(argc, argv); //Process qt-specific commandline arguments and create event loop app_init();
app_init(); //Let the application initialize it self
QtConcurrent::run(&app_loop); //Start a thread that executes app_loop QtConcurrent::run(&app_loop);
return app.exec(); //Run the event loop until the last window is closed. return app.exec();
} }

View File

@@ -1,29 +1,3 @@
/**************************************************************************************************************************************
* 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 "mainwindow.h"
#include "ui_mainwindow.h" #include "ui_mainwindow.h"
#include <QDebug> #include <QDebug>
@@ -32,173 +6,183 @@
#include <QMouseEvent> #include <QMouseEvent>
extern "C" { extern "C" {
#include "touch.h" #include "touch.h"
#include "tft.h" #include "tft.h"
} }
#define DISPLAY_WIDTH 320 #define DISPLAY_WIDTH 320
#define DISPLAY_HEIGHT 240 #define DISPLAY_HEIGHT 240
//function to calculate QColor out of a RGB565 16bit color QColor QColorFromRGB565(uint16_t color) {
QColor QColorFromRGB565(uint16_t color)
{ int R8 = (int) floor( (color>>(5+6)) * 255.0 / 31.0 + 0.5);
//interpolate colors int G8 = (int) floor( ((color>>5)&0x3F) * 255.0 / 63.0 + 0.5);
int R8 = (int) floor((color >> (5 + 6)) * 255.0 / 31.0 + 0.5); int B8 = (int) floor( (color&0x1F) * 255.0 / 31.0 + 0.5);
int G8 = (int) floor(((color >> 5) & 0x3F) * 255.0 / 63.0 + 0.5); return QColor::fromRgb(R8,G8,B8);
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)
{ int R8 = (int) floor( (color>>(5+6)) * 255.0 / 31.0 + 0.5);
//interpolate colors int G8 = (int) floor( ((color>>5)&0x3F) * 255.0 / 63.0 + 0.5);
int R8 = (int) floor((color >> (5 + 6)) * 255.0 / 31.0 + 0.5); int B8 = (int) floor( (color&0x1F) * 255.0 / 31.0 + 0.5);
int G8 = (int) floor(((color >> 5) & 0x3F) * 255.0 / 63.0 + 0.5); return qRgb(R8,G8,B8);
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); ui->setupUi(this);
image.fill(Qt::black); //clear display buffer image.fill(Qt::black);
currentScale = 1; //start with scale factor 1 currentScale = 1;
ui->widgetDisplay->setMouseTracking(true); //enable mouse move events, even when mouse is not pressed ui->widgetDisplay->setMouseTracking(true);
ui->widgetDisplay->installEventFilter(this); //install event filter for "display" widget, so that we receive those events as well ui->widgetDisplay->installEventFilter(this);
} }
void MainWindow::draw_line(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color) void MainWindow::draw_line(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color)
{ {
//render_mutex.lock();
QPainter painter(&(image)); QPainter painter(&(image));
painter.setPen(QColorFromRGB565(color)); painter.setPen(QColorFromRGB565(color));
painter.drawLine(x1, y1, x2, y2); painter.drawLine(x1,y1,x2,y2);
//render_mutex.unlock();
update(); update();
} }
void MainWindow::draw_pixel(uint16_t x, uint16_t y, uint16_t color) void MainWindow::draw_pixel(uint16_t x, uint16_t y, uint16_t color)
{ {
image.setPixel(x, y, QRgbFromRGB565(color)); //render_mutex.lock();
image.setPixel(x,y,QRgbFromRGB565(color));
//render_mutex.unlock();
update(); update();
} }
void MainWindow::clear(uint16_t color) void MainWindow::clear(uint16_t color)
{ {
//render_mutex.lock();
image.fill(QColorFromRGB565(color)); image.fill(QColorFromRGB565(color));
//render_mutex.unlock();
update(); update();
} }
void MainWindow::draw_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color) void MainWindow::draw_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color)
{ {
//render_mutex.lock();
QPainter painter(&(image)); QPainter painter(&(image));
painter.setPen(QColorFromRGB565(color)); 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)+1,abs((int)y2-(int)y1)+1);
//render_mutex.unlock();
update(); update();
} }
void MainWindow::fill_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color) void MainWindow::fill_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color)
{ {
//render_mutex.lock();
QPainter painter(&(image)); 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));
//render_mutex.unlock();
update(); 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 //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);
for (int yi = 0; yi < height; yi++) { //for each line for(int yi=0; yi<height; yi++) {
uint32_t* line = (uint32_t*)img.scanLine(yi); //get the pointer to the imagedata of the current line uint32_t* line = (uint32_t*)img.scanLine(yi);
for(int xi=0; xi<width; xi++) {
for (int xi = 0; xi < width; xi++) { //for each column *line++=QRgbFromRGB565(dat[yi*width+xi]);
*line++ = QRgbFromRGB565(dat[yi * width + xi]); //set pixel
} }
} }
//render_mutex.lock();
QPainter p(&image); QPainter p(&image);
p.drawImage(x, y, img); //draw created image p.drawImage(x,y,img);
//render_mutex.unlock();
update(); update();
} }
void MainWindow::draw_circle(uint16_t x, uint16_t y, uint16_t r, uint16_t color) void MainWindow::draw_circle(uint16_t x, uint16_t y, uint16_t r, uint16_t color)
{ {
//render_mutex.lock();
QPainter painter(&(image)); QPainter painter(&(image));
painter.setPen(QColorFromRGB565(color)); painter.setPen(QColorFromRGB565(color));
painter.drawEllipse(QPoint(x, y), r, r); painter.drawEllipse(QPoint(x,y), r, r);
//render_mutex.unlock();
update(); update();
} }
void MainWindow::draw_char(uint16_t x, uint16_t y, uint16_t color, uint16_t bgcolor, QFont font, char c) void MainWindow::draw_char(uint16_t x, uint16_t y, uint16_t color, uint16_t bgcolor, QFont font, char c)
{ {
//render_mutex.lock();
QPainter painter(&(image)); QPainter painter(&(image));
painter.setFont(font); painter.setFont(font);
if (bgcolor != TRANSPARENT) { //background color is not transparent if(bgcolor!=TRANSPARENT) {
painter.setBackgroundMode(Qt::OpaqueMode); painter.setBackgroundMode(Qt::OpaqueMode);
painter.setBackground(QColorFromRGB565(bgcolor)); //set text background painter.setBackground(QColorFromRGB565(bgcolor));
} }
painter.setPen(QColorFromRGB565(color)); //set fontcolor painter.setPen(QColorFromRGB565(color));
y += QFontMetrics(font).ascent(); //use y pos as highest point of char, instead of baseline y+=QFontMetrics(font).ascent(); //use y pos as highest point of char, instead of baseline
painter.drawText(QPoint(x, y), QString(QChar(c))); //draw char painter.drawText(QPoint(x,y), QString(QChar(c)));
//render_mutex.unlock();
update(); update();
} }
void MainWindow::paintEvent(QPaintEvent*) void MainWindow::paintEvent(QPaintEvent *)
{ {
//this method is called whenever the window needs to be redrawn (or after update() is called) //render_mutex.lock();
QPainter painter(this); QPainter painter(this);
//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));
QRectF imgRect(ui->widgetDisplay->geometry().topLeft(), QSizeF(DISPLAY_WIDTH * currentScale, DISPLAY_HEIGHT * currentScale));
painter.drawImage(imgRect, image); //draw buffer painter.drawImage(imgRect,image);
painter.setPen(QPen(Qt::green, 2)); //set border color painter.setPen(QPen(Qt::green,2));
painter.drawRect(imgRect.adjusted(-1, -1, 1, 1)); //draw border painter.drawRect(imgRect.adjusted(-1,-1,1,1));
//render_mutex.unlock();
} }
void MainWindow::mousePressEvent(QMouseEvent* evt) void MainWindow::mousePressEvent(QMouseEvent *evt)
{ {
//the mouse was pressed //qDebug() << "down" << evt->pos();
checkAndSendEvent(evt->pos(), true); checkAndSendEvent(evt->pos(),true);
} }
void MainWindow::mouseReleaseEvent(QMouseEvent* evt) void MainWindow::mouseReleaseEvent(QMouseEvent *evt)
{ {
//the mouse was released //qDebug() << "up" << evt->pos();
checkAndSendEvent(evt->pos(), false); checkAndSendEvent(evt->pos(),false);
} }
void MainWindow::mouseMoveEvent(QMouseEvent* evt) void MainWindow::mouseMoveEvent(QMouseEvent *evt)
{ {
//the mouse was released //qDebug() << "move" << evt->pos();
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 if(obj==ui->widgetDisplay) {
switch (evt->type()) { switch(evt->type()) {
case QEvent::MouseMove: { //it's a mouse move event case QEvent::MouseMove:
QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(evt); //get mouse event {
QPoint p = (mouseEvent->pos() - QPoint(1, 1)) / currentScale; //calculate correct corrdinates (undo scale) QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(evt);
QPoint p = (mouseEvent->pos()-QPoint(1,1))/currentScale;
if (p.x() < DISPLAY_WIDTH && p.y() < DISPLAY_HEIGHT) { //mouse position not out of bounds if(p.x()<DISPLAY_WIDTH && p.y()<DISPLAY_HEIGHT) {
//set mouse position text ui->txtMousePos->setText(QString("Mouse Position: (%1,%2)").arg(p.x()).arg(p.y()));
ui->txtMousePos->setText(QString("Mouse Position: (%1,%2)").arg(p.x()).arg(p.y())); }
} }
}
break;
default:
break; break;
}
}
return false; default: break;
}
}
return false;
} }
@@ -209,19 +193,18 @@ MainWindow::~MainWindow()
void MainWindow::checkAndSendEvent(QPoint pos, bool down) void MainWindow::checkAndSendEvent(QPoint pos, bool down)
{ {
QPoint p = pos - ui->widgetDisplay->geometry().topLeft(); //make coordinate relative to target area (0,0) QPoint p = pos - ui->widgetDisplay->geometry().topLeft();
p /= currentScale; //undo scaling p/=currentScale;
if(p.x()<0 || p.y()<0 || p.x() >= DISPLAY_WIDTH || p.y() >= DISPLAY_HEIGHT) return;
if (p.x() < 0 || p.y() < 0 || p.x() >= DISPLAY_WIDTH || p.y() >= DISPLAY_HEIGHT) { //qDebug() << down << p;
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) touch_add_raw_event(p.x(),p.y(),down?TOUCH_DOWN:TOUCH_UP);
} }
void MainWindow::on_cboZoom_currentIndexChanged(int index) 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;
update(); //force redraw update();
} }

View File

@@ -1,24 +1,3 @@
/**************************************************************************************************************************************
* 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 #ifndef MAINWINDOW_H
#define MAINWINDOW_H #define MAINWINDOW_H
@@ -26,8 +5,7 @@
#include <QMutex> #include <QMutex>
#include <stdint.h> #include <stdint.h>
namespace Ui namespace Ui {
{
class MainWindow; class MainWindow;
} }
@@ -36,33 +14,34 @@ class MainWindow : public QMainWindow
Q_OBJECT Q_OBJECT
public: 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_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 clear(uint16_t color);
void draw_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, 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 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_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); void draw_char(uint16_t x, uint16_t y, uint16_t color, uint16_t bgcolor, QFont font, char c);
protected: protected:
bool eventFilter(QObject* obj , QEvent* env); bool eventFilter(QObject * obj , QEvent * env);
void paintEvent(QPaintEvent* evt); void paintEvent(QPaintEvent * evt);
void mousePressEvent(QMouseEvent* evt); void mousePressEvent(QMouseEvent* evt);
void mouseReleaseEvent(QMouseEvent* evt); void mouseReleaseEvent(QMouseEvent* evt);
void mouseMoveEvent(QMouseEvent* evt); void mouseMoveEvent(QMouseEvent* evt);
~MainWindow(); ~MainWindow();
private slots: private slots:
void on_cboZoom_currentIndexChanged(int index); //slot that is called when the zoomlevel changed void on_cboZoom_currentIndexChanged(int index);
private: private:
QImage image; //Display buffer //QMutex render_mutex;
int currentScale; //current scale factor QImage image;
int currentScale;
void checkAndSendEvent(QPoint pos, bool down); void checkAndSendEvent(QPoint pos, bool down);
Ui::MainWindow* ui; Ui::MainWindow *ui;
}; };
#endif // MAINWINDOW_H #endif // MAINWINDOW_H

View File

@@ -0,0 +1,26 @@
Prerequisites:
- Qt5 for Windows (provides C:\Qt\5.4\mingw491_32 and C:\Qt\Tools\mingw491_32)
- Mingw msys-base (provides C:\MinGW\msys\1.0 and make, find )
- Boost (check emulator\libs\boost)
Steps:
- Open up the msys shell using the batchfile
- Navigate to the emulator folder of the project
- Source the qt binaries (qmake, gcc, g++) by executing
export PATH=$PATH:/c/Qt/Tools/mingw491_32/bin:/c/Qt/5.4/mingw491_32/bin
- navigate to libs/Pixy and execute make
- navigate back into the emulator folder and execute make
- this should generate you build/emulator.exe
Starting:
- Extract windows_dlls.rar to the build folder
- Copy the emulated folder into the build folder
- Make sure that you installed the pixy usb driver (e.g. by installing pixymon http://cmucam.org/projects/cmucam5/wiki/Latest_release)
- Start emulator.exe
Pitfalls:
- libstdc++ must be provided by qt. do not use one of msys or mingw. you will waste hours with debugging of the make process
Sources:
- libusb for windows was taken from https://github.com/charmedlabs/pixy/tree/master/src/host/windows
- Boost was compiled from sources, using http://andres.jaimes.net/718/how-to-install-the-c-boost-libraries-on-windows/ and http://www.boost.org/doc/libs/1_58_0/more/getting_started/windows.html

View File

@@ -1,33 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.cdt.launch.applicationLaunchType">
<booleanAttribute key="org.eclipse.cdt.dsf.gdb.AUTO_SOLIB" value="true"/>
<listAttribute key="org.eclipse.cdt.dsf.gdb.AUTO_SOLIB_LIST"/>
<stringAttribute key="org.eclipse.cdt.dsf.gdb.DEBUG_NAME" value="gdb"/>
<booleanAttribute key="org.eclipse.cdt.dsf.gdb.DEBUG_ON_FORK" value="false"/>
<stringAttribute key="org.eclipse.cdt.dsf.gdb.GDB_INIT" value=".gdbinit"/>
<booleanAttribute key="org.eclipse.cdt.dsf.gdb.NON_STOP" value="false"/>
<booleanAttribute key="org.eclipse.cdt.dsf.gdb.REVERSE" value="false"/>
<listAttribute key="org.eclipse.cdt.dsf.gdb.SOLIB_PATH"/>
<stringAttribute key="org.eclipse.cdt.dsf.gdb.TRACEPOINT_MODE" value="TP_NORMAL_ONLY"/>
<booleanAttribute key="org.eclipse.cdt.dsf.gdb.UPDATE_THREADLIST_ON_SUSPEND" value="false"/>
<booleanAttribute key="org.eclipse.cdt.dsf.gdb.internal.ui.launching.LocalApplicationCDebuggerTab.DEFAULTS_SET" value="true"/>
<intAttribute key="org.eclipse.cdt.launch.ATTR_BUILD_BEFORE_LAUNCH_ATTR" value="2"/>
<stringAttribute key="org.eclipse.cdt.launch.COREFILE_PATH" value=""/>
<stringAttribute key="org.eclipse.cdt.launch.DEBUGGER_ID" value="gdb"/>
<stringAttribute key="org.eclipse.cdt.launch.DEBUGGER_START_MODE" value="run"/>
<booleanAttribute key="org.eclipse.cdt.launch.DEBUGGER_STOP_AT_MAIN" value="true"/>
<stringAttribute key="org.eclipse.cdt.launch.DEBUGGER_STOP_AT_MAIN_SYMBOL" value="main"/>
<stringAttribute key="org.eclipse.cdt.launch.PROGRAM_NAME" value="build/emulator"/>
<stringAttribute key="org.eclipse.cdt.launch.PROJECT_ATTR" value="discoverpixy emulator"/>
<booleanAttribute key="org.eclipse.cdt.launch.PROJECT_BUILD_CONFIG_AUTO_ATTR" value="true"/>
<stringAttribute key="org.eclipse.cdt.launch.PROJECT_BUILD_CONFIG_ID_ATTR" value="cdt.managedbuild.toolchain.gnu.base.1806077868"/>
<booleanAttribute key="org.eclipse.cdt.launch.use_terminal" value="true"/>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
<listEntry value="/discoverpixy emulator"/>
</listAttribute>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
<listEntry value="4"/>
</listAttribute>
<stringAttribute key="org.eclipse.dsf.launch.MEMORY_BLOCKS" value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;memoryBlockExpressionList context=&quot;reserved-for-future-use&quot;/&gt;&#10;"/>
<stringAttribute key="process_factory_id" value="org.eclipse.cdt.dsf.gdb.GdbProcessFactory"/>
</launchConfiguration>

BIN
emulator/windows_dlls.rar Normal file

Binary file not shown.

View File

@@ -2,13 +2,12 @@
echo "/**************************************************************************************************************************************" echo "/**************************************************************************************************************************************"
echo "* Project: discoverpixy" echo "* Project: discoverpixy"
echo "* Website: https://github.com/t-moe/discoverpixy"
echo "* Authors: Aaron Schmocker, Timo Lang" echo "* Authors: Aaron Schmocker, Timo Lang"
echo "* Institution: BFH Bern University of Applied Sciences" echo "* Institution: BFH Bern University of Applied Sciences"
echo "* File: $1" echo "* File: $1"
echo "*" echo "*"
echo "* Version History:" echo "* Version History:"
echo "* Date Autor Email SHA Changes" echo "* Date Autor Email SHA Changes"
git log --pretty=format:"* %ad%x09%ae%x09%h%x09%s" --date=short --date-order --no-merges --reverse $1 | grep -v -i "fileheader" git log --pretty=format:"* %ad%x09%ae%x09%h%x09%s" --date=short --date-order --no-merges --reverse $1 | grep -v -i "fileheader"

Some files were not shown because too many files have changed in this diff Show More