Clock features#498
Merged
tehn merged 3 commits intomonome:mainfrom Dec 17, 2025
Merged
Conversation
I needed this function to automatically switch between internal and external clock with a timeout system
Member
|
These all sound great, thank you! Will be able to check out the code soon.
b
…-------- Original Message --------
On Tuesday, 12/09/25 at 14:50 Evan Johnson ***@***.***> wrote:
Consider this as a draft.
I've added 3 features to the clock system. I'm happy to make changes, amend this PR to drop some of the features, or split this into multiple PRs. If you don't want these features, that's fine too.
For any features you do want to merge, I can also add the corresponding documentation to the [docs repo](https://github.com/monome/docs). I can also go through the steps to [make a release](https://github.com/monome/crow/blob/main/readme-development.md#making-a-release) if desired.
---------------------------------------------------------------
clock.sync offset capability
[e2c23ff](e2c23ff) adds an optional offset parameter to clock.sync(), which is intended to work exactly as it does on norns. The implementation closely follows the [norns implementation](https://github.com/monome/norns/blob/main/matron/src/clocks/clock_scheduler.c#L43).
I figure you're familiar with how this works, but let me know if you'd like me to elaborate on this feature.
---------------------------------------------------------------
clock.handlers.tempo_change user-defined handler
[ce0028b](ce0028b) adds a handler that is called when the clock tempo changes, clock.tempo_change_handler on norns. Since crow [modifies the clock metatable](https://github.com/monome/crow/blob/main/lua/clock.lua#L107) to prevent setting new indices, I took the approach of using the existing clock.transport table, but added a new key clock.handlers that points to this same table. We could simply have clock.transport.tempo_change to do away with the new handlers key. We could also set clock.tempo_change_handler to an empty function that would then always be called when the tempo changes, but this would allow the user to set clock.tempo_change_handler = function(tempo) ... end like on norns.
---------------------------------------------------------------
clock.time_since_last_input() to check when an external clock trigger was last received
[b661e39](b661e39) adds a function clock.time_since_last_input() which returns the time in seconds since a trigger was received at an input set to drive the clock by input[n].mode('clock', div). If no input has been set to drive the clock, it returns -1.
I wanted to make a script that could be externally clocked, but only if an input was actually receiving a clock. Because there is no "jack detection", the only way I could think to do this is with a timeout that switches back to being unclocked if no external clock is received for some amount of time. I could not figure out a way to access the time that the last external trigger was received, although it is tracked internally in the C layer. I simply added a getter for this value. This enables a "timeout" like this:
function
await_clock
()
input
[
2
].
mode
(
'
change
'
,
3
,
0.1
,
'
rising
'
)
input
[
2
].
change
=
function
()
input
[
2
].
mode
(
'
clock
'
,
1
/
4
)
print
(
'
clocked
'
)
clock_timeout
:
start
()
end
end
clock_timeout
=
metro
.
init
{
event
=
function
()
if
clock
.
time_since_last_input
()
>
4
then
--
4 second timeout
clock_timeout
:
stop
()
await_clock
()
unclocked
()
end
end
,
time
=
1.0
,
count
=
-
1
}
function
unclocked
()
print
(
'
unclocked
'
)
end
await_clock
()
---------------------------------------------------------------
Let me know if you have questions, concerns, or want changes!
---------------------------------------------------------------
You can view, comment on, or merge this pull request online at:
#498
Commit Summary
- [e2c23ff](e2c23ff) add clock.sync offset capability
- [ce0028b](ce0028b) add clock tempo change handler
- [b661e39](b661e39) add clock.time_since_last_input()
File Changes
([5 files](https://github.com/monome/crow/pull/498/files))
- M [lib/clock.c](https://github.com/monome/crow/pull/498/files#diff-64beeae0e4e18196d7f1560f5af389c09daeb90d4a43abadcb8ee98dc127e5d4) (18)
- M [lib/clock.h](https://github.com/monome/crow/pull/498/files#diff-9c401f126923e5100541606d40b39611ddea79046548d76e346663429cf91364) (3)
- M [lib/lualink.c](https://github.com/monome/crow/pull/498/files#diff-f839890deb13731dfcb83935794f5b27cee0bc158b1a34205b0b55b6a95b9577) (26)
- M [lib/lualink.h](https://github.com/monome/crow/pull/498/files#diff-43f4e97e6b452ba68e5fb35daaf01acc1692b505f5b856abeba3a3a8336e1977) (1)
- M [lua/clock.lua](https://github.com/monome/crow/pull/498/files#diff-5445d930217480ccf03ed95026b31fbb38f16691d77a1e872105f4fb36722a70) (8)
Patch Links:
- https://github.com/monome/crow/pull/498.patch
- https://github.com/monome/crow/pull/498.diff
—
Reply to this email directly, [view it on GitHub](#498), or [unsubscribe](https://github.com/notifications/unsubscribe-auth/AAB4I4FK6TICXD6QBHLLCPT4A4RXTAVCNFSM6AAAAACORDT5X6VHI2DSMVQWIX3LMV43ASLTON2WKOZTG4YTENBRGIZDCMI).
You are receiving this because you are subscribed to this thread.Message ID: ***@***.***>
|
Contributor
Author
|
I just realized I left an unneeded |
tehn
approved these changes
Dec 16, 2025
Member
tehn
left a comment
There was a problem hiding this comment.
this looks good to me. haven't tested on hardware.
maybe @trentgill will have a minute to glance at this, otherwise we can merge end of the week.
Collaborator
|
all looks good to me at a glance - i had no idea the won't have a chance to test this any time soon, but if @evnoj has done a good amount, then i'm happy to merge! thanks for the work here! |
This was referenced Apr 17, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Consider this as a draft.
I've added 3 features to the clock system. I'm happy to make changes, amend this PR to drop some of the features, or split this into multiple PRs. If you don't want these features, that's fine too.
For any features you do want to merge, I can also add the corresponding documentation to the docs repo. I can also go through the steps to make a release if desired.
clock.syncoffset capabilitye2c23ff adds an optional
offsetparameter toclock.sync(), which is intended to work exactly as it does on norns. The implementation closely follows the norns implementation.I figure you're familiar with how this works, but let me know if you'd like me to elaborate on this feature.
clock.handlers.tempo_changeuser-defined handlerce0028b adds a handler that is called when the clock tempo changes, like
clock.tempo_change_handleron norns. Since crow modifies theclockmetatable to prevent setting new indices, I took the approach of using the existingclock.transporttable, but added a new keyclock.handlersthat points to this same table. We could simply haveclock.transport.tempo_changeto do away with the newhandlerskey. We could also setclock.tempo_change_handlerto an empty function that would then always be called when the tempo changes, but this would allow the user to setclock.tempo_change_handler = function(tempo) ... endlike on norns.clock.time_since_last_input()to check when an external clock trigger was last receivedb661e39 adds a function
clock.time_since_last_input()which returns the time in seconds since a trigger was received at an input set to drive the clock byinput[n].mode('clock', div). If no input has been set to drive the clock, it returns -1.I wanted to make a script that could be externally clocked, but only if an input was actually receiving a clock. Because there is no "jack detection", the only way I could think to do this is with a timeout that switches back to being unclocked if no external clock is received for some amount of time. I could not figure out a way to access the time that the last external trigger was received, although it is tracked internally in the C layer. I simply added a getter for this value. This enables a "timeout" like this:
Let me know if you have questions, concerns, or want changes!