I have here this time-critical routine to play samples on the psg which I don't completely undestand. But I want to:
A little code-snippet:
ld de,#0xb6f6
later on:
ld a,e ; 4
out (#0xff),a ; Send &f6 to port &f6 (Select Register)
Why does this output on port 0xF6 ?
later on:
ld a,d ; 4
out (#0xff),a ; 12 Send &b6 to port &f6 (Write Register)
And why does this output on port 0xF6 ?
Quote from: Shining on 13:37, 10 November 17
I have here this time-critical routine to play samples on the psg which I don't completely undestand. But I want to:
A little code-snippet:
ld de,#0xb6f6
later on:
ld a,e ; 4
out (#0xff),a ; Send &f6 to port &f6 (Select Register)
Why does this output on port 0xF6 ?
later on:
ld a,d ; 4
out (#0xff),a ; 12 Send &b6 to port &f6 (Write Register)
And why does this output on port 0xF6 ?
out (nn),a
register A is put into i/o address bits 15-8. nn is put into i/o address bits 7..0.
and register A data is written to the port.
ld a,e ; 4
out (#0xff),a ; Send &f6 to port &f6 (Select Register)
This is the same as out &F6FF,&F6. (here A = f6)
port f6 bits 7 and 6 are PSG "function", this is from the data written to &f6xx.
00xxxxxx = inactive,
11xxxxxx = register select,
01xxxxxx = read data,
10xxxxxxx = write data.
bits 3..0 are keyboard line, other bits for cassette.
Other OUT (n),A is out &b6ff,&b6.
with &b6 as data 10110110. bit 7=1,bit6 = 0, which is write data to psg.
decoding of both of these ports:
1111011011111111 <-f6ff
1011011011111111 <-b6ff
port decoding for 8255:
%xxxx0x10 xxxxxxxx
both have this in common. So both will access 8255.
But b6ff clashes with crtc because it decodes I/O address with:
%x0xxxxxx xxxxxxxx
Thankfully the other bits mean that crtc is selected for reading and it's doing a write. Shouldn't be a problem.
Don't use port B6, this may work on emulators, but it's dirty coding on a real CPC.
Thanks for your explanations ! I was aware what the code did but not why. I did not know that the bits in a were the high-byte of the address.
Because the code is for this Viterbi search 3-channel-digi-routine like (https://github.com/maxim-zhao/pcmenc), timing is very important.
But like the out is used in this algorithm, the out turns always the tape-relais on. I wanted to understand why the out worked and how to possibly find a solution (taking the same amout of cycles) where I can change the value for the port.
The original algorithm loads registers outside the time-critical part:
ld b,#0xf4
ld de,#0xb6f6
ld hl,#0x3608
And then during the time-critical part ist does:
ld a,e ; 4
out (#0xff),a ; 12 Send &f6 to port &f6 (Select Register)
ld c,l ; 4
out (c),c ; 16 Send &08 to port &f4 (Channel A)
ld a,h ; 4
out (#0xff),a ; 12 Send &36 to port &f6 (Inactive State)
Which are:
out &b6ff,&b6
out &F4xx,&08
out &36FF,&36 (which also adresses the pio. Again thanks for your explanation)
When I'm right and I replace &F6 through &E6 and &36 through &16, also the PIO is adressed but the relais remains off.
I'm now (thanks gunhed) aware that this also addresses other hardware, but is this possible ? I do not find an "undirty" replacement of the code, using exactly the same amount of cycles.
Ok, this dirty coding saves few us, but is that needed?
I would suggest to use
LD BC,&XXXX
OUT (C),C
This way still should be quick enough.