R2 = FORTH return stack pointer R7,R8 = vrij te gebruiken (lokaal) R9 = FORTH data stack pointer RC = programma teller van NEXT RE = vrij te gebruiken (globaal)Van de overige registers zijn er sommige gereserveerd voor interrupt en DMA (R0,R1); andere zijn pointers naar BASIC CALL en RETURN procedures (R4,R5,R6); weer andere hebben een vaste funktie in het FORTH operating system (R3,RA,RB,RD,RF). Wij zullen verder niet moeilijk doen, en alleen vrij gebruik maken van de registers R7,R8 en RE. Ook de return stack zal ons incidenteel (via R2) van nut zijn. De pointer in R9 hebben we nodig om parameters op te vissen van de data-stack.
/ instruktie C, instruktie C, ... \
HEX CREATE naam | | SMUDGE
\ instruktie+instruktie , ..... /
Een bijzondere plaats wordt ingenomen door de 1802 instruktie DC (hex):
maak RC tot programma teller. Dit betekent dat NEXT wordt aangeroepen,
waarmee de executie van het machinecode-woord beëindigd wordt.HEX CREATE AAN 7BDC , SMUDGE CREATE UIT 7ADC , SMUDGE DECIMAL 1000 VARIABLE TELLER : WACHT TELLER @ 0 DO LOOP ; : KEER_KNIPPEREN 0 DO AAN WACHT UIT WACHT LOOP ; 100 KEER KNIPPEREN (cr)
C C# D D# E F F# G G# A A# B = 12 tonen van de chromatische toonladder
LC LC# LD LD# LE LF LF# LG LG# LA LA# LB = idem, één oktaaf lager
HC HC# HD HD# HE HF HF# HG HG# HA HA# HB = idem, één oktaaf hoger
_ = met vastgestelde tijdsduur tot klinken brengen van een akkoord
\ = vaststellen van de tijdsduur voor _ , volgens: aantal_tellen ->
LO = verlagen met één oktaaf
HI = verhogen met één oktaaf
VOET = bevat een kodering van de registratie ( 1 = aan , 0 = uit ):
eerste bit = hoog , tweede bit = midden , derde bit = laag
We zullen zodadelijk zien dat elke samenklank op een volgend muzikaal
moment automatisch wordt uitgezet. Deze default kan echter overschreven
worden door:
^ = doorklinken van het akkoord (Klavarskribo "doorklinkpunt")Tenslotte enkele algemene voorzieningen, die strikt genomen niet tot het Musicode applikatie repertoire behoren:
START = zet de computerbesturing van het orgel aan STOP = zet de computerbesturing van het orgel uit (default) STIL = forceer stilte, wanneer de zaak uit de hand loopt
Bij eenstemmige muziek kan er maar één noot tegelijk klinken.
Dit betekent dat een vorige toon automatisch door de volgende wordt uitgezet.
Deze vanzelfsprekendheid gaat niet langer op voor meerstemmige muziek.
Een voorbeeld moge de situatie verduidelijken. Beschouw de volgende frase:
C E G _ C F A _ . Neem voor het gemak aan dat alleen
de laagste register voetmaat in werking is: 4 VOET !
We kunnen dan de kontaktnummers berekenen welke bij
de samenklank C E G behoren. Dat zijn in ons geval 13, 17 en 20 .
Om dit akkoord tot klinken te brengen zouden moeten worden overgezonden
de kodes 2 x kontakt - 1 = 25,33,39 . Het eerstvolgende muzikale moment
wordt gevuld door de samenklank C F A . Dit zou overeenkomen met output
van: 25,35,43 . Echter, het getal 25 korrespondeert met de C , die ook
al aanwezig is in C E G . Let op de verbindingsboog in het notenschrift.
Er is geen enkele reden om een toon die al klinkt nogmaals aan te zetten.
Resteert uitvoer van de kontakten 18 en 22. Maar behalve de samenklank
C F A horen we nog steeds de tonen E G , want die hebben we vergeten
uit te zetten. Dit wordt verholpen door 2 x (17,20) - 2 = 32 en 38
op poort 2 uit te voeren. Samenvattend zien we dat de akkoordwisseling
C B G _ C F A _ gepaard gaat met oversturen van de volgende kodes:
35,43 en 32,38 . Het is belangrijk dit resultaat te generaliseren,
alvorens ook maar een letter te programmeren. Als volgt.
Het opbouwen van een akkoord is gelijkwaardig met het verzamelen van
kontaktnummers. De aldus gekonstrueerde verzameling noemen wij AAN .
Wanneer een akkoord eenmaal tot klinken is gebracht, dan worden dezelfde
kontaktnummers overgebracht naar een andere verzameling, genaamd UIT .
Op dit punt aangeland is het zinnig een begrip uit de verzamelingenleer
naar voren te halen. Het verschil van twee verzamelingen X en Y ,
hetgeen we noteren als X \ Y , is gedefinieerd als de verzameling van
alle elementen van X die niet behoren tot Y .
Akkoordwisseling vindt nu in zijn algemeenheid plaats als volgt.
Bepaal het VERSCHIL van AAN en UIT. Stuur de elementen van AAN \ UIT
over de hoogste lijnen van de data-bus om bijbehorende orgelkontakten
aan te zetten: laagste bit op 1.
Bepaal het VERSCHIL van UIT en AAN. Stuur de elementen van UIT \ AAN
over de hoogste lijnen van de data-bus om bijbehorende orgelkontakten
uit te zetten: laagste bit op 0.
De termen in hoofdletters kan men wel ergens in de listing van de FORTH
screens terugvinden.
kontaktnummers = 12 x oktaafhoogte + stackparameter + ( 84 , 42 , 0 )De oktaafhoogte bevindt zich in de variabele OKT. Ze wordt geregeld door de applikatiefunkties LO en HI. Afhankelijk van de registratie-kodering in VOET worden de resulterende kontaktnummers, drie in getal, wel of niet aan de samenklank toegevoegd. Het akkoord draagt een bekende naam: AAN . Zoals gezegd is het een gesorteerd integer array. Nieuwe nummers worden ge"merged" met de reeds AANwezige kontakten. De daarbij gebruikte methode is "straight insertion". Wil men akkoordbouw in de praktijk soepel kunnen toepassen, dan is het niet altijd te voorkomen dat identieke kontakten in AAN komen. Deze moeten na afloop van het proces worden verwijderd, voordat akkoordwisseling plaatsvindt. Het VERSCHIL algorithme zal namelijk alleen werken op echte verzamelingen ("sets") AAN en UIT, en niet op "bags" (: Smalltalk terminologie).
AAN -> addr gesorteerde rij van aan te zetten kontakten
UIT -> addr gesorteerde rij van uit te zetten kontakten
De orgelkontakten zijn genummerd van 1 t/m 126; nullen betekent leeg.
_REG, a n -> kompileer-woord: breng adres a in register n
>REG, n -> kompileer-woord: breng TOS naar register n
LABEL -> addr array voor het opslaan van sprong-adressen
LABEL! a n -> label n toekennen aan sprong-adres a
LABEL@ n -> a bepaal sprong-adres a behorende bij label n
GOTO, m n -> kompileren van short/long branch
met opcode m naar het adres met label n
VERSCHIL a b -> bepaal het verschil van de verzamelingen a en b
en stuur de elementen van a \ b naar het orgel:
kode = 2 x kontakt - byte met label 4
HUP -> kopieer AAN naar UIT en maak AAN leeg
EXTRA n -> zet tos (1 of 2) in het adres met label 4
en wijzig daarmee lokaal een byte in VERSCHIL
KNIJP -> verwijder de identieke elementen in AAN
LEEG -> en maak waar nodig schoon; AAN wordt een "set"
VOET -> addr variabele waarin een kodering van de registratie
OKT -> addr variabele die de oktaafhoogte bevat
TOON n -> berekent kontaktnummers uit tos, OKT en VOET
en slaat deze gesorteerd op in AAN
& -> funktie voor akkoordwisseling
Gevolgd door alle tonen van de chromatische toonladder, uitgebreid met
een oktaaf hoger en een oktaaf lager: zie "Homofone Musicode".TEL -> addr variablele die de tel-eenheid bevat, voor: DUUR -> addr bevat de momentane tijdsduur van een akkoord TELLEN lege loopstruktuur om de tijd te dodenZij nog vermeld dat "doorklinken" ^ wordt bewerkstelligd door UIT terug te kopiëren naar AAN.