mirror of
https://github.com/google/pebble.git
synced 2025-06-13 05:03:12 +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
216
src/fw/apps/demo_apps/data_logging_test.c
Normal file
216
src/fw/apps/demo_apps/data_logging_test.c
Normal file
|
@ -0,0 +1,216 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "data_logging_test.h"
|
||||
|
||||
#include "system/logging.h"
|
||||
#include "services/common/comm_session/session.h"
|
||||
#include "services/normal/data_logging/data_logging_service.h"
|
||||
#include "services/normal/data_logging/dls_private.h"
|
||||
#include "applib/app.h"
|
||||
#include "applib/data_logging.h"
|
||||
#include "applib/ui/app_window_stack.h"
|
||||
#include "applib/ui/window.h"
|
||||
#include "applib/ui/text_layer.h"
|
||||
#include "applib/app_timer.h"
|
||||
#include "applib/app_logging.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
* Incremental STM CRC32 implemented in software
|
||||
*/
|
||||
|
||||
#define CRC_POLY 0x04C11DB7
|
||||
|
||||
static uint32_t crc_init(void) {
|
||||
return 0xffffffff;
|
||||
}
|
||||
|
||||
static uint32_t crc_update(uint32_t crc, const uint8_t *data, uint32_t length) {
|
||||
const uint8_t num_remainder_bytes = length % 4;
|
||||
uint32_t num_whole_word_bytes = length / 4;
|
||||
|
||||
while (num_whole_word_bytes--) {
|
||||
crc = crc ^ *((uint32_t*)data);
|
||||
for(int bit = 0; bit < 32; ++bit) {
|
||||
if ((crc & 0x80000000) != 0) {
|
||||
crc = (crc << 1) ^ CRC_POLY;
|
||||
} else {
|
||||
crc = (crc << 1);
|
||||
}
|
||||
}
|
||||
data += 4;
|
||||
}
|
||||
|
||||
if (num_remainder_bytes) {
|
||||
uint32_t last_word = 0;
|
||||
for (unsigned int i = 0; i < num_remainder_bytes; ++i) {
|
||||
last_word = (last_word << 8) | data[i];
|
||||
}
|
||||
return crc_update(crc, (uint8_t*)&last_word, 4);
|
||||
}
|
||||
|
||||
return crc & 0xffffffff;
|
||||
}
|
||||
|
||||
/*
|
||||
* Data Logging Test App
|
||||
*/
|
||||
|
||||
struct DataLoggingInfo {
|
||||
TextLayer text_layer;
|
||||
char text[32];
|
||||
int counter;
|
||||
uint32_t crc;
|
||||
DataLoggingSessionRef logging_session;
|
||||
uint8_t item_size;
|
||||
};
|
||||
|
||||
static struct {
|
||||
Window window;
|
||||
struct DataLoggingInfo info[3];
|
||||
TextLayer log_layer;
|
||||
} s_data;
|
||||
|
||||
static const int s_chunk_size = 80;
|
||||
|
||||
static void log_moar_data(struct DataLoggingInfo *info) {
|
||||
uint8_t buf[s_chunk_size];
|
||||
|
||||
for (int i = 0; i < s_chunk_size; i++) {
|
||||
buf[i] = (info->counter * s_chunk_size) + i;
|
||||
}
|
||||
|
||||
info->crc = crc_update(info->crc, buf, s_chunk_size);
|
||||
data_logging_log(info->logging_session, buf, s_chunk_size / info->item_size);
|
||||
++info->counter;
|
||||
}
|
||||
|
||||
static void handle_timer(void *ck) {
|
||||
if (s_data.info[0].logging_session == NULL) {
|
||||
// Sessions closed.
|
||||
return;
|
||||
}
|
||||
struct DataLoggingInfo*info = ck;
|
||||
|
||||
log_moar_data(info);
|
||||
|
||||
const int num_chunks = 30;
|
||||
|
||||
snprintf(info->text, sizeof(info->text), "%lu (%i) %i/%i", info->crc, info->counter * s_chunk_size, info->counter, num_chunks);
|
||||
text_layer_set_text(&info->text_layer, info->text);
|
||||
|
||||
if (info->counter < num_chunks) {
|
||||
app_timer_register(1000 /* milliseconds */, handle_timer, info);
|
||||
} else {
|
||||
text_layer_set_text(&s_data.log_layer, "Done logging. Select to close.");
|
||||
}
|
||||
}
|
||||
|
||||
static void close_sessions(void) {
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
data_logging_finish(s_data.info[i].logging_session);
|
||||
s_data.info[i].logging_session = NULL;
|
||||
}
|
||||
text_layer_set_text(&s_data.log_layer, "Closed all logging sessions.");
|
||||
}
|
||||
|
||||
static void start_logging(void) {
|
||||
const uint8_t item_size[] = {4, 2, 16};
|
||||
const DataLoggingItemType types[] = {DATA_LOGGING_INT, DATA_LOGGING_UINT, DATA_LOGGING_BYTE_ARRAY};
|
||||
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
text_layer_set_text(&s_data.info[i].text_layer, "Empty");
|
||||
s_data.info[i].item_size = item_size[i];
|
||||
s_data.info[i].logging_session = data_logging_create(i + 1, types[i], item_size[i], false);
|
||||
}
|
||||
|
||||
// start timers
|
||||
app_timer_register(2000 /* milliseconds */, handle_timer, (void *) &s_data.info[0]);
|
||||
app_timer_register(1500 /* milliseconds */, handle_timer, (void *) &s_data.info[1]);
|
||||
app_timer_register(4500 /* milliseconds */, handle_timer, (void *) &s_data.info[2]);
|
||||
|
||||
text_layer_set_text(&s_data.log_layer, "Logging...");
|
||||
}
|
||||
|
||||
static void select_click_handler(ClickRecognizerRef recognizer, void *context) {
|
||||
if (s_data.info[0].logging_session) {
|
||||
close_sessions();
|
||||
} else {
|
||||
start_logging();
|
||||
}
|
||||
}
|
||||
|
||||
static void click_config_provider(void *context) {
|
||||
window_single_click_subscribe(BUTTON_ID_SELECT, select_click_handler);
|
||||
}
|
||||
|
||||
|
||||
static void handle_deinit(void) {
|
||||
comm_session_set_responsiveness(comm_session_get_system_session(), BtConsumerApp,
|
||||
ResponseTimeMax, MAX_PERIOD_RUN_FOREVER);
|
||||
}
|
||||
|
||||
static void handle_init(void) {
|
||||
dls_clear();
|
||||
|
||||
memset(&s_data, 0, sizeof(s_data));
|
||||
// Init window
|
||||
window_init(&s_data.window, "Logging Demo");
|
||||
app_window_stack_push(&s_data.window, true /* Animated */);
|
||||
window_set_click_config_provider_with_context(&s_data.window, click_config_provider,
|
||||
&s_data.window);
|
||||
|
||||
const GRect *bounds = &s_data.window.layer.bounds;
|
||||
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
s_data.info[i].crc = crc_init();
|
||||
text_layer_init(&s_data.info[i].text_layer, &GRect(0, i * 20, bounds->size.w, 20));
|
||||
layer_add_child(&s_data.window.layer, &s_data.info[i].text_layer.layer);
|
||||
}
|
||||
|
||||
text_layer_init(&s_data.log_layer, &GRect(0, bounds->size.w / 2, bounds->size.w,
|
||||
bounds->size.w / 2));
|
||||
layer_add_child(&s_data.window.layer, &s_data.log_layer.layer);
|
||||
|
||||
start_logging();
|
||||
|
||||
comm_session_set_responsiveness(comm_session_get_system_session(), BtConsumerApp,
|
||||
ResponseTimeMax, MAX_PERIOD_RUN_FOREVER);
|
||||
}
|
||||
|
||||
////////////////////
|
||||
// App boilerplate
|
||||
|
||||
static void s_main(void) {
|
||||
handle_init();
|
||||
|
||||
app_event_loop();
|
||||
|
||||
handle_deinit();
|
||||
}
|
||||
|
||||
const PebbleProcessMd* data_logging_test_get_info() {
|
||||
static const PebbleProcessMdSystem s_app_info = {
|
||||
// UUID: 01020304-0506-0708-0910-111213141516
|
||||
.common.uuid = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16},
|
||||
.common.main_func = &s_main,
|
||||
.name = "Data Logging Test"
|
||||
};
|
||||
return (const PebbleProcessMd*) &s_app_info;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue