News for hackers. Stuff that matters.
Re:Using a Time-Of-Flight LIDAR Sensor by quotemstr on Thursday December 08, 2016 @11:18AM (#13131321)
Neat. I'm curious about why the sensor init code looks the way it does though. It's a very long sequence of repetitive register writes. Why not do it like this instead? Table-driven code is underappreciated, I think.

    static const struct {
        unsigned address;
        unsigned value;
    } inits[] = {
        { 0x207, 0x01 },
        { 0x208, 0x01 },
        { 0x096, 0x00 },
        ...
    };

    for (size_t i = 0; i < ARRAYSIZE(init_writes); ++i) {
        uint8_t res = VL_WriteReg8(i2cDeviceAddress,
                                   inits[i].address,
                                   inits[i].value);
        if (res != ERR_OK) {
            VL_OnError(VL_ON_ERROR_INIT_DEVICE);
            return res;
        }
    }

    return ERR_OK;
Re:Using a Time-Of-Flight LIDAR Sensor by anmorgan on Thursday December 08, 2016 @09:11PM (#13136140)
A friend and myself were talking about this exact same thing the other day (he works in the web / desktop app space and I work in the embedded space). We were working on an embedded project a while back and he didn't like seeing "bit magic" sprinkled throughout the code and I completely agree.

I approach this issue in 3 different ways: #define what those series of addresses and values mean, have a function that calls each one semantically, or a function that wraps all of them (what OP is doing).

I was going to show an example specific to this, but unfortunately ST did a poor job this time documenting this specific init sequence. If you look at those application notes linked in the tutorial, they just state they are mandatory private registers, which is disheartening. Looking at the example code that ST provides with their Nucleo boards for the evaluation kit of this module, it doesn't shed much more light, except that it seems to be something to do with ranging, tuning, and up-scaling of the data. They have two functions VL6180x_RangeStaticInit() and VL6180x_UpscaleRegInit() that call this sequence, depending on if up-scaling was defined.

Software for Nucleo Board for the VL6180X: http://www.st.com/content/st_com/en/products/embedded-softwa...

At this point, if I was actually working with this part, I would contact a ST rep and ask them what is up, because it seems weird they are forcing you to write to "private" registers.

If you look at the OP's code, you will see that he does wrap this series of code with VL_InitDevice(), and since ST does not have it documented any better than "These settings should be applied in this order with no substitutions", this is what you get. Doing what is suggested, I don't think really gets you much further, imo, but does condense your code, for what it is worth.

Re:Using a Time-Of-Flight LIDAR Sensor by delinka on Thursday December 08, 2016 @11:29AM (#13131439)
Indeed, their init routine seriously violates the DRY principle. At the very least, each section could be implemented by a macro, but I prefer your 'table-driven' implementation.
Re:Using a Time-Of-Flight LIDAR Sensor by Gibbon1 on Thursday December 08, 2016 @06:40PM (#13135393)
I have a feeling writing is that way is mostly habit because you often end up with init routines where the device barfs during init for various reasons[1] and you need to execute 'plan b'. That said I'd consider using macro's to be a distant third option.

[1] Classic is the uP resets and re-runs the init code on I2C bus peripherals that have already been configured.

Re:Using a Time-Of-Flight LIDAR Sensor by teraflop on Thursday December 08, 2016 @11:51AM (#13131681)
That change would decrease the repeated code, but I think it would also make the code more brittle. What if the requirements were very slightly different, and you needed to do something different in the middle of the sequence, like writing a register of a different size or sleeping for a millisecond?

This situation is crying out for either exception handling, or Go's "errors are values" pattern. (https://blog.golang.org/errors-are-values)

Re:Using a Time-Of-Flight LIDAR Sensor by MaulingMonkey on Thursday December 08, 2016 @12:31PM (#13132125)
> What if the requirements were very slightly different, and you needed to do something different in the middle of the sequence, like writing a register of a different size or sleeping for a millisecond?

Interestingly, I'd argue this is actually a great argument for brittleness in this case. The table oriented code makes it clear to the reader that no such subtle edge cases exist, improving the readability of the code.

Although a local macro or better error handling system would also make such things a bit clearer too.

Re:Using a Time-Of-Flight LIDAR Sensor by LeifCarrotson on Friday December 09, 2016 @01:11AM (#13137024)
> The table oriented code makes it clear to the reader that no such subtle edge cases exist,

As an occasional embedded systems programmer, initialization code without subtle edge cases only exists in artificial examples like this one.