Skip to content

Commit

Permalink
Merge branch '1.1.2'
Browse files Browse the repository at this point in the history
  • Loading branch information
patrickdowling committed Oct 12, 2016
2 parents 26c7691 + a7060eb commit a16b026
Show file tree
Hide file tree
Showing 39 changed files with 313 additions and 91 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
bin
software/test/build
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "software/test/gtest"]
path = software/test/gtest
url = https://github.com/google/googletest
22 changes: 11 additions & 11 deletions B_O_M.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
#/* BOM for O+C (rev 2d) */
#/* BOM for O+C (rev 2d, 2e) */

- if your board is **red** and labelled **rev.2d** (on top of the board, underneath the 'ornament and crime' label), that's rev 2d. previous versions differ only slightly. see the [build guide](https://github.com/mxmxmx/O_C/wiki/build-it#bill-of-materials-bom) for details.
- if your board is **red** and labelled **rev.2e** (on top of the board, underneath the 'ornament and crime' label), that's rev 2e. previous versions differ only slightly. see the [build guide](https://github.com/mxmxmx/O_C/wiki/build-it#bill-of-materials-bom) for details.

- the footprint for passives is **0805 throughout**. using 0603 everywhere will work just as fine, of course.

- there's five 3-pin pads for trimpots (input/output calibration): **simply omit the trimpots**; the calibration can be done entirely in software. use five **jumper wires** instead and, ideally, **0.1% resistors** for the output stage (the "wiki" has more details): it's cheaper and makes calibration easier.
- versions prior to 2e: there's five 3-pin pads for trimpots (input/output calibration): **simply omit the trimpots**; the calibration can be done entirely in software. use five **jumper wires** instead and, ideally, **0.1% resistors** for the output stage (the "wiki" has more details): it's cheaper and makes calibration easier.


### SMD resistors (0805):
Expand All @@ -15,18 +15,18 @@
| 510R | 2x | e.g. mouser # 603-RC0805JR-07510RL | 1-5% |
| 2k | 1x | e.g. mouser # 660-RK73H2ATTE2001F | 1% |
| 10k | 1x | e.g. mouser # 660-RK73H2ATTD1002F | 1-5% |
| **24k9** | 4x | e.g. mouser # 756-PCF0805R-24K9BT1 | **0.1%** (‡)|
| **24k9** | 4x | e.g. mouser # 756-PCF0805R-24K9BT1 | **0.1%** |
| 33k | 8x | e.g. mouser # 660-RK73H2ATTD3302F | 1% |
| 47k | 2x | e.g. mouser # 660-RK73H2ATTD4702F | 1% |
| **75k** | 4x | e.g. mouser # 660-RK73H2ATTD7502F | 1% (silkscreen says 49k9: ignore) |
| 75k | 4x | e.g. mouser # 660-RK73H2ATTD7502F | 1% |
| **100k** | 4x | e.g. mouser # 279-CPF0805B100KE | **0.1%** |
| 100k | 8x | e.g. mouser # 660-RK73H2ATTD1003F| 1% (or simply get 12 x 0.1%) |

### SMD caps (0805) (25V or better):
| value | #| type | note |
| --- | ---: | :---: | --- |
| 18p-22p | 4x | **C0G/NP0** (!) | e.g. mouser # 77-VJ0805A220GXAPBC |
| 10n | 4x | C0G/NP0 | e.g. mouser # 603-CC805JRNPO9BN103 |
| 18p-22p | 4x | **C0G/NP0** (!) | e.g. mouser # 77-VJ0805A180GXACBC|
| 560p | 4x | C0G/NP0 | e.g. mouser # 77-VJ0805A561JXAAC |
| 100n | 12x | ceramic | e.g. mouser # 80-C0805C104K5R |
| 470n | 3x | ceramic | e.g. mouser # 77-VJ0805Y474JXJTBC |
| 1u | 2x | ceramic | e.g. mouser # 581-08055C105K4Z2A |
Expand Down Expand Up @@ -54,11 +54,11 @@
| 22uF cap | 2x | RM2.5 (35V or better) | e.g. mouser # 647-UPM1V220MDD1TD |
| inductor | 1x | 10uH | e.g. mouser # 542-78F100-RC |
| jacks | 12x | 'thonkiconn' (or kobiconn) | [PJ301M-12](https://www.thonk.co.uk/shop/3-5mm-jacks/) |
| encoders | 2x | 24 steps w/ switch | e.g. PEC11R-4215K-S0024 (†) |
| encoders | 2x | 24 steps w/ switch | e.g. mouser # 652-PEC11R-4220F-S24 (†) |
| 2x5 pin header | 1x | 2.54mm (euro power connector) | e.g. mouser # 649-67996-410HLF |
| 1x7 (1x8) OLED socket | 1x | 2.54mm, **low profile** ! | e.g mouser # 517-929870-01-08-RA |
| 1x14 socket | 2x | 2.54mm, socket for teensy 3.x | see note (††) |
| 1x14 pin header (to match) | 2x | 2.54mm, header for teensy 3.x | - |
| 1x7 OLED socket | 1x | 2.54mm, **low profile** !, w/ standard square holes | e.g mouser # 517-929870-01-07-RA |
| 1x14 socket | 2x | 2.54mm, socket for teensy 3.x | w/ round holes, see note (††) |
| 1x14 pin header **(to match)** | 2x | 2.54mm, header for teensy 3.x | - |
| tact switches | 2x | multimecs 5E/5G | mouser #: 642-5GTH935 (†††) |
| + caps | 2x | multimecs 1SS09-15.0 or -16.0 | mouser #: 642-1SS09-15.0, or -16.0 |
| 3mm spacer | 1x | ∅ 3M, 10mm | - |
Expand Down
Binary file removed hardware/O_C_blank.fpd
Binary file not shown.
Binary file modified hardware/O_C_blank_spacer.fpd
Binary file not shown.
12 changes: 6 additions & 6 deletions hardware/O_C_blank_spacer.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file not shown.
Binary file removed hardware/gerbers/ornament2016_2d.zip
Binary file not shown.
Binary file added hardware/gerbers/ornament_2e.zip
Binary file not shown.
Binary file removed hardware/o_c_rev2d_schematic.pdf
Binary file not shown.
Binary file added hardware/o_c_rev2e_schematic.pdf
Binary file not shown.
6 changes: 3 additions & 3 deletions hardware/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ hardware files for o_C quad 16 bit CV generator/processor

- .fpd (= front panel express).
- .svg (= same thing, exported from frontDesign).
- NB: the ones ending in "_spacer" include a/the additional mounting hole (3mm). (recommended, but not über-important)
- /fpd_nearlyghost: .fpd, w/ graphics by nearly_ghost

###schematic

- rev 2.d
- (rev 2.c is basically identical)
- rev 2.e
- (rev 2.c, 2.d are basically identical)

### ... gerbers for:

Expand Down
2 changes: 1 addition & 1 deletion software/o_c_REV/OC_DAC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
*
*/

#include <spififo.h>
#include <SPIFIFO.h>
#include "OC_DAC.h"
#include "OC_gpio.h"

Expand Down
7 changes: 6 additions & 1 deletion software/o_c_REV/OC_calibration.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ struct CalibrationData {

uint8_t display_offset;
uint32_t flags;
uint32_t reserved0;
uint8_t screensaver_timeout; // 0: default, else seconds
uint8_t reserved0[3];
uint32_t reserved1;

EncoderConfig encoder_config() const {
Expand All @@ -56,6 +57,10 @@ struct CalibrationData {
}
};

static_assert(sizeof(DAC::CalibrationData) == 88, "DAC::CalibrationData size changed!");
static_assert(sizeof(ADC::CalibrationData) == 12, "ADC::CalibrationData size changed!");
static_assert(sizeof(CalibrationData) == 116, "Calibration data size changed!");

typedef PageStorage<EEPROMStorage, EEPROM_CALIBRATIONDATA_START, EEPROM_CALIBRATIONDATA_END, CalibrationData> CalibrationStorage;

extern CalibrationData calibration_data;
Expand Down
71 changes: 59 additions & 12 deletions software/o_c_REV/OC_calibration.ino
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ CalibrationData calibration_data;
};

static constexpr unsigned kCalibrationAdcSmoothing = 4;
bool calibration_data_loaded = false;

const OC::CalibrationData kCalibrationDefaults = {
// DAC
Expand All @@ -36,7 +37,8 @@ const OC::CalibrationData kCalibrationDefaults = {
// display_offset
SH1106_128x64_Driver::kDefaultOffset,
OC_CALIBRATION_DEFAULT_FLAGS,
0, 0 // reserved
SCREENSAVER_TIMEOUT_S, { 0, 0, 0 },
0 // reserved
};
//const uint16_t THEORY[OCTAVES+1] = {0, 6553, 13107, 19661, 26214, 32768, 39321, 45875, 52428, 58981, 65535}; // in theory

Expand All @@ -55,7 +57,8 @@ void calibration_load() {
OC::CalibrationStorage::PAGESIZE, OC::CalibrationStorage::PAGES, OC::CalibrationStorage::LENGTH);

calibration_reset();
if (!OC::calibration_storage.Load(OC::calibration_data)) {
calibration_data_loaded = OC::calibration_storage.Load(OC::calibration_data);
if (!calibration_data_loaded) {
#ifdef CALIBRATION_LOAD_LEGACY
if (EEPROM.read(0x2) > 0) {
SERIAL_PRINTLN("Calibration not loaded, non-zero data found, trying to import...");
Expand All @@ -75,6 +78,9 @@ void calibration_load() {
SERIAL_PRINTLN("NOTE: Pitch CV scale not set, using default...");
OC::calibration_data.adc.pitch_cv_scale = OC::ADC::kDefaultPitchCVScale;
}

if (!OC::calibration_data.screensaver_timeout)
OC::calibration_data.screensaver_timeout = SCREENSAVER_TIMEOUT_S;
}

void calibration_save() {
Expand All @@ -94,6 +100,7 @@ enum CALIBRATION_STEP {
CV_OFFSET,
CV_OFFSET_0, CV_OFFSET_1, CV_OFFSET_2, CV_OFFSET_3,
ADC_PITCH_C2, ADC_PITCH_C4,
CALIBRATION_SCREENSAVER_TIMEOUT,
CALIBRATION_EXIT,
CALIBRATION_STEP_LAST,
CALIBRATION_STEP_FINAL = ADC_PITCH_C4
Expand All @@ -106,7 +113,8 @@ enum CALIBRATION_TYPE {
CALIBRATE_ADC_OFFSET,
CALIBRATE_ADC_1V,
CALIBRATE_ADC_3V,
CALIBRATE_DISPLAY
CALIBRATE_DISPLAY,
CALIBRATE_SCREENSAVER,
};

struct CalibrationStep {
Expand Down Expand Up @@ -139,6 +147,8 @@ struct CalibrationState {

uint16_t adc_1v;
uint16_t adc_3v;

bool used_defaults;
};

OC::DigitalInputDisplay digital_input_displays[4];
Expand Down Expand Up @@ -198,7 +208,7 @@ const CalibrationStep calibration_steps[CALIBRATION_STEP_LAST] = {
{ DAC_D_VOLT_5, "DAC D 5 volts", "-> 5.000V ", default_help_r, default_footer, CALIBRATE_OCTAVE, 5, nullptr, 0, DAC::MAX_VALUE },
{ DAC_D_VOLT_6, "DAC D 6 volts", "-> 6.000V ", default_help_r, default_footer, CALIBRATE_OCTAVE, 6, nullptr, 0, DAC::MAX_VALUE },

{ CV_OFFSET, "CV offset", "", "Adjust CV trimpot", default_footer, CALIBRATE_ADC_TRIMMER, 0, nullptr, 0, 4095 },
{ CV_OFFSET, "CV offset (optional)", "", "Use CV trimmer/skip", default_footer, CALIBRATE_ADC_TRIMMER, 0, nullptr, 0, 4095 },
{ CV_OFFSET_0, "ADC CV1", "ADC value at 0V", default_help_r, default_footer, CALIBRATE_ADC_OFFSET, ADC_CHANNEL_1, nullptr, 0, 4095 },
{ CV_OFFSET_1, "ADC CV2", "ADC value at 0V", default_help_r, default_footer, CALIBRATE_ADC_OFFSET, ADC_CHANNEL_2, nullptr, 0, 4095 },
{ CV_OFFSET_2, "ADC CV3", "ADC value at 0V", default_help_r, default_footer, CALIBRATE_ADC_OFFSET, ADC_CHANNEL_3, nullptr, 0, 4095 },
Expand All @@ -207,6 +217,8 @@ const CalibrationStep calibration_steps[CALIBRATION_STEP_LAST] = {
{ ADC_PITCH_C2, "CV Scaling 1V", "CV1: Input 1V (C2)", "[R] Long press to set", default_footer, CALIBRATE_ADC_1V, 0, nullptr, 0, 0 },
{ ADC_PITCH_C4, "CV Scaling 3V", "CV1: Input 3V (C4)", "[R] Long press to set", default_footer, CALIBRATE_ADC_3V, 0, nullptr, 0, 0 },

{ CALIBRATION_SCREENSAVER_TIMEOUT, "Screensaver", "Timeout (s)", default_help_r, default_footer, CALIBRATE_SCREENSAVER, 0, nullptr, (OC::Ui::kLongPressTicks * 2 + 500) / 1000, SCREENSAVER_TIMEOUT_MAX_S },

{ CALIBRATION_EXIT, "Calibration complete", "Save values? ", select_help, end_footer, CALIBRATE_NONE, 0, OC::Strings::no_yes, 0, 1 }
};

Expand All @@ -219,9 +231,10 @@ void OC::Ui::Calibrate() {
CalibrationState calibration_state = {
HELLO,
&calibration_steps[HELLO],
1,
calibration_data_loaded ? 0 : 1, // "use defaults: no" if data loaded
};
calibration_state.adc_sum.set(_ADC_OFFSET);
calibration_state.used_defaults = false;

for (auto &did : digital_input_displays)
did.Init();
Expand Down Expand Up @@ -295,6 +308,7 @@ void OC::Ui::Calibrate() {
if (calibration_state.encoder_value) {
SERIAL_PRINTLN("Resetting to defaults...");
calibration_reset();
calibration_state.used_defaults = true;
}
break;
case ADC_PITCH_C4:
Expand Down Expand Up @@ -330,12 +344,24 @@ void OC::Ui::Calibrate() {
SERIAL_PRINTLN("offset=%d", OC::calibration_data.adc.offset[ADC_CHANNEL_1]);
break;

case CALIBRATE_SCREENSAVER:
calibration_state.encoder_value = OC::calibration_data.screensaver_timeout;
SERIAL_PRINTLN("timeout=%d", calibration_state.encoder_value);
break;

case CALIBRATE_NONE:
default:
if (CALIBRATION_EXIT != next_step->step)
if (CALIBRATION_EXIT != next_step->step) {
calibration_state.encoder_value = 0;
else
calibration_state.encoder_value = 1;
} else {
// Make the default "Save: no" if the calibration data was reset
// manually, but only if calibration data was actually loaded from
// EEPROM
if (calibration_state.used_defaults && calibration_data_loaded)
calibration_state.encoder_value = 0;
else
calibration_state.encoder_value = 1;
}
}
calibration_state.current_step = next_step;
}
Expand Down Expand Up @@ -366,6 +392,7 @@ void calibration_draw(const CalibrationState &state) {
graphics.setPrintPos(menu::kIndentDx, y + 2);
switch (step->calibration_type) {
case CALIBRATE_OCTAVE:
case CALIBRATE_SCREENSAVER:
graphics.print(step->message);
graphics.setPrintPos(kValueX, y + 2);
graphics.print((int)state.encoder_value, 5);
Expand Down Expand Up @@ -404,10 +431,26 @@ void calibration_draw(const CalibrationState &state) {

case CALIBRATE_NONE:
default:
graphics.setPrintPos(menu::kIndentDx, y + 2);
graphics.print(step->message);
if (step->value_str)
graphics.print(step->value_str[state.encoder_value]);
if (CALIBRATION_EXIT != step->step) {
graphics.setPrintPos(menu::kIndentDx, y + 2);
graphics.print(step->message);
if (step->value_str)
graphics.print(step->value_str[state.encoder_value]);
} else {
graphics.setPrintPos(menu::kIndentDx, y + 2);
if (calibration_data_loaded && state.used_defaults)
graphics.print("Overwrite? ");
else
graphics.print("Save? ");
if (step->value_str)
graphics.print(step->value_str[state.encoder_value]);

if (state.used_defaults && calibration_data_loaded) {
y += menu::kMenuLineH;
graphics.setPrintPos(menu::kIndentDx, y + 2);
graphics.print("NB replaces existing!");
}
}
break;
}

Expand Down Expand Up @@ -467,6 +510,10 @@ void calibration_update(CalibrationState &state) {
OC::calibration_data.display_offset = state.encoder_value;
display::AdjustOffset(OC::calibration_data.display_offset);
break;
case CALIBRATE_SCREENSAVER:
DAC::set_all_octave(0);
OC::calibration_data.screensaver_timeout = state.encoder_value;
break;
}
}

Expand Down
10 changes: 7 additions & 3 deletions software/o_c_REV/OC_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,15 @@ static constexpr uint32_t OC_CORE_ISR_FREQ = 16666U;
static constexpr uint32_t OC_CORE_TIMER_RATE = (1000000UL / OC_CORE_ISR_FREQ);
static constexpr uint32_t OC_UI_TIMER_RATE = 1000UL;

static constexpr int OC_CORE_TIMER_PRIO = 128; // default?
static constexpr int OC_UI_TIMER_PRIO = 132; // lower
// From kinetis.h
// Cortex-M4: 0,16,32,48,64,80,96,112,128,144,160,176,192,208,224,240
static constexpr int OC_CORE_TIMER_PRIO = 112; // higher
static constexpr int OC_GPIO_ISR_PRIO = 128; // default
static constexpr int OC_UI_TIMER_PRIO = 144; // lower

static constexpr unsigned long REDRAW_TIMEOUT_MS = 1;
static constexpr unsigned long SCREENSAVER_TIMEOUT_MS = 25000; // time out menu (in ms)
static constexpr uint32_t SCREENSAVER_TIMEOUT_S = 25; // default time out menu (in s)
static constexpr uint32_t SCREENSAVER_TIMEOUT_MAX_S = 120;

namespace OC {
static constexpr size_t kMaxTriggerDelayTicks = 96;
Expand Down
2 changes: 1 addition & 1 deletion software/o_c_REV/OC_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#include <stdint.h>
#include "OC_config.h"
#include "util/util_debugpins.h"
#include "drivers/display.h"
#include "src/drivers/display.h"

namespace OC {
namespace CORE {
Expand Down
30 changes: 30 additions & 0 deletions software/o_c_REV/OC_digital_inputs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
#include "OC_digital_inputs.h"
#include "OC_gpio.h"

/*static*/
uint32_t OC::DigitalInputs::clocked_mask_;

/*static*/
volatile uint32_t OC::DigitalInputs::clocked_[DIGITAL_INPUT_LAST];

Expand Down Expand Up @@ -40,5 +43,32 @@ void OC::DigitalInputs::Init() {
attachInterrupt(pin.pin, pin.isr_fn, FALLING);
}

clocked_mask_ = 0;
std::fill(clocked_, clocked_ + DIGITAL_INPUT_LAST, 0);

// Assume the priority of pin change interrupts is lower or equal to the
// thread where ::Scan function is called. Otherwise a safer mechanism is
// required to avoid conflicts (LDREX/STREX or store ARM_DWT_CYCCNT in the
// array to check for changes.
//
// A really nice approach would be to use the FTM timer mechanism and avoid
// the ISR altogether, but this only works for one of the pins. Using more
// explicit interrupt grouping might also improve the handling a bit (if
// implemented on the DX)
//
// It's still not guaranteed that 4 simultaneous triggers will be handled
// exactly simultaneously though, but that's micro-timing dependent even if
// the pins have higher prio.

// NVIC_SET_PRIORITY(IRQ_PORTB, 0); // TR1 = 0 = PTB16
// Defaults is 0, or set OC_GPIO_ISR_PRIO for all ports
}

/*static*/
void OC::DigitalInputs::Scan() {
clocked_mask_ =
ScanInput<DIGITAL_INPUT_1>() |
ScanInput<DIGITAL_INPUT_2>() |
ScanInput<DIGITAL_INPUT_3>() |
ScanInput<DIGITAL_INPUT_4>();
}
Loading

0 comments on commit a16b026

Please sign in to comment.