diff --git a/common/app/app.c b/common/app/app.c index cd593d7..6f6ee19 100644 --- a/common/app/app.c +++ b/common/app/app.c @@ -2,7 +2,7 @@ #include "tft.h" #include "system.h" #include "touch.h" -#include "screen_guitest.h" +#include "screen_main.h" #include "filesystem.h" void app_init() { @@ -11,7 +11,7 @@ void app_init() { touch_init(); filesystem_init(); - gui_screen_navigate(get_screen_guitest()); + gui_screen_navigate(get_screen_main()); } diff --git a/common/app/pixy_helper.c b/common/app/pixy_helper.c new file mode 100644 index 0000000..c4787a9 --- /dev/null +++ b/common/app/pixy_helper.c @@ -0,0 +1,140 @@ +#include "pixy_helper.h" +#include "pixy.h" +#include "tft.h" +#include + + + +static int renderBA81(uint16_t xpos, uint16_t ypos, 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; +} + + + + +static void interpolateBayer(uint16_t width, uint16_t x, uint16_t y, uint8_t *pixel, uint8_t* r, uint8_t* g, uint8_t* b) +{ + if (y&1) + { + if (x&1) + { + *r = *pixel; + *g = (*(pixel-1)+*(pixel+1)+*(pixel+width)+*(pixel-width))>>2; + *b = (*(pixel-width-1)+*(pixel-width+1)+*(pixel+width-1)+*(pixel+width+1))>>2; + } + else + { + *r = (*(pixel-1)+*(pixel+1))>>1; + *g = *pixel; + *b = (*(pixel-width)+*(pixel+width))>>1; + } + } + else + { + if (x&1) + { + *r = (*(pixel-width)+*(pixel+width))>>1; + *g = *pixel; + *b = (*(pixel-1)+*(pixel+1))>>1; + } + else + { + *r = (*(pixel-width-1)+*(pixel-width+1)+*(pixel+width-1)+*(pixel+width+1))>>2; + *g = (*(pixel-1)+*(pixel+1)+*(pixel+width)+*(pixel-width))>>2; + *b = *pixel; + } + } + +} + + + + + + +static int renderBA81(uint16_t xpos, uint16_t ypos, uint16_t width, uint16_t height, uint32_t frameLen, uint8_t *frame) +{ + uint16_t x, y; + uint8_t r, g, b; + + + // skip first line + frame += width; + + // don't render top and bottom rows, and left and rightmost columns because of color + // interpolation + //uint32_t decodedimage[(width-2)*(height-2)]; + uint16_t* decodedimage = malloc(sizeof(uint16_t)*(width-2)*(height-2)); + + if(decodedimage==NULL) { //not enough free space to decode image in memory + //decode & render image pixel by pixel + uint16_t* line = decodedimage; + for (y=1; y +#include + +int pixy_render_full_frame(uint16_t x, uint16_t y); +int pixy_render_cropped_frame(uint16_t x, uint16_t y, uint16_t xoffset, uint16_t yoffset, uint16_t width, uint16_t height); + +#endif /* PIXY_HELPER_H */ diff --git a/common/app/screen_main.c b/common/app/screen_main.c index 6baebfe..bdf089d 100644 --- a/common/app/screen_main.c +++ b/common/app/screen_main.c @@ -2,13 +2,32 @@ #include "screen_guitest.h" #include "screen_pixytest.h" #include "screen_filetest.h" +#include "screen_photomode.h" #include "button.h" #include "tft.h" +#include "filesystem.h" BUTTON_STRUCT b_guitest; BUTTON_STRUCT b_pixytest; BUTTON_STRUCT b_filetest; +BUTTON_STRUCT b_our_tracking; +BUTTON_STRUCT b_ref_tracking; +BUTTON_STRUCT b_photo_mode; + + +static void b_our_tracking_cb(void* button) { + +} + +static void b_ref_tracking_cb(void* button) { + +} + +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()); } @@ -25,47 +44,108 @@ static void b_pixytest_cb(void* button) { static void enter(void* screen) { tft_clear(WHITE); - //button to reach guitest - b_guitest.base.x1=25; //Start X of Button - b_guitest.base.y1=45; //Start Y of Button - b_guitest.base.x2=AUTO; //b_guitest.base.x1+160; //Auto Calculate X2 with String Width - b_guitest.base.y2=AUTO; //Auto Calculate Y2 with String Height - b_guitest.txtcolor=WHITE; //Set foreground color - b_guitest.bgcolor=HEX(0xDE1010); //Set background color (Don't take 255 or 0 on at least one channel, to make shadows possible) - b_guitest.font=0; //Select Font - b_guitest.text="Gui/Tft Test"; //Set Text (For formatted strings take sprintf) - b_guitest.callback=b_guitest_cb; //Call b_guitest_cb as Callback - gui_button_add(&b_guitest); //Register Button (and run the callback from now on) + //Heading + tft_print_line(10,10,BLUE,TRANSPARENT,1,"Discoverpixy"); + tft_draw_line(0,40,319,40,BLACK); - //button to reach pixy test - b_pixytest.base.x1=150; //Start X of Button - b_pixytest.base.y1=45; //Start Y of Button - b_pixytest.base.x2=AUTO; //b_pixytest.base.x1+160; //Auto Calculate X2 with String Width - b_pixytest.base.y2=AUTO; //Auto Calculate Y2 with String Height - b_pixytest.txtcolor=BLUE; //Set foreground color - b_pixytest.bgcolor=HEX(0x10DE10); //Set background color (Don't take 255 or 0 on at least one channel, to make shadows possible) - b_pixytest.font=0; //Select Font - b_pixytest.text="Pixy Test"; //Set Text (For formatted strings take sprintf) - b_pixytest.callback=b_pixytest_cb; //Call b_pixytest_cb as Callback - gui_button_add(&b_pixytest); //Register Button (and run the callback from now on) + #define X_TAB 90 + #define BUTTON_SPACING 7 - //button to reach filesystem test - b_filetest.base.x1=240; //Start X of Button - b_filetest.base.y1=45; //Start Y of Button - b_filetest.base.x2=AUTO; //b_filetest.base.x1+160; //Auto Calculate X2 with String Width - b_filetest.base.y2=AUTO; //Auto Calculate Y2 with String Height - b_filetest.txtcolor=WHITE; //Set foreground color - b_filetest.bgcolor=HEX(0x501EA0); //Set background color (Don't take 255 or 0 on at least one channel, to make shadows possible) - b_filetest.font=0; //Select Font - b_filetest.text="File Test"; //Set Text (For formatted strings take sprintf) - b_filetest.callback=b_filetest_cb; //Call b_filetest_cb as Callback - gui_button_add(&b_filetest); //Register Button (and run the callback from now on) + //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_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="Reference 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:"); + + 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:"); + + 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 Test"; + 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 Test"; + 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 Test"; + 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"); } 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); diff --git a/common/app/screen_photomode.c b/common/app/screen_photomode.c new file mode 100644 index 0000000..60718da --- /dev/null +++ b/common/app/screen_photomode.c @@ -0,0 +1,133 @@ +#include "screen_photomode.h" +#include "button.h" +#include "tft.h" +#include "touch.h" +#include "pixy.h" +#include "pixy_helper.h" +#include "system.h" + +static volatile bool pixy_connected = false; + + +static BUTTON_STRUCT b_back; +static TOUCH_AREA_STRUCT a_area; + +static void b_back_cb(void* button) { + gui_screen_back(); +} + +static POINT_STRUCT pixy_pos; +static POINT_STRUCT old_pos; +static void touchCB(void* touchArea, TOUCH_ACTION triggeredAction) { + POINT_STRUCT p = touch_get_last_point(); + switch(triggeredAction) { + case PEN_ENTER: + case PEN_DOWN: + old_pos = p; + break; + case PEN_MOVE: + { + int16_t deltaX = p.x - old_pos.x; + int16_t deltaY = p.y - old_pos.y; + old_pos=p; + printf("%d %d\n",deltaX,deltaY); + if(pixy_connected) { + int16_t new_x = pixy_pos.x+deltaX*2; + int16_t new_y = pixy_pos.y-deltaY*2; + 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; + pixy_pos.x = new_x; + pixy_pos.y= new_y; + } + } + break; + case PEN_UP: + case PEN_LEAVE: + printf("Leave/up\n"); + break; + default: break; + } + + +} + + +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; //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) + + //Area test + a_area.hookedActions = PEN_DOWN | PEN_MOVE | PEN_ENTER | PEN_UP | PEN_LEAVE; + a_area.x1 = 0; + a_area.y1 = 0; + a_area.x2 = 317; + a_area.y2 = 197; + a_area.callback = touchCB; + touch_register_area(&a_area); + + + + //Pixy stuff + pixy_connected = (pixy_init()==0); //try to connect to pixy + if(pixy_connected) { + pixy_pos.x=pixy_pos.y=500; + } +} + +static void leave(void* screen) { + gui_button_remove(&b_back); + touch_unregister_area(&a_area); +} + + + +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; + pixy_pos.x=pixy_pos.y=500; + printf("pixy reinitialized\n"); + } + } + + if(pixy_connected) { + pixy_service(); //Send/receive event data from/to pixy failed + + pixy_render_full_frame(1,1); + + pixy_rcs_set_position(0,pixy_pos.x); + pixy_rcs_set_position(1,pixy_pos.y); + } +} + + +static SCREEN_STRUCT screen = { + enter, + leave, + update +}; + + +SCREEN_STRUCT* get_screen_photomode() { + return &screen; +} + + + diff --git a/common/app/screen_photomode.h b/common/app/screen_photomode.h new file mode 100644 index 0000000..19545ac --- /dev/null +++ b/common/app/screen_photomode.h @@ -0,0 +1,22 @@ +#include "screen.h" + +/** + * @addtogroup screens + */ +/*@{*/ + +/** + * @defgroup photomode Photo Mode (Screen) + * The Photo Mode Screen allows taking snapshots of the current pixy cam feed + */ +/*@{*/ + +/** + * Returns a pointer to the photomode screen + * \sa gui_screen_navigate + * @return + */ +SCREEN_STRUCT* get_screen_photomode(); + +/*@}*/ +/*@}*/ diff --git a/common/app/screen_pixytest.c b/common/app/screen_pixytest.c index 7d5b0de..bfd0ac1 100644 --- a/common/app/screen_pixytest.c +++ b/common/app/screen_pixytest.c @@ -3,8 +3,8 @@ #include "tft.h" #include "touch.h" #include "pixy.h" -#include #include "system.h" +#include "pixy_helper.h" static volatile bool pixy_connected = false; @@ -207,134 +207,9 @@ int pixy_led_test() { return return_value; } -//---------------------------------------------------------------------------------------------------------------------------- - -int renderBA81(uint8_t renderFlags, uint16_t width, uint16_t height, uint32_t frameLen, uint8_t *frame); - int pixy_frame_test() { - - 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(0), // xoffset - INT16(0), // yoffset - INT16(320), // width - INT16(200), // 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(renderflags,xwidth,ywidth,size,videodata); - } - - return return_value; + return pixy_render_full_frame(0,0); } - - -void interpolateBayer(uint16_t width, uint16_t x, uint16_t y, uint8_t *pixel, uint8_t* r, uint8_t* g, uint8_t* b) -{ - if (y&1) - { - if (x&1) - { - *r = *pixel; - *g = (*(pixel-1)+*(pixel+1)+*(pixel+width)+*(pixel-width))>>2; - *b = (*(pixel-width-1)+*(pixel-width+1)+*(pixel+width-1)+*(pixel+width+1))>>2; - } - else - { - *r = (*(pixel-1)+*(pixel+1))>>1; - *g = *pixel; - *b = (*(pixel-width)+*(pixel+width))>>1; - } - } - else - { - if (x&1) - { - *r = (*(pixel-width)+*(pixel+width))>>1; - *g = *pixel; - *b = (*(pixel-1)+*(pixel+1))>>1; - } - else - { - *r = (*(pixel-width-1)+*(pixel-width+1)+*(pixel+width-1)+*(pixel+width+1))>>2; - *g = (*(pixel-1)+*(pixel+1)+*(pixel+width)+*(pixel-width))>>2; - *b = *pixel; - } - } - -} - - - - - - -int renderBA81(uint8_t renderFlags, uint16_t width, uint16_t height, uint32_t frameLen, uint8_t *frame) -{ - uint16_t x, y; - uint8_t r, g, b; - - - // skip first line - frame += width; - - // don't render top and bottom rows, and left and rightmost columns because of color - // interpolation - //uint32_t decodedimage[(width-2)*(height-2)]; - uint16_t* decodedimage = malloc(sizeof(uint16_t)*(width-2)*(height-2)); - - if(decodedimage==NULL) { //not enough free space to decode image in memory - //decode & render image pixel by pixel - uint16_t* line = decodedimage; - for (y=1; y