Ziggurat29, You have to let me help you. I was just gearing up to do a .NET MF port myself. I have an CC3000EM and I was about to setup an Arduino and ...
Sure, why not?
My plans (up to this point) were:
* prove hardware interface (done)
* prove SPI communications (done, I believe)
* first make a managed code 'driver'
* then make a native code integration with the firmware
So, two 'products' come out, one managed, and one native. I want to do the managed version first because I believe it will be easier to experiment and debug in that context, and should cement my understanding of the part (the documentation is stunningly poor), and because I think it is a useful end in it's own right. Once I have a thorough understanding of the device, then for the firmware it's a separate exercise to plan the integration, ostensibly replacing lwip (or maybe they can coexist, but I need to get into netmf's networking code to see what that means, since you'd effectively be making a multihomed system).
... Can you post a zip of what you have so far? Being able to start with (at least) the basic SPI stuff working would be very helpful.
What I have right now, such as it is, is really exploratory code with no design to speak of, so it would be an embarrassment for me to post it. If you really need it, I can douche out my more spirited comments and send it to you PM or something, but really I can sum it up this way:
Electrical:
using NP2
D13 - sck
D12 - miso
D11 - mosi
D6 - /IRQ
D5 - PWREN
D4 - /CS
3.3v - pwr *
GND - no 'earth'ly idea
* this will have to change soon as I start doing radio stuff; too much load
I am manually managing /CS and monitoring /IRQ for now -- maybe forever. The SPI transactions often have to be done in two parts, and /IRQ is irksome in that it has mixed duty and doesn't seem useful to use it as an interrupt source, at least not so far, and anyway it gives me the feel of being level-sensitive and that's not supported on the NP2, but I'm not sure.
Software:
things:
SPI cc3000; //I spi something that begins with the letter 'cc'
OutputPort cs; //active low
OutputPort pwren; //active high
//InterruptPort irq; //interrupt; active low
InputPort irq; //YYY I'm going to poll this for now until I understand this device better
config:
//make our spi (mode 1)
cc3000 = new SPI(new SPI.Configuration(
Pins.GPIO_NONE, // SS-pin (we will manually do it)
false, // SS-pin active state (low)
0, // The setup time for the SS port YYY 50 uSec
0, // The hold time for the SS port
false, // The idle state of the clock (low)
false, // The sampling clock edge (trailing)
1000, // The SPI clock rate in KHz
SPI_Devices.SPI1)); // The used SPI bus (refers to a MOSI MISO and SCLK pinset)
//make our (manually controlled) cs (active low)
cs = new OutputPort(Pins.GPIO_PIN_D4, true);
//make our power control (active high)
pwren = new OutputPort(Pins.GPIO_PIN_D5, false);
//make our interrupt input (active low) //XXX holding off on this until I understand the device better
//irq = new InterruptPort(Pins.GPIO_PIN_D6, false, Port.ResistorMode.Disabled, Port.InterruptMode.InterruptEdgeLow);
irq = new InputPort(Pins.GPIO_PIN_D6, false, Port.ResistorMode.Disabled);
//power up
pwren.Write(true);
the spi clock speed was chosen semi arbitrarily, to make debugging with the scope easier. Side note: specifying 1000 KHz actually gave me a clock of 640 KHz. I measured. Maybe a Gates reference joke -- 'who will ever need more than 640K'? anyway....
action:
The SPI transactions are mostly normal. 'Mostly', because:
* the first one only after powerup requires a 50usec pause after the 4th byte before continuing. seems like a workaround for device bug. I do this by two sequential WriteRead operations. netmf is slow enough that you don't have to use any delay code, and you get about 84 us delay. happily there doesn't appear to be a max delay.
* the reads involve retrieving a length of the variably sized payload that follows, so you need to do those transactions in two phases also.
goofy first write (also this required to be a 'link start' command):
//wait for the signal that its ready
//XXX III support a timeout
while (irq.Read()){}
begin(); //assert cs and (redundantly) wait for irq
//delay(50usec);
//goofy first write has a little pause after the first busy bit before moving on with the rest
cc3000.WriteRead(pktLinkStart, 0, 4, null, 0, 0, 0);
//delay(50usec);
//and then the rest of it
cc3000.WriteRead(pktLinkStart, 4, 6, null, 0, 0, 0);
end(); //negate cs
reading is a little interesting in that you must retrieve the length, and then complete the reading:
//wait for the signal that its ready
//XXX III support a timeout
while (irq.Read()) { }
begin(); //assert cs and (redundantly) wait for irq
//write header and read the length bytes
cc3000.WriteRead(pktReadHeader, 0, 5, pktReadPayloadLen, 0, 2, 3);
//make length into a number; header is big endian. other things are little.
int nPayloadLen = ( pktReadPayloadLen[0] << 8 ) | pktReadPayloadLen[1];
if (0 != nPayloadLen)
{
byte[] pktBogoWrite = new byte[1]; //dummy
//read payload
//XXX sanity check on length
byte[] pktReadPayload = new byte[nPayloadLen];
cc3000.WriteRead(pktBogoWrite, 0, 1, pktReadPayload, 0, nPayloadLen, 0);
//XXX III 'spatchy
}
end(); //negate cs
OK looks like I did wind up posting most of what I did so far, haha!
Some things:
* a healthy level of distrust of the documentation is worthwhile. For instance, they contradict themselves in what is the spi mode to use. It is spi mode 1.
* you can tell that different engineering teams worked on this, not necessarily in concert for whatever reason. For instance, some values are big endian, and others are little endian, so watch for that.
* the 5 byte header I would probably re-phrase as:
* unsigned char byDir; //1 = write, 3 = read; from the spi master perspective
* unsigned short sWriteLen; //little-endian; when op=1, master indicates payload length; otherwise zero
* unsigned short wReadLen; //little-endian; when op=3, slave indicates payload length; otherwise zero
I think this covers most of the SPI; I still need to get a handle on whether there is more /IRQ consideration since the doc claims it serves some double duty, and that there is collision resolution to be performed.
Beyond that, I planned to do some reading in the light of my newfound knowledge, before I do much more coding. There's something called 'patches' which are not really clear to me if I care about, and they use the term 'event' which I think really means 'return value' and 'asynchronous notification'.
On the plus side, it looks like the part is what I would describe as:
* SPI-based RPC mechanism to Berkeley sockets, with some added stuff as needed (e.g. setting mac, wifi keys, etc).
So I think it should be straightforward to implement an API even on the managed side that very closely resembles the existing network api, and possibly on the native side to mesh with what exists there as well. Hope springs eternal!