analogdevicesinc / libiio

A cross platform library for interfacing with local and remote Linux IIO devices
http://analogdevicesinc.github.io/libiio/
GNU Lesser General Public License v2.1
484 stars 312 forks source link

Global attributes for differential channels #352

Closed fpagliughi closed 4 years ago

fpagliughi commented 4 years ago

I'm playing with a couple types of little SPI devices that each have a single differential voltage input, such as the MPC3201 or the TI ADC0831. These have a single differential voltage channel and timestamp channel:

$ ls -1 /sys/bus/iio/devices/iio:device2/scan_elements
in_timestamp_en
in_timestamp_index
in_timestamp_type
in_voltage0-voltage1_en
in_voltage0-voltage1_index
in_voltage0-voltage1_type

But the scale attribute doesn't follow the channel naming convention, dropping the '0' and '1':

$ ls -1 /sys/bus/iio/devices/iio:device2
buffer
current_timestamp_clock
dev
in_voltage0-voltage1_raw        <-- Same channel, but
in_voltage-voltage_scale        <-- different naming convention
name
...

Notice that it's in_voltage-voltage_scale instead of in_voltage0-voltage1_scale.

This is causing libiio to interpret it as the attributes for a different channel (from iio_info):

    iio:device2: adc0831 (buffer capable)
        3 channels found:
            voltage0-voltage1:  (input, index: 0, format: le:U8/8>>0)
            1 channel-specific attributes found:
                attr  0: raw value: 24
            timestamp:  (input, index: 1, format: le:S64/64>>0)
            voltage-voltage:  (input)
            1 channel-specific attributes found:
                attr  0: scale value: 16.000000000
        1 device-specific attributes found:
                attr  0: current_timestamp_clock value: realtime

It interprets it as a different channel, voltage-voltage: (input), claiming 3 channels found, instead of 2.

So I can't tell if this is a problem in the kernel or a weird corner case for libiio to handle.

fpagliughi commented 4 years ago

Or is this a generic way to say, "all differential channels share this scaling," even though there's only one channel?

pcercuei commented 4 years ago

Is that with an upstream driver? I never saw this "voltage0-voltage1" thing before. Usually, when you have a "in_voltage_scale" attribute, that means it is shared across all "iio_voltageX" channels.

fpagliughi commented 4 years ago

So when libiio sees an attribute like "in_voltage_scale", does it create a "scale" attribute for each voltage channel? Or does it create an additional channel called "voltage" and then the application needs to look for it and apply it manually?

As for the "voltage0-voltage1" thing, this appears to be a representation for differential channels - at least on some low-end I2C and SPI chips that I have been playing with. The ADS1015/1115 chips seem popular with hobby projects probably from their Adafruit breakouts: https://www.adafruit.com/product/1083

These show several differential paths as well as all four single-ended channels:

iio:device1: ads1015 (buffer capable)
    9 channels found:
        voltage0-voltage1:  (input, index: 0, format: le:s12/16>>4)
        3 channel-specific attributes found:
            attr  0: raw value: 19
            attr  1: sampling_frequency value: 128
            attr  2: scale value: 3.000000000
        voltage0-voltage3:  (input, index: 1, format: le:s12/16>>4)
        3 channel-specific attributes found:
            attr  0: raw value: -9
            attr  1: sampling_frequency value: 128
            attr  2: scale value: 3.000000000
        voltage1-voltage3:  (input, index: 2, format: le:s12/16>>4)
        3 channel-specific attributes found:
            attr  0: raw value: 6
            attr  1: sampling_frequency value: 128
            attr  2: scale value: 3.000000000
        voltage2-voltage3:  (input, index: 3, format: le:s12/16>>4)
        3 channel-specific attributes found:
            attr  0: raw value: -16
            attr  1: sampling_frequency value: 128
            attr  2: scale value: 3.000000000
        voltage0:  (input, index: 4, format: le:s12/16>>4)
        3 channel-specific attributes found:
            attr  0: raw value: 177
            attr  1: sampling_frequency value: 490
            attr  2: scale value: 1.000000000
        voltage1:  (input, index: 5, format: le:s12/16>>4)
        3 channel-specific attributes found:
            attr  0: raw value: 308
            attr  1: sampling_frequency value: 490
            attr  2: scale value: 1.000000000
        voltage2:  (input, index: 6, format: le:s12/16>>4)
        3 channel-specific attributes found:
            attr  0: raw value: 289
            attr  1: sampling_frequency value: 490
            attr  2: scale value: 1.000000000
        voltage3:  (input, index: 7, format: le:s12/16>>4)
        3 channel-specific attributes found:
            attr  0: raw value: 192
            attr  1: sampling_frequency value: 128
            attr  2: scale value: 3.000000000
        timestamp:  (input, index: 8, format: le:S64/64>>0)
    3 device-specific attributes found:
            attr  0: current_timestamp_clock value: realtime
            attr  1: sampling_frequency_available value: 128 250 490 920 1600 2400 3300
            attr  2: scale_available value: 3 2 1 0.5 0.25 0.125
    1 buffer-specific attributes found:
        attr  0: watermark value: 1

With this driver, although all the differential channels share the same value, they appear in sysfs names individually:

$ ls -1 /sys/bus/iio/devices/iio\:device1
...
in_voltage0_raw
in_voltage0_sampling_frequency
in_voltage0_scale
in_voltage0-voltage1_raw
in_voltage0-voltage1_sampling_frequency
in_voltage0-voltage1_scale
in_voltage0-voltage3_raw
in_voltage0-voltage3_sampling_frequency
in_voltage0-voltage3_scale
in_voltage1-voltage3_raw
in_voltage1-voltage3_sampling_frequency
in_voltage1-voltage3_scale
in_voltage2-voltage3_raw
in_voltage2-voltage3_sampling_frequency
in_voltage2-voltage3_scale
...

Unfortunately, I don't know the IIO kernel stuff very well, so I can't see if that's causing the issue. But it's happening with two different drivers for chips from different vendors, and I don't see anything specific in the drivers themselves. So I'm starting to wonder if this is expected/acceptable behavior from the drivers, and we need to handle it in user space differently.

pcercuei commented 4 years ago

So when libiio sees an attribute like "in_voltage_scale", does it create a "scale" attribute for each voltage channel? Or does it create an additional channel called "voltage" and then the application needs to look for it and apply it manually?

It creates a "scale" attribute for each voltage channel, but they internally refer to the same sysfs node.

Unfortunately, I don't know the IIO kernel stuff very well, so I can't see if that's causing the issue. But it's happening with two different drivers for chips from different vendors, and I don't see anything specific in the drivers themselves. So I'm starting to wonder if this is expected/acceptable behavior from the drivers, and we need to handle it in user space differently.

I don't know if it's expected/acceptable behaviour from the drivers, but I can say for sure that libiio won't know how to parse that.

fpagliughi commented 4 years ago

It creates a "scale" attribute for each voltage channel, but they internally refer to the same sysfs node.

Oh, good. That's what I was hoping.

I don't know if it's expected/acceptable behaviour from the drivers, but I can say for sure that libiio won't know how to parse that.

It sounds like it's a similar behavior to the single-ended channels. So my guess is that it should probably be handled it in a similar manner - create a "scale" attribute for each differential voltage channel (voltageX-voltageY), but internally refer to the same sysfs node.

I haven't dug too deep into the code for the C lib, but I definitely need to get this fixed, so I can try at it and submit a PR if you think this is the proper way to proceed.

fpagliughi commented 4 years ago

Oh... actually this is in the dummy device, including the "in_voltage-voltage_scale" attribute...

IIO context has 1 devices:
    iio:device0: dummydev (buffer capable)
        11 channels found:
            voltage0:  (input, index: 0, format: le:u13/16>>0)
            3 channel-specific attributes found:
                attr  0: offset value: 7
                attr  1: raw value: 73
                attr  2: scale value: 0.001333
-->         voltage1-voltage2:  (input, index: 1, format: le:s12/16>>0)
            1 channel-specific attributes found:
                attr  0: raw value: 33
-->         voltage3-voltage4:  (input, index: 2, format: le:s11/16>>0)
            1 channel-specific attributes found:
                attr  0: raw value: -34
            accel_x:  (input, index: 3, format: le:S16/16>>0)
            3 channel-specific attributes found:
                attr  0: calibbias value: -7
                attr  1: calibscale value: 0.000100
                attr  2: raw value: 34
            timestamp:  (input, index: 4, format: le:S64/64>>0)
            activity_walking:  (input)
            1 channel-specific attributes found:
                attr  0: input value: 4
            voltage0:  (output)
            1 channel-specific attributes found:
                attr  0: raw value: 0
            activity_running:  (input)
            1 channel-specific attributes found:
                attr  0: input value: 98
            steps:  (input)
            3 channel-specific attributes found:
                attr  0: calibheight value: 0
                attr  1: en value: 0
                attr  2: input value: 47
            sampling:  (input)
            1 channel-specific attributes found:
                attr  0: frequency value: 3.000000033
-->         voltage-voltage:  (input)
            1 channel-specific attributes found:
                attr  0: scale value: 0.000001344
        1 device-specific attributes found:
                attr  0: current_timestamp_clock value: realtime

        2 buffer-specific attributes found:
                attr  0: data_available value: 0
                attr  1: watermark value: 1
rgetz commented 4 years ago

Thanks for the pull request; I assume the pull request works for you?

It will take a bit for us to set up a hardware where we can run a similar driver on, and test things. Thanks for your patience.

fpagliughi commented 4 years ago

No worries. We're still just prototyping the hardware. And I'm not totally familiar with the internal working of the library, so if any of you see a better way to do this, by all means, trash my PR and do it the better way.

rgetz commented 4 years ago

No - I think you are doing it similar to the way that I would have.

Thanks for pointing this out & providing a fix.

rgetz commented 4 years ago

I think everything is handled in the pull request, so I will close this. If you need it - please reopen.