Porting the Arduino RadioHead library to XMOS

Technical questions regarding the xTIMEcomposer, xSOFTip Explorer and Programming with XMOS.
User avatar
aclassifier
Respected Member
Posts: 319
Joined: Wed Apr 25, 2012 8:52 pm
Contact:

Porting the Arduino RadioHead library to XMOS

Postby aclassifier » Tue Jan 16, 2018 12:04 pm

I am planning to do this.

I have started a thread at the radiohead-arduiono group [1] where I have response from the author of the RadioHead library.

There are some questions raised there that maybe someone here would have the time to respond to. I'm afraid there are some text there, so it's not a one minute'er.

Like, could the xTIMEcomposer compile .ino and .pde files (with appropriate #ifdefs to remove Arduino code like "loop()"), or will I have to rename those files?

Also, are there any other matters that I would need to think about?

If I do get any replies there, then fine. If any reply comes here I will link it up there (at [1]).

My blog note where I will try to describe all of this is at [2].

[1] Getting the RF69 to run on XMOS processor

[2] My aquarium’s data radioed through the shelf - Standard disclaimer: no money, no ads, no gifts. Just fun and expenses!
User avatar
george
New User
Posts: 2
Joined: Thu Aug 24, 2017 12:02 pm

Postby george » Mon Apr 16, 2018 10:58 am

The compiler can be made to treat a .ino file as a c++ file using the flag "-x c++ *****.ino".
Below I've included a modified blink.ino with makefile that compiles for either xcore or arduino.

Blink.ino

Code: Select all

// Provide some functions to replace the arduino built-ins
#ifdef XCORE
#include <iostream>

enum PIN_STATE { HIGH, LOW };
enum PIN_MODE { INPUT, OUTPUT };
enum PINS { LED_BUILTIN };

void pinMode(int pin, int pin_mode) {
  std::cout << "Setting pin " << pin << " to " << pin_mode << "\n";
}

void digitalWrite(int pin, int pin_state) {
  std::cout << "Writing " << pin_state << " to " << pin_state << "\n";
}

void delay(int milli_seconds) {
  std::cout << "Delaying for " << milli_seconds << " milliseconds\n";
}
#endif


// the setup function runs once when you press reset or power the board
void setup() {
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(LED_BUILTIN, OUTPUT);
}

// the loop function runs over and over again forever
void loop() {
  digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);                       // wait for a second
  digitalWrite(LED_BUILTIN, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);                       // wait for a second
}

#ifdef XCORE
int main () {
    setup();
    loop();

    return 0;
}
#endif


makefile:

Code: Select all

blink.xe:
   xcc -x c++ Blink.ino -target=XCORE-200-EXPLORER -DXCORE -o blink.xe


The xTIMEcomposer build system will not detect .ino files, so if you plan on adding .ino files to an existing xcore project using xTIMEcomposer, I would suggest using #include, to include the contents of the .ino file in a .cpp file of the same name.

Blink.cpp:

Code: Select all

#ifndef XCORE
#define XCORE
#endif

#include "Blink.ino"
User avatar
aclassifier
Respected Member
Posts: 319
Joined: Wed Apr 25, 2012 8:52 pm
Contact:

Postby aclassifier » Mon Apr 16, 2018 4:07 pm

Great! I guess your last point is what it would boil down to? Or rename the ino file to become a cpp?

I actually now have ported the radio library to a startKIT and an eXplorerKIT. The fun thing is to do it the XC way, since that's what I was after: the porting experience. Not really an easy recompile.

But I guess an easy recompile (of an I/O bound application) doesn't really exist. Just have a look at how difficult it has been to port milliseconds(): Porting the Arduino millis(), possible?. Go to the end there and see akp's solution.

And then there would be bitmapped I/O which I guess is not what the elegant port system of XC just replaces by a macro. It even looks after access rights.

Finally the whole task concept of XC, it by a million surpasses the Arduino "loop".

I will post my complete code when I am satisfied with it on my blog note.

So I guess your "Provide some functions to replace the arduino built-ins" is the fun part here. Because it implies so much more of architectural, concurrency, XC interfaces etc. questions.

With the risk of presenting something obvious for those of you who know XC. Here is the main part of my code, to give a taste of what I mean. RFM69_driver internally is quite like the RFM69 radio library. spi_master_2 is a variant of the spi_master of XMOS lib_spi. Follow i_spi and see how the two clients use the spi library. IRQ_detect_task picks up the interrupt pin. XC code may be quite more elegant in my opinion, than traditional concurrent code.

Code: Select all

out port p_spi_cs_en = on tile[0]:SPI_CS_EN;
out port p_spi_aux   = on tile[0]:SPI_AUX;
in  port p_spi_irq   = on tile[0]:SPI_IRQ;
out port p_probe4    = on tile[0]:PROBE4;

int main() {

    spi_master_if i_spi[NUM_SPI_CLIENT_USERS];
    radio_if      i_radio;
    chan          c_irq_rising; // PROTOCOL: int16_t RSSI

    par {
        on tile[0].core[6]: spi_master_2    (i_spi, NUM_SPI_CLIENT_USERS, p_sclk, p_mosi, p_miso, SPI_CLOCK, p_spi_cs_en, maskof_spi_and_probe_pins, NUM_SPI_CS_SETS);
        on tile[0].core[0]: RFM69_driver    (i_spi[SPI_CLIENT_0], SPI_CLIENT_0, i_radio, p_spi_aux);
        on tile[0].core[1]: RFM69_client    (c_irq_rising, i_radio);
        on tile[0].core[2]: IRQ_detect_task (c_irq_rising, p_spi_irq, p_probe4, i_spi[SPI_CLIENT_1], SPI_CLIENT_1);
    }
    return 0;
}

george, it was good to see that you made that reply as your first response here! I guess as a user I guess I can say welcome!

Now, would anyoune (who hasn't fallen yet off from all my words) know if it's possible to also have .ino files be seen by the build system? Just for the record.

Who is online

Users browsing this forum: No registered users and 59 guests