From 1a3d630c67b87e8021c3fcaaf9dfd2d51168abd1 Mon Sep 17 00:00:00 2001 From: mxmxmx Date: Wed, 4 Apr 2018 10:05:42 +0200 Subject: [PATCH 01/14] [DQ] missing break --- software/o_c_REV/APP_DQ.ino | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/software/o_c_REV/APP_DQ.ino b/software/o_c_REV/APP_DQ.ino index e5749a13..7d31cc7b 100644 --- a/software/o_c_REV/APP_DQ.ino +++ b/software/o_c_REV/APP_DQ.ino @@ -1386,10 +1386,11 @@ void DQ_handleEncoderEvent(const UI::Event &event) { selected.update_enabled_settings(); dq_state.cursor.AdjustEnd(selected.num_enabled_settings() - 1); break; - case DQ_CHANNEL_SETTING_SCALE_SEQ: + case DQ_CHANNEL_SETTING_SCALE_SEQ: selected.update_enabled_settings(); dq_state.cursor.AdjustEnd(selected.num_enabled_settings() - 1); selected.reset_scale(); + break; default: break; } From fbb8f9cd91c0981905031b23bdbc1609a3bc909f Mon Sep 17 00:00:00 2001 From: mxmxmx Date: Wed, 4 Apr 2018 12:35:27 +0200 Subject: [PATCH 02/14] [DQ] update --- software/o_c_REV/APP_DQ.ino | 35 ++++++++++++++++++++--------------- software/o_c_REV/OC_version.h | 2 +- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/software/o_c_REV/APP_DQ.ino b/software/o_c_REV/APP_DQ.ino index 7d31cc7b..610ac2d2 100644 --- a/software/o_c_REV/APP_DQ.ino +++ b/software/o_c_REV/APP_DQ.ino @@ -446,12 +446,12 @@ public: // manual change? scale_reset_ = false; active_scale_slot_ = get_scale_select(); - prev_scale_slot_ = active_scale_slot_; + prev_scale_slot_ = display_scale_slot_ = active_scale_slot_; } } else if (prev_scale_slot_ != get_scale_select()) { active_scale_slot_ = get_scale_select(); - prev_scale_slot_ = active_scale_slot_; + prev_scale_slot_ = display_scale_slot_ = active_scale_slot_; } if (scale_advance_) { @@ -465,9 +465,6 @@ public: } bool update = continuous || triggered; - - if (update) - update_scale(force_update_, active_scale_slot_, schedule_mask_rotate_); int32_t sample = last_sample_; int32_t temp_sample = 0; @@ -513,8 +510,8 @@ public: root += (OC::ADC::value(static_cast(channel_id)) + 127) >> 8; break; case DQ_DEST_MASK: - update_scale(true, active_scale_slot_, (OC::ADC::value(static_cast(channel_id)) + 127) >> 8); - schedule_scale_update_ = false; + schedule_mask_rotate_ = (OC::ADC::value(static_cast(channel_id)) + 127) >> 8; + schedule_scale_update_ = true; break; case DQ_DEST_OCTAVE: octave += (OC::ADC::value(static_cast(channel_id)) + 255) >> 9; @@ -533,6 +530,10 @@ public: CONSTRAIN(root, 0, 11); CONSTRAIN(transpose, -12, 12); + // update scale? + if (update || schedule_scale_update_) + update_scale(force_update_, active_scale_slot_, schedule_mask_rotate_); + // internal CV source? if (source > DQ_CHANNEL_SOURCE_CV4) cv_source = channel_id - 1; @@ -598,11 +599,6 @@ public: // special treatment, continuous update -- only update the modulation values if/when the quantized input changes: bool _continuous_update = continuous && last_sample_ != sample; - - if ((!continuous && schedule_scale_update_) || (_continuous_update && schedule_scale_update_)) { - update_scale(true, display_scale_slot_, schedule_mask_rotate_); - schedule_scale_update_ = false; - } if (_continuous_update) { @@ -656,13 +652,19 @@ public: break; case DQ_DEST_MASK: schedule_mask_rotate_ = (OC::ADC::value(static_cast(channel_id)) + 127) >> 8; - update_scale(force_update_, active_scale_slot_, schedule_mask_rotate_); + schedule_scale_update_ = true; break; default: break; } // end switch + // update scale? + if (schedule_scale_update_ && _continuous_update) { + update_scale(false, display_scale_slot_, schedule_mask_rotate_); + schedule_scale_update_ = false; + } + // offset when TR source = continuous ? int8_t _trigger_offset = 0; bool _trigger_update = false; @@ -1167,8 +1169,10 @@ size_t DQ_restore(const void *storage) { size_t used = 0; for (size_t i = 0; i < NUMCHANNELS; ++i) { used += dq_quantizer_channels[i].Restore(static_cast(storage) + used); - int scale = dq_quantizer_channels[i].get_scale_select(); - dq_quantizer_channels[i].update_scale_mask(dq_quantizer_channels[i].get_mask(scale), scale); + //int scale = dq_quantizer_channels[i].get_scale_select(); + for (size_t j = SLOT1; j < LAST_SLOT; j++) { + dq_quantizer_channels[i].update_scale_mask(dq_quantizer_channels[i].get_mask(j), j); + } dq_quantizer_channels[i].update_enabled_settings(); } dq_state.cursor.AdjustEnd(dq_quantizer_channels[0].num_enabled_settings() - 1); @@ -1348,6 +1352,7 @@ void DQ_handleEncoderEvent(const UI::Event &event) { DQ_QuantizerChannel &selected = dq_quantizer_channels[dq_state.selected_channel]; if (dq_state.editing()) { + DQ_ChannelSetting setting = selected.enabled_setting_at(dq_state.cursor_pos()); if (DQ_CHANNEL_SETTING_MASK1 != setting || DQ_CHANNEL_SETTING_MASK2 != setting || DQ_CHANNEL_SETTING_MASK3 != setting || DQ_CHANNEL_SETTING_MASK4 != setting) { diff --git a/software/o_c_REV/OC_version.h b/software/o_c_REV/OC_version.h index 2a7577a8..50fc2578 100644 --- a/software/o_c_REV/OC_version.h +++ b/software/o_c_REV/OC_version.h @@ -3,5 +3,5 @@ // // GENERATED FILE, DO NOT EDIT // -#define OC_VERSION "v1.3.4" +#define OC_VERSION "v1.3.5b" #endif From 592d59c904bd94e5564c96c1a2b4e3f13a6d3bf3 Mon Sep 17 00:00:00 2001 From: mxmxmx Date: Wed, 4 Apr 2018 12:45:59 +0200 Subject: [PATCH 03/14] [DQ] update --- software/o_c_REV/APP_DQ.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/software/o_c_REV/APP_DQ.ino b/software/o_c_REV/APP_DQ.ino index 610ac2d2..8353c19e 100644 --- a/software/o_c_REV/APP_DQ.ino +++ b/software/o_c_REV/APP_DQ.ino @@ -532,7 +532,7 @@ public: // update scale? if (update || schedule_scale_update_) - update_scale(force_update_, active_scale_slot_, schedule_mask_rotate_); + update_scale(force_update_, display_scale_slot_, schedule_mask_rotate_); // internal CV source? if (source > DQ_CHANNEL_SOURCE_CV4) From ef36e816804c1225a47083e32c5e035ab36ee37d Mon Sep 17 00:00:00 2001 From: mxmxmx Date: Wed, 4 Apr 2018 12:55:15 +0200 Subject: [PATCH 04/14] [DQ] update --- software/o_c_REV/APP_DQ.ino | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/software/o_c_REV/APP_DQ.ino b/software/o_c_REV/APP_DQ.ino index 8353c19e..08deac0d 100644 --- a/software/o_c_REV/APP_DQ.ino +++ b/software/o_c_REV/APP_DQ.ino @@ -504,14 +504,12 @@ public: // if scale changes, we have to update the root and transpose values, too; mask gets updated in update_scale root = get_root(display_scale_slot_); transpose = get_transpose(display_scale_slot_); - schedule_scale_update_ = true; break; case DQ_DEST_ROOT: root += (OC::ADC::value(static_cast(channel_id)) + 127) >> 8; break; case DQ_DEST_MASK: schedule_mask_rotate_ = (OC::ADC::value(static_cast(channel_id)) + 127) >> 8; - schedule_scale_update_ = true; break; case DQ_DEST_OCTAVE: octave += (OC::ADC::value(static_cast(channel_id)) + 255) >> 9; @@ -531,8 +529,7 @@ public: CONSTRAIN(transpose, -12, 12); // update scale? - if (update || schedule_scale_update_) - update_scale(force_update_, display_scale_slot_, schedule_mask_rotate_); + update_scale(force_update_, display_scale_slot_, schedule_mask_rotate_); // internal CV source? if (source > DQ_CHANNEL_SOURCE_CV4) From 93e5915c7c6821642046aea3fec820658d84a073 Mon Sep 17 00:00:00 2001 From: mxmxmx Date: Mon, 16 Apr 2018 11:57:23 +0200 Subject: [PATCH 05/14] [SEQ] add root / CV --- software/o_c_REV/APP_A_SEQ.ino | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/software/o_c_REV/APP_A_SEQ.ino b/software/o_c_REV/APP_A_SEQ.ino index c6374308..38efcd5c 100644 --- a/software/o_c_REV/APP_A_SEQ.ino +++ b/software/o_c_REV/APP_A_SEQ.ino @@ -133,6 +133,7 @@ enum SEQ_ChannelSetting { // SEQ_CHANNEL_SETTING_SCALE, SEQ_CHANNEL_SETTING_OCTAVE, + SEQ_CHANNEL_SETTING_ROOT, SEQ_CHANNEL_SETTING_OCTAVE_AUX, SEQ_CHANNEL_SETTING_SCALE_MASK, // @@ -156,6 +157,7 @@ enum SEQ_ChannelSetting { SEQ_CHANNEL_SETTING_TRANSPOSE_CV_SOURCE, SEQ_CHANNEL_SETTING_PULSEWIDTH_CV_SOURCE, SEQ_CHANNEL_SETTING_OCTAVE_CV_SOURCE, + SEQ_CHANNEL_SETTING_ROOT_CV_SOURCE, SEQ_CHANNEL_SETTING_OCTAVE_AUX_CV_SOURCE, SEQ_CHANNEL_SETTING_SEQ_CV_SOURCE, SEQ_CHANNEL_SETTING_SCALE_MASK_CV_SOURCE, @@ -300,7 +302,7 @@ public: } uint8_t get_root(uint8_t DUMMY) const { - return 0x0; // dummy + return values_[SEQ_CHANNEL_SETTING_ROOT]; } uint8_t get_clock_source() const { @@ -445,6 +447,10 @@ public: return values_[SEQ_CHANNEL_SETTING_OCTAVE_CV_SOURCE]; } + uint8_t get_root_cv_source() const { + return values_[SEQ_CHANNEL_SETTING_ROOT_CV_SOURCE]; + } + uint8_t get_octave_aux_cv_source() const { return values_[SEQ_CHANNEL_SETTING_OCTAVE_AUX_CV_SOURCE]; } @@ -692,6 +698,7 @@ public: apply_value(SEQ_CHANNEL_SETTING_PULSEWIDTH_CV_SOURCE, 0); apply_value(SEQ_CHANNEL_SETTING_MULT_CV_SOURCE, 0); apply_value(SEQ_CHANNEL_SETTING_OCTAVE_CV_SOURCE, 0); + apply_value(SEQ_CHANNEL_SETTING_ROOT_CV_SOURCE, 0); apply_value(SEQ_CHANNEL_SETTING_OCTAVE_AUX_CV_SOURCE, 0); apply_value(SEQ_CHANNEL_SETTING_SEQ_CV_SOURCE, 0); apply_value(SEQ_CHANNEL_SETTING_SCALE_MASK_CV_SOURCE, 0); @@ -1062,6 +1069,12 @@ public: CONSTRAIN(_transpose, -12, 12); } + int8_t _root = get_root(0x0); + if (get_root_cv_source()) { + _root += (OC::ADC::value(static_cast(get_root_cv_source() - 1)) + 127) >> 8; + CONSTRAIN(_root, 0, 11); + } + if (_playmode != PM_ARP) { // use the current sequence, updated in process_num_seq_channel(): step_pitch_ = get_pitch_at_step(display_num_sequence_, clk_cnt_) + (_octave * 12 << 7); @@ -1088,7 +1101,7 @@ public: gate_state_ = step_state_ = OFF; } // update output: - step_pitch_ = quantizer_.Process(step_pitch_, 0, _transpose); + step_pitch_ = quantizer_.Process(step_pitch_, _root << 7, _transpose); int32_t _attack = get_attack_duration(); int32_t _decay = get_decay_duration(); @@ -1144,7 +1157,7 @@ public: else // this *might* not be quite a copy... step_pitch_aux_ = step_pitch_ + (_octave_aux * 12 << 7); - step_pitch_aux_ = quantizer_.Process(step_pitch_aux_, 0, _transpose); + step_pitch_aux_ = quantizer_.Process(step_pitch_aux_, _root << 7, _transpose); } break; case ENV_AD: @@ -1665,7 +1678,8 @@ public: else *settings++ = SEQ_CHANNEL_SETTING_SEQUENCE_PLAYMODE_CV_RANGES; - *settings++ = SEQ_CHANNEL_SETTING_OCTAVE; + *settings++ = SEQ_CHANNEL_SETTING_OCTAVE; + *settings++ = SEQ_CHANNEL_SETTING_ROOT; // aux output: *settings++ = SEQ_CHANNEL_SETTING_MODE; @@ -1759,7 +1773,8 @@ public: else *settings++ = SEQ_CHANNEL_SETTING_DUMMY; // = range - *settings++ = SEQ_CHANNEL_SETTING_OCTAVE_CV_SOURCE; + *settings++ = SEQ_CHANNEL_SETTING_OCTAVE_CV_SOURCE; + *settings++ = SEQ_CHANNEL_SETTING_ROOT_CV_SOURCE; *settings++ = SEQ_CHANNEL_SETTING_DUMMY; // = mode switch (get_aux_mode()) { @@ -1957,6 +1972,7 @@ SETTINGS_DECLARE(SEQ_Channel, SEQ_CHANNEL_SETTING_LAST) { // { OC::Scales::SCALE_SEMI, 0, OC::Scales::NUM_SCALES - 1, "scale", OC::scale_names_short, settings::STORAGE_TYPE_U8 }, { 0, -5, 5, "octave", NULL, settings::STORAGE_TYPE_I8 }, // octave + { 0, 0, 11, "root", OC::Strings::note_names_unpadded, settings::STORAGE_TYPE_U8 }, { 0, -5, 5, "--> aux +/-", NULL, settings::STORAGE_TYPE_I8 }, // aux octave { 65535, 1, 65535, "--> edit", NULL, settings::STORAGE_TYPE_U16 }, // mask // seq @@ -1979,8 +1995,9 @@ SETTINGS_DECLARE(SEQ_Channel, SEQ_CHANNEL_SETTING_LAST) { { 0, 0, 4, "mult/div CV ->", OC::Strings::cv_input_names_none, settings::STORAGE_TYPE_U4 }, { 0, 0, 4, "transpose ->", OC::Strings::cv_input_names_none, settings::STORAGE_TYPE_U4 }, { 0, 0, 4, "--> pw ->", OC::Strings::cv_input_names_none, settings::STORAGE_TYPE_U4 }, - { 0, 0, 4, "octave -/+ ->", OC::Strings::cv_input_names_none, settings::STORAGE_TYPE_U4 }, - { 0, 0, 4, "--> aux -/+ ->", OC::Strings::cv_input_names_none, settings::STORAGE_TYPE_U4 }, + { 0, 0, 4, "octave +/- ->", OC::Strings::cv_input_names_none, settings::STORAGE_TYPE_U4 }, + { 0, 0, 4, "root +/- ->", OC::Strings::cv_input_names_none, settings::STORAGE_TYPE_U4 }, + { 0, 0, 4, "--> aux +/- ->", OC::Strings::cv_input_names_none, settings::STORAGE_TYPE_U4 }, { 0, 0, 4, "sequence # ->", OC::Strings::cv_input_names_none, settings::STORAGE_TYPE_U4 }, { 0, 0, 4, "mask rotate ->", OC::Strings::cv_input_names_none, settings::STORAGE_TYPE_U4 }, { 0, 0, 4, "direction ->", OC::Strings::cv_input_names_none, settings::STORAGE_TYPE_U4 }, From 31af7e459e1c44b60d7f7b64fae0951b68a7c64e Mon Sep 17 00:00:00 2001 From: mxmxmx Date: Fri, 15 Jun 2018 08:15:34 +0200 Subject: [PATCH 06/14] [OC] 10V i/o --- software/o_c_REV/OC_autotuner.h | 2 +- software/o_c_REV/OC_calibration.ino | 6 +++--- software/o_c_REV/OC_options.h | 6 ++++++ software/o_c_REV/OC_ui.cpp | 2 +- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/software/o_c_REV/OC_autotuner.h b/software/o_c_REV/OC_autotuner.h index 543817a4..a26a4c00 100644 --- a/software/o_c_REV/OC_autotuner.h +++ b/software/o_c_REV/OC_autotuner.h @@ -4,7 +4,7 @@ #include "OC_autotune.h" #include "OC_options.h" -#ifdef BUCHLA_4U +#if defined(BUCHLA_4U) && !defined(IO_10V) const char* const AT_steps[] = { "0.0V", "1.2V", "2.4V", "3.6V", "4.8V", "6.0V", "7.2V", "8.4V", "9.6V", "10.8V", " " }; diff --git a/software/o_c_REV/OC_calibration.ino b/software/o_c_REV/OC_calibration.ino index 6bf7f843..6de97061 100644 --- a/software/o_c_REV/OC_calibration.ino +++ b/software/o_c_REV/OC_calibration.ino @@ -33,7 +33,7 @@ bool calibration_data_loaded = false; const OC::CalibrationData kCalibrationDefaults = { // DAC { { - #ifdef BUCHLA_cOC + #ifdef BUCHLA_cOC {197, 6634, 13083, 19517, 25966, 32417, 38850, 45301, 51733, 58180, 64400}, {197, 6634, 13083, 19517, 25966, 32417, 38850, 45301, 51733, 58180, 64400}, {197, 6634, 13083, 19517, 25966, 32417, 38850, 45301, 51733, 58180, 64400}, @@ -178,7 +178,7 @@ const CalibrationStep calibration_steps[CALIBRATION_STEP_LAST] = { { HELLO, "O&C Calibration", "Use defaults? ", select_help, start_footer, CALIBRATE_NONE, 0, OC::Strings::no_yes, 0, 1 }, { CENTER_DISPLAY, "Center Display", "Pixel offset ", default_help_r, default_footer, CALIBRATE_DISPLAY, 0, nullptr, 0, 2 }, - #ifdef BUCHLA_4U + #if defined(BUCHLA_4U) && !defined(IO_10V) { DAC_A_VOLT_3m, "DAC A 0.0 volts", "-> 0.000V ", default_help_r, default_footer, CALIBRATE_OCTAVE, 0, nullptr, 0, DAC::MAX_VALUE }, { DAC_A_VOLT_2m, "DAC A 1.2 volts", "-> 1.200V ", default_help_r, default_footer, CALIBRATE_OCTAVE, 1, nullptr, 0, DAC::MAX_VALUE }, { DAC_A_VOLT_1m, "DAC A 2.4 volts", "-> 2.400V ", default_help_r, default_footer, CALIBRATE_OCTAVE, 2, nullptr, 0, DAC::MAX_VALUE }, @@ -273,7 +273,7 @@ const CalibrationStep calibration_steps[CALIBRATION_STEP_LAST] = { { CV_OFFSET_2, "ADC CV3", "ADC value at 0V", default_help_r, default_footer, CALIBRATE_ADC_OFFSET, ADC_CHANNEL_3, nullptr, 0, 4095 }, { CV_OFFSET_3, "ADC CV4", "ADC value at 0V", default_help_r, default_footer, CALIBRATE_ADC_OFFSET, ADC_CHANNEL_4, nullptr, 0, 4095 }, - #ifdef BUCHLA_4U + #if defined(BUCHLA_4U) && !defined(IO_10V) { ADC_PITCH_C2, "ADC cal. octave #1", "CV1: Input 1.2V", "[R] Long press to set", default_footer, CALIBRATE_ADC_1V, 0, nullptr, 0, 0 }, { ADC_PITCH_C4, "ADC cal. octave #3", "CV1: Input 3.6V", "[R] Long press to set", default_footer, CALIBRATE_ADC_3V, 0, nullptr, 0, 0 }, #else diff --git a/software/o_c_REV/OC_options.h b/software/o_c_REV/OC_options.h index 28357a43..0775f640 100644 --- a/software/o_c_REV/OC_options.h +++ b/software/o_c_REV/OC_options.h @@ -23,6 +23,12 @@ //#define INVERT_DISPLAY /* ------------ use DAC8564 ------------------------------------------------------------------------- */ //#define DAC8564 +/* ------------ 0 / 10V range ----------------------------------------------------------------------- */ +//#define IO_10V + +#if defined(IO_10V) + #define BUCHLA_4U +#endif #endif diff --git a/software/o_c_REV/OC_ui.cpp b/software/o_c_REV/OC_ui.cpp index aaa624dd..bb405fd1 100644 --- a/software/o_c_REV/OC_ui.cpp +++ b/software/o_c_REV/OC_ui.cpp @@ -156,7 +156,7 @@ UiMode Ui::Splashscreen(bool &reset_settings) { mode = UI_MODE_APP_SETTINGS; reset_settings = - #ifdef BUCHLA_4U + #if defined(BUCHLA_4U) && !defined(IO_10V) read_immediate(CONTROL_BUTTON_UP) && read_immediate(CONTROL_BUTTON_R); #else read_immediate(CONTROL_BUTTON_UP) && read_immediate(CONTROL_BUTTON_DOWN); From ed6d701389cd4b8581dc4d3a97738d1f38ff1b1f Mon Sep 17 00:00:00 2001 From: mxmxmx Date: Fri, 15 Jun 2018 08:42:17 +0200 Subject: [PATCH 07/14] [OC] 10V i/o --- software/o_c_REV/OC_autotuner.h | 4 +++ software/o_c_REV/OC_calibration.ino | 44 +++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/software/o_c_REV/OC_autotuner.h b/software/o_c_REV/OC_autotuner.h index a26a4c00..dd33d780 100644 --- a/software/o_c_REV/OC_autotuner.h +++ b/software/o_c_REV/OC_autotuner.h @@ -8,6 +8,10 @@ const char* const AT_steps[] = { "0.0V", "1.2V", "2.4V", "3.6V", "4.8V", "6.0V", "7.2V", "8.4V", "9.6V", "10.8V", " " }; +#elif defined(IO_10V) +const char* const AT_steps[] = { + "0.0V", "1.0V", "2.0V", "3.0V", "4.0V", "5.0V", "6.0V", "7.0V", "8.0V", "9.0V", " " +}; #else const char* const AT_steps[] = { "-3V", "-2V", "-1V", " 0V", "+1V", "+2V", "+3V", "+4V", "+5V", "+6V", " " diff --git a/software/o_c_REV/OC_calibration.ino b/software/o_c_REV/OC_calibration.ino index 6de97061..ad7a8ad3 100644 --- a/software/o_c_REV/OC_calibration.ino +++ b/software/o_c_REV/OC_calibration.ino @@ -222,6 +222,50 @@ const CalibrationStep calibration_steps[CALIBRATION_STEP_LAST] = { { DAC_D_VOLT_4, "DAC D 8.4 volts", "-> 8.400V ", default_help_r, default_footer, CALIBRATE_OCTAVE, 7, nullptr, 0, DAC::MAX_VALUE }, { DAC_D_VOLT_5, "DAC D 9.6 volts", "-> 9.600V ", default_help_r, default_footer, CALIBRATE_OCTAVE, 8, nullptr, 0, DAC::MAX_VALUE }, { DAC_D_VOLT_6, "DAC D 10.8 volts", "-> 10.800V ", default_help_r, default_footer, CALIBRATE_OCTAVE, 9, nullptr, 0, DAC::MAX_VALUE }, + #elif defined(IO_10V) + { DAC_A_VOLT_3m, "DAC A 0.0 volts", "-> 0.000V ", default_help_r, default_footer, CALIBRATE_OCTAVE, 0, nullptr, 0, DAC::MAX_VALUE }, + { DAC_A_VOLT_2m, "DAC A 1.0 volts", "-> 1.000V ", default_help_r, default_footer, CALIBRATE_OCTAVE, 1, nullptr, 0, DAC::MAX_VALUE }, + { DAC_A_VOLT_1m, "DAC A 2.0 volts", "-> 2.000V ", default_help_r, default_footer, CALIBRATE_OCTAVE, 2, nullptr, 0, DAC::MAX_VALUE }, + { DAC_A_VOLT_0, "DAC A 3.0 volts", "-> 3.000V ", default_help_r, default_footer, CALIBRATE_OCTAVE, 3, nullptr, 0, DAC::MAX_VALUE }, + { DAC_A_VOLT_1, "DAC A 4.0 volts", "-> 4.000V ", default_help_r, default_footer, CALIBRATE_OCTAVE, 4, nullptr, 0, DAC::MAX_VALUE }, + { DAC_A_VOLT_2, "DAC A 5.0 volts", "-> 5.000V ", default_help_r, default_footer, CALIBRATE_OCTAVE, 5, nullptr, 0, DAC::MAX_VALUE }, + { DAC_A_VOLT_3, "DAC A 6.0 volts", "-> 6.000V ", default_help_r, default_footer, CALIBRATE_OCTAVE, 6, nullptr, 0, DAC::MAX_VALUE }, + { DAC_A_VOLT_4, "DAC A 7.0 volts", "-> 7.000V ", default_help_r, default_footer, CALIBRATE_OCTAVE, 7, nullptr, 0, DAC::MAX_VALUE }, + { DAC_A_VOLT_5, "DAC A 8.0 volts", "-> 8.000V ", default_help_r, default_footer, CALIBRATE_OCTAVE, 8, nullptr, 0, DAC::MAX_VALUE }, + { DAC_A_VOLT_6, "DAC A 9.0 volts", "-> 9.000V ", default_help_r, default_footer, CALIBRATE_OCTAVE, 9, nullptr, 0, DAC::MAX_VALUE }, + + { DAC_B_VOLT_3m, "DAC B 0.0 volts", "-> 0.000V ", default_help_r, default_footer, CALIBRATE_OCTAVE, 0, nullptr, 0, DAC::MAX_VALUE }, + { DAC_B_VOLT_2m, "DAC B 1.0 volts", "-> 1.000V ", default_help_r, default_footer, CALIBRATE_OCTAVE, 1, nullptr, 0, DAC::MAX_VALUE }, + { DAC_B_VOLT_1m, "DAC B 2.0 volts", "-> 2.000V ", default_help_r, default_footer, CALIBRATE_OCTAVE, 2, nullptr, 0, DAC::MAX_VALUE }, + { DAC_B_VOLT_0, "DAC B 3.0 volts", "-> 3.000V ", default_help_r, default_footer, CALIBRATE_OCTAVE, 3, nullptr, 0, DAC::MAX_VALUE }, + { DAC_B_VOLT_1, "DAC B 4.0 volts", "-> 4.000V ", default_help_r, default_footer, CALIBRATE_OCTAVE, 4, nullptr, 0, DAC::MAX_VALUE }, + { DAC_B_VOLT_2, "DAC B 5.0 volts", "-> 5.000V ", default_help_r, default_footer, CALIBRATE_OCTAVE, 5, nullptr, 0, DAC::MAX_VALUE }, + { DAC_B_VOLT_3, "DAC B 6.0 volts", "-> 6.000V ", default_help_r, default_footer, CALIBRATE_OCTAVE, 6, nullptr, 0, DAC::MAX_VALUE }, + { DAC_B_VOLT_4, "DAC B 7.0 volts", "-> 7.000V ", default_help_r, default_footer, CALIBRATE_OCTAVE, 7, nullptr, 0, DAC::MAX_VALUE }, + { DAC_B_VOLT_5, "DAC B 8.0 volts", "-> 8.000V ", default_help_r, default_footer, CALIBRATE_OCTAVE, 8, nullptr, 0, DAC::MAX_VALUE }, + { DAC_B_VOLT_6, "DAC B 9.0 volts", "-> 9.000V ", default_help_r, default_footer, CALIBRATE_OCTAVE, 9, nullptr, 0, DAC::MAX_VALUE }, + + { DAC_C_VOLT_3m, "DAC C 0.0 volts", "-> 0.000V ", default_help_r, default_footer, CALIBRATE_OCTAVE, 0, nullptr, 0, DAC::MAX_VALUE }, + { DAC_C_VOLT_2m, "DAC C 1.0 volts", "-> 1.000V ", default_help_r, default_footer, CALIBRATE_OCTAVE, 1, nullptr, 0, DAC::MAX_VALUE }, + { DAC_C_VOLT_1m, "DAC C 2.0 volts", "-> 2.000V ", default_help_r, default_footer, CALIBRATE_OCTAVE, 2, nullptr, 0, DAC::MAX_VALUE }, + { DAC_C_VOLT_0, "DAC C 3.0 volts", "-> 3.000V ", default_help_r, default_footer, CALIBRATE_OCTAVE, 3, nullptr, 0, DAC::MAX_VALUE }, + { DAC_C_VOLT_1, "DAC C 4.0 volts", "-> 4.000V ", default_help_r, default_footer, CALIBRATE_OCTAVE, 4, nullptr, 0, DAC::MAX_VALUE }, + { DAC_C_VOLT_2, "DAC C 5.0 volts", "-> 5.000V ", default_help_r, default_footer, CALIBRATE_OCTAVE, 5, nullptr, 0, DAC::MAX_VALUE }, + { DAC_C_VOLT_3, "DAC C 6.0 volts", "-> 6.000V ", default_help_r, default_footer, CALIBRATE_OCTAVE, 6, nullptr, 0, DAC::MAX_VALUE }, + { DAC_C_VOLT_4, "DAC C 7.0 volts", "-> 7.000V ", default_help_r, default_footer, CALIBRATE_OCTAVE, 7, nullptr, 0, DAC::MAX_VALUE }, + { DAC_C_VOLT_5, "DAC C 8.0 volts", "-> 8.000V ", default_help_r, default_footer, CALIBRATE_OCTAVE, 8, nullptr, 0, DAC::MAX_VALUE }, + { DAC_C_VOLT_6, "DAC C 9.0 volts", "-> 9.000V ", default_help_r, default_footer, CALIBRATE_OCTAVE, 9, nullptr, 0, DAC::MAX_VALUE }, + + { DAC_D_VOLT_3m, "DAC D 0.0 volts", "-> 0.000V ", default_help_r, default_footer, CALIBRATE_OCTAVE, 0, nullptr, 0, DAC::MAX_VALUE }, + { DAC_D_VOLT_2m, "DAC D 1.0 volts", "-> 1.000V ", default_help_r, default_footer, CALIBRATE_OCTAVE, 1, nullptr, 0, DAC::MAX_VALUE }, + { DAC_D_VOLT_1m, "DAC D 2.0 volts", "-> 2.000V ", default_help_r, default_footer, CALIBRATE_OCTAVE, 2, nullptr, 0, DAC::MAX_VALUE }, + { DAC_D_VOLT_0, "DAC D 3.0 volts", "-> 3.000V ", default_help_r, default_footer, CALIBRATE_OCTAVE, 3, nullptr, 0, DAC::MAX_VALUE }, + { DAC_D_VOLT_1, "DAC D 4.0 volts", "-> 4.000V ", default_help_r, default_footer, CALIBRATE_OCTAVE, 4, nullptr, 0, DAC::MAX_VALUE }, + { DAC_D_VOLT_2, "DAC D 5.0 volts", "-> 5.000V ", default_help_r, default_footer, CALIBRATE_OCTAVE, 5, nullptr, 0, DAC::MAX_VALUE }, + { DAC_D_VOLT_3, "DAC D 6.0 volts", "-> 6.000V ", default_help_r, default_footer, CALIBRATE_OCTAVE, 6, nullptr, 0, DAC::MAX_VALUE }, + { DAC_D_VOLT_4, "DAC D 7.0 volts", "-> 7.000V ", default_help_r, default_footer, CALIBRATE_OCTAVE, 7, nullptr, 0, DAC::MAX_VALUE }, + { DAC_D_VOLT_5, "DAC D 8.0 volts", "-> 8.000V ", default_help_r, default_footer, CALIBRATE_OCTAVE, 8, nullptr, 0, DAC::MAX_VALUE }, + { DAC_D_VOLT_6, "DAC D 9.0 volts", "-> 9.000V ", default_help_r, default_footer, CALIBRATE_OCTAVE, 9, nullptr, 0, DAC::MAX_VALUE }, #else { DAC_A_VOLT_3m, "DAC A -3 volts", "-> -3.000V ", default_help_r, default_footer, CALIBRATE_OCTAVE, -3, nullptr, 0, DAC::MAX_VALUE }, { DAC_A_VOLT_2m, "DAC A -2 volts", "-> -2.000V ", default_help_r, default_footer, CALIBRATE_OCTAVE, -2, nullptr, 0, DAC::MAX_VALUE }, From 3754b99f65e1c81d5bb4a2f06696b019e889eb65 Mon Sep 17 00:00:00 2001 From: Jason Justian Date: Sun, 8 Jul 2018 18:32:01 -0400 Subject: [PATCH 08/14] Fixed bitmap data for reversed percent sign --- software/o_c_REV/extern/gfx_font_6x8.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/software/o_c_REV/extern/gfx_font_6x8.h b/software/o_c_REV/extern/gfx_font_6x8.h index e9652acc..3207b4f6 100644 --- a/software/o_c_REV/extern/gfx_font_6x8.h +++ b/software/o_c_REV/extern/gfx_font_6x8.h @@ -25,7 +25,7 @@ const uint8_t ssd1306xled_font6x8 [] PROGMEM = { 0x00, 0x00, 0x07, 0x00, 0x07, 0x00, // " 0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14, // # 0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12, // $ - 0x00, 0x62, 0x64, 0x08, 0x13, 0x23, // % + 0x00, 0x23, 0x13, 0x08, 0x64, 0x62, // % 0x00, 0x36, 0x49, 0x55, 0x22, 0x50, // & 0x00, 0x00, 0x05, 0x03, 0x00, 0x00, // ' 0x00, 0x00, 0x1c, 0x22, 0x41, 0x00, // ( From 251eb163b56edd9d727d91ac44a5ba44d5ca802c Mon Sep 17 00:00:00 2001 From: mxmxmx Date: Thu, 30 Aug 2018 08:36:34 +0200 Subject: [PATCH 09/14] [ADC] use DMA --- software/o_c_REV/OC_ADC.cpp | 152 ++++++++++++++++++++--------------- software/o_c_REV/OC_ADC.h | 41 ++++------ software/o_c_REV/o_c_REV.ino | 3 +- 3 files changed, 102 insertions(+), 94 deletions(-) diff --git a/software/o_c_REV/OC_ADC.cpp b/software/o_c_REV/OC_ADC.cpp index e6ecf1e6..a4aa3e8a 100644 --- a/software/o_c_REV/OC_ADC.cpp +++ b/software/o_c_REV/OC_ADC.cpp @@ -1,32 +1,20 @@ #include "OC_ADC.h" #include "OC_gpio.h" - +#include "DMAChannel.h" #include namespace OC { -template struct ChannelDesc { }; -template <> struct ChannelDesc { - static const int PIN = CV1; -}; -template <> struct ChannelDesc { - static const int PIN = CV2; -}; -template <> struct ChannelDesc { - static const int PIN = CV3; -}; -template <> struct ChannelDesc { - static const int PIN = CV4; -}; - /*static*/ ::ADC ADC::adc_; -/*static*/ size_t ADC::scan_channel_; /*static*/ ADC::CalibrationData *ADC::calibration_data_; /*static*/ uint32_t ADC::raw_[ADC_CHANNEL_LAST]; /*static*/ uint32_t ADC::smoothed_[ADC_CHANNEL_LAST]; -#ifdef ENABLE_ADC_DEBUG -/*static*/ volatile uint32_t ADC::busy_waits_; -#endif +/*static*/ volatile bool ADC::ready_; + +constexpr uint16_t ADC::SCA_CHANNEL_ID[DMA_NUM_CH]; // ADCx_SCA register channel numbers +DMAChannel* dma0 = new DMAChannel(false); // dma0 channel, fills adcbuffer_0 +DMAChannel* dma1 = new DMAChannel(false); // dma1 channel, updates ADC0_SC1A which holds the channel/pin IDs +DMAMEM static volatile uint16_t __attribute__((aligned(DMA_BUF_SIZE+0))) adcbuffer_0[DMA_BUF_SIZE]; /*static*/ void ADC::Init(CalibrationData *calibration_data) { @@ -42,62 +30,94 @@ template <> struct ChannelDesc { adc_.setConversionSpeed(kAdcConversionSpeed); adc_.setSamplingSpeed(kAdcSamplingSpeed); adc_.setAveraging(kAdcScanAverages); - adc_.disableDMA(); - adc_.disableInterrupts(); - adc_.disableCompare(); - - scan_channel_ = ADC_CHANNEL_1; - adc_.startSingleRead(ChannelDesc::PIN); calibration_data_ = calibration_data; std::fill(raw_, raw_ + ADC_CHANNEL_LAST, 0); std::fill(smoothed_, smoothed_ + ADC_CHANNEL_LAST, 0); -#ifdef ENABLE_ADC_DEBUG - busy_waits_ = 0; -#endif + std::fill(adcbuffer_0, adcbuffer_0 + DMA_BUF_SIZE, 0); + + adc_.enableDMA(); } -// As I understand it, only CV4 can be muxed to ADC1, so it's not possible to -// use ADC::startSynchronizedSingleRead, which would allow reading two channels -// simultaneously +/*static*/ void ADC::DMA_ISR() { -/*static*/ void FASTRUN ADC::Scan() { + ADC::ready_ = true; + dma0->TCD->DADDR = &adcbuffer_0[0]; + dma0->clearInterrupt(); + /* restart DMA in ADC::Scan_DMA() */ +} -#ifdef ENABLE_ADC_DEBUG - if (!adc_.isComplete(ADC_0)) { - ++busy_waits_; - while (!adc_.isComplete(ADC_0)); - } -#endif - const uint16_t value = adc_.readSingle(ADC_0); - - size_t channel = scan_channel_; - switch (channel) { - case ADC_CHANNEL_1: - adc_.startSingleRead(ChannelDesc::PIN, ADC_0); - update(value); - ++channel; - break; - - case ADC_CHANNEL_2: - adc_.startSingleRead(ChannelDesc::PIN, ADC_0); - update(value); - ++channel; - break; - - case ADC_CHANNEL_3: - adc_.startSingleRead(ChannelDesc::PIN, ADC_0); - update(value); - ++channel; - break; - - case ADC_CHANNEL_4: - adc_.startSingleRead(ChannelDesc::PIN, ADC_0); - update(value); - channel = ADC_CHANNEL_1; - break; +/* + * + * DMA/ADC à la https://forum.pjrc.com/threads/30171-Reconfigure-ADC-via-a-DMA-transfer-to-allow-multiple-Channel-Acquisition + * basically, this sets up two DMA channels and cycles through the 10 (effectively: 16) adc channels once (until the buffer is full), resets, and so on; dma1 advances SCA_CHANNEL_ID + * somewhat like https://www.nxp.com/docs/en/application-note/AN4590.pdf but w/o the PDB. + * +*/ + +void ADC::Init_DMA() { + + dma0->begin(true); // allocate the DMA channel + dma0->TCD->SADDR = &ADC0_RA; + dma0->TCD->SOFF = 0; + dma0->TCD->ATTR = 0x101; + dma0->TCD->NBYTES = 2; + dma0->TCD->SLAST = 0; + dma0->TCD->DADDR = &adcbuffer_0[0]; + dma0->TCD->DOFF = 2; + dma0->TCD->DLASTSGA = -(2 * DMA_BUF_SIZE); + dma0->TCD->BITER = DMA_BUF_SIZE; + dma0->TCD->CITER = DMA_BUF_SIZE; + dma0->triggerAtHardwareEvent(DMAMUX_SOURCE_ADC0); + dma0->disableOnCompletion(); + dma0->interruptAtCompletion(); + dma0->attachInterrupt(DMA_ISR); + + dma1->begin(true); // allocate the DMA channel + dma1->TCD->SADDR = &ADC::SCA_CHANNEL_ID[0]; + dma1->TCD->SOFF = 2; // source increment each transfer (n bytes) + dma1->TCD->ATTR = 0x101; + dma1->TCD->SLAST = - DMA_NUM_CH*2; // num ADC0 samples * 2 + dma1->TCD->BITER = DMA_NUM_CH; + dma1->TCD->CITER = DMA_NUM_CH; + dma1->TCD->DADDR = &ADC0_SC1A; + dma1->TCD->DLASTSGA = 0; + dma1->TCD->NBYTES = 2; + dma1->TCD->DOFF = 0; + dma1->triggerAtTransfersOf(*dma0); + dma1->triggerAtCompletionOf(*dma0); + + dma0->enable(); + dma1->enable(); +} + +/*static*/void FASTRUN ADC::Scan_DMA() { + + if (ADC::ready_) + { + ADC::ready_ = false; + + /* + * collect results from adcbuffer_0; as things are, there's DMA_BUF_SIZE = 16 samples in the buffer. + */ + + uint32_t value; + + value = (adcbuffer_0[0] + adcbuffer_0[4] + adcbuffer_0[8] + adcbuffer_0[12]) / 4; + update(value); + + value = (adcbuffer_0[1] + adcbuffer_0[5] + adcbuffer_0[9] + adcbuffer_0[13]) / 4; + update(value); + + value = (adcbuffer_0[2] + adcbuffer_0[6] + adcbuffer_0[10] + adcbuffer_0[14]) / 4; + update(value); + + value = (adcbuffer_0[3] + adcbuffer_0[7] + adcbuffer_0[11] + adcbuffer_0[15]) / 4; + update(value); + + /* restart */ + dma0->enable(); } - scan_channel_ = channel; } /*static*/ void ADC::CalibratePitch(int32_t c2, int32_t c4) { diff --git a/software/o_c_REV/OC_ADC.h b/software/o_c_REV/OC_ADC.h index 4d1a7de2..c0a2d108 100644 --- a/software/o_c_REV/OC_ADC.h +++ b/software/o_c_REV/OC_ADC.h @@ -1,7 +1,6 @@ #ifndef OC_ADC_H_ #define OC_ADC_H_ -#include #include "src/drivers/ADC/OC_util_ADC.h" #include "OC_config.h" @@ -18,6 +17,9 @@ enum ADC_CHANNEL { ADC_CHANNEL_LAST, }; +#define DMA_BUF_SIZE 16 +#define DMA_NUM_CH ADC_CHANNEL_LAST + namespace OC { class ADC { @@ -34,7 +36,6 @@ class ADC { static constexpr uint8_t kAdcScanAverages = 16; static constexpr uint8_t kAdcSamplingSpeed = ADC_HIGH_SPEED_16BITS; static constexpr uint8_t kAdcConversionSpeed = ADC_HIGH_SPEED; - static constexpr uint32_t kAdcValueShift = kAdcSmoothBits; @@ -45,13 +46,9 @@ class ADC { }; static void Init(CalibrationData *calibration_data); - - // Read the value of the last conversion and update current channel, then - // start the next conversion. If necessary, some channels could be given - // priority by scanning them more often. Even better might be some kind of - // continuous/DMA sampling to make things even more independent of the main - // ISR timing restrictions. - static void Scan(); + static void Init_DMA(); + static void DMA_ISR(); + static void Scan_DMA(); template static int32_t value() { @@ -79,21 +76,6 @@ class ADC { return (value * calibration_data_->pitch_cv_scale) >> 12; } -#ifdef ENABLE_ADC_DEBUG - // DEBUG - static uint16_t fail_flag0() { - return adc_.adc0->fail_flag; - } - - static uint16_t fail_flag1() { - return adc_.adc1->fail_flag; - } - - static uint32_t busy_waits() { - return busy_waits_; - } -#endif - static void CalibratePitch(int32_t c2, int32_t c4); private: @@ -108,15 +90,20 @@ class ADC { } static ::ADC adc_; + static volatile bool ready_; static size_t scan_channel_; static CalibrationData *calibration_data_; static uint32_t raw_[ADC_CHANNEL_LAST]; static uint32_t smoothed_[ADC_CHANNEL_LAST]; -#ifdef ENABLE_ADC_DEBUG - static volatile uint32_t busy_waits_; -#endif + /* + * below: channel ids for the ADCx_SCA register: we have 4 inputs + * CV1 (19) = A5 = 0x4C; CV2 (18) = A4 = 0x4D; CV3 (20) = A6 = 0x46; CV4 (17) = A3 = 0x49 + * for some reason the IDs must be in order: CV2, CV3, CV4, CV1 (as is, this will break the FLIP_180 option) + */ + + static constexpr uint16_t SCA_CHANNEL_ID[DMA_NUM_CH] = { 0x4D, 0x46, 0x49, 0x4C }; }; }; diff --git a/software/o_c_REV/o_c_REV.ino b/software/o_c_REV/o_c_REV.ino index 8ab65ef6..7a9f9a4d 100644 --- a/software/o_c_REV/o_c_REV.ino +++ b/software/o_c_REV/o_c_REV.ino @@ -79,7 +79,7 @@ void FASTRUN CORE_timer_ISR() { // 100us: 10kHz / 4 / 4 ~ .6kHz // 60us: 16.666K / 4 / 4 ~ 1kHz // kAdcSmoothing == 4 has some (maybe 1-2LSB) jitter but seems "Good Enough". - OC::ADC::Scan(); + OC::ADC::Scan_DMA(); // Pin changes are tracked in separate ISRs, so depending on prio it might // need extra precautions. @@ -110,6 +110,7 @@ void setup() { OC::DigitalInputs::Init(); delay(400); OC::ADC::Init(&OC::calibration_data.adc); // Yes, it's using the calibration_data before it's loaded... + OC::ADC::Init_DMA(); OC::DAC::Init(&OC::calibration_data.dac); display::Init(); From 292b4eedd4d0a89ca09128011d1f0f15f80fd5bf Mon Sep 17 00:00:00 2001 From: mxmxmx Date: Thu, 30 Aug 2018 11:20:11 +0200 Subject: [PATCH 10/14] [ADC] params --- software/o_c_REV/OC_ADC.cpp | 18 +++++------------- software/o_c_REV/OC_ADC.h | 2 +- software/o_c_REV/o_c_REV.ino | 7 +------ 3 files changed, 7 insertions(+), 20 deletions(-) diff --git a/software/o_c_REV/OC_ADC.cpp b/software/o_c_REV/OC_ADC.cpp index a4aa3e8a..83755836 100644 --- a/software/o_c_REV/OC_ADC.cpp +++ b/software/o_c_REV/OC_ADC.cpp @@ -18,13 +18,6 @@ DMAMEM static volatile uint16_t __attribute__((aligned(DMA_BUF_SIZE+0))) adcbuff /*static*/ void ADC::Init(CalibrationData *calibration_data) { - // According to Paul Stoffregen: You do NOT want to have the pin in digital mode when using it as analog input. - // https://forum.pjrc.com/threads/34319-Analog-input-impedance-and-pull-up?p=103543&viewfull=1#post103543 - //pinMode(ChannelDesc::PIN, INPUT); - //pinMode(ChannelDesc::PIN, INPUT); - //pinMode(ChannelDesc::PIN, INPUT); - //pinMode(ChannelDesc::PIN, INPUT); - adc_.setReference(ADC_REF_3V3); adc_.setResolution(kAdcScanResolution); adc_.setConversionSpeed(kAdcConversionSpeed); @@ -100,19 +93,18 @@ void ADC::Init_DMA() { /* * collect results from adcbuffer_0; as things are, there's DMA_BUF_SIZE = 16 samples in the buffer. */ - uint32_t value; - - value = (adcbuffer_0[0] + adcbuffer_0[4] + adcbuffer_0[8] + adcbuffer_0[12]) / 4; + + value = (adcbuffer_0[0] + adcbuffer_0[4] + adcbuffer_0[8] + adcbuffer_0[12]) >> 2; // / 4 = DMA_BUF_SIZE / DMA_NUM_CH update(value); - value = (adcbuffer_0[1] + adcbuffer_0[5] + adcbuffer_0[9] + adcbuffer_0[13]) / 4; + value = (adcbuffer_0[1] + adcbuffer_0[5] + adcbuffer_0[9] + adcbuffer_0[13]) >> 2; update(value); - value = (adcbuffer_0[2] + adcbuffer_0[6] + adcbuffer_0[10] + adcbuffer_0[14]) / 4; + value = (adcbuffer_0[2] + adcbuffer_0[6] + adcbuffer_0[10] + adcbuffer_0[14]) >> 2; update(value); - value = (adcbuffer_0[3] + adcbuffer_0[7] + adcbuffer_0[11] + adcbuffer_0[15]) / 4; + value = (adcbuffer_0[3] + adcbuffer_0[7] + adcbuffer_0[11] + adcbuffer_0[15]) >> 2; update(value); /* restart */ diff --git a/software/o_c_REV/OC_ADC.h b/software/o_c_REV/OC_ADC.h index c0a2d108..3529bc05 100644 --- a/software/o_c_REV/OC_ADC.h +++ b/software/o_c_REV/OC_ADC.h @@ -33,7 +33,7 @@ class ADC { // These values should be tweaked so startSingleRead/readSingle run in main ISR update time // 16 bit has best-case 13 bits useable, but we only want 12 so we discard 4 anyway static constexpr uint8_t kAdcScanResolution = 16; - static constexpr uint8_t kAdcScanAverages = 16; + static constexpr uint8_t kAdcScanAverages = 4; static constexpr uint8_t kAdcSamplingSpeed = ADC_HIGH_SPEED_16BITS; static constexpr uint8_t kAdcConversionSpeed = ADC_HIGH_SPEED; static constexpr uint32_t kAdcValueShift = kAdcSmoothBits; diff --git a/software/o_c_REV/o_c_REV.ino b/software/o_c_REV/o_c_REV.ino index 7a9f9a4d..7cd3e7b2 100644 --- a/software/o_c_REV/o_c_REV.ino +++ b/software/o_c_REV/o_c_REV.ino @@ -73,12 +73,7 @@ void FASTRUN CORE_timer_ISR() { OC::DAC::Update(); display::Update(); - // The ADC scan uses async startSingleRead/readSingle and single channel each - // loop, so should be fast enough even at 60us (check ADC::busy_waits() == 0) - // to verify. Effectively, the scan rate is ISR / 4 / ADC::kAdcSmoothing - // 100us: 10kHz / 4 / 4 ~ .6kHz - // 60us: 16.666K / 4 / 4 ~ 1kHz - // kAdcSmoothing == 4 has some (maybe 1-2LSB) jitter but seems "Good Enough". + // see OC_ADC.h for details; empirically (with current parameters), Scan_DMA() picks up new samples @ 5.55kHz OC::ADC::Scan_DMA(); // Pin changes are tracked in separate ISRs, so depending on prio it might From 4b2c5e99a112f0d7d6c7698968467e541c0632d9 Mon Sep 17 00:00:00 2001 From: mxmxmx Date: Sat, 8 Sep 2018 19:20:47 +0200 Subject: [PATCH 11/14] [H1200] min/maj variation --- software/o_c_REV/APP_H1200.ino | 62 +++++++++++++++++++++++----------- 1 file changed, 43 insertions(+), 19 deletions(-) diff --git a/software/o_c_REV/APP_H1200.ino b/software/o_c_REV/APP_H1200.ino index 0853da2b..1d8310d6 100644 --- a/software/o_c_REV/APP_H1200.ino +++ b/software/o_c_REV/APP_H1200.ino @@ -305,6 +305,7 @@ public: void Init() { InitDefaults(); update_enabled_settings(); + manual_mode_change_ = false; } H1200Setting enabled_setting_at(int index) const { @@ -315,6 +316,14 @@ public: return num_enabled_settings_; } + void mode_change(bool yn) { + manual_mode_change_ = yn; + } + + bool mode_manual_change() const { + return manual_mode_change_; + } + void update_enabled_settings() { H1200Setting *settings = enabled_settings_; @@ -369,6 +378,7 @@ public: private: int num_enabled_settings_; + bool manual_mode_change_; H1200Setting enabled_settings_[H1200_SETTING_LAST]; }; @@ -499,24 +509,24 @@ public: euclidean_counter_ = 0; root_sample_ = false; root_ = 0; - p_euclidean_length_ = 8 ; - p_euclidean_fill_ = 0 ; - p_euclidean_offset_ = 0 ; - l_euclidean_length_ = 8 ; - l_euclidean_fill_ = 0 ; - l_euclidean_offset_ = 0 ; - r_euclidean_length_ = 8 ; - r_euclidean_fill_ = 0 ; - r_euclidean_offset_ = 0 ; - n_euclidean_length_ = 8 ; - n_euclidean_fill_ = 0 ; - n_euclidean_offset_ = 0 ; - s_euclidean_length_ = 8 ; - s_euclidean_fill_ = 0 ; - s_euclidean_offset_ = 0 ; - h_euclidean_length_ = 8 ; - h_euclidean_fill_ = 0 ; - h_euclidean_offset_ = 0 ; + p_euclidean_length_ = 8; + p_euclidean_fill_ = 0; + p_euclidean_offset_ = 0; + l_euclidean_length_ = 8; + l_euclidean_fill_ = 0; + l_euclidean_offset_ = 0; + r_euclidean_length_ = 8; + r_euclidean_fill_ = 0; + r_euclidean_offset_ = 0; + n_euclidean_length_ = 8; + n_euclidean_fill_ = 0; + n_euclidean_offset_ = 0; + s_euclidean_length_ = 8; + s_euclidean_fill_ = 0; + s_euclidean_offset_ = 0; + h_euclidean_length_ = 8; + h_euclidean_fill_ = 0; + h_euclidean_offset_ = 0; } @@ -674,6 +684,16 @@ void FASTRUN H1200_clock(uint32_t triggers) { // Reset has priority if (triggers & TRIGGER_MASK_TR1) { h1200_state.tonnetz_state.reset(h1200_settings.mode()); + h1200_settings.mode_change(false); + } + + // Reset on next trigger = manual change min/maj + if (h1200_settings.mode_manual_change()) { + + if ((triggers & OC::DIGITAL_INPUT_2_MASK) || (triggers & OC::DIGITAL_INPUT_3_MASK) || (triggers & OC::DIGITAL_INPUT_4_MASK)) { + h1200_settings.mode_change(false); + h1200_state.tonnetz_state.reset(h1200_settings.mode()); + } } int32_t root_ = h1200_settings.root_offset(); @@ -1092,6 +1112,9 @@ void H1200_handleEncoderEvent(const UI::Event &event) { if (h1200_settings.get_trigger_type() != H1200_TRIGGER_TYPE_EUCLIDEAN) h1200_state.cursor.Scroll(h1200_state.cursor_pos()); break; + case H1200_SETTING_MODE: + h1200_settings.mode_change(true); + break; default: break; } @@ -1105,7 +1128,8 @@ void H1200_handleEncoderEvent(const UI::Event &event) { void H1200_menu() { - const EMode current_mode = h1200_state.tonnetz_state.current_chord().mode(); + /* show mode change instantly, because it's somewhat confusing (inconsistent?) otherwise */ + const EMode current_mode = h1200_settings.mode(); // const EMode current_mode = h1200_state.tonnetz_state.current_chord().mode(); int outputs[4]; h1200_state.tonnetz_state.get_outputs(outputs); From 3bd8c92bb8945f71fddff60de062e34379541226 Mon Sep 17 00:00:00 2001 From: mxmxmx Date: Sun, 9 Sep 2018 19:13:10 +0200 Subject: [PATCH 12/14] [OC] pin voodoo --- software/o_c_REV/APP_H1200.ino | 3 +- software/o_c_REV/OC_DAC.cpp | 4 +- software/o_c_REV/OC_gpio.h | 43 +++++++++++++++++++ .../src/drivers/SH1106_128x64_driver.cpp | 6 +-- 4 files changed, 49 insertions(+), 7 deletions(-) diff --git a/software/o_c_REV/APP_H1200.ino b/software/o_c_REV/APP_H1200.ino index 1d8310d6..580c5bd4 100644 --- a/software/o_c_REV/APP_H1200.ino +++ b/software/o_c_REV/APP_H1200.ino @@ -1129,7 +1129,7 @@ void H1200_handleEncoderEvent(const UI::Event &event) { void H1200_menu() { /* show mode change instantly, because it's somewhat confusing (inconsistent?) otherwise */ - const EMode current_mode = h1200_settings.mode(); // const EMode current_mode = h1200_state.tonnetz_state.current_chord().mode(); + const EMode current_mode = h1200_settings.mode(); // const EMode current_mode = h1200_state.tonnetz_state.current_chord().mode(); int outputs[4]; h1200_state.tonnetz_state.get_outputs(outputs); @@ -1210,4 +1210,3 @@ void H1200_debug() { graphics.printf("I: %4d %4d", cv, scaled); } #endif // H1200_DEBUG - diff --git a/software/o_c_REV/OC_DAC.cpp b/software/o_c_REV/OC_DAC.cpp index 7b899130..a3029f34 100644 --- a/software/o_c_REV/OC_DAC.cpp +++ b/software/o_c_REV/OC_DAC.cpp @@ -53,8 +53,8 @@ void DAC::Init(CalibrationData *calibration_data) { restore_scaling(0x0); // set up DAC pins - pinMode(DAC_CS, OUTPUT); - pinMode(DAC_RST,OUTPUT); + OC::pinMode(DAC_CS, OUTPUT); + OC::pinMode(DAC_RST,OUTPUT); #ifdef DAC8564 // A0 = 0, A1 = 0 digitalWrite(DAC_RST, LOW); diff --git a/software/o_c_REV/OC_gpio.h b/software/o_c_REV/OC_gpio.h index 21cd5fc9..5c6b25f9 100644 --- a/software/o_c_REV/OC_gpio.h +++ b/software/o_c_REV/OC_gpio.h @@ -69,4 +69,47 @@ #define OC_GPIO_TRx_PINMODE INPUT_PULLUP #define OC_GPIO_ENC_PINMODE INPUT_PULLUP +/* local copy of pinMode (cf. cores/pins_teensy.c), using faster slew rate */ + +namespace OC { + +void inline pinMode(uint8_t pin, uint8_t mode) { + + volatile uint32_t *config; + + if (pin >= CORE_NUM_DIGITAL) return; + config = portConfigRegister(pin); + + if (mode == OUTPUT || mode == OUTPUT_OPENDRAIN) { + #ifdef KINETISK + *portModeRegister(pin) = 1; + #else + *portModeRegister(pin) |= digitalPinToBitMask(pin); // TODO: atomic + #endif + /* use fast slew rate for output */ + *config = PORT_PCR_DSE | PORT_PCR_MUX(1); + if (mode == OUTPUT_OPENDRAIN) { + *config |= PORT_PCR_ODE; + } else { + *config &= ~PORT_PCR_ODE; + } + } else { + #ifdef KINETISK + *portModeRegister(pin) = 0; + #else + *portModeRegister(pin) &= ~digitalPinToBitMask(pin); + #endif + if (mode == INPUT) { + *config = PORT_PCR_MUX(1); + } else if (mode == INPUT_PULLUP) { + *config = PORT_PCR_MUX(1) | PORT_PCR_PE | PORT_PCR_PS; + } else if (mode == INPUT_PULLDOWN) { + *config = PORT_PCR_MUX(1) | PORT_PCR_PE; + } else { // INPUT_DISABLE + *config = 0; + } + } + } +} + #endif // OC_GPIO_H_ diff --git a/software/o_c_REV/src/drivers/SH1106_128x64_driver.cpp b/software/o_c_REV/src/drivers/SH1106_128x64_driver.cpp index d5e1842c..d5bde1a4 100644 --- a/software/o_c_REV/src/drivers/SH1106_128x64_driver.cpp +++ b/software/o_c_REV/src/drivers/SH1106_128x64_driver.cpp @@ -84,9 +84,9 @@ static uint8_t SH1106_display_on_seq[] = { /*static*/ void SH1106_128x64_Driver::Init() { - pinMode(OLED_CS, OUTPUT); - pinMode(OLED_RST, OUTPUT); - pinMode(OLED_DC, OUTPUT); + OC::pinMode(OLED_CS, OUTPUT); + OC::pinMode(OLED_RST, OUTPUT); + OC::pinMode(OLED_DC, OUTPUT); //SPI_init(); // u8g_teensy::U8G_COM_MSG_INIT From 829071b512ec166f9ff7d50da30abd03943d021a Mon Sep 17 00:00:00 2001 From: mxmxmx Date: Mon, 10 Sep 2018 09:36:11 +0200 Subject: [PATCH 13/14] [ADC] comment --- software/o_c_REV/OC_ADC.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/software/o_c_REV/OC_ADC.cpp b/software/o_c_REV/OC_ADC.cpp index 83755836..e3f68bb4 100644 --- a/software/o_c_REV/OC_ADC.cpp +++ b/software/o_c_REV/OC_ADC.cpp @@ -43,7 +43,7 @@ DMAMEM static volatile uint16_t __attribute__((aligned(DMA_BUF_SIZE+0))) adcbuff /* * * DMA/ADC à la https://forum.pjrc.com/threads/30171-Reconfigure-ADC-via-a-DMA-transfer-to-allow-multiple-Channel-Acquisition - * basically, this sets up two DMA channels and cycles through the 10 (effectively: 16) adc channels once (until the buffer is full), resets, and so on; dma1 advances SCA_CHANNEL_ID + * basically, this sets up two DMA channels and cycles through the four adc mux channels (until the buffer is full), resets, and so on; dma1 advances SCA_CHANNEL_ID * somewhat like https://www.nxp.com/docs/en/application-note/AN4590.pdf but w/o the PDB. * */ From b83f38dfa0c68b59286b8d854f8349705f654f66 Mon Sep 17 00:00:00 2001 From: mxmxmx Date: Thu, 24 Jan 2019 20:32:32 +0100 Subject: [PATCH 14/14] [OC] v1.35 --- software/o_c_REV/OC_version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/software/o_c_REV/OC_version.h b/software/o_c_REV/OC_version.h index 50fc2578..80bd1c7c 100644 --- a/software/o_c_REV/OC_version.h +++ b/software/o_c_REV/OC_version.h @@ -3,5 +3,5 @@ // // GENERATED FILE, DO NOT EDIT // -#define OC_VERSION "v1.3.5b" +#define OC_VERSION "v1.3.5" #endif