RebbleOS icon indicating copy to clipboard operation
RebbleOS copied to clipboard

RebbleOS Emu-Compass Support

Open tertty opened this issue 8 months ago • 1 comments

The Plan

Get the CompassService to work on RebbleOS by creating the drivers/services required for the accelerometer and magnetometer. Additionally, implement the emu-compass commands found with the pebble CLT. This PR covers the latter (gotta walk before you can run).

Design

First and foremost, I have entirely based the design of this service from the currently implemented BatteryService. However, I don't know if this is the best idea or that I entirely understand why things are the way they are with the current BatteryService. If there is a rhyme or reason that could be explained to me, that would help.

While researching the CompassService and emu-compass features on the archived Pebble Development Website, I ran across this blog post discussing the design of the Pebble QEMU emulator. Towards the bottom of the post, I found this helpful tidbit that I used as a guiding light throughout design and implementation:

Data for the compass on the Pebble is also sent through the PQ channel with a unique PQP protocol ID. The pebble tool in the SDK includes a command for sending compass orientation (in degrees) and calibration status.

On the Pebble side, we have a custom handler for PQP compass packets that simply extracts the heading and calibration status from the packet and sends an event to the system with this information – which is exactly how the real compass driver hooks into the system.

I found this helpful because this means there isn't a separate service or code that's dedicated to handling emu-compass data vs "real" compass data. All data should funnel down to the same core API functions. I sort of saw how we were doing this with our current BatteryService, and I hope I've created a good foundation that will allow data to be pushed up to the API and not have the API pull data from the system.

hardware "driver"/handler/whatever in rcore --- \
                                                 ---informs--> API service --informs--> system/user app
             QEMU protocol handler          --- /

Implementation

A new compass.c/.h file in rcore has been created representing the routines for controlling the compass by combining the accelerometer and the magnetometer. A lot of this is currently just boilerplate for the (hopefully) later hardware implementation.

I have added a unique QEMU endpoint called QemuProtocol_Compass as I felt like the emu-compass was its own category and didn't fit in the current existing defined endpoints. Also, I felt the above quote was hinting towards this following the original implementation.

From there, a new protocol_compass.c/.h file has been added to our protocol folder in rcore. Inspired by the BatteryService, I've named this module "pcolcompass" and filed it under a "SYS" module type. This should properly bring out the two functions we need for emu-compass coms.

The following functions from the CompassService have graduated from UNIMPL to implemented:

  • compass_service_peek
  • compass_service_set_heading_filter
  • compass_service_subscribe
  • compass_service_unsubscribe

I've also implemented the following Pebble ~~Marcos~~ Macros that are heavily tied with the CompassService:

  • TRIANGLE_TO_DEG
  • DEG_TO_TRIGANGLE

Testing & Validation

I've attempted to run my verification tests using three different compass applications. I've chosen these apps specifically because A.) they looked good enough and B.) they had readily available source code that could be used to diagnose potential issues. Despite this, I unfortunately ran into a pitfall in nearly each one. I think not having the accelerometer and magnetometer and their Services (as well as other general API) rung out caused a lot of these snags:

  • The official Pebble Compass app - The app installed on RebbleOS, but wouldn't launch. I'm thinking we're getting stuck on the initial "calibration" window that pops up when the app launches and asks you to fill your ring.
  • Paul Mitchell's Compass app - The app installed, and I get a default compass outline. But it never responds to different emu-compass commands or displays the center text. It's trying to call the app message and app sync API, which is currently unimplemented, so I'm wondering if we're getting hung on that.
  • Ivan Gorinov's Compass app - This app is dead simple so I got this app's compass readings to work, but I couldn't get the center directional needle to draw. You'll see examples in a later video below.

In the following video demonstration you can find me testing the dummy compass emulation commands by comparing RebbleOS with Pebble. The top QEMU window is RebbleOS and the bottom QEMU window is Pebble. An obvious difference between the two windows is the missing compass needle in RebbleOS. I'm not exactly sure why this is. It could be a side effect from something else not yet being implemented, not sure. However I'm boldly asking you to ignore it, and instead pay attention to the degree reading on the top right of the application. As you can see, when I send the same command to RebbleOS and Pebble, the reading stays consistent. Screencast from 2024-02-18 16-01-15.webm

Conclusion

Therefore according to the results of my test, I feel like I have enough to prove that the basic functionality of the emu-compass tool is working even with the snags. If possible, I'd like feedback on if I've inserted my CompassService cleanly with RebbleOS' existing Service design and if I've created a stable and foundation for later hardware implementation. Of course, all other general feedback is welcome too.

tertty avatar Jun 18 '24 05:06 tertty