Documented pixy_helper and implemented/finished photo-mode screens! Snap some shots!

This commit is contained in:
t-moe
2015-05-16 00:11:19 +02:00
parent 27c09bad0d
commit 62006e0028
9 changed files with 532 additions and 55 deletions

View File

@@ -6,6 +6,7 @@
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);
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) { int pixy_render_full_frame(uint16_t x, uint16_t y) {
@@ -46,6 +47,44 @@ int pixy_render_cropped_frame(uint16_t x, uint16_t y, uint16_t xoffset, uint16_t
return return_value; 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;
}
@@ -105,7 +144,6 @@ static int renderBA81(uint16_t xpos, uint16_t ypos, uint16_t width, uint16_t hei
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 //decode & render image pixel by pixel
uint16_t* line = decodedimage;
for (y=1; y<height-1; y++) for (y=1; y<height-1; y++)
{ {
frame++; frame++;
@@ -138,3 +176,48 @@ static int renderBA81(uint16_t xpos, uint16_t ypos, uint16_t width, uint16_t hei
return 0; return 0;
} }
static int saveBA81(FILE_HANDLE* handle, uint16_t width, uint16_t height, uint32_t frameLen, uint8_t *frame)
{
uint16_t x, y;
uint8_t r, g, b;
uint32_t fpos = handle->fpos;
uint32_t row_size_padded = ((width-2)*3 + 3) & (~3); //row size aligned to 4 bytes
uint32_t fpos_end = fpos + row_size_padded* (height-2);
// skip first line
frame += width;
// don't render top and bottom rows, and left and rightmost columns because of color
// interpolation
for (y=1; y<height-1; y++)
{
frame++;
uint8_t rowbuf[row_size_padded];
//Bitmaps are saved "bottom-up". Seek to the right row.
if(filesystem_file_seek(handle,fpos_end-row_size_padded*y)!=F_OK) {
return -1;
}
for (x=1; x<width-1; x++, frame++)
{
interpolateBayer(width, x, y, frame, &r, &g, &b);
//bitmaps are saved in 24bit b,g,r format
rowbuf[(x-1)*3] = b;
rowbuf[(x-1)*3+1] = g;
rowbuf[(x-1)*3+2] = r;
}
if(filesystem_file_write(handle,rowbuf,row_size_padded)!=F_OK) {
return -1;
}
frame++;
}
return 0;
}

View File

@@ -3,8 +3,47 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include "filesystem.h"
/**
* Receives a fullsized frame from pixy and display's it on the display with the topleft corner at (x,y)
* @param x The x-Coordinate of the top left corner
* @param y The y-Coordinate of the top left corner
* @return 0 on success, otherwise the errorcode from pixy
*/
int pixy_render_full_frame(uint16_t x, uint16_t y); int pixy_render_full_frame(uint16_t x, uint16_t y);
/**
* Receives a cropped frame from pixy and display's it on the display with the topleft corner at (x,y)
* @param x The x-Coordinate of the top left corner to draw the image
* @param y The y-Coordinate of the top left corner to draw the image
* @param xoffset The x-Coordinate on the pixy image from where on you want the frame data
* @param yoffset The y-Coordinate on the pixy image from where on you want the frame data
* @param width The width of the image recorded from pixy
* @param height The height of the image recorded from pixy
* @return 0 on success, otherwise the errorcode from pixy
*/
int pixy_render_cropped_frame(uint16_t x, uint16_t y, uint16_t xoffset, uint16_t yoffset, uint16_t width, uint16_t height); int pixy_render_cropped_frame(uint16_t x, uint16_t y, uint16_t xoffset, uint16_t yoffset, uint16_t width, uint16_t height);
/**
* Receives a fullsized frame from pixy and saves it to the given file in the 24bit (b,g,a) format.
* Use this method to write the bitmap-data part of a windows bitmap (.bmp).
* This method will neither open nor close the passed file.
* @param handle The file to write the data to. The file must be open and it should be seeked to the right position.
* @return 0 on success, otherwise the errorcode from pixy
*/
int pixy_save_full_frame(FILE_HANDLE* handle);
/**
* Receives a cropped frame from pixy and saves it to the given file in the 24bit (b,g,a) format.
* @param handle The file to write the data to. The file must be open and it should be seeked to the right position.
* @param xoffset The x-Coordinate on the pixy image from where on you want the frame data
* @param yoffset The y-Coordinate on the pixy image from where on you want the frame data
* @param width The width of the image recorded from pixy
* @param height The height of the image recorded from pixy
* @return 0 on success, otherwise the errorcode from pixy
*/
int pixy_save_cropped_frame(FILE_HANDLE* handle, uint16_t xoffset, uint16_t yoffset, uint16_t width, uint16_t height);
#endif /* PIXY_HELPER_H */ #endif /* PIXY_HELPER_H */

View File

@@ -1,43 +1,60 @@
#include "screen_photomode.h" #include "screen_photomode.h"
#include "screen_photomode_save.h"
#include "button.h" #include "button.h"
#include "tft.h" #include "tft.h"
#include "touch.h" #include "touch.h"
#include "pixy.h" #include "pixy.h"
#include "pixy_helper.h"
#include "system.h" #include "system.h"
#include "pixy_helper.h"
static volatile bool pixy_connected = false; static bool pixy_connected = false; //Whether or not the pixy cam is currently connected
static BUTTON_STRUCT b_back; //Button to navigate back
static BUTTON_STRUCT b_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 BUTTON_STRUCT b_back; //Callback for when the user presses the "back" button
static TOUCH_AREA_STRUCT a_area;
static void b_back_cb(void* button) { static void b_back_cb(void* button) {
gui_screen_back(); subMenu = false; //we're not entering a submenu
gui_screen_back(); //navigate back to the previous screen
} }
static POINT_STRUCT pixy_pos; //Callback for when the user presses the "save" button
static POINT_STRUCT old_pos; 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) { static void touchCB(void* touchArea, TOUCH_ACTION triggeredAction) {
POINT_STRUCT p = touch_get_last_point(); POINT_STRUCT p = touch_get_last_point(); //get the last touched point
switch(triggeredAction) { switch(triggeredAction) {
case PEN_ENTER: case PEN_ENTER:
case PEN_DOWN: case PEN_DOWN:
old_pos = p; old_pos = p; //If the user "newly" enters the touch area, we set the "last" position to the current
break; break;
case PEN_MOVE: 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; int16_t deltaX = p.x - old_pos.x; //Calculate x difference between last and current touch
int16_t deltaY = p.y - old_pos.y; int16_t deltaY = p.y - old_pos.y; //Calculate y difference between last and current touch
old_pos=p; old_pos=p; //store the current touch point for the next time
printf("%d %d\n",deltaX,deltaY); //printf("%d %d\n",deltaX,deltaY);
if(pixy_connected) { 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_x = pixy_pos.x+deltaX*2;
int16_t new_y = pixy_pos.y-deltaY*2; int16_t new_y = pixy_pos.y-deltaY*2;
//check limits
if(new_x<0) new_x=0; if(new_x<0) new_x=0;
if(new_x>1000) new_x=1000; if(new_x>1000) new_x=1000;
if(new_y<0) new_y=0; if(new_y<0) new_y=0;
if(new_y>1000) new_y=1000; 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.x = new_x;
pixy_pos.y= new_y; pixy_pos.y= new_y;
} }
@@ -45,22 +62,23 @@ static void touchCB(void* touchArea, TOUCH_ACTION triggeredAction) {
break; break;
case PEN_UP: case PEN_UP:
case PEN_LEAVE: case PEN_LEAVE:
printf("Leave/up\n"); //printf("Leave/up\n");
break; break;
default: break; default: break;
} }
} }
//Callback for when the screen is entered/loaded
static void enter(void* screen) { static void enter(void* screen) {
tft_clear(WHITE); tft_clear(WHITE);
tft_print_line(5,5,BLACK,TRANSPARENT,0,"Drag the image around and ");
//Back button //Back button
b_back.base.x1=10; //Start X of Button b_back.base.x1=5; //Start X of Button
b_back.base.y1=210; //Start Y of Button b_back.base.y1=19; //Start Y of Button
b_back.base.x2=AUTO; //b_back.base.x1+160; //Auto Calculate X2 with String Width b_back.base.x2=AUTO; //Auto Calculate X2 with String Width
b_back.base.y2=AUTO; //Auto Calculate Y2 with String Height b_back.base.y2=AUTO; //Auto Calculate Y2 with String Height
b_back.txtcolor=WHITE; //Set foreground color b_back.txtcolor=WHITE; //Set foreground color
b_back.bgcolor=HEX(0xAE1010); //Set background color (Don't take 255 or 0 on at least one channel, to make shadows possible) b_back.bgcolor=HEX(0xAE1010); //Set background color (Don't take 255 or 0 on at least one channel, to make shadows possible)
@@ -69,55 +87,73 @@ static void enter(void* screen) {
b_back.callback=b_back_cb; //Call b_back_cb as Callback b_back.callback=b_back_cb; //Call b_back_cb as Callback
gui_button_add(&b_back); //Register Button (and run the callback from now on) gui_button_add(&b_back); //Register Button (and run the callback from now on)
//Area test //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);
//Frame Coordinates: topleft = (1,40); bottomright = (318,238)
//Leave a 10px border for the area
//Area to drag the image around
a_area.hookedActions = PEN_DOWN | PEN_MOVE | PEN_ENTER | PEN_UP | PEN_LEAVE; a_area.hookedActions = PEN_DOWN | PEN_MOVE | PEN_ENTER | PEN_UP | PEN_LEAVE;
a_area.x1 = 0; a_area.x1 = 11;
a_area.y1 = 0; a_area.y1 = 50;
a_area.x2 = 317; a_area.x2 = 308;
a_area.y2 = 197; a_area.y2 = 228;
a_area.callback = touchCB; a_area.callback = touchCB;
touch_register_area(&a_area); touch_register_area(&a_area);
//Pixy stuff //Pixy stuff
pixy_connected = (pixy_init()==0); //try to connect to pixy pixy_connected = (pixy_init()==0); //try to connect to pixy
if(pixy_connected) { if(pixy_connected && !subMenu) { //pixy is connected, but we are not coming from a submenu
pixy_pos.x=pixy_pos.y=500; 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) { static void leave(void* screen) {
//remove buttons and touch area.
gui_button_remove(&b_back); gui_button_remove(&b_back);
gui_button_remove(&b_save);
touch_unregister_area(&a_area); 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) { static void update(void* screen) {
//Note: The only way to detect that pixy has been disconnected is if a command fails. There's no pixy_is_connected method yet :'( //Note: The only way to detect that pixy has been disconnected is if a command fails. There's no pixy_is_connected method yet :'(
if(!pixy_connected) { //Pixy not connected if(!pixy_connected) { //Pixy not connected
pixy_close(); //Ensure that all pixy resources are freed (failsafe) pixy_close(); //Ensure that all pixy resources are freed (failsafe)
if(pixy_init()==0) { //try to connect to pixy if(pixy_init()==0) { //try to connect to pixy
pixy_connected=true; pixy_connected=true;
pixy_pos.x=pixy_pos.y=500; if(!subMenu) { //we're not coming from a submenu
printf("pixy reinitialized\n"); pixy_pos.x=pixy_pos.y=500; //reset servo positions to center
}
printf("pixy (re)initialized\n");
} }
} }
if(pixy_connected) { if(pixy_connected) { //If we are connected (now)
pixy_service(); //Send/receive event data from/to pixy failed pixy_service(); //Handle pending pixy events (e.g. color info retrival)
pixy_render_full_frame(1,1); 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(0,pixy_pos.x);
pixy_rcs_set_position(1,pixy_pos.y); pixy_rcs_set_position(1,pixy_pos.y);
} }
} }
//Declare screen callbacks
static SCREEN_STRUCT screen = { static SCREEN_STRUCT screen = {
enter, enter,
leave, leave,
@@ -128,6 +164,3 @@ static SCREEN_STRUCT screen = {
SCREEN_STRUCT* get_screen_photomode() { SCREEN_STRUCT* get_screen_photomode() {
return &screen; return &screen;
} }

View File

@@ -0,0 +1,301 @@
#include "screen_photomode_save.h"
#include "filesystem.h"
#include "button.h"
#include "tft.h"
#include "touch.h"
#include "pixy.h"
#include "pixy_helper.h"
#include <stdlib.h>
#include <string.h>
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 int num_files_ok; //number of files into which we can write the image (size, flags ok)
static enum {init, error, showlist, picking, saving, done} state; //Current state of the screen state machine
static int fontheight; //The space between one line of text to the next
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
} 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) {
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)
//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
};
//Bitmap header for a 318x198x24bit windows bitmap. data starts at 0x7A (= after this header)
//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
};
//Callback for when the screen is entered/loaded
static void enter(void* screen) {
tft_clear(WHITE);
#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)
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;
}
bool nomatch= true; //whether or not we have zero files which are suitable for saving
for(int i=0; i<dir->num_files; i++) { //walk through all files in the directory
FILE_STRUCT* file = &(dir->files[i]); //Pointer to the current file/subdirectory
//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;
//ignore files which are not large enough
if(file->fsize<189410) continue; //size taken from an example bitmap (318x198x24)
nomatch=false; //at least one file matches
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;
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;
}
filesystem_dir_close(dir); //free directory struct
}
break;
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
int y = 5; //y-Coordinate where to start drawing/writing text/list-elements
tft_print_line(X_OFS,y,BLACK,TRANSPARENT,0,"Pick a file to save the image to");
y+=fontheight+5;
tft_print_line(X_OFS,y,BLUE,TRANSPARENT,0,"Name Modified Size");
y+=fontheight;
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
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]);
//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;
//ignore files which are not large enough
if(file->fsize<189410) continue; //size taken from an example bitmap (318x198x24)
//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);
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)
//since we have found a suitable file we need to increment the position in the list
num_files_ok++;
y+=fontheight;
}
//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
filesystem_dir_close(dir2); //we no longer need the directory struct, since we have our own linked list now
state=picking;
}
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
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
}
}
}
//Declare screen callbacks
static SCREEN_STRUCT screen = {
enter,
leave,
update
};
SCREEN_STRUCT* get_screen_photomodesave() {
return &screen;
}

View File

@@ -0,0 +1,23 @@
#include "screen.h"
/**
* @addtogroup screens
*/
/*@{*/
/**
* @defgroup photomodesave Photo Mode Save (Screen)
* The Photo Mode Save Screen helps the user saving a file to the filesystem
*/
/*@{*/
/**
* Returns a pointer to the photomode save screen
* \sa gui_screen_navigate
* @return
*/
SCREEN_STRUCT* get_screen_photomodesave();
/*@}*/
/*@}*/

View File

@@ -17,7 +17,6 @@
#define __PIXY_H__ #define __PIXY_H__
#include <stdint.h> #include <stdint.h>
#include <unistd.h>
#include "pixydefs.h" #include "pixydefs.h"
// Pixy C API // // Pixy C API //

Binary file not shown.

Before

Width:  |  Height:  |  Size: 205 KiB

BIN
emulator/emulated/shot1.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 185 KiB

View File

@@ -1 +0,0 @@
hallo welt