Short beeper routines in assembly

The place for codemasters or beginners to talk about programming any language for the Spectrum.
User avatar
djnzx48
Manic Miner
Posts: 537
Joined: Wed Dec 06, 2017 2:13 am
Location: New Zealand

Re: Short beeper routines in assembly

Post by djnzx48 » Mon Nov 04, 2019 12:27 pm

Interesting that reducing the delays helped. I tried to keep the time between OUTs a constant 56 T-states to ensure regular output - 56 is also a multiple of 8 to avoid IO contention. I assume that more irregular delays would reduce the harmonics but in turn raise the noise floor.

I think the problem may be due to how the OUTs are performed in groups of 16, so for values that don't divide 16 the resulting pulse wave is irregular. I don't know for sure though.
0 x

ixn
Berk
Posts: 3
Joined: Thu Feb 22, 2018 4:44 am

Re: Short beeper routines in assembly

Post by ixn » Wed Nov 06, 2019 2:02 am

If you put this after the two ld a, r instructions in the code posted by djnzx48, you can get some arcing power lines in the background:

Code: Select all

        inc ix
        ld a, (ix)
        out ($fe), a
0 x

ixn
Berk
Posts: 3
Joined: Thu Feb 22, 2018 4:44 am

Re: Short beeper routines in assembly

Post by ixn » Wed Nov 06, 2019 7:22 am

You can get another "interesting" sound by also sticking

Code: Select all

        inc iy
        ld c, (iy)
at the start of pwm_loop.

It sounds good assembled at about 50000.
0 x

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

Re: Short beeper routines in assembly

Post by djnzx48 » Wed Nov 06, 2019 8:52 pm

Any better?

Code: Select all

org 32768
main:
        di

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

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

        ld hl, 0xC0DE

        ld de, 0

        ld b, 16

        xor a
        ld c, a

        ld ixl, %00101101

        jp mainloop_init

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

        ; runtime = 10 * 56 + 51 = 611
pwm_loop:                       ;    /  37
        xor d                   ;  4 /  41 [/  97]
        add a, e                ;  4 /  45 [/ 101]
        ld d, a                 ;  4 /  49 [/ 105]

        and 16                  ;  7 /  56 [/ 112]

        out ($fe), a            ; 11 /  67 [ 56]

        jp pwm_delay            ; 10 /  77

pwm_delay:
        dec c                   ;  4 /  81
        jr nz, pwm_loop         ; 12 /  93 [taken]

                                ;611 / 648

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

        xor d                   ;  4 / 652
        add a, e                ;  4 / 656
        ld d, a                 ;  4 / 660

        and 16                  ;  7 / 667

        ret c                   ;  5 / 672

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

        out ($fe), a            ; 11 / 683      ; OUT 12

        xor d                   ;  4 / 687
        add a, e                ;  4 / 691
        ld d, a                 ;  4 / 695

        and b                   ;  4 / 699      ; OUT 13 value
        ld c, a                 ;  4 / 703
        xor d                   ;  4 / 707

        add a, e                ;  4 / 711
        ld d, a                 ;  4 / 715

        ld a, r                 ;  9 / 724

        ld a, c                 ;  4 / 728      ; OUT 13 value

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

        out ($fe), a            ; 11 / 739      ; OUT 13

        ld a, d                 ;  4 / 743

        and b                   ;  4 / 747      ; OUT 14 value
        ld c, a                 ;  4 / 751
        xor d                   ;  4 / 755

        add a, e                ;  4 / 759
        ld d, a                 ;  4 / 763

        and b                   ;  4 / 767      ; OUT 15 value
        ld e, a                 ;  4 / 771

        ld a, r                 ;  9 / 780

        ld a, c                 ;  4 / 784      ; OUT 14 value

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

        ld a, e                 ;  4 / 799
        xor d                   ;  4 / 803

        ; 2 spare T-states!

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

        ld (volume+2), a        ; 13 / 836

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

        ld a, l                 ;  4 / 855
        xor ixl                 ;  8 / 863
        ld l, a                 ;  4 / 867

        ; OUTs:
        ;
        ;  0      0
        ;  1     56
        ;  2    112
        ;  3    168
        ;  4    224
        ;  5    280
        ;  6    336
        ;  7    392
        ;  8    448
        ;  9    504
        ; 10    560
        ; 11    616
        ; 12    672
        ; 13    728
        ; 14    784
        ; 15    840
        ; ---------
        ; 16    896

out_loop:

volume:
        ld de, 0                ; 10 / 877

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

        ld a, d                 ;  4 / 881
        add a, e                ;  4 / 885
        ld d, a                 ;  4 / 889

        and 16                  ;  7 / 896

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

        ld a, r                 ;  9 /  20
        ld c, 11                ;  7 /  27

        jp pwm_loop             ; 10 /  37

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

no_carry:                       ;    / 828

        nop                     ;  4 / 832
        ex af, af'              ;  4 / 836

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

        ex af, af'              ;  4 / 855
        ld (volume+2), a        ; 13 / 868

        ld a, 0                 ;  7 / 875
        ld a, 0                 ;  7 / 882
        ld a, 0                 ;  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:

        inc a                   ;  4 / 101
        ld (volume+1), a        ; 13 / 114

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

        ld a, 41                ;  7 / 121

        ; total time = 40 * (4 + 12) + (4 + 7) = 651
delay_loop:                     ;651 / 772
        dec a
        jr nz, delay_loop

        nop                     ;  4 / 776

        xor a                   ;  4 / 780
        ld e, a                 ;  4 / 784

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

        jp extra_delay          ; 19 / 805

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

        jp mainloop             ; 10 / 836
2 x

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

Re: Short beeper routines in assembly

Post by R-Tape » Wed Nov 06, 2019 9:43 pm

djnzx48 wrote:
Wed Nov 06, 2019 8:52 pm
Any better?
It's incredible. And 176 bytes. Hell.

I see the code is very different. There is the slightest memory of the ghost sounds from before, but they wouldn't even be noticed (and even if they were, they could be taken as soothing) if this was the first iteration. Do I take it that you understand what was causing the spikes previously?

How do you do it?!
0 x

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

Re: Short beeper routines in assembly

Post by djnzx48 » Wed Nov 06, 2019 10:01 pm

No idea. All I did was replace the table I was using previously with dynamically calculated values.
0 x

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

Re: Short beeper routines in assembly

Post by R-Tape » Wed Nov 06, 2019 10:18 pm

djnzx48 wrote:
Wed Nov 06, 2019 10:01 pm
No idea.
Slightly reassuring!
All I did was replace the table I was using previously with dynamically calculated values.
I haven't pulled it apart yet, but it looks like there's extra code too. Anyway, it's a brilliant piece of work.
0 x

Post Reply