Files
-
blinds / hardware_design / pcb / blinds_v60.brd
-
blinds / hardware_design / pcb / blinds_v60.sch
-
braids / hardware_design / pcb / braids_v50.brd
-
braids / hardware_design / pcb / braids_v50.sch
-
branches / hardware_design / pcb / branches_v40.brd
-
branches / hardware_design / pcb / branches_v40.sch
-
clouds / hardware_design / pcb / clouds_v30.brd
-
clouds / hardware_design / pcb / clouds_v30.sch
-
ears / hardware_design / panel / ears_panel_v30.brd
-
ears / hardware_design / panel / ears_panel_v30.sch
-
ears / hardware_design / pcb / ears_v40.brd
-
ears / hardware_design / pcb / ears_v40.sch
-
edges / hardware_design / pcb / edges_expander_v01.brd
-
edges / hardware_design / pcb / edges_expander_v01.sch
-
edges / hardware_design / pcb / edges_v20.brd
-
edges / hardware_design / pcb / edges_v20.sch
-
elements / hardware_design / pcb / elements_v02.brd
-
elements / hardware_design / pcb / elements_v02.sch
-
frames / hardware_design / pcb / frames_v03.brd
-
frames / hardware_design / pcb / frames_v03.sch
-
grids / hardware_design / pcb / grids_v02.brd
-
grids / hardware_design / pcb / grids_v02.sch
-
kinks / hardware_design / pcb / kinks_v41.brd
-
kinks / hardware_design / pcb / kinks_v41.sch
-
links / hardware_design / pcb / links_v40.brd
-
links / hardware_design / pcb / links_v40.sch
-
marbles / hardware_design / pcb / marbles_v70.brd
-
marbles / hardware_design / pcb / marbles_v70.sch
-
peaks / hardware_design / pcb / peaks_v30.brd
-
peaks / hardware_design / pcb / peaks_v30.sch
-
plaits / hardware_design / pcb / plaits_v50.brd
-
plaits / hardware_design / pcb / plaits_v50.sch
-
rings / hardware_design / pcb / rings_v30.brd
-
rings / hardware_design / pcb / rings_v30.sch
-
ripples / hardware_design / pcb / ripples_v40.brd
-
ripples / hardware_design / pcb / ripples_v40.sch
-
shades / hardware_design / pcb / shades_v30.brd
-
shades / hardware_design / pcb / shades_v30.sch
-
shelves / hardware_design / pcb / shelves_expander_v10.brd
-
shelves / hardware_design / pcb / shelves_expander_v10.sch
-
shelves / hardware_design / pcb / shelves_v05.brd
-
shelves / hardware_design / pcb / shelves_v05.sch
-
stages / hardware_design / pcb / stages_v70.brd
-
stages / hardware_design / pcb / stages_v70.sch
-
streams / hardware_design / pcb / streams_v02_bargraph.brd
-
streams / hardware_design / pcb / streams_v02_bargraph.sch
-
streams / hardware_design / pcb / streams_v05.brd
-
streams / hardware_design / pcb / streams_v05.sch
-
tides / hardware_design / pcb / tides_v40.brd
-
tides / hardware_design / pcb / tides_v40.sch
-
veils / hardware_design / pcb / veils_v40.brd
-
veils / hardware_design / pcb / veils_v40.sch
-
volts / hardware_design / pcb / volts_v01.brd
-
volts / hardware_design / pcb / volts_v01.sch
-
warps / hardware_design / pcb / warps_v30.brd
-
warps / hardware_design / pcb / warps_v30.sch
-
yarns / hardware_design / pcb / yarns_v03.brd
-
yarns / hardware_design / pcb / yarns_v03.sch
Last update 6 years 1 month
by
Olivier Gillet
Filesgrids | |
---|---|
.. | |
bootloader | |
hardware_design | |
resources | |
__init__.py | |
clock.cc | |
clock.h | |
grids.cc | |
hardware_config.h | |
makefile | |
pattern_generator.cc | |
pattern_generator.h | |
resources.cc | |
resources.h |
pattern_generator.h// Copyright 2011 Olivier Gillet. // // Author: Olivier Gillet (ol.gillet@gmail.com) // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. // // ----------------------------------------------------------------------------- // // Pattern generator. // // OUTPUT MODE OUTPUT CLOCK BIT7 BIT6 BIT5 BIT4 BIT3 BIT2 BIT1 BIT0 // DRUMS FALSE RND CLK HHAC SDAC BDAC HH SD BD // DRUMS TRUE RND CLK CLK BAR ACC HH SD BD // EUCLIDEAN FALSE RND CLK RST3 RST2 RST1 EUC3 EUC2 EUC1 // EUCLIDEAN TRUE RND CLK CLK STEP RST EUC3 EUC2 EUC1 #ifndef GRIDS_PATTERN_GENERATOR_H_ #define GRIDS_PATTERN_GENERATOR_H_ #include <string.h> #include "avrlib/base.h" #include "avrlib/random.h" #include "grids/hardware_config.h" namespace grids { const uint8_t kNumParts = 3; const uint8_t kPulsesPerStep = 3; // 24 ppqn ; 8 steps per quarter note. const uint8_t kStepsPerPattern = 32; const uint8_t kPulseDuration = 8; // 8 ticks of the main clock. struct DrumsSettings { uint8_t x; uint8_t y; uint8_t randomness; }; struct PatternGeneratorSettings { union Options { DrumsSettings drums; uint8_t euclidean_length[kNumParts]; } options; uint8_t density[kNumParts]; }; enum OutputMode { OUTPUT_MODE_EUCLIDEAN, OUTPUT_MODE_DRUMS }; enum ClockResolution { CLOCK_RESOLUTION_4_PPQN, CLOCK_RESOLUTION_8_PPQN, CLOCK_RESOLUTION_24_PPQN, CLOCK_RESOLUTION_LAST }; enum OutputBits { OUTPUT_BIT_COMMON = 0x08, OUTPUT_BIT_CLOCK = 0x10, OUTPUT_BIT_RESET = 0x20 }; struct Options { ClockResolution clock_resolution; OutputMode output_mode; bool output_clock; bool tap_tempo; bool gate_mode; bool swing; uint8_t pack() const { uint8_t byte = clock_resolution; if (!swing) { byte |= 0x08; } if (tap_tempo) { byte |= 0x10; } if (output_clock) { byte |= 0x20; } if (output_mode == OUTPUT_MODE_DRUMS) { byte |= 0x40; } if (!gate_mode) { byte |= 0x80; } return byte; } void unpack(uint8_t byte) { tap_tempo = byte & 0x10; output_clock = byte & 0x20; output_mode = byte & 0x40 ? OUTPUT_MODE_DRUMS : OUTPUT_MODE_EUCLIDEAN; gate_mode = !(byte & 0x80); swing = !(byte & 0x08); clock_resolution = static_cast<ClockResolution>(byte & 0x7); if (clock_resolution >= CLOCK_RESOLUTION_24_PPQN) { clock_resolution = CLOCK_RESOLUTION_24_PPQN; } } }; class PatternGenerator { public: PatternGenerator() { } ~PatternGenerator() { } static inline void Init() { LoadSettings(); Reset(); } static inline void Reset() { step_ = 0; pulse_ = 0; memset(euclidean_step_, 0, sizeof(euclidean_step_)); } static inline void Retrigger() { Evaluate(); } static inline void TickClock(uint8_t num_pulses) { Evaluate(); beat_ = (step_ & 0x7) == 0; first_beat_ = step_ == 0; pulse_ += num_pulses; // Wrap into ppqn steps. while (pulse_ >= kPulsesPerStep) { pulse_ -= kPulsesPerStep; if (!(step_ & 1)) { for (uint8_t i = 0; i < kNumParts; ++i) { ++euclidean_step_[i]; } } ++step_; } // Wrap into step sequence steps. if (step_ >= kStepsPerPattern) { step_ -= kStepsPerPattern; } } static inline uint8_t state() { return state_; } static inline uint8_t step() { return step_; } static inline bool swing() { return options_.swing; } static int8_t swing_amount(); static inline bool output_clock() { return options_.output_clock; } static inline bool tap_tempo() { return options_.tap_tempo; } static inline bool gate_mode() { return options_.gate_mode; } static inline OutputMode output_mode() { return options_.output_mode; } static inline ClockResolution clock_resolution() { return options_.clock_resolution; } static void set_swing(uint8_t value) { options_.swing = value; } static void set_output_clock(uint8_t value) { options_.output_clock = value; } static void set_tap_tempo(uint8_t value) { options_.tap_tempo = value; } static void set_output_mode(uint8_t value) { options_.output_mode = static_cast<OutputMode>(value); } static void set_clock_resolution(uint8_t value) { if (value >= CLOCK_RESOLUTION_24_PPQN) { value = CLOCK_RESOLUTION_24_PPQN; } options_.clock_resolution = static_cast<ClockResolution>(value); } static void set_gate_mode(bool gate_mode) { options_.gate_mode = gate_mode; } static inline void IncrementPulseCounter() { ++pulse_duration_counter_; // Zero all pulses after 1ms. if (pulse_duration_counter_ >= kPulseDuration && !options_.gate_mode) { state_ = 0; // Possible mod: the extra random pulse is not reset, and its behaviour // is more similar to that of a S&H. //state_ &= 0x80; } } static inline void ClockFallingEdge() { if (options_.gate_mode) { state_ = 0; } } static inline PatternGeneratorSettings* mutable_settings() { return &settings_; } static bool on_first_beat() { return first_beat_; } static bool on_beat() { return beat_; } static bool factory_testing() { return factory_testing_ < 5; } static void SaveSettings(); static inline uint8_t led_pattern() { uint8_t result = 0; if (state_ & 1) { result |= LED_BD; } if (state_ & 2) { result |= LED_SD; } if (state_ & 4) { result |= LED_HH; } return result; } private: static void LoadSettings(); static void Evaluate(); static void EvaluateEuclidean(); static void EvaluateDrums(); static uint8_t ReadDrumMap( uint8_t step, uint8_t instrument, uint8_t x, uint8_t y); static Options options_; static uint8_t pulse_; static uint8_t step_; static uint8_t euclidean_step_[kNumParts]; static bool first_beat_; static bool beat_; static uint8_t state_; static uint8_t part_perturbation_[kNumParts]; static uint8_t pulse_duration_counter_; static uint8_t factory_testing_; static PatternGeneratorSettings settings_; DISALLOW_COPY_AND_ASSIGN(PatternGenerator); }; extern PatternGenerator pattern_generator; } // namespace grids #endif // GRIDS_PATTERN_GENERATOR_H_