Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

hourly chime not working in standby mode #275

Closed
Niehztog opened this issue Sep 15, 2023 · 16 comments · Fixed by #325
Closed

hourly chime not working in standby mode #275

Niehztog opened this issue Sep 15, 2023 · 16 comments · Fixed by #325

Comments

@Niehztog
Copy link

Some time ago I flashed a new firmware to my sensor watch built directly from the up-to-date main branch. Since then the hourly chime is not working in standby mode. My watches buzzer is working fine, so it is not related to that. It must have been some of the commits from the last few months which broke the feature.

Can anyone running a more resent built of movement on his watch confirm this?

@CarpeNoctem
Copy link
Contributor

Hmm. I'm running a pretty fresh build. I'll enable the chime and comment back here later today.

@CarpeNoctem
Copy link
Contributor

I can confirm that my watch is missing these hourly chimes in LE mode as well. I'll check my other watch when I get home. Its firmware was compiled (by me) from source as well, but sometime earlier. If it doesn't have the issue, that could help narrow down when the issue crept in.

@CarpeNoctem
Copy link
Contributor

So I haven't made it home yet, but did another check out of curiosity. I set an alarm for a time during LE mode. Paying closer attention the second time, I confirmed that it actually wakes the watch up out of LE mode into normal mode. I'm not sure whether or not this used to be the case for the hourly chime, but may be worth noting.

@fedpost
Copy link

fedpost commented Sep 18, 2023

I have had this issue for a while. It has been intermittent and I haven't cared enough to investigate or give it any further thought, but I can confirm it happens with my build as well.

@Niehztog
Copy link
Author

Commit c1580b3 replaced the function call that plays the hourly chime from watch_buzzer_play_note with watch_buzzer_play_sequence.
watch_buzzer_play_note works in low energy mode, watch_buzzer_play_sequence obviously doesn't. (I tested that on my watch by reverting the change and the hourly chime worked again in low energy mode).

@TheOnePerson and @neutralinsomniac , does maybe one of you have an idea how we can get the beautiful custom hourly chime tunes from #209 working in low energy mode?

@TheOnePerson
Copy link
Contributor

As far as I know does neither of watch_buzzer_play_note or watch_buzzer_play_sequence work in LE mode.
Just from looking at the code:

The changes in the internal logic of movement_play_signal have led to tunes being played asynchronously. Consequently, the function returns immediately after initializing the buzzer, rather than waiting for the tune to finish playing. This means that the implementation here in simple_clock_face.c does not work as expected any more. When an hourly chime is to be played while the watch is in LE mode, it first enables the buzzer (which is good), initializes the sequence - and immediately after that the buzzer is disabled again (which is bad).

My take on this problem would be:

a) Restore movement_play_signal() to its former version, using watch_buzzer_play_note again. This approach would also maintain compatibility with other watch faces that rely on this function (e.g., tomato_face.c or rpn_calculator_alt_face.c). (However, we could consider whether playing a more elaborate hourly chime is appropriate in these contexts.)

b) Implement the hourly chime sequence directly in simple_clock_face.c, utilizing the callback functionality of watch_buzzer_play_sequence to control when the buzzer is disabled. This approach may provide more control over the chime's behavior and timing, ensuring it works as expected in LE mode.

What do you think, @neutralinsomniac ?

@neutralinsomniac
Copy link
Contributor

neutralinsomniac commented Sep 22, 2023

How about this approach? #283

I kinda like this since it pulls the sleep-specific code into its own functions for easier use by the watch faces (they don't have to manually enable/disable the buzzer). I left the tunes code in movement instead of moving it into simple clock face so that other watch faces can opt-in to playing hourly tunes if they want, but I restored movement_play_signal() (and created a corresponding movement_play_signal_background() for LE use) and pulled the tune code into two new functions: movement_play_tune() and movement_play_tune_background() as well.

Also, apologies to anyone affected by this bug. I should've caught it a long time ago.

@TheOnePerson
Copy link
Contributor

I like your approach, too @neutralinsomniac . This looks fine to me (haven't had a chance to test it yet).

@neutralinsomniac
Copy link
Contributor

Thinking about this further, what if we moved the watch_is_buzzer_or_led_enabled() call and appropriate buzzer enabled/disable logic into movement_play_signal() and movement_play_tune() so that these functions always "just work" and don't require a decision to be made in every watch face before calling these library functions?

@neutralinsomniac
Copy link
Contributor

I pushed this change into my MR if you want to see what it looks like

@synthead
Copy link

How about this approach? #283

I kinda like this since it pulls the sleep-specific code into its own functions for easier use by the watch faces (they don't have to manually enable/disable the buzzer). I left the tunes code in movement instead of moving it into simple clock face so that other watch faces can opt-in to playing hourly tunes if they want, but I restored movement_play_signal() (and created a corresponding movement_play_signal_background() for LE use) and pulled the tune code into two new functions: movement_play_tune() and movement_play_tune_background() as well.

Also, apologies to anyone affected by this bug. I should've caught it a long time ago.

I have built and flashed my red board with the latest main at 5c94111, and I can still reproduce this bug. I have SIGNAL_TUNE_ZELDA_SECRET defined in movement/movement_config.h, if it matters.

@814d3
Copy link

814d3 commented Nov 7, 2023

I can confirm, that the SIGNAL_TUNE_DEFAULT is not working, when the watch is in low energy mode. I am using the latest (67be6af) version. Only two short clicks are recognizable, but no signal.
I did not test timers or the alarm sound, when in LE mode, but probably they won't work either.
Greetings

Edit: Timers and alarm sounds are working well. So the behavior is limited to the hourly sound.

WesleyAC added a commit to WesleyAC/Sensor-Watch that referenced this issue Nov 13, 2023
This allows the default tune to be played in LE mode.

Fixes: joeycastillo#275
@WesleyAC
Copy link
Collaborator

My PR above fixes this for the default tune by using the legacy functions, but I started looking into fixing this for custom tunes as well. The gist of it is that the main problem is that we are immediately turning the TCC off, because watch_buzzer_play_sequence is async, so as soon as we call that, the watch face exits its loop and calls watch_enter_sleep_mode which calls _watch_disable_all_peripherals_except_slcd which calls _watch_disable_tcc. The fix is probably for movement to know when a sequence has been requested to be played, and in that case, turn off all peripherals except slcd and tcc.

However, even doing that doesn't get it quite working — when I ensure the TCC is enabled the whole time, the tune still sounds quiet and muted. My phone mic can't really pick it up well, but https://hack.wesleyac.com/tune_sleep_mode.aac and https://hack.wesleyac.com/tune_no_sleep_mode.aac show the difference. My guess is some kind of clock scaling difference but I need to track it down.

theorangerider pushed a commit to theorangerider/Sensor-Watch that referenced this issue Dec 21, 2023
This allows the default tune to be played in LE mode.

Fixes: joeycastillo#275
(cherry picked from commit 27c9845)
@maxz
Copy link
Contributor

maxz commented Jan 8, 2024

This issue still persists (or returned) in the current head of the main branch (Commit 63d6bc6aa0ddf4cc1ce1918ef7650852a25e581b.)

WesleyAC added a commit to WesleyAC/Sensor-Watch that referenced this issue Jan 9, 2024
This allows the default tune to be played in LE mode.

Fixes: joeycastillo#275
@WesleyAC
Copy link
Collaborator

WesleyAC commented Jan 9, 2024

@maxz that's because the PR fixing it (#325) hasn't been merged in yet. should be very soon, but you can grab the code from that PR if you want a fix now.

@maxz
Copy link
Contributor

maxz commented Jan 10, 2024

Ah, thank you for the update.

I was not sure about the current state with various reverts I encountered when trying to check what's actually merged right now and already though about band-aid fixing it myself in my local copy.

navan93 added a commit to navan93/Sensor-Watch that referenced this issue Mar 24, 2024
* Fixed incorrect conversion from UNIX timestamp to watch_date_time.

* Print memory percentages

this gives better idea of memories used.

* new face: Tuning tones

Add a new face that plays out tones that can be used as a
reference when tuning musical instruments.

* Turn on the funky segment of pos 0 for char '@'

* add new COLOR flag

* update alternate firmware for new board color

* Add a volume slider in the simulator

* Save the selected skin of the simulator in local storage

* fix signal tunes not firing in background, and split out foreground/background chime functions

* move buzzer enabled detection logic into movement for movement_play_signal/tune

this way watch faces don't have to disable/enable the buzzer themselves
before calling movement_play_signal() and movement_play_tune()

* use movement_play_signal for default tune (fixes background signal)

* Don't allow building without setting board color.

Fixes: joeycastillo#288

* add compile-time options for all preferences to movement_config

* Set default board color for GH workflow.

I've chosen blue arbitrarily.

* Update timer_face.c

Corrects the data type of the standard values in order to be able to configure seconds as well.

* new standard firmware for october boards

* Add Couch-To-5k training face

* Add sound to pause/resume button

* Add minute repeater decimal face

* moon_phase_face: Make alarm long-press reset to current day.

* Add solstice_face.

* Add simple_coin_flip_face.

* Add day_night_percentage_face.

* day_night_percentage_face: Calculate rise/set/daylen only once per day.

* day_night_percentage_face: Use PM indicator instead of DA/NI.

This allows for use of the weekday digits for displaying the weekday.

* day_night_percentage_face: Clear seconds digits when entering LE mode.

* Add save_load_face.

* day_one_face: cleanup

* day_one_face: allow years until 2080

This is the same limit introduced in commit 7fd51ca

* day_one_face: enable quick cycle through settings

This allows the alarm button to be held down in the date settings and
quickly cycle through the dates instead of having to push for each
single increment like in other faces.

* day_one_face: show set date on short alarm button press

* Improve simulator page design

* Fix simulator and hardware divergence in callback handling (joeycastillo#252)

When using the simulator, I encountered cases where the light would become stuck on, and the watch
would be unresponsive. In particular, this would occur when pressing the light button on the
sunrise sunset watch face.

I appears that this is caused by a divergence in out the callback mask is interpreted by the
hardware interface, and in the simulator in the following function.

void watch_rtc_disable_matching_periodic_callbacks(uint8_t mask)

In particular, a mask of 0xFE is intended to disable all except the 128hz callback at index 0,
but instead disables all except the 1hz callback at index 7 in the simulator.

* sunrise_sunset_face: Fix use of uninitialized memory.

This was causing a crash in the simulator when setting the location.

Fixes: joeycastillo#198

* Fit naming conventions

* Resign when the entering LE

* Simulator: Allow typing a, l & m in console input

These keys are the shortcuts to "press" the alarm, light and mode
buttons. However, they prevent these letters from being input in the
debug console to send filesystem commands. Strangely, there was already
some code to allow typing these letters in the console output, but not
in the input.

* Simulator: Allow sending debug command with Enter

* Simulator: Add keyboard arrows as buttons shortcuts

* Fix missing documentation for many clock faces:

* Move from .c to .h as needed for consistency.
* When missing from both, copy from pull request or wiki.
* When missing entirely, infer functionality from source code.

* Kitchen Conversions Face

* fix undefined behavior found by clang's sanitize

* make the zero in wyoscan a little more visually appealing

* make it clear that the movement_state contains indexes

* use a pointer to the watch face in the app loop instead of indirecting through the index each time, and also recalculate can_sleep based on the timeout loop call.

* clean up trailing whitespace in movement.c

* make the watch-face a global in movement.c, actually

* work around silicon erratum in TRNG

* work around silicon erratum in SUPC/VREG

* fix simulator build by declaring Trng type as a void pointer

* address SysTick erratum, which can hard-fault the chip

* make the HAL sleep function obey the chip documentation

the sleep mode doesn't get set immediately, and needs to be waited upon.

* make any unknown interrupts/faults reset the microcontroller

* delete stray line of code that messed with correction profile while adjusting cadence

* USB Improvements

* Introduce shell module for basic serial shell with argument parsing
* Introduce shell_cmd_list module for basic compile-time command
  registration
* Harden USB handling to hang less and drop fewer inputs
  - Service tud_task() with periodic TC0 timer interrupt
  - Service cdc_task() with periodic TC1 timer interrupt
  - Handle shell servicing in main app loop
  - Add a circular buffering layer for reads/writes
* Change newline prints to also send carriage return
* Refactor filesystem commands for shell subsystem
* Introduce new shell commands:
  - 'help' command
  - 'flash' command to reset into bootloader
  - 'stress' command to stress CDC writes

Testing:
* Shell validated on Sensor Watch Blue w/ Linux host
* Shell validated in emscripten emulator
* Tuned by spamming inputs during `stress` cmd until stack didn't crash

* Handle visibility for tomato watchface

(cherry picked from commit 547e8248ba3538693ee8c587a92ffece7b40d1a2)

* Revert "Merge pull request joeycastillo#283 from neutralinsomniac/fix_hourly_chime_background"

This reverts commit 5c94111, reversing
changes made to bc9b4ce.

* Use legacy buzzer functions when playing default tune.

This allows the default tune to be played in LE mode.

Fixes: joeycastillo#275

* Enable custom signal tones in LE mode.

This makes movement_play_signal synchronous when in LE mode, despite
using the underlying asynchronous API. It's a bit of a hack, but it
should work well enough for now.

This also moves the enabling/disabling of the buzzer into the
movement_play_signal function, so that watch faces no longer have to do
it.

* buzzer: fix simulator build, refactor sequence_length.

* movement: Use LE mode code to keep buzzer awake, instead of sleeping.

* fix alternate firmware script

* template: fix compiler warning on watch_face_index as mentioned in PR 269

* Revert "make the watch-face a global in movement.c, actually"

This reverts commit 0e801ed.

* annotate TRNG erratum, address review comment

* annotate SysTick erratum

* annotate voltage regulation erratum

* annotate SLEEPCFG-register detail

* Change inactivity deadlines: add 10 minutes and remove 2 days. (joeycastillo#365)

I like to use the ten minute timeout on my watch and there are other
people who have similar interests in a lower deadline. The two day
deadline had to go to still accommodate the change within the three
bit index.

The default setting is still the one hour timeout.

* faces/totp: define TOTP data structure

Aggregates all the data necessary for TOTP generation.

* faces/totp: define TOTP struct initializer macro

Generates a compound initializer for the given TOTP parameters.
Lessens repetition and allows functional definitions of TOTP records.

* faces/totp: update example data to new structure

The data definitions are much shorter and easier to read now.

* faces/totp: define TOTP data array size function

Computes the size of the array of TOTP records.
The compiler will likely evaluate it at compile time.

* faces/totp: define current TOTP data function

Selects the appropriate TOTP data structure
given the TOTP watch face state.

* faces/totp: update watch face logic for new struct

Using the new structured TOTP record data structure
allows the TOTP watch face to statically and implicitly
compute the total number of defined TOTP records.

Users can now simply add new keys and records in the designated area
and the watch face will compile and automatically use them with no need
to maintain a separate array size variable. Less chance of mistakes.

* faces/totp: delete unused structure field

The TOTP watch face now keeps track of each key separately.
There is no need to compute offsets at runtime.

* faces/totp: update copyright and license data

Update the copyrights to include full name attribution
to all who contributed to this watch face, including myself.

Also add an SPDX license identifier header comment to the files.

https://spdx.org/licenses/MIT.html

* faces/pulsometer: implement advanced pulsometer

Implements an advanced pulsometer that can be recalibrated by the user.
The main clock face now displays the measured pulses per minute.
The day of month digits now display the pulsometer calibration.
The light button now cycles through integer graduations
which now range from 1 to 39 pulses per minute.
Long presses of the light button cycle by 10 instead of 1.

The watch face's responsiveness to input has been carefully optimized.
The code has been reorganized and generally improved.

* faces/pulsometer: document the advanced pulsometer

Thoroughly document the new advanced pulsometer watch face
by describing what it is and how it works.

* faces/pulsometer: update copyrights and credits

Update the copyrights to include full name attribution to all
who contributed to the pulsometer watch face, including myself.

Also add an SPDX license identifier header comment to the files.

* faces/pulsometer: move structure definition

Instances of the pulsometer state structure are only passed
to the pulsometer itself and only via the opaque context pointer.
No other code uses it. There is no need to expose it in a header file
so make it an implementation detail of the watch face.

* faces: rename simple_clock_face to clock_face

It's not actually so simple and will only gain features from now on.
Just "clock face" also feels more canonical.

* faces/clock: move structure definition

Instances of the clock state structure
are only passed to the clock face itself
and only via the opaque context pointer.
No other code uses it.

Thus there is no need to expose it in a header file.
So make it an implementation detail of the watch face
by localizing it inside the translation unit.

* faces/clock: define general indication function

Sets or clears the specified indicator based on some boolean value.

* faces/clock: simplify alarm indication function

Deduplicates state in the clock state and movement settings.
Makes the code simpler.

Also makes it use the correct indicator.
For some reason it had been switched
with the hourly chime indicator.

    WATCH_INDICATOR_BELL
        The small bell indicating that an alarm is set.

    WATCH_INDICATOR_SIGNAL
        The hourly signal indicator.
        Also useful for indicating that sensors are on.

* faces/clock: simplify signal indication function

Simplifies the code and makes it use the correct indicator.
For some reason it had been switched with the alarm indicator.

    WATCH_INDICATOR_BELL
        The small bell indicating that an alarm is set.

    WATCH_INDICATOR_SIGNAL
        The hourly signal indicator.
        Also useful for indicating that sensors are on.

* faces/clock: simplify 24h indication function

Simplifies the code by adding a dedicated function for this.

* faces/clock: simplify PM indication function

Simplifies the code by adding dedicated functions for this.

* faces/clock: refactor daily battery check

Move the code in question to a dedicated function. Better organized.
Add overridable preprocessor definition for the low battery threshold.

* faces/clock: simplify LAP indication function

Simplifies the code by adding a dedicated function for this.
Also documents the meaning of the LAP indicator: Low Available Power.

* faces/clock: refactor low power tick function

Simplifies the code by defining dedicated functions
and separating the case from the main ones.

Also use the snprintf function since the buffer size is known.

* faces/clock: refactor tick tock animation code

Simplifies the code by defining dedicated functions for this.

* faces/clock: refactor full time display code

Simplifies the code by defining dedicated functions for this.

* faces/clock: refactor partial time display code

Simplifies the code by defining dedicated functions for this.

* faces/clock: reorder periodic battery check

Check the battery after the time has been updated.
Place all the indication code next to each other.

* faces/clock: refactor clock display code

Simplifies the code by defining dedicated functions for this.

* faces/clock: refactor time signal toggling code

Simplifies the code by defining dedicated functions for this.

* faces/clock: indicate alarm only when necessary

The alarm state is not modified within the clock face.
Therefore, it only needs to be set when the face is activated.

* faces/clock: indicate low power only when needed

There is no need to set the indicator on every clock tick.
Indicate only when the battery is checked.

* faces/totp: decode secrets when setting up

This allows the user to easily copy the base32 encoded secrets
into the TOTP record initializers. They will be decoded once
at runtime when the face is being set up by the movement framework.

Also rename the array of TOTP records to credentials. Much better.

* faces/totp: improve TOTP initializer labeling

It now generates the string literal from the preprocessor token.
Even warns the user if the string is too long!

* faces/totp: rename initializer macro to credential

Shorter and far more expressive.

* faces/totp: delete leading underscores

Makes for cleaner symbols.

* faces/clock: update copyrights and credits

Update the copyrights to include full name attribution to all
who contributed to the clock watch face, including myself.

Also add an SPDX license identifier header comment to the files.

* faces/clock: add 24h only feature

The clock watch face can now be configured at build time
to only display the time in 24h mode. Also enabled in forced 24h mode.

This should result in smaller code size due to dead code elimination.

* faces/totp: allow moving backwards through codes

Adds the ability to cycle back to the previous credential with LIGHT.
Long pressing LIGHT activates the LED.

Co-authored-by: Matheus Afonso Martins Moreira <matheus.a.m.moreira@gmail.com>

* faces/totp: update copyrights

Update the copyrights to include full name attribution
to Max Zettlmeißl whose code I've incorporated and who
has explicitly licensed it as MIT.

Max Zettlmeißl (@maxz) commented on 2024-01-20:

> I provide all my changes under the MIT license

GitHub-Comment: joeycastillo#356 (comment)

* faces/pulsometer: remember pulsometer calibration

Avoid resetting it to default when the face is activated.
Set the default pulsometer calibration once,
only when the face is first set up.

This makes it remember the calibration set by the user.
It will no longer overwrite it.

* faces/pulsometer: remember pulsometer measurement

Avoid resetting it to zero when the face is activated.
Initialize the variables once when the face is first set up.

This makes it remember the last measurement taken by the user.
It will no longer be overwritten when the watch face activates.

* movement: convert can_sleep an automatic variable

It is a simple boolean value and its scope is limited to the function.
There is no reason that I can think of for it to be a static variable.

* movement: fix unintended timeout short circuiting

Currently, movement drops time out events in case the previous loop
indicates that sleep is not possible due to short circuiting behavior
of logical and in C: if the left-hand side is false, the right hand
side is not evaluated at all, which means the loop is not called.
This was not intended to happen.

Fix it by storing the result in a second boolean variable
and working out the logic after the fact.

* faces: restore simple_clock_face

Restore the original simple clock face as requested.

---------

Signed-off-by: Matheus Afonso Martins Moreira <matheus.a.m.moreira@gmail.com>
Co-authored-by: Konrad Rieck <konrad@mlsec.org>
Co-authored-by: Per Waagø <perwaago@gmail.com>
Co-authored-by: Hugo Chargois <hugo.chargois@free.fr>
Co-authored-by: joeycastillo <joeycastillo@utexas.edu>
Co-authored-by: Jeremy O'Brien <neutral@fastmail.com>
Co-authored-by: Wesley Aptekar-Cassels <me@wesleyac.com>
Co-authored-by: madhogs <x3dh4vhf@duck.com>
Co-authored-by: LtKeks <LtKeks@users.noreply.github.com>
Co-authored-by: Ekaitz Zarraga <ekaitz@elenq.tech>
Co-authored-by: Brian Blakley <bblakley@gmail.com>
Co-authored-by: Christian Buschau <cbuschau@d00t.de>
Co-authored-by: Victor Graf <nategraf1@gmail.com>
Co-authored-by: Alex Utter <ooterness@gmail.com>
Co-authored-by: PrimmR <93214758+PrimmR@users.noreply.github.com>
Co-authored-by: Alex Maestas <git@se30.xyz>
Co-authored-by: Edward Shin <contact@edwardsh.in>
Co-authored-by: Pietro F. Maggi <pfm@pietromaggi.com>
Co-authored-by: CarpeNoctem <cryptomax@pm.me>
Co-authored-by: Wesley Ellis <tahnok@gmail.com>
Co-authored-by: Max Zettlmeißl <max@zettlmeissl.de>
Co-authored-by: madhogs <59648482+madhogs@users.noreply.github.com>
Co-authored-by: Matheus Afonso Martins Moreira <matheus.a.m.moreira@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

9 participants