Dr.Godfried-Willem RAES

Kursus Experimentele Muziek: Boekdeel 1: Algoritmische Kompositie

Hogeschool Gent - Departement Muziek en Drama


<Terug naar inhoudstafel kursus>

Inleiding

Kontkont.bas demonstratieprogramma

Ranger.bas: een echolood als continuous controller

PulsePing.bas: een voorbeeld programma van Joachim Brackx


 

1122

Continuous Controllers

 Inleiding

Wie de midi-standaard goed heeft bestudeerd zal het al zijn opgevallen dat binnen deze standaard middels de byte sekwens

176+kanaal kontroller-nummer waarde-byte

heel wat parameters van daarvoor gevoelige midi-apparatuur kunnen worden bestuurd.

Omdat standaard midi-keyboards naast het toonwiel (dat overigens een andere -met name de pitch-bend 14-bit sekwens- kode opwekt) hooguit nog over een enkel 'modulation'-wheel beschikken, blijven deze mogelijkheden voor wie met standaard midi-apparatuur werkt veelal geheel onbenut.

Nochtans zijn het bij uitstek deze mogelijkheden die je muzikale rezultaten een persoonlijk karakter kunnen verlenen en, zijn uitgerekend in deze mogelijkheden werkelijke interaktiviteit vervat.

Om met kontinu-kontrollers te experimenteren, ontwikkelden we een klein testprogramma dat je toelaat via het komputerkeyboard allerlei real-time kontinu kontrole informatie uit te sturen. Mits kleine wijzigingen in het programma kan je eender welke reeks van 40 kontinue midi-kontrollers in real- time aansturen.

 

File: C:\bc7\kompos\KONTKONT.BAS

' *************************************************************************

' * Continuous Controller Test Utility *

' * KONTKONT.BAS *

' *************************************************************************

' This program needs and consists of following files:

' KONTKONT.BAS main module

' C:\bc7\bom\mpuuart.exe

' IPS33B.DOC - ascii documentation file

' TSR24.DOC - ascii documentation file

 

REM $INCLUDE: 'C:\bc7\kompos\IPS33B.DOC' :' dokumentatie ASCII-file

REM $INCLUDE: 'C:\bc7\kompos\TSR24.DOC'

REM $DYNAMIC

 

COMMON SHARED Noot%, mch%

COMMON SHARED kmap%()

COMMON SHARED amap%()

 

DECLARE SUB Uit (b%)

DECLARE SUB Progchanges ()

DECLARE SUB Noteonseq ()

DECLARE SUB Noteoffseq ()

DECLARE SUB keymap ()

 

CONST DP = &H330

'DP = &H320: ' voor logotronics interfaces

'DP = &H330: ' voor Roland MPU401 of MusicQuest in UART-mode, or for Soundblaster interfaces

CLS

BEEP

IF DP = &H330 THEN SHELL "C:\bc7\bom\mpuuart.exe"

BEEP

DIM byte%(0 TO 127): ' continuous controller value

DIM oldbyte%(0 TO 127): ' previous CC-value

DIM controlmap%(0 TO 127): ' this program test maximum 40 controllers at the ' same time.

' The selected controllernumbers should be placed

' in this array

DIM SHARED kmap%(0 TO 80): ' index= controller-nummer

DIM SHARED amap%(0 TO 255): ' index= ascii-kode

 

keymap :' look-up table

 

Menu1:

CLS

LOCATE 5, 5: PRINT "Machine selection menu:";

LOCATE 7, 10: PRINT "1.- IPS33B - Digitech";

LOCATE 8, 10: PRINT "2.- TSR24 - Digitech";

LOCATE 9, 10: PRINT "3.- DHP55 - Digitech";

LOCATE 12, 10: PRINT "*.- QUIT";

DO

k$ = INKEY$

LOOP UNTIL k$ > ""

SELECT CASE k$

CASE "1"

machine$ = "IPS33B"

' set default start-up values:

FOR i% = 0 TO 126

controlmap%(i%) = i% + 1

' controllers 1 to 9 are used

NEXT i%

byte%(6) = 64: ' panning

byte%(7) = 127: ' master volume

'IPS33 basic midi channel:

mch% = 15

CASE "2"

machine$ = "TSR24"

FOR i% = 0 TO 127

controlmap%(i%) = i%

NEXT i%

mch% = 15

CASE "3"

machine$ = "DHP55"

FOR i% = 0 TO 127

controlmap%(i%) = i%

NEXT i%

mch% = 15

CASE "*"

END

CASE ELSE

GOTO Menu1

END SELECT

 

LOCATE 15, 10

PRINT "Controller numbers used will be:";

place% = 0

FOR i% = 0 TO 39

IF i% < 10 THEN

LOCATE 16 + (i% \ 10), 10 + place%:

PRINT controlmap%(i%)

place% = (place% + 5) MOD 50

ELSEIF i% < 20 THEN

LOCATE 16 + (i% \ 10), 10 + place% place% = (place% + 5) MOD 50

PRINT controlmap%(i%);

ELSEIF i% < 30 THEN

LOCATE 16 + (i% \ 10), 10 + place%

place% = (place% + 5) MOD 50

PRINT controlmap%(i%);

ELSEIF i% < 40 THEN

LOCATE 16 + (i% \ 10), 10 + place%

place% = (place% + 5) MOD 50

PRINT controlmap%(i%);

END IF

NEXT i%

LOCATE 21, 10

PRINT "The midi-channel used is"; mch%

SLEEP 10

 

' *************************************************************************

Explore:

CLS

LOCATE 25, 5

PRINT "LOGOSOFT - Dr.Godfried-Willem Raes -"; DATE$; "- Public Domain";

LOCATE 24, 10

PRINT " |=program-change +=note-ON -=note-OFF <space>= QUIT ";

regel = 1

LOCATE regel, 10

PRINT "Midi Continuous Controller Real Time Exploration Utility";

regel = regel + 1

LOCATE regel, 10

PRINT "********************* "; machine$; " ************************";

regel = regel + 2

LOCATE regel, 10

PRINT "Controllers: (Upper-Case=UP ; Lower-case= DOWN) ";

regel = regel + 1

LOCATE regel, 1

 

PRINT "1/! 2/@ 3/# 4/$ 5/% 6/^ 7/& 8/* 9/( 0/)";

regel = regel + 1

 

IF machine$ = "IPS33B" THEN

LOCATE regel, 1: regel = regel + 1

PRINT "Expr1 Expr2 Expr3 Expr4 Expr5 Expr6 Expr7 midi cc midi cc";

LOCATE regel, 1: regel = regel + 1

PRINT "Pitch L Pitch R Delay L Delay R LRpan dry/wet volume regen regen ";

END IF

 

FOR i% = 0 TO 9

LOCATE regel, 1 + (i% * 8)

PRINT HEX$(176); controlmap%(i%);

NEXT i%

blok1 = regel + 1

regel = regel + 3

 

LOCATE regel, 1: regel = regel + 1

 

PRINT "Q/q W/w E/e R/r T/t Y/y U/u I/i O/o P/p";

FOR i% = 10 TO 19

LOCATE regel, 1 + ((i% - 10) * 8)

PRINT HEX$(176); controlmap%(i%);

NEXT i%

blok2 = regel + 1

regel = regel + 3

LOCATE regel, 1: regel = regel + 1

PRINT "A/a S/S D/d F/f G/g H/h J/j K/k L/l :/;";

 

FOR i% = 20 TO 29

LOCATE regel, 1 + ((i% - 20) * 8)

PRINT HEX$(176); controlmap%(i%);

NEXT i%

blok3 = regel + 1

regel = regel + 3

LOCATE regel, 1: regel = regel + 1

PRINT "Z/z X/x C/c V/v B/b N/n M/m </, >/. ?//";

 

FOR i% = 30 TO 39

LOCATE regel, 1 + ((i% - 30) * 8)

PRINT HEX$(176); controlmap%(i%);

NEXT i%

blok4 = regel + 1

'regel = regel + 3

' Flush keyboard-buffer:

DO: LOOP UNTIL INKEY$ = ""

 

' **********************************************************************

' interaktieve kontrole - display 40 real-time controller-values:

DO

FOR i% = 0 TO 9

LOCATE blok1, 1 + (i% * 8)

PRINT byte%(controlmap%(i%)); " ";

NEXT i%

FOR i% = 10 TO 19

LOCATE blok2, 1 + ((i% - 10) * 8)

PRINT byte%(controlmap%(i%)); " ";

NEXT i%

FOR i% = 20 TO 29

LOCATE blok3, 1 + ((i% - 20) * 8)

PRINT byte%(controlmap%(i%)); " ";

NEXT i%

FOR i% = 30 TO 39

LOCATE blok4, 1 + ((i% - 30) * 8)

PRINT byte%(controlmap%(i%)); " ";

NEXT i%

 

k$ = INKEY$

IF k$ <> "" THEN

toets% = ASC(k$): ' ascii-waarde van de ingedrukte toets

kode% = amap%(toets%): ' kodegetal 0-79 voor kontrollers 1-40

' 0= even - 1=oneven

IF kode% MOD 2 = 0 THEN value% = -1 ELSE value% = 1 abskont% = controlmap%(kode% \ 2)

byte%(abskont%) = (byte%(abskont%) + value%)

' begrenzer:

IF byte%(abskont%) < 0 THEN byte%(abskont%) = 0

IF byte%(abskont%) > 127 THEN byte%(abskont%) = 127

IF machine$ = "IPS33B" THEN

IF abskont% = 8 OR abskont% = 9 THEN

' this limits the sum of both controllers to 100, as needed

' when these controllers are assigned to the regenerate Left

' and Right parameters.If not limited, overflow occurs in the IPS33B

IF byte%(8) > 100 THEN byte%(8) = 100: byte%(9) = 0

IF byte%(9) > 100 THEN byte%(9) = 100: byte%(8) = 0

IF byte%(8) + byte%(9) > 100 THEN

IF byte%(8) >= byte%(9) THEN

DO

byte%(8) = byte%(8) - 1

LOOP UNTIL byte%(8) + byte%(9) <= 100

ELSE

DO

byte%(9) = byte%(9) - 1

LOOP UNTIL byte%(8) + byte%(9) <= 100

END IF

END IF

END IF

END IF

' Uitsturing wanneer bytes verschillend zijn van hun vorige waarde:

IF machine$ = "IPS33B" THEN

' aangezien bij de IPS33B koppeling optreedt tussen de diverse

' kontrollers dienen alle gewijzigde waarden te worden opgespoord:

FOR i = 0 TO 120

IF byte%(controlmap%(i)) <> oldbyte%(controlmap%(i)) THEN

Uit (176 + mch%): Uit (i): Uit (byte%(controlmap%(i)))

oldbyte%(controlmap%(i)) = byte%(controlmap%(i))

END IF

NEXT i

ELSE

IF byte%(abskont%) <> oldbyte%(abskont%) THEN

Uit (176 + mch%): Uit (abskont%): Uit (byte%(abskont%))

oldbyte%(abskont%) = byte%(abskont%)

END IF

END IF

END IF

 

IF k$ = "|" THEN Progchanges

IF k$ = "+" THEN Noteonseq

IF k$ = "-" THEN Noteoffseq

IF k$ = " " THEN END

k$ = ""

LOOP

END

REM $STATIC

SUB keymap

' returns the filled array kmap%(0-79)

' look-up table for 40 keyboard-controller assignments

' in kommandovolgorde:

' eerste toetsenrij:

kmap%(0) = ASC("1"): ' dalend voor even

kmap%(1) = ASC("!"): ' stijgend voor oneven (shifted key)

kmap%(2) = ASC("2"): kmap%(3) = ASC("@")

kmap%(4) = ASC("3"): kmap%(5) = ASC("#")

kmap%(6) = ASC("4"): kmap%(7) = ASC("$")

kmap%(8) = ASC("5"): kmap%(9) = ASC("%")

kmap%(10) = ASC("6"): kmap%(11) = ASC("^")

kmap%(12) = ASC("7"): kmap%(13) = ASC("&")

kmap%(14) = ASC("8"): kmap%(15) = ASC("*")

kmap%(16) = ASC("9"): kmap%(17) = ASC("(")

kmap%(18) = ASC("0"): kmap%(19) = ASC(")")

' tweede toetsenrij:

kmap%(20) = ASC("q"): kmap%(21) = ASC("Q")

kmap%(22) = ASC("w"): kmap%(23) = ASC("W")

kmap%(24) = ASC("e"): kmap%(25) = ASC("E")

kmap%(26) = ASC("r"): kmap%(27) = ASC("R")

kmap%(28) = ASC("t"): kmap%(29) = ASC("T")

kmap%(30) = ASC("y"): kmap%(31) = ASC("Y")

kmap%(32) = ASC("u"): kmap%(33) = ASC("U")

kmap%(34) = ASC("i"): kmap%(35) = ASC("I")

kmap%(36) = ASC("o"): kmap%(37) = ASC("O")

kmap%(38) = ASC("p"): kmap%(39) = ASC("P")

' derde toetsenrij:

kmap%(40) = ASC("a"): kmap%(41) = ASC("A")

kmap%(42) = ASC("s"): kmap%(43) = ASC("S")

kmap%(44) = ASC("d"): kmap%(45) = ASC("D")

kmap%(46) = ASC("f"): kmap%(47) = ASC("F")

kmap%(48) = ASC("g"): kmap%(49) = ASC("G")

kmap%(50) = ASC("h"): kmap%(51) = ASC("H")

kmap%(52) = ASC("j"): kmap%(53) = ASC("J")

kmap%(54) = ASC("k"): kmap%(55) = ASC("K")

kmap%(56) = ASC("l"): kmap%(57) = ASC("L")

kmap%(58) = ASC(";"): kmap%(59) = ASC(":")

' vierde toetsenrij:

kmap%(60) = ASC("z"): kmap%(61) = ASC("Z")

kmap%(62) = ASC("x"): kmap%(63) = ASC("X")

kmap%(64) = ASC("c"): kmap%(65) = ASC("C")

kmap%(66) = ASC("v"): kmap%(67) = ASC("V")

kmap%(68) = ASC("b"): kmap%(69) = ASC("B")

kmap%(70) = ASC("n"): kmap%(71) = ASC("N")

kmap%(72) = ASC("m"): kmap%(73) = ASC("M")

kmap%(74) = ASC(","): kmap%(75) = ASC("<")

kmap%(76) = ASC("."): kmap%(77) = ASC(">")

kmap%(78) = ASC("/"): kmap%(79) = ASC("?")

 

' array in ascii-volgorde:

FOR i% = 0 TO 255

FOR j% = 0 TO 80

IF i% = kmap%(j%) THEN amap%(i%) = j%

NEXT j%

NEXT i%

END SUB

SUB Noteoffseq

Uit (144 + mch%): Uit (Noot%): Uit (0)

END SUB

 

SUB Noteonseq

Noot% = 24 + (RND(1) * 48)

Uit (144 + mch%): Uit (Noot%): Uit (127)

END SUB

 

SUB Progchanges

byte% = (RND(1) * 512) AND &H7F

Uit (192 + mch%): Uit (byte%)

END SUB

 

SUB Uit (b%)

IF DP = &H330 THEN

IF INP(&H331) AND 128 THEN

WAIT &H331, 64, 64: OUT DP, b%: EXIT SUB

ELSE

DO: dummy = INP(&H330): LOOP UNTIL INP(&H331) AND 128

WAIT &H331, 64, 64: OUT DP, b%: EXIT SUB

END IF

END IF

' Logotronics interfaces:

IF DP = &H2FA THEN

OUT &H2FA, b%: DO: LOOP UNTIL INP(&H2FB) AND 64: EXIT SUB

WHILE INP(&H2FB) < 64: WEND

END IF

IF DP = &H378 THEN

OUT &H378, b%: OUT &H37A, 0: ZZ# = ZZ# ^ ZZ#: OUT &H37A, 1

WHILE INP(&H379) AND 128: WEND

EXIT SUB

END IF

IF DP = &H320 THEN

' this is for Abulafia

OUT &H320, b%: OUT &H322, 0: ZZ# = TIMER + .00001

DO: LOOP UNTIL TIMER > ZZ#

OUT &H322, 1

WHILE INP(&H321) AND 128: WEND

EXIT SUB

ELSE

OUT DP, b%: OUT DP + 2, 0: T$ = "_": OUT DP + 2, 1

WHILE INP(DP + 1) AND 128: WEND

END IF

END SUB


 

Uitgaand van dit programma, is het niet erg moeilijk zelf een software- interface te schrijven dat zijn real-time input informatie nu eens niet betrekt uit manipulaties op het eerder beperkte komputerkeyboard, maar bvb. uit een reeks extern en via een ADC-kaart aan de komputer aangesloten sensoren.

Bijzonder geschikt daarvoor zijn o.m.:

- acceleratiemeters en transducers

- ultrasone bewegingsdetektoren

- mikrogolf-bewegingsdetektoren (radar) - piezoelektrische druktransducers

- potentiometers

- lichtgevoelige weerstanden

Meer informatie over de uitwerking van dergelijke projekten behoort echter tot het onderwerp van boekdeel 2, waar we ons uitvoerig met hardware en interaktiviteit gaan bezighouden.


 

Toepassingsvoorbeeld:

Een Echolood als midi continuous controller

Voor dit toepassingsvoorbeeld wordt uitgegaan van een als module op de markt verkrijgbare schakeling gepubliceerd in het amerikaanse elektronikatijdschrift Circuit Cellar. De bijhorende schemas en dokumentatie werden aan deze paragraaf toegevoegd. De praktische demonstratie van een en ander gebeurt in de les.

De software waarmee de schakeling als een midi-real-time controller kan worden gebruikt volgt hier:

 

' **************************************************************************

' * RANGER.BAS *

' * test-program for Ultrasonic Ranger *

' * to be used as a midi continuous controller *

' **************************************************************************

' Hardware conditions:

' - use Ciarcia's Circuit Cellar 50kHz Ultrasonic Ranging System

' based on a Polaroid sensor device.

' - connect to parallel printer port. Only 3 bits are used.

' - internal power supply: 5V dc - TTL compatible

' - meetbereik: 40cm - 10m Precizie: 2% (ca. 6-bits)

' - sampling rate: max. 12.5 s/s (recycle period= 80ms)

' - after switching on the Sonar-device, wait 5 milliseconds

' before sending the first INIT-command.

' - The pinning of the DIN-connector on SONAR-device is:

' PIN 1 = + 5V (can be used to detect whether the device is

' switched on

' PIN 2 = GROUND

' PIN 3 = NC

' PIN 4 = INIT (from computer to ranger)

' PIN 5 = ECHO (from ranger to computer)

' - The pinning on the DB25 printerconnector should be as follows:

' PIN 1 = -Strobe: bit 0 &H37A WR not used

' PIN 2 = Data-bit 0 &H378 INIT (DIN-pin4)

' PIN 3 = Data-bit 1 &H378

' PIN 4 = Data-bit 2 &H378

' PIN 5 = Data-bit 3 &H378

' PIN 6 = Data-bit 4 &H378

' PIN 7 = Data-bit 5 &H378

' PIN 8 = Data-bit 6 &H378

' PIN 9 = Data-bit 7 &H378

' PIN 10= -Acknowledge: bit 6 &H379 RD

' PIN 11= Busy: bit 7 &H379 RD ECHO (DIN-pin5)

' PIN 12= Paper End: bit 5 &H379 RD

' PIN 13= Select: bit 4 &H379 RD +5V (DIN-pin1)

' Second Row:

' PIN 14=-Autofeed: bit 1 &H37A WR

' PIN 15=-Error bit 3 &H379 RD

' PIN 16=-Init Printer: bit 2 &H37A WR

' PIN 17=-Select Input: bit 3 &H37A WR

' PIN 18-25= GROUND GROUND (DIN-pin2)

' 07.08.1993: hardware build' 05.03.1995: first working version

' hardware bugs removed. Cables checked.

' 06.03.1995: Timer - instructions removed

' They are not precize enough.

' Counter will be used instead.

' Time callibration routine should be written now

' 07.03.1995: Autocallibrating counter added

 

' Declaration of contants and variables:

CONST Wadr = &H378: ' use bit 0 as INIT-bit

CONST Radr = &H379: ' use bit 7 as echo databit

' use bit 4 to detect Sonar Device powered up.

' Omzettingskonstante:

' = geluidssnelheid/2 ( afstand= v.t/2 in sonar)

' 170 * 10 om uitkomst te hebben in decimeter

' 170 * 100 voor centimeter

' in teorie= 17000, maar deze waarde bleek onjuist

' een korrektiefaktor van 1.6 bleek nodig. Dus:

CONST Konst = 27200

CONST Inithigh = 1

CONST Initlow = 0

CONST Echo = 128

CONST Power = 16

CONST Channel = 0

CONST Cc = 176

 

COMMON SHARED Dist%, t#, timunit#, Delta%, Richting%

 

DECLARE SUB InitSonar ()

DECLARE SUB GetRange ()

DECLARE SUB Calibrate ()

DECLARE SUB Uit ()

 

' Initialisatie:

CP = INP(&H379)

DP = INP(&H378)

CLS

InitSonar

Calibrate

SHELL "C:\bc7\bom\MPUUART.EXE"

 

' Procedure:

LOCATE 14, 10

PRINT "Detected object is at a distance in centimeter of=";

LOCATE 15, 10

DO

GetRange

IF Dist% THEN

LOCATE 15, 10

PRINT Dist%; "cm", Delta%; "cm/s", Richting%;

byte% = (Dist% \ 2) AND &H7F

Uit (Cc + Channel): Uit (byte%)

END IF

SOUND 20000, 2

LOOP UNTIL INKEY$ <> ""

 

' Afsluiting:

LOCATE 18, 10PRINT " Reset printer-port on exit ? (Y/N)"

DO: k$ = INKEY$: LOOP UNTIL k$ <> ""

 

IF k$ = "Y" OR k$ = "y" THEN

' reset printerport to its original state:

LOCATE 19, 10

PRINT "Disconnect cable from ranging device now !";

SLEEP 20

OUT Wadr, DP

OUT Radr, CP

END IF

 

END

 

SUB Calibrate

ti# = TIMER

tt% = 0

DO: tt% = tt% + 1: LOOP UNTIL tt% = 32767

cnt# = TIMER - ti#

timunit# = (cnt# * Konst) / 32767#

END SUB

 

SUB GetRange

STATIC Olddist%

tt% = 0: ' reset time-counter

OUT Wadr, Inithigh: ' make INIT High. This enables the 420kHz

' oscillator and causes a transmit of 16

' cycles @ 300V - 49.4kHz

' The transducer holds a 150V dc bias, for receive.

' The osc. output steps to 93kHz and remains there as

' long as INIT stays high.

' DO : LOOP UNTIL (INP(Radr) AND Echo)

DO: tt% = tt% + 1: LOOP UNTIL (INP(Radr) XOR 255)

' Echo byte is inverted on printeradapter.

' Wait for echo. (When echo pulses high)

OUT Wadr, Initlow: ' make init low again.

Dist% = tt% * timunit#: ' read time-count value

 

' mits een konstante samplingfrekwentie (bv. 10 samples/s)

' kan ook de bewegingssnelheid in 1 dimensie worden afgeleid:

' Merk op dat de meetfout hier 2% * 2% = 4% beloopt, en dat de snelheid ook

' een funktie is van de cosinus van de bewegingshoek tegenover de rechte

' gevormd door de ultrasone golf!

IF Olddist% THEN

Delta% = Olddist% - Dist%

Richting% = SGN(Delta%)

Delta% = ABS(Delta%)

Olddist% = Dist%

ELSE

Olddist% = Dist%

END IF

 

END SUB

 

SUB InitSonar

OUT Wadr, Initlow

' check power-on:

IF INP(Radr) AND Power THEN SLEEP 1

ELSE

BEEP

LOCATE 10, 10:

PRINT "Sonar device unavailable or not powered on."

SLEEP 10

END

END IF

 

END SUB

 

SUB Uit

' hier komt de klassieke midi-uit procedure voor het interface naar keuze

' Cfr. andere plaats in deze syllabus

END SUB


 

Verdere perspektieven en toepassingsmogelijkheden:

 

- Wanneer we de software note-on/note-off kommandos laten uitsturen verkrijgen we een goed bespeelbare, maar één-dimensionele, Theremin.

- Het opzet van de schakeling leent zich uitstekend voor toepassingen in het domein van het muziekteater. Hier kan bvb. het geluidsvolume of de panning automatisch in funktie worden gesteld van de plaats van een akteur of uitvoerder op de scene.

- Het voorbeeld zoals hier gegeven is in meer dan één opzicht eigenlijk een 'overkill'. Er wordt immers een enorme hoeveelheid komputerkracht verspild. Daarom zou het beter zijn in deze toepassing een klein dedicated system toe te passen, of zelfs, de counter in hardware uit te voeren. Zelf een eenvoudige 1-chip 'Basic-stamp' kan de hier gevergde taken makkelijk aan, wanneer althans geen direkte 31.5kBaud midi-output wordt verlangd. De Basic-stamp kan wel rechtstreeks een RS232 signaal afgeven aan 1200 of 2400 Baud, wat ruim volstaat.

 

Voorbeeldprogramma:

 

Joachim Brackx schreef in 1995 een kleine algoritmische en interaktieve kompositie waarin van het hier beschreven echolood gebruik wordt gemaakt. De kode, waarin je veel procedures zult herkennen uit het vorige programma 'Ranger.bas', volgt hier:

 

< PULSE-PONG >

 ' 28.03.1995: Ranger routines used by Joachim Brackx for composition program "Pulse-Pong"

' Declaration of contants and variables:

CONST Wadr = &H378: ' use bit 0 as INIT-bit

CONST Radr = &H379: ' use bit 7 as echo databit

CONST Konst = 27200

CONST Inithigh = 1

CONST Initlow = 0

CONST Echo = 128

CONST Power = 16

CONST Channel = 0

CONST Cc = 176

 

COMMON SHARED Dist%, t#, timunit#, Delta%, richting%COMMON SHARED Tc%

 

DECLARE SUB InitSonar ()

DECLARE SUB GetRange ()

DECLARE SUB Calibrate ()

DECLARE SUB Uit (Byte%)

DECLARE SUB AllOff (dd%)

DECLARE SUB InitProteus ()

DECLARE SUB VerGrond ()

DECLARE SUB mpuuart ()

 

' Initialisatie:

CP = INP(&H379): DP = INP(&H378) :CLS

InitSonar

Calibrate

mpuuart

InitProteus

SCREEN 12

' Procedure:

LOCATE 10, 8: PRINT "Dist% :"

 

LINE (0, 200)-(640, 200)

LINE (0, 250)-(640, 250)

FOR i = 1 TO 5

LINE (125 * i, 200)-(125 * i, 250)

NEXT i

OldPos = 100

Finish% = 0

AantInt% = 1

RANDOMIZE (TIMER)

Tc% = INT(RND(1) * 12) + 54

 

Flag% = 1

COLOR 9

LOCATE 5, 10: PRINT "Waiting..."

COLOR 15

DO

GetRange

 

SOUND 20000, 3

LOOP UNTIL Dist% < 200

COLOR 1

LOCATE 5, 10: PRINT "Playing..."

COLOR 15

DO

GetRange

IF Dist% > 260 THEN Dist% = 300

IF Dist% < 50 THEN Dist% = 50

 

IF Dist% <> 300 THEN

Detect% = 1

IF ODet% = 0 THEN DetFlag% = 1

ODet% = 1

X% = (Dist% - 50) * 2.56

LINE (OX%, 210)-(OX%, 240), 0

LINE (X%, 210)-(X%, 240): OX% = X%

ELSE

Detect% = 0

ODet% = 0

END IF

 

LOCATE 10, 15: PRINT Dist%; " "

LOCATE 20, 10: PRINT AantInt%

LOCATE 22, 10: PRINT Tc%

 

IF Detect% THEN

SELECT CASE Dist%

CASE 251 TO 280

Finish% = 1

CASE 201 TO 250

IF DetFlag% = 1 THEN VerGrond

DetFlag% = 0

State% = 4

CASE 151 TO 200

IF DetFlag% THEN

AantInt% = AantInt% + 1

IF AantInt% > 7 THEN AantInt% = 7

END IF

DetFlag% = 0

State% = 2

CASE 101 TO 150

'nothing

IF DetFlag% THEN

AantInt% = AantInt% - 1

IF AantInt% <= 0 THEN AantInt% = 1

END IF

DetFlag% = 0

State% = 2

CASE 50 TO 100

Par% = INT((Dist% - 50) * 2)

Uit (176): Uit (7): Uit (Par%)

Uit (178): Uit (7): Uit (100 - Par%)

State% = 1

END SELECT

END IF

 

IF OState% <> State% THEN PercFlag% = 1

OState% = State%

 

RANDOMIZE (TIMER)

qq# = .6 / AantInt%

zz# = RND(1) * qq#

tt# = TIMER

Note% = (Tc% + INT(RND(1) * AantInt%) * 7) MOD 12 + (INT(RND(1) * 5) + 3) * 12

Note2% = (Tc% MOD 12) + 36

Vel% = 127 - INT(zz# * 200)

Pan% = INT(RND(1) * 126) + 1

DO UNTIL TIMER >= tt# + zz#: LOOP

SOUND 20000, 2

Uit (128): Uit (ONote%): Uit (64)

 

Uit (130): Uit (ONote%): Uit (64)

Uit (176): Uit (10): Uit (Pan%)

Uit (178): Uit (10): Uit (127 - Pan%) Uit (144): Uit (Note%): Uit (Vel%): ONote% = Note%

Uit (146): Uit (Note%): Uit (Vel%)

IF PercFlag% THEN

Uit (129): Uit (Onote2%): Uit (64)

Uit (145): Uit (Note2%): Uit (127): Onote2% = Note2%

PercFlag% = 0

END IF

 

LOOP UNTIL INKEY$ = CHR$(27) OR Finish% = 1

AantInt% = 7

COLOR 12

LOCATE 5, 10: PRINT "THE END..."

COLOR 15

DO

GetRange

LOCATE 10, 15: PRINT Dist%

IF Dist% <> 300 THEN

X% = (Dist% - 50) * 2.56

LINE (OX%, 210)-(OX%, 240), 0

LINE (X%, 210)-(X%, 240): OX% = X%

END IF

RANDOMIZE (TIMER)

qq# = .8 / AantInt%

zz# = RND(1) * qq#

tt# = TIMER

Note% = (Tc% + INT(RND(1) * AantInt%) * 7) MOD 12 + (INT(RND(1) * 5) + 3) * 12

Pan% = INT(RND(1) * 126) + 1

Vel% = AantInt% * 18

DO UNTIL TIMER >= tt# + zz#: LOOP

SOUND 20000, 2

Uit (128): Uit (ONote%): Uit (64)

Uit (130): Uit (ONote%): Uit (64)

Uit (176): Uit (10): Uit (Pan%)

Uit (178): Uit (10): Uit (127 - Pan%)

Uit (144): Uit (Note%): Uit (Vel%): ONote% = Note%

Uit (146): Uit (Note%): Uit (Vel%)

AantInt% = INT((Dist% - 50) / 35)

LOCATE 20, 10: PRINT AantInt%

LOOP UNTIL AantInt% = 0

 

 

AllOff (3)

 

CLS

' Afsluiting:

LOCATE 18, 10

PRINT " Reset printer-port on exit ? (Y/N)"

DO: k$ = INKEY$: LOOP UNTIL k$ <> ""

 

IF k$ = "Y" OR k$ = "y" THEN

' reset printerport to its original state:

LOCATE 19, 10

PRINT "Disconnect cable from ranging device now !";

SLEEP 20

OUT Wadr, DP

OUT Radr, CP

END IF

END

SUB AllOff (dd%)

FOR i = 1 TO dd%

FOR j = 1 TO 127

Uit (127 + i): Uit (j): Uit (64)

NEXT j

NEXT i

END SUB

 

SUB Calibrate

ti# = TIMER

tt% = 0

DO: tt% = tt% + 1: LOOP UNTIL tt% = 32767

cnt# = TIMER - ti#

timunit# = (cnt# * Konst) / 32767#

END SUB

 

SUB GetRange

STATIC Olddist%

tt% = 0: ' reset time-counter

OUT Wadr, Inithigh: ' make INIT High.

DO: tt% = tt% + 1: LOOP UNTIL (INP(Radr) XOR 255)

' Wait for echo. (When echo pulses high)

OUT Wadr, Initlow: ' make init low again.

Dist% = tt% * timunit#: ' read time-count value

 

IF Olddist% THEN

Delta% = Olddist% - Dist%

richting% = SGN(Delta%)

Delta% = ABS(Delta%)

Olddist% = Dist%

ELSE

Olddist% = Dist%

END IF

END SUB

 

SUB InitProteus

Uit (192): Uit (64)

Uit (193): Uit (51)

Uit (194): Uit (70)

Uit (176): Uit (7): Uit (100)

Uit (178): Uit (7): Uit (0)

END SUB

 

SUB InitSonar

OUT Wadr, Initlow

IF INP(Radr) AND Power THEN

SLEEP 1

ELSE

BEEP : LOCATE 10, 10:

PRINT "Sonar device unavailable or not powered on."

SLEEP 10 : END

END IF

END SUB

SUB mpuuart

' zie elders

END SUB

SUB VerGrond

RANDOMIZE (TIMER)

kans = INT(RND(1) * 5) + 1

SELECT CASE kans

CASE 1

RANDOMIZE (TIMER)

Tc% = INT(RND(1) * 12) + 54

CASE 2

Tc% = Tc% + 7

CASE 3

Tc% = Tc% - 7

CASE 4

Tc% = Tc% + 4

CASE 5

Tc% = Tc% - 4

END SELECT

END SUB


Terug naar de inhoudstafel: <Index Kursus>

Naar homepage Dr.Godfried-Willem RAES