Upload files to "src/c"

This commit is contained in:
2024-10-06 21:23:54 +00:00
parent 3d47e0895a
commit 0c51b688eb
5 changed files with 563 additions and 0 deletions

42
src/c/constants.c Normal file
View File

@@ -0,0 +1,42 @@
#include <pebble.h>
#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_DISPLAY_O_PREFIX = 0; //false
const int DEFAULT_WEATHERDATE_ALIGNMENT = 1; //center
const int DEFAULT_HOURMINUTES_ALIGNMENT = 0; //left
const int DEFAULT_CHALK_ALIGNMENT = 1; //center
const int DEFAULT_TIME_COLOR = 0xFFFFFF; //white
const int DEFAULT_HR_COLOR = 0xFFFFFF; //white
const int DEFAULT_MIN_COLOR = 0xFFFFFF; //white
const int DEFAULT_BACKGROUND_COLOR = 0x000000; //black
const int DEFAULT_WEATHERDATE_READABILITY = 0; //use original size
const int DEFAULT_MINUTES_READABILITY = 0; //use default size
const int DEFAULT_WEATHER_Y_OFFSET_READABILITY = 4; //Y-axis adjustment for increased readability font options
const int DEFAULT_DATE_Y_OFFSET_READABILITY = 5; //Y-axis adjustment for increased readability font options
const int DEFAULT_VIBRATE_BT_STATUS = 0; //false
const int DEFAULT_WD_COLOR = 0xFFFFFF; //white
const int DEFAULT_DISPLAY_DATE = 1; //true
const int DEFAULT_MAX_WEATHER_RETRY_COUNT = 5; //max (seconds) weather retry counts
const uint MAX_CHALK_SINGLE_LINE_CONDITIONS_LEN = 6; //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_WEATHER1_Y_OFFSET = 0; //Y-axis adjustment for weather display on Chalk (Pebble Time Round)
const int DEFAULT_CHALK_WEATHER2_Y_OFFSET = 15; //Y-axis adjustment for weather display on Chalk (Pebble Time Round)
const int DEFAULT_CHALK_WEATHER_CENTER_Y_OFFSET = 8; //Y-axis adjustment for weather 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_CHALK_DATE_Y_OFFSET = 5; //Y-axis adjustment for date display on Chalk (Pebble Time Round)
//watchface time display lines
const int HOUR_ROW = 0;
const int MINUTE_ROW1 = 1;
const int MINUTE_ROW2 = 2;

73
src/c/constants.h Normal file
View File

@@ -0,0 +1,73 @@
#pragma once
#define DEBUG 0
#define KEY_TEMPERATURE_IN_C 1
#define KEY_CONDITIONS 2
#define KEY_BACKGROUND_COLOR 3
#define KEY_TIME_COLOR 4
#define KEY_WEATHER_FREQUENCY 5
#define KEY_USE_CELSIUS 6
#define KEY_DISPLAY_O_PREFIX 7
#define KEY_DISPLAY_WEATHER 8
#define KEY_MIN_SINCE_WEATHER_UPDATE 9
#define KEY_WEATHERDATE_ALIGNMENT 10
#define KEY_HOURMINUTES_ALIGNMENT 11
#define KEY_GET_WEATHER 12
#define KEY_TEMPERATURE 13
#define KEY_WEATHERDATE_READABILITY 14
#define KEY_MINUTES_READABILITY 15
#define KEY_TEMPERATURE_LO 16
#define KEY_TEMPERATURE_HI 17
#define KEY_TEMPERATURE_IN_C_LO 18
#define KEY_TEMPERATURE_IN_C_HI 19
#define KEY_CONDITION_CODE 20
#define KEY_SHAKE_FOR_LOHI 21
#define KEY_VIBBRATE_BT_STATUS 22
#define KEY_WEATHER_USE_GPS 23
#define KEY_WEATHER_LOCATION 24
#define KEY_JS_READY 25
#define KEY_WD_COLOR 26
#define KEY_DISPLAY_DATE 27
#define KEY_HR_COLOR 28
#define KEY_MIN_COLOR 29
#define KEY_OPTIONS 99
extern const int DEFAULT_SHAKE_FOR_LOHI;
extern const int DEFAULT_DISPLAY_LOHI_TIMER;
extern const int DEFAULT_MIN_SINCE_WEATHER_UPDATE;
extern const char DEFAULT_LAST_WEATHER_UPDATE[16];
extern const char DEFAULT_ERROR_WEATHER_UPDATE[16];
extern const int DEFAULT_CONDITION_CODE;
extern const int DEFAULT_DISPLAY_WEATHER;
extern const int DEFAULT_WEATHER_FREQUENCY;
extern const int DEFAULT_WEATHER_USE_GPS;
extern const int DEFAULT_USE_CELSIUS;
extern const int DEFAULT_DISPLAY_O_PREFIX;
extern const int DEFAULT_WEATHERDATE_ALIGNMENT;
extern const int DEFAULT_HOURMINUTES_ALIGNMENT;
extern const int DEFAULT_CHALK_ALIGNMENT;
extern const int DEFAULT_TIME_COLOR;
extern const int DEFAULT_HR_COLOR;
extern const int DEFAULT_MIN_COLOR;
extern const int DEFAULT_BACKGROUND_COLOR;
extern const int DEFAULT_WEATHERDATE_READABILITY;
extern const int DEFAULT_MINUTES_READABILITY;
extern const int DEFAULT_WEATHER_Y_OFFSET_READABILITY;
extern const int DEFAULT_DATE_Y_OFFSET_READABILITY;
extern const int DEFAULT_VIBRATE_BT_STATUS;
extern const int DEFAULT_WD_COLOR;
extern const int DEFAULT_DISPLAY_DATE;
extern const int DEFAULT_MAX_WEATHER_RETRY_COUNT;
extern const uint MAX_CHALK_SINGLE_LINE_CONDITIONS_LEN;
extern const int DEFAULT_CHALK_TIME_X_OFFSET;
extern const int DEFAULT_CHALK_WEATHER1_Y_OFFSET;
extern const int DEFAULT_CHALK_WEATHER2_Y_OFFSET;
extern const int DEFAULT_CHALK_WEATHER_CENTER_Y_OFFSET;
extern const int DEFAULT_CHALK_TIME_Y_OFFSET;
extern const int DEFAULT_CHALK_DATE_Y_OFFSET;
extern const int HOUR_ROW;
extern const int MINUTE_ROW1;
extern const int MINUTE_ROW2;

224
src/c/messaging.c Normal file
View File

@@ -0,0 +1,224 @@
#include <pebble.h>
#include "messaging.h"
#include "constants.h"
#include "weather_date.h"
#include "sliding_time_wd.h"
extern Options s_options;
extern SlidingTextData *s_data;
void send(int key, int value, int key2, int value2, int key3, char value3[64]){
#if DEBUG
APP_LOG(APP_LOG_LEVEL_DEBUG, "send: s_options.pebble_js_ready: %d", s_options.pebble_js_ready);
#endif
if (s_options.pebble_js_ready) {
DictionaryIterator *iterator;
app_message_outbox_begin(&iterator);
dict_write_int(iterator, key, &value, sizeof(int), true);
dict_write_int(iterator, key2, &value2, sizeof(int), true);
dict_write_cstring(iterator, key3, value3);
app_message_outbox_send();
}
}
void inbox_received_callback(DictionaryIterator *iterator, void *context) {
SlidingTextData *data = s_data;
SlidingRow *row;
// Read first item
Tuple *t = dict_read_first(iterator);
#if DEBUG
int dic_size = (int)dict_size(iterator);
APP_LOG(APP_LOG_LEVEL_DEBUG, "***************************** inbox_received_callback dict_size: %d", dic_size);
#endif
// For all items
while(t != NULL) {
// Which key was received?
switch(t->key) {
case KEY_TEMPERATURE:
s_options.tempF = (int)t->value->int32;
break;
case KEY_TEMPERATURE_LO:
s_options.tempFLo = (int)t->value->int32;
break;
case KEY_TEMPERATURE_HI:
s_options.tempFHi = (int)t->value->int32;
break;
case KEY_TEMPERATURE_IN_C:
s_options.tempC = (int)t->value->int32;
break;
case KEY_TEMPERATURE_IN_C_LO:
s_options.tempCLo = (int)t->value->int32;
break;
case KEY_TEMPERATURE_IN_C_HI:
s_options.tempCHi = (int)t->value->int32;
break;
case KEY_CONDITIONS:
snprintf(s_options.conditions, sizeof(s_options.conditions), "%s", t->value->cstring);
//check if successful weather retrieval
if (strlen(s_options.conditions) > 0) {
// Get a tm structure
time_t temp = time(NULL);
struct tm *tick_time = localtime(&temp);
//strftime(s_options.last_weather_update, sizeof("00:00"), "%H:%M", tick_time);
strftime(s_options.last_weather_update24hr, sizeof("00:00"), "%H:%M", tick_time);
strftime(s_options.last_weather_update12hr, sizeof("00:00 pm"), "%l:%M %P", tick_time);
s_options.last_update = temp;
}
break;
case KEY_CONDITION_CODE:
s_options.condition_code = (int)t->value->int32;
break;
case KEY_DISPLAY_O_PREFIX:
s_options.display_prefix = (int)t->value->int32;
break;
case KEY_DISPLAY_DATE:
s_options.display_date = (int)t->value->int32;
break;
case KEY_SHAKE_FOR_LOHI:
s_options.shake_for_lohi = (int)t->value->int32;
break;
case KEY_USE_CELSIUS:
s_options.use_celsius = (int)t->value->int32;
break;
case KEY_WEATHER_USE_GPS:
//force weather update after each config page Save
memset(s_options.conditions, 0,sizeof(s_options.conditions));
s_options.condition_code = DEFAULT_CONDITION_CODE;
s_options.weather_use_GPS = (int)t->value->int32;
break;
case KEY_WEATHER_LOCATION:
snprintf(s_options.weather_location, sizeof(s_options.weather_location), "%s", t->value->cstring);
break;
case KEY_WEATHER_FREQUENCY:
s_options.weather_frequency = (int)t->value->int32;
break;
case KEY_BACKGROUND_COLOR:
s_options.background_color = (int)t->value->int32;
window_set_background_color(data->window, GColorFromHEX(s_options.background_color));
break;
case KEY_TIME_COLOR:
s_options.time_color = (int)t->value->int32;
set_time_layers_color(GColorFromHEX(s_options.time_color));
break;
case KEY_HR_COLOR:
s_options.hr_color = (int)t->value->int32;
set_hr_layer_color(GColorFromHEX(s_options.hr_color));
break;
case KEY_MIN_COLOR:
s_options.min_color = (int)t->value->int32;
set_min_layers_color(GColorFromHEX(s_options.min_color));
break;
case KEY_WD_COLOR:
s_options.wd_color = (int)t->value->int32;
set_wd_layers_color(GColorFromHEX(s_options.wd_color));
break;
case KEY_WEATHERDATE_ALIGNMENT:
s_options.weatherdate_alignment = (int)t->value->int32;
#if defined(PBL_RECT)
text_layer_set_text_alignment(weather_layer1, row_alignment(s_options.weatherdate_alignment));
text_layer_set_text_alignment(date_layer, row_alignment(s_options.weatherdate_alignment));
#elif defined(PBL_ROUND)
text_layer_set_text_alignment(weather_layer1, row_alignment(DEFAULT_CHALK_ALIGNMENT));
text_layer_set_text_alignment(weather_layer2, row_alignment(DEFAULT_CHALK_ALIGNMENT));
text_layer_set_text_alignment(weather_layer_center, row_alignment(DEFAULT_CHALK_ALIGNMENT));
text_layer_set_text_alignment(date_layer, row_alignment(DEFAULT_CHALK_ALIGNMENT));
#endif
break;
case KEY_HOURMINUTES_ALIGNMENT:
row = &data->rows[HOUR_ROW];
s_options.hourminute_alignment = (int)t->value->int32;
text_layer_set_text_alignment(row->label, row_alignment(s_options.hourminute_alignment));
row = &data->rows[MINUTE_ROW1];
text_layer_set_text_alignment(row->label, row_alignment(s_options.hourminute_alignment));
row = &data->rows[MINUTE_ROW2];
text_layer_set_text_alignment(row->label, row_alignment(s_options.hourminute_alignment));
break;
case KEY_WEATHERDATE_READABILITY:
s_options.weatherdate_readability = (int)t->value->int32;
break;
case KEY_MINUTES_READABILITY:
s_options.minutes_readability = (int)t->value->int32;
break;
case KEY_VIBBRATE_BT_STATUS:
s_options.vibrate_bt_status = (int)t->value->int32;
break;
case KEY_JS_READY:
s_options.pebble_js_ready = (int)t->value->int32;
#if DEBUG
APP_LOG(APP_LOG_LEVEL_DEBUG, "inbox_received_callback: s_options.pebble_js_ready: %d", s_options.pebble_js_ready);
#endif
break;
}
// Look for next item
t = dict_read_next(iterator);
}
//check update weather & date layers
update_date_layer();
update_weather_layer();
}
char *translate_error(AppMessageResult result) {
switch (result) {
case APP_MSG_OK: return "APP_MSG_OK";
case APP_MSG_SEND_TIMEOUT: return "APP_MSG_SEND_TIMEOUT";
case APP_MSG_SEND_REJECTED: return "APP_MSG_SEND_REJECTED";
case APP_MSG_NOT_CONNECTED: return "APP_MSG_NOT_CONNECTED";
case APP_MSG_APP_NOT_RUNNING: return "APP_MSG_APP_NOT_RUNNING";
case APP_MSG_INVALID_ARGS: return "APP_MSG_INVALID_ARGS";
case APP_MSG_BUSY: return "APP_MSG_BUSY";
case APP_MSG_BUFFER_OVERFLOW: return "APP_MSG_BUFFER_OVERFLOW";
case APP_MSG_ALREADY_RELEASED: return "APP_MSG_ALREADY_RELEASED";
case APP_MSG_CALLBACK_ALREADY_REGISTERED: return "APP_MSG_CALLBACK_ALREADY_REGISTERED";
case APP_MSG_CALLBACK_NOT_REGISTERED: return "APP_MSG_CALLBACK_NOT_REGISTERED";
case APP_MSG_OUT_OF_MEMORY: return "APP_MSG_OUT_OF_MEMORY";
case APP_MSG_CLOSED: return "APP_MSG_CLOSED";
case APP_MSG_INTERNAL_ERROR: return "APP_MSG_INTERNAL_ERROR";
default: return "UNKNOWN ERROR";
}
}
void message_dropped(AppMessageResult reason, void *context) {
APP_LOG(APP_LOG_LEVEL_ERROR, "Dropped message! Reason given: %s", translate_error(reason));
}
void message_out_success(DictionaryIterator *iter, void *context) {
APP_LOG(APP_LOG_LEVEL_DEBUG, "Message sent.");
}
void message_out_failed(DictionaryIterator *iter, AppMessageResult reason, void *context) {
APP_LOG(APP_LOG_LEVEL_DEBUG, "Failed to send message. Reason = %s", translate_error(reason));
}

7
src/c/messaging.h Normal file
View File

@@ -0,0 +1,7 @@
#pragma once
void send(int key, int value, int key2, int value2, int key3, char value3[64]);
void inbox_received_callback(DictionaryIterator *iterator, void *context);
void message_dropped(AppMessageResult reason, void *context);
void message_out_success(DictionaryIterator *iter, void *context);
void message_out_failed(DictionaryIterator *iter, AppMessageResult reason, void *context);

217
src/c/num2words.c Normal file
View File

@@ -0,0 +1,217 @@
#include "num2words.h"
#include <string.h>
#include <stdio.h>
static const char* const ONES[] = {
"zero",
"one",
"two",
"three",
"four",
"five",
"six",
"seven",
"eight",
"nine"
};
static const char* const TEENS[] ={
"",
"eleven",
"twelve",
"thirteen",
"fourteen",
"fifteen",
"sixteen",
"seventeen",
"eighteen",
"nineteen"
};
static const char* const TEENS_SPLIT[][2] = {
{"", ""},
{"eleven",""},
{"twelve",""},
{"thirteen",""},
{"four","teen"},
{"fifteen",""},
{"sixteen",""},
{"seven","teen"},
{"eight","teen"},
{"nine","teen"}
};
static const char* const TENS[] = {
"",
"ten",
"twenty",
"thirty",
"forty",
"fifty",
"sixty",
"seventy",
"eighty",
"ninety"
};
static const char* STR_OH_TICK = "o'";
static const char* STR_O_TICK = "o";
static const char* STR_CLOCK = "clock";
static const char* STR_NOON = "noon";
static const char* STR_MIDNIGHT = "midnight";
static const char* STR_QUARTER = "quarter";
static const char* STR_TO = "to";
static const char* STR_PAST = "past";
static const char* STR_HALF = "half";
static const char* STR_AFTER = "after";
static size_t append_number(char* words, int num) {
int tens_val = num / 10 % 10;
int ones_val = num % 10;
size_t len = 0;
if (tens_val > 0) {
if (tens_val == 1 && num != 10) {
strcat(words, TEENS[ones_val]);
return strlen(TEENS[ones_val]);
}
strcat(words, TENS[tens_val]);
len += strlen(TENS[tens_val]);
if (ones_val > 0) {
strcat(words, " ");
len += 1;
}
}
if (ones_val > 0 || num == 0) {
strcat(words, ONES[ones_val]);
len += strlen(ONES[ones_val]);
}
return len;
}
void fuzzy_time_to_words(int hours, int minutes, char* words) {
int fuzzy_hours = hours;
int fuzzy_minutes = ((minutes + 2) / 5) * 5;
// Handle hour & minute roll-over.
if (fuzzy_minutes > 55) {
fuzzy_minutes = 0;
fuzzy_hours += 1;
if (fuzzy_hours > 23) {
fuzzy_hours = 0;
}
}
time_to_common_words(fuzzy_hours, fuzzy_minutes, words);
}
// returns number of lines written
void time_to_common_words(int hours, int minutes, char *words) {
// TODO: make an app-safe assert
// PBL_ASSERT(hours >= 0 && hours < 24, "Invalid number of hours");
// PBL_ASSERT(minutes >= 0 && minutes < 60, "Invalid number of minutes");
size_t written = 0;
strcpy(words, "");
if (minutes != 0 && (minutes >= 10 || minutes == 5 || hours == 0 || hours == 12)) {
if (minutes == 15) {
written += sprintf(words, "%s %s ", STR_QUARTER, STR_AFTER);
} else if (minutes == 45) {
written += sprintf(words, "%s %s ", STR_QUARTER, STR_TO);
hours = (hours + 1) % 24;
} else if (minutes == 30) {
written += sprintf(words, "%s %s ", STR_HALF, STR_PAST);
} else if (minutes < 30) {
written += append_number(words, minutes);
written += sprintf(words + written, " %s ", STR_AFTER);
} else {
written += append_number(words, 60 - minutes);
written += sprintf(words + written, " %s ", STR_TO);
hours = (hours + 1) % 24;
}
}
if (hours == 0) {
written += sprintf(words + written, "%s", STR_MIDNIGHT);
} else if (hours == 12) {
strcat(words, STR_NOON);
written += sprintf(words + written, "%s", STR_NOON);
} else {
written += append_number(words, hours % 12);
}
if (minutes < 10 && minutes != 5 && !(hours == 0 || hours == 12)) {
if (minutes == 0) {
sprintf(words + written, " %s%s", STR_OH_TICK, STR_CLOCK);
} else {
sprintf(words + written, " %s%s", STR_OH_TICK, ONES[minutes]);
}
}
}
// o'clock (0) and plain number words (10..)
void minute_to_formal_words(int minutes, int displayPrefix, char *first_word, char *second_word) {
// PBL_ASSERT(minutes >= 0 && minutes < 60, "Invalid number of minutes");
strcpy(first_word, "");
strcpy(second_word, "");
if (minutes == 0) {
strcat(first_word, STR_OH_TICK);
strcat(first_word, STR_CLOCK);
return;
}
if (minutes < 10) {
if (displayPrefix) {
strcat(first_word, STR_O_TICK); //add "o"
strcat(second_word, ONES[minutes%10]); //new
}
else {
strcat(first_word, ONES[minutes%10]);
}
return;
}
if (minutes > 10 && minutes < 20) {
strcat(first_word, TEENS_SPLIT[(minutes - 10) % 10][0]);
strcat(second_word, TEENS_SPLIT[(minutes - 10) % 10][1]);
return;
}
strcat(first_word, TENS[minutes / 10 % 10]);
int minute_ones = minutes % 10;
if (minute_ones) {
strcat(second_word, ONES[minute_ones]);
}
}
void hour_to_12h_word(int hours, char *word) {
// PBL_ASSERT(hours >= 0 && hours < 24, "Invalid number of hours");
hours = hours % 12;
if (hours == 0) {
hours = 12;
}
strcpy(word, "");
append_number(word, hours);
}
void hour_to_24h_word(int hours, char *words) {
// PBL_ASSERT(hours >= 0 && hours < 24, "Invalid number of hours");
hours = hours % 24;
strcpy(words, "");
append_number(words, hours);
}