<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>http://knasmusic.com/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Knaadmin</id>
	<title>KNAS Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="http://knasmusic.com/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Knaadmin"/>
	<link rel="alternate" type="text/html" href="http://knasmusic.com/wiki/index.php?title=Special:Contributions/Knaadmin"/>
	<updated>2026-07-22T02:32:18Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.0</generator>
	<entry>
		<id>http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_reference_V1.1&amp;diff=1693</id>
		<title>The Ekdahl FAR - Command reference V1.1</title>
		<link rel="alternate" type="text/html" href="http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_reference_V1.1&amp;diff=1693"/>
		<updated>2026-06-17T12:04:40Z</updated>

		<summary type="html">&lt;p&gt;Knaadmin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
The Ekdahl FAR V1.1 introduces the concept of &#039;&#039;modules&#039;&#039;. A &#039;&#039;module&#039;&#039; can contain any number of &#039;&#039;commands&#039;&#039; as well as other &#039;&#039;modules&#039;&#039;. Furthermore any number of &#039;&#039;modules&#039;&#039; of the same type can exist within a context, these are addressed using classic C-style array &#039;&#039;indexing&#039;&#039; with the help of brackets (&amp;quot;[ ]&amp;quot;). Extending on the classic usage, multiple &#039;&#039;indexes&#039;&#039; can be addressed simultaneously by either comma-separating the objects (&amp;quot;[0,3,4]&amp;quot;) and using &#039;&#039;ranges&#039;&#039; (&amp;quot;[3-6]&amp;quot;). &#039;&#039;Modules&#039;&#039; can be either &#039;&#039;internal&#039;&#039; or &#039;&#039;external&#039;&#039;, meaning that they may all physically exist within a single hardware object, or they can be be remote-controlled devices. From a user perspective this however makes no difference as they will appear the same.&lt;br /&gt;
&lt;br /&gt;
While all &#039;&#039;modules&#039;&#039; have their own set of &#039;&#039;commands&#039;&#039;, there are certain &#039;&#039;commands&#039;&#039; that all &#039;&#039;modules&#039;&#039; &amp;lt;u&amp;gt;must&amp;lt;/u&amp;gt; implement and can thus be accessed anywhere within the &#039;&#039;module hierarchy.&#039;&#039; There are also &#039;&#039;base commands&#039;&#039; that always exist within any given FAR ecosystem as well as product-specific &#039;&#039;base commands&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Ubiquitous commands ==&lt;br /&gt;
The &#039;&#039;module commands&#039;&#039; that are &amp;lt;u&amp;gt;required&amp;lt;/u&amp;gt; to be implemented in &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; &#039;&#039;modules&#039;&#039; and that can thus be accessed from anywhere are&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|list&lt;br /&gt;
|ls&lt;br /&gt;
|hidden/h:modules/m:commands/c:instances/i:instancecounts/ic:recursive/r&lt;br /&gt;
|Lists all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039; under the current module depending on the parameters given; &#039;hidden&#039; includes normally hidden &#039;&#039;commands&#039;&#039;, &#039;modules&#039; includes any &#039;&#039;submodules&#039;&#039;, &#039;commands&#039; shows &#039;&#039;commands&#039;&#039;, &#039;instances&#039; shows data for each individual instance of a &#039;&#039;module&#039;&#039;, &#039;instancecounts&#039; includes number of instances of each &#039;&#039;module&#039;&#039;, &#039;recursive&#039; lists all child &#039;&#039;modules&#039;&#039; / &#039;&#039;commands&#039;&#039;. No parameters defaults to showing all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039; recursively with instance counts. It doesn&#039;t show per-instance data or hidden commands.&lt;br /&gt;
|-&lt;br /&gt;
|help&lt;br /&gt;
|help&lt;br /&gt;
|recursive/r&lt;br /&gt;
|Shows a brief explanation of all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039;, shows the help for all &#039;&#039;submodules&#039;&#039; as well if &#039;recursive&#039;&lt;br /&gt;
|-&lt;br /&gt;
|dumpdata&lt;br /&gt;
|dump&lt;br /&gt;
|recursive/r&lt;br /&gt;
|Dumps all data saved for the current &#039;&#039;module&#039;&#039;, will list the data of all &#039;&#039;submodules&#039;&#039; as well if &#039;recursive&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Base commands ==&lt;br /&gt;
B&#039;&#039;ase commands&#039;&#039; are &#039;&#039;commands&#039;&#039; that always exist at the root in any implementation of the Ekdahl FAR.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|version&lt;br /&gt;
|ver&lt;br /&gt;
| -&lt;br /&gt;
|Gets the current firmware version&lt;br /&gt;
|-&lt;br /&gt;
|debugprint&lt;br /&gt;
|dp&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;command|usb|hardware|undefined|priority|error|inforequest|expressionparser|debug:1|0&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Turns on or off serial feedback for the given item&lt;br /&gt;
|-&lt;br /&gt;
|requestinfo&lt;br /&gt;
|rqi&lt;br /&gt;
|command&lt;br /&gt;
|Retrives any data saved for a &#039;&#039;command&#039;&#039;, if applicable&lt;br /&gt;
|-&lt;br /&gt;
|saveallparameters&lt;br /&gt;
|sap&lt;br /&gt;
| -&lt;br /&gt;
|Saves all avaliable parameters&lt;br /&gt;
|-&lt;br /&gt;
|loadallparameters&lt;br /&gt;
|lap&lt;br /&gt;
| -&lt;br /&gt;
|Loads all avaliable parameters&lt;br /&gt;
|-&lt;br /&gt;
|resetallparameters&lt;br /&gt;
|rap&lt;br /&gt;
| -&lt;br /&gt;
|Resets all saved parameters&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|rst&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;1|0&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Resets the Ekdahl FAR, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|nick&lt;br /&gt;
|nick&lt;br /&gt;
|name&lt;br /&gt;
|Sets the nickname of this unit&lt;br /&gt;
|-&lt;br /&gt;
|nooperation&lt;br /&gt;
|nop&lt;br /&gt;
| -&lt;br /&gt;
|Do absolutely, positively, nothing. Useful for testing and interfacing with computers, it&#039;s a good way to know that the unit is alive and responding since a &amp;quot;nop&amp;quot; is being returned as a response upon reception.&lt;br /&gt;
|-&lt;br /&gt;
|uservariable&lt;br /&gt;
|uv&lt;br /&gt;
|variable(0-9):value&lt;br /&gt;
|Set user variable 0-9 to &#039;value&#039;&lt;br /&gt;
|-&lt;br /&gt;
|expressionparserevaluate&lt;br /&gt;
|epev&lt;br /&gt;
|expression&lt;br /&gt;
|Evaluates an arithmetric expression and sends back the output, all variables and functions that can be used in any &#039;&#039;command string&#039;&#039; can also be used here. Useful for testing expressions.&lt;br /&gt;
|-&lt;br /&gt;
|ifequal&lt;br /&gt;
|ife&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] EQUALS [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring].&lt;br /&gt;
|-&lt;br /&gt;
|ifgreater&lt;br /&gt;
|ifg&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] &amp;gt; [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring]&lt;br /&gt;
|-&lt;br /&gt;
|ifless&lt;br /&gt;
|ifl&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] &amp;lt; [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring]&lt;br /&gt;
|-&lt;br /&gt;
|freeram&lt;br /&gt;
|ram&lt;br /&gt;
| -&lt;br /&gt;
|Shows free RAM memory&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The base also contains the following &#039;&#039;modules:&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|pluginhandler&lt;br /&gt;
|ph&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The Ekdahl FAR stand alone single string unit ==&lt;br /&gt;
The Ekdahl FAR stand-alone single string unit offers these &#039;&#039;commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|calibrateall&lt;br /&gt;
|ca&lt;br /&gt;
| -&lt;br /&gt;
|Performs all calibration routines on the selected bow, see below for routines performed&lt;br /&gt;
|-&lt;br /&gt;
|calibratebowspeed&lt;br /&gt;
|cbs&lt;br /&gt;
| -&lt;br /&gt;
|Finds the minimum and maximum bow speed of the selected bow&lt;br /&gt;
|-&lt;br /&gt;
|calibratebowpressure&lt;br /&gt;
|cbp&lt;br /&gt;
| -&lt;br /&gt;
|Finds the minimum and maximum bow pressure of the selected bow&lt;br /&gt;
|-&lt;br /&gt;
|calibratemute&lt;br /&gt;
|cmu&lt;br /&gt;
| -&lt;br /&gt;
|Calibrate mute settings&lt;br /&gt;
|-&lt;br /&gt;
|pickupstringfrequency&lt;br /&gt;
|psf&lt;br /&gt;
| -&lt;br /&gt;
|Returns the fundamental tone calculated from the current audio signal if apliccable&lt;br /&gt;
|-&lt;br /&gt;
|pickupaudiopeak&lt;br /&gt;
|pap&lt;br /&gt;
| -&lt;br /&gt;
|Returns the peak amplitude of the current audio signal&lt;br /&gt;
|-&lt;br /&gt;
|pickupaudiorms&lt;br /&gt;
|par&lt;br /&gt;
| -&lt;br /&gt;
|Returns the RMS amplitude of the current audio signal&lt;br /&gt;
|}&lt;br /&gt;
The Ekdahl FAR also contains the following &#039;&#039;modules&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|bowingwheel&lt;br /&gt;
|bw&lt;br /&gt;
|-&lt;br /&gt;
|mute&lt;br /&gt;
|mu&lt;br /&gt;
|-&lt;br /&gt;
|solenoid&lt;br /&gt;
|so&lt;br /&gt;
|-&lt;br /&gt;
|controlbox&lt;br /&gt;
|cb&lt;br /&gt;
|-&lt;br /&gt;
|midiconfigurationhandler&lt;br /&gt;
|mcf&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The bowing wheel-&#039;&#039;module&#039;&#039; (&amp;quot;bowingwheel&amp;quot; / &amp;quot;bw&amp;quot;) ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;Bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; contains everything needed to interface with a single &#039;&#039;bowing wheel&#039;&#039;. Each &#039;&#039;bowing wheel&#039;&#039; has its own harmonic series, pressure actuators and direct hardware interface. It contains the following &#039;&#039;commands&#039;&#039;.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|speedmode&lt;br /&gt;
|sm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Bow motor speed mode, 0 = Automatic and 1 = Manual. Automatic mode means that the bowing wheel will automatically turn off after the &#039;&#039;motor timeout&#039;&#039; has been reached after being put into rest mode&lt;br /&gt;
|-&lt;br /&gt;
|motortimeout&lt;br /&gt;
|mt&lt;br /&gt;
|ms&lt;br /&gt;
|Bow motor shutdown timeout after bow having been put into the rest position&lt;br /&gt;
|-&lt;br /&gt;
|pidenable&lt;br /&gt;
|pe&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets the bow PID on/off&lt;br /&gt;
|-&lt;br /&gt;
|motorfaultcommands&lt;br /&gt;
|mfc&lt;br /&gt;
|commands&lt;br /&gt;
|Commands to execute when a motor fault is tripped - !WARNING! Can ruin your instrument if changed&lt;br /&gt;
|-&lt;br /&gt;
|motoroverpowercommands&lt;br /&gt;
|moc&lt;br /&gt;
|commands&lt;br /&gt;
|Commands to execute when motor is over the power limit - !WARNING! Can ruin your instrument if changed&lt;br /&gt;
|}&lt;br /&gt;
The &#039;&#039;modules&#039;&#039; in the &amp;quot;Bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; are as follows&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|bowpressure&lt;br /&gt;
|bp&lt;br /&gt;
|-&lt;br /&gt;
|dcmotor&lt;br /&gt;
|dcm&lt;br /&gt;
|-&lt;br /&gt;
|pid&lt;br /&gt;
|pid&lt;br /&gt;
|-&lt;br /&gt;
|harmonicserieshandler&lt;br /&gt;
|hsh&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The bow pressure-&#039;&#039;module&#039;&#039; (&amp;quot;bowpressure&amp;quot; / &amp;quot;bp&amp;quot;) ==&lt;br /&gt;
The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; handles the &#039;&#039;pressure&#039;&#039; of the &#039;&#039;bowing wheel&#039;&#039; against the string. The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|baseline&lt;br /&gt;
|ba&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure baseline, modulation is added to this point upward. Typically this is set with a knob on the &#039;&#039;control box&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|modifier&lt;br /&gt;
|mo&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure modulation, added to the baseline&lt;br /&gt;
|-&lt;br /&gt;
|rest&lt;br /&gt;
|rs&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the bow pressure in the &#039;&#039;rest&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|engage&lt;br /&gt;
|en&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the bow pressure in the &#039;&#039;engage&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|stallpressure&lt;br /&gt;
|sp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure stall/maximum position, this parameter is set using &#039;&#039;hardware positioning&#039;&#039; and is used as the absolute maximum for baseline and modifier combiner&lt;br /&gt;
|-&lt;br /&gt;
|engagepressure&lt;br /&gt;
|ep&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure touch/minimum position, this parameter is set using &#039;&#039;hardware position&#039;&#039; and is used as the starting point for when both the baseline and modifier is set to zero&lt;br /&gt;
|-&lt;br /&gt;
|restpressure&lt;br /&gt;
|rp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure rest position, this parameter is set using &#039;&#039;hardware positioning&#039;&#039; and is typically set to a point just below the string where it does not touch at all. The purpose of this is because while the actual hardware might be able to make the bow go even lower, that position might be far enough from the string that once &#039;&#039;engaged&#039;&#039; the bow may have so far to travel that there is perceptible &#039;&#039;latency&#039;&#039;.&lt;br /&gt;
|-&lt;br /&gt;
|engagespeed&lt;br /&gt;
|es&lt;br /&gt;
|1- ~100&lt;br /&gt;
|Bow pressure movement speed when engaging or disengaging&lt;br /&gt;
|-&lt;br /&gt;
|modulationspeed&lt;br /&gt;
|ms&lt;br /&gt;
|0.1 - 10&lt;br /&gt;
|Bow pressure movement speed while engaged&lt;br /&gt;
|-&lt;br /&gt;
|hold&lt;br /&gt;
|hd&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets bow hold (infinite sustain) on/off, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|home&lt;br /&gt;
|hm&lt;br /&gt;
| -&lt;br /&gt;
|Homing bow, used at startup and in case of the bow loosing position&lt;br /&gt;
|-&lt;br /&gt;
|tmcinfo&lt;br /&gt;
|tmi&lt;br /&gt;
| -&lt;br /&gt;
|Request statistical information from the TMC2209 stepper motor driver&lt;br /&gt;
|}&lt;br /&gt;
Note that the &amp;quot;stall&amp;quot;, &amp;quot;engage&amp;quot; and &amp;quot;rest&amp;quot;-pressure positions mention something called &#039;&#039;hardware position&#039;&#039;. This means the entire available movement of the &#039;&#039;bowing jack&#039;&#039;. Because the very bottom and top end of the movement might not be musically useful and may even harm the instrument, the &amp;quot;baseline&amp;quot; and &amp;quot;modifier&amp;quot; commands &#039;&#039;parameter&#039;&#039;s are scaled depending on these settings.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;engage&amp;quot; and &amp;quot;modulation&amp;quot;-speed settings sets how fast the stepper motor that drives the &#039;&#039;pressure&#039;&#039; moves depending on whether the &#039;&#039;bowing jack&#039;&#039; is set to &#039;&#039;engage&#039;&#039; or not. The idea here is that while wanting to be able to minimize &#039;&#039;latency&#039;&#039; by &#039;&#039;engaging&#039;&#039; and &#039;&#039;disengaging&#039;&#039; from the string as quickly as possible, dynamic changes in the &#039;&#039;pressure&#039;&#039; while playing benefits from much smoother movements as the &#039;&#039;bowing wheel&#039;&#039; takes some time to catch up to varying amounts of friction.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; contains one or more of the following &#039;&#039;modules&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|actuatorhandler&lt;br /&gt;
|ah&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The actuator handler-&#039;&#039;module&#039;&#039; (&amp;quot;actuatorhandler&amp;quot; / &amp;quot;ah&amp;quot;) ==&lt;br /&gt;
The concept of &amp;quot;actuators&amp;quot; came up as it is possible to have &#039;&#039;bowing wheels&#039;&#039; of different sizes and wanting to be able to switch quickly in between them, perhaps during mid-performance. Because a differently sized wheel will require different values for the above mentioned &amp;quot;stall&amp;quot;, &amp;quot;engage&amp;quot; and &amp;quot;reset&amp;quot;-&#039;&#039;pressure&#039;&#039;, each &#039;&#039;actuator&#039;&#039; stores these values. Instead of having to manually change the previously mentioned values, simply selecting a new &#039;&#039;actuator&#039;&#039; will automatically load the values. The &amp;quot;actuatorhandler&amp;quot;-&#039;&#039;module&#039;&#039; is the handler of one or more &amp;quot;actuator&amp;quot;-&#039;&#039;modules&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;commands&#039;&#039; of the &amp;quot;acuatorhandler&amp;quot;-&#039;&#039;module&#039;&#039; are as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|add&lt;br /&gt;
|a&lt;br /&gt;
|(name):(rest:engage:stall)&lt;br /&gt;
|Add new actuator with the given name and parameters&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|actuatornumber&lt;br /&gt;
|Remove bow actuator [actuatornumber]&lt;br /&gt;
|-&lt;br /&gt;
|count&lt;br /&gt;
|c&lt;br /&gt;
| -&lt;br /&gt;
|Returns the amount of saved bow actuators&lt;br /&gt;
|}&lt;br /&gt;
The &amp;quot;actuatorhandler&amp;quot;-&#039;&#039;module&#039;&#039; contains one or more of&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|actuator&lt;br /&gt;
|ac&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The actuator-&#039;&#039;module&#039;&#039; (&amp;quot;actuator&amp;quot; / &amp;quot;ac&amp;quot;) ==&lt;br /&gt;
The &amp;quot;actuator&amp;quot;-&#039;&#039;module&#039;&#039; contains the following commands&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|[index]&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|Selects the given actuator&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Sets the actuator name&lt;br /&gt;
|-&lt;br /&gt;
|data&lt;br /&gt;
|da&lt;br /&gt;
|name:rest:engage:stall&lt;br /&gt;
|Sets the actuator name, rest, engage and stall &#039;&#039;pressure&#039;&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The DC motor-&#039;&#039;module&#039;&#039; (&amp;quot;dcmotor&amp;quot; / &amp;quot;dcm&amp;quot;) ==&lt;br /&gt;
The &amp;quot;dcmotor&amp;quot;-&#039;&#039;module&#039;&#039; handles the direct &amp;lt;u&amp;gt;raw&amp;lt;/u&amp;gt; control of the &#039;&#039;bowing motor&#039;&#039; and handles the reporting back of the current speed. It has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|run&lt;br /&gt;
|ru&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Turns the motor off/on&lt;br /&gt;
|-&lt;br /&gt;
|pwm&lt;br /&gt;
|pw&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor direct power in 16-bit PWM values, requires that the &#039;&#039;PID&#039;&#039; is turned off&lt;br /&gt;
|-&lt;br /&gt;
|voltage&lt;br /&gt;
|vo&lt;br /&gt;
|~2 - 10V&lt;br /&gt;
|Sets the voltage of the regulator powering the motor. Changes here can make the motor more responsive to certain frequencies but will also affect how well the &#039;&#039;PID&#039;&#039; works. !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|current&lt;br /&gt;
|cu&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor reported current use&lt;br /&gt;
|-&lt;br /&gt;
|currentlimit&lt;br /&gt;
|cl&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor current limit (A)- !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|powerlimit&lt;br /&gt;
|pl&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor power limit (W) - !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|frequency&lt;br /&gt;
|fq&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor reported frequency&lt;br /&gt;
|-&lt;br /&gt;
|emergencystop&lt;br /&gt;
|es&lt;br /&gt;
|ms (0-65535)&lt;br /&gt;
|Immediately stops the bowing motor and doesn&#039;t allow it to start again until the cool down period given in the first argument has lapsed (milliseconds)&lt;br /&gt;
|-&lt;br /&gt;
|minpwm&lt;br /&gt;
|ip&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor minimum PWM (for calibration)&lt;br /&gt;
|-&lt;br /&gt;
|maxpwm&lt;br /&gt;
|xp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor maximum PWM (for calibration)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The PID controller-&#039;&#039;module&#039;&#039; (&amp;quot;pid&amp;quot;) ==&lt;br /&gt;
The &amp;quot;pidcontroller&amp;quot;-&#039;&#039;module&#039;&#039; is responsible for keeping the &amp;quot;dcmotor&amp;quot;-&#039;&#039;module&#039;&#039; at a certain frequency (given in Hertz). It takes the output of the motor frequency measurement and feeds it a PWM value that tries to make the speed constant regardless of the friction that the motor is enduring. To learn more about PID Controllers please see this [[wikipedia:PID_controller|wikipedia article]]. The &#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|targetfrequency&lt;br /&gt;
|tf&lt;br /&gt;
|hertz&lt;br /&gt;
|Sets the PID target frequency&lt;br /&gt;
|-&lt;br /&gt;
|ki&lt;br /&gt;
|ki&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Ki parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|kp&lt;br /&gt;
|kp&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Kp parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|kd&lt;br /&gt;
|kd&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Kd parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|integratorerror&lt;br /&gt;
|ie&lt;br /&gt;
|float&lt;br /&gt;
|Sets the lower threshold of error values for the PID integrator to ignore&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|re&lt;br /&gt;
| -&lt;br /&gt;
|Resets the PID integrator and derivative&lt;br /&gt;
|-&lt;br /&gt;
|maxerror&lt;br /&gt;
|xe&lt;br /&gt;
|float&lt;br /&gt;
|Maximum error to correct in each PID loop, essentially sets acceleration&lt;br /&gt;
|-&lt;br /&gt;
|peakerror&lt;br /&gt;
|pe&lt;br /&gt;
|float&lt;br /&gt;
|Get latest PID peak error&lt;br /&gt;
|-&lt;br /&gt;
|motorspeedmax&lt;br /&gt;
|msx&lt;br /&gt;
|Hertz&lt;br /&gt;
|Bow motor maximum speed limit&lt;br /&gt;
|-&lt;br /&gt;
|motorspeedmin&lt;br /&gt;
|msi&lt;br /&gt;
|Hertz&lt;br /&gt;
|Bow motor minimum speed limit&lt;br /&gt;
|-&lt;br /&gt;
|measuretimetotarget&lt;br /&gt;
|mtt&lt;br /&gt;
|Hertz&lt;br /&gt;
|Measure the time it takes to change from the current frequency to the target frequency, for testing purposes&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The harmonic series handler&amp;quot;-&#039;&#039;module&#039;&#039; (&amp;quot;harmonicserieshandler&amp;quot; / &amp;quot;hsh&amp;quot;) ==&lt;br /&gt;
The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; is responsible for sending frequency data to the &amp;quot;pid&amp;quot;-&#039;&#039;module&#039;&#039;. It handles calculating the correct frequency of the &#039;&#039;bowing wheel&#039;&#039; according to the selected &#039;&#039;harmonic&#039;&#039; and &#039;&#039;harmonic shift&#039;&#039; per the currently selected &#039;&#039;harmonic series&#039;&#039;. The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|fundamental&lt;br /&gt;
|fu&lt;br /&gt;
|Hertz&lt;br /&gt;
|The fundamental frequency of the string, all harmonics are calculated from this number&lt;br /&gt;
|-&lt;br /&gt;
|harmonic&lt;br /&gt;
|h&lt;br /&gt;
|int&lt;br /&gt;
|Selects the harmonic number to set the &#039;&#039;bowing wheel&#039;&#039; to. A ratio is taken from the given &#039;&#039;harmonic&#039;&#039; in the current &#039;&#039;harmonic series&#039;&#039;, the ratio is then multiplied by the &#039;&#039;fundamental frequency&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|harmonicadd&lt;br /&gt;
|ha&lt;br /&gt;
|int&lt;br /&gt;
|This number is added to the current harmonic&lt;br /&gt;
|-&lt;br /&gt;
|harmonicbase&lt;br /&gt;
|hb&lt;br /&gt;
|int&lt;br /&gt;
|Same as harmonic but where the harmonic number is based on a MIDI note given by basenote&lt;br /&gt;
|-&lt;br /&gt;
|basenote&lt;br /&gt;
|bn&lt;br /&gt;
|0-127&lt;br /&gt;
|Sets the MIDI base note of the &#039;&#039;bowing wheel&#039;&#039;, used in conjunction with &amp;quot;harmonicbase&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|shift&lt;br /&gt;
|sh&lt;br /&gt;
| -32767 - 32767&lt;br /&gt;
|Sets shift from the currently playing harmonic where 32767 equals the entire harmonic shift range shifted up&lt;br /&gt;
|-&lt;br /&gt;
|shiftrange&lt;br /&gt;
|sr&lt;br /&gt;
|0-36&lt;br /&gt;
|Set the number of harmonic numbers that constitutes an entire harmonic shift&lt;br /&gt;
|-&lt;br /&gt;
|shift5&lt;br /&gt;
|sh5&lt;br /&gt;
| -32767 - 32767&lt;br /&gt;
|Sets the shift from the currently playing harmonic over 5 octaves where 32767 equals 5 octaves shift up from the fundamental&lt;br /&gt;
|-&lt;br /&gt;
|add&lt;br /&gt;
|a&lt;br /&gt;
|(name):(ratios)&lt;br /&gt;
|Add a new series with the given name and parameters&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|series&lt;br /&gt;
|Remove the series given and shift any series accordingly. Cannot remove all series&lt;br /&gt;
|-&lt;br /&gt;
|count&lt;br /&gt;
|c&lt;br /&gt;
| -&lt;br /&gt;
|Returns the number of harmonic series in the list and their IDs&lt;br /&gt;
|}&lt;br /&gt;
The &amp;quot;harmonicserieshandler&amp;quot;-module contains at the very least ONE harmonic series, by default it contains two: one for equal temperament and one for just intonation. The current series can be selected by simply indexing the &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; without a &#039;&#039;command&#039;&#039;, e.g. &amp;quot;harmonicserieshandler.harmonicseries[1]&amp;quot;. To be consistent, these are the &#039;&#039;modules&#039;&#039; in the &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|harmonicseries&lt;br /&gt;
|hs&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The harmonic series-&#039;&#039;module&#039;&#039; (&amp;quot;harmonicseries&amp;quot; / &amp;quot;hs&amp;quot;) ==&lt;br /&gt;
The &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; contains any number of &#039;&#039;ratios&#039;&#039; that comprises a scale, ratios are given in a standard format where a ratio of &amp;quot;1&amp;quot; is equal to the fundamental, &amp;quot;2&amp;quot; would be one octave up etc. A standard &#039;&#039;harmonic series&#039;&#039; contains 12 ratios following a just intonation scheme. The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; will automatically adapt to the currently selected &#039;&#039;harmonic series&#039;&#039; length, whether it&#039;s a standard 12-tone scale, some kinda 3-tone scale or a full on bananas 53-tone scale. The &#039;&#039;commands&#039;&#039; of the &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; is as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|[index]&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
|Sets the currently selected &#039;&#039;harmonic Series&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Sets the name of the &#039;&#039;harmonic series&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|data&lt;br /&gt;
|da&lt;br /&gt;
|name:ratios&lt;br /&gt;
|Gets / sets all data for the &#039;&#039;harmonic series&#039;&#039; in the given slot with an arbitrary &#039;&#039;name&#039;&#039; as the first &#039;&#039;parameter&#039;&#039;. The length of the series is simply set to the amount of ratios given&lt;br /&gt;
|-&lt;br /&gt;
|ratio&lt;br /&gt;
|r&lt;br /&gt;
|harmonic:ratio&lt;br /&gt;
|Sets the ratio of the given harmonic in current &#039;&#039;harmonic series&#039;&#039;, will increase the list size if needed to address the harmonic&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|harmonic&lt;br /&gt;
|Remove the harmonic ratio given in the current series and shift any ratios accordingly. Cannot remove all ratios&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The mute-&#039;&#039;module&#039;&#039; (&amp;quot;mute&amp;quot; / &amp;quot;mu&amp;quot;) ==&lt;br /&gt;
The &amp;quot;mute&amp;quot;-&#039;&#039;module&#039;&#039; works very similarly to the &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; in that it controls a stepper motor with some software limits in place in order to press the mute against the string. The &#039;&#039;commands&#039;&#039; are as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|setposition&lt;br /&gt;
|sp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set mute position&lt;br /&gt;
|-&lt;br /&gt;
|fullmute&lt;br /&gt;
|fm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the mute in &#039;&#039;full mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|halfmute&lt;br /&gt;
|hm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the mute in &#039;&#039;half mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|rest&lt;br /&gt;
|rs&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Put the mute in the &#039;&#039;rest&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|savefull&lt;br /&gt;
|sf&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Save the current mute position as the &#039;&#039;full mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|savehalf&lt;br /&gt;
|sh&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Save the current mute position as the &#039;&#039;half mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|saverest&lt;br /&gt;
|sr&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Save the current mute position as the &#039;&#039;rest&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|fullmuteposition&lt;br /&gt;
|fmp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;full mute&#039;&#039; position according to the &#039;&#039;hardware position&#039;&#039; given&lt;br /&gt;
|-&lt;br /&gt;
|halfmuteposition&lt;br /&gt;
|hmp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;half mute&#039;&#039; position according to the &#039;&#039;hardware position&#039;&#039; given&lt;br /&gt;
|-&lt;br /&gt;
|restposition&lt;br /&gt;
|rp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;rest&#039;&#039; position according to the &#039;&#039;hardware position&#039;&#039; given&lt;br /&gt;
|-&lt;br /&gt;
|sustain&lt;br /&gt;
|su&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets the sustain off/on, this will keep the mute in the &#039;&#039;rest&#039;&#039; position even if a &amp;quot;fullmute&amp;quot;-&#039;&#039;command&#039;&#039; is given, lasts until &amp;quot;sustain&amp;quot; is set to &amp;quot;0&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
|backoff&lt;br /&gt;
|bo&lt;br /&gt;
|0-65535&lt;br /&gt;
|Setting the time that the mute stays in the mutefullmute position before automatically going into rest, set in mS. A value of &amp;quot;0&amp;quot; disables backoff. This is used because if the mute is not backing off until something is attempted to be played, the backing-off time will either introduce &#039;&#039;latency&#039;&#039; or the string will be initially partially muted&lt;br /&gt;
|-&lt;br /&gt;
|home&lt;br /&gt;
|hm&lt;br /&gt;
| -&lt;br /&gt;
|Home mute, used during initialization and if the mute were to loose position&lt;br /&gt;
|-&lt;br /&gt;
|hardwareposition&lt;br /&gt;
|hwp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;hardware position&#039;&#039; of the mute instead of scaling it over the &#039;&#039;full mute&#039;&#039; and &#039;&#039;rest&#039;&#039; positions. Mainly used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|completetask&lt;br /&gt;
|cpt&lt;br /&gt;
| -&lt;br /&gt;
|Requests a callback when the current operation is finished. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|autocorrect&lt;br /&gt;
|ac&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Enables auto correct positioning that uses the homing sensor to correct positioning on the fly. EXPERIMENTAL&lt;br /&gt;
|-&lt;br /&gt;
|homingsensed&lt;br /&gt;
|hms&lt;br /&gt;
| -&lt;br /&gt;
|Requests whether the homing sensor is currently active or not. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|movedirection&lt;br /&gt;
|md&lt;br /&gt;
| -&lt;br /&gt;
|Requests the current direction of movement (0 Forward, 1 Reverse). Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|currentstep&lt;br /&gt;
|cs&lt;br /&gt;
| -&lt;br /&gt;
|Requests the current step. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|homingpoint&lt;br /&gt;
|hmp&lt;br /&gt;
|edgedirection&lt;br /&gt;
|Requests the given homing point. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|homingstage&lt;br /&gt;
|hms&lt;br /&gt;
| -&lt;br /&gt;
|Requests the current homing stage (UNHOMED, HOMED, FIRSTHOMINGRISING, SECONDHOMINGFALLING, SECONDHOMINGRISING, FIRSTHOMINGFALLING, MOVEPASTHOMESWITCH, MOVETOHOMESWITCH, GOTOOFFSET). Only used internally by other &#039;&#039;modules.&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|tmcinfo&lt;br /&gt;
|tmi&lt;br /&gt;
| -&lt;br /&gt;
|Request statistical information from the TMC2209 stepper motor driver&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The solenoid-&#039;&#039;module&#039;&#039; (&amp;quot;solenoid&amp;quot; / &amp;quot;so&amp;quot;) ==&lt;br /&gt;
The &amp;quot;solenoid&amp;quot;-&#039;&#039;module&#039;&#039; currently controls the &#039;&#039;hammer&#039;&#039; of the Ekdahl FAR. Due to the fact that the very same &#039;&#039;module&#039;&#039; could be used for anything that uses a striking &#039;&#039;solenoid&#039;&#039; it was named as such. It has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|engage&lt;br /&gt;
|en&lt;br /&gt;
|0-65535&lt;br /&gt;
|Engages the solenoid using the first parameter as the force&lt;br /&gt;
|-&lt;br /&gt;
|rest&lt;br /&gt;
|rs&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Forces the solenoid to its rest position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|maxforce&lt;br /&gt;
|xf&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set solenoid maximum usable force&lt;br /&gt;
|-&lt;br /&gt;
|minforce&lt;br /&gt;
|if&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set solenoid minimum usable force&lt;br /&gt;
|-&lt;br /&gt;
|forcemultiplier&lt;br /&gt;
|fm&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set solenoid force multiplier, useful for scaling of all incoming &amp;quot;engage&amp;quot;-&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|engageduration&lt;br /&gt;
|ed&lt;br /&gt;
|uS&lt;br /&gt;
|Sets the duration of the solenoid hit in uS, if a value of 0 is set the solenoid will not disengage until a rest command has been given. WARNING!! HAVING THE SOLENOID ON FOR A SPAN OF SECONDS COULD DESTROY THE CIRCUITRY!!&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The control box-&#039;&#039;module&#039;&#039; (&amp;quot;controlbox&amp;quot; / &amp;quot;cb&amp;quot;) ==&lt;br /&gt;
The &amp;quot;controlbox&amp;quot;-&#039;&#039;module&#039;&#039; communicates with an external &#039;&#039;control box&#039;&#039; and will issue associated &#039;&#039;commands&#039;&#039; whenever new values are read on the ADC-converters. It handles averaging and does some noise-cancellation functions on the values as well. The &#039;&#039;commands&#039;&#039; are:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|harmonic&lt;br /&gt;
|har&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the harmonic knob or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|harmonicshift&lt;br /&gt;
|has&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the harmonic shift modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|finetune&lt;br /&gt;
|fin&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the fine tune knob changes&lt;br /&gt;
|-&lt;br /&gt;
|pressure&lt;br /&gt;
|pre&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the pressure knob or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|mute&lt;br /&gt;
|mut&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the mute knob or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|hammerscale&lt;br /&gt;
|hms&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the hammer scale knob changes&lt;br /&gt;
|-&lt;br /&gt;
|gate&lt;br /&gt;
|gt&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the gate switch or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|hammertrig&lt;br /&gt;
|hmt&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the hammer trigger modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|controldefaults&lt;br /&gt;
|cde&lt;br /&gt;
| -&lt;br /&gt;
|Reverts all ADC command strings to default values&lt;br /&gt;
|-&lt;br /&gt;
|datareturn&lt;br /&gt;
|dr&lt;br /&gt;
|channel:value&lt;br /&gt;
|Sent when a new value is presented on one of the ADC channels, cannot be invoked. Triggers the commands associated with the channel&lt;br /&gt;
|-&lt;br /&gt;
|adcsetting&lt;br /&gt;
|adcs&lt;br /&gt;
|channel : averages : interrupterrorthreshold : continuouserrorthreshold : continuoustimeout&lt;br /&gt;
|Sets ADC settings for a given channel. Averages are the number of samples to average, interruptthreshold is how much the value must change in order to issue a new value change event. continuousthreshold is how much the value must change when a previous change has already been recorded within the timespan of continuoustimeout&lt;br /&gt;
|-&lt;br /&gt;
|testadclatency&lt;br /&gt;
|tal&lt;br /&gt;
|0-65535&lt;br /&gt;
|Start a ADC latency test&lt;br /&gt;
|-&lt;br /&gt;
|testadclatencyreturn&lt;br /&gt;
|talr&lt;br /&gt;
| -&lt;br /&gt;
|Return from latency test&lt;br /&gt;
|-&lt;br /&gt;
|testadcminmax&lt;br /&gt;
|tix&lt;br /&gt;
|channel&lt;br /&gt;
|Test min/max value for a given channel and resets the counter&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The midi configuration handler-&#039;&#039;module&#039;&#039; (&amp;quot;midiconfigurationhandler&amp;quot; / &amp;quot;mcf&amp;quot;) ==&lt;br /&gt;
The &amp;quot;midiconfigurationhandler&amp;quot;-&#039;&#039;module&#039;&#039; handles a number of &amp;quot;midiconfiguration&amp;quot;-&#039;&#039;modules&#039;&#039;. It has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|allnotesoff&lt;br /&gt;
|ano&lt;br /&gt;
| -&lt;br /&gt;
|Clears the entire buffer of MIDI notes held&lt;br /&gt;
|-&lt;br /&gt;
|add&lt;br /&gt;
|a&lt;br /&gt;
|name&lt;br /&gt;
|Adds a new MIDI configuration with the given name&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|int&lt;br /&gt;
|Remove the specified MIDI configuration&lt;br /&gt;
|-&lt;br /&gt;
|count&lt;br /&gt;
|c&lt;br /&gt;
| -&lt;br /&gt;
|Returns the number of MIDI configurations&lt;br /&gt;
|}&lt;br /&gt;
It contains one or more of the following&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|midiconfiguration&lt;br /&gt;
|mc&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The midi configuration-&#039;&#039;module&#039;&#039; (&amp;quot;midiconfiguration&amp;quot; / &amp;quot;mc&amp;quot;) ==&lt;br /&gt;
A &amp;quot;midiconfiguration&amp;quot;-&#039;&#039;module&#039;&#039; handles the reception of &#039;&#039;MIDI messages&#039;&#039; and will output the associated &#039;&#039;commands&#039;&#039; to the instrument internally. The commands are as follows&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|[index]&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
|Sets the currently selected MIDI configuration&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Set the name of the MIDI configuration&lt;br /&gt;
|-&lt;br /&gt;
|noteon&lt;br /&gt;
|non&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Note On event&lt;br /&gt;
|-&lt;br /&gt;
|noteoff&lt;br /&gt;
|nof&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Note Off event&lt;br /&gt;
|-&lt;br /&gt;
|polyaftertouch&lt;br /&gt;
|pat&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Polyphonic after touch event&lt;br /&gt;
|-&lt;br /&gt;
|channelaftertouch&lt;br /&gt;
|cat&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Channel after touch event&lt;br /&gt;
|-&lt;br /&gt;
|pitchbend&lt;br /&gt;
|pb&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Pitch bend event&lt;br /&gt;
|-&lt;br /&gt;
|programchange&lt;br /&gt;
|pc&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Program change event&lt;br /&gt;
|-&lt;br /&gt;
|continuouscontrollerdata&lt;br /&gt;
|ccd&lt;br /&gt;
|controllernuber:&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Continuous controller event with the given [&#039;&#039;controllernumber&#039;&#039;]&lt;br /&gt;
|-&lt;br /&gt;
|removecc&lt;br /&gt;
|rmc&lt;br /&gt;
|controllernuber&lt;br /&gt;
|Removes the entry associated with the MIDI continuous controller even &#039;&#039;controllernumber&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|defaults&lt;br /&gt;
|d&lt;br /&gt;
| -&lt;br /&gt;
|Reverts the current configuration to default &#039;&#039;commands&#039;&#039;, values and CCs&lt;br /&gt;
|-&lt;br /&gt;
|receivechannel&lt;br /&gt;
|rc&lt;br /&gt;
|channel&lt;br /&gt;
|Sets the MIDI receive channel of the current configuration. 1-16 sets specific channel, any other value for OMNI&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The plugin handler-&#039;&#039;module&#039;&#039; (&amp;quot;pluginhandler&amp;quot; / &amp;quot;ph&amp;quot;) ==&lt;br /&gt;
The Ekdahl FAR allows for &#039;&#039;plugins&#039;&#039;. These are &#039;&#039;modules&#039;&#039; that can trigger certain &#039;&#039;command strings&#039;&#039; to be executed either periodically or triggered by an incoming &#039;&#039;command&#039;&#039;. Further explanation of the given &#039;&#039;plugins&#039;&#039; is given below. The various &#039;&#039;plugins&#039;&#039; are handled by the &amp;quot;pluginhandler&amp;quot;-&#039;&#039;module&#039;&#039;, the different &#039;&#039;plugin modules&#039;&#039; are identified by their own unique &#039;&#039;ID&#039;&#039;. The &amp;quot;pluginhandler&amp;quot;-&#039;&#039;module&#039;&#039; it has the following &#039;&#039;commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|add&lt;br /&gt;
|a&lt;br /&gt;
|pluginid&lt;br /&gt;
|Add plugin with the given ID&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|pluginid:index&lt;br /&gt;
|Remove plugin with the given ID and index&lt;br /&gt;
|-&lt;br /&gt;
|count&lt;br /&gt;
|c&lt;br /&gt;
|(pluginid)&lt;br /&gt;
|Return the number of plugins of the given type, if none is given it returns all plugins&lt;br /&gt;
|}&lt;br /&gt;
The number of available &#039;&#039;plugins&#039;&#039; will differ from time to time as the &#039;&#039;plugin system&#039;&#039; has been purposefully designed to allow for anyone to write and add their own &#039;&#039;plugins&#039;&#039;. As of the current writing (2026-06-14) the number of &amp;lt;u&amp;gt;possible&amp;lt;/u&amp;gt; &#039;&#039;plugin modules&#039;&#039; that &amp;lt;u&amp;gt;can&amp;lt;/u&amp;gt; exist under the &amp;quot;pluginhandler&amp;quot;-&#039;&#039;module&#039;&#039; are&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|lfo&lt;br /&gt;
|lfo&lt;br /&gt;
|-&lt;br /&gt;
|ahdsr&lt;br /&gt;
|ahdsr&lt;br /&gt;
|-&lt;br /&gt;
|numbermap&lt;br /&gt;
|map&lt;br /&gt;
|-&lt;br /&gt;
|multiple&lt;br /&gt;
|mlt&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The lfo-&#039;&#039;plugin module&#039;&#039; (&amp;quot;lfo&amp;quot;) ==&lt;br /&gt;
The &amp;quot;lfo&amp;quot;-&#039;&#039;plugin module&#039;&#039; works like regular [[wikipedia:Low-frequency_oscillation|low frequency oscillator]] in that it generates a given &#039;&#039;waveform&#039;&#039; with a given &#039;&#039;frequency&#039;&#039; at a certain &#039;&#039;amplitude&#039;&#039;. In the Ekdahl FAR the distinguishing factors are that besides the common &#039;&#039;frequency, amplitude&#039;&#039; and &#039;&#039;waveform&#039;&#039; parameters, it also requires the use of a &#039;&#039;update rate&#039;&#039; and &#039;&#039;target&#039;&#039; parameter. The &#039;&#039;update rate&#039;&#039; sets how often the current position of the LFO is sampled (aka how often it peeks in on where the LFO is in its waveform transition at the moment), and each time that happens, the &#039;&#039;target commands&#039;&#039; are outputted to the instrument.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example:&#039;&#039;&#039;&lt;br /&gt;
 Lets set the &#039;&#039;waveform&#039;&#039; to &amp;quot;triangle&amp;quot;, the &#039;&#039;amplitude&#039;&#039; to 65535 (max), the &#039;&#039;frequency&#039;&#039; to 1Hz (1 full waveform per second), the &#039;&#039;update rate&#039;&#039; to 10mS and the &#039;&#039;target&#039;&#039; to &amp;quot;bowingwheel.harmonicserieshandler.shift:lfoout&amp;quot;.&lt;br /&gt;
 &lt;br /&gt;
 The output of the LFO is always given in the variable &amp;quot;lfoout&amp;quot;, our &#039;&#039;target&#039;&#039; is set to &amp;quot;bowingwheel.harmonicserieshandler.shift&amp;quot; which controls the &#039;&#039;harmonic shift&#039;&#039; (pitchbend basically) of the &#039;&#039;bowing wheel&#039;&#039;.&lt;br /&gt;
 &lt;br /&gt;
 Since our update rate is set to every 10 milliseconds and our frequency is 1 Hertz the instrument will internally send 100 updates per second to the &#039;&#039;harmonic shift.&#039;&#039; Our amplitude is set to the maximum value and depending on the &amp;quot;harmonicserieshandler.shiftrange&amp;quot; this could give a smooth vibrato like sound or more of an experimental one with a wider range. If the modulation is too deep we can just adjust the amplitude of the LFO.&lt;br /&gt;
The &amp;quot;lfo&amp;quot;-&#039;&#039;plugin modules commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Sets the nickname of the LFO&lt;br /&gt;
|-&lt;br /&gt;
|enable&lt;br /&gt;
|en&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Disables / Enables the output of the &#039;&#039;target&#039;&#039; &#039;&#039;commands&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|target&lt;br /&gt;
|tg&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the command string to execute each update cycle, the string [lfoout] will be replaced with the current value&lt;br /&gt;
|-&lt;br /&gt;
|updaterate&lt;br /&gt;
|ur&lt;br /&gt;
|milliseconds&lt;br /&gt;
|Sets the frequency with which the &#039;&#039;target commands&#039;&#039; are executed. Limited by the global maximum as set in the plugin handler&lt;br /&gt;
|-&lt;br /&gt;
|waveform&lt;br /&gt;
|wf&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;sine|triangle|square|saw&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets the LFO waveform&lt;br /&gt;
|-&lt;br /&gt;
|frequency&lt;br /&gt;
|fq&lt;br /&gt;
|Hertz&lt;br /&gt;
|Sets the LFO frequency&lt;br /&gt;
|-&lt;br /&gt;
|amplitude&lt;br /&gt;
|amp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the LFO amplitude&lt;br /&gt;
|-&lt;br /&gt;
|delay&lt;br /&gt;
|dl&lt;br /&gt;
|0-65535 milliseconds&lt;br /&gt;
|Ramps up the amplitude of the output waveform from zero to full amplitude in the given time span&lt;br /&gt;
|-&lt;br /&gt;
|resetdelay&lt;br /&gt;
|rd&lt;br /&gt;
| -&lt;br /&gt;
|Resets the delay and starts the ramping of the waveform&lt;br /&gt;
|-&lt;br /&gt;
|resetwave&lt;br /&gt;
|rw&lt;br /&gt;
| -&lt;br /&gt;
|Resets the waveform from the start (sync)&lt;br /&gt;
|-&lt;br /&gt;
|bipolar&lt;br /&gt;
|bp&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets whether the waveform is bipolar (default) or positive only&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The ahdsr-&#039;&#039;plugin module&#039;&#039; (&amp;quot;ahdsr&amp;quot;) ==&lt;br /&gt;
The &amp;quot;ahdsr&amp;quot;-&#039;&#039;plugin module&#039;&#039; works like a standard [[wikipedia:ADSR|ADSR]] with the addition of a &amp;quot;hold&amp;quot;-period in between the &amp;quot;attack&amp;quot; and &amp;quot;decay&amp;quot; phase. The FAR specific items are the same as outlined in the &amp;quot;lfo&amp;quot;-&#039;&#039;plugin module&#039;&#039; with the exception of the &amp;quot;releasetarget&amp;quot; which triggers once the AHDSR reaches zero. This is useful for doing things like automatically putting the &#039;&#039;bowing jack&#039;&#039; in the &#039;&#039;rest&#039;&#039;-position when used on the &#039;&#039;pressure&#039;&#039; for instance. The &#039;&#039;commands&#039;&#039; for the &amp;quot;ahdsr&amp;quot;-&#039;&#039;plugin module&#039;&#039; are&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long command&lt;br /&gt;
!Short command&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Sets the nickname of the AHDSR&lt;br /&gt;
|-&lt;br /&gt;
|enable&lt;br /&gt;
|en&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Disables / Enables the output of the &#039;&#039;target commands&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|target&lt;br /&gt;
|tg&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the command string to execute each update cycle, the string [lfoout] will be replaced with the current value&lt;br /&gt;
|-&lt;br /&gt;
|updaterate&lt;br /&gt;
|ur&lt;br /&gt;
|milliseconds&lt;br /&gt;
|Sets the frequency with which the &#039;&#039;target commands&#039;&#039; are executed. Limited by the global maximum as set in the plugin handler&lt;br /&gt;
|-&lt;br /&gt;
|gate&lt;br /&gt;
|gt&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Gate signal, [1] initiates the &#039;&#039;attack&#039;&#039; phase and if it reaches its maximum value, &#039;&#039;holds&#039;&#039; for the time given. It then continues through the &#039;&#039;decay&#039;&#039; down to the &#039;&#039;sustain&#039;&#039; point. A [0] initiates the &#039;&#039;release&#039;&#039; from whatever point the ADSR is at&lt;br /&gt;
|-&lt;br /&gt;
|attack&lt;br /&gt;
|at&lt;br /&gt;
|milliseconds&lt;br /&gt;
|Attack time in milliseconds&lt;br /&gt;
|-&lt;br /&gt;
|hold&lt;br /&gt;
|hd&lt;br /&gt;
|milliseconds&lt;br /&gt;
|Hold time in milliseconds&lt;br /&gt;
|-&lt;br /&gt;
|decay&lt;br /&gt;
|dc&lt;br /&gt;
|milliseconds&lt;br /&gt;
|Decay time in milliseconds&lt;br /&gt;
|-&lt;br /&gt;
|sustain&lt;br /&gt;
|su&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sustain point in amplitude units&lt;br /&gt;
|-&lt;br /&gt;
|release&lt;br /&gt;
|re&lt;br /&gt;
|milliseconds&lt;br /&gt;
|Release time in milliseconds&lt;br /&gt;
|-&lt;br /&gt;
|releasetarget&lt;br /&gt;
|rt&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|&#039;&#039;Commands&#039;&#039; to execute once the release has hit zero&lt;br /&gt;
|-&lt;br /&gt;
|amplitude&lt;br /&gt;
|amp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Output amplitude&lt;br /&gt;
|-&lt;br /&gt;
|invert&lt;br /&gt;
|inv&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Inverts the results and gives negative values&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The number map-&#039;&#039;plugin module&#039;&#039; (&amp;quot;numbermap&amp;quot; / &amp;quot;nm&amp;quot;) ==&lt;br /&gt;
The &amp;quot;numbermap&amp;quot;-&#039;&#039;plugin module&#039;&#039; is used to &amp;quot;map&amp;quot; a incoming number to a different outgoing number. The idea of the &#039;&#039;Number Map&#039;&#039; is for instance to scale the volume of different overtones to be more even by modifying the &#039;&#039;bow pressure&#039;&#039; depending on what &#039;&#039;harmonic&#039;&#039; is being played. Another use case would be to group certain &#039;&#039;MIDI&#039;&#039; keys to address a certain string, and other &#039;&#039;MIDI&#039;&#039; keys addressing another, depending on the how well different strings can render certain tones / harmonics.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;Number Map&#039;&#039; first needs a data set of several points where each point contains &amp;quot;an input of x outputs y&amp;quot;. The &#039;&#039;Number Map&#039;&#039; is then &#039;&#039;triggered&#039;&#039; with a value of &#039;&#039;x&#039;&#039;. When this happens it looks in its database for anything mapped to &#039;&#039;x&#039;&#039;, if it finds it it outputs the &#039;&#039;commands&#039;&#039; set by the &#039;&#039;target&#039;&#039; but first replaces any occurances of the word &amp;quot;nmout&amp;quot; in the &#039;&#039;command string&#039;&#039; with the value of &#039;&#039;y&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;numbermap&amp;quot;-&#039;&#039;plugin modules&#039;&#039; commands&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Sets the nickname of the numbermap&lt;br /&gt;
|-&lt;br /&gt;
|target&lt;br /&gt;
|tg&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the &#039;&#039;commands&#039;&#039; to execute whenever the &amp;quot;numbermap&amp;quot;-&#039;&#039;plugin modules&#039;&#039; is triggered with a mapped value&lt;br /&gt;
|-&lt;br /&gt;
|data&lt;br /&gt;
|da&lt;br /&gt;
|(in:out)*&lt;br /&gt;
|Set the map data in any number of pairs of [in] returns [out]&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|in&lt;br /&gt;
|Removes the map with [in] if it exists&lt;br /&gt;
|-&lt;br /&gt;
|scale&lt;br /&gt;
|sc&lt;br /&gt;
|?&lt;br /&gt;
|Sets the overall scale of the Number Map&lt;br /&gt;
|-&lt;br /&gt;
|trigger&lt;br /&gt;
|tr&lt;br /&gt;
|in&lt;br /&gt;
|Triggers the &#039;&#039;targets&#039;&#039; with the &#039;&#039;out&#039;&#039; number mapped to &#039;&#039;in&#039;&#039; if found&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Knaadmin</name></author>
	</entry>
	<entry>
		<id>http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_reference_V1.1&amp;diff=1692</id>
		<title>The Ekdahl FAR - Command reference V1.1</title>
		<link rel="alternate" type="text/html" href="http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_reference_V1.1&amp;diff=1692"/>
		<updated>2026-06-17T12:03:11Z</updated>

		<summary type="html">&lt;p&gt;Knaadmin: /* The &amp;quot;bowingwheel&amp;quot;-module */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
The Ekdahl FAR V1.1 introduces the concept of &#039;&#039;modules&#039;&#039;. A &#039;&#039;module&#039;&#039; can contain any number of &#039;&#039;commands&#039;&#039; as well as other &#039;&#039;modules&#039;&#039;. Furthermore any number of &#039;&#039;modules&#039;&#039; of the same type can exist within a context, these are addressed using classic C-style array &#039;&#039;indexing&#039;&#039; with the help of brackets (&amp;quot;[ ]&amp;quot;). Extending on the classic usage, multiple &#039;&#039;indexes&#039;&#039; can be addressed simultaneously by either comma-separating the objects (&amp;quot;[0,3,4]&amp;quot;) and using &#039;&#039;ranges&#039;&#039; (&amp;quot;[3-6]&amp;quot;). &#039;&#039;Modules&#039;&#039; can be either &#039;&#039;internal&#039;&#039; or &#039;&#039;external&#039;&#039;, meaning that they may all physically exist within a single hardware object, or they can be be remote-controlled devices. From a user perspective this however makes no difference as they will appear the same.&lt;br /&gt;
&lt;br /&gt;
While all &#039;&#039;modules&#039;&#039; have their own set of &#039;&#039;commands&#039;&#039;, there are certain &#039;&#039;commands&#039;&#039; that all &#039;&#039;modules&#039;&#039; &amp;lt;u&amp;gt;must&amp;lt;/u&amp;gt; implement and can thus be accessed anywhere within the &#039;&#039;module hierarchy.&#039;&#039; There are also &#039;&#039;base commands&#039;&#039; that always exist within any given FAR ecosystem as well as product-specific &#039;&#039;base commands&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Ubiquitous commands ==&lt;br /&gt;
The &#039;&#039;module commands&#039;&#039; that are &amp;lt;u&amp;gt;required&amp;lt;/u&amp;gt; to be implemented in &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; &#039;&#039;modules&#039;&#039; and that can thus be accessed from anywhere are&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|list&lt;br /&gt;
|ls&lt;br /&gt;
|hidden/h:modules/m:commands/c:instances/i:instancecounts/ic:recursive/r&lt;br /&gt;
|Lists all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039; under the current module depending on the parameters given; &#039;hidden&#039; includes normally hidden &#039;&#039;commands&#039;&#039;, &#039;modules&#039; includes any &#039;&#039;submodules&#039;&#039;, &#039;commands&#039; shows &#039;&#039;commands&#039;&#039;, &#039;instances&#039; shows data for each individual instance of a &#039;&#039;module&#039;&#039;, &#039;instancecounts&#039; includes number of instances of each &#039;&#039;module&#039;&#039;, &#039;recursive&#039; lists all child &#039;&#039;modules&#039;&#039; / &#039;&#039;commands&#039;&#039;. No parameters defaults to showing all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039; recursively with instance counts. It doesn&#039;t show per-instance data or hidden commands.&lt;br /&gt;
|-&lt;br /&gt;
|help&lt;br /&gt;
|help&lt;br /&gt;
|recursive/r&lt;br /&gt;
|Shows a brief explanation of all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039;, shows the help for all &#039;&#039;submodules&#039;&#039; as well if &#039;recursive&#039;&lt;br /&gt;
|-&lt;br /&gt;
|dumpdata&lt;br /&gt;
|dump&lt;br /&gt;
|recursive/r&lt;br /&gt;
|Dumps all data saved for the current &#039;&#039;module&#039;&#039;, will list the data of all &#039;&#039;submodules&#039;&#039; as well if &#039;recursive&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Base commands ==&lt;br /&gt;
B&#039;&#039;ase commands&#039;&#039; are &#039;&#039;commands&#039;&#039; that always exist at the root in any implementation of the Ekdahl FAR.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|version&lt;br /&gt;
|ver&lt;br /&gt;
| -&lt;br /&gt;
|Gets the current firmware version&lt;br /&gt;
|-&lt;br /&gt;
|debugprint&lt;br /&gt;
|dp&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;command|usb|hardware|undefined|priority|error|inforequest|expressionparser|debug:1|0&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Turns on or off serial feedback for the given item&lt;br /&gt;
|-&lt;br /&gt;
|requestinfo&lt;br /&gt;
|rqi&lt;br /&gt;
|command&lt;br /&gt;
|Retrives any data saved for a &#039;&#039;command&#039;&#039;, if applicable&lt;br /&gt;
|-&lt;br /&gt;
|saveallparameters&lt;br /&gt;
|sap&lt;br /&gt;
| -&lt;br /&gt;
|Saves all avaliable parameters&lt;br /&gt;
|-&lt;br /&gt;
|loadallparameters&lt;br /&gt;
|lap&lt;br /&gt;
| -&lt;br /&gt;
|Loads all avaliable parameters&lt;br /&gt;
|-&lt;br /&gt;
|resetallparameters&lt;br /&gt;
|rap&lt;br /&gt;
| -&lt;br /&gt;
|Resets all saved parameters&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|rst&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;1|0&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Resets the Ekdahl FAR, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|nick&lt;br /&gt;
|nick&lt;br /&gt;
|name&lt;br /&gt;
|Sets the nickname of this unit&lt;br /&gt;
|-&lt;br /&gt;
|nooperation&lt;br /&gt;
|nop&lt;br /&gt;
| -&lt;br /&gt;
|Do absolutely, positively, nothing. Useful for testing and interfacing with computers, it&#039;s a good way to know that the unit is alive and responding since a &amp;quot;nop&amp;quot; is being returned as a response upon reception.&lt;br /&gt;
|-&lt;br /&gt;
|uservariable&lt;br /&gt;
|uv&lt;br /&gt;
|variable(0-9):value&lt;br /&gt;
|Set user variable 0-9 to &#039;value&#039;&lt;br /&gt;
|-&lt;br /&gt;
|expressionparserevaluate&lt;br /&gt;
|epev&lt;br /&gt;
|expression&lt;br /&gt;
|Evaluates an arithmetric expression and sends back the output, all variables and functions that can be used in any &#039;&#039;command string&#039;&#039; can also be used here. Useful for testing expressions.&lt;br /&gt;
|-&lt;br /&gt;
|ifequal&lt;br /&gt;
|ife&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] EQUALS [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring].&lt;br /&gt;
|-&lt;br /&gt;
|ifgreater&lt;br /&gt;
|ifg&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] &amp;gt; [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring]&lt;br /&gt;
|-&lt;br /&gt;
|ifless&lt;br /&gt;
|ifl&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] &amp;lt; [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring]&lt;br /&gt;
|-&lt;br /&gt;
|freeram&lt;br /&gt;
|ram&lt;br /&gt;
| -&lt;br /&gt;
|Shows free RAM memory&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The base also contains the following &#039;&#039;modules:&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|pluginhandler&lt;br /&gt;
|ph&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The Ekdahl FAR stand alone single string unit ==&lt;br /&gt;
The Ekdahl FAR stand-alone single string unit offers these &#039;&#039;commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|calibrateall&lt;br /&gt;
|ca&lt;br /&gt;
| -&lt;br /&gt;
|Performs all calibration routines on the selected bow, see below for routines performed&lt;br /&gt;
|-&lt;br /&gt;
|calibratebowspeed&lt;br /&gt;
|cbs&lt;br /&gt;
| -&lt;br /&gt;
|Finds the minimum and maximum bow speed of the selected bow&lt;br /&gt;
|-&lt;br /&gt;
|calibratebowpressure&lt;br /&gt;
|cbp&lt;br /&gt;
| -&lt;br /&gt;
|Finds the minimum and maximum bow pressure of the selected bow&lt;br /&gt;
|-&lt;br /&gt;
|calibratemute&lt;br /&gt;
|cmu&lt;br /&gt;
| -&lt;br /&gt;
|Calibrate mute settings&lt;br /&gt;
|-&lt;br /&gt;
|pickupstringfrequency&lt;br /&gt;
|psf&lt;br /&gt;
| -&lt;br /&gt;
|Returns the fundamental tone calculated from the current audio signal if apliccable&lt;br /&gt;
|-&lt;br /&gt;
|pickupaudiopeak&lt;br /&gt;
|pap&lt;br /&gt;
| -&lt;br /&gt;
|Returns the peak amplitude of the current audio signal&lt;br /&gt;
|-&lt;br /&gt;
|pickupaudiorms&lt;br /&gt;
|par&lt;br /&gt;
| -&lt;br /&gt;
|Returns the RMS amplitude of the current audio signal&lt;br /&gt;
|}&lt;br /&gt;
The Ekdahl FAR also contains the following &#039;&#039;modules&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|bowingwheel&lt;br /&gt;
|bw&lt;br /&gt;
|-&lt;br /&gt;
|mute&lt;br /&gt;
|mu&lt;br /&gt;
|-&lt;br /&gt;
|solenoid&lt;br /&gt;
|so&lt;br /&gt;
|-&lt;br /&gt;
|controlbox&lt;br /&gt;
|cb&lt;br /&gt;
|-&lt;br /&gt;
|midiconfigurationhandler&lt;br /&gt;
|mcf&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The bowing wheel-&#039;&#039;module&#039;&#039; (&amp;quot;bowingwheel&amp;quot; / &amp;quot;bw&amp;quot;) ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;Bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; contains everything needed to interface with a single &#039;&#039;bowing wheel&#039;&#039;. Each &#039;&#039;bowing wheel&#039;&#039; has its own harmonic series, pressure actuators and direct hardware interface. It contains the following &#039;&#039;commands&#039;&#039;.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|speedmode&lt;br /&gt;
|sm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Bow motor speed mode, 0 = Automatic and 1 = Manual. Automatic mode means that the bowing wheel will automatically turn off after the &#039;&#039;motor timeout&#039;&#039; has been reached after being put into rest mode&lt;br /&gt;
|-&lt;br /&gt;
|motortimeout&lt;br /&gt;
|mt&lt;br /&gt;
|ms&lt;br /&gt;
|Bow motor shutdown timeout after bow having been put into the rest position&lt;br /&gt;
|-&lt;br /&gt;
|pidenable&lt;br /&gt;
|pe&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets the bow PID on/off&lt;br /&gt;
|-&lt;br /&gt;
|motorfaultcommands&lt;br /&gt;
|mfc&lt;br /&gt;
|commands&lt;br /&gt;
|Commands to execute when a motor fault is tripped - !WARNING! Can ruin your instrument if changed&lt;br /&gt;
|-&lt;br /&gt;
|motoroverpowercommands&lt;br /&gt;
|moc&lt;br /&gt;
|commands&lt;br /&gt;
|Commands to execute when motor is over the power limit - !WARNING! Can ruin your instrument if changed&lt;br /&gt;
|}&lt;br /&gt;
The &#039;&#039;modules&#039;&#039; in the &amp;quot;Bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; are as follows&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|bowpressure&lt;br /&gt;
|bp&lt;br /&gt;
|-&lt;br /&gt;
|dcmotor&lt;br /&gt;
|dcm&lt;br /&gt;
|-&lt;br /&gt;
|pid&lt;br /&gt;
|pid&lt;br /&gt;
|-&lt;br /&gt;
|harmonicserieshandler&lt;br /&gt;
|hsh&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The bow pressure-&#039;&#039;module&#039;&#039; (&amp;quot;bowpressure&amp;quot; / &amp;quot;bp&amp;quot;) ==&lt;br /&gt;
The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; handles the &#039;&#039;pressure&#039;&#039; of the &#039;&#039;bowing wheel&#039;&#039; against the string. The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|baseline&lt;br /&gt;
|ba&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure baseline, modulation is added to this point upward. Typically this is set with a knob on the &#039;&#039;control box&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|modifier&lt;br /&gt;
|mo&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure modulation, added to the baseline&lt;br /&gt;
|-&lt;br /&gt;
|rest&lt;br /&gt;
|rs&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the bow pressure in the &#039;&#039;rest&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|engage&lt;br /&gt;
|en&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the bow pressure in the &#039;&#039;engage&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|stallpressure&lt;br /&gt;
|sp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure stall/maximum position, this parameter is set using &#039;&#039;hardware positioning&#039;&#039; and is used as the absolute maximum for baseline and modifier combiner&lt;br /&gt;
|-&lt;br /&gt;
|engagepressure&lt;br /&gt;
|ep&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure touch/minimum position, this parameter is set using &#039;&#039;hardware position&#039;&#039; and is used as the starting point for when both the baseline and modifier is set to zero&lt;br /&gt;
|-&lt;br /&gt;
|restpressure&lt;br /&gt;
|rp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure rest position, this parameter is set using &#039;&#039;hardware positioning&#039;&#039; and is typically set to a point just below the string where it does not touch at all. The purpose of this is because while the actual hardware might be able to make the bow go even lower, that position might be far enough from the string that once &#039;&#039;engaged&#039;&#039; the bow may have so far to travel that there is perceptible &#039;&#039;latency&#039;&#039;.&lt;br /&gt;
|-&lt;br /&gt;
|engagespeed&lt;br /&gt;
|es&lt;br /&gt;
|1- ~100&lt;br /&gt;
|Bow pressure movement speed when engaging or disengaging&lt;br /&gt;
|-&lt;br /&gt;
|modulationspeed&lt;br /&gt;
|ms&lt;br /&gt;
|0.1 - 10&lt;br /&gt;
|Bow pressure movement speed while engaged&lt;br /&gt;
|-&lt;br /&gt;
|hold&lt;br /&gt;
|hd&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets bow hold (infinite sustain) on/off, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|home&lt;br /&gt;
|hm&lt;br /&gt;
| -&lt;br /&gt;
|Homing bow, used at startup and in case of the bow loosing position&lt;br /&gt;
|-&lt;br /&gt;
|tmcinfo&lt;br /&gt;
|tmi&lt;br /&gt;
| -&lt;br /&gt;
|Request statistical information from the TMC2209 stepper motor driver&lt;br /&gt;
|}&lt;br /&gt;
Note that the &amp;quot;stall&amp;quot;, &amp;quot;engage&amp;quot; and &amp;quot;rest&amp;quot;-pressure positions mention something called &#039;&#039;hardware position&#039;&#039;. This means the entire available movement of the &#039;&#039;bowing jack&#039;&#039;. Because the very bottom and top end of the movement might not be musically useful and may even harm the instrument, the &amp;quot;baseline&amp;quot; and &amp;quot;modifier&amp;quot; commands &#039;&#039;parameter&#039;&#039;s are scaled depending on these settings.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;engage&amp;quot; and &amp;quot;modulation&amp;quot;-speed settings sets how fast the stepper motor that drives the &#039;&#039;pressure&#039;&#039; moves depending on whether the &#039;&#039;bowing jack&#039;&#039; is set to &#039;&#039;engage&#039;&#039; or not. The idea here is that while wanting to be able to minimize &#039;&#039;latency&#039;&#039; by &#039;&#039;engaging&#039;&#039; and &#039;&#039;disengaging&#039;&#039; from the string as quickly as possible, dynamic changes in the &#039;&#039;pressure&#039;&#039; while playing benefits from much smoother movements as the &#039;&#039;bowing wheel&#039;&#039; takes some time to catch up to varying amounts of friction.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; contains one or more of the following &#039;&#039;modules&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|actuatorhandler&lt;br /&gt;
|ah&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The actuator handler-&#039;&#039;module&#039;&#039; (&amp;quot;actuatorhandler&amp;quot; / &amp;quot;ah&amp;quot;) ==&lt;br /&gt;
The concept of &amp;quot;actuators&amp;quot; came up as it is possible to have &#039;&#039;bowing wheels&#039;&#039; of different sizes and wanting to be able to switch quickly in between them, perhaps during mid-performance. Because a differently sized wheel will require different values for the above mentioned &amp;quot;stall&amp;quot;, &amp;quot;engage&amp;quot; and &amp;quot;reset&amp;quot;-&#039;&#039;pressure&#039;&#039;, each &#039;&#039;actuator&#039;&#039; stores these values. Instead of having to manually change the previously mentioned values, simply selecting a new &#039;&#039;actuator&#039;&#039; will automatically load the values. The &amp;quot;actuatorhandler&amp;quot;-&#039;&#039;module&#039;&#039; is the handler of one or more &amp;quot;actuator&amp;quot;-&#039;&#039;modules&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;commands&#039;&#039; of the &amp;quot;acuatorhandler&amp;quot;-&#039;&#039;module&#039;&#039; are as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|add&lt;br /&gt;
|a&lt;br /&gt;
|(name):(rest:engage:stall)&lt;br /&gt;
|Add new actuator with the given name and parameters&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|actuatornumber&lt;br /&gt;
|Remove bow actuator [actuatornumber]&lt;br /&gt;
|-&lt;br /&gt;
|count&lt;br /&gt;
|c&lt;br /&gt;
| -&lt;br /&gt;
|Returns the amount of saved bow actuators&lt;br /&gt;
|}&lt;br /&gt;
The &amp;quot;actuatorhandler&amp;quot;-&#039;&#039;module&#039;&#039; contains one or more of&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|actuator&lt;br /&gt;
|ac&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The actuator-&#039;&#039;module&#039;&#039; (&amp;quot;actuator&amp;quot; / &amp;quot;ac&amp;quot;) ==&lt;br /&gt;
The &amp;quot;actuator&amp;quot;-&#039;&#039;module&#039;&#039; contains the following commands&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|[index]&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|Selects the given actuator&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Sets the actuator name&lt;br /&gt;
|-&lt;br /&gt;
|data&lt;br /&gt;
|da&lt;br /&gt;
|name:rest:engage:stall&lt;br /&gt;
|Sets the actuator name, rest, engage and stall &#039;&#039;pressure&#039;&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The DC motor-&#039;&#039;module&#039;&#039; (&amp;quot;dcmotor&amp;quot; / &amp;quot;dcm&amp;quot;) ==&lt;br /&gt;
The &amp;quot;dcmotor&amp;quot;-&#039;&#039;module&#039;&#039; handles the direct &amp;lt;u&amp;gt;raw&amp;lt;/u&amp;gt; control of the &#039;&#039;bowing motor&#039;&#039; and handles the reporting back of the current speed. It has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|run&lt;br /&gt;
|ru&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Turns the motor off/on&lt;br /&gt;
|-&lt;br /&gt;
|pwm&lt;br /&gt;
|pw&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor direct power in 16-bit PWM values, requires that the &#039;&#039;PID&#039;&#039; is turned off&lt;br /&gt;
|-&lt;br /&gt;
|voltage&lt;br /&gt;
|vo&lt;br /&gt;
|~2 - 10V&lt;br /&gt;
|Sets the voltage of the regulator powering the motor. Changes here can make the motor more responsive to certain frequencies but will also affect how well the &#039;&#039;PID&#039;&#039; works. !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|current&lt;br /&gt;
|cu&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor reported current use&lt;br /&gt;
|-&lt;br /&gt;
|currentlimit&lt;br /&gt;
|cl&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor current limit (A)- !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|powerlimit&lt;br /&gt;
|pl&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor power limit (W) - !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|frequency&lt;br /&gt;
|fq&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor reported frequency&lt;br /&gt;
|-&lt;br /&gt;
|emergencystop&lt;br /&gt;
|es&lt;br /&gt;
|ms (0-65535)&lt;br /&gt;
|Immediately stops the bowing motor and doesn&#039;t allow it to start again until the cool down period given in the first argument has lapsed (milliseconds)&lt;br /&gt;
|-&lt;br /&gt;
|minpwm&lt;br /&gt;
|ip&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor minimum PWM (for calibration)&lt;br /&gt;
|-&lt;br /&gt;
|maxpwm&lt;br /&gt;
|xp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor maximum PWM (for calibration)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The PID controller-&#039;&#039;module&#039;&#039; (&amp;quot;pid&amp;quot;) ==&lt;br /&gt;
The &amp;quot;pidcontroller&amp;quot;-&#039;&#039;module&#039;&#039; is responsible for keeping the &amp;quot;dcmotor&amp;quot;-&#039;&#039;module&#039;&#039; at a certain frequency (given in Hertz). It takes the output of the motor frequency measurement and feeds it a PWM value that tries to make the speed constant regardless of the friction that the motor is enduring. To learn more about PID Controllers please see this [[wikipedia:PID_controller|wikipedia article]]. The &#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|targetfrequency&lt;br /&gt;
|tf&lt;br /&gt;
|hertz&lt;br /&gt;
|Sets the PID target frequency&lt;br /&gt;
|-&lt;br /&gt;
|ki&lt;br /&gt;
|ki&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Ki parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|kp&lt;br /&gt;
|kp&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Kp parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|kd&lt;br /&gt;
|kd&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Kd parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|integratorerror&lt;br /&gt;
|ie&lt;br /&gt;
|float&lt;br /&gt;
|Sets the lower threshold of error values for the PID integrator to ignore&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|re&lt;br /&gt;
| -&lt;br /&gt;
|Resets the PID integrator and derivative&lt;br /&gt;
|-&lt;br /&gt;
|maxerror&lt;br /&gt;
|xe&lt;br /&gt;
|float&lt;br /&gt;
|Maximum error to correct in each PID loop, essentially sets acceleration&lt;br /&gt;
|-&lt;br /&gt;
|peakerror&lt;br /&gt;
|pe&lt;br /&gt;
|float&lt;br /&gt;
|Get latest PID peak error&lt;br /&gt;
|-&lt;br /&gt;
|motorspeedmax&lt;br /&gt;
|msx&lt;br /&gt;
|Hertz&lt;br /&gt;
|Bow motor maximum speed limit&lt;br /&gt;
|-&lt;br /&gt;
|motorspeedmin&lt;br /&gt;
|msi&lt;br /&gt;
|Hertz&lt;br /&gt;
|Bow motor minimum speed limit&lt;br /&gt;
|-&lt;br /&gt;
|measuretimetotarget&lt;br /&gt;
|mtt&lt;br /&gt;
|Hertz&lt;br /&gt;
|Measure the time it takes to change from the current frequency to the target frequency, for testing purposes&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The harmonic series handler&amp;quot;-&#039;&#039;module&#039;&#039; (&amp;quot;harmonicserieshandler&amp;quot; / &amp;quot;hsh&amp;quot;) ==&lt;br /&gt;
The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; is responsible for sending frequency data to the &amp;quot;pid&amp;quot;-&#039;&#039;module&#039;&#039;. It handles calculating the correct frequency of the &#039;&#039;bowing wheel&#039;&#039; according to the selected &#039;&#039;harmonic&#039;&#039; and &#039;&#039;harmonic shift&#039;&#039; per the currently selected &#039;&#039;harmonic series&#039;&#039;. The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|fundamental&lt;br /&gt;
|fu&lt;br /&gt;
|Hertz&lt;br /&gt;
|The fundamental frequency of the string, all harmonics are calculated from this number&lt;br /&gt;
|-&lt;br /&gt;
|harmonic&lt;br /&gt;
|h&lt;br /&gt;
|int&lt;br /&gt;
|Selects the harmonic number to set the &#039;&#039;bowing wheel&#039;&#039; to. A ratio is taken from the given &#039;&#039;harmonic&#039;&#039; in the current &#039;&#039;harmonic series&#039;&#039;, the ratio is then multiplied by the &#039;&#039;fundamental frequency&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|harmonicadd&lt;br /&gt;
|ha&lt;br /&gt;
|int&lt;br /&gt;
|This number is added to the current harmonic&lt;br /&gt;
|-&lt;br /&gt;
|harmonicbase&lt;br /&gt;
|hb&lt;br /&gt;
|int&lt;br /&gt;
|Same as harmonic but where the harmonic number is based on a MIDI note given by basenote&lt;br /&gt;
|-&lt;br /&gt;
|basenote&lt;br /&gt;
|bn&lt;br /&gt;
|0-127&lt;br /&gt;
|Sets the MIDI base note of the &#039;&#039;bowing wheel&#039;&#039;, used in conjunction with &amp;quot;harmonicbase&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|shift&lt;br /&gt;
|sh&lt;br /&gt;
| -32767 - 32767&lt;br /&gt;
|Sets shift from the currently playing harmonic where 32767 equals the entire harmonic shift range shifted up&lt;br /&gt;
|-&lt;br /&gt;
|shiftrange&lt;br /&gt;
|sr&lt;br /&gt;
|0-36&lt;br /&gt;
|Set the number of harmonic numbers that constitutes an entire harmonic shift&lt;br /&gt;
|-&lt;br /&gt;
|shift5&lt;br /&gt;
|sh5&lt;br /&gt;
| -32767 - 32767&lt;br /&gt;
|Sets the shift from the currently playing harmonic over 5 octaves where 32767 equals 5 octaves shift up from the fundamental&lt;br /&gt;
|-&lt;br /&gt;
|add&lt;br /&gt;
|a&lt;br /&gt;
|(name):(ratios)&lt;br /&gt;
|Add a new series with the given name and parameters&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|series&lt;br /&gt;
|Remove the series given and shift any series accordingly. Cannot remove all series&lt;br /&gt;
|-&lt;br /&gt;
|count&lt;br /&gt;
|c&lt;br /&gt;
| -&lt;br /&gt;
|Returns the number of harmonic series in the list and their IDs&lt;br /&gt;
|}&lt;br /&gt;
The &amp;quot;harmonicserieshandler&amp;quot;-module contains at the very least ONE harmonic series, by default it contains two: one for equal temperament and one for just intonation. The current series can be selected by simply indexing the &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; without a &#039;&#039;command&#039;&#039;, e.g. &amp;quot;harmonicserieshandler.harmonicseries[1]&amp;quot;. To be consistent, these are the &#039;&#039;modules&#039;&#039; in the &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|harmonicseries&lt;br /&gt;
|hs&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The harmonic series-&#039;&#039;module&#039;&#039; (&amp;quot;harmonicseries&amp;quot; / &amp;quot;hs&amp;quot;) ==&lt;br /&gt;
The &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; contains any number of &#039;&#039;ratios&#039;&#039; that comprises a scale, ratios are given in a standard format where a ratio of &amp;quot;1&amp;quot; is equal to the fundamental, &amp;quot;2&amp;quot; would be one octave up etc. A standard &#039;&#039;harmonic series&#039;&#039; contains 12 ratios following a just intonation scheme. The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; will automatically adapt to the currently selected &#039;&#039;harmonic series&#039;&#039; length, whether it&#039;s a standard 12-tone scale, some kinda 3-tone scale or a full on bananas 53-tone scale. The &#039;&#039;commands&#039;&#039; of the &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; is as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|[index]&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
|Sets the currently selected &#039;&#039;harmonic Series&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Sets the name of the &#039;&#039;harmonic series&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|data&lt;br /&gt;
|da&lt;br /&gt;
|name:ratios&lt;br /&gt;
|Gets / sets all data for the &#039;&#039;harmonic series&#039;&#039; in the given slot with an arbitrary &#039;&#039;name&#039;&#039; as the first &#039;&#039;parameter&#039;&#039;. The length of the series is simply set to the amount of ratios given&lt;br /&gt;
|-&lt;br /&gt;
|ratio&lt;br /&gt;
|r&lt;br /&gt;
|harmonic:ratio&lt;br /&gt;
|Sets the ratio of the given harmonic in current &#039;&#039;harmonic series&#039;&#039;, will increase the list size if needed to address the harmonic&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|harmonic&lt;br /&gt;
|Remove the harmonic ratio given in the current series and shift any ratios accordingly. Cannot remove all ratios&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The mute-&#039;&#039;module&#039;&#039; (&amp;quot;mute&amp;quot; / &amp;quot;mu&amp;quot;) ==&lt;br /&gt;
The &amp;quot;mute&amp;quot;-&#039;&#039;module&#039;&#039; works very similarly to the &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; in that it controls a stepper motor with some software limits in place in order to press the mute against the string. The &#039;&#039;commands&#039;&#039; are as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|setposition&lt;br /&gt;
|sp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set mute position&lt;br /&gt;
|-&lt;br /&gt;
|fullmute&lt;br /&gt;
|fm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the mute in &#039;&#039;full mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|halfmute&lt;br /&gt;
|hm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the mute in &#039;&#039;half mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|rest&lt;br /&gt;
|rs&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Put the mute in the &#039;&#039;rest&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|savefull&lt;br /&gt;
|sf&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Save the current mute position as the &#039;&#039;full mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|savehalf&lt;br /&gt;
|sh&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Save the current mute position as the &#039;&#039;half mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|saverest&lt;br /&gt;
|sr&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Save the current mute position as the &#039;&#039;rest&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|fullmuteposition&lt;br /&gt;
|fmp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;full mute&#039;&#039; position according to the &#039;&#039;hardware position&#039;&#039; given&lt;br /&gt;
|-&lt;br /&gt;
|halfmuteposition&lt;br /&gt;
|hmp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;half mute&#039;&#039; position according to the &#039;&#039;hardware position&#039;&#039; given&lt;br /&gt;
|-&lt;br /&gt;
|restposition&lt;br /&gt;
|rp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;rest&#039;&#039; position according to the &#039;&#039;hardware position&#039;&#039; given&lt;br /&gt;
|-&lt;br /&gt;
|sustain&lt;br /&gt;
|su&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets the sustain off/on, this will keep the mute in the &#039;&#039;rest&#039;&#039; position even if a &amp;quot;fullmute&amp;quot;-&#039;&#039;command&#039;&#039; is given, lasts until &amp;quot;sustain&amp;quot; is set to &amp;quot;0&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
|backoff&lt;br /&gt;
|bo&lt;br /&gt;
|0-65535&lt;br /&gt;
|Setting the time that the mute stays in the mutefullmute position before automatically going into rest, set in mS. A value of &amp;quot;0&amp;quot; disables backoff. This is used because if the mute is not backing off until something is attempted to be played, the backing-off time will either introduce &#039;&#039;latency&#039;&#039; or the string will be initially partially muted&lt;br /&gt;
|-&lt;br /&gt;
|home&lt;br /&gt;
|hm&lt;br /&gt;
| -&lt;br /&gt;
|Home mute, used during initialization and if the mute were to loose position&lt;br /&gt;
|-&lt;br /&gt;
|hardwareposition&lt;br /&gt;
|hwp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;hardware position&#039;&#039; of the mute instead of scaling it over the &#039;&#039;full mute&#039;&#039; and &#039;&#039;rest&#039;&#039; positions. Mainly used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|completetask&lt;br /&gt;
|cpt&lt;br /&gt;
| -&lt;br /&gt;
|Requests a callback when the current operation is finished. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|autocorrect&lt;br /&gt;
|ac&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Enables auto correct positioning that uses the homing sensor to correct positioning on the fly. EXPERIMENTAL&lt;br /&gt;
|-&lt;br /&gt;
|homingsensed&lt;br /&gt;
|hms&lt;br /&gt;
| -&lt;br /&gt;
|Requests whether the homing sensor is currently active or not. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|movedirection&lt;br /&gt;
|md&lt;br /&gt;
| -&lt;br /&gt;
|Requests the current direction of movement (0 Forward, 1 Reverse). Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|currentstep&lt;br /&gt;
|cs&lt;br /&gt;
| -&lt;br /&gt;
|Requests the current step. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|homingpoint&lt;br /&gt;
|hmp&lt;br /&gt;
|edgedirection&lt;br /&gt;
|Requests the given homing point. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|homingstage&lt;br /&gt;
|hms&lt;br /&gt;
| -&lt;br /&gt;
|Requests the current homing stage (UNHOMED, HOMED, FIRSTHOMINGRISING, SECONDHOMINGFALLING, SECONDHOMINGRISING, FIRSTHOMINGFALLING, MOVEPASTHOMESWITCH, MOVETOHOMESWITCH, GOTOOFFSET). Only used internally by other &#039;&#039;modules.&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|tmcinfo&lt;br /&gt;
|tmi&lt;br /&gt;
| -&lt;br /&gt;
|Request statistical information from the TMC2209 stepper motor driver&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The solenoid-&#039;&#039;module&#039;&#039; (&amp;quot;solenoid&amp;quot; / &amp;quot;so&amp;quot;) ==&lt;br /&gt;
The &amp;quot;solenoid&amp;quot;-&#039;&#039;module&#039;&#039; currently controls the &#039;&#039;hammer&#039;&#039; of the Ekdahl FAR. Due to the fact that the very same &#039;&#039;module&#039;&#039; could be used for anything that uses a striking &#039;&#039;solenoid&#039;&#039; it was named as such. It has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|engage&lt;br /&gt;
|en&lt;br /&gt;
|0-65535&lt;br /&gt;
|Engages the solenoid using the first parameter as the force&lt;br /&gt;
|-&lt;br /&gt;
|rest&lt;br /&gt;
|rs&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Forces the solenoid to its rest position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|maxforce&lt;br /&gt;
|xf&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set solenoid maximum usable force&lt;br /&gt;
|-&lt;br /&gt;
|minforce&lt;br /&gt;
|if&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set solenoid minimum usable force&lt;br /&gt;
|-&lt;br /&gt;
|forcemultiplier&lt;br /&gt;
|fm&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set solenoid force multiplier, useful for scaling of all incoming &amp;quot;engage&amp;quot;-&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|engageduration&lt;br /&gt;
|ed&lt;br /&gt;
|uS&lt;br /&gt;
|Sets the duration of the solenoid hit in uS, if a value of 0 is set the solenoid will not disengage until a rest command has been given. WARNING!! HAVING THE SOLENOID ON FOR A SPAN OF SECONDS COULD DESTROY THE CIRCUITRY!!&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The control box-&#039;&#039;module&#039;&#039; (&amp;quot;controlbox&amp;quot; / &amp;quot;cb&amp;quot;) ==&lt;br /&gt;
The &amp;quot;controlbox&amp;quot;-&#039;&#039;module&#039;&#039; communicates with an external &#039;&#039;control box&#039;&#039; and will issue associated &#039;&#039;commands&#039;&#039; whenever new values are read on the ADC-converters. It handles averaging and does some noise-cancellation functions on the values as well. The &#039;&#039;commands&#039;&#039; are:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|harmonic&lt;br /&gt;
|har&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the harmonic knob or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|harmonicshift&lt;br /&gt;
|has&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the harmonic shift modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|finetune&lt;br /&gt;
|fin&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the fine tune knob changes&lt;br /&gt;
|-&lt;br /&gt;
|pressure&lt;br /&gt;
|pre&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the pressure knob or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|mute&lt;br /&gt;
|mut&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the mute knob or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|hammerscale&lt;br /&gt;
|hms&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the hammer scale knob changes&lt;br /&gt;
|-&lt;br /&gt;
|gate&lt;br /&gt;
|gt&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the gate switch or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|hammertrig&lt;br /&gt;
|hmt&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the hammer trigger modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|controldefaults&lt;br /&gt;
|cde&lt;br /&gt;
| -&lt;br /&gt;
|Reverts all ADC command strings to default values&lt;br /&gt;
|-&lt;br /&gt;
|datareturn&lt;br /&gt;
|dr&lt;br /&gt;
|channel:value&lt;br /&gt;
|Sent when a new value is presented on one of the ADC channels, cannot be invoked. Triggers the commands associated with the channel&lt;br /&gt;
|-&lt;br /&gt;
|adcsetting&lt;br /&gt;
|adcs&lt;br /&gt;
|channel : averages : interrupterrorthreshold : continuouserrorthreshold : continuoustimeout&lt;br /&gt;
|Sets ADC settings for a given channel. Averages are the number of samples to average, interruptthreshold is how much the value must change in order to issue a new value change event. continuousthreshold is how much the value must change when a previous change has already been recorded within the timespan of continuoustimeout&lt;br /&gt;
|-&lt;br /&gt;
|testadclatency&lt;br /&gt;
|tal&lt;br /&gt;
|0-65535&lt;br /&gt;
|Start a ADC latency test&lt;br /&gt;
|-&lt;br /&gt;
|testadclatencyreturn&lt;br /&gt;
|talr&lt;br /&gt;
| -&lt;br /&gt;
|Return from latency test&lt;br /&gt;
|-&lt;br /&gt;
|testadcminmax&lt;br /&gt;
|tix&lt;br /&gt;
|channel&lt;br /&gt;
|Test min/max value for a given channel and resets the counter&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The midi configuration handler-&#039;&#039;module&#039;&#039; (&amp;quot;midiconfigurationhandler&amp;quot; / &amp;quot;mcf&amp;quot;) ==&lt;br /&gt;
The &amp;quot;midiconfigurationhandler&amp;quot;-&#039;&#039;module&#039;&#039; handles a number of &amp;quot;midiconfiguration&amp;quot;-&#039;&#039;modules&#039;&#039;. It has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|allnotesoff&lt;br /&gt;
|ano&lt;br /&gt;
| -&lt;br /&gt;
|Clears the entire buffer of MIDI notes held&lt;br /&gt;
|-&lt;br /&gt;
|add&lt;br /&gt;
|a&lt;br /&gt;
|name&lt;br /&gt;
|Adds a new MIDI configuration with the given name&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|int&lt;br /&gt;
|Remove the specified MIDI configuration&lt;br /&gt;
|-&lt;br /&gt;
|count&lt;br /&gt;
|c&lt;br /&gt;
| -&lt;br /&gt;
|Returns the number of MIDI configurations&lt;br /&gt;
|}&lt;br /&gt;
It contains one or more of the following&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|midiconfiguration&lt;br /&gt;
|mc&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;midiconfiguration&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
A &amp;quot;midiconfiguration&amp;quot;-&#039;&#039;module&#039;&#039; handles the reception of &#039;&#039;MIDI messages&#039;&#039; and will output the associated &#039;&#039;commands&#039;&#039; to the instrument internally. The commands are as follows&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|[index]&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
|Sets the currently selected MIDI configuration&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Set the name of the MIDI configuration&lt;br /&gt;
|-&lt;br /&gt;
|noteon&lt;br /&gt;
|non&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Note On event&lt;br /&gt;
|-&lt;br /&gt;
|noteoff&lt;br /&gt;
|nof&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Note Off event&lt;br /&gt;
|-&lt;br /&gt;
|polyaftertouch&lt;br /&gt;
|pat&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Polyphonic after touch event&lt;br /&gt;
|-&lt;br /&gt;
|channelaftertouch&lt;br /&gt;
|cat&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Channel after touch event&lt;br /&gt;
|-&lt;br /&gt;
|pitchbend&lt;br /&gt;
|pb&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Pitch bend event&lt;br /&gt;
|-&lt;br /&gt;
|programchange&lt;br /&gt;
|pc&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Program change event&lt;br /&gt;
|-&lt;br /&gt;
|continuouscontrollerdata&lt;br /&gt;
|ccd&lt;br /&gt;
|controllernuber:&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Continuous controller event with the given [&#039;&#039;controllernumber&#039;&#039;]&lt;br /&gt;
|-&lt;br /&gt;
|removecc&lt;br /&gt;
|rmc&lt;br /&gt;
|controllernuber&lt;br /&gt;
|Removes the entry associated with the MIDI continuous controller even &#039;&#039;controllernumber&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|defaults&lt;br /&gt;
|d&lt;br /&gt;
| -&lt;br /&gt;
|Reverts the current configuration to default &#039;&#039;commands&#039;&#039;, values and CCs&lt;br /&gt;
|-&lt;br /&gt;
|receivechannel&lt;br /&gt;
|rc&lt;br /&gt;
|channel&lt;br /&gt;
|Sets the MIDI receive channel of the current configuration. 1-16 sets specific channel, any other value for OMNI&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;pluginhandler&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The Ekdahl FAR allows for &#039;&#039;plugins&#039;&#039;. These are &#039;&#039;modules&#039;&#039; that can trigger certain &#039;&#039;command strings&#039;&#039; to be executed either periodically or triggered by an incoming &#039;&#039;command&#039;&#039;. Further explanation of the given &#039;&#039;plugins&#039;&#039; is given below. The various &#039;&#039;plugins&#039;&#039; are handled by the &amp;quot;pluginhandler&amp;quot;-&#039;&#039;module&#039;&#039;, the different &#039;&#039;plugin modules&#039;&#039; are identified by their own unique &#039;&#039;ID&#039;&#039;. The &amp;quot;pluginhandler&amp;quot;-&#039;&#039;module&#039;&#039; it has the following &#039;&#039;commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|add&lt;br /&gt;
|a&lt;br /&gt;
|pluginid&lt;br /&gt;
|Add plugin with the given ID&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|pluginid:index&lt;br /&gt;
|Remove plugin with the given ID and index&lt;br /&gt;
|-&lt;br /&gt;
|count&lt;br /&gt;
|c&lt;br /&gt;
|(pluginid)&lt;br /&gt;
|Return the number of plugins of the given type, if none is given it returns all plugins&lt;br /&gt;
|}&lt;br /&gt;
The number of available &#039;&#039;plugins&#039;&#039; will differ from time to time as the &#039;&#039;plugin system&#039;&#039; has been purposefully designed to allow for anyone to write and add their own &#039;&#039;plugins&#039;&#039;. As of the current writing (2026-06-14) the number of &amp;lt;u&amp;gt;possible&amp;lt;/u&amp;gt; &#039;&#039;plugin modules&#039;&#039; that &amp;lt;u&amp;gt;can&amp;lt;/u&amp;gt; exist under the &amp;quot;pluginhandler&amp;quot;-&#039;&#039;module&#039;&#039; are&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|lfo&lt;br /&gt;
|lfo&lt;br /&gt;
|-&lt;br /&gt;
|ahdsr&lt;br /&gt;
|ahdsr&lt;br /&gt;
|-&lt;br /&gt;
|numbermap&lt;br /&gt;
|map&lt;br /&gt;
|-&lt;br /&gt;
|multiple&lt;br /&gt;
|mlt&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;lfo&amp;quot;-&#039;&#039;plugin module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;lfo&amp;quot;-&#039;&#039;plugin module&#039;&#039; works like regular [[wikipedia:Low-frequency_oscillation|low frequency oscillator]] in that it generates a given &#039;&#039;waveform&#039;&#039; with a given &#039;&#039;frequency&#039;&#039; at a certain &#039;&#039;amplitude&#039;&#039;. In the Ekdahl FAR the distinguishing factors are that besides the common &#039;&#039;frequency, amplitude&#039;&#039; and &#039;&#039;waveform&#039;&#039; parameters, it also requires the use of a &#039;&#039;update rate&#039;&#039; and &#039;&#039;target&#039;&#039; parameter. The &#039;&#039;update rate&#039;&#039; sets how often the current position of the LFO is sampled (aka how often it peeks in on where the LFO is in its waveform transition at the moment), and each time that happens, the &#039;&#039;target commands&#039;&#039; are outputted to the instrument.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example:&#039;&#039;&#039;&lt;br /&gt;
 Lets set the &#039;&#039;waveform&#039;&#039; to &amp;quot;triangle&amp;quot;, the &#039;&#039;amplitude&#039;&#039; to 65535 (max), the &#039;&#039;frequency&#039;&#039; to 1Hz (1 full waveform per second), the &#039;&#039;update rate&#039;&#039; to 10mS and the &#039;&#039;target&#039;&#039; to &amp;quot;bowingwheel.harmonicserieshandler.shift:lfoout&amp;quot;.&lt;br /&gt;
 &lt;br /&gt;
 The output of the LFO is always given in the variable &amp;quot;lfoout&amp;quot;, our &#039;&#039;target&#039;&#039; is set to &amp;quot;bowingwheel.harmonicserieshandler.shift&amp;quot; which controls the &#039;&#039;harmonic shift&#039;&#039; (pitchbend basically) of the &#039;&#039;bowing wheel&#039;&#039;.&lt;br /&gt;
 &lt;br /&gt;
 Since our update rate is set to every 10 milliseconds and our frequency is 1 Hertz the instrument will internally send 100 updates per second to the &#039;&#039;harmonic shift.&#039;&#039; Our amplitude is set to the maximum value and depending on the &amp;quot;harmonicserieshandler.shiftrange&amp;quot; this could give a smooth vibrato like sound or more of an experimental one with a wider range. If the modulation is too deep we can just adjust the amplitude of the LFO.&lt;br /&gt;
The &amp;quot;lfo&amp;quot;-&#039;&#039;plugin modules commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Sets the nickname of the LFO&lt;br /&gt;
|-&lt;br /&gt;
|enable&lt;br /&gt;
|en&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Disables / Enables the output of the &#039;&#039;target&#039;&#039; &#039;&#039;commands&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|target&lt;br /&gt;
|tg&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the command string to execute each update cycle, the string [lfoout] will be replaced with the current value&lt;br /&gt;
|-&lt;br /&gt;
|updaterate&lt;br /&gt;
|ur&lt;br /&gt;
|milliseconds&lt;br /&gt;
|Sets the frequency with which the &#039;&#039;target commands&#039;&#039; are executed. Limited by the global maximum as set in the plugin handler&lt;br /&gt;
|-&lt;br /&gt;
|waveform&lt;br /&gt;
|wf&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;sine|triangle|square|saw&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets the LFO waveform&lt;br /&gt;
|-&lt;br /&gt;
|frequency&lt;br /&gt;
|fq&lt;br /&gt;
|Hertz&lt;br /&gt;
|Sets the LFO frequency&lt;br /&gt;
|-&lt;br /&gt;
|amplitude&lt;br /&gt;
|amp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the LFO amplitude&lt;br /&gt;
|-&lt;br /&gt;
|delay&lt;br /&gt;
|dl&lt;br /&gt;
|0-65535 milliseconds&lt;br /&gt;
|Ramps up the amplitude of the output waveform from zero to full amplitude in the given time span&lt;br /&gt;
|-&lt;br /&gt;
|resetdelay&lt;br /&gt;
|rd&lt;br /&gt;
| -&lt;br /&gt;
|Resets the delay and starts the ramping of the waveform&lt;br /&gt;
|-&lt;br /&gt;
|resetwave&lt;br /&gt;
|rw&lt;br /&gt;
| -&lt;br /&gt;
|Resets the waveform from the start (sync)&lt;br /&gt;
|-&lt;br /&gt;
|bipolar&lt;br /&gt;
|bp&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets whether the waveform is bipolar (default) or positive only&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;ahdsr&amp;quot;-&#039;&#039;plugin module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;ahdsr&amp;quot;-&#039;&#039;plugin module&#039;&#039; works like a standard [[wikipedia:ADSR|ADSR]] with the addition of a &amp;quot;hold&amp;quot;-period in between the &amp;quot;attack&amp;quot; and &amp;quot;decay&amp;quot; phase. The FAR specific items are the same as outlined in the &amp;quot;lfo&amp;quot;-&#039;&#039;plugin module&#039;&#039; with the exception of the &amp;quot;releasetarget&amp;quot; which triggers once the AHDSR reaches zero. This is useful for doing things like automatically putting the &#039;&#039;bowing jack&#039;&#039; in the &#039;&#039;rest&#039;&#039;-position when used on the &#039;&#039;pressure&#039;&#039; for instance. The &#039;&#039;commands&#039;&#039; for the &amp;quot;ahdsr&amp;quot;-&#039;&#039;plugin module&#039;&#039; are&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long command&lt;br /&gt;
!Short command&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Sets the nickname of the AHDSR&lt;br /&gt;
|-&lt;br /&gt;
|enable&lt;br /&gt;
|en&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Disables / Enables the output of the &#039;&#039;target commands&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|target&lt;br /&gt;
|tg&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the command string to execute each update cycle, the string [lfoout] will be replaced with the current value&lt;br /&gt;
|-&lt;br /&gt;
|updaterate&lt;br /&gt;
|ur&lt;br /&gt;
|milliseconds&lt;br /&gt;
|Sets the frequency with which the &#039;&#039;target commands&#039;&#039; are executed. Limited by the global maximum as set in the plugin handler&lt;br /&gt;
|-&lt;br /&gt;
|gate&lt;br /&gt;
|gt&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Gate signal, [1] initiates the &#039;&#039;attack&#039;&#039; phase and if it reaches its maximum value, &#039;&#039;holds&#039;&#039; for the time given. It then continues through the &#039;&#039;decay&#039;&#039; down to the &#039;&#039;sustain&#039;&#039; point. A [0] initiates the &#039;&#039;release&#039;&#039; from whatever point the ADSR is at&lt;br /&gt;
|-&lt;br /&gt;
|attack&lt;br /&gt;
|at&lt;br /&gt;
|milliseconds&lt;br /&gt;
|Attack time in milliseconds&lt;br /&gt;
|-&lt;br /&gt;
|hold&lt;br /&gt;
|hd&lt;br /&gt;
|milliseconds&lt;br /&gt;
|Hold time in milliseconds&lt;br /&gt;
|-&lt;br /&gt;
|decay&lt;br /&gt;
|dc&lt;br /&gt;
|milliseconds&lt;br /&gt;
|Decay time in milliseconds&lt;br /&gt;
|-&lt;br /&gt;
|sustain&lt;br /&gt;
|su&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sustain point in amplitude units&lt;br /&gt;
|-&lt;br /&gt;
|release&lt;br /&gt;
|re&lt;br /&gt;
|milliseconds&lt;br /&gt;
|Release time in milliseconds&lt;br /&gt;
|-&lt;br /&gt;
|releasetarget&lt;br /&gt;
|rt&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|&#039;&#039;Commands&#039;&#039; to execute once the release has hit zero&lt;br /&gt;
|-&lt;br /&gt;
|amplitude&lt;br /&gt;
|amp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Output amplitude&lt;br /&gt;
|-&lt;br /&gt;
|invert&lt;br /&gt;
|inv&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Inverts the results and gives negative values&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;numbermap&amp;quot;-&#039;&#039;plugin module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;numbermap&amp;quot;-&#039;&#039;plugin module&#039;&#039; is used to &amp;quot;map&amp;quot; a incoming number to a different outgoing number. The idea of the &#039;&#039;Number Map&#039;&#039; is for instance to scale the volume of different overtones to be more even by modifying the &#039;&#039;bow pressure&#039;&#039; depending on what &#039;&#039;harmonic&#039;&#039; is being played. Another use case would be to group certain &#039;&#039;MIDI&#039;&#039; keys to address a certain string, and other &#039;&#039;MIDI&#039;&#039; keys addressing another, depending on the how well different strings can render certain tones / harmonics.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;Number Map&#039;&#039; first needs a data set of several points where each point contains &amp;quot;an input of x outputs y&amp;quot;. The &#039;&#039;Number Map&#039;&#039; is then &#039;&#039;triggered&#039;&#039; with a value of &#039;&#039;x&#039;&#039;. When this happens it looks in its database for anything mapped to &#039;&#039;x&#039;&#039;, if it finds it it outputs the &#039;&#039;commands&#039;&#039; set by the &#039;&#039;target&#039;&#039; but first replaces any occurances of the word &amp;quot;nmout&amp;quot; in the &#039;&#039;command string&#039;&#039; with the value of &#039;&#039;y&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;numbermap&amp;quot;-&#039;&#039;plugin modules&#039;&#039; commands&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Sets the nickname of the numbermap&lt;br /&gt;
|-&lt;br /&gt;
|target&lt;br /&gt;
|tg&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the &#039;&#039;commands&#039;&#039; to execute whenever the &amp;quot;numbermap&amp;quot;-&#039;&#039;plugin modules&#039;&#039; is triggered with a mapped value&lt;br /&gt;
|-&lt;br /&gt;
|data&lt;br /&gt;
|da&lt;br /&gt;
|(in:out)*&lt;br /&gt;
|Set the map data in any number of pairs of [in] returns [out]&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|in&lt;br /&gt;
|Removes the map with [in] if it exists&lt;br /&gt;
|-&lt;br /&gt;
|scale&lt;br /&gt;
|sc&lt;br /&gt;
|?&lt;br /&gt;
|Sets the overall scale of the Number Map&lt;br /&gt;
|-&lt;br /&gt;
|trigger&lt;br /&gt;
|tr&lt;br /&gt;
|in&lt;br /&gt;
|Triggers the &#039;&#039;targets&#039;&#039; with the &#039;&#039;out&#039;&#039; number mapped to &#039;&#039;in&#039;&#039; if found&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Knaadmin</name></author>
	</entry>
	<entry>
		<id>http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_reference_V1.1&amp;diff=1691</id>
		<title>The Ekdahl FAR - Command reference V1.1</title>
		<link rel="alternate" type="text/html" href="http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_reference_V1.1&amp;diff=1691"/>
		<updated>2026-06-14T13:40:13Z</updated>

		<summary type="html">&lt;p&gt;Knaadmin: /* The &amp;quot;numbermap&amp;quot;-plugin module */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
The Ekdahl FAR V1.1 introduces the concept of &#039;&#039;modules&#039;&#039;. A &#039;&#039;module&#039;&#039; can contain any number of &#039;&#039;commands&#039;&#039; as well as other &#039;&#039;modules&#039;&#039;. Furthermore any number of &#039;&#039;modules&#039;&#039; of the same type can exist within a context, these are addressed using classic C-style array &#039;&#039;indexing&#039;&#039; with the help of brackets (&amp;quot;[ ]&amp;quot;). Extending on the classic usage, multiple &#039;&#039;indexes&#039;&#039; can be addressed simultaneously by either comma-separating the objects (&amp;quot;[0,3,4]&amp;quot;) and using &#039;&#039;ranges&#039;&#039; (&amp;quot;[3-6]&amp;quot;). &#039;&#039;Modules&#039;&#039; can be either &#039;&#039;internal&#039;&#039; or &#039;&#039;external&#039;&#039;, meaning that they may all physically exist within a single hardware object, or they can be be remote-controlled devices. From a user perspective this however makes no difference as they will appear the same.&lt;br /&gt;
&lt;br /&gt;
While all &#039;&#039;modules&#039;&#039; have their own set of &#039;&#039;commands&#039;&#039;, there are certain &#039;&#039;commands&#039;&#039; that all &#039;&#039;modules&#039;&#039; &amp;lt;u&amp;gt;must&amp;lt;/u&amp;gt; implement and can thus be accessed anywhere within the &#039;&#039;module hierarchy.&#039;&#039; There are also &#039;&#039;base commands&#039;&#039; that always exist within any given FAR ecosystem as well as product-specific &#039;&#039;base commands&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Ubiquitous commands ==&lt;br /&gt;
The &#039;&#039;module commands&#039;&#039; that are &amp;lt;u&amp;gt;required&amp;lt;/u&amp;gt; to be implemented in &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; &#039;&#039;modules&#039;&#039; and that can thus be accessed from anywhere are&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|list&lt;br /&gt;
|ls&lt;br /&gt;
|hidden/h:modules/m:commands/c:instances/i:instancecounts/ic:recursive/r&lt;br /&gt;
|Lists all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039; under the current module depending on the parameters given; &#039;hidden&#039; includes normally hidden &#039;&#039;commands&#039;&#039;, &#039;modules&#039; includes any &#039;&#039;submodules&#039;&#039;, &#039;commands&#039; shows &#039;&#039;commands&#039;&#039;, &#039;instances&#039; shows data for each individual instance of a &#039;&#039;module&#039;&#039;, &#039;instancecounts&#039; includes number of instances of each &#039;&#039;module&#039;&#039;, &#039;recursive&#039; lists all child &#039;&#039;modules&#039;&#039; / &#039;&#039;commands&#039;&#039;. No parameters defaults to showing all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039; recursively with instance counts. It doesn&#039;t show per-instance data or hidden commands.&lt;br /&gt;
|-&lt;br /&gt;
|help&lt;br /&gt;
|help&lt;br /&gt;
|recursive/r&lt;br /&gt;
|Shows a brief explanation of all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039;, shows the help for all &#039;&#039;submodules&#039;&#039; as well if &#039;recursive&#039;&lt;br /&gt;
|-&lt;br /&gt;
|dumpdata&lt;br /&gt;
|dump&lt;br /&gt;
|recursive/r&lt;br /&gt;
|Dumps all data saved for the current &#039;&#039;module&#039;&#039;, will list the data of all &#039;&#039;submodules&#039;&#039; as well if &#039;recursive&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Base commands ==&lt;br /&gt;
B&#039;&#039;ase commands&#039;&#039; are &#039;&#039;commands&#039;&#039; that always exist at the root in any implementation of the Ekdahl FAR.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|version&lt;br /&gt;
|ver&lt;br /&gt;
| -&lt;br /&gt;
|Gets the current firmware version&lt;br /&gt;
|-&lt;br /&gt;
|debugprint&lt;br /&gt;
|dp&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;command|usb|hardware|undefined|priority|error|inforequest|expressionparser|debug:1|0&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Turns on or off serial feedback for the given item&lt;br /&gt;
|-&lt;br /&gt;
|requestinfo&lt;br /&gt;
|rqi&lt;br /&gt;
|command&lt;br /&gt;
|Retrives any data saved for a &#039;&#039;command&#039;&#039;, if applicable&lt;br /&gt;
|-&lt;br /&gt;
|saveallparameters&lt;br /&gt;
|sap&lt;br /&gt;
| -&lt;br /&gt;
|Saves all avaliable parameters&lt;br /&gt;
|-&lt;br /&gt;
|loadallparameters&lt;br /&gt;
|lap&lt;br /&gt;
| -&lt;br /&gt;
|Loads all avaliable parameters&lt;br /&gt;
|-&lt;br /&gt;
|resetallparameters&lt;br /&gt;
|rap&lt;br /&gt;
| -&lt;br /&gt;
|Resets all saved parameters&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|rst&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;1|0&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Resets the Ekdahl FAR, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|nick&lt;br /&gt;
|nick&lt;br /&gt;
|name&lt;br /&gt;
|Sets the nickname of this unit&lt;br /&gt;
|-&lt;br /&gt;
|nooperation&lt;br /&gt;
|nop&lt;br /&gt;
| -&lt;br /&gt;
|Do absolutely, positively, nothing. Useful for testing and interfacing with computers, it&#039;s a good way to know that the unit is alive and responding since a &amp;quot;nop&amp;quot; is being returned as a response upon reception.&lt;br /&gt;
|-&lt;br /&gt;
|uservariable&lt;br /&gt;
|uv&lt;br /&gt;
|variable(0-9):value&lt;br /&gt;
|Set user variable 0-9 to &#039;value&#039;&lt;br /&gt;
|-&lt;br /&gt;
|expressionparserevaluate&lt;br /&gt;
|epev&lt;br /&gt;
|expression&lt;br /&gt;
|Evaluates an arithmetric expression and sends back the output, all variables and functions that can be used in any &#039;&#039;command string&#039;&#039; can also be used here. Useful for testing expressions.&lt;br /&gt;
|-&lt;br /&gt;
|ifequal&lt;br /&gt;
|ife&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] EQUALS [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring].&lt;br /&gt;
|-&lt;br /&gt;
|ifgreater&lt;br /&gt;
|ifg&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] &amp;gt; [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring]&lt;br /&gt;
|-&lt;br /&gt;
|ifless&lt;br /&gt;
|ifl&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] &amp;lt; [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring]&lt;br /&gt;
|-&lt;br /&gt;
|freeram&lt;br /&gt;
|ram&lt;br /&gt;
| -&lt;br /&gt;
|Shows free RAM memory&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The base also contains the following &#039;&#039;modules:&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|pluginhandler&lt;br /&gt;
|ph&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The Ekdahl FAR stand alone single string unit ==&lt;br /&gt;
The Ekdahl FAR stand-alone single string unit offers these &#039;&#039;commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|calibrateall&lt;br /&gt;
|ca&lt;br /&gt;
| -&lt;br /&gt;
|Performs all calibration routines on the selected bow, see below for routines performed&lt;br /&gt;
|-&lt;br /&gt;
|calibratebowspeed&lt;br /&gt;
|cbs&lt;br /&gt;
| -&lt;br /&gt;
|Finds the minimum and maximum bow speed of the selected bow&lt;br /&gt;
|-&lt;br /&gt;
|calibratebowpressure&lt;br /&gt;
|cbp&lt;br /&gt;
| -&lt;br /&gt;
|Finds the minimum and maximum bow pressure of the selected bow&lt;br /&gt;
|-&lt;br /&gt;
|calibratemute&lt;br /&gt;
|cmu&lt;br /&gt;
| -&lt;br /&gt;
|Calibrate mute settings&lt;br /&gt;
|-&lt;br /&gt;
|pickupstringfrequency&lt;br /&gt;
|psf&lt;br /&gt;
| -&lt;br /&gt;
|Returns the fundamental tone calculated from the current audio signal if apliccable&lt;br /&gt;
|-&lt;br /&gt;
|pickupaudiopeak&lt;br /&gt;
|pap&lt;br /&gt;
| -&lt;br /&gt;
|Returns the peak amplitude of the current audio signal&lt;br /&gt;
|-&lt;br /&gt;
|pickupaudiorms&lt;br /&gt;
|par&lt;br /&gt;
| -&lt;br /&gt;
|Returns the RMS amplitude of the current audio signal&lt;br /&gt;
|}&lt;br /&gt;
The Ekdahl FAR also contains the following &#039;&#039;modules&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|bowingwheel&lt;br /&gt;
|bw&lt;br /&gt;
|-&lt;br /&gt;
|mute&lt;br /&gt;
|mu&lt;br /&gt;
|-&lt;br /&gt;
|solenoid&lt;br /&gt;
|so&lt;br /&gt;
|-&lt;br /&gt;
|controlbox&lt;br /&gt;
|cb&lt;br /&gt;
|-&lt;br /&gt;
|midiconfigurationhandler&lt;br /&gt;
|mcf&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;Bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; contains everything needed to interface with a single &#039;&#039;bowing wheel&#039;&#039;. Each &#039;&#039;bowing wheel&#039;&#039; has its own harmonic series, pressure actuators and direct hardware interface. It contains the following &#039;&#039;commands&#039;&#039;.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|speedmode&lt;br /&gt;
|sm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Bow motor speed mode, 0 = Automatic and 1 = Manual. Automatic mode means that the bowing wheel will automatically turn off after the &#039;&#039;motor timeout&#039;&#039; has been reached after being put into rest mode&lt;br /&gt;
|-&lt;br /&gt;
|motortimeout&lt;br /&gt;
|mt&lt;br /&gt;
|ms&lt;br /&gt;
|Bow motor shutdown timeout after bow having been put into the rest position&lt;br /&gt;
|-&lt;br /&gt;
|pidenable&lt;br /&gt;
|pe&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets the bow PID on/off&lt;br /&gt;
|-&lt;br /&gt;
|motorfaultcommands&lt;br /&gt;
|mfc&lt;br /&gt;
|commands&lt;br /&gt;
|Commands to execute when a motor fault is tripped - !WARNING! Can ruin your instrument if changed&lt;br /&gt;
|-&lt;br /&gt;
|motoroverpowercommands&lt;br /&gt;
|moc&lt;br /&gt;
|commands&lt;br /&gt;
|Commands to execute when motor is over the power limit - !WARNING! Can ruin your instrument if changed&lt;br /&gt;
|}&lt;br /&gt;
The &#039;&#039;modules&#039;&#039; in the &amp;quot;Bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; are as follows&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|bowpressure&lt;br /&gt;
|bp&lt;br /&gt;
|-&lt;br /&gt;
|dcmotor&lt;br /&gt;
|dcm&lt;br /&gt;
|-&lt;br /&gt;
|pid&lt;br /&gt;
|pid&lt;br /&gt;
|-&lt;br /&gt;
|harmonicserieshandler&lt;br /&gt;
|hsh&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; handles the &#039;&#039;pressure&#039;&#039; of the &#039;&#039;bowing wheel&#039;&#039; against the string. The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|baseline&lt;br /&gt;
|ba&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure baseline, modulation is added to this point upward. Typically this is set with a knob on the &#039;&#039;control box&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|modifier&lt;br /&gt;
|mo&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure modulation, added to the baseline&lt;br /&gt;
|-&lt;br /&gt;
|rest&lt;br /&gt;
|rs&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the bow pressure in the &#039;&#039;rest&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|engage&lt;br /&gt;
|en&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the bow pressure in the &#039;&#039;engage&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|stallpressure&lt;br /&gt;
|sp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure stall/maximum position, this parameter is set using &#039;&#039;hardware positioning&#039;&#039; and is used as the absolute maximum for baseline and modifier combiner&lt;br /&gt;
|-&lt;br /&gt;
|engagepressure&lt;br /&gt;
|ep&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure touch/minimum position, this parameter is set using &#039;&#039;hardware position&#039;&#039; and is used as the starting point for when both the baseline and modifier is set to zero&lt;br /&gt;
|-&lt;br /&gt;
|restpressure&lt;br /&gt;
|rp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure rest position, this parameter is set using &#039;&#039;hardware positioning&#039;&#039; and is typically set to a point just below the string where it does not touch at all. The purpose of this is because while the actual hardware might be able to make the bow go even lower, that position might be far enough from the string that once &#039;&#039;engaged&#039;&#039; the bow may have so far to travel that there is perceptible &#039;&#039;latency&#039;&#039;.&lt;br /&gt;
|-&lt;br /&gt;
|engagespeed&lt;br /&gt;
|es&lt;br /&gt;
|1- ~100&lt;br /&gt;
|Bow pressure movement speed when engaging or disengaging&lt;br /&gt;
|-&lt;br /&gt;
|modulationspeed&lt;br /&gt;
|ms&lt;br /&gt;
|0.1 - 10&lt;br /&gt;
|Bow pressure movement speed while engaged&lt;br /&gt;
|-&lt;br /&gt;
|hold&lt;br /&gt;
|hd&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets bow hold (infinite sustain) on/off, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|home&lt;br /&gt;
|hm&lt;br /&gt;
| -&lt;br /&gt;
|Homing bow, used at startup and in case of the bow loosing position&lt;br /&gt;
|-&lt;br /&gt;
|tmcinfo&lt;br /&gt;
|tmi&lt;br /&gt;
| -&lt;br /&gt;
|Request statistical information from the TMC2209 stepper motor driver&lt;br /&gt;
|}&lt;br /&gt;
Note that the &amp;quot;stall&amp;quot;, &amp;quot;engage&amp;quot; and &amp;quot;rest&amp;quot;-pressure positions mention something called &#039;&#039;hardware position&#039;&#039;. This means the entire available movement of the &#039;&#039;bowing jack&#039;&#039;. Because the very bottom and top end of the movement might not be musically useful and may even harm the instrument, the &amp;quot;baseline&amp;quot; and &amp;quot;modifier&amp;quot; commands &#039;&#039;parameter&#039;&#039;s are scaled depending on these settings.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;engage&amp;quot; and &amp;quot;modulation&amp;quot;-speed settings sets how fast the stepper motor that drives the &#039;&#039;pressure&#039;&#039; moves depending on whether the &#039;&#039;bowing jack&#039;&#039; is set to &#039;&#039;engage&#039;&#039; or not. The idea here is that while wanting to be able to minimize &#039;&#039;latency&#039;&#039; by &#039;&#039;engaging&#039;&#039; and &#039;&#039;disengaging&#039;&#039; from the string as quickly as possible, dynamic changes in the &#039;&#039;pressure&#039;&#039; while playing benefits from much smoother movements as the &#039;&#039;bowing wheel&#039;&#039; takes some time to catch up to varying amounts of friction.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; contains one or more of the following &#039;&#039;modules&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|actuatorhandler&lt;br /&gt;
|ah&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;actuatorhandler&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The concept of &amp;quot;actuators&amp;quot; came up as it is possible to have &#039;&#039;bowing wheels&#039;&#039; of different sizes and wanting to be able to switch quickly in between them, perhaps during mid-performance. Because a differently sized wheel will require different values for the above mentioned &amp;quot;stall&amp;quot;, &amp;quot;engage&amp;quot; and &amp;quot;reset&amp;quot;-&#039;&#039;pressure&#039;&#039;, each &#039;&#039;actuator&#039;&#039; stores these values. Instead of having to manually change the previously mentioned values, simply selecting a new &#039;&#039;actuator&#039;&#039; will automatically load the values. The &amp;quot;actuatorhandler&amp;quot;-&#039;&#039;module&#039;&#039; is the handler of one or more &amp;quot;actuator&amp;quot;-&#039;&#039;modules&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;commands&#039;&#039; of the &amp;quot;acuatorhandler&amp;quot;-&#039;&#039;module&#039;&#039; are as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|add&lt;br /&gt;
|a&lt;br /&gt;
|(name):(rest:engage:stall)&lt;br /&gt;
|Add new actuator with the given name and parameters&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|actuatornumber&lt;br /&gt;
|Remove bow actuator [actuatornumber]&lt;br /&gt;
|-&lt;br /&gt;
|count&lt;br /&gt;
|c&lt;br /&gt;
| -&lt;br /&gt;
|Returns the amount of saved bow actuators&lt;br /&gt;
|}&lt;br /&gt;
The &amp;quot;actuatorhandler&amp;quot;-&#039;&#039;module&#039;&#039; contains one or more of&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|actuator&lt;br /&gt;
|ac&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;actuator&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;actuator&amp;quot;-&#039;&#039;module&#039;&#039; contains the following commands&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|[index]&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|Selects the given actuator&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Sets the actuator name&lt;br /&gt;
|-&lt;br /&gt;
|data&lt;br /&gt;
|da&lt;br /&gt;
|name:rest:engage:stall&lt;br /&gt;
|Sets the actuator name, rest, engage and stall &#039;&#039;pressure&#039;&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;dcmotor&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;dcmotor&amp;quot;-&#039;&#039;module&#039;&#039; handles the direct &amp;lt;u&amp;gt;raw&amp;lt;/u&amp;gt; control of the &#039;&#039;bowing motor&#039;&#039; and handles the reporting back of the current speed. It has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|run&lt;br /&gt;
|ru&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Turns the motor off/on&lt;br /&gt;
|-&lt;br /&gt;
|pwm&lt;br /&gt;
|pw&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor direct power in 16-bit PWM values, requires that the &#039;&#039;PID&#039;&#039; is turned off&lt;br /&gt;
|-&lt;br /&gt;
|voltage&lt;br /&gt;
|vo&lt;br /&gt;
|~2 - 10V&lt;br /&gt;
|Sets the voltage of the regulator powering the motor. Changes here can make the motor more responsive to certain frequencies but will also affect how well the &#039;&#039;PID&#039;&#039; works. !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|current&lt;br /&gt;
|cu&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor reported current use&lt;br /&gt;
|-&lt;br /&gt;
|currentlimit&lt;br /&gt;
|cl&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor current limit (A)- !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|powerlimit&lt;br /&gt;
|pl&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor power limit (W) - !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|frequency&lt;br /&gt;
|fq&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor reported frequency&lt;br /&gt;
|-&lt;br /&gt;
|emergencystop&lt;br /&gt;
|es&lt;br /&gt;
|ms (0-65535)&lt;br /&gt;
|Immediately stops the bowing motor and doesn&#039;t allow it to start again until the cool down period given in the first argument has lapsed (milliseconds)&lt;br /&gt;
|-&lt;br /&gt;
|minpwm&lt;br /&gt;
|ip&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor minimum PWM (for calibration)&lt;br /&gt;
|-&lt;br /&gt;
|maxpwm&lt;br /&gt;
|xp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor maximum PWM (for calibration)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;pidcontroller&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;pidcontroller&amp;quot;-&#039;&#039;module&#039;&#039; is responsible for keeping the &amp;quot;dcmotor&amp;quot;-&#039;&#039;module&#039;&#039; at a certain frequency (given in Hertz). It takes the output of the motor frequency measurement and feeds it a PWM value that tries to make the speed constant regardless of the friction that the motor is enduring. To learn more about PID Controllers please see this [[wikipedia:PID_controller|wikipedia article]]. The &#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|targetfrequency&lt;br /&gt;
|tf&lt;br /&gt;
|hertz&lt;br /&gt;
|Sets the PID target frequency&lt;br /&gt;
|-&lt;br /&gt;
|ki&lt;br /&gt;
|ki&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Ki parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|kp&lt;br /&gt;
|kp&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Kp parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|kd&lt;br /&gt;
|kd&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Kd parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|integratorerror&lt;br /&gt;
|ie&lt;br /&gt;
|float&lt;br /&gt;
|Sets the lower threshold of error values for the PID integrator to ignore&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|re&lt;br /&gt;
| -&lt;br /&gt;
|Resets the PID integrator and derivative&lt;br /&gt;
|-&lt;br /&gt;
|maxerror&lt;br /&gt;
|xe&lt;br /&gt;
|float&lt;br /&gt;
|Maximum error to correct in each PID loop, essentially sets acceleration&lt;br /&gt;
|-&lt;br /&gt;
|peakerror&lt;br /&gt;
|pe&lt;br /&gt;
|float&lt;br /&gt;
|Get latest PID peak error&lt;br /&gt;
|-&lt;br /&gt;
|motorspeedmax&lt;br /&gt;
|msx&lt;br /&gt;
|Hertz&lt;br /&gt;
|Bow motor maximum speed limit&lt;br /&gt;
|-&lt;br /&gt;
|motorspeedmin&lt;br /&gt;
|msi&lt;br /&gt;
|Hertz&lt;br /&gt;
|Bow motor minimum speed limit&lt;br /&gt;
|-&lt;br /&gt;
|measuretimetotarget&lt;br /&gt;
|mtt&lt;br /&gt;
|Hertz&lt;br /&gt;
|Measure the time it takes to change from the current frequency to the target frequency, for testing purposes&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; is responsible for sending frequency data to the &amp;quot;pid&amp;quot;-&#039;&#039;module&#039;&#039;. It handles calculating the correct frequency of the &#039;&#039;bowing wheel&#039;&#039; according to the selected &#039;&#039;harmonic&#039;&#039; and &#039;&#039;harmonic shift&#039;&#039; per the currently selected &#039;&#039;harmonic series&#039;&#039;. The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|fundamental&lt;br /&gt;
|fu&lt;br /&gt;
|Hertz&lt;br /&gt;
|The fundamental frequency of the string, all harmonics are calculated from this number&lt;br /&gt;
|-&lt;br /&gt;
|harmonic&lt;br /&gt;
|h&lt;br /&gt;
|int&lt;br /&gt;
|Selects the harmonic number to set the &#039;&#039;bowing wheel&#039;&#039; to. A ratio is taken from the given &#039;&#039;harmonic&#039;&#039; in the current &#039;&#039;harmonic series&#039;&#039;, the ratio is then multiplied by the &#039;&#039;fundamental frequency&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|harmonicadd&lt;br /&gt;
|ha&lt;br /&gt;
|int&lt;br /&gt;
|This number is added to the current harmonic&lt;br /&gt;
|-&lt;br /&gt;
|harmonicbase&lt;br /&gt;
|hb&lt;br /&gt;
|int&lt;br /&gt;
|Same as harmonic but where the harmonic number is based on a MIDI note given by basenote&lt;br /&gt;
|-&lt;br /&gt;
|basenote&lt;br /&gt;
|bn&lt;br /&gt;
|0-127&lt;br /&gt;
|Sets the MIDI base note of the &#039;&#039;bowing wheel&#039;&#039;, used in conjunction with &amp;quot;harmonicbase&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|shift&lt;br /&gt;
|sh&lt;br /&gt;
| -32767 - 32767&lt;br /&gt;
|Sets shift from the currently playing harmonic where 32767 equals the entire harmonic shift range shifted up&lt;br /&gt;
|-&lt;br /&gt;
|shiftrange&lt;br /&gt;
|sr&lt;br /&gt;
|0-36&lt;br /&gt;
|Set the number of harmonic numbers that constitutes an entire harmonic shift&lt;br /&gt;
|-&lt;br /&gt;
|shift5&lt;br /&gt;
|sh5&lt;br /&gt;
| -32767 - 32767&lt;br /&gt;
|Sets the shift from the currently playing harmonic over 5 octaves where 32767 equals 5 octaves shift up from the fundamental&lt;br /&gt;
|-&lt;br /&gt;
|add&lt;br /&gt;
|a&lt;br /&gt;
|(name):(ratios)&lt;br /&gt;
|Add a new series with the given name and parameters&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|series&lt;br /&gt;
|Remove the series given and shift any series accordingly. Cannot remove all series&lt;br /&gt;
|-&lt;br /&gt;
|count&lt;br /&gt;
|c&lt;br /&gt;
| -&lt;br /&gt;
|Returns the number of harmonic series in the list and their IDs&lt;br /&gt;
|}&lt;br /&gt;
The &amp;quot;harmonicserieshandler&amp;quot;-module contains at the very least ONE harmonic series, by default it contains two: one for equal temperament and one for just intonation. The current series can be selected by simply indexing the &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; without a &#039;&#039;command&#039;&#039;, e.g. &amp;quot;harmonicserieshandler.harmonicseries[1]&amp;quot;. To be consistent, these are the &#039;&#039;modules&#039;&#039; in the &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|harmonicseries&lt;br /&gt;
|hs&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; contains any number of &#039;&#039;ratios&#039;&#039; that comprises a scale, ratios are given in a standard format where a ratio of &amp;quot;1&amp;quot; is equal to the fundamental, &amp;quot;2&amp;quot; would be one octave up etc. A standard &#039;&#039;harmonic series&#039;&#039; contains 12 ratios following a just intonation scheme. The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; will automatically adapt to the currently selected &#039;&#039;harmonic series&#039;&#039; length, whether it&#039;s a standard 12-tone scale, some kinda 3-tone scale or a full on bananas 53-tone scale. The &#039;&#039;commands&#039;&#039; of the &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; is as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|[index]&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
|Sets the currently selected &#039;&#039;harmonic Series&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Sets the name of the &#039;&#039;harmonic series&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|data&lt;br /&gt;
|da&lt;br /&gt;
|name:ratios&lt;br /&gt;
|Gets / sets all data for the &#039;&#039;harmonic series&#039;&#039; in the given slot with an arbitrary &#039;&#039;name&#039;&#039; as the first &#039;&#039;parameter&#039;&#039;. The length of the series is simply set to the amount of ratios given&lt;br /&gt;
|-&lt;br /&gt;
|ratio&lt;br /&gt;
|r&lt;br /&gt;
|harmonic:ratio&lt;br /&gt;
|Sets the ratio of the given harmonic in current &#039;&#039;harmonic series&#039;&#039;, will increase the list size if needed to address the harmonic&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|harmonic&lt;br /&gt;
|Remove the harmonic ratio given in the current series and shift any ratios accordingly. Cannot remove all ratios&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;mute&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;mute&amp;quot;-&#039;&#039;module&#039;&#039; works very similarly to the &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; in that it controls a stepper motor with some software limits in place in order to press the mute against the string. The &#039;&#039;commands&#039;&#039; are as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|setposition&lt;br /&gt;
|sp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set mute position&lt;br /&gt;
|-&lt;br /&gt;
|fullmute&lt;br /&gt;
|fm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the mute in &#039;&#039;full mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|halfmute&lt;br /&gt;
|hm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the mute in &#039;&#039;half mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|rest&lt;br /&gt;
|rs&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Put the mute in the &#039;&#039;rest&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|savefull&lt;br /&gt;
|sf&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Save the current mute position as the &#039;&#039;full mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|savehalf&lt;br /&gt;
|sh&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Save the current mute position as the &#039;&#039;half mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|saverest&lt;br /&gt;
|sr&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Save the current mute position as the &#039;&#039;rest&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|fullmuteposition&lt;br /&gt;
|fmp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;full mute&#039;&#039; position according to the &#039;&#039;hardware position&#039;&#039; given&lt;br /&gt;
|-&lt;br /&gt;
|halfmuteposition&lt;br /&gt;
|hmp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;half mute&#039;&#039; position according to the &#039;&#039;hardware position&#039;&#039; given&lt;br /&gt;
|-&lt;br /&gt;
|restposition&lt;br /&gt;
|rp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;rest&#039;&#039; position according to the &#039;&#039;hardware position&#039;&#039; given&lt;br /&gt;
|-&lt;br /&gt;
|sustain&lt;br /&gt;
|su&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets the sustain off/on, this will keep the mute in the &#039;&#039;rest&#039;&#039; position even if a &amp;quot;fullmute&amp;quot;-&#039;&#039;command&#039;&#039; is given, lasts until &amp;quot;sustain&amp;quot; is set to &amp;quot;0&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
|backoff&lt;br /&gt;
|bo&lt;br /&gt;
|0-65535&lt;br /&gt;
|Setting the time that the mute stays in the mutefullmute position before automatically going into rest, set in mS. A value of &amp;quot;0&amp;quot; disables backoff. This is used because if the mute is not backing off until something is attempted to be played, the backing-off time will either introduce &#039;&#039;latency&#039;&#039; or the string will be initially partially muted&lt;br /&gt;
|-&lt;br /&gt;
|home&lt;br /&gt;
|hm&lt;br /&gt;
| -&lt;br /&gt;
|Home mute, used during initialization and if the mute were to loose position&lt;br /&gt;
|-&lt;br /&gt;
|hardwareposition&lt;br /&gt;
|hwp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;hardware position&#039;&#039; of the mute instead of scaling it over the &#039;&#039;full mute&#039;&#039; and &#039;&#039;rest&#039;&#039; positions. Mainly used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|completetask&lt;br /&gt;
|cpt&lt;br /&gt;
| -&lt;br /&gt;
|Requests a callback when the current operation is finished. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|autocorrect&lt;br /&gt;
|ac&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Enables auto correct positioning that uses the homing sensor to correct positioning on the fly. EXPERIMENTAL&lt;br /&gt;
|-&lt;br /&gt;
|homingsensed&lt;br /&gt;
|hms&lt;br /&gt;
| -&lt;br /&gt;
|Requests whether the homing sensor is currently active or not. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|movedirection&lt;br /&gt;
|md&lt;br /&gt;
| -&lt;br /&gt;
|Requests the current direction of movement (0 Forward, 1 Reverse). Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|currentstep&lt;br /&gt;
|cs&lt;br /&gt;
| -&lt;br /&gt;
|Requests the current step. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|homingpoint&lt;br /&gt;
|hmp&lt;br /&gt;
|edgedirection&lt;br /&gt;
|Requests the given homing point. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|homingstage&lt;br /&gt;
|hms&lt;br /&gt;
| -&lt;br /&gt;
|Requests the current homing stage (UNHOMED, HOMED, FIRSTHOMINGRISING, SECONDHOMINGFALLING, SECONDHOMINGRISING, FIRSTHOMINGFALLING, MOVEPASTHOMESWITCH, MOVETOHOMESWITCH, GOTOOFFSET). Only used internally by other &#039;&#039;modules.&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|tmcinfo&lt;br /&gt;
|tmi&lt;br /&gt;
| -&lt;br /&gt;
|Request statistical information from the TMC2209 stepper motor driver&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;solenoid&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;solenoid&amp;quot;-&#039;&#039;module&#039;&#039; currently controls the &#039;&#039;hammer&#039;&#039; of the Ekdahl FAR. Due to the fact that the very same &#039;&#039;module&#039;&#039; could be used for anything that uses a striking &#039;&#039;solenoid&#039;&#039; it was named as such. It has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|engage&lt;br /&gt;
|en&lt;br /&gt;
|0-65535&lt;br /&gt;
|Engages the solenoid using the first parameter as the force&lt;br /&gt;
|-&lt;br /&gt;
|rest&lt;br /&gt;
|rs&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Forces the solenoid to its rest position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|maxforce&lt;br /&gt;
|xf&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set solenoid maximum usable force&lt;br /&gt;
|-&lt;br /&gt;
|minforce&lt;br /&gt;
|if&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set solenoid minimum usable force&lt;br /&gt;
|-&lt;br /&gt;
|forcemultiplier&lt;br /&gt;
|fm&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set solenoid force multiplier, useful for scaling of all incoming &amp;quot;engage&amp;quot;-&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|engageduration&lt;br /&gt;
|ed&lt;br /&gt;
|uS&lt;br /&gt;
|Sets the duration of the solenoid hit in uS, if a value of 0 is set the solenoid will not disengage until a rest command has been given. WARNING!! HAVING THE SOLENOID ON FOR A SPAN OF SECONDS COULD DESTROY THE CIRCUITRY!!&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;controlbox&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;controlbox&amp;quot;-&#039;&#039;module&#039;&#039; communicates with an external &#039;&#039;control box&#039;&#039; and will issue associated &#039;&#039;commands&#039;&#039; whenever new values are read on the ADC-converters. It handles averaging and does some noise-cancellation functions on the values as well. The &#039;&#039;commands&#039;&#039; are:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|harmonic&lt;br /&gt;
|har&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the harmonic knob or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|harmonicshift&lt;br /&gt;
|has&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the harmonic shift modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|finetune&lt;br /&gt;
|fin&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the fine tune knob changes&lt;br /&gt;
|-&lt;br /&gt;
|pressure&lt;br /&gt;
|pre&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the pressure knob or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|mute&lt;br /&gt;
|mut&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the mute knob or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|hammerscale&lt;br /&gt;
|hms&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the hammer scale knob changes&lt;br /&gt;
|-&lt;br /&gt;
|gate&lt;br /&gt;
|gt&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the gate switch or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|hammertrig&lt;br /&gt;
|hmt&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the hammer trigger modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|controldefaults&lt;br /&gt;
|cde&lt;br /&gt;
| -&lt;br /&gt;
|Reverts all ADC command strings to default values&lt;br /&gt;
|-&lt;br /&gt;
|datareturn&lt;br /&gt;
|dr&lt;br /&gt;
|channel:value&lt;br /&gt;
|Sent when a new value is presented on one of the ADC channels, cannot be invoked. Triggers the commands associated with the channel&lt;br /&gt;
|-&lt;br /&gt;
|adcsetting&lt;br /&gt;
|adcs&lt;br /&gt;
|channel : averages : interrupterrorthreshold : continuouserrorthreshold : continuoustimeout&lt;br /&gt;
|Sets ADC settings for a given channel. Averages are the number of samples to average, interruptthreshold is how much the value must change in order to issue a new value change event. continuousthreshold is how much the value must change when a previous change has already been recorded within the timespan of continuoustimeout&lt;br /&gt;
|-&lt;br /&gt;
|testadclatency&lt;br /&gt;
|tal&lt;br /&gt;
|0-65535&lt;br /&gt;
|Start a ADC latency test&lt;br /&gt;
|-&lt;br /&gt;
|testadclatencyreturn&lt;br /&gt;
|talr&lt;br /&gt;
| -&lt;br /&gt;
|Return from latency test&lt;br /&gt;
|-&lt;br /&gt;
|testadcminmax&lt;br /&gt;
|tix&lt;br /&gt;
|channel&lt;br /&gt;
|Test min/max value for a given channel and resets the counter&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;midiconfigurationhandler&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;midiconfigurationhandler&amp;quot;-&#039;&#039;module&#039;&#039; handles a number of &amp;quot;midiconfiguration&amp;quot;-&#039;&#039;modules&#039;&#039;. It has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|allnotesoff&lt;br /&gt;
|ano&lt;br /&gt;
| -&lt;br /&gt;
|Clears the entire buffer of MIDI notes held&lt;br /&gt;
|-&lt;br /&gt;
|add&lt;br /&gt;
|a&lt;br /&gt;
|name&lt;br /&gt;
|Adds a new MIDI configuration with the given name&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|int&lt;br /&gt;
|Remove the specified MIDI configuration&lt;br /&gt;
|-&lt;br /&gt;
|count&lt;br /&gt;
|c&lt;br /&gt;
| -&lt;br /&gt;
|Returns the number of MIDI configurations&lt;br /&gt;
|}&lt;br /&gt;
It contains one or more of the following&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|midiconfiguration&lt;br /&gt;
|mc&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;midiconfiguration&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
A &amp;quot;midiconfiguration&amp;quot;-&#039;&#039;module&#039;&#039; handles the reception of &#039;&#039;MIDI messages&#039;&#039; and will output the associated &#039;&#039;commands&#039;&#039; to the instrument internally. The commands are as follows&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|[index]&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
|Sets the currently selected MIDI configuration&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Set the name of the MIDI configuration&lt;br /&gt;
|-&lt;br /&gt;
|noteon&lt;br /&gt;
|non&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Note On event&lt;br /&gt;
|-&lt;br /&gt;
|noteoff&lt;br /&gt;
|nof&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Note Off event&lt;br /&gt;
|-&lt;br /&gt;
|polyaftertouch&lt;br /&gt;
|pat&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Polyphonic after touch event&lt;br /&gt;
|-&lt;br /&gt;
|channelaftertouch&lt;br /&gt;
|cat&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Channel after touch event&lt;br /&gt;
|-&lt;br /&gt;
|pitchbend&lt;br /&gt;
|pb&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Pitch bend event&lt;br /&gt;
|-&lt;br /&gt;
|programchange&lt;br /&gt;
|pc&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Program change event&lt;br /&gt;
|-&lt;br /&gt;
|continuouscontrollerdata&lt;br /&gt;
|ccd&lt;br /&gt;
|controllernuber:&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Continuous controller event with the given [&#039;&#039;controllernumber&#039;&#039;]&lt;br /&gt;
|-&lt;br /&gt;
|removecc&lt;br /&gt;
|rmc&lt;br /&gt;
|controllernuber&lt;br /&gt;
|Removes the entry associated with the MIDI continuous controller even &#039;&#039;controllernumber&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|defaults&lt;br /&gt;
|d&lt;br /&gt;
| -&lt;br /&gt;
|Reverts the current configuration to default &#039;&#039;commands&#039;&#039;, values and CCs&lt;br /&gt;
|-&lt;br /&gt;
|receivechannel&lt;br /&gt;
|rc&lt;br /&gt;
|channel&lt;br /&gt;
|Sets the MIDI receive channel of the current configuration. 1-16 sets specific channel, any other value for OMNI&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;pluginhandler&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The Ekdahl FAR allows for &#039;&#039;plugins&#039;&#039;. These are &#039;&#039;modules&#039;&#039; that can trigger certain &#039;&#039;command strings&#039;&#039; to be executed either periodically or triggered by an incoming &#039;&#039;command&#039;&#039;. Further explanation of the given &#039;&#039;plugins&#039;&#039; is given below. The various &#039;&#039;plugins&#039;&#039; are handled by the &amp;quot;pluginhandler&amp;quot;-&#039;&#039;module&#039;&#039;, the different &#039;&#039;plugin modules&#039;&#039; are identified by their own unique &#039;&#039;ID&#039;&#039;. The &amp;quot;pluginhandler&amp;quot;-&#039;&#039;module&#039;&#039; it has the following &#039;&#039;commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|add&lt;br /&gt;
|a&lt;br /&gt;
|pluginid&lt;br /&gt;
|Add plugin with the given ID&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|pluginid:index&lt;br /&gt;
|Remove plugin with the given ID and index&lt;br /&gt;
|-&lt;br /&gt;
|count&lt;br /&gt;
|c&lt;br /&gt;
|(pluginid)&lt;br /&gt;
|Return the number of plugins of the given type, if none is given it returns all plugins&lt;br /&gt;
|}&lt;br /&gt;
The number of available &#039;&#039;plugins&#039;&#039; will differ from time to time as the &#039;&#039;plugin system&#039;&#039; has been purposefully designed to allow for anyone to write and add their own &#039;&#039;plugins&#039;&#039;. As of the current writing (2026-06-14) the number of &amp;lt;u&amp;gt;possible&amp;lt;/u&amp;gt; &#039;&#039;plugin modules&#039;&#039; that &amp;lt;u&amp;gt;can&amp;lt;/u&amp;gt; exist under the &amp;quot;pluginhandler&amp;quot;-&#039;&#039;module&#039;&#039; are&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|lfo&lt;br /&gt;
|lfo&lt;br /&gt;
|-&lt;br /&gt;
|ahdsr&lt;br /&gt;
|ahdsr&lt;br /&gt;
|-&lt;br /&gt;
|numbermap&lt;br /&gt;
|map&lt;br /&gt;
|-&lt;br /&gt;
|multiple&lt;br /&gt;
|mlt&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;lfo&amp;quot;-&#039;&#039;plugin module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;lfo&amp;quot;-&#039;&#039;plugin module&#039;&#039; works like regular [[wikipedia:Low-frequency_oscillation|low frequency oscillator]] in that it generates a given &#039;&#039;waveform&#039;&#039; with a given &#039;&#039;frequency&#039;&#039; at a certain &#039;&#039;amplitude&#039;&#039;. In the Ekdahl FAR the distinguishing factors are that besides the common &#039;&#039;frequency, amplitude&#039;&#039; and &#039;&#039;waveform&#039;&#039; parameters, it also requires the use of a &#039;&#039;update rate&#039;&#039; and &#039;&#039;target&#039;&#039; parameter. The &#039;&#039;update rate&#039;&#039; sets how often the current position of the LFO is sampled (aka how often it peeks in on where the LFO is in its waveform transition at the moment), and each time that happens, the &#039;&#039;target commands&#039;&#039; are outputted to the instrument.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example:&#039;&#039;&#039;&lt;br /&gt;
 Lets set the &#039;&#039;waveform&#039;&#039; to &amp;quot;triangle&amp;quot;, the &#039;&#039;amplitude&#039;&#039; to 65535 (max), the &#039;&#039;frequency&#039;&#039; to 1Hz (1 full waveform per second), the &#039;&#039;update rate&#039;&#039; to 10mS and the &#039;&#039;target&#039;&#039; to &amp;quot;bowingwheel.harmonicserieshandler.shift:lfoout&amp;quot;.&lt;br /&gt;
 &lt;br /&gt;
 The output of the LFO is always given in the variable &amp;quot;lfoout&amp;quot;, our &#039;&#039;target&#039;&#039; is set to &amp;quot;bowingwheel.harmonicserieshandler.shift&amp;quot; which controls the &#039;&#039;harmonic shift&#039;&#039; (pitchbend basically) of the &#039;&#039;bowing wheel&#039;&#039;.&lt;br /&gt;
 &lt;br /&gt;
 Since our update rate is set to every 10 milliseconds and our frequency is 1 Hertz the instrument will internally send 100 updates per second to the &#039;&#039;harmonic shift.&#039;&#039; Our amplitude is set to the maximum value and depending on the &amp;quot;harmonicserieshandler.shiftrange&amp;quot; this could give a smooth vibrato like sound or more of an experimental one with a wider range. If the modulation is too deep we can just adjust the amplitude of the LFO.&lt;br /&gt;
The &amp;quot;lfo&amp;quot;-&#039;&#039;plugin modules commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Sets the nickname of the LFO&lt;br /&gt;
|-&lt;br /&gt;
|enable&lt;br /&gt;
|en&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Disables / Enables the output of the &#039;&#039;target&#039;&#039; &#039;&#039;commands&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|target&lt;br /&gt;
|tg&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the command string to execute each update cycle, the string [lfoout] will be replaced with the current value&lt;br /&gt;
|-&lt;br /&gt;
|updaterate&lt;br /&gt;
|ur&lt;br /&gt;
|milliseconds&lt;br /&gt;
|Sets the frequency with which the &#039;&#039;target commands&#039;&#039; are executed. Limited by the global maximum as set in the plugin handler&lt;br /&gt;
|-&lt;br /&gt;
|waveform&lt;br /&gt;
|wf&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;sine|triangle|square|saw&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets the LFO waveform&lt;br /&gt;
|-&lt;br /&gt;
|frequency&lt;br /&gt;
|fq&lt;br /&gt;
|Hertz&lt;br /&gt;
|Sets the LFO frequency&lt;br /&gt;
|-&lt;br /&gt;
|amplitude&lt;br /&gt;
|amp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the LFO amplitude&lt;br /&gt;
|-&lt;br /&gt;
|delay&lt;br /&gt;
|dl&lt;br /&gt;
|0-65535 milliseconds&lt;br /&gt;
|Ramps up the amplitude of the output waveform from zero to full amplitude in the given time span&lt;br /&gt;
|-&lt;br /&gt;
|resetdelay&lt;br /&gt;
|rd&lt;br /&gt;
| -&lt;br /&gt;
|Resets the delay and starts the ramping of the waveform&lt;br /&gt;
|-&lt;br /&gt;
|resetwave&lt;br /&gt;
|rw&lt;br /&gt;
| -&lt;br /&gt;
|Resets the waveform from the start (sync)&lt;br /&gt;
|-&lt;br /&gt;
|bipolar&lt;br /&gt;
|bp&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets whether the waveform is bipolar (default) or positive only&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;ahdsr&amp;quot;-&#039;&#039;plugin module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;ahdsr&amp;quot;-&#039;&#039;plugin module&#039;&#039; works like a standard [[wikipedia:ADSR|ADSR]] with the addition of a &amp;quot;hold&amp;quot;-period in between the &amp;quot;attack&amp;quot; and &amp;quot;decay&amp;quot; phase. The FAR specific items are the same as outlined in the &amp;quot;lfo&amp;quot;-&#039;&#039;plugin module&#039;&#039; with the exception of the &amp;quot;releasetarget&amp;quot; which triggers once the AHDSR reaches zero. This is useful for doing things like automatically putting the &#039;&#039;bowing jack&#039;&#039; in the &#039;&#039;rest&#039;&#039;-position when used on the &#039;&#039;pressure&#039;&#039; for instance. The &#039;&#039;commands&#039;&#039; for the &amp;quot;ahdsr&amp;quot;-&#039;&#039;plugin module&#039;&#039; are&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long command&lt;br /&gt;
!Short command&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Sets the nickname of the AHDSR&lt;br /&gt;
|-&lt;br /&gt;
|enable&lt;br /&gt;
|en&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Disables / Enables the output of the &#039;&#039;target commands&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|target&lt;br /&gt;
|tg&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the command string to execute each update cycle, the string [lfoout] will be replaced with the current value&lt;br /&gt;
|-&lt;br /&gt;
|updaterate&lt;br /&gt;
|ur&lt;br /&gt;
|milliseconds&lt;br /&gt;
|Sets the frequency with which the &#039;&#039;target commands&#039;&#039; are executed. Limited by the global maximum as set in the plugin handler&lt;br /&gt;
|-&lt;br /&gt;
|gate&lt;br /&gt;
|gt&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Gate signal, [1] initiates the &#039;&#039;attack&#039;&#039; phase and if it reaches its maximum value, &#039;&#039;holds&#039;&#039; for the time given. It then continues through the &#039;&#039;decay&#039;&#039; down to the &#039;&#039;sustain&#039;&#039; point. A [0] initiates the &#039;&#039;release&#039;&#039; from whatever point the ADSR is at&lt;br /&gt;
|-&lt;br /&gt;
|attack&lt;br /&gt;
|at&lt;br /&gt;
|milliseconds&lt;br /&gt;
|Attack time in milliseconds&lt;br /&gt;
|-&lt;br /&gt;
|hold&lt;br /&gt;
|hd&lt;br /&gt;
|milliseconds&lt;br /&gt;
|Hold time in milliseconds&lt;br /&gt;
|-&lt;br /&gt;
|decay&lt;br /&gt;
|dc&lt;br /&gt;
|milliseconds&lt;br /&gt;
|Decay time in milliseconds&lt;br /&gt;
|-&lt;br /&gt;
|sustain&lt;br /&gt;
|su&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sustain point in amplitude units&lt;br /&gt;
|-&lt;br /&gt;
|release&lt;br /&gt;
|re&lt;br /&gt;
|milliseconds&lt;br /&gt;
|Release time in milliseconds&lt;br /&gt;
|-&lt;br /&gt;
|releasetarget&lt;br /&gt;
|rt&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|&#039;&#039;Commands&#039;&#039; to execute once the release has hit zero&lt;br /&gt;
|-&lt;br /&gt;
|amplitude&lt;br /&gt;
|amp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Output amplitude&lt;br /&gt;
|-&lt;br /&gt;
|invert&lt;br /&gt;
|inv&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Inverts the results and gives negative values&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;numbermap&amp;quot;-&#039;&#039;plugin module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;numbermap&amp;quot;-&#039;&#039;plugin module&#039;&#039; is used to &amp;quot;map&amp;quot; a incoming number to a different outgoing number. The idea of the &#039;&#039;Number Map&#039;&#039; is for instance to scale the volume of different overtones to be more even by modifying the &#039;&#039;bow pressure&#039;&#039; depending on what &#039;&#039;harmonic&#039;&#039; is being played. Another use case would be to group certain &#039;&#039;MIDI&#039;&#039; keys to address a certain string, and other &#039;&#039;MIDI&#039;&#039; keys addressing another, depending on the how well different strings can render certain tones / harmonics.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;Number Map&#039;&#039; first needs a data set of several points where each point contains &amp;quot;an input of x outputs y&amp;quot;. The &#039;&#039;Number Map&#039;&#039; is then &#039;&#039;triggered&#039;&#039; with a value of &#039;&#039;x&#039;&#039;. When this happens it looks in its database for anything mapped to &#039;&#039;x&#039;&#039;, if it finds it it outputs the &#039;&#039;commands&#039;&#039; set by the &#039;&#039;target&#039;&#039; but first replaces any occurances of the word &amp;quot;nmout&amp;quot; in the &#039;&#039;command string&#039;&#039; with the value of &#039;&#039;y&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;numbermap&amp;quot;-&#039;&#039;plugin modules&#039;&#039; commands&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Sets the nickname of the numbermap&lt;br /&gt;
|-&lt;br /&gt;
|target&lt;br /&gt;
|tg&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the &#039;&#039;commands&#039;&#039; to execute whenever the &amp;quot;numbermap&amp;quot;-&#039;&#039;plugin modules&#039;&#039; is triggered with a mapped value&lt;br /&gt;
|-&lt;br /&gt;
|data&lt;br /&gt;
|da&lt;br /&gt;
|(in:out)*&lt;br /&gt;
|Set the map data in any number of pairs of [in] returns [out]&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|in&lt;br /&gt;
|Removes the map with [in] if it exists&lt;br /&gt;
|-&lt;br /&gt;
|scale&lt;br /&gt;
|sc&lt;br /&gt;
|?&lt;br /&gt;
|Sets the overall scale of the Number Map&lt;br /&gt;
|-&lt;br /&gt;
|trigger&lt;br /&gt;
|tr&lt;br /&gt;
|in&lt;br /&gt;
|Triggers the &#039;&#039;targets&#039;&#039; with the &#039;&#039;out&#039;&#039; number mapped to &#039;&#039;in&#039;&#039; if found&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Knaadmin</name></author>
	</entry>
	<entry>
		<id>http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_reference_V1.1&amp;diff=1690</id>
		<title>The Ekdahl FAR - Command reference V1.1</title>
		<link rel="alternate" type="text/html" href="http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_reference_V1.1&amp;diff=1690"/>
		<updated>2026-06-14T13:34:32Z</updated>

		<summary type="html">&lt;p&gt;Knaadmin: /* The &amp;quot;numbermap&amp;quot;-plugin module */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
The Ekdahl FAR V1.1 introduces the concept of &#039;&#039;modules&#039;&#039;. A &#039;&#039;module&#039;&#039; can contain any number of &#039;&#039;commands&#039;&#039; as well as other &#039;&#039;modules&#039;&#039;. Furthermore any number of &#039;&#039;modules&#039;&#039; of the same type can exist within a context, these are addressed using classic C-style array &#039;&#039;indexing&#039;&#039; with the help of brackets (&amp;quot;[ ]&amp;quot;). Extending on the classic usage, multiple &#039;&#039;indexes&#039;&#039; can be addressed simultaneously by either comma-separating the objects (&amp;quot;[0,3,4]&amp;quot;) and using &#039;&#039;ranges&#039;&#039; (&amp;quot;[3-6]&amp;quot;). &#039;&#039;Modules&#039;&#039; can be either &#039;&#039;internal&#039;&#039; or &#039;&#039;external&#039;&#039;, meaning that they may all physically exist within a single hardware object, or they can be be remote-controlled devices. From a user perspective this however makes no difference as they will appear the same.&lt;br /&gt;
&lt;br /&gt;
While all &#039;&#039;modules&#039;&#039; have their own set of &#039;&#039;commands&#039;&#039;, there are certain &#039;&#039;commands&#039;&#039; that all &#039;&#039;modules&#039;&#039; &amp;lt;u&amp;gt;must&amp;lt;/u&amp;gt; implement and can thus be accessed anywhere within the &#039;&#039;module hierarchy.&#039;&#039; There are also &#039;&#039;base commands&#039;&#039; that always exist within any given FAR ecosystem as well as product-specific &#039;&#039;base commands&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Ubiquitous commands ==&lt;br /&gt;
The &#039;&#039;module commands&#039;&#039; that are &amp;lt;u&amp;gt;required&amp;lt;/u&amp;gt; to be implemented in &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; &#039;&#039;modules&#039;&#039; and that can thus be accessed from anywhere are&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|list&lt;br /&gt;
|ls&lt;br /&gt;
|hidden/h:modules/m:commands/c:instances/i:instancecounts/ic:recursive/r&lt;br /&gt;
|Lists all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039; under the current module depending on the parameters given; &#039;hidden&#039; includes normally hidden &#039;&#039;commands&#039;&#039;, &#039;modules&#039; includes any &#039;&#039;submodules&#039;&#039;, &#039;commands&#039; shows &#039;&#039;commands&#039;&#039;, &#039;instances&#039; shows data for each individual instance of a &#039;&#039;module&#039;&#039;, &#039;instancecounts&#039; includes number of instances of each &#039;&#039;module&#039;&#039;, &#039;recursive&#039; lists all child &#039;&#039;modules&#039;&#039; / &#039;&#039;commands&#039;&#039;. No parameters defaults to showing all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039; recursively with instance counts. It doesn&#039;t show per-instance data or hidden commands.&lt;br /&gt;
|-&lt;br /&gt;
|help&lt;br /&gt;
|help&lt;br /&gt;
|recursive/r&lt;br /&gt;
|Shows a brief explanation of all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039;, shows the help for all &#039;&#039;submodules&#039;&#039; as well if &#039;recursive&#039;&lt;br /&gt;
|-&lt;br /&gt;
|dumpdata&lt;br /&gt;
|dump&lt;br /&gt;
|recursive/r&lt;br /&gt;
|Dumps all data saved for the current &#039;&#039;module&#039;&#039;, will list the data of all &#039;&#039;submodules&#039;&#039; as well if &#039;recursive&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Base commands ==&lt;br /&gt;
B&#039;&#039;ase commands&#039;&#039; are &#039;&#039;commands&#039;&#039; that always exist at the root in any implementation of the Ekdahl FAR.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|version&lt;br /&gt;
|ver&lt;br /&gt;
| -&lt;br /&gt;
|Gets the current firmware version&lt;br /&gt;
|-&lt;br /&gt;
|debugprint&lt;br /&gt;
|dp&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;command|usb|hardware|undefined|priority|error|inforequest|expressionparser|debug:1|0&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Turns on or off serial feedback for the given item&lt;br /&gt;
|-&lt;br /&gt;
|requestinfo&lt;br /&gt;
|rqi&lt;br /&gt;
|command&lt;br /&gt;
|Retrives any data saved for a &#039;&#039;command&#039;&#039;, if applicable&lt;br /&gt;
|-&lt;br /&gt;
|saveallparameters&lt;br /&gt;
|sap&lt;br /&gt;
| -&lt;br /&gt;
|Saves all avaliable parameters&lt;br /&gt;
|-&lt;br /&gt;
|loadallparameters&lt;br /&gt;
|lap&lt;br /&gt;
| -&lt;br /&gt;
|Loads all avaliable parameters&lt;br /&gt;
|-&lt;br /&gt;
|resetallparameters&lt;br /&gt;
|rap&lt;br /&gt;
| -&lt;br /&gt;
|Resets all saved parameters&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|rst&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;1|0&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Resets the Ekdahl FAR, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|nick&lt;br /&gt;
|nick&lt;br /&gt;
|name&lt;br /&gt;
|Sets the nickname of this unit&lt;br /&gt;
|-&lt;br /&gt;
|nooperation&lt;br /&gt;
|nop&lt;br /&gt;
| -&lt;br /&gt;
|Do absolutely, positively, nothing. Useful for testing and interfacing with computers, it&#039;s a good way to know that the unit is alive and responding since a &amp;quot;nop&amp;quot; is being returned as a response upon reception.&lt;br /&gt;
|-&lt;br /&gt;
|uservariable&lt;br /&gt;
|uv&lt;br /&gt;
|variable(0-9):value&lt;br /&gt;
|Set user variable 0-9 to &#039;value&#039;&lt;br /&gt;
|-&lt;br /&gt;
|expressionparserevaluate&lt;br /&gt;
|epev&lt;br /&gt;
|expression&lt;br /&gt;
|Evaluates an arithmetric expression and sends back the output, all variables and functions that can be used in any &#039;&#039;command string&#039;&#039; can also be used here. Useful for testing expressions.&lt;br /&gt;
|-&lt;br /&gt;
|ifequal&lt;br /&gt;
|ife&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] EQUALS [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring].&lt;br /&gt;
|-&lt;br /&gt;
|ifgreater&lt;br /&gt;
|ifg&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] &amp;gt; [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring]&lt;br /&gt;
|-&lt;br /&gt;
|ifless&lt;br /&gt;
|ifl&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] &amp;lt; [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring]&lt;br /&gt;
|-&lt;br /&gt;
|freeram&lt;br /&gt;
|ram&lt;br /&gt;
| -&lt;br /&gt;
|Shows free RAM memory&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The base also contains the following &#039;&#039;modules:&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|pluginhandler&lt;br /&gt;
|ph&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The Ekdahl FAR stand alone single string unit ==&lt;br /&gt;
The Ekdahl FAR stand-alone single string unit offers these &#039;&#039;commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|calibrateall&lt;br /&gt;
|ca&lt;br /&gt;
| -&lt;br /&gt;
|Performs all calibration routines on the selected bow, see below for routines performed&lt;br /&gt;
|-&lt;br /&gt;
|calibratebowspeed&lt;br /&gt;
|cbs&lt;br /&gt;
| -&lt;br /&gt;
|Finds the minimum and maximum bow speed of the selected bow&lt;br /&gt;
|-&lt;br /&gt;
|calibratebowpressure&lt;br /&gt;
|cbp&lt;br /&gt;
| -&lt;br /&gt;
|Finds the minimum and maximum bow pressure of the selected bow&lt;br /&gt;
|-&lt;br /&gt;
|calibratemute&lt;br /&gt;
|cmu&lt;br /&gt;
| -&lt;br /&gt;
|Calibrate mute settings&lt;br /&gt;
|-&lt;br /&gt;
|pickupstringfrequency&lt;br /&gt;
|psf&lt;br /&gt;
| -&lt;br /&gt;
|Returns the fundamental tone calculated from the current audio signal if apliccable&lt;br /&gt;
|-&lt;br /&gt;
|pickupaudiopeak&lt;br /&gt;
|pap&lt;br /&gt;
| -&lt;br /&gt;
|Returns the peak amplitude of the current audio signal&lt;br /&gt;
|-&lt;br /&gt;
|pickupaudiorms&lt;br /&gt;
|par&lt;br /&gt;
| -&lt;br /&gt;
|Returns the RMS amplitude of the current audio signal&lt;br /&gt;
|}&lt;br /&gt;
The Ekdahl FAR also contains the following &#039;&#039;modules&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|bowingwheel&lt;br /&gt;
|bw&lt;br /&gt;
|-&lt;br /&gt;
|mute&lt;br /&gt;
|mu&lt;br /&gt;
|-&lt;br /&gt;
|solenoid&lt;br /&gt;
|so&lt;br /&gt;
|-&lt;br /&gt;
|controlbox&lt;br /&gt;
|cb&lt;br /&gt;
|-&lt;br /&gt;
|midiconfigurationhandler&lt;br /&gt;
|mcf&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;Bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; contains everything needed to interface with a single &#039;&#039;bowing wheel&#039;&#039;. Each &#039;&#039;bowing wheel&#039;&#039; has its own harmonic series, pressure actuators and direct hardware interface. It contains the following &#039;&#039;commands&#039;&#039;.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|speedmode&lt;br /&gt;
|sm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Bow motor speed mode, 0 = Automatic and 1 = Manual. Automatic mode means that the bowing wheel will automatically turn off after the &#039;&#039;motor timeout&#039;&#039; has been reached after being put into rest mode&lt;br /&gt;
|-&lt;br /&gt;
|motortimeout&lt;br /&gt;
|mt&lt;br /&gt;
|ms&lt;br /&gt;
|Bow motor shutdown timeout after bow having been put into the rest position&lt;br /&gt;
|-&lt;br /&gt;
|pidenable&lt;br /&gt;
|pe&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets the bow PID on/off&lt;br /&gt;
|-&lt;br /&gt;
|motorfaultcommands&lt;br /&gt;
|mfc&lt;br /&gt;
|commands&lt;br /&gt;
|Commands to execute when a motor fault is tripped - !WARNING! Can ruin your instrument if changed&lt;br /&gt;
|-&lt;br /&gt;
|motoroverpowercommands&lt;br /&gt;
|moc&lt;br /&gt;
|commands&lt;br /&gt;
|Commands to execute when motor is over the power limit - !WARNING! Can ruin your instrument if changed&lt;br /&gt;
|}&lt;br /&gt;
The &#039;&#039;modules&#039;&#039; in the &amp;quot;Bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; are as follows&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|bowpressure&lt;br /&gt;
|bp&lt;br /&gt;
|-&lt;br /&gt;
|dcmotor&lt;br /&gt;
|dcm&lt;br /&gt;
|-&lt;br /&gt;
|pid&lt;br /&gt;
|pid&lt;br /&gt;
|-&lt;br /&gt;
|harmonicserieshandler&lt;br /&gt;
|hsh&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; handles the &#039;&#039;pressure&#039;&#039; of the &#039;&#039;bowing wheel&#039;&#039; against the string. The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|baseline&lt;br /&gt;
|ba&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure baseline, modulation is added to this point upward. Typically this is set with a knob on the &#039;&#039;control box&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|modifier&lt;br /&gt;
|mo&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure modulation, added to the baseline&lt;br /&gt;
|-&lt;br /&gt;
|rest&lt;br /&gt;
|rs&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the bow pressure in the &#039;&#039;rest&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|engage&lt;br /&gt;
|en&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the bow pressure in the &#039;&#039;engage&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|stallpressure&lt;br /&gt;
|sp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure stall/maximum position, this parameter is set using &#039;&#039;hardware positioning&#039;&#039; and is used as the absolute maximum for baseline and modifier combiner&lt;br /&gt;
|-&lt;br /&gt;
|engagepressure&lt;br /&gt;
|ep&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure touch/minimum position, this parameter is set using &#039;&#039;hardware position&#039;&#039; and is used as the starting point for when both the baseline and modifier is set to zero&lt;br /&gt;
|-&lt;br /&gt;
|restpressure&lt;br /&gt;
|rp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure rest position, this parameter is set using &#039;&#039;hardware positioning&#039;&#039; and is typically set to a point just below the string where it does not touch at all. The purpose of this is because while the actual hardware might be able to make the bow go even lower, that position might be far enough from the string that once &#039;&#039;engaged&#039;&#039; the bow may have so far to travel that there is perceptible &#039;&#039;latency&#039;&#039;.&lt;br /&gt;
|-&lt;br /&gt;
|engagespeed&lt;br /&gt;
|es&lt;br /&gt;
|1- ~100&lt;br /&gt;
|Bow pressure movement speed when engaging or disengaging&lt;br /&gt;
|-&lt;br /&gt;
|modulationspeed&lt;br /&gt;
|ms&lt;br /&gt;
|0.1 - 10&lt;br /&gt;
|Bow pressure movement speed while engaged&lt;br /&gt;
|-&lt;br /&gt;
|hold&lt;br /&gt;
|hd&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets bow hold (infinite sustain) on/off, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|home&lt;br /&gt;
|hm&lt;br /&gt;
| -&lt;br /&gt;
|Homing bow, used at startup and in case of the bow loosing position&lt;br /&gt;
|-&lt;br /&gt;
|tmcinfo&lt;br /&gt;
|tmi&lt;br /&gt;
| -&lt;br /&gt;
|Request statistical information from the TMC2209 stepper motor driver&lt;br /&gt;
|}&lt;br /&gt;
Note that the &amp;quot;stall&amp;quot;, &amp;quot;engage&amp;quot; and &amp;quot;rest&amp;quot;-pressure positions mention something called &#039;&#039;hardware position&#039;&#039;. This means the entire available movement of the &#039;&#039;bowing jack&#039;&#039;. Because the very bottom and top end of the movement might not be musically useful and may even harm the instrument, the &amp;quot;baseline&amp;quot; and &amp;quot;modifier&amp;quot; commands &#039;&#039;parameter&#039;&#039;s are scaled depending on these settings.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;engage&amp;quot; and &amp;quot;modulation&amp;quot;-speed settings sets how fast the stepper motor that drives the &#039;&#039;pressure&#039;&#039; moves depending on whether the &#039;&#039;bowing jack&#039;&#039; is set to &#039;&#039;engage&#039;&#039; or not. The idea here is that while wanting to be able to minimize &#039;&#039;latency&#039;&#039; by &#039;&#039;engaging&#039;&#039; and &#039;&#039;disengaging&#039;&#039; from the string as quickly as possible, dynamic changes in the &#039;&#039;pressure&#039;&#039; while playing benefits from much smoother movements as the &#039;&#039;bowing wheel&#039;&#039; takes some time to catch up to varying amounts of friction.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; contains one or more of the following &#039;&#039;modules&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|actuatorhandler&lt;br /&gt;
|ah&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;actuatorhandler&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The concept of &amp;quot;actuators&amp;quot; came up as it is possible to have &#039;&#039;bowing wheels&#039;&#039; of different sizes and wanting to be able to switch quickly in between them, perhaps during mid-performance. Because a differently sized wheel will require different values for the above mentioned &amp;quot;stall&amp;quot;, &amp;quot;engage&amp;quot; and &amp;quot;reset&amp;quot;-&#039;&#039;pressure&#039;&#039;, each &#039;&#039;actuator&#039;&#039; stores these values. Instead of having to manually change the previously mentioned values, simply selecting a new &#039;&#039;actuator&#039;&#039; will automatically load the values. The &amp;quot;actuatorhandler&amp;quot;-&#039;&#039;module&#039;&#039; is the handler of one or more &amp;quot;actuator&amp;quot;-&#039;&#039;modules&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;commands&#039;&#039; of the &amp;quot;acuatorhandler&amp;quot;-&#039;&#039;module&#039;&#039; are as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|add&lt;br /&gt;
|a&lt;br /&gt;
|(name):(rest:engage:stall)&lt;br /&gt;
|Add new actuator with the given name and parameters&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|actuatornumber&lt;br /&gt;
|Remove bow actuator [actuatornumber]&lt;br /&gt;
|-&lt;br /&gt;
|count&lt;br /&gt;
|c&lt;br /&gt;
| -&lt;br /&gt;
|Returns the amount of saved bow actuators&lt;br /&gt;
|}&lt;br /&gt;
The &amp;quot;actuatorhandler&amp;quot;-&#039;&#039;module&#039;&#039; contains one or more of&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|actuator&lt;br /&gt;
|ac&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;actuator&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;actuator&amp;quot;-&#039;&#039;module&#039;&#039; contains the following commands&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|[index]&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|Selects the given actuator&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Sets the actuator name&lt;br /&gt;
|-&lt;br /&gt;
|data&lt;br /&gt;
|da&lt;br /&gt;
|name:rest:engage:stall&lt;br /&gt;
|Sets the actuator name, rest, engage and stall &#039;&#039;pressure&#039;&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;dcmotor&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;dcmotor&amp;quot;-&#039;&#039;module&#039;&#039; handles the direct &amp;lt;u&amp;gt;raw&amp;lt;/u&amp;gt; control of the &#039;&#039;bowing motor&#039;&#039; and handles the reporting back of the current speed. It has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|run&lt;br /&gt;
|ru&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Turns the motor off/on&lt;br /&gt;
|-&lt;br /&gt;
|pwm&lt;br /&gt;
|pw&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor direct power in 16-bit PWM values, requires that the &#039;&#039;PID&#039;&#039; is turned off&lt;br /&gt;
|-&lt;br /&gt;
|voltage&lt;br /&gt;
|vo&lt;br /&gt;
|~2 - 10V&lt;br /&gt;
|Sets the voltage of the regulator powering the motor. Changes here can make the motor more responsive to certain frequencies but will also affect how well the &#039;&#039;PID&#039;&#039; works. !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|current&lt;br /&gt;
|cu&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor reported current use&lt;br /&gt;
|-&lt;br /&gt;
|currentlimit&lt;br /&gt;
|cl&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor current limit (A)- !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|powerlimit&lt;br /&gt;
|pl&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor power limit (W) - !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|frequency&lt;br /&gt;
|fq&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor reported frequency&lt;br /&gt;
|-&lt;br /&gt;
|emergencystop&lt;br /&gt;
|es&lt;br /&gt;
|ms (0-65535)&lt;br /&gt;
|Immediately stops the bowing motor and doesn&#039;t allow it to start again until the cool down period given in the first argument has lapsed (milliseconds)&lt;br /&gt;
|-&lt;br /&gt;
|minpwm&lt;br /&gt;
|ip&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor minimum PWM (for calibration)&lt;br /&gt;
|-&lt;br /&gt;
|maxpwm&lt;br /&gt;
|xp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor maximum PWM (for calibration)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;pidcontroller&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;pidcontroller&amp;quot;-&#039;&#039;module&#039;&#039; is responsible for keeping the &amp;quot;dcmotor&amp;quot;-&#039;&#039;module&#039;&#039; at a certain frequency (given in Hertz). It takes the output of the motor frequency measurement and feeds it a PWM value that tries to make the speed constant regardless of the friction that the motor is enduring. To learn more about PID Controllers please see this [[wikipedia:PID_controller|wikipedia article]]. The &#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|targetfrequency&lt;br /&gt;
|tf&lt;br /&gt;
|hertz&lt;br /&gt;
|Sets the PID target frequency&lt;br /&gt;
|-&lt;br /&gt;
|ki&lt;br /&gt;
|ki&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Ki parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|kp&lt;br /&gt;
|kp&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Kp parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|kd&lt;br /&gt;
|kd&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Kd parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|integratorerror&lt;br /&gt;
|ie&lt;br /&gt;
|float&lt;br /&gt;
|Sets the lower threshold of error values for the PID integrator to ignore&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|re&lt;br /&gt;
| -&lt;br /&gt;
|Resets the PID integrator and derivative&lt;br /&gt;
|-&lt;br /&gt;
|maxerror&lt;br /&gt;
|xe&lt;br /&gt;
|float&lt;br /&gt;
|Maximum error to correct in each PID loop, essentially sets acceleration&lt;br /&gt;
|-&lt;br /&gt;
|peakerror&lt;br /&gt;
|pe&lt;br /&gt;
|float&lt;br /&gt;
|Get latest PID peak error&lt;br /&gt;
|-&lt;br /&gt;
|motorspeedmax&lt;br /&gt;
|msx&lt;br /&gt;
|Hertz&lt;br /&gt;
|Bow motor maximum speed limit&lt;br /&gt;
|-&lt;br /&gt;
|motorspeedmin&lt;br /&gt;
|msi&lt;br /&gt;
|Hertz&lt;br /&gt;
|Bow motor minimum speed limit&lt;br /&gt;
|-&lt;br /&gt;
|measuretimetotarget&lt;br /&gt;
|mtt&lt;br /&gt;
|Hertz&lt;br /&gt;
|Measure the time it takes to change from the current frequency to the target frequency, for testing purposes&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; is responsible for sending frequency data to the &amp;quot;pid&amp;quot;-&#039;&#039;module&#039;&#039;. It handles calculating the correct frequency of the &#039;&#039;bowing wheel&#039;&#039; according to the selected &#039;&#039;harmonic&#039;&#039; and &#039;&#039;harmonic shift&#039;&#039; per the currently selected &#039;&#039;harmonic series&#039;&#039;. The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|fundamental&lt;br /&gt;
|fu&lt;br /&gt;
|Hertz&lt;br /&gt;
|The fundamental frequency of the string, all harmonics are calculated from this number&lt;br /&gt;
|-&lt;br /&gt;
|harmonic&lt;br /&gt;
|h&lt;br /&gt;
|int&lt;br /&gt;
|Selects the harmonic number to set the &#039;&#039;bowing wheel&#039;&#039; to. A ratio is taken from the given &#039;&#039;harmonic&#039;&#039; in the current &#039;&#039;harmonic series&#039;&#039;, the ratio is then multiplied by the &#039;&#039;fundamental frequency&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|harmonicadd&lt;br /&gt;
|ha&lt;br /&gt;
|int&lt;br /&gt;
|This number is added to the current harmonic&lt;br /&gt;
|-&lt;br /&gt;
|harmonicbase&lt;br /&gt;
|hb&lt;br /&gt;
|int&lt;br /&gt;
|Same as harmonic but where the harmonic number is based on a MIDI note given by basenote&lt;br /&gt;
|-&lt;br /&gt;
|basenote&lt;br /&gt;
|bn&lt;br /&gt;
|0-127&lt;br /&gt;
|Sets the MIDI base note of the &#039;&#039;bowing wheel&#039;&#039;, used in conjunction with &amp;quot;harmonicbase&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|shift&lt;br /&gt;
|sh&lt;br /&gt;
| -32767 - 32767&lt;br /&gt;
|Sets shift from the currently playing harmonic where 32767 equals the entire harmonic shift range shifted up&lt;br /&gt;
|-&lt;br /&gt;
|shiftrange&lt;br /&gt;
|sr&lt;br /&gt;
|0-36&lt;br /&gt;
|Set the number of harmonic numbers that constitutes an entire harmonic shift&lt;br /&gt;
|-&lt;br /&gt;
|shift5&lt;br /&gt;
|sh5&lt;br /&gt;
| -32767 - 32767&lt;br /&gt;
|Sets the shift from the currently playing harmonic over 5 octaves where 32767 equals 5 octaves shift up from the fundamental&lt;br /&gt;
|-&lt;br /&gt;
|add&lt;br /&gt;
|a&lt;br /&gt;
|(name):(ratios)&lt;br /&gt;
|Add a new series with the given name and parameters&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|series&lt;br /&gt;
|Remove the series given and shift any series accordingly. Cannot remove all series&lt;br /&gt;
|-&lt;br /&gt;
|count&lt;br /&gt;
|c&lt;br /&gt;
| -&lt;br /&gt;
|Returns the number of harmonic series in the list and their IDs&lt;br /&gt;
|}&lt;br /&gt;
The &amp;quot;harmonicserieshandler&amp;quot;-module contains at the very least ONE harmonic series, by default it contains two: one for equal temperament and one for just intonation. The current series can be selected by simply indexing the &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; without a &#039;&#039;command&#039;&#039;, e.g. &amp;quot;harmonicserieshandler.harmonicseries[1]&amp;quot;. To be consistent, these are the &#039;&#039;modules&#039;&#039; in the &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|harmonicseries&lt;br /&gt;
|hs&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; contains any number of &#039;&#039;ratios&#039;&#039; that comprises a scale, ratios are given in a standard format where a ratio of &amp;quot;1&amp;quot; is equal to the fundamental, &amp;quot;2&amp;quot; would be one octave up etc. A standard &#039;&#039;harmonic series&#039;&#039; contains 12 ratios following a just intonation scheme. The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; will automatically adapt to the currently selected &#039;&#039;harmonic series&#039;&#039; length, whether it&#039;s a standard 12-tone scale, some kinda 3-tone scale or a full on bananas 53-tone scale. The &#039;&#039;commands&#039;&#039; of the &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; is as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|[index]&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
|Sets the currently selected &#039;&#039;harmonic Series&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Sets the name of the &#039;&#039;harmonic series&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|data&lt;br /&gt;
|da&lt;br /&gt;
|name:ratios&lt;br /&gt;
|Gets / sets all data for the &#039;&#039;harmonic series&#039;&#039; in the given slot with an arbitrary &#039;&#039;name&#039;&#039; as the first &#039;&#039;parameter&#039;&#039;. The length of the series is simply set to the amount of ratios given&lt;br /&gt;
|-&lt;br /&gt;
|ratio&lt;br /&gt;
|r&lt;br /&gt;
|harmonic:ratio&lt;br /&gt;
|Sets the ratio of the given harmonic in current &#039;&#039;harmonic series&#039;&#039;, will increase the list size if needed to address the harmonic&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|harmonic&lt;br /&gt;
|Remove the harmonic ratio given in the current series and shift any ratios accordingly. Cannot remove all ratios&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;mute&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;mute&amp;quot;-&#039;&#039;module&#039;&#039; works very similarly to the &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; in that it controls a stepper motor with some software limits in place in order to press the mute against the string. The &#039;&#039;commands&#039;&#039; are as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|setposition&lt;br /&gt;
|sp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set mute position&lt;br /&gt;
|-&lt;br /&gt;
|fullmute&lt;br /&gt;
|fm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the mute in &#039;&#039;full mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|halfmute&lt;br /&gt;
|hm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the mute in &#039;&#039;half mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|rest&lt;br /&gt;
|rs&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Put the mute in the &#039;&#039;rest&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|savefull&lt;br /&gt;
|sf&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Save the current mute position as the &#039;&#039;full mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|savehalf&lt;br /&gt;
|sh&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Save the current mute position as the &#039;&#039;half mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|saverest&lt;br /&gt;
|sr&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Save the current mute position as the &#039;&#039;rest&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|fullmuteposition&lt;br /&gt;
|fmp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;full mute&#039;&#039; position according to the &#039;&#039;hardware position&#039;&#039; given&lt;br /&gt;
|-&lt;br /&gt;
|halfmuteposition&lt;br /&gt;
|hmp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;half mute&#039;&#039; position according to the &#039;&#039;hardware position&#039;&#039; given&lt;br /&gt;
|-&lt;br /&gt;
|restposition&lt;br /&gt;
|rp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;rest&#039;&#039; position according to the &#039;&#039;hardware position&#039;&#039; given&lt;br /&gt;
|-&lt;br /&gt;
|sustain&lt;br /&gt;
|su&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets the sustain off/on, this will keep the mute in the &#039;&#039;rest&#039;&#039; position even if a &amp;quot;fullmute&amp;quot;-&#039;&#039;command&#039;&#039; is given, lasts until &amp;quot;sustain&amp;quot; is set to &amp;quot;0&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
|backoff&lt;br /&gt;
|bo&lt;br /&gt;
|0-65535&lt;br /&gt;
|Setting the time that the mute stays in the mutefullmute position before automatically going into rest, set in mS. A value of &amp;quot;0&amp;quot; disables backoff. This is used because if the mute is not backing off until something is attempted to be played, the backing-off time will either introduce &#039;&#039;latency&#039;&#039; or the string will be initially partially muted&lt;br /&gt;
|-&lt;br /&gt;
|home&lt;br /&gt;
|hm&lt;br /&gt;
| -&lt;br /&gt;
|Home mute, used during initialization and if the mute were to loose position&lt;br /&gt;
|-&lt;br /&gt;
|hardwareposition&lt;br /&gt;
|hwp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;hardware position&#039;&#039; of the mute instead of scaling it over the &#039;&#039;full mute&#039;&#039; and &#039;&#039;rest&#039;&#039; positions. Mainly used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|completetask&lt;br /&gt;
|cpt&lt;br /&gt;
| -&lt;br /&gt;
|Requests a callback when the current operation is finished. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|autocorrect&lt;br /&gt;
|ac&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Enables auto correct positioning that uses the homing sensor to correct positioning on the fly. EXPERIMENTAL&lt;br /&gt;
|-&lt;br /&gt;
|homingsensed&lt;br /&gt;
|hms&lt;br /&gt;
| -&lt;br /&gt;
|Requests whether the homing sensor is currently active or not. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|movedirection&lt;br /&gt;
|md&lt;br /&gt;
| -&lt;br /&gt;
|Requests the current direction of movement (0 Forward, 1 Reverse). Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|currentstep&lt;br /&gt;
|cs&lt;br /&gt;
| -&lt;br /&gt;
|Requests the current step. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|homingpoint&lt;br /&gt;
|hmp&lt;br /&gt;
|edgedirection&lt;br /&gt;
|Requests the given homing point. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|homingstage&lt;br /&gt;
|hms&lt;br /&gt;
| -&lt;br /&gt;
|Requests the current homing stage (UNHOMED, HOMED, FIRSTHOMINGRISING, SECONDHOMINGFALLING, SECONDHOMINGRISING, FIRSTHOMINGFALLING, MOVEPASTHOMESWITCH, MOVETOHOMESWITCH, GOTOOFFSET). Only used internally by other &#039;&#039;modules.&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|tmcinfo&lt;br /&gt;
|tmi&lt;br /&gt;
| -&lt;br /&gt;
|Request statistical information from the TMC2209 stepper motor driver&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;solenoid&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;solenoid&amp;quot;-&#039;&#039;module&#039;&#039; currently controls the &#039;&#039;hammer&#039;&#039; of the Ekdahl FAR. Due to the fact that the very same &#039;&#039;module&#039;&#039; could be used for anything that uses a striking &#039;&#039;solenoid&#039;&#039; it was named as such. It has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|engage&lt;br /&gt;
|en&lt;br /&gt;
|0-65535&lt;br /&gt;
|Engages the solenoid using the first parameter as the force&lt;br /&gt;
|-&lt;br /&gt;
|rest&lt;br /&gt;
|rs&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Forces the solenoid to its rest position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|maxforce&lt;br /&gt;
|xf&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set solenoid maximum usable force&lt;br /&gt;
|-&lt;br /&gt;
|minforce&lt;br /&gt;
|if&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set solenoid minimum usable force&lt;br /&gt;
|-&lt;br /&gt;
|forcemultiplier&lt;br /&gt;
|fm&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set solenoid force multiplier, useful for scaling of all incoming &amp;quot;engage&amp;quot;-&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|engageduration&lt;br /&gt;
|ed&lt;br /&gt;
|uS&lt;br /&gt;
|Sets the duration of the solenoid hit in uS, if a value of 0 is set the solenoid will not disengage until a rest command has been given. WARNING!! HAVING THE SOLENOID ON FOR A SPAN OF SECONDS COULD DESTROY THE CIRCUITRY!!&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;controlbox&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;controlbox&amp;quot;-&#039;&#039;module&#039;&#039; communicates with an external &#039;&#039;control box&#039;&#039; and will issue associated &#039;&#039;commands&#039;&#039; whenever new values are read on the ADC-converters. It handles averaging and does some noise-cancellation functions on the values as well. The &#039;&#039;commands&#039;&#039; are:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|harmonic&lt;br /&gt;
|har&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the harmonic knob or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|harmonicshift&lt;br /&gt;
|has&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the harmonic shift modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|finetune&lt;br /&gt;
|fin&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the fine tune knob changes&lt;br /&gt;
|-&lt;br /&gt;
|pressure&lt;br /&gt;
|pre&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the pressure knob or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|mute&lt;br /&gt;
|mut&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the mute knob or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|hammerscale&lt;br /&gt;
|hms&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the hammer scale knob changes&lt;br /&gt;
|-&lt;br /&gt;
|gate&lt;br /&gt;
|gt&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the gate switch or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|hammertrig&lt;br /&gt;
|hmt&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the hammer trigger modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|controldefaults&lt;br /&gt;
|cde&lt;br /&gt;
| -&lt;br /&gt;
|Reverts all ADC command strings to default values&lt;br /&gt;
|-&lt;br /&gt;
|datareturn&lt;br /&gt;
|dr&lt;br /&gt;
|channel:value&lt;br /&gt;
|Sent when a new value is presented on one of the ADC channels, cannot be invoked. Triggers the commands associated with the channel&lt;br /&gt;
|-&lt;br /&gt;
|adcsetting&lt;br /&gt;
|adcs&lt;br /&gt;
|channel : averages : interrupterrorthreshold : continuouserrorthreshold : continuoustimeout&lt;br /&gt;
|Sets ADC settings for a given channel. Averages are the number of samples to average, interruptthreshold is how much the value must change in order to issue a new value change event. continuousthreshold is how much the value must change when a previous change has already been recorded within the timespan of continuoustimeout&lt;br /&gt;
|-&lt;br /&gt;
|testadclatency&lt;br /&gt;
|tal&lt;br /&gt;
|0-65535&lt;br /&gt;
|Start a ADC latency test&lt;br /&gt;
|-&lt;br /&gt;
|testadclatencyreturn&lt;br /&gt;
|talr&lt;br /&gt;
| -&lt;br /&gt;
|Return from latency test&lt;br /&gt;
|-&lt;br /&gt;
|testadcminmax&lt;br /&gt;
|tix&lt;br /&gt;
|channel&lt;br /&gt;
|Test min/max value for a given channel and resets the counter&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;midiconfigurationhandler&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;midiconfigurationhandler&amp;quot;-&#039;&#039;module&#039;&#039; handles a number of &amp;quot;midiconfiguration&amp;quot;-&#039;&#039;modules&#039;&#039;. It has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|allnotesoff&lt;br /&gt;
|ano&lt;br /&gt;
| -&lt;br /&gt;
|Clears the entire buffer of MIDI notes held&lt;br /&gt;
|-&lt;br /&gt;
|add&lt;br /&gt;
|a&lt;br /&gt;
|name&lt;br /&gt;
|Adds a new MIDI configuration with the given name&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|int&lt;br /&gt;
|Remove the specified MIDI configuration&lt;br /&gt;
|-&lt;br /&gt;
|count&lt;br /&gt;
|c&lt;br /&gt;
| -&lt;br /&gt;
|Returns the number of MIDI configurations&lt;br /&gt;
|}&lt;br /&gt;
It contains one or more of the following&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|midiconfiguration&lt;br /&gt;
|mc&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;midiconfiguration&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
A &amp;quot;midiconfiguration&amp;quot;-&#039;&#039;module&#039;&#039; handles the reception of &#039;&#039;MIDI messages&#039;&#039; and will output the associated &#039;&#039;commands&#039;&#039; to the instrument internally. The commands are as follows&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|[index]&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
|Sets the currently selected MIDI configuration&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Set the name of the MIDI configuration&lt;br /&gt;
|-&lt;br /&gt;
|noteon&lt;br /&gt;
|non&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Note On event&lt;br /&gt;
|-&lt;br /&gt;
|noteoff&lt;br /&gt;
|nof&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Note Off event&lt;br /&gt;
|-&lt;br /&gt;
|polyaftertouch&lt;br /&gt;
|pat&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Polyphonic after touch event&lt;br /&gt;
|-&lt;br /&gt;
|channelaftertouch&lt;br /&gt;
|cat&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Channel after touch event&lt;br /&gt;
|-&lt;br /&gt;
|pitchbend&lt;br /&gt;
|pb&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Pitch bend event&lt;br /&gt;
|-&lt;br /&gt;
|programchange&lt;br /&gt;
|pc&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Program change event&lt;br /&gt;
|-&lt;br /&gt;
|continuouscontrollerdata&lt;br /&gt;
|ccd&lt;br /&gt;
|controllernuber:&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Continuous controller event with the given [&#039;&#039;controllernumber&#039;&#039;]&lt;br /&gt;
|-&lt;br /&gt;
|removecc&lt;br /&gt;
|rmc&lt;br /&gt;
|controllernuber&lt;br /&gt;
|Removes the entry associated with the MIDI continuous controller even &#039;&#039;controllernumber&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|defaults&lt;br /&gt;
|d&lt;br /&gt;
| -&lt;br /&gt;
|Reverts the current configuration to default &#039;&#039;commands&#039;&#039;, values and CCs&lt;br /&gt;
|-&lt;br /&gt;
|receivechannel&lt;br /&gt;
|rc&lt;br /&gt;
|channel&lt;br /&gt;
|Sets the MIDI receive channel of the current configuration. 1-16 sets specific channel, any other value for OMNI&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;pluginhandler&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The Ekdahl FAR allows for &#039;&#039;plugins&#039;&#039;. These are &#039;&#039;modules&#039;&#039; that can trigger certain &#039;&#039;command strings&#039;&#039; to be executed either periodically or triggered by an incoming &#039;&#039;command&#039;&#039;. Further explanation of the given &#039;&#039;plugins&#039;&#039; is given below. The various &#039;&#039;plugins&#039;&#039; are handled by the &amp;quot;pluginhandler&amp;quot;-&#039;&#039;module&#039;&#039;, the different &#039;&#039;plugin modules&#039;&#039; are identified by their own unique &#039;&#039;ID&#039;&#039;. The &amp;quot;pluginhandler&amp;quot;-&#039;&#039;module&#039;&#039; it has the following &#039;&#039;commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|add&lt;br /&gt;
|a&lt;br /&gt;
|pluginid&lt;br /&gt;
|Add plugin with the given ID&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|pluginid:index&lt;br /&gt;
|Remove plugin with the given ID and index&lt;br /&gt;
|-&lt;br /&gt;
|count&lt;br /&gt;
|c&lt;br /&gt;
|(pluginid)&lt;br /&gt;
|Return the number of plugins of the given type, if none is given it returns all plugins&lt;br /&gt;
|}&lt;br /&gt;
The number of available &#039;&#039;plugins&#039;&#039; will differ from time to time as the &#039;&#039;plugin system&#039;&#039; has been purposefully designed to allow for anyone to write and add their own &#039;&#039;plugins&#039;&#039;. As of the current writing (2026-06-14) the number of &amp;lt;u&amp;gt;possible&amp;lt;/u&amp;gt; &#039;&#039;plugin modules&#039;&#039; that &amp;lt;u&amp;gt;can&amp;lt;/u&amp;gt; exist under the &amp;quot;pluginhandler&amp;quot;-&#039;&#039;module&#039;&#039; are&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|lfo&lt;br /&gt;
|lfo&lt;br /&gt;
|-&lt;br /&gt;
|ahdsr&lt;br /&gt;
|ahdsr&lt;br /&gt;
|-&lt;br /&gt;
|numbermap&lt;br /&gt;
|map&lt;br /&gt;
|-&lt;br /&gt;
|multiple&lt;br /&gt;
|mlt&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;lfo&amp;quot;-&#039;&#039;plugin module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;lfo&amp;quot;-&#039;&#039;plugin module&#039;&#039; works like regular [[wikipedia:Low-frequency_oscillation|low frequency oscillator]] in that it generates a given &#039;&#039;waveform&#039;&#039; with a given &#039;&#039;frequency&#039;&#039; at a certain &#039;&#039;amplitude&#039;&#039;. In the Ekdahl FAR the distinguishing factors are that besides the common &#039;&#039;frequency, amplitude&#039;&#039; and &#039;&#039;waveform&#039;&#039; parameters, it also requires the use of a &#039;&#039;update rate&#039;&#039; and &#039;&#039;target&#039;&#039; parameter. The &#039;&#039;update rate&#039;&#039; sets how often the current position of the LFO is sampled (aka how often it peeks in on where the LFO is in its waveform transition at the moment), and each time that happens, the &#039;&#039;target commands&#039;&#039; are outputted to the instrument.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example:&#039;&#039;&#039;&lt;br /&gt;
 Lets set the &#039;&#039;waveform&#039;&#039; to &amp;quot;triangle&amp;quot;, the &#039;&#039;amplitude&#039;&#039; to 65535 (max), the &#039;&#039;frequency&#039;&#039; to 1Hz (1 full waveform per second), the &#039;&#039;update rate&#039;&#039; to 10mS and the &#039;&#039;target&#039;&#039; to &amp;quot;bowingwheel.harmonicserieshandler.shift:lfoout&amp;quot;.&lt;br /&gt;
 &lt;br /&gt;
 The output of the LFO is always given in the variable &amp;quot;lfoout&amp;quot;, our &#039;&#039;target&#039;&#039; is set to &amp;quot;bowingwheel.harmonicserieshandler.shift&amp;quot; which controls the &#039;&#039;harmonic shift&#039;&#039; (pitchbend basically) of the &#039;&#039;bowing wheel&#039;&#039;.&lt;br /&gt;
 &lt;br /&gt;
 Since our update rate is set to every 10 milliseconds and our frequency is 1 Hertz the instrument will internally send 100 updates per second to the &#039;&#039;harmonic shift.&#039;&#039; Our amplitude is set to the maximum value and depending on the &amp;quot;harmonicserieshandler.shiftrange&amp;quot; this could give a smooth vibrato like sound or more of an experimental one with a wider range. If the modulation is too deep we can just adjust the amplitude of the LFO.&lt;br /&gt;
The &amp;quot;lfo&amp;quot;-&#039;&#039;plugin modules commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Sets the nickname of the LFO&lt;br /&gt;
|-&lt;br /&gt;
|enable&lt;br /&gt;
|en&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Disables / Enables the output of the &#039;&#039;target&#039;&#039; &#039;&#039;commands&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|target&lt;br /&gt;
|tg&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the command string to execute each update cycle, the string [lfoout] will be replaced with the current value&lt;br /&gt;
|-&lt;br /&gt;
|updaterate&lt;br /&gt;
|ur&lt;br /&gt;
|milliseconds&lt;br /&gt;
|Sets the frequency with which the &#039;&#039;target commands&#039;&#039; are executed. Limited by the global maximum as set in the plugin handler&lt;br /&gt;
|-&lt;br /&gt;
|waveform&lt;br /&gt;
|wf&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;sine|triangle|square|saw&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets the LFO waveform&lt;br /&gt;
|-&lt;br /&gt;
|frequency&lt;br /&gt;
|fq&lt;br /&gt;
|Hertz&lt;br /&gt;
|Sets the LFO frequency&lt;br /&gt;
|-&lt;br /&gt;
|amplitude&lt;br /&gt;
|amp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the LFO amplitude&lt;br /&gt;
|-&lt;br /&gt;
|delay&lt;br /&gt;
|dl&lt;br /&gt;
|0-65535 milliseconds&lt;br /&gt;
|Ramps up the amplitude of the output waveform from zero to full amplitude in the given time span&lt;br /&gt;
|-&lt;br /&gt;
|resetdelay&lt;br /&gt;
|rd&lt;br /&gt;
| -&lt;br /&gt;
|Resets the delay and starts the ramping of the waveform&lt;br /&gt;
|-&lt;br /&gt;
|resetwave&lt;br /&gt;
|rw&lt;br /&gt;
| -&lt;br /&gt;
|Resets the waveform from the start (sync)&lt;br /&gt;
|-&lt;br /&gt;
|bipolar&lt;br /&gt;
|bp&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets whether the waveform is bipolar (default) or positive only&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;ahdsr&amp;quot;-&#039;&#039;plugin module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;ahdsr&amp;quot;-&#039;&#039;plugin module&#039;&#039; works like a standard [[wikipedia:ADSR|ADSR]] with the addition of a &amp;quot;hold&amp;quot;-period in between the &amp;quot;attack&amp;quot; and &amp;quot;decay&amp;quot; phase. The FAR specific items are the same as outlined in the &amp;quot;lfo&amp;quot;-&#039;&#039;plugin module&#039;&#039; with the exception of the &amp;quot;releasetarget&amp;quot; which triggers once the AHDSR reaches zero. This is useful for doing things like automatically putting the &#039;&#039;bowing jack&#039;&#039; in the &#039;&#039;rest&#039;&#039;-position when used on the &#039;&#039;pressure&#039;&#039; for instance. The &#039;&#039;commands&#039;&#039; for the &amp;quot;ahdsr&amp;quot;-&#039;&#039;plugin module&#039;&#039; are&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long command&lt;br /&gt;
!Short command&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Sets the nickname of the AHDSR&lt;br /&gt;
|-&lt;br /&gt;
|enable&lt;br /&gt;
|en&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Disables / Enables the output of the &#039;&#039;target commands&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|target&lt;br /&gt;
|tg&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the command string to execute each update cycle, the string [lfoout] will be replaced with the current value&lt;br /&gt;
|-&lt;br /&gt;
|updaterate&lt;br /&gt;
|ur&lt;br /&gt;
|milliseconds&lt;br /&gt;
|Sets the frequency with which the &#039;&#039;target commands&#039;&#039; are executed. Limited by the global maximum as set in the plugin handler&lt;br /&gt;
|-&lt;br /&gt;
|gate&lt;br /&gt;
|gt&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Gate signal, [1] initiates the &#039;&#039;attack&#039;&#039; phase and if it reaches its maximum value, &#039;&#039;holds&#039;&#039; for the time given. It then continues through the &#039;&#039;decay&#039;&#039; down to the &#039;&#039;sustain&#039;&#039; point. A [0] initiates the &#039;&#039;release&#039;&#039; from whatever point the ADSR is at&lt;br /&gt;
|-&lt;br /&gt;
|attack&lt;br /&gt;
|at&lt;br /&gt;
|milliseconds&lt;br /&gt;
|Attack time in milliseconds&lt;br /&gt;
|-&lt;br /&gt;
|hold&lt;br /&gt;
|hd&lt;br /&gt;
|milliseconds&lt;br /&gt;
|Hold time in milliseconds&lt;br /&gt;
|-&lt;br /&gt;
|decay&lt;br /&gt;
|dc&lt;br /&gt;
|milliseconds&lt;br /&gt;
|Decay time in milliseconds&lt;br /&gt;
|-&lt;br /&gt;
|sustain&lt;br /&gt;
|su&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sustain point in amplitude units&lt;br /&gt;
|-&lt;br /&gt;
|release&lt;br /&gt;
|re&lt;br /&gt;
|milliseconds&lt;br /&gt;
|Release time in milliseconds&lt;br /&gt;
|-&lt;br /&gt;
|releasetarget&lt;br /&gt;
|rt&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|&#039;&#039;Commands&#039;&#039; to execute once the release has hit zero&lt;br /&gt;
|-&lt;br /&gt;
|amplitude&lt;br /&gt;
|amp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Output amplitude&lt;br /&gt;
|-&lt;br /&gt;
|invert&lt;br /&gt;
|inv&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Inverts the results and gives negative values&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;numbermap&amp;quot;-&#039;&#039;plugin module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;numbermap&amp;quot;-&#039;&#039;plugin module&#039;&#039; is used to &amp;quot;map&amp;quot; a incoming number to a different outgoing number. The idea of the &#039;&#039;Number Map&#039;&#039; is for instance to scale the volume of different overtones to be more even by modifying the &#039;&#039;bow pressure&#039;&#039; depending on what &#039;&#039;harmonic&#039;&#039; is being played. Another use case would be to group certain &#039;&#039;MIDI&#039;&#039; keys to address a certain string, and other &#039;&#039;MIDI&#039;&#039; keys addressing another, depending on the how well different strings can render certain tones / harmonics.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;Number Map&#039;&#039; first needs a data set of several points where each point contains &amp;quot;an input of x outputs y&amp;quot;. The &#039;&#039;Number Map&#039;&#039; is then &#039;&#039;triggered&#039;&#039; with a value of &#039;&#039;x&#039;&#039;. When this happens it looks in its database for anything mapped to &#039;&#039;x&#039;&#039;, if it finds it it outputs the &#039;&#039;commands&#039;&#039; set by the &#039;&#039;target&#039;&#039; but first replaces any occurances of the word &amp;quot;nmout&amp;quot; in the &#039;&#039;command string&#039;&#039; with the value of &#039;&#039;y&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;numbermap&amp;quot;-&#039;&#039;plugin modules&#039;&#039; commands&lt;/div&gt;</summary>
		<author><name>Knaadmin</name></author>
	</entry>
	<entry>
		<id>http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_reference_V1.1&amp;diff=1689</id>
		<title>The Ekdahl FAR - Command reference V1.1</title>
		<link rel="alternate" type="text/html" href="http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_reference_V1.1&amp;diff=1689"/>
		<updated>2026-06-14T13:20:48Z</updated>

		<summary type="html">&lt;p&gt;Knaadmin: /* The &amp;quot;ahdsr&amp;quot;-plugin module */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
The Ekdahl FAR V1.1 introduces the concept of &#039;&#039;modules&#039;&#039;. A &#039;&#039;module&#039;&#039; can contain any number of &#039;&#039;commands&#039;&#039; as well as other &#039;&#039;modules&#039;&#039;. Furthermore any number of &#039;&#039;modules&#039;&#039; of the same type can exist within a context, these are addressed using classic C-style array &#039;&#039;indexing&#039;&#039; with the help of brackets (&amp;quot;[ ]&amp;quot;). Extending on the classic usage, multiple &#039;&#039;indexes&#039;&#039; can be addressed simultaneously by either comma-separating the objects (&amp;quot;[0,3,4]&amp;quot;) and using &#039;&#039;ranges&#039;&#039; (&amp;quot;[3-6]&amp;quot;). &#039;&#039;Modules&#039;&#039; can be either &#039;&#039;internal&#039;&#039; or &#039;&#039;external&#039;&#039;, meaning that they may all physically exist within a single hardware object, or they can be be remote-controlled devices. From a user perspective this however makes no difference as they will appear the same.&lt;br /&gt;
&lt;br /&gt;
While all &#039;&#039;modules&#039;&#039; have their own set of &#039;&#039;commands&#039;&#039;, there are certain &#039;&#039;commands&#039;&#039; that all &#039;&#039;modules&#039;&#039; &amp;lt;u&amp;gt;must&amp;lt;/u&amp;gt; implement and can thus be accessed anywhere within the &#039;&#039;module hierarchy.&#039;&#039; There are also &#039;&#039;base commands&#039;&#039; that always exist within any given FAR ecosystem as well as product-specific &#039;&#039;base commands&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Ubiquitous commands ==&lt;br /&gt;
The &#039;&#039;module commands&#039;&#039; that are &amp;lt;u&amp;gt;required&amp;lt;/u&amp;gt; to be implemented in &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; &#039;&#039;modules&#039;&#039; and that can thus be accessed from anywhere are&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|list&lt;br /&gt;
|ls&lt;br /&gt;
|hidden/h:modules/m:commands/c:instances/i:instancecounts/ic:recursive/r&lt;br /&gt;
|Lists all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039; under the current module depending on the parameters given; &#039;hidden&#039; includes normally hidden &#039;&#039;commands&#039;&#039;, &#039;modules&#039; includes any &#039;&#039;submodules&#039;&#039;, &#039;commands&#039; shows &#039;&#039;commands&#039;&#039;, &#039;instances&#039; shows data for each individual instance of a &#039;&#039;module&#039;&#039;, &#039;instancecounts&#039; includes number of instances of each &#039;&#039;module&#039;&#039;, &#039;recursive&#039; lists all child &#039;&#039;modules&#039;&#039; / &#039;&#039;commands&#039;&#039;. No parameters defaults to showing all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039; recursively with instance counts. It doesn&#039;t show per-instance data or hidden commands.&lt;br /&gt;
|-&lt;br /&gt;
|help&lt;br /&gt;
|help&lt;br /&gt;
|recursive/r&lt;br /&gt;
|Shows a brief explanation of all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039;, shows the help for all &#039;&#039;submodules&#039;&#039; as well if &#039;recursive&#039;&lt;br /&gt;
|-&lt;br /&gt;
|dumpdata&lt;br /&gt;
|dump&lt;br /&gt;
|recursive/r&lt;br /&gt;
|Dumps all data saved for the current &#039;&#039;module&#039;&#039;, will list the data of all &#039;&#039;submodules&#039;&#039; as well if &#039;recursive&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Base commands ==&lt;br /&gt;
B&#039;&#039;ase commands&#039;&#039; are &#039;&#039;commands&#039;&#039; that always exist at the root in any implementation of the Ekdahl FAR.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|version&lt;br /&gt;
|ver&lt;br /&gt;
| -&lt;br /&gt;
|Gets the current firmware version&lt;br /&gt;
|-&lt;br /&gt;
|debugprint&lt;br /&gt;
|dp&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;command|usb|hardware|undefined|priority|error|inforequest|expressionparser|debug:1|0&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Turns on or off serial feedback for the given item&lt;br /&gt;
|-&lt;br /&gt;
|requestinfo&lt;br /&gt;
|rqi&lt;br /&gt;
|command&lt;br /&gt;
|Retrives any data saved for a &#039;&#039;command&#039;&#039;, if applicable&lt;br /&gt;
|-&lt;br /&gt;
|saveallparameters&lt;br /&gt;
|sap&lt;br /&gt;
| -&lt;br /&gt;
|Saves all avaliable parameters&lt;br /&gt;
|-&lt;br /&gt;
|loadallparameters&lt;br /&gt;
|lap&lt;br /&gt;
| -&lt;br /&gt;
|Loads all avaliable parameters&lt;br /&gt;
|-&lt;br /&gt;
|resetallparameters&lt;br /&gt;
|rap&lt;br /&gt;
| -&lt;br /&gt;
|Resets all saved parameters&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|rst&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;1|0&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Resets the Ekdahl FAR, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|nick&lt;br /&gt;
|nick&lt;br /&gt;
|name&lt;br /&gt;
|Sets the nickname of this unit&lt;br /&gt;
|-&lt;br /&gt;
|nooperation&lt;br /&gt;
|nop&lt;br /&gt;
| -&lt;br /&gt;
|Do absolutely, positively, nothing. Useful for testing and interfacing with computers, it&#039;s a good way to know that the unit is alive and responding since a &amp;quot;nop&amp;quot; is being returned as a response upon reception.&lt;br /&gt;
|-&lt;br /&gt;
|uservariable&lt;br /&gt;
|uv&lt;br /&gt;
|variable(0-9):value&lt;br /&gt;
|Set user variable 0-9 to &#039;value&#039;&lt;br /&gt;
|-&lt;br /&gt;
|expressionparserevaluate&lt;br /&gt;
|epev&lt;br /&gt;
|expression&lt;br /&gt;
|Evaluates an arithmetric expression and sends back the output, all variables and functions that can be used in any &#039;&#039;command string&#039;&#039; can also be used here. Useful for testing expressions.&lt;br /&gt;
|-&lt;br /&gt;
|ifequal&lt;br /&gt;
|ife&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] EQUALS [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring].&lt;br /&gt;
|-&lt;br /&gt;
|ifgreater&lt;br /&gt;
|ifg&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] &amp;gt; [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring]&lt;br /&gt;
|-&lt;br /&gt;
|ifless&lt;br /&gt;
|ifl&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] &amp;lt; [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring]&lt;br /&gt;
|-&lt;br /&gt;
|freeram&lt;br /&gt;
|ram&lt;br /&gt;
| -&lt;br /&gt;
|Shows free RAM memory&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The base also contains the following &#039;&#039;modules:&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|pluginhandler&lt;br /&gt;
|ph&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The Ekdahl FAR stand alone single string unit ==&lt;br /&gt;
The Ekdahl FAR stand-alone single string unit offers these &#039;&#039;commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|calibrateall&lt;br /&gt;
|ca&lt;br /&gt;
| -&lt;br /&gt;
|Performs all calibration routines on the selected bow, see below for routines performed&lt;br /&gt;
|-&lt;br /&gt;
|calibratebowspeed&lt;br /&gt;
|cbs&lt;br /&gt;
| -&lt;br /&gt;
|Finds the minimum and maximum bow speed of the selected bow&lt;br /&gt;
|-&lt;br /&gt;
|calibratebowpressure&lt;br /&gt;
|cbp&lt;br /&gt;
| -&lt;br /&gt;
|Finds the minimum and maximum bow pressure of the selected bow&lt;br /&gt;
|-&lt;br /&gt;
|calibratemute&lt;br /&gt;
|cmu&lt;br /&gt;
| -&lt;br /&gt;
|Calibrate mute settings&lt;br /&gt;
|-&lt;br /&gt;
|pickupstringfrequency&lt;br /&gt;
|psf&lt;br /&gt;
| -&lt;br /&gt;
|Returns the fundamental tone calculated from the current audio signal if apliccable&lt;br /&gt;
|-&lt;br /&gt;
|pickupaudiopeak&lt;br /&gt;
|pap&lt;br /&gt;
| -&lt;br /&gt;
|Returns the peak amplitude of the current audio signal&lt;br /&gt;
|-&lt;br /&gt;
|pickupaudiorms&lt;br /&gt;
|par&lt;br /&gt;
| -&lt;br /&gt;
|Returns the RMS amplitude of the current audio signal&lt;br /&gt;
|}&lt;br /&gt;
The Ekdahl FAR also contains the following &#039;&#039;modules&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|bowingwheel&lt;br /&gt;
|bw&lt;br /&gt;
|-&lt;br /&gt;
|mute&lt;br /&gt;
|mu&lt;br /&gt;
|-&lt;br /&gt;
|solenoid&lt;br /&gt;
|so&lt;br /&gt;
|-&lt;br /&gt;
|controlbox&lt;br /&gt;
|cb&lt;br /&gt;
|-&lt;br /&gt;
|midiconfigurationhandler&lt;br /&gt;
|mcf&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;Bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; contains everything needed to interface with a single &#039;&#039;bowing wheel&#039;&#039;. Each &#039;&#039;bowing wheel&#039;&#039; has its own harmonic series, pressure actuators and direct hardware interface. It contains the following &#039;&#039;commands&#039;&#039;.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|speedmode&lt;br /&gt;
|sm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Bow motor speed mode, 0 = Automatic and 1 = Manual. Automatic mode means that the bowing wheel will automatically turn off after the &#039;&#039;motor timeout&#039;&#039; has been reached after being put into rest mode&lt;br /&gt;
|-&lt;br /&gt;
|motortimeout&lt;br /&gt;
|mt&lt;br /&gt;
|ms&lt;br /&gt;
|Bow motor shutdown timeout after bow having been put into the rest position&lt;br /&gt;
|-&lt;br /&gt;
|pidenable&lt;br /&gt;
|pe&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets the bow PID on/off&lt;br /&gt;
|-&lt;br /&gt;
|motorfaultcommands&lt;br /&gt;
|mfc&lt;br /&gt;
|commands&lt;br /&gt;
|Commands to execute when a motor fault is tripped - !WARNING! Can ruin your instrument if changed&lt;br /&gt;
|-&lt;br /&gt;
|motoroverpowercommands&lt;br /&gt;
|moc&lt;br /&gt;
|commands&lt;br /&gt;
|Commands to execute when motor is over the power limit - !WARNING! Can ruin your instrument if changed&lt;br /&gt;
|}&lt;br /&gt;
The &#039;&#039;modules&#039;&#039; in the &amp;quot;Bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; are as follows&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|bowpressure&lt;br /&gt;
|bp&lt;br /&gt;
|-&lt;br /&gt;
|dcmotor&lt;br /&gt;
|dcm&lt;br /&gt;
|-&lt;br /&gt;
|pid&lt;br /&gt;
|pid&lt;br /&gt;
|-&lt;br /&gt;
|harmonicserieshandler&lt;br /&gt;
|hsh&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; handles the &#039;&#039;pressure&#039;&#039; of the &#039;&#039;bowing wheel&#039;&#039; against the string. The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|baseline&lt;br /&gt;
|ba&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure baseline, modulation is added to this point upward. Typically this is set with a knob on the &#039;&#039;control box&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|modifier&lt;br /&gt;
|mo&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure modulation, added to the baseline&lt;br /&gt;
|-&lt;br /&gt;
|rest&lt;br /&gt;
|rs&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the bow pressure in the &#039;&#039;rest&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|engage&lt;br /&gt;
|en&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the bow pressure in the &#039;&#039;engage&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|stallpressure&lt;br /&gt;
|sp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure stall/maximum position, this parameter is set using &#039;&#039;hardware positioning&#039;&#039; and is used as the absolute maximum for baseline and modifier combiner&lt;br /&gt;
|-&lt;br /&gt;
|engagepressure&lt;br /&gt;
|ep&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure touch/minimum position, this parameter is set using &#039;&#039;hardware position&#039;&#039; and is used as the starting point for when both the baseline and modifier is set to zero&lt;br /&gt;
|-&lt;br /&gt;
|restpressure&lt;br /&gt;
|rp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure rest position, this parameter is set using &#039;&#039;hardware positioning&#039;&#039; and is typically set to a point just below the string where it does not touch at all. The purpose of this is because while the actual hardware might be able to make the bow go even lower, that position might be far enough from the string that once &#039;&#039;engaged&#039;&#039; the bow may have so far to travel that there is perceptible &#039;&#039;latency&#039;&#039;.&lt;br /&gt;
|-&lt;br /&gt;
|engagespeed&lt;br /&gt;
|es&lt;br /&gt;
|1- ~100&lt;br /&gt;
|Bow pressure movement speed when engaging or disengaging&lt;br /&gt;
|-&lt;br /&gt;
|modulationspeed&lt;br /&gt;
|ms&lt;br /&gt;
|0.1 - 10&lt;br /&gt;
|Bow pressure movement speed while engaged&lt;br /&gt;
|-&lt;br /&gt;
|hold&lt;br /&gt;
|hd&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets bow hold (infinite sustain) on/off, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|home&lt;br /&gt;
|hm&lt;br /&gt;
| -&lt;br /&gt;
|Homing bow, used at startup and in case of the bow loosing position&lt;br /&gt;
|-&lt;br /&gt;
|tmcinfo&lt;br /&gt;
|tmi&lt;br /&gt;
| -&lt;br /&gt;
|Request statistical information from the TMC2209 stepper motor driver&lt;br /&gt;
|}&lt;br /&gt;
Note that the &amp;quot;stall&amp;quot;, &amp;quot;engage&amp;quot; and &amp;quot;rest&amp;quot;-pressure positions mention something called &#039;&#039;hardware position&#039;&#039;. This means the entire available movement of the &#039;&#039;bowing jack&#039;&#039;. Because the very bottom and top end of the movement might not be musically useful and may even harm the instrument, the &amp;quot;baseline&amp;quot; and &amp;quot;modifier&amp;quot; commands &#039;&#039;parameter&#039;&#039;s are scaled depending on these settings.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;engage&amp;quot; and &amp;quot;modulation&amp;quot;-speed settings sets how fast the stepper motor that drives the &#039;&#039;pressure&#039;&#039; moves depending on whether the &#039;&#039;bowing jack&#039;&#039; is set to &#039;&#039;engage&#039;&#039; or not. The idea here is that while wanting to be able to minimize &#039;&#039;latency&#039;&#039; by &#039;&#039;engaging&#039;&#039; and &#039;&#039;disengaging&#039;&#039; from the string as quickly as possible, dynamic changes in the &#039;&#039;pressure&#039;&#039; while playing benefits from much smoother movements as the &#039;&#039;bowing wheel&#039;&#039; takes some time to catch up to varying amounts of friction.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; contains one or more of the following &#039;&#039;modules&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|actuatorhandler&lt;br /&gt;
|ah&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;actuatorhandler&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The concept of &amp;quot;actuators&amp;quot; came up as it is possible to have &#039;&#039;bowing wheels&#039;&#039; of different sizes and wanting to be able to switch quickly in between them, perhaps during mid-performance. Because a differently sized wheel will require different values for the above mentioned &amp;quot;stall&amp;quot;, &amp;quot;engage&amp;quot; and &amp;quot;reset&amp;quot;-&#039;&#039;pressure&#039;&#039;, each &#039;&#039;actuator&#039;&#039; stores these values. Instead of having to manually change the previously mentioned values, simply selecting a new &#039;&#039;actuator&#039;&#039; will automatically load the values. The &amp;quot;actuatorhandler&amp;quot;-&#039;&#039;module&#039;&#039; is the handler of one or more &amp;quot;actuator&amp;quot;-&#039;&#039;modules&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;commands&#039;&#039; of the &amp;quot;acuatorhandler&amp;quot;-&#039;&#039;module&#039;&#039; are as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|add&lt;br /&gt;
|a&lt;br /&gt;
|(name):(rest:engage:stall)&lt;br /&gt;
|Add new actuator with the given name and parameters&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|actuatornumber&lt;br /&gt;
|Remove bow actuator [actuatornumber]&lt;br /&gt;
|-&lt;br /&gt;
|count&lt;br /&gt;
|c&lt;br /&gt;
| -&lt;br /&gt;
|Returns the amount of saved bow actuators&lt;br /&gt;
|}&lt;br /&gt;
The &amp;quot;actuatorhandler&amp;quot;-&#039;&#039;module&#039;&#039; contains one or more of&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|actuator&lt;br /&gt;
|ac&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;actuator&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;actuator&amp;quot;-&#039;&#039;module&#039;&#039; contains the following commands&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|[index]&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|Selects the given actuator&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Sets the actuator name&lt;br /&gt;
|-&lt;br /&gt;
|data&lt;br /&gt;
|da&lt;br /&gt;
|name:rest:engage:stall&lt;br /&gt;
|Sets the actuator name, rest, engage and stall &#039;&#039;pressure&#039;&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;dcmotor&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;dcmotor&amp;quot;-&#039;&#039;module&#039;&#039; handles the direct &amp;lt;u&amp;gt;raw&amp;lt;/u&amp;gt; control of the &#039;&#039;bowing motor&#039;&#039; and handles the reporting back of the current speed. It has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|run&lt;br /&gt;
|ru&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Turns the motor off/on&lt;br /&gt;
|-&lt;br /&gt;
|pwm&lt;br /&gt;
|pw&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor direct power in 16-bit PWM values, requires that the &#039;&#039;PID&#039;&#039; is turned off&lt;br /&gt;
|-&lt;br /&gt;
|voltage&lt;br /&gt;
|vo&lt;br /&gt;
|~2 - 10V&lt;br /&gt;
|Sets the voltage of the regulator powering the motor. Changes here can make the motor more responsive to certain frequencies but will also affect how well the &#039;&#039;PID&#039;&#039; works. !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|current&lt;br /&gt;
|cu&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor reported current use&lt;br /&gt;
|-&lt;br /&gt;
|currentlimit&lt;br /&gt;
|cl&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor current limit (A)- !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|powerlimit&lt;br /&gt;
|pl&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor power limit (W) - !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|frequency&lt;br /&gt;
|fq&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor reported frequency&lt;br /&gt;
|-&lt;br /&gt;
|emergencystop&lt;br /&gt;
|es&lt;br /&gt;
|ms (0-65535)&lt;br /&gt;
|Immediately stops the bowing motor and doesn&#039;t allow it to start again until the cool down period given in the first argument has lapsed (milliseconds)&lt;br /&gt;
|-&lt;br /&gt;
|minpwm&lt;br /&gt;
|ip&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor minimum PWM (for calibration)&lt;br /&gt;
|-&lt;br /&gt;
|maxpwm&lt;br /&gt;
|xp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor maximum PWM (for calibration)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;pidcontroller&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;pidcontroller&amp;quot;-&#039;&#039;module&#039;&#039; is responsible for keeping the &amp;quot;dcmotor&amp;quot;-&#039;&#039;module&#039;&#039; at a certain frequency (given in Hertz). It takes the output of the motor frequency measurement and feeds it a PWM value that tries to make the speed constant regardless of the friction that the motor is enduring. To learn more about PID Controllers please see this [[wikipedia:PID_controller|wikipedia article]]. The &#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|targetfrequency&lt;br /&gt;
|tf&lt;br /&gt;
|hertz&lt;br /&gt;
|Sets the PID target frequency&lt;br /&gt;
|-&lt;br /&gt;
|ki&lt;br /&gt;
|ki&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Ki parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|kp&lt;br /&gt;
|kp&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Kp parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|kd&lt;br /&gt;
|kd&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Kd parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|integratorerror&lt;br /&gt;
|ie&lt;br /&gt;
|float&lt;br /&gt;
|Sets the lower threshold of error values for the PID integrator to ignore&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|re&lt;br /&gt;
| -&lt;br /&gt;
|Resets the PID integrator and derivative&lt;br /&gt;
|-&lt;br /&gt;
|maxerror&lt;br /&gt;
|xe&lt;br /&gt;
|float&lt;br /&gt;
|Maximum error to correct in each PID loop, essentially sets acceleration&lt;br /&gt;
|-&lt;br /&gt;
|peakerror&lt;br /&gt;
|pe&lt;br /&gt;
|float&lt;br /&gt;
|Get latest PID peak error&lt;br /&gt;
|-&lt;br /&gt;
|motorspeedmax&lt;br /&gt;
|msx&lt;br /&gt;
|Hertz&lt;br /&gt;
|Bow motor maximum speed limit&lt;br /&gt;
|-&lt;br /&gt;
|motorspeedmin&lt;br /&gt;
|msi&lt;br /&gt;
|Hertz&lt;br /&gt;
|Bow motor minimum speed limit&lt;br /&gt;
|-&lt;br /&gt;
|measuretimetotarget&lt;br /&gt;
|mtt&lt;br /&gt;
|Hertz&lt;br /&gt;
|Measure the time it takes to change from the current frequency to the target frequency, for testing purposes&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; is responsible for sending frequency data to the &amp;quot;pid&amp;quot;-&#039;&#039;module&#039;&#039;. It handles calculating the correct frequency of the &#039;&#039;bowing wheel&#039;&#039; according to the selected &#039;&#039;harmonic&#039;&#039; and &#039;&#039;harmonic shift&#039;&#039; per the currently selected &#039;&#039;harmonic series&#039;&#039;. The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|fundamental&lt;br /&gt;
|fu&lt;br /&gt;
|Hertz&lt;br /&gt;
|The fundamental frequency of the string, all harmonics are calculated from this number&lt;br /&gt;
|-&lt;br /&gt;
|harmonic&lt;br /&gt;
|h&lt;br /&gt;
|int&lt;br /&gt;
|Selects the harmonic number to set the &#039;&#039;bowing wheel&#039;&#039; to. A ratio is taken from the given &#039;&#039;harmonic&#039;&#039; in the current &#039;&#039;harmonic series&#039;&#039;, the ratio is then multiplied by the &#039;&#039;fundamental frequency&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|harmonicadd&lt;br /&gt;
|ha&lt;br /&gt;
|int&lt;br /&gt;
|This number is added to the current harmonic&lt;br /&gt;
|-&lt;br /&gt;
|harmonicbase&lt;br /&gt;
|hb&lt;br /&gt;
|int&lt;br /&gt;
|Same as harmonic but where the harmonic number is based on a MIDI note given by basenote&lt;br /&gt;
|-&lt;br /&gt;
|basenote&lt;br /&gt;
|bn&lt;br /&gt;
|0-127&lt;br /&gt;
|Sets the MIDI base note of the &#039;&#039;bowing wheel&#039;&#039;, used in conjunction with &amp;quot;harmonicbase&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|shift&lt;br /&gt;
|sh&lt;br /&gt;
| -32767 - 32767&lt;br /&gt;
|Sets shift from the currently playing harmonic where 32767 equals the entire harmonic shift range shifted up&lt;br /&gt;
|-&lt;br /&gt;
|shiftrange&lt;br /&gt;
|sr&lt;br /&gt;
|0-36&lt;br /&gt;
|Set the number of harmonic numbers that constitutes an entire harmonic shift&lt;br /&gt;
|-&lt;br /&gt;
|shift5&lt;br /&gt;
|sh5&lt;br /&gt;
| -32767 - 32767&lt;br /&gt;
|Sets the shift from the currently playing harmonic over 5 octaves where 32767 equals 5 octaves shift up from the fundamental&lt;br /&gt;
|-&lt;br /&gt;
|add&lt;br /&gt;
|a&lt;br /&gt;
|(name):(ratios)&lt;br /&gt;
|Add a new series with the given name and parameters&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|series&lt;br /&gt;
|Remove the series given and shift any series accordingly. Cannot remove all series&lt;br /&gt;
|-&lt;br /&gt;
|count&lt;br /&gt;
|c&lt;br /&gt;
| -&lt;br /&gt;
|Returns the number of harmonic series in the list and their IDs&lt;br /&gt;
|}&lt;br /&gt;
The &amp;quot;harmonicserieshandler&amp;quot;-module contains at the very least ONE harmonic series, by default it contains two: one for equal temperament and one for just intonation. The current series can be selected by simply indexing the &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; without a &#039;&#039;command&#039;&#039;, e.g. &amp;quot;harmonicserieshandler.harmonicseries[1]&amp;quot;. To be consistent, these are the &#039;&#039;modules&#039;&#039; in the &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|harmonicseries&lt;br /&gt;
|hs&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; contains any number of &#039;&#039;ratios&#039;&#039; that comprises a scale, ratios are given in a standard format where a ratio of &amp;quot;1&amp;quot; is equal to the fundamental, &amp;quot;2&amp;quot; would be one octave up etc. A standard &#039;&#039;harmonic series&#039;&#039; contains 12 ratios following a just intonation scheme. The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; will automatically adapt to the currently selected &#039;&#039;harmonic series&#039;&#039; length, whether it&#039;s a standard 12-tone scale, some kinda 3-tone scale or a full on bananas 53-tone scale. The &#039;&#039;commands&#039;&#039; of the &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; is as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|[index]&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
|Sets the currently selected &#039;&#039;harmonic Series&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Sets the name of the &#039;&#039;harmonic series&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|data&lt;br /&gt;
|da&lt;br /&gt;
|name:ratios&lt;br /&gt;
|Gets / sets all data for the &#039;&#039;harmonic series&#039;&#039; in the given slot with an arbitrary &#039;&#039;name&#039;&#039; as the first &#039;&#039;parameter&#039;&#039;. The length of the series is simply set to the amount of ratios given&lt;br /&gt;
|-&lt;br /&gt;
|ratio&lt;br /&gt;
|r&lt;br /&gt;
|harmonic:ratio&lt;br /&gt;
|Sets the ratio of the given harmonic in current &#039;&#039;harmonic series&#039;&#039;, will increase the list size if needed to address the harmonic&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|harmonic&lt;br /&gt;
|Remove the harmonic ratio given in the current series and shift any ratios accordingly. Cannot remove all ratios&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;mute&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;mute&amp;quot;-&#039;&#039;module&#039;&#039; works very similarly to the &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; in that it controls a stepper motor with some software limits in place in order to press the mute against the string. The &#039;&#039;commands&#039;&#039; are as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|setposition&lt;br /&gt;
|sp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set mute position&lt;br /&gt;
|-&lt;br /&gt;
|fullmute&lt;br /&gt;
|fm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the mute in &#039;&#039;full mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|halfmute&lt;br /&gt;
|hm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the mute in &#039;&#039;half mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|rest&lt;br /&gt;
|rs&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Put the mute in the &#039;&#039;rest&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|savefull&lt;br /&gt;
|sf&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Save the current mute position as the &#039;&#039;full mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|savehalf&lt;br /&gt;
|sh&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Save the current mute position as the &#039;&#039;half mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|saverest&lt;br /&gt;
|sr&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Save the current mute position as the &#039;&#039;rest&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|fullmuteposition&lt;br /&gt;
|fmp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;full mute&#039;&#039; position according to the &#039;&#039;hardware position&#039;&#039; given&lt;br /&gt;
|-&lt;br /&gt;
|halfmuteposition&lt;br /&gt;
|hmp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;half mute&#039;&#039; position according to the &#039;&#039;hardware position&#039;&#039; given&lt;br /&gt;
|-&lt;br /&gt;
|restposition&lt;br /&gt;
|rp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;rest&#039;&#039; position according to the &#039;&#039;hardware position&#039;&#039; given&lt;br /&gt;
|-&lt;br /&gt;
|sustain&lt;br /&gt;
|su&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets the sustain off/on, this will keep the mute in the &#039;&#039;rest&#039;&#039; position even if a &amp;quot;fullmute&amp;quot;-&#039;&#039;command&#039;&#039; is given, lasts until &amp;quot;sustain&amp;quot; is set to &amp;quot;0&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
|backoff&lt;br /&gt;
|bo&lt;br /&gt;
|0-65535&lt;br /&gt;
|Setting the time that the mute stays in the mutefullmute position before automatically going into rest, set in mS. A value of &amp;quot;0&amp;quot; disables backoff. This is used because if the mute is not backing off until something is attempted to be played, the backing-off time will either introduce &#039;&#039;latency&#039;&#039; or the string will be initially partially muted&lt;br /&gt;
|-&lt;br /&gt;
|home&lt;br /&gt;
|hm&lt;br /&gt;
| -&lt;br /&gt;
|Home mute, used during initialization and if the mute were to loose position&lt;br /&gt;
|-&lt;br /&gt;
|hardwareposition&lt;br /&gt;
|hwp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;hardware position&#039;&#039; of the mute instead of scaling it over the &#039;&#039;full mute&#039;&#039; and &#039;&#039;rest&#039;&#039; positions. Mainly used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|completetask&lt;br /&gt;
|cpt&lt;br /&gt;
| -&lt;br /&gt;
|Requests a callback when the current operation is finished. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|autocorrect&lt;br /&gt;
|ac&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Enables auto correct positioning that uses the homing sensor to correct positioning on the fly. EXPERIMENTAL&lt;br /&gt;
|-&lt;br /&gt;
|homingsensed&lt;br /&gt;
|hms&lt;br /&gt;
| -&lt;br /&gt;
|Requests whether the homing sensor is currently active or not. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|movedirection&lt;br /&gt;
|md&lt;br /&gt;
| -&lt;br /&gt;
|Requests the current direction of movement (0 Forward, 1 Reverse). Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|currentstep&lt;br /&gt;
|cs&lt;br /&gt;
| -&lt;br /&gt;
|Requests the current step. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|homingpoint&lt;br /&gt;
|hmp&lt;br /&gt;
|edgedirection&lt;br /&gt;
|Requests the given homing point. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|homingstage&lt;br /&gt;
|hms&lt;br /&gt;
| -&lt;br /&gt;
|Requests the current homing stage (UNHOMED, HOMED, FIRSTHOMINGRISING, SECONDHOMINGFALLING, SECONDHOMINGRISING, FIRSTHOMINGFALLING, MOVEPASTHOMESWITCH, MOVETOHOMESWITCH, GOTOOFFSET). Only used internally by other &#039;&#039;modules.&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|tmcinfo&lt;br /&gt;
|tmi&lt;br /&gt;
| -&lt;br /&gt;
|Request statistical information from the TMC2209 stepper motor driver&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;solenoid&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;solenoid&amp;quot;-&#039;&#039;module&#039;&#039; currently controls the &#039;&#039;hammer&#039;&#039; of the Ekdahl FAR. Due to the fact that the very same &#039;&#039;module&#039;&#039; could be used for anything that uses a striking &#039;&#039;solenoid&#039;&#039; it was named as such. It has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|engage&lt;br /&gt;
|en&lt;br /&gt;
|0-65535&lt;br /&gt;
|Engages the solenoid using the first parameter as the force&lt;br /&gt;
|-&lt;br /&gt;
|rest&lt;br /&gt;
|rs&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Forces the solenoid to its rest position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|maxforce&lt;br /&gt;
|xf&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set solenoid maximum usable force&lt;br /&gt;
|-&lt;br /&gt;
|minforce&lt;br /&gt;
|if&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set solenoid minimum usable force&lt;br /&gt;
|-&lt;br /&gt;
|forcemultiplier&lt;br /&gt;
|fm&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set solenoid force multiplier, useful for scaling of all incoming &amp;quot;engage&amp;quot;-&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|engageduration&lt;br /&gt;
|ed&lt;br /&gt;
|uS&lt;br /&gt;
|Sets the duration of the solenoid hit in uS, if a value of 0 is set the solenoid will not disengage until a rest command has been given. WARNING!! HAVING THE SOLENOID ON FOR A SPAN OF SECONDS COULD DESTROY THE CIRCUITRY!!&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;controlbox&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;controlbox&amp;quot;-&#039;&#039;module&#039;&#039; communicates with an external &#039;&#039;control box&#039;&#039; and will issue associated &#039;&#039;commands&#039;&#039; whenever new values are read on the ADC-converters. It handles averaging and does some noise-cancellation functions on the values as well. The &#039;&#039;commands&#039;&#039; are:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|harmonic&lt;br /&gt;
|har&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the harmonic knob or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|harmonicshift&lt;br /&gt;
|has&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the harmonic shift modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|finetune&lt;br /&gt;
|fin&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the fine tune knob changes&lt;br /&gt;
|-&lt;br /&gt;
|pressure&lt;br /&gt;
|pre&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the pressure knob or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|mute&lt;br /&gt;
|mut&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the mute knob or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|hammerscale&lt;br /&gt;
|hms&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the hammer scale knob changes&lt;br /&gt;
|-&lt;br /&gt;
|gate&lt;br /&gt;
|gt&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the gate switch or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|hammertrig&lt;br /&gt;
|hmt&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the hammer trigger modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|controldefaults&lt;br /&gt;
|cde&lt;br /&gt;
| -&lt;br /&gt;
|Reverts all ADC command strings to default values&lt;br /&gt;
|-&lt;br /&gt;
|datareturn&lt;br /&gt;
|dr&lt;br /&gt;
|channel:value&lt;br /&gt;
|Sent when a new value is presented on one of the ADC channels, cannot be invoked. Triggers the commands associated with the channel&lt;br /&gt;
|-&lt;br /&gt;
|adcsetting&lt;br /&gt;
|adcs&lt;br /&gt;
|channel : averages : interrupterrorthreshold : continuouserrorthreshold : continuoustimeout&lt;br /&gt;
|Sets ADC settings for a given channel. Averages are the number of samples to average, interruptthreshold is how much the value must change in order to issue a new value change event. continuousthreshold is how much the value must change when a previous change has already been recorded within the timespan of continuoustimeout&lt;br /&gt;
|-&lt;br /&gt;
|testadclatency&lt;br /&gt;
|tal&lt;br /&gt;
|0-65535&lt;br /&gt;
|Start a ADC latency test&lt;br /&gt;
|-&lt;br /&gt;
|testadclatencyreturn&lt;br /&gt;
|talr&lt;br /&gt;
| -&lt;br /&gt;
|Return from latency test&lt;br /&gt;
|-&lt;br /&gt;
|testadcminmax&lt;br /&gt;
|tix&lt;br /&gt;
|channel&lt;br /&gt;
|Test min/max value for a given channel and resets the counter&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;midiconfigurationhandler&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;midiconfigurationhandler&amp;quot;-&#039;&#039;module&#039;&#039; handles a number of &amp;quot;midiconfiguration&amp;quot;-&#039;&#039;modules&#039;&#039;. It has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|allnotesoff&lt;br /&gt;
|ano&lt;br /&gt;
| -&lt;br /&gt;
|Clears the entire buffer of MIDI notes held&lt;br /&gt;
|-&lt;br /&gt;
|add&lt;br /&gt;
|a&lt;br /&gt;
|name&lt;br /&gt;
|Adds a new MIDI configuration with the given name&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|int&lt;br /&gt;
|Remove the specified MIDI configuration&lt;br /&gt;
|-&lt;br /&gt;
|count&lt;br /&gt;
|c&lt;br /&gt;
| -&lt;br /&gt;
|Returns the number of MIDI configurations&lt;br /&gt;
|}&lt;br /&gt;
It contains one or more of the following&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|midiconfiguration&lt;br /&gt;
|mc&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;midiconfiguration&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
A &amp;quot;midiconfiguration&amp;quot;-&#039;&#039;module&#039;&#039; handles the reception of &#039;&#039;MIDI messages&#039;&#039; and will output the associated &#039;&#039;commands&#039;&#039; to the instrument internally. The commands are as follows&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|[index]&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
|Sets the currently selected MIDI configuration&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Set the name of the MIDI configuration&lt;br /&gt;
|-&lt;br /&gt;
|noteon&lt;br /&gt;
|non&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Note On event&lt;br /&gt;
|-&lt;br /&gt;
|noteoff&lt;br /&gt;
|nof&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Note Off event&lt;br /&gt;
|-&lt;br /&gt;
|polyaftertouch&lt;br /&gt;
|pat&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Polyphonic after touch event&lt;br /&gt;
|-&lt;br /&gt;
|channelaftertouch&lt;br /&gt;
|cat&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Channel after touch event&lt;br /&gt;
|-&lt;br /&gt;
|pitchbend&lt;br /&gt;
|pb&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Pitch bend event&lt;br /&gt;
|-&lt;br /&gt;
|programchange&lt;br /&gt;
|pc&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Program change event&lt;br /&gt;
|-&lt;br /&gt;
|continuouscontrollerdata&lt;br /&gt;
|ccd&lt;br /&gt;
|controllernuber:&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Continuous controller event with the given [&#039;&#039;controllernumber&#039;&#039;]&lt;br /&gt;
|-&lt;br /&gt;
|removecc&lt;br /&gt;
|rmc&lt;br /&gt;
|controllernuber&lt;br /&gt;
|Removes the entry associated with the MIDI continuous controller even &#039;&#039;controllernumber&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|defaults&lt;br /&gt;
|d&lt;br /&gt;
| -&lt;br /&gt;
|Reverts the current configuration to default &#039;&#039;commands&#039;&#039;, values and CCs&lt;br /&gt;
|-&lt;br /&gt;
|receivechannel&lt;br /&gt;
|rc&lt;br /&gt;
|channel&lt;br /&gt;
|Sets the MIDI receive channel of the current configuration. 1-16 sets specific channel, any other value for OMNI&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;pluginhandler&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The Ekdahl FAR allows for &#039;&#039;plugins&#039;&#039;. These are &#039;&#039;modules&#039;&#039; that can trigger certain &#039;&#039;command strings&#039;&#039; to be executed either periodically or triggered by an incoming &#039;&#039;command&#039;&#039;. Further explanation of the given &#039;&#039;plugins&#039;&#039; is given below. The various &#039;&#039;plugins&#039;&#039; are handled by the &amp;quot;pluginhandler&amp;quot;-&#039;&#039;module&#039;&#039;, the different &#039;&#039;plugin modules&#039;&#039; are identified by their own unique &#039;&#039;ID&#039;&#039;. The &amp;quot;pluginhandler&amp;quot;-&#039;&#039;module&#039;&#039; it has the following &#039;&#039;commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|add&lt;br /&gt;
|a&lt;br /&gt;
|pluginid&lt;br /&gt;
|Add plugin with the given ID&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|pluginid:index&lt;br /&gt;
|Remove plugin with the given ID and index&lt;br /&gt;
|-&lt;br /&gt;
|count&lt;br /&gt;
|c&lt;br /&gt;
|(pluginid)&lt;br /&gt;
|Return the number of plugins of the given type, if none is given it returns all plugins&lt;br /&gt;
|}&lt;br /&gt;
The number of available &#039;&#039;plugins&#039;&#039; will differ from time to time as the &#039;&#039;plugin system&#039;&#039; has been purposefully designed to allow for anyone to write and add their own &#039;&#039;plugins&#039;&#039;. As of the current writing (2026-06-14) the number of &amp;lt;u&amp;gt;possible&amp;lt;/u&amp;gt; &#039;&#039;plugin modules&#039;&#039; that &amp;lt;u&amp;gt;can&amp;lt;/u&amp;gt; exist under the &amp;quot;pluginhandler&amp;quot;-&#039;&#039;module&#039;&#039; are&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|lfo&lt;br /&gt;
|lfo&lt;br /&gt;
|-&lt;br /&gt;
|ahdsr&lt;br /&gt;
|ahdsr&lt;br /&gt;
|-&lt;br /&gt;
|numbermap&lt;br /&gt;
|map&lt;br /&gt;
|-&lt;br /&gt;
|multiple&lt;br /&gt;
|mlt&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;lfo&amp;quot;-&#039;&#039;plugin module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;lfo&amp;quot;-&#039;&#039;plugin module&#039;&#039; works like regular [[wikipedia:Low-frequency_oscillation|low frequency oscillator]] in that it generates a given &#039;&#039;waveform&#039;&#039; with a given &#039;&#039;frequency&#039;&#039; at a certain &#039;&#039;amplitude&#039;&#039;. In the Ekdahl FAR the distinguishing factors are that besides the common &#039;&#039;frequency, amplitude&#039;&#039; and &#039;&#039;waveform&#039;&#039; parameters, it also requires the use of a &#039;&#039;update rate&#039;&#039; and &#039;&#039;target&#039;&#039; parameter. The &#039;&#039;update rate&#039;&#039; sets how often the current position of the LFO is sampled (aka how often it peeks in on where the LFO is in its waveform transition at the moment), and each time that happens, the &#039;&#039;target commands&#039;&#039; are outputted to the instrument.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example:&#039;&#039;&#039;&lt;br /&gt;
 Lets set the &#039;&#039;waveform&#039;&#039; to &amp;quot;triangle&amp;quot;, the &#039;&#039;amplitude&#039;&#039; to 65535 (max), the &#039;&#039;frequency&#039;&#039; to 1Hz (1 full waveform per second), the &#039;&#039;update rate&#039;&#039; to 10mS and the &#039;&#039;target&#039;&#039; to &amp;quot;bowingwheel.harmonicserieshandler.shift:lfoout&amp;quot;.&lt;br /&gt;
 &lt;br /&gt;
 The output of the LFO is always given in the variable &amp;quot;lfoout&amp;quot;, our &#039;&#039;target&#039;&#039; is set to &amp;quot;bowingwheel.harmonicserieshandler.shift&amp;quot; which controls the &#039;&#039;harmonic shift&#039;&#039; (pitchbend basically) of the &#039;&#039;bowing wheel&#039;&#039;.&lt;br /&gt;
 &lt;br /&gt;
 Since our update rate is set to every 10 milliseconds and our frequency is 1 Hertz the instrument will internally send 100 updates per second to the &#039;&#039;harmonic shift.&#039;&#039; Our amplitude is set to the maximum value and depending on the &amp;quot;harmonicserieshandler.shiftrange&amp;quot; this could give a smooth vibrato like sound or more of an experimental one with a wider range. If the modulation is too deep we can just adjust the amplitude of the LFO.&lt;br /&gt;
The &amp;quot;lfo&amp;quot;-&#039;&#039;plugin modules commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Sets the nickname of the LFO&lt;br /&gt;
|-&lt;br /&gt;
|enable&lt;br /&gt;
|en&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Disables / Enables the output of the &#039;&#039;target&#039;&#039; &#039;&#039;commands&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|target&lt;br /&gt;
|tg&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the command string to execute each update cycle, the string [lfoout] will be replaced with the current value&lt;br /&gt;
|-&lt;br /&gt;
|updaterate&lt;br /&gt;
|ur&lt;br /&gt;
|milliseconds&lt;br /&gt;
|Sets the frequency with which the &#039;&#039;target commands&#039;&#039; are executed. Limited by the global maximum as set in the plugin handler&lt;br /&gt;
|-&lt;br /&gt;
|waveform&lt;br /&gt;
|wf&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;sine|triangle|square|saw&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets the LFO waveform&lt;br /&gt;
|-&lt;br /&gt;
|frequency&lt;br /&gt;
|fq&lt;br /&gt;
|Hertz&lt;br /&gt;
|Sets the LFO frequency&lt;br /&gt;
|-&lt;br /&gt;
|amplitude&lt;br /&gt;
|amp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the LFO amplitude&lt;br /&gt;
|-&lt;br /&gt;
|delay&lt;br /&gt;
|dl&lt;br /&gt;
|0-65535 milliseconds&lt;br /&gt;
|Ramps up the amplitude of the output waveform from zero to full amplitude in the given time span&lt;br /&gt;
|-&lt;br /&gt;
|resetdelay&lt;br /&gt;
|rd&lt;br /&gt;
| -&lt;br /&gt;
|Resets the delay and starts the ramping of the waveform&lt;br /&gt;
|-&lt;br /&gt;
|resetwave&lt;br /&gt;
|rw&lt;br /&gt;
| -&lt;br /&gt;
|Resets the waveform from the start (sync)&lt;br /&gt;
|-&lt;br /&gt;
|bipolar&lt;br /&gt;
|bp&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets whether the waveform is bipolar (default) or positive only&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;ahdsr&amp;quot;-&#039;&#039;plugin module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;ahdsr&amp;quot;-&#039;&#039;plugin module&#039;&#039; works like a standard [[wikipedia:ADSR|ADSR]] with the addition of a &amp;quot;hold&amp;quot;-period in between the &amp;quot;attack&amp;quot; and &amp;quot;decay&amp;quot; phase. The FAR specific items are the same as outlined in the &amp;quot;lfo&amp;quot;-&#039;&#039;plugin module&#039;&#039; with the exception of the &amp;quot;releasetarget&amp;quot; which triggers once the AHDSR reaches zero. This is useful for doing things like automatically putting the &#039;&#039;bowing jack&#039;&#039; in the &#039;&#039;rest&#039;&#039;-position when used on the &#039;&#039;pressure&#039;&#039; for instance. The &#039;&#039;commands&#039;&#039; for the &amp;quot;ahdsr&amp;quot;-&#039;&#039;plugin module&#039;&#039; are&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long command&lt;br /&gt;
!Short command&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Sets the nickname of the AHDSR&lt;br /&gt;
|-&lt;br /&gt;
|enable&lt;br /&gt;
|en&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Disables / Enables the output of the &#039;&#039;target commands&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|target&lt;br /&gt;
|tg&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the command string to execute each update cycle, the string [lfoout] will be replaced with the current value&lt;br /&gt;
|-&lt;br /&gt;
|updaterate&lt;br /&gt;
|ur&lt;br /&gt;
|milliseconds&lt;br /&gt;
|Sets the frequency with which the &#039;&#039;target commands&#039;&#039; are executed. Limited by the global maximum as set in the plugin handler&lt;br /&gt;
|-&lt;br /&gt;
|gate&lt;br /&gt;
|gt&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Gate signal, [1] initiates the &#039;&#039;attack&#039;&#039; phase and if it reaches its maximum value, &#039;&#039;holds&#039;&#039; for the time given. It then continues through the &#039;&#039;decay&#039;&#039; down to the &#039;&#039;sustain&#039;&#039; point. A [0] initiates the &#039;&#039;release&#039;&#039; from whatever point the ADSR is at&lt;br /&gt;
|-&lt;br /&gt;
|attack&lt;br /&gt;
|at&lt;br /&gt;
|milliseconds&lt;br /&gt;
|Attack time in milliseconds&lt;br /&gt;
|-&lt;br /&gt;
|hold&lt;br /&gt;
|hd&lt;br /&gt;
|milliseconds&lt;br /&gt;
|Hold time in milliseconds&lt;br /&gt;
|-&lt;br /&gt;
|decay&lt;br /&gt;
|dc&lt;br /&gt;
|milliseconds&lt;br /&gt;
|Decay time in milliseconds&lt;br /&gt;
|-&lt;br /&gt;
|sustain&lt;br /&gt;
|su&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sustain point in amplitude units&lt;br /&gt;
|-&lt;br /&gt;
|release&lt;br /&gt;
|re&lt;br /&gt;
|milliseconds&lt;br /&gt;
|Release time in milliseconds&lt;br /&gt;
|-&lt;br /&gt;
|releasetarget&lt;br /&gt;
|rt&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|&#039;&#039;Commands&#039;&#039; to execute once the release has hit zero&lt;br /&gt;
|-&lt;br /&gt;
|amplitude&lt;br /&gt;
|amp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Output amplitude&lt;br /&gt;
|-&lt;br /&gt;
|invert&lt;br /&gt;
|inv&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Inverts the results and gives negative values&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Knaadmin</name></author>
	</entry>
	<entry>
		<id>http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_reference_V1.1&amp;diff=1688</id>
		<title>The Ekdahl FAR - Command reference V1.1</title>
		<link rel="alternate" type="text/html" href="http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_reference_V1.1&amp;diff=1688"/>
		<updated>2026-06-14T12:42:29Z</updated>

		<summary type="html">&lt;p&gt;Knaadmin: /* The &amp;quot;lfo&amp;quot;-plugin module */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
The Ekdahl FAR V1.1 introduces the concept of &#039;&#039;modules&#039;&#039;. A &#039;&#039;module&#039;&#039; can contain any number of &#039;&#039;commands&#039;&#039; as well as other &#039;&#039;modules&#039;&#039;. Furthermore any number of &#039;&#039;modules&#039;&#039; of the same type can exist within a context, these are addressed using classic C-style array &#039;&#039;indexing&#039;&#039; with the help of brackets (&amp;quot;[ ]&amp;quot;). Extending on the classic usage, multiple &#039;&#039;indexes&#039;&#039; can be addressed simultaneously by either comma-separating the objects (&amp;quot;[0,3,4]&amp;quot;) and using &#039;&#039;ranges&#039;&#039; (&amp;quot;[3-6]&amp;quot;). &#039;&#039;Modules&#039;&#039; can be either &#039;&#039;internal&#039;&#039; or &#039;&#039;external&#039;&#039;, meaning that they may all physically exist within a single hardware object, or they can be be remote-controlled devices. From a user perspective this however makes no difference as they will appear the same.&lt;br /&gt;
&lt;br /&gt;
While all &#039;&#039;modules&#039;&#039; have their own set of &#039;&#039;commands&#039;&#039;, there are certain &#039;&#039;commands&#039;&#039; that all &#039;&#039;modules&#039;&#039; &amp;lt;u&amp;gt;must&amp;lt;/u&amp;gt; implement and can thus be accessed anywhere within the &#039;&#039;module hierarchy.&#039;&#039; There are also &#039;&#039;base commands&#039;&#039; that always exist within any given FAR ecosystem as well as product-specific &#039;&#039;base commands&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Ubiquitous commands ==&lt;br /&gt;
The &#039;&#039;module commands&#039;&#039; that are &amp;lt;u&amp;gt;required&amp;lt;/u&amp;gt; to be implemented in &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; &#039;&#039;modules&#039;&#039; and that can thus be accessed from anywhere are&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|list&lt;br /&gt;
|ls&lt;br /&gt;
|hidden/h:modules/m:commands/c:instances/i:instancecounts/ic:recursive/r&lt;br /&gt;
|Lists all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039; under the current module depending on the parameters given; &#039;hidden&#039; includes normally hidden &#039;&#039;commands&#039;&#039;, &#039;modules&#039; includes any &#039;&#039;submodules&#039;&#039;, &#039;commands&#039; shows &#039;&#039;commands&#039;&#039;, &#039;instances&#039; shows data for each individual instance of a &#039;&#039;module&#039;&#039;, &#039;instancecounts&#039; includes number of instances of each &#039;&#039;module&#039;&#039;, &#039;recursive&#039; lists all child &#039;&#039;modules&#039;&#039; / &#039;&#039;commands&#039;&#039;. No parameters defaults to showing all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039; recursively with instance counts. It doesn&#039;t show per-instance data or hidden commands.&lt;br /&gt;
|-&lt;br /&gt;
|help&lt;br /&gt;
|help&lt;br /&gt;
|recursive/r&lt;br /&gt;
|Shows a brief explanation of all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039;, shows the help for all &#039;&#039;submodules&#039;&#039; as well if &#039;recursive&#039;&lt;br /&gt;
|-&lt;br /&gt;
|dumpdata&lt;br /&gt;
|dump&lt;br /&gt;
|recursive/r&lt;br /&gt;
|Dumps all data saved for the current &#039;&#039;module&#039;&#039;, will list the data of all &#039;&#039;submodules&#039;&#039; as well if &#039;recursive&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Base commands ==&lt;br /&gt;
B&#039;&#039;ase commands&#039;&#039; are &#039;&#039;commands&#039;&#039; that always exist at the root in any implementation of the Ekdahl FAR.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|version&lt;br /&gt;
|ver&lt;br /&gt;
| -&lt;br /&gt;
|Gets the current firmware version&lt;br /&gt;
|-&lt;br /&gt;
|debugprint&lt;br /&gt;
|dp&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;command|usb|hardware|undefined|priority|error|inforequest|expressionparser|debug:1|0&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Turns on or off serial feedback for the given item&lt;br /&gt;
|-&lt;br /&gt;
|requestinfo&lt;br /&gt;
|rqi&lt;br /&gt;
|command&lt;br /&gt;
|Retrives any data saved for a &#039;&#039;command&#039;&#039;, if applicable&lt;br /&gt;
|-&lt;br /&gt;
|saveallparameters&lt;br /&gt;
|sap&lt;br /&gt;
| -&lt;br /&gt;
|Saves all avaliable parameters&lt;br /&gt;
|-&lt;br /&gt;
|loadallparameters&lt;br /&gt;
|lap&lt;br /&gt;
| -&lt;br /&gt;
|Loads all avaliable parameters&lt;br /&gt;
|-&lt;br /&gt;
|resetallparameters&lt;br /&gt;
|rap&lt;br /&gt;
| -&lt;br /&gt;
|Resets all saved parameters&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|rst&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;1|0&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Resets the Ekdahl FAR, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|nick&lt;br /&gt;
|nick&lt;br /&gt;
|name&lt;br /&gt;
|Sets the nickname of this unit&lt;br /&gt;
|-&lt;br /&gt;
|nooperation&lt;br /&gt;
|nop&lt;br /&gt;
| -&lt;br /&gt;
|Do absolutely, positively, nothing. Useful for testing and interfacing with computers, it&#039;s a good way to know that the unit is alive and responding since a &amp;quot;nop&amp;quot; is being returned as a response upon reception.&lt;br /&gt;
|-&lt;br /&gt;
|uservariable&lt;br /&gt;
|uv&lt;br /&gt;
|variable(0-9):value&lt;br /&gt;
|Set user variable 0-9 to &#039;value&#039;&lt;br /&gt;
|-&lt;br /&gt;
|expressionparserevaluate&lt;br /&gt;
|epev&lt;br /&gt;
|expression&lt;br /&gt;
|Evaluates an arithmetric expression and sends back the output, all variables and functions that can be used in any &#039;&#039;command string&#039;&#039; can also be used here. Useful for testing expressions.&lt;br /&gt;
|-&lt;br /&gt;
|ifequal&lt;br /&gt;
|ife&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] EQUALS [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring].&lt;br /&gt;
|-&lt;br /&gt;
|ifgreater&lt;br /&gt;
|ifg&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] &amp;gt; [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring]&lt;br /&gt;
|-&lt;br /&gt;
|ifless&lt;br /&gt;
|ifl&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] &amp;lt; [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring]&lt;br /&gt;
|-&lt;br /&gt;
|freeram&lt;br /&gt;
|ram&lt;br /&gt;
| -&lt;br /&gt;
|Shows free RAM memory&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The base also contains the following &#039;&#039;modules:&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|pluginhandler&lt;br /&gt;
|ph&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The Ekdahl FAR stand alone single string unit ==&lt;br /&gt;
The Ekdahl FAR stand-alone single string unit offers these &#039;&#039;commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|calibrateall&lt;br /&gt;
|ca&lt;br /&gt;
| -&lt;br /&gt;
|Performs all calibration routines on the selected bow, see below for routines performed&lt;br /&gt;
|-&lt;br /&gt;
|calibratebowspeed&lt;br /&gt;
|cbs&lt;br /&gt;
| -&lt;br /&gt;
|Finds the minimum and maximum bow speed of the selected bow&lt;br /&gt;
|-&lt;br /&gt;
|calibratebowpressure&lt;br /&gt;
|cbp&lt;br /&gt;
| -&lt;br /&gt;
|Finds the minimum and maximum bow pressure of the selected bow&lt;br /&gt;
|-&lt;br /&gt;
|calibratemute&lt;br /&gt;
|cmu&lt;br /&gt;
| -&lt;br /&gt;
|Calibrate mute settings&lt;br /&gt;
|-&lt;br /&gt;
|pickupstringfrequency&lt;br /&gt;
|psf&lt;br /&gt;
| -&lt;br /&gt;
|Returns the fundamental tone calculated from the current audio signal if apliccable&lt;br /&gt;
|-&lt;br /&gt;
|pickupaudiopeak&lt;br /&gt;
|pap&lt;br /&gt;
| -&lt;br /&gt;
|Returns the peak amplitude of the current audio signal&lt;br /&gt;
|-&lt;br /&gt;
|pickupaudiorms&lt;br /&gt;
|par&lt;br /&gt;
| -&lt;br /&gt;
|Returns the RMS amplitude of the current audio signal&lt;br /&gt;
|}&lt;br /&gt;
The Ekdahl FAR also contains the following &#039;&#039;modules&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|bowingwheel&lt;br /&gt;
|bw&lt;br /&gt;
|-&lt;br /&gt;
|mute&lt;br /&gt;
|mu&lt;br /&gt;
|-&lt;br /&gt;
|solenoid&lt;br /&gt;
|so&lt;br /&gt;
|-&lt;br /&gt;
|controlbox&lt;br /&gt;
|cb&lt;br /&gt;
|-&lt;br /&gt;
|midiconfigurationhandler&lt;br /&gt;
|mcf&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;Bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; contains everything needed to interface with a single &#039;&#039;bowing wheel&#039;&#039;. Each &#039;&#039;bowing wheel&#039;&#039; has its own harmonic series, pressure actuators and direct hardware interface. It contains the following &#039;&#039;commands&#039;&#039;.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|speedmode&lt;br /&gt;
|sm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Bow motor speed mode, 0 = Automatic and 1 = Manual. Automatic mode means that the bowing wheel will automatically turn off after the &#039;&#039;motor timeout&#039;&#039; has been reached after being put into rest mode&lt;br /&gt;
|-&lt;br /&gt;
|motortimeout&lt;br /&gt;
|mt&lt;br /&gt;
|ms&lt;br /&gt;
|Bow motor shutdown timeout after bow having been put into the rest position&lt;br /&gt;
|-&lt;br /&gt;
|pidenable&lt;br /&gt;
|pe&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets the bow PID on/off&lt;br /&gt;
|-&lt;br /&gt;
|motorfaultcommands&lt;br /&gt;
|mfc&lt;br /&gt;
|commands&lt;br /&gt;
|Commands to execute when a motor fault is tripped - !WARNING! Can ruin your instrument if changed&lt;br /&gt;
|-&lt;br /&gt;
|motoroverpowercommands&lt;br /&gt;
|moc&lt;br /&gt;
|commands&lt;br /&gt;
|Commands to execute when motor is over the power limit - !WARNING! Can ruin your instrument if changed&lt;br /&gt;
|}&lt;br /&gt;
The &#039;&#039;modules&#039;&#039; in the &amp;quot;Bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; are as follows&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|bowpressure&lt;br /&gt;
|bp&lt;br /&gt;
|-&lt;br /&gt;
|dcmotor&lt;br /&gt;
|dcm&lt;br /&gt;
|-&lt;br /&gt;
|pid&lt;br /&gt;
|pid&lt;br /&gt;
|-&lt;br /&gt;
|harmonicserieshandler&lt;br /&gt;
|hsh&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; handles the &#039;&#039;pressure&#039;&#039; of the &#039;&#039;bowing wheel&#039;&#039; against the string. The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|baseline&lt;br /&gt;
|ba&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure baseline, modulation is added to this point upward. Typically this is set with a knob on the &#039;&#039;control box&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|modifier&lt;br /&gt;
|mo&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure modulation, added to the baseline&lt;br /&gt;
|-&lt;br /&gt;
|rest&lt;br /&gt;
|rs&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the bow pressure in the &#039;&#039;rest&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|engage&lt;br /&gt;
|en&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the bow pressure in the &#039;&#039;engage&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|stallpressure&lt;br /&gt;
|sp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure stall/maximum position, this parameter is set using &#039;&#039;hardware positioning&#039;&#039; and is used as the absolute maximum for baseline and modifier combiner&lt;br /&gt;
|-&lt;br /&gt;
|engagepressure&lt;br /&gt;
|ep&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure touch/minimum position, this parameter is set using &#039;&#039;hardware position&#039;&#039; and is used as the starting point for when both the baseline and modifier is set to zero&lt;br /&gt;
|-&lt;br /&gt;
|restpressure&lt;br /&gt;
|rp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure rest position, this parameter is set using &#039;&#039;hardware positioning&#039;&#039; and is typically set to a point just below the string where it does not touch at all. The purpose of this is because while the actual hardware might be able to make the bow go even lower, that position might be far enough from the string that once &#039;&#039;engaged&#039;&#039; the bow may have so far to travel that there is perceptible &#039;&#039;latency&#039;&#039;.&lt;br /&gt;
|-&lt;br /&gt;
|engagespeed&lt;br /&gt;
|es&lt;br /&gt;
|1- ~100&lt;br /&gt;
|Bow pressure movement speed when engaging or disengaging&lt;br /&gt;
|-&lt;br /&gt;
|modulationspeed&lt;br /&gt;
|ms&lt;br /&gt;
|0.1 - 10&lt;br /&gt;
|Bow pressure movement speed while engaged&lt;br /&gt;
|-&lt;br /&gt;
|hold&lt;br /&gt;
|hd&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets bow hold (infinite sustain) on/off, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|home&lt;br /&gt;
|hm&lt;br /&gt;
| -&lt;br /&gt;
|Homing bow, used at startup and in case of the bow loosing position&lt;br /&gt;
|-&lt;br /&gt;
|tmcinfo&lt;br /&gt;
|tmi&lt;br /&gt;
| -&lt;br /&gt;
|Request statistical information from the TMC2209 stepper motor driver&lt;br /&gt;
|}&lt;br /&gt;
Note that the &amp;quot;stall&amp;quot;, &amp;quot;engage&amp;quot; and &amp;quot;rest&amp;quot;-pressure positions mention something called &#039;&#039;hardware position&#039;&#039;. This means the entire available movement of the &#039;&#039;bowing jack&#039;&#039;. Because the very bottom and top end of the movement might not be musically useful and may even harm the instrument, the &amp;quot;baseline&amp;quot; and &amp;quot;modifier&amp;quot; commands &#039;&#039;parameter&#039;&#039;s are scaled depending on these settings.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;engage&amp;quot; and &amp;quot;modulation&amp;quot;-speed settings sets how fast the stepper motor that drives the &#039;&#039;pressure&#039;&#039; moves depending on whether the &#039;&#039;bowing jack&#039;&#039; is set to &#039;&#039;engage&#039;&#039; or not. The idea here is that while wanting to be able to minimize &#039;&#039;latency&#039;&#039; by &#039;&#039;engaging&#039;&#039; and &#039;&#039;disengaging&#039;&#039; from the string as quickly as possible, dynamic changes in the &#039;&#039;pressure&#039;&#039; while playing benefits from much smoother movements as the &#039;&#039;bowing wheel&#039;&#039; takes some time to catch up to varying amounts of friction.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; contains one or more of the following &#039;&#039;modules&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|actuatorhandler&lt;br /&gt;
|ah&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;actuatorhandler&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The concept of &amp;quot;actuators&amp;quot; came up as it is possible to have &#039;&#039;bowing wheels&#039;&#039; of different sizes and wanting to be able to switch quickly in between them, perhaps during mid-performance. Because a differently sized wheel will require different values for the above mentioned &amp;quot;stall&amp;quot;, &amp;quot;engage&amp;quot; and &amp;quot;reset&amp;quot;-&#039;&#039;pressure&#039;&#039;, each &#039;&#039;actuator&#039;&#039; stores these values. Instead of having to manually change the previously mentioned values, simply selecting a new &#039;&#039;actuator&#039;&#039; will automatically load the values. The &amp;quot;actuatorhandler&amp;quot;-&#039;&#039;module&#039;&#039; is the handler of one or more &amp;quot;actuator&amp;quot;-&#039;&#039;modules&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;commands&#039;&#039; of the &amp;quot;acuatorhandler&amp;quot;-&#039;&#039;module&#039;&#039; are as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|add&lt;br /&gt;
|a&lt;br /&gt;
|(name):(rest:engage:stall)&lt;br /&gt;
|Add new actuator with the given name and parameters&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|actuatornumber&lt;br /&gt;
|Remove bow actuator [actuatornumber]&lt;br /&gt;
|-&lt;br /&gt;
|count&lt;br /&gt;
|c&lt;br /&gt;
| -&lt;br /&gt;
|Returns the amount of saved bow actuators&lt;br /&gt;
|}&lt;br /&gt;
The &amp;quot;actuatorhandler&amp;quot;-&#039;&#039;module&#039;&#039; contains one or more of&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|actuator&lt;br /&gt;
|ac&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;actuator&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;actuator&amp;quot;-&#039;&#039;module&#039;&#039; contains the following commands&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|[index]&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|Selects the given actuator&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Sets the actuator name&lt;br /&gt;
|-&lt;br /&gt;
|data&lt;br /&gt;
|da&lt;br /&gt;
|name:rest:engage:stall&lt;br /&gt;
|Sets the actuator name, rest, engage and stall &#039;&#039;pressure&#039;&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;dcmotor&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;dcmotor&amp;quot;-&#039;&#039;module&#039;&#039; handles the direct &amp;lt;u&amp;gt;raw&amp;lt;/u&amp;gt; control of the &#039;&#039;bowing motor&#039;&#039; and handles the reporting back of the current speed. It has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|run&lt;br /&gt;
|ru&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Turns the motor off/on&lt;br /&gt;
|-&lt;br /&gt;
|pwm&lt;br /&gt;
|pw&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor direct power in 16-bit PWM values, requires that the &#039;&#039;PID&#039;&#039; is turned off&lt;br /&gt;
|-&lt;br /&gt;
|voltage&lt;br /&gt;
|vo&lt;br /&gt;
|~2 - 10V&lt;br /&gt;
|Sets the voltage of the regulator powering the motor. Changes here can make the motor more responsive to certain frequencies but will also affect how well the &#039;&#039;PID&#039;&#039; works. !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|current&lt;br /&gt;
|cu&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor reported current use&lt;br /&gt;
|-&lt;br /&gt;
|currentlimit&lt;br /&gt;
|cl&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor current limit (A)- !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|powerlimit&lt;br /&gt;
|pl&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor power limit (W) - !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|frequency&lt;br /&gt;
|fq&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor reported frequency&lt;br /&gt;
|-&lt;br /&gt;
|emergencystop&lt;br /&gt;
|es&lt;br /&gt;
|ms (0-65535)&lt;br /&gt;
|Immediately stops the bowing motor and doesn&#039;t allow it to start again until the cool down period given in the first argument has lapsed (milliseconds)&lt;br /&gt;
|-&lt;br /&gt;
|minpwm&lt;br /&gt;
|ip&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor minimum PWM (for calibration)&lt;br /&gt;
|-&lt;br /&gt;
|maxpwm&lt;br /&gt;
|xp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor maximum PWM (for calibration)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;pidcontroller&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;pidcontroller&amp;quot;-&#039;&#039;module&#039;&#039; is responsible for keeping the &amp;quot;dcmotor&amp;quot;-&#039;&#039;module&#039;&#039; at a certain frequency (given in Hertz). It takes the output of the motor frequency measurement and feeds it a PWM value that tries to make the speed constant regardless of the friction that the motor is enduring. To learn more about PID Controllers please see this [[wikipedia:PID_controller|wikipedia article]]. The &#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|targetfrequency&lt;br /&gt;
|tf&lt;br /&gt;
|hertz&lt;br /&gt;
|Sets the PID target frequency&lt;br /&gt;
|-&lt;br /&gt;
|ki&lt;br /&gt;
|ki&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Ki parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|kp&lt;br /&gt;
|kp&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Kp parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|kd&lt;br /&gt;
|kd&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Kd parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|integratorerror&lt;br /&gt;
|ie&lt;br /&gt;
|float&lt;br /&gt;
|Sets the lower threshold of error values for the PID integrator to ignore&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|re&lt;br /&gt;
| -&lt;br /&gt;
|Resets the PID integrator and derivative&lt;br /&gt;
|-&lt;br /&gt;
|maxerror&lt;br /&gt;
|xe&lt;br /&gt;
|float&lt;br /&gt;
|Maximum error to correct in each PID loop, essentially sets acceleration&lt;br /&gt;
|-&lt;br /&gt;
|peakerror&lt;br /&gt;
|pe&lt;br /&gt;
|float&lt;br /&gt;
|Get latest PID peak error&lt;br /&gt;
|-&lt;br /&gt;
|motorspeedmax&lt;br /&gt;
|msx&lt;br /&gt;
|Hertz&lt;br /&gt;
|Bow motor maximum speed limit&lt;br /&gt;
|-&lt;br /&gt;
|motorspeedmin&lt;br /&gt;
|msi&lt;br /&gt;
|Hertz&lt;br /&gt;
|Bow motor minimum speed limit&lt;br /&gt;
|-&lt;br /&gt;
|measuretimetotarget&lt;br /&gt;
|mtt&lt;br /&gt;
|Hertz&lt;br /&gt;
|Measure the time it takes to change from the current frequency to the target frequency, for testing purposes&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; is responsible for sending frequency data to the &amp;quot;pid&amp;quot;-&#039;&#039;module&#039;&#039;. It handles calculating the correct frequency of the &#039;&#039;bowing wheel&#039;&#039; according to the selected &#039;&#039;harmonic&#039;&#039; and &#039;&#039;harmonic shift&#039;&#039; per the currently selected &#039;&#039;harmonic series&#039;&#039;. The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|fundamental&lt;br /&gt;
|fu&lt;br /&gt;
|Hertz&lt;br /&gt;
|The fundamental frequency of the string, all harmonics are calculated from this number&lt;br /&gt;
|-&lt;br /&gt;
|harmonic&lt;br /&gt;
|h&lt;br /&gt;
|int&lt;br /&gt;
|Selects the harmonic number to set the &#039;&#039;bowing wheel&#039;&#039; to. A ratio is taken from the given &#039;&#039;harmonic&#039;&#039; in the current &#039;&#039;harmonic series&#039;&#039;, the ratio is then multiplied by the &#039;&#039;fundamental frequency&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|harmonicadd&lt;br /&gt;
|ha&lt;br /&gt;
|int&lt;br /&gt;
|This number is added to the current harmonic&lt;br /&gt;
|-&lt;br /&gt;
|harmonicbase&lt;br /&gt;
|hb&lt;br /&gt;
|int&lt;br /&gt;
|Same as harmonic but where the harmonic number is based on a MIDI note given by basenote&lt;br /&gt;
|-&lt;br /&gt;
|basenote&lt;br /&gt;
|bn&lt;br /&gt;
|0-127&lt;br /&gt;
|Sets the MIDI base note of the &#039;&#039;bowing wheel&#039;&#039;, used in conjunction with &amp;quot;harmonicbase&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|shift&lt;br /&gt;
|sh&lt;br /&gt;
| -32767 - 32767&lt;br /&gt;
|Sets shift from the currently playing harmonic where 32767 equals the entire harmonic shift range shifted up&lt;br /&gt;
|-&lt;br /&gt;
|shiftrange&lt;br /&gt;
|sr&lt;br /&gt;
|0-36&lt;br /&gt;
|Set the number of harmonic numbers that constitutes an entire harmonic shift&lt;br /&gt;
|-&lt;br /&gt;
|shift5&lt;br /&gt;
|sh5&lt;br /&gt;
| -32767 - 32767&lt;br /&gt;
|Sets the shift from the currently playing harmonic over 5 octaves where 32767 equals 5 octaves shift up from the fundamental&lt;br /&gt;
|-&lt;br /&gt;
|add&lt;br /&gt;
|a&lt;br /&gt;
|(name):(ratios)&lt;br /&gt;
|Add a new series with the given name and parameters&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|series&lt;br /&gt;
|Remove the series given and shift any series accordingly. Cannot remove all series&lt;br /&gt;
|-&lt;br /&gt;
|count&lt;br /&gt;
|c&lt;br /&gt;
| -&lt;br /&gt;
|Returns the number of harmonic series in the list and their IDs&lt;br /&gt;
|}&lt;br /&gt;
The &amp;quot;harmonicserieshandler&amp;quot;-module contains at the very least ONE harmonic series, by default it contains two: one for equal temperament and one for just intonation. The current series can be selected by simply indexing the &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; without a &#039;&#039;command&#039;&#039;, e.g. &amp;quot;harmonicserieshandler.harmonicseries[1]&amp;quot;. To be consistent, these are the &#039;&#039;modules&#039;&#039; in the &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|harmonicseries&lt;br /&gt;
|hs&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; contains any number of &#039;&#039;ratios&#039;&#039; that comprises a scale, ratios are given in a standard format where a ratio of &amp;quot;1&amp;quot; is equal to the fundamental, &amp;quot;2&amp;quot; would be one octave up etc. A standard &#039;&#039;harmonic series&#039;&#039; contains 12 ratios following a just intonation scheme. The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; will automatically adapt to the currently selected &#039;&#039;harmonic series&#039;&#039; length, whether it&#039;s a standard 12-tone scale, some kinda 3-tone scale or a full on bananas 53-tone scale. The &#039;&#039;commands&#039;&#039; of the &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; is as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|[index]&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
|Sets the currently selected &#039;&#039;harmonic Series&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Sets the name of the &#039;&#039;harmonic series&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|data&lt;br /&gt;
|da&lt;br /&gt;
|name:ratios&lt;br /&gt;
|Gets / sets all data for the &#039;&#039;harmonic series&#039;&#039; in the given slot with an arbitrary &#039;&#039;name&#039;&#039; as the first &#039;&#039;parameter&#039;&#039;. The length of the series is simply set to the amount of ratios given&lt;br /&gt;
|-&lt;br /&gt;
|ratio&lt;br /&gt;
|r&lt;br /&gt;
|harmonic:ratio&lt;br /&gt;
|Sets the ratio of the given harmonic in current &#039;&#039;harmonic series&#039;&#039;, will increase the list size if needed to address the harmonic&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|harmonic&lt;br /&gt;
|Remove the harmonic ratio given in the current series and shift any ratios accordingly. Cannot remove all ratios&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;mute&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;mute&amp;quot;-&#039;&#039;module&#039;&#039; works very similarly to the &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; in that it controls a stepper motor with some software limits in place in order to press the mute against the string. The &#039;&#039;commands&#039;&#039; are as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|setposition&lt;br /&gt;
|sp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set mute position&lt;br /&gt;
|-&lt;br /&gt;
|fullmute&lt;br /&gt;
|fm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the mute in &#039;&#039;full mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|halfmute&lt;br /&gt;
|hm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the mute in &#039;&#039;half mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|rest&lt;br /&gt;
|rs&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Put the mute in the &#039;&#039;rest&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|savefull&lt;br /&gt;
|sf&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Save the current mute position as the &#039;&#039;full mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|savehalf&lt;br /&gt;
|sh&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Save the current mute position as the &#039;&#039;half mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|saverest&lt;br /&gt;
|sr&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Save the current mute position as the &#039;&#039;rest&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|fullmuteposition&lt;br /&gt;
|fmp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;full mute&#039;&#039; position according to the &#039;&#039;hardware position&#039;&#039; given&lt;br /&gt;
|-&lt;br /&gt;
|halfmuteposition&lt;br /&gt;
|hmp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;half mute&#039;&#039; position according to the &#039;&#039;hardware position&#039;&#039; given&lt;br /&gt;
|-&lt;br /&gt;
|restposition&lt;br /&gt;
|rp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;rest&#039;&#039; position according to the &#039;&#039;hardware position&#039;&#039; given&lt;br /&gt;
|-&lt;br /&gt;
|sustain&lt;br /&gt;
|su&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets the sustain off/on, this will keep the mute in the &#039;&#039;rest&#039;&#039; position even if a &amp;quot;fullmute&amp;quot;-&#039;&#039;command&#039;&#039; is given, lasts until &amp;quot;sustain&amp;quot; is set to &amp;quot;0&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
|backoff&lt;br /&gt;
|bo&lt;br /&gt;
|0-65535&lt;br /&gt;
|Setting the time that the mute stays in the mutefullmute position before automatically going into rest, set in mS. A value of &amp;quot;0&amp;quot; disables backoff. This is used because if the mute is not backing off until something is attempted to be played, the backing-off time will either introduce &#039;&#039;latency&#039;&#039; or the string will be initially partially muted&lt;br /&gt;
|-&lt;br /&gt;
|home&lt;br /&gt;
|hm&lt;br /&gt;
| -&lt;br /&gt;
|Home mute, used during initialization and if the mute were to loose position&lt;br /&gt;
|-&lt;br /&gt;
|hardwareposition&lt;br /&gt;
|hwp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;hardware position&#039;&#039; of the mute instead of scaling it over the &#039;&#039;full mute&#039;&#039; and &#039;&#039;rest&#039;&#039; positions. Mainly used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|completetask&lt;br /&gt;
|cpt&lt;br /&gt;
| -&lt;br /&gt;
|Requests a callback when the current operation is finished. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|autocorrect&lt;br /&gt;
|ac&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Enables auto correct positioning that uses the homing sensor to correct positioning on the fly. EXPERIMENTAL&lt;br /&gt;
|-&lt;br /&gt;
|homingsensed&lt;br /&gt;
|hms&lt;br /&gt;
| -&lt;br /&gt;
|Requests whether the homing sensor is currently active or not. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|movedirection&lt;br /&gt;
|md&lt;br /&gt;
| -&lt;br /&gt;
|Requests the current direction of movement (0 Forward, 1 Reverse). Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|currentstep&lt;br /&gt;
|cs&lt;br /&gt;
| -&lt;br /&gt;
|Requests the current step. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|homingpoint&lt;br /&gt;
|hmp&lt;br /&gt;
|edgedirection&lt;br /&gt;
|Requests the given homing point. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|homingstage&lt;br /&gt;
|hms&lt;br /&gt;
| -&lt;br /&gt;
|Requests the current homing stage (UNHOMED, HOMED, FIRSTHOMINGRISING, SECONDHOMINGFALLING, SECONDHOMINGRISING, FIRSTHOMINGFALLING, MOVEPASTHOMESWITCH, MOVETOHOMESWITCH, GOTOOFFSET). Only used internally by other &#039;&#039;modules.&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|tmcinfo&lt;br /&gt;
|tmi&lt;br /&gt;
| -&lt;br /&gt;
|Request statistical information from the TMC2209 stepper motor driver&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;solenoid&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;solenoid&amp;quot;-&#039;&#039;module&#039;&#039; currently controls the &#039;&#039;hammer&#039;&#039; of the Ekdahl FAR. Due to the fact that the very same &#039;&#039;module&#039;&#039; could be used for anything that uses a striking &#039;&#039;solenoid&#039;&#039; it was named as such. It has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|engage&lt;br /&gt;
|en&lt;br /&gt;
|0-65535&lt;br /&gt;
|Engages the solenoid using the first parameter as the force&lt;br /&gt;
|-&lt;br /&gt;
|rest&lt;br /&gt;
|rs&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Forces the solenoid to its rest position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|maxforce&lt;br /&gt;
|xf&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set solenoid maximum usable force&lt;br /&gt;
|-&lt;br /&gt;
|minforce&lt;br /&gt;
|if&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set solenoid minimum usable force&lt;br /&gt;
|-&lt;br /&gt;
|forcemultiplier&lt;br /&gt;
|fm&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set solenoid force multiplier, useful for scaling of all incoming &amp;quot;engage&amp;quot;-&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|engageduration&lt;br /&gt;
|ed&lt;br /&gt;
|uS&lt;br /&gt;
|Sets the duration of the solenoid hit in uS, if a value of 0 is set the solenoid will not disengage until a rest command has been given. WARNING!! HAVING THE SOLENOID ON FOR A SPAN OF SECONDS COULD DESTROY THE CIRCUITRY!!&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;controlbox&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;controlbox&amp;quot;-&#039;&#039;module&#039;&#039; communicates with an external &#039;&#039;control box&#039;&#039; and will issue associated &#039;&#039;commands&#039;&#039; whenever new values are read on the ADC-converters. It handles averaging and does some noise-cancellation functions on the values as well. The &#039;&#039;commands&#039;&#039; are:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|harmonic&lt;br /&gt;
|har&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the harmonic knob or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|harmonicshift&lt;br /&gt;
|has&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the harmonic shift modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|finetune&lt;br /&gt;
|fin&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the fine tune knob changes&lt;br /&gt;
|-&lt;br /&gt;
|pressure&lt;br /&gt;
|pre&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the pressure knob or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|mute&lt;br /&gt;
|mut&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the mute knob or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|hammerscale&lt;br /&gt;
|hms&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the hammer scale knob changes&lt;br /&gt;
|-&lt;br /&gt;
|gate&lt;br /&gt;
|gt&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the gate switch or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|hammertrig&lt;br /&gt;
|hmt&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the hammer trigger modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|controldefaults&lt;br /&gt;
|cde&lt;br /&gt;
| -&lt;br /&gt;
|Reverts all ADC command strings to default values&lt;br /&gt;
|-&lt;br /&gt;
|datareturn&lt;br /&gt;
|dr&lt;br /&gt;
|channel:value&lt;br /&gt;
|Sent when a new value is presented on one of the ADC channels, cannot be invoked. Triggers the commands associated with the channel&lt;br /&gt;
|-&lt;br /&gt;
|adcsetting&lt;br /&gt;
|adcs&lt;br /&gt;
|channel : averages : interrupterrorthreshold : continuouserrorthreshold : continuoustimeout&lt;br /&gt;
|Sets ADC settings for a given channel. Averages are the number of samples to average, interruptthreshold is how much the value must change in order to issue a new value change event. continuousthreshold is how much the value must change when a previous change has already been recorded within the timespan of continuoustimeout&lt;br /&gt;
|-&lt;br /&gt;
|testadclatency&lt;br /&gt;
|tal&lt;br /&gt;
|0-65535&lt;br /&gt;
|Start a ADC latency test&lt;br /&gt;
|-&lt;br /&gt;
|testadclatencyreturn&lt;br /&gt;
|talr&lt;br /&gt;
| -&lt;br /&gt;
|Return from latency test&lt;br /&gt;
|-&lt;br /&gt;
|testadcminmax&lt;br /&gt;
|tix&lt;br /&gt;
|channel&lt;br /&gt;
|Test min/max value for a given channel and resets the counter&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;midiconfigurationhandler&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;midiconfigurationhandler&amp;quot;-&#039;&#039;module&#039;&#039; handles a number of &amp;quot;midiconfiguration&amp;quot;-&#039;&#039;modules&#039;&#039;. It has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|allnotesoff&lt;br /&gt;
|ano&lt;br /&gt;
| -&lt;br /&gt;
|Clears the entire buffer of MIDI notes held&lt;br /&gt;
|-&lt;br /&gt;
|add&lt;br /&gt;
|a&lt;br /&gt;
|name&lt;br /&gt;
|Adds a new MIDI configuration with the given name&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|int&lt;br /&gt;
|Remove the specified MIDI configuration&lt;br /&gt;
|-&lt;br /&gt;
|count&lt;br /&gt;
|c&lt;br /&gt;
| -&lt;br /&gt;
|Returns the number of MIDI configurations&lt;br /&gt;
|}&lt;br /&gt;
It contains one or more of the following&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|midiconfiguration&lt;br /&gt;
|mc&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;midiconfiguration&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
A &amp;quot;midiconfiguration&amp;quot;-&#039;&#039;module&#039;&#039; handles the reception of &#039;&#039;MIDI messages&#039;&#039; and will output the associated &#039;&#039;commands&#039;&#039; to the instrument internally. The commands are as follows&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|[index]&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
|Sets the currently selected MIDI configuration&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Set the name of the MIDI configuration&lt;br /&gt;
|-&lt;br /&gt;
|noteon&lt;br /&gt;
|non&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Note On event&lt;br /&gt;
|-&lt;br /&gt;
|noteoff&lt;br /&gt;
|nof&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Note Off event&lt;br /&gt;
|-&lt;br /&gt;
|polyaftertouch&lt;br /&gt;
|pat&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Polyphonic after touch event&lt;br /&gt;
|-&lt;br /&gt;
|channelaftertouch&lt;br /&gt;
|cat&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Channel after touch event&lt;br /&gt;
|-&lt;br /&gt;
|pitchbend&lt;br /&gt;
|pb&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Pitch bend event&lt;br /&gt;
|-&lt;br /&gt;
|programchange&lt;br /&gt;
|pc&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Program change event&lt;br /&gt;
|-&lt;br /&gt;
|continuouscontrollerdata&lt;br /&gt;
|ccd&lt;br /&gt;
|controllernuber:&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Continuous controller event with the given [&#039;&#039;controllernumber&#039;&#039;]&lt;br /&gt;
|-&lt;br /&gt;
|removecc&lt;br /&gt;
|rmc&lt;br /&gt;
|controllernuber&lt;br /&gt;
|Removes the entry associated with the MIDI continuous controller even &#039;&#039;controllernumber&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|defaults&lt;br /&gt;
|d&lt;br /&gt;
| -&lt;br /&gt;
|Reverts the current configuration to default &#039;&#039;commands&#039;&#039;, values and CCs&lt;br /&gt;
|-&lt;br /&gt;
|receivechannel&lt;br /&gt;
|rc&lt;br /&gt;
|channel&lt;br /&gt;
|Sets the MIDI receive channel of the current configuration. 1-16 sets specific channel, any other value for OMNI&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;pluginhandler&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The Ekdahl FAR allows for &#039;&#039;plugins&#039;&#039;. These are &#039;&#039;modules&#039;&#039; that can trigger certain &#039;&#039;command strings&#039;&#039; to be executed either periodically or triggered by an incoming &#039;&#039;command&#039;&#039;. Further explanation of the given &#039;&#039;plugins&#039;&#039; is given below. The various &#039;&#039;plugins&#039;&#039; are handled by the &amp;quot;pluginhandler&amp;quot;-&#039;&#039;module&#039;&#039;, the different &#039;&#039;plugin modules&#039;&#039; are identified by their own unique &#039;&#039;ID&#039;&#039;. The &amp;quot;pluginhandler&amp;quot;-&#039;&#039;module&#039;&#039; it has the following &#039;&#039;commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|add&lt;br /&gt;
|a&lt;br /&gt;
|pluginid&lt;br /&gt;
|Add plugin with the given ID&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|pluginid:index&lt;br /&gt;
|Remove plugin with the given ID and index&lt;br /&gt;
|-&lt;br /&gt;
|count&lt;br /&gt;
|c&lt;br /&gt;
|(pluginid)&lt;br /&gt;
|Return the number of plugins of the given type, if none is given it returns all plugins&lt;br /&gt;
|}&lt;br /&gt;
The number of available &#039;&#039;plugins&#039;&#039; will differ from time to time as the &#039;&#039;plugin system&#039;&#039; has been purposefully designed to allow for anyone to write and add their own &#039;&#039;plugins&#039;&#039;. As of the current writing (2026-06-14) the number of &amp;lt;u&amp;gt;possible&amp;lt;/u&amp;gt; &#039;&#039;plugin modules&#039;&#039; that &amp;lt;u&amp;gt;can&amp;lt;/u&amp;gt; exist under the &amp;quot;pluginhandler&amp;quot;-&#039;&#039;module&#039;&#039; are&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|lfo&lt;br /&gt;
|lfo&lt;br /&gt;
|-&lt;br /&gt;
|ahdsr&lt;br /&gt;
|ahdsr&lt;br /&gt;
|-&lt;br /&gt;
|numbermap&lt;br /&gt;
|map&lt;br /&gt;
|-&lt;br /&gt;
|multiple&lt;br /&gt;
|mlt&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;lfo&amp;quot;-&#039;&#039;plugin module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;lfo&amp;quot;-&#039;&#039;plugin module&#039;&#039; works like regular [[wikipedia:Low-frequency_oscillation|low frequency oscillator]] in that it generates a given &#039;&#039;waveform&#039;&#039; with a given &#039;&#039;frequency&#039;&#039; at a certain &#039;&#039;amplitude&#039;&#039;. In the Ekdahl FAR the distinguishing factors are that besides the common &#039;&#039;frequency, amplitude&#039;&#039; and &#039;&#039;waveform&#039;&#039; parameters, it also requires the use of a &#039;&#039;update rate&#039;&#039; and &#039;&#039;target&#039;&#039; parameter. The &#039;&#039;update rate&#039;&#039; sets how often the current position of the LFO is sampled (aka how often it peeks in on where the LFO is in its waveform transition at the moment), and each time that happens, the &#039;&#039;target commands&#039;&#039; are outputted to the instrument.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example:&#039;&#039;&#039;&lt;br /&gt;
 Lets set the &#039;&#039;waveform&#039;&#039; to &amp;quot;triangle&amp;quot;, the &#039;&#039;amplitude&#039;&#039; to 65535 (max), the &#039;&#039;frequency&#039;&#039; to 1Hz (1 full waveform per second), the &#039;&#039;update rate&#039;&#039; to 10mS and the &#039;&#039;target&#039;&#039; to &amp;quot;bowingwheel.harmonicserieshandler.shift:lfoout&amp;quot;.&lt;br /&gt;
 &lt;br /&gt;
 The output of the LFO is always given in the variable &amp;quot;lfoout&amp;quot;, our &#039;&#039;target&#039;&#039; is set to &amp;quot;bowingwheel.harmonicserieshandler.shift&amp;quot; which controls the &#039;&#039;harmonic shift&#039;&#039; (pitchbend basically) of the &#039;&#039;bowing wheel&#039;&#039;.&lt;br /&gt;
 &lt;br /&gt;
 Since our update rate is set to every 10 milliseconds and our frequency is 1 Hertz the instrument will internally send 100 updates per second to the &#039;&#039;harmonic shift.&#039;&#039; Our amplitude is set to the maximum value and depending on the &amp;quot;harmonicserieshandler.shiftrange&amp;quot; this could give a smooth vibrato like sound or more of an experimental one with a wider range. If the modulation is too deep we can just adjust the amplitude of the LFO.&lt;br /&gt;
The &amp;quot;lfo&amp;quot;-&#039;&#039;plugin modules commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Sets the nickname of the LFO&lt;br /&gt;
|-&lt;br /&gt;
|enable&lt;br /&gt;
|en&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Disables / Enables the output of the &#039;&#039;target&#039;&#039; &#039;&#039;commands&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|target&lt;br /&gt;
|tg&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the command string to execute each update cycle, the string [lfoout] will be replaced with the current value&lt;br /&gt;
|-&lt;br /&gt;
|updaterate&lt;br /&gt;
|ur&lt;br /&gt;
|milliseconds&lt;br /&gt;
|Sets the frequency with which the &#039;&#039;target commands&#039;&#039; are executed. Limited by the global maximum as set in the plugin handler&lt;br /&gt;
|-&lt;br /&gt;
|waveform&lt;br /&gt;
|wf&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;sine|triangle|square|saw&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets the LFO waveform&lt;br /&gt;
|-&lt;br /&gt;
|frequency&lt;br /&gt;
|fq&lt;br /&gt;
|Hertz&lt;br /&gt;
|Sets the LFO frequency&lt;br /&gt;
|-&lt;br /&gt;
|amplitude&lt;br /&gt;
|amp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the LFO amplitude&lt;br /&gt;
|-&lt;br /&gt;
|delay&lt;br /&gt;
|dl&lt;br /&gt;
|0-65535 milliseconds&lt;br /&gt;
|Ramps up the amplitude of the output waveform from zero to full amplitude in the given time span&lt;br /&gt;
|-&lt;br /&gt;
|resetdelay&lt;br /&gt;
|rd&lt;br /&gt;
| -&lt;br /&gt;
|Resets the delay and starts the ramping of the waveform&lt;br /&gt;
|-&lt;br /&gt;
|resetwave&lt;br /&gt;
|rw&lt;br /&gt;
| -&lt;br /&gt;
|Resets the waveform from the start (sync)&lt;br /&gt;
|-&lt;br /&gt;
|bipolar&lt;br /&gt;
|bp&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets whether the waveform is bipolar (default) or positive only&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;ahdsr&amp;quot;-&#039;&#039;plugin module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;ahdsr&amp;quot;-&#039;&#039;plugin module&#039;&#039; works like a standard [[wikipedia:ADSR|ADSR]] with the addition of a &amp;quot;hold&amp;quot;-period in between the &amp;quot;attack&amp;quot; and &amp;quot;decay&amp;quot; phase. The FAR specific items are the same as outlined in the [[The &amp;quot;lfo&amp;quot;-plugin module|&amp;quot;lfo&amp;quot;-&#039;&#039;plugin module&#039;&#039;]]. The &#039;&#039;commands&#039;&#039; for the &amp;quot;ahdsr&amp;quot;-&#039;&#039;plugin module&#039;&#039; are&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long command&lt;br /&gt;
!Short command&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Sets the nickname of the AHDSR&lt;br /&gt;
|-&lt;br /&gt;
|enable&lt;br /&gt;
|en&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Disables / Enables the output of the &#039;&#039;target commands&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|target&lt;br /&gt;
|tg&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the command string to execute each update cycle, the string [lfoout] will be replaced with the current value&lt;br /&gt;
|-&lt;br /&gt;
|updaterate&lt;br /&gt;
|ur&lt;br /&gt;
|milliseconds&lt;br /&gt;
|Sets the frequency with which the &#039;&#039;target commands&#039;&#039; are executed. Limited by the global maximum as set in the plugin handler&lt;br /&gt;
|-&lt;br /&gt;
|gate&lt;br /&gt;
|gt&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Gate signal, [1] initiates the &#039;&#039;attack&#039;&#039; phase and if it reaches its maximum value, &#039;&#039;holds&#039;&#039; for the time given. It then continues through the &#039;&#039;decay&#039;&#039; down to the &#039;&#039;sustain&#039;&#039; point. A [0] initiates the &#039;&#039;release&#039;&#039; from whatever point the ADSR is at&lt;br /&gt;
|-&lt;br /&gt;
|attack&lt;br /&gt;
|at&lt;br /&gt;
|milliseconds&lt;br /&gt;
|Attack time in milliseconds&lt;br /&gt;
|-&lt;br /&gt;
|hold&lt;br /&gt;
|hd&lt;br /&gt;
|milliseconds&lt;br /&gt;
|Hold time in milliseconds&lt;br /&gt;
|-&lt;br /&gt;
|decay&lt;br /&gt;
|dc&lt;br /&gt;
|milliseconds&lt;br /&gt;
|Decay time in milliseconds&lt;br /&gt;
|-&lt;br /&gt;
|sustain&lt;br /&gt;
|su&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sustain point in amplitude units&lt;br /&gt;
|-&lt;br /&gt;
|release&lt;br /&gt;
|re&lt;br /&gt;
|milliseconds&lt;br /&gt;
|Release time in milliseconds&lt;br /&gt;
|-&lt;br /&gt;
|releasetarget&lt;br /&gt;
|rt&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|&#039;&#039;Commands&#039;&#039; to execute once the release has hit zero&lt;br /&gt;
|-&lt;br /&gt;
|amplitude&lt;br /&gt;
|amp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Output amplitude&lt;br /&gt;
|-&lt;br /&gt;
|invert&lt;br /&gt;
|inv&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Inverts the results and gives negative values&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Knaadmin</name></author>
	</entry>
	<entry>
		<id>http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_reference_V1.1&amp;diff=1687</id>
		<title>The Ekdahl FAR - Command reference V1.1</title>
		<link rel="alternate" type="text/html" href="http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_reference_V1.1&amp;diff=1687"/>
		<updated>2026-06-14T12:25:59Z</updated>

		<summary type="html">&lt;p&gt;Knaadmin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
The Ekdahl FAR V1.1 introduces the concept of &#039;&#039;modules&#039;&#039;. A &#039;&#039;module&#039;&#039; can contain any number of &#039;&#039;commands&#039;&#039; as well as other &#039;&#039;modules&#039;&#039;. Furthermore any number of &#039;&#039;modules&#039;&#039; of the same type can exist within a context, these are addressed using classic C-style array &#039;&#039;indexing&#039;&#039; with the help of brackets (&amp;quot;[ ]&amp;quot;). Extending on the classic usage, multiple &#039;&#039;indexes&#039;&#039; can be addressed simultaneously by either comma-separating the objects (&amp;quot;[0,3,4]&amp;quot;) and using &#039;&#039;ranges&#039;&#039; (&amp;quot;[3-6]&amp;quot;). &#039;&#039;Modules&#039;&#039; can be either &#039;&#039;internal&#039;&#039; or &#039;&#039;external&#039;&#039;, meaning that they may all physically exist within a single hardware object, or they can be be remote-controlled devices. From a user perspective this however makes no difference as they will appear the same.&lt;br /&gt;
&lt;br /&gt;
While all &#039;&#039;modules&#039;&#039; have their own set of &#039;&#039;commands&#039;&#039;, there are certain &#039;&#039;commands&#039;&#039; that all &#039;&#039;modules&#039;&#039; &amp;lt;u&amp;gt;must&amp;lt;/u&amp;gt; implement and can thus be accessed anywhere within the &#039;&#039;module hierarchy.&#039;&#039; There are also &#039;&#039;base commands&#039;&#039; that always exist within any given FAR ecosystem as well as product-specific &#039;&#039;base commands&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Ubiquitous commands ==&lt;br /&gt;
The &#039;&#039;module commands&#039;&#039; that are &amp;lt;u&amp;gt;required&amp;lt;/u&amp;gt; to be implemented in &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; &#039;&#039;modules&#039;&#039; and that can thus be accessed from anywhere are&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|list&lt;br /&gt;
|ls&lt;br /&gt;
|hidden/h:modules/m:commands/c:instances/i:instancecounts/ic:recursive/r&lt;br /&gt;
|Lists all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039; under the current module depending on the parameters given; &#039;hidden&#039; includes normally hidden &#039;&#039;commands&#039;&#039;, &#039;modules&#039; includes any &#039;&#039;submodules&#039;&#039;, &#039;commands&#039; shows &#039;&#039;commands&#039;&#039;, &#039;instances&#039; shows data for each individual instance of a &#039;&#039;module&#039;&#039;, &#039;instancecounts&#039; includes number of instances of each &#039;&#039;module&#039;&#039;, &#039;recursive&#039; lists all child &#039;&#039;modules&#039;&#039; / &#039;&#039;commands&#039;&#039;. No parameters defaults to showing all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039; recursively with instance counts. It doesn&#039;t show per-instance data or hidden commands.&lt;br /&gt;
|-&lt;br /&gt;
|help&lt;br /&gt;
|help&lt;br /&gt;
|recursive/r&lt;br /&gt;
|Shows a brief explanation of all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039;, shows the help for all &#039;&#039;submodules&#039;&#039; as well if &#039;recursive&#039;&lt;br /&gt;
|-&lt;br /&gt;
|dumpdata&lt;br /&gt;
|dump&lt;br /&gt;
|recursive/r&lt;br /&gt;
|Dumps all data saved for the current &#039;&#039;module&#039;&#039;, will list the data of all &#039;&#039;submodules&#039;&#039; as well if &#039;recursive&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Base commands ==&lt;br /&gt;
B&#039;&#039;ase commands&#039;&#039; are &#039;&#039;commands&#039;&#039; that always exist at the root in any implementation of the Ekdahl FAR.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|version&lt;br /&gt;
|ver&lt;br /&gt;
| -&lt;br /&gt;
|Gets the current firmware version&lt;br /&gt;
|-&lt;br /&gt;
|debugprint&lt;br /&gt;
|dp&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;command|usb|hardware|undefined|priority|error|inforequest|expressionparser|debug:1|0&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Turns on or off serial feedback for the given item&lt;br /&gt;
|-&lt;br /&gt;
|requestinfo&lt;br /&gt;
|rqi&lt;br /&gt;
|command&lt;br /&gt;
|Retrives any data saved for a &#039;&#039;command&#039;&#039;, if applicable&lt;br /&gt;
|-&lt;br /&gt;
|saveallparameters&lt;br /&gt;
|sap&lt;br /&gt;
| -&lt;br /&gt;
|Saves all avaliable parameters&lt;br /&gt;
|-&lt;br /&gt;
|loadallparameters&lt;br /&gt;
|lap&lt;br /&gt;
| -&lt;br /&gt;
|Loads all avaliable parameters&lt;br /&gt;
|-&lt;br /&gt;
|resetallparameters&lt;br /&gt;
|rap&lt;br /&gt;
| -&lt;br /&gt;
|Resets all saved parameters&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|rst&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;1|0&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Resets the Ekdahl FAR, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|nick&lt;br /&gt;
|nick&lt;br /&gt;
|name&lt;br /&gt;
|Sets the nickname of this unit&lt;br /&gt;
|-&lt;br /&gt;
|nooperation&lt;br /&gt;
|nop&lt;br /&gt;
| -&lt;br /&gt;
|Do absolutely, positively, nothing. Useful for testing and interfacing with computers, it&#039;s a good way to know that the unit is alive and responding since a &amp;quot;nop&amp;quot; is being returned as a response upon reception.&lt;br /&gt;
|-&lt;br /&gt;
|uservariable&lt;br /&gt;
|uv&lt;br /&gt;
|variable(0-9):value&lt;br /&gt;
|Set user variable 0-9 to &#039;value&#039;&lt;br /&gt;
|-&lt;br /&gt;
|expressionparserevaluate&lt;br /&gt;
|epev&lt;br /&gt;
|expression&lt;br /&gt;
|Evaluates an arithmetric expression and sends back the output, all variables and functions that can be used in any &#039;&#039;command string&#039;&#039; can also be used here. Useful for testing expressions.&lt;br /&gt;
|-&lt;br /&gt;
|ifequal&lt;br /&gt;
|ife&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] EQUALS [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring].&lt;br /&gt;
|-&lt;br /&gt;
|ifgreater&lt;br /&gt;
|ifg&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] &amp;gt; [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring]&lt;br /&gt;
|-&lt;br /&gt;
|ifless&lt;br /&gt;
|ifl&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] &amp;lt; [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring]&lt;br /&gt;
|-&lt;br /&gt;
|freeram&lt;br /&gt;
|ram&lt;br /&gt;
| -&lt;br /&gt;
|Shows free RAM memory&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The base also contains the following &#039;&#039;modules:&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|pluginhandler&lt;br /&gt;
|ph&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The Ekdahl FAR stand alone single string unit ==&lt;br /&gt;
The Ekdahl FAR stand-alone single string unit offers these &#039;&#039;commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|calibrateall&lt;br /&gt;
|ca&lt;br /&gt;
| -&lt;br /&gt;
|Performs all calibration routines on the selected bow, see below for routines performed&lt;br /&gt;
|-&lt;br /&gt;
|calibratebowspeed&lt;br /&gt;
|cbs&lt;br /&gt;
| -&lt;br /&gt;
|Finds the minimum and maximum bow speed of the selected bow&lt;br /&gt;
|-&lt;br /&gt;
|calibratebowpressure&lt;br /&gt;
|cbp&lt;br /&gt;
| -&lt;br /&gt;
|Finds the minimum and maximum bow pressure of the selected bow&lt;br /&gt;
|-&lt;br /&gt;
|calibratemute&lt;br /&gt;
|cmu&lt;br /&gt;
| -&lt;br /&gt;
|Calibrate mute settings&lt;br /&gt;
|-&lt;br /&gt;
|pickupstringfrequency&lt;br /&gt;
|psf&lt;br /&gt;
| -&lt;br /&gt;
|Returns the fundamental tone calculated from the current audio signal if apliccable&lt;br /&gt;
|-&lt;br /&gt;
|pickupaudiopeak&lt;br /&gt;
|pap&lt;br /&gt;
| -&lt;br /&gt;
|Returns the peak amplitude of the current audio signal&lt;br /&gt;
|-&lt;br /&gt;
|pickupaudiorms&lt;br /&gt;
|par&lt;br /&gt;
| -&lt;br /&gt;
|Returns the RMS amplitude of the current audio signal&lt;br /&gt;
|}&lt;br /&gt;
The Ekdahl FAR also contains the following &#039;&#039;modules&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|bowingwheel&lt;br /&gt;
|bw&lt;br /&gt;
|-&lt;br /&gt;
|mute&lt;br /&gt;
|mu&lt;br /&gt;
|-&lt;br /&gt;
|solenoid&lt;br /&gt;
|so&lt;br /&gt;
|-&lt;br /&gt;
|controlbox&lt;br /&gt;
|cb&lt;br /&gt;
|-&lt;br /&gt;
|midiconfigurationhandler&lt;br /&gt;
|mcf&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;Bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; contains everything needed to interface with a single &#039;&#039;bowing wheel&#039;&#039;. Each &#039;&#039;bowing wheel&#039;&#039; has its own harmonic series, pressure actuators and direct hardware interface. It contains the following &#039;&#039;commands&#039;&#039;.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|speedmode&lt;br /&gt;
|sm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Bow motor speed mode, 0 = Automatic and 1 = Manual. Automatic mode means that the bowing wheel will automatically turn off after the &#039;&#039;motor timeout&#039;&#039; has been reached after being put into rest mode&lt;br /&gt;
|-&lt;br /&gt;
|motortimeout&lt;br /&gt;
|mt&lt;br /&gt;
|ms&lt;br /&gt;
|Bow motor shutdown timeout after bow having been put into the rest position&lt;br /&gt;
|-&lt;br /&gt;
|pidenable&lt;br /&gt;
|pe&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets the bow PID on/off&lt;br /&gt;
|-&lt;br /&gt;
|motorfaultcommands&lt;br /&gt;
|mfc&lt;br /&gt;
|commands&lt;br /&gt;
|Commands to execute when a motor fault is tripped - !WARNING! Can ruin your instrument if changed&lt;br /&gt;
|-&lt;br /&gt;
|motoroverpowercommands&lt;br /&gt;
|moc&lt;br /&gt;
|commands&lt;br /&gt;
|Commands to execute when motor is over the power limit - !WARNING! Can ruin your instrument if changed&lt;br /&gt;
|}&lt;br /&gt;
The &#039;&#039;modules&#039;&#039; in the &amp;quot;Bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; are as follows&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|bowpressure&lt;br /&gt;
|bp&lt;br /&gt;
|-&lt;br /&gt;
|dcmotor&lt;br /&gt;
|dcm&lt;br /&gt;
|-&lt;br /&gt;
|pid&lt;br /&gt;
|pid&lt;br /&gt;
|-&lt;br /&gt;
|harmonicserieshandler&lt;br /&gt;
|hsh&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; handles the &#039;&#039;pressure&#039;&#039; of the &#039;&#039;bowing wheel&#039;&#039; against the string. The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|baseline&lt;br /&gt;
|ba&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure baseline, modulation is added to this point upward. Typically this is set with a knob on the &#039;&#039;control box&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|modifier&lt;br /&gt;
|mo&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure modulation, added to the baseline&lt;br /&gt;
|-&lt;br /&gt;
|rest&lt;br /&gt;
|rs&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the bow pressure in the &#039;&#039;rest&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|engage&lt;br /&gt;
|en&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the bow pressure in the &#039;&#039;engage&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|stallpressure&lt;br /&gt;
|sp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure stall/maximum position, this parameter is set using &#039;&#039;hardware positioning&#039;&#039; and is used as the absolute maximum for baseline and modifier combiner&lt;br /&gt;
|-&lt;br /&gt;
|engagepressure&lt;br /&gt;
|ep&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure touch/minimum position, this parameter is set using &#039;&#039;hardware position&#039;&#039; and is used as the starting point for when both the baseline and modifier is set to zero&lt;br /&gt;
|-&lt;br /&gt;
|restpressure&lt;br /&gt;
|rp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure rest position, this parameter is set using &#039;&#039;hardware positioning&#039;&#039; and is typically set to a point just below the string where it does not touch at all. The purpose of this is because while the actual hardware might be able to make the bow go even lower, that position might be far enough from the string that once &#039;&#039;engaged&#039;&#039; the bow may have so far to travel that there is perceptible &#039;&#039;latency&#039;&#039;.&lt;br /&gt;
|-&lt;br /&gt;
|engagespeed&lt;br /&gt;
|es&lt;br /&gt;
|1- ~100&lt;br /&gt;
|Bow pressure movement speed when engaging or disengaging&lt;br /&gt;
|-&lt;br /&gt;
|modulationspeed&lt;br /&gt;
|ms&lt;br /&gt;
|0.1 - 10&lt;br /&gt;
|Bow pressure movement speed while engaged&lt;br /&gt;
|-&lt;br /&gt;
|hold&lt;br /&gt;
|hd&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets bow hold (infinite sustain) on/off, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|home&lt;br /&gt;
|hm&lt;br /&gt;
| -&lt;br /&gt;
|Homing bow, used at startup and in case of the bow loosing position&lt;br /&gt;
|-&lt;br /&gt;
|tmcinfo&lt;br /&gt;
|tmi&lt;br /&gt;
| -&lt;br /&gt;
|Request statistical information from the TMC2209 stepper motor driver&lt;br /&gt;
|}&lt;br /&gt;
Note that the &amp;quot;stall&amp;quot;, &amp;quot;engage&amp;quot; and &amp;quot;rest&amp;quot;-pressure positions mention something called &#039;&#039;hardware position&#039;&#039;. This means the entire available movement of the &#039;&#039;bowing jack&#039;&#039;. Because the very bottom and top end of the movement might not be musically useful and may even harm the instrument, the &amp;quot;baseline&amp;quot; and &amp;quot;modifier&amp;quot; commands &#039;&#039;parameter&#039;&#039;s are scaled depending on these settings.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;engage&amp;quot; and &amp;quot;modulation&amp;quot;-speed settings sets how fast the stepper motor that drives the &#039;&#039;pressure&#039;&#039; moves depending on whether the &#039;&#039;bowing jack&#039;&#039; is set to &#039;&#039;engage&#039;&#039; or not. The idea here is that while wanting to be able to minimize &#039;&#039;latency&#039;&#039; by &#039;&#039;engaging&#039;&#039; and &#039;&#039;disengaging&#039;&#039; from the string as quickly as possible, dynamic changes in the &#039;&#039;pressure&#039;&#039; while playing benefits from much smoother movements as the &#039;&#039;bowing wheel&#039;&#039; takes some time to catch up to varying amounts of friction.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; contains one or more of the following &#039;&#039;modules&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|actuatorhandler&lt;br /&gt;
|ah&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;actuatorhandler&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The concept of &amp;quot;actuators&amp;quot; came up as it is possible to have &#039;&#039;bowing wheels&#039;&#039; of different sizes and wanting to be able to switch quickly in between them, perhaps during mid-performance. Because a differently sized wheel will require different values for the above mentioned &amp;quot;stall&amp;quot;, &amp;quot;engage&amp;quot; and &amp;quot;reset&amp;quot;-&#039;&#039;pressure&#039;&#039;, each &#039;&#039;actuator&#039;&#039; stores these values. Instead of having to manually change the previously mentioned values, simply selecting a new &#039;&#039;actuator&#039;&#039; will automatically load the values. The &amp;quot;actuatorhandler&amp;quot;-&#039;&#039;module&#039;&#039; is the handler of one or more &amp;quot;actuator&amp;quot;-&#039;&#039;modules&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;commands&#039;&#039; of the &amp;quot;acuatorhandler&amp;quot;-&#039;&#039;module&#039;&#039; are as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|add&lt;br /&gt;
|a&lt;br /&gt;
|(name):(rest:engage:stall)&lt;br /&gt;
|Add new actuator with the given name and parameters&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|actuatornumber&lt;br /&gt;
|Remove bow actuator [actuatornumber]&lt;br /&gt;
|-&lt;br /&gt;
|count&lt;br /&gt;
|c&lt;br /&gt;
| -&lt;br /&gt;
|Returns the amount of saved bow actuators&lt;br /&gt;
|}&lt;br /&gt;
The &amp;quot;actuatorhandler&amp;quot;-&#039;&#039;module&#039;&#039; contains one or more of&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|actuator&lt;br /&gt;
|ac&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;actuator&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;actuator&amp;quot;-&#039;&#039;module&#039;&#039; contains the following commands&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|[index]&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|Selects the given actuator&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Sets the actuator name&lt;br /&gt;
|-&lt;br /&gt;
|data&lt;br /&gt;
|da&lt;br /&gt;
|name:rest:engage:stall&lt;br /&gt;
|Sets the actuator name, rest, engage and stall &#039;&#039;pressure&#039;&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;dcmotor&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;dcmotor&amp;quot;-&#039;&#039;module&#039;&#039; handles the direct &amp;lt;u&amp;gt;raw&amp;lt;/u&amp;gt; control of the &#039;&#039;bowing motor&#039;&#039; and handles the reporting back of the current speed. It has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|run&lt;br /&gt;
|ru&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Turns the motor off/on&lt;br /&gt;
|-&lt;br /&gt;
|pwm&lt;br /&gt;
|pw&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor direct power in 16-bit PWM values, requires that the &#039;&#039;PID&#039;&#039; is turned off&lt;br /&gt;
|-&lt;br /&gt;
|voltage&lt;br /&gt;
|vo&lt;br /&gt;
|~2 - 10V&lt;br /&gt;
|Sets the voltage of the regulator powering the motor. Changes here can make the motor more responsive to certain frequencies but will also affect how well the &#039;&#039;PID&#039;&#039; works. !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|current&lt;br /&gt;
|cu&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor reported current use&lt;br /&gt;
|-&lt;br /&gt;
|currentlimit&lt;br /&gt;
|cl&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor current limit (A)- !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|powerlimit&lt;br /&gt;
|pl&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor power limit (W) - !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|frequency&lt;br /&gt;
|fq&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor reported frequency&lt;br /&gt;
|-&lt;br /&gt;
|emergencystop&lt;br /&gt;
|es&lt;br /&gt;
|ms (0-65535)&lt;br /&gt;
|Immediately stops the bowing motor and doesn&#039;t allow it to start again until the cool down period given in the first argument has lapsed (milliseconds)&lt;br /&gt;
|-&lt;br /&gt;
|minpwm&lt;br /&gt;
|ip&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor minimum PWM (for calibration)&lt;br /&gt;
|-&lt;br /&gt;
|maxpwm&lt;br /&gt;
|xp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor maximum PWM (for calibration)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;pidcontroller&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;pidcontroller&amp;quot;-&#039;&#039;module&#039;&#039; is responsible for keeping the &amp;quot;dcmotor&amp;quot;-&#039;&#039;module&#039;&#039; at a certain frequency (given in Hertz). It takes the output of the motor frequency measurement and feeds it a PWM value that tries to make the speed constant regardless of the friction that the motor is enduring. To learn more about PID Controllers please see this [[wikipedia:PID_controller|wikipedia article]]. The &#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|targetfrequency&lt;br /&gt;
|tf&lt;br /&gt;
|hertz&lt;br /&gt;
|Sets the PID target frequency&lt;br /&gt;
|-&lt;br /&gt;
|ki&lt;br /&gt;
|ki&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Ki parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|kp&lt;br /&gt;
|kp&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Kp parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|kd&lt;br /&gt;
|kd&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Kd parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|integratorerror&lt;br /&gt;
|ie&lt;br /&gt;
|float&lt;br /&gt;
|Sets the lower threshold of error values for the PID integrator to ignore&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|re&lt;br /&gt;
| -&lt;br /&gt;
|Resets the PID integrator and derivative&lt;br /&gt;
|-&lt;br /&gt;
|maxerror&lt;br /&gt;
|xe&lt;br /&gt;
|float&lt;br /&gt;
|Maximum error to correct in each PID loop, essentially sets acceleration&lt;br /&gt;
|-&lt;br /&gt;
|peakerror&lt;br /&gt;
|pe&lt;br /&gt;
|float&lt;br /&gt;
|Get latest PID peak error&lt;br /&gt;
|-&lt;br /&gt;
|motorspeedmax&lt;br /&gt;
|msx&lt;br /&gt;
|Hertz&lt;br /&gt;
|Bow motor maximum speed limit&lt;br /&gt;
|-&lt;br /&gt;
|motorspeedmin&lt;br /&gt;
|msi&lt;br /&gt;
|Hertz&lt;br /&gt;
|Bow motor minimum speed limit&lt;br /&gt;
|-&lt;br /&gt;
|measuretimetotarget&lt;br /&gt;
|mtt&lt;br /&gt;
|Hertz&lt;br /&gt;
|Measure the time it takes to change from the current frequency to the target frequency, for testing purposes&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; is responsible for sending frequency data to the &amp;quot;pid&amp;quot;-&#039;&#039;module&#039;&#039;. It handles calculating the correct frequency of the &#039;&#039;bowing wheel&#039;&#039; according to the selected &#039;&#039;harmonic&#039;&#039; and &#039;&#039;harmonic shift&#039;&#039; per the currently selected &#039;&#039;harmonic series&#039;&#039;. The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|fundamental&lt;br /&gt;
|fu&lt;br /&gt;
|Hertz&lt;br /&gt;
|The fundamental frequency of the string, all harmonics are calculated from this number&lt;br /&gt;
|-&lt;br /&gt;
|harmonic&lt;br /&gt;
|h&lt;br /&gt;
|int&lt;br /&gt;
|Selects the harmonic number to set the &#039;&#039;bowing wheel&#039;&#039; to. A ratio is taken from the given &#039;&#039;harmonic&#039;&#039; in the current &#039;&#039;harmonic series&#039;&#039;, the ratio is then multiplied by the &#039;&#039;fundamental frequency&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|harmonicadd&lt;br /&gt;
|ha&lt;br /&gt;
|int&lt;br /&gt;
|This number is added to the current harmonic&lt;br /&gt;
|-&lt;br /&gt;
|harmonicbase&lt;br /&gt;
|hb&lt;br /&gt;
|int&lt;br /&gt;
|Same as harmonic but where the harmonic number is based on a MIDI note given by basenote&lt;br /&gt;
|-&lt;br /&gt;
|basenote&lt;br /&gt;
|bn&lt;br /&gt;
|0-127&lt;br /&gt;
|Sets the MIDI base note of the &#039;&#039;bowing wheel&#039;&#039;, used in conjunction with &amp;quot;harmonicbase&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|shift&lt;br /&gt;
|sh&lt;br /&gt;
| -32767 - 32767&lt;br /&gt;
|Sets shift from the currently playing harmonic where 32767 equals the entire harmonic shift range shifted up&lt;br /&gt;
|-&lt;br /&gt;
|shiftrange&lt;br /&gt;
|sr&lt;br /&gt;
|0-36&lt;br /&gt;
|Set the number of harmonic numbers that constitutes an entire harmonic shift&lt;br /&gt;
|-&lt;br /&gt;
|shift5&lt;br /&gt;
|sh5&lt;br /&gt;
| -32767 - 32767&lt;br /&gt;
|Sets the shift from the currently playing harmonic over 5 octaves where 32767 equals 5 octaves shift up from the fundamental&lt;br /&gt;
|-&lt;br /&gt;
|add&lt;br /&gt;
|a&lt;br /&gt;
|(name):(ratios)&lt;br /&gt;
|Add a new series with the given name and parameters&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|series&lt;br /&gt;
|Remove the series given and shift any series accordingly. Cannot remove all series&lt;br /&gt;
|-&lt;br /&gt;
|count&lt;br /&gt;
|c&lt;br /&gt;
| -&lt;br /&gt;
|Returns the number of harmonic series in the list and their IDs&lt;br /&gt;
|}&lt;br /&gt;
The &amp;quot;harmonicserieshandler&amp;quot;-module contains at the very least ONE harmonic series, by default it contains two: one for equal temperament and one for just intonation. The current series can be selected by simply indexing the &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; without a &#039;&#039;command&#039;&#039;, e.g. &amp;quot;harmonicserieshandler.harmonicseries[1]&amp;quot;. To be consistent, these are the &#039;&#039;modules&#039;&#039; in the &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|harmonicseries&lt;br /&gt;
|hs&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; contains any number of &#039;&#039;ratios&#039;&#039; that comprises a scale, ratios are given in a standard format where a ratio of &amp;quot;1&amp;quot; is equal to the fundamental, &amp;quot;2&amp;quot; would be one octave up etc. A standard &#039;&#039;harmonic series&#039;&#039; contains 12 ratios following a just intonation scheme. The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; will automatically adapt to the currently selected &#039;&#039;harmonic series&#039;&#039; length, whether it&#039;s a standard 12-tone scale, some kinda 3-tone scale or a full on bananas 53-tone scale. The &#039;&#039;commands&#039;&#039; of the &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; is as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|[index]&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
|Sets the currently selected &#039;&#039;harmonic Series&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Sets the name of the &#039;&#039;harmonic series&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|data&lt;br /&gt;
|da&lt;br /&gt;
|name:ratios&lt;br /&gt;
|Gets / sets all data for the &#039;&#039;harmonic series&#039;&#039; in the given slot with an arbitrary &#039;&#039;name&#039;&#039; as the first &#039;&#039;parameter&#039;&#039;. The length of the series is simply set to the amount of ratios given&lt;br /&gt;
|-&lt;br /&gt;
|ratio&lt;br /&gt;
|r&lt;br /&gt;
|harmonic:ratio&lt;br /&gt;
|Sets the ratio of the given harmonic in current &#039;&#039;harmonic series&#039;&#039;, will increase the list size if needed to address the harmonic&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|harmonic&lt;br /&gt;
|Remove the harmonic ratio given in the current series and shift any ratios accordingly. Cannot remove all ratios&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;mute&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;mute&amp;quot;-&#039;&#039;module&#039;&#039; works very similarly to the &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; in that it controls a stepper motor with some software limits in place in order to press the mute against the string. The &#039;&#039;commands&#039;&#039; are as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|setposition&lt;br /&gt;
|sp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set mute position&lt;br /&gt;
|-&lt;br /&gt;
|fullmute&lt;br /&gt;
|fm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the mute in &#039;&#039;full mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|halfmute&lt;br /&gt;
|hm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the mute in &#039;&#039;half mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|rest&lt;br /&gt;
|rs&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Put the mute in the &#039;&#039;rest&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|savefull&lt;br /&gt;
|sf&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Save the current mute position as the &#039;&#039;full mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|savehalf&lt;br /&gt;
|sh&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Save the current mute position as the &#039;&#039;half mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|saverest&lt;br /&gt;
|sr&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Save the current mute position as the &#039;&#039;rest&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|fullmuteposition&lt;br /&gt;
|fmp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;full mute&#039;&#039; position according to the &#039;&#039;hardware position&#039;&#039; given&lt;br /&gt;
|-&lt;br /&gt;
|halfmuteposition&lt;br /&gt;
|hmp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;half mute&#039;&#039; position according to the &#039;&#039;hardware position&#039;&#039; given&lt;br /&gt;
|-&lt;br /&gt;
|restposition&lt;br /&gt;
|rp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;rest&#039;&#039; position according to the &#039;&#039;hardware position&#039;&#039; given&lt;br /&gt;
|-&lt;br /&gt;
|sustain&lt;br /&gt;
|su&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets the sustain off/on, this will keep the mute in the &#039;&#039;rest&#039;&#039; position even if a &amp;quot;fullmute&amp;quot;-&#039;&#039;command&#039;&#039; is given, lasts until &amp;quot;sustain&amp;quot; is set to &amp;quot;0&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
|backoff&lt;br /&gt;
|bo&lt;br /&gt;
|0-65535&lt;br /&gt;
|Setting the time that the mute stays in the mutefullmute position before automatically going into rest, set in mS. A value of &amp;quot;0&amp;quot; disables backoff. This is used because if the mute is not backing off until something is attempted to be played, the backing-off time will either introduce &#039;&#039;latency&#039;&#039; or the string will be initially partially muted&lt;br /&gt;
|-&lt;br /&gt;
|home&lt;br /&gt;
|hm&lt;br /&gt;
| -&lt;br /&gt;
|Home mute, used during initialization and if the mute were to loose position&lt;br /&gt;
|-&lt;br /&gt;
|hardwareposition&lt;br /&gt;
|hwp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;hardware position&#039;&#039; of the mute instead of scaling it over the &#039;&#039;full mute&#039;&#039; and &#039;&#039;rest&#039;&#039; positions. Mainly used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|completetask&lt;br /&gt;
|cpt&lt;br /&gt;
| -&lt;br /&gt;
|Requests a callback when the current operation is finished. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|autocorrect&lt;br /&gt;
|ac&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Enables auto correct positioning that uses the homing sensor to correct positioning on the fly. EXPERIMENTAL&lt;br /&gt;
|-&lt;br /&gt;
|homingsensed&lt;br /&gt;
|hms&lt;br /&gt;
| -&lt;br /&gt;
|Requests whether the homing sensor is currently active or not. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|movedirection&lt;br /&gt;
|md&lt;br /&gt;
| -&lt;br /&gt;
|Requests the current direction of movement (0 Forward, 1 Reverse). Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|currentstep&lt;br /&gt;
|cs&lt;br /&gt;
| -&lt;br /&gt;
|Requests the current step. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|homingpoint&lt;br /&gt;
|hmp&lt;br /&gt;
|edgedirection&lt;br /&gt;
|Requests the given homing point. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|homingstage&lt;br /&gt;
|hms&lt;br /&gt;
| -&lt;br /&gt;
|Requests the current homing stage (UNHOMED, HOMED, FIRSTHOMINGRISING, SECONDHOMINGFALLING, SECONDHOMINGRISING, FIRSTHOMINGFALLING, MOVEPASTHOMESWITCH, MOVETOHOMESWITCH, GOTOOFFSET). Only used internally by other &#039;&#039;modules.&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|tmcinfo&lt;br /&gt;
|tmi&lt;br /&gt;
| -&lt;br /&gt;
|Request statistical information from the TMC2209 stepper motor driver&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;solenoid&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;solenoid&amp;quot;-&#039;&#039;module&#039;&#039; currently controls the &#039;&#039;hammer&#039;&#039; of the Ekdahl FAR. Due to the fact that the very same &#039;&#039;module&#039;&#039; could be used for anything that uses a striking &#039;&#039;solenoid&#039;&#039; it was named as such. It has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|engage&lt;br /&gt;
|en&lt;br /&gt;
|0-65535&lt;br /&gt;
|Engages the solenoid using the first parameter as the force&lt;br /&gt;
|-&lt;br /&gt;
|rest&lt;br /&gt;
|rs&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Forces the solenoid to its rest position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|maxforce&lt;br /&gt;
|xf&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set solenoid maximum usable force&lt;br /&gt;
|-&lt;br /&gt;
|minforce&lt;br /&gt;
|if&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set solenoid minimum usable force&lt;br /&gt;
|-&lt;br /&gt;
|forcemultiplier&lt;br /&gt;
|fm&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set solenoid force multiplier, useful for scaling of all incoming &amp;quot;engage&amp;quot;-&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|engageduration&lt;br /&gt;
|ed&lt;br /&gt;
|uS&lt;br /&gt;
|Sets the duration of the solenoid hit in uS, if a value of 0 is set the solenoid will not disengage until a rest command has been given. WARNING!! HAVING THE SOLENOID ON FOR A SPAN OF SECONDS COULD DESTROY THE CIRCUITRY!!&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;controlbox&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;controlbox&amp;quot;-&#039;&#039;module&#039;&#039; communicates with an external &#039;&#039;control box&#039;&#039; and will issue associated &#039;&#039;commands&#039;&#039; whenever new values are read on the ADC-converters. It handles averaging and does some noise-cancellation functions on the values as well. The &#039;&#039;commands&#039;&#039; are:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|harmonic&lt;br /&gt;
|har&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the harmonic knob or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|harmonicshift&lt;br /&gt;
|has&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the harmonic shift modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|finetune&lt;br /&gt;
|fin&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the fine tune knob changes&lt;br /&gt;
|-&lt;br /&gt;
|pressure&lt;br /&gt;
|pre&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the pressure knob or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|mute&lt;br /&gt;
|mut&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the mute knob or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|hammerscale&lt;br /&gt;
|hms&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the hammer scale knob changes&lt;br /&gt;
|-&lt;br /&gt;
|gate&lt;br /&gt;
|gt&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the gate switch or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|hammertrig&lt;br /&gt;
|hmt&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the hammer trigger modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|controldefaults&lt;br /&gt;
|cde&lt;br /&gt;
| -&lt;br /&gt;
|Reverts all ADC command strings to default values&lt;br /&gt;
|-&lt;br /&gt;
|datareturn&lt;br /&gt;
|dr&lt;br /&gt;
|channel:value&lt;br /&gt;
|Sent when a new value is presented on one of the ADC channels, cannot be invoked. Triggers the commands associated with the channel&lt;br /&gt;
|-&lt;br /&gt;
|adcsetting&lt;br /&gt;
|adcs&lt;br /&gt;
|channel : averages : interrupterrorthreshold : continuouserrorthreshold : continuoustimeout&lt;br /&gt;
|Sets ADC settings for a given channel. Averages are the number of samples to average, interruptthreshold is how much the value must change in order to issue a new value change event. continuousthreshold is how much the value must change when a previous change has already been recorded within the timespan of continuoustimeout&lt;br /&gt;
|-&lt;br /&gt;
|testadclatency&lt;br /&gt;
|tal&lt;br /&gt;
|0-65535&lt;br /&gt;
|Start a ADC latency test&lt;br /&gt;
|-&lt;br /&gt;
|testadclatencyreturn&lt;br /&gt;
|talr&lt;br /&gt;
| -&lt;br /&gt;
|Return from latency test&lt;br /&gt;
|-&lt;br /&gt;
|testadcminmax&lt;br /&gt;
|tix&lt;br /&gt;
|channel&lt;br /&gt;
|Test min/max value for a given channel and resets the counter&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;midiconfigurationhandler&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;midiconfigurationhandler&amp;quot;-&#039;&#039;module&#039;&#039; handles a number of &amp;quot;midiconfiguration&amp;quot;-&#039;&#039;modules&#039;&#039;. It has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|allnotesoff&lt;br /&gt;
|ano&lt;br /&gt;
| -&lt;br /&gt;
|Clears the entire buffer of MIDI notes held&lt;br /&gt;
|-&lt;br /&gt;
|add&lt;br /&gt;
|a&lt;br /&gt;
|name&lt;br /&gt;
|Adds a new MIDI configuration with the given name&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|int&lt;br /&gt;
|Remove the specified MIDI configuration&lt;br /&gt;
|-&lt;br /&gt;
|count&lt;br /&gt;
|c&lt;br /&gt;
| -&lt;br /&gt;
|Returns the number of MIDI configurations&lt;br /&gt;
|}&lt;br /&gt;
It contains one or more of the following&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|midiconfiguration&lt;br /&gt;
|mc&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;midiconfiguration&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
A &amp;quot;midiconfiguration&amp;quot;-&#039;&#039;module&#039;&#039; handles the reception of &#039;&#039;MIDI messages&#039;&#039; and will output the associated &#039;&#039;commands&#039;&#039; to the instrument internally. The commands are as follows&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|[index]&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
|Sets the currently selected MIDI configuration&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Set the name of the MIDI configuration&lt;br /&gt;
|-&lt;br /&gt;
|noteon&lt;br /&gt;
|non&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Note On event&lt;br /&gt;
|-&lt;br /&gt;
|noteoff&lt;br /&gt;
|nof&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Note Off event&lt;br /&gt;
|-&lt;br /&gt;
|polyaftertouch&lt;br /&gt;
|pat&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Polyphonic after touch event&lt;br /&gt;
|-&lt;br /&gt;
|channelaftertouch&lt;br /&gt;
|cat&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Channel after touch event&lt;br /&gt;
|-&lt;br /&gt;
|pitchbend&lt;br /&gt;
|pb&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Pitch bend event&lt;br /&gt;
|-&lt;br /&gt;
|programchange&lt;br /&gt;
|pc&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Program change event&lt;br /&gt;
|-&lt;br /&gt;
|continuouscontrollerdata&lt;br /&gt;
|ccd&lt;br /&gt;
|controllernuber:&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Continuous controller event with the given [&#039;&#039;controllernumber&#039;&#039;]&lt;br /&gt;
|-&lt;br /&gt;
|removecc&lt;br /&gt;
|rmc&lt;br /&gt;
|controllernuber&lt;br /&gt;
|Removes the entry associated with the MIDI continuous controller even &#039;&#039;controllernumber&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|defaults&lt;br /&gt;
|d&lt;br /&gt;
| -&lt;br /&gt;
|Reverts the current configuration to default &#039;&#039;commands&#039;&#039;, values and CCs&lt;br /&gt;
|-&lt;br /&gt;
|receivechannel&lt;br /&gt;
|rc&lt;br /&gt;
|channel&lt;br /&gt;
|Sets the MIDI receive channel of the current configuration. 1-16 sets specific channel, any other value for OMNI&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;pluginhandler&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The Ekdahl FAR allows for &#039;&#039;plugins&#039;&#039;. These are &#039;&#039;modules&#039;&#039; that can trigger certain &#039;&#039;command strings&#039;&#039; to be executed either periodically or triggered by an incoming &#039;&#039;command&#039;&#039;. Further explanation of the given &#039;&#039;plugins&#039;&#039; is given below. The various &#039;&#039;plugins&#039;&#039; are handled by the &amp;quot;pluginhandler&amp;quot;-&#039;&#039;module&#039;&#039;, the different &#039;&#039;plugin modules&#039;&#039; are identified by their own unique &#039;&#039;ID&#039;&#039;. The &amp;quot;pluginhandler&amp;quot;-&#039;&#039;module&#039;&#039; it has the following &#039;&#039;commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|add&lt;br /&gt;
|a&lt;br /&gt;
|pluginid&lt;br /&gt;
|Add plugin with the given ID&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|pluginid:index&lt;br /&gt;
|Remove plugin with the given ID and index&lt;br /&gt;
|-&lt;br /&gt;
|count&lt;br /&gt;
|c&lt;br /&gt;
|(pluginid)&lt;br /&gt;
|Return the number of plugins of the given type, if none is given it returns all plugins&lt;br /&gt;
|}&lt;br /&gt;
The number of available &#039;&#039;plugins&#039;&#039; will differ from time to time as the &#039;&#039;plugin system&#039;&#039; has been purposefully designed to allow for anyone to write and add their own &#039;&#039;plugins&#039;&#039;. As of the current writing (2026-06-14) the number of &amp;lt;u&amp;gt;possible&amp;lt;/u&amp;gt; &#039;&#039;plugin modules&#039;&#039; that &amp;lt;u&amp;gt;can&amp;lt;/u&amp;gt; exist under the &amp;quot;pluginhandler&amp;quot;-&#039;&#039;module&#039;&#039; are&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|lfo&lt;br /&gt;
|lfo&lt;br /&gt;
|-&lt;br /&gt;
|ahdsr&lt;br /&gt;
|ahdsr&lt;br /&gt;
|-&lt;br /&gt;
|numbermap&lt;br /&gt;
|map&lt;br /&gt;
|-&lt;br /&gt;
|multiple&lt;br /&gt;
|mlt&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;lfo&amp;quot;-&#039;&#039;plugin module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;lfo&amp;quot;-&#039;&#039;plugin module&#039;&#039; works like regular [[wikipedia:Low-frequency_oscillation|low frequency oscillator]] in that it generates a given &#039;&#039;waveform&#039;&#039; with a given &#039;&#039;frequency&#039;&#039; at a certain &#039;&#039;amplitude&#039;&#039;. In the Ekdahl FAR the distinguishing factors are that besides the common &#039;&#039;frequency, amplitude&#039;&#039; and &#039;&#039;waveform&#039;&#039; parameters, it also requires the use of a &#039;&#039;update rate&#039;&#039; and &#039;&#039;target&#039;&#039; parameter. The &#039;&#039;update rate&#039;&#039; sets how often the current position of the LFO is sampled (aka how often it peeks in on where the LFO is in its waveform transition at the moment), and each time that happens, the &#039;&#039;target commands&#039;&#039; are outputted to the instrument.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example:&#039;&#039;&#039;&lt;br /&gt;
 Lets set the &#039;&#039;waveform&#039;&#039; to &amp;quot;triangle&amp;quot;, the &#039;&#039;amplitude&#039;&#039; to 65535 (max), the &#039;&#039;frequency&#039;&#039; to 1Hz (1 full waveform per second), the &#039;&#039;update rate&#039;&#039; to 10mS and the &#039;&#039;target&#039;&#039; to &amp;quot;bowingwheel.harmonicserieshandler.shift:lfoout&amp;quot;.&lt;br /&gt;
 &lt;br /&gt;
 The output of the LFO is always given in the variable &amp;quot;lfoout&amp;quot;, our &#039;&#039;target&#039;&#039; is set to &amp;quot;bowingwheel.harmonicserieshandler.shift&amp;quot; which controls the &#039;&#039;harmonic shift&#039;&#039; (pitchbend basically) of the &#039;&#039;bowing wheel&#039;&#039;.&lt;br /&gt;
 &lt;br /&gt;
 Since our update rate is set to every 10 milliseconds and our frequency is 1 Hertz the instrument will internally send 100 updates per second to the &#039;&#039;harmonic shift.&#039;&#039; Our amplitude is set to the maximum value and depending on the &amp;quot;harmonicserieshandler.shiftrange&amp;quot; this could give a smooth vibrato like sound or more of an experimental one with a wider range. If the modulation is too deep we can just adjust the amplitude of the LFO.&lt;br /&gt;
The &amp;quot;lfo&amp;quot;-&#039;&#039;plugin modules commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Sets the nickname of the LFO&lt;br /&gt;
|-&lt;br /&gt;
|enable&lt;br /&gt;
|en&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Disables / Enables the output of the &#039;&#039;target&#039;&#039; &#039;&#039;commands&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|target&lt;br /&gt;
|tg&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the command string to execute each update cycle, the string [lfoout] will be replaced with the current value&lt;br /&gt;
|-&lt;br /&gt;
|updaterate&lt;br /&gt;
|ur&lt;br /&gt;
|milliseconds&lt;br /&gt;
|Sets the frequency with which the &#039;&#039;target commands&#039;&#039; are executed. Limited by the global maximum as set in the plugin handler&lt;br /&gt;
|-&lt;br /&gt;
|waveform&lt;br /&gt;
|wf&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;sine|triangle|square|saw&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets the LFO waveform&lt;br /&gt;
|-&lt;br /&gt;
|frequency&lt;br /&gt;
|fq&lt;br /&gt;
|Hertz&lt;br /&gt;
|Sets the LFO frequency&lt;br /&gt;
|-&lt;br /&gt;
|amplitude&lt;br /&gt;
|amp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the LFO amplitude&lt;br /&gt;
|-&lt;br /&gt;
|delay&lt;br /&gt;
|dl&lt;br /&gt;
|0-65535 milliseconds&lt;br /&gt;
|Ramps up the amplitude of the output waveform from zero to full amplitude in the given time span&lt;br /&gt;
|-&lt;br /&gt;
|resetdelay&lt;br /&gt;
|rd&lt;br /&gt;
| -&lt;br /&gt;
|Resets the delay and starts the ramping of the waveform&lt;br /&gt;
|-&lt;br /&gt;
|resetwave&lt;br /&gt;
|rw&lt;br /&gt;
| -&lt;br /&gt;
|Resets the waveform from the start (sync)&lt;br /&gt;
|-&lt;br /&gt;
|bipolar&lt;br /&gt;
|bp&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets whether the waveform is bipolar (default) or positive only&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Knaadmin</name></author>
	</entry>
	<entry>
		<id>http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_reference_V1.1&amp;diff=1686</id>
		<title>The Ekdahl FAR - Command reference V1.1</title>
		<link rel="alternate" type="text/html" href="http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_reference_V1.1&amp;diff=1686"/>
		<updated>2026-06-14T08:20:36Z</updated>

		<summary type="html">&lt;p&gt;Knaadmin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
The Ekdahl FAR V1.1 introduces the concept of &#039;&#039;modules&#039;&#039;. A &#039;&#039;module&#039;&#039; can contain any number of &#039;&#039;commands&#039;&#039; as well as other &#039;&#039;modules&#039;&#039;. Furthermore any number of &#039;&#039;modules&#039;&#039; of the same type can exist within a context, these are addressed using classic C-style array &#039;&#039;indexing&#039;&#039; with the help of brackets (&amp;quot;[ ]&amp;quot;). Extending on the classic usage, multiple &#039;&#039;indexes&#039;&#039; can be addressed simultaneously by either comma-separating the objects (&amp;quot;[0,3,4]&amp;quot;) and using &#039;&#039;ranges&#039;&#039; (&amp;quot;[3-6]&amp;quot;). &#039;&#039;Modules&#039;&#039; can be either &#039;&#039;internal&#039;&#039; or &#039;&#039;external&#039;&#039;, meaning that they may all physically exist within a single hardware object, or they can be be remote-controlled devices. From a user perspective this however makes no difference as they will appear the same.&lt;br /&gt;
&lt;br /&gt;
While all &#039;&#039;modules&#039;&#039; have their own set of &#039;&#039;commands&#039;&#039;, there are certain &#039;&#039;commands&#039;&#039; that all &#039;&#039;modules&#039;&#039; &amp;lt;u&amp;gt;must&amp;lt;/u&amp;gt; implement and can thus be accessed anywhere within the &#039;&#039;module hierarchy.&#039;&#039; There are also &#039;&#039;base commands&#039;&#039; that always exist within any given FAR ecosystem as well as product-specific &#039;&#039;base commands&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Ubiquitous commands ==&lt;br /&gt;
The &#039;&#039;module commands&#039;&#039; that are &amp;lt;u&amp;gt;required&amp;lt;/u&amp;gt; to be implemented in &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; &#039;&#039;modules&#039;&#039; and that can thus be accessed from anywhere are&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|list&lt;br /&gt;
|ls&lt;br /&gt;
|hidden/h:modules/m:commands/c:instances/i:instancecounts/ic:recursive/r&lt;br /&gt;
|Lists all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039; under the current module depending on the parameters given; &#039;hidden&#039; includes normally hidden &#039;&#039;commands&#039;&#039;, &#039;modules&#039; includes any &#039;&#039;submodules&#039;&#039;, &#039;commands&#039; shows &#039;&#039;commands&#039;&#039;, &#039;instances&#039; shows data for each individual instance of a &#039;&#039;module&#039;&#039;, &#039;instancecounts&#039; includes number of instances of each &#039;&#039;module&#039;&#039;, &#039;recursive&#039; lists all child &#039;&#039;modules&#039;&#039; / &#039;&#039;commands&#039;&#039;. No parameters defaults to showing all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039; recursively with instance counts. It doesn&#039;t show per-instance data or hidden commands.&lt;br /&gt;
|-&lt;br /&gt;
|help&lt;br /&gt;
|help&lt;br /&gt;
|recursive/r&lt;br /&gt;
|Shows a brief explanation of all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039;, shows the help for all &#039;&#039;submodules&#039;&#039; as well if &#039;recursive&#039;&lt;br /&gt;
|-&lt;br /&gt;
|dumpdata&lt;br /&gt;
|dump&lt;br /&gt;
|recursive/r&lt;br /&gt;
|Dumps all data saved for the current &#039;&#039;module&#039;&#039;, will list the data of all &#039;&#039;submodules&#039;&#039; as well if &#039;recursive&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Base commands ==&lt;br /&gt;
B&#039;&#039;ase commands&#039;&#039; are &#039;&#039;commands&#039;&#039; that always exist at the root in any implementation of the Ekdahl FAR.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|version&lt;br /&gt;
|ver&lt;br /&gt;
| -&lt;br /&gt;
|Gets the current firmware version&lt;br /&gt;
|-&lt;br /&gt;
|debugprint&lt;br /&gt;
|dp&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;command|usb|hardware|undefined|priority|error|inforequest|expressionparser|debug:1|0&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Turns on or off serial feedback for the given item&lt;br /&gt;
|-&lt;br /&gt;
|requestinfo&lt;br /&gt;
|rqi&lt;br /&gt;
|command&lt;br /&gt;
|Retrives any data saved for a &#039;&#039;command&#039;&#039;, if applicable&lt;br /&gt;
|-&lt;br /&gt;
|saveallparameters&lt;br /&gt;
|sap&lt;br /&gt;
| -&lt;br /&gt;
|Saves all avaliable parameters&lt;br /&gt;
|-&lt;br /&gt;
|loadallparameters&lt;br /&gt;
|lap&lt;br /&gt;
| -&lt;br /&gt;
|Loads all avaliable parameters&lt;br /&gt;
|-&lt;br /&gt;
|resetallparameters&lt;br /&gt;
|rap&lt;br /&gt;
| -&lt;br /&gt;
|Resets all saved parameters&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|rst&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;1|0&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Resets the Ekdahl FAR, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|nick&lt;br /&gt;
|nick&lt;br /&gt;
|name&lt;br /&gt;
|Sets the nickname of this unit&lt;br /&gt;
|-&lt;br /&gt;
|nooperation&lt;br /&gt;
|nop&lt;br /&gt;
| -&lt;br /&gt;
|Do absolutely, positively, nothing. Useful for testing and interfacing with computers, it&#039;s a good way to know that the unit is alive and responding since a &amp;quot;nop&amp;quot; is being returned as a response upon reception.&lt;br /&gt;
|-&lt;br /&gt;
|uservariable&lt;br /&gt;
|uv&lt;br /&gt;
|variable(0-9):value&lt;br /&gt;
|Set user variable 0-9 to &#039;value&#039;&lt;br /&gt;
|-&lt;br /&gt;
|expressionparserevaluate&lt;br /&gt;
|epev&lt;br /&gt;
|expression&lt;br /&gt;
|Evaluates an arithmetric expression and sends back the output, all variables and functions that can be used in any &#039;&#039;command string&#039;&#039; can also be used here. Useful for testing expressions.&lt;br /&gt;
|-&lt;br /&gt;
|ifequal&lt;br /&gt;
|ife&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] EQUALS [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring].&lt;br /&gt;
|-&lt;br /&gt;
|ifgreater&lt;br /&gt;
|ifg&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] &amp;gt; [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring]&lt;br /&gt;
|-&lt;br /&gt;
|ifless&lt;br /&gt;
|ifl&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] &amp;lt; [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring]&lt;br /&gt;
|-&lt;br /&gt;
|freeram&lt;br /&gt;
|ram&lt;br /&gt;
| -&lt;br /&gt;
|Shows free RAM memory&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The base also contains the following &#039;&#039;modules:&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|pluginhandler&lt;br /&gt;
|ph&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The Ekdahl FAR stand alone single string unit ==&lt;br /&gt;
The Ekdahl FAR stand-alone single string unit offers these &#039;&#039;commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|calibrateall&lt;br /&gt;
|ca&lt;br /&gt;
| -&lt;br /&gt;
|Performs all calibration routines on the selected bow, see below for routines performed&lt;br /&gt;
|-&lt;br /&gt;
|calibratebowspeed&lt;br /&gt;
|cbs&lt;br /&gt;
| -&lt;br /&gt;
|Finds the minimum and maximum bow speed of the selected bow&lt;br /&gt;
|-&lt;br /&gt;
|calibratebowpressure&lt;br /&gt;
|cbp&lt;br /&gt;
| -&lt;br /&gt;
|Finds the minimum and maximum bow pressure of the selected bow&lt;br /&gt;
|-&lt;br /&gt;
|calibratemute&lt;br /&gt;
|cmu&lt;br /&gt;
| -&lt;br /&gt;
|Calibrate mute settings&lt;br /&gt;
|-&lt;br /&gt;
|pickupstringfrequency&lt;br /&gt;
|psf&lt;br /&gt;
| -&lt;br /&gt;
|Returns the fundamental tone calculated from the current audio signal if apliccable&lt;br /&gt;
|-&lt;br /&gt;
|pickupaudiopeak&lt;br /&gt;
|pap&lt;br /&gt;
| -&lt;br /&gt;
|Returns the peak amplitude of the current audio signal&lt;br /&gt;
|-&lt;br /&gt;
|pickupaudiorms&lt;br /&gt;
|par&lt;br /&gt;
| -&lt;br /&gt;
|Returns the RMS amplitude of the current audio signal&lt;br /&gt;
|}&lt;br /&gt;
The Ekdahl FAR also contains the following &#039;&#039;modules&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|bowingwheel&lt;br /&gt;
|bw&lt;br /&gt;
|-&lt;br /&gt;
|mute&lt;br /&gt;
|mu&lt;br /&gt;
|-&lt;br /&gt;
|solenoid&lt;br /&gt;
|so&lt;br /&gt;
|-&lt;br /&gt;
|controlbox&lt;br /&gt;
|cb&lt;br /&gt;
|-&lt;br /&gt;
|midiconfigurationhandler&lt;br /&gt;
|mcf&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;Bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; contains everything needed to interface with a single &#039;&#039;bowing wheel&#039;&#039;. Each &#039;&#039;bowing wheel&#039;&#039; has its own harmonic series, pressure actuators and direct hardware interface. It contains the following &#039;&#039;commands&#039;&#039;.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|speedmode&lt;br /&gt;
|sm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Bow motor speed mode, 0 = Automatic and 1 = Manual. Automatic mode means that the bowing wheel will automatically turn off after the &#039;&#039;motor timeout&#039;&#039; has been reached after being put into rest mode&lt;br /&gt;
|-&lt;br /&gt;
|motortimeout&lt;br /&gt;
|mt&lt;br /&gt;
|ms&lt;br /&gt;
|Bow motor shutdown timeout after bow having been put into the rest position&lt;br /&gt;
|-&lt;br /&gt;
|pidenable&lt;br /&gt;
|pe&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets the bow PID on/off&lt;br /&gt;
|-&lt;br /&gt;
|motorfaultcommands&lt;br /&gt;
|mfc&lt;br /&gt;
|commands&lt;br /&gt;
|Commands to execute when a motor fault is tripped - !WARNING! Can ruin your instrument if changed&lt;br /&gt;
|-&lt;br /&gt;
|motoroverpowercommands&lt;br /&gt;
|moc&lt;br /&gt;
|commands&lt;br /&gt;
|Commands to execute when motor is over the power limit - !WARNING! Can ruin your instrument if changed&lt;br /&gt;
|}&lt;br /&gt;
The &#039;&#039;modules&#039;&#039; in the &amp;quot;Bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; are as follows&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|bowpressure&lt;br /&gt;
|bp&lt;br /&gt;
|-&lt;br /&gt;
|dcmotor&lt;br /&gt;
|dcm&lt;br /&gt;
|-&lt;br /&gt;
|pid&lt;br /&gt;
|pid&lt;br /&gt;
|-&lt;br /&gt;
|harmonicserieshandler&lt;br /&gt;
|hsh&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; handles the &#039;&#039;pressure&#039;&#039; of the &#039;&#039;bowing wheel&#039;&#039; against the string. The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|baseline&lt;br /&gt;
|ba&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure baseline, modulation is added to this point upward. Typically this is set with a knob on the &#039;&#039;control box&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|modifier&lt;br /&gt;
|mo&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure modulation, added to the baseline&lt;br /&gt;
|-&lt;br /&gt;
|rest&lt;br /&gt;
|rs&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the bow pressure in the &#039;&#039;rest&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|engage&lt;br /&gt;
|en&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the bow pressure in the &#039;&#039;engage&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|stallpressure&lt;br /&gt;
|sp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure stall/maximum position, this parameter is set using &#039;&#039;hardware positioning&#039;&#039; and is used as the absolute maximum for baseline and modifier combiner&lt;br /&gt;
|-&lt;br /&gt;
|engagepressure&lt;br /&gt;
|ep&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure touch/minimum position, this parameter is set using &#039;&#039;hardware position&#039;&#039; and is used as the starting point for when both the baseline and modifier is set to zero&lt;br /&gt;
|-&lt;br /&gt;
|restpressure&lt;br /&gt;
|rp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure rest position, this parameter is set using &#039;&#039;hardware positioning&#039;&#039; and is typically set to a point just below the string where it does not touch at all. The purpose of this is because while the actual hardware might be able to make the bow go even lower, that position might be far enough from the string that once &#039;&#039;engaged&#039;&#039; the bow may have so far to travel that there is perceptible &#039;&#039;latency&#039;&#039;.&lt;br /&gt;
|-&lt;br /&gt;
|engagespeed&lt;br /&gt;
|es&lt;br /&gt;
|1- ~100&lt;br /&gt;
|Bow pressure movement speed when engaging or disengaging&lt;br /&gt;
|-&lt;br /&gt;
|modulationspeed&lt;br /&gt;
|ms&lt;br /&gt;
|0.1 - 10&lt;br /&gt;
|Bow pressure movement speed while engaged&lt;br /&gt;
|-&lt;br /&gt;
|hold&lt;br /&gt;
|hd&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets bow hold (infinite sustain) on/off, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|home&lt;br /&gt;
|hm&lt;br /&gt;
| -&lt;br /&gt;
|Homing bow, used at startup and in case of the bow loosing position&lt;br /&gt;
|-&lt;br /&gt;
|tmcinfo&lt;br /&gt;
|tmi&lt;br /&gt;
| -&lt;br /&gt;
|Request statistical information from the TMC2209 stepper motor driver&lt;br /&gt;
|}&lt;br /&gt;
Note that the &amp;quot;stall&amp;quot;, &amp;quot;engage&amp;quot; and &amp;quot;rest&amp;quot;-pressure positions mention something called &#039;&#039;hardware position&#039;&#039;. This means the entire available movement of the &#039;&#039;bowing jack&#039;&#039;. Because the very bottom and top end of the movement might not be musically useful and may even harm the instrument, the &amp;quot;baseline&amp;quot; and &amp;quot;modifier&amp;quot; commands &#039;&#039;parameter&#039;&#039;s are scaled depending on these settings.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;engage&amp;quot; and &amp;quot;modulation&amp;quot;-speed settings sets how fast the stepper motor that drives the &#039;&#039;pressure&#039;&#039; moves depending on whether the &#039;&#039;bowing jack&#039;&#039; is set to &#039;&#039;engage&#039;&#039; or not. The idea here is that while wanting to be able to minimize &#039;&#039;latency&#039;&#039; by &#039;&#039;engaging&#039;&#039; and &#039;&#039;disengaging&#039;&#039; from the string as quickly as possible, dynamic changes in the &#039;&#039;pressure&#039;&#039; while playing benefits from much smoother movements as the &#039;&#039;bowing wheel&#039;&#039; takes some time to catch up to varying amounts of friction.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; contains one or more of the following &#039;&#039;modules&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|actuatorhandler&lt;br /&gt;
|ah&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;actuatorhandler&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The concept of &amp;quot;actuators&amp;quot; came up as it is possible to have &#039;&#039;bowing wheels&#039;&#039; of different sizes and wanting to be able to switch quickly in between them, perhaps during mid-performance. Because a differently sized wheel will require different values for the above mentioned &amp;quot;stall&amp;quot;, &amp;quot;engage&amp;quot; and &amp;quot;reset&amp;quot;-&#039;&#039;pressure&#039;&#039;, each &#039;&#039;actuator&#039;&#039; stores these values. Instead of having to manually change the previously mentioned values, simply selecting a new &#039;&#039;actuator&#039;&#039; will automatically load the values. The &amp;quot;actuatorhandler&amp;quot;-&#039;&#039;module&#039;&#039; is the handler of one or more &amp;quot;actuator&amp;quot;-&#039;&#039;modules&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;commands&#039;&#039; of the &amp;quot;acuatorhandler&amp;quot;-&#039;&#039;module&#039;&#039; are as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|add&lt;br /&gt;
|a&lt;br /&gt;
|(name):(rest:engage:stall)&lt;br /&gt;
|Add new actuator with the given name and parameters&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|actuatornumber&lt;br /&gt;
|Remove bow actuator [actuatornumber]&lt;br /&gt;
|-&lt;br /&gt;
|count&lt;br /&gt;
|c&lt;br /&gt;
| -&lt;br /&gt;
|Returns the amount of saved bow actuators&lt;br /&gt;
|}&lt;br /&gt;
The &amp;quot;actuatorhandler&amp;quot;-&#039;&#039;module&#039;&#039; contains one or more of&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|actuator&lt;br /&gt;
|ac&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;actuator&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;actuator&amp;quot;-&#039;&#039;module&#039;&#039; contains the following commands&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|[index]&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|Selects the given actuator&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Sets the actuator name&lt;br /&gt;
|-&lt;br /&gt;
|data&lt;br /&gt;
|da&lt;br /&gt;
|name:rest:engage:stall&lt;br /&gt;
|Sets the actuator name, rest, engage and stall &#039;&#039;pressure&#039;&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;dcmotor&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;dcmotor&amp;quot;-&#039;&#039;module&#039;&#039; handles the direct &amp;lt;u&amp;gt;raw&amp;lt;/u&amp;gt; control of the &#039;&#039;bowing motor&#039;&#039; and handles the reporting back of the current speed. It has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|run&lt;br /&gt;
|ru&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Turns the motor off/on&lt;br /&gt;
|-&lt;br /&gt;
|pwm&lt;br /&gt;
|pw&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor direct power in 16-bit PWM values, requires that the &#039;&#039;PID&#039;&#039; is turned off&lt;br /&gt;
|-&lt;br /&gt;
|voltage&lt;br /&gt;
|vo&lt;br /&gt;
|~2 - 10V&lt;br /&gt;
|Sets the voltage of the regulator powering the motor. Changes here can make the motor more responsive to certain frequencies but will also affect how well the &#039;&#039;PID&#039;&#039; works. !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|current&lt;br /&gt;
|cu&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor reported current use&lt;br /&gt;
|-&lt;br /&gt;
|currentlimit&lt;br /&gt;
|cl&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor current limit (A)- !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|powerlimit&lt;br /&gt;
|pl&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor power limit (W) - !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|frequency&lt;br /&gt;
|fq&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor reported frequency&lt;br /&gt;
|-&lt;br /&gt;
|emergencystop&lt;br /&gt;
|es&lt;br /&gt;
|ms (0-65535)&lt;br /&gt;
|Immediately stops the bowing motor and doesn&#039;t allow it to start again until the cool down period given in the first argument has lapsed (milliseconds)&lt;br /&gt;
|-&lt;br /&gt;
|minpwm&lt;br /&gt;
|ip&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor minimum PWM (for calibration)&lt;br /&gt;
|-&lt;br /&gt;
|maxpwm&lt;br /&gt;
|xp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor maximum PWM (for calibration)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;pidcontroller&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;pidcontroller&amp;quot;-&#039;&#039;module&#039;&#039; is responsible for keeping the &amp;quot;dcmotor&amp;quot;-&#039;&#039;module&#039;&#039; at a certain frequency (given in Hertz). It takes the output of the motor frequency measurement and feeds it a PWM value that tries to make the speed constant regardless of the friction that the motor is enduring. To learn more about PID Controllers please see this [[wikipedia:PID_controller|wikipedia article]]. The &#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|targetfrequency&lt;br /&gt;
|tf&lt;br /&gt;
|hertz&lt;br /&gt;
|Sets the PID target frequency&lt;br /&gt;
|-&lt;br /&gt;
|ki&lt;br /&gt;
|ki&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Ki parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|kp&lt;br /&gt;
|kp&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Kp parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|kd&lt;br /&gt;
|kd&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Kd parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|integratorerror&lt;br /&gt;
|ie&lt;br /&gt;
|float&lt;br /&gt;
|Sets the lower threshold of error values for the PID integrator to ignore&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|re&lt;br /&gt;
| -&lt;br /&gt;
|Resets the PID integrator and derivative&lt;br /&gt;
|-&lt;br /&gt;
|maxerror&lt;br /&gt;
|xe&lt;br /&gt;
|float&lt;br /&gt;
|Maximum error to correct in each PID loop, essentially sets acceleration&lt;br /&gt;
|-&lt;br /&gt;
|peakerror&lt;br /&gt;
|pe&lt;br /&gt;
|float&lt;br /&gt;
|Get latest PID peak error&lt;br /&gt;
|-&lt;br /&gt;
|motorspeedmax&lt;br /&gt;
|msx&lt;br /&gt;
|Hertz&lt;br /&gt;
|Bow motor maximum speed limit&lt;br /&gt;
|-&lt;br /&gt;
|motorspeedmin&lt;br /&gt;
|msi&lt;br /&gt;
|Hertz&lt;br /&gt;
|Bow motor minimum speed limit&lt;br /&gt;
|-&lt;br /&gt;
|measuretimetotarget&lt;br /&gt;
|mtt&lt;br /&gt;
|Hertz&lt;br /&gt;
|Measure the time it takes to change from the current frequency to the target frequency, for testing purposes&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; is responsible for sending frequency data to the &amp;quot;pid&amp;quot;-&#039;&#039;module&#039;&#039;. It handles calculating the correct frequency of the &#039;&#039;bowing wheel&#039;&#039; according to the selected &#039;&#039;harmonic&#039;&#039; and &#039;&#039;harmonic shift&#039;&#039; per the currently selected &#039;&#039;harmonic series&#039;&#039;. The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|fundamental&lt;br /&gt;
|fu&lt;br /&gt;
|Hertz&lt;br /&gt;
|The fundamental frequency of the string, all harmonics are calculated from this number&lt;br /&gt;
|-&lt;br /&gt;
|harmonic&lt;br /&gt;
|h&lt;br /&gt;
|int&lt;br /&gt;
|Selects the harmonic number to set the &#039;&#039;bowing wheel&#039;&#039; to. A ratio is taken from the given &#039;&#039;harmonic&#039;&#039; in the current &#039;&#039;harmonic series&#039;&#039;, the ratio is then multiplied by the &#039;&#039;fundamental frequency&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|harmonicadd&lt;br /&gt;
|ha&lt;br /&gt;
|int&lt;br /&gt;
|This number is added to the current harmonic&lt;br /&gt;
|-&lt;br /&gt;
|harmonicbase&lt;br /&gt;
|hb&lt;br /&gt;
|int&lt;br /&gt;
|Same as harmonic but where the harmonic number is based on a MIDI note given by basenote&lt;br /&gt;
|-&lt;br /&gt;
|basenote&lt;br /&gt;
|bn&lt;br /&gt;
|0-127&lt;br /&gt;
|Sets the MIDI base note of the &#039;&#039;bowing wheel&#039;&#039;, used in conjunction with &amp;quot;harmonicbase&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|shift&lt;br /&gt;
|sh&lt;br /&gt;
| -32767 - 32767&lt;br /&gt;
|Sets shift from the currently playing harmonic where 32767 equals the entire harmonic shift range shifted up&lt;br /&gt;
|-&lt;br /&gt;
|shiftrange&lt;br /&gt;
|sr&lt;br /&gt;
|0-36&lt;br /&gt;
|Set the number of harmonic numbers that constitutes an entire harmonic shift&lt;br /&gt;
|-&lt;br /&gt;
|shift5&lt;br /&gt;
|sh5&lt;br /&gt;
| -32767 - 32767&lt;br /&gt;
|Sets the shift from the currently playing harmonic over 5 octaves where 32767 equals 5 octaves shift up from the fundamental&lt;br /&gt;
|-&lt;br /&gt;
|add&lt;br /&gt;
|a&lt;br /&gt;
|(name):(ratios)&lt;br /&gt;
|Add a new series with the given name and parameters&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|series&lt;br /&gt;
|Remove the series given and shift any series accordingly. Cannot remove all series&lt;br /&gt;
|-&lt;br /&gt;
|count&lt;br /&gt;
|c&lt;br /&gt;
| -&lt;br /&gt;
|Returns the number of harmonic series in the list and their IDs&lt;br /&gt;
|}&lt;br /&gt;
The &amp;quot;harmonicserieshandler&amp;quot;-module contains at the very least ONE harmonic series, by default it contains two: one for equal temperament and one for just intonation. The current series can be selected by simply indexing the &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; without a &#039;&#039;command&#039;&#039;, e.g. &amp;quot;harmonicserieshandler.harmonicseries[1]&amp;quot;. To be consistent, these are the &#039;&#039;modules&#039;&#039; in the &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|harmonicseries&lt;br /&gt;
|hs&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; contains any number of &#039;&#039;ratios&#039;&#039; that comprises a scale, ratios are given in a standard format where a ratio of &amp;quot;1&amp;quot; is equal to the fundamental, &amp;quot;2&amp;quot; would be one octave up etc. A standard &#039;&#039;harmonic series&#039;&#039; contains 12 ratios following a just intonation scheme. The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; will automatically adapt to the currently selected &#039;&#039;harmonic series&#039;&#039; length, whether it&#039;s a standard 12-tone scale, some kinda 3-tone scale or a full on bananas 53-tone scale. The &#039;&#039;commands&#039;&#039; of the &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; is as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|[index]&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
|Sets the currently selected &#039;&#039;harmonic Series&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Sets the name of the &#039;&#039;harmonic series&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|data&lt;br /&gt;
|da&lt;br /&gt;
|name:ratios&lt;br /&gt;
|Gets / sets all data for the &#039;&#039;harmonic series&#039;&#039; in the given slot with an arbitrary &#039;&#039;name&#039;&#039; as the first &#039;&#039;parameter&#039;&#039;. The length of the series is simply set to the amount of ratios given&lt;br /&gt;
|-&lt;br /&gt;
|ratio&lt;br /&gt;
|r&lt;br /&gt;
|harmonic:ratio&lt;br /&gt;
|Sets the ratio of the given harmonic in current &#039;&#039;harmonic series&#039;&#039;, will increase the list size if needed to address the harmonic&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|harmonic&lt;br /&gt;
|Remove the harmonic ratio given in the current series and shift any ratios accordingly. Cannot remove all ratios&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;mute&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;mute&amp;quot;-&#039;&#039;module&#039;&#039; works very similarly to the &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; in that it controls a stepper motor with some software limits in place in order to press the mute against the string. The &#039;&#039;commands&#039;&#039; are as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|setposition&lt;br /&gt;
|sp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set mute position&lt;br /&gt;
|-&lt;br /&gt;
|fullmute&lt;br /&gt;
|fm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the mute in &#039;&#039;full mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|halfmute&lt;br /&gt;
|hm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the mute in &#039;&#039;half mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|rest&lt;br /&gt;
|rs&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Put the mute in the &#039;&#039;rest&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|savefull&lt;br /&gt;
|sf&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Save the current mute position as the &#039;&#039;full mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|savehalf&lt;br /&gt;
|sh&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Save the current mute position as the &#039;&#039;half mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|saverest&lt;br /&gt;
|sr&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Save the current mute position as the &#039;&#039;rest&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|fullmuteposition&lt;br /&gt;
|fmp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;full mute&#039;&#039; position according to the &#039;&#039;hardware position&#039;&#039; given&lt;br /&gt;
|-&lt;br /&gt;
|halfmuteposition&lt;br /&gt;
|hmp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;half mute&#039;&#039; position according to the &#039;&#039;hardware position&#039;&#039; given&lt;br /&gt;
|-&lt;br /&gt;
|restposition&lt;br /&gt;
|rp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;rest&#039;&#039; position according to the &#039;&#039;hardware position&#039;&#039; given&lt;br /&gt;
|-&lt;br /&gt;
|sustain&lt;br /&gt;
|su&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets the sustain off/on, this will keep the mute in the &#039;&#039;rest&#039;&#039; position even if a &amp;quot;fullmute&amp;quot;-&#039;&#039;command&#039;&#039; is given, lasts until &amp;quot;sustain&amp;quot; is set to &amp;quot;0&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
|backoff&lt;br /&gt;
|bo&lt;br /&gt;
|0-65535&lt;br /&gt;
|Setting the time that the mute stays in the mutefullmute position before automatically going into rest, set in mS. A value of &amp;quot;0&amp;quot; disables backoff. This is used because if the mute is not backing off until something is attempted to be played, the backing-off time will either introduce &#039;&#039;latency&#039;&#039; or the string will be initially partially muted&lt;br /&gt;
|-&lt;br /&gt;
|home&lt;br /&gt;
|hm&lt;br /&gt;
| -&lt;br /&gt;
|Home mute, used during initialization and if the mute were to loose position&lt;br /&gt;
|-&lt;br /&gt;
|hardwareposition&lt;br /&gt;
|hwp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;hardware position&#039;&#039; of the mute instead of scaling it over the &#039;&#039;full mute&#039;&#039; and &#039;&#039;rest&#039;&#039; positions. Mainly used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|completetask&lt;br /&gt;
|cpt&lt;br /&gt;
| -&lt;br /&gt;
|Requests a callback when the current operation is finished. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|autocorrect&lt;br /&gt;
|ac&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Enables auto correct positioning that uses the homing sensor to correct positioning on the fly. EXPERIMENTAL&lt;br /&gt;
|-&lt;br /&gt;
|homingsensed&lt;br /&gt;
|hms&lt;br /&gt;
| -&lt;br /&gt;
|Requests whether the homing sensor is currently active or not. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|movedirection&lt;br /&gt;
|md&lt;br /&gt;
| -&lt;br /&gt;
|Requests the current direction of movement (0 Forward, 1 Reverse). Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|currentstep&lt;br /&gt;
|cs&lt;br /&gt;
| -&lt;br /&gt;
|Requests the current step. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|homingpoint&lt;br /&gt;
|hmp&lt;br /&gt;
|edgedirection&lt;br /&gt;
|Requests the given homing point. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|homingstage&lt;br /&gt;
|hms&lt;br /&gt;
| -&lt;br /&gt;
|Requests the current homing stage (UNHOMED, HOMED, FIRSTHOMINGRISING, SECONDHOMINGFALLING, SECONDHOMINGRISING, FIRSTHOMINGFALLING, MOVEPASTHOMESWITCH, MOVETOHOMESWITCH, GOTOOFFSET). Only used internally by other &#039;&#039;modules.&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|tmcinfo&lt;br /&gt;
|tmi&lt;br /&gt;
| -&lt;br /&gt;
|Request statistical information from the TMC2209 stepper motor driver&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;solenoid&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;solenoid&amp;quot;-&#039;&#039;module&#039;&#039; currently controls the &#039;&#039;hammer&#039;&#039; of the Ekdahl FAR. Due to the fact that the very same &#039;&#039;module&#039;&#039; could be used for anything that uses a striking &#039;&#039;solenoid&#039;&#039; it was named as such. It has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|engage&lt;br /&gt;
|en&lt;br /&gt;
|0-65535&lt;br /&gt;
|Engages the solenoid using the first parameter as the force&lt;br /&gt;
|-&lt;br /&gt;
|rest&lt;br /&gt;
|rs&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Forces the solenoid to its rest position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|maxforce&lt;br /&gt;
|xf&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set solenoid maximum usable force&lt;br /&gt;
|-&lt;br /&gt;
|minforce&lt;br /&gt;
|if&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set solenoid minimum usable force&lt;br /&gt;
|-&lt;br /&gt;
|forcemultiplier&lt;br /&gt;
|fm&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set solenoid force multiplier, useful for scaling of all incoming &amp;quot;engage&amp;quot;-&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|engageduration&lt;br /&gt;
|ed&lt;br /&gt;
|uS&lt;br /&gt;
|Sets the duration of the solenoid hit in uS, if a value of 0 is set the solenoid will not disengage until a rest command has been given. WARNING!! HAVING THE SOLENOID ON FOR A SPAN OF SECONDS COULD DESTROY THE CIRCUITRY!!&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;controlbox&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;controlbox&amp;quot;-&#039;&#039;module&#039;&#039; communicates with an external &#039;&#039;control box&#039;&#039; and will issue associated &#039;&#039;commands&#039;&#039; whenever new values are read on the ADC-converters. It handles averaging and does some noise-cancellation functions on the values as well. The &#039;&#039;commands&#039;&#039; are:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|harmonic&lt;br /&gt;
|har&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the harmonic knob or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|harmonicshift&lt;br /&gt;
|has&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the harmonic shift modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|finetune&lt;br /&gt;
|fin&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the fine tune knob changes&lt;br /&gt;
|-&lt;br /&gt;
|pressure&lt;br /&gt;
|pre&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the pressure knob or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|mute&lt;br /&gt;
|mut&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the mute knob or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|hammerscale&lt;br /&gt;
|hms&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the hammer scale knob changes&lt;br /&gt;
|-&lt;br /&gt;
|gate&lt;br /&gt;
|gt&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the gate switch or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|hammertrig&lt;br /&gt;
|hmt&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the hammer trigger modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|controldefaults&lt;br /&gt;
|cde&lt;br /&gt;
| -&lt;br /&gt;
|Reverts all ADC command strings to default values&lt;br /&gt;
|-&lt;br /&gt;
|datareturn&lt;br /&gt;
|dr&lt;br /&gt;
|channel:value&lt;br /&gt;
|Sent when a new value is presented on one of the ADC channels, cannot be invoked. Triggers the commands associated with the channel&lt;br /&gt;
|-&lt;br /&gt;
|adcsetting&lt;br /&gt;
|adcs&lt;br /&gt;
|channel : averages : interrupterrorthreshold : continuouserrorthreshold : continuoustimeout&lt;br /&gt;
|Sets ADC settings for a given channel. Averages are the number of samples to average, interruptthreshold is how much the value must change in order to issue a new value change event. continuousthreshold is how much the value must change when a previous change has already been recorded within the timespan of continuoustimeout&lt;br /&gt;
|-&lt;br /&gt;
|testadclatency&lt;br /&gt;
|tal&lt;br /&gt;
|0-65535&lt;br /&gt;
|Start a ADC latency test&lt;br /&gt;
|-&lt;br /&gt;
|testadclatencyreturn&lt;br /&gt;
|talr&lt;br /&gt;
| -&lt;br /&gt;
|Return from latency test&lt;br /&gt;
|-&lt;br /&gt;
|testadcminmax&lt;br /&gt;
|tix&lt;br /&gt;
|channel&lt;br /&gt;
|Test min/max value for a given channel and resets the counter&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;midiconfigurationhandler&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;midiconfigurationhandler&amp;quot;-&#039;&#039;module&#039;&#039; handles a number of &amp;quot;midiconfiguration&amp;quot;-&#039;&#039;modules&#039;&#039;. It has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|allnotesoff&lt;br /&gt;
|ano&lt;br /&gt;
| -&lt;br /&gt;
|Clears the entire buffer of MIDI notes held&lt;br /&gt;
|-&lt;br /&gt;
|add&lt;br /&gt;
|a&lt;br /&gt;
|name&lt;br /&gt;
|Adds a new MIDI configuration with the given name&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|int&lt;br /&gt;
|Remove the specified MIDI configuration&lt;br /&gt;
|-&lt;br /&gt;
|count&lt;br /&gt;
|c&lt;br /&gt;
| -&lt;br /&gt;
|Returns the number of MIDI configurations&lt;br /&gt;
|}&lt;br /&gt;
It contains one or more of the following&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|midiconfiguration&lt;br /&gt;
|mc&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;midiconfiguration&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
A &amp;quot;midiconfiguration&amp;quot;-&#039;&#039;module&#039;&#039; handles the reception of &#039;&#039;MIDI messages&#039;&#039; and will output the associated &#039;&#039;commands&#039;&#039; to the instrument internally. The commands are as follows&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|[index]&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
|Sets the currently selected MIDI configuration&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Set the name of the MIDI configuration&lt;br /&gt;
|-&lt;br /&gt;
|noteon&lt;br /&gt;
|non&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Note On event&lt;br /&gt;
|-&lt;br /&gt;
|noteoff&lt;br /&gt;
|nof&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Note Off event&lt;br /&gt;
|-&lt;br /&gt;
|polyaftertouch&lt;br /&gt;
|pat&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Polyphonic after touch event&lt;br /&gt;
|-&lt;br /&gt;
|channelaftertouch&lt;br /&gt;
|cat&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Channel after touch event&lt;br /&gt;
|-&lt;br /&gt;
|pitchbend&lt;br /&gt;
|pb&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Pitch bend event&lt;br /&gt;
|-&lt;br /&gt;
|programchange&lt;br /&gt;
|pc&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Program change event&lt;br /&gt;
|-&lt;br /&gt;
|continuouscontrollerdata&lt;br /&gt;
|ccd&lt;br /&gt;
|controllernuber:&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Continuous controller event with the given [&#039;&#039;controllernumber&#039;&#039;]&lt;br /&gt;
|-&lt;br /&gt;
|removecc&lt;br /&gt;
|rmc&lt;br /&gt;
|controllernuber&lt;br /&gt;
|Removes the entry associated with the MIDI continuous controller even &#039;&#039;controllernumber&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|defaults&lt;br /&gt;
|d&lt;br /&gt;
| -&lt;br /&gt;
|Reverts the current configuration to default &#039;&#039;commands&#039;&#039;, values and CCs&lt;br /&gt;
|-&lt;br /&gt;
|receivechannel&lt;br /&gt;
|rc&lt;br /&gt;
|channel&lt;br /&gt;
|Sets the MIDI receive channel of the current configuration. 1-16 sets specific channel, any other value for OMNI&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;pluginhandler&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The Ekdahl FAR allows for &#039;&#039;plugins&#039;&#039;. These are &#039;&#039;modules&#039;&#039; that can trigger certain &#039;&#039;command strings&#039;&#039; to be executed either periodically or triggered by an incoming &#039;&#039;command&#039;&#039;. Further explanation of the given &#039;&#039;plugins&#039;&#039; is given below. The various &#039;&#039;plugins&#039;&#039; are handled by the &amp;quot;pluginhandler&amp;quot;-&#039;&#039;module&#039;&#039;, the different &#039;&#039;plugin modules&#039;&#039; are identified by their own unique &#039;&#039;ID&#039;&#039;. The &amp;quot;pluginhandler&amp;quot;-&#039;&#039;module&#039;&#039; it has the following &#039;&#039;commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|add&lt;br /&gt;
|a&lt;br /&gt;
|pluginid&lt;br /&gt;
|Add plugin with the given ID&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|pluginid:index&lt;br /&gt;
|Remove plugin with the given ID and index&lt;br /&gt;
|-&lt;br /&gt;
|count&lt;br /&gt;
|c&lt;br /&gt;
|(pluginid)&lt;br /&gt;
|Return the number of plugins of the given type, if none is given it returns all plugins&lt;br /&gt;
|}&lt;br /&gt;
The number of available &#039;&#039;plugins&#039;&#039; will differ from time to time as the &#039;&#039;plugin system&#039;&#039; has been purposefully designed to allow for anyone to write and add their own &#039;&#039;plugins&#039;&#039;. As of the current writing (2026-06-14) the number of &amp;lt;u&amp;gt;possible&amp;lt;/u&amp;gt; &#039;&#039;plugin modules&#039;&#039; that &amp;lt;u&amp;gt;can&amp;lt;/u&amp;gt; exist under the &amp;quot;pluginhandler&amp;quot;-&#039;&#039;module&#039;&#039; are&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|lfo&lt;br /&gt;
|lfo&lt;br /&gt;
|-&lt;br /&gt;
|ahdsr&lt;br /&gt;
|ahdsr&lt;br /&gt;
|-&lt;br /&gt;
|numbermap&lt;br /&gt;
|map&lt;br /&gt;
|-&lt;br /&gt;
|multiple&lt;br /&gt;
|mlt&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;lfo&amp;quot;-&#039;&#039;plugin module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;lfo&amp;quot;-&#039;&#039;plugin module&#039;&#039; works like regular [[wikipedia:Low-frequency_oscillation|low frequency oscillator]] in that it generates a given &#039;&#039;waveform&#039;&#039; with a given &#039;&#039;frequency&#039;&#039; at a certain &#039;&#039;amplitude&#039;&#039;. In the Ekdahl FAR the distinguishing factors are that besides the common &#039;&#039;frequency, amplitude&#039;&#039; and &#039;&#039;waveform&#039;&#039; parameters, it also requires the use of a &#039;&#039;update rate&#039;&#039; and &#039;&#039;target&#039;&#039; parameter. The &#039;&#039;update rate&#039;&#039; sets how often the current position of the LFO is sampled (aka how often it peeks in on where the LFO is in its waveform transition at the moment), and each time that happens, the &#039;&#039;target commands&#039;&#039; are outputted to the instrument.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example:&#039;&#039;&#039;&lt;br /&gt;
 Lets set the &#039;&#039;waveform&#039;&#039; to &amp;quot;triangle&amp;quot;, the &#039;&#039;amplitude&#039;&#039; to 65535 (max), the &#039;&#039;frequency&#039;&#039; to 1Hz (1 full waveform per second), the &#039;&#039;update rate&#039;&#039; to 10mS and the &#039;&#039;target&#039;&#039; to &amp;quot;bowingwheel.harmonicserieshandler.shift:lfoout&amp;quot;.&lt;br /&gt;
 &lt;br /&gt;
 The output of the LFO is always given in the variable &amp;quot;lfoout&amp;quot;, our &#039;&#039;target&#039;&#039; is set to &amp;quot;bowingwheel.harmonicserieshandler.shift&amp;quot; which controls the &#039;&#039;harmonic shift&#039;&#039; (pitchbend basically) of the &#039;&#039;bowing wheel&#039;&#039;.&lt;br /&gt;
 &lt;br /&gt;
 Since our update rate is set to every 10 milliseconds and our frequency is 1 Hertz the instrument will internally send 100 updates per second to the &#039;&#039;harmonic shift.&#039;&#039; Our amplitude is set to the maximum value and depending on the &amp;quot;harmonicserieshandler.shiftrange&amp;quot; this could give a smooth vibrato like sound or more of an experimental one with a wider range. If the modulation is too deep we can just adjust the amplitude of the LFO.&lt;/div&gt;</summary>
		<author><name>Knaadmin</name></author>
	</entry>
	<entry>
		<id>http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_reference_V1.1&amp;diff=1685</id>
		<title>The Ekdahl FAR - Command reference V1.1</title>
		<link rel="alternate" type="text/html" href="http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_reference_V1.1&amp;diff=1685"/>
		<updated>2026-06-14T08:08:45Z</updated>

		<summary type="html">&lt;p&gt;Knaadmin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
The Ekdahl FAR V1.1 introduces the concept of &#039;&#039;modules&#039;&#039;. A &#039;&#039;module&#039;&#039; can contain any number of &#039;&#039;commands&#039;&#039; as well as other &#039;&#039;modules&#039;&#039;. Furthermore any number of &#039;&#039;modules&#039;&#039; of the same type can exist within a context, these are addressed using classic C-style array &#039;&#039;indexing&#039;&#039; with the help of brackets (&amp;quot;[ ]&amp;quot;). Extending on the classic usage, multiple &#039;&#039;indexes&#039;&#039; can be addressed simultaneously by either comma-separating the objects (&amp;quot;[0,3,4]&amp;quot;) and using &#039;&#039;ranges&#039;&#039; (&amp;quot;[3-6]&amp;quot;). &#039;&#039;Modules&#039;&#039; can be either &#039;&#039;internal&#039;&#039; or &#039;&#039;external&#039;&#039;, meaning that they may all physically exist within a single hardware object, or they can be be remote-controlled devices. From a user perspective this however makes no difference as they will appear the same.&lt;br /&gt;
&lt;br /&gt;
While all &#039;&#039;modules&#039;&#039; have their own set of &#039;&#039;commands&#039;&#039;, there are certain &#039;&#039;commands&#039;&#039; that all &#039;&#039;modules&#039;&#039; &amp;lt;u&amp;gt;must&amp;lt;/u&amp;gt; implement and can thus be accessed anywhere within the &#039;&#039;module hierarchy.&#039;&#039; There are also &#039;&#039;base commands&#039;&#039; that always exist within any given FAR ecosystem as well as product-specific &#039;&#039;base commands&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Ubiquitous commands ==&lt;br /&gt;
The &#039;&#039;module commands&#039;&#039; that are &amp;lt;u&amp;gt;required&amp;lt;/u&amp;gt; to be implemented in &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; &#039;&#039;modules&#039;&#039; and that can thus be accessed from anywhere are&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|list&lt;br /&gt;
|ls&lt;br /&gt;
|hidden/h:modules/m:commands/c:instances/i:instancecounts/ic:recursive/r&lt;br /&gt;
|Lists all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039; under the current module depending on the parameters given; &#039;hidden&#039; includes normally hidden &#039;&#039;commands&#039;&#039;, &#039;modules&#039; includes any &#039;&#039;submodules&#039;&#039;, &#039;commands&#039; shows &#039;&#039;commands&#039;&#039;, &#039;instances&#039; shows data for each individual instance of a &#039;&#039;module&#039;&#039;, &#039;instancecounts&#039; includes number of instances of each &#039;&#039;module&#039;&#039;, &#039;recursive&#039; lists all child &#039;&#039;modules&#039;&#039; / &#039;&#039;commands&#039;&#039;. No parameters defaults to showing all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039; recursively with instance counts. It doesn&#039;t show per-instance data or hidden commands.&lt;br /&gt;
|-&lt;br /&gt;
|help&lt;br /&gt;
|help&lt;br /&gt;
|recursive/r&lt;br /&gt;
|Shows a brief explanation of all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039;, shows the help for all &#039;&#039;submodules&#039;&#039; as well if &#039;recursive&#039;&lt;br /&gt;
|-&lt;br /&gt;
|dumpdata&lt;br /&gt;
|dump&lt;br /&gt;
|recursive/r&lt;br /&gt;
|Dumps all data saved for the current &#039;&#039;module&#039;&#039;, will list the data of all &#039;&#039;submodules&#039;&#039; as well if &#039;recursive&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Base commands ==&lt;br /&gt;
B&#039;&#039;ase commands&#039;&#039; are &#039;&#039;commands&#039;&#039; that always exist at the root in any implementation of the Ekdahl FAR.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|version&lt;br /&gt;
|ver&lt;br /&gt;
| -&lt;br /&gt;
|Gets the current firmware version&lt;br /&gt;
|-&lt;br /&gt;
|debugprint&lt;br /&gt;
|dp&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;command|usb|hardware|undefined|priority|error|inforequest|expressionparser|debug:1|0&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Turns on or off serial feedback for the given item&lt;br /&gt;
|-&lt;br /&gt;
|requestinfo&lt;br /&gt;
|rqi&lt;br /&gt;
|command&lt;br /&gt;
|Retrives any data saved for a &#039;&#039;command&#039;&#039;, if applicable&lt;br /&gt;
|-&lt;br /&gt;
|saveallparameters&lt;br /&gt;
|sap&lt;br /&gt;
| -&lt;br /&gt;
|Saves all avaliable parameters&lt;br /&gt;
|-&lt;br /&gt;
|loadallparameters&lt;br /&gt;
|lap&lt;br /&gt;
| -&lt;br /&gt;
|Loads all avaliable parameters&lt;br /&gt;
|-&lt;br /&gt;
|resetallparameters&lt;br /&gt;
|rap&lt;br /&gt;
| -&lt;br /&gt;
|Resets all saved parameters&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|rst&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;1|0&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Resets the Ekdahl FAR, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|nick&lt;br /&gt;
|nick&lt;br /&gt;
|name&lt;br /&gt;
|Sets the nickname of this unit&lt;br /&gt;
|-&lt;br /&gt;
|nooperation&lt;br /&gt;
|nop&lt;br /&gt;
| -&lt;br /&gt;
|Do absolutely, positively, nothing. Useful for testing and interfacing with computers, it&#039;s a good way to know that the unit is alive and responding since a &amp;quot;nop&amp;quot; is being returned as a response upon reception.&lt;br /&gt;
|-&lt;br /&gt;
|uservariable&lt;br /&gt;
|uv&lt;br /&gt;
|variable(0-9):value&lt;br /&gt;
|Set user variable 0-9 to &#039;value&#039;&lt;br /&gt;
|-&lt;br /&gt;
|expressionparserevaluate&lt;br /&gt;
|epev&lt;br /&gt;
|expression&lt;br /&gt;
|Evaluates an arithmetric expression and sends back the output, all variables and functions that can be used in any &#039;&#039;command string&#039;&#039; can also be used here. Useful for testing expressions.&lt;br /&gt;
|-&lt;br /&gt;
|ifequal&lt;br /&gt;
|ife&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] EQUALS [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring].&lt;br /&gt;
|-&lt;br /&gt;
|ifgreater&lt;br /&gt;
|ifg&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] &amp;gt; [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring]&lt;br /&gt;
|-&lt;br /&gt;
|ifless&lt;br /&gt;
|ifl&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] &amp;lt; [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring]&lt;br /&gt;
|-&lt;br /&gt;
|freeram&lt;br /&gt;
|ram&lt;br /&gt;
| -&lt;br /&gt;
|Shows free RAM memory&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The base also contains the following &#039;&#039;modules:&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|pluginhandler&lt;br /&gt;
|ph&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The Ekdahl FAR stand alone single string unit ==&lt;br /&gt;
The Ekdahl FAR stand-alone single string unit offers these &#039;&#039;commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|calibrateall&lt;br /&gt;
|ca&lt;br /&gt;
| -&lt;br /&gt;
|Performs all calibration routines on the selected bow, see below for routines performed&lt;br /&gt;
|-&lt;br /&gt;
|calibratebowspeed&lt;br /&gt;
|cbs&lt;br /&gt;
| -&lt;br /&gt;
|Finds the minimum and maximum bow speed of the selected bow&lt;br /&gt;
|-&lt;br /&gt;
|calibratebowpressure&lt;br /&gt;
|cbp&lt;br /&gt;
| -&lt;br /&gt;
|Finds the minimum and maximum bow pressure of the selected bow&lt;br /&gt;
|-&lt;br /&gt;
|calibratemute&lt;br /&gt;
|cmu&lt;br /&gt;
| -&lt;br /&gt;
|Calibrate mute settings&lt;br /&gt;
|-&lt;br /&gt;
|pickupstringfrequency&lt;br /&gt;
|psf&lt;br /&gt;
| -&lt;br /&gt;
|Returns the fundamental tone calculated from the current audio signal if apliccable&lt;br /&gt;
|-&lt;br /&gt;
|pickupaudiopeak&lt;br /&gt;
|pap&lt;br /&gt;
| -&lt;br /&gt;
|Returns the peak amplitude of the current audio signal&lt;br /&gt;
|-&lt;br /&gt;
|pickupaudiorms&lt;br /&gt;
|par&lt;br /&gt;
| -&lt;br /&gt;
|Returns the RMS amplitude of the current audio signal&lt;br /&gt;
|}&lt;br /&gt;
The Ekdahl FAR also contains the following &#039;&#039;modules&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|bowingwheel&lt;br /&gt;
|bw&lt;br /&gt;
|-&lt;br /&gt;
|mute&lt;br /&gt;
|mu&lt;br /&gt;
|-&lt;br /&gt;
|solenoid&lt;br /&gt;
|so&lt;br /&gt;
|-&lt;br /&gt;
|controlbox&lt;br /&gt;
|cb&lt;br /&gt;
|-&lt;br /&gt;
|midiconfigurationhandler&lt;br /&gt;
|mcf&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;Bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; contains everything needed to interface with a single &#039;&#039;bowing wheel&#039;&#039;. Each &#039;&#039;bowing wheel&#039;&#039; has its own harmonic series, pressure actuators and direct hardware interface. It contains the following &#039;&#039;commands&#039;&#039;.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|speedmode&lt;br /&gt;
|sm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Bow motor speed mode, 0 = Automatic and 1 = Manual. Automatic mode means that the bowing wheel will automatically turn off after the &#039;&#039;motor timeout&#039;&#039; has been reached after being put into rest mode&lt;br /&gt;
|-&lt;br /&gt;
|motortimeout&lt;br /&gt;
|mt&lt;br /&gt;
|ms&lt;br /&gt;
|Bow motor shutdown timeout after bow having been put into the rest position&lt;br /&gt;
|-&lt;br /&gt;
|pidenable&lt;br /&gt;
|pe&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets the bow PID on/off&lt;br /&gt;
|-&lt;br /&gt;
|motorfaultcommands&lt;br /&gt;
|mfc&lt;br /&gt;
|commands&lt;br /&gt;
|Commands to execute when a motor fault is tripped - !WARNING! Can ruin your instrument if changed&lt;br /&gt;
|-&lt;br /&gt;
|motoroverpowercommands&lt;br /&gt;
|moc&lt;br /&gt;
|commands&lt;br /&gt;
|Commands to execute when motor is over the power limit - !WARNING! Can ruin your instrument if changed&lt;br /&gt;
|}&lt;br /&gt;
The &#039;&#039;modules&#039;&#039; in the &amp;quot;Bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; are as follows&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|bowpressure&lt;br /&gt;
|bp&lt;br /&gt;
|-&lt;br /&gt;
|dcmotor&lt;br /&gt;
|dcm&lt;br /&gt;
|-&lt;br /&gt;
|pid&lt;br /&gt;
|pid&lt;br /&gt;
|-&lt;br /&gt;
|harmonicserieshandler&lt;br /&gt;
|hsh&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; handles the &#039;&#039;pressure&#039;&#039; of the &#039;&#039;bowing wheel&#039;&#039; against the string. The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|baseline&lt;br /&gt;
|ba&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure baseline, modulation is added to this point upward. Typically this is set with a knob on the &#039;&#039;control box&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|modifier&lt;br /&gt;
|mo&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure modulation, added to the baseline&lt;br /&gt;
|-&lt;br /&gt;
|rest&lt;br /&gt;
|rs&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the bow pressure in the &#039;&#039;rest&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|engage&lt;br /&gt;
|en&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the bow pressure in the &#039;&#039;engage&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|stallpressure&lt;br /&gt;
|sp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure stall/maximum position, this parameter is set using &#039;&#039;hardware positioning&#039;&#039; and is used as the absolute maximum for baseline and modifier combiner&lt;br /&gt;
|-&lt;br /&gt;
|engagepressure&lt;br /&gt;
|ep&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure touch/minimum position, this parameter is set using &#039;&#039;hardware position&#039;&#039; and is used as the starting point for when both the baseline and modifier is set to zero&lt;br /&gt;
|-&lt;br /&gt;
|restpressure&lt;br /&gt;
|rp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure rest position, this parameter is set using &#039;&#039;hardware positioning&#039;&#039; and is typically set to a point just below the string where it does not touch at all. The purpose of this is because while the actual hardware might be able to make the bow go even lower, that position might be far enough from the string that once &#039;&#039;engaged&#039;&#039; the bow may have so far to travel that there is perceptible &#039;&#039;latency&#039;&#039;.&lt;br /&gt;
|-&lt;br /&gt;
|engagespeed&lt;br /&gt;
|es&lt;br /&gt;
|1- ~100&lt;br /&gt;
|Bow pressure movement speed when engaging or disengaging&lt;br /&gt;
|-&lt;br /&gt;
|modulationspeed&lt;br /&gt;
|ms&lt;br /&gt;
|0.1 - 10&lt;br /&gt;
|Bow pressure movement speed while engaged&lt;br /&gt;
|-&lt;br /&gt;
|hold&lt;br /&gt;
|hd&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets bow hold (infinite sustain) on/off, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|home&lt;br /&gt;
|hm&lt;br /&gt;
| -&lt;br /&gt;
|Homing bow, used at startup and in case of the bow loosing position&lt;br /&gt;
|-&lt;br /&gt;
|tmcinfo&lt;br /&gt;
|tmi&lt;br /&gt;
| -&lt;br /&gt;
|Request statistical information from the TMC2209 stepper motor driver&lt;br /&gt;
|}&lt;br /&gt;
Note that the &amp;quot;stall&amp;quot;, &amp;quot;engage&amp;quot; and &amp;quot;rest&amp;quot;-pressure positions mention something called &#039;&#039;hardware position&#039;&#039;. This means the entire available movement of the &#039;&#039;bowing jack&#039;&#039;. Because the very bottom and top end of the movement might not be musically useful and may even harm the instrument, the &amp;quot;baseline&amp;quot; and &amp;quot;modifier&amp;quot; commands &#039;&#039;parameter&#039;&#039;s are scaled depending on these settings.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;engage&amp;quot; and &amp;quot;modulation&amp;quot;-speed settings sets how fast the stepper motor that drives the &#039;&#039;pressure&#039;&#039; moves depending on whether the &#039;&#039;bowing jack&#039;&#039; is set to &#039;&#039;engage&#039;&#039; or not. The idea here is that while wanting to be able to minimize &#039;&#039;latency&#039;&#039; by &#039;&#039;engaging&#039;&#039; and &#039;&#039;disengaging&#039;&#039; from the string as quickly as possible, dynamic changes in the &#039;&#039;pressure&#039;&#039; while playing benefits from much smoother movements as the &#039;&#039;bowing wheel&#039;&#039; takes some time to catch up to varying amounts of friction.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; contains one or more of the following &#039;&#039;modules&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|actuatorhandler&lt;br /&gt;
|ah&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;actuatorhandler&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The concept of &amp;quot;actuators&amp;quot; came up as it is possible to have &#039;&#039;bowing wheels&#039;&#039; of different sizes and wanting to be able to switch quickly in between them, perhaps during mid-performance. Because a differently sized wheel will require different values for the above mentioned &amp;quot;stall&amp;quot;, &amp;quot;engage&amp;quot; and &amp;quot;reset&amp;quot;-&#039;&#039;pressure&#039;&#039;, each &#039;&#039;actuator&#039;&#039; stores these values. Instead of having to manually change the previously mentioned values, simply selecting a new &#039;&#039;actuator&#039;&#039; will automatically load the values. The &amp;quot;actuatorhandler&amp;quot;-&#039;&#039;module&#039;&#039; is the handler of one or more &amp;quot;actuator&amp;quot;-&#039;&#039;modules&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;commands&#039;&#039; of the &amp;quot;acuatorhandler&amp;quot;-&#039;&#039;module&#039;&#039; are as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|add&lt;br /&gt;
|a&lt;br /&gt;
|(name):(rest:engage:stall)&lt;br /&gt;
|Add new actuator with the given name and parameters&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|actuatornumber&lt;br /&gt;
|Remove bow actuator [actuatornumber]&lt;br /&gt;
|-&lt;br /&gt;
|count&lt;br /&gt;
|c&lt;br /&gt;
| -&lt;br /&gt;
|Returns the amount of saved bow actuators&lt;br /&gt;
|}&lt;br /&gt;
The &amp;quot;actuatorhandler&amp;quot;-&#039;&#039;module&#039;&#039; contains one or more of&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|actuator&lt;br /&gt;
|ac&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;actuator&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;actuator&amp;quot;-&#039;&#039;module&#039;&#039; contains the following commands&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|[index]&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|Selects the given actuator&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Sets the actuator name&lt;br /&gt;
|-&lt;br /&gt;
|data&lt;br /&gt;
|da&lt;br /&gt;
|name:rest:engage:stall&lt;br /&gt;
|Sets the actuator name, rest, engage and stall &#039;&#039;pressure&#039;&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;dcmotor&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;dcmotor&amp;quot;-&#039;&#039;module&#039;&#039; handles the direct &amp;lt;u&amp;gt;raw&amp;lt;/u&amp;gt; control of the &#039;&#039;bowing motor&#039;&#039; and handles the reporting back of the current speed. It has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|run&lt;br /&gt;
|ru&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Turns the motor off/on&lt;br /&gt;
|-&lt;br /&gt;
|pwm&lt;br /&gt;
|pw&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor direct power in 16-bit PWM values, requires that the &#039;&#039;PID&#039;&#039; is turned off&lt;br /&gt;
|-&lt;br /&gt;
|voltage&lt;br /&gt;
|vo&lt;br /&gt;
|~2 - 10V&lt;br /&gt;
|Sets the voltage of the regulator powering the motor. Changes here can make the motor more responsive to certain frequencies but will also affect how well the &#039;&#039;PID&#039;&#039; works. !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|current&lt;br /&gt;
|cu&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor reported current use&lt;br /&gt;
|-&lt;br /&gt;
|currentlimit&lt;br /&gt;
|cl&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor current limit (A)- !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|powerlimit&lt;br /&gt;
|pl&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor power limit (W) - !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|frequency&lt;br /&gt;
|fq&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor reported frequency&lt;br /&gt;
|-&lt;br /&gt;
|emergencystop&lt;br /&gt;
|es&lt;br /&gt;
|ms (0-65535)&lt;br /&gt;
|Immediately stops the bowing motor and doesn&#039;t allow it to start again until the cool down period given in the first argument has lapsed (milliseconds)&lt;br /&gt;
|-&lt;br /&gt;
|minpwm&lt;br /&gt;
|ip&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor minimum PWM (for calibration)&lt;br /&gt;
|-&lt;br /&gt;
|maxpwm&lt;br /&gt;
|xp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor maximum PWM (for calibration)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;pidcontroller&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;pidcontroller&amp;quot;-&#039;&#039;module&#039;&#039; is responsible for keeping the &amp;quot;dcmotor&amp;quot;-&#039;&#039;module&#039;&#039; at a certain frequency (given in Hertz). It takes the output of the motor frequency measurement and feeds it a PWM value that tries to make the speed constant regardless of the friction that the motor is enduring. To learn more about PID Controllers please see this [[wikipedia:PID_controller|wikipedia article]]. The &#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|targetfrequency&lt;br /&gt;
|tf&lt;br /&gt;
|hertz&lt;br /&gt;
|Sets the PID target frequency&lt;br /&gt;
|-&lt;br /&gt;
|ki&lt;br /&gt;
|ki&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Ki parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|kp&lt;br /&gt;
|kp&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Kp parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|kd&lt;br /&gt;
|kd&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Kd parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|integratorerror&lt;br /&gt;
|ie&lt;br /&gt;
|float&lt;br /&gt;
|Sets the lower threshold of error values for the PID integrator to ignore&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|re&lt;br /&gt;
| -&lt;br /&gt;
|Resets the PID integrator and derivative&lt;br /&gt;
|-&lt;br /&gt;
|maxerror&lt;br /&gt;
|xe&lt;br /&gt;
|float&lt;br /&gt;
|Maximum error to correct in each PID loop, essentially sets acceleration&lt;br /&gt;
|-&lt;br /&gt;
|peakerror&lt;br /&gt;
|pe&lt;br /&gt;
|float&lt;br /&gt;
|Get latest PID peak error&lt;br /&gt;
|-&lt;br /&gt;
|motorspeedmax&lt;br /&gt;
|msx&lt;br /&gt;
|Hertz&lt;br /&gt;
|Bow motor maximum speed limit&lt;br /&gt;
|-&lt;br /&gt;
|motorspeedmin&lt;br /&gt;
|msi&lt;br /&gt;
|Hertz&lt;br /&gt;
|Bow motor minimum speed limit&lt;br /&gt;
|-&lt;br /&gt;
|measuretimetotarget&lt;br /&gt;
|mtt&lt;br /&gt;
|Hertz&lt;br /&gt;
|Measure the time it takes to change from the current frequency to the target frequency, for testing purposes&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; is responsible for sending frequency data to the &amp;quot;pid&amp;quot;-&#039;&#039;module&#039;&#039;. It handles calculating the correct frequency of the &#039;&#039;bowing wheel&#039;&#039; according to the selected &#039;&#039;harmonic&#039;&#039; and &#039;&#039;harmonic shift&#039;&#039; per the currently selected &#039;&#039;harmonic series&#039;&#039;. The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|fundamental&lt;br /&gt;
|fu&lt;br /&gt;
|Hertz&lt;br /&gt;
|The fundamental frequency of the string, all harmonics are calculated from this number&lt;br /&gt;
|-&lt;br /&gt;
|harmonic&lt;br /&gt;
|h&lt;br /&gt;
|int&lt;br /&gt;
|Selects the harmonic number to set the &#039;&#039;bowing wheel&#039;&#039; to. A ratio is taken from the given &#039;&#039;harmonic&#039;&#039; in the current &#039;&#039;harmonic series&#039;&#039;, the ratio is then multiplied by the &#039;&#039;fundamental frequency&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|harmonicadd&lt;br /&gt;
|ha&lt;br /&gt;
|int&lt;br /&gt;
|This number is added to the current harmonic&lt;br /&gt;
|-&lt;br /&gt;
|harmonicbase&lt;br /&gt;
|hb&lt;br /&gt;
|int&lt;br /&gt;
|Same as harmonic but where the harmonic number is based on a MIDI note given by basenote&lt;br /&gt;
|-&lt;br /&gt;
|basenote&lt;br /&gt;
|bn&lt;br /&gt;
|0-127&lt;br /&gt;
|Sets the MIDI base note of the &#039;&#039;bowing wheel&#039;&#039;, used in conjunction with &amp;quot;harmonicbase&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|shift&lt;br /&gt;
|sh&lt;br /&gt;
| -32767 - 32767&lt;br /&gt;
|Sets shift from the currently playing harmonic where 32767 equals the entire harmonic shift range shifted up&lt;br /&gt;
|-&lt;br /&gt;
|shiftrange&lt;br /&gt;
|sr&lt;br /&gt;
|0-36&lt;br /&gt;
|Set the number of harmonic numbers that constitutes an entire harmonic shift&lt;br /&gt;
|-&lt;br /&gt;
|shift5&lt;br /&gt;
|sh5&lt;br /&gt;
| -32767 - 32767&lt;br /&gt;
|Sets the shift from the currently playing harmonic over 5 octaves where 32767 equals 5 octaves shift up from the fundamental&lt;br /&gt;
|-&lt;br /&gt;
|add&lt;br /&gt;
|a&lt;br /&gt;
|(name):(ratios)&lt;br /&gt;
|Add a new series with the given name and parameters&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|series&lt;br /&gt;
|Remove the series given and shift any series accordingly. Cannot remove all series&lt;br /&gt;
|-&lt;br /&gt;
|count&lt;br /&gt;
|c&lt;br /&gt;
| -&lt;br /&gt;
|Returns the number of harmonic series in the list and their IDs&lt;br /&gt;
|}&lt;br /&gt;
The &amp;quot;harmonicserieshandler&amp;quot;-module contains at the very least ONE harmonic series, by default it contains two: one for equal temperament and one for just intonation. The current series can be selected by simply indexing the &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; without a &#039;&#039;command&#039;&#039;, e.g. &amp;quot;harmonicserieshandler.harmonicseries[1]&amp;quot;. To be consistent, these are the &#039;&#039;modules&#039;&#039; in the &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|harmonicseries&lt;br /&gt;
|hs&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; contains any number of &#039;&#039;ratios&#039;&#039; that comprises a scale, ratios are given in a standard format where a ratio of &amp;quot;1&amp;quot; is equal to the fundamental, &amp;quot;2&amp;quot; would be one octave up etc. A standard &#039;&#039;harmonic series&#039;&#039; contains 12 ratios following a just intonation scheme. The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; will automatically adapt to the currently selected &#039;&#039;harmonic series&#039;&#039; length, whether it&#039;s a standard 12-tone scale, some kinda 3-tone scale or a full on bananas 53-tone scale. The &#039;&#039;commands&#039;&#039; of the &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; is as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|[index]&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
|Sets the currently selected &#039;&#039;harmonic Series&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Sets the name of the &#039;&#039;harmonic series&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|data&lt;br /&gt;
|da&lt;br /&gt;
|name:ratios&lt;br /&gt;
|Gets / sets all data for the &#039;&#039;harmonic series&#039;&#039; in the given slot with an arbitrary &#039;&#039;name&#039;&#039; as the first &#039;&#039;parameter&#039;&#039;. The length of the series is simply set to the amount of ratios given&lt;br /&gt;
|-&lt;br /&gt;
|ratio&lt;br /&gt;
|r&lt;br /&gt;
|harmonic:ratio&lt;br /&gt;
|Sets the ratio of the given harmonic in current &#039;&#039;harmonic series&#039;&#039;, will increase the list size if needed to address the harmonic&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|harmonic&lt;br /&gt;
|Remove the harmonic ratio given in the current series and shift any ratios accordingly. Cannot remove all ratios&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;mute&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;mute&amp;quot;-&#039;&#039;module&#039;&#039; works very similarly to the &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; in that it controls a stepper motor with some software limits in place in order to press the mute against the string. The &#039;&#039;commands&#039;&#039; are as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|setposition&lt;br /&gt;
|sp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set mute position&lt;br /&gt;
|-&lt;br /&gt;
|fullmute&lt;br /&gt;
|fm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the mute in &#039;&#039;full mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|halfmute&lt;br /&gt;
|hm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the mute in &#039;&#039;half mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|rest&lt;br /&gt;
|rs&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Put the mute in the &#039;&#039;rest&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|savefull&lt;br /&gt;
|sf&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Save the current mute position as the &#039;&#039;full mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|savehalf&lt;br /&gt;
|sh&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Save the current mute position as the &#039;&#039;half mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|saverest&lt;br /&gt;
|sr&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Save the current mute position as the &#039;&#039;rest&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|fullmuteposition&lt;br /&gt;
|fmp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;full mute&#039;&#039; position according to the &#039;&#039;hardware position&#039;&#039; given&lt;br /&gt;
|-&lt;br /&gt;
|halfmuteposition&lt;br /&gt;
|hmp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;half mute&#039;&#039; position according to the &#039;&#039;hardware position&#039;&#039; given&lt;br /&gt;
|-&lt;br /&gt;
|restposition&lt;br /&gt;
|rp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;rest&#039;&#039; position according to the &#039;&#039;hardware position&#039;&#039; given&lt;br /&gt;
|-&lt;br /&gt;
|sustain&lt;br /&gt;
|su&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets the sustain off/on, this will keep the mute in the &#039;&#039;rest&#039;&#039; position even if a &amp;quot;fullmute&amp;quot;-&#039;&#039;command&#039;&#039; is given, lasts until &amp;quot;sustain&amp;quot; is set to &amp;quot;0&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
|backoff&lt;br /&gt;
|bo&lt;br /&gt;
|0-65535&lt;br /&gt;
|Setting the time that the mute stays in the mutefullmute position before automatically going into rest, set in mS. A value of &amp;quot;0&amp;quot; disables backoff. This is used because if the mute is not backing off until something is attempted to be played, the backing-off time will either introduce &#039;&#039;latency&#039;&#039; or the string will be initially partially muted&lt;br /&gt;
|-&lt;br /&gt;
|home&lt;br /&gt;
|hm&lt;br /&gt;
| -&lt;br /&gt;
|Home mute, used during initialization and if the mute were to loose position&lt;br /&gt;
|-&lt;br /&gt;
|hardwareposition&lt;br /&gt;
|hwp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;hardware position&#039;&#039; of the mute instead of scaling it over the &#039;&#039;full mute&#039;&#039; and &#039;&#039;rest&#039;&#039; positions. Mainly used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|completetask&lt;br /&gt;
|cpt&lt;br /&gt;
| -&lt;br /&gt;
|Requests a callback when the current operation is finished. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|autocorrect&lt;br /&gt;
|ac&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Enables auto correct positioning that uses the homing sensor to correct positioning on the fly. EXPERIMENTAL&lt;br /&gt;
|-&lt;br /&gt;
|homingsensed&lt;br /&gt;
|hms&lt;br /&gt;
| -&lt;br /&gt;
|Requests whether the homing sensor is currently active or not. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|movedirection&lt;br /&gt;
|md&lt;br /&gt;
| -&lt;br /&gt;
|Requests the current direction of movement (0 Forward, 1 Reverse). Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|currentstep&lt;br /&gt;
|cs&lt;br /&gt;
| -&lt;br /&gt;
|Requests the current step. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|homingpoint&lt;br /&gt;
|hmp&lt;br /&gt;
|edgedirection&lt;br /&gt;
|Requests the given homing point. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|homingstage&lt;br /&gt;
|hms&lt;br /&gt;
| -&lt;br /&gt;
|Requests the current homing stage (UNHOMED, HOMED, FIRSTHOMINGRISING, SECONDHOMINGFALLING, SECONDHOMINGRISING, FIRSTHOMINGFALLING, MOVEPASTHOMESWITCH, MOVETOHOMESWITCH, GOTOOFFSET). Only used internally by other &#039;&#039;modules.&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|tmcinfo&lt;br /&gt;
|tmi&lt;br /&gt;
| -&lt;br /&gt;
|Request statistical information from the TMC2209 stepper motor driver&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;solenoid&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;solenoid&amp;quot;-&#039;&#039;module&#039;&#039; currently controls the &#039;&#039;hammer&#039;&#039; of the Ekdahl FAR. Due to the fact that the very same &#039;&#039;module&#039;&#039; could be used for anything that uses a striking &#039;&#039;solenoid&#039;&#039; it was named as such. It has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|engage&lt;br /&gt;
|en&lt;br /&gt;
|0-65535&lt;br /&gt;
|Engages the solenoid using the first parameter as the force&lt;br /&gt;
|-&lt;br /&gt;
|rest&lt;br /&gt;
|rs&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Forces the solenoid to its rest position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|maxforce&lt;br /&gt;
|xf&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set solenoid maximum usable force&lt;br /&gt;
|-&lt;br /&gt;
|minforce&lt;br /&gt;
|if&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set solenoid minimum usable force&lt;br /&gt;
|-&lt;br /&gt;
|forcemultiplier&lt;br /&gt;
|fm&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set solenoid force multiplier, useful for scaling of all incoming &amp;quot;engage&amp;quot;-&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|engageduration&lt;br /&gt;
|ed&lt;br /&gt;
|uS&lt;br /&gt;
|Sets the duration of the solenoid hit in uS, if a value of 0 is set the solenoid will not disengage until a rest command has been given. WARNING!! HAVING THE SOLENOID ON FOR A SPAN OF SECONDS COULD DESTROY THE CIRCUITRY!!&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;controlbox&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;controlbox&amp;quot;-&#039;&#039;module&#039;&#039; communicates with an external &#039;&#039;control box&#039;&#039; and will issue associated &#039;&#039;commands&#039;&#039; whenever new values are read on the ADC-converters. It handles averaging and does some noise-cancellation functions on the values as well. The &#039;&#039;commands&#039;&#039; are:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|harmonic&lt;br /&gt;
|har&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the harmonic knob or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|harmonicshift&lt;br /&gt;
|has&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the harmonic shift modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|finetune&lt;br /&gt;
|fin&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the fine tune knob changes&lt;br /&gt;
|-&lt;br /&gt;
|pressure&lt;br /&gt;
|pre&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the pressure knob or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|mute&lt;br /&gt;
|mut&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the mute knob or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|hammerscale&lt;br /&gt;
|hms&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the hammer scale knob changes&lt;br /&gt;
|-&lt;br /&gt;
|gate&lt;br /&gt;
|gt&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the gate switch or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|hammertrig&lt;br /&gt;
|hmt&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the hammer trigger modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|controldefaults&lt;br /&gt;
|cde&lt;br /&gt;
| -&lt;br /&gt;
|Reverts all ADC command strings to default values&lt;br /&gt;
|-&lt;br /&gt;
|datareturn&lt;br /&gt;
|dr&lt;br /&gt;
|channel:value&lt;br /&gt;
|Sent when a new value is presented on one of the ADC channels, cannot be invoked. Triggers the commands associated with the channel&lt;br /&gt;
|-&lt;br /&gt;
|adcsetting&lt;br /&gt;
|adcs&lt;br /&gt;
|channel : averages : interrupterrorthreshold : continuouserrorthreshold : continuoustimeout&lt;br /&gt;
|Sets ADC settings for a given channel. Averages are the number of samples to average, interruptthreshold is how much the value must change in order to issue a new value change event. continuousthreshold is how much the value must change when a previous change has already been recorded within the timespan of continuoustimeout&lt;br /&gt;
|-&lt;br /&gt;
|testadclatency&lt;br /&gt;
|tal&lt;br /&gt;
|0-65535&lt;br /&gt;
|Start a ADC latency test&lt;br /&gt;
|-&lt;br /&gt;
|testadclatencyreturn&lt;br /&gt;
|talr&lt;br /&gt;
| -&lt;br /&gt;
|Return from latency test&lt;br /&gt;
|-&lt;br /&gt;
|testadcminmax&lt;br /&gt;
|tix&lt;br /&gt;
|channel&lt;br /&gt;
|Test min/max value for a given channel and resets the counter&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;midiconfigurationhandler&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;midiconfigurationhandler&amp;quot;-&#039;&#039;module&#039;&#039; handles a number of &amp;quot;midiconfiguration&amp;quot;-&#039;&#039;modules&#039;&#039;. It has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|allnotesoff&lt;br /&gt;
|ano&lt;br /&gt;
| -&lt;br /&gt;
|Clears the entire buffer of MIDI notes held&lt;br /&gt;
|-&lt;br /&gt;
|add&lt;br /&gt;
|a&lt;br /&gt;
|name&lt;br /&gt;
|Adds a new MIDI configuration with the given name&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|int&lt;br /&gt;
|Remove the specified MIDI configuration&lt;br /&gt;
|-&lt;br /&gt;
|count&lt;br /&gt;
|c&lt;br /&gt;
| -&lt;br /&gt;
|Returns the number of MIDI configurations&lt;br /&gt;
|}&lt;br /&gt;
It contains one or more of the following&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|midiconfiguration&lt;br /&gt;
|mc&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;midiconfiguration&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
A &amp;quot;midiconfiguration&amp;quot;-&#039;&#039;module&#039;&#039; handles the reception of &#039;&#039;MIDI messages&#039;&#039; and will output the associated &#039;&#039;commands&#039;&#039; to the instrument internally. The commands are as follows&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|[index]&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
|Sets the currently selected MIDI configuration&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Set the name of the MIDI configuration&lt;br /&gt;
|-&lt;br /&gt;
|noteon&lt;br /&gt;
|non&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Note On event&lt;br /&gt;
|-&lt;br /&gt;
|noteoff&lt;br /&gt;
|nof&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Note Off event&lt;br /&gt;
|-&lt;br /&gt;
|polyaftertouch&lt;br /&gt;
|pat&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Polyphonic after touch event&lt;br /&gt;
|-&lt;br /&gt;
|channelaftertouch&lt;br /&gt;
|cat&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Channel after touch event&lt;br /&gt;
|-&lt;br /&gt;
|pitchbend&lt;br /&gt;
|pb&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Pitch bend event&lt;br /&gt;
|-&lt;br /&gt;
|programchange&lt;br /&gt;
|pc&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Program change event&lt;br /&gt;
|-&lt;br /&gt;
|continuouscontrollerdata&lt;br /&gt;
|ccd&lt;br /&gt;
|controllernuber:&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Continuous controller event with the given [&#039;&#039;controllernumber&#039;&#039;]&lt;br /&gt;
|-&lt;br /&gt;
|removecc&lt;br /&gt;
|rmc&lt;br /&gt;
|controllernuber&lt;br /&gt;
|Removes the entry associated with the MIDI continuous controller even &#039;&#039;controllernumber&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|defaults&lt;br /&gt;
|d&lt;br /&gt;
| -&lt;br /&gt;
|Reverts the current configuration to default &#039;&#039;commands&#039;&#039;, values and CCs&lt;br /&gt;
|-&lt;br /&gt;
|receivechannel&lt;br /&gt;
|rc&lt;br /&gt;
|channel&lt;br /&gt;
|Sets the MIDI receive channel of the current configuration. 1-16 sets specific channel, any other value for OMNI&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;pluginhandler&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The Ekdahl FAR allows for &#039;&#039;plugins&#039;&#039;. These are &#039;&#039;modules&#039;&#039; that can trigger certain &#039;&#039;command strings&#039;&#039; to be executed either periodically or triggered by an incoming &#039;&#039;command&#039;&#039;. Further explanation of the given &#039;&#039;plugins&#039;&#039; is given below. The various &#039;&#039;plugins&#039;&#039; are handled by the &amp;quot;pluginhandler&amp;quot;-&#039;&#039;module&#039;&#039;, the different &#039;&#039;plugin modules&#039;&#039; are identified by their own unique &#039;&#039;ID&#039;&#039;. The &amp;quot;pluginhandler&amp;quot;-&#039;&#039;module&#039;&#039; it has the following &#039;&#039;commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|add&lt;br /&gt;
|a&lt;br /&gt;
|pluginid&lt;br /&gt;
|Add plugin with the given ID&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|pluginid:index&lt;br /&gt;
|Remove plugin with the given ID and index&lt;br /&gt;
|-&lt;br /&gt;
|count&lt;br /&gt;
|c&lt;br /&gt;
|(pluginid)&lt;br /&gt;
|Return the number of plugins of the given type, if none is given it returns all plugins&lt;br /&gt;
|}&lt;br /&gt;
The number of available &#039;&#039;plugins&#039;&#039; will differ from time to time as the &#039;&#039;plugin system&#039;&#039; has been purposefully designed to allow for anyone to write and add their own &#039;&#039;plugins&#039;&#039;. As of the current writing (2026-06-14) the number of &amp;lt;u&amp;gt;possible&amp;lt;/u&amp;gt; &#039;&#039;plugin modules&#039;&#039; that &amp;lt;u&amp;gt;can&amp;lt;/u&amp;gt; exist under the &amp;quot;pluginhandler&amp;quot;-&#039;&#039;module&#039;&#039; are&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|lfo&lt;br /&gt;
|lfo&lt;br /&gt;
|-&lt;br /&gt;
|ahdsr&lt;br /&gt;
|ahdsr&lt;br /&gt;
|-&lt;br /&gt;
|numbermap&lt;br /&gt;
|map&lt;br /&gt;
|-&lt;br /&gt;
|multiple&lt;br /&gt;
|mlt&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;lfo&amp;quot;-&#039;&#039;plugin module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;lfo&amp;quot;-&#039;&#039;plugin module&#039;&#039; works like regular &amp;lt;u&amp;gt;low frequency oscillator&amp;lt;/u&amp;gt; in that it generates a given &#039;&#039;waveform&#039;&#039; with a given &#039;&#039;frequency&#039;&#039; at a certain &#039;&#039;amplitude&#039;&#039;. In the Ekdahl FAR the distinguishing factors are that besides the common &#039;&#039;frequency, amplitude&#039;&#039; and &#039;&#039;waveform&#039;&#039; parameters, it also requires the use of a &#039;&#039;update rate&#039;&#039; and &#039;&#039;target&#039;&#039; parameter. The &#039;&#039;update rate&#039;&#039; sets how often the current position of the LFO is sampled (aka how often it peeks in on where the LFO is in its waveform transition at the moment), and each time that happens, the &#039;&#039;target commands&#039;&#039; are outputted to the instrument.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Lets set the &#039;&#039;waveform&#039;&#039; to &amp;quot;triangle&amp;quot;, the &#039;&#039;amplitude&#039;&#039; to 65535 (max), the &#039;&#039;frequency&#039;&#039; to 1Hz (1 full waveform per second), the &#039;&#039;update rate&#039;&#039; to 10mS and the target to &amp;quot;bw.hsh.sh:lfoout&amp;quot;.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Knaadmin</name></author>
	</entry>
	<entry>
		<id>http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_reference_V1.1&amp;diff=1684</id>
		<title>The Ekdahl FAR - Command reference V1.1</title>
		<link rel="alternate" type="text/html" href="http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_reference_V1.1&amp;diff=1684"/>
		<updated>2026-06-14T08:06:05Z</updated>

		<summary type="html">&lt;p&gt;Knaadmin: /* The &amp;quot;lfo&amp;quot;-plugin module */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
The Ekdahl FAR V1.1 introduces the concept of &#039;&#039;modules&#039;&#039;. A &#039;&#039;module&#039;&#039; can contain any number of &#039;&#039;commands&#039;&#039; as well as other &#039;&#039;modules&#039;&#039;. Furthermore any number of &#039;&#039;modules&#039;&#039; of the same type can exist within a context, these are addressed using classic C-style array &#039;&#039;indexing&#039;&#039; with the help of brackets (&amp;quot;[ ]&amp;quot;). Extending on the classic usage, multiple &#039;&#039;indexes&#039;&#039; can be addressed simultaneously by either comma-separating the objects (&amp;quot;[0,3,4]&amp;quot;) and using &#039;&#039;ranges&#039;&#039; (&amp;quot;[3-6]&amp;quot;). &#039;&#039;Modules&#039;&#039; can be either &#039;&#039;internal&#039;&#039; or &#039;&#039;external&#039;&#039;, meaning that they may all physically exist within a single hardware object, or they can be be remote-controlled devices. From a user perspective this however makes no difference as they will appear the same.&lt;br /&gt;
&lt;br /&gt;
While all &#039;&#039;modules&#039;&#039; have their own set of &#039;&#039;commands&#039;&#039;, there are certain &#039;&#039;commands&#039;&#039; that all &#039;&#039;modules&#039;&#039; &amp;lt;u&amp;gt;must&amp;lt;/u&amp;gt; implement and can thus be accessed anywhere within the &#039;&#039;module hierarchy.&#039;&#039; There are also &#039;&#039;base commands&#039;&#039; that always exist within any given FAR ecosystem as well as product-specific &#039;&#039;base commands&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Ubiquitous commands ==&lt;br /&gt;
The &#039;&#039;module commands&#039;&#039; that are &amp;lt;u&amp;gt;required&amp;lt;/u&amp;gt; to be implemented in &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; &#039;&#039;modules&#039;&#039; and that can thus be accessed from anywhere are&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|list&lt;br /&gt;
|ls&lt;br /&gt;
|hidden/h:modules/m:commands/c:instances/i:instancecounts/ic:recursive/r&lt;br /&gt;
|Lists all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039; under the current module depending on the parameters given; &#039;hidden&#039; includes normally hidden &#039;&#039;commands&#039;&#039;, &#039;modules&#039; includes any &#039;&#039;submodules&#039;&#039;, &#039;commands&#039; shows &#039;&#039;commands&#039;&#039;, &#039;instances&#039; shows data for each individual instance of a &#039;&#039;module&#039;&#039;, &#039;instancecounts&#039; includes number of instances of each &#039;&#039;module&#039;&#039;, &#039;recursive&#039; lists all child &#039;&#039;modules&#039;&#039; / &#039;&#039;commands&#039;&#039;. No parameters defaults to showing all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039; recursively with instance counts. It doesn&#039;t show per-instance data or hidden commands.&lt;br /&gt;
|-&lt;br /&gt;
|help&lt;br /&gt;
|help&lt;br /&gt;
|recursive/r&lt;br /&gt;
|Shows a brief explanation of all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039;, shows the help for all &#039;&#039;submodules&#039;&#039; as well if &#039;recursive&#039;&lt;br /&gt;
|-&lt;br /&gt;
|dumpdata&lt;br /&gt;
|dump&lt;br /&gt;
|recursive/r&lt;br /&gt;
|Dumps all data saved for the current &#039;&#039;module&#039;&#039;, will list the data of all &#039;&#039;submodules&#039;&#039; as well if &#039;recursive&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Base commands ==&lt;br /&gt;
B&#039;&#039;ase commands&#039;&#039; are &#039;&#039;commands&#039;&#039; that always exist at the root in any implementation of the Ekdahl FAR.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|version&lt;br /&gt;
|ver&lt;br /&gt;
| -&lt;br /&gt;
|Gets the current firmware version&lt;br /&gt;
|-&lt;br /&gt;
|debugprint&lt;br /&gt;
|dp&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;command|usb|hardware|undefined|priority|error|inforequest|expressionparser|debug:1|0&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Turns on or off serial feedback for the given item&lt;br /&gt;
|-&lt;br /&gt;
|requestinfo&lt;br /&gt;
|rqi&lt;br /&gt;
|command&lt;br /&gt;
|Retrives any data saved for a &#039;&#039;command&#039;&#039;, if applicable&lt;br /&gt;
|-&lt;br /&gt;
|saveallparameters&lt;br /&gt;
|sap&lt;br /&gt;
| -&lt;br /&gt;
|Saves all avaliable parameters&lt;br /&gt;
|-&lt;br /&gt;
|loadallparameters&lt;br /&gt;
|lap&lt;br /&gt;
| -&lt;br /&gt;
|Loads all avaliable parameters&lt;br /&gt;
|-&lt;br /&gt;
|resetallparameters&lt;br /&gt;
|rap&lt;br /&gt;
| -&lt;br /&gt;
|Resets all saved parameters&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|rst&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;1|0&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Resets the Ekdahl FAR, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|nick&lt;br /&gt;
|nick&lt;br /&gt;
|name&lt;br /&gt;
|Sets the nickname of this unit&lt;br /&gt;
|-&lt;br /&gt;
|nooperation&lt;br /&gt;
|nop&lt;br /&gt;
| -&lt;br /&gt;
|Do absolutely, positively, nothing. Useful for testing and interfacing with computers, it&#039;s a good way to know that the unit is alive and responding since a &amp;quot;nop&amp;quot; is being returned as a response upon reception.&lt;br /&gt;
|-&lt;br /&gt;
|uservariable&lt;br /&gt;
|uv&lt;br /&gt;
|variable(0-9):value&lt;br /&gt;
|Set user variable 0-9 to &#039;value&#039;&lt;br /&gt;
|-&lt;br /&gt;
|expressionparserevaluate&lt;br /&gt;
|epev&lt;br /&gt;
|expression&lt;br /&gt;
|Evaluates an arithmetric expression and sends back the output, all variables and functions that can be used in any &#039;&#039;command string&#039;&#039; can also be used here. Useful for testing expressions.&lt;br /&gt;
|-&lt;br /&gt;
|ifequal&lt;br /&gt;
|ife&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] EQUALS [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring].&lt;br /&gt;
|-&lt;br /&gt;
|ifgreater&lt;br /&gt;
|ifg&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] &amp;gt; [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring]&lt;br /&gt;
|-&lt;br /&gt;
|ifless&lt;br /&gt;
|ifl&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] &amp;lt; [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring]&lt;br /&gt;
|-&lt;br /&gt;
|freeram&lt;br /&gt;
|ram&lt;br /&gt;
| -&lt;br /&gt;
|Shows free RAM memory&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The base also contains the following &#039;&#039;modules:&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|pluginhandler&lt;br /&gt;
|ph&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The Ekdahl FAR stand alone single string unit ==&lt;br /&gt;
The Ekdahl FAR stand-alone single string unit offers these &#039;&#039;commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|calibrateall&lt;br /&gt;
|ca&lt;br /&gt;
| -&lt;br /&gt;
|Performs all calibration routines on the selected bow, see below for routines performed&lt;br /&gt;
|-&lt;br /&gt;
|calibratebowspeed&lt;br /&gt;
|cbs&lt;br /&gt;
| -&lt;br /&gt;
|Finds the minimum and maximum bow speed of the selected bow&lt;br /&gt;
|-&lt;br /&gt;
|calibratebowpressure&lt;br /&gt;
|cbp&lt;br /&gt;
| -&lt;br /&gt;
|Finds the minimum and maximum bow pressure of the selected bow&lt;br /&gt;
|-&lt;br /&gt;
|calibratemute&lt;br /&gt;
|cmu&lt;br /&gt;
| -&lt;br /&gt;
|Calibrate mute settings&lt;br /&gt;
|-&lt;br /&gt;
|pickupstringfrequency&lt;br /&gt;
|psf&lt;br /&gt;
| -&lt;br /&gt;
|Returns the fundamental tone calculated from the current audio signal if apliccable&lt;br /&gt;
|-&lt;br /&gt;
|pickupaudiopeak&lt;br /&gt;
|pap&lt;br /&gt;
| -&lt;br /&gt;
|Returns the peak amplitude of the current audio signal&lt;br /&gt;
|-&lt;br /&gt;
|pickupaudiorms&lt;br /&gt;
|par&lt;br /&gt;
| -&lt;br /&gt;
|Returns the RMS amplitude of the current audio signal&lt;br /&gt;
|}&lt;br /&gt;
The Ekdahl FAR also contains the following &#039;&#039;modules&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|bowingwheel&lt;br /&gt;
|bw&lt;br /&gt;
|-&lt;br /&gt;
|mute&lt;br /&gt;
|mu&lt;br /&gt;
|-&lt;br /&gt;
|solenoid&lt;br /&gt;
|so&lt;br /&gt;
|-&lt;br /&gt;
|controlbox&lt;br /&gt;
|cb&lt;br /&gt;
|-&lt;br /&gt;
|midiconfigurationhandler&lt;br /&gt;
|mcf&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;Bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; contains everything needed to interface with a single &#039;&#039;bowing wheel&#039;&#039;. Each &#039;&#039;bowing wheel&#039;&#039; has its own harmonic series, pressure actuators and direct hardware interface. It contains the following &#039;&#039;commands&#039;&#039;.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|speedmode&lt;br /&gt;
|sm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Bow motor speed mode, 0 = Automatic and 1 = Manual. Automatic mode means that the bowing wheel will automatically turn off after the &#039;&#039;motor timeout&#039;&#039; has been reached after being put into rest mode&lt;br /&gt;
|-&lt;br /&gt;
|motortimeout&lt;br /&gt;
|mt&lt;br /&gt;
|ms&lt;br /&gt;
|Bow motor shutdown timeout after bow having been put into the rest position&lt;br /&gt;
|-&lt;br /&gt;
|pidenable&lt;br /&gt;
|pe&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets the bow PID on/off&lt;br /&gt;
|-&lt;br /&gt;
|motorfaultcommands&lt;br /&gt;
|mfc&lt;br /&gt;
|commands&lt;br /&gt;
|Commands to execute when a motor fault is tripped - !WARNING! Can ruin your instrument if changed&lt;br /&gt;
|-&lt;br /&gt;
|motoroverpowercommands&lt;br /&gt;
|moc&lt;br /&gt;
|commands&lt;br /&gt;
|Commands to execute when motor is over the power limit - !WARNING! Can ruin your instrument if changed&lt;br /&gt;
|}&lt;br /&gt;
The &#039;&#039;modules&#039;&#039; in the &amp;quot;Bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; are as follows&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|bowpressure&lt;br /&gt;
|bp&lt;br /&gt;
|-&lt;br /&gt;
|dcmotor&lt;br /&gt;
|dcm&lt;br /&gt;
|-&lt;br /&gt;
|pid&lt;br /&gt;
|pid&lt;br /&gt;
|-&lt;br /&gt;
|harmonicserieshandler&lt;br /&gt;
|hsh&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; handles the &#039;&#039;pressure&#039;&#039; of the &#039;&#039;bowing wheel&#039;&#039; against the string. The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|baseline&lt;br /&gt;
|ba&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure baseline, modulation is added to this point upward. Typically this is set with a knob on the &#039;&#039;control box&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|modifier&lt;br /&gt;
|mo&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure modulation, added to the baseline&lt;br /&gt;
|-&lt;br /&gt;
|rest&lt;br /&gt;
|rs&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the bow pressure in the &#039;&#039;rest&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|engage&lt;br /&gt;
|en&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the bow pressure in the &#039;&#039;engage&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|stallpressure&lt;br /&gt;
|sp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure stall/maximum position, this parameter is set using &#039;&#039;hardware positioning&#039;&#039; and is used as the absolute maximum for baseline and modifier combiner&lt;br /&gt;
|-&lt;br /&gt;
|engagepressure&lt;br /&gt;
|ep&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure touch/minimum position, this parameter is set using &#039;&#039;hardware position&#039;&#039; and is used as the starting point for when both the baseline and modifier is set to zero&lt;br /&gt;
|-&lt;br /&gt;
|restpressure&lt;br /&gt;
|rp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure rest position, this parameter is set using &#039;&#039;hardware positioning&#039;&#039; and is typically set to a point just below the string where it does not touch at all. The purpose of this is because while the actual hardware might be able to make the bow go even lower, that position might be far enough from the string that once &#039;&#039;engaged&#039;&#039; the bow may have so far to travel that there is perceptible &#039;&#039;latency&#039;&#039;.&lt;br /&gt;
|-&lt;br /&gt;
|engagespeed&lt;br /&gt;
|es&lt;br /&gt;
|1- ~100&lt;br /&gt;
|Bow pressure movement speed when engaging or disengaging&lt;br /&gt;
|-&lt;br /&gt;
|modulationspeed&lt;br /&gt;
|ms&lt;br /&gt;
|0.1 - 10&lt;br /&gt;
|Bow pressure movement speed while engaged&lt;br /&gt;
|-&lt;br /&gt;
|hold&lt;br /&gt;
|hd&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets bow hold (infinite sustain) on/off, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|home&lt;br /&gt;
|hm&lt;br /&gt;
| -&lt;br /&gt;
|Homing bow, used at startup and in case of the bow loosing position&lt;br /&gt;
|-&lt;br /&gt;
|tmcinfo&lt;br /&gt;
|tmi&lt;br /&gt;
| -&lt;br /&gt;
|Request statistical information from the TMC2209 stepper motor driver&lt;br /&gt;
|}&lt;br /&gt;
Note that the &amp;quot;stall&amp;quot;, &amp;quot;engage&amp;quot; and &amp;quot;rest&amp;quot;-pressure positions mention something called &#039;&#039;hardware position&#039;&#039;. This means the entire available movement of the &#039;&#039;bowing jack&#039;&#039;. Because the very bottom and top end of the movement might not be musically useful and may even harm the instrument, the &amp;quot;baseline&amp;quot; and &amp;quot;modifier&amp;quot; commands &#039;&#039;parameter&#039;&#039;s are scaled depending on these settings.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;engage&amp;quot; and &amp;quot;modulation&amp;quot;-speed settings sets how fast the stepper motor that drives the &#039;&#039;pressure&#039;&#039; moves depending on whether the &#039;&#039;bowing jack&#039;&#039; is set to &#039;&#039;engage&#039;&#039; or not. The idea here is that while wanting to be able to minimize &#039;&#039;latency&#039;&#039; by &#039;&#039;engaging&#039;&#039; and &#039;&#039;disengaging&#039;&#039; from the string as quickly as possible, dynamic changes in the &#039;&#039;pressure&#039;&#039; while playing benefits from much smoother movements as the &#039;&#039;bowing wheel&#039;&#039; takes some time to catch up to varying amounts of friction.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; contains one or more of the following &#039;&#039;modules&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|actuatorhandler&lt;br /&gt;
|ah&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;actuatorhandler&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The concept of &amp;quot;actuators&amp;quot; came up as it is possible to have &#039;&#039;bowing wheels&#039;&#039; of different sizes and wanting to be able to switch quickly in between them, perhaps during mid-performance. Because a differently sized wheel will require different values for the above mentioned &amp;quot;stall&amp;quot;, &amp;quot;engage&amp;quot; and &amp;quot;reset&amp;quot;-&#039;&#039;pressure&#039;&#039;, each &#039;&#039;actuator&#039;&#039; stores these values. Instead of having to manually change the previously mentioned values, simply selecting a new &#039;&#039;actuator&#039;&#039; will automatically load the values. The &amp;quot;actuatorhandler&amp;quot;-&#039;&#039;module&#039;&#039; is the handler of one or more &amp;quot;actuator&amp;quot;-&#039;&#039;modules&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;commands&#039;&#039; of the &amp;quot;acuatorhandler&amp;quot;-&#039;&#039;module&#039;&#039; are as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|add&lt;br /&gt;
|a&lt;br /&gt;
|(name):(rest:engage:stall)&lt;br /&gt;
|Add new actuator with the given name and parameters&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|actuatornumber&lt;br /&gt;
|Remove bow actuator [actuatornumber]&lt;br /&gt;
|-&lt;br /&gt;
|count&lt;br /&gt;
|c&lt;br /&gt;
| -&lt;br /&gt;
|Returns the amount of saved bow actuators&lt;br /&gt;
|}&lt;br /&gt;
The &amp;quot;actuatorhandler&amp;quot;-&#039;&#039;module&#039;&#039; contains one or more of&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|actuator&lt;br /&gt;
|ac&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;actuator&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;actuator&amp;quot;-&#039;&#039;module&#039;&#039; contains the following commands&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|[index]&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|Selects the given actuator&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Sets the actuator name&lt;br /&gt;
|-&lt;br /&gt;
|data&lt;br /&gt;
|da&lt;br /&gt;
|name:rest:engage:stall&lt;br /&gt;
|Sets the actuator name, rest, engage and stall &#039;&#039;pressure&#039;&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;dcmotor&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;dcmotor&amp;quot;-&#039;&#039;module&#039;&#039; handles the direct &amp;lt;u&amp;gt;raw&amp;lt;/u&amp;gt; control of the &#039;&#039;bowing motor&#039;&#039; and handles the reporting back of the current speed. It has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|run&lt;br /&gt;
|ru&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Turns the motor off/on&lt;br /&gt;
|-&lt;br /&gt;
|pwm&lt;br /&gt;
|pw&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor direct power in 16-bit PWM values, requires that the &#039;&#039;PID&#039;&#039; is turned off&lt;br /&gt;
|-&lt;br /&gt;
|voltage&lt;br /&gt;
|vo&lt;br /&gt;
|~2 - 10V&lt;br /&gt;
|Sets the voltage of the regulator powering the motor. Changes here can make the motor more responsive to certain frequencies but will also affect how well the &#039;&#039;PID&#039;&#039; works. !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|current&lt;br /&gt;
|cu&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor reported current use&lt;br /&gt;
|-&lt;br /&gt;
|currentlimit&lt;br /&gt;
|cl&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor current limit (A)- !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|powerlimit&lt;br /&gt;
|pl&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor power limit (W) - !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|frequency&lt;br /&gt;
|fq&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor reported frequency&lt;br /&gt;
|-&lt;br /&gt;
|emergencystop&lt;br /&gt;
|es&lt;br /&gt;
|ms (0-65535)&lt;br /&gt;
|Immediately stops the bowing motor and doesn&#039;t allow it to start again until the cool down period given in the first argument has lapsed (milliseconds)&lt;br /&gt;
|-&lt;br /&gt;
|minpwm&lt;br /&gt;
|ip&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor minimum PWM (for calibration)&lt;br /&gt;
|-&lt;br /&gt;
|maxpwm&lt;br /&gt;
|xp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor maximum PWM (for calibration)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;pidcontroller&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;pidcontroller&amp;quot;-&#039;&#039;module&#039;&#039; is responsible for keeping the &amp;quot;dcmotor&amp;quot;-&#039;&#039;module&#039;&#039; at a certain frequency (given in Hertz). It takes the output of the motor frequency measurement and feeds it a PWM value that tries to make the speed constant regardless of the friction that the motor is enduring. To learn more about PID Controllers please see this [[wikipedia:PID_controller|wikipedia article]]. The &#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|targetfrequency&lt;br /&gt;
|tf&lt;br /&gt;
|hertz&lt;br /&gt;
|Sets the PID target frequency&lt;br /&gt;
|-&lt;br /&gt;
|ki&lt;br /&gt;
|ki&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Ki parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|kp&lt;br /&gt;
|kp&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Kp parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|kd&lt;br /&gt;
|kd&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Kd parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|integratorerror&lt;br /&gt;
|ie&lt;br /&gt;
|float&lt;br /&gt;
|Sets the lower threshold of error values for the PID integrator to ignore&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|re&lt;br /&gt;
| -&lt;br /&gt;
|Resets the PID integrator and derivative&lt;br /&gt;
|-&lt;br /&gt;
|maxerror&lt;br /&gt;
|xe&lt;br /&gt;
|float&lt;br /&gt;
|Maximum error to correct in each PID loop, essentially sets acceleration&lt;br /&gt;
|-&lt;br /&gt;
|peakerror&lt;br /&gt;
|pe&lt;br /&gt;
|float&lt;br /&gt;
|Get latest PID peak error&lt;br /&gt;
|-&lt;br /&gt;
|motorspeedmax&lt;br /&gt;
|msx&lt;br /&gt;
|Hertz&lt;br /&gt;
|Bow motor maximum speed limit&lt;br /&gt;
|-&lt;br /&gt;
|motorspeedmin&lt;br /&gt;
|msi&lt;br /&gt;
|Hertz&lt;br /&gt;
|Bow motor minimum speed limit&lt;br /&gt;
|-&lt;br /&gt;
|measuretimetotarget&lt;br /&gt;
|mtt&lt;br /&gt;
|Hertz&lt;br /&gt;
|Measure the time it takes to change from the current frequency to the target frequency, for testing purposes&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; is responsible for sending frequency data to the &amp;quot;pid&amp;quot;-&#039;&#039;module&#039;&#039;. It handles calculating the correct frequency of the &#039;&#039;bowing wheel&#039;&#039; according to the selected &#039;&#039;harmonic&#039;&#039; and &#039;&#039;harmonic shift&#039;&#039; per the currently selected &#039;&#039;harmonic series&#039;&#039;. The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|fundamental&lt;br /&gt;
|fu&lt;br /&gt;
|Hertz&lt;br /&gt;
|The fundamental frequency of the string, all harmonics are calculated from this number&lt;br /&gt;
|-&lt;br /&gt;
|harmonic&lt;br /&gt;
|h&lt;br /&gt;
|int&lt;br /&gt;
|Selects the harmonic number to set the &#039;&#039;bowing wheel&#039;&#039; to. A ratio is taken from the given &#039;&#039;harmonic&#039;&#039; in the current &#039;&#039;harmonic series&#039;&#039;, the ratio is then multiplied by the &#039;&#039;fundamental frequency&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|harmonicadd&lt;br /&gt;
|ha&lt;br /&gt;
|int&lt;br /&gt;
|This number is added to the current harmonic&lt;br /&gt;
|-&lt;br /&gt;
|harmonicbase&lt;br /&gt;
|hb&lt;br /&gt;
|int&lt;br /&gt;
|Same as harmonic but where the harmonic number is based on a MIDI note given by basenote&lt;br /&gt;
|-&lt;br /&gt;
|basenote&lt;br /&gt;
|bn&lt;br /&gt;
|0-127&lt;br /&gt;
|Sets the MIDI base note of the &#039;&#039;bowing wheel&#039;&#039;, used in conjunction with &amp;quot;harmonicbase&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|shift&lt;br /&gt;
|sh&lt;br /&gt;
| -32767 - 32767&lt;br /&gt;
|Sets shift from the currently playing harmonic where 32767 equals the entire harmonic shift range shifted up&lt;br /&gt;
|-&lt;br /&gt;
|shiftrange&lt;br /&gt;
|sr&lt;br /&gt;
|0-36&lt;br /&gt;
|Set the number of harmonic numbers that constitutes an entire harmonic shift&lt;br /&gt;
|-&lt;br /&gt;
|shift5&lt;br /&gt;
|sh5&lt;br /&gt;
| -32767 - 32767&lt;br /&gt;
|Sets the shift from the currently playing harmonic over 5 octaves where 32767 equals 5 octaves shift up from the fundamental&lt;br /&gt;
|-&lt;br /&gt;
|add&lt;br /&gt;
|a&lt;br /&gt;
|(name):(ratios)&lt;br /&gt;
|Add a new series with the given name and parameters&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|series&lt;br /&gt;
|Remove the series given and shift any series accordingly. Cannot remove all series&lt;br /&gt;
|-&lt;br /&gt;
|count&lt;br /&gt;
|c&lt;br /&gt;
| -&lt;br /&gt;
|Returns the number of harmonic series in the list and their IDs&lt;br /&gt;
|}&lt;br /&gt;
The &amp;quot;harmonicserieshandler&amp;quot;-module contains at the very least ONE harmonic series, by default it contains two: one for equal temperament and one for just intonation. The current series can be selected by simply indexing the &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; without a &#039;&#039;command&#039;&#039;, e.g. &amp;quot;harmonicserieshandler.harmonicseries[1]&amp;quot;. To be consistent, these are the &#039;&#039;modules&#039;&#039; in the &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|harmonicseries&lt;br /&gt;
|hs&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; contains any number of &#039;&#039;ratios&#039;&#039; that comprises a scale, ratios are given in a standard format where a ratio of &amp;quot;1&amp;quot; is equal to the fundamental, &amp;quot;2&amp;quot; would be one octave up etc. A standard &#039;&#039;harmonic series&#039;&#039; contains 12 ratios following a just intonation scheme. The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; will automatically adapt to the currently selected &#039;&#039;harmonic series&#039;&#039; length, whether it&#039;s a standard 12-tone scale, some kinda 3-tone scale or a full on bananas 53-tone scale. The &#039;&#039;commands&#039;&#039; of the &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; is as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|[index]&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
|Sets the currently selected &#039;&#039;harmonic Series&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Sets the name of the &#039;&#039;harmonic series&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|data&lt;br /&gt;
|da&lt;br /&gt;
|name:ratios&lt;br /&gt;
|Gets / sets all data for the &#039;&#039;harmonic series&#039;&#039; in the given slot with an arbitrary &#039;&#039;name&#039;&#039; as the first &#039;&#039;parameter&#039;&#039;. The length of the series is simply set to the amount of ratios given&lt;br /&gt;
|-&lt;br /&gt;
|ratio&lt;br /&gt;
|r&lt;br /&gt;
|harmonic:ratio&lt;br /&gt;
|Sets the ratio of the given harmonic in current &#039;&#039;harmonic series&#039;&#039;, will increase the list size if needed to address the harmonic&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|harmonic&lt;br /&gt;
|Remove the harmonic ratio given in the current series and shift any ratios accordingly. Cannot remove all ratios&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;mute&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;mute&amp;quot;-&#039;&#039;module&#039;&#039; works very similarly to the &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; in that it controls a stepper motor with some software limits in place in order to press the mute against the string. The &#039;&#039;commands&#039;&#039; are as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|setposition&lt;br /&gt;
|sp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set mute position&lt;br /&gt;
|-&lt;br /&gt;
|fullmute&lt;br /&gt;
|fm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the mute in &#039;&#039;full mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|halfmute&lt;br /&gt;
|hm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the mute in &#039;&#039;half mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|rest&lt;br /&gt;
|rs&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Put the mute in the &#039;&#039;rest&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|savefull&lt;br /&gt;
|sf&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Save the current mute position as the &#039;&#039;full mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|savehalf&lt;br /&gt;
|sh&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Save the current mute position as the &#039;&#039;half mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|saverest&lt;br /&gt;
|sr&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Save the current mute position as the &#039;&#039;rest&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|fullmuteposition&lt;br /&gt;
|fmp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;full mute&#039;&#039; position according to the &#039;&#039;hardware position&#039;&#039; given&lt;br /&gt;
|-&lt;br /&gt;
|halfmuteposition&lt;br /&gt;
|hmp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;half mute&#039;&#039; position according to the &#039;&#039;hardware position&#039;&#039; given&lt;br /&gt;
|-&lt;br /&gt;
|restposition&lt;br /&gt;
|rp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;rest&#039;&#039; position according to the &#039;&#039;hardware position&#039;&#039; given&lt;br /&gt;
|-&lt;br /&gt;
|sustain&lt;br /&gt;
|su&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets the sustain off/on, this will keep the mute in the &#039;&#039;rest&#039;&#039; position even if a &amp;quot;fullmute&amp;quot;-&#039;&#039;command&#039;&#039; is given, lasts until &amp;quot;sustain&amp;quot; is set to &amp;quot;0&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
|backoff&lt;br /&gt;
|bo&lt;br /&gt;
|0-65535&lt;br /&gt;
|Setting the time that the mute stays in the mutefullmute position before automatically going into rest, set in mS. A value of &amp;quot;0&amp;quot; disables backoff. This is used because if the mute is not backing off until something is attempted to be played, the backing-off time will either introduce &#039;&#039;latency&#039;&#039; or the string will be initially partially muted&lt;br /&gt;
|-&lt;br /&gt;
|home&lt;br /&gt;
|hm&lt;br /&gt;
| -&lt;br /&gt;
|Home mute, used during initialization and if the mute were to loose position&lt;br /&gt;
|-&lt;br /&gt;
|hardwareposition&lt;br /&gt;
|hwp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;hardware position&#039;&#039; of the mute instead of scaling it over the &#039;&#039;full mute&#039;&#039; and &#039;&#039;rest&#039;&#039; positions. Mainly used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|completetask&lt;br /&gt;
|cpt&lt;br /&gt;
| -&lt;br /&gt;
|Requests a callback when the current operation is finished. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|autocorrect&lt;br /&gt;
|ac&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Enables auto correct positioning that uses the homing sensor to correct positioning on the fly. EXPERIMENTAL&lt;br /&gt;
|-&lt;br /&gt;
|homingsensed&lt;br /&gt;
|hms&lt;br /&gt;
| -&lt;br /&gt;
|Requests whether the homing sensor is currently active or not. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|movedirection&lt;br /&gt;
|md&lt;br /&gt;
| -&lt;br /&gt;
|Requests the current direction of movement (0 Forward, 1 Reverse). Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|currentstep&lt;br /&gt;
|cs&lt;br /&gt;
| -&lt;br /&gt;
|Requests the current step. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|homingpoint&lt;br /&gt;
|hmp&lt;br /&gt;
|edgedirection&lt;br /&gt;
|Requests the given homing point. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|homingstage&lt;br /&gt;
|hms&lt;br /&gt;
| -&lt;br /&gt;
|Requests the current homing stage (UNHOMED, HOMED, FIRSTHOMINGRISING, SECONDHOMINGFALLING, SECONDHOMINGRISING, FIRSTHOMINGFALLING, MOVEPASTHOMESWITCH, MOVETOHOMESWITCH, GOTOOFFSET). Only used internally by other &#039;&#039;modules.&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|tmcinfo&lt;br /&gt;
|tmi&lt;br /&gt;
| -&lt;br /&gt;
|Request statistical information from the TMC2209 stepper motor driver&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;solenoid&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;solenoid&amp;quot;-&#039;&#039;module&#039;&#039; currently controls the &#039;&#039;hammer&#039;&#039; of the Ekdahl FAR. Due to the fact that the very same &#039;&#039;module&#039;&#039; could be used for anything that uses a striking &#039;&#039;solenoid&#039;&#039; it was named as such. It has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|engage&lt;br /&gt;
|en&lt;br /&gt;
|0-65535&lt;br /&gt;
|Engages the solenoid using the first parameter as the force&lt;br /&gt;
|-&lt;br /&gt;
|rest&lt;br /&gt;
|rs&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Forces the solenoid to its rest position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|maxforce&lt;br /&gt;
|xf&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set solenoid maximum usable force&lt;br /&gt;
|-&lt;br /&gt;
|minforce&lt;br /&gt;
|if&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set solenoid minimum usable force&lt;br /&gt;
|-&lt;br /&gt;
|forcemultiplier&lt;br /&gt;
|fm&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set solenoid force multiplier, useful for scaling of all incoming &amp;quot;engage&amp;quot;-&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|engageduration&lt;br /&gt;
|ed&lt;br /&gt;
|uS&lt;br /&gt;
|Sets the duration of the solenoid hit in uS, if a value of 0 is set the solenoid will not disengage until a rest command has been given. WARNING!! HAVING THE SOLENOID ON FOR A SPAN OF SECONDS COULD DESTROY THE CIRCUITRY!!&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;controlbox&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;controlbox&amp;quot;-&#039;&#039;module&#039;&#039; communicates with an external &#039;&#039;control box&#039;&#039; and will issue associated &#039;&#039;commands&#039;&#039; whenever new values are read on the ADC-converters. It handles averaging and does some noise-cancellation functions on the values as well. The &#039;&#039;commands&#039;&#039; are:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|harmonic&lt;br /&gt;
|har&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the harmonic knob or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|harmonicshift&lt;br /&gt;
|has&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the harmonic shift modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|finetune&lt;br /&gt;
|fin&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the fine tune knob changes&lt;br /&gt;
|-&lt;br /&gt;
|pressure&lt;br /&gt;
|pre&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the pressure knob or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|mute&lt;br /&gt;
|mut&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the mute knob or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|hammerscale&lt;br /&gt;
|hms&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the hammer scale knob changes&lt;br /&gt;
|-&lt;br /&gt;
|gate&lt;br /&gt;
|gt&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the gate switch or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|hammertrig&lt;br /&gt;
|hmt&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the hammer trigger modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|controldefaults&lt;br /&gt;
|cde&lt;br /&gt;
| -&lt;br /&gt;
|Reverts all ADC command strings to default values&lt;br /&gt;
|-&lt;br /&gt;
|datareturn&lt;br /&gt;
|dr&lt;br /&gt;
|channel:value&lt;br /&gt;
|Sent when a new value is presented on one of the ADC channels, cannot be invoked. Triggers the commands associated with the channel&lt;br /&gt;
|-&lt;br /&gt;
|adcsetting&lt;br /&gt;
|adcs&lt;br /&gt;
|channel : averages : interrupterrorthreshold : continuouserrorthreshold : continuoustimeout&lt;br /&gt;
|Sets ADC settings for a given channel. Averages are the number of samples to average, interruptthreshold is how much the value must change in order to issue a new value change event. continuousthreshold is how much the value must change when a previous change has already been recorded within the timespan of continuoustimeout&lt;br /&gt;
|-&lt;br /&gt;
|testadclatency&lt;br /&gt;
|tal&lt;br /&gt;
|0-65535&lt;br /&gt;
|Start a ADC latency test&lt;br /&gt;
|-&lt;br /&gt;
|testadclatencyreturn&lt;br /&gt;
|talr&lt;br /&gt;
| -&lt;br /&gt;
|Return from latency test&lt;br /&gt;
|-&lt;br /&gt;
|testadcminmax&lt;br /&gt;
|tix&lt;br /&gt;
|channel&lt;br /&gt;
|Test min/max value for a given channel and resets the counter&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;midiconfigurationhandler&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;midiconfigurationhandler&amp;quot;-&#039;&#039;module&#039;&#039; handles a number of &amp;quot;midiconfiguration&amp;quot;-&#039;&#039;modules&#039;&#039;. It has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|allnotesoff&lt;br /&gt;
|ano&lt;br /&gt;
| -&lt;br /&gt;
|Clears the entire buffer of MIDI notes held&lt;br /&gt;
|-&lt;br /&gt;
|add&lt;br /&gt;
|a&lt;br /&gt;
|name&lt;br /&gt;
|Adds a new MIDI configuration with the given name&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|int&lt;br /&gt;
|Remove the specified MIDI configuration&lt;br /&gt;
|-&lt;br /&gt;
|count&lt;br /&gt;
|c&lt;br /&gt;
| -&lt;br /&gt;
|Returns the number of MIDI configurations&lt;br /&gt;
|}&lt;br /&gt;
It contains one or more of the following&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|midiconfiguration&lt;br /&gt;
|mc&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;midiconfiguration&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
A &amp;quot;midiconfiguration&amp;quot;-&#039;&#039;module&#039;&#039; handles the reception of &#039;&#039;MIDI messages&#039;&#039; and will output the associated &#039;&#039;commands&#039;&#039; to the instrument internally. The commands are as follows&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|[index]&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
|Sets the currently selected MIDI configuration&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Set the name of the MIDI configuration&lt;br /&gt;
|-&lt;br /&gt;
|noteon&lt;br /&gt;
|non&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Note On event&lt;br /&gt;
|-&lt;br /&gt;
|noteoff&lt;br /&gt;
|nof&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Note Off event&lt;br /&gt;
|-&lt;br /&gt;
|polyaftertouch&lt;br /&gt;
|pat&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Polyphonic after touch event&lt;br /&gt;
|-&lt;br /&gt;
|channelaftertouch&lt;br /&gt;
|cat&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Channel after touch event&lt;br /&gt;
|-&lt;br /&gt;
|pitchbend&lt;br /&gt;
|pb&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Pitch bend event&lt;br /&gt;
|-&lt;br /&gt;
|programchange&lt;br /&gt;
|pc&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Program change event&lt;br /&gt;
|-&lt;br /&gt;
|continuouscontrollerdata&lt;br /&gt;
|ccd&lt;br /&gt;
|controllernuber:&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Continuous controller event with the given [&#039;&#039;controllernumber&#039;&#039;]&lt;br /&gt;
|-&lt;br /&gt;
|removecc&lt;br /&gt;
|rmc&lt;br /&gt;
|controllernuber&lt;br /&gt;
|Removes the entry associated with the MIDI continuous controller even &#039;&#039;controllernumber&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|defaults&lt;br /&gt;
|d&lt;br /&gt;
| -&lt;br /&gt;
|Reverts the current configuration to default &#039;&#039;commands&#039;&#039;, values and CCs&lt;br /&gt;
|-&lt;br /&gt;
|receivechannel&lt;br /&gt;
|rc&lt;br /&gt;
|channel&lt;br /&gt;
|Sets the MIDI receive channel of the current configuration. 1-16 sets specific channel, any other value for OMNI&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;pluginhandler&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The Ekdahl FAR allows for &#039;&#039;plugins&#039;&#039;. These are &#039;&#039;modules&#039;&#039; that can trigger certain &#039;&#039;command strings&#039;&#039; to be executed either periodically or triggered by an incoming &#039;&#039;command&#039;&#039;. Further explanation of the given &#039;&#039;plugins&#039;&#039; is given below. The various &#039;&#039;plugins&#039;&#039; are handled by the &amp;quot;pluginhandler&amp;quot;-&#039;&#039;module&#039;&#039;, the different &#039;&#039;plugin modules&#039;&#039; are identified by their own unique &#039;&#039;ID&#039;&#039;. The &amp;quot;pluginhandler&amp;quot;-&#039;&#039;module&#039;&#039; it has the following &#039;&#039;commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|add&lt;br /&gt;
|a&lt;br /&gt;
|pluginid&lt;br /&gt;
|Add plugin with the given ID&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|pluginid:index&lt;br /&gt;
|Remove plugin with the given ID and index&lt;br /&gt;
|-&lt;br /&gt;
|count&lt;br /&gt;
|c&lt;br /&gt;
|(pluginid)&lt;br /&gt;
|Return the number of plugins of the given type, if none is given it returns all plugins&lt;br /&gt;
|}&lt;br /&gt;
The number of available &#039;&#039;plugins&#039;&#039; will differ from time to time as the &#039;&#039;plugin system&#039;&#039; has been purposefully designed to allow for anyone to write and add their own &#039;&#039;plugins&#039;&#039;. As of the current writing (2026-06-14) the number of &amp;lt;u&amp;gt;possible&amp;lt;/u&amp;gt; &#039;&#039;plugin modules&#039;&#039; that &amp;lt;u&amp;gt;can&amp;lt;/u&amp;gt; exist under the &amp;quot;pluginhandler&amp;quot;-&#039;&#039;module&#039;&#039; are&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|lfo&lt;br /&gt;
|lfo&lt;br /&gt;
|-&lt;br /&gt;
|ahdsr&lt;br /&gt;
|ahdsr&lt;br /&gt;
|-&lt;br /&gt;
|numbermap&lt;br /&gt;
|map&lt;br /&gt;
|-&lt;br /&gt;
|multiple&lt;br /&gt;
|mlt&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;lfo&amp;quot;-&#039;&#039;plugin module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;lfo&amp;quot;-&#039;&#039;plugin module&#039;&#039; works like regular &amp;lt;u&amp;gt;low frequency oscillator&amp;lt;/u&amp;gt; in that it generates a given &#039;&#039;waveform&#039;&#039; with a given &#039;&#039;frequency&#039;&#039; at a certain &#039;&#039;amplitude&#039;&#039;. In the Ekdahl FAR the distinguishing factors are that besides the common &#039;&#039;frequency, amplitude&#039;&#039; and &#039;&#039;waveform&#039;&#039; parameters, it also requires the use of a &#039;&#039;update rate&#039;&#039; and &#039;&#039;target&#039;&#039; parameter. The &#039;&#039;update rate&#039;&#039; sets how often the current position of the LFO is sampled (aka how often it peeks in on where the LFO is in its waveform transition at the moment), and each time that happens, the &#039;&#039;target commands&#039;&#039; are outputted to the instrument.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example:&#039;&#039;&#039;&lt;br /&gt;
 Lets set the &#039;&#039;waveform&#039;&#039; to &amp;quot;triangle&amp;quot;, the &#039;&#039;amplitude&#039;&#039; to 65535 (max), the &#039;&#039;frequency&#039;&#039; to 1Hz (1 full waveform per second), the &#039;&#039;update rate&#039;&#039; to 10mS and the target to &amp;quot;bw.hsh.sh:lfoout&amp;quot;.&lt;/div&gt;</summary>
		<author><name>Knaadmin</name></author>
	</entry>
	<entry>
		<id>http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_reference_V1.1&amp;diff=1683</id>
		<title>The Ekdahl FAR - Command reference V1.1</title>
		<link rel="alternate" type="text/html" href="http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_reference_V1.1&amp;diff=1683"/>
		<updated>2026-06-14T07:51:17Z</updated>

		<summary type="html">&lt;p&gt;Knaadmin: /* The &amp;quot;pluginhandler&amp;quot;-module */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
The Ekdahl FAR V1.1 introduces the concept of &#039;&#039;modules&#039;&#039;. A &#039;&#039;module&#039;&#039; can contain any number of &#039;&#039;commands&#039;&#039; as well as other &#039;&#039;modules&#039;&#039;. Furthermore any number of &#039;&#039;modules&#039;&#039; of the same type can exist within a context, these are addressed using classic C-style array &#039;&#039;indexing&#039;&#039; with the help of brackets (&amp;quot;[ ]&amp;quot;). Extending on the classic usage, multiple &#039;&#039;indexes&#039;&#039; can be addressed simultaneously by either comma-separating the objects (&amp;quot;[0,3,4]&amp;quot;) and using &#039;&#039;ranges&#039;&#039; (&amp;quot;[3-6]&amp;quot;). &#039;&#039;Modules&#039;&#039; can be either &#039;&#039;internal&#039;&#039; or &#039;&#039;external&#039;&#039;, meaning that they may all physically exist within a single hardware object, or they can be be remote-controlled devices. From a user perspective this however makes no difference as they will appear the same.&lt;br /&gt;
&lt;br /&gt;
While all &#039;&#039;modules&#039;&#039; have their own set of &#039;&#039;commands&#039;&#039;, there are certain &#039;&#039;commands&#039;&#039; that all &#039;&#039;modules&#039;&#039; &amp;lt;u&amp;gt;must&amp;lt;/u&amp;gt; implement and can thus be accessed anywhere within the &#039;&#039;module hierarchy.&#039;&#039; There are also &#039;&#039;base commands&#039;&#039; that always exist within any given FAR ecosystem as well as product-specific &#039;&#039;base commands&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Ubiquitous commands ==&lt;br /&gt;
The &#039;&#039;module commands&#039;&#039; that are &amp;lt;u&amp;gt;required&amp;lt;/u&amp;gt; to be implemented in &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; &#039;&#039;modules&#039;&#039; and that can thus be accessed from anywhere are&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|list&lt;br /&gt;
|ls&lt;br /&gt;
|hidden/h:modules/m:commands/c:instances/i:instancecounts/ic:recursive/r&lt;br /&gt;
|Lists all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039; under the current module depending on the parameters given; &#039;hidden&#039; includes normally hidden &#039;&#039;commands&#039;&#039;, &#039;modules&#039; includes any &#039;&#039;submodules&#039;&#039;, &#039;commands&#039; shows &#039;&#039;commands&#039;&#039;, &#039;instances&#039; shows data for each individual instance of a &#039;&#039;module&#039;&#039;, &#039;instancecounts&#039; includes number of instances of each &#039;&#039;module&#039;&#039;, &#039;recursive&#039; lists all child &#039;&#039;modules&#039;&#039; / &#039;&#039;commands&#039;&#039;. No parameters defaults to showing all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039; recursively with instance counts. It doesn&#039;t show per-instance data or hidden commands.&lt;br /&gt;
|-&lt;br /&gt;
|help&lt;br /&gt;
|help&lt;br /&gt;
|recursive/r&lt;br /&gt;
|Shows a brief explanation of all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039;, shows the help for all &#039;&#039;submodules&#039;&#039; as well if &#039;recursive&#039;&lt;br /&gt;
|-&lt;br /&gt;
|dumpdata&lt;br /&gt;
|dump&lt;br /&gt;
|recursive/r&lt;br /&gt;
|Dumps all data saved for the current &#039;&#039;module&#039;&#039;, will list the data of all &#039;&#039;submodules&#039;&#039; as well if &#039;recursive&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Base commands ==&lt;br /&gt;
B&#039;&#039;ase commands&#039;&#039; are &#039;&#039;commands&#039;&#039; that always exist at the root in any implementation of the Ekdahl FAR.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|version&lt;br /&gt;
|ver&lt;br /&gt;
| -&lt;br /&gt;
|Gets the current firmware version&lt;br /&gt;
|-&lt;br /&gt;
|debugprint&lt;br /&gt;
|dp&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;command|usb|hardware|undefined|priority|error|inforequest|expressionparser|debug:1|0&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Turns on or off serial feedback for the given item&lt;br /&gt;
|-&lt;br /&gt;
|requestinfo&lt;br /&gt;
|rqi&lt;br /&gt;
|command&lt;br /&gt;
|Retrives any data saved for a &#039;&#039;command&#039;&#039;, if applicable&lt;br /&gt;
|-&lt;br /&gt;
|saveallparameters&lt;br /&gt;
|sap&lt;br /&gt;
| -&lt;br /&gt;
|Saves all avaliable parameters&lt;br /&gt;
|-&lt;br /&gt;
|loadallparameters&lt;br /&gt;
|lap&lt;br /&gt;
| -&lt;br /&gt;
|Loads all avaliable parameters&lt;br /&gt;
|-&lt;br /&gt;
|resetallparameters&lt;br /&gt;
|rap&lt;br /&gt;
| -&lt;br /&gt;
|Resets all saved parameters&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|rst&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;1|0&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Resets the Ekdahl FAR, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|nick&lt;br /&gt;
|nick&lt;br /&gt;
|name&lt;br /&gt;
|Sets the nickname of this unit&lt;br /&gt;
|-&lt;br /&gt;
|nooperation&lt;br /&gt;
|nop&lt;br /&gt;
| -&lt;br /&gt;
|Do absolutely, positively, nothing. Useful for testing and interfacing with computers, it&#039;s a good way to know that the unit is alive and responding since a &amp;quot;nop&amp;quot; is being returned as a response upon reception.&lt;br /&gt;
|-&lt;br /&gt;
|uservariable&lt;br /&gt;
|uv&lt;br /&gt;
|variable(0-9):value&lt;br /&gt;
|Set user variable 0-9 to &#039;value&#039;&lt;br /&gt;
|-&lt;br /&gt;
|expressionparserevaluate&lt;br /&gt;
|epev&lt;br /&gt;
|expression&lt;br /&gt;
|Evaluates an arithmetric expression and sends back the output, all variables and functions that can be used in any &#039;&#039;command string&#039;&#039; can also be used here. Useful for testing expressions.&lt;br /&gt;
|-&lt;br /&gt;
|ifequal&lt;br /&gt;
|ife&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] EQUALS [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring].&lt;br /&gt;
|-&lt;br /&gt;
|ifgreater&lt;br /&gt;
|ifg&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] &amp;gt; [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring]&lt;br /&gt;
|-&lt;br /&gt;
|ifless&lt;br /&gt;
|ifl&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] &amp;lt; [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring]&lt;br /&gt;
|-&lt;br /&gt;
|freeram&lt;br /&gt;
|ram&lt;br /&gt;
| -&lt;br /&gt;
|Shows free RAM memory&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The base also contains the following &#039;&#039;modules:&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|pluginhandler&lt;br /&gt;
|ph&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The Ekdahl FAR stand alone single string unit ==&lt;br /&gt;
The Ekdahl FAR stand-alone single string unit offers these &#039;&#039;commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|calibrateall&lt;br /&gt;
|ca&lt;br /&gt;
| -&lt;br /&gt;
|Performs all calibration routines on the selected bow, see below for routines performed&lt;br /&gt;
|-&lt;br /&gt;
|calibratebowspeed&lt;br /&gt;
|cbs&lt;br /&gt;
| -&lt;br /&gt;
|Finds the minimum and maximum bow speed of the selected bow&lt;br /&gt;
|-&lt;br /&gt;
|calibratebowpressure&lt;br /&gt;
|cbp&lt;br /&gt;
| -&lt;br /&gt;
|Finds the minimum and maximum bow pressure of the selected bow&lt;br /&gt;
|-&lt;br /&gt;
|calibratemute&lt;br /&gt;
|cmu&lt;br /&gt;
| -&lt;br /&gt;
|Calibrate mute settings&lt;br /&gt;
|-&lt;br /&gt;
|pickupstringfrequency&lt;br /&gt;
|psf&lt;br /&gt;
| -&lt;br /&gt;
|Returns the fundamental tone calculated from the current audio signal if apliccable&lt;br /&gt;
|-&lt;br /&gt;
|pickupaudiopeak&lt;br /&gt;
|pap&lt;br /&gt;
| -&lt;br /&gt;
|Returns the peak amplitude of the current audio signal&lt;br /&gt;
|-&lt;br /&gt;
|pickupaudiorms&lt;br /&gt;
|par&lt;br /&gt;
| -&lt;br /&gt;
|Returns the RMS amplitude of the current audio signal&lt;br /&gt;
|}&lt;br /&gt;
The Ekdahl FAR also contains the following &#039;&#039;modules&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|bowingwheel&lt;br /&gt;
|bw&lt;br /&gt;
|-&lt;br /&gt;
|mute&lt;br /&gt;
|mu&lt;br /&gt;
|-&lt;br /&gt;
|solenoid&lt;br /&gt;
|so&lt;br /&gt;
|-&lt;br /&gt;
|controlbox&lt;br /&gt;
|cb&lt;br /&gt;
|-&lt;br /&gt;
|midiconfigurationhandler&lt;br /&gt;
|mcf&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;Bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; contains everything needed to interface with a single &#039;&#039;bowing wheel&#039;&#039;. Each &#039;&#039;bowing wheel&#039;&#039; has its own harmonic series, pressure actuators and direct hardware interface. It contains the following &#039;&#039;commands&#039;&#039;.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|speedmode&lt;br /&gt;
|sm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Bow motor speed mode, 0 = Automatic and 1 = Manual. Automatic mode means that the bowing wheel will automatically turn off after the &#039;&#039;motor timeout&#039;&#039; has been reached after being put into rest mode&lt;br /&gt;
|-&lt;br /&gt;
|motortimeout&lt;br /&gt;
|mt&lt;br /&gt;
|ms&lt;br /&gt;
|Bow motor shutdown timeout after bow having been put into the rest position&lt;br /&gt;
|-&lt;br /&gt;
|pidenable&lt;br /&gt;
|pe&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets the bow PID on/off&lt;br /&gt;
|-&lt;br /&gt;
|motorfaultcommands&lt;br /&gt;
|mfc&lt;br /&gt;
|commands&lt;br /&gt;
|Commands to execute when a motor fault is tripped - !WARNING! Can ruin your instrument if changed&lt;br /&gt;
|-&lt;br /&gt;
|motoroverpowercommands&lt;br /&gt;
|moc&lt;br /&gt;
|commands&lt;br /&gt;
|Commands to execute when motor is over the power limit - !WARNING! Can ruin your instrument if changed&lt;br /&gt;
|}&lt;br /&gt;
The &#039;&#039;modules&#039;&#039; in the &amp;quot;Bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; are as follows&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|bowpressure&lt;br /&gt;
|bp&lt;br /&gt;
|-&lt;br /&gt;
|dcmotor&lt;br /&gt;
|dcm&lt;br /&gt;
|-&lt;br /&gt;
|pid&lt;br /&gt;
|pid&lt;br /&gt;
|-&lt;br /&gt;
|harmonicserieshandler&lt;br /&gt;
|hsh&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; handles the &#039;&#039;pressure&#039;&#039; of the &#039;&#039;bowing wheel&#039;&#039; against the string. The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|baseline&lt;br /&gt;
|ba&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure baseline, modulation is added to this point upward. Typically this is set with a knob on the &#039;&#039;control box&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|modifier&lt;br /&gt;
|mo&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure modulation, added to the baseline&lt;br /&gt;
|-&lt;br /&gt;
|rest&lt;br /&gt;
|rs&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the bow pressure in the &#039;&#039;rest&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|engage&lt;br /&gt;
|en&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the bow pressure in the &#039;&#039;engage&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|stallpressure&lt;br /&gt;
|sp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure stall/maximum position, this parameter is set using &#039;&#039;hardware positioning&#039;&#039; and is used as the absolute maximum for baseline and modifier combiner&lt;br /&gt;
|-&lt;br /&gt;
|engagepressure&lt;br /&gt;
|ep&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure touch/minimum position, this parameter is set using &#039;&#039;hardware position&#039;&#039; and is used as the starting point for when both the baseline and modifier is set to zero&lt;br /&gt;
|-&lt;br /&gt;
|restpressure&lt;br /&gt;
|rp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure rest position, this parameter is set using &#039;&#039;hardware positioning&#039;&#039; and is typically set to a point just below the string where it does not touch at all. The purpose of this is because while the actual hardware might be able to make the bow go even lower, that position might be far enough from the string that once &#039;&#039;engaged&#039;&#039; the bow may have so far to travel that there is perceptible &#039;&#039;latency&#039;&#039;.&lt;br /&gt;
|-&lt;br /&gt;
|engagespeed&lt;br /&gt;
|es&lt;br /&gt;
|1- ~100&lt;br /&gt;
|Bow pressure movement speed when engaging or disengaging&lt;br /&gt;
|-&lt;br /&gt;
|modulationspeed&lt;br /&gt;
|ms&lt;br /&gt;
|0.1 - 10&lt;br /&gt;
|Bow pressure movement speed while engaged&lt;br /&gt;
|-&lt;br /&gt;
|hold&lt;br /&gt;
|hd&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets bow hold (infinite sustain) on/off, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|home&lt;br /&gt;
|hm&lt;br /&gt;
| -&lt;br /&gt;
|Homing bow, used at startup and in case of the bow loosing position&lt;br /&gt;
|-&lt;br /&gt;
|tmcinfo&lt;br /&gt;
|tmi&lt;br /&gt;
| -&lt;br /&gt;
|Request statistical information from the TMC2209 stepper motor driver&lt;br /&gt;
|}&lt;br /&gt;
Note that the &amp;quot;stall&amp;quot;, &amp;quot;engage&amp;quot; and &amp;quot;rest&amp;quot;-pressure positions mention something called &#039;&#039;hardware position&#039;&#039;. This means the entire available movement of the &#039;&#039;bowing jack&#039;&#039;. Because the very bottom and top end of the movement might not be musically useful and may even harm the instrument, the &amp;quot;baseline&amp;quot; and &amp;quot;modifier&amp;quot; commands &#039;&#039;parameter&#039;&#039;s are scaled depending on these settings.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;engage&amp;quot; and &amp;quot;modulation&amp;quot;-speed settings sets how fast the stepper motor that drives the &#039;&#039;pressure&#039;&#039; moves depending on whether the &#039;&#039;bowing jack&#039;&#039; is set to &#039;&#039;engage&#039;&#039; or not. The idea here is that while wanting to be able to minimize &#039;&#039;latency&#039;&#039; by &#039;&#039;engaging&#039;&#039; and &#039;&#039;disengaging&#039;&#039; from the string as quickly as possible, dynamic changes in the &#039;&#039;pressure&#039;&#039; while playing benefits from much smoother movements as the &#039;&#039;bowing wheel&#039;&#039; takes some time to catch up to varying amounts of friction.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; contains one or more of the following &#039;&#039;modules&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|actuatorhandler&lt;br /&gt;
|ah&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;actuatorhandler&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The concept of &amp;quot;actuators&amp;quot; came up as it is possible to have &#039;&#039;bowing wheels&#039;&#039; of different sizes and wanting to be able to switch quickly in between them, perhaps during mid-performance. Because a differently sized wheel will require different values for the above mentioned &amp;quot;stall&amp;quot;, &amp;quot;engage&amp;quot; and &amp;quot;reset&amp;quot;-&#039;&#039;pressure&#039;&#039;, each &#039;&#039;actuator&#039;&#039; stores these values. Instead of having to manually change the previously mentioned values, simply selecting a new &#039;&#039;actuator&#039;&#039; will automatically load the values. The &amp;quot;actuatorhandler&amp;quot;-&#039;&#039;module&#039;&#039; is the handler of one or more &amp;quot;actuator&amp;quot;-&#039;&#039;modules&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;commands&#039;&#039; of the &amp;quot;acuatorhandler&amp;quot;-&#039;&#039;module&#039;&#039; are as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|add&lt;br /&gt;
|a&lt;br /&gt;
|(name):(rest:engage:stall)&lt;br /&gt;
|Add new actuator with the given name and parameters&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|actuatornumber&lt;br /&gt;
|Remove bow actuator [actuatornumber]&lt;br /&gt;
|-&lt;br /&gt;
|count&lt;br /&gt;
|c&lt;br /&gt;
| -&lt;br /&gt;
|Returns the amount of saved bow actuators&lt;br /&gt;
|}&lt;br /&gt;
The &amp;quot;actuatorhandler&amp;quot;-&#039;&#039;module&#039;&#039; contains one or more of&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|actuator&lt;br /&gt;
|ac&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;actuator&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;actuator&amp;quot;-&#039;&#039;module&#039;&#039; contains the following commands&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|[index]&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|Selects the given actuator&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Sets the actuator name&lt;br /&gt;
|-&lt;br /&gt;
|data&lt;br /&gt;
|da&lt;br /&gt;
|name:rest:engage:stall&lt;br /&gt;
|Sets the actuator name, rest, engage and stall &#039;&#039;pressure&#039;&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;dcmotor&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;dcmotor&amp;quot;-&#039;&#039;module&#039;&#039; handles the direct &amp;lt;u&amp;gt;raw&amp;lt;/u&amp;gt; control of the &#039;&#039;bowing motor&#039;&#039; and handles the reporting back of the current speed. It has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|run&lt;br /&gt;
|ru&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Turns the motor off/on&lt;br /&gt;
|-&lt;br /&gt;
|pwm&lt;br /&gt;
|pw&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor direct power in 16-bit PWM values, requires that the &#039;&#039;PID&#039;&#039; is turned off&lt;br /&gt;
|-&lt;br /&gt;
|voltage&lt;br /&gt;
|vo&lt;br /&gt;
|~2 - 10V&lt;br /&gt;
|Sets the voltage of the regulator powering the motor. Changes here can make the motor more responsive to certain frequencies but will also affect how well the &#039;&#039;PID&#039;&#039; works. !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|current&lt;br /&gt;
|cu&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor reported current use&lt;br /&gt;
|-&lt;br /&gt;
|currentlimit&lt;br /&gt;
|cl&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor current limit (A)- !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|powerlimit&lt;br /&gt;
|pl&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor power limit (W) - !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|frequency&lt;br /&gt;
|fq&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor reported frequency&lt;br /&gt;
|-&lt;br /&gt;
|emergencystop&lt;br /&gt;
|es&lt;br /&gt;
|ms (0-65535)&lt;br /&gt;
|Immediately stops the bowing motor and doesn&#039;t allow it to start again until the cool down period given in the first argument has lapsed (milliseconds)&lt;br /&gt;
|-&lt;br /&gt;
|minpwm&lt;br /&gt;
|ip&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor minimum PWM (for calibration)&lt;br /&gt;
|-&lt;br /&gt;
|maxpwm&lt;br /&gt;
|xp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor maximum PWM (for calibration)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;pidcontroller&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;pidcontroller&amp;quot;-&#039;&#039;module&#039;&#039; is responsible for keeping the &amp;quot;dcmotor&amp;quot;-&#039;&#039;module&#039;&#039; at a certain frequency (given in Hertz). It takes the output of the motor frequency measurement and feeds it a PWM value that tries to make the speed constant regardless of the friction that the motor is enduring. To learn more about PID Controllers please see this [[wikipedia:PID_controller|wikipedia article]]. The &#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|targetfrequency&lt;br /&gt;
|tf&lt;br /&gt;
|hertz&lt;br /&gt;
|Sets the PID target frequency&lt;br /&gt;
|-&lt;br /&gt;
|ki&lt;br /&gt;
|ki&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Ki parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|kp&lt;br /&gt;
|kp&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Kp parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|kd&lt;br /&gt;
|kd&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Kd parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|integratorerror&lt;br /&gt;
|ie&lt;br /&gt;
|float&lt;br /&gt;
|Sets the lower threshold of error values for the PID integrator to ignore&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|re&lt;br /&gt;
| -&lt;br /&gt;
|Resets the PID integrator and derivative&lt;br /&gt;
|-&lt;br /&gt;
|maxerror&lt;br /&gt;
|xe&lt;br /&gt;
|float&lt;br /&gt;
|Maximum error to correct in each PID loop, essentially sets acceleration&lt;br /&gt;
|-&lt;br /&gt;
|peakerror&lt;br /&gt;
|pe&lt;br /&gt;
|float&lt;br /&gt;
|Get latest PID peak error&lt;br /&gt;
|-&lt;br /&gt;
|motorspeedmax&lt;br /&gt;
|msx&lt;br /&gt;
|Hertz&lt;br /&gt;
|Bow motor maximum speed limit&lt;br /&gt;
|-&lt;br /&gt;
|motorspeedmin&lt;br /&gt;
|msi&lt;br /&gt;
|Hertz&lt;br /&gt;
|Bow motor minimum speed limit&lt;br /&gt;
|-&lt;br /&gt;
|measuretimetotarget&lt;br /&gt;
|mtt&lt;br /&gt;
|Hertz&lt;br /&gt;
|Measure the time it takes to change from the current frequency to the target frequency, for testing purposes&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; is responsible for sending frequency data to the &amp;quot;pid&amp;quot;-&#039;&#039;module&#039;&#039;. It handles calculating the correct frequency of the &#039;&#039;bowing wheel&#039;&#039; according to the selected &#039;&#039;harmonic&#039;&#039; and &#039;&#039;harmonic shift&#039;&#039; per the currently selected &#039;&#039;harmonic series&#039;&#039;. The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|fundamental&lt;br /&gt;
|fu&lt;br /&gt;
|Hertz&lt;br /&gt;
|The fundamental frequency of the string, all harmonics are calculated from this number&lt;br /&gt;
|-&lt;br /&gt;
|harmonic&lt;br /&gt;
|h&lt;br /&gt;
|int&lt;br /&gt;
|Selects the harmonic number to set the &#039;&#039;bowing wheel&#039;&#039; to. A ratio is taken from the given &#039;&#039;harmonic&#039;&#039; in the current &#039;&#039;harmonic series&#039;&#039;, the ratio is then multiplied by the &#039;&#039;fundamental frequency&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|harmonicadd&lt;br /&gt;
|ha&lt;br /&gt;
|int&lt;br /&gt;
|This number is added to the current harmonic&lt;br /&gt;
|-&lt;br /&gt;
|harmonicbase&lt;br /&gt;
|hb&lt;br /&gt;
|int&lt;br /&gt;
|Same as harmonic but where the harmonic number is based on a MIDI note given by basenote&lt;br /&gt;
|-&lt;br /&gt;
|basenote&lt;br /&gt;
|bn&lt;br /&gt;
|0-127&lt;br /&gt;
|Sets the MIDI base note of the &#039;&#039;bowing wheel&#039;&#039;, used in conjunction with &amp;quot;harmonicbase&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|shift&lt;br /&gt;
|sh&lt;br /&gt;
| -32767 - 32767&lt;br /&gt;
|Sets shift from the currently playing harmonic where 32767 equals the entire harmonic shift range shifted up&lt;br /&gt;
|-&lt;br /&gt;
|shiftrange&lt;br /&gt;
|sr&lt;br /&gt;
|0-36&lt;br /&gt;
|Set the number of harmonic numbers that constitutes an entire harmonic shift&lt;br /&gt;
|-&lt;br /&gt;
|shift5&lt;br /&gt;
|sh5&lt;br /&gt;
| -32767 - 32767&lt;br /&gt;
|Sets the shift from the currently playing harmonic over 5 octaves where 32767 equals 5 octaves shift up from the fundamental&lt;br /&gt;
|-&lt;br /&gt;
|add&lt;br /&gt;
|a&lt;br /&gt;
|(name):(ratios)&lt;br /&gt;
|Add a new series with the given name and parameters&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|series&lt;br /&gt;
|Remove the series given and shift any series accordingly. Cannot remove all series&lt;br /&gt;
|-&lt;br /&gt;
|count&lt;br /&gt;
|c&lt;br /&gt;
| -&lt;br /&gt;
|Returns the number of harmonic series in the list and their IDs&lt;br /&gt;
|}&lt;br /&gt;
The &amp;quot;harmonicserieshandler&amp;quot;-module contains at the very least ONE harmonic series, by default it contains two: one for equal temperament and one for just intonation. The current series can be selected by simply indexing the &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; without a &#039;&#039;command&#039;&#039;, e.g. &amp;quot;harmonicserieshandler.harmonicseries[1]&amp;quot;. To be consistent, these are the &#039;&#039;modules&#039;&#039; in the &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|harmonicseries&lt;br /&gt;
|hs&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; contains any number of &#039;&#039;ratios&#039;&#039; that comprises a scale, ratios are given in a standard format where a ratio of &amp;quot;1&amp;quot; is equal to the fundamental, &amp;quot;2&amp;quot; would be one octave up etc. A standard &#039;&#039;harmonic series&#039;&#039; contains 12 ratios following a just intonation scheme. The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; will automatically adapt to the currently selected &#039;&#039;harmonic series&#039;&#039; length, whether it&#039;s a standard 12-tone scale, some kinda 3-tone scale or a full on bananas 53-tone scale. The &#039;&#039;commands&#039;&#039; of the &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; is as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|[index]&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
|Sets the currently selected &#039;&#039;harmonic Series&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Sets the name of the &#039;&#039;harmonic series&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|data&lt;br /&gt;
|da&lt;br /&gt;
|name:ratios&lt;br /&gt;
|Gets / sets all data for the &#039;&#039;harmonic series&#039;&#039; in the given slot with an arbitrary &#039;&#039;name&#039;&#039; as the first &#039;&#039;parameter&#039;&#039;. The length of the series is simply set to the amount of ratios given&lt;br /&gt;
|-&lt;br /&gt;
|ratio&lt;br /&gt;
|r&lt;br /&gt;
|harmonic:ratio&lt;br /&gt;
|Sets the ratio of the given harmonic in current &#039;&#039;harmonic series&#039;&#039;, will increase the list size if needed to address the harmonic&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|harmonic&lt;br /&gt;
|Remove the harmonic ratio given in the current series and shift any ratios accordingly. Cannot remove all ratios&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;mute&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;mute&amp;quot;-&#039;&#039;module&#039;&#039; works very similarly to the &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; in that it controls a stepper motor with some software limits in place in order to press the mute against the string. The &#039;&#039;commands&#039;&#039; are as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|setposition&lt;br /&gt;
|sp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set mute position&lt;br /&gt;
|-&lt;br /&gt;
|fullmute&lt;br /&gt;
|fm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the mute in &#039;&#039;full mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|halfmute&lt;br /&gt;
|hm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the mute in &#039;&#039;half mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|rest&lt;br /&gt;
|rs&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Put the mute in the &#039;&#039;rest&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|savefull&lt;br /&gt;
|sf&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Save the current mute position as the &#039;&#039;full mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|savehalf&lt;br /&gt;
|sh&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Save the current mute position as the &#039;&#039;half mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|saverest&lt;br /&gt;
|sr&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Save the current mute position as the &#039;&#039;rest&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|fullmuteposition&lt;br /&gt;
|fmp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;full mute&#039;&#039; position according to the &#039;&#039;hardware position&#039;&#039; given&lt;br /&gt;
|-&lt;br /&gt;
|halfmuteposition&lt;br /&gt;
|hmp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;half mute&#039;&#039; position according to the &#039;&#039;hardware position&#039;&#039; given&lt;br /&gt;
|-&lt;br /&gt;
|restposition&lt;br /&gt;
|rp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;rest&#039;&#039; position according to the &#039;&#039;hardware position&#039;&#039; given&lt;br /&gt;
|-&lt;br /&gt;
|sustain&lt;br /&gt;
|su&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets the sustain off/on, this will keep the mute in the &#039;&#039;rest&#039;&#039; position even if a &amp;quot;fullmute&amp;quot;-&#039;&#039;command&#039;&#039; is given, lasts until &amp;quot;sustain&amp;quot; is set to &amp;quot;0&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
|backoff&lt;br /&gt;
|bo&lt;br /&gt;
|0-65535&lt;br /&gt;
|Setting the time that the mute stays in the mutefullmute position before automatically going into rest, set in mS. A value of &amp;quot;0&amp;quot; disables backoff. This is used because if the mute is not backing off until something is attempted to be played, the backing-off time will either introduce &#039;&#039;latency&#039;&#039; or the string will be initially partially muted&lt;br /&gt;
|-&lt;br /&gt;
|home&lt;br /&gt;
|hm&lt;br /&gt;
| -&lt;br /&gt;
|Home mute, used during initialization and if the mute were to loose position&lt;br /&gt;
|-&lt;br /&gt;
|hardwareposition&lt;br /&gt;
|hwp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;hardware position&#039;&#039; of the mute instead of scaling it over the &#039;&#039;full mute&#039;&#039; and &#039;&#039;rest&#039;&#039; positions. Mainly used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|completetask&lt;br /&gt;
|cpt&lt;br /&gt;
| -&lt;br /&gt;
|Requests a callback when the current operation is finished. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|autocorrect&lt;br /&gt;
|ac&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Enables auto correct positioning that uses the homing sensor to correct positioning on the fly. EXPERIMENTAL&lt;br /&gt;
|-&lt;br /&gt;
|homingsensed&lt;br /&gt;
|hms&lt;br /&gt;
| -&lt;br /&gt;
|Requests whether the homing sensor is currently active or not. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|movedirection&lt;br /&gt;
|md&lt;br /&gt;
| -&lt;br /&gt;
|Requests the current direction of movement (0 Forward, 1 Reverse). Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|currentstep&lt;br /&gt;
|cs&lt;br /&gt;
| -&lt;br /&gt;
|Requests the current step. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|homingpoint&lt;br /&gt;
|hmp&lt;br /&gt;
|edgedirection&lt;br /&gt;
|Requests the given homing point. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|homingstage&lt;br /&gt;
|hms&lt;br /&gt;
| -&lt;br /&gt;
|Requests the current homing stage (UNHOMED, HOMED, FIRSTHOMINGRISING, SECONDHOMINGFALLING, SECONDHOMINGRISING, FIRSTHOMINGFALLING, MOVEPASTHOMESWITCH, MOVETOHOMESWITCH, GOTOOFFSET). Only used internally by other &#039;&#039;modules.&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|tmcinfo&lt;br /&gt;
|tmi&lt;br /&gt;
| -&lt;br /&gt;
|Request statistical information from the TMC2209 stepper motor driver&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;solenoid&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;solenoid&amp;quot;-&#039;&#039;module&#039;&#039; currently controls the &#039;&#039;hammer&#039;&#039; of the Ekdahl FAR. Due to the fact that the very same &#039;&#039;module&#039;&#039; could be used for anything that uses a striking &#039;&#039;solenoid&#039;&#039; it was named as such. It has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|engage&lt;br /&gt;
|en&lt;br /&gt;
|0-65535&lt;br /&gt;
|Engages the solenoid using the first parameter as the force&lt;br /&gt;
|-&lt;br /&gt;
|rest&lt;br /&gt;
|rs&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Forces the solenoid to its rest position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|maxforce&lt;br /&gt;
|xf&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set solenoid maximum usable force&lt;br /&gt;
|-&lt;br /&gt;
|minforce&lt;br /&gt;
|if&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set solenoid minimum usable force&lt;br /&gt;
|-&lt;br /&gt;
|forcemultiplier&lt;br /&gt;
|fm&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set solenoid force multiplier, useful for scaling of all incoming &amp;quot;engage&amp;quot;-&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|engageduration&lt;br /&gt;
|ed&lt;br /&gt;
|uS&lt;br /&gt;
|Sets the duration of the solenoid hit in uS, if a value of 0 is set the solenoid will not disengage until a rest command has been given. WARNING!! HAVING THE SOLENOID ON FOR A SPAN OF SECONDS COULD DESTROY THE CIRCUITRY!!&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;controlbox&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;controlbox&amp;quot;-&#039;&#039;module&#039;&#039; communicates with an external &#039;&#039;control box&#039;&#039; and will issue associated &#039;&#039;commands&#039;&#039; whenever new values are read on the ADC-converters. It handles averaging and does some noise-cancellation functions on the values as well. The &#039;&#039;commands&#039;&#039; are:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|harmonic&lt;br /&gt;
|har&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the harmonic knob or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|harmonicshift&lt;br /&gt;
|has&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the harmonic shift modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|finetune&lt;br /&gt;
|fin&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the fine tune knob changes&lt;br /&gt;
|-&lt;br /&gt;
|pressure&lt;br /&gt;
|pre&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the pressure knob or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|mute&lt;br /&gt;
|mut&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the mute knob or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|hammerscale&lt;br /&gt;
|hms&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the hammer scale knob changes&lt;br /&gt;
|-&lt;br /&gt;
|gate&lt;br /&gt;
|gt&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the gate switch or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|hammertrig&lt;br /&gt;
|hmt&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the hammer trigger modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|controldefaults&lt;br /&gt;
|cde&lt;br /&gt;
| -&lt;br /&gt;
|Reverts all ADC command strings to default values&lt;br /&gt;
|-&lt;br /&gt;
|datareturn&lt;br /&gt;
|dr&lt;br /&gt;
|channel:value&lt;br /&gt;
|Sent when a new value is presented on one of the ADC channels, cannot be invoked. Triggers the commands associated with the channel&lt;br /&gt;
|-&lt;br /&gt;
|adcsetting&lt;br /&gt;
|adcs&lt;br /&gt;
|channel : averages : interrupterrorthreshold : continuouserrorthreshold : continuoustimeout&lt;br /&gt;
|Sets ADC settings for a given channel. Averages are the number of samples to average, interruptthreshold is how much the value must change in order to issue a new value change event. continuousthreshold is how much the value must change when a previous change has already been recorded within the timespan of continuoustimeout&lt;br /&gt;
|-&lt;br /&gt;
|testadclatency&lt;br /&gt;
|tal&lt;br /&gt;
|0-65535&lt;br /&gt;
|Start a ADC latency test&lt;br /&gt;
|-&lt;br /&gt;
|testadclatencyreturn&lt;br /&gt;
|talr&lt;br /&gt;
| -&lt;br /&gt;
|Return from latency test&lt;br /&gt;
|-&lt;br /&gt;
|testadcminmax&lt;br /&gt;
|tix&lt;br /&gt;
|channel&lt;br /&gt;
|Test min/max value for a given channel and resets the counter&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;midiconfigurationhandler&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;midiconfigurationhandler&amp;quot;-&#039;&#039;module&#039;&#039; handles a number of &amp;quot;midiconfiguration&amp;quot;-&#039;&#039;modules&#039;&#039;. It has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|allnotesoff&lt;br /&gt;
|ano&lt;br /&gt;
| -&lt;br /&gt;
|Clears the entire buffer of MIDI notes held&lt;br /&gt;
|-&lt;br /&gt;
|add&lt;br /&gt;
|a&lt;br /&gt;
|name&lt;br /&gt;
|Adds a new MIDI configuration with the given name&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|int&lt;br /&gt;
|Remove the specified MIDI configuration&lt;br /&gt;
|-&lt;br /&gt;
|count&lt;br /&gt;
|c&lt;br /&gt;
| -&lt;br /&gt;
|Returns the number of MIDI configurations&lt;br /&gt;
|}&lt;br /&gt;
It contains one or more of the following&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|midiconfiguration&lt;br /&gt;
|mc&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;midiconfiguration&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
A &amp;quot;midiconfiguration&amp;quot;-&#039;&#039;module&#039;&#039; handles the reception of &#039;&#039;MIDI messages&#039;&#039; and will output the associated &#039;&#039;commands&#039;&#039; to the instrument internally. The commands are as follows&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|[index]&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
|Sets the currently selected MIDI configuration&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Set the name of the MIDI configuration&lt;br /&gt;
|-&lt;br /&gt;
|noteon&lt;br /&gt;
|non&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Note On event&lt;br /&gt;
|-&lt;br /&gt;
|noteoff&lt;br /&gt;
|nof&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Note Off event&lt;br /&gt;
|-&lt;br /&gt;
|polyaftertouch&lt;br /&gt;
|pat&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Polyphonic after touch event&lt;br /&gt;
|-&lt;br /&gt;
|channelaftertouch&lt;br /&gt;
|cat&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Channel after touch event&lt;br /&gt;
|-&lt;br /&gt;
|pitchbend&lt;br /&gt;
|pb&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Pitch bend event&lt;br /&gt;
|-&lt;br /&gt;
|programchange&lt;br /&gt;
|pc&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Program change event&lt;br /&gt;
|-&lt;br /&gt;
|continuouscontrollerdata&lt;br /&gt;
|ccd&lt;br /&gt;
|controllernuber:&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Continuous controller event with the given [&#039;&#039;controllernumber&#039;&#039;]&lt;br /&gt;
|-&lt;br /&gt;
|removecc&lt;br /&gt;
|rmc&lt;br /&gt;
|controllernuber&lt;br /&gt;
|Removes the entry associated with the MIDI continuous controller even &#039;&#039;controllernumber&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|defaults&lt;br /&gt;
|d&lt;br /&gt;
| -&lt;br /&gt;
|Reverts the current configuration to default &#039;&#039;commands&#039;&#039;, values and CCs&lt;br /&gt;
|-&lt;br /&gt;
|receivechannel&lt;br /&gt;
|rc&lt;br /&gt;
|channel&lt;br /&gt;
|Sets the MIDI receive channel of the current configuration. 1-16 sets specific channel, any other value for OMNI&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;pluginhandler&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The Ekdahl FAR allows for &#039;&#039;plugins&#039;&#039;. These are &#039;&#039;modules&#039;&#039; that can trigger certain &#039;&#039;command strings&#039;&#039; to be executed either periodically or triggered by an incoming &#039;&#039;command&#039;&#039;. Further explanation of the given &#039;&#039;plugins&#039;&#039; is given below. The various &#039;&#039;plugins&#039;&#039; are handled by the &amp;quot;pluginhandler&amp;quot;-&#039;&#039;module&#039;&#039;, the different &#039;&#039;plugin modules&#039;&#039; are identified by their own unique &#039;&#039;ID&#039;&#039;. The &amp;quot;pluginhandler&amp;quot;-&#039;&#039;module&#039;&#039; it has the following &#039;&#039;commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|add&lt;br /&gt;
|a&lt;br /&gt;
|pluginid&lt;br /&gt;
|Add plugin with the given ID&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|pluginid:index&lt;br /&gt;
|Remove plugin with the given ID and index&lt;br /&gt;
|-&lt;br /&gt;
|count&lt;br /&gt;
|c&lt;br /&gt;
|(pluginid)&lt;br /&gt;
|Return the number of plugins of the given type, if none is given it returns all plugins&lt;br /&gt;
|}&lt;br /&gt;
The number of available &#039;&#039;plugins&#039;&#039; will differ from time to time as the &#039;&#039;plugin system&#039;&#039; has been purposefully designed to allow for anyone to write and add their own &#039;&#039;plugins&#039;&#039;. As of the current writing (2026-06-14) the number of &amp;lt;u&amp;gt;possible&amp;lt;/u&amp;gt; &#039;&#039;plugin modules&#039;&#039; that can exist under the &amp;quot;pluginhandler&amp;quot;-&#039;&#039;module&#039;&#039; are&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|lfo&lt;br /&gt;
|lfo&lt;br /&gt;
|-&lt;br /&gt;
|ahdsr&lt;br /&gt;
|ahdsr&lt;br /&gt;
|-&lt;br /&gt;
|numbermap&lt;br /&gt;
|map&lt;br /&gt;
|-&lt;br /&gt;
|multiple&lt;br /&gt;
|mlt&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;lfo&amp;quot;-&#039;&#039;plugin module&#039;&#039; ==&lt;/div&gt;</summary>
		<author><name>Knaadmin</name></author>
	</entry>
	<entry>
		<id>http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_reference_V1.1&amp;diff=1682</id>
		<title>The Ekdahl FAR - Command reference V1.1</title>
		<link rel="alternate" type="text/html" href="http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_reference_V1.1&amp;diff=1682"/>
		<updated>2026-06-14T07:39:09Z</updated>

		<summary type="html">&lt;p&gt;Knaadmin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
The Ekdahl FAR V1.1 introduces the concept of &#039;&#039;modules&#039;&#039;. A &#039;&#039;module&#039;&#039; can contain any number of &#039;&#039;commands&#039;&#039; as well as other &#039;&#039;modules&#039;&#039;. Furthermore any number of &#039;&#039;modules&#039;&#039; of the same type can exist within a context, these are addressed using classic C-style array &#039;&#039;indexing&#039;&#039; with the help of brackets (&amp;quot;[ ]&amp;quot;). Extending on the classic usage, multiple &#039;&#039;indexes&#039;&#039; can be addressed simultaneously by either comma-separating the objects (&amp;quot;[0,3,4]&amp;quot;) and using &#039;&#039;ranges&#039;&#039; (&amp;quot;[3-6]&amp;quot;). &#039;&#039;Modules&#039;&#039; can be either &#039;&#039;internal&#039;&#039; or &#039;&#039;external&#039;&#039;, meaning that they may all physically exist within a single hardware object, or they can be be remote-controlled devices. From a user perspective this however makes no difference as they will appear the same.&lt;br /&gt;
&lt;br /&gt;
While all &#039;&#039;modules&#039;&#039; have their own set of &#039;&#039;commands&#039;&#039;, there are certain &#039;&#039;commands&#039;&#039; that all &#039;&#039;modules&#039;&#039; &amp;lt;u&amp;gt;must&amp;lt;/u&amp;gt; implement and can thus be accessed anywhere within the &#039;&#039;module hierarchy.&#039;&#039; There are also &#039;&#039;base commands&#039;&#039; that always exist within any given FAR ecosystem as well as product-specific &#039;&#039;base commands&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Ubiquitous commands ==&lt;br /&gt;
The &#039;&#039;module commands&#039;&#039; that are &amp;lt;u&amp;gt;required&amp;lt;/u&amp;gt; to be implemented in &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; &#039;&#039;modules&#039;&#039; and that can thus be accessed from anywhere are&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|list&lt;br /&gt;
|ls&lt;br /&gt;
|hidden/h:modules/m:commands/c:instances/i:instancecounts/ic:recursive/r&lt;br /&gt;
|Lists all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039; under the current module depending on the parameters given; &#039;hidden&#039; includes normally hidden &#039;&#039;commands&#039;&#039;, &#039;modules&#039; includes any &#039;&#039;submodules&#039;&#039;, &#039;commands&#039; shows &#039;&#039;commands&#039;&#039;, &#039;instances&#039; shows data for each individual instance of a &#039;&#039;module&#039;&#039;, &#039;instancecounts&#039; includes number of instances of each &#039;&#039;module&#039;&#039;, &#039;recursive&#039; lists all child &#039;&#039;modules&#039;&#039; / &#039;&#039;commands&#039;&#039;. No parameters defaults to showing all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039; recursively with instance counts. It doesn&#039;t show per-instance data or hidden commands.&lt;br /&gt;
|-&lt;br /&gt;
|help&lt;br /&gt;
|help&lt;br /&gt;
|recursive/r&lt;br /&gt;
|Shows a brief explanation of all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039;, shows the help for all &#039;&#039;submodules&#039;&#039; as well if &#039;recursive&#039;&lt;br /&gt;
|-&lt;br /&gt;
|dumpdata&lt;br /&gt;
|dump&lt;br /&gt;
|recursive/r&lt;br /&gt;
|Dumps all data saved for the current &#039;&#039;module&#039;&#039;, will list the data of all &#039;&#039;submodules&#039;&#039; as well if &#039;recursive&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Base commands ==&lt;br /&gt;
B&#039;&#039;ase commands&#039;&#039; are &#039;&#039;commands&#039;&#039; that always exist at the root in any implementation of the Ekdahl FAR.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|version&lt;br /&gt;
|ver&lt;br /&gt;
| -&lt;br /&gt;
|Gets the current firmware version&lt;br /&gt;
|-&lt;br /&gt;
|debugprint&lt;br /&gt;
|dp&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;command|usb|hardware|undefined|priority|error|inforequest|expressionparser|debug:1|0&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Turns on or off serial feedback for the given item&lt;br /&gt;
|-&lt;br /&gt;
|requestinfo&lt;br /&gt;
|rqi&lt;br /&gt;
|command&lt;br /&gt;
|Retrives any data saved for a &#039;&#039;command&#039;&#039;, if applicable&lt;br /&gt;
|-&lt;br /&gt;
|saveallparameters&lt;br /&gt;
|sap&lt;br /&gt;
| -&lt;br /&gt;
|Saves all avaliable parameters&lt;br /&gt;
|-&lt;br /&gt;
|loadallparameters&lt;br /&gt;
|lap&lt;br /&gt;
| -&lt;br /&gt;
|Loads all avaliable parameters&lt;br /&gt;
|-&lt;br /&gt;
|resetallparameters&lt;br /&gt;
|rap&lt;br /&gt;
| -&lt;br /&gt;
|Resets all saved parameters&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|rst&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;1|0&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Resets the Ekdahl FAR, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|nick&lt;br /&gt;
|nick&lt;br /&gt;
|name&lt;br /&gt;
|Sets the nickname of this unit&lt;br /&gt;
|-&lt;br /&gt;
|nooperation&lt;br /&gt;
|nop&lt;br /&gt;
| -&lt;br /&gt;
|Do absolutely, positively, nothing. Useful for testing and interfacing with computers, it&#039;s a good way to know that the unit is alive and responding since a &amp;quot;nop&amp;quot; is being returned as a response upon reception.&lt;br /&gt;
|-&lt;br /&gt;
|uservariable&lt;br /&gt;
|uv&lt;br /&gt;
|variable(0-9):value&lt;br /&gt;
|Set user variable 0-9 to &#039;value&#039;&lt;br /&gt;
|-&lt;br /&gt;
|expressionparserevaluate&lt;br /&gt;
|epev&lt;br /&gt;
|expression&lt;br /&gt;
|Evaluates an arithmetric expression and sends back the output, all variables and functions that can be used in any &#039;&#039;command string&#039;&#039; can also be used here. Useful for testing expressions.&lt;br /&gt;
|-&lt;br /&gt;
|ifequal&lt;br /&gt;
|ife&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] EQUALS [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring].&lt;br /&gt;
|-&lt;br /&gt;
|ifgreater&lt;br /&gt;
|ifg&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] &amp;gt; [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring]&lt;br /&gt;
|-&lt;br /&gt;
|ifless&lt;br /&gt;
|ifl&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] &amp;lt; [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring]&lt;br /&gt;
|-&lt;br /&gt;
|freeram&lt;br /&gt;
|ram&lt;br /&gt;
| -&lt;br /&gt;
|Shows free RAM memory&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The base also contains the following &#039;&#039;modules:&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|pluginhandler&lt;br /&gt;
|ph&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The Ekdahl FAR stand alone single string unit ==&lt;br /&gt;
The Ekdahl FAR stand-alone single string unit offers these &#039;&#039;commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|calibrateall&lt;br /&gt;
|ca&lt;br /&gt;
| -&lt;br /&gt;
|Performs all calibration routines on the selected bow, see below for routines performed&lt;br /&gt;
|-&lt;br /&gt;
|calibratebowspeed&lt;br /&gt;
|cbs&lt;br /&gt;
| -&lt;br /&gt;
|Finds the minimum and maximum bow speed of the selected bow&lt;br /&gt;
|-&lt;br /&gt;
|calibratebowpressure&lt;br /&gt;
|cbp&lt;br /&gt;
| -&lt;br /&gt;
|Finds the minimum and maximum bow pressure of the selected bow&lt;br /&gt;
|-&lt;br /&gt;
|calibratemute&lt;br /&gt;
|cmu&lt;br /&gt;
| -&lt;br /&gt;
|Calibrate mute settings&lt;br /&gt;
|-&lt;br /&gt;
|pickupstringfrequency&lt;br /&gt;
|psf&lt;br /&gt;
| -&lt;br /&gt;
|Returns the fundamental tone calculated from the current audio signal if apliccable&lt;br /&gt;
|-&lt;br /&gt;
|pickupaudiopeak&lt;br /&gt;
|pap&lt;br /&gt;
| -&lt;br /&gt;
|Returns the peak amplitude of the current audio signal&lt;br /&gt;
|-&lt;br /&gt;
|pickupaudiorms&lt;br /&gt;
|par&lt;br /&gt;
| -&lt;br /&gt;
|Returns the RMS amplitude of the current audio signal&lt;br /&gt;
|}&lt;br /&gt;
The Ekdahl FAR also contains the following &#039;&#039;modules&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|bowingwheel&lt;br /&gt;
|bw&lt;br /&gt;
|-&lt;br /&gt;
|mute&lt;br /&gt;
|mu&lt;br /&gt;
|-&lt;br /&gt;
|solenoid&lt;br /&gt;
|so&lt;br /&gt;
|-&lt;br /&gt;
|controlbox&lt;br /&gt;
|cb&lt;br /&gt;
|-&lt;br /&gt;
|midiconfigurationhandler&lt;br /&gt;
|mcf&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;Bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; contains everything needed to interface with a single &#039;&#039;bowing wheel&#039;&#039;. Each &#039;&#039;bowing wheel&#039;&#039; has its own harmonic series, pressure actuators and direct hardware interface. It contains the following &#039;&#039;commands&#039;&#039;.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|speedmode&lt;br /&gt;
|sm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Bow motor speed mode, 0 = Automatic and 1 = Manual. Automatic mode means that the bowing wheel will automatically turn off after the &#039;&#039;motor timeout&#039;&#039; has been reached after being put into rest mode&lt;br /&gt;
|-&lt;br /&gt;
|motortimeout&lt;br /&gt;
|mt&lt;br /&gt;
|ms&lt;br /&gt;
|Bow motor shutdown timeout after bow having been put into the rest position&lt;br /&gt;
|-&lt;br /&gt;
|pidenable&lt;br /&gt;
|pe&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets the bow PID on/off&lt;br /&gt;
|-&lt;br /&gt;
|motorfaultcommands&lt;br /&gt;
|mfc&lt;br /&gt;
|commands&lt;br /&gt;
|Commands to execute when a motor fault is tripped - !WARNING! Can ruin your instrument if changed&lt;br /&gt;
|-&lt;br /&gt;
|motoroverpowercommands&lt;br /&gt;
|moc&lt;br /&gt;
|commands&lt;br /&gt;
|Commands to execute when motor is over the power limit - !WARNING! Can ruin your instrument if changed&lt;br /&gt;
|}&lt;br /&gt;
The &#039;&#039;modules&#039;&#039; in the &amp;quot;Bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; are as follows&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|bowpressure&lt;br /&gt;
|bp&lt;br /&gt;
|-&lt;br /&gt;
|dcmotor&lt;br /&gt;
|dcm&lt;br /&gt;
|-&lt;br /&gt;
|pid&lt;br /&gt;
|pid&lt;br /&gt;
|-&lt;br /&gt;
|harmonicserieshandler&lt;br /&gt;
|hsh&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; handles the &#039;&#039;pressure&#039;&#039; of the &#039;&#039;bowing wheel&#039;&#039; against the string. The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|baseline&lt;br /&gt;
|ba&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure baseline, modulation is added to this point upward. Typically this is set with a knob on the &#039;&#039;control box&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|modifier&lt;br /&gt;
|mo&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure modulation, added to the baseline&lt;br /&gt;
|-&lt;br /&gt;
|rest&lt;br /&gt;
|rs&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the bow pressure in the &#039;&#039;rest&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|engage&lt;br /&gt;
|en&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the bow pressure in the &#039;&#039;engage&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|stallpressure&lt;br /&gt;
|sp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure stall/maximum position, this parameter is set using &#039;&#039;hardware positioning&#039;&#039; and is used as the absolute maximum for baseline and modifier combiner&lt;br /&gt;
|-&lt;br /&gt;
|engagepressure&lt;br /&gt;
|ep&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure touch/minimum position, this parameter is set using &#039;&#039;hardware position&#039;&#039; and is used as the starting point for when both the baseline and modifier is set to zero&lt;br /&gt;
|-&lt;br /&gt;
|restpressure&lt;br /&gt;
|rp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure rest position, this parameter is set using &#039;&#039;hardware positioning&#039;&#039; and is typically set to a point just below the string where it does not touch at all. The purpose of this is because while the actual hardware might be able to make the bow go even lower, that position might be far enough from the string that once &#039;&#039;engaged&#039;&#039; the bow may have so far to travel that there is perceptible &#039;&#039;latency&#039;&#039;.&lt;br /&gt;
|-&lt;br /&gt;
|engagespeed&lt;br /&gt;
|es&lt;br /&gt;
|1- ~100&lt;br /&gt;
|Bow pressure movement speed when engaging or disengaging&lt;br /&gt;
|-&lt;br /&gt;
|modulationspeed&lt;br /&gt;
|ms&lt;br /&gt;
|0.1 - 10&lt;br /&gt;
|Bow pressure movement speed while engaged&lt;br /&gt;
|-&lt;br /&gt;
|hold&lt;br /&gt;
|hd&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets bow hold (infinite sustain) on/off, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|home&lt;br /&gt;
|hm&lt;br /&gt;
| -&lt;br /&gt;
|Homing bow, used at startup and in case of the bow loosing position&lt;br /&gt;
|-&lt;br /&gt;
|tmcinfo&lt;br /&gt;
|tmi&lt;br /&gt;
| -&lt;br /&gt;
|Request statistical information from the TMC2209 stepper motor driver&lt;br /&gt;
|}&lt;br /&gt;
Note that the &amp;quot;stall&amp;quot;, &amp;quot;engage&amp;quot; and &amp;quot;rest&amp;quot;-pressure positions mention something called &#039;&#039;hardware position&#039;&#039;. This means the entire available movement of the &#039;&#039;bowing jack&#039;&#039;. Because the very bottom and top end of the movement might not be musically useful and may even harm the instrument, the &amp;quot;baseline&amp;quot; and &amp;quot;modifier&amp;quot; commands &#039;&#039;parameter&#039;&#039;s are scaled depending on these settings.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;engage&amp;quot; and &amp;quot;modulation&amp;quot;-speed settings sets how fast the stepper motor that drives the &#039;&#039;pressure&#039;&#039; moves depending on whether the &#039;&#039;bowing jack&#039;&#039; is set to &#039;&#039;engage&#039;&#039; or not. The idea here is that while wanting to be able to minimize &#039;&#039;latency&#039;&#039; by &#039;&#039;engaging&#039;&#039; and &#039;&#039;disengaging&#039;&#039; from the string as quickly as possible, dynamic changes in the &#039;&#039;pressure&#039;&#039; while playing benefits from much smoother movements as the &#039;&#039;bowing wheel&#039;&#039; takes some time to catch up to varying amounts of friction.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; contains one or more of the following &#039;&#039;modules&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|actuatorhandler&lt;br /&gt;
|ah&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;actuatorhandler&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The concept of &amp;quot;actuators&amp;quot; came up as it is possible to have &#039;&#039;bowing wheels&#039;&#039; of different sizes and wanting to be able to switch quickly in between them, perhaps during mid-performance. Because a differently sized wheel will require different values for the above mentioned &amp;quot;stall&amp;quot;, &amp;quot;engage&amp;quot; and &amp;quot;reset&amp;quot;-&#039;&#039;pressure&#039;&#039;, each &#039;&#039;actuator&#039;&#039; stores these values. Instead of having to manually change the previously mentioned values, simply selecting a new &#039;&#039;actuator&#039;&#039; will automatically load the values. The &amp;quot;actuatorhandler&amp;quot;-&#039;&#039;module&#039;&#039; is the handler of one or more &amp;quot;actuator&amp;quot;-&#039;&#039;modules&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;commands&#039;&#039; of the &amp;quot;acuatorhandler&amp;quot;-&#039;&#039;module&#039;&#039; are as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|add&lt;br /&gt;
|a&lt;br /&gt;
|(name):(rest:engage:stall)&lt;br /&gt;
|Add new actuator with the given name and parameters&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|actuatornumber&lt;br /&gt;
|Remove bow actuator [actuatornumber]&lt;br /&gt;
|-&lt;br /&gt;
|count&lt;br /&gt;
|c&lt;br /&gt;
| -&lt;br /&gt;
|Returns the amount of saved bow actuators&lt;br /&gt;
|}&lt;br /&gt;
The &amp;quot;actuatorhandler&amp;quot;-&#039;&#039;module&#039;&#039; contains one or more of&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|actuator&lt;br /&gt;
|ac&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;actuator&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;actuator&amp;quot;-&#039;&#039;module&#039;&#039; contains the following commands&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|[index]&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|Selects the given actuator&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Sets the actuator name&lt;br /&gt;
|-&lt;br /&gt;
|data&lt;br /&gt;
|da&lt;br /&gt;
|name:rest:engage:stall&lt;br /&gt;
|Sets the actuator name, rest, engage and stall &#039;&#039;pressure&#039;&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;dcmotor&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;dcmotor&amp;quot;-&#039;&#039;module&#039;&#039; handles the direct &amp;lt;u&amp;gt;raw&amp;lt;/u&amp;gt; control of the &#039;&#039;bowing motor&#039;&#039; and handles the reporting back of the current speed. It has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|run&lt;br /&gt;
|ru&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Turns the motor off/on&lt;br /&gt;
|-&lt;br /&gt;
|pwm&lt;br /&gt;
|pw&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor direct power in 16-bit PWM values, requires that the &#039;&#039;PID&#039;&#039; is turned off&lt;br /&gt;
|-&lt;br /&gt;
|voltage&lt;br /&gt;
|vo&lt;br /&gt;
|~2 - 10V&lt;br /&gt;
|Sets the voltage of the regulator powering the motor. Changes here can make the motor more responsive to certain frequencies but will also affect how well the &#039;&#039;PID&#039;&#039; works. !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|current&lt;br /&gt;
|cu&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor reported current use&lt;br /&gt;
|-&lt;br /&gt;
|currentlimit&lt;br /&gt;
|cl&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor current limit (A)- !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|powerlimit&lt;br /&gt;
|pl&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor power limit (W) - !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|frequency&lt;br /&gt;
|fq&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor reported frequency&lt;br /&gt;
|-&lt;br /&gt;
|emergencystop&lt;br /&gt;
|es&lt;br /&gt;
|ms (0-65535)&lt;br /&gt;
|Immediately stops the bowing motor and doesn&#039;t allow it to start again until the cool down period given in the first argument has lapsed (milliseconds)&lt;br /&gt;
|-&lt;br /&gt;
|minpwm&lt;br /&gt;
|ip&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor minimum PWM (for calibration)&lt;br /&gt;
|-&lt;br /&gt;
|maxpwm&lt;br /&gt;
|xp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor maximum PWM (for calibration)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;pidcontroller&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;pidcontroller&amp;quot;-&#039;&#039;module&#039;&#039; is responsible for keeping the &amp;quot;dcmotor&amp;quot;-&#039;&#039;module&#039;&#039; at a certain frequency (given in Hertz). It takes the output of the motor frequency measurement and feeds it a PWM value that tries to make the speed constant regardless of the friction that the motor is enduring. To learn more about PID Controllers please see this [[wikipedia:PID_controller|wikipedia article]]. The &#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|targetfrequency&lt;br /&gt;
|tf&lt;br /&gt;
|hertz&lt;br /&gt;
|Sets the PID target frequency&lt;br /&gt;
|-&lt;br /&gt;
|ki&lt;br /&gt;
|ki&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Ki parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|kp&lt;br /&gt;
|kp&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Kp parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|kd&lt;br /&gt;
|kd&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Kd parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|integratorerror&lt;br /&gt;
|ie&lt;br /&gt;
|float&lt;br /&gt;
|Sets the lower threshold of error values for the PID integrator to ignore&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|re&lt;br /&gt;
| -&lt;br /&gt;
|Resets the PID integrator and derivative&lt;br /&gt;
|-&lt;br /&gt;
|maxerror&lt;br /&gt;
|xe&lt;br /&gt;
|float&lt;br /&gt;
|Maximum error to correct in each PID loop, essentially sets acceleration&lt;br /&gt;
|-&lt;br /&gt;
|peakerror&lt;br /&gt;
|pe&lt;br /&gt;
|float&lt;br /&gt;
|Get latest PID peak error&lt;br /&gt;
|-&lt;br /&gt;
|motorspeedmax&lt;br /&gt;
|msx&lt;br /&gt;
|Hertz&lt;br /&gt;
|Bow motor maximum speed limit&lt;br /&gt;
|-&lt;br /&gt;
|motorspeedmin&lt;br /&gt;
|msi&lt;br /&gt;
|Hertz&lt;br /&gt;
|Bow motor minimum speed limit&lt;br /&gt;
|-&lt;br /&gt;
|measuretimetotarget&lt;br /&gt;
|mtt&lt;br /&gt;
|Hertz&lt;br /&gt;
|Measure the time it takes to change from the current frequency to the target frequency, for testing purposes&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; is responsible for sending frequency data to the &amp;quot;pid&amp;quot;-&#039;&#039;module&#039;&#039;. It handles calculating the correct frequency of the &#039;&#039;bowing wheel&#039;&#039; according to the selected &#039;&#039;harmonic&#039;&#039; and &#039;&#039;harmonic shift&#039;&#039; per the currently selected &#039;&#039;harmonic series&#039;&#039;. The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|fundamental&lt;br /&gt;
|fu&lt;br /&gt;
|Hertz&lt;br /&gt;
|The fundamental frequency of the string, all harmonics are calculated from this number&lt;br /&gt;
|-&lt;br /&gt;
|harmonic&lt;br /&gt;
|h&lt;br /&gt;
|int&lt;br /&gt;
|Selects the harmonic number to set the &#039;&#039;bowing wheel&#039;&#039; to. A ratio is taken from the given &#039;&#039;harmonic&#039;&#039; in the current &#039;&#039;harmonic series&#039;&#039;, the ratio is then multiplied by the &#039;&#039;fundamental frequency&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|harmonicadd&lt;br /&gt;
|ha&lt;br /&gt;
|int&lt;br /&gt;
|This number is added to the current harmonic&lt;br /&gt;
|-&lt;br /&gt;
|harmonicbase&lt;br /&gt;
|hb&lt;br /&gt;
|int&lt;br /&gt;
|Same as harmonic but where the harmonic number is based on a MIDI note given by basenote&lt;br /&gt;
|-&lt;br /&gt;
|basenote&lt;br /&gt;
|bn&lt;br /&gt;
|0-127&lt;br /&gt;
|Sets the MIDI base note of the &#039;&#039;bowing wheel&#039;&#039;, used in conjunction with &amp;quot;harmonicbase&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|shift&lt;br /&gt;
|sh&lt;br /&gt;
| -32767 - 32767&lt;br /&gt;
|Sets shift from the currently playing harmonic where 32767 equals the entire harmonic shift range shifted up&lt;br /&gt;
|-&lt;br /&gt;
|shiftrange&lt;br /&gt;
|sr&lt;br /&gt;
|0-36&lt;br /&gt;
|Set the number of harmonic numbers that constitutes an entire harmonic shift&lt;br /&gt;
|-&lt;br /&gt;
|shift5&lt;br /&gt;
|sh5&lt;br /&gt;
| -32767 - 32767&lt;br /&gt;
|Sets the shift from the currently playing harmonic over 5 octaves where 32767 equals 5 octaves shift up from the fundamental&lt;br /&gt;
|-&lt;br /&gt;
|add&lt;br /&gt;
|a&lt;br /&gt;
|(name):(ratios)&lt;br /&gt;
|Add a new series with the given name and parameters&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|series&lt;br /&gt;
|Remove the series given and shift any series accordingly. Cannot remove all series&lt;br /&gt;
|-&lt;br /&gt;
|count&lt;br /&gt;
|c&lt;br /&gt;
| -&lt;br /&gt;
|Returns the number of harmonic series in the list and their IDs&lt;br /&gt;
|}&lt;br /&gt;
The &amp;quot;harmonicserieshandler&amp;quot;-module contains at the very least ONE harmonic series, by default it contains two: one for equal temperament and one for just intonation. The current series can be selected by simply indexing the &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; without a &#039;&#039;command&#039;&#039;, e.g. &amp;quot;harmonicserieshandler.harmonicseries[1]&amp;quot;. To be consistent, these are the &#039;&#039;modules&#039;&#039; in the &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|harmonicseries&lt;br /&gt;
|hs&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; contains any number of &#039;&#039;ratios&#039;&#039; that comprises a scale, ratios are given in a standard format where a ratio of &amp;quot;1&amp;quot; is equal to the fundamental, &amp;quot;2&amp;quot; would be one octave up etc. A standard &#039;&#039;harmonic series&#039;&#039; contains 12 ratios following a just intonation scheme. The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; will automatically adapt to the currently selected &#039;&#039;harmonic series&#039;&#039; length, whether it&#039;s a standard 12-tone scale, some kinda 3-tone scale or a full on bananas 53-tone scale. The &#039;&#039;commands&#039;&#039; of the &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; is as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|[index]&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
|Sets the currently selected &#039;&#039;harmonic Series&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Sets the name of the &#039;&#039;harmonic series&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|data&lt;br /&gt;
|da&lt;br /&gt;
|name:ratios&lt;br /&gt;
|Gets / sets all data for the &#039;&#039;harmonic series&#039;&#039; in the given slot with an arbitrary &#039;&#039;name&#039;&#039; as the first &#039;&#039;parameter&#039;&#039;. The length of the series is simply set to the amount of ratios given&lt;br /&gt;
|-&lt;br /&gt;
|ratio&lt;br /&gt;
|r&lt;br /&gt;
|harmonic:ratio&lt;br /&gt;
|Sets the ratio of the given harmonic in current &#039;&#039;harmonic series&#039;&#039;, will increase the list size if needed to address the harmonic&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|harmonic&lt;br /&gt;
|Remove the harmonic ratio given in the current series and shift any ratios accordingly. Cannot remove all ratios&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;mute&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;mute&amp;quot;-&#039;&#039;module&#039;&#039; works very similarly to the &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; in that it controls a stepper motor with some software limits in place in order to press the mute against the string. The &#039;&#039;commands&#039;&#039; are as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|setposition&lt;br /&gt;
|sp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set mute position&lt;br /&gt;
|-&lt;br /&gt;
|fullmute&lt;br /&gt;
|fm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the mute in &#039;&#039;full mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|halfmute&lt;br /&gt;
|hm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the mute in &#039;&#039;half mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|rest&lt;br /&gt;
|rs&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Put the mute in the &#039;&#039;rest&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|savefull&lt;br /&gt;
|sf&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Save the current mute position as the &#039;&#039;full mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|savehalf&lt;br /&gt;
|sh&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Save the current mute position as the &#039;&#039;half mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|saverest&lt;br /&gt;
|sr&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Save the current mute position as the &#039;&#039;rest&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|fullmuteposition&lt;br /&gt;
|fmp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;full mute&#039;&#039; position according to the &#039;&#039;hardware position&#039;&#039; given&lt;br /&gt;
|-&lt;br /&gt;
|halfmuteposition&lt;br /&gt;
|hmp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;half mute&#039;&#039; position according to the &#039;&#039;hardware position&#039;&#039; given&lt;br /&gt;
|-&lt;br /&gt;
|restposition&lt;br /&gt;
|rp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;rest&#039;&#039; position according to the &#039;&#039;hardware position&#039;&#039; given&lt;br /&gt;
|-&lt;br /&gt;
|sustain&lt;br /&gt;
|su&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets the sustain off/on, this will keep the mute in the &#039;&#039;rest&#039;&#039; position even if a &amp;quot;fullmute&amp;quot;-&#039;&#039;command&#039;&#039; is given, lasts until &amp;quot;sustain&amp;quot; is set to &amp;quot;0&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
|backoff&lt;br /&gt;
|bo&lt;br /&gt;
|0-65535&lt;br /&gt;
|Setting the time that the mute stays in the mutefullmute position before automatically going into rest, set in mS. A value of &amp;quot;0&amp;quot; disables backoff. This is used because if the mute is not backing off until something is attempted to be played, the backing-off time will either introduce &#039;&#039;latency&#039;&#039; or the string will be initially partially muted&lt;br /&gt;
|-&lt;br /&gt;
|home&lt;br /&gt;
|hm&lt;br /&gt;
| -&lt;br /&gt;
|Home mute, used during initialization and if the mute were to loose position&lt;br /&gt;
|-&lt;br /&gt;
|hardwareposition&lt;br /&gt;
|hwp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;hardware position&#039;&#039; of the mute instead of scaling it over the &#039;&#039;full mute&#039;&#039; and &#039;&#039;rest&#039;&#039; positions. Mainly used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|completetask&lt;br /&gt;
|cpt&lt;br /&gt;
| -&lt;br /&gt;
|Requests a callback when the current operation is finished. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|autocorrect&lt;br /&gt;
|ac&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Enables auto correct positioning that uses the homing sensor to correct positioning on the fly. EXPERIMENTAL&lt;br /&gt;
|-&lt;br /&gt;
|homingsensed&lt;br /&gt;
|hms&lt;br /&gt;
| -&lt;br /&gt;
|Requests whether the homing sensor is currently active or not. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|movedirection&lt;br /&gt;
|md&lt;br /&gt;
| -&lt;br /&gt;
|Requests the current direction of movement (0 Forward, 1 Reverse). Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|currentstep&lt;br /&gt;
|cs&lt;br /&gt;
| -&lt;br /&gt;
|Requests the current step. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|homingpoint&lt;br /&gt;
|hmp&lt;br /&gt;
|edgedirection&lt;br /&gt;
|Requests the given homing point. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|homingstage&lt;br /&gt;
|hms&lt;br /&gt;
| -&lt;br /&gt;
|Requests the current homing stage (UNHOMED, HOMED, FIRSTHOMINGRISING, SECONDHOMINGFALLING, SECONDHOMINGRISING, FIRSTHOMINGFALLING, MOVEPASTHOMESWITCH, MOVETOHOMESWITCH, GOTOOFFSET). Only used internally by other &#039;&#039;modules.&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|tmcinfo&lt;br /&gt;
|tmi&lt;br /&gt;
| -&lt;br /&gt;
|Request statistical information from the TMC2209 stepper motor driver&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;solenoid&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;solenoid&amp;quot;-&#039;&#039;module&#039;&#039; currently controls the &#039;&#039;hammer&#039;&#039; of the Ekdahl FAR. Due to the fact that the very same &#039;&#039;module&#039;&#039; could be used for anything that uses a striking &#039;&#039;solenoid&#039;&#039; it was named as such. It has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|engage&lt;br /&gt;
|en&lt;br /&gt;
|0-65535&lt;br /&gt;
|Engages the solenoid using the first parameter as the force&lt;br /&gt;
|-&lt;br /&gt;
|rest&lt;br /&gt;
|rs&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Forces the solenoid to its rest position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|maxforce&lt;br /&gt;
|xf&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set solenoid maximum usable force&lt;br /&gt;
|-&lt;br /&gt;
|minforce&lt;br /&gt;
|if&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set solenoid minimum usable force&lt;br /&gt;
|-&lt;br /&gt;
|forcemultiplier&lt;br /&gt;
|fm&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set solenoid force multiplier, useful for scaling of all incoming &amp;quot;engage&amp;quot;-&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|engageduration&lt;br /&gt;
|ed&lt;br /&gt;
|uS&lt;br /&gt;
|Sets the duration of the solenoid hit in uS, if a value of 0 is set the solenoid will not disengage until a rest command has been given. WARNING!! HAVING THE SOLENOID ON FOR A SPAN OF SECONDS COULD DESTROY THE CIRCUITRY!!&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;controlbox&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;controlbox&amp;quot;-&#039;&#039;module&#039;&#039; communicates with an external &#039;&#039;control box&#039;&#039; and will issue associated &#039;&#039;commands&#039;&#039; whenever new values are read on the ADC-converters. It handles averaging and does some noise-cancellation functions on the values as well. The &#039;&#039;commands&#039;&#039; are:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|harmonic&lt;br /&gt;
|har&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the harmonic knob or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|harmonicshift&lt;br /&gt;
|has&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the harmonic shift modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|finetune&lt;br /&gt;
|fin&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the fine tune knob changes&lt;br /&gt;
|-&lt;br /&gt;
|pressure&lt;br /&gt;
|pre&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the pressure knob or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|mute&lt;br /&gt;
|mut&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the mute knob or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|hammerscale&lt;br /&gt;
|hms&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the hammer scale knob changes&lt;br /&gt;
|-&lt;br /&gt;
|gate&lt;br /&gt;
|gt&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the gate switch or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|hammertrig&lt;br /&gt;
|hmt&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the hammer trigger modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|controldefaults&lt;br /&gt;
|cde&lt;br /&gt;
| -&lt;br /&gt;
|Reverts all ADC command strings to default values&lt;br /&gt;
|-&lt;br /&gt;
|datareturn&lt;br /&gt;
|dr&lt;br /&gt;
|channel:value&lt;br /&gt;
|Sent when a new value is presented on one of the ADC channels, cannot be invoked. Triggers the commands associated with the channel&lt;br /&gt;
|-&lt;br /&gt;
|adcsetting&lt;br /&gt;
|adcs&lt;br /&gt;
|channel : averages : interrupterrorthreshold : continuouserrorthreshold : continuoustimeout&lt;br /&gt;
|Sets ADC settings for a given channel. Averages are the number of samples to average, interruptthreshold is how much the value must change in order to issue a new value change event. continuousthreshold is how much the value must change when a previous change has already been recorded within the timespan of continuoustimeout&lt;br /&gt;
|-&lt;br /&gt;
|testadclatency&lt;br /&gt;
|tal&lt;br /&gt;
|0-65535&lt;br /&gt;
|Start a ADC latency test&lt;br /&gt;
|-&lt;br /&gt;
|testadclatencyreturn&lt;br /&gt;
|talr&lt;br /&gt;
| -&lt;br /&gt;
|Return from latency test&lt;br /&gt;
|-&lt;br /&gt;
|testadcminmax&lt;br /&gt;
|tix&lt;br /&gt;
|channel&lt;br /&gt;
|Test min/max value for a given channel and resets the counter&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;midiconfigurationhandler&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;midiconfigurationhandler&amp;quot;-&#039;&#039;module&#039;&#039; handles a number of &amp;quot;midiconfiguration&amp;quot;-&#039;&#039;modules&#039;&#039;. It has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|allnotesoff&lt;br /&gt;
|ano&lt;br /&gt;
| -&lt;br /&gt;
|Clears the entire buffer of MIDI notes held&lt;br /&gt;
|-&lt;br /&gt;
|add&lt;br /&gt;
|a&lt;br /&gt;
|name&lt;br /&gt;
|Adds a new MIDI configuration with the given name&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|int&lt;br /&gt;
|Remove the specified MIDI configuration&lt;br /&gt;
|-&lt;br /&gt;
|count&lt;br /&gt;
|c&lt;br /&gt;
| -&lt;br /&gt;
|Returns the number of MIDI configurations&lt;br /&gt;
|}&lt;br /&gt;
It contains one or more of the following&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|midiconfiguration&lt;br /&gt;
|mc&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;midiconfiguration&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
A &amp;quot;midiconfiguration&amp;quot;-&#039;&#039;module&#039;&#039; handles the reception of &#039;&#039;MIDI messages&#039;&#039; and will output the associated &#039;&#039;commands&#039;&#039; to the instrument internally. The commands are as follows&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|[index]&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
|Sets the currently selected MIDI configuration&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Set the name of the MIDI configuration&lt;br /&gt;
|-&lt;br /&gt;
|noteon&lt;br /&gt;
|non&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Note On event&lt;br /&gt;
|-&lt;br /&gt;
|noteoff&lt;br /&gt;
|nof&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Note Off event&lt;br /&gt;
|-&lt;br /&gt;
|polyaftertouch&lt;br /&gt;
|pat&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Polyphonic after touch event&lt;br /&gt;
|-&lt;br /&gt;
|channelaftertouch&lt;br /&gt;
|cat&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Channel after touch event&lt;br /&gt;
|-&lt;br /&gt;
|pitchbend&lt;br /&gt;
|pb&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Pitch bend event&lt;br /&gt;
|-&lt;br /&gt;
|programchange&lt;br /&gt;
|pc&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Program change event&lt;br /&gt;
|-&lt;br /&gt;
|continuouscontrollerdata&lt;br /&gt;
|ccd&lt;br /&gt;
|controllernuber:&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Continuous controller event with the given [&#039;&#039;controllernumber&#039;&#039;]&lt;br /&gt;
|-&lt;br /&gt;
|removecc&lt;br /&gt;
|rmc&lt;br /&gt;
|controllernuber&lt;br /&gt;
|Removes the entry associated with the MIDI continuous controller even &#039;&#039;controllernumber&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|defaults&lt;br /&gt;
|d&lt;br /&gt;
| -&lt;br /&gt;
|Reverts the current configuration to default &#039;&#039;commands&#039;&#039;, values and CCs&lt;br /&gt;
|-&lt;br /&gt;
|receivechannel&lt;br /&gt;
|rc&lt;br /&gt;
|channel&lt;br /&gt;
|Sets the MIDI receive channel of the current configuration. 1-16 sets specific channel, any other value for OMNI&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;pluginhandler&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;/div&gt;</summary>
		<author><name>Knaadmin</name></author>
	</entry>
	<entry>
		<id>http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_reference_V1.1&amp;diff=1681</id>
		<title>The Ekdahl FAR - Command reference V1.1</title>
		<link rel="alternate" type="text/html" href="http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_reference_V1.1&amp;diff=1681"/>
		<updated>2026-06-14T06:53:39Z</updated>

		<summary type="html">&lt;p&gt;Knaadmin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
The Ekdahl FAR V1.1 introduces the concept of &#039;&#039;modules&#039;&#039;. A &#039;&#039;module&#039;&#039; can contain any number of &#039;&#039;commands&#039;&#039; as well as other &#039;&#039;modules&#039;&#039;. Furthermore any number of &#039;&#039;modules&#039;&#039; of the same type can exist within a context, these are addressed using classic C-style array &#039;&#039;indexing&#039;&#039; with the help of brackets (&amp;quot;[ ]&amp;quot;). Extending on the classic usage, multiple &#039;&#039;indexes&#039;&#039; can be addressed simultaneously by either comma-separating the objects (&amp;quot;[0,3,4]&amp;quot;) and using &#039;&#039;ranges&#039;&#039; (&amp;quot;[3-6]&amp;quot;). &#039;&#039;Modules&#039;&#039; can be either &#039;&#039;internal&#039;&#039; or &#039;&#039;external&#039;&#039;, meaning that they may all physically exist within a single hardware object, or they can be be remote-controlled devices. From a user perspective this however makes no difference as they will appear the same.&lt;br /&gt;
&lt;br /&gt;
While all &#039;&#039;modules&#039;&#039; have their own set of &#039;&#039;commands&#039;&#039;, there are certain &#039;&#039;commands&#039;&#039; that all &#039;&#039;modules&#039;&#039; &amp;lt;u&amp;gt;must&amp;lt;/u&amp;gt; implement and can thus be accessed anywhere within the &#039;&#039;module hierarchy.&#039;&#039; There are also &#039;&#039;base commands&#039;&#039; that always exist within any given FAR ecosystem as well as product-specific &#039;&#039;base commands&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Ubiquitous commands ==&lt;br /&gt;
The &#039;&#039;module commands&#039;&#039; that are &amp;lt;u&amp;gt;required&amp;lt;/u&amp;gt; to be implemented in &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; &#039;&#039;modules&#039;&#039; and that can thus be accessed from anywhere are&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|list&lt;br /&gt;
|ls&lt;br /&gt;
|hidden/h:modules/m:commands/c:instances/i:instancecounts/ic:recursive/r&lt;br /&gt;
|Lists all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039; under the current module depending on the parameters given; &#039;hidden&#039; includes normally hidden &#039;&#039;commands&#039;&#039;, &#039;modules&#039; includes any &#039;&#039;submodules&#039;&#039;, &#039;commands&#039; shows &#039;&#039;commands&#039;&#039;, &#039;instances&#039; shows data for each individual instance of a &#039;&#039;module&#039;&#039;, &#039;instancecounts&#039; includes number of instances of each &#039;&#039;module&#039;&#039;, &#039;recursive&#039; lists all child &#039;&#039;modules&#039;&#039; / &#039;&#039;commands&#039;&#039;. No parameters defaults to showing all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039; recursively with instance counts. It doesn&#039;t show per-instance data or hidden commands.&lt;br /&gt;
|-&lt;br /&gt;
|help&lt;br /&gt;
|help&lt;br /&gt;
|recursive/r&lt;br /&gt;
|Shows a brief explanation of all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039;, shows the help for all &#039;&#039;submodules&#039;&#039; as well if &#039;recursive&#039;&lt;br /&gt;
|-&lt;br /&gt;
|dumpdata&lt;br /&gt;
|dump&lt;br /&gt;
|recursive/r&lt;br /&gt;
|Dumps all data saved for the current &#039;&#039;module&#039;&#039;, will list the data of all &#039;&#039;submodules&#039;&#039; as well if &#039;recursive&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Base commands ==&lt;br /&gt;
B&#039;&#039;ase commands&#039;&#039; are &#039;&#039;commands&#039;&#039; that always exist at the root in any implementation of the Ekdahl FAR.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|version&lt;br /&gt;
|ver&lt;br /&gt;
| -&lt;br /&gt;
|Gets the current firmware version&lt;br /&gt;
|-&lt;br /&gt;
|debugprint&lt;br /&gt;
|dp&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;command|usb|hardware|undefined|priority|error|inforequest|expressionparser|debug:1|0&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Turns on or off serial feedback for the given item&lt;br /&gt;
|-&lt;br /&gt;
|requestinfo&lt;br /&gt;
|rqi&lt;br /&gt;
|command&lt;br /&gt;
|Retrives any data saved for a &#039;&#039;command&#039;&#039;, if applicable&lt;br /&gt;
|-&lt;br /&gt;
|saveallparameters&lt;br /&gt;
|sap&lt;br /&gt;
| -&lt;br /&gt;
|Saves all avaliable parameters&lt;br /&gt;
|-&lt;br /&gt;
|loadallparameters&lt;br /&gt;
|lap&lt;br /&gt;
| -&lt;br /&gt;
|Loads all avaliable parameters&lt;br /&gt;
|-&lt;br /&gt;
|resetallparameters&lt;br /&gt;
|rap&lt;br /&gt;
| -&lt;br /&gt;
|Resets all saved parameters&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|rst&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;1|0&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Resets the Ekdahl FAR, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|nick&lt;br /&gt;
|nick&lt;br /&gt;
|name&lt;br /&gt;
|Sets the nickname of this unit&lt;br /&gt;
|-&lt;br /&gt;
|nooperation&lt;br /&gt;
|nop&lt;br /&gt;
| -&lt;br /&gt;
|Do absolutely, positively, nothing. Useful for testing and interfacing with computers, it&#039;s a good way to know that the unit is alive and responding since a &amp;quot;nop&amp;quot; is being returned as a response upon reception.&lt;br /&gt;
|-&lt;br /&gt;
|uservariable&lt;br /&gt;
|uv&lt;br /&gt;
|variable(0-9):value&lt;br /&gt;
|Set user variable 0-9 to &#039;value&#039;&lt;br /&gt;
|-&lt;br /&gt;
|expressionparserevaluate&lt;br /&gt;
|epev&lt;br /&gt;
|expression&lt;br /&gt;
|Evaluates an arithmetric expression and sends back the output, all variables and functions that can be used in any &#039;&#039;command string&#039;&#039; can also be used here. Useful for testing expressions.&lt;br /&gt;
|-&lt;br /&gt;
|ifequal&lt;br /&gt;
|ife&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] EQUALS [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring].&lt;br /&gt;
|-&lt;br /&gt;
|ifgreater&lt;br /&gt;
|ifg&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] &amp;gt; [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring]&lt;br /&gt;
|-&lt;br /&gt;
|ifless&lt;br /&gt;
|ifl&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] &amp;lt; [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring]&lt;br /&gt;
|-&lt;br /&gt;
|freeram&lt;br /&gt;
|ram&lt;br /&gt;
| -&lt;br /&gt;
|Shows free RAM memory&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The base also contains the following &#039;&#039;modules:&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|pluginhandler&lt;br /&gt;
|ph&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The Ekdahl FAR stand alone single string unit ==&lt;br /&gt;
The Ekdahl FAR stand-alone single string unit offers these &#039;&#039;commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|calibrateall&lt;br /&gt;
|ca&lt;br /&gt;
| -&lt;br /&gt;
|Performs all calibration routines on the selected bow, see below for routines performed&lt;br /&gt;
|-&lt;br /&gt;
|calibratebowspeed&lt;br /&gt;
|cbs&lt;br /&gt;
| -&lt;br /&gt;
|Finds the minimum and maximum bow speed of the selected bow&lt;br /&gt;
|-&lt;br /&gt;
|calibratebowpressure&lt;br /&gt;
|cbp&lt;br /&gt;
| -&lt;br /&gt;
|Finds the minimum and maximum bow pressure of the selected bow&lt;br /&gt;
|-&lt;br /&gt;
|calibratemute&lt;br /&gt;
|cmu&lt;br /&gt;
| -&lt;br /&gt;
|Calibrate mute settings&lt;br /&gt;
|-&lt;br /&gt;
|pickupstringfrequency&lt;br /&gt;
|psf&lt;br /&gt;
| -&lt;br /&gt;
|Returns the fundamental tone calculated from the current audio signal if apliccable&lt;br /&gt;
|-&lt;br /&gt;
|pickupaudiopeak&lt;br /&gt;
|pap&lt;br /&gt;
| -&lt;br /&gt;
|Returns the peak amplitude of the current audio signal&lt;br /&gt;
|-&lt;br /&gt;
|pickupaudiorms&lt;br /&gt;
|par&lt;br /&gt;
| -&lt;br /&gt;
|Returns the RMS amplitude of the current audio signal&lt;br /&gt;
|}&lt;br /&gt;
The Ekdahl FAR also contains the following &#039;&#039;modules&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|bowingwheel&lt;br /&gt;
|bw&lt;br /&gt;
|-&lt;br /&gt;
|mute&lt;br /&gt;
|mu&lt;br /&gt;
|-&lt;br /&gt;
|solenoid&lt;br /&gt;
|so&lt;br /&gt;
|-&lt;br /&gt;
|controlbox&lt;br /&gt;
|cb&lt;br /&gt;
|-&lt;br /&gt;
|midiconfigurationhandler&lt;br /&gt;
|mcf&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;Bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; contains everything needed to interface with a single &#039;&#039;bowing wheel&#039;&#039;. Each &#039;&#039;bowing wheel&#039;&#039; has its own harmonic series, pressure actuators and direct hardware interface. It contains the following &#039;&#039;commands&#039;&#039;.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|speedmode&lt;br /&gt;
|sm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Bow motor speed mode, 0 = Automatic and 1 = Manual. Automatic mode means that the bowing wheel will automatically turn off after the &#039;&#039;motor timeout&#039;&#039; has been reached after being put into rest mode&lt;br /&gt;
|-&lt;br /&gt;
|motortimeout&lt;br /&gt;
|mt&lt;br /&gt;
|ms&lt;br /&gt;
|Bow motor shutdown timeout after bow having been put into the rest position&lt;br /&gt;
|-&lt;br /&gt;
|pidenable&lt;br /&gt;
|pe&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets the bow PID on/off&lt;br /&gt;
|-&lt;br /&gt;
|motorfaultcommands&lt;br /&gt;
|mfc&lt;br /&gt;
|commands&lt;br /&gt;
|Commands to execute when a motor fault is tripped - !WARNING! Can ruin your instrument if changed&lt;br /&gt;
|-&lt;br /&gt;
|motoroverpowercommands&lt;br /&gt;
|moc&lt;br /&gt;
|commands&lt;br /&gt;
|Commands to execute when motor is over the power limit - !WARNING! Can ruin your instrument if changed&lt;br /&gt;
|}&lt;br /&gt;
The &#039;&#039;modules&#039;&#039; in the &amp;quot;Bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; are as follows&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|bowpressure&lt;br /&gt;
|bp&lt;br /&gt;
|-&lt;br /&gt;
|dcmotor&lt;br /&gt;
|dcm&lt;br /&gt;
|-&lt;br /&gt;
|pid&lt;br /&gt;
|pid&lt;br /&gt;
|-&lt;br /&gt;
|harmonicserieshandler&lt;br /&gt;
|hsh&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; handles the &#039;&#039;pressure&#039;&#039; of the &#039;&#039;bowing wheel&#039;&#039; against the string. The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|baseline&lt;br /&gt;
|ba&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure baseline, modulation is added to this point upward. Typically this is set with a knob on the &#039;&#039;control box&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|modifier&lt;br /&gt;
|mo&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure modulation, added to the baseline&lt;br /&gt;
|-&lt;br /&gt;
|rest&lt;br /&gt;
|rs&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the bow pressure in the &#039;&#039;rest&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|engage&lt;br /&gt;
|en&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the bow pressure in the &#039;&#039;engage&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|stallpressure&lt;br /&gt;
|sp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure stall/maximum position, this parameter is set using &#039;&#039;hardware positioning&#039;&#039; and is used as the absolute maximum for baseline and modifier combiner&lt;br /&gt;
|-&lt;br /&gt;
|engagepressure&lt;br /&gt;
|ep&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure touch/minimum position, this parameter is set using &#039;&#039;hardware position&#039;&#039; and is used as the starting point for when both the baseline and modifier is set to zero&lt;br /&gt;
|-&lt;br /&gt;
|restpressure&lt;br /&gt;
|rp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure rest position, this parameter is set using &#039;&#039;hardware positioning&#039;&#039; and is typically set to a point just below the string where it does not touch at all. The purpose of this is because while the actual hardware might be able to make the bow go even lower, that position might be far enough from the string that once &#039;&#039;engaged&#039;&#039; the bow may have so far to travel that there is perceptible &#039;&#039;latency&#039;&#039;.&lt;br /&gt;
|-&lt;br /&gt;
|engagespeed&lt;br /&gt;
|es&lt;br /&gt;
|1- ~100&lt;br /&gt;
|Bow pressure movement speed when engaging or disengaging&lt;br /&gt;
|-&lt;br /&gt;
|modulationspeed&lt;br /&gt;
|ms&lt;br /&gt;
|0.1 - 10&lt;br /&gt;
|Bow pressure movement speed while engaged&lt;br /&gt;
|-&lt;br /&gt;
|hold&lt;br /&gt;
|hd&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets bow hold (infinite sustain) on/off, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|home&lt;br /&gt;
|hm&lt;br /&gt;
| -&lt;br /&gt;
|Homing bow, used at startup and in case of the bow loosing position&lt;br /&gt;
|-&lt;br /&gt;
|tmcinfo&lt;br /&gt;
|tmi&lt;br /&gt;
| -&lt;br /&gt;
|Request statistical information from the TMC2209 stepper motor driver&lt;br /&gt;
|}&lt;br /&gt;
Note that the &amp;quot;stall&amp;quot;, &amp;quot;engage&amp;quot; and &amp;quot;rest&amp;quot;-pressure positions mention something called &#039;&#039;hardware position&#039;&#039;. This means the entire available movement of the &#039;&#039;bowing jack&#039;&#039;. Because the very bottom and top end of the movement might not be musically useful and may even harm the instrument, the &amp;quot;baseline&amp;quot; and &amp;quot;modifier&amp;quot; commands &#039;&#039;parameter&#039;&#039;s are scaled depending on these settings.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;engage&amp;quot; and &amp;quot;modulation&amp;quot;-speed settings sets how fast the stepper motor that drives the &#039;&#039;pressure&#039;&#039; moves depending on whether the &#039;&#039;bowing jack&#039;&#039; is set to &#039;&#039;engage&#039;&#039; or not. The idea here is that while wanting to be able to minimize &#039;&#039;latency&#039;&#039; by &#039;&#039;engaging&#039;&#039; and &#039;&#039;disengaging&#039;&#039; from the string as quickly as possible, dynamic changes in the &#039;&#039;pressure&#039;&#039; while playing benefits from much smoother movements as the &#039;&#039;bowing wheel&#039;&#039; takes some time to catch up to varying amounts of friction.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; contains one or more of the following &#039;&#039;modules&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|actuatorhandler&lt;br /&gt;
|ah&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;actuatorhandler&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The concept of &amp;quot;actuators&amp;quot; came up as it is possible to have &#039;&#039;bowing wheels&#039;&#039; of different sizes and wanting to be able to switch quickly in between them, perhaps during mid-performance. Because a differently sized wheel will require different values for the above mentioned &amp;quot;stall&amp;quot;, &amp;quot;engage&amp;quot; and &amp;quot;reset&amp;quot;-&#039;&#039;pressure&#039;&#039;, each &#039;&#039;actuator&#039;&#039; stores these values. Instead of having to manually change the previously mentioned values, simply selecting a new &#039;&#039;actuator&#039;&#039; will automatically load the values. The &amp;quot;actuatorhandler&amp;quot;-&#039;&#039;module&#039;&#039; is the handler of one or more &amp;quot;actuator&amp;quot;-&#039;&#039;modules&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;commands&#039;&#039; of the &amp;quot;acuatorhandler&amp;quot;-&#039;&#039;module&#039;&#039; are as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|add&lt;br /&gt;
|a&lt;br /&gt;
|(name):(rest:engage:stall)&lt;br /&gt;
|Add new actuator with the given name and parameters&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|actuatornumber&lt;br /&gt;
|Remove bow actuator [actuatornumber]&lt;br /&gt;
|-&lt;br /&gt;
|count&lt;br /&gt;
|c&lt;br /&gt;
| -&lt;br /&gt;
|Returns the amount of saved bow actuators&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;dcmotor&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;dcmotor&amp;quot;-&#039;&#039;module&#039;&#039; handles the direct &amp;lt;u&amp;gt;raw&amp;lt;/u&amp;gt; control of the &#039;&#039;bowing motor&#039;&#039; and handles the reporting back of the current speed. It has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|run&lt;br /&gt;
|ru&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Turns the motor off/on&lt;br /&gt;
|-&lt;br /&gt;
|pwm&lt;br /&gt;
|pw&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor direct power in 16-bit PWM values, requires that the &#039;&#039;PID&#039;&#039; is turned off&lt;br /&gt;
|-&lt;br /&gt;
|voltage&lt;br /&gt;
|vo&lt;br /&gt;
|~2 - 10V&lt;br /&gt;
|Sets the voltage of the regulator powering the motor. Changes here can make the motor more responsive to certain frequencies but will also affect how well the &#039;&#039;PID&#039;&#039; works. !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|current&lt;br /&gt;
|cu&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor reported current use&lt;br /&gt;
|-&lt;br /&gt;
|currentlimit&lt;br /&gt;
|cl&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor current limit (A)- !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|powerlimit&lt;br /&gt;
|pl&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor power limit (W) - !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|frequency&lt;br /&gt;
|fq&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor reported frequency&lt;br /&gt;
|-&lt;br /&gt;
|emergencystop&lt;br /&gt;
|es&lt;br /&gt;
|ms (0-65535)&lt;br /&gt;
|Immediately stops the bowing motor and doesn&#039;t allow it to start again until the cool down period given in the first argument has lapsed (milliseconds)&lt;br /&gt;
|-&lt;br /&gt;
|minpwm&lt;br /&gt;
|ip&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor minimum PWM (for calibration)&lt;br /&gt;
|-&lt;br /&gt;
|maxpwm&lt;br /&gt;
|xp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor maximum PWM (for calibration)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;pidcontroller&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;pidcontroller&amp;quot;-&#039;&#039;module&#039;&#039; is responsible for keeping the &amp;quot;dcmotor&amp;quot;-&#039;&#039;module&#039;&#039; at a certain frequency (given in Hertz). It takes the output of the motor frequency measurement and feeds it a PWM value that tries to make the speed constant regardless of the friction that the motor is enduring. To learn more about PID Controllers please see this [[wikipedia:PID_controller|wikipedia article]]. The &#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|targetfrequency&lt;br /&gt;
|tf&lt;br /&gt;
|hertz&lt;br /&gt;
|Sets the PID target frequency&lt;br /&gt;
|-&lt;br /&gt;
|ki&lt;br /&gt;
|ki&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Ki parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|kp&lt;br /&gt;
|kp&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Kp parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|kd&lt;br /&gt;
|kd&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Kd parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|integratorerror&lt;br /&gt;
|ie&lt;br /&gt;
|float&lt;br /&gt;
|Sets the lower threshold of error values for the PID integrator to ignore&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|re&lt;br /&gt;
| -&lt;br /&gt;
|Resets the PID integrator and derivative&lt;br /&gt;
|-&lt;br /&gt;
|maxerror&lt;br /&gt;
|xe&lt;br /&gt;
|float&lt;br /&gt;
|Maximum error to correct in each PID loop, essentially sets acceleration&lt;br /&gt;
|-&lt;br /&gt;
|peakerror&lt;br /&gt;
|pe&lt;br /&gt;
|float&lt;br /&gt;
|Get latest PID peak error&lt;br /&gt;
|-&lt;br /&gt;
|motorspeedmax&lt;br /&gt;
|msx&lt;br /&gt;
|Hertz&lt;br /&gt;
|Bow motor maximum speed limit&lt;br /&gt;
|-&lt;br /&gt;
|motorspeedmin&lt;br /&gt;
|msi&lt;br /&gt;
|Hertz&lt;br /&gt;
|Bow motor minimum speed limit&lt;br /&gt;
|-&lt;br /&gt;
|measuretimetotarget&lt;br /&gt;
|mtt&lt;br /&gt;
|Hertz&lt;br /&gt;
|Measure the time it takes to change from the current frequency to the target frequency, for testing purposes&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; is responsible for sending frequency data to the &amp;quot;pid&amp;quot;-&#039;&#039;module&#039;&#039;. It handles calculating the correct frequency of the &#039;&#039;bowing wheel&#039;&#039; according to the selected &#039;&#039;harmonic&#039;&#039; and &#039;&#039;harmonic shift&#039;&#039; per the currently selected &#039;&#039;harmonic series&#039;&#039;. The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|fundamental&lt;br /&gt;
|fu&lt;br /&gt;
|Hertz&lt;br /&gt;
|The fundamental frequency of the string, all harmonics are calculated from this number&lt;br /&gt;
|-&lt;br /&gt;
|harmonic&lt;br /&gt;
|h&lt;br /&gt;
|int&lt;br /&gt;
|Selects the harmonic number to set the &#039;&#039;bowing wheel&#039;&#039; to. A ratio is taken from the given &#039;&#039;harmonic&#039;&#039; in the current &#039;&#039;harmonic series&#039;&#039;, the ratio is then multiplied by the &#039;&#039;fundamental frequency&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|harmonicadd&lt;br /&gt;
|ha&lt;br /&gt;
|int&lt;br /&gt;
|This number is added to the current harmonic&lt;br /&gt;
|-&lt;br /&gt;
|harmonicbase&lt;br /&gt;
|hb&lt;br /&gt;
|int&lt;br /&gt;
|Same as harmonic but where the harmonic number is based on a MIDI note given by basenote&lt;br /&gt;
|-&lt;br /&gt;
|basenote&lt;br /&gt;
|bn&lt;br /&gt;
|0-127&lt;br /&gt;
|Sets the MIDI base note of the &#039;&#039;bowing wheel&#039;&#039;, used in conjunction with &amp;quot;harmonicbase&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|shift&lt;br /&gt;
|sh&lt;br /&gt;
| -32767 - 32767&lt;br /&gt;
|Sets shift from the currently playing harmonic where 32767 equals the entire harmonic shift range shifted up&lt;br /&gt;
|-&lt;br /&gt;
|shiftrange&lt;br /&gt;
|sr&lt;br /&gt;
|0-36&lt;br /&gt;
|Set the number of harmonic numbers that constitutes an entire harmonic shift&lt;br /&gt;
|-&lt;br /&gt;
|shift5&lt;br /&gt;
|sh5&lt;br /&gt;
| -32767 - 32767&lt;br /&gt;
|Sets the shift from the currently playing harmonic over 5 octaves where 32767 equals 5 octaves shift up from the fundamental&lt;br /&gt;
|-&lt;br /&gt;
|add&lt;br /&gt;
|a&lt;br /&gt;
|(name):(ratios)&lt;br /&gt;
|Add a new series with the given name and parameters&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|series&lt;br /&gt;
|Remove the series given and shift any series accordingly. Cannot remove all series&lt;br /&gt;
|-&lt;br /&gt;
|count&lt;br /&gt;
|c&lt;br /&gt;
| -&lt;br /&gt;
|Returns the number of harmonic series in the list and their IDs&lt;br /&gt;
|}&lt;br /&gt;
The &amp;quot;harmonicserieshandler&amp;quot;-module contains at the very least ONE harmonic series, by default it contains two: one for equal temperament and one for just intonation. The current series can be selected by simply indexing the &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; without a &#039;&#039;command&#039;&#039;, e.g. &amp;quot;harmonicserieshandler.harmonicseries[1]&amp;quot;. To be consistent, these are the &#039;&#039;modules&#039;&#039; in the &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|harmonicseries&lt;br /&gt;
|hs&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; contains any number of &#039;&#039;ratios&#039;&#039; that comprises a scale, ratios are given in a standard format where a ratio of &amp;quot;1&amp;quot; is equal to the fundamental, &amp;quot;2&amp;quot; would be one octave up etc. A standard &#039;&#039;harmonic series&#039;&#039; contains 12 ratios following a just intonation scheme. The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; will automatically adapt to the currently selected &#039;&#039;harmonic series&#039;&#039; length, whether it&#039;s a standard 12-tone scale, some kinda 3-tone scale or a full on bananas 53-tone scale. The &#039;&#039;commands&#039;&#039; of the &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; is as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|[index]&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
|Sets the currently selected &#039;&#039;harmonic Series&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Sets the name of the &#039;&#039;harmonic series&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|data&lt;br /&gt;
|da&lt;br /&gt;
|name:ratios&lt;br /&gt;
|Gets / sets all data for the &#039;&#039;harmonic series&#039;&#039; in the given slot with an arbitrary &#039;&#039;name&#039;&#039; as the first &#039;&#039;parameter&#039;&#039;. The length of the series is simply set to the amount of ratios given&lt;br /&gt;
|-&lt;br /&gt;
|ratio&lt;br /&gt;
|r&lt;br /&gt;
|harmonic:ratio&lt;br /&gt;
|Sets the ratio of the given harmonic in current &#039;&#039;harmonic series&#039;&#039;, will increase the list size if needed to address the harmonic&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|harmonic&lt;br /&gt;
|Remove the harmonic ratio given in the current series and shift any ratios accordingly. Cannot remove all ratios&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;mute&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;mute&amp;quot;-&#039;&#039;module&#039;&#039; works very similarly to the &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; in that it controls a stepper motor with some software limits in place in order to press the mute against the string. The &#039;&#039;commands&#039;&#039; are as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|setposition&lt;br /&gt;
|sp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set mute position&lt;br /&gt;
|-&lt;br /&gt;
|fullmute&lt;br /&gt;
|fm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the mute in &#039;&#039;full mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|halfmute&lt;br /&gt;
|hm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the mute in &#039;&#039;half mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|rest&lt;br /&gt;
|rs&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Put the mute in the &#039;&#039;rest&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|savefull&lt;br /&gt;
|sf&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Save the current mute position as the &#039;&#039;full mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|savehalf&lt;br /&gt;
|sh&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Save the current mute position as the &#039;&#039;half mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|saverest&lt;br /&gt;
|sr&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Save the current mute position as the &#039;&#039;rest&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|fullmuteposition&lt;br /&gt;
|fmp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;full mute&#039;&#039; position according to the &#039;&#039;hardware position&#039;&#039; given&lt;br /&gt;
|-&lt;br /&gt;
|halfmuteposition&lt;br /&gt;
|hmp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;half mute&#039;&#039; position according to the &#039;&#039;hardware position&#039;&#039; given&lt;br /&gt;
|-&lt;br /&gt;
|restposition&lt;br /&gt;
|rp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;rest&#039;&#039; position according to the &#039;&#039;hardware position&#039;&#039; given&lt;br /&gt;
|-&lt;br /&gt;
|sustain&lt;br /&gt;
|su&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets the sustain off/on, this will keep the mute in the &#039;&#039;rest&#039;&#039; position even if a &amp;quot;fullmute&amp;quot;-&#039;&#039;command&#039;&#039; is given, lasts until &amp;quot;sustain&amp;quot; is set to &amp;quot;0&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
|backoff&lt;br /&gt;
|bo&lt;br /&gt;
|0-65535&lt;br /&gt;
|Setting the time that the mute stays in the mutefullmute position before automatically going into rest, set in mS. A value of &amp;quot;0&amp;quot; disables backoff. This is used because if the mute is not backing off until something is attempted to be played, the backing-off time will either introduce &#039;&#039;latency&#039;&#039; or the string will be initially partially muted&lt;br /&gt;
|-&lt;br /&gt;
|home&lt;br /&gt;
|hm&lt;br /&gt;
| -&lt;br /&gt;
|Home mute, used during initialization and if the mute were to loose position&lt;br /&gt;
|-&lt;br /&gt;
|hardwareposition&lt;br /&gt;
|hwp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;hardware position&#039;&#039; of the mute instead of scaling it over the &#039;&#039;full mute&#039;&#039; and &#039;&#039;rest&#039;&#039; positions. Mainly used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|completetask&lt;br /&gt;
|cpt&lt;br /&gt;
| -&lt;br /&gt;
|Requests a callback when the current operation is finished. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|autocorrect&lt;br /&gt;
|ac&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Enables auto correct positioning that uses the homing sensor to correct positioning on the fly. EXPERIMENTAL&lt;br /&gt;
|-&lt;br /&gt;
|homingsensed&lt;br /&gt;
|hms&lt;br /&gt;
| -&lt;br /&gt;
|Requests whether the homing sensor is currently active or not. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|movedirection&lt;br /&gt;
|md&lt;br /&gt;
| -&lt;br /&gt;
|Requests the current direction of movement (0 Forward, 1 Reverse). Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|currentstep&lt;br /&gt;
|cs&lt;br /&gt;
| -&lt;br /&gt;
|Requests the current step. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|homingpoint&lt;br /&gt;
|hmp&lt;br /&gt;
|edgedirection&lt;br /&gt;
|Requests the given homing point. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|homingstage&lt;br /&gt;
|hms&lt;br /&gt;
| -&lt;br /&gt;
|Requests the current homing stage (UNHOMED, HOMED, FIRSTHOMINGRISING, SECONDHOMINGFALLING, SECONDHOMINGRISING, FIRSTHOMINGFALLING, MOVEPASTHOMESWITCH, MOVETOHOMESWITCH, GOTOOFFSET). Only used internally by other &#039;&#039;modules.&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|tmcinfo&lt;br /&gt;
|tmi&lt;br /&gt;
| -&lt;br /&gt;
|Request statistical information from the TMC2209 stepper motor driver&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;solenoid&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;solenoid&amp;quot;-&#039;&#039;module&#039;&#039; currently controls the &#039;&#039;hammer&#039;&#039; of the Ekdahl FAR. Due to the fact that the very same &#039;&#039;module&#039;&#039; could be used for anything that uses a striking &#039;&#039;solenoid&#039;&#039; it was named as such. It has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|engage&lt;br /&gt;
|en&lt;br /&gt;
|0-65535&lt;br /&gt;
|Engages the solenoid using the first parameter as the force&lt;br /&gt;
|-&lt;br /&gt;
|rest&lt;br /&gt;
|rs&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Forces the solenoid to its rest position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|maxforce&lt;br /&gt;
|xf&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set solenoid maximum usable force&lt;br /&gt;
|-&lt;br /&gt;
|minforce&lt;br /&gt;
|if&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set solenoid minimum usable force&lt;br /&gt;
|-&lt;br /&gt;
|forcemultiplier&lt;br /&gt;
|fm&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set solenoid force multiplier, useful for scaling of all incoming &amp;quot;engage&amp;quot;-&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|engageduration&lt;br /&gt;
|ed&lt;br /&gt;
|uS&lt;br /&gt;
|Sets the duration of the solenoid hit in uS, if a value of 0 is set the solenoid will not disengage until a rest command has been given. WARNING!! HAVING THE SOLENOID ON FOR A SPAN OF SECONDS COULD DESTROY THE CIRCUITRY!!&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;controlbox&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;controlbox&amp;quot;-&#039;&#039;module&#039;&#039; communicates with an external &#039;&#039;control box&#039;&#039; and will issue associated &#039;&#039;commands&#039;&#039; whenever new values are read on the ADC-converters. It handles averaging and does some noise-cancellation functions on the values as well. The &#039;&#039;commands&#039;&#039; are:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|harmonic&lt;br /&gt;
|har&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the harmonic knob or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|harmonicshift&lt;br /&gt;
|has&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the harmonic shift modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|finetune&lt;br /&gt;
|fin&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the fine tune knob changes&lt;br /&gt;
|-&lt;br /&gt;
|pressure&lt;br /&gt;
|pre&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the pressure knob or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|mute&lt;br /&gt;
|mut&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the mute knob or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|hammerscale&lt;br /&gt;
|hms&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the hammer scale knob changes&lt;br /&gt;
|-&lt;br /&gt;
|gate&lt;br /&gt;
|gt&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the gate switch or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|hammertrig&lt;br /&gt;
|hmt&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the hammer trigger modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|controldefaults&lt;br /&gt;
|cde&lt;br /&gt;
| -&lt;br /&gt;
|Reverts all ADC command strings to default values&lt;br /&gt;
|-&lt;br /&gt;
|datareturn&lt;br /&gt;
|dr&lt;br /&gt;
|channel:value&lt;br /&gt;
|Sent when a new value is presented on one of the ADC channels, cannot be invoked. Triggers the commands associated with the channel&lt;br /&gt;
|-&lt;br /&gt;
|adcsetting&lt;br /&gt;
|adcs&lt;br /&gt;
|channel : averages : interrupterrorthreshold : continuouserrorthreshold : continuoustimeout&lt;br /&gt;
|Sets ADC settings for a given channel. Averages are the number of samples to average, interruptthreshold is how much the value must change in order to issue a new value change event. continuousthreshold is how much the value must change when a previous change has already been recorded within the timespan of continuoustimeout&lt;br /&gt;
|-&lt;br /&gt;
|testadclatency&lt;br /&gt;
|tal&lt;br /&gt;
|0-65535&lt;br /&gt;
|Start a ADC latency test&lt;br /&gt;
|-&lt;br /&gt;
|testadclatencyreturn&lt;br /&gt;
|talr&lt;br /&gt;
| -&lt;br /&gt;
|Return from latency test&lt;br /&gt;
|-&lt;br /&gt;
|testadcminmax&lt;br /&gt;
|tix&lt;br /&gt;
|channel&lt;br /&gt;
|Test min/max value for a given channel and resets the counter&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;midiconfigurationhandler&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;midiconfigurationhandler&amp;quot;-&#039;&#039;module&#039;&#039; handles a number of &amp;quot;midiconfiguration&amp;quot;-&#039;&#039;modules&#039;&#039;. It has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|allnotesoff&lt;br /&gt;
|ano&lt;br /&gt;
| -&lt;br /&gt;
|Clears the entire buffer of MIDI notes held&lt;br /&gt;
|-&lt;br /&gt;
|add&lt;br /&gt;
|a&lt;br /&gt;
|name&lt;br /&gt;
|Adds a new MIDI configuration with the given name&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|int&lt;br /&gt;
|Remove the specified MIDI configuration&lt;br /&gt;
|-&lt;br /&gt;
|count&lt;br /&gt;
|c&lt;br /&gt;
| -&lt;br /&gt;
|Returns the number of MIDI configurations&lt;br /&gt;
|}&lt;br /&gt;
It contains one or more of the following&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|midiconfiguration&lt;br /&gt;
|mc&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;midiconfiguration&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
A &amp;quot;midiconfiguration&amp;quot;-&#039;&#039;module&#039;&#039; handles the reception of &#039;&#039;MIDI messages&#039;&#039; and will output the associated &#039;&#039;commands&#039;&#039; to the instrument internally. The commands are as follows&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|[index]&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
|Sets the currently selected MIDI configuration&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Set the name of the MIDI configuration&lt;br /&gt;
|-&lt;br /&gt;
|noteon&lt;br /&gt;
|non&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Note On event&lt;br /&gt;
|-&lt;br /&gt;
|noteoff&lt;br /&gt;
|nof&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Note Off event&lt;br /&gt;
|-&lt;br /&gt;
|polyaftertouch&lt;br /&gt;
|pat&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Polyphonic after touch event&lt;br /&gt;
|-&lt;br /&gt;
|channelaftertouch&lt;br /&gt;
|cat&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Channel after touch event&lt;br /&gt;
|-&lt;br /&gt;
|pitchbend&lt;br /&gt;
|pb&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Pitch bend event&lt;br /&gt;
|-&lt;br /&gt;
|programchange&lt;br /&gt;
|pc&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Program change event&lt;br /&gt;
|-&lt;br /&gt;
|continuouscontrollerdata&lt;br /&gt;
|ccd&lt;br /&gt;
|controllernuber:&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Continuous controller event with the given [&#039;&#039;controllernumber&#039;&#039;]&lt;br /&gt;
|-&lt;br /&gt;
|removecc&lt;br /&gt;
|rmc&lt;br /&gt;
|controllernuber&lt;br /&gt;
|Removes the entry associated with the MIDI continuous controller even &#039;&#039;controllernumber&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|defaults&lt;br /&gt;
|d&lt;br /&gt;
| -&lt;br /&gt;
|Reverts the current configuration to default &#039;&#039;commands&#039;&#039;, values and CCs&lt;br /&gt;
|-&lt;br /&gt;
|receivechannel&lt;br /&gt;
|rc&lt;br /&gt;
|channel&lt;br /&gt;
|Sets the MIDI receive channel of the current configuration. 1-16 sets specific channel, any other value for OMNI&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;pluginhandler&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;/div&gt;</summary>
		<author><name>Knaadmin</name></author>
	</entry>
	<entry>
		<id>http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_reference_V1.1&amp;diff=1680</id>
		<title>The Ekdahl FAR - Command reference V1.1</title>
		<link rel="alternate" type="text/html" href="http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_reference_V1.1&amp;diff=1680"/>
		<updated>2026-06-14T06:37:20Z</updated>

		<summary type="html">&lt;p&gt;Knaadmin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
The Ekdahl FAR V1.1 introduces the concept of &#039;&#039;modules&#039;&#039;. A &#039;&#039;module&#039;&#039; can contain any number of &#039;&#039;commands&#039;&#039; as well as other &#039;&#039;modules&#039;&#039;. Furthermore any number of &#039;&#039;modules&#039;&#039; of the same type can exist within a context, these are addressed using classic C-style array &#039;&#039;indexing&#039;&#039; with the help of brackets (&amp;quot;[ ]&amp;quot;). Extending on the classic usage, multiple &#039;&#039;indexes&#039;&#039; can be addressed simultaneously by either comma-separating the objects (&amp;quot;[0,3,4]&amp;quot;) and using &#039;&#039;ranges&#039;&#039; (&amp;quot;[3-6]&amp;quot;). &#039;&#039;Modules&#039;&#039; can be either &#039;&#039;internal&#039;&#039; or &#039;&#039;external&#039;&#039;, meaning that they may all physically exist within a single hardware object, or they can be be remote-controlled devices. From a user perspective this however makes no difference as they will appear the same.&lt;br /&gt;
&lt;br /&gt;
While all &#039;&#039;modules&#039;&#039; have their own set of &#039;&#039;commands&#039;&#039;, there are certain &#039;&#039;commands&#039;&#039; that all &#039;&#039;modules&#039;&#039; &amp;lt;u&amp;gt;must&amp;lt;/u&amp;gt; implement and can thus be accessed anywhere within the &#039;&#039;module hierarchy.&#039;&#039; There are also &#039;&#039;base commands&#039;&#039; that always exist within any given FAR ecosystem as well as product-specific &#039;&#039;base commands&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Ubiquitous commands ==&lt;br /&gt;
The &#039;&#039;module commands&#039;&#039; that are &amp;lt;u&amp;gt;required&amp;lt;/u&amp;gt; to be implemented in &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; &#039;&#039;modules&#039;&#039; and that can thus be accessed from anywhere are&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|list&lt;br /&gt;
|ls&lt;br /&gt;
|hidden/h:modules/m:commands/c:instances/i:instancecounts/ic:recursive/r&lt;br /&gt;
|Lists all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039; under the current module depending on the parameters given; &#039;hidden&#039; includes normally hidden &#039;&#039;commands&#039;&#039;, &#039;modules&#039; includes any &#039;&#039;submodules&#039;&#039;, &#039;commands&#039; shows &#039;&#039;commands&#039;&#039;, &#039;instances&#039; shows data for each individual instance of a &#039;&#039;module&#039;&#039;, &#039;instancecounts&#039; includes number of instances of each &#039;&#039;module&#039;&#039;, &#039;recursive&#039; lists all child &#039;&#039;modules&#039;&#039; / &#039;&#039;commands&#039;&#039;. No parameters defaults to showing all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039; recursively with instance counts. It doesn&#039;t show per-instance data or hidden commands.&lt;br /&gt;
|-&lt;br /&gt;
|help&lt;br /&gt;
|help&lt;br /&gt;
|recursive/r&lt;br /&gt;
|Shows a brief explanation of all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039;, shows the help for all &#039;&#039;submodules&#039;&#039; as well if &#039;recursive&#039;&lt;br /&gt;
|-&lt;br /&gt;
|dumpdata&lt;br /&gt;
|dump&lt;br /&gt;
|recursive/r&lt;br /&gt;
|Dumps all data saved for the current &#039;&#039;module&#039;&#039;, will list the data of all &#039;&#039;submodules&#039;&#039; as well if &#039;recursive&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Base commands ==&lt;br /&gt;
B&#039;&#039;ase commands&#039;&#039; are &#039;&#039;commands&#039;&#039; that always exist at the root in any implementation of the Ekdahl FAR.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|version&lt;br /&gt;
|ver&lt;br /&gt;
| -&lt;br /&gt;
|Gets the current firmware version&lt;br /&gt;
|-&lt;br /&gt;
|debugprint&lt;br /&gt;
|dp&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;command|usb|hardware|undefined|priority|error|inforequest|expressionparser|debug:1|0&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Turns on or off serial feedback for the given item&lt;br /&gt;
|-&lt;br /&gt;
|requestinfo&lt;br /&gt;
|rqi&lt;br /&gt;
|command&lt;br /&gt;
|Retrives any data saved for a &#039;&#039;command&#039;&#039;, if applicable&lt;br /&gt;
|-&lt;br /&gt;
|saveallparameters&lt;br /&gt;
|sap&lt;br /&gt;
| -&lt;br /&gt;
|Saves all avaliable parameters&lt;br /&gt;
|-&lt;br /&gt;
|loadallparameters&lt;br /&gt;
|lap&lt;br /&gt;
| -&lt;br /&gt;
|Loads all avaliable parameters&lt;br /&gt;
|-&lt;br /&gt;
|resetallparameters&lt;br /&gt;
|rap&lt;br /&gt;
| -&lt;br /&gt;
|Resets all saved parameters&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|rst&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;1|0&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Resets the Ekdahl FAR, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|nick&lt;br /&gt;
|nick&lt;br /&gt;
|name&lt;br /&gt;
|Sets the nickname of this unit&lt;br /&gt;
|-&lt;br /&gt;
|nooperation&lt;br /&gt;
|nop&lt;br /&gt;
| -&lt;br /&gt;
|Do absolutely, positively, nothing. Useful for testing and interfacing with computers, it&#039;s a good way to know that the unit is alive and responding since a &amp;quot;nop&amp;quot; is being returned as a response upon reception.&lt;br /&gt;
|-&lt;br /&gt;
|uservariable&lt;br /&gt;
|uv&lt;br /&gt;
|variable(0-9):value&lt;br /&gt;
|Set user variable 0-9 to &#039;value&#039;&lt;br /&gt;
|-&lt;br /&gt;
|expressionparserevaluate&lt;br /&gt;
|epev&lt;br /&gt;
|expression&lt;br /&gt;
|Evaluates an arithmetric expression and sends back the output, all variables and functions that can be used in any &#039;&#039;command string&#039;&#039; can also be used here. Useful for testing expressions.&lt;br /&gt;
|-&lt;br /&gt;
|ifequal&lt;br /&gt;
|ife&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] EQUALS [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring].&lt;br /&gt;
|-&lt;br /&gt;
|ifgreater&lt;br /&gt;
|ifg&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] &amp;gt; [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring]&lt;br /&gt;
|-&lt;br /&gt;
|ifless&lt;br /&gt;
|ifl&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] &amp;lt; [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring]&lt;br /&gt;
|-&lt;br /&gt;
|freeram&lt;br /&gt;
|ram&lt;br /&gt;
| -&lt;br /&gt;
|Shows free RAM memory&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The base also contains the following &#039;&#039;modules:&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|pluginhandler&lt;br /&gt;
|ph&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The Ekdahl FAR stand alone single string unit ==&lt;br /&gt;
The Ekdahl FAR stand-alone single string unit offers these &#039;&#039;commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|calibrateall&lt;br /&gt;
|ca&lt;br /&gt;
| -&lt;br /&gt;
|Performs all calibration routines on the selected bow, see below for routines performed&lt;br /&gt;
|-&lt;br /&gt;
|calibratebowspeed&lt;br /&gt;
|cbs&lt;br /&gt;
| -&lt;br /&gt;
|Finds the minimum and maximum bow speed of the selected bow&lt;br /&gt;
|-&lt;br /&gt;
|calibratebowpressure&lt;br /&gt;
|cbp&lt;br /&gt;
| -&lt;br /&gt;
|Finds the minimum and maximum bow pressure of the selected bow&lt;br /&gt;
|-&lt;br /&gt;
|calibratemute&lt;br /&gt;
|cmu&lt;br /&gt;
| -&lt;br /&gt;
|Calibrate mute settings&lt;br /&gt;
|-&lt;br /&gt;
|pickupstringfrequency&lt;br /&gt;
|psf&lt;br /&gt;
| -&lt;br /&gt;
|Returns the fundamental tone calculated from the current audio signal if apliccable&lt;br /&gt;
|-&lt;br /&gt;
|pickupaudiopeak&lt;br /&gt;
|pap&lt;br /&gt;
| -&lt;br /&gt;
|Returns the peak amplitude of the current audio signal&lt;br /&gt;
|-&lt;br /&gt;
|pickupaudiorms&lt;br /&gt;
|par&lt;br /&gt;
| -&lt;br /&gt;
|Returns the RMS amplitude of the current audio signal&lt;br /&gt;
|}&lt;br /&gt;
The Ekdahl FAR also contains the following &#039;&#039;modules&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|bowingwheel&lt;br /&gt;
|bw&lt;br /&gt;
|-&lt;br /&gt;
|mute&lt;br /&gt;
|mu&lt;br /&gt;
|-&lt;br /&gt;
|solenoid&lt;br /&gt;
|so&lt;br /&gt;
|-&lt;br /&gt;
|controlbox&lt;br /&gt;
|cb&lt;br /&gt;
|-&lt;br /&gt;
|midiconfigurationhandler&lt;br /&gt;
|mcf&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;Bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; contains everything needed to interface with a single &#039;&#039;bowing wheel&#039;&#039;. Each &#039;&#039;bowing wheel&#039;&#039; has its own harmonic series, pressure actuators and direct hardware interface. It contains the following &#039;&#039;commands&#039;&#039;.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|speedmode&lt;br /&gt;
|sm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Bow motor speed mode, 0 = Automatic and 1 = Manual. Automatic mode means that the bowing wheel will automatically turn off after the &#039;&#039;motor timeout&#039;&#039; has been reached after being put into rest mode&lt;br /&gt;
|-&lt;br /&gt;
|motortimeout&lt;br /&gt;
|mt&lt;br /&gt;
|ms&lt;br /&gt;
|Bow motor shutdown timeout after bow having been put into the rest position&lt;br /&gt;
|-&lt;br /&gt;
|pidenable&lt;br /&gt;
|pe&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets the bow PID on/off&lt;br /&gt;
|-&lt;br /&gt;
|motorfaultcommands&lt;br /&gt;
|mfc&lt;br /&gt;
|commands&lt;br /&gt;
|Commands to execute when a motor fault is tripped - !WARNING! Can ruin your instrument if changed&lt;br /&gt;
|-&lt;br /&gt;
|motoroverpowercommands&lt;br /&gt;
|moc&lt;br /&gt;
|commands&lt;br /&gt;
|Commands to execute when motor is over the power limit - !WARNING! Can ruin your instrument if changed&lt;br /&gt;
|}&lt;br /&gt;
The &#039;&#039;modules&#039;&#039; in the &amp;quot;Bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; are as follows&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|bowpressure&lt;br /&gt;
|bp&lt;br /&gt;
|-&lt;br /&gt;
|dcmotor&lt;br /&gt;
|dcm&lt;br /&gt;
|-&lt;br /&gt;
|pid&lt;br /&gt;
|pid&lt;br /&gt;
|-&lt;br /&gt;
|harmonicserieshandler&lt;br /&gt;
|hsh&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; handles the &#039;&#039;pressure&#039;&#039; of the &#039;&#039;bowing wheel&#039;&#039; against the string. The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|baseline&lt;br /&gt;
|ba&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure baseline, modulation is added to this point upward. Typically this is set with a knob on the &#039;&#039;control box&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|modifier&lt;br /&gt;
|mo&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure modulation, added to the baseline&lt;br /&gt;
|-&lt;br /&gt;
|rest&lt;br /&gt;
|rs&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the bow pressure in the &#039;&#039;rest&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|engage&lt;br /&gt;
|en&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the bow pressure in the &#039;&#039;engage&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|stallpressure&lt;br /&gt;
|sp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure stall/maximum position, this parameter is set using &#039;&#039;hardware positioning&#039;&#039; and is used as the absolute maximum for baseline and modifier combiner&lt;br /&gt;
|-&lt;br /&gt;
|engagepressure&lt;br /&gt;
|ep&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure touch/minimum position, this parameter is set using &#039;&#039;hardware position&#039;&#039; and is used as the starting point for when both the baseline and modifier is set to zero&lt;br /&gt;
|-&lt;br /&gt;
|restpressure&lt;br /&gt;
|rp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure rest position, this parameter is set using &#039;&#039;hardware positioning&#039;&#039; and is typically set to a point just below the string where it does not touch at all. The purpose of this is because while the actual hardware might be able to make the bow go even lower, that position might be far enough from the string that once &#039;&#039;engaged&#039;&#039; the bow may have so far to travel that there is perceptible &#039;&#039;latency&#039;&#039;.&lt;br /&gt;
|-&lt;br /&gt;
|engagespeed&lt;br /&gt;
|es&lt;br /&gt;
|1- ~100&lt;br /&gt;
|Bow pressure movement speed when engaging or disengaging&lt;br /&gt;
|-&lt;br /&gt;
|modulationspeed&lt;br /&gt;
|ms&lt;br /&gt;
|0.1 - 10&lt;br /&gt;
|Bow pressure movement speed while engaged&lt;br /&gt;
|-&lt;br /&gt;
|hold&lt;br /&gt;
|hd&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets bow hold (infinite sustain) on/off, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|home&lt;br /&gt;
|hm&lt;br /&gt;
| -&lt;br /&gt;
|Homing bow, used at startup and in case of the bow loosing position&lt;br /&gt;
|-&lt;br /&gt;
|tmcinfo&lt;br /&gt;
|tmi&lt;br /&gt;
| -&lt;br /&gt;
|Request statistical information from the TMC2209 stepper motor driver&lt;br /&gt;
|}&lt;br /&gt;
Note that the &amp;quot;stall&amp;quot;, &amp;quot;engage&amp;quot; and &amp;quot;rest&amp;quot;-pressure positions mention something called &#039;&#039;hardware position&#039;&#039;. This means the entire available movement of the &#039;&#039;bowing jack&#039;&#039;. Because the very bottom and top end of the movement might not be musically useful and may even harm the instrument, the &amp;quot;baseline&amp;quot; and &amp;quot;modifier&amp;quot; commands &#039;&#039;parameter&#039;&#039;s are scaled depending on these settings.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;engage&amp;quot; and &amp;quot;modulation&amp;quot;-speed settings sets how fast the stepper motor that drives the &#039;&#039;pressure&#039;&#039; moves depending on whether the &#039;&#039;bowing jack&#039;&#039; is set to &#039;&#039;engage&#039;&#039; or not. The idea here is that while wanting to be able to minimize &#039;&#039;latency&#039;&#039; by &#039;&#039;engaging&#039;&#039; and &#039;&#039;disengaging&#039;&#039; from the string as quickly as possible, dynamic changes in the &#039;&#039;pressure&#039;&#039; while playing benefits from much smoother movements as the &#039;&#039;bowing wheel&#039;&#039; takes some time to catch up to varying amounts of friction.&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;dcmotor&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;dcmotor&amp;quot;-&#039;&#039;module&#039;&#039; handles the direct &amp;lt;u&amp;gt;raw&amp;lt;/u&amp;gt; control of the &#039;&#039;bowing motor&#039;&#039; and handles the reporting back of the current speed. It has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|run&lt;br /&gt;
|ru&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Turns the motor off/on&lt;br /&gt;
|-&lt;br /&gt;
|pwm&lt;br /&gt;
|pw&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor direct power in 16-bit PWM values, requires that the &#039;&#039;PID&#039;&#039; is turned off&lt;br /&gt;
|-&lt;br /&gt;
|voltage&lt;br /&gt;
|vo&lt;br /&gt;
|~2 - 10V&lt;br /&gt;
|Sets the voltage of the regulator powering the motor. Changes here can make the motor more responsive to certain frequencies but will also affect how well the &#039;&#039;PID&#039;&#039; works. !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|current&lt;br /&gt;
|cu&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor reported current use&lt;br /&gt;
|-&lt;br /&gt;
|currentlimit&lt;br /&gt;
|cl&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor current limit (A)- !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|powerlimit&lt;br /&gt;
|pl&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor power limit (W) - !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|frequency&lt;br /&gt;
|fq&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor reported frequency&lt;br /&gt;
|-&lt;br /&gt;
|emergencystop&lt;br /&gt;
|es&lt;br /&gt;
|ms (0-65535)&lt;br /&gt;
|Immediately stops the bowing motor and doesn&#039;t allow it to start again until the cool down period given in the first argument has lapsed (milliseconds)&lt;br /&gt;
|-&lt;br /&gt;
|minpwm&lt;br /&gt;
|ip&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor minimum PWM (for calibration)&lt;br /&gt;
|-&lt;br /&gt;
|maxpwm&lt;br /&gt;
|xp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor maximum PWM (for calibration)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;pidcontroller&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;pidcontroller&amp;quot;-&#039;&#039;module&#039;&#039; is responsible for keeping the &amp;quot;dcmotor&amp;quot;-&#039;&#039;module&#039;&#039; at a certain frequency (given in Hertz). It takes the output of the motor frequency measurement and feeds it a PWM value that tries to make the speed constant regardless of the friction that the motor is enduring. To learn more about PID Controllers please see this [[wikipedia:PID_controller|wikipedia article]]. The &#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|targetfrequency&lt;br /&gt;
|tf&lt;br /&gt;
|hertz&lt;br /&gt;
|Sets the PID target frequency&lt;br /&gt;
|-&lt;br /&gt;
|ki&lt;br /&gt;
|ki&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Ki parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|kp&lt;br /&gt;
|kp&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Kp parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|kd&lt;br /&gt;
|kd&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Kd parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|integratorerror&lt;br /&gt;
|ie&lt;br /&gt;
|float&lt;br /&gt;
|Sets the lower threshold of error values for the PID integrator to ignore&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|re&lt;br /&gt;
| -&lt;br /&gt;
|Resets the PID integrator and derivative&lt;br /&gt;
|-&lt;br /&gt;
|maxerror&lt;br /&gt;
|xe&lt;br /&gt;
|float&lt;br /&gt;
|Maximum error to correct in each PID loop, essentially sets acceleration&lt;br /&gt;
|-&lt;br /&gt;
|peakerror&lt;br /&gt;
|pe&lt;br /&gt;
|float&lt;br /&gt;
|Get latest PID peak error&lt;br /&gt;
|-&lt;br /&gt;
|motorspeedmax&lt;br /&gt;
|msx&lt;br /&gt;
|Hertz&lt;br /&gt;
|Bow motor maximum speed limit&lt;br /&gt;
|-&lt;br /&gt;
|motorspeedmin&lt;br /&gt;
|msi&lt;br /&gt;
|Hertz&lt;br /&gt;
|Bow motor minimum speed limit&lt;br /&gt;
|-&lt;br /&gt;
|measuretimetotarget&lt;br /&gt;
|mtt&lt;br /&gt;
|Hertz&lt;br /&gt;
|Measure the time it takes to change from the current frequency to the target frequency, for testing purposes&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; is responsible for sending frequency data to the &amp;quot;pid&amp;quot;-&#039;&#039;module&#039;&#039;. It handles calculating the correct frequency of the &#039;&#039;bowing wheel&#039;&#039; according to the selected &#039;&#039;harmonic&#039;&#039; and &#039;&#039;harmonic shift&#039;&#039; per the currently selected &#039;&#039;harmonic series&#039;&#039;. The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|fundamental&lt;br /&gt;
|fu&lt;br /&gt;
|Hertz&lt;br /&gt;
|The fundamental frequency of the string, all harmonics are calculated from this number&lt;br /&gt;
|-&lt;br /&gt;
|harmonic&lt;br /&gt;
|h&lt;br /&gt;
|int&lt;br /&gt;
|Selects the harmonic number to set the &#039;&#039;bowing wheel&#039;&#039; to. A ratio is taken from the given &#039;&#039;harmonic&#039;&#039; in the current &#039;&#039;harmonic series&#039;&#039;, the ratio is then multiplied by the &#039;&#039;fundamental frequency&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|harmonicadd&lt;br /&gt;
|ha&lt;br /&gt;
|int&lt;br /&gt;
|This number is added to the current harmonic&lt;br /&gt;
|-&lt;br /&gt;
|harmonicbase&lt;br /&gt;
|hb&lt;br /&gt;
|int&lt;br /&gt;
|Same as harmonic but where the harmonic number is based on a MIDI note given by basenote&lt;br /&gt;
|-&lt;br /&gt;
|basenote&lt;br /&gt;
|bn&lt;br /&gt;
|0-127&lt;br /&gt;
|Sets the MIDI base note of the &#039;&#039;bowing wheel&#039;&#039;, used in conjunction with &amp;quot;harmonicbase&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|shift&lt;br /&gt;
|sh&lt;br /&gt;
| -32767 - 32767&lt;br /&gt;
|Sets shift from the currently playing harmonic where 32767 equals the entire harmonic shift range shifted up&lt;br /&gt;
|-&lt;br /&gt;
|shiftrange&lt;br /&gt;
|sr&lt;br /&gt;
|0-36&lt;br /&gt;
|Set the number of harmonic numbers that constitutes an entire harmonic shift&lt;br /&gt;
|-&lt;br /&gt;
|shift5&lt;br /&gt;
|sh5&lt;br /&gt;
| -32767 - 32767&lt;br /&gt;
|Sets the shift from the currently playing harmonic over 5 octaves where 32767 equals 5 octaves shift up from the fundamental&lt;br /&gt;
|-&lt;br /&gt;
|add&lt;br /&gt;
|a&lt;br /&gt;
|(name):(ratios)&lt;br /&gt;
|Add a new series with the given name and parameters&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|series&lt;br /&gt;
|Remove the series given and shift any series accordingly. Cannot remove all series&lt;br /&gt;
|-&lt;br /&gt;
|count&lt;br /&gt;
|c&lt;br /&gt;
| -&lt;br /&gt;
|Returns the number of harmonic series in the list and their IDs&lt;br /&gt;
|}&lt;br /&gt;
The &amp;quot;harmonicserieshandler&amp;quot;-module contains at the very least ONE harmonic series, by default it contains two: one for equal temperament and one for just intonation. The current series can be selected by simply indexing the &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; without a &#039;&#039;command&#039;&#039;, e.g. &amp;quot;harmonicserieshandler.harmonicseries[1]&amp;quot;. To be consistent, these are the &#039;&#039;modules&#039;&#039; in the &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|harmonicseries&lt;br /&gt;
|hs&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; contains any number of &#039;&#039;ratios&#039;&#039; that comprises a scale, ratios are given in a standard format where a ratio of &amp;quot;1&amp;quot; is equal to the fundamental, &amp;quot;2&amp;quot; would be one octave up etc. A standard &#039;&#039;harmonic series&#039;&#039; contains 12 ratios following a just intonation scheme. The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; will automatically adapt to the currently selected &#039;&#039;harmonic series&#039;&#039; length, whether it&#039;s a standard 12-tone scale, some kinda 3-tone scale or a full on bananas 53-tone scale. The &#039;&#039;commands&#039;&#039; of the &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; is as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|[index]&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
|Sets the currently selected &#039;&#039;harmonic Series&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Sets the name of the &#039;&#039;harmonic series&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|data&lt;br /&gt;
|da&lt;br /&gt;
|name:ratios&lt;br /&gt;
|Gets / sets all data for the &#039;&#039;harmonic series&#039;&#039; in the given slot with an arbitrary &#039;&#039;name&#039;&#039; as the first &#039;&#039;parameter&#039;&#039;. The length of the series is simply set to the amount of ratios given&lt;br /&gt;
|-&lt;br /&gt;
|ratio&lt;br /&gt;
|r&lt;br /&gt;
|harmonic:ratio&lt;br /&gt;
|Sets the ratio of the given harmonic in current &#039;&#039;harmonic series&#039;&#039;, will increase the list size if needed to address the harmonic&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|harmonic&lt;br /&gt;
|Remove the harmonic ratio given in the current series and shift any ratios accordingly. Cannot remove all ratios&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;mute&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;mute&amp;quot;-&#039;&#039;module&#039;&#039; works very similarly to the &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; in that it controls a stepper motor with some software limits in place in order to press the mute against the string. The &#039;&#039;commands&#039;&#039; are as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|setposition&lt;br /&gt;
|sp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set mute position&lt;br /&gt;
|-&lt;br /&gt;
|fullmute&lt;br /&gt;
|fm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the mute in &#039;&#039;full mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|halfmute&lt;br /&gt;
|hm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the mute in &#039;&#039;half mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|rest&lt;br /&gt;
|rs&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Put the mute in the &#039;&#039;rest&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|savefull&lt;br /&gt;
|sf&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Save the current mute position as the &#039;&#039;full mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|savehalf&lt;br /&gt;
|sh&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Save the current mute position as the &#039;&#039;half mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|saverest&lt;br /&gt;
|sr&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Save the current mute position as the &#039;&#039;rest&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|fullmuteposition&lt;br /&gt;
|fmp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;full mute&#039;&#039; position according to the &#039;&#039;hardware position&#039;&#039; given&lt;br /&gt;
|-&lt;br /&gt;
|halfmuteposition&lt;br /&gt;
|hmp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;half mute&#039;&#039; position according to the &#039;&#039;hardware position&#039;&#039; given&lt;br /&gt;
|-&lt;br /&gt;
|restposition&lt;br /&gt;
|rp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;rest&#039;&#039; position according to the &#039;&#039;hardware position&#039;&#039; given&lt;br /&gt;
|-&lt;br /&gt;
|sustain&lt;br /&gt;
|su&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets the sustain off/on, this will keep the mute in the &#039;&#039;rest&#039;&#039; position even if a &amp;quot;fullmute&amp;quot;-&#039;&#039;command&#039;&#039; is given, lasts until &amp;quot;sustain&amp;quot; is set to &amp;quot;0&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
|backoff&lt;br /&gt;
|bo&lt;br /&gt;
|0-65535&lt;br /&gt;
|Setting the time that the mute stays in the mutefullmute position before automatically going into rest, set in mS. A value of &amp;quot;0&amp;quot; disables backoff. This is used because if the mute is not backing off until something is attempted to be played, the backing-off time will either introduce &#039;&#039;latency&#039;&#039; or the string will be initially partially muted&lt;br /&gt;
|-&lt;br /&gt;
|home&lt;br /&gt;
|hm&lt;br /&gt;
| -&lt;br /&gt;
|Home mute, used during initialization and if the mute were to loose position&lt;br /&gt;
|-&lt;br /&gt;
|hardwareposition&lt;br /&gt;
|hwp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;hardware position&#039;&#039; of the mute instead of scaling it over the &#039;&#039;full mute&#039;&#039; and &#039;&#039;rest&#039;&#039; positions. Mainly used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|completetask&lt;br /&gt;
|cpt&lt;br /&gt;
| -&lt;br /&gt;
|Requests a callback when the current operation is finished. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|autocorrect&lt;br /&gt;
|ac&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Enables auto correct positioning that uses the homing sensor to correct positioning on the fly. EXPERIMENTAL&lt;br /&gt;
|-&lt;br /&gt;
|homingsensed&lt;br /&gt;
|hms&lt;br /&gt;
| -&lt;br /&gt;
|Requests whether the homing sensor is currently active or not. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|movedirection&lt;br /&gt;
|md&lt;br /&gt;
| -&lt;br /&gt;
|Requests the current direction of movement (0 Forward, 1 Reverse). Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|currentstep&lt;br /&gt;
|cs&lt;br /&gt;
| -&lt;br /&gt;
|Requests the current step. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|homingpoint&lt;br /&gt;
|hmp&lt;br /&gt;
|edgedirection&lt;br /&gt;
|Requests the given homing point. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|homingstage&lt;br /&gt;
|hms&lt;br /&gt;
| -&lt;br /&gt;
|Requests the current homing stage (UNHOMED, HOMED, FIRSTHOMINGRISING, SECONDHOMINGFALLING, SECONDHOMINGRISING, FIRSTHOMINGFALLING, MOVEPASTHOMESWITCH, MOVETOHOMESWITCH, GOTOOFFSET). Only used internally by other &#039;&#039;modules.&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|tmcinfo&lt;br /&gt;
|tmi&lt;br /&gt;
| -&lt;br /&gt;
|Request statistical information from the TMC2209 stepper motor driver&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;solenoid&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;solenoid&amp;quot;-&#039;&#039;module&#039;&#039; currently controls the &#039;&#039;hammer&#039;&#039; of the Ekdahl FAR. Due to the fact that the very same &#039;&#039;module&#039;&#039; could be used for anything that uses a striking &#039;&#039;solenoid&#039;&#039; it was named as such. It has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|engage&lt;br /&gt;
|en&lt;br /&gt;
|0-65535&lt;br /&gt;
|Engages the solenoid using the first parameter as the force&lt;br /&gt;
|-&lt;br /&gt;
|rest&lt;br /&gt;
|rs&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Forces the solenoid to its rest position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|maxforce&lt;br /&gt;
|xf&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set solenoid maximum usable force&lt;br /&gt;
|-&lt;br /&gt;
|minforce&lt;br /&gt;
|if&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set solenoid minimum usable force&lt;br /&gt;
|-&lt;br /&gt;
|forcemultiplier&lt;br /&gt;
|fm&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set solenoid force multiplier, useful for scaling of all incoming &amp;quot;engage&amp;quot;-&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|engageduration&lt;br /&gt;
|ed&lt;br /&gt;
|uS&lt;br /&gt;
|Sets the duration of the solenoid hit in uS, if a value of 0 is set the solenoid will not disengage until a rest command has been given. WARNING!! HAVING THE SOLENOID ON FOR A SPAN OF SECONDS COULD DESTROY THE CIRCUITRY!!&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;controlbox&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;controlbox&amp;quot;-&#039;&#039;module&#039;&#039; communicates with an external &#039;&#039;control box&#039;&#039; and will issue associated &#039;&#039;commands&#039;&#039; whenever new values are read on the ADC-converters. It handles averaging and does some noise-cancellation functions on the values as well. The &#039;&#039;commands&#039;&#039; are:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|harmonic&lt;br /&gt;
|har&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the harmonic knob or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|harmonicshift&lt;br /&gt;
|has&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the harmonic shift modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|finetune&lt;br /&gt;
|fin&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the fine tune knob changes&lt;br /&gt;
|-&lt;br /&gt;
|pressure&lt;br /&gt;
|pre&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the pressure knob or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|mute&lt;br /&gt;
|mut&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the mute knob or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|hammerscale&lt;br /&gt;
|hms&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the hammer scale knob changes&lt;br /&gt;
|-&lt;br /&gt;
|gate&lt;br /&gt;
|gt&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the gate switch or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|hammertrig&lt;br /&gt;
|hmt&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the hammer trigger modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|controldefaults&lt;br /&gt;
|cde&lt;br /&gt;
| -&lt;br /&gt;
|Reverts all ADC command strings to default values&lt;br /&gt;
|-&lt;br /&gt;
|datareturn&lt;br /&gt;
|dr&lt;br /&gt;
|channel:value&lt;br /&gt;
|Sent when a new value is presented on one of the ADC channels, cannot be invoked. Triggers the commands associated with the channel&lt;br /&gt;
|-&lt;br /&gt;
|adcsetting&lt;br /&gt;
|adcs&lt;br /&gt;
|channel : averages : interrupterrorthreshold : continuouserrorthreshold : continuoustimeout&lt;br /&gt;
|Sets ADC settings for a given channel. Averages are the number of samples to average, interruptthreshold is how much the value must change in order to issue a new value change event. continuousthreshold is how much the value must change when a previous change has already been recorded within the timespan of continuoustimeout&lt;br /&gt;
|-&lt;br /&gt;
|testadclatency&lt;br /&gt;
|tal&lt;br /&gt;
|0-65535&lt;br /&gt;
|Start a ADC latency test&lt;br /&gt;
|-&lt;br /&gt;
|testadclatencyreturn&lt;br /&gt;
|talr&lt;br /&gt;
| -&lt;br /&gt;
|Return from latency test&lt;br /&gt;
|-&lt;br /&gt;
|testadcminmax&lt;br /&gt;
|tix&lt;br /&gt;
|channel&lt;br /&gt;
|Test min/max value for a given channel and resets the counter&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;midiconfigurationhandler&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;midiconfigurationhandler&amp;quot;-&#039;&#039;module&#039;&#039; handles a number of &amp;quot;midiconfiguration&amp;quot;-&#039;&#039;modules&#039;&#039;. It has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|allnotesoff&lt;br /&gt;
|ano&lt;br /&gt;
| -&lt;br /&gt;
|Clears the entire buffer of MIDI notes held&lt;br /&gt;
|-&lt;br /&gt;
|add&lt;br /&gt;
|a&lt;br /&gt;
|name&lt;br /&gt;
|Adds a new MIDI configuration with the given name&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|int&lt;br /&gt;
|Remove the specified MIDI configuration&lt;br /&gt;
|-&lt;br /&gt;
|count&lt;br /&gt;
|c&lt;br /&gt;
| -&lt;br /&gt;
|Returns the number of MIDI configurations&lt;br /&gt;
|}&lt;br /&gt;
It contains one or more of the following&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|midiconfiguration&lt;br /&gt;
|mc&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;midiconfiguration&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
A &amp;quot;midiconfiguration&amp;quot;-&#039;&#039;module&#039;&#039; handles the reception of &#039;&#039;MIDI messages&#039;&#039; and will output the associated &#039;&#039;commands&#039;&#039; to the instrument internally. The commands are as follows&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|[index]&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
|Sets the currently selected MIDI configuration&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Set the name of the MIDI configuration&lt;br /&gt;
|-&lt;br /&gt;
|noteon&lt;br /&gt;
|non&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Note On event&lt;br /&gt;
|-&lt;br /&gt;
|noteoff&lt;br /&gt;
|nof&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Note Off event&lt;br /&gt;
|-&lt;br /&gt;
|polyaftertouch&lt;br /&gt;
|pat&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Polyphonic after touch event&lt;br /&gt;
|-&lt;br /&gt;
|channelaftertouch&lt;br /&gt;
|cat&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Channel after touch event&lt;br /&gt;
|-&lt;br /&gt;
|pitchbend&lt;br /&gt;
|pb&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Pitch bend event&lt;br /&gt;
|-&lt;br /&gt;
|programchange&lt;br /&gt;
|pc&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Program change event&lt;br /&gt;
|-&lt;br /&gt;
|continuouscontrollerdata&lt;br /&gt;
|ccd&lt;br /&gt;
|controllernuber:&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Continuous controller event with the given [&#039;&#039;controllernumber&#039;&#039;]&lt;br /&gt;
|-&lt;br /&gt;
|removecc&lt;br /&gt;
|rmc&lt;br /&gt;
|controllernuber&lt;br /&gt;
|Removes the entry associated with the MIDI continuous controller even &#039;&#039;controllernumber&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|defaults&lt;br /&gt;
|d&lt;br /&gt;
| -&lt;br /&gt;
|Reverts the current configuration to default &#039;&#039;commands&#039;&#039;, values and CCs&lt;br /&gt;
|-&lt;br /&gt;
|receivechannel&lt;br /&gt;
|rc&lt;br /&gt;
|channel&lt;br /&gt;
|Sets the MIDI receive channel of the current configuration. 1-16 sets specific channel, any other value for OMNI&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;pluginhandler&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;/div&gt;</summary>
		<author><name>Knaadmin</name></author>
	</entry>
	<entry>
		<id>http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_reference_V1.1&amp;diff=1679</id>
		<title>The Ekdahl FAR - Command reference V1.1</title>
		<link rel="alternate" type="text/html" href="http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_reference_V1.1&amp;diff=1679"/>
		<updated>2026-06-12T16:23:11Z</updated>

		<summary type="html">&lt;p&gt;Knaadmin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
The Ekdahl FAR V1.1 introduces the concept of &#039;&#039;modules&#039;&#039;. A &#039;&#039;module&#039;&#039; can contain any number of &#039;&#039;commands&#039;&#039; as well as other &#039;&#039;modules&#039;&#039;. Furthermore any number of &#039;&#039;modules&#039;&#039; of the same type can exist within a context, these are addressed using classic C-style array &#039;&#039;indexing&#039;&#039; with the help of brackets (&amp;quot;[ ]&amp;quot;). Extending on the classic usage, multiple &#039;&#039;indexes&#039;&#039; can be addressed simultaneously by either comma-separating the objects (&amp;quot;[0,3,4]&amp;quot;) and using &#039;&#039;ranges&#039;&#039; (&amp;quot;[3-6]&amp;quot;). &#039;&#039;Modules&#039;&#039; can be either &#039;&#039;internal&#039;&#039; or &#039;&#039;external&#039;&#039;, meaning that they may all physically exist within a single hardware object, or they can be be remote-controlled devices. From a user perspective this however makes no difference as they will appear the same.&lt;br /&gt;
&lt;br /&gt;
While all &#039;&#039;modules&#039;&#039; have their own set of &#039;&#039;commands&#039;&#039;, there are certain &#039;&#039;commands&#039;&#039; that all &#039;&#039;modules&#039;&#039; &amp;lt;u&amp;gt;must&amp;lt;/u&amp;gt; implement and can thus be accessed anywhere within the &#039;&#039;module hierarchy.&#039;&#039; There are also &#039;&#039;base commands&#039;&#039; that always exist within any given FAR ecosystem as well as product-specific &#039;&#039;base commands&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Basic commands ==&lt;br /&gt;
The &#039;&#039;module commands&#039;&#039; that are &amp;lt;u&amp;gt;required&amp;lt;/u&amp;gt; to be implemented in &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; &#039;&#039;modules&#039;&#039; and that can thus be accessed from anywhere are&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|list&lt;br /&gt;
|ls&lt;br /&gt;
|hidden/h:modules/m:commands/c:instances/i:instancecounts/ic:recursive/r&lt;br /&gt;
|Lists all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039; under the current module depending on the parameters given; &#039;hidden&#039; includes normally hidden &#039;&#039;commands&#039;&#039;, &#039;modules&#039; includes any &#039;&#039;submodules&#039;&#039;, &#039;commands&#039; shows &#039;&#039;commands&#039;&#039;, &#039;instances&#039; shows data for each individual instance of a &#039;&#039;module&#039;&#039;, &#039;instancecounts&#039; includes number of instances of each &#039;&#039;module&#039;&#039;, &#039;recursive&#039; lists all child &#039;&#039;modules&#039;&#039; / &#039;&#039;commands&#039;&#039;. No parameters defaults to showing all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039; recursively with instance counts. It doesn&#039;t show per-instance data or hidden commands.&lt;br /&gt;
|-&lt;br /&gt;
|help&lt;br /&gt;
|help&lt;br /&gt;
|recursive/r&lt;br /&gt;
|Shows a brief explanation of all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039;, shows the help for all &#039;&#039;submodules&#039;&#039; as well if &#039;recursive&#039;&lt;br /&gt;
|-&lt;br /&gt;
|dumpdata&lt;br /&gt;
|dump&lt;br /&gt;
|recursive/r&lt;br /&gt;
|Dumps all data saved for the current &#039;&#039;module&#039;&#039;, will list the data of all &#039;&#039;submodules&#039;&#039; as well if &#039;recursive&#039;&lt;br /&gt;
|}&lt;br /&gt;
The &#039;&#039;base commands&#039;&#039; are as follows&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|version&lt;br /&gt;
|ver&lt;br /&gt;
| -&lt;br /&gt;
|Gets the current firmware version&lt;br /&gt;
|-&lt;br /&gt;
|debugprint&lt;br /&gt;
|dp&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;command|usb|hardware|undefined|priority|error|inforequest|expressionparser|debug:1|0&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Turns on or off serial feedback for the given item&lt;br /&gt;
|-&lt;br /&gt;
|requestinfo&lt;br /&gt;
|rqi&lt;br /&gt;
|command&lt;br /&gt;
|Retrives any data saved for a &#039;&#039;command&#039;&#039;, if applicable&lt;br /&gt;
|-&lt;br /&gt;
|saveallparameters&lt;br /&gt;
|sap&lt;br /&gt;
| -&lt;br /&gt;
|Saves all avaliable parameters&lt;br /&gt;
|-&lt;br /&gt;
|loadallparameters&lt;br /&gt;
|lap&lt;br /&gt;
| -&lt;br /&gt;
|Loads all avaliable parameters&lt;br /&gt;
|-&lt;br /&gt;
|resetallparameters&lt;br /&gt;
|rap&lt;br /&gt;
| -&lt;br /&gt;
|Resets all saved parameters&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|rst&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;1|0&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Resets the Ekdahl FAR, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|nick&lt;br /&gt;
|nick&lt;br /&gt;
|name&lt;br /&gt;
|Sets the nickname of this unit&lt;br /&gt;
|-&lt;br /&gt;
|nooperation&lt;br /&gt;
|nop&lt;br /&gt;
| -&lt;br /&gt;
|Do absolutely, positively, nothing. Useful for testing and interfacing with computers, it&#039;s a good way to know that the unit is alive and responding since a &amp;quot;nop&amp;quot; is being returned as a response upon reception.&lt;br /&gt;
|-&lt;br /&gt;
|uservariable&lt;br /&gt;
|uv&lt;br /&gt;
|variable(0-9):value&lt;br /&gt;
|Set user variable 0-9 to &#039;value&#039;&lt;br /&gt;
|-&lt;br /&gt;
|expressionparserevaluate&lt;br /&gt;
|epev&lt;br /&gt;
|expression&lt;br /&gt;
|Evaluates an arithmetric expression and sends back the output, all variables and functions that can be used in any &#039;&#039;command string&#039;&#039; can also be used here. Useful for testing expressions.&lt;br /&gt;
|-&lt;br /&gt;
|ifequal&lt;br /&gt;
|ife&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] EQUALS [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring].&lt;br /&gt;
|-&lt;br /&gt;
|ifgreater&lt;br /&gt;
|ifg&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] &amp;gt; [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring]&lt;br /&gt;
|-&lt;br /&gt;
|ifless&lt;br /&gt;
|ifl&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] &amp;lt; [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring]&lt;br /&gt;
|-&lt;br /&gt;
|freeram&lt;br /&gt;
|ram&lt;br /&gt;
| -&lt;br /&gt;
|Shows free RAM memory&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The base also contains the following &#039;&#039;modules:&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|pluginhandler&lt;br /&gt;
|ph&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The Ekdahl FAR stand alone single string unit ==&lt;br /&gt;
The Ekdahl FAR stand-alone single string unit offers these &#039;&#039;commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|calibrateall&lt;br /&gt;
|ca&lt;br /&gt;
| -&lt;br /&gt;
|Performs all calibration routines on the selected bow, see below for routines performed&lt;br /&gt;
|-&lt;br /&gt;
|calibratebowspeed&lt;br /&gt;
|cbs&lt;br /&gt;
| -&lt;br /&gt;
|Finds the minimum and maximum bow speed of the selected bow&lt;br /&gt;
|-&lt;br /&gt;
|calibratebowpressure&lt;br /&gt;
|cbp&lt;br /&gt;
| -&lt;br /&gt;
|Finds the minimum and maximum bow pressure of the selected bow&lt;br /&gt;
|-&lt;br /&gt;
|calibratemute&lt;br /&gt;
|cmu&lt;br /&gt;
| -&lt;br /&gt;
|Calibrate mute settings&lt;br /&gt;
|-&lt;br /&gt;
|pickupstringfrequency&lt;br /&gt;
|psf&lt;br /&gt;
| -&lt;br /&gt;
|Returns the fundamental tone calculated from the current audio signal if apliccable&lt;br /&gt;
|-&lt;br /&gt;
|pickupaudiopeak&lt;br /&gt;
|pap&lt;br /&gt;
| -&lt;br /&gt;
|Returns the peak amplitude of the current audio signal&lt;br /&gt;
|-&lt;br /&gt;
|pickupaudiorms&lt;br /&gt;
|par&lt;br /&gt;
| -&lt;br /&gt;
|Returns the RMS amplitude of the current audio signal&lt;br /&gt;
|}&lt;br /&gt;
The Ekdahl FAR also contains the following &#039;&#039;modules&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|bowingwheel&lt;br /&gt;
|bw&lt;br /&gt;
|-&lt;br /&gt;
|mute&lt;br /&gt;
|mu&lt;br /&gt;
|-&lt;br /&gt;
|solenoid&lt;br /&gt;
|so&lt;br /&gt;
|-&lt;br /&gt;
|controlbox&lt;br /&gt;
|cb&lt;br /&gt;
|-&lt;br /&gt;
|midiconfigurationhandler&lt;br /&gt;
|mcf&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;Bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; contains everything needed to interface with a single &#039;&#039;bowing wheel&#039;&#039;. Each &#039;&#039;bowing wheel&#039;&#039; has its own harmonic series, pressure actuators and direct hardware interface. It contains the following &#039;&#039;commands&#039;&#039;.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|speedmode&lt;br /&gt;
|sm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Bow motor speed mode, 0 = Automatic and 1 = Manual. Automatic mode means that the bowing wheel will automatically turn off after the &#039;&#039;motor timeout&#039;&#039; has been reached after being put into rest mode&lt;br /&gt;
|-&lt;br /&gt;
|motortimeout&lt;br /&gt;
|mt&lt;br /&gt;
|ms&lt;br /&gt;
|Bow motor shutdown timeout after bow having been put into the rest position&lt;br /&gt;
|-&lt;br /&gt;
|pidenable&lt;br /&gt;
|pe&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets the bow PID on/off&lt;br /&gt;
|-&lt;br /&gt;
|motorfaultcommands&lt;br /&gt;
|mfc&lt;br /&gt;
|commands&lt;br /&gt;
|Commands to execute when a motor fault is tripped - !WARNING! Can ruin your instrument if changed&lt;br /&gt;
|-&lt;br /&gt;
|motoroverpowercommands&lt;br /&gt;
|moc&lt;br /&gt;
|commands&lt;br /&gt;
|Commands to execute when motor is over the power limit - !WARNING! Can ruin your instrument if changed&lt;br /&gt;
|}&lt;br /&gt;
The &#039;&#039;modules&#039;&#039; in the &amp;quot;Bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; are as follows&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|bowpressure&lt;br /&gt;
|bp&lt;br /&gt;
|-&lt;br /&gt;
|dcmotor&lt;br /&gt;
|dcm&lt;br /&gt;
|-&lt;br /&gt;
|pid&lt;br /&gt;
|pid&lt;br /&gt;
|-&lt;br /&gt;
|harmonicserieshandler&lt;br /&gt;
|hsh&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; handles the &#039;&#039;pressure&#039;&#039; of the &#039;&#039;bowing wheel&#039;&#039; against the string. The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|baseline&lt;br /&gt;
|ba&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure baseline, modulation is added to this point upward. Typically this is set with a knob on the &#039;&#039;control box&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|modifier&lt;br /&gt;
|mo&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure modulation, added to the baseline&lt;br /&gt;
|-&lt;br /&gt;
|rest&lt;br /&gt;
|rs&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the bow pressure in the &#039;&#039;rest&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|engage&lt;br /&gt;
|en&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the bow pressure in the &#039;&#039;engage&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|stallpressure&lt;br /&gt;
|sp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure stall/maximum position, this parameter is set using &#039;&#039;hardware positioning&#039;&#039; and is used as the absolute maximum for baseline and modifier combiner&lt;br /&gt;
|-&lt;br /&gt;
|engagepressure&lt;br /&gt;
|ep&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure touch/minimum position, this parameter is set using &#039;&#039;hardware position&#039;&#039; and is used as the starting point for when both the baseline and modifier is set to zero&lt;br /&gt;
|-&lt;br /&gt;
|restpressure&lt;br /&gt;
|rp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure rest position, this parameter is set using &#039;&#039;hardware positioning&#039;&#039; and is typically set to a point just below the string where it does not touch at all. The purpose of this is because while the actual hardware might be able to make the bow go even lower, that position might be far enough from the string that once &#039;&#039;engaged&#039;&#039; the bow may have so far to travel that there is perceptible &#039;&#039;latency&#039;&#039;.&lt;br /&gt;
|-&lt;br /&gt;
|engagespeed&lt;br /&gt;
|es&lt;br /&gt;
|1- ~100&lt;br /&gt;
|Bow pressure movement speed when engaging or disengaging&lt;br /&gt;
|-&lt;br /&gt;
|modulationspeed&lt;br /&gt;
|ms&lt;br /&gt;
|0.1 - 10&lt;br /&gt;
|Bow pressure movement speed while engaged&lt;br /&gt;
|-&lt;br /&gt;
|hold&lt;br /&gt;
|hd&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets bow hold (infinite sustain) on/off, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|home&lt;br /&gt;
|hm&lt;br /&gt;
| -&lt;br /&gt;
|Homing bow, used at startup and in case of the bow loosing position&lt;br /&gt;
|-&lt;br /&gt;
|tmcinfo&lt;br /&gt;
|tmi&lt;br /&gt;
| -&lt;br /&gt;
|Request statistical information from the TMC2209 stepper motor driver&lt;br /&gt;
|}&lt;br /&gt;
Note that the &amp;quot;stall&amp;quot;, &amp;quot;engage&amp;quot; and &amp;quot;rest&amp;quot;-pressure positions mention something called &#039;&#039;hardware position&#039;&#039;. This means the entire available movement of the &#039;&#039;bowing jack&#039;&#039;. Because the very bottom and top end of the movement might not be musically useful and may even harm the instrument, the &amp;quot;baseline&amp;quot; and &amp;quot;modifier&amp;quot; commands &#039;&#039;parameter&#039;&#039;s are scaled depending on these settings.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;engage&amp;quot; and &amp;quot;modulation&amp;quot;-speed settings sets how fast the stepper motor that drives the &#039;&#039;pressure&#039;&#039; moves depending on whether the &#039;&#039;bowing jack&#039;&#039; is set to &#039;&#039;engage&#039;&#039; or not. The idea here is that while wanting to be able to minimize &#039;&#039;latency&#039;&#039; by &#039;&#039;engaging&#039;&#039; and &#039;&#039;disengaging&#039;&#039; from the string as quickly as possible, dynamic changes in the &#039;&#039;pressure&#039;&#039; while playing benefits from much smoother movements as the &#039;&#039;bowing wheel&#039;&#039; takes some time to catch up to varying amounts of friction.&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;dcmotor&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;dcmotor&amp;quot;-&#039;&#039;module&#039;&#039; handles the direct &amp;lt;u&amp;gt;raw&amp;lt;/u&amp;gt; control of the &#039;&#039;bowing motor&#039;&#039; and handles the reporting back of the current speed. It has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|run&lt;br /&gt;
|ru&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Turns the motor off/on&lt;br /&gt;
|-&lt;br /&gt;
|pwm&lt;br /&gt;
|pw&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor direct power in 16-bit PWM values, requires that the &#039;&#039;PID&#039;&#039; is turned off&lt;br /&gt;
|-&lt;br /&gt;
|voltage&lt;br /&gt;
|vo&lt;br /&gt;
|~2 - 10V&lt;br /&gt;
|Sets the voltage of the regulator powering the motor. Changes here can make the motor more responsive to certain frequencies but will also affect how well the &#039;&#039;PID&#039;&#039; works. !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|current&lt;br /&gt;
|cu&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor reported current use&lt;br /&gt;
|-&lt;br /&gt;
|currentlimit&lt;br /&gt;
|cl&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor current limit (A)- !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|powerlimit&lt;br /&gt;
|pl&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor power limit (W) - !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|frequency&lt;br /&gt;
|fq&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor reported frequency&lt;br /&gt;
|-&lt;br /&gt;
|emergencystop&lt;br /&gt;
|es&lt;br /&gt;
|ms (0-65535)&lt;br /&gt;
|Immediately stops the bowing motor and doesn&#039;t allow it to start again until the cool down period given in the first argument has lapsed (milliseconds)&lt;br /&gt;
|-&lt;br /&gt;
|minpwm&lt;br /&gt;
|ip&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor minimum PWM (for calibration)&lt;br /&gt;
|-&lt;br /&gt;
|maxpwm&lt;br /&gt;
|xp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor maximum PWM (for calibration)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;pidcontroller&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;pidcontroller&amp;quot;-&#039;&#039;module&#039;&#039; is responsible for keeping the &amp;quot;dcmotor&amp;quot;-&#039;&#039;module&#039;&#039; at a certain frequency (given in Hertz). It takes the output of the motor frequency measurement and feeds it a PWM value that tries to make the speed constant regardless of the friction that the motor is enduring. To learn more about PID Controllers please see this [[wikipedia:PID_controller|wikipedia article]]. The &#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|targetfrequency&lt;br /&gt;
|tf&lt;br /&gt;
|hertz&lt;br /&gt;
|Sets the PID target frequency&lt;br /&gt;
|-&lt;br /&gt;
|ki&lt;br /&gt;
|ki&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Ki parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|kp&lt;br /&gt;
|kp&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Kp parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|kd&lt;br /&gt;
|kd&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Kd parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|integratorerror&lt;br /&gt;
|ie&lt;br /&gt;
|float&lt;br /&gt;
|Sets the lower threshold of error values for the PID integrator to ignore&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|re&lt;br /&gt;
| -&lt;br /&gt;
|Resets the PID integrator and derivative&lt;br /&gt;
|-&lt;br /&gt;
|maxerror&lt;br /&gt;
|xe&lt;br /&gt;
|float&lt;br /&gt;
|Maximum error to correct in each PID loop, essentially sets acceleration&lt;br /&gt;
|-&lt;br /&gt;
|peakerror&lt;br /&gt;
|pe&lt;br /&gt;
|float&lt;br /&gt;
|Get latest PID peak error&lt;br /&gt;
|-&lt;br /&gt;
|motorspeedmax&lt;br /&gt;
|msx&lt;br /&gt;
|Hertz&lt;br /&gt;
|Bow motor maximum speed limit&lt;br /&gt;
|-&lt;br /&gt;
|motorspeedmin&lt;br /&gt;
|msi&lt;br /&gt;
|Hertz&lt;br /&gt;
|Bow motor minimum speed limit&lt;br /&gt;
|-&lt;br /&gt;
|measuretimetotarget&lt;br /&gt;
|mtt&lt;br /&gt;
|Hertz&lt;br /&gt;
|Measure the time it takes to change from the current frequency to the target frequency, for testing purposes&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; is responsible for sending frequency data to the &amp;quot;pid&amp;quot;-&#039;&#039;module&#039;&#039;. It handles calculating the correct frequency of the &#039;&#039;bowing wheel&#039;&#039; according to the selected &#039;&#039;harmonic&#039;&#039; and &#039;&#039;harmonic shift&#039;&#039; per the currently selected &#039;&#039;harmonic series&#039;&#039;. The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|fundamental&lt;br /&gt;
|fu&lt;br /&gt;
|Hertz&lt;br /&gt;
|The fundamental frequency of the string, all harmonics are calculated from this number&lt;br /&gt;
|-&lt;br /&gt;
|harmonic&lt;br /&gt;
|h&lt;br /&gt;
|int&lt;br /&gt;
|Selects the harmonic number to set the &#039;&#039;bowing wheel&#039;&#039; to. A ratio is taken from the given &#039;&#039;harmonic&#039;&#039; in the current &#039;&#039;harmonic series&#039;&#039;, the ratio is then multiplied by the &#039;&#039;fundamental frequency&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|harmonicadd&lt;br /&gt;
|ha&lt;br /&gt;
|int&lt;br /&gt;
|This number is added to the current harmonic&lt;br /&gt;
|-&lt;br /&gt;
|harmonicbase&lt;br /&gt;
|hb&lt;br /&gt;
|int&lt;br /&gt;
|Same as harmonic but where the harmonic number is based on a MIDI note given by basenote&lt;br /&gt;
|-&lt;br /&gt;
|basenote&lt;br /&gt;
|bn&lt;br /&gt;
|0-127&lt;br /&gt;
|Sets the MIDI base note of the &#039;&#039;bowing wheel&#039;&#039;, used in conjunction with &amp;quot;harmonicbase&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|shift&lt;br /&gt;
|sh&lt;br /&gt;
| -32767 - 32767&lt;br /&gt;
|Sets shift from the currently playing harmonic where 32767 equals the entire harmonic shift range shifted up&lt;br /&gt;
|-&lt;br /&gt;
|shiftrange&lt;br /&gt;
|sr&lt;br /&gt;
|0-36&lt;br /&gt;
|Set the number of harmonic numbers that constitutes an entire harmonic shift&lt;br /&gt;
|-&lt;br /&gt;
|shift5&lt;br /&gt;
|sh5&lt;br /&gt;
| -32767 - 32767&lt;br /&gt;
|Sets the shift from the currently playing harmonic over 5 octaves where 32767 equals 5 octaves shift up from the fundamental&lt;br /&gt;
|-&lt;br /&gt;
|add&lt;br /&gt;
|a&lt;br /&gt;
|(name):(ratios)&lt;br /&gt;
|Add a new series with the given name and parameters&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|series&lt;br /&gt;
|Remove the series given and shift any series accordingly. Cannot remove all series&lt;br /&gt;
|-&lt;br /&gt;
|count&lt;br /&gt;
|c&lt;br /&gt;
| -&lt;br /&gt;
|Returns the number of harmonic series in the list and their IDs&lt;br /&gt;
|}&lt;br /&gt;
The &amp;quot;harmonicserieshandler&amp;quot;-module contains at the very least ONE harmonic series, by default it contains two: one for equal temperament and one for just intonation. The current series can be selected by simply indexing the &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; without a &#039;&#039;command&#039;&#039;, e.g. &amp;quot;harmonicserieshandler.harmonicseries[1]&amp;quot;. To be consistent, these are the &#039;&#039;modules&#039;&#039; in the &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|harmonicseries&lt;br /&gt;
|hs&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; contains any number of &#039;&#039;ratios&#039;&#039; that comprises a scale, ratios are given in a standard format where a ratio of &amp;quot;1&amp;quot; is equal to the fundamental, &amp;quot;2&amp;quot; would be one octave up etc. A standard &#039;&#039;harmonic series&#039;&#039; contains 12 ratios following a just intonation scheme. The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; will automatically adapt to the currently selected &#039;&#039;harmonic series&#039;&#039; length, whether it&#039;s a standard 12-tone scale, some kinda 3-tone scale or a full on bananas 53-tone scale. The &#039;&#039;commands&#039;&#039; of the &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; is as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|[index]&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
|Sets the currently selected &#039;&#039;harmonic Series&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Sets the name of the &#039;&#039;harmonic series&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|data&lt;br /&gt;
|da&lt;br /&gt;
|name:ratios&lt;br /&gt;
|Gets / sets all data for the &#039;&#039;harmonic series&#039;&#039; in the given slot with an arbitrary &#039;&#039;name&#039;&#039; as the first &#039;&#039;parameter&#039;&#039;. The length of the series is simply set to the amount of ratios given&lt;br /&gt;
|-&lt;br /&gt;
|ratio&lt;br /&gt;
|r&lt;br /&gt;
|harmonic:ratio&lt;br /&gt;
|Sets the ratio of the given harmonic in current &#039;&#039;harmonic series&#039;&#039;, will increase the list size if needed to address the harmonic&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|harmonic&lt;br /&gt;
|Remove the harmonic ratio given in the current series and shift any ratios accordingly. Cannot remove all ratios&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;mute&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;mute&amp;quot;-&#039;&#039;module&#039;&#039; works very similarly to the &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; in that it controls a stepper motor with some software limits in place in order to press the mute against the string. The &#039;&#039;commands&#039;&#039; are as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|setposition&lt;br /&gt;
|sp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set mute position&lt;br /&gt;
|-&lt;br /&gt;
|fullmute&lt;br /&gt;
|fm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the mute in &#039;&#039;full mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|halfmute&lt;br /&gt;
|hm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the mute in &#039;&#039;half mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|rest&lt;br /&gt;
|rs&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Put the mute in the &#039;&#039;rest&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|savefull&lt;br /&gt;
|sf&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Save the current mute position as the &#039;&#039;full mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|savehalf&lt;br /&gt;
|sh&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Save the current mute position as the &#039;&#039;half mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|saverest&lt;br /&gt;
|sr&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Save the current mute position as the &#039;&#039;rest&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|fullmuteposition&lt;br /&gt;
|fmp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;full mute&#039;&#039; position according to the &#039;&#039;hardware position&#039;&#039; given&lt;br /&gt;
|-&lt;br /&gt;
|halfmuteposition&lt;br /&gt;
|hmp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;half mute&#039;&#039; position according to the &#039;&#039;hardware position&#039;&#039; given&lt;br /&gt;
|-&lt;br /&gt;
|restposition&lt;br /&gt;
|rp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;rest&#039;&#039; position according to the &#039;&#039;hardware position&#039;&#039; given&lt;br /&gt;
|-&lt;br /&gt;
|sustain&lt;br /&gt;
|su&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets the sustain off/on, this will keep the mute in the &#039;&#039;rest&#039;&#039; position even if a &amp;quot;fullmute&amp;quot;-&#039;&#039;command&#039;&#039; is given, lasts until &amp;quot;sustain&amp;quot; is set to &amp;quot;0&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
|backoff&lt;br /&gt;
|bo&lt;br /&gt;
|0-65535&lt;br /&gt;
|Setting the time that the mute stays in the mutefullmute position before automatically going into rest, set in mS. A value of &amp;quot;0&amp;quot; disables backoff. This is used because if the mute is not backing off until something is attempted to be played, the backing-off time will either introduce &#039;&#039;latency&#039;&#039; or the string will be initially partially muted&lt;br /&gt;
|-&lt;br /&gt;
|home&lt;br /&gt;
|hm&lt;br /&gt;
| -&lt;br /&gt;
|Home mute, used during initialization and if the mute were to loose position&lt;br /&gt;
|-&lt;br /&gt;
|hardwareposition&lt;br /&gt;
|hwp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;hardware position&#039;&#039; of the mute instead of scaling it over the &#039;&#039;full mute&#039;&#039; and &#039;&#039;rest&#039;&#039; positions. Mainly used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|completetask&lt;br /&gt;
|cpt&lt;br /&gt;
| -&lt;br /&gt;
|Requests a callback when the current operation is finished. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|autocorrect&lt;br /&gt;
|ac&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Enables auto correct positioning that uses the homing sensor to correct positioning on the fly. EXPERIMENTAL&lt;br /&gt;
|-&lt;br /&gt;
|homingsensed&lt;br /&gt;
|hms&lt;br /&gt;
| -&lt;br /&gt;
|Requests whether the homing sensor is currently active or not. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|movedirection&lt;br /&gt;
|md&lt;br /&gt;
| -&lt;br /&gt;
|Requests the current direction of movement (0 Forward, 1 Reverse). Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|currentstep&lt;br /&gt;
|cs&lt;br /&gt;
| -&lt;br /&gt;
|Requests the current step. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|homingpoint&lt;br /&gt;
|hmp&lt;br /&gt;
|edgedirection&lt;br /&gt;
|Requests the given homing point. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|homingstage&lt;br /&gt;
|hms&lt;br /&gt;
| -&lt;br /&gt;
|Requests the current homing stage (UNHOMED, HOMED, FIRSTHOMINGRISING, SECONDHOMINGFALLING, SECONDHOMINGRISING, FIRSTHOMINGFALLING, MOVEPASTHOMESWITCH, MOVETOHOMESWITCH, GOTOOFFSET). Only used internally by other &#039;&#039;modules.&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|tmcinfo&lt;br /&gt;
|tmi&lt;br /&gt;
| -&lt;br /&gt;
|Request statistical information from the TMC2209 stepper motor driver&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;solenoid&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;solenoid&amp;quot;-&#039;&#039;module&#039;&#039; currently controls the &#039;&#039;hammer&#039;&#039; of the Ekdahl FAR. Due to the fact that the very same &#039;&#039;module&#039;&#039; could be used for anything that uses a striking &#039;&#039;solenoid&#039;&#039; it was named as such. It has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|engage&lt;br /&gt;
|en&lt;br /&gt;
|0-65535&lt;br /&gt;
|Engages the solenoid using the first parameter as the force&lt;br /&gt;
|-&lt;br /&gt;
|rest&lt;br /&gt;
|rs&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Forces the solenoid to its rest position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|maxforce&lt;br /&gt;
|xf&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set solenoid maximum usable force&lt;br /&gt;
|-&lt;br /&gt;
|minforce&lt;br /&gt;
|if&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set solenoid minimum usable force&lt;br /&gt;
|-&lt;br /&gt;
|forcemultiplier&lt;br /&gt;
|fm&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set solenoid force multiplier, useful for scaling of all incoming &amp;quot;engage&amp;quot;-&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|engageduration&lt;br /&gt;
|ed&lt;br /&gt;
|uS&lt;br /&gt;
|Sets the duration of the solenoid hit in uS, if a value of 0 is set the solenoid will not disengage until a rest command has been given. WARNING!! HAVING THE SOLENOID ON FOR A SPAN OF SECONDS COULD DESTROY THE CIRCUITRY!!&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;controlbox&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;controlbox&amp;quot;-&#039;&#039;module&#039;&#039; communicates with an external &#039;&#039;control box&#039;&#039; and will issue associated &#039;&#039;commands&#039;&#039; whenever new values are read on the ADC-converters. It handles averaging and does some noise-cancellation functions on the values as well. The &#039;&#039;commands&#039;&#039; are:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|harmonic&lt;br /&gt;
|har&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the harmonic knob or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|harmonicshift&lt;br /&gt;
|has&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the harmonic shift modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|finetune&lt;br /&gt;
|fin&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the fine tune knob changes&lt;br /&gt;
|-&lt;br /&gt;
|pressure&lt;br /&gt;
|pre&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the pressure knob or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|mute&lt;br /&gt;
|mut&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the mute knob or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|hammerscale&lt;br /&gt;
|hms&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the hammer scale knob changes&lt;br /&gt;
|-&lt;br /&gt;
|gate&lt;br /&gt;
|gt&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the gate switch or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|hammertrig&lt;br /&gt;
|hmt&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the hammer trigger modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|controldefaults&lt;br /&gt;
|cde&lt;br /&gt;
| -&lt;br /&gt;
|Reverts all ADC command strings to default values&lt;br /&gt;
|-&lt;br /&gt;
|datareturn&lt;br /&gt;
|dr&lt;br /&gt;
|channel:value&lt;br /&gt;
|Sent when a new value is presented on one of the ADC channels, cannot be invoked. Triggers the commands associated with the channel&lt;br /&gt;
|-&lt;br /&gt;
|adcsetting&lt;br /&gt;
|adcs&lt;br /&gt;
|channel : averages : interrupterrorthreshold : continuouserrorthreshold : continuoustimeout&lt;br /&gt;
|Sets ADC settings for a given channel. Averages are the number of samples to average, interruptthreshold is how much the value must change in order to issue a new value change event. continuousthreshold is how much the value must change when a previous change has already been recorded within the timespan of continuoustimeout&lt;br /&gt;
|-&lt;br /&gt;
|testadclatency&lt;br /&gt;
|tal&lt;br /&gt;
|0-65535&lt;br /&gt;
|Start a ADC latency test&lt;br /&gt;
|-&lt;br /&gt;
|testadclatencyreturn&lt;br /&gt;
|talr&lt;br /&gt;
| -&lt;br /&gt;
|Return from latency test&lt;br /&gt;
|-&lt;br /&gt;
|testadcminmax&lt;br /&gt;
|tix&lt;br /&gt;
|channel&lt;br /&gt;
|Test min/max value for a given channel and resets the counter&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;midiconfigurationhandler&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;midiconfigurationhandler&amp;quot;-&#039;&#039;module&#039;&#039; handles a number of &amp;quot;midiconfiguration&amp;quot;-&#039;&#039;modules&#039;&#039;. It has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|allnotesoff&lt;br /&gt;
|ano&lt;br /&gt;
| -&lt;br /&gt;
|Clears the entire buffer of MIDI notes held&lt;br /&gt;
|-&lt;br /&gt;
|add&lt;br /&gt;
|a&lt;br /&gt;
|name&lt;br /&gt;
|Adds a new MIDI configuration with the given name&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|int&lt;br /&gt;
|Remove the specified MIDI configuration&lt;br /&gt;
|-&lt;br /&gt;
|count&lt;br /&gt;
|c&lt;br /&gt;
| -&lt;br /&gt;
|Returns the number of MIDI configurations&lt;br /&gt;
|}&lt;br /&gt;
It contains one or more of the following&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|midiconfiguration&lt;br /&gt;
|mc&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;midiconfiguration&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
A &amp;quot;midiconfiguration&amp;quot;-&#039;&#039;module&#039;&#039; handles the reception of &#039;&#039;MIDI messages&#039;&#039; and will output the associated &#039;&#039;commands&#039;&#039; to the instrument internally. The commands are as follows&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|[index]&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
|Sets the currently selected MIDI configuration&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Set the name of the MIDI configuration&lt;br /&gt;
|-&lt;br /&gt;
|noteon&lt;br /&gt;
|non&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Note On event&lt;br /&gt;
|-&lt;br /&gt;
|noteoff&lt;br /&gt;
|nof&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Note Off event&lt;br /&gt;
|-&lt;br /&gt;
|polyaftertouch&lt;br /&gt;
|pat&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Polyphonic after touch event&lt;br /&gt;
|-&lt;br /&gt;
|channelaftertouch&lt;br /&gt;
|cat&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Channel after touch event&lt;br /&gt;
|-&lt;br /&gt;
|pitchbend&lt;br /&gt;
|pb&lt;br /&gt;
|&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|Sets the commands to execute at a MIDI Pitch bend event&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Knaadmin</name></author>
	</entry>
	<entry>
		<id>http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_reference_V1.1&amp;diff=1678</id>
		<title>The Ekdahl FAR - Command reference V1.1</title>
		<link rel="alternate" type="text/html" href="http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_reference_V1.1&amp;diff=1678"/>
		<updated>2026-06-12T15:36:04Z</updated>

		<summary type="html">&lt;p&gt;Knaadmin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
The Ekdahl FAR V1.1 introduces the concept of &#039;&#039;modules&#039;&#039;. A &#039;&#039;module&#039;&#039; can contain any number of &#039;&#039;commands&#039;&#039; as well as other &#039;&#039;modules&#039;&#039;. Furthermore any number of &#039;&#039;modules&#039;&#039; of the same type can exist within a context, these are addressed using classic C-style array &#039;&#039;indexing&#039;&#039; with the help of brackets (&amp;quot;[ ]&amp;quot;). Extending on the classic usage, multiple &#039;&#039;indexes&#039;&#039; can be addressed simultaneously by either comma-separating the objects (&amp;quot;[0,3,4]&amp;quot;) and using &#039;&#039;ranges&#039;&#039; (&amp;quot;[3-6]&amp;quot;). &#039;&#039;Modules&#039;&#039; can be either &#039;&#039;internal&#039;&#039; or &#039;&#039;external&#039;&#039;, meaning that they may all physically exist within a single hardware object, or they can be be remote-controlled devices. From a user perspective this however makes no difference as they will appear the same.&lt;br /&gt;
&lt;br /&gt;
While all &#039;&#039;modules&#039;&#039; have their own set of &#039;&#039;commands&#039;&#039;, there are certain &#039;&#039;commands&#039;&#039; that all &#039;&#039;modules&#039;&#039; &amp;lt;u&amp;gt;must&amp;lt;/u&amp;gt; implement and can thus be accessed anywhere within the &#039;&#039;module hierarchy.&#039;&#039; There are also &#039;&#039;base commands&#039;&#039; that always exist within any given FAR ecosystem as well as product-specific &#039;&#039;base commands&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Basic commands ==&lt;br /&gt;
The &#039;&#039;module commands&#039;&#039; that are &amp;lt;u&amp;gt;required&amp;lt;/u&amp;gt; to be implemented in &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; &#039;&#039;modules&#039;&#039; and that can thus be accessed from anywhere are&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|list&lt;br /&gt;
|ls&lt;br /&gt;
|hidden/h:modules/m:commands/c:instances/i:instancecounts/ic:recursive/r&lt;br /&gt;
|Lists all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039; under the current module depending on the parameters given; &#039;hidden&#039; includes normally hidden &#039;&#039;commands&#039;&#039;, &#039;modules&#039; includes any &#039;&#039;submodules&#039;&#039;, &#039;commands&#039; shows &#039;&#039;commands&#039;&#039;, &#039;instances&#039; shows data for each individual instance of a &#039;&#039;module&#039;&#039;, &#039;instancecounts&#039; includes number of instances of each &#039;&#039;module&#039;&#039;, &#039;recursive&#039; lists all child &#039;&#039;modules&#039;&#039; / &#039;&#039;commands&#039;&#039;. No parameters defaults to showing all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039; recursively with instance counts. It doesn&#039;t show per-instance data or hidden commands.&lt;br /&gt;
|-&lt;br /&gt;
|help&lt;br /&gt;
|help&lt;br /&gt;
|recursive/r&lt;br /&gt;
|Shows a brief explanation of all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039;, shows the help for all &#039;&#039;submodules&#039;&#039; as well if &#039;recursive&#039;&lt;br /&gt;
|-&lt;br /&gt;
|dumpdata&lt;br /&gt;
|dump&lt;br /&gt;
|recursive/r&lt;br /&gt;
|Dumps all data saved for the current &#039;&#039;module&#039;&#039;, will list the data of all &#039;&#039;submodules&#039;&#039; as well if &#039;recursive&#039;&lt;br /&gt;
|}&lt;br /&gt;
The &#039;&#039;base commands&#039;&#039; are as follows&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|version&lt;br /&gt;
|ver&lt;br /&gt;
| -&lt;br /&gt;
|Gets the current firmware version&lt;br /&gt;
|-&lt;br /&gt;
|debugprint&lt;br /&gt;
|dp&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;command|usb|hardware|undefined|priority|error|inforequest|expressionparser|debug:1|0&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Turns on or off serial feedback for the given item&lt;br /&gt;
|-&lt;br /&gt;
|requestinfo&lt;br /&gt;
|rqi&lt;br /&gt;
|command&lt;br /&gt;
|Retrives any data saved for a &#039;&#039;command&#039;&#039;, if applicable&lt;br /&gt;
|-&lt;br /&gt;
|saveallparameters&lt;br /&gt;
|sap&lt;br /&gt;
| -&lt;br /&gt;
|Saves all avaliable parameters&lt;br /&gt;
|-&lt;br /&gt;
|loadallparameters&lt;br /&gt;
|lap&lt;br /&gt;
| -&lt;br /&gt;
|Loads all avaliable parameters&lt;br /&gt;
|-&lt;br /&gt;
|resetallparameters&lt;br /&gt;
|rap&lt;br /&gt;
| -&lt;br /&gt;
|Resets all saved parameters&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|rst&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;1|0&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Resets the Ekdahl FAR, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|nick&lt;br /&gt;
|nick&lt;br /&gt;
|name&lt;br /&gt;
|Sets the nickname of this unit&lt;br /&gt;
|-&lt;br /&gt;
|nooperation&lt;br /&gt;
|nop&lt;br /&gt;
| -&lt;br /&gt;
|Do absolutely, positively, nothing. Useful for testing and interfacing with computers, it&#039;s a good way to know that the unit is alive and responding since a &amp;quot;nop&amp;quot; is being returned as a response upon reception.&lt;br /&gt;
|-&lt;br /&gt;
|uservariable&lt;br /&gt;
|uv&lt;br /&gt;
|variable(0-9):value&lt;br /&gt;
|Set user variable 0-9 to &#039;value&#039;&lt;br /&gt;
|-&lt;br /&gt;
|expressionparserevaluate&lt;br /&gt;
|epev&lt;br /&gt;
|expression&lt;br /&gt;
|Evaluates an arithmetric expression and sends back the output, all variables and functions that can be used in any &#039;&#039;command string&#039;&#039; can also be used here. Useful for testing expressions.&lt;br /&gt;
|-&lt;br /&gt;
|ifequal&lt;br /&gt;
|ife&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] EQUALS [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring].&lt;br /&gt;
|-&lt;br /&gt;
|ifgreater&lt;br /&gt;
|ifg&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] &amp;gt; [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring]&lt;br /&gt;
|-&lt;br /&gt;
|ifless&lt;br /&gt;
|ifl&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] &amp;lt; [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring]&lt;br /&gt;
|-&lt;br /&gt;
|freeram&lt;br /&gt;
|ram&lt;br /&gt;
| -&lt;br /&gt;
|Shows free RAM memory&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The base also contains the following &#039;&#039;modules:&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|pluginhandler&lt;br /&gt;
|ph&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The Ekdahl FAR stand alone single string unit ==&lt;br /&gt;
The Ekdahl FAR stand-alone single string unit offers these &#039;&#039;commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|calibrateall&lt;br /&gt;
|ca&lt;br /&gt;
| -&lt;br /&gt;
|Performs all calibration routines on the selected bow, see below for routines performed&lt;br /&gt;
|-&lt;br /&gt;
|calibratebowspeed&lt;br /&gt;
|cbs&lt;br /&gt;
| -&lt;br /&gt;
|Finds the minimum and maximum bow speed of the selected bow&lt;br /&gt;
|-&lt;br /&gt;
|calibratebowpressure&lt;br /&gt;
|cbp&lt;br /&gt;
| -&lt;br /&gt;
|Finds the minimum and maximum bow pressure of the selected bow&lt;br /&gt;
|-&lt;br /&gt;
|calibratemute&lt;br /&gt;
|cmu&lt;br /&gt;
| -&lt;br /&gt;
|Calibrate mute settings&lt;br /&gt;
|-&lt;br /&gt;
|pickupstringfrequency&lt;br /&gt;
|psf&lt;br /&gt;
| -&lt;br /&gt;
|Returns the fundamental tone calculated from the current audio signal if apliccable&lt;br /&gt;
|-&lt;br /&gt;
|pickupaudiopeak&lt;br /&gt;
|pap&lt;br /&gt;
| -&lt;br /&gt;
|Returns the peak amplitude of the current audio signal&lt;br /&gt;
|-&lt;br /&gt;
|pickupaudiorms&lt;br /&gt;
|par&lt;br /&gt;
| -&lt;br /&gt;
|Returns the RMS amplitude of the current audio signal&lt;br /&gt;
|}&lt;br /&gt;
The Ekdahl FAR also contains the following &#039;&#039;modules&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|bowingwheel&lt;br /&gt;
|bw&lt;br /&gt;
|-&lt;br /&gt;
|mute&lt;br /&gt;
|mu&lt;br /&gt;
|-&lt;br /&gt;
|solenoid&lt;br /&gt;
|so&lt;br /&gt;
|-&lt;br /&gt;
|controlbox&lt;br /&gt;
|cb&lt;br /&gt;
|-&lt;br /&gt;
|midiconfigurationhandler&lt;br /&gt;
|mcf&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;Bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; contains everything needed to interface with a single &#039;&#039;bowing wheel&#039;&#039;. Each &#039;&#039;bowing wheel&#039;&#039; has its own harmonic series, pressure actuators and direct hardware interface. It contains the following &#039;&#039;commands&#039;&#039;.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|speedmode&lt;br /&gt;
|sm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Bow motor speed mode, 0 = Automatic and 1 = Manual. Automatic mode means that the bowing wheel will automatically turn off after the &#039;&#039;motor timeout&#039;&#039; has been reached after being put into rest mode&lt;br /&gt;
|-&lt;br /&gt;
|motortimeout&lt;br /&gt;
|mt&lt;br /&gt;
|ms&lt;br /&gt;
|Bow motor shutdown timeout after bow having been put into the rest position&lt;br /&gt;
|-&lt;br /&gt;
|pidenable&lt;br /&gt;
|pe&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets the bow PID on/off&lt;br /&gt;
|-&lt;br /&gt;
|motorfaultcommands&lt;br /&gt;
|mfc&lt;br /&gt;
|commands&lt;br /&gt;
|Commands to execute when a motor fault is tripped - !WARNING! Can ruin your instrument if changed&lt;br /&gt;
|-&lt;br /&gt;
|motoroverpowercommands&lt;br /&gt;
|moc&lt;br /&gt;
|commands&lt;br /&gt;
|Commands to execute when motor is over the power limit - !WARNING! Can ruin your instrument if changed&lt;br /&gt;
|}&lt;br /&gt;
The &#039;&#039;modules&#039;&#039; in the &amp;quot;Bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; are as follows&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|bowpressure&lt;br /&gt;
|bp&lt;br /&gt;
|-&lt;br /&gt;
|dcmotor&lt;br /&gt;
|dcm&lt;br /&gt;
|-&lt;br /&gt;
|pid&lt;br /&gt;
|pid&lt;br /&gt;
|-&lt;br /&gt;
|harmonicserieshandler&lt;br /&gt;
|hsh&lt;br /&gt;
|}&lt;br /&gt;
The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; handles the &#039;&#039;pressure&#039;&#039; of the &#039;&#039;bowing wheel&#039;&#039; against the string. The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|baseline&lt;br /&gt;
|ba&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure baseline, modulation is added to this point upward. Typically this is set with a knob on the &#039;&#039;control box&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|modifier&lt;br /&gt;
|mo&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure modulation, added to the baseline&lt;br /&gt;
|-&lt;br /&gt;
|rest&lt;br /&gt;
|rs&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the bow pressure in the &#039;&#039;rest&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|engage&lt;br /&gt;
|en&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the bow pressure in the &#039;&#039;engage&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|stallpressure&lt;br /&gt;
|sp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure stall/maximum position, this parameter is set using &#039;&#039;hardware positioning&#039;&#039; and is used as the absolute maximum for baseline and modifier combiner&lt;br /&gt;
|-&lt;br /&gt;
|engagepressure&lt;br /&gt;
|ep&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure touch/minimum position, this parameter is set using &#039;&#039;hardware position&#039;&#039; and is used as the starting point for when both the baseline and modifier is set to zero&lt;br /&gt;
|-&lt;br /&gt;
|restpressure&lt;br /&gt;
|rp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure rest position, this parameter is set using &#039;&#039;hardware positioning&#039;&#039; and is typically set to a point just below the string where it does not touch at all. The purpose of this is because while the actual hardware might be able to make the bow go even lower, that position might be far enough from the string that once &#039;&#039;engaged&#039;&#039; the bow may have so far to travel that there is perceptible &#039;&#039;latency&#039;&#039;.&lt;br /&gt;
|-&lt;br /&gt;
|engagespeed&lt;br /&gt;
|es&lt;br /&gt;
|1- ~100&lt;br /&gt;
|Bow pressure movement speed when engaging or disengaging&lt;br /&gt;
|-&lt;br /&gt;
|modulationspeed&lt;br /&gt;
|ms&lt;br /&gt;
|0.1 - 10&lt;br /&gt;
|Bow pressure movement speed while engaged&lt;br /&gt;
|-&lt;br /&gt;
|hold&lt;br /&gt;
|hd&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets bow hold (infinite sustain) on/off, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|home&lt;br /&gt;
|hm&lt;br /&gt;
| -&lt;br /&gt;
|Homing bow, used at startup and in case of the bow loosing position&lt;br /&gt;
|-&lt;br /&gt;
|tmcinfo&lt;br /&gt;
|tmi&lt;br /&gt;
| -&lt;br /&gt;
|Request statistical information from the TMC2209 stepper motor driver&lt;br /&gt;
|}&lt;br /&gt;
Note that the &amp;quot;stall&amp;quot;, &amp;quot;engage&amp;quot; and &amp;quot;rest&amp;quot;-pressure positions mention something called &#039;&#039;hardware position&#039;&#039;. This means the entire available movement of the &#039;&#039;bowing jack&#039;&#039;. Because the very bottom and top end of the movement might not be musically useful and may even harm the instrument, the &amp;quot;baseline&amp;quot; and &amp;quot;modifier&amp;quot; commands &#039;&#039;parameter&#039;&#039;s are scaled depending on these settings.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;engage&amp;quot; and &amp;quot;modulation&amp;quot;-speed settings sets how fast the stepper motor that drives the &#039;&#039;pressure&#039;&#039; moves depending on whether the &#039;&#039;bowing jack&#039;&#039; is set to &#039;&#039;engage&#039;&#039; or not. The idea here is that while wanting to be able to minimize &#039;&#039;latency&#039;&#039; by &#039;&#039;engaging&#039;&#039; and &#039;&#039;disengaging&#039;&#039; from the string as quickly as possible, dynamic changes in the &#039;&#039;pressure&#039;&#039; while playing benefits from much smoother movements as the &#039;&#039;bowing wheel&#039;&#039; takes some time to catch up to varying amounts of friction.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;dcmotor&amp;quot;-&#039;&#039;module&#039;&#039; handles the direct &amp;lt;u&amp;gt;raw&amp;lt;/u&amp;gt; control of the &#039;&#039;bowing motor&#039;&#039; and handles the reporting back of the current speed. It has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|run&lt;br /&gt;
|ru&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Turns the motor off/on&lt;br /&gt;
|-&lt;br /&gt;
|pwm&lt;br /&gt;
|pw&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor direct power in 16-bit PWM values, requires that the &#039;&#039;PID&#039;&#039; is turned off&lt;br /&gt;
|-&lt;br /&gt;
|voltage&lt;br /&gt;
|vo&lt;br /&gt;
|~2 - 10V&lt;br /&gt;
|Sets the voltage of the regulator powering the motor. Changes here can make the motor more responsive to certain frequencies but will also affect how well the &#039;&#039;PID&#039;&#039; works. !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|current&lt;br /&gt;
|cu&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor reported current use&lt;br /&gt;
|-&lt;br /&gt;
|currentlimit&lt;br /&gt;
|cl&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor current limit (A)- !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|powerlimit&lt;br /&gt;
|pl&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor power limit (W) - !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|frequency&lt;br /&gt;
|fq&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor reported frequency&lt;br /&gt;
|-&lt;br /&gt;
|emergencystop&lt;br /&gt;
|es&lt;br /&gt;
|ms (0-65535)&lt;br /&gt;
|Immediately stops the bowing motor and doesn&#039;t allow it to start again until the cool down period given in the first argument has lapsed (milliseconds)&lt;br /&gt;
|-&lt;br /&gt;
|minpwm&lt;br /&gt;
|ip&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor minimum PWM (for calibration)&lt;br /&gt;
|-&lt;br /&gt;
|maxpwm&lt;br /&gt;
|xp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor maximum PWM (for calibration)&lt;br /&gt;
|}&lt;br /&gt;
The &amp;quot;pidcontroller&amp;quot;-&#039;&#039;module&#039;&#039; is responsible for keeping the &amp;quot;dcmotor&amp;quot;-&#039;&#039;module&#039;&#039; at a certain frequency (given in Hertz). It takes the output of the motor frequency measurement and feeds it a PWM value that tries to make the speed constant regardless of the friction that the motor is enduring. To learn more about PID Controllers please see this [[wikipedia:PID_controller|wikipedia article]]. The &#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|targetfrequency&lt;br /&gt;
|tf&lt;br /&gt;
|hertz&lt;br /&gt;
|Sets the PID target frequency&lt;br /&gt;
|-&lt;br /&gt;
|ki&lt;br /&gt;
|ki&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Ki parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|kp&lt;br /&gt;
|kp&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Kp parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|kd&lt;br /&gt;
|kd&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Kd parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|integratorerror&lt;br /&gt;
|ie&lt;br /&gt;
|float&lt;br /&gt;
|Sets the lower threshold of error values for the PID integrator to ignore&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|re&lt;br /&gt;
| -&lt;br /&gt;
|Resets the PID integrator and derivative&lt;br /&gt;
|-&lt;br /&gt;
|maxerror&lt;br /&gt;
|xe&lt;br /&gt;
|float&lt;br /&gt;
|Maximum error to correct in each PID loop, essentially sets acceleration&lt;br /&gt;
|-&lt;br /&gt;
|peakerror&lt;br /&gt;
|pe&lt;br /&gt;
|float&lt;br /&gt;
|Get latest PID peak error&lt;br /&gt;
|-&lt;br /&gt;
|motorspeedmax&lt;br /&gt;
|msx&lt;br /&gt;
|Hertz&lt;br /&gt;
|Bow motor maximum speed limit&lt;br /&gt;
|-&lt;br /&gt;
|motorspeedmin&lt;br /&gt;
|msi&lt;br /&gt;
|Hertz&lt;br /&gt;
|Bow motor minimum speed limit&lt;br /&gt;
|-&lt;br /&gt;
|measuretimetotarget&lt;br /&gt;
|mtt&lt;br /&gt;
|Hertz&lt;br /&gt;
|Measure the time it takes to change from the current frequency to the target frequency, for testing purposes&lt;br /&gt;
|}&lt;br /&gt;
The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; is responsible for sending frequency data to the &amp;quot;pid&amp;quot;-&#039;&#039;module&#039;&#039;. It handles calculating the correct frequency of the &#039;&#039;bowing wheel&#039;&#039; according to the selected &#039;&#039;harmonic&#039;&#039; and &#039;&#039;harmonic shift&#039;&#039; per the currently selected &#039;&#039;harmonic series&#039;&#039;. The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|fundamental&lt;br /&gt;
|fu&lt;br /&gt;
|Hertz&lt;br /&gt;
|The fundamental frequency of the string, all harmonics are calculated from this number&lt;br /&gt;
|-&lt;br /&gt;
|harmonic&lt;br /&gt;
|h&lt;br /&gt;
|int&lt;br /&gt;
|Selects the harmonic number to set the &#039;&#039;bowing wheel&#039;&#039; to. A ratio is taken from the given &#039;&#039;harmonic&#039;&#039; in the current &#039;&#039;harmonic series&#039;&#039;, the ratio is then multiplied by the &#039;&#039;fundamental frequency&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|harmonicadd&lt;br /&gt;
|ha&lt;br /&gt;
|int&lt;br /&gt;
|This number is added to the current harmonic&lt;br /&gt;
|-&lt;br /&gt;
|harmonicbase&lt;br /&gt;
|hb&lt;br /&gt;
|int&lt;br /&gt;
|Same as harmonic but where the harmonic number is based on a MIDI note given by basenote&lt;br /&gt;
|-&lt;br /&gt;
|basenote&lt;br /&gt;
|bn&lt;br /&gt;
|0-127&lt;br /&gt;
|Sets the MIDI base note of the &#039;&#039;bowing wheel&#039;&#039;, used in conjunction with &amp;quot;harmonicbase&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|shift&lt;br /&gt;
|sh&lt;br /&gt;
| -32767 - 32767&lt;br /&gt;
|Sets shift from the currently playing harmonic where 32767 equals the entire harmonic shift range shifted up&lt;br /&gt;
|-&lt;br /&gt;
|shiftrange&lt;br /&gt;
|sr&lt;br /&gt;
|0-36&lt;br /&gt;
|Set the number of harmonic numbers that constitutes an entire harmonic shift&lt;br /&gt;
|-&lt;br /&gt;
|shift5&lt;br /&gt;
|sh5&lt;br /&gt;
| -32767 - 32767&lt;br /&gt;
|Sets the shift from the currently playing harmonic over 5 octaves where 32767 equals 5 octaves shift up from the fundamental&lt;br /&gt;
|-&lt;br /&gt;
|add&lt;br /&gt;
|a&lt;br /&gt;
|(name):(ratios)&lt;br /&gt;
|Add a new series with the given name and parameters&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|series&lt;br /&gt;
|Remove the series given and shift any series accordingly. Cannot remove all series&lt;br /&gt;
|-&lt;br /&gt;
|count&lt;br /&gt;
|c&lt;br /&gt;
| -&lt;br /&gt;
|Returns the number of harmonic series in the list and their IDs&lt;br /&gt;
|}&lt;br /&gt;
The &amp;quot;harmonicserieshandler&amp;quot;-module contains at the very least ONE harmonic series, by default it contains two: one for equal temperament and one for just intonation. The current series can be selected by simply indexing the &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; without a &#039;&#039;command&#039;&#039;, e.g. &amp;quot;harmonicserieshandler.harmonicseries[1]&amp;quot;. To be consistent, these are the &#039;&#039;modules&#039;&#039; in the &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|harmonicseries&lt;br /&gt;
|hs&lt;br /&gt;
|}&lt;br /&gt;
The &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; contains any number of &#039;&#039;ratios&#039;&#039; that comprises a scale, ratios are given in a standard format where a ratio of &amp;quot;1&amp;quot; is equal to the fundamental, &amp;quot;2&amp;quot; would be one octave up etc. A standard &#039;&#039;harmonic series&#039;&#039; contains 12 ratios following a just intonation scheme. The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; will automatically adapt to the currently selected &#039;&#039;harmonic series&#039;&#039; length, whether it&#039;s a standard 12-tone scale, some kinda 3-tone scale or a full on bananas 53-tone scale. The &#039;&#039;commands&#039;&#039; of the &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; is as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|[index]&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
|Sets the currently selected &#039;&#039;harmonic Series&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Sets the name of the &#039;&#039;harmonic series&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|data&lt;br /&gt;
|da&lt;br /&gt;
|name:ratios&lt;br /&gt;
|Gets / sets all data for the &#039;&#039;harmonic series&#039;&#039; in the given slot with an arbitrary &#039;&#039;name&#039;&#039; as the first &#039;&#039;parameter&#039;&#039;. The length of the series is simply set to the amount of ratios given&lt;br /&gt;
|-&lt;br /&gt;
|ratio&lt;br /&gt;
|r&lt;br /&gt;
|harmonic:ratio&lt;br /&gt;
|Sets the ratio of the given harmonic in current &#039;&#039;harmonic series&#039;&#039;, will increase the list size if needed to address the harmonic&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|harmonic&lt;br /&gt;
|Remove the harmonic ratio given in the current series and shift any ratios accordingly. Cannot remove all ratios&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;mute&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;mute&amp;quot;-&#039;&#039;module&#039;&#039; works very similarly to the &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; in that it controls a stepper motor with some software limits in place in order to press the mute against the string. The &#039;&#039;commands&#039;&#039; are as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|setposition&lt;br /&gt;
|sp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set mute position&lt;br /&gt;
|-&lt;br /&gt;
|fullmute&lt;br /&gt;
|fm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the mute in &#039;&#039;full mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|halfmute&lt;br /&gt;
|hm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the mute in &#039;&#039;half mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|rest&lt;br /&gt;
|rs&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Put the mute in the &#039;&#039;rest&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|savefull&lt;br /&gt;
|sf&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Save the current mute position as the &#039;&#039;full mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|savehalf&lt;br /&gt;
|sh&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Save the current mute position as the &#039;&#039;half mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|saverest&lt;br /&gt;
|sr&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Save the current mute position as the &#039;&#039;rest&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|fullmuteposition&lt;br /&gt;
|fmp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;full mute&#039;&#039; position according to the &#039;&#039;hardware position&#039;&#039; given&lt;br /&gt;
|-&lt;br /&gt;
|halfmuteposition&lt;br /&gt;
|hmp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;half mute&#039;&#039; position according to the &#039;&#039;hardware position&#039;&#039; given&lt;br /&gt;
|-&lt;br /&gt;
|restposition&lt;br /&gt;
|rp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;rest&#039;&#039; position according to the &#039;&#039;hardware position&#039;&#039; given&lt;br /&gt;
|-&lt;br /&gt;
|sustain&lt;br /&gt;
|su&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets the sustain off/on, this will keep the mute in the &#039;&#039;rest&#039;&#039; position even if a &amp;quot;fullmute&amp;quot;-&#039;&#039;command&#039;&#039; is given, lasts until &amp;quot;sustain&amp;quot; is set to &amp;quot;0&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
|backoff&lt;br /&gt;
|bo&lt;br /&gt;
|0-65535&lt;br /&gt;
|Setting the time that the mute stays in the mutefullmute position before automatically going into rest, set in mS. A value of &amp;quot;0&amp;quot; disables backoff. This is used because if the mute is not backing off until something is attempted to be played, the backing-off time will either introduce &#039;&#039;latency&#039;&#039; or the string will be initially partially muted&lt;br /&gt;
|-&lt;br /&gt;
|home&lt;br /&gt;
|hm&lt;br /&gt;
| -&lt;br /&gt;
|Home mute, used during initialization and if the mute were to loose position&lt;br /&gt;
|-&lt;br /&gt;
|hardwareposition&lt;br /&gt;
|hwp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;hardware position&#039;&#039; of the mute instead of scaling it over the &#039;&#039;full mute&#039;&#039; and &#039;&#039;rest&#039;&#039; positions. Mainly used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|completetask&lt;br /&gt;
|cpt&lt;br /&gt;
| -&lt;br /&gt;
|Requests a callback when the current operation is finished. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|autocorrect&lt;br /&gt;
|ac&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Enables auto correct positioning that uses the homing sensor to correct positioning on the fly. EXPERIMENTAL&lt;br /&gt;
|-&lt;br /&gt;
|homingsensed&lt;br /&gt;
|hms&lt;br /&gt;
| -&lt;br /&gt;
|Requests whether the homing sensor is currently active or not. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|movedirection&lt;br /&gt;
|md&lt;br /&gt;
| -&lt;br /&gt;
|Requests the current direction of movement (0 Forward, 1 Reverse). Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|currentstep&lt;br /&gt;
|cs&lt;br /&gt;
| -&lt;br /&gt;
|Requests the current step. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|homingpoint&lt;br /&gt;
|hmp&lt;br /&gt;
|edgedirection&lt;br /&gt;
|Requests the given homing point. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|homingstage&lt;br /&gt;
|hms&lt;br /&gt;
| -&lt;br /&gt;
|Requests the current homing stage (UNHOMED, HOMED, FIRSTHOMINGRISING, SECONDHOMINGFALLING, SECONDHOMINGRISING, FIRSTHOMINGFALLING, MOVEPASTHOMESWITCH, MOVETOHOMESWITCH, GOTOOFFSET). Only used internally by other &#039;&#039;modules.&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|tmcinfo&lt;br /&gt;
|tmi&lt;br /&gt;
| -&lt;br /&gt;
|Request statistical information from the TMC2209 stepper motor driver&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;solenoid&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;solenoid&amp;quot;-&#039;&#039;module&#039;&#039; currently controls the &#039;&#039;hammer&#039;&#039; of the Ekdahl FAR. Due to the fact that the very same &#039;&#039;module&#039;&#039; could be used for anything that uses a striking &#039;&#039;solenoid&#039;&#039; it was named as such. It has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|engage&lt;br /&gt;
|en&lt;br /&gt;
|0-65535&lt;br /&gt;
|Engages the solenoid using the first parameter as the force&lt;br /&gt;
|-&lt;br /&gt;
|rest&lt;br /&gt;
|rs&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Forces the solenoid to its rest position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|maxforce&lt;br /&gt;
|xf&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set solenoid maximum usable force&lt;br /&gt;
|-&lt;br /&gt;
|minforce&lt;br /&gt;
|if&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set solenoid minimum usable force&lt;br /&gt;
|-&lt;br /&gt;
|forcemultiplier&lt;br /&gt;
|fm&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set solenoid force multiplier, useful for scaling of all incoming &amp;quot;engage&amp;quot;-&#039;&#039;commands&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|engageduration&lt;br /&gt;
|ed&lt;br /&gt;
|uS&lt;br /&gt;
|Sets the duration of the solenoid hit in uS, if a value of 0 is set the solenoid will not disengage until a rest command has been given. WARNING!! HAVING THE SOLENOID ON FOR A SPAN OF SECONDS COULD DESTROY THE CIRCUITRY!!&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;controlbox&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;controlbox&amp;quot;-&#039;&#039;module&#039;&#039; communicates with an external &#039;&#039;control box&#039;&#039; and will issue associated &#039;&#039;commands&#039;&#039; whenever new values are read on the ADC-converters. It handles averaging and does some noise-cancellation functions on the values as well. The &#039;&#039;commands&#039;&#039; are:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|harmonic&lt;br /&gt;
|har&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the harmonic knob or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|harmonicshift&lt;br /&gt;
|has&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the harmonic shift modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|finetune&lt;br /&gt;
|fin&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the fine tune knob changes&lt;br /&gt;
|-&lt;br /&gt;
|pressure&lt;br /&gt;
|pre&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the pressure knob or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|mute&lt;br /&gt;
|mut&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the mute knob or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|hammerscale&lt;br /&gt;
|hms&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the hammer scale knob changes&lt;br /&gt;
|-&lt;br /&gt;
|gate&lt;br /&gt;
|gt&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the gate switch or modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|hammertrig&lt;br /&gt;
|hmt&lt;br /&gt;
|command string&lt;br /&gt;
|Sets the command string invoked when the hammer trigger modulation changes&lt;br /&gt;
|-&lt;br /&gt;
|controldefaults&lt;br /&gt;
|cde&lt;br /&gt;
| -&lt;br /&gt;
|Reverts all ADC command strings to default values&lt;br /&gt;
|-&lt;br /&gt;
|datareturn&lt;br /&gt;
|dr&lt;br /&gt;
|channel:value&lt;br /&gt;
|Sent when a new value is presented on one of the ADC channels, cannot be invoked. Triggers the commands associated with the channel&lt;br /&gt;
|-&lt;br /&gt;
|adcsetting&lt;br /&gt;
|adcs&lt;br /&gt;
|channel : averages : interrupterrorthreshold : continuouserrorthreshold : continuoustimeout&lt;br /&gt;
|&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Knaadmin</name></author>
	</entry>
	<entry>
		<id>http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_reference_V1.1&amp;diff=1677</id>
		<title>The Ekdahl FAR - Command reference V1.1</title>
		<link rel="alternate" type="text/html" href="http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_reference_V1.1&amp;diff=1677"/>
		<updated>2026-06-12T15:10:00Z</updated>

		<summary type="html">&lt;p&gt;Knaadmin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
The Ekdahl FAR V1.1 introduces the concept of &#039;&#039;modules&#039;&#039;. A &#039;&#039;module&#039;&#039; can contain any number of &#039;&#039;commands&#039;&#039; as well as other &#039;&#039;modules&#039;&#039;. Furthermore any number of &#039;&#039;modules&#039;&#039; of the same type can exist within a context, these are addressed using classic C-style array &#039;&#039;indexing&#039;&#039; with the help of brackets (&amp;quot;[ ]&amp;quot;). Extending on the classic usage, multiple &#039;&#039;indexes&#039;&#039; can be addressed simultaneously by either comma-separating the objects (&amp;quot;[0,3,4]&amp;quot;) and using &#039;&#039;ranges&#039;&#039; (&amp;quot;[3-6]&amp;quot;). &#039;&#039;Modules&#039;&#039; can be either &#039;&#039;internal&#039;&#039; or &#039;&#039;external&#039;&#039;, meaning that they may all physically exist within a single hardware object, or they can be be remote-controlled devices. From a user perspective this however makes no difference as they will appear the same.&lt;br /&gt;
&lt;br /&gt;
While all &#039;&#039;modules&#039;&#039; have their own set of &#039;&#039;commands&#039;&#039;, there are certain &#039;&#039;commands&#039;&#039; that all &#039;&#039;modules&#039;&#039; &amp;lt;u&amp;gt;must&amp;lt;/u&amp;gt; implement and can thus be accessed anywhere within the &#039;&#039;module hierarchy.&#039;&#039; There are also &#039;&#039;base commands&#039;&#039; that always exist within any given FAR ecosystem as well as product-specific &#039;&#039;base commands&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Basic commands ==&lt;br /&gt;
The &#039;&#039;module commands&#039;&#039; that are &amp;lt;u&amp;gt;required&amp;lt;/u&amp;gt; to be implemented in &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; &#039;&#039;modules&#039;&#039; and that can thus be accessed from anywhere are&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|list&lt;br /&gt;
|ls&lt;br /&gt;
|hidden/h:modules/m:commands/c:instances/i:instancecounts/ic:recursive/r&lt;br /&gt;
|Lists all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039; under the current module depending on the parameters given; &#039;hidden&#039; includes normally hidden &#039;&#039;commands&#039;&#039;, &#039;modules&#039; includes any &#039;&#039;submodules&#039;&#039;, &#039;commands&#039; shows &#039;&#039;commands&#039;&#039;, &#039;instances&#039; shows data for each individual instance of a &#039;&#039;module&#039;&#039;, &#039;instancecounts&#039; includes number of instances of each &#039;&#039;module&#039;&#039;, &#039;recursive&#039; lists all child &#039;&#039;modules&#039;&#039; / &#039;&#039;commands&#039;&#039;. No parameters defaults to showing all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039; recursively with instance counts. It doesn&#039;t show per-instance data or hidden commands.&lt;br /&gt;
|-&lt;br /&gt;
|help&lt;br /&gt;
|help&lt;br /&gt;
|recursive/r&lt;br /&gt;
|Shows a brief explanation of all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039;, shows the help for all &#039;&#039;submodules&#039;&#039; as well if &#039;recursive&#039;&lt;br /&gt;
|-&lt;br /&gt;
|dumpdata&lt;br /&gt;
|dump&lt;br /&gt;
|recursive/r&lt;br /&gt;
|Dumps all data saved for the current &#039;&#039;module&#039;&#039;, will list the data of all &#039;&#039;submodules&#039;&#039; as well if &#039;recursive&#039;&lt;br /&gt;
|}&lt;br /&gt;
The &#039;&#039;base commands&#039;&#039; are as follows&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|version&lt;br /&gt;
|ver&lt;br /&gt;
| -&lt;br /&gt;
|Gets the current firmware version&lt;br /&gt;
|-&lt;br /&gt;
|debugprint&lt;br /&gt;
|dp&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;command|usb|hardware|undefined|priority|error|inforequest|expressionparser|debug:1|0&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Turns on or off serial feedback for the given item&lt;br /&gt;
|-&lt;br /&gt;
|requestinfo&lt;br /&gt;
|rqi&lt;br /&gt;
|command&lt;br /&gt;
|Retrives any data saved for a &#039;&#039;command&#039;&#039;, if applicable&lt;br /&gt;
|-&lt;br /&gt;
|saveallparameters&lt;br /&gt;
|sap&lt;br /&gt;
| -&lt;br /&gt;
|Saves all avaliable parameters&lt;br /&gt;
|-&lt;br /&gt;
|loadallparameters&lt;br /&gt;
|lap&lt;br /&gt;
| -&lt;br /&gt;
|Loads all avaliable parameters&lt;br /&gt;
|-&lt;br /&gt;
|resetallparameters&lt;br /&gt;
|rap&lt;br /&gt;
| -&lt;br /&gt;
|Resets all saved parameters&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|rst&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;1|0&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Resets the Ekdahl FAR, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|nick&lt;br /&gt;
|nick&lt;br /&gt;
|name&lt;br /&gt;
|Sets the nickname of this unit&lt;br /&gt;
|-&lt;br /&gt;
|nooperation&lt;br /&gt;
|nop&lt;br /&gt;
| -&lt;br /&gt;
|Do absolutely, positively, nothing. Useful for testing and interfacing with computers, it&#039;s a good way to know that the unit is alive and responding since a &amp;quot;nop&amp;quot; is being returned as a response upon reception.&lt;br /&gt;
|-&lt;br /&gt;
|uservariable&lt;br /&gt;
|uv&lt;br /&gt;
|variable(0-9):value&lt;br /&gt;
|Set user variable 0-9 to &#039;value&#039;&lt;br /&gt;
|-&lt;br /&gt;
|expressionparserevaluate&lt;br /&gt;
|epev&lt;br /&gt;
|expression&lt;br /&gt;
|Evaluates an arithmetric expression and sends back the output, all variables and functions that can be used in any &#039;&#039;command string&#039;&#039; can also be used here. Useful for testing expressions.&lt;br /&gt;
|-&lt;br /&gt;
|ifequal&lt;br /&gt;
|ife&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] EQUALS [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring].&lt;br /&gt;
|-&lt;br /&gt;
|ifgreater&lt;br /&gt;
|ifg&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] &amp;gt; [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring]&lt;br /&gt;
|-&lt;br /&gt;
|ifless&lt;br /&gt;
|ifl&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] &amp;lt; [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring]&lt;br /&gt;
|-&lt;br /&gt;
|freeram&lt;br /&gt;
|ram&lt;br /&gt;
| -&lt;br /&gt;
|Shows free RAM memory&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The base also contains the following &#039;&#039;modules:&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|pluginhandler&lt;br /&gt;
|ph&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The Ekdahl FAR stand alone single string unit ==&lt;br /&gt;
The Ekdahl FAR stand-alone single string unit offers these &#039;&#039;commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|calibrateall&lt;br /&gt;
|ca&lt;br /&gt;
| -&lt;br /&gt;
|Performs all calibration routines on the selected bow, see below for routines performed&lt;br /&gt;
|-&lt;br /&gt;
|calibratebowspeed&lt;br /&gt;
|cbs&lt;br /&gt;
| -&lt;br /&gt;
|Finds the minimum and maximum bow speed of the selected bow&lt;br /&gt;
|-&lt;br /&gt;
|calibratebowpressure&lt;br /&gt;
|cbp&lt;br /&gt;
| -&lt;br /&gt;
|Finds the minimum and maximum bow pressure of the selected bow&lt;br /&gt;
|-&lt;br /&gt;
|calibratemute&lt;br /&gt;
|cmu&lt;br /&gt;
| -&lt;br /&gt;
|Calibrate mute settings&lt;br /&gt;
|-&lt;br /&gt;
|pickupstringfrequency&lt;br /&gt;
|psf&lt;br /&gt;
| -&lt;br /&gt;
|Returns the fundamental tone calculated from the current audio signal if apliccable&lt;br /&gt;
|-&lt;br /&gt;
|pickupaudiopeak&lt;br /&gt;
|pap&lt;br /&gt;
| -&lt;br /&gt;
|Returns the peak amplitude of the current audio signal&lt;br /&gt;
|-&lt;br /&gt;
|pickupaudiorms&lt;br /&gt;
|par&lt;br /&gt;
| -&lt;br /&gt;
|Returns the RMS amplitude of the current audio signal&lt;br /&gt;
|}&lt;br /&gt;
The Ekdahl FAR also contains the following &#039;&#039;modules&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|bowingwheel&lt;br /&gt;
|bw&lt;br /&gt;
|-&lt;br /&gt;
|mute&lt;br /&gt;
|mu&lt;br /&gt;
|-&lt;br /&gt;
|solenoid&lt;br /&gt;
|so&lt;br /&gt;
|-&lt;br /&gt;
|controlbox&lt;br /&gt;
|cb&lt;br /&gt;
|-&lt;br /&gt;
|midiconfigurationhandler&lt;br /&gt;
|mcf&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;Bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; contains everything needed to interface with a single &#039;&#039;bowing wheel&#039;&#039;. Each &#039;&#039;bowing wheel&#039;&#039; has its own harmonic series, pressure actuators and direct hardware interface. It contains the following &#039;&#039;commands&#039;&#039;.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|speedmode&lt;br /&gt;
|sm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Bow motor speed mode, 0 = Automatic and 1 = Manual. Automatic mode means that the bowing wheel will automatically turn off after the &#039;&#039;motor timeout&#039;&#039; has been reached after being put into rest mode&lt;br /&gt;
|-&lt;br /&gt;
|motortimeout&lt;br /&gt;
|mt&lt;br /&gt;
|ms&lt;br /&gt;
|Bow motor shutdown timeout after bow having been put into the rest position&lt;br /&gt;
|-&lt;br /&gt;
|pidenable&lt;br /&gt;
|pe&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets the bow PID on/off&lt;br /&gt;
|-&lt;br /&gt;
|motorfaultcommands&lt;br /&gt;
|mfc&lt;br /&gt;
|commands&lt;br /&gt;
|Commands to execute when a motor fault is tripped - !WARNING! Can ruin your instrument if changed&lt;br /&gt;
|-&lt;br /&gt;
|motoroverpowercommands&lt;br /&gt;
|moc&lt;br /&gt;
|commands&lt;br /&gt;
|Commands to execute when motor is over the power limit - !WARNING! Can ruin your instrument if changed&lt;br /&gt;
|}&lt;br /&gt;
The &#039;&#039;modules&#039;&#039; in the &amp;quot;Bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; are as follows&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|bowpressure&lt;br /&gt;
|bp&lt;br /&gt;
|-&lt;br /&gt;
|dcmotor&lt;br /&gt;
|dcm&lt;br /&gt;
|-&lt;br /&gt;
|pid&lt;br /&gt;
|pid&lt;br /&gt;
|-&lt;br /&gt;
|harmonicserieshandler&lt;br /&gt;
|hsh&lt;br /&gt;
|}&lt;br /&gt;
The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; handles the &#039;&#039;pressure&#039;&#039; of the &#039;&#039;bowing wheel&#039;&#039; against the string. The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|baseline&lt;br /&gt;
|ba&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure baseline, modulation is added to this point upward. Typically this is set with a knob on the &#039;&#039;control box&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|modifier&lt;br /&gt;
|mo&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure modulation, added to the baseline&lt;br /&gt;
|-&lt;br /&gt;
|rest&lt;br /&gt;
|rs&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the bow pressure in the &#039;&#039;rest&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|engage&lt;br /&gt;
|en&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the bow pressure in the &#039;&#039;engage&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|stallpressure&lt;br /&gt;
|sp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure stall/maximum position, this parameter is set using &#039;&#039;hardware positioning&#039;&#039; and is used as the absolute maximum for baseline and modifier combiner&lt;br /&gt;
|-&lt;br /&gt;
|engagepressure&lt;br /&gt;
|ep&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure touch/minimum position, this parameter is set using &#039;&#039;hardware position&#039;&#039; and is used as the starting point for when both the baseline and modifier is set to zero&lt;br /&gt;
|-&lt;br /&gt;
|restpressure&lt;br /&gt;
|rp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure rest position, this parameter is set using &#039;&#039;hardware positioning&#039;&#039; and is typically set to a point just below the string where it does not touch at all. The purpose of this is because while the actual hardware might be able to make the bow go even lower, that position might be far enough from the string that once &#039;&#039;engaged&#039;&#039; the bow may have so far to travel that there is perceptible &#039;&#039;latency&#039;&#039;.&lt;br /&gt;
|-&lt;br /&gt;
|engagespeed&lt;br /&gt;
|es&lt;br /&gt;
|1- ~100&lt;br /&gt;
|Bow pressure movement speed when engaging or disengaging&lt;br /&gt;
|-&lt;br /&gt;
|modulationspeed&lt;br /&gt;
|ms&lt;br /&gt;
|0.1 - 10&lt;br /&gt;
|Bow pressure movement speed while engaged&lt;br /&gt;
|-&lt;br /&gt;
|hold&lt;br /&gt;
|hd&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets bow hold (infinite sustain) on/off, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|home&lt;br /&gt;
|hm&lt;br /&gt;
| -&lt;br /&gt;
|Homing bow, used at startup and in case of the bow loosing position&lt;br /&gt;
|-&lt;br /&gt;
|tmcinfo&lt;br /&gt;
|tmi&lt;br /&gt;
| -&lt;br /&gt;
|Request statistical information from the TMC2209 stepper motor driver&lt;br /&gt;
|}&lt;br /&gt;
Note that the &amp;quot;stall&amp;quot;, &amp;quot;engage&amp;quot; and &amp;quot;rest&amp;quot;-pressure positions mention something called &#039;&#039;hardware position&#039;&#039;. This means the entire available movement of the &#039;&#039;bowing jack&#039;&#039;. Because the very bottom and top end of the movement might not be musically useful and may even harm the instrument, the &amp;quot;baseline&amp;quot; and &amp;quot;modifier&amp;quot; commands &#039;&#039;parameter&#039;&#039;s are scaled depending on these settings.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;engage&amp;quot; and &amp;quot;modulation&amp;quot;-speed settings sets how fast the stepper motor that drives the &#039;&#039;pressure&#039;&#039; moves depending on whether the &#039;&#039;bowing jack&#039;&#039; is set to &#039;&#039;engage&#039;&#039; or not. The idea here is that while wanting to be able to minimize &#039;&#039;latency&#039;&#039; by &#039;&#039;engaging&#039;&#039; and &#039;&#039;disengaging&#039;&#039; from the string as quickly as possible, dynamic changes in the &#039;&#039;pressure&#039;&#039; while playing benefits from much smoother movements as the &#039;&#039;bowing wheel&#039;&#039; takes some time to catch up to varying amounts of friction.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;dcmotor&amp;quot;-&#039;&#039;module&#039;&#039; handles the direct &amp;lt;u&amp;gt;raw&amp;lt;/u&amp;gt; control of the &#039;&#039;bowing motor&#039;&#039; and handles the reporting back of the current speed. It has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|run&lt;br /&gt;
|ru&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Turns the motor off/on&lt;br /&gt;
|-&lt;br /&gt;
|pwm&lt;br /&gt;
|pw&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor direct power in 16-bit PWM values, requires that the &#039;&#039;PID&#039;&#039; is turned off&lt;br /&gt;
|-&lt;br /&gt;
|voltage&lt;br /&gt;
|vo&lt;br /&gt;
|~2 - 10V&lt;br /&gt;
|Sets the voltage of the regulator powering the motor. Changes here can make the motor more responsive to certain frequencies but will also affect how well the &#039;&#039;PID&#039;&#039; works. !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|current&lt;br /&gt;
|cu&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor reported current use&lt;br /&gt;
|-&lt;br /&gt;
|currentlimit&lt;br /&gt;
|cl&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor current limit (A)- !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|powerlimit&lt;br /&gt;
|pl&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor power limit (W) - !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|frequency&lt;br /&gt;
|fq&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor reported frequency&lt;br /&gt;
|-&lt;br /&gt;
|emergencystop&lt;br /&gt;
|es&lt;br /&gt;
|ms (0-65535)&lt;br /&gt;
|Immediately stops the bowing motor and doesn&#039;t allow it to start again until the cool down period given in the first argument has lapsed (milliseconds)&lt;br /&gt;
|-&lt;br /&gt;
|minpwm&lt;br /&gt;
|ip&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor minimum PWM (for calibration)&lt;br /&gt;
|-&lt;br /&gt;
|maxpwm&lt;br /&gt;
|xp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor maximum PWM (for calibration)&lt;br /&gt;
|}&lt;br /&gt;
The &amp;quot;pidcontroller&amp;quot;-&#039;&#039;module&#039;&#039; is responsible for keeping the &amp;quot;dcmotor&amp;quot;-&#039;&#039;module&#039;&#039; at a certain frequency (given in Hertz). It takes the output of the motor frequency measurement and feeds it a PWM value that tries to make the speed constant regardless of the friction that the motor is enduring. To learn more about PID Controllers please see this [[wikipedia:PID_controller|wikipedia article]]. The &#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|targetfrequency&lt;br /&gt;
|tf&lt;br /&gt;
|hertz&lt;br /&gt;
|Sets the PID target frequency&lt;br /&gt;
|-&lt;br /&gt;
|ki&lt;br /&gt;
|ki&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Ki parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|kp&lt;br /&gt;
|kp&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Kp parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|kd&lt;br /&gt;
|kd&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Kd parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|integratorerror&lt;br /&gt;
|ie&lt;br /&gt;
|float&lt;br /&gt;
|Sets the lower threshold of error values for the PID integrator to ignore&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|re&lt;br /&gt;
| -&lt;br /&gt;
|Resets the PID integrator and derivative&lt;br /&gt;
|-&lt;br /&gt;
|maxerror&lt;br /&gt;
|xe&lt;br /&gt;
|float&lt;br /&gt;
|Maximum error to correct in each PID loop, essentially sets acceleration&lt;br /&gt;
|-&lt;br /&gt;
|peakerror&lt;br /&gt;
|pe&lt;br /&gt;
|float&lt;br /&gt;
|Get latest PID peak error&lt;br /&gt;
|-&lt;br /&gt;
|motorspeedmax&lt;br /&gt;
|msx&lt;br /&gt;
|Hertz&lt;br /&gt;
|Bow motor maximum speed limit&lt;br /&gt;
|-&lt;br /&gt;
|motorspeedmin&lt;br /&gt;
|msi&lt;br /&gt;
|Hertz&lt;br /&gt;
|Bow motor minimum speed limit&lt;br /&gt;
|-&lt;br /&gt;
|measuretimetotarget&lt;br /&gt;
|mtt&lt;br /&gt;
|Hertz&lt;br /&gt;
|Measure the time it takes to change from the current frequency to the target frequency, for testing purposes&lt;br /&gt;
|}&lt;br /&gt;
The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; is responsible for sending frequency data to the &amp;quot;pid&amp;quot;-&#039;&#039;module&#039;&#039;. It handles calculating the correct frequency of the &#039;&#039;bowing wheel&#039;&#039; according to the selected &#039;&#039;harmonic&#039;&#039; and &#039;&#039;harmonic shift&#039;&#039; per the currently selected &#039;&#039;harmonic series&#039;&#039;. The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|fundamental&lt;br /&gt;
|fu&lt;br /&gt;
|Hertz&lt;br /&gt;
|The fundamental frequency of the string, all harmonics are calculated from this number&lt;br /&gt;
|-&lt;br /&gt;
|harmonic&lt;br /&gt;
|h&lt;br /&gt;
|int&lt;br /&gt;
|Selects the harmonic number to set the &#039;&#039;bowing wheel&#039;&#039; to. A ratio is taken from the given &#039;&#039;harmonic&#039;&#039; in the current &#039;&#039;harmonic series&#039;&#039;, the ratio is then multiplied by the &#039;&#039;fundamental frequency&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|harmonicadd&lt;br /&gt;
|ha&lt;br /&gt;
|int&lt;br /&gt;
|This number is added to the current harmonic&lt;br /&gt;
|-&lt;br /&gt;
|harmonicbase&lt;br /&gt;
|hb&lt;br /&gt;
|int&lt;br /&gt;
|Same as harmonic but where the harmonic number is based on a MIDI note given by basenote&lt;br /&gt;
|-&lt;br /&gt;
|basenote&lt;br /&gt;
|bn&lt;br /&gt;
|0-127&lt;br /&gt;
|Sets the MIDI base note of the &#039;&#039;bowing wheel&#039;&#039;, used in conjunction with &amp;quot;harmonicbase&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|shift&lt;br /&gt;
|sh&lt;br /&gt;
| -32767 - 32767&lt;br /&gt;
|Sets shift from the currently playing harmonic where 32767 equals the entire harmonic shift range shifted up&lt;br /&gt;
|-&lt;br /&gt;
|shiftrange&lt;br /&gt;
|sr&lt;br /&gt;
|0-36&lt;br /&gt;
|Set the number of harmonic numbers that constitutes an entire harmonic shift&lt;br /&gt;
|-&lt;br /&gt;
|shift5&lt;br /&gt;
|sh5&lt;br /&gt;
| -32767 - 32767&lt;br /&gt;
|Sets the shift from the currently playing harmonic over 5 octaves where 32767 equals 5 octaves shift up from the fundamental&lt;br /&gt;
|-&lt;br /&gt;
|add&lt;br /&gt;
|a&lt;br /&gt;
|(name):(ratios)&lt;br /&gt;
|Add a new series with the given name and parameters&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|series&lt;br /&gt;
|Remove the series given and shift any series accordingly. Cannot remove all series&lt;br /&gt;
|-&lt;br /&gt;
|count&lt;br /&gt;
|c&lt;br /&gt;
| -&lt;br /&gt;
|Returns the number of harmonic series in the list and their IDs&lt;br /&gt;
|}&lt;br /&gt;
The &amp;quot;harmonicserieshandler&amp;quot;-module contains at the very least ONE harmonic series, by default it contains two: one for equal temperament and one for just intonation. The current series can be selected by simply indexing the &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; without a &#039;&#039;command&#039;&#039;, e.g. &amp;quot;harmonicserieshandler.harmonicseries[1]&amp;quot;. To be consistent, these are the &#039;&#039;modules&#039;&#039; in the &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|harmonicseries&lt;br /&gt;
|hs&lt;br /&gt;
|}&lt;br /&gt;
The &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; contains any number of &#039;&#039;ratios&#039;&#039; that comprises a scale, ratios are given in a standard format where a ratio of &amp;quot;1&amp;quot; is equal to the fundamental, &amp;quot;2&amp;quot; would be one octave up etc. A standard &#039;&#039;harmonic series&#039;&#039; contains 12 ratios following a just intonation scheme. The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; will automatically adapt to the currently selected &#039;&#039;harmonic series&#039;&#039; length, whether it&#039;s a standard 12-tone scale, some kinda 3-tone scale or a full on bananas 53-tone scale. The &#039;&#039;commands&#039;&#039; of the &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; is as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|[index]&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
|Sets the currently selected &#039;&#039;harmonic Series&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Sets the name of the &#039;&#039;harmonic series&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|data&lt;br /&gt;
|da&lt;br /&gt;
|name:ratios&lt;br /&gt;
|Gets / sets all data for the &#039;&#039;harmonic series&#039;&#039; in the given slot with an arbitrary &#039;&#039;name&#039;&#039; as the first &#039;&#039;parameter&#039;&#039;. The length of the series is simply set to the amount of ratios given&lt;br /&gt;
|-&lt;br /&gt;
|ratio&lt;br /&gt;
|r&lt;br /&gt;
|harmonic:ratio&lt;br /&gt;
|Sets the ratio of the given harmonic in current &#039;&#039;harmonic series&#039;&#039;, will increase the list size if needed to address the harmonic&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|harmonic&lt;br /&gt;
|Remove the harmonic ratio given in the current series and shift any ratios accordingly. Cannot remove all ratios&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;mute&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
The &amp;quot;mute&amp;quot;-&#039;&#039;module&#039;&#039; works very similarly to the &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; in that it controls a stepper motor with some software limits in place in order to press the mute against the string. The &#039;&#039;commands&#039;&#039; are as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|setposition&lt;br /&gt;
|sp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Set mute position&lt;br /&gt;
|-&lt;br /&gt;
|fullmute&lt;br /&gt;
|fm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the mute in &#039;&#039;full mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|halfmute&lt;br /&gt;
|hm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the mute in &#039;&#039;half mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|rest&lt;br /&gt;
|rs&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Put the mute in the &#039;&#039;rest&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|savefull&lt;br /&gt;
|sf&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Save the current mute position as the &#039;&#039;full mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|savehalf&lt;br /&gt;
|sh&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Save the current mute position as the &#039;&#039;half mute&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|saverest&lt;br /&gt;
|sr&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Save the current mute position as the &#039;&#039;rest&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|fullmuteposition&lt;br /&gt;
|fmp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;full mute&#039;&#039; position according to the &#039;&#039;hardware position&#039;&#039; given&lt;br /&gt;
|-&lt;br /&gt;
|halfmuteposition&lt;br /&gt;
|hmp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;half mute&#039;&#039; position according to the &#039;&#039;hardware position&#039;&#039; given&lt;br /&gt;
|-&lt;br /&gt;
|restposition&lt;br /&gt;
|rp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;rest&#039;&#039; position according to the &#039;&#039;hardware position&#039;&#039; given&lt;br /&gt;
|-&lt;br /&gt;
|sustain&lt;br /&gt;
|su&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets the sustain off/on, this will keep the mute in the &#039;&#039;rest&#039;&#039; position even if a &amp;quot;fullmute&amp;quot;-&#039;&#039;command&#039;&#039; is given, lasts until &amp;quot;sustain&amp;quot; is set to &amp;quot;0&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
|backoff&lt;br /&gt;
|bo&lt;br /&gt;
|0-65535&lt;br /&gt;
|Setting the time that the mute stays in the mutefullmute position before automatically going into rest, set in mS. A value of &amp;quot;0&amp;quot; disables backoff. This is used because if the mute is not backing off until something is attempted to be played, the backing-off time will either introduce &#039;&#039;latency&#039;&#039; or the string will be initially partially muted&lt;br /&gt;
|-&lt;br /&gt;
|home&lt;br /&gt;
|hm&lt;br /&gt;
| -&lt;br /&gt;
|Home mute, used during initialization and if the mute were to loose position&lt;br /&gt;
|-&lt;br /&gt;
|hardwareposition&lt;br /&gt;
|hwp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Sets the &#039;&#039;hardware position&#039;&#039; of the mute instead of scaling it over the &#039;&#039;full mute&#039;&#039; and &#039;&#039;rest&#039;&#039; positions. Mainly used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|completetask&lt;br /&gt;
|cpt&lt;br /&gt;
| -&lt;br /&gt;
|Requests a callback when the current operation is finished. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|autocorrect&lt;br /&gt;
|ac&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Enables auto correct positioning that uses the homing sensor to correct positioning on the fly. EXPERIMENTAL&lt;br /&gt;
|-&lt;br /&gt;
|homingsensed&lt;br /&gt;
|hms&lt;br /&gt;
| -&lt;br /&gt;
|Requests whether the homing sensor is currently active or not. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|movedirection&lt;br /&gt;
|md&lt;br /&gt;
| -&lt;br /&gt;
|Requests the current direction of movement (0 Forward, 1 Reverse). Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|currentstep&lt;br /&gt;
|cs&lt;br /&gt;
| -&lt;br /&gt;
|Requests the current step. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|homingpoint&lt;br /&gt;
|hmp&lt;br /&gt;
|edgedirection&lt;br /&gt;
|Requests the given homing point. Only used internally by other &#039;&#039;modules&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|homingstage&lt;br /&gt;
|hms&lt;br /&gt;
| -&lt;br /&gt;
|Requests the current homing stage (UNHOMED, HOMED, FIRSTHOMINGRISING, SECONDHOMINGFALLING, SECONDHOMINGRISING, FIRSTHOMINGFALLING, MOVEPASTHOMESWITCH, MOVETOHOMESWITCH, GOTOOFFSET). Only used internally by other &#039;&#039;modules.&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|tmcinfo&lt;br /&gt;
|tmi&lt;br /&gt;
| -&lt;br /&gt;
|Request statistical information from the TMC2209 stepper motor driver&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Knaadmin</name></author>
	</entry>
	<entry>
		<id>http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_reference_V1.1&amp;diff=1676</id>
		<title>The Ekdahl FAR - Command reference V1.1</title>
		<link rel="alternate" type="text/html" href="http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_reference_V1.1&amp;diff=1676"/>
		<updated>2026-06-12T14:34:15Z</updated>

		<summary type="html">&lt;p&gt;Knaadmin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
The Ekdahl FAR V1.1 introduces the concept of &#039;&#039;modules&#039;&#039;. A &#039;&#039;module&#039;&#039; can contain any number of &#039;&#039;commands&#039;&#039; as well as other &#039;&#039;modules&#039;&#039;. Furthermore any number of &#039;&#039;modules&#039;&#039; of the same type can exist within a context, these are addressed using classic C-style array &#039;&#039;indexing&#039;&#039; with the help of brackets (&amp;quot;[ ]&amp;quot;). Extending on the classic usage, multiple &#039;&#039;indexes&#039;&#039; can be addressed simultaneously by either comma-separating the objects (&amp;quot;[0,3,4]&amp;quot;) and using &#039;&#039;ranges&#039;&#039; (&amp;quot;[3-6]&amp;quot;). &#039;&#039;Modules&#039;&#039; can be either &#039;&#039;internal&#039;&#039; or &#039;&#039;external&#039;&#039;, meaning that they may all physically exist within a single hardware object, or they can be be remote-controlled devices. From a user perspective this however makes no difference as they will appear the same.&lt;br /&gt;
&lt;br /&gt;
While all &#039;&#039;modules&#039;&#039; have their own set of &#039;&#039;commands&#039;&#039;, there are certain &#039;&#039;commands&#039;&#039; that all &#039;&#039;modules&#039;&#039; &amp;lt;u&amp;gt;must&amp;lt;/u&amp;gt; implement and can thus be accessed anywhere within the &#039;&#039;module hierarchy.&#039;&#039; There are also &#039;&#039;base commands&#039;&#039; that always exist within any given FAR ecosystem as well as product-specific &#039;&#039;base commands&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Basic commands ==&lt;br /&gt;
The &#039;&#039;module commands&#039;&#039; that are &amp;lt;u&amp;gt;required&amp;lt;/u&amp;gt; to be implemented in &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; &#039;&#039;modules&#039;&#039; and that can thus be accessed from anywhere are&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|list&lt;br /&gt;
|ls&lt;br /&gt;
|hidden/h:modules/m:commands/c:instances/i:instancecounts/ic:recursive/r&lt;br /&gt;
|Lists all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039; under the current module depending on the parameters given; &#039;hidden&#039; includes normally hidden &#039;&#039;commands&#039;&#039;, &#039;modules&#039; includes any &#039;&#039;submodules&#039;&#039;, &#039;commands&#039; shows &#039;&#039;commands&#039;&#039;, &#039;instances&#039; shows data for each individual instance of a &#039;&#039;module&#039;&#039;, &#039;instancecounts&#039; includes number of instances of each &#039;&#039;module&#039;&#039;, &#039;recursive&#039; lists all child &#039;&#039;modules&#039;&#039; / &#039;&#039;commands&#039;&#039;. No parameters defaults to showing all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039; recursively with instance counts. It doesn&#039;t show per-instance data or hidden commands.&lt;br /&gt;
|-&lt;br /&gt;
|help&lt;br /&gt;
|help&lt;br /&gt;
|recursive/r&lt;br /&gt;
|Shows a brief explanation of all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039;, shows the help for all &#039;&#039;submodules&#039;&#039; as well if &#039;recursive&#039;&lt;br /&gt;
|-&lt;br /&gt;
|dumpdata&lt;br /&gt;
|dump&lt;br /&gt;
|recursive/r&lt;br /&gt;
|Dumps all data saved for the current &#039;&#039;module&#039;&#039;, will list the data of all &#039;&#039;submodules&#039;&#039; as well if &#039;recursive&#039;&lt;br /&gt;
|}&lt;br /&gt;
The &#039;&#039;base commands&#039;&#039; are as follows&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|version&lt;br /&gt;
|ver&lt;br /&gt;
| -&lt;br /&gt;
|Gets the current firmware version&lt;br /&gt;
|-&lt;br /&gt;
|debugprint&lt;br /&gt;
|dp&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;command|usb|hardware|undefined|priority|error|inforequest|expressionparser|debug:1|0&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Turns on or off serial feedback for the given item&lt;br /&gt;
|-&lt;br /&gt;
|requestinfo&lt;br /&gt;
|rqi&lt;br /&gt;
|command&lt;br /&gt;
|Retrives any data saved for a &#039;&#039;command&#039;&#039;, if applicable&lt;br /&gt;
|-&lt;br /&gt;
|saveallparameters&lt;br /&gt;
|sap&lt;br /&gt;
| -&lt;br /&gt;
|Saves all avaliable parameters&lt;br /&gt;
|-&lt;br /&gt;
|loadallparameters&lt;br /&gt;
|lap&lt;br /&gt;
| -&lt;br /&gt;
|Loads all avaliable parameters&lt;br /&gt;
|-&lt;br /&gt;
|resetallparameters&lt;br /&gt;
|rap&lt;br /&gt;
| -&lt;br /&gt;
|Resets all saved parameters&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|rst&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;1|0&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Resets the Ekdahl FAR, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|nick&lt;br /&gt;
|nick&lt;br /&gt;
|name&lt;br /&gt;
|Sets the nickname of this unit&lt;br /&gt;
|-&lt;br /&gt;
|nooperation&lt;br /&gt;
|nop&lt;br /&gt;
| -&lt;br /&gt;
|Do absolutely, positively, nothing. Useful for testing and interfacing with computers, it&#039;s a good way to know that the unit is alive and responding since a &amp;quot;nop&amp;quot; is being returned as a response upon reception.&lt;br /&gt;
|-&lt;br /&gt;
|uservariable&lt;br /&gt;
|uv&lt;br /&gt;
|variable(0-9):value&lt;br /&gt;
|Set user variable 0-9 to &#039;value&#039;&lt;br /&gt;
|-&lt;br /&gt;
|expressionparserevaluate&lt;br /&gt;
|epev&lt;br /&gt;
|expression&lt;br /&gt;
|Evaluates an arithmetric expression and sends back the output, all variables and functions that can be used in any &#039;&#039;command string&#039;&#039; can also be used here. Useful for testing expressions.&lt;br /&gt;
|-&lt;br /&gt;
|ifequal&lt;br /&gt;
|ife&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] EQUALS [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring].&lt;br /&gt;
|-&lt;br /&gt;
|ifgreater&lt;br /&gt;
|ifg&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] &amp;gt; [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring]&lt;br /&gt;
|-&lt;br /&gt;
|ifless&lt;br /&gt;
|ifl&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] &amp;lt; [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring]&lt;br /&gt;
|-&lt;br /&gt;
|freeram&lt;br /&gt;
|ram&lt;br /&gt;
| -&lt;br /&gt;
|Shows free RAM memory&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The base also contains the following &#039;&#039;modules:&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|pluginhandler&lt;br /&gt;
|ph&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The Ekdahl FAR stand alone single string unit ==&lt;br /&gt;
The Ekdahl FAR stand-alone single string unit offers these &#039;&#039;commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|calibrateall&lt;br /&gt;
|ca&lt;br /&gt;
| -&lt;br /&gt;
|Performs all calibration routines on the selected bow, see below for routines performed&lt;br /&gt;
|-&lt;br /&gt;
|calibratebowspeed&lt;br /&gt;
|cbs&lt;br /&gt;
| -&lt;br /&gt;
|Finds the minimum and maximum bow speed of the selected bow&lt;br /&gt;
|-&lt;br /&gt;
|calibratebowpressure&lt;br /&gt;
|cbp&lt;br /&gt;
| -&lt;br /&gt;
|Finds the minimum and maximum bow pressure of the selected bow&lt;br /&gt;
|-&lt;br /&gt;
|calibratemute&lt;br /&gt;
|cmu&lt;br /&gt;
| -&lt;br /&gt;
|Calibrate mute settings&lt;br /&gt;
|-&lt;br /&gt;
|pickupstringfrequency&lt;br /&gt;
|psf&lt;br /&gt;
| -&lt;br /&gt;
|Returns the fundamental tone calculated from the current audio signal if apliccable&lt;br /&gt;
|-&lt;br /&gt;
|pickupaudiopeak&lt;br /&gt;
|pap&lt;br /&gt;
| -&lt;br /&gt;
|Returns the peak amplitude of the current audio signal&lt;br /&gt;
|-&lt;br /&gt;
|pickupaudiorms&lt;br /&gt;
|par&lt;br /&gt;
| -&lt;br /&gt;
|Returns the RMS amplitude of the current audio signal&lt;br /&gt;
|}&lt;br /&gt;
The Ekdahl FAR also contains the following &#039;&#039;modules&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|bowingwheel&lt;br /&gt;
|bw&lt;br /&gt;
|-&lt;br /&gt;
|mute&lt;br /&gt;
|mu&lt;br /&gt;
|-&lt;br /&gt;
|solenoid&lt;br /&gt;
|so&lt;br /&gt;
|-&lt;br /&gt;
|controlbox&lt;br /&gt;
|cb&lt;br /&gt;
|-&lt;br /&gt;
|midiconfigurationhandler&lt;br /&gt;
|mcf&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;Bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; contains everything needed to interface with a single &#039;&#039;bowing wheel&#039;&#039;. Each &#039;&#039;bowing wheel&#039;&#039; has its own harmonic series, pressure actuators and direct hardware interface. It contains the following &#039;&#039;commands&#039;&#039;.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|speedmode&lt;br /&gt;
|sm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Bow motor speed mode, 0 = Automatic and 1 = Manual. Automatic mode means that the bowing wheel will automatically turn off after the &#039;&#039;motor timeout&#039;&#039; has been reached after being put into rest mode&lt;br /&gt;
|-&lt;br /&gt;
|motortimeout&lt;br /&gt;
|mt&lt;br /&gt;
|ms&lt;br /&gt;
|Bow motor shutdown timeout after bow having been put into the rest position&lt;br /&gt;
|-&lt;br /&gt;
|pidenable&lt;br /&gt;
|pe&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets the bow PID on/off&lt;br /&gt;
|-&lt;br /&gt;
|motorfaultcommands&lt;br /&gt;
|mfc&lt;br /&gt;
|commands&lt;br /&gt;
|Commands to execute when a motor fault is tripped - !WARNING! Can ruin your instrument if changed&lt;br /&gt;
|-&lt;br /&gt;
|motoroverpowercommands&lt;br /&gt;
|moc&lt;br /&gt;
|commands&lt;br /&gt;
|Commands to execute when motor is over the power limit - !WARNING! Can ruin your instrument if changed&lt;br /&gt;
|}&lt;br /&gt;
The &#039;&#039;modules&#039;&#039; in the &amp;quot;Bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; are as follows&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|bowpressure&lt;br /&gt;
|bp&lt;br /&gt;
|-&lt;br /&gt;
|dcmotor&lt;br /&gt;
|dcm&lt;br /&gt;
|-&lt;br /&gt;
|pid&lt;br /&gt;
|pid&lt;br /&gt;
|-&lt;br /&gt;
|harmonicserieshandler&lt;br /&gt;
|hsh&lt;br /&gt;
|}&lt;br /&gt;
The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; handles the &#039;&#039;pressure&#039;&#039; of the &#039;&#039;bowing wheel&#039;&#039; against the string. The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|baseline&lt;br /&gt;
|ba&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure baseline, modulation is added to this point upward. Typically this is set with a knob on the &#039;&#039;control box&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|modifier&lt;br /&gt;
|mo&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure modulation, added to the baseline&lt;br /&gt;
|-&lt;br /&gt;
|rest&lt;br /&gt;
|rs&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the bow pressure in the &#039;&#039;rest&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|engage&lt;br /&gt;
|en&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the bow pressure in the &#039;&#039;engage&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|stallpressure&lt;br /&gt;
|sp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure stall/maximum position, this parameter is set using &#039;&#039;hardware positioning&#039;&#039; and is used as the absolute maximum for baseline and modifier combiner&lt;br /&gt;
|-&lt;br /&gt;
|engagepressure&lt;br /&gt;
|ep&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure touch/minimum position, this parameter is set using &#039;&#039;hardware position&#039;&#039; and is used as the starting point for when both the baseline and modifier is set to zero&lt;br /&gt;
|-&lt;br /&gt;
|restpressure&lt;br /&gt;
|rp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure rest position, this parameter is set using &#039;&#039;hardware positioning&#039;&#039; and is typically set to a point just below the string where it does not touch at all. The purpose of this is because while the actual hardware might be able to make the bow go even lower, that position might be far enough from the string that once &#039;&#039;engaged&#039;&#039; the bow may have so far to travel that there is perceptible &#039;&#039;latency&#039;&#039;.&lt;br /&gt;
|-&lt;br /&gt;
|engagespeed&lt;br /&gt;
|es&lt;br /&gt;
|1- ~100&lt;br /&gt;
|Bow pressure movement speed when engaging or disengaging&lt;br /&gt;
|-&lt;br /&gt;
|modulationspeed&lt;br /&gt;
|ms&lt;br /&gt;
|0.1 - 10&lt;br /&gt;
|Bow pressure movement speed while engaged&lt;br /&gt;
|-&lt;br /&gt;
|hold&lt;br /&gt;
|hd&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets bow hold (infinite sustain) on/off, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|home&lt;br /&gt;
|hm&lt;br /&gt;
| -&lt;br /&gt;
|Homing bow, used at startup and in case of the bow loosing position&lt;br /&gt;
|-&lt;br /&gt;
|tmcinfo&lt;br /&gt;
|tmi&lt;br /&gt;
| -&lt;br /&gt;
|Request statistical information from the TMC2209 stepper motor driver&lt;br /&gt;
|}&lt;br /&gt;
Note that the &amp;quot;stall&amp;quot;, &amp;quot;engage&amp;quot; and &amp;quot;rest&amp;quot;-pressure positions mention something called &#039;&#039;hardware position&#039;&#039;. This means the entire available movement of the &#039;&#039;bowing jack&#039;&#039;. Because the very bottom and top end of the movement might not be musically useful and may even harm the instrument, the &amp;quot;baseline&amp;quot; and &amp;quot;modifier&amp;quot; commands &#039;&#039;parameter&#039;&#039;s are scaled depending on these settings.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;engage&amp;quot; and &amp;quot;modulation&amp;quot;-speed settings sets how fast the stepper motor that drives the &#039;&#039;pressure&#039;&#039; moves depending on whether the &#039;&#039;bowing jack&#039;&#039; is set to &#039;&#039;engage&#039;&#039; or not. The idea here is that while wanting to be able to minimize &#039;&#039;latency&#039;&#039; by &#039;&#039;engaging&#039;&#039; and &#039;&#039;disengaging&#039;&#039; from the string as quickly as possible, dynamic changes in the &#039;&#039;pressure&#039;&#039; while playing benefits from much smoother movements as the &#039;&#039;bowing wheel&#039;&#039; takes some time to catch up to varying amounts of friction.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;dcmotor&amp;quot;-&#039;&#039;module&#039;&#039; handles the direct &amp;lt;u&amp;gt;raw&amp;lt;/u&amp;gt; control of the &#039;&#039;bowing motor&#039;&#039; and handles the reporting back of the current speed. It has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|run&lt;br /&gt;
|ru&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Turns the motor off/on&lt;br /&gt;
|-&lt;br /&gt;
|pwm&lt;br /&gt;
|pw&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor direct power in 16-bit PWM values, requires that the &#039;&#039;PID&#039;&#039; is turned off&lt;br /&gt;
|-&lt;br /&gt;
|voltage&lt;br /&gt;
|vo&lt;br /&gt;
|~2 - 10V&lt;br /&gt;
|Sets the voltage of the regulator powering the motor. Changes here can make the motor more responsive to certain frequencies but will also affect how well the &#039;&#039;PID&#039;&#039; works. !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|current&lt;br /&gt;
|cu&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor reported current use&lt;br /&gt;
|-&lt;br /&gt;
|currentlimit&lt;br /&gt;
|cl&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor current limit (A)- !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|powerlimit&lt;br /&gt;
|pl&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor power limit (W) - !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|frequency&lt;br /&gt;
|fq&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor reported frequency&lt;br /&gt;
|-&lt;br /&gt;
|emergencystop&lt;br /&gt;
|es&lt;br /&gt;
|ms (0-65535)&lt;br /&gt;
|Immediately stops the bowing motor and doesn&#039;t allow it to start again until the cool down period given in the first argument has lapsed (milliseconds)&lt;br /&gt;
|-&lt;br /&gt;
|minpwm&lt;br /&gt;
|ip&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor minimum PWM (for calibration)&lt;br /&gt;
|-&lt;br /&gt;
|maxpwm&lt;br /&gt;
|xp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor maximum PWM (for calibration)&lt;br /&gt;
|}&lt;br /&gt;
The &amp;quot;pidcontroller&amp;quot;-&#039;&#039;module&#039;&#039; is responsible for keeping the &amp;quot;dcmotor&amp;quot;-&#039;&#039;module&#039;&#039; at a certain frequency (given in Hertz). It takes the output of the motor frequency measurement and feeds it a PWM value that tries to make the speed constant regardless of the friction that the motor is enduring. To learn more about PID Controllers please see this [[wikipedia:PID_controller|wikipedia article]]. The &#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|targetfrequency&lt;br /&gt;
|tf&lt;br /&gt;
|hertz&lt;br /&gt;
|Sets the PID target frequency&lt;br /&gt;
|-&lt;br /&gt;
|ki&lt;br /&gt;
|ki&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Ki parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|kp&lt;br /&gt;
|kp&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Kp parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|kd&lt;br /&gt;
|kd&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Kd parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|integratorerror&lt;br /&gt;
|ie&lt;br /&gt;
|float&lt;br /&gt;
|Sets the lower threshold of error values for the PID integrator to ignore&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|re&lt;br /&gt;
| -&lt;br /&gt;
|Resets the PID integrator and derivative&lt;br /&gt;
|-&lt;br /&gt;
|maxerror&lt;br /&gt;
|xe&lt;br /&gt;
|float&lt;br /&gt;
|Maximum error to correct in each PID loop, essentially sets acceleration&lt;br /&gt;
|-&lt;br /&gt;
|peakerror&lt;br /&gt;
|pe&lt;br /&gt;
|float&lt;br /&gt;
|Get latest PID peak error&lt;br /&gt;
|-&lt;br /&gt;
|motorspeedmax&lt;br /&gt;
|msx&lt;br /&gt;
|Hertz&lt;br /&gt;
|Bow motor maximum speed limit&lt;br /&gt;
|-&lt;br /&gt;
|motorspeedmin&lt;br /&gt;
|msi&lt;br /&gt;
|Hertz&lt;br /&gt;
|Bow motor minimum speed limit&lt;br /&gt;
|-&lt;br /&gt;
|measuretimetotarget&lt;br /&gt;
|mtt&lt;br /&gt;
|Hertz&lt;br /&gt;
|Measure the time it takes to change from the current frequency to the target frequency, for testing purposes&lt;br /&gt;
|}&lt;br /&gt;
The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; is responsible for sending frequency data to the &amp;quot;pid&amp;quot;-&#039;&#039;module&#039;&#039;. It handles calculating the correct frequency of the &#039;&#039;bowing wheel&#039;&#039; according to the selected &#039;&#039;harmonic&#039;&#039; and &#039;&#039;harmonic shift&#039;&#039; per the currently selected &#039;&#039;harmonic series&#039;&#039;. The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|fundamental&lt;br /&gt;
|fu&lt;br /&gt;
|Hertz&lt;br /&gt;
|The fundamental frequency of the string, all harmonics are calculated from this number&lt;br /&gt;
|-&lt;br /&gt;
|harmonic&lt;br /&gt;
|h&lt;br /&gt;
|int&lt;br /&gt;
|Selects the harmonic number to set the &#039;&#039;bowing wheel&#039;&#039; to. A ratio is taken from the given &#039;&#039;harmonic&#039;&#039; in the current &#039;&#039;harmonic series&#039;&#039;, the ratio is then multiplied by the &#039;&#039;fundamental frequency&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|harmonicadd&lt;br /&gt;
|ha&lt;br /&gt;
|int&lt;br /&gt;
|This number is added to the current harmonic&lt;br /&gt;
|-&lt;br /&gt;
|harmonicbase&lt;br /&gt;
|hb&lt;br /&gt;
|int&lt;br /&gt;
|Same as harmonic but where the harmonic number is based on a MIDI note given by basenote&lt;br /&gt;
|-&lt;br /&gt;
|basenote&lt;br /&gt;
|bn&lt;br /&gt;
|0-127&lt;br /&gt;
|Sets the MIDI base note of the &#039;&#039;bowing wheel&#039;&#039;, used in conjunction with &amp;quot;harmonicbase&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|shift&lt;br /&gt;
|sh&lt;br /&gt;
| -32767 - 32767&lt;br /&gt;
|Sets shift from the currently playing harmonic where 32767 equals the entire harmonic shift range shifted up&lt;br /&gt;
|-&lt;br /&gt;
|shiftrange&lt;br /&gt;
|sr&lt;br /&gt;
|0-36&lt;br /&gt;
|Set the number of harmonic numbers that constitutes an entire harmonic shift&lt;br /&gt;
|-&lt;br /&gt;
|shift5&lt;br /&gt;
|sh5&lt;br /&gt;
| -32767 - 32767&lt;br /&gt;
|Sets the shift from the currently playing harmonic over 5 octaves where 32767 equals 5 octaves shift up from the fundamental&lt;br /&gt;
|-&lt;br /&gt;
|add&lt;br /&gt;
|a&lt;br /&gt;
|(name):(ratios)&lt;br /&gt;
|Add a new series with the given name and parameters&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|series&lt;br /&gt;
|Remove the series given and shift any series accordingly. Cannot remove all series&lt;br /&gt;
|-&lt;br /&gt;
|count&lt;br /&gt;
|c&lt;br /&gt;
| -&lt;br /&gt;
|Returns the number of harmonic series in the list and their IDs&lt;br /&gt;
|}&lt;br /&gt;
The &amp;quot;harmonicserieshandler&amp;quot;-module contains at the very least ONE harmonic series, by default it contains two: one for equal temperament and one for just intonation. The current series can be selected by simply indexing the &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; without a &#039;&#039;command&#039;&#039;, e.g. &amp;quot;harmonicserieshandler.harmonicseries[1]&amp;quot;. To be consistent, these are the &#039;&#039;modules&#039;&#039; in the &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|harmonicseries&lt;br /&gt;
|hs&lt;br /&gt;
|}&lt;br /&gt;
The &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; contains any number of &#039;&#039;ratios&#039;&#039; that comprises a scale, ratios are given in a standard format where a ratio of &amp;quot;1&amp;quot; is equal to the fundamental, &amp;quot;2&amp;quot; would be one octave up etc. A standard &#039;&#039;harmonic series&#039;&#039; contains 12 ratios following a just intonation scheme. The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; will automatically adapt to the currently selected &#039;&#039;harmonic series&#039;&#039; length, whether it&#039;s a standard 12-tone scale, some kinda 3-tone scale or a full on bananas 53-tone scale. The &#039;&#039;commands&#039;&#039; of the &amp;quot;harmonicseries&amp;quot;-&#039;&#039;module&#039;&#039; is as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|[index]&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
|Sets the currently selected &#039;&#039;harmonic Series&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|na&lt;br /&gt;
|string&lt;br /&gt;
|Sets the name of the &#039;&#039;harmonic series&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|data&lt;br /&gt;
|da&lt;br /&gt;
|name:ratios&lt;br /&gt;
|Gets / sets all data for the &#039;&#039;harmonic series&#039;&#039; in the given slot with an arbitrary &#039;&#039;name&#039;&#039; as the first &#039;&#039;parameter&#039;&#039;. The length of the series is simply set to the amount of ratios given&lt;br /&gt;
|-&lt;br /&gt;
|ratio&lt;br /&gt;
|r&lt;br /&gt;
|harmonic:ratio&lt;br /&gt;
|Sets the ratio of the given harmonic in current &#039;&#039;harmonic series&#039;&#039;, will increase the list size if needed to address the harmonic&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|harmonic&lt;br /&gt;
|Remove the harmonic ratio given in the current series and shift any ratios accordingly. Cannot remove all ratios&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;mute&amp;quot;-&#039;&#039;module&#039;&#039; ==&lt;br /&gt;
asdf&lt;/div&gt;</summary>
		<author><name>Knaadmin</name></author>
	</entry>
	<entry>
		<id>http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_reference_V1.1&amp;diff=1675</id>
		<title>The Ekdahl FAR - Command reference V1.1</title>
		<link rel="alternate" type="text/html" href="http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_reference_V1.1&amp;diff=1675"/>
		<updated>2026-06-12T14:15:51Z</updated>

		<summary type="html">&lt;p&gt;Knaadmin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
The Ekdahl FAR V1.1 introduces the concept of &#039;&#039;modules&#039;&#039;. A &#039;&#039;module&#039;&#039; can contain any number of &#039;&#039;commands&#039;&#039; as well as other &#039;&#039;modules&#039;&#039;. Furthermore any number of &#039;&#039;modules&#039;&#039; of the same type can exist within a context, these are addressed using classic C-style array &#039;&#039;indexing&#039;&#039; with the help of brackets (&amp;quot;[ ]&amp;quot;). Extending on the classic usage, multiple &#039;&#039;indexes&#039;&#039; can be addressed simultaneously by either comma-separating the objects (&amp;quot;[0,3,4]&amp;quot;) and using &#039;&#039;ranges&#039;&#039; (&amp;quot;[3-6]&amp;quot;). &#039;&#039;Modules&#039;&#039; can be either &#039;&#039;internal&#039;&#039; or &#039;&#039;external&#039;&#039;, meaning that they may all physically exist within a single hardware object, or they can be be remote-controlled devices. From a user perspective this however makes no difference as they will appear the same.&lt;br /&gt;
&lt;br /&gt;
While all &#039;&#039;modules&#039;&#039; have their own set of &#039;&#039;commands&#039;&#039;, there are certain &#039;&#039;commands&#039;&#039; that all &#039;&#039;modules&#039;&#039; &amp;lt;u&amp;gt;must&amp;lt;/u&amp;gt; implement and can thus be accessed anywhere within the &#039;&#039;module hierarchy.&#039;&#039; There are also &#039;&#039;base commands&#039;&#039; that always exist within any given FAR ecosystem as well as product-specific &#039;&#039;base commands&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Basic commands ==&lt;br /&gt;
The &#039;&#039;module commands&#039;&#039; that are &amp;lt;u&amp;gt;required&amp;lt;/u&amp;gt; to be implemented in &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; &#039;&#039;modules&#039;&#039; and that can thus be accessed from anywhere are&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|list&lt;br /&gt;
|ls&lt;br /&gt;
|hidden/h:modules/m:commands/c:instances/i:instancecounts/ic:recursive/r&lt;br /&gt;
|Lists all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039; under the current module depending on the parameters given; &#039;hidden&#039; includes normally hidden &#039;&#039;commands&#039;&#039;, &#039;modules&#039; includes any &#039;&#039;submodules&#039;&#039;, &#039;commands&#039; shows &#039;&#039;commands&#039;&#039;, &#039;instances&#039; shows data for each individual instance of a &#039;&#039;module&#039;&#039;, &#039;instancecounts&#039; includes number of instances of each &#039;&#039;module&#039;&#039;, &#039;recursive&#039; lists all child &#039;&#039;modules&#039;&#039; / &#039;&#039;commands&#039;&#039;. No parameters defaults to showing all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039; recursively with instance counts. It doesn&#039;t show per-instance data or hidden commands.&lt;br /&gt;
|-&lt;br /&gt;
|help&lt;br /&gt;
|help&lt;br /&gt;
|recursive/r&lt;br /&gt;
|Shows a brief explanation of all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039;, shows the help for all &#039;&#039;submodules&#039;&#039; as well if &#039;recursive&#039;&lt;br /&gt;
|-&lt;br /&gt;
|dumpdata&lt;br /&gt;
|dump&lt;br /&gt;
|recursive/r&lt;br /&gt;
|Dumps all data saved for the current &#039;&#039;module&#039;&#039;, will list the data of all &#039;&#039;submodules&#039;&#039; as well if &#039;recursive&#039;&lt;br /&gt;
|}&lt;br /&gt;
The &#039;&#039;base commands&#039;&#039; are as follows&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|version&lt;br /&gt;
|ver&lt;br /&gt;
| -&lt;br /&gt;
|Gets the current firmware version&lt;br /&gt;
|-&lt;br /&gt;
|debugprint&lt;br /&gt;
|dp&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;command|usb|hardware|undefined|priority|error|inforequest|expressionparser|debug:1|0&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Turns on or off serial feedback for the given item&lt;br /&gt;
|-&lt;br /&gt;
|requestinfo&lt;br /&gt;
|rqi&lt;br /&gt;
|command&lt;br /&gt;
|Retrives any data saved for a &#039;&#039;command&#039;&#039;, if applicable&lt;br /&gt;
|-&lt;br /&gt;
|saveallparameters&lt;br /&gt;
|sap&lt;br /&gt;
| -&lt;br /&gt;
|Saves all avaliable parameters&lt;br /&gt;
|-&lt;br /&gt;
|loadallparameters&lt;br /&gt;
|lap&lt;br /&gt;
| -&lt;br /&gt;
|Loads all avaliable parameters&lt;br /&gt;
|-&lt;br /&gt;
|resetallparameters&lt;br /&gt;
|rap&lt;br /&gt;
| -&lt;br /&gt;
|Resets all saved parameters&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|rst&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;1|0&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Resets the Ekdahl FAR, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|nick&lt;br /&gt;
|nick&lt;br /&gt;
|name&lt;br /&gt;
|Sets the nickname of this unit&lt;br /&gt;
|-&lt;br /&gt;
|nooperation&lt;br /&gt;
|nop&lt;br /&gt;
| -&lt;br /&gt;
|Do absolutely, positively, nothing. Useful for testing and interfacing with computers, it&#039;s a good way to know that the unit is alive and responding since a &amp;quot;nop&amp;quot; is being returned as a response upon reception.&lt;br /&gt;
|-&lt;br /&gt;
|uservariable&lt;br /&gt;
|uv&lt;br /&gt;
|variable(0-9):value&lt;br /&gt;
|Set user variable 0-9 to &#039;value&#039;&lt;br /&gt;
|-&lt;br /&gt;
|expressionparserevaluate&lt;br /&gt;
|epev&lt;br /&gt;
|expression&lt;br /&gt;
|Evaluates an arithmetric expression and sends back the output, all variables and functions that can be used in any &#039;&#039;command string&#039;&#039; can also be used here. Useful for testing expressions.&lt;br /&gt;
|-&lt;br /&gt;
|ifequal&lt;br /&gt;
|ife&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] EQUALS [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring].&lt;br /&gt;
|-&lt;br /&gt;
|ifgreater&lt;br /&gt;
|ifg&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] &amp;gt; [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring]&lt;br /&gt;
|-&lt;br /&gt;
|ifless&lt;br /&gt;
|ifl&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] &amp;lt; [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring]&lt;br /&gt;
|-&lt;br /&gt;
|freeram&lt;br /&gt;
|ram&lt;br /&gt;
| -&lt;br /&gt;
|Shows free RAM memory&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The base also contains the following &#039;&#039;modules:&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|pluginhandler&lt;br /&gt;
|ph&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The Ekdahl FAR stand alone single string unit ==&lt;br /&gt;
The Ekdahl FAR stand-alone single string unit offers these &#039;&#039;commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|calibrateall&lt;br /&gt;
|ca&lt;br /&gt;
| -&lt;br /&gt;
|Performs all calibration routines on the selected bow, see below for routines performed&lt;br /&gt;
|-&lt;br /&gt;
|calibratebowspeed&lt;br /&gt;
|cbs&lt;br /&gt;
| -&lt;br /&gt;
|Finds the minimum and maximum bow speed of the selected bow&lt;br /&gt;
|-&lt;br /&gt;
|calibratebowpressure&lt;br /&gt;
|cbp&lt;br /&gt;
| -&lt;br /&gt;
|Finds the minimum and maximum bow pressure of the selected bow&lt;br /&gt;
|-&lt;br /&gt;
|calibratemute&lt;br /&gt;
|cmu&lt;br /&gt;
| -&lt;br /&gt;
|Calibrate mute settings&lt;br /&gt;
|-&lt;br /&gt;
|pickupstringfrequency&lt;br /&gt;
|psf&lt;br /&gt;
| -&lt;br /&gt;
|Returns the fundamental tone calculated from the current audio signal if apliccable&lt;br /&gt;
|-&lt;br /&gt;
|pickupaudiopeak&lt;br /&gt;
|pap&lt;br /&gt;
| -&lt;br /&gt;
|Returns the peak amplitude of the current audio signal&lt;br /&gt;
|-&lt;br /&gt;
|pickupaudiorms&lt;br /&gt;
|par&lt;br /&gt;
| -&lt;br /&gt;
|Returns the RMS amplitude of the current audio signal&lt;br /&gt;
|}&lt;br /&gt;
The Ekdahl FAR also contains the following &#039;&#039;modules&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|bowingwheel&lt;br /&gt;
|bw&lt;br /&gt;
|-&lt;br /&gt;
|mute&lt;br /&gt;
|mu&lt;br /&gt;
|-&lt;br /&gt;
|solenoid&lt;br /&gt;
|so&lt;br /&gt;
|-&lt;br /&gt;
|controlbox&lt;br /&gt;
|cb&lt;br /&gt;
|-&lt;br /&gt;
|midiconfigurationhandler&lt;br /&gt;
|mcf&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;bowingwheel&amp;quot; module ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;Bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; contains everything needed to interface with a single &#039;&#039;bowing wheel&#039;&#039;. Each &#039;&#039;bowing wheel&#039;&#039; has its own harmonic series, pressure actuators and direct hardware interface. It contains the following &#039;&#039;commands&#039;&#039;.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|speedmode&lt;br /&gt;
|sm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Bow motor speed mode, 0 = Automatic and 1 = Manual. Automatic mode means that the bowing wheel will automatically turn off after the &#039;&#039;motor timeout&#039;&#039; has been reached after being put into rest mode&lt;br /&gt;
|-&lt;br /&gt;
|motortimeout&lt;br /&gt;
|mt&lt;br /&gt;
|ms&lt;br /&gt;
|Bow motor shutdown timeout after bow having been put into the rest position&lt;br /&gt;
|-&lt;br /&gt;
|pidenable&lt;br /&gt;
|pe&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets the bow PID on/off&lt;br /&gt;
|-&lt;br /&gt;
|motorfaultcommands&lt;br /&gt;
|mfc&lt;br /&gt;
|commands&lt;br /&gt;
|Commands to execute when a motor fault is tripped - !WARNING! Can ruin your instrument if changed&lt;br /&gt;
|-&lt;br /&gt;
|motoroverpowercommands&lt;br /&gt;
|moc&lt;br /&gt;
|commands&lt;br /&gt;
|Commands to execute when motor is over the power limit - !WARNING! Can ruin your instrument if changed&lt;br /&gt;
|}&lt;br /&gt;
The &#039;&#039;modules&#039;&#039; in the &amp;quot;Bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; are as follows&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|bowpressure&lt;br /&gt;
|bp&lt;br /&gt;
|-&lt;br /&gt;
|dcmotor&lt;br /&gt;
|dcm&lt;br /&gt;
|-&lt;br /&gt;
|pid&lt;br /&gt;
|pid&lt;br /&gt;
|-&lt;br /&gt;
|harmonicserieshandler&lt;br /&gt;
|hsh&lt;br /&gt;
|}&lt;br /&gt;
The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; handles the &#039;&#039;pressure&#039;&#039; of the &#039;&#039;bowing wheel&#039;&#039; against the string. The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|baseline&lt;br /&gt;
|ba&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure baseline, modulation is added to this point upward. Typically this is set with a knob on the &#039;&#039;control box&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|modifier&lt;br /&gt;
|mo&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure modulation, added to the baseline&lt;br /&gt;
|-&lt;br /&gt;
|rest&lt;br /&gt;
|rs&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the bow pressure in the &#039;&#039;rest&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|engage&lt;br /&gt;
|en&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the bow pressure in the &#039;&#039;engage&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|stallpressure&lt;br /&gt;
|sp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure stall/maximum position, this parameter is set using &#039;&#039;hardware positioning&#039;&#039; and is used as the absolute maximum for baseline and modifier combiner&lt;br /&gt;
|-&lt;br /&gt;
|engagepressure&lt;br /&gt;
|ep&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure touch/minimum position, this parameter is set using &#039;&#039;hardware position&#039;&#039; and is used as the starting point for when both the baseline and modifier is set to zero&lt;br /&gt;
|-&lt;br /&gt;
|restpressure&lt;br /&gt;
|rp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure rest position, this parameter is set using &#039;&#039;hardware positioning&#039;&#039; and is typically set to a point just below the string where it does not touch at all. The purpose of this is because while the actual hardware might be able to make the bow go even lower, that position might be far enough from the string that once &#039;&#039;engaged&#039;&#039; the bow may have so far to travel that there is perceptible &#039;&#039;latency&#039;&#039;.&lt;br /&gt;
|-&lt;br /&gt;
|engagespeed&lt;br /&gt;
|es&lt;br /&gt;
|1- ~100&lt;br /&gt;
|Bow pressure movement speed when engaging or disengaging&lt;br /&gt;
|-&lt;br /&gt;
|modulationspeed&lt;br /&gt;
|ms&lt;br /&gt;
|0.1 - 10&lt;br /&gt;
|Bow pressure movement speed while engaged&lt;br /&gt;
|-&lt;br /&gt;
|hold&lt;br /&gt;
|hd&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets bow hold (infinite sustain) on/off, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|home&lt;br /&gt;
|hm&lt;br /&gt;
| -&lt;br /&gt;
|Homing bow, used at startup and in case of the bow loosing position&lt;br /&gt;
|-&lt;br /&gt;
|tmcinfo&lt;br /&gt;
|tmi&lt;br /&gt;
| -&lt;br /&gt;
|Request statistical information from the TMC2209 stepper motor driver&lt;br /&gt;
|}&lt;br /&gt;
Note that the &amp;quot;stall&amp;quot;, &amp;quot;engage&amp;quot; and &amp;quot;rest&amp;quot;-pressure positions mention something called &#039;&#039;hardware position&#039;&#039;. This means the entire available movement of the &#039;&#039;bowing jack&#039;&#039;. Because the very bottom and top end of the movement might not be musically useful and may even harm the instrument, the &amp;quot;baseline&amp;quot; and &amp;quot;modifier&amp;quot; commands &#039;&#039;parameter&#039;&#039;s are scaled depending on these settings.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;engage&amp;quot; and &amp;quot;modulation&amp;quot;-speed settings sets how fast the stepper motor that drives the &#039;&#039;pressure&#039;&#039; moves depending on whether the &#039;&#039;bowing jack&#039;&#039; is set to &#039;&#039;engage&#039;&#039; or not. The idea here is that while wanting to be able to minimize &#039;&#039;latency&#039;&#039; by &#039;&#039;engaging&#039;&#039; and &#039;&#039;disengaging&#039;&#039; from the string as quickly as possible, dynamic changes in the &#039;&#039;pressure&#039;&#039; while playing benefits from much smoother movements as the &#039;&#039;bowing wheel&#039;&#039; takes some time to catch up to varying amounts of friction.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;dcmotor&amp;quot;-&#039;&#039;module&#039;&#039; handles the direct &amp;lt;u&amp;gt;raw&amp;lt;/u&amp;gt; control of the &#039;&#039;bowing motor&#039;&#039; and handles the reporting back of the current speed. It has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|run&lt;br /&gt;
|ru&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Turns the motor off/on&lt;br /&gt;
|-&lt;br /&gt;
|pwm&lt;br /&gt;
|pw&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor direct power in 16-bit PWM values, requires that the &#039;&#039;PID&#039;&#039; is turned off&lt;br /&gt;
|-&lt;br /&gt;
|voltage&lt;br /&gt;
|vo&lt;br /&gt;
|~2 - 10V&lt;br /&gt;
|Sets the voltage of the regulator powering the motor. Changes here can make the motor more responsive to certain frequencies but will also affect how well the &#039;&#039;PID&#039;&#039; works. !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|current&lt;br /&gt;
|cu&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor reported current use&lt;br /&gt;
|-&lt;br /&gt;
|currentlimit&lt;br /&gt;
|cl&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor current limit (A)- !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|powerlimit&lt;br /&gt;
|pl&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor power limit (W) - !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|frequency&lt;br /&gt;
|fq&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor reported frequency&lt;br /&gt;
|-&lt;br /&gt;
|emergencystop&lt;br /&gt;
|es&lt;br /&gt;
|ms (0-65535)&lt;br /&gt;
|Immediately stops the bowing motor and doesn&#039;t allow it to start again until the cool down period given in the first argument has lapsed (milliseconds)&lt;br /&gt;
|-&lt;br /&gt;
|minpwm&lt;br /&gt;
|ip&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor minimum PWM (for calibration)&lt;br /&gt;
|-&lt;br /&gt;
|maxpwm&lt;br /&gt;
|xp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor maximum PWM (for calibration)&lt;br /&gt;
|}&lt;br /&gt;
The &amp;quot;pidcontroller&amp;quot;-&#039;&#039;module&#039;&#039; is responsible for keeping the &amp;quot;dcmotor&amp;quot;-&#039;&#039;module&#039;&#039; at a certain frequency (given in Hertz). It takes the output of the motor frequency measurement and feeds it a PWM value that tries to make the speed constant regardless of the friction that the motor is enduring. To learn more about PID Controllers please see this [[wikipedia:PID_controller|wikipedia article]]. The &#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|targetfrequency&lt;br /&gt;
|tf&lt;br /&gt;
|hertz&lt;br /&gt;
|Sets the PID target frequency&lt;br /&gt;
|-&lt;br /&gt;
|ki&lt;br /&gt;
|ki&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Ki parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|kp&lt;br /&gt;
|kp&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Kp parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|kd&lt;br /&gt;
|kd&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Kd parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|integratorerror&lt;br /&gt;
|ie&lt;br /&gt;
|float&lt;br /&gt;
|Sets the lower threshold of error values for the PID integrator to ignore&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|re&lt;br /&gt;
| -&lt;br /&gt;
|Resets the PID integrator and derivative&lt;br /&gt;
|-&lt;br /&gt;
|maxerror&lt;br /&gt;
|xe&lt;br /&gt;
|float&lt;br /&gt;
|Maximum error to correct in each PID loop, essentially sets acceleration&lt;br /&gt;
|-&lt;br /&gt;
|peakerror&lt;br /&gt;
|pe&lt;br /&gt;
|float&lt;br /&gt;
|Get latest PID peak error&lt;br /&gt;
|-&lt;br /&gt;
|motorspeedmax&lt;br /&gt;
|msx&lt;br /&gt;
|Hertz&lt;br /&gt;
|Bow motor maximum speed limit&lt;br /&gt;
|-&lt;br /&gt;
|motorspeedmin&lt;br /&gt;
|msi&lt;br /&gt;
|Hertz&lt;br /&gt;
|Bow motor minimum speed limit&lt;br /&gt;
|-&lt;br /&gt;
|measuretimetotarget&lt;br /&gt;
|mtt&lt;br /&gt;
|Hertz&lt;br /&gt;
|Measure the time it takes to change from the current frequency to the target frequency, for testing purposes&lt;br /&gt;
|}&lt;br /&gt;
The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; is responsible for sending frequency data to the &amp;quot;pid&amp;quot;-&#039;&#039;module&#039;&#039;. It handles calculating the correct frequency of the &#039;&#039;bowing wheel&#039;&#039; according to the selected &#039;&#039;harmonic&#039;&#039; and &#039;&#039;harmonic shift&#039;&#039; per the currently selected &#039;&#039;harmonic series&#039;&#039;. The &amp;quot;harmonicserieshandler&amp;quot;-&#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|fundamental&lt;br /&gt;
|fu&lt;br /&gt;
|Hertz&lt;br /&gt;
|The fundamental frequency of the string, all harmonics are calculated from this number&lt;br /&gt;
|-&lt;br /&gt;
|harmonic&lt;br /&gt;
|h&lt;br /&gt;
|int&lt;br /&gt;
|Selects the harmonic number to set the &#039;&#039;bowing wheel&#039;&#039; to. A ratio is taken from the given &#039;&#039;harmonic&#039;&#039; in the current &#039;&#039;harmonic series&#039;&#039;, the ratio is then multiplied by the &#039;&#039;fundamental frequency&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|harmonicadd&lt;br /&gt;
|ha&lt;br /&gt;
|int&lt;br /&gt;
|This number is added to the current harmonic&lt;br /&gt;
|-&lt;br /&gt;
|harmonicbase&lt;br /&gt;
|hb&lt;br /&gt;
|int&lt;br /&gt;
|Same as harmonic but where the harmonic number is based on a MIDI note given by basenote&lt;br /&gt;
|-&lt;br /&gt;
|basenote&lt;br /&gt;
|bn&lt;br /&gt;
|0-127&lt;br /&gt;
|Sets the MIDI base note of the &#039;&#039;bowing wheel&#039;&#039;, used in conjunction with &amp;quot;harmonicbase&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|shift&lt;br /&gt;
|sh&lt;br /&gt;
| -32767 - 32767&lt;br /&gt;
|Sets shift from the currently playing harmonic where 32767 equals the entire harmonic shift range shifted up&lt;br /&gt;
|-&lt;br /&gt;
|shiftrange&lt;br /&gt;
|sr&lt;br /&gt;
|0-36&lt;br /&gt;
|Set the number of harmonic numbers that constitutes an entire harmonic shift&lt;br /&gt;
|-&lt;br /&gt;
|shift5&lt;br /&gt;
|sh5&lt;br /&gt;
| -32767 - 32767&lt;br /&gt;
|Sets the shift from the currently playing harmonic over 5 octaves where 32767 equals 5 octaves shift up from the fundamental&lt;br /&gt;
|-&lt;br /&gt;
|add&lt;br /&gt;
|a&lt;br /&gt;
|(name):(ratios)&lt;br /&gt;
|Add a new series with the given name and parameters&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|rm&lt;br /&gt;
|series&lt;br /&gt;
|Remove the series given and shift any series accordingly. Cannot remove all series&lt;br /&gt;
|-&lt;br /&gt;
|count&lt;br /&gt;
|c&lt;br /&gt;
| -&lt;br /&gt;
|Returns the number of harmonic series in the list and their IDs&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Knaadmin</name></author>
	</entry>
	<entry>
		<id>http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_reference_V1.1&amp;diff=1674</id>
		<title>The Ekdahl FAR - Command reference V1.1</title>
		<link rel="alternate" type="text/html" href="http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_reference_V1.1&amp;diff=1674"/>
		<updated>2026-06-12T14:01:16Z</updated>

		<summary type="html">&lt;p&gt;Knaadmin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
The Ekdahl FAR V1.1 introduces the concept of &#039;&#039;modules&#039;&#039;. A &#039;&#039;module&#039;&#039; can contain any number of &#039;&#039;commands&#039;&#039; as well as other &#039;&#039;modules&#039;&#039;. Furthermore any number of &#039;&#039;modules&#039;&#039; of the same type can exist within a context, these are addressed using classic C-style array &#039;&#039;indexing&#039;&#039; with the help of brackets (&amp;quot;[ ]&amp;quot;). Extending on the classic usage, multiple &#039;&#039;indexes&#039;&#039; can be addressed simultaneously by either comma-separating the objects (&amp;quot;[0,3,4]&amp;quot;) and using &#039;&#039;ranges&#039;&#039; (&amp;quot;[3-6]&amp;quot;). &#039;&#039;Modules&#039;&#039; can be either &#039;&#039;internal&#039;&#039; or &#039;&#039;external&#039;&#039;, meaning that they may all physically exist within a single hardware object, or they can be be remote-controlled devices. From a user perspective this however makes no difference as they will appear the same.&lt;br /&gt;
&lt;br /&gt;
While all &#039;&#039;modules&#039;&#039; have their own set of &#039;&#039;commands&#039;&#039;, there are certain &#039;&#039;commands&#039;&#039; that all &#039;&#039;modules&#039;&#039; &amp;lt;u&amp;gt;must&amp;lt;/u&amp;gt; implement and can thus be accessed anywhere within the &#039;&#039;module hierarchy.&#039;&#039; There are also &#039;&#039;base commands&#039;&#039; that always exist within any given FAR ecosystem as well as product-specific &#039;&#039;base commands&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Basic commands ==&lt;br /&gt;
The &#039;&#039;module commands&#039;&#039; that are &amp;lt;u&amp;gt;required&amp;lt;/u&amp;gt; to be implemented in &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; &#039;&#039;modules&#039;&#039; and that can thus be accessed from anywhere are&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|list&lt;br /&gt;
|ls&lt;br /&gt;
|hidden/h:modules/m:commands/c:instances/i:instancecounts/ic:recursive/r&lt;br /&gt;
|Lists all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039; under the current module depending on the parameters given; &#039;hidden&#039; includes normally hidden &#039;&#039;commands&#039;&#039;, &#039;modules&#039; includes any &#039;&#039;submodules&#039;&#039;, &#039;commands&#039; shows &#039;&#039;commands&#039;&#039;, &#039;instances&#039; shows data for each individual instance of a &#039;&#039;module&#039;&#039;, &#039;instancecounts&#039; includes number of instances of each &#039;&#039;module&#039;&#039;, &#039;recursive&#039; lists all child &#039;&#039;modules&#039;&#039; / &#039;&#039;commands&#039;&#039;. No parameters defaults to showing all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039; recursively with instance counts. It doesn&#039;t show per-instance data or hidden commands.&lt;br /&gt;
|-&lt;br /&gt;
|help&lt;br /&gt;
|help&lt;br /&gt;
|recursive/r&lt;br /&gt;
|Shows a brief explanation of all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039;, shows the help for all &#039;&#039;submodules&#039;&#039; as well if &#039;recursive&#039;&lt;br /&gt;
|-&lt;br /&gt;
|dumpdata&lt;br /&gt;
|dump&lt;br /&gt;
|recursive/r&lt;br /&gt;
|Dumps all data saved for the current &#039;&#039;module&#039;&#039;, will list the data of all &#039;&#039;submodules&#039;&#039; as well if &#039;recursive&#039;&lt;br /&gt;
|}&lt;br /&gt;
The &#039;&#039;base commands&#039;&#039; are as follows&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|version&lt;br /&gt;
|ver&lt;br /&gt;
| -&lt;br /&gt;
|Gets the current firmware version&lt;br /&gt;
|-&lt;br /&gt;
|debugprint&lt;br /&gt;
|dp&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;command|usb|hardware|undefined|priority|error|inforequest|expressionparser|debug:1|0&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Turns on or off serial feedback for the given item&lt;br /&gt;
|-&lt;br /&gt;
|requestinfo&lt;br /&gt;
|rqi&lt;br /&gt;
|command&lt;br /&gt;
|Retrives any data saved for a &#039;&#039;command&#039;&#039;, if applicable&lt;br /&gt;
|-&lt;br /&gt;
|saveallparameters&lt;br /&gt;
|sap&lt;br /&gt;
| -&lt;br /&gt;
|Saves all avaliable parameters&lt;br /&gt;
|-&lt;br /&gt;
|loadallparameters&lt;br /&gt;
|lap&lt;br /&gt;
| -&lt;br /&gt;
|Loads all avaliable parameters&lt;br /&gt;
|-&lt;br /&gt;
|resetallparameters&lt;br /&gt;
|rap&lt;br /&gt;
| -&lt;br /&gt;
|Resets all saved parameters&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|rst&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;1|0&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Resets the Ekdahl FAR, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|nick&lt;br /&gt;
|nick&lt;br /&gt;
|name&lt;br /&gt;
|Sets the nickname of this unit&lt;br /&gt;
|-&lt;br /&gt;
|nooperation&lt;br /&gt;
|nop&lt;br /&gt;
| -&lt;br /&gt;
|Do absolutely, positively, nothing. Useful for testing and interfacing with computers, it&#039;s a good way to know that the unit is alive and responding since a &amp;quot;nop&amp;quot; is being returned as a response upon reception.&lt;br /&gt;
|-&lt;br /&gt;
|uservariable&lt;br /&gt;
|uv&lt;br /&gt;
|variable(0-9):value&lt;br /&gt;
|Set user variable 0-9 to &#039;value&#039;&lt;br /&gt;
|-&lt;br /&gt;
|expressionparserevaluate&lt;br /&gt;
|epev&lt;br /&gt;
|expression&lt;br /&gt;
|Evaluates an arithmetric expression and sends back the output, all variables and functions that can be used in any &#039;&#039;command string&#039;&#039; can also be used here. Useful for testing expressions.&lt;br /&gt;
|-&lt;br /&gt;
|ifequal&lt;br /&gt;
|ife&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] EQUALS [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring].&lt;br /&gt;
|-&lt;br /&gt;
|ifgreater&lt;br /&gt;
|ifg&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] &amp;gt; [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring]&lt;br /&gt;
|-&lt;br /&gt;
|ifless&lt;br /&gt;
|ifl&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] &amp;lt; [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring]&lt;br /&gt;
|-&lt;br /&gt;
|freeram&lt;br /&gt;
|ram&lt;br /&gt;
| -&lt;br /&gt;
|Shows free RAM memory&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The base also contains the following &#039;&#039;modules:&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|pluginhandler&lt;br /&gt;
|ph&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The Ekdahl FAR stand alone single string unit ==&lt;br /&gt;
The Ekdahl FAR stand-alone single string unit offers these &#039;&#039;commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|calibrateall&lt;br /&gt;
|ca&lt;br /&gt;
| -&lt;br /&gt;
|Performs all calibration routines on the selected bow, see below for routines performed&lt;br /&gt;
|-&lt;br /&gt;
|calibratebowspeed&lt;br /&gt;
|cbs&lt;br /&gt;
| -&lt;br /&gt;
|Finds the minimum and maximum bow speed of the selected bow&lt;br /&gt;
|-&lt;br /&gt;
|calibratebowpressure&lt;br /&gt;
|cbp&lt;br /&gt;
| -&lt;br /&gt;
|Finds the minimum and maximum bow pressure of the selected bow&lt;br /&gt;
|-&lt;br /&gt;
|calibratemute&lt;br /&gt;
|cmu&lt;br /&gt;
| -&lt;br /&gt;
|Calibrate mute settings&lt;br /&gt;
|-&lt;br /&gt;
|pickupstringfrequency&lt;br /&gt;
|psf&lt;br /&gt;
| -&lt;br /&gt;
|Returns the fundamental tone calculated from the current audio signal if apliccable&lt;br /&gt;
|-&lt;br /&gt;
|pickupaudiopeak&lt;br /&gt;
|pap&lt;br /&gt;
| -&lt;br /&gt;
|Returns the peak amplitude of the current audio signal&lt;br /&gt;
|-&lt;br /&gt;
|pickupaudiorms&lt;br /&gt;
|par&lt;br /&gt;
| -&lt;br /&gt;
|Returns the RMS amplitude of the current audio signal&lt;br /&gt;
|}&lt;br /&gt;
The Ekdahl FAR also contains the following &#039;&#039;modules&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|bowingwheel&lt;br /&gt;
|bw&lt;br /&gt;
|-&lt;br /&gt;
|mute&lt;br /&gt;
|mu&lt;br /&gt;
|-&lt;br /&gt;
|solenoid&lt;br /&gt;
|so&lt;br /&gt;
|-&lt;br /&gt;
|controlbox&lt;br /&gt;
|cb&lt;br /&gt;
|-&lt;br /&gt;
|midiconfigurationhandler&lt;br /&gt;
|mcf&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;bowingwheel&amp;quot; module ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;Bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; contains everything needed to interface with a single &#039;&#039;bowing wheel&#039;&#039;. Each &#039;&#039;bowing wheel&#039;&#039; has its own harmonic series, pressure actuators and direct hardware interface. It contains the following &#039;&#039;commands&#039;&#039;.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|speedmode&lt;br /&gt;
|sm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Bow motor speed mode, 0 = Automatic and 1 = Manual. Automatic mode means that the bowing wheel will automatically turn off after the &#039;&#039;motor timeout&#039;&#039; has been reached after being put into rest mode&lt;br /&gt;
|-&lt;br /&gt;
|motortimeout&lt;br /&gt;
|mt&lt;br /&gt;
|ms&lt;br /&gt;
|Bow motor shutdown timeout after bow having been put into the rest position&lt;br /&gt;
|-&lt;br /&gt;
|pidenable&lt;br /&gt;
|pe&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets the bow PID on/off&lt;br /&gt;
|-&lt;br /&gt;
|motorfaultcommands&lt;br /&gt;
|mfc&lt;br /&gt;
|commands&lt;br /&gt;
|Commands to execute when a motor fault is tripped - !WARNING! Can ruin your instrument if changed&lt;br /&gt;
|-&lt;br /&gt;
|motoroverpowercommands&lt;br /&gt;
|moc&lt;br /&gt;
|commands&lt;br /&gt;
|Commands to execute when motor is over the power limit - !WARNING! Can ruin your instrument if changed&lt;br /&gt;
|}&lt;br /&gt;
The &#039;&#039;modules&#039;&#039; in the &amp;quot;Bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; are as follows&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|bowpressure&lt;br /&gt;
|bp&lt;br /&gt;
|-&lt;br /&gt;
|dcmotor&lt;br /&gt;
|dcm&lt;br /&gt;
|-&lt;br /&gt;
|pid&lt;br /&gt;
|pid&lt;br /&gt;
|-&lt;br /&gt;
|harmonicserieshandler&lt;br /&gt;
|hsh&lt;br /&gt;
|}&lt;br /&gt;
The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; handles the &#039;&#039;pressure&#039;&#039; of the &#039;&#039;bowing wheel&#039;&#039; against the string. The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|baseline&lt;br /&gt;
|ba&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure baseline, modulation is added to this point upward. Typically this is set with a knob on the &#039;&#039;control box&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|modifier&lt;br /&gt;
|mo&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure modulation, added to the baseline&lt;br /&gt;
|-&lt;br /&gt;
|rest&lt;br /&gt;
|rs&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the bow pressure in the &#039;&#039;rest&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|engage&lt;br /&gt;
|en&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the bow pressure in the &#039;&#039;engage&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|stallpressure&lt;br /&gt;
|sp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure stall/maximum position, this parameter is set using &#039;&#039;hardware positioning&#039;&#039; and is used as the absolute maximum for baseline and modifier combiner&lt;br /&gt;
|-&lt;br /&gt;
|engagepressure&lt;br /&gt;
|ep&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure touch/minimum position, this parameter is set using &#039;&#039;hardware position&#039;&#039; and is used as the starting point for when both the baseline and modifier is set to zero&lt;br /&gt;
|-&lt;br /&gt;
|restpressure&lt;br /&gt;
|rp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure rest position, this parameter is set using &#039;&#039;hardware positioning&#039;&#039; and is typically set to a point just below the string where it does not touch at all. The purpose of this is because while the actual hardware might be able to make the bow go even lower, that position might be far enough from the string that once &#039;&#039;engaged&#039;&#039; the bow may have so far to travel that there is perceptible &#039;&#039;latency&#039;&#039;.&lt;br /&gt;
|-&lt;br /&gt;
|engagespeed&lt;br /&gt;
|es&lt;br /&gt;
|1- ~100&lt;br /&gt;
|Bow pressure movement speed when engaging or disengaging&lt;br /&gt;
|-&lt;br /&gt;
|modulationspeed&lt;br /&gt;
|ms&lt;br /&gt;
|0.1 - 10&lt;br /&gt;
|Bow pressure movement speed while engaged&lt;br /&gt;
|-&lt;br /&gt;
|hold&lt;br /&gt;
|hd&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets bow hold (infinite sustain) on/off, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|home&lt;br /&gt;
|hm&lt;br /&gt;
| -&lt;br /&gt;
|Homing bow, used at startup and in case of the bow loosing position&lt;br /&gt;
|-&lt;br /&gt;
|tmcinfo&lt;br /&gt;
|tmi&lt;br /&gt;
| -&lt;br /&gt;
|Request statistical information from the TMC2209 stepper motor driver&lt;br /&gt;
|}&lt;br /&gt;
Note that the &amp;quot;stall&amp;quot;, &amp;quot;engage&amp;quot; and &amp;quot;rest&amp;quot;-pressure positions mention something called &#039;&#039;hardware position&#039;&#039;. This means the entire available movement of the &#039;&#039;bowing jack&#039;&#039;. Because the very bottom and top end of the movement might not be musically useful and may even harm the instrument, the &amp;quot;baseline&amp;quot; and &amp;quot;modifier&amp;quot; commands &#039;&#039;parameter&#039;&#039;s are scaled depending on these settings.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;engage&amp;quot; and &amp;quot;modulation&amp;quot;-speed settings sets how fast the stepper motor that drives the &#039;&#039;pressure&#039;&#039; moves depending on whether the &#039;&#039;bowing jack&#039;&#039; is set to &#039;&#039;engage&#039;&#039; or not. The idea here is that while wanting to be able to minimize &#039;&#039;latency&#039;&#039; by &#039;&#039;engaging&#039;&#039; and &#039;&#039;disengaging&#039;&#039; from the string as quickly as possible, dynamic changes in the &#039;&#039;pressure&#039;&#039; while playing benefits from much smoother movements as the &#039;&#039;bowing wheel&#039;&#039; takes some time to catch up to varying amounts of friction.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;dcmotor&amp;quot;-&#039;&#039;module&#039;&#039; handles the direct &amp;lt;u&amp;gt;raw&amp;lt;/u&amp;gt; control of the &#039;&#039;bowing motor&#039;&#039; and handles the reporting back of the current speed. It has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|run&lt;br /&gt;
|ru&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Turns the motor off/on&lt;br /&gt;
|-&lt;br /&gt;
|pwm&lt;br /&gt;
|pw&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor direct power in 16-bit PWM values, requires that the &#039;&#039;PID&#039;&#039; is turned off&lt;br /&gt;
|-&lt;br /&gt;
|voltage&lt;br /&gt;
|vo&lt;br /&gt;
|~2 - 10V&lt;br /&gt;
|Sets the voltage of the regulator powering the motor. Changes here can make the motor more responsive to certain frequencies but will also affect how well the &#039;&#039;PID&#039;&#039; works. !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|current&lt;br /&gt;
|cu&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor reported current use&lt;br /&gt;
|-&lt;br /&gt;
|currentlimit&lt;br /&gt;
|cl&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor current limit (A)- !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|powerlimit&lt;br /&gt;
|pl&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor power limit (W) - !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|frequency&lt;br /&gt;
|fq&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor reported frequency&lt;br /&gt;
|-&lt;br /&gt;
|emergencystop&lt;br /&gt;
|es&lt;br /&gt;
|ms (0-65535)&lt;br /&gt;
|Immediately stops the bowing motor and doesn&#039;t allow it to start again until the cool down period given in the first argument has lapsed (milliseconds)&lt;br /&gt;
|-&lt;br /&gt;
|minpwm&lt;br /&gt;
|ip&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor minimum PWM (for calibration)&lt;br /&gt;
|-&lt;br /&gt;
|maxpwm&lt;br /&gt;
|xp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor maximum PWM (for calibration)&lt;br /&gt;
|}&lt;br /&gt;
The &amp;quot;pidcontroller&amp;quot;-&#039;&#039;module&#039;&#039; is responsible for keeping the &amp;quot;dcmotor&amp;quot;-&#039;&#039;module&#039;&#039; at a certain frequency (given in Hertz). It takes the output of the motor frequency measurement and feeds it a PWM value that tries to make the speed constant regardless of the friction that the motor is enduring. To learn more about PID Controllers please see this [[wikipedia:PID_controller|wikipedia article]]. The &#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|targetfrequency&lt;br /&gt;
|tf&lt;br /&gt;
|hertz&lt;br /&gt;
|Sets the PID target frequency&lt;br /&gt;
|-&lt;br /&gt;
|ki&lt;br /&gt;
|ki&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Ki parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|kp&lt;br /&gt;
|kp&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Kp parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|kd&lt;br /&gt;
|kd&lt;br /&gt;
|float&lt;br /&gt;
|Sets the Kd parameter of the PID&lt;br /&gt;
|-&lt;br /&gt;
|integratorerror&lt;br /&gt;
|ie&lt;br /&gt;
|float&lt;br /&gt;
|Sets the lower threshold of error values for the PID integrator to ignore&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|re&lt;br /&gt;
| -&lt;br /&gt;
|Resets the PID integrator and derivative&lt;br /&gt;
|-&lt;br /&gt;
|maxerror&lt;br /&gt;
|xe&lt;br /&gt;
|float&lt;br /&gt;
|Maximum error to correct in each PID loop, essentially sets acceleration&lt;br /&gt;
|-&lt;br /&gt;
|peakerror&lt;br /&gt;
|pe&lt;br /&gt;
|float&lt;br /&gt;
|Get latest PID peak error&lt;br /&gt;
|-&lt;br /&gt;
|motorspeedmax&lt;br /&gt;
|msx&lt;br /&gt;
|Hertz&lt;br /&gt;
|Bow motor maximum speed limit&lt;br /&gt;
|-&lt;br /&gt;
|motorspeedmin&lt;br /&gt;
|msi&lt;br /&gt;
|Hertz&lt;br /&gt;
|Bow motor minimum speed limit&lt;br /&gt;
|-&lt;br /&gt;
|measuretimetotarget&lt;br /&gt;
|mtt&lt;br /&gt;
|Hertz&lt;br /&gt;
|Measure the time it takes to change from the current frequency to the target frequency, for testing purposes&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Knaadmin</name></author>
	</entry>
	<entry>
		<id>http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_reference_V1.1&amp;diff=1673</id>
		<title>The Ekdahl FAR - Command reference V1.1</title>
		<link rel="alternate" type="text/html" href="http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_reference_V1.1&amp;diff=1673"/>
		<updated>2026-06-12T13:38:26Z</updated>

		<summary type="html">&lt;p&gt;Knaadmin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
The Ekdahl FAR V1.1 introduces the concept of &#039;&#039;modules&#039;&#039;. A &#039;&#039;module&#039;&#039; can contain any number of &#039;&#039;commands&#039;&#039; as well as other &#039;&#039;modules&#039;&#039;. Furthermore any number of &#039;&#039;modules&#039;&#039; of the same type can exist within a context, these are addressed using classic C-style array &#039;&#039;indexing&#039;&#039; with the help of brackets (&amp;quot;[ ]&amp;quot;). Extending on the classic usage, multiple &#039;&#039;indexes&#039;&#039; can be addressed simultaneously by either comma-separating the objects (&amp;quot;[0,3,4]&amp;quot;) and using &#039;&#039;ranges&#039;&#039; (&amp;quot;[3-6]&amp;quot;). &#039;&#039;Modules&#039;&#039; can be either &#039;&#039;internal&#039;&#039; or &#039;&#039;external&#039;&#039;, meaning that they may all physically exist within a single hardware object, or they can be be remote-controlled devices. From a user perspective this however makes no difference as they will appear the same.&lt;br /&gt;
&lt;br /&gt;
While all &#039;&#039;modules&#039;&#039; have their own set of &#039;&#039;commands&#039;&#039;, there are certain &#039;&#039;commands&#039;&#039; that all &#039;&#039;modules&#039;&#039; &amp;lt;u&amp;gt;must&amp;lt;/u&amp;gt; implement and can thus be accessed anywhere within the &#039;&#039;module hierarchy.&#039;&#039; There are also &#039;&#039;base commands&#039;&#039; that always exist within any given FAR ecosystem as well as product-specific &#039;&#039;base commands&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Basic commands ==&lt;br /&gt;
The &#039;&#039;module commands&#039;&#039; that are &amp;lt;u&amp;gt;required&amp;lt;/u&amp;gt; to be implemented in &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; &#039;&#039;modules&#039;&#039; and that can thus be accessed from anywhere are&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|list&lt;br /&gt;
|ls&lt;br /&gt;
|hidden/h:modules/m:commands/c:instances/i:instancecounts/ic:recursive/r&lt;br /&gt;
|Lists all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039; under the current module depending on the parameters given; &#039;hidden&#039; includes normally hidden &#039;&#039;commands&#039;&#039;, &#039;modules&#039; includes any &#039;&#039;submodules&#039;&#039;, &#039;commands&#039; shows &#039;&#039;commands&#039;&#039;, &#039;instances&#039; shows data for each individual instance of a &#039;&#039;module&#039;&#039;, &#039;instancecounts&#039; includes number of instances of each &#039;&#039;module&#039;&#039;, &#039;recursive&#039; lists all child &#039;&#039;modules&#039;&#039; / &#039;&#039;commands&#039;&#039;. No parameters defaults to showing all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039; recursively with instance counts. It doesn&#039;t show per-instance data or hidden commands.&lt;br /&gt;
|-&lt;br /&gt;
|help&lt;br /&gt;
|help&lt;br /&gt;
|recursive/r&lt;br /&gt;
|Shows a brief explanation of all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039;, shows the help for all &#039;&#039;submodules&#039;&#039; as well if &#039;recursive&#039;&lt;br /&gt;
|-&lt;br /&gt;
|dumpdata&lt;br /&gt;
|dump&lt;br /&gt;
|recursive/r&lt;br /&gt;
|Dumps all data saved for the current &#039;&#039;module&#039;&#039;, will list the data of all &#039;&#039;submodules&#039;&#039; as well if &#039;recursive&#039;&lt;br /&gt;
|}&lt;br /&gt;
The &#039;&#039;base commands&#039;&#039; are as follows&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|version&lt;br /&gt;
|ver&lt;br /&gt;
| -&lt;br /&gt;
|Gets the current firmware version&lt;br /&gt;
|-&lt;br /&gt;
|debugprint&lt;br /&gt;
|dp&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;command|usb|hardware|undefined|priority|error|inforequest|expressionparser|debug:1|0&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Turns on or off serial feedback for the given item&lt;br /&gt;
|-&lt;br /&gt;
|requestinfo&lt;br /&gt;
|rqi&lt;br /&gt;
|command&lt;br /&gt;
|Retrives any data saved for a &#039;&#039;command&#039;&#039;, if applicable&lt;br /&gt;
|-&lt;br /&gt;
|saveallparameters&lt;br /&gt;
|sap&lt;br /&gt;
| -&lt;br /&gt;
|Saves all avaliable parameters&lt;br /&gt;
|-&lt;br /&gt;
|loadallparameters&lt;br /&gt;
|lap&lt;br /&gt;
| -&lt;br /&gt;
|Loads all avaliable parameters&lt;br /&gt;
|-&lt;br /&gt;
|resetallparameters&lt;br /&gt;
|rap&lt;br /&gt;
| -&lt;br /&gt;
|Resets all saved parameters&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|rst&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;1|0&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Resets the Ekdahl FAR, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|nick&lt;br /&gt;
|nick&lt;br /&gt;
|name&lt;br /&gt;
|Sets the nickname of this unit&lt;br /&gt;
|-&lt;br /&gt;
|nooperation&lt;br /&gt;
|nop&lt;br /&gt;
| -&lt;br /&gt;
|Do absolutely, positively, nothing. Useful for testing and interfacing with computers, it&#039;s a good way to know that the unit is alive and responding since a &amp;quot;nop&amp;quot; is being returned as a response upon reception.&lt;br /&gt;
|-&lt;br /&gt;
|uservariable&lt;br /&gt;
|uv&lt;br /&gt;
|variable(0-9):value&lt;br /&gt;
|Set user variable 0-9 to &#039;value&#039;&lt;br /&gt;
|-&lt;br /&gt;
|expressionparserevaluate&lt;br /&gt;
|epev&lt;br /&gt;
|expression&lt;br /&gt;
|Evaluates an arithmetric expression and sends back the output, all variables and functions that can be used in any &#039;&#039;command string&#039;&#039; can also be used here. Useful for testing expressions.&lt;br /&gt;
|-&lt;br /&gt;
|ifequal&lt;br /&gt;
|ife&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] EQUALS [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring].&lt;br /&gt;
|-&lt;br /&gt;
|ifgreater&lt;br /&gt;
|ifg&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] &amp;gt; [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring]&lt;br /&gt;
|-&lt;br /&gt;
|ifless&lt;br /&gt;
|ifl&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] &amp;lt; [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring]&lt;br /&gt;
|-&lt;br /&gt;
|freeram&lt;br /&gt;
|ram&lt;br /&gt;
| -&lt;br /&gt;
|Shows free RAM memory&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The base also contains the following &#039;&#039;modules:&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|pluginhandler&lt;br /&gt;
|ph&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The Ekdahl FAR stand alone single string unit ==&lt;br /&gt;
The Ekdahl FAR stand-alone single string unit offers these &#039;&#039;commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|calibrateall&lt;br /&gt;
|ca&lt;br /&gt;
| -&lt;br /&gt;
|Performs all calibration routines on the selected bow, see below for routines performed&lt;br /&gt;
|-&lt;br /&gt;
|calibratebowspeed&lt;br /&gt;
|cbs&lt;br /&gt;
| -&lt;br /&gt;
|Finds the minimum and maximum bow speed of the selected bow&lt;br /&gt;
|-&lt;br /&gt;
|calibratebowpressure&lt;br /&gt;
|cbp&lt;br /&gt;
| -&lt;br /&gt;
|Finds the minimum and maximum bow pressure of the selected bow&lt;br /&gt;
|-&lt;br /&gt;
|calibratemute&lt;br /&gt;
|cmu&lt;br /&gt;
| -&lt;br /&gt;
|Calibrate mute settings&lt;br /&gt;
|-&lt;br /&gt;
|pickupstringfrequency&lt;br /&gt;
|psf&lt;br /&gt;
| -&lt;br /&gt;
|Returns the fundamental tone calculated from the current audio signal if apliccable&lt;br /&gt;
|-&lt;br /&gt;
|pickupaudiopeak&lt;br /&gt;
|pap&lt;br /&gt;
| -&lt;br /&gt;
|Returns the peak amplitude of the current audio signal&lt;br /&gt;
|-&lt;br /&gt;
|pickupaudiorms&lt;br /&gt;
|par&lt;br /&gt;
| -&lt;br /&gt;
|Returns the RMS amplitude of the current audio signal&lt;br /&gt;
|}&lt;br /&gt;
The Ekdahl FAR also contains the following &#039;&#039;modules&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|bowingwheel&lt;br /&gt;
|bw&lt;br /&gt;
|-&lt;br /&gt;
|mute&lt;br /&gt;
|mu&lt;br /&gt;
|-&lt;br /&gt;
|solenoid&lt;br /&gt;
|so&lt;br /&gt;
|-&lt;br /&gt;
|controlbox&lt;br /&gt;
|cb&lt;br /&gt;
|-&lt;br /&gt;
|midiconfigurationhandler&lt;br /&gt;
|mcf&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;bowingwheel&amp;quot; module ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;Bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; contains everything needed to interface with a single &#039;&#039;bowing wheel&#039;&#039;. Each &#039;&#039;bowing wheel&#039;&#039; has its own harmonic series, pressure actuators and direct hardware interface. It contains the following &#039;&#039;commands&#039;&#039;.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|speedmode&lt;br /&gt;
|sm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Bow motor speed mode, 0 = Automatic and 1 = Manual. Automatic mode means that the bowing wheel will automatically turn off after the &#039;&#039;motor timeout&#039;&#039; has been reached after being put into rest mode&lt;br /&gt;
|-&lt;br /&gt;
|motortimeout&lt;br /&gt;
|mt&lt;br /&gt;
|ms&lt;br /&gt;
|Bow motor shutdown timeout after bow having been put into the rest position&lt;br /&gt;
|-&lt;br /&gt;
|pidenable&lt;br /&gt;
|pe&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets the bow PID on/off&lt;br /&gt;
|-&lt;br /&gt;
|motorfaultcommands&lt;br /&gt;
|mfc&lt;br /&gt;
|commands&lt;br /&gt;
|Commands to execute when a motor fault is tripped - !WARNING! Can ruin your instrument if changed&lt;br /&gt;
|-&lt;br /&gt;
|motoroverpowercommands&lt;br /&gt;
|moc&lt;br /&gt;
|commands&lt;br /&gt;
|Commands to execute when motor is over the power limit - !WARNING! Can ruin your instrument if changed&lt;br /&gt;
|}&lt;br /&gt;
The &#039;&#039;modules&#039;&#039; in the &amp;quot;Bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; are as follows&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|bowpressure&lt;br /&gt;
|bp&lt;br /&gt;
|-&lt;br /&gt;
|dcmotor&lt;br /&gt;
|dcm&lt;br /&gt;
|-&lt;br /&gt;
|pid&lt;br /&gt;
|pid&lt;br /&gt;
|-&lt;br /&gt;
|harmonicserieshandler&lt;br /&gt;
|hsh&lt;br /&gt;
|}&lt;br /&gt;
The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; handles the &#039;&#039;pressure&#039;&#039; of the &#039;&#039;bowing wheel&#039;&#039; against the string. The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|baseline&lt;br /&gt;
|ba&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure baseline, modulation is added to this point upward. Typically this is set with a knob on the &#039;&#039;control box&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|modifier&lt;br /&gt;
|mo&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure modulation, added to the baseline&lt;br /&gt;
|-&lt;br /&gt;
|rest&lt;br /&gt;
|rs&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the bow pressure in the &#039;&#039;rest&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|engage&lt;br /&gt;
|en&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the bow pressure in the &#039;&#039;engage&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|stallpressure&lt;br /&gt;
|sp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure stall/maximum position, this parameter is set using &#039;&#039;hardware positioning&#039;&#039; and is used as the absolute maximum for baseline and modifier combiner&lt;br /&gt;
|-&lt;br /&gt;
|engagepressure&lt;br /&gt;
|ep&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure touch/minimum position, this parameter is set using &#039;&#039;hardware position&#039;&#039; and is used as the starting point for when both the baseline and modifier is set to zero&lt;br /&gt;
|-&lt;br /&gt;
|restpressure&lt;br /&gt;
|rp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure rest position, this parameter is set using &#039;&#039;hardware positioning&#039;&#039; and is typically set to a point just below the string where it does not touch at all. The purpose of this is because while the actual hardware might be able to make the bow go even lower, that position might be far enough from the string that once &#039;&#039;engaged&#039;&#039; the bow may have so far to travel that there is perceptible &#039;&#039;latency&#039;&#039;.&lt;br /&gt;
|-&lt;br /&gt;
|engagespeed&lt;br /&gt;
|es&lt;br /&gt;
|1- ~100&lt;br /&gt;
|Bow pressure movement speed when engaging or disengaging&lt;br /&gt;
|-&lt;br /&gt;
|modulationspeed&lt;br /&gt;
|ms&lt;br /&gt;
|0.1 - 10&lt;br /&gt;
|Bow pressure movement speed while engaged&lt;br /&gt;
|-&lt;br /&gt;
|hold&lt;br /&gt;
|hd&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets bow hold (infinite sustain) on/off, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|home&lt;br /&gt;
|hm&lt;br /&gt;
| -&lt;br /&gt;
|Homing bow, used at startup and in case of the bow loosing position&lt;br /&gt;
|-&lt;br /&gt;
|tmcinfo&lt;br /&gt;
|tmi&lt;br /&gt;
| -&lt;br /&gt;
|Request statistical information from the TMC2209 stepper motor driver&lt;br /&gt;
|}&lt;br /&gt;
Note that the &amp;quot;stall&amp;quot;, &amp;quot;engage&amp;quot; and &amp;quot;rest&amp;quot;-pressure positions mention something called &#039;&#039;hardware position&#039;&#039;. This means the entire available movement of the &#039;&#039;bowing jack&#039;&#039;. Because the very bottom and top end of the movement might not be musically useful and may even harm the instrument, the &amp;quot;baseline&amp;quot; and &amp;quot;modifier&amp;quot; commands &#039;&#039;parameter&#039;&#039;s are scaled depending on these settings.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;engage&amp;quot; and &amp;quot;modulation&amp;quot;-speed settings sets how fast the stepper motor that drives the &#039;&#039;pressure&#039;&#039; moves depending on whether the &#039;&#039;bowing jack&#039;&#039; is set to &#039;&#039;engage&#039;&#039; or not. The idea here is that while wanting to be able to minimize &#039;&#039;latency&#039;&#039; by &#039;&#039;engaging&#039;&#039; and &#039;&#039;disengaging&#039;&#039; from the string as quickly as possible, dynamic changes in the &#039;&#039;pressure&#039;&#039; while playing benefits from much smoother movements as the &#039;&#039;bowing wheel&#039;&#039; takes some time to catch up to varying amounts of friction.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;dcmotor&amp;quot;-&#039;&#039;module&#039;&#039; handles the direct &amp;lt;u&amp;gt;raw&amp;lt;/u&amp;gt; control of the &#039;&#039;bowing motor&#039;&#039; and handles the reporting back of the current speed. It has the following &#039;&#039;commands&#039;&#039;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|run&lt;br /&gt;
|ru&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Set bow motor run on/off&lt;br /&gt;
|-&lt;br /&gt;
|pwm&lt;br /&gt;
|pw&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor direct power in 16-bit PWM values, requires that the &#039;&#039;PID&#039;&#039; is turned off&lt;br /&gt;
|-&lt;br /&gt;
|voltage&lt;br /&gt;
|vo&lt;br /&gt;
|~2 - 10V&lt;br /&gt;
|Sets the voltage of the regulator powering the motor. Changes here can make the motor more responsive to certain frequencies but will also affect how well the &#039;&#039;PID&#039;&#039; works. !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|current&lt;br /&gt;
|cu&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor reported current use&lt;br /&gt;
|-&lt;br /&gt;
|currentlimit&lt;br /&gt;
|cl&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor current limit (A)- !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|powerlimit&lt;br /&gt;
|pl&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor power limit (W) - !WARNING! CAN RUIN YOUR INSTRUMENT IF CHANGED&lt;br /&gt;
|-&lt;br /&gt;
|frequency&lt;br /&gt;
|fq&lt;br /&gt;
|float&lt;br /&gt;
|Bow motor reported frequency&lt;br /&gt;
|-&lt;br /&gt;
|emergencystop&lt;br /&gt;
|es&lt;br /&gt;
|ms (0-65535)&lt;br /&gt;
|Immediately stops the bowing motor and doesn&#039;t allow it to start again until the cool down period given in the first argument has lapsed (milliseconds)&lt;br /&gt;
|-&lt;br /&gt;
|minpwm&lt;br /&gt;
|ip&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor minimum PWM (for calibration)&lt;br /&gt;
|-&lt;br /&gt;
|maxpwm&lt;br /&gt;
|xp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow motor maximum PWM (for calibration)&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Knaadmin</name></author>
	</entry>
	<entry>
		<id>http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_reference_V1.1&amp;diff=1672</id>
		<title>The Ekdahl FAR - Command reference V1.1</title>
		<link rel="alternate" type="text/html" href="http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_reference_V1.1&amp;diff=1672"/>
		<updated>2026-06-12T13:27:18Z</updated>

		<summary type="html">&lt;p&gt;Knaadmin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
The Ekdahl FAR V1.1 introduces the concept of &#039;&#039;modules&#039;&#039;. A &#039;&#039;module&#039;&#039; can contain any number of &#039;&#039;commands&#039;&#039; as well as other &#039;&#039;modules&#039;&#039;. Furthermore any number of &#039;&#039;modules&#039;&#039; of the same type can exist within a context, these are addressed using classic C-style array &#039;&#039;indexing&#039;&#039; with the help of brackets (&amp;quot;[ ]&amp;quot;). Extending on the classic usage, multiple &#039;&#039;indexes&#039;&#039; can be addressed simultaneously by either comma-separating the objects (&amp;quot;[0,3,4]&amp;quot;) and using &#039;&#039;ranges&#039;&#039; (&amp;quot;[3-6]&amp;quot;). &#039;&#039;Modules&#039;&#039; can be either &#039;&#039;internal&#039;&#039; or &#039;&#039;external&#039;&#039;, meaning that they may all physically exist within a single hardware object, or they can be be remote-controlled devices. From a user perspective this however makes no difference as they will appear the same.&lt;br /&gt;
&lt;br /&gt;
While all &#039;&#039;modules&#039;&#039; have their own set of &#039;&#039;commands&#039;&#039;, there are certain &#039;&#039;commands&#039;&#039; that all &#039;&#039;modules&#039;&#039; &amp;lt;u&amp;gt;must&amp;lt;/u&amp;gt; implement and can thus be accessed anywhere within the &#039;&#039;module hierarchy.&#039;&#039; There are also &#039;&#039;base commands&#039;&#039; that always exist within any given FAR ecosystem as well as product-specific &#039;&#039;base commands&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Basic commands ==&lt;br /&gt;
The &#039;&#039;module commands&#039;&#039; that are &amp;lt;u&amp;gt;required&amp;lt;/u&amp;gt; to be implemented in &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; &#039;&#039;modules&#039;&#039; and that can thus be accessed from anywhere are&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|list&lt;br /&gt;
|ls&lt;br /&gt;
|hidden/h:modules/m:commands/c:instances/i:instancecounts/ic:recursive/r&lt;br /&gt;
|Lists all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039; under the current module depending on the parameters given; &#039;hidden&#039; includes normally hidden &#039;&#039;commands&#039;&#039;, &#039;modules&#039; includes any &#039;&#039;submodules&#039;&#039;, &#039;commands&#039; shows &#039;&#039;commands&#039;&#039;, &#039;instances&#039; shows data for each individual instance of a &#039;&#039;module&#039;&#039;, &#039;instancecounts&#039; includes number of instances of each &#039;&#039;module&#039;&#039;, &#039;recursive&#039; lists all child &#039;&#039;modules&#039;&#039; / &#039;&#039;commands&#039;&#039;. No parameters defaults to showing all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039; recursively with instance counts. It doesn&#039;t show per-instance data or hidden commands.&lt;br /&gt;
|-&lt;br /&gt;
|help&lt;br /&gt;
|help&lt;br /&gt;
|recursive/r&lt;br /&gt;
|Shows a brief explanation of all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039;, shows the help for all &#039;&#039;submodules&#039;&#039; as well if &#039;recursive&#039;&lt;br /&gt;
|-&lt;br /&gt;
|dumpdata&lt;br /&gt;
|dump&lt;br /&gt;
|recursive/r&lt;br /&gt;
|Dumps all data saved for the current &#039;&#039;module&#039;&#039;, will list the data of all &#039;&#039;submodules&#039;&#039; as well if &#039;recursive&#039;&lt;br /&gt;
|}&lt;br /&gt;
The &#039;&#039;base commands&#039;&#039; are as follows&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|version&lt;br /&gt;
|ver&lt;br /&gt;
| -&lt;br /&gt;
|Gets the current firmware version&lt;br /&gt;
|-&lt;br /&gt;
|debugprint&lt;br /&gt;
|dp&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;command|usb|hardware|undefined|priority|error|inforequest|expressionparser|debug:1|0&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Turns on or off serial feedback for the given item&lt;br /&gt;
|-&lt;br /&gt;
|requestinfo&lt;br /&gt;
|rqi&lt;br /&gt;
|command&lt;br /&gt;
|Retrives any data saved for a &#039;&#039;command&#039;&#039;, if applicable&lt;br /&gt;
|-&lt;br /&gt;
|saveallparameters&lt;br /&gt;
|sap&lt;br /&gt;
| -&lt;br /&gt;
|Saves all avaliable parameters&lt;br /&gt;
|-&lt;br /&gt;
|loadallparameters&lt;br /&gt;
|lap&lt;br /&gt;
| -&lt;br /&gt;
|Loads all avaliable parameters&lt;br /&gt;
|-&lt;br /&gt;
|resetallparameters&lt;br /&gt;
|rap&lt;br /&gt;
| -&lt;br /&gt;
|Resets all saved parameters&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|rst&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;1|0&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Resets the Ekdahl FAR, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|nick&lt;br /&gt;
|nick&lt;br /&gt;
|name&lt;br /&gt;
|Sets the nickname of this unit&lt;br /&gt;
|-&lt;br /&gt;
|nooperation&lt;br /&gt;
|nop&lt;br /&gt;
| -&lt;br /&gt;
|Do absolutely, positively, nothing. Useful for testing and interfacing with computers, it&#039;s a good way to know that the unit is alive and responding since a &amp;quot;nop&amp;quot; is being returned as a response upon reception.&lt;br /&gt;
|-&lt;br /&gt;
|uservariable&lt;br /&gt;
|uv&lt;br /&gt;
|variable(0-9):value&lt;br /&gt;
|Set user variable 0-9 to &#039;value&#039;&lt;br /&gt;
|-&lt;br /&gt;
|expressionparserevaluate&lt;br /&gt;
|epev&lt;br /&gt;
|expression&lt;br /&gt;
|Evaluates an arithmetric expression and sends back the output, all variables and functions that can be used in any &#039;&#039;command string&#039;&#039; can also be used here. Useful for testing expressions.&lt;br /&gt;
|-&lt;br /&gt;
|ifequal&lt;br /&gt;
|ife&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] EQUALS [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring].&lt;br /&gt;
|-&lt;br /&gt;
|ifgreater&lt;br /&gt;
|ifg&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] &amp;gt; [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring]&lt;br /&gt;
|-&lt;br /&gt;
|ifless&lt;br /&gt;
|ifl&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] &amp;lt; [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring]&lt;br /&gt;
|-&lt;br /&gt;
|freeram&lt;br /&gt;
|ram&lt;br /&gt;
| -&lt;br /&gt;
|Shows free RAM memory&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The base also contains the following &#039;&#039;modules:&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|pluginhandler&lt;br /&gt;
|ph&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The Ekdahl FAR stand alone single string unit ==&lt;br /&gt;
The Ekdahl FAR stand-alone single string unit offers these &#039;&#039;commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|calibrateall&lt;br /&gt;
|ca&lt;br /&gt;
| -&lt;br /&gt;
|Performs all calibration routines on the selected bow, see below for routines performed&lt;br /&gt;
|-&lt;br /&gt;
|calibratebowspeed&lt;br /&gt;
|cbs&lt;br /&gt;
| -&lt;br /&gt;
|Finds the minimum and maximum bow speed of the selected bow&lt;br /&gt;
|-&lt;br /&gt;
|calibratebowpressure&lt;br /&gt;
|cbp&lt;br /&gt;
| -&lt;br /&gt;
|Finds the minimum and maximum bow pressure of the selected bow&lt;br /&gt;
|-&lt;br /&gt;
|calibratemute&lt;br /&gt;
|cmu&lt;br /&gt;
| -&lt;br /&gt;
|Calibrate mute settings&lt;br /&gt;
|-&lt;br /&gt;
|pickupstringfrequency&lt;br /&gt;
|psf&lt;br /&gt;
| -&lt;br /&gt;
|Returns the fundamental tone calculated from the current audio signal if apliccable&lt;br /&gt;
|-&lt;br /&gt;
|pickupaudiopeak&lt;br /&gt;
|pap&lt;br /&gt;
| -&lt;br /&gt;
|Returns the peak amplitude of the current audio signal&lt;br /&gt;
|-&lt;br /&gt;
|pickupaudiorms&lt;br /&gt;
|par&lt;br /&gt;
| -&lt;br /&gt;
|Returns the RMS amplitude of the current audio signal&lt;br /&gt;
|}&lt;br /&gt;
The Ekdahl FAR also contains the following &#039;&#039;modules&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|bowingwheel&lt;br /&gt;
|bw&lt;br /&gt;
|-&lt;br /&gt;
|mute&lt;br /&gt;
|mu&lt;br /&gt;
|-&lt;br /&gt;
|solenoid&lt;br /&gt;
|so&lt;br /&gt;
|-&lt;br /&gt;
|controlbox&lt;br /&gt;
|cb&lt;br /&gt;
|-&lt;br /&gt;
|midiconfigurationhandler&lt;br /&gt;
|mcf&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;bowingwheel&amp;quot; module ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;Bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; contains everything needed to interface with a single &#039;&#039;bowing wheel&#039;&#039;. Each &#039;&#039;bowing wheel&#039;&#039; has its own harmonic series, pressure actuators and direct hardware interface. It contains the following &#039;&#039;commands&#039;&#039;.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|speedmode&lt;br /&gt;
|sm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Bow motor speed mode, 0 = Automatic and 1 = Manual. Automatic mode means that the bowing wheel will automatically turn off after the &#039;&#039;motor timeout&#039;&#039; has been reached after being put into rest mode&lt;br /&gt;
|-&lt;br /&gt;
|motortimeout&lt;br /&gt;
|mt&lt;br /&gt;
|ms&lt;br /&gt;
|Bow motor shutdown timeout after bow having been put into the rest position&lt;br /&gt;
|-&lt;br /&gt;
|pidenable&lt;br /&gt;
|pe&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets the bow PID on/off&lt;br /&gt;
|-&lt;br /&gt;
|motorfaultcommands&lt;br /&gt;
|mfc&lt;br /&gt;
|commands&lt;br /&gt;
|Commands to execute when a motor fault is tripped - !WARNING! Can ruin your instrument if changed&lt;br /&gt;
|-&lt;br /&gt;
|motoroverpowercommands&lt;br /&gt;
|moc&lt;br /&gt;
|commands&lt;br /&gt;
|Commands to execute when motor is over the power limit - !WARNING! Can ruin your instrument if changed&lt;br /&gt;
|}&lt;br /&gt;
The &#039;&#039;modules&#039;&#039; in the &amp;quot;Bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; are as follows&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|bowpressure&lt;br /&gt;
|bp&lt;br /&gt;
|-&lt;br /&gt;
|harmonicserieshandler&lt;br /&gt;
|hsh&lt;br /&gt;
|-&lt;br /&gt;
|dcmotor&lt;br /&gt;
|dcm&lt;br /&gt;
|-&lt;br /&gt;
|pid&lt;br /&gt;
|pid&lt;br /&gt;
|}&lt;br /&gt;
The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; handles the &#039;&#039;pressure&#039;&#039; of the &#039;&#039;bowing wheel&#039;&#039; against the string. The &amp;quot;bowpressure&amp;quot;-&#039;&#039;module&#039;&#039; has the following &#039;&#039;commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|baseline&lt;br /&gt;
|ba&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure baseline, modulation is added to this point upward. Typically this is set with a knob on the &#039;&#039;control box&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|modifier&lt;br /&gt;
|mo&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure modulation, added to the baseline&lt;br /&gt;
|-&lt;br /&gt;
|rest&lt;br /&gt;
|rs&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the bow pressure in the &#039;&#039;rest&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|engage&lt;br /&gt;
|en&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the bow pressure in the &#039;&#039;engage&#039;&#039; position, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|stallpressure&lt;br /&gt;
|sp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure stall/maximum position, this parameter is set using &#039;&#039;hardware positioning&#039;&#039; and is used as the absolute maximum for baseline and modifier combiner&lt;br /&gt;
|-&lt;br /&gt;
|engagepressure&lt;br /&gt;
|ep&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure touch/minimum position, this parameter is set using &#039;&#039;hardware position&#039;&#039; and is used as the starting point for when both the baseline and modifier is set to zero&lt;br /&gt;
|-&lt;br /&gt;
|restpressure&lt;br /&gt;
|rp&lt;br /&gt;
|0-65535&lt;br /&gt;
|Bow pressure rest position, this parameter is set using &#039;&#039;hardware positioning&#039;&#039; and is typically set to a point just below the string where it does not touch at all. The purpose of this is because while the actual hardware might be able to make the bow go even lower, that position might be far enough from the string that once &#039;&#039;engaged&#039;&#039; the bow may have so far to travel that there is perceptible &#039;&#039;latency&#039;&#039;.&lt;br /&gt;
|-&lt;br /&gt;
|engagespeed&lt;br /&gt;
|es&lt;br /&gt;
|1- ~100&lt;br /&gt;
|Bow pressure movement speed when engaging or disengaging&lt;br /&gt;
|-&lt;br /&gt;
|modulationspeed&lt;br /&gt;
|ms&lt;br /&gt;
|0.1 - 10&lt;br /&gt;
|Bow pressure movement speed while engaged&lt;br /&gt;
|-&lt;br /&gt;
|hold&lt;br /&gt;
|hd&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets bow hold (infinite sustain) on/off, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|home&lt;br /&gt;
|hm&lt;br /&gt;
| -&lt;br /&gt;
|Homing bow, used at startup and in case of the bow loosing position&lt;br /&gt;
|-&lt;br /&gt;
|tmcinfo&lt;br /&gt;
|tmi&lt;br /&gt;
| -&lt;br /&gt;
|Request statistical information from the TMC2209 stepper motor driver&lt;br /&gt;
|}&lt;br /&gt;
Note that the &amp;quot;stall&amp;quot;, &amp;quot;engage&amp;quot; and &amp;quot;rest&amp;quot;-pressure positions mention something called &#039;&#039;hardware position&#039;&#039;. This means the entire available movement of the &#039;&#039;bowing jack&#039;&#039;. Because the very bottom and top end of the movement might not be musically useful and may even harm the instrument, the &amp;quot;baseline&amp;quot; and &amp;quot;modifier&amp;quot; commands &#039;&#039;parameter&#039;&#039;s are scaled depending on these settings.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;engage&amp;quot; and &amp;quot;modulation&amp;quot;-speed settings sets how fast the stepper motor that drives the &#039;&#039;pressure&#039;&#039; moves depending on whether the &#039;&#039;bowing jack&#039;&#039; is set to &#039;&#039;engage&#039;&#039; or not. The idea here is that while wanting to be able to minimize &#039;&#039;latency&#039;&#039; by &#039;&#039;engaging&#039;&#039; and &#039;&#039;disengaging&#039;&#039; from the string as quickly as possible, dynamic changes in the &#039;&#039;pressure&#039;&#039; while playing benefits from much smoother movements as the &#039;&#039;bowing wheel&#039;&#039; takes some time to catch up to varying amounts of friction.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;dcmotor&amp;quot;-&#039;&#039;module&#039;&#039; handles the direct &amp;lt;u&amp;gt;raw&amp;lt;/u&amp;gt; control of the&lt;/div&gt;</summary>
		<author><name>Knaadmin</name></author>
	</entry>
	<entry>
		<id>http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_reference_V1.1&amp;diff=1671</id>
		<title>The Ekdahl FAR - Command reference V1.1</title>
		<link rel="alternate" type="text/html" href="http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_reference_V1.1&amp;diff=1671"/>
		<updated>2026-06-12T12:44:53Z</updated>

		<summary type="html">&lt;p&gt;Knaadmin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
The Ekdahl FAR V1.1 introduces the concept of &#039;&#039;modules&#039;&#039;. A &#039;&#039;module&#039;&#039; can contain any number of &#039;&#039;commands&#039;&#039; as well as other &#039;&#039;modules&#039;&#039;. Furthermore any number of &#039;&#039;modules&#039;&#039; of the same type can exist within a context, these are addressed using classic C-style array &#039;&#039;indexing&#039;&#039; with the help of brackets (&amp;quot;[ ]&amp;quot;). Extending on the classic usage, multiple &#039;&#039;indexes&#039;&#039; can be addressed simultaneously by either comma-separating the objects (&amp;quot;[0,3,4]&amp;quot;) and using &#039;&#039;ranges&#039;&#039; (&amp;quot;[3-6]&amp;quot;). &#039;&#039;Modules&#039;&#039; can be either &#039;&#039;internal&#039;&#039; or &#039;&#039;external&#039;&#039;, meaning that they may all physically exist within a single hardware object, or they can be be remote-controlled devices. From a user perspective this however makes no difference as they will appear the same.&lt;br /&gt;
&lt;br /&gt;
While all &#039;&#039;modules&#039;&#039; have their own set of &#039;&#039;commands&#039;&#039;, there are certain &#039;&#039;commands&#039;&#039; that all &#039;&#039;modules&#039;&#039; &amp;lt;u&amp;gt;must&amp;lt;/u&amp;gt; implement and can thus be accessed anywhere within the &#039;&#039;module hierarchy.&#039;&#039; There are also &#039;&#039;base commands&#039;&#039; that always exist within any given FAR ecosystem as well as product-specific &#039;&#039;base commands&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Basic commands ==&lt;br /&gt;
The &#039;&#039;module commands&#039;&#039; that are &amp;lt;u&amp;gt;required&amp;lt;/u&amp;gt; to be implemented in &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; &#039;&#039;modules&#039;&#039; and that can thus be accessed from anywhere are&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|list&lt;br /&gt;
|ls&lt;br /&gt;
|hidden/h:modules/m:commands/c:instances/i:instancecounts/ic:recursive/r&lt;br /&gt;
|Lists all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039; under the current module depending on the parameters given; &#039;hidden&#039; includes normally hidden &#039;&#039;commands&#039;&#039;, &#039;modules&#039; includes any &#039;&#039;submodules&#039;&#039;, &#039;commands&#039; shows &#039;&#039;commands&#039;&#039;, &#039;instances&#039; shows data for each individual instance of a &#039;&#039;module&#039;&#039;, &#039;instancecounts&#039; includes number of instances of each &#039;&#039;module&#039;&#039;, &#039;recursive&#039; lists all child &#039;&#039;modules&#039;&#039; / &#039;&#039;commands&#039;&#039;. No parameters defaults to showing all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039; recursively with instance counts. It doesn&#039;t show per-instance data or hidden commands.&lt;br /&gt;
|-&lt;br /&gt;
|help&lt;br /&gt;
|help&lt;br /&gt;
|recursive/r&lt;br /&gt;
|Shows a brief explanation of all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039;, shows the help for all &#039;&#039;submodules&#039;&#039; as well if &#039;recursive&#039;&lt;br /&gt;
|-&lt;br /&gt;
|dumpdata&lt;br /&gt;
|dump&lt;br /&gt;
|recursive/r&lt;br /&gt;
|Dumps all data saved for the current &#039;&#039;module&#039;&#039;, will list the data of all &#039;&#039;submodules&#039;&#039; as well if &#039;recursive&#039;&lt;br /&gt;
|}&lt;br /&gt;
The &#039;&#039;base commands&#039;&#039; are as follows&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|version&lt;br /&gt;
|ver&lt;br /&gt;
| -&lt;br /&gt;
|Gets the current firmware version&lt;br /&gt;
|-&lt;br /&gt;
|debugprint&lt;br /&gt;
|dp&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;command|usb|hardware|undefined|priority|error|inforequest|expressionparser|debug:1|0&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Turns on or off serial feedback for the given item&lt;br /&gt;
|-&lt;br /&gt;
|requestinfo&lt;br /&gt;
|rqi&lt;br /&gt;
|command&lt;br /&gt;
|Retrives any data saved for a &#039;&#039;command&#039;&#039;, if applicable&lt;br /&gt;
|-&lt;br /&gt;
|saveallparameters&lt;br /&gt;
|sap&lt;br /&gt;
| -&lt;br /&gt;
|Saves all avaliable parameters&lt;br /&gt;
|-&lt;br /&gt;
|loadallparameters&lt;br /&gt;
|lap&lt;br /&gt;
| -&lt;br /&gt;
|Loads all avaliable parameters&lt;br /&gt;
|-&lt;br /&gt;
|resetallparameters&lt;br /&gt;
|rap&lt;br /&gt;
| -&lt;br /&gt;
|Resets all saved parameters&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|rst&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;1|0&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Resets the Ekdahl FAR, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|nick&lt;br /&gt;
|nick&lt;br /&gt;
|name&lt;br /&gt;
|Sets the nickname of this unit&lt;br /&gt;
|-&lt;br /&gt;
|nooperation&lt;br /&gt;
|nop&lt;br /&gt;
| -&lt;br /&gt;
|Do absolutely, positively, nothing. Useful for testing and interfacing with computers, it&#039;s a good way to know that the unit is alive and responding since a &amp;quot;nop&amp;quot; is being returned as a response upon reception.&lt;br /&gt;
|-&lt;br /&gt;
|uservariable&lt;br /&gt;
|uv&lt;br /&gt;
|variable(0-9):value&lt;br /&gt;
|Set user variable 0-9 to &#039;value&#039;&lt;br /&gt;
|-&lt;br /&gt;
|expressionparserevaluate&lt;br /&gt;
|epev&lt;br /&gt;
|expression&lt;br /&gt;
|Evaluates an arithmetric expression and sends back the output, all variables and functions that can be used in any &#039;&#039;command string&#039;&#039; can also be used here. Useful for testing expressions.&lt;br /&gt;
|-&lt;br /&gt;
|ifequal&lt;br /&gt;
|ife&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] EQUALS [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring].&lt;br /&gt;
|-&lt;br /&gt;
|ifgreater&lt;br /&gt;
|ifg&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] &amp;gt; [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring]&lt;br /&gt;
|-&lt;br /&gt;
|ifless&lt;br /&gt;
|ifl&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] &amp;lt; [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring]&lt;br /&gt;
|-&lt;br /&gt;
|freeram&lt;br /&gt;
|ram&lt;br /&gt;
| -&lt;br /&gt;
|Shows free RAM memory&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The base also contains the following &#039;&#039;modules:&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|pluginhandler&lt;br /&gt;
|ph&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The Ekdahl FAR stand alone single string unit ==&lt;br /&gt;
The Ekdahl FAR stand-alone single string unit offers these &#039;&#039;commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|calibrateall&lt;br /&gt;
|ca&lt;br /&gt;
| -&lt;br /&gt;
|Performs all calibration routines on the selected bow, see below for routines performed&lt;br /&gt;
|-&lt;br /&gt;
|calibratebowspeed&lt;br /&gt;
|cbs&lt;br /&gt;
| -&lt;br /&gt;
|Finds the minimum and maximum bow speed of the selected bow&lt;br /&gt;
|-&lt;br /&gt;
|calibratebowpressure&lt;br /&gt;
|cbp&lt;br /&gt;
| -&lt;br /&gt;
|Finds the minimum and maximum bow pressure of the selected bow&lt;br /&gt;
|-&lt;br /&gt;
|calibratemute&lt;br /&gt;
|cmu&lt;br /&gt;
| -&lt;br /&gt;
|Calibrate mute settings&lt;br /&gt;
|-&lt;br /&gt;
|pickupstringfrequency&lt;br /&gt;
|psf&lt;br /&gt;
| -&lt;br /&gt;
|Returns the fundamental tone calculated from the current audio signal if apliccable&lt;br /&gt;
|-&lt;br /&gt;
|pickupaudiopeak&lt;br /&gt;
|pap&lt;br /&gt;
| -&lt;br /&gt;
|Returns the peak amplitude of the current audio signal&lt;br /&gt;
|-&lt;br /&gt;
|pickupaudiorms&lt;br /&gt;
|par&lt;br /&gt;
| -&lt;br /&gt;
|Returns the RMS amplitude of the current audio signal&lt;br /&gt;
|}&lt;br /&gt;
The Ekdahl FAR also contains the following &#039;&#039;modules&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|bowingwheel&lt;br /&gt;
|bw&lt;br /&gt;
|-&lt;br /&gt;
|mute&lt;br /&gt;
|mu&lt;br /&gt;
|-&lt;br /&gt;
|solenoid&lt;br /&gt;
|so&lt;br /&gt;
|-&lt;br /&gt;
|controlbox&lt;br /&gt;
|cb&lt;br /&gt;
|-&lt;br /&gt;
|midiconfigurationhandler&lt;br /&gt;
|mcf&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The &amp;quot;bowingwheel&amp;quot; module ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;Bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; contains everything needed to interface with a single &#039;&#039;bowing wheel&#039;&#039;. Each &#039;&#039;bowing wheel&#039;&#039; has its own harmonic series, pressure actuators and direct hardware interface. It contains the following &#039;&#039;commands&#039;&#039;.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|speedmode&lt;br /&gt;
|sm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Bow motor speed mode, 0 = Automatic and 1 = Manual. Automatic mode means that the bowing wheel will automatically turn off after the &#039;&#039;motor timeout&#039;&#039; has been reached after being put into rest mode&lt;br /&gt;
|-&lt;br /&gt;
|motortimeout&lt;br /&gt;
|mt&lt;br /&gt;
|ms&lt;br /&gt;
|Bow motor shutdown timeout after bow having been put into the rest position&lt;br /&gt;
|-&lt;br /&gt;
|pidenable&lt;br /&gt;
|pe&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;0|1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets the bow PID on/off&lt;br /&gt;
|-&lt;br /&gt;
|motorfaultcommands&lt;br /&gt;
|mfc&lt;br /&gt;
|commands&lt;br /&gt;
|Commands to execute when a motor fault is tripped - !WARNING! Can ruin your instrument if changed&lt;br /&gt;
|-&lt;br /&gt;
|motoroverpowercommands&lt;br /&gt;
|moc&lt;br /&gt;
|commands&lt;br /&gt;
|Commands to execute when motor is over the power limit - !WARNING! Can ruin your instrument if changed&lt;br /&gt;
|}&lt;br /&gt;
The &#039;&#039;modules&#039;&#039; in the &amp;quot;Bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; are as follows&lt;/div&gt;</summary>
		<author><name>Knaadmin</name></author>
	</entry>
	<entry>
		<id>http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_reference_V1.1&amp;diff=1670</id>
		<title>The Ekdahl FAR - Command reference V1.1</title>
		<link rel="alternate" type="text/html" href="http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_reference_V1.1&amp;diff=1670"/>
		<updated>2026-06-12T12:07:20Z</updated>

		<summary type="html">&lt;p&gt;Knaadmin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
The Ekdahl FAR V1.1 introduces the concept of &#039;&#039;modules&#039;&#039;. A &#039;&#039;module&#039;&#039; can contain any number of &#039;&#039;commands&#039;&#039; as well as other &#039;&#039;modules&#039;&#039;. Furthermore any number of &#039;&#039;modules&#039;&#039; of the same type can exist within a context, these are addressed using classic C-style array &#039;&#039;indexing&#039;&#039; with the help of brackets (&amp;quot;[ ]&amp;quot;). Extending on the classic usage, multiple &#039;&#039;indexes&#039;&#039; can be addressed simultaneously by either comma-separating the objects (&amp;quot;[0,3,4]&amp;quot;) and using &#039;&#039;ranges&#039;&#039; (&amp;quot;[3-6]&amp;quot;). &#039;&#039;Modules&#039;&#039; can be either &#039;&#039;internal&#039;&#039; or &#039;&#039;external&#039;&#039;, meaning that they may all physically exist within a single hardware object, or they can be be remote-controlled devices. From a user perspective this however makes no difference as they will appear the same.&lt;br /&gt;
&lt;br /&gt;
While all &#039;&#039;modules&#039;&#039; have their own set of &#039;&#039;commands&#039;&#039;, there are certain &#039;&#039;commands&#039;&#039; that all &#039;&#039;modules&#039;&#039; &amp;lt;u&amp;gt;must&amp;lt;/u&amp;gt; implement and can thus be accessed anywhere within the &#039;&#039;module hierarchy.&#039;&#039; There are also &#039;&#039;base commands&#039;&#039; that always exist within any given FAR ecosystem as well as product-specific &#039;&#039;base commands&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;module commands&#039;&#039; that are &amp;lt;u&amp;gt;required&amp;lt;/u&amp;gt; to be implemented in &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; &#039;&#039;modules&#039;&#039; and that can thus be accessed from anywhere are&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|list&lt;br /&gt;
|ls&lt;br /&gt;
|hidden/h:modules/m:commands/c:instances/i:instancecounts/ic:recursive/r&lt;br /&gt;
|Lists all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039; under the current module depending on the parameters given; &#039;hidden&#039; includes normally hidden &#039;&#039;commands&#039;&#039;, &#039;modules&#039; includes any &#039;&#039;submodules&#039;&#039;, &#039;commands&#039; shows &#039;&#039;commands&#039;&#039;, &#039;instances&#039; shows data for each individual instance of a &#039;&#039;module&#039;&#039;, &#039;instancecounts&#039; includes number of instances of each &#039;&#039;module&#039;&#039;, &#039;recursive&#039; lists all child &#039;&#039;modules&#039;&#039; / &#039;&#039;commands&#039;&#039;. No parameters defaults to showing all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039; recursively with instance counts. It doesn&#039;t show per-instance data or hidden commands.&lt;br /&gt;
|-&lt;br /&gt;
|help&lt;br /&gt;
|help&lt;br /&gt;
|recursive/r&lt;br /&gt;
|Shows a brief explanation of all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039;, shows the help for all &#039;&#039;submodules&#039;&#039; as well if &#039;recursive&#039;&lt;br /&gt;
|-&lt;br /&gt;
|dumpdata&lt;br /&gt;
|dump&lt;br /&gt;
|recursive/r&lt;br /&gt;
|Dumps all data saved for the current &#039;&#039;module&#039;&#039;, will list the data of all &#039;&#039;submodules&#039;&#039; as well if &#039;recursive&#039;&lt;br /&gt;
|}&lt;br /&gt;
The &#039;&#039;base commands&#039;&#039; are as follows&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|version&lt;br /&gt;
|ver&lt;br /&gt;
| -&lt;br /&gt;
|Gets the current firmware version&lt;br /&gt;
|-&lt;br /&gt;
|debugprint&lt;br /&gt;
|dp&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;command|usb|hardware|undefined|priority|error|inforequest|expressionparser|debug:1|0&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Turns on or off serial feedback for the given item&lt;br /&gt;
|-&lt;br /&gt;
|requestinfo&lt;br /&gt;
|rqi&lt;br /&gt;
|command&lt;br /&gt;
|Retrives any data saved for a &#039;&#039;command&#039;&#039;, if applicable&lt;br /&gt;
|-&lt;br /&gt;
|saveallparameters&lt;br /&gt;
|sap&lt;br /&gt;
| -&lt;br /&gt;
|Saves all avaliable parameters&lt;br /&gt;
|-&lt;br /&gt;
|loadallparameters&lt;br /&gt;
|lap&lt;br /&gt;
| -&lt;br /&gt;
|Loads all avaliable parameters&lt;br /&gt;
|-&lt;br /&gt;
|resetallparameters&lt;br /&gt;
|rap&lt;br /&gt;
| -&lt;br /&gt;
|Resets all saved parameters&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|rst&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;1|0&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Resets the Ekdahl FAR, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|nick&lt;br /&gt;
|nick&lt;br /&gt;
|name&lt;br /&gt;
|Sets the nickname of this unit&lt;br /&gt;
|-&lt;br /&gt;
|nooperation&lt;br /&gt;
|nop&lt;br /&gt;
| -&lt;br /&gt;
|Do absolutely, positively, nothing. Useful for testing and interfacing with computers, it&#039;s a good way to know that the unit is alive and responding since a &amp;quot;nop&amp;quot; is being returned as a response upon reception.&lt;br /&gt;
|-&lt;br /&gt;
|uservariable&lt;br /&gt;
|uv&lt;br /&gt;
|variable(0-9):value&lt;br /&gt;
|Set user variable 0-9 to &#039;value&#039;&lt;br /&gt;
|-&lt;br /&gt;
|expressionparserevaluate&lt;br /&gt;
|epev&lt;br /&gt;
|expression&lt;br /&gt;
|Evaluates an arithmetric expression and sends back the output, all variables and functions that can be used in any &#039;&#039;command string&#039;&#039; can also be used here. Useful for testing expressions.&lt;br /&gt;
|-&lt;br /&gt;
|ifequal&lt;br /&gt;
|ife&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] EQUALS [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring].&lt;br /&gt;
|-&lt;br /&gt;
|ifgreater&lt;br /&gt;
|ifg&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] &amp;gt; [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring]&lt;br /&gt;
|-&lt;br /&gt;
|ifless&lt;br /&gt;
|ifl&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] &amp;lt; [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring]&lt;br /&gt;
|-&lt;br /&gt;
|freeram&lt;br /&gt;
|ram&lt;br /&gt;
| -&lt;br /&gt;
|Shows free RAM memory&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The base also contains the following &#039;&#039;modules:&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
|-&lt;br /&gt;
|pluginhandler&lt;br /&gt;
|ph&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The Ekdahl FAR stand-alone single string unit offers these &#039;&#039;commands&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|calibrateall&lt;br /&gt;
|ca&lt;br /&gt;
| -&lt;br /&gt;
|Performs all calibration routines on the selected bow, see below for routines performed&lt;br /&gt;
|-&lt;br /&gt;
|calibratebowspeed&lt;br /&gt;
|cbs&lt;br /&gt;
| -&lt;br /&gt;
|Finds the minimum and maximum bow speed of the selected bow&lt;br /&gt;
|-&lt;br /&gt;
|calibratebowpressure&lt;br /&gt;
|cbp&lt;br /&gt;
| -&lt;br /&gt;
|Finds the minimum and maximum bow pressure of the selected bow&lt;br /&gt;
|-&lt;br /&gt;
|calibratemute&lt;br /&gt;
|cmu&lt;br /&gt;
| -&lt;br /&gt;
|Calibrate mute settings&lt;br /&gt;
|-&lt;br /&gt;
|pickupstringfrequency&lt;br /&gt;
|psf&lt;br /&gt;
| -&lt;br /&gt;
|Returns the fundamental tone calculated from the current audio signal if apliccable&lt;br /&gt;
|-&lt;br /&gt;
|pickupaudiopeak&lt;br /&gt;
|pap&lt;br /&gt;
| -&lt;br /&gt;
|Returns the peak amplitude of the current audio signal&lt;br /&gt;
|-&lt;br /&gt;
|pickupaudiorms&lt;br /&gt;
|par&lt;br /&gt;
| -&lt;br /&gt;
|Returns the RMS amplitude of the current audio signal&lt;br /&gt;
|}&lt;br /&gt;
The Ekdahl FAR also contains the following &#039;&#039;modules&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Knaadmin</name></author>
	</entry>
	<entry>
		<id>http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_reference_V1.1&amp;diff=1669</id>
		<title>The Ekdahl FAR - Command reference V1.1</title>
		<link rel="alternate" type="text/html" href="http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_reference_V1.1&amp;diff=1669"/>
		<updated>2026-06-12T11:55:23Z</updated>

		<summary type="html">&lt;p&gt;Knaadmin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
The Ekdahl FAR V1.1 introduces the concept of &#039;&#039;modules&#039;&#039;. A &#039;&#039;module&#039;&#039; can contain any number of &#039;&#039;commands&#039;&#039; as well as other &#039;&#039;modules&#039;&#039;. Furthermore any number of &#039;&#039;modules&#039;&#039; of the same type can exist within a context, these are addressed using classic C-style array &#039;&#039;indexing&#039;&#039; with the help of brackets (&amp;quot;[ ]&amp;quot;). Extending on the classic usage, multiple &#039;&#039;indexes&#039;&#039; can be addressed simultaneously by either comma-separating the objects (&amp;quot;[0,3,4]&amp;quot;) and using &#039;&#039;ranges&#039;&#039; (&amp;quot;[3-6]&amp;quot;). &#039;&#039;Modules&#039;&#039; can be either &#039;&#039;internal&#039;&#039; or &#039;&#039;external&#039;&#039;, meaning that they may all physically exist within a single hardware object, or they can be be remote-controlled devices. From a user perspective this however makes no difference as they will appear the same.&lt;br /&gt;
&lt;br /&gt;
While all &#039;&#039;modules&#039;&#039; have their own set of &#039;&#039;commands&#039;&#039;, there are certain &#039;&#039;commands&#039;&#039; that all &#039;&#039;modules&#039;&#039; &amp;lt;u&amp;gt;must&amp;lt;/u&amp;gt; implement and can thus be accessed anywhere within the &#039;&#039;module hierarchy.&#039;&#039; There are also &#039;&#039;base commands&#039;&#039; that always exist within any given FAR ecosystem as well as product-specific &#039;&#039;base commands&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;module commands&#039;&#039; that are &amp;lt;u&amp;gt;required&amp;lt;/u&amp;gt; to be implemented in &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; &#039;&#039;modules&#039;&#039; and that can thus be accessed from anywhere are&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|list&lt;br /&gt;
|ls&lt;br /&gt;
|hidden/h:modules/m:commands/c:instances/i:instancecounts/ic:recursive/r&lt;br /&gt;
|Lists all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039; under the current module depending on the parameters given; &#039;hidden&#039; includes normally hidden &#039;&#039;commands&#039;&#039;, &#039;modules&#039; includes any &#039;&#039;submodules&#039;&#039;, &#039;commands&#039; shows &#039;&#039;commands&#039;&#039;, &#039;instances&#039; shows data for each individual instance of a &#039;&#039;module&#039;&#039;, &#039;instancecounts&#039; includes number of instances of each &#039;&#039;module&#039;&#039;, &#039;recursive&#039; lists all child &#039;&#039;modules&#039;&#039; / &#039;&#039;commands&#039;&#039;. No parameters defaults to showing all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039; recursively with instance counts. It doesn&#039;t show per-instance data or hidden commands.&lt;br /&gt;
|-&lt;br /&gt;
|help&lt;br /&gt;
|help&lt;br /&gt;
|recursive/r&lt;br /&gt;
|Shows a brief explanation of all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039;, shows the help for all &#039;&#039;submodules&#039;&#039; as well if &#039;recursive&#039;&lt;br /&gt;
|-&lt;br /&gt;
|dumpdata&lt;br /&gt;
|dump&lt;br /&gt;
|recursive/r&lt;br /&gt;
|Dumps all data saved for the current &#039;&#039;module&#039;&#039;, will list the data of all &#039;&#039;submodules&#039;&#039; as well if &#039;recursive&#039;&lt;br /&gt;
|}&lt;br /&gt;
The &#039;&#039;base commands&#039;&#039; are as follows&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|version&lt;br /&gt;
|ver&lt;br /&gt;
| -&lt;br /&gt;
|Gets the current firmware version&lt;br /&gt;
|-&lt;br /&gt;
|debugprint&lt;br /&gt;
|dp&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;command|usb|hardware|undefined|priority|error|inforequest|expressionparser|debug:1|0&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Turns on or off serial feedback for the given item&lt;br /&gt;
|-&lt;br /&gt;
|requestinfo&lt;br /&gt;
|rqi&lt;br /&gt;
|command&lt;br /&gt;
|Retrives any data saved for a &#039;&#039;command&#039;&#039;, if applicable&lt;br /&gt;
|-&lt;br /&gt;
|saveallparameters&lt;br /&gt;
|sap&lt;br /&gt;
| -&lt;br /&gt;
|Saves all avaliable parameters&lt;br /&gt;
|-&lt;br /&gt;
|loadallparameters&lt;br /&gt;
|lap&lt;br /&gt;
| -&lt;br /&gt;
|Loads all avaliable parameters&lt;br /&gt;
|-&lt;br /&gt;
|resetallparameters&lt;br /&gt;
|rap&lt;br /&gt;
| -&lt;br /&gt;
|Resets all saved parameters&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|rst&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;1|0&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Resets the Ekdahl FAR, &#039;&#039;conditional&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|nick&lt;br /&gt;
|nick&lt;br /&gt;
|name&lt;br /&gt;
|Sets the nickname of this unit&lt;br /&gt;
|-&lt;br /&gt;
|nooperation&lt;br /&gt;
|nop&lt;br /&gt;
| -&lt;br /&gt;
|Do absolutely, positively, nothing. Useful for testing and interfacing with computers, it&#039;s a good way to know that the unit is alive and responding since a &amp;quot;nop&amp;quot; is being returned as a response upon reception.&lt;br /&gt;
|-&lt;br /&gt;
|uservariable&lt;br /&gt;
|uv&lt;br /&gt;
|variable(0-9):value&lt;br /&gt;
|Set user variable 0-9 to &#039;value&#039;&lt;br /&gt;
|-&lt;br /&gt;
|expressionparserevaluate&lt;br /&gt;
|epev&lt;br /&gt;
|expression&lt;br /&gt;
|Evaluates an arithmetric expression and sends back the output, all variables and functions that can be used in any &#039;&#039;command string&#039;&#039; can also be used here.&lt;br /&gt;
|-&lt;br /&gt;
|ifequal&lt;br /&gt;
|ife&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] EQUALS [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring].&lt;br /&gt;
|-&lt;br /&gt;
|ifgreater&lt;br /&gt;
|ifg&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] &amp;gt; [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring]&lt;br /&gt;
|-&lt;br /&gt;
|ifless&lt;br /&gt;
|ifl&lt;br /&gt;
|variable:comparator:truecommandstring:elsecommandstring&lt;br /&gt;
|Performs [IF [variable] &amp;lt; [comparator]] then add [truecommandstring] to the que if TRUE, otherwise add [elsecommandstring]&lt;br /&gt;
|-&lt;br /&gt;
|freeram&lt;br /&gt;
|ram&lt;br /&gt;
| -&lt;br /&gt;
|Shows free RAM memory&lt;br /&gt;
|}&lt;br /&gt;
The Ekdahl FAR stand-alone single string unit offers these &#039;&#039;commands&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Knaadmin</name></author>
	</entry>
	<entry>
		<id>http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_reference_V1.1&amp;diff=1668</id>
		<title>The Ekdahl FAR - Command reference V1.1</title>
		<link rel="alternate" type="text/html" href="http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_reference_V1.1&amp;diff=1668"/>
		<updated>2026-06-12T11:40:18Z</updated>

		<summary type="html">&lt;p&gt;Knaadmin: /* Introduction */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
The Ekdahl FAR V1.1 introduces the concept of &#039;&#039;modules&#039;&#039;. A &#039;&#039;module&#039;&#039; can contain any number of &#039;&#039;commands&#039;&#039; as well as other &#039;&#039;modules&#039;&#039;. Furthermore any number of &#039;&#039;modules&#039;&#039; of the same type can exist within a context, these are addressed using classic C-style array &#039;&#039;indexing&#039;&#039; with the help of brackets (&amp;quot;[ ]&amp;quot;). Extending on the classic usage, multiple &#039;&#039;indexes&#039;&#039; can be addressed simultaneously by either comma-separating the objects (&amp;quot;[0,3,4]&amp;quot;) and using &#039;&#039;ranges&#039;&#039; (&amp;quot;[3-6]&amp;quot;). &#039;&#039;Modules&#039;&#039; can be either &#039;&#039;internal&#039;&#039; or &#039;&#039;external&#039;&#039;, meaning that they may all physically exist within a single hardware object, or they can be be remote-controlled devices. From a user perspective this however makes no difference as they will appear the same.&lt;br /&gt;
&lt;br /&gt;
While all &#039;&#039;modules&#039;&#039; have their own set of &#039;&#039;commands&#039;&#039;, there are certain &#039;&#039;commands&#039;&#039; that all &#039;&#039;modules&#039;&#039; &amp;lt;u&amp;gt;must&amp;lt;/u&amp;gt; implement and can thus be accessed anywhere within the &#039;&#039;module hierarchy.&#039;&#039; There are also &#039;&#039;global commands&#039;&#039; that always exist within any given FAR ecosystem as well as product-specific &#039;&#039;global commands&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;module commands&#039;&#039; that are &amp;lt;u&amp;gt;required&amp;lt;/u&amp;gt; to be implemented in &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; &#039;&#039;modules&#039;&#039; and that can thus be accessed from anywhere are&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|list&lt;br /&gt;
|ls&lt;br /&gt;
|hidden/h:modules/m:commands/c:instances/i:instancecounts/ic:recursive/r&lt;br /&gt;
|Lists all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039; under the current module depending on the parameters given; &#039;hidden&#039; includes normally hidden &#039;&#039;commands&#039;&#039;, &#039;modules&#039; includes any &#039;&#039;submodules&#039;&#039;, &#039;commands&#039; shows &#039;&#039;commands&#039;&#039;, &#039;instances&#039; shows data for each individual instance of a &#039;&#039;module&#039;&#039;, &#039;instancecounts&#039; includes number of instances of each &#039;&#039;module&#039;&#039;, &#039;recursive&#039; lists all child &#039;&#039;modules&#039;&#039; / &#039;&#039;commands&#039;&#039;. No parameters defaults to showing all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039; recursively with instance counts. It doesn&#039;t show per-instance data or hidden commands.&lt;br /&gt;
|-&lt;br /&gt;
|help&lt;br /&gt;
|help&lt;br /&gt;
|recursive/r&lt;br /&gt;
|Shows a brief explanation of all &#039;&#039;commands&#039;&#039; and &#039;&#039;modules&#039;&#039;, shows the help for all &#039;&#039;submodules&#039;&#039; as well if &#039;recursive&#039;&lt;br /&gt;
|-&lt;br /&gt;
|dumpdata&lt;br /&gt;
|dump&lt;br /&gt;
|recursive/r&lt;br /&gt;
|Dumps all data to be saved for the current &#039;&#039;module&#039;&#039;, will list the data of all &#039;&#039;submodules&#039;&#039; as well if &#039;recursive&#039;&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Knaadmin</name></author>
	</entry>
	<entry>
		<id>http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_reference_V1.1&amp;diff=1667</id>
		<title>The Ekdahl FAR - Command reference V1.1</title>
		<link rel="alternate" type="text/html" href="http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_reference_V1.1&amp;diff=1667"/>
		<updated>2026-06-12T11:05:30Z</updated>

		<summary type="html">&lt;p&gt;Knaadmin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
The Ekdahl FAR V1.1 introduces the concept of &#039;&#039;modules&#039;&#039;. A &#039;&#039;module&#039;&#039; can contain any number of &#039;&#039;commands&#039;&#039; as well as other &#039;&#039;modules&#039;&#039;. Furthermore any number of &#039;&#039;modules&#039;&#039; of the same type can exist within a context, these are addressed using classic C-style array &#039;&#039;indexing&#039;&#039; with the help of brackets (&amp;quot;[ ]&amp;quot;). Extending on the classic usage, multiple &#039;&#039;indexes&#039;&#039; can be addressed simultaneously by either comma-separating the objects (&amp;quot;[0,3,4]&amp;quot;) and using &#039;&#039;ranges&#039;&#039; (&amp;quot;[3-6]&amp;quot;). &#039;&#039;Modules&#039;&#039; can be either &#039;&#039;internal&#039;&#039; or &#039;&#039;external&#039;&#039;, meaning that they may all physically exist within a single hardware object, or they can be be remote-controlled devices. From a user perspective this however makes no difference as they will appear the same.&lt;br /&gt;
&lt;br /&gt;
While all &#039;&#039;modules&#039;&#039; have their own set of &#039;&#039;commands&#039;&#039;, there are certain &#039;&#039;commands&#039;&#039; that all &#039;&#039;modules&#039;&#039; &amp;lt;u&amp;gt;must&amp;lt;/u&amp;gt; implement and can thus be accessed anywhere within the &#039;&#039;module hierarchy.&#039;&#039; There are also &#039;&#039;global commands&#039;&#039; that always exist within any given FAR ecosystem as well as product-specific &#039;&#039;global commands&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;module commands&#039;&#039; that are &amp;lt;u&amp;gt;required&amp;lt;/u&amp;gt; to be implemented in &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; &#039;&#039;modules&#039;&#039; and that can thus be accessed from anywhere are&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|requestinfo&lt;br /&gt;
|rqi&lt;br /&gt;
|[command]:[optional parameters]&lt;br /&gt;
|Uses a &#039;&#039;command&#039;&#039;-name to retrieve rather than set information associated with it, some commands have no information associated and will return nothing. Some commands require the use of optional &#039;&#039;parameters&#039;&#039; to specify which information that is to be retrieved.&lt;br /&gt;
|-&lt;br /&gt;
|module&lt;br /&gt;
|m&lt;br /&gt;
|[module number (0)]&lt;br /&gt;
|Sets the current &#039;&#039;module&#039;&#039;. This command is intended for future versions of the Ekdahl FAR that may have more than one &#039;&#039;string module.&#039;&#039; Currently &#039;0&#039; is the only valid &#039;&#039;parameter&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|modulecount&lt;br /&gt;
|mc&lt;br /&gt;
|none&lt;br /&gt;
|Returns the number of &#039;&#039;modules&#039;&#039; in the Ekdahl FAR. Currently always returns &#039;1&#039;&lt;br /&gt;
|-&lt;br /&gt;
|debugprint&lt;br /&gt;
|dp&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;[command|usb|hardware|undefined|priority|error|inforequest|expressionparser|debug]:[0|1]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Used to turn on or off whether the instrument will return certain information over &#039;&#039;USB-Serial&#039;&#039;. The first &#039;&#039;parameter&#039;&#039; is the category, the second &#039;&#039;parameter&#039;&#039; is a boolean value.&lt;br /&gt;
|-&lt;br /&gt;
|version&lt;br /&gt;
|ver&lt;br /&gt;
|none&lt;br /&gt;
|Returns the current &#039;&#039;firmware&#039;&#039; version&lt;br /&gt;
|-&lt;br /&gt;
|globalsaveallparameters&lt;br /&gt;
|gsap&lt;br /&gt;
|none&lt;br /&gt;
|Saves all current data into the internal flash memory&lt;br /&gt;
|-&lt;br /&gt;
|globalloadallparameters&lt;br /&gt;
|glap&lt;br /&gt;
|none&lt;br /&gt;
|Loads all data saved into flash, effectively overwriting any changed parameters included in the last save&lt;br /&gt;
|-&lt;br /&gt;
|globalresetparameters&lt;br /&gt;
|grap&lt;br /&gt;
|none&lt;br /&gt;
|Resets all saved data in the flash memory, requires a immediate reset to be enacted&lt;br /&gt;
|-&lt;br /&gt;
|globaluservariable&lt;br /&gt;
|guv&lt;br /&gt;
|[variable number (0-9)]:[value (float)]&lt;br /&gt;
|Sets or returns the user variable defined in the first &#039;&#039;parameter,&#039;&#039; if used to set the variable, the second &#039;&#039;parameter&#039;&#039; is the value.&lt;br /&gt;
|-&lt;br /&gt;
|expressionparserevaluate&lt;br /&gt;
|epev&lt;br /&gt;
|[expression]&lt;br /&gt;
|Evaluates the given &#039;&#039;expression&#039;&#039; and returns the calculated value. Used for debugging&lt;br /&gt;
|-&lt;br /&gt;
|testadclatency&lt;br /&gt;
|tal&lt;br /&gt;
|[value (0 - 65535)]&lt;br /&gt;
|Debugging command to test ADC latency&lt;br /&gt;
|-&lt;br /&gt;
|testadclatencyreturn&lt;br /&gt;
|talr&lt;br /&gt;
|none&lt;br /&gt;
|Stops ADC latency testing started with &#039;&#039;tal&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|testadcminmac&lt;br /&gt;
|tamm&lt;br /&gt;
|[channel]&lt;br /&gt;
|Debugging command to test the min/max value for a given &#039;&#039;channel&#039;&#039;&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Knaadmin</name></author>
	</entry>
	<entry>
		<id>http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_reference_V1.1&amp;diff=1666</id>
		<title>The Ekdahl FAR - Command reference V1.1</title>
		<link rel="alternate" type="text/html" href="http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_reference_V1.1&amp;diff=1666"/>
		<updated>2026-06-12T11:03:39Z</updated>

		<summary type="html">&lt;p&gt;Knaadmin: Created page with &amp;quot;== Introduction == The Ekdahl FAR V1.1 introduces the concept of &amp;#039;&amp;#039;modules&amp;#039;&amp;#039;. A &amp;#039;&amp;#039;module&amp;#039;&amp;#039; can contain any number of &amp;#039;&amp;#039;commands&amp;#039;&amp;#039; as well as other &amp;#039;&amp;#039;modules&amp;#039;&amp;#039;. Furthermore any number of &amp;#039;&amp;#039;modules&amp;#039;&amp;#039; of the same type can exist within a context, these are addressed using classic C-style array &amp;#039;&amp;#039;indexing&amp;#039;&amp;#039; with the help of brackets (&amp;quot;[ ]&amp;quot;). Extending on the classic usage, multiple &amp;#039;&amp;#039;indexes&amp;#039;&amp;#039; can be addressed simultaneously by either comma-separating the objects (&amp;quot;[0,3,4]&amp;quot;)...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
The Ekdahl FAR V1.1 introduces the concept of &#039;&#039;modules&#039;&#039;. A &#039;&#039;module&#039;&#039; can contain any number of &#039;&#039;commands&#039;&#039; as well as other &#039;&#039;modules&#039;&#039;. Furthermore any number of &#039;&#039;modules&#039;&#039; of the same type can exist within a context, these are addressed using classic C-style array &#039;&#039;indexing&#039;&#039; with the help of brackets (&amp;quot;[ ]&amp;quot;). Extending on the classic usage, multiple &#039;&#039;indexes&#039;&#039; can be addressed simultaneously by either comma-separating the objects (&amp;quot;[0,3,4]&amp;quot;) and using &#039;&#039;ranges&#039;&#039; (&amp;quot;[3-6]&amp;quot;). &#039;&#039;Modules&#039;&#039; can be either &#039;&#039;internal&#039;&#039; or &#039;&#039;external&#039;&#039;, meaning that they may all physically exist within a single hardware object, or they can be be remote-controlled devices. From a user perspective this however makes no difference as they will appear the same.&lt;br /&gt;
&lt;br /&gt;
While all &#039;&#039;modules&#039;&#039; have their own set of &#039;&#039;commands&#039;&#039;, there are certain &#039;&#039;commands&#039;&#039; that all &#039;&#039;modules&#039;&#039; &amp;lt;u&amp;gt;must&amp;lt;/u&amp;gt; implement and can thus be accessed anywhere within the &#039;&#039;module hierarchy.&#039;&#039; There are also &#039;&#039;global commands&#039;&#039; that always exist within any given FAR ecosystem as well as product-specific &#039;&#039;global commands&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;module commands&#039;&#039; that are &amp;lt;u&amp;gt;required&amp;lt;/u&amp;gt; to be implemented in &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; &#039;&#039;modules&#039;&#039; and that can thus be accessed from anywhere are&lt;/div&gt;</summary>
		<author><name>Knaadmin</name></author>
	</entry>
	<entry>
		<id>http://knasmusic.com/wiki/index.php?title=MediaWiki:Sidebar&amp;diff=1665</id>
		<title>MediaWiki:Sidebar</title>
		<link rel="alternate" type="text/html" href="http://knasmusic.com/wiki/index.php?title=MediaWiki:Sidebar&amp;diff=1665"/>
		<updated>2026-06-12T10:48:52Z</updated>

		<summary type="html">&lt;p&gt;Knaadmin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
* navigation&lt;br /&gt;
** https://www.knasmusic.com|Knas website&lt;br /&gt;
** https://www.knasmusic.com/forum|Forum&lt;br /&gt;
* The Ekdahl FAR&lt;br /&gt;
** The Ekdahl FAR|- Introduction&lt;br /&gt;
** The_Ekdahl_FAR_-_Getting_started|- Getting started&lt;br /&gt;
** The Ekdahl FAR - The Control box|- The Control box&lt;br /&gt;
** The Ekdahl FAR - Basic MIDI Setup|- Basic MIDI Setup&lt;br /&gt;
** The Ekdahl FAR - Tuning|- Tuning&lt;br /&gt;
** The Ekdahl FAR - Limits|- Limits&lt;br /&gt;
** The Ekdahl FAR - Calibrations|- Calibrations&lt;br /&gt;
** The Ekdahl FAR - Changing the string|- Changing the string&lt;br /&gt;
** The Ekdahl FAR - Bowing wheels|- Bowing wheels&lt;br /&gt;
** The Ekdahl FAR - Bowing jack|- The bowing jack&lt;br /&gt;
** The Ekdahl FAR - Mute|- The mute&lt;br /&gt;
** The Ekdahl FAR - Hammer|- The hammer&lt;br /&gt;
** The Ekdahl FAR - Pickup|- The pickup&lt;br /&gt;
** The Ekdahl FAR - Configuration utility - Concept and Installation|Configuration utility&lt;br /&gt;
** The Ekdahl FAR - Configuration utility - Overview|- Overview&lt;br /&gt;
** The Ekdahl FAR - Configuration utility - Tuning tab|- The Tuning tab&lt;br /&gt;
** The Ekdahl FAR - Configuration utility - Midi tab|- The MIDI tab&lt;br /&gt;
** The Ekdahl FAR - Configuration utility - CV tab|- The CV tab&lt;br /&gt;
** The Ekdahl FAR - Configuration utility - Advanced tab|- The Advanced tab&lt;br /&gt;
** The Ekdahl FAR - Configuration utility - Statistics tab|- The Statistics tab&lt;br /&gt;
** The Ekdahl FAR - Configuration utility - Software tab|- The Software tab&lt;br /&gt;
** The Ekdahl FAR - Service|Service &amp;amp; Maintenance&lt;br /&gt;
** The Ekdahl FAR - Command langue|Command language&lt;br /&gt;
** The Ekdahl FAR - Command reference V1.0|Command reference V1.0&lt;br /&gt;
** The Ekdahl FAR - Command reference V1.1|Command reference V1.1&lt;br /&gt;
** The Ekdahl FAR - Specifications|Specifications&lt;br /&gt;
* SEARCH&lt;br /&gt;
* TOOLBOX&lt;br /&gt;
* LANGUAGES&lt;/div&gt;</summary>
		<author><name>Knaadmin</name></author>
	</entry>
	<entry>
		<id>http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_language_(1.0)&amp;diff=1664</id>
		<title>The Ekdahl FAR - Command language (1.0)</title>
		<link rel="alternate" type="text/html" href="http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_language_(1.0)&amp;diff=1664"/>
		<updated>2026-06-12T10:46:04Z</updated>

		<summary type="html">&lt;p&gt;Knaadmin: Knaadmin moved page The Ekdahl FAR - Command language (1.0) to The Ekdahl FAR - Command language over redirect&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[The Ekdahl FAR - Command language]]&lt;/div&gt;</summary>
		<author><name>Knaadmin</name></author>
	</entry>
	<entry>
		<id>http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_language&amp;diff=1663</id>
		<title>The Ekdahl FAR - Command language</title>
		<link rel="alternate" type="text/html" href="http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_language&amp;diff=1663"/>
		<updated>2026-06-12T10:46:04Z</updated>

		<summary type="html">&lt;p&gt;Knaadmin: Knaadmin moved page The Ekdahl FAR - Command language (1.0) to The Ekdahl FAR - Command language over redirect&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Command language ==&lt;br /&gt;
The Ekdahl FAR is entirely controlled by &#039;&#039;commands&#039;&#039;, these &#039;&#039;commands&#039;&#039; decide everything that the instrument is doing, whether it is playing a melody or changing an internal parameter. &lt;br /&gt;
&lt;br /&gt;
When a &#039;&#039;MIDI message&#039;&#039; is received or a new CV / knob value is read, the &#039;&#039;commands&#039;&#039; associated with it will be internally sent. This can be things like &amp;quot;engage hammer&amp;quot; or &amp;quot;set the fundamental frequency&amp;quot; etc. &lt;br /&gt;
&lt;br /&gt;
Some of the available &#039;&#039;commands&#039;&#039; are mainly used for calibrating and setting up the instrument and are usually saved into the instruments memory, these will be executed whenever the instrument is turned on. &lt;br /&gt;
&lt;br /&gt;
All &#039;&#039;commands&#039;&#039; can be manually invoked via &#039;&#039;USB-Serial&#039;&#039;, in conjunction with certain software this presents an unprecedented level of control and sequenceability.&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
The &#039;&#039;commands&#039;&#039; are invoked using a &#039;&#039;plain text approach&#039;&#039;, all commands have both a &#039;&#039;long name&#039;&#039; and a &#039;&#039;short name&#039;&#039; which are interchangeable. A &#039;&#039;command&#039;&#039; may have one or more &#039;&#039;parameters&#039;&#039; associated with it, these &#039;&#039;parameters&#039;&#039; can be of different types; 16-bit numbers (values 0 - 65535 or -32767 - 32767), floating point numbers (values with decimals), booleans (0 for &#039;false&#039;, 1 for &#039;true&#039;) and strings (text). Some commands are &#039;&#039;conditional&#039;&#039;, meaning they will only execute if a parameter equates to &#039;1&#039; (&#039;true&#039;). &lt;br /&gt;
&lt;br /&gt;
The way &#039;&#039;commands&#039;&#039; are written in order to be executed is &#039;&#039;commandname:parameter1:parameter2:parameter3 [etc]&#039;&#039;, several commands be executed in sequence by separating them with a comma (&#039;,&#039;), a bunch of commands strung together is called a &#039;&#039;command string&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Since version 1.1 of the Ekdahl FAR Firmware, all commands are grouped in a hierarchical fashion according to their &#039;&#039;modules&#039;&#039; and each ladder in the hierarchy is separated by a period (&amp;quot;.&amp;quot;), this works very much like folders or directories in a regular computer. Every &#039;&#039;module&#039;&#039; can contain both &#039;&#039;commands&#039;&#039; and other &#039;&#039;modules&#039;&#039;. For instance, everything associated with the &#039;&#039;bowing wheel&#039;&#039; is now collected under &amp;quot;bowingwheel&amp;quot; &#039;&#039;module&#039;&#039;. That in turn contains a &amp;quot;dcmotor&amp;quot; &#039;&#039;module&#039;&#039; which handles direct control of the bowing motor. It also has a &amp;quot;pid&amp;quot; &#039;&#039;module&#039;&#039; that handles bow frequency among other thing. &lt;br /&gt;
&lt;br /&gt;
If for instance we would like to start the &#039;&#039;bowing wheel&#039;&#039; and set its frequency to 82.5 Hertz we could send the Ekdahl FAR the following &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
bowmotorrun:1, bowcontrolfrequecy:82.5&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bowingwheel.dcmotor.run:1, bowingwheel.pid.targetfrequency:82.5&amp;lt;/pre&amp;gt;We could also use the &#039;&#039;short names&#039;&#039; for the commands&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
bmr:1,bcf:82.5&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bw.dcm.ru:1, bw.pid.tf:82.5&amp;lt;/pre&amp;gt;Both &amp;quot;bowmotorrun&amp;quot; / &amp;quot;bowingwheel.dcmotor.run&amp;quot; and &amp;quot;bowcontrolfrequency&amp;quot; / &amp;quot;bowingwheel.pid.targetfrequency&amp;quot; takes one &#039;&#039;parameter&#039;&#039; each, &#039;&#039;&amp;quot;&#039;&#039;bowmotorrun&amp;quot; / &amp;quot;bowingwheel.dcmotor.run&amp;quot; is &#039;&#039;conditional&#039;&#039; and unless the first &#039;&#039;parameter&#039;&#039; is equal to &#039;1&#039; the motor will not start. The first &#039;&#039;parameter&#039;&#039; of &amp;quot;bowcontrolfrequency&amp;quot; / &amp;quot;bowingwheel.pid.targetfrequency&amp;quot; sets the frequency of the &#039;&#039;bowing wheel&#039;&#039;, the instrument may not execute a &#039;&#039;command&#039;&#039; if it decides that the given &#039;&#039;parameters&#039;&#039; are outside of the working range or they are missing.&lt;br /&gt;
&lt;br /&gt;
The addition of the hierarchy in the FAR 1.1 firmware isn&#039;t just to be able to group commands, but it&#039;s also to make the FAR not limited to a single set of &#039;&#039;modules&#039;&#039; (and is the first stepping stone to a &#039;&#039;modular&#039;&#039; Ekdahl FAR). In fact, you could have 12 different bowing wheel &#039;&#039;modules&#039;&#039; for 12 different strings, these would then be addressed as &amp;quot;bowingwheel[0].command&amp;quot;&#039;&#039;, &amp;quot;&#039;&#039;bowingwheel[1].command&amp;quot; etc. Anyone familiar with C programming notices that this is the standard way of &#039;&#039;indexing&#039;&#039; an array; using brackets (&amp;quot;[ ]&amp;quot;). When addressing a module without &#039;&#039;indexing&#039;&#039; as in the example above, the FAR will do one or two things; either use the first object (&amp;quot;[0]&amp;quot;) or, if the object is &#039;&#039;selectable&#039;&#039; it will use the previously selected object. To make things smoother a command can be executed on several objects at once by using ranges (&amp;quot;[0-4]&amp;quot;) and comma separation (&amp;quot;[0, 3, 5-6]&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
To test out a &#039;&#039;command&#039;&#039; you can send it directly to the Ekdahl FAR using the &#039;&#039;Console&#039;&#039; in the &#039;&#039;Configuration utility&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
To read up on existing &#039;&#039;commands&#039;&#039;, their &#039;&#039;parameters&#039;&#039; and a brief description you can check the &#039;&#039;Command reference&#039;&#039; in the &#039;&#039;Configuration utility&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Variables, functions and equations ==&lt;br /&gt;
What makes the &#039;&#039;Command language&#039;&#039; truly powerful is the concept of &#039;&#039;variables, functions&#039;&#039; and &#039;&#039;equations&#039;&#039;. All &#039;&#039;parameters&#039;&#039; that take numerical values can use any combination of &#039;&#039;variables, functions&#039;&#039; or &#039;&#039;equations.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
For instance, we can use the previous example and instead write our &#039;&#039;command string&#039;&#039; as follows&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
bowmotorrun:1, bowcontrolfrequency:82.5+note*20&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bowingwheel.dcmotor.run:1, bowingwheel.pid.targetfrequency:82.5+note*20&amp;lt;/pre&amp;gt;This example requires of course that the &#039;&#039;variable&#039;&#039; &#039;&#039;note&#039;&#039; exists in the current context. &lt;br /&gt;
&lt;br /&gt;
===== Variables =====&lt;br /&gt;
There are two types of &#039;&#039;variables&#039;&#039; in the Ekdahl FAR; &#039;&#039;global variables&#039;&#039; and &#039;&#039;event variables&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Global variables&#039;&#039; are variables that are always valid, in any context. The &#039;&#039;global variables&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;notecount&#039;&#039;&#039; - Contains the number of &#039;&#039;MIDI&#039;&#039; keys that are being held down, i.e. all &#039;&#039;Note on messages&#039;&#039; received that haven&#039;t gotten a paired &#039;&#039;Note off message&#039;&#039; yet&lt;br /&gt;
* &#039;&#039;&#039;uv0&#039;&#039;&#039; - &#039;&#039;&#039;uv9&#039;&#039;&#039; - These are &#039;&#039;user variables&#039;&#039; and can be set at any point using the &#039;&#039;globaluservariable command&#039;&#039; with the first &#039;&#039;parameter&#039;&#039; being which variable to set (0-9) and the second &#039;&#039;parameter&#039;&#039; being the value (float).&lt;br /&gt;
* &#039;&#039;&#039;e&#039;&#039;&#039; - Contains the constant &#039;&#039;[[wikipedia:E_(mathematical_constant)|e]]&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pi&#039;&#039;&#039; - Contains the constant &#039;&#039;[[wikipedia:Pi|pi]]&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Event variables&#039;&#039; are variables that are set by certain &#039;&#039;MIDI messages&#039;&#039; or when a new value is read on one of the jacks or knobs on the &#039;&#039;Control box&#039;&#039;. The &#039;&#039;Event variables&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;channel&#039;&#039;&#039; - Set by the &#039;&#039;Note on, Note off, Continuous Controller, Poly after touch, Pitch bend, Channel after touch&#039;&#039; and &#039;&#039;Program change MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;note&#039;&#039;&#039; - Set by the &#039;&#039;Note on, Note off&#039;&#039; and &#039;&#039;Poly after touch MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;velocity&#039;&#039;&#039; - Set by the &#039;&#039;Note on&#039;&#039; and &#039;&#039;Note off MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pressure&#039;&#039;&#039; - Set by the &#039;&#039;Poly after touch&#039;&#039; and &#039;&#039;Channel after touch MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; - Set by the &#039;&#039;Continuous Controller MIDI message&#039;&#039; and by the &#039;&#039;Control box&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pitch&#039;&#039;&#039; - Set by the &#039;&#039;Pitch bend MIDI message&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;program&#039;&#039;&#039; - Set by the &#039;&#039;Program change MIDI message&#039;&#039;&lt;br /&gt;
These variables will contain whatever data is relevant to the last event that occurred and may be overwritten by the next event.&lt;br /&gt;
&lt;br /&gt;
===== Functions =====&lt;br /&gt;
&#039;&#039;Functions&#039;&#039; can be used to change a numerical value or the result of an &#039;&#039;equation&#039;&#039;, the Ekdahl FAR contains both general &#039;&#039;arithmetic functions&#039;&#039; (courtesy of Lewis Van Winkle and the TINYEXPR engine) and &#039;&#039;specialized functions&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;arithmetic functions&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;abs&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Absolute_value|absolute value]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;acos&#039;&#039;&#039;(x), &#039;&#039;&#039;asin&#039;&#039;&#039;(x), &#039;&#039;&#039;atan&#039;&#039;&#039;(x), atan2(x, y) - Returns the [[wikipedia:Inverse_trigonometric_functions|&#039;&#039;arc-cos, -sin, -tan&#039;&#039; and &#039;&#039;-tan2&#039;&#039;]] of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;atan2&#039;&#039;&#039;(x,y) - Returns the &#039;&#039;[[wikipedia:Atan2|arctan2]]&#039;&#039; of &#039;&#039;x, y&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;floor&#039;&#039;&#039;(x), ceil(x) - Returns the [[wikipedia:Floor_and_ceiling_functions|&#039;&#039;floor&#039;&#039; and &#039;&#039;ceiling&#039;&#039;]] of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;exp&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Exponential_function|exponent]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;fac&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Factorial|factorial]]&#039;&#039; of x&lt;br /&gt;
* &#039;&#039;&#039;ln&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Natural_logarithm|natural logarithm]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;log10&#039;&#039;&#039;(x), &#039;&#039;&#039;log20&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Logarithm|logarithm]]&#039;&#039; of &#039;&#039;x&#039;&#039; using base 10 and 20 respectively&lt;br /&gt;
* &#039;&#039;&#039;ncr&#039;&#039;&#039;(x,y), &#039;&#039;&#039;npr&#039;&#039;&#039;(x,y) - Functions to calculate &#039;&#039;[[wikipedia:Combination|combinations]]&#039;&#039; and &#039;&#039;[[wikipedia:Permutation|permutations]]&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pow&#039;&#039;&#039;(x,y) - Returns &#039;&#039;x^y&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;sqrt&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Square_root|square root]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;cos&#039;&#039;&#039;(x), &#039;&#039;&#039;sin&#039;&#039;&#039;(x), &#039;&#039;&#039;tan&#039;&#039;&#039;(x) - Returns the [[wikipedia:Trigonometric_functions|&#039;&#039;cos, sin&#039;&#039; and &#039;&#039;tan&#039;&#039;]] of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;cosh&#039;&#039;&#039;(x), &#039;&#039;&#039;sinh&#039;&#039;&#039;(x), &#039;&#039;&#039;tanh&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Hyperbolic_functions|hyperbolic cos, sin and tan]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
The &#039;&#039;specialized functions&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;bool&#039;&#039;&#039;(x) - Returns 1 if &#039;&#039;x&#039;&#039; is more than 0&lt;br /&gt;
* &#039;&#039;&#039;ibool&#039;&#039;&#039;(x) - Returns 0 if &#039;&#039;x&#039;&#039; is more than 0&lt;br /&gt;
* &#039;&#039;&#039;deadband&#039;&#039;&#039;(x,y) - Returns &#039;&#039;x + y &#039;&#039; if &#039;&#039;x &amp;lt; y&#039;&#039; or &#039;&#039;x - y&#039;&#039; if &#039;&#039;x &amp;gt; y&#039;&#039;. If neither of these statements is true it returns &#039;&#039;0&#039;&#039; - used to create a [[wikipedia:Deadband|deadband]] of &#039;&#039;x&#039;&#039; with the threshold of &#039;&#039;y&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Functions&#039;&#039; can be readily used in a &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
bowmotorrun:1, bowcontrolfrequency:&amp;quot;8.17579875 * pow(2, (1/12 * note))&amp;quot;&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bowingwheel.dcmotor.run:1, bowingwheel.pid.targetfrequency:&amp;quot;8.17579875 * pow(2, (1/12 * note))&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;The previous statements starts the &#039;&#039;bowing wheel&#039;&#039; and sets the frequency of the wheel to &#039;&#039;8.17579875 * 2^(1/12 * note)&#039;&#039;. A middle &#039;C&#039; according to &#039;&#039;MIDI&#039;&#039; has a &#039;&#039;note value&#039;&#039; of 36, meaning if we substitute &#039;&#039;note&#039;&#039; with 36 we get the equation &#039;&#039;8.17579875 * 2^(1/12 * 36)&#039;&#039; which comes out to &#039;&#039;~65.4&#039;&#039; Hertz.&lt;br /&gt;
&lt;br /&gt;
Note that the first &#039;&#039;parameter&#039;&#039; for &#039;&#039;&amp;quot;&#039;&#039;bowcontrolfrequency&amp;quot; / &amp;quot;bowingwheel.pid.targetfrequency&amp;quot; is put in between double quotes (&amp;quot;). This is because the &amp;quot;pow&#039;&#039;&amp;quot;-&#039;&#039;function requires the use of a comma (&amp;quot;,&amp;quot;) in order to separate in between its two required inputs; &#039;&#039;x&#039;&#039; and &#039;&#039;y&#039;&#039;. In order for the Ekdahl FAR to know that this comma does not signal the beginning of a new &#039;&#039;command,&#039;&#039; we use quotes. Single (&#039;) and double (&amp;quot;) quotes can be used and nested in all &#039;&#039;parameters&#039;&#039; and are &amp;lt;u&amp;gt;required&amp;lt;/u&amp;gt; in a lot of circumstances, improper nesting or not using quotes can lead to the instrument not understanding the &#039;&#039;command string&#039;&#039; correctly.&lt;br /&gt;
&lt;br /&gt;
== Return messages ==&lt;br /&gt;
The Ekdahl FAR when connected via &#039;&#039;USB-Serial&#039;&#039; doesn&#039;t only accept &#039;&#039;commands&#039;&#039; but will also send various &#039;&#039;return messages&#039;&#039;. These are prefixed by their &#039;&#039;category&#039;&#039; denoted in brackets (&amp;quot;[]&amp;quot;), the existing categories as of this writing (2025-01-22) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;command&#039;&#039;&#039; / &#039;&#039;&#039;cmd&#039;&#039;&#039; - Acknowledges the reception of a command in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;usb&#039;&#039;&#039; - Acknowledges the reception of a &#039;&#039;MIDI message&#039;&#039; over &#039;&#039;USB&#039;&#039; in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;hardware&#039;&#039;&#039; / &#039;&#039;&#039;hw&#039;&#039;&#039; - Signals that a change has been sent to the Ekdahl FAR hardware, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;undefined&#039;&#039;&#039; / &#039;&#039;&#039;un&#039;&#039;&#039; - The message sent is in the &#039;&#039;undefined&#039;&#039; category, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;priority&#039;&#039;&#039; / &#039;&#039;&#039;pri&#039;&#039;&#039; - The message sent is in the &#039;&#039;priority&#039;&#039; category, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;error&#039;&#039;&#039; / &#039;&#039;&#039;err&#039;&#039;&#039; - Signals that an &#039;&#039;error&#039;&#039; has occurred, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;expressionparser&#039;&#039;&#039; / &#039;&#039;&#039;ep&#039;&#039;&#039; - These messages contains debugging information regarding the internal &#039;&#039;expression parser&#039;&#039; and is used for development&lt;br /&gt;
*&#039;&#039;&#039;debug&#039;&#039;&#039; / &#039;&#039;&#039;dbg&#039;&#039;&#039; - These messages contains various debugging information and is used for development&lt;br /&gt;
*&#039;&#039;&#039;help&#039;&#039;&#039; / &#039;&#039;&#039;hlp&#039;&#039;&#039; - Signals that the message is a response to a &#039;&#039;help&#039;&#039;-command being sent to the Ekdahl FAR. These messages are structured so that a receiver, like the &#039;&#039;Configuration utility&#039;&#039;, can parse information about available &#039;&#039;commands&#039;&#039; in the current &#039;&#039;firmware&#039;&#039; and relay it to a user in a structured way.&lt;br /&gt;
* &#039;&#039;&#039;inforequest&#039;&#039;&#039; / &#039;&#039;&#039;irq&#039;&#039;&#039; - Signals that an &#039;&#039;info request&#039;&#039; has been returned. This is a specialized message that is either sent as a response to an &#039;&#039;rqi&#039;&#039;-command or as a &#039;&#039;interrupt&#039;&#039;-message telling the user or receiving software about different parameters in the Ekdahl FAR. These messages follows the same structure as regular &#039;&#039;command message&#039;&#039;s of &#039;&#039;[irq]commandname:parameter1 [etc]&#039;&#039; so that it can be used by a receiving software to keep track of parameter changes&lt;br /&gt;
&lt;br /&gt;
===== Explicitly requesting information =====&lt;br /&gt;
By using the special command &amp;quot;requestinfo&amp;quot; / &amp;quot;rqi&amp;quot; one can request the information stored by a certain &#039;&#039;command&#039;&#039; or a state of the Ekdahl FAR. The &amp;quot;rqi&amp;quot;-command is executed in the convention &amp;quot;rqi:commandname:optional parameters&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
To go back to our example of setting the bowing frequency using the &#039;&#039;&amp;quot;&#039;&#039;bowcontrolfrequency&amp;quot; / &amp;quot;bowingwheel.pid.targetfrequency&amp;quot;-command we can ask the Ekdahl FAR what the bowing frequency is set to by writing&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
rqi:bowcontrolfrequency&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
rqi:bowingwheel.pid.targetfrequency&lt;br /&gt;
&amp;lt;/pre&amp;gt;The return value would be something like&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
[irq]bcf:82.5&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
[irq]bw[0].pid[0].tf:82.5&lt;br /&gt;
&amp;lt;/pre&amp;gt;Where &#039;[irq]&#039; denotes that the message returned is in the &#039;&#039;info request-&#039;&#039;category, that it pertains to the command &amp;quot;bcf&amp;quot; / &amp;quot;bw.pid.tf&amp;quot; and has the value &#039;&#039;82.5&#039;&#039;. Note that the returned &#039;&#039;command&#039;&#039; sent by an &amp;quot;rqi&amp;quot;-command always uses the &#039;&#039;short name&#039;&#039; in order to preserve bandwidth. In the FAR 1.1 the return statement always returns the &#039;&#039;index&#039;&#039; of the &#039;&#039;module&#039;&#039;(s) in question. &lt;br /&gt;
&lt;br /&gt;
Most commands do not require any &#039;&#039;parameters&#039;&#039; when using the &amp;quot;rqi&amp;quot;-command. The &#039;&#039;&amp;quot;&#039;&#039;adcread&amp;quot; / &amp;quot;controlbox.datareturn&amp;quot;-command is an example of a &#039;&#039;command&#039;&#039; that &amp;lt;u&amp;gt;does&amp;lt;/u&amp;gt; require a &#039;&#039;parameter&#039;&#039; when used with &amp;quot;rqi&amp;quot;. The &amp;quot;adcread&amp;quot; / &amp;quot;controlbox.datareturn&amp;quot;&#039;&#039;-&#039;&#039;command returns the last value read by the &#039;&#039;analog-to-digital converter&#039;&#039; in the &#039;&#039;Control box&#039;&#039;, because there are 8 different channels the first &#039;&#039;parameter&#039;&#039; sets which channel to return the data for, hence executing the &#039;&#039;command&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
rqi:adcr:3&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
rqi:controlbox.datareturn:3&lt;br /&gt;
&amp;lt;/pre&amp;gt;will return the last data read on &#039;&#039;analog-to-digital convert&#039;&#039; channel 3.&lt;br /&gt;
&lt;br /&gt;
== MIDI mapping ==&lt;br /&gt;
The way &#039;&#039;MIDI&#039;&#039; works int the Ekdahl FAR is that each &#039;&#039;MIDI message&#039;&#039; is associated with a certain &#039;&#039;command string&#039;&#039; and the &#039;&#039;MIDI message&#039;&#039; will also update some of the internal &#039;&#039;variables&#039;&#039;. Any time the associated &#039;&#039;MIDI message&#039;&#039; is received the Ekdahl FAR will execute the &#039;&#039;commands&#039;&#039; that have been associated with that &#039;&#039;MIDI message&#039;&#039;. Several &#039;&#039;MIDI configurations&#039;&#039; can be stored and recalled at any time, each with a different set of &#039;&#039;commands&#039;&#039; associated with each &#039;&#039;MIDI message&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;FAR &amp;lt; 1.1&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 The &#039;&#039;command&#039;&#039; responsible for mapping &#039;&#039;command strings&#039;&#039; to different &#039;&#039;MIDI messages&#039;&#039; is &amp;quot;midieventhandler&amp;quot; or &amp;quot;mev&amp;quot; for short. The first &#039;&#039;parameter&#039;&#039; of &amp;quot;mev&amp;quot; is the type of &#039;&#039;MIDI message&#039;&#039; that we want to remap;&lt;br /&gt;
 &lt;br /&gt;
 * &#039;&#039;&#039;noteon&#039;&#039;&#039; - Note on&lt;br /&gt;
 * &#039;&#039;&#039;noteoff&#039;&#039;&#039; - Note off&lt;br /&gt;
 * &#039;&#039;&#039;pat&#039;&#039;&#039; - Poly after touch&lt;br /&gt;
 * &#039;&#039;&#039;cat&#039;&#039;&#039; - Channel after touch&lt;br /&gt;
 * &#039;&#039;&#039;pb&#039;&#039;&#039; - Pitch bend&lt;br /&gt;
 * &#039;&#039;&#039;pc&#039;&#039;&#039; - Program change&lt;br /&gt;
 * &#039;&#039;&#039;cc&#039;&#039;&#039; - Continuous controller&lt;br /&gt;
 &lt;br /&gt;
 The second &#039;&#039;parameter&#039;&#039; is the &#039;&#039;command string&#039;&#039; that is to be associated with the &#039;&#039;MIDI Message&#039;&#039; - with the exception of the &#039;&#039;&#039;cc&#039;&#039;&#039;-type, here the second &#039;&#039;parameter&#039;&#039; is the &#039;&#039;controller number&#039;&#039; (0 - 127) and the third &#039;&#039;parameter&#039;&#039; is the &#039;&#039;command string&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;FAR 1.1&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 The &amp;quot;bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; contains a &#039;&#039;module&#039;&#039; called &amp;quot;midiconfigurationhandler&amp;quot; that handles the loading and switching in between different &#039;&#039;MIDI configurations&#039;&#039;. The &amp;quot;midiconfigurationhandler&amp;quot;&#039;&#039;-module&#039;&#039; has one or more &#039;&#039;&amp;quot;&#039;&#039;midiconfiguration&amp;quot;-&#039;&#039;modules&#039;&#039;, each having its own &#039;&#039;MIDI&#039;&#039; settings. In order to change the &#039;&#039;command mapping&#039;&#039; for a &#039;&#039;MIDI message&#039;&#039; in a specific &#039;&#039;MIDI configuration&#039;&#039;, the following &#039;&#039;commands&#039;&#039; are used;&lt;br /&gt;
 &lt;br /&gt;
 * &#039;&#039;&#039;noteon/non&#039;&#039;&#039;:&#039;&#039;commands&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed for a &#039;note on&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;noteoff/nof&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;note off&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;polyaftertouch/pat&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;poly aftertouch&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;channelaftertouch/cat&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;channel aftertouch&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;pitchbend/pb&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;pitch bend&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;programchange/pc&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;program change&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;continuouscontrollerdata/ccd&#039;&#039;&#039;&#039;&#039;:controller:commands&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed for &#039;continuous controller&#039; no &#039;&#039;controller&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
We can of course use the &#039;&#039;&amp;quot;&#039;&#039;rqi&amp;quot;-&#039;&#039;command&#039;&#039; to check the current mapping, below we are asking what the current &#039;&#039;command string&#039;&#039; associated with the &#039;&#039;pitch bend&#039;&#039; &#039;&#039;MIDI message&#039;&#039; is in the currently selected &#039;&#039;MIDI configuration&#039;&#039;.&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
rqi:midieventhandler:pb&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
rqi:bowingwheel.midiconfigurationhandler.midiconfiguration.pitchbend&lt;br /&gt;
&amp;lt;/pre&amp;gt;This may return something like&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
[irq]mev:pb:&amp;quot;bowcontrolharmonicshift:pitch*4&amp;quot;&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
[irq]bw[0].mcf[0].mc[0].pb:&amp;quot;bowingwheel.harmonicserieshandler.harmonicseries.shift:pitch*4&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;The first part of the return message tells us that the incoming message is of &amp;quot;rqi&amp;quot;-type (&amp;quot;[irq]&amp;quot;) which means it&#039;s responding to a information request &#039;&#039;command&#039;&#039; sent. The second part tells us what &#039;&#039;command&#039;&#039; the information request return is responding to and any &#039;&#039;parameters&#039;&#039; that may be pertinent. The third part of the message is the actual data stored.  &lt;br /&gt;
&lt;br /&gt;
For the FAR &amp;lt; 1.1 the data returned is for the &#039;&#039;command&#039;&#039; &amp;quot;mev&amp;quot; with the first &#039;&#039;parameter&#039;&#039; set to &amp;quot;pb&amp;quot;, the &#039;&#039;command reference&#039;&#039; tells us this means the &#039;&#039;command&#039;&#039; &amp;quot;midieventhandler&amp;quot; and the &#039;&#039;parameter&#039;&#039; &amp;quot;pb&amp;quot; indicates this has to do with the &#039;&#039;pitch bend&#039;&#039;. The data is &amp;quot;bowcontrolharmonicshift:pitch*4&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
For the FAR 1.1 the data returned is for the &#039;&#039;command&#039;&#039; &amp;quot;bw[0].mcf[0].mc[0].pb&amp;quot; (bowinwheel[0].midiconfigurationhandler[0].midiconfiguration[0].pitchbend) and the data is &amp;quot;bowingwheel.harmonicserieshandler.harmonicseries.shift:pitch*4&amp;quot;. Note here that if we have several different &#039;&#039;MIDI configurations&#039;&#039; stored and we&#039;re currently using configuration number 2, the returned message would have been &amp;quot;bw[0].mcf[0].mc[2].pb&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
that the &#039;&#039;pitch bend MIDI message&#039;&#039; is executing a &amp;quot;bowcontrolharmonicshift&amp;quot; / &amp;quot;harmonicseries.shift&amp;quot;-command with the parameter &#039;&#039;pitch*4&#039;&#039;. Looking in the &#039;&#039;command reference&#039;&#039; we can see that &#039;&#039;&amp;quot;&#039;&#039;bowcontrolharmonicshift&amp;quot; / &amp;quot;harmonicseries.shift&amp;quot;-&#039;&#039;command&#039;&#039; shifts the frequency of the &#039;&#039;bowing wheel&#039;&#039; from the currently selected harmonic. The first (and only) &#039;&#039;parameter&#039;&#039; sets how much we want to shift it (the range depends on the &amp;quot;bowcontrolharmonicshiftrange&#039;&#039;&amp;quot;&#039;&#039; / &amp;quot;harmonicseries.shiftrange&amp;quot;-&#039;&#039;command&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
If we look in the list of &#039;&#039;[[The Ekdahl FAR - Command langue#Variables|variables]]&#039;&#039; above we can see that the &#039;&#039;pitch bend MIDI message&#039;&#039; will set the &amp;quot;pitch&amp;quot;&#039;&#039;-variable&#039;&#039; which is indeed used. Now what is the &#039;&#039;&#039;*4&#039;&#039;&amp;lt;nowiki/&amp;gt;&#039; all about? Well the &amp;quot;bowcontrolharmonicshift&amp;quot; / &amp;quot;harmoniceseries.shift&amp;quot;-&#039;&#039;command&#039;&#039; expects a &#039;&#039;16-bit signed&#039;&#039; value as its &#039;&#039;parameter&#039;&#039;. This means that the valid &#039;&#039;parameter&#039;&#039; number can be anything from -32767 to 32767. A full &#039;&#039;harmonic shift&#039;&#039; downwards according to the range set is equal to -32767, a full &#039;&#039;harmonic shift&#039;&#039; upwards is 32767 and no &#039;&#039;harmonic shift&#039;&#039; is 0. The &#039;&#039;pitch bend MIDI message&#039;&#039; however is only 14-bits, meaning its range is -8192 to 8192. So we have to multiply &#039;&#039;pitch&#039;&#039; by 4 in order to meet the requirements of a &#039;&#039;16-bit signed parameter&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
This whole thing about number of bits can seem confusing but in the end it&#039;s all about how fine control you have over things; the more possible values, the more detailed control. In fact, most &#039;&#039;MIDI&#039;&#039; values are only 7-bit (!) meaning a range of 0 - 127. While this may sound like a lot of detail for something like a volume control, it is not even close to enough resolution to for instance set the &#039;&#039;bowing frequency&#039;&#039;. Even if you would limit yourself to a single octave the instrument would never be able to be properly in tune. The idea of limiting the Ekdahl FAR to what is possible through &#039;&#039;MIDI&#039;&#039; seemed like a poor choice thus it was decided that &amp;lt;u&amp;gt;most&amp;lt;/u&amp;gt; parameters will instead be 16-bit.&lt;br /&gt;
&lt;br /&gt;
Now lets look at a more complex example, the &amp;lt;u&amp;gt;default&amp;lt;/u&amp;gt; &#039;&#039;Note On MIDI message&#039;&#039;. On a stock Ekdahl FAR, executing&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
rqi:mev:noteon&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
rqi:mcf.mf.non&lt;br /&gt;
&amp;lt;/pre&amp;gt;Will return something like&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
[irq]mev:noteon:&#039;bchb:note,bmr:1,bpid:1,bpe:1,se:(velocity*512)*(1-notecount),bcsm:0&#039;&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
[irq]mcf[0].mc[0].non:&#039;bw.hsh.hb:note,bw.dcm.ru:1,bw.pe:1,bw.bp.en:1,so.en:(velocity*512)*(1-notecount),bw.sm:0&#039;&amp;lt;/pre&amp;gt;As can be seen, there&#039;s a lot of stuff going on here! First of all, notice that everything after &amp;quot;mev:noteon:&amp;quot; / &amp;quot;mcf[0].mc[0].non:&amp;quot; is situated in between single quotes (&#039;) - this is &amp;lt;u&amp;gt;absolutely crucial&amp;lt;/u&amp;gt; for the Ekdahl FAR in order to know that everything within those last two quotes is part of the last &#039;&#039;parameter&#039;&#039; of the &amp;quot;mev&amp;quot; / &amp;quot;mcf.mc.non&amp;quot;-&#039;&#039;command&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Now let&#039;s break down what happens when this &#039;&#039;MIDI message&#039;&#039; is received, i.e. when a &#039;&#039;MIDI&#039;&#039; key is pressed down:&lt;br /&gt;
&lt;br /&gt;
# &amp;quot;bchb:note&amp;quot; / &amp;quot;bw.hsh.hb:note&amp;quot;  - Invokes the &amp;quot;bowcontrolharmonicbase&amp;quot; / &amp;quot;harmonicserieshandler.harmonicbase&amp;quot;&#039;&#039;-command&#039;&#039; with the first &#039;&#039;parameter&#039;&#039; set to the &#039;&#039;variable &amp;quot;&#039;&#039;note&amp;quot;. This sets the &#039;&#039;base harmonic&#039;&#039; that the Ekdahl FARs &#039;&#039;bowing motor&#039;&#039; should be set to. Here the &#039;&#039;variable&#039;&#039; &amp;quot;note&amp;quot; is used which is simply the MIDI key being pressed down, it is automatically converted by the &#039;&#039;command&#039;&#039; to the corresponding harmonic in the &#039;&#039;harmonic list&#039;&#039;&lt;br /&gt;
# &amp;quot;bmr:1&amp;quot; / &amp;quot;bw.dcm.ru&amp;quot; - Sets the &amp;quot;bowmotorrun&amp;quot; / &amp;quot;dcmotor.run&amp;quot;-command to &#039;1&#039;, starting the &#039;&#039;bow motor&#039;&#039;&lt;br /&gt;
# &amp;quot;bpid:1&amp;quot; / &amp;quot;bw.pe:1&amp;quot; - Sets the &amp;quot;bowpid&amp;quot; / &amp;quot;bowingwheel.pidenable&amp;quot;-&#039;&#039;command&#039;&#039; to &#039;1&#039;. Basically this enables the function that makes the Ekdahl FAR able to keep a stable frequency on the &#039;&#039;bowing motor&#039;&#039;.&lt;br /&gt;
# &amp;quot;bpe:1&amp;quot; / &amp;quot;bw.bp.en&amp;quot; - Sets the &amp;quot;bowpressureengage&amp;quot; / &amp;quot;bowpressure.engage&amp;quot;-&#039;&#039;command&#039;&#039; to &#039;1&#039; which moves the &#039;&#039;bowing jack&#039;&#039; to the &#039;&#039;engage position&#039;&#039;, aka just below the string if not additional &#039;&#039;pressure&#039;&#039; is applied&lt;br /&gt;
# &amp;quot;se:(velocity*512)*(1-notecount)&amp;quot; / &amp;quot;so.en:(velocity*512)*(1-notecount)&amp;quot; - Executes the &amp;quot;solenoidengage&amp;quot; / &amp;quot;solenoid.engage&amp;quot;-&#039;&#039;command&#039;&#039; with the value &#039;&#039;(velocity*512)*(1-notecount)&#039;&#039;. This will make the &#039;&#039;solenoid&#039;&#039; strike the &#039;&#039;hammer&#039;&#039; with a force that is dependent on the &amp;quot;velocity&amp;quot;-&#039;&#039;variable&#039;&#039; sent by the &#039;&#039;Note On MIDI message&#039;&#039; in order to make the &#039;&#039;hammer&#039;&#039; velocity sensitive.   But it also adds the somewhat perplexing part &amp;quot;*(1-notecount)&amp;quot;. &amp;quot;notecount&amp;quot; is a global &#039;&#039;variable&#039;&#039; that contains the number of MIDI keys that are currently being held down. If &amp;quot;notecount&amp;quot; is anything above zero, the outcome of the equation will either be zero or a negative number. The &amp;quot;solenoidengage&amp;quot; / &amp;quot;solenoid.engage&amp;quot;-&#039;&#039;command&#039;&#039; requires a &#039;&#039;16-bit unsigned&#039;&#039; value, aka the only valid numbers are 0 - 65535. Anything below 0 will be interpreted as zero, so what this equation does is that it only fires off the &#039;&#039;hammer&#039;&#039; if there are no previous keys being held down - it&#039;s being used in &#039;&#039;staccato&#039;&#039;  mode.&lt;br /&gt;
# &amp;quot;bcsm:0&amp;quot; / &amp;quot;bowingwheel.speedmode&amp;quot; - Sets the &amp;quot;bowcontrolspeedmode&amp;quot; / &amp;quot;bowingwheel.speedmode&amp;quot; to &#039;1&#039; which enables automatic shut down of the &#039;&#039;bowing motor&#039;&#039; after a given timeout.&lt;br /&gt;
Let&#039;s postulate that the Ekdahl FAR is tuned to a &#039;C&#039; at 65.4Hz and has its &#039;&#039;base&#039;&#039; set to middle &#039;C&#039; (&#039;&#039;MIDI key&#039;&#039; no 36). We are using the equal-temperament 12-tone scale and the Ekdahl FAR is set to respond to &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; &#039;&#039;MIDI channels&#039;&#039; (omni). Without having previously held any keys we press the middle &#039;C&#039; (&#039;&#039;note&#039;&#039; value 36) as hard as possible (&#039;&#039;velocity&#039;&#039; value &#039;&#039;127&#039;&#039;) on &#039;&#039;MIDI channel&#039;&#039; number 1 (&#039;&#039;channel&#039;&#039; value of 0). The Ekdahl FAR will get a &#039;&#039;note on MIDI message&#039;&#039; sent to it and from our mapping it will create the following &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
[irq]mev:noteon:&#039;bchb:36,bmr:1,bpid:1,bpe:1,se:(127*512)*(1-0),bcsm:0&#039;&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
[irq]mcf[0].mc[0].non:&#039;bw.hsh.hb:36,bw.dcm.ru:1,bw.pe:1,bw.bp.en:1,so.en:(127*512)*(1-0),bw.sm:0&#039;&amp;lt;/pre&amp;gt;What has happened here is that all &#039;&#039;variables&#039;&#039; have been replaced with the values sent by the &#039;&#039;MIDI message&#039;&#039;. Since those &#039;&#039;commands&#039;&#039; that doesn&#039;t have any &#039;&#039;variables&#039;&#039; with them will execute just as previously, only those &#039;&#039;commands&#039;&#039; whos &#039;&#039;parameters&#039;&#039; have changed will be explained:&lt;br /&gt;
&lt;br /&gt;
# &amp;quot;bchb: 36&amp;quot; / &amp;quot;bw.hsh.hb:36&amp;quot; - The &amp;quot;bowcontrolharmonicbase&amp;quot; / &amp;quot;harmonicserieshandler.harmonicbase&amp;quot; gets a value of &#039;&#039;36&#039;&#039; (middle &#039;C&#039;), because &#039;&#039;harmonic number 0&#039;&#039; is mapped to this key it will set the &#039;&#039;bowing wheel&#039;&#039; frequency to the &#039;&#039;fundamental&#039;&#039;; &#039;&#039;65.4&#039;&#039; Hertz&lt;br /&gt;
# &amp;quot;se: (127*512)*(1-0)&amp;quot; / &amp;quot;so.en: (127*512)*(1-0)&amp;quot; - the value of &#039;&#039;127&#039;&#039; comes from the &amp;quot;velocity&amp;quot;-&#039;&#039;variable&#039;&#039;, &#039;&#039;127 * 512 = 65024&#039;&#039; which is awfully close to a maximum hammer force of 65535. Since no previous notes were held down, the &#039;&#039;&amp;quot;&#039;&#039;notecount&amp;quot;-&#039;&#039;variable&#039;&#039;  is equal to &#039;&#039;0&#039;&#039; and thus &#039;&#039;65024 * 1 = 65024&#039;&#039;. The hammer is engaged with near maximum force.&lt;br /&gt;
So the result is that we have set the speed of the &#039;&#039;bowing motor&#039;&#039; and we have engaged the &#039;&#039;hammer&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Now imagine that without releasing this key, we press another &#039;C&#039; one octave above but at half the velocity. The Ekdahl FAR creates the following &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
[irq]mev:noteon:&#039;bchb:48,bmr:1,bpid:1,bpe:1,se:(63*512)*(1-1),bcsm:0&#039;&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
[irq]mcf[0].mc[0].non:&#039;bw.hsh.hb:48,bw.dcm.ru:1,bw.pe:1,bw.bp.en:1,so.en:(65*512)*(1-1),bw.sm:0&#039;&lt;br /&gt;
&amp;lt;/pre&amp;gt;Now we can see that the &amp;quot;note&amp;quot;-&#039;&#039;variable&#039;&#039; is 48 because the &#039;C&#039; one octave up is exactly 12 keys above the first. The &amp;quot;velocity&amp;quot;-&#039;&#039;variable&#039;&#039; has changed to 63 since we hit it with a lighter touch - and because we are &amp;lt;u&amp;gt;still holding the first key down&amp;lt;/u&amp;gt;, the &amp;quot;notecount&amp;quot;-&#039;&#039;variable&#039;&#039; is equal to &#039;&#039;1&#039;&#039;. Here&#039;s what happens&lt;br /&gt;
&lt;br /&gt;
# &amp;quot;bchb: 48&amp;quot; / &amp;quot;hsh.hb:48&amp;quot; - Due to the &#039;&#039;base&#039;&#039; being set to &#039;&#039;36&#039;&#039; the &#039;&#039;harmonic number&#039;&#039; is set to &#039;&#039;48 - 36 = 12&#039;&#039;. Because we are using a 12-tone scale &#039;&#039;harmonic number 12&#039;&#039; is exactly one octave above the &#039;&#039;fundamental&#039;&#039; thus the speed of the &#039;&#039;bowing wheel&#039;&#039; is set to &#039;&#039;65.4 * 2 = 130.8&#039;&#039; Hertz.&lt;br /&gt;
# &amp;quot;se: (63*512)*(1-1)&amp;quot; / &amp;quot;so.en: (63*512)*(1-1)&amp;quot; - The equation evalutes as &#039;&#039;63 * 512 = 32256&#039;&#039; and &#039;&#039;1 - 1 = 0&#039;&#039; thus &#039;&#039;32256 * 0 = 0&#039;&#039;. When the &amp;quot;solenoidengage&amp;quot; / &amp;quot;solenoid.engage&amp;quot;-&#039;&#039;command&#039;&#039; gets a &#039;&#039;parameter&#039;&#039; of &#039;&#039;0&#039;&#039; it will not engage the &#039;&#039;hammer&#039;&#039; - so the &#039;&#039;hammer&#039;&#039; doesn&#039;t strike&lt;br /&gt;
So it can be seen that with quite rudimentary math we can accomplish a whole lot of things here. Note also that even though the &#039;&#039;note on MIDI message&#039;&#039; also sets the &#039;&#039;channel&#039;&#039;-variable we never use it in this example - plenty of opportunity to make something weird happen depending on the &#039;&#039;MIDI channel&#039;&#039;!&lt;br /&gt;
&lt;br /&gt;
== CV Mapping ==&lt;br /&gt;
&#039;&#039;CV Mapping&#039;&#039; works exactly like the &#039;&#039;MIDI mapping&#039;&#039; with the difference that the command(s) for setting the &#039;&#039;CV mapping&#039;&#039; is different and that they all modify (and thus share) the &amp;quot;value&amp;quot;-&#039;&#039;variable&#039;&#039;. These &#039;&#039;events&#039;&#039; are triggered whenever the analog-to-digital converter senses a change in a control or modulation jack, if you use something like an LFO with the modulation jacks here you will get a LOT of events and subsequent &#039;&#039;commands&#039;&#039; being sent.  &lt;br /&gt;
 &#039;&#039;&#039;FAR &amp;lt; 1.1:&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 The command for changing the CV mapping is &amp;quot;adccommandmap&amp;quot; or &amp;quot;acm&amp;quot;, it take two parameters; channel and command string. The channels on the original Edkahl FAR Control box are as &lt;br /&gt;
 &lt;br /&gt;
 * 0 - The &amp;quot;Harmonic&amp;quot; knob and jack&lt;br /&gt;
 * 1 - The &amp;quot;Harmonic shift&amp;quot; knob and jack&lt;br /&gt;
 * 2 - The &amp;quot;Fine tune&amp;quot; knob&lt;br /&gt;
 * 3 - The &amp;quot;Pressure&amp;quot; knob and jack&lt;br /&gt;
 * 4 - The &amp;quot;Hammertrig&amp;quot; button and jack&lt;br /&gt;
 * 5 - The &amp;quot;Gate&amp;quot; switch and jack&lt;br /&gt;
 * 6 - The &amp;quot;Hammer Scale&amp;quot; knob&lt;br /&gt;
 * 7 - The &amp;quot;Mute&amp;quot; knob and jack&lt;br /&gt;
 &lt;br /&gt;
 &#039;&#039;&#039;FAR 1.1:&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 The commands responsible for changing the CV mapping are located in the &amp;quot;controlbox&amp;quot;-module, these are&lt;br /&gt;
 &lt;br /&gt;
 * &#039;&#039;&#039;harmonic&#039;&#039;&#039; &#039;&#039;&#039;/ har&#039;&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed when the &amp;quot;Harmonic&amp;quot;-knob or modulation changes&lt;br /&gt;
 * &#039;&#039;&#039;harmonicshift&#039;&#039;&#039; &#039;&#039;&#039;/ has&#039;&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed when the &amp;quot;Harmonic shift&amp;quot;-knob or modulation changes&lt;br /&gt;
 * &#039;&#039;&#039;finetune / fin&#039;&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed when the &amp;quot;Fine tune&amp;quot;-knob changes&lt;br /&gt;
 * &#039;&#039;&#039;pressure&#039;&#039;&#039; &#039;&#039;&#039;/ pre&#039;&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed when the &amp;quot;Pressure&amp;quot;-knob or modulation changes&lt;br /&gt;
 * &#039;&#039;&#039;mute&#039;&#039;&#039; &#039;&#039;&#039;/ mut&#039;&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed when the &amp;quot;Mute&amp;quot;-knob or modulation changes&lt;br /&gt;
 * &#039;&#039;&#039;hammerscale / hms&#039;&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed when the &amp;quot;Hammer scale&amp;quot;-knob changes&lt;br /&gt;
 * &#039;&#039;&#039;gate / gt&#039;&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed when the &amp;quot;Gate&amp;quot;-switch or modulation changes&lt;br /&gt;
 * &#039;&#039;&#039;hammertrig&#039;&#039;&#039; &#039;&#039;&#039;/ hmt&#039;&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed when the &amp;quot;Hammer Trig&amp;quot;-button or modulation changes&lt;br /&gt;
In order to set/retrieve &#039;&#039;mapping data&#039;&#039; we just use a regular &amp;quot;rqi&amp;quot;-&#039;&#039;command&#039;&#039;. To for instance get the &#039;&#039;command string&#039;&#039; executed when the &amp;quot;pressure&amp;quot; knob or modulation is sent we can do the following&lt;br /&gt;
 &#039;&#039;&#039;FAR &amp;lt; 1.1:&#039;&#039;&#039;&lt;br /&gt;
 [send] rqi:acm:3&lt;br /&gt;
 [returns] [irq]acm:3:&#039;bpb:value&#039;&lt;br /&gt;
 &lt;br /&gt;
 &#039;&#039;&#039;FAR 1.1:&#039;&#039;&#039;&lt;br /&gt;
 [send] rqi:controlbox.pressure&lt;br /&gt;
 [returns] [irq]cb[0].pre:&#039;bw.bp.ba:value&#039;&lt;br /&gt;
As can be seen, when the &#039;&#039;pressure&#039;&#039; knob or modulation changes, the new data read by the ADC (stored in the &amp;quot;value&amp;quot;-&#039;&#039;variable&#039;&#039;) is sent to the &#039;&#039;command&#039;&#039; controlling the &#039;&#039;bow pressure baseline.&#039;&#039; Hopefully at this point it is obvious that making the knob and jack on the &#039;&#039;control box&#039;&#039; that is labeled as &amp;quot;Pressure&amp;quot; do something completely different, is quite easy - just remap the &#039;&#039;command string&#039;&#039;.{{docnav&lt;br /&gt;
|[[The Ekdahl FAR - Service|Service]]&lt;br /&gt;
|[[The Ekdahl FAR - Command reference|Command reference]]&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Knaadmin</name></author>
	</entry>
	<entry>
		<id>http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_language&amp;diff=1661</id>
		<title>The Ekdahl FAR - Command language</title>
		<link rel="alternate" type="text/html" href="http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_language&amp;diff=1661"/>
		<updated>2026-06-12T10:45:15Z</updated>

		<summary type="html">&lt;p&gt;Knaadmin: Knaadmin moved page The Ekdahl FAR - Command language to The Ekdahl FAR - Command language (1.0)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Command language ==&lt;br /&gt;
The Ekdahl FAR is entirely controlled by &#039;&#039;commands&#039;&#039;, these &#039;&#039;commands&#039;&#039; decide everything that the instrument is doing, whether it is playing a melody or changing an internal parameter. &lt;br /&gt;
&lt;br /&gt;
When a &#039;&#039;MIDI message&#039;&#039; is received or a new CV / knob value is read, the &#039;&#039;commands&#039;&#039; associated with it will be internally sent. This can be things like &amp;quot;engage hammer&amp;quot; or &amp;quot;set the fundamental frequency&amp;quot; etc. &lt;br /&gt;
&lt;br /&gt;
Some of the available &#039;&#039;commands&#039;&#039; are mainly used for calibrating and setting up the instrument and are usually saved into the instruments memory, these will be executed whenever the instrument is turned on. &lt;br /&gt;
&lt;br /&gt;
All &#039;&#039;commands&#039;&#039; can be manually invoked via &#039;&#039;USB-Serial&#039;&#039;, in conjunction with certain software this presents an unprecedented level of control and sequenceability.&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
The &#039;&#039;commands&#039;&#039; are invoked using a &#039;&#039;plain text approach&#039;&#039;, all commands have both a &#039;&#039;long name&#039;&#039; and a &#039;&#039;short name&#039;&#039; which are interchangeable. A &#039;&#039;command&#039;&#039; may have one or more &#039;&#039;parameters&#039;&#039; associated with it, these &#039;&#039;parameters&#039;&#039; can be of different types; 16-bit numbers (values 0 - 65535 or -32767 - 32767), floating point numbers (values with decimals), booleans (0 for &#039;false&#039;, 1 for &#039;true&#039;) and strings (text). Some commands are &#039;&#039;conditional&#039;&#039;, meaning they will only execute if a parameter equates to &#039;1&#039; (&#039;true&#039;). &lt;br /&gt;
&lt;br /&gt;
The way &#039;&#039;commands&#039;&#039; are written in order to be executed is &#039;&#039;commandname:parameter1:parameter2:parameter3 [etc]&#039;&#039;, several commands be executed in sequence by separating them with a comma (&#039;,&#039;), a bunch of commands strung together is called a &#039;&#039;command string&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Since version 1.1 of the Ekdahl FAR Firmware, all commands are grouped in a hierarchical fashion according to their &#039;&#039;modules&#039;&#039; and each ladder in the hierarchy is separated by a period (&amp;quot;.&amp;quot;), this works very much like folders or directories in a regular computer. Every &#039;&#039;module&#039;&#039; can contain both &#039;&#039;commands&#039;&#039; and other &#039;&#039;modules&#039;&#039;. For instance, everything associated with the &#039;&#039;bowing wheel&#039;&#039; is now collected under &amp;quot;bowingwheel&amp;quot; &#039;&#039;module&#039;&#039;. That in turn contains a &amp;quot;dcmotor&amp;quot; &#039;&#039;module&#039;&#039; which handles direct control of the bowing motor. It also has a &amp;quot;pid&amp;quot; &#039;&#039;module&#039;&#039; that handles bow frequency among other thing. &lt;br /&gt;
&lt;br /&gt;
If for instance we would like to start the &#039;&#039;bowing wheel&#039;&#039; and set its frequency to 82.5 Hertz we could send the Ekdahl FAR the following &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
bowmotorrun:1, bowcontrolfrequecy:82.5&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bowingwheel.dcmotor.run:1, bowingwheel.pid.targetfrequency:82.5&amp;lt;/pre&amp;gt;We could also use the &#039;&#039;short names&#039;&#039; for the commands&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
bmr:1,bcf:82.5&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bw.dcm.ru:1, bw.pid.tf:82.5&amp;lt;/pre&amp;gt;Both &amp;quot;bowmotorrun&amp;quot; / &amp;quot;bowingwheel.dcmotor.run&amp;quot; and &amp;quot;bowcontrolfrequency&amp;quot; / &amp;quot;bowingwheel.pid.targetfrequency&amp;quot; takes one &#039;&#039;parameter&#039;&#039; each, &#039;&#039;&amp;quot;&#039;&#039;bowmotorrun&amp;quot; / &amp;quot;bowingwheel.dcmotor.run&amp;quot; is &#039;&#039;conditional&#039;&#039; and unless the first &#039;&#039;parameter&#039;&#039; is equal to &#039;1&#039; the motor will not start. The first &#039;&#039;parameter&#039;&#039; of &amp;quot;bowcontrolfrequency&amp;quot; / &amp;quot;bowingwheel.pid.targetfrequency&amp;quot; sets the frequency of the &#039;&#039;bowing wheel&#039;&#039;, the instrument may not execute a &#039;&#039;command&#039;&#039; if it decides that the given &#039;&#039;parameters&#039;&#039; are outside of the working range or they are missing.&lt;br /&gt;
&lt;br /&gt;
The addition of the hierarchy in the FAR 1.1 firmware isn&#039;t just to be able to group commands, but it&#039;s also to make the FAR not limited to a single set of &#039;&#039;modules&#039;&#039; (and is the first stepping stone to a &#039;&#039;modular&#039;&#039; Ekdahl FAR). In fact, you could have 12 different bowing wheel &#039;&#039;modules&#039;&#039; for 12 different strings, these would then be addressed as &amp;quot;bowingwheel[0].command&amp;quot;&#039;&#039;, &amp;quot;&#039;&#039;bowingwheel[1].command&amp;quot; etc. Anyone familiar with C programming notices that this is the standard way of &#039;&#039;indexing&#039;&#039; an array; using brackets (&amp;quot;[ ]&amp;quot;). When addressing a module without &#039;&#039;indexing&#039;&#039; as in the example above, the FAR will do one or two things; either use the first object (&amp;quot;[0]&amp;quot;) or, if the object is &#039;&#039;selectable&#039;&#039; it will use the previously selected object. To make things smoother a command can be executed on several objects at once by using ranges (&amp;quot;[0-4]&amp;quot;) and comma separation (&amp;quot;[0, 3, 5-6]&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
To test out a &#039;&#039;command&#039;&#039; you can send it directly to the Ekdahl FAR using the &#039;&#039;Console&#039;&#039; in the &#039;&#039;Configuration utility&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
To read up on existing &#039;&#039;commands&#039;&#039;, their &#039;&#039;parameters&#039;&#039; and a brief description you can check the &#039;&#039;Command reference&#039;&#039; in the &#039;&#039;Configuration utility&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Variables, functions and equations ==&lt;br /&gt;
What makes the &#039;&#039;Command language&#039;&#039; truly powerful is the concept of &#039;&#039;variables, functions&#039;&#039; and &#039;&#039;equations&#039;&#039;. All &#039;&#039;parameters&#039;&#039; that take numerical values can use any combination of &#039;&#039;variables, functions&#039;&#039; or &#039;&#039;equations.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
For instance, we can use the previous example and instead write our &#039;&#039;command string&#039;&#039; as follows&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
bowmotorrun:1, bowcontrolfrequency:82.5+note*20&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bowingwheel.dcmotor.run:1, bowingwheel.pid.targetfrequency:82.5+note*20&amp;lt;/pre&amp;gt;This example requires of course that the &#039;&#039;variable&#039;&#039; &#039;&#039;note&#039;&#039; exists in the current context. &lt;br /&gt;
&lt;br /&gt;
===== Variables =====&lt;br /&gt;
There are two types of &#039;&#039;variables&#039;&#039; in the Ekdahl FAR; &#039;&#039;global variables&#039;&#039; and &#039;&#039;event variables&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Global variables&#039;&#039; are variables that are always valid, in any context. The &#039;&#039;global variables&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;notecount&#039;&#039;&#039; - Contains the number of &#039;&#039;MIDI&#039;&#039; keys that are being held down, i.e. all &#039;&#039;Note on messages&#039;&#039; received that haven&#039;t gotten a paired &#039;&#039;Note off message&#039;&#039; yet&lt;br /&gt;
* &#039;&#039;&#039;uv0&#039;&#039;&#039; - &#039;&#039;&#039;uv9&#039;&#039;&#039; - These are &#039;&#039;user variables&#039;&#039; and can be set at any point using the &#039;&#039;globaluservariable command&#039;&#039; with the first &#039;&#039;parameter&#039;&#039; being which variable to set (0-9) and the second &#039;&#039;parameter&#039;&#039; being the value (float).&lt;br /&gt;
* &#039;&#039;&#039;e&#039;&#039;&#039; - Contains the constant &#039;&#039;[[wikipedia:E_(mathematical_constant)|e]]&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pi&#039;&#039;&#039; - Contains the constant &#039;&#039;[[wikipedia:Pi|pi]]&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Event variables&#039;&#039; are variables that are set by certain &#039;&#039;MIDI messages&#039;&#039; or when a new value is read on one of the jacks or knobs on the &#039;&#039;Control box&#039;&#039;. The &#039;&#039;Event variables&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;channel&#039;&#039;&#039; - Set by the &#039;&#039;Note on, Note off, Continuous Controller, Poly after touch, Pitch bend, Channel after touch&#039;&#039; and &#039;&#039;Program change MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;note&#039;&#039;&#039; - Set by the &#039;&#039;Note on, Note off&#039;&#039; and &#039;&#039;Poly after touch MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;velocity&#039;&#039;&#039; - Set by the &#039;&#039;Note on&#039;&#039; and &#039;&#039;Note off MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pressure&#039;&#039;&#039; - Set by the &#039;&#039;Poly after touch&#039;&#039; and &#039;&#039;Channel after touch MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; - Set by the &#039;&#039;Continuous Controller MIDI message&#039;&#039; and by the &#039;&#039;Control box&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pitch&#039;&#039;&#039; - Set by the &#039;&#039;Pitch bend MIDI message&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;program&#039;&#039;&#039; - Set by the &#039;&#039;Program change MIDI message&#039;&#039;&lt;br /&gt;
These variables will contain whatever data is relevant to the last event that occurred and may be overwritten by the next event.&lt;br /&gt;
&lt;br /&gt;
===== Functions =====&lt;br /&gt;
&#039;&#039;Functions&#039;&#039; can be used to change a numerical value or the result of an &#039;&#039;equation&#039;&#039;, the Ekdahl FAR contains both general &#039;&#039;arithmetic functions&#039;&#039; (courtesy of Lewis Van Winkle and the TINYEXPR engine) and &#039;&#039;specialized functions&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;arithmetic functions&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;abs&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Absolute_value|absolute value]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;acos&#039;&#039;&#039;(x), &#039;&#039;&#039;asin&#039;&#039;&#039;(x), &#039;&#039;&#039;atan&#039;&#039;&#039;(x), atan2(x, y) - Returns the [[wikipedia:Inverse_trigonometric_functions|&#039;&#039;arc-cos, -sin, -tan&#039;&#039; and &#039;&#039;-tan2&#039;&#039;]] of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;atan2&#039;&#039;&#039;(x,y) - Returns the &#039;&#039;[[wikipedia:Atan2|arctan2]]&#039;&#039; of &#039;&#039;x, y&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;floor&#039;&#039;&#039;(x), ceil(x) - Returns the [[wikipedia:Floor_and_ceiling_functions|&#039;&#039;floor&#039;&#039; and &#039;&#039;ceiling&#039;&#039;]] of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;exp&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Exponential_function|exponent]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;fac&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Factorial|factorial]]&#039;&#039; of x&lt;br /&gt;
* &#039;&#039;&#039;ln&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Natural_logarithm|natural logarithm]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;log10&#039;&#039;&#039;(x), &#039;&#039;&#039;log20&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Logarithm|logarithm]]&#039;&#039; of &#039;&#039;x&#039;&#039; using base 10 and 20 respectively&lt;br /&gt;
* &#039;&#039;&#039;ncr&#039;&#039;&#039;(x,y), &#039;&#039;&#039;npr&#039;&#039;&#039;(x,y) - Functions to calculate &#039;&#039;[[wikipedia:Combination|combinations]]&#039;&#039; and &#039;&#039;[[wikipedia:Permutation|permutations]]&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pow&#039;&#039;&#039;(x,y) - Returns &#039;&#039;x^y&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;sqrt&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Square_root|square root]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;cos&#039;&#039;&#039;(x), &#039;&#039;&#039;sin&#039;&#039;&#039;(x), &#039;&#039;&#039;tan&#039;&#039;&#039;(x) - Returns the [[wikipedia:Trigonometric_functions|&#039;&#039;cos, sin&#039;&#039; and &#039;&#039;tan&#039;&#039;]] of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;cosh&#039;&#039;&#039;(x), &#039;&#039;&#039;sinh&#039;&#039;&#039;(x), &#039;&#039;&#039;tanh&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Hyperbolic_functions|hyperbolic cos, sin and tan]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
The &#039;&#039;specialized functions&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;bool&#039;&#039;&#039;(x) - Returns 1 if &#039;&#039;x&#039;&#039; is more than 0&lt;br /&gt;
* &#039;&#039;&#039;ibool&#039;&#039;&#039;(x) - Returns 0 if &#039;&#039;x&#039;&#039; is more than 0&lt;br /&gt;
* &#039;&#039;&#039;deadband&#039;&#039;&#039;(x,y) - Returns &#039;&#039;x + y &#039;&#039; if &#039;&#039;x &amp;lt; y&#039;&#039; or &#039;&#039;x - y&#039;&#039; if &#039;&#039;x &amp;gt; y&#039;&#039;. If neither of these statements is true it returns &#039;&#039;0&#039;&#039; - used to create a [[wikipedia:Deadband|deadband]] of &#039;&#039;x&#039;&#039; with the threshold of &#039;&#039;y&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Functions&#039;&#039; can be readily used in a &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
bowmotorrun:1, bowcontrolfrequency:&amp;quot;8.17579875 * pow(2, (1/12 * note))&amp;quot;&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bowingwheel.dcmotor.run:1, bowingwheel.pid.targetfrequency:&amp;quot;8.17579875 * pow(2, (1/12 * note))&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;The previous statements starts the &#039;&#039;bowing wheel&#039;&#039; and sets the frequency of the wheel to &#039;&#039;8.17579875 * 2^(1/12 * note)&#039;&#039;. A middle &#039;C&#039; according to &#039;&#039;MIDI&#039;&#039; has a &#039;&#039;note value&#039;&#039; of 36, meaning if we substitute &#039;&#039;note&#039;&#039; with 36 we get the equation &#039;&#039;8.17579875 * 2^(1/12 * 36)&#039;&#039; which comes out to &#039;&#039;~65.4&#039;&#039; Hertz.&lt;br /&gt;
&lt;br /&gt;
Note that the first &#039;&#039;parameter&#039;&#039; for &#039;&#039;&amp;quot;&#039;&#039;bowcontrolfrequency&amp;quot; / &amp;quot;bowingwheel.pid.targetfrequency&amp;quot; is put in between double quotes (&amp;quot;). This is because the &amp;quot;pow&#039;&#039;&amp;quot;-&#039;&#039;function requires the use of a comma (&amp;quot;,&amp;quot;) in order to separate in between its two required inputs; &#039;&#039;x&#039;&#039; and &#039;&#039;y&#039;&#039;. In order for the Ekdahl FAR to know that this comma does not signal the beginning of a new &#039;&#039;command,&#039;&#039; we use quotes. Single (&#039;) and double (&amp;quot;) quotes can be used and nested in all &#039;&#039;parameters&#039;&#039; and are &amp;lt;u&amp;gt;required&amp;lt;/u&amp;gt; in a lot of circumstances, improper nesting or not using quotes can lead to the instrument not understanding the &#039;&#039;command string&#039;&#039; correctly.&lt;br /&gt;
&lt;br /&gt;
== Return messages ==&lt;br /&gt;
The Ekdahl FAR when connected via &#039;&#039;USB-Serial&#039;&#039; doesn&#039;t only accept &#039;&#039;commands&#039;&#039; but will also send various &#039;&#039;return messages&#039;&#039;. These are prefixed by their &#039;&#039;category&#039;&#039; denoted in brackets (&amp;quot;[]&amp;quot;), the existing categories as of this writing (2025-01-22) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;command&#039;&#039;&#039; / &#039;&#039;&#039;cmd&#039;&#039;&#039; - Acknowledges the reception of a command in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;usb&#039;&#039;&#039; - Acknowledges the reception of a &#039;&#039;MIDI message&#039;&#039; over &#039;&#039;USB&#039;&#039; in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;hardware&#039;&#039;&#039; / &#039;&#039;&#039;hw&#039;&#039;&#039; - Signals that a change has been sent to the Ekdahl FAR hardware, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;undefined&#039;&#039;&#039; / &#039;&#039;&#039;un&#039;&#039;&#039; - The message sent is in the &#039;&#039;undefined&#039;&#039; category, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;priority&#039;&#039;&#039; / &#039;&#039;&#039;pri&#039;&#039;&#039; - The message sent is in the &#039;&#039;priority&#039;&#039; category, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;error&#039;&#039;&#039; / &#039;&#039;&#039;err&#039;&#039;&#039; - Signals that an &#039;&#039;error&#039;&#039; has occurred, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;expressionparser&#039;&#039;&#039; / &#039;&#039;&#039;ep&#039;&#039;&#039; - These messages contains debugging information regarding the internal &#039;&#039;expression parser&#039;&#039; and is used for development&lt;br /&gt;
*&#039;&#039;&#039;debug&#039;&#039;&#039; / &#039;&#039;&#039;dbg&#039;&#039;&#039; - These messages contains various debugging information and is used for development&lt;br /&gt;
*&#039;&#039;&#039;help&#039;&#039;&#039; / &#039;&#039;&#039;hlp&#039;&#039;&#039; - Signals that the message is a response to a &#039;&#039;help&#039;&#039;-command being sent to the Ekdahl FAR. These messages are structured so that a receiver, like the &#039;&#039;Configuration utility&#039;&#039;, can parse information about available &#039;&#039;commands&#039;&#039; in the current &#039;&#039;firmware&#039;&#039; and relay it to a user in a structured way.&lt;br /&gt;
* &#039;&#039;&#039;inforequest&#039;&#039;&#039; / &#039;&#039;&#039;irq&#039;&#039;&#039; - Signals that an &#039;&#039;info request&#039;&#039; has been returned. This is a specialized message that is either sent as a response to an &#039;&#039;rqi&#039;&#039;-command or as a &#039;&#039;interrupt&#039;&#039;-message telling the user or receiving software about different parameters in the Ekdahl FAR. These messages follows the same structure as regular &#039;&#039;command message&#039;&#039;s of &#039;&#039;[irq]commandname:parameter1 [etc]&#039;&#039; so that it can be used by a receiving software to keep track of parameter changes&lt;br /&gt;
&lt;br /&gt;
===== Explicitly requesting information =====&lt;br /&gt;
By using the special command &amp;quot;requestinfo&amp;quot; / &amp;quot;rqi&amp;quot; one can request the information stored by a certain &#039;&#039;command&#039;&#039; or a state of the Ekdahl FAR. The &amp;quot;rqi&amp;quot;-command is executed in the convention &amp;quot;rqi:commandname:optional parameters&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
To go back to our example of setting the bowing frequency using the &#039;&#039;&amp;quot;&#039;&#039;bowcontrolfrequency&amp;quot; / &amp;quot;bowingwheel.pid.targetfrequency&amp;quot;-command we can ask the Ekdahl FAR what the bowing frequency is set to by writing&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
rqi:bowcontrolfrequency&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
rqi:bowingwheel.pid.targetfrequency&lt;br /&gt;
&amp;lt;/pre&amp;gt;The return value would be something like&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
[irq]bcf:82.5&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
[irq]bw[0].pid[0].tf:82.5&lt;br /&gt;
&amp;lt;/pre&amp;gt;Where &#039;[irq]&#039; denotes that the message returned is in the &#039;&#039;info request-&#039;&#039;category, that it pertains to the command &amp;quot;bcf&amp;quot; / &amp;quot;bw.pid.tf&amp;quot; and has the value &#039;&#039;82.5&#039;&#039;. Note that the returned &#039;&#039;command&#039;&#039; sent by an &amp;quot;rqi&amp;quot;-command always uses the &#039;&#039;short name&#039;&#039; in order to preserve bandwidth. In the FAR 1.1 the return statement always returns the &#039;&#039;index&#039;&#039; of the &#039;&#039;module&#039;&#039;(s) in question. &lt;br /&gt;
&lt;br /&gt;
Most commands do not require any &#039;&#039;parameters&#039;&#039; when using the &amp;quot;rqi&amp;quot;-command. The &#039;&#039;&amp;quot;&#039;&#039;adcread&amp;quot; / &amp;quot;controlbox.datareturn&amp;quot;-command is an example of a &#039;&#039;command&#039;&#039; that &amp;lt;u&amp;gt;does&amp;lt;/u&amp;gt; require a &#039;&#039;parameter&#039;&#039; when used with &amp;quot;rqi&amp;quot;. The &amp;quot;adcread&amp;quot; / &amp;quot;controlbox.datareturn&amp;quot;&#039;&#039;-&#039;&#039;command returns the last value read by the &#039;&#039;analog-to-digital converter&#039;&#039; in the &#039;&#039;Control box&#039;&#039;, because there are 8 different channels the first &#039;&#039;parameter&#039;&#039; sets which channel to return the data for, hence executing the &#039;&#039;command&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
rqi:adcr:3&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
rqi:controlbox.datareturn:3&lt;br /&gt;
&amp;lt;/pre&amp;gt;will return the last data read on &#039;&#039;analog-to-digital convert&#039;&#039; channel 3.&lt;br /&gt;
&lt;br /&gt;
== MIDI mapping ==&lt;br /&gt;
The way &#039;&#039;MIDI&#039;&#039; works int the Ekdahl FAR is that each &#039;&#039;MIDI message&#039;&#039; is associated with a certain &#039;&#039;command string&#039;&#039; and the &#039;&#039;MIDI message&#039;&#039; will also update some of the internal &#039;&#039;variables&#039;&#039;. Any time the associated &#039;&#039;MIDI message&#039;&#039; is received the Ekdahl FAR will execute the &#039;&#039;commands&#039;&#039; that have been associated with that &#039;&#039;MIDI message&#039;&#039;. Several &#039;&#039;MIDI configurations&#039;&#039; can be stored and recalled at any time, each with a different set of &#039;&#039;commands&#039;&#039; associated with each &#039;&#039;MIDI message&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;FAR &amp;lt; 1.1&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 The &#039;&#039;command&#039;&#039; responsible for mapping &#039;&#039;command strings&#039;&#039; to different &#039;&#039;MIDI messages&#039;&#039; is &amp;quot;midieventhandler&amp;quot; or &amp;quot;mev&amp;quot; for short. The first &#039;&#039;parameter&#039;&#039; of &amp;quot;mev&amp;quot; is the type of &#039;&#039;MIDI message&#039;&#039; that we want to remap;&lt;br /&gt;
 &lt;br /&gt;
 * &#039;&#039;&#039;noteon&#039;&#039;&#039; - Note on&lt;br /&gt;
 * &#039;&#039;&#039;noteoff&#039;&#039;&#039; - Note off&lt;br /&gt;
 * &#039;&#039;&#039;pat&#039;&#039;&#039; - Poly after touch&lt;br /&gt;
 * &#039;&#039;&#039;cat&#039;&#039;&#039; - Channel after touch&lt;br /&gt;
 * &#039;&#039;&#039;pb&#039;&#039;&#039; - Pitch bend&lt;br /&gt;
 * &#039;&#039;&#039;pc&#039;&#039;&#039; - Program change&lt;br /&gt;
 * &#039;&#039;&#039;cc&#039;&#039;&#039; - Continuous controller&lt;br /&gt;
 &lt;br /&gt;
 The second &#039;&#039;parameter&#039;&#039; is the &#039;&#039;command string&#039;&#039; that is to be associated with the &#039;&#039;MIDI Message&#039;&#039; - with the exception of the &#039;&#039;&#039;cc&#039;&#039;&#039;-type, here the second &#039;&#039;parameter&#039;&#039; is the &#039;&#039;controller number&#039;&#039; (0 - 127) and the third &#039;&#039;parameter&#039;&#039; is the &#039;&#039;command string&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;FAR 1.1&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 The &amp;quot;bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; contains a &#039;&#039;module&#039;&#039; called &amp;quot;midiconfigurationhandler&amp;quot; that handles the loading and switching in between different &#039;&#039;MIDI configurations&#039;&#039;. The &amp;quot;midiconfigurationhandler&amp;quot;&#039;&#039;-module&#039;&#039; has one or more &#039;&#039;&amp;quot;&#039;&#039;midiconfiguration&amp;quot;-&#039;&#039;modules&#039;&#039;, each having its own &#039;&#039;MIDI&#039;&#039; settings. In order to change the &#039;&#039;command mapping&#039;&#039; for a &#039;&#039;MIDI message&#039;&#039; in a specific &#039;&#039;MIDI configuration&#039;&#039;, the following &#039;&#039;commands&#039;&#039; are used;&lt;br /&gt;
 &lt;br /&gt;
 * &#039;&#039;&#039;noteon/non&#039;&#039;&#039;:&#039;&#039;commands&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed for a &#039;note on&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;noteoff/nof&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;note off&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;polyaftertouch/pat&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;poly aftertouch&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;channelaftertouch/cat&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;channel aftertouch&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;pitchbend/pb&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;pitch bend&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;programchange/pc&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;program change&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;continuouscontrollerdata/ccd&#039;&#039;&#039;&#039;&#039;:controller:commands&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed for &#039;continuous controller&#039; no &#039;&#039;controller&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
We can of course use the &#039;&#039;&amp;quot;&#039;&#039;rqi&amp;quot;-&#039;&#039;command&#039;&#039; to check the current mapping, below we are asking what the current &#039;&#039;command string&#039;&#039; associated with the &#039;&#039;pitch bend&#039;&#039; &#039;&#039;MIDI message&#039;&#039; is in the currently selected &#039;&#039;MIDI configuration&#039;&#039;.&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
rqi:midieventhandler:pb&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
rqi:bowingwheel.midiconfigurationhandler.midiconfiguration.pitchbend&lt;br /&gt;
&amp;lt;/pre&amp;gt;This may return something like&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
[irq]mev:pb:&amp;quot;bowcontrolharmonicshift:pitch*4&amp;quot;&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
[irq]bw[0].mcf[0].mc[0].pb:&amp;quot;bowingwheel.harmonicserieshandler.harmonicseries.shift:pitch*4&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;The first part of the return message tells us that the incoming message is of &amp;quot;rqi&amp;quot;-type (&amp;quot;[irq]&amp;quot;) which means it&#039;s responding to a information request &#039;&#039;command&#039;&#039; sent. The second part tells us what &#039;&#039;command&#039;&#039; the information request return is responding to and any &#039;&#039;parameters&#039;&#039; that may be pertinent. The third part of the message is the actual data stored.  &lt;br /&gt;
&lt;br /&gt;
For the FAR &amp;lt; 1.1 the data returned is for the &#039;&#039;command&#039;&#039; &amp;quot;mev&amp;quot; with the first &#039;&#039;parameter&#039;&#039; set to &amp;quot;pb&amp;quot;, the &#039;&#039;command reference&#039;&#039; tells us this means the &#039;&#039;command&#039;&#039; &amp;quot;midieventhandler&amp;quot; and the &#039;&#039;parameter&#039;&#039; &amp;quot;pb&amp;quot; indicates this has to do with the &#039;&#039;pitch bend&#039;&#039;. The data is &amp;quot;bowcontrolharmonicshift:pitch*4&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
For the FAR 1.1 the data returned is for the &#039;&#039;command&#039;&#039; &amp;quot;bw[0].mcf[0].mc[0].pb&amp;quot; (bowinwheel[0].midiconfigurationhandler[0].midiconfiguration[0].pitchbend) and the data is &amp;quot;bowingwheel.harmonicserieshandler.harmonicseries.shift:pitch*4&amp;quot;. Note here that if we have several different &#039;&#039;MIDI configurations&#039;&#039; stored and we&#039;re currently using configuration number 2, the returned message would have been &amp;quot;bw[0].mcf[0].mc[2].pb&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
that the &#039;&#039;pitch bend MIDI message&#039;&#039; is executing a &amp;quot;bowcontrolharmonicshift&amp;quot; / &amp;quot;harmonicseries.shift&amp;quot;-command with the parameter &#039;&#039;pitch*4&#039;&#039;. Looking in the &#039;&#039;command reference&#039;&#039; we can see that &#039;&#039;&amp;quot;&#039;&#039;bowcontrolharmonicshift&amp;quot; / &amp;quot;harmonicseries.shift&amp;quot;-&#039;&#039;command&#039;&#039; shifts the frequency of the &#039;&#039;bowing wheel&#039;&#039; from the currently selected harmonic. The first (and only) &#039;&#039;parameter&#039;&#039; sets how much we want to shift it (the range depends on the &amp;quot;bowcontrolharmonicshiftrange&#039;&#039;&amp;quot;&#039;&#039; / &amp;quot;harmonicseries.shiftrange&amp;quot;-&#039;&#039;command&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
If we look in the list of &#039;&#039;[[The Ekdahl FAR - Command langue#Variables|variables]]&#039;&#039; above we can see that the &#039;&#039;pitch bend MIDI message&#039;&#039; will set the &amp;quot;pitch&amp;quot;&#039;&#039;-variable&#039;&#039; which is indeed used. Now what is the &#039;&#039;&#039;*4&#039;&#039;&amp;lt;nowiki/&amp;gt;&#039; all about? Well the &amp;quot;bowcontrolharmonicshift&amp;quot; / &amp;quot;harmoniceseries.shift&amp;quot;-&#039;&#039;command&#039;&#039; expects a &#039;&#039;16-bit signed&#039;&#039; value as its &#039;&#039;parameter&#039;&#039;. This means that the valid &#039;&#039;parameter&#039;&#039; number can be anything from -32767 to 32767. A full &#039;&#039;harmonic shift&#039;&#039; downwards according to the range set is equal to -32767, a full &#039;&#039;harmonic shift&#039;&#039; upwards is 32767 and no &#039;&#039;harmonic shift&#039;&#039; is 0. The &#039;&#039;pitch bend MIDI message&#039;&#039; however is only 14-bits, meaning its range is -8192 to 8192. So we have to multiply &#039;&#039;pitch&#039;&#039; by 4 in order to meet the requirements of a &#039;&#039;16-bit signed parameter&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
This whole thing about number of bits can seem confusing but in the end it&#039;s all about how fine control you have over things; the more possible values, the more detailed control. In fact, most &#039;&#039;MIDI&#039;&#039; values are only 7-bit (!) meaning a range of 0 - 127. While this may sound like a lot of detail for something like a volume control, it is not even close to enough resolution to for instance set the &#039;&#039;bowing frequency&#039;&#039;. Even if you would limit yourself to a single octave the instrument would never be able to be properly in tune. The idea of limiting the Ekdahl FAR to what is possible through &#039;&#039;MIDI&#039;&#039; seemed like a poor choice thus it was decided that &amp;lt;u&amp;gt;most&amp;lt;/u&amp;gt; parameters will instead be 16-bit.&lt;br /&gt;
&lt;br /&gt;
Now lets look at a more complex example, the &amp;lt;u&amp;gt;default&amp;lt;/u&amp;gt; &#039;&#039;Note On MIDI message&#039;&#039;. On a stock Ekdahl FAR, executing&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
rqi:mev:noteon&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
rqi:mcf.mf.non&lt;br /&gt;
&amp;lt;/pre&amp;gt;Will return something like&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
[irq]mev:noteon:&#039;bchb:note,bmr:1,bpid:1,bpe:1,se:(velocity*512)*(1-notecount),bcsm:0&#039;&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
[irq]mcf[0].mc[0].non:&#039;bw.hsh.hb:note,bw.dcm.ru:1,bw.pe:1,bw.bp.en:1,so.en:(velocity*512)*(1-notecount),bw.sm:0&#039;&amp;lt;/pre&amp;gt;As can be seen, there&#039;s a lot of stuff going on here! First of all, notice that everything after &amp;quot;mev:noteon:&amp;quot; / &amp;quot;mcf[0].mc[0].non:&amp;quot; is situated in between single quotes (&#039;) - this is &amp;lt;u&amp;gt;absolutely crucial&amp;lt;/u&amp;gt; for the Ekdahl FAR in order to know that everything within those last two quotes is part of the last &#039;&#039;parameter&#039;&#039; of the &amp;quot;mev&amp;quot; / &amp;quot;mcf.mc.non&amp;quot;-&#039;&#039;command&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Now let&#039;s break down what happens when this &#039;&#039;MIDI message&#039;&#039; is received, i.e. when a &#039;&#039;MIDI&#039;&#039; key is pressed down:&lt;br /&gt;
&lt;br /&gt;
# &amp;quot;bchb:note&amp;quot; / &amp;quot;bw.hsh.hb:note&amp;quot;  - Invokes the &amp;quot;bowcontrolharmonicbase&amp;quot; / &amp;quot;harmonicserieshandler.harmonicbase&amp;quot;&#039;&#039;-command&#039;&#039; with the first &#039;&#039;parameter&#039;&#039; set to the &#039;&#039;variable &amp;quot;&#039;&#039;note&amp;quot;. This sets the &#039;&#039;base harmonic&#039;&#039; that the Ekdahl FARs &#039;&#039;bowing motor&#039;&#039; should be set to. Here the &#039;&#039;variable&#039;&#039; &amp;quot;note&amp;quot; is used which is simply the MIDI key being pressed down, it is automatically converted by the &#039;&#039;command&#039;&#039; to the corresponding harmonic in the &#039;&#039;harmonic list&#039;&#039;&lt;br /&gt;
# &amp;quot;bmr:1&amp;quot; / &amp;quot;bw.dcm.ru&amp;quot; - Sets the &amp;quot;bowmotorrun&amp;quot; / &amp;quot;dcmotor.run&amp;quot;-command to &#039;1&#039;, starting the &#039;&#039;bow motor&#039;&#039;&lt;br /&gt;
# &amp;quot;bpid:1&amp;quot; / &amp;quot;bw.pe:1&amp;quot; - Sets the &amp;quot;bowpid&amp;quot; / &amp;quot;bowingwheel.pidenable&amp;quot;-&#039;&#039;command&#039;&#039; to &#039;1&#039;. Basically this enables the function that makes the Ekdahl FAR able to keep a stable frequency on the &#039;&#039;bowing motor&#039;&#039;.&lt;br /&gt;
# &amp;quot;bpe:1&amp;quot; / &amp;quot;bw.bp.en&amp;quot; - Sets the &amp;quot;bowpressureengage&amp;quot; / &amp;quot;bowpressure.engage&amp;quot;-&#039;&#039;command&#039;&#039; to &#039;1&#039; which moves the &#039;&#039;bowing jack&#039;&#039; to the &#039;&#039;engage position&#039;&#039;, aka just below the string if not additional &#039;&#039;pressure&#039;&#039; is applied&lt;br /&gt;
# &amp;quot;se:(velocity*512)*(1-notecount)&amp;quot; / &amp;quot;so.en:(velocity*512)*(1-notecount)&amp;quot; - Executes the &amp;quot;solenoidengage&amp;quot; / &amp;quot;solenoid.engage&amp;quot;-&#039;&#039;command&#039;&#039; with the value &#039;&#039;(velocity*512)*(1-notecount)&#039;&#039;. This will make the &#039;&#039;solenoid&#039;&#039; strike the &#039;&#039;hammer&#039;&#039; with a force that is dependent on the &amp;quot;velocity&amp;quot;-&#039;&#039;variable&#039;&#039; sent by the &#039;&#039;Note On MIDI message&#039;&#039; in order to make the &#039;&#039;hammer&#039;&#039; velocity sensitive.   But it also adds the somewhat perplexing part &amp;quot;*(1-notecount)&amp;quot;. &amp;quot;notecount&amp;quot; is a global &#039;&#039;variable&#039;&#039; that contains the number of MIDI keys that are currently being held down. If &amp;quot;notecount&amp;quot; is anything above zero, the outcome of the equation will either be zero or a negative number. The &amp;quot;solenoidengage&amp;quot; / &amp;quot;solenoid.engage&amp;quot;-&#039;&#039;command&#039;&#039; requires a &#039;&#039;16-bit unsigned&#039;&#039; value, aka the only valid numbers are 0 - 65535. Anything below 0 will be interpreted as zero, so what this equation does is that it only fires off the &#039;&#039;hammer&#039;&#039; if there are no previous keys being held down - it&#039;s being used in &#039;&#039;staccato&#039;&#039;  mode.&lt;br /&gt;
# &amp;quot;bcsm:0&amp;quot; / &amp;quot;bowingwheel.speedmode&amp;quot; - Sets the &amp;quot;bowcontrolspeedmode&amp;quot; / &amp;quot;bowingwheel.speedmode&amp;quot; to &#039;1&#039; which enables automatic shut down of the &#039;&#039;bowing motor&#039;&#039; after a given timeout.&lt;br /&gt;
Let&#039;s postulate that the Ekdahl FAR is tuned to a &#039;C&#039; at 65.4Hz and has its &#039;&#039;base&#039;&#039; set to middle &#039;C&#039; (&#039;&#039;MIDI key&#039;&#039; no 36). We are using the equal-temperament 12-tone scale and the Ekdahl FAR is set to respond to &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; &#039;&#039;MIDI channels&#039;&#039; (omni). Without having previously held any keys we press the middle &#039;C&#039; (&#039;&#039;note&#039;&#039; value 36) as hard as possible (&#039;&#039;velocity&#039;&#039; value &#039;&#039;127&#039;&#039;) on &#039;&#039;MIDI channel&#039;&#039; number 1 (&#039;&#039;channel&#039;&#039; value of 0). The Ekdahl FAR will get a &#039;&#039;note on MIDI message&#039;&#039; sent to it and from our mapping it will create the following &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
[irq]mev:noteon:&#039;bchb:36,bmr:1,bpid:1,bpe:1,se:(127*512)*(1-0),bcsm:0&#039;&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
[irq]mcf[0].mc[0].non:&#039;bw.hsh.hb:36,bw.dcm.ru:1,bw.pe:1,bw.bp.en:1,so.en:(127*512)*(1-0),bw.sm:0&#039;&amp;lt;/pre&amp;gt;What has happened here is that all &#039;&#039;variables&#039;&#039; have been replaced with the values sent by the &#039;&#039;MIDI message&#039;&#039;. Since those &#039;&#039;commands&#039;&#039; that doesn&#039;t have any &#039;&#039;variables&#039;&#039; with them will execute just as previously, only those &#039;&#039;commands&#039;&#039; whos &#039;&#039;parameters&#039;&#039; have changed will be explained:&lt;br /&gt;
&lt;br /&gt;
# &amp;quot;bchb: 36&amp;quot; / &amp;quot;bw.hsh.hb:36&amp;quot; - The &amp;quot;bowcontrolharmonicbase&amp;quot; / &amp;quot;harmonicserieshandler.harmonicbase&amp;quot; gets a value of &#039;&#039;36&#039;&#039; (middle &#039;C&#039;), because &#039;&#039;harmonic number 0&#039;&#039; is mapped to this key it will set the &#039;&#039;bowing wheel&#039;&#039; frequency to the &#039;&#039;fundamental&#039;&#039;; &#039;&#039;65.4&#039;&#039; Hertz&lt;br /&gt;
# &amp;quot;se: (127*512)*(1-0)&amp;quot; / &amp;quot;so.en: (127*512)*(1-0)&amp;quot; - the value of &#039;&#039;127&#039;&#039; comes from the &amp;quot;velocity&amp;quot;-&#039;&#039;variable&#039;&#039;, &#039;&#039;127 * 512 = 65024&#039;&#039; which is awfully close to a maximum hammer force of 65535. Since no previous notes were held down, the &#039;&#039;&amp;quot;&#039;&#039;notecount&amp;quot;-&#039;&#039;variable&#039;&#039;  is equal to &#039;&#039;0&#039;&#039; and thus &#039;&#039;65024 * 1 = 65024&#039;&#039;. The hammer is engaged with near maximum force.&lt;br /&gt;
So the result is that we have set the speed of the &#039;&#039;bowing motor&#039;&#039; and we have engaged the &#039;&#039;hammer&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Now imagine that without releasing this key, we press another &#039;C&#039; one octave above but at half the velocity. The Ekdahl FAR creates the following &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
[irq]mev:noteon:&#039;bchb:48,bmr:1,bpid:1,bpe:1,se:(63*512)*(1-1),bcsm:0&#039;&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
[irq]mcf[0].mc[0].non:&#039;bw.hsh.hb:48,bw.dcm.ru:1,bw.pe:1,bw.bp.en:1,so.en:(65*512)*(1-1),bw.sm:0&#039;&lt;br /&gt;
&amp;lt;/pre&amp;gt;Now we can see that the &amp;quot;note&amp;quot;-&#039;&#039;variable&#039;&#039; is 48 because the &#039;C&#039; one octave up is exactly 12 keys above the first. The &amp;quot;velocity&amp;quot;-&#039;&#039;variable&#039;&#039; has changed to 63 since we hit it with a lighter touch - and because we are &amp;lt;u&amp;gt;still holding the first key down&amp;lt;/u&amp;gt;, the &amp;quot;notecount&amp;quot;-&#039;&#039;variable&#039;&#039; is equal to &#039;&#039;1&#039;&#039;. Here&#039;s what happens&lt;br /&gt;
&lt;br /&gt;
# &amp;quot;bchb: 48&amp;quot; / &amp;quot;hsh.hb:48&amp;quot; - Due to the &#039;&#039;base&#039;&#039; being set to &#039;&#039;36&#039;&#039; the &#039;&#039;harmonic number&#039;&#039; is set to &#039;&#039;48 - 36 = 12&#039;&#039;. Because we are using a 12-tone scale &#039;&#039;harmonic number 12&#039;&#039; is exactly one octave above the &#039;&#039;fundamental&#039;&#039; thus the speed of the &#039;&#039;bowing wheel&#039;&#039; is set to &#039;&#039;65.4 * 2 = 130.8&#039;&#039; Hertz.&lt;br /&gt;
# &amp;quot;se: (63*512)*(1-1)&amp;quot; / &amp;quot;so.en: (63*512)*(1-1)&amp;quot; - The equation evalutes as &#039;&#039;63 * 512 = 32256&#039;&#039; and &#039;&#039;1 - 1 = 0&#039;&#039; thus &#039;&#039;32256 * 0 = 0&#039;&#039;. When the &amp;quot;solenoidengage&amp;quot; / &amp;quot;solenoid.engage&amp;quot;-&#039;&#039;command&#039;&#039; gets a &#039;&#039;parameter&#039;&#039; of &#039;&#039;0&#039;&#039; it will not engage the &#039;&#039;hammer&#039;&#039; - so the &#039;&#039;hammer&#039;&#039; doesn&#039;t strike&lt;br /&gt;
So it can be seen that with quite rudimentary math we can accomplish a whole lot of things here. Note also that even though the &#039;&#039;note on MIDI message&#039;&#039; also sets the &#039;&#039;channel&#039;&#039;-variable we never use it in this example - plenty of opportunity to make something weird happen depending on the &#039;&#039;MIDI channel&#039;&#039;!&lt;br /&gt;
&lt;br /&gt;
== CV Mapping ==&lt;br /&gt;
&#039;&#039;CV Mapping&#039;&#039; works exactly like the &#039;&#039;MIDI mapping&#039;&#039; with the difference that the command(s) for setting the &#039;&#039;CV mapping&#039;&#039; is different and that they all modify (and thus share) the &amp;quot;value&amp;quot;-&#039;&#039;variable&#039;&#039;. These &#039;&#039;events&#039;&#039; are triggered whenever the analog-to-digital converter senses a change in a control or modulation jack, if you use something like an LFO with the modulation jacks here you will get a LOT of events and subsequent &#039;&#039;commands&#039;&#039; being sent.  &lt;br /&gt;
 &#039;&#039;&#039;FAR &amp;lt; 1.1:&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 The command for changing the CV mapping is &amp;quot;adccommandmap&amp;quot; or &amp;quot;acm&amp;quot;, it take two parameters; channel and command string. The channels on the original Edkahl FAR Control box are as &lt;br /&gt;
 &lt;br /&gt;
 * 0 - The &amp;quot;Harmonic&amp;quot; knob and jack&lt;br /&gt;
 * 1 - The &amp;quot;Harmonic shift&amp;quot; knob and jack&lt;br /&gt;
 * 2 - The &amp;quot;Fine tune&amp;quot; knob&lt;br /&gt;
 * 3 - The &amp;quot;Pressure&amp;quot; knob and jack&lt;br /&gt;
 * 4 - The &amp;quot;Hammertrig&amp;quot; button and jack&lt;br /&gt;
 * 5 - The &amp;quot;Gate&amp;quot; switch and jack&lt;br /&gt;
 * 6 - The &amp;quot;Hammer Scale&amp;quot; knob&lt;br /&gt;
 * 7 - The &amp;quot;Mute&amp;quot; knob and jack&lt;br /&gt;
 &lt;br /&gt;
 &#039;&#039;&#039;FAR 1.1:&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 The commands responsible for changing the CV mapping are located in the &amp;quot;controlbox&amp;quot;-module, these are&lt;br /&gt;
 &lt;br /&gt;
 * &#039;&#039;&#039;harmonic&#039;&#039;&#039; &#039;&#039;&#039;/ har&#039;&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed when the &amp;quot;Harmonic&amp;quot;-knob or modulation changes&lt;br /&gt;
 * &#039;&#039;&#039;harmonicshift&#039;&#039;&#039; &#039;&#039;&#039;/ has&#039;&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed when the &amp;quot;Harmonic shift&amp;quot;-knob or modulation changes&lt;br /&gt;
 * &#039;&#039;&#039;finetune / fin&#039;&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed when the &amp;quot;Fine tune&amp;quot;-knob changes&lt;br /&gt;
 * &#039;&#039;&#039;pressure&#039;&#039;&#039; &#039;&#039;&#039;/ pre&#039;&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed when the &amp;quot;Pressure&amp;quot;-knob or modulation changes&lt;br /&gt;
 * &#039;&#039;&#039;mute&#039;&#039;&#039; &#039;&#039;&#039;/ mut&#039;&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed when the &amp;quot;Mute&amp;quot;-knob or modulation changes&lt;br /&gt;
 * &#039;&#039;&#039;hammerscale / hms&#039;&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed when the &amp;quot;Hammer scale&amp;quot;-knob changes&lt;br /&gt;
 * &#039;&#039;&#039;gate / gt&#039;&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed when the &amp;quot;Gate&amp;quot;-switch or modulation changes&lt;br /&gt;
 * &#039;&#039;&#039;hammertrig&#039;&#039;&#039; &#039;&#039;&#039;/ hmt&#039;&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed when the &amp;quot;Hammer Trig&amp;quot;-button or modulation changes&lt;br /&gt;
In order to set/retrieve &#039;&#039;mapping data&#039;&#039; we just use a regular &amp;quot;rqi&amp;quot;-&#039;&#039;command&#039;&#039;. To for instance get the &#039;&#039;command string&#039;&#039; executed when the &amp;quot;pressure&amp;quot; knob or modulation is sent we can do the following&lt;br /&gt;
 &#039;&#039;&#039;FAR &amp;lt; 1.1:&#039;&#039;&#039;&lt;br /&gt;
 [send] rqi:acm:3&lt;br /&gt;
 [returns] [irq]acm:3:&#039;bpb:value&#039;&lt;br /&gt;
 &lt;br /&gt;
 &#039;&#039;&#039;FAR 1.1:&#039;&#039;&#039;&lt;br /&gt;
 [send] rqi:controlbox.pressure&lt;br /&gt;
 [returns] [irq]cb[0].pre:&#039;bw.bp.ba:value&#039;&lt;br /&gt;
As can be seen, when the &#039;&#039;pressure&#039;&#039; knob or modulation changes, the new data read by the ADC (stored in the &amp;quot;value&amp;quot;-&#039;&#039;variable&#039;&#039;) is sent to the &#039;&#039;command&#039;&#039; controlling the &#039;&#039;bow pressure baseline.&#039;&#039; Hopefully at this point it is obvious that making the knob and jack on the &#039;&#039;control box&#039;&#039; that is labeled as &amp;quot;Pressure&amp;quot; do something completely different, is quite easy - just remap the &#039;&#039;command string&#039;&#039;.{{docnav&lt;br /&gt;
|[[The Ekdahl FAR - Service|Service]]&lt;br /&gt;
|[[The Ekdahl FAR - Command reference|Command reference]]&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Knaadmin</name></author>
	</entry>
	<entry>
		<id>http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_reference_V1.0&amp;diff=1660</id>
		<title>The Ekdahl FAR - Command reference V1.0</title>
		<link rel="alternate" type="text/html" href="http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_reference_V1.0&amp;diff=1660"/>
		<updated>2026-06-12T10:44:30Z</updated>

		<summary type="html">&lt;p&gt;Knaadmin: Knaadmin moved page The Ekdahl FAR - Command reference to The Ekdahl FAR - Command reference V1.0 without leaving a redirect&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
The &#039;&#039;commands&#039;&#039; in the Ekdahl FAR are using a certain &#039;&#039;naming convention&#039;&#039; to make it more clear which parts of the instrument a certain &#039;&#039;command&#039;&#039; is dealing with. Furthermore commands can be global or local, global commands change settings that will affect the entire instrument, local commands change settings depending on previously set commands. The idea of local commands is a future-proofing of the Ekdahl FAR firmware and can generally be ignored for the time being. The first part of many &#039;&#039;command&#039;&#039;-names are a prefix that denotes category, the &#039;&#039;global&#039;&#039; categories as of this writing (2025-01-26) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;global*&#039;&#039; - commands that have a global reach&lt;br /&gt;
* &#039;&#039;midi*&#039;&#039; - commands that deal with &#039;&#039;MIDI&#039;&#039;&lt;br /&gt;
* &#039;&#039;adc*&#039;&#039; - commands that deal with the &#039;&#039;Control box&#039;&#039; and its &#039;&#039;analog-to-digital converter&#039;&#039;&lt;br /&gt;
* &#039;&#039;expressionparser&#039;&#039; - commands that deal with how &#039;&#039;commands&#039;&#039; are interpreted and parsed, mainly used for debugging&lt;br /&gt;
* &#039;&#039;test&#039;&#039;* - commands made for testing and debugging&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;global&#039;&#039; commands as of this writing (2025-01-26) are:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|requestinfo&lt;br /&gt;
|rqi&lt;br /&gt;
|[command]:[optional parameters]&lt;br /&gt;
|Uses a &#039;&#039;command&#039;&#039;-name to retrieve rather than set information associated with it, some commands have no information associated and will return nothing. Some commands require the use of optional &#039;&#039;parameters&#039;&#039; to specify which information that is to be retrieved.&lt;br /&gt;
|-&lt;br /&gt;
|module&lt;br /&gt;
|m&lt;br /&gt;
|[module number (0)]&lt;br /&gt;
|Sets the current &#039;&#039;module&#039;&#039;. This command is intended for future versions of the Ekdahl FAR that may have more than one &#039;&#039;string module.&#039;&#039; Currently &#039;0&#039; is the only valid &#039;&#039;parameter&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|modulecount&lt;br /&gt;
|mc&lt;br /&gt;
|none&lt;br /&gt;
|Returns the number of &#039;&#039;modules&#039;&#039; in the Ekdahl FAR. Currently always returns &#039;1&#039;&lt;br /&gt;
|-&lt;br /&gt;
|debugprint&lt;br /&gt;
|dp&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;[command|usb|hardware|undefined|priority|error|inforequest|expressionparser|debug]:[0|1]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Used to turn on or off whether the instrument will return certain information over &#039;&#039;USB-Serial&#039;&#039;. The first &#039;&#039;parameter&#039;&#039; is the category, the second &#039;&#039;parameter&#039;&#039; is a boolean value.&lt;br /&gt;
|-&lt;br /&gt;
|version&lt;br /&gt;
|ver&lt;br /&gt;
|none&lt;br /&gt;
|Returns the current &#039;&#039;firmware&#039;&#039; version&lt;br /&gt;
|-&lt;br /&gt;
|globalsaveallparameters&lt;br /&gt;
|gsap&lt;br /&gt;
|none&lt;br /&gt;
|Saves all current data into the internal flash memory&lt;br /&gt;
|-&lt;br /&gt;
|globalloadallparameters&lt;br /&gt;
|glap&lt;br /&gt;
|none&lt;br /&gt;
|Loads all data saved into flash, effectively overwriting any changed parameters included in the last save&lt;br /&gt;
|-&lt;br /&gt;
|globalresetparameters&lt;br /&gt;
|grap&lt;br /&gt;
|none&lt;br /&gt;
|Resets all saved data in the flash memory, requires a immediate reset to be enacted&lt;br /&gt;
|-&lt;br /&gt;
|globaluservariable&lt;br /&gt;
|guv&lt;br /&gt;
|[variable number (0-9)]:[value (float)]&lt;br /&gt;
|Sets or returns the user variable defined in the first &#039;&#039;parameter,&#039;&#039; if used to set the variable, the second &#039;&#039;parameter&#039;&#039; is the value.&lt;br /&gt;
|-&lt;br /&gt;
|expressionparserevaluate&lt;br /&gt;
|epev&lt;br /&gt;
|[expression]&lt;br /&gt;
|Evaluates the given &#039;&#039;expression&#039;&#039; and returns the calculated value. Used for debugging&lt;br /&gt;
|-&lt;br /&gt;
|testadclatency&lt;br /&gt;
|tal&lt;br /&gt;
|[value (0 - 65535)]&lt;br /&gt;
|Debugging command to test ADC latency&lt;br /&gt;
|-&lt;br /&gt;
|testadclatencyreturn&lt;br /&gt;
|talr&lt;br /&gt;
|none&lt;br /&gt;
|Stops ADC latency testing started with &#039;&#039;tal&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|testadcminmac&lt;br /&gt;
|tamm&lt;br /&gt;
|[channel]&lt;br /&gt;
|Debugging command to test the min/max value for a given &#039;&#039;channel&#039;&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
MIDI commands&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|midiconfiguration&lt;br /&gt;
|mcf&lt;br /&gt;
|[config (0-9)]&lt;br /&gt;
|Sets or returns the &#039;&#039;current MIDI configuration&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|midiconfigurationadd&lt;br /&gt;
|mcfa&lt;br /&gt;
|none&lt;br /&gt;
|Adds a new &#039;&#039;MIDI configuration&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|midiconfigurationremove&lt;br /&gt;
|mcfr&lt;br /&gt;
|[config (0-9)]&lt;br /&gt;
|Removes the &#039;&#039;MIDI configuration&#039;&#039; denoted by the &#039;&#039;parameter&#039;&#039; passed. If there are &#039;&#039;MIDI configurations&#039;&#039; with a higher number, these are moved down the list. The &#039;&#039;current configuration&#039;&#039; may be changed during the execution of this &#039;&#039;command&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|midiconfigurationcount&lt;br /&gt;
|mcfc&lt;br /&gt;
|none&lt;br /&gt;
|Returns the number of &#039;&#039;MIDI configurations&#039;&#039; available&lt;br /&gt;
|-&lt;br /&gt;
|midiconfigurationname&lt;br /&gt;
|mcfn&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;[config|name]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|When used as a &#039;set&#039;-command, the first &#039;&#039;parameter&#039;&#039; sets the name of the &#039;&#039;current MIDI configuration&#039;&#039;. When used to retrieve information, the first &#039;&#039;parameter&#039;&#039; sets &amp;lt;u&amp;gt;which&amp;lt;/u&amp;gt; &#039;&#039;MIDI configuration&#039;&#039; to return the name for&lt;br /&gt;
|-&lt;br /&gt;
|midieventhandler&lt;br /&gt;
|mev&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;[noteon|noteoff|pat|cc[:0-127]|cat|pb|pc]:[command string]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Used to set the &#039;&#039;command string&#039;&#039; executed when a certain &#039;&#039;MIDI event&#039;&#039; occurs. The first &#039;&#039;parameter&#039;&#039; is the type of &#039;&#039;MIDI event.&#039;&#039; With exception for the &#039;&#039;&amp;lt;nowiki/&amp;gt;&#039;cc&#039; MIDI event&#039;&#039; the second &#039;&#039;parameter&#039;&#039; is the &#039;&#039;command string&#039;&#039;. For &#039;&#039;&amp;lt;nowiki/&amp;gt;&#039;cc&#039;&#039;&#039; the second &#039;&#039;parameter&#039;&#039; is the &#039;&#039;controller number&#039;&#039; and the third &#039;&#039;parameter&#039;&#039; is the &#039;&#039;command string&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|midiconfigurationdefaults&lt;br /&gt;
|mcfd&lt;br /&gt;
|none&lt;br /&gt;
|Reverts all settings of the &#039;&#039;current MIDI configuration&#039;&#039; to default values and remove any added &#039;&#039;continuous controllers&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|midireceivechannel&lt;br /&gt;
|mrc&lt;br /&gt;
|[channel (0-16)]&lt;br /&gt;
|Sets which &#039;&#039;MIDI channel&#039;&#039; the instrument will respond to. 1-16 sets the &#039;&#039;MIDI channel&#039;&#039; while &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; other values sets the instrument to &#039;&#039;&amp;lt;nowiki/&amp;gt;&#039;Omni&#039;&#039;&#039; (the instrument responding to all channels)&lt;br /&gt;
|-&lt;br /&gt;
|midiallnotesoff&lt;br /&gt;
|mano&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;[conditional (0|1)]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Clears the entire &#039;&#039;MIDI&#039;&#039; buffer of notes held and turns off any bowing&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
ADC / Control box commands&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|adccommandmap&lt;br /&gt;
|acm&lt;br /&gt;
|[channel]:[command string]&lt;br /&gt;
|Sets the &#039;&#039;command string&#039;&#039; associated with the &#039;&#039;analog-to-digital converter channel&#039;&#039; of the &#039;&#039;Control box&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|adcdefaults&lt;br /&gt;
|acd&lt;br /&gt;
|none&lt;br /&gt;
|Sets &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; &#039;&#039;command strings&#039;&#039; associated with &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; &#039;&#039;analog-to-digital converter channels&#039;&#039; to their default values&lt;br /&gt;
|-&lt;br /&gt;
|adcread&lt;br /&gt;
|adcr&lt;br /&gt;
|[channel]:[return only: value]&lt;br /&gt;
|Returns the last value read by the &#039;&#039;analog-to-digital converter&#039;&#039; of the &#039;&#039;Command box&#039;&#039; on the &#039;&#039;channel&#039;&#039; given. This value is sent automatically any time a change in data is read&lt;br /&gt;
|-&lt;br /&gt;
|adcsettings&lt;br /&gt;
|adcs&lt;br /&gt;
|[channel]:[averages]:[interrupterrorthreshold]:[continuouserrorthreshold]:[continuoustimeout]&lt;br /&gt;
|Sets the settings for the &#039;&#039;averager&#039;&#039; used for the given &#039;&#039;Control box analog-to-digital channel&#039;&#039;. &#039;&#039;Averages&#039;&#039; denote number of values read and averaged, &#039;&#039;interrupterrorthreshold&#039;&#039; sets the value change required for the &#039;&#039;Control box&#039;&#039; to report a new value. The &#039;&#039;continuouserrorthreshold&#039;&#039; and &#039;&#039;continuoustimeout&#039;&#039; are used to allow for &#039;&#039;continuous&#039;&#039; changes. See the &#039;&#039;firmware&#039;&#039; for more information&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
MIDI commands&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;local&#039;&#039; commands as of this writing (2025-01-26) are:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|bow&lt;br /&gt;
|bow&lt;br /&gt;
|[bow (0)]&lt;br /&gt;
|Sets the &#039;&#039;current bow.&#039;&#039; This command is intended for future versions of the Ekdahl FAR that may have more than one &#039;&#039;bow&#039;&#039; per &#039;&#039;string module.&#039;&#039; Currently &#039;0&#039; is the only valid &#039;&#039;parameter&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|bowstatus&lt;br /&gt;
|bs&lt;br /&gt;
|none&lt;br /&gt;
|Outputs debugging data. Deprecated&lt;br /&gt;
|-&lt;br /&gt;
|pickupstringfrequency&lt;br /&gt;
|psf&lt;br /&gt;
|none&lt;br /&gt;
|Returns the fundamental frequency calculated from the current audio signal if, applicable&lt;br /&gt;
|-&lt;br /&gt;
|pickupaudiopeak&lt;br /&gt;
|pap&lt;br /&gt;
|none&lt;br /&gt;
|Returns the peak amplitude of the current audio signal&lt;br /&gt;
|-&lt;br /&gt;
|pickupaudiorms&lt;br /&gt;
|par&lt;br /&gt;
|none&lt;br /&gt;
|Returns the [[wikipedia:Root_mean_square|RMS]] amplitude of the current audio signal&lt;br /&gt;
|-&lt;br /&gt;
|bowdebugmeasuretimetotarget&lt;br /&gt;
|bdmtt&lt;br /&gt;
|[frequency]&lt;br /&gt;
|Measure the time it takes to change from the current frequency to the target frequency, used to debug the &#039;&#039;PID&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|bowhome&lt;br /&gt;
|bh&lt;br /&gt;
|none&lt;br /&gt;
|Homing bow, used at startup and in case of the bow loosing position&lt;br /&gt;
|-&lt;br /&gt;
|bowcalibrateall&lt;br /&gt;
|bca&lt;br /&gt;
|none&lt;br /&gt;
|Performs all calibration routines for a single bow available in the given firmware&lt;br /&gt;
|-&lt;br /&gt;
|bowcalibratespeed&lt;br /&gt;
|bcf&lt;br /&gt;
|none&lt;br /&gt;
|Performs a &#039;&#039;bowing speed calibration&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|bowcalibratepressure&lt;br /&gt;
|bcp&lt;br /&gt;
|none&lt;br /&gt;
|Performs a &#039;&#039;pressure calibration&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|nooperation&lt;br /&gt;
|nop&lt;br /&gt;
|none&lt;br /&gt;
|Do absolutely, positively, nothing&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Commands setting parameters relating to the bow PID&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|bowpid&lt;br /&gt;
|bpid&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;[conditional (0|1)]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets whether the [[wikipedia:Proportional–integral–derivative_controller|Proprtional-Integral-Deriviate controller]] is on or off. For all normal operation, the &#039;&#039;PID&#039;&#039; should be turned on. If it is turned off the instrument will not be able to play specific frequencies, but will only respond to &#039;&#039;bowmotordirectpwm&#039;&#039;-commands&lt;br /&gt;
|-&lt;br /&gt;
|bowpidki&lt;br /&gt;
|bpki&lt;br /&gt;
|[float]&lt;br /&gt;
|Sets the &#039;&#039;ki&#039;&#039;-value of the &#039;&#039;PID&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|bowpidkp&lt;br /&gt;
|bpkp&lt;br /&gt;
|[float]&lt;br /&gt;
|Sets the &#039;&#039;kp-&#039;&#039;value of the &#039;&#039;PID&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|bowpidkd&lt;br /&gt;
|bpkd&lt;br /&gt;
|[float]&lt;br /&gt;
|Sets the &#039;&#039;kd&#039;&#039;-value of the &#039;&#039;PID&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|bowpidintegratorerror&lt;br /&gt;
|bpie&lt;br /&gt;
|[float]&lt;br /&gt;
|Sets the minimum &#039;&#039;error value&#039;&#039; required in between the &#039;&#039;set point&#039;&#039; and the &#039;&#039;process variable&#039;&#039; for the integrator part of the &#039;&#039;PID&#039;&#039; to initiate correction&lt;br /&gt;
|-&lt;br /&gt;
|bowpidmaxerror&lt;br /&gt;
|bpme&lt;br /&gt;
|[float]&lt;br /&gt;
|Sets the maximum error correction attempted in each call to the &#039;&#039;PID loop&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|bowpidr&lt;br /&gt;
|bpir&lt;br /&gt;
|none&lt;br /&gt;
|Resets all data stored by the &#039;&#039;PID&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|bowpidpeakerror&lt;br /&gt;
|bpperr&lt;br /&gt;
|none&lt;br /&gt;
|Returns the last &#039;&#039;error value&#039;&#039; measured in between the &#039;&#039;set point&#039;&#039; and the &#039;&#039;process variable&#039;&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Commands relating to bow frequency control&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|bowcontrolfrequecy&lt;br /&gt;
|bcf&lt;br /&gt;
|[float]&lt;br /&gt;
|Sets the frequency (in Hertz) that the &#039;&#039;bowing motor&#039;&#039; should attempt to run at&lt;br /&gt;
|-&lt;br /&gt;
|bowcontrolfundamental&lt;br /&gt;
|bcu&lt;br /&gt;
|[float]&lt;br /&gt;
|Sets the &#039;&#039;fundamental frequency&#039;&#039; that all &#039;&#039;harmonics&#039;&#039; are using as its base for calculations&lt;br /&gt;
|-&lt;br /&gt;
|bowcontrolharmonic&lt;br /&gt;
|bch&lt;br /&gt;
|[float]&lt;br /&gt;
|Sets the &#039;&#039;harmonic number&#039;&#039; to use to calculate the &#039;&#039;motor speed&#039;&#039;. See &#039;&#039;bowcontrolharmonicadd&#039;&#039; and &#039;&#039;bowcontrolharmonicbase&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|bowcontrolharmonicadd&lt;br /&gt;
|bcha&lt;br /&gt;
|[float]&lt;br /&gt;
|Sets the number of &#039;&#039;harmonic numbers&#039;&#039; to add or remove to the value given in &#039;&#039;bowcontrolharmonic&#039;&#039; and &#039;&#039;bowcontrolharmonicbase&#039;&#039;. Can be negative values&lt;br /&gt;
|-&lt;br /&gt;
|bowcontrolharmonicbase&lt;br /&gt;
|bchb&lt;br /&gt;
|[float]&lt;br /&gt;
|Sets the &#039;&#039;harmonic number&#039;&#039; to use to calculate the &#039;&#039;motor speed&#039;&#039; but uses the value set by &#039;&#039;bowcontrolharmonicbasenote&#039;&#039; as its base. Includes any value set by &#039;&#039;bowcontrolharmonicadd&#039;&#039; and overwrites any value set by &#039;&#039;bowcontrolharmonic&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|bowcontrolharmonicbasenote&lt;br /&gt;
|bchbn&lt;br /&gt;
|[midi key (0-127)]&lt;br /&gt;
|Sets the &#039;&#039;MIDI&#039;&#039; key to use as the base for &#039;&#039;bowcontrolharmonicbase&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|bowcontrolharmonicshift&lt;br /&gt;
|bchsh&lt;br /&gt;
|[value (-32767 - 32767)]&lt;br /&gt;
|Sets how much to shift the &#039;&#039;motor speed&#039;&#039; away from the &#039;&#039;harmonic number&#039;&#039; set by &#039;&#039;bowcontrolharmonic&#039;&#039; or &#039;&#039;bowcontrolharmonicbase&#039;&#039;. The &#039;&#039;harmonic shift&#039;&#039; is dependent on the range set by &#039;&#039;bowcontrolharmonicshiftrange&#039;&#039;. Also see &#039;&#039;bowcontrolharmonicshift5&#039;&#039; &lt;br /&gt;
|-&lt;br /&gt;
|bowcontrolharmonicshiftrange&lt;br /&gt;
|bchsr&lt;br /&gt;
|[harmonics (0-36)]&lt;br /&gt;
|Sets the range of the &#039;&#039;bowcontrolharmonicshift&#039;&#039;-command. The &#039;&#039;parameter&#039;&#039; given denotes how many &#039;&#039;harmonic numbers&#039;&#039; to shift from the current &#039;&#039;harmonic number&#039;&#039; when the maximum &#039;&#039;harmonic shift&#039;&#039; has been set.&lt;br /&gt;
|-&lt;br /&gt;
|bowcontrolharmonicshift5&lt;br /&gt;
|bchs5&lt;br /&gt;
|[value (-32767 - 32767)]&lt;br /&gt;
|Sets how much to shift the &#039;&#039;motor speed&#039;&#039; away from the &#039;&#039;harmonic number&#039;&#039; set by &#039;&#039;bowcontrolharmonic&#039;&#039; or &#039;&#039;bowcontrolharmonicbase&#039;&#039;. Unlike &#039;&#039;bowcontrolharmonicshift&#039;&#039; this value is &amp;lt;u&amp;gt;always&amp;lt;/u&amp;gt; calculated on a range of 5 octaves, meaning a maximum &#039;&#039;harmonic shift&#039;&#039; will equal 5 times the amount of &#039;&#039;harmonic ratios&#039;&#039; in the current &#039;&#039;harmonic table&#039;&#039;. This value is added to the &#039;&#039;harmonic shift&#039;&#039; set by &#039;&#039;bowcontrolharmonicshift&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|bowcontrolspeedmode&lt;br /&gt;
|bcsm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;[mode (0|1)]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets the &#039;&#039;speed mode&#039;&#039; where &#039;&#039;0 = Automatic&#039;&#039; and &#039;&#039;1 = Manual&#039;&#039;. The only difference in between these two modes is that &#039;&#039;Automatic&#039;&#039; will automatically turn off the motor when the bow has been set in its &#039;&#039;rest position&#039;&#039; and no frequency changing &#039;&#039;commands&#039;&#039; have been sent within the time period given by &#039;&#039;bowmotortimeout&#039;&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Commands for controlling harmonic series&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|bowharmonicseries&lt;br /&gt;
|bhs&lt;br /&gt;
|[series]&lt;br /&gt;
|Sets the &#039;&#039;current harmonic series&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|bowharmonicseriesdata&lt;br /&gt;
|bhsl&lt;br /&gt;
|[(set  only) series]:[name]:[ratios]&lt;br /&gt;
|Sets &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; &#039;&#039;ratios&#039;&#039; and the &#039;&#039;name&#039;&#039; of the &#039;&#039;harmonic list&#039;&#039; in the given &#039;&#039;series&#039;&#039;. There can be any number of &#039;&#039;ratio&#039;&#039;-parameters and this effectively sets the number of &#039;&#039;harmonics&#039;&#039; per octave. If required, empty &#039;&#039;harmonic lists&#039;&#039; will be added until &#039;&#039;slot&#039;&#039; is a valid number. On return, requires [series] and returns &#039;&#039;name&#039;&#039; and &#039;&#039;ratios&#039;&#039; of the &#039;&#039;harmonic series&#039;&#039; given&lt;br /&gt;
|-&lt;br /&gt;
|bowharmonicseriesratio&lt;br /&gt;
|bhsr&lt;br /&gt;
|[harmonic]:[ratio]&lt;br /&gt;
|Sets the &#039;&#039;ratio&#039;&#039; of the given &#039;&#039;harmonic number&#039;&#039; in the &#039;&#039;current harmonic series&#039;&#039;. Will increase the number of ratios in the series if needed&lt;br /&gt;
|-&lt;br /&gt;
|bowharmonicseriesratioremove&lt;br /&gt;
|bhsrr&lt;br /&gt;
|[ratio]&lt;br /&gt;
|Removes the &#039;&#039;ratio&#039;&#039; given, will move all &#039;&#039;ratios&#039;&#039; with a higher &#039;&#039;harmonic number&#039;&#039; in the series. Cannot remove all &#039;&#039;ratios&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|bowharmonicseriescount&lt;br /&gt;
|bhsc&lt;br /&gt;
|none&lt;br /&gt;
|Returns the number of &#039;&#039;harmonic series&#039;&#039; and their &#039;&#039;names&#039;&#039; in the format &#039;&#039;ratios:name1:name2 [etc]&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|bowharmonicseriessave&lt;br /&gt;
|bhss&lt;br /&gt;
|[series]:[name]&lt;br /&gt;
|Saves the current &#039;&#039;harmonic series&#039;&#039; into the slot given by the second &#039;&#039;parameter&#039;&#039; with the name give in the first &#039;&#039;parameter&#039;&#039;. Note that this &#039;&#039;command&#039;&#039; does &amp;lt;u&amp;gt;not&amp;lt;/u&amp;gt; save it into flash memory&lt;br /&gt;
|-&lt;br /&gt;
|bowharmonicseriesremove&lt;br /&gt;
|bhsrm&lt;br /&gt;
|[series]&lt;br /&gt;
|Removes the &#039;&#039;harmonic series&#039;&#039; given in the &#039;&#039;parameter&#039;&#039;. Shifts all &#039;&#039;series&#039;&#039;&#039; with a higher &#039;&#039;series&#039;&#039; number&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Commands relating to the bowing motor&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|bowmotorrun&lt;br /&gt;
|bmr&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;[(0|1)]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets the &#039;&#039;bow motor&#039;&#039; to off or on &lt;br /&gt;
|-&lt;br /&gt;
|bowmotordirectpwm&lt;br /&gt;
|bmdp&lt;br /&gt;
|[pwm (0 - 65535)]&lt;br /&gt;
|Sets the &#039;&#039;bow motor&#039;&#039; power in 16-bit PWM values, requires that the &#039;&#039;PID&#039;&#039; is turned off&lt;br /&gt;
|-&lt;br /&gt;
|bowmotortimeout&lt;br /&gt;
|bmt&lt;br /&gt;
|[ms (0 - 65535)]&lt;br /&gt;
|Sets the &#039;&#039;bow motor&#039;&#039; shutdown timeout after bow having been put into the rest position, given in milli-seconds&lt;br /&gt;
|-&lt;br /&gt;
|bowmotorspeedmax&lt;br /&gt;
|bmsx&lt;br /&gt;
|[pwm (0 - 65535)]&lt;br /&gt;
|Sets &#039;&#039;bow motor&#039;&#039; maximum speed in 16-bit PWM&lt;br /&gt;
|-&lt;br /&gt;
|bowmotorspeedmin&lt;br /&gt;
|bmsi&lt;br /&gt;
|[pwm (0 - 65535)]&lt;br /&gt;
|Sets &#039;&#039;bow motor&#039;&#039; minimum speed in 16-bit PWM&lt;br /&gt;
|-&lt;br /&gt;
|bowmotorvoltage&lt;br /&gt;
|bmv&lt;br /&gt;
|[voltage (1.2 - 9)]&lt;br /&gt;
|Sets the &#039;&#039;bow motor&#039;&#039; voltage&lt;br /&gt;
|-&lt;br /&gt;
|bowmotorfrequency&lt;br /&gt;
|bmf&lt;br /&gt;
|none&lt;br /&gt;
|Returns the last read &#039;&#039;bow motor frequency&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|bowmotorcurrent&lt;br /&gt;
|bmc&lt;br /&gt;
|none&lt;br /&gt;
|Returns the last read current usage of the &#039;&#039;bowing motor&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|bowmotorcurrentlimit&lt;br /&gt;
|bmcl&lt;br /&gt;
|[current]&lt;br /&gt;
|Sets the current limit of the &#039;&#039;bowing motor&#039;&#039; in &#039;&#039;amperes&#039;&#039;, &amp;lt;u&amp;gt;used to safeguard the motor, &#039;&#039;&#039;can ruin the instrument if improperly set&#039;&#039;&#039;&amp;lt;/u&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|bowmotorpowerlimit&lt;br /&gt;
|bmpl&lt;br /&gt;
|[power]&lt;br /&gt;
|Sets the power limit of the &#039;&#039;bowing motor&#039;&#039; in &#039;&#039;watts&#039;&#039;, &amp;lt;u&amp;gt;used to safeguard the motor, &#039;&#039;&#039;can ruin the instrument if improperly set&#039;&#039;&#039;&amp;lt;/u&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|bowmotorfaultcommands&lt;br /&gt;
|bmfc&lt;br /&gt;
|[command string]&lt;br /&gt;
|Sets the &#039;&#039;commands&#039;&#039; to execute when a motor fault is tripped, &amp;lt;u&amp;gt;used to safeguard the motor, &#039;&#039;&#039;can ruin the instrument if improperly set&#039;&#039;&#039;&amp;lt;/u&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|bowmotoroverpowercommands&lt;br /&gt;
|bmopc&lt;br /&gt;
|[command string]&lt;br /&gt;
|Sets the &#039;&#039;commands&#039;&#039; to execute when the &#039;&#039;bowing motor&#039;&#039; is over the power limit, &amp;lt;u&amp;gt;used to safeguard the motor, &#039;&#039;&#039;can ruin the instrument if improperly set&#039;&#039;&#039;&amp;lt;/u&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Commands for controlling bow pressure&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|bowpressurebaseline&lt;br /&gt;
|bpb&lt;br /&gt;
|[pressure (0 - 65535)]&lt;br /&gt;
|Sets the &#039;&#039;pressure baseline&#039;&#039; value, scaled by the &#039;&#039;bowpressurepositionengage&#039;&#039; and &#039;&#039;bowpressurepositionmax&#039;&#039; parameters. The &#039;&#039;pressure baseline&#039;&#039; and &#039;&#039;pressure modifier&#039;&#039; forms the total &#039;&#039;pressure position&#039;&#039;.&lt;br /&gt;
|-&lt;br /&gt;
|bowpressuremodifier&lt;br /&gt;
|bpm&lt;br /&gt;
|[pressure (0 - 65535)]&lt;br /&gt;
|Sets the &#039;&#039;pressure modifier&#039;&#039; value, scaled by the &#039;&#039;bowpressurepositionengage&#039;&#039; and &#039;&#039;bowpressurepositionmax&#039;&#039; parameters. The &#039;&#039;pressure baseline&#039;&#039; and &#039;&#039;pressure modifier&#039;&#039; forms the total &#039;&#039;pressure position&#039;&#039;.&lt;br /&gt;
|-&lt;br /&gt;
|bowpressurerest&lt;br /&gt;
|bpr&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;[conditional (0|1)]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the bow pressure in the &#039;&#039;rest position&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|bowpressureengage&lt;br /&gt;
|bpe&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;[conditional (0|1)]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Puts the bow pressure in the &#039;&#039;engage position&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|bowpressurepositionmax&lt;br /&gt;
|bppx&lt;br /&gt;
|[value (0 - 65535)]&lt;br /&gt;
|Sets the maximum &amp;lt;u&amp;gt;hardware&amp;lt;/u&amp;gt; position of the &#039;&#039;bowing jack&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|bowpressurepositionengage&lt;br /&gt;
|bppe&lt;br /&gt;
|[value (0 - 65535)]&lt;br /&gt;
|Sets the &#039;&#039;engage&#039;&#039; &#039;&#039;position&#039;&#039; &amp;lt;u&amp;gt;hardware&amp;lt;/u&amp;gt; position of the &#039;&#039;bowing jack&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|bowpressurepositionrest&lt;br /&gt;
|bppr&lt;br /&gt;
|[value (0 - 65535)]&lt;br /&gt;
|Sets the &#039;&#039;rest position&#039;&#039; &amp;lt;u&amp;gt;hardware&amp;lt;/u&amp;gt; position of the &#039;&#039;bowing jack&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|bowpressureengagespeed&lt;br /&gt;
|bpes&lt;br /&gt;
|[speed (0 - 100)]&lt;br /&gt;
|Sets the speed of the &#039;&#039;pressure motor&#039;&#039; in RPM when going from &#039;&#039;rest&#039;&#039; to &#039;&#039;engage&#039;&#039; or vice versa. Setting this value too high will result in the &#039;&#039;pressure motor&#039;&#039; loosing track and the instrument malfunctioning as a result. Setting this value too low will result in the instrument getting increased &#039;&#039;latency&#039;&#039; and feeling sluggish.&lt;br /&gt;
|-&lt;br /&gt;
|bowpressuremodulationspeed&lt;br /&gt;
|bpms&lt;br /&gt;
|[speed (0.1 - &#039;&#039;bpes&#039;&#039;)]&lt;br /&gt;
|Sets the speed of the &#039;&#039;pressure motor&#039;&#039; in RPM when at &#039;&#039;engage&#039;&#039; and modulating the pressure. The main purpose of this setting is to avoid the &#039;&#039;bowing motor&#039;&#039; slowing down too much when modulating the &#039;&#039;pressure&#039;&#039;, resulting in audible artifacts&lt;br /&gt;
|-&lt;br /&gt;
|bowpressurehold&lt;br /&gt;
|bph&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;[(0|1)]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets &#039;&#039;bow hold&#039;&#039; off or on. If &#039;&#039;bow hold&#039;&#039; is on, any &#039;&#039;bowpressurerest&#039;&#039;-command will be ignored until &#039;&#039;bowpressurehold&#039;&#039; is set to off. Analog to the concept of &#039;&#039;infinite sustain&#039;&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Commands for solenoid control&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|solenoid&lt;br /&gt;
|so&lt;br /&gt;
|[(&#039;0&#039;)]&lt;br /&gt;
|Sets the &#039;&#039;current solenoid&#039;&#039;. This command is intended for future versions of the Ekdahl FAR that may have more than one &#039;&#039;solenoid&#039;&#039; per &#039;&#039;string module.&#039;&#039; Currently &#039;0&#039; is the only valid &#039;&#039;parameter&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|solenoidengage&lt;br /&gt;
|se&lt;br /&gt;
|[force (0 - 65535)]&lt;br /&gt;
|Engages the &#039;&#039;current solenoid&#039;&#039; with the &#039;&#039;force&#039;&#039; given, the &#039;&#039;force&#039;&#039; is mutiplied by the &#039;&#039;force multiplier&#039;&#039; as set by &#039;&#039;solenoidforcemultiplier&#039;&#039;. The &#039;&#039;force&#039;&#039; is scaled according to the &#039;&#039;solenoidmaxforce&#039;&#039; and &#039;&#039;solenoidminforce&#039;&#039; parameters, a &#039;&#039;force&#039;&#039; of &#039;&#039;0&#039;&#039; always means to not engage. Also see &#039;&#039;solenoidengageduration&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|solenoiddisengage&lt;br /&gt;
|sd&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;[conditional (0|1)]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Disengages the &#039;&#039;solenoid&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|solenoidmaxforce&lt;br /&gt;
|sxf&lt;br /&gt;
|[value (0 - 65535)]&lt;br /&gt;
|Sets the maximum hardware force used&lt;br /&gt;
|-&lt;br /&gt;
|solenoidminforce&lt;br /&gt;
|sif&lt;br /&gt;
|[value (0 - 65535)]&lt;br /&gt;
|Sets the minimum hardware force used&lt;br /&gt;
|-&lt;br /&gt;
|solenoidforcemultiplier&lt;br /&gt;
|sfm&lt;br /&gt;
|[value (0 - 1)]&lt;br /&gt;
|Sets the value of the &#039;&#039;force multiplier&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|solenoidengageduration&lt;br /&gt;
|sed&lt;br /&gt;
|[duration (0 - 65535)]&lt;br /&gt;
|Sets the duration of the &#039;&#039;solenoid engagement&#039;&#039; in ɥS. if a value of &#039;&#039;0&#039;&#039; is set the &#039;&#039;solenoid&#039;&#039; will not disengage until a &#039;&#039;solenoiddisengage-&#039;&#039;command has been given. This latter behavior is &amp;lt;u&amp;gt;not encouraged&amp;lt;/u&amp;gt; as it &amp;lt;u&amp;gt;&#039;&#039;&#039;can ruin the instrument if improperly used&#039;&#039;&#039;&amp;lt;/u&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Commands for controlling the mute&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|mutesetposition&lt;br /&gt;
|msp&lt;br /&gt;
|[position (0 - 65535)]&lt;br /&gt;
|Sets the &#039;&#039;mute position&#039;&#039;, scaled by the &#039;&#039;mutefullmuteposition&#039;&#039; and &#039;&#039;muterestposition&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|mutefullmute&lt;br /&gt;
|mfm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;[conditional (0|1)]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets the &#039;&#039;mute&#039;&#039; in the &#039;&#039;full mute position&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|mutehalfmute&lt;br /&gt;
|mhm&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;[conditional (0|1)]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets the &#039;&#039;mute&#039;&#039; in the &#039;&#039;half mute position&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|muterest&lt;br /&gt;
|mr&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;[conditional (0|1)]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets the &#039;&#039;mute&#039;&#039; in the &#039;&#039;mute rest position&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|mutesavefull&lt;br /&gt;
|msf&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;[conditional (0|1)]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets the &#039;&#039;full mute position&#039;&#039; to be equal to the current &#039;&#039;mute position&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|mutesavehalf&lt;br /&gt;
|msh&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;[conditional (0|1)]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets the &#039;&#039;half mute position&#039;&#039; to be equal to the current &#039;&#039;mute position&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|mutesaverest&lt;br /&gt;
|msr&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;[conditional (0|1)]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets the &#039;&#039;mute rest position&#039;&#039; to be equal to the current &#039;&#039;mute position&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|mutefullmuteposition&lt;br /&gt;
|mfmp&lt;br /&gt;
|[value (0 - 65535)]&lt;br /&gt;
|Sets the &#039;&#039;full mute position&#039;&#039; to &#039;&#039;value&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|mutehalfmuteposition&lt;br /&gt;
|mhmp&lt;br /&gt;
|[value (0 - 65535)]&lt;br /&gt;
|Sets the &#039;&#039;half mute position&#039;&#039; to &#039;&#039;value&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|muterestposition&lt;br /&gt;
|mrp&lt;br /&gt;
|[value (0 - 65535)]&lt;br /&gt;
|Sets the &#039;&#039;mute rest position&#039;&#039; to &#039;&#039;value&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|mutesustain&lt;br /&gt;
|ms&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;[conditional (0|1)]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|Sets the &#039;&#039;mute sustain&#039;&#039; to &#039;&#039;off&#039;&#039; or &#039;&#039;on&#039;&#039;. When &#039;&#039;mute sustain&#039;&#039; is &#039;&#039;on&#039;&#039;, any &#039;&#039;mutefullmute-&#039;&#039;commands sent will be ignored until &#039;&#039;mute sustain&#039;&#039; is set to &#039;&#039;off&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|mutebackoff&lt;br /&gt;
|mbo&lt;br /&gt;
|[backoff (0 - 65535)]&lt;br /&gt;
|Sets the &#039;&#039;mute backoff&#039;&#039; to &#039;&#039;backoff&#039;&#039;, given in mS. The &#039;&#039;mute backoff&#039;&#039; sets the time that the &#039;&#039;mute&#039;&#039; stays in the &#039;&#039;mutefullmute&#039;&#039; position before automatically going to the &#039;&#039;rest position&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|mutehome&lt;br /&gt;
|mh&lt;br /&gt;
|none&lt;br /&gt;
|Homing the &#039;&#039;mute&#039;&#039; &lt;br /&gt;
|-&lt;br /&gt;
|mutecalibrate&lt;br /&gt;
|mca&lt;br /&gt;
|none&lt;br /&gt;
|Runs the &#039;&#039;mute calibration&#039;&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Commands for bow actuators&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Long name&lt;br /&gt;
!Short name&lt;br /&gt;
!Parameters&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;s&amp;gt;bowactuatoradd&amp;lt;/s&amp;gt;&lt;br /&gt;
|baa&lt;br /&gt;
|none&lt;br /&gt;
|Add new bow &#039;&#039;actuator&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|bowacutatorremove&lt;br /&gt;
|bar&lt;br /&gt;
|[actuator]&lt;br /&gt;
|Removes the &#039;&#039;actuator&#039;&#039; given in the &#039;&#039;parameter&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;s&amp;gt;bowactuatorset&amp;lt;/s&amp;gt;&lt;br /&gt;
|bas&lt;br /&gt;
|[actuator]&lt;br /&gt;
|Sets the &#039;&#039;current actuator&#039;&#039; to the number given in the &#039;&#039;parameter&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;s&amp;gt;bowactuatorload&amp;lt;/s&amp;gt;&lt;br /&gt;
|bal&lt;br /&gt;
|none&lt;br /&gt;
|Loads data from the &#039;&#039;current actuator&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|bowactuatorsave&lt;br /&gt;
|bas&lt;br /&gt;
|none&lt;br /&gt;
|Saves the &#039;&#039;bow pressure position rest, bow pressure position engage&#039;&#039; and &#039;&#039;bow pressure position max&#039;&#039; into the &#039;&#039;current actuator&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|bowactuatordata&lt;br /&gt;
|bad&lt;br /&gt;
|[actuator]:[engage]:[max]:[rest]:[id]&lt;br /&gt;
|Sets the &#039;&#039;bow pressure position engage, bow pressure position max, bow pressure position rest&#039;&#039; and &#039;&#039;actuator id&#039;&#039; of the &#039;&#039;actuator&#039;&#039; given by the first &#039;&#039;parameter&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|bowactuatorcount&lt;br /&gt;
|bac&lt;br /&gt;
|none&lt;br /&gt;
|Returns the number of saved &#039;&#039;actuators&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;s&amp;gt;bowactuatorid&amp;lt;/s&amp;gt;&lt;br /&gt;
|bai&lt;br /&gt;
|id&lt;br /&gt;
|Sets the &#039;&#039;id&#039;&#039; of the &#039;&#039;current actuator&#039;&#039;&lt;br /&gt;
|}&lt;br /&gt;
Please note that &#039;&#039;commands&#039;&#039; may be added or subtracted from this list as the Ekdahl FAR &#039;&#039;firmware&#039;&#039; development progresses, the most sincere attempts will be made to keep this list up to date but no guarantees will be made.{{docnav&lt;br /&gt;
|[[The Ekdahl FAR - Command langue|Command language]]&lt;br /&gt;
|[[The Ekdahl FAR - Specifications|Specifications]]&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Knaadmin</name></author>
	</entry>
	<entry>
		<id>http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_language&amp;diff=1659</id>
		<title>The Ekdahl FAR - Command language</title>
		<link rel="alternate" type="text/html" href="http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_language&amp;diff=1659"/>
		<updated>2026-06-12T10:32:53Z</updated>

		<summary type="html">&lt;p&gt;Knaadmin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Command language ==&lt;br /&gt;
The Ekdahl FAR is entirely controlled by &#039;&#039;commands&#039;&#039;, these &#039;&#039;commands&#039;&#039; decide everything that the instrument is doing, whether it is playing a melody or changing an internal parameter. &lt;br /&gt;
&lt;br /&gt;
When a &#039;&#039;MIDI message&#039;&#039; is received or a new CV / knob value is read, the &#039;&#039;commands&#039;&#039; associated with it will be internally sent. This can be things like &amp;quot;engage hammer&amp;quot; or &amp;quot;set the fundamental frequency&amp;quot; etc. &lt;br /&gt;
&lt;br /&gt;
Some of the available &#039;&#039;commands&#039;&#039; are mainly used for calibrating and setting up the instrument and are usually saved into the instruments memory, these will be executed whenever the instrument is turned on. &lt;br /&gt;
&lt;br /&gt;
All &#039;&#039;commands&#039;&#039; can be manually invoked via &#039;&#039;USB-Serial&#039;&#039;, in conjunction with certain software this presents an unprecedented level of control and sequenceability.&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
The &#039;&#039;commands&#039;&#039; are invoked using a &#039;&#039;plain text approach&#039;&#039;, all commands have both a &#039;&#039;long name&#039;&#039; and a &#039;&#039;short name&#039;&#039; which are interchangeable. A &#039;&#039;command&#039;&#039; may have one or more &#039;&#039;parameters&#039;&#039; associated with it, these &#039;&#039;parameters&#039;&#039; can be of different types; 16-bit numbers (values 0 - 65535 or -32767 - 32767), floating point numbers (values with decimals), booleans (0 for &#039;false&#039;, 1 for &#039;true&#039;) and strings (text). Some commands are &#039;&#039;conditional&#039;&#039;, meaning they will only execute if a parameter equates to &#039;1&#039; (&#039;true&#039;). &lt;br /&gt;
&lt;br /&gt;
The way &#039;&#039;commands&#039;&#039; are written in order to be executed is &#039;&#039;commandname:parameter1:parameter2:parameter3 [etc]&#039;&#039;, several commands be executed in sequence by separating them with a comma (&#039;,&#039;), a bunch of commands strung together is called a &#039;&#039;command string&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Since version 1.1 of the Ekdahl FAR Firmware, all commands are grouped in a hierarchical fashion according to their &#039;&#039;modules&#039;&#039; and each ladder in the hierarchy is separated by a period (&amp;quot;.&amp;quot;), this works very much like folders or directories in a regular computer. Every &#039;&#039;module&#039;&#039; can contain both &#039;&#039;commands&#039;&#039; and other &#039;&#039;modules&#039;&#039;. For instance, everything associated with the &#039;&#039;bowing wheel&#039;&#039; is now collected under &amp;quot;bowingwheel&amp;quot; &#039;&#039;module&#039;&#039;. That in turn contains a &amp;quot;dcmotor&amp;quot; &#039;&#039;module&#039;&#039; which handles direct control of the bowing motor. It also has a &amp;quot;pid&amp;quot; &#039;&#039;module&#039;&#039; that handles bow frequency among other thing. &lt;br /&gt;
&lt;br /&gt;
If for instance we would like to start the &#039;&#039;bowing wheel&#039;&#039; and set its frequency to 82.5 Hertz we could send the Ekdahl FAR the following &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
bowmotorrun:1, bowcontrolfrequecy:82.5&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bowingwheel.dcmotor.run:1, bowingwheel.pid.targetfrequency:82.5&amp;lt;/pre&amp;gt;We could also use the &#039;&#039;short names&#039;&#039; for the commands&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
bmr:1,bcf:82.5&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bw.dcm.ru:1, bw.pid.tf:82.5&amp;lt;/pre&amp;gt;Both &amp;quot;bowmotorrun&amp;quot; / &amp;quot;bowingwheel.dcmotor.run&amp;quot; and &amp;quot;bowcontrolfrequency&amp;quot; / &amp;quot;bowingwheel.pid.targetfrequency&amp;quot; takes one &#039;&#039;parameter&#039;&#039; each, &#039;&#039;&amp;quot;&#039;&#039;bowmotorrun&amp;quot; / &amp;quot;bowingwheel.dcmotor.run&amp;quot; is &#039;&#039;conditional&#039;&#039; and unless the first &#039;&#039;parameter&#039;&#039; is equal to &#039;1&#039; the motor will not start. The first &#039;&#039;parameter&#039;&#039; of &amp;quot;bowcontrolfrequency&amp;quot; / &amp;quot;bowingwheel.pid.targetfrequency&amp;quot; sets the frequency of the &#039;&#039;bowing wheel&#039;&#039;, the instrument may not execute a &#039;&#039;command&#039;&#039; if it decides that the given &#039;&#039;parameters&#039;&#039; are outside of the working range or they are missing.&lt;br /&gt;
&lt;br /&gt;
The addition of the hierarchy in the FAR 1.1 firmware isn&#039;t just to be able to group commands, but it&#039;s also to make the FAR not limited to a single set of &#039;&#039;modules&#039;&#039; (and is the first stepping stone to a &#039;&#039;modular&#039;&#039; Ekdahl FAR). In fact, you could have 12 different bowing wheel &#039;&#039;modules&#039;&#039; for 12 different strings, these would then be addressed as &amp;quot;bowingwheel[0].command&amp;quot;&#039;&#039;, &amp;quot;&#039;&#039;bowingwheel[1].command&amp;quot; etc. Anyone familiar with C programming notices that this is the standard way of &#039;&#039;indexing&#039;&#039; an array; using brackets (&amp;quot;[ ]&amp;quot;). When addressing a module without &#039;&#039;indexing&#039;&#039; as in the example above, the FAR will do one or two things; either use the first object (&amp;quot;[0]&amp;quot;) or, if the object is &#039;&#039;selectable&#039;&#039; it will use the previously selected object. To make things smoother a command can be executed on several objects at once by using ranges (&amp;quot;[0-4]&amp;quot;) and comma separation (&amp;quot;[0, 3, 5-6]&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
To test out a &#039;&#039;command&#039;&#039; you can send it directly to the Ekdahl FAR using the &#039;&#039;Console&#039;&#039; in the &#039;&#039;Configuration utility&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
To read up on existing &#039;&#039;commands&#039;&#039;, their &#039;&#039;parameters&#039;&#039; and a brief description you can check the &#039;&#039;Command reference&#039;&#039; in the &#039;&#039;Configuration utility&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Variables, functions and equations ==&lt;br /&gt;
What makes the &#039;&#039;Command language&#039;&#039; truly powerful is the concept of &#039;&#039;variables, functions&#039;&#039; and &#039;&#039;equations&#039;&#039;. All &#039;&#039;parameters&#039;&#039; that take numerical values can use any combination of &#039;&#039;variables, functions&#039;&#039; or &#039;&#039;equations.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
For instance, we can use the previous example and instead write our &#039;&#039;command string&#039;&#039; as follows&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
bowmotorrun:1, bowcontrolfrequency:82.5+note*20&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bowingwheel.dcmotor.run:1, bowingwheel.pid.targetfrequency:82.5+note*20&amp;lt;/pre&amp;gt;This example requires of course that the &#039;&#039;variable&#039;&#039; &#039;&#039;note&#039;&#039; exists in the current context. &lt;br /&gt;
&lt;br /&gt;
===== Variables =====&lt;br /&gt;
There are two types of &#039;&#039;variables&#039;&#039; in the Ekdahl FAR; &#039;&#039;global variables&#039;&#039; and &#039;&#039;event variables&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Global variables&#039;&#039; are variables that are always valid, in any context. The &#039;&#039;global variables&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;notecount&#039;&#039;&#039; - Contains the number of &#039;&#039;MIDI&#039;&#039; keys that are being held down, i.e. all &#039;&#039;Note on messages&#039;&#039; received that haven&#039;t gotten a paired &#039;&#039;Note off message&#039;&#039; yet&lt;br /&gt;
* &#039;&#039;&#039;uv0&#039;&#039;&#039; - &#039;&#039;&#039;uv9&#039;&#039;&#039; - These are &#039;&#039;user variables&#039;&#039; and can be set at any point using the &#039;&#039;globaluservariable command&#039;&#039; with the first &#039;&#039;parameter&#039;&#039; being which variable to set (0-9) and the second &#039;&#039;parameter&#039;&#039; being the value (float).&lt;br /&gt;
* &#039;&#039;&#039;e&#039;&#039;&#039; - Contains the constant &#039;&#039;[[wikipedia:E_(mathematical_constant)|e]]&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pi&#039;&#039;&#039; - Contains the constant &#039;&#039;[[wikipedia:Pi|pi]]&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Event variables&#039;&#039; are variables that are set by certain &#039;&#039;MIDI messages&#039;&#039; or when a new value is read on one of the jacks or knobs on the &#039;&#039;Control box&#039;&#039;. The &#039;&#039;Event variables&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;channel&#039;&#039;&#039; - Set by the &#039;&#039;Note on, Note off, Continuous Controller, Poly after touch, Pitch bend, Channel after touch&#039;&#039; and &#039;&#039;Program change MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;note&#039;&#039;&#039; - Set by the &#039;&#039;Note on, Note off&#039;&#039; and &#039;&#039;Poly after touch MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;velocity&#039;&#039;&#039; - Set by the &#039;&#039;Note on&#039;&#039; and &#039;&#039;Note off MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pressure&#039;&#039;&#039; - Set by the &#039;&#039;Poly after touch&#039;&#039; and &#039;&#039;Channel after touch MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; - Set by the &#039;&#039;Continuous Controller MIDI message&#039;&#039; and by the &#039;&#039;Control box&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pitch&#039;&#039;&#039; - Set by the &#039;&#039;Pitch bend MIDI message&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;program&#039;&#039;&#039; - Set by the &#039;&#039;Program change MIDI message&#039;&#039;&lt;br /&gt;
These variables will contain whatever data is relevant to the last event that occurred and may be overwritten by the next event.&lt;br /&gt;
&lt;br /&gt;
===== Functions =====&lt;br /&gt;
&#039;&#039;Functions&#039;&#039; can be used to change a numerical value or the result of an &#039;&#039;equation&#039;&#039;, the Ekdahl FAR contains both general &#039;&#039;arithmetic functions&#039;&#039; (courtesy of Lewis Van Winkle and the TINYEXPR engine) and &#039;&#039;specialized functions&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;arithmetic functions&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;abs&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Absolute_value|absolute value]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;acos&#039;&#039;&#039;(x), &#039;&#039;&#039;asin&#039;&#039;&#039;(x), &#039;&#039;&#039;atan&#039;&#039;&#039;(x), atan2(x, y) - Returns the [[wikipedia:Inverse_trigonometric_functions|&#039;&#039;arc-cos, -sin, -tan&#039;&#039; and &#039;&#039;-tan2&#039;&#039;]] of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;atan2&#039;&#039;&#039;(x,y) - Returns the &#039;&#039;[[wikipedia:Atan2|arctan2]]&#039;&#039; of &#039;&#039;x, y&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;floor&#039;&#039;&#039;(x), ceil(x) - Returns the [[wikipedia:Floor_and_ceiling_functions|&#039;&#039;floor&#039;&#039; and &#039;&#039;ceiling&#039;&#039;]] of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;exp&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Exponential_function|exponent]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;fac&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Factorial|factorial]]&#039;&#039; of x&lt;br /&gt;
* &#039;&#039;&#039;ln&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Natural_logarithm|natural logarithm]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;log10&#039;&#039;&#039;(x), &#039;&#039;&#039;log20&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Logarithm|logarithm]]&#039;&#039; of &#039;&#039;x&#039;&#039; using base 10 and 20 respectively&lt;br /&gt;
* &#039;&#039;&#039;ncr&#039;&#039;&#039;(x,y), &#039;&#039;&#039;npr&#039;&#039;&#039;(x,y) - Functions to calculate &#039;&#039;[[wikipedia:Combination|combinations]]&#039;&#039; and &#039;&#039;[[wikipedia:Permutation|permutations]]&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pow&#039;&#039;&#039;(x,y) - Returns &#039;&#039;x^y&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;sqrt&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Square_root|square root]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;cos&#039;&#039;&#039;(x), &#039;&#039;&#039;sin&#039;&#039;&#039;(x), &#039;&#039;&#039;tan&#039;&#039;&#039;(x) - Returns the [[wikipedia:Trigonometric_functions|&#039;&#039;cos, sin&#039;&#039; and &#039;&#039;tan&#039;&#039;]] of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;cosh&#039;&#039;&#039;(x), &#039;&#039;&#039;sinh&#039;&#039;&#039;(x), &#039;&#039;&#039;tanh&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Hyperbolic_functions|hyperbolic cos, sin and tan]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
The &#039;&#039;specialized functions&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;bool&#039;&#039;&#039;(x) - Returns 1 if &#039;&#039;x&#039;&#039; is more than 0&lt;br /&gt;
* &#039;&#039;&#039;ibool&#039;&#039;&#039;(x) - Returns 0 if &#039;&#039;x&#039;&#039; is more than 0&lt;br /&gt;
* &#039;&#039;&#039;deadband&#039;&#039;&#039;(x,y) - Returns &#039;&#039;x + y &#039;&#039; if &#039;&#039;x &amp;lt; y&#039;&#039; or &#039;&#039;x - y&#039;&#039; if &#039;&#039;x &amp;gt; y&#039;&#039;. If neither of these statements is true it returns &#039;&#039;0&#039;&#039; - used to create a [[wikipedia:Deadband|deadband]] of &#039;&#039;x&#039;&#039; with the threshold of &#039;&#039;y&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Functions&#039;&#039; can be readily used in a &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
bowmotorrun:1, bowcontrolfrequency:&amp;quot;8.17579875 * pow(2, (1/12 * note))&amp;quot;&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bowingwheel.dcmotor.run:1, bowingwheel.pid.targetfrequency:&amp;quot;8.17579875 * pow(2, (1/12 * note))&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;The previous statements starts the &#039;&#039;bowing wheel&#039;&#039; and sets the frequency of the wheel to &#039;&#039;8.17579875 * 2^(1/12 * note)&#039;&#039;. A middle &#039;C&#039; according to &#039;&#039;MIDI&#039;&#039; has a &#039;&#039;note value&#039;&#039; of 36, meaning if we substitute &#039;&#039;note&#039;&#039; with 36 we get the equation &#039;&#039;8.17579875 * 2^(1/12 * 36)&#039;&#039; which comes out to &#039;&#039;~65.4&#039;&#039; Hertz.&lt;br /&gt;
&lt;br /&gt;
Note that the first &#039;&#039;parameter&#039;&#039; for &#039;&#039;&amp;quot;&#039;&#039;bowcontrolfrequency&amp;quot; / &amp;quot;bowingwheel.pid.targetfrequency&amp;quot; is put in between double quotes (&amp;quot;). This is because the &amp;quot;pow&#039;&#039;&amp;quot;-&#039;&#039;function requires the use of a comma (&amp;quot;,&amp;quot;) in order to separate in between its two required inputs; &#039;&#039;x&#039;&#039; and &#039;&#039;y&#039;&#039;. In order for the Ekdahl FAR to know that this comma does not signal the beginning of a new &#039;&#039;command,&#039;&#039; we use quotes. Single (&#039;) and double (&amp;quot;) quotes can be used and nested in all &#039;&#039;parameters&#039;&#039; and are &amp;lt;u&amp;gt;required&amp;lt;/u&amp;gt; in a lot of circumstances, improper nesting or not using quotes can lead to the instrument not understanding the &#039;&#039;command string&#039;&#039; correctly.&lt;br /&gt;
&lt;br /&gt;
== Return messages ==&lt;br /&gt;
The Ekdahl FAR when connected via &#039;&#039;USB-Serial&#039;&#039; doesn&#039;t only accept &#039;&#039;commands&#039;&#039; but will also send various &#039;&#039;return messages&#039;&#039;. These are prefixed by their &#039;&#039;category&#039;&#039; denoted in brackets (&amp;quot;[]&amp;quot;), the existing categories as of this writing (2025-01-22) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;command&#039;&#039;&#039; / &#039;&#039;&#039;cmd&#039;&#039;&#039; - Acknowledges the reception of a command in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;usb&#039;&#039;&#039; - Acknowledges the reception of a &#039;&#039;MIDI message&#039;&#039; over &#039;&#039;USB&#039;&#039; in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;hardware&#039;&#039;&#039; / &#039;&#039;&#039;hw&#039;&#039;&#039; - Signals that a change has been sent to the Ekdahl FAR hardware, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;undefined&#039;&#039;&#039; / &#039;&#039;&#039;un&#039;&#039;&#039; - The message sent is in the &#039;&#039;undefined&#039;&#039; category, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;priority&#039;&#039;&#039; / &#039;&#039;&#039;pri&#039;&#039;&#039; - The message sent is in the &#039;&#039;priority&#039;&#039; category, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;error&#039;&#039;&#039; / &#039;&#039;&#039;err&#039;&#039;&#039; - Signals that an &#039;&#039;error&#039;&#039; has occurred, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;expressionparser&#039;&#039;&#039; / &#039;&#039;&#039;ep&#039;&#039;&#039; - These messages contains debugging information regarding the internal &#039;&#039;expression parser&#039;&#039; and is used for development&lt;br /&gt;
*&#039;&#039;&#039;debug&#039;&#039;&#039; / &#039;&#039;&#039;dbg&#039;&#039;&#039; - These messages contains various debugging information and is used for development&lt;br /&gt;
*&#039;&#039;&#039;help&#039;&#039;&#039; / &#039;&#039;&#039;hlp&#039;&#039;&#039; - Signals that the message is a response to a &#039;&#039;help&#039;&#039;-command being sent to the Ekdahl FAR. These messages are structured so that a receiver, like the &#039;&#039;Configuration utility&#039;&#039;, can parse information about available &#039;&#039;commands&#039;&#039; in the current &#039;&#039;firmware&#039;&#039; and relay it to a user in a structured way.&lt;br /&gt;
* &#039;&#039;&#039;inforequest&#039;&#039;&#039; / &#039;&#039;&#039;irq&#039;&#039;&#039; - Signals that an &#039;&#039;info request&#039;&#039; has been returned. This is a specialized message that is either sent as a response to an &#039;&#039;rqi&#039;&#039;-command or as a &#039;&#039;interrupt&#039;&#039;-message telling the user or receiving software about different parameters in the Ekdahl FAR. These messages follows the same structure as regular &#039;&#039;command message&#039;&#039;s of &#039;&#039;[irq]commandname:parameter1 [etc]&#039;&#039; so that it can be used by a receiving software to keep track of parameter changes&lt;br /&gt;
&lt;br /&gt;
===== Explicitly requesting information =====&lt;br /&gt;
By using the special command &amp;quot;requestinfo&amp;quot; / &amp;quot;rqi&amp;quot; one can request the information stored by a certain &#039;&#039;command&#039;&#039; or a state of the Ekdahl FAR. The &amp;quot;rqi&amp;quot;-command is executed in the convention &amp;quot;rqi:commandname:optional parameters&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
To go back to our example of setting the bowing frequency using the &#039;&#039;&amp;quot;&#039;&#039;bowcontrolfrequency&amp;quot; / &amp;quot;bowingwheel.pid.targetfrequency&amp;quot;-command we can ask the Ekdahl FAR what the bowing frequency is set to by writing&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
rqi:bowcontrolfrequency&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
rqi:bowingwheel.pid.targetfrequency&lt;br /&gt;
&amp;lt;/pre&amp;gt;The return value would be something like&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
[irq]bcf:82.5&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
[irq]bw[0].pid[0].tf:82.5&lt;br /&gt;
&amp;lt;/pre&amp;gt;Where &#039;[irq]&#039; denotes that the message returned is in the &#039;&#039;info request-&#039;&#039;category, that it pertains to the command &amp;quot;bcf&amp;quot; / &amp;quot;bw.pid.tf&amp;quot; and has the value &#039;&#039;82.5&#039;&#039;. Note that the returned &#039;&#039;command&#039;&#039; sent by an &amp;quot;rqi&amp;quot;-command always uses the &#039;&#039;short name&#039;&#039; in order to preserve bandwidth. In the FAR 1.1 the return statement always returns the &#039;&#039;index&#039;&#039; of the &#039;&#039;module&#039;&#039;(s) in question. &lt;br /&gt;
&lt;br /&gt;
Most commands do not require any &#039;&#039;parameters&#039;&#039; when using the &amp;quot;rqi&amp;quot;-command. The &#039;&#039;&amp;quot;&#039;&#039;adcread&amp;quot; / &amp;quot;controlbox.datareturn&amp;quot;-command is an example of a &#039;&#039;command&#039;&#039; that &amp;lt;u&amp;gt;does&amp;lt;/u&amp;gt; require a &#039;&#039;parameter&#039;&#039; when used with &amp;quot;rqi&amp;quot;. The &amp;quot;adcread&amp;quot; / &amp;quot;controlbox.datareturn&amp;quot;&#039;&#039;-&#039;&#039;command returns the last value read by the &#039;&#039;analog-to-digital converter&#039;&#039; in the &#039;&#039;Control box&#039;&#039;, because there are 8 different channels the first &#039;&#039;parameter&#039;&#039; sets which channel to return the data for, hence executing the &#039;&#039;command&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
rqi:adcr:3&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
rqi:controlbox.datareturn:3&lt;br /&gt;
&amp;lt;/pre&amp;gt;will return the last data read on &#039;&#039;analog-to-digital convert&#039;&#039; channel 3.&lt;br /&gt;
&lt;br /&gt;
== MIDI mapping ==&lt;br /&gt;
The way &#039;&#039;MIDI&#039;&#039; works int the Ekdahl FAR is that each &#039;&#039;MIDI message&#039;&#039; is associated with a certain &#039;&#039;command string&#039;&#039; and the &#039;&#039;MIDI message&#039;&#039; will also update some of the internal &#039;&#039;variables&#039;&#039;. Any time the associated &#039;&#039;MIDI message&#039;&#039; is received the Ekdahl FAR will execute the &#039;&#039;commands&#039;&#039; that have been associated with that &#039;&#039;MIDI message&#039;&#039;. Several &#039;&#039;MIDI configurations&#039;&#039; can be stored and recalled at any time, each with a different set of &#039;&#039;commands&#039;&#039; associated with each &#039;&#039;MIDI message&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;FAR &amp;lt; 1.1&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 The &#039;&#039;command&#039;&#039; responsible for mapping &#039;&#039;command strings&#039;&#039; to different &#039;&#039;MIDI messages&#039;&#039; is &amp;quot;midieventhandler&amp;quot; or &amp;quot;mev&amp;quot; for short. The first &#039;&#039;parameter&#039;&#039; of &amp;quot;mev&amp;quot; is the type of &#039;&#039;MIDI message&#039;&#039; that we want to remap;&lt;br /&gt;
 &lt;br /&gt;
 * &#039;&#039;&#039;noteon&#039;&#039;&#039; - Note on&lt;br /&gt;
 * &#039;&#039;&#039;noteoff&#039;&#039;&#039; - Note off&lt;br /&gt;
 * &#039;&#039;&#039;pat&#039;&#039;&#039; - Poly after touch&lt;br /&gt;
 * &#039;&#039;&#039;cat&#039;&#039;&#039; - Channel after touch&lt;br /&gt;
 * &#039;&#039;&#039;pb&#039;&#039;&#039; - Pitch bend&lt;br /&gt;
 * &#039;&#039;&#039;pc&#039;&#039;&#039; - Program change&lt;br /&gt;
 * &#039;&#039;&#039;cc&#039;&#039;&#039; - Continuous controller&lt;br /&gt;
 &lt;br /&gt;
 The second &#039;&#039;parameter&#039;&#039; is the &#039;&#039;command string&#039;&#039; that is to be associated with the &#039;&#039;MIDI Message&#039;&#039; - with the exception of the &#039;&#039;&#039;cc&#039;&#039;&#039;-type, here the second &#039;&#039;parameter&#039;&#039; is the &#039;&#039;controller number&#039;&#039; (0 - 127) and the third &#039;&#039;parameter&#039;&#039; is the &#039;&#039;command string&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;FAR 1.1&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 The &amp;quot;bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; contains a &#039;&#039;module&#039;&#039; called &amp;quot;midiconfigurationhandler&amp;quot; that handles the loading and switching in between different &#039;&#039;MIDI configurations&#039;&#039;. The &amp;quot;midiconfigurationhandler&amp;quot;&#039;&#039;-module&#039;&#039; has one or more &#039;&#039;&amp;quot;&#039;&#039;midiconfiguration&amp;quot;-&#039;&#039;modules&#039;&#039;, each having its own &#039;&#039;MIDI&#039;&#039; settings. In order to change the &#039;&#039;command mapping&#039;&#039; for a &#039;&#039;MIDI message&#039;&#039; in a specific &#039;&#039;MIDI configuration&#039;&#039;, the following &#039;&#039;commands&#039;&#039; are used;&lt;br /&gt;
 &lt;br /&gt;
 * &#039;&#039;&#039;noteon/non&#039;&#039;&#039;:&#039;&#039;commands&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed for a &#039;note on&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;noteoff/nof&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;note off&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;polyaftertouch/pat&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;poly aftertouch&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;channelaftertouch/cat&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;channel aftertouch&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;pitchbend/pb&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;pitch bend&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;programchange/pc&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;program change&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;continuouscontrollerdata/ccd&#039;&#039;&#039;&#039;&#039;:controller:commands&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed for &#039;continuous controller&#039; no &#039;&#039;controller&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
We can of course use the &#039;&#039;&amp;quot;&#039;&#039;rqi&amp;quot;-&#039;&#039;command&#039;&#039; to check the current mapping, below we are asking what the current &#039;&#039;command string&#039;&#039; associated with the &#039;&#039;pitch bend&#039;&#039; &#039;&#039;MIDI message&#039;&#039; is in the currently selected &#039;&#039;MIDI configuration&#039;&#039;.&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
rqi:midieventhandler:pb&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
rqi:bowingwheel.midiconfigurationhandler.midiconfiguration.pitchbend&lt;br /&gt;
&amp;lt;/pre&amp;gt;This may return something like&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
[irq]mev:pb:&amp;quot;bowcontrolharmonicshift:pitch*4&amp;quot;&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
[irq]bw[0].mcf[0].mc[0].pb:&amp;quot;bowingwheel.harmonicserieshandler.harmonicseries.shift:pitch*4&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;The first part of the return message tells us that the incoming message is of &amp;quot;rqi&amp;quot;-type (&amp;quot;[irq]&amp;quot;) which means it&#039;s responding to a information request &#039;&#039;command&#039;&#039; sent. The second part tells us what &#039;&#039;command&#039;&#039; the information request return is responding to and any &#039;&#039;parameters&#039;&#039; that may be pertinent. The third part of the message is the actual data stored.  &lt;br /&gt;
&lt;br /&gt;
For the FAR &amp;lt; 1.1 the data returned is for the &#039;&#039;command&#039;&#039; &amp;quot;mev&amp;quot; with the first &#039;&#039;parameter&#039;&#039; set to &amp;quot;pb&amp;quot;, the &#039;&#039;command reference&#039;&#039; tells us this means the &#039;&#039;command&#039;&#039; &amp;quot;midieventhandler&amp;quot; and the &#039;&#039;parameter&#039;&#039; &amp;quot;pb&amp;quot; indicates this has to do with the &#039;&#039;pitch bend&#039;&#039;. The data is &amp;quot;bowcontrolharmonicshift:pitch*4&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
For the FAR 1.1 the data returned is for the &#039;&#039;command&#039;&#039; &amp;quot;bw[0].mcf[0].mc[0].pb&amp;quot; (bowinwheel[0].midiconfigurationhandler[0].midiconfiguration[0].pitchbend) and the data is &amp;quot;bowingwheel.harmonicserieshandler.harmonicseries.shift:pitch*4&amp;quot;. Note here that if we have several different &#039;&#039;MIDI configurations&#039;&#039; stored and we&#039;re currently using configuration number 2, the returned message would have been &amp;quot;bw[0].mcf[0].mc[2].pb&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
that the &#039;&#039;pitch bend MIDI message&#039;&#039; is executing a &amp;quot;bowcontrolharmonicshift&amp;quot; / &amp;quot;harmonicseries.shift&amp;quot;-command with the parameter &#039;&#039;pitch*4&#039;&#039;. Looking in the &#039;&#039;command reference&#039;&#039; we can see that &#039;&#039;&amp;quot;&#039;&#039;bowcontrolharmonicshift&amp;quot; / &amp;quot;harmonicseries.shift&amp;quot;-&#039;&#039;command&#039;&#039; shifts the frequency of the &#039;&#039;bowing wheel&#039;&#039; from the currently selected harmonic. The first (and only) &#039;&#039;parameter&#039;&#039; sets how much we want to shift it (the range depends on the &amp;quot;bowcontrolharmonicshiftrange&#039;&#039;&amp;quot;&#039;&#039; / &amp;quot;harmonicseries.shiftrange&amp;quot;-&#039;&#039;command&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
If we look in the list of &#039;&#039;[[The Ekdahl FAR - Command langue#Variables|variables]]&#039;&#039; above we can see that the &#039;&#039;pitch bend MIDI message&#039;&#039; will set the &amp;quot;pitch&amp;quot;&#039;&#039;-variable&#039;&#039; which is indeed used. Now what is the &#039;&#039;&#039;*4&#039;&#039;&amp;lt;nowiki/&amp;gt;&#039; all about? Well the &amp;quot;bowcontrolharmonicshift&amp;quot; / &amp;quot;harmoniceseries.shift&amp;quot;-&#039;&#039;command&#039;&#039; expects a &#039;&#039;16-bit signed&#039;&#039; value as its &#039;&#039;parameter&#039;&#039;. This means that the valid &#039;&#039;parameter&#039;&#039; number can be anything from -32767 to 32767. A full &#039;&#039;harmonic shift&#039;&#039; downwards according to the range set is equal to -32767, a full &#039;&#039;harmonic shift&#039;&#039; upwards is 32767 and no &#039;&#039;harmonic shift&#039;&#039; is 0. The &#039;&#039;pitch bend MIDI message&#039;&#039; however is only 14-bits, meaning its range is -8192 to 8192. So we have to multiply &#039;&#039;pitch&#039;&#039; by 4 in order to meet the requirements of a &#039;&#039;16-bit signed parameter&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
This whole thing about number of bits can seem confusing but in the end it&#039;s all about how fine control you have over things; the more possible values, the more detailed control. In fact, most &#039;&#039;MIDI&#039;&#039; values are only 7-bit (!) meaning a range of 0 - 127. While this may sound like a lot of detail for something like a volume control, it is not even close to enough resolution to for instance set the &#039;&#039;bowing frequency&#039;&#039;. Even if you would limit yourself to a single octave the instrument would never be able to be properly in tune. The idea of limiting the Ekdahl FAR to what is possible through &#039;&#039;MIDI&#039;&#039; seemed like a poor choice thus it was decided that &amp;lt;u&amp;gt;most&amp;lt;/u&amp;gt; parameters will instead be 16-bit.&lt;br /&gt;
&lt;br /&gt;
Now lets look at a more complex example, the &amp;lt;u&amp;gt;default&amp;lt;/u&amp;gt; &#039;&#039;Note On MIDI message&#039;&#039;. On a stock Ekdahl FAR, executing&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
rqi:mev:noteon&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
rqi:mcf.mf.non&lt;br /&gt;
&amp;lt;/pre&amp;gt;Will return something like&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
[irq]mev:noteon:&#039;bchb:note,bmr:1,bpid:1,bpe:1,se:(velocity*512)*(1-notecount),bcsm:0&#039;&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
[irq]mcf[0].mc[0].non:&#039;bw.hsh.hb:note,bw.dcm.ru:1,bw.pe:1,bw.bp.en:1,so.en:(velocity*512)*(1-notecount),bw.sm:0&#039;&amp;lt;/pre&amp;gt;As can be seen, there&#039;s a lot of stuff going on here! First of all, notice that everything after &amp;quot;mev:noteon:&amp;quot; / &amp;quot;mcf[0].mc[0].non:&amp;quot; is situated in between single quotes (&#039;) - this is &amp;lt;u&amp;gt;absolutely crucial&amp;lt;/u&amp;gt; for the Ekdahl FAR in order to know that everything within those last two quotes is part of the last &#039;&#039;parameter&#039;&#039; of the &amp;quot;mev&amp;quot; / &amp;quot;mcf.mc.non&amp;quot;-&#039;&#039;command&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Now let&#039;s break down what happens when this &#039;&#039;MIDI message&#039;&#039; is received, i.e. when a &#039;&#039;MIDI&#039;&#039; key is pressed down:&lt;br /&gt;
&lt;br /&gt;
# &amp;quot;bchb:note&amp;quot; / &amp;quot;bw.hsh.hb:note&amp;quot;  - Invokes the &amp;quot;bowcontrolharmonicbase&amp;quot; / &amp;quot;harmonicserieshandler.harmonicbase&amp;quot;&#039;&#039;-command&#039;&#039; with the first &#039;&#039;parameter&#039;&#039; set to the &#039;&#039;variable &amp;quot;&#039;&#039;note&amp;quot;. This sets the &#039;&#039;base harmonic&#039;&#039; that the Ekdahl FARs &#039;&#039;bowing motor&#039;&#039; should be set to. Here the &#039;&#039;variable&#039;&#039; &amp;quot;note&amp;quot; is used which is simply the MIDI key being pressed down, it is automatically converted by the &#039;&#039;command&#039;&#039; to the corresponding harmonic in the &#039;&#039;harmonic list&#039;&#039;&lt;br /&gt;
# &amp;quot;bmr:1&amp;quot; / &amp;quot;bw.dcm.ru&amp;quot; - Sets the &amp;quot;bowmotorrun&amp;quot; / &amp;quot;dcmotor.run&amp;quot;-command to &#039;1&#039;, starting the &#039;&#039;bow motor&#039;&#039;&lt;br /&gt;
# &amp;quot;bpid:1&amp;quot; / &amp;quot;bw.pe:1&amp;quot; - Sets the &amp;quot;bowpid&amp;quot; / &amp;quot;bowingwheel.pidenable&amp;quot;-&#039;&#039;command&#039;&#039; to &#039;1&#039;. Basically this enables the function that makes the Ekdahl FAR able to keep a stable frequency on the &#039;&#039;bowing motor&#039;&#039;.&lt;br /&gt;
# &amp;quot;bpe:1&amp;quot; / &amp;quot;bw.bp.en&amp;quot; - Sets the &amp;quot;bowpressureengage&amp;quot; / &amp;quot;bowpressure.engage&amp;quot;-&#039;&#039;command&#039;&#039; to &#039;1&#039; which moves the &#039;&#039;bowing jack&#039;&#039; to the &#039;&#039;engage position&#039;&#039;, aka just below the string if not additional &#039;&#039;pressure&#039;&#039; is applied&lt;br /&gt;
# &amp;quot;se:(velocity*512)*(1-notecount)&amp;quot; / &amp;quot;so.en:(velocity*512)*(1-notecount)&amp;quot; - Executes the &amp;quot;solenoidengage&amp;quot; / &amp;quot;solenoid.engage&amp;quot;-&#039;&#039;command&#039;&#039; with the value &#039;&#039;(velocity*512)*(1-notecount)&#039;&#039;. This will make the &#039;&#039;solenoid&#039;&#039; strike the &#039;&#039;hammer&#039;&#039; with a force that is dependent on the &amp;quot;velocity&amp;quot;-&#039;&#039;variable&#039;&#039; sent by the &#039;&#039;Note On MIDI message&#039;&#039; in order to make the &#039;&#039;hammer&#039;&#039; velocity sensitive.   But it also adds the somewhat perplexing part &amp;quot;*(1-notecount)&amp;quot;. &amp;quot;notecount&amp;quot; is a global &#039;&#039;variable&#039;&#039; that contains the number of MIDI keys that are currently being held down. If &amp;quot;notecount&amp;quot; is anything above zero, the outcome of the equation will either be zero or a negative number. The &amp;quot;solenoidengage&amp;quot; / &amp;quot;solenoid.engage&amp;quot;-&#039;&#039;command&#039;&#039; requires a &#039;&#039;16-bit unsigned&#039;&#039; value, aka the only valid numbers are 0 - 65535. Anything below 0 will be interpreted as zero, so what this equation does is that it only fires off the &#039;&#039;hammer&#039;&#039; if there are no previous keys being held down - it&#039;s being used in &#039;&#039;staccato&#039;&#039;  mode.&lt;br /&gt;
# &amp;quot;bcsm:0&amp;quot; / &amp;quot;bowingwheel.speedmode&amp;quot; - Sets the &amp;quot;bowcontrolspeedmode&amp;quot; / &amp;quot;bowingwheel.speedmode&amp;quot; to &#039;1&#039; which enables automatic shut down of the &#039;&#039;bowing motor&#039;&#039; after a given timeout.&lt;br /&gt;
Let&#039;s postulate that the Ekdahl FAR is tuned to a &#039;C&#039; at 65.4Hz and has its &#039;&#039;base&#039;&#039; set to middle &#039;C&#039; (&#039;&#039;MIDI key&#039;&#039; no 36). We are using the equal-temperament 12-tone scale and the Ekdahl FAR is set to respond to &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; &#039;&#039;MIDI channels&#039;&#039; (omni). Without having previously held any keys we press the middle &#039;C&#039; (&#039;&#039;note&#039;&#039; value 36) as hard as possible (&#039;&#039;velocity&#039;&#039; value &#039;&#039;127&#039;&#039;) on &#039;&#039;MIDI channel&#039;&#039; number 1 (&#039;&#039;channel&#039;&#039; value of 0). The Ekdahl FAR will get a &#039;&#039;note on MIDI message&#039;&#039; sent to it and from our mapping it will create the following &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
[irq]mev:noteon:&#039;bchb:36,bmr:1,bpid:1,bpe:1,se:(127*512)*(1-0),bcsm:0&#039;&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
[irq]mcf[0].mc[0].non:&#039;bw.hsh.hb:36,bw.dcm.ru:1,bw.pe:1,bw.bp.en:1,so.en:(127*512)*(1-0),bw.sm:0&#039;&amp;lt;/pre&amp;gt;What has happened here is that all &#039;&#039;variables&#039;&#039; have been replaced with the values sent by the &#039;&#039;MIDI message&#039;&#039;. Since those &#039;&#039;commands&#039;&#039; that doesn&#039;t have any &#039;&#039;variables&#039;&#039; with them will execute just as previously, only those &#039;&#039;commands&#039;&#039; whos &#039;&#039;parameters&#039;&#039; have changed will be explained:&lt;br /&gt;
&lt;br /&gt;
# &amp;quot;bchb: 36&amp;quot; / &amp;quot;bw.hsh.hb:36&amp;quot; - The &amp;quot;bowcontrolharmonicbase&amp;quot; / &amp;quot;harmonicserieshandler.harmonicbase&amp;quot; gets a value of &#039;&#039;36&#039;&#039; (middle &#039;C&#039;), because &#039;&#039;harmonic number 0&#039;&#039; is mapped to this key it will set the &#039;&#039;bowing wheel&#039;&#039; frequency to the &#039;&#039;fundamental&#039;&#039;; &#039;&#039;65.4&#039;&#039; Hertz&lt;br /&gt;
# &amp;quot;se: (127*512)*(1-0)&amp;quot; / &amp;quot;so.en: (127*512)*(1-0)&amp;quot; - the value of &#039;&#039;127&#039;&#039; comes from the &amp;quot;velocity&amp;quot;-&#039;&#039;variable&#039;&#039;, &#039;&#039;127 * 512 = 65024&#039;&#039; which is awfully close to a maximum hammer force of 65535. Since no previous notes were held down, the &#039;&#039;&amp;quot;&#039;&#039;notecount&amp;quot;-&#039;&#039;variable&#039;&#039;  is equal to &#039;&#039;0&#039;&#039; and thus &#039;&#039;65024 * 1 = 65024&#039;&#039;. The hammer is engaged with near maximum force.&lt;br /&gt;
So the result is that we have set the speed of the &#039;&#039;bowing motor&#039;&#039; and we have engaged the &#039;&#039;hammer&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Now imagine that without releasing this key, we press another &#039;C&#039; one octave above but at half the velocity. The Ekdahl FAR creates the following &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
[irq]mev:noteon:&#039;bchb:48,bmr:1,bpid:1,bpe:1,se:(63*512)*(1-1),bcsm:0&#039;&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
[irq]mcf[0].mc[0].non:&#039;bw.hsh.hb:48,bw.dcm.ru:1,bw.pe:1,bw.bp.en:1,so.en:(65*512)*(1-1),bw.sm:0&#039;&lt;br /&gt;
&amp;lt;/pre&amp;gt;Now we can see that the &amp;quot;note&amp;quot;-&#039;&#039;variable&#039;&#039; is 48 because the &#039;C&#039; one octave up is exactly 12 keys above the first. The &amp;quot;velocity&amp;quot;-&#039;&#039;variable&#039;&#039; has changed to 63 since we hit it with a lighter touch - and because we are &amp;lt;u&amp;gt;still holding the first key down&amp;lt;/u&amp;gt;, the &amp;quot;notecount&amp;quot;-&#039;&#039;variable&#039;&#039; is equal to &#039;&#039;1&#039;&#039;. Here&#039;s what happens&lt;br /&gt;
&lt;br /&gt;
# &amp;quot;bchb: 48&amp;quot; / &amp;quot;hsh.hb:48&amp;quot; - Due to the &#039;&#039;base&#039;&#039; being set to &#039;&#039;36&#039;&#039; the &#039;&#039;harmonic number&#039;&#039; is set to &#039;&#039;48 - 36 = 12&#039;&#039;. Because we are using a 12-tone scale &#039;&#039;harmonic number 12&#039;&#039; is exactly one octave above the &#039;&#039;fundamental&#039;&#039; thus the speed of the &#039;&#039;bowing wheel&#039;&#039; is set to &#039;&#039;65.4 * 2 = 130.8&#039;&#039; Hertz.&lt;br /&gt;
# &amp;quot;se: (63*512)*(1-1)&amp;quot; / &amp;quot;so.en: (63*512)*(1-1)&amp;quot; - The equation evalutes as &#039;&#039;63 * 512 = 32256&#039;&#039; and &#039;&#039;1 - 1 = 0&#039;&#039; thus &#039;&#039;32256 * 0 = 0&#039;&#039;. When the &amp;quot;solenoidengage&amp;quot; / &amp;quot;solenoid.engage&amp;quot;-&#039;&#039;command&#039;&#039; gets a &#039;&#039;parameter&#039;&#039; of &#039;&#039;0&#039;&#039; it will not engage the &#039;&#039;hammer&#039;&#039; - so the &#039;&#039;hammer&#039;&#039; doesn&#039;t strike&lt;br /&gt;
So it can be seen that with quite rudimentary math we can accomplish a whole lot of things here. Note also that even though the &#039;&#039;note on MIDI message&#039;&#039; also sets the &#039;&#039;channel&#039;&#039;-variable we never use it in this example - plenty of opportunity to make something weird happen depending on the &#039;&#039;MIDI channel&#039;&#039;!&lt;br /&gt;
&lt;br /&gt;
== CV Mapping ==&lt;br /&gt;
&#039;&#039;CV Mapping&#039;&#039; works exactly like the &#039;&#039;MIDI mapping&#039;&#039; with the difference that the command(s) for setting the &#039;&#039;CV mapping&#039;&#039; is different and that they all modify (and thus share) the &amp;quot;value&amp;quot;-&#039;&#039;variable&#039;&#039;. These &#039;&#039;events&#039;&#039; are triggered whenever the analog-to-digital converter senses a change in a control or modulation jack, if you use something like an LFO with the modulation jacks here you will get a LOT of events and subsequent &#039;&#039;commands&#039;&#039; being sent.  &lt;br /&gt;
 &#039;&#039;&#039;FAR &amp;lt; 1.1:&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 The command for changing the CV mapping is &amp;quot;adccommandmap&amp;quot; or &amp;quot;acm&amp;quot;, it take two parameters; channel and command string. The channels on the original Edkahl FAR Control box are as &lt;br /&gt;
 &lt;br /&gt;
 * 0 - The &amp;quot;Harmonic&amp;quot; knob and jack&lt;br /&gt;
 * 1 - The &amp;quot;Harmonic shift&amp;quot; knob and jack&lt;br /&gt;
 * 2 - The &amp;quot;Fine tune&amp;quot; knob&lt;br /&gt;
 * 3 - The &amp;quot;Pressure&amp;quot; knob and jack&lt;br /&gt;
 * 4 - The &amp;quot;Hammertrig&amp;quot; button and jack&lt;br /&gt;
 * 5 - The &amp;quot;Gate&amp;quot; switch and jack&lt;br /&gt;
 * 6 - The &amp;quot;Hammer Scale&amp;quot; knob&lt;br /&gt;
 * 7 - The &amp;quot;Mute&amp;quot; knob and jack&lt;br /&gt;
 &lt;br /&gt;
 &#039;&#039;&#039;FAR 1.1:&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 The commands responsible for changing the CV mapping are located in the &amp;quot;controlbox&amp;quot;-module, these are&lt;br /&gt;
 &lt;br /&gt;
 * &#039;&#039;&#039;harmonic&#039;&#039;&#039; &#039;&#039;&#039;/ har&#039;&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed when the &amp;quot;Harmonic&amp;quot;-knob or modulation changes&lt;br /&gt;
 * &#039;&#039;&#039;harmonicshift&#039;&#039;&#039; &#039;&#039;&#039;/ has&#039;&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed when the &amp;quot;Harmonic shift&amp;quot;-knob or modulation changes&lt;br /&gt;
 * &#039;&#039;&#039;finetune / fin&#039;&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed when the &amp;quot;Fine tune&amp;quot;-knob changes&lt;br /&gt;
 * &#039;&#039;&#039;pressure&#039;&#039;&#039; &#039;&#039;&#039;/ pre&#039;&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed when the &amp;quot;Pressure&amp;quot;-knob or modulation changes&lt;br /&gt;
 * &#039;&#039;&#039;mute&#039;&#039;&#039; &#039;&#039;&#039;/ mut&#039;&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed when the &amp;quot;Mute&amp;quot;-knob or modulation changes&lt;br /&gt;
 * &#039;&#039;&#039;hammerscale / hms&#039;&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed when the &amp;quot;Hammer scale&amp;quot;-knob changes&lt;br /&gt;
 * &#039;&#039;&#039;gate / gt&#039;&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed when the &amp;quot;Gate&amp;quot;-switch or modulation changes&lt;br /&gt;
 * &#039;&#039;&#039;hammertrig&#039;&#039;&#039; &#039;&#039;&#039;/ hmt&#039;&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed when the &amp;quot;Hammer Trig&amp;quot;-button or modulation changes&lt;br /&gt;
In order to set/retrieve &#039;&#039;mapping data&#039;&#039; we just use a regular &amp;quot;rqi&amp;quot;-&#039;&#039;command&#039;&#039;. To for instance get the &#039;&#039;command string&#039;&#039; executed when the &amp;quot;pressure&amp;quot; knob or modulation is sent we can do the following&lt;br /&gt;
 &#039;&#039;&#039;FAR &amp;lt; 1.1:&#039;&#039;&#039;&lt;br /&gt;
 [send] rqi:acm:3&lt;br /&gt;
 [returns] [irq]acm:3:&#039;bpb:value&#039;&lt;br /&gt;
 &lt;br /&gt;
 &#039;&#039;&#039;FAR 1.1:&#039;&#039;&#039;&lt;br /&gt;
 [send] rqi:controlbox.pressure&lt;br /&gt;
 [returns] [irq]cb[0].pre:&#039;bw.bp.ba:value&#039;&lt;br /&gt;
As can be seen, when the &#039;&#039;pressure&#039;&#039; knob or modulation changes, the new data read by the ADC (stored in the &amp;quot;value&amp;quot;-&#039;&#039;variable&#039;&#039;) is sent to the &#039;&#039;command&#039;&#039; controlling the &#039;&#039;bow pressure baseline.&#039;&#039; Hopefully at this point it is obvious that making the knob and jack on the &#039;&#039;control box&#039;&#039; that is labeled as &amp;quot;Pressure&amp;quot; do something completely different, is quite easy - just remap the &#039;&#039;command string&#039;&#039;.{{docnav&lt;br /&gt;
|[[The Ekdahl FAR - Service|Service]]&lt;br /&gt;
|[[The Ekdahl FAR - Command reference|Command reference]]&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Knaadmin</name></author>
	</entry>
	<entry>
		<id>http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_language&amp;diff=1658</id>
		<title>The Ekdahl FAR - Command language</title>
		<link rel="alternate" type="text/html" href="http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_language&amp;diff=1658"/>
		<updated>2026-06-12T10:12:26Z</updated>

		<summary type="html">&lt;p&gt;Knaadmin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Command language ==&lt;br /&gt;
The Ekdahl FAR is entirely controlled by &#039;&#039;commands&#039;&#039;, these &#039;&#039;commands&#039;&#039; decide everything that the instrument is doing, whether it is playing a melody or changing an internal parameter. &lt;br /&gt;
&lt;br /&gt;
When a &#039;&#039;MIDI message&#039;&#039; is received or a new CV / knob value is read, the &#039;&#039;commands&#039;&#039; associated with it will be internally sent. This can be things like &amp;quot;engage hammer&amp;quot; or &amp;quot;set the fundamental frequency&amp;quot; etc. &lt;br /&gt;
&lt;br /&gt;
Some of the available &#039;&#039;commands&#039;&#039; are mainly used for calibrating and setting up the instrument and are usually saved into the instruments memory, these will be executed whenever the instrument is turned on. &lt;br /&gt;
&lt;br /&gt;
All &#039;&#039;commands&#039;&#039; can be manually invoked via &#039;&#039;USB-Serial&#039;&#039;, in conjunction with certain software this presents an unprecedented level of control and sequenceability.&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
The &#039;&#039;commands&#039;&#039; are invoked using a &#039;&#039;plain text approach&#039;&#039;, all commands have both a &#039;&#039;long name&#039;&#039; and a &#039;&#039;short name&#039;&#039; which are interchangeable. A &#039;&#039;command&#039;&#039; may have one or more &#039;&#039;parameters&#039;&#039; associated with it, these &#039;&#039;parameters&#039;&#039; can be of different types; 16-bit numbers (values 0 - 65535 or -32767 - 32767), floating point numbers (values with decimals), booleans (0 for &#039;false&#039;, 1 for &#039;true&#039;) and strings (text). Some commands are &#039;&#039;conditional&#039;&#039;, meaning they will only execute if a parameter equates to &#039;1&#039; (&#039;true&#039;). &lt;br /&gt;
&lt;br /&gt;
The way &#039;&#039;commands&#039;&#039; are written in order to be executed is &#039;&#039;commandname:parameter1:parameter2:parameter3 [etc]&#039;&#039;, several commands be executed in sequence by separating them with a comma (&#039;,&#039;), a bunch of commands strung together is called a &#039;&#039;command string&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Since version 1.1 of the Ekdahl FAR Firmware, all commands are grouped in a hierarchical fashion according to their &#039;&#039;modules&#039;&#039; and each ladder in the hierarchy is separated by a period (&amp;quot;.&amp;quot;), this works very much like folders or directories in a regular computer. Every &#039;&#039;module&#039;&#039; can contain both &#039;&#039;commands&#039;&#039; and other &#039;&#039;modules&#039;&#039;. For instance, everything associated with the &#039;&#039;bowing wheel&#039;&#039; is now collected under &amp;quot;bowingwheel&amp;quot; &#039;&#039;module&#039;&#039;. That in turn contains a &amp;quot;dcmotor&amp;quot; &#039;&#039;module&#039;&#039; which handles direct control of the bowing motor. It also has a &amp;quot;pid&amp;quot; &#039;&#039;module&#039;&#039; that handles bow frequency among other thing. &lt;br /&gt;
&lt;br /&gt;
If for instance we would like to start the &#039;&#039;bowing wheel&#039;&#039; and set its frequency to 82.5 Hertz we could send the Ekdahl FAR the following &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
bowmotorrun:1, bowcontrolfrequecy:82.5&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bowingwheel.dcmotor.run:1, bowingwheel.pid.targetfrequency:82.5&amp;lt;/pre&amp;gt;We could also use the &#039;&#039;short names&#039;&#039; for the commands&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
bmr:1,bcf:82.5&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bw.dcm.ru:1, bw.pid.tf:82.5&amp;lt;/pre&amp;gt;Both &amp;quot;bowmotorrun&amp;quot; / &amp;quot;bowingwheel.dcmotor.run&amp;quot; and &amp;quot;bowcontrolfrequency&amp;quot; / &amp;quot;bowingwheel.pid.targetfrequency&amp;quot; takes one &#039;&#039;parameter&#039;&#039; each, &#039;&#039;&amp;quot;&#039;&#039;bowmotorrun&amp;quot; / &amp;quot;bowingwheel.dcmotor.run&amp;quot; is &#039;&#039;conditional&#039;&#039; and unless the first &#039;&#039;parameter&#039;&#039; is equal to &#039;1&#039; the motor will not start. The first &#039;&#039;parameter&#039;&#039; of &amp;quot;bowcontrolfrequency&amp;quot; / &amp;quot;bowingwheel.pid.targetfrequency&amp;quot; sets the frequency of the &#039;&#039;bowing wheel&#039;&#039;, the instrument may not execute a &#039;&#039;command&#039;&#039; if it decides that the given &#039;&#039;parameters&#039;&#039; are outside of the working range or they are missing.&lt;br /&gt;
&lt;br /&gt;
The addition of the hierarchy in the FAR 1.1 firmware isn&#039;t just to be able to group commands, but it&#039;s also to make the FAR not limited to a single set of &#039;&#039;modules&#039;&#039; (and is the first stepping stone to a &#039;&#039;modular&#039;&#039; Ekdahl FAR). In fact, you could have 12 different bowing wheel &#039;&#039;modules&#039;&#039; for 12 different strings, these would then be addressed as &amp;quot;bowingwheel[0].command&amp;quot;&#039;&#039;, &amp;quot;&#039;&#039;bowingwheel[1].command&amp;quot; etc. Anyone familiar with C programming notices that this is the standard way of &#039;&#039;indexing&#039;&#039; an array; using brackets (&amp;quot;[ ]&amp;quot;). When addressing a module without &#039;&#039;indexing&#039;&#039; as in the example above, the FAR will do one or two things; either use the first object (&amp;quot;[0]&amp;quot;) or, if the object is &#039;&#039;selectable&#039;&#039; it will use the previously selected object. To make things smoother a command can be executed on several objects at once by using ranges (&amp;quot;[0-4]&amp;quot;) and comma separation (&amp;quot;[0, 3, 5-6]&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
To test out a &#039;&#039;command&#039;&#039; you can send it directly to the Ekdahl FAR using the &#039;&#039;Console&#039;&#039; in the &#039;&#039;Configuration utility&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
To read up on existing &#039;&#039;commands&#039;&#039;, their &#039;&#039;parameters&#039;&#039; and a brief description you can check the &#039;&#039;Command reference&#039;&#039; in the &#039;&#039;Configuration utility&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Variables, functions and equations ==&lt;br /&gt;
What makes the &#039;&#039;Command language&#039;&#039; truly powerful is the concept of &#039;&#039;variables, functions&#039;&#039; and &#039;&#039;equations&#039;&#039;. All &#039;&#039;parameters&#039;&#039; that take numerical values can use any combination of &#039;&#039;variables, functions&#039;&#039; or &#039;&#039;equations.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
For instance, we can use the previous example and instead write our &#039;&#039;command string&#039;&#039; as follows&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
bowmotorrun:1, bowcontrolfrequency:82.5+note*20&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bowingwheel.dcmotor.run:1, bowingwheel.pid.targetfrequency:82.5+note*20&amp;lt;/pre&amp;gt;This example requires of course that the &#039;&#039;variable&#039;&#039; &#039;&#039;note&#039;&#039; exists in the current context. &lt;br /&gt;
&lt;br /&gt;
===== Variables =====&lt;br /&gt;
There are two types of &#039;&#039;variables&#039;&#039; in the Ekdahl FAR; &#039;&#039;global variables&#039;&#039; and &#039;&#039;event variables&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Global variables&#039;&#039; are variables that are always valid, in any context. The &#039;&#039;global variables&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;notecount&#039;&#039;&#039; - Contains the number of &#039;&#039;MIDI&#039;&#039; keys that are being held down, i.e. all &#039;&#039;Note on messages&#039;&#039; received that haven&#039;t gotten a paired &#039;&#039;Note off message&#039;&#039; yet&lt;br /&gt;
* &#039;&#039;&#039;uv0&#039;&#039;&#039; - &#039;&#039;&#039;uv9&#039;&#039;&#039; - These are &#039;&#039;user variables&#039;&#039; and can be set at any point using the &#039;&#039;globaluservariable command&#039;&#039; with the first &#039;&#039;parameter&#039;&#039; being which variable to set (0-9) and the second &#039;&#039;parameter&#039;&#039; being the value (float).&lt;br /&gt;
* &#039;&#039;&#039;e&#039;&#039;&#039; - Contains the constant &#039;&#039;[[wikipedia:E_(mathematical_constant)|e]]&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pi&#039;&#039;&#039; - Contains the constant &#039;&#039;[[wikipedia:Pi|pi]]&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Event variables&#039;&#039; are variables that are set by certain &#039;&#039;MIDI messages&#039;&#039; or when a new value is read on one of the jacks or knobs on the &#039;&#039;Control box&#039;&#039;. The &#039;&#039;Event variables&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;channel&#039;&#039;&#039; - Set by the &#039;&#039;Note on, Note off, Continuous Controller, Poly after touch, Pitch bend, Channel after touch&#039;&#039; and &#039;&#039;Program change MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;note&#039;&#039;&#039; - Set by the &#039;&#039;Note on, Note off&#039;&#039; and &#039;&#039;Poly after touch MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;velocity&#039;&#039;&#039; - Set by the &#039;&#039;Note on&#039;&#039; and &#039;&#039;Note off MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pressure&#039;&#039;&#039; - Set by the &#039;&#039;Poly after touch&#039;&#039; and &#039;&#039;Channel after touch MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; - Set by the &#039;&#039;Continuous Controller MIDI message&#039;&#039; and by the &#039;&#039;Control box&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pitch&#039;&#039;&#039; - Set by the &#039;&#039;Pitch bend MIDI message&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;program&#039;&#039;&#039; - Set by the &#039;&#039;Program change MIDI message&#039;&#039;&lt;br /&gt;
These variables will contain whatever data is relevant to the last event that occurred and may be overwritten by the next event.&lt;br /&gt;
&lt;br /&gt;
===== Functions =====&lt;br /&gt;
&#039;&#039;Functions&#039;&#039; can be used to change a numerical value or the result of an &#039;&#039;equation&#039;&#039;, the Ekdahl FAR contains both general &#039;&#039;arithmetic functions&#039;&#039; (courtesy of Lewis Van Winkle and the TINYEXPR engine) and &#039;&#039;specialized functions&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;arithmetic functions&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;abs&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Absolute_value|absolute value]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;acos&#039;&#039;&#039;(x), &#039;&#039;&#039;asin&#039;&#039;&#039;(x), &#039;&#039;&#039;atan&#039;&#039;&#039;(x), atan2(x, y) - Returns the [[wikipedia:Inverse_trigonometric_functions|&#039;&#039;arc-cos, -sin, -tan&#039;&#039; and &#039;&#039;-tan2&#039;&#039;]] of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;atan2&#039;&#039;&#039;(x,y) - Returns the &#039;&#039;[[wikipedia:Atan2|arctan2]]&#039;&#039; of &#039;&#039;x, y&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;floor&#039;&#039;&#039;(x), ceil(x) - Returns the [[wikipedia:Floor_and_ceiling_functions|&#039;&#039;floor&#039;&#039; and &#039;&#039;ceiling&#039;&#039;]] of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;exp&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Exponential_function|exponent]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;fac&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Factorial|factorial]]&#039;&#039; of x&lt;br /&gt;
* &#039;&#039;&#039;ln&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Natural_logarithm|natural logarithm]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;log10&#039;&#039;&#039;(x), &#039;&#039;&#039;log20&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Logarithm|logarithm]]&#039;&#039; of &#039;&#039;x&#039;&#039; using base 10 and 20 respectively&lt;br /&gt;
* &#039;&#039;&#039;ncr&#039;&#039;&#039;(x,y), &#039;&#039;&#039;npr&#039;&#039;&#039;(x,y) - Functions to calculate &#039;&#039;[[wikipedia:Combination|combinations]]&#039;&#039; and &#039;&#039;[[wikipedia:Permutation|permutations]]&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pow&#039;&#039;&#039;(x,y) - Returns &#039;&#039;x^y&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;sqrt&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Square_root|square root]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;cos&#039;&#039;&#039;(x), &#039;&#039;&#039;sin&#039;&#039;&#039;(x), &#039;&#039;&#039;tan&#039;&#039;&#039;(x) - Returns the [[wikipedia:Trigonometric_functions|&#039;&#039;cos, sin&#039;&#039; and &#039;&#039;tan&#039;&#039;]] of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;cosh&#039;&#039;&#039;(x), &#039;&#039;&#039;sinh&#039;&#039;&#039;(x), &#039;&#039;&#039;tanh&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Hyperbolic_functions|hyperbolic cos, sin and tan]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
The &#039;&#039;specialized functions&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;bool&#039;&#039;&#039;(x) - Returns 1 if &#039;&#039;x&#039;&#039; is more than 0&lt;br /&gt;
* &#039;&#039;&#039;ibool&#039;&#039;&#039;(x) - Returns 0 if &#039;&#039;x&#039;&#039; is more than 0&lt;br /&gt;
* &#039;&#039;&#039;deadband&#039;&#039;&#039;(x,y) - Returns &#039;&#039;x + y &#039;&#039; if &#039;&#039;x &amp;lt; y&#039;&#039; or &#039;&#039;x - y&#039;&#039; if &#039;&#039;x &amp;gt; y&#039;&#039;. If neither of these statements is true it returns &#039;&#039;0&#039;&#039; - used to create a [[wikipedia:Deadband|deadband]] of &#039;&#039;x&#039;&#039; with the threshold of &#039;&#039;y&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Functions&#039;&#039; can be readily used in a &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
bowmotorrun:1, bowcontrolfrequency:&amp;quot;8.17579875 * pow(2, (1/12 * note))&amp;quot;&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bowingwheel.dcmotor.run:1, bowingwheel.pid.targetfrequency:&amp;quot;8.17579875 * pow(2, (1/12 * note))&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;The previous statements starts the &#039;&#039;bowing wheel&#039;&#039; and sets the frequency of the wheel to &#039;&#039;8.17579875 * 2^(1/12 * note)&#039;&#039;. A middle &#039;C&#039; according to &#039;&#039;MIDI&#039;&#039; has a &#039;&#039;note value&#039;&#039; of 36, meaning if we substitute &#039;&#039;note&#039;&#039; with 36 we get the equation &#039;&#039;8.17579875 * 2^(1/12 * 36)&#039;&#039; which comes out to &#039;&#039;~65.4&#039;&#039; Hertz.&lt;br /&gt;
&lt;br /&gt;
Note that the first &#039;&#039;parameter&#039;&#039; for &#039;&#039;&amp;quot;&#039;&#039;bowcontrolfrequency&amp;quot; / &amp;quot;bowingwheel.pid.targetfrequency&amp;quot; is put in between double quotes (&amp;quot;). This is because the &amp;quot;pow&#039;&#039;&amp;quot;-&#039;&#039;function requires the use of a comma (&amp;quot;,&amp;quot;) in order to separate in between its two required inputs; &#039;&#039;x&#039;&#039; and &#039;&#039;y&#039;&#039;. In order for the Ekdahl FAR to know that this comma does not signal the beginning of a new &#039;&#039;command,&#039;&#039; we use quotes. Single (&#039;) and double (&amp;quot;) quotes can be used and nested in all &#039;&#039;parameters&#039;&#039; and are &amp;lt;u&amp;gt;required&amp;lt;/u&amp;gt; in a lot of circumstances, improper nesting or not using quotes can lead to the instrument not understanding the &#039;&#039;command string&#039;&#039; correctly.&lt;br /&gt;
&lt;br /&gt;
== Return messages ==&lt;br /&gt;
The Ekdahl FAR when connected via &#039;&#039;USB-Serial&#039;&#039; doesn&#039;t only accept &#039;&#039;commands&#039;&#039; but will also send various &#039;&#039;return messages&#039;&#039;. These are prefixed by their &#039;&#039;category&#039;&#039; denoted in brackets (&amp;quot;[]&amp;quot;), the existing categories as of this writing (2025-01-22) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;command&#039;&#039;&#039; / &#039;&#039;&#039;cmd&#039;&#039;&#039; - Acknowledges the reception of a command in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;usb&#039;&#039;&#039; - Acknowledges the reception of a &#039;&#039;MIDI message&#039;&#039; over &#039;&#039;USB&#039;&#039; in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;hardware&#039;&#039;&#039; / &#039;&#039;&#039;hw&#039;&#039;&#039; - Signals that a change has been sent to the Ekdahl FAR hardware, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;undefined&#039;&#039;&#039; / &#039;&#039;&#039;un&#039;&#039;&#039; - The message sent is in the &#039;&#039;undefined&#039;&#039; category, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;priority&#039;&#039;&#039; / &#039;&#039;&#039;pri&#039;&#039;&#039; - The message sent is in the &#039;&#039;priority&#039;&#039; category, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;error&#039;&#039;&#039; / &#039;&#039;&#039;err&#039;&#039;&#039; - Signals that an &#039;&#039;error&#039;&#039; has occurred, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;expressionparser&#039;&#039;&#039; / &#039;&#039;&#039;ep&#039;&#039;&#039; - These messages contains debugging information regarding the internal &#039;&#039;expression parser&#039;&#039; and is used for development&lt;br /&gt;
*&#039;&#039;&#039;debug&#039;&#039;&#039; / &#039;&#039;&#039;dbg&#039;&#039;&#039; - These messages contains various debugging information and is used for development&lt;br /&gt;
*&#039;&#039;&#039;help&#039;&#039;&#039; / &#039;&#039;&#039;hlp&#039;&#039;&#039; - Signals that the message is a response to a &#039;&#039;help&#039;&#039;-command being sent to the Ekdahl FAR. These messages are structured so that a receiver, like the &#039;&#039;Configuration utility&#039;&#039;, can parse information about available &#039;&#039;commands&#039;&#039; in the current &#039;&#039;firmware&#039;&#039; and relay it to a user in a structured way.&lt;br /&gt;
* &#039;&#039;&#039;inforequest&#039;&#039;&#039; / &#039;&#039;&#039;irq&#039;&#039;&#039; - Signals that an &#039;&#039;info request&#039;&#039; has been returned. This is a specialized message that is either sent as a response to an &#039;&#039;rqi&#039;&#039;-command or as a &#039;&#039;interrupt&#039;&#039;-message telling the user or receiving software about different parameters in the Ekdahl FAR. These messages follows the same structure as regular &#039;&#039;command message&#039;&#039;s of &#039;&#039;[irq]commandname:parameter1 [etc]&#039;&#039; so that it can be used by a receiving software to keep track of parameter changes&lt;br /&gt;
&lt;br /&gt;
===== Explicitly requesting information =====&lt;br /&gt;
By using the special command &amp;quot;requestinfo&amp;quot; / &amp;quot;rqi&amp;quot; one can request the information stored by a certain &#039;&#039;command&#039;&#039; or a state of the Ekdahl FAR. The &amp;quot;rqi&amp;quot;-command is executed in the convention &amp;quot;rqi:commandname:optional parameters&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
To go back to our example of setting the bowing frequency using the &#039;&#039;&amp;quot;&#039;&#039;bowcontrolfrequency&amp;quot; / &amp;quot;bowingwheel.pid.targetfrequency&amp;quot;-command we can ask the Ekdahl FAR what the bowing frequency is set to by writing&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
rqi:bowcontrolfrequency&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
rqi:bowingwheel.pid.targetfrequency&lt;br /&gt;
&amp;lt;/pre&amp;gt;The return value would be something like&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
[irq]bcf:82.5&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
[irq]bw[0].pid[0].tf:82.5&lt;br /&gt;
&amp;lt;/pre&amp;gt;Where &#039;[irq]&#039; denotes that the message returned is in the &#039;&#039;info request-&#039;&#039;category, that it pertains to the command &amp;quot;bcf&amp;quot; / &amp;quot;bw.pid.tf&amp;quot; and has the value &#039;&#039;82.5&#039;&#039;. Note that the returned &#039;&#039;command&#039;&#039; sent by an &amp;quot;rqi&amp;quot;-command always uses the &#039;&#039;short name&#039;&#039; in order to preserve bandwidth. In the FAR 1.1 the return statement always returns the &#039;&#039;index&#039;&#039; of the &#039;&#039;module&#039;&#039;(s) in question. &lt;br /&gt;
&lt;br /&gt;
Most commands do not require any &#039;&#039;parameters&#039;&#039; when using the &amp;quot;rqi&amp;quot;-command. The &#039;&#039;&amp;quot;&#039;&#039;adcread&amp;quot; / &amp;quot;controlbox.datareturn&amp;quot;-command is an example of a &#039;&#039;command&#039;&#039; that &amp;lt;u&amp;gt;does&amp;lt;/u&amp;gt; require a &#039;&#039;parameter&#039;&#039; when used with &amp;quot;rqi&amp;quot;. The &amp;quot;adcread&amp;quot; / &amp;quot;controlbox.datareturn&amp;quot;&#039;&#039;-&#039;&#039;command returns the last value read by the &#039;&#039;analog-to-digital converter&#039;&#039; in the &#039;&#039;Control box&#039;&#039;, because there are 8 different channels the first &#039;&#039;parameter&#039;&#039; sets which channel to return the data for, hence executing the &#039;&#039;command&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
rqi:adcr:3&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
rqi:controlbox.datareturn:3&lt;br /&gt;
&amp;lt;/pre&amp;gt;will return the last data read on &#039;&#039;analog-to-digital convert&#039;&#039; channel 3.&lt;br /&gt;
&lt;br /&gt;
== MIDI mapping ==&lt;br /&gt;
The way &#039;&#039;MIDI&#039;&#039; works int the Ekdahl FAR is that each &#039;&#039;MIDI message&#039;&#039; is associated with a certain &#039;&#039;command string&#039;&#039; and the &#039;&#039;MIDI message&#039;&#039; will also update some of the internal &#039;&#039;variables&#039;&#039;. Any time the associated &#039;&#039;MIDI message&#039;&#039; is received the Ekdahl FAR will execute the &#039;&#039;commands&#039;&#039; that have been associated with that &#039;&#039;MIDI message&#039;&#039;. Several &#039;&#039;MIDI configurations&#039;&#039; can be stored and recalled at any time, each with a different set of &#039;&#039;commands&#039;&#039; associated with each &#039;&#039;MIDI message&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;FAR &amp;lt; 1.1&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 The &#039;&#039;command&#039;&#039; responsible for mapping &#039;&#039;command strings&#039;&#039; to different &#039;&#039;MIDI messages&#039;&#039; is &amp;quot;midieventhandler&amp;quot; or &amp;quot;mev&amp;quot; for short. The first &#039;&#039;parameter&#039;&#039; of &amp;quot;mev&amp;quot; is the type of &#039;&#039;MIDI message&#039;&#039; that we want to remap;&lt;br /&gt;
 &lt;br /&gt;
 * &#039;&#039;&#039;noteon&#039;&#039;&#039; - Note on&lt;br /&gt;
 * &#039;&#039;&#039;noteoff&#039;&#039;&#039; - Note off&lt;br /&gt;
 * &#039;&#039;&#039;pat&#039;&#039;&#039; - Poly after touch&lt;br /&gt;
 * &#039;&#039;&#039;cat&#039;&#039;&#039; - Channel after touch&lt;br /&gt;
 * &#039;&#039;&#039;pb&#039;&#039;&#039; - Pitch bend&lt;br /&gt;
 * &#039;&#039;&#039;pc&#039;&#039;&#039; - Program change&lt;br /&gt;
 * &#039;&#039;&#039;cc&#039;&#039;&#039; - Continuous controller&lt;br /&gt;
 &lt;br /&gt;
 The second &#039;&#039;parameter&#039;&#039; is the &#039;&#039;command string&#039;&#039; that is to be associated with the &#039;&#039;MIDI Message&#039;&#039; - with the exception of the &#039;&#039;&#039;cc&#039;&#039;&#039;-type, here the second &#039;&#039;parameter&#039;&#039; is the &#039;&#039;controller number&#039;&#039; (0 - 127) and the third &#039;&#039;parameter&#039;&#039; is the &#039;&#039;command string&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;FAR 1.1&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 The &amp;quot;bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; contains a &#039;&#039;module&#039;&#039; called &amp;quot;midiconfigurationhandler&amp;quot; that handles the loading and switching in between different &#039;&#039;MIDI configurations&#039;&#039;. The &amp;quot;midiconfigurationhandler&amp;quot;&#039;&#039;-module&#039;&#039; has one or more &#039;&#039;&amp;quot;&#039;&#039;midiconfiguration&amp;quot;-&#039;&#039;modules&#039;&#039;, each having its own &#039;&#039;MIDI&#039;&#039; settings. In order to change the &#039;&#039;command mapping&#039;&#039; for a &#039;&#039;MIDI message&#039;&#039; in a specific &#039;&#039;MIDI configuration&#039;&#039;, the following &#039;&#039;commands&#039;&#039; are used;&lt;br /&gt;
 &lt;br /&gt;
 * &#039;&#039;&#039;noteon/non&#039;&#039;&#039;:&#039;&#039;commands&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed for a &#039;note on&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;noteoff/nof&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;note off&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;polyaftertouch/pat&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;poly aftertouch&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;channelaftertouch/cat&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;channel aftertouch&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;pitchbend/pb&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;pitch bend&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;programchange/pc&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;program change&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;continuouscontrollerdata/ccd&#039;&#039;&#039;&#039;&#039;:controller:commands&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed for &#039;continuous controller&#039; no &#039;&#039;controller&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
We can of course use the &#039;&#039;&amp;quot;&#039;&#039;rqi&amp;quot;-&#039;&#039;command&#039;&#039; to check the current mapping, below we are asking what the current &#039;&#039;command string&#039;&#039; associated with the &#039;&#039;pitch bend&#039;&#039; &#039;&#039;MIDI message&#039;&#039; is in the currently selected &#039;&#039;MIDI configuration&#039;&#039;.&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
rqi:midieventhandler:pb&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
rqi:bowingwheel.midiconfigurationhandler.midiconfiguration.pitchbend&lt;br /&gt;
&amp;lt;/pre&amp;gt;This may return something like&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
[irq]mev:pb:&amp;quot;bowcontrolharmonicshift:pitch*4&amp;quot;&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
[irq]bw[0].mcf[0].mc[0].pb:&amp;quot;bowingwheel.harmonicserieshandler.harmonicseries.shift:pitch*4&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;The first part of the return message tells us that the incoming message is of &amp;quot;rqi&amp;quot;-type (&amp;quot;[irq]&amp;quot;) which means it&#039;s responding to a information request &#039;&#039;command&#039;&#039; sent. The second part tells us what &#039;&#039;command&#039;&#039; the information request return is responding to and any &#039;&#039;parameters&#039;&#039; that may be pertinent. The third part of the message is the actual data stored.  &lt;br /&gt;
&lt;br /&gt;
For the FAR &amp;lt; 1.1 the data returned is for the &#039;&#039;command&#039;&#039; &amp;quot;mev&amp;quot; with the first &#039;&#039;parameter&#039;&#039; set to &amp;quot;pb&amp;quot;, the &#039;&#039;command reference&#039;&#039; tells us this means the &#039;&#039;command&#039;&#039; &amp;quot;midieventhandler&amp;quot; and the &#039;&#039;parameter&#039;&#039; &amp;quot;pb&amp;quot; indicates this has to do with the &#039;&#039;pitch bend&#039;&#039;. The data is &amp;quot;bowcontrolharmonicshift:pitch*4&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
For the FAR 1.1 the data returned is for the &#039;&#039;command&#039;&#039; &amp;quot;bw[0].mcf[0].mc[0].pb&amp;quot; (bowinwheel[0].midiconfigurationhandler[0].midiconfiguration[0].pitchbend) and the data is &amp;quot;bowingwheel.harmonicserieshandler.harmonicseries.shift:pitch*4&amp;quot;. Note here that if we have several different &#039;&#039;MIDI configurations&#039;&#039; stored and we&#039;re currently using configuration number 2, the returned message would have been &amp;quot;bw[0].mcf[0].mc[2].pb&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
that the &#039;&#039;pitch bend MIDI message&#039;&#039; is executing a &amp;quot;bowcontrolharmonicshift&amp;quot; / &amp;quot;harmonicseries.shift&amp;quot;-command with the parameter &#039;&#039;pitch*4&#039;&#039;. Looking in the &#039;&#039;command reference&#039;&#039; we can see that &#039;&#039;&amp;quot;&#039;&#039;bowcontrolharmonicshift&amp;quot; / &amp;quot;harmonicseries.shift&amp;quot;-&#039;&#039;command&#039;&#039; shifts the frequency of the &#039;&#039;bowing wheel&#039;&#039; from the currently selected harmonic. The first (and only) &#039;&#039;parameter&#039;&#039; sets how much we want to shift it (the range depends on the &amp;quot;bowcontrolharmonicshiftrange&#039;&#039;&amp;quot;&#039;&#039; / &amp;quot;harmonicseries.shiftrange&amp;quot;-&#039;&#039;command&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
If we look in the list of &#039;&#039;[[The Ekdahl FAR - Command langue#Variables|variables]]&#039;&#039; above we can see that the &#039;&#039;pitch bend MIDI message&#039;&#039; will set the &amp;quot;pitch&amp;quot;&#039;&#039;-variable&#039;&#039; which is indeed used. Now what is the &#039;&#039;&#039;*4&#039;&#039;&amp;lt;nowiki/&amp;gt;&#039; all about? Well the &amp;quot;bowcontrolharmonicshift&amp;quot; / &amp;quot;harmoniceseries.shift&amp;quot;-&#039;&#039;command&#039;&#039; expects a &#039;&#039;16-bit signed&#039;&#039; value as its &#039;&#039;parameter&#039;&#039;. This means that the valid &#039;&#039;parameter&#039;&#039; number can be anything from -32767 to 32767. A full &#039;&#039;harmonic shift&#039;&#039; downwards according to the range set is equal to -32767, a full &#039;&#039;harmonic shift&#039;&#039; upwards is 32767 and no &#039;&#039;harmonic shift&#039;&#039; is 0. The &#039;&#039;pitch bend MIDI message&#039;&#039; however is only 14-bits, meaning its range is -8192 to 8192. So we have to multiply &#039;&#039;pitch&#039;&#039; by 4 in order to meet the requirements of a &#039;&#039;16-bit signed parameter&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
This whole thing about number of bits can seem confusing but in the end it&#039;s all about how fine control you have over things; the more possible values, the more detailed control. In fact, most &#039;&#039;MIDI&#039;&#039; values are only 7-bit (!) meaning a range of 0 - 127. While this may sound like a lot of detail for something like a volume control, it is not even close to enough resolution to for instance set the &#039;&#039;bowing frequency&#039;&#039;. Even if you would limit yourself to a single octave the instrument would never be able to be properly in tune. The idea of limiting the Ekdahl FAR to what is possible through &#039;&#039;MIDI&#039;&#039; seemed like a poor choice thus it was decided that &amp;lt;u&amp;gt;most&amp;lt;/u&amp;gt; parameters will instead be 16-bit.&lt;br /&gt;
&lt;br /&gt;
Now lets look at a more complex example, the &amp;lt;u&amp;gt;default&amp;lt;/u&amp;gt; &#039;&#039;Note On MIDI message&#039;&#039;. On a stock Ekdahl FAR, executing&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
rqi:mev:noteon&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
rqi:mcf.mf.non&lt;br /&gt;
&amp;lt;/pre&amp;gt;Will return something like&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
[irq]mev:noteon:&#039;bchb:note,bmr:1,bpid:1,bpe:1,se:(velocity*512)*(1-notecount),bcsm:0&#039;&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
[irq]mcf[0].mc[0].non:&#039;bw.hsh.hb:note,bw.dcm.ru:1,bw.pe:1,bw.bp.en:1,so.en:(velocity*512)*(1-notecount),bw.sm:0&#039;&amp;lt;/pre&amp;gt;As can be seen, there&#039;s a lot of stuff going on here! First of all, notice that everything after &amp;quot;mev:noteon:&amp;quot; / &amp;quot;mcf[0].mc[0].non:&amp;quot; is situated in between single quotes (&#039;) - this is &amp;lt;u&amp;gt;absolutely crucial&amp;lt;/u&amp;gt; for the Ekdahl FAR in order to know that everything within those last two quotes is part of the last &#039;&#039;parameter&#039;&#039; of the &amp;quot;mev&amp;quot; / &amp;quot;mcf.mc.non&amp;quot;-&#039;&#039;command&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Now let&#039;s break down what happens when this &#039;&#039;MIDI message&#039;&#039; is received, i.e. when a &#039;&#039;MIDI&#039;&#039; key is pressed down:&lt;br /&gt;
&lt;br /&gt;
# &amp;quot;bchb:note&amp;quot; / &amp;quot;bw.hsh.hb:note&amp;quot;  - Invokes the &amp;quot;bowcontrolharmonicbase&amp;quot; / &amp;quot;harmonicserieshandler.harmonicbase&amp;quot;&#039;&#039;-command&#039;&#039; with the first &#039;&#039;parameter&#039;&#039; set to the &#039;&#039;variable &amp;quot;&#039;&#039;note&amp;quot;. This sets the &#039;&#039;base harmonic&#039;&#039; that the Ekdahl FARs &#039;&#039;bowing motor&#039;&#039; should be set to. Here the &#039;&#039;variable&#039;&#039; &amp;quot;note&amp;quot; is used which is simply the MIDI key being pressed down, it is automatically converted by the &#039;&#039;command&#039;&#039; to the corresponding harmonic in the &#039;&#039;harmonic list&#039;&#039;&lt;br /&gt;
# &amp;quot;bmr:1&amp;quot; / &amp;quot;bw.dcm.ru&amp;quot; - Sets the &amp;quot;bowmotorrun&amp;quot; / &amp;quot;dcmotor.run&amp;quot;-command to &#039;1&#039;, starting the &#039;&#039;bow motor&#039;&#039;&lt;br /&gt;
# &amp;quot;bpid:1&amp;quot; / &amp;quot;bw.pe:1&amp;quot; - Sets the &amp;quot;bowpid&amp;quot; / &amp;quot;bowingwheel.pidenable&amp;quot;-&#039;&#039;command&#039;&#039; to &#039;1&#039;. Basically this enables the function that makes the Ekdahl FAR able to keep a stable frequency on the &#039;&#039;bowing motor&#039;&#039;.&lt;br /&gt;
# &amp;quot;bpe:1&amp;quot; / &amp;quot;bw.bp.en&amp;quot; - Sets the &amp;quot;bowpressureengage&amp;quot; / &amp;quot;bowpressure.engage&amp;quot;-&#039;&#039;command&#039;&#039; to &#039;1&#039; which moves the &#039;&#039;bowing jack&#039;&#039; to the &#039;&#039;engage position&#039;&#039;, aka just below the string if not additional &#039;&#039;pressure&#039;&#039; is applied&lt;br /&gt;
# &amp;quot;se:(velocity*512)*(1-notecount)&amp;quot; / &amp;quot;so.en:(velocity*512)*(1-notecount)&amp;quot; - Executes the &amp;quot;solenoidengage&amp;quot; / &amp;quot;solenoid.engage&amp;quot;-&#039;&#039;command&#039;&#039; with the value &#039;&#039;(velocity*512)*(1-notecount)&#039;&#039;. This will make the &#039;&#039;solenoid&#039;&#039; strike the &#039;&#039;hammer&#039;&#039; with a force that is dependent on the &amp;quot;velocity&amp;quot;-&#039;&#039;variable&#039;&#039; sent by the &#039;&#039;Note On MIDI message&#039;&#039; in order to make the &#039;&#039;hammer&#039;&#039; velocity sensitive.   But it also adds the somewhat perplexing part &amp;quot;*(1-notecount)&amp;quot;. &amp;quot;notecount&amp;quot; is a global &#039;&#039;variable&#039;&#039; that contains the number of MIDI keys that are currently being held down. If &amp;quot;notecount&amp;quot; is anything above zero, the outcome of the equation will either be zero or a negative number. The &amp;quot;solenoidengage&amp;quot; / &amp;quot;solenoid.engage&amp;quot;-&#039;&#039;command&#039;&#039; requires a &#039;&#039;16-bit unsigned&#039;&#039; value, aka the only valid numbers are 0 - 65535. Anything below 0 will be interpreted as zero, so what this equation does is that it only fires off the &#039;&#039;hammer&#039;&#039; if there are no previous keys being held down - it&#039;s being used in &#039;&#039;staccato&#039;&#039;  mode.&lt;br /&gt;
# &amp;quot;bcsm:0&amp;quot; / &amp;quot;bowingwheel.speedmode&amp;quot; - Sets the &amp;quot;bowcontrolspeedmode&amp;quot; / &amp;quot;bowingwheel.speedmode&amp;quot; to &#039;1&#039; which enables automatic shut down of the &#039;&#039;bowing motor&#039;&#039; after a given timeout.&lt;br /&gt;
Let&#039;s postulate that the Ekdahl FAR is tuned to a &#039;C&#039; at 65.4Hz and has its &#039;&#039;base&#039;&#039; set to middle &#039;C&#039; (&#039;&#039;MIDI key&#039;&#039; no 36). We are using the equal-temperament 12-tone scale and the Ekdahl FAR is set to respond to &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; &#039;&#039;MIDI channels&#039;&#039; (omni). Without having previously held any keys we press the middle &#039;C&#039; (&#039;&#039;note&#039;&#039; value 36) as hard as possible (&#039;&#039;velocity&#039;&#039; value &#039;&#039;127&#039;&#039;) on &#039;&#039;MIDI channel&#039;&#039; number 1 (&#039;&#039;channel&#039;&#039; value of 0). The Ekdahl FAR will get a &#039;&#039;note on MIDI message&#039;&#039; sent to it and from our mapping it will create the following &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
[irq]mev:noteon:&#039;bchb:36,bmr:1,bpid:1,bpe:1,se:(127*512)*(1-0),bcsm:0&#039;&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
[irq]mcf[0].mc[0].non:&#039;bw.hsh.hb:36,bw.dcm.ru:1,bw.pe:1,bw.bp.en:1,so.en:(127*512)*(1-0),bw.sm:0&#039;&amp;lt;/pre&amp;gt;What has happened here is that all &#039;&#039;variables&#039;&#039; have been replaced with the values sent by the &#039;&#039;MIDI message&#039;&#039;. Since those &#039;&#039;commands&#039;&#039; that doesn&#039;t have any &#039;&#039;variables&#039;&#039; with them will execute just as previously, only those &#039;&#039;commands&#039;&#039; whos &#039;&#039;parameters&#039;&#039; have changed will be explained:&lt;br /&gt;
&lt;br /&gt;
# &amp;quot;bchb: 36&amp;quot; / &amp;quot;bw.hsh.hb:36&amp;quot; - The &amp;quot;bowcontrolharmonicbase&amp;quot; / &amp;quot;harmonicserieshandler.harmonicbase&amp;quot; gets a value of &#039;&#039;36&#039;&#039; (middle &#039;C&#039;), because &#039;&#039;harmonic number 0&#039;&#039; is mapped to this key it will set the &#039;&#039;bowing wheel&#039;&#039; frequency to the &#039;&#039;fundamental&#039;&#039;; &#039;&#039;65.4&#039;&#039; Hertz&lt;br /&gt;
# &amp;quot;se: (127*512)*(1-0)&amp;quot; / &amp;quot;so.en: (127*512)*(1-0)&amp;quot; - the value of &#039;&#039;127&#039;&#039; comes from the &amp;quot;velocity&amp;quot;-&#039;&#039;variable&#039;&#039;, &#039;&#039;127 * 512 = 65024&#039;&#039; which is awfully close to a maximum hammer force of 65535. Since no previous notes were held down, the &#039;&#039;&amp;quot;&#039;&#039;notecount&amp;quot;-&#039;&#039;variable&#039;&#039;  is equal to &#039;&#039;0&#039;&#039; and thus &#039;&#039;65024 * 1 = 65024&#039;&#039;. The hammer is engaged with near maximum force.&lt;br /&gt;
So the result is that we have set the speed of the &#039;&#039;bowing motor&#039;&#039; and we have engaged the &#039;&#039;hammer&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Now imagine that without releasing this key, we press another &#039;C&#039; one octave above but at half the velocity. The Ekdahl FAR creates the following &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
[irq]mev:noteon:&#039;bchb:48,bmr:1,bpid:1,bpe:1,se:(63*512)*(1-1),bcsm:0&#039;&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
[irq]mcf[0].mc[0].non:&#039;bw.hsh.hb:48,bw.dcm.ru:1,bw.pe:1,bw.bp.en:1,so.en:(65*512)*(1-1),bw.sm:0&#039;&lt;br /&gt;
&amp;lt;/pre&amp;gt;Now we can see that the &amp;quot;note&amp;quot;-&#039;&#039;variable&#039;&#039; is 48 because the &#039;C&#039; one octave up is exactly 12 keys above the first. The &amp;quot;velocity&amp;quot;-&#039;&#039;variable&#039;&#039; has changed to 63 since we hit it with a lighter touch - and because we are &amp;lt;u&amp;gt;still holding the first key down&amp;lt;/u&amp;gt;, the &amp;quot;notecount&amp;quot;-&#039;&#039;variable&#039;&#039; is equal to &#039;&#039;1&#039;&#039;. Here&#039;s what happens&lt;br /&gt;
&lt;br /&gt;
# &amp;quot;bchb: 48&amp;quot; / &amp;quot;hsh.hb:48&amp;quot; - Due to the &#039;&#039;base&#039;&#039; being set to &#039;&#039;36&#039;&#039; the &#039;&#039;harmonic number&#039;&#039; is set to &#039;&#039;48 - 36 = 12&#039;&#039;. Because we are using a 12-tone scale &#039;&#039;harmonic number 12&#039;&#039; is exactly one octave above the &#039;&#039;fundamental&#039;&#039; thus the speed of the &#039;&#039;bowing wheel&#039;&#039; is set to &#039;&#039;65.4 * 2 = 130.8&#039;&#039; Hertz.&lt;br /&gt;
# &amp;quot;se: (63*512)*(1-1)&amp;quot; / &amp;quot;so.en: (63*512)*(1-1)&amp;quot; - The equation evalutes as &#039;&#039;63 * 512 = 32256&#039;&#039; and &#039;&#039;1 - 1 = 0&#039;&#039; thus &#039;&#039;32256 * 0 = 0&#039;&#039;. When the &amp;quot;solenoidengage&amp;quot; / &amp;quot;solenoid.engage&amp;quot;-&#039;&#039;command&#039;&#039; gets a &#039;&#039;parameter&#039;&#039; of &#039;&#039;0&#039;&#039; it will not engage the &#039;&#039;hammer&#039;&#039; - so the &#039;&#039;hammer&#039;&#039; doesn&#039;t strike&lt;br /&gt;
So it can be seen that with quite rudimentary math we can accomplish a whole lot of things here. Note also that even though the &#039;&#039;note on MIDI message&#039;&#039; also sets the &#039;&#039;channel&#039;&#039;-variable we never use it in this example - plenty of opportunity to make something weird happen depending on the &#039;&#039;MIDI channel&#039;&#039;!&lt;br /&gt;
&lt;br /&gt;
== CV Mapping ==&lt;br /&gt;
&#039;&#039;CV Mapping&#039;&#039; works exactly like the &#039;&#039;MIDI mapping&#039;&#039; with the difference that the command(s) for setting the &#039;&#039;CV mapping&#039;&#039; is different and that they all modify (and thus share) the &amp;quot;value&amp;quot;-&#039;&#039;variable&#039;&#039;. These &#039;&#039;events&#039;&#039; are triggered whenever the analog-to-digital converter senses a change in a control or modulation jack, if you use something like an LFO with the modulation jacks here you will get a LOT of events and subsequent &#039;&#039;commands&#039;&#039; being sent.  &lt;br /&gt;
 &#039;&#039;&#039;FAR &amp;lt; 1.1:&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 The command for changing the CV mapping is &amp;quot;adccommandmap&amp;quot; or &amp;quot;acm&amp;quot;, it take two parameters; channel and command string. The channels on the original Edkahl FAR Control box are as &lt;br /&gt;
 &lt;br /&gt;
 * 0 - The &amp;quot;Harmonic&amp;quot; knob and jack&lt;br /&gt;
 * 1 - The &amp;quot;Harmonic shift&amp;quot; knob and jack&lt;br /&gt;
 * 2 - The &amp;quot;Fine tune&amp;quot; knob&lt;br /&gt;
 * 3 - The &amp;quot;Pressure&amp;quot; knob and jack&lt;br /&gt;
 * 4 - The &amp;quot;Hammertrig&amp;quot; button and jack&lt;br /&gt;
 * 5 - The &amp;quot;Gate&amp;quot; switch and jack&lt;br /&gt;
 * 6 - The &amp;quot;Hammer Scale&amp;quot; knob&lt;br /&gt;
 * 7 - The &amp;quot;Mute&amp;quot; knob and jack&lt;br /&gt;
 &lt;br /&gt;
 &#039;&#039;&#039;FAR 1.1:&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 The commands responsible for changing the CV mapping are located in the &amp;quot;controlbox&amp;quot;-module, these are&lt;br /&gt;
 &lt;br /&gt;
 * &#039;&#039;&#039;harmonic&#039;&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed when the &amp;quot;Harmonic&amp;quot;-knob or modulation changes&lt;br /&gt;
 * &#039;&#039;&#039;harmonicshift&#039;&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed when the &amp;quot;Harmonic shift&amp;quot;-knob or modulation changes&lt;br /&gt;
 * &#039;&#039;&#039;finetune&#039;&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed when the &amp;quot;Fine tune&amp;quot;-knob changes&lt;br /&gt;
 * &#039;&#039;&#039;pressure&#039;&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed when the &amp;quot;Pressure&amp;quot;-knob or modulation changes&lt;br /&gt;
 * &#039;&#039;&#039;mute&#039;&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed when the &amp;quot;Mute&amp;quot;-knob or modulation changes&lt;br /&gt;
 * &#039;&#039;&#039;hammerscale&#039;&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed when the &amp;quot;Hammer scale&amp;quot;-knob changes&lt;br /&gt;
 * &#039;&#039;&#039;gate&#039;&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed when the &amp;quot;Gate&amp;quot;-switch or modulation changes&lt;br /&gt;
 * &#039;&#039;&#039;hammertrig&#039;&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed when the &amp;quot;Hammer Trig&amp;quot;-button or modulation changes&lt;br /&gt;
In order to set/retrieve &#039;&#039;mapping data&#039;&#039; we just use a regular &amp;quot;rqi&amp;quot;-&#039;&#039;command&#039;&#039;. To for instance get the &#039;&#039;command string&#039;&#039; executed when the &amp;quot;harmonic&amp;quot; knob or modulation is sent we can do the following&lt;br /&gt;
 &#039;&#039;&#039;FAR &amp;lt; 1.1:&#039;&#039;&#039;&lt;br /&gt;
 [send] rqi:acm:0&lt;br /&gt;
 [returns] [irq]acm:0:&#039;bcha:value/1327.716667-20&#039;&lt;br /&gt;
 &lt;br /&gt;
 &#039;&#039;&#039;FAR 1.1:&#039;&#039;&#039;&lt;br /&gt;
 [send] rqi:controlbox.harmonic&lt;br /&gt;
 [returns] [irq]cb[0].har:&#039;bw.hsh.ha:value/1327.716667-20&#039;&lt;br /&gt;
What is returned is the &#039;&#039;command&#039;&#039; to set the &#039;&#039;harmonic&#039;&#039; with a &#039;&#039;parameter&#039;&#039; of  &amp;quot;value/1327.71667-20&amp;quot;&lt;br /&gt;
We retrieve the &#039;&#039;command string&#039;&#039; for channel &#039;&#039;0&#039;&#039; which reads the sum of the &#039;&#039;harm. v/oct&#039;&#039;-jack and the &#039;&#039;harmonic&#039;&#039;-knob by sending a command of&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;u&amp;gt;default&amp;lt;/u&amp;gt; response will be something like&lt;br /&gt;
 &lt;br /&gt;
{{docnav&lt;br /&gt;
|[[The Ekdahl FAR - Service|Service]]&lt;br /&gt;
|[[The Ekdahl FAR - Command reference|Command reference]]&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Knaadmin</name></author>
	</entry>
	<entry>
		<id>http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_language&amp;diff=1657</id>
		<title>The Ekdahl FAR - Command language</title>
		<link rel="alternate" type="text/html" href="http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_language&amp;diff=1657"/>
		<updated>2026-06-12T09:37:55Z</updated>

		<summary type="html">&lt;p&gt;Knaadmin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Command language ==&lt;br /&gt;
The Ekdahl FAR is entirely controlled by &#039;&#039;commands&#039;&#039;, these &#039;&#039;commands&#039;&#039; decide everything that the instrument is doing, whether it is playing a melody or changing an internal parameter. &lt;br /&gt;
&lt;br /&gt;
When a &#039;&#039;MIDI message&#039;&#039; is received or a new CV / knob value is read, the &#039;&#039;commands&#039;&#039; associated with it will be internally sent. This can be things like &amp;quot;engage hammer&amp;quot; or &amp;quot;set the fundamental frequency&amp;quot; etc. &lt;br /&gt;
&lt;br /&gt;
Some of the available &#039;&#039;commands&#039;&#039; are mainly used for calibrating and setting up the instrument and are usually saved into the instruments memory, these will be executed whenever the instrument is turned on. &lt;br /&gt;
&lt;br /&gt;
All &#039;&#039;commands&#039;&#039; can be manually invoked via &#039;&#039;USB-Serial&#039;&#039;, in conjunction with certain software this presents an unprecedented level of control and sequenceability.&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
The &#039;&#039;commands&#039;&#039; are invoked using a &#039;&#039;plain text approach&#039;&#039;, all commands have both a &#039;&#039;long name&#039;&#039; and a &#039;&#039;short name&#039;&#039; which are interchangeable. A &#039;&#039;command&#039;&#039; may have one or more &#039;&#039;parameters&#039;&#039; associated with it, these &#039;&#039;parameters&#039;&#039; can be of different types; 16-bit numbers (values 0 - 65535 or -32767 - 32767), floating point numbers (values with decimals), booleans (0 for &#039;false&#039;, 1 for &#039;true&#039;) and strings (text). Some commands are &#039;&#039;conditional&#039;&#039;, meaning they will only execute if a parameter equates to &#039;1&#039; (&#039;true&#039;). &lt;br /&gt;
&lt;br /&gt;
The way &#039;&#039;commands&#039;&#039; are written in order to be executed is &#039;&#039;commandname:parameter1:parameter2:parameter3 [etc]&#039;&#039;, several commands be executed in sequence by separating them with a comma (&#039;,&#039;), a bunch of commands strung together is called a &#039;&#039;command string&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Since version 1.1 of the Ekdahl FAR Firmware, all commands are grouped in a hierarchical fashion according to their &#039;&#039;modules&#039;&#039; and each ladder in the hierarchy is separated by a period (&amp;quot;.&amp;quot;), this works very much like folders or directories in a regular computer. Every &#039;&#039;module&#039;&#039; can contain both &#039;&#039;commands&#039;&#039; and other &#039;&#039;modules&#039;&#039;. For instance, everything associated with the &#039;&#039;bowing wheel&#039;&#039; is now collected under &amp;quot;bowingwheel&amp;quot; &#039;&#039;module&#039;&#039;. That in turn contains a &amp;quot;dcmotor&amp;quot; &#039;&#039;module&#039;&#039; which handles direct control of the bowing motor. It also has a &amp;quot;pid&amp;quot; &#039;&#039;module&#039;&#039; that handles bow frequency among other thing. &lt;br /&gt;
&lt;br /&gt;
If for instance we would like to start the &#039;&#039;bowing wheel&#039;&#039; and set its frequency to 82.5 Hertz we could send the Ekdahl FAR the following &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
bowmotorrun:1, bowcontrolfrequecy:82.5&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bowingwheel.dcmotor.run:1, bowingwheel.pid.targetfrequency:82.5&amp;lt;/pre&amp;gt;We could also use the &#039;&#039;short names&#039;&#039; for the commands&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
bmr:1,bcf:82.5&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bw.dcm.ru:1, bw.pid.tf:82.5&amp;lt;/pre&amp;gt;Both &amp;quot;bowmotorrun&amp;quot; / &amp;quot;bowingwheel.dcmotor.run&amp;quot; and &amp;quot;bowcontrolfrequency&amp;quot; / &amp;quot;bowingwheel.pid.targetfrequency&amp;quot; takes one &#039;&#039;parameter&#039;&#039; each, &#039;&#039;&amp;quot;&#039;&#039;bowmotorrun&amp;quot; / &amp;quot;bowingwheel.dcmotor.run&amp;quot; is &#039;&#039;conditional&#039;&#039; and unless the first &#039;&#039;parameter&#039;&#039; is equal to &#039;1&#039; the motor will not start. The first &#039;&#039;parameter&#039;&#039; of &amp;quot;bowcontrolfrequency&amp;quot; / &amp;quot;bowingwheel.pid.targetfrequency&amp;quot; sets the frequency of the &#039;&#039;bowing wheel&#039;&#039;, the instrument may not execute a &#039;&#039;command&#039;&#039; if it decides that the given &#039;&#039;parameters&#039;&#039; are outside of the working range or they are missing.&lt;br /&gt;
&lt;br /&gt;
The addition of the hierarchy in the FAR 1.1 firmware isn&#039;t just to be able to group commands, but it&#039;s also to make the FAR not limited to a single set of &#039;&#039;modules&#039;&#039; (and is the first stepping stone to a &#039;&#039;modular&#039;&#039; Ekdahl FAR). In fact, you could have 12 different bowing wheel &#039;&#039;modules&#039;&#039; for 12 different strings, these would then be addressed as &amp;quot;bowingwheel[0].command&amp;quot;&#039;&#039;, &amp;quot;&#039;&#039;bowingwheel[1].command&amp;quot; etc. Anyone familiar with C programming notices that this is the standard way of &#039;&#039;indexing&#039;&#039; an array; using brackets (&amp;quot;[ ]&amp;quot;). When addressing a module without &#039;&#039;indexing&#039;&#039; as in the example above, the FAR will do one or two things; either use the first object (&amp;quot;[0]&amp;quot;) or, if the object is &#039;&#039;selectable&#039;&#039; it will use the previously selected object. To make things smoother a command can be executed on several objects at once by using ranges (&amp;quot;[0-4]&amp;quot;) and comma separation (&amp;quot;[0, 3, 5-6]&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
To test out a &#039;&#039;command&#039;&#039; you can send it directly to the Ekdahl FAR using the &#039;&#039;Console&#039;&#039; in the &#039;&#039;Configuration utility&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
To read up on existing &#039;&#039;commands&#039;&#039;, their &#039;&#039;parameters&#039;&#039; and a brief description you can check the &#039;&#039;Command reference&#039;&#039; in the &#039;&#039;Configuration utility&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Variables, functions and equations ==&lt;br /&gt;
What makes the &#039;&#039;Command language&#039;&#039; truly powerful is the concept of &#039;&#039;variables, functions&#039;&#039; and &#039;&#039;equations&#039;&#039;. All &#039;&#039;parameters&#039;&#039; that take numerical values can use any combination of &#039;&#039;variables, functions&#039;&#039; or &#039;&#039;equations.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
For instance, we can use the previous example and instead write our &#039;&#039;command string&#039;&#039; as follows&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
bowmotorrun:1, bowcontrolfrequency:82.5+note*20&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bowingwheel.dcmotor.run:1, bowingwheel.pid.targetfrequency:82.5+note*20&amp;lt;/pre&amp;gt;This example requires of course that the &#039;&#039;variable&#039;&#039; &#039;&#039;note&#039;&#039; exists in the current context. &lt;br /&gt;
&lt;br /&gt;
===== Variables =====&lt;br /&gt;
There are two types of &#039;&#039;variables&#039;&#039; in the Ekdahl FAR; &#039;&#039;global variables&#039;&#039; and &#039;&#039;event variables&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Global variables&#039;&#039; are variables that are always valid, in any context. The &#039;&#039;global variables&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;notecount&#039;&#039;&#039; - Contains the number of &#039;&#039;MIDI&#039;&#039; keys that are being held down, i.e. all &#039;&#039;Note on messages&#039;&#039; received that haven&#039;t gotten a paired &#039;&#039;Note off message&#039;&#039; yet&lt;br /&gt;
* &#039;&#039;&#039;uv0&#039;&#039;&#039; - &#039;&#039;&#039;uv9&#039;&#039;&#039; - These are &#039;&#039;user variables&#039;&#039; and can be set at any point using the &#039;&#039;globaluservariable command&#039;&#039; with the first &#039;&#039;parameter&#039;&#039; being which variable to set (0-9) and the second &#039;&#039;parameter&#039;&#039; being the value (float).&lt;br /&gt;
* &#039;&#039;&#039;e&#039;&#039;&#039; - Contains the constant &#039;&#039;[[wikipedia:E_(mathematical_constant)|e]]&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pi&#039;&#039;&#039; - Contains the constant &#039;&#039;[[wikipedia:Pi|pi]]&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Event variables&#039;&#039; are variables that are set by certain &#039;&#039;MIDI messages&#039;&#039; or when a new value is read on one of the jacks or knobs on the &#039;&#039;Control box&#039;&#039;. The &#039;&#039;Event variables&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;channel&#039;&#039;&#039; - Set by the &#039;&#039;Note on, Note off, Continuous Controller, Poly after touch, Pitch bend, Channel after touch&#039;&#039; and &#039;&#039;Program change MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;note&#039;&#039;&#039; - Set by the &#039;&#039;Note on, Note off&#039;&#039; and &#039;&#039;Poly after touch MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;velocity&#039;&#039;&#039; - Set by the &#039;&#039;Note on&#039;&#039; and &#039;&#039;Note off MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pressure&#039;&#039;&#039; - Set by the &#039;&#039;Poly after touch&#039;&#039; and &#039;&#039;Channel after touch MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; - Set by the &#039;&#039;Continuous Controller MIDI message&#039;&#039; and by the &#039;&#039;Control box&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pitch&#039;&#039;&#039; - Set by the &#039;&#039;Pitch bend MIDI message&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;program&#039;&#039;&#039; - Set by the &#039;&#039;Program change MIDI message&#039;&#039;&lt;br /&gt;
These variables will contain whatever data is relevant to the last event that occurred and may be overwritten by the next event.&lt;br /&gt;
&lt;br /&gt;
===== Functions =====&lt;br /&gt;
&#039;&#039;Functions&#039;&#039; can be used to change a numerical value or the result of an &#039;&#039;equation&#039;&#039;, the Ekdahl FAR contains both general &#039;&#039;arithmetic functions&#039;&#039; (courtesy of Lewis Van Winkle and the TINYEXPR engine) and &#039;&#039;specialized functions&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;arithmetic functions&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;abs&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Absolute_value|absolute value]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;acos&#039;&#039;&#039;(x), &#039;&#039;&#039;asin&#039;&#039;&#039;(x), &#039;&#039;&#039;atan&#039;&#039;&#039;(x), atan2(x, y) - Returns the [[wikipedia:Inverse_trigonometric_functions|&#039;&#039;arc-cos, -sin, -tan&#039;&#039; and &#039;&#039;-tan2&#039;&#039;]] of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;atan2&#039;&#039;&#039;(x,y) - Returns the &#039;&#039;[[wikipedia:Atan2|arctan2]]&#039;&#039; of &#039;&#039;x, y&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;floor&#039;&#039;&#039;(x), ceil(x) - Returns the [[wikipedia:Floor_and_ceiling_functions|&#039;&#039;floor&#039;&#039; and &#039;&#039;ceiling&#039;&#039;]] of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;exp&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Exponential_function|exponent]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;fac&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Factorial|factorial]]&#039;&#039; of x&lt;br /&gt;
* &#039;&#039;&#039;ln&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Natural_logarithm|natural logarithm]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;log10&#039;&#039;&#039;(x), &#039;&#039;&#039;log20&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Logarithm|logarithm]]&#039;&#039; of &#039;&#039;x&#039;&#039; using base 10 and 20 respectively&lt;br /&gt;
* &#039;&#039;&#039;ncr&#039;&#039;&#039;(x,y), &#039;&#039;&#039;npr&#039;&#039;&#039;(x,y) - Functions to calculate &#039;&#039;[[wikipedia:Combination|combinations]]&#039;&#039; and &#039;&#039;[[wikipedia:Permutation|permutations]]&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pow&#039;&#039;&#039;(x,y) - Returns &#039;&#039;x^y&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;sqrt&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Square_root|square root]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;cos&#039;&#039;&#039;(x), &#039;&#039;&#039;sin&#039;&#039;&#039;(x), &#039;&#039;&#039;tan&#039;&#039;&#039;(x) - Returns the [[wikipedia:Trigonometric_functions|&#039;&#039;cos, sin&#039;&#039; and &#039;&#039;tan&#039;&#039;]] of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;cosh&#039;&#039;&#039;(x), &#039;&#039;&#039;sinh&#039;&#039;&#039;(x), &#039;&#039;&#039;tanh&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Hyperbolic_functions|hyperbolic cos, sin and tan]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
The &#039;&#039;specialized functions&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;bool&#039;&#039;&#039;(x) - Returns 1 if &#039;&#039;x&#039;&#039; is more than 0&lt;br /&gt;
* &#039;&#039;&#039;ibool&#039;&#039;&#039;(x) - Returns 0 if &#039;&#039;x&#039;&#039; is more than 0&lt;br /&gt;
* &#039;&#039;&#039;deadband&#039;&#039;&#039;(x,y) - Returns &#039;&#039;x + y &#039;&#039; if &#039;&#039;x &amp;lt; y&#039;&#039; or &#039;&#039;x - y&#039;&#039; if &#039;&#039;x &amp;gt; y&#039;&#039;. If neither of these statements is true it returns &#039;&#039;0&#039;&#039; - used to create a [[wikipedia:Deadband|deadband]] of &#039;&#039;x&#039;&#039; with the threshold of &#039;&#039;y&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Functions&#039;&#039; can be readily used in a &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
bowmotorrun:1, bowcontrolfrequency:&amp;quot;8.17579875 * pow(2, (1/12 * note))&amp;quot;&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bowingwheel.dcmotor.run:1, bowingwheel.pid.targetfrequency:&amp;quot;8.17579875 * pow(2, (1/12 * note))&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;The previous statements starts the &#039;&#039;bowing wheel&#039;&#039; and sets the frequency of the wheel to &#039;&#039;8.17579875 * 2^(1/12 * note)&#039;&#039;. A middle &#039;C&#039; according to &#039;&#039;MIDI&#039;&#039; has a &#039;&#039;note value&#039;&#039; of 36, meaning if we substitute &#039;&#039;note&#039;&#039; with 36 we get the equation &#039;&#039;8.17579875 * 2^(1/12 * 36)&#039;&#039; which comes out to &#039;&#039;~65.4&#039;&#039; Hertz.&lt;br /&gt;
&lt;br /&gt;
Note that the first &#039;&#039;parameter&#039;&#039; for &#039;&#039;&amp;quot;&#039;&#039;bowcontrolfrequency&amp;quot; / &amp;quot;bowingwheel.pid.targetfrequency&amp;quot; is put in between double quotes (&amp;quot;). This is because the &amp;quot;pow&#039;&#039;&amp;quot;-&#039;&#039;function requires the use of a comma (&amp;quot;,&amp;quot;) in order to separate in between its two required inputs; &#039;&#039;x&#039;&#039; and &#039;&#039;y&#039;&#039;. In order for the Ekdahl FAR to know that this comma does not signal the beginning of a new &#039;&#039;command,&#039;&#039; we use quotes. Single (&#039;) and double (&amp;quot;) quotes can be used and nested in all &#039;&#039;parameters&#039;&#039; and are &amp;lt;u&amp;gt;required&amp;lt;/u&amp;gt; in a lot of circumstances, improper nesting or not using quotes can lead to the instrument not understanding the &#039;&#039;command string&#039;&#039; correctly.&lt;br /&gt;
&lt;br /&gt;
== Return messages ==&lt;br /&gt;
The Ekdahl FAR when connected via &#039;&#039;USB-Serial&#039;&#039; doesn&#039;t only accept &#039;&#039;commands&#039;&#039; but will also send various &#039;&#039;return messages&#039;&#039;. These are prefixed by their &#039;&#039;category&#039;&#039; denoted in brackets (&amp;quot;[]&amp;quot;), the existing categories as of this writing (2025-01-22) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;command&#039;&#039;&#039; / &#039;&#039;&#039;cmd&#039;&#039;&#039; - Acknowledges the reception of a command in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;usb&#039;&#039;&#039; - Acknowledges the reception of a &#039;&#039;MIDI message&#039;&#039; over &#039;&#039;USB&#039;&#039; in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;hardware&#039;&#039;&#039; / &#039;&#039;&#039;hw&#039;&#039;&#039; - Signals that a change has been sent to the Ekdahl FAR hardware, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;undefined&#039;&#039;&#039; / &#039;&#039;&#039;un&#039;&#039;&#039; - The message sent is in the &#039;&#039;undefined&#039;&#039; category, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;priority&#039;&#039;&#039; / &#039;&#039;&#039;pri&#039;&#039;&#039; - The message sent is in the &#039;&#039;priority&#039;&#039; category, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;error&#039;&#039;&#039; / &#039;&#039;&#039;err&#039;&#039;&#039; - Signals that an &#039;&#039;error&#039;&#039; has occurred, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;expressionparser&#039;&#039;&#039; / &#039;&#039;&#039;ep&#039;&#039;&#039; - These messages contains debugging information regarding the internal &#039;&#039;expression parser&#039;&#039; and is used for development&lt;br /&gt;
*&#039;&#039;&#039;debug&#039;&#039;&#039; / &#039;&#039;&#039;dbg&#039;&#039;&#039; - These messages contains various debugging information and is used for development&lt;br /&gt;
*&#039;&#039;&#039;help&#039;&#039;&#039; / &#039;&#039;&#039;hlp&#039;&#039;&#039; - Signals that the message is a response to a &#039;&#039;help&#039;&#039;-command being sent to the Ekdahl FAR. These messages are structured so that a receiver, like the &#039;&#039;Configuration utility&#039;&#039;, can parse information about available &#039;&#039;commands&#039;&#039; in the current &#039;&#039;firmware&#039;&#039; and relay it to a user in a structured way.&lt;br /&gt;
* &#039;&#039;&#039;inforequest&#039;&#039;&#039; / &#039;&#039;&#039;irq&#039;&#039;&#039; - Signals that an &#039;&#039;info request&#039;&#039; has been returned. This is a specialized message that is either sent as a response to an &#039;&#039;rqi&#039;&#039;-command or as a &#039;&#039;interrupt&#039;&#039;-message telling the user or receiving software about different parameters in the Ekdahl FAR. These messages follows the same structure as regular &#039;&#039;command message&#039;&#039;s of &#039;&#039;[irq]commandname:parameter1 [etc]&#039;&#039; so that it can be used by a receiving software to keep track of parameter changes&lt;br /&gt;
&lt;br /&gt;
===== Explicitly requesting information =====&lt;br /&gt;
By using the special command &amp;quot;requestinfo&amp;quot; / &amp;quot;rqi&amp;quot; one can request the information stored by a certain &#039;&#039;command&#039;&#039; or a state of the Ekdahl FAR. The &amp;quot;rqi&amp;quot;-command is executed in the convention &amp;quot;rqi:commandname:optional parameters&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
To go back to our example of setting the bowing frequency using the &#039;&#039;&amp;quot;&#039;&#039;bowcontrolfrequency&amp;quot; / &amp;quot;bowingwheel.pid.targetfrequency&amp;quot;-command we can ask the Ekdahl FAR what the bowing frequency is set to by writing&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
rqi:bowcontrolfrequency&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
rqi:bowingwheel.pid.targetfrequency&lt;br /&gt;
&amp;lt;/pre&amp;gt;The return value would be something like&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
[irq]bcf:82.5&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
[irq]bw[0].pid[0].tf:82.5&lt;br /&gt;
&amp;lt;/pre&amp;gt;Where &#039;[irq]&#039; denotes that the message returned is in the &#039;&#039;info request-&#039;&#039;category, that it pertains to the command &amp;quot;bcf&amp;quot; / &amp;quot;bw.pid.tf&amp;quot; and has the value &#039;&#039;82.5&#039;&#039;. Note that the returned &#039;&#039;command&#039;&#039; sent by an &amp;quot;rqi&amp;quot;-command always uses the &#039;&#039;short name&#039;&#039; in order to preserve bandwidth. In the FAR 1.1 the return statement always returns the &#039;&#039;index&#039;&#039; of the &#039;&#039;module&#039;&#039;(s) in question. &lt;br /&gt;
&lt;br /&gt;
Most commands do not require any &#039;&#039;parameters&#039;&#039; when using the &amp;quot;rqi&amp;quot;-command. The &#039;&#039;&amp;quot;&#039;&#039;adcread&amp;quot; / &amp;quot;controlbox.datareturn&amp;quot;-command is an example of a &#039;&#039;command&#039;&#039; that &amp;lt;u&amp;gt;does&amp;lt;/u&amp;gt; require a &#039;&#039;parameter&#039;&#039; when used with &amp;quot;rqi&amp;quot;. The &amp;quot;adcread&amp;quot; / &amp;quot;controlbox.datareturn&amp;quot;&#039;&#039;-&#039;&#039;command returns the last value read by the &#039;&#039;analog-to-digital converter&#039;&#039; in the &#039;&#039;Control box&#039;&#039;, because there are 8 different channels the first &#039;&#039;parameter&#039;&#039; sets which channel to return the data for, hence executing the &#039;&#039;command&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
rqi:adcr:3&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
rqi:controlbox.datareturn:3&lt;br /&gt;
&amp;lt;/pre&amp;gt;will return the last data read on &#039;&#039;analog-to-digital convert&#039;&#039; channel 3.&lt;br /&gt;
&lt;br /&gt;
== MIDI mapping ==&lt;br /&gt;
The way &#039;&#039;MIDI&#039;&#039; works int the Ekdahl FAR is that each &#039;&#039;MIDI message&#039;&#039; is associated with a certain &#039;&#039;command string&#039;&#039; and the &#039;&#039;MIDI message&#039;&#039; will also update some of the internal &#039;&#039;variables&#039;&#039;. Any time the associated &#039;&#039;MIDI message&#039;&#039; is received the Ekdahl FAR will execute the &#039;&#039;commands&#039;&#039; that have been associated with that &#039;&#039;MIDI message&#039;&#039;. Several &#039;&#039;MIDI configurations&#039;&#039; can be stored and recalled at any time, each with a different set of &#039;&#039;commands&#039;&#039; associated with each &#039;&#039;MIDI message&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;FAR &amp;lt; 1.1&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 The &#039;&#039;command&#039;&#039; responsible for mapping &#039;&#039;command strings&#039;&#039; to different &#039;&#039;MIDI messages&#039;&#039; is &amp;quot;midieventhandler&amp;quot; or &amp;quot;mev&amp;quot; for short. The first &#039;&#039;parameter&#039;&#039; of &amp;quot;mev&amp;quot; is the type of &#039;&#039;MIDI message&#039;&#039; that we want to remap;&lt;br /&gt;
 &lt;br /&gt;
 * &#039;&#039;&#039;noteon&#039;&#039;&#039; - Note on&lt;br /&gt;
 * &#039;&#039;&#039;noteoff&#039;&#039;&#039; - Note off&lt;br /&gt;
 * &#039;&#039;&#039;pat&#039;&#039;&#039; - Poly after touch&lt;br /&gt;
 * &#039;&#039;&#039;cat&#039;&#039;&#039; - Channel after touch&lt;br /&gt;
 * &#039;&#039;&#039;pb&#039;&#039;&#039; - Pitch bend&lt;br /&gt;
 * &#039;&#039;&#039;pc&#039;&#039;&#039; - Program change&lt;br /&gt;
 * &#039;&#039;&#039;cc&#039;&#039;&#039; - Continuous controller&lt;br /&gt;
 &lt;br /&gt;
 The second &#039;&#039;parameter&#039;&#039; is the &#039;&#039;command string&#039;&#039; that is to be associated with the &#039;&#039;MIDI Message&#039;&#039; - with the exception of the &#039;&#039;&#039;cc&#039;&#039;&#039;-type, here the second &#039;&#039;parameter&#039;&#039; is the &#039;&#039;controller number&#039;&#039; (0 - 127) and the third &#039;&#039;parameter&#039;&#039; is the &#039;&#039;command string&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;FAR 1.1&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 The &amp;quot;bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; contains a &#039;&#039;module&#039;&#039; called &amp;quot;midiconfigurationhandler&amp;quot; that handles the loading and switching in between different &#039;&#039;MIDI configurations&#039;&#039;. The &amp;quot;midiconfigurationhandler&amp;quot;&#039;&#039;-module&#039;&#039; has one or more &#039;&#039;&amp;quot;&#039;&#039;midiconfiguration&amp;quot;-&#039;&#039;modules&#039;&#039;, each having its own &#039;&#039;MIDI&#039;&#039; settings. In order to change the &#039;&#039;command mapping&#039;&#039; for a &#039;&#039;MIDI message&#039;&#039; in a specific &#039;&#039;MIDI configuration&#039;&#039;, the following &#039;&#039;commands&#039;&#039; are used;&lt;br /&gt;
 &lt;br /&gt;
 * &#039;&#039;&#039;noteon/non&#039;&#039;&#039;:&#039;&#039;commands&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed for a &#039;note on&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;noteoff/nof&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;note off&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;polyaftertouch/pat&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;poly aftertouch&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;channelaftertouch/cat&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;channel aftertouch&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;pitchbend/pb&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;pitch bend&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;programchange/pc&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;program change&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;continuouscontrollerdata/ccd&#039;&#039;&#039;&#039;&#039;:controller:commands&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed for &#039;continuous controller&#039; no &#039;&#039;controller&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
We can of course use the &#039;&#039;&amp;quot;&#039;&#039;rqi&amp;quot;-&#039;&#039;command&#039;&#039; to check the current mapping, below we are asking what the current &#039;&#039;command string&#039;&#039; associated with the &#039;&#039;pitch bend&#039;&#039; &#039;&#039;MIDI message&#039;&#039; is in the currently selected &#039;&#039;MIDI configuration&#039;&#039;.&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
rqi:midieventhandler:pb&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
rqi:bowingwheel.midiconfigurationhandler.midiconfiguration.pitchbend&lt;br /&gt;
&amp;lt;/pre&amp;gt;This may return something like&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
[irq]mev:pb:&amp;quot;bowcontrolharmonicshift:pitch*4&amp;quot;&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
[irq]bw[0].mcf[0].mc[0].pb:&amp;quot;bowingwheel.harmonicserieshandler.harmonicseries.shift:pitch*4&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;The first part of the return message tells us that the incoming message is of &amp;quot;rqi&amp;quot;-type (&amp;quot;[irq]&amp;quot;) which means it&#039;s responding to a information request &#039;&#039;command&#039;&#039; sent. The second part tells us what &#039;&#039;command&#039;&#039; the information request return is responding to and any &#039;&#039;parameters&#039;&#039; that may be pertinent. The third part of the message is the actual data stored.  &lt;br /&gt;
&lt;br /&gt;
For the FAR &amp;lt; 1.1 the data returned is for the &#039;&#039;command&#039;&#039; &amp;quot;mev&amp;quot; with the first &#039;&#039;parameter&#039;&#039; set to &amp;quot;pb&amp;quot;, the &#039;&#039;command reference&#039;&#039; tells us this means the &#039;&#039;command&#039;&#039; &amp;quot;midieventhandler&amp;quot; and the &#039;&#039;parameter&#039;&#039; &amp;quot;pb&amp;quot; indicates this has to do with the &#039;&#039;pitch bend&#039;&#039;. The data is &amp;quot;bowcontrolharmonicshift:pitch*4&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
For the FAR 1.1 the data returned is for the &#039;&#039;command&#039;&#039; &amp;quot;bw[0].mcf[0].mc[0].pb&amp;quot; (bowinwheel[0].midiconfigurationhandler[0].midiconfiguration[0].pitchbend) and the data is &amp;quot;bowingwheel.harmonicserieshandler.harmonicseries.shift:pitch*4&amp;quot;. Note here that if we have several different &#039;&#039;MIDI configurations&#039;&#039; stored and we&#039;re currently using configuration number 2, the returned message would have been &amp;quot;bw[0].mcf[0].mc[2].pb&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
that the &#039;&#039;pitch bend MIDI message&#039;&#039; is executing a &amp;quot;bowcontrolharmonicshift&amp;quot; / &amp;quot;harmonicseries.shift&amp;quot;-command with the parameter &#039;&#039;pitch*4&#039;&#039;. Looking in the &#039;&#039;command reference&#039;&#039; we can see that &#039;&#039;&amp;quot;&#039;&#039;bowcontrolharmonicshift&amp;quot; / &amp;quot;harmonicseries.shift&amp;quot;-&#039;&#039;command&#039;&#039; shifts the frequency of the &#039;&#039;bowing wheel&#039;&#039; from the currently selected harmonic. The first (and only) &#039;&#039;parameter&#039;&#039; sets how much we want to shift it (the range depends on the &amp;quot;bowcontrolharmonicshiftrange&#039;&#039;&amp;quot;&#039;&#039; / &amp;quot;harmonicseries.shiftrange&amp;quot;-&#039;&#039;command&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
If we look in the list of &#039;&#039;[[The Ekdahl FAR - Command langue#Variables|variables]]&#039;&#039; above we can see that the &#039;&#039;pitch bend MIDI message&#039;&#039; will set the &amp;quot;pitch&amp;quot;&#039;&#039;-variable&#039;&#039; which is indeed used. Now what is the &#039;&#039;&#039;*4&#039;&#039;&amp;lt;nowiki/&amp;gt;&#039; all about? Well the &amp;quot;bowcontrolharmonicshift&amp;quot; / &amp;quot;harmoniceseries.shift&amp;quot;-&#039;&#039;command&#039;&#039; expects a &#039;&#039;16-bit signed&#039;&#039; value as its &#039;&#039;parameter&#039;&#039;. This means that the valid &#039;&#039;parameter&#039;&#039; number can be anything from -32767 to 32767. A full &#039;&#039;harmonic shift&#039;&#039; downwards according to the range set is equal to -32767, a full &#039;&#039;harmonic shift&#039;&#039; upwards is 32767 and no &#039;&#039;harmonic shift&#039;&#039; is 0. The &#039;&#039;pitch bend MIDI message&#039;&#039; however is only 14-bits, meaning its range is -8192 to 8192. So we have to multiply &#039;&#039;pitch&#039;&#039; by 4 in order to meet the requirements of a &#039;&#039;16-bit signed parameter&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
This whole thing about number of bits can seem confusing but in the end it&#039;s all about how fine control you have over things; the more possible values, the more detailed control. In fact, most &#039;&#039;MIDI&#039;&#039; values are only 7-bit (!) meaning a range of 0 - 127. While this may sound like a lot of detail for something like a volume control, it is not even close to enough resolution to for instance set the &#039;&#039;bowing frequency&#039;&#039;. Even if you would limit yourself to a single octave the instrument would never be able to be properly in tune. The idea of limiting the Ekdahl FAR to what is possible through &#039;&#039;MIDI&#039;&#039; seemed like a poor choice thus it was decided that &amp;lt;u&amp;gt;most&amp;lt;/u&amp;gt; parameters will instead be 16-bit.&lt;br /&gt;
&lt;br /&gt;
Now lets look at a more complex example, the &amp;lt;u&amp;gt;default&amp;lt;/u&amp;gt; &#039;&#039;Note On MIDI message&#039;&#039;. On a stock Ekdahl FAR, executing&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
rqi:mev:noteon&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
rqi:mcf.mf.non&lt;br /&gt;
&amp;lt;/pre&amp;gt;Will return something like&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
[irq]mev:noteon:&#039;bchb:note,bmr:1,bpid:1,bpe:1,se:(velocity*512)*(1-notecount),bcsm:0&#039;&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
[irq]mcf[0].mc[0].non:&#039;bw.hsh.hb:note,bw.dcm.ru:1,bw.pe:1,bw.bp.en:1,so.en:(velocity*512)*(1-notecount),bw.sm:0&#039;&amp;lt;/pre&amp;gt;As can be seen, there&#039;s a lot of stuff going on here! First of all, notice that everything after &amp;quot;mev:noteon:&amp;quot; / &amp;quot;mcf[0].mc[0].non:&amp;quot; is situated in between single quotes (&#039;) - this is &amp;lt;u&amp;gt;absolutely crucial&amp;lt;/u&amp;gt; for the Ekdahl FAR in order to know that everything within those last two quotes is part of the last &#039;&#039;parameter&#039;&#039; of the &amp;quot;mev&amp;quot; / &amp;quot;mcf.mc.non&amp;quot;-&#039;&#039;command&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Now let&#039;s break down what happens when this &#039;&#039;MIDI message&#039;&#039; is received, i.e. when a &#039;&#039;MIDI&#039;&#039; key is pressed down:&lt;br /&gt;
&lt;br /&gt;
# &amp;quot;bchb:note&amp;quot; / &amp;quot;bw.hsh.hb:note&amp;quot;  - Invokes the &amp;quot;bowcontrolharmonicbase&amp;quot; / &amp;quot;harmonicserieshandler.harmonicbase&amp;quot;&#039;&#039;-command&#039;&#039; with the first &#039;&#039;parameter&#039;&#039; set to the &#039;&#039;variable &amp;quot;&#039;&#039;note&amp;quot;. This sets the &#039;&#039;base harmonic&#039;&#039; that the Ekdahl FARs &#039;&#039;bowing motor&#039;&#039; should be set to. Here the &#039;&#039;variable&#039;&#039; &amp;quot;note&amp;quot; is used which is simply the MIDI key being pressed down, it is automatically converted by the &#039;&#039;command&#039;&#039; to the corresponding harmonic in the &#039;&#039;harmonic list&#039;&#039;&lt;br /&gt;
# &amp;quot;bmr:1&amp;quot; / &amp;quot;bw.dcm.ru&amp;quot; - Sets the &amp;quot;bowmotorrun&amp;quot; / &amp;quot;dcmotor.run&amp;quot;-command to &#039;1&#039;, starting the &#039;&#039;bow motor&#039;&#039;&lt;br /&gt;
# &amp;quot;bpid:1&amp;quot; / &amp;quot;bw.pe:1&amp;quot; - Sets the &amp;quot;bowpid&amp;quot; / &amp;quot;bowingwheel.pidenable&amp;quot;-&#039;&#039;command&#039;&#039; to &#039;1&#039;. Basically this enables the function that makes the Ekdahl FAR able to keep a stable frequency on the &#039;&#039;bowing motor&#039;&#039;.&lt;br /&gt;
# &amp;quot;bpe:1&amp;quot; / &amp;quot;bw.bp.en&amp;quot; - Sets the &amp;quot;bowpressureengage&amp;quot; / &amp;quot;bowpressure.engage&amp;quot;-&#039;&#039;command&#039;&#039; to &#039;1&#039; which moves the &#039;&#039;bowing jack&#039;&#039; to the &#039;&#039;engage position&#039;&#039;, aka just below the string if not additional &#039;&#039;pressure&#039;&#039; is applied&lt;br /&gt;
# &amp;quot;se:(velocity*512)*(1-notecount)&amp;quot; / &amp;quot;so.en:(velocity*512)*(1-notecount)&amp;quot; - Executes the &amp;quot;solenoidengage&amp;quot; / &amp;quot;solenoid.engage&amp;quot;-&#039;&#039;command&#039;&#039; with the value &#039;&#039;(velocity*512)*(1-notecount)&#039;&#039;. This will make the &#039;&#039;solenoid&#039;&#039; strike the &#039;&#039;hammer&#039;&#039; with a force that is dependent on the &amp;quot;velocity&amp;quot;-&#039;&#039;variable&#039;&#039; sent by the &#039;&#039;Note On MIDI message&#039;&#039; in order to make the &#039;&#039;hammer&#039;&#039; velocity sensitive.   But it also adds the somewhat perplexing part &amp;quot;*(1-notecount)&amp;quot;. &amp;quot;notecount&amp;quot; is a global &#039;&#039;variable&#039;&#039; that contains the number of MIDI keys that are currently being held down. If &amp;quot;notecount&amp;quot; is anything above zero, the outcome of the equation will either be zero or a negative number. The &amp;quot;solenoidengage&amp;quot; / &amp;quot;solenoid.engage&amp;quot;-&#039;&#039;command&#039;&#039; requires a &#039;&#039;16-bit unsigned&#039;&#039; value, aka the only valid numbers are 0 - 65535. Anything below 0 will be interpreted as zero, so what this equation does is that it only fires off the &#039;&#039;hammer&#039;&#039; if there are no previous keys being held down - it&#039;s being used in &#039;&#039;staccato&#039;&#039;  mode.&lt;br /&gt;
# &amp;quot;bcsm:0&amp;quot; / &amp;quot;bowingwheel.speedmode&amp;quot; - Sets the &amp;quot;bowcontrolspeedmode&amp;quot; / &amp;quot;bowingwheel.speedmode&amp;quot; to &#039;1&#039; which enables automatic shut down of the &#039;&#039;bowing motor&#039;&#039; after a given timeout.&lt;br /&gt;
Let&#039;s postulate that the Ekdahl FAR is tuned to a &#039;C&#039; at 65.4Hz and has its &#039;&#039;base&#039;&#039; set to middle &#039;C&#039; (&#039;&#039;MIDI key&#039;&#039; no 36). We are using the equal-temperament 12-tone scale and the Ekdahl FAR is set to respond to &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; &#039;&#039;MIDI channels&#039;&#039; (omni). Without having previously held any keys we press the middle &#039;C&#039; (&#039;&#039;note&#039;&#039; value 36) as hard as possible (&#039;&#039;velocity&#039;&#039; value &#039;&#039;127&#039;&#039;) on &#039;&#039;MIDI channel&#039;&#039; number 1 (&#039;&#039;channel&#039;&#039; value of 0). The Ekdahl FAR will get a &#039;&#039;note on MIDI message&#039;&#039; sent to it and from our mapping it will create the following &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
[irq]mev:noteon:&#039;bchb:36,bmr:1,bpid:1,bpe:1,se:(127*512)*(1-0),bcsm:0&#039;&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
[irq]mcf[0].mc[0].non:&#039;bw.hsh.hb:36,bw.dcm.ru:1,bw.pe:1,bw.bp.en:1,so.en:(127*512)*(1-0),bw.sm:0&#039;&amp;lt;/pre&amp;gt;What has happened here is that all &#039;&#039;variables&#039;&#039; have been replaced with the values sent by the &#039;&#039;MIDI message&#039;&#039;. Since those &#039;&#039;commands&#039;&#039; that doesn&#039;t have any &#039;&#039;variables&#039;&#039; with them will execute just as previously, only those &#039;&#039;commands&#039;&#039; whos &#039;&#039;parameters&#039;&#039; have changed will be explained:&lt;br /&gt;
&lt;br /&gt;
# &amp;quot;bchb: 36&amp;quot; / &amp;quot;bw.hsh.hb:36&amp;quot; - The &amp;quot;bowcontrolharmonicbase&amp;quot; / &amp;quot;harmonicserieshandler.harmonicbase&amp;quot; gets a value of &#039;&#039;36&#039;&#039; (middle &#039;C&#039;), because &#039;&#039;harmonic number 0&#039;&#039; is mapped to this key it will set the &#039;&#039;bowing wheel&#039;&#039; frequency to the &#039;&#039;fundamental&#039;&#039;; &#039;&#039;65.4&#039;&#039; Hertz&lt;br /&gt;
# &amp;quot;se: (127*512)*(1-0)&amp;quot; / &amp;quot;so.en: (127*512)*(1-0)&amp;quot; - the value of &#039;&#039;127&#039;&#039; comes from the &amp;quot;velocity&amp;quot;-&#039;&#039;variable&#039;&#039;, &#039;&#039;127 * 512 = 65024&#039;&#039; which is awfully close to a maximum hammer force of 65535. Since no previous notes were held down, the &#039;&#039;&amp;quot;&#039;&#039;notecount&amp;quot;-&#039;&#039;variable&#039;&#039;  is equal to &#039;&#039;0&#039;&#039; and thus &#039;&#039;65024 * 1 = 65024&#039;&#039;. The hammer is engaged with near maximum force.&lt;br /&gt;
So the result is that we have set the speed of the &#039;&#039;bowing motor&#039;&#039; and we have engaged the &#039;&#039;hammer&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Now imagine that without releasing this key, we press another &#039;C&#039; one octave above but at half the velocity. The Ekdahl FAR creates the following &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
[irq]mev:noteon:&#039;bchb:48,bmr:1,bpid:1,bpe:1,se:(63*512)*(1-1),bcsm:0&#039;&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
[irq]mcf[0].mc[0].non:&#039;bw.hsh.hb:48,bw.dcm.ru:1,bw.pe:1,bw.bp.en:1,so.en:(65*512)*(1-1),bw.sm:0&#039;&lt;br /&gt;
&amp;lt;/pre&amp;gt;Now we can see that the &amp;quot;note&amp;quot;-&#039;&#039;variable&#039;&#039; is 48 because the &#039;C&#039; one octave up is exactly 12 keys above the first. The &amp;quot;velocity&amp;quot;-&#039;&#039;variable&#039;&#039; has changed to 63 since we hit it with a lighter touch - and because we are &amp;lt;u&amp;gt;still holding the first key down&amp;lt;/u&amp;gt;, the &amp;quot;notecount&amp;quot;-&#039;&#039;variable&#039;&#039; is equal to &#039;&#039;1&#039;&#039;. Here&#039;s what happens&lt;br /&gt;
&lt;br /&gt;
# &amp;quot;bchb: 48&amp;quot; / &amp;quot;hsh.hb:48&amp;quot; - Due to the &#039;&#039;base&#039;&#039; being set to &#039;&#039;36&#039;&#039; the &#039;&#039;harmonic number&#039;&#039; is set to &#039;&#039;48 - 36 = 12&#039;&#039;. Because we are using a 12-tone scale &#039;&#039;harmonic number 12&#039;&#039; is exactly one octave above the &#039;&#039;fundamental&#039;&#039; thus the speed of the &#039;&#039;bowing wheel&#039;&#039; is set to &#039;&#039;65.4 * 2 = 130.8&#039;&#039; Hertz.&lt;br /&gt;
# &amp;quot;se: (63*512)*(1-1)&amp;quot; / &amp;quot;so.en: (63*512)*(1-1)&amp;quot; - The equation evalutes as &#039;&#039;63 * 512 = 32256&#039;&#039; and &#039;&#039;1 - 1 = 0&#039;&#039; thus &#039;&#039;32256 * 0 = 0&#039;&#039;. When the &amp;quot;solenoidengage&amp;quot; / &amp;quot;solenoid.engage&amp;quot;-&#039;&#039;command&#039;&#039; gets a &#039;&#039;parameter&#039;&#039; of &#039;&#039;0&#039;&#039; it will not engage the &#039;&#039;hammer&#039;&#039; - so the &#039;&#039;hammer&#039;&#039; doesn&#039;t strike&lt;br /&gt;
So it can be seen that with quite rudimentary math we can accomplish a whole lot of things here. Note also that even though the &#039;&#039;note on MIDI message&#039;&#039; also sets the &#039;&#039;channel&#039;&#039;-variable we never use it in this example - plenty of opportunity to make something weird happen depending on the &#039;&#039;MIDI channel&#039;&#039;!&lt;br /&gt;
&lt;br /&gt;
== CV Mapping ==&lt;br /&gt;
&#039;&#039;CV Mapping&#039;&#039; works exactly like the &#039;&#039;MIDI mapping&#039;&#039; with the difference that the command for setting the &#039;&#039;CV mapping&#039;&#039; is different and that &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; events pertaining to this &amp;lt;u&amp;gt;only&amp;lt;/u&amp;gt; change the &amp;quot;value&amp;quot;-&#039;&#039;variable&#039;&#039;.  &lt;br /&gt;
 &#039;&#039;&#039;FAR &amp;lt; 1.1:&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 The command for changing the CV mapping is &amp;quot;adccommandmap&amp;quot; or &amp;quot;acm&amp;quot;, it take two parameters; channel and command string. The channels on the original Edkahl FAR Control box are as &lt;br /&gt;
 &lt;br /&gt;
 * 0 - The &amp;quot;Harmonic&amp;quot; knob and jack&lt;br /&gt;
 * 1 - The &amp;quot;Harmonic shift&amp;quot; knob and jack&lt;br /&gt;
 * 2 - The &amp;quot;Fine tune&amp;quot; knob&lt;br /&gt;
 * 3 - The &amp;quot;Pressure&amp;quot; knob and jack&lt;br /&gt;
 * 4 - The &amp;quot;Hammertrig&amp;quot; button and jack&lt;br /&gt;
 * 5 - The &amp;quot;Gate&amp;quot; switch and jack&lt;br /&gt;
 * 6 - The &amp;quot;Hammer Scale&amp;quot; knob&lt;br /&gt;
 * 7 - The &amp;quot;Mute&amp;quot; knob and jack&lt;br /&gt;
 &lt;br /&gt;
 &#039;&#039;&#039;FAR 1.1:&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 The commands responsible for changing the CV mapping are located in the &amp;quot;controlbox&amp;quot;-module, these are&lt;br /&gt;
 &lt;br /&gt;
 * &#039;&#039;&#039;harmonic&#039;&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed when the &amp;quot;Harmonic&amp;quot;-knob or modulation changes&lt;br /&gt;
 * &#039;&#039;&#039;harmonicshift&#039;&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed when the &amp;quot;Harmonic shift&amp;quot;-knob or modulation changes&lt;br /&gt;
 * &#039;&#039;&#039;finetune&#039;&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed when the &amp;quot;Fine tune&amp;quot;-knob changes&lt;br /&gt;
 * &#039;&#039;&#039;pressure&#039;&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed when the &amp;quot;Pressure&amp;quot;-knob or modulation changes&lt;br /&gt;
 * &#039;&#039;&#039;mute&#039;&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed when the &amp;quot;Mute&amp;quot;-knob or modulation changes&lt;br /&gt;
 * &#039;&#039;&#039;hammerscale&#039;&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed when the &amp;quot;Hammer scale&amp;quot;-knob changes&lt;br /&gt;
 * &#039;&#039;&#039;gate&#039;&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed when the &amp;quot;Gate&amp;quot;-switch or modulation changes&lt;br /&gt;
 * &#039;&#039;&#039;hammertrig&#039;&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed when the &amp;quot;Hammer Trig&amp;quot;-button or modulation changes&lt;br /&gt;
We retrieve the &#039;&#039;command string&#039;&#039; for channel &#039;&#039;0&#039;&#039; which reads the sum of the &#039;&#039;harm. v/oct&#039;&#039;-jack and the &#039;&#039;harmonic&#039;&#039;-knob by sending a command of&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;u&amp;gt;default&amp;lt;/u&amp;gt; response will be something like&lt;br /&gt;
&amp;lt;pre&amp;gt;[irq]acm:0:&#039;bcha:value/1327.716667-20&#039;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{docnav&lt;br /&gt;
|[[The Ekdahl FAR - Service|Service]]&lt;br /&gt;
|[[The Ekdahl FAR - Command reference|Command reference]]&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Knaadmin</name></author>
	</entry>
	<entry>
		<id>http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_language&amp;diff=1656</id>
		<title>The Ekdahl FAR - Command language</title>
		<link rel="alternate" type="text/html" href="http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_language&amp;diff=1656"/>
		<updated>2026-06-12T09:04:31Z</updated>

		<summary type="html">&lt;p&gt;Knaadmin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Command language ==&lt;br /&gt;
The Ekdahl FAR is entirely controlled by &#039;&#039;commands&#039;&#039;, these &#039;&#039;commands&#039;&#039; decide everything that the instrument is doing, whether it is playing a melody or changing an internal parameter. &lt;br /&gt;
&lt;br /&gt;
When a &#039;&#039;MIDI message&#039;&#039; is received or a new CV / knob value is read, the &#039;&#039;commands&#039;&#039; associated with it will be internally sent. This can be things like &amp;quot;engage hammer&amp;quot; or &amp;quot;set the fundamental frequency&amp;quot; etc. &lt;br /&gt;
&lt;br /&gt;
Some of the available &#039;&#039;commands&#039;&#039; are mainly used for calibrating and setting up the instrument and are usually saved into the instruments memory, these will be executed whenever the instrument is turned on. &lt;br /&gt;
&lt;br /&gt;
All &#039;&#039;commands&#039;&#039; can be manually invoked via &#039;&#039;USB-Serial&#039;&#039;, in conjunction with certain software this presents an unprecedented level of control and sequenceability.&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
The &#039;&#039;commands&#039;&#039; are invoked using a &#039;&#039;plain text approach&#039;&#039;, all commands have both a &#039;&#039;long name&#039;&#039; and a &#039;&#039;short name&#039;&#039; which are interchangeable. A &#039;&#039;command&#039;&#039; may have one or more &#039;&#039;parameters&#039;&#039; associated with it, these &#039;&#039;parameters&#039;&#039; can be of different types; 16-bit numbers (values 0 - 65535 or -32767 - 32767), floating point numbers (values with decimals), booleans (0 for &#039;false&#039;, 1 for &#039;true&#039;) and strings (text). Some commands are &#039;&#039;conditional&#039;&#039;, meaning they will only execute if a parameter equates to &#039;1&#039; (&#039;true&#039;). &lt;br /&gt;
&lt;br /&gt;
The way &#039;&#039;commands&#039;&#039; are written in order to be executed is &#039;&#039;commandname:parameter1:parameter2:parameter3 [etc]&#039;&#039;, several commands be executed in sequence by separating them with a comma (&#039;,&#039;), a bunch of commands strung together is called a &#039;&#039;command string&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Since version 1.1 of the Ekdahl FAR Firmware, all commands are grouped in a hierarchical fashion according to their &#039;&#039;modules&#039;&#039; and each ladder in the hierarchy is separated by a period (&amp;quot;.&amp;quot;), this works very much like folders or directories in a regular computer. Every &#039;&#039;module&#039;&#039; can contain both &#039;&#039;commands&#039;&#039; and other &#039;&#039;modules&#039;&#039;. For instance, everything associated with the &#039;&#039;bowing wheel&#039;&#039; is now collected under &amp;quot;bowingwheel&amp;quot; &#039;&#039;module&#039;&#039;. That in turn contains a &amp;quot;dcmotor&amp;quot; &#039;&#039;module&#039;&#039; which handles direct control of the bowing motor. It also has a &amp;quot;pid&amp;quot; &#039;&#039;module&#039;&#039; that handles bow frequency among other thing. &lt;br /&gt;
&lt;br /&gt;
If for instance we would like to start the &#039;&#039;bowing wheel&#039;&#039; and set its frequency to 82.5 Hertz we could send the Ekdahl FAR the following &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
bowmotorrun:1, bowcontrolfrequecy:82.5&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bowingwheel.dcmotor.run:1, bowingwheel.pid.targetfrequency:82.5&amp;lt;/pre&amp;gt;We could also use the &#039;&#039;short names&#039;&#039; for the commands&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
bmr:1,bcf:82.5&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bw.dcm.ru:1, bw.pid.tf:82.5&amp;lt;/pre&amp;gt;Both &amp;quot;bowmotorrun&amp;quot; / &amp;quot;bowingwheel.dcmotor.run&amp;quot; and &amp;quot;bowcontrolfrequency&amp;quot; / &amp;quot;bowingwheel.pid.targetfrequency&amp;quot; takes one &#039;&#039;parameter&#039;&#039; each, &#039;&#039;&amp;quot;&#039;&#039;bowmotorrun&amp;quot; / &amp;quot;bowingwheel.dcmotor.run&amp;quot; is &#039;&#039;conditional&#039;&#039; and unless the first &#039;&#039;parameter&#039;&#039; is equal to &#039;1&#039; the motor will not start. The first &#039;&#039;parameter&#039;&#039; of &amp;quot;bowcontrolfrequency&amp;quot; / &amp;quot;bowingwheel.pid.targetfrequency&amp;quot; sets the frequency of the &#039;&#039;bowing wheel&#039;&#039;, the instrument may not execute a &#039;&#039;command&#039;&#039; if it decides that the given &#039;&#039;parameters&#039;&#039; are outside of the working range or they are missing.&lt;br /&gt;
&lt;br /&gt;
The addition of the hierarchy in the FAR 1.1 firmware isn&#039;t just to be able to group commands, but it&#039;s also to make the FAR not limited to a single set of &#039;&#039;modules&#039;&#039; (and is the first stepping stone to a &#039;&#039;modular&#039;&#039; Ekdahl FAR). In fact, you could have 12 different bowing wheel &#039;&#039;modules&#039;&#039; for 12 different strings, these would then be addressed as &amp;quot;bowingwheel[0].command&amp;quot;&#039;&#039;, &amp;quot;&#039;&#039;bowingwheel[1].command&amp;quot; etc. Anyone familiar with C programming notices that this is the standard way of &#039;&#039;indexing&#039;&#039; an array; using brackets (&amp;quot;[ ]&amp;quot;). When addressing a module without &#039;&#039;indexing&#039;&#039; as in the example above, the FAR will do one or two things; either use the first object (&amp;quot;[0]&amp;quot;) or, if the object is &#039;&#039;selectable&#039;&#039; it will use the previously selected object. To make things smoother a command can be executed on several objects at once by using ranges (&amp;quot;[0-4]&amp;quot;) and comma separation (&amp;quot;[0, 3, 5-6]&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
To test out a &#039;&#039;command&#039;&#039; you can send it directly to the Ekdahl FAR using the &#039;&#039;Console&#039;&#039; in the &#039;&#039;Configuration utility&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
To read up on existing &#039;&#039;commands&#039;&#039;, their &#039;&#039;parameters&#039;&#039; and a brief description you can check the &#039;&#039;Command reference&#039;&#039; in the &#039;&#039;Configuration utility&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Variables, functions and equations ==&lt;br /&gt;
What makes the &#039;&#039;Command language&#039;&#039; truly powerful is the concept of &#039;&#039;variables, functions&#039;&#039; and &#039;&#039;equations&#039;&#039;. All &#039;&#039;parameters&#039;&#039; that take numerical values can use any combination of &#039;&#039;variables, functions&#039;&#039; or &#039;&#039;equations.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
For instance, we can use the previous example and instead write our &#039;&#039;command string&#039;&#039; as follows&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
bowmotorrun:1, bowcontrolfrequency:82.5+note*20&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bowingwheel.dcmotor.run:1, bowingwheel.pid.targetfrequency:82.5+note*20&amp;lt;/pre&amp;gt;This example requires of course that the &#039;&#039;variable&#039;&#039; &#039;&#039;note&#039;&#039; exists in the current context. &lt;br /&gt;
&lt;br /&gt;
===== Variables =====&lt;br /&gt;
There are two types of &#039;&#039;variables&#039;&#039; in the Ekdahl FAR; &#039;&#039;global variables&#039;&#039; and &#039;&#039;event variables&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Global variables&#039;&#039; are variables that are always valid, in any context. The &#039;&#039;global variables&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;notecount&#039;&#039;&#039; - Contains the number of &#039;&#039;MIDI&#039;&#039; keys that are being held down, i.e. all &#039;&#039;Note on messages&#039;&#039; received that haven&#039;t gotten a paired &#039;&#039;Note off message&#039;&#039; yet&lt;br /&gt;
* &#039;&#039;&#039;uv0&#039;&#039;&#039; - &#039;&#039;&#039;uv9&#039;&#039;&#039; - These are &#039;&#039;user variables&#039;&#039; and can be set at any point using the &#039;&#039;globaluservariable command&#039;&#039; with the first &#039;&#039;parameter&#039;&#039; being which variable to set (0-9) and the second &#039;&#039;parameter&#039;&#039; being the value (float).&lt;br /&gt;
* &#039;&#039;&#039;e&#039;&#039;&#039; - Contains the constant &#039;&#039;[[wikipedia:E_(mathematical_constant)|e]]&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pi&#039;&#039;&#039; - Contains the constant &#039;&#039;[[wikipedia:Pi|pi]]&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Event variables&#039;&#039; are variables that are set by certain &#039;&#039;MIDI messages&#039;&#039; or when a new value is read on one of the jacks or knobs on the &#039;&#039;Control box&#039;&#039;. The &#039;&#039;Event variables&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;channel&#039;&#039;&#039; - Set by the &#039;&#039;Note on, Note off, Continuous Controller, Poly after touch, Pitch bend, Channel after touch&#039;&#039; and &#039;&#039;Program change MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;note&#039;&#039;&#039; - Set by the &#039;&#039;Note on, Note off&#039;&#039; and &#039;&#039;Poly after touch MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;velocity&#039;&#039;&#039; - Set by the &#039;&#039;Note on&#039;&#039; and &#039;&#039;Note off MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pressure&#039;&#039;&#039; - Set by the &#039;&#039;Poly after touch&#039;&#039; and &#039;&#039;Channel after touch MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; - Set by the &#039;&#039;Continuous Controller MIDI message&#039;&#039; and by the &#039;&#039;Control box&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pitch&#039;&#039;&#039; - Set by the &#039;&#039;Pitch bend MIDI message&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;program&#039;&#039;&#039; - Set by the &#039;&#039;Program change MIDI message&#039;&#039;&lt;br /&gt;
These variables will contain whatever data is relevant to the last event that occurred and may be overwritten by the next event.&lt;br /&gt;
&lt;br /&gt;
===== Functions =====&lt;br /&gt;
&#039;&#039;Functions&#039;&#039; can be used to change a numerical value or the result of an &#039;&#039;equation&#039;&#039;, the Ekdahl FAR contains both general &#039;&#039;arithmetic functions&#039;&#039; (courtesy of Lewis Van Winkle and the TINYEXPR engine) and &#039;&#039;specialized functions&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;arithmetic functions&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;abs&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Absolute_value|absolute value]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;acos&#039;&#039;&#039;(x), &#039;&#039;&#039;asin&#039;&#039;&#039;(x), &#039;&#039;&#039;atan&#039;&#039;&#039;(x), atan2(x, y) - Returns the [[wikipedia:Inverse_trigonometric_functions|&#039;&#039;arc-cos, -sin, -tan&#039;&#039; and &#039;&#039;-tan2&#039;&#039;]] of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;atan2&#039;&#039;&#039;(x,y) - Returns the &#039;&#039;[[wikipedia:Atan2|arctan2]]&#039;&#039; of &#039;&#039;x, y&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;floor&#039;&#039;&#039;(x), ceil(x) - Returns the [[wikipedia:Floor_and_ceiling_functions|&#039;&#039;floor&#039;&#039; and &#039;&#039;ceiling&#039;&#039;]] of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;exp&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Exponential_function|exponent]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;fac&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Factorial|factorial]]&#039;&#039; of x&lt;br /&gt;
* &#039;&#039;&#039;ln&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Natural_logarithm|natural logarithm]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;log10&#039;&#039;&#039;(x), &#039;&#039;&#039;log20&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Logarithm|logarithm]]&#039;&#039; of &#039;&#039;x&#039;&#039; using base 10 and 20 respectively&lt;br /&gt;
* &#039;&#039;&#039;ncr&#039;&#039;&#039;(x,y), &#039;&#039;&#039;npr&#039;&#039;&#039;(x,y) - Functions to calculate &#039;&#039;[[wikipedia:Combination|combinations]]&#039;&#039; and &#039;&#039;[[wikipedia:Permutation|permutations]]&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pow&#039;&#039;&#039;(x,y) - Returns &#039;&#039;x^y&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;sqrt&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Square_root|square root]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;cos&#039;&#039;&#039;(x), &#039;&#039;&#039;sin&#039;&#039;&#039;(x), &#039;&#039;&#039;tan&#039;&#039;&#039;(x) - Returns the [[wikipedia:Trigonometric_functions|&#039;&#039;cos, sin&#039;&#039; and &#039;&#039;tan&#039;&#039;]] of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;cosh&#039;&#039;&#039;(x), &#039;&#039;&#039;sinh&#039;&#039;&#039;(x), &#039;&#039;&#039;tanh&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Hyperbolic_functions|hyperbolic cos, sin and tan]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
The &#039;&#039;specialized functions&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;bool&#039;&#039;&#039;(x) - Returns 1 if &#039;&#039;x&#039;&#039; is more than 0&lt;br /&gt;
* &#039;&#039;&#039;ibool&#039;&#039;&#039;(x) - Returns 0 if &#039;&#039;x&#039;&#039; is more than 0&lt;br /&gt;
* &#039;&#039;&#039;deadband&#039;&#039;&#039;(x,y) - Returns &#039;&#039;x + y &#039;&#039; if &#039;&#039;x &amp;lt; y&#039;&#039; or &#039;&#039;x - y&#039;&#039; if &#039;&#039;x &amp;gt; y&#039;&#039;. If neither of these statements is true it returns &#039;&#039;0&#039;&#039; - used to create a [[wikipedia:Deadband|deadband]] of &#039;&#039;x&#039;&#039; with the threshold of &#039;&#039;y&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Functions&#039;&#039; can be readily used in a &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
bowmotorrun:1, bowcontrolfrequency:&amp;quot;8.17579875 * pow(2, (1/12 * note))&amp;quot;&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bowingwheel.dcmotor.run:1, bowingwheel.pid.targetfrequency:&amp;quot;8.17579875 * pow(2, (1/12 * note))&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;The previous statements starts the &#039;&#039;bowing wheel&#039;&#039; and sets the frequency of the wheel to &#039;&#039;8.17579875 * 2^(1/12 * note)&#039;&#039;. A middle &#039;C&#039; according to &#039;&#039;MIDI&#039;&#039; has a &#039;&#039;note value&#039;&#039; of 36, meaning if we substitute &#039;&#039;note&#039;&#039; with 36 we get the equation &#039;&#039;8.17579875 * 2^(1/12 * 36)&#039;&#039; which comes out to &#039;&#039;~65.4&#039;&#039; Hertz.&lt;br /&gt;
&lt;br /&gt;
Note that the first &#039;&#039;parameter&#039;&#039; for &#039;&#039;&amp;quot;&#039;&#039;bowcontrolfrequency&amp;quot; / &amp;quot;bowingwheel.pid.targetfrequency&amp;quot; is put in between double quotes (&amp;quot;). This is because the &amp;quot;pow&#039;&#039;&amp;quot;-&#039;&#039;function requires the use of a comma (&amp;quot;,&amp;quot;) in order to separate in between its two required inputs; &#039;&#039;x&#039;&#039; and &#039;&#039;y&#039;&#039;. In order for the Ekdahl FAR to know that this comma does not signal the beginning of a new &#039;&#039;command,&#039;&#039; we use quotes. Single (&#039;) and double (&amp;quot;) quotes can be used and nested in all &#039;&#039;parameters&#039;&#039; and are &amp;lt;u&amp;gt;required&amp;lt;/u&amp;gt; in a lot of circumstances, improper nesting or not using quotes can lead to the instrument not understanding the &#039;&#039;command string&#039;&#039; correctly.&lt;br /&gt;
&lt;br /&gt;
== Return messages ==&lt;br /&gt;
The Ekdahl FAR when connected via &#039;&#039;USB-Serial&#039;&#039; doesn&#039;t only accept &#039;&#039;commands&#039;&#039; but will also send various &#039;&#039;return messages&#039;&#039;. These are prefixed by their &#039;&#039;category&#039;&#039; denoted in brackets (&amp;quot;[]&amp;quot;), the existing categories as of this writing (2025-01-22) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;command&#039;&#039;&#039; / &#039;&#039;&#039;cmd&#039;&#039;&#039; - Acknowledges the reception of a command in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;usb&#039;&#039;&#039; - Acknowledges the reception of a &#039;&#039;MIDI message&#039;&#039; over &#039;&#039;USB&#039;&#039; in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;hardware&#039;&#039;&#039; / &#039;&#039;&#039;hw&#039;&#039;&#039; - Signals that a change has been sent to the Ekdahl FAR hardware, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;undefined&#039;&#039;&#039; / &#039;&#039;&#039;un&#039;&#039;&#039; - The message sent is in the &#039;&#039;undefined&#039;&#039; category, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;priority&#039;&#039;&#039; / &#039;&#039;&#039;pri&#039;&#039;&#039; - The message sent is in the &#039;&#039;priority&#039;&#039; category, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;error&#039;&#039;&#039; / &#039;&#039;&#039;err&#039;&#039;&#039; - Signals that an &#039;&#039;error&#039;&#039; has occurred, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;expressionparser&#039;&#039;&#039; / &#039;&#039;&#039;ep&#039;&#039;&#039; - These messages contains debugging information regarding the internal &#039;&#039;expression parser&#039;&#039; and is used for development&lt;br /&gt;
*&#039;&#039;&#039;debug&#039;&#039;&#039; / &#039;&#039;&#039;dbg&#039;&#039;&#039; - These messages contains various debugging information and is used for development&lt;br /&gt;
*&#039;&#039;&#039;help&#039;&#039;&#039; / &#039;&#039;&#039;hlp&#039;&#039;&#039; - Signals that the message is a response to a &#039;&#039;help&#039;&#039;-command being sent to the Ekdahl FAR. These messages are structured so that a receiver, like the &#039;&#039;Configuration utility&#039;&#039;, can parse information about available &#039;&#039;commands&#039;&#039; in the current &#039;&#039;firmware&#039;&#039; and relay it to a user in a structured way.&lt;br /&gt;
* &#039;&#039;&#039;inforequest&#039;&#039;&#039; / &#039;&#039;&#039;irq&#039;&#039;&#039; - Signals that an &#039;&#039;info request&#039;&#039; has been returned. This is a specialized message that is either sent as a response to an &#039;&#039;rqi&#039;&#039;-command or as a &#039;&#039;interrupt&#039;&#039;-message telling the user or receiving software about different parameters in the Ekdahl FAR. These messages follows the same structure as regular &#039;&#039;command message&#039;&#039;s of &#039;&#039;[irq]commandname:parameter1 [etc]&#039;&#039; so that it can be used by a receiving software to keep track of parameter changes&lt;br /&gt;
&lt;br /&gt;
===== Explicitly requesting information =====&lt;br /&gt;
By using the special command &amp;quot;requestinfo&amp;quot; / &amp;quot;rqi&amp;quot; one can request the information stored by a certain &#039;&#039;command&#039;&#039; or a state of the Ekdahl FAR. The &amp;quot;rqi&amp;quot;-command is executed in the convention &amp;quot;rqi:commandname:optional parameters&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
To go back to our example of setting the bowing frequency using the &#039;&#039;&amp;quot;&#039;&#039;bowcontrolfrequency&amp;quot; / &amp;quot;bowingwheel.pid.targetfrequency&amp;quot;-command we can ask the Ekdahl FAR what the bowing frequency is set to by writing&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
rqi:bowcontrolfrequency&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
rqi:bowingwheel.pid.targetfrequency&lt;br /&gt;
&amp;lt;/pre&amp;gt;The return value would be something like&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
[irq]bcf:82.5&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
[irq]bw[0].pid[0].tf:82.5&lt;br /&gt;
&amp;lt;/pre&amp;gt;Where &#039;[irq]&#039; denotes that the message returned is in the &#039;&#039;info request-&#039;&#039;category, that it pertains to the command &amp;quot;bcf&amp;quot; / &amp;quot;bw.pid.tf&amp;quot; and has the value &#039;&#039;82.5&#039;&#039;. Note that the returned &#039;&#039;command&#039;&#039; sent by an &amp;quot;rqi&amp;quot;-command always uses the &#039;&#039;short name&#039;&#039; in order to preserve bandwidth. In the FAR 1.1 the return statement always returns the &#039;&#039;index&#039;&#039; of the &#039;&#039;module&#039;&#039;(s) in question. &lt;br /&gt;
&lt;br /&gt;
Most commands do not require any &#039;&#039;parameters&#039;&#039; when using the &amp;quot;rqi&amp;quot;-command. The &#039;&#039;&amp;quot;&#039;&#039;adcread&amp;quot; / &amp;quot;controlbox.datareturn&amp;quot;-command is an example of a &#039;&#039;command&#039;&#039; that &amp;lt;u&amp;gt;does&amp;lt;/u&amp;gt; require a &#039;&#039;parameter&#039;&#039; when used with &amp;quot;rqi&amp;quot;. The &amp;quot;adcread&amp;quot; / &amp;quot;controlbox.datareturn&amp;quot;&#039;&#039;-&#039;&#039;command returns the last value read by the &#039;&#039;analog-to-digital converter&#039;&#039; in the &#039;&#039;Control box&#039;&#039;, because there are 8 different channels the first &#039;&#039;parameter&#039;&#039; sets which channel to return the data for, hence executing the &#039;&#039;command&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
rqi:adcr:3&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
rqi:controlbox.datareturn:3&lt;br /&gt;
&amp;lt;/pre&amp;gt;will return the last data read on &#039;&#039;analog-to-digital convert&#039;&#039; channel 3.&lt;br /&gt;
&lt;br /&gt;
== MIDI mapping ==&lt;br /&gt;
The way &#039;&#039;MIDI&#039;&#039; works int the Ekdahl FAR is that each &#039;&#039;MIDI message&#039;&#039; is associated with a certain &#039;&#039;command string&#039;&#039; and the &#039;&#039;MIDI message&#039;&#039; will also update some of the internal &#039;&#039;variables&#039;&#039;. Any time the associated &#039;&#039;MIDI message&#039;&#039; is received the Ekdahl FAR will execute the &#039;&#039;commands&#039;&#039; that have been associated with that &#039;&#039;MIDI message&#039;&#039;. Several &#039;&#039;MIDI configurations&#039;&#039; can be stored and recalled at any time, each with a different set of &#039;&#039;commands&#039;&#039; associated with each &#039;&#039;MIDI message&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;FAR &amp;lt; 1.1:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;FAR &amp;lt; 1.1&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 The &#039;&#039;command&#039;&#039; responsible for mapping &#039;&#039;command strings&#039;&#039; to different &#039;&#039;MIDI messages&#039;&#039; is &amp;quot;midieventhandler&amp;quot; or &amp;quot;mev&amp;quot; for short. The first &#039;&#039;parameter&#039;&#039; of &amp;quot;mev&amp;quot; is the type of &#039;&#039;MIDI message&#039;&#039; that we want to remap;&lt;br /&gt;
 &lt;br /&gt;
 * &#039;&#039;&#039;noteon&#039;&#039;&#039; - Note on&lt;br /&gt;
 * &#039;&#039;&#039;noteoff&#039;&#039;&#039; - Note off&lt;br /&gt;
 * &#039;&#039;&#039;pat&#039;&#039;&#039; - Poly after touch&lt;br /&gt;
 * &#039;&#039;&#039;cat&#039;&#039;&#039; - Channel after touch&lt;br /&gt;
 * &#039;&#039;&#039;pb&#039;&#039;&#039; - Pitch bend&lt;br /&gt;
 * &#039;&#039;&#039;pc&#039;&#039;&#039; - Program change&lt;br /&gt;
 * &#039;&#039;&#039;cc&#039;&#039;&#039; - Continuous controller&lt;br /&gt;
 &lt;br /&gt;
 The second &#039;&#039;parameter&#039;&#039; is the &#039;&#039;command string&#039;&#039; that is to be associated with the &#039;&#039;MIDI Message&#039;&#039; - with the exception of the &#039;&#039;&#039;cc&#039;&#039;&#039;-type, here the second &#039;&#039;parameter&#039;&#039; is the &#039;&#039;controller number&#039;&#039; (0 - 127) and the third &#039;&#039;parameter&#039;&#039; is the &#039;&#039;command string&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;FAR 1.1&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 The &amp;quot;bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; contains a &#039;&#039;module&#039;&#039; called &amp;quot;midiconfigurationhandler&amp;quot; that handles the loading and switching in between different &#039;&#039;MIDI configurations&#039;&#039;. The &amp;quot;midiconfigurationhandler&amp;quot;&#039;&#039;-module&#039;&#039; has one or more &#039;&#039;&amp;quot;&#039;&#039;midiconfiguration&amp;quot;-&#039;&#039;modules&#039;&#039;, each having its own &#039;&#039;MIDI&#039;&#039; settings. In order to change the &#039;&#039;command mapping&#039;&#039; for a &#039;&#039;MIDI message&#039;&#039; in a specific &#039;&#039;MIDI configuration&#039;&#039;, the following &#039;&#039;commands&#039;&#039; are used;&lt;br /&gt;
 &lt;br /&gt;
 * &#039;&#039;&#039;noteon/non&#039;&#039;&#039;:&#039;&#039;commands&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed for a &#039;note on&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;noteoff/nof&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;note off&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;polyaftertouch/pat&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;poly aftertouch&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;channelaftertouch/cat&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;channel aftertouch&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;pitchbend/pb&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;pitch bend&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;programchange/pc&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;program change&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;continuouscontrollerdata/ccd&#039;&#039;&#039;&#039;&#039;:controller:commands&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed for &#039;continuous controller&#039; no &#039;&#039;controller&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
We can of course use the &#039;&#039;&amp;quot;&#039;&#039;rqi&amp;quot;-&#039;&#039;command&#039;&#039; to check the current mapping, below we are asking what the current &#039;&#039;command string&#039;&#039; associated with the &#039;&#039;pitch bend&#039;&#039; &#039;&#039;MIDI message&#039;&#039; is in the currently selected &#039;&#039;MIDI configuration&#039;&#039;.&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
rqi:midieventhandler:pb&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
rqi:bowingwheel.midiconfigurationhandler.midiconfiguration.pitchbend&lt;br /&gt;
&amp;lt;/pre&amp;gt;This may return something like&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
[irq]mev:pb:&amp;quot;bowcontrolharmonicshift:pitch*4&amp;quot;&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
[irq]bw[0].mcf[0].mc[0].pb:&amp;quot;bowingwheel.harmonicserieshandler.harmonicseries.shift:pitch*4&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;The first part of the return message tells us that the incoming message is of &amp;quot;rqi&amp;quot;-type (&amp;quot;[irq]&amp;quot;) which means it&#039;s responding to a information request &#039;&#039;command&#039;&#039; sent. The second part tells us what &#039;&#039;command&#039;&#039; the information request return is responding to and any &#039;&#039;parameters&#039;&#039; that may be pertinent. The third part of the message is the actual data stored.  &lt;br /&gt;
&lt;br /&gt;
For the FAR &amp;lt; 1.1 the data returned is for the &#039;&#039;command&#039;&#039; &amp;quot;mev&amp;quot; with the first &#039;&#039;parameter&#039;&#039; set to &amp;quot;pb&amp;quot;, the &#039;&#039;command reference&#039;&#039; tells us this means the &#039;&#039;command&#039;&#039; &amp;quot;midieventhandler&amp;quot; and the &#039;&#039;parameter&#039;&#039; &amp;quot;pb&amp;quot; indicates this has to do with the &#039;&#039;pitch bend&#039;&#039;. The data is &amp;quot;bowcontrolharmonicshift:pitch*4&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
For the FAR 1.1 the data returned is for the &#039;&#039;command&#039;&#039; &amp;quot;bw[0].mcf[0].mc[0].pb&amp;quot; (bowinwheel[0].midiconfigurationhandler[0].midiconfiguration[0].pitchbend) and the data is &amp;quot;bowingwheel.harmonicserieshandler.harmonicseries.shift:pitch*4&amp;quot;. Note here that if we have several different &#039;&#039;MIDI configurations&#039;&#039; stored and we&#039;re currently using configuration number 2, the returned message would have been &amp;quot;bw[0].mcf[0].mc[2].pb&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
that the &#039;&#039;pitch bend MIDI message&#039;&#039; is executing a &amp;quot;bowcontrolharmonicshift&amp;quot; / &amp;quot;harmonicseries.shift&amp;quot;-command with the parameter &#039;&#039;pitch*4&#039;&#039;. Looking in the &#039;&#039;command reference&#039;&#039; we can see that &#039;&#039;&amp;quot;&#039;&#039;bowcontrolharmonicshift&amp;quot; / &amp;quot;harmonicseries.shift&amp;quot;-&#039;&#039;command&#039;&#039; shifts the frequency of the &#039;&#039;bowing wheel&#039;&#039; from the currently selected harmonic. The first (and only) &#039;&#039;parameter&#039;&#039; sets how much we want to shift it (the range depends on the &amp;quot;bowcontrolharmonicshiftrange&#039;&#039;&amp;quot;&#039;&#039; / &amp;quot;harmonicseries.shiftrange&amp;quot;-&#039;&#039;command&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
If we look in the list of &#039;&#039;[[The Ekdahl FAR - Command langue#Variables|variables]]&#039;&#039; above we can see that the &#039;&#039;pitch bend MIDI message&#039;&#039; will set the &amp;quot;pitch&amp;quot;&#039;&#039;-variable&#039;&#039; which is indeed used. Now what is the &#039;&#039;&#039;*4&#039;&#039;&amp;lt;nowiki/&amp;gt;&#039; all about? Well the &amp;quot;bowcontrolharmonicshift&amp;quot; / &amp;quot;harmoniceseries.shift&amp;quot;-&#039;&#039;command&#039;&#039; expects a &#039;&#039;16-bit signed&#039;&#039; value as its &#039;&#039;parameter&#039;&#039;. This means that the valid &#039;&#039;parameter&#039;&#039; number can be anything from -32767 to 32767. A full &#039;&#039;harmonic shift&#039;&#039; downwards according to the range set is equal to -32767, a full &#039;&#039;harmonic shift&#039;&#039; upwards is 32767 and no &#039;&#039;harmonic shift&#039;&#039; is 0. The &#039;&#039;pitch bend MIDI message&#039;&#039; however is only 14-bits, meaning its range is -8192 to 8192. So we have to multiply &#039;&#039;pitch&#039;&#039; by 4 in order to meet the requirements of a &#039;&#039;16-bit signed parameter&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
This whole thing about number of bits can seem confusing but in the end it&#039;s all about how fine control you have over things; the more possible values, the more detailed control. In fact, most &#039;&#039;MIDI&#039;&#039; values are only 7-bit (!) meaning a range of 0 - 127. While this may sound like a lot of detail for something like a volume control, it is not even close to enough resolution to for instance set the &#039;&#039;bowing frequency&#039;&#039;. Even if you would limit yourself to a single octave the instrument would never be able to be properly in tune. The idea of limiting the Ekdahl FAR to what is possible through &#039;&#039;MIDI&#039;&#039; seemed like a poor choice thus it was decided that &amp;lt;u&amp;gt;most&amp;lt;/u&amp;gt; parameters will instead be 16-bit.&lt;br /&gt;
&lt;br /&gt;
Now lets look at a more complex example, the &amp;lt;u&amp;gt;default&amp;lt;/u&amp;gt; &#039;&#039;Note On MIDI message&#039;&#039;. On a stock Ekdahl FAR, executing&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
rqi:mev:noteon&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
rqi:mcf.mf.non&lt;br /&gt;
&amp;lt;/pre&amp;gt;Will return something like&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
[irq]mev:noteon:&#039;bchb:note,bmr:1,bpid:1,bpe:1,se:(velocity*512)*(1-notecount),bcsm:0&#039;&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
[irq]mcf[0].mc[0].non:&#039;bw.hsh.hb:note,bw.dcm.ru:1,bw.pe:1,bw.bp.en:1,so.en:(velocity*512)*(1-notecount),bw.sm:0&#039;&amp;lt;/pre&amp;gt;As can be seen, there&#039;s a lot of stuff going on here! First of all, notice that everything after &amp;quot;mev:noteon:&amp;quot; / &amp;quot;mcf[0].mc[0].non:&amp;quot; is situated in between single quotes (&#039;) - this is &amp;lt;u&amp;gt;absolutely crucial&amp;lt;/u&amp;gt; for the Ekdahl FAR in order to know that everything within those last two quotes is part of the last &#039;&#039;parameter&#039;&#039; of the &amp;quot;mev&amp;quot; / &amp;quot;mcf.mc.non&amp;quot;-&#039;&#039;command&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Now let&#039;s break down what happens when this &#039;&#039;MIDI message&#039;&#039; is received, i.e. when a &#039;&#039;MIDI&#039;&#039; key is pressed down:&lt;br /&gt;
&lt;br /&gt;
# &amp;quot;bchb:note&amp;quot; / &amp;quot;bw.hsh.hb:note&amp;quot;  - Invokes the &amp;quot;bowcontrolharmonicbase&amp;quot; / &amp;quot;harmonicserieshandler.harmonicbase&amp;quot;&#039;&#039;-command&#039;&#039; with the first &#039;&#039;parameter&#039;&#039; set to the &#039;&#039;variable &amp;quot;&#039;&#039;note&amp;quot;. This sets the &#039;&#039;base harmonic&#039;&#039; that the Ekdahl FARs &#039;&#039;bowing motor&#039;&#039; should be set to. Here the &#039;&#039;variable&#039;&#039; &amp;quot;note&amp;quot; is used which is simply the MIDI key being pressed down, it is automatically converted by the &#039;&#039;command&#039;&#039; to the corresponding harmonic in the &#039;&#039;harmonic list&#039;&#039;&lt;br /&gt;
# &amp;quot;bmr:1&amp;quot; / &amp;quot;bw.dcm.ru&amp;quot; - Sets the &amp;quot;bowmotorrun&amp;quot; / &amp;quot;dcmotor.run&amp;quot;-command to &#039;1&#039;, starting the &#039;&#039;bow motor&#039;&#039;&lt;br /&gt;
# &amp;quot;bpid:1&amp;quot; / &amp;quot;bw.pe:1&amp;quot; - Sets the &amp;quot;bowpid&amp;quot; / &amp;quot;bowingwheel.pidenable&amp;quot;-&#039;&#039;command&#039;&#039; to &#039;1&#039;. Basically this enables the function that makes the Ekdahl FAR able to keep a stable frequency on the &#039;&#039;bowing motor&#039;&#039;.&lt;br /&gt;
# &amp;quot;bpe:1&amp;quot; / &amp;quot;bw.bp.en&amp;quot; - Sets the &amp;quot;bowpressureengage&amp;quot; / &amp;quot;bowpressure.engage&amp;quot;-&#039;&#039;command&#039;&#039; to &#039;1&#039; which moves the &#039;&#039;bowing jack&#039;&#039; to the &#039;&#039;engage position&#039;&#039;, aka just below the string if not additional &#039;&#039;pressure&#039;&#039; is applied&lt;br /&gt;
# &amp;quot;se:(velocity*512)*(1-notecount)&amp;quot; / &amp;quot;so.en:(velocity*512)*(1-notecount)&amp;quot; - Executes the &amp;quot;solenoidengage&amp;quot; / &amp;quot;solenoid.engage&amp;quot;-&#039;&#039;command&#039;&#039; with the value &#039;&#039;(velocity*512)*(1-notecount)&#039;&#039;. This will make the &#039;&#039;solenoid&#039;&#039; strike the &#039;&#039;hammer&#039;&#039; with a force that is dependent on the &amp;quot;velocity&amp;quot;-&#039;&#039;variable&#039;&#039; sent by the &#039;&#039;Note On MIDI message&#039;&#039; in order to make the &#039;&#039;hammer&#039;&#039; velocity sensitive.   But it also adds the somewhat perplexing part &amp;quot;*(1-notecount)&amp;quot;. &amp;quot;notecount&amp;quot; is a global &#039;&#039;variable&#039;&#039; that contains the number of MIDI keys that are currently being held down. If &amp;quot;notecount&amp;quot; is anything above zero, the outcome of the equation will either be zero or a negative number. The &amp;quot;solenoidengage&amp;quot; / &amp;quot;solenoid.engage&amp;quot;-&#039;&#039;command&#039;&#039; requires a &#039;&#039;16-bit unsigned&#039;&#039; value, aka the only valid numbers are 0 - 65535. Anything below 0 will be interpreted as zero, so what this equation does is that it only fires off the &#039;&#039;hammer&#039;&#039; if there are no previous keys being held down - it&#039;s being used in &#039;&#039;staccato&#039;&#039;  mode.&lt;br /&gt;
# &amp;quot;bcsm:0&amp;quot; / &amp;quot;bowingwheel.speedmode&amp;quot; - Sets the &amp;quot;bowcontrolspeedmode&amp;quot; / &amp;quot;bowingwheel.speedmode&amp;quot; to &#039;1&#039; which enables automatic shut down of the &#039;&#039;bowing motor&#039;&#039; after a given timeout.&lt;br /&gt;
Let&#039;s postulate that the Ekdahl FAR is tuned to a &#039;C&#039; at 65.4Hz and has its &#039;&#039;base&#039;&#039; set to middle &#039;C&#039; (&#039;&#039;MIDI key&#039;&#039; no 36). We are using the equal-temperament 12-tone scale and the Ekdahl FAR is set to respond to &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; &#039;&#039;MIDI channels&#039;&#039; (omni). Without having previously held any keys we press the middle &#039;C&#039; (&#039;&#039;note&#039;&#039; value 36) as hard as possible (&#039;&#039;velocity&#039;&#039; value &#039;&#039;127&#039;&#039;) on &#039;&#039;MIDI channel&#039;&#039; number 1 (&#039;&#039;channel&#039;&#039; value of 0). The Ekdahl FAR will get a &#039;&#039;note on MIDI message&#039;&#039; sent to it and from our mapping it will create the following &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
[irq]mev:noteon:&#039;bchb:36,bmr:1,bpid:1,bpe:1,se:(127*512)*(1-0),bcsm:0&#039;&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
[irq]mcf[0].mc[0].non:&#039;bw.hsh.hb:36,bw.dcm.ru:1,bw.pe:1,bw.bp.en:1,so.en:(127*512)*(1-0),bw.sm:0&#039;&amp;lt;/pre&amp;gt;What has happened here is that all &#039;&#039;variables&#039;&#039; have been replaced with the values sent by the &#039;&#039;MIDI message&#039;&#039;. Since those &#039;&#039;commands&#039;&#039; that doesn&#039;t have any &#039;&#039;variables&#039;&#039; with them will execute just as previously, only those &#039;&#039;commands&#039;&#039; whos &#039;&#039;parameters&#039;&#039; have changed will be explained:&lt;br /&gt;
&lt;br /&gt;
# &amp;quot;bchb: 36&amp;quot; / &amp;quot;bw.hsh.hb:36&amp;quot; - The &amp;quot;bowcontrolharmonicbase&amp;quot; / &amp;quot;harmonicserieshandler.harmonicbase&amp;quot; gets a value of &#039;&#039;36&#039;&#039; (middle &#039;C&#039;), because &#039;&#039;harmonic number 0&#039;&#039; is mapped to this key it will set the &#039;&#039;bowing wheel&#039;&#039; frequency to the &#039;&#039;fundamental&#039;&#039;; &#039;&#039;65.4&#039;&#039; Hertz&lt;br /&gt;
# &amp;quot;se: (127*512)*(1-0)&amp;quot; / &amp;quot;so.en: (127*512)*(1-0)&amp;quot; - the value of &#039;&#039;127&#039;&#039; comes from the &amp;quot;velocity&amp;quot;-&#039;&#039;variable&#039;&#039;, &#039;&#039;127 * 512 = 65024&#039;&#039; which is awfully close to a maximum hammer force of 65535. Since no previous notes were held down, the &#039;&#039;&amp;quot;&#039;&#039;notecount&amp;quot;-&#039;&#039;variable&#039;&#039;  is equal to &#039;&#039;0&#039;&#039; and thus &#039;&#039;65024 * 1 = 65024&#039;&#039;. The hammer is engaged with near maximum force.&lt;br /&gt;
So the result is that we have set the speed of the &#039;&#039;bowing motor&#039;&#039; and we have engaged the &#039;&#039;hammer&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Now imagine that without releasing this key, we press another &#039;C&#039; one octave above but at half the velocity. The Ekdahl FAR creates the following &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
[irq]mev:noteon:&#039;bchb:48,bmr:1,bpid:1,bpe:1,se:(63*512)*(1-1),bcsm:0&#039;&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
[irq]mcf[0].mc[0].non:&#039;bw.hsh.hb:48,bw.dcm.ru:1,bw.pe:1,bw.bp.en:1,so.en:(65*512)*(1-1),bw.sm:0&#039;&lt;br /&gt;
&amp;lt;/pre&amp;gt;Now we can see that the &amp;quot;note&amp;quot;-&#039;&#039;variable&#039;&#039; is 48 because the &#039;C&#039; one octave up is exactly 12 keys above the first. The &amp;quot;velocity&amp;quot;-&#039;&#039;variable&#039;&#039; has changed to 63 since we hit it with a lighter touch - and because we are &amp;lt;u&amp;gt;still holding the first key down&amp;lt;/u&amp;gt;, the &amp;quot;notecount&amp;quot;-&#039;&#039;variable&#039;&#039; is equal to &#039;&#039;1&#039;&#039;. Here&#039;s what happens&lt;br /&gt;
&lt;br /&gt;
# &amp;quot;bchb: 48&amp;quot; / &amp;quot;hsh.hb:48&amp;quot; - Due to the &#039;&#039;base&#039;&#039; being set to &#039;&#039;36&#039;&#039; the &#039;&#039;harmonic number&#039;&#039; is set to &#039;&#039;48 - 36 = 12&#039;&#039;. Because we are using a 12-tone scale &#039;&#039;harmonic number 12&#039;&#039; is exactly one octave above the &#039;&#039;fundamental&#039;&#039; thus the speed of the &#039;&#039;bowing wheel&#039;&#039; is set to &#039;&#039;65.4 * 2 = 130.8&#039;&#039; Hertz.&lt;br /&gt;
# &amp;quot;se: (63*512)*(1-1)&amp;quot; / &amp;quot;so.en: (63*512)*(1-1)&amp;quot; - The equation evalutes as &#039;&#039;63 * 512 = 32256&#039;&#039; and &#039;&#039;1 - 1 = 0&#039;&#039; thus &#039;&#039;32256 * 0 = 0&#039;&#039;. When the &amp;quot;solenoidengage&amp;quot; / &amp;quot;solenoid.engage&amp;quot;-&#039;&#039;command&#039;&#039; gets a &#039;&#039;parameter&#039;&#039; of &#039;&#039;0&#039;&#039; it will not engage the &#039;&#039;hammer&#039;&#039; - so the &#039;&#039;hammer&#039;&#039; doesn&#039;t strike&lt;br /&gt;
So it can be seen that with quite rudimentary math we can accomplish a whole lot of things here. Note also that even though the &#039;&#039;note on MIDI message&#039;&#039; also sets the &#039;&#039;channel&#039;&#039;-variable we never use it in this example - plenty of opportunity to make something weird happen depending on the &#039;&#039;MIDI channel&#039;&#039;!&lt;br /&gt;
&lt;br /&gt;
== CV Mapping ==&lt;br /&gt;
&#039;&#039;CV Mapping&#039;&#039; works exactly like the &#039;&#039;MIDI mapping&#039;&#039; with the difference that the command for setting the &#039;&#039;CV mapping&#039;&#039; is different and that &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; events pertaining to this &amp;lt;u&amp;gt;only&amp;lt;/u&amp;gt; change the &#039;&#039;value&#039;&#039;-variable. The &#039;&#039;command&#039;&#039; for changing the &#039;&#039;CV mapping&#039;&#039; is &#039;&#039;adccommandmap&#039;&#039; or &#039;&#039;acm&#039;&#039;, it take two &#039;&#039;parameters&#039;&#039;; &#039;&#039;channel&#039;&#039; and &#039;&#039;command string&#039;&#039;. We retrieve the &#039;&#039;command string&#039;&#039; for channel &#039;&#039;0&#039;&#039; which reads the sum of the &#039;&#039;harm. v/oct&#039;&#039;-jack and the &#039;&#039;harmonic&#039;&#039;-knob by sending a command of&amp;lt;pre&amp;gt;&lt;br /&gt;
rqi:acm:0&lt;br /&gt;
&amp;lt;/pre&amp;gt;The &amp;lt;u&amp;gt;default&amp;lt;/u&amp;gt; response will be something like&lt;br /&gt;
&amp;lt;pre&amp;gt;[irq]acm:0:&#039;bcha:value/1327.716667-20&#039;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{docnav&lt;br /&gt;
|[[The Ekdahl FAR - Service|Service]]&lt;br /&gt;
|[[The Ekdahl FAR - Command reference|Command reference]]&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Knaadmin</name></author>
	</entry>
	<entry>
		<id>http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_language&amp;diff=1655</id>
		<title>The Ekdahl FAR - Command language</title>
		<link rel="alternate" type="text/html" href="http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_language&amp;diff=1655"/>
		<updated>2026-06-10T18:05:36Z</updated>

		<summary type="html">&lt;p&gt;Knaadmin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Command language ==&lt;br /&gt;
The Ekdahl FAR is entirely controlled by &#039;&#039;commands&#039;&#039;, these &#039;&#039;commands&#039;&#039; decide everything that the instrument is doing, whether it is playing a melody or changing an internal parameter. &lt;br /&gt;
&lt;br /&gt;
When a &#039;&#039;MIDI message&#039;&#039; is received or a new CV / knob value is read, the &#039;&#039;commands&#039;&#039; associated with it will be internally sent. This can be things like &amp;quot;engage hammer&amp;quot; or &amp;quot;set the fundamental frequency&amp;quot; etc. &lt;br /&gt;
&lt;br /&gt;
Some of the available &#039;&#039;commands&#039;&#039; are mainly used for calibrating and setting up the instrument and are usually saved into the instruments memory, these will be executed whenever the instrument is turned on. &lt;br /&gt;
&lt;br /&gt;
All &#039;&#039;commands&#039;&#039; can be manually invoked via &#039;&#039;USB-Serial&#039;&#039;, in conjunction with certain software this presents an unprecedented level of control and sequenceability.&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
The &#039;&#039;commands&#039;&#039; are invoked using a &#039;&#039;plain text approach&#039;&#039;, all commands have both a &#039;&#039;long name&#039;&#039; and a &#039;&#039;short name&#039;&#039; which are interchangeable. A &#039;&#039;command&#039;&#039; may have one or more &#039;&#039;parameters&#039;&#039; associated with it, these &#039;&#039;parameters&#039;&#039; can be of different types; 16-bit numbers (values 0 - 65535 or -32767 - 32767), floating point numbers (values with decimals), booleans (0 for &#039;false&#039;, 1 for &#039;true&#039;) and strings (text). Some commands are &#039;&#039;conditional&#039;&#039;, meaning they will only execute if a parameter equates to &#039;1&#039; (&#039;true&#039;). &lt;br /&gt;
&lt;br /&gt;
The way &#039;&#039;commands&#039;&#039; are written in order to be executed is &#039;&#039;commandname:parameter1:parameter2:parameter3 [etc]&#039;&#039;, several commands be executed in sequence by separating them with a comma (&#039;,&#039;), a bunch of commands strung together is called a &#039;&#039;command string&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Since version 1.1 of the Ekdahl FAR Firmware, all commands are grouped in a hierarchical fashion according to their &#039;&#039;modules&#039;&#039; and each ladder in the hierarchy is separated by a period (&amp;quot;.&amp;quot;), this works very much like folders or directories in a regular computer. Every &#039;&#039;module&#039;&#039; can contain both &#039;&#039;commands&#039;&#039; and other &#039;&#039;modules&#039;&#039;. For instance, everything associated with the &#039;&#039;bowing wheel&#039;&#039; is now collected under &amp;quot;bowingwheel&amp;quot; &#039;&#039;module&#039;&#039;. That in turn contains a &amp;quot;dcmotor&amp;quot; &#039;&#039;module&#039;&#039; which handles direct control of the bowing motor. It also has a &amp;quot;pid&amp;quot; &#039;&#039;module&#039;&#039; that handles bow frequency among other thing. &lt;br /&gt;
&lt;br /&gt;
If for instance we would like to start the &#039;&#039;bowing wheel&#039;&#039; and set its frequency to 82.5 Hertz we could send the Ekdahl FAR the following &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
bowmotorrun:1, bowcontrolfrequecy:82.5&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bowingwheel.dcmotor.run:1, bowingwheel.pid.targetfrequency:82.5&amp;lt;/pre&amp;gt;We could also use the &#039;&#039;short names&#039;&#039; for the commands&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
bmr:1,bcf:82.5&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bw.dcm.ru:1, bw.pid.tf:82.5&amp;lt;/pre&amp;gt;Both &amp;quot;bowmotorrun&amp;quot; / &amp;quot;bowingwheel.dcmotor.run&amp;quot; and &amp;quot;bowcontrolfrequency&amp;quot; / &amp;quot;bowingwheel.pid.targetfrequency&amp;quot; takes one &#039;&#039;parameter&#039;&#039; each, &#039;&#039;&amp;quot;&#039;&#039;bowmotorrun&amp;quot; / &amp;quot;bowingwheel.dcmotor.run&amp;quot; is &#039;&#039;conditional&#039;&#039; and unless the first &#039;&#039;parameter&#039;&#039; is equal to &#039;1&#039; the motor will not start. The first &#039;&#039;parameter&#039;&#039; of &amp;quot;bowcontrolfrequency&amp;quot; / &amp;quot;bowingwheel.pid.targetfrequency&amp;quot; sets the frequency of the &#039;&#039;bowing wheel&#039;&#039;, the instrument may not execute a &#039;&#039;command&#039;&#039; if it decides that the given &#039;&#039;parameters&#039;&#039; are outside of the working range or they are missing.&lt;br /&gt;
&lt;br /&gt;
The addition of the hierarchy in the FAR 1.1 firmware isn&#039;t just to be able to group commands, but it&#039;s also to make the FAR not limited to a single set of &#039;&#039;modules&#039;&#039; (and is the first stepping stone to a &#039;&#039;modular&#039;&#039; Ekdahl FAR). In fact, you could have 12 different bowing wheel &#039;&#039;modules&#039;&#039; for 12 different strings, these would then be addressed as &amp;quot;bowingwheel[0].command&amp;quot;&#039;&#039;, &amp;quot;&#039;&#039;bowingwheel[1].command&amp;quot; etc. Anyone familiar with C programming notices that this is the standard way of &#039;&#039;indexing&#039;&#039; an array; using brackets (&amp;quot;[ ]&amp;quot;). When addressing a module without &#039;&#039;indexing&#039;&#039; as in the example above, the FAR will do one or two things; either use the first object (&amp;quot;[0]&amp;quot;) or, if the object is &#039;&#039;selectable&#039;&#039; it will use the previously selected object. To make things smoother a command can be executed on several objects at once by using ranges (&amp;quot;[0-4]&amp;quot;) and comma separation (&amp;quot;[0, 3, 5-6]&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
To test out a &#039;&#039;command&#039;&#039; you can send it directly to the Ekdahl FAR using the &#039;&#039;Console&#039;&#039; in the &#039;&#039;Configuration utility&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
To read up on existing &#039;&#039;commands&#039;&#039;, their &#039;&#039;parameters&#039;&#039; and a brief description you can check the &#039;&#039;Command reference&#039;&#039; in the &#039;&#039;Configuration utility&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Variables, functions and equations ==&lt;br /&gt;
What makes the &#039;&#039;Command language&#039;&#039; truly powerful is the concept of &#039;&#039;variables, functions&#039;&#039; and &#039;&#039;equations&#039;&#039;. All &#039;&#039;parameters&#039;&#039; that take numerical values can use any combination of &#039;&#039;variables, functions&#039;&#039; or &#039;&#039;equations.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
For instance, we can use the previous example and instead write our &#039;&#039;command string&#039;&#039; as follows&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
bowmotorrun:1, bowcontrolfrequency:82.5+note*20&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bowingwheel.dcmotor.run:1, bowingwheel.pid.targetfrequency:82.5+note*20&amp;lt;/pre&amp;gt;This example requires of course that the &#039;&#039;variable&#039;&#039; &#039;&#039;note&#039;&#039; exists in the current context. &lt;br /&gt;
&lt;br /&gt;
===== Variables =====&lt;br /&gt;
There are two types of &#039;&#039;variables&#039;&#039; in the Ekdahl FAR; &#039;&#039;global variables&#039;&#039; and &#039;&#039;event variables&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Global variables&#039;&#039; are variables that are always valid, in any context. The &#039;&#039;global variables&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;notecount&#039;&#039;&#039; - Contains the number of &#039;&#039;MIDI&#039;&#039; keys that are being held down, i.e. all &#039;&#039;Note on messages&#039;&#039; received that haven&#039;t gotten a paired &#039;&#039;Note off message&#039;&#039; yet&lt;br /&gt;
* &#039;&#039;&#039;uv0&#039;&#039;&#039; - &#039;&#039;&#039;uv9&#039;&#039;&#039; - These are &#039;&#039;user variables&#039;&#039; and can be set at any point using the &#039;&#039;globaluservariable command&#039;&#039; with the first &#039;&#039;parameter&#039;&#039; being which variable to set (0-9) and the second &#039;&#039;parameter&#039;&#039; being the value (float).&lt;br /&gt;
* &#039;&#039;&#039;e&#039;&#039;&#039; - Contains the constant &#039;&#039;[[wikipedia:E_(mathematical_constant)|e]]&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pi&#039;&#039;&#039; - Contains the constant &#039;&#039;[[wikipedia:Pi|pi]]&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Event variables&#039;&#039; are variables that are set by certain &#039;&#039;MIDI messages&#039;&#039; or when a new value is read on one of the jacks or knobs on the &#039;&#039;Control box&#039;&#039;. The &#039;&#039;Event variables&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;channel&#039;&#039;&#039; - Set by the &#039;&#039;Note on, Note off, Continuous Controller, Poly after touch, Pitch bend, Channel after touch&#039;&#039; and &#039;&#039;Program change MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;note&#039;&#039;&#039; - Set by the &#039;&#039;Note on, Note off&#039;&#039; and &#039;&#039;Poly after touch MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;velocity&#039;&#039;&#039; - Set by the &#039;&#039;Note on&#039;&#039; and &#039;&#039;Note off MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pressure&#039;&#039;&#039; - Set by the &#039;&#039;Poly after touch&#039;&#039; and &#039;&#039;Channel after touch MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; - Set by the &#039;&#039;Continuous Controller MIDI message&#039;&#039; and by the &#039;&#039;Control box&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pitch&#039;&#039;&#039; - Set by the &#039;&#039;Pitch bend MIDI message&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;program&#039;&#039;&#039; - Set by the &#039;&#039;Program change MIDI message&#039;&#039;&lt;br /&gt;
These variables will contain whatever data is relevant to the last event that occurred and may be overwritten by the next event.&lt;br /&gt;
&lt;br /&gt;
===== Functions =====&lt;br /&gt;
&#039;&#039;Functions&#039;&#039; can be used to change a numerical value or the result of an &#039;&#039;equation&#039;&#039;, the Ekdahl FAR contains both general &#039;&#039;arithmetic functions&#039;&#039; (courtesy of Lewis Van Winkle and the TINYEXPR engine) and &#039;&#039;specialized functions&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;arithmetic functions&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;abs&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Absolute_value|absolute value]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;acos&#039;&#039;&#039;(x), &#039;&#039;&#039;asin&#039;&#039;&#039;(x), &#039;&#039;&#039;atan&#039;&#039;&#039;(x), atan2(x, y) - Returns the [[wikipedia:Inverse_trigonometric_functions|&#039;&#039;arc-cos, -sin, -tan&#039;&#039; and &#039;&#039;-tan2&#039;&#039;]] of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;atan2&#039;&#039;&#039;(x,y) - Returns the &#039;&#039;[[wikipedia:Atan2|arctan2]]&#039;&#039; of &#039;&#039;x, y&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;floor&#039;&#039;&#039;(x), ceil(x) - Returns the [[wikipedia:Floor_and_ceiling_functions|&#039;&#039;floor&#039;&#039; and &#039;&#039;ceiling&#039;&#039;]] of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;exp&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Exponential_function|exponent]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;fac&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Factorial|factorial]]&#039;&#039; of x&lt;br /&gt;
* &#039;&#039;&#039;ln&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Natural_logarithm|natural logarithm]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;log10&#039;&#039;&#039;(x), &#039;&#039;&#039;log20&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Logarithm|logarithm]]&#039;&#039; of &#039;&#039;x&#039;&#039; using base 10 and 20 respectively&lt;br /&gt;
* &#039;&#039;&#039;ncr&#039;&#039;&#039;(x,y), &#039;&#039;&#039;npr&#039;&#039;&#039;(x,y) - Functions to calculate &#039;&#039;[[wikipedia:Combination|combinations]]&#039;&#039; and &#039;&#039;[[wikipedia:Permutation|permutations]]&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pow&#039;&#039;&#039;(x,y) - Returns &#039;&#039;x^y&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;sqrt&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Square_root|square root]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;cos&#039;&#039;&#039;(x), &#039;&#039;&#039;sin&#039;&#039;&#039;(x), &#039;&#039;&#039;tan&#039;&#039;&#039;(x) - Returns the [[wikipedia:Trigonometric_functions|&#039;&#039;cos, sin&#039;&#039; and &#039;&#039;tan&#039;&#039;]] of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;cosh&#039;&#039;&#039;(x), &#039;&#039;&#039;sinh&#039;&#039;&#039;(x), &#039;&#039;&#039;tanh&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Hyperbolic_functions|hyperbolic cos, sin and tan]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
The &#039;&#039;specialized functions&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;bool&#039;&#039;&#039;(x) - Returns 1 if &#039;&#039;x&#039;&#039; is more than 0&lt;br /&gt;
* &#039;&#039;&#039;ibool&#039;&#039;&#039;(x) - Returns 0 if &#039;&#039;x&#039;&#039; is more than 0&lt;br /&gt;
* &#039;&#039;&#039;deadband&#039;&#039;&#039;(x,y) - Returns &#039;&#039;x + y &#039;&#039; if &#039;&#039;x &amp;lt; y&#039;&#039; or &#039;&#039;x - y&#039;&#039; if &#039;&#039;x &amp;gt; y&#039;&#039;. If neither of these statements is true it returns &#039;&#039;0&#039;&#039; - used to create a [[wikipedia:Deadband|deadband]] of &#039;&#039;x&#039;&#039; with the threshold of &#039;&#039;y&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Functions&#039;&#039; can be readily used in a &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
bowmotorrun:1, bowcontrolfrequency:&amp;quot;8.17579875 * pow(2, (1/12 * note))&amp;quot;&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bowingwheel.dcmotor.run:1, bowingwheel.pid.targetfrequency:&amp;quot;8.17579875 * pow(2, (1/12 * note))&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;The previous statements starts the &#039;&#039;bowing wheel&#039;&#039; and sets the frequency of the wheel to &#039;&#039;8.17579875 * 2^(1/12 * note)&#039;&#039;. A middle &#039;C&#039; according to &#039;&#039;MIDI&#039;&#039; has a &#039;&#039;note value&#039;&#039; of 36, meaning if we substitute &#039;&#039;note&#039;&#039; with 36 we get the equation &#039;&#039;8.17579875 * 2^(1/12 * 36)&#039;&#039; which comes out to &#039;&#039;~65.4&#039;&#039; Hertz.&lt;br /&gt;
&lt;br /&gt;
Note that the first &#039;&#039;parameter&#039;&#039; for &#039;&#039;&amp;quot;&#039;&#039;bowcontrolfrequency&amp;quot; / &amp;quot;bowingwheel.pid.targetfrequency&amp;quot; is put in between double quotes (&amp;quot;). This is because the &amp;quot;pow&#039;&#039;&amp;quot;-&#039;&#039;function requires the use of a comma (&amp;quot;,&amp;quot;) in order to separate in between its two required inputs; &#039;&#039;x&#039;&#039; and &#039;&#039;y&#039;&#039;. In order for the Ekdahl FAR to know that this comma does not signal the beginning of a new &#039;&#039;command,&#039;&#039; we use quotes. Single (&#039;) and double (&amp;quot;) quotes can be used and nested in all &#039;&#039;parameters&#039;&#039; and are &amp;lt;u&amp;gt;required&amp;lt;/u&amp;gt; in a lot of circumstances, improper nesting or not using quotes can lead to the instrument not understanding the &#039;&#039;command string&#039;&#039; correctly.&lt;br /&gt;
&lt;br /&gt;
== Return messages ==&lt;br /&gt;
The Ekdahl FAR when connected via &#039;&#039;USB-Serial&#039;&#039; doesn&#039;t only accept &#039;&#039;commands&#039;&#039; but will also send various &#039;&#039;return messages&#039;&#039;. These are prefixed by their &#039;&#039;category&#039;&#039; denoted in brackets (&amp;quot;[]&amp;quot;), the existing categories as of this writing (2025-01-22) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;command&#039;&#039;&#039; / &#039;&#039;&#039;cmd&#039;&#039;&#039; - Acknowledges the reception of a command in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;usb&#039;&#039;&#039; - Acknowledges the reception of a &#039;&#039;MIDI message&#039;&#039; over &#039;&#039;USB&#039;&#039; in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;hardware&#039;&#039;&#039; / &#039;&#039;&#039;hw&#039;&#039;&#039; - Signals that a change has been sent to the Ekdahl FAR hardware, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;undefined&#039;&#039;&#039; / &#039;&#039;&#039;un&#039;&#039;&#039; - The message sent is in the &#039;&#039;undefined&#039;&#039; category, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;priority&#039;&#039;&#039; / &#039;&#039;&#039;pri&#039;&#039;&#039; - The message sent is in the &#039;&#039;priority&#039;&#039; category, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;error&#039;&#039;&#039; / &#039;&#039;&#039;err&#039;&#039;&#039; - Signals that an &#039;&#039;error&#039;&#039; has occurred, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;expressionparser&#039;&#039;&#039; / &#039;&#039;&#039;ep&#039;&#039;&#039; - These messages contains debugging information regarding the internal &#039;&#039;expression parser&#039;&#039; and is used for development&lt;br /&gt;
*&#039;&#039;&#039;debug&#039;&#039;&#039; / &#039;&#039;&#039;dbg&#039;&#039;&#039; - These messages contains various debugging information and is used for development&lt;br /&gt;
*&#039;&#039;&#039;help&#039;&#039;&#039; / &#039;&#039;&#039;hlp&#039;&#039;&#039; - Signals that the message is a response to a &#039;&#039;help&#039;&#039;-command being sent to the Ekdahl FAR. These messages are structured so that a receiver, like the &#039;&#039;Configuration utility&#039;&#039;, can parse information about available &#039;&#039;commands&#039;&#039; in the current &#039;&#039;firmware&#039;&#039; and relay it to a user in a structured way.&lt;br /&gt;
* &#039;&#039;&#039;inforequest&#039;&#039;&#039; / &#039;&#039;&#039;irq&#039;&#039;&#039; - Signals that an &#039;&#039;info request&#039;&#039; has been returned. This is a specialized message that is either sent as a response to an &#039;&#039;rqi&#039;&#039;-command or as a &#039;&#039;interrupt&#039;&#039;-message telling the user or receiving software about different parameters in the Ekdahl FAR. These messages follows the same structure as regular &#039;&#039;command message&#039;&#039;s of &#039;&#039;[irq]commandname:parameter1 [etc]&#039;&#039; so that it can be used by a receiving software to keep track of parameter changes&lt;br /&gt;
&lt;br /&gt;
===== Explicitly requesting information =====&lt;br /&gt;
By using the special command &amp;quot;requestinfo&amp;quot; / &amp;quot;rqi&amp;quot; one can request the information stored by a certain &#039;&#039;command&#039;&#039; or a state of the Ekdahl FAR. The &amp;quot;rqi&amp;quot;-command is executed in the convention &amp;quot;rqi:commandname:optional parameters&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
To go back to our example of setting the bowing frequency using the &#039;&#039;&amp;quot;&#039;&#039;bowcontrolfrequency&amp;quot; / &amp;quot;bowingwheel.pid.targetfrequency&amp;quot;-command we can ask the Ekdahl FAR what the bowing frequency is set to by writing&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
rqi:bowcontrolfrequency&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
rqi:bowingwheel.pid.targetfrequency&lt;br /&gt;
&amp;lt;/pre&amp;gt;The return value would be something like&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
[irq]bcf:82.5&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
[irq]bw[0].pid[0].tf:82.5&lt;br /&gt;
&amp;lt;/pre&amp;gt;Where &#039;[irq]&#039; denotes that the message returned is in the &#039;&#039;info request-&#039;&#039;category, that it pertains to the command &amp;quot;bcf&amp;quot; / &amp;quot;bw.pid.tf&amp;quot; and has the value &#039;&#039;82.5&#039;&#039;. Note that the returned &#039;&#039;command&#039;&#039; sent by an &amp;quot;rqi&amp;quot;-command always uses the &#039;&#039;short name&#039;&#039; in order to preserve bandwidth. In the FAR 1.1 the return statement always returns the &#039;&#039;index&#039;&#039; of the &#039;&#039;module&#039;&#039;(s) in question. &lt;br /&gt;
&lt;br /&gt;
Most commands do not require any &#039;&#039;parameters&#039;&#039; when using the &amp;quot;rqi&amp;quot;-command. The &#039;&#039;&amp;quot;&#039;&#039;adcread&amp;quot; / &amp;quot;controlbox.datareturn&amp;quot;-command is an example of a &#039;&#039;command&#039;&#039; that &amp;lt;u&amp;gt;does&amp;lt;/u&amp;gt; require a &#039;&#039;parameter&#039;&#039; when used with &amp;quot;rqi&amp;quot;. The &amp;quot;adcread&amp;quot; / &amp;quot;controlbox.datareturn&amp;quot;&#039;&#039;-&#039;&#039;command returns the last value read by the &#039;&#039;analog-to-digital converter&#039;&#039; in the &#039;&#039;Control box&#039;&#039;, because there are 8 different channels the first &#039;&#039;parameter&#039;&#039; sets which channel to return the data for, hence executing the &#039;&#039;command&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
rqi:adcr:3&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
rqi:controlbox.datareturn:3&lt;br /&gt;
&amp;lt;/pre&amp;gt;will return the last data read on &#039;&#039;analog-to-digital convert&#039;&#039; channel 3.&lt;br /&gt;
&lt;br /&gt;
== MIDI mapping ==&lt;br /&gt;
The way &#039;&#039;MIDI&#039;&#039; works int the Ekdahl FAR is that each &#039;&#039;MIDI message&#039;&#039; is associated with a certain &#039;&#039;command string&#039;&#039; and the &#039;&#039;MIDI message&#039;&#039; will also update some of the internal &#039;&#039;variables&#039;&#039;. Any time the associated &#039;&#039;MIDI message&#039;&#039; is received the Ekdahl FAR will execute the &#039;&#039;commands&#039;&#039; that have been associated with that &#039;&#039;MIDI message&#039;&#039;. Several &#039;&#039;MIDI configurations&#039;&#039; can be stored and recalled at any time, each with a different set of &#039;&#039;commands&#039;&#039; associated with each &#039;&#039;MIDI message&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;FAR &amp;lt; 1.1:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;FAR &amp;lt; 1.1&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 The &#039;&#039;command&#039;&#039; responsible for mapping &#039;&#039;command strings&#039;&#039; to different &#039;&#039;MIDI messages&#039;&#039; is &amp;quot;midieventhandler&amp;quot; or &amp;quot;mev&amp;quot; for short. The first &#039;&#039;parameter&#039;&#039; of &amp;quot;mev&amp;quot; is the type of &#039;&#039;MIDI message&#039;&#039; that we want to remap;&lt;br /&gt;
 &lt;br /&gt;
 * &#039;&#039;&#039;noteon&#039;&#039;&#039; - Note on&lt;br /&gt;
 * &#039;&#039;&#039;noteoff&#039;&#039;&#039; - Note off&lt;br /&gt;
 * &#039;&#039;&#039;pat&#039;&#039;&#039; - Poly after touch&lt;br /&gt;
 * &#039;&#039;&#039;cat&#039;&#039;&#039; - Channel after touch&lt;br /&gt;
 * &#039;&#039;&#039;pb&#039;&#039;&#039; - Pitch bend&lt;br /&gt;
 * &#039;&#039;&#039;pc&#039;&#039;&#039; - Program change&lt;br /&gt;
 * &#039;&#039;&#039;cc&#039;&#039;&#039; - Continuous controller&lt;br /&gt;
 &lt;br /&gt;
 The second &#039;&#039;parameter&#039;&#039; is the &#039;&#039;command string&#039;&#039; that is to be associated with the &#039;&#039;MIDI Message&#039;&#039; - with the exception of the &#039;&#039;&#039;cc&#039;&#039;&#039;-type, here the second &#039;&#039;parameter&#039;&#039; is the &#039;&#039;controller number&#039;&#039; (0 - 127) and the third &#039;&#039;parameter&#039;&#039; is the &#039;&#039;command string&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;FAR 1.1&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 The &amp;quot;bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; contains a &#039;&#039;module&#039;&#039; called &amp;quot;midiconfigurationhandler&amp;quot; that handles the loading and switching in between different &#039;&#039;MIDI configurations&#039;&#039;. The &amp;quot;midiconfigurationhandler&amp;quot;&#039;&#039;-module&#039;&#039; has one or more &#039;&#039;&amp;quot;&#039;&#039;midiconfiguration&amp;quot;-&#039;&#039;modules&#039;&#039;, each having its own &#039;&#039;MIDI&#039;&#039; settings. In order to change the &#039;&#039;command mapping&#039;&#039; for a &#039;&#039;MIDI message&#039;&#039; in a specific &#039;&#039;MIDI configuration&#039;&#039;, the following &#039;&#039;commands&#039;&#039; are used;&lt;br /&gt;
 &lt;br /&gt;
 * &#039;&#039;&#039;noteon/non&#039;&#039;&#039;:&#039;&#039;commands&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed for a &#039;note on&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;noteoff/nof&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;note off&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;polyaftertouch/pat&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;poly aftertouch&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;channelaftertouch/cat&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;channel aftertouch&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;pitchbend/pb&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;pitch bend&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;programchange/pc&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;program change&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;continuouscontrollerdata/ccd&#039;&#039;&#039;&#039;&#039;:controller:commands&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed for &#039;continuous controller&#039; no &#039;&#039;controller&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
We can of course use the &#039;&#039;&amp;quot;&#039;&#039;rqi&amp;quot;-&#039;&#039;command&#039;&#039; to check the current mapping, below we are asking what the current &#039;&#039;command string&#039;&#039; associated with the &#039;&#039;pitch bend&#039;&#039; &#039;&#039;MIDI message&#039;&#039; is in the currently selected &#039;&#039;MIDI configuration&#039;&#039;.&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
rqi:midieventhandler:pb&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
rqi:bowingwheel.midiconfigurationhandler.midiconfiguration.pitchbend&lt;br /&gt;
&amp;lt;/pre&amp;gt;This may return something like&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
[irq]mev:pb:&amp;quot;bowcontrolharmonicshift:pitch*4&amp;quot;&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
[irq]bw[0].mcf[0].mc[0].pb:&amp;quot;bowingwheel.harmonicserieshandler.harmonicseries.shift:pitch*4&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;The first part of the return message tells us that the incoming message is of &amp;quot;rqi&amp;quot;-type (&amp;quot;[irq]&amp;quot;) which means it&#039;s responding to a information request &#039;&#039;command&#039;&#039; sent. The second part tells us what &#039;&#039;command&#039;&#039; the information request return is responding to and any &#039;&#039;parameters&#039;&#039; that may be pertinent. The third part of the message is the actual data stored.  &lt;br /&gt;
&lt;br /&gt;
For the FAR &amp;lt; 1.1 the data returned is for the &#039;&#039;command&#039;&#039; &amp;quot;mev&amp;quot; with the first &#039;&#039;parameter&#039;&#039; set to &amp;quot;pb&amp;quot;, the &#039;&#039;command reference&#039;&#039; tells us this means the &#039;&#039;command&#039;&#039; &amp;quot;midieventhandler&amp;quot; and the &#039;&#039;parameter&#039;&#039; &amp;quot;pb&amp;quot; indicates this has to do with the &#039;&#039;pitch bend&#039;&#039;. The data is &amp;quot;bowcontrolharmonicshift*4&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
For the FAR 1.1 the data returned is for the &#039;&#039;command&#039;&#039; &amp;quot;bw[0].mcf[0].mc[0].pb&amp;quot; (bowinwheel[0].midiconfigurationhandler[0].midiconfiguration[0].pitchbend) and the data is &amp;quot;bowingwheel.harmonicserieshandler.harmonicseries.shift:pitch*4&amp;quot;. Note here that if we have several different &#039;&#039;MIDI configurations&#039;&#039; stored and we&#039;re currently using configuration number 2, the returned message would have been &amp;quot;bw[0].mcf[0].mc[2].pb&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
that the &#039;&#039;pitch bend MIDI message&#039;&#039; is executing a &amp;quot;bowcontrolharmonicshift&amp;quot; / &amp;quot;harmonicseries.shift&amp;quot;-command with the parameter &#039;&#039;pitch*4&#039;&#039;. Looking in the &#039;&#039;command reference&#039;&#039; we can see that &#039;&#039;&amp;quot;&#039;&#039;bowcontrolharmonicshift&amp;quot; / &amp;quot;harmonicseries.shift&amp;quot;-&#039;&#039;command&#039;&#039; shifts the frequency of the &#039;&#039;bowing wheel&#039;&#039; from the currently selected harmonic. The first (and only) &#039;&#039;parameter&#039;&#039; sets how much we want to shift it (the range depends on the &amp;quot;bowcontrolharmonicshiftrange&#039;&#039;&amp;quot;&#039;&#039; / &amp;quot;harmonicseries.shiftrange&amp;quot;-&#039;&#039;command&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
If we look in the list of &#039;&#039;[[The Ekdahl FAR - Command langue#Variables|variables]]&#039;&#039; above we can see that the &#039;&#039;pitch bend MIDI message&#039;&#039; will set the &amp;quot;pitch&amp;quot;&#039;&#039;-variable&#039;&#039; which is indeed used. Now what is the &#039;&#039;&#039;*4&#039;&#039;&amp;lt;nowiki/&amp;gt;&#039; all about? Well the &amp;quot;bowcontrolharmonicshift&amp;quot; / &amp;quot;harmoniceseries.shift&amp;quot;-&#039;&#039;command&#039;&#039; expects a &#039;&#039;16-bit signed&#039;&#039; value as its &#039;&#039;parameter&#039;&#039;. This means that the valid &#039;&#039;parameter&#039;&#039; number can be anything from -32767 to 32767. A full &#039;&#039;harmonic shift&#039;&#039; downwards according to the range set is equal to -32767, a full &#039;&#039;harmonic shift&#039;&#039; upwards is 32767 and no &#039;&#039;harmonic shift&#039;&#039; is 0. The &#039;&#039;pitch bend MIDI message&#039;&#039; however is only 14-bits, meaning its range is -8192 to 8192. So we have to multiply &#039;&#039;pitch&#039;&#039; by 4 in order to meet the requirements of a &#039;&#039;16-bit signed parameter&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
This whole thing about number of bits can seem confusing but in the end it&#039;s all about how fine control you have over things; the more possible values, the more detailed control. In fact, most &#039;&#039;MIDI&#039;&#039; values are only 7-bit (!) meaning a range of 0 - 127. While this may sound like a lot of detail for something like a volume control, it is not even close to enough resolution to for instance set the &#039;&#039;bowing frequency&#039;&#039;. Even if you would limit yourself to a single octave the instrument would never be able to be properly in tune. The idea of limiting the Ekdahl FAR to what is possible through &#039;&#039;MIDI&#039;&#039; seemed like a poor choice thus it was decided that &amp;lt;u&amp;gt;most&amp;lt;/u&amp;gt; parameters will instead be 16-bit.&lt;br /&gt;
&lt;br /&gt;
Now lets look at a more complex example, the &amp;lt;u&amp;gt;default&amp;lt;/u&amp;gt; &#039;&#039;Note On MIDI message&#039;&#039;. On a stock Ekdahl FAR, executing&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
rqi:mev:noteon&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
rqi:mcf.mf.non&lt;br /&gt;
&amp;lt;/pre&amp;gt;Will return something like&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
[irq]mev:noteon:&#039;bchb:note,bmr:1,bpid:1,bpe:1,se:(velocity*512)*(1-notecount),bcsm:0&#039;&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
[irq]mcf[0].mc[0].non:&#039;bw.hsh.hb:note,bw.dcm.ru:1,bw.pe:1,bw.bp.en:1,so.en:(velocity*512)*(1-notecount),bw.sm:0&#039;&amp;lt;/pre&amp;gt;As can be seen, there&#039;s a lot of stuff going on here! First of all, notice that everything after &amp;quot;mev:noteon:&amp;quot; / &amp;quot;mcf[0].mc[0].non:&amp;quot; is situated in between single quotes (&#039;) - this is &amp;lt;u&amp;gt;absolutely crucial&amp;lt;/u&amp;gt; for the Ekdahl FAR in order to know that everything within those last two quotes is part of the last &#039;&#039;parameter&#039;&#039; of the &amp;quot;mev&amp;quot; / &amp;quot;mcf.mc.non&amp;quot;-&#039;&#039;command&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Now let&#039;s break down what happens when this &#039;&#039;MIDI message&#039;&#039; is received, i.e. when a &#039;&#039;MIDI&#039;&#039; key is pressed down:&lt;br /&gt;
&lt;br /&gt;
# &amp;quot;bchb:note&amp;quot; / &amp;quot;bw.hsh.hb:note&amp;quot;  - Invokes the &amp;quot;bowcontrolharmonicbase&amp;quot; / &amp;quot;harmonicserieshandler.harmonicbase&amp;quot;&#039;&#039;-command&#039;&#039; with the first &#039;&#039;parameter&#039;&#039; set to the &#039;&#039;variable note&#039;&#039;. This sets the &#039;&#039;base harmonic&#039;&#039; that the Ekdahl FARs &#039;&#039;bowing motor&#039;&#039; should be set to. Here the &#039;&#039;variable&#039;&#039; &amp;quot;note&amp;quot; is used which is simply the MIDI key being pressed down, it is automatically converted by the &#039;&#039;command&#039;&#039; to the corresponding harmonic in the &#039;&#039;harmonic list&#039;&#039;&lt;br /&gt;
# &amp;quot;bmr:1&amp;quot; / &amp;quot;bw.dcm.ru&amp;quot; - Sets the &amp;quot;bowmotorrun&amp;quot; / &amp;quot;dcmotor.run&amp;quot;-command to &#039;1&#039;, starting the &#039;&#039;bow motor&#039;&#039;&lt;br /&gt;
# &amp;quot;bpid:1&amp;quot; / &amp;quot;bw.pe:1&amp;quot; - Sets the &amp;quot;bowpid&amp;quot; / &amp;quot;bowingwheel.pidenable&amp;quot;-&#039;&#039;command&#039;&#039; to &#039;1&#039;. Basically this enables the function that makes the Ekdahl FAR able to keep a stable frequency on the &#039;&#039;bowing motor&#039;&#039;.&lt;br /&gt;
# &amp;quot;bpe:1&amp;quot; / &amp;quot;bw.bp.en&amp;quot; - Sets the &amp;quot;bowpressureengage&amp;quot; / &amp;quot;bowpressure.engage&amp;quot;-&#039;&#039;command&#039;&#039; to &#039;1&#039; which moves the &#039;&#039;bowing jack&#039;&#039; to the &#039;&#039;engage position&#039;&#039;, aka just below the string if not additional &#039;&#039;pressure&#039;&#039; is applied&lt;br /&gt;
# &amp;quot;se:(velocity*512)*(1-notecount)&amp;quot; / &amp;quot;so.en:(velocity*512)*(1-notecount)&amp;quot; - Executes the &amp;quot;solenoidengage&amp;quot; / &amp;quot;solenoid.engage&amp;quot;-&#039;&#039;command&#039;&#039; with the value &#039;&#039;(velocity*512)*(1-notecount)&#039;&#039;. This will make the &#039;&#039;solenoid&#039;&#039; strike the &#039;&#039;hammer&#039;&#039; with a force that is dependent on the &#039;&#039;velocity&#039;&#039; variable sent by the &#039;&#039;Note On MIDI message&#039;&#039; in order to make the &#039;&#039;hammer&#039;&#039; velocity sensitive.   But it also adds the somewhat perplexing part &amp;quot;*(1-notecount)&amp;quot;. &amp;quot;notecount&amp;quot; is a global &#039;&#039;variable&#039;&#039; that contains the number of MIDI keys that are currently being held down. If &amp;quot;notecount&amp;quot; is anything above zero, the outcome of the equation will either be zero or a negative number. The &amp;quot;solenoidengage&amp;quot; / &amp;quot;solenoid.engage&amp;quot;-&#039;&#039;command&#039;&#039; requires a &#039;&#039;16-bit unsigned&#039;&#039; value, aka the only valid numbers are 0 - 65535. Anything below 0 will be interpreted as zero, so what this equation does is that it only fires off the &#039;&#039;hammer&#039;&#039; if there are no previous keys being held down - it&#039;s being used in &#039;&#039;staccato&#039;&#039;  mode.&lt;br /&gt;
# &amp;quot;bcsm:0&amp;quot; / &amp;quot;bowingwheel.speedmode&amp;quot; - Sets the &amp;quot;bowcontrolspeedmode&amp;quot; / &amp;quot;bowingwheel.speedmode&amp;quot; to &#039;1&#039; which enables automatic shut down of the &#039;&#039;bowing motor&#039;&#039; after a given timeout.&lt;br /&gt;
Let&#039;s postulate that the Ekdahl FAR is tuned to a &#039;C&#039; at 65.4Hz and has its &#039;&#039;base&#039;&#039; set to middle &#039;C&#039; (&#039;&#039;MIDI key&#039;&#039; no 36). We are using the equal-temperament 12-tone scale and the Ekdahl FAR is set to respond to &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; &#039;&#039;MIDI channels&#039;&#039; (omni). Without having previously held any keys we press the middle &#039;C&#039; (&#039;&#039;note&#039;&#039; value 36) as hard as possible (&#039;&#039;velocity&#039;&#039; value &#039;&#039;127&#039;&#039;) on &#039;&#039;MIDI channel&#039;&#039; number 1 (&#039;&#039;channel&#039;&#039; value of 0). The Ekdahl FAR will get a &#039;&#039;note on MIDI message&#039;&#039; sent to it and from our mapping it will create the following &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;[irq]mev:noteon:&#039;m:0,b:0,bchb:36,bmr:1,bpid:1,bpe:1,se:(127*512)*(1-0),bcsm:0&#039;&amp;lt;/pre&amp;gt;What has happened here is that all &#039;&#039;variables&#039;&#039; have been replaced with the values sent by the &#039;&#039;MIDI message&#039;&#039;. Since those &#039;&#039;commands&#039;&#039; that doesn&#039;t have any &#039;&#039;variables&#039;&#039; with them will execute just as previously, only those &#039;&#039;commands&#039;&#039; whos &#039;&#039;parameters&#039;&#039; have changed will be explained:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;bchb: 36&#039;&#039; - The &#039;&#039;bowcontrolharmonicbase&#039;&#039; gets a value of &#039;&#039;36&#039;&#039; (middle &#039;C&#039;), because &#039;&#039;harmonic number 0&#039;&#039; is mapped to this key it will set the &#039;&#039;bowing wheel&#039;&#039; frequency to the &#039;&#039;fundamental&#039;&#039;; &#039;&#039;65.4&#039;&#039; Hertz&lt;br /&gt;
# &#039;&#039;se: (127*512)*(1-0)&#039;&#039; - the value of &#039;&#039;127&#039;&#039; comes from the &#039;&#039;velocity&#039;&#039;-variable, &#039;&#039;127 * 512 = 65024&#039;&#039; which is awfully close to a maximum hammer force of 65535. Since no previous notes were held down &#039;&#039;notecount&#039;&#039;  is equal to &#039;&#039;0&#039;&#039; and thus &#039;&#039;65024 * 1 = 65024&#039;&#039;. The hammer is engaged with near maximum force.&lt;br /&gt;
So the result is that we have set the speed of the &#039;&#039;bowing motor&#039;&#039; and we have engaged the &#039;&#039;hammer&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Now imagine that without releasing this key, we press another &#039;C&#039; one octave above but at half the velocity. The Ekdahl FAR creates the following &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
[irq]mev:noteon:&#039;m:0,b:0,bchb:48,bmr:1,bpid:1,bpe:1,se:(63*512)*(1-1),bcsm:0&#039;&lt;br /&gt;
&amp;lt;/pre&amp;gt;Now we can see that the &#039;&#039;note&#039;&#039; variable is &#039;&#039;48&#039;&#039; because the &#039;C&#039; one octave up is exactly 12 keys above the first, the &#039;&#039;velocity&#039;&#039; variable has changed to &#039;&#039;63&#039;&#039; since we hit it with a lighter touch - and because we are &amp;lt;u&amp;gt;still holding the first key down&amp;lt;/u&amp;gt; &#039;&#039;notecount&#039;&#039; is equal to &#039;&#039;1&#039;&#039;. Here&#039;s what happens&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;bchb: 48&#039;&#039; - Due to the &#039;&#039;base&#039;&#039; being set to &#039;&#039;36&#039;&#039; the &#039;&#039;harmonic number&#039;&#039; is set to &#039;&#039;48 - 36 = 12&#039;&#039;. Because we are using a 12-tone scale &#039;&#039;harmonic number 12&#039;&#039; is exactly one octave above the &#039;&#039;fundamental&#039;&#039; thus the speed of the &#039;&#039;bowing wheel&#039;&#039; is set to &#039;&#039;65.4 * 2 = 130.8&#039;&#039; Hertz.&lt;br /&gt;
# &#039;&#039;se: (63*512)*(1-1)&#039;&#039; - So &#039;&#039;63 * 512 = 32256&#039;&#039; and &#039;&#039;1 - 1 = 0&#039;&#039; thus &#039;&#039;32256 * 0 = 0&#039;&#039;. When the &#039;&#039;solenoidengage&#039;&#039;-command gets a &#039;&#039;parameter&#039;&#039; of &#039;&#039;0&#039;&#039; it will not engage the &#039;&#039;hammer&#039;&#039; - so the &#039;&#039;hammer&#039;&#039; doesn&#039;t strike&lt;br /&gt;
So it can be seen that with quite rudimentary math we can accomplish a whole lot of things here. Note also that even though the &#039;&#039;note on MIDI message&#039;&#039; also sets the &#039;&#039;channel&#039;&#039;-variable we never use it in this example - plenty of opportunity to make something weird happen depending on the &#039;&#039;MIDI channel&#039;&#039;!&lt;br /&gt;
&lt;br /&gt;
== CV Mapping ==&lt;br /&gt;
&#039;&#039;CV Mapping&#039;&#039; works exactly like the &#039;&#039;MIDI mapping&#039;&#039; with the difference that the command for setting the &#039;&#039;CV mapping&#039;&#039; is different and that &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; events pertaining to this &amp;lt;u&amp;gt;only&amp;lt;/u&amp;gt; change the &#039;&#039;value&#039;&#039;-variable. The &#039;&#039;command&#039;&#039; for changing the &#039;&#039;CV mapping&#039;&#039; is &#039;&#039;adccommandmap&#039;&#039; or &#039;&#039;acm&#039;&#039;, it take two &#039;&#039;parameters&#039;&#039;; &#039;&#039;channel&#039;&#039; and &#039;&#039;command string&#039;&#039;. We retrieve the &#039;&#039;command string&#039;&#039; for channel &#039;&#039;0&#039;&#039; which reads the sum of the &#039;&#039;harm. v/oct&#039;&#039;-jack and the &#039;&#039;harmonic&#039;&#039;-knob by sending a command of&amp;lt;pre&amp;gt;&lt;br /&gt;
rqi:acm:0&lt;br /&gt;
&amp;lt;/pre&amp;gt;The &amp;lt;u&amp;gt;default&amp;lt;/u&amp;gt; response will be something like&lt;br /&gt;
&amp;lt;pre&amp;gt;[irq]acm:0:&#039;bcha:value/1327.716667-20&#039;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{docnav&lt;br /&gt;
|[[The Ekdahl FAR - Service|Service]]&lt;br /&gt;
|[[The Ekdahl FAR - Command reference|Command reference]]&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Knaadmin</name></author>
	</entry>
	<entry>
		<id>http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_language&amp;diff=1654</id>
		<title>The Ekdahl FAR - Command language</title>
		<link rel="alternate" type="text/html" href="http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_language&amp;diff=1654"/>
		<updated>2026-06-10T17:53:56Z</updated>

		<summary type="html">&lt;p&gt;Knaadmin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Command language ==&lt;br /&gt;
The Ekdahl FAR is entirely controlled by &#039;&#039;commands&#039;&#039;, these &#039;&#039;commands&#039;&#039; decide everything that the instrument is doing, whether it is playing a melody or changing an internal parameter. &lt;br /&gt;
&lt;br /&gt;
When a &#039;&#039;MIDI message&#039;&#039; is received or a new CV / knob value is read, the &#039;&#039;commands&#039;&#039; associated with it will be internally sent. This can be things like &amp;quot;engage hammer&amp;quot; or &amp;quot;set the fundamental frequency&amp;quot; etc. &lt;br /&gt;
&lt;br /&gt;
Some of the available &#039;&#039;commands&#039;&#039; are mainly used for calibrating and setting up the instrument and are usually saved into the instruments memory, these will be executed whenever the instrument is turned on. &lt;br /&gt;
&lt;br /&gt;
All &#039;&#039;commands&#039;&#039; can be manually invoked via &#039;&#039;USB-Serial&#039;&#039;, in conjunction with certain software this presents an unprecedented level of control and sequenceability.&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
The &#039;&#039;commands&#039;&#039; are invoked using a &#039;&#039;plain text approach&#039;&#039;, all commands have both a &#039;&#039;long name&#039;&#039; and a &#039;&#039;short name&#039;&#039; which are interchangeable. A &#039;&#039;command&#039;&#039; may have one or more &#039;&#039;parameters&#039;&#039; associated with it, these &#039;&#039;parameters&#039;&#039; can be of different types; 16-bit numbers (values 0 - 65535 or -32767 - 32767), floating point numbers (values with decimals), booleans (0 for &#039;false&#039;, 1 for &#039;true&#039;) and strings (text). Some commands are &#039;&#039;conditional&#039;&#039;, meaning they will only execute if a parameter equates to &#039;1&#039; (&#039;true&#039;). &lt;br /&gt;
&lt;br /&gt;
The way &#039;&#039;commands&#039;&#039; are written in order to be executed is &#039;&#039;commandname:parameter1:parameter2:parameter3 [etc]&#039;&#039;, several commands be executed in sequence by separating them with a comma (&#039;,&#039;), a bunch of commands strung together is called a &#039;&#039;command string&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Since version 1.1 of the Ekdahl FAR Firmware, all commands are grouped in a hierarchical fashion according to their &#039;&#039;modules&#039;&#039; and each ladder in the hierarchy is separated by a period (&amp;quot;.&amp;quot;), this works very much like folders or directories in a regular computer. Every &#039;&#039;module&#039;&#039; can contain both &#039;&#039;commands&#039;&#039; and other &#039;&#039;modules&#039;&#039;. For instance, everything associated with the &#039;&#039;bowing wheel&#039;&#039; is now collected under &amp;quot;bowingwheel&amp;quot; &#039;&#039;module&#039;&#039;. That in turn contains a &amp;quot;dcmotor&amp;quot; &#039;&#039;module&#039;&#039; which handles direct control of the bowing motor. It also has a &amp;quot;pid&amp;quot; &#039;&#039;module&#039;&#039; that handles bow frequency among other thing. &lt;br /&gt;
&lt;br /&gt;
If for instance we would like to start the &#039;&#039;bowing wheel&#039;&#039; and set its frequency to 82.5 Hertz we could send the Ekdahl FAR the following &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
bowmotorrun:1, bowcontrolfrequecy:82.5&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bowingwheel.dcmotor.run:1, bowingwheel.pid.targetfrequency:82.5&amp;lt;/pre&amp;gt;We could also use the &#039;&#039;short names&#039;&#039; for the commands&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
bmr:1,bcf:82.5&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bw.dcm.ru:1, bw.pid.tf:82.5&amp;lt;/pre&amp;gt;Both &amp;quot;bowmotorrun&amp;quot; / &amp;quot;bowingwheel.dcmotor.run&amp;quot; and &amp;quot;bowcontrolfrequency&amp;quot; / &amp;quot;bowingwheel.pid.targetfrequency&amp;quot; takes one &#039;&#039;parameter&#039;&#039; each, &#039;&#039;&amp;quot;&#039;&#039;bowmotorrun&amp;quot; / &amp;quot;bowingwheel.dcmotor.run&amp;quot; is &#039;&#039;conditional&#039;&#039; and unless the first &#039;&#039;parameter&#039;&#039; is equal to &#039;1&#039; the motor will not start. The first &#039;&#039;parameter&#039;&#039; of &amp;quot;bowcontrolfrequency&amp;quot; / &amp;quot;bowingwheel.pid.targetfrequency&amp;quot; sets the frequency of the &#039;&#039;bowing wheel&#039;&#039;, the instrument may not execute a &#039;&#039;command&#039;&#039; if it decides that the given &#039;&#039;parameters&#039;&#039; are outside of the working range or they are missing.&lt;br /&gt;
&lt;br /&gt;
The addition of the hierarchy in the FAR 1.1 firmware isn&#039;t just to be able to group commands, but it&#039;s also to make the FAR not limited to a single set of &#039;&#039;modules&#039;&#039; (and is the first stepping stone to a &#039;&#039;modular&#039;&#039; Ekdahl FAR). In fact, you could have 12 different bowing wheel &#039;&#039;modules&#039;&#039; for 12 different strings, these would then be addressed as &amp;quot;bowingwheel[0].command&amp;quot;&#039;&#039;, &amp;quot;&#039;&#039;bowingwheel[1].command&amp;quot; etc. Anyone familiar with C programming notices that this is the standard way of &#039;&#039;indexing&#039;&#039; an array; using brackets (&amp;quot;[ ]&amp;quot;). When addressing a module without &#039;&#039;indexing&#039;&#039; as in the example above, the FAR will do one or two things; either use the first object (&amp;quot;[0]&amp;quot;) or, if the object is &#039;&#039;selectable&#039;&#039; it will use the previously selected object. To make things smoother a command can be executed on several objects at once by using ranges (&amp;quot;[0-4]&amp;quot;) and comma separation (&amp;quot;[0, 3, 5-6]&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
To test out a &#039;&#039;command&#039;&#039; you can send it directly to the Ekdahl FAR using the &#039;&#039;Console&#039;&#039; in the &#039;&#039;Configuration utility&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
To read up on existing &#039;&#039;commands&#039;&#039;, their &#039;&#039;parameters&#039;&#039; and a brief description you can check the &#039;&#039;Command reference&#039;&#039; in the &#039;&#039;Configuration utility&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Variables, functions and equations ==&lt;br /&gt;
What makes the &#039;&#039;Command language&#039;&#039; truly powerful is the concept of &#039;&#039;variables, functions&#039;&#039; and &#039;&#039;equations&#039;&#039;. All &#039;&#039;parameters&#039;&#039; that take numerical values can use any combination of &#039;&#039;variables, functions&#039;&#039; or &#039;&#039;equations.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
For instance, we can use the previous example and instead write our &#039;&#039;command string&#039;&#039; as follows&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
bowmotorrun:1, bowcontrolfrequency:82.5+note*20&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bowingwheel.dcmotor.run:1, bowingwheel.pid.targetfrequency:82.5+note*20&amp;lt;/pre&amp;gt;This example requires of course that the &#039;&#039;variable&#039;&#039; &#039;&#039;note&#039;&#039; exists in the current context. &lt;br /&gt;
&lt;br /&gt;
===== Variables =====&lt;br /&gt;
There are two types of &#039;&#039;variables&#039;&#039; in the Ekdahl FAR; &#039;&#039;global variables&#039;&#039; and &#039;&#039;event variables&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Global variables&#039;&#039; are variables that are always valid, in any context. The &#039;&#039;global variables&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;notecount&#039;&#039;&#039; - Contains the number of &#039;&#039;MIDI&#039;&#039; keys that are being held down, i.e. all &#039;&#039;Note on messages&#039;&#039; received that haven&#039;t gotten a paired &#039;&#039;Note off message&#039;&#039; yet&lt;br /&gt;
* &#039;&#039;&#039;uv0&#039;&#039;&#039; - &#039;&#039;&#039;uv9&#039;&#039;&#039; - These are &#039;&#039;user variables&#039;&#039; and can be set at any point using the &#039;&#039;globaluservariable command&#039;&#039; with the first &#039;&#039;parameter&#039;&#039; being which variable to set (0-9) and the second &#039;&#039;parameter&#039;&#039; being the value (float).&lt;br /&gt;
* &#039;&#039;&#039;e&#039;&#039;&#039; - Contains the constant &#039;&#039;[[wikipedia:E_(mathematical_constant)|e]]&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pi&#039;&#039;&#039; - Contains the constant &#039;&#039;[[wikipedia:Pi|pi]]&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Event variables&#039;&#039; are variables that are set by certain &#039;&#039;MIDI messages&#039;&#039; or when a new value is read on one of the jacks or knobs on the &#039;&#039;Control box&#039;&#039;. The &#039;&#039;Event variables&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;channel&#039;&#039;&#039; - Set by the &#039;&#039;Note on, Note off, Continuous Controller, Poly after touch, Pitch bend, Channel after touch&#039;&#039; and &#039;&#039;Program change MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;note&#039;&#039;&#039; - Set by the &#039;&#039;Note on, Note off&#039;&#039; and &#039;&#039;Poly after touch MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;velocity&#039;&#039;&#039; - Set by the &#039;&#039;Note on&#039;&#039; and &#039;&#039;Note off MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pressure&#039;&#039;&#039; - Set by the &#039;&#039;Poly after touch&#039;&#039; and &#039;&#039;Channel after touch MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; - Set by the &#039;&#039;Continuous Controller MIDI message&#039;&#039; and by the &#039;&#039;Control box&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pitch&#039;&#039;&#039; - Set by the &#039;&#039;Pitch bend MIDI message&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;program&#039;&#039;&#039; - Set by the &#039;&#039;Program change MIDI message&#039;&#039;&lt;br /&gt;
These variables will contain whatever data is relevant to the last event that occurred and may be overwritten by the next event.&lt;br /&gt;
&lt;br /&gt;
===== Functions =====&lt;br /&gt;
&#039;&#039;Functions&#039;&#039; can be used to change a numerical value or the result of an &#039;&#039;equation&#039;&#039;, the Ekdahl FAR contains both general &#039;&#039;arithmetic functions&#039;&#039; (courtesy of Lewis Van Winkle and the TINYEXPR engine) and &#039;&#039;specialized functions&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;arithmetic functions&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;abs&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Absolute_value|absolute value]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;acos&#039;&#039;&#039;(x), &#039;&#039;&#039;asin&#039;&#039;&#039;(x), &#039;&#039;&#039;atan&#039;&#039;&#039;(x), atan2(x, y) - Returns the [[wikipedia:Inverse_trigonometric_functions|&#039;&#039;arc-cos, -sin, -tan&#039;&#039; and &#039;&#039;-tan2&#039;&#039;]] of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;atan2&#039;&#039;&#039;(x,y) - Returns the &#039;&#039;[[wikipedia:Atan2|arctan2]]&#039;&#039; of &#039;&#039;x, y&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;floor&#039;&#039;&#039;(x), ceil(x) - Returns the [[wikipedia:Floor_and_ceiling_functions|&#039;&#039;floor&#039;&#039; and &#039;&#039;ceiling&#039;&#039;]] of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;exp&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Exponential_function|exponent]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;fac&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Factorial|factorial]]&#039;&#039; of x&lt;br /&gt;
* &#039;&#039;&#039;ln&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Natural_logarithm|natural logarithm]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;log10&#039;&#039;&#039;(x), &#039;&#039;&#039;log20&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Logarithm|logarithm]]&#039;&#039; of &#039;&#039;x&#039;&#039; using base 10 and 20 respectively&lt;br /&gt;
* &#039;&#039;&#039;ncr&#039;&#039;&#039;(x,y), &#039;&#039;&#039;npr&#039;&#039;&#039;(x,y) - Functions to calculate &#039;&#039;[[wikipedia:Combination|combinations]]&#039;&#039; and &#039;&#039;[[wikipedia:Permutation|permutations]]&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pow&#039;&#039;&#039;(x,y) - Returns &#039;&#039;x^y&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;sqrt&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Square_root|square root]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;cos&#039;&#039;&#039;(x), &#039;&#039;&#039;sin&#039;&#039;&#039;(x), &#039;&#039;&#039;tan&#039;&#039;&#039;(x) - Returns the [[wikipedia:Trigonometric_functions|&#039;&#039;cos, sin&#039;&#039; and &#039;&#039;tan&#039;&#039;]] of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;cosh&#039;&#039;&#039;(x), &#039;&#039;&#039;sinh&#039;&#039;&#039;(x), &#039;&#039;&#039;tanh&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Hyperbolic_functions|hyperbolic cos, sin and tan]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
The &#039;&#039;specialized functions&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;bool&#039;&#039;&#039;(x) - Returns 1 if &#039;&#039;x&#039;&#039; is more than 0&lt;br /&gt;
* &#039;&#039;&#039;ibool&#039;&#039;&#039;(x) - Returns 0 if &#039;&#039;x&#039;&#039; is more than 0&lt;br /&gt;
* &#039;&#039;&#039;deadband&#039;&#039;&#039;(x,y) - Returns &#039;&#039;x + y &#039;&#039; if &#039;&#039;x &amp;lt; y&#039;&#039; or &#039;&#039;x - y&#039;&#039; if &#039;&#039;x &amp;gt; y&#039;&#039;. If neither of these statements is true it returns &#039;&#039;0&#039;&#039; - used to create a [[wikipedia:Deadband|deadband]] of &#039;&#039;x&#039;&#039; with the threshold of &#039;&#039;y&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Functions&#039;&#039; can be readily used in a &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
bowmotorrun:1, bowcontrolfrequency:&amp;quot;8.17579875 * pow(2, (1/12 * note))&amp;quot;&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bowingwheel.dcmotor.run:1, bowingwheel.pid.targetfrequency:&amp;quot;8.17579875 * pow(2, (1/12 * note))&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;The previous statements starts the &#039;&#039;bowing wheel&#039;&#039; and sets the frequency of the wheel to &#039;&#039;8.17579875 * 2^(1/12 * note)&#039;&#039;. A middle &#039;C&#039; according to &#039;&#039;MIDI&#039;&#039; has a &#039;&#039;note value&#039;&#039; of 36, meaning if we substitute &#039;&#039;note&#039;&#039; with 36 we get the equation &#039;&#039;8.17579875 * 2^(1/12 * 36)&#039;&#039; which comes out to &#039;&#039;~65.4&#039;&#039; Hertz.&lt;br /&gt;
&lt;br /&gt;
Note that the first &#039;&#039;parameter&#039;&#039; for &#039;&#039;&amp;quot;&#039;&#039;bowcontrolfrequency&amp;quot; / &amp;quot;bowingwheel.pid.targetfrequency&amp;quot; is put in between double quotes (&amp;quot;). This is because the &amp;quot;pow&#039;&#039;&amp;quot;-&#039;&#039;function requires the use of a comma (&amp;quot;,&amp;quot;) in order to separate in between its two required inputs; &#039;&#039;x&#039;&#039; and &#039;&#039;y&#039;&#039;. In order for the Ekdahl FAR to know that this comma does not signal the beginning of a new &#039;&#039;command,&#039;&#039; we use quotes. Single (&#039;) and double (&amp;quot;) quotes can be used and nested in all &#039;&#039;parameters&#039;&#039; and are &amp;lt;u&amp;gt;required&amp;lt;/u&amp;gt; in a lot of circumstances, improper nesting or not using quotes can lead to the instrument not understanding the &#039;&#039;command string&#039;&#039; correctly.&lt;br /&gt;
&lt;br /&gt;
== Return messages ==&lt;br /&gt;
The Ekdahl FAR when connected via &#039;&#039;USB-Serial&#039;&#039; doesn&#039;t only accept &#039;&#039;commands&#039;&#039; but will also send various &#039;&#039;return messages&#039;&#039;. These are prefixed by their &#039;&#039;category&#039;&#039; denoted in brackets (&amp;quot;[]&amp;quot;), the existing categories as of this writing (2025-01-22) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;command&#039;&#039;&#039; / &#039;&#039;&#039;cmd&#039;&#039;&#039; - Acknowledges the reception of a command in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;usb&#039;&#039;&#039; - Acknowledges the reception of a &#039;&#039;MIDI message&#039;&#039; over &#039;&#039;USB&#039;&#039; in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;hardware&#039;&#039;&#039; / &#039;&#039;&#039;hw&#039;&#039;&#039; - Signals that a change has been sent to the Ekdahl FAR hardware, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;undefined&#039;&#039;&#039; / &#039;&#039;&#039;un&#039;&#039;&#039; - The message sent is in the &#039;&#039;undefined&#039;&#039; category, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;priority&#039;&#039;&#039; / &#039;&#039;&#039;pri&#039;&#039;&#039; - The message sent is in the &#039;&#039;priority&#039;&#039; category, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;error&#039;&#039;&#039; / &#039;&#039;&#039;err&#039;&#039;&#039; - Signals that an &#039;&#039;error&#039;&#039; has occurred, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;expressionparser&#039;&#039;&#039; / &#039;&#039;&#039;ep&#039;&#039;&#039; - These messages contains debugging information regarding the internal &#039;&#039;expression parser&#039;&#039; and is used for development&lt;br /&gt;
*&#039;&#039;&#039;debug&#039;&#039;&#039; / &#039;&#039;&#039;dbg&#039;&#039;&#039; - These messages contains various debugging information and is used for development&lt;br /&gt;
*&#039;&#039;&#039;help&#039;&#039;&#039; / &#039;&#039;&#039;hlp&#039;&#039;&#039; - Signals that the message is a response to a &#039;&#039;help&#039;&#039;-command being sent to the Ekdahl FAR. These messages are structured so that a receiver, like the &#039;&#039;Configuration utility&#039;&#039;, can parse information about available &#039;&#039;commands&#039;&#039; in the current &#039;&#039;firmware&#039;&#039; and relay it to a user in a structured way.&lt;br /&gt;
* &#039;&#039;&#039;inforequest&#039;&#039;&#039; / &#039;&#039;&#039;irq&#039;&#039;&#039; - Signals that an &#039;&#039;info request&#039;&#039; has been returned. This is a specialized message that is either sent as a response to an &#039;&#039;rqi&#039;&#039;-command or as a &#039;&#039;interrupt&#039;&#039;-message telling the user or receiving software about different parameters in the Ekdahl FAR. These messages follows the same structure as regular &#039;&#039;command message&#039;&#039;s of &#039;&#039;[irq]commandname:parameter1 [etc]&#039;&#039; so that it can be used by a receiving software to keep track of parameter changes&lt;br /&gt;
&lt;br /&gt;
===== Explicitly requesting information =====&lt;br /&gt;
By using the special command &amp;quot;requestinfo&amp;quot; / &amp;quot;rqi&amp;quot; one can request the information stored by a certain &#039;&#039;command&#039;&#039; or a state of the Ekdahl FAR. The &amp;quot;rqi&amp;quot;-command is executed in the convention &amp;quot;rqi:commandname:optional parameters&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
To go back to our example of setting the bowing frequency using the &#039;&#039;&amp;quot;&#039;&#039;bowcontrolfrequency&amp;quot; / &amp;quot;bowingwheel.pid.targetfrequency&amp;quot;-command we can ask the Ekdahl FAR what the bowing frequency is set to by writing&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
rqi:bowcontrolfrequency&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
rqi:bowingwheel.pid.targetfrequency&lt;br /&gt;
&amp;lt;/pre&amp;gt;The return value would be something like&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
[irq]bcf:82.5&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
[irq]bw[0].pid[0].tf:82.5&lt;br /&gt;
&amp;lt;/pre&amp;gt;Where &#039;[irq]&#039; denotes that the message returned is in the &#039;&#039;info request-&#039;&#039;category, that it pertains to the command &amp;quot;bcf&amp;quot; / &amp;quot;bw.pid.tf&amp;quot; and has the value &#039;&#039;82.5&#039;&#039;. Note that the returned &#039;&#039;command&#039;&#039; sent by an &amp;quot;rqi&amp;quot;-command always uses the &#039;&#039;short name&#039;&#039; in order to preserve bandwidth. In the FAR 1.1 the return statement always returns the &#039;&#039;index&#039;&#039; of the &#039;&#039;module&#039;&#039;(s) in question. &lt;br /&gt;
&lt;br /&gt;
Most commands do not require any &#039;&#039;parameters&#039;&#039; when using the &amp;quot;rqi&amp;quot;-command. The &#039;&#039;&amp;quot;&#039;&#039;adcread&amp;quot; / &amp;quot;controlbox.datareturn&amp;quot;-command is an example of a &#039;&#039;command&#039;&#039; that &amp;lt;u&amp;gt;does&amp;lt;/u&amp;gt; require a &#039;&#039;parameter&#039;&#039; when used with &amp;quot;rqi&amp;quot;. The &amp;quot;adcread&amp;quot; / &amp;quot;controlbox.datareturn&amp;quot;&#039;&#039;-&#039;&#039;command returns the last value read by the &#039;&#039;analog-to-digital converter&#039;&#039; in the &#039;&#039;Control box&#039;&#039;, because there are 8 different channels the first &#039;&#039;parameter&#039;&#039; sets which channel to return the data for, hence executing the &#039;&#039;command&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
rqi:adcr:3&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
rqi:controlbox.datareturn:3&lt;br /&gt;
&amp;lt;/pre&amp;gt;will return the last data read on &#039;&#039;analog-to-digital convert&#039;&#039; channel 3.&lt;br /&gt;
&lt;br /&gt;
== MIDI mapping ==&lt;br /&gt;
The way &#039;&#039;MIDI&#039;&#039; works int the Ekdahl FAR is that each &#039;&#039;MIDI message&#039;&#039; is associated with a certain &#039;&#039;command string&#039;&#039; and the &#039;&#039;MIDI message&#039;&#039; will also update some of the internal &#039;&#039;variables&#039;&#039;. Any time the associated &#039;&#039;MIDI message&#039;&#039; is received the Ekdahl FAR will execute the &#039;&#039;commands&#039;&#039; that have been associated with that &#039;&#039;MIDI message&#039;&#039;. Several &#039;&#039;MIDI configurations&#039;&#039; can be stored and recalled at any time, each with a different set of &#039;&#039;commands&#039;&#039; associated with each &#039;&#039;MIDI message&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;FAR &amp;lt; 1.1:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;FAR &amp;lt; 1.1&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 The &#039;&#039;command&#039;&#039; responsible for mapping &#039;&#039;command strings&#039;&#039; to different &#039;&#039;MIDI messages&#039;&#039; is &amp;quot;midieventhandler&amp;quot; or &amp;quot;mev&amp;quot; for short. The first &#039;&#039;parameter&#039;&#039; of &amp;quot;mev&amp;quot; is the type of &#039;&#039;MIDI message&#039;&#039; that we want to remap;&lt;br /&gt;
 &lt;br /&gt;
 * &#039;&#039;&#039;noteon&#039;&#039;&#039; - Note on&lt;br /&gt;
 * &#039;&#039;&#039;noteoff&#039;&#039;&#039; - Note off&lt;br /&gt;
 * &#039;&#039;&#039;pat&#039;&#039;&#039; - Poly after touch&lt;br /&gt;
 * &#039;&#039;&#039;cat&#039;&#039;&#039; - Channel after touch&lt;br /&gt;
 * &#039;&#039;&#039;pb&#039;&#039;&#039; - Pitch bend&lt;br /&gt;
 * &#039;&#039;&#039;pc&#039;&#039;&#039; - Program change&lt;br /&gt;
 * &#039;&#039;&#039;cc&#039;&#039;&#039; - Continuous controller&lt;br /&gt;
 &lt;br /&gt;
 The second &#039;&#039;parameter&#039;&#039; is the &#039;&#039;command string&#039;&#039; that is to be associated with the &#039;&#039;MIDI Message&#039;&#039; - with the exception of the &#039;&#039;&#039;cc&#039;&#039;&#039;-type, here the second &#039;&#039;parameter&#039;&#039; is the &#039;&#039;controller number&#039;&#039; (0 - 127) and the third &#039;&#039;parameter&#039;&#039; is the &#039;&#039;command string&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;FAR 1.1&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 The &amp;quot;bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; contains a &#039;&#039;module&#039;&#039; called &amp;quot;midiconfigurationhandler&amp;quot; that handles the loading and switching in between different &#039;&#039;MIDI configurations&#039;&#039;. The &amp;quot;midiconfigurationhandler&amp;quot;&#039;&#039;-module&#039;&#039; has one or more &#039;&#039;&amp;quot;&#039;&#039;midiconfiguration&amp;quot;-&#039;&#039;modules&#039;&#039;, each having its own &#039;&#039;MIDI&#039;&#039; settings. In order to change the &#039;&#039;command mapping&#039;&#039; for a &#039;&#039;MIDI message&#039;&#039; in a specific &#039;&#039;MIDI configuration&#039;&#039;, the following &#039;&#039;commands&#039;&#039; are used;&lt;br /&gt;
 &lt;br /&gt;
 * &#039;&#039;&#039;noteon/non&#039;&#039;&#039;:&#039;&#039;commands&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed for a &#039;note on&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;noteoff/nof&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;note off&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;polyaftertouch/pat&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;poly aftertouch&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;channelaftertouch/cat&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;channel aftertouch&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;pitchbend/pb&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;pitch bend&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;programchange/pc&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;program change&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;continuouscontrollerdata/ccd&#039;&#039;&#039;&#039;&#039;:controller:commands&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed for &#039;continuous controller&#039; no &#039;&#039;controller&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
We can of course use the &#039;&#039;&amp;quot;&#039;&#039;rqi&amp;quot;-&#039;&#039;command&#039;&#039; to check the current mapping, below we are asking what the current &#039;&#039;command string&#039;&#039; associated with the &#039;&#039;pitch bend&#039;&#039; &#039;&#039;MIDI message&#039;&#039; is in the currently selected &#039;&#039;MIDI configuration&#039;&#039;.&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
rqi:midieventhandler:pb&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
rqi:bowingwheel.midiconfigurationhandler.midiconfiguration.pitchbend&lt;br /&gt;
&amp;lt;/pre&amp;gt;This may return something like&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
[irq]mev:pb:&amp;quot;bowcontrolharmonicshift:pitch*4&amp;quot;&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
[irq]bw[0].mcf[0].mc[0].pb:&amp;quot;bowingwheel.harmonicserieshandler.harmonicseries.shift:pitch*4&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;The first part of the return message tells us that the incoming message is of &amp;quot;rqi&amp;quot;-type (&amp;quot;[irq]&amp;quot;) which means it&#039;s responding to a information request &#039;&#039;command&#039;&#039; sent. The second part tells us what &#039;&#039;command&#039;&#039; the information request return is responding to and any &#039;&#039;parameters&#039;&#039; that may be pertinent. The third part of the message is the actual data stored.  &lt;br /&gt;
&lt;br /&gt;
For the FAR &amp;lt; 1.1 the data returned is for the &#039;&#039;command&#039;&#039; &amp;quot;mev&amp;quot; with the first &#039;&#039;parameter&#039;&#039; set to &amp;quot;pb&amp;quot;, the &#039;&#039;command reference&#039;&#039; tells us this means the &#039;&#039;command&#039;&#039; &amp;quot;midieventhandler&amp;quot; and the &#039;&#039;parameter&#039;&#039; &amp;quot;pb&amp;quot; indicates this has to do with the &#039;&#039;pitch bend&#039;&#039;. The data is &amp;quot;bowcontrolharmonicshift*4&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
For the FAR 1.1 the data returned is for the &#039;&#039;command&#039;&#039; &amp;quot;bw[0].mcf[0].mc[0].pb&amp;quot; (bowinwheel[0].midiconfigurationhandler[0].midiconfiguration[0].pitchbend) and the data is &amp;quot;bowingwheel.harmonicserieshandler.harmonicseries.shift:pitch*4&amp;quot;. Note here that if we have several different &#039;&#039;MIDI configurations&#039;&#039; stored and we&#039;re currently using configuration number 2, the returned message would have been &amp;quot;bw[0].mcf[0].mc[2].pb&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
that the &#039;&#039;pitch bend MIDI message&#039;&#039; is executing a &amp;quot;bowcontrolharmonicshift&amp;quot; / &amp;quot;harmonicseries.shift&amp;quot;-command with the parameter &#039;&#039;pitch*4&#039;&#039;. Looking in the &#039;&#039;command reference&#039;&#039; we can see that &#039;&#039;&amp;quot;&#039;&#039;bowcontrolharmonicshift&amp;quot; / &amp;quot;harmonicseries.shift&amp;quot;-&#039;&#039;command&#039;&#039; shifts the frequency of the &#039;&#039;bowing wheel&#039;&#039; from the currently selected harmonic. The first (and only) &#039;&#039;parameter&#039;&#039; sets how much we want to shift it (the range depends on the &amp;quot;bowcontrolharmonicshiftrange&#039;&#039;&amp;quot;&#039;&#039; / &amp;quot;harmonicseries.shiftrange&amp;quot;-&#039;&#039;command&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
If we look in the list of &#039;&#039;[[The Ekdahl FAR - Command langue#Variables|variables]]&#039;&#039; above we can see that the &#039;&#039;pitch bend MIDI message&#039;&#039; will set the &amp;quot;pitch&amp;quot;&#039;&#039;-variable&#039;&#039; which is indeed used. Now what is the &#039;&#039;&#039;*4&#039;&#039;&amp;lt;nowiki/&amp;gt;&#039; all about? Well the &amp;quot;bowcontrolharmonicshift&amp;quot; / &amp;quot;harmoniceseries.shift&amp;quot;-&#039;&#039;command&#039;&#039; expects a &#039;&#039;16-bit signed&#039;&#039; value as its &#039;&#039;parameter&#039;&#039;. This means that the valid &#039;&#039;parameter&#039;&#039; number can be anything from -32767 to 32767. A full &#039;&#039;harmonic shift&#039;&#039; downwards according to the range set is equal to -32767, a full &#039;&#039;harmonic shift&#039;&#039; upwards is 32767 and no &#039;&#039;harmonic shift&#039;&#039; is 0. The &#039;&#039;pitch bend MIDI message&#039;&#039; however is only 14-bits, meaning its range is -8192 to 8192. So we have to multiply &#039;&#039;pitch&#039;&#039; by 4 in order to meet the requirements of a &#039;&#039;16-bit signed parameter&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
This whole thing about number of bits can seem confusing but in the end it&#039;s all about how fine control you have over things; the more possible values, the more detailed control. In fact, most &#039;&#039;MIDI&#039;&#039; values are only 7-bit (!) meaning a range of 0 - 127. While this may sound like a lot of detail for something like a volume control, it is not even close to enough resolution to for instance set the &#039;&#039;bowing frequency&#039;&#039;. Even if you would limit yourself to a single octave the instrument would never be able to be properly in tune. The idea of limiting the Ekdahl FAR to what is possible through &#039;&#039;MIDI&#039;&#039; seemed like a poor choice thus it was decided that &amp;lt;u&amp;gt;most&amp;lt;/u&amp;gt; parameters will instead be 16-bit.&lt;br /&gt;
&lt;br /&gt;
Now lets look at a more complex example, the &amp;lt;u&amp;gt;default&amp;lt;/u&amp;gt; &#039;&#039;Note On MIDI message&#039;&#039;. On a stock Ekdahl FAR, executing&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
rqi:mev:noteon&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
rqi:mcf.mf.non&lt;br /&gt;
&amp;lt;/pre&amp;gt;Will return something like&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
[irq]mev:noteon:&#039;bchb:note,bmr:1,bpid:1,bpe:1,se:(velocity*512)*(1-notecount),bcsm:0&#039;&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
[irq]mcf[0].mc[0].non:&#039;bw.hsh.hb:note,bw.dcm.ru:1,bw.pe:1,bw.bp.en:1,so.en:(velocity*512)*(1-notecount),bw.sm:0&#039;&amp;lt;/pre&amp;gt;As can be seen, there&#039;s a lot of stuff going on here! First of all, notice that everything after &amp;quot;mev:noteon:&amp;quot; / &amp;quot;mcf[0].mc[0].non:&amp;quot; is situated in between single quotes (&#039;) - this is &amp;lt;u&amp;gt;absolutely crucial&amp;lt;/u&amp;gt; for the Ekdahl FAR in order to know that everything within those last two quotes is part of the last &#039;&#039;parameter&#039;&#039; of the &amp;quot;mev&amp;quot; / &amp;quot;mcf.mc.non&amp;quot;-&#039;&#039;command&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Now let&#039;s break down what happens when this &#039;&#039;MIDI message&#039;&#039; is received, i.e. when a &#039;&#039;MIDI&#039;&#039; key is pressed down:&lt;br /&gt;
&lt;br /&gt;
# &amp;quot;bchb:note&amp;quot; / &amp;quot;bw.hsh.hb:note&amp;quot;  - Invokes the &amp;quot;bowcontrolharmonicbase&amp;quot; / &amp;quot;harmonicserieshandler.harmonicbase&amp;quot;&#039;&#039;-command&#039;&#039; with the first &#039;&#039;parameter&#039;&#039; set to the &#039;&#039;variable note&#039;&#039;. This sets the &#039;&#039;base harmonic&#039;&#039; that the Ekdahl FARs &#039;&#039;bowing motor&#039;&#039; should be set to.&lt;br /&gt;
# &amp;quot;bmr:1&amp;quot; / &amp;quot;bw.dcm.ru&amp;quot; - Sets the &amp;quot;bowmotorrun&amp;quot; / &amp;quot;dcmotor.run&amp;quot;-command to &#039;1&#039;, starting the &#039;&#039;bow motor&#039;&#039;&lt;br /&gt;
# &amp;quot;bpid:1&amp;quot; / &amp;quot;bw.pe:1&amp;quot; - Sets the &amp;quot;bowpid&amp;quot; / &amp;quot;bowingwheel.pidenable&amp;quot;-&#039;&#039;command&#039;&#039; to &#039;1&#039;. Basically this enables the function that makes the Ekdahl FAR able to keep a stable frequency on the &#039;&#039;bowing motor&#039;&#039;.&lt;br /&gt;
# &amp;quot;bpe:1&amp;quot; / &amp;quot;bw.bp.en&amp;quot; - Sets the &amp;quot;bowpressureengage&amp;quot; / &amp;quot;bowpressure.engage&amp;quot;-&#039;&#039;command&#039;&#039; to &#039;1&#039; which moves the &#039;&#039;bowing jack&#039;&#039; to the &#039;&#039;engage position&#039;&#039;&lt;br /&gt;
# &amp;quot;se:(velocity*512)*(1-notecount)&amp;quot; / &amp;quot;so.en:(velocity*512)*(1-notecount)&amp;quot; - Executes the &amp;quot;solenoidengage&amp;quot; / &amp;quot;solenoid.engage&amp;quot;-&#039;&#039;command&#039;&#039; with the value &#039;&#039;(velocity*512)*(1-notecount)&#039;&#039;. This will make the &#039;&#039;solenoid&#039;&#039; strike the &#039;&#039;hammer&#039;&#039; with a force that is dependent on the &#039;&#039;velocity&#039;&#039; variable sent by the &#039;&#039;Note On MIDI message&#039;&#039; in order to make the &#039;&#039;hammer&#039;&#039; velocity sensitive.  But it also adds the somewhat perplexing part &amp;quot;*(1-notecount)&amp;quot;. &amp;quot;notecount&amp;quot; is a global &#039;&#039;variable&#039;&#039; that contains the number of MIDI keys that are currently being held down. If &amp;quot;notecount&amp;quot; is anything above zero, the outcome of the equation will either be zero or a negative number. The &amp;quot;solenoidengage&amp;quot; / &amp;quot;solenoid.engage&amp;quot;-&#039;&#039;command&#039;&#039; requires a &#039;&#039;16-bit unsigned&#039;&#039; value, aka the only valid numbers are 0 - 65535. Anything below 0 will be interpreted as zero, so what this equation does is that it only fires off the &#039;&#039;hammer&#039;&#039; if there are no previous keys being held down - it&#039;s going into &#039;&#039;staccato&#039;&#039;  mode.&lt;br /&gt;
# &amp;quot;bcsm:0&amp;quot; / &amp;quot;bowingwheel.speedmode&amp;quot; - Sets the &amp;quot;bowcontrolspeedmode&amp;quot; / &amp;quot;bowingwheel.speedmode&amp;quot; to &#039;1&#039; which enables automatic shut down of the &#039;&#039;bowing motor&#039;&#039; after a given timeout.&lt;br /&gt;
The first two &#039;&#039;commands&#039;&#039; are the &#039;&#039;module&#039;&#039;- and &#039;&#039;bow-&#039;&#039;command. These &#039;&#039;commands&#039;&#039; are is intended for future versions of the Ekdahl FAR that may contain more than one string or more than one bow per string. For now &#039;&#039;0&#039;&#039; is the only valid &#039;&#039;parameter&#039;&#039; value that will be accepted for either &#039;&#039;command&#039;&#039;.&#039;&#039;&amp;lt;nowiki/&amp;gt;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;bowcontrolharmonicbase&#039;&#039;-command sets the speed of the &#039;&#039;bowing wheel&#039;&#039; to its corresponding &#039;&#039;harmonic number&#039;&#039; but also takes into account its &#039;&#039;&amp;lt;nowiki/&amp;gt;&#039;base&#039;&#039;&#039; which is the &#039;&#039;MIDI key&#039;&#039; that is mapped to &#039;&#039;harmonic number 0&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
After this the bowing motor is started and the &#039;&#039;PID&#039;&#039; is turned, now the instrument will try and make sure that the &#039;&#039;bowing wheel&#039;&#039; is at the right speed.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;bowing jack&#039;&#039; is raised to the &#039;&#039;engage position&#039;&#039;, any added &#039;&#039;pressure modifiers&#039;&#039; will also be taken into account - once the &#039;&#039;bowing jack&#039;&#039; has reached its intended position the &#039;&#039;bowing wheel&#039;&#039; should (hopefully) make contact with the string and the Ekdahl FAR will start to produce sounds.&lt;br /&gt;
&lt;br /&gt;
After this we have the &#039;&#039;solenoidengage&#039;&#039;-command &#039;&#039;command&#039;&#039; that engages the &#039;&#039;hammer&#039;&#039; and uses the first and only &#039;&#039;parameter&#039;&#039; as the force used. Like with most &#039;&#039;commands&#039;&#039; the &#039;&#039;se&#039;&#039;-command is 16-bit (0 - 65535) but the &#039;&#039;MIDI velocity variable&#039;&#039; is 7-bit (0 - 127), so to get the &#039;&#039;velocity&#039;&#039; variable to cover the entire range it needs to be multiplied with 512. &lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&amp;lt;nowiki/&amp;gt;&#039;*(1-notecount)&#039;&#039;&#039;-part is a way of making sure that we are using &#039;&#039;legato&#039;&#039; mode, i.e. that the &#039;&#039;hammer&#039;&#039; is not triggered if a key is already held down when a new key is pressed. The &#039;&#039;notecount&#039;&#039;-variable contains the number of &#039;&#039;MIDI&#039;&#039; notes currently held down. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s postulate that the Ekdahl FAR is tuned to a &#039;C&#039; at 65.4Hz and has its &#039;&#039;base&#039;&#039; set to middle &#039;C&#039; (&#039;&#039;MIDI key&#039;&#039; no 36). We are using the equal-temperament 12-tone scale and the Ekdahl FAR is set to respond to &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; &#039;&#039;MIDI channels&#039;&#039; (omni). Without having previously held any keys we press the middle &#039;C&#039; (&#039;&#039;note&#039;&#039; value 36) as hard as possible (&#039;&#039;velocity&#039;&#039; value &#039;&#039;127&#039;&#039;) on &#039;&#039;MIDI channel&#039;&#039; number 1 (&#039;&#039;channel&#039;&#039; value of 0). The Ekdahl FAR will get a &#039;&#039;note on MIDI message&#039;&#039; sent to it and from our mapping it will create the following &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;[irq]mev:noteon:&#039;m:0,b:0,bchb:36,bmr:1,bpid:1,bpe:1,se:(127*512)*(1-0),bcsm:0&#039;&amp;lt;/pre&amp;gt;What has happened here is that all &#039;&#039;variables&#039;&#039; have been replaced with the values sent by the &#039;&#039;MIDI message&#039;&#039;. Since those &#039;&#039;commands&#039;&#039; that doesn&#039;t have any &#039;&#039;variables&#039;&#039; with them will execute just as previously, only those &#039;&#039;commands&#039;&#039; whos &#039;&#039;parameters&#039;&#039; have changed will be explained:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;bchb: 36&#039;&#039; - The &#039;&#039;bowcontrolharmonicbase&#039;&#039; gets a value of &#039;&#039;36&#039;&#039; (middle &#039;C&#039;), because &#039;&#039;harmonic number 0&#039;&#039; is mapped to this key it will set the &#039;&#039;bowing wheel&#039;&#039; frequency to the &#039;&#039;fundamental&#039;&#039;; &#039;&#039;65.4&#039;&#039; Hertz&lt;br /&gt;
# &#039;&#039;se: (127*512)*(1-0)&#039;&#039; - the value of &#039;&#039;127&#039;&#039; comes from the &#039;&#039;velocity&#039;&#039;-variable, &#039;&#039;127 * 512 = 65024&#039;&#039; which is awfully close to a maximum hammer force of 65535. Since no previous notes were held down &#039;&#039;notecount&#039;&#039;  is equal to &#039;&#039;0&#039;&#039; and thus &#039;&#039;65024 * 1 = 65024&#039;&#039;. The hammer is engaged with near maximum force.&lt;br /&gt;
So the result is that we have set the speed of the &#039;&#039;bowing motor&#039;&#039; and we have engaged the &#039;&#039;hammer&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Now imagine that without releasing this key, we press another &#039;C&#039; one octave above but at half the velocity. The Ekdahl FAR creates the following &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
[irq]mev:noteon:&#039;m:0,b:0,bchb:48,bmr:1,bpid:1,bpe:1,se:(63*512)*(1-1),bcsm:0&#039;&lt;br /&gt;
&amp;lt;/pre&amp;gt;Now we can see that the &#039;&#039;note&#039;&#039; variable is &#039;&#039;48&#039;&#039; because the &#039;C&#039; one octave up is exactly 12 keys above the first, the &#039;&#039;velocity&#039;&#039; variable has changed to &#039;&#039;63&#039;&#039; since we hit it with a lighter touch - and because we are &amp;lt;u&amp;gt;still holding the first key down&amp;lt;/u&amp;gt; &#039;&#039;notecount&#039;&#039; is equal to &#039;&#039;1&#039;&#039;. Here&#039;s what happens&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;bchb: 48&#039;&#039; - Due to the &#039;&#039;base&#039;&#039; being set to &#039;&#039;36&#039;&#039; the &#039;&#039;harmonic number&#039;&#039; is set to &#039;&#039;48 - 36 = 12&#039;&#039;. Because we are using a 12-tone scale &#039;&#039;harmonic number 12&#039;&#039; is exactly one octave above the &#039;&#039;fundamental&#039;&#039; thus the speed of the &#039;&#039;bowing wheel&#039;&#039; is set to &#039;&#039;65.4 * 2 = 130.8&#039;&#039; Hertz.&lt;br /&gt;
# &#039;&#039;se: (63*512)*(1-1)&#039;&#039; - So &#039;&#039;63 * 512 = 32256&#039;&#039; and &#039;&#039;1 - 1 = 0&#039;&#039; thus &#039;&#039;32256 * 0 = 0&#039;&#039;. When the &#039;&#039;solenoidengage&#039;&#039;-command gets a &#039;&#039;parameter&#039;&#039; of &#039;&#039;0&#039;&#039; it will not engage the &#039;&#039;hammer&#039;&#039; - so the &#039;&#039;hammer&#039;&#039; doesn&#039;t strike&lt;br /&gt;
So it can be seen that with quite rudimentary math we can accomplish a whole lot of things here. Note also that even though the &#039;&#039;note on MIDI message&#039;&#039; also sets the &#039;&#039;channel&#039;&#039;-variable we never use it in this example - plenty of opportunity to make something weird happen depending on the &#039;&#039;MIDI channel&#039;&#039;!&lt;br /&gt;
&lt;br /&gt;
== CV Mapping ==&lt;br /&gt;
&#039;&#039;CV Mapping&#039;&#039; works exactly like the &#039;&#039;MIDI mapping&#039;&#039; with the difference that the command for setting the &#039;&#039;CV mapping&#039;&#039; is different and that &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; events pertaining to this &amp;lt;u&amp;gt;only&amp;lt;/u&amp;gt; change the &#039;&#039;value&#039;&#039;-variable. The &#039;&#039;command&#039;&#039; for changing the &#039;&#039;CV mapping&#039;&#039; is &#039;&#039;adccommandmap&#039;&#039; or &#039;&#039;acm&#039;&#039;, it take two &#039;&#039;parameters&#039;&#039;; &#039;&#039;channel&#039;&#039; and &#039;&#039;command string&#039;&#039;. We retrieve the &#039;&#039;command string&#039;&#039; for channel &#039;&#039;0&#039;&#039; which reads the sum of the &#039;&#039;harm. v/oct&#039;&#039;-jack and the &#039;&#039;harmonic&#039;&#039;-knob by sending a command of&amp;lt;pre&amp;gt;&lt;br /&gt;
rqi:acm:0&lt;br /&gt;
&amp;lt;/pre&amp;gt;The &amp;lt;u&amp;gt;default&amp;lt;/u&amp;gt; response will be something like&lt;br /&gt;
&amp;lt;pre&amp;gt;[irq]acm:0:&#039;bcha:value/1327.716667-20&#039;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{docnav&lt;br /&gt;
|[[The Ekdahl FAR - Service|Service]]&lt;br /&gt;
|[[The Ekdahl FAR - Command reference|Command reference]]&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Knaadmin</name></author>
	</entry>
	<entry>
		<id>http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_language&amp;diff=1653</id>
		<title>The Ekdahl FAR - Command language</title>
		<link rel="alternate" type="text/html" href="http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_language&amp;diff=1653"/>
		<updated>2026-06-08T18:17:41Z</updated>

		<summary type="html">&lt;p&gt;Knaadmin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Command language ==&lt;br /&gt;
The Ekdahl FAR is entirely controlled by &#039;&#039;commands&#039;&#039;, these &#039;&#039;commands&#039;&#039; decide everything that the instrument is doing, whether it is playing a melody or changing an internal parameter. &lt;br /&gt;
&lt;br /&gt;
When a &#039;&#039;MIDI message&#039;&#039; is received or a new CV / knob value is read, the &#039;&#039;commands&#039;&#039; associated with it will be internally sent. This can be things like &amp;quot;engage hammer&amp;quot; or &amp;quot;set the fundamental frequency&amp;quot; etc. &lt;br /&gt;
&lt;br /&gt;
Some of the available &#039;&#039;commands&#039;&#039; are mainly used for calibrating and setting up the instrument and are usually saved into the instruments memory, these will be executed whenever the instrument is turned on. &lt;br /&gt;
&lt;br /&gt;
All &#039;&#039;commands&#039;&#039; can be manually invoked via &#039;&#039;USB-Serial&#039;&#039;, in conjunction with certain software this presents an unprecedented level of control and sequenceability.&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
The &#039;&#039;commands&#039;&#039; are invoked using a &#039;&#039;plain text approach&#039;&#039;, all commands have both a &#039;&#039;long name&#039;&#039; and a &#039;&#039;short name&#039;&#039; which are interchangeable. A &#039;&#039;command&#039;&#039; may have one or more &#039;&#039;parameters&#039;&#039; associated with it, these &#039;&#039;parameters&#039;&#039; can be of different types; 16-bit numbers (values 0 - 65535 or -32767 - 32767), floating point numbers (values with decimals), booleans (0 for &#039;false&#039;, 1 for &#039;true&#039;) and strings (text). Some commands are &#039;&#039;conditional&#039;&#039;, meaning they will only execute if a parameter equates to &#039;1&#039; (&#039;true&#039;). &lt;br /&gt;
&lt;br /&gt;
The way &#039;&#039;commands&#039;&#039; are written in order to be executed is &#039;&#039;commandname:parameter1:parameter2:parameter3 [etc]&#039;&#039;, several commands be executed in sequence by separating them with a comma (&#039;,&#039;), a bunch of commands strung together is called a &#039;&#039;command string&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Since version 1.1 of the Ekdahl FAR Firmware, all commands are grouped in a hierarchical fashion according to their &#039;&#039;modules&#039;&#039; and each ladder in the hierarchy is separated by a period (&amp;quot;.&amp;quot;), this works very much like folders or directories in a regular computer. Every &#039;&#039;module&#039;&#039; can contain both &#039;&#039;commands&#039;&#039; and other &#039;&#039;modules&#039;&#039;. For instance, everything associated with the &#039;&#039;bowing wheel&#039;&#039; is now collected under &amp;quot;bowingwheel&amp;quot; &#039;&#039;module&#039;&#039;. That in turn contains a &amp;quot;dcmotor&amp;quot; &#039;&#039;module&#039;&#039; which handles direct control of the bowing motor. It also has a &amp;quot;pid&amp;quot; &#039;&#039;module&#039;&#039; that handles bow frequency among other thing. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If for instance we would like to start the &#039;&#039;bowing wheel&#039;&#039; and set its frequency to 82.5 Hertz we could send the Ekdahl FAR the following &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
bowmotorrun:1, bowcontrolfrequecy:82.5&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bowingwheel.dcmotor.run:1, bowingwheel.pid.targetfrequency:82.5&amp;lt;/pre&amp;gt;We could also use the &#039;&#039;short names&#039;&#039; for the commands&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
bmr:1,bcf:82.5&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bw.dcm.ru:1, bw.pid.tf:82.5&amp;lt;/pre&amp;gt;Both &amp;quot;bowmotorrun&amp;quot; / &amp;quot;bowingwheel.dcmotor.run&amp;quot; and &amp;quot;bowcontrolfrequency&amp;quot; / &amp;quot;bowingwheel.pid.targetfrequency&amp;quot; takes one &#039;&#039;parameter&#039;&#039; each, &#039;&#039;&amp;quot;&#039;&#039;bowmotorrun&amp;quot; / &amp;quot;bowingwheel.dcmotor.run&amp;quot; is &#039;&#039;conditional&#039;&#039; and unless the first &#039;&#039;parameter&#039;&#039; is equal to &#039;1&#039; the motor will not start. The first &#039;&#039;parameter&#039;&#039; of &amp;quot;bowcontrolfrequency&amp;quot; / &amp;quot;bowingwheel.pid.targetfrequency&amp;quot; sets the frequency of the &#039;&#039;bowing wheel&#039;&#039;, the instrument may not execute a &#039;&#039;command&#039;&#039; if it decides that the given &#039;&#039;parameters&#039;&#039; are outside of the working range or they are missing.&lt;br /&gt;
&lt;br /&gt;
The addition of the hierarchy in the FAR 1.1 firmware isn&#039;t just to be able to group commands, but it&#039;s also to make the FAR not limited to a single set of &#039;&#039;modules&#039;&#039; (and is the first stepping stone to a &#039;&#039;modular&#039;&#039; Ekdahl FAR). In fact, you could have 12 different bowing wheel &#039;&#039;modules&#039;&#039; for 12 different strings, these would then be addressed as &amp;quot;bowingwheel[0].command&amp;quot;&#039;&#039;, &amp;quot;&#039;&#039;bowingwheel[1].command&amp;quot; etc. Anyone familiar with C programming notices that this is the standard way of &#039;&#039;indexing&#039;&#039; an array; using brackets (&amp;quot;[ ]&amp;quot;). When addressing a module without &#039;&#039;indexing&#039;&#039; as in the example above, the FAR will do one or two things; either use the first object (&amp;quot;[0]&amp;quot;) or, if the object is &#039;&#039;selectable&#039;&#039; it will use the previously selected object. To make things smoother a command can be executed on several objects at once by using ranges (&amp;quot;[0-4]&amp;quot;) and comma separation (&amp;quot;[0, 3, 5-6]&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
To test out a &#039;&#039;command&#039;&#039; you can send it directly to the Ekdahl FAR using the &#039;&#039;Console&#039;&#039; in the &#039;&#039;Configuration utility&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
To read up on existing &#039;&#039;commands&#039;&#039;, their &#039;&#039;parameters&#039;&#039; and a brief description you can check the &#039;&#039;Command reference&#039;&#039; in the &#039;&#039;Configuration utility&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Variables, functions and equations ==&lt;br /&gt;
What makes the &#039;&#039;Command language&#039;&#039; truly powerful is the concept of &#039;&#039;variables, functions&#039;&#039; and &#039;&#039;equations&#039;&#039;. All &#039;&#039;parameters&#039;&#039; that take numerical values can use any combination of &#039;&#039;variables, functions&#039;&#039; or &#039;&#039;equations.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
For instance, we can use the previous example and instead write our &#039;&#039;command string&#039;&#039; as follows&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
bowmotorrun:1, bowcontrolfrequency:82.5+note*20&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bowingwheel.dcmotor.run:1, bowingwheel.pid.targetfrequency:82.5+note*20&amp;lt;/pre&amp;gt;This example requires of course that the &#039;&#039;variable&#039;&#039; &#039;&#039;note&#039;&#039; exists in the current context. &lt;br /&gt;
&lt;br /&gt;
===== Variables =====&lt;br /&gt;
There are two types of &#039;&#039;variables&#039;&#039; in the Ekdahl FAR; &#039;&#039;global variables&#039;&#039; and &#039;&#039;event variables&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Global variables&#039;&#039; are variables that are always valid, in any context. The &#039;&#039;global variables&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;notecount&#039;&#039;&#039; - Contains the number of &#039;&#039;MIDI&#039;&#039; keys that are being held down, i.e. all &#039;&#039;Note on messages&#039;&#039; received that haven&#039;t gotten a paired &#039;&#039;Note off message&#039;&#039; yet&lt;br /&gt;
* &#039;&#039;&#039;uv0&#039;&#039;&#039; - &#039;&#039;&#039;uv9&#039;&#039;&#039; - These are &#039;&#039;user variables&#039;&#039; and can be set at any point using the &#039;&#039;globaluservariable command&#039;&#039; with the first &#039;&#039;parameter&#039;&#039; being which variable to set (0-9) and the second &#039;&#039;parameter&#039;&#039; being the value (float).&lt;br /&gt;
* &#039;&#039;&#039;e&#039;&#039;&#039; - Contains the constant &#039;&#039;[[wikipedia:E_(mathematical_constant)|e]]&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pi&#039;&#039;&#039; - Contains the constant &#039;&#039;[[wikipedia:Pi|pi]]&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Event variables&#039;&#039; are variables that are set by certain &#039;&#039;MIDI messages&#039;&#039; or when a new value is read on one of the jacks or knobs on the &#039;&#039;Control box&#039;&#039;. The &#039;&#039;Event variables&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;channel&#039;&#039;&#039; - Set by the &#039;&#039;Note on, Note off, Continuous Controller, Poly after touch, Pitch bend, Channel after touch&#039;&#039; and &#039;&#039;Program change MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;note&#039;&#039;&#039; - Set by the &#039;&#039;Note on, Note off&#039;&#039; and &#039;&#039;Poly after touch MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;velocity&#039;&#039;&#039; - Set by the &#039;&#039;Note on&#039;&#039; and &#039;&#039;Note off MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pressure&#039;&#039;&#039; - Set by the &#039;&#039;Poly after touch&#039;&#039; and &#039;&#039;Channel after touch MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; - Set by the &#039;&#039;Continuous Controller MIDI message&#039;&#039; and by the &#039;&#039;Control box&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pitch&#039;&#039;&#039; - Set by the &#039;&#039;Pitch bend MIDI message&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;program&#039;&#039;&#039; - Set by the &#039;&#039;Program change MIDI message&#039;&#039;&lt;br /&gt;
These variables will contain whatever data is relevant to the last event that occurred and may be overwritten by the next event.&lt;br /&gt;
&lt;br /&gt;
===== Functions =====&lt;br /&gt;
&#039;&#039;Functions&#039;&#039; can be used to change a numerical value or the result of an &#039;&#039;equation&#039;&#039;, the Ekdahl FAR contains both general &#039;&#039;arithmetic functions&#039;&#039; (courtesy of Lewis Van Winkle and the TINYEXPR engine) and &#039;&#039;specialized functions&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;arithmetic functions&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;abs&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Absolute_value|absolute value]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;acos&#039;&#039;&#039;(x), &#039;&#039;&#039;asin&#039;&#039;&#039;(x), &#039;&#039;&#039;atan&#039;&#039;&#039;(x), atan2(x, y) - Returns the [[wikipedia:Inverse_trigonometric_functions|&#039;&#039;arc-cos, -sin, -tan&#039;&#039; and &#039;&#039;-tan2&#039;&#039;]] of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;atan2&#039;&#039;&#039;(x,y) - Returns the &#039;&#039;[[wikipedia:Atan2|arctan2]]&#039;&#039; of &#039;&#039;x, y&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;floor&#039;&#039;&#039;(x), ceil(x) - Returns the [[wikipedia:Floor_and_ceiling_functions|&#039;&#039;floor&#039;&#039; and &#039;&#039;ceiling&#039;&#039;]] of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;exp&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Exponential_function|exponent]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;fac&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Factorial|factorial]]&#039;&#039; of x&lt;br /&gt;
* &#039;&#039;&#039;ln&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Natural_logarithm|natural logarithm]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;log10&#039;&#039;&#039;(x), &#039;&#039;&#039;log20&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Logarithm|logarithm]]&#039;&#039; of &#039;&#039;x&#039;&#039; using base 10 and 20 respectively&lt;br /&gt;
* &#039;&#039;&#039;ncr&#039;&#039;&#039;(x,y), &#039;&#039;&#039;npr&#039;&#039;&#039;(x,y) - Functions to calculate &#039;&#039;[[wikipedia:Combination|combinations]]&#039;&#039; and &#039;&#039;[[wikipedia:Permutation|permutations]]&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pow&#039;&#039;&#039;(x,y) - Returns &#039;&#039;x^y&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;sqrt&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Square_root|square root]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;cos&#039;&#039;&#039;(x), &#039;&#039;&#039;sin&#039;&#039;&#039;(x), &#039;&#039;&#039;tan&#039;&#039;&#039;(x) - Returns the [[wikipedia:Trigonometric_functions|&#039;&#039;cos, sin&#039;&#039; and &#039;&#039;tan&#039;&#039;]] of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;cosh&#039;&#039;&#039;(x), &#039;&#039;&#039;sinh&#039;&#039;&#039;(x), &#039;&#039;&#039;tanh&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Hyperbolic_functions|hyperbolic cos, sin and tan]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
The &#039;&#039;specialized functions&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;bool&#039;&#039;&#039;(x) - Returns 1 if &#039;&#039;x&#039;&#039; is more than 0&lt;br /&gt;
* &#039;&#039;&#039;ibool&#039;&#039;&#039;(x) - Returns 0 if &#039;&#039;x&#039;&#039; is more than 0&lt;br /&gt;
* &#039;&#039;&#039;deadband&#039;&#039;&#039;(x,y) - Returns &#039;&#039;x + y &#039;&#039; if &#039;&#039;x &amp;lt; y&#039;&#039; or &#039;&#039;x - y&#039;&#039; if &#039;&#039;x &amp;gt; y&#039;&#039;. If neither of these statements is true it returns &#039;&#039;0&#039;&#039; - used to create a [[wikipedia:Deadband|deadband]] of &#039;&#039;x&#039;&#039; with the threshold of &#039;&#039;y&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Functions&#039;&#039; can be readily used in a &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
bowmotorrun:1, bowcontrolfrequency:&amp;quot;8.17579875 * pow(2, (1/12 * note))&amp;quot;&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bowingwheel.dcmotor.run:1, bowingwheel.pid.targetfrequency:&amp;quot;8.17579875 * pow(2, (1/12 * note))&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;The previous statements starts the &#039;&#039;bowing wheel&#039;&#039; and sets the frequency of the wheel to &#039;&#039;8.17579875 * 2^(1/12 * note)&#039;&#039;. A middle &#039;C&#039; according to &#039;&#039;MIDI&#039;&#039; has a &#039;&#039;note value&#039;&#039; of 36, meaning if we substitute &#039;&#039;note&#039;&#039; with 36 we get the equation &#039;&#039;8.17579875 * 2^(1/12 * 36)&#039;&#039; which comes out to &#039;&#039;~65.4&#039;&#039; Hertz.&lt;br /&gt;
&lt;br /&gt;
Note that the first &#039;&#039;parameter&#039;&#039; for &#039;&#039;&amp;quot;&#039;&#039;bowcontrolfrequency&amp;quot; / &amp;quot;bowingwheel.pid.targetfrequency&amp;quot; is put in between double quotes (&amp;quot;). This is because the &amp;quot;pow&#039;&#039;&amp;quot;-&#039;&#039;function requires the use of a comma (&amp;quot;,&amp;quot;) in order to separate in between its two required inputs; &#039;&#039;x&#039;&#039; and &#039;&#039;y&#039;&#039;. In order for the Ekdahl FAR to know that this comma does not signal the beginning of a new &#039;&#039;command,&#039;&#039; we use quotes. Single (&#039;) and double (&amp;quot;) quotes can be used and nested in all &#039;&#039;parameters&#039;&#039; and are &amp;lt;u&amp;gt;required&amp;lt;/u&amp;gt; in a lot of circumstances, improper nesting or not using quotes can lead to the instrument not understanding the &#039;&#039;command string&#039;&#039; correctly.&lt;br /&gt;
&lt;br /&gt;
== Return messages ==&lt;br /&gt;
The Ekdahl FAR when connected via &#039;&#039;USB-Serial&#039;&#039; doesn&#039;t only accept &#039;&#039;commands&#039;&#039; but will also send various &#039;&#039;return messages&#039;&#039;. These are prefixed by their &#039;&#039;category&#039;&#039; denoted in brackets (&amp;quot;[]&amp;quot;), the existing categories as of this writing (2025-01-22) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;command&#039;&#039;&#039; / &#039;&#039;&#039;cmd&#039;&#039;&#039; - Acknowledges the reception of a command in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;usb&#039;&#039;&#039; - Acknowledges the reception of a &#039;&#039;MIDI message&#039;&#039; over &#039;&#039;USB&#039;&#039; in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;hardware&#039;&#039;&#039; / &#039;&#039;&#039;hw&#039;&#039;&#039; - Signals that a change has been sent to the Ekdahl FAR hardware, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;undefined&#039;&#039;&#039; / &#039;&#039;&#039;un&#039;&#039;&#039; - The message sent is in the &#039;&#039;undefined&#039;&#039; category, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;priority&#039;&#039;&#039; / &#039;&#039;&#039;pri&#039;&#039;&#039; - The message sent is in the &#039;&#039;priority&#039;&#039; category, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;error&#039;&#039;&#039; / &#039;&#039;&#039;err&#039;&#039;&#039; - Signals that an &#039;&#039;error&#039;&#039; has occurred, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;expressionparser&#039;&#039;&#039; / &#039;&#039;&#039;ep&#039;&#039;&#039; - These messages contains debugging information regarding the internal &#039;&#039;expression parser&#039;&#039; and is used for development&lt;br /&gt;
*&#039;&#039;&#039;debug&#039;&#039;&#039; / &#039;&#039;&#039;dbg&#039;&#039;&#039; - These messages contains various debugging information and is used for development&lt;br /&gt;
*&#039;&#039;&#039;help&#039;&#039;&#039; / &#039;&#039;&#039;hlp&#039;&#039;&#039; - Signals that the message is a response to a &#039;&#039;help&#039;&#039;-command being sent to the Ekdahl FAR. These messages are structured so that a receiver, like the &#039;&#039;Configuration utility&#039;&#039;, can parse information about available &#039;&#039;commands&#039;&#039; in the current &#039;&#039;firmware&#039;&#039; and relay it to a user in a structured way.&lt;br /&gt;
* &#039;&#039;&#039;inforequest&#039;&#039;&#039; / &#039;&#039;&#039;irq&#039;&#039;&#039; - Signals that an &#039;&#039;info request&#039;&#039; has been returned. This is a specialized message that is either sent as a response to an &#039;&#039;rqi&#039;&#039;-command or as a &#039;&#039;interrupt&#039;&#039;-message telling the user or receiving software about different parameters in the Ekdahl FAR. These messages follows the same structure as regular &#039;&#039;command message&#039;&#039;s of &#039;&#039;[irq]commandname:parameter1 [etc]&#039;&#039; so that it can be used by a receiving software to keep track of parameter changes&lt;br /&gt;
&lt;br /&gt;
===== Explicitly requesting information =====&lt;br /&gt;
By using the special command &amp;quot;requestinfo&amp;quot; / &amp;quot;rqi&amp;quot; one can request the information stored by a certain &#039;&#039;command&#039;&#039; or a state of the Ekdahl FAR. The &amp;quot;rqi&amp;quot;-command is executed in the convention &amp;quot;rqi:commandname:optional parameters&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
To go back to our example of setting the bowing frequency using the &#039;&#039;&amp;quot;&#039;&#039;bowcontrolfrequency&amp;quot; / &amp;quot;bowingwheel.pid.targetfrequency&amp;quot;-command we can ask the Ekdahl FAR what the bowing frequency is set to by writing&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
rqi:bowcontrolfrequency&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
rqi:bowingwheel.pid.targetfrequency&lt;br /&gt;
&amp;lt;/pre&amp;gt;The return value would be something like&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
[irq]bcf:82.5&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
[irq]bw[0].pid[0].tf:82.5&lt;br /&gt;
&amp;lt;/pre&amp;gt;Where &#039;[irq]&#039; denotes that the message returned is in the &#039;&#039;info request-&#039;&#039;category, that it pertains to the command &amp;quot;bcf&amp;quot; / &amp;quot;bw.pid.tf&amp;quot; and has the value &#039;&#039;82.5&#039;&#039;. Note that the returned &#039;&#039;command&#039;&#039; sent by an &amp;quot;rqi&amp;quot;-command always uses the &#039;&#039;short name&#039;&#039; in order to preserve bandwidth. In the FAR 1.1 the return statement always returns the &#039;&#039;index&#039;&#039; of the &#039;&#039;module&#039;&#039;(s) in question. &lt;br /&gt;
&lt;br /&gt;
Most commands do not require any &#039;&#039;parameters&#039;&#039; when using the &amp;quot;rqi&amp;quot;-command. The &#039;&#039;&amp;quot;&#039;&#039;adcread&amp;quot; / &amp;quot;controlbox.datareturn&amp;quot;-command is an example of a &#039;&#039;command&#039;&#039; that &amp;lt;u&amp;gt;does&amp;lt;/u&amp;gt; require a &#039;&#039;parameter&#039;&#039; when used with &amp;quot;rqi&amp;quot;. The &amp;quot;adcread&amp;quot; / &amp;quot;controlbox.datareturn&amp;quot;&#039;&#039;-&#039;&#039;command returns the last value read by the &#039;&#039;analog-to-digital converter&#039;&#039; in the &#039;&#039;Control box&#039;&#039;, because there are 8 different channels the first &#039;&#039;parameter&#039;&#039; sets which channel to return the data for, hence executing the &#039;&#039;command&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
rqi:adcr:3&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
rqi:controlbox.datareturn:3&lt;br /&gt;
&amp;lt;/pre&amp;gt;will return the last data read on &#039;&#039;analog-to-digital convert&#039;&#039; channel 3.&lt;br /&gt;
&lt;br /&gt;
== MIDI mapping ==&lt;br /&gt;
The way &#039;&#039;MIDI&#039;&#039; works int the Ekdahl FAR is that each &#039;&#039;MIDI message&#039;&#039; is associated with a certain &#039;&#039;command string&#039;&#039; and the &#039;&#039;MIDI message&#039;&#039; will also update some of the internal &#039;&#039;variables&#039;&#039;. Any time the associated &#039;&#039;MIDI message&#039;&#039; is received the Ekdahl FAR will execute the &#039;&#039;commands&#039;&#039; that have been associated with that &#039;&#039;MIDI message&#039;&#039;. Several &#039;&#039;MIDI configurations&#039;&#039; can be stored and recalled at any time, each with a different set of &#039;&#039;commands&#039;&#039; associated with each &#039;&#039;MIDI message&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;FAR &amp;lt; 1.1:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;FAR &amp;lt; 1.1&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 The &#039;&#039;command&#039;&#039; responsible for mapping &#039;&#039;command strings&#039;&#039; to different &#039;&#039;MIDI messages&#039;&#039; is &amp;quot;midieventhandler&amp;quot; or &amp;quot;mev&amp;quot; for short. The first &#039;&#039;parameter&#039;&#039; of &amp;quot;mev&amp;quot; is the type of &#039;&#039;MIDI message&#039;&#039; that we want to remap;&lt;br /&gt;
 &lt;br /&gt;
 * &#039;&#039;&#039;noteon&#039;&#039;&#039; - Note on&lt;br /&gt;
 * &#039;&#039;&#039;noteoff&#039;&#039;&#039; - Note off&lt;br /&gt;
 * &#039;&#039;&#039;pat&#039;&#039;&#039; - Poly after touch&lt;br /&gt;
 * &#039;&#039;&#039;cat&#039;&#039;&#039; - Channel after touch&lt;br /&gt;
 * &#039;&#039;&#039;pb&#039;&#039;&#039; - Pitch bend&lt;br /&gt;
 * &#039;&#039;&#039;pc&#039;&#039;&#039; - Program change&lt;br /&gt;
 * &#039;&#039;&#039;cc&#039;&#039;&#039; - Continuous controller&lt;br /&gt;
 &lt;br /&gt;
 The second &#039;&#039;parameter&#039;&#039; is the &#039;&#039;command string&#039;&#039; that is to be associated with the &#039;&#039;MIDI Message&#039;&#039; - with the exception of the &#039;&#039;&#039;cc&#039;&#039;&#039;-type, here the second &#039;&#039;parameter&#039;&#039; is the &#039;&#039;controller number&#039;&#039; (0 - 127) and the third &#039;&#039;parameter&#039;&#039; is the &#039;&#039;command string&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;FAR 1.1&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 The &amp;quot;bowingwheel&amp;quot;-&#039;&#039;module&#039;&#039; contains a &#039;&#039;module&#039;&#039; called &amp;quot;midiconfigurationhandler&amp;quot; that handles the loading and switching in between different &#039;&#039;MIDI configurations&#039;&#039;. The &amp;quot;midiconfigurationhandler&amp;quot;&#039;&#039;-module&#039;&#039; has one or more &#039;&#039;&amp;quot;&#039;&#039;midiconfiguration&amp;quot;-&#039;&#039;modules&#039;&#039;, each having its own &#039;&#039;MIDI&#039;&#039; settings. In order to change the &#039;&#039;command mapping&#039;&#039; for a &#039;&#039;MIDI message&#039;&#039; in a specific &#039;&#039;MIDI configuration&#039;&#039;, the following &#039;&#039;commands&#039;&#039; are used;&lt;br /&gt;
 &lt;br /&gt;
 * &#039;&#039;&#039;noteon/non&#039;&#039;&#039;:&#039;&#039;commands&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed for a &#039;note on&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;noteoff/nof&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;note off&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;polyaftertouch/pat&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;poly aftertouch&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;channelaftertouch/cat&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;channel aftertouch&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;pitchbend/pb&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;pitch bend&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;programchange/pc&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;program change&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;continuouscontrollerdata/ccd&#039;&#039;&#039;&#039;&#039;:controller:commands&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed for &#039;continuous controller&#039; no &#039;&#039;controller&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
We can of course use the &#039;&#039;&amp;quot;&#039;&#039;rqi&amp;quot;-&#039;&#039;command&#039;&#039; to check the current mapping, below we are asking what the current &#039;&#039;command string&#039;&#039; associated with the &#039;&#039;pitch bend&#039;&#039; &#039;&#039;MIDI message&#039;&#039; is in the currently selected &#039;&#039;MIDI configuration&#039;&#039;.&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
rqi:midieventhandler:pb&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
rqi:bowingwheel.midiconfigurationhandler.midiconfiguration.pitchbend&lt;br /&gt;
&amp;lt;/pre&amp;gt;This may return something like&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
[irq]mev:pb:&amp;quot;bchsh:pitch*4&amp;quot;&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
[irq]bw[0].mcf[0].mc[0].pb:&amp;quot;bowingwheel.harmonicserieshandler.harmonicseries.shift:pitch*4&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;The first part of the return message tells us that the incoming message is of &amp;quot;rqi&amp;quot;-type (&amp;quot;[irq]&amp;quot;) which means it&#039;s responding to a information request &#039;&#039;command&#039;&#039; sent. The second part tells us what &#039;&#039;command&#039;&#039; the data pertains to, and any &#039;&#039;parameters&#039;&#039; that may be pertinent. The third part of the message is the actual data stored.  &lt;br /&gt;
&lt;br /&gt;
For the FAR &amp;lt; 1.1 the data returned is for the &#039;&#039;command&#039;&#039; &amp;quot;mev&amp;quot; with the first &#039;&#039;parameter&#039;&#039; set to &amp;quot;pb&amp;quot;, the &#039;&#039;command reference&#039;&#039; tells us this means the &#039;&#039;command&#039;&#039; &amp;quot;midieventhandler&amp;quot; and the &#039;&#039;parameter&#039;&#039; &amp;quot;pb&amp;quot; indicates this has to do with the &#039;&#039;pitch bend&#039;&#039;. The data is &amp;quot;bchsh*4&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
For the FAR 1.1 the data returned is for the &#039;&#039;command&#039;&#039; &amp;quot;bw[0].mcf[0].mc[0].pb&amp;quot; (bowinwheel[0].midiconfigurationhandler[0].midiconfiguration[0].pitchbend) and the data is &amp;quot;bowingwheel.harmonicserieshandler.harmonicseries.shift:pitch*4&amp;quot;. Note here that if we have several different &#039;&#039;MIDI configurations&#039;&#039; stored and we&#039;re currently using configuration number 2, the returned message would have been &amp;quot;bw[0].mcf[0].mc[2].pb&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
that the &#039;&#039;pitch bend MIDI message&#039;&#039; is executing a &amp;quot;bchsh&amp;quot; / &amp;quot;-command with the parameter &#039;&#039;pitch*4&#039;&#039;. Looking in the &#039;&#039;command reference&#039;&#039; we can see that &#039;&#039;bchsh&#039;&#039; is the &#039;&#039;short name&#039;&#039; of the &#039;&#039;bowcontrolharmonicshift&#039;&#039;-command which shifts the frequency of the &#039;&#039;bowing wheel&#039;&#039; from the current frequency, the first (and only) parameter sets how much we want to shift it (depends on the &#039;&#039;bowcontrolharmonicshiftrange command&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
If we look in the list of &#039;&#039;[[The Ekdahl FAR - Command langue#Variables|variables]]&#039;&#039; above we can see that the &#039;&#039;pitch bend MIDI message&#039;&#039; will set the &#039;&#039;pitch variable&#039;&#039; which is indeed used. Now what is the &#039;&#039;&#039;*4&#039;&#039;&amp;lt;nowiki/&amp;gt;&#039; all about? Well the &#039;&#039;bchsh&#039;&#039;-command expects a &#039;&#039;16-bit signed&#039;&#039; value, meaning that a full &#039;&#039;harmonic shift&#039;&#039; downwards is equal to -32767, a full &#039;&#039;harmonic shift&#039;&#039; upwards is 32767 and no &#039;&#039;harmonic shift&#039;&#039; is 0. The &#039;&#039;pitch bend MIDI message&#039;&#039; however is only 14-bits, meaning its range is -8192 to 8192, so in order to be able to use the entire range we have to multiply &#039;&#039;pitch&#039;&#039; by 4.&lt;br /&gt;
&lt;br /&gt;
This whole thing about number of bits can seem confusing but in the end it&#039;s all about how fine control you have over things; the more possible values, the more detailed control. In fact, most &#039;&#039;MIDI&#039;&#039; values are only 7-bit (!) meaning a range of 0 - 127. While this may sound like a lot of detail for something like a volume control, it is not even close to enough resolution to for instance set the &#039;&#039;bowing speed&#039;&#039;. Imagine that our lowest possible note frequency is 50 Hz, that means that with a 0-127 range we can only go from 50 Hz to 127 + 50 = 177 Hz - and with no decimals! This meager range and the very coarse steps of only 1 Hz would mean the instrument would never be able to sound in tune and wouldn&#039;t even have two octaves of range. The idea of limiting the Ekdahl FAR to what is possible through &#039;&#039;MIDI&#039;&#039; seemed like a poor choice thus it was decided that &amp;lt;u&amp;gt;most&amp;lt;/u&amp;gt; parameters will instead be 16-bit.&lt;br /&gt;
&lt;br /&gt;
Now lets look at a more complex example, the &amp;lt;u&amp;gt;default&amp;lt;/u&amp;gt; &#039;&#039;Note On MIDI message&#039;&#039;. On a stock Ekdahl FAR, executing&amp;lt;pre&amp;gt;&lt;br /&gt;
rqi:mev:noteon&lt;br /&gt;
&amp;lt;/pre&amp;gt;Will return something like&amp;lt;pre&amp;gt;[irq]mev:noteon:&#039;m:0,b:0,bchb:note,bmr:1,bpid:1,bpe:1,se:(velocity*512)*(1-notecount),bcsm:0&#039;&amp;lt;/pre&amp;gt;As can be seen, there&#039;s a lot of stuff going on here! First of all, notice that everything after &#039;&#039;mev:noteon:&#039;&#039; is situated in between single quotes (&#039;) - this is &amp;lt;u&amp;gt;absolutely crucial&amp;lt;/u&amp;gt; for the Ekdahl FAR to know that everything within those last two quotes is part of the last &#039;&#039;parameter&#039;&#039; of the &#039;&#039;mev&#039;&#039;-command.&lt;br /&gt;
&lt;br /&gt;
Now let&#039;s break down what happens when this &#039;&#039;MIDI message&#039;&#039; is received, i.e. when a &#039;&#039;MIDI&#039;&#039; key is pressed down:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;m:0&#039;&#039; - Sets &#039;&#039;module&#039;&#039; to 0&lt;br /&gt;
# &#039;&#039;b:0&#039;&#039; - Sets &#039;&#039;bow&#039;&#039; to 0&lt;br /&gt;
# &#039;&#039;bchb:note&#039;&#039; - Invokes the &#039;&#039;bowcontrolharmonicbase-&#039;&#039;command with the first &#039;&#039;parameter&#039;&#039; set to the &#039;&#039;variable note&#039;&#039;. &lt;br /&gt;
# &#039;&#039;bmr:1&#039;&#039; - Sets the &#039;&#039;bowmotorrun&#039;&#039;-command to &#039;1&#039;, starting the &#039;&#039;bow motor&#039;&#039;&lt;br /&gt;
# &#039;&#039;bpid:1&#039;&#039; - Sets the &#039;&#039;bowpid&#039;&#039;-command to &#039;1&#039;, making sure the &#039;&#039;PID&#039;&#039; is used&lt;br /&gt;
# &#039;&#039;bpe:1&#039;&#039; - Sets the &#039;&#039;bowpressureengage&#039;&#039; to &#039;1&#039; which moves the &#039;&#039;bowing jack&#039;&#039; to the &#039;&#039;engage position&#039;&#039;&lt;br /&gt;
# &#039;&#039;se:(velocity*512)*(1-notecount)&#039;&#039; - Executes the &#039;&#039;solenoidengage&#039;&#039;-command with the value &#039;&#039;(velocity*512)*(1-notecount)&#039;&#039;&lt;br /&gt;
# &#039;&#039;bcsm:0&#039;&#039; - Sets the &#039;&#039;bowcontrolspeedmode&#039;&#039; to &#039;1&#039; which enables automatic shut down of the &#039;&#039;bowing motor&#039;&#039;&lt;br /&gt;
The first two &#039;&#039;commands&#039;&#039; are the &#039;&#039;module&#039;&#039;- and &#039;&#039;bow-&#039;&#039;command. These &#039;&#039;commands&#039;&#039; are is intended for future versions of the Ekdahl FAR that may contain more than one string or more than one bow per string. For now &#039;&#039;0&#039;&#039; is the only valid &#039;&#039;parameter&#039;&#039; value that will be accepted for either &#039;&#039;command&#039;&#039;.&#039;&#039;&amp;lt;nowiki/&amp;gt;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;bowcontrolharmonicbase&#039;&#039;-command sets the speed of the &#039;&#039;bowing wheel&#039;&#039; to its corresponding &#039;&#039;harmonic number&#039;&#039; but also takes into account its &#039;&#039;&amp;lt;nowiki/&amp;gt;&#039;base&#039;&#039;&#039; which is the &#039;&#039;MIDI key&#039;&#039; that is mapped to &#039;&#039;harmonic number 0&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
After this the bowing motor is started and the &#039;&#039;PID&#039;&#039; is turned, now the instrument will try and make sure that the &#039;&#039;bowing wheel&#039;&#039; is at the right speed.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;bowing jack&#039;&#039; is raised to the &#039;&#039;engage position&#039;&#039;, any added &#039;&#039;pressure modifiers&#039;&#039; will also be taken into account - once the &#039;&#039;bowing jack&#039;&#039; has reached its intended position the &#039;&#039;bowing wheel&#039;&#039; should (hopefully) make contact with the string and the Ekdahl FAR will start to produce sounds.&lt;br /&gt;
&lt;br /&gt;
After this we have the &#039;&#039;solenoidengage&#039;&#039;-command &#039;&#039;command&#039;&#039; that engages the &#039;&#039;hammer&#039;&#039; and uses the first and only &#039;&#039;parameter&#039;&#039; as the force used. Like with most &#039;&#039;commands&#039;&#039; the &#039;&#039;se&#039;&#039;-command is 16-bit (0 - 65535) but the &#039;&#039;MIDI velocity variable&#039;&#039; is 7-bit (0 - 127), so to get the &#039;&#039;velocity&#039;&#039; variable to cover the entire range it needs to be multiplied with 512. &lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&amp;lt;nowiki/&amp;gt;&#039;*(1-notecount)&#039;&#039;&#039;-part is a way of making sure that we are using &#039;&#039;legato&#039;&#039; mode, i.e. that the &#039;&#039;hammer&#039;&#039; is not triggered if a key is already held down when a new key is pressed. The &#039;&#039;notecount&#039;&#039;-variable contains the number of &#039;&#039;MIDI&#039;&#039; notes currently held down. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s postulate that the Ekdahl FAR is tuned to a &#039;C&#039; at 65.4Hz and has its &#039;&#039;base&#039;&#039; set to middle &#039;C&#039; (&#039;&#039;MIDI key&#039;&#039; no 36). We are using the equal-temperament 12-tone scale and the Ekdahl FAR is set to respond to &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; &#039;&#039;MIDI channels&#039;&#039; (omni). Without having previously held any keys we press the middle &#039;C&#039; (&#039;&#039;note&#039;&#039; value 36) as hard as possible (&#039;&#039;velocity&#039;&#039; value &#039;&#039;127&#039;&#039;) on &#039;&#039;MIDI channel&#039;&#039; number 1 (&#039;&#039;channel&#039;&#039; value of 0). The Ekdahl FAR will get a &#039;&#039;note on MIDI message&#039;&#039; sent to it and from our mapping it will create the following &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;[irq]mev:noteon:&#039;m:0,b:0,bchb:36,bmr:1,bpid:1,bpe:1,se:(127*512)*(1-0),bcsm:0&#039;&amp;lt;/pre&amp;gt;What has happened here is that all &#039;&#039;variables&#039;&#039; have been replaced with the values sent by the &#039;&#039;MIDI message&#039;&#039;. Since those &#039;&#039;commands&#039;&#039; that doesn&#039;t have any &#039;&#039;variables&#039;&#039; with them will execute just as previously, only those &#039;&#039;commands&#039;&#039; whos &#039;&#039;parameters&#039;&#039; have changed will be explained:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;bchb: 36&#039;&#039; - The &#039;&#039;bowcontrolharmonicbase&#039;&#039; gets a value of &#039;&#039;36&#039;&#039; (middle &#039;C&#039;), because &#039;&#039;harmonic number 0&#039;&#039; is mapped to this key it will set the &#039;&#039;bowing wheel&#039;&#039; frequency to the &#039;&#039;fundamental&#039;&#039;; &#039;&#039;65.4&#039;&#039; Hertz&lt;br /&gt;
# &#039;&#039;se: (127*512)*(1-0)&#039;&#039; - the value of &#039;&#039;127&#039;&#039; comes from the &#039;&#039;velocity&#039;&#039;-variable, &#039;&#039;127 * 512 = 65024&#039;&#039; which is awfully close to a maximum hammer force of 65535. Since no previous notes were held down &#039;&#039;notecount&#039;&#039;  is equal to &#039;&#039;0&#039;&#039; and thus &#039;&#039;65024 * 1 = 65024&#039;&#039;. The hammer is engaged with near maximum force.&lt;br /&gt;
So the result is that we have set the speed of the &#039;&#039;bowing motor&#039;&#039; and we have engaged the &#039;&#039;hammer&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Now imagine that without releasing this key, we press another &#039;C&#039; one octave above but at half the velocity. The Ekdahl FAR creates the following &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
[irq]mev:noteon:&#039;m:0,b:0,bchb:48,bmr:1,bpid:1,bpe:1,se:(63*512)*(1-1),bcsm:0&#039;&lt;br /&gt;
&amp;lt;/pre&amp;gt;Now we can see that the &#039;&#039;note&#039;&#039; variable is &#039;&#039;48&#039;&#039; because the &#039;C&#039; one octave up is exactly 12 keys above the first, the &#039;&#039;velocity&#039;&#039; variable has changed to &#039;&#039;63&#039;&#039; since we hit it with a lighter touch - and because we are &amp;lt;u&amp;gt;still holding the first key down&amp;lt;/u&amp;gt; &#039;&#039;notecount&#039;&#039; is equal to &#039;&#039;1&#039;&#039;. Here&#039;s what happens&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;bchb: 48&#039;&#039; - Due to the &#039;&#039;base&#039;&#039; being set to &#039;&#039;36&#039;&#039; the &#039;&#039;harmonic number&#039;&#039; is set to &#039;&#039;48 - 36 = 12&#039;&#039;. Because we are using a 12-tone scale &#039;&#039;harmonic number 12&#039;&#039; is exactly one octave above the &#039;&#039;fundamental&#039;&#039; thus the speed of the &#039;&#039;bowing wheel&#039;&#039; is set to &#039;&#039;65.4 * 2 = 130.8&#039;&#039; Hertz.&lt;br /&gt;
# &#039;&#039;se: (63*512)*(1-1)&#039;&#039; - So &#039;&#039;63 * 512 = 32256&#039;&#039; and &#039;&#039;1 - 1 = 0&#039;&#039; thus &#039;&#039;32256 * 0 = 0&#039;&#039;. When the &#039;&#039;solenoidengage&#039;&#039;-command gets a &#039;&#039;parameter&#039;&#039; of &#039;&#039;0&#039;&#039; it will not engage the &#039;&#039;hammer&#039;&#039; - so the &#039;&#039;hammer&#039;&#039; doesn&#039;t strike&lt;br /&gt;
So it can be seen that with quite rudimentary math we can accomplish a whole lot of things here. Note also that even though the &#039;&#039;note on MIDI message&#039;&#039; also sets the &#039;&#039;channel&#039;&#039;-variable we never use it in this example - plenty of opportunity to make something weird happen depending on the &#039;&#039;MIDI channel&#039;&#039;!&lt;br /&gt;
&lt;br /&gt;
== CV Mapping ==&lt;br /&gt;
&#039;&#039;CV Mapping&#039;&#039; works exactly like the &#039;&#039;MIDI mapping&#039;&#039; with the difference that the command for setting the &#039;&#039;CV mapping&#039;&#039; is different and that &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; events pertaining to this &amp;lt;u&amp;gt;only&amp;lt;/u&amp;gt; change the &#039;&#039;value&#039;&#039;-variable. The &#039;&#039;command&#039;&#039; for changing the &#039;&#039;CV mapping&#039;&#039; is &#039;&#039;adccommandmap&#039;&#039; or &#039;&#039;acm&#039;&#039;, it take two &#039;&#039;parameters&#039;&#039;; &#039;&#039;channel&#039;&#039; and &#039;&#039;command string&#039;&#039;. We retrieve the &#039;&#039;command string&#039;&#039; for channel &#039;&#039;0&#039;&#039; which reads the sum of the &#039;&#039;harm. v/oct&#039;&#039;-jack and the &#039;&#039;harmonic&#039;&#039;-knob by sending a command of&amp;lt;pre&amp;gt;&lt;br /&gt;
rqi:acm:0&lt;br /&gt;
&amp;lt;/pre&amp;gt;The &amp;lt;u&amp;gt;default&amp;lt;/u&amp;gt; response will be something like&lt;br /&gt;
&amp;lt;pre&amp;gt;[irq]acm:0:&#039;bcha:value/1327.716667-20&#039;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{docnav&lt;br /&gt;
|[[The Ekdahl FAR - Service|Service]]&lt;br /&gt;
|[[The Ekdahl FAR - Command reference|Command reference]]&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Knaadmin</name></author>
	</entry>
	<entry>
		<id>http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_language&amp;diff=1652</id>
		<title>The Ekdahl FAR - Command language</title>
		<link rel="alternate" type="text/html" href="http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_language&amp;diff=1652"/>
		<updated>2026-06-08T15:06:37Z</updated>

		<summary type="html">&lt;p&gt;Knaadmin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Command language ==&lt;br /&gt;
The Ekdahl FAR is entirely controlled by &#039;&#039;commands&#039;&#039;, these &#039;&#039;commands&#039;&#039; decide everything that the instrument is doing, whether it is playing a melody or changing an internal parameter. &lt;br /&gt;
&lt;br /&gt;
When a &#039;&#039;MIDI message&#039;&#039; is received or a new CV / knob value is read, the &#039;&#039;commands&#039;&#039; associated with it will be internally sent. This can be things like &amp;quot;engage hammer&amp;quot; or &amp;quot;set the fundamental frequency&amp;quot; etc. &lt;br /&gt;
&lt;br /&gt;
Some of the available &#039;&#039;commands&#039;&#039; are mainly used for calibrating and setting up the instrument and are usually saved into the instruments memory, these will be executed whenever the instrument is turned on. &lt;br /&gt;
&lt;br /&gt;
All &#039;&#039;commands&#039;&#039; can be manually invoked via &#039;&#039;USB-Serial&#039;&#039;, in conjunction with certain software this presents an unprecedented level of control and sequenceability.&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
The &#039;&#039;commands&#039;&#039; are invoked using a &#039;&#039;plain text approach&#039;&#039;, all commands have both a &#039;&#039;long name&#039;&#039; and a &#039;&#039;short name&#039;&#039; which are interchangeable. A &#039;&#039;command&#039;&#039; may have one or more &#039;&#039;parameters&#039;&#039; associated with it, these &#039;&#039;parameters&#039;&#039; can be of different types; 16-bit numbers (values 0 - 65535 or -32767 - 32767), floating point numbers (values with decimals), booleans (0 for &#039;false&#039;, 1 for &#039;true&#039;) and strings (text). Some commands are &#039;&#039;conditional&#039;&#039;, meaning they will only execute if a parameter equates to &#039;1&#039; (&#039;true&#039;). &lt;br /&gt;
&lt;br /&gt;
The way &#039;&#039;commands&#039;&#039; are written in order to be executed is &#039;&#039;commandname:parameter1:parameter2:parameter3 [etc]&#039;&#039;, several commands be executed in sequence by separating them with a comma (&#039;,&#039;), a bunch of commands strung together is called a &#039;&#039;command string&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Since version 1.1 of the Ekdahl FAR Firmware, all commands are grouped in a hierarchical fashion according to their &#039;&#039;modules&#039;&#039; and each ladder in the hierarchy is separated by a period (&amp;quot;.&amp;quot;), this works very much like folders or directories in a regular computer. Every &#039;&#039;module&#039;&#039; can contain both &#039;&#039;commands&#039;&#039; and other &#039;&#039;modules&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
For instance, everything associated with the &#039;&#039;bowing wheel&#039;&#039; is now collected under &amp;quot;bowingwheel&amp;quot; &#039;&#039;module&#039;&#039;. That in turn contains a &amp;quot;dcmotor&amp;quot; &#039;&#039;module&#039;&#039; which does direct control of the bowing motor, and it has a &amp;quot;pid&amp;quot; &#039;&#039;module&#039;&#039; that handles bow frequency.&lt;br /&gt;
&lt;br /&gt;
If for instance we would like to start the &#039;&#039;bowing wheel&#039;&#039; and set its frequency to 82.5 Hertz we could send the Ekdahl FAR the following &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
bowmotorrun:1, bowcontrolfrequecy:82.5&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bowingwheel.dcmotor.run:1, bowingwheel.pid.targetfrequency:82.5&amp;lt;/pre&amp;gt;We could also use the &#039;&#039;short names&#039;&#039; for the commands&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
bmr:1,bcf:82.5&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bw.dcm.ru:1, bw.pid.tf:82.5&amp;lt;/pre&amp;gt;Both &#039;&#039;bowmotorrun&#039;&#039; / &#039;&#039;bowingwheel.dcmotor.run&#039;&#039; and &#039;&#039;bowcontrolfrequency / bowingwheel.pid.targetfrequency&#039;&#039; takes one &#039;&#039;parameter&#039;&#039; each, &#039;&#039;bowmotorrun / bowingwheel.dcmotor.run&#039;&#039; is &#039;&#039;conditional&#039;&#039; and unless the first &#039;&#039;parameter&#039;&#039; is equal to &#039;1&#039; the motor will not start. The first &#039;&#039;parameter&#039;&#039; of &#039;&#039;bowcontrolfrequency / bowingwheel.pid.targetfrequency&#039;&#039; sets the frequency of the &#039;&#039;bowing wheel&#039;&#039;, the instrument may not execute a &#039;&#039;command&#039;&#039; if it decides that the given &#039;&#039;parameters&#039;&#039; are outside of the working range or they are missing.&lt;br /&gt;
&lt;br /&gt;
The addition of the hierarchy in the FAR 1.1 firmware isn&#039;t just to be able to group commands, but it&#039;s also to make the FAR not limited to a single set of &#039;&#039;modules&#039;&#039; (and is the first stepping stone to a &#039;&#039;modular&#039;&#039; Ekdahl FAR). In fact, you could have 12 different bowing wheel &#039;&#039;modules&#039;&#039; for 12 different strings, these would then be addressed as &#039;&#039;bowingwheel[0].command, bowingwheel[1].command&#039;&#039; etc. Anyone familiar with C programming notices that this is the standard way of &#039;&#039;indexing&#039;&#039; an array; using brackets (&amp;quot;[ ]&amp;quot;). When addressing a module without &#039;&#039;indexing&#039;&#039; as above, the FAR will do one or two things; either use the first object (&amp;quot;[0]&amp;quot;) or, if the object is &#039;&#039;selectable&#039;&#039; it will use the previously selected object. To make things smoother a command can be executed on several objects at once by using ranges (&amp;quot;[0-4]&amp;quot;) and comma separation (&amp;quot;[0, 3, 5-6]&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
To test out a &#039;&#039;command&#039;&#039; you can send it directly to the Ekdahl FAR using the &#039;&#039;Console&#039;&#039; in the &#039;&#039;Configuration utility&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
To read up on existing &#039;&#039;commands&#039;&#039;, their &#039;&#039;parameters&#039;&#039; and a brief description you can check the &#039;&#039;Command reference&#039;&#039; in the &#039;&#039;Configuration utility&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Variables, functions and equations ==&lt;br /&gt;
What makes the &#039;&#039;Command language&#039;&#039; truly powerful is the concept of &#039;&#039;variables, functions&#039;&#039; and &#039;&#039;equations&#039;&#039;. All &#039;&#039;parameters&#039;&#039; that take numerical values can use any combination of &#039;&#039;variables, functions&#039;&#039; or &#039;&#039;equations.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
For instance, we can use the previous example and instead write our &#039;&#039;command string&#039;&#039; as follows&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
bowmotorrun:1, bowcontrolfrequency:82.5+note*20&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bowingwheel.dcmotor.run:1, bowingwheel.pid.targetfrequency:82.5+note*20&amp;lt;/pre&amp;gt;This example requires of course that the &#039;&#039;variable&#039;&#039; &#039;&#039;note&#039;&#039; exists in the current context. &lt;br /&gt;
&lt;br /&gt;
===== Variables =====&lt;br /&gt;
There are two types of &#039;&#039;variables&#039;&#039; in the Ekdahl FAR; &#039;&#039;global variables&#039;&#039; and &#039;&#039;event variables&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Global variables&#039;&#039; are variables that are always available and will exist in any context. The &#039;&#039;global variables&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;notecount&#039;&#039;&#039; - Contains the number of &#039;&#039;MIDI&#039;&#039; keys that are being held down, i.e. all &#039;&#039;Note on messages&#039;&#039; received that haven&#039;t gotten a paired &#039;&#039;Note off message&#039;&#039; yet&lt;br /&gt;
* &#039;&#039;&#039;uv0&#039;&#039;&#039; - &#039;&#039;&#039;uv9&#039;&#039;&#039; - These are &#039;&#039;user variables&#039;&#039; and can be set at any point using the &#039;&#039;globaluservariable command&#039;&#039; with the first &#039;&#039;parameter&#039;&#039; being which variable to set (0-9) and the second &#039;&#039;parameter&#039;&#039; being the value (float).&lt;br /&gt;
* &#039;&#039;&#039;e&#039;&#039;&#039; - Contains the constant &#039;&#039;[[wikipedia:E_(mathematical_constant)|e]]&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pi&#039;&#039;&#039; - Contains the constant &#039;&#039;[[wikipedia:Pi|pi]]&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Event variables&#039;&#039; are variables that are set by certain &#039;&#039;MIDI messages&#039;&#039; or when a new value is read on one of the jacks or knobs on the &#039;&#039;Control box&#039;&#039;. The &#039;&#039;Event variables&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;channel&#039;&#039;&#039; - Set by the &#039;&#039;Note on, Note off, Continuous Controller, Poly after touch, Pitch bend, Channel after touch&#039;&#039; and &#039;&#039;Program change MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;note&#039;&#039;&#039; - Set by the &#039;&#039;Note on, Note off&#039;&#039; and &#039;&#039;Poly after touch MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;velocity&#039;&#039;&#039; - Set by the &#039;&#039;Note on&#039;&#039; and &#039;&#039;Note off MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pressure&#039;&#039;&#039; - Set by the &#039;&#039;Poly after touch&#039;&#039; and &#039;&#039;Channel after touch MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; - Set by the &#039;&#039;Continuous Controller MIDI message&#039;&#039; and by the &#039;&#039;Control box&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pitch&#039;&#039;&#039; - Set by the &#039;&#039;Pitch bend MIDI message&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;program&#039;&#039;&#039; - Set by the &#039;&#039;Program change MIDI message&#039;&#039;&lt;br /&gt;
These variables will contain whatever data is relevant to the &amp;lt;u&amp;gt;last midi message sent&amp;lt;/u&amp;gt; and will not stay relevant beyond the reception of the last message.&lt;br /&gt;
&lt;br /&gt;
===== Functions =====&lt;br /&gt;
&#039;&#039;Functions&#039;&#039; can be used to change a numerical value or the result of an &#039;&#039;equation&#039;&#039;, the Ekdahl FAR contains both general &#039;&#039;arithmetic functions&#039;&#039; (courtesy of Lewis Van Winkle and the TINYEXPR engine) and &#039;&#039;specialized functions&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;arithmetic functions&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;abs&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Absolute_value|absolute value]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;acos&#039;&#039;&#039;(x), &#039;&#039;&#039;asin&#039;&#039;&#039;(x), &#039;&#039;&#039;atan&#039;&#039;&#039;(x), atan2(x, y) - Returns the [[wikipedia:Inverse_trigonometric_functions|&#039;&#039;arc-cos, -sin, -tan&#039;&#039; and &#039;&#039;-tan2&#039;&#039;]] of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;atan2&#039;&#039;&#039;(x,y) - Returns the &#039;&#039;[[wikipedia:Atan2|arctan2]]&#039;&#039; of &#039;&#039;x, y&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;floor&#039;&#039;&#039;(x), ceil(x) - Returns the [[wikipedia:Floor_and_ceiling_functions|&#039;&#039;floor&#039;&#039; and &#039;&#039;ceiling&#039;&#039;]] of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;exp&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Exponential_function|exponent]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;fac&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Factorial|factorial]]&#039;&#039; of x&lt;br /&gt;
* &#039;&#039;&#039;ln&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Natural_logarithm|natural logarithm]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;log10&#039;&#039;&#039;(x), &#039;&#039;&#039;log20&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Logarithm|logarithm]]&#039;&#039; of &#039;&#039;x&#039;&#039; using base 10 and 20 respectively&lt;br /&gt;
* &#039;&#039;&#039;ncr&#039;&#039;&#039;(x,y), &#039;&#039;&#039;npr&#039;&#039;&#039;(x,y) - Functions to calculate &#039;&#039;[[wikipedia:Combination|combinations]]&#039;&#039; and &#039;&#039;[[wikipedia:Permutation|permutations]]&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pow&#039;&#039;&#039;(x,y) - Returns &#039;&#039;x^y&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;sqrt&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Square_root|square root]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;cos&#039;&#039;&#039;(x), &#039;&#039;&#039;sin&#039;&#039;&#039;(x), &#039;&#039;&#039;tan&#039;&#039;&#039;(x) - Returns the [[wikipedia:Trigonometric_functions|&#039;&#039;cos, sin&#039;&#039; and &#039;&#039;tan&#039;&#039;]] of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;cosh&#039;&#039;&#039;(x), &#039;&#039;&#039;sinh&#039;&#039;&#039;(x), &#039;&#039;&#039;tanh&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Hyperbolic_functions|hyperbolic cos, sin and tan]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
The &#039;&#039;specialized functions&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;bool&#039;&#039;&#039;(x) - Returns 1 if &#039;&#039;x&#039;&#039; is more than 0&lt;br /&gt;
* &#039;&#039;&#039;ibool&#039;&#039;&#039;(x) - Returns 0 if &#039;&#039;x&#039;&#039; is more than 0&lt;br /&gt;
* &#039;&#039;&#039;deadband&#039;&#039;&#039;(x,y) - Returns &#039;&#039;x + y &#039;&#039; if &#039;&#039;x &amp;lt; y&#039;&#039; or &#039;&#039;x - y&#039;&#039; if &#039;&#039;x &amp;gt; y&#039;&#039;. If neither of these statements is true it returns &#039;&#039;0&#039;&#039; - used to create a [[wikipedia:Deadband|deadband]] of &#039;&#039;x&#039;&#039; with the threshold of &#039;&#039;y&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Functions&#039;&#039; can be readily used in a &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
bowmotorrun:1, bowcontrolfrequency:&amp;quot;8.17579875 * pow(2, (1/12 * note))&amp;quot;&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bowingwheel.dcmotor.run:1, bowingwheel.pid.targetfrequency:&amp;quot;8.17579875 * pow(2, (1/12 * note))&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;The previous statements starts the &#039;&#039;bowing wheel&#039;&#039; and sets the frequency of the wheel to &#039;&#039;8.17579875 * 2^(1/12 * note)&#039;&#039;. A middle &#039;C&#039; according to &#039;&#039;MIDI&#039;&#039; has a &#039;&#039;note value&#039;&#039; of 36, meaning if we substitute &#039;&#039;note&#039;&#039; with 36 we get the equation &#039;&#039;8.17579875 * 2^(1/12 * 36)&#039;&#039; which comes out to &#039;&#039;~65.4&#039;&#039; Hertz.&lt;br /&gt;
&lt;br /&gt;
Note that the first &#039;&#039;parameter&#039;&#039; for &#039;&#039;bowcontrolfrequency / bowingwheel.pid.targetfrequency&#039;&#039; is put in between double quotes (&amp;quot;). This is because the &#039;&#039;pow&#039;&#039;-function requires the use of a comma (&amp;quot;,&amp;quot;) in order to separate in between its two required inputs; &#039;&#039;x&#039;&#039; and &#039;&#039;y&#039;&#039;. In order for the Ekdahl FAR to know that this comma does not signal the beginning of a new &#039;&#039;command,&#039;&#039; we use quotes. Single (&#039;) and double (&amp;quot;) quotes can be used and nested in all &#039;&#039;parameters&#039;&#039; and are &amp;lt;u&amp;gt;required&amp;lt;/u&amp;gt; in a lot of circumstances, improper nesting or not using quotes can lead to the instrument not understanding the &#039;&#039;command string&#039;&#039; correctly.&lt;br /&gt;
&lt;br /&gt;
== Return messages ==&lt;br /&gt;
The Ekdahl FAR when connected via &#039;&#039;USB-Serial&#039;&#039; doesn&#039;t only accept &#039;&#039;commands&#039;&#039; but will also send various &#039;&#039;return messages&#039;&#039;. These are prefixed by their &#039;&#039;category&#039;&#039; denoted in brackets (&amp;quot;[]&amp;quot;), the existing categories as of this writing (2025-01-22) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;command&#039;&#039;&#039; / &#039;&#039;&#039;cmd&#039;&#039;&#039; - Acknowledges the reception of a command in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;usb&#039;&#039;&#039; - Acknowledges the reception of a &#039;&#039;MIDI message&#039;&#039; over &#039;&#039;USB&#039;&#039; in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;hardware&#039;&#039;&#039; / &#039;&#039;&#039;hw&#039;&#039;&#039; - Signals that a change has been sent to the Ekdahl FAR hardware, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;undefined&#039;&#039;&#039; / &#039;&#039;&#039;un&#039;&#039;&#039; - The message sent is in the &#039;&#039;undefined&#039;&#039; category, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;priority&#039;&#039;&#039; / &#039;&#039;&#039;pri&#039;&#039;&#039; - The message sent is in the &#039;&#039;priority&#039;&#039; category, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;error&#039;&#039;&#039; / &#039;&#039;&#039;err&#039;&#039;&#039; - Signals that an &#039;&#039;error&#039;&#039; has occurred, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;expressionparser&#039;&#039;&#039; / &#039;&#039;&#039;ep&#039;&#039;&#039; - These messages contains debugging information regarding the internal &#039;&#039;expression parser&#039;&#039; and is used for development&lt;br /&gt;
*&#039;&#039;&#039;debug&#039;&#039;&#039; / &#039;&#039;&#039;dbg&#039;&#039;&#039; - These messages contains various debugging information and is used for development&lt;br /&gt;
*&#039;&#039;&#039;help&#039;&#039;&#039; / &#039;&#039;&#039;hlp&#039;&#039;&#039; - Signals that the message is a response to a &#039;&#039;help&#039;&#039;-command being sent to the Ekdahl FAR. These messages are structured so that a receiver, like the &#039;&#039;Configuration utility&#039;&#039;, can parse information about available &#039;&#039;commands&#039;&#039; in the current &#039;&#039;firmware&#039;&#039; and relay it to a user in a structured way.&lt;br /&gt;
* &#039;&#039;&#039;inforequest&#039;&#039;&#039; / &#039;&#039;&#039;irq&#039;&#039;&#039; - Signals that an &#039;&#039;info request&#039;&#039; has been returned. This is a specialized message that is either sent as a response to an &#039;&#039;rqi&#039;&#039;-command or as a &#039;&#039;interrupt&#039;&#039;-message telling the user or receiving software about different parameters in the Ekdahl FAR. These messages follows the same structure as regular &#039;&#039;command message&#039;&#039;s of &#039;&#039;[irq]commandname:parameter1 [etc]&#039;&#039; so that it can be used by a receiving software to keep track of parameter changes&lt;br /&gt;
&lt;br /&gt;
===== Explicitly requesting information =====&lt;br /&gt;
By using the special command &#039;&#039;requestinfo / rqi&#039;&#039; one can request the information stored by a certain &#039;&#039;command&#039;&#039; or a state of the Ekdahl FAR. The &#039;&#039;rqi&#039;&#039;-command is executed in the convention &#039;&#039;rqi:commandname[:optional parameters]&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
To go back to our example of setting the bowing frequency using the &#039;&#039;bowcontrolfrequency&#039;&#039;-command we can ask the Ekdahl FAR what the bowing frequency is set to by writing&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
rqi:bowcontrolfrequency&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
rqi:bowingwheel.pid.targetfrequency&lt;br /&gt;
&amp;lt;/pre&amp;gt;The return value would be something like&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
[irq]bcf:82.5&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
[irq]bw[0].pid[0].tf:82.5&lt;br /&gt;
&amp;lt;/pre&amp;gt;Where &#039;[irq]&#039; denotes that the message returned is in the &#039;&#039;info request-&#039;&#039;category, that it pertains to the command &#039;&#039;bcf&#039;&#039; / &#039;&#039;bw.pid.tf&#039;&#039; and has the value &#039;&#039;82.5&#039;&#039;. Note that the returned &#039;&#039;command&#039;&#039; sent by an &#039;&#039;rqi&#039;&#039;-command always uses the &#039;&#039;short name&#039;&#039; in order to preserve bandwidth. In the FAR 1.1 the return statement always returns the &#039;&#039;index&#039;&#039; of the &#039;&#039;module&#039;&#039;(s) in question.&lt;br /&gt;
&lt;br /&gt;
Most commands do not require any &#039;&#039;parameters&#039;&#039; when using the &#039;&#039;rqi&#039;&#039;-command. The &#039;&#039;adcread&#039;&#039; / &#039;&#039;datareturn&#039;&#039;-command is an example of a &#039;&#039;command&#039;&#039; that &amp;lt;u&amp;gt;does&amp;lt;/u&amp;gt; require a &#039;&#039;parameter&#039;&#039; when used with &#039;&#039;rqi&#039;&#039;. The &#039;&#039;adcread / datareturn-&#039;&#039;command returns the last value read by the &#039;&#039;analog-to-digital converter&#039;&#039; in the &#039;&#039;Control box&#039;&#039;, because there are 8 different channels the first &#039;&#039;parameter&#039;&#039; sets which channel to return the data for, hence executing the &#039;&#039;command&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
rqi:adcr:3&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
rqi:controlbox.datareturn:3&lt;br /&gt;
&amp;lt;/pre&amp;gt;will return the last data read on &#039;&#039;analog-to-digital convert&#039;&#039; channel 3.&lt;br /&gt;
&lt;br /&gt;
== MIDI mapping ==&lt;br /&gt;
To change how a certain &#039;&#039;MIDI message&#039;&#039; interacts with the Ekdahl FAR we need to change the &#039;&#039;commands&#039;&#039; or &#039;&#039;parameters&#039;&#039; sent when the message is received. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;FAR &amp;lt; 1.1:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;FAR &amp;lt; 1.1&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 The &#039;&#039;command&#039;&#039; responsible for mapping &#039;&#039;command strings&#039;&#039; to different &#039;&#039;MIDI messages&#039;&#039; is &#039;midieventhandler&#039; or &#039;mev&#039; for short. The first &#039;&#039;parameter&#039;&#039; of &#039;mev&#039; is the type of &#039;&#039;MIDI message&#039;&#039; that we want to remap&lt;br /&gt;
 &lt;br /&gt;
 * &#039;&#039;&#039;noteon&#039;&#039;&#039; - Note on&lt;br /&gt;
 * &#039;&#039;&#039;noteoff&#039;&#039;&#039; - Note off&lt;br /&gt;
 * &#039;&#039;&#039;pat&#039;&#039;&#039; - Poly after touch&lt;br /&gt;
 * &#039;&#039;&#039;cat&#039;&#039;&#039; - Channel after touch&lt;br /&gt;
 * &#039;&#039;&#039;pb&#039;&#039;&#039; - Pitch bend&lt;br /&gt;
 * &#039;&#039;&#039;pc&#039;&#039;&#039; - Program change&lt;br /&gt;
 * &#039;&#039;&#039;cc&#039;&#039;&#039; - Continuous controller&lt;br /&gt;
 &lt;br /&gt;
 The second &#039;&#039;parameter&#039;&#039; is the &#039;&#039;command string&#039;&#039; that is to be associated with the &#039;&#039;MIDI Message&#039;&#039; - with the exception of the &#039;&#039;&#039;cc&#039;&#039;&#039;-type, here the second &#039;&#039;parameter&#039;&#039; is the &#039;&#039;controller number&#039;&#039; (0 - 127) and the third &#039;&#039;parameter&#039;&#039; is the &#039;&#039;command string&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;FAR 1.1&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 The &#039;&#039;commands&#039;&#039; responsible for mapping &#039;&#039;command strings&#039;&#039; to different &#039;&#039;MIDI messages&#039;&#039; are as follows&lt;br /&gt;
 &lt;br /&gt;
 * &#039;&#039;&#039;noteon/non&#039;&#039;&#039;:&#039;&#039;commands&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed for a &#039;note on&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;noteoff/nof&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;note off&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;polyaftertouch/pat&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;poly aftertouch&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;channelaftertouch/cat&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;channel aftertouch&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;pitchbend/pb&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;pitch bend&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;programchange/pc&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;program change&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
 * &#039;&#039;&#039;continuouscontrollerdata/ccd&#039;&#039;&#039;&#039;&#039;:controller:commands&#039;&#039; - Sets the &#039;&#039;commands&#039;&#039; executed for &#039;continuous controller&#039; no &#039;&#039;controller&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We can of course use the &#039;&#039;rqi&#039;&#039;-command to check the current mapping, below we are asking what the current &#039;&#039;command string&#039;&#039; associated with the &#039;&#039;pitch bend&#039;&#039; &#039;&#039;MIDI message&#039;&#039; is&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
rqi:mev:pb&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
rqi:mcf.mc.pb&lt;br /&gt;
&amp;lt;/pre&amp;gt;This may return something like&amp;lt;pre&amp;gt;&lt;br /&gt;
[irq]bchsh:pitch*4&lt;br /&gt;
&amp;lt;/pre&amp;gt;The return message tells us that the &#039;&#039;pitch bend MIDI message&#039;&#039; is executing a &#039;&#039;bchsh&#039;&#039;-command with the parameter &#039;&#039;pitch*4&#039;&#039;. Looking in the &#039;&#039;command reference&#039;&#039; we can see that &#039;&#039;bchsh&#039;&#039; is the &#039;&#039;short name&#039;&#039; of the &#039;&#039;bowcontrolharmonicshift&#039;&#039;-command which shifts the frequency of the &#039;&#039;bowing wheel&#039;&#039; from the current frequency, the first (and only) parameter sets how much we want to shift it (depends on the &#039;&#039;bowcontrolharmonicshiftrange command&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
If we look in the list of &#039;&#039;[[The Ekdahl FAR - Command langue#Variables|variables]]&#039;&#039; above we can see that the &#039;&#039;pitch bend MIDI message&#039;&#039; will set the &#039;&#039;pitch variable&#039;&#039; which is indeed used. Now what is the &#039;&#039;&#039;*4&#039;&#039;&amp;lt;nowiki/&amp;gt;&#039; all about? Well the &#039;&#039;bchsh&#039;&#039;-command expects a &#039;&#039;16-bit signed&#039;&#039; value, meaning that a full &#039;&#039;harmonic shift&#039;&#039; downwards is equal to -32767, a full &#039;&#039;harmonic shift&#039;&#039; upwards is 32767 and no &#039;&#039;harmonic shift&#039;&#039; is 0. The &#039;&#039;pitch bend MIDI message&#039;&#039; however is only 14-bits, meaning its range is -8192 to 8192, so in order to be able to use the entire range we have to multiply &#039;&#039;pitch&#039;&#039; by 4.&lt;br /&gt;
&lt;br /&gt;
This whole thing about number of bits can seem confusing but in the end it&#039;s all about how fine control you have over things; the more possible values, the more detailed control. In fact, most &#039;&#039;MIDI&#039;&#039; values are only 7-bit (!) meaning a range of 0 - 127. While this may sound like a lot of detail for something like a volume control, it is not even close to enough resolution to for instance set the &#039;&#039;bowing speed&#039;&#039;. Imagine that our lowest possible note frequency is 50 Hz, that means that with a 0-127 range we can only go from 50 Hz to 127 + 50 = 177 Hz - and with no decimals! This meager range and the very coarse steps of only 1 Hz would mean the instrument would never be able to sound in tune and wouldn&#039;t even have two octaves of range. The idea of limiting the Ekdahl FAR to what is possible through &#039;&#039;MIDI&#039;&#039; seemed like a poor choice thus it was decided that &amp;lt;u&amp;gt;most&amp;lt;/u&amp;gt; parameters will instead be 16-bit.&lt;br /&gt;
&lt;br /&gt;
Now lets look at a more complex example, the &amp;lt;u&amp;gt;default&amp;lt;/u&amp;gt; &#039;&#039;Note On MIDI message&#039;&#039;. On a stock Ekdahl FAR, executing&amp;lt;pre&amp;gt;&lt;br /&gt;
rqi:mev:noteon&lt;br /&gt;
&amp;lt;/pre&amp;gt;Will return something like&amp;lt;pre&amp;gt;[irq]mev:noteon:&#039;m:0,b:0,bchb:note,bmr:1,bpid:1,bpe:1,se:(velocity*512)*(1-notecount),bcsm:0&#039;&amp;lt;/pre&amp;gt;As can be seen, there&#039;s a lot of stuff going on here! First of all, notice that everything after &#039;&#039;mev:noteon:&#039;&#039; is situated in between single quotes (&#039;) - this is &amp;lt;u&amp;gt;absolutely crucial&amp;lt;/u&amp;gt; for the Ekdahl FAR to know that everything within those last two quotes is part of the last &#039;&#039;parameter&#039;&#039; of the &#039;&#039;mev&#039;&#039;-command.&lt;br /&gt;
&lt;br /&gt;
Now let&#039;s break down what happens when this &#039;&#039;MIDI message&#039;&#039; is received, i.e. when a &#039;&#039;MIDI&#039;&#039; key is pressed down:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;m:0&#039;&#039; - Sets &#039;&#039;module&#039;&#039; to 0&lt;br /&gt;
# &#039;&#039;b:0&#039;&#039; - Sets &#039;&#039;bow&#039;&#039; to 0&lt;br /&gt;
# &#039;&#039;bchb:note&#039;&#039; - Invokes the &#039;&#039;bowcontrolharmonicbase-&#039;&#039;command with the first &#039;&#039;parameter&#039;&#039; set to the &#039;&#039;variable note&#039;&#039;. &lt;br /&gt;
# &#039;&#039;bmr:1&#039;&#039; - Sets the &#039;&#039;bowmotorrun&#039;&#039;-command to &#039;1&#039;, starting the &#039;&#039;bow motor&#039;&#039;&lt;br /&gt;
# &#039;&#039;bpid:1&#039;&#039; - Sets the &#039;&#039;bowpid&#039;&#039;-command to &#039;1&#039;, making sure the &#039;&#039;PID&#039;&#039; is used&lt;br /&gt;
# &#039;&#039;bpe:1&#039;&#039; - Sets the &#039;&#039;bowpressureengage&#039;&#039; to &#039;1&#039; which moves the &#039;&#039;bowing jack&#039;&#039; to the &#039;&#039;engage position&#039;&#039;&lt;br /&gt;
# &#039;&#039;se:(velocity*512)*(1-notecount)&#039;&#039; - Executes the &#039;&#039;solenoidengage&#039;&#039;-command with the value &#039;&#039;(velocity*512)*(1-notecount)&#039;&#039;&lt;br /&gt;
# &#039;&#039;bcsm:0&#039;&#039; - Sets the &#039;&#039;bowcontrolspeedmode&#039;&#039; to &#039;1&#039; which enables automatic shut down of the &#039;&#039;bowing motor&#039;&#039;&lt;br /&gt;
The first two &#039;&#039;commands&#039;&#039; are the &#039;&#039;module&#039;&#039;- and &#039;&#039;bow-&#039;&#039;command. These &#039;&#039;commands&#039;&#039; are is intended for future versions of the Ekdahl FAR that may contain more than one string or more than one bow per string. For now &#039;&#039;0&#039;&#039; is the only valid &#039;&#039;parameter&#039;&#039; value that will be accepted for either &#039;&#039;command&#039;&#039;.&#039;&#039;&amp;lt;nowiki/&amp;gt;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;bowcontrolharmonicbase&#039;&#039;-command sets the speed of the &#039;&#039;bowing wheel&#039;&#039; to its corresponding &#039;&#039;harmonic number&#039;&#039; but also takes into account its &#039;&#039;&amp;lt;nowiki/&amp;gt;&#039;base&#039;&#039;&#039; which is the &#039;&#039;MIDI key&#039;&#039; that is mapped to &#039;&#039;harmonic number 0&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
After this the bowing motor is started and the &#039;&#039;PID&#039;&#039; is turned, now the instrument will try and make sure that the &#039;&#039;bowing wheel&#039;&#039; is at the right speed.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;bowing jack&#039;&#039; is raised to the &#039;&#039;engage position&#039;&#039;, any added &#039;&#039;pressure modifiers&#039;&#039; will also be taken into account - once the &#039;&#039;bowing jack&#039;&#039; has reached its intended position the &#039;&#039;bowing wheel&#039;&#039; should (hopefully) make contact with the string and the Ekdahl FAR will start to produce sounds.&lt;br /&gt;
&lt;br /&gt;
After this we have the &#039;&#039;solenoidengage&#039;&#039;-command &#039;&#039;command&#039;&#039; that engages the &#039;&#039;hammer&#039;&#039; and uses the first and only &#039;&#039;parameter&#039;&#039; as the force used. Like with most &#039;&#039;commands&#039;&#039; the &#039;&#039;se&#039;&#039;-command is 16-bit (0 - 65535) but the &#039;&#039;MIDI velocity variable&#039;&#039; is 7-bit (0 - 127), so to get the &#039;&#039;velocity&#039;&#039; variable to cover the entire range it needs to be multiplied with 512. &lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&amp;lt;nowiki/&amp;gt;&#039;*(1-notecount)&#039;&#039;&#039;-part is a way of making sure that we are using &#039;&#039;legato&#039;&#039; mode, i.e. that the &#039;&#039;hammer&#039;&#039; is not triggered if a key is already held down when a new key is pressed. The &#039;&#039;notecount&#039;&#039;-variable contains the number of &#039;&#039;MIDI&#039;&#039; notes currently held down. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s postulate that the Ekdahl FAR is tuned to a &#039;C&#039; at 65.4Hz and has its &#039;&#039;base&#039;&#039; set to middle &#039;C&#039; (&#039;&#039;MIDI key&#039;&#039; no 36). We are using the equal-temperament 12-tone scale and the Ekdahl FAR is set to respond to &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; &#039;&#039;MIDI channels&#039;&#039; (omni). Without having previously held any keys we press the middle &#039;C&#039; (&#039;&#039;note&#039;&#039; value 36) as hard as possible (&#039;&#039;velocity&#039;&#039; value &#039;&#039;127&#039;&#039;) on &#039;&#039;MIDI channel&#039;&#039; number 1 (&#039;&#039;channel&#039;&#039; value of 0). The Ekdahl FAR will get a &#039;&#039;note on MIDI message&#039;&#039; sent to it and from our mapping it will create the following &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;[irq]mev:noteon:&#039;m:0,b:0,bchb:36,bmr:1,bpid:1,bpe:1,se:(127*512)*(1-0),bcsm:0&#039;&amp;lt;/pre&amp;gt;What has happened here is that all &#039;&#039;variables&#039;&#039; have been replaced with the values sent by the &#039;&#039;MIDI message&#039;&#039;. Since those &#039;&#039;commands&#039;&#039; that doesn&#039;t have any &#039;&#039;variables&#039;&#039; with them will execute just as previously, only those &#039;&#039;commands&#039;&#039; whos &#039;&#039;parameters&#039;&#039; have changed will be explained:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;bchb: 36&#039;&#039; - The &#039;&#039;bowcontrolharmonicbase&#039;&#039; gets a value of &#039;&#039;36&#039;&#039; (middle &#039;C&#039;), because &#039;&#039;harmonic number 0&#039;&#039; is mapped to this key it will set the &#039;&#039;bowing wheel&#039;&#039; frequency to the &#039;&#039;fundamental&#039;&#039;; &#039;&#039;65.4&#039;&#039; Hertz&lt;br /&gt;
# &#039;&#039;se: (127*512)*(1-0)&#039;&#039; - the value of &#039;&#039;127&#039;&#039; comes from the &#039;&#039;velocity&#039;&#039;-variable, &#039;&#039;127 * 512 = 65024&#039;&#039; which is awfully close to a maximum hammer force of 65535. Since no previous notes were held down &#039;&#039;notecount&#039;&#039;  is equal to &#039;&#039;0&#039;&#039; and thus &#039;&#039;65024 * 1 = 65024&#039;&#039;. The hammer is engaged with near maximum force.&lt;br /&gt;
So the result is that we have set the speed of the &#039;&#039;bowing motor&#039;&#039; and we have engaged the &#039;&#039;hammer&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Now imagine that without releasing this key, we press another &#039;C&#039; one octave above but at half the velocity. The Ekdahl FAR creates the following &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
[irq]mev:noteon:&#039;m:0,b:0,bchb:48,bmr:1,bpid:1,bpe:1,se:(63*512)*(1-1),bcsm:0&#039;&lt;br /&gt;
&amp;lt;/pre&amp;gt;Now we can see that the &#039;&#039;note&#039;&#039; variable is &#039;&#039;48&#039;&#039; because the &#039;C&#039; one octave up is exactly 12 keys above the first, the &#039;&#039;velocity&#039;&#039; variable has changed to &#039;&#039;63&#039;&#039; since we hit it with a lighter touch - and because we are &amp;lt;u&amp;gt;still holding the first key down&amp;lt;/u&amp;gt; &#039;&#039;notecount&#039;&#039; is equal to &#039;&#039;1&#039;&#039;. Here&#039;s what happens&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;bchb: 48&#039;&#039; - Due to the &#039;&#039;base&#039;&#039; being set to &#039;&#039;36&#039;&#039; the &#039;&#039;harmonic number&#039;&#039; is set to &#039;&#039;48 - 36 = 12&#039;&#039;. Because we are using a 12-tone scale &#039;&#039;harmonic number 12&#039;&#039; is exactly one octave above the &#039;&#039;fundamental&#039;&#039; thus the speed of the &#039;&#039;bowing wheel&#039;&#039; is set to &#039;&#039;65.4 * 2 = 130.8&#039;&#039; Hertz.&lt;br /&gt;
# &#039;&#039;se: (63*512)*(1-1)&#039;&#039; - So &#039;&#039;63 * 512 = 32256&#039;&#039; and &#039;&#039;1 - 1 = 0&#039;&#039; thus &#039;&#039;32256 * 0 = 0&#039;&#039;. When the &#039;&#039;solenoidengage&#039;&#039;-command gets a &#039;&#039;parameter&#039;&#039; of &#039;&#039;0&#039;&#039; it will not engage the &#039;&#039;hammer&#039;&#039; - so the &#039;&#039;hammer&#039;&#039; doesn&#039;t strike&lt;br /&gt;
So it can be seen that with quite rudimentary math we can accomplish a whole lot of things here. Note also that even though the &#039;&#039;note on MIDI message&#039;&#039; also sets the &#039;&#039;channel&#039;&#039;-variable we never use it in this example - plenty of opportunity to make something weird happen depending on the &#039;&#039;MIDI channel&#039;&#039;!&lt;br /&gt;
&lt;br /&gt;
== CV Mapping ==&lt;br /&gt;
&#039;&#039;CV Mapping&#039;&#039; works exactly like the &#039;&#039;MIDI mapping&#039;&#039; with the difference that the command for setting the &#039;&#039;CV mapping&#039;&#039; is different and that &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; events pertaining to this &amp;lt;u&amp;gt;only&amp;lt;/u&amp;gt; change the &#039;&#039;value&#039;&#039;-variable. The &#039;&#039;command&#039;&#039; for changing the &#039;&#039;CV mapping&#039;&#039; is &#039;&#039;adccommandmap&#039;&#039; or &#039;&#039;acm&#039;&#039;, it take two &#039;&#039;parameters&#039;&#039;; &#039;&#039;channel&#039;&#039; and &#039;&#039;command string&#039;&#039;. We retrieve the &#039;&#039;command string&#039;&#039; for channel &#039;&#039;0&#039;&#039; which reads the sum of the &#039;&#039;harm. v/oct&#039;&#039;-jack and the &#039;&#039;harmonic&#039;&#039;-knob by sending a command of&amp;lt;pre&amp;gt;&lt;br /&gt;
rqi:acm:0&lt;br /&gt;
&amp;lt;/pre&amp;gt;The &amp;lt;u&amp;gt;default&amp;lt;/u&amp;gt; response will be something like&lt;br /&gt;
&amp;lt;pre&amp;gt;[irq]acm:0:&#039;bcha:value/1327.716667-20&#039;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{docnav&lt;br /&gt;
|[[The Ekdahl FAR - Service|Service]]&lt;br /&gt;
|[[The Ekdahl FAR - Command reference|Command reference]]&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Knaadmin</name></author>
	</entry>
	<entry>
		<id>http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_language&amp;diff=1651</id>
		<title>The Ekdahl FAR - Command language</title>
		<link rel="alternate" type="text/html" href="http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_language&amp;diff=1651"/>
		<updated>2026-06-08T14:58:21Z</updated>

		<summary type="html">&lt;p&gt;Knaadmin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Command language ==&lt;br /&gt;
The Ekdahl FAR is entirely controlled by &#039;&#039;commands&#039;&#039;, these &#039;&#039;commands&#039;&#039; decide everything that the instrument is doing, whether it is playing a melody or changing an internal parameter. &lt;br /&gt;
&lt;br /&gt;
When a &#039;&#039;MIDI message&#039;&#039; is received or a new CV / knob value is read, the &#039;&#039;commands&#039;&#039; associated with it will be internally sent. This can be things like &amp;quot;engage hammer&amp;quot; or &amp;quot;set the fundamental frequency&amp;quot; etc. &lt;br /&gt;
&lt;br /&gt;
Some of the available &#039;&#039;commands&#039;&#039; are mainly used for calibrating and setting up the instrument and are usually saved into the instruments memory, these will be executed whenever the instrument is turned on. &lt;br /&gt;
&lt;br /&gt;
All &#039;&#039;commands&#039;&#039; can be manually invoked via &#039;&#039;USB-Serial&#039;&#039;, in conjunction with certain software this presents an unprecedented level of control and sequenceability.&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
The &#039;&#039;commands&#039;&#039; are invoked using a &#039;&#039;plain text approach&#039;&#039;, all commands have both a &#039;&#039;long name&#039;&#039; and a &#039;&#039;short name&#039;&#039; which are interchangeable. A &#039;&#039;command&#039;&#039; may have one or more &#039;&#039;parameters&#039;&#039; associated with it, these &#039;&#039;parameters&#039;&#039; can be of different types; 16-bit numbers (values 0 - 65535 or -32767 - 32767), floating point numbers (values with decimals), booleans (0 for &#039;false&#039;, 1 for &#039;true&#039;) and strings (text). Some commands are &#039;&#039;conditional&#039;&#039;, meaning they will only execute if a parameter equates to &#039;1&#039; (&#039;true&#039;). &lt;br /&gt;
&lt;br /&gt;
The way &#039;&#039;commands&#039;&#039; are written in order to be executed is &#039;&#039;commandname:parameter1:parameter2:parameter3 [etc]&#039;&#039;, several commands be executed in sequence by separating them with a comma (&#039;,&#039;), a bunch of commands strung together is called a &#039;&#039;command string&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Since version 1.1 of the Ekdahl FAR Firmware, all commands are grouped in a hierarchical fashion according to their &#039;&#039;modules&#039;&#039; and each ladder in the hierarchy is separated by a period (&amp;quot;.&amp;quot;), this works very much like folders or directories in a regular computer. Every &#039;&#039;module&#039;&#039; can contain both &#039;&#039;commands&#039;&#039; and other &#039;&#039;modules&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
For instance, everything associated with the &#039;&#039;bowing wheel&#039;&#039; is now collected under &amp;quot;bowingwheel&amp;quot; &#039;&#039;module&#039;&#039;. That in turn contains a &amp;quot;dcmotor&amp;quot; &#039;&#039;module&#039;&#039; which does direct control of the bowing motor, and it has a &amp;quot;pid&amp;quot; &#039;&#039;module&#039;&#039; that handles bow frequency.&lt;br /&gt;
&lt;br /&gt;
If for instance we would like to start the &#039;&#039;bowing wheel&#039;&#039; and set its frequency to 82.5 Hertz we could send the Ekdahl FAR the following &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
bowmotorrun:1, bowcontrolfrequecy:82.5&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bowingwheel.dcmotor.run:1, bowingwheel.pid.targetfrequency:82.5&amp;lt;/pre&amp;gt;We could also use the &#039;&#039;short names&#039;&#039; for the commands&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
bmr:1,bcf:82.5&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bw.dcm.ru:1, bw.pid.tf:82.5&amp;lt;/pre&amp;gt;Both &#039;&#039;bowmotorrun&#039;&#039; / &#039;&#039;bowingwheel.dcmotor.run&#039;&#039; and &#039;&#039;bowcontrolfrequency / bowingwheel.pid.targetfrequency&#039;&#039; takes one &#039;&#039;parameter&#039;&#039; each, &#039;&#039;bowmotorrun / bowingwheel.dcmotor.run&#039;&#039; is &#039;&#039;conditional&#039;&#039; and unless the first &#039;&#039;parameter&#039;&#039; is equal to &#039;1&#039; the motor will not start. The first &#039;&#039;parameter&#039;&#039; of &#039;&#039;bowcontrolfrequency / bowingwheel.pid.targetfrequency&#039;&#039; sets the frequency of the &#039;&#039;bowing wheel&#039;&#039;, the instrument may not execute a &#039;&#039;command&#039;&#039; if it decides that the given &#039;&#039;parameters&#039;&#039; are outside of the working range or they are missing.&lt;br /&gt;
&lt;br /&gt;
The addition of the hierarchy in the FAR 1.1 firmware isn&#039;t just to be able to group commands, but it&#039;s also to make the FAR not limited to a single set of &#039;&#039;modules&#039;&#039; (and is the first stepping stone to a &#039;&#039;modular&#039;&#039; Ekdahl FAR). In fact, you could have 12 different bowing wheel &#039;&#039;modules&#039;&#039; for 12 different strings, these would then be addressed as &#039;&#039;bowingwheel[0].command, bowingwheel[1].command&#039;&#039; etc. Anyone familiar with C programming notices that this is the standard way of &#039;&#039;indexing&#039;&#039; an array; using brackets (&amp;quot;[ ]&amp;quot;). When addressing a module without &#039;&#039;indexing&#039;&#039; as above, the FAR will do one or two things; either use the first object (&amp;quot;[0]&amp;quot;) or, if the object is &#039;&#039;selectable&#039;&#039; it will use the previously selected object. To make things smoother a command can be executed on several objects at once by using ranges (&amp;quot;[0-4]&amp;quot;) and comma separation (&amp;quot;[0, 3, 5-6]&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
To test out a &#039;&#039;command&#039;&#039; you can send it directly to the Ekdahl FAR using the &#039;&#039;Console&#039;&#039; in the &#039;&#039;Configuration utility&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
To read up on existing &#039;&#039;commands&#039;&#039;, their &#039;&#039;parameters&#039;&#039; and a brief description you can check the &#039;&#039;Command reference&#039;&#039; in the &#039;&#039;Configuration utility&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Variables, functions and equations ==&lt;br /&gt;
What makes the &#039;&#039;Command language&#039;&#039; truly powerful is the concept of &#039;&#039;variables, functions&#039;&#039; and &#039;&#039;equations&#039;&#039;. All &#039;&#039;parameters&#039;&#039; that take numerical values can use any combination of &#039;&#039;variables, functions&#039;&#039; or &#039;&#039;equations.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
For instance, we can use the previous example and instead write our &#039;&#039;command string&#039;&#039; as follows&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
bowmotorrun:1, bowcontrolfrequency:82.5+note*20&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bowingwheel.dcmotor.run:1, bowingwheel.pid.targetfrequency:82.5+note*20&amp;lt;/pre&amp;gt;This example requires of course that the &#039;&#039;variable&#039;&#039; &#039;&#039;note&#039;&#039; exists in the current context. &lt;br /&gt;
&lt;br /&gt;
===== Variables =====&lt;br /&gt;
There are two types of &#039;&#039;variables&#039;&#039; in the Ekdahl FAR; &#039;&#039;global variables&#039;&#039; and &#039;&#039;event variables&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Global variables&#039;&#039; are variables that are always available and will exist in any context. The &#039;&#039;global variables&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;notecount&#039;&#039;&#039; - Contains the number of &#039;&#039;MIDI&#039;&#039; keys that are being held down, i.e. all &#039;&#039;Note on messages&#039;&#039; received that haven&#039;t gotten a paired &#039;&#039;Note off message&#039;&#039; yet&lt;br /&gt;
* &#039;&#039;&#039;uv0&#039;&#039;&#039; - &#039;&#039;&#039;uv9&#039;&#039;&#039; - These are &#039;&#039;user variables&#039;&#039; and can be set at any point using the &#039;&#039;globaluservariable command&#039;&#039; with the first &#039;&#039;parameter&#039;&#039; being which variable to set (0-9) and the second &#039;&#039;parameter&#039;&#039; being the value (float).&lt;br /&gt;
* &#039;&#039;&#039;e&#039;&#039;&#039; - Contains the constant &#039;&#039;[[wikipedia:E_(mathematical_constant)|e]]&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pi&#039;&#039;&#039; - Contains the constant &#039;&#039;[[wikipedia:Pi|pi]]&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Event variables&#039;&#039; are variables that are set by certain &#039;&#039;MIDI messages&#039;&#039; or when a new value is read on one of the jacks or knobs on the &#039;&#039;Control box&#039;&#039;. The &#039;&#039;Event variables&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;channel&#039;&#039;&#039; - Set by the &#039;&#039;Note on, Note off, Continuous Controller, Poly after touch, Pitch bend, Channel after touch&#039;&#039; and &#039;&#039;Program change MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;note&#039;&#039;&#039; - Set by the &#039;&#039;Note on, Note off&#039;&#039; and &#039;&#039;Poly after touch MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;velocity&#039;&#039;&#039; - Set by the &#039;&#039;Note on&#039;&#039; and &#039;&#039;Note off MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pressure&#039;&#039;&#039; - Set by the &#039;&#039;Poly after touch&#039;&#039; and &#039;&#039;Channel after touch MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; - Set by the &#039;&#039;Continuous Controller MIDI message&#039;&#039; and by the &#039;&#039;Control box&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pitch&#039;&#039;&#039; - Set by the &#039;&#039;Pitch bend MIDI message&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;program&#039;&#039;&#039; - Set by the &#039;&#039;Program change MIDI message&#039;&#039;&lt;br /&gt;
These variables will contain whatever data is relevant to the &amp;lt;u&amp;gt;last midi message sent&amp;lt;/u&amp;gt; and will not stay relevant beyond the reception of the last message.&lt;br /&gt;
&lt;br /&gt;
===== Functions =====&lt;br /&gt;
&#039;&#039;Functions&#039;&#039; can be used to change a numerical value or the result of an &#039;&#039;equation&#039;&#039;, the Ekdahl FAR contains both general &#039;&#039;arithmetic functions&#039;&#039; (courtesy of Lewis Van Winkle and the TINYEXPR engine) and &#039;&#039;specialized functions&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;arithmetic functions&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;abs&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Absolute_value|absolute value]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;acos&#039;&#039;&#039;(x), &#039;&#039;&#039;asin&#039;&#039;&#039;(x), &#039;&#039;&#039;atan&#039;&#039;&#039;(x), atan2(x, y) - Returns the [[wikipedia:Inverse_trigonometric_functions|&#039;&#039;arc-cos, -sin, -tan&#039;&#039; and &#039;&#039;-tan2&#039;&#039;]] of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;atan2&#039;&#039;&#039;(x,y) - Returns the &#039;&#039;[[wikipedia:Atan2|arctan2]]&#039;&#039; of &#039;&#039;x, y&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;floor&#039;&#039;&#039;(x), ceil(x) - Returns the [[wikipedia:Floor_and_ceiling_functions|&#039;&#039;floor&#039;&#039; and &#039;&#039;ceiling&#039;&#039;]] of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;exp&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Exponential_function|exponent]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;fac&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Factorial|factorial]]&#039;&#039; of x&lt;br /&gt;
* &#039;&#039;&#039;ln&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Natural_logarithm|natural logarithm]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;log10&#039;&#039;&#039;(x), &#039;&#039;&#039;log20&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Logarithm|logarithm]]&#039;&#039; of &#039;&#039;x&#039;&#039; using base 10 and 20 respectively&lt;br /&gt;
* &#039;&#039;&#039;ncr&#039;&#039;&#039;(x,y), &#039;&#039;&#039;npr&#039;&#039;&#039;(x,y) - Functions to calculate &#039;&#039;[[wikipedia:Combination|combinations]]&#039;&#039; and &#039;&#039;[[wikipedia:Permutation|permutations]]&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pow&#039;&#039;&#039;(x,y) - Returns &#039;&#039;x^y&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;sqrt&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Square_root|square root]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;cos&#039;&#039;&#039;(x), &#039;&#039;&#039;sin&#039;&#039;&#039;(x), &#039;&#039;&#039;tan&#039;&#039;&#039;(x) - Returns the [[wikipedia:Trigonometric_functions|&#039;&#039;cos, sin&#039;&#039; and &#039;&#039;tan&#039;&#039;]] of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;cosh&#039;&#039;&#039;(x), &#039;&#039;&#039;sinh&#039;&#039;&#039;(x), &#039;&#039;&#039;tanh&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Hyperbolic_functions|hyperbolic cos, sin and tan]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
The &#039;&#039;specialized functions&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;bool&#039;&#039;&#039;(x) - Returns 1 if &#039;&#039;x&#039;&#039; is more than 0&lt;br /&gt;
* &#039;&#039;&#039;ibool&#039;&#039;&#039;(x) - Returns 0 if &#039;&#039;x&#039;&#039; is more than 0&lt;br /&gt;
* &#039;&#039;&#039;deadband&#039;&#039;&#039;(x,y) - Returns &#039;&#039;x + y &#039;&#039; if &#039;&#039;x &amp;lt; y&#039;&#039; or &#039;&#039;x - y&#039;&#039; if &#039;&#039;x &amp;gt; y&#039;&#039;. If neither of these statements is true it returns &#039;&#039;0&#039;&#039; - used to create a [[wikipedia:Deadband|deadband]] of &#039;&#039;x&#039;&#039; with the threshold of &#039;&#039;y&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Functions&#039;&#039; can be readily used in a &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
bowmotorrun:1, bowcontrolfrequency:&amp;quot;8.17579875 * pow(2, (1/12 * note))&amp;quot;&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bowingwheel.dcmotor.run:1, bowingwheel.pid.targetfrequency:&amp;quot;8.17579875 * pow(2, (1/12 * note))&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;The previous statements starts the &#039;&#039;bowing wheel&#039;&#039; and sets the frequency of the wheel to &#039;&#039;8.17579875 * 2^(1/12 * note)&#039;&#039;. A middle &#039;C&#039; according to &#039;&#039;MIDI&#039;&#039; has a &#039;&#039;note value&#039;&#039; of 36, meaning if we substitute &#039;&#039;note&#039;&#039; with 36 we get the equation &#039;&#039;8.17579875 * 2^(1/12 * 36)&#039;&#039; which comes out to &#039;&#039;~65.4&#039;&#039; Hertz.&lt;br /&gt;
&lt;br /&gt;
Note that the first &#039;&#039;parameter&#039;&#039; for &#039;&#039;bowcontrolfrequency / bowingwheel.pid.targetfrequency&#039;&#039; is put in between double quotes (&amp;quot;). This is because the &#039;&#039;pow&#039;&#039;-function requires the use of a comma (&amp;quot;,&amp;quot;) in order to separate in between its two required inputs; &#039;&#039;x&#039;&#039; and &#039;&#039;y&#039;&#039;. In order for the Ekdahl FAR to know that this comma does not signal the beginning of a new &#039;&#039;command,&#039;&#039; we use quotes. Single (&#039;) and double (&amp;quot;) quotes can be used and nested in all &#039;&#039;parameters&#039;&#039; and are &amp;lt;u&amp;gt;required&amp;lt;/u&amp;gt; in a lot of circumstances, improper nesting or not using quotes can lead to the instrument not understanding the &#039;&#039;command string&#039;&#039; correctly.&lt;br /&gt;
&lt;br /&gt;
== Return messages ==&lt;br /&gt;
The Ekdahl FAR when connected via &#039;&#039;USB-Serial&#039;&#039; doesn&#039;t only accept &#039;&#039;commands&#039;&#039; but will also send various &#039;&#039;return messages&#039;&#039;. These are prefixed by their &#039;&#039;category&#039;&#039; denoted in brackets (&amp;quot;[]&amp;quot;), the existing categories as of this writing (2025-01-22) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;command&#039;&#039;&#039; / &#039;&#039;&#039;cmd&#039;&#039;&#039; - Acknowledges the reception of a command in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;usb&#039;&#039;&#039; - Acknowledges the reception of a &#039;&#039;MIDI message&#039;&#039; over &#039;&#039;USB&#039;&#039; in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;hardware&#039;&#039;&#039; / &#039;&#039;&#039;hw&#039;&#039;&#039; - Signals that a change has been sent to the Ekdahl FAR hardware, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;undefined&#039;&#039;&#039; / &#039;&#039;&#039;un&#039;&#039;&#039; - The message sent is in the &#039;&#039;undefined&#039;&#039; category, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;priority&#039;&#039;&#039; / &#039;&#039;&#039;pri&#039;&#039;&#039; - The message sent is in the &#039;&#039;priority&#039;&#039; category, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;error&#039;&#039;&#039; / &#039;&#039;&#039;err&#039;&#039;&#039; - Signals that an &#039;&#039;error&#039;&#039; has occurred, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;expressionparser&#039;&#039;&#039; / &#039;&#039;&#039;ep&#039;&#039;&#039; - These messages contains debugging information regarding the internal &#039;&#039;expression parser&#039;&#039; and is used for development&lt;br /&gt;
*&#039;&#039;&#039;debug&#039;&#039;&#039; / &#039;&#039;&#039;dbg&#039;&#039;&#039; - These messages contains various debugging information and is used for development&lt;br /&gt;
*&#039;&#039;&#039;help&#039;&#039;&#039; / &#039;&#039;&#039;hlp&#039;&#039;&#039; - Signals that the message is a response to a &#039;&#039;help&#039;&#039;-command being sent to the Ekdahl FAR. These messages are structured so that a receiver, like the &#039;&#039;Configuration utility&#039;&#039;, can parse information about available &#039;&#039;commands&#039;&#039; in the current &#039;&#039;firmware&#039;&#039; and relay it to a user in a structured way.&lt;br /&gt;
* &#039;&#039;&#039;inforequest&#039;&#039;&#039; / &#039;&#039;&#039;irq&#039;&#039;&#039; - Signals that an &#039;&#039;info request&#039;&#039; has been returned. This is a specialized message that is either sent as a response to an &#039;&#039;rqi&#039;&#039;-command or as a &#039;&#039;interrupt&#039;&#039;-message telling the user or receiving software about different parameters in the Ekdahl FAR. These messages follows the same structure as regular &#039;&#039;command message&#039;&#039;s of &#039;&#039;[irq]commandname:parameter1 [etc]&#039;&#039; so that it can be used by a receiving software to keep track of parameter changes&lt;br /&gt;
&lt;br /&gt;
===== Explicitly requesting information =====&lt;br /&gt;
By using the special command &#039;&#039;requestinfo / rqi&#039;&#039; one can request the information stored by a certain &#039;&#039;command&#039;&#039; or a state of the Ekdahl FAR. The &#039;&#039;rqi&#039;&#039;-command is executed in the convention &#039;&#039;rqi:commandname[:optional parameters]&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
To go back to our example of setting the bowing frequency using the &#039;&#039;bowcontrolfrequency&#039;&#039;-command we can ask the Ekdahl FAR what the bowing frequency is set to by writing&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
rqi:bowcontrolfrequency&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
rqi:bowingwheel.pid.targetfrequency&lt;br /&gt;
&amp;lt;/pre&amp;gt;The return value would be something like&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
[irq]bcf:82.5&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
[irq]bw[0].pid[0].tf:82.5&lt;br /&gt;
&amp;lt;/pre&amp;gt;Where &#039;[irq]&#039; denotes that the message returned is in the &#039;&#039;info request-&#039;&#039;category, that it pertains to the command &#039;&#039;bcf&#039;&#039; / &#039;&#039;bw.pid.tf&#039;&#039; and has the value &#039;&#039;82.5&#039;&#039;. Note that the returned &#039;&#039;command&#039;&#039; sent by an &#039;&#039;rqi&#039;&#039;-command always uses the &#039;&#039;short name&#039;&#039; in order to preserve bandwidth. In the FAR 1.1 the return statement always returns the &#039;&#039;index&#039;&#039; of the &#039;&#039;module&#039;&#039;(s) in question.&lt;br /&gt;
&lt;br /&gt;
Most commands do not require any &#039;&#039;parameters&#039;&#039; when using the &#039;&#039;rqi&#039;&#039;-command. The &#039;&#039;adcread&#039;&#039; / &#039;&#039;datareturn&#039;&#039;-command is an example of a &#039;&#039;command&#039;&#039; that &amp;lt;u&amp;gt;does&amp;lt;/u&amp;gt; require a &#039;&#039;parameter&#039;&#039; when used with &#039;&#039;rqi&#039;&#039;. The &#039;&#039;adcread / datareturn-&#039;&#039;command returns the last value read by the &#039;&#039;analog-to-digital converter&#039;&#039; in the &#039;&#039;Control box&#039;&#039;, because there are 8 different channels the first &#039;&#039;parameter&#039;&#039; sets which channel to return the data for, hence executing the &#039;&#039;command&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
rqi:adcr:3&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
rqi:controlbox.datareturn:3&lt;br /&gt;
&amp;lt;/pre&amp;gt;will return the last data read on &#039;&#039;analog-to-digital convert&#039;&#039; channel 3.&lt;br /&gt;
&lt;br /&gt;
== MIDI mapping ==&lt;br /&gt;
To change how a certain &#039;&#039;MIDI message&#039;&#039; interacts with the Ekdahl FAR we need to change the &#039;&#039;commands&#039;&#039; or &#039;&#039;parameters&#039;&#039; sent when the message is received. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;FAR &amp;lt; 1.1:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
The &#039;&#039;command&#039;&#039; responsible for mapping &#039;&#039;command strings&#039;&#039; to different &#039;&#039;MIDI messages&#039;&#039; is &#039;&#039;midieventhandler&#039;&#039; or &#039;&#039;mev&#039;&#039; for short. The first &#039;&#039;parameter&#039;&#039; of &#039;&#039;mev&#039;&#039; is the type of &#039;&#039;MIDI message&#039;&#039; that we want to remap&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;&#039;&#039;noteon&#039;&#039;&#039;&#039;&#039; - Note on&lt;br /&gt;
* &#039;&#039;&#039;&#039;&#039;noteoff&#039;&#039;&#039; -&#039;&#039; Note off&lt;br /&gt;
* &#039;&#039;&#039;&#039;&#039;pat&#039;&#039;&#039; -&#039;&#039; Poly after touch&lt;br /&gt;
* &#039;&#039;&#039;&#039;&#039;cat&#039;&#039;&#039;&#039;&#039; - Channel after touch&lt;br /&gt;
* &#039;&#039;&#039;&#039;&#039;pb&#039;&#039;&#039;&#039;&#039; - Pitch bend&lt;br /&gt;
* &#039;&#039;&#039;&#039;&#039;pc&#039;&#039;&#039;&#039;&#039; - Program change&lt;br /&gt;
* &#039;&#039;&#039;&#039;&#039;cc&#039;&#039;&#039;&#039;&#039; - Continuous controller&lt;br /&gt;
&lt;br /&gt;
The second &#039;&#039;parameter&#039;&#039; is the &#039;&#039;command string&#039;&#039; that is to be associated with the &#039;&#039;MIDI Message&#039;&#039; - with the exception of the &#039;&#039;cc&#039;&#039;-type, here the second &#039;&#039;parameter&#039;&#039; is the &#039;&#039;controller number&#039;&#039; (0 - 127) and the &amp;lt;u&amp;gt;third&amp;lt;/u&amp;gt; &#039;&#039;parameter&#039;&#039; is the &#039;&#039;command string&#039;&#039;.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;FAR 1.1:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;commands&#039;&#039; responsible for mapping &#039;&#039;command strings&#039;&#039; to different &#039;&#039;MIDI messages&#039;&#039; are as follows&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;noteon/non&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;&#039;note on&#039;&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;noteoff&#039;&#039;/nof&#039;&#039;&#039;&#039;&#039;&amp;lt;nowiki/&amp;gt;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;&#039;note off MIDI message&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;polyaftertouch/pat&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;&#039;poly aftertouch MIDI message&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;channelaftertouch/cat&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;&#039;channel aftertouch MIDI message&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pitchbend/pb&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;&#039;pitch bend MIDI message&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;programchange/pc&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;&#039;program change MIDI message&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;continuouscontrollerdata/ccd&#039;&#039;&#039;&#039;&#039;:controller:commands&#039;&#039; - Sets the commands executed for &#039;&#039;continuous controller&#039;&#039; no &#039;&#039;controller&#039;&#039;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can of course use the &#039;&#039;rqi&#039;&#039;-command to check the current mapping, below we are asking what the current &#039;&#039;command string&#039;&#039; associated with the &#039;&#039;pitch bend&#039;&#039; &#039;&#039;MIDI message&#039;&#039; is&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
rqi:mev:pb&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
rqi:mcf.mc.pb&lt;br /&gt;
&amp;lt;/pre&amp;gt;This may return something like&amp;lt;pre&amp;gt;&lt;br /&gt;
[irq]bchsh:pitch*4&lt;br /&gt;
&amp;lt;/pre&amp;gt;The return message tells us that the &#039;&#039;pitch bend MIDI message&#039;&#039; is executing a &#039;&#039;bchsh&#039;&#039;-command with the parameter &#039;&#039;pitch*4&#039;&#039;. Looking in the &#039;&#039;command reference&#039;&#039; we can see that &#039;&#039;bchsh&#039;&#039; is the &#039;&#039;short name&#039;&#039; of the &#039;&#039;bowcontrolharmonicshift&#039;&#039;-command which shifts the frequency of the &#039;&#039;bowing wheel&#039;&#039; from the current frequency, the first (and only) parameter sets how much we want to shift it (depends on the &#039;&#039;bowcontrolharmonicshiftrange command&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
If we look in the list of &#039;&#039;[[The Ekdahl FAR - Command langue#Variables|variables]]&#039;&#039; above we can see that the &#039;&#039;pitch bend MIDI message&#039;&#039; will set the &#039;&#039;pitch variable&#039;&#039; which is indeed used. Now what is the &#039;&#039;&#039;*4&#039;&#039;&amp;lt;nowiki/&amp;gt;&#039; all about? Well the &#039;&#039;bchsh&#039;&#039;-command expects a &#039;&#039;16-bit signed&#039;&#039; value, meaning that a full &#039;&#039;harmonic shift&#039;&#039; downwards is equal to -32767, a full &#039;&#039;harmonic shift&#039;&#039; upwards is 32767 and no &#039;&#039;harmonic shift&#039;&#039; is 0. The &#039;&#039;pitch bend MIDI message&#039;&#039; however is only 14-bits, meaning its range is -8192 to 8192, so in order to be able to use the entire range we have to multiply &#039;&#039;pitch&#039;&#039; by 4.&lt;br /&gt;
&lt;br /&gt;
This whole thing about number of bits can seem confusing but in the end it&#039;s all about how fine control you have over things; the more possible values, the more detailed control. In fact, most &#039;&#039;MIDI&#039;&#039; values are only 7-bit (!) meaning a range of 0 - 127. While this may sound like a lot of detail for something like a volume control, it is not even close to enough resolution to for instance set the &#039;&#039;bowing speed&#039;&#039;. Imagine that our lowest possible note frequency is 50 Hz, that means that with a 0-127 range we can only go from 50 Hz to 127 + 50 = 177 Hz - and with no decimals! This meager range and the very coarse steps of only 1 Hz would mean the instrument would never be able to sound in tune and wouldn&#039;t even have two octaves of range. The idea of limiting the Ekdahl FAR to what is possible through &#039;&#039;MIDI&#039;&#039; seemed like a poor choice thus it was decided that &amp;lt;u&amp;gt;most&amp;lt;/u&amp;gt; parameters will instead be 16-bit.&lt;br /&gt;
&lt;br /&gt;
Now lets look at a more complex example, the &amp;lt;u&amp;gt;default&amp;lt;/u&amp;gt; &#039;&#039;Note On MIDI message&#039;&#039;. On a stock Ekdahl FAR, executing&amp;lt;pre&amp;gt;&lt;br /&gt;
rqi:mev:noteon&lt;br /&gt;
&amp;lt;/pre&amp;gt;Will return something like&amp;lt;pre&amp;gt;[irq]mev:noteon:&#039;m:0,b:0,bchb:note,bmr:1,bpid:1,bpe:1,se:(velocity*512)*(1-notecount),bcsm:0&#039;&amp;lt;/pre&amp;gt;As can be seen, there&#039;s a lot of stuff going on here! First of all, notice that everything after &#039;&#039;mev:noteon:&#039;&#039; is situated in between single quotes (&#039;) - this is &amp;lt;u&amp;gt;absolutely crucial&amp;lt;/u&amp;gt; for the Ekdahl FAR to know that everything within those last two quotes is part of the last &#039;&#039;parameter&#039;&#039; of the &#039;&#039;mev&#039;&#039;-command.&lt;br /&gt;
&lt;br /&gt;
Now let&#039;s break down what happens when this &#039;&#039;MIDI message&#039;&#039; is received, i.e. when a &#039;&#039;MIDI&#039;&#039; key is pressed down:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;m:0&#039;&#039; - Sets &#039;&#039;module&#039;&#039; to 0&lt;br /&gt;
# &#039;&#039;b:0&#039;&#039; - Sets &#039;&#039;bow&#039;&#039; to 0&lt;br /&gt;
# &#039;&#039;bchb:note&#039;&#039; - Invokes the &#039;&#039;bowcontrolharmonicbase-&#039;&#039;command with the first &#039;&#039;parameter&#039;&#039; set to the &#039;&#039;variable note&#039;&#039;. &lt;br /&gt;
# &#039;&#039;bmr:1&#039;&#039; - Sets the &#039;&#039;bowmotorrun&#039;&#039;-command to &#039;1&#039;, starting the &#039;&#039;bow motor&#039;&#039;&lt;br /&gt;
# &#039;&#039;bpid:1&#039;&#039; - Sets the &#039;&#039;bowpid&#039;&#039;-command to &#039;1&#039;, making sure the &#039;&#039;PID&#039;&#039; is used&lt;br /&gt;
# &#039;&#039;bpe:1&#039;&#039; - Sets the &#039;&#039;bowpressureengage&#039;&#039; to &#039;1&#039; which moves the &#039;&#039;bowing jack&#039;&#039; to the &#039;&#039;engage position&#039;&#039;&lt;br /&gt;
# &#039;&#039;se:(velocity*512)*(1-notecount)&#039;&#039; - Executes the &#039;&#039;solenoidengage&#039;&#039;-command with the value &#039;&#039;(velocity*512)*(1-notecount)&#039;&#039;&lt;br /&gt;
# &#039;&#039;bcsm:0&#039;&#039; - Sets the &#039;&#039;bowcontrolspeedmode&#039;&#039; to &#039;1&#039; which enables automatic shut down of the &#039;&#039;bowing motor&#039;&#039;&lt;br /&gt;
The first two &#039;&#039;commands&#039;&#039; are the &#039;&#039;module&#039;&#039;- and &#039;&#039;bow-&#039;&#039;command. These &#039;&#039;commands&#039;&#039; are is intended for future versions of the Ekdahl FAR that may contain more than one string or more than one bow per string. For now &#039;&#039;0&#039;&#039; is the only valid &#039;&#039;parameter&#039;&#039; value that will be accepted for either &#039;&#039;command&#039;&#039;.&#039;&#039;&amp;lt;nowiki/&amp;gt;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;bowcontrolharmonicbase&#039;&#039;-command sets the speed of the &#039;&#039;bowing wheel&#039;&#039; to its corresponding &#039;&#039;harmonic number&#039;&#039; but also takes into account its &#039;&#039;&amp;lt;nowiki/&amp;gt;&#039;base&#039;&#039;&#039; which is the &#039;&#039;MIDI key&#039;&#039; that is mapped to &#039;&#039;harmonic number 0&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
After this the bowing motor is started and the &#039;&#039;PID&#039;&#039; is turned, now the instrument will try and make sure that the &#039;&#039;bowing wheel&#039;&#039; is at the right speed.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;bowing jack&#039;&#039; is raised to the &#039;&#039;engage position&#039;&#039;, any added &#039;&#039;pressure modifiers&#039;&#039; will also be taken into account - once the &#039;&#039;bowing jack&#039;&#039; has reached its intended position the &#039;&#039;bowing wheel&#039;&#039; should (hopefully) make contact with the string and the Ekdahl FAR will start to produce sounds.&lt;br /&gt;
&lt;br /&gt;
After this we have the &#039;&#039;solenoidengage&#039;&#039;-command &#039;&#039;command&#039;&#039; that engages the &#039;&#039;hammer&#039;&#039; and uses the first and only &#039;&#039;parameter&#039;&#039; as the force used. Like with most &#039;&#039;commands&#039;&#039; the &#039;&#039;se&#039;&#039;-command is 16-bit (0 - 65535) but the &#039;&#039;MIDI velocity variable&#039;&#039; is 7-bit (0 - 127), so to get the &#039;&#039;velocity&#039;&#039; variable to cover the entire range it needs to be multiplied with 512. &lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&amp;lt;nowiki/&amp;gt;&#039;*(1-notecount)&#039;&#039;&#039;-part is a way of making sure that we are using &#039;&#039;legato&#039;&#039; mode, i.e. that the &#039;&#039;hammer&#039;&#039; is not triggered if a key is already held down when a new key is pressed. The &#039;&#039;notecount&#039;&#039;-variable contains the number of &#039;&#039;MIDI&#039;&#039; notes currently held down. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s postulate that the Ekdahl FAR is tuned to a &#039;C&#039; at 65.4Hz and has its &#039;&#039;base&#039;&#039; set to middle &#039;C&#039; (&#039;&#039;MIDI key&#039;&#039; no 36). We are using the equal-temperament 12-tone scale and the Ekdahl FAR is set to respond to &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; &#039;&#039;MIDI channels&#039;&#039; (omni). Without having previously held any keys we press the middle &#039;C&#039; (&#039;&#039;note&#039;&#039; value 36) as hard as possible (&#039;&#039;velocity&#039;&#039; value &#039;&#039;127&#039;&#039;) on &#039;&#039;MIDI channel&#039;&#039; number 1 (&#039;&#039;channel&#039;&#039; value of 0). The Ekdahl FAR will get a &#039;&#039;note on MIDI message&#039;&#039; sent to it and from our mapping it will create the following &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;[irq]mev:noteon:&#039;m:0,b:0,bchb:36,bmr:1,bpid:1,bpe:1,se:(127*512)*(1-0),bcsm:0&#039;&amp;lt;/pre&amp;gt;What has happened here is that all &#039;&#039;variables&#039;&#039; have been replaced with the values sent by the &#039;&#039;MIDI message&#039;&#039;. Since those &#039;&#039;commands&#039;&#039; that doesn&#039;t have any &#039;&#039;variables&#039;&#039; with them will execute just as previously, only those &#039;&#039;commands&#039;&#039; whos &#039;&#039;parameters&#039;&#039; have changed will be explained:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;bchb: 36&#039;&#039; - The &#039;&#039;bowcontrolharmonicbase&#039;&#039; gets a value of &#039;&#039;36&#039;&#039; (middle &#039;C&#039;), because &#039;&#039;harmonic number 0&#039;&#039; is mapped to this key it will set the &#039;&#039;bowing wheel&#039;&#039; frequency to the &#039;&#039;fundamental&#039;&#039;; &#039;&#039;65.4&#039;&#039; Hertz&lt;br /&gt;
# &#039;&#039;se: (127*512)*(1-0)&#039;&#039; - the value of &#039;&#039;127&#039;&#039; comes from the &#039;&#039;velocity&#039;&#039;-variable, &#039;&#039;127 * 512 = 65024&#039;&#039; which is awfully close to a maximum hammer force of 65535. Since no previous notes were held down &#039;&#039;notecount&#039;&#039;  is equal to &#039;&#039;0&#039;&#039; and thus &#039;&#039;65024 * 1 = 65024&#039;&#039;. The hammer is engaged with near maximum force.&lt;br /&gt;
So the result is that we have set the speed of the &#039;&#039;bowing motor&#039;&#039; and we have engaged the &#039;&#039;hammer&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Now imagine that without releasing this key, we press another &#039;C&#039; one octave above but at half the velocity. The Ekdahl FAR creates the following &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
[irq]mev:noteon:&#039;m:0,b:0,bchb:48,bmr:1,bpid:1,bpe:1,se:(63*512)*(1-1),bcsm:0&#039;&lt;br /&gt;
&amp;lt;/pre&amp;gt;Now we can see that the &#039;&#039;note&#039;&#039; variable is &#039;&#039;48&#039;&#039; because the &#039;C&#039; one octave up is exactly 12 keys above the first, the &#039;&#039;velocity&#039;&#039; variable has changed to &#039;&#039;63&#039;&#039; since we hit it with a lighter touch - and because we are &amp;lt;u&amp;gt;still holding the first key down&amp;lt;/u&amp;gt; &#039;&#039;notecount&#039;&#039; is equal to &#039;&#039;1&#039;&#039;. Here&#039;s what happens&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;bchb: 48&#039;&#039; - Due to the &#039;&#039;base&#039;&#039; being set to &#039;&#039;36&#039;&#039; the &#039;&#039;harmonic number&#039;&#039; is set to &#039;&#039;48 - 36 = 12&#039;&#039;. Because we are using a 12-tone scale &#039;&#039;harmonic number 12&#039;&#039; is exactly one octave above the &#039;&#039;fundamental&#039;&#039; thus the speed of the &#039;&#039;bowing wheel&#039;&#039; is set to &#039;&#039;65.4 * 2 = 130.8&#039;&#039; Hertz.&lt;br /&gt;
# &#039;&#039;se: (63*512)*(1-1)&#039;&#039; - So &#039;&#039;63 * 512 = 32256&#039;&#039; and &#039;&#039;1 - 1 = 0&#039;&#039; thus &#039;&#039;32256 * 0 = 0&#039;&#039;. When the &#039;&#039;solenoidengage&#039;&#039;-command gets a &#039;&#039;parameter&#039;&#039; of &#039;&#039;0&#039;&#039; it will not engage the &#039;&#039;hammer&#039;&#039; - so the &#039;&#039;hammer&#039;&#039; doesn&#039;t strike&lt;br /&gt;
So it can be seen that with quite rudimentary math we can accomplish a whole lot of things here. Note also that even though the &#039;&#039;note on MIDI message&#039;&#039; also sets the &#039;&#039;channel&#039;&#039;-variable we never use it in this example - plenty of opportunity to make something weird happen depending on the &#039;&#039;MIDI channel&#039;&#039;!&lt;br /&gt;
&lt;br /&gt;
== CV Mapping ==&lt;br /&gt;
&#039;&#039;CV Mapping&#039;&#039; works exactly like the &#039;&#039;MIDI mapping&#039;&#039; with the difference that the command for setting the &#039;&#039;CV mapping&#039;&#039; is different and that &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; events pertaining to this &amp;lt;u&amp;gt;only&amp;lt;/u&amp;gt; change the &#039;&#039;value&#039;&#039;-variable. The &#039;&#039;command&#039;&#039; for changing the &#039;&#039;CV mapping&#039;&#039; is &#039;&#039;adccommandmap&#039;&#039; or &#039;&#039;acm&#039;&#039;, it take two &#039;&#039;parameters&#039;&#039;; &#039;&#039;channel&#039;&#039; and &#039;&#039;command string&#039;&#039;. We retrieve the &#039;&#039;command string&#039;&#039; for channel &#039;&#039;0&#039;&#039; which reads the sum of the &#039;&#039;harm. v/oct&#039;&#039;-jack and the &#039;&#039;harmonic&#039;&#039;-knob by sending a command of&amp;lt;pre&amp;gt;&lt;br /&gt;
rqi:acm:0&lt;br /&gt;
&amp;lt;/pre&amp;gt;The &amp;lt;u&amp;gt;default&amp;lt;/u&amp;gt; response will be something like&lt;br /&gt;
&amp;lt;pre&amp;gt;[irq]acm:0:&#039;bcha:value/1327.716667-20&#039;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{docnav&lt;br /&gt;
|[[The Ekdahl FAR - Service|Service]]&lt;br /&gt;
|[[The Ekdahl FAR - Command reference|Command reference]]&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Knaadmin</name></author>
	</entry>
	<entry>
		<id>http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_language&amp;diff=1650</id>
		<title>The Ekdahl FAR - Command language</title>
		<link rel="alternate" type="text/html" href="http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_language&amp;diff=1650"/>
		<updated>2026-06-08T14:18:17Z</updated>

		<summary type="html">&lt;p&gt;Knaadmin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Command language ==&lt;br /&gt;
The Ekdahl FAR is entirely controlled by &#039;&#039;commands&#039;&#039;, these &#039;&#039;commands&#039;&#039; decide everything that the instrument is doing, whether it is playing a melody or changing an internal parameter. &lt;br /&gt;
&lt;br /&gt;
When a &#039;&#039;MIDI message&#039;&#039; is received or a new CV / knob value is read, the &#039;&#039;commands&#039;&#039; associated with it will be internally sent. This can be things like &amp;quot;engage hammer&amp;quot; or &amp;quot;set the fundamental frequency&amp;quot; etc. &lt;br /&gt;
&lt;br /&gt;
Some of the available &#039;&#039;commands&#039;&#039; are mainly used for calibrating and setting up the instrument and are usually saved into the instruments memory, these will be executed whenever the instrument is turned on. &lt;br /&gt;
&lt;br /&gt;
All &#039;&#039;commands&#039;&#039; can be manually invoked via &#039;&#039;USB-Serial&#039;&#039;, in conjunction with certain software this presents an unprecedented level of control and sequenceability.&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
The &#039;&#039;commands&#039;&#039; are invoked using a &#039;&#039;plain text approach&#039;&#039;, all commands have both a &#039;&#039;long name&#039;&#039; and a &#039;&#039;short name&#039;&#039; which are interchangeable. A &#039;&#039;command&#039;&#039; may have one or more &#039;&#039;parameters&#039;&#039; associated with it, these &#039;&#039;parameters&#039;&#039; can be of different types; 16-bit numbers (values 0 - 65535 or -32767 - 32767), floating point numbers (values with decimals), booleans (0 for &#039;false&#039;, 1 for &#039;true&#039;) and strings (text). Some commands are &#039;&#039;conditional&#039;&#039;, meaning they will only execute if a parameter equates to &#039;1&#039; (&#039;true&#039;). &lt;br /&gt;
&lt;br /&gt;
The way &#039;&#039;commands&#039;&#039; are written in order to be executed is &#039;&#039;commandname:parameter1:parameter2:parameter3 [etc]&#039;&#039;, several commands be executed in sequence by separating them with a comma (&#039;,&#039;), a bunch of commands strung together is called a &#039;&#039;command string&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Since version 1.1 of the Ekdahl FAR Firmware, all commands are grouped in a hierarchical fashion according to their &#039;&#039;modules&#039;&#039; and each ladder in the hierarchy is separated by a period (&amp;quot;.&amp;quot;), this works very much like folders or directories in a regular computer. Every &#039;&#039;module&#039;&#039; can contain both &#039;&#039;commands&#039;&#039; and other &#039;&#039;modules&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
For instance, everything associated with the &#039;&#039;bowing wheel&#039;&#039; is now collected under &amp;quot;bowingwheel&amp;quot; &#039;&#039;module&#039;&#039;. That in turn contains a &amp;quot;dcmotor&amp;quot; &#039;&#039;module&#039;&#039; which does direct control of the bowing motor, and it has a &amp;quot;pid&amp;quot; &#039;&#039;module&#039;&#039; that handles bow frequency.&lt;br /&gt;
&lt;br /&gt;
If for instance we would like to start the &#039;&#039;bowing wheel&#039;&#039; and set its frequency to 82.5 Hertz we could send the Ekdahl FAR the following &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
bowmotorrun:1, bowcontrolfrequecy:82.5&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bowingwheel.dcmotor.run:1, bowingwheel.pid.targetfrequency:82.5&amp;lt;/pre&amp;gt;We could also use the &#039;&#039;short names&#039;&#039; for the commands&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
bmr:1,bcf:82.5&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bw.dcm.ru:1, bw.pid.tf:82.5&amp;lt;/pre&amp;gt;Both &#039;&#039;bowmotorrun&#039;&#039; / &#039;&#039;bowingwheel.dcmotor.run&#039;&#039; and &#039;&#039;bowcontrolfrequency / bowingwheel.pid.targetfrequency&#039;&#039; takes one &#039;&#039;parameter&#039;&#039; each, &#039;&#039;bowmotorrun / bowingwheel.dcmotor.run&#039;&#039; is &#039;&#039;conditional&#039;&#039; and unless the first &#039;&#039;parameter&#039;&#039; is equal to &#039;1&#039; the motor will not start. The first &#039;&#039;parameter&#039;&#039; of &#039;&#039;bowcontrolfrequency / bowingwheel.pid.targetfrequency&#039;&#039; sets the frequency of the &#039;&#039;bowing wheel&#039;&#039;, the instrument may not execute a &#039;&#039;command&#039;&#039; if it decides that the given &#039;&#039;parameters&#039;&#039; are outside of the working range or they are missing.&lt;br /&gt;
&lt;br /&gt;
The addition of the hierarchy in the FAR 1.1 firmware isn&#039;t just to be able to group commands, but it&#039;s also to make the FAR not limited to a single set of &#039;&#039;modules&#039;&#039; (and is the first stepping stone to a &#039;&#039;modular&#039;&#039; Ekdahl FAR). In fact, you could have 12 different bowing wheel &#039;&#039;modules&#039;&#039; for 12 different strings, these would then be addressed as &#039;&#039;bowingwheel[0].command, bowingwheel[1].command&#039;&#039; etc. Anyone familiar with C programming notices that this is the standard way of &#039;&#039;indexing&#039;&#039; an array; using brackets (&amp;quot;[ ]&amp;quot;). When addressing a module without &#039;&#039;indexing&#039;&#039; as above, the FAR will do one or two things; either use the first object (&amp;quot;[0]&amp;quot;) or, if the object is &#039;&#039;selectable&#039;&#039; it will use the previously selected object. To make things smoother a command can be executed on several objects at once by using ranges (&amp;quot;[0-4]&amp;quot;) and comma separation (&amp;quot;[0, 3, 5-6]&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
To test out a &#039;&#039;command&#039;&#039; you can send it directly to the Ekdahl FAR using the &#039;&#039;Console&#039;&#039; in the &#039;&#039;Configuration utility&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
To read up on existing &#039;&#039;commands&#039;&#039;, their &#039;&#039;parameters&#039;&#039; and a brief description you can check the &#039;&#039;Command reference&#039;&#039; in the &#039;&#039;Configuration utility&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Variables, functions and equations ==&lt;br /&gt;
What makes the &#039;&#039;Command language&#039;&#039; truly powerful is the concept of &#039;&#039;variables, functions&#039;&#039; and &#039;&#039;equations&#039;&#039;. All &#039;&#039;parameters&#039;&#039; that take numerical values can use any combination of &#039;&#039;variables, functions&#039;&#039; or &#039;&#039;equations.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
For instance, we can use the previous example and instead write our &#039;&#039;command string&#039;&#039; as follows&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
bowmotorrun:1, bowcontrolfrequency:82.5+note*20&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bowingwheel.dcmotor.run:1, bowingwheel.pid.targetfrequency:82.5+note*20&amp;lt;/pre&amp;gt;This example requires of course that the &#039;&#039;variable&#039;&#039; &#039;&#039;note&#039;&#039; exists in the current context. &lt;br /&gt;
&lt;br /&gt;
===== Variables =====&lt;br /&gt;
There are two types of &#039;&#039;variables&#039;&#039; in the Ekdahl FAR; &#039;&#039;global variables&#039;&#039; and &#039;&#039;event variables&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Global variables&#039;&#039; are variables that are always available and will exist in any context. The &#039;&#039;global variables&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;notecount&#039;&#039;&#039; - Contains the number of &#039;&#039;MIDI&#039;&#039; keys that are being held down, i.e. all &#039;&#039;Note on messages&#039;&#039; received that haven&#039;t gotten a paired &#039;&#039;Note off message&#039;&#039; yet&lt;br /&gt;
* &#039;&#039;&#039;uv0&#039;&#039;&#039; - &#039;&#039;&#039;uv9&#039;&#039;&#039; - These are &#039;&#039;user variables&#039;&#039; and can be set at any point using the &#039;&#039;globaluservariable command&#039;&#039; with the first &#039;&#039;parameter&#039;&#039; being which variable to set (0-9) and the second &#039;&#039;parameter&#039;&#039; being the value (float).&lt;br /&gt;
* &#039;&#039;&#039;e&#039;&#039;&#039; - Contains the constant &#039;&#039;[[wikipedia:E_(mathematical_constant)|e]]&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pi&#039;&#039;&#039; - Contains the constant &#039;&#039;[[wikipedia:Pi|pi]]&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Event variables&#039;&#039; are variables that are set by certain &#039;&#039;MIDI messages&#039;&#039; or when a new value is read on one of the jacks or knobs on the &#039;&#039;Control box&#039;&#039;. The &#039;&#039;Event variables&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;channel&#039;&#039;&#039; - Set by the &#039;&#039;Note on, Note off, Continuous Controller, Poly after touch, Pitch bend, Channel after touch&#039;&#039; and &#039;&#039;Program change MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;note&#039;&#039;&#039; - Set by the &#039;&#039;Note on, Note off&#039;&#039; and &#039;&#039;Poly after touch MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;velocity&#039;&#039;&#039; - Set by the &#039;&#039;Note on&#039;&#039; and &#039;&#039;Note off MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pressure&#039;&#039;&#039; - Set by the &#039;&#039;Poly after touch&#039;&#039; and &#039;&#039;Channel after touch MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; - Set by the &#039;&#039;Continuous Controller MIDI message&#039;&#039; and by the &#039;&#039;Control box&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pitch&#039;&#039;&#039; - Set by the &#039;&#039;Pitch bend MIDI message&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;program&#039;&#039;&#039; - Set by the &#039;&#039;Program change MIDI message&#039;&#039;&lt;br /&gt;
These variables will contain whatever data is relevant to the &amp;lt;u&amp;gt;last midi message sent&amp;lt;/u&amp;gt; and will not stay relevant beyond the reception of the last message.&lt;br /&gt;
&lt;br /&gt;
===== Functions =====&lt;br /&gt;
&#039;&#039;Functions&#039;&#039; can be used to change a numerical value or the result of an &#039;&#039;equation&#039;&#039;, the Ekdahl FAR contains both general &#039;&#039;arithmetic functions&#039;&#039; (courtesy of Lewis Van Winkle and the TINYEXPR engine) and &#039;&#039;specialized functions&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;arithmetic functions&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;abs&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Absolute_value|absolute value]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;acos&#039;&#039;&#039;(x), &#039;&#039;&#039;asin&#039;&#039;&#039;(x), &#039;&#039;&#039;atan&#039;&#039;&#039;(x), atan2(x, y) - Returns the [[wikipedia:Inverse_trigonometric_functions|&#039;&#039;arc-cos, -sin, -tan&#039;&#039; and &#039;&#039;-tan2&#039;&#039;]] of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;atan2&#039;&#039;&#039;(x,y) - Returns the &#039;&#039;[[wikipedia:Atan2|arctan2]]&#039;&#039; of &#039;&#039;x, y&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;floor&#039;&#039;&#039;(x), ceil(x) - Returns the [[wikipedia:Floor_and_ceiling_functions|&#039;&#039;floor&#039;&#039; and &#039;&#039;ceiling&#039;&#039;]] of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;exp&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Exponential_function|exponent]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;fac&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Factorial|factorial]]&#039;&#039; of x&lt;br /&gt;
* &#039;&#039;&#039;ln&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Natural_logarithm|natural logarithm]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;log10&#039;&#039;&#039;(x), &#039;&#039;&#039;log20&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Logarithm|logarithm]]&#039;&#039; of &#039;&#039;x&#039;&#039; using base 10 and 20 respectively&lt;br /&gt;
* &#039;&#039;&#039;ncr&#039;&#039;&#039;(x,y), &#039;&#039;&#039;npr&#039;&#039;&#039;(x,y) - Functions to calculate &#039;&#039;[[wikipedia:Combination|combinations]]&#039;&#039; and &#039;&#039;[[wikipedia:Permutation|permutations]]&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pow&#039;&#039;&#039;(x,y) - Returns &#039;&#039;x^y&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;sqrt&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Square_root|square root]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;cos&#039;&#039;&#039;(x), &#039;&#039;&#039;sin&#039;&#039;&#039;(x), &#039;&#039;&#039;tan&#039;&#039;&#039;(x) - Returns the [[wikipedia:Trigonometric_functions|&#039;&#039;cos, sin&#039;&#039; and &#039;&#039;tan&#039;&#039;]] of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;cosh&#039;&#039;&#039;(x), &#039;&#039;&#039;sinh&#039;&#039;&#039;(x), &#039;&#039;&#039;tanh&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Hyperbolic_functions|hyperbolic cos, sin and tan]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
The &#039;&#039;specialized functions&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;bool&#039;&#039;&#039;(x) - Returns 1 if &#039;&#039;x&#039;&#039; is more than 0&lt;br /&gt;
* &#039;&#039;&#039;ibool&#039;&#039;&#039;(x) - Returns 0 if &#039;&#039;x&#039;&#039; is more than 0&lt;br /&gt;
* &#039;&#039;&#039;deadband&#039;&#039;&#039;(x,y) - Returns &#039;&#039;x + y &#039;&#039; if &#039;&#039;x &amp;lt; y&#039;&#039; or &#039;&#039;x - y&#039;&#039; if &#039;&#039;x &amp;gt; y&#039;&#039;. If neither of these statements is true it returns &#039;&#039;0&#039;&#039; - used to create a [[wikipedia:Deadband|deadband]] of &#039;&#039;x&#039;&#039; with the threshold of &#039;&#039;y&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Functions&#039;&#039; can be readily used in a &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
bowmotorrun:1, bowcontrolfrequency:&amp;quot;8.17579875 * pow(2, (1/12 * note))&amp;quot;&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bowingwheel.dcmotor.run:1, bowingwheel.pid.targetfrequency:&amp;quot;8.17579875 * pow(2, (1/12 * note))&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;The previous statements starts the &#039;&#039;bowing wheel&#039;&#039; and sets the frequency of the wheel to &#039;&#039;8.17579875 * 2^(1/12 * note)&#039;&#039;. A middle &#039;C&#039; according to &#039;&#039;MIDI&#039;&#039; has a &#039;&#039;note value&#039;&#039; of 36, meaning if we substitute &#039;&#039;note&#039;&#039; with 36 we get the equation &#039;&#039;8.17579875 * 2^(1/12 * 36)&#039;&#039; which comes out to &#039;&#039;~65.4&#039;&#039; Hertz.&lt;br /&gt;
&lt;br /&gt;
Note that the first &#039;&#039;parameter&#039;&#039; for &#039;&#039;bowcontrolfrequency / bowingwheel.pid.targetfrequency&#039;&#039; is put in between double quotes (&amp;quot;). This is because the &#039;&#039;pow&#039;&#039;-function requires the use of a comma (&amp;quot;,&amp;quot;) in order to separate in between its two required inputs; &#039;&#039;x&#039;&#039; and &#039;&#039;y&#039;&#039;. In order for the Ekdahl FAR to know that this comma does not signal the beginning of a new &#039;&#039;command,&#039;&#039; we use quotes. Single (&#039;) and double (&amp;quot;) quotes can be used and nested in all &#039;&#039;parameters&#039;&#039; and are &amp;lt;u&amp;gt;required&amp;lt;/u&amp;gt; in a lot of circumstances, improper nesting or not using quotes can lead to the instrument not understanding the &#039;&#039;command string&#039;&#039; correctly.&lt;br /&gt;
&lt;br /&gt;
== Return messages ==&lt;br /&gt;
The Ekdahl FAR when connected via &#039;&#039;USB-Serial&#039;&#039; doesn&#039;t only accept &#039;&#039;commands&#039;&#039; but will also send various &#039;&#039;return messages&#039;&#039;. These are prefixed by their &#039;&#039;category&#039;&#039; denoted in brackets (&amp;quot;[]&amp;quot;), the existing categories as of this writing (2025-01-22) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;command&#039;&#039;&#039; / &#039;&#039;&#039;cmd&#039;&#039;&#039; - Acknowledges the reception of a command in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;usb&#039;&#039;&#039; - Acknowledges the reception of a &#039;&#039;MIDI message&#039;&#039; over &#039;&#039;USB&#039;&#039; in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;hardware&#039;&#039;&#039; / &#039;&#039;&#039;hw&#039;&#039;&#039; - Signals that a change has been sent to the Ekdahl FAR hardware, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;undefined&#039;&#039;&#039; / &#039;&#039;&#039;un&#039;&#039;&#039; - The message sent is in the &#039;&#039;undefined&#039;&#039; category, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;priority&#039;&#039;&#039; / &#039;&#039;&#039;pri&#039;&#039;&#039; - The message sent is in the &#039;&#039;priority&#039;&#039; category, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;error&#039;&#039;&#039; / &#039;&#039;&#039;err&#039;&#039;&#039; - Signals that an &#039;&#039;error&#039;&#039; has occurred, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;expressionparser&#039;&#039;&#039; / &#039;&#039;&#039;ep&#039;&#039;&#039; - These messages contains debugging information regarding the internal &#039;&#039;expression parser&#039;&#039; and is used for development&lt;br /&gt;
*&#039;&#039;&#039;debug&#039;&#039;&#039; / &#039;&#039;&#039;dbg&#039;&#039;&#039; - These messages contains various debugging information and is used for development&lt;br /&gt;
*&#039;&#039;&#039;help&#039;&#039;&#039; / &#039;&#039;&#039;hlp&#039;&#039;&#039; - Signals that the message is a response to a &#039;&#039;help&#039;&#039;-command being sent to the Ekdahl FAR. These messages are structured so that a receiver, like the &#039;&#039;Configuration utility&#039;&#039;, can parse information about available &#039;&#039;commands&#039;&#039; in the current &#039;&#039;firmware&#039;&#039; and relay it to a user in a structured way.&lt;br /&gt;
* &#039;&#039;&#039;inforequest&#039;&#039;&#039; / &#039;&#039;&#039;irq&#039;&#039;&#039; - Signals that an &#039;&#039;info request&#039;&#039; has been returned. This is a specialized message that is either sent as a response to an &#039;&#039;rqi&#039;&#039;-command or as a &#039;&#039;interrupt&#039;&#039;-message telling the user or receiving software about different parameters in the Ekdahl FAR. These messages follows the same structure as regular &#039;&#039;command message&#039;&#039;s of &#039;&#039;[irq]commandname:parameter1 [etc]&#039;&#039; so that it can be used by a receiving software to keep track of parameter changes&lt;br /&gt;
&lt;br /&gt;
===== Explicitly requesting information =====&lt;br /&gt;
By using the special command &#039;&#039;requestinfo / rqi&#039;&#039; one can request the information stored by a certain &#039;&#039;command&#039;&#039; or a state of the Ekdahl FAR. The &#039;&#039;rqi&#039;&#039;-command is executed in the convention &#039;&#039;rqi:commandname[:optional parameters]&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
To go back to our example of setting the bowing frequency using the &#039;&#039;bowcontrolfrequency&#039;&#039;-command we can ask the Ekdahl FAR what the bowing frequency is set to by writing&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
rqi:bowcontrolfrequency&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
rqi:bowingwheel.pid.targetfrequency&lt;br /&gt;
&amp;lt;/pre&amp;gt;The return value would be something like&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
[irq]bcf:82.5&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
[irq]bw[0].pid[0].tf:82.5&lt;br /&gt;
&amp;lt;/pre&amp;gt;Where &#039;[irq]&#039; denotes that the message returned is in the &#039;&#039;info request-&#039;&#039;category, that it pertains to the command &#039;&#039;bcf&#039;&#039; / &#039;&#039;bw.pid.tf&#039;&#039; and has the value &#039;&#039;82.5&#039;&#039;. Note that the returned &#039;&#039;command&#039;&#039; sent by an &#039;&#039;rqi&#039;&#039;-command always uses the &#039;&#039;short name&#039;&#039; in order to preserve bandwidth. In the FAR 1.1 the return statement always returns the &#039;&#039;index&#039;&#039; of the &#039;&#039;module&#039;&#039;(s) in question.&lt;br /&gt;
&lt;br /&gt;
Most commands do not require any &#039;&#039;parameters&#039;&#039; when using the &#039;&#039;rqi&#039;&#039;-command. The &#039;&#039;adcread&#039;&#039; / &#039;&#039;datareturn&#039;&#039;-command is an example of a &#039;&#039;command&#039;&#039; that &amp;lt;u&amp;gt;does&amp;lt;/u&amp;gt; require a &#039;&#039;parameter&#039;&#039; when used with &#039;&#039;rqi&#039;&#039;. The &#039;&#039;adcread / datareturn-&#039;&#039;command returns the last value read by the &#039;&#039;analog-to-digital converter&#039;&#039; in the &#039;&#039;Control box&#039;&#039;, because there are 8 different channels the first &#039;&#039;parameter&#039;&#039; sets which channel to return the data for, hence executing the &#039;&#039;command&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
rqi:adcr:3&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
rqi:controlbox.datareturn:3&lt;br /&gt;
&amp;lt;/pre&amp;gt;will return the last data read on &#039;&#039;analog-to-digital convert&#039;&#039; channel 3.&lt;br /&gt;
&lt;br /&gt;
== MIDI mapping ==&lt;br /&gt;
To change how a certain &#039;&#039;MIDI message&#039;&#039; interacts with the Ekdahl FAR we need to change the &#039;&#039;commands&#039;&#039; or &#039;&#039;parameters&#039;&#039; sent when the message is received. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;FAR &amp;lt; 1.1:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;command&#039;&#039; responsible for mapping &#039;&#039;command strings&#039;&#039; to different &#039;&#039;MIDI messages&#039;&#039; is &#039;&#039;midieventhandler&#039;&#039; or &#039;&#039;mev&#039;&#039; for short. The first &#039;&#039;parameter&#039;&#039; of &#039;&#039;mev&#039;&#039; is the type of &#039;&#039;MIDI message&#039;&#039; that we want to remap&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;&#039;&#039;noteon&#039;&#039;&#039;&#039;&#039; - Note on&lt;br /&gt;
* &#039;&#039;&#039;&#039;&#039;noteoff&#039;&#039;&#039; -&#039;&#039; Note off&lt;br /&gt;
* &#039;&#039;&#039;&#039;&#039;pat&#039;&#039;&#039; -&#039;&#039; Poly after touch&lt;br /&gt;
* &#039;&#039;&#039;&#039;&#039;cat&#039;&#039;&#039;&#039;&#039; - Channel after touch&lt;br /&gt;
* &#039;&#039;&#039;&#039;&#039;pb&#039;&#039;&#039;&#039;&#039; - Pitch bend&lt;br /&gt;
* &#039;&#039;&#039;&#039;&#039;pc&#039;&#039;&#039;&#039;&#039; - Program change&lt;br /&gt;
* &#039;&#039;&#039;&#039;&#039;cc&#039;&#039;&#039;&#039;&#039; - Continuous controller&lt;br /&gt;
&lt;br /&gt;
The second &#039;&#039;parameter&#039;&#039; is the &#039;&#039;command string&#039;&#039; that is to be associated with the &#039;&#039;MIDI Message&#039;&#039; - with the exception of the &#039;&#039;cc&#039;&#039;-type, here the second &#039;&#039;parameter&#039;&#039; is the &#039;&#039;controller number&#039;&#039; (0 - 127) and the &amp;lt;u&amp;gt;third&amp;lt;/u&amp;gt; &#039;&#039;parameter&#039;&#039; is the &#039;&#039;command string&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;FAR 1.1:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;commands&#039;&#039; responsible for mapping &#039;&#039;command strings&#039;&#039; to different &#039;&#039;MIDI messages&#039;&#039; are as follows&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;noteon/non&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;&#039;note on&#039;&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;noteoff&#039;&#039;/nof&#039;&#039;&#039;&#039;&#039;&amp;lt;nowiki/&amp;gt;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;&#039;note off MIDI message&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;polyaftertouch/pat&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;&#039;poly aftertouch MIDI message&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;channelaftertouch/cat&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;&#039;channel aftertouch MIDI message&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pitchbend/pb&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;&#039;pitch bend MIDI message&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;programchange/pc&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;&#039;program change MIDI message&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;continuouscontrollerdata/ccd&#039;&#039;&#039;&#039;&#039;:controller:commands&#039;&#039; - Sets the commands executed for &#039;&#039;continuous controller&#039;&#039; no &#039;&#039;controller&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
We can of course use the &#039;&#039;rqi&#039;&#039;-command to check the current mapping, below we are asking what the current &#039;&#039;command string&#039;&#039; associated with the &#039;&#039;pitch bend&#039;&#039; &#039;&#039;MIDI message&#039;&#039; is&amp;lt;pre&amp;gt;&lt;br /&gt;
rqi:mev:pb&lt;br /&gt;
&amp;lt;/pre&amp;gt;This may return something like&amp;lt;pre&amp;gt;&lt;br /&gt;
[irq]bchsh:pitch*4&lt;br /&gt;
&amp;lt;/pre&amp;gt;The return message tells us that the &#039;&#039;pitch bend MIDI message&#039;&#039; is executing a &#039;&#039;bchsh&#039;&#039;-command with the parameter &#039;&#039;pitch*4&#039;&#039;. Looking in the &#039;&#039;command reference&#039;&#039; we can see that &#039;&#039;bchsh&#039;&#039; is the &#039;&#039;short name&#039;&#039; of the &#039;&#039;bowcontrolharmonicshift&#039;&#039;-command which shifts the frequency of the &#039;&#039;bowing wheel&#039;&#039; from the current frequency, the first (and only) parameter sets how much we want to shift it (depends on the &#039;&#039;bowcontrolharmonicshiftrange command&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
If we look in the list of &#039;&#039;[[The Ekdahl FAR - Command langue#Variables|variables]]&#039;&#039; above we can see that the &#039;&#039;pitch bend MIDI message&#039;&#039; will set the &#039;&#039;pitch variable&#039;&#039; which is indeed used. Now what is the &#039;&#039;&#039;*4&#039;&#039;&amp;lt;nowiki/&amp;gt;&#039; all about? Well the &#039;&#039;bchsh&#039;&#039;-command expects a &#039;&#039;16-bit signed&#039;&#039; value, meaning that a full &#039;&#039;harmonic shift&#039;&#039; downwards is equal to -32767, a full &#039;&#039;harmonic shift&#039;&#039; upwards is 32767 and no &#039;&#039;harmonic shift&#039;&#039; is 0. The &#039;&#039;pitch bend MIDI message&#039;&#039; however is only 14-bits, meaning its range is -8192 to 8192, so in order to be able to use the entire range we have to multiply &#039;&#039;pitch&#039;&#039; by 4.&lt;br /&gt;
&lt;br /&gt;
This whole thing about number of bits can seem confusing but in the end it&#039;s all about how fine control you have over things; the more possible values, the more detailed control. In fact, most &#039;&#039;MIDI&#039;&#039; values are only 7-bit (!) meaning a range of 0 - 127. While this may sound like a lot of detail for something like a volume control, it is not even close to enough resolution to for instance set the &#039;&#039;bowing speed&#039;&#039;. Imagine that our lowest possible note frequency is 50 Hz, that means that with a 0-127 range we can only go from 50 Hz to 127 + 50 = 177 Hz - and with no decimals! This meager range and the very coarse steps of only 1 Hz would mean the instrument would never be able to sound in tune and wouldn&#039;t even have two octaves of range. The idea of limiting the Ekdahl FAR to what is possible through &#039;&#039;MIDI&#039;&#039; seemed like a poor choice thus it was decided that &amp;lt;u&amp;gt;most&amp;lt;/u&amp;gt; parameters will instead be 16-bit.&lt;br /&gt;
&lt;br /&gt;
Now lets look at a more complex example, the &amp;lt;u&amp;gt;default&amp;lt;/u&amp;gt; &#039;&#039;Note On MIDI message&#039;&#039;. On a stock Ekdahl FAR, executing&amp;lt;pre&amp;gt;&lt;br /&gt;
rqi:mev:noteon&lt;br /&gt;
&amp;lt;/pre&amp;gt;Will return something like&amp;lt;pre&amp;gt;[irq]mev:noteon:&#039;m:0,b:0,bchb:note,bmr:1,bpid:1,bpe:1,se:(velocity*512)*(1-notecount),bcsm:0&#039;&amp;lt;/pre&amp;gt;As can be seen, there&#039;s a lot of stuff going on here! First of all, notice that everything after &#039;&#039;mev:noteon:&#039;&#039; is situated in between single quotes (&#039;) - this is &amp;lt;u&amp;gt;absolutely crucial&amp;lt;/u&amp;gt; for the Ekdahl FAR to know that everything within those last two quotes is part of the last &#039;&#039;parameter&#039;&#039; of the &#039;&#039;mev&#039;&#039;-command.&lt;br /&gt;
&lt;br /&gt;
Now let&#039;s break down what happens when this &#039;&#039;MIDI message&#039;&#039; is received, i.e. when a &#039;&#039;MIDI&#039;&#039; key is pressed down:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;m:0&#039;&#039; - Sets &#039;&#039;module&#039;&#039; to 0&lt;br /&gt;
# &#039;&#039;b:0&#039;&#039; - Sets &#039;&#039;bow&#039;&#039; to 0&lt;br /&gt;
# &#039;&#039;bchb:note&#039;&#039; - Invokes the &#039;&#039;bowcontrolharmonicbase-&#039;&#039;command with the first &#039;&#039;parameter&#039;&#039; set to the &#039;&#039;variable note&#039;&#039;. &lt;br /&gt;
# &#039;&#039;bmr:1&#039;&#039; - Sets the &#039;&#039;bowmotorrun&#039;&#039;-command to &#039;1&#039;, starting the &#039;&#039;bow motor&#039;&#039;&lt;br /&gt;
# &#039;&#039;bpid:1&#039;&#039; - Sets the &#039;&#039;bowpid&#039;&#039;-command to &#039;1&#039;, making sure the &#039;&#039;PID&#039;&#039; is used&lt;br /&gt;
# &#039;&#039;bpe:1&#039;&#039; - Sets the &#039;&#039;bowpressureengage&#039;&#039; to &#039;1&#039; which moves the &#039;&#039;bowing jack&#039;&#039; to the &#039;&#039;engage position&#039;&#039;&lt;br /&gt;
# &#039;&#039;se:(velocity*512)*(1-notecount)&#039;&#039; - Executes the &#039;&#039;solenoidengage&#039;&#039;-command with the value &#039;&#039;(velocity*512)*(1-notecount)&#039;&#039;&lt;br /&gt;
# &#039;&#039;bcsm:0&#039;&#039; - Sets the &#039;&#039;bowcontrolspeedmode&#039;&#039; to &#039;1&#039; which enables automatic shut down of the &#039;&#039;bowing motor&#039;&#039;&lt;br /&gt;
The first two &#039;&#039;commands&#039;&#039; are the &#039;&#039;module&#039;&#039;- and &#039;&#039;bow-&#039;&#039;command. These &#039;&#039;commands&#039;&#039; are is intended for future versions of the Ekdahl FAR that may contain more than one string or more than one bow per string. For now &#039;&#039;0&#039;&#039; is the only valid &#039;&#039;parameter&#039;&#039; value that will be accepted for either &#039;&#039;command&#039;&#039;.&#039;&#039;&amp;lt;nowiki/&amp;gt;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;bowcontrolharmonicbase&#039;&#039;-command sets the speed of the &#039;&#039;bowing wheel&#039;&#039; to its corresponding &#039;&#039;harmonic number&#039;&#039; but also takes into account its &#039;&#039;&amp;lt;nowiki/&amp;gt;&#039;base&#039;&#039;&#039; which is the &#039;&#039;MIDI key&#039;&#039; that is mapped to &#039;&#039;harmonic number 0&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
After this the bowing motor is started and the &#039;&#039;PID&#039;&#039; is turned, now the instrument will try and make sure that the &#039;&#039;bowing wheel&#039;&#039; is at the right speed.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;bowing jack&#039;&#039; is raised to the &#039;&#039;engage position&#039;&#039;, any added &#039;&#039;pressure modifiers&#039;&#039; will also be taken into account - once the &#039;&#039;bowing jack&#039;&#039; has reached its intended position the &#039;&#039;bowing wheel&#039;&#039; should (hopefully) make contact with the string and the Ekdahl FAR will start to produce sounds.&lt;br /&gt;
&lt;br /&gt;
After this we have the &#039;&#039;solenoidengage&#039;&#039;-command &#039;&#039;command&#039;&#039; that engages the &#039;&#039;hammer&#039;&#039; and uses the first and only &#039;&#039;parameter&#039;&#039; as the force used. Like with most &#039;&#039;commands&#039;&#039; the &#039;&#039;se&#039;&#039;-command is 16-bit (0 - 65535) but the &#039;&#039;MIDI velocity variable&#039;&#039; is 7-bit (0 - 127), so to get the &#039;&#039;velocity&#039;&#039; variable to cover the entire range it needs to be multiplied with 512. &lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&amp;lt;nowiki/&amp;gt;&#039;*(1-notecount)&#039;&#039;&#039;-part is a way of making sure that we are using &#039;&#039;legato&#039;&#039; mode, i.e. that the &#039;&#039;hammer&#039;&#039; is not triggered if a key is already held down when a new key is pressed. The &#039;&#039;notecount&#039;&#039;-variable contains the number of &#039;&#039;MIDI&#039;&#039; notes currently held down. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s postulate that the Ekdahl FAR is tuned to a &#039;C&#039; at 65.4Hz and has its &#039;&#039;base&#039;&#039; set to middle &#039;C&#039; (&#039;&#039;MIDI key&#039;&#039; no 36). We are using the equal-temperament 12-tone scale and the Ekdahl FAR is set to respond to &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; &#039;&#039;MIDI channels&#039;&#039; (omni). Without having previously held any keys we press the middle &#039;C&#039; (&#039;&#039;note&#039;&#039; value 36) as hard as possible (&#039;&#039;velocity&#039;&#039; value &#039;&#039;127&#039;&#039;) on &#039;&#039;MIDI channel&#039;&#039; number 1 (&#039;&#039;channel&#039;&#039; value of 0). The Ekdahl FAR will get a &#039;&#039;note on MIDI message&#039;&#039; sent to it and from our mapping it will create the following &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;[irq]mev:noteon:&#039;m:0,b:0,bchb:36,bmr:1,bpid:1,bpe:1,se:(127*512)*(1-0),bcsm:0&#039;&amp;lt;/pre&amp;gt;What has happened here is that all &#039;&#039;variables&#039;&#039; have been replaced with the values sent by the &#039;&#039;MIDI message&#039;&#039;. Since those &#039;&#039;commands&#039;&#039; that doesn&#039;t have any &#039;&#039;variables&#039;&#039; with them will execute just as previously, only those &#039;&#039;commands&#039;&#039; whos &#039;&#039;parameters&#039;&#039; have changed will be explained:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;bchb: 36&#039;&#039; - The &#039;&#039;bowcontrolharmonicbase&#039;&#039; gets a value of &#039;&#039;36&#039;&#039; (middle &#039;C&#039;), because &#039;&#039;harmonic number 0&#039;&#039; is mapped to this key it will set the &#039;&#039;bowing wheel&#039;&#039; frequency to the &#039;&#039;fundamental&#039;&#039;; &#039;&#039;65.4&#039;&#039; Hertz&lt;br /&gt;
# &#039;&#039;se: (127*512)*(1-0)&#039;&#039; - the value of &#039;&#039;127&#039;&#039; comes from the &#039;&#039;velocity&#039;&#039;-variable, &#039;&#039;127 * 512 = 65024&#039;&#039; which is awfully close to a maximum hammer force of 65535. Since no previous notes were held down &#039;&#039;notecount&#039;&#039;  is equal to &#039;&#039;0&#039;&#039; and thus &#039;&#039;65024 * 1 = 65024&#039;&#039;. The hammer is engaged with near maximum force.&lt;br /&gt;
So the result is that we have set the speed of the &#039;&#039;bowing motor&#039;&#039; and we have engaged the &#039;&#039;hammer&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Now imagine that without releasing this key, we press another &#039;C&#039; one octave above but at half the velocity. The Ekdahl FAR creates the following &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
[irq]mev:noteon:&#039;m:0,b:0,bchb:48,bmr:1,bpid:1,bpe:1,se:(63*512)*(1-1),bcsm:0&#039;&lt;br /&gt;
&amp;lt;/pre&amp;gt;Now we can see that the &#039;&#039;note&#039;&#039; variable is &#039;&#039;48&#039;&#039; because the &#039;C&#039; one octave up is exactly 12 keys above the first, the &#039;&#039;velocity&#039;&#039; variable has changed to &#039;&#039;63&#039;&#039; since we hit it with a lighter touch - and because we are &amp;lt;u&amp;gt;still holding the first key down&amp;lt;/u&amp;gt; &#039;&#039;notecount&#039;&#039; is equal to &#039;&#039;1&#039;&#039;. Here&#039;s what happens&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;bchb: 48&#039;&#039; - Due to the &#039;&#039;base&#039;&#039; being set to &#039;&#039;36&#039;&#039; the &#039;&#039;harmonic number&#039;&#039; is set to &#039;&#039;48 - 36 = 12&#039;&#039;. Because we are using a 12-tone scale &#039;&#039;harmonic number 12&#039;&#039; is exactly one octave above the &#039;&#039;fundamental&#039;&#039; thus the speed of the &#039;&#039;bowing wheel&#039;&#039; is set to &#039;&#039;65.4 * 2 = 130.8&#039;&#039; Hertz.&lt;br /&gt;
# &#039;&#039;se: (63*512)*(1-1)&#039;&#039; - So &#039;&#039;63 * 512 = 32256&#039;&#039; and &#039;&#039;1 - 1 = 0&#039;&#039; thus &#039;&#039;32256 * 0 = 0&#039;&#039;. When the &#039;&#039;solenoidengage&#039;&#039;-command gets a &#039;&#039;parameter&#039;&#039; of &#039;&#039;0&#039;&#039; it will not engage the &#039;&#039;hammer&#039;&#039; - so the &#039;&#039;hammer&#039;&#039; doesn&#039;t strike&lt;br /&gt;
So it can be seen that with quite rudimentary math we can accomplish a whole lot of things here. Note also that even though the &#039;&#039;note on MIDI message&#039;&#039; also sets the &#039;&#039;channel&#039;&#039;-variable we never use it in this example - plenty of opportunity to make something weird happen depending on the &#039;&#039;MIDI channel&#039;&#039;!&lt;br /&gt;
&lt;br /&gt;
== CV Mapping ==&lt;br /&gt;
&#039;&#039;CV Mapping&#039;&#039; works exactly like the &#039;&#039;MIDI mapping&#039;&#039; with the difference that the command for setting the &#039;&#039;CV mapping&#039;&#039; is different and that &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; events pertaining to this &amp;lt;u&amp;gt;only&amp;lt;/u&amp;gt; change the &#039;&#039;value&#039;&#039;-variable. The &#039;&#039;command&#039;&#039; for changing the &#039;&#039;CV mapping&#039;&#039; is &#039;&#039;adccommandmap&#039;&#039; or &#039;&#039;acm&#039;&#039;, it take two &#039;&#039;parameters&#039;&#039;; &#039;&#039;channel&#039;&#039; and &#039;&#039;command string&#039;&#039;. We retrieve the &#039;&#039;command string&#039;&#039; for channel &#039;&#039;0&#039;&#039; which reads the sum of the &#039;&#039;harm. v/oct&#039;&#039;-jack and the &#039;&#039;harmonic&#039;&#039;-knob by sending a command of&amp;lt;pre&amp;gt;&lt;br /&gt;
rqi:acm:0&lt;br /&gt;
&amp;lt;/pre&amp;gt;The &amp;lt;u&amp;gt;default&amp;lt;/u&amp;gt; response will be something like&lt;br /&gt;
&amp;lt;pre&amp;gt;[irq]acm:0:&#039;bcha:value/1327.716667-20&#039;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{docnav&lt;br /&gt;
|[[The Ekdahl FAR - Service|Service]]&lt;br /&gt;
|[[The Ekdahl FAR - Command reference|Command reference]]&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Knaadmin</name></author>
	</entry>
	<entry>
		<id>http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_language&amp;diff=1649</id>
		<title>The Ekdahl FAR - Command language</title>
		<link rel="alternate" type="text/html" href="http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_language&amp;diff=1649"/>
		<updated>2026-06-08T14:16:14Z</updated>

		<summary type="html">&lt;p&gt;Knaadmin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Command language ==&lt;br /&gt;
The Ekdahl FAR is entirely controlled by &#039;&#039;commands&#039;&#039;, these &#039;&#039;commands&#039;&#039; decide everything that the instrument is doing, whether it is playing a melody or changing an internal parameter. &lt;br /&gt;
&lt;br /&gt;
When a &#039;&#039;MIDI message&#039;&#039; is received or a new CV / knob value is read, the &#039;&#039;commands&#039;&#039; associated with it will be internally sent. This can be things like &amp;quot;engage hammer&amp;quot; or &amp;quot;set the fundamental frequency&amp;quot; etc. &lt;br /&gt;
&lt;br /&gt;
Some of the available &#039;&#039;commands&#039;&#039; are mainly used for calibrating and setting up the instrument and are usually saved into the instruments memory, these will be executed whenever the instrument is turned on. &lt;br /&gt;
&lt;br /&gt;
All &#039;&#039;commands&#039;&#039; can be manually invoked via &#039;&#039;USB-Serial&#039;&#039;, in conjunction with certain software this presents an unprecedented level of control and sequenceability.&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
The &#039;&#039;commands&#039;&#039; are invoked using a &#039;&#039;plain text approach&#039;&#039;, all commands have both a &#039;&#039;long name&#039;&#039; and a &#039;&#039;short name&#039;&#039; which are interchangeable. A &#039;&#039;command&#039;&#039; may have one or more &#039;&#039;parameters&#039;&#039; associated with it, these &#039;&#039;parameters&#039;&#039; can be of different types; 16-bit numbers (values 0 - 65535 or -32767 - 32767), floating point numbers (values with decimals), booleans (0 for &#039;false&#039;, 1 for &#039;true&#039;) and strings (text). Some commands are &#039;&#039;conditional&#039;&#039;, meaning they will only execute if a parameter equates to &#039;1&#039; (&#039;true&#039;). &lt;br /&gt;
&lt;br /&gt;
The way &#039;&#039;commands&#039;&#039; are written in order to be executed is &#039;&#039;commandname:parameter1:parameter2:parameter3 [etc]&#039;&#039;, several commands be executed in sequence by separating them with a comma (&#039;,&#039;), a bunch of commands strung together is called a &#039;&#039;command string&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Since version 1.1 of the Ekdahl FAR Firmware, all commands are grouped in a hierarchical fashion according to their &#039;&#039;modules&#039;&#039; and each ladder in the hierarchy is separated by a period (&amp;quot;.&amp;quot;), this works very much like folders or directories in a regular computer. Every &#039;&#039;module&#039;&#039; can contain both &#039;&#039;commands&#039;&#039; and other &#039;&#039;modules&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
For instance, everything associated with the &#039;&#039;bowing wheel&#039;&#039; is now collected under &amp;quot;bowingwheel&amp;quot; &#039;&#039;module&#039;&#039;. That in turn contains a &amp;quot;dcmotor&amp;quot; &#039;&#039;module&#039;&#039; which does direct control of the bowing motor, and it has a &amp;quot;pid&amp;quot; &#039;&#039;module&#039;&#039; that handles bow frequency.&lt;br /&gt;
&lt;br /&gt;
If for instance we would like to start the &#039;&#039;bowing wheel&#039;&#039; and set its frequency to 82.5 Hertz we could send the Ekdahl FAR the following &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
bowmotorrun:1, bowcontrolfrequecy:82.5&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bowingwheel.dcmotor.run:1, bowingwheel.pid.targetfrequency:82.5&amp;lt;/pre&amp;gt;We could also use the &#039;&#039;short names&#039;&#039; for the commands&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
bmr:1,bcf:82.5&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bw.dcm.ru:1, bw.pid.tf:82.5&amp;lt;/pre&amp;gt;Both &#039;&#039;bowmotorrun&#039;&#039; / &#039;&#039;bowingwheel.dcmotor.run&#039;&#039; and &#039;&#039;bowcontrolfrequency / bowingwheel.pid.targetfrequency&#039;&#039; takes one &#039;&#039;parameter&#039;&#039; each, &#039;&#039;bowmotorrun / bowingwheel.dcmotor.run&#039;&#039; is &#039;&#039;conditional&#039;&#039; and unless the first &#039;&#039;parameter&#039;&#039; is equal to &#039;1&#039; the motor will not start. The first &#039;&#039;parameter&#039;&#039; of &#039;&#039;bowcontrolfrequency / bowingwheel.pid.targetfrequency&#039;&#039; sets the frequency of the &#039;&#039;bowing wheel&#039;&#039;, the instrument may not execute a &#039;&#039;command&#039;&#039; if it decides that the given &#039;&#039;parameters&#039;&#039; are outside of the working range or they are missing.&lt;br /&gt;
&lt;br /&gt;
The addition of the hierarchy in the FAR 1.1 firmware isn&#039;t just to be able to group commands, but it&#039;s also to make the FAR not limited to a single set of &#039;&#039;modules&#039;&#039; (and is the first stepping stone to a &#039;&#039;modular&#039;&#039; Ekdahl FAR). In fact, you could have 12 different bowing wheel &#039;&#039;modules&#039;&#039; for 12 different strings, these would then be addressed as &#039;&#039;bowingwheel[0].command, bowingwheel[1].command&#039;&#039; etc. Anyone familiar with C programming notices that this is the standard way of &#039;&#039;indexing&#039;&#039; an array; using brackets (&amp;quot;[ ]&amp;quot;). When addressing a module without &#039;&#039;indexing&#039;&#039; as above, the FAR will do one or two things; either use the first object (&amp;quot;[0]&amp;quot;) or, if the object is &#039;&#039;selectable&#039;&#039; it will use the previously selected object. To make things smoother a command can be executed on several objects at once by using ranges (&amp;quot;[0-4]&amp;quot;) and comma separation (&amp;quot;[0, 3, 5-6]&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
To test out a &#039;&#039;command&#039;&#039; you can send it directly to the Ekdahl FAR using the &#039;&#039;Console&#039;&#039; in the &#039;&#039;Configuration utility&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
To read up on existing &#039;&#039;commands&#039;&#039;, their &#039;&#039;parameters&#039;&#039; and a brief description you can check the &#039;&#039;Command reference&#039;&#039; in the &#039;&#039;Configuration utility&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Variables, functions and equations ==&lt;br /&gt;
What makes the &#039;&#039;Command language&#039;&#039; truly powerful is the concept of &#039;&#039;variables, functions&#039;&#039; and &#039;&#039;equations&#039;&#039;. All &#039;&#039;parameters&#039;&#039; that take numerical values can use any combination of &#039;&#039;variables, functions&#039;&#039; or &#039;&#039;equations.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
For instance, we can use the previous example and instead write our &#039;&#039;command string&#039;&#039; as follows&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
bowmotorrun:1, bowcontrolfrequency:82.5+note*20&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bowingwheel.dcmotor.run:1, bowingwheel.pid.targetfrequency:82.5+note*20&amp;lt;/pre&amp;gt;This example requires of course that the &#039;&#039;variable&#039;&#039; &#039;&#039;note&#039;&#039; exists in the current context. &lt;br /&gt;
&lt;br /&gt;
===== Variables =====&lt;br /&gt;
There are two types of &#039;&#039;variables&#039;&#039; in the Ekdahl FAR; &#039;&#039;global variables&#039;&#039; and &#039;&#039;event variables&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Global variables&#039;&#039; are variables that are always available and will exist in any context. The &#039;&#039;global variables&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;notecount&#039;&#039;&#039; - Contains the number of &#039;&#039;MIDI&#039;&#039; keys that are being held down, i.e. all &#039;&#039;Note on messages&#039;&#039; received that haven&#039;t gotten a paired &#039;&#039;Note off message&#039;&#039; yet&lt;br /&gt;
* &#039;&#039;&#039;uv0&#039;&#039;&#039; - &#039;&#039;&#039;uv9&#039;&#039;&#039; - These are &#039;&#039;user variables&#039;&#039; and can be set at any point using the &#039;&#039;globaluservariable command&#039;&#039; with the first &#039;&#039;parameter&#039;&#039; being which variable to set (0-9) and the second &#039;&#039;parameter&#039;&#039; being the value (float).&lt;br /&gt;
* &#039;&#039;&#039;e&#039;&#039;&#039; - Contains the constant &#039;&#039;[[wikipedia:E_(mathematical_constant)|e]]&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pi&#039;&#039;&#039; - Contains the constant &#039;&#039;[[wikipedia:Pi|pi]]&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Event variables&#039;&#039; are variables that are set by certain &#039;&#039;MIDI messages&#039;&#039; or when a new value is read on one of the jacks or knobs on the &#039;&#039;Control box&#039;&#039;. The &#039;&#039;Event variables&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;channel&#039;&#039;&#039; - Set by the &#039;&#039;Note on, Note off, Continuous Controller, Poly after touch, Pitch bend, Channel after touch&#039;&#039; and &#039;&#039;Program change MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;note&#039;&#039;&#039; - Set by the &#039;&#039;Note on, Note off&#039;&#039; and &#039;&#039;Poly after touch MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;velocity&#039;&#039;&#039; - Set by the &#039;&#039;Note on&#039;&#039; and &#039;&#039;Note off MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pressure&#039;&#039;&#039; - Set by the &#039;&#039;Poly after touch&#039;&#039; and &#039;&#039;Channel after touch MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; - Set by the &#039;&#039;Continuous Controller MIDI message&#039;&#039; and by the &#039;&#039;Control box&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pitch&#039;&#039;&#039; - Set by the &#039;&#039;Pitch bend MIDI message&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;program&#039;&#039;&#039; - Set by the &#039;&#039;Program change MIDI message&#039;&#039;&lt;br /&gt;
These variables will contain whatever data is relevant to the &amp;lt;u&amp;gt;last midi message sent&amp;lt;/u&amp;gt; and will not stay relevant beyond the reception of the last message.&lt;br /&gt;
&lt;br /&gt;
===== Functions =====&lt;br /&gt;
&#039;&#039;Functions&#039;&#039; can be used to change a numerical value or the result of an &#039;&#039;equation&#039;&#039;, the Ekdahl FAR contains both general &#039;&#039;arithmetic functions&#039;&#039; (courtesy of Lewis Van Winkle and the TINYEXPR engine) and &#039;&#039;specialized functions&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;arithmetic functions&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;abs&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Absolute_value|absolute value]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;acos&#039;&#039;&#039;(x), &#039;&#039;&#039;asin&#039;&#039;&#039;(x), &#039;&#039;&#039;atan&#039;&#039;&#039;(x), atan2(x, y) - Returns the [[wikipedia:Inverse_trigonometric_functions|&#039;&#039;arc-cos, -sin, -tan&#039;&#039; and &#039;&#039;-tan2&#039;&#039;]] of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;atan2&#039;&#039;&#039;(x,y) - Returns the &#039;&#039;[[wikipedia:Atan2|arctan2]]&#039;&#039; of &#039;&#039;x, y&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;floor&#039;&#039;&#039;(x), ceil(x) - Returns the [[wikipedia:Floor_and_ceiling_functions|&#039;&#039;floor&#039;&#039; and &#039;&#039;ceiling&#039;&#039;]] of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;exp&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Exponential_function|exponent]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;fac&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Factorial|factorial]]&#039;&#039; of x&lt;br /&gt;
* &#039;&#039;&#039;ln&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Natural_logarithm|natural logarithm]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;log10&#039;&#039;&#039;(x), &#039;&#039;&#039;log20&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Logarithm|logarithm]]&#039;&#039; of &#039;&#039;x&#039;&#039; using base 10 and 20 respectively&lt;br /&gt;
* &#039;&#039;&#039;ncr&#039;&#039;&#039;(x,y), &#039;&#039;&#039;npr&#039;&#039;&#039;(x,y) - Functions to calculate &#039;&#039;[[wikipedia:Combination|combinations]]&#039;&#039; and &#039;&#039;[[wikipedia:Permutation|permutations]]&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pow&#039;&#039;&#039;(x,y) - Returns &#039;&#039;x^y&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;sqrt&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Square_root|square root]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;cos&#039;&#039;&#039;(x), &#039;&#039;&#039;sin&#039;&#039;&#039;(x), &#039;&#039;&#039;tan&#039;&#039;&#039;(x) - Returns the [[wikipedia:Trigonometric_functions|&#039;&#039;cos, sin&#039;&#039; and &#039;&#039;tan&#039;&#039;]] of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;cosh&#039;&#039;&#039;(x), &#039;&#039;&#039;sinh&#039;&#039;&#039;(x), &#039;&#039;&#039;tanh&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Hyperbolic_functions|hyperbolic cos, sin and tan]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
The &#039;&#039;specialized functions&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;bool&#039;&#039;&#039;(x) - Returns 1 if &#039;&#039;x&#039;&#039; is more than 0&lt;br /&gt;
* &#039;&#039;&#039;ibool&#039;&#039;&#039;(x) - Returns 0 if &#039;&#039;x&#039;&#039; is more than 0&lt;br /&gt;
* &#039;&#039;&#039;deadband&#039;&#039;&#039;(x,y) - Returns &#039;&#039;x + y &#039;&#039; if &#039;&#039;x &amp;lt; y&#039;&#039; or &#039;&#039;x - y&#039;&#039; if &#039;&#039;x &amp;gt; y&#039;&#039;. If neither of these statements is true it returns &#039;&#039;0&#039;&#039; - used to create a [[wikipedia:Deadband|deadband]] of &#039;&#039;x&#039;&#039; with the threshold of &#039;&#039;y&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Functions&#039;&#039; can be readily used in a &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
bowmotorrun:1, bowcontrolfrequency:&amp;quot;8.17579875 * pow(2, (1/12 * note))&amp;quot;&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bowingwheel.dcmotor.run:1, bowingwheel.pid.targetfrequency:&amp;quot;8.17579875 * pow(2, (1/12 * note))&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;The previous statements starts the &#039;&#039;bowing wheel&#039;&#039; and sets the frequency of the wheel to &#039;&#039;8.17579875 * 2^(1/12 * note)&#039;&#039;. A middle &#039;C&#039; according to &#039;&#039;MIDI&#039;&#039; has a &#039;&#039;note value&#039;&#039; of 36, meaning if we substitute &#039;&#039;note&#039;&#039; with 36 we get the equation &#039;&#039;8.17579875 * 2^(1/12 * 36)&#039;&#039; which comes out to &#039;&#039;~65.4&#039;&#039; Hertz.&lt;br /&gt;
&lt;br /&gt;
Note that the first &#039;&#039;parameter&#039;&#039; for &#039;&#039;bowcontrolfrequency / bowingwheel.pid.targetfrequency&#039;&#039; is put in between double quotes (&amp;quot;). This is because the &#039;&#039;pow&#039;&#039;-function requires the use of a comma (&amp;quot;,&amp;quot;) in order to separate in between its two required inputs; &#039;&#039;x&#039;&#039; and &#039;&#039;y&#039;&#039;. In order for the Ekdahl FAR to know that this comma does not signal the beginning of a new &#039;&#039;command,&#039;&#039; we use quotes. Single (&#039;) and double (&amp;quot;) quotes can be used and nested in all &#039;&#039;parameters&#039;&#039; and are &amp;lt;u&amp;gt;required&amp;lt;/u&amp;gt; in a lot of circumstances, improper nesting or not using quotes can lead to the instrument not understanding the &#039;&#039;command string&#039;&#039; correctly.&lt;br /&gt;
&lt;br /&gt;
== Return messages ==&lt;br /&gt;
The Ekdahl FAR when connected via &#039;&#039;USB-Serial&#039;&#039; doesn&#039;t only accept &#039;&#039;commands&#039;&#039; but will also send various &#039;&#039;return messages&#039;&#039;. These are prefixed by their &#039;&#039;category&#039;&#039; denoted in brackets (&amp;quot;[]&amp;quot;), the existing categories as of this writing (2025-01-22) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;command&#039;&#039;&#039; / &#039;&#039;&#039;cmd&#039;&#039;&#039; - Acknowledges the reception of a command in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;usb&#039;&#039;&#039; - Acknowledges the reception of a &#039;&#039;MIDI message&#039;&#039; over &#039;&#039;USB&#039;&#039; in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;hardware&#039;&#039;&#039; / &#039;&#039;&#039;hw&#039;&#039;&#039; - Signals that a change has been sent to the Ekdahl FAR hardware, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;undefined&#039;&#039;&#039; / &#039;&#039;&#039;un&#039;&#039;&#039; - The message sent is in the &#039;&#039;undefined&#039;&#039; category, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;priority&#039;&#039;&#039; / &#039;&#039;&#039;pri&#039;&#039;&#039; - The message sent is in the &#039;&#039;priority&#039;&#039; category, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;error&#039;&#039;&#039; / &#039;&#039;&#039;err&#039;&#039;&#039; - Signals that an &#039;&#039;error&#039;&#039; has occurred, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;expressionparser&#039;&#039;&#039; / &#039;&#039;&#039;ep&#039;&#039;&#039; - These messages contains debugging information regarding the internal &#039;&#039;expression parser&#039;&#039; and is used for development&lt;br /&gt;
*&#039;&#039;&#039;debug&#039;&#039;&#039; / &#039;&#039;&#039;dbg&#039;&#039;&#039; - These messages contains various debugging information and is used for development&lt;br /&gt;
*&#039;&#039;&#039;help&#039;&#039;&#039; / &#039;&#039;&#039;hlp&#039;&#039;&#039; - Signals that the message is a response to a &#039;&#039;help&#039;&#039;-command being sent to the Ekdahl FAR. These messages are structured so that a receiver, like the &#039;&#039;Configuration utility&#039;&#039;, can parse information about available &#039;&#039;commands&#039;&#039; in the current &#039;&#039;firmware&#039;&#039; and relay it to a user in a structured way.&lt;br /&gt;
* &#039;&#039;&#039;inforequest&#039;&#039;&#039; / &#039;&#039;&#039;irq&#039;&#039;&#039; - Signals that an &#039;&#039;info request&#039;&#039; has been returned. This is a specialized message that is either sent as a response to an &#039;&#039;rqi&#039;&#039;-command or as a &#039;&#039;interrupt&#039;&#039;-message telling the user or receiving software about different parameters in the Ekdahl FAR. These messages follows the same structure as regular &#039;&#039;command message&#039;&#039;s of &#039;&#039;[irq]commandname:parameter1 [etc]&#039;&#039; so that it can be used by a receiving software to keep track of parameter changes&lt;br /&gt;
&lt;br /&gt;
===== Explicitly requesting information =====&lt;br /&gt;
By using the special command &#039;&#039;requestinfo / rqi&#039;&#039; one can request the information stored by a certain &#039;&#039;command&#039;&#039; or a state of the Ekdahl FAR. The &#039;&#039;rqi&#039;&#039;-command is executed in the convention &#039;&#039;rqi:commandname[:optional parameters]&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
To go back to our example of setting the bowing frequency using the &#039;&#039;bowcontrolfrequency&#039;&#039;-command we can ask the Ekdahl FAR what the bowing frequency is set to by writing&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
rqi:bowcontrolfrequency&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
rqi:bowingwheel.pid.targetfrequency&lt;br /&gt;
&amp;lt;/pre&amp;gt;The return value would be something like&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
[irq]bcf:82.5&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
[irq]bw[0].pid[0].tf:82.5&lt;br /&gt;
&amp;lt;/pre&amp;gt;Where &#039;[irq]&#039; denotes that the message returned is in the &#039;&#039;info request-&#039;&#039;category, that it pertains to the command &#039;&#039;bcf&#039;&#039; / &#039;&#039;bw.pid.tf&#039;&#039; and has the value &#039;&#039;82.5&#039;&#039;. Note that the returned &#039;&#039;command&#039;&#039; sent by an &#039;&#039;rqi&#039;&#039;-command always uses the &#039;&#039;short name&#039;&#039; in order to preserve bandwidth. In the FAR 1.1 the return statement always returns the &#039;&#039;index&#039;&#039; of the &#039;&#039;module&#039;&#039;(s) in question.&lt;br /&gt;
&lt;br /&gt;
Most commands do not require any &#039;&#039;parameters&#039;&#039; when using the &#039;&#039;rqi&#039;&#039;-command. The &#039;&#039;adcread&#039;&#039; / &#039;&#039;datareturn&#039;&#039;-command is an example of a &#039;&#039;command&#039;&#039; that &amp;lt;u&amp;gt;does&amp;lt;/u&amp;gt; require a &#039;&#039;parameter&#039;&#039; when used with &#039;&#039;rqi&#039;&#039;. The &#039;&#039;adcread / datareturn-&#039;&#039;command returns the last value read by the &#039;&#039;analog-to-digital converter&#039;&#039; in the &#039;&#039;Control box&#039;&#039;, because there are 8 different channels the first &#039;&#039;parameter&#039;&#039; sets which channel to return the data for, hence executing the &#039;&#039;command&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
rqi:adcr:3&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
rqi:controlbox.datareturn:3&lt;br /&gt;
&amp;lt;/pre&amp;gt;will return the last data read on &#039;&#039;analog-to-digital convert&#039;&#039; channel 3.&lt;br /&gt;
&lt;br /&gt;
== MIDI mapping ==&lt;br /&gt;
To change how a certain &#039;&#039;MIDI message&#039;&#039; interacts with the Ekdahl FAR we need to change the &#039;&#039;commands&#039;&#039; or &#039;&#039;parameters&#039;&#039; sent when the message is received. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;FAR &amp;lt; 1.1:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
The &#039;&#039;command&#039;&#039; responsible for mapping &#039;&#039;command strings&#039;&#039; to different &#039;&#039;MIDI messages&#039;&#039; is &#039;&#039;midieventhandler&#039;&#039; or &#039;&#039;mev&#039;&#039; for short. The first &#039;&#039;parameter&#039;&#039; of &#039;&#039;mev&#039;&#039; is the type of &#039;&#039;MIDI message&#039;&#039; that we want to remap&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;&#039;&#039;noteon&#039;&#039;&#039;&#039;&#039; - Note on&lt;br /&gt;
* &#039;&#039;&#039;&#039;&#039;noteoff&#039;&#039;&#039; -&#039;&#039; Note off&lt;br /&gt;
* &#039;&#039;&#039;&#039;&#039;pat&#039;&#039;&#039; -&#039;&#039; Poly after touch&lt;br /&gt;
* &#039;&#039;&#039;&#039;&#039;cat&#039;&#039;&#039;&#039;&#039; - Channel after touch&lt;br /&gt;
* &#039;&#039;&#039;&#039;&#039;pb&#039;&#039;&#039;&#039;&#039; - Pitch bend&lt;br /&gt;
* &#039;&#039;&#039;&#039;&#039;pc&#039;&#039;&#039;&#039;&#039; - Program change&lt;br /&gt;
* &#039;&#039;&#039;&#039;&#039;cc&#039;&#039;&#039;&#039;&#039; - Continuous controller&lt;br /&gt;
&lt;br /&gt;
The second &#039;&#039;parameter&#039;&#039; is the &#039;&#039;command string&#039;&#039; that is to be associated with the &#039;&#039;MIDI Message&#039;&#039; - with the exception of the &#039;&#039;cc&#039;&#039;-type, here the second &#039;&#039;parameter&#039;&#039; is the &#039;&#039;controller number&#039;&#039; (0 - 127) and the &amp;lt;u&amp;gt;third&amp;lt;/u&amp;gt; &#039;&#039;parameter&#039;&#039; is the &#039;&#039;command string&#039;&#039;.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;FAR 1.1:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;commands&#039;&#039; responsible for mapping &#039;&#039;command strings&#039;&#039; to different &#039;&#039;MIDI messages&#039;&#039; are as follows&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;noteon/non&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;&#039;note on&#039;&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;noteoff&#039;&#039;/nof&#039;&#039;&#039;&#039;&#039;&amp;lt;nowiki/&amp;gt;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;&#039;note off MIDI message&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;polyaftertouch/pat&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;&#039;poly aftertouch MIDI message&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;channelaftertouch/cat&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;&#039;channel aftertouch MIDI message&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pitchbend/pb&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;&#039;pitch bend MIDI message&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;programchange/pc&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;&#039;program change MIDI message&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;continuouscontrollerdata/ccd&#039;&#039;&#039;&#039;&#039;:controller:commands&#039;&#039; - Sets the commands executed for &#039;&#039;continuous controller&#039;&#039; no &#039;&#039;controller&#039;&#039;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can of course use the &#039;&#039;rqi&#039;&#039;-command to check the current mapping, below we are asking what the current &#039;&#039;command string&#039;&#039; associated with the &#039;&#039;pitch bend&#039;&#039; &#039;&#039;MIDI message&#039;&#039; is&amp;lt;pre&amp;gt;&lt;br /&gt;
rqi:mev:pb&lt;br /&gt;
&amp;lt;/pre&amp;gt;This may return something like&amp;lt;pre&amp;gt;&lt;br /&gt;
[irq]bchsh:pitch*4&lt;br /&gt;
&amp;lt;/pre&amp;gt;The return message tells us that the &#039;&#039;pitch bend MIDI message&#039;&#039; is executing a &#039;&#039;bchsh&#039;&#039;-command with the parameter &#039;&#039;pitch*4&#039;&#039;. Looking in the &#039;&#039;command reference&#039;&#039; we can see that &#039;&#039;bchsh&#039;&#039; is the &#039;&#039;short name&#039;&#039; of the &#039;&#039;bowcontrolharmonicshift&#039;&#039;-command which shifts the frequency of the &#039;&#039;bowing wheel&#039;&#039; from the current frequency, the first (and only) parameter sets how much we want to shift it (depends on the &#039;&#039;bowcontrolharmonicshiftrange command&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
If we look in the list of &#039;&#039;[[The Ekdahl FAR - Command langue#Variables|variables]]&#039;&#039; above we can see that the &#039;&#039;pitch bend MIDI message&#039;&#039; will set the &#039;&#039;pitch variable&#039;&#039; which is indeed used. Now what is the &#039;&#039;&#039;*4&#039;&#039;&amp;lt;nowiki/&amp;gt;&#039; all about? Well the &#039;&#039;bchsh&#039;&#039;-command expects a &#039;&#039;16-bit signed&#039;&#039; value, meaning that a full &#039;&#039;harmonic shift&#039;&#039; downwards is equal to -32767, a full &#039;&#039;harmonic shift&#039;&#039; upwards is 32767 and no &#039;&#039;harmonic shift&#039;&#039; is 0. The &#039;&#039;pitch bend MIDI message&#039;&#039; however is only 14-bits, meaning its range is -8192 to 8192, so in order to be able to use the entire range we have to multiply &#039;&#039;pitch&#039;&#039; by 4.&lt;br /&gt;
&lt;br /&gt;
This whole thing about number of bits can seem confusing but in the end it&#039;s all about how fine control you have over things; the more possible values, the more detailed control. In fact, most &#039;&#039;MIDI&#039;&#039; values are only 7-bit (!) meaning a range of 0 - 127. While this may sound like a lot of detail for something like a volume control, it is not even close to enough resolution to for instance set the &#039;&#039;bowing speed&#039;&#039;. Imagine that our lowest possible note frequency is 50 Hz, that means that with a 0-127 range we can only go from 50 Hz to 127 + 50 = 177 Hz - and with no decimals! This meager range and the very coarse steps of only 1 Hz would mean the instrument would never be able to sound in tune and wouldn&#039;t even have two octaves of range. The idea of limiting the Ekdahl FAR to what is possible through &#039;&#039;MIDI&#039;&#039; seemed like a poor choice thus it was decided that &amp;lt;u&amp;gt;most&amp;lt;/u&amp;gt; parameters will instead be 16-bit.&lt;br /&gt;
&lt;br /&gt;
Now lets look at a more complex example, the &amp;lt;u&amp;gt;default&amp;lt;/u&amp;gt; &#039;&#039;Note On MIDI message&#039;&#039;. On a stock Ekdahl FAR, executing&amp;lt;pre&amp;gt;&lt;br /&gt;
rqi:mev:noteon&lt;br /&gt;
&amp;lt;/pre&amp;gt;Will return something like&amp;lt;pre&amp;gt;[irq]mev:noteon:&#039;m:0,b:0,bchb:note,bmr:1,bpid:1,bpe:1,se:(velocity*512)*(1-notecount),bcsm:0&#039;&amp;lt;/pre&amp;gt;As can be seen, there&#039;s a lot of stuff going on here! First of all, notice that everything after &#039;&#039;mev:noteon:&#039;&#039; is situated in between single quotes (&#039;) - this is &amp;lt;u&amp;gt;absolutely crucial&amp;lt;/u&amp;gt; for the Ekdahl FAR to know that everything within those last two quotes is part of the last &#039;&#039;parameter&#039;&#039; of the &#039;&#039;mev&#039;&#039;-command.&lt;br /&gt;
&lt;br /&gt;
Now let&#039;s break down what happens when this &#039;&#039;MIDI message&#039;&#039; is received, i.e. when a &#039;&#039;MIDI&#039;&#039; key is pressed down:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;m:0&#039;&#039; - Sets &#039;&#039;module&#039;&#039; to 0&lt;br /&gt;
# &#039;&#039;b:0&#039;&#039; - Sets &#039;&#039;bow&#039;&#039; to 0&lt;br /&gt;
# &#039;&#039;bchb:note&#039;&#039; - Invokes the &#039;&#039;bowcontrolharmonicbase-&#039;&#039;command with the first &#039;&#039;parameter&#039;&#039; set to the &#039;&#039;variable note&#039;&#039;. &lt;br /&gt;
# &#039;&#039;bmr:1&#039;&#039; - Sets the &#039;&#039;bowmotorrun&#039;&#039;-command to &#039;1&#039;, starting the &#039;&#039;bow motor&#039;&#039;&lt;br /&gt;
# &#039;&#039;bpid:1&#039;&#039; - Sets the &#039;&#039;bowpid&#039;&#039;-command to &#039;1&#039;, making sure the &#039;&#039;PID&#039;&#039; is used&lt;br /&gt;
# &#039;&#039;bpe:1&#039;&#039; - Sets the &#039;&#039;bowpressureengage&#039;&#039; to &#039;1&#039; which moves the &#039;&#039;bowing jack&#039;&#039; to the &#039;&#039;engage position&#039;&#039;&lt;br /&gt;
# &#039;&#039;se:(velocity*512)*(1-notecount)&#039;&#039; - Executes the &#039;&#039;solenoidengage&#039;&#039;-command with the value &#039;&#039;(velocity*512)*(1-notecount)&#039;&#039;&lt;br /&gt;
# &#039;&#039;bcsm:0&#039;&#039; - Sets the &#039;&#039;bowcontrolspeedmode&#039;&#039; to &#039;1&#039; which enables automatic shut down of the &#039;&#039;bowing motor&#039;&#039;&lt;br /&gt;
The first two &#039;&#039;commands&#039;&#039; are the &#039;&#039;module&#039;&#039;- and &#039;&#039;bow-&#039;&#039;command. These &#039;&#039;commands&#039;&#039; are is intended for future versions of the Ekdahl FAR that may contain more than one string or more than one bow per string. For now &#039;&#039;0&#039;&#039; is the only valid &#039;&#039;parameter&#039;&#039; value that will be accepted for either &#039;&#039;command&#039;&#039;.&#039;&#039;&amp;lt;nowiki/&amp;gt;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;bowcontrolharmonicbase&#039;&#039;-command sets the speed of the &#039;&#039;bowing wheel&#039;&#039; to its corresponding &#039;&#039;harmonic number&#039;&#039; but also takes into account its &#039;&#039;&amp;lt;nowiki/&amp;gt;&#039;base&#039;&#039;&#039; which is the &#039;&#039;MIDI key&#039;&#039; that is mapped to &#039;&#039;harmonic number 0&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
After this the bowing motor is started and the &#039;&#039;PID&#039;&#039; is turned, now the instrument will try and make sure that the &#039;&#039;bowing wheel&#039;&#039; is at the right speed.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;bowing jack&#039;&#039; is raised to the &#039;&#039;engage position&#039;&#039;, any added &#039;&#039;pressure modifiers&#039;&#039; will also be taken into account - once the &#039;&#039;bowing jack&#039;&#039; has reached its intended position the &#039;&#039;bowing wheel&#039;&#039; should (hopefully) make contact with the string and the Ekdahl FAR will start to produce sounds.&lt;br /&gt;
&lt;br /&gt;
After this we have the &#039;&#039;solenoidengage&#039;&#039;-command &#039;&#039;command&#039;&#039; that engages the &#039;&#039;hammer&#039;&#039; and uses the first and only &#039;&#039;parameter&#039;&#039; as the force used. Like with most &#039;&#039;commands&#039;&#039; the &#039;&#039;se&#039;&#039;-command is 16-bit (0 - 65535) but the &#039;&#039;MIDI velocity variable&#039;&#039; is 7-bit (0 - 127), so to get the &#039;&#039;velocity&#039;&#039; variable to cover the entire range it needs to be multiplied with 512. &lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&amp;lt;nowiki/&amp;gt;&#039;*(1-notecount)&#039;&#039;&#039;-part is a way of making sure that we are using &#039;&#039;legato&#039;&#039; mode, i.e. that the &#039;&#039;hammer&#039;&#039; is not triggered if a key is already held down when a new key is pressed. The &#039;&#039;notecount&#039;&#039;-variable contains the number of &#039;&#039;MIDI&#039;&#039; notes currently held down. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s postulate that the Ekdahl FAR is tuned to a &#039;C&#039; at 65.4Hz and has its &#039;&#039;base&#039;&#039; set to middle &#039;C&#039; (&#039;&#039;MIDI key&#039;&#039; no 36). We are using the equal-temperament 12-tone scale and the Ekdahl FAR is set to respond to &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; &#039;&#039;MIDI channels&#039;&#039; (omni). Without having previously held any keys we press the middle &#039;C&#039; (&#039;&#039;note&#039;&#039; value 36) as hard as possible (&#039;&#039;velocity&#039;&#039; value &#039;&#039;127&#039;&#039;) on &#039;&#039;MIDI channel&#039;&#039; number 1 (&#039;&#039;channel&#039;&#039; value of 0). The Ekdahl FAR will get a &#039;&#039;note on MIDI message&#039;&#039; sent to it and from our mapping it will create the following &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;[irq]mev:noteon:&#039;m:0,b:0,bchb:36,bmr:1,bpid:1,bpe:1,se:(127*512)*(1-0),bcsm:0&#039;&amp;lt;/pre&amp;gt;What has happened here is that all &#039;&#039;variables&#039;&#039; have been replaced with the values sent by the &#039;&#039;MIDI message&#039;&#039;. Since those &#039;&#039;commands&#039;&#039; that doesn&#039;t have any &#039;&#039;variables&#039;&#039; with them will execute just as previously, only those &#039;&#039;commands&#039;&#039; whos &#039;&#039;parameters&#039;&#039; have changed will be explained:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;bchb: 36&#039;&#039; - The &#039;&#039;bowcontrolharmonicbase&#039;&#039; gets a value of &#039;&#039;36&#039;&#039; (middle &#039;C&#039;), because &#039;&#039;harmonic number 0&#039;&#039; is mapped to this key it will set the &#039;&#039;bowing wheel&#039;&#039; frequency to the &#039;&#039;fundamental&#039;&#039;; &#039;&#039;65.4&#039;&#039; Hertz&lt;br /&gt;
# &#039;&#039;se: (127*512)*(1-0)&#039;&#039; - the value of &#039;&#039;127&#039;&#039; comes from the &#039;&#039;velocity&#039;&#039;-variable, &#039;&#039;127 * 512 = 65024&#039;&#039; which is awfully close to a maximum hammer force of 65535. Since no previous notes were held down &#039;&#039;notecount&#039;&#039;  is equal to &#039;&#039;0&#039;&#039; and thus &#039;&#039;65024 * 1 = 65024&#039;&#039;. The hammer is engaged with near maximum force.&lt;br /&gt;
So the result is that we have set the speed of the &#039;&#039;bowing motor&#039;&#039; and we have engaged the &#039;&#039;hammer&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Now imagine that without releasing this key, we press another &#039;C&#039; one octave above but at half the velocity. The Ekdahl FAR creates the following &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
[irq]mev:noteon:&#039;m:0,b:0,bchb:48,bmr:1,bpid:1,bpe:1,se:(63*512)*(1-1),bcsm:0&#039;&lt;br /&gt;
&amp;lt;/pre&amp;gt;Now we can see that the &#039;&#039;note&#039;&#039; variable is &#039;&#039;48&#039;&#039; because the &#039;C&#039; one octave up is exactly 12 keys above the first, the &#039;&#039;velocity&#039;&#039; variable has changed to &#039;&#039;63&#039;&#039; since we hit it with a lighter touch - and because we are &amp;lt;u&amp;gt;still holding the first key down&amp;lt;/u&amp;gt; &#039;&#039;notecount&#039;&#039; is equal to &#039;&#039;1&#039;&#039;. Here&#039;s what happens&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;bchb: 48&#039;&#039; - Due to the &#039;&#039;base&#039;&#039; being set to &#039;&#039;36&#039;&#039; the &#039;&#039;harmonic number&#039;&#039; is set to &#039;&#039;48 - 36 = 12&#039;&#039;. Because we are using a 12-tone scale &#039;&#039;harmonic number 12&#039;&#039; is exactly one octave above the &#039;&#039;fundamental&#039;&#039; thus the speed of the &#039;&#039;bowing wheel&#039;&#039; is set to &#039;&#039;65.4 * 2 = 130.8&#039;&#039; Hertz.&lt;br /&gt;
# &#039;&#039;se: (63*512)*(1-1)&#039;&#039; - So &#039;&#039;63 * 512 = 32256&#039;&#039; and &#039;&#039;1 - 1 = 0&#039;&#039; thus &#039;&#039;32256 * 0 = 0&#039;&#039;. When the &#039;&#039;solenoidengage&#039;&#039;-command gets a &#039;&#039;parameter&#039;&#039; of &#039;&#039;0&#039;&#039; it will not engage the &#039;&#039;hammer&#039;&#039; - so the &#039;&#039;hammer&#039;&#039; doesn&#039;t strike&lt;br /&gt;
So it can be seen that with quite rudimentary math we can accomplish a whole lot of things here. Note also that even though the &#039;&#039;note on MIDI message&#039;&#039; also sets the &#039;&#039;channel&#039;&#039;-variable we never use it in this example - plenty of opportunity to make something weird happen depending on the &#039;&#039;MIDI channel&#039;&#039;!&lt;br /&gt;
&lt;br /&gt;
== CV Mapping ==&lt;br /&gt;
&#039;&#039;CV Mapping&#039;&#039; works exactly like the &#039;&#039;MIDI mapping&#039;&#039; with the difference that the command for setting the &#039;&#039;CV mapping&#039;&#039; is different and that &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; events pertaining to this &amp;lt;u&amp;gt;only&amp;lt;/u&amp;gt; change the &#039;&#039;value&#039;&#039;-variable. The &#039;&#039;command&#039;&#039; for changing the &#039;&#039;CV mapping&#039;&#039; is &#039;&#039;adccommandmap&#039;&#039; or &#039;&#039;acm&#039;&#039;, it take two &#039;&#039;parameters&#039;&#039;; &#039;&#039;channel&#039;&#039; and &#039;&#039;command string&#039;&#039;. We retrieve the &#039;&#039;command string&#039;&#039; for channel &#039;&#039;0&#039;&#039; which reads the sum of the &#039;&#039;harm. v/oct&#039;&#039;-jack and the &#039;&#039;harmonic&#039;&#039;-knob by sending a command of&amp;lt;pre&amp;gt;&lt;br /&gt;
rqi:acm:0&lt;br /&gt;
&amp;lt;/pre&amp;gt;The &amp;lt;u&amp;gt;default&amp;lt;/u&amp;gt; response will be something like&lt;br /&gt;
&amp;lt;pre&amp;gt;[irq]acm:0:&#039;bcha:value/1327.716667-20&#039;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{docnav&lt;br /&gt;
|[[The Ekdahl FAR - Service|Service]]&lt;br /&gt;
|[[The Ekdahl FAR - Command reference|Command reference]]&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Knaadmin</name></author>
	</entry>
	<entry>
		<id>http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_language&amp;diff=1648</id>
		<title>The Ekdahl FAR - Command language</title>
		<link rel="alternate" type="text/html" href="http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_language&amp;diff=1648"/>
		<updated>2026-06-08T14:15:12Z</updated>

		<summary type="html">&lt;p&gt;Knaadmin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Command language ==&lt;br /&gt;
The Ekdahl FAR is entirely controlled by &#039;&#039;commands&#039;&#039;, these &#039;&#039;commands&#039;&#039; decide everything that the instrument is doing, whether it is playing a melody or changing an internal parameter. &lt;br /&gt;
&lt;br /&gt;
When a &#039;&#039;MIDI message&#039;&#039; is received or a new CV / knob value is read, the &#039;&#039;commands&#039;&#039; associated with it will be internally sent. This can be things like &amp;quot;engage hammer&amp;quot; or &amp;quot;set the fundamental frequency&amp;quot; etc. &lt;br /&gt;
&lt;br /&gt;
Some of the available &#039;&#039;commands&#039;&#039; are mainly used for calibrating and setting up the instrument and are usually saved into the instruments memory, these will be executed whenever the instrument is turned on. &lt;br /&gt;
&lt;br /&gt;
All &#039;&#039;commands&#039;&#039; can be manually invoked via &#039;&#039;USB-Serial&#039;&#039;, in conjunction with certain software this presents an unprecedented level of control and sequenceability.&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
The &#039;&#039;commands&#039;&#039; are invoked using a &#039;&#039;plain text approach&#039;&#039;, all commands have both a &#039;&#039;long name&#039;&#039; and a &#039;&#039;short name&#039;&#039; which are interchangeable. A &#039;&#039;command&#039;&#039; may have one or more &#039;&#039;parameters&#039;&#039; associated with it, these &#039;&#039;parameters&#039;&#039; can be of different types; 16-bit numbers (values 0 - 65535 or -32767 - 32767), floating point numbers (values with decimals), booleans (0 for &#039;false&#039;, 1 for &#039;true&#039;) and strings (text). Some commands are &#039;&#039;conditional&#039;&#039;, meaning they will only execute if a parameter equates to &#039;1&#039; (&#039;true&#039;). &lt;br /&gt;
&lt;br /&gt;
The way &#039;&#039;commands&#039;&#039; are written in order to be executed is &#039;&#039;commandname:parameter1:parameter2:parameter3 [etc]&#039;&#039;, several commands be executed in sequence by separating them with a comma (&#039;,&#039;), a bunch of commands strung together is called a &#039;&#039;command string&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Since version 1.1 of the Ekdahl FAR Firmware, all commands are grouped in a hierarchical fashion according to their &#039;&#039;modules&#039;&#039; and each ladder in the hierarchy is separated by a period (&amp;quot;.&amp;quot;), this works very much like folders or directories in a regular computer. Every &#039;&#039;module&#039;&#039; can contain both &#039;&#039;commands&#039;&#039; and other &#039;&#039;modules&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
For instance, everything associated with the &#039;&#039;bowing wheel&#039;&#039; is now collected under &amp;quot;bowingwheel&amp;quot; &#039;&#039;module&#039;&#039;. That in turn contains a &amp;quot;dcmotor&amp;quot; &#039;&#039;module&#039;&#039; which does direct control of the bowing motor, and it has a &amp;quot;pid&amp;quot; &#039;&#039;module&#039;&#039; that handles bow frequency.&lt;br /&gt;
&lt;br /&gt;
If for instance we would like to start the &#039;&#039;bowing wheel&#039;&#039; and set its frequency to 82.5 Hertz we could send the Ekdahl FAR the following &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
bowmotorrun:1, bowcontrolfrequecy:82.5&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bowingwheel.dcmotor.run:1, bowingwheel.pid.targetfrequency:82.5&amp;lt;/pre&amp;gt;We could also use the &#039;&#039;short names&#039;&#039; for the commands&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
bmr:1,bcf:82.5&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bw.dcm.ru:1, bw.pid.tf:82.5&amp;lt;/pre&amp;gt;Both &#039;&#039;bowmotorrun&#039;&#039; / &#039;&#039;bowingwheel.dcmotor.run&#039;&#039; and &#039;&#039;bowcontrolfrequency / bowingwheel.pid.targetfrequency&#039;&#039; takes one &#039;&#039;parameter&#039;&#039; each, &#039;&#039;bowmotorrun / bowingwheel.dcmotor.run&#039;&#039; is &#039;&#039;conditional&#039;&#039; and unless the first &#039;&#039;parameter&#039;&#039; is equal to &#039;1&#039; the motor will not start. The first &#039;&#039;parameter&#039;&#039; of &#039;&#039;bowcontrolfrequency / bowingwheel.pid.targetfrequency&#039;&#039; sets the frequency of the &#039;&#039;bowing wheel&#039;&#039;, the instrument may not execute a &#039;&#039;command&#039;&#039; if it decides that the given &#039;&#039;parameters&#039;&#039; are outside of the working range or they are missing.&lt;br /&gt;
&lt;br /&gt;
The addition of the hierarchy in the FAR 1.1 firmware isn&#039;t just to be able to group commands, but it&#039;s also to make the FAR not limited to a single set of &#039;&#039;modules&#039;&#039; (and is the first stepping stone to a &#039;&#039;modular&#039;&#039; Ekdahl FAR). In fact, you could have 12 different bowing wheel &#039;&#039;modules&#039;&#039; for 12 different strings, these would then be addressed as &#039;&#039;bowingwheel[0].command, bowingwheel[1].command&#039;&#039; etc. Anyone familiar with C programming notices that this is the standard way of &#039;&#039;indexing&#039;&#039; an array; using brackets (&amp;quot;[ ]&amp;quot;). When addressing a module without &#039;&#039;indexing&#039;&#039; as above, the FAR will do one or two things; either use the first object (&amp;quot;[0]&amp;quot;) or, if the object is &#039;&#039;selectable&#039;&#039; it will use the previously selected object. To make things smoother a command can be executed on several objects at once by using ranges (&amp;quot;[0-4]&amp;quot;) and comma separation (&amp;quot;[0, 3, 5-6]&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
To test out a &#039;&#039;command&#039;&#039; you can send it directly to the Ekdahl FAR using the &#039;&#039;Console&#039;&#039; in the &#039;&#039;Configuration utility&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
To read up on existing &#039;&#039;commands&#039;&#039;, their &#039;&#039;parameters&#039;&#039; and a brief description you can check the &#039;&#039;Command reference&#039;&#039; in the &#039;&#039;Configuration utility&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Variables, functions and equations ==&lt;br /&gt;
What makes the &#039;&#039;Command language&#039;&#039; truly powerful is the concept of &#039;&#039;variables, functions&#039;&#039; and &#039;&#039;equations&#039;&#039;. All &#039;&#039;parameters&#039;&#039; that take numerical values can use any combination of &#039;&#039;variables, functions&#039;&#039; or &#039;&#039;equations.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
For instance, we can use the previous example and instead write our &#039;&#039;command string&#039;&#039; as follows&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
bowmotorrun:1, bowcontrolfrequency:82.5+note*20&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bowingwheel.dcmotor.run:1, bowingwheel.pid.targetfrequency:82.5+note*20&amp;lt;/pre&amp;gt;This example requires of course that the &#039;&#039;variable&#039;&#039; &#039;&#039;note&#039;&#039; exists in the current context. &lt;br /&gt;
&lt;br /&gt;
===== Variables =====&lt;br /&gt;
There are two types of &#039;&#039;variables&#039;&#039; in the Ekdahl FAR; &#039;&#039;global variables&#039;&#039; and &#039;&#039;event variables&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Global variables&#039;&#039; are variables that are always available and will exist in any context. The &#039;&#039;global variables&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;notecount&#039;&#039;&#039; - Contains the number of &#039;&#039;MIDI&#039;&#039; keys that are being held down, i.e. all &#039;&#039;Note on messages&#039;&#039; received that haven&#039;t gotten a paired &#039;&#039;Note off message&#039;&#039; yet&lt;br /&gt;
* &#039;&#039;&#039;uv0&#039;&#039;&#039; - &#039;&#039;&#039;uv9&#039;&#039;&#039; - These are &#039;&#039;user variables&#039;&#039; and can be set at any point using the &#039;&#039;globaluservariable command&#039;&#039; with the first &#039;&#039;parameter&#039;&#039; being which variable to set (0-9) and the second &#039;&#039;parameter&#039;&#039; being the value (float).&lt;br /&gt;
* &#039;&#039;&#039;e&#039;&#039;&#039; - Contains the constant &#039;&#039;[[wikipedia:E_(mathematical_constant)|e]]&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pi&#039;&#039;&#039; - Contains the constant &#039;&#039;[[wikipedia:Pi|pi]]&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Event variables&#039;&#039; are variables that are set by certain &#039;&#039;MIDI messages&#039;&#039; or when a new value is read on one of the jacks or knobs on the &#039;&#039;Control box&#039;&#039;. The &#039;&#039;Event variables&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;channel&#039;&#039;&#039; - Set by the &#039;&#039;Note on, Note off, Continuous Controller, Poly after touch, Pitch bend, Channel after touch&#039;&#039; and &#039;&#039;Program change MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;note&#039;&#039;&#039; - Set by the &#039;&#039;Note on, Note off&#039;&#039; and &#039;&#039;Poly after touch MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;velocity&#039;&#039;&#039; - Set by the &#039;&#039;Note on&#039;&#039; and &#039;&#039;Note off MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pressure&#039;&#039;&#039; - Set by the &#039;&#039;Poly after touch&#039;&#039; and &#039;&#039;Channel after touch MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; - Set by the &#039;&#039;Continuous Controller MIDI message&#039;&#039; and by the &#039;&#039;Control box&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pitch&#039;&#039;&#039; - Set by the &#039;&#039;Pitch bend MIDI message&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;program&#039;&#039;&#039; - Set by the &#039;&#039;Program change MIDI message&#039;&#039;&lt;br /&gt;
These variables will contain whatever data is relevant to the &amp;lt;u&amp;gt;last midi message sent&amp;lt;/u&amp;gt; and will not stay relevant beyond the reception of the last message.&lt;br /&gt;
&lt;br /&gt;
===== Functions =====&lt;br /&gt;
&#039;&#039;Functions&#039;&#039; can be used to change a numerical value or the result of an &#039;&#039;equation&#039;&#039;, the Ekdahl FAR contains both general &#039;&#039;arithmetic functions&#039;&#039; (courtesy of Lewis Van Winkle and the TINYEXPR engine) and &#039;&#039;specialized functions&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;arithmetic functions&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;abs&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Absolute_value|absolute value]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;acos&#039;&#039;&#039;(x), &#039;&#039;&#039;asin&#039;&#039;&#039;(x), &#039;&#039;&#039;atan&#039;&#039;&#039;(x), atan2(x, y) - Returns the [[wikipedia:Inverse_trigonometric_functions|&#039;&#039;arc-cos, -sin, -tan&#039;&#039; and &#039;&#039;-tan2&#039;&#039;]] of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;atan2&#039;&#039;&#039;(x,y) - Returns the &#039;&#039;[[wikipedia:Atan2|arctan2]]&#039;&#039; of &#039;&#039;x, y&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;floor&#039;&#039;&#039;(x), ceil(x) - Returns the [[wikipedia:Floor_and_ceiling_functions|&#039;&#039;floor&#039;&#039; and &#039;&#039;ceiling&#039;&#039;]] of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;exp&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Exponential_function|exponent]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;fac&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Factorial|factorial]]&#039;&#039; of x&lt;br /&gt;
* &#039;&#039;&#039;ln&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Natural_logarithm|natural logarithm]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;log10&#039;&#039;&#039;(x), &#039;&#039;&#039;log20&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Logarithm|logarithm]]&#039;&#039; of &#039;&#039;x&#039;&#039; using base 10 and 20 respectively&lt;br /&gt;
* &#039;&#039;&#039;ncr&#039;&#039;&#039;(x,y), &#039;&#039;&#039;npr&#039;&#039;&#039;(x,y) - Functions to calculate &#039;&#039;[[wikipedia:Combination|combinations]]&#039;&#039; and &#039;&#039;[[wikipedia:Permutation|permutations]]&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pow&#039;&#039;&#039;(x,y) - Returns &#039;&#039;x^y&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;sqrt&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Square_root|square root]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;cos&#039;&#039;&#039;(x), &#039;&#039;&#039;sin&#039;&#039;&#039;(x), &#039;&#039;&#039;tan&#039;&#039;&#039;(x) - Returns the [[wikipedia:Trigonometric_functions|&#039;&#039;cos, sin&#039;&#039; and &#039;&#039;tan&#039;&#039;]] of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;cosh&#039;&#039;&#039;(x), &#039;&#039;&#039;sinh&#039;&#039;&#039;(x), &#039;&#039;&#039;tanh&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Hyperbolic_functions|hyperbolic cos, sin and tan]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
The &#039;&#039;specialized functions&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;bool&#039;&#039;&#039;(x) - Returns 1 if &#039;&#039;x&#039;&#039; is more than 0&lt;br /&gt;
* &#039;&#039;&#039;ibool&#039;&#039;&#039;(x) - Returns 0 if &#039;&#039;x&#039;&#039; is more than 0&lt;br /&gt;
* &#039;&#039;&#039;deadband&#039;&#039;&#039;(x,y) - Returns &#039;&#039;x + y &#039;&#039; if &#039;&#039;x &amp;lt; y&#039;&#039; or &#039;&#039;x - y&#039;&#039; if &#039;&#039;x &amp;gt; y&#039;&#039;. If neither of these statements is true it returns &#039;&#039;0&#039;&#039; - used to create a [[wikipedia:Deadband|deadband]] of &#039;&#039;x&#039;&#039; with the threshold of &#039;&#039;y&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Functions&#039;&#039; can be readily used in a &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
bowmotorrun:1, bowcontrolfrequency:&amp;quot;8.17579875 * pow(2, (1/12 * note))&amp;quot;&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bowingwheel.dcmotor.run:1, bowingwheel.pid.targetfrequency:&amp;quot;8.17579875 * pow(2, (1/12 * note))&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;The previous statements starts the &#039;&#039;bowing wheel&#039;&#039; and sets the frequency of the wheel to &#039;&#039;8.17579875 * 2^(1/12 * note)&#039;&#039;. A middle &#039;C&#039; according to &#039;&#039;MIDI&#039;&#039; has a &#039;&#039;note value&#039;&#039; of 36, meaning if we substitute &#039;&#039;note&#039;&#039; with 36 we get the equation &#039;&#039;8.17579875 * 2^(1/12 * 36)&#039;&#039; which comes out to &#039;&#039;~65.4&#039;&#039; Hertz.&lt;br /&gt;
&lt;br /&gt;
Note that the first &#039;&#039;parameter&#039;&#039; for &#039;&#039;bowcontrolfrequency / bowingwheel.pid.targetfrequency&#039;&#039; is put in between double quotes (&amp;quot;). This is because the &#039;&#039;pow&#039;&#039;-function requires the use of a comma (&amp;quot;,&amp;quot;) in order to separate in between its two required inputs; &#039;&#039;x&#039;&#039; and &#039;&#039;y&#039;&#039;. In order for the Ekdahl FAR to know that this comma does not signal the beginning of a new &#039;&#039;command,&#039;&#039; we use quotes. Single (&#039;) and double (&amp;quot;) quotes can be used and nested in all &#039;&#039;parameters&#039;&#039; and are &amp;lt;u&amp;gt;required&amp;lt;/u&amp;gt; in a lot of circumstances, improper nesting or not using quotes can lead to the instrument not understanding the &#039;&#039;command string&#039;&#039; correctly.&lt;br /&gt;
&lt;br /&gt;
== Return messages ==&lt;br /&gt;
The Ekdahl FAR when connected via &#039;&#039;USB-Serial&#039;&#039; doesn&#039;t only accept &#039;&#039;commands&#039;&#039; but will also send various &#039;&#039;return messages&#039;&#039;. These are prefixed by their &#039;&#039;category&#039;&#039; denoted in brackets (&amp;quot;[]&amp;quot;), the existing categories as of this writing (2025-01-22) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;command&#039;&#039;&#039; / &#039;&#039;&#039;cmd&#039;&#039;&#039; - Acknowledges the reception of a command in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;usb&#039;&#039;&#039; - Acknowledges the reception of a &#039;&#039;MIDI message&#039;&#039; over &#039;&#039;USB&#039;&#039; in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;hardware&#039;&#039;&#039; / &#039;&#039;&#039;hw&#039;&#039;&#039; - Signals that a change has been sent to the Ekdahl FAR hardware, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;undefined&#039;&#039;&#039; / &#039;&#039;&#039;un&#039;&#039;&#039; - The message sent is in the &#039;&#039;undefined&#039;&#039; category, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;priority&#039;&#039;&#039; / &#039;&#039;&#039;pri&#039;&#039;&#039; - The message sent is in the &#039;&#039;priority&#039;&#039; category, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;error&#039;&#039;&#039; / &#039;&#039;&#039;err&#039;&#039;&#039; - Signals that an &#039;&#039;error&#039;&#039; has occurred, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;expressionparser&#039;&#039;&#039; / &#039;&#039;&#039;ep&#039;&#039;&#039; - These messages contains debugging information regarding the internal &#039;&#039;expression parser&#039;&#039; and is used for development&lt;br /&gt;
*&#039;&#039;&#039;debug&#039;&#039;&#039; / &#039;&#039;&#039;dbg&#039;&#039;&#039; - These messages contains various debugging information and is used for development&lt;br /&gt;
*&#039;&#039;&#039;help&#039;&#039;&#039; / &#039;&#039;&#039;hlp&#039;&#039;&#039; - Signals that the message is a response to a &#039;&#039;help&#039;&#039;-command being sent to the Ekdahl FAR. These messages are structured so that a receiver, like the &#039;&#039;Configuration utility&#039;&#039;, can parse information about available &#039;&#039;commands&#039;&#039; in the current &#039;&#039;firmware&#039;&#039; and relay it to a user in a structured way.&lt;br /&gt;
* &#039;&#039;&#039;inforequest&#039;&#039;&#039; / &#039;&#039;&#039;irq&#039;&#039;&#039; - Signals that an &#039;&#039;info request&#039;&#039; has been returned. This is a specialized message that is either sent as a response to an &#039;&#039;rqi&#039;&#039;-command or as a &#039;&#039;interrupt&#039;&#039;-message telling the user or receiving software about different parameters in the Ekdahl FAR. These messages follows the same structure as regular &#039;&#039;command message&#039;&#039;s of &#039;&#039;[irq]commandname:parameter1 [etc]&#039;&#039; so that it can be used by a receiving software to keep track of parameter changes&lt;br /&gt;
&lt;br /&gt;
===== Explicitly requesting information =====&lt;br /&gt;
By using the special command &#039;&#039;requestinfo / rqi&#039;&#039; one can request the information stored by a certain &#039;&#039;command&#039;&#039; or a state of the Ekdahl FAR. The &#039;&#039;rqi&#039;&#039;-command is executed in the convention &#039;&#039;rqi:commandname[:optional parameters]&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
To go back to our example of setting the bowing frequency using the &#039;&#039;bowcontrolfrequency&#039;&#039;-command we can ask the Ekdahl FAR what the bowing frequency is set to by writing&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
rqi:bowcontrolfrequency&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
rqi:bowingwheel.pid.targetfrequency&lt;br /&gt;
&amp;lt;/pre&amp;gt;The return value would be something like&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
[irq]bcf:82.5&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
[irq]bw[0].pid[0].tf:82.5&lt;br /&gt;
&amp;lt;/pre&amp;gt;Where &#039;[irq]&#039; denotes that the message returned is in the &#039;&#039;info request-&#039;&#039;category, that it pertains to the command &#039;&#039;bcf&#039;&#039; / &#039;&#039;bw.pid.tf&#039;&#039; and has the value &#039;&#039;82.5&#039;&#039;. Note that the returned &#039;&#039;command&#039;&#039; sent by an &#039;&#039;rqi&#039;&#039;-command always uses the &#039;&#039;short name&#039;&#039; in order to preserve bandwidth. In the FAR 1.1 the return statement always returns the &#039;&#039;index&#039;&#039; of the &#039;&#039;module&#039;&#039;(s) in question.&lt;br /&gt;
&lt;br /&gt;
Most commands do not require any &#039;&#039;parameters&#039;&#039; when using the &#039;&#039;rqi&#039;&#039;-command. The &#039;&#039;adcread&#039;&#039; / &#039;&#039;datareturn&#039;&#039;-command is an example of a &#039;&#039;command&#039;&#039; that &amp;lt;u&amp;gt;does&amp;lt;/u&amp;gt; require a &#039;&#039;parameter&#039;&#039; when used with &#039;&#039;rqi&#039;&#039;. The &#039;&#039;adcread / datareturn-&#039;&#039;command returns the last value read by the &#039;&#039;analog-to-digital converter&#039;&#039; in the &#039;&#039;Control box&#039;&#039;, because there are 8 different channels the first &#039;&#039;parameter&#039;&#039; sets which channel to return the data for, hence executing the &#039;&#039;command&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
rqi:adcr:3&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
rqi:controlbox.datareturn:3&lt;br /&gt;
&amp;lt;/pre&amp;gt;will return the last data read on &#039;&#039;analog-to-digital convert&#039;&#039; channel 3.&lt;br /&gt;
&lt;br /&gt;
== MIDI mapping ==&lt;br /&gt;
To change how a certain &#039;&#039;MIDI message&#039;&#039; interacts with the Ekdahl FAR we need to change the &#039;&#039;commands&#039;&#039; or &#039;&#039;parameters&#039;&#039; sent when the message is received. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;FAR &amp;lt; 1.1:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;command&#039;&#039; responsible for mapping &#039;&#039;command strings&#039;&#039; to different &#039;&#039;MIDI messages&#039;&#039; is &#039;&#039;midieventhandler&#039;&#039; or &#039;&#039;mev&#039;&#039; for short. The first &#039;&#039;parameter&#039;&#039; of &#039;&#039;mev&#039;&#039; is the type of &#039;&#039;MIDI message&#039;&#039; that we want to remap&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;&#039;&#039;noteon&#039;&#039;&#039;&#039;&#039; - Note on&lt;br /&gt;
* &#039;&#039;&#039;&#039;&#039;noteoff&#039;&#039;&#039; -&#039;&#039; Note off&lt;br /&gt;
* &#039;&#039;&#039;&#039;&#039;pat&#039;&#039;&#039; -&#039;&#039; Poly after touch&lt;br /&gt;
* &#039;&#039;&#039;&#039;&#039;cat&#039;&#039;&#039;&#039;&#039; - Channel after touch&lt;br /&gt;
* &#039;&#039;&#039;&#039;&#039;pb&#039;&#039;&#039;&#039;&#039; - Pitch bend&lt;br /&gt;
* &#039;&#039;&#039;&#039;&#039;pc&#039;&#039;&#039;&#039;&#039; - Program change&lt;br /&gt;
* &#039;&#039;&#039;&#039;&#039;cc&#039;&#039;&#039;&#039;&#039; - Continuous controller&lt;br /&gt;
&lt;br /&gt;
The second &#039;&#039;parameter&#039;&#039; is the &#039;&#039;command string&#039;&#039; that is to be associated with the &#039;&#039;MIDI Message&#039;&#039; - with the exception of the &#039;&#039;cc&#039;&#039;-type, here the second &#039;&#039;parameter&#039;&#039; is the &#039;&#039;controller number&#039;&#039; (0 - 127) and the &amp;lt;u&amp;gt;third&amp;lt;/u&amp;gt; &#039;&#039;parameter&#039;&#039; is the &#039;&#039;command string&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;FAR 1.1:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;commands&#039;&#039; responsible for mapping &#039;&#039;command strings&#039;&#039; to different &#039;&#039;MIDI messages&#039;&#039; are as follows&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;noteon/non&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;&#039;note on&#039;&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;noteoff&#039;&#039;/nof&#039;&#039;&#039;&#039;&#039;&amp;lt;nowiki/&amp;gt;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;&#039;note off MIDI message&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;polyaftertouch/pat&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;&#039;poly aftertouch MIDI message&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;channelaftertouch/cat&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;&#039;channel aftertouch MIDI message&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pitchbend/pb&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;&#039;pitch bend MIDI message&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;programchange/pc&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;&#039;program change MIDI message&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;continuouscontrollerdata/ccd&#039;&#039;&#039;&#039;&#039;:controller:commands&#039;&#039; - Sets the commands executed for &#039;&#039;continuous controller&#039;&#039; no &#039;&#039;controller&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We can of course use the &#039;&#039;rqi&#039;&#039;-command to check the current mapping, below we are asking what the current &#039;&#039;command string&#039;&#039; associated with the &#039;&#039;pitch bend&#039;&#039; &#039;&#039;MIDI message&#039;&#039; is&amp;lt;pre&amp;gt;&lt;br /&gt;
rqi:mev:pb&lt;br /&gt;
&amp;lt;/pre&amp;gt;This may return something like&amp;lt;pre&amp;gt;&lt;br /&gt;
[irq]bchsh:pitch*4&lt;br /&gt;
&amp;lt;/pre&amp;gt;The return message tells us that the &#039;&#039;pitch bend MIDI message&#039;&#039; is executing a &#039;&#039;bchsh&#039;&#039;-command with the parameter &#039;&#039;pitch*4&#039;&#039;. Looking in the &#039;&#039;command reference&#039;&#039; we can see that &#039;&#039;bchsh&#039;&#039; is the &#039;&#039;short name&#039;&#039; of the &#039;&#039;bowcontrolharmonicshift&#039;&#039;-command which shifts the frequency of the &#039;&#039;bowing wheel&#039;&#039; from the current frequency, the first (and only) parameter sets how much we want to shift it (depends on the &#039;&#039;bowcontrolharmonicshiftrange command&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
If we look in the list of &#039;&#039;[[The Ekdahl FAR - Command langue#Variables|variables]]&#039;&#039; above we can see that the &#039;&#039;pitch bend MIDI message&#039;&#039; will set the &#039;&#039;pitch variable&#039;&#039; which is indeed used. Now what is the &#039;&#039;&#039;*4&#039;&#039;&amp;lt;nowiki/&amp;gt;&#039; all about? Well the &#039;&#039;bchsh&#039;&#039;-command expects a &#039;&#039;16-bit signed&#039;&#039; value, meaning that a full &#039;&#039;harmonic shift&#039;&#039; downwards is equal to -32767, a full &#039;&#039;harmonic shift&#039;&#039; upwards is 32767 and no &#039;&#039;harmonic shift&#039;&#039; is 0. The &#039;&#039;pitch bend MIDI message&#039;&#039; however is only 14-bits, meaning its range is -8192 to 8192, so in order to be able to use the entire range we have to multiply &#039;&#039;pitch&#039;&#039; by 4.&lt;br /&gt;
&lt;br /&gt;
This whole thing about number of bits can seem confusing but in the end it&#039;s all about how fine control you have over things; the more possible values, the more detailed control. In fact, most &#039;&#039;MIDI&#039;&#039; values are only 7-bit (!) meaning a range of 0 - 127. While this may sound like a lot of detail for something like a volume control, it is not even close to enough resolution to for instance set the &#039;&#039;bowing speed&#039;&#039;. Imagine that our lowest possible note frequency is 50 Hz, that means that with a 0-127 range we can only go from 50 Hz to 127 + 50 = 177 Hz - and with no decimals! This meager range and the very coarse steps of only 1 Hz would mean the instrument would never be able to sound in tune and wouldn&#039;t even have two octaves of range. The idea of limiting the Ekdahl FAR to what is possible through &#039;&#039;MIDI&#039;&#039; seemed like a poor choice thus it was decided that &amp;lt;u&amp;gt;most&amp;lt;/u&amp;gt; parameters will instead be 16-bit.&lt;br /&gt;
&lt;br /&gt;
Now lets look at a more complex example, the &amp;lt;u&amp;gt;default&amp;lt;/u&amp;gt; &#039;&#039;Note On MIDI message&#039;&#039;. On a stock Ekdahl FAR, executing&amp;lt;pre&amp;gt;&lt;br /&gt;
rqi:mev:noteon&lt;br /&gt;
&amp;lt;/pre&amp;gt;Will return something like&amp;lt;pre&amp;gt;[irq]mev:noteon:&#039;m:0,b:0,bchb:note,bmr:1,bpid:1,bpe:1,se:(velocity*512)*(1-notecount),bcsm:0&#039;&amp;lt;/pre&amp;gt;As can be seen, there&#039;s a lot of stuff going on here! First of all, notice that everything after &#039;&#039;mev:noteon:&#039;&#039; is situated in between single quotes (&#039;) - this is &amp;lt;u&amp;gt;absolutely crucial&amp;lt;/u&amp;gt; for the Ekdahl FAR to know that everything within those last two quotes is part of the last &#039;&#039;parameter&#039;&#039; of the &#039;&#039;mev&#039;&#039;-command.&lt;br /&gt;
&lt;br /&gt;
Now let&#039;s break down what happens when this &#039;&#039;MIDI message&#039;&#039; is received, i.e. when a &#039;&#039;MIDI&#039;&#039; key is pressed down:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;m:0&#039;&#039; - Sets &#039;&#039;module&#039;&#039; to 0&lt;br /&gt;
# &#039;&#039;b:0&#039;&#039; - Sets &#039;&#039;bow&#039;&#039; to 0&lt;br /&gt;
# &#039;&#039;bchb:note&#039;&#039; - Invokes the &#039;&#039;bowcontrolharmonicbase-&#039;&#039;command with the first &#039;&#039;parameter&#039;&#039; set to the &#039;&#039;variable note&#039;&#039;. &lt;br /&gt;
# &#039;&#039;bmr:1&#039;&#039; - Sets the &#039;&#039;bowmotorrun&#039;&#039;-command to &#039;1&#039;, starting the &#039;&#039;bow motor&#039;&#039;&lt;br /&gt;
# &#039;&#039;bpid:1&#039;&#039; - Sets the &#039;&#039;bowpid&#039;&#039;-command to &#039;1&#039;, making sure the &#039;&#039;PID&#039;&#039; is used&lt;br /&gt;
# &#039;&#039;bpe:1&#039;&#039; - Sets the &#039;&#039;bowpressureengage&#039;&#039; to &#039;1&#039; which moves the &#039;&#039;bowing jack&#039;&#039; to the &#039;&#039;engage position&#039;&#039;&lt;br /&gt;
# &#039;&#039;se:(velocity*512)*(1-notecount)&#039;&#039; - Executes the &#039;&#039;solenoidengage&#039;&#039;-command with the value &#039;&#039;(velocity*512)*(1-notecount)&#039;&#039;&lt;br /&gt;
# &#039;&#039;bcsm:0&#039;&#039; - Sets the &#039;&#039;bowcontrolspeedmode&#039;&#039; to &#039;1&#039; which enables automatic shut down of the &#039;&#039;bowing motor&#039;&#039;&lt;br /&gt;
The first two &#039;&#039;commands&#039;&#039; are the &#039;&#039;module&#039;&#039;- and &#039;&#039;bow-&#039;&#039;command. These &#039;&#039;commands&#039;&#039; are is intended for future versions of the Ekdahl FAR that may contain more than one string or more than one bow per string. For now &#039;&#039;0&#039;&#039; is the only valid &#039;&#039;parameter&#039;&#039; value that will be accepted for either &#039;&#039;command&#039;&#039;.&#039;&#039;&amp;lt;nowiki/&amp;gt;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;bowcontrolharmonicbase&#039;&#039;-command sets the speed of the &#039;&#039;bowing wheel&#039;&#039; to its corresponding &#039;&#039;harmonic number&#039;&#039; but also takes into account its &#039;&#039;&amp;lt;nowiki/&amp;gt;&#039;base&#039;&#039;&#039; which is the &#039;&#039;MIDI key&#039;&#039; that is mapped to &#039;&#039;harmonic number 0&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
After this the bowing motor is started and the &#039;&#039;PID&#039;&#039; is turned, now the instrument will try and make sure that the &#039;&#039;bowing wheel&#039;&#039; is at the right speed.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;bowing jack&#039;&#039; is raised to the &#039;&#039;engage position&#039;&#039;, any added &#039;&#039;pressure modifiers&#039;&#039; will also be taken into account - once the &#039;&#039;bowing jack&#039;&#039; has reached its intended position the &#039;&#039;bowing wheel&#039;&#039; should (hopefully) make contact with the string and the Ekdahl FAR will start to produce sounds.&lt;br /&gt;
&lt;br /&gt;
After this we have the &#039;&#039;solenoidengage&#039;&#039;-command &#039;&#039;command&#039;&#039; that engages the &#039;&#039;hammer&#039;&#039; and uses the first and only &#039;&#039;parameter&#039;&#039; as the force used. Like with most &#039;&#039;commands&#039;&#039; the &#039;&#039;se&#039;&#039;-command is 16-bit (0 - 65535) but the &#039;&#039;MIDI velocity variable&#039;&#039; is 7-bit (0 - 127), so to get the &#039;&#039;velocity&#039;&#039; variable to cover the entire range it needs to be multiplied with 512. &lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&amp;lt;nowiki/&amp;gt;&#039;*(1-notecount)&#039;&#039;&#039;-part is a way of making sure that we are using &#039;&#039;legato&#039;&#039; mode, i.e. that the &#039;&#039;hammer&#039;&#039; is not triggered if a key is already held down when a new key is pressed. The &#039;&#039;notecount&#039;&#039;-variable contains the number of &#039;&#039;MIDI&#039;&#039; notes currently held down. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s postulate that the Ekdahl FAR is tuned to a &#039;C&#039; at 65.4Hz and has its &#039;&#039;base&#039;&#039; set to middle &#039;C&#039; (&#039;&#039;MIDI key&#039;&#039; no 36). We are using the equal-temperament 12-tone scale and the Ekdahl FAR is set to respond to &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; &#039;&#039;MIDI channels&#039;&#039; (omni). Without having previously held any keys we press the middle &#039;C&#039; (&#039;&#039;note&#039;&#039; value 36) as hard as possible (&#039;&#039;velocity&#039;&#039; value &#039;&#039;127&#039;&#039;) on &#039;&#039;MIDI channel&#039;&#039; number 1 (&#039;&#039;channel&#039;&#039; value of 0). The Ekdahl FAR will get a &#039;&#039;note on MIDI message&#039;&#039; sent to it and from our mapping it will create the following &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;[irq]mev:noteon:&#039;m:0,b:0,bchb:36,bmr:1,bpid:1,bpe:1,se:(127*512)*(1-0),bcsm:0&#039;&amp;lt;/pre&amp;gt;What has happened here is that all &#039;&#039;variables&#039;&#039; have been replaced with the values sent by the &#039;&#039;MIDI message&#039;&#039;. Since those &#039;&#039;commands&#039;&#039; that doesn&#039;t have any &#039;&#039;variables&#039;&#039; with them will execute just as previously, only those &#039;&#039;commands&#039;&#039; whos &#039;&#039;parameters&#039;&#039; have changed will be explained:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;bchb: 36&#039;&#039; - The &#039;&#039;bowcontrolharmonicbase&#039;&#039; gets a value of &#039;&#039;36&#039;&#039; (middle &#039;C&#039;), because &#039;&#039;harmonic number 0&#039;&#039; is mapped to this key it will set the &#039;&#039;bowing wheel&#039;&#039; frequency to the &#039;&#039;fundamental&#039;&#039;; &#039;&#039;65.4&#039;&#039; Hertz&lt;br /&gt;
# &#039;&#039;se: (127*512)*(1-0)&#039;&#039; - the value of &#039;&#039;127&#039;&#039; comes from the &#039;&#039;velocity&#039;&#039;-variable, &#039;&#039;127 * 512 = 65024&#039;&#039; which is awfully close to a maximum hammer force of 65535. Since no previous notes were held down &#039;&#039;notecount&#039;&#039;  is equal to &#039;&#039;0&#039;&#039; and thus &#039;&#039;65024 * 1 = 65024&#039;&#039;. The hammer is engaged with near maximum force.&lt;br /&gt;
So the result is that we have set the speed of the &#039;&#039;bowing motor&#039;&#039; and we have engaged the &#039;&#039;hammer&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Now imagine that without releasing this key, we press another &#039;C&#039; one octave above but at half the velocity. The Ekdahl FAR creates the following &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
[irq]mev:noteon:&#039;m:0,b:0,bchb:48,bmr:1,bpid:1,bpe:1,se:(63*512)*(1-1),bcsm:0&#039;&lt;br /&gt;
&amp;lt;/pre&amp;gt;Now we can see that the &#039;&#039;note&#039;&#039; variable is &#039;&#039;48&#039;&#039; because the &#039;C&#039; one octave up is exactly 12 keys above the first, the &#039;&#039;velocity&#039;&#039; variable has changed to &#039;&#039;63&#039;&#039; since we hit it with a lighter touch - and because we are &amp;lt;u&amp;gt;still holding the first key down&amp;lt;/u&amp;gt; &#039;&#039;notecount&#039;&#039; is equal to &#039;&#039;1&#039;&#039;. Here&#039;s what happens&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;bchb: 48&#039;&#039; - Due to the &#039;&#039;base&#039;&#039; being set to &#039;&#039;36&#039;&#039; the &#039;&#039;harmonic number&#039;&#039; is set to &#039;&#039;48 - 36 = 12&#039;&#039;. Because we are using a 12-tone scale &#039;&#039;harmonic number 12&#039;&#039; is exactly one octave above the &#039;&#039;fundamental&#039;&#039; thus the speed of the &#039;&#039;bowing wheel&#039;&#039; is set to &#039;&#039;65.4 * 2 = 130.8&#039;&#039; Hertz.&lt;br /&gt;
# &#039;&#039;se: (63*512)*(1-1)&#039;&#039; - So &#039;&#039;63 * 512 = 32256&#039;&#039; and &#039;&#039;1 - 1 = 0&#039;&#039; thus &#039;&#039;32256 * 0 = 0&#039;&#039;. When the &#039;&#039;solenoidengage&#039;&#039;-command gets a &#039;&#039;parameter&#039;&#039; of &#039;&#039;0&#039;&#039; it will not engage the &#039;&#039;hammer&#039;&#039; - so the &#039;&#039;hammer&#039;&#039; doesn&#039;t strike&lt;br /&gt;
So it can be seen that with quite rudimentary math we can accomplish a whole lot of things here. Note also that even though the &#039;&#039;note on MIDI message&#039;&#039; also sets the &#039;&#039;channel&#039;&#039;-variable we never use it in this example - plenty of opportunity to make something weird happen depending on the &#039;&#039;MIDI channel&#039;&#039;!&lt;br /&gt;
&lt;br /&gt;
== CV Mapping ==&lt;br /&gt;
&#039;&#039;CV Mapping&#039;&#039; works exactly like the &#039;&#039;MIDI mapping&#039;&#039; with the difference that the command for setting the &#039;&#039;CV mapping&#039;&#039; is different and that &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; events pertaining to this &amp;lt;u&amp;gt;only&amp;lt;/u&amp;gt; change the &#039;&#039;value&#039;&#039;-variable. The &#039;&#039;command&#039;&#039; for changing the &#039;&#039;CV mapping&#039;&#039; is &#039;&#039;adccommandmap&#039;&#039; or &#039;&#039;acm&#039;&#039;, it take two &#039;&#039;parameters&#039;&#039;; &#039;&#039;channel&#039;&#039; and &#039;&#039;command string&#039;&#039;. We retrieve the &#039;&#039;command string&#039;&#039; for channel &#039;&#039;0&#039;&#039; which reads the sum of the &#039;&#039;harm. v/oct&#039;&#039;-jack and the &#039;&#039;harmonic&#039;&#039;-knob by sending a command of&amp;lt;pre&amp;gt;&lt;br /&gt;
rqi:acm:0&lt;br /&gt;
&amp;lt;/pre&amp;gt;The &amp;lt;u&amp;gt;default&amp;lt;/u&amp;gt; response will be something like&lt;br /&gt;
&amp;lt;pre&amp;gt;[irq]acm:0:&#039;bcha:value/1327.716667-20&#039;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{docnav&lt;br /&gt;
|[[The Ekdahl FAR - Service|Service]]&lt;br /&gt;
|[[The Ekdahl FAR - Command reference|Command reference]]&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Knaadmin</name></author>
	</entry>
	<entry>
		<id>http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_language&amp;diff=1647</id>
		<title>The Ekdahl FAR - Command language</title>
		<link rel="alternate" type="text/html" href="http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_language&amp;diff=1647"/>
		<updated>2026-06-07T18:04:44Z</updated>

		<summary type="html">&lt;p&gt;Knaadmin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Command language ==&lt;br /&gt;
The Ekdahl FAR is entirely controlled by &#039;&#039;commands&#039;&#039;, these &#039;&#039;commands&#039;&#039; decide everything that the instrument is doing, whether it is playing a melody or changing an internal parameter. &lt;br /&gt;
&lt;br /&gt;
When a &#039;&#039;MIDI message&#039;&#039; is received or a new CV / knob value is read, the &#039;&#039;commands&#039;&#039; associated with it will be internally sent. This can be things like &amp;quot;engage hammer&amp;quot; or &amp;quot;set the fundamental frequency&amp;quot; etc. &lt;br /&gt;
&lt;br /&gt;
Some of the available &#039;&#039;commands&#039;&#039; are mainly used for calibrating and setting up the instrument and are usually saved into the instruments memory, these will be executed whenever the instrument is turned on. &lt;br /&gt;
&lt;br /&gt;
All &#039;&#039;commands&#039;&#039; can be manually invoked via &#039;&#039;USB-Serial&#039;&#039;, in conjunction with certain software this presents an unprecedented level of control and sequenceability.&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
The &#039;&#039;commands&#039;&#039; are invoked using a &#039;&#039;plain text approach&#039;&#039;, all commands have both a &#039;&#039;long name&#039;&#039; and a &#039;&#039;short name&#039;&#039; which are interchangeable. A &#039;&#039;command&#039;&#039; may have one or more &#039;&#039;parameters&#039;&#039; associated with it, these &#039;&#039;parameters&#039;&#039; can be of different types; 16-bit numbers (values 0 - 65535 or -32767 - 32767), floating point numbers (values with decimals), booleans (0 for &#039;false&#039;, 1 for &#039;true&#039;) and strings (text). Some commands are &#039;&#039;conditional&#039;&#039;, meaning they will only execute if a parameter equates to &#039;1&#039; (&#039;true&#039;). &lt;br /&gt;
&lt;br /&gt;
The way &#039;&#039;commands&#039;&#039; are written in order to be executed is &#039;&#039;commandname:parameter1:parameter2:parameter3 [etc]&#039;&#039;, several commands be executed in sequence by separating them with a comma (&#039;,&#039;), a bunch of commands strung together is called a &#039;&#039;command string&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Since version 1.1 of the Ekdahl FAR Firmware, all commands are grouped in a hierarchical fashion according to their &#039;&#039;modules&#039;&#039; and each ladder in the hierarchy is separated by a period (&amp;quot;.&amp;quot;), this works very much like folders or directories in a regular computer. Every &#039;&#039;module&#039;&#039; can contain both &#039;&#039;commands&#039;&#039; and other &#039;&#039;modules&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
For instance, everything associated with the &#039;&#039;bowing wheel&#039;&#039; is now collected under &amp;quot;bowingwheel&amp;quot; &#039;&#039;module&#039;&#039;. That in turn contains a &amp;quot;dcmotor&amp;quot; &#039;&#039;module&#039;&#039; which does direct control of the bowing motor, and it has a &amp;quot;pid&amp;quot; &#039;&#039;module&#039;&#039; that handles bow frequency.&lt;br /&gt;
&lt;br /&gt;
If for instance we would like to start the &#039;&#039;bowing wheel&#039;&#039; and set its frequency to 82.5 Hertz we could send the Ekdahl FAR the following &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
bowmotorrun:1, bowcontrolfrequecy:82.5&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bowingwheel.dcmotor.run:1, bowingwheel.pid.targetfrequency:82.5&amp;lt;/pre&amp;gt;We could also use the &#039;&#039;short names&#039;&#039; for the commands&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
bmr:1,bcf:82.5&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bw.dcm.ru:1, bw.pid.tf:82.5&amp;lt;/pre&amp;gt;Both &#039;&#039;bowmotorrun&#039;&#039; / &#039;&#039;bowingwheel.dcmotor.run&#039;&#039; and &#039;&#039;bowcontrolfrequency / bowingwheel.pid.targetfrequency&#039;&#039; takes one &#039;&#039;parameter&#039;&#039; each, &#039;&#039;bowmotorrun / bowingwheel.dcmotor.run&#039;&#039; is &#039;&#039;conditional&#039;&#039; and unless the first &#039;&#039;parameter&#039;&#039; is equal to &#039;1&#039; the motor will not start. The first &#039;&#039;parameter&#039;&#039; of &#039;&#039;bowcontrolfrequency / bowingwheel.pid.targetfrequency&#039;&#039; sets the frequency of the &#039;&#039;bowing wheel&#039;&#039;, the instrument may not execute a &#039;&#039;command&#039;&#039; if it decides that the given &#039;&#039;parameters&#039;&#039; are outside of the working range or they are missing.&lt;br /&gt;
&lt;br /&gt;
The addition of the hierarchy in the FAR 1.1 firmware isn&#039;t just to be able to group commands, but it&#039;s also to make the FAR not limited to a single set of &#039;&#039;modules&#039;&#039; (and is the first stepping stone to a &#039;&#039;modular&#039;&#039; Ekdahl FAR). In fact, you could have 12 different bowing wheel &#039;&#039;modules&#039;&#039; for 12 different strings, these would then be addressed as &#039;&#039;bowingwheel[0].command, bowingwheel[1].command&#039;&#039; etc. Anyone familiar with C programming notices that this is the standard way of &#039;&#039;indexing&#039;&#039; an array; using brackets (&amp;quot;[ ]&amp;quot;). When addressing a module without &#039;&#039;indexing&#039;&#039; as above, the FAR will do one or two things; either use the first object (&amp;quot;[0]&amp;quot;) or, if the object is &#039;&#039;selectable&#039;&#039; it will use the previously selected object. To make things smoother a command can be executed on several objects at once by using ranges (&amp;quot;[0-4]&amp;quot;) and comma separation (&amp;quot;[0, 3, 5-6]&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
To test out a &#039;&#039;command&#039;&#039; you can send it directly to the Ekdahl FAR using the &#039;&#039;Console&#039;&#039; in the &#039;&#039;Configuration utility&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
To read up on existing &#039;&#039;commands&#039;&#039;, their &#039;&#039;parameters&#039;&#039; and a brief description you can check the &#039;&#039;Command reference&#039;&#039; in the &#039;&#039;Configuration utility&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Variables, functions and equations ==&lt;br /&gt;
What makes the &#039;&#039;Command language&#039;&#039; truly powerful is the concept of &#039;&#039;variables, functions&#039;&#039; and &#039;&#039;equations&#039;&#039;. All &#039;&#039;parameters&#039;&#039; that take numerical values can use any combination of &#039;&#039;variables, functions&#039;&#039; or &#039;&#039;equations.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
For instance, we can use the previous example and instead write our &#039;&#039;command string&#039;&#039; as follows&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
bowmotorrun:1, bowcontrolfrequency:82.5+note*20&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bowingwheel.dcmotor.run:1, bowingwheel.pid.targetfrequency:82.5+note*20&amp;lt;/pre&amp;gt;This example requires of course that the &#039;&#039;variable&#039;&#039; &#039;&#039;note&#039;&#039; exists in the current context. &lt;br /&gt;
&lt;br /&gt;
===== Variables =====&lt;br /&gt;
There are two types of &#039;&#039;variables&#039;&#039; in the Ekdahl FAR; &#039;&#039;global variables&#039;&#039; and &#039;&#039;event variables&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Global variables&#039;&#039; are variables that are always available and will exist in any context. The &#039;&#039;global variables&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;notecount&#039;&#039;&#039; - Contains the number of &#039;&#039;MIDI&#039;&#039; keys that are being held down, i.e. all &#039;&#039;Note on messages&#039;&#039; received that haven&#039;t gotten a paired &#039;&#039;Note off message&#039;&#039; yet&lt;br /&gt;
* &#039;&#039;&#039;uv0&#039;&#039;&#039; - &#039;&#039;&#039;uv9&#039;&#039;&#039; - These are &#039;&#039;user variables&#039;&#039; and can be set at any point using the &#039;&#039;globaluservariable command&#039;&#039; with the first &#039;&#039;parameter&#039;&#039; being which variable to set (0-9) and the second &#039;&#039;parameter&#039;&#039; being the value (float).&lt;br /&gt;
* &#039;&#039;&#039;e&#039;&#039;&#039; - Contains the constant &#039;&#039;[[wikipedia:E_(mathematical_constant)|e]]&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pi&#039;&#039;&#039; - Contains the constant &#039;&#039;[[wikipedia:Pi|pi]]&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Event variables&#039;&#039; are variables that are set by certain &#039;&#039;MIDI messages&#039;&#039; or when a new value is read on one of the jacks or knobs on the &#039;&#039;Control box&#039;&#039;. The &#039;&#039;Event variables&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;channel&#039;&#039;&#039; - Set by the &#039;&#039;Note on, Note off, Continuous Controller, Poly after touch, Pitch bend, Channel after touch&#039;&#039; and &#039;&#039;Program change MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;note&#039;&#039;&#039; - Set by the &#039;&#039;Note on, Note off&#039;&#039; and &#039;&#039;Poly after touch MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;velocity&#039;&#039;&#039; - Set by the &#039;&#039;Note on&#039;&#039; and &#039;&#039;Note off MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pressure&#039;&#039;&#039; - Set by the &#039;&#039;Poly after touch&#039;&#039; and &#039;&#039;Channel after touch MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; - Set by the &#039;&#039;Continuous Controller MIDI message&#039;&#039; and by the &#039;&#039;Control box&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pitch&#039;&#039;&#039; - Set by the &#039;&#039;Pitch bend MIDI message&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;program&#039;&#039;&#039; - Set by the &#039;&#039;Program change MIDI message&#039;&#039;&lt;br /&gt;
These variables will contain whatever data is relevant to the &amp;lt;u&amp;gt;last midi message sent&amp;lt;/u&amp;gt; and will not stay relevant beyond the reception of the last message.&lt;br /&gt;
&lt;br /&gt;
===== Functions =====&lt;br /&gt;
&#039;&#039;Functions&#039;&#039; can be used to change a numerical value or the result of an &#039;&#039;equation&#039;&#039;, the Ekdahl FAR contains both general &#039;&#039;arithmetic functions&#039;&#039; (courtesy of Lewis Van Winkle and the TINYEXPR engine) and &#039;&#039;specialized functions&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;arithmetic functions&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;abs&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Absolute_value|absolute value]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;acos&#039;&#039;&#039;(x), &#039;&#039;&#039;asin&#039;&#039;&#039;(x), &#039;&#039;&#039;atan&#039;&#039;&#039;(x), atan2(x, y) - Returns the [[wikipedia:Inverse_trigonometric_functions|&#039;&#039;arc-cos, -sin, -tan&#039;&#039; and &#039;&#039;-tan2&#039;&#039;]] of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;atan2&#039;&#039;&#039;(x,y) - Returns the &#039;&#039;[[wikipedia:Atan2|arctan2]]&#039;&#039; of &#039;&#039;x, y&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;floor&#039;&#039;&#039;(x), ceil(x) - Returns the [[wikipedia:Floor_and_ceiling_functions|&#039;&#039;floor&#039;&#039; and &#039;&#039;ceiling&#039;&#039;]] of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;exp&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Exponential_function|exponent]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;fac&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Factorial|factorial]]&#039;&#039; of x&lt;br /&gt;
* &#039;&#039;&#039;ln&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Natural_logarithm|natural logarithm]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;log10&#039;&#039;&#039;(x), &#039;&#039;&#039;log20&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Logarithm|logarithm]]&#039;&#039; of &#039;&#039;x&#039;&#039; using base 10 and 20 respectively&lt;br /&gt;
* &#039;&#039;&#039;ncr&#039;&#039;&#039;(x,y), &#039;&#039;&#039;npr&#039;&#039;&#039;(x,y) - Functions to calculate &#039;&#039;[[wikipedia:Combination|combinations]]&#039;&#039; and &#039;&#039;[[wikipedia:Permutation|permutations]]&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pow&#039;&#039;&#039;(x,y) - Returns &#039;&#039;x^y&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;sqrt&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Square_root|square root]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;cos&#039;&#039;&#039;(x), &#039;&#039;&#039;sin&#039;&#039;&#039;(x), &#039;&#039;&#039;tan&#039;&#039;&#039;(x) - Returns the [[wikipedia:Trigonometric_functions|&#039;&#039;cos, sin&#039;&#039; and &#039;&#039;tan&#039;&#039;]] of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;cosh&#039;&#039;&#039;(x), &#039;&#039;&#039;sinh&#039;&#039;&#039;(x), &#039;&#039;&#039;tanh&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Hyperbolic_functions|hyperbolic cos, sin and tan]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
The &#039;&#039;specialized functions&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;bool&#039;&#039;&#039;(x) - Returns 1 if &#039;&#039;x&#039;&#039; is more than 0&lt;br /&gt;
* &#039;&#039;&#039;ibool&#039;&#039;&#039;(x) - Returns 0 if &#039;&#039;x&#039;&#039; is more than 0&lt;br /&gt;
* &#039;&#039;&#039;deadband&#039;&#039;&#039;(x,y) - Returns &#039;&#039;x + y &#039;&#039; if &#039;&#039;x &amp;lt; y&#039;&#039; or &#039;&#039;x - y&#039;&#039; if &#039;&#039;x &amp;gt; y&#039;&#039;. If neither of these statements is true it returns &#039;&#039;0&#039;&#039; - used to create a [[wikipedia:Deadband|deadband]] of &#039;&#039;x&#039;&#039; with the threshold of &#039;&#039;y&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Functions&#039;&#039; can be readily used in a &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
bowmotorrun:1, bowcontrolfrequency:&amp;quot;8.17579875 * pow(2, (1/12 * note))&amp;quot;&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bowingwheel.dcmotor.run:1, bowingwheel.pid.targetfrequency:&amp;quot;8.17579875 * pow(2, (1/12 * note))&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;The previous statements starts the &#039;&#039;bowing wheel&#039;&#039; and sets the frequency of the wheel to &#039;&#039;8.17579875 * 2^(1/12 * note)&#039;&#039;. A middle &#039;C&#039; according to &#039;&#039;MIDI&#039;&#039; has a &#039;&#039;note value&#039;&#039; of 36, meaning if we substitute &#039;&#039;note&#039;&#039; with 36 we get the equation &#039;&#039;8.17579875 * 2^(1/12 * 36)&#039;&#039; which comes out to &#039;&#039;~65.4&#039;&#039; Hertz.&lt;br /&gt;
&lt;br /&gt;
Note that the first &#039;&#039;parameter&#039;&#039; for &#039;&#039;bowcontrolfrequency / bowingwheel.pid.targetfrequency&#039;&#039; is put in between double quotes (&amp;quot;). This is because the &#039;&#039;pow&#039;&#039;-function requires the use of a comma (&amp;quot;,&amp;quot;) in order to separate in between its two required inputs; &#039;&#039;x&#039;&#039; and &#039;&#039;y&#039;&#039;. In order for the Ekdahl FAR to know that this comma does not signal the beginning of a new &#039;&#039;command,&#039;&#039; we use quotes. Single (&#039;) and double (&amp;quot;) quotes can be used and nested in all &#039;&#039;parameters&#039;&#039; and are &amp;lt;u&amp;gt;required&amp;lt;/u&amp;gt; in a lot of circumstances, improper nesting or not using quotes can lead to the instrument not understanding the &#039;&#039;command string&#039;&#039; correctly.&lt;br /&gt;
&lt;br /&gt;
== Return messages ==&lt;br /&gt;
The Ekdahl FAR when connected via &#039;&#039;USB-Serial&#039;&#039; doesn&#039;t only accept &#039;&#039;commands&#039;&#039; but will also send various &#039;&#039;return messages&#039;&#039;. These are prefixed by their &#039;&#039;category&#039;&#039; denoted in brackets (&amp;quot;[]&amp;quot;), the existing categories as of this writing (2025-01-22) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;command&#039;&#039;&#039; / &#039;&#039;&#039;cmd&#039;&#039;&#039; - Acknowledges the reception of a command in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;usb&#039;&#039;&#039; - Acknowledges the reception of a &#039;&#039;MIDI message&#039;&#039; over &#039;&#039;USB&#039;&#039; in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;hardware&#039;&#039;&#039; / &#039;&#039;&#039;hw&#039;&#039;&#039; - Signals that a change has been sent to the Ekdahl FAR hardware, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;undefined&#039;&#039;&#039; / &#039;&#039;&#039;un&#039;&#039;&#039; - The message sent is in the &#039;&#039;undefined&#039;&#039; category, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;priority&#039;&#039;&#039; / &#039;&#039;&#039;pri&#039;&#039;&#039; - The message sent is in the &#039;&#039;priority&#039;&#039; category, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;error&#039;&#039;&#039; / &#039;&#039;&#039;err&#039;&#039;&#039; - Signals that an &#039;&#039;error&#039;&#039; has occurred, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;expressionparser&#039;&#039;&#039; / &#039;&#039;&#039;ep&#039;&#039;&#039; - These messages contains debugging information regarding the internal &#039;&#039;expression parser&#039;&#039; and is used for development&lt;br /&gt;
*&#039;&#039;&#039;debug&#039;&#039;&#039; / &#039;&#039;&#039;dbg&#039;&#039;&#039; - These messages contains various debugging information and is used for development&lt;br /&gt;
*&#039;&#039;&#039;help&#039;&#039;&#039; / &#039;&#039;&#039;hlp&#039;&#039;&#039; - Signals that the message is a response to a &#039;&#039;help&#039;&#039;-command being sent to the Ekdahl FAR. These messages are structured so that a receiver, like the &#039;&#039;Configuration utility&#039;&#039;, can parse information about available &#039;&#039;commands&#039;&#039; in the current &#039;&#039;firmware&#039;&#039; and relay it to a user in a structured way.&lt;br /&gt;
* &#039;&#039;&#039;inforequest&#039;&#039;&#039; / &#039;&#039;&#039;irq&#039;&#039;&#039; - Signals that an &#039;&#039;info request&#039;&#039; has been returned. This is a specialized message that is either sent as a response to an &#039;&#039;rqi&#039;&#039;-command or as a &#039;&#039;interrupt&#039;&#039;-message telling the user or receiving software about different parameters in the Ekdahl FAR. These messages follows the same structure as regular &#039;&#039;command message&#039;&#039;s of &#039;&#039;[irq]commandname:parameter1 [etc]&#039;&#039; so that it can be used by a receiving software to keep track of parameter changes&lt;br /&gt;
&lt;br /&gt;
===== Explicitly requesting information =====&lt;br /&gt;
By using the special command &#039;&#039;requestinfo / rqi&#039;&#039; one can request the information stored by a certain &#039;&#039;command&#039;&#039; or a state of the Ekdahl FAR. The &#039;&#039;rqi&#039;&#039;-command is executed in the convention &#039;&#039;rqi:commandname[:optional parameters]&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
To go back to our example of setting the bowing frequency using the &#039;&#039;bowcontrolfrequency&#039;&#039;-command we can ask the Ekdahl FAR what the bowing frequency is set to by writing&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
rqi:bowcontrolfrequency&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
rqi:bowingwheel.pid.targetfrequency&lt;br /&gt;
&amp;lt;/pre&amp;gt;The return value would be something like&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
[irq]bcf:82.5&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
[irq]bw[0].pid[0].tf:82.5&lt;br /&gt;
&amp;lt;/pre&amp;gt;Where &#039;[irq]&#039; denotes that the message returned is in the &#039;&#039;info request-&#039;&#039;category, that it pertains to the command &#039;&#039;bcf&#039;&#039; / &#039;&#039;bw.pid.tf&#039;&#039; and has the value &#039;&#039;82.5&#039;&#039;. Note that the returned &#039;&#039;command&#039;&#039; sent by an &#039;&#039;rqi&#039;&#039;-command always uses the &#039;&#039;short name&#039;&#039; in order to preserve bandwidth. In the FAR 1.1 the return statement always returns the &#039;&#039;index&#039;&#039; of the &#039;&#039;module&#039;&#039;(s) in question.&lt;br /&gt;
&lt;br /&gt;
Most commands do not require any &#039;&#039;parameters&#039;&#039; when using the &#039;&#039;rqi&#039;&#039;-command. The &#039;&#039;adcread&#039;&#039; / &#039;&#039;datareturn&#039;&#039;-command is an example of a &#039;&#039;command&#039;&#039; that &amp;lt;u&amp;gt;does&amp;lt;/u&amp;gt; require a &#039;&#039;parameter&#039;&#039; when used with &#039;&#039;rqi&#039;&#039;. The &#039;&#039;adcread / datareturn-&#039;&#039;command returns the last value read by the &#039;&#039;analog-to-digital converter&#039;&#039; in the &#039;&#039;Control box&#039;&#039;, because there are 8 different channels the first &#039;&#039;parameter&#039;&#039; sets which channel to return the data for, hence executing the &#039;&#039;command&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
rqi:adcr:3&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
rqi:controlbox.datareturn:3&lt;br /&gt;
&amp;lt;/pre&amp;gt;will return the last data read on &#039;&#039;analog-to-digital convert&#039;&#039; channel 3.&lt;br /&gt;
&lt;br /&gt;
== MIDI mapping ==&lt;br /&gt;
To change how a certain &#039;&#039;MIDI message&#039;&#039; interacts with the Ekdahl FAR we need to change the &#039;&#039;commands&#039;&#039; or &#039;&#039;parameters&#039;&#039; sent when the message is received. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;FAR &amp;lt; 1.1:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;command&#039;&#039; responsible for mapping &#039;&#039;command strings&#039;&#039; to different &#039;&#039;MIDI messages&#039;&#039; is &#039;&#039;midieventhandler&#039;&#039; or &#039;&#039;mev&#039;&#039; for short. The first &#039;&#039;parameter&#039;&#039; of &#039;&#039;mev&#039;&#039; is the type of &#039;&#039;MIDI message&#039;&#039; that we want to remap&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;&#039;&#039;noteon&#039;&#039;&#039;&#039;&#039; - Note on&lt;br /&gt;
* &#039;&#039;&#039;&#039;&#039;noteoff&#039;&#039;&#039; -&#039;&#039; Note off&lt;br /&gt;
* &#039;&#039;&#039;&#039;&#039;pat&#039;&#039;&#039; -&#039;&#039; Poly after touch&lt;br /&gt;
* &#039;&#039;&#039;&#039;&#039;cat&#039;&#039;&#039;&#039;&#039; - Channel after touch&lt;br /&gt;
* &#039;&#039;&#039;&#039;&#039;pb&#039;&#039;&#039;&#039;&#039; - Pitch bend&lt;br /&gt;
* &#039;&#039;&#039;&#039;&#039;pc&#039;&#039;&#039;&#039;&#039; - Program change&lt;br /&gt;
* &#039;&#039;&#039;&#039;&#039;cc&#039;&#039;&#039;&#039;&#039; - Continuous controller&lt;br /&gt;
&lt;br /&gt;
The second &#039;&#039;parameter&#039;&#039; is the &#039;&#039;command string&#039;&#039; that is to be associated with the &#039;&#039;MIDI Message&#039;&#039; - with the exception of the &#039;&#039;cc&#039;&#039;-type, here the second &#039;&#039;parameter&#039;&#039; is the &#039;&#039;controller number&#039;&#039; (0 - 127) and the &amp;lt;u&amp;gt;third&amp;lt;/u&amp;gt; &#039;&#039;parameter&#039;&#039; is the &#039;&#039;command string&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;FAR 1.1:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;commands&#039;&#039; responsible for mapping &#039;&#039;command strings&#039;&#039; to different &#039;&#039;MIDI messages&#039;&#039; are as follows&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;noteon/non&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;&#039;note on&#039;&#039; &#039;&#039;MIDI message&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;noteoff&#039;&#039;/nof&#039;&#039;&#039;&#039;&#039;&amp;lt;nowiki/&amp;gt;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;&#039;note off MIDI message&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;polyaftertouch/pat&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;&#039;poly aftertouch MIDI message&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;channelaftertouch/cat&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;&#039;channel aftertouch MIDI message&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pitchbend/pb&#039;&#039;&#039;&#039;&#039;:commands&#039;&#039; - Sets the commands executed for a &#039;&#039;pitch bend MIDI message&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We can of course use the &#039;&#039;rqi&#039;&#039;-command to check the current mapping, below we are asking what the current &#039;&#039;command string&#039;&#039; associated with the &#039;&#039;pitch bend&#039;&#039; &#039;&#039;MIDI message&#039;&#039; is&amp;lt;pre&amp;gt;&lt;br /&gt;
rqi:mev:pb&lt;br /&gt;
&amp;lt;/pre&amp;gt;This may return something like&amp;lt;pre&amp;gt;&lt;br /&gt;
[irq]bchsh:pitch*4&lt;br /&gt;
&amp;lt;/pre&amp;gt;The return message tells us that the &#039;&#039;pitch bend MIDI message&#039;&#039; is executing a &#039;&#039;bchsh&#039;&#039;-command with the parameter &#039;&#039;pitch*4&#039;&#039;. Looking in the &#039;&#039;command reference&#039;&#039; we can see that &#039;&#039;bchsh&#039;&#039; is the &#039;&#039;short name&#039;&#039; of the &#039;&#039;bowcontrolharmonicshift&#039;&#039;-command which shifts the frequency of the &#039;&#039;bowing wheel&#039;&#039; from the current frequency, the first (and only) parameter sets how much we want to shift it (depends on the &#039;&#039;bowcontrolharmonicshiftrange command&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
If we look in the list of &#039;&#039;[[The Ekdahl FAR - Command langue#Variables|variables]]&#039;&#039; above we can see that the &#039;&#039;pitch bend MIDI message&#039;&#039; will set the &#039;&#039;pitch variable&#039;&#039; which is indeed used. Now what is the &#039;&#039;&#039;*4&#039;&#039;&amp;lt;nowiki/&amp;gt;&#039; all about? Well the &#039;&#039;bchsh&#039;&#039;-command expects a &#039;&#039;16-bit signed&#039;&#039; value, meaning that a full &#039;&#039;harmonic shift&#039;&#039; downwards is equal to -32767, a full &#039;&#039;harmonic shift&#039;&#039; upwards is 32767 and no &#039;&#039;harmonic shift&#039;&#039; is 0. The &#039;&#039;pitch bend MIDI message&#039;&#039; however is only 14-bits, meaning its range is -8192 to 8192, so in order to be able to use the entire range we have to multiply &#039;&#039;pitch&#039;&#039; by 4.&lt;br /&gt;
&lt;br /&gt;
This whole thing about number of bits can seem confusing but in the end it&#039;s all about how fine control you have over things; the more possible values, the more detailed control. In fact, most &#039;&#039;MIDI&#039;&#039; values are only 7-bit (!) meaning a range of 0 - 127. While this may sound like a lot of detail for something like a volume control, it is not even close to enough resolution to for instance set the &#039;&#039;bowing speed&#039;&#039;. Imagine that our lowest possible note frequency is 50 Hz, that means that with a 0-127 range we can only go from 50 Hz to 127 + 50 = 177 Hz - and with no decimals! This meager range and the very coarse steps of only 1 Hz would mean the instrument would never be able to sound in tune and wouldn&#039;t even have two octaves of range. The idea of limiting the Ekdahl FAR to what is possible through &#039;&#039;MIDI&#039;&#039; seemed like a poor choice thus it was decided that &amp;lt;u&amp;gt;most&amp;lt;/u&amp;gt; parameters will instead be 16-bit.&lt;br /&gt;
&lt;br /&gt;
Now lets look at a more complex example, the &amp;lt;u&amp;gt;default&amp;lt;/u&amp;gt; &#039;&#039;Note On MIDI message&#039;&#039;. On a stock Ekdahl FAR, executing&amp;lt;pre&amp;gt;&lt;br /&gt;
rqi:mev:noteon&lt;br /&gt;
&amp;lt;/pre&amp;gt;Will return something like&amp;lt;pre&amp;gt;[irq]mev:noteon:&#039;m:0,b:0,bchb:note,bmr:1,bpid:1,bpe:1,se:(velocity*512)*(1-notecount),bcsm:0&#039;&amp;lt;/pre&amp;gt;As can be seen, there&#039;s a lot of stuff going on here! First of all, notice that everything after &#039;&#039;mev:noteon:&#039;&#039; is situated in between single quotes (&#039;) - this is &amp;lt;u&amp;gt;absolutely crucial&amp;lt;/u&amp;gt; for the Ekdahl FAR to know that everything within those last two quotes is part of the last &#039;&#039;parameter&#039;&#039; of the &#039;&#039;mev&#039;&#039;-command.&lt;br /&gt;
&lt;br /&gt;
Now let&#039;s break down what happens when this &#039;&#039;MIDI message&#039;&#039; is received, i.e. when a &#039;&#039;MIDI&#039;&#039; key is pressed down:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;m:0&#039;&#039; - Sets &#039;&#039;module&#039;&#039; to 0&lt;br /&gt;
# &#039;&#039;b:0&#039;&#039; - Sets &#039;&#039;bow&#039;&#039; to 0&lt;br /&gt;
# &#039;&#039;bchb:note&#039;&#039; - Invokes the &#039;&#039;bowcontrolharmonicbase-&#039;&#039;command with the first &#039;&#039;parameter&#039;&#039; set to the &#039;&#039;variable note&#039;&#039;. &lt;br /&gt;
# &#039;&#039;bmr:1&#039;&#039; - Sets the &#039;&#039;bowmotorrun&#039;&#039;-command to &#039;1&#039;, starting the &#039;&#039;bow motor&#039;&#039;&lt;br /&gt;
# &#039;&#039;bpid:1&#039;&#039; - Sets the &#039;&#039;bowpid&#039;&#039;-command to &#039;1&#039;, making sure the &#039;&#039;PID&#039;&#039; is used&lt;br /&gt;
# &#039;&#039;bpe:1&#039;&#039; - Sets the &#039;&#039;bowpressureengage&#039;&#039; to &#039;1&#039; which moves the &#039;&#039;bowing jack&#039;&#039; to the &#039;&#039;engage position&#039;&#039;&lt;br /&gt;
# &#039;&#039;se:(velocity*512)*(1-notecount)&#039;&#039; - Executes the &#039;&#039;solenoidengage&#039;&#039;-command with the value &#039;&#039;(velocity*512)*(1-notecount)&#039;&#039;&lt;br /&gt;
# &#039;&#039;bcsm:0&#039;&#039; - Sets the &#039;&#039;bowcontrolspeedmode&#039;&#039; to &#039;1&#039; which enables automatic shut down of the &#039;&#039;bowing motor&#039;&#039;&lt;br /&gt;
The first two &#039;&#039;commands&#039;&#039; are the &#039;&#039;module&#039;&#039;- and &#039;&#039;bow-&#039;&#039;command. These &#039;&#039;commands&#039;&#039; are is intended for future versions of the Ekdahl FAR that may contain more than one string or more than one bow per string. For now &#039;&#039;0&#039;&#039; is the only valid &#039;&#039;parameter&#039;&#039; value that will be accepted for either &#039;&#039;command&#039;&#039;.&#039;&#039;&amp;lt;nowiki/&amp;gt;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;bowcontrolharmonicbase&#039;&#039;-command sets the speed of the &#039;&#039;bowing wheel&#039;&#039; to its corresponding &#039;&#039;harmonic number&#039;&#039; but also takes into account its &#039;&#039;&amp;lt;nowiki/&amp;gt;&#039;base&#039;&#039;&#039; which is the &#039;&#039;MIDI key&#039;&#039; that is mapped to &#039;&#039;harmonic number 0&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
After this the bowing motor is started and the &#039;&#039;PID&#039;&#039; is turned, now the instrument will try and make sure that the &#039;&#039;bowing wheel&#039;&#039; is at the right speed.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;bowing jack&#039;&#039; is raised to the &#039;&#039;engage position&#039;&#039;, any added &#039;&#039;pressure modifiers&#039;&#039; will also be taken into account - once the &#039;&#039;bowing jack&#039;&#039; has reached its intended position the &#039;&#039;bowing wheel&#039;&#039; should (hopefully) make contact with the string and the Ekdahl FAR will start to produce sounds.&lt;br /&gt;
&lt;br /&gt;
After this we have the &#039;&#039;solenoidengage&#039;&#039;-command &#039;&#039;command&#039;&#039; that engages the &#039;&#039;hammer&#039;&#039; and uses the first and only &#039;&#039;parameter&#039;&#039; as the force used. Like with most &#039;&#039;commands&#039;&#039; the &#039;&#039;se&#039;&#039;-command is 16-bit (0 - 65535) but the &#039;&#039;MIDI velocity variable&#039;&#039; is 7-bit (0 - 127), so to get the &#039;&#039;velocity&#039;&#039; variable to cover the entire range it needs to be multiplied with 512. &lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&amp;lt;nowiki/&amp;gt;&#039;*(1-notecount)&#039;&#039;&#039;-part is a way of making sure that we are using &#039;&#039;legato&#039;&#039; mode, i.e. that the &#039;&#039;hammer&#039;&#039; is not triggered if a key is already held down when a new key is pressed. The &#039;&#039;notecount&#039;&#039;-variable contains the number of &#039;&#039;MIDI&#039;&#039; notes currently held down. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s postulate that the Ekdahl FAR is tuned to a &#039;C&#039; at 65.4Hz and has its &#039;&#039;base&#039;&#039; set to middle &#039;C&#039; (&#039;&#039;MIDI key&#039;&#039; no 36). We are using the equal-temperament 12-tone scale and the Ekdahl FAR is set to respond to &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; &#039;&#039;MIDI channels&#039;&#039; (omni). Without having previously held any keys we press the middle &#039;C&#039; (&#039;&#039;note&#039;&#039; value 36) as hard as possible (&#039;&#039;velocity&#039;&#039; value &#039;&#039;127&#039;&#039;) on &#039;&#039;MIDI channel&#039;&#039; number 1 (&#039;&#039;channel&#039;&#039; value of 0). The Ekdahl FAR will get a &#039;&#039;note on MIDI message&#039;&#039; sent to it and from our mapping it will create the following &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;[irq]mev:noteon:&#039;m:0,b:0,bchb:36,bmr:1,bpid:1,bpe:1,se:(127*512)*(1-0),bcsm:0&#039;&amp;lt;/pre&amp;gt;What has happened here is that all &#039;&#039;variables&#039;&#039; have been replaced with the values sent by the &#039;&#039;MIDI message&#039;&#039;. Since those &#039;&#039;commands&#039;&#039; that doesn&#039;t have any &#039;&#039;variables&#039;&#039; with them will execute just as previously, only those &#039;&#039;commands&#039;&#039; whos &#039;&#039;parameters&#039;&#039; have changed will be explained:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;bchb: 36&#039;&#039; - The &#039;&#039;bowcontrolharmonicbase&#039;&#039; gets a value of &#039;&#039;36&#039;&#039; (middle &#039;C&#039;), because &#039;&#039;harmonic number 0&#039;&#039; is mapped to this key it will set the &#039;&#039;bowing wheel&#039;&#039; frequency to the &#039;&#039;fundamental&#039;&#039;; &#039;&#039;65.4&#039;&#039; Hertz&lt;br /&gt;
# &#039;&#039;se: (127*512)*(1-0)&#039;&#039; - the value of &#039;&#039;127&#039;&#039; comes from the &#039;&#039;velocity&#039;&#039;-variable, &#039;&#039;127 * 512 = 65024&#039;&#039; which is awfully close to a maximum hammer force of 65535. Since no previous notes were held down &#039;&#039;notecount&#039;&#039;  is equal to &#039;&#039;0&#039;&#039; and thus &#039;&#039;65024 * 1 = 65024&#039;&#039;. The hammer is engaged with near maximum force.&lt;br /&gt;
So the result is that we have set the speed of the &#039;&#039;bowing motor&#039;&#039; and we have engaged the &#039;&#039;hammer&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Now imagine that without releasing this key, we press another &#039;C&#039; one octave above but at half the velocity. The Ekdahl FAR creates the following &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
[irq]mev:noteon:&#039;m:0,b:0,bchb:48,bmr:1,bpid:1,bpe:1,se:(63*512)*(1-1),bcsm:0&#039;&lt;br /&gt;
&amp;lt;/pre&amp;gt;Now we can see that the &#039;&#039;note&#039;&#039; variable is &#039;&#039;48&#039;&#039; because the &#039;C&#039; one octave up is exactly 12 keys above the first, the &#039;&#039;velocity&#039;&#039; variable has changed to &#039;&#039;63&#039;&#039; since we hit it with a lighter touch - and because we are &amp;lt;u&amp;gt;still holding the first key down&amp;lt;/u&amp;gt; &#039;&#039;notecount&#039;&#039; is equal to &#039;&#039;1&#039;&#039;. Here&#039;s what happens&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;bchb: 48&#039;&#039; - Due to the &#039;&#039;base&#039;&#039; being set to &#039;&#039;36&#039;&#039; the &#039;&#039;harmonic number&#039;&#039; is set to &#039;&#039;48 - 36 = 12&#039;&#039;. Because we are using a 12-tone scale &#039;&#039;harmonic number 12&#039;&#039; is exactly one octave above the &#039;&#039;fundamental&#039;&#039; thus the speed of the &#039;&#039;bowing wheel&#039;&#039; is set to &#039;&#039;65.4 * 2 = 130.8&#039;&#039; Hertz.&lt;br /&gt;
# &#039;&#039;se: (63*512)*(1-1)&#039;&#039; - So &#039;&#039;63 * 512 = 32256&#039;&#039; and &#039;&#039;1 - 1 = 0&#039;&#039; thus &#039;&#039;32256 * 0 = 0&#039;&#039;. When the &#039;&#039;solenoidengage&#039;&#039;-command gets a &#039;&#039;parameter&#039;&#039; of &#039;&#039;0&#039;&#039; it will not engage the &#039;&#039;hammer&#039;&#039; - so the &#039;&#039;hammer&#039;&#039; doesn&#039;t strike&lt;br /&gt;
So it can be seen that with quite rudimentary math we can accomplish a whole lot of things here. Note also that even though the &#039;&#039;note on MIDI message&#039;&#039; also sets the &#039;&#039;channel&#039;&#039;-variable we never use it in this example - plenty of opportunity to make something weird happen depending on the &#039;&#039;MIDI channel&#039;&#039;!&lt;br /&gt;
&lt;br /&gt;
== CV Mapping ==&lt;br /&gt;
&#039;&#039;CV Mapping&#039;&#039; works exactly like the &#039;&#039;MIDI mapping&#039;&#039; with the difference that the command for setting the &#039;&#039;CV mapping&#039;&#039; is different and that &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; events pertaining to this &amp;lt;u&amp;gt;only&amp;lt;/u&amp;gt; change the &#039;&#039;value&#039;&#039;-variable. The &#039;&#039;command&#039;&#039; for changing the &#039;&#039;CV mapping&#039;&#039; is &#039;&#039;adccommandmap&#039;&#039; or &#039;&#039;acm&#039;&#039;, it take two &#039;&#039;parameters&#039;&#039;; &#039;&#039;channel&#039;&#039; and &#039;&#039;command string&#039;&#039;. We retrieve the &#039;&#039;command string&#039;&#039; for channel &#039;&#039;0&#039;&#039; which reads the sum of the &#039;&#039;harm. v/oct&#039;&#039;-jack and the &#039;&#039;harmonic&#039;&#039;-knob by sending a command of&amp;lt;pre&amp;gt;&lt;br /&gt;
rqi:acm:0&lt;br /&gt;
&amp;lt;/pre&amp;gt;The &amp;lt;u&amp;gt;default&amp;lt;/u&amp;gt; response will be something like&lt;br /&gt;
&amp;lt;pre&amp;gt;[irq]acm:0:&#039;bcha:value/1327.716667-20&#039;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{docnav&lt;br /&gt;
|[[The Ekdahl FAR - Service|Service]]&lt;br /&gt;
|[[The Ekdahl FAR - Command reference|Command reference]]&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Knaadmin</name></author>
	</entry>
	<entry>
		<id>http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_language&amp;diff=1646</id>
		<title>The Ekdahl FAR - Command language</title>
		<link rel="alternate" type="text/html" href="http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_language&amp;diff=1646"/>
		<updated>2026-06-07T17:58:29Z</updated>

		<summary type="html">&lt;p&gt;Knaadmin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Command language ==&lt;br /&gt;
The Ekdahl FAR is entirely controlled by &#039;&#039;commands&#039;&#039;, these &#039;&#039;commands&#039;&#039; decide everything that the instrument is doing, whether it is playing a melody or changing an internal parameter. &lt;br /&gt;
&lt;br /&gt;
When a &#039;&#039;MIDI message&#039;&#039; is received or a new CV / knob value is read, the &#039;&#039;commands&#039;&#039; associated with it will be internally sent. This can be things like &amp;quot;engage hammer&amp;quot; or &amp;quot;set the fundamental frequency&amp;quot; etc. &lt;br /&gt;
&lt;br /&gt;
Some of the available &#039;&#039;commands&#039;&#039; are mainly used for calibrating and setting up the instrument and are usually saved into the instruments memory, these will be executed whenever the instrument is turned on. &lt;br /&gt;
&lt;br /&gt;
All &#039;&#039;commands&#039;&#039; can be manually invoked via &#039;&#039;USB-Serial&#039;&#039;, in conjunction with certain software this presents an unprecedented level of control and sequenceability.&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
The &#039;&#039;commands&#039;&#039; are invoked using a &#039;&#039;plain text approach&#039;&#039;, all commands have both a &#039;&#039;long name&#039;&#039; and a &#039;&#039;short name&#039;&#039; which are interchangeable. A &#039;&#039;command&#039;&#039; may have one or more &#039;&#039;parameters&#039;&#039; associated with it, these &#039;&#039;parameters&#039;&#039; can be of different types; 16-bit numbers (values 0 - 65535 or -32767 - 32767), floating point numbers (values with decimals), booleans (0 for &#039;false&#039;, 1 for &#039;true&#039;) and strings (text). Some commands are &#039;&#039;conditional&#039;&#039;, meaning they will only execute if a parameter equates to &#039;1&#039; (&#039;true&#039;). &lt;br /&gt;
&lt;br /&gt;
The way &#039;&#039;commands&#039;&#039; are written in order to be executed is &#039;&#039;commandname:parameter1:parameter2:parameter3 [etc]&#039;&#039;, several commands be executed in sequence by separating them with a comma (&#039;,&#039;), a bunch of commands strung together is called a &#039;&#039;command string&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Since version 1.1 of the Ekdahl FAR Firmware, all commands are grouped in a hierarchical fashion according to their &#039;&#039;modules&#039;&#039; and each ladder in the hierarchy is separated by a period (&amp;quot;.&amp;quot;), this works very much like folders or directories in a regular computer. Every &#039;&#039;module&#039;&#039; can contain both &#039;&#039;commands&#039;&#039; and other &#039;&#039;modules&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
For instance, everything associated with the &#039;&#039;bowing wheel&#039;&#039; is now collected under &amp;quot;bowingwheel&amp;quot; &#039;&#039;module&#039;&#039;. That in turn contains a &amp;quot;dcmotor&amp;quot; &#039;&#039;module&#039;&#039; which does direct control of the bowing motor, and it has a &amp;quot;pid&amp;quot; &#039;&#039;module&#039;&#039; that handles bow frequency.&lt;br /&gt;
&lt;br /&gt;
If for instance we would like to start the &#039;&#039;bowing wheel&#039;&#039; and set its frequency to 82.5 Hertz we could send the Ekdahl FAR the following &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
bowmotorrun:1, bowcontrolfrequecy:82.5&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bowingwheel.dcmotor.run:1, bowingwheel.pid.targetfrequency:82.5&amp;lt;/pre&amp;gt;We could also use the &#039;&#039;short names&#039;&#039; for the commands&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
bmr:1,bcf:82.5&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bw.dcm.ru:1, bw.pid.tf:82.5&amp;lt;/pre&amp;gt;Both &#039;&#039;bowmotorrun&#039;&#039; / &#039;&#039;bowingwheel.dcmotor.run&#039;&#039; and &#039;&#039;bowcontrolfrequency / bowingwheel.pid.targetfrequency&#039;&#039; takes one &#039;&#039;parameter&#039;&#039; each, &#039;&#039;bowmotorrun / bowingwheel.dcmotor.run&#039;&#039; is &#039;&#039;conditional&#039;&#039; and unless the first &#039;&#039;parameter&#039;&#039; is equal to &#039;1&#039; the motor will not start. The first &#039;&#039;parameter&#039;&#039; of &#039;&#039;bowcontrolfrequency / bowingwheel.pid.targetfrequency&#039;&#039; sets the frequency of the &#039;&#039;bowing wheel&#039;&#039;, the instrument may not execute a &#039;&#039;command&#039;&#039; if it decides that the given &#039;&#039;parameters&#039;&#039; are outside of the working range or they are missing.&lt;br /&gt;
&lt;br /&gt;
The addition of the hierarchy in the FAR 1.1 firmware isn&#039;t just to be able to group commands, but it&#039;s also to make the FAR not limited to a single set of &#039;&#039;modules&#039;&#039; (and is the first stepping stone to a &#039;&#039;modular&#039;&#039; Ekdahl FAR). In fact, you could have 12 different bowing wheel &#039;&#039;modules&#039;&#039; for 12 different strings, these would then be addressed as &#039;&#039;bowingwheel[0].command, bowingwheel[1].command&#039;&#039; etc. Anyone familiar with C programming notices that this is the standard way of &#039;&#039;indexing&#039;&#039; an array; using brackets (&amp;quot;[ ]&amp;quot;). When addressing a module without &#039;&#039;indexing&#039;&#039; as above, the FAR will do one or two things; either use the first object (&amp;quot;[0]&amp;quot;) or, if the object is &#039;&#039;selectable&#039;&#039; it will use the previously selected object. To make things smoother a command can be executed on several objects at once by using ranges (&amp;quot;[0-4]&amp;quot;) and comma separation (&amp;quot;[0, 3, 5-6]&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
To test out a &#039;&#039;command&#039;&#039; you can send it directly to the Ekdahl FAR using the &#039;&#039;Console&#039;&#039; in the &#039;&#039;Configuration utility&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
To read up on existing &#039;&#039;commands&#039;&#039;, their &#039;&#039;parameters&#039;&#039; and a brief description you can check the &#039;&#039;Command reference&#039;&#039; in the &#039;&#039;Configuration utility&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Variables, functions and equations ==&lt;br /&gt;
What makes the &#039;&#039;Command language&#039;&#039; truly powerful is the concept of &#039;&#039;variables, functions&#039;&#039; and &#039;&#039;equations&#039;&#039;. All &#039;&#039;parameters&#039;&#039; that take numerical values can use any combination of &#039;&#039;variables, functions&#039;&#039; or &#039;&#039;equations.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
For instance, we can use the previous example and instead write our &#039;&#039;command string&#039;&#039; as follows&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
bowmotorrun:1, bowcontrolfrequency:82.5+note*20&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bowingwheel.dcmotor.run:1, bowingwheel.pid.targetfrequency:82.5+note*20&amp;lt;/pre&amp;gt;This example requires of course that the &#039;&#039;variable&#039;&#039; &#039;&#039;note&#039;&#039; exists in the current context. &lt;br /&gt;
&lt;br /&gt;
===== Variables =====&lt;br /&gt;
There are two types of &#039;&#039;variables&#039;&#039; in the Ekdahl FAR; &#039;&#039;global variables&#039;&#039; and &#039;&#039;event variables&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Global variables&#039;&#039; are variables that are always available and will exist in any context. The &#039;&#039;global variables&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;notecount&#039;&#039;&#039; - Contains the number of &#039;&#039;MIDI&#039;&#039; keys that are being held down, i.e. all &#039;&#039;Note on messages&#039;&#039; received that haven&#039;t gotten a paired &#039;&#039;Note off message&#039;&#039; yet&lt;br /&gt;
* &#039;&#039;&#039;uv0&#039;&#039;&#039; - &#039;&#039;&#039;uv9&#039;&#039;&#039; - These are &#039;&#039;user variables&#039;&#039; and can be set at any point using the &#039;&#039;globaluservariable command&#039;&#039; with the first &#039;&#039;parameter&#039;&#039; being which variable to set (0-9) and the second &#039;&#039;parameter&#039;&#039; being the value (float).&lt;br /&gt;
* &#039;&#039;&#039;e&#039;&#039;&#039; - Contains the constant &#039;&#039;[[wikipedia:E_(mathematical_constant)|e]]&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pi&#039;&#039;&#039; - Contains the constant &#039;&#039;[[wikipedia:Pi|pi]]&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Event variables&#039;&#039; are variables that are set by certain &#039;&#039;MIDI messages&#039;&#039; or when a new value is read on one of the jacks or knobs on the &#039;&#039;Control box&#039;&#039;. The &#039;&#039;Event variables&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;channel&#039;&#039;&#039; - Set by the &#039;&#039;Note on, Note off, Continuous Controller, Poly after touch, Pitch bend, Channel after touch&#039;&#039; and &#039;&#039;Program change MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;note&#039;&#039;&#039; - Set by the &#039;&#039;Note on, Note off&#039;&#039; and &#039;&#039;Poly after touch MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;velocity&#039;&#039;&#039; - Set by the &#039;&#039;Note on&#039;&#039; and &#039;&#039;Note off MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pressure&#039;&#039;&#039; - Set by the &#039;&#039;Poly after touch&#039;&#039; and &#039;&#039;Channel after touch MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; - Set by the &#039;&#039;Continuous Controller MIDI message&#039;&#039; and by the &#039;&#039;Control box&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pitch&#039;&#039;&#039; - Set by the &#039;&#039;Pitch bend MIDI message&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;program&#039;&#039;&#039; - Set by the &#039;&#039;Program change MIDI message&#039;&#039;&lt;br /&gt;
These variables will contain whatever data is relevant to the &amp;lt;u&amp;gt;last midi message sent&amp;lt;/u&amp;gt; and will not stay relevant beyond the reception of the last message.&lt;br /&gt;
&lt;br /&gt;
===== Functions =====&lt;br /&gt;
&#039;&#039;Functions&#039;&#039; can be used to change a numerical value or the result of an &#039;&#039;equation&#039;&#039;, the Ekdahl FAR contains both general &#039;&#039;arithmetic functions&#039;&#039; (courtesy of Lewis Van Winkle and the TINYEXPR engine) and &#039;&#039;specialized functions&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;arithmetic functions&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;abs&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Absolute_value|absolute value]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;acos&#039;&#039;&#039;(x), &#039;&#039;&#039;asin&#039;&#039;&#039;(x), &#039;&#039;&#039;atan&#039;&#039;&#039;(x), atan2(x, y) - Returns the [[wikipedia:Inverse_trigonometric_functions|&#039;&#039;arc-cos, -sin, -tan&#039;&#039; and &#039;&#039;-tan2&#039;&#039;]] of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;atan2&#039;&#039;&#039;(x,y) - Returns the &#039;&#039;[[wikipedia:Atan2|arctan2]]&#039;&#039; of &#039;&#039;x, y&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;floor&#039;&#039;&#039;(x), ceil(x) - Returns the [[wikipedia:Floor_and_ceiling_functions|&#039;&#039;floor&#039;&#039; and &#039;&#039;ceiling&#039;&#039;]] of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;exp&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Exponential_function|exponent]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;fac&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Factorial|factorial]]&#039;&#039; of x&lt;br /&gt;
* &#039;&#039;&#039;ln&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Natural_logarithm|natural logarithm]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;log10&#039;&#039;&#039;(x), &#039;&#039;&#039;log20&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Logarithm|logarithm]]&#039;&#039; of &#039;&#039;x&#039;&#039; using base 10 and 20 respectively&lt;br /&gt;
* &#039;&#039;&#039;ncr&#039;&#039;&#039;(x,y), &#039;&#039;&#039;npr&#039;&#039;&#039;(x,y) - Functions to calculate &#039;&#039;[[wikipedia:Combination|combinations]]&#039;&#039; and &#039;&#039;[[wikipedia:Permutation|permutations]]&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pow&#039;&#039;&#039;(x,y) - Returns &#039;&#039;x^y&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;sqrt&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Square_root|square root]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;cos&#039;&#039;&#039;(x), &#039;&#039;&#039;sin&#039;&#039;&#039;(x), &#039;&#039;&#039;tan&#039;&#039;&#039;(x) - Returns the [[wikipedia:Trigonometric_functions|&#039;&#039;cos, sin&#039;&#039; and &#039;&#039;tan&#039;&#039;]] of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;cosh&#039;&#039;&#039;(x), &#039;&#039;&#039;sinh&#039;&#039;&#039;(x), &#039;&#039;&#039;tanh&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Hyperbolic_functions|hyperbolic cos, sin and tan]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
The &#039;&#039;specialized functions&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;bool&#039;&#039;&#039;(x) - Returns 1 if &#039;&#039;x&#039;&#039; is more than 0&lt;br /&gt;
* &#039;&#039;&#039;ibool&#039;&#039;&#039;(x) - Returns 0 if &#039;&#039;x&#039;&#039; is more than 0&lt;br /&gt;
* &#039;&#039;&#039;deadband&#039;&#039;&#039;(x,y) - Returns &#039;&#039;x + y &#039;&#039; if &#039;&#039;x &amp;lt; y&#039;&#039; or &#039;&#039;x - y&#039;&#039; if &#039;&#039;x &amp;gt; y&#039;&#039;. If neither of these statements is true it returns &#039;&#039;0&#039;&#039; - used to create a [[wikipedia:Deadband|deadband]] of &#039;&#039;x&#039;&#039; with the threshold of &#039;&#039;y&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Functions&#039;&#039; can be readily used in a &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
bowmotorrun:1, bowcontrolfrequency:&amp;quot;8.17579875 * pow(2, (1/12 * note))&amp;quot;&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bowingwheel.dcmotor.run:1, bowingwheel.pid.targetfrequency:&amp;quot;8.17579875 * pow(2, (1/12 * note))&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;The previous statements starts the &#039;&#039;bowing wheel&#039;&#039; and sets the frequency of the wheel to &#039;&#039;8.17579875 * 2^(1/12 * note)&#039;&#039;. A middle &#039;C&#039; according to &#039;&#039;MIDI&#039;&#039; has a &#039;&#039;note value&#039;&#039; of 36, meaning if we substitute &#039;&#039;note&#039;&#039; with 36 we get the equation &#039;&#039;8.17579875 * 2^(1/12 * 36)&#039;&#039; which comes out to &#039;&#039;~65.4&#039;&#039; Hertz.&lt;br /&gt;
&lt;br /&gt;
Note that the first &#039;&#039;parameter&#039;&#039; for &#039;&#039;bowcontrolfrequency / bowingwheel.pid.targetfrequency&#039;&#039; is put in between double quotes (&amp;quot;). This is because the &#039;&#039;pow&#039;&#039;-function requires the use of a comma (&amp;quot;,&amp;quot;) in order to separate in between its two required inputs; &#039;&#039;x&#039;&#039; and &#039;&#039;y&#039;&#039;. In order for the Ekdahl FAR to know that this comma does not signal the beginning of a new &#039;&#039;command,&#039;&#039; we use quotes. Single (&#039;) and double (&amp;quot;) quotes can be used and nested in all &#039;&#039;parameters&#039;&#039; and are &amp;lt;u&amp;gt;required&amp;lt;/u&amp;gt; in a lot of circumstances, improper nesting or not using quotes can lead to the instrument not understanding the &#039;&#039;command string&#039;&#039; correctly.&lt;br /&gt;
&lt;br /&gt;
== Return messages ==&lt;br /&gt;
The Ekdahl FAR when connected via &#039;&#039;USB-Serial&#039;&#039; doesn&#039;t only accept &#039;&#039;commands&#039;&#039; but will also send various &#039;&#039;return messages&#039;&#039;. These are prefixed by their &#039;&#039;category&#039;&#039; denoted in brackets (&amp;quot;[]&amp;quot;), the existing categories as of this writing (2025-01-22) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;command&#039;&#039;&#039; / &#039;&#039;&#039;cmd&#039;&#039;&#039; - Acknowledges the reception of a command in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;usb&#039;&#039;&#039; - Acknowledges the reception of a &#039;&#039;MIDI message&#039;&#039; over &#039;&#039;USB&#039;&#039; in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;hardware&#039;&#039;&#039; / &#039;&#039;&#039;hw&#039;&#039;&#039; - Signals that a change has been sent to the Ekdahl FAR hardware, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;undefined&#039;&#039;&#039; / &#039;&#039;&#039;un&#039;&#039;&#039; - The message sent is in the &#039;&#039;undefined&#039;&#039; category, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;priority&#039;&#039;&#039; / &#039;&#039;&#039;pri&#039;&#039;&#039; - The message sent is in the &#039;&#039;priority&#039;&#039; category, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;error&#039;&#039;&#039; / &#039;&#039;&#039;err&#039;&#039;&#039; - Signals that an &#039;&#039;error&#039;&#039; has occurred, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;expressionparser&#039;&#039;&#039; / &#039;&#039;&#039;ep&#039;&#039;&#039; - These messages contains debugging information regarding the internal &#039;&#039;expression parser&#039;&#039; and is used for development&lt;br /&gt;
*&#039;&#039;&#039;debug&#039;&#039;&#039; / &#039;&#039;&#039;dbg&#039;&#039;&#039; - These messages contains various debugging information and is used for development&lt;br /&gt;
*&#039;&#039;&#039;help&#039;&#039;&#039; / &#039;&#039;&#039;hlp&#039;&#039;&#039; - Signals that the message is a response to a &#039;&#039;help&#039;&#039;-command being sent to the Ekdahl FAR. These messages are structured so that a receiver, like the &#039;&#039;Configuration utility&#039;&#039;, can parse information about available &#039;&#039;commands&#039;&#039; in the current &#039;&#039;firmware&#039;&#039; and relay it to a user in a structured way.&lt;br /&gt;
* &#039;&#039;&#039;inforequest&#039;&#039;&#039; / &#039;&#039;&#039;irq&#039;&#039;&#039; - Signals that an &#039;&#039;info request&#039;&#039; has been returned. This is a specialized message that is either sent as a response to an &#039;&#039;rqi&#039;&#039;-command or as a &#039;&#039;interrupt&#039;&#039;-message telling the user or receiving software about different parameters in the Ekdahl FAR. These messages follows the same structure as regular &#039;&#039;command message&#039;&#039;s of &#039;&#039;[irq]commandname:parameter1 [etc]&#039;&#039; so that it can be used by a receiving software to keep track of parameter changes&lt;br /&gt;
&lt;br /&gt;
===== Explicitly requesting information =====&lt;br /&gt;
By using the special command &#039;&#039;requestinfo / rqi&#039;&#039; one can request the information stored by a certain &#039;&#039;command&#039;&#039; or a state of the Ekdahl FAR. The &#039;&#039;rqi&#039;&#039;-command is executed in the convention &#039;&#039;rqi:commandname[:optional parameters]&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
To go back to our example of setting the bowing frequency using the &#039;&#039;bowcontrolfrequency&#039;&#039;-command we can ask the Ekdahl FAR what the bowing frequency is set to by writing&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
rqi:bowcontrolfrequency&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
rqi:bowingwheel.pid.targetfrequency&lt;br /&gt;
&amp;lt;/pre&amp;gt;The return value would be something like&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
[irq]bcf:82.5&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
[irq]bw[0].pid[0].tf:82.5&lt;br /&gt;
&amp;lt;/pre&amp;gt;Where &#039;[irq]&#039; denotes that the message returned is in the &#039;&#039;info request-&#039;&#039;category, that it pertains to the command &#039;&#039;bcf&#039;&#039; / &#039;&#039;bw.pid.tf&#039;&#039; and has the value &#039;&#039;82.5&#039;&#039;. Note that the returned &#039;&#039;command&#039;&#039; sent by an &#039;&#039;rqi&#039;&#039;-command always uses the &#039;&#039;short name&#039;&#039; in order to preserve bandwidth. In the FAR 1.1 the return statement always returns the &#039;&#039;index&#039;&#039; of the &#039;&#039;module&#039;&#039;(s) in question.&lt;br /&gt;
&lt;br /&gt;
Most commands do not require any &#039;&#039;parameters&#039;&#039; when using the &#039;&#039;rqi&#039;&#039;-command. The &#039;&#039;adcread&#039;&#039; / &#039;&#039;datareturn&#039;&#039;-command is an example of a &#039;&#039;command&#039;&#039; that &amp;lt;u&amp;gt;does&amp;lt;/u&amp;gt; require a &#039;&#039;parameter&#039;&#039; when used with &#039;&#039;rqi&#039;&#039;. The &#039;&#039;adcread / datareturn-&#039;&#039;command returns the last value read by the &#039;&#039;analog-to-digital converter&#039;&#039; in the &#039;&#039;Control box&#039;&#039;, because there are 8 different channels the first &#039;&#039;parameter&#039;&#039; sets which channel to return the data for, hence executing the &#039;&#039;command&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
rqi:adcr:3&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
rqi:controlbox.datareturn:3&lt;br /&gt;
&amp;lt;/pre&amp;gt;will return the last data read on &#039;&#039;analog-to-digital convert&#039;&#039; channel 3.&lt;br /&gt;
&lt;br /&gt;
== MIDI mapping ==&lt;br /&gt;
To change how a certain &#039;&#039;MIDI message&#039;&#039; interacts with the Ekdahl FAR we need to change the &#039;&#039;commands&#039;&#039; or &#039;&#039;parameters&#039;&#039; sent when the message is received. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;FAR &amp;lt; 1.1:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;command&#039;&#039; responsible for mapping &#039;&#039;command strings&#039;&#039; to different &#039;&#039;MIDI messages&#039;&#039; is &#039;&#039;midieventhandler&#039;&#039; or &#039;&#039;mev&#039;&#039; for short. The first &#039;&#039;parameter&#039;&#039; of &#039;&#039;mev&#039;&#039; is the type of &#039;&#039;MIDI message&#039;&#039; that we want to remap&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;&#039;&#039;noteon&#039;&#039;&#039;&#039;&#039; - Note on&lt;br /&gt;
* &#039;&#039;&#039;&#039;&#039;noteoff&#039;&#039;&#039; -&#039;&#039; Note off&lt;br /&gt;
* &#039;&#039;&#039;&#039;&#039;pat&#039;&#039;&#039; -&#039;&#039; Poly after touch&lt;br /&gt;
* &#039;&#039;&#039;&#039;&#039;cat&#039;&#039;&#039;&#039;&#039; - Channel after touch&lt;br /&gt;
* &#039;&#039;&#039;&#039;&#039;pb&#039;&#039;&#039;&#039;&#039; - Pitch bend&lt;br /&gt;
* &#039;&#039;&#039;&#039;&#039;pc&#039;&#039;&#039;&#039;&#039; - Program change&lt;br /&gt;
* &#039;&#039;&#039;&#039;&#039;cc&#039;&#039;&#039;&#039;&#039; - Continuous controller&lt;br /&gt;
&lt;br /&gt;
The second &#039;&#039;parameter&#039;&#039; is the &#039;&#039;command string&#039;&#039; that is to be associated with the &#039;&#039;MIDI Message&#039;&#039; - with the exception of the &#039;&#039;cc&#039;&#039;-type, here the second &#039;&#039;parameter&#039;&#039; is the &#039;&#039;controller number&#039;&#039; (0 - 127) and the &amp;lt;u&amp;gt;third&amp;lt;/u&amp;gt; &#039;&#039;parameter&#039;&#039; is the &#039;&#039;command string&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;FAR 1.1:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;commands&#039;&#039; responsible for mapping &#039;&#039;command strings&#039;&#039; to different &#039;&#039;MIDI messages&#039;&#039; are as follows&lt;br /&gt;
&lt;br /&gt;
We can of course use the &#039;&#039;rqi&#039;&#039;-command to check the current mapping, below we are asking what the current &#039;&#039;command string&#039;&#039; associated with the &#039;&#039;pitch bend&#039;&#039; &#039;&#039;MIDI message&#039;&#039; is&amp;lt;pre&amp;gt;&lt;br /&gt;
rqi:mev:pb&lt;br /&gt;
&amp;lt;/pre&amp;gt;This may return something like&amp;lt;pre&amp;gt;&lt;br /&gt;
[irq]bchsh:pitch*4&lt;br /&gt;
&amp;lt;/pre&amp;gt;The return message tells us that the &#039;&#039;pitch bend MIDI message&#039;&#039; is executing a &#039;&#039;bchsh&#039;&#039;-command with the parameter &#039;&#039;pitch*4&#039;&#039;. Looking in the &#039;&#039;command reference&#039;&#039; we can see that &#039;&#039;bchsh&#039;&#039; is the &#039;&#039;short name&#039;&#039; of the &#039;&#039;bowcontrolharmonicshift&#039;&#039;-command which shifts the frequency of the &#039;&#039;bowing wheel&#039;&#039; from the current frequency, the first (and only) parameter sets how much we want to shift it (depends on the &#039;&#039;bowcontrolharmonicshiftrange command&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
If we look in the list of &#039;&#039;[[The Ekdahl FAR - Command langue#Variables|variables]]&#039;&#039; above we can see that the &#039;&#039;pitch bend MIDI message&#039;&#039; will set the &#039;&#039;pitch variable&#039;&#039; which is indeed used. Now what is the &#039;&#039;&#039;*4&#039;&#039;&amp;lt;nowiki/&amp;gt;&#039; all about? Well the &#039;&#039;bchsh&#039;&#039;-command expects a &#039;&#039;16-bit signed&#039;&#039; value, meaning that a full &#039;&#039;harmonic shift&#039;&#039; downwards is equal to -32767, a full &#039;&#039;harmonic shift&#039;&#039; upwards is 32767 and no &#039;&#039;harmonic shift&#039;&#039; is 0. The &#039;&#039;pitch bend MIDI message&#039;&#039; however is only 14-bits, meaning its range is -8192 to 8192, so in order to be able to use the entire range we have to multiply &#039;&#039;pitch&#039;&#039; by 4.&lt;br /&gt;
&lt;br /&gt;
This whole thing about number of bits can seem confusing but in the end it&#039;s all about how fine control you have over things; the more possible values, the more detailed control. In fact, most &#039;&#039;MIDI&#039;&#039; values are only 7-bit (!) meaning a range of 0 - 127. While this may sound like a lot of detail for something like a volume control, it is not even close to enough resolution to for instance set the &#039;&#039;bowing speed&#039;&#039;. Imagine that our lowest possible note frequency is 50 Hz, that means that with a 0-127 range we can only go from 50 Hz to 127 + 50 = 177 Hz - and with no decimals! This meager range and the very coarse steps of only 1 Hz would mean the instrument would never be able to sound in tune and wouldn&#039;t even have two octaves of range. The idea of limiting the Ekdahl FAR to what is possible through &#039;&#039;MIDI&#039;&#039; seemed like a poor choice thus it was decided that &amp;lt;u&amp;gt;most&amp;lt;/u&amp;gt; parameters will instead be 16-bit.&lt;br /&gt;
&lt;br /&gt;
Now lets look at a more complex example, the &amp;lt;u&amp;gt;default&amp;lt;/u&amp;gt; &#039;&#039;Note On MIDI message&#039;&#039;. On a stock Ekdahl FAR, executing&amp;lt;pre&amp;gt;&lt;br /&gt;
rqi:mev:noteon&lt;br /&gt;
&amp;lt;/pre&amp;gt;Will return something like&amp;lt;pre&amp;gt;[irq]mev:noteon:&#039;m:0,b:0,bchb:note,bmr:1,bpid:1,bpe:1,se:(velocity*512)*(1-notecount),bcsm:0&#039;&amp;lt;/pre&amp;gt;As can be seen, there&#039;s a lot of stuff going on here! First of all, notice that everything after &#039;&#039;mev:noteon:&#039;&#039; is situated in between single quotes (&#039;) - this is &amp;lt;u&amp;gt;absolutely crucial&amp;lt;/u&amp;gt; for the Ekdahl FAR to know that everything within those last two quotes is part of the last &#039;&#039;parameter&#039;&#039; of the &#039;&#039;mev&#039;&#039;-command.&lt;br /&gt;
&lt;br /&gt;
Now let&#039;s break down what happens when this &#039;&#039;MIDI message&#039;&#039; is received, i.e. when a &#039;&#039;MIDI&#039;&#039; key is pressed down:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;m:0&#039;&#039; - Sets &#039;&#039;module&#039;&#039; to 0&lt;br /&gt;
# &#039;&#039;b:0&#039;&#039; - Sets &#039;&#039;bow&#039;&#039; to 0&lt;br /&gt;
# &#039;&#039;bchb:note&#039;&#039; - Invokes the &#039;&#039;bowcontrolharmonicbase-&#039;&#039;command with the first &#039;&#039;parameter&#039;&#039; set to the &#039;&#039;variable note&#039;&#039;. &lt;br /&gt;
# &#039;&#039;bmr:1&#039;&#039; - Sets the &#039;&#039;bowmotorrun&#039;&#039;-command to &#039;1&#039;, starting the &#039;&#039;bow motor&#039;&#039;&lt;br /&gt;
# &#039;&#039;bpid:1&#039;&#039; - Sets the &#039;&#039;bowpid&#039;&#039;-command to &#039;1&#039;, making sure the &#039;&#039;PID&#039;&#039; is used&lt;br /&gt;
# &#039;&#039;bpe:1&#039;&#039; - Sets the &#039;&#039;bowpressureengage&#039;&#039; to &#039;1&#039; which moves the &#039;&#039;bowing jack&#039;&#039; to the &#039;&#039;engage position&#039;&#039;&lt;br /&gt;
# &#039;&#039;se:(velocity*512)*(1-notecount)&#039;&#039; - Executes the &#039;&#039;solenoidengage&#039;&#039;-command with the value &#039;&#039;(velocity*512)*(1-notecount)&#039;&#039;&lt;br /&gt;
# &#039;&#039;bcsm:0&#039;&#039; - Sets the &#039;&#039;bowcontrolspeedmode&#039;&#039; to &#039;1&#039; which enables automatic shut down of the &#039;&#039;bowing motor&#039;&#039;&lt;br /&gt;
The first two &#039;&#039;commands&#039;&#039; are the &#039;&#039;module&#039;&#039;- and &#039;&#039;bow-&#039;&#039;command. These &#039;&#039;commands&#039;&#039; are is intended for future versions of the Ekdahl FAR that may contain more than one string or more than one bow per string. For now &#039;&#039;0&#039;&#039; is the only valid &#039;&#039;parameter&#039;&#039; value that will be accepted for either &#039;&#039;command&#039;&#039;.&#039;&#039;&amp;lt;nowiki/&amp;gt;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;bowcontrolharmonicbase&#039;&#039;-command sets the speed of the &#039;&#039;bowing wheel&#039;&#039; to its corresponding &#039;&#039;harmonic number&#039;&#039; but also takes into account its &#039;&#039;&amp;lt;nowiki/&amp;gt;&#039;base&#039;&#039;&#039; which is the &#039;&#039;MIDI key&#039;&#039; that is mapped to &#039;&#039;harmonic number 0&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
After this the bowing motor is started and the &#039;&#039;PID&#039;&#039; is turned, now the instrument will try and make sure that the &#039;&#039;bowing wheel&#039;&#039; is at the right speed.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;bowing jack&#039;&#039; is raised to the &#039;&#039;engage position&#039;&#039;, any added &#039;&#039;pressure modifiers&#039;&#039; will also be taken into account - once the &#039;&#039;bowing jack&#039;&#039; has reached its intended position the &#039;&#039;bowing wheel&#039;&#039; should (hopefully) make contact with the string and the Ekdahl FAR will start to produce sounds.&lt;br /&gt;
&lt;br /&gt;
After this we have the &#039;&#039;solenoidengage&#039;&#039;-command &#039;&#039;command&#039;&#039; that engages the &#039;&#039;hammer&#039;&#039; and uses the first and only &#039;&#039;parameter&#039;&#039; as the force used. Like with most &#039;&#039;commands&#039;&#039; the &#039;&#039;se&#039;&#039;-command is 16-bit (0 - 65535) but the &#039;&#039;MIDI velocity variable&#039;&#039; is 7-bit (0 - 127), so to get the &#039;&#039;velocity&#039;&#039; variable to cover the entire range it needs to be multiplied with 512. &lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&amp;lt;nowiki/&amp;gt;&#039;*(1-notecount)&#039;&#039;&#039;-part is a way of making sure that we are using &#039;&#039;legato&#039;&#039; mode, i.e. that the &#039;&#039;hammer&#039;&#039; is not triggered if a key is already held down when a new key is pressed. The &#039;&#039;notecount&#039;&#039;-variable contains the number of &#039;&#039;MIDI&#039;&#039; notes currently held down. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s postulate that the Ekdahl FAR is tuned to a &#039;C&#039; at 65.4Hz and has its &#039;&#039;base&#039;&#039; set to middle &#039;C&#039; (&#039;&#039;MIDI key&#039;&#039; no 36). We are using the equal-temperament 12-tone scale and the Ekdahl FAR is set to respond to &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; &#039;&#039;MIDI channels&#039;&#039; (omni). Without having previously held any keys we press the middle &#039;C&#039; (&#039;&#039;note&#039;&#039; value 36) as hard as possible (&#039;&#039;velocity&#039;&#039; value &#039;&#039;127&#039;&#039;) on &#039;&#039;MIDI channel&#039;&#039; number 1 (&#039;&#039;channel&#039;&#039; value of 0). The Ekdahl FAR will get a &#039;&#039;note on MIDI message&#039;&#039; sent to it and from our mapping it will create the following &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;[irq]mev:noteon:&#039;m:0,b:0,bchb:36,bmr:1,bpid:1,bpe:1,se:(127*512)*(1-0),bcsm:0&#039;&amp;lt;/pre&amp;gt;What has happened here is that all &#039;&#039;variables&#039;&#039; have been replaced with the values sent by the &#039;&#039;MIDI message&#039;&#039;. Since those &#039;&#039;commands&#039;&#039; that doesn&#039;t have any &#039;&#039;variables&#039;&#039; with them will execute just as previously, only those &#039;&#039;commands&#039;&#039; whos &#039;&#039;parameters&#039;&#039; have changed will be explained:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;bchb: 36&#039;&#039; - The &#039;&#039;bowcontrolharmonicbase&#039;&#039; gets a value of &#039;&#039;36&#039;&#039; (middle &#039;C&#039;), because &#039;&#039;harmonic number 0&#039;&#039; is mapped to this key it will set the &#039;&#039;bowing wheel&#039;&#039; frequency to the &#039;&#039;fundamental&#039;&#039;; &#039;&#039;65.4&#039;&#039; Hertz&lt;br /&gt;
# &#039;&#039;se: (127*512)*(1-0)&#039;&#039; - the value of &#039;&#039;127&#039;&#039; comes from the &#039;&#039;velocity&#039;&#039;-variable, &#039;&#039;127 * 512 = 65024&#039;&#039; which is awfully close to a maximum hammer force of 65535. Since no previous notes were held down &#039;&#039;notecount&#039;&#039;  is equal to &#039;&#039;0&#039;&#039; and thus &#039;&#039;65024 * 1 = 65024&#039;&#039;. The hammer is engaged with near maximum force.&lt;br /&gt;
So the result is that we have set the speed of the &#039;&#039;bowing motor&#039;&#039; and we have engaged the &#039;&#039;hammer&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Now imagine that without releasing this key, we press another &#039;C&#039; one octave above but at half the velocity. The Ekdahl FAR creates the following &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
[irq]mev:noteon:&#039;m:0,b:0,bchb:48,bmr:1,bpid:1,bpe:1,se:(63*512)*(1-1),bcsm:0&#039;&lt;br /&gt;
&amp;lt;/pre&amp;gt;Now we can see that the &#039;&#039;note&#039;&#039; variable is &#039;&#039;48&#039;&#039; because the &#039;C&#039; one octave up is exactly 12 keys above the first, the &#039;&#039;velocity&#039;&#039; variable has changed to &#039;&#039;63&#039;&#039; since we hit it with a lighter touch - and because we are &amp;lt;u&amp;gt;still holding the first key down&amp;lt;/u&amp;gt; &#039;&#039;notecount&#039;&#039; is equal to &#039;&#039;1&#039;&#039;. Here&#039;s what happens&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;bchb: 48&#039;&#039; - Due to the &#039;&#039;base&#039;&#039; being set to &#039;&#039;36&#039;&#039; the &#039;&#039;harmonic number&#039;&#039; is set to &#039;&#039;48 - 36 = 12&#039;&#039;. Because we are using a 12-tone scale &#039;&#039;harmonic number 12&#039;&#039; is exactly one octave above the &#039;&#039;fundamental&#039;&#039; thus the speed of the &#039;&#039;bowing wheel&#039;&#039; is set to &#039;&#039;65.4 * 2 = 130.8&#039;&#039; Hertz.&lt;br /&gt;
# &#039;&#039;se: (63*512)*(1-1)&#039;&#039; - So &#039;&#039;63 * 512 = 32256&#039;&#039; and &#039;&#039;1 - 1 = 0&#039;&#039; thus &#039;&#039;32256 * 0 = 0&#039;&#039;. When the &#039;&#039;solenoidengage&#039;&#039;-command gets a &#039;&#039;parameter&#039;&#039; of &#039;&#039;0&#039;&#039; it will not engage the &#039;&#039;hammer&#039;&#039; - so the &#039;&#039;hammer&#039;&#039; doesn&#039;t strike&lt;br /&gt;
So it can be seen that with quite rudimentary math we can accomplish a whole lot of things here. Note also that even though the &#039;&#039;note on MIDI message&#039;&#039; also sets the &#039;&#039;channel&#039;&#039;-variable we never use it in this example - plenty of opportunity to make something weird happen depending on the &#039;&#039;MIDI channel&#039;&#039;!&lt;br /&gt;
&lt;br /&gt;
== CV Mapping ==&lt;br /&gt;
&#039;&#039;CV Mapping&#039;&#039; works exactly like the &#039;&#039;MIDI mapping&#039;&#039; with the difference that the command for setting the &#039;&#039;CV mapping&#039;&#039; is different and that &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; events pertaining to this &amp;lt;u&amp;gt;only&amp;lt;/u&amp;gt; change the &#039;&#039;value&#039;&#039;-variable. The &#039;&#039;command&#039;&#039; for changing the &#039;&#039;CV mapping&#039;&#039; is &#039;&#039;adccommandmap&#039;&#039; or &#039;&#039;acm&#039;&#039;, it take two &#039;&#039;parameters&#039;&#039;; &#039;&#039;channel&#039;&#039; and &#039;&#039;command string&#039;&#039;. We retrieve the &#039;&#039;command string&#039;&#039; for channel &#039;&#039;0&#039;&#039; which reads the sum of the &#039;&#039;harm. v/oct&#039;&#039;-jack and the &#039;&#039;harmonic&#039;&#039;-knob by sending a command of&amp;lt;pre&amp;gt;&lt;br /&gt;
rqi:acm:0&lt;br /&gt;
&amp;lt;/pre&amp;gt;The &amp;lt;u&amp;gt;default&amp;lt;/u&amp;gt; response will be something like&lt;br /&gt;
&amp;lt;pre&amp;gt;[irq]acm:0:&#039;bcha:value/1327.716667-20&#039;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{docnav&lt;br /&gt;
|[[The Ekdahl FAR - Service|Service]]&lt;br /&gt;
|[[The Ekdahl FAR - Command reference|Command reference]]&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Knaadmin</name></author>
	</entry>
	<entry>
		<id>http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_language&amp;diff=1645</id>
		<title>The Ekdahl FAR - Command language</title>
		<link rel="alternate" type="text/html" href="http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_language&amp;diff=1645"/>
		<updated>2026-06-07T17:24:28Z</updated>

		<summary type="html">&lt;p&gt;Knaadmin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Command language ==&lt;br /&gt;
The Ekdahl FAR is entirely controlled by &#039;&#039;commands&#039;&#039;, these &#039;&#039;commands&#039;&#039; decide everything that the instrument is doing, whether it is playing a melody or changing an internal parameter. &lt;br /&gt;
&lt;br /&gt;
When a &#039;&#039;MIDI message&#039;&#039; is received or a new CV / knob value is read, the &#039;&#039;commands&#039;&#039; associated with it will be internally sent. This can be things like &amp;quot;engage hammer&amp;quot; or &amp;quot;set the fundamental frequency&amp;quot; etc. &lt;br /&gt;
&lt;br /&gt;
Some of the available &#039;&#039;commands&#039;&#039; are mainly used for calibrating and setting up the instrument and are usually saved into the instruments memory, these will be executed whenever the instrument is turned on. &lt;br /&gt;
&lt;br /&gt;
All &#039;&#039;commands&#039;&#039; can be manually invoked via &#039;&#039;USB-Serial&#039;&#039;, in conjunction with certain software this presents an unprecedented level of control and sequenceability.&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
The &#039;&#039;commands&#039;&#039; are invoked using a &#039;&#039;plain text approach&#039;&#039;, all commands have both a &#039;&#039;long name&#039;&#039; and a &#039;&#039;short name&#039;&#039; which are interchangeable. A &#039;&#039;command&#039;&#039; may have one or more &#039;&#039;parameters&#039;&#039; associated with it, these &#039;&#039;parameters&#039;&#039; can be of different types; 16-bit numbers (values 0 - 65535 or -32767 - 32767), floating point numbers (values with decimals), booleans (0 for &#039;false&#039;, 1 for &#039;true&#039;) and strings (text). Some commands are &#039;&#039;conditional&#039;&#039;, meaning they will only execute if a parameter equates to &#039;1&#039; (&#039;true&#039;). &lt;br /&gt;
&lt;br /&gt;
The way &#039;&#039;commands&#039;&#039; are written in order to be executed is &#039;&#039;commandname:parameter1:parameter2:parameter3 [etc]&#039;&#039;, several commands be executed in sequence by separating them with a comma (&#039;,&#039;), a bunch of commands strung together is called a &#039;&#039;command string&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Since version 1.1 of the Ekdahl FAR Firmware, all commands are grouped in a hierarchical fashion according to their &#039;&#039;modules&#039;&#039; and each ladder in the hierarchy is separated by a period (&amp;quot;.&amp;quot;), this works very much like folders or directories in a regular computer. Every &#039;&#039;module&#039;&#039; can contain both &#039;&#039;commands&#039;&#039; and other &#039;&#039;modules&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
For instance, everything associated with the &#039;&#039;bowing wheel&#039;&#039; is now collected under &amp;quot;bowingwheel&amp;quot; &#039;&#039;module&#039;&#039;. That in turn contains a &amp;quot;dcmotor&amp;quot; &#039;&#039;module&#039;&#039; which does direct control of the bowing motor, and it has a &amp;quot;pid&amp;quot; &#039;&#039;module&#039;&#039; that handles bow frequency.&lt;br /&gt;
&lt;br /&gt;
If for instance we would like to start the &#039;&#039;bowing wheel&#039;&#039; and set its frequency to 82.5 Hertz we could send the Ekdahl FAR the following &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
bowmotorrun:1, bowcontrolfrequecy:82.5&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bowingwheel.dcmotor.run:1, bowingwheel.pid.targetfrequency:82.5&amp;lt;/pre&amp;gt;We could also use the &#039;&#039;short names&#039;&#039; for the commands&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
bmr:1,bcf:82.5&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bw.dcm.ru:1, bw.pid.tf:82.5&amp;lt;/pre&amp;gt;Both &#039;&#039;bowmotorrun&#039;&#039; / &#039;&#039;bowingwheel.dcmotor.run&#039;&#039; and &#039;&#039;bowcontrolfrequency / bowingwheel.pid.targetfrequency&#039;&#039; takes one &#039;&#039;parameter&#039;&#039; each, &#039;&#039;bowmotorrun / bowingwheel.dcmotor.run&#039;&#039; is &#039;&#039;conditional&#039;&#039; and unless the first &#039;&#039;parameter&#039;&#039; is equal to &#039;1&#039; the motor will not start. The first &#039;&#039;parameter&#039;&#039; of &#039;&#039;bowcontrolfrequency / bowingwheel.pid.targetfrequency&#039;&#039; sets the frequency of the &#039;&#039;bowing wheel&#039;&#039;, the instrument may not execute a &#039;&#039;command&#039;&#039; if it decides that the given &#039;&#039;parameters&#039;&#039; are outside of the working range or they are missing.&lt;br /&gt;
&lt;br /&gt;
The addition of the hierarchy in the FAR 1.1 firmware isn&#039;t just to be able to group commands, but it&#039;s also to make the FAR not limited to a single set of &#039;&#039;modules&#039;&#039; (and is the first stepping stone to a &#039;&#039;modular&#039;&#039; Ekdahl FAR). In fact, you could have 12 different bowing wheel &#039;&#039;modules&#039;&#039; for 12 different strings, these would then be addressed as &#039;&#039;bowingwheel[0].command, bowingwheel[1].command&#039;&#039; etc. Anyone familiar with C programming notices that this is the standard way of &#039;&#039;indexing&#039;&#039; an array; using brackets (&amp;quot;[ ]&amp;quot;). When addressing a module without &#039;&#039;indexing&#039;&#039; as above, the FAR will do one or two things; either use the first object (&amp;quot;[0]&amp;quot;) or, if the object is &#039;&#039;selectable&#039;&#039; it will use the previously selected object. To make things smoother a command can be executed on several objects at once by using ranges (&amp;quot;[0-4]&amp;quot;) and comma separation (&amp;quot;[0, 3, 5-6]&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
To test out a &#039;&#039;command&#039;&#039; you can send it directly to the Ekdahl FAR using the &#039;&#039;Console&#039;&#039; in the &#039;&#039;Configuration utility&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
To read up on existing &#039;&#039;commands&#039;&#039;, their &#039;&#039;parameters&#039;&#039; and a brief description you can check the &#039;&#039;Command reference&#039;&#039; in the &#039;&#039;Configuration utility&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Variables, functions and equations ==&lt;br /&gt;
What makes the &#039;&#039;Command language&#039;&#039; truly powerful is the concept of &#039;&#039;variables, functions&#039;&#039; and &#039;&#039;equations&#039;&#039;. All &#039;&#039;parameters&#039;&#039; that take numerical values can use any combination of &#039;&#039;variables, functions&#039;&#039; or &#039;&#039;equations.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
For instance, we can use the previous example and instead write our &#039;&#039;command string&#039;&#039; as follows&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
bowmotorrun:1, bowcontrolfrequency:82.5+note*20&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bowingwheel.dcmotor.run:1, bowingwheel.pid.targetfrequency:82.5+note*20&amp;lt;/pre&amp;gt;This example requires of course that the &#039;&#039;variable&#039;&#039; &#039;&#039;note&#039;&#039; exists in the current context. &lt;br /&gt;
&lt;br /&gt;
===== Variables =====&lt;br /&gt;
There are two types of &#039;&#039;variables&#039;&#039; in the Ekdahl FAR; &#039;&#039;global variables&#039;&#039; and &#039;&#039;event variables&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Global variables&#039;&#039; are variables that are always available and will exist in any context. The &#039;&#039;global variables&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;notecount&#039;&#039;&#039; - Contains the number of &#039;&#039;MIDI&#039;&#039; keys that are being held down, i.e. all &#039;&#039;Note on messages&#039;&#039; received that haven&#039;t gotten a paired &#039;&#039;Note off message&#039;&#039; yet&lt;br /&gt;
* &#039;&#039;&#039;uv0&#039;&#039;&#039; - &#039;&#039;&#039;uv9&#039;&#039;&#039; - These are &#039;&#039;user variables&#039;&#039; and can be set at any point using the &#039;&#039;globaluservariable command&#039;&#039; with the first &#039;&#039;parameter&#039;&#039; being which variable to set (0-9) and the second &#039;&#039;parameter&#039;&#039; being the value (float).&lt;br /&gt;
* &#039;&#039;&#039;e&#039;&#039;&#039; - Contains the constant &#039;&#039;[[wikipedia:E_(mathematical_constant)|e]]&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pi&#039;&#039;&#039; - Contains the constant &#039;&#039;[[wikipedia:Pi|pi]]&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Event variables&#039;&#039; are variables that are set by certain &#039;&#039;MIDI messages&#039;&#039; or when a new value is read on one of the jacks or knobs on the &#039;&#039;Control box&#039;&#039;. The &#039;&#039;Event variables&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;channel&#039;&#039;&#039; - Set by the &#039;&#039;Note on, Note off, Continuous Controller, Poly after touch, Pitch bend, Channel after touch&#039;&#039; and &#039;&#039;Program change MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;note&#039;&#039;&#039; - Set by the &#039;&#039;Note on, Note off&#039;&#039; and &#039;&#039;Poly after touch MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;velocity&#039;&#039;&#039; - Set by the &#039;&#039;Note on&#039;&#039; and &#039;&#039;Note off MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pressure&#039;&#039;&#039; - Set by the &#039;&#039;Poly after touch&#039;&#039; and &#039;&#039;Channel after touch MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; - Set by the &#039;&#039;Continuous Controller MIDI message&#039;&#039; and by the &#039;&#039;Control box&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pitch&#039;&#039;&#039; - Set by the &#039;&#039;Pitch bend MIDI message&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;program&#039;&#039;&#039; - Set by the &#039;&#039;Program change MIDI message&#039;&#039;&lt;br /&gt;
These variables will contain whatever data is relevant to the &amp;lt;u&amp;gt;last midi message sent&amp;lt;/u&amp;gt; and will not stay relevant beyond the reception of the last message.&lt;br /&gt;
&lt;br /&gt;
===== Functions =====&lt;br /&gt;
&#039;&#039;Functions&#039;&#039; can be used to change a numerical value or the result of an &#039;&#039;equation&#039;&#039;, the Ekdahl FAR contains both general &#039;&#039;arithmetic functions&#039;&#039; (courtesy of Lewis Van Winkle and the TINYEXPR engine) and &#039;&#039;specialized functions&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;arithmetic functions&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;abs&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Absolute_value|absolute value]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;acos&#039;&#039;&#039;(x), &#039;&#039;&#039;asin&#039;&#039;&#039;(x), &#039;&#039;&#039;atan&#039;&#039;&#039;(x), atan2(x, y) - Returns the [[wikipedia:Inverse_trigonometric_functions|&#039;&#039;arc-cos, -sin, -tan&#039;&#039; and &#039;&#039;-tan2&#039;&#039;]] of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;atan2&#039;&#039;&#039;(x,y) - Returns the &#039;&#039;[[wikipedia:Atan2|arctan2]]&#039;&#039; of &#039;&#039;x, y&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;floor&#039;&#039;&#039;(x), ceil(x) - Returns the [[wikipedia:Floor_and_ceiling_functions|&#039;&#039;floor&#039;&#039; and &#039;&#039;ceiling&#039;&#039;]] of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;exp&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Exponential_function|exponent]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;fac&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Factorial|factorial]]&#039;&#039; of x&lt;br /&gt;
* &#039;&#039;&#039;ln&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Natural_logarithm|natural logarithm]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;log10&#039;&#039;&#039;(x), &#039;&#039;&#039;log20&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Logarithm|logarithm]]&#039;&#039; of &#039;&#039;x&#039;&#039; using base 10 and 20 respectively&lt;br /&gt;
* &#039;&#039;&#039;ncr&#039;&#039;&#039;(x,y), &#039;&#039;&#039;npr&#039;&#039;&#039;(x,y) - Functions to calculate &#039;&#039;[[wikipedia:Combination|combinations]]&#039;&#039; and &#039;&#039;[[wikipedia:Permutation|permutations]]&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pow&#039;&#039;&#039;(x,y) - Returns &#039;&#039;x^y&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;sqrt&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Square_root|square root]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;cos&#039;&#039;&#039;(x), &#039;&#039;&#039;sin&#039;&#039;&#039;(x), &#039;&#039;&#039;tan&#039;&#039;&#039;(x) - Returns the [[wikipedia:Trigonometric_functions|&#039;&#039;cos, sin&#039;&#039; and &#039;&#039;tan&#039;&#039;]] of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;cosh&#039;&#039;&#039;(x), &#039;&#039;&#039;sinh&#039;&#039;&#039;(x), &#039;&#039;&#039;tanh&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Hyperbolic_functions|hyperbolic cos, sin and tan]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
The &#039;&#039;specialized functions&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;bool&#039;&#039;&#039;(x) - Returns 1 if &#039;&#039;x&#039;&#039; is more than 0&lt;br /&gt;
* &#039;&#039;&#039;ibool&#039;&#039;&#039;(x) - Returns 0 if &#039;&#039;x&#039;&#039; is more than 0&lt;br /&gt;
* &#039;&#039;&#039;deadband&#039;&#039;&#039;(x,y) - Returns &#039;&#039;x + y &#039;&#039; if &#039;&#039;x &amp;lt; y&#039;&#039; or &#039;&#039;x - y&#039;&#039; if &#039;&#039;x &amp;gt; y&#039;&#039;. If neither of these statements is true it returns &#039;&#039;0&#039;&#039; - used to create a [[wikipedia:Deadband|deadband]] of &#039;&#039;x&#039;&#039; with the threshold of &#039;&#039;y&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Functions&#039;&#039; can be readily used in a &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
bowmotorrun:1, bowcontrolfrequency:&amp;quot;8.17579875 * pow(2, (1/12 * note))&amp;quot;&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bowingwheel.dcmotor.run:1, bowingwheel.pid.targetfrequency:&amp;quot;8.17579875 * pow(2, (1/12 * note))&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;The previous statements starts the &#039;&#039;bowing wheel&#039;&#039; and sets the frequency of the wheel to &#039;&#039;8.17579875 * 2^(1/12 * note)&#039;&#039;. A middle &#039;C&#039; according to &#039;&#039;MIDI&#039;&#039; has a &#039;&#039;note value&#039;&#039; of 36, meaning if we substitute &#039;&#039;note&#039;&#039; with 36 we get the equation &#039;&#039;8.17579875 * 2^(1/12 * 36)&#039;&#039; which comes out to &#039;&#039;~65.4&#039;&#039; Hertz.&lt;br /&gt;
&lt;br /&gt;
Note that the first &#039;&#039;parameter&#039;&#039; for &#039;&#039;bowcontrolfrequency / bowingwheel.pid.targetfrequency&#039;&#039; is put in between double quotes (&amp;quot;). This is because the &#039;&#039;pow&#039;&#039;-function requires the use of a comma (&amp;quot;,&amp;quot;) in order to separate in between its two required inputs; &#039;&#039;x&#039;&#039; and &#039;&#039;y&#039;&#039;. In order for the Ekdahl FAR to know that this comma does not signal the beginning of a new &#039;&#039;command,&#039;&#039; we use quotes. Single (&#039;) and double (&amp;quot;) quotes can be used and nested in all &#039;&#039;parameters&#039;&#039; and are &amp;lt;u&amp;gt;required&amp;lt;/u&amp;gt; in a lot of circumstances, improper nesting or not using quotes can lead to the instrument not understanding the &#039;&#039;command string&#039;&#039; correctly.&lt;br /&gt;
&lt;br /&gt;
== Return messages ==&lt;br /&gt;
The Ekdahl FAR when connected via &#039;&#039;USB-Serial&#039;&#039; doesn&#039;t only accept &#039;&#039;commands&#039;&#039; but will also send various &#039;&#039;return messages&#039;&#039;. These are prefixed by their &#039;&#039;category&#039;&#039; denoted in brackets (&amp;quot;[]&amp;quot;), the existing categories as of this writing (2025-01-22) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;command&#039;&#039;&#039; / &#039;&#039;&#039;cmd&#039;&#039;&#039; - Acknowledges the reception of a command in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;usb&#039;&#039;&#039; - Acknowledges the reception of a &#039;&#039;MIDI message&#039;&#039; over &#039;&#039;USB&#039;&#039; in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;hardware&#039;&#039;&#039; / &#039;&#039;&#039;hw&#039;&#039;&#039; - Signals that a change has been sent to the Ekdahl FAR hardware, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;undefined&#039;&#039;&#039; / &#039;&#039;&#039;un&#039;&#039;&#039; - The message sent is in the &#039;&#039;undefined&#039;&#039; category, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;priority&#039;&#039;&#039; / &#039;&#039;&#039;pri&#039;&#039;&#039; - The message sent is in the &#039;&#039;priority&#039;&#039; category, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;error&#039;&#039;&#039; / &#039;&#039;&#039;err&#039;&#039;&#039; - Signals that an &#039;&#039;error&#039;&#039; has occurred, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;expressionparser&#039;&#039;&#039; / &#039;&#039;&#039;ep&#039;&#039;&#039; - These messages contains debugging information regarding the internal &#039;&#039;expression parser&#039;&#039; and is used for development&lt;br /&gt;
*&#039;&#039;&#039;debug&#039;&#039;&#039; / &#039;&#039;&#039;dbg&#039;&#039;&#039; - These messages contains various debugging information and is used for development&lt;br /&gt;
*&#039;&#039;&#039;help&#039;&#039;&#039; / &#039;&#039;&#039;hlp&#039;&#039;&#039; - Signals that the message is a response to a &#039;&#039;help&#039;&#039;-command being sent to the Ekdahl FAR. These messages are structured so that a receiver, like the &#039;&#039;Configuration utility&#039;&#039;, can parse information about available &#039;&#039;commands&#039;&#039; in the current &#039;&#039;firmware&#039;&#039; and relay it to a user in a structured way.&lt;br /&gt;
* &#039;&#039;&#039;inforequest&#039;&#039;&#039; / &#039;&#039;&#039;irq&#039;&#039;&#039; - Signals that an &#039;&#039;info request&#039;&#039; has been returned. This is a specialized message that is either sent as a response to an &#039;&#039;rqi&#039;&#039;-command or as a &#039;&#039;interrupt&#039;&#039;-message telling the user or receiving software about different parameters in the Ekdahl FAR. These messages follows the same structure as regular &#039;&#039;command message&#039;&#039;s of &#039;&#039;[irq]commandname:parameter1 [etc]&#039;&#039; so that it can be used by a receiving software to keep track of parameter changes&lt;br /&gt;
&lt;br /&gt;
===== Explicitly requesting information =====&lt;br /&gt;
By using the special command &#039;&#039;requestinfo / rqi&#039;&#039; one can request the information stored by a certain &#039;&#039;command&#039;&#039; or a state of the Ekdahl FAR. The &#039;&#039;rqi&#039;&#039;-command is executed in the convention &#039;&#039;rqi:commandname[:optional parameters]&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
To go back to our example of setting the bowing frequency using the &#039;&#039;bowcontrolfrequency&#039;&#039;-command we can ask the Ekdahl FAR what the bowing frequency is set to by writing&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
rqi:bowcontrolfrequency&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
rqi:bowingwheel.pid.targetfrequency&lt;br /&gt;
&amp;lt;/pre&amp;gt;The return value would be something like&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
[irq]bcf:82.5&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
[irq]bw[0].pid[0].tf:82.5&lt;br /&gt;
&amp;lt;/pre&amp;gt;Where &#039;[irq]&#039; denotes that the message returned is in the &#039;&#039;info request-&#039;&#039;category, that it pertains to the command &#039;&#039;bcf&#039;&#039; and has the value &#039;&#039;82.5&#039;&#039;. Note that the returned &#039;&#039;command&#039;&#039; sent by an &#039;&#039;rqi&#039;&#039;-command always uses the &#039;&#039;short name&#039;&#039; in order to preserve bandwidth.&lt;br /&gt;
&lt;br /&gt;
Most commands do not require any &#039;&#039;parameters&#039;&#039; when using the &#039;&#039;rqi&#039;&#039;-command. The &#039;&#039;adcread&#039;&#039;-command is an example of a &#039;&#039;command&#039;&#039; that &amp;lt;u&amp;gt;does&amp;lt;/u&amp;gt; require a &#039;&#039;parameter&#039;&#039; when used with &#039;&#039;rqi&#039;&#039;. The &#039;&#039;adcread&#039;&#039; command returns the last value read by the &#039;&#039;analog-to-digital converter&#039;&#039; in the &#039;&#039;Control box&#039;&#039;, because there are 8 different channels the first &#039;&#039;parameter&#039;&#039; sets which channel to return the data for, hence executing the &#039;&#039;command&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
rqi:adcr:3&lt;br /&gt;
&amp;lt;/pre&amp;gt;will return the last data read on &#039;&#039;analog-to-digital convert&#039;&#039; channel 3.&lt;br /&gt;
&lt;br /&gt;
== MIDI mapping ==&lt;br /&gt;
To change how a certain &#039;&#039;MIDI message&#039;&#039; interacts with the Ekdahl FAR we need to change the &#039;&#039;commands&#039;&#039; or &#039;&#039;parameters&#039;&#039; sent when the message is received. The &#039;&#039;command&#039;&#039; responsible for mapping &#039;&#039;command strimgs&#039;&#039; to different &#039;&#039;MIDI messages&#039;&#039; is &#039;&#039;midieventhandler&#039;&#039; or &#039;&#039;mev&#039;&#039; for short. The first &#039;&#039;parameter&#039;&#039; of &#039;&#039;mev&#039;&#039; is the type of &#039;&#039;MIDI message&#039;&#039; that we want to remap&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;noteon&#039;&#039; - Note on&lt;br /&gt;
* &#039;&#039;noteoff -&#039;&#039; Note off&lt;br /&gt;
* &#039;&#039;pat -&#039;&#039; Poly after touch&lt;br /&gt;
* &#039;&#039;cat&#039;&#039; - Channel after touch&lt;br /&gt;
* &#039;&#039;pb&#039;&#039; - Pitch bend&lt;br /&gt;
* &#039;&#039;pc&#039;&#039; - Program change&lt;br /&gt;
* &#039;&#039;cc&#039;&#039; - Continuous controller&lt;br /&gt;
&lt;br /&gt;
The second &#039;&#039;parameter&#039;&#039; is the &#039;&#039;command string&#039;&#039; that is to be associated with the &#039;&#039;MIDI Message&#039;&#039; - with the exception of the &#039;&#039;cc&#039;&#039;-type, here the second &#039;&#039;parameter&#039;&#039; is the &#039;&#039;controller number&#039;&#039; (0 - 127) and the &amp;lt;u&amp;gt;third&amp;lt;/u&amp;gt; &#039;&#039;parameter&#039;&#039; is the &#039;&#039;command string&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
We can of course use the &#039;&#039;rqi&#039;&#039;-command to check the current mapping, below we are asking what the current &#039;&#039;command string&#039;&#039; associated with the &#039;&#039;pitch bend&#039;&#039; &#039;&#039;MIDI message&#039;&#039; is&amp;lt;pre&amp;gt;&lt;br /&gt;
rqi:mev:pb&lt;br /&gt;
&amp;lt;/pre&amp;gt;This may return something like&amp;lt;pre&amp;gt;&lt;br /&gt;
[irq]bchsh:pitch*4&lt;br /&gt;
&amp;lt;/pre&amp;gt;The return message tells us that the &#039;&#039;pitch bend MIDI message&#039;&#039; is executing a &#039;&#039;bchsh&#039;&#039;-command with the parameter &#039;&#039;pitch*4&#039;&#039;. Looking in the &#039;&#039;command reference&#039;&#039; we can see that &#039;&#039;bchsh&#039;&#039; is the &#039;&#039;short name&#039;&#039; of the &#039;&#039;bowcontrolharmonicshift&#039;&#039;-command which shifts the frequency of the &#039;&#039;bowing wheel&#039;&#039; from the current frequency, the first (and only) parameter sets how much we want to shift it (depends on the &#039;&#039;bowcontrolharmonicshiftrange command&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
If we look in the list of &#039;&#039;[[The Ekdahl FAR - Command langue#Variables|variables]]&#039;&#039; above we can see that the &#039;&#039;pitch bend MIDI message&#039;&#039; will set the &#039;&#039;pitch variable&#039;&#039; which is indeed used. Now what is the &#039;&#039;&#039;*4&#039;&#039;&amp;lt;nowiki/&amp;gt;&#039; all about? Well the &#039;&#039;bchsh&#039;&#039;-command expects a &#039;&#039;16-bit signed&#039;&#039; value, meaning that a full &#039;&#039;harmonic shift&#039;&#039; downwards is equal to -32767, a full &#039;&#039;harmonic shift&#039;&#039; upwards is 32767 and no &#039;&#039;harmonic shift&#039;&#039; is 0. The &#039;&#039;pitch bend MIDI message&#039;&#039; however is only 14-bits, meaning its range is -8192 to 8192, so in order to be able to use the entire range we have to multiply &#039;&#039;pitch&#039;&#039; by 4.&lt;br /&gt;
&lt;br /&gt;
This whole thing about number of bits can seem confusing but in the end it&#039;s all about how fine control you have over things; the more possible values, the more detailed control. In fact, most &#039;&#039;MIDI&#039;&#039; values are only 7-bit (!) meaning a range of 0 - 127. While this may sound like a lot of detail for something like a volume control, it is not even close to enough resolution to for instance set the &#039;&#039;bowing speed&#039;&#039;. Imagine that our lowest possible note frequency is 50 Hz, that means that with a 0-127 range we can only go from 50 Hz to 127 + 50 = 177 Hz - and with no decimals! This meager range and the very coarse steps of only 1 Hz would mean the instrument would never be able to sound in tune and wouldn&#039;t even have two octaves of range. The idea of limiting the Ekdahl FAR to what is possible through &#039;&#039;MIDI&#039;&#039; seemed like a poor choice thus it was decided that &amp;lt;u&amp;gt;most&amp;lt;/u&amp;gt; parameters will instead be 16-bit.&lt;br /&gt;
&lt;br /&gt;
Now lets look at a more complex example, the &amp;lt;u&amp;gt;default&amp;lt;/u&amp;gt; &#039;&#039;Note On MIDI message&#039;&#039;. On a stock Ekdahl FAR, executing&amp;lt;pre&amp;gt;&lt;br /&gt;
rqi:mev:noteon&lt;br /&gt;
&amp;lt;/pre&amp;gt;Will return something like&amp;lt;pre&amp;gt;[irq]mev:noteon:&#039;m:0,b:0,bchb:note,bmr:1,bpid:1,bpe:1,se:(velocity*512)*(1-notecount),bcsm:0&#039;&amp;lt;/pre&amp;gt;As can be seen, there&#039;s a lot of stuff going on here! First of all, notice that everything after &#039;&#039;mev:noteon:&#039;&#039; is situated in between single quotes (&#039;) - this is &amp;lt;u&amp;gt;absolutely crucial&amp;lt;/u&amp;gt; for the Ekdahl FAR to know that everything within those last two quotes is part of the last &#039;&#039;parameter&#039;&#039; of the &#039;&#039;mev&#039;&#039;-command.&lt;br /&gt;
&lt;br /&gt;
Now let&#039;s break down what happens when this &#039;&#039;MIDI message&#039;&#039; is received, i.e. when a &#039;&#039;MIDI&#039;&#039; key is pressed down:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;m:0&#039;&#039; - Sets &#039;&#039;module&#039;&#039; to 0&lt;br /&gt;
# &#039;&#039;b:0&#039;&#039; - Sets &#039;&#039;bow&#039;&#039; to 0&lt;br /&gt;
# &#039;&#039;bchb:note&#039;&#039; - Invokes the &#039;&#039;bowcontrolharmonicbase-&#039;&#039;command with the first &#039;&#039;parameter&#039;&#039; set to the &#039;&#039;variable note&#039;&#039;. &lt;br /&gt;
# &#039;&#039;bmr:1&#039;&#039; - Sets the &#039;&#039;bowmotorrun&#039;&#039;-command to &#039;1&#039;, starting the &#039;&#039;bow motor&#039;&#039;&lt;br /&gt;
# &#039;&#039;bpid:1&#039;&#039; - Sets the &#039;&#039;bowpid&#039;&#039;-command to &#039;1&#039;, making sure the &#039;&#039;PID&#039;&#039; is used&lt;br /&gt;
# &#039;&#039;bpe:1&#039;&#039; - Sets the &#039;&#039;bowpressureengage&#039;&#039; to &#039;1&#039; which moves the &#039;&#039;bowing jack&#039;&#039; to the &#039;&#039;engage position&#039;&#039;&lt;br /&gt;
# &#039;&#039;se:(velocity*512)*(1-notecount)&#039;&#039; - Executes the &#039;&#039;solenoidengage&#039;&#039;-command with the value &#039;&#039;(velocity*512)*(1-notecount)&#039;&#039;&lt;br /&gt;
# &#039;&#039;bcsm:0&#039;&#039; - Sets the &#039;&#039;bowcontrolspeedmode&#039;&#039; to &#039;1&#039; which enables automatic shut down of the &#039;&#039;bowing motor&#039;&#039;&lt;br /&gt;
The first two &#039;&#039;commands&#039;&#039; are the &#039;&#039;module&#039;&#039;- and &#039;&#039;bow-&#039;&#039;command. These &#039;&#039;commands&#039;&#039; are is intended for future versions of the Ekdahl FAR that may contain more than one string or more than one bow per string. For now &#039;&#039;0&#039;&#039; is the only valid &#039;&#039;parameter&#039;&#039; value that will be accepted for either &#039;&#039;command&#039;&#039;.&#039;&#039;&amp;lt;nowiki/&amp;gt;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;bowcontrolharmonicbase&#039;&#039;-command sets the speed of the &#039;&#039;bowing wheel&#039;&#039; to its corresponding &#039;&#039;harmonic number&#039;&#039; but also takes into account its &#039;&#039;&amp;lt;nowiki/&amp;gt;&#039;base&#039;&#039;&#039; which is the &#039;&#039;MIDI key&#039;&#039; that is mapped to &#039;&#039;harmonic number 0&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
After this the bowing motor is started and the &#039;&#039;PID&#039;&#039; is turned, now the instrument will try and make sure that the &#039;&#039;bowing wheel&#039;&#039; is at the right speed.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;bowing jack&#039;&#039; is raised to the &#039;&#039;engage position&#039;&#039;, any added &#039;&#039;pressure modifiers&#039;&#039; will also be taken into account - once the &#039;&#039;bowing jack&#039;&#039; has reached its intended position the &#039;&#039;bowing wheel&#039;&#039; should (hopefully) make contact with the string and the Ekdahl FAR will start to produce sounds.&lt;br /&gt;
&lt;br /&gt;
After this we have the &#039;&#039;solenoidengage&#039;&#039;-command &#039;&#039;command&#039;&#039; that engages the &#039;&#039;hammer&#039;&#039; and uses the first and only &#039;&#039;parameter&#039;&#039; as the force used. Like with most &#039;&#039;commands&#039;&#039; the &#039;&#039;se&#039;&#039;-command is 16-bit (0 - 65535) but the &#039;&#039;MIDI velocity variable&#039;&#039; is 7-bit (0 - 127), so to get the &#039;&#039;velocity&#039;&#039; variable to cover the entire range it needs to be multiplied with 512. &lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&amp;lt;nowiki/&amp;gt;&#039;*(1-notecount)&#039;&#039;&#039;-part is a way of making sure that we are using &#039;&#039;legato&#039;&#039; mode, i.e. that the &#039;&#039;hammer&#039;&#039; is not triggered if a key is already held down when a new key is pressed. The &#039;&#039;notecount&#039;&#039;-variable contains the number of &#039;&#039;MIDI&#039;&#039; notes currently held down. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s postulate that the Ekdahl FAR is tuned to a &#039;C&#039; at 65.4Hz and has its &#039;&#039;base&#039;&#039; set to middle &#039;C&#039; (&#039;&#039;MIDI key&#039;&#039; no 36). We are using the equal-temperament 12-tone scale and the Ekdahl FAR is set to respond to &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; &#039;&#039;MIDI channels&#039;&#039; (omni). Without having previously held any keys we press the middle &#039;C&#039; (&#039;&#039;note&#039;&#039; value 36) as hard as possible (&#039;&#039;velocity&#039;&#039; value &#039;&#039;127&#039;&#039;) on &#039;&#039;MIDI channel&#039;&#039; number 1 (&#039;&#039;channel&#039;&#039; value of 0). The Ekdahl FAR will get a &#039;&#039;note on MIDI message&#039;&#039; sent to it and from our mapping it will create the following &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;[irq]mev:noteon:&#039;m:0,b:0,bchb:36,bmr:1,bpid:1,bpe:1,se:(127*512)*(1-0),bcsm:0&#039;&amp;lt;/pre&amp;gt;What has happened here is that all &#039;&#039;variables&#039;&#039; have been replaced with the values sent by the &#039;&#039;MIDI message&#039;&#039;. Since those &#039;&#039;commands&#039;&#039; that doesn&#039;t have any &#039;&#039;variables&#039;&#039; with them will execute just as previously, only those &#039;&#039;commands&#039;&#039; whos &#039;&#039;parameters&#039;&#039; have changed will be explained:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;bchb: 36&#039;&#039; - The &#039;&#039;bowcontrolharmonicbase&#039;&#039; gets a value of &#039;&#039;36&#039;&#039; (middle &#039;C&#039;), because &#039;&#039;harmonic number 0&#039;&#039; is mapped to this key it will set the &#039;&#039;bowing wheel&#039;&#039; frequency to the &#039;&#039;fundamental&#039;&#039;; &#039;&#039;65.4&#039;&#039; Hertz&lt;br /&gt;
# &#039;&#039;se: (127*512)*(1-0)&#039;&#039; - the value of &#039;&#039;127&#039;&#039; comes from the &#039;&#039;velocity&#039;&#039;-variable, &#039;&#039;127 * 512 = 65024&#039;&#039; which is awfully close to a maximum hammer force of 65535. Since no previous notes were held down &#039;&#039;notecount&#039;&#039;  is equal to &#039;&#039;0&#039;&#039; and thus &#039;&#039;65024 * 1 = 65024&#039;&#039;. The hammer is engaged with near maximum force.&lt;br /&gt;
So the result is that we have set the speed of the &#039;&#039;bowing motor&#039;&#039; and we have engaged the &#039;&#039;hammer&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Now imagine that without releasing this key, we press another &#039;C&#039; one octave above but at half the velocity. The Ekdahl FAR creates the following &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
[irq]mev:noteon:&#039;m:0,b:0,bchb:48,bmr:1,bpid:1,bpe:1,se:(63*512)*(1-1),bcsm:0&#039;&lt;br /&gt;
&amp;lt;/pre&amp;gt;Now we can see that the &#039;&#039;note&#039;&#039; variable is &#039;&#039;48&#039;&#039; because the &#039;C&#039; one octave up is exactly 12 keys above the first, the &#039;&#039;velocity&#039;&#039; variable has changed to &#039;&#039;63&#039;&#039; since we hit it with a lighter touch - and because we are &amp;lt;u&amp;gt;still holding the first key down&amp;lt;/u&amp;gt; &#039;&#039;notecount&#039;&#039; is equal to &#039;&#039;1&#039;&#039;. Here&#039;s what happens&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;bchb: 48&#039;&#039; - Due to the &#039;&#039;base&#039;&#039; being set to &#039;&#039;36&#039;&#039; the &#039;&#039;harmonic number&#039;&#039; is set to &#039;&#039;48 - 36 = 12&#039;&#039;. Because we are using a 12-tone scale &#039;&#039;harmonic number 12&#039;&#039; is exactly one octave above the &#039;&#039;fundamental&#039;&#039; thus the speed of the &#039;&#039;bowing wheel&#039;&#039; is set to &#039;&#039;65.4 * 2 = 130.8&#039;&#039; Hertz.&lt;br /&gt;
# &#039;&#039;se: (63*512)*(1-1)&#039;&#039; - So &#039;&#039;63 * 512 = 32256&#039;&#039; and &#039;&#039;1 - 1 = 0&#039;&#039; thus &#039;&#039;32256 * 0 = 0&#039;&#039;. When the &#039;&#039;solenoidengage&#039;&#039;-command gets a &#039;&#039;parameter&#039;&#039; of &#039;&#039;0&#039;&#039; it will not engage the &#039;&#039;hammer&#039;&#039; - so the &#039;&#039;hammer&#039;&#039; doesn&#039;t strike&lt;br /&gt;
So it can be seen that with quite rudimentary math we can accomplish a whole lot of things here. Note also that even though the &#039;&#039;note on MIDI message&#039;&#039; also sets the &#039;&#039;channel&#039;&#039;-variable we never use it in this example - plenty of opportunity to make something weird happen depending on the &#039;&#039;MIDI channel&#039;&#039;!&lt;br /&gt;
&lt;br /&gt;
== CV Mapping ==&lt;br /&gt;
&#039;&#039;CV Mapping&#039;&#039; works exactly like the &#039;&#039;MIDI mapping&#039;&#039; with the difference that the command for setting the &#039;&#039;CV mapping&#039;&#039; is different and that &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; events pertaining to this &amp;lt;u&amp;gt;only&amp;lt;/u&amp;gt; change the &#039;&#039;value&#039;&#039;-variable. The &#039;&#039;command&#039;&#039; for changing the &#039;&#039;CV mapping&#039;&#039; is &#039;&#039;adccommandmap&#039;&#039; or &#039;&#039;acm&#039;&#039;, it take two &#039;&#039;parameters&#039;&#039;; &#039;&#039;channel&#039;&#039; and &#039;&#039;command string&#039;&#039;. We retrieve the &#039;&#039;command string&#039;&#039; for channel &#039;&#039;0&#039;&#039; which reads the sum of the &#039;&#039;harm. v/oct&#039;&#039;-jack and the &#039;&#039;harmonic&#039;&#039;-knob by sending a command of&amp;lt;pre&amp;gt;&lt;br /&gt;
rqi:acm:0&lt;br /&gt;
&amp;lt;/pre&amp;gt;The &amp;lt;u&amp;gt;default&amp;lt;/u&amp;gt; response will be something like&lt;br /&gt;
&amp;lt;pre&amp;gt;[irq]acm:0:&#039;bcha:value/1327.716667-20&#039;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{docnav&lt;br /&gt;
|[[The Ekdahl FAR - Service|Service]]&lt;br /&gt;
|[[The Ekdahl FAR - Command reference|Command reference]]&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Knaadmin</name></author>
	</entry>
	<entry>
		<id>http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_language&amp;diff=1644</id>
		<title>The Ekdahl FAR - Command language</title>
		<link rel="alternate" type="text/html" href="http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_language&amp;diff=1644"/>
		<updated>2026-06-07T17:21:37Z</updated>

		<summary type="html">&lt;p&gt;Knaadmin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Command language ==&lt;br /&gt;
The Ekdahl FAR is entirely controlled by &#039;&#039;commands&#039;&#039;, these &#039;&#039;commands&#039;&#039; decide everything that the instrument is doing, whether it is playing a melody or changing an internal parameter. &lt;br /&gt;
&lt;br /&gt;
When a &#039;&#039;MIDI message&#039;&#039; is received or a new CV / knob value is read, the &#039;&#039;commands&#039;&#039; associated with it will be internally sent. This can be things like &amp;quot;engage hammer&amp;quot; or &amp;quot;set the fundamental frequency&amp;quot; etc. &lt;br /&gt;
&lt;br /&gt;
Some of the available &#039;&#039;commands&#039;&#039; are mainly used for calibrating and setting up the instrument and are usually saved into the instruments memory, these will be executed whenever the instrument is turned on. &lt;br /&gt;
&lt;br /&gt;
All &#039;&#039;commands&#039;&#039; can be manually invoked via &#039;&#039;USB-Serial&#039;&#039;, in conjunction with certain software this presents an unprecedented level of control and sequenceability.&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
The &#039;&#039;commands&#039;&#039; are invoked using a &#039;&#039;plain text approach&#039;&#039;, all commands have both a &#039;&#039;long name&#039;&#039; and a &#039;&#039;short name&#039;&#039; which are interchangeable. A &#039;&#039;command&#039;&#039; may have one or more &#039;&#039;parameters&#039;&#039; associated with it, these &#039;&#039;parameters&#039;&#039; can be of different types; 16-bit numbers (values 0 - 65535 or -32767 - 32767), floating point numbers (values with decimals), booleans (0 for &#039;false&#039;, 1 for &#039;true&#039;) and strings (text). Some commands are &#039;&#039;conditional&#039;&#039;, meaning they will only execute if a parameter equates to &#039;1&#039; (&#039;true&#039;). &lt;br /&gt;
&lt;br /&gt;
The way &#039;&#039;commands&#039;&#039; are written in order to be executed is &#039;&#039;commandname:parameter1:parameter2:parameter3 [etc]&#039;&#039;, several commands be executed in sequence by separating them with a comma (&#039;,&#039;), a bunch of commands strung together is called a &#039;&#039;command string&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Since version 1.1 of the Ekdahl FAR Firmware, all commands are grouped in a hierarchical fashion according to their &#039;&#039;modules&#039;&#039; and each ladder in the hierarchy is separated by a period (&amp;quot;.&amp;quot;), this works very much like folders or directories in a regular computer. Every &#039;&#039;module&#039;&#039; can contain both &#039;&#039;commands&#039;&#039; and other &#039;&#039;modules&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
For instance, everything associated with the &#039;&#039;bowing wheel&#039;&#039; is now collected under &amp;quot;bowingwheel&amp;quot; &#039;&#039;module&#039;&#039;. That in turn contains a &amp;quot;dcmotor&amp;quot; &#039;&#039;module&#039;&#039; which does direct control of the bowing motor, and it has a &amp;quot;pid&amp;quot; &#039;&#039;module&#039;&#039; that handles bow frequency.&lt;br /&gt;
&lt;br /&gt;
If for instance we would like to start the &#039;&#039;bowing wheel&#039;&#039; and set its frequency to 82.5 Hertz we could send the Ekdahl FAR the following &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
bowmotorrun:1, bowcontrolfrequecy:82.5&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bowingwheel.dcmotor.run:1, bowingwheel.pid.targetfrequency:82.5&amp;lt;/pre&amp;gt;We could also use the &#039;&#039;short names&#039;&#039; for the commands&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
bmr:1,bcf:82.5&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bw.dcm.ru:1, bw.pid.tf:82.5&amp;lt;/pre&amp;gt;Both &#039;&#039;bowmotorrun&#039;&#039; / &#039;&#039;bowingwheel.dcmotor.run&#039;&#039; and &#039;&#039;bowcontrolfrequency / bowingwheel.pid.targetfrequency&#039;&#039; takes one &#039;&#039;parameter&#039;&#039; each, &#039;&#039;bowmotorrun / bowingwheel.dcmotor.run&#039;&#039; is &#039;&#039;conditional&#039;&#039; and unless the first &#039;&#039;parameter&#039;&#039; is equal to &#039;1&#039; the motor will not start. The first &#039;&#039;parameter&#039;&#039; of &#039;&#039;bowcontrolfrequency / bowingwheel.pid.targetfrequency&#039;&#039; sets the frequency of the &#039;&#039;bowing wheel&#039;&#039;, the instrument may not execute a &#039;&#039;command&#039;&#039; if it decides that the given &#039;&#039;parameters&#039;&#039; are outside of the working range or they are missing.&lt;br /&gt;
&lt;br /&gt;
The addition of the hierarchy in the FAR 1.1 firmware isn&#039;t just to be able to group commands, but it&#039;s also to make the FAR not limited to a single set of &#039;&#039;modules&#039;&#039; (and is the first stepping stone to a &#039;&#039;modular&#039;&#039; Ekdahl FAR). In fact, you could have 12 different bowing wheel &#039;&#039;modules&#039;&#039; for 12 different strings, these would then be addressed as &#039;&#039;bowingwheel[0].command, bowingwheel[1].command&#039;&#039; etc. Anyone familiar with C programming notices that this is the standard way of &#039;&#039;indexing&#039;&#039; an array; using brackets (&amp;quot;[ ]&amp;quot;). When addressing a module without &#039;&#039;indexing&#039;&#039; as above, the FAR will do one or two things; either use the first object (&amp;quot;[0]&amp;quot;) or, if the object is &#039;&#039;selectable&#039;&#039; it will use the previously selected object. To make things smoother a command can be executed on several objects at once by using ranges (&amp;quot;[0-4]&amp;quot;) and comma separation (&amp;quot;[0, 3, 5-6]&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
To test out a &#039;&#039;command&#039;&#039; you can send it directly to the Ekdahl FAR using the &#039;&#039;Console&#039;&#039; in the &#039;&#039;Configuration utility&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
To read up on existing &#039;&#039;commands&#039;&#039;, their &#039;&#039;parameters&#039;&#039; and a brief description you can check the &#039;&#039;Command reference&#039;&#039; in the &#039;&#039;Configuration utility&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Variables, functions and equations ==&lt;br /&gt;
What makes the &#039;&#039;Command language&#039;&#039; truly powerful is the concept of &#039;&#039;variables, functions&#039;&#039; and &#039;&#039;equations&#039;&#039;. All &#039;&#039;parameters&#039;&#039; that take numerical values can use any combination of &#039;&#039;variables, functions&#039;&#039; or &#039;&#039;equations.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
For instance, we can use the previous example and instead write our &#039;&#039;command string&#039;&#039; as follows&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
bowmotorrun:1, bowcontrolfrequency:82.5+note*20&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bowingwheel.dcmotor.run:1, bowingwheel.pid.targetfrequency:82.5+note*20&amp;lt;/pre&amp;gt;This example requires of course that the &#039;&#039;variable&#039;&#039; &#039;&#039;note&#039;&#039; exists in the current context. &lt;br /&gt;
&lt;br /&gt;
===== Variables =====&lt;br /&gt;
There are two types of &#039;&#039;variables&#039;&#039; in the Ekdahl FAR; &#039;&#039;global variables&#039;&#039; and &#039;&#039;event variables&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Global variables&#039;&#039; are variables that are always available and will exist in any context. The &#039;&#039;global variables&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;notecount&#039;&#039;&#039; - Contains the number of &#039;&#039;MIDI&#039;&#039; keys that are being held down, i.e. all &#039;&#039;Note on messages&#039;&#039; received that haven&#039;t gotten a paired &#039;&#039;Note off message&#039;&#039; yet&lt;br /&gt;
* &#039;&#039;&#039;uv0&#039;&#039;&#039; - &#039;&#039;&#039;uv9&#039;&#039;&#039; - These are &#039;&#039;user variables&#039;&#039; and can be set at any point using the &#039;&#039;globaluservariable command&#039;&#039; with the first &#039;&#039;parameter&#039;&#039; being which variable to set (0-9) and the second &#039;&#039;parameter&#039;&#039; being the value (float).&lt;br /&gt;
* &#039;&#039;&#039;e&#039;&#039;&#039; - Contains the constant &#039;&#039;[[wikipedia:E_(mathematical_constant)|e]]&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pi&#039;&#039;&#039; - Contains the constant &#039;&#039;[[wikipedia:Pi|pi]]&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Event variables&#039;&#039; are variables that are set by certain &#039;&#039;MIDI messages&#039;&#039; or when a new value is read on one of the jacks or knobs on the &#039;&#039;Control box&#039;&#039;. The &#039;&#039;Event variables&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;channel&#039;&#039;&#039; - Set by the &#039;&#039;Note on, Note off, Continuous Controller, Poly after touch, Pitch bend, Channel after touch&#039;&#039; and &#039;&#039;Program change MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;note&#039;&#039;&#039; - Set by the &#039;&#039;Note on, Note off&#039;&#039; and &#039;&#039;Poly after touch MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;velocity&#039;&#039;&#039; - Set by the &#039;&#039;Note on&#039;&#039; and &#039;&#039;Note off MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pressure&#039;&#039;&#039; - Set by the &#039;&#039;Poly after touch&#039;&#039; and &#039;&#039;Channel after touch MIDI messages&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; - Set by the &#039;&#039;Continuous Controller MIDI message&#039;&#039; and by the &#039;&#039;Control box&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pitch&#039;&#039;&#039; - Set by the &#039;&#039;Pitch bend MIDI message&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;program&#039;&#039;&#039; - Set by the &#039;&#039;Program change MIDI message&#039;&#039;&lt;br /&gt;
These variables will contain whatever data is relevant to the &amp;lt;u&amp;gt;last midi message sent&amp;lt;/u&amp;gt; and will not stay relevant beyond the reception of the last message.&lt;br /&gt;
&lt;br /&gt;
===== Functions =====&lt;br /&gt;
&#039;&#039;Functions&#039;&#039; can be used to change a numerical value or the result of an &#039;&#039;equation&#039;&#039;, the Ekdahl FAR contains both general &#039;&#039;arithmetic functions&#039;&#039; (courtesy of Lewis Van Winkle and the TINYEXPR engine) and &#039;&#039;specialized functions&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;arithmetic functions&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;abs&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Absolute_value|absolute value]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;acos&#039;&#039;&#039;(x), &#039;&#039;&#039;asin&#039;&#039;&#039;(x), &#039;&#039;&#039;atan&#039;&#039;&#039;(x), atan2(x, y) - Returns the [[wikipedia:Inverse_trigonometric_functions|&#039;&#039;arc-cos, -sin, -tan&#039;&#039; and &#039;&#039;-tan2&#039;&#039;]] of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;atan2&#039;&#039;&#039;(x,y) - Returns the &#039;&#039;[[wikipedia:Atan2|arctan2]]&#039;&#039; of &#039;&#039;x, y&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;floor&#039;&#039;&#039;(x), ceil(x) - Returns the [[wikipedia:Floor_and_ceiling_functions|&#039;&#039;floor&#039;&#039; and &#039;&#039;ceiling&#039;&#039;]] of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;exp&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Exponential_function|exponent]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;fac&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Factorial|factorial]]&#039;&#039; of x&lt;br /&gt;
* &#039;&#039;&#039;ln&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Natural_logarithm|natural logarithm]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;log10&#039;&#039;&#039;(x), &#039;&#039;&#039;log20&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Logarithm|logarithm]]&#039;&#039; of &#039;&#039;x&#039;&#039; using base 10 and 20 respectively&lt;br /&gt;
* &#039;&#039;&#039;ncr&#039;&#039;&#039;(x,y), &#039;&#039;&#039;npr&#039;&#039;&#039;(x,y) - Functions to calculate &#039;&#039;[[wikipedia:Combination|combinations]]&#039;&#039; and &#039;&#039;[[wikipedia:Permutation|permutations]]&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;pow&#039;&#039;&#039;(x,y) - Returns &#039;&#039;x^y&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;sqrt&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Square_root|square root]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;cos&#039;&#039;&#039;(x), &#039;&#039;&#039;sin&#039;&#039;&#039;(x), &#039;&#039;&#039;tan&#039;&#039;&#039;(x) - Returns the [[wikipedia:Trigonometric_functions|&#039;&#039;cos, sin&#039;&#039; and &#039;&#039;tan&#039;&#039;]] of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;cosh&#039;&#039;&#039;(x), &#039;&#039;&#039;sinh&#039;&#039;&#039;(x), &#039;&#039;&#039;tanh&#039;&#039;&#039;(x) - Returns the &#039;&#039;[[wikipedia:Hyperbolic_functions|hyperbolic cos, sin and tan]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
The &#039;&#039;specialized functions&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;bool&#039;&#039;&#039;(x) - Returns 1 if &#039;&#039;x&#039;&#039; is more than 0&lt;br /&gt;
* &#039;&#039;&#039;ibool&#039;&#039;&#039;(x) - Returns 0 if &#039;&#039;x&#039;&#039; is more than 0&lt;br /&gt;
* &#039;&#039;&#039;deadband&#039;&#039;&#039;(x,y) - Returns &#039;&#039;x + y &#039;&#039; if &#039;&#039;x &amp;lt; y&#039;&#039; or &#039;&#039;x - y&#039;&#039; if &#039;&#039;x &amp;gt; y&#039;&#039;. If neither of these statements is true it returns &#039;&#039;0&#039;&#039; - used to create a [[wikipedia:Deadband|deadband]] of &#039;&#039;x&#039;&#039; with the threshold of &#039;&#039;y&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Functions&#039;&#039; can be readily used in a &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
FAR &amp;lt; 1.1:&lt;br /&gt;
bowmotorrun:1, bowcontrolfrequency:&amp;quot;8.17579875 * pow(2, (1/12 * note))&amp;quot;&lt;br /&gt;
&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bowingwheel.dcmotor.run:1, bowingwheel.pid.targetfrequency:&amp;quot;8.17579875 * pow(2, (1/12 * note))&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;The previous statements starts the &#039;&#039;bowing wheel&#039;&#039; and sets the frequency of the wheel to &#039;&#039;8.17579875 * 2^(1/12 * note)&#039;&#039;. A middle &#039;C&#039; according to &#039;&#039;MIDI&#039;&#039; has a &#039;&#039;note value&#039;&#039; of 36, meaning if we substitute &#039;&#039;note&#039;&#039; with 36 we get the equation &#039;&#039;8.17579875 * 2^(1/12 * 36)&#039;&#039; which comes out to &#039;&#039;~65.4&#039;&#039; Hertz.&lt;br /&gt;
&lt;br /&gt;
Note that the first &#039;&#039;parameter&#039;&#039; for &#039;&#039;bowcontrolfrequency / bowingwheel.pid.targetfrequency&#039;&#039; is put in between double quotes (&amp;quot;). This is because the &#039;&#039;pow&#039;&#039;-function requires the use of a comma (&amp;quot;,&amp;quot;) in order to separate in between its two required inputs; &#039;&#039;x&#039;&#039; and &#039;&#039;y&#039;&#039;. In order for the Ekdahl FAR to know that this comma does not signal the beginning of a new &#039;&#039;command,&#039;&#039; we use quotes. Single (&#039;) and double (&amp;quot;) quotes can be used and nested in all &#039;&#039;parameters&#039;&#039; and are &amp;lt;u&amp;gt;required&amp;lt;/u&amp;gt; in a lot of circumstances, improper nesting or not using quotes can lead to the instrument not understanding the &#039;&#039;command string&#039;&#039; correctly.&lt;br /&gt;
&lt;br /&gt;
== Return messages ==&lt;br /&gt;
The Ekdahl FAR when connected via &#039;&#039;USB-Serial&#039;&#039; doesn&#039;t only accept &#039;&#039;commands&#039;&#039; but will also send various &#039;&#039;return messages&#039;&#039;. These are prefixed by their &#039;&#039;category&#039;&#039; denoted in brackets (&amp;quot;[]&amp;quot;), the existing categories as of this writing (2025-01-22) are:&lt;br /&gt;
&lt;br /&gt;
* command / cmd - Acknowledges the reception of a command in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* usb - Acknowledges the reception of a &#039;&#039;MIDI message&#039;&#039; over &#039;&#039;USB&#039;&#039; in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* hardware / hw - Signals that a change has been sent to the Ekdahl FAR hardware, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* undefined / un - The message sent is in the &#039;&#039;undefined&#039;&#039; category, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* priority / pri - The message sent is in the &#039;&#039;priority&#039;&#039; category, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* error / err - Signals that an &#039;&#039;error&#039;&#039; has occurred, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* expressionparser / ep - These messages contains debugging information regarding the internal &#039;&#039;expression parser&#039;&#039; and is used for development&lt;br /&gt;
*debug / dbg - These messages contains various debugging information and is used for development&lt;br /&gt;
*help / hlp - Signals that the message is a response to a &#039;&#039;help&#039;&#039;-command being sent to the Ekdahl FAR. These messages are structured so that a receiver, like the &#039;&#039;Configuration utility&#039;&#039;, can parse information about available &#039;&#039;commands&#039;&#039; in the current &#039;&#039;firmware&#039;&#039; and relay it to a user in a structured way.&lt;br /&gt;
* inforequest / irq - Signals that an &#039;&#039;info request&#039;&#039; has been returned. This is a specialized message that is either sent as a response to an &#039;&#039;rqi&#039;&#039;-command or as a &#039;&#039;interrupt&#039;&#039;-message telling the user or receiving software about different parameters in the Ekdahl FAR. These messages follows the same structure as regular &#039;&#039;command message&#039;&#039;s of &#039;&#039;[irq]commandname:parameter1 [etc]&#039;&#039; so that it can be used by a receiving software to keep track of parameter changes&lt;br /&gt;
&lt;br /&gt;
===== Explicitly requesting information =====&lt;br /&gt;
By using the special command &#039;&#039;requestinfo / rqi&#039;&#039; one can request the information stored by a certain &#039;&#039;command&#039;&#039; or a state of the Ekdahl FAR. The &#039;&#039;rqi&#039;&#039;-command is executed in the convention &#039;&#039;rqi:commandname[:optional parameters]&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
To go back to our example of setting the bowing frequency using the &#039;&#039;bowcontrolfrequency&#039;&#039;-command we can ask the Ekdahl FAR what the bowing frequency is set to by writing&amp;lt;pre&amp;gt;&lt;br /&gt;
rqi:bowcontrolfrequency&lt;br /&gt;
&amp;lt;/pre&amp;gt;The return value would be something like&amp;lt;pre&amp;gt;&lt;br /&gt;
[irq]bcf:82.5&lt;br /&gt;
&amp;lt;/pre&amp;gt;Where &#039;[irq]&#039; denotes that the message returned is in the &#039;&#039;info request-&#039;&#039;category, that it pertains to the command &#039;&#039;bcf&#039;&#039; and has the value &#039;&#039;82.5&#039;&#039;. Note that the returned &#039;&#039;command&#039;&#039; sent by an &#039;&#039;rqi&#039;&#039;-command always uses the &#039;&#039;short name&#039;&#039; in order to preserve bandwidth.&lt;br /&gt;
&lt;br /&gt;
Most commands do not require any &#039;&#039;parameters&#039;&#039; when using the &#039;&#039;rqi&#039;&#039;-command. The &#039;&#039;adcread&#039;&#039;-command is an example of a &#039;&#039;command&#039;&#039; that &amp;lt;u&amp;gt;does&amp;lt;/u&amp;gt; require a &#039;&#039;parameter&#039;&#039; when used with &#039;&#039;rqi&#039;&#039;. The &#039;&#039;adcread&#039;&#039; command returns the last value read by the &#039;&#039;analog-to-digital converter&#039;&#039; in the &#039;&#039;Control box&#039;&#039;, because there are 8 different channels the first &#039;&#039;parameter&#039;&#039; sets which channel to return the data for, hence executing the &#039;&#039;command&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
rqi:adcr:3&lt;br /&gt;
&amp;lt;/pre&amp;gt;will return the last data read on &#039;&#039;analog-to-digital convert&#039;&#039; channel 3.&lt;br /&gt;
&lt;br /&gt;
== MIDI mapping ==&lt;br /&gt;
To change how a certain &#039;&#039;MIDI message&#039;&#039; interacts with the Ekdahl FAR we need to change the &#039;&#039;commands&#039;&#039; or &#039;&#039;parameters&#039;&#039; sent when the message is received. The &#039;&#039;command&#039;&#039; responsible for mapping &#039;&#039;command strimgs&#039;&#039; to different &#039;&#039;MIDI messages&#039;&#039; is &#039;&#039;midieventhandler&#039;&#039; or &#039;&#039;mev&#039;&#039; for short. The first &#039;&#039;parameter&#039;&#039; of &#039;&#039;mev&#039;&#039; is the type of &#039;&#039;MIDI message&#039;&#039; that we want to remap&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;noteon&#039;&#039; - Note on&lt;br /&gt;
* &#039;&#039;noteoff -&#039;&#039; Note off&lt;br /&gt;
* &#039;&#039;pat -&#039;&#039; Poly after touch&lt;br /&gt;
* &#039;&#039;cat&#039;&#039; - Channel after touch&lt;br /&gt;
* &#039;&#039;pb&#039;&#039; - Pitch bend&lt;br /&gt;
* &#039;&#039;pc&#039;&#039; - Program change&lt;br /&gt;
* &#039;&#039;cc&#039;&#039; - Continuous controller&lt;br /&gt;
&lt;br /&gt;
The second &#039;&#039;parameter&#039;&#039; is the &#039;&#039;command string&#039;&#039; that is to be associated with the &#039;&#039;MIDI Message&#039;&#039; - with the exception of the &#039;&#039;cc&#039;&#039;-type, here the second &#039;&#039;parameter&#039;&#039; is the &#039;&#039;controller number&#039;&#039; (0 - 127) and the &amp;lt;u&amp;gt;third&amp;lt;/u&amp;gt; &#039;&#039;parameter&#039;&#039; is the &#039;&#039;command string&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
We can of course use the &#039;&#039;rqi&#039;&#039;-command to check the current mapping, below we are asking what the current &#039;&#039;command string&#039;&#039; associated with the &#039;&#039;pitch bend&#039;&#039; &#039;&#039;MIDI message&#039;&#039; is&amp;lt;pre&amp;gt;&lt;br /&gt;
rqi:mev:pb&lt;br /&gt;
&amp;lt;/pre&amp;gt;This may return something like&amp;lt;pre&amp;gt;&lt;br /&gt;
[irq]bchsh:pitch*4&lt;br /&gt;
&amp;lt;/pre&amp;gt;The return message tells us that the &#039;&#039;pitch bend MIDI message&#039;&#039; is executing a &#039;&#039;bchsh&#039;&#039;-command with the parameter &#039;&#039;pitch*4&#039;&#039;. Looking in the &#039;&#039;command reference&#039;&#039; we can see that &#039;&#039;bchsh&#039;&#039; is the &#039;&#039;short name&#039;&#039; of the &#039;&#039;bowcontrolharmonicshift&#039;&#039;-command which shifts the frequency of the &#039;&#039;bowing wheel&#039;&#039; from the current frequency, the first (and only) parameter sets how much we want to shift it (depends on the &#039;&#039;bowcontrolharmonicshiftrange command&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
If we look in the list of &#039;&#039;[[The Ekdahl FAR - Command langue#Variables|variables]]&#039;&#039; above we can see that the &#039;&#039;pitch bend MIDI message&#039;&#039; will set the &#039;&#039;pitch variable&#039;&#039; which is indeed used. Now what is the &#039;&#039;&#039;*4&#039;&#039;&amp;lt;nowiki/&amp;gt;&#039; all about? Well the &#039;&#039;bchsh&#039;&#039;-command expects a &#039;&#039;16-bit signed&#039;&#039; value, meaning that a full &#039;&#039;harmonic shift&#039;&#039; downwards is equal to -32767, a full &#039;&#039;harmonic shift&#039;&#039; upwards is 32767 and no &#039;&#039;harmonic shift&#039;&#039; is 0. The &#039;&#039;pitch bend MIDI message&#039;&#039; however is only 14-bits, meaning its range is -8192 to 8192, so in order to be able to use the entire range we have to multiply &#039;&#039;pitch&#039;&#039; by 4.&lt;br /&gt;
&lt;br /&gt;
This whole thing about number of bits can seem confusing but in the end it&#039;s all about how fine control you have over things; the more possible values, the more detailed control. In fact, most &#039;&#039;MIDI&#039;&#039; values are only 7-bit (!) meaning a range of 0 - 127. While this may sound like a lot of detail for something like a volume control, it is not even close to enough resolution to for instance set the &#039;&#039;bowing speed&#039;&#039;. Imagine that our lowest possible note frequency is 50 Hz, that means that with a 0-127 range we can only go from 50 Hz to 127 + 50 = 177 Hz - and with no decimals! This meager range and the very coarse steps of only 1 Hz would mean the instrument would never be able to sound in tune and wouldn&#039;t even have two octaves of range. The idea of limiting the Ekdahl FAR to what is possible through &#039;&#039;MIDI&#039;&#039; seemed like a poor choice thus it was decided that &amp;lt;u&amp;gt;most&amp;lt;/u&amp;gt; parameters will instead be 16-bit.&lt;br /&gt;
&lt;br /&gt;
Now lets look at a more complex example, the &amp;lt;u&amp;gt;default&amp;lt;/u&amp;gt; &#039;&#039;Note On MIDI message&#039;&#039;. On a stock Ekdahl FAR, executing&amp;lt;pre&amp;gt;&lt;br /&gt;
rqi:mev:noteon&lt;br /&gt;
&amp;lt;/pre&amp;gt;Will return something like&amp;lt;pre&amp;gt;[irq]mev:noteon:&#039;m:0,b:0,bchb:note,bmr:1,bpid:1,bpe:1,se:(velocity*512)*(1-notecount),bcsm:0&#039;&amp;lt;/pre&amp;gt;As can be seen, there&#039;s a lot of stuff going on here! First of all, notice that everything after &#039;&#039;mev:noteon:&#039;&#039; is situated in between single quotes (&#039;) - this is &amp;lt;u&amp;gt;absolutely crucial&amp;lt;/u&amp;gt; for the Ekdahl FAR to know that everything within those last two quotes is part of the last &#039;&#039;parameter&#039;&#039; of the &#039;&#039;mev&#039;&#039;-command.&lt;br /&gt;
&lt;br /&gt;
Now let&#039;s break down what happens when this &#039;&#039;MIDI message&#039;&#039; is received, i.e. when a &#039;&#039;MIDI&#039;&#039; key is pressed down:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;m:0&#039;&#039; - Sets &#039;&#039;module&#039;&#039; to 0&lt;br /&gt;
# &#039;&#039;b:0&#039;&#039; - Sets &#039;&#039;bow&#039;&#039; to 0&lt;br /&gt;
# &#039;&#039;bchb:note&#039;&#039; - Invokes the &#039;&#039;bowcontrolharmonicbase-&#039;&#039;command with the first &#039;&#039;parameter&#039;&#039; set to the &#039;&#039;variable note&#039;&#039;. &lt;br /&gt;
# &#039;&#039;bmr:1&#039;&#039; - Sets the &#039;&#039;bowmotorrun&#039;&#039;-command to &#039;1&#039;, starting the &#039;&#039;bow motor&#039;&#039;&lt;br /&gt;
# &#039;&#039;bpid:1&#039;&#039; - Sets the &#039;&#039;bowpid&#039;&#039;-command to &#039;1&#039;, making sure the &#039;&#039;PID&#039;&#039; is used&lt;br /&gt;
# &#039;&#039;bpe:1&#039;&#039; - Sets the &#039;&#039;bowpressureengage&#039;&#039; to &#039;1&#039; which moves the &#039;&#039;bowing jack&#039;&#039; to the &#039;&#039;engage position&#039;&#039;&lt;br /&gt;
# &#039;&#039;se:(velocity*512)*(1-notecount)&#039;&#039; - Executes the &#039;&#039;solenoidengage&#039;&#039;-command with the value &#039;&#039;(velocity*512)*(1-notecount)&#039;&#039;&lt;br /&gt;
# &#039;&#039;bcsm:0&#039;&#039; - Sets the &#039;&#039;bowcontrolspeedmode&#039;&#039; to &#039;1&#039; which enables automatic shut down of the &#039;&#039;bowing motor&#039;&#039;&lt;br /&gt;
The first two &#039;&#039;commands&#039;&#039; are the &#039;&#039;module&#039;&#039;- and &#039;&#039;bow-&#039;&#039;command. These &#039;&#039;commands&#039;&#039; are is intended for future versions of the Ekdahl FAR that may contain more than one string or more than one bow per string. For now &#039;&#039;0&#039;&#039; is the only valid &#039;&#039;parameter&#039;&#039; value that will be accepted for either &#039;&#039;command&#039;&#039;.&#039;&#039;&amp;lt;nowiki/&amp;gt;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;bowcontrolharmonicbase&#039;&#039;-command sets the speed of the &#039;&#039;bowing wheel&#039;&#039; to its corresponding &#039;&#039;harmonic number&#039;&#039; but also takes into account its &#039;&#039;&amp;lt;nowiki/&amp;gt;&#039;base&#039;&#039;&#039; which is the &#039;&#039;MIDI key&#039;&#039; that is mapped to &#039;&#039;harmonic number 0&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
After this the bowing motor is started and the &#039;&#039;PID&#039;&#039; is turned, now the instrument will try and make sure that the &#039;&#039;bowing wheel&#039;&#039; is at the right speed.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;bowing jack&#039;&#039; is raised to the &#039;&#039;engage position&#039;&#039;, any added &#039;&#039;pressure modifiers&#039;&#039; will also be taken into account - once the &#039;&#039;bowing jack&#039;&#039; has reached its intended position the &#039;&#039;bowing wheel&#039;&#039; should (hopefully) make contact with the string and the Ekdahl FAR will start to produce sounds.&lt;br /&gt;
&lt;br /&gt;
After this we have the &#039;&#039;solenoidengage&#039;&#039;-command &#039;&#039;command&#039;&#039; that engages the &#039;&#039;hammer&#039;&#039; and uses the first and only &#039;&#039;parameter&#039;&#039; as the force used. Like with most &#039;&#039;commands&#039;&#039; the &#039;&#039;se&#039;&#039;-command is 16-bit (0 - 65535) but the &#039;&#039;MIDI velocity variable&#039;&#039; is 7-bit (0 - 127), so to get the &#039;&#039;velocity&#039;&#039; variable to cover the entire range it needs to be multiplied with 512. &lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&amp;lt;nowiki/&amp;gt;&#039;*(1-notecount)&#039;&#039;&#039;-part is a way of making sure that we are using &#039;&#039;legato&#039;&#039; mode, i.e. that the &#039;&#039;hammer&#039;&#039; is not triggered if a key is already held down when a new key is pressed. The &#039;&#039;notecount&#039;&#039;-variable contains the number of &#039;&#039;MIDI&#039;&#039; notes currently held down. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s postulate that the Ekdahl FAR is tuned to a &#039;C&#039; at 65.4Hz and has its &#039;&#039;base&#039;&#039; set to middle &#039;C&#039; (&#039;&#039;MIDI key&#039;&#039; no 36). We are using the equal-temperament 12-tone scale and the Ekdahl FAR is set to respond to &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; &#039;&#039;MIDI channels&#039;&#039; (omni). Without having previously held any keys we press the middle &#039;C&#039; (&#039;&#039;note&#039;&#039; value 36) as hard as possible (&#039;&#039;velocity&#039;&#039; value &#039;&#039;127&#039;&#039;) on &#039;&#039;MIDI channel&#039;&#039; number 1 (&#039;&#039;channel&#039;&#039; value of 0). The Ekdahl FAR will get a &#039;&#039;note on MIDI message&#039;&#039; sent to it and from our mapping it will create the following &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;[irq]mev:noteon:&#039;m:0,b:0,bchb:36,bmr:1,bpid:1,bpe:1,se:(127*512)*(1-0),bcsm:0&#039;&amp;lt;/pre&amp;gt;What has happened here is that all &#039;&#039;variables&#039;&#039; have been replaced with the values sent by the &#039;&#039;MIDI message&#039;&#039;. Since those &#039;&#039;commands&#039;&#039; that doesn&#039;t have any &#039;&#039;variables&#039;&#039; with them will execute just as previously, only those &#039;&#039;commands&#039;&#039; whos &#039;&#039;parameters&#039;&#039; have changed will be explained:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;bchb: 36&#039;&#039; - The &#039;&#039;bowcontrolharmonicbase&#039;&#039; gets a value of &#039;&#039;36&#039;&#039; (middle &#039;C&#039;), because &#039;&#039;harmonic number 0&#039;&#039; is mapped to this key it will set the &#039;&#039;bowing wheel&#039;&#039; frequency to the &#039;&#039;fundamental&#039;&#039;; &#039;&#039;65.4&#039;&#039; Hertz&lt;br /&gt;
# &#039;&#039;se: (127*512)*(1-0)&#039;&#039; - the value of &#039;&#039;127&#039;&#039; comes from the &#039;&#039;velocity&#039;&#039;-variable, &#039;&#039;127 * 512 = 65024&#039;&#039; which is awfully close to a maximum hammer force of 65535. Since no previous notes were held down &#039;&#039;notecount&#039;&#039;  is equal to &#039;&#039;0&#039;&#039; and thus &#039;&#039;65024 * 1 = 65024&#039;&#039;. The hammer is engaged with near maximum force.&lt;br /&gt;
So the result is that we have set the speed of the &#039;&#039;bowing motor&#039;&#039; and we have engaged the &#039;&#039;hammer&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Now imagine that without releasing this key, we press another &#039;C&#039; one octave above but at half the velocity. The Ekdahl FAR creates the following &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
[irq]mev:noteon:&#039;m:0,b:0,bchb:48,bmr:1,bpid:1,bpe:1,se:(63*512)*(1-1),bcsm:0&#039;&lt;br /&gt;
&amp;lt;/pre&amp;gt;Now we can see that the &#039;&#039;note&#039;&#039; variable is &#039;&#039;48&#039;&#039; because the &#039;C&#039; one octave up is exactly 12 keys above the first, the &#039;&#039;velocity&#039;&#039; variable has changed to &#039;&#039;63&#039;&#039; since we hit it with a lighter touch - and because we are &amp;lt;u&amp;gt;still holding the first key down&amp;lt;/u&amp;gt; &#039;&#039;notecount&#039;&#039; is equal to &#039;&#039;1&#039;&#039;. Here&#039;s what happens&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;bchb: 48&#039;&#039; - Due to the &#039;&#039;base&#039;&#039; being set to &#039;&#039;36&#039;&#039; the &#039;&#039;harmonic number&#039;&#039; is set to &#039;&#039;48 - 36 = 12&#039;&#039;. Because we are using a 12-tone scale &#039;&#039;harmonic number 12&#039;&#039; is exactly one octave above the &#039;&#039;fundamental&#039;&#039; thus the speed of the &#039;&#039;bowing wheel&#039;&#039; is set to &#039;&#039;65.4 * 2 = 130.8&#039;&#039; Hertz.&lt;br /&gt;
# &#039;&#039;se: (63*512)*(1-1)&#039;&#039; - So &#039;&#039;63 * 512 = 32256&#039;&#039; and &#039;&#039;1 - 1 = 0&#039;&#039; thus &#039;&#039;32256 * 0 = 0&#039;&#039;. When the &#039;&#039;solenoidengage&#039;&#039;-command gets a &#039;&#039;parameter&#039;&#039; of &#039;&#039;0&#039;&#039; it will not engage the &#039;&#039;hammer&#039;&#039; - so the &#039;&#039;hammer&#039;&#039; doesn&#039;t strike&lt;br /&gt;
So it can be seen that with quite rudimentary math we can accomplish a whole lot of things here. Note also that even though the &#039;&#039;note on MIDI message&#039;&#039; also sets the &#039;&#039;channel&#039;&#039;-variable we never use it in this example - plenty of opportunity to make something weird happen depending on the &#039;&#039;MIDI channel&#039;&#039;!&lt;br /&gt;
&lt;br /&gt;
== CV Mapping ==&lt;br /&gt;
&#039;&#039;CV Mapping&#039;&#039; works exactly like the &#039;&#039;MIDI mapping&#039;&#039; with the difference that the command for setting the &#039;&#039;CV mapping&#039;&#039; is different and that &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; events pertaining to this &amp;lt;u&amp;gt;only&amp;lt;/u&amp;gt; change the &#039;&#039;value&#039;&#039;-variable. The &#039;&#039;command&#039;&#039; for changing the &#039;&#039;CV mapping&#039;&#039; is &#039;&#039;adccommandmap&#039;&#039; or &#039;&#039;acm&#039;&#039;, it take two &#039;&#039;parameters&#039;&#039;; &#039;&#039;channel&#039;&#039; and &#039;&#039;command string&#039;&#039;. We retrieve the &#039;&#039;command string&#039;&#039; for channel &#039;&#039;0&#039;&#039; which reads the sum of the &#039;&#039;harm. v/oct&#039;&#039;-jack and the &#039;&#039;harmonic&#039;&#039;-knob by sending a command of&amp;lt;pre&amp;gt;&lt;br /&gt;
rqi:acm:0&lt;br /&gt;
&amp;lt;/pre&amp;gt;The &amp;lt;u&amp;gt;default&amp;lt;/u&amp;gt; response will be something like&lt;br /&gt;
&amp;lt;pre&amp;gt;[irq]acm:0:&#039;bcha:value/1327.716667-20&#039;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{docnav&lt;br /&gt;
|[[The Ekdahl FAR - Service|Service]]&lt;br /&gt;
|[[The Ekdahl FAR - Command reference|Command reference]]&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Knaadmin</name></author>
	</entry>
	<entry>
		<id>http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_language&amp;diff=1643</id>
		<title>The Ekdahl FAR - Command language</title>
		<link rel="alternate" type="text/html" href="http://knasmusic.com/wiki/index.php?title=The_Ekdahl_FAR_-_Command_language&amp;diff=1643"/>
		<updated>2026-06-07T08:29:58Z</updated>

		<summary type="html">&lt;p&gt;Knaadmin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Command language ==&lt;br /&gt;
The Ekdahl FAR is entirely controlled by &#039;&#039;commands&#039;&#039;, these &#039;&#039;commands&#039;&#039; decide everything that the instrument is doing, whether it is playing a melody or changing an internal parameter. &lt;br /&gt;
&lt;br /&gt;
When a &#039;&#039;MIDI message&#039;&#039; is received or a new CV / knob value is read, the &#039;&#039;commands&#039;&#039; associated with it will be internally sent. This can be things like &amp;quot;engage hammer&amp;quot; or &amp;quot;set the fundamental frequency&amp;quot; etc. &lt;br /&gt;
&lt;br /&gt;
Some of the available &#039;&#039;commands&#039;&#039; are mainly used for calibrating and setting up the instrument and are usually saved into the instruments memory, these will be executed whenever the instrument is turned on. &lt;br /&gt;
&lt;br /&gt;
All &#039;&#039;commands&#039;&#039; can be manually invoked via &#039;&#039;USB-Serial&#039;&#039;, in conjunction with certain software this presents an unprecedented level of control and sequenceability.&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
The &#039;&#039;commands&#039;&#039; are invoked using a &#039;&#039;plain text approach&#039;&#039;, all commands have both a &#039;&#039;long name&#039;&#039; and a &#039;&#039;short name&#039;&#039; which are interchangeable. A &#039;&#039;command&#039;&#039; may have one or more &#039;&#039;parameters&#039;&#039; associated with it, these &#039;&#039;parameters&#039;&#039; can be of different types; 16-bit numbers (values 0 - 65535 or -32767 - 32767), floating point numbers (values with decimals), booleans (0 for &#039;false&#039;, 1 for &#039;true&#039;) and strings (text). Some commands are &#039;&#039;conditional&#039;&#039;, meaning they will only execute if a parameter equates to &#039;1&#039; (&#039;true&#039;). &lt;br /&gt;
&lt;br /&gt;
The way &#039;&#039;commands&#039;&#039; are written in order to be executed is &#039;&#039;commandname:parameter1:parameter2:parameter3 [etc]&#039;&#039;, several commands be executed in sequence by separating them with a comma (&#039;,&#039;), a bunch of commands strung together is called a &#039;&#039;command string&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Since version 1.1 of the Ekdahl FAR Firmware, all commands are grouped in a hierarchical fashion according to their &#039;&#039;modules&#039;&#039; and each ladder in the hierarchy is separated by a period (&amp;quot;.&amp;quot;), this works very much like folders or directories in a regular computer. Every &#039;&#039;module&#039;&#039; can contain both &#039;&#039;commands&#039;&#039; and other &#039;&#039;modules&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
For instance, everything associated with the &#039;&#039;bowing wheel&#039;&#039; is now collected under &amp;quot;bowingwheel&amp;quot; &#039;&#039;module&#039;&#039;. That in turn contains a &amp;quot;dcmotor&amp;quot; &#039;&#039;module&#039;&#039; which does direct control of the bowing motor, and it has a &amp;quot;pid&amp;quot; &#039;&#039;module&#039;&#039; that handles bow frequency.&lt;br /&gt;
&lt;br /&gt;
If for instance we would like to start the &#039;&#039;bowing wheel&#039;&#039; and set its frequency to 82.5 Hertz we could send the Ekdahl FAR the following &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
bowmotorrun:1, bowcontrolfrequecy:82.5&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bowingwheel.dcmotor.run:1, bowingwheel.pid.targetfrequency:82.5&amp;lt;/pre&amp;gt;We could also use the &#039;&#039;short names&#039;&#039; for the commands&amp;lt;pre&amp;gt;FAR &amp;lt; 1.1:&lt;br /&gt;
bmr:1,bcf:82.5&lt;br /&gt;
FAR 1.1:&lt;br /&gt;
bw.dcm.ru:1, bw.pid.tf:82.5&amp;lt;/pre&amp;gt;Both &#039;&#039;bowmotorrun&#039;&#039; and &#039;&#039;bowcontrolfrequency&#039;&#039; takes one &#039;&#039;parameter&#039;&#039; each, &#039;&#039;bowmotorrun&#039;&#039; is &#039;&#039;conditional&#039;&#039; and unless the first &#039;&#039;parameter&#039;&#039; is equal to &#039;1&#039; the motor will not start. The first &#039;&#039;parameter&#039;&#039; of &#039;&#039;bowcontrolfrequency&#039;&#039; sets the frequency of the &#039;&#039;bowing wheel&#039;&#039;, the instrument may not execute a &#039;&#039;command&#039;&#039; if it decides that the given &#039;&#039;parameters&#039;&#039; are outside of the working range or they are missing.&lt;br /&gt;
&lt;br /&gt;
The addition of the hierarchy in the FAR 1.1 firmware isn&#039;t just to be able to group commands, but it&#039;s also to make the FAR not limited to a single set of &#039;&#039;modules&#039;&#039;. In fact, you could have 12 different bowing wheel &#039;&#039;modules&#039;&#039; for 12 different strings, these would then be addressed as &#039;&#039;bowingwheel[0].command, bowingwheel[1].command&#039;&#039; etc. Anyone familiar with C programming notices that this is the standard way of &#039;&#039;indexing&#039;&#039; an object in an array using brackets (&amp;quot;[ ]&amp;quot;). When addressing a module without &#039;&#039;indexing&#039;&#039; as above, the FAR will do one or two things; either use the first object (&amp;quot;[0]&amp;quot;) or, if the object is &#039;&#039;selectable&#039;&#039; it will use the previously selected object. To make things smoother a command can be executed on several objects at once by using ranges (&amp;quot;[0-4]&amp;quot;) and comma separation (&amp;quot;[0, 3, 5-6]&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
To test out a &#039;&#039;command&#039;&#039; you can send it directly to the Ekdahl FAR using the &#039;&#039;Console&#039;&#039; in the &#039;&#039;Configuration utility&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
To read up on existing &#039;&#039;commands&#039;&#039;, their &#039;&#039;parameters&#039;&#039; and a brief description you can check the &#039;&#039;Command reference&#039;&#039; in the &#039;&#039;Configuration utility&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Variables, functions and equations ==&lt;br /&gt;
What makes the &#039;&#039;Command language&#039;&#039; truly powerful is the concept of &#039;&#039;variables, functions&#039;&#039; and &#039;&#039;equations&#039;&#039;. All &#039;&#039;parameters&#039;&#039; that take numerical values can use any combination of &#039;&#039;variables, functions&#039;&#039; or &#039;&#039;equations.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
For instance, we can use the previous example and instead write our &#039;&#039;command string&#039;&#039; as follows&amp;lt;pre&amp;gt;&lt;br /&gt;
bowmotorrun:1,bowcontrolfrequency:82.5+note*20&lt;br /&gt;
&amp;lt;/pre&amp;gt;This example requires of course that the &#039;&#039;variable&#039;&#039; &#039;&#039;note&#039;&#039; exists in the current context. &lt;br /&gt;
&lt;br /&gt;
===== Variables =====&lt;br /&gt;
There are two types of &#039;&#039;variables&#039;&#039; in the Ekdahl FAR; &#039;&#039;global variables&#039;&#039; and &#039;&#039;event variables&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Global variables&#039;&#039; are variables that are always available and will exist in any context. The &#039;&#039;global variables&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* notecount - Contains the number of &#039;&#039;MIDI&#039;&#039; keys that are being held down, i.e. all &#039;&#039;Note on messages&#039;&#039; received that haven&#039;t gotten a paired &#039;&#039;Note off message&#039;&#039; yet&lt;br /&gt;
* uv0 - uv9 - These are &#039;&#039;user variables&#039;&#039; and can be set at any point using the &#039;&#039;globaluservariable command&#039;&#039; with the first &#039;&#039;parameter&#039;&#039; being which variable to set (0-9) and the second &#039;&#039;parameter&#039;&#039; being the value (float).&lt;br /&gt;
* e - Contains the constant &#039;&#039;[[wikipedia:E_(mathematical_constant)|e]]&#039;&#039;&lt;br /&gt;
* pi - Contains the constant &#039;&#039;[[wikipedia:Pi|pi]]&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Event variables&#039;&#039; are variables that are set by certain &#039;&#039;MIDI messages&#039;&#039; or when a new value is read on one of the jacks or knobs on the &#039;&#039;Control box&#039;&#039;. The &#039;&#039;Event variables&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* channel - Set by the &#039;&#039;Note on, Note off, Continuous Controller, Poly after touch, Pitch bend, Channel after touch&#039;&#039; and &#039;&#039;Program change MIDI messages&#039;&#039;&lt;br /&gt;
* note - Set by the &#039;&#039;Note on, Note off&#039;&#039; and &#039;&#039;Poly after touch MIDI messages&#039;&#039;&lt;br /&gt;
* velocity - Set by the &#039;&#039;Note on&#039;&#039; and &#039;&#039;Note off MIDI messages&#039;&#039;&lt;br /&gt;
* pressure - Set by the &#039;&#039;Poly after touch&#039;&#039; and &#039;&#039;Channel after touch MIDI messages&#039;&#039;&lt;br /&gt;
* value - Set by the &#039;&#039;Continuous Controller MIDI message&#039;&#039; and by the &#039;&#039;Control box&#039;&#039;&lt;br /&gt;
* pitch - Set by the &#039;&#039;Pitch bend MIDI message&#039;&#039;&lt;br /&gt;
* program - Set by the &#039;&#039;Program change MIDI message&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
===== Functions =====&lt;br /&gt;
&#039;&#039;Functions&#039;&#039; can be used to change a numerical value or the result of an &#039;&#039;equation&#039;&#039;, the Ekdahl FAR contains both general &#039;&#039;arithmetic functions&#039;&#039; (courtesy of Lewis Van Winkle and the TINYEXPR engine) and &#039;&#039;specialized functions&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;arithmetic functions&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* abs(x) - Returns the &#039;&#039;[[wikipedia:Absolute_value|absolute value]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* acos(x), asin(x), atan(x), atan2(x, y) - Returns the [[wikipedia:Inverse_trigonometric_functions|&#039;&#039;arc-cos, -sin, -tan&#039;&#039; and &#039;&#039;-tan2&#039;&#039;]] of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* atan2(x,y) - Returns the &#039;&#039;[[wikipedia:Atan2|arctan2]]&#039;&#039; of &#039;&#039;x, y&#039;&#039;&lt;br /&gt;
* floor(x), ceil(x) - Returns the [[wikipedia:Floor_and_ceiling_functions|&#039;&#039;floor&#039;&#039; and &#039;&#039;ceiling&#039;&#039;]] of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* exp(x) - Returns the &#039;&#039;[[wikipedia:Exponential_function|exponent]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* fac(x) - Returns the &#039;&#039;[[wikipedia:Factorial|factorial]]&#039;&#039; of x&lt;br /&gt;
* ln(x) - Returns the &#039;&#039;[[wikipedia:Natural_logarithm|natural logarithm]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* log10(x), log20(x) - Returns the &#039;&#039;[[wikipedia:Logarithm|logarithm]]&#039;&#039; of &#039;&#039;x&#039;&#039; using base 10 and 20 respectively&lt;br /&gt;
* ncr(x,y), npr(x,y) - Functions to calculate &#039;&#039;[[wikipedia:Combination|combinations]]&#039;&#039; and &#039;&#039;[[wikipedia:Permutation|permutations]]&#039;&#039;&lt;br /&gt;
* pow(x,y) - Returns &#039;&#039;x^y&#039;&#039;&lt;br /&gt;
* sqrt(x) - Returns the &#039;&#039;[[wikipedia:Square_root|square root]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* cos(x), sin(x), tan(x) - Returns the [[wikipedia:Trigonometric_functions|&#039;&#039;cos, sin&#039;&#039; and &#039;&#039;tan&#039;&#039;]] of &#039;&#039;x&#039;&#039;&lt;br /&gt;
* cosh(x), sinh(x), tanh(x) - Returns the &#039;&#039;[[wikipedia:Hyperbolic_functions|hyperbolic cos, sin and tan]]&#039;&#039; of &#039;&#039;x&#039;&#039;&lt;br /&gt;
The &#039;&#039;specialized functions&#039;&#039; that are incorporated in the &#039;&#039;firmware&#039;&#039; as of this writing (2025-01-21) are:&lt;br /&gt;
&lt;br /&gt;
* bool(x) - Returns 1 if &#039;&#039;x&#039;&#039; is more than 0&lt;br /&gt;
* ibool(x) - Returns 0 if &#039;&#039;x&#039;&#039; is more than 0&lt;br /&gt;
* deadband(x,y) - Returns &#039;&#039;x + y &#039;&#039; if &#039;&#039;x &amp;lt; y&#039;&#039; or &#039;&#039;x - y&#039;&#039; if &#039;&#039;x &amp;gt; y&#039;&#039;. If neither of these statements is true it returns &#039;&#039;0&#039;&#039; - used to create a [[wikipedia:Deadband|deadband]] of &#039;&#039;x&#039;&#039; with the threshold of &#039;&#039;y&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Functions&#039;&#039; can be readily used in a &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
bmr:1,bcf:&amp;quot;8.17579875 * pow(2, (1/12 * note))&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;The previous statements starts the &#039;&#039;bowing wheel&#039;&#039; and sets the frequency of the wheel to &#039;&#039;8.17579875 * 2^(1/12 * note)&#039;&#039;. A middle &#039;C&#039; according to &#039;&#039;MIDI&#039;&#039; has a &#039;&#039;note value&#039;&#039; of 36, meaning if we substitute &#039;&#039;note&#039;&#039; with 36 we get the equation &#039;&#039;8.17579875 * 2^(1/12 * 36)&#039;&#039; which comes out to &#039;&#039;~65.4&#039;&#039; Hertz.&lt;br /&gt;
&lt;br /&gt;
Note that the first &#039;&#039;parameter&#039;&#039; for &#039;&#039;bcf&#039;&#039; is put in between double quotes (&amp;quot;). This is because the &#039;&#039;pow&#039;&#039;-function requires the use of a comma (&amp;quot;,&amp;quot;) in order to separate in between its two require inputs &#039;&#039;x&#039;&#039; and &#039;&#039;y&#039;&#039; and we need to make sure that the Ekdahl FAR doesn&#039;t mistake that comma for meaning that a new &#039;&#039;command&#039;&#039; is being sent. Single (&#039;) and double (&amp;quot;) quotes can be used and nested in all &#039;&#039;parameters&#039;&#039; and are &amp;lt;u&amp;gt;required&amp;lt;/u&amp;gt; in a lot of circumstances, improper nesting or not using quotes can lead to the instrument not parsing the &#039;&#039;command string&#039;&#039; correctly.&lt;br /&gt;
&lt;br /&gt;
== Return messages ==&lt;br /&gt;
The Ekdahl FAR when connected via &#039;&#039;USB-Serial&#039;&#039; doesn&#039;t only accept &#039;&#039;commands&#039;&#039; but will also send various &#039;&#039;return messages&#039;&#039;. These are prefixed by their &#039;&#039;category&#039;&#039; denoted in brackets (&amp;quot;[]&amp;quot;), the existing categories as of this writing (2025-01-22) are:&lt;br /&gt;
&lt;br /&gt;
* command / cmd - Acknowledges the reception of a command in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* usb - Acknowledges the reception of a &#039;&#039;MIDI message&#039;&#039; over &#039;&#039;USB&#039;&#039; in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* hardware / hw - Signals that a change has been sent to the Ekdahl FAR hardware, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* undefined / un - The message sent is in the &#039;&#039;undefined&#039;&#039; category, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* priority / pri - The message sent is in the &#039;&#039;priority&#039;&#039; category, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* error / err - Signals that an &#039;&#039;error&#039;&#039; has occurred, sent in &#039;&#039;plain text&#039;&#039;&lt;br /&gt;
* expressionparser / ep - These messages contains debugging information regarding the internal &#039;&#039;expression parser&#039;&#039; and is used for development&lt;br /&gt;
*debug / dbg - These messages contains various debugging information and is used for development&lt;br /&gt;
*help / hlp - Signals that the message is a response to a &#039;&#039;help&#039;&#039;-command being sent to the Ekdahl FAR. These messages are structured so that a receiver, like the &#039;&#039;Configuration utility&#039;&#039;, can parse information about available &#039;&#039;commands&#039;&#039; in the current &#039;&#039;firmware&#039;&#039; and relay it to a user in a structured way.&lt;br /&gt;
* inforequest / irq - Signals that an &#039;&#039;info request&#039;&#039; has been returned. This is a specialized message that is either sent as a response to an &#039;&#039;rqi&#039;&#039;-command or as a &#039;&#039;interrupt&#039;&#039;-message telling the user or receiving software about different parameters in the Ekdahl FAR. These messages follows the same structure as regular &#039;&#039;command message&#039;&#039;s of &#039;&#039;[irq]commandname:parameter1 [etc]&#039;&#039; so that it can be used by a receiving software to keep track of parameter changes&lt;br /&gt;
&lt;br /&gt;
===== Explicitly requesting information =====&lt;br /&gt;
By using the special command &#039;&#039;requestinfo / rqi&#039;&#039; one can request the information stored by a certain &#039;&#039;command&#039;&#039; or a state of the Ekdahl FAR. The &#039;&#039;rqi&#039;&#039;-command is executed in the convention &#039;&#039;rqi:commandname[:optional parameters]&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
To go back to our example of setting the bowing frequency using the &#039;&#039;bowcontrolfrequency&#039;&#039;-command we can ask the Ekdahl FAR what the bowing frequency is set to by writing&amp;lt;pre&amp;gt;&lt;br /&gt;
rqi:bowcontrolfrequency&lt;br /&gt;
&amp;lt;/pre&amp;gt;The return value would be something like&amp;lt;pre&amp;gt;&lt;br /&gt;
[irq]bcf:82.5&lt;br /&gt;
&amp;lt;/pre&amp;gt;Where &#039;[irq]&#039; denotes that the message returned is in the &#039;&#039;info request-&#039;&#039;category, that it pertains to the command &#039;&#039;bcf&#039;&#039; and has the value &#039;&#039;82.5&#039;&#039;. Note that the returned &#039;&#039;command&#039;&#039; sent by an &#039;&#039;rqi&#039;&#039;-command always uses the &#039;&#039;short name&#039;&#039; in order to preserve bandwidth.&lt;br /&gt;
&lt;br /&gt;
Most commands do not require any &#039;&#039;parameters&#039;&#039; when using the &#039;&#039;rqi&#039;&#039;-command. The &#039;&#039;adcread&#039;&#039;-command is an example of a &#039;&#039;command&#039;&#039; that &amp;lt;u&amp;gt;does&amp;lt;/u&amp;gt; require a &#039;&#039;parameter&#039;&#039; when used with &#039;&#039;rqi&#039;&#039;. The &#039;&#039;adcread&#039;&#039; command returns the last value read by the &#039;&#039;analog-to-digital converter&#039;&#039; in the &#039;&#039;Control box&#039;&#039;, because there are 8 different channels the first &#039;&#039;parameter&#039;&#039; sets which channel to return the data for, hence executing the &#039;&#039;command&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
rqi:adcr:3&lt;br /&gt;
&amp;lt;/pre&amp;gt;will return the last data read on &#039;&#039;analog-to-digital convert&#039;&#039; channel 3.&lt;br /&gt;
&lt;br /&gt;
== MIDI mapping ==&lt;br /&gt;
To change how a certain &#039;&#039;MIDI message&#039;&#039; interacts with the Ekdahl FAR we need to change the &#039;&#039;commands&#039;&#039; or &#039;&#039;parameters&#039;&#039; sent when the message is received. The &#039;&#039;command&#039;&#039; responsible for mapping &#039;&#039;command strimgs&#039;&#039; to different &#039;&#039;MIDI messages&#039;&#039; is &#039;&#039;midieventhandler&#039;&#039; or &#039;&#039;mev&#039;&#039; for short. The first &#039;&#039;parameter&#039;&#039; of &#039;&#039;mev&#039;&#039; is the type of &#039;&#039;MIDI message&#039;&#039; that we want to remap&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;noteon&#039;&#039; - Note on&lt;br /&gt;
* &#039;&#039;noteoff -&#039;&#039; Note off&lt;br /&gt;
* &#039;&#039;pat -&#039;&#039; Poly after touch&lt;br /&gt;
* &#039;&#039;cat&#039;&#039; - Channel after touch&lt;br /&gt;
* &#039;&#039;pb&#039;&#039; - Pitch bend&lt;br /&gt;
* &#039;&#039;pc&#039;&#039; - Program change&lt;br /&gt;
* &#039;&#039;cc&#039;&#039; - Continuous controller&lt;br /&gt;
&lt;br /&gt;
The second &#039;&#039;parameter&#039;&#039; is the &#039;&#039;command string&#039;&#039; that is to be associated with the &#039;&#039;MIDI Message&#039;&#039; - with the exception of the &#039;&#039;cc&#039;&#039;-type, here the second &#039;&#039;parameter&#039;&#039; is the &#039;&#039;controller number&#039;&#039; (0 - 127) and the &amp;lt;u&amp;gt;third&amp;lt;/u&amp;gt; &#039;&#039;parameter&#039;&#039; is the &#039;&#039;command string&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
We can of course use the &#039;&#039;rqi&#039;&#039;-command to check the current mapping, below we are asking what the current &#039;&#039;command string&#039;&#039; associated with the &#039;&#039;pitch bend&#039;&#039; &#039;&#039;MIDI message&#039;&#039; is&amp;lt;pre&amp;gt;&lt;br /&gt;
rqi:mev:pb&lt;br /&gt;
&amp;lt;/pre&amp;gt;This may return something like&amp;lt;pre&amp;gt;&lt;br /&gt;
[irq]bchsh:pitch*4&lt;br /&gt;
&amp;lt;/pre&amp;gt;The return message tells us that the &#039;&#039;pitch bend MIDI message&#039;&#039; is executing a &#039;&#039;bchsh&#039;&#039;-command with the parameter &#039;&#039;pitch*4&#039;&#039;. Looking in the &#039;&#039;command reference&#039;&#039; we can see that &#039;&#039;bchsh&#039;&#039; is the &#039;&#039;short name&#039;&#039; of the &#039;&#039;bowcontrolharmonicshift&#039;&#039;-command which shifts the frequency of the &#039;&#039;bowing wheel&#039;&#039; from the current frequency, the first (and only) parameter sets how much we want to shift it (depends on the &#039;&#039;bowcontrolharmonicshiftrange command&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
If we look in the list of &#039;&#039;[[The Ekdahl FAR - Command langue#Variables|variables]]&#039;&#039; above we can see that the &#039;&#039;pitch bend MIDI message&#039;&#039; will set the &#039;&#039;pitch variable&#039;&#039; which is indeed used. Now what is the &#039;&#039;&#039;*4&#039;&#039;&amp;lt;nowiki/&amp;gt;&#039; all about? Well the &#039;&#039;bchsh&#039;&#039;-command expects a &#039;&#039;16-bit signed&#039;&#039; value, meaning that a full &#039;&#039;harmonic shift&#039;&#039; downwards is equal to -32767, a full &#039;&#039;harmonic shift&#039;&#039; upwards is 32767 and no &#039;&#039;harmonic shift&#039;&#039; is 0. The &#039;&#039;pitch bend MIDI message&#039;&#039; however is only 14-bits, meaning its range is -8192 to 8192, so in order to be able to use the entire range we have to multiply &#039;&#039;pitch&#039;&#039; by 4.&lt;br /&gt;
&lt;br /&gt;
This whole thing about number of bits can seem confusing but in the end it&#039;s all about how fine control you have over things; the more possible values, the more detailed control. In fact, most &#039;&#039;MIDI&#039;&#039; values are only 7-bit (!) meaning a range of 0 - 127. While this may sound like a lot of detail for something like a volume control, it is not even close to enough resolution to for instance set the &#039;&#039;bowing speed&#039;&#039;. Imagine that our lowest possible note frequency is 50 Hz, that means that with a 0-127 range we can only go from 50 Hz to 127 + 50 = 177 Hz - and with no decimals! This meager range and the very coarse steps of only 1 Hz would mean the instrument would never be able to sound in tune and wouldn&#039;t even have two octaves of range. The idea of limiting the Ekdahl FAR to what is possible through &#039;&#039;MIDI&#039;&#039; seemed like a poor choice thus it was decided that &amp;lt;u&amp;gt;most&amp;lt;/u&amp;gt; parameters will instead be 16-bit.&lt;br /&gt;
&lt;br /&gt;
Now lets look at a more complex example, the &amp;lt;u&amp;gt;default&amp;lt;/u&amp;gt; &#039;&#039;Note On MIDI message&#039;&#039;. On a stock Ekdahl FAR, executing&amp;lt;pre&amp;gt;&lt;br /&gt;
rqi:mev:noteon&lt;br /&gt;
&amp;lt;/pre&amp;gt;Will return something like&amp;lt;pre&amp;gt;[irq]mev:noteon:&#039;m:0,b:0,bchb:note,bmr:1,bpid:1,bpe:1,se:(velocity*512)*(1-notecount),bcsm:0&#039;&amp;lt;/pre&amp;gt;As can be seen, there&#039;s a lot of stuff going on here! First of all, notice that everything after &#039;&#039;mev:noteon:&#039;&#039; is situated in between single quotes (&#039;) - this is &amp;lt;u&amp;gt;absolutely crucial&amp;lt;/u&amp;gt; for the Ekdahl FAR to know that everything within those last two quotes is part of the last &#039;&#039;parameter&#039;&#039; of the &#039;&#039;mev&#039;&#039;-command.&lt;br /&gt;
&lt;br /&gt;
Now let&#039;s break down what happens when this &#039;&#039;MIDI message&#039;&#039; is received, i.e. when a &#039;&#039;MIDI&#039;&#039; key is pressed down:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;m:0&#039;&#039; - Sets &#039;&#039;module&#039;&#039; to 0&lt;br /&gt;
# &#039;&#039;b:0&#039;&#039; - Sets &#039;&#039;bow&#039;&#039; to 0&lt;br /&gt;
# &#039;&#039;bchb:note&#039;&#039; - Invokes the &#039;&#039;bowcontrolharmonicbase-&#039;&#039;command with the first &#039;&#039;parameter&#039;&#039; set to the &#039;&#039;variable note&#039;&#039;. &lt;br /&gt;
# &#039;&#039;bmr:1&#039;&#039; - Sets the &#039;&#039;bowmotorrun&#039;&#039;-command to &#039;1&#039;, starting the &#039;&#039;bow motor&#039;&#039;&lt;br /&gt;
# &#039;&#039;bpid:1&#039;&#039; - Sets the &#039;&#039;bowpid&#039;&#039;-command to &#039;1&#039;, making sure the &#039;&#039;PID&#039;&#039; is used&lt;br /&gt;
# &#039;&#039;bpe:1&#039;&#039; - Sets the &#039;&#039;bowpressureengage&#039;&#039; to &#039;1&#039; which moves the &#039;&#039;bowing jack&#039;&#039; to the &#039;&#039;engage position&#039;&#039;&lt;br /&gt;
# &#039;&#039;se:(velocity*512)*(1-notecount)&#039;&#039; - Executes the &#039;&#039;solenoidengage&#039;&#039;-command with the value &#039;&#039;(velocity*512)*(1-notecount)&#039;&#039;&lt;br /&gt;
# &#039;&#039;bcsm:0&#039;&#039; - Sets the &#039;&#039;bowcontrolspeedmode&#039;&#039; to &#039;1&#039; which enables automatic shut down of the &#039;&#039;bowing motor&#039;&#039;&lt;br /&gt;
The first two &#039;&#039;commands&#039;&#039; are the &#039;&#039;module&#039;&#039;- and &#039;&#039;bow-&#039;&#039;command. These &#039;&#039;commands&#039;&#039; are is intended for future versions of the Ekdahl FAR that may contain more than one string or more than one bow per string. For now &#039;&#039;0&#039;&#039; is the only valid &#039;&#039;parameter&#039;&#039; value that will be accepted for either &#039;&#039;command&#039;&#039;.&#039;&#039;&amp;lt;nowiki/&amp;gt;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;bowcontrolharmonicbase&#039;&#039;-command sets the speed of the &#039;&#039;bowing wheel&#039;&#039; to its corresponding &#039;&#039;harmonic number&#039;&#039; but also takes into account its &#039;&#039;&amp;lt;nowiki/&amp;gt;&#039;base&#039;&#039;&#039; which is the &#039;&#039;MIDI key&#039;&#039; that is mapped to &#039;&#039;harmonic number 0&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
After this the bowing motor is started and the &#039;&#039;PID&#039;&#039; is turned, now the instrument will try and make sure that the &#039;&#039;bowing wheel&#039;&#039; is at the right speed.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;bowing jack&#039;&#039; is raised to the &#039;&#039;engage position&#039;&#039;, any added &#039;&#039;pressure modifiers&#039;&#039; will also be taken into account - once the &#039;&#039;bowing jack&#039;&#039; has reached its intended position the &#039;&#039;bowing wheel&#039;&#039; should (hopefully) make contact with the string and the Ekdahl FAR will start to produce sounds.&lt;br /&gt;
&lt;br /&gt;
After this we have the &#039;&#039;solenoidengage&#039;&#039;-command &#039;&#039;command&#039;&#039; that engages the &#039;&#039;hammer&#039;&#039; and uses the first and only &#039;&#039;parameter&#039;&#039; as the force used. Like with most &#039;&#039;commands&#039;&#039; the &#039;&#039;se&#039;&#039;-command is 16-bit (0 - 65535) but the &#039;&#039;MIDI velocity variable&#039;&#039; is 7-bit (0 - 127), so to get the &#039;&#039;velocity&#039;&#039; variable to cover the entire range it needs to be multiplied with 512. &lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&amp;lt;nowiki/&amp;gt;&#039;*(1-notecount)&#039;&#039;&#039;-part is a way of making sure that we are using &#039;&#039;legato&#039;&#039; mode, i.e. that the &#039;&#039;hammer&#039;&#039; is not triggered if a key is already held down when a new key is pressed. The &#039;&#039;notecount&#039;&#039;-variable contains the number of &#039;&#039;MIDI&#039;&#039; notes currently held down. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s postulate that the Ekdahl FAR is tuned to a &#039;C&#039; at 65.4Hz and has its &#039;&#039;base&#039;&#039; set to middle &#039;C&#039; (&#039;&#039;MIDI key&#039;&#039; no 36). We are using the equal-temperament 12-tone scale and the Ekdahl FAR is set to respond to &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; &#039;&#039;MIDI channels&#039;&#039; (omni). Without having previously held any keys we press the middle &#039;C&#039; (&#039;&#039;note&#039;&#039; value 36) as hard as possible (&#039;&#039;velocity&#039;&#039; value &#039;&#039;127&#039;&#039;) on &#039;&#039;MIDI channel&#039;&#039; number 1 (&#039;&#039;channel&#039;&#039; value of 0). The Ekdahl FAR will get a &#039;&#039;note on MIDI message&#039;&#039; sent to it and from our mapping it will create the following &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;[irq]mev:noteon:&#039;m:0,b:0,bchb:36,bmr:1,bpid:1,bpe:1,se:(127*512)*(1-0),bcsm:0&#039;&amp;lt;/pre&amp;gt;What has happened here is that all &#039;&#039;variables&#039;&#039; have been replaced with the values sent by the &#039;&#039;MIDI message&#039;&#039;. Since those &#039;&#039;commands&#039;&#039; that doesn&#039;t have any &#039;&#039;variables&#039;&#039; with them will execute just as previously, only those &#039;&#039;commands&#039;&#039; whos &#039;&#039;parameters&#039;&#039; have changed will be explained:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;bchb: 36&#039;&#039; - The &#039;&#039;bowcontrolharmonicbase&#039;&#039; gets a value of &#039;&#039;36&#039;&#039; (middle &#039;C&#039;), because &#039;&#039;harmonic number 0&#039;&#039; is mapped to this key it will set the &#039;&#039;bowing wheel&#039;&#039; frequency to the &#039;&#039;fundamental&#039;&#039;; &#039;&#039;65.4&#039;&#039; Hertz&lt;br /&gt;
# &#039;&#039;se: (127*512)*(1-0)&#039;&#039; - the value of &#039;&#039;127&#039;&#039; comes from the &#039;&#039;velocity&#039;&#039;-variable, &#039;&#039;127 * 512 = 65024&#039;&#039; which is awfully close to a maximum hammer force of 65535. Since no previous notes were held down &#039;&#039;notecount&#039;&#039;  is equal to &#039;&#039;0&#039;&#039; and thus &#039;&#039;65024 * 1 = 65024&#039;&#039;. The hammer is engaged with near maximum force.&lt;br /&gt;
So the result is that we have set the speed of the &#039;&#039;bowing motor&#039;&#039; and we have engaged the &#039;&#039;hammer&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Now imagine that without releasing this key, we press another &#039;C&#039; one octave above but at half the velocity. The Ekdahl FAR creates the following &#039;&#039;command string&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
[irq]mev:noteon:&#039;m:0,b:0,bchb:48,bmr:1,bpid:1,bpe:1,se:(63*512)*(1-1),bcsm:0&#039;&lt;br /&gt;
&amp;lt;/pre&amp;gt;Now we can see that the &#039;&#039;note&#039;&#039; variable is &#039;&#039;48&#039;&#039; because the &#039;C&#039; one octave up is exactly 12 keys above the first, the &#039;&#039;velocity&#039;&#039; variable has changed to &#039;&#039;63&#039;&#039; since we hit it with a lighter touch - and because we are &amp;lt;u&amp;gt;still holding the first key down&amp;lt;/u&amp;gt; &#039;&#039;notecount&#039;&#039; is equal to &#039;&#039;1&#039;&#039;. Here&#039;s what happens&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;bchb: 48&#039;&#039; - Due to the &#039;&#039;base&#039;&#039; being set to &#039;&#039;36&#039;&#039; the &#039;&#039;harmonic number&#039;&#039; is set to &#039;&#039;48 - 36 = 12&#039;&#039;. Because we are using a 12-tone scale &#039;&#039;harmonic number 12&#039;&#039; is exactly one octave above the &#039;&#039;fundamental&#039;&#039; thus the speed of the &#039;&#039;bowing wheel&#039;&#039; is set to &#039;&#039;65.4 * 2 = 130.8&#039;&#039; Hertz.&lt;br /&gt;
# &#039;&#039;se: (63*512)*(1-1)&#039;&#039; - So &#039;&#039;63 * 512 = 32256&#039;&#039; and &#039;&#039;1 - 1 = 0&#039;&#039; thus &#039;&#039;32256 * 0 = 0&#039;&#039;. When the &#039;&#039;solenoidengage&#039;&#039;-command gets a &#039;&#039;parameter&#039;&#039; of &#039;&#039;0&#039;&#039; it will not engage the &#039;&#039;hammer&#039;&#039; - so the &#039;&#039;hammer&#039;&#039; doesn&#039;t strike&lt;br /&gt;
So it can be seen that with quite rudimentary math we can accomplish a whole lot of things here. Note also that even though the &#039;&#039;note on MIDI message&#039;&#039; also sets the &#039;&#039;channel&#039;&#039;-variable we never use it in this example - plenty of opportunity to make something weird happen depending on the &#039;&#039;MIDI channel&#039;&#039;!&lt;br /&gt;
&lt;br /&gt;
== CV Mapping ==&lt;br /&gt;
&#039;&#039;CV Mapping&#039;&#039; works exactly like the &#039;&#039;MIDI mapping&#039;&#039; with the difference that the command for setting the &#039;&#039;CV mapping&#039;&#039; is different and that &amp;lt;u&amp;gt;all&amp;lt;/u&amp;gt; events pertaining to this &amp;lt;u&amp;gt;only&amp;lt;/u&amp;gt; change the &#039;&#039;value&#039;&#039;-variable. The &#039;&#039;command&#039;&#039; for changing the &#039;&#039;CV mapping&#039;&#039; is &#039;&#039;adccommandmap&#039;&#039; or &#039;&#039;acm&#039;&#039;, it take two &#039;&#039;parameters&#039;&#039;; &#039;&#039;channel&#039;&#039; and &#039;&#039;command string&#039;&#039;. We retrieve the &#039;&#039;command string&#039;&#039; for channel &#039;&#039;0&#039;&#039; which reads the sum of the &#039;&#039;harm. v/oct&#039;&#039;-jack and the &#039;&#039;harmonic&#039;&#039;-knob by sending a command of&amp;lt;pre&amp;gt;&lt;br /&gt;
rqi:acm:0&lt;br /&gt;
&amp;lt;/pre&amp;gt;The &amp;lt;u&amp;gt;default&amp;lt;/u&amp;gt; response will be something like&lt;br /&gt;
&amp;lt;pre&amp;gt;[irq]acm:0:&#039;bcha:value/1327.716667-20&#039;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{docnav&lt;br /&gt;
|[[The Ekdahl FAR - Service|Service]]&lt;br /&gt;
|[[The Ekdahl FAR - Command reference|Command reference]]&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Knaadmin</name></author>
	</entry>
</feed>