#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;
}