6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Mon Jul 08, 2024 11:28 pm

All times are UTC




Post new topic Reply to topic  [ 7 posts ] 
Author Message
PostPosted: Wed Sep 04, 2019 5:47 pm 
Offline

Joined: Sun Jun 29, 2014 5:42 am
Posts: 337
Hi all,

I'd like to be able to use the 6522's CA1 pin as an ordinary input and poll it's current value.

(This is on the printer port of the BBC Micro)

My reading of the 6522 datasheet is that this is not possible.

CA1 can be configured as an "interrupt input", where the currently programmed active edge sets the CA1 flag in the interrupt flag register. But that's a bit different, and as far as I understand there is no way to simply establish the current value.

Is my thinking correct here, or are there some techniques that I am missing?

Dave


Top
 Profile  
Reply with quote  
PostPosted: Wed Sep 04, 2019 7:12 pm 
Offline

Joined: Mon May 21, 2018 8:09 pm
Posts: 1462
As far as I can tell, that is correct. The active edge of CA1 sets the corresponding bit in the IFR (regardless of the value of the IER) and optionally latches the current inputs of PA0-7. You can then select the opposite edge as the trigger to work out when it falls, but there's no guarantee that it hasn't already occurred.


Top
 Profile  
Reply with quote  
PostPosted: Wed Sep 04, 2019 7:20 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8464
Location: Southern California
CA1, when used as an input, can only be edge-sensitive, not level-sensitive. Although you cannot poll its current value, you can poll to see if there's been an active edge, by reading the IFR, without actually making it interrupt, if that helps. Just leave its flag in the IER a 0.

_________________
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?


Top
 Profile  
Reply with quote  
PostPosted: Wed Sep 04, 2019 9:08 pm 
Offline

Joined: Sun Jun 29, 2014 5:42 am
Posts: 337
Thanks all for confirming this.

Some background: what I've been exploring is whether it's possible connect an SD Card to the BBC Micro's printer port (usinmg SPI). The printer port uses the 6522's port A buffered via a 74LS244:
Attachment:
printer.png
printer.png [ 80.88 KiB | Viewed 1301 times ]

(Normally on the BBC Micro, a modern SD card would be interfaced to the User Port, which uses the 6522's Port B. This can then use the 6522's shift register for efficiently reading data. Obviously you loose that with Port A).

I'm currently using:
- Port A D0 for MOSI (output)
- Port A D1 for SCK (output)
- Port A D7 for MISO (input, wired to bypass the LS244)

This is the best I could come up with for the read byte code:
Code:
.P1_ReadByte
    LDA #&FF   
    LDX #one_clocklow%
    SEC          \\ Set carry so D0 (MOSI) remains high after ROL
FOR n, 0, 7
    STX iora%    \\ Take clock (D1) low
    ROL iora%    \\ Sample D7 (MISO) into C, and take clock (D1) high
    ROL A        \\ C=1 after this, because A starts off as FF
NEXT
    RTS

This works, but requires some modifications to the Beeb, namely to allow D7 to be used as an input. See here for more details.

So I'd like to use CA1 instead of D7, but the difficultly is the initial value of MISO is not always known. And without this, you can't correctly program the active edge for the interrupt. It would also, I suspect, be substantially less efficient.

Dave


Top
 Profile  
Reply with quote  
PostPosted: Thu Sep 05, 2019 6:58 am 
Offline
User avatar

Joined: Fri Dec 11, 2009 3:50 pm
Posts: 3366
Location: Ontario, Canada
hoglet wrote:
So I'd like to use CA1 instead of D7, but the difficultly is the initial value of MISO is not always known.
Perhaps your initialization procedure could include a routine whose purpose is to coax MISO to go high and then low (or low and then high) one or more times. This would be purely for warm-up, with no meaningful transfer of data, and it'd be harmless if you happen not to detect the very first transition... as will happen, for example, if the first transition is positive but CA1 starts off programmed to detect a negative transition. As long as you can produce some sort of warmup activity I think you should be able to get the assumptions in step with reality before the actual, "real work" data transmission begins. :)

Quote:
It would also, I suspect, be substantially less efficient.
Yup. After detecting a negative edge you'll re-program CA1 to detect a positive edge, and vice versa. But the performance hit might not be too bad if you're willing to be a bit fanatical about how the thing is coded! :twisted:

cheers
Jeff

_________________
In 1988 my 65C02 got six new registers and 44 new full-speed instructions!
https://laughtonelectronics.com/Arcana/ ... mmary.html


Top
 Profile  
Reply with quote  
PostPosted: Thu Sep 05, 2019 9:42 am 
Offline

Joined: Sun Jun 29, 2014 5:42 am
Posts: 337
Dr Jefyll wrote:
As long as you can produce some sort of warmup activity I think you should be able to get the assumptions in step with reality before the actual, "real work" data transmission begins. :)

I've been thinking about this some more, and I now believe that every SPI response sequence should start with a 1=>0 transition, so that really simplifies things.
Dr Jefyll wrote:
After detecting a negative edge you'll re-program CA1 to detect a positive edge, and vice versa. But the performance hit might not be too bad if you're willing to be a bit fanatical about how the thing is coded! :twisted:

Here's my original code that uses D7:
Code:
FOR n, 0, 7
    STX iora%    \\ (4) Take clock (D1) low
    ROL iora%    \\ (6) Sample D7 (MISO) into C, and take clock (D1) high
    ROL A        \\ (2) C=1 after this, because A starts off as FF
NEXT
    RTS

That works out at 12 cycles per bit.

Here's a completely untested version that uses CA1:
Code:

FOR n, 0, 7
    // clock low, clear CA1 int, MISO changes on this edge
    LDA #&FD     // (2)
    STA ora%     // (4)
    // Update active edge
    LDA ifr%     // (4) IFR bit 1 set if active edge seen
    ROR A        // (2) Move to bit 0
    AND #&01     // (2) Mask off all other bits
    EOR pcr%     // (4) toggle active edge if necessary
    STA pcr%     // (4) bit 0 of A is now not(CA1)
    // Accumulate value of not(CA1) in zero page sr%
    ROR A        // (2) C=not(CA1)
    ROL sr%      // (5) Accumulate result (bit 7 sent first)
    // clock high, clear CA1 int
    LDA #&FF     // (2)
    STA ora%     // (4)
NEXT
    LDA sr%
    EOR #&FF     // Invert to correct negation
    RTS

This works out at 35 cycles per bit, so about 3x slower.

That's probably too much of a performance hit, but it would be interesting to see if this actually works.

Dave


Top
 Profile  
Reply with quote  
PostPosted: Thu Sep 05, 2019 12:31 pm 
Offline

Joined: Sun Jun 29, 2014 5:42 am
Posts: 337
Gosh, and it actually works, albeit rather slowly!

The final "read bit" code is:
Code:
iora%=_VIA_BASE + &01
ddra%=_VIA_BASE + &03
pcr%= _VIA_BASE + &0C
ifr%= _VIA_BASE + &0d
iorx%=_VIA_BASE + &0f

\\ MOSI is connected to D0
\\ SCK  is connected to D1
\\ MISO is connected to CA1

\\ This is unused on the Beeb, according to JGH
sr%=&F8

clockbit%=&02
   
one_clockhigh%=&FF
one_clocklow%=&FF-clockbit%

MACRO READ_BIT
    \\ clock low, MISO changes on this edge
    LDA #one_clocklow%  \\ (2)
    STA iorx%           \\ (4) Don't clear CA1 int!
    \\ Update active edge
    LDA ifr%            \\ (4) IFR bit 1 set if active edge seen
    ROR A               \\ (2) Move to bit 0
    AND #&01            \\ (2) Mask off all other bits
    EOR pcr%            \\ (4) toggle active edge if necessary
    STA pcr%            \\ (4) bit 0 of A is now not(CA1)
    \\ Accumulate value of not(CA1) in zero page sr%
    ROR A               \\ (2) C=not(CA1)
    ROL sr%             \\ (5) Accumulate result (bit 7 sent first)
    \\ clock high, clear CA1 int
    LDA #one_clockhigh% \\ (2)
    STA iora%           \\ (4)
ENDMACRO

The complete code is in github:
https://github.com/hoglet67/MMFS/blob/m ... terCA1.asm

The only change I had to make was to use the alterate version of IORA (at register offset F) in one place to avoid a race condition clearing the interrupt flag as it was being updated.

Dave


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 7 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 21 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: