diff --git a/src/c/analog_wd.c b/src/c/analog_wd.c new file mode 100644 index 0000000..86e525c --- /dev/null +++ b/src/c/analog_wd.c @@ -0,0 +1,569 @@ +#include +#include "analog_wd.h" +#include "constants.h" +#include "options.h" +#include "weather.h" +#include "date.h" +#include "messaging.h" +#include "digital_time.h" +#include "battery.h" + +#define ANTIALIASING true + +#define HAND_MARGIN 18 +#define FINAL_RADIUS 80 + +#define REGULAR_HANDS_WIDTH 6 +#define THIN_HANDS_WIDTH 5 + +#define ANIMATION_DURATION 500 +#define ANIMATION_DELAY 600 + +#define HOUR_BAR_MARGIN 5 + +#define SCREEN_SHOT_HR 18 +#define SCREEN_SHOT_MIN 22 + +#define HAND_LENGTH_SEC 75 +#define SECONDS_HAND_DISPLAY_TIME_SECS 18 +int g_display_seconds_hand_count = 0; //stores brief counter to display seconds hand + +Options s_options; + +//stores weather retry counts (incremented in second tick handler). +//Stop retry count at DEFAULT_MAX_WEATHER_RETRY_COUNT +int g_weather_retry_count = 0; + +typedef struct { + int hours; + int minutes; + int seconds; +} Time; + +static GPoint s_center; +static Time s_last_time, s_anim_time; +static int s_radius = 0, s_color_channels[3]; +static bool s_animating = false; + +void set_text_layers_color(GColor textColor) { + text_layer_set_text_color(weather_layer1, textColor); + text_layer_set_text_color(weather_layer2, textColor); + text_layer_set_text_color(weather_layer_center, textColor); + text_layer_set_text_color(date_layer1, textColor); + text_layer_set_text_color(date_layer2, textColor); + text_layer_set_text_color(battery_layer, textColor); +} + +static void init_window_background_color(){ + + window_set_background_color(s_main_window, GColorBlack); + window_set_background_color(s_main_window, GColorFromHEX(s_options.background_color)); +} + +void init_static_row(TextLayer *label, GFont font) { + + text_layer_set_background_color(label, GColorClear); + text_layer_set_text_color(label, GColorWhite); + + text_layer_set_text_color(label, GColorFromHEX(s_options.text_color)); + + if (font) { + text_layer_set_font(label, font); + } +} + +/*************************** AnimationImplementation **************************/ + +static void animation_started(Animation *anim, void *context) { + s_animating = true; +} + +static void animation_stopped(Animation *anim, bool stopped, void *context) { + s_animating = false; +} + +static void animate(int duration, int delay, AnimationImplementation *implementation, bool handlers) { + Animation *anim = animation_create(); + animation_set_duration(anim, duration); + animation_set_delay(anim, delay); + animation_set_curve(anim, AnimationCurveEaseInOut); + animation_set_implementation(anim, implementation); + if(handlers) { + animation_set_handlers(anim, (AnimationHandlers) { + .started = animation_started, + .stopped = animation_stopped + }, NULL); + } + animation_schedule(anim); +} + +/************************************ UI **************************************/ + +static void bt_handler(bool isConnected) { + + int current_bluetooth_state = 0; //default bluetooth disconnected + if (isConnected) { + current_bluetooth_state = 1; //bluetooth connected + } + + //if bluetooth was previously connected and is now disconnected + if (s_options.bluetooth_state == 1 && + current_bluetooth_state == 0) { + + if (s_options.vibrate_bt_status) { + vibes_short_pulse(); //vibrate on bt disconnect, if option enabled + + if(s_canvas_layer) { + layer_mark_dirty(s_canvas_layer); + } + } + } + + //if bluetooth was previously disconnected and is now connected + if (s_options.bluetooth_state == 0 && + current_bluetooth_state == 1) { + + //clear weather conditions and reset weather retry count to force weather update + memset(s_options.conditions, 0,sizeof(s_options.conditions)); + s_options.condition_code = DEFAULT_CONDITION_CODE; + g_weather_retry_count = 0; + } + + //store bluetooth state + s_options.bluetooth_state = current_bluetooth_state; +} + +static void tap_handler(AccelAxisType axis, int32_t direction) { + + if (s_options.display_seconds_hand > 0) { + time_t t = time(NULL); + struct tm *time_now = localtime(&t); + + s_last_time.seconds = time_now->tm_sec; + + g_display_seconds_hand_count = SECONDS_HAND_DISPLAY_TIME_SECS; + } + + if (s_options.shake_for_lohi == 1) { + //Display Lo Hi temp info; + display_lohi_weather_info(); + } +} + +//every five seconds +static void handle_5second_tick(struct tm *tick_time, TimeUnits units_changed) { + + //if conditions blank (no current weather info) + if(strlen(s_options.conditions) == 0 && + g_weather_retry_count < DEFAULT_MAX_WEATHER_RETRY_COUNT) { + + //add one to weather retry count - stop trying this app session at DEFAULT_MAX_WEATHER_RETRY_COUNT + ++g_weather_retry_count; + + //reset time since last forecast timer + s_options.min_since_last_forecast = 0; + + //get updated weather + send(KEY_GET_WEATHER, 1, KEY_WEATHER_USE_GPS, s_options.weather_use_GPS, KEY_WEATHER_LOCATION, s_options.weather_location); + + //update weather layer + update_weather_layer(); + } + //APP_LOG(APP_LOG_LEVEL_DEBUG, "heap_bytes_free:heap_bytes_used %zu: %zu", heap_bytes_free(), heap_bytes_used()); +} + +//every second +static void handle_second_tick(struct tm *tick_time, TimeUnits units_changed) { + + if((s_options.display_seconds_hand == 1 && g_display_seconds_hand_count > 0) || + s_options.display_seconds_hand == 2) { + + s_last_time.seconds = tick_time->tm_sec; + + if(s_canvas_layer) { + layer_mark_dirty(s_canvas_layer); + } + } +} + +//every minute +static void handle_minute_tick(struct tm *tick_time, TimeUnits units_changed) { + + // Store time + s_last_time.hours = tick_time->tm_hour; + s_last_time.hours -= (s_last_time.hours > 12) ? 12 : 0; + s_last_time.minutes = tick_time->tm_min; + + for(int i = 0; i < 3; i++) { + s_color_channels[i] = 0; + } + + // Redraw + if(s_canvas_layer) { + layer_mark_dirty(s_canvas_layer); + } + + if (units_changed & HOUR_UNIT) { + //vibes_double_pulse(); //hourly vibration + } + + update_date_layer(); //check/update date layer + update_digital_time_layer(); //check/update digital_time_layer + update_battery_layer(); //check/update update_battery_layer + + //get minutes since last weather update + time_t t = time(NULL); + int min_since_last_update = (difftime(t, s_options.last_update) / 60) + 1; + + APP_LOG(APP_LOG_LEVEL_DEBUG, " (Last update %s) min_since_last_update:weather_frequency - %d:%d", s_options.last_weather_update24hr, min_since_last_update, s_options.weather_frequency); + //APP_LOG(APP_LOG_LEVEL_DEBUG, "handle_minute_tick strlen(s_options.conditions): %zu", strlen(s_options.conditions)); + //if min_since_last_forecast greater than or equal to weatherUpdateFrequency + if(min_since_last_update >= s_options.weather_frequency || + strlen(s_options.conditions) == 0) { + + s_options.min_since_last_forecast = 0; + + //get updated weather + send(KEY_GET_WEATHER, 1, KEY_WEATHER_USE_GPS, s_options.weather_use_GPS, KEY_WEATHER_LOCATION, s_options.weather_location); + + //update weather layer + update_weather_layer(); + } +} + +void handle_tick(struct tm *tick_time, TimeUnits units_changed) { + + if (units_changed & SECOND_UNIT) { + handle_second_tick(tick_time, units_changed); + + if (tick_time->tm_sec % 5 == 0) { + handle_5second_tick(tick_time, units_changed); + } + } + if (units_changed & MINUTE_UNIT) { + handle_minute_tick(tick_time, units_changed); + } +} + +static int hours_to_minutes(int hours_out_of_12) { + return (int)(float)(((float)hours_out_of_12 / 12.0F) * 60.0F); +} + +static void update_proc(Layer *layer, GContext *ctx) { + + GRect layer_frame = layer_get_frame(window_get_root_layer(s_main_window)); + const int16_t width = layer_frame.size.w; + const int16_t height = layer_frame.size.h; + + graphics_context_set_stroke_color(ctx, GColorWhite); + graphics_context_set_antialiased(ctx, ANTIALIASING); + + /************************************ Minute lines **************************************/ + + for (int i = 0; i < 60; i++) { + // hour bar + if (i % 1 == 0 && i / 1 != -1) { + GPoint minute_line = (GPoint) { + .x = (int16_t)(sin_lookup(TRIG_MAX_ANGLE * i / 60) * (int32_t)(s_radius - HOUR_BAR_MARGIN) / TRIG_MAX_RATIO) + s_center.x, + .y = (int16_t)(-cos_lookup(TRIG_MAX_ANGLE * i / 60) * (int32_t)(s_radius - HOUR_BAR_MARGIN) / TRIG_MAX_RATIO) + s_center.y, + }; + + GPoint line_start = minute_line; + + time_t t = time(NULL); + struct tm *time_now = localtime(&t); + #if DEBUG + time_now->tm_hour = SCREEN_SHOT_HR; //for screen shots + time_now->tm_min = SCREEN_SHOT_MIN; + #endif + + //emphasize/display hour indicators + if (i % 5 == 0) { + if (!s_options.display_hour_digits) { + // emphasis + graphics_context_set_stroke_color(ctx, GColorFromHEX(s_options.hour_markers_color)); + + line_start.x += (s_center.x - minute_line.x) * 0.12; + line_start.y += (s_center.y - minute_line.y) * 0.12; + + graphics_context_set_stroke_width(ctx, 2); + graphics_draw_line(ctx, line_start, minute_line); + } + else { + + graphics_context_set_stroke_color(ctx, GColorFromHEX(s_options.hour_markers_color)); + + line_start.x += (s_center.x - minute_line.x) * 0.02; + line_start.y += (s_center.y - minute_line.y) * 0.02; + + graphics_context_set_stroke_width(ctx, 2); + graphics_draw_line(ctx, line_start, minute_line); + + // show hour digits + line_start.x += (s_center.x - line_start.x) * 0.11; + line_start.y += (s_center.y - line_start.y) * 0.11; + line_start.x -= 14; + line_start.y -= 12; + GSize sz = (GSize) { + .w = 30, + .h = 20, + }; + GRect rect = (GRect) { + .origin = line_start, + .size = sz, + }; + + char str[3]; + snprintf(str, 3, "%d", i / 5 == 0 ? 12 : i / 5); + if (clock_is_24h_style() && time_now->tm_hour > 12) { + snprintf(str, 3, "%d", i / 5 == 0 ? 24 : i / 5 + 12); + } + graphics_context_set_text_color(ctx, GColorFromHEX(s_options.hour_markers_color)); + graphics_draw_text(ctx, str, fonts_get_system_font(FONT_KEY_GOTHIC_18_BOLD), rect, GTextOverflowModeWordWrap, GTextAlignmentCenter, NULL); + } + } + else { + + if (!s_options.display_hour_digits) { + graphics_context_set_stroke_color(ctx, GColorFromHEX(s_options.minor_markers_color)); + + line_start.x += (s_center.x - minute_line.x) * 0.07; + line_start.y += (s_center.y - minute_line.y) * 0.07; + + graphics_context_set_stroke_width(ctx, 1); + graphics_draw_line(ctx, line_start, minute_line); + } + else { + graphics_context_set_stroke_color(ctx, GColorFromHEX(s_options.minor_markers_color)); + graphics_context_set_fill_color(ctx, GColorFromHEX(s_options.minor_markers_color)); + graphics_fill_circle(ctx, minute_line, 1); + } + } + } + } + + /************************************ Watch hand width **************************************/ + + //set watch hand width + if (s_options.use_thin_hands) { + graphics_context_set_stroke_width(ctx, THIN_HANDS_WIDTH); + } + else { + graphics_context_set_stroke_width(ctx, REGULAR_HANDS_WIDTH); + } + + /************************************ Twelve o'clock dot **************************************/ + + //if background color the same color as the hour marker color, dispaly a dot at twelve o'clock position + int chalk_offset = 10; + if (s_options.background_color == s_options.hour_markers_color) { + graphics_context_set_stroke_color(ctx, GColorFromHEX(s_options.hour_hand_color)); + graphics_draw_circle(ctx, GPoint(width / 2, chalk_offset), 1); //twelve + } + + /************************************ Hour and minute hands **************************************/ + + // Don't use current time while animating + Time mode_time = (s_animating) ? s_anim_time : s_last_time; + + // Adjust for minutes through the hour + float minute_angle = TRIG_MAX_ANGLE * mode_time.minutes / 60; + float hour_angle; + if(s_animating) { + // Hours out of 60 for smoothness + hour_angle = TRIG_MAX_ANGLE * mode_time.hours / 60; + } else { + hour_angle = TRIG_MAX_ANGLE * mode_time.hours / 12; + } + hour_angle += (minute_angle / TRIG_MAX_ANGLE) * (TRIG_MAX_ANGLE / 12); + + // Plot hands + GPoint minute_hand = (GPoint) { + .x = (int16_t)(sin_lookup(TRIG_MAX_ANGLE * mode_time.minutes / 60) * (int32_t)(s_radius - HAND_MARGIN) / TRIG_MAX_RATIO) + s_center.x, + .y = (int16_t)(-cos_lookup(TRIG_MAX_ANGLE * mode_time.minutes / 60) * (int32_t)(s_radius - HAND_MARGIN) / TRIG_MAX_RATIO) + s_center.y, + }; + GPoint hour_hand = (GPoint) { + .x = (int16_t)(sin_lookup(hour_angle) * (int32_t)(s_radius - (1.75 * HAND_MARGIN)) / TRIG_MAX_RATIO) + s_center.x, + .y = (int16_t)(-cos_lookup(hour_angle) * (int32_t)(s_radius - (1.75 * HAND_MARGIN)) / TRIG_MAX_RATIO) + s_center.y, + }; + + // Draw hands with positive length only + + if(s_radius > HAND_MARGIN) { + graphics_context_set_stroke_color(ctx, GColorFromHEX(s_options.minute_hand_color)); + graphics_draw_line(ctx, s_center, minute_hand); + } + if(s_radius > 2 * HAND_MARGIN) { + graphics_context_set_stroke_color(ctx, GColorFromHEX(s_options.hour_hand_color)); + if (s_options.vibrate_bt_status) { + if (s_options.bluetooth_state == 0) { + graphics_context_set_stroke_color(ctx, GColorBlue); + } + } + graphics_draw_line(ctx, s_center, hour_hand); + + //center circle + graphics_draw_circle(ctx, GPoint(width / 2, height / 2), 1); + } + + /************************************ Seconds hand line **************************************/ + + // Draw seconds hand + --g_display_seconds_hand_count; + if (g_display_seconds_hand_count < 0) + g_display_seconds_hand_count = 0; + + if((s_options.display_seconds_hand == 1 && g_display_seconds_hand_count > 0) || + (s_options.display_seconds_hand == 2)) { + // Plot seconds hand ends + GPoint second_hand_long = (GPoint) { + .x = (int16_t)(sin_lookup(TRIG_MAX_ANGLE * s_last_time.seconds / 60) * (int32_t)HAND_LENGTH_SEC / TRIG_MAX_RATIO) + s_center.x, + .y = (int16_t)(-cos_lookup(TRIG_MAX_ANGLE * s_last_time.seconds / 60) * (int32_t)HAND_LENGTH_SEC / TRIG_MAX_RATIO) + s_center.y, + }; + + graphics_context_set_stroke_width(ctx, 2); + graphics_context_set_stroke_color(ctx, GColorFromHEX(s_options.seconds_hand_color)); + graphics_draw_line(ctx, GPoint(s_center.x, s_center.y), GPoint(second_hand_long.x, second_hand_long.y)); + } +} + +static void window_load(Window *window) { + Layer *window_layer = window_get_root_layer(window); + GRect window_bounds = layer_get_bounds(window_layer); + s_center = grect_center_point(&window_bounds); + s_canvas_layer = layer_create(window_bounds); + layer_set_update_proc(s_canvas_layer, update_proc); + layer_add_child(window_layer, s_canvas_layer); +} + +static void window_unload(Window *window) { + layer_destroy(s_canvas_layer); +} + +/*********************************** App **************************************/ + +static int anim_percentage(AnimationProgress dist_normalized, int max) { + return (int)(float)(((float)dist_normalized / (float)ANIMATION_NORMALIZED_MAX) * (float)max); +} + +static void radius_update(Animation *anim, AnimationProgress dist_normalized) { + int chalkRadiusAdjustment = 0; + #if defined(PBL_ROUND) + chalkRadiusAdjustment = 12; + #endif + s_radius = anim_percentage(dist_normalized, FINAL_RADIUS + chalkRadiusAdjustment); + + layer_mark_dirty(s_canvas_layer); +} + +static void hands_update(Animation *anim, AnimationProgress dist_normalized) { + s_anim_time.hours = anim_percentage(dist_normalized, hours_to_minutes(s_last_time.hours)); + s_anim_time.minutes = anim_percentage(dist_normalized, s_last_time.minutes); + + layer_mark_dirty(s_canvas_layer); +} + +static void handle_deinit() { + //save watchface options + persist_write_data(KEY_OPTIONS, &s_options, sizeof(s_options)); + + text_layer_destroy(weather_layer1); + text_layer_destroy(weather_layer_center); + text_layer_destroy(weather_layer2); + text_layer_destroy(digital_time_layer); + text_layer_destroy(battery_layer); + text_layer_destroy(date_layer1); + text_layer_destroy(date_layer2); + + connection_service_unsubscribe(); + + accel_tap_service_unsubscribe(); + tick_timer_service_unsubscribe(); + + window_destroy(s_main_window); +} + +static void handle_init() { + //light_enable(true); //background light for screen shots + srand(time(NULL)); + + s_main_window = window_create(); + window_set_window_handlers(s_main_window, (WindowHandlers) { + .load = window_load, + .unload = window_unload, + }); + + + //set-retrieve watchface options + init_options(); + + init_window_background_color(); + + // Prepare animations + AnimationImplementation radius_impl = { + .update = radius_update + }; + animate(ANIMATION_DURATION, ANIMATION_DELAY, &radius_impl, false); + + AnimationImplementation hands_impl = { + .update = hands_update + }; + animate(2 * ANIMATION_DURATION, ANIMATION_DELAY, &hands_impl, true); + + //add weather and date layers + GRect layer_frame = layer_get_frame(window_get_root_layer(s_main_window)); + const int16_t width = layer_frame.size.w; + const int16_t height = layer_frame.size.h; + + //add_weatherdate_layers(window_get_root_layer(s_main_window), width, height); + add_date_layers(window_get_root_layer(s_main_window), width, height); + add_weather_layers(window_get_root_layer(s_main_window), width, height); + add_digital_time_layer(window_get_root_layer(s_main_window), width, height); + add_battery_layer(window_get_root_layer(s_main_window), width, height); + + app_message_register_inbox_received(inbox_received_callback); + app_message_register_inbox_dropped(message_dropped); + app_message_register_outbox_sent(message_out_success); + app_message_register_outbox_failed(message_out_failed); + + app_message_open(app_message_inbox_size_maximum(), app_message_outbox_size_maximum()); + + update_date_layer(); //update date_layer + update_digital_time_layer(); //update digital_time_layer + update_battery_layer(); //update update_battery_layer + update_weather_layer(); //update weather layer + + tick_timer_service_subscribe(MINUTE_UNIT | SECOND_UNIT, handle_tick); + accel_tap_service_subscribe(tap_handler); + + time_t t = time(NULL); + struct tm *time_now = localtime(&t); + #if DEBUG + time_now->tm_hour = SCREEN_SHOT_HR; //for screen shots + time_now->tm_min = SCREEN_SHOT_MIN; + #endif + if (s_options.display_seconds_hand > 0) + s_last_time.seconds = time_now->tm_sec; + handle_tick(time_now, MINUTE_UNIT); + + //get minutes since last weather update + //int min_since_last_update = difftime(t, s_options.last_update) / 60; + //APP_LOG(APP_LOG_LEVEL_DEBUG, "******************* minutes since last weather update %d: weather_frequency %d", min_since_last_update, s_options.weather_frequency); + + // Subscribe to Bluetooth updates + connection_service_subscribe((ConnectionHandlers) { + .pebble_app_connection_handler = bt_handler + }); + + // Check current bluetooth connection state + bt_handler(connection_service_peek_pebble_app_connection()); + + const bool animated = true; + window_stack_push(s_main_window, animated); +} + +int main() { + handle_init(); + app_event_loop(); + handle_deinit(); +} \ No newline at end of file diff --git a/src/c/analog_wd.h b/src/c/analog_wd.h new file mode 100644 index 0000000..d118b4f --- /dev/null +++ b/src/c/analog_wd.h @@ -0,0 +1,51 @@ +#include + +TextLayer *weather_layer1, *weather_layer2, *weather_layer_center; +TextLayer *date_layer1, *date_layer2; +TextLayer *digital_time_layer; +TextLayer *battery_layer; +AppTimer *lohi_display_timer; + +void init_static_row(TextLayer *label, GFont font); //creates/configures static (weather/date) display lines +void set_text_layers_color(GColor textColor); //sets color for text (weather, date, digital time) elements + +typedef struct { + int shake_for_lohi; + int tempF; + int tempFLo; + int tempFHi; + int tempC; + int tempCLo; + int tempCHi; + int display_weather; + int weather_use_GPS; + char weather_location[64]; + int use_celsius; + int weather_frequency; + int min_since_last_forecast; + int background_color; + int text_color; + int hour_hand_color; + int minute_hand_color; + int seconds_hand_color; + int use_thin_hands; + int hour_markers_color; + int minor_markers_color; + int readability; + int condition_code; + int display_digital_time; + int display_date; + int vibrate_bt_status; + int display_battery; + int display_hour_digits; + int display_seconds_hand; + int pebble_js_ready; + bool bluetooth_state; + time_t last_update; + char conditions[32]; + char last_weather_update12hr[16]; + char last_weather_update24hr[16]; +} Options; + +Window *s_main_window; +Layer *s_canvas_layer; \ No newline at end of file diff --git a/src/c/battery.c b/src/c/battery.c new file mode 100644 index 0000000..3fcfed0 --- /dev/null +++ b/src/c/battery.c @@ -0,0 +1,57 @@ +#include +#include "battery.h" +#include "constants.h" +#include "analog_wd.h" + +extern Options s_options; + +//adds/configures display battery line +void add_battery_layer(Layer *window_layer, int16_t width, int16_t height) { + + GFont battery_font; + int battery_Y_readability_offset = 0; + int battery_X_hour_digits_offset = 0; + + if (s_options.readability) { + battery_Y_readability_offset = DEFAULT_BATTERY_OFFSET_READABILITY; + battery_font = fonts_get_system_font(FONT_KEY_GOTHIC_24); + } + else { + battery_font = fonts_get_system_font(FONT_KEY_GOTHIC_18); + } + + if (s_options.display_hour_digits) { + battery_X_hour_digits_offset = DEFAULT_BATTERY_OFFSET_HOUR_DIGITS; + } + + battery_layer = text_layer_create(GRect(17 + battery_X_hour_digits_offset, (height / 2) - 12 - battery_Y_readability_offset, width, 28)); + text_layer_set_text_alignment(battery_layer, GTextAlignmentLeft); + init_static_row(battery_layer, battery_font); + layer_add_child(window_layer, text_layer_get_layer(battery_layer)); +} + +//checks/updates date display line +void update_battery_layer() { + static char battery_buffer[16]; + const char *current_battery_layer; + + //if displaying battery + if (s_options.display_battery) { + + //get current date_layer text + current_battery_layer = text_layer_get_text(battery_layer); + + //get battery percent + snprintf(battery_buffer, sizeof("100%"), "%d%%", battery_state_service_peek().charge_percent); + + if (current_battery_layer != battery_buffer) { + text_layer_set_text(battery_layer, battery_buffer); + } + } + else { + text_layer_set_text(battery_layer, ""); + } + #if DEBUG + APP_LOG(APP_LOG_LEVEL_DEBUG, "update_battery_layer: text_layer_set_text battery_layer: %s", battery_buffer); + #endif +} \ No newline at end of file diff --git a/src/c/battery.h b/src/c/battery.h new file mode 100644 index 0000000..052fd0d --- /dev/null +++ b/src/c/battery.h @@ -0,0 +1,4 @@ +#pragma once + + void update_battery_layer(); + void add_battery_layer(Layer *window_layer, int16_t width, int16_t height); \ No newline at end of file diff --git a/src/c/constants.c b/src/c/constants.c new file mode 100644 index 0000000..4bd2775 --- /dev/null +++ b/src/c/constants.c @@ -0,0 +1,54 @@ +#include +#include "constants.h" + +const int DEFAULT_SHAKE_FOR_LOHI = 1; //True - shake to show Lo Hi Temps +const int DEFAULT_DISPLAY_LOHI_TIMER = 5000; //length time (milliseconds) to display Lo Hi Temps +const int DEFAULT_MIN_SINCE_WEATHER_UPDATE = 0; //weather just updated +const char DEFAULT_LAST_WEATHER_UPDATE[16] = "--:--"; //default last update "time" display +const char DEFAULT_ERROR_WEATHER_UPDATE[16] = "---"; //default text display upon weather update error +const int DEFAULT_CONDITION_CODE = -99; //Invalid condition code to force weather update +const int DEFAULT_DISPLAY_WEATHER = 1; //true +const int DEFAULT_WEATHER_FREQUENCY = 30; //minutes +const int DEFAULT_WEATHER_USE_GPS = 1; //true +const int DEFAULT_USE_CELSIUS = 0; //false +const int DEFAULT_BACKGROUND_COLOR = 0x000000; //black +const int DEFAULT_TEXT_COLOR = 0xFFFFFF; //white +const int DEFAULT_HOUR_HAND_COLOR = 0xFF0000; //red +const int DEFAULT_MINUTE_HAND_COLOR = 0xFFFFFF; //white +const int DEFAULT_SECONDS_HAND_COLOR = 0xFFFFFF; //white +const int DEFAULT_HOUR_MARKERS_COLOR = 0xFF0000; //red +const int DEFAULT_MINOR_MARKERS_COLOR = 0xFFFFFF; //white +const int DEFAULT_READABILITY = 0; //false - use original size +const int DEFAULT_DISPLAY_DIGITAL_TIME = 0; //false +const int DEFAULT_DISPLAY_DATE = 1; //true +const int DEFAULT_VIBRATE_BT_STATUS = 0; //false +const int DEFAULT_DISPLAY_BATTERY = 0; //false +const int DEFAULT_USE_THIN_HANDS = 0; //false +const int DEFAULT_DISPLAY_HOUR_DIGITS = 0; //false +const int DEFAULT_DISPLAY_SECONDS_HAND = 0; //false + +const int DEFAULT_MAX_WEATHER_RETRY_COUNT = 5; //max (seconds) weather retry counts +const uint MAX_CHALK_SINGLE_LINE_CONDITIONS_LEN = 4; //max length for weather conditions to display on single line. longer split to two lines + +const int DEFAULT_CHALK_TIME_X_OFFSET = 20; //X-axis adjustment for time display on Chalk (Pebble Time Round) +const int DEFAULT_CHALK_TIME_Y_OFFSET = 10; //Y-axis adjustment for time display on Chalk (Pebble Time Round) +const int DEFAULT_MARKERS_X_OFFSET = 7; //X-axix adjustment for when displaying hour/minute markers + +const int DEFAULT_CHALK_WEATHER_CENTER_Y_OFFSET = 10; //Y-axis adjustment for weather display on Chalk (Pebble Time Round) +const int DEFAULT_CHALK_WEATHER1_Y_OFFSET = 10; //Y-axis adjustment for weather display on Chalk (Pebble Time Round) +const int DEFAULT_CHALK_WEATHER2_Y_OFFSET = 28; //Y-axis adjustment for weather display on Chalk (Pebble Time Round) +const int DEFAULT_WEATHER_Y_OFFSET_READABILITY = 4; //Y-axis adjustment for increased readability font options +const int DEFAULT_WEATHER_Y_OFFSET_HOUR_DIGITS = 4; //Y-axis adjustment for hour digits options + +const int DEFAULT_DATE_Y_OFFSET_READABILITY = 4; //Y-axis adjustment for increased readability font options +const int DEFAULT_DATE_X_OFFSET_READABILITY = 4; //X-axis adjustment for increased readability font options +const int DEFAULT_DATE_X_OFFSET_HOUR_DIGITS = 4; //X-axis adjustment for hour digits display option + +const int DEFAULT_MARKERS_Y_OFFSET = 12; //Y-axix adjustment for when displaying hour/minute markers +const int DEFAULT_CHALK_DIGITAL_TIME_Y_OFFSET = 12; //Y-axis adjustment for digital time display on Chalk (Pebble Time Round) +const int DEFAULT_DIGITAL_TIME_Y_OFFSET_READABILITY = 5; //Y-axis adjustment for increased readability font options +const int DEFAULT_DIGITAL_TIME_Y_OFFSET_HOUR_DIGITS = 5; //Y-axis adjustment for digital time display on Chalk (Pebble Time Round) + +const int DEFAULT_CHALK_BATTERY_X_OFFSET = 5; //X-axis adjustment for battery display on Chalk (Pebble Time Round) +const int DEFAULT_BATTERY_OFFSET_READABILITY = 5; //Y-axis adjustment for increased readability font options +const int DEFAULT_BATTERY_OFFSET_HOUR_DIGITS = 5; //X-axis adjustment for hour digits options