From a51a67674b93b0c4cf37326191df85cf8cf30483 Mon Sep 17 00:00:00 2001 From: needto Date: Sun, 1 Jul 2018 20:22:49 +0200 Subject: [PATCH 1/3] Add LFSR loop reset functionality to Quantermain --- software/o_c_REV/APP_QQ.ino | 23 +++++++++++++++++++++++ software/o_c_REV/util/util_turing.h | 16 ++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/software/o_c_REV/APP_QQ.ino b/software/o_c_REV/APP_QQ.ino index 85fa1ab9..837762bb 100644 --- a/software/o_c_REV/APP_QQ.ino +++ b/software/o_c_REV/APP_QQ.ino @@ -65,6 +65,7 @@ enum ChannelSetting { CHANNEL_SETTING_TURING_PROB_CV_SOURCE, CHANNEL_SETTING_TURING_MODULUS_CV_SOURCE, CHANNEL_SETTING_TURING_RANGE_CV_SOURCE, + CHANNEL_SETTING_TURING_RESET_TRIGGER, CHANNEL_SETTING_LOGISTIC_MAP_R, CHANNEL_SETTING_LOGISTIC_MAP_RANGE, CHANNEL_SETTING_LOGISTIC_MAP_R_CV_SOURCE, @@ -241,6 +242,10 @@ public: return values_[CHANNEL_SETTING_TURING_RANGE_CV_SOURCE]; } + ChannelTriggerSource get_turing_reset_trigger_source() const { + return static_cast(values_[CHANNEL_SETTING_TURING_RESET_TRIGGER]); + } + uint8_t get_logistic_map_r() const { return values_[CHANNEL_SETTING_LOGISTIC_MAP_R]; } @@ -383,6 +388,7 @@ public: last_sample_ = 0; clock_ = 0; int_seq_reset_ = false; + turing_reset_ = false; continuous_offset_ = false; schedule_mask_rotate_ = false; prev_octave_cv_ = 0; @@ -425,6 +431,11 @@ public: ChannelTriggerSource int_seq_reset_trigger_source = get_int_seq_reset_trigger_source() ; int_seq_reset_ = (triggers & DIGITAL_INPUT_MASK(int_seq_reset_trigger_source - 1)); } + + if (source == CHANNEL_SOURCE_TURING) { + ChannelTriggerSource turing_reset_trigger_source = get_turing_reset_trigger_source(); + turing_reset_ = (triggers & DIGITAL_INPUT_MASK(turing_reset_trigger_source - 1)); + } trigger_delay_.Update(); if (triggered) @@ -463,6 +474,12 @@ public: CONSTRAIN(probability, 0, 255); } turing_machine_.set_probability(probability); + + if (turing_reset_) { + turing_machine_.reset_loop(); + turing_reset_ = false; + } + if (triggered) { uint32_t shift_register = turing_machine_.Clock(); uint8_t range = get_turing_range(); @@ -954,7 +971,10 @@ public: *settings++ = CHANNEL_SETTING_TURING_PROB; if (OC::Scales::SCALE_NONE != get_scale(DUMMY)) *settings++ = CHANNEL_SETTING_TURING_RANGE_CV_SOURCE; + if (OC::Scales::SCALE_NONE != get_scale(DUMMY)) + *settings++ = CHANNEL_SETTING_TURING_MODULUS_CV_SOURCE; *settings++ = CHANNEL_SETTING_TURING_PROB_CV_SOURCE; + *settings++ = CHANNEL_SETTING_TURING_RESET_TRIGGER; break; case CHANNEL_SOURCE_LOGISTIC_MAP: *settings++ = CHANNEL_SETTING_LOGISTIC_MAP_R; @@ -1015,6 +1035,7 @@ public: case CHANNEL_SETTING_TURING_MODULUS_CV_SOURCE: case CHANNEL_SETTING_TURING_RANGE_CV_SOURCE: case CHANNEL_SETTING_TURING_PROB_CV_SOURCE: + case CHANNEL_SETTING_TURING_RESET_TRIGGER: case CHANNEL_SETTING_LOGISTIC_MAP_R: case CHANNEL_SETTING_LOGISTIC_MAP_RANGE: case CHANNEL_SETTING_LOGISTIC_MAP_R_CV_SOURCE: @@ -1062,6 +1083,7 @@ private: int32_t last_sample_; uint8_t clock_; bool int_seq_reset_; + bool turing_reset_; int8_t continuous_offset_; int8_t channel_index_; int32_t schedule_mask_rotate_; @@ -1130,6 +1152,7 @@ SETTINGS_DECLARE(QuantizerChannel, CHANNEL_SETTING_LAST) { { 0, 0, 4, "LFSR prb CV >", OC::Strings::cv_input_names_none, settings::STORAGE_TYPE_U4 }, { 0, 0, 4, "LFSR mod CV >", OC::Strings::cv_input_names_none, settings::STORAGE_TYPE_U4 }, { 0, 0, 4, "LFSR rng CV >", OC::Strings::cv_input_names_none, settings::STORAGE_TYPE_U4 }, + { 0, 0, 4, "LFSR reset", OC::Strings::trigger_input_names_none, settings::STORAGE_TYPE_U4 }, { 128, 1, 255, "Logistic r", NULL, settings::STORAGE_TYPE_U8 }, { 12, 1, 120, "Logistic range", NULL, settings::STORAGE_TYPE_U8 }, { 0, 0, 4, "Log r CV >", OC::Strings::cv_input_names_none, settings::STORAGE_TYPE_U4 }, diff --git a/software/o_c_REV/util/util_turing.h b/software/o_c_REV/util/util_turing.h index 6fc7b043..3161f441 100644 --- a/software/o_c_REV/util/util_turing.h +++ b/software/o_c_REV/util/util_turing.h @@ -38,10 +38,15 @@ class TuringShiftRegister { length_ = kDefaultLength; probability_ = kDefaultProbability; shift_register_ = 0xffffffff; + current_step_ = 0; } uint32_t Clock() { uint32_t shift_register = shift_register_; + + current_step_++; + if (current_step_ >= length_) + current_step_ = 0; // Toggle LSB; there might be better random options if (255 == probability_ || @@ -63,6 +68,16 @@ class TuringShiftRegister { return shift_register & ~(0xffffffff << length_); } + void reset_loop() { + uint32_t temp_buffer; + uint8_t bits_to_shift = length_ - current_step_; + + temp_buffer = (1 << bits_to_shift) - 1; + temp_buffer = (temp_buffer & shift_register_) << current_step_; + shift_register_ = (shift_register_ >> bits_to_shift) | temp_buffer; + current_step_ = 0; + } + void set_length(uint8_t length) { // hack... don't turn all zero ... if (length > length_) @@ -92,6 +107,7 @@ class TuringShiftRegister { uint8_t length_; uint8_t probability_; uint32_t shift_register_; + uint8_t current_step_; }; }; // namespace util From cd6cb4047bd11fe579055c7a5afbc714b524620b Mon Sep 17 00:00:00 2001 From: needto Date: Sun, 1 Jul 2018 20:22:49 +0200 Subject: [PATCH 2/3] Add LFSR loop reset functionality to Quantermain --- software/o_c_REV/APP_QQ.ino | 21 +++++++++++++++++++++ software/o_c_REV/util/util_turing.h | 16 ++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/software/o_c_REV/APP_QQ.ino b/software/o_c_REV/APP_QQ.ino index 85fa1ab9..95d72149 100644 --- a/software/o_c_REV/APP_QQ.ino +++ b/software/o_c_REV/APP_QQ.ino @@ -65,6 +65,7 @@ enum ChannelSetting { CHANNEL_SETTING_TURING_PROB_CV_SOURCE, CHANNEL_SETTING_TURING_MODULUS_CV_SOURCE, CHANNEL_SETTING_TURING_RANGE_CV_SOURCE, + CHANNEL_SETTING_TURING_RESET_TRIGGER, CHANNEL_SETTING_LOGISTIC_MAP_R, CHANNEL_SETTING_LOGISTIC_MAP_RANGE, CHANNEL_SETTING_LOGISTIC_MAP_R_CV_SOURCE, @@ -241,6 +242,10 @@ public: return values_[CHANNEL_SETTING_TURING_RANGE_CV_SOURCE]; } + ChannelTriggerSource get_turing_reset_trigger_source() const { + return static_cast(values_[CHANNEL_SETTING_TURING_RESET_TRIGGER]); + } + uint8_t get_logistic_map_r() const { return values_[CHANNEL_SETTING_LOGISTIC_MAP_R]; } @@ -383,6 +388,7 @@ public: last_sample_ = 0; clock_ = 0; int_seq_reset_ = false; + turing_reset_ = false; continuous_offset_ = false; schedule_mask_rotate_ = false; prev_octave_cv_ = 0; @@ -425,6 +431,11 @@ public: ChannelTriggerSource int_seq_reset_trigger_source = get_int_seq_reset_trigger_source() ; int_seq_reset_ = (triggers & DIGITAL_INPUT_MASK(int_seq_reset_trigger_source - 1)); } + + if (source == CHANNEL_SOURCE_TURING) { + ChannelTriggerSource turing_reset_trigger_source = get_turing_reset_trigger_source(); + turing_reset_ = (triggers & DIGITAL_INPUT_MASK(turing_reset_trigger_source - 1)); + } trigger_delay_.Update(); if (triggered) @@ -463,6 +474,12 @@ public: CONSTRAIN(probability, 0, 255); } turing_machine_.set_probability(probability); + + if (turing_reset_) { + turing_machine_.reset_loop(); + turing_reset_ = false; + } + if (triggered) { uint32_t shift_register = turing_machine_.Clock(); uint8_t range = get_turing_range(); @@ -955,6 +972,7 @@ public: if (OC::Scales::SCALE_NONE != get_scale(DUMMY)) *settings++ = CHANNEL_SETTING_TURING_RANGE_CV_SOURCE; *settings++ = CHANNEL_SETTING_TURING_PROB_CV_SOURCE; + *settings++ = CHANNEL_SETTING_TURING_RESET_TRIGGER; break; case CHANNEL_SOURCE_LOGISTIC_MAP: *settings++ = CHANNEL_SETTING_LOGISTIC_MAP_R; @@ -1015,6 +1033,7 @@ public: case CHANNEL_SETTING_TURING_MODULUS_CV_SOURCE: case CHANNEL_SETTING_TURING_RANGE_CV_SOURCE: case CHANNEL_SETTING_TURING_PROB_CV_SOURCE: + case CHANNEL_SETTING_TURING_RESET_TRIGGER: case CHANNEL_SETTING_LOGISTIC_MAP_R: case CHANNEL_SETTING_LOGISTIC_MAP_RANGE: case CHANNEL_SETTING_LOGISTIC_MAP_R_CV_SOURCE: @@ -1062,6 +1081,7 @@ private: int32_t last_sample_; uint8_t clock_; bool int_seq_reset_; + bool turing_reset_; int8_t continuous_offset_; int8_t channel_index_; int32_t schedule_mask_rotate_; @@ -1130,6 +1150,7 @@ SETTINGS_DECLARE(QuantizerChannel, CHANNEL_SETTING_LAST) { { 0, 0, 4, "LFSR prb CV >", OC::Strings::cv_input_names_none, settings::STORAGE_TYPE_U4 }, { 0, 0, 4, "LFSR mod CV >", OC::Strings::cv_input_names_none, settings::STORAGE_TYPE_U4 }, { 0, 0, 4, "LFSR rng CV >", OC::Strings::cv_input_names_none, settings::STORAGE_TYPE_U4 }, + { 0, 0, 4, "LFSR reset", OC::Strings::trigger_input_names_none, settings::STORAGE_TYPE_U4 }, { 128, 1, 255, "Logistic r", NULL, settings::STORAGE_TYPE_U8 }, { 12, 1, 120, "Logistic range", NULL, settings::STORAGE_TYPE_U8 }, { 0, 0, 4, "Log r CV >", OC::Strings::cv_input_names_none, settings::STORAGE_TYPE_U4 }, diff --git a/software/o_c_REV/util/util_turing.h b/software/o_c_REV/util/util_turing.h index 6fc7b043..3161f441 100644 --- a/software/o_c_REV/util/util_turing.h +++ b/software/o_c_REV/util/util_turing.h @@ -38,10 +38,15 @@ class TuringShiftRegister { length_ = kDefaultLength; probability_ = kDefaultProbability; shift_register_ = 0xffffffff; + current_step_ = 0; } uint32_t Clock() { uint32_t shift_register = shift_register_; + + current_step_++; + if (current_step_ >= length_) + current_step_ = 0; // Toggle LSB; there might be better random options if (255 == probability_ || @@ -63,6 +68,16 @@ class TuringShiftRegister { return shift_register & ~(0xffffffff << length_); } + void reset_loop() { + uint32_t temp_buffer; + uint8_t bits_to_shift = length_ - current_step_; + + temp_buffer = (1 << bits_to_shift) - 1; + temp_buffer = (temp_buffer & shift_register_) << current_step_; + shift_register_ = (shift_register_ >> bits_to_shift) | temp_buffer; + current_step_ = 0; + } + void set_length(uint8_t length) { // hack... don't turn all zero ... if (length > length_) @@ -92,6 +107,7 @@ class TuringShiftRegister { uint8_t length_; uint8_t probability_; uint32_t shift_register_; + uint8_t current_step_; }; }; // namespace util From 3f9f5b4a2290d379d5f2a04e48d0d08a74a669ca Mon Sep 17 00:00:00 2001 From: needto Date: Sun, 10 May 2020 00:49:20 +0200 Subject: [PATCH 3/3] Fast forward to buffer end on reset --- software/o_c_REV/util/util_turing.h | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/software/o_c_REV/util/util_turing.h b/software/o_c_REV/util/util_turing.h index 3161f441..ea9712f5 100644 --- a/software/o_c_REV/util/util_turing.h +++ b/software/o_c_REV/util/util_turing.h @@ -69,13 +69,22 @@ class TuringShiftRegister { } void reset_loop() { - uint32_t temp_buffer; - uint8_t bits_to_shift = length_ - current_step_; + uint8_t bits_to_shift = length_ - current_step_ - 1; - temp_buffer = (1 << bits_to_shift) - 1; - temp_buffer = (temp_buffer & shift_register_) << current_step_; - shift_register_ = (shift_register_ >> bits_to_shift) | temp_buffer; - current_step_ = 0; + uint8_t probability_backup = probability_; + + // scale down probability temporarily to avoid increased randomness when using resets + // we need to scale relative to 50% probability to keep the behavior for values over 50% + if (probability_ < 128) + probability_ = probability_ / bits_to_shift; + else if (probability_ > 128) + probability_ = 255 - (255 - probability_) / bits_to_shift; + + for (uint8_t i = 0; i < bits_to_shift; i++) { + Clock(); + } + + probability_ = probability_backup; } void set_length(uint8_t length) {