More actions
No edit summary |
No edit summary |
||
(11 intermediate revisions by the same user not shown) | |||
Line 2: | Line 2: | ||
The Ekdahl FAR is entirely controlled by ''commands'', these ''commands'' decide everything that the instrument is doing, whether it is playing a melody or changing an internal parameter. | The Ekdahl FAR is entirely controlled by ''commands'', these ''commands'' decide everything that the instrument is doing, whether it is playing a melody or changing an internal parameter. | ||
When a MIDI | When a ''MIDI message'' is received or a new CV / knob value is read, the ''commands'' associated with it will be internally sent. This can be things like "engage hammer" or "set the fundamental frequency" etc. | ||
Some of the available ''commands'' 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. | Some of the available ''commands'' 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. | ||
Line 9: | Line 9: | ||
== Syntax == | == Syntax == | ||
The ''commands'' are invoked using a ''plain text approach'', most commands have both a ''long name'' and a ''short name'' which are interchangeable. A ''command'' may have one or more ''parameters'' associated with it, these ''parameters'' can be of different types; 16-bit numbers (values 0 - 65535), floating point numbers (values with decimals), booleans (0 for 'false', 1 for 'true') and strings (text). Some commands are ''conditional'', meaning they will only execute if a parameter equates to '1' ('true'). | The ''commands'' are invoked using a ''plain text approach'', most commands have both a ''long name'' and a ''short name'' which are interchangeable. A ''command'' may have one or more ''parameters'' associated with it, these ''parameters'' can be of different types; 16-bit numbers (values 0 - 65535 or -32767 - 32767), floating point numbers (values with decimals), booleans (0 for 'false', 1 for 'true') and strings (text). Some commands are ''conditional'', meaning they will only execute if a parameter equates to '1' ('true'). | ||
The way ''commands'' are written in order to be executed is ''commandname:parameter1:parameter2:parameter3 [etc]'', several commands be executed in sequence by separating them with a comma (','), a bunch of commands strung together is called a ''command string''. If for instance we would like to start the ''bowing wheel'' and set its frequency to 82.5 Hertz we could send the Ekdahl FAR the following ''command string''<pre> | The way ''commands'' are written in order to be executed is ''commandname:parameter1:parameter2:parameter3 [etc]'', several commands be executed in sequence by separating them with a comma (','), a bunch of commands strung together is called a ''command string''. If for instance we would like to start the ''bowing wheel'' and set its frequency to 82.5 Hertz we could send the Ekdahl FAR the following ''command string''<pre> | ||
bowmotorrun:1, bowcontrolfrequecy:82.5 | bowmotorrun:1, bowcontrolfrequecy:82.5 | ||
</pre>We could also use the ''short names'' for the commands<pre>bmr:1,bcf:82.5</pre>Both ''bowmotorrun'' and ''bowcontrolfrequency'' takes one ''parameter'' each, ''bowmotorrun'' | </pre>We could also use the ''short names'' for the commands<pre>bmr:1,bcf:82.5</pre>Both ''bowmotorrun'' and ''bowcontrolfrequency'' takes one ''parameter'' each, ''bowmotorrun'' is ''conditional'' and unless the first ''parameter'' is equal to '1' the motor will not start. The first ''parameter'' of ''bowcontrolfrequency'' sets the frequency of the ''bowing wheel'', the instrument may not execute a ''command'' if it decides that the given ''parameters'' are outside of the working range or they are missing. | ||
To test out a ''command'' you can send it directly to the Ekdahl FAR using the ''Console'' in the ''Configuration utility''. | To test out a ''command'' you can send it directly to the Ekdahl FAR using the ''Console'' in the ''Configuration utility''. | ||
Line 70: | Line 70: | ||
* deadband(x,y) - Returns ''x + y '' if ''x < y'' or ''x - y'' if ''x > y''. If neither of these statements is true it returns ''0'' - used to create a [[wikipedia:Deadband|deadband]] of ''x'' with the threshold of ''y'' | * deadband(x,y) - Returns ''x + y '' if ''x < y'' or ''x - y'' if ''x > y''. If neither of these statements is true it returns ''0'' - used to create a [[wikipedia:Deadband|deadband]] of ''x'' with the threshold of ''y'' | ||
''Functions'' can be readily used in a ''command string'' | ''Functions'' can be readily used in a ''command string''<pre> | ||
bmr:1,bcf:"8.17579875 * pow(2, (1/12 * note))" | |||
</pre>The previous statements starts the ''bowing wheel'' and sets the frequency of the wheel to ''8.17579875 * 2^(1/12 * note)''. A middle 'C' according to ''MIDI'' has a ''note value'' of 36, meaning if we substitute ''note'' with 36 we get the equation ''8.17579875 * 2^(1/12 * 36)'' which comes out to ''~65.4'' Hertz. | |||
Note that the first ''parameter'' for ''bcf'' is put in between double quotes ("). This is because the ''pow''-function requires the use of a comma (",") in order to separate in between its two require inputs ''x'' and ''y'' and we need to make sure that the Ekdahl FAR doesn't mistake that comma for meaning that a new ''command'' is being sent. Single (') and double (") quotes can be used and nested in all ''parameters'' and are <u>required</u> in a lot of circumstances, improper nesting or not using quotes can lead to the instrument not parsing the ''command string'' correctly. | |||
== Return messages == | |||
The Ekdahl FAR when connected via ''USB-Serial'' doesn't only accept ''commands'' but will also send various ''return messages''. These are prefixed by their ''category'' denoted in brackets ("[]"), the existing categories as of this writing (2025-01-22) are: | |||
* command / cmd - Acknowledges the reception of a command in ''plain text'' | |||
* usb - Acknowledges the reception of a ''MIDI message'' over ''USB'' in ''plain text'' | |||
* hardware / hw - Signals that a change has been sent to the Ekdahl FAR hardware, sent in ''plain text'' | |||
* undefined / un - The message sent is in the ''undefined'' category, sent in ''plain text'' | |||
* priority / pri - The message sent is in the ''priority'' category, sent in ''plain text'' | |||
* error / err - Signals that an ''error'' has occurred, sent in ''plain text'' | |||
* expressionparser / ep - These messages contains debugging information regarding the internal ''expression parser'' and is used for development | |||
*debug / dbg - These messages contains various debugging information and is used for development | |||
*help / hlp - Signals that the message is a response to a ''help''-command being sent to the Ekdahl FAR. These messages are structured so that a receiver, like the ''Configuration utility'', can parse information about available ''commands'' in the current ''firmware'' and relay it to a user in a structured way. | |||
* inforequest / irq - Signals that an ''info request'' has been returned. This is a specialized message that is either sent as a response to an ''rqi''-command or as a ''interrupt''-message telling the user or receiving software about different parameters in the Ekdahl FAR. These messages follows the same structure as regular ''command message''s of ''[irq]commandname:parameter1 [etc]'' so that it can be used by a receiving software to keep track of parameter changes | |||
===== Explicitly requesting information ===== | |||
By using the special command ''requestinfo / rqi'' one can request the information stored by a certain ''command'' or a state of the Ekdahl FAR. The ''rqi''-command is executed in the convention ''rqi:commandname[:optional parameters]''. | |||
To go back to our example of setting the bowing frequency using the ''bowcontrolfrequency''-command we can ask the Ekdahl FAR what the bowing frequency is set to by writing<pre> | |||
rqi:bowcontrolfrequency | |||
</pre>The return value would be something like<pre> | |||
[irq]bcf:82.5 | |||
</pre>Where '[irq]' denotes that the message returned is in the ''info request-''category, that it pertains to the command ''bcf'' and has the value ''82.5''. Note that the returned ''command'' sent by an ''rqi''-command always uses the ''short name'' in order to preserve bandwidth. | |||
Most commands do not require any ''parameters'' when using the ''rqi''-command. The ''adcread''-command is an example of a ''command'' that <u>does</u> require a ''parameter'' when used with ''rqi''. The ''adcread'' command returns the last value read by the ''analog-to-digital converter'' in the ''Control box'', because there are 8 different channels the first ''parameter'' sets which channel to return the data for, hence executing the ''command''<pre> | |||
rqi:adcr:3 | |||
</pre>will return the last data read on ''analog-to-digital convert'' channel 3. | |||
== MIDI mapping == | |||
To change how a certain ''MIDI message'' interacts with the Ekdahl FAR we need to change the ''commands'' or ''parameters'' sent when the message is received. The ''command'' responsible for mapping ''command strimgs'' to different ''MIDI messages'' is ''midieventhandler'' or ''mev'' for short. The first ''parameter'' of ''mev'' is the type of ''MIDI message'' that we want to remap | |||
* ''noteon'' - Note on | |||
* ''noteoff -'' Note off | |||
* ''pat -'' Poly after touch | |||
* ''cat'' - Channel after touch | |||
* ''pb'' - Pitch bend | |||
* ''pc'' - Program change | |||
* ''cc'' - Continuous controller | |||
The second ''parameter'' is the ''command string'' that is to be associated with the ''MIDI Message'' - with the exception of the ''cc''-type, here the second ''parameter'' is the ''controller number'' (0 - 127) and the <u>third</u> ''parameter'' is the ''command string''. | |||
We can of course use the ''rqi''-command to check the current mapping, below we are asking what the current ''command string'' associated with the ''pitch bend'' ''MIDI message'' is<pre> | |||
rqi:mev:pb | |||
</pre>This may return something like<pre> | |||
[irq]bchsh:pitch*4 | |||
</pre>The return message tells us that the ''pitch bend MIDI message'' is executing a ''bchsh''-command with the parameter ''pitch*4''. Looking in the ''command reference'' we can see that ''bchsh'' is the ''short name'' of the ''bowcontrolharmonicshift''-command which shifts the frequency of the ''bowing wheel'' from the current frequency, the first (and only) parameter sets how much we want to shift it (depends on the ''bowcontrolharmonicshiftrange command''). | |||
If we look in the list of ''[[The Ekdahl FAR - Command langue#Variables|variables]]'' above we can see that the ''pitch bend MIDI message'' will set the ''pitch variable'' which is indeed used. Now what is the '''*4''<nowiki/>' all about? Well the ''bchsh''-command expects a ''16-bit signed'' value, meaning that a full ''harmonic shift'' downwards is equal to -32767, a full ''harmonic shift'' upwards is 32767 and no ''harmonic shift'' is 0. The ''pitch bend MIDI message'' 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 ''pitch'' by 4. | |||
This whole thing about number of bits can seem confusing but in the end it's all about how fine control you have over things; the more possible values, the more detailed control. In fact, most ''MIDI'' 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 ''bowing speed''. 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't even have two octaves of range. The idea of limiting the Ekdahl FAR to what is possible through ''MIDI'' seemed like a poor choice thus it was decided that <u>most</u> parameters will instead be 16-bit. | |||
Now lets look at a more complex example, the <u>default</u> ''Note On MIDI message''. On a stock Ekdahl FAR, executing<pre> | |||
rqi:mev:noteon | |||
</pre>Will return something like<pre>[irq]mev:noteon:'m:0,b:0,bchb:note,bmr:1,bpid:1,bpe:1,se:(velocity*512)*(1-notecount),bcsm:0'</pre>As can be seen, there's a lot of stuff going on here! First of all, notice that everything after ''mev:noteon:'' is situated in between single quotes (') - this is <u>absolutely crucial</u> for the Ekdahl FAR to know that everything within those last two quotes is part of the last ''parameter'' of the ''mev''-command. | |||
Now let's break down what happens when this ''MIDI message'' is received, i.e. when a ''MIDI'' key is pressed down: | |||
# ''m:0'' - Sets ''module'' to 0 | |||
# ''b:0'' - Sets ''bow'' to 0 | |||
# ''bchb:note'' - Invokes the ''bowcontrolharmonicbase-''command with the first ''parameter'' set to the ''variable note''. | |||
# ''bmr:1'' - Sets the ''bowmotorrun''-command to '1', starting the ''bow motor'' | |||
# ''bpid:1'' - Sets the ''bowpid''-command to '1', making sure the ''PID'' is used | |||
# ''bpe:1'' - Sets the ''bowpressureengage'' to '1' which moves the ''bowing jack'' to the ''engage position'' | |||
# ''se:(velocity*512)*(1-notecount)'' - Executes the ''solenoidengage''-command with the value ''(velocity*512)*(1-notecount)'' | |||
# ''bcsm:0'' - Sets the ''bowcontrolspeedmode'' to '1' which enables automatic shut down of the ''bowing motor'' | |||
The first two ''commands'' are the ''module''- and ''bow-''command. These ''commands'' 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 ''0'' is the only valid ''parameter'' value that will be accepted for either ''command''.''<nowiki/>'' | |||
The ''bowcontrolharmonicbase''-command sets the speed of the ''bowing wheel'' to its corresponding ''harmonic number'' but also takes into account its ''<nowiki/>'base''' which is the ''MIDI key'' that is mapped to ''harmonic number 0''. | |||
After this the bowing motor is started and the ''PID'' is turned, now the instrument will try and make sure that the ''bowing wheel'' is at the right speed. | |||
The ''bowing jack'' is raised to the ''engage position'', any added ''pressure modifiers'' will also be taken into account - once the ''bowing jack'' has reached its intended position the ''bowing wheel'' should (hopefully) make contact with the string and the Ekdahl FAR will start to produce sounds. | |||
After this we have the ''solenoidengage''-command ''command'' that engages the ''hammer'' and uses the first and only ''parameter'' as the force used. Like with most ''commands'' the ''se''-command is 16-bit (0 - 65535) but the ''MIDI velocity variable'' is 7-bit (0 - 127), so to get the ''velocity'' variable to cover the entire range it needs to be multiplied with 512. | |||
The ''<nowiki/>'*(1-notecount)'''-part is a way of making sure that we are using ''legato'' mode, i.e. that the ''hammer'' is not triggered if a key is already held down when a new key is pressed. The ''notecount''-variable contains the number of ''MIDI'' notes currently held down. | |||
Let's postulate that the Ekdahl FAR is tuned to a 'C' at 65.4Hz and has its ''base'' set to middle 'C' (''MIDI key'' no 36). We are using the equal-temperament 12-tone scale and the Ekdahl FAR is set to respond to <u>all</u> ''MIDI channels'' (omni). Without having previously held any keys we press the middle 'C' (''note'' value 36) as hard as possible (''velocity'' value ''127'') on ''MIDI channel'' number 1 (''channel'' value of 0). The Ekdahl FAR will get a ''note on MIDI message'' sent to it and from our mapping it will create the following ''command string''<pre>[irq]mev:noteon:'m:0,b:0,bchb:36,bmr:1,bpid:1,bpe:1,se:(127*512)*(1-0),bcsm:0'</pre>What has happened here is that all ''variables'' have been replaced with the values sent by the ''MIDI message''. Since those ''commands'' that doesn't have any ''variables'' with them will execute just as previously, only those ''commands'' whos ''parameters'' have changed will be explained: | |||
# ''bchb: 36'' - The ''bowcontrolharmonicbase'' gets a value of ''36'' (middle 'C'), because ''harmonic number 0'' is mapped to this key it will set the ''bowing wheel'' frequency to the ''fundamental''; ''65.4'' Hertz | |||
# ''se: (127*512)*(1-0)'' - the value of ''127'' comes from the ''velocity''-variable, ''127 * 512 = 65024'' which is awfully close to a maximum hammer force of 65535. Since no previous notes were held down ''notecount'' is equal to ''0'' and thus ''65024 * 1 = 65024''. The hammer is engaged with near maximum force. | |||
So the result is that we have set the speed of the ''bowing motor'' and we have engaged the ''hammer''. | |||
Now imagine that without releasing this key, we press another 'C' one octave above but at half the velocity. The Ekdahl FAR creates the following ''command string''<pre> | |||
[irq]mev:noteon:'m:0,b:0,bchb:48,bmr:1,bpid:1,bpe:1,se:(63*512)*(1-1),bcsm:0' | |||
</pre>Now we can see that the ''note'' variable is ''48'' because the 'C' one octave up is exactly 12 keys above the first, the ''velocity'' variable has changed to ''63'' since we hit it with a lighter touch - and because we are <u>still holding the first key down</u> ''notecount'' is equal to ''1''. Here's what happens | |||
# ''bchb: 48'' - Due to the ''base'' being set to ''36'' the ''harmonic number'' is set to ''48 - 36 = 12''. Because we are using a 12-tone scale ''harmonic number 12'' is exactly one octave above the ''fundamental'' thus the speed of the ''bowing wheel'' is set to ''65.4 * 2 = 130.8'' Hertz. | |||
# ''se: (63*512)*(1-1)'' - So ''63 * 512 = 32256'' and ''1 - 1 = 0'' thus ''32256 * 0 = 0''. When the ''solenoidengage''-command gets a ''parameter'' of ''0'' it will not engage the ''hammer'' - so the ''hammer'' doesn't strike | |||
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 ''note on MIDI message'' also sets the ''channel''-variable we never use it in this example - plenty of opportunity to make something weird happen depending on the ''MIDI channel''! | |||
== CV Mapping == | |||
''CV Mapping'' works exactly like the ''MIDI mapping'' with the difference that the command for setting the ''CV mapping'' is different and that <u>all</u> events pertaining to this <u>only</u> change the ''value''-variable. The ''command'' for changing the ''CV mapping'' is ''adccommandmap'' or ''acm'', it take two ''parameters''; ''channel'' and ''command string''. We retrieve the ''command string'' for channel ''0'' which reads the sum of the ''harm. v/oct''-jack and the ''harmonic''-knob by sending a command of<pre> | |||
rqi:acm:0 | |||
</pre>The <u>default</u> response will be something like | |||
<pre>[irq]acm:0:'bcha:value/1327.716667-20'</pre> | |||
{{docnav | |||
|[[The Ekdahl FAR - Service|Service]] | |||
|[[The Ekdahl FAR - Command reference|Command reference]] | |||
}} |