diff --git a/.gitignore b/.gitignore index 1e3381d2..22903d05 100644 --- a/.gitignore +++ b/.gitignore @@ -53,5 +53,5 @@ __pycache__/ /docs/teletype.pdf /docs/teletype.html /docs/cheatsheet/* -!/docs/cheatsheet/cheatsheet.tex +!/docs/cheatsheet/cs-common.tex /docs/testServe/ diff --git a/CHANGELOG.md b/CHANGELOG.md index 574fc76e..f62371be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,7 @@ - **NEW**: apply VCV Rack compatibility patches, so branches off main can be used in both hardware and software - **FIX**: update Disting EX looper ops to work with Disting EX firmware 1.23+ - **NEW**: new dual W/ ops: `W/.SEL`, `W/S.POLY`, `W/S.POLY.RESET`, `W/1`, `W/2` +- **NEW**: split cheatsheets into separate PDFs for core ops and i2c ## v4.0.0 diff --git a/docs/Makefile b/docs/Makefile index ccecdb26..391c3550 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -1,11 +1,11 @@ .PHONY: build clean -build: teletype.pdf teletype.html cheatsheet/cheatsheet.pdf +build: teletype.pdf teletype.html cheatsheet/cheatsheet.pdf cheatsheet/cheatsheet-i2c.pdf clean: rm -f teletype.pdf && \ rm -f teletype.html && \ - rm -f cheatsheet/include.tex && \ + rm -f cheatsheet/cheatsheet-*.* && \ cd cheatsheet && \ latexmk -xelatex -c && \ rm -f cheatsheet.pdf @@ -18,8 +18,11 @@ teletype.html: $(wildcard *.md ops/*.md ops/*.toml) \ ../utils/docs.py ../CHANGELOG.md $(wildcard ../utils/templates/*) ../utils/docs.py teletype.html -cheatsheet/include.tex: $(wildcard ops/*.toml) ../utils/cheatsheet.py - ../utils/cheatsheet.py "cheatsheet/include.tex" +cheatsheet/cheatsheet-%.tex: $(wildcard ops/*.toml) ../utils/cheatsheet.py + ../utils/cheatsheet.py $* "cheatsheet/cheatsheet-$*.tex" -cheatsheet/cheatsheet.pdf: cheatsheet/cheatsheet.tex cheatsheet/include.tex - cd cheatsheet && latexmk -xelatex cheatsheet.tex +cheatsheet/cheatsheet-%.pdf: cheatsheet/cs-common.tex cheatsheet/cheatsheet-%.tex + cd cheatsheet && latexmk -xelatex cs-common.tex -jobname=cheatsheet-$* + +cheatsheet/cheatsheet.pdf: cheatsheet/cheatsheet-core.pdf + cd cheatsheet && cp cheatsheet-core.pdf cheatsheet.pdf \ No newline at end of file diff --git a/docs/cheatsheet/cheatsheet.tex b/docs/cheatsheet/cs-common.tex similarity index 98% rename from docs/cheatsheet/cheatsheet.tex rename to docs/cheatsheet/cs-common.tex index 4321da00..c02f0377 100644 --- a/docs/cheatsheet/cheatsheet.tex +++ b/docs/cheatsheet/cs-common.tex @@ -59,7 +59,7 @@ \begin{document} \begin{multicols}{5} - \input{include.tex} + \input{\jobname.tex} %% add a page break at the end to force the last column to not balance \pagebreak diff --git a/docs/ops/calibration.md b/docs/ops/calibration.md new file mode 100644 index 00000000..fbf47db6 --- /dev/null +++ b/docs/ops/calibration.md @@ -0,0 +1 @@ +## Calibration \ No newline at end of file diff --git a/docs/ops/calibration.toml b/docs/ops/calibration.toml new file mode 100644 index 00000000..90f241f4 --- /dev/null +++ b/docs/ops/calibration.toml @@ -0,0 +1,93 @@ + +["DEVICE.FLIP"] +prototype = "DEVICE.FLIP" +short = "Flip the screen/inputs/outputs" +description = """ +Flip the screen, the inputs and the outputs. This op is useful if you want to mount your Teletype upside down. +The new state will be saved to flash. +""" + +["IN.CAL.MIN"] +prototype = "IN.CAL.MIN" +short = "Reads the input CV and assigns the voltage to the zero point" +description = """ + 1. Connect a patch cable from a calibrated voltage source + 2. Set the voltage source to 0 volts + 3. Execute IN.CAL.MIN from the live terminal + 4. Call IN and confirm the 0 result +""" + +["IN.CAL.MAX"] +prototype = "IN.CAL.MAX" +short = "Reads the input CV and assigns the voltage to the max point" +description = """ + 5. Set the voltage source to target maximum voltage (10V) + 6. Execute IN.CAL.MAX from the live terminal + 7. Call IN and confirm that the result is 16383 +""" + +["IN.CAL.RESET"] +prototype = "IN.CAL.RESET" +short = "Resets the input CV calibration" + +["PARAM.CAL.MIN"] +prototype = "PARAM.CAL.MIN" +short = "Reads the Parameter Knob minimum position and assigns a zero value" +description = """ + 1. Turn the PARAM knob all the way to the left + 2. Execute PARAM.CAL.MIN from the live terminal + 3. Call PARAM and confirm the 0 result +""" + +["PARAM.CAL.MAX"] +prototype = "PARAM.CAL.MAX" +short = "Reads the Parameter Knob maximum position and assigns the maximum point" +description = """ + 4. Turn the knob all the way to the right + 5. Execute PARAM.CAL.MAX from the live terminal + 6. Call PARAM and verify that the result is 16383 +""" + +["PARAM.CAL.RESET"] +prototype = "PARAM.CAL.RESET" +short = "Resets the Parameter Knob calibration" + +["CV.CAL"] +prototype = "CV.CAL n mv1v mv3v" +short = "Calibrate CV output `n`" +description = """ +Following a short calibration procedure, you can use `CV.CAL` to more +precisely match your CV outputs to each other or to an external reference. A +digital multimeter (or other voltage measuring device) is required. + +To calibrate CV 1, first set it to output one volt with `CV 1 V 1`. Using +a digital multimeter with at least millivolt precision (three digits after +the decimal point), record the measured output of CV 1 between tip and sleeve +on a patch cable. Then set CV 1 to three volts with `CV 1 V 3` and measure +again. + +Once you have both measurements, use the observed 1V and 3V values in +millivolts as the second and third arguments to `CV.CAL`. For example, if you +measured 0.990V and 2.984V, enter `CV.CAL 1 990 2984`. (If both your +measurements are within 1 or 2 millivolts already, there's no need to run +`CV.CAL`.) + +Measure the output with `CV 1 V 1` and `CV 1 V 3` again and confirm the values +are closer to the expected 1.000V and 3.000V. + +Repeat the above steps for CV 2-4, if desired. The calibration data is stored +in flash memory so you only need to go through this process once. + +Note: The calibration adjustment is made after `CV.SLEW` and `CV.OFF` are +applied, and does not affect `CV.GET` or any other scene-visible values. It +only affects the levels coming out of the DAC. +""" + +["CV.CAL.RESET"] +prototype = "CV.CAL.RESET n" +short = "Reset calibration data for CV output `n`" +description = """ +Clear the calibration data for CV output `n` and return it to its default +behavior, with no calibration adjustment. +""" + diff --git a/docs/ops/controlflow.toml b/docs/ops/controlflow.toml index 1ec523b3..d06c82df 100644 --- a/docs/ops/controlflow.toml +++ b/docs/ops/controlflow.toml @@ -398,7 +398,7 @@ Does not affect the CV input (IN) or the Parameter knob (PARAM) values. ["INIT.P"] prototype = "INIT.P x" -short = "clears pattern associated with pattern number x" +short = "clears pattern number x" ["INIT.P.ALL"] prototype = "INIT.P.ALL" @@ -422,7 +422,7 @@ short = "clear time on trigger x" ["INIT.TR"] prototype = "INIT.TR x" -short = "clear all parameters on trigger associated with TR x" +short = "clear all parameters on trigger x" ["INIT.TR.ALL"] prototype = "INIT.TR.ALL" diff --git a/docs/ops/hardware.toml b/docs/ops/hardware.toml index f5a34e6f..9a5c199a 100644 --- a/docs/ops/hardware.toml +++ b/docs/ops/hardware.toml @@ -18,8 +18,8 @@ output `x` to `y`. """ ["CV.SET"] -prototype = "CV.SET x" -short = "Set CV value" +prototype = "CV.SET x y" +short = "Set CV value, ignoring slew" description = """ Set the CV value at output `x` bypassing any slew settings. """ @@ -40,44 +40,13 @@ Get the slew time in ms associated with CV output `x`. Set the slew time associated with CV output `x` to `y` ms. """ -["CV.CAL"] -prototype = "CV.CAL n mv1v mv3v" -short = "Calibrate CV output `n`" -description = """ -Following a short calibration procedure, you can use `CV.CAL` to more -precisely match your CV outputs to each other or to an external reference. A -digital multimeter (or other voltage measuring device) is required. - -To calibrate CV 1, first set it to output one volt with `CV 1 V 1`. Using -a digital multimeter with at least millivolt precision (three digits after -the decimal point), record the measured output of CV 1 between tip and sleeve -on a patch cable. Then set CV 1 to three volts with `CV 1 V 3` and measure -again. - -Once you have both measurements, use the observed 1V and 3V values in -millivolts as the second and third arguments to `CV.CAL`. For example, if you -measured 0.990V and 2.984V, enter `CV.CAL 1 990 2984`. (If both your -measurements are within 1 or 2 millivolts already, there's no need to run -`CV.CAL`.) - -Measure the output with `CV 1 V 1` and `CV 1 V 3` again and confirm the values -are closer to the expected 1.000V and 3.000V. +[V] +prototype = "V x" +short = "converts a voltage to a value usable by the CV outputs (`x` between `0` and `10`)" -Repeat the above steps for CV 2-4, if desired. The calibration data is stored -in flash memory so you only need to go through this process once. - -Note: The calibration adjustment is made after `CV.SLEW` and `CV.OFF` are -applied, and does not affect `CV.GET` or any other scene-visible values. It -only affects the levels coming out of the DAC. -""" - -["CV.CAL.RESET"] -prototype = "CV.CAL.RESET n" -short = "Reset calibration data for CV output `n`" -description = """ -Clear the calibration data for CV output `n` and return it to its default -behavior, with no calibration adjustment. -""" +[VV] +prototype = "VV x" +short = "converts a voltage to a value usable by the CV outputs (`x` between `0` and `1000`, `100` represents 1V)" ["IN"] prototype = "IN" @@ -102,51 +71,6 @@ Get the value of the PARAM knob. This returns a valuue in the range 0-16383. prototype = "PARAM.SCALE min max" short = "Set static scaling of the PARAM knob to between `min` and `max`." -["IN.CAL.MIN"] -prototype = "IN.CAL.MIN" -short = "Reads the input CV and assigns the voltage to the zero point" -description = """ - 1. Connect a patch cable from a calibrated voltage source - 2. Set the voltage source to 0 volts - 3. Execute IN.CAL.MIN from the live terminal - 4. Call IN and confirm the 0 result -""" - -["IN.CAL.MAX"] -prototype = "IN.CAL.MAX" -short = "Reads the input CV and assigns the voltage to the max point" -description = """ - 5. Set the voltage source to target maximum voltage (10V) - 6. Execute IN.CAL.MAX from the live terminal - 7. Call IN and confirm that the result is 16383 -""" - -["IN.CAL.RESET"] -prototype = "IN.CAL.RESET" -short = "Resets the input CV calibration" - -["PARAM.CAL.MIN"] -prototype = "PARAM.CAL.MIN" -short = "Reads the Parameter Knob minimum position and assigns a zero value" -description = """ - 1. Turn the PARAM knob all the way to the left - 2. Execute PARAM.CAL.MIN from the live terminal - 3. Call PARAM and confirm the 0 result -""" - -["PARAM.CAL.MAX"] -prototype = "PARAM.CAL.MAX" -short = "Reads the Parameter Knob maximum position and assigns the maximum point" -description = """ - 4. Turn the knob all the way to the right - 5. Execute PARAM.CAL.MAX from the live terminal - 6. Call PARAM and verify that the result is 16383 -""" - -["PARAM.CAL.RESET"] -prototype = "PARAM.CAL.RESET" -short = "Resets the Parameter Knob calibration" - ["TR"] prototype = "TR x" prototype_set = "TR x y" @@ -156,14 +80,12 @@ Get the current state of trigger output `x`. Set the state of trigger output `x` to `y` (0-1). """ -["TR.POL"] -prototype = "TR.POL x" -prototype_set = "TR.POL x y" -short = "Set polarity of trigger output x to y (0-1)" +["TR.PULSE"] +prototype = "TR.PULSE x" +aliases = ["TR.P"] +short = "Pulse trigger output x" description = """ -Get the current polarity of trigger output `x`. Set the polarity of trigger -output `x` to `y` (0-1). When TR.POL = 1, the pulse is 0 to 1 then back to 0. -When TR.POL = 0, the inverse is true, 1 to 0 to 1. +Pulse trigger output x. """ ["TR.TIME"] @@ -182,12 +104,14 @@ description = """ Flip the state of trigger output `x`. """ -["TR.PULSE"] -prototype = "TR.PULSE x" -aliases = ["TR.P"] -short = "Pulse trigger output x" +["TR.POL"] +prototype = "TR.POL x" +prototype_set = "TR.POL x y" +short = "Set polarity of trigger output x to y (0-1)" description = """ -Pulse trigger output x. +Get the current polarity of trigger output `x`. Set the polarity of trigger +output `x` to `y` (0-1). When TR.POL = 1, the pulse is 0 to 1 then back to 0. +When TR.POL = 0, the inverse is true, 1 to 0 to 1. """ ["MUTE"] @@ -205,14 +129,6 @@ description = """ Read the current state of trigger input `x` (0=low, 1=high). """ -["DEVICE.FLIP"] -prototype = "DEVICE.FLIP" -short = "Flip the screen/inputs/outputs" -description = """ -Flip the screen, the inputs and the outputs. This op is useful if you want to mount your Teletype upside down. -The new state will be saved to flash. -""" - ["LIVE.OFF"] prototype = "LIVE.OFF" aliases = ["LIVE.O"] diff --git a/docs/ops/i2c2midi.toml b/docs/ops/i2c2midi.toml index 7b03a0eb..51d6c033 100644 --- a/docs/ops/i2c2midi.toml +++ b/docs/ops/i2c2midi.toml @@ -418,7 +418,7 @@ Set strumming of chord `x` (0..8) to `x` ms (0..32767). Strumming plays the note ["I2M.C.VCUR"] prototype = "I2M.C.VCUR w x y z" -alias = ["I2M.C.V~"] +aliases = ["I2M.C.V~"] short = "Set velocity curve for chord `w` (0..8) with curve type `x` (0..5), start value `y`% (0..32767) and end value `z`% (0..32767), use `w = 0` to set for all chords, use `x = 0` to turn off" description = """ Set velocity curve for chord `w` (0..8) with curve type `x` (0..5), start value `y`% (0..32767) and end value `z`% (0..32767). This will affect the velocity of the notes in the order they are defined in the chord. Start and end percentages refer to the velocity with which the chord is played via `I2M.C`. Use `x = 0` to turn velocity curve off. The following curves are available: 0) Off 1) Linear 2) Exponential 3) Triangle 4) Square 5) Random. Use `w = 0` to set velocity curve for all chords. Try a random curve with subtle values for a humanizing effect. @@ -426,7 +426,7 @@ Set velocity curve for chord `w` (0..8) with curve type `x` (0..5), start value ["I2M.C.TCUR"] prototype = "I2M.C.TCUR w x y z" -alias = ["I2M.C.T~"] +aliases = ["I2M.C.T~"] short = "Set time curve to strumming for chord `w` (0..8) with curve type `x` (0..5), start value `y`% (0..32767) and end value `z`% (0..32767), use `w = 0` to set for all chords, use `x = 0` to turn off" description = """ Set time curve for chord `w` (0..8) with curve type `x` (0..5), start value `y`% (0..32767) and end value `z`% (0..32767). This will affect the time interval between the notes in the order they are defined in the chord. Start and end percentages refer to the current strumming setting of the chord, set via `I2M.C.STR`. Use `x = 0` to turn time curve off. The following curves are available: 0) Off 1) Linear 2) Exponential 3) Triangle 4) Square 5) Random. Use `w = 0` to set time curve for all chords. Try a square curve with similar values to create swing. Try a random curve with subtle values for a humanizing effect. diff --git a/docs/ops/maths.toml b/docs/ops/maths.toml index 1fd8e50a..0eec7e75 100644 --- a/docs/ops/maths.toml +++ b/docs/ops/maths.toml @@ -24,20 +24,6 @@ prototype = "MOD x y" aliases = ["%"] short = "find the remainder after division of `x` by `y`" -[RAND] -prototype = "RAND x" -aliases = ["RND"] -short = "generate a random number between `0` and `x` inclusive" - -[RRAND] -prototype = "RRAND x y" -aliases = ["RRND"] -short = "generate a random number between `x` and `y` inclusive" - -[TOSS] -prototype = "TOSS" -short = "randomly return `0` or `1`" - ["?"] prototype = "? x y z" short = "if condition `x` is true return `y`, otherwise return `z`" @@ -62,33 +48,11 @@ short = "limit the value `x` to the range `y` to `z` inclusive, but with wrappin [QT] prototype = "QT x y" short = "round `x` to the closest multiple of `y` (quantise)" - -["QT.S"] -prototype = "QT.S x r s" -short = "quantize 1V/OCT signal `x` to scale `s` (0-8, reference N.S scales) with root 1V/OCT pitch `r`" - -["QT.CS"] -prototype = "QT.CS x r s d c" -short = "quantize 1V/OCT signal `x` to chord `c` (1-7) from scale `s` (0-8, reference N.S scales) at degree `d` (1-7) with root 1V/OCT pitch `r`" description = """ -Quantize 1V/OCT signal `x` to chord `c` (1-7) from scale `s` (0-8, reference N.S scales) at degree `d` (1-7) with root 1V/OCT pitch `r`. - -Chords (1-7) - - `1` = Tonic - - `2` = Third - - `3` = Triad - - `4` = Seventh - - etc. +Round `x` to the closest multiple of `y`. +*See also: `QT.S`, `QT.CS`, `QT.B`, `QT.BX` in the Pitch section*. """ -["QT.B"] -prototype = "QT.B x" -short = "quantize 1V/OCT signal `x` to scale defined by `N.B`" - -["QT.BX"] -prototype = "QT.BX i x" -short = "quantize 1V/OCT signal `x` to scale defined by `N.BX` in scale index `i`" - [AVG] prototype = "AVG x y" short = "the average of `x` and `y`" @@ -260,10 +224,6 @@ description = """ Logical OR of `x`, `y`, `z` and `a`. Returns `1` if either `x`, `y`, `z` or `a` are greater than `0`, otherwise it returns `0`. """ -[JI] -prototype = "JI x y" -short = "just intonation helper, precision ratio divider normalised to 1V" - [SCALE] prototype = "SCALE a b x y i" aliases = ["SCL"] @@ -274,242 +234,6 @@ prototype = "SCALE a b i" aliases = ["SCL0"] short = "scale `i` from range `0` to `a` to range `0` to `b`" -[ER] -prototype = "ER f l i" -short = "Euclidean rhythm, `f` is fill (`1-32`), `l` is length (`1-32`) and `i` is step (any value), returns `0` or `1`" -description=""" -Euclidean rhythm helper, as described by Godfried Toussaint in his 2005 paper ["The Euclidean Algorithm Generates Traditional Musical Rhythms"][euclidean_rhythm_paper][^euclidean_rhythm_citation]. From the abstract: - - - `f` is fill (`1-32`) and should be less then or equal to length - - `l` is length (`1-32`) - - `i` is the step index, and will work with negative as well as positive numbers - -If you wish to add rotation as well, use the following form: - -``` -ER f l SUB i r -``` - -where `r` is the number of step of _forward_ rotation you want. - -For more info, see the post on [samdoshi.com][samdoshi_com_euclidean] - -[samdoshi_com_euclidean]: http://samdoshi.com/post/2016/03/teletype-euclidean/ -[euclidean_rhythm_paper]: http://cgm.cs.mcgill.ca/~godfried/publications/banff.pdf -[^euclidean_rhythm_citation]: Toussaint, G. T. (2005, July). The Euclidean algorithm generates traditional musical rhythms. _In Proceedings of BRIDGES: Mathematical Connections in Art, Music and Science_ (pp. 47-56). -""" - -[NR] -prototype = "NR p m f s" -short = "Numeric Repeater, `p` is prime pattern (`0-31`), `m` is & mask (`0-3`), `f` is variation factor (`0-16`) and `s` is step (`0-15`), returns `0` or `1`" -description = """ -Numeric Repeater is similar to ER, except it generates patterns using the binary arithmetic process found in ["Noise Engineering's Numeric Repetitor"][numeric_repetitor]. From the description: - -Numeric Repetitor is a rhythmic gate generator based on binary arithmetic. A core pattern forms the basis and variation is achieved by treating this pattern as a binary number and multiplying it by another. NR contains 32 prime rhythms derived by examining all possible rhythms and weeding out bad ones via heuristic. - -All parameters wrap around their specified ranges automatically and support negative indexing. - -Masks - - `0` is no mask - - `1` is `0x0F0F` - - `2` is `0xF003` - - `3` is `0x1F0` - -For further detail ["see the manual"][nr_manual]. - -[numeric_repetitor]: https://www.noiseengineering.us/shop/numeric-repetitor -[nr_manual]: https://static1.squarespace.com/static/58c709192e69cf2422026fa6/t/5e6041ad4cbc0979d6d793f2/1583366574430/NR_manual.pdf -""" - -["DR.T"] -prototype = "DR.T b p q l s" -short = "Tresillo helper, `b` is the drum bank (`0-4`), `p` is first pattern (0-215), `q` is the second pattern (0-215), `l` is length (`1-64`), and step is the step number (0-length-1), returns `0` or `1`" -description = """ -The Tresillo helper uses the preset drum patterns described in the drum pattern help function in a 3, 3, 2 rythmic formation. In the tresillo, pattern 1 will be repeated twice for a number of steps determined by the overall length of the pattern. A pattern of length 8 will play the first three steps of your selected pattern 1 twice, and -the first two steps of pattern 2 once. A pattern length of 16 will play the first six steps of selected pattern 1 twice, and the first four steps of pattern 2 once. And so on. The max length is 64. Length will be rounded down to the nearest multiple of 8. The step number wraps at the given length. -""" - -["DR.P"] -prototype = "DR.P b p s" -short = "Drum pattern helper, `b` is the drum bank (`0-4`), `p` is the pattern (0-215) and step is the step number (0-15), returns `0` or `1`" -description = """ -The drum helper uses preset drum patterns to give 16-step gate patterns. Gates wrap after step 16. Bank 0 is a set of pseudo random gates increasing in density at higher numbered patterns, where pattern 0 is empty, -and pattern 215 is 1s. Bank 1 is bass drum patterns. Bank 2 is snare drum patterns. Bank 3 is closed hi-hats. Bank 4 is open hi-hits and in some cases cymbals. Bank 1-4 patterns are related to each other (bank 1 pattern 1's bass drum pattern fits bank 2 pattern 1's snare drum pattern). -The patterns are from [Paul Wenzel's "Pocket Operations" book](https://shittyrecording.studio/). -""" - -["DR.V"] -prototype = "DR.V p s" -short = "Velocity helper. `p` is the pattern (0-19). `s` is the step number (0-15)" -description = """ -The velocity helper gives velocity values (0-16383) at each step. The values are intended to be used for drum hit velocities. There are 16 steps, which wrap around. Divide by 129 to convert to midi cc values. -""" - -[BPM] -prototype = "BPM x" -short = "milliseconds per beat in BPM `x`" - -[N] -prototype = "N x" -short = "converts an equal temperament note number to a value usable by the CV outputs (`x` in the range `-127` to `127`)" -description = """ -The `N` OP converts an equal temperament note number to a value usable by the CV outputs. - -Examples: - -``` -CV 1 N 60 => set CV 1 to middle C, i.e. 5V -CV 1 N RAND 24 => set CV 1 to a random note from the lowest 2 octaves -``` -""" - -[VN] -prototype = "VN x" -short = "converts 1V/OCT value `x` to an equal temperament note number" - -[HZ] -prototype = "HZ x" -short = "converts 1V/OCT value `x` to Hz/Volt value, useful for controlling non-euro synths like Korg MS-20" - -["N.B"] -prototype = "N.B d" -prototype_set = "N.B r s" -short = "get degree `d` of scale/set scale root to `r`, scale to `s`, `s` is either bit mask (`s` >= 1) or scale preset (`s` < 1)" -description = """ -Converts a degree in a user-defined equal temperament scale to a value usable by the CV outputs. Default values of `r` and `s` are 0 and R101011010101, corresponding to C-major. -To make it easier to generate bit-masks in code, LSB (bit 0) represent the first note in the octave. To avoid having to mirror scales in our heads when entering them by hand, we use `R...` (reverse binary) instead of `B...` (binary ). - -The bit-masks uses the 12 lower bits. - -Note that N.B is using scale at index 0 as used by N.BX ,so N.B and N.BX 0 are equivalent. - -Examples: -``` -CV 1 N.B 1 ==> set CV 1 to 1st degree of default scale - (C, value corresponding to N 0) -N.B 0 R101011010101 ==> set scale to C-major (default) -CV 1 N.B 1 ==> set CV 1 get 1st degree of scale - (C, value corresponding to N 0) -N.B 2 R101011010101 ==> set scale to D-major -CV 1 N.B 3 ==> set CV 1 to 3rd degree of scale - (F#, value corresponding to N 6) -N.B 3 R100101010010 ==> set scale to Eb-minor pentatonic -CV 1 N.B 2 ==> set CV 1 to 2nd degree of scale - (Gb, value corresponding to N 6) -N.B 5 -3 ==> set scale to F-lydian using preset -``` -Values of `s` less than 1 sets the bit mask to a preset scale: -``` -0: Ionian (major) --1: Dorian --2: Phrygian --3: Lydian --4: Mixolydian --5: Aeolean (natural minor) --6: Locrian --7: Melodic minor --8: Harmonic minor --9: Major pentatonic --10: Minor pentatonic --11 Whole note (1st Messiaen mode) --12 Octatonic (half-whole, 2nd Messiaen mode) --13 Octatonic (whole-half) --14 3rd Messiaen mode --15 4th Messiaen mode --16 5th Messiaen mode --17 6th Messiaen mode --18 7th Messiaen mode --19 Augmented -``` -""" - -["N.BX"] -prototype = "N.BX i d" -prototype_set = "N.BX i r s" -short = "multi-index version of N.B, scale at `i` (index) 0 is shared with N.B" -description = """ -Multi-index version of N.B. Index `i` in the range 0-15, allows working with 16 independent scales. Scale at `i` 0 is shared with N.B. - -Examples: -``` -N.BX 0 0 R101011010101 ==> set scale at index 0 to C-major (default) -CV 1 N.BX 0 1 ==> set CV 1 to 1st degree of scale - (C, value corresponding to N 0) -N.BX 1 3 R100101010010 ==> set scale at index 1 to Eb-minor pentatonic -CV 1 N.BX 1 2 ==> set CV 1 to 2nd degree of scale - (Gb, value corresponding to N 6) -N.BX 2 5 -3 ==> set scale at index 2 to F-lydian using preset -``` - -""" - - -["N.S"] -prototype = "N.S r s d" -short = "Note Scale operator, `r` is the root note (`0-127`), `s` is the scale (`0-8`) and `d` is the degree (`1-7`), returns a value from the `N` table." -description = """ -The `N.S` OP lets you retrieve `N` table values according to traditional western scales. `s` and `d` wrap to their ranges automatically and support negative indexing. - -Scales - - `0` = Major - - `1` = Natural Minor - - `2` = Harmonic Minor - - `3` = Melodic Minor - - `4` = Dorian - - `5` = Phrygian - - `6` = Lydian - - `7` = Mixolydian - - `8` = Locrian -""" - -["N.C"] -prototype = "N.C r c d" -short = "Note Chord operator, `r` is the root note (`0-127`), `c` is the chord (`0-12`) and `d` is the degree (`0-3`), returns a value from the `N` table." -description = """ -The `N.C` OP lets you retrieve `N` table values according to traditional western chords. `c` and `d` wrap to their ranges automatically and support negative indexing. - -Chords - - `0` = Major 7th `{0, 4, 7, 11}` - - `1` = Minor 7th `{0, 3, 7, 10}` - - `2` = Dominant 7th `{0, 4, 7, 10}` - - `3` = Diminished 7th `{0, 3, 6, 9}` - - `4` = Augmented 7th `{0, 4, 8, 10}` - - `5` = Dominant 7b5 `{0, 4, 6, 10}` - - `6` = Minor 7b5 `{0, 3, 6, 10}` - - `7` = Major 7#5 `{0, 4, 8, 11}` - - `8` = Minor Major 7th `{0, 3, 7, 11}` - - `9` = Diminished Major 7th `{0, 3, 6, 11}` - - `10` = Major 6th `{0, 4, 7, 9}` - - `11` = Minor 6th `{0, 3, 7, 9}` - - `12` = 7sus4 `{0, 5, 7, 10}` - """ - -["N.CS"] -prototype = "N.CS r s d c" -short = "Note Chord Scale operator, `r` is the root note (`0-127`), `s` is the scale (`0-8`), `d` is the scale degree (`1-7`) and `c` is the chord component (`0-3`), returns a value from the `N` table." -description = """ -The `N.CS` OP lets you retrieve `N` table values according to traditional western scales and chords. `s`, `c` and `d` wrap to their ranges automatically and support negative indexing. - -Chord Scales - Refer to chord indices in `N.C` OP - - `0` = Major `{0, 1, 1, 0, 2, 1, 6}` - - `1` = Natural Minor `{1, 6, 0, 1, 1, 0, 2}` - - `2` = Harmonic Minor `{8, 6, 7, 1, 2, 0, 3}` - - `3` = Melodic Minor `{8, 1, 7, 2, 2, 6, 6}` - - `4` = Dorian `{1, 1, 0, 2, 1, 6, 0}` - - `5` = Phrygian `{1, 0, 2, 1, 6, 0, 1}` - - `6` = Lydian `{0, 2, 1, 6, 0, 1, 1}` - - `7` = Mixolydian `{2, 1, 6, 0, 1, 1, 0}` - - `8` = Locrian `{6, 0, 1, 1, 0, 2, 1}` - """ - -[V] -prototype = "V x" -short = "converts a voltage to a value usable by the CV outputs (`x` between `0` and `10`)" - -[VV] -prototype = "VV x" -short = "converts a voltage to a value usable by the CV outputs (`x` between `0` and `1000`, `100` represents 1V)" - [EXP] prototype = "EXP x" short = "exponentiation table lookup. `0-16383` range (V `0-10`)" @@ -517,28 +241,3 @@ short = "exponentiation table lookup. `0-16383` range (V `0-10`)" [SGN] prototype = "SGN x" short = "sign function: 1 for positive, -1 for negative, 0 for 0" - -[CHAOS] -prototype = "CHAOS x" -short = "get next value from chaos generator, or set the current value" - -["CHAOS.R"] -prototype = "CHAOS.R x" -short = "get or set the `R` parameter for the `CHAOS` generator" - -["CHAOS.ALG"] -prototype = "CHAOS.ALG x" -short = "get or set the algorithm for the `CHAOS` generator. 0 = LOGISTIC, 1 = CUBIC, 2 = HENON, 3 = CELLULAR" - -[R] -prototype = "R" -prototype_set = "R x" -short = "get a random number/set `R.MIN` and `R.MAX` to same value `x` (effectively allowing `R` to be used as a global variable)" - -["R.MIN"] -prototype = "R.MIN x" -short = "set the lower end of the range from -32768 – 32767, default: 0" - -["R.MAX"] -prototype = "R.MAX x" -short = "set the upper end of the range from -32768 – 32767, default: 16383" diff --git a/docs/ops/pitch.md b/docs/ops/pitch.md new file mode 100644 index 00000000..c4e1905b --- /dev/null +++ b/docs/ops/pitch.md @@ -0,0 +1,3 @@ +## Pitch + +Mathematical calcuations and tables helpful for musical pitch. diff --git a/docs/ops/pitch.toml b/docs/ops/pitch.toml new file mode 100644 index 00000000..231989de --- /dev/null +++ b/docs/ops/pitch.toml @@ -0,0 +1,181 @@ +[HZ] +prototype = "HZ x" +short = "converts 1V/OCT value `x` to Hz/Volt value, useful for controlling non-euro synths like Korg MS-20" + +[JI] +prototype = "JI x y" +short = "just intonation helper, precision ratio divider normalised to 1V" + +[N] +prototype = "N x" +short = "converts an equal temperament note number to a value usable by the CV outputs (`x` in the range `-127` to `127`)" +description = """ +The `N` OP converts an equal temperament note number to a value usable by the CV outputs. + +Examples: + +``` +CV 1 N 60 => set CV 1 to middle C, i.e. 5V +CV 1 N RAND 24 => set CV 1 to a random note from the lowest 2 octaves +``` +""" + +["N.S"] +prototype = "N.S r s d" +short = "Note Scale operator, `r` is the root note (`0-127`), `s` is the scale (`0-8`) and `d` is the degree (`1-7`), returns a value from the `N` table." +description = """ +The `N.S` OP lets you retrieve `N` table values according to traditional western scales. `s` and `d` wrap to their ranges automatically and support negative indexing. + +Scales + - `0` = Major + - `1` = Natural Minor + - `2` = Harmonic Minor + - `3` = Melodic Minor + - `4` = Dorian + - `5` = Phrygian + - `6` = Lydian + - `7` = Mixolydian + - `8` = Locrian +""" + +["N.C"] +prototype = "N.C r c d" +short = "Note Chord operator, `r` is the root note (`0-127`), `c` is the chord (`0-12`) and `d` is the degree (`0-3`), returns a value from the `N` table." +description = """ +The `N.C` OP lets you retrieve `N` table values according to traditional western chords. `c` and `d` wrap to their ranges automatically and support negative indexing. + +Chords + - `0` = Major 7th `{0, 4, 7, 11}` + - `1` = Minor 7th `{0, 3, 7, 10}` + - `2` = Dominant 7th `{0, 4, 7, 10}` + - `3` = Diminished 7th `{0, 3, 6, 9}` + - `4` = Augmented 7th `{0, 4, 8, 10}` + - `5` = Dominant 7b5 `{0, 4, 6, 10}` + - `6` = Minor 7b5 `{0, 3, 6, 10}` + - `7` = Major 7#5 `{0, 4, 8, 11}` + - `8` = Minor Major 7th `{0, 3, 7, 11}` + - `9` = Diminished Major 7th `{0, 3, 6, 11}` + - `10` = Major 6th `{0, 4, 7, 9}` + - `11` = Minor 6th `{0, 3, 7, 9}` + - `12` = 7sus4 `{0, 5, 7, 10}` + """ + +["N.CS"] +prototype = "N.CS r s d c" +short = "Note Chord Scale operator, `r` is the root note (`0-127`), `s` is the scale (`0-8`), `d` is the scale degree (`1-7`) and `c` is the chord component (`0-3`), returns a value from the `N` table." +description = """ +The `N.CS` OP lets you retrieve `N` table values according to traditional western scales and chords. `s`, `c` and `d` wrap to their ranges automatically and support negative indexing. + +Chord Scales - Refer to chord indices in `N.C` OP + - `0` = Major `{0, 1, 1, 0, 2, 1, 6}` + - `1` = Natural Minor `{1, 6, 0, 1, 1, 0, 2}` + - `2` = Harmonic Minor `{8, 6, 7, 1, 2, 0, 3}` + - `3` = Melodic Minor `{8, 1, 7, 2, 2, 6, 6}` + - `4` = Dorian `{1, 1, 0, 2, 1, 6, 0}` + - `5` = Phrygian `{1, 0, 2, 1, 6, 0, 1}` + - `6` = Lydian `{0, 2, 1, 6, 0, 1, 1}` + - `7` = Mixolydian `{2, 1, 6, 0, 1, 1, 0}` + - `8` = Locrian `{6, 0, 1, 1, 0, 2, 1}` + """ + +["N.B"] +prototype = "N.B d" +prototype_set = "N.B r s" +short = "get degree `d` of scale/set scale root to `r`, scale to `s`, `s` is either bit mask (`s` >= 1) or scale preset (`s` < 1)" +description = """ +Converts a degree in a user-defined equal temperament scale to a value usable by the CV outputs. Default values of `r` and `s` are 0 and R101011010101, corresponding to C-major. +To make it easier to generate bit-masks in code, LSB (bit 0) represent the first note in the octave. To avoid having to mirror scales in our heads when entering them by hand, we use `R...` (reverse binary) instead of `B...` (binary ). + +The bit-masks uses the 12 lower bits. + +Note that N.B is using scale at index 0 as used by N.BX ,so N.B and N.BX 0 are equivalent. + +Examples: +``` +CV 1 N.B 1 ==> set CV 1 to 1st degree of default scale + (C, value corresponding to N 0) +N.B 0 R101011010101 ==> set scale to C-major (default) +CV 1 N.B 1 ==> set CV 1 get 1st degree of scale + (C, value corresponding to N 0) +N.B 2 R101011010101 ==> set scale to D-major +CV 1 N.B 3 ==> set CV 1 to 3rd degree of scale + (F#, value corresponding to N 6) +N.B 3 R100101010010 ==> set scale to Eb-minor pentatonic +CV 1 N.B 2 ==> set CV 1 to 2nd degree of scale + (Gb, value corresponding to N 6) +N.B 5 -3 ==> set scale to F-lydian using preset +``` +Values of `s` less than 1 sets the bit mask to a preset scale: +``` +0: Ionian (major) +-1: Dorian +-2: Phrygian +-3: Lydian +-4: Mixolydian +-5: Aeolean (natural minor) +-6: Locrian +-7: Melodic minor +-8: Harmonic minor +-9: Major pentatonic +-10: Minor pentatonic +-11 Whole note (1st Messiaen mode) +-12 Octatonic (half-whole, 2nd Messiaen mode) +-13 Octatonic (whole-half) +-14 3rd Messiaen mode +-15 4th Messiaen mode +-16 5th Messiaen mode +-17 6th Messiaen mode +-18 7th Messiaen mode +-19 Augmented +``` +""" + +["N.BX"] +prototype = "N.BX i d" +prototype_set = "N.BX i r s" +short = "multi-index version of N.B, scale at `i` (index) 0 is shared with N.B" +description = """ +Multi-index version of N.B. Index `i` in the range 0-15, allows working with 16 independent scales. Scale at `i` 0 is shared with N.B. + +Examples: +``` +N.BX 0 0 R101011010101 ==> set scale at index 0 to C-major (default) +CV 1 N.BX 0 1 ==> set CV 1 to 1st degree of scale + (C, value corresponding to N 0) +N.BX 1 3 R100101010010 ==> set scale at index 1 to Eb-minor pentatonic +CV 1 N.BX 1 2 ==> set CV 1 to 2nd degree of scale + (Gb, value corresponding to N 6) +N.BX 2 5 -3 ==> set scale at index 2 to F-lydian using preset +``` + +""" + +[VN] +prototype = "VN x" +short = "converts 1V/OCT value `x` to an equal temperament note number" + +["QT.B"] +prototype = "QT.B x" +short = "quantize 1V/OCT signal `x` to scale defined by `N.B`" + +["QT.BX"] +prototype = "QT.BX i x" +short = "quantize 1V/OCT signal `x` to scale defined by `N.BX` in scale index `i`" + +["QT.S"] +prototype = "QT.S x r s" +short = "quantize 1V/OCT signal `x` to scale `s` (0-8, reference N.S scales) with root 1V/OCT pitch `r`" + +["QT.CS"] +prototype = "QT.CS x r s d c" +short = "quantize 1V/OCT signal `x` to chord `c` (1-7) from scale `s` (0-8, reference N.S scales) at degree `d` (1-7) with root 1V/OCT pitch `r`" +description = """ +Quantize 1V/OCT signal `x` to chord `c` (1-7) from scale `s` (0-8, reference N.S scales) at degree `d` (1-7) with root 1V/OCT pitch `r`. + +Chords (1-7) + - `1` = Tonic + - `2` = Third + - `3` = Triad + - `4` = Seventh + - etc. +""" diff --git a/docs/ops/random.md b/docs/ops/random.md new file mode 100644 index 00000000..fb338934 --- /dev/null +++ b/docs/ops/random.md @@ -0,0 +1 @@ +## Randomness diff --git a/docs/ops/random.toml b/docs/ops/random.toml new file mode 100644 index 00000000..424cd8b8 --- /dev/null +++ b/docs/ops/random.toml @@ -0,0 +1,103 @@ +[RAND] +prototype = "RAND x" +aliases = ["RND"] +short = "generate a random number between `0` and `x` inclusive" + +[RRAND] +prototype = "RRAND x y" +aliases = ["RRND"] +short = "generate a random number between `x` and `y` inclusive" + +[TOSS] +prototype = "TOSS" +short = "randomly return `0` or `1`" + +[R] +prototype = "R" +prototype_set = "R x" +short = "get a random number/set `R.MIN` and `R.MAX` to same value `x` (effectively allowing `R` to be used as a global variable)" + +["R.MIN"] +prototype = "R.MIN x" +short = "set the lower end of the range from -32768 – 32767, default: 0" + +["R.MAX"] +prototype = "R.MAX x" +short = "set the upper end of the range from -32768 – 32767, default: 16383" + +[CHAOS] +prototype = "CHAOS x" +short = "get next value from chaos generator, or set the current value" + +["CHAOS.R"] +prototype = "CHAOS.R x" +short = "get or set the `R` parameter for the `CHAOS` generator" + +["CHAOS.ALG"] +prototype = "CHAOS.ALG x" +short = "get or set the algorithm for the `CHAOS` generator. 0 = LOGISTIC, 1 = CUBIC, 2 = HENON, 3 = CELLULAR" + +[DRUNK] +prototype = "DRUNK" +prototype_set = "DRUNK x" +short = """changes by `-1`, `0`, or `1` upon each read saving its state, +setting will give it a new value for the next read""" +description=""" +Changes by `-1`, `0`, or `1` upon each read, saving its state. Setting `DRUNK` +will give it a new value for the next read, and drunkedness will continue on +from there with subsequent reads. + +Setting `DRUNK.MIN` and `DRUNK.MAX` controls the lower and upper bounds +(inclusive) that `DRUNK` can reach. `DRUNK.WRAP` controls whether the value can +wrap around when it reaches it's bounds. +""" + +["DRUNK.MIN"] +prototype = "DRUNK.MIN" +prototype_set = "DRUNK.MIN x" +short = "set the lower bound for `DRUNK`, default `0`" + +["DRUNK.MAX"] +prototype = "DRUNK.MAX" +prototype_set = "DRUNK.MAX x" +short = "set the upper bound for `DRUNK`, default `255`" + +["DRUNK.WRAP"] +prototype = "DRUNK.WRAP" +prototype_set = "DRUNK.WRAP x" +short = "should `DRUNK` wrap around when it reaches it's bounds, default `0`" + +["SEED"] +prototype = "SEED" +prototype_set = "SEED x" +short = "get / set the random number generator seed for all `SEED` ops" + +["RAND.SEED"] +prototype = "RAND.SEED" +prototype_set = "RAND.SEED x" +aliases = ["RAND.SD", "R.SD"] +short = "get / set the random number generator seed for `R`, `RRAND`, and `RAND` ops" + +["TOSS.SEED"] +prototype = "TOSS.SEED" +prototype_set = "TOSS.SEED x" +aliases = ["TOSS.SD"] +short = "get / set the random number generator seed for the `TOSS` op" + +["PROB.SEED"] +prototype = "PROB.SEED" +prototype_set = "PROB.SEED x" +aliases = ["PROB.SD"] +short = "get / set the random number generator seed for the `PROB` mod" + +["DRUNK.SEED"] +prototype = "DRUNK.SEED" +prototype_set = "DRUNK.SEED x" +aliases = ["DRUNK.SD"] +short = "get / set the random number generator seed for the `DRUNK` op" + +["P.SEED"] +prototype = "P.SEED" +prototype_set = "P.SEED x" +aliases = ["P.SD"] +short = "get / set the random number generator seed for the `P.RND` and `PN.RND` ops" diff --git a/docs/ops/rhythm.md b/docs/ops/rhythm.md new file mode 100644 index 00000000..580ae12f --- /dev/null +++ b/docs/ops/rhythm.md @@ -0,0 +1,3 @@ +## Rhythm + +Mathematical calculations and tables helpful for rhythmic decisions. diff --git a/docs/ops/rhythm.toml b/docs/ops/rhythm.toml new file mode 100644 index 00000000..9ef05387 --- /dev/null +++ b/docs/ops/rhythm.toml @@ -0,0 +1,74 @@ +[BPM] +prototype = "BPM x" +short = "milliseconds per beat in BPM `x`" + +["DR.P"] +prototype = "DR.P b p s" +short = "Drum pattern helper, `b` is the drum bank (`0-4`), `p` is the pattern (0-215) and step is the step number (0-15), returns `0` or `1`" +description = """ +The drum helper uses preset drum patterns to give 16-step gate patterns. Gates wrap after step 16. Bank 0 is a set of pseudo random gates increasing in density at higher numbered patterns, where pattern 0 is empty, +and pattern 215 is 1s. Bank 1 is bass drum patterns. Bank 2 is snare drum patterns. Bank 3 is closed hi-hats. Bank 4 is open hi-hits and in some cases cymbals. Bank 1-4 patterns are related to each other (bank 1 pattern 1's bass drum pattern fits bank 2 pattern 1's snare drum pattern). +The patterns are from [Paul Wenzel's "Pocket Operations" book](https://shittyrecording.studio/). +""" + +["DR.T"] +prototype = "DR.T b p q l s" +short = "Tresillo helper, `b` is the drum bank (`0-4`), `p` is first pattern (0-215), `q` is the second pattern (0-215), `l` is length (`1-64`), and step is the step number (0-length-1), returns `0` or `1`" +description = """ +The Tresillo helper uses the preset drum patterns described in the drum pattern help function in a 3, 3, 2 rythmic formation. In the tresillo, pattern 1 will be repeated twice for a number of steps determined by the overall length of the pattern. A pattern of length 8 will play the first three steps of your selected pattern 1 twice, and +the first two steps of pattern 2 once. A pattern length of 16 will play the first six steps of selected pattern 1 twice, and the first four steps of pattern 2 once. And so on. The max length is 64. Length will be rounded down to the nearest multiple of 8. The step number wraps at the given length. +""" + +["DR.V"] +prototype = "DR.V p s" +short = "Velocity helper. `p` is the pattern (0-19). `s` is the step number (0-15)" +description = """ +The velocity helper gives velocity values (0-16383) at each step. The values are intended to be used for drum hit velocities. There are 16 steps, which wrap around. Divide by 129 to convert to midi cc values. +""" + +[ER] +prototype = "ER f l i" +short = "Euclidean rhythm, `f` is fill (`1-32`), `l` is length (`1-32`) and `i` is step (any value), returns `0` or `1`" +description=""" +Euclidean rhythm helper, as described by Godfried Toussaint in his 2005 paper ["The Euclidean Algorithm Generates Traditional Musical Rhythms"][euclidean_rhythm_paper][^euclidean_rhythm_citation]. From the abstract: + + - `f` is fill (`1-32`) and should be less then or equal to length + - `l` is length (`1-32`) + - `i` is the step index, and will work with negative as well as positive numbers + +If you wish to add rotation as well, use the following form: + +``` +ER f l SUB i r +``` + +where `r` is the number of step of _forward_ rotation you want. + +For more info, see the post on [samdoshi.com][samdoshi_com_euclidean] + +[samdoshi_com_euclidean]: http://samdoshi.com/post/2016/03/teletype-euclidean/ +[euclidean_rhythm_paper]: http://cgm.cs.mcgill.ca/~godfried/publications/banff.pdf +[^euclidean_rhythm_citation]: Toussaint, G. T. (2005, July). The Euclidean algorithm generates traditional musical rhythms. _In Proceedings of BRIDGES: Mathematical Connections in Art, Music and Science_ (pp. 47-56). +""" + +[NR] +prototype = "NR p m f s" +short = "Numeric Repeater, `p` is prime pattern (`0-31`), `m` is & mask (`0-3`), `f` is variation factor (`0-16`) and `s` is step (`0-15`), returns `0` or `1`" +description = """ +Numeric Repeater is similar to ER, except it generates patterns using the binary arithmetic process found in ["Noise Engineering's Numeric Repetitor"][numeric_repetitor]. From the description: + +Numeric Repetitor is a rhythmic gate generator based on binary arithmetic. A core pattern forms the basis and variation is achieved by treating this pattern as a binary number and multiplying it by another. NR contains 32 prime rhythms derived by examining all possible rhythms and weeding out bad ones via heuristic. + +All parameters wrap around their specified ranges automatically and support negative indexing. + +Masks + - `0` is no mask + - `1` is `0x0F0F` + - `2` is `0xF003` + - `3` is `0x1F0` + +For further detail ["see the manual"][nr_manual]. + +[numeric_repetitor]: https://www.noiseengineering.us/shop/numeric-repetitor +[nr_manual]: https://static1.squarespace.com/static/58c709192e69cf2422026fa6/t/5e6041ad4cbc0979d6d793f2/1583366574430/NR_manual.pdf +""" diff --git a/docs/ops/seed.md b/docs/ops/seed.md deleted file mode 100644 index 40a76a4c..00000000 --- a/docs/ops/seed.md +++ /dev/null @@ -1,2 +0,0 @@ -## Seed - diff --git a/docs/ops/seed.toml b/docs/ops/seed.toml deleted file mode 100644 index 8301af14..00000000 --- a/docs/ops/seed.toml +++ /dev/null @@ -1,34 +0,0 @@ -["SEED"] -prototype = "SEED" -prototype_set = "SEED x" -short = "get / set the random number generator seed for all `SEED` ops" - -["RAND.SEED"] -prototype = "RAND.SEED" -prototype_set = "RAND.SEED x" -aliases = ["RAND.SD", "R.SD"] -short = "get / set the random number generator seed for `R`, `RRAND`, and `RAND` ops" - -["TOSS.SEED"] -prototype = "TOSS.SEED" -prototype_set = "TOSS.SEED x" -aliases = ["TOSS.SD"] -short = "get / set the random number generator seed for the `TOSS` op" - -["PROB.SEED"] -prototype = "PROB.SEED" -prototype_set = "PROB.SEED x" -aliases = ["PROB.SD"] -short = "get / set the random number generator seed for the `PROB` mod" - -["DRUNK.SEED"] -prototype = "DRUNK.SEED" -prototype_set = "DRUNK.SEED x" -aliases = ["DRUNK.SD"] -short = "get / set the random number generator seed for the `DRUNK` op" - -["P.SEED"] -prototype = "P.SEED" -prototype_set = "P.SEED x" -aliases = ["P.SD"] -short = "get / set the random number generator seed for the `P.RND` and `PN.RND` ops" diff --git a/docs/ops/telex_o.toml b/docs/ops/telex_o.toml index 18a423f5..ef7959f5 100644 --- a/docs/ops/telex_o.toml +++ b/docs/ops/telex_o.toml @@ -272,12 +272,16 @@ You will find that the offset is now zero, but the output is at the value that y ["TO.CV.RESET"] prototype = "TO.CV.RESET x" -short = "Clears the calibration offset for output `x`." +short = "Clears the calibration offset for output `x`" ["TO.OSC"] prototype = "TO.OSC x y" -short = "targets oscillation for CV output `x` to `y` with the portamento rate determined by the `TO.OSC.SLEW` value; `y` is 1v/oct translated from the standard range (1-16384); a value of `0` disables oscillation; `CV` amplitude is used as the peak for oscillation and needs to be `> 0` for it to be perceivable" +short = "Targets oscillation for CV output `x` to `y`" description = """ +Targets oscillation for CV output `x` to `y` with the portamento rate determined by the `TO.OSC.SLEW` value. +`y` is 1V/oct translated from the standard range (1-16384). +A value of `0` disables oscillation; `CV` amplitude is used as the peak for oscillation and needs to be `> 0` for it to be perceivable. + Setting an `OSC` frequency greater than zero for a `CV` output will start that output oscillating. It will swing its voltage between to the current `CV` value and its polar opposite. For example: ``` @@ -302,39 +306,79 @@ If you want to go back to regular `CV` behavior, you need to set the oscillation ["TO.OSC.SET"] prototype = "TO.OSC.SET x y" -short = "set oscillation for CV output `x` to `y` (ignores `CV.OSC.SLEW`); `y` is 1v/oct translated from the standard range (1-16384); a value of `0` disables oscillation; `CV` amplitude is used as the peak for oscillation and needs to be `> 0` for it to be perceivable" +short = "set oscillation for CV output `x` to `y` (ignores slew)" +description = """ +Set oscillation for CV output `x` to `y` (ignores `CV.OSC.SLEW`.) `y` is 1V/oct translated from the standard range (1-16384); +a value of `0` disables oscillation. `CV` amplitude is used as the peak for oscillation and needs to be `> 0` for it to be perceivable. +""" ["TO.OSC.QT"] prototype = "TO.OSC.QT x y" -short = "targets oscillation for CV output `x` to `y` with the portamento rate determined by the `TO.OSC.SLEW` value; `y` is 1v/oct translated from the standard range (1-16384) and quantized to current `OSC.SCALE`; a value of `0` disables oscillation; `CV` amplitude is used as the peak for oscillation and needs to be `> 0` for it to be perceivable" +short = "targets oscillation for CV output `x` to `y`" +description = """ +Targets oscillation for CV output `x` to `y` with the portamento rate determined by the `TO.OSC.SLEW` value. +`y` is 1V/oct translated from the standard range (1-16384) and quantized to current `OSC.SCALE`. +A value of `0` disables oscillation; `CV` amplitude is used as the peak for oscillation and needs to be `> 0` for it to be perceivable. +""" ["TO.OSC.QT.SET"] prototype = "TO.OSC.QT.SET x y" -short = "set oscillation for CV output `x` to `y` (ignores `CV.OSC.SLEW`); `y` is 1v/oct translated from the standard range (1-16384) and quantized to current `OSC.SCALE`; a value of `0` disables oscillation; `CV` amplitude is used as the peak for oscillation and needs to be `> 0` for it to be perceivable" +short = "set oscillation for CV output `x` to `y`, quantized to the current scale (ignores slew)" +description = """ +Set oscillation for CV output `x` to the 1V/oct value `y` (ignores `CV.OSC.SLEW`.) +`y` is 1v/oct translated from the standard range (1-16384) and quantized to current `OSC.SCALE`. +A value of `0` disables oscillation; `CV` amplitude is used as the peak for oscillation and needs to be `> 0` for it to be perceivable. +""" ["TO.OSC.N"] prototype = "TO.OSC.N x y" -short = "targets oscillation for CV output `x` to note `y` with the portamento rate determined by the `TO.OSC.SLEW` value; see quantization scale reference for `y`; `CV` amplitude is used as the peak for oscillation and needs to be `> 0` for it to be perceivable" +short = "targets oscillation for CV output `x` to note `y`" +description = """ +Targets oscillation for CV output `x` to note `y` with the portamento rate determined by the `TO.OSC.SLEW` value. +See quantization scale reference for `y`; `CV` amplitude is used as the peak for oscillation and needs to be `> 0` for it to be perceivable. +""" ["TO.OSC.N.SET"] prototype = "TO.OSC.N.SET x y" -short = "sets oscillation for CV output `x` to note `y` (ignores `CV.OSC.SLEW`); see quantization scale reference for `y`; `CV` amplitude is used as the peak for oscillation and needs to be `> 0` for it to be perceivable" +short = "sets oscillation for CV output `x` to note `y` (ignores slew)" +description = """ +Sets oscillation for CV output `x` to note `y` (ignores `CV.OSC.SLEW`.) +See quantization scale reference for `y`; `CV` amplitude is used as the peak for oscillation and needs to be `> 0` for it to be perceivable. +""" ["TO.OSC.FQ"] prototype = "TO.OSC.FQ x y" -short = "targets oscillation for CV output `x` to frequency `y` with the portamento rate determined by the `TO.OSC.SLEW` value; `y` is in Hz; a value of `0` disables oscillation; `CV` amplitude is used as the peak for oscillation and needs to be `> 0` for it to be perceivable" +short = "targets oscillation for CV output `x` to frequency `y` in Hertz" +description = """ +Targets oscillation for CV output `x` to frequency `y` with the portamento rate determined by the `TO.OSC.SLEW` value. +`y` is in Hz; a value of `0` disables oscillation. `CV` amplitude is used as the peak for oscillation and needs to be `> 0` for it to be perceivable. +""" ["TO.OSC.FQ.SET"] prototype = "TO.OSC.FQ.SET x y" -short = "sets oscillation for CV output `x` to frequency `y` (ignores `CV.OSC.SLEW`); `y` is in Hz; a value of `0` disables oscillation; `CV` amplitude is used as the peak for oscillation and needs to be `> 0` for it to be perceivable" +short = "targets oscillation for CV output `x` to frequency `y` in Hertz (ignores slew)" +description = """ +Sets oscillation for CV output `x` to frequency `y` (ignores `CV.OSC.SLEW`.) +`y` is in Hz; a value of `0` disables oscillation. `CV` amplitude is used as the peak for oscillation and needs to be `> 0` for it to be perceivable. +""" ["TO.OSC.LFO"] prototype = "TO.OSC.LFO x y" -short = "targets oscillation for CV output `x` to LFO frequency `y` with the portamento rate determined by the `TO.OSC.SLEW` value; `y` is in mHz (millihertz: 10^-3 Hz); a value of `0` disables oscillation; `CV` amplitude is used as the peak for oscillation and needs to be `> 0` for it to be perceivable" +short = "Targets oscillation for CV output `x` to LFO frequency `y` in millihertz" +description = """ +Targets oscillation for CV output `x` to LFO frequency `y` with the portamento rate determined by the `TO.OSC.SLEW` value. +`y` is in mHz (millihertz: 10^-3 Hz); a value of `0` disables oscillation. +`CV` amplitude is used as the peak for oscillation and needs to be `> 0` for it to be perceivable. +""" ["TO.OSC.LFO.SET"] prototype = "TO.OSC.LFO.SET x y" -short = "sets oscillation for CV output `x` to LFO frequency `y` (ignores `CV.OSC.SLEW`); `y` is in mHz (millihertz: 10^-3 Hz); a value of `0` disables oscillation; `CV` amplitude is used as the peak for oscillation and needs to be `> 0` for it to be perceivable" +short = "Targets oscillation for CV output `x` to LFO frequency `y` in millihertz (ignores slew)" +description = """ +Sets oscillation for CV output `x` to LFO frequency `y` (ignores `CV.OSC.SLEW`.) +`y` is in mHz (millihertz: 10^-3 Hz); a value of `0` disables oscillation. +`CV` amplitude is used as the peak for oscillation and needs to be `> 0` for it to be perceivable. +""" ["TO.OSC.CYC"] prototype = "TO.OSC.CYC x y" @@ -386,11 +430,15 @@ description = """ ["TO.OSC.WAVE"] prototype = "TO.OSC.WAVE x y" -short = "set the waveform for output `x` to `y`; `y` values range `0-4500`. There are 45 different waveforms, values translate to sine (0), triangle (100), saw (200), pulse (300) all the way to random/noise (4500); oscillator shape between values is a blend of the pure waveforms" +short = "set the waveform for output `x` to `y`; `y` range is `0-4500`, blending between 45 waveforms" +description = """ +There are 45 different waveforms, values translate to sine (0), triangle (100), saw (200), pulse (300) all the way to random/noise (4500). +Oscillator shape between values is a blend of the pure waveforms. +""" ["TO.OSC.RECT"] prototype = "TO.OSC.RECT x y" -short = "rectifies the polarity of the oscillator for output `x` to `y`; range for `y` is -2 to 2; default is 0 (no rectification); 1 & -1 are partial rectification - omitting all values on the other side of the sign; 2 & -2 are full rectification - inverting values from the other pole" +short = "rectifies the polarity of the oscillator for output `x` to `y`; 0 is no rectification, +/-1 is partial rectification, +/-2 is full rectification" description = """ The rectification command performs a couple of levels of rectification based on how you have it set. The following values for `y` work as follows: @@ -470,7 +518,12 @@ To return your `CV` output to normal function, either deactivate the envelope (` ["TO.ENV"] prototype = "TO.ENV x y" -short = "This parameter essentially allows output `x` to act as a gate between the 0 and 1 state. Changing this value from 0 to 1 causes the envelope to trigger the attack phase and hold at the peak CV value; changing this value from 1 to 0 causes the decay stage of the envelope to be triggered." +short = "trigger the attack stage of output `x` when `y` changes to 1, or decay stage when it changes to 0" +description = """ +This parameter essentially allows output `x` to act as a gate between the 0 and 1 state. Changing this value from 0 to 1 +causes the envelope to trigger the attack phase and hold at the peak CV value; changing this value from 1 to 0 causes the +decay stage of the envelope to be triggered. +""" ["TO.ENV.TRIG"] prototype = "TO.ENV.TRIG x" @@ -502,8 +555,11 @@ short = "set the envelope decay time to `y` for `CV` output `x`; `y` in minutes" ["TO.ENV.EOR"] prototype = "TO.ENV.EOR x n" -short = "fires a `PULSE` at the End of Rise to the unit-local trigger output 'n' for the envelope on `CV` output `x`; `n` refers to trigger output 1-4 on the same TXo as CV output 'y'" +short = "at the end of rise of `CV` output `x`, fires a `PULSE` to the trigget output `n`" description = """ +Fires a `PULSE` at the End of Rise to the unit-local trigger output `n` for the envelope on `CV` output `x`; +`n` refers to trigger output 1-4 on the same TXo as CV output `x`. + The most important thing to know with this operator is that you can only cause the EOR trigger to fire on the same device as the TXo with the envelope. For this command, the outputs are numbered LOCALLY to the unit with the envelope. For example, if you have an envelope running on your second TXo, you can only send the EOR pulse to the four outputs on that device: @@ -517,8 +573,11 @@ This will cause the first output on TXo #2 (`TO.TR 5`) to pulse after the envelo ["TO.ENV.EOC"] prototype = "TO.ENV.EOC x n" -short = "fires a `PULSE` at the End of Cycle to the unit-local trigger output 'n' for the envelope on `CV` output `x`; `n` refers to trigger output 1-4 on the same TXo as CV output 'y'" +short = "at the end of cycle of `CV` output `x`, fires a `PULSE` to the trigget output `n`" description = """ +Fires a `PULSE` at the End of Cycle to the unit-local trigger output `n` for the envelope on `CV` output `x`. +`n` refers to trigger output 1-4 on the same TXo as CV output 'y'. + The most important thing to know with this operator is that you can only cause the EOC trigger to fire on the same device as the TXo with the envelope. For this command, the outputs are numbered LOCALLY to the unit with the envelope. For example, if you have an envelope running on your second TXo, you can only send the EOC pulse to the four outputs on that device: @@ -532,7 +591,12 @@ This will cause the first output on TXo #2 (`TO.TR 5`) to pulse after the envelo ["TO.ENV.LOOP"] prototype = "TO.ENV.LOOP x y" -short = "causes the envelope on `CV` output `x` to loop for `y` times; a `y` of `0` will cause the envelope to loop infinitely; setting `y` to 1 (default) disables looping and (if currently looping) will cause it to finish its current cycle and cease" +short = "causes the envelope on `CV` output `x` to loop for `y` times" +description = """ +Causes the envelope on `CV` output `x` to loop for `y` times. +A `y` of `0` will cause the envelope to loop infinitely; setting `y` to 1 (default) disables looping and (if currently looping) will +cause it to finish its current cycle and cease. +""" ["TO.TR.INIT"] prototype = "TO.TR.INIT x" diff --git a/docs/ops/variables.toml b/docs/ops/variables.toml index 8d63425e..0c460355 100644 --- a/docs/ops/variables.toml +++ b/docs/ops/variables.toml @@ -18,54 +18,41 @@ prototype = "D" prototype_set = "D x" short = "get / set the variable `D`, default `4`" -[DRUNK] -prototype = "DRUNK" -prototype_set = "DRUNK x" -short = """changes by `-1`, `0`, or `1` upon each read saving its state, -setting will give it a new value for the next read""" -description=""" -Changes by `-1`, `0`, or `1` upon each read, saving its state. Setting `DRUNK` -will give it a new value for the next read, and drunkedness will continue on -from there with subsequent reads. - -Setting `DRUNK.MIN` and `DRUNK.MAX` controls the lower and upper bounds -(inclusive) that `DRUNK` can reach. `DRUNK.WRAP` controls whether the value can -wrap around when it reaches it's bounds. -""" - -["DRUNK.MIN"] -prototype = "DRUNK.MIN" -prototype_set = "DRUNK.MIN x" -short = "set the lower bound for `DRUNK`, default `0`" - -["DRUNK.MAX"] -prototype = "DRUNK.MAX" -prototype_set = "DRUNK.MAX x" -short = "set the upper bound for `DRUNK`, default `255`" - -["DRUNK.WRAP"] -prototype = "DRUNK.WRAP" -prototype_set = "DRUNK.WRAP x" -short = "should `DRUNK` wrap around when it reaches it's bounds, default `0`" - [FLIP] prototype = "FLIP" prototype_set = "FLIP x" -short = "returns inverted state (`0` or `1`) on each read (also settable)" - +short = "returns the opposite of its previous state (`0` or `1`) on each read (also settable)" [I] prototype = "I" prototype_set = "I x" -short = """get / set the variable `I`""" +short = """get / set the per-script variable `I`. *See also `L:` in control flow*""" description=""" -Get / set the variable `I`, this variable is overwritten by `L`, but can be used +Get / set the variable `I`. This variable is overwritten by `L`, but can be used freely outside an `L` loop. Each script gets its own `I` variable, so if you call a script from another script's loop you can still use and modify `I` without affecting the calling loop. In this scenario the script getting called will have its `I` value initialized with the calling loop's current `I` value. """ +[J] +prototype = "J" +prototype_set = "J x" +short = """get / set the per-script variable `J`""" +description=""" +get / set the variable `J`, each script gets its own `J` variable, so if you call +a script from another script you can still use and modify `J` without affecting the calling script. +""" + +[K] +prototype = "K" +prototype_set = "K x" +short = """get / set the per-script variable `K`""" +description=""" +get / set the variable `K`, each script gets its own `K` variable, so if you call +a script from another script you can still use and modify `K` without affecting the calling script. +""" + [O] prototype = "O" prototype_set = "O x" @@ -95,7 +82,6 @@ O => 61 ``` """ - ["O.INC"] prototype = "O.INC" prototype_set = "O.INC x" @@ -160,21 +146,3 @@ short = "get / set the variable `Y`, default `0`" prototype = "Z" prototype_set = "Z x" short = "get / set the variable `Z`, default `0`" - -[J] -prototype = "J" -prototype_set = "J x" -short = """get / set the variable `J`""" -description=""" -get / set the variable `J`, each script gets its own `J` variable, so if you call -a script from another script you can still use and modify `J` without affecting the calling script. -""" - -[K] -prototype = "K" -prototype_set = "K x" -short = """get / set the variable `K`""" -description=""" -get / set the variable `K`, each script gets its own `K` variable, so if you call -a script from another script you can still use and modify `K` without affecting the calling script. -""" diff --git a/docs/whats_new.md b/docs/whats_new.md index de74dc10..46e7a073 100644 --- a/docs/whats_new.md +++ b/docs/whats_new.md @@ -33,6 +33,7 @@ - **NEW**: apply VCV Rack compatibility patches, so branches off main can be used in both hardware and software - **FIX**: update Disting EX looper ops to work with Disting EX firmware 1.23+ - **NEW**: new dual W/ ops: `W/.SEL`, `W/S.POLY`, `W/S.POLY.RESET`, `W/1`, `W/2` +- **NEW**: split cheatsheets into separate PDFs for core ops and i2c ## v4.0.0 diff --git a/utils/cheatsheet.py b/utils/cheatsheet.py index bd966b3f..2fb07db1 100755 --- a/utils/cheatsheet.py +++ b/utils/cheatsheet.py @@ -45,43 +45,49 @@ def inject_latex(value): ) # determines the order in which sections are displayed, -# final column indicates that a new page is inserted _after_ that section -OPS_SECTIONS = [ - ("variables", "Variables", False), - ("hardware", "Hardware", False), - ("patterns", "Patterns", False), - ("controlflow", "Control flow", False), - ("maths", "Maths", False), - ("metronome", "Metronome", False), - ("delay", "Delay", False), - ("stack", "Stack", False), - ("queue", "Queue", False), - ("seed", "Seed", False), - ("turtle", "Turtle", True), - ("grid", "Grid", True), - ("midi_in", "MIDI In", True), - ("i2c", "Generic I2C", True), - ("ansible", "Ansible", False), - ("whitewhale", "Whitewhale", False), - ("meadowphysics", "Meadowphysics", False), - ("earthsea", "Earthsea", False), - ("orca", "Orca", True), - ("justfriends", "Just Friends", False), - ("wslash", "W/", False), - ("er301", "ER-301", False), - ("fader", "Fader", False), - ("matrixarchate", "Matrixarchate", True), - ("telex_i", "TELEXi", False), - ("telex_o", "TELEXo", False), - ("disting", "Disting EX", True), - ("wslash_shared", "W/2.0", False), - ("wslashdelay", "W/2.0 delay", False), - ("wslashsynth", "W/2.0 synth", False), - ("wslashtape", "W/2.0 tape", False), - ("crow", "Crow", True), - ("i2c2midi", "I2C2MIDI", True) -] - +# last two columns indicates when a column break or page break is inserted _after_ that section +OPS_SECTIONS = { + "core": [ + ("variables", "Variables", True, False), + ("hardware", "Hardware I/O", False, False), + ("pitch", "Pitch", True, False), + ("rhythm", "Rhythm", False, False), + ("metronome", "Metronome", False, False), + ("random", "Randomness", True, False), + ("controlflow", "Control flow", False, False), + ("maths", "Maths", False, False), + ("delay", "Delay", False, False), + ("stack", "Stack", True, False), + ("patterns", "Patterns", True, False), + ("queue", "Queue", True, False), + ("turtle", "Turtle", False, True), + ("grid", "Grid", True, False), + ("midi_in", "MIDI In", False, False), + ("calibration", "Calibration", False, False) + ], + "i2c": [ + ("i2c", "Generic I2C", False, False), + ("ansible", "Ansible", False, False), + ("whitewhale", "White Whale", False, False), + ("meadowphysics", "Meadowphysics", False, False), + ("earthsea", "Earthsea", True, False), + ("orca", "Orca", False, False), + ("justfriends", "Just Friends", True, False), + ("fader", "Faderbank", False, False), + ("er301", "ER-301", False, False), + ("telex_i", "TELEXi", True, False), + ("telex_o", "TELEXo", True, False), + ("crow", "Crow", False, False), + ("wslash", "W/1.0", True, False), + ("wslash_shared", "W/2.0", False, False), + ("wslashtape", "W/2.0 tape", False, False), + ("wslashdelay", "W/2.0 delay", True, False), + ("wslashsynth", "W/2.0 synth", True, False), + ("disting", "Disting EX", True, False), + ("matrixarchate", "Matrixarchate", False, True), + ("i2c2midi", "I2C2MIDI", False, False) + ] +} def latex_safe(s): # backslash must be first, otherwise it will duplicate itself @@ -93,13 +99,13 @@ def latex_safe(s): return s -def cheatsheet_tex(): +def cheatsheet_tex(sections): print(f"Using docs directory: {DOCS_DIR}") print(f"Using ops docs directory: {OP_DOCS_DIR}") print() output = VERSION_STR + "\n\n" - for (section, title, new_page) in OPS_SECTIONS: + for (section, title, new_col, new_page) in sections: toml_file = Path(OP_DOCS_DIR, section + ".toml") if toml_file.exists() and toml_file.is_file(): output += f"\\group{{{ title }}}\n\n" @@ -122,16 +128,18 @@ def cheatsheet_tex(): output += "\n\n" if new_page: output += "\\pagebreak\n\n" + if new_col: + output += "\\vfill\\null\n\\columnbreak\n" return output def main(): - if len(sys.argv) != 2: - sys.exit("Please supply a filename") - - p = Path(sys.argv[1]).resolve() - p.write_text(cheatsheet_tex()) + if len(sys.argv) != 3: + sys.exit("Please supply a cheatsheet category and filename") + category = sys.argv[1] + p = Path(sys.argv[2]).resolve() + p.write_text(cheatsheet_tex(OPS_SECTIONS[category])) if __name__ == "__main__": main() diff --git a/utils/docs.py b/utils/docs.py index 94ac173d..7218bd39 100755 --- a/utils/docs.py +++ b/utils/docs.py @@ -34,17 +34,20 @@ OPS_SECTIONS = [ "variables", "hardware", - "patterns", + "pitch", + "rhythm", + "metronome", + "random", "controlflow", "maths", - "metronome", "delay", "stack", + "patterns", "queue", - "seed", "turtle", "grid", "midi_in", + "calibration", "i2c", "ansible", "whitewhale", @@ -52,18 +55,18 @@ "earthsea", "orca", "justfriends", + "fader", + "er301", "telex_i", "telex_o", - "er301", - "fader", + "crow", "wslash", - "matrixarchate", - "disting", "wslash_shared", + "wslashtape", "wslashdelay", "wslashsynth", - "wslashtape", - "crow", + "disting", + "matrixarchate", "i2c2midi" ]