MSX turbo R - De PCM controller

Last updated on: August 21, 1998

Deze keer zullen we het rechtstreeks aansturen van de PCM controller van de MSX turbo R bespreken. Met deze PCM controller is het mogelijk om samples op te nemen en af te spelen.

De PCM controller kan vrij eenvoudig worden aangestuurd via een paar routines in de ROM BIOS. In MCCM 72 is te vinden hoe die routines gebruikt moeten worden.
Hoewel deze BIOS routines handig te gebruiken zijn, hebben ze ook een tweetal nadelen:

Het is mogelijk om deze beperkingen te omzeilen door de PCM controller rechtstreeks aan te sturen.

De in/out poorten
De PCM controller gebruikt twee in/out (I/O) poorten. Verder heeft de MSX turbo R ook nog twee andere I/O poorten die handig zijn bij het samplen. Op deze twee poorten zit een 16 bits teller die gebruikt kan worden om de sample frequentie af te regelen. In totaal hebben we dus te maken met vier I/O poorten. De precieze functie van deze poorten hangt ervan af of je een waarde naar de poorten toe schrijft of dat je ze uitleest. De betekenis van de poorten is te vinden in tabel 1, voor het uitlezen van de poorten, en in tabel 2, voor het schrijven naar de poorten. 
Addr b7 b6 b5 b4 b3 b2 b1 b0
0a4h 0 0 0 0 0 0 CT1 CT0
0a5h CMP 0 0 HLD SEL FIL MUT BUF
0e6h 16 bits teller LSB
0e7h 16 bits teller MSB
  tabel 1: de poorten uitlezen
 
Addr b7 b6 b5 b4 b3 b2 b1 b0
0a4h DA7 DA6 DA5 DA4 DA3 DA2 DA1 DA0
0a5h 0 0 0 HLD SEL FIL MUT BUF
0e6h reset 16 bits teller
0e7h --- --- --- --- --- --- --- ---
  tabel 2: schrijven naar de poorten
 
I/O poort 0a4h uitlezen
Op I/O poort 0a4h zit een 2-bits teller welke uit te lezen is en die om de 228 klokpulsen wordt opgehoogd. Daar de hoofdklok frequentie in de MSX computer 3,579545 MHz is, wordt deze teller 15700 keer per seconde opgehoogd. De sample routines in de ROM BIOS maken hier gebruik van om de sample frequentie te bepalen. Vandaar dat die routines alleen kunnen opnemen en afspelen met de volgende vier sample frequenties:

Naar I/O poort 0a4h schrijven
Verder zit op I/O poort 0a4h een digitaal analoog converter (DAC) welke aan de geluidsuitgang van de MSX turbo R gekoppeld is. Deze DAC zet de waarde die het laatst naar I/O poort 0a4h is geschreven om in een analoge spanning. De waarde die naar deze poort is geschreven wordt opgevat als een 8 bits positief getal. Dit houdt in dat de waarde 0 overeenkomt met de laagste spanning, de waarde 128 met de midden spanning en de waarde 255 met de hoogste spanning. Verder wordt de teller op I/O poort 0a4h gereset op het moment dat je naar deze poort schrijft.

I/O poort 0a5h
Op I/O poort 0a5h zitten vijf controle bits waarnaar geschreven kan worden en die ook uit te lezen zijn. Deze bits hebben de volgende functie:

SEL: Select
Dit bit bepaalt welk geluidssignaal op de uitgang van de PCM controller komt te staan. Als SEL 0 is, is de DAC aan de uitgang van de PCM controller gekoppeld en kunnen samples worden afgespeeld. Anders is de microfoon aan deze uitgang gekoppeld en kan de MSX turbo R als microfoon gebruikt worden en kunnen er eventueel samples worden opgenomen.

FIL: Filter
Met dit bit kan de geluidsbron voor het PCM filter worden ingesteld. Dit PCM filter zit voor de zogenaamde verschil versterker die nodig is om samples op te nemen. Als FIL 0 is, is de ingang van het PCM filter aan de massa gekoppeld en kunnen er geen samples worden opgenomen. Anders zit de ingang van het filter op de geluidsuitgang van de PCM controller en kunnen er wel samples worden opgenomen. Om samples op te nemen moeten dus zowel SEL als FIL geset worden.

MUT: Muting
Met dit bit kan de geluidsuitgang van de MSX turbo R worden in en uitgeschakeld. Indien MUT 0 is, staat het geluid uit terwijl als MUT 1 is het geluid juist aan staat.

HLD: Sample/hold
Dit bit bepaalt of het signaal op de sample ingang van de verschil versterker zolang mogelijk vastgehouden moet worden of niet. Dit is dus het signaal dat uit het PCM filter komt. Als HLD 1 is, wordt het signaal zolang mogelijk vastgehouden zodat het analoge signaal omgezet kan worden in een binaire waarde zonder dat het signaal tijdens die conversie verandert. Indien HLD daarentegen 0 is, wordt het signaal dat op de sample ingang aangeboden wordt, zo snel mogelijk gevolgd.

BUF: Buffer mode
Dit bit bepaalt of de dubbel buffer functie van de DAC aan of uit staat. Indien BUF 1 is, staat de dubbel buffer functie aan en is het opnemen van geluid zo goed als onmogelijk; er wordt dan een gigantische ruis opgenomen. Als BUF daarentegen 0 is, staat de dubbel buffer functie uit. Geluid opnemen is dan wel mogelijk. Tijdens het afspelen van samples kan BUF het beste op 1 worden gezet.

Het CMP bit
Behalve deze vijf controle bits zit op I/O poort 0a5h ook nog een bit dat alleen gelezen kan worden. Dit bit, met de naam CMP, is de uitgang van de verschil versterker die nodig is om samples op te nemen. Een verschil versterker is een chip met twee ingangen en een uitgang, die het spannings verschil tussen deze twee ingangen zo hard mogelijk versterkt en dit verschil vervolgens op de uitgang zet. Eén ingang van deze verschil versterker is altijd gekoppeld aan de uitgang van de DAC die op I/O poort 0a4h zit. De andere ingang van de verschil versterker is de zogenaamde sample ingang en deze is aan de microfoon gekoppeld als SEL en FIL beiden 1 zijn. In dit geval is aan het CMP bit dus te zien welke spanning hoger is; de spanning afgeleverd door de DAC of de spanning afgeleverd door de microfoon. CMP is 0 als de microfoon een lagere spanning afgeeft dan de DAC terwijl CMP juist 1 is als de microfoon een hogere spanning afgeeft dan de DAC.

De MSX turbo R heeft geen ADC
Zoals wel uit de omschrijving van de PCM controller poorten blijkt, heeft de MSX turbo R geen ingebouwde analoog digitaal converter (ADC). Desondanks is het toch mogelijk om met de MSX turbo R samples op te nemen. Dit kan gedaan worden door gebruik te maken van de DAC en de verschil versterker. Het converteren van een analoog signaal -dat uit de microfoon komt- naar een binair getal kan namelijk als volgt plaatsvinden:
Zet eerst een waarde op de DAC en kijk vervolgens naar het CMP bit om te zien of die waarde hoger of lager is dan het analoge signaal. Als het signaal op de DAC te laag is, zet je er een hogere waarde op en kijk je weer. Anders zet je er juist een lagere waarde op en kijk je weer. Dit proces kan herhaald worden totdat de juiste waarde gevonden is. In feite zoek je op deze manier naar een binair getal dat via de DAC wordt omgezet in een even hoge spanning als de microfoon afgeeft.
Dit zoekproces kan vrij snel worden gemaakt door een zogenaamd binair zoek algoritme te gebruiken:

De ADC routine
Een voorbeeld routine waarin een ADC algoritme uitgevoerd wordt, is te vinden in de listing adc-tr.gen. Eerst wordt via I/O poort 0a5h de PCM controller geinitialiseerd:
de bits HLD, SEL, en FIL worden geset zodat de microfoon ingang op de verschil versterker zit en zodat het huidige analoge signaal wordt vastgehouden. Verder wordt het bit MUT gereset zodat het geluid uitstaat om te voorkomen dat het gaat rondzingen nu de microfoon open staat en wordt het bit BUF gereset om te voorkomen dat er ruis wordt opgenomen. Daarna wordt in een lusje het binaire zoekproces uitgevoerd en in de laatste stap wordt het HLD bit weer gereset zodat het microfoon signaal weer wordt gevolgd.

Merk trouwens op dat het programma gebruikt maakt van de instructie in (hl),(c). Deze instructie leest een waarde in via I/O poort c, slaat die waarde niet op, maar past wel de vlag-registers aan zoals bijvoorbeeld de sign-flag. Dit is een officiele Z80 instructie die echter niet door alle Z80 assemblers ondersteund wordt. Op de R800 is deze instructie omgedoopt tot in f,(c) om aan te geven dat ze alleen de vlag-registers verandert. Mocht je een assembler gebruiken die deze instructie niet herkent, dan kun je ze vervangen door defb 0edh, 070h.
Deze input instructie wordt hier gebruikt om het CMP bit te controleren; het CMP bit is bit 7 van de I/O poort wat overeenkomt met het sign bit van de Z80/R800. Als dit sign bit 0 is, komt dat overeen met een positief getal en als het bit 1 is komt dat overeen met een negatief getal. Daardoor hoeft niet nog eens expliciet op de waarde van het CMP bit gecontroleerd te worden. Direct na het uitlezen van de I/O poort staat een conditionele sprong die alleen uitgevoerd wordt als er een positief getal ingelezen is, dus als het CMP bit 0 is.
De routine kan nog versneld worden door het lusje helemaal uit te coderen. Dan kunnen de instructies srl l en djnz verdwijnen waardoor de totale conversie not iets sneller verloopt. Zo'n versnelde routine is te vinden in de listing fadc-tr.gen. Die routine maakt ook nog gebruik van een wiskundig trucje om het samplen te verder te versnellen. Lees de remregels in de file maar eens goed door.

De sample-frequentie
We weten nu hoe een enkele byte kan worden gesampled. Om echter een compleet geluidsfragment op te nemen, dienen er zeer veel bytes achter elkaar te worden gesampled met iedere keer een korte wachtpauze ertussen. De lengte van deze pauze bepaalt de kwaliteit van de opname; hoe korter de pauze, des te beter de opname. Hier staat echter wel tegenover dat er dan meer bytes moeten worden opgenomen om een gluidsopname met dezelfde tijdsduur te maken. De kwaliteit van een sample wordt dan ook vaak uitgedrukt in de zogenaamde samplefrequentie; dit is het aantal bytes dat je per seconde opneemt. Als je bijvoorbeeld alleen spraak wilt opnemen, is een samplefrequentie van 7 kHz, dus 7000 bytes per sconde, ruim voldoende. Maar als je muziek wilt opnemen met CD-kwaliteit, heb je een sample-frequentie van 44kHz nodig. Dit haalt de MSX turbo R niet.

I/O-poort 0e6h gebruiken
Op de MSX turbo R kun je de samplefrequentie vrij nauwkeurig afregelen met de 16-bits teller op I/O poort 0e6h en 0e7h. Deze teller wordt om de 14 klokpulsen opgehoogd, ofwel 255682 keer per seconde. Als je bijvoorbeeld wilt opnemen met een sample-frequentie van 15980 Hz, zul je tussen het opnemen van twee opeenvolgende waarden moeten wachten tot deze teller zestien tikken hoger is geworden. Deze wachttijd tussen het opnemen van twee opeenvolgende waarden, kan als volgt worden uitgerekend:

In bovenstaand voorbeeld geldt dus: Zoals wel uit dit voorbeeld blijkt, is de wachttijd kleiner dan 256. Zelfs bij een sample-frequentie van 7 kHz is de wachttijd slechts 37 tikken. Het is dus voldoende om alleen naar de laagste acht bits van de teller te kijken. Deze zijn te vinden op I/O poort 0e6h.

Een mini sample tool.
In de listing samtool.gen is een programma te zien dat een sample opneemt met een sample-frequentie van 15980 Hz en die sample vervolgens weer afspeelt. Dit programma kan onder MSXDOS geassembleerd worden met bijvoorbeeld Gen80. De geassembleerde versie is tevens te vinden in de lzh file, maar heet dan samtool.com. het opnemen van de sample zelf gebeurt met de routine uit de listing adc-tr.gen; er wordt iedere keer een byte opgenomen en vervolgens opgeslagen in het geheugen.

Het afspelen van de sample is uiterst eenvoudig: zet gewoon de opgenomen waarden een voor een op de DAC en wacht tussendoor lang genoeg om de goede samplefrequentie te krijgen. Voordat het afspelen start, wordt eerst de PCM controller op geluidsuitvoer ingesteld door SEL te resetten en MUT te setten.

Verbeteringen
Deze mini sample tool kan uiteraard nog sterk uitgebreid worden door de fanatieke lezer. Een aantal handige opties zijn bijvoorbeeld het wegschrijven en inlezen van samples, opnemen en afspelen met andere samplefrequenties en het opnemen en afspelen van extra lange samples door de memory mapper te gebruiken. Verder valt te denken aan edit functies als het knippen in samples, het bij elkaar optellen en verder nog het filteren van samples.

De mini sample tool controleert trouwens niet of deze op een MSX turbo R wordt opgestart en selecteert ook de R800 niet. Voordat je de tool start, zul je dus eerst zelf de R800 moeten activeren. Dit kan bijvoorbeeld door de MSX turbo R onder MSXDOS2 op te starten. Een andere optie is om de tool aan te passen, zodat deze zelf de R800 aanzet met behulp van de ROMBIOS routines op adres 0180h; zie hiervoor MCCM 72.