Update the Spi library from the playground

Hello,

Lately I've started using the Spi library from the Arduino Playground to communicate between two arduino's using two nRF24L01+ transceiver modules.

http://www.arduino.cc/playground/Code/Spi

Because this library uses the Spi library I've downloaded it and started working with it. I interface between an Arduino Mega and an Arduino Duemilanove. I had a lot of problems at the start, this because both the boards use different digital pins for the SCK, MISO, MOSI and SS configuration.

Duemilanove:
pin 13 SCK SPI clock
pin 12 MISO SPI master in, slave out
pin 11 MOSI SPI master out, slave in
pin 10 SS SPI slave select

Mega:
pin 52 SCK SPI clock
pin 50 MISO SPI master in, slave out
pin 51 MOSI SPI master out, slave in
pin 53 SS SPI slave select

The Spi library uses the following pin configuration:
pin 13 SCK SPI clock
pin 12 MISO SPI master in, slave out
pin 11 MOSI SPI master out, slave in
pin 10 SS SPI slave select

Now I needs to change the pins in the Spi.h file before I upload the sketch to the Mega or Duamilanove board.....

Maybe it's better to be able to config the pins in the setup of the arduino board. In this way you'll have much more flexibility :slight_smile:

For example:

void setup(){
Spi.MISO(12); // This will config pin 12 as MISO
}

Or maybe be able to select a board when the library is inserted.

#include <Spi.h>

void setup(){
Spi(mega);
}

(I don't know if this is possible, my library programming skills are bad....)

The problem is I don't have the skills to update/modify this library and I don't know how updating normally works? Can users just update and upload it or do they need to have permission from the author of this library

Any users who know how to do this or have better suggestions?

Thanks in advance,

/me

Hello,

I've did a small modification on the library. I changed the name to SpiM.H and SpiM.cpp, but this is just temporarily for debugging purposes. All the changes are marked using this tag:

// Added to the original library

SpiM.h

#ifndef SpiM_h
#define SpiM_h

#include "WProgram.h"

#define SCK_PIN   13
#define MISO_PIN  12
#define MOSI_PIN  11
#define SS_PIN    10

class SPI
{
  public:
    SPI(void);
    void mode(byte);
      void SCK(int); // Added to the original library
      void MISO(int); // Added to the original library
      void MOSI(int); // Added to the original library
      void SS(int); // Added to the original library
    byte transfer(byte);
    byte transfer(byte, byte);
};

extern SPI Spi;

#endif

Please note, all the copyright stuff is left out in this example.

SpiM.cpp This is the actual modified part

#include "WProgram.h"
#include "SpiM.h"

//---------- constructor ----------------------------------------------------

SPI::SPI()
{
  // initialize the SPI pins
  pinMode(SCK_PIN, OUTPUT);
  pinMode(MOSI_PIN, OUTPUT);
  pinMode(MISO_PIN, INPUT);
  pinMode(SS_PIN, OUTPUT);

  // enable SPI Master, MSB, SPI mode 0, FOSC/4
  mode(0);
}

void SPI::SCK(int SCK_PIN_CHANGED) // Added to the original library
{
  // Change the SCK pin
  pinMode(SCK_PIN_CHANGED, OUTPUT);
}

void SPI::MOSI(int MOSI_PIN_CHANGED) // Added to the original library
{
  // Change the MOSI pin
  pinMode(MOSI_PIN_CHANGED, OUTPUT);
}

void SPI::MISO(int MISO_PIN_CHANGED) // Added to the original library
{
  // Change the MISO pin
  pinMode(MISO_PIN_CHANGED, OUTPUT);
}

void SPI::SS(int SS_PIN_CHANGED) // Added to the original library
{
  // Change the SS pin
  pinMode(SS_PIN_CHANGED, OUTPUT);
}

//------------------ mode ---------------------------------------------------

void SPI::mode(byte config)
{
  byte tmp;

  // enable SPI master with configuration byte specified
  SPCR = 0;
  SPCR = (config & 0x7F) | (1<<SPE) | (1<<MSTR);
  tmp = SPSR;
  tmp = SPDR;
}

//------------------ transfer -----------------------------------------------

byte SPI::transfer(byte value)
{
  SPDR = value;
  while (!(SPSR & (1<<SPIF))) ;
  return SPDR;
}

byte SPI::transfer(byte value, byte period)
{
  SPDR = value;
  if (period > 0) delayMicroseconds(period);
  while (!(SPSR & (1<<SPIF))) ;
  return SPDR;
}


//---------- preinstantiate SPI object --------------------------------------

SPI Spi = SPI();

Please note, all the copyright stuff is left out in this example.

The arduino sketch would become:

Arduino sketch example

#include <SpiM.h>

void setup(){
SpiM.SCK(52);
SpiM.MOSI(51);
SpiM.MISO(50);
SpiM.SS(51);
}

void loop(){
// code
}

This is just an attempt to modify the library, I would like to know from the code experts if this is the good way to go ( and if it actually works..)?

Thanks in advance,

/me :slight_smile:

Based on some suggestions by Alexander (Immetic) the following changes to the header file will also do:

#if defined(__AVR_ATmega1280__)
  #define SCK_PIN   52
  #define MISO_PIN  50
  #define MOSI_PIN  51
  #define SS_PIN    53
#else  
  #define SCK_PIN   13
  #define MISO_PIN  12
  #define MOSI_PIN  11
  #define SS_PIN    10
#endif

Do all board except the Mega board use:

SCK_PIN 13
MISO_PIN 12
MOSI_PIN 11
SS_PIN 10

as Spi pins?

Cheers,

/me

Please your suggestions?

I think they do :slight_smile:

The pins for the ATMega328 is fixed. There is no point in exposing them to the user via a header file.

I suggest adding those internals to the source instead, else you end getting people changing the pins and wondering for ages why things do not work (like I did for ArduinoISP).

Also, I dont really see the point of adding pins, as the SPI library should be using the SPI registers directly, which in the case of the 328, is just those mentioned, but IMO they should not be used directly, else you would be doing software SPI and not using the hardware SPI.

Correct me if I am wrong.

Sounds like a good idea to me.
The only reason for exposing the pins would be so that you know where to plug things in!

If the source is suitably #if'd, that eliminates the problem for everybody and allows future changes for things like ATMega1284Ps.

The only reason for exposing the pins would be so that you know where to plug things in!

That's why it should be in documentation or code comments. :slight_smile:

I do see however the library uses the Arduino mapped pins to enable output on those pins. Whether that is needed (and I suspect not all pins require that), is another story.

I'll be trying to implement spi with two shaft encoder peripherals (LS7366R) for a two-axis drive system. To that end, and for other uses as well, I'll need two different SS pins. The peripherals are three-stated on the MISO line, dependent on the SS. So it would be better to be able to call the SS pin at the time of the spi function call. Otherwise, I guess it'll be fiddling around with some kind of self-developed subroutines...
Don