SPI.setClock()

186 views
Skip to first unread message

Paul Stoffregen

unread,
Dec 21, 2013, 10:44:10 AM12/21/13
to devel...@arduino.cc
Another hardware independent API I'm hoping to see is SPI.setClock().

Currently, sketches and libraries using SPI use setClockDivider(). On
Arduino Due, a small integer 1-255 is required. On AVR, 7 symbolic
constants are defined, where 4 is actually the fastest, 3 the slowest.
The method is different on different architectures. It depends on
knowledge of the clock speed, with nearly all AVR assuming it's fixed at
16 MHz.

SPI.setClock(bitrate) would take an unsigned 32 bit number for the
desired clock speed. The library would configure the SPI to the closest
speed that does not exceed the user's request (which matches the way SPI
chips are specified, with maximum clock speeds). All hardware details,
including knowledge of the board's main clock speed, would be handled by
the library.

Both setClockDivider() and setClock() would probably need to be
published for some time, while people transition.

Tom Igoe

unread,
Dec 21, 2013, 10:50:42 AM12/21/13
to Paul Stoffregen, Arduino Developers
I like the sound of that, Paul. Makes things much clearer, to me.

t.
> --
> You received this message because you are subscribed to the Google Groups "Developers" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@arduino.cc.

Rob Tillaart

unread,
Dec 21, 2013, 10:57:05 AM12/21/13
to Tom Igoe, Paul Stoffregen, Arduino Developers
Probably same for I2C (aka wire)

Kristian Sloth Lauszus

unread,
Dec 21, 2013, 10:58:10 AM12/21/13
to devel...@arduino.cc, Paul Stoffregen
I like this as well. Also I think it would be nice if the Wire/I2C library had this future as well.
> To unsubscribe from this group and stop receiving emails from it, send an email to developers+unsubscribe@arduino.cc.

Rob Tillaart

unread,
Dec 21, 2013, 11:12:59 AM12/21/13
to Kristian Sloth Lauszus, Arduino Developers, Paul Stoffregen
int setClock(int freq) // freq in KHz
{
  int prev = TWBR;
  if (freq > 0)  TWBR = F_CPU/(freq*1000) -16 + 2;  // something like that 
  return prev;
}

a -1 or 0 would allow it to act as getClock()

this would allow me to do 

prev = setClock(800); // high speed modus
lcd.print("hello");
setClock(prev); // back to normal modus

better alternative is of course is to add a real getClock(); function.




To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@arduino.cc.

Kristian Sloth Lauszus

unread,
Dec 21, 2013, 12:27:05 PM12/21/13
to devel...@arduino.cc, Kristian Sloth Lauszus, Paul Stoffregen
The problem with that is if people want to use a clock frequency below 30kHz (when running at 16MHz), then TWBR will get above 255.
We could fix this by setting the prescalers depending on the frequency.

Regards
Lauszus
To unsubscribe from this group and stop receiving emails from it, send an email to developers+unsubscribe@arduino.cc.

Rob Tillaart

unread,
Dec 21, 2013, 12:43:49 PM12/21/13
to Kristian Sloth Lauszus, Arduino Developers, Paul Stoffregen
Why / when would people use a frequency lower than 30KHz?  
very long cables?


To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@arduino.cc.

Kristian Sloth Lauszus

unread,
Dec 21, 2013, 1:51:07 PM12/21/13
to devel...@arduino.cc, Kristian Sloth Lauszus, Paul Stoffregen
I have actually used a frequency of 11.4kHz, as this is used by the Mindstorms Ultrasonic sensor: https://github.com/TKJElectronics/NXTShield/blob/master/NXTShield.cpp#L23-L37, but I have never used it anywhere else ;)

I have no idea why LEGO decided to use that frequency, but it does not work it you use a higher frequency than that.

Regards
Lauszus
To unsubscribe from this group and stop receiving emails from it, send an email to developers+unsubscribe@arduino.cc.

Rob Tillaart

unread,
Dec 21, 2013, 2:28:27 PM12/21/13
to Kristian Sloth Lauszus, Arduino Developers, Paul Stoffregen
>  I have no idea why LEGO decided to use that frequency, 
Customer lock in? :) 


To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@arduino.cc.

Paul Stoffregen

unread,
Dec 21, 2013, 3:19:48 PM12/21/13
to Rob Tillaart, Kristian Sloth Lauszus, Arduino Developers
On 12/21/2013 08:12 AM, Rob Tillaart wrote:
int setClock(int freq) // freq in KHz

I believe it's best to use Hz.  Arduino has a strong API tradition of Hz with Serial.begin().  Consistent units across similar APIs are easier to learn and use.

Maybe you're concerned about using 32 bits when 16 would be only half the size?  In terms of implementation, these functions are almost always called with compile-time constants.  An inline function can provide a nice 32 bit API and convert to the native representation with zero bits of overhead for the const input.

Rob Giseburt

unread,
Dec 21, 2013, 3:58:00 PM12/21/13
to Kristian Sloth Lauszus, devel...@arduino.cc, Paul Stoffregen, Kristian Sloth Lauszus
I know that code being ignorant of the architecture isn't as big of a goal with the Arduino as it is with Motate, but I have been trying to make Motate so that the code (that's using Motate) doesn't have to "know" what frequency it's running at unless absolutely necessary. I believe that is what Paul was getting at here.

I am just now writing the SPI library for Motate, and set the frequency/baud directly (in Hz) instead of as a divider or as a constant.

To help the code further isolate from knowledge of what frequency it's running, I have an (incomplete as of right now) getFrequency(), as well as setFrequency() returning the frequency it actually set to. This allows the code to fail or adjust based on hardware constraints without having to know them directly.

-Rob

Sent from Mailbox for iPhone


To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@arduino.cc.

--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@arduino.cc.

Matthijs Kooijman

unread,
Dec 22, 2013, 4:21:50 AM12/22/13
to Rob Tillaart, Kristian Sloth Lauszus, Arduino Developers, Paul Stoffregen
Hey Rob,

On Sat, Dec 21, 2013 at 05:12:59PM +0100, Rob Tillaart wrote:
> int setClock(int freq) // freq in KHz
> {
> int prev = TWBR;
> if (freq > 0) TWBR = F_CPU/(freq*1000) -16 + 2; // something like that
> return prev;
> }
>
> a -1 or 0 would allow it to act as getClock()
>
> this would allow me to do
>
> prev = setClock(800); // high speed modus
> lcd.print("hello");
> setClock(prev); // back to normal modus
Huh? With the above implementation, this breaks? setClock returns the
old value of TWBR, not the old frequency, so you can't just pass it to
setClock again.

> better alternative is of course is to add a real getClock(); function.
I agree that having a getClock would make sense, since (as also pointed
out by Rob Giseburt later in this thread) that allows the user to get
feedback about the actual frequency used.

However, for the "restore the previous clock frequency value" use case,
perhaps it makes sense to add a getClockDivider() function that returns
the current setting as an architecture-dependent value that can be
passed to setClockDivider again?

This would allow restoring the previous settings, while saving a few
costly calculations (from TWBR to frequency, and back from frequency to
TWBR).


All of the above applies equally to SPI and Wire, btw.

Gr.

Matthijs
signature.asc

Rob Tillaart

unread,
Dec 22, 2013, 5:00:33 AM12/22/13
to Rob Tillaart, Kristian Sloth Lauszus, Arduino Developers, Paul Stoffregen
> setClock(prev); // back to normal modus
Huh? With the above implementation, this breaks? setClock returns the
old value of TWBR, not the old frequency, so you can't just pass it to
setClock again.

Sorry, mea culpa;  typed too quickly without thinking  ...

This would allow restoring the previous settings, while saving a few
costly calculations (from TWBR to frequency, and back from frequency to
TWBR).

Yep, the use case in mind is to switch very fast between different speeds.
Otherwise the time gained by setting e.g. to 800KHz is lost by the time to set it.

A generic low level getter and setter would help on all platforms (protocols)

- struct I2CLLConfig  = getI2CLLConfig(); 
- setI2CLLConfig(struct I2CLLConfig  );  

struct I2CLLConfig for AVR = { TWBR, ClockDivider, ... }; // might include the freq as that was set initially.

same pattern for 
- struct SPILLConfig = getSPILLConfig() 
- struct rs232LLConfig = getrs232Config(); 
- ...

(just thinking out loud)



-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)

iEYEARECAAYFAlK2ry4ACgkQz0nQ5oovr7zG7wCeJ57+zHGLgV6Pm5fyjfDSiAFP
IJQAnArhWIZ/5qoTPg6HjaMxYOPqQdru
=X55J
-----END PGP SIGNATURE-----


Matthijs Kooijman

unread,
Dec 22, 2013, 7:13:35 AM12/22/13
to Rob Tillaart, Kristian Sloth Lauszus, Arduino Developers, Paul Stoffregen
Hey Rob,

> Yep, the use case in mind is to switch very fast between different speeds.
> Otherwise the time gained by setting e.g. to 800KHz is lost by the time to
> set it.
Exactly.

> A generic low level getter and setter would help on all platforms
> (protocols)
>
> - struct I2CLLConfig = getI2CLLConfig();
> - setI2CLLConfig(struct I2CLLConfig );
>
> struct I2CLLConfig for AVR = { TWBR, ClockDivider, ... }; // might include
> the freq as that was set initially.
>
> same pattern for
> - struct SPILLConfig = getSPILLConfig()
> - struct rs232LLConfig = getrs232Config();
> - ...

I like the struct approach, that allows different platforms to define
different amounts of information according to what they need. This does
mean that we need a new API instead of re-using setClockDivider, but
that's probably a good ide anyway, since the setClockDivider name
already points to a specific implementation that might not be applicable
on all platforms.

Gr.

Matthijs
signature.asc

Cristian Maglie

unread,
Dec 22, 2013, 3:27:11 PM12/22/13
to devel...@arduino.cc
In data sabato 21 dicembre 2013 16:44:10, Paul Stoffregen ha scritto:
> Another hardware independent API I'm hoping to see is SPI.setClock().

Agree with that, if someone have a good implementation of SPI.setClock() I'll
be happy to merge it.

C

Kristian Sloth Lauszus

unread,
Mar 6, 2014, 11:26:16 AM3/6/14
to devel...@arduino.cc
Hi all,

I just opened up a pull request that implements setClock for the Wire library: https://github.com/arduino/Arduino/pull/1912.

Regards
Lauszus
Reply all
Reply to author
Forward
0 new messages