@@ -3,7 +3,7 @@ Pedometer for TP of the course "System Engineering" 2016, EPFL
Authors: Léa Bole-Feysot, Quentin Golay, Benjamin Ramtoula & Nicolas Talabot
Version: 1.0
Date: 05.11.2016
Date: 06.11.2016
---------------------------------------------------------------------------*/

#include <pebble.h>
@@ -21,16 +21,16 @@ Date: 05.11.2016
#define Y 1 //
#define Z 2 //
#define NUM_SAMPLES 16 // Value used for num_samples
#define MAX_COUNTER 7 // Number of num_samples data_blocks to send for steps computation
#define SIZE_DATA NUM_SAMPLES*(MAX_COUNTER+1) // size of the data for steps computation
#define MAX_COUNTER 7 // Number of num_samples data_blocks to send for steps computation, minus 1
#define SIZE_DATA NUM_SAMPLES*(MAX_COUNTER+1) // size of the data for steps computation : 16 * (7+1) = 128

// Declare the global variable used for the person's informations
// Global variables used for the person's informations
int size = 170;
int steps = 0;
int goal = 50000;
int goal = 10000;
float gender = FEMALE;

// Given the filtered samples for the steps, returns the number of steps counted
// Given the filtered norm of the acceleration, returns the number of steps counted
static uint16_t step_count(short *samples) {
uint16_t num_edges = 0;
uint16_t num_steps = 0;
@@ -40,121 +40,50 @@ static uint16_t step_count(short *samples) {
int16_t sign1, sign2;
int16_t min_threshold = 100;
int16_t max_threshold = 1000;
double max_distance_ratio = 0.1;

// Count and store number of edges in the signal
for (int i = 9; i < 19; ++i)
{
sign1 = samples[1 + i - 9] - samples[i - 9];
sign2 = samples[2 + i - 9] - samples[1 + i - 9];
float max_distance_ratio = 0.1;

// Count and store number of edges (extremums) in the signal
for (int i = 0; i < 10; ++i)
{
// Check if there is a sign change to see if the point is a local extremum
sign1 = samples[1 + i] - samples[i];
sign2 = samples[2 + i] - samples[1 + i];
if (sign1*sign2 < 0)
{
edges[num_edges] = samples[1 + i - 9];
num_edges += 1;
if (i == 9) {
differences[i - 9] = edges[i - 9];
}
edges[num_edges] = samples[1 + i];
num_edges++;
if (i == 0)
differences[i] = edges[i];
else {
differences[i - 9] = abs(edges[i - 9] - edges[i - 1 - 9]);
differences[i] = abs(edges[i] - edges[i - 1]);
// Store biggest difference in this data set
if (differences[i] > max_difference && differences[i] < max_threshold)
if ((differences[i] > max_difference) && (differences[i] < max_threshold))
max_difference = differences[i];
}
}
}


// Count the steps based on the value of the difference between the edges of the signal
for (int i = 0; i < num_edges; i++) {
if (differences[i] > min_threshold && differences[i] < max_threshold && differences[i] > (int16_t)(max_distance_ratio*(double)max_difference))
num_steps += 1;
}

/*
// Create edges array to stock top and bottom edges separatly
if ((num_edges % 2) == 0) { // Used to be fmod(num_edges,2)
num_edges1 = num_edges >> 1; // >>1 is equivalent to /2
num_edges2 = num_edges >> 1;
}
else {
num_edges1 = (num_edges + 1) >> 1;
num_edges2 = (num_edges - 1) >> 1;
}
//short edges1[num_edges1]; ********************
//short edges2[num_edges2]; ********************
short sum1 = 0, sum2 = 0;
// Separate edges in the 2 arrays
for (int i = 0; i<num_edges - 1; i++) {
if ((i % 2) == 0) { // Used to be fmod(i,2)
//edges1[i/2] = edges[i]; *****************
sum1 += edges[i];
}
else {
//edges2[(i-1)/2] = edges[i]; *************
sum2 += edges[i];
}
}
short mean1, mean2, val1, val2;
mean1 = sum1 / num_edges1;
mean2 = sum2 / num_edges2;
int fixed1, fixed2, threshold;
fixed1 = 30000; // old value = 0.0084
fixed2 = 150; // old value = 0.076
int maxi = 0;
// Check if conditions for counting steps are verified and count steps
for (int i = 1; i < num_edges; i++) {
if (i == 0) {
val1 = 0;
}
else {
val1 = edges[i - 1];
}
val2 = edges[i];
if ((abs(mean1 - mean2) >> 2) > fixed1) { // >>2 is equivalent to /4
threshold = abs(mean1 - mean2) >> 2;
}
else {
threshold = fixed2;
}
if (abs(val2 - val1) > threshold) {
if (abs(val2 - val1) > 0.5*maxi) {
if ((differences[i] > min_threshold) && (differences[i] < max_threshold) && (differences[i] > (int16_t)(max_distance_ratio*(float)max_difference)))
num_steps += 1;
if (abs(val2 - val1) > maxi)
maxi = abs(val2 - val1); // IMPROVE BY STORING EVERY DIFFERENCE AND THEN COMPARING TO MAXIMUM DIFFERENCE AT END
}
}
}*/

return num_steps;
}

//Function that filters given sample array and modifies it with new filtered values
//Function that low-pass filters given sample array
static void filter_samples(short *samples) {
short fr[SIZE_DATA], fi[SIZE_DATA];
short fr[SIZE_DATA], fi[SIZE_DATA]; // used for the fft and ifft
int M, lowerbound; // M is the power of 2 that gives us the number of samples we have. lowerbound is when we start to filter
int HNHN = 0; ///////////////////////////////////////////////// garbage
// Copy sample values in table and initialise fi
//char fourier[20000];
// char *temp = " ";
// strcpy(fourier, "\nTest ");


// Copy sample values in table and initialise fi
for (int i = 0; i < SIZE_DATA; i++) {
fr[i] = samples[i];
fi[i] = 0;
//APP_LOG(APP_LOG_LEVEL_DEBUG, "\n%d", samples[i]);

//snprintf(temp,10,"%d ",samples[i]);
//strcat(fourier, temp);
}

// APP_LOG(APP_LOG_LEVEL_DEBUG,"\n%s",fourier);

// Lowerbound is ceiling of 0.05*num_samples
// Lowerbound is 0.05 * SIZE_DATA rounded up
switch (SIZE_DATA) {
case(32) : M = 5; lowerbound = 2; break;
case(64) : M = 6; lowerbound = 4; break;
@@ -163,7 +92,6 @@ static void filter_samples(short *samples) {
}

// Do the fft
HNHN = HNHN + M + 1 + lowerbound + fr[0] + fi[0]; // To avoid unused variable ; Only for Debugging
fix_fft(fr, fi, M, 0);

// Filter depending on the lowerbound
@@ -174,54 +102,46 @@ static void filter_samples(short *samples) {

// Do inverse fft to get filtered samples
int scale = fix_fft(fr, fr, M, 1);
APP_LOG(APP_LOG_LEVEL_DEBUG, "\nINVERSE\n");

// Give values back to samples array. Imaginary part is added because it seems closer to what we want
for (int i = 0; i < SIZE_DATA; i++) {
fr[i] = fr[i] << scale;
fi[i] = fi[i] << scale;
samples[i] = abs(fr[i]) + abs(fi[i]);
//APP_LOG(APP_LOG_LEVEL_DEBUG, "\n%d", samples[i]);
samples[i] = abs(fr[i]) + abs(fi[i]); // an aproximate complex modulus
}
}

// Function that compute the number of steps in the raw_data[SIZE_DATA]
// Function that compute the number of steps in the raw_data signal given by the accelerometer
static uint16_t compute_steps(short(*raw_data)[SIZE_DATA]) {
short i, squared_norm[SIZE_DATA]; // store the squared norm of the data
short i, squared_norm[SIZE_DATA];

// square norm calculation
// Squared norm computation
for (i = 0; i < SIZE_DATA; ++i)
squared_norm[i] = raw_data[X][i] * raw_data[X][i] +
raw_data[Y][i] * raw_data[Y][i] + raw_data[Z][i] * raw_data[Z][i];
raw_data[Y][i] * raw_data[Y][i] + raw_data[Z][i] * raw_data[Z][i];

APP_LOG(APP_LOG_LEVEL_DEBUG, "Starting filtering...\n");
filter_samples(squared_norm);
APP_LOG(APP_LOG_LEVEL_DEBUG, "Starting step counting...\n");
return step_count(squared_norm);
}

// Function called when num_samples are ready from the accel.
static void accel_data_handler(AccelData *data, uint32_t num_samples) {
uint32_t i;
int temp_steps;
int i;
static short counter = 0; // used to know when we have all samples ready
static short raw_data[3][SIZE_DATA]; // store those samples

APP_LOG(APP_LOG_LEVEL_DEBUG, "counter = %d\n", counter);
// Store the data from the accel. into one big array
for (i = 0; i < num_samples; ++i)
for (i = 0; i < (int)num_samples; ++i)
{
raw_data[X][i + num_samples*counter] = data[i].x >> 5; // >>5 is equivalent to /32
raw_data[Y][i + num_samples*counter] = data[i].y >> 5; // to avoid overflow with values that are too big
raw_data[Z][i + num_samples*counter] = data[i].z >> 5;
raw_data[Z][i + num_samples*counter] = data[i].z >> 5; // when computing the squared norm
}

if (counter == MAX_COUNTER) // when all the data is ready, send it
if (counter == MAX_COUNTER) // when all the data is ready, count the steps
{
APP_LOG(APP_LOG_LEVEL_DEBUG, "Sending the data...\n");
temp_steps = compute_steps(raw_data);
steps += temp_steps;
APP_LOG(APP_LOG_LEVEL_DEBUG, "Temp: %d; Total: %d\n", temp_steps, steps);
steps += compute_steps(raw_data);
counter = 0;
update_steps_window();
update_distance_window();
@@ -234,36 +154,32 @@ static void accel_data_handler(AccelData *data, uint32_t num_samples) {
// Change windows from welcome to steps
void launch_app(void *data) {
hide_welcome_window();
show_steps_window(); // first window to show
show_steps_window(); // We start the app on the steps window
}

// Init function called when app is launched
static void init(void) {
int num_samples = NUM_SAMPLES;
// Subscribe to accelerometer
accel_data_service_subscribe(num_samples, accel_data_handler);
accel_data_service_subscribe(NUM_SAMPLES, accel_data_handler);

// Define accelerometer sampling rate
accel_service_set_sampling_rate(ACCEL_SAMPLING_25HZ);

// Add a logging message (for debug)
APP_LOG(APP_LOG_LEVEL_DEBUG, "End of init'");
}

// Deinit function called when the app is closed
static void deinit(void) {
// Unsubsribe to accelerometer
accel_data_service_unsubscribe();

// Add a logging message (for debug)
APP_LOG(APP_LOG_LEVEL_DEBUG, "End of deinit'");
}

int main(void) {
init();

show_welcome_window();
app_timer_register(2000, launch_app, NULL); // Wait 2 seconds on the welcome windows, then goes to the App
app_event_loop();
app_timer_register(2000, launch_app, NULL); // 2 seconds on the welcome windows, then goes to the app

app_event_loop();

deinit();
return EXIT_SUCCESS;
}
@@ -8,6 +8,7 @@

#define NUM_WINDOWS_MENU 4 // Goal, Gender, Size and Reset rows

// Global variables for the person's infos, declared in main.c
extern int size;
extern int goal;
extern float gender;
@@ -17,28 +18,24 @@ static MenuLayer *menu_layer;
static TextLayer *s_text_layer;

// SIZE WINDOW Save the size and return to menu window
static void size_complete_callback(PIN pin, void *context)
{
static void size_complete_callback(PIN pin, void *context) {
size = pin.digits[0];
APP_LOG(APP_LOG_LEVEL_INFO, "Size is %d", size);
size_window_pop((SizeWindow*)context, true);
}

// GOAL WINDOW Save the goal and return to menu window
static void goal_complete_callback(GOALS goals, void *context)
{
static void goal_complete_callback(GOALS goals, void *context) {
goal = goals.digits[0];
APP_LOG(APP_LOG_LEVEL_INFO, "Goal is %d", goal);
goal_window_pop((GoalWindow*)context, true);
}

// Give the total number of rows
static uint16_t num_rows_callback(MenuLayer *menu_layer, uint16_t section_index, void *callback_context)
{ return NUM_WINDOWS_MENU; }
static uint16_t num_rows_callback(MenuLayer *menu_layer, uint16_t section_index, void *callback_context) {
return NUM_WINDOWS_MENU;
}

// Create the rows
static void draw_row_callback(GContext *ctx, Layer *cell_layer, MenuIndex *cell_index, void *callback_context)
{
static void draw_row_callback(GContext *ctx, Layer *cell_layer, MenuIndex *cell_index, void *callback_context) {
switch (cell_index->row)
{
case 0:
@@ -57,8 +54,7 @@ static void draw_row_callback(GContext *ctx, Layer *cell_layer, MenuIndex *cell_
}

// Callback function when a row is selected
void select_click_callback(MenuLayer *menu_layer, MenuIndex *cell_index, void *callback_context)
{
void select_click_callback(MenuLayer *menu_layer, MenuIndex *cell_index, void *callback_context) {
switch (cell_index->row)
{
case 0: //Open the goal window
@@ -78,18 +74,6 @@ void select_click_callback(MenuLayer *menu_layer, MenuIndex *cell_index, void *c
}
}

// BEGIN AUTO-GENERATED UI CODE; DO NOT MODIFY
//static Window *s_window;

//static void back_click_handler(ClickRecognizerRef recognizer, void *context) {
// hide_menu_window();
// show_welcome_window();
//}

//static void click_config_provider(void *context) {
// window_single_click_subscribe(BUTTON_ID_BACK, back_click_handler);
//}

// Create the layout
static void initialise_ui(void) {
s_window = window_create();
@@ -127,16 +111,17 @@ static void initialise_ui(void) {
layer_add_child(window_get_root_layer(s_window), menu_layer_get_layer(menu_layer));
}

// Destroy the layout
static void destroy_ui(void) {
window_destroy(s_window);
menu_layer_destroy(menu_layer);
}
// END AUTO-GENERATED UI CODE

static void handle_window_unload(Window* window) {
destroy_ui();
}

// Display the menu window on the Pebble
void show_menu_window(void) {
initialise_ui();
window_set_window_handlers(s_window, (WindowHandlers) {
@@ -145,6 +130,7 @@ void show_menu_window(void) {
window_stack_push(s_window, true);
}

// Hide the menu window, so that another window can be displayed
void hide_menu_window(void) {
window_stack_remove(s_window, true);
}
@@ -1,7 +1,10 @@
#ifndef __MENU_WINDOW_H__
#define __MENU_WINDOW_H__

// Display the menu window on the Pebble
void show_menu_window(void);

// Hide the menu window, so that another window can be displayed
void hide_menu_window(void);

#endif
@@ -8,23 +8,22 @@ static ActionBarLayer *s_action_bar_layer;

static GBitmap *s_tick_bitmap, *s_cross_bitmap;

// Global variables for the person's infos, declared in main.c
extern int steps;

// Up click configuration
static void up_click_handler(ClickRecognizerRef recognizer, void *context)
{
static void up_click_handler(ClickRecognizerRef recognizer, void *context) {
steps = 0;
APP_LOG(APP_LOG_LEVEL_INFO, "Steps = %d", steps);
window_stack_remove(s_main_window, true);
}

// Down click configuration
static void down_click_handler(ClickRecognizerRef recognizer, void *context)
{ window_stack_remove(s_main_window, true); }

static void down_click_handler(ClickRecognizerRef recognizer, void *context) {
window_stack_remove(s_main_window, true);
}

static void click_config_provider(void *context)
{
// Set the function associated to each buttons
static void click_config_provider(void *context) {
window_single_click_subscribe(BUTTON_ID_UP, up_click_handler);
window_single_click_subscribe(BUTTON_ID_DOWN, down_click_handler);
}
@@ -69,8 +68,7 @@ static void window_unload(Window *window)
}

// Push the window onto the stack
void reset_window_push()
{
void reset_window_push(void) {
if (!s_main_window) {
s_main_window = window_create();
window_set_background_color(s_main_window, PBL_IF_COLOR_ELSE(GColorJaegerGreen, GColorWhite));
@@ -1,7 +1,7 @@
#ifndef __RESET_WINDOW_H__
#define __RESET_WINDOW_H__

// Push the window onto the stack
// Push the window onto the stack
void reset_window_push();

#endif
@@ -5,40 +5,37 @@
/* THIS FILE IS GREATLY INSPIRED OF THE CODE IN THE FOLLOWING LINK
http://www.mediafire.com/file/btramcjbtnq1a9w/pinentrytestmodification.zip */

// Global variables for the person's infos, declared in main.c
extern int size;

static char* selection_handle_get_text(int index, void *context)
{
static char* selection_handle_get_text(int index, void *context) {
SizeWindow *size_window = (SizeWindow*)context;
snprintf(
size_window->field_buffs[index],
sizeof(size_window->field_buffs[0]), "%d", (int)size_window->pin.digits[index]);
return size_window->field_buffs[index];
}

static void selection_handle_complete(void *context)
{
static void selection_handle_complete(void *context) {
SizeWindow *size_window = (SizeWindow*)context;
size_window->callbacks.size_complete(size_window->pin, size_window);
}

// Size incementing
static void selection_handle_inc(int index, uint8_t clicks, void *context)
{
static void selection_handle_inc(int index, uint8_t clicks, void *context) {
SizeWindow *size_window = (SizeWindow*)context;
size_window->pin.digits[index]++;
if (size_window->pin.digits[index] > MAX_SIZE)
{
size_window->pin.digits[index] = 0;
size_window->pin.digits[index] = MIN_SIZE;
}
}

// Size decrementing
static void selection_handle_dec(int index, uint8_t clicks, void *context)
{
static void selection_handle_dec(int index, uint8_t clicks, void *context) {
SizeWindow *size_window = (SizeWindow*)context;
size_window->pin.digits[index]--;
if (size_window->pin.digits[index] < 0)
if (size_window->pin.digits[index] < MIN_SIZE)
{
size_window->pin.digits[index] = MAX_SIZE;
}
@@ -99,8 +96,8 @@ SizeWindow* size_window_create(SizeWindowCallbacks callbacks) {
return NULL;
}

void size_window_destroy(SizeWindow *size_window)
{
// Destroys the SizeWindow
void size_window_destroy(SizeWindow *size_window) {
if (size_window)
{
selection_layer_destroy(size_window->selection);
@@ -113,18 +110,22 @@ void size_window_destroy(SizeWindow *size_window)
}

// Push the window onto the stack
void size_window_push(SizeWindow *size_window, bool animated)
{ window_stack_push(size_window->window, animated); }
void size_window_push(SizeWindow *size_window, bool animated) {
window_stack_push(size_window->window, animated);
}

// Push the window off the stack
void size_window_pop(SizeWindow *size_window, bool animated)
{ window_stack_remove(size_window->window, animated); }
void size_window_pop(SizeWindow *size_window, bool animated) {
window_stack_remove(size_window->window, animated);
}

bool size_window_get_topmost_window(SizeWindow *size_window)
{ return window_stack_get_top_window() == size_window->window; }
// Gets whether it is the topmost window or not
bool size_window_get_topmost_window(SizeWindow *size_window) {
return window_stack_get_top_window() == size_window->window;
}

void size_window_set_highlight_color(SizeWindow *size_window, GColor color)
{
// Sets the over-all color scheme of the window
void size_window_set_highlight_color(SizeWindow *size_window, GColor color) {
size_window->highlight_color = color;
selection_layer_set_active_bg_color(size_window->selection, color);
}
@@ -8,6 +8,7 @@

#define NUM_CELLS 1
#define MAX_SIZE 250
#define MIN_SIZE 70

typedef struct {
int digits[NUM_CELLS];
@@ -37,7 +38,7 @@ typedef struct {
// Creates the SizeWindow in memory but does not push it into view
SizeWindow* size_window_create(SizeWindowCallbacks size_window_callbacks);

// Destroys the GoalWindow
// Destroys the SizeWindow
void size_window_destroy(SizeWindow *size_window);

// Push the window onto the stack
@@ -12,9 +12,10 @@ static TextLayer *s_textlayer_2;
static TextLayer *s_textlayer_3;
StatusBarLayer *status_bar_layer;

// Variables
// Global variables for the person's infos, declared in main.c
extern int steps;
extern int goal;

static char buffer1[16];
static char buffer2[16];
static char testbuffer[25];
@@ -51,7 +52,6 @@ static void display_value(uint16_t value, char buffer[]) {

// Update routine for the progress bar
static void progress_layer_update_proc(Layer *layer, GContext *ctx) {
APP_LOG(APP_LOG_LEVEL_INFO, "progress update");
GRect inset;

// If the current goal is overpassed, the progress bar continues with another color
@@ -91,7 +91,7 @@ static void progress_layer_update_proc(Layer *layer, GContext *ctx) {
graphics_fill_radial(ctx, inset, GOvalScaleModeFitCircle, 7, trigangle - line_width_trigangle, trigangle);

}
else {
else { // Or display the simple progress bar toward goal
// progress bar
inset = grect_inset(layer_get_bounds(layer), GEdgeInsets(16));
graphics_context_set_fill_color(ctx, GColorDarkGray);
@@ -122,7 +122,7 @@ static void progress_layer_update_proc(Layer *layer, GContext *ctx) {
graphics_fill_radial(ctx, inset, GOvalScaleModeFitCircle, 8, trigangle - line_width_trigangle, trigangle);
}

// Update text_layers
// Update the text layers (steps and goal)
display_value(steps, buffer1);
text_layer_set_text(s_textlayer_2, buffer1);

@@ -131,10 +131,10 @@ static void progress_layer_update_proc(Layer *layer, GContext *ctx) {
text_layer_set_text(s_textlayer_3, testbuffer);
}

// Init function called when the window is created
static void initialise_ui(void) {
s_window = window_create();
s_window_layer = window_get_root_layer(s_window);
//GRect window_bounds = layer_get_bounds(s_window_layer);
window_set_click_config_provider(s_window, click_config_provider); // buttons interactions
window_set_background_color(s_window, GColorBlack);
#ifndef PBL_SDK_3
@@ -159,8 +159,6 @@ static void initialise_ui(void) {
s_textlayer_2 = text_layer_create(GRect(41, 48, 62, 30));
text_layer_set_background_color(s_textlayer_2, GColorBlack);
text_layer_set_text_color(s_textlayer_2, GColorWhite);
//display_value(steps, buffer1);
//text_layer_set_text(s_textlayer_2, buffer1);
text_layer_set_font(s_textlayer_2, s_res_gothic_28_bold);
text_layer_set_text_alignment(s_textlayer_2, GTextAlignmentCenter);
layer_add_child(s_window_layer, (Layer *)s_textlayer_2);
@@ -169,14 +167,12 @@ static void initialise_ui(void) {
s_textlayer_3 = text_layer_create(GRect(0, 143, 144, 20));
text_layer_set_background_color(s_textlayer_3, GColorBlack);
text_layer_set_text_color(s_textlayer_3, GColorWhite);
//display_value(goal, buffer2);
//snprintf(testbuffer, sizeof(testbuffer),"%s %s", "Current goal:", buffer2);
//text_layer_set_text(s_textlayer_3, testbuffer);
text_layer_set_text_alignment(s_textlayer_3, GTextAlignmentCenter);
text_layer_set_font(s_textlayer_3, fonts_get_system_font(FONT_KEY_GOTHIC_14));
layer_add_child(window_get_root_layer(s_window), (Layer *)s_textlayer_3);
}

// Deinit function called when the window is destroyed
static void destroy_ui(void) {
window_destroy(s_window);
status_bar_layer_destroy(status_bar_layer);
@@ -189,6 +185,7 @@ static void handle_window_unload(Window* window) {
destroy_ui();
}

// Display the steps window on the Pebble
void show_steps_window(void) {
initialise_ui();
window_set_window_handlers(s_window, (WindowHandlers) {
@@ -197,11 +194,13 @@ void show_steps_window(void) {
window_stack_push(s_window, true);
}

// Ask for an update of the steps window to display current values
void update_steps_window(void) {
if (s_window != NULL)
if (s_window)
layer_mark_dirty(s_progress_layer);
}

// Hide the steps window, so that another window can be displayed
void hide_steps_window(void) {
window_stack_remove(s_window, true);
}
@@ -1,8 +1,13 @@
#ifndef __STEPS_WINDOW_H__
#define __STEPS_WINDOW_H__

// Display the steps window on the Pebble
void show_steps_window(void);

// Ask for an update of the steps window to display current values
void update_steps_window(void);

// Hide the steps window, so that another window can be displayed
void hide_steps_window(void);

#endif
@@ -10,6 +10,7 @@ static TextLayer *s_textlayer_3;
static TextLayer *s_textlayer_4;
static BitmapLayer *s_bitmaplayer_1;

// Init function called when the window is created
static void initialise_ui(void) {
s_window = window_create();
#ifndef PBL_SDK_3
@@ -54,6 +55,7 @@ static void initialise_ui(void) {
layer_add_child(window_get_root_layer(s_window), (Layer *)s_bitmaplayer_1);
}

// Deinit function called when the window is destroyed
static void destroy_ui(void) {
window_destroy(s_window);
text_layer_destroy(s_textlayer_1);
@@ -68,12 +70,14 @@ static void handle_window_unload(Window* window) {
destroy_ui();
}

// Display the welcome window on the Pebble
void show_welcome_window(void) {
initialise_ui();
window_set_window_handlers(s_window, (WindowHandlers) {.unload = handle_window_unload,});
window_stack_push(s_window, true);
}

// Hide the welcome window, so that another window can be displayed
void hide_welcome_window(void) {
window_stack_remove(s_window, true);
}
@@ -1,7 +1,10 @@
#ifndef __WELCOME_WINDOW_H__
#define __WELCOME_WINDOW_H__

// Display the welcome window on the Pebble
void show_welcome_window(void);

// Hide the welcome window, so that another window can be displayed
void hide_welcome_window(void);

#endif