From: John Tsiombikas Date: Wed, 23 Jan 2019 01:00:11 +0000 (+0200) Subject: fixed DMA bug X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=dos_sbtest;a=commitdiff_plain;h=b4ee0075a2a231ef06e333b77510187aeb22f8fa fixed DMA bug --- diff --git a/src/au_sb.c b/src/au_sb.c index c49b2cf..d733f20 100644 --- a/src/au_sb.c +++ b/src/au_sb.c @@ -89,9 +89,11 @@ static int xfer_mode; static int isplaying; static int cur_bits, cur_mode; +static int curblk; static void (INTERRUPT *prev_intr_handler)(); + int sb_detect(void) { int i; @@ -178,11 +180,11 @@ void sb_set_output_rate(int rate) void *sb_buffer(int *size) { - *size = 65536; - return buffer; + *size = 32768; + return (char*)buffer + curblk * 32768; } -void sb_start(int rate, int nchan) +void sb_start(int rate, int bits, int nchan) { uint16_t seg, pmsel; uint32_t addr; @@ -205,21 +207,23 @@ void sb_start(int rate, int nchan) addr = (uint32_t)buffer; } - if(!(size = audio_callback(buffer, 65536))) { + if(!(size = audio_callback(buffer, 32768))) { return; } + curblk = 1; _disable(); if(!prev_intr_handler) { prev_intr_handler = _dos_getvect(IRQ_TO_INTR(irq)); } + printf("setting interrupt vector: %d\n", IRQ_TO_INTR(irq)); _dos_setvect(IRQ_TO_INTR(irq), intr_handler); _enable(); unmask_irq(irq); - cur_bits = 8; - cur_mode = 0; + cur_bits = bits; + cur_mode = 0; /* TODO */ if(nchan > 1) { cur_mode |= DSP4_MODE_STEREO; } @@ -236,6 +240,8 @@ static void start_dsp4(int bits, unsigned int mode, int num_samples) unsigned char cmd = bits == 8 ? DSP4_START_DMA8 : DSP4_START_DMA16; assert(bits == 8 || bits == 16); + /*cmd |= DSP4_AUTO | DSP4_FIFO;*/ + /* program the DSP to start the DMA transfer */ write_dsp(cmd); write_dsp(mode); @@ -290,12 +296,15 @@ void sb_volume(int vol) static void INTERRUPT intr_handler() { int size; + void *bptr = (unsigned char*)buffer + curblk * 32768; + + curblk = (curblk + 1) & 1; /* ask for more data */ - if(!(size = audio_callback(buffer, 65536))) { + if(!(size = audio_callback(bptr, 32768))) { sb_stop(); } else { - dma_out(dma_chan, (uint32_t)buffer, size, DMA_SINGLE); + dma_out(dma_chan, (uint32_t)bptr, size, DMA_SINGLE); start_dsp4(cur_bits, cur_mode, size); } diff --git a/src/au_sb.h b/src/au_sb.h index 0981ba6..4766b44 100644 --- a/src/au_sb.h +++ b/src/au_sb.h @@ -15,7 +15,7 @@ void *sb_buffer(int *size); void sb_set_output_rate(int rate); -void sb_start(int rate, int nchan); +void sb_start(int rate, int bits, int nchan); void sb_pause(void); void sb_continue(void); void sb_stop(void); diff --git a/src/audio.c b/src/audio.c index adb8e3e..88b8400 100644 --- a/src/audio.c +++ b/src/audio.c @@ -4,7 +4,7 @@ struct audrv { void *(*get_buffer)(int *size); - void (*start)(int rate, int nchan); + void (*start)(int rate, int bits, int nchan); void (*pause)(void); void (*cont)(void); void (*stop)(void); @@ -47,9 +47,9 @@ int audio_callback(void *buf, int sz) return cbfunc(buf, sz, cbcls); } -void audio_play(int rate, int nchan) +void audio_play(int rate, int bits, int nchan) { - drv.start(rate, nchan); + drv.start(rate, bits, nchan); } void audio_pause(void) diff --git a/src/audio.h b/src/audio.h index 1fde706..c522134 100644 --- a/src/audio.h +++ b/src/audio.h @@ -1,20 +1,3 @@ -/* -pcboot - bootable PC demo/game kernel -Copyright (C) 2018 John Tsiombikas - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY, without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ #ifndef AUDIO_H_ #define AUDIO_H_ @@ -25,7 +8,7 @@ void audio_init(void); void audio_set_callback(audio_callback_func func, void *cls); int audio_callback(void *buf, int sz); -void audio_play(int rate, int nchan); +void audio_play(int rate, int bits, int nchan); void audio_pause(void); void audio_resume(void); void audio_stop(void); diff --git a/src/dma.c b/src/dma.c index 92f0a1b..17baead 100644 --- a/src/dma.c +++ b/src/dma.c @@ -100,8 +100,8 @@ static void dma_io(int chan, uint32_t phyaddr, int size, unsigned int flags, uns mask(chan); outp(DMA_CLR_FLIPFLOP(chan), 0); - /* single / block / cascade */ - mode = ((flags & 3) << 6) | MODE_CHAN(chan); + /* first 2 bits of flags correspond to the mode bits 6,7 */ + mode = ((flags & 3) << 6) | dir | MODE_CHAN(chan); if(flags & DMA_DECR) mode |= MODE_DECR; if(flags & DMA_AUTO) mode |= MODE_AUTO; outp(DMA_MODE(chan), mode); diff --git a/src/main.c b/src/main.c index 264c04e..1d148d0 100644 --- a/src/main.c +++ b/src/main.c @@ -43,7 +43,7 @@ int main(int argc, char **argv) if(audio_isplaying()) { audio_stop(); } else { - audio_play(22050, 1); + audio_play(22050, 8, 1); } break; default: