Netduino home hardware projects downloads community

Jump to content


The Netduino forums have been replaced by new forums at community.wildernesslabs.co. This site has been preserved for archival purposes only and the ability to make new accounts or posts has been turned off.
Photo

Interfacing Gameduino to Netduino - SPI trouble


  • Please log in to reply
13 replies to this topic

#1 kerry_h

kerry_h

    New Member

  • Members
  • Pip
  • 1 posts

Posted 25 June 2011 - 09:33 PM

Hi,

I'm trying to hook my Gameduino up to a Netduino Plus. The Gameduino talks over SPI and is thought to be .NETMF-compatible, though this hasn't been verified yet. I am able to construct a SPI interface to the Gameduino but the hard-coded ID register is reading incorrectly. If you're familiar with SPI on Netduino, could you help me figure out where the problem is?

According to the technical reference and samples, The Gameduino expects pin 9 to be the chip select and pins 11, 12, 13 to be SPI MOSI/MISO/SCK respectively. It operates in SPI data mode 0 (clock signal low when idle, data sampled on rising edge) and the chip select is active low. Most samples run the clock at half system clock speed which works out to 8 MHz on a standard 16MHz Arduino. Multi-byte data is read and written MSB first. No specs indicate a requirement for setup time or hold time. This is how the SPI.Configuration looks:

// Chip select port:  Pin 9
// Chip select active state:  false (chip select pin is active low)
// Chip select setup time:  0 ms 
// Chip select hold time:  0 ms 
// Clock idle state:  false, clock is low when idle 
// Clock edge:  true, data is sampled on clock rising edge
// Clock rate KHz:  System clock / 8 (approximately 6 MHz, close to safe max of 8 MHz)
// SPI module:  SPI1

SPI.Configuration GameduinoInterfaceConfig = new SPI.Configuration(Pins.GPIO_PIN_D9, false, 0, 0, false, true, (Cpu.SystemClock / 1024) / 8, SPI_Devices.SPI1); 

Next, I try to read a hard-coded read-only identifier from the Gameduino’s address 0x2800. The protocol for reading from the Gameduino is: write the two-byte target address to SPI, most-significant byte first. Then read a byte from SPI to get the contents of that address.

byte[] addressBuffer = new byte[2];
byte[] oneByteReadBuffer = new byte[1];
byte[] oneByteWriteBuffer = new byte[1];
oneByteWriteBuffer[0] = 0;

addressBuffer[0] = 0x28;
addressBuffer[1] = 0x00;
GameduinoInterface.Write(addressBuffer);
GameduinoInterface.WriteRead(oneByteWriteBuffer, oneByteReadBuffer);

The read operation produces a seemingly random number that changes from run to run. The expected value is 0x6D (109 decimal).

A few additional notes:

  • It appears there is no way to read from the SPI bus without also writing to it. The write should be inconsequential in this case, though, because the Gameduino only performs writes if the most significant bit of the address is set to 1. Also, the target memory location is read-only.
  • The Gameduino samples explicitly set the chip select pin before and after read operations. There’s no way to set the select pin explicitly in NETMF’s SPI class, so I’m guessing the Write and WriteRead methods take care of this.
  • Some Gameduino samples contain a line of code: SPSR = (1 << SPI2X). This sets a bit in the SPI status register which doubles the clock speed from what was originally specified. I don’t see an equivalent status register exposed in the .NETMF SPI class, but I’ve tried a variety of different clock speeds in the SPI.Configuration with no success.

Does anyone see what might be wrong here, or have ideas of other things to try?

Thanks,
-- K

#2 Mario Vernari

Mario Vernari

    Advanced Member

  • Members
  • PipPipPip
  • 1768 posts
  • LocationVenezia, Italia

Posted 26 June 2011 - 04:22 AM

Hi Kerry and welcome in the forum!

I didn't know Gameduino and it looks interesting indeed.
Just to be sure, the clock constant has the right value?...I don't know how much is the SystemClock value. In case of doubt, use 6000.

About your questions...
Gameduino doesn't specify so much about the characteristics of its SPI. No indication about the clock edge, no about the bit order, etc. That's could be an issue.

You can't perform a read without a write, because you can't perform a write without a read also. The SPI exchanges bits from master and slave, so read and write is the same task. About the SPI APIs, I don't think that could be a big problem. Maybe the only tedious thing is that you must create an instance of a buffer uselessly.

The chip select (aka SSEL as Slave SELect) is totally managed by the Netduino hardware. I guess your problem could be right here.
The Arduino sample manage the chip select manually. It is tied low, then the R/W performed, then finally tied high back.
Netduino manages the SSEL automatically and can't know WHEN the message is finished. Netduino consider that you call the "Write" method feeding a buffer of N bytes, and *that* is the message. The SSEL is tied low at the beginning, then pulled high back after the last byte.
I think you should change the code such as follows:

byte[] outputBuffer = new byte[] { 0x28, 0x00, 0x00 };
byte[] inputBuffer = new byte[3];
GameduinoInterface.WriteRead(outputBuffer, inputBuffer);
That should work.
Cheers
Biggest fault of Netduino? It runs by electricity.

#3 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 26 June 2011 - 05:28 PM

Hi Kerry, We're making tweaks to the SPI code right now, so if there's something related to the Gameduino shield that you need...just let me know! Chris

#4 sweetlilmre

sweetlilmre

    Advanced Member

  • Members
  • PipPipPip
  • 62 posts

Posted 26 June 2011 - 07:47 PM

Hi,

Firstly to kerry_h:

You need to independently handle chip select with an OutputPort on Pin9 and make sure that your SPI config does not specify ChipSelect (see my setup code below).
Your code example should look something like:

ChipSelect = new OutputPort( Pins.GPIO_PIN_D9, true );

byte[] addressBuffer = new byte[2];
byte[] oneByteReadBuffer = new byte[1];
byte[] oneByteWriteBuffer = new byte[1];
oneByteWriteBuffer[0] = 0;

ChipSelect.Write( false );
addressBuffer[0] = 0x28;
addressBuffer[1] = 0x00;
mySPI.Write(addressBuffer);
mySPI.WriteRead(oneByteWriteBuffer, oneByteReadBuffer);
ChipSelect.Write( true );

Secondly to Mario Vernari:

The SPI setup for the GameDuino is specified as SPI Mode Zero i.e. CPOL = 0 and CPHA = 0
edit:
  SPI.setClockDivider(SPI_CLOCK_DIV2);
  SPI.setBitOrder(MSBFIRST);
  SPI.setDataMode(SPI_MODE0);

Thirdly:

I've ported the GD library to the NetDuino and got the Ball demo working.
This was a direct C++ -> C# port and very messy but it works.

However performance is abysmal, which is not surprising considering that the Ball demo makes 45 * 2 SPI writes for the sprites and 256 SPI writes for the palette shift.
This in turn results in 346 interop calls...

To increase performance I built an SPIBuffer class that buffers the 90 sprite writes and 256 palette writes and only makes 2 SPI calls per frame.
Performance increased significantly but still results in only about 5 FPS (pure guess work).

The SPI interface is supposed to run at 8Mhz stable for the GameDuino (1/2 Arduino clock).
The RAM size of the GameDuino is 32KB.
Calculating the transfer rate: 8Mhz = 8 000Khz = 8 000 000Hz = 8 000 000 bits per second = 1 000 000 bytes per second = 975KB/s

At the above rate I should be able to write the entire RAM at about 30 times a second.
I do not achieve anything remotely near this even with a significantly smaller write size.

Even taking .NET runtime and interop overhead into account this seems really strange.
Is there an issue with SPI transfer rate that I am not aware of?


My setup code is:

  	bool chipSelect_ActiveState = false;
  	bool clock_IdleState = false;
  	bool clock_Edge = true;
  	uint clockKHz = 8000;

  	SPI.Configuration config = new SPI.Configuration( Pins.GPIO_NONE, chipSelect_ActiveState, 0, 0, clock_IdleState, clock_Edge, clockKHz,
                       									SPI.SPI_module.SPI1 );

I use a separate OutputPort on PIN9 for chip select.

If I can get this working I will publish the library.
-(e)

#5 Mario Vernari

Mario Vernari

    Advanced Member

  • Members
  • PipPipPip
  • 1768 posts
  • LocationVenezia, Italia

Posted 27 June 2011 - 11:39 AM

@sweetlilmre: I don't think there's need to implement the chip-select manually. The SPI manages an output automatically without any problem and the result is much faster than the manual solution. Try yourself and maybe your ball game will run at a satisfying speed. Cheers
Biggest fault of Netduino? It runs by electricity.

#6 sweetlilmre

sweetlilmre

    Advanced Member

  • Members
  • PipPipPip
  • 62 posts

Posted 28 June 2011 - 05:02 AM

@sweetlilmre:
I don't think there's need to implement the chip-select manually. The SPI manages an output automatically without any problem and the result is much faster than the manual solution.

Try yourself and maybe your ball game will run at a satisfying speed.
Cheers


Hi

In my code there are only 2 SPI writes per frame so the independent chip select doesn't make any difference.
I rewrote the code as a test to flush the entire 32KB of data per frame with SPI handling the select.
This also made no difference.

I'll try some more options, but it seems the NetDuino running C# is just not fast enough to handle this :(
-(e)

#7 Mario Vernari

Mario Vernari

    Advanced Member

  • Members
  • PipPipPip
  • 1768 posts
  • LocationVenezia, Italia

Posted 28 June 2011 - 05:20 AM

That's really strange, because I've checked a deep difference in performance.
Writing a single frame byte-by-byte is hugely slow than writing a buffer all at once.
The actual byte-rate is around 2-3 KBytes/s: very slow.

Moreover, by adding a little help to the circuit, you may reach very high byte-rates, close to the theoretical SPI speed (around 200 KBytes/s).
Check my fresh post about the SPI perf.

Cheers

PS: after writing that post, I have done some other test and it seems that the speed could be improved enough.
Biggest fault of Netduino? It runs by electricity.

#8 sweetlilmre

sweetlilmre

    Advanced Member

  • Members
  • PipPipPip
  • 62 posts

Posted 28 June 2011 - 10:14 AM

That's really strange, because I've checked a deep difference in performance.
Writing a single frame byte-by-byte is hugely slow than writing a buffer all at once.
The actual byte-rate is around 2-3 KBytes/s: very slow.

Moreover, by adding a little help to the circuit, you may reach very high byte-rates, close to the theoretical SPI speed (around 200 KBytes/s).
Check my fresh post about the SPI perf.

Cheers

PS: after writing that post, I have done some other test and it seems that the speed could be improved enough.


Hi,

I read your post (great article btw!) and I agree... what I am seeing is waay to slow. Thanks for the upper metric of 200 KBps, that gives me something to work with.
I will try some more options and see if I can improve performance.

This is really frustrating... a GameDuino programmed with a C# backend would just be awesome.

I have some other avenues to explore with eLua that I am going to have a look at and see if there is any relative performance difference as well.
-(e)

#9 Nobby

Nobby

    Advanced Member

  • Members
  • PipPipPip
  • 70 posts

Posted 14 October 2011 - 01:54 AM

Hey guys, I'm extremely new to this wonder of stackable development boards. I've done 8bit AVR and .Net development for about ten years and stumbled across this stuff last week. I just unpacked a Netduino and a Gameduino. Obviously one is C# and programmed via VS, the other C++ and libraries used with the Arduino suite. I'm looking at writing creating a managed C++ wrapper library but starting with a really simple interface. I'd like to support: -Initialising the device -Set pixel (x,y) to ARGB1555 value Doesn't need to be high performance, no sprites or background scrolling. From what i've seen in this thread, everything is done via SPI. Is an address table used to write various configuration values or even to just write pixel colours? Any tips would be great thanks :o) --edit I can't get the whole thing up and running. The gameduino doesn't exactly sit properly onto the netduino due to the DC supply socket. The whole time I was firing the system up, the screen had a band of fine vertical lines, all different colours. If I pushed the board in a bit harder, the system would start up with a black screen. A few posts debate the correct way to control the SPI. I've tried to use my own selection pin control, writing the address by itself then data or read. I tried to read address 0x2800 and had the number 0xDA returned instead of 0x6D. In fact, 0xDA is 0x6D left shifted by one bit. The same thing happened when I tried to write an 'A' to the screen from the example by writing to address 0x0000 with 0x41 as the data. When I read that memory area, i get 0x82 which is 0x41 left shifted by one bit. Is my gameduino partially faulty or am I missing something?

#10 Nobby

Nobby

    Advanced Member

  • Members
  • PipPipPip
  • 70 posts

Posted 15 October 2011 - 03:28 AM

So I've done a bit of reading and experimenting. I wrote a simple class that manages SPI comms to a Gameduino. The class has a single public method at the moment which is GetIDCode(). The constructor of the class allows you to choose: -Manual chip select or SPOT.Hardware.SPI chip select -Sending the address in a write then calling WriteRead to get the IDCode back VS a single WriteRead operation -The SPI operating frequency After much testing, I couldn't conclude anything about different methods except that they don't make a difference in the result. Except for the SPI frequency. It MUST be 8MHz. I was running at 6MHz as someone else in this thread was using CpuClock/(1024*8) which works out to be 6MHz. Since I'm getting 0x6D every time, I'll move onto more basics with a managed lib and see how it goes.

#11 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 15 October 2011 - 03:44 AM

Hi Nobby, Thanks for the updates! Chris

#12 Mario Vernari

Mario Vernari

    Advanced Member

  • Members
  • PipPipPip
  • 1768 posts
  • LocationVenezia, Italia

Posted 15 October 2011 - 04:05 AM

Hello Nobby.

According to the Gameduino specs, the SPI clock can run up to 8MHz. It can be even slower (and I'd prefer), so 6MHz should be okay.
Anyway, just for beginning I'd try to get even lower, let's say 1MHz.

Second point: is the SPI configured correctly?
Always basing on the specs, the SPI must work at "mode 0". And "Mode 0" means both CPOL and CPHA equal to zero.
Finally, if you check here, you can get the equivalent parameters to use in the SPI configuration structure.

It means that the init code should look as the follows:
SPI.Configuration xSPIConfig;
            SPI xspi;
            xSPIConfig = new SPI.Configuration(Pins.GPIO_PIN_D9,   //Chip Select pin
                                                false,              //Chip Select Active State is LOW
                                                0,                  //Chip Select Setup Time
                                                0,                  //Chip Select Hold Time
                                                false,              //Clock Idle State = CPOL
                                                false,              //Clock Edge = CPOL XOR CPHA
                                                1000,               //Clock Rate (kHz)
                                                SPI.SPI_module.SPI1);//SPI Module
            xspi = new SPI(xSPIConfig);
(part of the code was "stolen" from the Wiki).

Be sure to keep the wiring shorter enough (max 10-15cm).
At this point, you should be able to light your first pixel!
Cheers

PS: I'm really intrigued about this shield. I'd love seeing how it works, so I'll keep in touch.
Biggest fault of Netduino? It runs by electricity.

#13 RichardE

RichardE

    Member

  • Members
  • PipPip
  • 13 posts
  • LocationNorth Yorkshire, UK

Posted 03 November 2011 - 09:57 PM

I've been playing around with a Gameduino attached to a Netduino and have had some success. If anyone is interested, see the attached files. There are three programs : 1. Character set editor and screen designer This is a Windows forms program which you can run on a PC (you will need .NET 4 installed) and allows you to design your own character sets and screen layouts and then export them as C++ source code (for Arduino) or C# (for Netduino). A bit ropey. No source code. If anyone gets stuck let me know. 2. Netduino program that plays a tune in a separate thread using 3 voices Full Visual Studio 2010 solution. 3. Netduino program that moves some sprites around Full Visual Studio 2010 solution. Funny glitch at the top left of the screen which I haven't sorted yet. Anyone who has played with an Arduino will recognise the sprites. The key to the Netduino examples is the Arduino class. Instantiate one of these as shown in the Program.cs files and then use its methods. Note that these examples are very slow. For reasons discussed above the SPI link is much slower than it would be on an Arduino. Would be much quicker using C++ and without .NET, but it works. Hope this is of some use and thanks for the help given above which was very useful in getting this to work.

Attached Files



#14 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 04 November 2011 - 01:42 AM

Hi RichardE, Very cool. Thanks for sharing your progress and code! Chris




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users

home    hardware    projects    downloads    community    where to buy    contact Copyright © 2016 Wilderness Labs Inc.  |  Legal   |   CC BY-SA
This webpage is licensed under a Creative Commons Attribution-ShareAlike License.