how to get around an absent driver

sterretje:
You missed them by miles :smiley: I was just not in the mood to try to find the library.

I have that same problem, by the way. Wife or dogs call while I'm typing, don't want the energy to go to waste and post anyway when I get back (it will just emphasize what was said before :wink: ).

Dogs in this case too. :slight_smile:
Or dog, to be more specific - the boss my young pup insisted on going outside right now.
Better to oblige than to have to mop up afterwards. :smiley:

OldSteve:
There's no need "to get around an absent driver", or for porting code from one language/platform to another.

right, in this particular case - i just can use the opensource project.

But my confusion is about a more general question/situation:
what if there were no opensource project. What if i had only the source code from the manufacturer. How could i use it with arduino? or for what matters PIC?

here is a copy/paste the examples from the manufacturer's supplied examples:

/*! ----------------------------------------------------------------------------
 *  @file    main.c
 *  @brief   Simple RX with diagnostics example code
 *
 *           This application waits for reception of a frame. After each frame received with a good CRC it reads some data provided by DW1000:
 *               - Diagnostics data (e.g. first path index, first path amplitude, channel impulse response, etc.). See dwt_rxdiag_t structure for more
 *                 details on the data read.
 *               - Accumulator values around the first path.
 *           It also reads event counters (e.g. CRC good, CRC error, PHY header error, etc.) after any event, be it a good frame or an RX error. See
 *           dwt_deviceentcnts_t structure for more details on the counters read.
 *
 * @attention
 *
 * Copyright 2016 (c) Decawave Ltd, Dublin, Ireland.
 *
 * All rights reserved.
 *
 * @author Decawave
 */
#include "deca_device_api.h"
#include "deca_regs.h"
#include "lcd.h"
#include "port.h"

/* Example application name and version to display on LCD screen. */
#define APP_NAME "RX DIAG v1.0"

/* Default communication configuration. We use here EVK1000's default mode (mode 3). */
static dwt_config_t config = {
    2,               /* Channel number. */
    DWT_PRF_64M,     /* Pulse repetition frequency. */
    DWT_PLEN_1024,   /* Preamble length. Used in TX only. */
    DWT_PAC32,       /* Preamble acquisition chunk size. Used in RX only. */
    9,               /* TX preamble code. Used in TX only. */
    9,               /* RX preamble code. Used in RX only. */
    1,               /* 0 to use standard SFD, 1 to use non-standard SFD. */
    DWT_BR_110K,     /* Data rate. */
    DWT_PHRMODE_STD, /* PHY header mode. */
    (1025 + 64 - 32) /* SFD timeout (preamble length + 1 + SFD length - PAC size). Used in RX only. */
};

/* Buffer to store received frame. See NOTE 1 below. */
#define FRAME_LEN_MAX 127
static uint8 rx_buffer[FRAME_LEN_MAX];

/* Hold copy of status register state here for reference, so reader can examine it at a breakpoint. */
static uint32 status_reg = 0;

/* Hold copy of frame length of frame received (if good), so reader can examine it at a breakpoint. */
static uint16 frame_len = 0;

/* Hold copy of event counters so that it can be examined at a debug breakpoint. */
static dwt_deviceentcnts_t event_cnt;

/* Hold copy of diagnostics data so that it can be examined at a debug breakpoint. */
static dwt_rxdiag_t rx_diag;

/* Hold copy of accumulator data so that it can be examined at a debug breakpoint. See NOTE 2. */
#define ACCUM_DATA_LEN (2 * 2 * (3 + 3) + 1)
static uint8 accum_data[ACCUM_DATA_LEN];

/**
 * Application entry point.
 */
int main(void)
{
    /* Start with board specific hardware init. */
    peripherals_init();

    /* Display application name on LCD. */
    lcd_display_str(APP_NAME);

    /* Reset and initialise DW1000. See NOTE 3 below.
     * For initialisation, DW1000 clocks must be temporarily set to crystal speed. After initialisation SPI rate can be increased for optimum
     * performance. */
    reset_DW1000(); /* Target specific drive of RSTn line into DW1000 low for a period. */
    spi_set_rate_low();
    if (dwt_initialise(DWT_LOADUCODE) == DWT_ERROR)
    {
        lcd_display_str("INIT FAILED");
        while (1)
        { };
    }
    spi_set_rate_high();

    /* Configure DW1000. */
    dwt_configure(&config);

    /* Activate event counters. */
    dwt_configeventcounters(1);

    /* Loop forever receiving frames. */
    while (1)
    {
        int i;

        /* TESTING BREAKPOINT LOCATION #1 */

        /* Clear local RX buffer, rx_diag structure and accumulator values to avoid having leftovers from previous receptions  This is not necessary
         * but is included here to aid reading the data for each new frame.
         * This is a good place to put a breakpoint. Here (after first time through the loop) the local status register will be set for last event
         * and if a good receive has happened the data buffer will have the data in it, and frame_len will be set to the length of the RX frame. All
         * diagnostics data will also be available. */
        for (i = 0 ; i < FRAME_LEN_MAX; i++ )
        {
            rx_buffer[i] = 0;
        }
        for (i = 0 ; i < ACCUM_DATA_LEN; i++ )
        {
           accum_data[i] = 0;
        }
        rx_diag.firstPath = 0;
        rx_diag.firstPathAmp1 = 0;
        rx_diag.firstPathAmp2 = 0;
        rx_diag.firstPathAmp3 = 0;
        rx_diag.maxGrowthCIR = 0;
        rx_diag.rxPreamCount = 0;
        rx_diag.maxNoise = 0;
        rx_diag.stdNoise = 0;

        /* Activate reception immediately. See NOTE 4 below. */
        dwt_rxenable(DWT_START_RX_IMMEDIATE);

        /* Poll until a frame is properly received or an error/timeout occurs. See NOTE 5 below.
         * STATUS register is 5 bytes long but, as the event we are looking at is in the first byte of the register, we can use this simplest API
         * function to access it. */
        while (!((status_reg = dwt_read32bitreg(SYS_STATUS_ID)) & (SYS_STATUS_RXFCG | SYS_STATUS_ALL_RX_ERR)))
        { };

        if (status_reg & SYS_STATUS_RXFCG)
        {
            /* Clear good RX frame event in the DW1000 status register. */
            dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_RXFCG);

            /* A frame has been received, copy it to our local buffer. */
            frame_len = dwt_read32bitreg(RX_FINFO_ID) & RX_FINFO_RXFL_MASK_1023;
            if (frame_len <= FRAME_LEN_MAX)
            {
                dwt_readrxdata(rx_buffer, frame_len, 0);
            }

            /* Read diagnostics data. */
            dwt_readdiagnostics(&rx_diag);

            /* Read accumulator. See NOTES 2 and 6. */
            uint16 fp_int = rx_diag.firstPath / 64;
            dwt_readaccdata(accum_data, ACCUM_DATA_LEN, (fp_int - 2) * 4);
        }
        else
        {
            /* Clear RX error events in the DW1000 status register. */
            dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_ALL_RX_ERR);

            /* Reset RX to properly reinitialise LDE operation. */
            dwt_rxreset();
        }

        /* Read event counters. See NOTE 7. */
        dwt_readeventcounters(&event_cnt);
    }
}

What you'd do is study the code that the manufacturer supplied and take into account what device it was written for. Then you write code for the Arduino to do the same thing. Much of the old code can be kept maybe. But for some things the functions may be different. For example if the code used cout, you'd have to change those lines to Serial.print instead since the Arduino doesn't have a console. Or if the code was written for a PIC or some other chip and did some twiddling with an SPI register you'd have to go in and change the names of the registers and check which bits needed to be set or cleared to get the equivalent thing to happen on an AVR. That's what porting code is all about. The structure and the things that have to happen are the same but the specific means to do those things may be different. There's not a quick and easy answer for this other than you have to fix the code to work with the chip you have.

AZZ:
What if i had only the source code from the manufacturer. How could i use it with arduino? or for what matters PIC?

here is a copy/paste the examples from the manufacturer's supplied examples:
...
...

Important parts in that code are the device/manufacturer specific includes; usually they have a C or CPP file associated with them. You need to understand that code (and the datasheet can be useful for that).

If the code was written for a PC, the associated C/CPP file is often compiled to a dll (or other file that you can link) by the manufacturer and you don't have access to the source code. The include files only tell the compiler which functions / methods are available). In that case you only have the datasheet to rely on.

So, according to the datasheet

http://thetoolchain.com/mirror/dw1000/dw1000_datasheet_v2.04.pdf

you talk to this thing using SPI. The SPI interface is defined starting at page 21 of that PDF. That is the API that you program to.

The concept of a 'driver' means it is code specifically written for not just
a specific processor or family of processors but for specific hardware.
The Arduino is a micro controller. What that means is that it is not only
a specifc processor family but also has specific built in functions that may
need to be addressed to provide an interface to any specific external
device.
It is silly to think of a driver as being universal.
There are many libraies that have been created for the Arduino family
of which some are drivers for specific devices.
If none exits for the device you have in mind, you will still have to write
it, no matter what language it is written in.
It is something like expecting to use a manual for a Piper Cub to fly a
747. Some parts are similar but it would be of little help.
The manufacture of the device often has some pseudo code to assist
but they have no idea what processor and hardware you have in mind.
Dwight

Gentlemen,
appreciate your clarifications and help on this subject. I "got it" finally.