In the first post in the series we looked at how to attach displays of various sorts SAMA5D4 Xplained Ultra - Tips and Tricks #1 - Getting Displays up and Running
In this post we will look at how to use some of the IO abilities of the SAMA5D4 Xplained Ultra board (There is no reason I can think of why this would not also work on the SAMA5D3 board should you have one and want to try)
Namely the following
Built in 12 Bit Analogue to Digital Converter
Built in GPIO and a few pitfalls to watch out for
Using the I2C bus and drive
An 8bit I2C port expander (PCF8574) :- http://www.ti.com/lit/ds/symlink/pcf8574.pdf
A quad channel 16bit Digital to Analogue converter (DAC8574) :- http://www.ti.com/lit/ds/slas377b/slas377b.pdf
Here is some written content to get you started
The first experiment was to read from the Analogue ports
A really handy PDF was found here:- http://www.at91.com/linux4sam/bin/view/Linux4SAM/IioAdcDriver
In summary though:
To list the available analogue devices run
ls -l /sys/bus/iio/devices/iio\:device0/
it should show the following:
drwxr-xr-x 2 root root 0 Nov 4 11:21 buffer
-r--r--r-- 1 root root 4096 Nov 4 11:21 dev
-rw-r--r-- 1 root root 4096 Nov 4 10:42 in_voltage0_raw
-rw-r--r-- 1 root root 4096 Nov 4 10:42 in_voltage1_raw
-rw-r--r-- 1 root root 4096 Nov 4 10:37 in_voltage2_raw
-rw-r--r-- 1 root root 4096 Nov 4 10:47 in_voltage3_raw
-rw-r--r-- 1 root root 4096 Nov 4 11:21 in_voltage4_raw
-rw-r--r-- 1 root root 4096 Nov 4 11:02 in_voltage_scale
-r--r--r-- 1 root root 4096 Nov 4 11:21 name
drwxr-xr-x 2 root root 0 Nov 4 11:21 power
drwxr-xr-x 2 root root 0 Nov 4 11:21 scan_elements
lrwxrwxrwx 1 root root 0 Nov 4 08:28 subsystem -> ../../../../../bus/iio
drwxr-xr-x 2 root root 0 Nov 4 11:21 trigger
-rw-r--r-- 1 root root 4096 Nov 4 08:28 uevent
Note there are 5 analog input channels in_voltage0 - in_voltage4 these are NOT mapped to pins A0 – A4 but instead are mapped to pins A1 – A5
Example Usage:
cat /sys/bus/iio/devices/iio\:device0/in_voltage0_raw will read from ADC channel 0 and show the raw value between 0 and 1023 (12 Bit) lest say it showed "948"
cat /sys/bus/iio/devices/iio\:device0/in_voltage_scale will show the scale value and will typically return 3222.00000 indicating the uV per count in this case
so if we multiply 948 and 3222 we get 3054456 which is 3.05V so full scale 1023 would = 3.296V (VREF= 3V3)
in_voltage0_raw --> PIN A1 on the board
in_voltage1_raw --> PIN A2 on the board
If the analog inputs are not enabled then run this to enable them (I have not tried beyond this list)
# echo 1 > /sys/bus/iio/devices/iio:device0/scan_elements/in_voltage0_en
# echo 1 > /sys/bus/iio/devices/iio:device0/scan_elements/in_voltage1_en
# echo 1 > /sys/bus/iio/devices/iio:device0/scan_elements/in_voltage2_en
# echo 1 > /sys/bus/iio/devices/iio:device0/scan_elements/in_voltage3_en
# echo 1 > /sys/bus/iio/devices/iio:device0/scan_elements/in_voltage4_en
Now for some GPIO
GPIO pins are enabled by using commands like the following
echo 8 > /sys/class/gpio/export results in pioA8
echo 24 > /sys/class/gpio/export results in pioA24
echo 32 > /sys/class/gpio/export results in pioB0
echo 48 > /sys/class/gpio/export results in pioB16
echo 64 > /sys/class/gpio/export results in pioC0
echo 96 > /sys/class/gpio/export results in pioD0
now as some pins are already defined by the OS for their operation, you will find that even though the command seems to work, it wont show up on the expected pins
This one however proved to work without an issue
echo 33 > /sys/class/gpio/export results in pioB1
this pin is identified in the diagram above
to set the direction of the pins we simply output an "in" or "out" to the direction folder as follows
"echo "out" > /sys/class/gpio/pioXX/direction"
or specifically
"echo "out" > /sys/class/gpio/pioB1/direction"
and to change values when set as output use
"echo 1 > /sys/class/gpio/pioXX/value" to set the output high
or
"echo 0 > /sys/class/gpio/pioXX/value" to set the output low
and for inputs it is just as simple
"cat /sys/class/gpio/pioXX/value"
if you also want to list all your GPIO settings / status you can run the command
"cat /sys/kernel/debug/gpio"
if it does not work try running this first to enable the debug ability
"mount -t debugfs none /sys/kernel/debug"
There are plenty of example Python, C++ and other languages out on the internet to be found and these can simply be adapted to use the correct references shown here
And then there is I2C to play with
assuming the I2C utilities are installed (And for the official images it is) you can run the program "i2cdetect" to get a list of the devices on a named bus, in our case bus 0 is enables and has our devices connected so we can run the following
"i2cdetect -y 0"
this will (Or should) show the following table
xx | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | a | b | c | d | e | f |
00: | x | x | x | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- |
10: | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | UU | -- | -- | -- | -- |
20: | 20 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- |
30: | -- | -- | -- | -- | 34 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- |
40: | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | 4c | -- | -- | -- |
50: | 50 | -- | -- | -- | 54 | -- | -- | -- | -- | -- | -- | -- | 5c | -- | -- | -- |
60: | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- |
70: | -- | -- | -- | -- | -- | -- | -- | -- |
|
|
|
|
|
|
|
|
For I2C we are going to use two devices, an 8 bit port expander, the PCF8574 and the quad digital to analogue converter the DAC8574
PCF8574
for the port expander we simply need to write the bit pattern for its output to the correct address or issue a read command
Its address has been wired for 0x20 and can be seen detected in the above table
to read we can do this: (The "-y" is to force the conformation and the 0 before the address is identifying the I2C bus number)
i2cget -y 0 0x20
or
i2cget -y 0 0x20 0 b <-- hte trailing b is to tell the command we want only a byte writing or reading, we would use a w for word size. there are other variants so look at the help ("i2cget --help") for more details
the second version will error out in our case, the additional 0 is ment to set a command register in the device and the PCF8574 does not have one, it will interpret this as a write command and set all the outputs to zero instead
so this version of the command is only useful if your using a chip that requires a command before the read or Write
Writing to the I2C bus is just as easy, you just use a set rather than a get
i2cset -y 0 0x20 0xF0 or i2cset -y 0 0x20 255
DAC8574
this is a quad channel 16bit digital to analogue converter and is found at address 48 in our tests, this chip does have a command register used to select internal or external VREF and also to indicate which DAC channel is to be referenced with the subsequent data write (A word as it is 16bit)
"i2cset -y 0 0x48 0x10 0xffff w" will set the channel 0 to full scale and with a 5V reference attached its output is 5V (Bit 4 of the control register, thats the 0x10 is used to indicate an external vref, the 0xffff is the value)
"i2cset -y 0 0x48 0x10 0x0080 w" will set the channel 0 to 50% scale and with a 5V reference attached its output is 2.5V , note that the 08 is the lower order byte as the library sends the lower byte first but the chip expects it last
you can also write to the I2C bus or any other of the above examples using python if you like, the following is an example writing to the port expander
I2C now with python
wget ftp://www.linux4sam.org/pub/Trainings/at91data/ipk/python-smbus_3.0.3-r0_cortexa5hf-vfp.ipk
opkg install python-smbus_3.0.3-r0_cortexa5hf-vfp.ipk
#!/usr/bin/python import smbus bus = smbus.SMBus(0) # 0 = /dev/i2c-0 (port I2C0), 1 = /dev/i2c-1 (port I2C1) DEVICE_ADDRESS = 0x20 DEVICE_REG_TEMP = 0xFF # need 0xff so you can read the switches from 8574 expander t = bus.read_byte_data(DEVICE_ADDRESS, DEVICE_REG_TEMP) print "t = %#x" %t
if you get an error indicating the SMBUS is not there then run the following commands to install it
wget ftp://www.linux4sam.org/pub/Trainings/at91data/ipk/python-smbus_3.0.3-r0_cortexa5hf-vfp.ipk
opkg install python-smbus_3.0.3-r0_cortexa5hf-vfp.ipk
then try again, it should now be working
I would like to thanks Element 14 and Christian doctorcdf for making this post possible by providing me a SAMA5D4 and Display to figure it all out with, also Thomas of Atmel for his help finding training material and demo's to refer to, it has taken quite an effort to pull this all together but now it is done or at least a good bit done, this road test should be significantly better than the SAMA5D3 and you testers should have a lot more fun and much less frustration, I will post more as I find it
Peter