;********************************************************************* ;* Title: code-onebit-v00.asm ;********************************************************************* ;* Author: R. Allen Murphey ;* ;* License: Copyright (c) 2020-2022 R. Allen Murphey. All Rights Reserved. ;* ;* Description: One-Bit sound driver ;* ;* Documentation: ;* EXAMPLE BUILD INSTRUCTIONS ;* >>> vi onebit.s ;* >>> lwasm -9 -p cd --list=onebit.txt -o onebit.bin onebit.s ;* >>> perl -e 'print chr(255) x (35*18*256)' > ONEBIT.DSK ;* >>> decb dskini ONEBIT.DSK ;* >>> decb kill ONEBIT.DSK,ONEBIT.BIN ;* >>> decb copy onebit.bin ONEBIT.DSK,ONEBIT.BIN -2 ;* >>> mame coco3h -ramsize 2M -window -resolution 1920x1080 -skip_gameinfo -flop1 ONEBIT.DSK & ;* ;* Include Files: PIA1 ;* ;* Assembler: lwasm 1.4.2 ;* ;* Revision History: ;* Rev # Date Who Comments ;* ----- ----------- ------ --------------------------------------- ;* 00 2020-2021 RAM Created initial file ;********************************************************************* ; start somewhere arbitrary in RAM ; implies 32K+ CoCo1/2/3 -move lower for 4/16K ;org $4000 ; only needed for standalone testing ; first we're going to setup the coco pias for one-bit sound ONEBIT: ; step 1: disable SNDEN line silencing DAC ; note: you do this anyway for reading joysticks too lda PIA1BC ; PIA1 Port B Control anda #%11110111 ; clear bit 3=0 sixbit sound disable sta PIA1BC ; update Port B control ; step 2: configure PIA1 Port B Data register to Data Dir register lda PIA1BC ; PIA1 Port B Control (again) anda #%11111011 ; clear bit 2=0 FF22 as Data Dir register sta PIA1BC ; update Port B Control ; step 3: now configure PIA1 Port B so bit 2 is output not input ; i suspect tandy never bothered to update port after resets lda PIA1BD ; PIA1 Port B Data Dir register ora #%00000010 ; set bit 2=1 onebit sound output enable sta PIA1BD ; update Port B Data Dir register ; step 4: set PIA1 Port B register back to Data Port from Data Dir lda PIA1BC ; PIA1 Port B Control (again) ora #%00000100 ; set bit 2=1 configure FF22 as Data Port B sta PIA1BC ; update Port B Control ; okay the basic setup is done now let's make some noise with it ldx #999 ; start with 2000 as a tone period - this number is one half that stx TONE ; store it in a 16 bit spot ; a onebit sound is a repeating on off pattern ; and the tone is controlled by the period of time between on-to-off-to-on again ; so lets turn on the onebit for "a while" defined by one-half of the desired tone period BITON: ; turn on the one-bit sound output lda PIA1BD ; get the onebit output port address ora #%00000010 ; set bit 2=1 starting sound out sta PIA1BD ; update PIA1 Port B and start making noise ; once the noise starts we spend "some time" letting it make noise ; the time is defined as counter of some sort ; here a simple countdown loop hogs up the MPU ; real implementations should refer to Simon "Invisible Man" Jonassen's 1bitplayer ; to see how to do this super efficiently under irq control for blazing speed ; http://www.roust-it.dk/coco/1bitplayer.asm ldx TONE ; get the current value for tone LOOPON: ; start a countdown loop leax -1,X ; countdown by 1 bne LOOPON ; if counter not zero loop back ; so now we've played the noise for a while let's create an equal silence ; this is why the counter was one-half the value of the tone period we wanted BITOFF: ; turn off the one-bit sound output lda PIA1BD ; get the onebit output port address anda #%11111101 ; clear bit 2=0 stopping sound out sta PIA1BD ; update PIA1 Port B to stop noise ; once the noise stops we spend "some time" enjoying the silence ; again we define the silent period using a countdown one half desired tone period ldd #1000 subd TONE tfr D,X ; get the current value for tone LOOPOFF: ; start a countdown loop leax -1,X ; countdown by 1 bne LOOPOFF ; if counter not zero loop back ; okay we've had a period with sound on then off in equal measure ; from here on out the sky and our imagination is the limit ; for this simple demonstration, we can update the tone value and loop ; this will create a rising or falling tone depending on how we update ; the value - making the tone period smaller makes for a rising sound ldx TONE ; get the current value for tone leax -1,X ; subtract one stx TONE ; update the current tone value bra BITON ; go back and start the on-off cycles again ; we'll use 2 bytes to hold a 16-bit tone period TONE: rmb 2 ; and we're done - execute starting at address of onebit ;end ONEBIT ; only needed for standalone testing ;********************************************************************* ;* End of code-onebit-v00.asm ;*********************************************************************