Detect Moteino board type at compile time?

Started by scott216, December 20, 2017, 01:10:22 PM

scott216

I'm modifying w5100.h so I can use a different slave select pin when using a Moteino and Ethernet shield together.  By default they both use D10.  At compile time, is there a way to distinguish if the board selected is a Moteino?  This is already done with some boards in w5100.h with this code.

    #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
      inline static void initSS()    { DDRB  |=  _BV(4); };
      inline static void setSS()     { PORTB &= ~_BV(4); };
      inline static void resetSS()   { PORTB |=  _BV(4); };
    #elif defined(__AVR_ATmega32U4__)
      inline static void initSS()    { DDRB  |=  _BV(6); };
      inline static void setSS()     { PORTB &= ~_BV(6); };
      inline static void resetSS()   { PORTB |=  _BV(6); };
    #elif defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB162__)
      inline static void initSS()    { DDRB  |=  _BV(0); };
      inline static void setSS()     { PORTB &= ~_BV(0); };
      inline static void resetSS()   { PORTB |=  _BV(0); };
    #else
      inline static void initSS()    { DDRB  |=  _BV(2); };
      inline static void setSS()     { PORTB &= ~_BV(2); };
      inline static void resetSS()   { PORTB |=  _BV(2); };
    #endif



I'd like to add a Moteino specific #elif block that would work for Moteino and MoteinoMega if possible.

--Scott



TomWS

I don't have the specifics handy, but, when you select the board in the IDE, it sets environment variables based on what is in the boards.txt file for that particular platform.  So... if you look in the Moteino Boards file, you should find the prefix that's being used.

Sorry I can't be more specific...
Tom

scott216

I checked my boards.txt file and Moteino isn't in there, but it does show up in the boards drop down.  Maybe the IDE is using the json link for the Moteino info and not boards.txt

https://lowpowerlab.github.io/MoteinoCore/package_LowPowerLab_index.json


TomWS

It will be in a folder where platform specific packages reside.
On a windows system it is something like:
C:\Users\<yourUserName>\AppData\Local\Arduino15\packages\arduino\hardware\Moteino

But I think the macro you're looking for is:
AVR_MOTEINO

Tom

scott216

Thanks Tom. 

I still didn't find the boards.txt, but I did find a forum link where they list the moteino info for boards.txt
https://lowpowerlab.com/forum/moteino/timing-using-8mhz/msg13837/#msg13837
The last line of the moteino section reads:
MoteinoLP.build.board=AVR_MOTEINO


Assuming you're right about AVR_MOTEINO macro, how would I check for the Moteino board?

--Scott

Felix

Scott,
I don't have a quick answer but are you just looking to switch between boards quickly?
I have had this problem too for many years (switching between boards a lot when testing them), using the menus for serial port and boards is a pain and terrible time waste.

scott216

I want the program to compile differently when a Moteino is selected.  Specifically I want the Ethernet and w5100 libraries to use a different slave select pin for Ethernet communication.  The default Ethernet SS pin D10, but this is also the pin Moteino uses for the radio SS.  So, in order to use the Moteino with an Ethernet board, I have to force it Ethernet library to use a different SS pin.

Currently, in the w5100.h file, there's code like this:

#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
      inline static void initSS()    { DDRB  |=  _BV(4); };
      inline static void setSS()     { PORTB &= ~_BV(4); };
      inline static void resetSS()   { PORTB |=  _BV(4); };
    #elif defined(__AVR_ATmega32U4__)
      inline static void initSS()    { DDRB  |=  _BV(6); };
      inline static void setSS()     { PORTB &= ~_BV(6); };
      inline static void resetSS()   { PORTB |=  _BV(6); };
    #elif defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB162__)
      inline static void initSS()    { DDRB  |=  _BV(0); };
      inline static void setSS()     { PORTB &= ~_BV(0); };
      inline static void resetSS()   { PORTB |=  _BV(0); };
    #else
      inline static void initSS()    { DDRB  |=  _BV(2); };
      inline static void setSS()     { PORTB &= ~_BV(2); };
      inline static void resetSS()   { PORTB |=  _BV(2); };
    #endif


Both Moteino's fall into the #else group.  I'd prefer only the Moteino's are compiled differently.  Ideally I'd want something like this:

    #elif defines (__MOTEINO__)
        // Code to set Moteino SS Pin
    #else
      inline static void initSS()    { DDRB  |=  _BV(2); };
      inline static void setSS()     { PORTB &= ~_BV(2); };
      inline static void resetSS()   { PORTB |=  _BV(2); };
    #endif


There's other library changes too, but this gives you an idea of what I'm trying to do. 

Felix

Understood. Only, there are 2 main MCUs on Moteinos, the 328p, and the 1284p. So you'd need a combination of __MOTEINO__ and the MCU (__AVR_ATmegaXXXX__) to really tell which it is. Or the __MOTEINO__ would require more info on the MCU, like __MOTEINO_328P__ / __MOTEINO_1284P__.
This has been asked for before so I will keep it in mind for a future mod to the Moteino core. If anyone has already done and tested something like this, let me know.

scott216

Either way would work fine

#if defined(__AVR_ATmega1284P__) && defined(__MOTEINO__)
#elif defined(__AVR_ATmega328P__) && defined(__MOTEINO__)

or

#if defined(__MOTEINO_1284P_)
#elif defined(__MOTEINO_328P_)


I'm gonna be switching my project over to the MoteinoMega.  I'm a bit low on memory and my sketch keeps hanging after a few hours or days (it varies). I don't think I have anything else that uses a 1284p CPU, so just checking the CPU should be okay for now.

For the MoteinoMega, the radio SS pin uses D4. In w5100 it looks like be default Ethernet SS would assigned to use Port B, bit #2. I looked at the MoteinoMega schematic and it looks like that's pin D2.  Is that correct?

Felix

Quote from: scott216 on December 22, 2017, 04:35:02 PM
For the MoteinoMega, the radio SS pin uses D4. In w5100 it looks like be default Ethernet SS would assigned to use Port B, bit #2. I looked at the MoteinoMega schematic and it looks like that's pin D2.  Is that correct?

Yes. D2 is used by the radio module interrupt.

scott216

So, if I use a Moteino Mega with the Ethernet library, I won't have a conflict where they both use the same SS pin.

perky

Quote from: Felix on December 26, 2017, 03:20:59 PM
Yes. D2 is used by the radio module interrupt.
So in other words D2 can't be used for SS on the ethernet, onother SS pin would need to be selected. I assume the ethernet also has an interrupt. This is going to get complicated if the ethernet and radio share the same SPI port and both are interrupt driven and both try to access the SPI their ISRs (unless I've misunderstood, I'm assuming a Moteino and ethernet would be used together).

Mark.

Felix

The D2 on MoteinoMEGA (digital pin 2) cannot be used by anything else when there is a radio module installed on it.
You will need to use another SPI CS/SS pin in the Ethernet library.

scott216

Thanks.  I was thinking that I could use D2 for Ethernet slave select since Moteino uses D4.  But I see the Moteino radio needs D2 for an interrupt. I can modify the w5100.h library so Ethernet uses a free pin.  I'm doing that now with the Moteina and and Ethernet board. The problem I'm having is it hangs after a while.  It's usually good for 1/2 day to a couple days.  I'm using most of the memory on the Moteino, so I'm hoping that if I switch to a Moteino Mega, it will stop hanging. 

--Scott

perky

I suspect this is down to SPI being a shared resource and during an SPI access for one device it is interrupted by the other device which then tries to use the same resource. You woud need to put some protection mechanisms in there to prevent it, for example disabling the interrupt for the other device while the SPI is being used. If the radio library ISR only sets a flag rather than accessing the SPI, and all accesses to SPI for the radio are done in the main loop, then you may get away with simply disabling the ethernet interrupt during those accesses. You'd need to look carefully at what the code is doing, but hanging like this is typical of this type of problem.

Mark.