Dec 102017
 
TP source code that access the CMS chip on some Sound Blasters.
File CMSUNIT.ZIP from The Programmer’s Corner in
Category Pascal Source Code
TP source code that access the CMS chip on some Sound Blasters.
File Name File Size Zip Size Zip Type
CMS.PAS 6153 1734 deflated
CMSALARM.PAS 579 284 deflated
CMSVOICE.TXT 19944 4272 deflated

Download File CMSUNIT.ZIP Here

Contents of the CMSVOICE.TXT file


Greetings,

Here is a first run at some documentation for the optional CMS Music chips
available for the Soundblaster 1.5 and 2.0. (Previous versions of the
Soundblaster included these CMS chips).

Please let me know if you have any problems or additions to this. If my
network administrator will ever quit having fun in redefining our internet
addresses, I may actually receive the mail!

This document is done in the style of the document by Jeffrey S. Lee which
documented the Adlib FM Music Chips. Hopefully, future documents will stick
to this format.

+----------------------------------------------------------------------+
| Jerry Joplin | [email protected] | All these worlds are yours |
| Sunnyvale, CA | Compu$erve: 70441,2627 | except California. |
+---------------+-------------------------+----------------------------+

-------------------------------------------------------------------------------

Programming the Soundblaster
CMS Music Chips
Version 1.0 (6 Mar 1992)

Copyright (c) 1991, 1992 by Jerry Joplin
[email protected]



Format and much of the text of this document was taken from:

Programming the AdLib/Sound Blaster
FM Music Chips
Version 2.0 (24 Feb 1992)

Copyright (c) 1991, 1992 by Jeffrey S. Lee

[email protected]




Warranty and Copyright Policy

This document is provided on an "as-is" basis, and its author makes no
warranty or representation, express or implied, with respect to its
quality performance or fitness for a particular purpose. In no event
will the author of this document be liable for direct, indirect,
special, incidental, or consequential damages arising out of the use or
inability to use the information contained within. Use of this document
is at your own risk.

This file may be used and copied freely so long as the applicable
copyright notices are retained, and no modifications are made to the
text of the document. No money shall be charged for its distribution
beyond reasonable shipping, handling and duplication costs, nor shall
proprietary changes be made to this document so that it cannot be
distributed freely. This document may not be included in published
material or commercial packages without the written consent of its
author.



Overview

Two of the most popular sound cards for the IBM-PC, the AdLib and the
Sound Blaster, suffer from a real dearth of clear documentation for
programmers. AdLib Inc. and Creative Labs, Inc. both sell developers'
kits for their sound cards, but these are expensive, and (in the case of
the Sound Blaster developers' kit) can be extremely cryptic.

This document is submitted to the Soundblaster Freedom Project and is
intended to provide programmers with a FREE source of information about
the programming of these sound cards.

The information contained in this document is a combination of
information found in the Sound Blaster Software Developer's Kit, and
that learned by painful experience. This document only applies to the
optional CMS Music chips available for the Sound Blaster 1.5 and 2.0.
All previous versions of the Soundblaster included these CMS chips.

Please note that numbers will be given in hexadecimal, unless otherwise
indicated. If a number is written out longhand (sixteen instead of 16)
it is in decimal.


Chapter One - CMS Chip I/O

CMS chips provide the Sound Blaster with an additional twelve stereo
voices, and four noise generators. A programmable sound generator is
used to create amplitude modulated sound on each voice.

The chips are programmed by sending data to a voice's internal registers
via its two I/O ports:

Voice 1 - Voice 6 Voice 7 - Voice C

02?1 (hex) - register address 02?3 (hex) - register address
02?0 (hex) - data to register 02?2 (hex) - data to register

The ports given are relative to the base I/O address. Using the default
base I/O address of 0220 (hex):

Voice 1 - Voice 6 Voice 7 - Voice C

0221 (hex) - register address 0223 (hex) - register address
0220 (hex) - data to register 0222 (hex) - data to register

The CMS chips possess an array of thirty two registers; to write to a
voice's particular register, send the register number (00-1F) to the
address port, followed by the desired value to the data port.



Chapter Two - The Registers

The following table shows the function of each CMS chip register.
Registers will be explained in detail after the table. Registers not
listed are unused.

Address Function
------- ----------------------------------------------------
00 Right and Left Channel Amplitude for Voice 1/ Voice 7
01 Right and Left Channel Amplitude for Voice 2/ Voice 8
02 Right and Left Channel Amplitude for Voice 3/ Voice 9
03 Right and Left Channel Amplitude for Voice 4/ Voice A
04 Right and Left Channel Amplitude for Voice 5/ Voice B
05 Right and Left Channel Amplitude for Voice 6/ Voice C

08 Tone Frequency for Voice 1/ Voice 7
09 Tone Frequency for Voice 2/ Voice 8
0A Tone Frequency for Voice 3/ Voice 9
0B Tone Frequency for Voice 4/ Voice A
0C Tone Frequency for Voice 5/ Voice B
0D Tone Frequency for Voice 6/ Voice C

10 Octave for Voice 2/8, Octave for Voice 1/7
11 Octave for Voice 4/A, Octave for Voice 3/9
12 Octave for Voice 6/C, Octave for Voice 5/B

14 Frequency enable bits
15 Noise enable bits
16 Noise frequency select bits

1C Frequency Reset/Sound enable



Explanations of Registers

Registers 00 through 05

- These registers are used to set the Right and Left
channel amplitude control. The 4 bits of amplitude
control are defined as:

0000 minimum amplitude, off
1111 maximum amplitude

- Register 00

7 6 5 4 3 2 1 0
+-----+-----+-----+-----+-----+-----+-----+-----+
|right amp. Voice 1/7 | left amp. Voice 1/7 |
+-----+-----+-----+-----+-----+-----+-----+-----+

- Register 01

7 6 5 4 3 2 1 0
+-----+-----+-----+-----+-----+-----+-----+-----+
|right amp. Voice 2/8 | left amp. Voice 2/8 |
+-----+-----+-----+-----+-----+-----+-----+-----+

- Register 02

7 6 5 4 3 2 1 0
+-----+-----+-----+-----+-----+-----+-----+-----+
|right amp. Voice 3/9 | left amp. Voice 3/9 |
+-----+-----+-----+-----+-----+-----+-----+-----+

- Register 03

7 6 5 4 3 2 1 0
+-----+-----+-----+-----+-----+-----+-----+-----+
|right amp. Voice 4/A | left amp. Voice 4/A |
+-----+-----+-----+-----+-----+-----+-----+-----+

- Register 04

7 6 5 4 3 2 1 0
+-----+-----+-----+-----+-----+-----+-----+-----+
|right amp. Voice 5/B | left amp. Voice 5/B |
+-----+-----+-----+-----+-----+-----+-----+-----+

- Register 05

7 6 5 4 3 2 1 0
+-----+-----+-----+-----+-----+-----+-----+-----+
|right amp. Voice 6/C | left amp. Voice 6/C |
+-----+-----+-----+-----+-----+-----+-----+-----+


Registers 08 through 0D

- These registers are used to set the tone frequency. The
frequency is combined with the octave value for the voice
to determine the frequency of the sound generated.

- Register 08

7 6 5 4 3 2 1 0
+-----+-----+-----+-----+-----+-----+-----+-----+
| tone frequency Voice 1/7 |
+-----+-----+-----+-----+-----+-----+-----+-----+

- Register 09

7 6 5 4 3 2 1 0
+-----+-----+-----+-----+-----+-----+-----+-----+
| tone frequency Voice 2/8 |
+-----+-----+-----+-----+-----+-----+-----+-----+

- Register 0A

7 6 5 4 3 2 1 0
+-----+-----+-----+-----+-----+-----+-----+-----+
| tone frequency Voice 3/9 |
+-----+-----+-----+-----+-----+-----+-----+-----+

- Register 0B

7 6 5 4 3 2 1 0
+-----+-----+-----+-----+-----+-----+-----+-----+
| tone frequency Voice 4/A |
+-----+-----+-----+-----+-----+-----+-----+-----+

- Register 0C

7 6 5 4 3 2 1 0
+-----+-----+-----+-----+-----+-----+-----+-----+
| tone frequency Voice 5/B |
+-----+-----+-----+-----+-----+-----+-----+-----+

- Register 0D

7 6 5 4 3 2 1 0
+-----+-----+-----+-----+-----+-----+-----+-----+
| tone frequency Voice 6/C |
+-----+-----+-----+-----+-----+-----+-----+-----+


Registers 10 through 12

- These registers are used to set the octave value. The 3
bits of octave control are defined as:

000 minimum octave (28 Hz to 55 Hz)
001 (55 Hz to 109 Hz)
010 (109 Hz to 218 Hz)
011 (218 Hz to 437 Hz)
100 (437 Hz to 875 Hz)
101 (875 Hz to 1.75 kHz)
110 (1.75 kHz to 3.50 kHz)
111 maximum octave (3.50 kHz to 6.99 kHz)

To produce a note, set the octave to a value of 0 through
7, then set the tone frequency for the desired note within
the octave.

Note Tone frequency value
A 03
A# 1F
B 3A
C 53
C# 6B
D 82
D# 97
E AC
F BF
F# D1
G E2
G# F2


- Register 10

7 6 5 4 3 2 1 0
+-----+-----+-----+-----+-----+-----+-----+-----+
| | Octave 2/8 | | Octave 1/7 |
+-----+-----+-----+-----+-----+-----+-----+-----+

- Register 11

7 6 5 4 3 2 1 0
+-----+-----+-----+-----+-----+-----+-----+-----+
| | Octave 4/A | | Octave 3/9 |
+-----+-----+-----+-----+-----+-----+-----+-----+

- Register 12

7 6 5 4 3 2 1 0
+-----+-----+-----+-----+-----+-----+-----+-----+
| | Octave 6/C | | Octave 5/B |
+-----+-----+-----+-----+-----+-----+-----+-----+


Register 14

- This register contains the frequency enable bits for all
voices. Setting the enable bit for the voice allows sound
generation for the programmed frequency. Turning off the
bit turns the frequency off.

7 6 5 4 3 2 1 0
+-----+-----+-----+-----+-----+-----+-----+-----+
| | | 6/C | 5/B | 4/A | 3/9 | 2/8 | 1/7 |
+-----+-----+-----+-----+-----+-----+-----+-----+


Register 15

- This register contains the noise enable bits for all voices.
Setting the enable bit for the voice allows noise generation,
turning off the bit turns noise generation off.

7 6 5 4 3 2 1 0
+-----+-----+-----+-----+-----+-----+-----+-----+
| | | 6/C | 5/B | 4/A | 3/9 | 2/8 | 1/7 |
+-----+-----+-----+-----+-----+-----+-----+-----+


Register 16

- This register is used to set the noise generation frequency.
There are four noise generators. Each generator is dedicated
to three voices:

Noise generator 1, voice 1 through voice 3
Noise generator 2, voice 4 through voice 6
Noise generator 3, voice 7 through voice 9
Noise generator 4, voice A through voice C

The 2 bits of noise generator control are defined as:

00 (clock frequency)
01 (28.0 Hz)
10 (14.0 Hz)
11 (6.8 Hz)

7 6 5 4 3 2 1 0
+-----+-----+-----+-----+-----+-----+-----+-----+
| | | gen. 2/4 | | | gen. 1/3 |
+-----+-----+-----+-----+-----+-----+-----+-----+

Register 1C

- This register contains a sound enable bit for all voices and
a requency reset signal bit.

The sound enable bit (SE) is defined as

0 (all channels disabled)
1 (all channels enabled)

The reset bit (RST) is used to send a Reset signal to all
frequency generators.

0 (all generators disabled)
1 (all generators reset and synchronized)



Detecting CMS Chips

Hmmmm, Anybody know of a good way to detect CMS Chips?



Making a Sound

The CMS chips are very easy to program. The following code written in
Turbo C provides a good start on mastering the CMS chips. The global
variable SbIOaddr should be set to the base I/O address of the Sound
Blaster.

extern unsigned SbIOaddr;

/*****************************************************************/
/* Function to set a register to a specified value using a */
/* given register address port. */
/*****************************************************************/

void CmsSetReg(unsigned regAddr, unsigned reg, unsigned val)
{
outportb(regAddr, reg); /* Select the register */
regAddr--; /* Get data to register port */
outportb(regAddr, val); /* Set the value of the register */
}


/*****************************************************************/
/* Function to initialize the Music chip by setting all internal */
/* registers to zero. */
/*****************************************************************/

void CmsInit() {
unsigned reg;
unsigned port;

port = SbIOaddr + 1; /* Voice 1-6 registers */
for (reg=0; reg < 0x20; reg++) /* Loop through all registers */
CmsSetReg(port,reg,0x0); /* Zero the register */
CmsSetReg(port,0x1C,0x2); /* Set the Reset bit (RST) */

port = SbIOaddr + 3; /* Voice 7-C registers */
for (reg=0; reg < 0x20; reg++) /* Loop through all registers */
CmsSetReg(port,reg,0x0); /* Zero the register */
CmsSetReg(port,0x1C,0x2); /* Set the Reset bit (RST) */
}


/*****************************************************************/
/* Function to set the left and right channel amplitudes of a */
/* voice to specified values. */
/*****************************************************************/

void CmsSetAmp(int voice, unsigned rAmp, unsigned lAmp) {
unsigned regAddr;

if (voice < 7) /* Select the correct register */
regAddr = SbIOaddr + 1; /* address for the voice */
else
regAddr = SbIOaddr + 3;

/* Set the voice right and left amplitude */
CmsSetReg(regAddr, voice-1, (rAmp << 4) + lAmp);
}


/*****************************************************************/
/* Function to set the tone frequency for a specified voice */
/*****************************************************************/

void CmsSetFreq(int voice, unsigned freq) {
unsigned regAddr;

if (voice < 7) /* Select the correct register */
regAddr = SbIOaddr + 1; /* address for the voice */
else
regAddr = SbIOaddr + 3;

/* Set the voice tone frequency */
CmsSetReg(regAddr, 0x8 + voice-1, freq);
}


/*****************************************************************/
/* Function to set the octave for a specified voice */
/*****************************************************************/

void CmsSetOctave(int voice, unsigned octave) {
unsigned regAddr;
unsigned reg;
unsigned val;

if (voice < 7) /* Select the correct register */
regAddr = SbIOaddr + 1; /* address for the voice */
else
regAddr = SbIOaddr + 3;

/* Compute the register and value to send to CmsSetReg */
val = (voice & 0x1 ? octave : octave << 4);
switch (voice) {
case 1:
case 2:
case 7:
case 8:
reg = 0x10;
break;

case 3:
case 4:
case 9:
case 10:
reg = 0x11;
break;

case 5:
case 6:
case 11:
case 12:
reg = 0x12;
break;
}

CmsSetReg(regAddr, reg, val);
}


/*****************************************************************/
/* Function to enable sound frequency for a voice. */
/*****************************************************************/

void CmsEnableVoice(int voice) {
unsigned regAddr;
unsigned val;

if (voice < 7) /* Select the correct register */
regAddr = SbIOaddr + 1; /* address for the voice */
else
regAddr = SbIOaddr + 3;

val = 0x40; /* Compute the value to send */
if (voice < 7) /* to CmsSetReg */
val >>= 7 - voice;
else
val >>= 13 - voice;

CmsSetReg(regAddr, 0x14, val); /* Set the voice enable bit */
CmsSetReg(regAddr, 0x1C, 0x1); /* Set the sound enable bit */
}


Acknowledgements

Thanks are due to the following people:

Jeffrey S. Lee ([email protected]cp) for writing the original document
on Programming the AdLib/Sound Blaster. This is a must read for anyone
trying to hack their way through the AdLib programming interface.

Mike Kretzer ([email protected]) for providing information on the
availability of CMS chips on the Sound Blaster.



 December 10, 2017  Add comments

Leave a Reply