#include "turing-module.hh" #include namespace rack_plugin_Skylights { const double SEMITONE = 1.0 / 12.0; void turing_module::step() { double mode; if (inputs[I_MODE].active) mode = inputs[I_MODE].value; else mode = params[P_MODE].value; bool hot = m_sequence & 0x1; outputs[O_GATE].value = hot ? 10.0 : 0.0; outputs[O_PULSE].value = min(outputs[O_GATE].value * inputs[I_CLOCK].value, 10.0); // check for clock advance auto was_high = m_clock_trigger.isHigh(); m_clock_trigger.process(inputs[I_CLOCK].value); if (!was_high && was_high != m_clock_trigger.isHigh()) { // clock was advanced // write knob always zeroes our input if (params[P_WRITE].value > 0.9) hot = false; else if (mode > 0.9) { // leave hot alone } else if (mode > 0.55) { // inverts about 13% of the time const size_t TRIES = 3; bool should_flip = true; for (size_t i = 0; i <= TRIES; i++) { should_flip = (should_flip == m_spigot.next()); if (!should_flip) break; } hot = should_flip ? !hot : hot; } else if (mode > 0.10) { // 50/50 invert bool should_invert = m_spigot.next(); hot = should_invert ? !hot : hot; } else { // always invert hot = !hot; } // compute an advance mask based on step length, [2, 16) uint16_t mask = 0; size_t steps = 0; for (double i = 0; i < params[P_LENGTH].value; i += 1) { mask <<= 1; mask |= 0x1; steps++; } uint16_t seq = m_sequence & mask; seq >>= 1; seq |= (hot ? 1 : 0) << (steps - 1); m_sequence &= ~mask; m_sequence += seq; uint8_t signal_d = m_sequence & 0xFF; double signal_a = (((double)signal_d) / 255.0); outputs[O_VOLTAGE].value = (signal_a * params[P_SCALE].value) // signal scaled by scale knob - (5.0 * params[P_POLE].value); // shift to bi-polar on request // expander is always 10v unipolar outputs[O_EXPANSION].value = (((double)m_sequence) / 65535.0) * 10.0; for (size_t i = 0; i < 8; i++) { lights[L_LIGHT8-i].value = ((m_sequence & (1 << i)) > 0) ? 1.0 : 0.0; } } } turing_module::turing_module() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS), m_sequence(0) { } turing_module::~turing_module() { } json_t* turing_module::toJson() { auto map = json_object(); json_object_set_new(map, "sequence", json_integer(m_sequence)); return map; } void turing_module::fromJson(json_t *root) { if (!root) return; auto seqo = json_object_get(root, "sequence"); if (json_is_number(seqo)) { m_sequence = (uint16_t)json_integer_value(seqo); } } void turing_module::onReset() { Module::onReset(); m_sequence = 0; } void turing_module::onRandomize() { Module::onRandomize(); m_sequence = 0; for (size_t i = 0; i < 16; i++) { m_sequence += m_spigot.next() << i; } } } // namespace rack_plugin_Skylights