Another 6522 SPI question
Another 6522 SPI question
Hi all,
I am trying to get SPI working on an interface card I am creating for my Apple ][ (actually an Apple IIgs). I am trying to use the implementation by André for his CS/A65, rev 1.1A. I had to re-create the PHI2 signal, as the Apple ][ bus doesn't include it, by using a 74HCT74 as per Apple's TIL #494 info.
I had to rewrite the driver by André, as I use indexed I/O to the card (using /DEVSEL), but it was almost a complete copy-and-paste action.
However it seems the SCLK is out-of-sync with the MOSI/MISO signal(s), but I am at a lost right now of where the culprit would be....
I have attached both the screenshot of my logic analyzer (Bitscope micro/Bitscope Logic combo) and the source, written for ca65.
Does anyone know what might be solution to my 'problem'? I have this issue while both shifting under T2 and PHI2
Thanks in advance!
I am trying to get SPI working on an interface card I am creating for my Apple ][ (actually an Apple IIgs). I am trying to use the implementation by André for his CS/A65, rev 1.1A. I had to re-create the PHI2 signal, as the Apple ][ bus doesn't include it, by using a 74HCT74 as per Apple's TIL #494 info.
I had to rewrite the driver by André, as I use indexed I/O to the card (using /DEVSEL), but it was almost a complete copy-and-paste action.
However it seems the SCLK is out-of-sync with the MOSI/MISO signal(s), but I am at a lost right now of where the culprit would be....
I have attached both the screenshot of my logic analyzer (Bitscope micro/Bitscope Logic combo) and the source, written for ca65.
Does anyone know what might be solution to my 'problem'? I have this issue while both shifting under T2 and PHI2
Thanks in advance!
- Attachments
-
- main.s.zip
- Source file of my test driver
- (7.52 KiB) Downloaded 143 times
Re: Another 6522 SPI question
I'm very curious about this. I've been exploring SPI a teeny bit recently, and I've seen the things Andre has done. I will admit I didn't understand much of it.
It seems that SPI is, in essence, really quite simple: chip select the chip, put the value you want on the data pin, and toggle the clock pin. Rinse and repeat.
If I had two output ports A and B, and had pin 0 of A set to the clock, and pin 0 of B set to the data out line, shouldn't this "just work"?
Assuming that the device is fast enough to keep up, and yea, not the most efficient use of the ports, but… shouldn't this "just work"? Maybe I have the clock backward, but, on principle, isn't it supposed to be "this simple"?
Given that base understanding, I didn't grok the extra complexities and difficulties that Andre was talking about.
It seems that SPI is, in essence, really quite simple: chip select the chip, put the value you want on the data pin, and toggle the clock pin. Rinse and repeat.
If I had two output ports A and B, and had pin 0 of A set to the clock, and pin 0 of B set to the data out line, shouldn't this "just work"?
Code: Select all
LDA valueToSend ; Value to stream out
LDY 8 ; Number of bits
LOOP: STA PORT_B ; Store A to PORT_B, thus setting Pin 0 with LSBit
LDX #00 ; Toggle the clock
STX PORT_A ; down
LDX #01 ; ... then ...
STX PORT_A ; up
LSR ; Next bit
DEY ; around we go
BNE LOOP
Given that base understanding, I didn't grok the extra complexities and difficulties that Andre was talking about.
- GARTHWILSON
- Forum Moderator
- Posts: 8773
- Joined: 30 Aug 2002
- Location: Southern California
- Contact:
Re: Another 6522 SPI question
Mr. Hartung, SPI goes msb first, unlike RS-232. Otherwise your code looks right. Note that as long as you know the state of the clock pin, and it's on bit 0, you can cycle it without affecting the other bits using just INC<port> and DEC<port>. (The order will depend on the SPI mode.) And if you were going to take up the whole port, you might as well just shift the port itself to shorten the code. I have a section on bit-banging SPI in the 6502 primer's "circuit potpourri" page, at http://wilsonminesco.com/6502primer/pot ... ITBANG_SPI, and sample code to go with it at http://wilsonminesco.com/6502primer/SPI.ASM .
SPI can do input and output at the same time, but I don't think any of the SPI parts I've used took advantage of that. For MISO (the master-in, slave-out data line), it's nice to put it on bit 6 or 7 of a port so you can use the BIT instruction on it, regardless of what's in A, X, or Y, and without affecting them, and then branch on the V or N flag. The VIA's SR can be used for SPI within a heavy set of limitations. Bit-banging OTOH, although not as fast, gives the freedom to do all of the modes without extra logic, can input and output at the same time, and even do different numbers of bits per frame, of interest to me since I recently came across a data converter I'd like to use that can go with 12-bit frames.
SPI can do input and output at the same time, but I don't think any of the SPI parts I've used took advantage of that. For MISO (the master-in, slave-out data line), it's nice to put it on bit 6 or 7 of a port so you can use the BIT instruction on it, regardless of what's in A, X, or Y, and without affecting them, and then branch on the V or N flag. The VIA's SR can be used for SPI within a heavy set of limitations. Bit-banging OTOH, although not as fast, gives the freedom to do all of the modes without extra logic, can input and output at the same time, and even do different numbers of bits per frame, of interest to me since I recently came across a data converter I'd like to use that can go with 12-bit frames.
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?
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
Re: Another 6522 SPI question
GARTHWILSON wrote:
as long as you know the state of the clock pin, and it's on bit 0, you can cycle it without affecting the other bits using just INC<port> and DEC<port>.
GARTHWILSON wrote:
For MISO (the master-in, slave-out data line), it's nice to put it on bit 6 or 7 of a port so you can use the BIT instruction on it
Yes, by all means attach the SPI clock to bit0 of the port, because INC<port> (or DEC<port>) is usually faster than the instructions it would take to set (or clear) the clock if it were attached to some other bit. As for MISO (which requires testing when the Master is inputting), I recommend attaching it to bit7. Bit6 is special only if you use the BIT instruction -- and it turns out the BIT instruction can be optimized away! I didn't quite believe it at first, and had to give my head a shake. But I've successfully tested code equivalent to the following. Here's how the port bits are used in the snippets below. Bit1 (MOSI) was chosen arbitrarily; the other two not.
- bit7 of VIAPORT is in input mode -- attaches to MISO
- (bits available for other uses, especially as inputs)
- bit1 of VIAPORT is in output mode -- attaches to MOSI
- bit0 of VIAPORT is in output mode -- attaches to Ck
Code: Select all
SPIBYTEIN: LDA #1 ;LDA #1 is for counting
INPUTLOOP: 4 STZ VIAPORT_IO ;set Ck=0, mosi=0
6 INC VIAPORT_IO ;set Ck=1 INC DOES 2 THINGS (sets Ck; also updates N flag per MISO)
2/3 BMI MISO_IS_1
2 CLC ; MISO is =0
2 ROL A
3 BCC INPUTLOOP ;more bits?
RTS
MISO_IS_1: 2 SEC ; MISO is =1
2 ROL A
3 BCC INPUTLOOP ;more bits?
RTS
19/20 <----- cycles per bitCode: Select all
SPIBYTEIN: LDA #1 ;LDA #1 is for counting
INPUTLOOP: 4 STZ VIAPORT_IO ;set Ck=0, mosi=0
6 INC VIAPORT_IO ;set Ck=1 INC DOES 2 THINGS (sets Ck; also updates N flag per MISO)
2/3 BPL MISO_IS_0
2 SEC ;MISO is =1
2 ROL A
3 BCC INPUTLOOP ;more bits?
RTS
MISO_IS_0: 2 ASL A ;MISO is =0
3 BCC INPUTLOOP ;more bits?
RTS
19/18 <----- cycles per bit
Code: Select all
SPIBYTEOUT: LDY #2 ;Y is used to hold a constant.
SEC ;SEC / ROL A is for counting
ROL A
OUTPUTLOOP: 2/3 BCS MOSI_1
4 STZ VIAPORT_IO ;ck=0, mosi=0 STZ updates both Ck & mosi
6 INC VIAPORT_IO ;ck=1
2 ASL A
3 BNE OUTPUTLOOP ;more bits?
RTS
MOSI_1: 4 STY VIAPORT_IO ;ck=0, mosi=1 STY updates both Ck & mosi
6 INC VIAPORT_IO ;ck=1
2 ASL A
3 BNE OUTPUTLOOP ;more bits?
RTS
17/18 <----- cycles per bit
Last edited by Dr Jefyll on Mon Jun 04, 2018 3:30 am, edited 2 times in total.
In 1988 my 65C02 got six new registers and 44 new full-speed instructions!
https://laughtonelectronics.com/Arcana/ ... mmary.html
https://laughtonelectronics.com/Arcana/ ... mmary.html
Re: Another 6522 SPI question
So, in the first routine, A is set to the byte that it read, correct?
In the second routine, A contains the byte to be sent out. The SEC acts as a sentinel for when the byte is done. The ROL A shifts the first bit to send in to Carry.
Ok, I see how this works. This is very clever.
On an older 6502, you can use X = 0 in place of the STZ, yes?
The initial attraction to SPI was that it seems pretty bone simple, and easy to implement, even badly. And you can get reliable mass storage out of it in the end. Because with the SD cards, you can operated on them with 512 byte blocks, and not worry about leveling or any of those other Flash issues. I saw an article using a 8 pin SPI 1MB flash chip, but you have to manage the 4K page erases yourself and, ostensibly, manage the leveling and block use yourself as well. Having to dedicate 4K to a storage buffer just to write a single 512 byte block seemed excessive.
In the second routine, A contains the byte to be sent out. The SEC acts as a sentinel for when the byte is done. The ROL A shifts the first bit to send in to Carry.
Ok, I see how this works. This is very clever.
On an older 6502, you can use X = 0 in place of the STZ, yes?
The initial attraction to SPI was that it seems pretty bone simple, and easy to implement, even badly. And you can get reliable mass storage out of it in the end. Because with the SD cards, you can operated on them with 512 byte blocks, and not worry about leveling or any of those other Flash issues. I saw an article using a 8 pin SPI 1MB flash chip, but you have to manage the 4K page erases yourself and, ostensibly, manage the leveling and block use yourself as well. Having to dedicate 4K to a storage buffer just to write a single 512 byte block seemed excessive.
- GARTHWILSON
- Forum Moderator
- Posts: 8773
- Joined: 30 Aug 2002
- Location: Southern California
- Contact:
Re: Another 6522 SPI question
whartung wrote:
I saw an article using a 8 pin SPI 1MB flash chip, but you have to manage the 4K page erases yourself and, ostensibly, manage the leveling [...]
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?
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
- GARTHWILSON
- Forum Moderator
- Posts: 8773
- Joined: 30 Aug 2002
- Location: Southern California
- Contact:
Re: Another 6522 SPI question
Dr Jefyll wrote:
and it turns out the BIT instruction can be optimized away!
Quote:
Code: Select all
SPIBYTEIN: LDA #1 ;LDA #1 is for counting
INPUTLOOP: STZ VIAPORT_IO ;set Ck=0
INC VIAPORT_IO ;set Ck=1 INC DOES 2 THINGS (sets Ck; also updates N flag per MISO)
BMI MISO_IS_1
CLC ; MISO is =0
ROL A
<snip>
Also, other bits on the port will probably be in use for unrelated things, so STZ VIAPORT_IO should probably be replaced with DEC VIAPORT_IO to set Ck=0 without disturbing those other things. (It does assume bit 0 had been high though; so it will need initializing before you start into the loop.)
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?
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
Re: Another 6522 SPI question
GARTHWILSON wrote:
whartung wrote:
I saw an article using a 8 pin SPI 1MB flash chip, but you have to manage the 4K page erases yourself and, ostensibly, manage the leveling [...]
4K just seems like..a lot, especially on a 64K (or less: 32K) machine since it's ostensibly empty 99% of the time. A large gaping hole Just In Case.
The SD card manages all of that for me.
Of course, nowadays, you could probably get a tiny uController for $1 to act as a surrogate to the host and manage that aspect for you. That's effectively what's on a SD card already anyway. Stream 512 bytes to the surrogate, and use it's 4K of RAM to manage the Flash device.
But cost and part count aren't my primary concern.
Re: Another 6522 SPI question
Thanks for the feedback on the code, fellas. Here's the input routine, replacing CLC / ROL with ASL as Garth suggested. FWIW I also flipped the sense of the branch, because "one" bits ended up 3~ slower than "zero" bits, and I think I'd prefer the timing to be more uniform.
As before,
Yes -- and your inferences about register usage are also correct. I got a little lazy about commenting that!
Doing as you say will avoid disturbing those other bits, so it's a valid suggestion. But it slows the loop down by 2~ per bit, so let's only use it as a last resort. Depending on circumstances, there may be as many as three ways to avoid having writes such as STZ disturb the other bits.
As before,
- bit7 of VIAPORT is in input mode -- attaches to MISO
- (bits available for other uses, especially as inputs)
- bit1 of VIAPORT is in output mode -- attaches to MOSI
- bit0 of VIAPORT is in output mode -- attaches to Ck
Code: Select all
SPIBYTEIN: LDA #1 ;LDA #1 is for counting
INPUTLOOP: 4 STZ VIAPORT_IO ;set Ck=0, mosi=0
6 INC VIAPORT_IO ;set Ck=1 INC DOES 2 THINGS (sets Ck; also updates N flag per MISO)
2/3 BPL MISO_IS_0
2 SEC ;MISO is =1
2 ROL A
3 BCC INPUTLOOP ;more bits?
RTS
MISO_IS_0: 2 ASL A ;MISO is =0
3 BCC INPUTLOOP ;more bits?
RTS
19/18 <----- cycles per bitwhartung wrote:
On an older 6502, you can use X = 0 in place of the STZ, yes?
GARTHWILSON wrote:
other bits on the port will probably be in use for unrelated things, so STZ VIAPORT_IO should probably be replaced with DEC VIAPORT_IO to set Ck=0 without disturbing those other things.
- there's no problem if the other bits are inputs
- there's no problem if the other bits are outputs which remain low by default
- there's no problem if the other bits are outputs that have pullup resistors attached and are controlled by the DDR
Last edited by Dr Jefyll on Tue Jun 12, 2018 2:51 am, edited 2 times in total.
In 1988 my 65C02 got six new registers and 44 new full-speed instructions!
https://laughtonelectronics.com/Arcana/ ... mmary.html
https://laughtonelectronics.com/Arcana/ ... mmary.html
- GARTHWILSON
- Forum Moderator
- Posts: 8773
- Joined: 30 Aug 2002
- Location: Southern California
- Contact:
Re: Another 6522 SPI question
whartung wrote:
Well my complaint was [...] more of "if I want to write a 512 byte block, I need to read in 4K first, copy my block in, then erase it from flash, and write it back", meaning I need a 4K buffer (and arguably the original 512 byte block as well) to write the block.
4K just seems like..a lot, especially on a 64K (or less: 32K) machine since it's ostensibly empty 99% of the time. A large gaping hole Just In Case.
4K just seems like..a lot, especially on a 64K (or less: 32K) machine since it's ostensibly empty 99% of the time. A large gaping hole Just In Case.
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?
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
Re: Another 6522 SPI question
GARTHWILSON wrote:
The 25VF032 I mentioned lets you write as little as one byte at a time (if the 4K sector is already erased), but I think the write counts toward the wear-out the same as writing the whole sector. The 25VF064 (8MB, which I have not used) lets you write 256 bytes at a time, but not just a single byte. At Atmel SPI flash I used years ago gave the user access to its own buffers, so IIRC, you could read a 1K sector into its buffer, overwrite only a small part of that onboard buffer, and write it back.
- GARTHWILSON
- Forum Moderator
- Posts: 8773
- Joined: 30 Aug 2002
- Location: Southern California
- Contact:
Re: Another 6522 SPI question
Yes, that's what flash is all about; but with the Atmel part, at least you wouldn't have to set aside that much memory in your 6502 memory map. It actually had two buffers, so you could have the flash programming from one (which took a few milliseconds) while you're loading or reading the other.
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?
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
Re: Another 6522 SPI question
Dr Jefyll wrote:
Code: Select all
SPIBYTEIN: LDA #1 ;LDA #1 is for counting
INPUTLOOP: 4 STZ VIAPORT_IO ;set Ck=0, mosi=0
6 INC VIAPORT_IO ;set Ck=1 INC DOES 2 THINGS (sets Ck; also updates N flag per MISO)
2/3 BPL MISO_IS_0
2 SEC ;MISO is =1
2 ROL A
3 BCC INPUTLOOP ;more bits?
RTS
MISO_IS_0: 2 ASL A ;MISO is =0
3 BCC INPUTLOOP ;more bits?
RTS
19/18 <----- cycles per bitCode: Select all
SPIBYTEIN: LDA #$FE ; for counting, and as a nice supply of set bits
SEC
INPUTLOOP: 4 STZ VIAPORT_IO ; Ck=0, nextmosi=0, mosi=0
6 ROL VIAPORT_IO ; set Ck=1, shift MISO into carry
2 ROL A
3 BCS INPUTLOOP
Though I think for SD cards you're meant to be sending set bits - not clear bits - on MOSI when reading data. You could load #$06 into X or Y and use STX or STY instead of STZ.
Re: Another 6522 SPI question
xjmaas wrote:
Hi all,
I am trying to get SPI working on an interface card I am creating for my Apple ][ (actually an Apple IIgs). I am trying to use the implementation by André for his CS/A65, rev 1.1A. I had to re-create the PHI2 signal, as the Apple ][ bus doesn't include it, by using a 74HCT74 as per Apple's TIL #494 info.
I am trying to get SPI working on an interface card I am creating for my Apple ][ (actually an Apple IIgs). I am trying to use the implementation by André for his CS/A65, rev 1.1A. I had to re-create the PHI2 signal, as the Apple ][ bus doesn't include it, by using a 74HCT74 as per Apple's TIL #494 info.
In fact even the Commodore userport USB was using the VIA shift register and no bit banging.
IMHO bit banging is a waste of CPU cycles that can easily be avoided by using a shift register...
Author of the GeckOS multitasking operating system, the usb65 stack, designer of the Micro-PET and many more 6502 content: http://6502.org/users/andre/
Re: Another 6522 SPI question
I guess phi2 needs to be recreated not because it is not included ( it isn't but phi0 should work just as well) but because the leading edge needs to be delayed.
The VIA is a latching in the register select lines when phi2 goes high. Systems with shared busses typically have video during phi2 low, so when phi2 goes high the register select is not ready yet. The C64 has this problem and it seems the Apple II also.
The VIA is a latching in the register select lines when phi2 goes high. Systems with shared busses typically have video during phi2 low, so when phi2 goes high the register select is not ready yet. The C64 has this problem and it seems the Apple II also.
Author of the GeckOS multitasking operating system, the usb65 stack, designer of the Micro-PET and many more 6502 content: http://6502.org/users/andre/