Updated fileheaders and styled files using astyle.

This commit is contained in:
t-moe
2015-06-08 11:00:52 +02:00
parent 7e61a129a3
commit fceb2d15b2
63 changed files with 6045 additions and 4691 deletions

View File

@@ -1,3 +1,32 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/app/app.c
*
* Version History:
* Date Autor Email SHA Changes
* 2015-04-03 timolang@gmail.com 51089aa Refactored Project Structure for use with emulator
* 2015-04-03 timolang@gmail.com 1f2af9f Added more tft functions to common and emulator. Fixed eventloop.
* 2015-04-03 timolang@gmail.com cab8609 Integrated pixy into emulator. Pixy is no longer in the common/libs folder but in emulator/libs and discovery/libs
* 2015-04-03 timolang@gmail.com 1aa9194 Fixed Drawing of rects in Emulator. Got frames from pixy to emulator. Slooooow.
* 2015-04-25 timolang@gmail.com 416883c Pixy&Usb work with the new folder structure now.
* 2015-04-25 timolang@gmail.com 3d1e4b2 Simplified code a bit. Emulator does not work stable when replugging pixy.
* 2015-04-25 timolang@gmail.com 0858b0d Fixed some bugs when receiving large data.
* 2015-04-27 timolang@gmail.com 259d446 Added touch support to emulator. Implemented basic touch function.
* 2015-04-27 aaron@duckpond.ch aed90ef Drawcircle added (emulator)
* 2015-04-27 timolang@gmail.com e249fb2 Added font support
* 2015-04-27 timolang@gmail.com 7c9eabc Added button support.
* 2015-04-27 timolang@gmail.com b300ac5 Added Checkbox support
* 2015-04-27 timolang@gmail.com cf72baa Introduced a Screen (sub) module and divided app into multiple screens.
* 2015-05-10 timolang@gmail.com e2bce8f Added filesystem module, tests and implementation for it in emulator.
* 2015-05-12 aaron@duckpond.ch aec62d4 Added datasheets, updated touchsupport.
* 2015-05-28 aaron@duckpond.ch 5bda699 implemented functions to get x and y coordinates and a test function
* 2015-05-29 aaron@duckpond.ch 7d2d1a1 Implemented basic sampling and averaging of touch coordinates using timer7
*
**************************************************************************************************************************************/
#include "app.h"
#include "tft.h"
#include "system.h"
@@ -5,20 +34,20 @@
#include "screen_main.h"
#include "filesystem.h"
void app_init() {
system_init();
tft_init();
touch_init();
filesystem_init();
void app_init()
{
system_init();
tft_init();
touch_init();
filesystem_init();
gui_screen_navigate(get_screen_main());
gui_screen_navigate(get_screen_main());
}
//app event loop
void app_process() {
system_process(); //Let the system handle it's pending events
gui_screen_update(); //update the currently active screen
void app_process()
{
system_process(); //Let the system handle it's pending events
gui_screen_update(); //update the currently active screen
}

View File

@@ -1,10 +1,26 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/app/app.h
*
* Version History:
* Date Autor Email SHA Changes
* 2015-04-03 timolang@gmail.com 51089aa Refactored Project Structure for use with emulator
* 2015-05-10 timolang@gmail.com 21edc56 Added doxyfile (doxygen) for the common folder. Started with doxygen comments for app and tft module.
* 2015-05-11 timolang@gmail.com 08d9fe0 More work on doxygen module structure
* 2015-06-08 timolang@gmail.com 73db8b5 Added doxygen mainpage comment in app.h
*
**************************************************************************************************************************************/
#ifndef APP_H
#define APP_H
/*!
/*!
\mainpage discoverpixy Doxygen Documentation
Welcome to the code-documentation for all common (and plattformindependent) code. \n
A good point to start is probably the <a href="modules.html">Modules</a> page.
A good point to start is probably the <a href="modules.html">Modules</a> page.
*/
/**

View File

@@ -1,3 +1,21 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/app/pixy_control.c
*
* Version History:
* Date Autor Email SHA Changes
* 2015-06-02 aaron@duckpond.ch e018a75 Implemented basic pi and pid controller
* 2015-06-06 aaron@duckpond.ch 8c264c2 Comment refactoring, updated PID values
* 2015-06-06 aaron@duckpond.ch a04cda9 Refactured comments and implemented a bugfix for the PID controller
* 2015-06-07 aaron@duckpond.ch 802d3df Fixed pid controller and refactored code
* 2015-06-07 aaron@duckpond.ch 3d98ca9 Minor changes
* 2015-06-07 timolang@gmail.com c87220d Renamed pixy_helper to pixy_frame. Updated docu of appliaction. added doxygen comments to pixy_{frame,control}.h
*
**************************************************************************************************************************************/
/*
* pixy_control.c
*

View File

@@ -1,3 +1,20 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/app/pixy_control.h
*
* Version History:
* Date Autor Email SHA Changes
* 2015-06-02 aaron@duckpond.ch e018a75 Implemented basic pi and pid controller
* 2015-06-06 aaron@duckpond.ch 8c264c2 Comment refactoring, updated PID values
* 2015-06-06 aaron@duckpond.ch a04cda9 Refactured comments and implemented a bugfix for the PID controller
* 2015-06-07 aaron@duckpond.ch 802d3df Fixed pid controller and refactored code
* 2015-06-07 timolang@gmail.com c87220d Renamed pixy_helper to pixy_frame. Updated docu of appliaction. added doxygen comments to pixy_{frame,control}.h
*
**************************************************************************************************************************************/
#ifndef PIXY_CONTROL_H_
#define PIXY_CONTROL_H_

View File

@@ -1,3 +1,16 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/app/pixy_frame.c
*
* Version History:
* Date Autor Email SHA Changes
* 2015-06-07 timolang@gmail.com c87220d Renamed pixy_helper to pixy_frame. Updated docu of appliaction. added doxygen comments to pixy_{frame,control}.h
*
**************************************************************************************************************************************/
#include "pixy_frame.h"
#include "pixy.h"
#include "tft.h"
@@ -5,118 +18,113 @@
static int renderBA81(uint16_t xpos, uint16_t ypos, uint16_t width, uint16_t height, uint32_t frameLen, uint8_t *frame);
static int saveBA81(FILE_HANDLE* handle, uint16_t width, uint16_t height, uint32_t frameLen, uint8_t *frame);
static int renderBA81(uint16_t xpos, uint16_t ypos, uint16_t width, uint16_t height, uint32_t frameLen, uint8_t* frame);
static int saveBA81(FILE_HANDLE* handle, uint16_t width, uint16_t height, uint32_t frameLen, uint8_t* frame);
int pixy_render_full_frame(uint16_t x, uint16_t y) {
return pixy_render_cropped_frame(x,y,0,0,320,200);
}
int pixy_render_cropped_frame(uint16_t x, uint16_t y, uint16_t xoffset, uint16_t yoffset, uint16_t width, uint16_t height) {
uint8_t* videodata;
int32_t response;
int32_t fourccc;
int8_t renderflags;
uint16_t xwidth;
uint16_t ywidth;
uint32_t size;
int return_value = pixy_command("cam_getFrame", // String id for remote procedure
INT8(0x21), // mode
INT16(xoffset), // xoffset
INT16(yoffset), // yoffset
INT16(width), // width
INT16(height), // height
END_OUT_ARGS, // separator
&response, // pointer to mem address for return value
&fourccc,
&renderflags,
&xwidth,
&ywidth,
&size,
&videodata, // pointer to mem address for returned frame
END_IN_ARGS);
if(return_value==0) {
return_value = renderBA81(x,y,xwidth,ywidth,size,videodata);
}
return return_value;
}
int pixy_save_full_frame(FILE_HANDLE* handle) {
return pixy_save_cropped_frame(handle,0,0,320,200);
}
int pixy_save_cropped_frame(FILE_HANDLE* handle, uint16_t xoffset, uint16_t yoffset, uint16_t width, uint16_t height) {
uint8_t* videodata;
int32_t response;
int32_t fourccc;
int8_t renderflags;
uint16_t xwidth;
uint16_t ywidth;
uint32_t size;
int return_value = pixy_command("cam_getFrame", // String id for remote procedure
INT8(0x21), // mode
INT16(xoffset), // xoffset
INT16(yoffset), // yoffset
INT16(width), // width
INT16(height), // height
END_OUT_ARGS, // separator
&response, // pointer to mem address for return value
&fourccc,
&renderflags,
&xwidth,
&ywidth,
&size,
&videodata, // pointer to mem address for returned frame
END_IN_ARGS);
if(return_value==0) {
return_value = saveBA81(handle,xwidth,ywidth,size,videodata);
}
return return_value;
}
static void interpolateBayer(uint16_t width, uint16_t x, uint16_t y, uint8_t *pixel, uint8_t* r, uint8_t* g, uint8_t* b)
int pixy_render_full_frame(uint16_t x, uint16_t y)
{
if (y&1)
{
if (x&1)
{
*r = *pixel;
*g = (*(pixel-1)+*(pixel+1)+*(pixel+width)+*(pixel-width))>>2;
*b = (*(pixel-width-1)+*(pixel-width+1)+*(pixel+width-1)+*(pixel+width+1))>>2;
}
else
{
*r = (*(pixel-1)+*(pixel+1))>>1;
*g = *pixel;
*b = (*(pixel-width)+*(pixel+width))>>1;
}
return pixy_render_cropped_frame(x, y, 0, 0, 320, 200);
}
int pixy_render_cropped_frame(uint16_t x, uint16_t y, uint16_t xoffset, uint16_t yoffset, uint16_t width, uint16_t height)
{
uint8_t* videodata;
int32_t response;
int32_t fourccc;
int8_t renderflags;
uint16_t xwidth;
uint16_t ywidth;
uint32_t size;
int return_value = pixy_command("cam_getFrame", // String id for remote procedure
INT8(0x21), // mode
INT16(xoffset), // xoffset
INT16(yoffset), // yoffset
INT16(width), // width
INT16(height), // height
END_OUT_ARGS, // separator
&response, // pointer to mem address for return value
&fourccc,
&renderflags,
&xwidth,
&ywidth,
&size,
&videodata, // pointer to mem address for returned frame
END_IN_ARGS);
if (return_value == 0) {
return_value = renderBA81(x, y, xwidth, ywidth, size, videodata);
}
else
{
if (x&1)
{
*r = (*(pixel-width)+*(pixel+width))>>1;
return return_value;
}
int pixy_save_full_frame(FILE_HANDLE* handle)
{
return pixy_save_cropped_frame(handle, 0, 0, 320, 200);
}
int pixy_save_cropped_frame(FILE_HANDLE* handle, uint16_t xoffset, uint16_t yoffset, uint16_t width, uint16_t height)
{
uint8_t* videodata;
int32_t response;
int32_t fourccc;
int8_t renderflags;
uint16_t xwidth;
uint16_t ywidth;
uint32_t size;
int return_value = pixy_command("cam_getFrame", // String id for remote procedure
INT8(0x21), // mode
INT16(xoffset), // xoffset
INT16(yoffset), // yoffset
INT16(width), // width
INT16(height), // height
END_OUT_ARGS, // separator
&response, // pointer to mem address for return value
&fourccc,
&renderflags,
&xwidth,
&ywidth,
&size,
&videodata, // pointer to mem address for returned frame
END_IN_ARGS);
if (return_value == 0) {
return_value = saveBA81(handle, xwidth, ywidth, size, videodata);
}
return return_value;
}
static void interpolateBayer(uint16_t width, uint16_t x, uint16_t y, uint8_t* pixel, uint8_t* r, uint8_t* g, uint8_t* b)
{
if (y & 1) {
if (x & 1) {
*r = *pixel;
*g = (*(pixel - 1) + * (pixel + 1) + * (pixel + width) + * (pixel - width)) >> 2;
*b = (*(pixel - width - 1) + * (pixel - width + 1) + * (pixel + width - 1) + * (pixel + width + 1)) >> 2;
} else {
*r = (*(pixel - 1) + * (pixel + 1)) >> 1;
*g = *pixel;
*b = (*(pixel-1)+*(pixel+1))>>1;
*b = (*(pixel - width) + * (pixel + width)) >> 1;
}
else
{
*r = (*(pixel-width-1)+*(pixel-width+1)+*(pixel+width-1)+*(pixel+width+1))>>2;
*g = (*(pixel-1)+*(pixel+1)+*(pixel+width)+*(pixel-width))>>2;
} else {
if (x & 1) {
*r = (*(pixel - width) + * (pixel + width)) >> 1;
*g = *pixel;
*b = (*(pixel - 1) + * (pixel + 1)) >> 1;
} else {
*r = (*(pixel - width - 1) + * (pixel - width + 1) + * (pixel + width - 1) + * (pixel + width + 1)) >> 2;
*g = (*(pixel - 1) + * (pixel + 1) + * (pixel + width) + * (pixel - width)) >> 2;
*b = *pixel;
}
}
@@ -128,7 +136,7 @@ static void interpolateBayer(uint16_t width, uint16_t x, uint16_t y, uint8_t *pi
static int renderBA81(uint16_t xpos, uint16_t ypos, uint16_t width, uint16_t height, uint32_t frameLen, uint8_t *frame)
static int renderBA81(uint16_t xpos, uint16_t ypos, uint16_t width, uint16_t height, uint32_t frameLen, uint8_t* frame)
{
uint16_t x, y;
uint8_t r, g, b;
@@ -140,102 +148,101 @@ static int renderBA81(uint16_t xpos, uint16_t ypos, uint16_t width, uint16_t hei
// don't render top and bottom rows, and left and rightmost columns because of color
// interpolation
//uint32_t decodedimage[(width-2)*(height-2)];
uint16_t* decodedimage = malloc(sizeof(uint16_t)*(width-2)*(height-2));
uint16_t* decodedimage = malloc(sizeof(uint16_t) * (width - 2) * (height - 2));
if(decodedimage==NULL) { //not enough free space to decode image in memory
if (decodedimage == NULL) { //not enough free space to decode image in memory
//decode & render image pixel by pixel
for (y=1; 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++;
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));
}
tft_draw_bitmap_unscaled(xpos,ypos,width-2,height-2,decodedimage);
frame++;
}
} else { //enough space
uint16_t* line = decodedimage;
free(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)
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);
uint32_t row_size_padded = ((width - 2) * 3 + 3) & (~3); //row size aligned to 4 bytes
uint32_t fpos_end = fpos + row_size_padded * (height - 2);
// skip first line
frame += width;
// don't render top and bottom rows, and left and rightmost columns because of color
// interpolation
// interpolation
for (y=1; y<height-1; y++)
{
frame++;
uint8_t rowbuf[row_size_padded];
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;
}
//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;
}
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;
}
if (filesystem_file_write(handle, rowbuf, row_size_padded) != F_OK) {
return -1;
}
frame++;
}
return 0;
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 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;
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,3 +1,16 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/app/pixy_frame.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

View File

@@ -1,3 +1,20 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/app/screen_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 "button.h"
#include "tft.h"
@@ -7,133 +24,132 @@
static BUTTON_STRUCT b_back;
static void b_back_cb(void* button) {
gui_screen_back();
static void b_back_cb(void* button)
{
gui_screen_back();
}
static void image_test();
static void enter(void* screen) {
tft_clear(HEX(0xBABECD));
//Back button
b_back.base.x1=10; //Start X of Button
b_back.base.y1=200; //Start Y of Button
b_back.base.x2=AUTO; //b_back.base.x1+160; //Auto Calculate X2 with String Width
b_back.base.y2=AUTO; //Auto Calculate Y2 with String Height
b_back.txtcolor=WHITE; //Set foreground color
b_back.bgcolor=HEX(0xAE1010); //Set background color (Don't take 255 or 0 on at least one channel, to make shadows possible)
b_back.font=0; //Select Font
b_back.text="Back"; //Set Text (For formatted strings take sprintf)
b_back.callback=b_back_cb; //Call b_back_cb as Callback
gui_button_add(&b_back); //Register Button (and run the callback from now on)
static void enter(void* screen)
{
tft_clear(HEX(0xBABECD));
//Back button
b_back.base.x1 = 10; //Start X of Button
b_back.base.y1 = 200; //Start Y of Button
b_back.base.x2 = AUTO; //b_back.base.x1+160; //Auto Calculate X2 with String Width
b_back.base.y2 = AUTO; //Auto Calculate Y2 with String Height
b_back.txtcolor = WHITE; //Set foreground color
b_back.bgcolor = HEX(0xAE1010); //Set background color (Don't take 255 or 0 on at least one channel, to make shadows possible)
b_back.font = 0; //Select Font
b_back.text = "Back"; //Set Text (For formatted strings take sprintf)
b_back.callback = b_back_cb; //Call b_back_cb as Callback
gui_button_add(&b_back); //Register Button (and run the callback from now on)
/*
//tft test
tft_draw_pixel(0,0,BLACK);
tft_draw_pixel(319,239,BLACK);
tft_draw_pixel(10,210,BLUE);
tft_draw_pixel(12,210,BLUE);
tft_draw_rectangle(40,100,60,235,BLUE);
tft_fill_rectangle(100,215,200,225,GREEN);
tft_draw_line(10,50,310,225,RGB(0xFF,0,0xFF));
tft_draw_circle(10,10,100, RED);
tft_print_line(30, 130, RED, BLUE, 0, "Hallo");
*/
tft_draw_line(10, 30, 310, 30, BLACK);
tft_print_line(10, 18, BLUE, TRANSPARENT, 0, "Name D H RO Date Time Size");
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;
int y = 33;
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;
}
DIRECTORY_STRUCT* dir = filesystem_dir_open(".");
filesystem_dir_close(dir);
if (dir == NULL) {
return;
}
y+=14;
for (int i = 0; i < dir->num_files; i++) {
FILE_STRUCT* file = &(dir->files[i]);
tft_print_formatted(10, y,
(file->fattrib & F_DIR) ? GREEN : RED,
TRANSPARENT, 0, "%-13s%c %c %s %02u%02u%02u %02u:%02u:%02u %u",
file->fname,
(file->fattrib & F_DIR) ? 'D' : ' ',
(file->fattrib & F_HID) ? 'H' : ' ',
(file->fattrib & F_RDO) ? "R " : "RW",
file->fdate.day,
file->fdate.month,
(file->fdate.year + 1980) % 100,
file->ftime.hour,
file->ftime.min,
file->ftime.sec * 2,
file->fsize);
y += 14;
}
FILE_HANDLE* file = filesystem_file_open("test.txt");
if(file==NULL) {
tft_print_line(10,y,BLUE,TRANSPARENT,0,"Could not open test.txt");
} else {
char buf [30];
int size = (file->fsize>30)?29:file->fsize-1;
FILE_STATUS st = filesystem_file_read(file,buf,size);
if(st==F_OK) {
buf[file->fpos]='\0';
tft_print_formatted(10,y,BLUE,TRANSPARENT,0,"test.txt contains \"%s\"",buf);
long num = strtol(&(buf[file->fpos-4]),NULL,0);
num++;
y+=14;
if(filesystem_file_seek(file,file->fpos-4)!=F_OK) {
tft_print_formatted(10,y,BLUE,TRANSPARENT,0,"Could not seek to %d",file->fpos-4);
} else {
sprintf(buf,"%04d",num);
if(filesystem_file_write(file,buf,4) != F_OK) {
tft_print_formatted(10,y,BLUE,TRANSPARENT,0,"Could not write new number %d",num);
} else {
tft_print_formatted(10,y,BLUE,TRANSPARENT,0,"New number written %d",num);
}
}
} else {
tft_print_line(10,y,BLUE,TRANSPARENT,0,"Could not read from test.txt");
}
filesystem_dir_close(dir);
}
filesystem_file_close(file);
y += 14;
image_test();
FILE_HANDLE* file = filesystem_file_open("test.txt");
if (file == NULL) {
tft_print_line(10, y, BLUE, TRANSPARENT, 0, "Could not open test.txt");
} else {
char buf [30];
int size = (file->fsize > 30) ? 29 : file->fsize - 1;
FILE_STATUS st = filesystem_file_read(file, buf, size);
if (st == F_OK) {
buf[file->fpos] = '\0';
tft_print_formatted(10, y, BLUE, TRANSPARENT, 0, "test.txt contains \"%s\"", buf);
long num = strtol(&(buf[file->fpos - 4]), NULL, 0);
num++;
y += 14;
if (filesystem_file_seek(file, file->fpos - 4) != F_OK) {
tft_print_formatted(10, y, BLUE, TRANSPARENT, 0, "Could not seek to %d", file->fpos - 4);
} else {
sprintf(buf, "%04d", num);
if (filesystem_file_write(file, buf, 4) != F_OK) {
tft_print_formatted(10, y, BLUE, TRANSPARENT, 0, "Could not write new number %d", num);
} else {
tft_print_formatted(10, y, BLUE, TRANSPARENT, 0, "New number written %d", num);
}
}
} else {
tft_print_line(10, y, BLUE, TRANSPARENT, 0, "Could not read from test.txt");
}
}
filesystem_file_close(file);
image_test();
}
static void leave(void* screen) {
gui_button_remove(&b_back);
static void leave(void* screen)
{
gui_button_remove(&b_back);
}
static void update(void* screen) {
static void update(void* screen)
{
}
static SCREEN_STRUCT screen = {
enter,
leave,
update
enter,
leave,
update
};
SCREEN_STRUCT* get_screen_filetest() {
return &screen;
SCREEN_STRUCT* get_screen_filetest()
{
return &screen;
}
static void image_test() {
static void image_test()
{
if(!tft_draw_bitmap_file_unscaled(250,170,"cpu.bmp")) {
tft_print_line(10,180,BLUE,TRANSPARENT,0,"Could not open cpu.bmp");
}
tft_draw_rectangle(250-1,170-1,250-1+64,170-1+64,BLACK);
if (!tft_draw_bitmap_file_unscaled(250, 170, "cpu.bmp")) {
tft_print_line(10, 180, BLUE, TRANSPARENT, 0, "Could not open cpu.bmp");
}
tft_draw_rectangle(250 - 1, 170 - 1, 250 - 1 + 64, 170 - 1 + 64, BLACK);
}

View File

@@ -1,3 +1,18 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/app/screen_filetest.h
*
* Version History:
* Date Autor Email SHA Changes
* 2015-05-10 timolang@gmail.com e2bce8f Added filesystem module, tests and implementation for it in emulator.
* 2015-05-10 timolang@gmail.com 21edc56 Added doxyfile (doxygen) for the common folder. Started with doxygen comments for app and tft module.
* 2015-05-15 timolang@gmail.com 9a16865 Added doxgen comments to filesyste, checkbox, numupdown and screen module. And some minor changes to the other modules.
*
**************************************************************************************************************************************/
#include "screen.h"
/**

View File

@@ -1,3 +1,21 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/app/screen_guitest.c
*
* Version History:
* Date Autor Email SHA Changes
* 2015-04-27 timolang@gmail.com cf72baa Introduced a Screen (sub) module and divided app into multiple screens.
* 2015-04-30 timolang@gmail.com 76ea9d8 Added num up down support.
* 2015-05-09 timolang@gmail.com c652b6b Improved Emulator Gui
* 2015-05-29 aaron@duckpond.ch 7d2d1a1 Implemented basic sampling and averaging of touch coordinates using timer7
* 2015-06-01 timolang@gmail.com eb573bc Finalized calibration. Fixed a bug in screen module.
* 2015-06-02 timolang@gmail.com da34bce Fixed all printf related problems on discovery using workarounds and newlib nano-instead of newlib
*
**************************************************************************************************************************************/
#include "screen_guitest.h"
#include "button.h"
#include "tft.h"
@@ -9,127 +27,138 @@ static TOUCH_AREA_STRUCT a_area;
static CHECKBOX_STRUCT c_cbox;
static NUMUPDOWN_STRUCT n_updown;
static void checkboxCB(void *checkbox, bool checked) {
printf("Checkbox %s\n",(checked?"checked":"unchecked"));
static void checkboxCB(void* checkbox, bool checked)
{
printf("Checkbox %s\n", (checked ? "checked" : "unchecked"));
}
static void b_back_cb(void* button) {
gui_screen_back();
static void b_back_cb(void* button)
{
gui_screen_back();
}
static void n_updown_cb(void* numupdown, int16_t value) {
printf("New NumUpDown Value %d\n",value);
static void n_updown_cb(void* numupdown, int16_t value)
{
printf("New NumUpDown Value %d\n", value);
}
static void touchCB(void* touchArea, TOUCH_ACTION triggeredAction) {
switch(triggeredAction) {
case PEN_DOWN:
printf("action PEN_DOWN\n");
break;
case PEN_UP:
printf("action PEN_UP\n");
break;
case PEN_MOVE:
printf("action PEN_MOVE\n");
break;
case PEN_ENTER:
printf("action PEN_ENTER\n");
break;
case PEN_LEAVE:
printf("action PEN_LEAVE\n");
break;
default:
printf("action %s\n",triggeredAction);
break;
}
static void touchCB(void* touchArea, TOUCH_ACTION triggeredAction)
{
switch (triggeredAction) {
case PEN_DOWN:
printf("action PEN_DOWN\n");
break;
case PEN_UP:
printf("action PEN_UP\n");
break;
case PEN_MOVE:
printf("action PEN_MOVE\n");
break;
case PEN_ENTER:
printf("action PEN_ENTER\n");
break;
case PEN_LEAVE:
printf("action PEN_LEAVE\n");
break;
default:
printf("action %s\n", triggeredAction);
break;
}
}
static void enter(void* screen) {
tft_clear(HEX(0xA6FD9A));
//Back button
b_back.base.x1=10; //Start X of Button
b_back.base.y1=10; //Start Y of Button
b_back.base.x2=AUTO; //b_back.base.x1+160; //Auto Calculate X2 with String Width
b_back.base.y2=AUTO; //Auto Calculate Y2 with String Height
b_back.txtcolor=WHITE; //Set foreground color
b_back.bgcolor=HEX(0xAE1010); //Set background color (Don't take 255 or 0 on at least one channel, to make shadows possible)
b_back.font=0; //Select Font
b_back.text="Back"; //Set Text (For formatted strings take sprintf)
b_back.callback=b_back_cb; //Call b_back_cb as Callback
gui_button_add(&b_back); //Register Button (and run the callback from now on)
static void enter(void* screen)
{
tft_clear(HEX(0xA6FD9A));
//Back button
b_back.base.x1 = 10; //Start X of Button
b_back.base.y1 = 10; //Start Y of Button
b_back.base.x2 = AUTO; //b_back.base.x1+160; //Auto Calculate X2 with String Width
b_back.base.y2 = AUTO; //Auto Calculate Y2 with String Height
b_back.txtcolor = WHITE; //Set foreground color
b_back.bgcolor = HEX(0xAE1010); //Set background color (Don't take 255 or 0 on at least one channel, to make shadows possible)
b_back.font = 0; //Select Font
b_back.text = "Back"; //Set Text (For formatted strings take sprintf)
b_back.callback = b_back_cb; //Call b_back_cb as Callback
gui_button_add(&b_back); //Register Button (and run the callback from now on)
//tft test
tft_draw_pixel(0,0,BLACK);
tft_draw_pixel(319,239,BLACK);
tft_draw_pixel(10,210,BLUE);
tft_draw_pixel(12,210,BLUE);
tft_draw_rectangle(40,100,60,235,BLUE);
tft_fill_rectangle(100,215,200,225,GREEN);
tft_draw_line(10,50,310,225,RGB(0xFF,0,0xFF));
tft_draw_circle(10,10,100, RED);
tft_print_line(30, 130, RED, BLUE, 0, "Hallo");
//Area test
a_area.hookedActions = PEN_DOWN | PEN_UP | PEN_MOVE | PEN_ENTER | PEN_LEAVE;
a_area.x1 = 130;
a_area.y1 = 30;
a_area.x2 = 200;
a_area.y2 = 60;
a_area.callback = touchCB;
touch_register_area(&a_area);
//tft test
tft_draw_pixel(0, 0, BLACK);
tft_draw_pixel(319, 239, BLACK);
tft_draw_pixel(10, 210, BLUE);
tft_draw_pixel(12, 210, BLUE);
tft_draw_rectangle(40, 100, 60, 235, BLUE);
tft_fill_rectangle(100, 215, 200, 225, GREEN);
tft_draw_line(10, 50, 310, 225, RGB(0xFF, 0, 0xFF));
tft_draw_circle(10, 10, 100, RED);
tft_print_line(30, 130, RED, BLUE, 0, "Hallo");
//Checkbox test
c_cbox.base.x1=220;
c_cbox.base.y1=45;
c_cbox.base.x2=c_cbox.base.x1+16;
c_cbox.base.y2=c_cbox.base.y1+16;
c_cbox.fgcolor = GREEN;
c_cbox.checked = true;
c_cbox.callback = checkboxCB;
gui_checkbox_add(&c_cbox);
//Area test
a_area.hookedActions = PEN_DOWN | PEN_UP | PEN_MOVE | PEN_ENTER | PEN_LEAVE;
a_area.x1 = 130;
a_area.y1 = 30;
a_area.x2 = 200;
a_area.y2 = 60;
a_area.callback = touchCB;
touch_register_area(&a_area);
//Num up down test
n_updown.x=200;
n_updown.y=120;
n_updown.fgcolor=RED;
n_updown.value = -3;
n_updown.max=11;
n_updown.min =-5;
n_updown.callback=n_updown_cb;
gui_numupdown_add(&n_updown);
//Checkbox test
c_cbox.base.x1 = 220;
c_cbox.base.y1 = 45;
c_cbox.base.x2 = c_cbox.base.x1 + 16;
c_cbox.base.y2 = c_cbox.base.y1 + 16;
c_cbox.fgcolor = GREEN;
c_cbox.checked = true;
c_cbox.callback = checkboxCB;
gui_checkbox_add(&c_cbox);
//Num up down test
n_updown.x = 200;
n_updown.y = 120;
n_updown.fgcolor = RED;
n_updown.value = -3;
n_updown.max = 11;
n_updown.min = -5;
n_updown.callback = n_updown_cb;
gui_numupdown_add(&n_updown);
}
static void leave(void* screen) {
gui_button_remove(&b_back);
gui_checkbox_remove(&c_cbox);
gui_numupdown_remove(&n_updown);
touch_unregister_area(&a_area);
static void leave(void* screen)
{
gui_button_remove(&b_back);
gui_checkbox_remove(&c_cbox);
gui_numupdown_remove(&n_updown);
touch_unregister_area(&a_area);
}
static void update(void* screen) {
//gui_button_redraw(&b_back); //only needed if button is overdrawn by others
//.... for the other elements as well
static void update(void* screen)
{
//gui_button_redraw(&b_back); //only needed if button is overdrawn by others
//.... for the other elements as well
}
static SCREEN_STRUCT screen = {
enter,
leave,
update
enter,
leave,
update
};
SCREEN_STRUCT* get_screen_guitest() {
return &screen;
SCREEN_STRUCT* get_screen_guitest()
{
return &screen;
}

View File

@@ -1,3 +1,18 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/app/screen_guitest.h
*
* Version History:
* Date Autor Email SHA Changes
* 2015-04-27 timolang@gmail.com cf72baa Introduced a Screen (sub) module and divided app into multiple screens.
* 2015-05-10 timolang@gmail.com 21edc56 Added doxyfile (doxygen) for the common folder. Started with doxygen comments for app and tft module.
* 2015-05-15 timolang@gmail.com 9a16865 Added doxgen comments to filesyste, checkbox, numupdown and screen module. And some minor changes to the other modules.
*
**************************************************************************************************************************************/
#include "screen.h"

View File

@@ -1,3 +1,21 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/app/screen_main.c
*
* Version History:
* Date Autor Email SHA Changes
* 2015-04-27 timolang@gmail.com cf72baa Introduced a Screen (sub) module and divided app into multiple screens.
* 2015-05-10 timolang@gmail.com e2bce8f Added filesystem module, tests and implementation for it in emulator.
* 2015-05-15 timolang@gmail.com 27c09ba Redesigned main menu. Moved stuff from pixytest to a new helper file and to the new "photo mode"-screen.
* 2015-05-16 timolang@gmail.com e46314b Added Tracking Screen and implemented "Reference Tracking" and "Color Region Selection"
* 2015-06-01 aaron@duckpond.ch caa7b5c Added IRQ for user button, fixed some touchproblems.
* 2015-06-01 timolang@gmail.com 3155f42 Fixed mainscreen layout.
*
**************************************************************************************************************************************/
#include "screen_main.h"
#include "screen_guitest.h"
#include "screen_pixytest.h"
@@ -17,157 +35,165 @@ BUTTON_STRUCT b_ref_tracking;
BUTTON_STRUCT b_photo_mode;
static void b_our_tracking_cb(void* button) {
tracking_set_mode(OUR_TRACKING);
gui_screen_navigate(get_screen_tracking());
static void b_our_tracking_cb(void* button)
{
tracking_set_mode(OUR_TRACKING);
gui_screen_navigate(get_screen_tracking());
}
static void b_ref_tracking_cb(void* button) {
tracking_set_mode(REFERENCE_TRACKING);
gui_screen_navigate(get_screen_tracking());
static void b_ref_tracking_cb(void* button)
{
tracking_set_mode(REFERENCE_TRACKING);
gui_screen_navigate(get_screen_tracking());
}
static void b_photo_mode_cb(void* button) {
gui_screen_navigate(get_screen_photomode());
static void b_photo_mode_cb(void* button)
{
gui_screen_navigate(get_screen_photomode());
}
static void b_guitest_cb(void* button) {
gui_screen_navigate(get_screen_guitest());
static void b_guitest_cb(void* button)
{
gui_screen_navigate(get_screen_guitest());
}
static void b_filetest_cb(void* button) {
gui_screen_navigate(get_screen_filetest());
static void b_filetest_cb(void* button)
{
gui_screen_navigate(get_screen_filetest());
}
static void b_pixytest_cb(void* button) {
gui_screen_navigate(get_screen_pixytest());
static void b_pixytest_cb(void* button)
{
gui_screen_navigate(get_screen_pixytest());
}
static void enter(void* screen) {
tft_clear(WHITE);
static void enter(void* screen)
{
tft_clear(WHITE);
//Heading
tft_print_line(10,10,BLUE,TRANSPARENT,1,"Discoverpixy");
tft_draw_line(0,40,319,40,BLACK);
//Heading
tft_print_line(10, 10, BLUE, TRANSPARENT, 1, "Discoverpixy");
tft_draw_line(0, 40, 319, 40, BLACK);
#define X_TAB 97
#define BUTTON_SPACING 7
#define X_TAB 97
#define BUTTON_SPACING 7
//First line of buttons
#define Y_FIRST 60
tft_print_line(10,Y_FIRST,BLACK,TRANSPARENT,0,"Tracking:");
//First line of buttons
#define Y_FIRST 60
tft_print_line(10, Y_FIRST, BLACK, TRANSPARENT, 0, "Tracking:");
b_our_tracking.base.x1=X_TAB; //Start X of Button
b_our_tracking.base.y1=Y_FIRST-3; //Start Y of Button
b_our_tracking.base.x2=AUTO; //Auto Calculate X2 with String Width
b_our_tracking.base.y2=AUTO; //Auto Calculate Y2 with String Height
b_our_tracking.txtcolor=WHITE; //Set foreground color
b_our_tracking.bgcolor=HEX(0xE30535); //Set background color (Don't take 255 or 0 on at least one channel, to make shadows possible)
b_our_tracking.font=0; //Select Font
b_our_tracking.text="Our Tracking"; //Set Text (For formatted strings take sprintf)
b_our_tracking.callback=b_our_tracking_cb; //Call b_our_tracking when the button get's pressed
gui_button_add(&b_our_tracking); //Register Button (and run the callback from now on)
b_our_tracking.base.x1 = X_TAB; //Start X of Button
b_our_tracking.base.y1 = Y_FIRST - 3; //Start Y of Button
b_our_tracking.base.x2 = AUTO; //Auto Calculate X2 with String Width
b_our_tracking.base.y2 = AUTO; //Auto Calculate Y2 with String Height
b_our_tracking.txtcolor = WHITE; //Set foreground color
b_our_tracking.bgcolor = HEX(0xE30535); //Set background color (Don't take 255 or 0 on at least one channel, to make shadows possible)
b_our_tracking.font = 0; //Select Font
b_our_tracking.text = "Our Tracking"; //Set Text (For formatted strings take sprintf)
b_our_tracking.callback = b_our_tracking_cb; //Call b_our_tracking when the button get's pressed
gui_button_add(&b_our_tracking); //Register Button (and run the callback from now on)
b_ref_tracking.base.x1=b_our_tracking.base.x2+BUTTON_SPACING;
b_ref_tracking.base.y1=Y_FIRST-3;
b_ref_tracking.base.x2=AUTO;
b_ref_tracking.base.y2=AUTO;
b_ref_tracking.txtcolor=WHITE;
b_ref_tracking.bgcolor=HEX(0xFF2151);
b_ref_tracking.font=0;
b_ref_tracking.text="Ref Tracking";
b_ref_tracking.callback=b_ref_tracking_cb;
gui_button_add(&b_ref_tracking);
b_ref_tracking.base.x1 = b_our_tracking.base.x2 + BUTTON_SPACING;
b_ref_tracking.base.y1 = Y_FIRST - 3;
b_ref_tracking.base.x2 = AUTO;
b_ref_tracking.base.y2 = AUTO;
b_ref_tracking.txtcolor = WHITE;
b_ref_tracking.bgcolor = HEX(0xFF2151);
b_ref_tracking.font = 0;
b_ref_tracking.text = "Ref Tracking";
b_ref_tracking.callback = b_ref_tracking_cb;
gui_button_add(&b_ref_tracking);
//Second line of buttons
#define Y_SECOND Y_FIRST+25
tft_print_line(10,Y_SECOND,BLACK,TRANSPARENT,0,"Photo mode:");
//Second line of buttons
#define Y_SECOND Y_FIRST+25
tft_print_line(10, Y_SECOND, BLACK, TRANSPARENT, 0, "Photo mode:");
b_photo_mode.base.x1=X_TAB;
b_photo_mode.base.y1=Y_SECOND-3;
b_photo_mode.base.x2=AUTO;
b_photo_mode.base.y2=AUTO;
b_photo_mode.txtcolor=WHITE;
b_photo_mode.bgcolor=HEX(0x21B1FF);
b_photo_mode.font=0;
b_photo_mode.text="Photo Mode";
b_photo_mode.callback=b_photo_mode_cb;
gui_button_add(&b_photo_mode);
b_photo_mode.base.x1 = X_TAB;
b_photo_mode.base.y1 = Y_SECOND - 3;
b_photo_mode.base.x2 = AUTO;
b_photo_mode.base.y2 = AUTO;
b_photo_mode.txtcolor = WHITE;
b_photo_mode.bgcolor = HEX(0x21B1FF);
b_photo_mode.font = 0;
b_photo_mode.text = "Photo Mode";
b_photo_mode.callback = b_photo_mode_cb;
gui_button_add(&b_photo_mode);
//Third line of buttons
#define Y_THIRD Y_SECOND+25
tft_print_line(10,Y_THIRD,BLACK,TRANSPARENT,0,"Tests:");
//Third line of buttons
#define Y_THIRD Y_SECOND+25
tft_print_line(10, Y_THIRD, BLACK, TRANSPARENT, 0, "Tests:");
b_guitest.base.x1=X_TAB;
b_guitest.base.y1=Y_THIRD-3;
b_guitest.base.x2=AUTO;
b_guitest.base.y2=AUTO;
b_guitest.txtcolor=BLACK;
b_guitest.bgcolor=HEX(0x00FA21);
b_guitest.font=0;
b_guitest.text="Gui & Tft";
b_guitest.callback=b_guitest_cb;
gui_button_add(&b_guitest);
b_guitest.base.x1 = X_TAB;
b_guitest.base.y1 = Y_THIRD - 3;
b_guitest.base.x2 = AUTO;
b_guitest.base.y2 = AUTO;
b_guitest.txtcolor = BLACK;
b_guitest.bgcolor = HEX(0x00FA21);
b_guitest.font = 0;
b_guitest.text = "Gui & Tft";
b_guitest.callback = b_guitest_cb;
gui_button_add(&b_guitest);
b_pixytest.base.x1=b_guitest.base.x2+BUTTON_SPACING;
b_pixytest.base.y1=Y_THIRD-3;
b_pixytest.base.x2=AUTO;
b_pixytest.base.y2=AUTO;
b_pixytest.txtcolor=BLACK;
b_pixytest.bgcolor=HEX(0x00FA96);
b_pixytest.font=0;
b_pixytest.text="Pixy";
b_pixytest.callback=b_pixytest_cb;
gui_button_add(&b_pixytest);
b_pixytest.base.x1 = b_guitest.base.x2 + BUTTON_SPACING;
b_pixytest.base.y1 = Y_THIRD - 3;
b_pixytest.base.x2 = AUTO;
b_pixytest.base.y2 = AUTO;
b_pixytest.txtcolor = BLACK;
b_pixytest.bgcolor = HEX(0x00FA96);
b_pixytest.font = 0;
b_pixytest.text = "Pixy";
b_pixytest.callback = b_pixytest_cb;
gui_button_add(&b_pixytest);
b_filetest.base.x1=b_pixytest.base.x2+BUTTON_SPACING;
b_filetest.base.y1=Y_THIRD-3;
b_filetest.base.x2=AUTO;
b_filetest.base.y2=AUTO;
b_filetest.txtcolor=BLACK;
b_filetest.bgcolor=HEX(0x00FAC4);
b_filetest.font=0;
b_filetest.text="File";
b_filetest.callback=b_filetest_cb;
gui_button_add(&b_filetest);
b_filetest.base.x1 = b_pixytest.base.x2 + BUTTON_SPACING;
b_filetest.base.y1 = Y_THIRD - 3;
b_filetest.base.x2 = AUTO;
b_filetest.base.y2 = AUTO;
b_filetest.txtcolor = BLACK;
b_filetest.bgcolor = HEX(0x00FAC4);
b_filetest.font = 0;
b_filetest.text = "File";
b_filetest.callback = b_filetest_cb;
gui_button_add(&b_filetest);
//Bottom line
tft_draw_line(0,145,319,145,BLACK);
tft_print_line(10,150,BLUE,TRANSPARENT,0,"Powered by");
tft_draw_bitmap_file_unscaled(10,165,"pixy_small.bmp");
tft_draw_bitmap_file_unscaled(165,165,"stm_small.bmp");
//Bottom line
tft_draw_line(0, 145, 319, 145, BLACK);
tft_print_line(10, 150, BLUE, TRANSPARENT, 0, "Powered by");
tft_draw_bitmap_file_unscaled(10, 165, "pixy_small.bmp");
tft_draw_bitmap_file_unscaled(165, 165, "stm_small.bmp");
}
static void leave(void* screen) {
gui_button_remove(&b_our_tracking);
gui_button_remove(&b_ref_tracking);
gui_button_remove(&b_photo_mode);
gui_button_remove(&b_guitest);
gui_button_remove(&b_pixytest);
gui_button_remove(&b_filetest);
static void leave(void* screen)
{
gui_button_remove(&b_our_tracking);
gui_button_remove(&b_ref_tracking);
gui_button_remove(&b_photo_mode);
gui_button_remove(&b_guitest);
gui_button_remove(&b_pixytest);
gui_button_remove(&b_filetest);
}
static void update(void* screen) {
//gui_button_redraw(&b_guitest); //only needed if button is overdrawn by others
static void update(void* screen)
{
//gui_button_redraw(&b_guitest); //only needed if button is overdrawn by others
}
static SCREEN_STRUCT screen = {
enter,
leave,
update
enter,
leave,
update
};
SCREEN_STRUCT* get_screen_main() {
return &screen;
SCREEN_STRUCT* get_screen_main()
{
return &screen;
}

View File

@@ -1,3 +1,20 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/app/screen_main.h
*
* Version History:
* Date Autor Email SHA Changes
* 2015-04-27 timolang@gmail.com cf72baa Introduced a Screen (sub) module and divided app into multiple screens.
* 2015-05-10 timolang@gmail.com 21edc56 Added doxyfile (doxygen) for the common folder. Started with doxygen comments for app and tft module.
* 2015-05-11 timolang@gmail.com 08d9fe0 More work on doxygen module structure
* 2015-05-12 timolang@gmail.com 1402598 Added doxygen stuff for button module and some minor changes to touch, screen_main and tft module.
* 2015-05-15 timolang@gmail.com 9a16865 Added doxgen comments to filesyste, checkbox, numupdown and screen module. And some minor changes to the other modules.
*
**************************************************************************************************************************************/
#include "screen.h"
/**

View File

@@ -1,3 +1,18 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/app/screen_photomode.c
*
* Version History:
* Date Autor Email SHA Changes
* 2015-05-15 timolang@gmail.com 27c09ba Redesigned main menu. Moved stuff from pixytest to a new helper file and to the new "photo mode"-screen.
* 2015-05-16 timolang@gmail.com 62006e0 Documented pixy_helper and implemented/finished photo-mode screens! Snap some shots!
* 2015-06-07 timolang@gmail.com c87220d Renamed pixy_helper to pixy_frame. Updated docu of appliaction. added doxygen comments to pixy_{frame,control}.h
*
**************************************************************************************************************************************/
#include "screen_photomode.h"
#include "screen_photomode_save.h"
#include "button.h"
@@ -12,155 +27,182 @@ static bool pixy_connected = false; //Whether or not the pixy cam is currently c
static BUTTON_STRUCT b_back; //Button to navigate back
static BUTTON_STRUCT b_save; //Button to save the current image
static TOUCH_AREA_STRUCT a_area; //Touch Area, where the frame is drawn. Used to drag the image around
static bool subMenu=false; //Whether or not we left the current screen for a submenu
static bool subMenu = false; //Whether or not we left the current screen for a submenu
//Callback for when the user presses the "back" button
static void b_back_cb(void* button) {
subMenu = false; //we're not entering a submenu
gui_screen_back(); //navigate back to the previous screen
static void b_back_cb(void* button)
{
subMenu = false; //we're not entering a submenu
gui_screen_back(); //navigate back to the previous screen
}
//Callback for when the user presses the "save" button
static void b_save_cb(void* button) {
subMenu = true; //we're entering a submenu
gui_screen_navigate(get_screen_photomodesave()); //navigate to the save screen
static void b_save_cb(void* button)
{
subMenu = true; //we're entering a submenu
gui_screen_navigate(get_screen_photomodesave()); //navigate to the save screen
}
static POINT_STRUCT pixy_pos; //The current position of pixy's servos
static POINT_STRUCT old_pos; //The last touch position on the screen
//Callback for when the user drags the image around
static void touchCB(void* touchArea, TOUCH_ACTION triggeredAction) {
POINT_STRUCT p = touch_get_last_point(); //get the last touched point
switch(triggeredAction) {
case PEN_ENTER:
case PEN_DOWN:
old_pos = p; //If the user "newly" enters the touch area, we set the "last" position to the current
break;
case PEN_MOVE: //the user is moving around, he entered the screen a while ago (old_pos is set)
{
int16_t deltaX = p.x - old_pos.x; //Calculate x difference between last and current touch
int16_t deltaY = p.y - old_pos.y; //Calculate y difference between last and current touch
old_pos=p; //store the current touch point for the next time
//printf("%d %d\n",deltaX,deltaY);
if(pixy_connected) {
//Calculate new servo coordinates. 2 is just a proportional factor
int16_t new_x = pixy_pos.x+deltaX*2;
int16_t new_y = pixy_pos.y-deltaY*2;
static void touchCB(void* touchArea, TOUCH_ACTION triggeredAction)
{
POINT_STRUCT p = touch_get_last_point(); //get the last touched point
//check limits
if(new_x<0) new_x=0;
if(new_x>1000) new_x=1000;
if(new_y<0) new_y=0;
if(new_y>1000) new_y=1000;
//set pixy_pos so that the main routine can send it to the servos
pixy_pos.x = new_x;
pixy_pos.y= new_y;
}
}
switch (triggeredAction) {
case PEN_ENTER:
case PEN_DOWN:
old_pos = p; //If the user "newly" enters the touch area, we set the "last" position to the current
break;
case PEN_UP:
case PEN_LEAVE:
//printf("Leave/up\n");
break;
default: break;
}
case PEN_MOVE: { //the user is moving around, he entered the screen a while ago (old_pos is set)
int16_t deltaX = p.x - old_pos.x; //Calculate x difference between last and current touch
int16_t deltaY = p.y - old_pos.y; //Calculate y difference between last and current touch
old_pos = p; //store the current touch point for the next time
//printf("%d %d\n",deltaX,deltaY);
if (pixy_connected) {
//Calculate new servo coordinates. 2 is just a proportional factor
int16_t new_x = pixy_pos.x + deltaX * 2;
int16_t new_y = pixy_pos.y - deltaY * 2;
//check limits
if (new_x < 0) {
new_x = 0;
}
if (new_x > 1000) {
new_x = 1000;
}
if (new_y < 0) {
new_y = 0;
}
if (new_y > 1000) {
new_y = 1000;
}
//set pixy_pos so that the main routine can send it to the servos
pixy_pos.x = new_x;
pixy_pos.y = new_y;
}
}
break;
case PEN_UP:
case PEN_LEAVE:
//printf("Leave/up\n");
break;
default:
break;
}
}
//Callback for when the screen is entered/loaded
static void enter(void* screen) {
tft_clear(WHITE);
tft_print_line(5,5,BLACK,TRANSPARENT,0,"Drag the image around and ");
static void enter(void* screen)
{
tft_clear(WHITE);
//Back button
b_back.base.x1=5; //Start X of Button
b_back.base.y1=19; //Start Y of Button
b_back.base.x2=AUTO; //Auto Calculate X2 with String Width
b_back.base.y2=AUTO; //Auto Calculate Y2 with String Height
b_back.txtcolor=WHITE; //Set foreground color
b_back.bgcolor=HEX(0xAE1010); //Set background color (Don't take 255 or 0 on at least one channel, to make shadows possible)
b_back.font=0; //Select Font
b_back.text="Back"; //Set Text (For formatted strings take sprintf)
b_back.callback=b_back_cb; //Call b_back_cb as Callback
gui_button_add(&b_back); //Register Button (and run the callback from now on)
tft_print_line(5, 5, BLACK, TRANSPARENT, 0, "Drag the image around and ");
//Save button
b_save.base.x1=190;
b_save.base.y1=3;
b_save.base.x2=AUTO;
b_save.base.y2=AUTO;
b_save.txtcolor=WHITE;
b_save.bgcolor=HEX(0x1010AE);
b_save.font=0;
b_save.text="Save it!";
b_save.callback=b_save_cb;
gui_button_add(&b_save);
//Back button
b_back.base.x1 = 5; //Start X of Button
b_back.base.y1 = 19; //Start Y of Button
b_back.base.x2 = AUTO; //Auto Calculate X2 with String Width
b_back.base.y2 = AUTO; //Auto Calculate Y2 with String Height
b_back.txtcolor = WHITE; //Set foreground color
b_back.bgcolor = HEX(0xAE1010); //Set background color (Don't take 255 or 0 on at least one channel, to make shadows possible)
b_back.font = 0; //Select Font
b_back.text = "Back"; //Set Text (For formatted strings take sprintf)
b_back.callback = b_back_cb; //Call b_back_cb as Callback
gui_button_add(&b_back); //Register Button (and run the callback from now on)
//Frame Coordinates: topleft = (1,40); bottomright = (318,238)
//Leave a 10px border for the area
//Save button
b_save.base.x1 = 190;
b_save.base.y1 = 3;
b_save.base.x2 = AUTO;
b_save.base.y2 = AUTO;
b_save.txtcolor = WHITE;
b_save.bgcolor = HEX(0x1010AE);
b_save.font = 0;
b_save.text = "Save it!";
b_save.callback = b_save_cb;
gui_button_add(&b_save);
//Area to drag the image around
a_area.hookedActions = PEN_DOWN | PEN_MOVE | PEN_ENTER | PEN_UP | PEN_LEAVE;
a_area.x1 = 11;
a_area.y1 = 50;
a_area.x2 = 308;
a_area.y2 = 228;
a_area.callback = touchCB;
touch_register_area(&a_area);
//Frame Coordinates: topleft = (1,40); bottomright = (318,238)
//Leave a 10px border for the area
//Pixy stuff
pixy_connected = (pixy_init()==0); //try to connect to pixy
if(pixy_connected && !subMenu) { //pixy is connected, but we are not coming from a submenu
pixy_pos.x=pixy_pos.y=500; //reset servo positions to center
}
//Area to drag the image around
a_area.hookedActions = PEN_DOWN | PEN_MOVE | PEN_ENTER | PEN_UP | PEN_LEAVE;
a_area.x1 = 11;
a_area.y1 = 50;
a_area.x2 = 308;
a_area.y2 = 228;
a_area.callback = touchCB;
touch_register_area(&a_area);
//Pixy stuff
pixy_connected = (pixy_init() == 0); //try to connect to pixy
if (pixy_connected && !subMenu) { //pixy is connected, but we are not coming from a submenu
pixy_pos.x = pixy_pos.y = 500; //reset servo positions to center
}
}
//Callback for when the screen is left/unloaded
static void leave(void* screen) {
//remove buttons and touch area.
gui_button_remove(&b_back);
gui_button_remove(&b_save);
touch_unregister_area(&a_area);
static void leave(void* screen)
{
//remove buttons and touch area.
gui_button_remove(&b_back);
gui_button_remove(&b_save);
touch_unregister_area(&a_area);
}
//Callback for when the screen should be updated
//This is the main loop of the screen. This method will be called repeatedly
static void update(void* screen) {
//Note: The only way to detect that pixy has been disconnected is if a command fails. There's no pixy_is_connected method yet :'(
static void update(void* screen)
{
//Note: The only way to detect that pixy has been disconnected is if a command fails. There's no pixy_is_connected method yet :'(
if(!pixy_connected) { //Pixy not connected
pixy_close(); //Ensure that all pixy resources are freed (failsafe)
if(pixy_init()==0) { //try to connect to pixy
pixy_connected=true;
if(!subMenu) { //we're not coming from a submenu
pixy_pos.x=pixy_pos.y=500; //reset servo positions to center
}
printf("pixy (re)initialized\n");
}
}
if (!pixy_connected) { //Pixy not connected
pixy_close(); //Ensure that all pixy resources are freed (failsafe)
if(pixy_connected) { //If we are connected (now)
pixy_service(); //Handle pending pixy events (e.g. color info retrival)
if (pixy_init() == 0) { //try to connect to pixy
pixy_connected = true;
pixy_render_full_frame(1,40); //render the pixy video at point (1,40)
//set the servo positions to the coordinates form the touch interrupt
pixy_rcs_set_position(0,pixy_pos.x);
pixy_rcs_set_position(1,pixy_pos.y);
}
if (!subMenu) { //we're not coming from a submenu
pixy_pos.x = pixy_pos.y = 500; //reset servo positions to center
}
printf("pixy (re)initialized\n");
}
}
if (pixy_connected) { //If we are connected (now)
pixy_service(); //Handle pending pixy events (e.g. color info retrival)
pixy_render_full_frame(1, 40); //render the pixy video at point (1,40)
//set the servo positions to the coordinates form the touch interrupt
pixy_rcs_set_position(0, pixy_pos.x);
pixy_rcs_set_position(1, pixy_pos.y);
}
}
//Declare screen callbacks
static SCREEN_STRUCT screen = {
enter,
leave,
update
enter,
leave,
update
};
SCREEN_STRUCT* get_screen_photomode() {
return &screen;
SCREEN_STRUCT* get_screen_photomode()
{
return &screen;
}

View File

@@ -1,3 +1,16 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/app/screen_photomode.h
*
* Version History:
* Date Autor Email SHA Changes
* 2015-05-15 timolang@gmail.com 27c09ba Redesigned main menu. Moved stuff from pixytest to a new helper file and to the new "photo mode"-screen.
*
**************************************************************************************************************************************/
#include "screen.h"
/**

View File

@@ -1,3 +1,17 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/app/screen_photomode_save.c
*
* Version History:
* Date Autor Email SHA Changes
* 2015-05-16 timolang@gmail.com 62006e0 Documented pixy_helper and implemented/finished photo-mode screens! Snap some shots!
* 2015-06-07 timolang@gmail.com c87220d Renamed pixy_helper to pixy_frame. Updated docu of appliaction. added doxygen comments to pixy_{frame,control}.h
*
**************************************************************************************************************************************/
#include "screen_photomode_save.h"
#include "filesystem.h"
#include "button.h"
@@ -13,8 +27,9 @@ static BUTTON_STRUCT b_back; //Button to navigate back
static TOUCH_AREA_STRUCT a_area; //Touch area to select the save-file
//Callback for when the user presses the "back" button
static void b_back_cb(void* button) {
gui_screen_back();
static void b_back_cb(void* button)
{
gui_screen_back();
}
static int num_files_ok; //number of files into which we can write the image (size, flags ok)
@@ -24,46 +39,51 @@ static int liststart; //The y-Coordinate of the Start of the File-List
static const char* picked_file; //The filename picked by the user, to save the image to
//Linked list structure to save all files which are suitable for saving.
typedef struct FILE_LIST_ENTRY_S{
char* filename; //Name of the file
struct FILE_LIST_ENTRY_S* next; //Pointer to the next entry in the list or NULL
typedef struct FILE_LIST_ENTRY_S {
char* filename; //Name of the file
struct FILE_LIST_ENTRY_S* next; //Pointer to the next entry in the list or NULL
} FILE_LIST_ENTRY;
static FILE_LIST_ENTRY* files_ok; //Pointer to the head of the list
//Callback for when the user selects a file to save the image into
static void touchCB(void* touchArea, TOUCH_ACTION triggeredAction) {
static void touchCB(void* touchArea, TOUCH_ACTION triggeredAction)
{
int y = touch_get_last_point().y-liststart; //Calculate the y-Coordinate of the touch point relative to the start of the file-list
int elem = y/fontheight; //Calculate the file index
if(elem<0 | elem>= num_files_ok) return; //Check if the file index is valid (0,1,..,num_files_ok-1)
int y = touch_get_last_point().y - liststart; //Calculate the y-Coordinate of the touch point relative to the start of the file-list
int elem = y / fontheight; //Calculate the file index
//Search for the corresponding entry in the linked list
FILE_LIST_ENTRY* current_entry = files_ok; //Start walking through the list, starting by the head of the list
for(int i=0; i<elem; i++) { //Until we have reached the file (index)
current_entry= current_entry->next; //traverse to the next file
}
if (elem < 0 | elem >= num_files_ok) {
return; //Check if the file index is valid (0,1,..,num_files_ok-1)
}
picked_file = current_entry->filename; //save the picked filename. It will be used by the statemachine in the main loop
touch_unregister_area(&a_area); //unregister the touch area, we no longer need it. No more interrupts will be fired.
state=saving; //Change the state of the statemachine
//Search for the corresponding entry in the linked list
FILE_LIST_ENTRY* current_entry = files_ok; //Start walking through the list, starting by the head of the list
for (int i = 0; i < elem; i++) { //Until we have reached the file (index)
current_entry = current_entry->next; //traverse to the next file
}
picked_file = current_entry->filename; //save the picked filename. It will be used by the statemachine in the main loop
touch_unregister_area(&a_area); //unregister the touch area, we no longer need it. No more interrupts will be fired.
state = saving; //Change the state of the statemachine
}
//Text-Lines to show if we have no matching files (num_files_ok==0)
static const char* nomatch_text [] = {
"Due to limitations of the filesystem",
"implementation you can only write to",
"existing files.",
"",
"The files need to have a .bmp",
"extension and must be at least",
"189410 bytes (185kb) large.",
"Unfortunately there were no such",
"files found in the root directory.",
"",
"Please create some files and come",
"back again.",
NULL
"Due to limitations of the filesystem",
"implementation you can only write to",
"existing files.",
"",
"The files need to have a .bmp",
"extension and must be at least",
"189410 bytes (185kb) large.",
"Unfortunately there were no such",
"files found in the root directory.",
"",
"Please create some files and come",
"back again.",
NULL
};
@@ -71,231 +91,251 @@ static const char* nomatch_text [] = {
//This header has been taken from a white bitmap saved with gimp.
//Wikipedia has a pretty good description on the header: http://de.wikipedia.org/wiki/Windows_Bitmap
static unsigned char bmpheader_data[0x7A] = {
0x42, 0x4d, 0xe2, 0xe3, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x00,
0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x3e, 0x01, 0x00, 0x00, 0xc6, 0x00,
0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0xe3,
0x02, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x47, 0x52, 0x73, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00
0x42, 0x4d, 0xe2, 0xe3, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x00,
0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x3e, 0x01, 0x00, 0x00, 0xc6, 0x00,
0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0xe3,
0x02, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x47, 0x52, 0x73, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00
};
//Callback for when the screen is entered/loaded
static void enter(void* screen) {
tft_clear(WHITE);
static void enter(void* screen)
{
tft_clear(WHITE);
#define X_OFS 5
#define X_OFS 5
//Back button
b_back.base.x1=X_OFS; //Start X of Button
b_back.base.y1=210; //Start Y of Button
b_back.base.x2=AUTO; //Auto Calculate X2 with String Width
b_back.base.y2=AUTO; //Auto Calculate Y2 with String Height
b_back.txtcolor=WHITE; //Set foreground color
b_back.bgcolor=HEX(0xAE1010); //Set background color (Don't take 255 or 0 on at least one channel, to make shadows possible)
b_back.font=0; //Select Font
b_back.text="Back"; //Set Text (For formatted strings take sprintf)
b_back.callback=b_back_cb; //Call b_back_cb as Callback
gui_button_add(&b_back); //Register Button (and run the callback from now on)
//Back button
b_back.base.x1 = X_OFS; //Start X of Button
b_back.base.y1 = 210; //Start Y of Button
b_back.base.x2 = AUTO; //Auto Calculate X2 with String Width
b_back.base.y2 = AUTO; //Auto Calculate Y2 with String Height
b_back.txtcolor = WHITE; //Set foreground color
b_back.bgcolor = HEX(0xAE1010); //Set background color (Don't take 255 or 0 on at least one channel, to make shadows possible)
b_back.font = 0; //Select Font
b_back.text = "Back"; //Set Text (For formatted strings take sprintf)
b_back.callback = b_back_cb; //Call b_back_cb as Callback
gui_button_add(&b_back); //Register Button (and run the callback from now on)
state =init; //Start with the init state
fontheight = tft_font_height(0)+2; //Save the height of the used font, for fast access
files_ok = NULL; //initialize the linked list with 0 elements
num_files_ok = 0; //we have zero! elements
state = init; //Start with the init state
fontheight = tft_font_height(0) + 2; //Save the height of the used font, for fast access
files_ok = NULL; //initialize the linked list with 0 elements
num_files_ok = 0; //we have zero! elements
}
//Callback for when the screen should be updated
//This is the main loop of the screen. This method will be called repeatedly
static void update(void* screen) {
switch(state) {
case init: //Init State: The user just entered the screen
{
DIRECTORY_STRUCT* dir = filesystem_dir_open("."); //open root directory
if(dir==NULL) { //error while opening root directory
tft_print_line(X_OFS,5,BLACK,TRANSPARENT,0,"Error accessing Filesystem");
state=error;
break;
}
static void update(void* screen)
{
switch (state) {
case init: { //Init State: The user just entered the screen
DIRECTORY_STRUCT* dir = filesystem_dir_open("."); //open root directory
bool nomatch= true; //whether or not we have zero files which are suitable for saving
if (dir == NULL) { //error while opening root directory
tft_print_line(X_OFS, 5, BLACK, TRANSPARENT, 0, "Error accessing Filesystem");
state = error;
break;
}
for(int i=0; i<dir->num_files; i++) { //walk through all files in the directory
FILE_STRUCT* file = &(dir->files[i]); //Pointer to the current file/subdirectory
bool nomatch = true; //whether or not we have zero files which are suitable for saving
//Ignore directories, archives, hidden files, system files and files we cannot write to
if(file->fattrib&(F_SYS|F_HID|F_ARC|F_DIR|F_RDO)) continue;
for (int i = 0; i < dir->num_files; i++) { //walk through all files in the directory
FILE_STRUCT* file = &(dir->files[i]); //Pointer to the current file/subdirectory
//ignore files which are not large enough
if(file->fsize<189410) continue; //size taken from an example bitmap (318x198x24)
//Ignore directories, archives, hidden files, system files and files we cannot write to
if (file->fattrib & (F_SYS | F_HID | F_ARC | F_DIR | F_RDO)) {
continue;
}
nomatch=false; //at least one file matches
break;
}
//ignore files which are not large enough
if (file->fsize < 189410) {
continue; //size taken from an example bitmap (318x198x24)
}
if(nomatch) { //not one file is suitable for writing
int y=5; //y-Coordinate where to start writing the error text
int i=0;
while(nomatch_text[i]!=NULL) { //for every line in the big error array
//Write the line's text and go to the next line
tft_print_line(X_OFS,y+i*fontheight,BLACK,TRANSPARENT,0,nomatch_text[i]);
i++;
}
state = error;
} else { //we have a least one suitable file
state = showlist;
}
nomatch = false; //at least one file matches
break;
}
filesystem_dir_close(dir); //free directory struct
}
break;
if (nomatch) { //not one file is suitable for writing
int y = 5; //y-Coordinate where to start writing the error text
int i = 0;
case showlist: //Show List State: Where we load and present the suitable file's to the user in a list
{
DIRECTORY_STRUCT* dir2 = filesystem_dir_open("."); //Open the directory again
if(dir2==NULL) return; //Error on opening? This should never happen, since it's handled in the previous state
while (nomatch_text[i] != NULL) { //for every line in the big error array
//Write the line's text and go to the next line
tft_print_line(X_OFS, y + i * fontheight, BLACK, TRANSPARENT, 0, nomatch_text[i]);
i++;
}
int y = 5; //y-Coordinate where to start drawing/writing text/list-elements
state = error;
} else { //we have a least one suitable file
state = showlist;
}
tft_print_line(X_OFS,y,BLACK,TRANSPARENT,0,"Pick a file to save the image to");
y+=fontheight+5;
filesystem_dir_close(dir); //free directory struct
}
break;
tft_print_line(X_OFS,y,BLUE,TRANSPARENT,0,"Name Modified Size");
y+=fontheight;
case showlist: { //Show List State: Where we load and present the suitable file's to the user in a list
DIRECTORY_STRUCT* dir2 = filesystem_dir_open("."); //Open the directory again
liststart = y; //store the y coordinate of the start of the list away (used in toucharea callback)
num_files_ok = 0; //we start with 0 matching files
if (dir2 == NULL) {
return; //Error on opening? This should never happen, since it's handled in the previous state
}
FILE_LIST_ENTRY* current_entry = NULL; //We start with an empty list
for(int i=0; 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]);
int y = 5; //y-Coordinate where to start drawing/writing text/list-elements
//Ignore directories, archives, hidden files, system files and files we cannot write to
if(file->fattrib&(F_SYS|F_HID|F_ARC|F_DIR|F_RDO)) continue;
tft_print_line(X_OFS, y, BLACK, TRANSPARENT, 0, "Pick a file to save the image to");
y += fontheight + 5;
//ignore files which are not large enough
if(file->fsize<189410) continue; //size taken from an example bitmap (318x198x24)
tft_print_line(X_OFS, y, BLUE, TRANSPARENT, 0, "Name Modified Size");
y += fontheight;
//Print out filename, modified date,time and file size
tft_print_formatted(X_OFS,y,BLACK,
TRANSPARENT,0,"%-16s %02u.%02u.%02u %02u:%02u:%02u %u",
file->fname,
file->fdate.day,
file->fdate.month,
(file->fdate.year+1980)%100,
file->ftime.hour,
file->ftime.min,
file->ftime.sec*2,
file->fsize);
liststart = y; //store the y coordinate of the start of the list away (used in toucharea callback)
num_files_ok = 0; //we start with 0 matching files
if(current_entry==NULL) { //The list is empty
current_entry = malloc(sizeof(FILE_LIST_ENTRY)); //create new entry
files_ok = current_entry; //assign it to the list head
} else { //there's a least one entry in the list
current_entry->next = malloc(sizeof(FILE_LIST_ENTRY)); //append entry to previous entry
current_entry = current_entry->next; //newly created entry is the current now.
}
current_entry->next = NULL; //we're at the end of the list (for now)
current_entry->filename = malloc(strlen(file->fname)+1); //allocate space for the filename + zero-termination
strcpy(current_entry->filename,file->fname); //copy filename (so that we can close the directory after scanning)
FILE_LIST_ENTRY* current_entry = NULL; //We start with an empty list
//since we have found a suitable file we need to increment the position in the list
num_files_ok++;
y+=fontheight;
}
for (int i = 0; i < dir2->num_files && num_files_ok < 10; i++) { //go through all the files of the directory, abort if we have 10 matches
FILE_STRUCT* file = &(dir2->files[i]);
//Touch area for file-selection (in the list)
a_area.hookedActions = PEN_UP; //we're only interested in PEN_UP events
a_area.x1 = X_OFS; //Left border
a_area.y1 = liststart; //Start where the list started
a_area.x2 = 320-X_OFS; //Right border
a_area.y2 = liststart+fontheight*num_files_ok; //stop at the end of the list
a_area.callback = touchCB; //execute our callback when PEN_UP occurs
touch_register_area(&a_area); //register the touch area and receive events from now on
//Ignore directories, archives, hidden files, system files and files we cannot write to
if (file->fattrib & (F_SYS | F_HID | F_ARC | F_DIR | F_RDO)) {
continue;
}
filesystem_dir_close(dir2); //we no longer need the directory struct, since we have our own linked list now
//ignore files which are not large enough
if (file->fsize < 189410) {
continue; //size taken from an example bitmap (318x198x24)
}
state=picking;
}
break;
//Print out filename, modified date,time and file size
tft_print_formatted(X_OFS, y, BLACK,
TRANSPARENT, 0, "%-16s %02u.%02u.%02u %02u:%02u:%02u %u",
file->fname,
file->fdate.day,
file->fdate.month,
(file->fdate.year + 1980) % 100,
file->ftime.hour,
file->ftime.min,
file->ftime.sec * 2,
file->fsize);
case picking: //Picking State: Where we wait on the users file choice
pixy_service(); //Handle pending pixy events
//do nothing and wait on user to pick a file
break;
if (current_entry == NULL) { //The list is empty
current_entry = malloc(sizeof(FILE_LIST_ENTRY)); //create new entry
files_ok = current_entry; //assign it to the list head
} else { //there's a least one entry in the list
current_entry->next = malloc(sizeof(FILE_LIST_ENTRY)); //append entry to previous entry
current_entry = current_entry->next; //newly created entry is the current now.
}
case saving: //Saving State: Where we save the image to the selected file
{
FILE_HANDLE* file = filesystem_file_open(picked_file); //try to open the selected file
if(file==NULL) { //opening the file failed
tft_print_formatted(X_OFS,190,BLUE,TRANSPARENT,0,"Could not open %s",picked_file);
state=error;
break;
}
current_entry->next = NULL; //we're at the end of the list (for now)
current_entry->filename = malloc(strlen(file->fname) + 1); //allocate space for the filename + zero-termination
strcpy(current_entry->filename, file->fname); //copy filename (so that we can close the directory after scanning)
filesystem_file_seek(file,0); //seek to the start of the file (optional?)
if(filesystem_file_write(file,bmpheader_data,0x7A)!=F_OK) { //Writing the header failed
tft_print_formatted(X_OFS,190,BLUE,TRANSPARENT,0,"Error while writing to %s",picked_file);
filesystem_file_close(file);
state=error;
break;
}
//since we have found a suitable file we need to increment the position in the list
num_files_ok++;
y += fontheight;
}
if(pixy_save_full_frame(file)!=0) { //Writing the imagedata failed
tft_print_formatted(X_OFS,190,BLUE,TRANSPARENT,0,"Error while writing to %s",picked_file);
filesystem_file_close(file);
state=error;
break;
}
//Touch area for file-selection (in the list)
a_area.hookedActions = PEN_UP; //we're only interested in PEN_UP events
a_area.x1 = X_OFS; //Left border
a_area.y1 = liststart; //Start where the list started
a_area.x2 = 320 - X_OFS; //Right border
a_area.y2 = liststart + fontheight * num_files_ok; //stop at the end of the list
a_area.callback = touchCB; //execute our callback when PEN_UP occurs
touch_register_area(&a_area); //register the touch area and receive events from now on
//if we reach this point, we have written all data out successfully
filesystem_dir_close(dir2); //we no longer need the directory struct, since we have our own linked list now
filesystem_file_close(file); //close/finalize the file
tft_print_formatted(X_OFS,190,BLUE,TRANSPARENT,0,"Image saved to %s",picked_file);
state = done;
}
break;
state = picking;
}
break;
case error: //Error State: Where we show an error message and leave the user no other choice than to click the backbutton
case done: //Done State: When saving the file was successful
pixy_service(); //Handle pending pixy events
//wait on user to click the back button
break;
case picking: //Picking State: Where we wait on the users file choice
pixy_service(); //Handle pending pixy events
//do nothing and wait on user to pick a file
break;
}
case saving: { //Saving State: Where we save the image to the selected file
FILE_HANDLE* file = filesystem_file_open(picked_file); //try to open the selected file
if (file == NULL) { //opening the file failed
tft_print_formatted(X_OFS, 190, BLUE, TRANSPARENT, 0, "Could not open %s", picked_file);
state = error;
break;
}
filesystem_file_seek(file, 0); //seek to the start of the file (optional?)
if (filesystem_file_write(file, bmpheader_data, 0x7A) != F_OK) { //Writing the header failed
tft_print_formatted(X_OFS, 190, BLUE, TRANSPARENT, 0, "Error while writing to %s", picked_file);
filesystem_file_close(file);
state = error;
break;
}
if (pixy_save_full_frame(file) != 0) { //Writing the imagedata failed
tft_print_formatted(X_OFS, 190, BLUE, TRANSPARENT, 0, "Error while writing to %s", picked_file);
filesystem_file_close(file);
state = error;
break;
}
//if we reach this point, we have written all data out successfully
filesystem_file_close(file); //close/finalize the file
tft_print_formatted(X_OFS, 190, BLUE, TRANSPARENT, 0, "Image saved to %s", picked_file);
state = done;
}
break;
case error: //Error State: Where we show an error message and leave the user no other choice than to click the backbutton
case done: //Done State: When saving the file was successful
pixy_service(); //Handle pending pixy events
//wait on user to click the back button
break;
}
}
//Callback for when the screen is left/unloaded
static void leave(void* screen) {
gui_button_remove(&b_back); //Remove/Free the back button
static void leave(void* screen)
{
gui_button_remove(&b_back); //Remove/Free the back button
if(state==picking){ //The user left the screen in the "picking"-phase
touch_unregister_area(&a_area); //remove the touch area (for the list)
}
if (state == picking) { //The user left the screen in the "picking"-phase
touch_unregister_area(&a_area); //remove the touch area (for the list)
}
if(state==picking|| state==saving || state==done) { //the user left the screen after we created the linked list
//Iterate through the linked list and free all resources
FILE_LIST_ENTRY* current_entry = files_ok; //start with the list head
while(current_entry!=NULL) { //while we're not at the end
FILE_LIST_ENTRY* temp = current_entry->next; //save the next pointer because we free the current element on the next line
free((void*)(current_entry->filename)); //free filename
free(current_entry); //free element itself
current_entry= temp; //advance
}
}
if (state == picking || state == saving || state == done) { //the user left the screen after we created the linked list
//Iterate through the linked list and free all resources
FILE_LIST_ENTRY* current_entry = files_ok; //start with the list head
while (current_entry != NULL) { //while we're not at the end
FILE_LIST_ENTRY* temp = current_entry->next; //save the next pointer because we free the current element on the next line
free((void*)(current_entry->filename)); //free filename
free(current_entry); //free element itself
current_entry = temp; //advance
}
}
}
//Declare screen callbacks
static SCREEN_STRUCT screen = {
enter,
leave,
update
enter,
leave,
update
};
SCREEN_STRUCT* get_screen_photomodesave() {
return &screen;
SCREEN_STRUCT* get_screen_photomodesave()
{
return &screen;
}

View File

@@ -1,3 +1,16 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/app/screen_photomode_save.h
*
* Version History:
* Date Autor Email SHA Changes
* 2015-05-16 timolang@gmail.com 62006e0 Documented pixy_helper and implemented/finished photo-mode screens! Snap some shots!
*
**************************************************************************************************************************************/
#include "screen.h"
/**
@@ -20,4 +33,3 @@ SCREEN_STRUCT* get_screen_photomodesave();
/*@}*/
/*@}*/

View File

@@ -1,3 +1,23 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/app/screen_pixytest.c
*
* Version History:
* Date Autor Email SHA Changes
* 2015-04-27 timolang@gmail.com cf72baa Introduced a Screen (sub) module and divided app into multiple screens.
* 2015-05-02 timolang@gmail.com 3281616 Added some more touch functions. Improved pixy test. Drag the Image around!
* 2015-05-09 timolang@gmail.com 0b5173e Added reference tracking.
* 2015-05-15 timolang@gmail.com 27c09ba Redesigned main menu. Moved stuff from pixytest to a new helper file and to the new "photo mode"-screen.
* 2015-05-25 timolang@gmail.com 6a61769 Reimplemented pixytest screen. Added a lot of Test-Buttons.
* 2015-06-01 aaron@duckpond.ch caa7b5c Added IRQ for user button, fixed some touchproblems.
* 2015-06-03 timolang@gmail.com 74aa186 Made pixy_test screen working again. Had to disable pixy_service. Recalibrated initial touch values.
* 2015-06-07 timolang@gmail.com c87220d Renamed pixy_helper to pixy_frame. Updated docu of appliaction. added doxygen comments to pixy_{frame,control}.h
*
**************************************************************************************************************************************/
#include "screen_pixytest.h"
#include "button.h"
#include "numupdown.h"
@@ -7,7 +27,7 @@
#include "system.h"
#include "pixy_frame.h"
static volatile enum {detecting, idle,update_servos, update_ledcolor, update_ledcurrent} state; //Current state of the screen state machine
static volatile enum {detecting, idle, update_servos, update_ledcolor, update_ledcurrent} state; //Current state of the screen state machine
static BUTTON_STRUCT b_back;
@@ -30,313 +50,328 @@ static uint32_t led_maxcurrent;
static NUMUPDOWN_STRUCT n_led_powerlimit;
static void b_back_cb(void* button) {
gui_screen_back();
static void b_back_cb(void* button)
{
gui_screen_back();
}
static void b_servos_center_cb(void* button) {
if(state==idle) {
servo_x=500;
servo_y=500;
state=update_servos;
}
static void b_servos_center_cb(void* button)
{
if (state == idle) {
servo_x = 500;
servo_y = 500;
state = update_servos;
}
}
static void b_servos_topleft_cb(void* button) {
if(state==idle) {
servo_x=0;
servo_y=0;
state=update_servos;
}
static void b_servos_topleft_cb(void* button)
{
if (state == idle) {
servo_x = 0;
servo_y = 0;
state = update_servos;
}
}
static void b_servos_topright_cb(void* button) {
if(state==idle) {
servo_x=1000;
servo_y=0;
state=update_servos;
}
static void b_servos_topright_cb(void* button)
{
if (state == idle) {
servo_x = 1000;
servo_y = 0;
state = update_servos;
}
}
static void b_servos_bottomleft_cb(void* button) {
if(state==idle) {
servo_x=0;
servo_y=1000;
state=update_servos;
}
static void b_servos_bottomleft_cb(void* button)
{
if (state == idle) {
servo_x = 0;
servo_y = 1000;
state = update_servos;
}
}
static void b_servos_bottomright_cb(void* button) {
if(state==idle) {
servo_x=1000;
servo_y=1000;
state=update_servos;
}
static void b_servos_bottomright_cb(void* button)
{
if (state == idle) {
servo_x = 1000;
servo_y = 1000;
state = update_servos;
}
}
static void b_led_off_cb(void* button) {
if(state==idle) {
led_color=0x000000;
state=update_ledcolor;
}
static void b_led_off_cb(void* button)
{
if (state == idle) {
led_color = 0x000000;
state = update_ledcolor;
}
}
static void b_led_white_cb(void* button) {
if(state==idle) {
led_color=0xFFFFFF;
state=update_ledcolor;
}
static void b_led_white_cb(void* button)
{
if (state == idle) {
led_color = 0xFFFFFF;
state = update_ledcolor;
}
}
static void b_led_red_cb(void* button) {
if(state==idle) {
led_color=0xFF0000;
state=update_ledcolor;
}
static void b_led_red_cb(void* button)
{
if (state == idle) {
led_color = 0xFF0000;
state = update_ledcolor;
}
}
static void b_led_green_cb(void* button) {
if(state==idle) {
led_color=0x00FF00;
state=update_ledcolor;
}
static void b_led_green_cb(void* button)
{
if (state == idle) {
led_color = 0x00FF00;
state = update_ledcolor;
}
}
static void b_led_blue_cb(void* button) {
if(state==idle) {
led_color=0x0000FF;
state=update_ledcolor;
}
static void b_led_blue_cb(void* button)
{
if (state == idle) {
led_color = 0x0000FF;
state = update_ledcolor;
}
}
static void n_led_powerlimit_cb(void* numupdown, int16_t value) {
if(state==idle) {
led_maxcurrent=value;
state=update_ledcurrent;
}
static void n_led_powerlimit_cb(void* numupdown, int16_t value)
{
if (state == idle) {
led_maxcurrent = value;
state = update_ledcurrent;
}
}
static void enter(void* screen) {
tft_clear(WHITE);
//Back button
b_back.base.x1=10; //Start X of Button
b_back.base.y1=210; //Start Y of Button
b_back.base.x2=AUTO; //Auto Calculate X2 with String Width
b_back.base.y2=AUTO; //Auto Calculate Y2 with String Height
b_back.txtcolor=WHITE; //Set foreground color
b_back.bgcolor=HEX(0xAE1010); //Set background color (Don't take 255 or 0 on at least one channel, to make shadows possible)
b_back.font=0; //Select Font
b_back.text="Back"; //Set Text (For formatted strings take sprintf)
b_back.callback=b_back_cb; //Call b_back_cb as Callback
gui_button_add(&b_back); //Register Button (and run the callback from now on)
static void enter(void* screen)
{
tft_clear(WHITE);
//Back button
b_back.base.x1 = 10; //Start X of Button
b_back.base.y1 = 210; //Start Y of Button
b_back.base.x2 = AUTO; //Auto Calculate X2 with String Width
b_back.base.y2 = AUTO; //Auto Calculate Y2 with String Height
b_back.txtcolor = WHITE; //Set foreground color
b_back.bgcolor = HEX(0xAE1010); //Set background color (Don't take 255 or 0 on at least one channel, to make shadows possible)
b_back.font = 0; //Select Font
b_back.text = "Back"; //Set Text (For formatted strings take sprintf)
b_back.callback = b_back_cb; //Call b_back_cb as Callback
gui_button_add(&b_back); //Register Button (and run the callback from now on)
//Servo stuff
#define SERVO_BUTTON_Y 10
#define SERVO_BUTTON_SPACING 5
tft_print_line(5,SERVO_BUTTON_Y,BLACK,TRANSPARENT,0,"Servos:");
//Servo stuff
#define SERVO_BUTTON_Y 10
#define SERVO_BUTTON_SPACING 5
tft_print_line(5, SERVO_BUTTON_Y, BLACK, TRANSPARENT, 0, "Servos:");
b_servos_center.base.x1=55;
b_servos_center.base.y1=SERVO_BUTTON_Y-3;
b_servos_center.base.x2=AUTO;
b_servos_center.base.y2=AUTO;
b_servos_center.txtcolor=WHITE;
b_servos_center.bgcolor=HEX(0xAE1010);
b_servos_center.font=0;
b_servos_center.text="Center";
b_servos_center.callback=b_servos_center_cb;
gui_button_add(&b_servos_center);
b_servos_center.base.x1 = 55;
b_servos_center.base.y1 = SERVO_BUTTON_Y - 3;
b_servos_center.base.x2 = AUTO;
b_servos_center.base.y2 = AUTO;
b_servos_center.txtcolor = WHITE;
b_servos_center.bgcolor = HEX(0xAE1010);
b_servos_center.font = 0;
b_servos_center.text = "Center";
b_servos_center.callback = b_servos_center_cb;
gui_button_add(&b_servos_center);
b_servos_topleft.base.x1=b_servos_center.base.x2+SERVO_BUTTON_SPACING;
b_servos_topleft.base.y1=SERVO_BUTTON_Y-3;
b_servos_topleft.base.x2=AUTO;
b_servos_topleft.base.y2=AUTO;
b_servos_topleft.txtcolor=WHITE;
b_servos_topleft.bgcolor=HEX(0xAE1010);
b_servos_topleft.font=0;
b_servos_topleft.text="ToLe";
b_servos_topleft.callback=b_servos_topleft_cb;
gui_button_add(&b_servos_topleft);
b_servos_topleft.base.x1 = b_servos_center.base.x2 + SERVO_BUTTON_SPACING;
b_servos_topleft.base.y1 = SERVO_BUTTON_Y - 3;
b_servos_topleft.base.x2 = AUTO;
b_servos_topleft.base.y2 = AUTO;
b_servos_topleft.txtcolor = WHITE;
b_servos_topleft.bgcolor = HEX(0xAE1010);
b_servos_topleft.font = 0;
b_servos_topleft.text = "ToLe";
b_servos_topleft.callback = b_servos_topleft_cb;
gui_button_add(&b_servos_topleft);
b_servos_topright.base.x1=b_servos_topleft.base.x2+SERVO_BUTTON_SPACING;
b_servos_topright.base.y1=SERVO_BUTTON_Y-3;
b_servos_topright.base.x2=AUTO;
b_servos_topright.base.y2=AUTO;
b_servos_topright.txtcolor=WHITE;
b_servos_topright.bgcolor=HEX(0xAE1010);
b_servos_topright.font=0;
b_servos_topright.text="ToRi";
b_servos_topright.callback=b_servos_topright_cb;
gui_button_add(&b_servos_topright);
b_servos_topright.base.x1 = b_servos_topleft.base.x2 + SERVO_BUTTON_SPACING;
b_servos_topright.base.y1 = SERVO_BUTTON_Y - 3;
b_servos_topright.base.x2 = AUTO;
b_servos_topright.base.y2 = AUTO;
b_servos_topright.txtcolor = WHITE;
b_servos_topright.bgcolor = HEX(0xAE1010);
b_servos_topright.font = 0;
b_servos_topright.text = "ToRi";
b_servos_topright.callback = b_servos_topright_cb;
gui_button_add(&b_servos_topright);
b_servos_bottomleft.base.x1=b_servos_topright.base.x2+SERVO_BUTTON_SPACING;
b_servos_bottomleft.base.y1=SERVO_BUTTON_Y-3;
b_servos_bottomleft.base.x2=AUTO;
b_servos_bottomleft.base.y2=AUTO;
b_servos_bottomleft.txtcolor=WHITE;
b_servos_bottomleft.bgcolor=HEX(0xAE1010);
b_servos_bottomleft.font=0;
b_servos_bottomleft.text="BoLe";
b_servos_bottomleft.callback=b_servos_bottomleft_cb;
gui_button_add(&b_servos_bottomleft);
b_servos_bottomleft.base.x1 = b_servos_topright.base.x2 + SERVO_BUTTON_SPACING;
b_servos_bottomleft.base.y1 = SERVO_BUTTON_Y - 3;
b_servos_bottomleft.base.x2 = AUTO;
b_servos_bottomleft.base.y2 = AUTO;
b_servos_bottomleft.txtcolor = WHITE;
b_servos_bottomleft.bgcolor = HEX(0xAE1010);
b_servos_bottomleft.font = 0;
b_servos_bottomleft.text = "BoLe";
b_servos_bottomleft.callback = b_servos_bottomleft_cb;
gui_button_add(&b_servos_bottomleft);
b_servos_bottomright.base.x1=b_servos_bottomleft.base.x2+SERVO_BUTTON_SPACING;
b_servos_bottomright.base.y1=SERVO_BUTTON_Y-3;
b_servos_bottomright.base.x2=AUTO;
b_servos_bottomright.base.y2=AUTO;
b_servos_bottomright.txtcolor=WHITE;
b_servos_bottomright.bgcolor=HEX(0xAE1010);
b_servos_bottomright.font=0;
b_servos_bottomright.text="BoRi";
b_servos_bottomright.callback=b_servos_bottomright_cb;
gui_button_add(&b_servos_bottomright);
b_servos_bottomright.base.x1 = b_servos_bottomleft.base.x2 + SERVO_BUTTON_SPACING;
b_servos_bottomright.base.y1 = SERVO_BUTTON_Y - 3;
b_servos_bottomright.base.x2 = AUTO;
b_servos_bottomright.base.y2 = AUTO;
b_servos_bottomright.txtcolor = WHITE;
b_servos_bottomright.bgcolor = HEX(0xAE1010);
b_servos_bottomright.font = 0;
b_servos_bottomright.text = "BoRi";
b_servos_bottomright.callback = b_servos_bottomright_cb;
gui_button_add(&b_servos_bottomright);
//Led Color stuff
#define LED_COLOR_BUTTON_Y 35
#define LED_COLOR_BUTTON_SPACING 5
tft_print_line(5,LED_COLOR_BUTTON_Y,BLACK,TRANSPARENT,0,"Led Color:");
//Led Color stuff
#define LED_COLOR_BUTTON_Y 35
#define LED_COLOR_BUTTON_SPACING 5
tft_print_line(5, LED_COLOR_BUTTON_Y, BLACK, TRANSPARENT, 0, "Led Color:");
b_led_off.base.x1=85;
b_led_off.base.y1=LED_COLOR_BUTTON_Y-3;
b_led_off.base.x2=AUTO;
b_led_off.base.y2=AUTO;
b_led_off.txtcolor=WHITE;
b_led_off.bgcolor=BLACK;
b_led_off.font=0;
b_led_off.text="Off";
b_led_off.callback=b_led_off_cb;
gui_button_add(&b_led_off);
b_led_off.base.x1 = 85;
b_led_off.base.y1 = LED_COLOR_BUTTON_Y - 3;
b_led_off.base.x2 = AUTO;
b_led_off.base.y2 = AUTO;
b_led_off.txtcolor = WHITE;
b_led_off.bgcolor = BLACK;
b_led_off.font = 0;
b_led_off.text = "Off";
b_led_off.callback = b_led_off_cb;
gui_button_add(&b_led_off);
b_led_white.base.x1=b_led_off.base.x2+LED_COLOR_BUTTON_SPACING;
b_led_white.base.y1=LED_COLOR_BUTTON_Y-3;
b_led_white.base.x2=AUTO;
b_led_white.base.y2=AUTO;
b_led_white.txtcolor=BLACK;
b_led_white.bgcolor=HEX(0xEEEEEE);
b_led_white.font=0;
b_led_white.text="White";
b_led_white.callback=b_led_white_cb;
gui_button_add(&b_led_white);
b_led_white.base.x1 = b_led_off.base.x2 + LED_COLOR_BUTTON_SPACING;
b_led_white.base.y1 = LED_COLOR_BUTTON_Y - 3;
b_led_white.base.x2 = AUTO;
b_led_white.base.y2 = AUTO;
b_led_white.txtcolor = BLACK;
b_led_white.bgcolor = HEX(0xEEEEEE);
b_led_white.font = 0;
b_led_white.text = "White";
b_led_white.callback = b_led_white_cb;
gui_button_add(&b_led_white);
b_led_red.base.x1=b_led_white.base.x2+LED_COLOR_BUTTON_SPACING;
b_led_red.base.y1=LED_COLOR_BUTTON_Y-3;
b_led_red.base.x2=AUTO;
b_led_red.base.y2=AUTO;
b_led_red.txtcolor=WHITE;
b_led_red.bgcolor=HEX(0xEE0000);
b_led_red.font=0;
b_led_red.text="Red";
b_led_red.callback=b_led_red_cb;
gui_button_add(&b_led_red);
b_led_red.base.x1 = b_led_white.base.x2 + LED_COLOR_BUTTON_SPACING;
b_led_red.base.y1 = LED_COLOR_BUTTON_Y - 3;
b_led_red.base.x2 = AUTO;
b_led_red.base.y2 = AUTO;
b_led_red.txtcolor = WHITE;
b_led_red.bgcolor = HEX(0xEE0000);
b_led_red.font = 0;
b_led_red.text = "Red";
b_led_red.callback = b_led_red_cb;
gui_button_add(&b_led_red);
b_led_green.base.x1=b_led_red.base.x2+LED_COLOR_BUTTON_SPACING;
b_led_green.base.y1=LED_COLOR_BUTTON_Y-3;
b_led_green.base.x2=AUTO;
b_led_green.base.y2=AUTO;
b_led_green.txtcolor=WHITE;
b_led_green.bgcolor=HEX(0x00EE00);
b_led_green.font=0;
b_led_green.text="Green";
b_led_green.callback=b_led_green_cb;
gui_button_add(&b_led_green);
b_led_green.base.x1 = b_led_red.base.x2 + LED_COLOR_BUTTON_SPACING;
b_led_green.base.y1 = LED_COLOR_BUTTON_Y - 3;
b_led_green.base.x2 = AUTO;
b_led_green.base.y2 = AUTO;
b_led_green.txtcolor = WHITE;
b_led_green.bgcolor = HEX(0x00EE00);
b_led_green.font = 0;
b_led_green.text = "Green";
b_led_green.callback = b_led_green_cb;
gui_button_add(&b_led_green);
b_led_blue.base.x1=b_led_green.base.x2+LED_COLOR_BUTTON_SPACING;
b_led_blue.base.y1=LED_COLOR_BUTTON_Y-3;
b_led_blue.base.x2=AUTO;
b_led_blue.base.y2=AUTO;
b_led_blue.txtcolor=WHITE;
b_led_blue.bgcolor=HEX(0x0000EE);
b_led_blue.font=0;
b_led_blue.text="Blue";
b_led_blue.callback=b_led_blue_cb;
gui_button_add(&b_led_blue);
b_led_blue.base.x1 = b_led_green.base.x2 + LED_COLOR_BUTTON_SPACING;
b_led_blue.base.y1 = LED_COLOR_BUTTON_Y - 3;
b_led_blue.base.x2 = AUTO;
b_led_blue.base.y2 = AUTO;
b_led_blue.txtcolor = WHITE;
b_led_blue.bgcolor = HEX(0x0000EE);
b_led_blue.font = 0;
b_led_blue.text = "Blue";
b_led_blue.callback = b_led_blue_cb;
gui_button_add(&b_led_blue);
//Led MaxPower stuff
#define LED_POWER_BUTTON_Y 70
tft_print_line(5,LED_POWER_BUTTON_Y,BLACK,TRANSPARENT,0,"Led Maximum Current:");
//Led MaxPower stuff
#define LED_POWER_BUTTON_Y 70
tft_print_line(5, LED_POWER_BUTTON_Y, BLACK, TRANSPARENT, 0, "Led Maximum Current:");
//Num up down test
n_led_powerlimit.x=160;
n_led_powerlimit.y=LED_POWER_BUTTON_Y-7;
n_led_powerlimit.fgcolor=WHITE;
n_led_powerlimit.value = 10;
n_led_powerlimit.max=40;
n_led_powerlimit.min =0;
n_led_powerlimit.callback=n_led_powerlimit_cb;
gui_numupdown_add(&n_led_powerlimit);
//Num up down test
n_led_powerlimit.x = 160;
n_led_powerlimit.y = LED_POWER_BUTTON_Y - 7;
n_led_powerlimit.fgcolor = WHITE;
n_led_powerlimit.value = 10;
n_led_powerlimit.max = 40;
n_led_powerlimit.min = 0;
n_led_powerlimit.callback = n_led_powerlimit_cb;
gui_numupdown_add(&n_led_powerlimit);
state=detecting;
state = detecting;
}
static void leave(void* screen) {
gui_button_remove(&b_back);
gui_button_remove(&b_servos_center);
gui_button_remove(&b_servos_topleft);
gui_button_remove(&b_servos_topright);
gui_button_remove(&b_servos_bottomleft);
gui_button_remove(&b_servos_bottomright);
gui_button_remove(&b_led_off);
gui_button_remove(&b_led_white);
gui_button_remove(&b_led_red);
gui_button_remove(&b_led_green);
gui_button_remove(&b_led_blue);
gui_numupdown_remove(&n_led_powerlimit);
static void leave(void* screen)
{
gui_button_remove(&b_back);
gui_button_remove(&b_servos_center);
gui_button_remove(&b_servos_topleft);
gui_button_remove(&b_servos_topright);
gui_button_remove(&b_servos_bottomleft);
gui_button_remove(&b_servos_bottomright);
gui_button_remove(&b_led_off);
gui_button_remove(&b_led_white);
gui_button_remove(&b_led_red);
gui_button_remove(&b_led_green);
gui_button_remove(&b_led_blue);
gui_numupdown_remove(&n_led_powerlimit);
}
static void update(void* screen) {
switch(state) {
case detecting: //Detecting State: Where we try to connect to the pixy
if(pixy_init()==0) { //Pixy connection ok
int32_t response;
int return_value;
return_value = pixy_command("stop", END_OUT_ARGS, &response, END_IN_ARGS);
pixy_led_set_max_current(10);
static void update(void* screen)
{
switch (state) {
case detecting: //Detecting State: Where we try to connect to the pixy
if (pixy_init() == 0) { //Pixy connection ok
int32_t response;
int return_value;
return_value = pixy_command("stop", END_OUT_ARGS, &response, END_IN_ARGS);
pixy_led_set_max_current(10);
state = idle; //Go to next state
}
break;
case idle:
pixy_service();
break;
case update_servos:
pixy_rcs_set_position(0,servo_x);
pixy_rcs_set_position(1,servo_y);
state = idle;
break;
state = idle; //Go to next state
}
case update_ledcolor:
{
int32_t response;
int return_value;
return_value = pixy_command("led_set", INT32(led_color), END_OUT_ARGS, &response, END_IN_ARGS);
state = idle;
}
break;
break;
case update_ledcurrent:
pixy_led_set_max_current(led_maxcurrent);
state = idle;
break;
}
case idle:
pixy_service();
break;
case update_servos:
pixy_rcs_set_position(0, servo_x);
pixy_rcs_set_position(1, servo_y);
state = idle;
break;
case update_ledcolor: {
int32_t response;
int return_value;
return_value = pixy_command("led_set", INT32(led_color), END_OUT_ARGS, &response, END_IN_ARGS);
state = idle;
}
break;
case update_ledcurrent:
pixy_led_set_max_current(led_maxcurrent);
state = idle;
break;
}
}
static SCREEN_STRUCT screen = {
enter,
leave,
update
enter,
leave,
update
};
SCREEN_STRUCT* get_screen_pixytest() {
return &screen;
SCREEN_STRUCT* get_screen_pixytest()
{
return &screen;
}

View File

@@ -1,3 +1,18 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/app/screen_pixytest.h
*
* Version History:
* Date Autor Email SHA Changes
* 2015-04-27 timolang@gmail.com cf72baa Introduced a Screen (sub) module and divided app into multiple screens.
* 2015-05-10 timolang@gmail.com 21edc56 Added doxyfile (doxygen) for the common folder. Started with doxygen comments for app and tft module.
* 2015-05-15 timolang@gmail.com 9a16865 Added doxgen comments to filesyste, checkbox, numupdown and screen module. And some minor changes to the other modules.
*
**************************************************************************************************************************************/
#include "screen.h"
/**

View File

@@ -1,3 +1,22 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/app/screen_tracking.c
*
* Version History:
* Date Autor Email SHA Changes
* 2015-05-16 timolang@gmail.com e46314b Added Tracking Screen and implemented "Reference Tracking" and "Color Region Selection"
* 2015-05-25 timolang@gmail.com 8088014 Updated Tracking Screen so that the implementations are separated into different method groups.
* 2015-06-06 aaron@duckpond.ch 8c264c2 Comment refactoring, updated PID values
* 2015-06-06 aaron@duckpond.ch a04cda9 Refactured comments and implemented a bugfix for the PID controller
* 2015-06-07 aaron@duckpond.ch 802d3df Fixed pid controller and refactored code
* 2015-06-07 aaron@duckpond.ch 3d98ca9 Minor changes
* 2015-06-07 timolang@gmail.com c87220d Renamed pixy_helper to pixy_frame. Updated docu of appliaction. added doxygen comments to pixy_{frame,control}.h
*
**************************************************************************************************************************************/
#include "screen_tracking.h"
#include "pixy_control.h"
#include "button.h"
@@ -14,14 +33,16 @@ static CHECKBOX_STRUCT c_frame_toggle; //Checkbox to toggle video data on/off
static TOUCH_AREA_STRUCT a_area; //Touch area for the color region selection
//Callback for when the user presses the "back" button
static void b_back_cb(void* button) {
gui_screen_back(); //navigate back to the previous screen
static void b_back_cb(void* button)
{
gui_screen_back(); //navigate back to the previous screen
}
static volatile bool frame_visible = false; //Whether or not the video data should be displayed
static void c_frame_toggle_cb(void *checkbox, bool checked) {
frame_visible=checked; //Set the visibility of the frame to the checked state of the checkbox
//Frame will be drawn in the main loop below
static void c_frame_toggle_cb(void* checkbox, bool checked)
{
frame_visible = checked; //Set the visibility of the frame to the checked state of the checkbox
//Frame will be drawn in the main loop below
}
static enum {detecting, init, tracking, preselecting, abortselecting, selecting, selected, error} state; //Current state of the screen state machine
@@ -31,12 +52,13 @@ static POINT_STRUCT point2; //End point of the rectangle selected by the user (c
static bool point1_valid; //Whether or not we have a valid first point
//Callback for when the user presses the "select color" button
static void b_select_cb(void* button) {
if(state==selecting) { //we're currently selecting a color region
state = abortselecting; //Abort selecting!!
} else if (state==tracking) { //we're currently watching the tracking
state = preselecting; //start selecting
}
static void b_select_cb(void* button)
{
if (state == selecting) { //we're currently selecting a color region
state = abortselecting; //Abort selecting!!
} else if (state == tracking) { //we're currently watching the tracking
state = preselecting; //start selecting
}
}
//Video Region properties
@@ -50,34 +72,38 @@ static void b_select_cb(void* button) {
//Callback for when the user touches the frame area to select a color region.
//Note: It doesn't matter in which direction the user draws the rectangle, we'll normalize the coordinates later
static void touchCB(void* touchArea, TOUCH_ACTION triggeredAction) {
POINT_STRUCT p = touch_get_last_point();
switch(triggeredAction) {
case PEN_DOWN: //The user just put down the pen
point1.x = p.x-FRAME_START_X; //Calculate x-Coordinate relative to frame start
point1.y = p.y-FRAME_START_Y; //Calculate y-Coordinate relative to frame start
point1_valid= true; //The point1 is now valid
break;
case PEN_UP: //The user took the pen away
if(point1_valid) { //only execute if point1 is valid
point2.x = p.x-FRAME_START_X; //Calculate x-Coordinate relative to frame start
point2.y = p.y-FRAME_START_Y; //Calculate y-Coordinate relative to frame start
state = selected;
}
break;
}
static void touchCB(void* touchArea, TOUCH_ACTION triggeredAction)
{
POINT_STRUCT p = touch_get_last_point();
switch (triggeredAction) {
case PEN_DOWN: //The user just put down the pen
point1.x = p.x - FRAME_START_X; //Calculate x-Coordinate relative to frame start
point1.y = p.y - FRAME_START_Y; //Calculate y-Coordinate relative to frame start
point1_valid = true; //The point1 is now valid
break;
case PEN_UP: //The user took the pen away
if (point1_valid) { //only execute if point1 is valid
point2.x = p.x - FRAME_START_X; //Calculate x-Coordinate relative to frame start
point2.y = p.y - FRAME_START_Y; //Calculate y-Coordinate relative to frame start
state = selected;
}
break;
}
}
//Prototype for tracking start/stop methods
typedef void (*TRACKING_VOID_CALLBACK)(void* tracking_config);
//Prototype for tracking update method
typedef void (*TRACKING_BLOCK_CALLBACK)(void* tracking_config, struct Block* blocks, int num_blocks );
typedef void (*TRACKING_BLOCK_CALLBACK)(void* tracking_config, struct Block* blocks, int num_blocks);
//Structure to save callbacks and settings of a tracking implementation
typedef struct {
TRACKING_VOID_CALLBACK start;
TRACKING_VOID_CALLBACK stop;
TRACKING_BLOCK_CALLBACK update;
TRACKING_VOID_CALLBACK start;
TRACKING_VOID_CALLBACK stop;
TRACKING_BLOCK_CALLBACK update;
} TRACKING_CONFIG_STRUCT;
//Methods for our tracking implementation ahead
@@ -85,45 +111,48 @@ static int16_t servo_x = 0;
static int16_t servo_y = 0;
//Method/Callback to start our tracking
void tracking_our_start(void* tracking_config) {
//Activate pixy's data send program
int32_t response;
int return_value;
void tracking_our_start(void* tracking_config)
{
//Activate pixy's data send program
int32_t response;
int return_value;
servo_x = servo_y = 500; // set a default value of 500
pixy_rcs_set_position(0, servo_x); // set default
pixy_rcs_set_position(0, servo_x); // set default
pixy_rcs_set_position(1, servo_y); // set default
return_value = pixy_command("runprog", INT8(0), END_OUT_ARGS, &response, END_IN_ARGS);
return_value = pixy_command("runprog", INT8(0), END_OUT_ARGS, &response, END_IN_ARGS);
}
//Method/Callback to stop our tracking
void tracking_our_stop(void* tracking_config) {
//Stop pixy's data send programm
int32_t response;
int return_value;
return_value = pixy_command("stop", END_OUT_ARGS, &response, END_IN_ARGS);
void tracking_our_stop(void* tracking_config)
{
//Stop pixy's data send programm
int32_t response;
int return_value;
return_value = pixy_command("stop", END_OUT_ARGS, &response, END_IN_ARGS);
}
//Method/Callback to calculate one step of our tracking
void tracking_our_update(void* tracking_config, struct Block* blocks, int num_blocks) {
void tracking_our_update(void* tracking_config, struct Block* blocks, int num_blocks)
{
if(num_blocks <= 0){ // Check if there are blocks available
if (num_blocks <= 0) { // Check if there are blocks available
return; // When there are none, do nothing
}
uint16_t x = blocks[0].x; // Get x coordinate of the biggest object
uint16_t y = blocks[0].y; // Get y coordinate of the biggest object
int16_t xset = 0;
int16_t xset = 0;
int16_t yset = 0;
xset = (servo_x + pixy_PID_X((FRAME_WIDTH / 2), x)); // calculate the PID output for x
yset = (servo_y - pixy_PID_Y((FRAME_HEIGHT / 2), y)); // calculate the PID output for y
xset = (xset < 0) ? 0 : xset; // x lower boundary check
xset = (xset > 1000) ? 1000 : xset; // x upper boundary check
yset = (yset < 0) ? 0 : yset; // y lower boundary check
yset = (yset > 1000) ? 1000 : yset; // y upper boundary check
@@ -136,245 +165,257 @@ void tracking_our_update(void* tracking_config, struct Block* blocks, int num_bl
//Variable which stores all the callbacks and settings for our tracking implementation
static TRACKING_CONFIG_STRUCT tracking_our = {
tracking_our_start,
tracking_our_stop,
tracking_our_update
tracking_our_start,
tracking_our_stop,
tracking_our_update
};
//Methods for reference tracking implementation ahead
//Method/Callback to start reference tracking
void tracking_reference_start(void* tracking_config) {
//Run reference tracking
int32_t response;
int return_value;
return_value = pixy_command("runprog", INT8(2), END_OUT_ARGS, &response, END_IN_ARGS);
void tracking_reference_start(void* tracking_config)
{
//Run reference tracking
int32_t response;
int return_value;
return_value = pixy_command("runprog", INT8(2), END_OUT_ARGS, &response, END_IN_ARGS);
}
//Method/Callback to stop reference tracking
void tracking_reference_stop(void* tracking_config) {
//Stop reference tracking
int32_t response;
int return_value;
return_value = pixy_command("stop", END_OUT_ARGS, &response, END_IN_ARGS);
void tracking_reference_stop(void* tracking_config)
{
//Stop reference tracking
int32_t response;
int return_value;
return_value = pixy_command("stop", END_OUT_ARGS, &response, END_IN_ARGS);
}
//Method/Callback to calculate one step of the reference tracking
void tracking_reference_update(void* tracking_config, struct Block* blocks, int num_blocks) {
//Nothing to do here. Pixy does it all.
void tracking_reference_update(void* tracking_config, struct Block* blocks, int num_blocks)
{
//Nothing to do here. Pixy does it all.
}
//Variable which stores all the callbacks and settings for the reference tracking implementation
static TRACKING_CONFIG_STRUCT tracking_reference = {
tracking_reference_start,
tracking_reference_stop,
tracking_reference_update
tracking_reference_start,
tracking_reference_stop,
tracking_reference_update
};
//Pointer to the currently active tracking implementation. See also tracking_set_mode
static TRACKING_CONFIG_STRUCT* tracking_current;
//Method to set the current tracking implementation. This function is exported and should be called before getting the screen
void tracking_set_mode(enum Tracking_Implementation impl) {
//Depending on the enum value let tracking_current point to a different setting/callback structure
switch(impl) {
case OUR_TRACKING:
tracking_current = &tracking_our;
break;
case REFERENCE_TRACKING:
tracking_current = &tracking_reference;
break;
default:
tracking_current=NULL;
break;
}
void tracking_set_mode(enum Tracking_Implementation impl)
{
//Depending on the enum value let tracking_current point to a different setting/callback structure
switch (impl) {
case OUR_TRACKING:
tracking_current = &tracking_our;
break;
case REFERENCE_TRACKING:
tracking_current = &tracking_reference;
break;
default:
tracking_current = NULL;
break;
}
}
//Callback for when the screen is entered/loaded
static void enter(void* screen) {
tft_clear(WHITE);
//"Back" button
b_back.base.x1=5; //Start X of Button
b_back.base.y1=5; //Start Y of Button
b_back.base.x2=AUTO; //Auto Calculate X2 with String Width
b_back.base.y2=AUTO; //Auto Calculate Y2 with String Height
b_back.txtcolor=WHITE; //Set foreground color
b_back.bgcolor=HEX(0xAE1010); //Set background color (Don't take 255 or 0 on at least one channel, to make shadows possible)
b_back.font=0; //Select Font
b_back.text="Back"; //Set Text (For formatted strings take sprintf)
b_back.callback=b_back_cb; //Call b_back_cb as Callback
gui_button_add(&b_back); //Register Button (and run the callback from now on)
static void enter(void* screen)
{
tft_clear(WHITE);
//"Back" button
b_back.base.x1 = 5; //Start X of Button
b_back.base.y1 = 5; //Start Y of Button
b_back.base.x2 = AUTO; //Auto Calculate X2 with String Width
b_back.base.y2 = AUTO; //Auto Calculate Y2 with String Height
b_back.txtcolor = WHITE; //Set foreground color
b_back.bgcolor = HEX(0xAE1010); //Set background color (Don't take 255 or 0 on at least one channel, to make shadows possible)
b_back.font = 0; //Select Font
b_back.text = "Back"; //Set Text (For formatted strings take sprintf)
b_back.callback = b_back_cb; //Call b_back_cb as Callback
gui_button_add(&b_back); //Register Button (and run the callback from now on)
//"Select color" button
b_select.base.x1=150;
b_select.base.y1=5;
b_select.base.x2=AUTO;
b_select.base.y2=AUTO;
b_select.txtcolor=WHITE;
b_select.bgcolor=HEX(0xAE1010);
b_select.font=0;
b_select.text="Select Color";
b_select.callback=b_select_cb;
gui_button_add(&b_select);
//"Select color" button
b_select.base.x1 = 150;
b_select.base.y1 = 5;
b_select.base.x2 = AUTO;
b_select.base.y2 = AUTO;
b_select.txtcolor = WHITE;
b_select.bgcolor = HEX(0xAE1010);
b_select.font = 0;
b_select.text = "Select Color";
b_select.callback = b_select_cb;
gui_button_add(&b_select);
//"Frame visible" checkbox
c_frame_toggle.base.x1 = 50;
c_frame_toggle.base.x2 = 50+16;
c_frame_toggle.base.y1 = 5;
c_frame_toggle.base.y2 = 5+16;
c_frame_toggle.checked = frame_visible;
c_frame_toggle.fgcolor = CHECKBOX_WIN_FG_COLOR;
c_frame_toggle.callback = c_frame_toggle_cb;
gui_checkbox_add(&c_frame_toggle);
tft_print_line(73,8,BLACK,TRANSPARENT,0,"Show Video");
//"Frame visible" checkbox
c_frame_toggle.base.x1 = 50;
c_frame_toggle.base.x2 = 50 + 16;
c_frame_toggle.base.y1 = 5;
c_frame_toggle.base.y2 = 5 + 16;
c_frame_toggle.checked = frame_visible;
c_frame_toggle.fgcolor = CHECKBOX_WIN_FG_COLOR;
c_frame_toggle.callback = c_frame_toggle_cb;
gui_checkbox_add(&c_frame_toggle);
tft_print_line(73, 8, BLACK, TRANSPARENT, 0, "Show Video");
//Area to select a "color region"
a_area.hookedActions = PEN_DOWN | PEN_UP;
a_area.x1 = FRAME_START_X;
a_area.y1 = FRAME_START_Y;
a_area.x2 = FRAME_END_X;
a_area.y2 = FRAME_END_Y;
a_area.callback = touchCB;
//Area to select a "color region"
a_area.hookedActions = PEN_DOWN | PEN_UP;
a_area.x1 = FRAME_START_X;
a_area.y1 = FRAME_START_Y;
a_area.x2 = FRAME_END_X;
a_area.y2 = FRAME_END_Y;
a_area.callback = touchCB;
//Do not register it here, we do that later
if(tracking_current==NULL) {
state = error;
} else {
state = detecting; //Start with the detecting state
}
if (tracking_current == NULL) {
state = error;
} else {
state = detecting; //Start with the detecting state
}
}
//Callback for when the screen is left/unloaded
static void leave(void* screen) {
//Remove buttons and checkbox
gui_button_remove(&b_back);
gui_button_remove(&b_select);
gui_checkbox_remove(&c_frame_toggle);
static void leave(void* screen)
{
//Remove buttons and checkbox
gui_button_remove(&b_back);
gui_button_remove(&b_select);
gui_checkbox_remove(&c_frame_toggle);
if(state==selecting) { //the user left the screen in the "selecting" phase
touch_unregister_area(&a_area); //remove the touch area
}
if (state == selecting) { //the user left the screen in the "selecting" phase
touch_unregister_area(&a_area); //remove the touch area
}
if(state==tracking) { //the user left the screen in the "tracking" phase
tracking_current->stop(tracking_current); //stop tracking
pixy_led_set_RGB(0,0,0);
}
if (state == tracking) { //the user left the screen in the "tracking" phase
tracking_current->stop(tracking_current); //stop tracking
pixy_led_set_RGB(0, 0, 0);
}
}
//Callback for when the screen should be updated
//This is the main loop of the screen. This method will be called repeatedly
static void update(void* screen) {
switch(state) {
case detecting: //Detecting State: Where we try to connect to the pixy
if(pixy_init()==0) { //Pixy connection ok
state = init; //Go to next state
}
break;
static void update(void* screen)
{
switch (state) {
case detecting: //Detecting State: Where we try to connect to the pixy
if (pixy_init() == 0) { //Pixy connection ok
state = init; //Go to next state
}
case init: //Init State: Where we start the tracking
tracking_current->start(tracking_current);
state=tracking;
break;
break;
case tracking: //Tracking state: Where we render the frame and the tracked objects
pixy_service(); //Receive events (e.g. block-data) from pixy
case init: //Init State: Where we start the tracking
tracking_current->start(tracking_current);
state = tracking;
break;
if(pixy_blocks_are_new()) { //There are new blocks available
if(frame_visible) { //If the user want's us to draw the video data
pixy_render_full_frame(FRAME_START_X,FRAME_START_Y);
} else { //the user want's a colored background
tft_fill_rectangle(FRAME_START_X,FRAME_START_Y,FRAME_END_X,FRAME_END_Y,RGB(200,200,200));
}
case tracking: //Tracking state: Where we render the frame and the tracked objects
pixy_service(); //Receive events (e.g. block-data) from pixy
#define BLOCK_BUFFER_SIZE 5 //The maximum amount of blocks that we want to receive
struct Block blocks[BLOCK_BUFFER_SIZE]; //Storage to receive blocks from pixy
int blocks_received= pixy_get_blocks(BLOCK_BUFFER_SIZE,blocks); //Try to receive up to BLOCK_BUFFER_SIZE Blocks from pixy
if (pixy_blocks_are_new()) { //There are new blocks available
if (frame_visible) { //If the user want's us to draw the video data
pixy_render_full_frame(FRAME_START_X, FRAME_START_Y);
} else { //the user want's a colored background
tft_fill_rectangle(FRAME_START_X, FRAME_START_Y, FRAME_END_X, FRAME_END_Y, RGB(200, 200, 200));
}
if(blocks_received>=0) { //block receiving ok
tracking_current->update(tracking_current,blocks,blocks_received); //apply tracking
#define BLOCK_BUFFER_SIZE 5 //The maximum amount of blocks that we want to receive
struct Block blocks[BLOCK_BUFFER_SIZE]; //Storage to receive blocks from pixy
int blocks_received = pixy_get_blocks(BLOCK_BUFFER_SIZE, blocks); //Try to receive up to BLOCK_BUFFER_SIZE Blocks from pixy
//Draw blocks
for(int i=0; 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;
if (blocks_received >= 0) { //block receiving ok
tracking_current->update(tracking_current, blocks, blocks_received); //apply tracking
case preselecting: //Pre-Selecting State: Where we set up the color region selection
{
tracking_current->stop(tracking_current); //Stop tracking
//Draw blocks
for (int i = 0; i < blocks_received; i++) { //for each received block
struct Block* block = &(blocks[i]);
//block.x and block.y are the center coordinates of the object relative to the camera origin.
uint16_t x = block->x - 1 + FRAME_START_X - block->width / 2; //Calculate x-Coordinate on the display
uint16_t y = block->y - 1 + FRAME_START_Y - block->height / 2; //Calculate y-Coordinate on the display
tft_draw_rectangle(x, y, x + block->width - 1, y + block->height - 1, WHITE); //Draw a white rectangle
}
}
}
pixy_render_full_frame(FRAME_START_X,FRAME_START_Y); //Render one frame
break;
touch_register_area(&a_area); //Register touch area and receive events from now on
point1_valid=false; //we start with an invalid point1
case preselecting: { //Pre-Selecting State: Where we set up the color region selection
tracking_current->stop(tracking_current); //Stop tracking
b_select.text="Abort"; //Change the button text to "Abort"
gui_button_redraw(&b_select); //redraw button
pixy_render_full_frame(FRAME_START_X, FRAME_START_Y); //Render one frame
state = selecting; //The user can now select a region
}
break;
touch_register_area(&a_area); //Register touch area and receive events from now on
point1_valid = false; //we start with an invalid point1
case selected: //Selected State: Where we send the users selection to pixy
{
//Ensure that (x1,y1) represent the top-left point and (x2,y2) the bottom-right.
unsigned int tmp;
if(point1.x > point2.x){
tmp = point1.x;
point1.x = point2.x;
point2.x = tmp;
}
b_select.text = "Abort"; //Change the button text to "Abort"
gui_button_redraw(&b_select); //redraw button
if(point1.y > point2.y){
tmp = point1.y;
point1.y = point2.y;
point2.y = tmp;
}
//Send pixy the selected region
pixy_cc_set_region(1,point1.x,point1.y,point2.x-point1.x,point2.y-point1.y);
}
//no break here: We want the following code to be executed as well
state = selecting; //The user can now select a region
}
break;
case abortselecting: //Abort-Selecting State: Where we deinitialize the stuff we used for region selection
{
touch_unregister_area(&a_area); //Remove the touch area. We'll no longer receive touch events
case selected: { //Selected State: Where we send the users selection to pixy
//Ensure that (x1,y1) represent the top-left point and (x2,y2) the bottom-right.
unsigned int tmp;
b_select.text="Select Color"; //Change the button text back to "Select Color"
gui_button_redraw(&b_select); //redraw button
if (point1.x > point2.x) {
tmp = point1.x;
point1.x = point2.x;
point2.x = tmp;
}
tracking_current->start(tracking_current); //Start tracking again
state=tracking;
}
break;
if (point1.y > point2.y) {
tmp = point1.y;
point1.y = point2.y;
point2.y = tmp;
}
case selecting: //Selecting State: Where we wait on the user to select a color region
pixy_service(); //receive pixy events
//wait on user to select the image area
break;
//Send pixy the selected region
pixy_cc_set_region(1, point1.x, point1.y, point2.x - point1.x, point2.y - point1.y);
}
case error: //Error State: Where we show an error message and leave the user no other choice than to click the backbutton
//wait on user to click the back button
break;
}
//no break here: We want the following code to be executed as well
case abortselecting: { //Abort-Selecting State: Where we deinitialize the stuff we used for region selection
touch_unregister_area(&a_area); //Remove the touch area. We'll no longer receive touch events
b_select.text = "Select Color"; //Change the button text back to "Select Color"
gui_button_redraw(&b_select); //redraw button
tracking_current->start(tracking_current); //Start tracking again
state = tracking;
}
break;
case selecting: //Selecting State: Where we wait on the user to select a color region
pixy_service(); //receive pixy events
//wait on user to select the image area
break;
case error: //Error State: Where we show an error message and leave the user no other choice than to click the backbutton
//wait on user to click the back button
break;
}
}
//Declare screen callbacks
static SCREEN_STRUCT screen = {
enter,
leave,
update
enter,
leave,
update
};
SCREEN_STRUCT* get_screen_tracking() {
return &screen;
SCREEN_STRUCT* get_screen_tracking()
{
return &screen;
}

View File

@@ -1,3 +1,16 @@
/**************************************************************************************************************************************
* Project: discoverpixy
* Website: https://github.com/t-moe/discoverpixy
* Authors: Aaron Schmocker, Timo Lang
* Institution: BFH Bern University of Applied Sciences
* File: common/app/screen_tracking.h
*
* Version History:
* Date Autor Email SHA Changes
* 2015-05-16 timolang@gmail.com e46314b Added Tracking Screen and implemented "Reference Tracking" and "Color Region Selection"
*
**************************************************************************************************************************************/
#include "screen.h"
/**
@@ -16,8 +29,8 @@
* Enum which contains the available tracking implementations
*/
enum Tracking_Implementation {
OUR_TRACKING, //!< Our own tracking PID implementation
REFERENCE_TRACKING//!< Pixy's internal tracking implementation
OUR_TRACKING, //!< Our own tracking PID implementation
REFERENCE_TRACKING//!< Pixy's internal tracking implementation
};
/**