mirror of
https://github.com/google/pebble.git
synced 2025-07-04 06:06:20 +00:00
Import of the watch repository from Pebble
This commit is contained in:
commit
3b92768480
10334 changed files with 2564465 additions and 0 deletions
331
src/fw/apps/demo_apps/flash_test.c
Normal file
331
src/fw/apps/demo_apps/flash_test.c
Normal file
|
@ -0,0 +1,331 @@
|
|||
/*
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
// This app only makes sense on Snowy, as it uses addresses and sector sizes that only make sense
|
||||
// on our parallel flash hardware
|
||||
#if CAPABILITY_USE_PARALLEL_FLASH
|
||||
|
||||
#include "flash_test.h"
|
||||
|
||||
#include "applib/app.h"
|
||||
#include "applib/ui/app_window_stack.h"
|
||||
#include "applib/ui/simple_menu_layer.h"
|
||||
#include "applib/ui/text_layer.h"
|
||||
#include "applib/ui/window.h"
|
||||
#include "applib/ui/window_stack.h"
|
||||
|
||||
|
||||
#include "mfg/mfg_apps/mfg_flash_test.h"
|
||||
#include "process_state/app_state/app_state.h"
|
||||
#include "services/common/system_task.h"
|
||||
#include "system/logging.h"
|
||||
|
||||
#include "kernel/pbl_malloc.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
enum FlashTestCaseStatus {
|
||||
FLASH_TEST_STATUS_INIT = 0,
|
||||
FLASH_TEST_STATUS_RUNNING = 1,
|
||||
FLASH_TEST_STATUS_STOPPED = 2,
|
||||
FLASH_TEST_STATUS_PASSED = 3,
|
||||
FLASH_TEST_STATUS_FAILED = 4,
|
||||
};
|
||||
|
||||
#define STATUS_TEXT_SIZE 18
|
||||
struct FlashTestData {
|
||||
Window window;
|
||||
SimpleMenuLayer simple_menu_layer;
|
||||
SimpleMenuSection menu_sections[1];
|
||||
SimpleMenuItem menu_items[FLASH_TEST_CASE_NUM_MENU_ITEMS];
|
||||
Window test_window;
|
||||
TextLayer msg_text_layer[3];
|
||||
TextLayer status_text_layer;
|
||||
char status_text[STATUS_TEXT_SIZE];
|
||||
FlashTestCaseType test_case;
|
||||
uint8_t test_case_status;
|
||||
};
|
||||
|
||||
/***********************************************************/
|
||||
/******************* Window Related Functions **************/
|
||||
/***********************************************************/
|
||||
static void handle_timer(struct tm *tick_time, TimeUnits units_changed) {
|
||||
struct FlashTestData *data = app_state_get_user_data();
|
||||
// simply marking the window dirty will make everything update
|
||||
if (data && (data->test_case_status != FLASH_TEST_STATUS_INIT))
|
||||
{
|
||||
layer_mark_dirty(&data->test_window.layer);
|
||||
}
|
||||
}
|
||||
|
||||
static void update_test_case_status(struct FlashTestData *data) {
|
||||
switch (data->test_case_status) {
|
||||
case FLASH_TEST_STATUS_INIT:
|
||||
snprintf(data->status_text, STATUS_TEXT_SIZE, "Test Initialized");
|
||||
break;
|
||||
case FLASH_TEST_STATUS_RUNNING:
|
||||
snprintf(data->status_text, STATUS_TEXT_SIZE, "Test Running");
|
||||
break;
|
||||
case FLASH_TEST_STATUS_STOPPED:
|
||||
snprintf(data->status_text, STATUS_TEXT_SIZE, "Test Stopped");
|
||||
break;
|
||||
case FLASH_TEST_STATUS_PASSED:
|
||||
snprintf(data->status_text, STATUS_TEXT_SIZE, "Test Passed");
|
||||
break;
|
||||
case FLASH_TEST_STATUS_FAILED:
|
||||
snprintf(data->status_text, STATUS_TEXT_SIZE, "Test Failed");
|
||||
break;
|
||||
default:
|
||||
snprintf(data->status_text, STATUS_TEXT_SIZE, "Unknown Status");
|
||||
PBL_LOG(LOG_LEVEL_DEBUG, "ERROR: Unknown Test Case Selected");
|
||||
break;
|
||||
}
|
||||
|
||||
text_layer_set_text(&data->status_text_layer, data->status_text);
|
||||
}
|
||||
|
||||
static void test_window_load(Window *window) {
|
||||
struct FlashTestData *data = app_state_get_user_data();
|
||||
|
||||
window_set_background_color(window, GColorBlack);
|
||||
|
||||
TextLayer *msg_text_layer = &data->msg_text_layer[0];
|
||||
text_layer_init(msg_text_layer, &GRect(0, 12, window->layer.bounds.size.w, 18));
|
||||
switch (data->test_case) {
|
||||
case FLASH_TEST_CASE_RUN_DATA_TEST:
|
||||
text_layer_set_text(msg_text_layer, "Data Bus Test");
|
||||
break;
|
||||
case FLASH_TEST_CASE_RUN_ADDR_TEST:
|
||||
text_layer_set_text(msg_text_layer, "Addr Bus Test");
|
||||
break;
|
||||
case FLASH_TEST_CASE_RUN_STRESS_ADDR_TEST:
|
||||
text_layer_set_text(msg_text_layer, "Stress Addr Test");
|
||||
break;
|
||||
case FLASH_TEST_CASE_RUN_PERF_DATA_TEST:
|
||||
text_layer_set_text(msg_text_layer, "Perf Data Test");
|
||||
break;
|
||||
case FLASH_TEST_CASE_RUN_SWITCH_MODE_ASYNC:
|
||||
case FLASH_TEST_CASE_RUN_SWITCH_MODE_SYNC_BURST:
|
||||
text_layer_set_text(msg_text_layer, "Switch Mode");
|
||||
break;
|
||||
default:
|
||||
text_layer_set_text(msg_text_layer, "Unknown Test");
|
||||
break;
|
||||
}
|
||||
|
||||
text_layer_set_text_alignment(msg_text_layer, GTextAlignmentCenter);
|
||||
text_layer_set_background_color(msg_text_layer, GColorBlack);
|
||||
text_layer_set_text_color(msg_text_layer, GColorWhite);
|
||||
text_layer_set_font(msg_text_layer, fonts_get_system_font(FONT_KEY_GOTHIC_14_BOLD));
|
||||
layer_add_child(&window->layer, &msg_text_layer->layer);
|
||||
|
||||
msg_text_layer = &data->msg_text_layer[1];
|
||||
text_layer_init(msg_text_layer, &GRect(0, 32, window->layer.bounds.size.w, 18));
|
||||
if (data->test_case >= FLASH_TEST_CASE_RUN_SWITCH_MODE_ASYNC) {
|
||||
text_layer_set_text(msg_text_layer, "Select To Confirm Switch");
|
||||
}
|
||||
else {
|
||||
text_layer_set_text(msg_text_layer, "Press Select To Start");
|
||||
}
|
||||
text_layer_set_text_alignment(msg_text_layer, GTextAlignmentCenter);
|
||||
text_layer_set_background_color(msg_text_layer, GColorBlack);
|
||||
text_layer_set_text_color(msg_text_layer, GColorWhite);
|
||||
text_layer_set_font(msg_text_layer, fonts_get_system_font(FONT_KEY_GOTHIC_14_BOLD));
|
||||
layer_add_child(&window->layer, &msg_text_layer->layer);
|
||||
|
||||
msg_text_layer = &data->msg_text_layer[2];
|
||||
text_layer_init(msg_text_layer, &GRect(0, 64, window->layer.bounds.size.w, 40));
|
||||
if (data->test_case >= FLASH_TEST_CASE_RUN_SWITCH_MODE_ASYNC) {
|
||||
text_layer_set_text(msg_text_layer, "Press Back To Exit");
|
||||
}
|
||||
else {
|
||||
text_layer_set_text(msg_text_layer, "Press Up to Exit, Down to Stop Test");
|
||||
}
|
||||
text_layer_set_text_alignment(msg_text_layer, GTextAlignmentCenter);
|
||||
text_layer_set_background_color(msg_text_layer, GColorBlack);
|
||||
text_layer_set_text_color(msg_text_layer, GColorWhite);
|
||||
text_layer_set_font(msg_text_layer, fonts_get_system_font(FONT_KEY_GOTHIC_14_BOLD));
|
||||
layer_add_child(&window->layer, &msg_text_layer->layer);
|
||||
|
||||
TextLayer *status_text_layer = &data->status_text_layer;
|
||||
text_layer_init(status_text_layer, &GRect(0, 106, window->layer.bounds.size.w, 40));
|
||||
text_layer_set_text_alignment(status_text_layer, GTextAlignmentCenter);
|
||||
text_layer_set_background_color(status_text_layer, GColorBlack);
|
||||
text_layer_set_text_color(status_text_layer, GColorWhite);
|
||||
text_layer_set_font(status_text_layer, fonts_get_system_font(FONT_KEY_GOTHIC_14_BOLD));
|
||||
layer_add_child(&window->layer, &status_text_layer->layer);
|
||||
|
||||
update_test_case_status(data);
|
||||
}
|
||||
|
||||
void flash_test_dismiss_window(void) {
|
||||
struct FlashTestData *data = app_state_get_user_data();
|
||||
|
||||
const bool animated = true;
|
||||
window_stack_remove(&data->test_window, animated);
|
||||
}
|
||||
|
||||
static void up_click_handler(ClickRecognizerRef recognizer, void *unusued) {
|
||||
struct FlashTestData *data = app_state_get_user_data();
|
||||
|
||||
if (data->test_case_status != FLASH_TEST_STATUS_RUNNING) {
|
||||
flash_test_dismiss_window();
|
||||
}
|
||||
}
|
||||
|
||||
static void down_click_handler(ClickRecognizerRef recognizer, void *unusued) {
|
||||
struct FlashTestData *data = app_state_get_user_data();
|
||||
|
||||
// Only stop stress test
|
||||
if ((data->test_case == FLASH_TEST_CASE_RUN_STRESS_ADDR_TEST) && (data->test_case_status == FLASH_TEST_STATUS_RUNNING)) {
|
||||
data->test_case_status = FLASH_TEST_STATUS_STOPPED;
|
||||
stop_flash_test_case();
|
||||
update_test_case_status(data);
|
||||
}
|
||||
}
|
||||
|
||||
static void run_test(void* context) {
|
||||
struct FlashTestData *data = app_state_get_user_data();
|
||||
FlashTestErrorType status = FLASH_TEST_SUCCESS;
|
||||
|
||||
// Execute test - pass in 0 by default for iterations
|
||||
status = run_flash_test_case(data->test_case, 0);
|
||||
|
||||
if (status == FLASH_TEST_SUCCESS) {
|
||||
data->test_case_status = FLASH_TEST_STATUS_PASSED;
|
||||
}
|
||||
else {
|
||||
PBL_LOG(LOG_LEVEL_DEBUG, ">>>>>FAILED TEST CASE<<<<<");
|
||||
data->test_case_status = FLASH_TEST_STATUS_FAILED;
|
||||
}
|
||||
|
||||
update_test_case_status(data);
|
||||
}
|
||||
|
||||
static void select_click_handler(ClickRecognizerRef recognizer, void *unusued) {
|
||||
struct FlashTestData *data = app_state_get_user_data();
|
||||
|
||||
if ((data->test_case == FLASH_TEST_CASE_RUN_STRESS_ADDR_TEST) && (data->test_case_status == FLASH_TEST_STATUS_RUNNING)) {
|
||||
data->test_case_status = FLASH_TEST_STATUS_STOPPED;
|
||||
stop_flash_test_case();
|
||||
update_test_case_status(data);
|
||||
}
|
||||
else if (data->test_case_status == FLASH_TEST_STATUS_INIT) {
|
||||
data->test_case_status = FLASH_TEST_STATUS_RUNNING;
|
||||
update_test_case_status(data);
|
||||
system_task_add_callback(run_test, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void click_config_provider(void *context) {
|
||||
window_single_click_subscribe(BUTTON_ID_UP, (ClickHandler)up_click_handler);
|
||||
window_single_click_subscribe(BUTTON_ID_DOWN, (ClickHandler)down_click_handler);
|
||||
window_single_click_subscribe(BUTTON_ID_SELECT, (ClickHandler)select_click_handler);
|
||||
}
|
||||
|
||||
static void flash_test_select_callback(int index, void *context) {
|
||||
struct FlashTestData *data = (struct FlashTestData *) context;
|
||||
|
||||
data->test_case = index;
|
||||
data->test_case_status = FLASH_TEST_STATUS_INIT;
|
||||
|
||||
// Display window for running test case
|
||||
// Init the window
|
||||
Window *test_window = &data->test_window;
|
||||
window_init(test_window, WINDOW_NAME("Test Case"));
|
||||
window_set_window_handlers(test_window, &(WindowHandlers) {
|
||||
.load = test_window_load,
|
||||
});
|
||||
window_set_user_data(test_window, data);
|
||||
window_set_click_config_provider(test_window, click_config_provider);
|
||||
|
||||
const bool animated = true;
|
||||
app_window_stack_push(test_window, animated);
|
||||
}
|
||||
|
||||
static void flash_test_window_load(Window *window) {
|
||||
struct FlashTestData *data = (struct FlashTestData*) window_get_user_data(window);
|
||||
|
||||
// Configure menu items:
|
||||
uint8_t num_items = 0;
|
||||
data->menu_items[num_items++] = (SimpleMenuItem) { .title = "Run Data Test",
|
||||
.callback = flash_test_select_callback};
|
||||
data->menu_items[num_items++] = (SimpleMenuItem) { .title = "Run Address Test",
|
||||
.callback = flash_test_select_callback};
|
||||
data->menu_items[num_items++] = (SimpleMenuItem) { .title = "Run Stress Test",
|
||||
.callback = flash_test_select_callback};
|
||||
data->menu_items[num_items++] = (SimpleMenuItem) { .title = "Run Perf Data Test",
|
||||
.callback = flash_test_select_callback};
|
||||
data->menu_items[num_items++] = (SimpleMenuItem) { .title = "-->Async Mode",
|
||||
.callback = flash_test_select_callback};
|
||||
data->menu_items[num_items++] = (SimpleMenuItem) { .title = "-->Sync Burst Mode",
|
||||
.callback = flash_test_select_callback};
|
||||
|
||||
data->menu_sections[0].num_items = num_items;
|
||||
data->menu_sections[0].items = data->menu_items;
|
||||
|
||||
// Configure simple menu:
|
||||
const GRect *bounds = &data->window.layer.bounds;
|
||||
simple_menu_layer_init(&data->simple_menu_layer, bounds, window, data->menu_sections, 1, data);
|
||||
layer_add_child(&data->window.layer, simple_menu_layer_get_layer(&data->simple_menu_layer));
|
||||
}
|
||||
|
||||
static void handle_init(void) {
|
||||
struct FlashTestData* data_ptr = app_malloc_check(sizeof(struct FlashTestData));
|
||||
|
||||
memset(data_ptr, 0, sizeof(struct FlashTestData));
|
||||
|
||||
app_state_set_user_data(data_ptr);
|
||||
|
||||
window_init(&data_ptr->window, WINDOW_NAME("Flash Test"));
|
||||
window_set_user_data(&data_ptr->window, data_ptr);
|
||||
window_set_window_handlers(&data_ptr->window, &(WindowHandlers){
|
||||
.load = flash_test_window_load,
|
||||
});
|
||||
|
||||
const bool animated = true;
|
||||
app_window_stack_push(&data_ptr->window, animated);
|
||||
|
||||
tick_timer_service_subscribe(SECOND_UNIT, handle_timer);
|
||||
}
|
||||
|
||||
static void handle_deinit(void) {
|
||||
struct FlashTestData *data = app_state_get_user_data();
|
||||
simple_menu_layer_deinit(&data->simple_menu_layer);
|
||||
app_free(data);
|
||||
|
||||
stop_flash_test_case();
|
||||
}
|
||||
|
||||
|
||||
static void s_main(void) {
|
||||
handle_init();
|
||||
|
||||
app_event_loop();
|
||||
|
||||
handle_deinit();
|
||||
}
|
||||
|
||||
const PebbleProcessMd* flash_test_demo_get_app_info(void) {
|
||||
static const PebbleProcessMdSystem s_app_info = {
|
||||
.common.main_func = s_main,
|
||||
.name = "Flash Test"
|
||||
};
|
||||
return (const PebbleProcessMd*) &s_app_info;
|
||||
}
|
||||
|
||||
#endif // CAPABILITY_USE_PARALLEL_FLASH
|
Loading…
Add table
Add a link
Reference in a new issue