Commit 3e2fe48a authored by David Boddie's avatar David Boddie
Browse files

Merge branch 'update-i2c-address' into 'master'

Add a phone version of a devkit guide for testing

See merge request Librem5/developer.puri.sm!383
parents e623bab7 97568976
Pipeline #52283 passed with stages
in 1 minute and 48 seconds
......@@ -105,148 +105,14 @@ development board below the ``LS1601`` label.
The location of the proximity and ambient light sensors
The `VCNL4040M3OE-H5`_ module is accessed via an |I2C| bus address and exposes
a set of registers that can be accessed by their addresses in the device. This
means that we need two addresses -- a bus address and a device address -- to
access a register.
The kernel provides abstractions that allow the sensors to be accessed fairly
simply without requiring knowledge of the message protocol used for |I2C|
devices.
Preparations
~~~~~~~~~~~~
Before trying to access the sensors as the ``purism`` user, you need to
install the ``i2c-tools`` package on the development board::
sudo apt install i2c-tools
Then add the ``purism`` user to the ``i2c`` group::
sudo usermod -a -G i2c purism
This user should now have permission to read and write the device files for the
|I2C| devices and run the tools to access them.
Accessing the Module
~~~~~~~~~~~~~~~~~~~~
The module is available via address ``0x60`` on |I2C| bus 2. This can be
verified by running the ``i2cdetect`` tool::
purism@pureos:~$ /usr/sbin/i2cdetect -y 2
This should produce output like the following::
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- UU -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- 1e --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- UU -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- UU -- --
60: 60 -- -- -- -- -- -- -- -- -- UU -- -- -- -- --
70: -- -- -- -- -- -- -- --
It should be clear that there is a device at address ``0x60`` on the |I2C| bus
-- this should be the proximity and ambient light sensor.
Reading the Device ID
~~~~~~~~~~~~~~~~~~~~~
We check that the device at address ``0x60`` on |I2C| bus 2 is the sensor by
querying its ``ID_L`` and ``ID_M`` registers, which should be readable at
address ``0x0c`` on the device. We can do this with the ``i2cget`` tool::
/usr/sbin/i2cget -y 2 0x60 0x0c w
The expected value is ``0x0186`` for the sensor module. If a different value is
returned then the device is not the one we were expecting.
Powering the Ambient Light Sensor
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Initially, the device will be powered down. To determine its state we read its
``ALS_CONF`` register at address ``0x00`` on the device::
/usr/sbin/i2cget -y 2 0x60 0x00 w
This should return ``0x0001``, indicating that the shut down bit is enabled.
Set it to ``0x0000`` with the ``i2cset`` tool::
/usr/sbin/i2cset -y 2 0x60 0x00 0 w
When we no longer need to read from the device, we set the shut down bit again::
/usr/sbin/i2cset -y 2 0x60 0x00 1 w
We can read the state of the device again to verify that it has powered down,
if necessary.
Reading the Ambient Light Level
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
With the device powered, ambient light sensor readings can be obtained by
reading from the ``ALS_Data_L`` and ``ALS_Data_H`` registers at address
``0x09`` on the device::
/usr/sbin/i2cget -y 2 0x60 0x09 w
White channel values can be read from the ``White_Data_L`` and ``White_Data_H``
registers at ``0x0a`` on the device::
/usr/sbin/i2cget -y 2 0x60 0x0a w
These should vary as the ambient light level at the sensor changes.
Powering the Proximity Sensor
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The state of the proximity sensor can be obtained by reading the ``PS_CONF1``
and ``PS_CONF2`` registers at address ``0x03`` on the device::
/usr/sbin/i2cget -y 2 0x60 0x03 w
The lowest bit (``PS_SD``) of the value returned is ``1`` if the sensor is
shut down. Set it to ``0`` to power it up. In the simplest case, we can set
both the registers to ``0x00``::
/usr/sbin/i2cset -y 2 0x60 0x03 0 w
Setting the lowest bit to ``1`` again will shut down the sensor.
Reading Proximity Data
~~~~~~~~~~~~~~~~~~~~~~
With the proximity sensor enabled, values can be obtained for the proximity of
object to the sensor by reading from the ``PS_Data_L`` and ``PS_Data_M``
registers at address ``0x08`` on the device::
/usr/sbin/i2cget -y 2 0x60 0x08 w
Closer objects should result in higher values, up to the maximum value set in
bit 3 (``PS_HD``) of the ``PS_CONF2`` register. The default resolution is 12
bits.
Using Python to Access the Sensors
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The ``python3-smbus`` package can be used to read these levels. Install it on
the development board Python script with ``apt``::
sudo apt install python3-smbus
The following script will show the ambient light levels every second until it
is terminated: :download:`ambient.py <_files/ambient.py>`
.. literalinclude:: _files/ambient.py
:language: python3
Similarly, this script will show the proximity sensor's response to close
objects four times a second: :download:`proximity.py <_files/proximity.py>`
.. literalinclude:: _files/proximity.py
:language: python3
.. |i2cbus| replace:: 2
.. |i2c-0a| replace:: UU
.. |i2c-1e| replace:: 1e
.. |i2c-3c| replace:: UU
.. |i2c-3e| replace:: --
.. |i2c-5d| replace:: UU
.. |i2c-60| replace:: 60
.. |i2c-6a| replace:: UU
.. include:: ../../common/Proximity_I2C.txt
.. include:: /links.txt
......@@ -13,3 +13,4 @@ The following sections provide information for developers who need to investigat
Troubleshooting/Reflashing_the_Phone
Troubleshooting/Reinstalling_Core_Apps
Troubleshooting/Testing_GNSS
Troubleshooting/Testing_Proximity
.. _librem_5_testing_proximity:
Testing the Proximity and Ambient Light Sensors
===============================================
.. |I2C| raw:: html
I<sup>2</sup>C
The Librem 5 phone has a proximity sensor (PS) and ambient light sensor (ALS) provided by the `VCNL4040M3OE-H5`_ module. These sensors can be accessed programmatically via messages sent to the relevant addresses on the appropriate |I2C| bus. It can be useful to test that these sensors are working before using the appropriate system D-Bus interface.
.. contents::
:local:
This guide provides a basic overview of the commands that can be used to obtain
ambient light and proximity information from the device using the I2C bus.
Using the I2C Bus
~~~~~~~~~~~~~~~~~
.. |i2cbus| replace:: 1
.. |i2c-0a| replace:: --
.. |i2c-1e| replace:: 1e
.. |i2c-3c| replace:: --
.. |i2c-3e| replace:: UU
.. |i2c-5d| replace:: --
.. |i2c-60| replace:: 60
.. |i2c-6a| replace:: UU
.. include:: ../../common/Proximity_I2C.txt
.. include:: /links.txt
#!/usr/bin/env python3
import smbus
import time
# Bus number and i2c address:
BUS = 1
ADDRESS = 0x60
# Register addresses:
ALS_CONF = 0x00
ALS_Data = 0x09
White_Data = 0x0a
# Masks and values:
ALS_SD = 1
# Create an object to represent the appropriate bus.
bus = smbus.SMBus(BUS)
# Power up the ambient light sensor if not already powered.
state = bus.read_word_data(ADDRESS, ALS_CONF)
if state & ALS_SD == ALS_SD:
bus.write_word_data(ADDRESS, ALS_CONF, state ^ ALS_SD)
try:
while True:
print('Ambient:', bus.read_word_data(ADDRESS, ALS_Data))
print('White: ', bus.read_word_data(ADDRESS, White_Data))
time.sleep(1)
finally:
# Restore the initial state.
bus.write_word_data(ADDRESS, ALS_CONF, state)
#!/usr/bin/env python3
import smbus
import time
# Bus number and i2c address:
BUS = 1
ADDRESS = 0x60
# Register addresses:
PS_CONF1 = 0x03
PS_Data = 0x08
# Masks and values:
PS_SD = 1
# Create an object to represent the appropriate bus.
bus = smbus.SMBus(BUS)
# Power up the proximity sensor if not already powered.
state = bus.read_word_data(ADDRESS, PS_CONF1)
if state & PS_SD == PS_SD:
bus.write_word_data(ADDRESS, PS_CONF1, state ^ PS_SD)
try:
while True:
print('Proximity:', bus.read_word_data(ADDRESS, PS_Data))
time.sleep(0.25)
finally:
# Restore the initial state.
bus.write_word_data(ADDRESS, PS_CONF1, state)
.. Common text for the devkit and phone documentation about the I2C interface
to the proximity and ambient light sensors.
The `VCNL4040M3OE-H5`_ module is accessed via an |I2C| bus address and exposes
a set of registers that can be accessed by their addresses in the device. This
means that we need two addresses -- a bus address and a device address -- to
access a register.
The kernel provides abstractions that allow the sensors to be accessed fairly
simply without requiring knowledge of the message protocol used for |I2C|
devices.
Preparations
~~~~~~~~~~~~
Before trying to access the sensors as the ``purism`` user, you need to
install the ``i2c-tools`` package on the development board::
sudo apt install i2c-tools
Then add the ``purism`` user to the ``i2c`` group::
sudo usermod -a -G i2c purism
This user should now have permission to read and write the device files for the
|I2C| devices and run the tools to access them.
Accessing the Module
~~~~~~~~~~~~~~~~~~~~
The module is available via address ``0x60`` on |I2C| bus |i2cbus|. This can be
verified by running the ``i2cdetect`` tool:
.. code-par::
purism@pureos:~$ /usr/sbin/i2cdetect -y |i2cbus|
This should produce output like the following:
.. code-par::
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- |i2c-0a| -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- |i2c-1e| --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- |i2c-3c| -- |i2c-3e| --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- |i2c-5d| -- --
60: |i2c-60| -- -- -- -- -- -- -- -- -- |i2c-6a| -- -- -- -- --
70: -- -- -- -- -- -- -- --
It should be clear that there is a device at address ``0x60`` on the |I2C| bus
-- this should be the proximity and ambient light sensor.
Reading the Device ID
~~~~~~~~~~~~~~~~~~~~~
We check that the device at address ``0x60`` on |I2C| bus |i2cbus| is the sensor by
querying its ``ID_L`` and ``ID_M`` registers, which should be readable at
address ``0x0c`` on the device. We can do this with the ``i2cget`` tool:
.. code-par::
/usr/sbin/i2cget -y |i2cbus| 0x60 0x0c w
The expected value is ``0x0186`` for the sensor module. If a different value is
returned then the device is not the one we were expecting.
Powering the Ambient Light Sensor
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Initially, the device will be powered down. To determine its state we read its
``ALS_CONF`` register at address ``0x00`` on the device:
.. code-par::
/usr/sbin/i2cget -y |i2cbus| 0x60 0x00 w
This should return ``0x0001``, indicating that the shut down bit is enabled.
Set it to ``0x0000`` with the ``i2cset`` tool:
.. code-par::
/usr/sbin/i2cset -y |i2cbus| 0x60 0x00 0 w
When we no longer need to read from the device, we set the shut down bit again:
.. code-par::
/usr/sbin/i2cset -y |i2cbus| 0x60 0x00 1 w
We can read the state of the device again to verify that it has powered down,
if necessary.
Reading the Ambient Light Level
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
With the device powered, ambient light sensor readings can be obtained by
reading from the ``ALS_Data_L`` and ``ALS_Data_H`` registers at address
``0x09`` on the device:
.. code-par::
/usr/sbin/i2cget -y |i2cbus| 0x60 0x09 w
White channel values can be read from the ``White_Data_L`` and ``White_Data_H``
registers at ``0x0a`` on the device:
.. code-par::
/usr/sbin/i2cget -y |i2cbus| 0x60 0x0a w
These should vary as the ambient light level at the sensor changes.
Powering the Proximity Sensor
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The state of the proximity sensor can be obtained by reading the ``PS_CONF1``
and ``PS_CONF2`` registers at address ``0x03`` on the device:
.. code-par::
/usr/sbin/i2cget -y |i2cbus| 0x60 0x03 w
The lowest bit (``PS_SD``) of the value returned is ``1`` if the sensor is
shut down. Set it to ``0`` to power it up. In the simplest case, we can set
both the registers to ``0x00``:
.. code-par::
/usr/sbin/i2cset -y |i2cbus| 0x60 0x03 0 w
Setting the lowest bit to ``1`` again will shut down the sensor.
Reading Proximity Data
~~~~~~~~~~~~~~~~~~~~~~
With the proximity sensor enabled, values can be obtained for the proximity of
object to the sensor by reading from the ``PS_Data_L`` and ``PS_Data_M``
registers at address ``0x08`` on the device:
.. code-par::
/usr/sbin/i2cget -y |i2cbus| 0x60 0x08 w
Closer objects should result in higher values, up to the maximum value set in
bit 3 (``PS_HD``) of the ``PS_CONF2`` register. The default resolution is 12
bits.
Using Python to Access the Sensors
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The ``python3-smbus`` package can be used to read these levels. Install it on
the development board Python script with ``apt``::
sudo apt install python3-smbus
The following script will show the ambient light levels every second until it
is terminated: :download:`ambient.py <_files/ambient.py>`
.. literalinclude:: _files/ambient.py
:language: python3
Similarly, this script will show the proximity sensor's response to close
objects four times a second: :download:`proximity.py <_files/proximity.py>`
.. literalinclude:: _files/proximity.py
:language: python3
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment