LowPowerLab / RFM69

RFM69 library for RFM69W, RFM69HW, RFM69CW, RFM69HCW (semtech SX1231, SX1231H)
GNU General Public License v3.0
777 stars 381 forks source link

SS undefined when used with attiny core #11

Closed cyrus007 closed 10 years ago

cyrus007 commented 10 years ago

The definition for SPI_CS = SS at line 14 throws error when used with attiny cores due to SS not being defined in pins_arduino.h for those cores. Work around has been to explicitly define 'static cont unit8_t SS = ' in the code. Any workaround you could think of in the library ?

LowPowerLab commented 10 years ago

How about

if def ATTyiny....__

#define SS = ..... ?

endif

On Wed, Jun 4, 2014 at 9:50 AM, cyrus007 notifications@github.com wrote:

The definition for SPI_CS = SS at line 14 throws error when used with attiny cores due to SS not being defined in pins_arduino.h for those cores. Work around has been to explicitly define 'static cont unit8_t SS = ' in the code. Any workaround you could think of in the library ?

— Reply to this email directly or view it on GitHub https://github.com/LowPowerLab/RFM69/issues/11.

tlanfer commented 10 years ago

Since rfm69.c seems to use SPI.h: Would that workaround actually work? If i understand this correctly (i am not really sure if i do), you cant just define SS for example for the attiny44, because it cant do SPI using spi.h. Instead, you would have to use the USI for SPI. @tsimon57 seems to have written something to make spi.h compatible. I will try to use that.

f4n commented 10 years ago

hi tlanfer, please let me know if you had success with that. i will try it too with a attiny84

tlanfer commented 10 years ago

Well, i got it somewhat working. You can see my changes tlanfer@fe1ffb04fb65842dd29c397bd724493d95b898ec. The USISPI.h you can see in there is just tsimon57/USI-compat-SPI-for-ATTiny, renamed to avoid naming conflicts. What it did is basically just put IFDEFS around all thos Serial.printlns, add a few parantheses (to be able to send without DIO0 interrupt) and define RF69_SPI_CS.

The reason i wrote "somewhat working" is this: I can send stuff, but only under certain conditions. One being attachPcInterrupt being included, although i see no reason why, since i never ever use it (every reference to its function is commented out). Also, i can send some messages, but not others.

This is my sending code:

#include <RFM69.h>
#include <USISPI.h>

#include <PinChangeInterruptSimple.h>

//#include <avr/sleep.h>
//#include <avr/wdt.h>

#define NODEID        2    //unique for each node on same network
#define NETWORKID     100  //the same on all nodes that talk to each other
#define GATEWAYID     1

#define FREQUENCY   RF69_433MHZ

#define LED 3

RFM69 radio(4, 0, true, 0);
void setup() {
  pinMode(LED, OUTPUT);
  digitalWrite( LED, HIGH);
  pinMode( 0, INPUT);
  digitalWrite( 0, LOW);
  //blink(1);

  delay(250);
  radio.initialize(FREQUENCY,NODEID,NETWORKID);
  radio.setHighPower(); //uncomment only for RFM69HW!
  delay(100);
  digitalWrite( LED, LOW);
  delay(100);
}

void loop() {
  char* buff = "1234";
  digitalWrite( LED, HIGH);
  radio.send( 1, buff, strlen(buff), false);
  digitalWrite( LED, LOW);
  delay(500);
}

If instead of the static cstring i try to build a string using sprintf, it will just restart permanently. Am i running out of memory here? attiny85 has 512 bytes of sram.

LowPowerLab commented 10 years ago

You bet, 512sram is very very little to work with. That's why I did not target this for attiny cores. I'm sure there's a way to make it work and squeeze it in 512, but you're still left with little to work with for other things. Attinys are not as cheap as they used to be.

tlanfer commented 10 years ago

The weird thing is that when it works, it only does while the #include is in. Thats what confuses me the most. I even tried copying all of the includes of PinChangeInterruptSimple to my main sketch and removing PinChangeInterruptSimple.h, but it wont work. As soon as i add it, it will. I am pretty sure this is something really really stupid which i overlooked because i actually have no idea what i am doing,...

/E: HA! It was due to the fact that PinChangeInterruptSimple.h defines the interrupt routines. Now to see if i actually need those.

tsimon57 commented 10 years ago

If you are using Arduino, the preprocessor decides what library folders to include/read based on the #include files in your main sketch file. You must add an include file with the name of the library (folder) or it will not use any of the files from the library. Often I have added a 'dummy' include and then used the actual include file (diff from the folder/lib name) in one of the other c++ files. I hope this helps.

vicatcu commented 10 years ago

Be advised, the Arduino pre-processor that decides which libraries to put on the include path is not smart enough to calculate conditionally included (e.g. wrapped by #ifdef) #include. The mere existence of an #include statement anywhere in the source is enough put the library on the include path.

tlanfer commented 10 years ago

tsimon57, vicatcu. Thanks, but (un)fortunately i stumbled upon that some time ago. I just copied everything to my main sketch to see what was going on.

But i am proud to anounce, that it now works as it should :smile: In other words, this (in my opinion rather simple) sketch works:

#include <RFM69.h>
#include <USISPI.h>

#define NODEID        2    //unique for each node on same network
#define NETWORKID     100  //the same on all nodes that talk to each other
#define GATEWAYID     1

#define FREQUENCY   RF69_433MHZ

#define LED 3

RFM69 radio(4, 0, true, 0);

void setup() {
  pinMode(LED, OUTPUT);
  pinMode( 0, INPUT);
  digitalWrite( 0, LOW);
  radio.initialize(FREQUENCY,NODEID,NETWORKID);
  radio.setHighPower(); //uncomment only for RFM69HW!
}

void loop() {
  char buff[5];
  sprintf( buff, "%d", 123);
  digitalWrite( LED, HIGH);
  radio.send( 1, buff, strlen(buff), false);
  digitalWrite( LED, LOW);
  delay(500);
}

All it took in the end was to comment out the attachInterrupt. @LowPowerLab: What exactly do you use the interrupts for? If i understand your code correctly, i can set the module to RX, put myself to sleep and be woken when a packet has arrived by waking on external interrupt. But if i dont intent to sleep, i could also just call receiveBegin() and poll receiveDone(), couldnt i?

LowPowerLab commented 10 years ago

Yesir you are correct, you could just poll. However it's useful to receive a packet as soon as the transceiver receives it, even if your code is busy doing something else. Then whenever you have a chance to call receiveDone() again your packet is already in the buffer ready to be processed by your code, even if the packet was received "long ago" before that. "Long ago" should not be too long ago, meaning your code should try to check the library if a packet was received as often as it can or as is expected to be received. In your case, if you didn't use an interrupt, then whenever you would poll the radio, if a packet was received, then you'd have to read it directly from the radio, and make sure you poll it often enough that no other packets are received and overwritten in the radio's internal buffer. So slight distinction there, but is a big difference in operation. Can this thread be closed?

tlanfer commented 10 years ago

Yes, i think this issue can be closed. As long as the default SPI.h does not support attinys (which i assume will not happen any time soon), it is not possible to make this library compatible for attiny cores without changing other. So theres not much to be done here. FWIW, i may put something together on my blog about how to more or less make it work on attinys. An attiny84 for example should work rather nicely due to more pins and thus the external interrupt not being the same pin as USCLK.

LowPowerLab commented 10 years ago

Great, thanks!