Sound Blaster 16: Difference between revisions
[unchecked revision] | [unchecked revision] |
→Code: add assembly driver code |
|||
Line 77: | Line 77: | ||
==Code== |
==Code== |
||
<source lang="C"> |
|||
//Digital Sound Processor ports |
|||
#define DSP_RESET 0x226 |
|||
#define DSP_READ 0x22A |
|||
#define DSP_WRITE 0x22C |
|||
#define DSP_BUFFER 0x22A |
|||
#define DSP_STATUS 0x22E |
|||
#define DSP_INTERRUPT 0x22F |
|||
//Digital Sound Processor commands |
|||
#define DSP_CMD_OUTPUT_RATE 0x41 |
|||
#define DSP_CMD_TRANSFER_MODE 0xB6 |
|||
#define DSP_CMD_STOP 0xD5 |
|||
#define DSP_CMD_VERSION 0xE1 |
|||
//DMA ports |
|||
#define DMA_ADDRES 0xC4 |
|||
#define DMA_COUNT 0xC6 |
|||
#define DMA_PAGE 0x8B |
|||
#define DMA_SINGLE_MASK 0xD4 |
|||
#define DMA_TRANSFER_MODE 0xD6 |
|||
#define DMA_CLEAR_POINTER 0xD8 |
|||
void reset_DSP(void) { |
|||
outb(DSP_RESET, 1); |
|||
sleep(3); //wait 3 microseconds |
|||
outb(DSP_RESET, 0); |
|||
if(read_DSP()==0xAA) { |
|||
sound_blaster=TRUE; |
|||
} |
|||
} |
|||
void sb16_init(void) { |
|||
reset_DSP(); |
|||
//if DSP doesnt exist |
|||
if(sound_blaster==FALSE) { |
|||
return; |
|||
} |
|||
//get DSP version |
|||
write_DSP(DSP_CMD_VERSION); |
|||
sb16_version_major=read_DSP(); |
|||
sb16_version_minor=read_DSP(); |
|||
} |
|||
</source> |
|||
<source lang="asm"> |
<source lang="asm"> |
||
%macro OUTB 2 |
%macro OUTB 2 |
||
Line 153: | Line 104: | ||
OUTB 0x0C, 1 ;flip flop |
OUTB 0x0C, 1 ;flip flop |
||
OUTB 0x0B, 0x49 ;transfer mode |
OUTB 0x0B, 0x49 ;transfer mode |
||
OUTB 0x83, |
OUTB 0x83, 0x01 ;PAGE TRANSFER (EXAMPLE POSITION IN MEMORY 0x[01]0F04) - SET THIS VALUE FOR YOU |
||
OUTB 0x02, |
OUTB 0x02, 0x0F ;POSITION LOW BIT (EXAMPLE POSITION IN MEMORY 0x01[0F]04) - SET THIS VALUE FOR YOU |
||
OUTB 0x02, |
OUTB 0x02, 0x04 ;POSITON HIGH BIT (EXAMPLE POSITION IN MEMORY 0x010F[04]) - SET THIS VALUE FOR YOU |
||
OUTB 0x03, 0xFF ;COUNT LOW BIT (EXAMPLE 0x0FFF) - SET THIS VALUE FOR YOU |
OUTB 0x03, 0xFF ;COUNT LOW BIT (EXAMPLE 0x0FFF) - SET THIS VALUE FOR YOU |
||
OUTB 0x03, 0x0F ;COUNT HIGH BIT (EXAMPLE 0x0FFF) - SET THIS VALUE FOR YOU |
OUTB 0x03, 0x0F ;COUNT HIGH BIT (EXAMPLE 0x0FFF) - SET THIS VALUE FOR YOU |
Revision as of 16:30, 16 May 2020
The Sound Blaster series is a family of sound cards made by Creative. For many years they were the standard audio cards on IBM PC's.
Introduction
The Sound Blaster 16 is the successor to the Sound Blaster Pro audio card found in many older computers. It was first brought out in 1992. The main improvement over the Pro is its 16-bit digital audio sampling (hence the name). Most SB16 cards are PCI compatible, as Creative made this improvement shortly after releasing the card, upgrading from ISA.
Digital Signal Processor
The DSP built into the Sound Blaster 16 supports playing and recording audio in 8-bit and 16-bit PCM encoded samples, along with playing several other formats (ADPCM, etc.). The base I/O register address can be found using the PCI bus for PCI models, or by detecting the presence of an older ISA Sound Blaster by issuing a Get Version command to one of several common I/O port addresses (0x220, 0x240, etc.) and waiting for a response.
Port | Description |
---|---|
0x226 | DSP Reset |
0x22A | DSP Read |
0x22C | DSP Write (Read this port for Write Status) |
0x22E | DSP Read Status (Read this port to acknowledge 8-bit interrupt) |
0x22F | DSP 16-bit Interrupt Acknowledge (Read this port to acknowledge 16-bit interrupt) (DSP Version 4.0+ Only) |
Command | Description |
---|---|
0x41 | Set Output Sample Rate |
0xB6 | Auto transfer mode |
0xD5 | Stop playing |
0xE1 | Get DSP version |
When the samples have been played, an interrupt will be fired, and the OS/Driver will have the chance to refill the buffer, or to issue a Stop command.
Because you only have a single DMA buffer to transfer data, it is recommended that you issue the Play PCM command with a sample count of half of the data buffer. This will fire an interrupt when the buffer is half played, allowing you to refill the segment that was just played, while the DSP continues playing the other half, and so on.
Reading and writing
Until you write to the DSP write port, check the DSP write port for 0x00. Until reading the DSP read port, check the DSP status port for 0x80.
Detecting DSP
Detecting DSP is really easy. You must send to DSP reset port 1, wait 3 microseconds, send to DSP reset 0 and read DSP read port. If in it is 0xAA, DSP exist. Some SB-compatible cards returned 0xAA on first check but on second check they reported their specific version.
Playing sound
- Detect DSP
- Load sound data to memory
- Program ISA DMA
- Set output sample rate(command/High byte/Low byte)
- Write DMA transfer type to DSP(command)
- Write data lenght to DSP(Low byte/High byte)
Programming DMA
Port | Description |
---|---|
0xC4 | Address |
0xC6 | Count |
0x8B | Page |
0xD4 | Single mask |
0xD6 | Transfer mode |
0xD8 | Clear pointer |
Code
%macro OUTB 2
mov dx, %1
mov al, %2
out dx, al
%endmacro
%macro INB 2
mov dx, %1
in al, dx
%endmacro
;SOUND BLASTER 16 driver in real mode
;reset sound blaster
OUTB 0x226, 1 ;reset port
mov ah, 86h
mov cx, 0x0000
mov dx, 0xFFFF
int 15h ;wait
OUTB 0x226, 0 ;reset port
;DMA channel 1
OUTB 0x0A, 5 ;disable channel 1 (number of channel + 0x04)
OUTB 0x0C, 1 ;flip flop
OUTB 0x0B, 0x49 ;transfer mode
OUTB 0x83, 0x01 ;PAGE TRANSFER (EXAMPLE POSITION IN MEMORY 0x[01]0F04) - SET THIS VALUE FOR YOU
OUTB 0x02, 0x0F ;POSITION LOW BIT (EXAMPLE POSITION IN MEMORY 0x01[0F]04) - SET THIS VALUE FOR YOU
OUTB 0x02, 0x04 ;POSITON HIGH BIT (EXAMPLE POSITION IN MEMORY 0x010F[04]) - SET THIS VALUE FOR YOU
OUTB 0x03, 0xFF ;COUNT LOW BIT (EXAMPLE 0x0FFF) - SET THIS VALUE FOR YOU
OUTB 0x03, 0x0F ;COUNT HIGH BIT (EXAMPLE 0x0FFF) - SET THIS VALUE FOR YOU
OUTB 0x0A, 1 ;enable channel 1
;program sound blaster 16
OUTB 0x22C, 0x40 ;set time constant
OUTB 0x22C, 165 ;10989 Hz
OUTB 0x22C, 0x14 ;mode DAC 8 bit
OUTB 0x22C, 0xFE ;COUNT LOW BIT (EXAMPLE 0x0FFF) - SET THIS VALUE FOR YOU
OUTB 0x22C, 0x0F ;COUNT HIGH BIT (EXAMPLE 0x0FFF) - SET THIS VALUE FOR YOU
;now transfer start - dont forget to handle irq