diff --git a/.gitignore b/.gitignore index 35d6daaf..f04dbe1f 100644 --- a/.gitignore +++ b/.gitignore @@ -41,9 +41,14 @@ # Debug files *.dSYM/ +# Python +__pycache__/ + # Build outputs /src/match_token.c /src/scanner.c /simulator/tt /module/gitversion.c /tests/tests +/docs/teletype.pdf +/docs/teletype.html diff --git a/CHANGELOG.md b/CHANGELOG.md index 606ba6b9..0f58be40 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,25 +1,30 @@ # Changelog -## vNext +## v2.0 - **BREAKING**: remove `II` op. Ops that required it will now work with out it. (e.g. `II MP.PRESET 1` will become just `MP.PRESET 1`) - **BREAKING**: merge the `MUTE` and `UNMUTE` ops. Now `MUTE x` will return the mute status for trigger `x` (`0` is unmuted, `1` is muted), and `MUTE x y` will set the mute for trigger `x` (`y = 0` to unmute, `y = 1` to mute) +- **BREAKING**: remove unused Meadowphysics ops: `MP.SYNC`, `MP.MUTE`, `MP.UNMUTE`, `MP.FREEZE`, `MP.UNFREEZE` +- **BREAKING**: rename Ansible Meadowphysics ops to start with `ME` - **NEW**: sub commands, use a `;` separator to run multiple commands on a single line, e.g. `X 1; Y 2` -- **NEW**: key bindings rewritten, see [docs](./docs/modes.md) -- **NEW**: multiple commands on each line separated by ':' +- **NEW**: key bindings rewritten - **NEW**: aliases: `+` for `ADD`, `-` for `SUB`, `*` for `MUL`, `/` for `DIV`, `%` for `MOD`, `<<` for `LSH`, `>>` for `RSH`, `==` for `EQ`, `!=` for `NE`, `<` for `LT`, `>` for `GT`, `<=` for `LTE`, `>=` for `GTE`, `!` for `EZ`, `&&` for `AND`, `||` for `OR`, `PRM` for `PARAM`, `TR.P` for `TR.PULSE` - **NEW**: new ops: `LTE` (less than or equal), and `GTE` (greater than or equal) - **NEW**: new pattern ops: `PN.L`, `PN.WRAP`, `PN.START`, `PN.END`, `PN.I`, `PN.HERE`, `PN.NEXT`, `PN.PREV`, `PN.INS`, `PN.RM`, `PN.PUSH` and `PN.POP` - **NEW**: USB disk loading and saving works at any time +- **NEW**: `M` limited to setting the metronome speed to 25ms, added `M!` to allow setting the metronome at unsupported speeds as low as 2ms +- **NEW**: TELEX Aliases: `TO.TR.P` for `TO.TR.PULSE` (plus all sub-commands) and `TI.PRM` for `TI.PARAM` (plus all sub-commands) +- **NEW**: TELEX initialization commands: `TO.TR.INIT n`, `TO.CV.INIT n`, `TO.INIT x`, `TI.PARAM.INIT n`, `TI.IN.INIT n`, and `TI.INIT x` - **IMP**: new Ragel parser backend - **IMP**: script recursion enhanced, maximum recursion depth is 8, and self recursion is allowed - **IMP**: removed the need to prefix `:` and `;` with a space, e.g. `IF X : TR.PULSE 1` becomes `IF X: TR.PULSE` +- **IMP**: `AND` and `OR` now work as boolean logic, rather than bitwise, `XOR` is an alias for `NE` - **FIX**: divide by zero errors now explicitly return a 0 (e.g. `DIV 5 0` now returns 0 instead of -1), previously the behaviour was undefined and would crash the simulator - **FIX**: numerous crashing bugs with text entry - **FIX**: `i2c` bus crashes under high `M` times with external triggers -- **NEW**: TELEX Aliases: `TO.TR.P` for `TO.TR.PULSE` (plus all sub-commands) and `TI.PRM` for `TI.PARAM` (plus all sub-commands) -- **NEW**: TELEX initialization commands: `TO.TR.INIT n`, `TO.CV.INIT n`, `TO.INIT x`, `TI.PARAM.INIT n`, `TI.IN.INIT n`, and `TI.INIT x` +- **FIX**: `P.I` and `PN.I` no longer set values longer than allowed +- **FIX**: `VV` works correctly with negative values -## v1.41 +## v1.4.1 - **NEW**: added Ansible remote commands `LV.CV` and `CY.CV` - **NEW**: Added TELEX Modules Support for the TXi and the TXo - **NEW**: 75 New Operators Across the Two Modules @@ -29,7 +34,7 @@ - **NEW**: Experimental output operators add oscillators, envelopes, independent metronomes, pulse dividing, etc. - **NEW**: [Full List of Methods Found and Maintained Here](https://github.com/bpcmusic/telex/blob/master/commands.md) -## v1.21 +## v1.2.1 - **NEW**: Just Friends ops: `JF.GOD`, `JF.MODE`, `JF.NOTE`, `JF.RMODE`, `JF.RUN`, `JF.SHIFT`, `JF.TICK`, `JF.TR`, `JF.TUNE`, `JF.VOX`, `JF.VTR` ## v1.2 diff --git a/Makefile b/Makefile index ae46c915..53493bf9 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,33 @@ -.PHONY: format +.PHONY: release format \ + clean clean-docs clean-module clean-simulator clean-tests clean-zip + +release: teletype.zip + +clean: clean-docs clean-module clean-simulator clean-tests + +clean-docs: + cd docs && make clean && cd .. + +clean-module: + cd module && make clean && cd .. + +clean-simulator: + cd simulator && make clean && cd .. + +clean-tests: + cd tests && make clean && cd .. + +clean-zip: + rm -f teletype.zip + +teletype.zip: clean-zip + cd module && make && cd .. && \ + cd docs && make teletype.pdf && cd .. && \ + zip -j teletype.zip \ + module/teletype.hex \ + module/flash.sh \ + module/update_firmware.command \ + docs/teletype.pdf + format: find . -type f -name "*.c" -o -name "*.h" | xargs clang-format -style=file -i diff --git a/README.md b/README.md index a515e113..eb11f17c 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,7 @@ http://monome.org/docs/modular/teletype - `module`: `main.c` and additional code for the Eurorack module (e.g. IO and UI) - `tests`: algorithm tests - `simulator`: a (very) simple teletype command parser and simulator +- `docs`: files used to generate the teletype manual ## Building @@ -66,3 +67,46 @@ To format the code using `clang-format`, run `make format` in the project's root [libavr32]: https://github.com/monome/libavr32 [ragel]: http://www.colm.net/open-source/ragel/ + +## Documentation + +In order to build the documentation you will need Python 3.6 or greater, [Pandoc][], as well as the Python libraries specified in the [`requirements.pip`][requirements.pip] file. In addition, to generate the PDF output you will also require [TexLive][] (or [MacTex][]). + +On OSX the dependencies can be installed with `brew`. + +```bash +brew install python3 +brew install pandoc +brew cask install mactex # warning, MacTex is a very large install! +cd utils +pip3 install -r requirements.pip +``` + +On Linux I would suggest using [`virtualenv`][virtualenv] to install all the Python dependencies (including those in the [`requirements.pip`][requirements.pip] file), and to ensure that the `python3` binary is version 3.6 or greater instead of the default of your distro. + +[virtualenv]: https://virtualenv.pypa.io/en/stable/ + +To generate the documentation: + +```bash +cd docs +make # build both teletype.pdf and teletype.html +make teletype.pdf # build just teletype.pdf (requires TexLive or MacTex) +make teletype.html # build just teletype.html +``` + +[requirements.pip]: utils/requirements.pip +[Pandoc]: http://pandoc.org/ +[TexLive]: https://www.tug.org/texlive/ +[MacTex]: https://www.tug.org/mactex/ + +## Making a Release + +To create a `teletype.zip` file containing: + + - `teletype.hex` + - `flash.sh` + - `update_firmware.command` + - `teletype.pdf` + +Run `make release` in the project's root directory diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 00000000..85cb1e9c --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,14 @@ +.PHONY: build clean + +build: teletype.pdf teletype.html + +clean: + rm -f teletype.pdf && rm -f teletype.html + +teletype.pdf: $(wildcard *.md ops/*.md ops/*.toml) \ + ../utils/docs.py ../CHANGELOG.md + ../utils/docs.py teletype.pdf + +teletype.html: $(wildcard *.md ops/*.md ops/*.toml) \ + ../utils/docs.py ../CHANGELOG.md + ../utils/docs.py teletype.html diff --git a/docs/advanced.md b/docs/advanced.md new file mode 100644 index 00000000..a453926f --- /dev/null +++ b/docs/advanced.md @@ -0,0 +1,129 @@ +# Advanced + +## Teletype terminology + +Here is a picture to help understand the naming of the various parts of a Teletype command: + +![Teletype command terminology](img/terminology.jpg) + +`COMMAND` + +: The entire command, e.g. `IF X: Y 1; Z 2;`. + +`PRE` + +: The (optional) part before the _`PRE SEP`_, e.g. `IF X`. + +`POST` + +: The part after the _PRE SEP_, e.g. `Y 1; Z 2`. + +`SUB` + +: A sub command (only allowed in the _`POST`_), e.g. `Y 1`, or `Z 2`. + +`PRE SEP` + +: A _colon_, only one is allowed. + +`SUB SEP` + +: A _semi-colon_, that separates sub commands (if used), only allowed in the _`POST`_. + +`NUM` + +: A number between `−32768` and `32767`. + +`OP` + +: An _operator_, e.g. `X`, `TR.PULSE` + +`MOD` + +: A _modifier_, e.g. `IF`, or `L`. + +## Sub commands + +Sub commands allow you to run multiple commands on a single line by utilising a semi-colon to separate each command, for example the following script: + +``` +X 0 +Y 1 +Z 2 +``` + +Can be rewritten using sub commands as: + +``` +X 0; Y 1; Z 2 +``` + +On their own sub commands allow for an increased command density on the Teletype. However when combined with `PRE` statements, certain operations become a lot easier. + +Firstly, sub commands cannot be used before a `MOD` or in the `PRE` itself. For example, the following is **not allowed**: + +``` +X 1; IF X: TR.PULSE 1 +``` + +We can use them in the `POST` though, particularly with an `IF`, for example: + +``` +IF X: CV 1 N 60; TR.P 1 +IF Y: TR.P 1; TR.P 2; TR.P 3 +``` + +Sub commands can also be used with `L`, though due to (current) limitations on how many separate numbers, `OP`s and `MOD`s are allowed in a single command this can be tricky (even if you can fit the text on a line). + +## Aliases + +In general, aliases are a simple concept to understand. Certain `OP`s have been given shorted names to save space and the amount of typing, for example: + +``` +TR.PULSE 1 +``` + +Can be replaced with: + +``` +TR.P 1 +``` + +Where confusion may arise is with the symbolic aliases that have been given to some of the maths `OP`s. For instance `+` is given as an alias for `ADD` and it _must_ be used as a direct replacement: + +``` +X ADD 1 1 +X + 1 1 +``` + +The key to understanding this is that the Teletype uses _prefix notation_[^polish] always, even when using mathematical symbols. + +[^polish]: Also know as _Polish notation_. + +The following example (using _infix notation_) **will not work**: + +``` +X 1 + 1 +``` + +Aliases are entirely optional, most `OP`s do not have aliases. Consult the `OP` tables and documentation to find them. + +## Avoiding non-determinism + +Although happy accidents in the modular world are one of it's many joys, when writing computer programs they can be incredibly frustrating. Here are some small tips to help keep things predictable (when you want to them to be): + + 1. **Don't use variables unless you need to.** + + This is not to say that variables are not useful, rather it's the opposite and they are extremely powerful. But it can be hard to keep a track of what each variable is used for and on which script it is used. Rather, try to save using variables for when you do want non-deterministic (i.e. _variable_) behaviour. + + 2. **Consider using `I` as a temporary variable.** + + If you do find yourself needing a variable, particularly one that is used to continue a calculation on another line, consider using the variable `I`. Unlike the other variables, `I` is overwritten whenever `L` is used, and as such, is implicitly transient in nature. One should never need to worry about modifying the value of `I` and causing another script to malfunction, as no script should ever assume the value of `I`. + + 3. **Use `PN` versions of `OP`s.** + + Most `P` `OP`s are now available as `PN` versions that ignore the value of `P.I`. (e.g. `PN.START` for `P.START`). Unless you explicitly require the non-determinism of `P` versions, stick to the `PN` versions (space allowing). + + 4. **Avoid using `A`, `B`, `C` and `D` to refer to the trigger outputs, instead use the numerical values directly.** + + As `A-D` are variables, they may no longer contain the values `1-4`, and while this was the recommend way to name triggers, it is no longer consider ideal. Newer versions of the Teletype hardware have replaced the labels on the trigger outputs, with the numbers `1` to `4`. diff --git a/docs/img/terminology.jpg b/docs/img/terminology.jpg new file mode 100644 index 00000000..1a789af0 Binary files /dev/null and b/docs/img/terminology.jpg differ diff --git a/docs/modes.md b/docs/modes.md index ac3e7e55..af4d3563 100644 --- a/docs/modes.md +++ b/docs/modes.md @@ -1,3 +1,4 @@ +# Modes ## Global key bindings @@ -9,7 +10,7 @@ These bindings work everywhere. | `` | preset read mode, or return to last mode | | `alt-` | preset write mode | | `win-` | clear delays, stack and slews | -| `` | help text, or return to last mode | +| `-?` | help text, or return to last mode | | `` to `` | run corresponding script | | `` | run metro script | | `` | run init script | @@ -17,6 +18,8 @@ These bindings work everywhere. | `alt-` | edit metro script | | `alt-` | edit init script | | `` to `` | run corresponding script | +| `` / `` | jump to pattern mode | +| `` / `` | jump to live mode | ## Text editing diff --git a/docs/ops.md b/docs/ops.md new file mode 100644 index 00000000..9c485324 --- /dev/null +++ b/docs/ops.md @@ -0,0 +1,2 @@ +# OPs and MODs + diff --git a/docs/ops/ansible.md b/docs/ops/ansible.md new file mode 100644 index 00000000..0329a1ac --- /dev/null +++ b/docs/ops/ansible.md @@ -0,0 +1,2 @@ +## Ansible + diff --git a/docs/ops/ansible.toml b/docs/ops/ansible.toml new file mode 100644 index 00000000..8d2258f1 --- /dev/null +++ b/docs/ops/ansible.toml @@ -0,0 +1,183 @@ +["KR.PRE"] +prototype = "KR.PRE" +prototype_set = "KR.PRE x" +short = "return current preset / load preset `x`" + +["KR.PERIOD"] +prototype = "KR.PERIOD" +prototype_set = "KR.PERIOD x" +short = "get/set internal clock period" + +["KR.PAT"] +prototype = "KR.PAT" +prototype_set = "KR.PAT x" +short = "get/set current pattern" + +["KR.SCALE"] +prototype = "KR.SCALE" +prototype_set = "KR.SCALE x" +short = "get/set current scale" + +["KR.POS"] +prototype = "KR.POS x y" +prototype_set = "KR.POS x y z" +short = "get/set position `z` for track `z`, parameter `y`" +description = """ +Set position to `z` for track `x`, parameter `y`. + +A value of `0` for `x` means all tracks. + +A value of `0` for `y` means all parameters + +Parameters: + + - `0` = all + - `1` = trigger + - `2` = note + - `3` = octave + - `4` = length +""" + +["KR.L.ST"] +prototype = "KR.L.ST x y" +prototype_set = "KR.L.ST x y z" +short = "get loop start for track `x`, parameter `y` / set to `z`" + +["KR.L.LEN"] +prototype = "KR.L.LEN" +prototype_set = "KR.L.LEN" +short = "get length of trrack `x`, parameter `y` / set to `z`" + +["KR.RES"] +prototype = "KR.RES x y" +short = "reset to loop start for track `x`, parameter `y`" + +["ME.PRE"] +prototype = "ME.PRE" +prototype_set = "ME.PRE x" +short = "return current preset / load preset `x`" + +["ME.SCALE"] +prototype = "ME.SCALE" +prototype_set = "ME.SCALE x" +short = "get/set current scale" + +["ME.PERIOD"] +prototype = "ME.PERIOD" +prototype_set = "ME.PERIOD x" +short = "get/set internal clock period" + +["ME.STOP"] +prototype = "ME.STOP x" +short = "stop channel `x` (`0` = all)" + +["ME.RES"] +prototype = "ME.RES x" +short = "reset channel `x` (`0` = all), also used as \"start\"" + +["LV.PRE"] +prototype = "LV.PRE" +prototype_set = "LV.PRE x" +short = "return current preset / load preset `x`" + +["LV.RES"] +prototype = "LV.RES x" +short = "reset, `0` for soft reset (on next ext. clock), `1` for hard reset" + +["LV.POS"] +prototype = "LV.POS" +prototype_set = "LV.POS x" +short = "get/set current position" + +["LV.L.ST"] +prototype = "LV.L.ST" +prototype_set = "LV.L.ST x" +short = "get/set loop start" + +["LV.L.LEN"] +prototype = "LV.L.LEN" +prototype_set = "LV.L.LEN x" +short = "get/set loop length" + +["LV.L.DIR"] +prototype = "LV.L.DIR" +prototype_set = "LV.L.DIR x" +short = "get/set loop direction" + +["LV.CV"] +prototype = "LV.CV x" +short = "get the current CV value for channel `x`" + +["CY.PRE"] +prototype = "CY.PRE" +prototype_set = "CY.PRE x" +short = "return current preset / load preset `x`" + +["CY.RES"] +prototype = "CY.RES x" +short = "reset channel `x` (`0` = all)" + +["CY.POS"] +prototype = "CY.POS x" +prototype_set = "CY.POS x y" +short = "get / set position of channel `x` (`x = 0` to set all), position between `0-255`" + +["CY.REV"] +prototype = "CY.REV x" +short = "reverse channel `x` (`0` = all)" + +["CY.CV"] +prototype = "CY.CV x" +short = "get the current CV value for channel `x`" + +["MID.SLEW"] +prototype = "MID.SLEW t" +short = "set pitch slew time in ms (applies to all allocation styles except FIXED)" + +["MID.SHIFT"] +prototype = "MID.SHIFT o" +short = "shift pitch CV by standard Teletype pitch value (e.g. `N 6`, `V -1`, etc)" + +["ARP.HLD"] +prototype = "ARP.HLD h" +short = "`0` disables key hold mode, other values enable" + +["ARP.STY"] +prototype = "ARP.STY y" +short = "set base arp style [0-7]" + +["ARP.GT"] +prototype = "ARP.GT v g" +short = "set voice gate length [0-127], scaled/synced to course divisions of voice clock" + +["ARP.SLEW"] +prototype = "ARP.SLEW v t" +short = "set voice slew time in ms" + +["ARP.RPT"] +prototype = "ARP.RPT v n s" +short = "set voice pattern repeat, `n` times [0-8], shifted by `s` semitones [-24, 24]" + +["ARP.DIV"] +prototype = "ARP.DIV v d" +short = "set voice clock divisor (euclidean length), range [1-32]" + +["ARP.FIL"] +prototype = "ARP.FIL v f" +short = "set voice euclidean fill, use 1 for straight clock division, range [1-32]" + +["ARP.ROT"] +prototype = "ARP.ROT v r" +short = "set voice euclidean rotation, range [-32, 32]" + +["ARP.ER"] +prototype = "ARP.ER v f d r" +short = "set all euclidean rhythm" + +["ARP.RES"] +prototype = "ARP.RES v" +short = "reset voice clock/pattern on next base clock tick" + +["ARP.SHIFT"] +prototype = "ARP.SHIFT v o" +short = "shift voice cv by standard tt pitch value (e.g. N 6, V -1, etc)" diff --git a/docs/ops/controlflow.md b/docs/ops/controlflow.md new file mode 100644 index 00000000..77a8428d --- /dev/null +++ b/docs/ops/controlflow.md @@ -0,0 +1,2 @@ +## Control flow + diff --git a/docs/ops/controlflow.toml b/docs/ops/controlflow.toml new file mode 100644 index 00000000..2ae75407 --- /dev/null +++ b/docs/ops/controlflow.toml @@ -0,0 +1,105 @@ +[IF] +prototype = "IF x: ..." +short = "if `x` is not zero execute command" +description = """ +If `x` is not zero execute command + +#### Advanced `IF` / `ELIF` / `ELSE` usage + + 1. Intermediate statements always run + + ```text + SCRIPT 1: + IF 0: 0 => do nothing + TR.P 1 => always happens + ELSE: TR.P 2 => else branch runs because of the previous IF + ``` + + 2. `ELSE` without an `IF` + + ```text + SCRIPT 1: + ELSE: TR.P 1 => never runs, as there is no preceding IF + ``` + + + 3. `ELIF` without an `IF` + + ```text + SCRIPT 1: + ELIF 1: TR.P 1 => never runs, as there is no preceding IF + ``` + + 4. Independent scripts + + ```text + SCRIPT 1: + IF 1: TR.P 1 => pulse output 1 + + SCRIPT 2: + ELSE: TR.P 2 => never runs regardless of what happens in script 1 + (see example 2) + ``` + + 5. Dependent scripts + + ```text + SCRIPT 1: + IF 0: TR.P 1 => do nothing + SCRIPT 2 => will pulse output 2 + + SCRIPT 2: + ELSE: TR.P 2 => will not pulse output 2 if called directly, + but will if called from script 1 + ``` +""" + +[ELIF] +prototype = "ELIF x: ..." +short = "if all previous `IF` / `ELIF` fail, and `x` is not zero, execute command" + +[ELSE] +prototype = "ELSE: ..." +short = "if all previous `IF` / `ELIF` fail, excute command" + +[L] +prototype = "L x y: ..." +short = "run the command sequentially with `I` values from `x` to `y`" +description = """ +Run the command sequentially with `I` values from `x` to `y`. + +For example: + +``` +L 1 4: TR.PULSE I => pulse outputs 1, 2, 3 and 4 +L 4 1: TR.PULSE I => pulse outputs 4, 3, 2 and 1 +``` +""" + +[PROB] +prototype = "PROB x: ..." +short = "potentially execute command with probability `x` (0-100)" + +[SCRIPT] +prototype = "SCRIPT x" +short = "execute script `x` (1-8), recursion allowed" +description = """ +Execute script `x` (1-8), recursion allowed. + +There is a limit of 8 for the maximum number of nested calls to `SCRIPT` to stop infinite loops from locking up the Teletype. +""" + +[SCENE] +prototype = "SCENE x" +short = "load scene `x` (0-31)" +description = """ +Load scene `x` (0-31). + +Does _not_ execute the `I` script. + +**WARNING**: You will lose any unsaved changes to your scene. +""" + +[KILL] +prototype = "KILL" +short = "clears stack, clears delays, cancels pulses, cancels slews" \ No newline at end of file diff --git a/docs/ops/delay.md b/docs/ops/delay.md new file mode 100644 index 00000000..cc961882 --- /dev/null +++ b/docs/ops/delay.md @@ -0,0 +1,7 @@ +## Delay +The `DEL` delay op allow commands to be sheduled for execution after a +defined interval by placing them into a buffer which can hold up to 8 commands. +Commands can be delayed by up to 16 seconds + +In LIVE mode, the second icon (an upside-down U) will be lit up when there is +a command in the `DEL` buffer. diff --git a/docs/ops/delay.toml b/docs/ops/delay.toml new file mode 100644 index 00000000..dc9cf31b --- /dev/null +++ b/docs/ops/delay.toml @@ -0,0 +1,14 @@ +["DEL"] +prototype = "DEL x: ..." +short = "Delay command by `x` ms" +description = """ +Delay the command following the colon by `x` ms by placing it into a buffer. +The buffer can hold up to 8 commands. If the buffer is full, additional commands +will be discarded. +""" +["DEL.CLR"] +prototype = "DEL.CLR" +short = "Clear the delay buffer" +description = """ +Clear the delay buffer, cancelling the pending commands. +""" diff --git a/docs/ops/earthsea.md b/docs/ops/earthsea.md new file mode 100644 index 00000000..aa1a1d65 --- /dev/null +++ b/docs/ops/earthsea.md @@ -0,0 +1 @@ +## Earthsea diff --git a/docs/ops/earthsea.toml b/docs/ops/earthsea.toml new file mode 100644 index 00000000..88163683 --- /dev/null +++ b/docs/ops/earthsea.toml @@ -0,0 +1,63 @@ +["ES.PRESET"] +prototype = "ES.PRESET x" +short = "Recall preset `x` (0-7)" +description = """ +Recall the preset in location `x`. This will stop the currently playing pattern. +""" + +["ES.MODE"] +prototype = "ES.MODE x" +short = "Set pattern clock mode. (0=normal, 1=II clock)" +description = """ +Sets the pattern clock mode. Setting `x` to 0 sets Earthsea to use it's internal clock. Setting `x` to 1 clocks Earthsea via the `ES.CLOCK` command. +""" + +["ES.CLOCK"] +prototype = "ES.CLOCK x" +short = "If II clocked, next pattern event" +description = """ +If Earthsea is II clocked (see `ES.MODE`), and `x` is non-zero, advance to the next pattern event. +""" + +["ES.RESET"] +prototype = "ES.RESET x" +short = "Reset pattern to start (and start playing)" +description = """ +If `x` is non-zero, reset the position in the current pattern to the start and start playing. +""" + +["ES.PATTERN"] +prototype = "ES.PATTERN x" +short = "Select playing pattern (0-15)" +description = """ +Select pattern (0-15) from the current preset. +""" + +["ES.TRANS"] +prototype = "ES.TRANS x" +short = "Transpose the current pattern" +description = """ +Apply a transposition relative to the current 'root' position. Integer divisions of `x` shift the root note up or down a row, `x` modulo 5 will shift the position +left or right up to 4 notes. +""" + +["ES.STOP"] +prototype = "ES.STOP x" +short = "Stop pattern playback." +description = """ +If `x` is non-zero, stop pattern playback, or stop record if currently recording. +""" + +["ES.TRIPLE"] +prototype = "ES.TRIPLE x" +short = "Recall triple shape (1-4)" +description = """ +Recall triple shape (1-4). +""" + +["ES.MAGIC"] +prototype = "ES.MAGIC x" +short = "Magic shape (1= halfspeed, 2=doublespeed, 3=linearize)" +description = """ +Apply one of the magic shapes, (1= halfspeed, 2=doublespeed, 3=linearize). Other shapes are not currently available via II ops. +""" diff --git a/docs/ops/hardware.md b/docs/ops/hardware.md new file mode 100644 index 00000000..88ed2473 --- /dev/null +++ b/docs/ops/hardware.md @@ -0,0 +1,4 @@ +## Hardware +The Teletype trigger inputs are numbered 1-8, the CV and trigger outputs 1-4. +See the Ansible documentation for details of the Ansible output numbering +when in Teletype mode. diff --git a/docs/ops/hardware.toml b/docs/ops/hardware.toml new file mode 100644 index 00000000..dccca615 --- /dev/null +++ b/docs/ops/hardware.toml @@ -0,0 +1,108 @@ +["CV"] +prototype = "CV x" +prototype_set = "CV x y" +short = "CV target value" +description = """ +Get the value of CV associated with output `x`, or set the CV output of `x` to +`y`. +""" + +["CV.OFF"] +prototype = "CV.OFF x" +prototype_set = "CV.OFF x y" +short = "CV offset added to output" +description = """ +Get the value of the offset added to the CV value at output `x`. The offset is +added at the final stage. Set the value of the offset added to the CV value at +output `x` to `y`. +""" + +["CV.SET"] +prototype = "CV.SET x" +short = "Set CV value" +description = """ +Set the CV value at output `x` bypassing any slew settings. +""" + +["CV.SLEW"] +prototype = "CV.SLEW x" +prototype_set = "CV.SLEW x y" +short = "Get/set the CV slew time in ms" +description = """ +Get the slew time in ms associated with CV output `x`. Set the slew time +associated with CV output `x` to `y` ms. +""" + +["IN"] +prototype = "IN" +short = "Get the value of IN jack (0-16383)" +description = """ +Get the value of the IN jack. This returns a valuue in the range 0-16383. +""" + +["PARAM"] +prototype = "PARAM" +aliases = ["PRM"] +short = "Get the value of PARAM knob (0-16383)" +description = """ +Get the value of the PARAM knob. This returns a valuue in the range 0-16383. +""" + +["TR"] +prototype = "TR" +prototype_set = "TR" +short = "Set trigger output x to y (0-1)" +description = """ +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)" +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. +""" + +["TR.TIME"] +prototype = "TR.TIME x" +prototype_set = "TR.TIME x y" +short = "Set the pulse time of trigger x to y ms" +description = """ +Get the pulse time of trigger output `x`. Set the pulse time of trigger +output `x` to `y`ms. +""" + +["TR.TOG"] +prototype = "TR.TOG x" +short = "Flip the state of trigger output x" +description = """ +Flip the state of trigger output `x`. +""" + +["TR.PULSE"] +prototype = "TR.PULSE x" +aliases = ["TR.P"] +short = "Pulse trigger output x" +description = """ +Pulse trigger output x. +""" + +["MUTE"] +prototype = "MUTE x" +prototype_set = "MUTE x y" +short = "Disable trigger input x" +description = """ +Mute the trigger input on `x` (0-7) when `y` is non-zero. +""" + +["STATE"] +prototype = "STATE x" +short = "Read the current state of input x" +description = """ +Read the current state of trigger input `x` (0=low, 1=high). +""" + diff --git a/docs/ops/maths.md b/docs/ops/maths.md new file mode 100644 index 00000000..0806bf98 --- /dev/null +++ b/docs/ops/maths.md @@ -0,0 +1,4 @@ +## Maths + +Logical operators such as `EQ`, `OR` and `LT` return `1` for true, and `0` for false. + diff --git a/docs/ops/maths.toml b/docs/ops/maths.toml new file mode 100644 index 00000000..b38bf48b --- /dev/null +++ b/docs/ops/maths.toml @@ -0,0 +1,188 @@ +[ADD] +prototype = "ADD x y" +aliases = ["+"] +short = "add `x` and `y` together" + +[SUB] +prototype = "SUB x y" +aliases = ["-"] +short = "subtract `y` from `x`" + +[MUL] +prototype = "MUL x y" +aliases = ["*"] +short = "multiply `x` and `y` together" + +[DIV] +prototype = "DIV x y" +aliases = ["/"] +short = "divide `x` by `y`" + +[MOD] +prototype = "MOD x y" +aliases = ["%"] +short = "find the remainder after division of `x` by `y`" + +[RAND] +prototype = "RAND x" +short = "generate a random number between `0` and `x` inclusive" + +[RRAND] +prototype = "RRAND x y" +short = "generate a random number between `x` and `y` inclusive" + +[TOSS] +prototype = "TOSS" +short = "randomly return `0` or `1`" + +[MIN] +prototype = "MIN x y" +short = "return the minimum of `x` and `y`" + +[MAX] +prototype = "MAX x y" +short = "return the maximum of `x` and `y`" + +[LIM] +prototype = "LIM x y z" +short = "limit the value `x` to the range `y` to `z` inclusive" + +[WRAP] +prototype = "WRAP x y z" +short = "limit the value `x` to the range `y` to `z` inclusive, but with wrapping" + +[QT] +prototype = "QT x y" +short = "round `x` to the closest multiple of `y` (quantise)" + +[AVG] +prototype = "AVG x y" +short = "the average of `x` and `y`" + +[EQ] +prototype = "EQ x y" +aliases = ["=="] +short = "does `x` equal `y`" + +[NE] +prototype = "NE x y" +aliases = ["!=", "XOR"] +short = "`x` is not equal to `y`" + +[LT] +prototype = "LT x y" +aliases = ["<"] +short = "`x` is less than `y`" + +[GT] +prototype = "GT x y" +aliases = [">"] +short = "`x` is greater than `y`" + +[LTE] +prototype = "LTE x y" +aliases = ["<="] +short = "`x` is less than or equal to `y`" + +[GTE] +prototype = "GTE x y" +aliases = [">="] +short = "`x` is greater than or equal to `y`" + +[EZ] +prototype = "EZ x" +aliases = ["!"] +short = "`x` is `0`, equivalent to logical NOT" + +[NZ] +prototype = "NZ x" +short = "`x` is not `0`" + +[LSH] +prototype = "LSH x y" +aliases = ["<<"] +short = "left shift `x` by `y` bits, in effect multiply by `2` to the power of `x`" + +[RSH] +prototype = "RSH x y" +aliases = [">>"] +short = "right shift `x` by `y` bits, in effect divide by `2` to the power of `x`" + +[ABS] +prototype = "ABS x" +short = "absolute value of `x`" + +[AND] +prototype = "AND x y" +aliases = ["&&"] +short = "logical AND of `x` and `y`" +description = """ +Logical AND of `x` and `y`. Returns `1` if both `x` and `y` are greater than `0`, otherwise it returns `0`. +""" + +[OR] +prototype = "OR x y" +aliases = ["||"] +short = "logical OR of `x` and `y`" +description = """ +Logical OR of `x` and `y`. Returns `1` if either `x` or `y` 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" +short = "scale `i` from range `a` to `b` to range `x` to `y`, i.e. `i * (y - x) / (b - a)`" + +[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). +""" + +[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 +``` +""" + +[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`)" diff --git a/docs/ops/meadowphysics.md b/docs/ops/meadowphysics.md new file mode 100644 index 00000000..f0b0fefd --- /dev/null +++ b/docs/ops/meadowphysics.md @@ -0,0 +1,3 @@ +## Meadowphysics + +For use on the original Meadowphysics module with version 2 firmware. Reference the Ansible ops for using Meadowphysics on the Ansible module. diff --git a/docs/ops/meadowphysics.toml b/docs/ops/meadowphysics.toml new file mode 100644 index 00000000..cdda85dc --- /dev/null +++ b/docs/ops/meadowphysics.toml @@ -0,0 +1,11 @@ +["MP.PRESET"] +prototype = "MP.PRESET x" +short = "set Meadowphysics to preset `x` (indexed from `0`)" + +["MP.RESET"] +prototype = "MP.RESET x" +short = "reset countdown for channel `x` (`0` = all, `1-8` = individual channels)" + +["MP.STOP"] +prototype = "MP.STOP x" +short = "reset channel `x` (`0` = all, `1-8` = individual channels)" diff --git a/docs/ops/metronome.md b/docs/ops/metronome.md new file mode 100644 index 00000000..f7397a78 --- /dev/null +++ b/docs/ops/metronome.md @@ -0,0 +1,5 @@ +## Metronome + +An internal metronome executes the M script at a specified rate (in ms). By default the metronome is enabled (`M.ACT 1`) and set to 1000ms (`M 1000`). The metro can be set as fast as 25ms (`M 25`). An additional `M!` op allows for setting the metronome to experimental rates as high as 2ms (`M! 2`). **WARNING**: when using a large number of i2c commands in the M script at metro speeds beyond the 25ms teletype stability issues can occur. + +Access the M script directly with `alt-` or run the script once using ``. diff --git a/docs/ops/metronome.toml b/docs/ops/metronome.toml new file mode 100644 index 00000000..34153e04 --- /dev/null +++ b/docs/ops/metronome.toml @@ -0,0 +1,19 @@ +[M] +prototype = "M" +prototype_set = "M x" +short = "get/set metronome interval to `x` (in ms), default `1000`, minimum value `25`" + +["M!"] +prototype = "M!" +prototype_set = "M! x" +short = "get/set metronome to experimental interval `x` (in ms), minimum value `2`" + +["M.ACT"] +prototype = "M.ACT" +prototype_set = "M.ACT x" +short = "get/set metronome activation to `x` (`0/1`), default `1` (enabled)" + +["M.RESET"] +prototype = "M.RESET" +short = "hard reset metronome count without triggering" + diff --git a/docs/ops/orca.md b/docs/ops/orca.md new file mode 100644 index 00000000..6890b656 --- /dev/null +++ b/docs/ops/orca.md @@ -0,0 +1,3 @@ +## Orca + +Remote commands for Orca (alternative WW firmware). For detailed info and tips on usage please refer to the [Orca manual](https://github.com/scanner-darkly/monome-mods/wiki/Orca---manual#teletype-integration). \ No newline at end of file diff --git a/docs/ops/orca.toml b/docs/ops/orca.toml new file mode 100644 index 00000000..6761a72a --- /dev/null +++ b/docs/ops/orca.toml @@ -0,0 +1,84 @@ +["OR.CLK"] +prototype = "OR.CLK x" +short = "Advance track `x` (`1-4`)" +description = """ +Gives you the ability to clock individual tracks. The master clock will still advance all 4 tracks. +""" + +["OR.RST"] +prototype = "OR.RST x" +short = "Reset track `x` (`1-4`)" + +["OR.GRST"] +prototype = "OR.GRST x" +short = "Global reset (`x` can be any value)" + +["OR.TRK"] +prototype = "OR.TRK x" +short = "Choose track `x` (`1-4`) to be used by `OR.DIV`, `OR.PHASE`, `OR.WGT` or `OR.MUTE`" + +["OR.DIV"] +prototype = "OR.DIV x" +short = "Set divisor for selected track to `x` (`1-16`)" + +["OR.PHASE"] +prototype = "OR.PHASE x" +short = "Set phase for selected track to `x` (`0-16`)" + +["OR.WGT"] +prototype = "OR.WGT x" +short = "Set weight for selected track to `x` (`1-8`)" + +["OR.MUTE"] +prototype = "OR.MUTE x" +short = "Mute trigger selected by `OR.TRK` (`0` = on, `1` = mute)" + +["OR.SCALE"] +prototype = "OR.SCALE x" +short = "Select scale `x` (`1-16`)" +description = """ +Value of `1-16` will select scale for both CV A and CV B. To select individual scales append their numbers, for instance, `105` will select scale 1 for CV A and scale 5 for CV B, and `1005` will select scale 10 for CV A and scale 5 for CV B. +""" + +["OR.BANK"] +prototype = "OR.BANK x" +short = "Select preset bank `x` (`1-8`)" + +["OR.PRESET"] +prototype = "OR.PRESET x" +short = "Select preset `x` (`1-8`)" + +["OR.RELOAD"] +prototype = "OR.RELOAD x" +short = "Reload preset or bank (`0` - current preset, `1` - current bank, `2` - all banks)" +description = """ +Abandons any unsaved changes and reloads selected presets/banks from flash. Could be useful in `I` script. +""" + +["OR.ROTS"] +prototype = "OR.ROTS x" +short = "Rotate scales by `x` (`1-15`)" +description = """ +Rotates scales up. To rotate them down set `x` to `16` minus the amount. +""" + +["OR.ROTW"] +prototype = "OR.ROTW x" +short = "Rotate weights by `x` (`1-3`)" +description = """ +Rotates weights up. To rotate them down set `x` to `4` minus the amount. +""" + +["OR.CVA"] +prototype = "OR.CVA x" +short = "Select tracks for CV A where `x` is a binary number representing the tracks" +description = """ +Convert a binary number representing selected tracks (so `1001` will select tracks 1 and 4, for instance) and set `x` to that. +""" + +["OR.CVB"] +prototype = "OR.CVB x" +short = "Select tracks for CV B where `x` is a binary number representing the tracks" +description = """ +Convert a binary number representing selected tracks (so `1001` will select tracks 1 and 4, for instance) and set `x` to that. +""" diff --git a/docs/ops/patterns.md b/docs/ops/patterns.md new file mode 100644 index 00000000..04b1617f --- /dev/null +++ b/docs/ops/patterns.md @@ -0,0 +1,16 @@ +##Patterns +Patterns facilitate musical data manipulation– lists of numbers that can be used as sequences, chord sets, rhythms, or whatever you choose. Pattern memory consists four banks of 64 steps. Functions are provided for a variety of pattern creation, transformation, and playback. + +New in teletype 2.0, a second version of all Pattern ops have been added. The original `P` ops (`P`, `P.L`, `P.NEXT`, etc.) act upon the ‘working pattern’ as defined by `P.N`. By default the working pattern is assigned to pattern 0 (`P.N 0`), in order to execute a command on pattern 1 using `P` ops you would need to first reassign the working pattern to pattern 1 (`P.N 1`). + +The new set of ops, `PN` (`PN`, `PN.L`, `PN.NEXT`, etc.), include a variable to designate the pattern number they act upon, and don’t effect the pattern assignment of the ‘working pattern’ (ex: `PN.NEXT 2` would increment pattern 2 one index and return the value at the new index). For simplicity throughout this introduction we will only refer to the `P` ops, but keep in mind that they now each have a `PN` counterpart (all of which are detailed below) + +Both patterns and their arrays of numbers are indexed from 0. This makes the first pattern number 0, and the first value of a pattern is index 0. The pattern index (`P.I`) functions like a playhead which can be moved throughout the pattern and/or read using ops: `P`, `P.I`, `P.HERE`, `P.NEXT`, and `P.PREV`. You can contain pattern movements to ranges of a pattern and define wrapping behavior using ops: `P.START`, `P.END`, `P.L`, and `P.WRAP`. + +Values can be edited, added, and retrieved from the command line using ops: `P`, `P.INS`, `P.RM`, `P.PUSH`, `P.HERE`, `P.NEXT`, and `P.PREV`. Some of these ops will additionally impact the pattern length upon their execution: `P.INS`, `P.RM`, `P.PUSH`, and `P.POP`. + +To see your current pattern data use the `` key to cycle through live mode, edit mode, and pattern mode. In pattern mode each of the 4 patterns is represented as a column. You can use the arrow keys to navigate throughout the 4 patterns and their 64 values. For reference a key of numbers runs the down the lefthand side of the screen in pattern mode displaying 0-63. + +From a blank set of patterns you can enter data by typing into the first cell in a column. Once you hit `` you will move to the cell below and the pattern length will become one step long. You can continue this process to write out a pattern of desired length. The step you are editing is always the brightest. As you add steps to a pattern by editing the value and hitting `` they become brighter than the unused cells. This provides a visual indication of the pattern length. + +The start and end points of a pattern are represented by the dotted line next to the column, and the highlighted dot in this line indicates the current pattern index for each of the patterns. See the key bindings for an extensive list of editing shortcuts available within pattern mode. diff --git a/docs/ops/patterns.toml b/docs/ops/patterns.toml new file mode 100644 index 00000000..148150d4 --- /dev/null +++ b/docs/ops/patterns.toml @@ -0,0 +1,186 @@ +["P.N"] +prototype = "P.N" +prototype_set = "P.N x" +short = "get/set the pattern number for the working pattern, default `0`" +description = "get/set the pattern number for the working pattern, default `0`. All `P` ops refer to this pattern." + +[P] +prototype = "P x" +prototype_set = "P x y" +short = "get/set the value of the working pattern at index `x`" + +description = """get/set the value of the working pattern at index `x`. All positive values (`0-63`) can be set or returned while index values greater than 63 clip to 63. Negative `x` values are indexed backwards from the end of the pattern length of the working pattern. + +Example: + +with a pattern length of 6 for the working pattern: + +`P 10` +retrieves the working pattern value at index 6 + +`P.I -2` +retrieves the working pattern value at index 4 + +This applies to `PN` as well, except the pattern number is the first variable and a second variable specifies the index. +""" + +[PN] +prototype = "PN x y" +prototype_set = "PN x y z" +short = "get/set the value of pattern `x` at index `y`" + +["P.L"] +prototype = "P.L" +prototype_set = "P.L x" +short = "get/set pattern length of the working pattern, non-destructive to data" + +["PN.L"] +prototype = "PN.L x" +prototype_set = "PN.L x y" +short = "get/set pattern length of pattern x. non-destructive to data" + +["P.WRAP"] +prototype = "P.WRAP" +prototype_set = "P.WRAP x" +short = "when the working pattern reaches its bounds does it wrap (`0/1`), default `1` (enabled)" + +description = """when the working pattern reaches its bounds does it wrap (`0/1`). With `PN.WRAP` enabled (`1`), when an index reaches its upper or lower bound using `P.NEXT` or `P.PREV` it will wrap to the other end of the pattern and you can continue advancing. The bounds of P.WRAP are defined through `P.L`, `P.START`, and `P.END`. + +If wrap is enabled (`P.WRAP 1`) a pattern will begin at its start location and advance to the lesser index of either its end location or the end of its pattern length + +Examples: + +With wrap enabled, a pattern length of 6, a start location of 2 , and an end location of 8. + +`P.WRAP 1; P.L 6; P.START 2; P.END 8` + +The pattern will wrap between the indexes `2` and `5`. + +With wrap enabled, a pattern length of 10, a start location of 3, and an end location of 6. + +`P.WRAP 1; P.L 10; P.START 3; P.END 6` + +The pattern will wrap between the indexes `3` and `6`. + +If wrap is disabled (`P.WRAP 0`) a pattern will run between its start and end locations and halt at either bound. + +This applies to `PN.WRAP` as well, except the pattern number is the first variable and a second variable specifies the wrap behavior (`0/1`). +""" + +["PN.WRAP"] +prototype = "PN.WRAP x" +prototype_set = "PN.WRAP x y" +short = "when pattern `x` reaches its bounds does it wrap (`0/1`), default `1` (enabled)" + +["P.START"] +prototype = "P.START" +prototype_set = "P.START x" +short = "get/set the start location of the working pattern, default `0`" + +["PN.START"] +prototype = "PN.START x" +prototype_set = "PN.START x y" +short = "get/set the start location of pattern `x`, default `0`" + +["P.END"] +prototype = "P.END" +prototype_set = "P.END x" +short = "get/set the end location of the working pattern, default `63`" + +["PN.END"] +prototype = "PN.END x" +prototype_set = "PN.END x y" +short = "get/set the end location of the pattern `x`, default `63`" + +["P.I"] +prototype = "P.I" +prototype_set = "P.I x" +short = "get/set index position for the working pattern." +description = """ +get/set index position for the working pattern. all values greater than pattern length return the first step beyond the pattern length. negative values are indexed backwards from the end of the pattern length. + +Example: + +With a pattern length of `6` (`P.L 6`), yielding an index range of `0-5`: + +`P.I 3` + +moves the index of the working pattern to `3` + +`P.I 10` + +moves the index of the working pattern to `6` + +`P.I -2` + +moves the index of the working pattern to `4` + +This applies to `PN.I`, except the pattern number is the first variable and a second variable specifics the index. +""" + +["PN.I"] +prototype = "PN.I x" +prototype_set = "PN.I x y" +short = "get/set index position for pattern `x`" + +["P.HERE"] +prototype = "P.HERE" +prototype_set = "P.HERE x " +short = "get/set value at current index of working pattern" + +["PN.HERE"] +prototype = "PN.HERE x" +prototype_set = "PN.HERE x y" +short = "get/set value at current index of pattern `x`" + +["P.NEXT"] +prototype = "P.NEXT" +prototype_set = "P.NEXT x" +short = "increment index of working pattern then get/set value" + +["PN.NEXT"] +prototype = "PN.NEXT x" +prototype_set = "PN.NEXT x y" +short = "increment index of pattern `x` then get/set value" + +["P.PREV"] +prototype = "P.PREV" +prototype_set = "P.PREV x" +short = "decrement index of working pattern then get/set value" + +["PN.PREV"] +prototype = "PN.PREV x" +prototype_set = "PN.PREV x y" +short = "decrement index of pattern `x` then get/set value" + +["P.INS"] +prototype = "P.INS x y" +short = "insert value `y` at index `x` of working pattern, shift later values down, destructive to loop length" + +["PN.INS"] +prototype = "PN.INS x y z" +short = "insert value `z` at index `y` of pattern `x`, shift later values down, destructive to loop length" + +["P.RM"] +prototype = "P.RM x" +short = "delete index `x` of working pattern, shift later values up, destructive to loop length" + +["PN.RM"] +prototype = "PN.RM x y" +short = "delete index `y` of pattern `x`, shift later values up, destructive to loop length" + +["P.PUSH"] +prototype = "P.PUSH x" +short = "insert value `x` to the end of the working pattern (like a stack), destructive to loop length" + +["PN.PUSH"] +prototype = "PN.PUSH x y" +short = "insert value `y` to the end of pattern `x` (like a stack), destructive to loop length" + +["P.POP"] +prototype = "P.POP" +short = "return and remove the value from the end of the working pattern (like a stack), destructive to loop length" + +["PN.POP"] +prototype = "PN.POP x" +short = "return and remove the value from the end of pattern `x` (like a stack), destructive to loop length" diff --git a/docs/ops/queue.md b/docs/ops/queue.md new file mode 100644 index 00000000..24bb36b2 --- /dev/null +++ b/docs/ops/queue.md @@ -0,0 +1,5 @@ +## Queue +These operators manage a first in, first out, queue of values. The queue can +hold up to 16 values. The length of the queue can be dynamically changed and +the contents will be preserved. There is also an averaging operator which is +useful for smoothing input values. diff --git a/docs/ops/queue.toml b/docs/ops/queue.toml new file mode 100644 index 00000000..2bebff44 --- /dev/null +++ b/docs/ops/queue.toml @@ -0,0 +1,24 @@ +["Q"] +prototype = "Q" +prototype_set = "Q x" +short = "Modify the queue entries" +description = """ +Gets the output value from the queue, or places `x` into the queue. +""" + +["Q.N"] +prototype = "Q.N" +prototype_set = "Q.N x" +short = "The queue length" +description = """ +Gets/sets the length of the queue. +""" + +["Q.AVG"] +prototype = "Q.AVG" +prototype_set = "Q.AVG x" +short = "Return the average of the queue" +description = """ +Getting the value the average of the values in the queue. Setting `x` sets the +value of each entry in the queue to `x`. +""" diff --git a/docs/ops/stack.md b/docs/ops/stack.md new file mode 100644 index 00000000..b4d6ca11 --- /dev/null +++ b/docs/ops/stack.md @@ -0,0 +1,4 @@ +## Stack +These operators manage a last in, first out, stack of commands, allowing them +to be memorised for later execution at an unspecified time. The stack can hold +up to 8 commands. Commands added to a full stack will be discarded. diff --git a/docs/ops/stack.toml b/docs/ops/stack.toml new file mode 100644 index 00000000..ffada0df --- /dev/null +++ b/docs/ops/stack.toml @@ -0,0 +1,36 @@ +["S"] +prototype = "S: ..." +short = "Place a command onto the stack" +description = """ +Add the command following the colon to the top of the stack. If the stack +is full, the command will be discarded. +""" + +["S.CLR"] +prototype = "S.CLR" +short = "Clear all entries in the stack" +description = """ +Clear the stack, cancelling all of the commands. +""" + +["S.ALL"] +prototype = "S.ALL" +short = "Execute all entries in the stack" +description = """ +Execute all entries in the stack (last in, first out), clearing the stack in +the process. +""" + +["S.POP"] +prototype = "S.POP" +short = "Execute the most recent entry" +description = """ +Pop the most recent command off the stack and execute it. +""" + +["S.L"] +prototype = "S.L" +short = "Get the length of the stack" +description = """ +Get the number of entries in the stack. +""" diff --git a/docs/ops/telex_i.md b/docs/ops/telex_i.md new file mode 100644 index 00000000..59f43431 --- /dev/null +++ b/docs/ops/telex_i.md @@ -0,0 +1,6 @@ +## TELEXi Teletype Input Expander + +The TELEXi (or TXi) is an input expander that adds 4 IN jacks and 4 PARAM knobs to the Teletype. There are jumpers on the back so you can hook more than one TXi to your Teletype simultaneously. + +Inputs added to the system by the TELEX modules are addressed sequentially: 1-4 are on your first module of any type, 5-8 are on the second, 9-12 on the third, and so on. A few of the commands reference the module by its unit number – but those are rare. + diff --git a/docs/ops/telex_i.toml b/docs/ops/telex_i.toml new file mode 100644 index 00000000..96833dc4 --- /dev/null +++ b/docs/ops/telex_i.toml @@ -0,0 +1,147 @@ +["TI.PARAM"] +prototype = "TI.PARAM x" +aliases = ["TI.PRM"] +short = "reads the value of `PARAM` knob `x`; default return range is from 0 to 16383; return range can be altered by the `TI.PARAM.MAP` command" + +["TI.PARAM.QT"] +prototype = "TI.PARAM.QT x" +aliases = ["TI.PRM.QT"] +short = "return the quantized value for `PARAM` knob `x` using the scale set by `TI.PARAM.SCALE`; default return range is from 0 to 16383" + +["TI.PARAM.N"] +prototype = "TI.PARAM.N x" +aliases = ["TI.PRM.N"] +short = "return the quantized note number for `PARAM` knob `x` using the scale set by `TI.PARAM.SCALE`" + +["TI.PARAM.SCALE"] +prototype = "TI.PARAM.SCALE x" +aliases = ["TI.PRM.SCALE"] +short = "select scale # `y` for `PARAM` knob `x`; scales listed in full description" +description = """ +### Quantization Scales +0. Equal Temperament [DEFAULT] +1. 12-tone Pythagorean scale +2. Vallotti & Young scale (Vallotti version) also known as Tartini-Vallotti (1754) +3. Andreas Werckmeister's temperament III (the most famous one, 1681) +4. Wendy Carlos' Alpha scale with perfect fifth divided in nine +5. Wendy Carlos' Beta scale with perfect fifth divided by eleven +6. Wendy Carlos' Gamma scale with third divided by eleven or fifth by twenty +7. Carlos Harmonic & Ben Johnston's scale of 'Blues' from Suite f.micr.piano (1977) & David Beardsley's scale of 'Science Friction' +8. Carlos Super Just +9. Kurzweil "Empirical Arabic" +10. Kurzweil "Just with natural b7th", is Sauveur Just with 7/4 +11. Kurzweil "Empirical Bali/Java Harmonic Pelog" +12. Kurzweil "Empirical Bali/Java Slendro, Siam 7" +13. Kurzweil "Empirical Tibetian Ceremonial" +14. Harry Partch's 43-tone pure scale +15. Partch's Indian Chromatic, Exposition of Monophony, 1933. +16. Partch Greek scales from "Two Studies on Ancient Greek Scales" on black/white +""" + +["TI.PARAM.MAP"] +prototype = "TI.PARAM.MAP x y z" +aliases = ["TI.PRM.MAP"] +short = "maps the PARAM values for input `x` across the range y - z (defaults 0-16383)" +description = """ +If you would like to have a `PARAM` knob values over a specific range, you can offload the processing for this to the TXo by mapping the range of the potentiometer using the `MAP` command. It works a lot like the `MAP` operator, but does the heavy lifting on the TXi, saving you space in your code and cycles on your processor. + +For instance, let's have the first knob return a range from 0 to 100. + +``` +TI.PARAM.MAP 1 0 100 +``` + +You can reset the mapping by either calling the map command with the default range or by using the `INIT` command (`TO.PARAM.INIT 1`). +""" + +["TI.IN"] +prototype = "TI.IN x" +short = "reads the value of IN jack `x`; default return range is from -16384 to 16383 - representing -10V to +10V; return range can be altered by the `TI.IN.MAP` command" + +["TI.IN.QT"] +prototype = "TI.IN.QT x" +short = "return the quantized value for `IN` jack `x` using the scale set by `TI.IN.SCALE`; default return range is from -16384 to 16383 - representing -10V to +10V" + +["TI.IN.N"] +prototype = "TI.IN.N x" +short = "return the quantized note number for `IN` jack `x` using the scale set by `TI.IN.SCALE`" + +["TI.IN.SCALE"] +prototype = "TI.IN.SCALE x" +short = "select scale # `y` for `IN` jack `x`; scales listed in full description" +description = """ +### Quantization Scales +0. Equal Temperament [DEFAULT] +1. 12-tone Pythagorean scale +2. Vallotti & Young scale (Vallotti version) also known as Tartini-Vallotti (1754) +3. Andreas Werckmeister's temperament III (the most famous one, 1681) +4. Wendy Carlos' Alpha scale with perfect fifth divided in nine +5. Wendy Carlos' Beta scale with perfect fifth divided by eleven +6. Wendy Carlos' Gamma scale with third divided by eleven or fifth by twenty +7. Carlos Harmonic & Ben Johnston's scale of 'Blues' from Suite f.micr.piano (1977) & David Beardsley's scale of 'Science Friction' +8. Carlos Super Just +9. Kurzweil "Empirical Arabic" +10. Kurzweil "Just with natural b7th", is Sauveur Just with 7/4 +11. Kurzweil "Empirical Bali/Java Harmonic Pelog" +12. Kurzweil "Empirical Bali/Java Slendro, Siam 7" +13. Kurzweil "Empirical Tibetian Ceremonial" +14. Harry Partch's 43-tone pure scale +15. Partch's Indian Chromatic, Exposition of Monophony, 1933. +16. Partch Greek scales from "Two Studies on Ancient Greek Scales" on black/white +""" + +["TI.IN.MAP"] +prototype = "TI.IN.MAP x y z" +short = "maps the IN values for input jack `x` across the range y - z (default range is -16384 to 16383 - representing -10V to +10V)" + +["TI.PARAM.INIT"] +prototype = "TI.PARAM.INIT x" +aliases = ["TI.PRM.INIT"] +short = "initializes `PARAM` knob `x` back to the default boot settings and behaviors; neutralizes mapping (but not calibration)" + +["TI.IN.INIT"] +prototype = "TI.IN.INIT x" +short = "initializes `IN` jack `x` back to the default boot settings and behaviors; neutralizes mapping (but not calibration)" + +["TI.INIT"] +prototype = "TI.INIT d" +short = "initializes all of the `PARAM` and `IN` inputs for device number `d` (1-8)" + +["TI.PARAM.CALIB"] +prototype = "TI.PARAM.CALIB x y" +aliases = ["TI.PRM.CALIB"] +short = "calibrates the scaling for PARAM knob `x`; `y` of `0` sets the bottom bound; `y` of `1` sets the top bound" +description = """ +You can calibrate your `PARAM` knob by using this command. The steps for full calibration are as follows: + +1. Turn the PARAM knob `x` all the way to the left +2. Send the command 'TI.PARAM.CALIBRATE x 0' +3. Turn the PARAM knob `x` all the way to the right +4. Send the command 'TI.PARAM.CALIBRATE x 1' + +Don't forget to call the `TI.STORE` command to save your calibration between sessions. +""" + +["TI.IN.CALIB"] +prototype = "TI.IN.CALIB x y" +short = "calibrates the scaling for IN jack `x`; `y` of `-1` sets the `-10V` point; `y` of `0` sets the `0V` point; `y` of `1` sets the `+10V` point" +description = """ +You can calibrate your `IN` jack to external voltages by using this command. The steps for full calibration are as follows: + +1. Send a `-10V` signal to the input `x` +2. Send the command 'TI.IN.CALIBRATE x -1' +3. Send a `0V` signal to the input `x` +4. Send the command 'TI.IN.CALIBRATE x 0' +5. Send a `10V` signal to the input `x` +6. Send the command 'TI.IN.CALIBRATE x 1' + +Don't forget to call the `TI.STORE` command to save your calibration between sessions. +""" + +["TI.STORE"] +prototype = "TI.STORE d" +short = "stores the calibration data for TXi number `d` (1-8) to its internal flash memory" + +["TI.RESET"] +prototype = "TI.RESET d" +short = "resets the calibration data for TXi number `d` (1-8) to its factory defaults (no calibration)" \ No newline at end of file diff --git a/docs/ops/telex_o.md b/docs/ops/telex_o.md new file mode 100644 index 00000000..376ee4ef --- /dev/null +++ b/docs/ops/telex_o.md @@ -0,0 +1,8 @@ +## TELEXo Teletype Output Expander + +The TELEXo (or TXo) is an output expander that adds an additional 4 Trigger and 4 CV jacks to the Teletype. There are jumpers on the back so you can hook more than one TXo to your Teletype simultaneously. + +Outputs added to the system by the TELEX modules are addressed sequentially: 1-4 are on your first module of any type, 5-8 are on the second, 9-12 on the third, and so on. A few of the commands reference the module by its unit number – but those are rare. + +Unlike the Teletype's equivalent operators, the TXo does not have get commands for its functions. This was intentional as these commands eat up processor and bus-space. While they may be added in the future, as of now you cannot poll the TXo for the current state of its various operators. + diff --git a/docs/ops/telex_o.toml b/docs/ops/telex_o.toml new file mode 100644 index 00000000..c61a4277 --- /dev/null +++ b/docs/ops/telex_o.toml @@ -0,0 +1,519 @@ +["TO.TR"] +prototype = "TO.TR x y" +short = "sets the `TR` value for output `x` to `y` (0/1)" + +["TO.TR.TOG"] +prototype = "TO.TR.TOG x" +short = "toggles the `TR` value for output `x`" + +["TO.TR.PULSE"] +prototype = "TO.TR.PULSE x" +aliases = ["TO.TR.P"] +short = "pulses the `TR` value for output `x` for the duration set by `TO.TR.TIME/S/M`" + +["TO.TR.PULSE.DIV"] +prototype = "TO.TR.PULSE.DIV x y" +aliases = ["TO.TR.P.DIV"] +short = "sets the clock division factor for `TR` output `x` to `y`" +description = """ +The pulse divider will output one trigger pulse every `y` pulse commands. For example, setting the `DIV` factor to `2` like this: +``` +TO.TR.P.DIV 1 2 +``` +Will cause every other `TO.TR.P 1` command to emit a pulse. + +Reset it to one (`TO.TR.P.DIV 1 1`) or initialize the output (`TO.TR.INIT 1`) to return to the default behavior. +""" + +["TO.TR.PULSE.MUTE"] +prototype = "TO.TR.PULSE.MUTE x y" +aliases = ["TO.TR.P.MUTE"] +short = "mutes or un-mutes `TR` output `x`; `y` is 1 (mute) or 0 (un-mute)" + +["TO.TR.TIME"] +prototype = "TO.TR.TIME x y" +short = "sets the time for `TR.PULSE` on output `n`; `y` in milliseconds" + +["TO.TR.TIME.S"] +prototype = "TO.TR.TIME.S x y" +short = "sets the time for `TR.PULSE` on output `n`; `y` in seconds" + +["TO.TR.TIME.M"] +prototype = "TO.TR.TIME.M x y" +short = "sets the time for `TR.PULSE` on output `n`; `y` in minutes" + +["TO.TR.WIDTH"] +prototype = "TO.TR.WIDTH x y" +short = "sets the time for `TR.PULSE` on output `n` based on the width of its current metronomic value; `y` in percentage (0-100)" +description = """ +The actual time value for the trigger pulse when set by the `WIDTH` command is relative to the current value for `TO.TR.M`. Changes to `TO.TR.M` will change the duration of `TR.PULSE` when using the `WIDTH` mode to set its value. Values for `y` are set in percentage (0-100). + +For example: + +``` +TO.TR.M 1 1000 +TO.TR.WIDTH 1 50 +``` + +The length of a `TR.PULSE` is now 500ms. + +``` +TO.TR.M 1 500 +``` + +The length of a `TR.PULSE` is now 250ms. Note that you don't need to use the width command again as it automatically tracks the value for `TO.TR.M`. +""" + +["TO.TR.POL"] +prototype = "TO.TR.POL x y" +short = "sets the polarity for `TR` output `n`" + +["TO.TR.M.ACT"] +prototype = "TO.TR.M.ACT x y" +short = "sets the active status for the independent metronome for output `x` to `y` (`0`/`1`); default `0` (disabled)" +description = """ +Each `TR` output has its own independent metronome that will execute a `TR.PULSE` at a specified interval. The `ACT` command enables (1) or disables (0) the metronome. +""" + +["TO.TR.M"] +prototype = "TO.TR.M x y" +short = "sets the independent metronome interval for output `x` to `y` in milliseconds; default `1000`" + +["TO.TR.M.S"] +prototype = "TO.TR.M.S x y" +short = "sets the independent metronome interval for output `x` to `y` in seconds; default `1`" + +["TO.TR.M.M"] +prototype = "TO.TR.M.M x y" +short = "sets the independent metronome interval for output `x` to `y` in minutes" + +["TO.TR.M.BPM"] +prototype = "TO.TR.M.BPM x y" +short = "sets the independent metronome interval for output `x` to `y` in Beats Per Minute" + +["TO.TR.M.COUNT"] +prototype = "TO.TR.M.COUNT x y" +short = "sets the number of repeats before deactivating for output `x` to `y`; default `0` (infinity)" +description = """ +This allows for setting a limit to the number of times `TO.TR.M` will `PULSE` when active before automatically disabling itself. For example, let's set it to pulse 5 times with 500ms between pulses: + +``` +TO.TR.M 1 500 +TO.TR.M.COUNT 1 5 +``` + +Now, each time we activate it, the metronome will pulse 5 times - each a half-second apart. + +``` +TO.TR.M.ACT 1 1 +``` + +`PULSE` ... `PULSE` ... `PULSE` ... `PULSE` ... `PULSE`. + +The metronome is now disabled after pulsing five times. If you call `ACT` again, it will emit five more pulses. + +To reset, either set your `COUNT` to zero (`TO.TR.M.COUNT 1 0`) or call init on the output (`TO.TR.INIT 1 1`). +""" + +["TO.TR.M.MUL"] +prototype = "TO.TR.M.MUL x y" +short = "multiplies the `M` rate on `TR` output `x` by `y`; `y` defaults to `1` - no multiplication" +description = """ +The following example will cause 2 against 3 patterns to pulse out of `TO.TR` outputs `3` and `4`. + +``` +TO.TR.M.MUL 3 2 +TO.TR.M.MUL 4 3 +L 3 4: TO.TR.M.ACT I 1 +``` +""" + +["TO.TR.M.SYNC"] +prototype = "TO.TR.M.SYNC x" +short = "synchronizes the `PULSE` for metronome on `TR` output number `x`" + +["TO.M.ACT"] +prototype = "TO.M.ACT d y" +short = "sets the active status for the 4 independent metronomes on device `d` (1-8) to `y` (`0`/`1`); default `0` (disabled)" + +["TO.M"] +prototype = "TO.M d y" +short = "sets the 4 independent metronome intervals for device `d` (1-8) to `y` in milliseconds; default `1000`" + +["TO.M.S"] +prototype = "TO.M.S d y" +short = "sets the 4 independent metronome intervals for device `d` to `y` in seconds; default `1`" + +["TO.M.M"] +prototype = "TO.M.M d y" +short = "sets the 4 independent metronome intervals for device `d` to `y` in minutes" + +["TO.M.BPM"] +prototype = "TO.M.BPM d y" +short = "sets the 4 independent metronome intervals for device `d` to `y` in Beats Per Minute" + +["TO.M.COUNT"] +prototype = "TO.M.COUNT d y" +short = "sets the number of repeats before deactivating for the 4 metronomes on device `d` to `y`; default `0` (infinity)" + +["TO.M.SYNC"] +prototype = "TO.M.SYNC d" +short = "synchronizes the 4 metronomes for device number `d` (1-8)" +description = """ +This command causes the TXo at device `d` to synchronize all of its independent metronomes to the moment it receives the command. Each will then continue to pulse at its own independent `M` rate. +""" + +["TO.CV"] +prototype = "TO.CV x" +short = "CV target output `x`; `y` values are bipolar (-16384 to +16383) and map to -10 to +10" + +["TO.CV.SLEW"] +prototype = "TO.CV.SLEW x y" +short = "set the slew amount for output `x`; `y` in milliseconds" + +["TO.CV.SLEW.S"] +prototype = "TO.CV.SLEW.S x y" +short = "set the slew amount for output `x`; `y` in seconds" + +["TO.CV.SLEW.M"] +prototype = "TO.CV.SLEW.M x y" +short = "set the slew amount for output `x`; `y` in minutes" + +["TO.CV.SET"] +prototype = "TO.CV.SET x y" +short = "set the CV for output `x` (ignoring `SLEW`); `y` values are bipolar (-16384 to +16383) and map to -10 to +10" + +["TO.CV.OFF"] +prototype = "TO.CV.OFF x y" +short = "set the CV offset for output `x`; `y` values are added at the final stage" + +["TO.CV.QT"] +prototype = "TO.CV.QT x y" +short = "CV target output `x`; `y` is quantized to output's current `CV.SCALE`" + +["TO.CV.QT.SET"] +prototype = "TO.CV.QT.SET x y" +short = "set the CV for output `x` (ignoring `SLEW`); `y` is quantized to output's current `CV.SCALE`" + +["TO.CV.N"] +prototype = "TO.CV.N x y" +short = "target the CV to note `y` for output `x`; `y` is indexed in the output's current `CV.SCALE`" + +["TO.CV.N.SET"] +prototype = "TO.CV.N.SET x y" +short = "set the CV to note `y` for output `x`; `y` is indexed in the output's current `CV.SCALE` (ignoring `SLEW`)" + +["TO.CV.SCALE"] +prototype = "TO.CV.SCALE x y" +short = "select scale # `y` for CV output `x`; scales listed in full description" +description = """ +### Quantization Scales +0. Equal Temperament [DEFAULT] +1. 12-tone Pythagorean scale +2. Vallotti & Young scale (Vallotti version) also known as Tartini-Vallotti (1754) +3. Andreas Werckmeister's temperament III (the most famous one, 1681) +4. Wendy Carlos' Alpha scale with perfect fifth divided in nine +5. Wendy Carlos' Beta scale with perfect fifth divided by eleven +6. Wendy Carlos' Gamma scale with third divided by eleven or fifth by twenty +7. Carlos Harmonic & Ben Johnston's scale of 'Blues' from Suite f.micr.piano (1977) & David Beardsley's scale of 'Science Friction' +8. Carlos Super Just +9. Kurzweil "Empirical Arabic" +10. Kurzweil "Just with natural b7th", is Sauveur Just with 7/4 +11. Kurzweil "Empirical Bali/Java Harmonic Pelog" +12. Kurzweil "Empirical Bali/Java Slendro, Siam 7" +13. Kurzweil "Empirical Tibetian Ceremonial" +14. Harry Partch's 43-tone pure scale +15. Partch's Indian Chromatic, Exposition of Monophony, 1933. +16. Partch Greek scales from "Two Studies on Ancient Greek Scales" on black/white +""" + +["TO.CV.LOG"] +prototype = "TO.CV.LOG x y" +short = "translates the output for `CV` output `x` to logarithmic mode `y`; `y` defaults to `0` (off); mode `1` is for 0-16384 (0V-10V), mode `2` is for 0-8192 (0V-5V), mode `3` is for 0-4096 (0V-2.5V), etc." +description = """ +The following example creates an envelope that ramps to 5V over a logarithmic curve: + +``` +TO.CV.SET 1 V 5 +TO.CV.LOG 1 2 +TO.ENV.ATT 1 500 +TO.ENV.DEC.S 1 2 +TO.ENV.ACT 1 1 +``` + +When triggered (`TO.ENV.TRIG 1`), the envelope will rise to 5V over a half a second and then decay back to zero over two seconds. The curve used is `2`, which covers 0V-5V. + +If a curve is too small for the range being covered, values above the range will be limited to the range's ceiling. In the above example, voltages above 5V will all return as 5V. + +""" + +["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" +description = """ +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: + +``` +TO.CV 1 V 5 +TO.OSC 1 N 69 +``` + +This will emit the audio-rate note A (at 440Hz) swinging from '+5V' to '-5V'. The `CV` value acts as an amplitude control. For example: + +``` +TO.CV.SLEW.M 1 1 +TO.CV 1 V 10 +``` + +This will cause the oscillations to gradually increase in amplitude from `5V` to `10V` over a period of one minute. + +**IMPORANT:** if you do not set a `CV` value, the oscillator will not emit a signal. + +If you want to go back to regular `CV` behavior, you need to set the oscillation frequency to zero. E.g. `TO.OSC 1 0`. You can also initialize the `CV` output with `TO.CV.INIT 1`, which resets all of its settings back to start-up default. + +""" + +["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" + +["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" + +["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" + +["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" + +["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" + +["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" + +["TO.OSC.FQ.SET"] +prototype = "TO.OSC.FQ 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" + +["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" + +["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" + +["TO.OSC.CYC"] +prototype = "TO.OSC.CYC x y" +short = "targets the oscillator cycle length to `y` for CV output `x` with the portamento rate determined by the `TO.OSC.SLEW` value; `y` is in milliseconds" + +["TO.OSC.CYC.SET"] +prototype = "TO.OSC.CYC.SET x y" +short = "sets the oscillator cycle length to `y` for CV output `x` (ignores `CV.OSC.SLEW`); `y` is in milliseconds" + +["TO.OSC.CYC.S"] +prototype = "TO.OSC.CYC.S x y" +short = "targets the oscillator cycle length to `y` for CV output `x` with the portamento rate determined by the `TO.OSC.SLEW` value; `y` is in seconds" + +["TO.OSC.CYC.S.SET"] +prototype = "TO.OSC.CYC.S.SET x y" +short = "sets the oscillator cycle length to `y` for CV output `x` (ignores `CV.OSC.SLEW`); `y` is in seconds" + +["TO.OSC.CYC.M"] +prototype = "TO.OSC.CYC.M x y" +short = "targets the oscillator cycle length to `y` for CV output `x` with the portamento rate determined by the `TO.OSC.SLEW` value; `y` is in minutes" + +["TO.OSC.CYC.M.SET"] +prototype = "TO.OSC.CYC.M.SET x y" +short = "sets the oscillator cycle length to `y` for CV output `x` (ignores `CV.OSC.SLEW`); `y` is in minutes" + +["TO.OSC.SCALE"] +prototype = "TO.OSC.SCALE x y" +short = "select scale # `y` for CV output `x`; scales listed in full description" +description = """ +### Quantization Scales +0. Equal Temperament [DEFAULT] +1. 12-tone Pythagorean scale +2. Vallotti & Young scale (Vallotti version) also known as Tartini-Vallotti (1754) +3. Andreas Werckmeister's temperament III (the most famous one, 1681) +4. Wendy Carlos' Alpha scale with perfect fifth divided in nine +5. Wendy Carlos' Beta scale with perfect fifth divided by eleven +6. Wendy Carlos' Gamma scale with third divided by eleven or fifth by twenty +7. Carlos Harmonic & Ben Johnston's scale of 'Blues' from Suite f.micr.piano (1977) & David Beardsley's scale of 'Science Friction' +8. Carlos Super Just +9. Kurzweil "Empirical Arabic" +10. Kurzweil "Just with natural b7th", is Sauveur Just with 7/4 +11. Kurzweil "Empirical Bali/Java Harmonic Pelog" +12. Kurzweil "Empirical Bali/Java Slendro, Siam 7" +13. Kurzweil "Empirical Tibetian Ceremonial" +14. Harry Partch's 43-tone pure scale +15. Partch's Indian Chromatic, Exposition of Monophony, 1933. +16. Partch Greek scales from "Two Studies on Ancient Greek Scales" on black/white +""" + +["TO.OSC.WAVE"] +prototype = "TO.OSC.WAVE x y" +short = "set the waveform for output `x` to `y`; `y` values range `0-4999`; values translate to sine (0), triangle (1000), saw (2000), pulse (3000), or noise (4000); 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" +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: +* `y = 2`: "full-positive" - inverts negative values, making them positive +* `y = 1`: "half-positive" - omits all negative values (values below zero are set to zero) +* `y = 0`: no rectification (default) +* `y = -1`: "half-negative" - omits all positive values (values above zero are set to zero) +* `y = -2`: "full-negative" - inverts positive values, making them negative +""" + +["TO.OSC.WIDTH"] +prototype = "TO.OSC.WIDTH x y" +short = "sets the width of the pulse wave on output `x` to `y`; `y` is a percentage of total width (0 to 100); only affects waveform `3000`" + +["TO.OSC.SYNC"] +prototype = "TO.OSC.SYNC x" +short = "resets the phase of the oscillator on `CV` output `x` (relative to `TO.OSC.PHASE`)" + +["TO.OSC.PHASE"] +prototype = "TO.OSC.PHASE x y" +short = "sets the phase offset of the oscillator on CV output `x` to `y` (0 to 16383); `y` is the range of one cycle" + +["TO.OSC.SLEW"] +prototype = "TO.OSC.SLEW x y" +short = "sets the frequency slew time (portamento) for the oscillator on CV output `x` to `y`; `y` in milliseconds" +description = """ +This parameter acts as a frequency slew for the targeted `CV` output. It allows you to gradually slide from one frequency to another, creating a portamento like effect. It is also great for smoothing transitions between different `LFO` rates on the oscillator. For example: + +``` +TO.CV 1 V 5 +TO.OSC.SLEW 1 30000 +TO.OSC.LFO.SET 1 1000 +TO.OSC.LFO 1 100 +``` + +This will start an LFO on `CV 1` with a rate of 1000mHz. Then, over the next 30 seconds, it will gradually decrease in rate to 100mHz. +""" + +["TO.OSC.SLEW.S"] +prototype = "TO.OSC.SLEW.S x y" +short = "sets the frequency slew time (portamento) for the oscillator on CV output `x` to `y`; `y` in seconds" + +["TO.OSC.SLEW.M"] +prototype = "TO.OSC.SLEW.M x y" +short = "sets the frequency slew time (portamento) for the oscillator on CV output `x` to `y`; `y` in minutes" + +["TO.OSC.CTR"] +prototype = "TO.OSC.CTR x y" +short = "centers the oscillation on CV output `x` to `y`; `y` values are bipolar (-16384 to +16383) and map to -10 to +10" +description = """ +For example, to create a sine wave that is centered at 2.5V and swings up to +5V and down to 0V, you would do this: + +``` +TO.CV 1 VV 250 +TO.OSC.CTR 1 VV 250 +TO.OSC.LFO 1 500 +``` +""" + +["TO.ENV.ACT"] +prototype = "TO.ENV.ACT x y" +short = "activates/deactivates the AD envelope generator for the CV output `x`; `y` turns the envelope generator off (0 - default) or on (1); `CV` amplitude is used as the peak for the envelope and needs to be `> 0` for the envelope to be perceivable" +description = """ +This setting activates (1) or deactivates (0) the envelope generator on `CV` output `y`. The envelope generator is dependent on the current voltage setting for the output. Upon activation, the targeted output will go to zero. Then, when triggered (`TO.ENV.TRIG`), it will ramp the voltage from zero to the currently set peak voltage (`TO.CV`) over the attack time (`TO.ENV.ATT`) and then decay back to zero over the decay time (`TO.ENV.DEC`). For example: + +``` +TO.CV.SET 1 V 8 +TO.ENV.ACT 1 1 +TO.ENV.ATT.S 1 1 +TO.ENV.DEC.S 1 30 +``` + +This will initialize the `CV 1` output to have an envelope that will ramp to `+8V` over one second and decay back to zero over thirty seconds. To trigger the envelope, you need to send the trigger command `TO.ENV.TRIG 1`. Envelopes currently re-trigger from the start of the cycle. + +To return your `CV` output to normal function, either deactivate the envelope (`TO.ENV.ACT 1 0`) or reinitialize the output (`TO.CV.INIT 1`). +""" + +["TO.ENV.TRIG"] +prototype = "TO.ENV.TRIG x" +short = "triggers the envelope at `CV` output `x` to cycle; `CV` amplitude is used as the peak for the envelope and needs to be `> 0` for the envelope to be perceivable" + +["TO.ENV.ATT"] +prototype = "TO.ENV.ATT x y" +short = "set the envelope attack time to `y` for `CV` output `x`; `y` in milliseconds (default 12 ms)" + +["TO.ENV.ATT.S"] +prototype = "TO.ENV.ATT.S x y" +short = "set the envelope attack time to `y` for `CV` output `x`; `y` in seconds" + +["TO.ENV.ATT.M"] +prototype = "TO.ENV.ATT.M x y" +short = "set the envelope attack time to `y` for `CV` output `x`; `y` in minutes" + +["TO.ENV.DEC"] +prototype = "TO.ENV.DEC x y" +short = "set the envelope decay time to `y` for `CV` output `x`; `y` in milliseconds (default 250 ms)" + +["TO.ENV.DEC.S"] +prototype = "TO.ENV.DEC.S x y" +short = "set the envelope decay time to `y` for `CV` output `x`; `y` in seconds" + +["TO.ENV.DEC.M"] +prototype = "TO.ENV.DEC.M x y" +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'" +description = """ +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: + +``` +TO.ENV.EOR 5 1 +``` + +This will cause the first output on TXo #2 (`TO.TR 5`) to pulse after the envelope's attack segment. +""" + +["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'" +description = """ +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: + +``` +TO.ENV.EOC 5 1 +``` + +This will cause the first output on TXo #2 (`TO.TR 5`) to pulse after the envelope's decay segment. +""" + +["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" + +["TO.TR.INIT"] +prototype = "TO.TR.INIT x" +short = "initializes `TR` output `x` back to the default boot settings and behaviors; neutralizes metronomes, dividers, pulse counters, etc." + +["TO.CV.INIT"] +prototype = "TO.CV.INIT x" +short = "initializes `CV` output `x` back to the default boot settings and behaviors; neutralizes offsets, slews, envelopes, oscillation, etc." + +["TO.INIT"] +prototype = "TO.INIT d" +short = "initializes all of the `TR` and `CV` outputs for device number `d` (1-8)" + +["TO.KILL"] +prototype = "TO.KILL d" +short = "cancels all `TR` pulses and `CV` slews for device number `d` (1-8)" diff --git a/docs/ops/variables.md b/docs/ops/variables.md new file mode 100644 index 00000000..071bab27 --- /dev/null +++ b/docs/ops/variables.md @@ -0,0 +1,2 @@ +## Variables + diff --git a/docs/ops/variables.toml b/docs/ops/variables.toml new file mode 100644 index 00000000..ebb56543 --- /dev/null +++ b/docs/ops/variables.toml @@ -0,0 +1,142 @@ +[A] +prototype = "A" +prototype_set = "A x" +short = "get / set the variable `A`, default `1`" + +[B] +prototype = "B" +prototype_set = "B x" +short = "get / set the variable `B`, default `2`" + +[C] +prototype = "C" +prototype_set = "C x" +short = "get / set the variable `C`, default `3`" + +[D] +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)" + + +[I] +prototype = "I" +prototype_set = "I x" +short = """ +get / set the variable `I`, this variable is overwritten by `L`, but can be used +freely outside an `L` loop""" + +[O] +prototype = "O" +prototype_set = "O x" +short = "auto-increments _after_ each access, can be set, starting value `0`" +description=""" +Auto-increments by `O.INC` _after_ each access. The initial value is `0`. The +lower and upper bounds can be set by `O.MIN` (default `0`) and `O.MAX` +(default `63`). `O.WRAP` controls if the value wraps when it reaches a bound +(default is `1`). + +Example: + +``` +O => 0 +O => 1 +X O +X => 2 +O.INC 2 +O => 3 (O increments after it's accessed) +O => 5 +O.INC -2 +O 2 +O => 2 +O => 0 +O => 63 +O => 61 +``` +""" + + +["O.INC"] +prototype = "O.INC" +prototype_set = "O.INC x" +short = "how much to increment `O` by on each invocation, default `1`" + +["O.MIN"] +prototype = "O.MIN" +prototype_set = "O.MIN x" +short = "the lower bound for `O`, default `0`" + +["O.MAX"] +prototype = "O.MAX" +prototype_set = "O.MAX x" +short = "the upper bound for `O`, default `63`" + +["O.WRAP"] +prototype = "O.WRAP" +prototype_set = "O.WRAP x" +short = "should `O` wrap when it reaches its bounds, default `1`" + +[T] +prototype = "T" +prototype_set = "T x" +short = "get / set the variable `T`, typically used for time, default `0`" + +[TIME] +prototype = "TIME" +prototype_set = "TIME x" +short = "timer value, counts up in ms., wraps after 32s, can be set" + +["TIME.ACT"] +prototype = "TIME.ACT" +prototype_set = "TIME.ACT x" +short = "enable or disable timer counting, default `1`" + +[X] +prototype = "X" +prototype_set = "X x" +short = "get / set the variable `X`, default `0`" + +[Y] +prototype = "Y" +prototype_set = "Y x" +short = "get / set the variable `Y`, default `0`" + +[Z] +prototype = "Z" +prototype_set = "Z x" +short = "get / set the variable `Z`, default `0`" diff --git a/docs/ops/whitewhale.md b/docs/ops/whitewhale.md new file mode 100644 index 00000000..66fcd61d --- /dev/null +++ b/docs/ops/whitewhale.md @@ -0,0 +1 @@ +## White Whale diff --git a/docs/ops/whitewhale.toml b/docs/ops/whitewhale.toml new file mode 100644 index 00000000..b82f6155 --- /dev/null +++ b/docs/ops/whitewhale.toml @@ -0,0 +1,106 @@ +["WW.PRESET"] +prototype = "WW.PRESET x" +short = "Recall preset (0-7)" +description = """ +Set White Whale to preset `x` (0-7). This takes effect immediately. The current playback +position is not changed. +""" + +["WW.POS"] +prototype = "WW.POS x" +short = "Cut to position (0-15)" +description = """ +Cut immediately to position (0-15) in the currently playing pattern. +""" + +["WW.SYNC"] +prototype = "WW.SYNC x" +short = "Cut to position (0-15) and hard-sync the clock (if clocked internally)" +description = """ +Cut to position (0-15) in the currently playing pattern. If White Whale is being clocked internaly, +this also hard-syncs the clock. +""" + +["WW.START"] +prototype = "WW.START x" +short = "Set the loop start position (0-15)" +description = """ +Set the loop start position (0-15). This does not impact the current playback position. If the +playback position is outside of the defined loop it will continue to step until it enters the +loop. If the start position is after the end position, the loop will wrap around the ends of the +grid. +""" + +["WW.END"] +prototype = "WW.END x" +short = "Set the loop end position (0-15)" +description = """ +Set the loop end position (0-15). This does not impact the current playback position. If the +playback position is outside of the defined loop it will continue to step until it enters the +loop. If the end position is before the end position, the loop will wrap around the ends of the +grid. +""" + +["WW.PMODE"] +prototype = "WW.PMODE x" +short = "Set the loop play mode (0-5)" +description = """ +Set the loop play mode. The available modes are: 0 - forward, 1 - reverse, 2 - drunk, 3 - random, 4 - pingpong, 5 - pingpong with repeated end points. +""" + +["WW.PATTERN"] +prototype = "WW.PATTERN x" +short = "Change pattern (0-15)" +description = """ +Change pattern. This does not impact the current playback position. +""" + +["WW.QPATTERN"] +prototype = "WW.QPATTERN x" +short = "Change pattern (0-15) after current pattern ends" +description = """ +Change pattern (0-15) after current pattern ends +""" + +["WW.MUTE1"] +prototype = "WW.MUTE1 x" +short = "Mute trigger 1 (0 = on, 1 = mute)" +description = """ +Mute trigger 1 (0 = on, 1 = mute). +""" + +["WW.MUTE2"] +prototype = "WW.MUTE2 x" +short = "Mute trigger 2 (0 = on, 1 = mute)" +description = """ +Mute trigger 2 (0 = on, 1 = mute). +""" + +["WW.MUTE3"] +prototype = "WW.MUTE3 x" +short = "Mute trigger 3 (0 = on, 1 = mute)" +description = """ +Mute trigger 3 (0 = on, 1 = mute). +""" + +["WW.MUTE4"] +prototype = "WW.MUTE4 x" +short = "Mute trigger 4 (0 = on, 1 = mute)" +description = """ +Mute trigger 4 (0 = on, 1 = mute). +""" + +["WW.MUTEA"] +prototype = "WW.MUTEA x" +short = "Mute CV A (0 = on, 1 = mute)" +description = """ +Mute CV A (0 = on, 1 = mute). +""" + +["WW.MUTEB"] +prototype = "WW.MUTEB x" +short = "Mute CV B (0 = on, 1 = mute)" +description = """ +Mute CV B (0 = on, 1 = mute). +""" + diff --git a/docs/whats_new.md b/docs/whats_new.md new file mode 100644 index 00000000..3b389390 --- /dev/null +++ b/docs/whats_new.md @@ -0,0 +1,96 @@ +# What's new? + +## Version 2.0 + +Teletype version 2.0 represents a large rewrite of the Teletype code base. There are many new language additions, some small breaking changes and a lot of under the hood enhancements. + + +### Breaking changes + + - **Removed the need for the `II` `OP`.** + + For example, `II MP.PRESET 1` will become just `MP.PRESET 1`. + + - **Merge `MUTE` and `UNMUTE` `OP`s to `MUTE x` / `MUTE x y`.** + + See the documentation for `MUTE` for more information. + + - **Remove unused Meadowphysics `OP`s.** + + Removed: `MP.SYNC`, `MP.MUTE`, `MP.UNMUTE`, `MP.FREEZE`, `MP.UNFREEZE`. + + - **Rename Ansible Meadowphysics `OP`s to start with `ME`.** + + This was done to avoid conflicts with the Meadowphysics `OP`s. + + **WARNING**: If you restore your scripts from a USB memory stick, please manually fix any changes first. Alternatively, incorrect commands (due to the above changes) will be skipped when imported, please re-add them. + +### Major new features + +#### Sub commands + +e.g. `IF X: CV 1 N 60 TR.PULSE 1`. + +See the section on "Sub commands" for more information. + +#### Aliases + +For example, use `TR.P 1` instead of `TR.PULSE 1`, and use `+ 1 1`, instead of `ADD 1 1`. + +See the section on "Aliases" for more information. + +#### `PN` versions of every `P` `OP` + +There are now `PN` versions of every `P` `OP`. For example, instead of: + +``` +P.I 0 +P.START 0 +P.I 1 +P.START 10 +``` + +You can use: + +``` +PN.START 0 0 +PN.START 1 10 +``` + +#### TELEXi and TELEXo `OP`s + +Lots of `OP`s have been added for interacting with the wonderful TELEXi input expander and TELEXo output expander. See their respective sections in the documentation for more information. + +#### New keybindings + +The function keys can now directly trigger a script. + +The `` key is now used to cycle between live, edit and pattern modes, and there are now easy access keys to directly jump to a mode. + +Many new text editing keyboard shortcuts have been added. + +See the "Modes" documentation for a listing of all the keybindings. + +#### USB memory stick support + +You can now save you scenes to USB memory stick at any time, and not just at boot up. Just insert a USB memory stick to start the save and load process. Your edit scene should not be effected. + +It should also be significantly more reliable with a wider ranger of memory sticks. + +**WARNING:** Please backup the contents of your USB stick before inserting it. Particularly with a freshly flashed Teletype as you will end up overwriting all the saved scenes with blank ones. + +### Other additions + + - Limited script recursion now allowed (max recursion depth is 8) including self recursion. + - Metro scripts limited to 25ms, but new `M!` op to set it as low as 2ms (at your own risk), see "Metronome" `OP` section for more. + +### Known issues + +#### Visual glitches + +The cause of these is well understood, and they are essentially harmless. Changing modes with the `` key will force the screen to redraw. A fix should hopefully be coming in version 2.1. + +#### Tables in the PDF documentation + +Unfortunately the tables in the PDF documentation are somewhat hard to read due to the lack of horizontal lines between rows. + diff --git a/module/Makefile b/module/Makefile index 5e8b18b3..e532f309 100644 --- a/module/Makefile +++ b/module/Makefile @@ -80,9 +80,3 @@ include $(MAKEFILE_PATH) # Add the git commit id to a file for use when printing out the version ../module/gitversion.c: ../.git/HEAD ../.git/index echo "const char *git_version = \"$(shell git describe --always --dirty | tr '[a-z]' '[A-Z]')\";" > $@ - -# Make a zip release -.PHONY: release -release: teletype.hex - rm -f teletype.zip && \ - zip teletype.zip teletype.hex flash.sh update_firmware.command diff --git a/module/flash.c b/module/flash.c index 80dece6d..3446eea9 100644 --- a/module/flash.c +++ b/module/flash.c @@ -42,8 +42,7 @@ void flash_prepare() { memset(text, 0, SCENE_TEXT_LINES * SCENE_TEXT_CHARS); for (uint8_t i = 0; i < SCENE_SLOTS; i++) { flash_write(i, &scene, &text); } - preset_select = 0; - flashc_memset8((void *)&f.last_scene, preset_select, 1, true); + flash_update_last_saved_scene(0); flashc_memset8((void *)&f.fresh, FIRSTRUN_KEY, 1, true); } @@ -55,7 +54,6 @@ void flash_write(uint8_t preset_no, scene_state_t *scene, ss_patterns_size(), true); flashc_memcpy((void *)&f.scenes[preset_no].text, text, SCENE_TEXT_LINES * SCENE_TEXT_CHARS, true); - flashc_memset8((void *)&(f.last_scene), preset_no, 1, true); } void flash_read(uint8_t preset_no, scene_state_t *scene, @@ -66,13 +64,16 @@ void flash_read(uint8_t preset_no, scene_state_t *scene, ss_patterns_size()); memcpy(text, &f.scenes[preset_no].text, SCENE_TEXT_LINES * SCENE_TEXT_CHARS); - flashc_memset8((void *)&f.last_scene, preset_no, 1, true); } uint8_t flash_last_saved_scene() { return f.last_scene; } +void flash_update_last_saved_scene(uint8_t preset_no) { + flashc_memset8((void *)&f.last_scene, preset_no, 1, true); +} + const char *flash_scene_text(uint8_t preset_no, size_t line) { return f.scenes[preset_no].text[line]; } diff --git a/module/flash.h b/module/flash.h index 17d3e0fc..85b2cd82 100644 --- a/module/flash.h +++ b/module/flash.h @@ -15,6 +15,7 @@ void flash_read(uint8_t preset_no, scene_state_t *scene, void flash_write(uint8_t preset_no, scene_state_t *scene, char (*text)[SCENE_TEXT_LINES][SCENE_TEXT_CHARS]); uint8_t flash_last_saved_scene(void); +void flash_update_last_saved_scene(uint8_t preset_no); const char *flash_scene_text(uint8_t preset_no, size_t line); #endif diff --git a/module/help_mode.c b/module/help_mode.c index 4b5f1713..e0e15c02 100644 --- a/module/help_mode.c +++ b/module/help_mode.c @@ -15,15 +15,18 @@ //////////////////////////////////////////////////////////////////////////////// // Help text /////////////////////////////////////////////////////////////////// -#define HELP_PAGES 8 +#define HELP_PAGES 7 -#define HELP1_LENGTH 38 -const char* help1[HELP1_LENGTH] = { "1/8 HELP", +#define HELP1_LENGTH 41 +const char* help1[HELP1_LENGTH] = { "1/7 HELP", "[ ] NAVIGATE HELP PAGES", "UP/DOWN TO SCROLL", " ", - "TAB|EDIT/LIVE", - "TILDE|TRACKER", + "TAB|EDIT/LIVE/PATTERN", + "PRINT SCREEN|JUMP TO LIVE", + "NUM LOCK|JUMP TO PATTERN", + "F1-F10|EXECUTE SCRIPT", + "ALT-F1-F10|EDIT SCRIPT", "ESC|SCENE", "ALT-ESC|WRITE", " ", @@ -42,7 +45,7 @@ const char* help1[HELP1_LENGTH] = { "1/8 HELP", "SH-ENTER|INSERT", "SH-BSP|CLEAR", " ", - "// TRACKER", + "// PATTERN", "ARROWS|NAVIGATE", "ALT-ARROWS|JUMP", "0-9|NUMERIC ENTRY", @@ -58,18 +61,22 @@ const char* help1[HELP1_LENGTH] = { "1/8 HELP", "ALT-L,S,E|JUMP" }; #define HELP2_LENGTH 13 -const char* help2[HELP2_LENGTH] = { - "2/8 VARIABLES", " ", - "X, Y, Z|GENERAL PURPOSE", "T|USE FOR TIME", - "A-D|ASSIGNED TO 1-4", " ", - "// SPECIAL VARIABLES", "I|USED BY LOOP", - "O|INCREMENTS ON READ", "DRUNK|INC BY -1, 0, +1", - "Q|SHIFT REGISTER", "Q.N|SET Q LENGTH", - "Q.AVG|AVERAGE OF ALL Q" -}; +const char* help2[HELP2_LENGTH] = { "2/7 VARIABLES", + " ", + "X, Y, Z|GENERAL PURPOSE", + "T|USE FOR TIME", + "A, B, C, D|ASSIGNED TO 1-4", + " ", + "// SPECIAL VARIABLES", + "I|USED BY LOOP", + "O|INCREMENTS ON READ", + "DRUNK|INC BY -1, 0, +1", + "Q|SHIFT REGISTER", + "Q.N|SET Q LENGTH", + "Q.AVG|AVERAGE OF ALL Q" }; -#define HELP3_LENGTH 20 -const char* help3[HELP3_LENGTH] = { "3/8 PARAMETERS", +#define HELP3_LENGTH 21 +const char* help3[HELP3_LENGTH] = { "3/7 PARAMETERS", " ", "TR A-D|SET TR VALUE (0,1)", "TR.TIME A-D|TR PULSE TIME", @@ -88,10 +95,11 @@ const char* help3[HELP3_LENGTH] = { "3/8 PARAMETERS", "TIME|TIMER COUNT (MS)", "TIME.ACT|ENABLE TIMER (0/1)", " ", + "SCRIPT A|RUN SCRIPT", "SCENE|GET/SET SCENE #" }; #define HELP4_LENGTH 9 -const char* help4[HELP4_LENGTH] = { "4/8 DATA AND TABLES", +const char* help4[HELP4_LENGTH] = { "4/7 DATA AND TABLES", " ", "ALL PARAMS HAVE 16B RANGE", "-32768 TO 32767", @@ -102,7 +110,7 @@ const char* help4[HELP4_LENGTH] = { "4/8 DATA AND TABLES", "VV 0-1000|V WITH 2 DECIMALS" }; #define HELP5_LENGTH 35 -const char* help5[HELP5_LENGTH] = { "5/8 OPERATORS", +const char* help5[HELP5_LENGTH] = { "5/7 OPERATORS", " ", "RAND A|RANDOM 0 - A", "RRAND A B|RANDOM A - B", @@ -139,31 +147,31 @@ const char* help5[HELP5_LENGTH] = { "5/8 OPERATORS", "TR.PULSE X|PULSE TR X" }; #define HELP6_LENGTH 22 -const char* help6[HELP6_LENGTH] = { "6/8 PRE :", +const char* help6[HELP6_LENGTH] = { "6/7 PRE :", " ", "EACH PRE NEEDS A : FOLLOWED", "BY A COMMAND TO OPERATE ON", " ", - "PROB A :|PROBABALITY 0-100", + "PROB A: | PROBABALITY 0-100", " ", - "DEL A :|DELAY BY A (MS)", + "DEL A: |DELAY BY A (MS)", "DEL.CLR|KILL ALL DELAYS", " ", - "S :|PUSH ONTO STACK", + "S: |PUSH ONTO STACK", "S.CLR|CLEAR S", "S.ALL|EXECUTE ALL S", "S.POP|EXECUTE NEWEST S", "S.L|QUERY LENGTH OF S", " ", - "IF A :|EXECUTE IF NON-ZERO", - "ELIF A :|AFTER IF WHEN TRUE", - "ELSE :|AFTER FAILED IF", + "IF A: |EXECUTE IF NON-ZERO", + "ELIF A: |AFTER IF WHEN TRUE", + "ELSE: |AFTER FAILED IF", " ", - "L A B :|ITERATE FROM A-B", + "L A B: |ITERATE FROM A-B", "NB: I IS UPDATED EACH TIME" }; #define HELP7_LENGTH 26 -const char* help7[HELP7_LENGTH] = { "7/8 PATTERNS", +const char* help7[HELP7_LENGTH] = { "7/7 PATTERNS", " ", "// DIRECT ACCESS", "P A|GET VAL AT INDEX A", @@ -190,60 +198,16 @@ const char* help7[HELP7_LENGTH] = { "7/8 PATTERNS", "P.NEXT A|GET/SET NEXT POS", "P.PREV A|GET/SET PREV POS" }; -#define HELP8_LENGTH 42 -const char* help8[HELP8_LENGTH] = { "8/8 REMOTE", - " ", - "REMOTE CONTROL OF MONOME", - "TRILOGY MODULES OVER II", - " ", - "ALL MESSAGES NEED A VALUE", - " ", - "// WHITE WHALE", - "WW.PRESET|RECALL PRESET", - "WW.POS|CUT TO POSITION", - "WW.SYNC|CUT & HARD SYNC", - "WW.START|SET LOOP START", - "WW.END|SET LOOP END", - "WW.PMODE|SET PLAY MODE", - "WW.PATTERN| CHANGE PATTERN", - "WW.QPATTERN| QUEUED P CHANGE", - "WW.MUTE1|MUTE TR 1", - "WW.MUTE2|MUTE TR 2", - "WW.MUTE3|MUTE TR 3", - "WW.MUTE4|MUTE TR 4", - "WW.MUTEA|MUTE CV A", - "WW.MUTEB|MUTE CV B", - " ", - "// MEADOWPHYSICS", - "MP.PRESET|RECALL PRESET", - "MP.RESET|RESET POSITIONS", - "MP.SYNC|RESET POS AND SYNC", - "MP.MUTE|MUTES OUTPUT 1-8", - "MP.UNMUTE|UNMUTES OUTPUT", - "MP.FREEZE|FREEZE ROW 1-8", - "MP.UNFREEZE| UNFREEZE ROW", - " ", - "// EARTHSEA", - "ES.PRESET|RECALL PRESET", - "ES.MODE|SET PATTERN CLOCK", - "ES.CLOCK|NEXT PATT EVENT", - "ES.RESET|PLAY PATTERN", - "ES.PATTERN|SET PATTERN #", - "ES.TRANS|SET TRANSPOSE", - "ES.STOP|STOP PATTERN", - "ES.TRIPLE|RECALL SHAPE 1-4", - "ES.MAGIC|1=HALF, 2=DOUBLE" }; - //////////////////////////////////////////////////////////////////////////////// // Help mode /////////////////////////////////////////////////////////////////// const char** help_pages[HELP_PAGES] = { help1, help2, help3, help4, - help5, help6, help7, help8 }; + help5, help6, help7 }; const uint8_t help_length[HELP_PAGES] = { HELP1_LENGTH, HELP2_LENGTH, HELP3_LENGTH, HELP4_LENGTH, HELP5_LENGTH, HELP6_LENGTH, - HELP7_LENGTH, HELP8_LENGTH }; + HELP7_LENGTH }; static uint8_t page_no; static uint8_t offset; diff --git a/module/live_mode.c b/module/live_mode.c index ecff4d56..a5793acf 100644 --- a/module/live_mode.c +++ b/module/live_mode.c @@ -21,9 +21,11 @@ #include "conf_usb_host.h" // needed in order to include "usb_protocol_hid.h" #include "usb_protocol_hid.h" -#define HISTORY_SIZE 16 -static tele_command_t history[HISTORY_SIZE]; -static uint8_t history_line; +#define MAX_HISTORY_SIZE 16 +static tele_command_t history[MAX_HISTORY_SIZE]; // newest entry in index 0 +static int8_t history_line; // -1 for not selected +static int8_t history_top; // -1 when empty + static line_editor_t le; static process_result_t output; static error_t status; @@ -84,11 +86,13 @@ void init_live_mode() { show_welcome_message = true; dirty = D_ALL; activity_prev = 0xFF; + history_top = -1; + history_line = -1; } void set_live_mode() { line_editor_set(&le, ""); - history_line = HISTORY_SIZE; + history_line = -1; dirty = D_ALL; activity_prev = 0xFF; } @@ -96,21 +100,20 @@ void set_live_mode() { void process_live_keys(uint8_t k, uint8_t m, bool is_held_key) { // or C-n: history next if (match_no_mod(m, k, HID_DOWN) || match_ctrl(m, k, HID_N)) { - if (history_line < (HISTORY_SIZE - 1)) { - history_line++; + if (history_line > 0) { + history_line--; line_editor_set_command(&le, &history[history_line]); - dirty |= D_INPUT; } else { - history_line = HISTORY_SIZE; + history_line = -1; line_editor_set(&le, ""); - dirty |= D_INPUT; } + dirty |= D_INPUT; } // or C-p: history previous else if (match_no_mod(m, k, HID_UP) || match_ctrl(m, k, HID_P)) { - if (history_line) { - history_line--; + if (history_line < history_top) { + history_line++; line_editor_set_command(&le, &history[history_line]); dirty |= D_INPUT; } @@ -130,17 +133,23 @@ void process_live_keys(uint8_t k, uint8_t m, bool is_held_key) { if (status != E_OK) return; // quit, screen_refresh_live will display the error message - history_line = HISTORY_SIZE; if (command.length) { + // increase history_size up to a maximum + history_top++; + if (history_top >= MAX_HISTORY_SIZE) + history_top = MAX_HISTORY_SIZE - 1; + // shuffle the history up // should really use some sort of ring buffer - for (size_t i = 0; i < HISTORY_SIZE - 1; i++) { - memcpy(&history[i], &history[i + 1], sizeof(command)); + for (size_t i = history_top; i > 0; i--) { + memcpy(&history[i], &history[i - 1], sizeof(command)); } - memcpy(&history[HISTORY_SIZE - 1], &command, sizeof(command)); + memcpy(&history[0], &command, sizeof(command)); output = run_command(&scene_state, &command); } + + history_line = -1; line_editor_set(&le, ""); } // [ or ]: switch to edit mode diff --git a/module/main.c b/module/main.c index 76665c47..77fb26ce 100644 --- a/module/main.c +++ b/module/main.c @@ -260,13 +260,8 @@ void handler_PollADC(int32_t data) { void handler_KeyTimer(int32_t data) { if (front_timer) { if (front_timer == 1) { - flash_read(preset_select, &scene_state, &scene_text); - - run_script(&scene_state, INIT_SCRIPT); - - set_last_mode(); - - front_timer--; + if (mode == M_PRESET_R) { process_preset_r_long_front(); } + front_timer = 0; } else front_timer--; @@ -516,8 +511,8 @@ bool process_global_keys(uint8_t k, uint8_t m, bool is_held_key) { } return true; } - // : help text, or return to last mode - else if (match_no_mod(m, k, HID_PRINTSCREEN)) { + // -?: help text, or return to last mode + else if (match_shift_alt(m, k, HID_SLASH)) { if (mode == M_HELP) set_last_mode(); else { @@ -545,6 +540,18 @@ bool process_global_keys(uint8_t k, uint8_t m, bool is_held_key) { run_script(&scene_state, k - HID_KEYPAD_1); return true; } + // : jump to pattern mode + else if (match_no_mod(m, k, HID_KEYPAD_NUM_LOCK) || + match_no_mod(m, k, HID_F11)) { + if (mode != M_PATTERN) { set_mode(M_PATTERN); } + return true; + } + // : jump to live mode + else if (match_no_mod(m, k, HID_PRINTSCREEN) || + match_no_mod(m, k, HID_F12)) { + if (mode != M_LIVE) { set_mode(M_LIVE); } + return true; + } else { return false; } @@ -573,7 +580,9 @@ void tele_metro_updated() { uint32_t metro_time = scene_state.variables.m; bool m_act = scene_state.variables.m_act > 0; - if (metro_time < 10) metro_time = 10; + if (metro_time < METRO_MIN_UNSUPPORTED_MS) { + metro_time = METRO_MIN_UNSUPPORTED_MS; + } if (m_act && !metro_timer_enabled) { // enable the timer timer_add(&metroTimer, metro_time, &metroTimer_callback, NULL); @@ -722,6 +731,10 @@ int main(void) { init_live_mode(); set_mode(M_LIVE); + // wait 50ms before running the init script to allow for any i2c devices to + // fully initalise + delay_ms(50); + run_script(&scene_state, INIT_SCRIPT); while (true) { check_events(); } diff --git a/module/preset_r_mode.c b/module/preset_r_mode.c index 2775cdb2..446179b5 100644 --- a/module/preset_r_mode.c +++ b/module/preset_r_mode.c @@ -18,6 +18,8 @@ static uint8_t offset; static uint8_t knob_last; static bool dirty; +static void do_preset_read(void); + void set_preset_r_mode(uint16_t knob) { knob_last = knob >> 7; offset = 0; @@ -33,6 +35,10 @@ void process_preset_r_knob(uint16_t knob, uint8_t mod_key) { } } +void process_preset_r_long_front() { + do_preset_read(); +} + void process_preset_r_keys(uint8_t k, uint8_t m, bool is_held_key) { // or C-n: line down if (match_no_mod(m, k, HID_DOWN) || match_ctrl(m, k, HID_N)) { @@ -62,12 +68,7 @@ void process_preset_r_keys(uint8_t k, uint8_t m, bool is_held_key) { } // : load preset else if (match_no_mod(m, k, HID_ENTER) && !is_held_key) { - flash_read(preset_select, &scene_state, &scene_text); - ss_set_scene(&scene_state, preset_select); - - run_script(&scene_state, INIT_SCRIPT); - - set_last_mode(); + do_preset_read(); } } @@ -92,3 +93,13 @@ bool screen_refresh_preset_r() { dirty = false; return true; }; + +void do_preset_read() { + flash_read(preset_select, &scene_state, &scene_text); + flash_update_last_saved_scene(preset_select); + ss_set_scene(&scene_state, preset_select); + + run_script(&scene_state, INIT_SCRIPT); + + set_last_mode(); +} diff --git a/module/preset_r_mode.h b/module/preset_r_mode.h index e9f28c35..14c96556 100644 --- a/module/preset_r_mode.h +++ b/module/preset_r_mode.h @@ -6,6 +6,7 @@ void set_preset_r_mode(uint16_t knob); void process_preset_r_knob(uint16_t knob, uint8_t mod_key); +void process_preset_r_long_front(void); void process_preset_r_keys(uint8_t key, uint8_t mod_key, bool is_held_key); bool screen_refresh_preset_r(void); diff --git a/module/preset_w_mode.c b/module/preset_w_mode.c index 3db48423..fe8f1ed6 100644 --- a/module/preset_w_mode.c +++ b/module/preset_w_mode.c @@ -87,6 +87,7 @@ void process_preset_w_keys(uint8_t k, uint8_t m, bool is_held_key) { if (!is_held_key) { strcpy(scene_text[edit_line + edit_offset], line_editor_get(&le)); flash_write(preset_select, &scene_state, &scene_text); + flash_update_last_saved_scene(preset_select); set_last_mode(); } } diff --git a/src/match_token.rl b/src/match_token.rl index 809db9d8..82c6b36c 100644 --- a/src/match_token.rl +++ b/src/match_token.rl @@ -43,6 +43,7 @@ # metronome "M" => { MATCH_OP(E_OP_M); }; + "M!" => { MATCH_OP(E_OP_M_SYM_EXCLAMATION); }; "M.ACT" => { MATCH_OP(E_OP_M_ACT); }; "M.RESET" => { MATCH_OP(E_OP_M_RESET); }; @@ -116,6 +117,8 @@ "NE" => { MATCH_OP(E_OP_NE); }; "LT" => { MATCH_OP(E_OP_LT); }; "GT" => { MATCH_OP(E_OP_GT); }; + "LTE" => { MATCH_OP(E_OP_LTE); }; + "GTE" => { MATCH_OP(E_OP_GTE); }; "NZ" => { MATCH_OP(E_OP_NZ); }; "EZ" => { MATCH_OP(E_OP_EZ); }; "RSH" => { MATCH_OP(E_OP_RSH); }; @@ -124,13 +127,13 @@ "ABS" => { MATCH_OP(E_OP_ABS); }; "AND" => { MATCH_OP(E_OP_AND); }; "OR" => { MATCH_OP(E_OP_OR); }; - "XOR" => { MATCH_OP(E_OP_XOR); }; "JI" => { MATCH_OP(E_OP_JI); }; "SCALE" => { MATCH_OP(E_OP_SCALE); }; "N" => { MATCH_OP(E_OP_N); }; "V" => { MATCH_OP(E_OP_V); }; "VV" => { MATCH_OP(E_OP_VV); }; "ER" => { MATCH_OP(E_OP_ER); }; + "XOR" => { MATCH_OP(E_OP_XOR); }; "+" => { MATCH_OP(E_OP_SYM_PLUS); }; "-" => { MATCH_OP(E_OP_SYM_DASH); }; "*" => { MATCH_OP(E_OP_SYM_STAR); }; @@ -145,8 +148,8 @@ "!" => { MATCH_OP(E_OP_SYM_EXCLAMATION); }; "<<" => { MATCH_OP(E_OP_SYM_LEFT_ANGLED_x2); }; ">>" => { MATCH_OP(E_OP_SYM_RIGHT_ANGLED_x2); }; - "&&" => { MATCH_OP(E_OP_AMPERSAND_x2); }; - "||" => { MATCH_OP(E_OP_PIPE_x2); }; + "&&" => { MATCH_OP(E_OP_SYM_AMPERSAND_x2); }; + "||" => { MATCH_OP(E_OP_SYM_PIPE_x2); }; # stack "S.ALL" => { MATCH_OP(E_OP_S_ALL); }; @@ -178,14 +181,9 @@ "WW.MUTEA" => { MATCH_OP(E_OP_WW_MUTEA); }; "WW.MUTEB" => { MATCH_OP(E_OP_WW_MUTEB); }; - # earthsea + # meadowphysics "MP.PRESET" => { MATCH_OP(E_OP_MP_PRESET); }; "MP.RESET" => { MATCH_OP(E_OP_MP_RESET); }; - "MP.SYNC" => { MATCH_OP(E_OP_MP_SYNC); }; - "MP.MUTE" => { MATCH_OP(E_OP_MP_MUTE); }; - "MP.UNMUTE" => { MATCH_OP(E_OP_MP_UNMUTE); }; - "MP.FREEZE" => { MATCH_OP(E_OP_MP_FREEZE); }; - "MP.UNFREEZE" => { MATCH_OP(E_OP_MP_UNFREEZE); }; "MP.STOP" => { MATCH_OP(E_OP_MP_STOP); }; # earthsea @@ -218,42 +216,42 @@ "OR.CVB" => { MATCH_OP(E_OP_OR_CVB); }; # ansible - "KR.PRE" => { MATCH_OP(E_OP_KR_PRESET); }; - "KR.PAT" => { MATCH_OP(E_OP_KR_PATTERN); }; + "KR.PRE" => { MATCH_OP(E_OP_KR_PRE); }; + "KR.PAT" => { MATCH_OP(E_OP_KR_PAT); }; "KR.SCALE" => { MATCH_OP(E_OP_KR_SCALE); }; "KR.PERIOD" => { MATCH_OP(E_OP_KR_PERIOD); }; "KR.POS" => { MATCH_OP(E_OP_KR_POS); }; - "KR.L.ST" => { MATCH_OP(E_OP_KR_LOOP_ST); }; - "KR.L.LEN" => { MATCH_OP(E_OP_KR_LOOP_LEN); }; - "KR.RES" => { MATCH_OP(E_OP_KR_RESET); }; - "MP.PRE" => { MATCH_OP(E_OP_MP_PRESET1); }; - "MP.RES" => { MATCH_OP(E_OP_MP_RESET1); }; - "MP.OFF" => { MATCH_OP(E_OP_MP_STOP1); }; - "MP.SCALE" => { MATCH_OP(E_OP_MP_SCALE); }; - "MP.PERIOD" => { MATCH_OP(E_OP_MP_PERIOD); }; - "LV.PRE" => { MATCH_OP(E_OP_LV_PRESET); }; - "LV.RES" => { MATCH_OP(E_OP_LV_RESET); }; + "KR.L.ST" => { MATCH_OP(E_OP_KR_L_ST); }; + "KR.L.LEN" => { MATCH_OP(E_OP_KR_L_LEN); }; + "KR.RES" => { MATCH_OP(E_OP_KR_RES); }; + "ME.PRE" => { MATCH_OP(E_OP_ME_PRE); }; + "ME.RES" => { MATCH_OP(E_OP_ME_RES); }; + "ME.STOP" => { MATCH_OP(E_OP_ME_STOP); }; + "ME.SCALE" => { MATCH_OP(E_OP_ME_SCALE); }; + "ME.PERIOD" => { MATCH_OP(E_OP_ME_PERIOD); }; + "LV.PRE" => { MATCH_OP(E_OP_LV_PRE); }; + "LV.RES" => { MATCH_OP(E_OP_LV_RES); }; "LV.POS" => { MATCH_OP(E_OP_LV_POS); }; "LV.L.ST" => { MATCH_OP(E_OP_LV_L_ST); }; "LV.L.LEN" => { MATCH_OP(E_OP_LV_L_LEN); }; "LV.L.DIR" => { MATCH_OP(E_OP_LV_L_DIR); }; "LV.CV" => { MATCH_OP(E_OP_LV_CV); }; - "CY.PRE" => { MATCH_OP(E_OP_CY_PRESET); }; - "CY.RES" => { MATCH_OP(E_OP_CY_RESET); }; + "CY.PRE" => { MATCH_OP(E_OP_CY_PRE); }; + "CY.RES" => { MATCH_OP(E_OP_CY_RES); }; "CY.POS" => { MATCH_OP(E_OP_CY_POS); }; "CY.REV" => { MATCH_OP(E_OP_CY_REV); }; "CY.CV" => { MATCH_OP(E_OP_CY_CV); }; "MID.SHIFT" => { MATCH_OP(E_OP_MID_SHIFT); }; "MID.SLEW" => { MATCH_OP(E_OP_MID_SLEW); }; - "ARP.STY" => { MATCH_OP(E_OP_ARP_STYLE); }; - "ARP.HLD" => { MATCH_OP(E_OP_ARP_HOLD); }; + "ARP.STY" => { MATCH_OP(E_OP_ARP_STY); }; + "ARP.HLD" => { MATCH_OP(E_OP_ARP_HLD); }; "ARP.RPT" => { MATCH_OP(E_OP_ARP_RPT); }; - "ARP.GT" => { MATCH_OP(E_OP_ARP_GATE); }; + "ARP.GT" => { MATCH_OP(E_OP_ARP_GT); }; "ARP.DIV" => { MATCH_OP(E_OP_ARP_DIV); }; - "ARP.RES" => { MATCH_OP(E_OP_ARP_RESET); }; + "ARP.RES" => { MATCH_OP(E_OP_ARP_RES); }; "ARP.SHIFT" => { MATCH_OP(E_OP_ARP_SHIFT); }; "ARP.SLEW" => { MATCH_OP(E_OP_ARP_SLEW); }; - "ARP.FIL" => { MATCH_OP(E_OP_ARP_FILL); }; + "ARP.FIL" => { MATCH_OP(E_OP_ARP_FIL); }; "ARP.ROT" => { MATCH_OP(E_OP_ARP_ROT); }; "ARP.ER" => { MATCH_OP(E_OP_ARP_ER); }; @@ -282,6 +280,17 @@ "TO.KILL" => { MATCH_OP(E_OP_TO_KILL); }; "TO.TR.PULSE.DIV" => { MATCH_OP(E_OP_TO_TR_PULSE_DIV); }; + "TO.TR.PULSE.MUTE" => { MATCH_OP(E_OP_TO_TR_PULSE_MUTE); }; + "TO.TR.M.MUL" => { MATCH_OP(E_OP_TO_TR_M_MUL); }; + + "TO.M" => { MATCH_OP(E_OP_TO_M); }; + "TO.M.S" => { MATCH_OP(E_OP_TO_M_S); }; + "TO.M.M" => { MATCH_OP(E_OP_TO_M_M); }; + "TO.M.BPM" => { MATCH_OP(E_OP_TO_M_BPM); }; + "TO.M.ACT" => { MATCH_OP(E_OP_TO_M_ACT); }; + "TO.M.SYNC" => { MATCH_OP(E_OP_TO_M_SYNC); }; + "TO.M.COUNT" => { MATCH_OP(E_OP_TO_M_COUNT); }; + "TO.TR.M" => { MATCH_OP(E_OP_TO_TR_M); }; "TO.TR.M.S" => { MATCH_OP(E_OP_TO_TR_M_S); }; "TO.TR.M.M" => { MATCH_OP(E_OP_TO_TR_M_M); }; @@ -302,13 +311,15 @@ "TO.CV.N" => { MATCH_OP(E_OP_TO_CV_N); }; "TO.CV.N.SET" => { MATCH_OP(E_OP_TO_CV_N_SET); }; "TO.CV.SCALE" => { MATCH_OP(E_OP_TO_CV_SCALE); }; + "TO.CV.LOG" => { MATCH_OP(E_OP_TO_CV_LOG); }; "TO.CV.INIT" => { MATCH_OP(E_OP_TO_CV_INIT); }; "TO.TR.INIT" => { MATCH_OP(E_OP_TO_TR_INIT); }; "TO.INIT" => { MATCH_OP(E_OP_TO_INIT); }; "TO.TR.P" => { MATCH_OP(E_OP_TO_TR_P); }; - "TO.TR.P.DIV" => { MATCH_OP(E_OP_TO_TR_P_DIV); }; + "TO.TR.P.DIV" => { MATCH_OP(E_OP_TO_TR_P_DIV); }; + "TO.TR.P.MUTE" => { MATCH_OP(E_OP_TO_TR_P_MUTE); }; "TO.OSC" => { MATCH_OP(E_OP_TO_OSC); }; "TO.OSC.SET" => { MATCH_OP(E_OP_TO_OSC_SET); }; @@ -335,6 +346,7 @@ "TO.OSC.CYC.SET" => { MATCH_OP(E_OP_TO_OSC_CYC_SET); }; "TO.OSC.CYC.S.SET" => { MATCH_OP(E_OP_TO_OSC_CYC_S_SET); }; "TO.OSC.CYC.M.SET" => { MATCH_OP(E_OP_TO_OSC_CYC_M_SET); }; + "TO.OSC.CTR" => { MATCH_OP(E_OP_TO_OSC_CTR); }; "TO.ENV.ACT" => { MATCH_OP(E_OP_TO_ENV_ACT); }; "TO.ENV.ATT" => { MATCH_OP(E_OP_TO_ENV_ATT); }; @@ -345,6 +357,10 @@ "TO.ENV.DEC.M" => { MATCH_OP(E_OP_TO_ENV_DEC_M); }; "TO.ENV.TRIG" => { MATCH_OP(E_OP_TO_ENV_TRIG); }; + "TO.ENV.EOR" => { MATCH_OP(E_OP_TO_ENV_EOR); }; + "TO.ENV.EOC" => { MATCH_OP(E_OP_TO_ENV_EOC); }; + "TO.ENV.LOOP" => { MATCH_OP(E_OP_TO_ENV_LOOP); }; + "TI.PARAM" => { MATCH_OP(E_OP_TI_PARAM); }; "TI.PARAM.QT" => { MATCH_OP(E_OP_TI_PARAM_QT); }; "TI.PARAM.N" => { MATCH_OP(E_OP_TI_PARAM_N); }; diff --git a/src/ops/ansible.c b/src/ops/ansible.c index 6b14a1e9..b1807b1e 100644 --- a/src/ops/ansible.c +++ b/src/ops/ansible.c @@ -5,14 +5,14 @@ #include "teletype_io.h" -static void op_KR_PRESET_get(const void *data, scene_state_t *ss, - exec_state_t *es, command_state_t *cs); -static void op_KR_PRESET_set(const void *data, scene_state_t *ss, - exec_state_t *es, command_state_t *cs); -static void op_KR_PATTERN_get(const void *data, scene_state_t *ss, - exec_state_t *es, command_state_t *cs); -static void op_KR_PATTERN_set(const void *data, scene_state_t *ss, - exec_state_t *es, command_state_t *cs); +static void op_KR_PRE_get(const void *data, scene_state_t *ss, exec_state_t *es, + command_state_t *cs); +static void op_KR_PRE_set(const void *data, scene_state_t *ss, exec_state_t *es, + command_state_t *cs); +static void op_KR_PAT_get(const void *data, scene_state_t *ss, exec_state_t *es, + command_state_t *cs); +static void op_KR_PAT_set(const void *data, scene_state_t *ss, exec_state_t *es, + command_state_t *cs); static void op_KR_SCALE_get(const void *data, scene_state_t *ss, exec_state_t *es, command_state_t *cs); static void op_KR_SCALE_set(const void *data, scene_state_t *ss, @@ -25,40 +25,40 @@ static void op_KR_POS_get(const void *data, scene_state_t *ss, exec_state_t *es, command_state_t *cs); static void op_KR_POS_set(const void *data, scene_state_t *ss, exec_state_t *es, command_state_t *cs); -static void op_KR_LOOP_ST_get(const void *data, scene_state_t *ss, - exec_state_t *es, command_state_t *cs); -static void op_KR_LOOP_ST_set(const void *data, scene_state_t *ss, - exec_state_t *es, command_state_t *cs); -static void op_KR_LOOP_LEN_get(const void *data, scene_state_t *ss, - exec_state_t *es, command_state_t *cs); -static void op_KR_LOOP_LEN_set(const void *data, scene_state_t *ss, - exec_state_t *es, command_state_t *cs); -static void op_KR_RESET_get(const void *data, scene_state_t *ss, +static void op_KR_L_ST_get(const void *data, scene_state_t *ss, + exec_state_t *es, command_state_t *cs); +static void op_KR_L_ST_set(const void *data, scene_state_t *ss, + exec_state_t *es, command_state_t *cs); +static void op_KR_L_LEN_get(const void *data, scene_state_t *ss, exec_state_t *es, command_state_t *cs); - -static void op_MP_PRESET_get(const void *data, scene_state_t *ss, - exec_state_t *es, command_state_t *cs); -static void op_MP_PRESET_set(const void *data, scene_state_t *ss, - exec_state_t *es, command_state_t *cs); -static void op_MP_RESET_get(const void *data, scene_state_t *ss, +static void op_KR_L_LEN_set(const void *data, scene_state_t *ss, exec_state_t *es, command_state_t *cs); -static void op_MP_STOP_get(const void *data, scene_state_t *ss, +static void op_KR_RES_get(const void *data, scene_state_t *ss, exec_state_t *es, + command_state_t *cs); + +static void op_ME_PRE_get(const void *data, scene_state_t *ss, exec_state_t *es, + command_state_t *cs); +static void op_ME_PRE_set(const void *data, scene_state_t *ss, exec_state_t *es, + command_state_t *cs); +static void op_ME_RES_get(const void *data, scene_state_t *ss, exec_state_t *es, + command_state_t *cs); +static void op_ME_STOP_get(const void *data, scene_state_t *ss, exec_state_t *es, command_state_t *cs); -static void op_MP_SCALE_get(const void *data, scene_state_t *ss, +static void op_ME_SCALE_get(const void *data, scene_state_t *ss, exec_state_t *es, command_state_t *cs); -static void op_MP_SCALE_set(const void *data, scene_state_t *ss, +static void op_ME_SCALE_set(const void *data, scene_state_t *ss, exec_state_t *es, command_state_t *cs); -static void op_MP_PERIOD_get(const void *data, scene_state_t *ss, +static void op_ME_PERIOD_get(const void *data, scene_state_t *ss, exec_state_t *es, command_state_t *cs); -static void op_MP_PERIOD_set(const void *data, scene_state_t *ss, +static void op_ME_PERIOD_set(const void *data, scene_state_t *ss, exec_state_t *es, command_state_t *cs); -static void op_LV_PRESET_get(const void *data, scene_state_t *ss, - exec_state_t *es, command_state_t *cs); -static void op_LV_PRESET_set(const void *data, scene_state_t *ss, - exec_state_t *es, command_state_t *cs); -static void op_LV_RESET_get(const void *data, scene_state_t *ss, - exec_state_t *es, command_state_t *cs); +static void op_LV_PRE_get(const void *data, scene_state_t *ss, exec_state_t *es, + command_state_t *cs); +static void op_LV_PRE_set(const void *data, scene_state_t *ss, exec_state_t *es, + command_state_t *cs); +static void op_LV_RES_get(const void *data, scene_state_t *ss, exec_state_t *es, + command_state_t *cs); static void op_LV_POS_get(const void *data, scene_state_t *ss, exec_state_t *es, command_state_t *cs); static void op_LV_POS_set(const void *data, scene_state_t *ss, exec_state_t *es, @@ -78,12 +78,12 @@ static void op_LV_L_DIR_set(const void *data, scene_state_t *ss, static void op_LV_CV_get(const void *data, scene_state_t *ss, exec_state_t *es, command_state_t *cs); -static void op_CY_PRESET_get(const void *data, scene_state_t *ss, - exec_state_t *es, command_state_t *cs); -static void op_CY_PRESET_set(const void *data, scene_state_t *ss, - exec_state_t *es, command_state_t *cs); -static void op_CY_RESET_get(const void *data, scene_state_t *ss, - exec_state_t *es, command_state_t *cs); +static void op_CY_PRE_get(const void *data, scene_state_t *ss, exec_state_t *es, + command_state_t *cs); +static void op_CY_PRE_set(const void *data, scene_state_t *ss, exec_state_t *es, + command_state_t *cs); +static void op_CY_RES_get(const void *data, scene_state_t *ss, exec_state_t *es, + command_state_t *cs); static void op_CY_POS_get(const void *data, scene_state_t *ss, exec_state_t *es, command_state_t *cs); static void op_CY_POS_set(const void *data, scene_state_t *ss, exec_state_t *es, @@ -98,24 +98,24 @@ static void op_MID_SHIFT_get(const void *data, scene_state_t *ss, static void op_MID_SLEW_get(const void *data, scene_state_t *ss, exec_state_t *es, command_state_t *cs); -static void op_ARP_STYLE_get(const void *data, scene_state_t *ss, - exec_state_t *es, command_state_t *cs); -static void op_ARP_HOLD_get(const void *data, scene_state_t *ss, - exec_state_t *es, command_state_t *cs); +static void op_ARP_STY_get(const void *data, scene_state_t *ss, + exec_state_t *es, command_state_t *cs); +static void op_ARP_HLD_get(const void *data, scene_state_t *ss, + exec_state_t *es, command_state_t *cs); static void op_ARP_RPT_get(const void *data, scene_state_t *ss, exec_state_t *es, command_state_t *cs); -static void op_ARP_GATE_get(const void *data, scene_state_t *ss, - exec_state_t *es, command_state_t *cs); +static void op_ARP_GT_get(const void *data, scene_state_t *ss, exec_state_t *es, + command_state_t *cs); static void op_ARP_DIV_get(const void *data, scene_state_t *ss, exec_state_t *es, command_state_t *cs); -static void op_ARP_RESET_get(const void *data, scene_state_t *ss, - exec_state_t *es, command_state_t *cs); +static void op_ARP_RES_get(const void *data, scene_state_t *ss, + exec_state_t *es, command_state_t *cs); static void op_ARP_SHIFT_get(const void *data, scene_state_t *ss, exec_state_t *es, command_state_t *cs); static void op_ARP_SLEW_get(const void *data, scene_state_t *ss, exec_state_t *es, command_state_t *cs); -static void op_ARP_FILL_get(const void *data, scene_state_t *ss, - exec_state_t *es, command_state_t *cs); +static void op_ARP_FIL_get(const void *data, scene_state_t *ss, + exec_state_t *es, command_state_t *cs); static void op_ARP_ROT_get(const void *data, scene_state_t *ss, exec_state_t *es, command_state_t *cs); static void op_ARP_ER_get(const void *data, scene_state_t *ss, exec_state_t *es, @@ -123,63 +123,61 @@ static void op_ARP_ER_get(const void *data, scene_state_t *ss, exec_state_t *es, // clang-format off -const tele_op_t op_KR_PRESET = MAKE_GET_SET_OP(KR.PRE , op_KR_PRESET_get , op_KR_PRESET_set , 0, true); -const tele_op_t op_KR_PATTERN = MAKE_GET_SET_OP(KR.PAT , op_KR_PATTERN_get , op_KR_PATTERN_set , 0, true); +const tele_op_t op_KR_PRE = MAKE_GET_SET_OP(KR.PRE , op_KR_PRE_get , op_KR_PRE_set , 0, true); +const tele_op_t op_KR_PAT = MAKE_GET_SET_OP(KR.PAT , op_KR_PAT_get , op_KR_PAT_set , 0, true); const tele_op_t op_KR_SCALE = MAKE_GET_SET_OP(KR.SCALE , op_KR_SCALE_get , op_KR_SCALE_set , 0, true); const tele_op_t op_KR_PERIOD = MAKE_GET_SET_OP(KR.PERIOD , op_KR_PERIOD_get , op_KR_PERIOD_set , 0, true); const tele_op_t op_KR_POS = MAKE_GET_SET_OP(KR.POS , op_KR_POS_get , op_KR_POS_set , 2, true); -const tele_op_t op_KR_LOOP_ST = MAKE_GET_SET_OP(KR.L.ST , op_KR_LOOP_ST_get , op_KR_LOOP_ST_set , 2, true); -const tele_op_t op_KR_LOOP_LEN = MAKE_GET_SET_OP(KR.L.LEN , op_KR_LOOP_LEN_get , op_KR_LOOP_LEN_set , 2, true); -const tele_op_t op_KR_RESET = MAKE_GET_OP (KR.RES , op_KR_RESET_get , 2, false); - -const tele_op_t op_MP_PRESET1 = MAKE_GET_SET_OP(MP.PRE , op_MP_PRESET_get , op_MP_PRESET_set , 0, true); -const tele_op_t op_MP_RESET1 = MAKE_GET_OP (MP.RES , op_MP_RESET_get , 1, false); -const tele_op_t op_MP_STOP1 = MAKE_GET_OP (MP.OFF , op_MP_STOP_get , 1, false); -const tele_op_t op_MP_SCALE = MAKE_GET_SET_OP(MP.SCALE , op_MP_SCALE_get , op_MP_SCALE_set , 0, true); -const tele_op_t op_MP_PERIOD = MAKE_GET_SET_OP(MP.PERIOD , op_MP_PERIOD_get , op_MP_PERIOD_set , 0, true); - -const tele_op_t op_LV_PRESET = MAKE_GET_SET_OP(LV.PRE , op_LV_PRESET_get , op_LV_PRESET_set , 0, true); -const tele_op_t op_LV_RESET = MAKE_GET_OP(LV.RES , op_LV_RESET_get , 1, false); +const tele_op_t op_KR_L_ST = MAKE_GET_SET_OP(KR.L.ST , op_KR_L_ST_get , op_KR_L_ST_set , 2, true); +const tele_op_t op_KR_L_LEN = MAKE_GET_SET_OP(KR.L.LEN , op_KR_L_LEN_get , op_KR_L_LEN_set , 2, true); +const tele_op_t op_KR_RES = MAKE_GET_OP (KR.RES , op_KR_RES_get , 2, false); + +const tele_op_t op_ME_PRE = MAKE_GET_SET_OP(ME.PRE , op_ME_PRE_get , op_ME_PRE_set , 0, true); +const tele_op_t op_ME_RES = MAKE_GET_OP (ME.RES , op_ME_RES_get , 1, false); +const tele_op_t op_ME_STOP = MAKE_GET_OP (ME.STOP , op_ME_STOP_get , 1, false); +const tele_op_t op_ME_SCALE = MAKE_GET_SET_OP(ME.SCALE , op_ME_SCALE_get , op_ME_SCALE_set , 0, true); +const tele_op_t op_ME_PERIOD = MAKE_GET_SET_OP(ME.PERIOD , op_ME_PERIOD_get , op_ME_PERIOD_set , 0, true); + +const tele_op_t op_LV_PRE = MAKE_GET_SET_OP(LV.PRE , op_LV_PRE_get , op_LV_PRE_set , 0, true); +const tele_op_t op_LV_RES = MAKE_GET_OP (LV.RES , op_LV_RES_get , 1, false); const tele_op_t op_LV_POS = MAKE_GET_SET_OP(LV.POS , op_LV_POS_get , op_LV_POS_set , 0, true); const tele_op_t op_LV_L_ST = MAKE_GET_SET_OP(LV.L.ST , op_LV_L_ST_get , op_LV_L_ST_set , 0, true); const tele_op_t op_LV_L_LEN = MAKE_GET_SET_OP(LV.L.LEN , op_LV_L_LEN_get , op_LV_L_LEN_set , 0, true); const tele_op_t op_LV_L_DIR = MAKE_GET_SET_OP(LV.L.DIR , op_LV_L_DIR_get , op_LV_L_DIR_set , 0, true); -const tele_op_t op_LV_CV = MAKE_GET_OP(LV.CV , op_LV_CV_get , 1, true); +const tele_op_t op_LV_CV = MAKE_GET_OP (LV.CV , op_LV_CV_get , 1, true); -const tele_op_t op_CY_PRESET = MAKE_GET_SET_OP(CY.PRE , op_CY_PRESET_get , op_CY_PRESET_set , 0, true); -const tele_op_t op_CY_RESET = MAKE_GET_OP (CY.RES , op_CY_RESET_get , 1, false); +const tele_op_t op_CY_PRE = MAKE_GET_SET_OP(CY.PRE , op_CY_PRE_get , op_CY_PRE_set , 0, true); +const tele_op_t op_CY_RES = MAKE_GET_OP (CY.RES , op_CY_RES_get , 1, false); const tele_op_t op_CY_POS = MAKE_GET_SET_OP(CY.POS , op_CY_POS_get , op_CY_POS_set , 1, true); -const tele_op_t op_CY_REV = MAKE_GET_OP(CY.REV , op_CY_REV_get , 1, false); -const tele_op_t op_CY_CV = MAKE_GET_OP(CY.CV , op_CY_CV_get , 1, true); - -const tele_op_t op_MID_SHIFT = MAKE_GET_OP(MID.SHIFT , op_MID_SHIFT_get , 1, false); -const tele_op_t op_MID_SLEW = MAKE_GET_OP(MID.SLEW , op_MID_SLEW_get , 1, false); - -const tele_op_t op_ARP_STYLE = MAKE_GET_OP(ARP.STY , op_ARP_STYLE_get , 1, false); -const tele_op_t op_ARP_HOLD = MAKE_GET_OP(ARP.HLD , op_ARP_HOLD_get , 1, false); -const tele_op_t op_ARP_RPT = MAKE_GET_OP(ARP.RPT , op_ARP_RPT_get , 3, false); -const tele_op_t op_ARP_GATE = MAKE_GET_OP(ARP.GT , op_ARP_GATE_get , 2, false); -const tele_op_t op_ARP_DIV = MAKE_GET_OP(ARP.DIV , op_ARP_DIV_get , 2, false); -const tele_op_t op_ARP_RESET = MAKE_GET_OP(ARP.RES , op_ARP_RESET_get , 1, false); -const tele_op_t op_ARP_SHIFT = MAKE_GET_OP(ARP.SHIFT , op_ARP_SHIFT_get , 2, false); -const tele_op_t op_ARP_SLEW = MAKE_GET_OP(ARP.SLEW , op_ARP_SLEW_get , 2, false); -const tele_op_t op_ARP_FILL = MAKE_GET_OP(ARP.FIL , op_ARP_FILL_get , 2, false); -const tele_op_t op_ARP_ROT = MAKE_GET_OP(ARP.ROT , op_ARP_ROT_get , 2, false); -const tele_op_t op_ARP_ER = MAKE_GET_OP(ARP.ER , op_ARP_ER_get , 4, false); +const tele_op_t op_CY_REV = MAKE_GET_OP (CY.REV , op_CY_REV_get , 1, false); +const tele_op_t op_CY_CV = MAKE_GET_OP (CY.CV , op_CY_CV_get , 1, true); + +const tele_op_t op_MID_SHIFT = MAKE_GET_OP(MID.SHIFT , op_MID_SHIFT_get , 1, false); +const tele_op_t op_MID_SLEW = MAKE_GET_OP(MID.SLEW , op_MID_SLEW_get , 1, false); + +const tele_op_t op_ARP_STY = MAKE_GET_OP(ARP.STY , op_ARP_STY_get , 1, false); +const tele_op_t op_ARP_HLD = MAKE_GET_OP(ARP.HLD , op_ARP_HLD_get , 1, false); +const tele_op_t op_ARP_RPT = MAKE_GET_OP(ARP.RPT , op_ARP_RPT_get , 3, false); +const tele_op_t op_ARP_GT = MAKE_GET_OP(ARP.GT , op_ARP_GT_get , 2, false); +const tele_op_t op_ARP_DIV = MAKE_GET_OP(ARP.DIV , op_ARP_DIV_get , 2, false); +const tele_op_t op_ARP_RES = MAKE_GET_OP(ARP.RES , op_ARP_RES_get , 1, false); +const tele_op_t op_ARP_SHIFT = MAKE_GET_OP(ARP.SHIFT , op_ARP_SHIFT_get , 2, false); +const tele_op_t op_ARP_SLEW = MAKE_GET_OP(ARP.SLEW , op_ARP_SLEW_get , 2, false); +const tele_op_t op_ARP_FIL = MAKE_GET_OP(ARP.FIL , op_ARP_FIL_get , 2, false); +const tele_op_t op_ARP_ROT = MAKE_GET_OP(ARP.ROT , op_ARP_ROT_get , 2, false); +const tele_op_t op_ARP_ER = MAKE_GET_OP(ARP.ER , op_ARP_ER_get , 4, false); // clang-format on -static void op_KR_PRESET_set(const void *NOTUSED(data), - scene_state_t *NOTUSED(ss), - exec_state_t *NOTUSED(es), command_state_t *cs) { +static void op_KR_PRE_set(const void *NOTUSED(data), scene_state_t *NOTUSED(ss), + exec_state_t *NOTUSED(es), command_state_t *cs) { int16_t a = cs_pop(cs); uint8_t d[] = { II_KR_PRESET, a }; tele_ii_tx(II_KR_ADDR, d, 2); } -static void op_KR_PRESET_get(const void *NOTUSED(data), - scene_state_t *NOTUSED(ss), - exec_state_t *NOTUSED(es), command_state_t *cs) { +static void op_KR_PRE_get(const void *NOTUSED(data), scene_state_t *NOTUSED(ss), + exec_state_t *NOTUSED(es), command_state_t *cs) { uint8_t d[] = { II_KR_PRESET | II_GET }; uint8_t addr = II_KR_ADDR; tele_ii_tx(addr, d, 1); @@ -188,17 +186,15 @@ static void op_KR_PRESET_get(const void *NOTUSED(data), cs_push(cs, d[0]); } -static void op_KR_PATTERN_set(const void *NOTUSED(data), - scene_state_t *NOTUSED(ss), - exec_state_t *NOTUSED(es), command_state_t *cs) { +static void op_KR_PAT_set(const void *NOTUSED(data), scene_state_t *NOTUSED(ss), + exec_state_t *NOTUSED(es), command_state_t *cs) { int16_t a = cs_pop(cs); uint8_t d[] = { II_KR_PATTERN, a }; tele_ii_tx(II_KR_ADDR, d, 2); } -static void op_KR_PATTERN_get(const void *NOTUSED(data), - scene_state_t *NOTUSED(ss), - exec_state_t *NOTUSED(es), command_state_t *cs) { +static void op_KR_PAT_get(const void *NOTUSED(data), scene_state_t *NOTUSED(ss), + exec_state_t *NOTUSED(es), command_state_t *cs) { uint8_t d[] = { II_KR_PATTERN | II_GET }; uint8_t addr = II_KR_ADDR; tele_ii_tx(addr, d, 1); @@ -267,9 +263,9 @@ static void op_KR_POS_get(const void *NOTUSED(data), scene_state_t *NOTUSED(ss), cs_push(cs, d[0]); } -static void op_KR_LOOP_ST_set(const void *NOTUSED(data), - scene_state_t *NOTUSED(ss), - exec_state_t *NOTUSED(es), command_state_t *cs) { +static void op_KR_L_ST_set(const void *NOTUSED(data), + scene_state_t *NOTUSED(ss), + exec_state_t *NOTUSED(es), command_state_t *cs) { int16_t a = cs_pop(cs); int16_t b = cs_pop(cs); int16_t c = cs_pop(cs); @@ -277,9 +273,9 @@ static void op_KR_LOOP_ST_set(const void *NOTUSED(data), tele_ii_tx(II_KR_ADDR, d, 4); } -static void op_KR_LOOP_ST_get(const void *NOTUSED(data), - scene_state_t *NOTUSED(ss), - exec_state_t *NOTUSED(es), command_state_t *cs) { +static void op_KR_L_ST_get(const void *NOTUSED(data), + scene_state_t *NOTUSED(ss), + exec_state_t *NOTUSED(es), command_state_t *cs) { int16_t a = cs_pop(cs); int16_t b = cs_pop(cs); uint8_t d[] = { II_KR_LOOP_ST | II_GET, a, b }; @@ -290,9 +286,9 @@ static void op_KR_LOOP_ST_get(const void *NOTUSED(data), cs_push(cs, d[0]); } -static void op_KR_LOOP_LEN_set(const void *NOTUSED(data), - scene_state_t *NOTUSED(ss), - exec_state_t *NOTUSED(es), command_state_t *cs) { +static void op_KR_L_LEN_set(const void *NOTUSED(data), + scene_state_t *NOTUSED(ss), + exec_state_t *NOTUSED(es), command_state_t *cs) { int16_t a = cs_pop(cs); int16_t b = cs_pop(cs); int16_t c = cs_pop(cs); @@ -300,9 +296,9 @@ static void op_KR_LOOP_LEN_set(const void *NOTUSED(data), tele_ii_tx(II_KR_ADDR, d, 4); } -static void op_KR_LOOP_LEN_get(const void *NOTUSED(data), - scene_state_t *NOTUSED(ss), - exec_state_t *NOTUSED(es), command_state_t *cs) { +static void op_KR_L_LEN_get(const void *NOTUSED(data), + scene_state_t *NOTUSED(ss), + exec_state_t *NOTUSED(es), command_state_t *cs) { int16_t a = cs_pop(cs); int16_t b = cs_pop(cs); uint8_t d[] = { II_KR_LOOP_LEN | II_GET, a, b }; @@ -313,26 +309,23 @@ static void op_KR_LOOP_LEN_get(const void *NOTUSED(data), cs_push(cs, d[0]); } -static void op_KR_RESET_get(const void *NOTUSED(data), - scene_state_t *NOTUSED(ss), - exec_state_t *NOTUSED(es), command_state_t *cs) { +static void op_KR_RES_get(const void *NOTUSED(data), scene_state_t *NOTUSED(ss), + exec_state_t *NOTUSED(es), command_state_t *cs) { int16_t a = cs_pop(cs); int16_t b = cs_pop(cs); uint8_t d[] = { II_KR_RESET, a, b }; tele_ii_tx(II_KR_ADDR, d, 3); } -static void op_MP_PRESET_set(const void *NOTUSED(data), - scene_state_t *NOTUSED(ss), - exec_state_t *NOTUSED(es), command_state_t *cs) { +static void op_ME_PRE_set(const void *NOTUSED(data), scene_state_t *NOTUSED(ss), + exec_state_t *NOTUSED(es), command_state_t *cs) { int16_t a = cs_pop(cs); uint8_t d[] = { II_MP_PRESET, a }; tele_ii_tx(II_MP_ADDR, d, 2); } -static void op_MP_PRESET_get(const void *NOTUSED(data), - scene_state_t *NOTUSED(ss), - exec_state_t *NOTUSED(es), command_state_t *cs) { +static void op_ME_PRE_get(const void *NOTUSED(data), scene_state_t *NOTUSED(ss), + exec_state_t *NOTUSED(es), command_state_t *cs) { uint8_t d[] = { II_MP_PRESET | II_GET }; uint8_t addr = II_MP_ADDR; tele_ii_tx(addr, d, 1); @@ -341,15 +334,14 @@ static void op_MP_PRESET_get(const void *NOTUSED(data), cs_push(cs, d[0]); } -static void op_MP_RESET_get(const void *NOTUSED(data), - scene_state_t *NOTUSED(ss), - exec_state_t *NOTUSED(es), command_state_t *cs) { +static void op_ME_RES_get(const void *NOTUSED(data), scene_state_t *NOTUSED(ss), + exec_state_t *NOTUSED(es), command_state_t *cs) { int16_t a = cs_pop(cs); uint8_t d[] = { II_MP_RESET, a }; tele_ii_tx(II_MP_ADDR, d, 2); } -static void op_MP_STOP_get(const void *NOTUSED(data), +static void op_ME_STOP_get(const void *NOTUSED(data), scene_state_t *NOTUSED(ss), exec_state_t *NOTUSED(es), command_state_t *cs) { int16_t a = cs_pop(cs); @@ -357,7 +349,7 @@ static void op_MP_STOP_get(const void *NOTUSED(data), tele_ii_tx(II_MP_ADDR, d, 2); } -static void op_MP_SCALE_set(const void *NOTUSED(data), +static void op_ME_SCALE_set(const void *NOTUSED(data), scene_state_t *NOTUSED(ss), exec_state_t *NOTUSED(es), command_state_t *cs) { int16_t a = cs_pop(cs); @@ -365,7 +357,7 @@ static void op_MP_SCALE_set(const void *NOTUSED(data), tele_ii_tx(II_MP_ADDR, d, 2); } -static void op_MP_SCALE_get(const void *NOTUSED(data), +static void op_ME_SCALE_get(const void *NOTUSED(data), scene_state_t *NOTUSED(ss), exec_state_t *NOTUSED(es), command_state_t *cs) { uint8_t d[] = { II_MP_SCALE | II_GET }; @@ -376,7 +368,7 @@ static void op_MP_SCALE_get(const void *NOTUSED(data), cs_push(cs, d[0]); } -static void op_MP_PERIOD_set(const void *NOTUSED(data), +static void op_ME_PERIOD_set(const void *NOTUSED(data), scene_state_t *NOTUSED(ss), exec_state_t *NOTUSED(es), command_state_t *cs) { int16_t a = cs_pop(cs); @@ -384,7 +376,7 @@ static void op_MP_PERIOD_set(const void *NOTUSED(data), tele_ii_tx(II_MP_ADDR, d, 3); } -static void op_MP_PERIOD_get(const void *NOTUSED(data), +static void op_ME_PERIOD_get(const void *NOTUSED(data), scene_state_t *NOTUSED(ss), exec_state_t *NOTUSED(es), command_state_t *cs) { uint8_t d[] = { II_MP_PERIOD | II_GET, 0 }; @@ -396,17 +388,15 @@ static void op_MP_PERIOD_get(const void *NOTUSED(data), cs_push(cs, (d[0] << 8) + d[1]); } -static void op_LV_PRESET_set(const void *NOTUSED(data), - scene_state_t *NOTUSED(ss), - exec_state_t *NOTUSED(es), command_state_t *cs) { +static void op_LV_PRE_set(const void *NOTUSED(data), scene_state_t *NOTUSED(ss), + exec_state_t *NOTUSED(es), command_state_t *cs) { int16_t a = cs_pop(cs); uint8_t d[] = { II_LV_PRESET, a }; tele_ii_tx(II_LV_ADDR, d, 2); } -static void op_LV_PRESET_get(const void *NOTUSED(data), - scene_state_t *NOTUSED(ss), - exec_state_t *NOTUSED(es), command_state_t *cs) { +static void op_LV_PRE_get(const void *NOTUSED(data), scene_state_t *NOTUSED(ss), + exec_state_t *NOTUSED(es), command_state_t *cs) { uint8_t d[] = { II_LV_PRESET | II_GET }; uint8_t addr = II_LV_ADDR; tele_ii_tx(addr, d, 1); @@ -415,9 +405,8 @@ static void op_LV_PRESET_get(const void *NOTUSED(data), cs_push(cs, d[0]); } -static void op_LV_RESET_get(const void *NOTUSED(data), - scene_state_t *NOTUSED(ss), - exec_state_t *NOTUSED(es), command_state_t *cs) { +static void op_LV_RES_get(const void *NOTUSED(data), scene_state_t *NOTUSED(ss), + exec_state_t *NOTUSED(es), command_state_t *cs) { int16_t a = cs_pop(cs); uint8_t d[] = { II_LV_RESET, a }; tele_ii_tx(II_LV_ADDR, d, 2); @@ -504,16 +493,15 @@ static void op_LV_CV_get(const void *data, scene_state_t *ss, exec_state_t *es, cs_push(cs, (d[0] << 8) + d[1]); } -static void op_CY_PRESET_set(const void *data, scene_state_t *ss, - exec_state_t *es, command_state_t *cs) { +static void op_CY_PRE_set(const void *data, scene_state_t *ss, exec_state_t *es, + command_state_t *cs) { int16_t a = cs_pop(cs); uint8_t d[] = { II_CY_PRESET, a }; tele_ii_tx(II_CY_ADDR, d, 2); } -static void op_CY_PRESET_get(const void *NOTUSED(data), - scene_state_t *NOTUSED(ss), - exec_state_t *NOTUSED(es), command_state_t *cs) { +static void op_CY_PRE_get(const void *NOTUSED(data), scene_state_t *NOTUSED(ss), + exec_state_t *NOTUSED(es), command_state_t *cs) { uint8_t d[] = { II_CY_PRESET | II_GET }; uint8_t addr = II_CY_ADDR; tele_ii_tx(addr, d, 1); @@ -522,9 +510,8 @@ static void op_CY_PRESET_get(const void *NOTUSED(data), cs_push(cs, d[0]); } -static void op_CY_RESET_get(const void *NOTUSED(data), - scene_state_t *NOTUSED(ss), - exec_state_t *NOTUSED(es), command_state_t *cs) { +static void op_CY_RES_get(const void *NOTUSED(data), scene_state_t *NOTUSED(ss), + exec_state_t *NOTUSED(es), command_state_t *cs) { int16_t a = cs_pop(cs); uint8_t d[] = { II_CY_RESET, a }; tele_ii_tx(II_CY_ADDR, d, 2); @@ -585,17 +572,17 @@ static void op_MID_SLEW_get(const void *NOTUSED(data), tele_ii_tx(II_MID_ADDR, d, 3); } -static void op_ARP_STYLE_get(const void *NOTUSED(data), - scene_state_t *NOTUSED(ss), - exec_state_t *NOTUSED(es), command_state_t *cs) { +static void op_ARP_STY_get(const void *NOTUSED(data), + scene_state_t *NOTUSED(ss), + exec_state_t *NOTUSED(es), command_state_t *cs) { int16_t a = cs_pop(cs); uint8_t d[] = { II_ARP_STYLE, a }; tele_ii_tx(II_ARP_ADDR, d, 2); } -static void op_ARP_HOLD_get(const void *NOTUSED(data), - scene_state_t *NOTUSED(ss), - exec_state_t *NOTUSED(es), command_state_t *cs) { +static void op_ARP_HLD_get(const void *NOTUSED(data), + scene_state_t *NOTUSED(ss), + exec_state_t *NOTUSED(es), command_state_t *cs) { int16_t a = cs_pop(cs); uint8_t d[] = { II_ARP_HOLD, a & 0xff }; tele_ii_tx(II_ARP_ADDR, d, 2); @@ -611,9 +598,8 @@ static void op_ARP_RPT_get(const void *NOTUSED(data), tele_ii_tx(II_ARP_ADDR, d, 5); } -static void op_ARP_GATE_get(const void *NOTUSED(data), - scene_state_t *NOTUSED(ss), - exec_state_t *NOTUSED(es), command_state_t *cs) { +static void op_ARP_GT_get(const void *NOTUSED(data), scene_state_t *NOTUSED(ss), + exec_state_t *NOTUSED(es), command_state_t *cs) { int16_t a = cs_pop(cs); int16_t b = cs_pop(cs); uint8_t d[] = { II_ARP_GATE, a & 0xff, b & 0xff }; @@ -629,9 +615,9 @@ static void op_ARP_DIV_get(const void *NOTUSED(data), tele_ii_tx(II_ARP_ADDR, d, 3); } -static void op_ARP_RESET_get(const void *NOTUSED(data), - scene_state_t *NOTUSED(ss), - exec_state_t *NOTUSED(es), command_state_t *cs) { +static void op_ARP_RES_get(const void *NOTUSED(data), + scene_state_t *NOTUSED(ss), + exec_state_t *NOTUSED(es), command_state_t *cs) { int16_t a = cs_pop(cs); uint8_t d[] = { II_ARP_RESET, a }; tele_ii_tx(II_ARP_ADDR, d, 2); @@ -655,9 +641,9 @@ static void op_ARP_SLEW_get(const void *NOTUSED(data), tele_ii_tx(II_ARP_ADDR, d, 4); } -static void op_ARP_FILL_get(const void *NOTUSED(data), - scene_state_t *NOTUSED(ss), - exec_state_t *NOTUSED(es), command_state_t *cs) { +static void op_ARP_FIL_get(const void *NOTUSED(data), + scene_state_t *NOTUSED(ss), + exec_state_t *NOTUSED(es), command_state_t *cs) { int16_t a = cs_pop(cs); int16_t b = cs_pop(cs); uint8_t d[] = { II_ARP_FILL, a, b }; diff --git a/src/ops/ansible.h b/src/ops/ansible.h index fe424681..55a48af9 100644 --- a/src/ops/ansible.h +++ b/src/ops/ansible.h @@ -3,31 +3,31 @@ #include "ops/op.h" -extern const tele_op_t op_KR_PRESET; -extern const tele_op_t op_KR_PATTERN; +extern const tele_op_t op_KR_PRE; +extern const tele_op_t op_KR_PAT; extern const tele_op_t op_KR_SCALE; extern const tele_op_t op_KR_PERIOD; extern const tele_op_t op_KR_POS; -extern const tele_op_t op_KR_LOOP_ST; -extern const tele_op_t op_KR_LOOP_LEN; -extern const tele_op_t op_KR_RESET; - -extern const tele_op_t op_MP_PRESET1; -extern const tele_op_t op_MP_RESET1; -extern const tele_op_t op_MP_STOP1; -extern const tele_op_t op_MP_SCALE; -extern const tele_op_t op_MP_PERIOD; - -extern const tele_op_t op_LV_PRESET; -extern const tele_op_t op_LV_RESET; +extern const tele_op_t op_KR_L_ST; +extern const tele_op_t op_KR_L_LEN; +extern const tele_op_t op_KR_RES; + +extern const tele_op_t op_ME_PRE; +extern const tele_op_t op_ME_RES; +extern const tele_op_t op_ME_STOP; +extern const tele_op_t op_ME_SCALE; +extern const tele_op_t op_ME_PERIOD; + +extern const tele_op_t op_LV_PRE; +extern const tele_op_t op_LV_RES; extern const tele_op_t op_LV_POS; extern const tele_op_t op_LV_L_ST; extern const tele_op_t op_LV_L_LEN; extern const tele_op_t op_LV_L_DIR; extern const tele_op_t op_LV_CV; -extern const tele_op_t op_CY_PRESET; -extern const tele_op_t op_CY_RESET; +extern const tele_op_t op_CY_PRE; +extern const tele_op_t op_CY_RES; extern const tele_op_t op_CY_POS; extern const tele_op_t op_CY_REV; extern const tele_op_t op_CY_CV; @@ -35,15 +35,15 @@ extern const tele_op_t op_CY_CV; extern const tele_op_t op_MID_SHIFT; extern const tele_op_t op_MID_SLEW; -extern const tele_op_t op_ARP_STYLE; -extern const tele_op_t op_ARP_HOLD; +extern const tele_op_t op_ARP_STY; +extern const tele_op_t op_ARP_HLD; extern const tele_op_t op_ARP_RPT; -extern const tele_op_t op_ARP_GATE; +extern const tele_op_t op_ARP_GT; extern const tele_op_t op_ARP_DIV; -extern const tele_op_t op_ARP_RESET; +extern const tele_op_t op_ARP_RES; extern const tele_op_t op_ARP_SHIFT; extern const tele_op_t op_ARP_SLEW; -extern const tele_op_t op_ARP_FILL; +extern const tele_op_t op_ARP_FIL; extern const tele_op_t op_ARP_ROT; extern const tele_op_t op_ARP_ER; diff --git a/src/ops/maths.c b/src/ops/maths.c index c67381c8..880e5b01 100644 --- a/src/ops/maths.c +++ b/src/ops/maths.c @@ -62,8 +62,6 @@ static void op_AND_get(const void *data, scene_state_t *ss, exec_state_t *es, command_state_t *cs); static void op_OR_get(const void *data, scene_state_t *ss, exec_state_t *es, command_state_t *cs); -static void op_XOR_get(const void *data, scene_state_t *ss, exec_state_t *es, - command_state_t *cs); static void op_JI_get(const void *data, scene_state_t *ss, exec_state_t *es, command_state_t *cs); static void op_SCALE_get(const void *data, scene_state_t *ss, exec_state_t *es, @@ -107,7 +105,6 @@ const tele_op_t op_EXP = MAKE_GET_OP(EXP , op_EXP_get , 1, true); const tele_op_t op_ABS = MAKE_GET_OP(ABS , op_ABS_get , 1, true); const tele_op_t op_AND = MAKE_GET_OP(AND , op_AND_get , 2, true); const tele_op_t op_OR = MAKE_GET_OP(OR , op_OR_get , 2, true); -const tele_op_t op_XOR = MAKE_GET_OP(XOR , op_XOR_get , 2, true); const tele_op_t op_JI = MAKE_GET_OP(JI , op_JI_get , 2, true); const tele_op_t op_SCALE = MAKE_GET_OP(SCALE , op_SCALE_get , 5, true); const tele_op_t op_N = MAKE_GET_OP(N , op_N_get , 1, true); @@ -115,6 +112,8 @@ const tele_op_t op_V = MAKE_GET_OP(V , op_V_get , 1, true); const tele_op_t op_VV = MAKE_GET_OP(VV , op_VV_get , 1, true); const tele_op_t op_ER = MAKE_GET_OP(ER , op_ER_get , 3, true); +const tele_op_t op_XOR = MAKE_ALIAS_OP(XOR, op_NE_get, NULL, 2, true); + const tele_op_t op_SYM_PLUS = MAKE_ALIAS_OP(+ , op_ADD_get, NULL, 2, true); const tele_op_t op_SYM_DASH = MAKE_ALIAS_OP(- , op_SUB_get, NULL, 2, true); const tele_op_t op_SYM_STAR = MAKE_ALIAS_OP(* , op_MUL_get, NULL, 2, true); @@ -129,8 +128,8 @@ const tele_op_t op_SYM_RIGHT_ANGLED_EQUAL = MAKE_ALIAS_OP(>=, op_GTE_get, NULL, const tele_op_t op_SYM_EXCLAMATION = MAKE_ALIAS_OP(! , op_EZ_get , NULL, 1, true); const tele_op_t op_SYM_LEFT_ANGLED_x2 = MAKE_ALIAS_OP(<<, op_LSH_get, NULL, 2, true); const tele_op_t op_SYM_RIGHT_ANGLED_x2 = MAKE_ALIAS_OP(>>, op_RSH_get, NULL, 2, true); -const tele_op_t op_AMPERSAND_x2 = MAKE_ALIAS_OP(&&, op_AND_get, NULL, 2, true); -const tele_op_t op_PIPE_x2 = MAKE_ALIAS_OP(||, op_OR_get , NULL, 2, true); +const tele_op_t op_SYM_AMPERSAND_x2 = MAKE_ALIAS_OP(&&, op_AND_get, NULL, 2, true); +const tele_op_t op_SYM_PIPE_x2 = MAKE_ALIAS_OP(||, op_OR_get , NULL, 2, true); // clang-format on @@ -361,17 +360,16 @@ static void op_ABS_get(const void *NOTUSED(data), scene_state_t *NOTUSED(ss), static void op_AND_get(const void *NOTUSED(data), scene_state_t *NOTUSED(ss), exec_state_t *NOTUSED(es), command_state_t *cs) { - cs_push(cs, cs_pop(cs) & cs_pop(cs)); + int16_t a = cs_pop(cs); + int16_t b = cs_pop(cs); + cs_push(cs, (a > 0) && (b > 0)); } static void op_OR_get(const void *NOTUSED(data), scene_state_t *NOTUSED(ss), exec_state_t *NOTUSED(es), command_state_t *cs) { - cs_push(cs, cs_pop(cs) | cs_pop(cs)); -} - -static void op_XOR_get(const void *NOTUSED(data), scene_state_t *NOTUSED(ss), - exec_state_t *NOTUSED(es), command_state_t *cs) { - cs_push(cs, cs_pop(cs) ^ cs_pop(cs)); + int16_t a = cs_pop(cs); + int16_t b = cs_pop(cs); + cs_push(cs, (a > 0) || (b > 0)); } static void op_JI_get(const void *NOTUSED(data), scene_state_t *NOTUSED(ss), @@ -439,14 +437,13 @@ static void op_V_get(const void *NOTUSED(data), scene_state_t *NOTUSED(ss), static void op_VV_get(const void *NOTUSED(data), scene_state_t *NOTUSED(ss), exec_state_t *NOTUSED(es), command_state_t *cs) { - uint8_t negative = 1; + int16_t negative = 1; int16_t a = cs_pop(cs); if (a < 0) { negative = -1; a = -a; } if (a > 1000) a = 1000; - cs_push(cs, negative * (table_v[a / 100] + table_vv[a % 100])); } diff --git a/src/ops/maths.h b/src/ops/maths.h index 5e51ef12..7009c85b 100644 --- a/src/ops/maths.h +++ b/src/ops/maths.h @@ -31,7 +31,6 @@ extern const tele_op_t op_EXP; extern const tele_op_t op_ABS; extern const tele_op_t op_AND; extern const tele_op_t op_OR; -extern const tele_op_t op_XOR; extern const tele_op_t op_JI; extern const tele_op_t op_SCALE; extern const tele_op_t op_N; @@ -39,6 +38,8 @@ extern const tele_op_t op_V; extern const tele_op_t op_VV; extern const tele_op_t op_ER; +extern const tele_op_t op_XOR; // XOR alias NE + extern const tele_op_t op_SYM_PLUS; // + alias ADD extern const tele_op_t op_SYM_DASH; // - alias SUB extern const tele_op_t op_SYM_STAR; // * alias MUL @@ -53,7 +54,7 @@ extern const tele_op_t op_SYM_RIGHT_ANGLED_EQUAL; // >= alias GT extern const tele_op_t op_SYM_EXCLAMATION; // ! alias NZ extern const tele_op_t op_SYM_LEFT_ANGLED_x2; // << alias LSH extern const tele_op_t op_SYM_RIGHT_ANGLED_x2; // >> alias RSH -extern const tele_op_t op_AMPERSAND_x2; // && alias AND -extern const tele_op_t op_PIPE_x2; // || alias OR +extern const tele_op_t op_SYM_AMPERSAND_x2; // && alias AND +extern const tele_op_t op_SYM_PIPE_x2; // || alias OR #endif diff --git a/src/ops/meadowphysics.c b/src/ops/meadowphysics.c index 2b771661..5401b2c6 100644 --- a/src/ops/meadowphysics.c +++ b/src/ops/meadowphysics.c @@ -4,9 +4,4 @@ const tele_op_t op_MP_PRESET = MAKE_SIMPLE_I2C_OP(MP.PRESET, MP_PRESET); const tele_op_t op_MP_RESET = MAKE_SIMPLE_I2C_OP(MP.RESET, MP_RESET); -const tele_op_t op_MP_SYNC = MAKE_SIMPLE_I2C_OP(MP.SYNC, MP_SYNC); -const tele_op_t op_MP_MUTE = MAKE_SIMPLE_I2C_OP(MP.MUTE, MP_MUTE); -const tele_op_t op_MP_UNMUTE = MAKE_SIMPLE_I2C_OP(MP.UNMUTE, MP_UNMUTE); -const tele_op_t op_MP_FREEZE = MAKE_SIMPLE_I2C_OP(MP.FREEZE, MP_FREEZE); -const tele_op_t op_MP_UNFREEZE = MAKE_SIMPLE_I2C_OP(MP.UNFREEZE, MP_UNFREEZE); const tele_op_t op_MP_STOP = MAKE_SIMPLE_I2C_OP(MP.STOP, MP_STOP); diff --git a/src/ops/meadowphysics.h b/src/ops/meadowphysics.h index 838183d1..d41cf2a1 100644 --- a/src/ops/meadowphysics.h +++ b/src/ops/meadowphysics.h @@ -5,11 +5,6 @@ extern const tele_op_t op_MP_PRESET; extern const tele_op_t op_MP_RESET; -extern const tele_op_t op_MP_SYNC; -extern const tele_op_t op_MP_MUTE; -extern const tele_op_t op_MP_UNMUTE; -extern const tele_op_t op_MP_FREEZE; -extern const tele_op_t op_MP_UNFREEZE; extern const tele_op_t op_MP_STOP; #endif diff --git a/src/ops/metronome.c b/src/ops/metronome.c index 9ad563b8..30d5ec5c 100644 --- a/src/ops/metronome.c +++ b/src/ops/metronome.c @@ -1,12 +1,17 @@ #include "ops/metronome.h" #include "helpers.h" +#include "teletype.h" #include "teletype_io.h" static void op_M_get(const void *data, scene_state_t *ss, exec_state_t *es, command_state_t *cs); static void op_M_set(const void *data, scene_state_t *ss, exec_state_t *es, command_state_t *cs); +static void op_M_SYM_EXCLAMATION_get(const void *data, scene_state_t *ss, + exec_state_t *es, command_state_t *cs); +static void op_M_SYM_EXCLAMATION_set(const void *data, scene_state_t *ss, + exec_state_t *es, command_state_t *cs); static void op_M_ACT_get(const void *data, scene_state_t *ss, exec_state_t *es, command_state_t *cs); static void op_M_ACT_set(const void *data, scene_state_t *ss, exec_state_t *es, @@ -24,7 +29,30 @@ static void op_M_get(const void *NOTUSED(data), scene_state_t *ss, static void op_M_set(const void *NOTUSED(data), scene_state_t *ss, exec_state_t *NOTUSED(es), command_state_t *cs) { int16_t m = cs_pop(cs); - if (m < 10) m = 10; + if (m < METRO_MIN_MS) m = METRO_MIN_MS; + ss->variables.m = m; + tele_metro_updated(); +} + +// clang-format off +// clang format has problems with the M! +const tele_op_t op_M_SYM_EXCLAMATION = MAKE_GET_SET_OP( + M!, op_M_SYM_EXCLAMATION_get, op_M_SYM_EXCLAMATION_set, 0, true); +// clang-format on + +static void op_M_SYM_EXCLAMATION_get(const void *NOTUSED(data), + scene_state_t *ss, + exec_state_t *NOTUSED(es), + command_state_t *cs) { + cs_push(cs, ss->variables.m); +} + +static void op_M_SYM_EXCLAMATION_set(const void *NOTUSED(data), + scene_state_t *ss, + exec_state_t *NOTUSED(es), + command_state_t *cs) { + int16_t m = cs_pop(cs); + if (m < METRO_MIN_UNSUPPORTED_MS) m = METRO_MIN_UNSUPPORTED_MS; ss->variables.m = m; tele_metro_updated(); } diff --git a/src/ops/metronome.h b/src/ops/metronome.h index 521df8af..9445cefb 100644 --- a/src/ops/metronome.h +++ b/src/ops/metronome.h @@ -4,6 +4,7 @@ #include "ops/op.h" extern const tele_op_t op_M; +extern const tele_op_t op_M_SYM_EXCLAMATION; extern const tele_op_t op_M_ACT; extern const tele_op_t op_M_RESET; diff --git a/src/ops/op.c b/src/ops/op.c index 71612620..f656ab3c 100644 --- a/src/ops/op.c +++ b/src/ops/op.c @@ -35,7 +35,7 @@ const tele_op_t *tele_ops[E_OP__LENGTH] = { &op_O_WRAP, &op_T, &op_TIME, &op_TIME_ACT, &op_X, &op_Y, &op_Z, // metronome - &op_M, &op_M_ACT, &op_M_RESET, + &op_M, &op_M_SYM_EXCLAMATION, &op_M_ACT, &op_M_RESET, // patterns &op_P_N, &op_P, &op_PN, &op_P_L, &op_PN_L, &op_P_WRAP, &op_PN_WRAP, @@ -55,13 +55,13 @@ const tele_op_t *tele_ops[E_OP__LENGTH] = { // maths &op_ADD, &op_SUB, &op_MUL, &op_DIV, &op_MOD, &op_RAND, &op_RRAND, &op_TOSS, &op_MIN, &op_MAX, &op_LIM, &op_WRAP, &op_QT, &op_AVG, &op_EQ, &op_NE, - &op_LT, &op_GT, &op_NZ, &op_EZ, &op_RSH, &op_LSH, &op_EXP, &op_ABS, &op_AND, - &op_OR, &op_XOR, &op_JI, &op_SCALE, &op_N, &op_V, &op_VV, &op_ER, - &op_SYM_PLUS, &op_SYM_DASH, &op_SYM_STAR, &op_SYM_FORWARD_SLASH, + &op_LT, &op_GT, &op_LTE, &op_GTE, &op_NZ, &op_EZ, &op_RSH, &op_LSH, &op_EXP, + &op_ABS, &op_AND, &op_OR, &op_JI, &op_SCALE, &op_N, &op_V, &op_VV, &op_ER, + &op_XOR, &op_SYM_PLUS, &op_SYM_DASH, &op_SYM_STAR, &op_SYM_FORWARD_SLASH, &op_SYM_PERCENTAGE, &op_SYM_EQUAL_x2, &op_SYM_EXCLAMATION_EQUAL, &op_SYM_LEFT_ANGLED, &op_SYM_RIGHT_ANGLED, &op_SYM_LEFT_ANGLED_EQUAL, &op_SYM_RIGHT_ANGLED_EQUAL, &op_SYM_EXCLAMATION, &op_SYM_LEFT_ANGLED_x2, - &op_SYM_RIGHT_ANGLED_x2, &op_AMPERSAND_x2, &op_PIPE_x2, + &op_SYM_RIGHT_ANGLED_x2, &op_SYM_AMPERSAND_x2, &op_SYM_PIPE_x2, // stack &op_S_ALL, &op_S_POP, &op_S_CLR, &op_S_L, @@ -78,8 +78,7 @@ const tele_op_t *tele_ops[E_OP__LENGTH] = { &op_WW_MUTE3, &op_WW_MUTE4, &op_WW_MUTEA, &op_WW_MUTEB, // meadowphysics - &op_MP_PRESET, &op_MP_RESET, &op_MP_SYNC, &op_MP_MUTE, &op_MP_UNMUTE, - &op_MP_FREEZE, &op_MP_UNFREEZE, &op_MP_STOP, + &op_MP_PRESET, &op_MP_RESET, &op_MP_STOP, // earthsea &op_ES_PRESET, &op_ES_MODE, &op_ES_CLOCK, &op_ES_RESET, &op_ES_PATTERN, @@ -91,14 +90,13 @@ const tele_op_t *tele_ops[E_OP__LENGTH] = { &op_OR_ROTS, &op_OR_ROTW, &op_OR_GRST, &op_OR_CVA, &op_OR_CVB, // ansible - &op_KR_PRESET, &op_KR_PATTERN, &op_KR_SCALE, &op_KR_PERIOD, &op_KR_POS, - &op_KR_LOOP_ST, &op_KR_LOOP_LEN, &op_KR_RESET, &op_MP_PRESET1, - &op_MP_RESET1, &op_MP_STOP1, &op_MP_SCALE, &op_MP_PERIOD, &op_LV_PRESET, - &op_LV_RESET, &op_LV_POS, &op_LV_L_ST, &op_LV_L_LEN, &op_LV_L_DIR, - &op_LV_CV, &op_CY_PRESET, &op_CY_RESET, &op_CY_POS, &op_CY_REV, &op_CY_CV, - &op_MID_SHIFT, &op_MID_SLEW, &op_ARP_STYLE, &op_ARP_HOLD, &op_ARP_RPT, - &op_ARP_GATE, &op_ARP_DIV, &op_ARP_RESET, &op_ARP_SHIFT, &op_ARP_SLEW, - &op_ARP_FILL, &op_ARP_ROT, &op_ARP_ER, + &op_KR_PRE, &op_KR_PAT, &op_KR_SCALE, &op_KR_PERIOD, &op_KR_POS, + &op_KR_L_ST, &op_KR_L_LEN, &op_KR_RES, &op_ME_PRE, &op_ME_RES, &op_ME_STOP, + &op_ME_SCALE, &op_ME_PERIOD, &op_LV_PRE, &op_LV_RES, &op_LV_POS, + &op_LV_L_ST, &op_LV_L_LEN, &op_LV_L_DIR, &op_LV_CV, &op_CY_PRE, &op_CY_RES, + &op_CY_POS, &op_CY_REV, &op_CY_CV, &op_MID_SHIFT, &op_MID_SLEW, &op_ARP_STY, + &op_ARP_HLD, &op_ARP_RPT, &op_ARP_GT, &op_ARP_DIV, &op_ARP_RES, + &op_ARP_SHIFT, &op_ARP_SLEW, &op_ARP_FIL, &op_ARP_ROT, &op_ARP_ER, // justfriends &op_JF_TR, &op_JF_RMODE, &op_JF_RUN, &op_JF_SHIFT, &op_JF_VTR, &op_JF_MODE, @@ -108,17 +106,21 @@ const tele_op_t *tele_ops[E_OP__LENGTH] = { &op_TO_TR, &op_TO_TR_TOG, &op_TO_TR_PULSE, &op_TO_TR_TIME, &op_TO_TR_TIME_S, &op_TO_TR_TIME_M, &op_TO_TR_POL, &op_TO_KILL, - &op_TO_TR_PULSE_DIV, &op_TO_TR_M, &op_TO_TR_M_S, &op_TO_TR_M_M, - &op_TO_TR_M_BPM, &op_TO_TR_M_ACT, &op_TO_TR_M_SYNC, &op_TO_TR_WIDTH, - &op_TO_TR_M_COUNT, + &op_TO_TR_PULSE_DIV, &op_TO_TR_PULSE_MUTE, &op_TO_TR_M_MUL, + + &op_TO_M, &op_TO_M_S, &op_TO_M_M, &op_TO_M_BPM, &op_TO_M_ACT, &op_TO_M_SYNC, + &op_TO_M_COUNT, + + &op_TO_TR_M, &op_TO_TR_M_S, &op_TO_TR_M_M, &op_TO_TR_M_BPM, &op_TO_TR_M_ACT, + &op_TO_TR_M_SYNC, &op_TO_TR_WIDTH, &op_TO_TR_M_COUNT, &op_TO_CV, &op_TO_CV_SLEW, &op_TO_CV_SLEW_S, &op_TO_CV_SLEW_M, &op_TO_CV_SET, &op_TO_CV_OFF, &op_TO_CV_QT, &op_TO_CV_QT_SET, &op_TO_CV_N, - &op_TO_CV_N_SET, &op_TO_CV_SCALE, + &op_TO_CV_N_SET, &op_TO_CV_SCALE, &op_TO_CV_LOG, &op_TO_CV_INIT, &op_TO_TR_INIT, &op_TO_INIT, - &op_TO_TR_P, &op_TO_TR_P_DIV, + &op_TO_TR_P, &op_TO_TR_P_DIV, &op_TO_TR_P_MUTE, &op_TO_OSC, &op_TO_OSC_SET, &op_TO_OSC_QT, &op_TO_OSC_QT_SET, &op_TO_OSC_FQ, &op_TO_OSC_FQ_SET, &op_TO_OSC_N, &op_TO_OSC_N_SET, &op_TO_OSC_LFO, @@ -126,10 +128,11 @@ const tele_op_t *tele_ops[E_OP__LENGTH] = { &op_TO_OSC_WIDTH, &op_TO_OSC_RECT, &op_TO_OSC_SLEW, &op_TO_OSC_SLEW_S, &op_TO_OSC_SLEW_M, &op_TO_OSC_SCALE, &op_TO_OSC_CYC, &op_TO_OSC_CYC_S, &op_TO_OSC_CYC_M, &op_TO_OSC_CYC_SET, &op_TO_OSC_CYC_S_SET, - &op_TO_OSC_CYC_M_SET, + &op_TO_OSC_CYC_M_SET, &op_TO_OSC_CTR, &op_TO_ENV_ACT, &op_TO_ENV_ATT, &op_TO_ENV_ATT_S, &op_TO_ENV_ATT_M, &op_TO_ENV_DEC, &op_TO_ENV_DEC_S, &op_TO_ENV_DEC_M, &op_TO_ENV_TRIG, + &op_TO_ENV_EOR, &op_TO_ENV_EOC, &op_TO_ENV_LOOP, &op_TI_PARAM, &op_TI_PARAM_QT, &op_TI_PARAM_N, &op_TI_PARAM_SCALE, &op_TI_PARAM_MAP, &op_TI_IN, &op_TI_IN_QT, &op_TI_IN_N, &op_TI_IN_SCALE, diff --git a/src/ops/op_enum.h b/src/ops/op_enum.h index df42d3a4..95bcc3fa 100644 --- a/src/ops/op_enum.h +++ b/src/ops/op_enum.h @@ -28,6 +28,7 @@ typedef enum { E_OP_Y, E_OP_Z, E_OP_M, + E_OP_M_SYM_EXCLAMATION, E_OP_M_ACT, E_OP_M_RESET, E_OP_P_N, @@ -93,6 +94,8 @@ typedef enum { E_OP_NE, E_OP_LT, E_OP_GT, + E_OP_LTE, + E_OP_GTE, E_OP_NZ, E_OP_EZ, E_OP_RSH, @@ -101,13 +104,13 @@ typedef enum { E_OP_ABS, E_OP_AND, E_OP_OR, - E_OP_XOR, E_OP_JI, E_OP_SCALE, E_OP_N, E_OP_V, E_OP_VV, E_OP_ER, + E_OP_XOR, E_OP_SYM_PLUS, E_OP_SYM_DASH, E_OP_SYM_STAR, @@ -122,8 +125,8 @@ typedef enum { E_OP_SYM_EXCLAMATION, E_OP_SYM_LEFT_ANGLED_x2, E_OP_SYM_RIGHT_ANGLED_x2, - E_OP_AMPERSAND_x2, - E_OP_PIPE_x2, + E_OP_SYM_AMPERSAND_x2, + E_OP_SYM_PIPE_x2, E_OP_S_ALL, E_OP_S_POP, E_OP_S_CLR, @@ -148,11 +151,6 @@ typedef enum { E_OP_WW_MUTEB, E_OP_MP_PRESET, E_OP_MP_RESET, - E_OP_MP_SYNC, - E_OP_MP_MUTE, - E_OP_MP_UNMUTE, - E_OP_MP_FREEZE, - E_OP_MP_UNFREEZE, E_OP_MP_STOP, E_OP_ES_PRESET, E_OP_ES_MODE, @@ -179,42 +177,42 @@ typedef enum { E_OP_OR_GRST, E_OP_OR_CVA, E_OP_OR_CVB, - E_OP_KR_PRESET, - E_OP_KR_PATTERN, + E_OP_KR_PRE, + E_OP_KR_PAT, E_OP_KR_SCALE, E_OP_KR_PERIOD, E_OP_KR_POS, - E_OP_KR_LOOP_ST, - E_OP_KR_LOOP_LEN, - E_OP_KR_RESET, - E_OP_MP_PRESET1, - E_OP_MP_RESET1, - E_OP_MP_STOP1, - E_OP_MP_SCALE, - E_OP_MP_PERIOD, - E_OP_LV_PRESET, - E_OP_LV_RESET, + E_OP_KR_L_ST, + E_OP_KR_L_LEN, + E_OP_KR_RES, + E_OP_ME_PRE, + E_OP_ME_RES, + E_OP_ME_STOP, + E_OP_ME_SCALE, + E_OP_ME_PERIOD, + E_OP_LV_PRE, + E_OP_LV_RES, E_OP_LV_POS, E_OP_LV_L_ST, E_OP_LV_L_LEN, E_OP_LV_L_DIR, E_OP_LV_CV, - E_OP_CY_PRESET, - E_OP_CY_RESET, + E_OP_CY_PRE, + E_OP_CY_RES, E_OP_CY_POS, E_OP_CY_REV, E_OP_CY_CV, E_OP_MID_SHIFT, E_OP_MID_SLEW, - E_OP_ARP_STYLE, - E_OP_ARP_HOLD, + E_OP_ARP_STY, + E_OP_ARP_HLD, E_OP_ARP_RPT, - E_OP_ARP_GATE, + E_OP_ARP_GT, E_OP_ARP_DIV, - E_OP_ARP_RESET, + E_OP_ARP_RES, E_OP_ARP_SHIFT, E_OP_ARP_SLEW, - E_OP_ARP_FILL, + E_OP_ARP_FIL, E_OP_ARP_ROT, E_OP_ARP_ER, E_OP_JF_TR, @@ -238,6 +236,15 @@ typedef enum { E_OP_TO_TR_POL, E_OP_TO_KILL, E_OP_TO_TR_PULSE_DIV, + E_OP_TO_TR_PULSE_MUTE, + E_OP_TO_TR_M_MUL, + E_OP_TO_M, + E_OP_TO_M_S, + E_OP_TO_M_M, + E_OP_TO_M_BPM, + E_OP_TO_M_ACT, + E_OP_TO_M_SYNC, + E_OP_TO_M_COUNT, E_OP_TO_TR_M, E_OP_TO_TR_M_S, E_OP_TO_TR_M_M, @@ -257,11 +264,13 @@ typedef enum { E_OP_TO_CV_N, E_OP_TO_CV_N_SET, E_OP_TO_CV_SCALE, + E_OP_TO_CV_LOG, E_OP_TO_CV_INIT, E_OP_TO_TR_INIT, E_OP_TO_INIT, E_OP_TO_TR_P, E_OP_TO_TR_P_DIV, + E_OP_TO_TR_P_MUTE, E_OP_TO_OSC, E_OP_TO_OSC_SET, E_OP_TO_OSC_QT, @@ -287,6 +296,7 @@ typedef enum { E_OP_TO_OSC_CYC_SET, E_OP_TO_OSC_CYC_S_SET, E_OP_TO_OSC_CYC_M_SET, + E_OP_TO_OSC_CTR, E_OP_TO_ENV_ACT, E_OP_TO_ENV_ATT, E_OP_TO_ENV_ATT_S, @@ -295,6 +305,9 @@ typedef enum { E_OP_TO_ENV_DEC_S, E_OP_TO_ENV_DEC_M, E_OP_TO_ENV_TRIG, + E_OP_TO_ENV_EOR, + E_OP_TO_ENV_EOC, + E_OP_TO_ENV_LOOP, E_OP_TI_PARAM, E_OP_TI_PARAM_QT, E_OP_TI_PARAM_N, diff --git a/src/ops/patterns.c b/src/ops/patterns.c index 14cc0098..08276878 100644 --- a/src/ops/patterns.c +++ b/src/ops/patterns.c @@ -295,10 +295,10 @@ static void p_i_set(scene_state_t *ss, int16_t pn, int16_t i) { pn = normalise_pn(pn); i = normalise_idx(ss, pn, i); int16_t len = ss_get_pattern_len(ss, pn); - if (i < 0) + if (i < 0 || len == 0) ss_set_pattern_idx(ss, pn, 0); - else if (i > len) - ss_set_pattern_idx(ss, pn, len); + else if (i >= len) + ss_set_pattern_idx(ss, pn, len - 1); else ss_set_pattern_idx(ss, pn, i); } diff --git a/src/ops/telex.c b/src/ops/telex.c index b8b1efa2..1447e014 100644 --- a/src/ops/telex.c +++ b/src/ops/telex.c @@ -26,6 +26,26 @@ static void op_TO_KILL_get(const void *data, scene_state_t *ss, static void op_TO_TR_PULSE_DIV_get(const void *data, scene_state_t *ss, exec_state_t *es, command_state_t *cs); +static void op_TO_TR_PULSE_MUTE_get(const void *data, scene_state_t *ss, + exec_state_t *es, command_state_t *cs); +static void op_TO_TR_M_MUL_get(const void *data, scene_state_t *ss, + exec_state_t *es, command_state_t *cs); + +static void op_TO_M_get(const void *data, scene_state_t *ss, exec_state_t *es, + command_state_t *cs); +static void op_TO_M_S_get(const void *data, scene_state_t *ss, exec_state_t *es, + command_state_t *cs); +static void op_TO_M_M_get(const void *data, scene_state_t *ss, exec_state_t *es, + command_state_t *cs); +static void op_TO_M_BPM_get(const void *data, scene_state_t *ss, + exec_state_t *es, command_state_t *cs); +static void op_TO_M_ACT_get(const void *data, scene_state_t *ss, + exec_state_t *es, command_state_t *cs); +static void op_TO_M_SYNC_get(const void *data, scene_state_t *ss, + exec_state_t *es, command_state_t *cs); +static void op_TO_M_COUNT_get(const void *data, scene_state_t *ss, + exec_state_t *es, command_state_t *cs); + static void op_TO_TR_M_get(const void *data, scene_state_t *ss, exec_state_t *es, command_state_t *cs); static void op_TO_TR_M_S_get(const void *data, scene_state_t *ss, @@ -65,6 +85,8 @@ static void op_TO_CV_N_SET_get(const void *data, scene_state_t *ss, exec_state_t *es, command_state_t *cs); static void op_TO_CV_SCALE_get(const void *data, scene_state_t *ss, exec_state_t *es, command_state_t *cs); +static void op_TO_CV_LOG_get(const void *data, scene_state_t *ss, + exec_state_t *es, command_state_t *cs); static void op_TO_OSC_get(const void *data, scene_state_t *ss, exec_state_t *es, command_state_t *cs); @@ -117,6 +139,8 @@ static void op_TO_OSC_CYC_S_SET_get(const void *data, scene_state_t *ss, exec_state_t *es, command_state_t *cs); static void op_TO_OSC_CYC_M_SET_get(const void *data, scene_state_t *ss, exec_state_t *es, command_state_t *cs); +static void op_TO_OSC_CTR_get(const void *data, scene_state_t *ss, + exec_state_t *es, command_state_t *cs); static void op_TO_ENV_ACT_get(const void *data, scene_state_t *ss, exec_state_t *es, command_state_t *cs); @@ -135,6 +159,13 @@ static void op_TO_ENV_DEC_M_get(const void *data, scene_state_t *ss, static void op_TO_ENV_TRIG_get(const void *data, scene_state_t *ss, exec_state_t *es, command_state_t *cs); +static void op_TO_ENV_EOR_get(const void *data, scene_state_t *ss, + exec_state_t *es, command_state_t *cs); +static void op_TO_ENV_EOC_get(const void *data, scene_state_t *ss, + exec_state_t *es, command_state_t *cs); +static void op_TO_ENV_LOOP_get(const void *data, scene_state_t *ss, + exec_state_t *es, command_state_t *cs); + static void op_TO_CV_INIT_get(const void *data, scene_state_t *ss, exec_state_t *es, command_state_t *cs); static void op_TO_TR_INIT_get(const void *data, scene_state_t *ss, @@ -194,6 +225,17 @@ const tele_op_t op_TO_TR_POL = MAKE_GET_OP(TO.TR.POL , op_TO_ const tele_op_t op_TO_KILL = MAKE_GET_OP(TO.KILL , op_TO_KILL_get , 1, false); const tele_op_t op_TO_TR_PULSE_DIV = MAKE_GET_OP(TO.TR.PULSE.DIV , op_TO_TR_PULSE_DIV_get , 2, false); +const tele_op_t op_TO_TR_PULSE_MUTE = MAKE_GET_OP(TO.TR.PULSE.MUTE , op_TO_TR_PULSE_MUTE_get , 2, false); +const tele_op_t op_TO_TR_M_MUL = MAKE_GET_OP(TO.TR.M.MUL , op_TO_TR_M_MUL_get , 2, false); + +const tele_op_t op_TO_M = MAKE_GET_OP(TO.M , op_TO_M_get , 2, false); +const tele_op_t op_TO_M_S = MAKE_GET_OP(TO.M.S , op_TO_M_S_get , 2, false); +const tele_op_t op_TO_M_M = MAKE_GET_OP(TO.M.M , op_TO_M_M_get , 2, false); +const tele_op_t op_TO_M_BPM = MAKE_GET_OP(TO.M.BPM , op_TO_M_BPM_get , 2, false); +const tele_op_t op_TO_M_ACT = MAKE_GET_OP(TO.M.ACT , op_TO_M_ACT_get , 2, false); +const tele_op_t op_TO_M_SYNC = MAKE_GET_OP(TO.M.SYNC , op_TO_M_SYNC_get , 1, false); +const tele_op_t op_TO_M_COUNT = MAKE_GET_OP(TO.M.COUNT , op_TO_M_COUNT_get , 2, false); + const tele_op_t op_TO_TR_M = MAKE_GET_OP(TO.TR.M , op_TO_TR_M_get , 2, false); const tele_op_t op_TO_TR_M_S = MAKE_GET_OP(TO.TR.M.S , op_TO_TR_M_S_get , 2, false); const tele_op_t op_TO_TR_M_M = MAKE_GET_OP(TO.TR.M.M , op_TO_TR_M_M_get , 2, false); @@ -214,6 +256,7 @@ const tele_op_t op_TO_CV_QT_SET = MAKE_GET_OP(TO.CV.QT.SET , op_TO_ const tele_op_t op_TO_CV_N = MAKE_GET_OP(TO.CV.N , op_TO_CV_N_get , 2, false); const tele_op_t op_TO_CV_N_SET = MAKE_GET_OP(TO.CV.N.SET , op_TO_CV_N_SET_get , 2, false); const tele_op_t op_TO_CV_SCALE = MAKE_GET_OP(TO.CV.SCALE , op_TO_CV_SCALE_get , 2, false); +const tele_op_t op_TO_CV_LOG = MAKE_GET_OP(TO.CV.LOG , op_TO_CV_LOG_get , 2, false); const tele_op_t op_TO_OSC = MAKE_GET_OP(TO.OSC , op_TO_OSC_get , 2, false); const tele_op_t op_TO_OSC_SET = MAKE_GET_OP(TO.OSC.SET , op_TO_OSC_SET_get , 2, false); @@ -241,6 +284,7 @@ const tele_op_t op_TO_OSC_CYC_M = MAKE_GET_OP(TO.OSC.CYC.M , op_TO_ const tele_op_t op_TO_OSC_CYC_SET = MAKE_GET_OP(TO.OSC.CYC.SET , op_TO_OSC_CYC_SET_get , 2, false); const tele_op_t op_TO_OSC_CYC_S_SET = MAKE_GET_OP(TO.OSC.CYC.S.SET , op_TO_OSC_CYC_S_SET_get , 2, false); const tele_op_t op_TO_OSC_CYC_M_SET = MAKE_GET_OP(TO.OSC.CYC.M.SET , op_TO_OSC_CYC_M_SET_get , 2, false); +const tele_op_t op_TO_OSC_CTR = MAKE_GET_OP(TO.OSC.CTR , op_TO_OSC_CTR_get , 2, false); const tele_op_t op_TO_ENV_ACT = MAKE_GET_OP(TO.ENV.ACT , op_TO_ENV_ACT_get , 2, false); const tele_op_t op_TO_ENV_ATT = MAKE_GET_OP(TO.ENV.ATT , op_TO_ENV_ATT_get , 2, false); @@ -251,6 +295,10 @@ const tele_op_t op_TO_ENV_DEC_S = MAKE_GET_OP(TO.ENV.DEC.S , op_TO_ const tele_op_t op_TO_ENV_DEC_M = MAKE_GET_OP(TO.ENV.DEC.M , op_TO_ENV_DEC_M_get , 2, false); const tele_op_t op_TO_ENV_TRIG = MAKE_GET_OP(TO.ENV.TRIG , op_TO_ENV_TRIG_get , 1, false); +const tele_op_t op_TO_ENV_EOR = MAKE_GET_OP(TO.ENV.EOR , op_TO_ENV_EOR_get , 2, false); +const tele_op_t op_TO_ENV_EOC = MAKE_GET_OP(TO.ENV.EOC , op_TO_ENV_EOC_get , 2, false); +const tele_op_t op_TO_ENV_LOOP = MAKE_GET_OP(TO.ENV.LOOP , op_TO_ENV_LOOP_get , 2, false); + const tele_op_t op_TO_CV_INIT = MAKE_GET_OP(TO.CV.INIT , op_TO_CV_INIT_get , 1, false); const tele_op_t op_TO_TR_INIT = MAKE_GET_OP(TO.TR.INIT , op_TO_TR_INIT_get , 1, false); const tele_op_t op_TO_INIT = MAKE_GET_OP(TO.INIT , op_TO_INIT_get , 1, false); @@ -258,6 +306,7 @@ const tele_op_t op_TO_INIT = MAKE_GET_OP(TO.INIT , op_TO_ // TXo Ailiases const tele_op_t op_TO_TR_P = MAKE_ALIAS_OP(TO.TR.P , op_TO_TR_PULSE_get , NULL, 1, false); const tele_op_t op_TO_TR_P_DIV = MAKE_ALIAS_OP(TO.TR.P.DIV , op_TO_TR_PULSE_DIV_get , NULL, 2, false); +const tele_op_t op_TO_TR_P_MUTE = MAKE_ALIAS_OP(TO.TR.P.MUTE , op_TO_TR_PULSE_MUTE_get , NULL, 2, false); // TXi Operators const tele_op_t op_TI_PARAM = MAKE_GET_OP(TI.PARAM , op_TI_PARAM_get , 1, true); @@ -320,6 +369,11 @@ void TXSet(uint8_t model, uint8_t command, command_state_t *cs) { int16_t value = cs_pop(cs); TXSend(model, command, output, value, true); } +void TXDeviceSet(uint8_t model, uint8_t command, command_state_t *cs) { + uint8_t output = DeviceToOutput(cs_pop(cs)); + int16_t value = cs_pop(cs); + TXSend(model, command, output, value, true); +} void TXReceive(uint8_t model, command_state_t *cs, uint8_t mode, bool shift) { // zero-index the output uint8_t input = cs_pop(cs) - 1; @@ -334,39 +388,17 @@ void TXReceive(uint8_t model, command_state_t *cs, uint8_t mode, bool shift) { uint8_t buffer[2]; buffer[0] = port; tele_ii_tx(address, buffer, 1); - // now read the vaule + // now read the value buffer[0] = 0; buffer[1] = 0; tele_ii_rx(address, buffer, 2); int16_t value = (buffer[0] << 8) + buffer[1]; cs_push(cs, value); } -// Temporary Init Functions (will refactor to the TELEX soon) -void TRInit(uint8_t output) { - TXSend(TO, TO_TR_POL, output, 1, true); - TXSend(TO, TO_TR, output, 0, true); - TXSend(TO, TO_TR_TIME, output, 100, true); - TXSend(TO, TO_TR_PULSE_DIV, output, 1, true); - TXSend(TO, TO_TR_M_ACT, output, 0, true); - TXSend(TO, TO_TR_M, output, 1000, true); -} -void CVInit(uint8_t output) { - TXSend(TO, TO_CV_SET, output, 0, true); - TXSend(TO, TO_CV_OFF, output, 0, true); - TXSend(TO, TO_CV_SLEW, output, 0, true); - TXSend(TO, TO_CV_SCALE, output, 0, true); - - TXSend(TO, TO_OSC_FQ_SET, output, 0, true); - TXSend(TO, TO_OSC_SCALE, output, 0, true); - TXSend(TO, TO_OSC_WAVE, output, 0, true); - TXSend(TO, TO_OSC_PHASE, output, 0, true); - TXSend(TO, TO_OSC_RECT, output, 0, true); - TXSend(TO, TO_OSC_SLEW, output, 0, true); - - TXSend(TO, TO_ENV_ACT, output, 0, true); - TXSend(TO, TO_ENV_ATT, output, 12, true); - TXSend(TO, TO_ENV_DEC, output, 250, true); +uint8_t DeviceToOutput(int16_t device) { + return ((device - 1) * 4) + 1; } +// Temporary Init Functions (will refactor to the TELEX soon) void INInit(uint8_t input) { TXSend(TI, TI_IN_SCALE, input, 0, true); TXSend(TI, TI_IN_TOP, input, 16383, true); @@ -419,6 +451,46 @@ static void op_TO_TR_PULSE_DIV_get(const void *NOTUSED(data), scene_state_t *ss, command_state_t *cs) { TXSet(TO, TO_TR_PULSE_DIV, cs); } +static void op_TO_TR_PULSE_MUTE_get(const void *NOTUSED(data), + scene_state_t *ss, + exec_state_t *NOTUSED(es), + command_state_t *cs) { + TXSet(TO, TO_TR_PULSE_MUTE, cs); +} +static void op_TO_TR_M_MUL_get(const void *NOTUSED(data), scene_state_t *ss, + exec_state_t *NOTUSED(es), command_state_t *cs) { + TXSet(TO, TO_TR_M_MUL, cs); +} +static void op_TO_M_get(const void *NOTUSED(data), scene_state_t *ss, + exec_state_t *NOTUSED(es), command_state_t *cs) { + TXDeviceSet(TO, TO_M, cs); +} +static void op_TO_M_S_get(const void *NOTUSED(data), scene_state_t *ss, + exec_state_t *NOTUSED(es), command_state_t *cs) { + TXDeviceSet(TO, TO_M_S, cs); +} +static void op_TO_M_M_get(const void *NOTUSED(data), scene_state_t *ss, + exec_state_t *NOTUSED(es), command_state_t *cs) { + TXDeviceSet(TO, TO_M_M, cs); +} +static void op_TO_M_BPM_get(const void *NOTUSED(data), scene_state_t *ss, + exec_state_t *NOTUSED(es), command_state_t *cs) { + TXDeviceSet(TO, TO_M_BPM, cs); +} +static void op_TO_M_ACT_get(const void *NOTUSED(data), scene_state_t *ss, + exec_state_t *NOTUSED(es), command_state_t *cs) { + TXDeviceSet(TO, TO_M_ACT, cs); +} + +static void op_TO_M_SYNC_get(const void *NOTUSED(data), scene_state_t *ss, + exec_state_t *NOTUSED(es), command_state_t *cs) { + TXCmd(TO, TO_M_SYNC, DeviceToOutput(cs_pop(cs))); +} + +static void op_TO_M_COUNT_get(const void *NOTUSED(data), scene_state_t *ss, + exec_state_t *NOTUSED(es), command_state_t *cs) { + TXDeviceSet(TO, TO_M_COUNT, cs); +} static void op_TO_TR_M_get(const void *NOTUSED(data), scene_state_t *ss, exec_state_t *NOTUSED(es), command_state_t *cs) { TXSet(TO, TO_TR_M, cs); @@ -500,6 +572,10 @@ static void op_TO_CV_SCALE_get(const void *NOTUSED(data), scene_state_t *ss, exec_state_t *NOTUSED(es), command_state_t *cs) { TXSet(TO, TO_CV_SCALE, cs); } +static void op_TO_CV_LOG_get(const void *NOTUSED(data), scene_state_t *ss, + exec_state_t *NOTUSED(es), command_state_t *cs) { + TXSet(TO, TO_CV_LOG, cs); +} static void op_TO_OSC_get(const void *NOTUSED(data), scene_state_t *ss, exec_state_t *NOTUSED(es), command_state_t *cs) { TXSet(TO, TO_OSC, cs); @@ -616,6 +692,10 @@ static void op_TO_OSC_CYC_M_SET_get(const void *NOTUSED(data), command_state_t *cs) { TXSet(TO, TO_OSC_CYC_M_SET, cs); } +static void op_TO_OSC_CTR_get(const void *NOTUSED(data), scene_state_t *ss, + exec_state_t *NOTUSED(es), command_state_t *cs) { + TXSet(TO, TO_OSC_CTR, cs); +} static void op_TO_ENV_ACT_get(const void *NOTUSED(data), scene_state_t *ss, exec_state_t *NOTUSED(es), command_state_t *cs) { TXSet(TO, TO_ENV_ACT, cs); @@ -652,23 +732,29 @@ static void op_TO_ENV_TRIG_get(const void *NOTUSED(data), scene_state_t *ss, exec_state_t *NOTUSED(es), command_state_t *cs) { TXCmd(TO, TO_ENV_TRIG, cs_pop(cs)); } +static void op_TO_ENV_EOR_get(const void *NOTUSED(data), scene_state_t *ss, + exec_state_t *NOTUSED(es), command_state_t *cs) { + TXSet(TO, TO_ENV_EOR, cs); +} +static void op_TO_ENV_EOC_get(const void *NOTUSED(data), scene_state_t *ss, + exec_state_t *NOTUSED(es), command_state_t *cs) { + TXSet(TO, TO_ENV_EOC, cs); +} +static void op_TO_ENV_LOOP_get(const void *NOTUSED(data), scene_state_t *ss, + exec_state_t *NOTUSED(es), command_state_t *cs) { + TXSet(TO, TO_ENV_LOOP, cs); +} static void op_TO_CV_INIT_get(const void *NOTUSED(data), scene_state_t *ss, exec_state_t *NOTUSED(es), command_state_t *cs) { - CVInit(cs_pop(cs)); + TXCmd(TO, TO_CV_INIT, cs_pop(cs)); } static void op_TO_TR_INIT_get(const void *NOTUSED(data), scene_state_t *ss, exec_state_t *NOTUSED(es), command_state_t *cs) { - TRInit(cs_pop(cs)); + TXCmd(TO, TO_TR_INIT, cs_pop(cs)); } static void op_TO_INIT_get(const void *NOTUSED(data), scene_state_t *ss, exec_state_t *NOTUSED(es), command_state_t *cs) { - uint8_t end = cs_pop(cs) * 4; - uint8_t start = end - 3; - uint8_t i; - for (i = start; i <= end; i++) { - CVInit(i); - TRInit(i); - } + TXCmd(TO, TO_INIT, DeviceToOutput(cs_pop(cs))); } // TXi @@ -733,11 +819,11 @@ static void op_TI_IN_CALIB_get(const void *NOTUSED(data), scene_state_t *ss, } static void op_TI_STORE_get(const void *NOTUSED(data), scene_state_t *ss, exec_state_t *NOTUSED(es), command_state_t *cs) { - TXCmd(TI, TI_STORE, cs_pop(cs)); + TXCmd(TI, TI_STORE, DeviceToOutput(cs_pop(cs))); } static void op_TI_RESET_get(const void *NOTUSED(data), scene_state_t *ss, exec_state_t *NOTUSED(es), command_state_t *cs) { - TXCmd(TI, TI_RESET, cs_pop(cs)); + TXCmd(TI, TI_RESET, DeviceToOutput(cs_pop(cs))); } static void op_TI_PARAM_INIT_get(const void *NOTUSED(data), scene_state_t *ss, exec_state_t *NOTUSED(es), diff --git a/src/ops/telex.h b/src/ops/telex.h index 5b9c803c..85664963 100644 --- a/src/ops/telex.h +++ b/src/ops/telex.h @@ -14,6 +14,17 @@ extern const tele_op_t op_TO_TR_TIME_M; extern const tele_op_t op_TO_TR_POL; extern const tele_op_t op_TO_TR_PULSE_DIV; +extern const tele_op_t op_TO_TR_PULSE_MUTE; +extern const tele_op_t op_TO_TR_M_MUL; + +extern const tele_op_t op_TO_M; +extern const tele_op_t op_TO_M_S; +extern const tele_op_t op_TO_M_M; +extern const tele_op_t op_TO_M_BPM; +extern const tele_op_t op_TO_M_ACT; +extern const tele_op_t op_TO_M_SYNC; +extern const tele_op_t op_TO_M_COUNT; + extern const tele_op_t op_TO_TR_M; extern const tele_op_t op_TO_TR_M_S; extern const tele_op_t op_TO_TR_M_M; @@ -36,6 +47,7 @@ extern const tele_op_t op_TO_CV_QT_SET; extern const tele_op_t op_TO_CV_N; extern const tele_op_t op_TO_CV_N_SET; extern const tele_op_t op_TO_CV_SCALE; +extern const tele_op_t op_TO_CV_LOG; extern const tele_op_t op_TO_OSC; extern const tele_op_t op_TO_OSC_SET; @@ -63,6 +75,7 @@ extern const tele_op_t op_TO_OSC_CYC_M; extern const tele_op_t op_TO_OSC_CYC_SET; extern const tele_op_t op_TO_OSC_CYC_S_SET; extern const tele_op_t op_TO_OSC_CYC_M_SET; +extern const tele_op_t op_TO_OSC_CTR; extern const tele_op_t op_TO_ENV_ACT; extern const tele_op_t op_TO_ENV_ATT; @@ -73,12 +86,18 @@ extern const tele_op_t op_TO_ENV_DEC_S; extern const tele_op_t op_TO_ENV_DEC_M; extern const tele_op_t op_TO_ENV_TRIG; +extern const tele_op_t op_TO_ENV_EOR; +extern const tele_op_t op_TO_ENV_EOC; +extern const tele_op_t op_TO_ENV_LOOP; + extern const tele_op_t op_TO_CV_INIT; extern const tele_op_t op_TO_TR_INIT; extern const tele_op_t op_TO_INIT; extern const tele_op_t op_TO_TR_P; extern const tele_op_t op_TO_TR_P_DIV; +extern const tele_op_t op_TO_TR_P_MUTE; +extern const tele_op_t op_TO_TR_P_MUL; // TXi Operators @@ -115,10 +134,10 @@ void TXSend(uint8_t model, uint8_t command, uint8_t output, int16_t value, bool set); void TXCmd(uint8_t model, uint8_t command, uint8_t output); void TXSet(uint8_t model, uint8_t command, command_state_t *cs); +void TXDeviceSet(uint8_t model, uint8_t command, command_state_t *cs); void TXReceive(uint8_t model, command_state_t *cs, uint8_t mode, bool shift); +uint8_t DeviceToOutput(int16_t device); // temporary init functions -void TRInit(uint8_t output); -void CVInit(uint8_t output); void INInit(uint8_t input); void PRMInit(uint8_t input); @@ -163,14 +182,29 @@ void PRMInit(uint8_t input); #define TO_CV_SLEW_M 0x14 #define TO_CV_OFF 0x15 +#define TO_TR_PULSE_MUTE 0x16 +#define TO_TR_M_MUL 0x17 + +#define TO_M 0x18 +#define TO_M_S 0x19 +#define TO_M_M 0x1A +#define TO_M_BPM 0x1B +#define TO_M_ACT 0x1C +#define TO_M_SYNC 0x1D +#define TO_M_COUNT 0x1E + #define TO_KILL 0x20 #define TO_RESET 0x21 +#define TO_TR_INIT 0x22 +#define TO_CV_INIT 0x23 +#define TO_INIT 0x24 #define TO_CV_QT 0x30 #define TO_CV_QT_SET 0x31 #define TO_CV_N 0x32 #define TO_CV_N_SET 0x33 #define TO_CV_SCALE 0x34 +#define TO_CV_LOG 0x35 #define TO_OSC 0x40 #define TO_OSC_SET 0x41 @@ -199,6 +233,8 @@ void PRMInit(uint8_t input); #define TO_OSC_CYC_S_SET 0x58 #define TO_OSC_CYC_M_SET 0x59 +#define TO_OSC_CTR 0x5A + #define TO_ENV_ACT 0x60 #define TO_ENV_ATT 0x61 #define TO_ENV_ATT_S 0x62 @@ -210,6 +246,10 @@ void PRMInit(uint8_t input); #define TO_ENV_CYC 0x68 #define TO_ENV_BPOL 0x69 +#define TO_ENV_EOR 0x6A +#define TO_ENV_EOC 0x6B +#define TO_ENV_LOOP 0x6C + // TELEXi #define TI 0x68 diff --git a/src/state.h b/src/state.h index ebd0518a..6f25a877 100644 --- a/src/state.h +++ b/src/state.h @@ -22,6 +22,9 @@ #define METRO_SCRIPT 8 #define INIT_SCRIPT 9 +#define METRO_MIN_MS 25 +#define METRO_MIN_UNSUPPORTED_MS 2 + //////////////////////////////////////////////////////////////////////////////// // SCENE STATE ///////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// diff --git a/src/teletype.h b/src/teletype.h index 66569301..76f7c169 100644 --- a/src/teletype.h +++ b/src/teletype.h @@ -8,7 +8,7 @@ #include "command.h" #include "state.h" -#define TELETYPE_VERSION "TELETYPE 2.0b9" +#define TELETYPE_VERSION "TELETYPE 2.0.0" #define TELE_ERROR_MSG_LENGTH 16 typedef enum { diff --git a/tests/parser_tests.c b/tests/parser_tests.c index 6c25b6f0..bd20969b 100644 --- a/tests/parser_tests.c +++ b/tests/parser_tests.c @@ -59,11 +59,8 @@ char corpus[CORPUS_COUNT][32] = { "CV 1 ADD N P.HERE Z", "ES.RESET 1", "ES.STOP 1", "ES.TRANS X", - "MP.FREEZE 1", "MP.PRESET X", "MP.RESET 1", - "MP.SYNC 1", - "MP.UNFREEZE 1", "WW.MUTE1 0", "WW.MUTE1 1", "WW.MUTE2 0", @@ -80,8 +77,6 @@ char corpus[CORPUS_COUNT][32] = { "CV 1 ADD N P.HERE Z", "L 1 4: CV.SLEW 50", "L 1 4: CV.SLEW I 12", "L 1 4: TR I 0", - "L 1 8: MP.MUTE I", - "L 1 8: MP.UNMUTE I", "L A B: TR.TIME I 25", "L A B: TR.TIME I 40", "L A D: TR.PULSE I", diff --git a/utils/common/__init__.py b/utils/common/__init__.py new file mode 100644 index 00000000..66c0c30e --- /dev/null +++ b/utils/common/__init__.py @@ -0,0 +1,73 @@ +from os import path +import re + +_THIS_FILE = path.realpath(__file__) +_THIS_DIR = path.dirname(_THIS_FILE) + +OP_C = path.abspath(path.join(_THIS_DIR, "../../src/ops/op.c")) + + +def list_tele_ops(): + """Return the names of all the structs defined in tele_ops""" + with open(OP_C, "r") as f: + op_c = _remove_comments(f.read()) + ops = re.findall("&op_[a-zA-Z0-9_]+", op_c) + ops = [s[1:] for s in ops] + return ops + + +def list_ops(): + return map(_convert_struct_name_to_op_name, list_tele_ops()) + + +def list_tele_mods(): + """Return the names of all the structs defined in tele_mods""" + with open(OP_C, "r") as f: + op_c = _remove_comments(f.read()) + mods = re.findall("&mod_[a-zA-Z0-9_]+", op_c) + mods = [s[1:] for s in mods] + return mods + + +def list_mods(): + return map(_convert_struct_name_to_op_name, list_tele_mods()) + + +def _remove_comments(op_c): + out = op_c.splitlines() + out = filter(_is_not_comment, out) + return "\n".join(out) + + +def _is_not_comment(line): + s = line.lstrip() + return not (s.startswith("//") or s.startswith("/*")) + + +def _convert_struct_name_to_op_name(name): + stripped = name.replace("op_", "").replace("mod_", "") + + MAPPINGS = { + "SYM_PLUS": "+", + "SYM_DASH": "-", + "SYM_STAR": "*", + "SYM_FORWARD_SLASH": "/", + "SYM_PERCENTAGE": "%", + "SYM_EQUAL_x2": "==", + "SYM_EXCLAMATION_EQUAL": "!=", + "SYM_LEFT_ANGLED": "<", + "SYM_RIGHT_ANGLED": ">", + "SYM_LEFT_ANGLED_EQUAL": "<=", + "SYM_RIGHT_ANGLED_EQUAL": ">=", + "SYM_EXCLAMATION": "!", + "SYM_LEFT_ANGLED_x2": "<<", + "SYM_RIGHT_ANGLED_x2": ">>", + "SYM_AMPERSAND_x2": "&&", + "SYM_PIPE_x2": "||", + "M_SYM_EXCLAMATION": "M!" + } + + if stripped in MAPPINGS: + return MAPPINGS[stripped] + else: + return stripped.replace("_", ".") diff --git a/utils/docs.py b/utils/docs.py new file mode 100755 index 00000000..d4e1863e --- /dev/null +++ b/utils/docs.py @@ -0,0 +1,192 @@ +#!/usr/bin/env python3 + +import sys +from pathlib import Path + +import jinja2 +import pypandoc +import pytoml as toml + +from common import list_ops, list_mods + +if (sys.version_info.major, sys.version_info.minor) < (3, 6): + raise Exception("need Python 3.6 or later") + +THIS_FILE = Path(__file__).resolve() +ROOT_DIR = THIS_FILE.parent.parent +TEMPLATE_DIR = ROOT_DIR / "utils" / "templates" +DOCS_DIR = ROOT_DIR / "docs" +OP_DOCS_DIR = DOCS_DIR / "ops" +FONTS_DIR = ROOT_DIR / "utils" / "fonts" + +env = jinja2.Environment( + autoescape=False, + loader=jinja2.FileSystemLoader(str(TEMPLATE_DIR)), + trim_blocks=True, + lstrip_blocks=True +) + +# determines the order in which sections are displayed +OPS_SECTIONS = [ + "variables", + "hardware", + "patterns", + "controlflow", + "maths", + "metronome", + "delay", + "stack", + "queue", + "ansible", + "whitewhale", + "meadowphysics", + "earthsea", + "orca", + "justfriends", + "telex_i", + "telex_o" +] + + +def deep_merge_dict(source, destination): + for key, value in source.items(): + if isinstance(value, dict): + node = destination.setdefault(key, {}) + deep_merge_dict(value, node) + else: + destination[key] = value + + return destination + + +def validate_toml(ops): + for (name, d) in ops.items(): + keys = set(d) + if "prototype" not in keys: + print(f" - WARNING: {name} - no prototype entry") + + if "short" not in keys: + print(f" - WARNING: {name} - no short entry") + + if "aliases" in keys and not isinstance(d["aliases"], list): + print(f" - WARNING: {name} - aliases is not an array") + + for k in keys - {"prototype", "prototype_set", "aliases", + "short", "description"}: + print(f" - WARNING: {name} - unknown entry - {k}") + + +def common_md(): + print(f"Using docs directory: {DOCS_DIR}") + print(f"Using ops docs directory: {OP_DOCS_DIR}") + print() + + op_table_template = env.get_template("op_table.jinga2.md") + op_extended_template = env.get_template("op_extended.jinga2.md") + + output = "" + output += Path(DOCS_DIR / "whats_new.md").read_text() + "\n\n" + output += Path(DOCS_DIR / "modes.md").read_text() + "\n\n" + output += Path(DOCS_DIR / "ops.md").read_text() + "\n\n" + + all_ops = set(list_ops()) | set(list_mods()) + all_ops_dict = {} + + ops_with_docs = set() + + for section in OPS_SECTIONS: + md_file = Path(OP_DOCS_DIR, section + ".md") + toml_file = Path(OP_DOCS_DIR, section + ".toml") + + output += "\\newpage\n" + + if md_file.exists() and md_file.is_file(): + print(f"Reading {md_file}") + output += md_file.read_text() + "\n\n" + output += "\n" + + if toml_file.exists() and toml_file.is_file(): + print(f"Reading {toml_file}") + extended = [] + # n.b. Python 3.6 dicts maintain insertion order + ops = toml.loads(toml_file.read_text()) + validate_toml(ops) + deep_merge_dict(ops, all_ops_dict) + for key in ops: + if key not in all_ops: + print(f" - WARNING: unknown {key}") + ops_with_docs.add(key) + if "aliases" in ops[key]: + ops_with_docs |= set(ops[key]["aliases"]) + if "description" in ops[key]: + render = op_extended_template.render(name=key, **ops[key]) + extended.append((key, render)) + + output += op_table_template.render(ops=ops.values()) + output += "\n" + output += "\n".join([e[1] for e in extended]) + "\n\n" + + output += Path(DOCS_DIR / "advanced.md").read_text() + "\n\n" + + output += "\\appendix\n\n" + + output += "# Alphabetical list of OPs and MODs\n\n" + sorted_ops = [kv[1] for kv in sorted(all_ops_dict.items())] + output += op_table_template.render(ops=sorted_ops) + + output += "# Missing documentation\n\n" + missing_ops = all_ops - ops_with_docs + output += ", ".join([f"`{o}`" for o in sorted(missing_ops)]) + "\n\n" + + output += Path(ROOT_DIR / "CHANGELOG.md").read_text() + "\n\n" + + return output + + +def main(): + if len(sys.argv) <= 1: + sys.exit("Please supply a filename") + + input_format = "markdown" + output = common_md() + + print() + + for arg in sys.argv[1:]: + p = Path(arg).resolve() + print(f"Generating: {p}") + + ext = p.suffix + + if ext == ".md": + p.write_text(output) + elif ext == ".html": + pypandoc.convert_text( + output, + format=input_format, + to="html5", + outputfile=str(p), + extra_args=["--standalone", + "--self-contained", + "--toc", + "--toc-depth=2", + "--css=" + str(TEMPLATE_DIR / "docs.css")]) + elif ext == ".pdf" or ext == ".tex": + latex_preamble = env.get_template("latex_preamble.jinga2.md") + latex = latex_preamble.render(fonts_dir=FONTS_DIR) + latex += output + pypandoc.convert_text( + latex, + format=input_format, + to=ext[1:], + outputfile=str(p), + extra_args=["--standalone", + "--column=80", + "--toc", + "--toc-depth=2", + "--latex-engine=xelatex", + "--variable=papersize:A4"]) + + +if __name__ == "__main__": + main() diff --git a/utils/fonts/roboto-hinted/LICENSE b/utils/fonts/roboto-hinted/LICENSE new file mode 100644 index 00000000..261eeb9e --- /dev/null +++ b/utils/fonts/roboto-hinted/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/utils/fonts/roboto-hinted/Roboto-Bold.ttf b/utils/fonts/roboto-hinted/Roboto-Bold.ttf new file mode 100644 index 00000000..5fd9dd9e Binary files /dev/null and b/utils/fonts/roboto-hinted/Roboto-Bold.ttf differ diff --git a/utils/fonts/roboto-hinted/Roboto-BoldItalic.ttf b/utils/fonts/roboto-hinted/Roboto-BoldItalic.ttf new file mode 100644 index 00000000..e9918414 Binary files /dev/null and b/utils/fonts/roboto-hinted/Roboto-BoldItalic.ttf differ diff --git a/utils/fonts/roboto-hinted/Roboto-Italic.ttf b/utils/fonts/roboto-hinted/Roboto-Italic.ttf new file mode 100644 index 00000000..318b6dca Binary files /dev/null and b/utils/fonts/roboto-hinted/Roboto-Italic.ttf differ diff --git a/utils/fonts/roboto-hinted/Roboto-Regular.ttf b/utils/fonts/roboto-hinted/Roboto-Regular.ttf new file mode 100644 index 00000000..c1c3700f Binary files /dev/null and b/utils/fonts/roboto-hinted/Roboto-Regular.ttf differ diff --git a/utils/fonts/roboto-mono/LICENSE.txt b/utils/fonts/roboto-mono/LICENSE.txt new file mode 100755 index 00000000..d6456956 --- /dev/null +++ b/utils/fonts/roboto-mono/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/utils/fonts/roboto-mono/RobotoMono-Bold.ttf b/utils/fonts/roboto-mono/RobotoMono-Bold.ttf new file mode 100755 index 00000000..07ef607d Binary files /dev/null and b/utils/fonts/roboto-mono/RobotoMono-Bold.ttf differ diff --git a/utils/fonts/roboto-mono/RobotoMono-BoldItalic.ttf b/utils/fonts/roboto-mono/RobotoMono-BoldItalic.ttf new file mode 100755 index 00000000..1cca0bf4 Binary files /dev/null and b/utils/fonts/roboto-mono/RobotoMono-BoldItalic.ttf differ diff --git a/utils/fonts/roboto-mono/RobotoMono-Italic.ttf b/utils/fonts/roboto-mono/RobotoMono-Italic.ttf new file mode 100755 index 00000000..ef92c372 Binary files /dev/null and b/utils/fonts/roboto-mono/RobotoMono-Italic.ttf differ diff --git a/utils/fonts/roboto-mono/RobotoMono-Regular.ttf b/utils/fonts/roboto-mono/RobotoMono-Regular.ttf new file mode 100755 index 00000000..b158a334 Binary files /dev/null and b/utils/fonts/roboto-mono/RobotoMono-Regular.ttf differ diff --git a/utils/op_enums.py b/utils/op_enums.py index 35aded5b..d21350f1 100755 --- a/utils/op_enums.py +++ b/utils/op_enums.py @@ -1,11 +1,15 @@ #!/usr/bin/env python3 +import sys from os import path -import re + +from common import list_tele_ops, list_tele_mods, OP_C + +if (sys.version_info.major, sys.version_info.minor) < (3, 6): + raise Exception("need Python 3.6 or later") THIS_FILE = path.realpath(__file__) THIS_DIR = path.dirname(THIS_FILE) -OP_C = path.abspath(path.join(THIS_DIR, "../src/ops/op.c")) OP_ENUM_H = path.abspath(path.join(THIS_DIR, "../src/ops/op_enum.h")) HEADER_PRE = """// clang-format off @@ -19,27 +23,12 @@ HEADER_POST = "#endif\n" -def is_not_comment(line): - s = line.lstrip() - return not (s.startswith("//") or s.startswith("/*")) - - -def remove_comments(op_c): - out = op_c.splitlines() - out = filter(is_not_comment, out) - return "\n".join(out) - - -def find_ops(op_c): - raw = re.findall("&op_[a-zA-Z0-9_]+", op_c) - stripped = [s[4:] for s in raw] - return stripped +def make_ops(): + return [s[3:] for s in list_tele_ops()] -def find_mods(op_c): - raw = re.findall("&mod_[a-zA-Z0-9_]+", op_c) - stripped = [s[5:] for s in raw] - return stripped +def make_mods(): + return [s[4:] for s in list_tele_mods()] def make_enum(name, prefix, entries): @@ -56,15 +45,13 @@ def make_enum(name, prefix, entries): def main(): print("reading: {}".format(OP_C)) print("generating: {}".format(OP_ENUM_H)) - with open(OP_C, "r") as f: - op_c = remove_comments(f.read()) - ops = find_ops(op_c) - mods = find_mods(op_c) - op_enum = make_enum("tele_op_idx_t", "E_OP_", ops) - mod_enum = make_enum("tele_mod_idx_t", "E_MOD_", mods) - header = HEADER_PRE + op_enum + mod_enum + HEADER_POST - with open(OP_ENUM_H, "w") as g: - g.write(header) + ops = make_ops() + mods = make_mods() + op_enum = make_enum("tele_op_idx_t", "E_OP_", ops) + mod_enum = make_enum("tele_mod_idx_t", "E_MOD_", mods) + header = HEADER_PRE + op_enum + mod_enum + HEADER_POST + with open(OP_ENUM_H, "w") as g: + g.write(header) if __name__ == '__main__': diff --git a/utils/requirements.pip b/utils/requirements.pip new file mode 100644 index 00000000..2d6cdd14 --- /dev/null +++ b/utils/requirements.pip @@ -0,0 +1,3 @@ +Jinja2>=2.9.6 +pypandoc>=1.4 +pytoml>=0.1.12 diff --git a/utils/templates/docs.css b/utils/templates/docs.css new file mode 100644 index 00000000..c010d993 --- /dev/null +++ b/utils/templates/docs.css @@ -0,0 +1,355 @@ +body { + font-family: Helvetica, arial, sans-serif; + font-size: 14px; + line-height: 1.6; + padding-top: 10px; + padding-bottom: 10px; + background-color: white; + padding: 30px; +} +body > *:first-child { + margin-top: 0 !important; +} +body > *:last-child { + margin-bottom: 0 !important; +} +a { + color: #4183C4; +} +a.absent { + color: #cc0000; +} +a.anchor { + display: block; + padding-left: 30px; + margin-left: -30px; + cursor: pointer; + position: absolute; + top: 0; + left: 0; + bottom: 0; +} +h1, +h2, +h3, +h4, +h5, +h6 { + margin: 20px 0 10px; + padding: 0; + font-weight: bold; + -webkit-font-smoothing: antialiased; + cursor: text; + position: relative; +} +h1:hover a.anchor, +h2:hover a.anchor, +h3:hover a.anchor, +h4:hover a.anchor, +h5:hover a.anchor, +h6:hover a.anchor { + text-decoration: none; +} +h1 tt, +h1 code { + font-size: inherit; +} +h2 tt, +h2 code { + font-size: inherit; +} +h3 tt, +h3 code { + font-size: inherit; +} +h4 tt, +h4 code { + font-size: inherit; +} +h5 tt, +h5 code { + font-size: inherit; +} +h6 tt, +h6 code { + font-size: inherit; +} +h1 { + font-size: 28px; + color: black; +} +h2 { + font-size: 24px; + border-bottom: 1px solid #cccccc; + color: black; +} +h3 { + font-size: 18px; +} +h4 { + font-size: 16px; +} +h5 { + font-size: 14px; +} +h6 { + color: #777777; + font-size: 14px; +} +p, +blockquote, +ul, +ol, +dl, +li, +table, +pre { + margin: 15px 0; +} +hr { + border: 0 none; + color: #cccccc; + height: 4px; + padding: 0; +} +body > h2:first-child { + margin-top: 0; + padding-top: 0; +} +body > h1:first-child { + margin-top: 0; + padding-top: 0; +} +body > h1:first-child + h2 { + margin-top: 0; + padding-top: 0; +} +body > h3:first-child, +body > h4:first-child, +body > h5:first-child, +body > h6:first-child { + margin-top: 0; + padding-top: 0; +} +a:first-child h1, +a:first-child h2, +a:first-child h3, +a:first-child h4, +a:first-child h5, +a:first-child h6 { + margin-top: 0; + padding-top: 0; +} +h1 p, +h2 p, +h3 p, +h4 p, +h5 p, +h6 p { + margin-top: 0; +} +li p.first { + display: inline-block; +} +ul, +ol { + padding-left: 30px; +} +ul:first-child, +ol:first-child { + margin-top: 0; +} +ul:last-child, +ol:last-child { + margin-bottom: 0; +} +dl { + padding: 0; +} +dl dt { + font-size: 14px; + font-weight: bold; + font-style: italic; + padding: 0; + margin: 15px 0 5px; +} +dl dt:first-child { + padding: 0; +} +dl dt >:first-child { + margin-top: 0; +} +dl dt >:last-child { + margin-bottom: 0; +} +dl dd { + margin: 0 0 15px; + padding: 0 15px; +} +dl dd >:first-child { + margin-top: 0; +} +dl dd >:last-child { + margin-bottom: 0; +} +blockquote { + border-left: 4px solid #dddddd; + padding: 0 15px; + color: #777777; +} +blockquote >:first-child { + margin-top: 0; +} +blockquote >:last-child { + margin-bottom: 0; +} +table { + padding: 0; +} +table tr { + border-top: 1px solid #cccccc; + background-color: white; + margin: 0; + padding: 0; +} +table tr:nth-child(2n) { + background-color: #f8f8f8; +} +table tr th { + font-weight: bold; + border: 1px solid #cccccc; + text-align: left; + margin: 0; + padding: 6px 13px; +} +table tr td { + border: 1px solid #cccccc; + text-align: left; + margin: 0; + padding: 6px 13px; +} +table tr th:first-child, +table tr td:first-child { + margin-top: 0; +} +table tr th:last-child, +table tr td:last-child { + margin-bottom: 0; +} +img { + max-width: 100%; +} +span.frame { + display: block; + overflow: hidden; +} +span.frame > span { + border: 1px solid #dddddd; + display: block; + float: left; + overflow: hidden; + margin: 13px 0 0; + padding: 7px; + width: auto; +} +span.frame span img { + display: block; + float: left; +} +span.frame span span { + clear: both; + color: #333333; + display: block; + padding: 5px 0 0; +} +span.align-center { + display: block; + overflow: hidden; + clear: both; +} +span.align-center > span { + display: block; + overflow: hidden; + margin: 13px auto 0; + text-align: center; +} +span.align-center span img { + margin: 0 auto; + text-align: center; +} +span.align-right { + display: block; + overflow: hidden; + clear: both; +} +span.align-right > span { + display: block; + overflow: hidden; + margin: 13px 0 0; + text-align: right; +} +span.align-right span img { + margin: 0; + text-align: right; +} +span.float-left { + display: block; + margin-right: 13px; + overflow: hidden; + float: left; +} +span.float-left span { + margin: 13px 0 0; +} +span.float-right { + display: block; + margin-left: 13px; + overflow: hidden; + float: right; +} +span.float-right > span { + display: block; + overflow: hidden; + margin: 13px auto 0; + text-align: right; +} +code, +tt { + font-family: Menlo, Consolas, monospace; + margin: 0 2px; + padding: 0 5px; + white-space: nowrap; + border: 1px solid #eaeaea; + background-color: #f8f8f8; + border-radius: 3px; +} +pre code { + margin: 0; + padding: 0; + white-space: pre; + border: none; + background: transparent; +} +.highlight pre { + background-color: #f8f8f8; + border: 1px solid #cccccc; + font-size: 13px; + line-height: 19px; + overflow: auto; + padding: 6px 10px; + border-radius: 3px; +} +pre { + background-color: #f8f8f8; + border: 1px solid #cccccc; + font-size: 13px; + line-height: 19px; + overflow: auto; + padding: 6px 10px; + border-radius: 3px; +} +pre code, +pre tt { + background-color: transparent; + border: none; +} diff --git a/utils/templates/latex_preamble.jinga2.md b/utils/templates/latex_preamble.jinga2.md new file mode 100644 index 00000000..b12a96aa --- /dev/null +++ b/utils/templates/latex_preamble.jinga2.md @@ -0,0 +1,28 @@ +--- +title: Teletype Documenation +documentclass: report +geometry: margin=1in +links-as-notes: true +subparagraph: true +fontsize: 12pt +mainfont: Roboto-Regular.ttf +mainfontoptions: +- Path=/Users/sam/Dropbox/Projects/monome/teletype/utils/fonts/roboto-hinted/ +- BoldFont=Roboto-Bold.ttf +- ItalicFont=Roboto-Italic.ttf +- BoldItalicFont=Roboto-BoldItalic.ttf +monofont: RobotoMono-Regular.ttf +monofontoptions: +- Path=/Users/sam/Dropbox/Projects/monome/teletype/utils/fonts/roboto-mono/ +- BoldFont=RobotoMono-Bold.ttf +- ItalicFont=RobotoMono-Italic.ttf +- BoldItalicFont=RobotoMono-BoldItalic.ttf +header-includes: +- \usepackage{titlesec} +- \titleformat{\chapter}{\normalfont\LARGE\bfseries}{\thechapter.}{1em}{} +- \titlespacing*{\chapter}{0pt}{3.5ex plus 1ex minus .2ex}{2.3ex plus .2ex} +- \AtBeginEnvironment{longtable}{\small}{}{} +- \renewcommand\arraystretch{1.3} +--- + + diff --git a/utils/templates/latex_preamble.md b/utils/templates/latex_preamble.md new file mode 100644 index 00000000..f3d40c74 --- /dev/null +++ b/utils/templates/latex_preamble.md @@ -0,0 +1,28 @@ +--- +title: Teletype Documenation +documentclass: report +geometry: margin=1in +links-as-notes: true +subparagraph: true +fontsize: 12pt +mainfont: Roboto-Regular.ttf +mainfontoptions: +- Path={{fonts_dir}}roboto-hinted/ +- BoldFont=Roboto-Bold.ttf +- ItalicFont=Roboto-Italic.ttf +- BoldItalicFont=Roboto-BoldItalic.ttf +monofont: RobotoMono-Regular.ttf +monofontoptions: +- Path={{fonts_dir}}roboto-mono/ +- BoldFont=RobotoMono-Bold.ttf +- ItalicFont=RobotoMono-Italic.ttf +- BoldItalicFont=RobotoMono-BoldItalic.ttf +header-includes: +- \usepackage{titlesec} +- \titleformat{\chapter}{\normalfont\LARGE\bfseries}{\thechapter.}{1em}{} +- \titlespacing*{\chapter}{0pt}{3.5ex plus 1ex minus .2ex}{2.3ex plus .2ex} +- \AtBeginEnvironment{longtable}{\small}{}{} +- \renewcommand\arraystretch{1.3} +--- + + diff --git a/utils/templates/op_extended.jinga2.md b/utils/templates/op_extended.jinga2.md new file mode 100644 index 00000000..aad0f05d --- /dev/null +++ b/utils/templates/op_extended.jinga2.md @@ -0,0 +1,21 @@ +### `{{ name }}` + +{% if prototype_set is defined %} + - **`{{ prototype }}`** / **`{{ prototype_set }}`** +{% else %} + - **`{{ prototype }}`** +{% endif %} +{% if aliases is defined %} +{% for alias in aliases %} + - _alias_: **`{{ alias }}`** +{% endfor %} +{% endif %} + +{% if description is defined %} +{{ description }} +{% else %} +{% if short is defined %} +{{ short }} +{% endif %} +{% endif %} + diff --git a/utils/templates/op_table.jinga2.md b/utils/templates/op_table.jinga2.md new file mode 100644 index 00000000..181dc5f4 --- /dev/null +++ b/utils/templates/op_table.jinga2.md @@ -0,0 +1,11 @@ + + +| OP | OP _(set)_ | _(aliases)_ | Description | +|------------------------|--------------|-------------|----------------------------------| +{% for op in ops %} +| **`{{ op.prototype }}`** | {% if op.prototype_set is defined %}**`{{ op.prototype_set }}`**{% endif %} | {% for a in op.aliases %} **`{{a}}`** {% if not loop.last %}, {% endif %} {% endfor %} | {{ op.short | replace("\n", " ") }} | +{% endfor %}