eclipse / upm

UPM is a high level repository that provides software drivers for a wide variety of commonly used sensors and actuators. These software drivers interact with the underlying hardware platform through calls to MRAA APIs.
MIT License
663 stars 411 forks source link

add a new driver with python bindings for upm/mraa #575

Open mgiaco opened 7 years ago

mgiaco commented 7 years ago

Hi,

For a project I have to add a custom driver. So the C code is already available. There is also a interface file for the spi_init, spi_read, and so on available. Is there a good sample driver where I can get a good recipe of porting?

thx

Propanu commented 7 years ago

Hi @mgiaco, the best examples for porting are other drivers that already exist in the UPM library. Since you already have the implementation, sounds like all you have to do is plug the MRAA SPI API function calls to the interface.

You can learn more about MRAA's SPI C API here. We also have a document on porting here.

Example UPM SPI drivers: apa102, adis16448, max31855, st7735, rf22, rsc, lpd8806.

mgiaco commented 7 years ago

@Propanu Many thanks. My problem is let´s say I have a driver in C which works very well. So there I have extracted the spi stuf so the driver is plain ansi C now. I would be nice if I can use this C driver add some mraa specifiy spi stuf and add the python wrapper files for that. But I always find examples with cpp therfore I taught it is for C++ only. I am wrong here?

Propanu commented 7 years ago

You're right, SWIG will need a C++ class to generate bindings for the other languages.

In UPM, only about half of the drivers have both C/C++ implementations, the others are C++ only, and none are C only, because we want the bindings generated too. Thus use one of the examples that has both (e.g. rsc).

The way this usually works, if you want to provide a C implementation and have UPM generate python/node/Java bindings for you, you'll also have to wrap a C++ class around that C implementation. In certain cases, the C++ class can be header only since all functions map to corresponding C calls.

mgiaco commented 7 years ago

@Propanu many thanks that was what i found out. For developing it is really bad that building took so much time. So therefore I delete almost every driver in the src on my fork. Do you know a better way?

Propanu commented 7 years ago

Yes, after you run cmake you can run make and make install from the folder of the one library you are trying to build (e.g. src/sensortemplate, there's a short paragraph on this in the build documentation towards the end). This will not install dependencies though. Alternatively, you can list only the directories you want to build with a variable while running cmake: -DMODULE_LIST=dirname and then proceed as usual with make.

mgiaco commented 7 years ago

Hi,

I tried to work on my driver for a ad7124 here https://github.com/mgiaco/upm/tree/only_ad7124/src/ad7124 So it works now as expected but I have a question concerning the C defines i use in ad7124.hpp I would like to get access to some defines from the header like this one

#define AD7124_ADC_CTRL_REG_REF_EN         (1 << 8)

Do I really need to move all the defines in the public section or outside the Class definition?

Propanu commented 7 years ago

This is really up to you, but the way it usually works:

mgiaco commented 7 years ago

@Propanu many thanks. I have moved the defines. Is there a way how I can tell swig to generate functions for the Function-like Macros?

Example C:

#define AD7124_CFG_REG_BURNOUT(x)  (((x) & 0x3) << 9)

To python:

AD7124_CFG_REG_BURNOUT = lambda x: ((x & 0x3) << 9)

or

def AD7124_CFG_REG_BURNOUT(x):
    return (x & 0x3) << 9
mgiaco commented 7 years ago

Also some other problem is how can I map this pointer to something python is able to handle?

    /*! Reads the conversion result from the device. */
    int32_t ReadData(int32_t* pData);

I tried this but dose not work:

// Include doxygen-generated documentation
%include "pyupm_doxy2swig.i"
%module pyupm_ad7124
%include "../upm.i"
%include "cpointer.i"

%pointer_functions(int, intPointer);

%{
    #include "ad7124.hpp"
%}

%include "ad7124.hpp"

many thanks

Propanu commented 7 years ago

Hi @mgiaco, try using array classes instead:

%include "stdint.i"
%include "carrays.i"
%array_class(int32_t, int32Array);

We have some decent examples on how to use them under upm/src, see the carrays_<type>.i files.

For function macros I believe you can just declare them as normal functions in the swig interface. E.g:

mgiaco commented 7 years ago

@Propanu okay many thanks - i will try this later.