Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Programming a Sound Blaster Pro compatible card for single cycle record via DMA

12 views
Skip to first unread message

ktcm

unread,
Jan 6, 2006, 10:00:36 PM1/6/06
to
I've managed to get the interrupt sub-routine to be activated. However,
all the elements in the buffer are 128 which indicates that no signal
is being read despite my inputting of a signal. Below is my code, does
anyone know what could be the problem? I would also appreciate if
anyone has any documentation or information on programming the SB pro
sound card in C. I've also not managed to do any recording directly
from the sound card without the DMA, so any help in that area would
also be useful. Thanks.

#include <pc.h>
#include <dpmi.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <go32.h>
#include <sys\nearptr.h>
#include <crt0.h>
#include <dos.h>
#include <time.h>
#include "rd-wr.c"
#include "constant4.h"
#define IRQ5 0x0D
#define SB_Add 0x220
#define buffer_size 0xFF
//#define MK_FP(seg,off) ((void far*)((unsigned long)(seg)<<16 |
(unsigned)(off))

_go32_dpmi_seginfo SegInfo;
static _go32_dpmi_seginfo old_irq5;
static _go32_dpmi_seginfo new_irq5;
int page_register, LSB_memory, MSB_memory, memory, port;
unsigned long phys;
unsigned char *buffer, *temp;

void SBINT ();
void * MK_FP (unsigned long seg, unsigned long ofs);
int DSP_clear();

int main (){
int i = 0, ch, num, success = 0, GPIO, j, start_time, select;
printf ("Version 1.1\n");
printf ("Enter GPIO to set:");
scanf ("%d",&GPIO);
configure_GPIOs ();
set_GPIO (GPIO);

new_irq5.pm_offset = (int)SBINT; // link the address of ISR to
the irq3 variable
new_irq5.pm_selector = _go32_my_cs();
_go32_dpmi_allocate_iret_wrapper(&new_irq5); // handles the
overhead of servicing the interrupt
_go32_dpmi_get_protected_mode_interrupt_vector(IRQ5,&old_irq5); //
store the old protected mode interrupt vector
_go32_dpmi_set_protected_mode_interrupt_vector(IRQ5,&new_irq5);
//Set the new interrupt vector
outportb (0x21,(inportb(0x21) & 0xDF)); //Enable programmable
interrupt (0xDF for IRQ5 - Sets pin 5 to low)
printf ("Interrupt Enabled\n");
outportb (SB_Add + 0xC, 0xD3); //Turn Off Speakers


/*To set up the DMA channel*/
SegInfo.size = ((buffer_size*2) + 15) / 16;
_go32_dpmi_allocate_dos_memory (&SegInfo);
phys = SegInfo.rm_segment << 4;
printf ("Physical address:%p\n",phys);
page_register = (long)(phys >>16);
printf ("Page register:%p\n",page_register);
buffer = (unsigned char *)MK_FP(phys>>4,0);
printf ("Buffer:%p\n",buffer);
memset (buffer, 0, buffer_size);
LSB_memory = (phys << 24) >>24;
printf ("LSB memory:%p\n", LSB_memory);
MSB_memory = (phys << 16) >>24;
printf ("MSB_memory:%p\n\n",MSB_memory);

outportb (0x0A, 0x05); //Disable Channel 1; 0Ah is the write mask
register
printf ("Write mask register:%p\n", inportb (0x0A));
outportb (0x0B, 0x45); //Select single cycle record for channel 1
printf ("Mode register:%p\n", inportb (0x0B));
outportb (0x0C, 0x00); //Clear byte pointer flipflop
printf ("Byte pointer register:\n", inportb (0x0C));
outportb (0x02, LSB_memory); //Set LSB of memory in Ch 1 address
port
outportb (0x02, MSB_memory); //Set MSB of memory
printf ("Address register for DMA:%p\n",inportb (0x02));
printf ("Address register for dma:%p\n", inportb (0x02));
outportb (0x83, page_register); //Set page in ch 1 page register
printf ("Page register:%p\n", inportb (0x83));
outportb (0x03, buffer_size); //Set LSB of transfer length on Ch 1
count port
outportb (0x03, 0x00); //Set MSB of transfer length on Ch 1 count
port
printf ("Buffer size:%p\n", inportb (0x03));
printf ("buffer size:%p\n", inportb (0x03));
outportb (0x0A, 0x01); //Clear the mask bit for channel 1; Enable
channel 1
printf ("Mask register:%p\n", inportb (0x0A));

printf ("DMA Programmed \n");

start_time = clock ();

while (clock() - start_time < 536);

for (i=0; i < buffer_size; i++){
printf ("%d\t", *(buffer + i));
}

/* To reset the sound card*/
outportb (SB_Add + 6, 1); //output 1 to the Reset Address

for(i=0;i<6;i++) //Time delay for 3
microseconds
inportb (SB_Add + 0xE);

outportb (SB_Add + 6, 0); // output 0 to the Reset Address
for (i=0; i < 65536; i ++){
num = inportb (SB_Add + 0xE); //Check read status register to see
if there is data
num &= 0x80;

if (num != 0){
success = 0;
for (j=0; j < 30; j++){
ch = inportb(SB_Add+ 0xA);
ch -= 0xAA;
if (ch == 0){
success = 1;
break;
}
}
}
}
if (success == 1)
printf ("Sound Card Reset\n");
else {
printf ("Reset Failed\n");
goto end;
}

/*To configure Mixer*/
printf ("Input value for select register:");
scanf ("%p", &select);
outportb (SB_Add + 0x4, 0x00); // Select reset data register
inportb (SB_Add + 0x5); //Wait for 0.5 microseconds
outportb (SB_Add + 0x5, 0x00); // Reset the mixer
outportb (SB_Add + 0x4, 0xC); //Select 'select input choice'
register
outportb (SB_Add + 0x5, ((inportb (SB_Add + 0x5)) | select)); //
Select Line In input and switch filter off
printf ("Select Register:%p\n", inportb (SB_Add + 0x5)); //Print
'select input' register value
outportb (SB_Add + 0x04, 0x2E); //Select 'Line Volume'
register
outportb (SB_Add + 0x05, ((inportb (SB_Add + 0x5))| 0x88)); //Set
Line volume
printf ("Line Volume: %p\n", inportb (SB_Add + 0x05)); //Print Line
Volume
outportb (SB_Add + 0x4, 0x22);
outportb (SB_Add + 0x5, ((inportb (SB_Add + 0x5)) | 0x88)); //Set
Master Volume
printf ("Master Volume:%p\n", inportb (SB_Add + 0x5)); //Print Master
volume
outportb (SB_Add + 0x04, 0x0A); //Select Mic
volume register
outportb (SB_Add + 0x05, ((inportb (SB_Add + 0x5)) | 0x06)); //Set
Mic volume
printf ("Mic Volume:%p\n", inportb (SB_Add + 0x5)); //print mic
volume
outportb (SB_Add + 0x04, 0x0E);
outportb (SB_Add + 0x05, ((inportb (SB_Add + 0x05)) & 0xFD));
//Select mono output
printf ("Register 0E: %p\n", inportb (SB_Add + 0x05));
start_time = clock ();

while (clock() - start_time < 536);

/*To configure DSP*/
while (!DSP_clear());
outportb (SB_Add + 0xC, 0x40); //To set time constant
while (!DSP_clear ());
outportb (SB_Add + 0xC, 0xE9); //MSB of time constant
while (!DSP_clear ());
// outportb (SB_Add + 0xC, 0xCE); //LSB of time constant
outportb(SB_Add + 0xC, 0x48); //To program high
speed input
while (!DSP_clear ());
outportb (SB_Add + 0xC, buffer_size); //Low byte of
transfer count
while (!DSP_clear ());
outportb (SB_Add + 0xC, 0x00); //High byte of
transfer count


while (!DSP_clear ());
outportb (SB_Add + 0xC, 0x99); //enable

printf ("Sound Card initialized\n");

while (!kbhit());
clear_GPIO (GPIO);

_go32_dpmi_set_protected_mode_interrupt_vector(IRQ5,&old_irq5);
//assign old interrupt vector to com 1
_go32_dpmi_free_iret_wrapper(&new_irq5); // free new interrupt
vector?
printf ("Interrupt Disabled");
end:;
}

void SBINT (){
int i=0;

temp = (unsigned char *) malloc (buffer_size * sizeof (char));
for (i = 0; i < buffer_size; i++){
// *(temp+i) = *(buffer + i);
printf ("%d\t", *(buffer+i));
}


/*To set up the DMA channel*/
outportb (0x0A, 0x05); //Disable Channel 1; 0Ah is the write mask
register
outportb (0x0B, 0x45); //Select single cycle record for channel 1
outportb (0x0C, 0x00); //Clear byte pointer flipflop
outportb (0x02, LSB_memory); //Set LSB of memory in Ch 1 address
port
outportb (0x02, MSB_memory); //Set MSB of memory
outportb (0x83, page_register); //Set page in ch 1 page register
outportb (0x03, buffer_size); //Set LSB of transfer length on Ch 1
count port
outportb (0x03, 0x00); //Set MSB of transfer length on Ch 1 count
port
outportb (0x0A, 0x01); //Clear the mask bit for channel 1; Enable
channel 1
printf ("DMA Programmed \n");
/*To configure DSP*/
outportb(SB_Add + 0xC, 0x48); //To program 8 bit PCM
input
outportb (SB_Add + 0xC, buffer_size); //Low byte of
transfer count
outportb (SB_Add + 0xC, 0x00); //High byte of
transfer count
outportb (SB_Add + 0xC, 0x99); //enable
printf ("Sound Card initialized\n");
inportb (SB_Add + 0xE); //To acknowledge the DSP interrupt
outportb (0x20,0x20); //return from interrupt
}

void * MK_FP (unsigned long seg, unsigned long ofs){
if (!(_crt0_startup_flags & _CRT0_FLAG_NEARPTR))
if (!__djgpp_nearptr_enable ())
return (void *) 0;
return (void *)(seg*16 + ofs + __djgpp_conventional_base);
}

int DSP_clear (){
if ((inportb (SB_Add + 0xC)&0x80) == 0)
return 1;
else
return 0;
}

0 new messages