discoverpixy
Data Structures | Macros | Typedefs | Enumerations | Functions | Variables
screen_photomode_save.c File Reference
#include "screen_photomode_save.h"
#include "filesystem.h"
#include "button.h"
#include "tft.h"
#include "touch.h"
#include "pixy.h"
#include "pixy_frame.h"
#include <stdlib.h>
#include <string.h>
Include dependency graph for screen_photomode_save.c:

Go to the source code of this file.

Data Structures

struct  FILE_LIST_ENTRY_S
 

Macros

#define X_OFS   5
 

Typedefs

typedef struct FILE_LIST_ENTRY_S FILE_LIST_ENTRY
 

Enumerations

enum  {
  init, error, showlist, picking,
  saving, done
}
 

Functions

static void b_back_cb (void *button)
 
static void touchCB (void *touchArea, TOUCH_ACTION triggeredAction)
 
static void enter (void *screen)
 
static void update (void *screen)
 
static void leave (void *screen)
 
SCREEN_STRUCTget_screen_photomodesave ()
 

Variables

static BUTTON_STRUCT b_back
 
static TOUCH_AREA_STRUCT a_area
 
static int num_files_ok
 
static enum { ... }  state
 
static int fontheight
 
static int liststart
 
static const char * picked_file
 
static FILE_LIST_ENTRYfiles_ok
 
static const char * nomatch_text []
 
static unsigned char bmpheader_data [0x7A]
 
static SCREEN_STRUCT screen
 

Macro Definition Documentation

#define X_OFS   5

Typedef Documentation

Enumeration Type Documentation

anonymous enum
Enumerator
init 
error 
showlist 
picking 
saving 
done 

Definition at line 36 of file screen_photomode_save.c.

36 {init, error, showlist, picking, saving, done} state; //Current state of the screen state machine
static enum @0 state

Function Documentation

static void b_back_cb ( void *  button)
static

Definition at line 30 of file screen_photomode_save.c.

31 {
33 }
bool gui_screen_back()
Definition: screen.c:85

Here is the call graph for this function:

Here is the caller graph for this function:

static void enter ( void *  screen)
static

Definition at line 108 of file screen_photomode_save.c.

109 {
110  tft_clear(WHITE);
111 
112 
113 #define X_OFS 5
114 
115  //Back button
116  b_back.base.x1 = X_OFS; //Start X of Button
117  b_back.base.y1 = 210; //Start Y of Button
118  b_back.base.x2 = AUTO; //Auto Calculate X2 with String Width
119  b_back.base.y2 = AUTO; //Auto Calculate Y2 with String Height
120  b_back.txtcolor = WHITE; //Set foreground color
121  b_back.bgcolor = HEX(0xAE1010); //Set background color (Don't take 255 or 0 on at least one channel, to make shadows possible)
122  b_back.font = 0; //Select Font
123  b_back.text = "Back"; //Set Text (For formatted strings take sprintf)
124  b_back.callback = b_back_cb; //Call b_back_cb as Callback
125  gui_button_add(&b_back); //Register Button (and run the callback from now on)
126 
127  state = init; //Start with the init state
128  fontheight = tft_font_height(0) + 2; //Save the height of the used font, for fast access
129  files_ok = NULL; //initialize the linked list with 0 elements
130  num_files_ok = 0; //we have zero! elements
131 }
uint8_t tft_font_height(uint8_t fontnum)
Definition: tft.c:87
const char * text
The label of the button.
Definition: button.h:61
uint16_t txtcolor
The 16-bit text color.
Definition: button.h:59
#define AUTO
Use this value instead of x2, y2 in the BUTTON_STRUCT to autocalculate the button width/height...
Definition: button.h:65
uint16_t y1
Top Left Y-Coordinate of Area.
Definition: touch.h:75
#define X_OFS
bool gui_button_add(BUTTON_STRUCT *button)
Definition: button.c:133
uint16_t x1
Top Left X-Coordinate of Area.
Definition: touch.h:74
static void b_back_cb(void *button)
uint16_t bgcolor
The 16-bit background color of the button.
Definition: button.h:57
static int fontheight
TOUCH_AREA_STRUCT base
Basic geometry of the button. You only need to set the x1, y1, x2, y2 members of this struct...
Definition: button.h:56
#define HEX(h)
Definition: tft.h:60
uint16_t y2
Bottom Right Y-Coordinate of Area.
Definition: touch.h:77
static enum @0 state
void tft_clear(uint16_t color)
Definition: tft.c:45
static BUTTON_STRUCT b_back
uint16_t x2
Bottom Right X-Coordinate of Area.
Definition: touch.h:76
#define WHITE
Definition: tft.h:53
static int num_files_ok
static FILE_LIST_ENTRY * files_ok
BUTTON_CALLBACK callback
Callback which is executed when the button is pressed.
Definition: button.h:58
uint8_t font
The number of the font to use.
Definition: button.h:60

Here is the call graph for this function:

static void leave ( void *  screen)
static

Definition at line 310 of file screen_photomode_save.c.

311 {
312  gui_button_remove(&b_back); //Remove/Free the back button
313 
314  if (state == picking) { //The user left the screen in the "picking"-phase
315  touch_unregister_area(&a_area); //remove the touch area (for the list)
316  }
317 
318  if (state == picking || state == saving || state == done) { //the user left the screen after we created the linked list
319  //Iterate through the linked list and free all resources
320  FILE_LIST_ENTRY* current_entry = files_ok; //start with the list head
321 
322  while (current_entry != NULL) { //while we're not at the end
323  FILE_LIST_ENTRY* temp = current_entry->next; //save the next pointer because we free the current element on the next line
324  free((void*)(current_entry->filename)); //free filename
325  free(current_entry); //free element itself
326  current_entry = temp; //advance
327  }
328  }
329 }
static TOUCH_AREA_STRUCT a_area
void touch_unregister_area(TOUCH_AREA_STRUCT *area)
Definition: touch.c:195
static enum @0 state
static BUTTON_STRUCT b_back
void gui_button_remove(BUTTON_STRUCT *button)
Definition: button.c:184
struct FILE_LIST_ENTRY_S * next
static FILE_LIST_ENTRY * files_ok

Here is the call graph for this function:

static void touchCB ( void *  touchArea,
TOUCH_ACTION  triggeredAction 
)
static

Definition at line 50 of file screen_photomode_save.c.

51 {
52 
53  int y = touch_get_last_point().y - liststart; //Calculate the y-Coordinate of the touch point relative to the start of the file-list
54  int elem = y / fontheight; //Calculate the file index
55 
56  if (elem < 0 | elem >= num_files_ok) {
57  return; //Check if the file index is valid (0,1,..,num_files_ok-1)
58  }
59 
60  //Search for the corresponding entry in the linked list
61  FILE_LIST_ENTRY* current_entry = files_ok; //Start walking through the list, starting by the head of the list
62 
63  for (int i = 0; i < elem; i++) { //Until we have reached the file (index)
64  current_entry = current_entry->next; //traverse to the next file
65  }
66 
67  picked_file = current_entry->filename; //save the picked filename. It will be used by the statemachine in the main loop
68  touch_unregister_area(&a_area); //unregister the touch area, we no longer need it. No more interrupts will be fired.
69  state = saving; //Change the state of the statemachine
70 }
uint16_t y
The Y-Coordinate of the point.
Definition: touch.h:88
static int fontheight
static TOUCH_AREA_STRUCT a_area
void touch_unregister_area(TOUCH_AREA_STRUCT *area)
Definition: touch.c:195
static enum @0 state
POINT_STRUCT touch_get_last_point()
Definition: touch.c:211
struct FILE_LIST_ENTRY_S * next
static int liststart
static int num_files_ok
static FILE_LIST_ENTRY * files_ok
static const char * picked_file

Here is the call graph for this function:

Here is the caller graph for this function:

static void update ( void *  screen)
static

Definition at line 135 of file screen_photomode_save.c.

136 {
137  switch (state) {
138  case init: { //Init State: The user just entered the screen
139  DIRECTORY_STRUCT* dir = filesystem_dir_open("."); //open root directory
140 
141  if (dir == NULL) { //error while opening root directory
142  tft_print_line(X_OFS, 5, BLACK, TRANSPARENT, 0, "Error accessing Filesystem");
143  state = error;
144  break;
145  }
146 
147  bool nomatch = true; //whether or not we have zero files which are suitable for saving
148 
149  for (int i = 0; i < dir->num_files; i++) { //walk through all files in the directory
150  FILE_STRUCT* file = &(dir->files[i]); //Pointer to the current file/subdirectory
151 
152  //Ignore directories, archives, hidden files, system files and files we cannot write to
153  if (file->fattrib & (F_SYS | F_HID | F_ARC | F_DIR | F_RDO)) {
154  continue;
155  }
156 
157  //ignore files which are not large enough
158  if (file->fsize < 189410) {
159  continue; //size taken from an example bitmap (318x198x24)
160  }
161 
162  nomatch = false; //at least one file matches
163  break;
164  }
165 
166  if (nomatch) { //not one file is suitable for writing
167  int y = 5; //y-Coordinate where to start writing the error text
168  int i = 0;
169 
170  while (nomatch_text[i] != NULL) { //for every line in the big error array
171  //Write the line's text and go to the next line
173  i++;
174  }
175 
176  state = error;
177  } else { //we have a least one suitable file
178  state = showlist;
179  }
180 
181  filesystem_dir_close(dir); //free directory struct
182  }
183  break;
184 
185  case showlist: { //Show List State: Where we load and present the suitable file's to the user in a list
186  DIRECTORY_STRUCT* dir2 = filesystem_dir_open("."); //Open the directory again
187 
188  if (dir2 == NULL) {
189  return; //Error on opening? This should never happen, since it's handled in the previous state
190  }
191 
192  int y = 5; //y-Coordinate where to start drawing/writing text/list-elements
193 
194  tft_print_line(X_OFS, y, BLACK, TRANSPARENT, 0, "Pick a file to save the image to");
195  y += fontheight + 5;
196 
197  tft_print_line(X_OFS, y, BLUE, TRANSPARENT, 0, "Name Modified Size");
198  y += fontheight;
199 
200  liststart = y; //store the y coordinate of the start of the list away (used in toucharea callback)
201  num_files_ok = 0; //we start with 0 matching files
202 
203  FILE_LIST_ENTRY* current_entry = NULL; //We start with an empty list
204 
205  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
206  FILE_STRUCT* file = &(dir2->files[i]);
207 
208  //Ignore directories, archives, hidden files, system files and files we cannot write to
209  if (file->fattrib & (F_SYS | F_HID | F_ARC | F_DIR | F_RDO)) {
210  continue;
211  }
212 
213  //ignore files which are not large enough
214  if (file->fsize < 189410) {
215  continue; //size taken from an example bitmap (318x198x24)
216  }
217 
218  //Print out filename, modified date,time and file size
220  TRANSPARENT, 0, "%-16s %02u.%02u.%02u %02u:%02u:%02u %u",
221  file->fname,
222  file->fdate.day,
223  file->fdate.month,
224  (file->fdate.year + 1980) % 100,
225  file->ftime.hour,
226  file->ftime.min,
227  file->ftime.sec * 2,
228  file->fsize);
229 
230  if (current_entry == NULL) { //The list is empty
231  current_entry = malloc(sizeof(FILE_LIST_ENTRY)); //create new entry
232  files_ok = current_entry; //assign it to the list head
233  } else { //there's a least one entry in the list
234  current_entry->next = malloc(sizeof(FILE_LIST_ENTRY)); //append entry to previous entry
235  current_entry = current_entry->next; //newly created entry is the current now.
236  }
237 
238  current_entry->next = NULL; //we're at the end of the list (for now)
239  current_entry->filename = malloc(strlen(file->fname) + 1); //allocate space for the filename + zero-termination
240  strcpy(current_entry->filename, file->fname); //copy filename (so that we can close the directory after scanning)
241 
242  //since we have found a suitable file we need to increment the position in the list
243  num_files_ok++;
244  y += fontheight;
245  }
246 
247  //Touch area for file-selection (in the list)
248  a_area.hookedActions = PEN_UP; //we're only interested in PEN_UP events
249  a_area.x1 = X_OFS; //Left border
250  a_area.y1 = liststart; //Start where the list started
251  a_area.x2 = 320 - X_OFS; //Right border
252  a_area.y2 = liststart + fontheight * num_files_ok; //stop at the end of the list
253  a_area.callback = touchCB; //execute our callback when PEN_UP occurs
254  touch_register_area(&a_area); //register the touch area and receive events from now on
255 
256  filesystem_dir_close(dir2); //we no longer need the directory struct, since we have our own linked list now
257 
258  state = picking;
259  }
260  break;
261 
262  case picking: //Picking State: Where we wait on the users file choice
263  pixy_service(); //Handle pending pixy events
264  //do nothing and wait on user to pick a file
265  break;
266 
267  case saving: { //Saving State: Where we save the image to the selected file
268  FILE_HANDLE* file = filesystem_file_open(picked_file); //try to open the selected file
269 
270  if (file == NULL) { //opening the file failed
271  tft_print_formatted(X_OFS, 190, BLUE, TRANSPARENT, 0, "Could not open %s", picked_file);
272  state = error;
273  break;
274  }
275 
276  filesystem_file_seek(file, 0); //seek to the start of the file (optional?)
277 
278  if (filesystem_file_write(file, bmpheader_data, 0x7A) != F_OK) { //Writing the header failed
279  tft_print_formatted(X_OFS, 190, BLUE, TRANSPARENT, 0, "Error while writing to %s", picked_file);
280  filesystem_file_close(file);
281  state = error;
282  break;
283  }
284 
285  if (pixy_save_full_frame(file) != 0) { //Writing the imagedata failed
286  tft_print_formatted(X_OFS, 190, BLUE, TRANSPARENT, 0, "Error while writing to %s", picked_file);
287  filesystem_file_close(file);
288  state = error;
289  break;
290  }
291 
292  //if we reach this point, we have written all data out successfully
293 
294  filesystem_file_close(file); //close/finalize the file
295  tft_print_formatted(X_OFS, 190, BLUE, TRANSPARENT, 0, "Image saved to %s", picked_file);
296  state = done;
297  }
298  break;
299 
300  case error: //Error State: Where we show an error message and leave the user no other choice than to click the backbutton
301  case done: //Done State: When saving the file was successful
302  pixy_service(); //Handle pending pixy events
303  //wait on user to click the back button
304  break;
305 
306  }
307 }
bool touch_register_area(TOUCH_AREA_STRUCT *area)
Definition: touch.c:181
static unsigned char bmpheader_data[0x7A]
FILE_STATUS filesystem_file_seek(FILE_HANDLE *handle, uint32_t offset)
Definition: filesystem.c:43
Receive an event when the pen goes up inside the region.
Definition: touch.h:55
unsigned sec
second/2 (0..29)
Definition: filesystem.h:55
uint16_t y1
Top Left Y-Coordinate of Area.
Definition: touch.h:75
void tft_print_formatted(uint16_t x, uint16_t y, uint16_t color, uint16_t bgcolor, uint8_t font, const char *format,...)
Definition: tft.c:111
#define X_OFS
void tft_print_line(uint16_t x, uint16_t y, uint16_t color, uint16_t bgcolor, uint8_t font, const char *text)
Definition: tft.c:98
FILE_DATE_STRUCT fdate
Last modified date.
Definition: filesystem.h:63
unsigned day
day (1..31)
Definition: filesystem.h:46
uint8_t fattrib
File/Directory Attributes.
Definition: filesystem.h:65
uint16_t x1
Top Left X-Coordinate of Area.
Definition: touch.h:74
#define TRANSPARENT
Definition: tft.h:66
int pixy_save_full_frame(FILE_HANDLE *handle)
Definition: pixy_frame.c:65
static int fontheight
static TOUCH_AREA_STRUCT a_area
uint16_t y2
Bottom Right Y-Coordinate of Area.
Definition: touch.h:77
int pixy_service()
FILE_HANDLE * filesystem_file_open(const char *filename)
Definition: filesystem.c:33
static enum @0 state
void filesystem_file_close(FILE_HANDLE *handle)
Definition: filesystem.c:38
TOUCH_CALLBACK callback
Callback which is executed when an event occurred in this Area.
Definition: touch.h:78
File has the archive flag set (probably unused)
Definition: filesystem.h:37
char * fname
File/Directory name.
Definition: filesystem.h:66
uint16_t x2
Bottom Right X-Coordinate of Area.
Definition: touch.h:76
File is a system file.
Definition: filesystem.h:35
unsigned year
year from 1980 (0..127)
Definition: filesystem.h:44
uint16_t num_files
Number of files/directories in this directory.
Definition: filesystem.h:74
unsigned month
month (1..12)
Definition: filesystem.h:45
FILE_STATUS filesystem_file_write(FILE_HANDLE *handle, uint8_t *buf, uint32_t size)
Definition: filesystem.c:53
unsigned min
minute (0..59
Definition: filesystem.h:54
File is hidden.
Definition: filesystem.h:34
struct FILE_LIST_ENTRY_S * next
unsigned hour
hour (0..23)
Definition: filesystem.h:53
TOUCH_ACTION hookedActions
Actions to listen to.
Definition: touch.h:73
Everything ok.
Definition: filesystem.h:91
FILE_STRUCT * files
An array with num_files FILE_STRUCT entries.
Definition: filesystem.h:75
DIRECTORY_STRUCT * filesystem_dir_open(const char *path)
Definition: filesystem.c:23
#define BLUE
Definition: tft.h:52
static int liststart
It's a directory and not a file.
Definition: filesystem.h:36
static int num_files_ok
static FILE_LIST_ENTRY * files_ok
File is readonly. You cannot write to it.
Definition: filesystem.h:33
static void touchCB(void *touchArea, TOUCH_ACTION triggeredAction)
static const char * picked_file
static const char * nomatch_text[]
void filesystem_dir_close(DIRECTORY_STRUCT *dir)
Definition: filesystem.c:28
FILE_TIME_STRUCT ftime
Last modified time.
Definition: filesystem.h:64
#define BLACK
Definition: tft.h:54
uint32_t fsize
File size in bytes. 0 for directories.
Definition: filesystem.h:62

Here is the call graph for this function:

Variable Documentation

TOUCH_AREA_STRUCT a_area
static

Definition at line 27 of file screen_photomode_save.c.

BUTTON_STRUCT b_back
static

Definition at line 26 of file screen_photomode_save.c.

unsigned char bmpheader_data[0x7A]
static
Initial value:
= {
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
}

Definition at line 93 of file screen_photomode_save.c.

FILE_LIST_ENTRY* files_ok
static

Definition at line 47 of file screen_photomode_save.c.

int fontheight
static

Definition at line 37 of file screen_photomode_save.c.

int liststart
static

Definition at line 38 of file screen_photomode_save.c.

const char* nomatch_text[]
static
Initial value:
= {
"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
}

Definition at line 73 of file screen_photomode_save.c.

int num_files_ok
static

Definition at line 35 of file screen_photomode_save.c.

const char* picked_file
static

Definition at line 39 of file screen_photomode_save.c.

SCREEN_STRUCT screen
static
Initial value:
= {
}
static void update(void *screen)
static void enter(void *screen)
static void leave(void *screen)

Definition at line 332 of file screen_photomode_save.c.

enum { ... } state