this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Initial implementation

alice 44521a88

+248
+2
.gitignore
··· 1 + build/ 2 + .lock*
+29
package.json
··· 1 + { 2 + "name": "tidface", 3 + "author": "aliceisjustplaying", 4 + "version": "1.0.0", 5 + "keywords": ["pebble-app"], 6 + "private": true, 7 + "dependencies": {}, 8 + "pebble": { 9 + "displayName": "tidface", 10 + "uuid": "d3486974-f487-4d30-b67f-9143c3ce7ab3", 11 + "sdkVersion": "3", 12 + "enableMultiJS": true, 13 + "targetPlatforms": [ 14 + "aplite", 15 + "basalt", 16 + "chalk", 17 + "diorite" 18 + ], 19 + "watchapp": { 20 + "watchface": true 21 + }, 22 + "messageKeys": [ 23 + "dummy" 24 + ], 25 + "resources": { 26 + "media": [] 27 + } 28 + } 29 + }
+163
src/c/watchface.c
··· 1 + #include <pebble.h> 2 + #include <stdlib.h> 3 + #include <string.h> 4 + #include <stdint.h> 5 + 6 + static Window *s_main_window; 7 + static TextLayer *s_time_layer; 8 + 9 + static const char S32_CHAR[] = "234567abcdefghijklmnopqrstuvwxyz"; 10 + #define S32_CHAR_LEN (sizeof(S32_CHAR) - 1) // 32 11 + 12 + static uint64_t last_timestamp = 0; 13 + 14 + // Encodes 'i' into 'buffer' (size 'buffer_len'). 15 + // Returns a pointer to the start of the encoded string within the buffer. 16 + // Fills from the end. Result is NOT null-terminated by this function itself. 17 + static char* s32encode_c(uint64_t i, char *buffer, size_t buffer_len) { 18 + if (buffer_len == 0) return NULL; 19 + 20 + char *ptr = buffer + buffer_len; // Point *past* the end 21 + 22 + // Handle 0 case directly if timestamp/clockid can be 0 23 + if (i == 0 && ptr > buffer) { 24 + *(--ptr) = S32_CHAR[0]; // '2' 25 + return ptr; 26 + } 27 + 28 + // Encode the number from right to left 29 + while (i > 0 && ptr > buffer) { 30 + // Optimize: Use bitwise operations for division/modulo by 32 (2^5) 31 + uint8_t remainder = i & 31; // i % 32 32 + i >>= 5; // i / 32 33 + *(--ptr) = S32_CHAR[remainder]; // Place character and move pointer left 34 + } 35 + 36 + // If i is still > 0 here, the buffer was too small for the number. 37 + // This shouldn't happen for timestamp (11 chars) or clockid (2 chars). 38 + 39 + return ptr; // Pointer to the first character written 40 + } 41 + 42 + 43 + // Creates a TID in tid_buffer (size must be >= 14) 44 + static void createRaw_c(uint64_t timestamp, uint16_t clockid, char *tid_buffer, size_t tid_buffer_len) { 45 + if (tid_buffer_len < 14) return; // Need space for 13 chars + null terminator 46 + 47 + // --- Timestamp Encoding (11 chars) --- 48 + char ts_temp_buffer[11]; 49 + char* encoded_ts_start = s32encode_c(timestamp, ts_temp_buffer, sizeof(ts_temp_buffer)); 50 + size_t encoded_ts_len = (ts_temp_buffer + sizeof(ts_temp_buffer)) - encoded_ts_start; 51 + 52 + // Pad beginning with '2' 53 + memset(tid_buffer, '2', 11); 54 + // Copy encoded part to the end of the 11-char section 55 + if (encoded_ts_start && encoded_ts_len > 0) { 56 + if (encoded_ts_len <= 11) { 57 + memcpy(tid_buffer + (11 - encoded_ts_len), encoded_ts_start, encoded_ts_len); 58 + } else { 59 + // Timestamp too large? Copy last 11 chars. 60 + memcpy(tid_buffer, encoded_ts_start + (encoded_ts_len - 11), 11); 61 + } 62 + } 63 + // If timestamp was 0, encoded_ts_len is 1 ('2'), correctly placed by the above. 64 + 65 + 66 + // --- Hardcoded Clock ID ("22") --- 67 + // The new logic always appends "22", ignoring the clockid parameter. 68 + tid_buffer[11] = S32_CHAR[0]; // '2' 69 + tid_buffer[12] = S32_CHAR[0]; // '2' 70 + 71 + // Null-terminate the final string 72 + tid_buffer[13] = '\0'; 73 + } 74 + 75 + // Generates a new TID into tid_buffer (size must be >= 14) 76 + static void now_c(char *tid_buffer, size_t tid_buffer_len) { 77 + if (tid_buffer_len < 14) return; 78 + 79 + time_t seconds; 80 + uint16_t milliseconds; 81 + // Get time with millisecond precision 82 + time_ms(&seconds, &milliseconds); 83 + 84 + // Convert to microseconds (Pebble resolution) 85 + uint64_t current_micros = (uint64_t)seconds * 1000000 + (uint64_t)milliseconds * 1000; 86 + 87 + // Ensure monotonicity (at microsecond level) 88 + if (current_micros <= last_timestamp) { 89 + current_micros = last_timestamp + 1; 90 + } 91 + last_timestamp = current_micros; 92 + 93 + // Create the final TID string 94 + // Pass 0 for clockid, although it's ignored by the modified createRaw_c 95 + createRaw_c(current_micros, 0, tid_buffer, tid_buffer_len); 96 + } 97 + 98 + 99 + // --- Watchface Code --- 100 + 101 + static void main_window_load(Window *window) { 102 + // Get information about the Window 103 + Layer *window_layer = window_get_root_layer(window); 104 + GRect bounds = layer_get_bounds(window_layer); 105 + 106 + // Create the TextLayer with specific bounds 107 + s_time_layer = 108 + text_layer_create(GRect(0, PBL_IF_ROUND_ELSE(58, 52), bounds.size.w, 50)); 109 + 110 + // Improve the layout to be more like a watchface 111 + text_layer_set_background_color(s_time_layer, GColorClear); 112 + text_layer_set_text_color(s_time_layer, GColorBlack); 113 + // text_layer_set_text(s_time_layer, "00:00"); 114 + text_layer_set_font(s_time_layer, 115 + fonts_get_system_font(FONT_KEY_GOTHIC_18_BOLD)); 116 + text_layer_set_text_alignment(s_time_layer, GTextAlignmentCenter); 117 + 118 + // Add it as a child layer to the Window's root layer 119 + layer_add_child(window_layer, text_layer_get_layer(s_time_layer)); 120 + } 121 + 122 + static void main_window_unload(Window *window) { 123 + text_layer_destroy(s_time_layer); 124 + } 125 + 126 + static void update_time() { 127 + static char s_tid_buffer[14]; // Buffer for TID string (13 chars + null) 128 + now_c(s_tid_buffer, sizeof(s_tid_buffer)); // Generate TID 129 + 130 + // Display this time on the TextLayer 131 + text_layer_set_text(s_time_layer, s_tid_buffer); // Display TID 132 + } 133 + 134 + static void tick_handler(struct tm *tick_time, TimeUnits units_changed) { 135 + update_time(); 136 + } 137 + 138 + static void init() { 139 + // Create main Window element and assign to pointer 140 + s_main_window = window_create(); 141 + 142 + // Set handlers to manage the elements inside the Window 143 + window_set_window_handlers( 144 + s_main_window, 145 + (WindowHandlers){.load = main_window_load, .unload = main_window_unload}); 146 + 147 + // Show the Window on the watch, with animated=true 148 + window_stack_push(s_main_window, true); 149 + 150 + // Update the time immediately 151 + update_time(); 152 + 153 + // Register with TickTimerService 154 + tick_timer_service_subscribe(SECOND_UNIT, tick_handler); 155 + } 156 + 157 + static void deinit() { window_destroy(s_main_window); } 158 + 159 + int main(void) { 160 + init(); 161 + app_event_loop(); 162 + deinit(); 163 + }
+54
wscript
··· 1 + # 2 + # This file is the default set of rules to compile a Pebble application. 3 + # 4 + # Feel free to customize this to your needs. 5 + # 6 + import os.path 7 + 8 + top = '.' 9 + out = 'build' 10 + 11 + 12 + def options(ctx): 13 + ctx.load('pebble_sdk') 14 + 15 + 16 + def configure(ctx): 17 + """ 18 + This method is used to configure your build. ctx.load(`pebble_sdk`) automatically configures 19 + a build for each valid platform in `targetPlatforms`. Platform-specific configuration: add your 20 + change after calling ctx.load('pebble_sdk') and make sure to set the correct environment first. 21 + Universal configuration: add your change prior to calling ctx.load('pebble_sdk'). 22 + """ 23 + ctx.load('pebble_sdk') 24 + 25 + 26 + def build(ctx): 27 + ctx.load('pebble_sdk') 28 + 29 + build_worker = os.path.exists('worker_src') 30 + binaries = [] 31 + 32 + cached_env = ctx.env 33 + for platform in ctx.env.TARGET_PLATFORMS: 34 + ctx.env = ctx.all_envs[platform] 35 + ctx.set_group(ctx.env.PLATFORM_NAME) 36 + app_elf = '{}/pebble-app.elf'.format(ctx.env.BUILD_DIR) 37 + ctx.pbl_build(source=ctx.path.ant_glob('src/c/**/*.c'), target=app_elf, bin_type='app') 38 + 39 + if build_worker: 40 + worker_elf = '{}/pebble-worker.elf'.format(ctx.env.BUILD_DIR) 41 + binaries.append({'platform': platform, 'app_elf': app_elf, 'worker_elf': worker_elf}) 42 + ctx.pbl_build(source=ctx.path.ant_glob('worker_src/c/**/*.c'), 43 + target=worker_elf, 44 + bin_type='worker') 45 + else: 46 + binaries.append({'platform': platform, 'app_elf': app_elf}) 47 + ctx.env = cached_env 48 + 49 + ctx.set_group('bundle') 50 + ctx.pbl_bundle(binaries=binaries, 51 + js=ctx.path.ant_glob(['src/pkjs/**/*.js', 52 + 'src/pkjs/**/*.json', 53 + 'src/common/**/*.js']), 54 + js_entry_file='src/pkjs/index.js')