Skip to content

Add FP-Grids app#454

Open
rjsmith wants to merge 28 commits intoATOVproject:mainfrom
rjsmith:feature/fp-grids2
Open

Add FP-Grids app#454
rjsmith wants to merge 28 commits intoATOVproject:mainfrom
rjsmith:feature/fp-grids2

Conversation

@rjsmith
Copy link
Collaborator

@rjsmith rjsmith commented Mar 1, 2026

A port of Emilie Gillet's renowned Mutable Instruments Grids topographic drum sequencer for the ATOV Faderpunk

@rjsmith rjsmith requested review from ArthurGibert and chmanie March 1, 2026 21:49
defmt-rtt = "1.0.0"
embedded-hal = "1.0.0"
embedded-hal-async = "1.0.0"
enum-ordinalize = "4.3.2"
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added this crate so I use code like this for array indexes:

[OutputMode::OutputModeDrums.ordinal() as usize]

In this case, there are only two modes, so could easily replace with constants if necessary


// Ported Random class from avrlib/random.h
#[derive(Debug, Clone, Copy)]
pub struct Random {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left the original Grids firmware random generator algo here. It also means the libfp code could directly use it cleanly, rather than somehow piping in multiple pre-rolled die values from the app code on each tick(), which is always going to be messy imho.

}

/// Scale from 4095 u16 to 255 u8
pub fn scale_bits_12_8(value: u16) -> u8 {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found this a useful utility function to have a few places.

enum-ordinalize = "4.3.2"
heapless = "0.7.17"
libm = "0.2.15"
log = { version = "0.4", default-features = false }
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found this solution to have logging in libfp code, otherwise I could see no way of logging or debugging it. https://github.com/rjsmith/faderpunk/wiki#logging-in-libfp


// App configuration visible to the configurator
pub static CONFIG: Config<PARAMS> = Config::new(
"FP Grids",
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure about using the original name "Grids" unqualified. Or even "FP Grids". See https://github.com/pichenettes/eurorack/tree/master?tab=readme-ov-file#guidelines-for-derivative-works

Maybe something like "Frids" (Faderpunk Grids) or "Griunk" (Grids Punk!) ?

output_mode = output_mode_glob.get();
reset_all_outputs(midi, leds, notes, &jack, &note_on_glob, &accent_on_glob).await;

generator.set_seed(die.roll());
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that this re-seeds the RNG in the pattern generator on every reset, meaning that it is not possible to re-create the same randomised sequence again after a reset / re-start. I think that's fine, it's supposed to be random.

let output_mode_ = output_mode_glob.get();
match output_mode_ {
OutputMode::OutputModeDrums => {
match chan {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This set of match rules could be refactored to reduce number of lines of code where there are commonalities between the channels, but imho it would make the readability of the code worse. This way, it's pretty clear whats going on in each channel. Certainly made it easy to reason about during development.


};

const LATCH_LAYER_DETECTION_MILLIS: u64 = 50;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't see any reason to run this shift detection loop at 1kHz like other apps do, in my tests, sampling every 50 milliseconds is undetectably different.

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 this pull request may close these issues.

1 participant