From afe31574767311a12ac71893573f1eedf9e3eab5 Mon Sep 17 00:00:00 2001 From: Jamie Ferguson Date: Fri, 8 Sep 2017 12:43:45 +1000 Subject: [PATCH 01/16] Tweaks to Harrington encoder and button defaults L encoder changes inversion, buttons change octaves --- software/o_c_REV/APP_H1200.ino | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/software/o_c_REV/APP_H1200.ino b/software/o_c_REV/APP_H1200.ino index b9efb3c1..0853da2b 100644 --- a/software/o_c_REV/APP_H1200.ino +++ b/software/o_c_REV/APP_H1200.ino @@ -1045,11 +1045,11 @@ void H1200_handleButtonEvent(const UI::Event &event) { if (UI::EVENT_BUTTON_PRESS == event.type) { switch (event.control) { case OC::CONTROL_BUTTON_UP: - if (h1200_settings.change_value(H1200_SETTING_INVERSION, 1)) + if (h1200_settings.change_value(H1200_SETTING_OCTAVE, 1)) h1200_state.force_update(); break; case OC::CONTROL_BUTTON_DOWN: - if (h1200_settings.change_value(H1200_SETTING_INVERSION, -1)) + if (h1200_settings.change_value(H1200_SETTING_OCTAVE, -1)) h1200_state.force_update(); break; case OC::CONTROL_BUTTON_L: @@ -1070,7 +1070,7 @@ void H1200_handleButtonEvent(const UI::Event &event) { void H1200_handleEncoderEvent(const UI::Event &event) { if (OC::CONTROL_ENCODER_L == event.control) { - if (h1200_settings.change_value(H1200_SETTING_ROOT_OFFSET, event.value)) + if (h1200_settings.change_value(H1200_SETTING_INVERSION, event.value)) h1200_state.force_update(); } else if (OC::CONTROL_ENCODER_R == event.control) { if (h1200_state.cursor.editing()) { From 334b5b2e8d75f47638af5630250a59ba9ec57eb0 Mon Sep 17 00:00:00 2001 From: Jamie Ferguson Date: Fri, 8 Sep 2017 12:44:59 +1000 Subject: [PATCH 02/16] Add octave menu item to Quantermain UI --- software/o_c_REV/APP_QQ.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/software/o_c_REV/APP_QQ.ino b/software/o_c_REV/APP_QQ.ino index 1b14cb9b..8efc6da1 100644 --- a/software/o_c_REV/APP_QQ.ino +++ b/software/o_c_REV/APP_QQ.ino @@ -992,6 +992,7 @@ public: *settings++ = CHANNEL_SETTING_CLKDIV; *settings++ = CHANNEL_SETTING_DELAY; } + *settings++ = CHANNEL_SETTING_OCTAVE; *settings++ = CHANNEL_SETTING_TRANSPOSE; *settings++ = CHANNEL_SETTING_FINE; From f908b94d03d237273b8cdea1b56913367b22a4dd Mon Sep 17 00:00:00 2001 From: Patrick Dowling Date: Sat, 30 Sep 2017 15:27:02 +0200 Subject: [PATCH 03/16] [ENVGEN] Align parameters with enum in call to apply_cv_mapping to avoid off-by-one --- software/o_c_REV/APP_ENVGEN.ino | 79 +++++++++++++++++---------------- 1 file changed, 40 insertions(+), 39 deletions(-) diff --git a/software/o_c_REV/APP_ENVGEN.ino b/software/o_c_REV/APP_ENVGEN.ino index 084fc664..47099567 100644 --- a/software/o_c_REV/APP_ENVGEN.ino +++ b/software/o_c_REV/APP_ENVGEN.ino @@ -316,7 +316,7 @@ public: return 0; } - inline void apply_cv_mapping(EnvelopeSettings cv_setting, const int32_t cvs[ADC_CHANNEL_LAST], int32_t segments[kMaxSegments + kEuclideanParams + kDelayParams + kAmplitudeParams]) { + inline void apply_cv_mapping(EnvelopeSettings cv_setting, const int32_t cvs[ADC_CHANNEL_LAST], int32_t segments[CV_MAPPING_LAST]) { int mapping = values_[cv_setting]; switch (mapping) { case CV_MAPPING_SEG1: @@ -419,53 +419,54 @@ public: template void Update(uint32_t triggers, uint32_t internal_trigger_mask, const int32_t cvs[ADC_CHANNEL_LAST]) { - int32_t s[kMaxSegments + kEuclideanParams + kDelayParams + kAmplitudeParams]; - s[0] = SCALE8_16(static_cast(get_segment_value(0))); - s[1] = SCALE8_16(static_cast(get_segment_value(1))); - s[2] = SCALE8_16(static_cast(get_segment_value(2))); - s[3] = SCALE8_16(static_cast(get_segment_value(3))); - s[4] = static_cast(get_euclidean_length()); - s[5] = static_cast(get_euclidean_fill()); - s[6] = static_cast(get_euclidean_offset()); - s[7] = get_trigger_delay_ms(); - s[8] = get_amplitude(); - s[9] = get_max_loops(); + int32_t s[CV_MAPPING_LAST]; + s[CV_MAPPING_SEG1] = SCALE8_16(static_cast(get_segment_value(0))); + s[CV_MAPPING_SEG2] = SCALE8_16(static_cast(get_segment_value(1))); + s[CV_MAPPING_SEG3] = SCALE8_16(static_cast(get_segment_value(2))); + s[CV_MAPPING_SEG4] = SCALE8_16(static_cast(get_segment_value(3))); + s[CV_MAPPING_ADR] = 0; // unused, but needs a placeholder to align with enum CVMapping + s[CV_MAPPING_EUCLIDEAN_LENGTH] = static_cast(get_euclidean_length()); + s[CV_MAPPING_EUCLIDEAN_FILL] = static_cast(get_euclidean_fill()); + s[CV_MAPPING_EUCLIDEAN_OFFSET] = static_cast(get_euclidean_offset()); + s[CV_MAPPING_DELAY_MSEC] = get_trigger_delay_ms(); + s[CV_MAPPING_AMPLITUDE] = get_amplitude(); + s[CV_MAPPING_MAX_LOOPS] = get_max_loops(); apply_cv_mapping(ENV_SETTING_CV1, cvs, s); apply_cv_mapping(ENV_SETTING_CV2, cvs, s); apply_cv_mapping(ENV_SETTING_CV3, cvs, s); apply_cv_mapping(ENV_SETTING_CV4, cvs, s); - s[0] = USAT16(s[0]); - s[1] = USAT16(s[1]); - s[2] = USAT16(s[2]); - s[3] = USAT16(s[3]); - CONSTRAIN(s[4], 0, 31); - CONSTRAIN(s[5], 0, 32); - CONSTRAIN(s[6], 0, 32); - CONSTRAIN(s[7], 0, 65535); - CONSTRAIN(s[8], 0, 65535); - CONSTRAIN(s[9], 0, 65535); + s[CV_MAPPING_SEG1] = USAT16(s[CV_MAPPING_SEG1]); + s[CV_MAPPING_SEG2] = USAT16(s[CV_MAPPING_SEG2]); + s[CV_MAPPING_SEG3] = USAT16(s[CV_MAPPING_SEG3]); + s[CV_MAPPING_SEG4] = USAT16(s[CV_MAPPING_SEG4]); + CONSTRAIN(s[CV_MAPPING_EUCLIDEAN_LENGTH], 0, 31); + CONSTRAIN(s[CV_MAPPING_EUCLIDEAN_FILL], 0, 32); + CONSTRAIN(s[CV_MAPPING_EUCLIDEAN_OFFSET], 0, 32); + CONSTRAIN(s[CV_MAPPING_DELAY_MSEC], 0, 65535); + CONSTRAIN(s[CV_MAPPING_AMPLITUDE], 0, 65535); + CONSTRAIN(s[CV_MAPPING_MAX_LOOPS], 0, 65535); EnvelopeType type = get_type(); switch (type) { - case ENV_TYPE_AD: env_.set_ad(s[0], s[1], 0, 0); break; - case ENV_TYPE_ADSR: env_.set_adsr(s[0], s[1], s[2]>>1, s[3]); break; - case ENV_TYPE_ADR: env_.set_adr(s[0], s[1], s[2]>>1, s[3], 0, 0 ); break; - case ENV_TYPE_AR: env_.set_ar(s[0], s[1]); break; - case ENV_TYPE_ADSAR: env_.set_adsar(s[0], s[1], s[2]>>1, s[3]); break; - case ENV_TYPE_ADAR: env_.set_adar(s[0], s[1], s[2]>>1, s[3], 0, 0); break; - case ENV_TYPE_ADL2: env_.set_ad(s[0], s[1], 0, 2); break; - case ENV_TYPE_ADRL3: env_.set_adr(s[0], s[1], s[2]>>1, s[3], 0, 3); break; - case ENV_TYPE_ADL2R: env_.set_adr(s[0], s[1], s[2]>>1, s[3], 0, 2); break; - case ENV_TYPE_ADARL4: env_.set_adar(s[0], s[1], s[2]>>1, s[3], 0, 4); break; - case ENV_TYPE_ADAL2R: env_.set_adar(s[0], s[1], s[2]>>1, s[3], 1, 3); break; // was 2, 4 + case ENV_TYPE_AD: env_.set_ad(s[CV_MAPPING_SEG1], s[CV_MAPPING_SEG2], 0, 0); break; + case ENV_TYPE_ADSR: env_.set_adsr(s[CV_MAPPING_SEG1], s[CV_MAPPING_SEG2], s[CV_MAPPING_SEG3]>>1, s[CV_MAPPING_SEG4]); break; + case ENV_TYPE_ADR: env_.set_adr(s[CV_MAPPING_SEG1], s[CV_MAPPING_SEG2], s[CV_MAPPING_SEG3]>>1, s[CV_MAPPING_SEG4], 0, 0 ); break; + case ENV_TYPE_AR: env_.set_ar(s[CV_MAPPING_SEG1], s[CV_MAPPING_SEG2]); break; + case ENV_TYPE_ADSAR: env_.set_adsar(s[CV_MAPPING_SEG1], s[CV_MAPPING_SEG2], s[CV_MAPPING_SEG3]>>1, s[CV_MAPPING_SEG4]); break; + case ENV_TYPE_ADAR: env_.set_adar(s[CV_MAPPING_SEG1], s[CV_MAPPING_SEG2], s[CV_MAPPING_SEG3]>>1, s[CV_MAPPING_SEG4], 0, 0); break; + case ENV_TYPE_ADL2: env_.set_ad(s[CV_MAPPING_SEG1], s[CV_MAPPING_SEG2], 0, 2); break; + case ENV_TYPE_ADRL3: env_.set_adr(s[CV_MAPPING_SEG1], s[CV_MAPPING_SEG2], s[CV_MAPPING_SEG3]>>1, s[CV_MAPPING_SEG4], 0, 3); break; + case ENV_TYPE_ADL2R: env_.set_adr(s[CV_MAPPING_SEG1], s[CV_MAPPING_SEG2], s[CV_MAPPING_SEG3]>>1, s[CV_MAPPING_SEG4], 0, 2); break; + case ENV_TYPE_ADARL4: env_.set_adar(s[CV_MAPPING_SEG1], s[CV_MAPPING_SEG2], s[CV_MAPPING_SEG3]>>1, s[CV_MAPPING_SEG4], 0, 4); break; + case ENV_TYPE_ADAL2R: env_.set_adar(s[CV_MAPPING_SEG1], s[CV_MAPPING_SEG2], s[CV_MAPPING_SEG3]>>1, s[CV_MAPPING_SEG4], 1, 3); break; // was 2, 4 default: break; } // set the amplitude - env_.set_amplitude(s[8], is_amplitude_sampled()) ; + env_.set_amplitude(s[CV_MAPPING_AMPLITUDE], is_amplitude_sampled()) ; if (type != last_type_) { last_type_ = type; @@ -488,7 +489,7 @@ public: env_.set_release_time_multiplier(get_release_time_multiplier()); // set the looping envelope maximum number of loops - env_.set_max_loops(s[9]); + env_.set_max_loops(s[CV_MAPPING_MAX_LOOPS]); int trigger_input = get_trigger_input(); bool triggered = false; @@ -507,9 +508,9 @@ public: trigger_display_.Update(1, triggered || gate_raised_); if (triggered) ++euclidean_counter_; - uint8_t euclidean_length = static_cast(s[4]); - uint8_t euclidean_fill = static_cast(s[5]); - uint8_t euclidean_offset = static_cast(s[6]); + uint8_t euclidean_length = static_cast(s[CV_MAPPING_EUCLIDEAN_LENGTH]); + uint8_t euclidean_fill = static_cast(s[CV_MAPPING_EUCLIDEAN_FILL]); + uint8_t euclidean_offset = static_cast(s[CV_MAPPING_EUCLIDEAN_OFFSET]); // Process Euclidean pattern reset uint8_t euclidean_reset_trigger_input = get_euclidean_reset_trigger_input(); @@ -534,7 +535,7 @@ public: if (triggered) { TriggerDelayMode delay_mode = get_trigger_delay_mode(); // uint32_t delay = get_trigger_delay_ms() * 1000U; - uint32_t delay = static_cast(s[7] * 1000U); + uint32_t delay = static_cast(s[CV_MAPPING_DELAY_MSEC] * 1000U); if (delay_mode && delay) { triggered = false; if (TRIGGER_DELAY_QUEUE == delay_mode) { From 92d7573c170f96c056a78faaad78fb08b26c8e78 Mon Sep 17 00:00:00 2001 From: mxmxmx Date: Thu, 5 Oct 2017 08:33:57 +0200 Subject: [PATCH 04/16] [OC] cOC support --- software/o_c_REV/OC_DAC.cpp | 19 ++++++++++++++++--- software/o_c_REV/OC_options.h | 5 ++++- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/software/o_c_REV/OC_DAC.cpp b/software/o_c_REV/OC_DAC.cpp index 6f922b3c..81ac62e7 100644 --- a/software/o_c_REV/OC_DAC.cpp +++ b/software/o_c_REV/OC_DAC.cpp @@ -207,7 +207,11 @@ uint8_t DAC::DAC_scaling[DAC_CHANNEL_LAST]; }; // namespace OC void set8565_CHA(uint32_t data) { + #ifdef BUCHLA_cOC + uint32_t _data = data; + #else uint32_t _data = OC::DAC::MAX_VALUE - data; + #endif #ifdef FLIP_180 SPIFIFO.write(0b00010110, SPI_CONTINUE); #else @@ -219,8 +223,11 @@ void set8565_CHA(uint32_t data) { } void set8565_CHB(uint32_t data) { + #ifdef BUCHLA_cOC + uint32_t _data = data; + #else uint32_t _data = OC::DAC::MAX_VALUE - data; - + #endif #ifdef FLIP_180 SPIFIFO.write(0b00010100, SPI_CONTINUE); #else @@ -232,8 +239,11 @@ void set8565_CHB(uint32_t data) { } void set8565_CHC(uint32_t data) { + #ifdef BUCHLA_cOC + uint32_t _data = data; + #else uint32_t _data = OC::DAC::MAX_VALUE - data; - + #endif #ifdef FLIP_180 SPIFIFO.write(0b00010010, SPI_CONTINUE); #else @@ -245,8 +255,11 @@ void set8565_CHC(uint32_t data) { } void set8565_CHD(uint32_t data) { + #ifdef BUCHLA_cOC + uint32_t _data = data; + #else uint32_t _data = OC::DAC::MAX_VALUE - data; - + #endif #ifdef FLIP_180 SPIFIFO.write(0b00010000, SPI_CONTINUE); #else diff --git a/software/o_c_REV/OC_options.h b/software/o_c_REV/OC_options.h index 2712f08e..3da510ed 100644 --- a/software/o_c_REV/OC_options.h +++ b/software/o_c_REV/OC_options.h @@ -9,7 +9,9 @@ /* ------------ uncomment for Buchla/non-octaval/quartertone support: ------------------------------- */ //#define BUCHLA_SUPPORT -/* ------------ uncomment for use with Northernlight 4U version: ------------------------------------ */ +/* ------------ uncomment for use with Northernlight cOC program card: ------------------------------ */ +//#define BUCHLA_cOC +/* ------------ uncomment for use with Northernlight 4U / cOC : ------------------------------------- */ //#define BUCHLA_4U /* ------------ uncomment for boring app names ------------------------------------------------------ */ //#define BORING_APP_NAMES @@ -18,3 +20,4 @@ /* ------------ flip screen / IO mapping ------------------------------------------------------------ */ //#define FLIP_180 #endif + From b56a826817014415f7fe57eee4c23b8330fbcac9 Mon Sep 17 00:00:00 2001 From: mxmxmx Date: Sat, 7 Oct 2017 16:56:06 +0200 Subject: [PATCH 05/16] [OC] cOC offset --- software/o_c_REV/OC_calibration.ino | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/software/o_c_REV/OC_calibration.ino b/software/o_c_REV/OC_calibration.ino index f3b75072..27129438 100644 --- a/software/o_c_REV/OC_calibration.ino +++ b/software/o_c_REV/OC_calibration.ino @@ -10,7 +10,12 @@ using OC::DAC; +#ifdef BUCHLA_cOC +static constexpr uint16_t DAC_OFFSET = 485; // DAC offset, initial approx., ish (Easel card) +#else static constexpr uint16_t DAC_OFFSET = 4890; // DAC offset, initial approx., ish --> -3.5V to 6V +#endif + #ifdef BUCHLA_4U static constexpr uint16_t _ADC_OFFSET = (uint16_t)((float)pow(2,OC::ADC::kAdcResolution)*1.0f); // ADC offset @3.3V #else From 8f2004fe748943d2b45c1163d67589a30a814d2b Mon Sep 17 00:00:00 2001 From: mxmxmx Date: Fri, 13 Oct 2017 15:38:13 +0200 Subject: [PATCH 06/16] [OC] cOC calibration --- software/o_c_REV/OC_calibration.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/software/o_c_REV/OC_calibration.ino b/software/o_c_REV/OC_calibration.ino index 27129438..482e3114 100644 --- a/software/o_c_REV/OC_calibration.ino +++ b/software/o_c_REV/OC_calibration.ino @@ -11,7 +11,7 @@ using OC::DAC; #ifdef BUCHLA_cOC -static constexpr uint16_t DAC_OFFSET = 485; // DAC offset, initial approx., ish (Easel card) +static constexpr uint16_t DAC_OFFSET = 335; // DAC offset, initial approx., ish (Easel card) #else static constexpr uint16_t DAC_OFFSET = 4890; // DAC offset, initial approx., ish --> -3.5V to 6V #endif From df3ab2aacf63f78c4c335c96cbda4165214d56c0 Mon Sep 17 00:00:00 2001 From: Patrick Dowling Date: Sun, 24 Dec 2017 12:37:07 +0100 Subject: [PATCH 07/16] Correct handling of odd numbers of nibbles in ::Save function --- software/o_c_REV/util/util_settings.h | 16 ++-- software/test/Makefile | 2 +- software/test/oc_test_settings.cpp | 109 ++++++++++++++++++++++++++ 3 files changed, 120 insertions(+), 7 deletions(-) create mode 100644 software/test/oc_test_settings.cpp diff --git a/software/o_c_REV/util/util_settings.h b/software/o_c_REV/util/util_settings.h index 2d65f981..cdcd853d 100644 --- a/software/o_c_REV/util/util_settings.h +++ b/software/o_c_REV/util/util_settings.h @@ -150,6 +150,8 @@ class SettingsBase { protected: + static constexpr uint16_t kNibbleValid = 0xf000; + int values_[num_settings]; static const settings::value_attr value_attr_[]; static const size_t storage_size_; @@ -163,11 +165,13 @@ class SettingsBase { } uint8_t *write_nibble(uint8_t *dest, size_t index) const { - nibbles_ = (nibbles_ << 4) | (values_[index] & 0x0f); - if (nibbles_ & 0xf000) { + if (nibbles_) { + nibbles_ |= (values_[index] & 0x0f); dest = flush_nibbles(dest); } else { - nibbles_ |= 0x0f00; + // Ensure correct packing for reads even if there's an odd number of nibbles; + // the first nibble is assumed to be in the msbits. + nibbles_ = kNibbleValid | ((values_[index] & 0x0f) << 4); } return dest; } @@ -187,9 +191,9 @@ class SettingsBase { value = nibbles_ & 0x0f; nibbles_ = 0; } else { - nibbles_ = *src++; - value = (nibbles_ & 0xf0) >> 4; - nibbles_ = nibbles_ | 0xf000; + value = *src++; + nibbles_ = kNibbleValid | value; + value >>= 4; } apply_value(index, value); return src; diff --git a/software/test/Makefile b/software/test/Makefile index e2e3c3e5..e528a815 100644 --- a/software/test/Makefile +++ b/software/test/Makefile @@ -12,7 +12,7 @@ CXX = g++ LD = g++ AR = ar -r -CPPFLAGS += -I$(OC_SRC_DIR) -I$(GTEST_DIR)include -Wall -Werror +CPPFLAGS += -I$(OC_SRC_DIR) -I$(GTEST_DIR)include -Wall -Werror -std=c++11 # GTEST GTEST_DIR = ./gtest/googletest/ diff --git a/software/test/oc_test_settings.cpp b/software/test/oc_test_settings.cpp new file mode 100644 index 00000000..a7dac28d --- /dev/null +++ b/software/test/oc_test_settings.cpp @@ -0,0 +1,109 @@ +#include "gtest/gtest.h" +#include "util/util_settings.h" + +class TestU8Settings : public settings::SettingsBase { }; +SETTINGS_DECLARE(TestU8Settings, 1) { + { 0, 0, 8, "U8", nullptr, settings::STORAGE_TYPE_U8 }, +}; + +TEST(TestSettings,TestU8) +{ + EXPECT_EQ(1U, TestU8Settings::storageSize()); + + TestU8Settings settings; + settings.InitDefaults(); + EXPECT_EQ(0, settings.get_value(0)); +} + +class TestPackU4EvenSettings : public settings::SettingsBase { }; +SETTINGS_DECLARE(TestPackU4EvenSettings, 3) { + { 0, 0, 15, "U4", nullptr, settings::STORAGE_TYPE_U4 }, + { 0, 0, 15, "U4", nullptr, settings::STORAGE_TYPE_U4 }, + { 0, -1, 8, "I32", nullptr, settings::STORAGE_TYPE_I32 }, +}; + +TEST(TestSettings,TestPackU4Even) +{ + EXPECT_EQ(5, TestPackU4EvenSettings::storageSize()); + + TestPackU4EvenSettings settings; + settings.InitDefaults(); + EXPECT_TRUE(settings.apply_value(0, 0x09)); // 1001 + EXPECT_TRUE(settings.apply_value(1, 0x06)); // 0110 + EXPECT_TRUE(settings.apply_value(2, -1)); + + std::vector data; + data.resize(TestPackU4EvenSettings::storageSize() + 1, 0xff); + + size_t saved_size = settings.Save(&data.front()); + EXPECT_EQ(TestPackU4EvenSettings::storageSize(), saved_size); + EXPECT_EQ(0xff, data[TestPackU4EvenSettings::storageSize()]); + + settings.InitDefaults(); + size_t restored_size = settings.Restore(&data.front()); + EXPECT_EQ(saved_size, restored_size); + + EXPECT_EQ(0x09, settings.get_value(0)); + EXPECT_EQ(0x06, settings.get_value(1)); + EXPECT_EQ(-1, settings.get_value(2)); +} + +class TestPackU4OddSettings : public settings::SettingsBase { }; +SETTINGS_DECLARE(TestPackU4OddSettings, 2) { + { 0, 0, 15, "U4", nullptr, settings::STORAGE_TYPE_U4 }, + { 0, -1, 8, "I32", nullptr, settings::STORAGE_TYPE_I32 }, +}; + +TEST(TestSettings,TestPackU4Odd) +{ + EXPECT_EQ(5, TestPackU4OddSettings::storageSize()); + + TestPackU4OddSettings settings; + settings.InitDefaults(); + EXPECT_TRUE(settings.apply_value(0, 0x09)); // 1001 + EXPECT_TRUE(settings.apply_value(1, -1)); + + std::vector data; + data.resize(TestPackU4OddSettings::storageSize() + 1, 0xff); + + size_t saved_size = settings.Save(&data.front()); + EXPECT_EQ(TestPackU4OddSettings::storageSize(), saved_size); + EXPECT_EQ(0xff, data[TestPackU4OddSettings::storageSize()]); + + settings.InitDefaults(); + size_t restored_size = settings.Restore(&data.front()); + EXPECT_EQ(saved_size, restored_size); + + EXPECT_EQ(0x09, settings.get_value(0)); + EXPECT_EQ(-1, settings.get_value(1)); +} + +class TestPackU4OddEndSettings : public settings::SettingsBase { }; +SETTINGS_DECLARE(TestPackU4OddEndSettings, 2) { + { 0, -1, 8, "I32", nullptr, settings::STORAGE_TYPE_I32 }, + { 0, 0, 15, "U4", nullptr, settings::STORAGE_TYPE_U4 }, +}; + +TEST(TestSettings,TestPackU4OddEnd) +{ + EXPECT_EQ(5, TestPackU4OddSettings::storageSize()); + + TestPackU4OddEndSettings settings; + settings.InitDefaults(); + EXPECT_TRUE(settings.apply_value(0, -1)); + EXPECT_TRUE(settings.apply_value(1, 0x09)); + + std::vector data; + data.resize(TestPackU4OddEndSettings::storageSize() + 1, 0xff); + + size_t saved_size = settings.Save(&data.front()); + EXPECT_EQ(TestPackU4OddEndSettings::storageSize(), saved_size); + EXPECT_EQ(0xff, data[TestPackU4OddEndSettings::storageSize()]); + + settings.InitDefaults(); + size_t restored_size = settings.Restore(&data.front()); + EXPECT_EQ(saved_size, restored_size); + + EXPECT_EQ(-1, settings.get_value(0)); + EXPECT_EQ(0x09, settings.get_value(1)); +} From f23b3e6fca00faebbb5514e14666b26f65352d42 Mon Sep 17 00:00:00 2001 From: mxmxmx Date: Wed, 27 Dec 2017 15:03:16 +0100 Subject: [PATCH 08/16] cOC misc --- software/o_c_REV/APP_DQ.ino | 14 ++++++++++---- software/o_c_REV/APP_ENVGEN.ino | 1 - software/o_c_REV/APP_QQ.ino | 15 +++++++++++---- software/o_c_REV/OC_calibration.ino | 12 ++++++++++-- software/o_c_REV/OC_ui.cpp | 7 +++++-- software/o_c_REV/OC_version.h | 2 +- 6 files changed, 37 insertions(+), 14 deletions(-) diff --git a/software/o_c_REV/APP_DQ.ino b/software/o_c_REV/APP_DQ.ino index 02410079..e5749a13 100644 --- a/software/o_c_REV/APP_DQ.ino +++ b/software/o_c_REV/APP_DQ.ino @@ -36,6 +36,12 @@ #include "OC_scale_edit.h" #include "OC_strings.h" +#ifdef BUCHLA_4U + #define DQ_OFFSET_X 22 +#else + #define DQ_OFFSET_X 47 +#endif + const uint8_t NUMCHANNELS = 2; const uint8_t NUM_SCALE_SLOTS = 4; @@ -1482,15 +1488,15 @@ void DQ_QuantizerChannel::RenderScreensaver(weegfx::coord_t start_x) const { menu::DrawMask(start_x + 58, 1, get_shift_register(), get_turing_display_length()); break; default: { - graphics.setPixel(start_x + 47 - 16, 4); + graphics.setPixel(start_x + DQ_OFFSET_X - 16, 4); int32_t cv = OC::ADC::value(static_cast(source)); cv = (cv * 20 + 2047) >> 11; if (cv < 0) - graphics.drawRect(start_x + 47 - 16 + cv, 6, -cv, 2); + graphics.drawRect(start_x + DQ_OFFSET_X - 16 + cv, 6, -cv, 2); else if (cv > 0) - graphics.drawRect(start_x + 47 - 16, 6, cv, 2); + graphics.drawRect(start_x + DQ_OFFSET_X - 16, 6, cv, 2); else - graphics.drawRect(start_x + 47 - 16, 6, 1, 2); + graphics.drawRect(start_x + DQ_OFFSET_X - 16, 6, 1, 2); } break; } diff --git a/software/o_c_REV/APP_ENVGEN.ino b/software/o_c_REV/APP_ENVGEN.ino index 47099567..c737423f 100644 --- a/software/o_c_REV/APP_ENVGEN.ino +++ b/software/o_c_REV/APP_ENVGEN.ino @@ -1,4 +1,3 @@ -// Copyright (c) 2016 Patrick Dowling, Tim Churches // // Initial app implementation: Patrick Dowling (pld@gurkenkiste.com) // Modifications by: Tim Churches (tim.churches@gmail.com) diff --git a/software/o_c_REV/APP_QQ.ino b/software/o_c_REV/APP_QQ.ino index 1b14cb9b..ec7a2af8 100644 --- a/software/o_c_REV/APP_QQ.ino +++ b/software/o_c_REV/APP_QQ.ino @@ -39,6 +39,13 @@ #include "OC_scale_edit.h" #include "OC_strings.h" + +#ifdef BUCHLA_4U + #define QQ_OFFSET_X 20 +#else + #define QQ_OFFSET_X 31 +#endif + enum ChannelSetting { CHANNEL_SETTING_SCALE, CHANNEL_SETTING_ROOT, @@ -1489,15 +1496,15 @@ void QuantizerChannel::RenderScreensaver(weegfx::coord_t start_x) const { // menu::DrawMask(start_x + 31, 1, get_int_seq_register(), 8); break; default: { - graphics.setPixel(start_x + 31 - 16, 4); + graphics.setPixel(start_x + QQ_OFFSET_X - 16, 4); int32_t cv = OC::ADC::value(static_cast(source)); cv = (cv * 24 + 2047) >> 12; if (cv < 0) - graphics.drawRect(start_x + 31 - 16 + cv, 6, -cv, 2); + graphics.drawRect(start_x + QQ_OFFSET_X - 16 + cv, 6, -cv, 2); else if (cv > 0) - graphics.drawRect(start_x + 31 - 16, 6, cv, 2); + graphics.drawRect(start_x + QQ_OFFSET_X - 16, 6, cv, 2); else - graphics.drawRect(start_x + 31 - 16, 6, 1, 2); + graphics.drawRect(start_x + QQ_OFFSET_X - 16, 6, 1, 2); } break; } diff --git a/software/o_c_REV/OC_calibration.ino b/software/o_c_REV/OC_calibration.ino index 482e3114..6bf7f843 100644 --- a/software/o_c_REV/OC_calibration.ino +++ b/software/o_c_REV/OC_calibration.ino @@ -11,7 +11,7 @@ using OC::DAC; #ifdef BUCHLA_cOC -static constexpr uint16_t DAC_OFFSET = 335; // DAC offset, initial approx., ish (Easel card) +static constexpr uint16_t DAC_OFFSET = 0; // DAC offset, initial approx., ish (Easel card) #else static constexpr uint16_t DAC_OFFSET = 4890; // DAC offset, initial approx., ish --> -3.5V to 6V #endif @@ -33,10 +33,18 @@ bool calibration_data_loaded = false; const OC::CalibrationData kCalibrationDefaults = { // DAC { { + #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}, + {197, 6634, 13083, 19517, 25966, 32417, 38850, 45301, 51733, 58180, 64400} + #else {0, 6553, 13107, 19661, 26214, 32768, 39321, 45875, 52428, 58981, 65535}, {0, 6553, 13107, 19661, 26214, 32768, 39321, 45875, 52428, 58981, 65535}, {0, 6553, 13107, 19661, 26214, 32768, 39321, 45875, 52428, 58981, 65535}, - {0, 6553, 13107, 19661, 26214, 32768, 39321, 45875, 52428, 58981, 65535} }, + {0, 6553, 13107, 19661, 26214, 32768, 39321, 45875, 52428, 58981, 65535} + #endif + }, }, // ADC { { _ADC_OFFSET, _ADC_OFFSET, _ADC_OFFSET, _ADC_OFFSET }, diff --git a/software/o_c_REV/OC_ui.cpp b/software/o_c_REV/OC_ui.cpp index 67e19dd6..aaa624dd 100644 --- a/software/o_c_REV/OC_ui.cpp +++ b/software/o_c_REV/OC_ui.cpp @@ -167,8 +167,11 @@ UiMode Ui::Splashscreen(bool &reset_settings) { GRAPHICS_BEGIN_FRAME(true); menu::DefaultTitleBar::Draw(); - graphics.print("Ornaments & Crimes"); - + #ifdef BUCHLA_cOC + graphics.print("NLM card O_C"); + #else + graphics.print("Ornaments & Crimes"); + #endif weegfx::coord_t y = menu::CalcLineY(0); graphics.setPrintPos(menu::kIndentDx, y + menu::kTextDy); diff --git a/software/o_c_REV/OC_version.h b/software/o_c_REV/OC_version.h index d35a18dc..eea3f3db 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.3b" +#define OC_VERSION "v1.3.4a" #endif From 607734bded918d32cacb6a7173d62c9c98ecb01d Mon Sep 17 00:00:00 2001 From: Patrick Dowling Date: Sun, 7 Jan 2018 19:11:25 +0100 Subject: [PATCH 09/16] [ENVGEN] Fix off-by-one indexing into array --- software/o_c_REV/APP_ENVGEN.ino | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/software/o_c_REV/APP_ENVGEN.ino b/software/o_c_REV/APP_ENVGEN.ino index c737423f..f8ed3695 100644 --- a/software/o_c_REV/APP_ENVGEN.ino +++ b/software/o_c_REV/APP_ENVGEN.ino @@ -316,32 +316,33 @@ public: } inline void apply_cv_mapping(EnvelopeSettings cv_setting, const int32_t cvs[ADC_CHANNEL_LAST], int32_t segments[CV_MAPPING_LAST]) { + // segments is indexed directly with CVMapping enum values int mapping = values_[cv_setting]; switch (mapping) { case CV_MAPPING_SEG1: case CV_MAPPING_SEG2: case CV_MAPPING_SEG3: case CV_MAPPING_SEG4: - segments[mapping - CV_MAPPING_SEG1] += (cvs[cv_setting - ENV_SETTING_CV1] * 65536) >> 12; + segments[mapping] += (cvs[cv_setting - ENV_SETTING_CV1] * 65536) >> 12; break; case CV_MAPPING_ADR: - segments[CV_MAPPING_SEG1 - CV_MAPPING_SEG1] += (cvs[cv_setting - ENV_SETTING_CV1] * 65536) >> 12; - segments[CV_MAPPING_SEG2 - CV_MAPPING_SEG1] += (cvs[cv_setting - ENV_SETTING_CV1] * 65536) >> 12; - segments[CV_MAPPING_SEG4 - CV_MAPPING_SEG1] += (cvs[cv_setting - ENV_SETTING_CV1] * 65536) >> 12; + segments[CV_MAPPING_SEG1] += (cvs[cv_setting - ENV_SETTING_CV1] * 65536) >> 12; + segments[CV_MAPPING_SEG2] += (cvs[cv_setting - ENV_SETTING_CV1] * 65536) >> 12; + segments[CV_MAPPING_SEG4] += (cvs[cv_setting - ENV_SETTING_CV1] * 65536) >> 12; break; case CV_MAPPING_EUCLIDEAN_LENGTH: case CV_MAPPING_EUCLIDEAN_FILL: case CV_MAPPING_EUCLIDEAN_OFFSET: - segments[mapping - CV_MAPPING_SEG1] += cvs[cv_setting - ENV_SETTING_CV1] >> 6; + segments[mapping] += cvs[cv_setting - ENV_SETTING_CV1] >> 6; break; case CV_MAPPING_DELAY_MSEC: - segments[mapping - CV_MAPPING_SEG1] += cvs[cv_setting - ENV_SETTING_CV1] >> 2; + segments[mapping] += cvs[cv_setting - ENV_SETTING_CV1] >> 2; break; case CV_MAPPING_AMPLITUDE: - segments[mapping - CV_MAPPING_SEG1] += cvs[cv_setting - ENV_SETTING_CV1] << 5 ; + segments[mapping] += cvs[cv_setting - ENV_SETTING_CV1] << 5 ; break; case CV_MAPPING_MAX_LOOPS: - segments[mapping - CV_MAPPING_SEG1] += cvs[cv_setting - ENV_SETTING_CV1] << 2 ; + segments[mapping] += cvs[cv_setting - ENV_SETTING_CV1] << 2 ; break; default: break; @@ -419,6 +420,7 @@ public: template void Update(uint32_t triggers, uint32_t internal_trigger_mask, const int32_t cvs[ADC_CHANNEL_LAST]) { int32_t s[CV_MAPPING_LAST]; + s[CV_MAPPING_NONE] = 0; // unused, but needs a placeholder to align with enum CVMapping s[CV_MAPPING_SEG1] = SCALE8_16(static_cast(get_segment_value(0))); s[CV_MAPPING_SEG2] = SCALE8_16(static_cast(get_segment_value(1))); s[CV_MAPPING_SEG3] = SCALE8_16(static_cast(get_segment_value(2))); From 9ca06ba0ef7243932871219c81eee8b8ff7201d5 Mon Sep 17 00:00:00 2001 From: Patrick Dowling Date: Tue, 9 Jan 2018 20:28:58 +0100 Subject: [PATCH 10/16] [SEQ] fix brownian motion when selected by cv --- software/o_c_REV/APP_A_SEQ.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/software/o_c_REV/APP_A_SEQ.ino b/software/o_c_REV/APP_A_SEQ.ino index 70336013..c6374308 100644 --- a/software/o_c_REV/APP_A_SEQ.ino +++ b/software/o_c_REV/APP_A_SEQ.ino @@ -1513,7 +1513,7 @@ public: break; case PENDULUM1: case BROWNIAN: - if (BROWNIAN == get_direction()) { + if (BROWNIAN == _direction) { // Compare Brownian probability and reverse direction if needed int16_t brown_prb = get_brownian_probability(); From 47baf2f25d82874d082304c35d07c51fab1fa35f Mon Sep 17 00:00:00 2001 From: Patrick Dowling Date: Sat, 27 Jan 2018 16:42:11 +0100 Subject: [PATCH 11/16] Add option to invert display pixels --- software/o_c_REV/OC_options.h | 2 ++ software/o_c_REV/src/drivers/SH1106_128x64_driver.cpp | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/software/o_c_REV/OC_options.h b/software/o_c_REV/OC_options.h index 3da510ed..2d74f991 100644 --- a/software/o_c_REV/OC_options.h +++ b/software/o_c_REV/OC_options.h @@ -19,5 +19,7 @@ //#define PRINT_DEBUG /* ------------ flip screen / IO mapping ------------------------------------------------------------ */ //#define FLIP_180 +/* ------------ invert screen pixels ---------------------------------------------------------------- */ +//#define INVERT_DISPLAY #endif 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 737be379..d5e1842c 100644 --- a/software/o_c_REV/src/drivers/SH1106_128x64_driver.cpp +++ b/software/o_c_REV/src/drivers/SH1106_128x64_driver.cpp @@ -70,7 +70,11 @@ static uint8_t SH1106_init_seq[] = { 0x02e, /* 2012-05-27: Deactivate scroll */ 0x0a4, /* output ram to display */ +#ifdef INVERT_DISPLAY + 0x0a7, /* inverted display mode */ +#else 0x0a6, /* none inverted normal display mode */ +#endif //0x0af, /* display on */ }; From 85dcb4c385b38a37b2643db76d05bec09bd8e589 Mon Sep 17 00:00:00 2001 From: Patrick Dowling Date: Wed, 31 Jan 2018 08:31:21 +0100 Subject: [PATCH 12/16] Fix mapping between DigitalInput enum and physical pin This works in the regular case (since TR1-4 are pins 0-3) but fails when FLIP_180 is enabled (or if the physical pins are remapped) --- software/o_c_REV/OC_digital_inputs.h | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/software/o_c_REV/OC_digital_inputs.h b/software/o_c_REV/OC_digital_inputs.h index 371b62c4..ce8cedbf 100644 --- a/software/o_c_REV/OC_digital_inputs.h +++ b/software/o_c_REV/OC_digital_inputs.h @@ -4,6 +4,7 @@ #include #include "OC_config.h" #include "OC_core.h" +#include "OC_gpio.h" namespace OC { @@ -22,6 +23,12 @@ static constexpr uint32_t DIGITAL_INPUT_2_MASK = DIGITAL_INPUT_MASK(DIGITAL_INPU static constexpr uint32_t DIGITAL_INPUT_3_MASK = DIGITAL_INPUT_MASK(DIGITAL_INPUT_3); static constexpr uint32_t DIGITAL_INPUT_4_MASK = DIGITAL_INPUT_MASK(DIGITAL_INPUT_4); +template struct InputPinDesc { }; +template <> struct InputPinDesc { static constexpr int PIN = TR1; }; +template <> struct InputPinDesc { static constexpr int PIN = TR2; }; +template <> struct InputPinDesc { static constexpr int PIN = TR3; }; +template <> struct InputPinDesc { static constexpr int PIN = TR4; }; + class DigitalInputs { public: @@ -47,11 +54,11 @@ class DigitalInputs { } template static inline bool read_immediate() { - return !digitalReadFast(input); + return !digitalReadFast(InputPinDesc::PIN); } static inline bool read_immediate(DigitalInput input) { - return !digitalReadFast(input); + return !digitalReadFast(InputPinMap(input)); } template static inline void clock() { @@ -60,6 +67,17 @@ class DigitalInputs { private: + inline static int InputPinMap(DigitalInput input) { + switch (input) { + case DIGITAL_INPUT_1: return InputPinDesc::PIN; + case DIGITAL_INPUT_2: return InputPinDesc::PIN; + case DIGITAL_INPUT_3: return InputPinDesc::PIN; + case DIGITAL_INPUT_4: return InputPinDesc::PIN; + default: break; + } + return 0; + } + static uint32_t clocked_mask_; static volatile uint32_t clocked_[DIGITAL_INPUT_LAST]; From 7ec84feaa61113296eb59943309b88a018172817 Mon Sep 17 00:00:00 2001 From: mxmxmx Date: Fri, 2 Mar 2018 08:42:09 +0100 Subject: [PATCH 13/16] [OC] move DAC8564 to options --- software/o_c_REV/OC_DAC.cpp | 1 - software/o_c_REV/OC_options.h | 4 ++++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/software/o_c_REV/OC_DAC.cpp b/software/o_c_REV/OC_DAC.cpp index 81ac62e7..99f4bbc5 100644 --- a/software/o_c_REV/OC_DAC.cpp +++ b/software/o_c_REV/OC_DAC.cpp @@ -42,7 +42,6 @@ #include "OC_autotune.h" #define SPICLOCK_30MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(60 / 2) * ((1+1)/2) = 30 MHz (= 24MHz, when F_BUS == 48000000) -//#define DAC8564 // <-- uncomment, if using DAC8564 namespace OC { diff --git a/software/o_c_REV/OC_options.h b/software/o_c_REV/OC_options.h index 2d74f991..d1dcc545 100644 --- a/software/o_c_REV/OC_options.h +++ b/software/o_c_REV/OC_options.h @@ -21,5 +21,9 @@ //#define FLIP_180 /* ------------ invert screen pixels ---------------------------------------------------------------- */ //#define INVERT_DISPLAY +/* ------------ use DAC8564 ------------------------------------------------------------------------- */ +//#define DAC8564 + + */ #endif From 6d01b7eb517d08df645a9a26aa04d04a8eea8179 Mon Sep 17 00:00:00 2001 From: mxmxmx Date: Fri, 2 Mar 2018 08:42:53 +0100 Subject: [PATCH 14/16] [OC] move DAC8564 to options --- software/o_c_REV/OC_options.h | 1 - 1 file changed, 1 deletion(-) diff --git a/software/o_c_REV/OC_options.h b/software/o_c_REV/OC_options.h index d1dcc545..28357a43 100644 --- a/software/o_c_REV/OC_options.h +++ b/software/o_c_REV/OC_options.h @@ -24,6 +24,5 @@ /* ------------ use DAC8564 ------------------------------------------------------------------------- */ //#define DAC8564 - */ #endif From 1157164b0b1d2f6c407d618d8883d7a8a005f9c5 Mon Sep 17 00:00:00 2001 From: mxmxmx Date: Fri, 2 Mar 2018 09:17:03 +0100 Subject: [PATCH 15/16] [OC] SPIFIFO deprecated (TD1.42) --- software/o_c_REV/OC_DAC.cpp | 2 +- software/o_c_REV/util/util_SPIFIFO.h | 289 +++++++++++++++++++++++++++ 2 files changed, 290 insertions(+), 1 deletion(-) create mode 100644 software/o_c_REV/util/util_SPIFIFO.h diff --git a/software/o_c_REV/OC_DAC.cpp b/software/o_c_REV/OC_DAC.cpp index 99f4bbc5..7b899130 100644 --- a/software/o_c_REV/OC_DAC.cpp +++ b/software/o_c_REV/OC_DAC.cpp @@ -33,7 +33,7 @@ * */ -#include +#include "util/util_SPIFIFO.h" #include "OC_DAC.h" #include "OC_gpio.h" #include "OC_options.h" diff --git a/software/o_c_REV/util/util_SPIFIFO.h b/software/o_c_REV/util/util_SPIFIFO.h new file mode 100644 index 00000000..fe8298c9 --- /dev/null +++ b/software/o_c_REV/util/util_SPIFIFO.h @@ -0,0 +1,289 @@ +/* from teensy core : https://github.com/PaulStoffregen/cores/ */ + +#ifndef _UTIL_SPIFIFO_h_ +#define _UTIL_SPIFIFO_h_ + +#include + +#ifdef KINETISK + +#if F_BUS == 120000000 +#define HAS_SPIFIFO +#define SPI_CLOCK_24MHz (SPI_CTAR_PBR(3) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(120 / 5) * ((1+1)/2) +#define SPI_CLOCK_16MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(2)) //(120 / 2) * ((1+0)/4) = 15 MHz +#define SPI_CLOCK_12MHz (SPI_CTAR_PBR(3) | SPI_CTAR_BR(0)) //(120 / 5) * ((1+0)/2) +#define SPI_CLOCK_8MHz (SPI_CTAR_PBR(3) | SPI_CTAR_BR(4) | SPI_CTAR_DBR) //(120 / 5) * ((1+1)/6) +#define SPI_CLOCK_6MHz (SPI_CTAR_PBR(3) | SPI_CTAR_BR(2)) //(120 / 5) * ((1+0)/4) +#define SPI_CLOCK_4MHz (SPI_CTAR_PBR(3) | SPI_CTAR_BR(4)) //(120 / 5) * ((1+0)/6) + +#elif F_BUS == 108000000 +#define HAS_SPIFIFO +#define SPI_CLOCK_24MHz (SPI_CTAR_PBR(3) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(108 / 5) * ((1+1)/2) = 21.6 MHz +#define SPI_CLOCK_16MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(2)) //(108 / 2) * ((1+0)/4) = 13.5 MHz +#define SPI_CLOCK_12MHz (SPI_CTAR_PBR(1) | SPI_CTAR_BR(4) | SPI_CTAR_DBR) //(108 / 3) * ((1+1)/6) +#define SPI_CLOCK_8MHz (SPI_CTAR_PBR(3) | SPI_CTAR_BR(4) | SPI_CTAR_DBR) //(108 / 5) * ((1+1)/6) = 7.2 MHz +#define SPI_CLOCK_6MHz (SPI_CTAR_PBR(1) | SPI_CTAR_BR(4)) //(108 / 3) * ((1+0)/6) +#define SPI_CLOCK_4MHz (SPI_CTAR_PBR(5) | SPI_CTAR_BR(2)) //(108 / 7) * ((1+0)/4) = 3.86 MHz + +#elif F_BUS == 96000000 +#define HAS_SPIFIFO +#define SPI_CLOCK_24MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0)) //(96 / 2) * ((1+0)/2) +#define SPI_CLOCK_16MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(4) | SPI_CTAR_DBR) //(96 / 2) * ((1+1)/6) +#define SPI_CLOCK_12MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(6) | SPI_CTAR_DBR) //(96 / 2) * ((1+1)/8) +#define SPI_CLOCK_8MHz (SPI_CTAR_PBR(1) | SPI_CTAR_BR(2)) //(96 / 3) * ((1+0)/4) +#define SPI_CLOCK_6MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(6)) //(96 / 2) * ((1+0)/8) +#define SPI_CLOCK_4MHz (SPI_CTAR_PBR(1) | SPI_CTAR_BR(6)) //(96 / 3) * ((1+0)/8) + +#elif F_BUS == 90000000 +#define HAS_SPIFIFO +#define SPI_CLOCK_24MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0)) //(90 / 2) * ((1+0)/2) = 22.5 MHz +#define SPI_CLOCK_16MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(4) | SPI_CTAR_DBR) //(90 / 2) * ((1+1)/6) = 15 MHz +#define SPI_CLOCK_12MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(6) | SPI_CTAR_DBR) //(90 / 2) * ((1+1)/8) = 11.25 MHz +#define SPI_CLOCK_8MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(4)) //(90 / 2) * ((1+0)/6) = 7.5 MHz +#define SPI_CLOCK_6MHz (SPI_CTAR_PBR(3) | SPI_CTAR_BR(4) | SPI_CTAR_DBR) //(90 / 5) * ((1+1)/6) +#define SPI_CLOCK_4MHz (SPI_CTAR_PBR(1) | SPI_CTAR_BR(6)) //(90 / 3) * ((1+0)/8) = 3.75 MHz + +#elif F_BUS == 80000000 +#define HAS_SPIFIFO +#define SPI_CLOCK_24MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0)) //(80 / 2) * ((1+0)/2) = 20 MHz +#define SPI_CLOCK_16MHz (SPI_CTAR_PBR(3) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(80 / 5) * ((1+1)/2) +#define SPI_CLOCK_12MHz (SPI_CTAR_PBR(5) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(80 / 7) * ((1+1)/2) = 11.42 MHz +#define SPI_CLOCK_8MHz (SPI_CTAR_PBR(3) | SPI_CTAR_BR(0)) //(80 / 5) * ((1+0)/2) +#define SPI_CLOCK_6MHz (SPI_CTAR_PBR(5) | SPI_CTAR_BR(0)) //(80 / 7) * ((1+0)/2) = 5.7 MHz +#define SPI_CLOCK_4MHz (SPI_CTAR_PBR(3) | SPI_CTAR_BR(2)) //(80 / 5) * ((1+0)/4) + +#elif F_BUS == 72000000 +#define HAS_SPIFIFO +#define SPI_CLOCK_24MHz (SPI_CTAR_PBR(1) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(72 / 3) * ((1+1)/2) +#define SPI_CLOCK_16MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(4) | SPI_CTAR_DBR) //(72 / 2) * ((1+1)/6) = 12 MHz +#define SPI_CLOCK_12MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(4) | SPI_CTAR_DBR) //(72 / 2) * ((1+1)/6) +#define SPI_CLOCK_8MHz (SPI_CTAR_PBR(1) | SPI_CTAR_BR(4) | SPI_CTAR_DBR) //(72 / 3) * ((1+1)/6) +#define SPI_CLOCK_6MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(4)) //(72 / 2) * ((1+0)/6) +#define SPI_CLOCK_4MHz (SPI_CTAR_PBR(1) | SPI_CTAR_BR(4)) //(72 / 3) * ((1+0)/6) + +#elif F_BUS == 64000000 +#define HAS_SPIFIFO +#define SPI_CLOCK_24MHz (SPI_CTAR_PBR(1) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(64 / 3) * ((1+1)/2) = 21.3 MHz +#define SPI_CLOCK_16MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0)) //(64 / 2) * ((1+0)/2) +#define SPI_CLOCK_12MHz (SPI_CTAR_PBR(1) | SPI_CTAR_BR(0)) //(64 / 3) * ((1+0)/2) = 10.67 MHz +#define SPI_CLOCK_8MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(2)) //(64 / 2) * ((1+0)/4) +#define SPI_CLOCK_6MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(4)) //(64 / 2) * ((1+0)/6) = 5.3 MHz +#define SPI_CLOCK_4MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(6)) //(64 / 2) * ((1+0)/8) + +#elif F_BUS == 60000000 +#define HAS_SPIFIFO +#define SPI_CLOCK_24MHz (SPI_CTAR_PBR(1) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(60 / 3) * ((1+1)/2) = 20 MHz +#define SPI_CLOCK_16MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0)) //(60 / 2) * ((1+0)/2) = 15 MHz +#define SPI_CLOCK_12MHz (SPI_CTAR_PBR(2) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(60 / 5) * ((1+1)/2) +#define SPI_CLOCK_8MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(1)) //(60 / 2) * ((1+0)/4) = 7.5 MHz +#define SPI_CLOCK_6MHz (SPI_CTAR_PBR(2) | SPI_CTAR_BR(0)) //(60 / 5) * ((1+0)/2) +#define SPI_CLOCK_4MHz (SPI_CTAR_PBR(2) | SPI_CTAR_BR(2) | SPI_CTAR_DBR) //(60 / 5) * ((1+1)/6) + +#elif F_BUS == 56000000 +#define HAS_SPIFIFO +#define SPI_CLOCK_24MHz (SPI_CTAR_PBR(1) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(56 / 3) * ((1+1)/2) = 18.67 +#define SPI_CLOCK_16MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0)) //(56 / 2) * ((1+0)/2) = 14 +#define SPI_CLOCK_12MHz (SPI_CTAR_PBR(2) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(56 / 5) * ((1+1)/2) = 11.2 +#define SPI_CLOCK_8MHz (SPI_CTAR_PBR(3) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(56 / 7) * ((1+1)/2) +#define SPI_CLOCK_6MHz (SPI_CTAR_PBR(2) | SPI_CTAR_BR(0)) //(56 / 5) * ((1+0)/2) +#define SPI_CLOCK_4MHz (SPI_CTAR_PBR(3) | SPI_CTAR_BR(0)) //(56 / 7) * ((1+0)/2) + +#elif F_BUS == 48000000 +#define HAS_SPIFIFO +#define SPI_CLOCK_24MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(48 / 2) * ((1+1)/2) +#define SPI_CLOCK_16MHz (SPI_CTAR_PBR(1) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(48 / 3) * ((1+1)/2) +#define SPI_CLOCK_12MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0)) //(48 / 2) * ((1+0)/2) +#define SPI_CLOCK_8MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(2) | SPI_CTAR_DBR) //(48 / 2) * ((1+1)/6) +#define SPI_CLOCK_6MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(1)) //(48 / 2) * ((1+0)/4) +#define SPI_CLOCK_4MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(2)) //(48 / 2) * ((1+0)/6) + +#elif F_BUS == 40000000 +#define HAS_SPIFIFO +#define SPI_CLOCK_24MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(40 / 2) * ((1+1)/2) = 20 +#define SPI_CLOCK_16MHz (SPI_CTAR_PBR(1) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(40 / 3) * ((1+1)/2) = 13.33 +#define SPI_CLOCK_12MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0)) //(40 / 2) * ((1+0)/2) = 10 +#define SPI_CLOCK_8MHz (SPI_CTAR_PBR(2) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(40 / 5) * ((1+1)/2) +#define SPI_CLOCK_6MHz (SPI_CTAR_PBR(3) | SPI_CTAR_BR(1) | SPI_CTAR_DBR) //(40 / 7) * ((1+1)/2) = 5.71 +#define SPI_CLOCK_4MHz (SPI_CTAR_PBR(2) | SPI_CTAR_BR(1)) //(40 / 5) * ((1+0)/2) + +#elif F_BUS == 36000000 +#define HAS_SPIFIFO +#define SPI_CLOCK_24MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(36 / 2) * ((1+1)/2) = 18 +#define SPI_CLOCK_16MHz (SPI_CTAR_PBR(1) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(36 / 3) * ((1+1)/2) = 12 +#define SPI_CLOCK_12MHz (SPI_CTAR_PBR(1) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(36 / 3) * ((1+1)/2) = 12 +#define SPI_CLOCK_8MHz (SPI_CTAR_PBR(2) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(36 / 5) * ((1+1)/2) = 7.2 +#define SPI_CLOCK_6MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(2) | SPI_CTAR_DBR) //(36 / 2) * ((1+1)/6) +#define SPI_CLOCK_4MHz (SPI_CTAR_PBR(1) | SPI_CTAR_BR(2) | SPI_CTAR_DBR) //(36 / 3) * ((1+1)/6) + +#elif F_BUS == 24000000 +#define HAS_SPIFIFO +#define SPI_CLOCK_24MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(24 / 2) * ((1+1)/2) 12 MHz +#define SPI_CLOCK_16MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(24 / 2) * ((1+1)/2) 12 MHz +#define SPI_CLOCK_12MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(24 / 2) * ((1+1)/2) +#define SPI_CLOCK_8MHz (SPI_CTAR_PBR(1) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(24 / 3) * ((1+1)/2) +#define SPI_CLOCK_6MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0)) //(24 / 2) * ((1+0)/2) +#define SPI_CLOCK_4MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(2) | SPI_CTAR_DBR) //(24 / 2) * ((1+1)/6) + +#elif F_BUS == 16000000 +#define HAS_SPIFIFO +#define SPI_CLOCK_24MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(3) | SPI_CTAR_DBR) //(16 / 2) * ((1+1)/8) = 2 MHz +#define SPI_CLOCK_16MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(3) | SPI_CTAR_DBR) //(16 / 2) * ((1+1)/8) = 2 MHz +#define SPI_CLOCK_12MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(3) | SPI_CTAR_DBR) //(16 / 2) * ((1+1)/8) = 2 MHz +#define SPI_CLOCK_8MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(3) | SPI_CTAR_DBR) //(16 / 2) * ((1+1)/8) = 2 MHz +#define SPI_CLOCK_6MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(3) | SPI_CTAR_DBR) //(16 / 2) * ((1+1)/8) = 2 MHz +#define SPI_CLOCK_4MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(3) | SPI_CTAR_DBR) //(16 / 2) * ((1+1)/8) = 2 MHz + +#elif F_BUS == 8000000 +#define HAS_SPIFIFO +#define SPI_CLOCK_24MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(1) | SPI_CTAR_DBR) //(8 / 2) * ((1+1)/4) = 2 MHz +#define SPI_CLOCK_16MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(1) | SPI_CTAR_DBR) //(8 / 2) * ((1+1)/4) = 2 MHz +#define SPI_CLOCK_12MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(1) | SPI_CTAR_DBR) //(8 / 2) * ((1+1)/4) = 2 MHz +#define SPI_CLOCK_8MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(1) | SPI_CTAR_DBR) //(8 / 2) * ((1+1)/4) = 2 MHz +#define SPI_CLOCK_6MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(1) | SPI_CTAR_DBR) //(8 / 2) * ((1+1)/4) = 2 MHz +#define SPI_CLOCK_4MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(1) | SPI_CTAR_DBR) //(8 / 2) * ((1+1)/4) = 2 MHz + +#elif F_BUS == 4000000 +#define HAS_SPIFIFO +#define SPI_CLOCK_24MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(4 / 2) * ((1+1)/2) = 2 MHz +#define SPI_CLOCK_16MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(4 / 2) * ((1+1)/2) = 2 MHz +#define SPI_CLOCK_12MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(4 / 2) * ((1+1)/2) = 2 MHz +#define SPI_CLOCK_8MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(4 / 2) * ((1+1)/2) = 2 MHz +#define SPI_CLOCK_6MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(4 / 2) * ((1+1)/2) = 2 MHz +#define SPI_CLOCK_4MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(4 / 2) * ((1+1)/2) = 2 MHz + +#elif F_BUS == 2000000 +#define HAS_SPIFIFO +#define SPI_CLOCK_24MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(4 / 2) * ((1+1)/2) = 1 MHz +#define SPI_CLOCK_16MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(4 / 2) * ((1+1)/2) = 1 MHz +#define SPI_CLOCK_12MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(4 / 2) * ((1+1)/2) = 1 MHz +#define SPI_CLOCK_8MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(4 / 2) * ((1+1)/2) = 1 MHz +#define SPI_CLOCK_6MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(4 / 2) * ((1+1)/2) = 1 MHz +#define SPI_CLOCK_4MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(4 / 2) * ((1+1)/2) = 1 MHz + +#endif // F_BUS + +#endif // KINETISK + +#ifdef HAS_SPIFIFO + +#ifndef SPI_MODE0 +#define SPI_MODE0 0x00 // CPOL = 0, CPHA = 0 +#define SPI_MODE1 0x04 // CPOL = 0, CPHA = 1 +#define SPI_MODE2 0x08 // CPOL = 1, CPHA = 0 +#define SPI_MODE3 0x0C // CPOL = 1, CPHA = 1 +#endif + +#define SPI_CONTINUE 1 + + + +class SPIFIFOclass +{ +public: + inline void begin(uint8_t pin, uint32_t speed, uint32_t mode=SPI_MODE0) __attribute__((always_inline)) { + uint32_t p, ctar = speed; + SIM_SCGC6 |= SIM_SCGC6_SPI0; + + KINETISK_SPI0.MCR = SPI_MCR_MSTR | SPI_MCR_MDIS | SPI_MCR_HALT | SPI_MCR_PCSIS(0x1F); + if (mode & 0x08) ctar |= SPI_CTAR_CPOL; + if (mode & 0x04) { + ctar |= SPI_CTAR_CPHA; + ctar |= (ctar & 0x0F) << 8; + } else { + ctar |= (ctar & 0x0F) << 12; + } + KINETISK_SPI0.CTAR0 = ctar | SPI_CTAR_FMSZ(7); + KINETISK_SPI0.CTAR1 = ctar | SPI_CTAR_FMSZ(15); + if (pin == 10) { // PTC4 + CORE_PIN10_CONFIG = PORT_PCR_MUX(2); + p = 0x01; + } else if (pin == 2) { // PTD0 + CORE_PIN2_CONFIG = PORT_PCR_MUX(2); + p = 0x01; + } else if (pin == 9) { // PTC3 + CORE_PIN9_CONFIG = PORT_PCR_MUX(2); + p = 0x02; + } else if (pin == 6) { // PTD4 + CORE_PIN6_CONFIG = PORT_PCR_MUX(2); + p = 0x02; + } else if (pin == 20) { // PTD5 + CORE_PIN20_CONFIG = PORT_PCR_MUX(2); + p = 0x04; + } else if (pin == 23) { // PTC2 + CORE_PIN23_CONFIG = PORT_PCR_MUX(2); + p = 0x04; + } else if (pin == 21) { // PTD6 + CORE_PIN21_CONFIG = PORT_PCR_MUX(2); + p = 0x08; + } else if (pin == 22) { // PTC1 + CORE_PIN22_CONFIG = PORT_PCR_MUX(2); + p = 0x08; + } else if (pin == 15) { // PTC0 + CORE_PIN15_CONFIG = PORT_PCR_MUX(2); + p = 0x10; +#if defined(__MK64FX512__) || defined(__MK66FX1M0__) + } else if (pin == 26) { + CORE_PIN26_CONFIG = PORT_PCR_MUX(2); + p = 0x01; +#endif + } else { + reg = portOutputRegister(pin); + pinMode(pin, OUTPUT); + *reg = 1; + p = 0; + } + pcs = p; + clear(); + SPCR.enable_pins(); + } + inline void write(uint32_t b, uint32_t cont=0) __attribute__((always_inline)) { + uint32_t pcsbits = pcs << 16; + if (pcsbits) { + KINETISK_SPI0.PUSHR = (b & 0xFF) | pcsbits | (cont ? SPI_PUSHR_CONT : 0); + while (((KINETISK_SPI0.SR) & (15 << 12)) > (3 << 12)) ; // wait if FIFO full + } else { + *reg = 0; + KINETISK_SPI0.SR = SPI_SR_EOQF; + KINETISK_SPI0.PUSHR = (b & 0xFF) | (cont ? 0 : SPI_PUSHR_EOQ); + if (cont) { + while (((KINETISK_SPI0.SR) & (15 << 12)) > (3 << 12)) ; + } else { + while (!(KINETISK_SPI0.SR & SPI_SR_EOQF)) ; + *reg = 1; + } + } + } + inline void write16(uint32_t b, uint32_t cont=0) __attribute__((always_inline)) { + uint32_t pcsbits = pcs << 16; + if (pcsbits) { + KINETISK_SPI0.PUSHR = (b & 0xFFFF) | (pcs << 16) | + (cont ? SPI_PUSHR_CONT : 0) | SPI_PUSHR_CTAS(1); + while (((KINETISK_SPI0.SR) & (15 << 12)) > (3 << 12)) ; + } else { + *reg = 0; + KINETISK_SPI0.SR = SPI_SR_EOQF; + KINETISK_SPI0.PUSHR = (b & 0xFFFF) | (cont ? 0 : SPI_PUSHR_EOQ) | SPI_PUSHR_CTAS(1); + if (cont) { + while (((KINETISK_SPI0.SR) & (15 << 12)) > (3 << 12)) ; + } else { + while (!(KINETISK_SPI0.SR & SPI_SR_EOQF)) ; + *reg = 1; + } + } + } + inline uint32_t read(void) __attribute__((always_inline)) { + while ((KINETISK_SPI0.SR & (15 << 4)) == 0) ; // TODO, could wait forever + return KINETISK_SPI0.POPR; + } + inline void clear(void) __attribute__((always_inline)) { + KINETISK_SPI0.MCR = SPI_MCR_MSTR | SPI_MCR_PCSIS(0x1F) | SPI_MCR_CLR_TXF | SPI_MCR_CLR_RXF; + } +private: + static uint8_t pcs; + static volatile uint8_t *reg; +}; +extern SPIFIFOclass SPIFIFO; + +#endif // HAS_SPIFIFO + +#endif From 4006f99b903a725ca6576de15f14d38ee561c22d Mon Sep 17 00:00:00 2001 From: mxmxmx Date: Sat, 3 Mar 2018 10:15:23 +0100 Subject: [PATCH 16/16] [OC] bump version --- 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 eea3f3db..2a7577a8 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.4a" +#define OC_VERSION "v1.3.4" #endif