Short beeper routines in assembly

The place for codemasters or beginners to talk about programming any language for the Spectrum.
User avatar
Seven.FFF
Manic Miner
Posts: 340
Joined: Sat Nov 25, 2017 10:50 pm
Location: USA

Re: Short beeper routines in assembly

Post by Seven.FFF » Tue Oct 15, 2019 5:18 pm

djnzx48 wrote:
Mon Oct 14, 2019 7:00 am
I rechecked the wiki page about I/O contention. Is it just me, or does it have a mistake?

According to the description, "access to ports between 0x4000 and 0x7ffe with the low bit clear (i.e. when the ULA's own port is not being accessed) is subject to contention on every T state."

This seems to be contradicted by the table on the same page, which indicates contention on every T-state when the low bit is set. When it mentions the 'low bit clear', does that refer to the bit being set or reset?
I think you are right. IMO it should say “ Access to ports between 0x4000 and 0x7ffe with the low bit SET (i.e. when the ULA's own port is not being accessed) is subject to contention on every T state”
0 x
Robin Verhagen-Guest
SevenFFF / Threetwosevensixseven / colonel32
seven-fff.com/blog

User avatar
Woodster
Berk
Posts: 26
Joined: Mon Nov 13, 2017 12:17 pm

Re: Short beeper routines in assembly

Post by Woodster » Tue Oct 15, 2019 6:22 pm

Seven.FFF wrote:
Tue Oct 15, 2019 5:18 pm
I think you are right. IMO it should say “ Access to ports between 0x4000 and 0x7ffe with the low bit SET (i.e. when the ULA's own port is not being accessed) is subject to contention on every T state”
It should indeed say when the low bit is set.
1 x

User avatar
djnzx48
Manic Miner
Posts: 539
Joined: Wed Dec 06, 2017 2:13 am
Location: New Zealand

Re: Short beeper routines in assembly

Post by djnzx48 » Tue Oct 15, 2019 9:45 pm

That makes more sense. But why is port 0x7fff not included in that range? Should 0x7ffe be changed to 0x7fff, or is that correct as it is?
0 x

User avatar
Seven.FFF
Manic Miner
Posts: 340
Joined: Sat Nov 25, 2017 10:50 pm
Location: USA

Re: Short beeper routines in assembly

Post by Seven.FFF » Tue Oct 15, 2019 9:48 pm

Yes, it should be included I think. Part of the same mistake.
0 x
Robin Verhagen-Guest
SevenFFF / Threetwosevensixseven / colonel32
seven-fff.com/blog

User avatar
R-Tape
Site Admin
Posts: 2536
Joined: Thu Nov 09, 2017 11:46 am

Waves lapping on the shore beeper sound

Post by R-Tape » Sun Nov 03, 2019 2:36 pm

I'm trying to approximate the soothing sound of gentle waves lapping on a tropical shore, but my attempts so far are closer to a stormy day at Heysham. I'm just posting this in case anyone can suggest improvements or even post better code examples*. It has to be a shortish piece of code, so no huge samples.

*to be clear: I want to make it sound more gentle.

Code: Select all

org 32768	;might be slightly better in contended memory
mloop:	call wave
	call wavelaprumble ;(superfluous?)
	call betweenwavepause
	jr mloop
	;
betweenwavepause:
	ld b,30
	call rnd
	and 15
	add a,b
	ld b,a
bwplp:	halt
	djnz bwplp
	ret
	;
wavelaprumble:
	ld bc,10000
bwlp:	call rnd
	and 16
	out (254),a
	dec bc
	ld a,b
	or c
	jr nz,bwlp
	ret
	;
wave:	ld c,63
	ld de,1024
	ld hl,0
main:	call rnd
	and 16
	out (254),a
	ld e,c
dlp:	dec e
	jr nz,dlp
dlp1:	dec de
	ld a,d
	or a
	jr nz,miss
ica:	dec c
	ret z
miss:	ld a,d
	or e
	jr nz,main
	ld a,2
	out (254),a
	ret
	;
;PATRIK RAK's XOR SHIFT RND generator
rnd:
	push hl
	push de
rsd0:	ld  hl,0xA280   ; yw -> zt
rsd1:	ld  de,0xC0DE   ; xz -> yw
	ld  (rnd+6),hl  ; x = y, z = w
	ld  a,l         ; w = w ^ ( w << 3 )
	add a,a
	add a,a
	add a,a
	xor l
	ld  l,a
	ld  a,d         ; t = x ^ (x << 1)
	add a,a
	xor d
	ld  h,a
	rra             ; t = t ^ (t >> 1) ^ w
	xor h
	xor l
	ld  h,e         ; y = z
	ld  l,a         ; w = t
	ld  (rnd+3),hl
	pop de
	pop hl
	ret
	;
0 x

User avatar
Seven.FFF
Manic Miner
Posts: 340
Joined: Sat Nov 25, 2017 10:50 pm
Location: USA

Re: Short beeper routines in assembly

Post by Seven.FFF » Sun Nov 03, 2019 4:48 pm

I think Shiru’s BeepFX is a valuable tool for prototyping beeper effects in a RAD way.

https://shiru.untergrund.net/software.shtml

To be clear, it’s an fx engine that runs in the Speccy, combined with an editor that runs on the pc. However... the editor gives you a very clear idea of which different component parts the sound you are creating has. It also has a settings randomiser which is a useful way of coming up with completely unexpected effects.

Armed with this understanding, it would be extremely quick to try out different sounds in the editor, then write your own raw asm to approximate the sounds that please you, based on their component parts.
1 x
Robin Verhagen-Guest
SevenFFF / Threetwosevensixseven / colonel32
seven-fff.com/blog

catmeows
Berk
Posts: 34
Joined: Tue May 28, 2019 11:02 am

Re: Short beeper routines in assembly

Post by catmeows » Sun Nov 03, 2019 5:25 pm

Image

Try to produce very short impulses. Regarding the occasional clicks, I'm suspecting my source of "randomness" . Perhaps with proper RNG, you could avoid it (I was to lazy to type in Rak's LCRNG to memory, sorry).
1 x

catmeows
Berk
Posts: 34
Joined: Tue May 28, 2019 11:02 am

Re: Short beeper routines in assembly

Post by catmeows » Sun Nov 03, 2019 5:52 pm

One more experiment :)

Code: Select all

	ld hl, $0300		 ; b000 21 00 03 $0ats
l_b003: ld a, (hl)		 ; b003 7e $07ts
	inc hl			 ; b004 23 $06ts
	and $13			 ; b005 e6 13 $07ts
	out ($fe), a		 ; b007 d3 fe $0bts
	inc de			 ; b009 13 $06ts
	ld b, d			 ; b00a 42 $04ts
	xor a			 ; b00b af $04ts
	out ($fe), a		 ; b00c d3 fe $0bts
	ld a, b			 ; b00e 78 $04ts
	and $3f			 ; b00f e6 3f $07ts
	inc a			 ; b011 3c $04ts
	ld b, a			 ; b012 47 $04ts
l_b013: djnz l_b013		 ; b013 10 fe $08/$0dts
	ld a, h			 ; b015 7c $04ts
	and $00			 ; b016 e6 00 $07ts
	add a, $0f		 ; b018 c6 0f $07ts
	ld h, a			 ; b01a 67 $04ts
	jr l_b003		 ; b01b 18 e6 $0ct
0 x

User avatar
djnzx48
Manic Miner
Posts: 539
Joined: Wed Dec 06, 2017 2:13 am
Location: New Zealand

Re: Short beeper routines in assembly

Post by djnzx48 » Mon Nov 04, 2019 10:35 am

Here's my attempt. I don't really understand how PWM works so I ended up with some annoying high-pitched tones. Maybe I'm not toggling the speaker bit fast enough.

Code: Select all

org 32768
main:
        di

        ld hl, pwm_table + 240
        ld (pwm_ptr+1), hl

        ld hl, 0
        ld (time+1), hl

        ld hl, 0xC0DE

        ld de, 0

        ld a, 1 ; pitch
        ld (pitch+1), a
        ld b, a

mainloop:
        add hl, hl              ; 11 / 816
        jr nc, no_carry         ;  7 / 823 [828 taken]

        ret nc                  ;  5 / 828
        nop                     ;  4 / 832
        nop                     ;  4 / 836

        ld a, c                 ;  4 / 840
        out ($fe), a            ; 11 / 851 [840] [next 896]

        ld a, l                 ;  4 / 855
        xor %00101101           ;  7 / 862
        ld l, a                 ;  4 / 866

out_loop:

pwm_ptr:
        ld de, pwm_table        ; 10 / 876
        ld c, 12                ;  7 / 883

pwm_loop:
        ld a, (de)              ;  7 / 890 / 50
        inc de                  ;  6 / 896 / 56

        ; first OUT
        out ($fe), a            ; 11 /  11 [896] [0]

        ld a, r                 ;  9 /  20
        ld a, r                 ;  9 /  29

        dec c                   ;  4 /  33
        jp nz, pwm_loop         ; 10 /  43

        ; ---------------------      / 659 [next 672]

        ld a, (de)              ;  7 / 666
        inc de                  ;  6 / 672

        ; 13th OUT
        out ($fe), a            ; 11 / 683 [672] [next 728]

        ; 14th value
        ld a, (de)              ;  7 / 690
        inc de                  ;  6 / 696
        ex af, af'              ;  4 / 700

        ; 15th value
        ld a, (de)              ;  7 / 707
        ld a, (de)              ;  7 / 714
        inc de                  ;  6 / 720

        nop                     ;  4 / 724

        ; 14th OUT
        ex af, af'              ;  4 / 728
        out ($fe), a            ; 11 / 739 [728] [next 784]

        ; 16th value
        ld a, (de)              ;  7 / 746
        ld a, (de)              ;  7 / 753
        ld c, a                 ;  4 / 757

        ; retrieve 15th value
        ex af, af'              ;  4 / 761

        djnz out_continue       ;  8 / 769 [774 taken]

pitch:
        ld b, 0                 ;  7 / 776

        nop                     ;  4 / 780
        nop                     ;  4 / 784

        out ($fe), a            ; 11 / 795 [784] [next 840]

        jp mainloop             ; 10 / 805

; ============================================

out_continue:
        dec de                  ;  6 / 780
        nop                     ;  4 / 784

        out ($fe), a            ; 11 / 795 [784] [next 840]

        ld a, (de)              ;  7 / 802
        ld a, (de)              ;  7 / 809
        ld a, (de)              ;  7 / 816
        ld a, (de)              ;  7 / 823
        ld a, r                 ;  9 / 832
        xor a                   ;  4 / 836

        ld a, c                 ;  4 / 840
        out ($fe), a            ; 11 / 851

        ret nz                  ;  5 / 856

        jp out_loop             ; 10 / 866

; ============================================

no_carry:                       ;    / 828

        nop                     ;  4 / 832
        nop                     ;  4 / 836

        ld a, c                 ;  4 / 840
        out ($fe), a            ; 11 / 851 [840] [next 896]

        ; waste time
        ld de, 0                ; 10 / 861
        ld a, (de)              ;  7 / 868
        ld a, (de)              ;  7 / 875
        ld a, (de)              ;  7 / 882
        ld a, (de)              ;  7 / 889

        ld a, 0                 ;  7 / 896
        out ($fe), a            ; 11 /  11 [896] [0]

        ld c, a                 ;  4 /  15

        ; ---------------------

time:
        ld de, 0                ; 10 /  25

        inc de                  ;  6 /  31
        ld (time+1), de         ; 20 /  51

        ld a, d                 ;  4 /  55
        and 15                  ;  7 /  62

        bit 4, d                ;  8 /  70
        jr nz, reverse_wave     ;  7 /  77 [82 taken]

        ld de, 0                ; 10 /  87
        jp continue_wave        ; 10 /  97

reverse_wave:

        sub 15                  ;  7 /  89
        neg                     ;  8 /  97

continue_wave:

        add a, a                ;  4 / 101
        add a, a                ;  4 / 105
        add a, a                ;  4 / 109
        add a, a                ;  4 / 113

        push hl                 ; 11 / 124
        ld hl, pwm_table        ; 10 / 134

        ld d, 0                 ;  7 / 141
        ld e, a                 ;  4 / 145

        add hl, de              ; 11 / 156
        ld (pwm_ptr+1), hl      ; 16 / 172

        pop hl                  ; 10 / 182

        ; ---------------------

        ld a, 36                ;  7 / 189

        ; total time = 35 * (4 + 12) + (4 + 7) = 571
delay_loop:                     ;571 / 760
        dec a
        jr nz, delay_loop

        ld de, 0                ; 10 / 770
        ld de, 0                ; 10 / 780

        xor a                   ;  4 / 784

        out ($fe), a            ; 11 / 795 [784] [next 840]

        jp mainloop             ; 10 / 805

pwm_table:
        db 16,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
        db 16,  0,  0,  0,  0,  0,  0,  0, 16,  0,  0,  0,  0,  0,  0,  0
        db 16,  0,  0,  0,  0, 16,  0,  0,  0,  0,  0, 16,  0,  0,  0,  0
        db 16,  0,  0,  0, 16,  0,  0,  0, 16,  0,  0,  0, 16,  0,  0,  0
        db 16,  0,  0, 16,  0,  0, 16,  0,  0,  0, 16,  0,  0, 16,  0,  0
        db 16,  0,  0, 16,  0, 16,  0,  0, 16,  0,  0, 16,  0, 16,  0,  0
        db 16,  0, 16,  0,  0, 16,  0, 16,  0, 16,  0, 16,  0,  0, 16,  0
        db 16,  0, 16,  0, 16,  0, 16,  0, 16,  0, 16,  0, 16,  0, 16,  0
        db 16,  0, 16,  0, 16, 16,  0, 16,  0, 16,  0, 16, 16,  0, 16,  0
        db 16,  0, 16, 16,  0, 16, 16,  0, 16,  0, 16, 16,  0, 16, 16,  0
        db 16, 16,  0, 16, 16,  0, 16, 16,  0, 16, 16,  0, 16, 16,  0, 16
        db 16, 16,  0, 16, 16, 16,  0, 16, 16, 16,  0, 16, 16, 16,  0, 16
        db 16, 16, 16,  0, 16, 16, 16, 16,  0, 16, 16, 16, 16,  0, 16, 16
        db 16, 16, 16, 16,  0, 16, 16, 16, 16, 16, 16, 16,  0, 16, 16, 16
        db 16, 16, 16, 16, 16, 16, 16, 16,  0, 16, 16, 16, 16, 16, 16, 16
        db 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16
0 x

User avatar
R-Tape
Site Admin
Posts: 2536
Joined: Thu Nov 09, 2017 11:46 am

Re: Short beeper routines in assembly

Post by R-Tape » Mon Nov 04, 2019 11:17 am

djnzx48 wrote:
Mon Nov 04, 2019 10:35 am
Here's my attempt. I don't really understand how PWM works so I ended up with some annoying high-pitched tones. Maybe I'm not toggling the speaker bit fast enough.
Ohhh that would be perfect if we can get rid of those extra tones. We're nearly on the desert island now, but with a pager going off in your rucksack.

I tried reducing some of the delays and 'waste times' and it reduced the tones a lot, and didn't really affect the wave noise itself (to my uneducated ear). It's still now there though. Putting it in contended memory didn't remove the tones, but changed them into a different sound that doesn't grate quite as much.

Brilliant work. I hope these noises spikes can be smoothed out.
0 x

Post Reply