GARTHWILSON wrote:
That's what I²C does. With the fact that start and stop conditions are produced by bringing the data line down or up (respectively) while the clock line is high, it can do away with the select lines too. The data line is bidirectional, leaving you with only two wires plus power and ground. I think it's best to leave the I²C interface separate though.
The data line, being bidirectional, means that it's not what SPI does, since it assumes the MISO line is always driven. What I was saying was to deliberately break the standard just enough to permit single-select-line operation.
Quote:
Another way that comes to mind to handle the addressing with only one wire is that the one select line carries a number of pulses corresponding to the address you want to select. The devices' counters get reset anytime the select line is false and there's a pulse on the clock line. This again requires additional parts in front of every device though. Although I think the idea is interesting, I don't expect it to necessarily be taken seriously. It could be arranged for autoaddressing, but otherwise each device would need to be told its address, like IEEE-488 address DIP switches.
I think it'd be easier to have a rule: if /SEL is asserted, then MOSI is shifted into an address register. If /SEL is negated, then it is shifted into the currently selected device. This is simpler, and I think would use less logic.
Quote:
Here's the senario: You have something like a flash memory which requires a long stream of data to load a 2KB page. If you interrupt the page by
...
This just smacks of how Commodore did things; see, each device, particularly disk drives, had their own operating system and device drivers on board. The application on the Commodore CPU would issue amazingly high-level commands to the devices as appropriate. For example, to format a disk:
OPEN 1,8,15,"N0:MY DISK NAME":CLOSE 1
The fact that you're addressing subaddress 15 on the disk drive (unit
was all that was necessary for the DOS resident on the drive to know that you're issuing a command. In fact, it doesn't matter if it's specified as a filename or as normal data, leaving the ability to send multiple commands:
OPEN 1,8,15
REM FIRST, FORMAT THE NEW DISK.
PRINT #1,"N0:MY DISK NAME"
REM NOW, COPY THE DATA OVER FROM THE MASTER DISK.
GOSUB 1000:REM WAIT FOR DISK TO FINISH
PRINT #1,"C0:MY FILE=1:YOUR FILE"
CLOSE 1
Notice also a bit of pipelining here; after sending the command to the disk, the CPU is free to do whatever else it needs to do in the mean time, thus making certain kinds of programs MUCH faster than their DOS, Windows, or, hell, even Linux equivalents.
Quote:
I did get it going for a product we did not go through with, so I could look through my code if it's really important. It is only a 2MB flash though, which is not worth using for new designs considering its cost and the fact that it is so few megabytes compared to what's available today. SPI has modes 0, 1, 2, and 3. Some devices can figure out for themselves which mode (at least out of two) you're using. IIRC, mode 0 is most common. Keep reading though.
This isn't what I was talking about.
Look again at the data sheet. You'll notice two sets of timing diagrams: one where there is one extra bit inserted between when data is sent to when it is received, and one where there
isn't. This has nothing to do with SPI mode, so far as I am aware, as they use the same phase and polarity for the clock in both diagrams. Look in particular on diagrams on pages 13 and 14.
But Andre already answered by question; although the clock and phase are identical for the actual transfer of data, the *initial* state of CLK is what determines which, which to me, is utterly stupid.
But I digress.
Quote:
Although it would be kind of nice to have the OS be able to handle all the humdrum serial bus communications details, the bit-banging will leave total freedom to run any mode a device wants.
You can still have a nice OS-level API for the serial bus. All you need is to remember a bit of state when addressing a device:
Code:
;
; Address the device to receive our special, important message.
;
LDA #spi_mode ; 0, 1, 2, or 3
LDX #device_id ; 0 .. 6
JSR SPI_beginTransaction
;
; Send the message, and at the same time, receive the data it
; sends back.
;
LDA #'H'
JSR SPI_exchangeByte
STA result
LDA #'I'
JSR SPI_exchangeByte
STA result+1
;
; Release any select lines on the bus; we're done.
;
JSR SPI_endTransaction
Of course, Kestrel's firmware will have a bit more sophistication than this for various reasons I'll explain in my book. But this is the core essence, the absolute minimum interface. Heck, even SPI_endTransaction can be implemented as:
Code:
.export SPI_endTransaction
.proc SPI_endTransaction
ldx #7
jmp SPI_beginTransaction
.endproc
I of course don't recommend having applications depend on a "magic address" to de-select all devices on the bus, since that magic address can change and, necessarily, is hardware dependent. Consider a system with two, or more, SPI port interfaces (not strictly necessary of course, but this is a
what if scenario). And, besides, it's more self-documenting that way too.