diff --git a/config.mk b/config.mk index 6467cc73..af7fa737 100644 --- a/config.mk +++ b/config.mk @@ -117,6 +117,7 @@ SRCS_all += rcore/rebble_util.c SRCS_all += rcore/qemu.c SRCS_all += rcore/qemu_endpoints.c SRCS_all += rcore/service.c +SRCS_all += rcore/compass.c SRCS_all += rcore/protocol/protocol_notification.c SRCS_all += rcore/protocol/protocol_system.c @@ -126,6 +127,7 @@ SRCS_all += rcore/protocol/protocol_blob.c SRCS_all += rcore/protocol/protocol_call.c SRCS_all += rcore/protocol/protocol_music.c SRCS_all += rcore/protocol/protocol_transfer.c +SRCS_all += rcore/protocol/protocol_compass.c SRCS_all += rcore/rdb.c SRCS_all += rcore/rdb_test.c @@ -154,6 +156,7 @@ SRCS_all += rwatch/graphics/font_loader.c SRCS_all += rwatch/event/tick_timer_service.c SRCS_all += rwatch/event/app_timer.c SRCS_all += rwatch/event/battery_state_service.c +SRCS_all += rwatch/event/compass_service.c SRCS_all += rwatch/event/connection_service.c SRCS_all += rwatch/event/event_service.c SRCS_all += rwatch/ui/layer/status_bar_layer.c diff --git a/rcore/api_func_symbols.h b/rcore/api_func_symbols.h index 2ae8eab9..ff434cc7 100644 --- a/rcore/api_func_symbols.h +++ b/rcore/api_func_symbols.h @@ -7,6 +7,7 @@ #include "inverter_layer.h" #include "storage_persist.h" #include "dictionary.h" +#include "compass_service.h" GBitmap *gbitmap_create_with_resource_proxy(uint32_t resource_id); @@ -122,10 +123,6 @@ UNIMPL(_app_worker_message_unsubscribe); UNIMPL(_app_worker_send_message); UNIMPL(_worker_event_loop); UNIMPL(_worker_launch_app); -UNIMPL(_compass_service_peek); -UNIMPL(_compass_service_set_heading_filter); -UNIMPL(_compass_service_subscribe); -UNIMPL(_compass_service_unsubscribe); UNIMPL(_animation_legacy2_set_custom_curve); UNIMPL(_watch_info_get_color); UNIMPL(_watch_info_get_firmware_version); @@ -472,6 +469,11 @@ const VoidFunc sym[] = { [335] = (VoidFunc)app_heap_bytes_free, // heap_bytes_free@0000053c [336] = (VoidFunc)app_heap_bytes_used, // heap_bytes_used@00000540 + [337] = (VoidFunc)compass_service_peek, // compass_service_peek@00000544 + [338] = (VoidFunc)compass_service_set_heading_filter, // compass_service_set_heading_filter@00000548 + [339] = (VoidFunc)compass_service_subscribe, // compass_service_subscribe@0000054c + [340] = (VoidFunc)compass_service_unsubscribe, // compass_service_unsubscribe@00000550 + [341] = (VoidFunc)uuid_equal, // uuid_equal@00000554 [342] = (VoidFunc)uuid_to_string, // uuid_to_string@00000558 [343] = (VoidFunc)gpath_fill_app, // gpath_draw_filled@0000055c @@ -795,10 +797,7 @@ const VoidFunc sym[] = { [332] = (UnimplFunc)_app_worker_send_message, // app_worker_send_message@00000530 [333] = (UnimplFunc)_worker_event_loop, // worker_event_loop@00000534 [334] = (UnimplFunc)_worker_launch_app, // worker_launch_app@00000538 - [337] = (UnimplFunc)_compass_service_peek, // compass_service_peek@00000544 - [338] = (UnimplFunc)_compass_service_set_heading_filter, // compass_service_set_heading_filter@00000548 - [339] = (UnimplFunc)_compass_service_subscribe, // compass_service_subscribe@0000054c - [340] = (UnimplFunc)_compass_service_unsubscribe, // compass_service_unsubscribe@00000550 + [344] = (UnimplFunc)_animation_legacy2_set_custom_curve, // animation_legacy2_set_custom_curve@00000560 [345] = (UnimplFunc)_watch_info_get_color, // watch_info_get_color@00000564 [346] = (UnimplFunc)_watch_info_get_firmware_version, // watch_info_get_firmware_version@00000568 diff --git a/rcore/compass.c b/rcore/compass.c new file mode 100644 index 00000000..bfb0b0f7 --- /dev/null +++ b/rcore/compass.c @@ -0,0 +1,53 @@ +/* compass.c + * routines for controlling the compass (accelerometer + magnetometer) + * RebbleOS + * + * Author: Taylor E. + */ + +#include "compass.h" +#include "rebbleos.h" +#include "compass_service.h" + +static uint8_t _calibration_mode = 0; +static int32_t _compass_heading = 0; +static int32_t _compass_heading_filter = (TRIG_MAX_ANGLE / 360); + +void compass_init() { + +} + +void compass_off() { + +} + +uint8_t compass_get_calibration_mode(void) { + return _calibration_mode; +} + +int32_t compass_get_heading(void) { + return _compass_heading; +} + +int32_t compass_get_heading_filter(void) { + return _compass_heading_filter; +} + +// These set functions have been put here so the Compass Emu protocol can update the Compass' values (this was made first). +// However these functions probably shouldn't exist, as this file should be polling hardware to get latest values, not having hardware +// push to this file... + +void compass_set_calibration_mode(uint8_t new_compass_calibration_mode) { + _calibration_mode = new_compass_calibration_mode; + compass_service_state_change(); +} + +void compass_set_heading(int32_t new_compass_heading) { + _compass_heading = new_compass_heading; + compass_service_state_change(); +} + +void compass_set_heading_filter(int32_t new_compass_heading_filter) { + _compass_heading_filter = new_compass_heading_filter; + compass_service_state_change(); +} diff --git a/rcore/compass.h b/rcore/compass.h new file mode 100644 index 00000000..c9f645ec --- /dev/null +++ b/rcore/compass.h @@ -0,0 +1,31 @@ +#pragma once +/* compass.c + * routines for controlling the compass (accelerometer + magnetometer) + * RebbleOS + * + * Author: Taylor E. + */ + +#include "FreeRTOS.h" + +/** + * @brief Compass calibration modes. +*/ +#define COMPASS_CAL_STATUS_UNAVAILABLE 0 +#define COMPASS_CAL_STATUS_DATA_INVALID 1 +#define COMPASS_CAL_STATUS_CALIBRATING 2 +#define COMPASS_CAL_STATUS_CALIBRATED 3 + +void compass_init(void); + +void compass_off(void); + +uint8_t compass_get_calibration_mode(void); + +int32_t compass_get_heading(void); + +int32_t compass_get_heading_filter(void); + +void compass_set_heading_filter(int32_t new_compass_heading_filter); +void compass_set_calibration_mode(uint8_t new_compass_calibration_mode); +void compass_set_heading(int32_t new_compass_heading); \ No newline at end of file diff --git a/rcore/protocol/protocol_compass.c b/rcore/protocol/protocol_compass.c new file mode 100644 index 00000000..fd81d727 --- /dev/null +++ b/rcore/protocol/protocol_compass.c @@ -0,0 +1,28 @@ +/* protocol_compass.c + * R/Pebble Protocol Compass requests. + * libRebbleOS + * + * Author: Taylor E. + */ +#include "rebbleos.h" +#include "protocol.h" +#include "protocol_service.h" +#include "compass_service.h" +/* Configure Logging */ +#define MODULE_NAME "pcolcompass" +#define MODULE_TYPE "SYS" +#define LOG_LEVEL RBL_LOG_LEVEL_DEBUG //RBL_LOG_LEVEL_ERROR + +typedef struct qemu_compass_t { + uint32_t heading; + uint8_t calibrated; +} __attribute__((__packed__)) qemu_compass; + +void protocol_compass_handler(const RebblePacket packet) +{ + qemu_compass *qemu_compass_payload = (qemu_compass *) packet_get_data(packet); + qemu_compass_payload->heading = ntohl(qemu_compass_payload->heading); + + compass_set_calibration_mode(qemu_compass_payload->calibrated); + compass_set_heading(qemu_compass_payload->heading); +} \ No newline at end of file diff --git a/rcore/protocol/protocol_compass.h b/rcore/protocol/protocol_compass.h new file mode 100644 index 00000000..914fa6fc --- /dev/null +++ b/rcore/protocol/protocol_compass.h @@ -0,0 +1,5 @@ +#pragma once + +#include "protocol.h" + +void protocol_compass_handler(const RebblePacket packet); \ No newline at end of file diff --git a/rcore/qemu_endpoints.c b/rcore/qemu_endpoints.c index ce399462..2bb2142c 100644 --- a/rcore/qemu_endpoints.c +++ b/rcore/qemu_endpoints.c @@ -5,6 +5,7 @@ #include "test.h" #include "protocol_service.h" #include "rebble_memory.h" +#include "protocol_compass.h" void other_handler(const RebblePacket incoming_packet) { @@ -37,5 +38,9 @@ const PebbleEndpoint qemu_endpoints[] = .endpoint = QemuProtocol_BluetoothConnection, .handler = other_handler }, + { + .endpoint = QemuProtocol_Compass, + .handler = protocol_compass_handler + }, { .handler = NULL } }; diff --git a/rcore/rebbleos.c b/rcore/rebbleos.c index 20bcfcfe..a1734f57 100644 --- a/rcore/rebbleos.c +++ b/rcore/rebbleos.c @@ -19,6 +19,7 @@ #include "rtoswrap.h" #include "test.h" #include "service.h" +#include "compass.h" typedef uint8_t (*mod_callback)(void); // static TaskHandle_t _os_task; diff --git a/rwatch/event/compass_service.c b/rwatch/event/compass_service.c new file mode 100644 index 00000000..30d71387 --- /dev/null +++ b/rwatch/event/compass_service.c @@ -0,0 +1,50 @@ +/* routines that implement the PebbleOS compass api + * libRebbleOS + * + * Author: Taylor E. + * + */ + +#include "librebble.h" +#include "compass_service.h" + +static CompassHeadingHandler _state_handler; + +int compass_service_set_heading_filter(CompassHeading filter) { + if (filter < 0 || filter > (TRIG_MAX_ANGLE / 2)) { + return -1; + } + else { + compass_set_heading_filter(filter); + return 0; + } + +} + +void compass_service_subscribe(CompassHeadingHandler handler) { + _state_handler = handler; +} + +void compass_service_unsubscribe(void) { + _state_handler = NULL; +} + +int compass_service_peek(CompassHeadingData * data) { + data->magnetic_heading = compass_get_heading(); + data->true_heading = compass_get_heading(); + data->compass_status = compass_get_calibration_mode(); + data->is_declination_valid = false; + + return 0; +} + +void compass_service_state_change(void) +{ + SYS_LOG("COMP", APP_LOG_LEVEL_INFO, "Update"); + + CompassHeadingData new_compass_heading_data; + compass_service_peek(&new_compass_heading_data); + + if (_state_handler != NULL) + _state_handler(new_compass_heading_data); +} \ No newline at end of file diff --git a/rwatch/event/compass_service.h b/rwatch/event/compass_service.h new file mode 100644 index 00000000..c28efc33 --- /dev/null +++ b/rwatch/event/compass_service.h @@ -0,0 +1,38 @@ +/* routines that implement the PebbleOS compass api +*/ + +/** + * @brief Represents an angle relative to get to a reference direction, e.g. (magnetic) north. The angle value is scaled linearly, such that a value of TRIG_MAX_ANGLE corresponds to 360 degrees or 2 PI radians. Thus, if heading towards north, north is 0, west is TRIG_MAX_ANGLE/4, south is TRIG_MAX_ANGLE/2, and so on. +*/ +typedef int32_t CompassHeading; + +typedef enum { + CompassStatusUnavailable, /* The Compass Service is unavailable. */ + CompassStatusDataInvalid, /* Compass is calibrating: data is invalid and should not be used Data will become valid once calibration is complete. */ + CompassStatusCalibrating, /* Compass is calibrating: the data is valid but the calibration is still being refined. */ + CompassStatusCalibrated /* Compass data is valid and the calibration has completed. */ +} CompassStatus; + +typedef struct { + CompassHeading magnetic_heading; /* Measured angle that increases counter-clockwise from magnetic north (use int clockwise_heading = TRIG_MAX_ANGLE - heading_data.magnetic_heading; for example to find your heading clockwise from magnetic north). */ + CompassHeading true_heading; /* Currently same value as magnetic_heading (reserved for future implementation). */ + CompassStatus compass_status; /* Indicates the current state of the Compass Service calibration. */ + bool is_declination_valid; /* Currently always false (reserved for future implementation). */ +} CompassHeadingData; + +/** + * @brief Callback type for compass heading events. + * @param heading A copy of last recorded heading. +*/ +typedef void(* CompassHeadingHandler)(CompassHeadingData heading); + +int compass_service_set_heading_filter(CompassHeading filter); + +void compass_service_subscribe(CompassHeadingHandler handler); + +void compass_service_unsubscribe(void); + +int compass_service_peek(CompassHeadingData * data); + +void compass_service_hw_state_change(void); +void compass_service_emu_state_change(CompassHeadingData emu_data); \ No newline at end of file diff --git a/rwatch/pebble.h b/rwatch/pebble.h index e655e65d..d9c9d4ce 100644 --- a/rwatch/pebble.h +++ b/rwatch/pebble.h @@ -27,6 +27,8 @@ #define TRIG_MAX_RATIO 0xffff #define TRIG_MAX_ANGLE 0x10000 +#define TRIANGLE_TO_DEG(trig_angle) (trig_angle) * 360 / TRIG_MAX_ANGLE +#define DEG_TO_TRIGANGLE(angle) (angle) * TRIG_MAX_ANGLE / 360 struct n_GRect;