From ba2c288e8dd35306edee13550d215c4b2cead9ad Mon Sep 17 00:00:00 2001 From: Steven Hugg Date: Wed, 15 Jul 2020 19:01:28 -0500 Subject: [PATCH] apple2: delta modulation demo --- presets/apple2/deltamod.dasm | 218 +++++++++++++++++++++++++ presets/apple2/springchicken.dat12.bin | Bin 0 -> 42373 bytes src/common/audio.ts | 8 +- src/machine/apple2.ts | 11 +- src/platform/apple2.ts | 1 + 5 files changed, 228 insertions(+), 10 deletions(-) create mode 100644 presets/apple2/deltamod.dasm create mode 100644 presets/apple2/springchicken.dat12.bin diff --git a/presets/apple2/deltamod.dasm b/presets/apple2/deltamod.dasm new file mode 100644 index 00000000..c6c06997 --- /dev/null +++ b/presets/apple2/deltamod.dasm @@ -0,0 +1,218 @@ + + processor 6502 + +;;; +;;; Apple ][ Delta Modulation Sample Playback +;;; +;;; This is the same technique used in the NES +;;; for DMC samples, but adapted for the Apple ][. +;;; Basically: Every 1 bit increases the signal +;;; by 1 step, every 0 bit decreases by 1 step. +;;; The signal is clipped on the top and bottom. +;;; +;;; The NES has a 6-bit DAC, but we only have a +;;; PWM-encoded signal. We have 13 different +;;; routines to generate pulses ranging from 4 to +;;; 14 microseconds long, with a 29-30 microsecond +;;; interval (when we reach 50% duty cycle we just +;;; invert the signal) +;;; +;;; Every 8 bits we have to fetch a new byte +;;; and increment the pointer. To avoid a high- +;;; frequency tone, we generate another pulse +;;; (the same width as the last) in this macro. +;;; +;;; also see http://michaeljmahon.com/RTSynth.html +;;; and https://github.com/oliverschmidt/Play-BTc +;;; + +; uninitialized zero-page variables + seg.u ZEROPAGE + org $0 +PWMBUF .ds 2 +PWMLEN .ds 1 +TRASH .ds 1 + +; speaker toggle +SPKR equ $c030 + +; max pulse width = PULWID*2+4 cycles +PULWID = 6 + +; sleep {1} cycles +; must be multiple of 2 + MAC SLEEP2 +.CYCLES SET {1} + IF .CYCLES == 1 + ECHO "MACRO ERROR: 'SLEEP': Duration must be > 1" + ERR + ENDIF + IF .CYCLES >= 12 + jsr HandyRTS +.CYCLES SET .CYCLES - 12 + ENDIF + REPEAT .CYCLES / 2 + nop + REPEND + ENDM + ENDM + +; pulse macro +; flip speaker, wait N*2 cycles +; flip again, wait (MAX-N)*2 cycles +; total = 8 + PULWID*2 cycles + MAC PULSE + sta SPKR + SLEEP2 {1}*2 + sta SPKR + SLEEP2 (PULWID-{1})*2 + ENDM + +; shift next bit into carry flag +; load next byte and increment +; pointer if needed +; {1} : index of previous routine +; {2} : index of current routine +; we also interleave a speaker pulse in this routine +; using macros (these are the IF/ENDIF blocks) + MAC NEXTPULSE + lsr ; next bit -> carry flag + dex ; bit count == 0? + bne .noinc ; skip inc/reload cycle + ; total pulse = 15 + PULWID*2 cycles + IF {2} > 0 + sta SPKR + ELSE + SLEEP2 8 ; no SPKR toggle, take up 8 cycles + ENDIF + IF {2} == 1 + sta SPKR + ENDIF + +; increment pointer lo byte + iny ; 2-1 = 1 + + IF {2} == 2 + sta SPKR + ENDIF + + bne .noinchi ; 4 +; increment pointer hi byte + inc PWMBUF+1 + dec PWMLEN + bne .noinchi + rts ; end of sound data +.noinchi + + IF {2} == 3 + sta SPKR + ENDIF + +; reset X counter + ldx #8 ; 6 + + IF {2} == 4 || {2} == 5 + sta SPKR + ENDIF + +; fetch new byte + lda (PWMBUF),y ; 11 + + ; a few NOPs to match the normal pulse width + ; (inx, lsr, branch) + IF {2} == 6 + sta SPKR + nop + ENDIF + IF {2} >= 7 + nop + sta SPKR + ENDIF + ; make up cycles we missed + SLEEP2 PULWID*2-6 + +.noinc +; carry flag still valid from lsr + bcc LVLS{1} + ENDM + +;;; start of code + seg CODE + org $803 ; starting address + +Start + lda #>(SAMPLE_END-SAMPLES)+1 + sta PWMLEN + lda #SAMPLES + sta PWMBUF+1 + jsr Play + jmp Start +; handy RTS for wasting 6+6 cycles +HandyRTS + rts + +; each pulse takes PULWID*2+18(-1) cycles +; every 8 bits, the last pulse is repeated +; 1022727 / 29.5 / (9/8) = 30817 Hz +; Y = PWMBUF lo address +; PWMBUF+0 = 0 +Play + ldy PWMBUF + lda #0 + sta PWMBUF + ldx #8 + lda (PWMBUF),y +; each label emits a pulse at a duty cycle +; from 0 (silent) to 7 +; if bit is 1, falls through to next highest level +; otherwise, jumps back to previous level +LVLS0 + SLEEP2 PULWID*2+8 ; sleep, don't click + NEXTPULSE 0,0 +LVLS1 + PULSE 0 + NEXTPULSE 0,1 +LVLS2 + PULSE 1 + NEXTPULSE 1,2 +LVLS3 + PULSE 2 + NEXTPULSE 2,3 +LVLS4 + PULSE 3 + NEXTPULSE 3,4 +LVLS5 + PULSE 4 + NEXTPULSE 4,5 +LVLS6 +LVLS6INV equ *+3 ; skip STA SPKR to invert signal + PULSE 5 + NEXTPULSE 5,6 + bcs LVLS7INV ; 1 = invert signal +LVLS7 +LVLS7INV equ *+3 ; skip STA SPKR to invert signal + PULSE 4 + NEXTPULSE 6INV,5 ; 0 = invert signal +LVLS8 + PULSE 3 + NEXTPULSE 7,4 +LVLS9 + PULSE 2 + NEXTPULSE 8,3 +LVLS10 + PULSE 1 + NEXTPULSE 9,2 +LVLS11 + PULSE 0 + NEXTPULSE 10,1 +LVLS12 + SLEEP2 PULWID*2+8 ; sleep, don't click + NEXTPULSE 11,0 + bcs LVLS12 ; if 1, stay at highest level + +; delta-encoded samples +SAMPLES + .incbin "springchicken.dat12.bin" ; "Spring Chicken" by BryanTeoh +SAMPLE_END diff --git a/presets/apple2/springchicken.dat12.bin b/presets/apple2/springchicken.dat12.bin new file mode 100644 index 0000000000000000000000000000000000000000..a5eec8dfd7f6aef46d0779b8573650cfe6468e9f GIT binary patch literal 42373 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 z 1) { + if (sfrac >= 1) { accum /= sfrac; - this.addSingleSample(accum * sinc); - sfrac -= Math.floor(sfrac); + while (sfrac >= 1) { + this.addSingleSample(accum * sinc); + sfrac -= 1; + } accum *= sfrac; } } diff --git a/src/machine/apple2.ts b/src/machine/apple2.ts index 14941313..d03fd61d 100644 --- a/src/machine/apple2.ts +++ b/src/machine/apple2.ts @@ -4,10 +4,6 @@ import { Bus, BasicScanlineMachine, xorshift32, SavesState } from "../common/dev import { KeyFlags } from "../common/emu"; // TODO import { hex, lzgmini, stringToByteArray, RGBA, printFlags } from "../common/util"; -const cpuFrequency = 1022727; -const cpuCyclesPerLine = 65; // approx: http://www.cs.columbia.edu/~sedwards/apple2fpga/ -const cpuCyclesPerFrame = 65*262; - // TODO: read prodos/ca65 header? const VM_BASE = 0x803; // where to JMP after pr#6 const LOAD_BASE = VM_BASE; @@ -39,10 +35,11 @@ interface SlotDevice extends Bus { export class AppleII extends BasicScanlineMachine { - cpuFrequency = 1023000; + // approx: http://www.cs.columbia.edu/~sedwards/apple2fpga/ + cpuFrequency = 1022727; sampleRate = this.cpuFrequency; - cpuCyclesPerLine = 65; // approx: http://www.cs.columbia.edu/~sedwards/apple2fpga/ - cpuCyclesPerFrame = 65*262; + cpuCyclesPerLine = 912/14; // approx: http://www.cs.columbia.edu/~sedwards/apple2fpga/ + cpuCyclesPerFrame = this.cpuCyclesPerLine * 262; canvasWidth = 280; numVisibleScanlines = 192; numTotalScanlines = 262; diff --git a/src/platform/apple2.ts b/src/platform/apple2.ts index 6c415278..c49dba89 100644 --- a/src/platform/apple2.ts +++ b/src/platform/apple2.ts @@ -16,6 +16,7 @@ const APPLE2_PRESETS = [ {id:'hgrtest.a', name:"HGR Test (ASM)"}, {id:'conway.a', name:"Conway's Game of Life (ASM)"}, {id:'lz4fh.a', name:"LZ4FH Decompressor (ASM)"}, + {id:'deltamod.dasm', name:"Delta Modulation (ASM)"}, // {id:'zap.dasm', name:"ZAP! (ASM)"}, // {id:'tb_6502.s', name:'Tom Bombem (assembler game)'}, ];