May 29, 2015

MXR9500MZ accelerometer

Now that I have Linux and bare metal running on the same ARM chip, I can interact with any HW in a bare metal application and expose the HW to Linux application in an appropriate manner.  I have already discussed digital interface to various chips in another blog entry, but have not yet discussed bare metal code to interact with such chips, nor have I gone into analog interface to peripheral chips.  I want to do explore real-time signal processing on FPGA and on ARM chip, and I just came by an accelerometer (MXR9500MZ), so I am going to start looking into some motion analysis on Zedboard with it.  Originally, I was going to buy an Analog Devices PMOD accelerometer because the Zedboard supports PMOD, but I might use MXR9500MZ at work, so I began there.

MXR9500MZ is particularly convenient because an eval board is available: MXR9500MZ-B, shown below:
Even though the chip supports a low power mode (pull up DI1 and DI2 pins) where the chip draws only a uW, for the evaluation, I can just always run it, by pulling down DI1 and DI2 pins, exposed on the P1.2 and P1.3 pins in the schematic shown below:
I connected Vdd to the 3.3 V available on my Zedboard, and put the scope on P2.1 and P2.2 on the eval board.  When I shake the chip laterally (because I cannot see Z with my 2 channel scope), I see the following:
Note that at rest, the output is half of Vdd, and the output reflects either + or - values with deviation from Vdd/2.  The sensor maxes out at +/- 1.5 g, so the above excursion in x corresponds to slightly less than 0.5 g.

Zynq ADC is differential, so I would have to use 6 pins to read the acceleration in x, y, z.  For I/O pin strapped application, sensor vendors have I2C or SPI digital interface as well.  But for the purpose of learning to read the Znyq XADC, this sensor is perfect!

May 27, 2015

Xilinx FMC105 breakout board JTAG chain breakage workaround

I love the Avnet Zedboard; for learning a computing system from ground up, this medium priced board is the best thing I found so far; the flexibility to modify the HW forces me to really understand the low level concepts.  The Zedboard has lots of I/O possibilities, but exposes ALL I/O pins available on Zynq (that's the CPU/FPGA package that runs the Zedboard) to the FMC connector.  For serious dorking with Zedboard, a breakout board to access all those pins is necessary.  For $150, Xilinx FMC105 board does exactly that.  But when I mounted the FMC105 board on my Zedboard, I found that the JTAG stopped working, and discovered that it is because the FMC105 board also brings out the JTAG TDI/TDO pins, but leave them open--leading to a broken JTAG chain.  Since I want to keep using the USB JTAG connector on the Zedboard, I had to short the TDI/TDO pins with a jumper, as you can see on the lower left corner of my setup, shown below:

Another handy thing to know: although it is hard to get at 3.3V on the Zedboard (as a protection measure, VADJ can only be either 1.8 V or 2.5 V--unless you solder on a jumper), there are a few 3.3 V on the FMC105.  One of them is shown above, where I connected a red cable to my voltage regulator chip (not shown above).  The JTAG pins above also has a 3.3 V source.

May 23, 2015

TI Lightcrafter EVM3010 tear down

One of my challenges at Pacific Biosciences was understanding other technical disciplines.  I interfaced with chemists, biologists, optics, software, bioinformatics, firmware, electrical engineers.  I didn't need to interface with the chemists and biologists all that much, because I was in the "engineering wing" of the R&D.  I can write SW to some extent, and can read schematics, but I found optics very difficult.  I mistakenly expected to understand optics with just some common sense and basic math and physics.  But still, it did not "jell".  At that time, I did not understand why the optics engineers gave me that condescending "you just don't understand" look when I asked for explanations.  Apparently, the chasm between optics and other branches of engineering has been noticed by others; my work colleague told me that the optics people and photography people don't mix either.  I don't know why the chasm is so deep and wide; I have seen optics people try: for example, Richard Szeliski maps (one of the many) mathematical derivations to photography concepts in his book (Computer Vision: Algorithms and Applications)--and then goes right back to more math.  In all the optics books, the math is chastizingly boring; maybe this is what separates the optics professionals from the pretenders/aspirants--like me?

I now realize that I have to understand optics better if I am to continue in the biotech industry.  Rather than launch into hard core lens design, I thought I would ease into it by playing around with active light control using DLP.  So I got a TI DLP EVM 3010, and wondered how to get a collimated image, and hit a roadblock right away: I don't really understand how the basic projector works; I expected the LED collimators to actually collimate the LEDs, and the focusing module to expand the image downstream of the DLP.  Consider this picture of the EVM 3010's optics module, made by eProtech:
The light source is a lone LED sitting on a copper board, drawing a lot of current, as you can see here:
Note that all those pins are positive; the ground is the whole copper board (which has been painted non-reflective), as you can see here:
The copper backplane also has to conduct heat away from the LEDs, so the thermal pad between the back of the copper and the heatsink makes sense.

How much do the 2 convex lenses in front of each LED focus the light?  I thought that after the "collimator" above, the RGB sources would be roughly collimated, because the prism/wedge assembly in front of the DMD does NOT seem to magnify, as you can see below (the smaller rectangle on the side facing the DMD just cleans up the light being thrown at the DMD):

My next step will be to really collimate the RGB LEDs at the source, with a parabolic reflectors.

May 20, 2015

Debugging Zedboard HDMI resolution 1360x768

Problem

I don't see the penguin logo on the 1360x768 HDMI monitor.  After debugging, I discovered that I can actually see something (can run the Qt pathstroke demo), but if the monitor is NOT on when the board boots, the resolution initialization is incorrect (1024x768 instead of 1360x768).

dmesg shows:


[drm] Initialized drm 1.1.0 20060810
drivers/gpu/drm/adi_axi_hdmi/axi_hdmi_drv.c:axi_hdmi_platform_probe[176]
platform 70e00000.axi_hdmi: Driver axi-hdmi requests probe deferral
...
adv7511-hdmi-snd fpga-axi@0:adv7511_hdmi_snd: adv7511 <-> 75c00000.axi-spdif-tx mapping ok
...
Console: colour dummy device 80x30
Console: switching to colour frame buffer device 128x48

axi-hdmi 70e00000.axi_hdmi: fb0:  frame buffer device
axi-hdmi 70e00000.axi_hdmi: registered panic notifier
[drm] Initialized axi_hdmi_drm 1.0.0 20120930 on minor 0

The "Console: switching to colour..." log above is from drivers/tty/vt/vt.c, do_bind_con_driver()

ADI diagnostic tool

To run this tool, get python

git clone https://github.com/analogdevicesinc/diagnostic_report.git

sed 's/@PREFIX@/\/usr/' adi-diagnostic-report.desktop.in > adi-diagnostic-report.desktop

install -d /usr/bin
install -d /usr/share/adi_diagnostic_report/
install ./adi_diagnostic_report /usr/bin/
install ./adi_diagnostic_report.glade /usr/share/adi_diagnostic_report/
xdg-desktop-menu install adi-diagnostic-report.desktop

In the end, it just wants to gather the following output:

dmesg

...

uname -a

Linux zed 3.19.0 #1 SMP PREEMPT Sat May 9 10:20:22 PDT 2015 armv7l GNU/Linux

/etc/os-release:
NAME=Buildroot
VERSION=2015.05-rc1-00029-g89f96ea-dirty
ID=buildroot
VERSION_ID=2015.05-rc1
PRETTY_NAME="Buildroot 2015.05-rc1"

Bitstream information: /sys/kernel/debug/adi_diagnostic/info

does NOT exist

/sys/kernel/debug

Nothing here!
Clock information: /sys/kernel/debug/clk/clk_summary
/sys/kernel/debug/adi_diagnostic/clock_monitor
Board status signals: /sys/kernel/debug/adi_diagnostic/status_monitor

Video out information: /sys/class/drm/*/status

# find  /sys/class/drm/
# find  /sys/class/drm/ -exec file {} \;
/sys/class/drm/: directory
/sys/class/drm/card0-HDMI-A-1: symbolic link to ../../devices/soc0/fpga-axi@0/70e00000.axi_hdmi/drm/card0/card0-HDMI-A-1
/sys/class/drm/card0: symbolic link to ../../devices/soc0/fpga-axi@0/70e00000.axi_hdmi/drm/card0
/sys/class/drm/controlD64: symbolic link to ../../devices/soc0/fpga-axi@0/70e00000.axi_hdmi/drm/controlD64
/sys/class/drm/version: drm 1.1.0 20060810

# file *
device:    symbolic link to ../../card0
dpms:      ASCII text
edid:      empty
enabled:   ASCII text
modes:     empty
power:     directory
status:    ASCII text
subsystem: symbolic link to ../../../../../../../class/drm

# cd /sys/devices/soc0/fpga-axi@0/70e00000.axi_hdmi/drm/card0/card0-HDMI-A-1
# cat dpms
On
# cat enabled
enabled
# cat status
disconnected

IIO device information: iio_info

/proc/config.gz
/proc/interrupts
/proc/iomem
/proc/cmdline

Device register settings (regmap): /sys/kernel/debug/regmap/*


ADI tools source revisions:
mount
/media/boot/VERSION: does NOT exist
FMC FRU EEPROMs: /sys/devices/*/eeprom
/var/log/Xorg.0.log
/proc/device-tree
/sbin/ifconfig -a
/sbin/route -n
/sys/bus/{platform,i2c,spi}/

May 16, 2015

Running Python script within Qt application

IronPython is a way to expose .NET objects to python interpreter (IronPython to be exact) embedded into an executable.  The problem with IronPython is the requirement for .NET: whether using the MSFT .NET framework or the mono, the WPF GUI development is time consuming and expensive, more than small projects can afford.  Qt on the other hand seems to keep simple things simple, and still scale.  But there is not a lot of concrete examples of embedding Python into a Qt GUI.  Many of the discussions are about creating a Qt GUI from Python, which I am NOT interested in.

PythonQt

I ran across PythonQt in this article.  Unlike PyQt and Qt Jambi, PythonQt is NOT designed to provide support for developers writing standalone applications. Instead, it provides facilities to embed a Python interpreter and focuses on making it easy to expose parts of the application to Python.

Scripts often need to do more than just process data, make connections, and call functions. For example, it is usually necessary for scripts to be able to create new objects of certain types to supply to the application.

To meet this need, PythonQt contains a Python module named PythonQt which you can use to access constructors and static members of all known objects. This includes the QVariant types and the Qt namespace.

Here are some example uses of the PythonQt module:

    from PythonQt import *
    print Qt.AlignLeft# Access enum values of the Qt namespace.
    print QDate.currentDate()# Access a static QDate method.
    a = QSize(1,2)# Construct a QSize object

PythonQt requires Qt version >= 4.6.1 and Python >= 2.6 or 3.3.  Ubuntu 14.04.2 LTS already has Python 3.4, as you can check with this command:

$ dpkg-query -L python3.4 3.4.0-2ubuntu1
$ ls -lgh /usr/bin/python3

Ubuntu 14.04 also has Python 2.7 right along Python 3.

Getting PythonQt

PythonQt comes in source, so I had to build it.  Download the source from http://sourceforge.net/projects/pythonqt/files/.  I downloaded the 3.0 zip package, which contains the top level qmake file PythonQt.pro, which points at the projects in folders generator, src, extensions, tests, and examples.

The build scripts currently set to use Python 2.6. You may need to tweak the build/python.prf file to set the correct Python includes and libs.  Make sure that you use the same compiler as the one that your Python distribution is built with. If you want to use another compiler, you will need to build Python yourself, using your compiler.  On my Ubuntu system, Qt5 community version downloaded from qt.io was built with gcc 4.6.1.  On the other hand, the default compiler on Ubuntu 14.04 LTS is 4.8.2.

$ gcc --version
gcc (Ubuntu 4.8.2-19ubuntu1) 4.8.2

On Linux, you need to install a Python-dev package.  For Python 3.4 (what Ubuntu comes with), the command is:

$ sudo apt-get install python3.4-dev

which also gives me the following dependent packages: libexpat1-dev libpython3.4-dev.

Edit preference files

The preference files are in build/ folder.  In common.prf, I specify the release config only.

CONFIG += release

This preference file also determines the Qt version from the qmake being used, and the output format (release/debug); appending "staticlib" will emit a static library, for example.

build/python.prf points to the python version.  To use 3.4, I just had to change to:

win32:PYTHON_VERSION=34
unix:PYTHON_VERSION=3.4

The test for whether that python version exists is the python<ver>-config utility.  While building the extensions, I realized that linking against PythonQt fails because QtCreator uses a different build directory than the source; more precisely, the linked library path is set when qmake runs at first, by this line in build/PythonQt.prf:

unix::LIBS += -L$$PWD/../lib -lPythonQt$${DEBUG_EXT}

So I modified all occurrences of BuildDirectory in PythonQt.pro.user:

<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/henry/Dorking/Qt/PythonQt3.0</value>

Build in QtCreator

After the build (ignore the warnings), the examples and tests are in lib/ folder (along with the library itself).  I ran a simple example by putting the LD_LIBRARY_PATH to the lib/ folder, like this example:

~/Dorking/Qt/PythonQt3.0$ LD_LIBRARY_PATH=./lib lib/PyGettingStarted

Using the same method, I ran the unit tests successfully;

~/Dorking/Qt/PythonQt3.0$ LD_LIBRARY_PATH=./lib lib/PythonQtTest

Time now to start writing my own Qt5 GUI.

[Optional] generate wrappers for my embedded Qt build

Since Qt is highly configurable, the wrappers that come with the released PythonQt is possibly inappropriate, and a new wrapper should be generated.  In the generator/ folder of the PythonQt code, build_all.txt specifies the Qt modules that PythonQt should interface with.  For example, I modified my build_all.txt like this:

<typesystem>
  <load-typesystem name="typesystem_core.xml" generate="yes" />
  <load-typesystem name="typesystem_gui.xml" generate="yes" />
  <load-typesystem name="typesystem_sql.xml" generate="yes" />
  <load-typesystem name="typesystem_opengl.xml" generate="yes" />
  <load-typesystem name="typesystem_svg.xml" generate="yes" />
  <load-typesystem name="typesystem_network.xml" generate="yes" />
  <load-typesystem name="typesystem_xml.xml" generate="yes" />
  <load-typesystem name="typesystem_webkit.xml" generate="yes" />
  <load-typesystem name="typesystem_xmlpatterns.xml" generate="yes" />
  <load-typesystem name="typesystem_uitools.xml" generate="yes" />
  <load-typesystem name="typesystem_multimedia.xml" generate="yes" />
</typesystem>

When run with the environment variable QTDIR pointing to the root of the Qt source folder (which includes the include/ folder), the pythonqt_generator executable will look for that file, and emit the wrappers in the generated_cpp/ folder above the generator/ folder, which the PythonQt build looks for first when building.

My Qt5 GUI

As an instrument engineer, I need a low-level way to monitor what the instrument is doing.  Since it is difficult to monitor ALL aspects of even a moderately complex instrument in 1 panel, either an MDI or a stacked panel (such as a tabbed panel) is necessary to manage the different views.  For now, a simple place holder for TIFF image (often used as the raw image from the camera, for machine vision processing) display suffices.  In the main window ctor, I code the placeholder widgets like this:

ui->setupUi(this);
setWindowTitle(tr("Instrument Control and Scripting"));
mainIcon = new QIcon(":/res/ICS-icon.png"); setWindowIcon(*mainIcon);
welcomeLabel = new QLabel();

static QPixmap icstif(":/res/ICS-blue.tif");
welcomeLabel->setPixmap(icstif);

mainHrow = new QHBoxLayout();
centralWidget()->setLayout(mainHrow);//central layout is the hrow

mainTab = new QTabWidget();
mainTab->addTab(welcomeLabel, "Image");
mainHrow->addWidget(mainTab);
mainTab->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); mainTab->resize(768, 728);

On the right hand side of the GUI, I want to interact with the instrument through Python.  The most obvious usage of PythonQt is as a Python shell within a Qt GUI, for which the examples/PyScriptingConsole/ folder is the best starting point, even though it is not documented.  As a child of the QTextEdit, it can be the top level widget, or embedded as a child widget of another--as can be seen in PythonQtScriptingConsole.h:

class PYTHONQT_EXPORT PythonQtScriptingConsole : public QTextEdit
{
  Q_OBJECT

public:
  PythonQtScriptingConsole(QWidget* parent, const PythonQtObjectPtr& context, Qt::WindowFlags i = 0);
...

I want the application to have 2 main interfaces: textbox and button based control--perhaps managed in a tabbed widget--on the left, and a python shell on the right.  To pull in the PythonQtScriptingConsole, I added the following lines to the .pro file:

PYTHONQT_ROOT = ../lib/PythonQt3.0
include ( $$PYTHONQT_ROOT/build/common.prf )
include ( $$PYTHONQT_ROOT/build/PythonQt.prf )
include ( $$PYTHONQT_ROOT/build/PythonQt_QtAll.prf )

The Python shell is inserted to the right hand side of the horizontal layout (mainHrow above) like this:

#include "PythonQt.h"
#include "PythonQt_QtAll.h"
#include "gui/PythonQtScriptingConsole.h"
...

Gui::Gui(QWidget *parent) : QMainWindow(parent), ui(new Ui::Gui)
{
...
    PythonQt::init(//PythonQt::IgnoreSiteModule |
            PythonQt::RedirectStdOut);
    PythonQt_QtAll::init();
    mainContext = PythonQt::self()->getMainModule();
    shell = new PythonQtScriptingConsole(NULL, mainContext);
    shell->resize(1280-768, 728);
    mainHrow->addWidget(shell);

The result is this GUI, which shows the welcome TIFF image I made up in MSFT PPT:
As you can see, the code suggest works, and I can import the Python3 modules (because I did NOT specify PythonQt::IgnoreSiteModule in PythonQt::init).  Note that the system wide Python module folders are already in sys.path.  To get modules that do NOT come with Python3 (such as the pyserial module I tried to import in the above screenshot), PIP is the recommended way to go.  To install pip on a system, run get-pip.py as root, as in this example:

$ sudo python3 get-pip.py
Downloading pip-6.1.1-py2.py3-none-any.whl (1.1MB)
    100% |████████████████████████████████| 1.1MB 679kB/s 
Collecting setuptools
  Downloading setuptools-15.2-py2.py3-none-any.whl (501kB)
    100% |████████████████████████████████| 503kB 1.4MB/s 
Installing collected packages: pip, setuptools
Successfully installed pip-6.1.1 setuptools-15.2

Then I can install whatever modules that support pip as root again:

$ sudo pip install pyserial

And then use the module in the python shell above, like this example:

py> import serial
py> dir(serial)

Installing python packages manually on an embedded target

The pip is convenient on a networked computer.  If an embedded target lacks networking, I need to manually download the package and run the setup file to install the files on the target.  Here is an example for the hexdump package.  After extracting the zip file and moving the folder to the target's root folder, this is what the package looked like:

# ls
PKG-INFO     __main__.py  hexdump.py   setup.py
README.txt   build        hexfile.bin

After giving executable permissions to the python files, I ran the setup script:

# ./setup.py  install
running install
running build
running build_py
creating build
creating build/lib
copying hexdump.py -> build/lib
running install_lib
copying build/lib/hexdump.py -> /usr/lib/python3.4/site-packages
byte-compiling /usr/lib/python3.4/site-packages/hexdump.py to hexdump.cpython-34.pyc
running install_data
copying hexfile.bin -> /usr/lib/python3.4/site-packages/
running install_egg_info
Writing /usr/lib/python3.4/site-packages/hexdump-3.2-py3.4.egg-info

You can see that the files wind up in the correct site-packages.

Exposing the lower level SW to PythonQt

Suppose you wanted a class Instrument exposed to Python.  An example is getting and setting the names.  In PythonQt, it is done through signals and slots mechanism.  Here is api.h:

#include <QObject>
class InstrumentWrapper : public QObject {
  Q_OBJECT

public Q_SLOTS:
  class Instrument* new_Instrument(const QString& first, const QString& last);
  void delete_Instrument(class Instrument* o);
  QString firstName(class Instrument* o);
  QString lastName(class Instrument* o);
  void setFirstName(class Instrument* o, const QString& name);
  void setLastName(class Instrument* o, const QString& name); 
};

And an implementation of this API is in api.cpp:


#include "PythonQt.h"
#include "PythonQtCppWrapperFactory.h"
#include <QObject>

class Instrument {
public:
  Instrument() {}
  Instrument(const QString& first, const QString& last) {
    _firstName = first; _lastName = last; }
  QString _firstName;
  QString _lastName;
};

#include "api.h"

class Instrument* InstrumentWrapper::new_Instrument(
        const QString& first, const QString& last) {
    return new Instrument(first, last);
}
void InstrumentWrapper::delete_Instrument(Instrument* o) { delete o; }

QString InstrumentWrapper::firstName(class Instrument* o) {

    return o->_firstName;
}
QString InstrumentWrapper::lastName(class Instrument* o) {
    return o->_lastName; 
}
void InstrumentWrapper::setFirstName(class Instrument* o,
                                     const QString& name) {
    o->_firstName = name;
}
void InstrumentWrapper::setLastName(class Instrument* o,
                                    const QString& name) {
    o->_lastName = name;
}

After the C++ side is initialized, register the wrapper to PythonQt:

#include "PythonQt.h" 
#include "api.h"

int main() {
...
    PythonQt::self()->registerCPPClass("Instrument", "",
                                       "instrument",//package within PythonQt                                        
            PythonQtCreateObject<InstrumentWrapper>);
}

Finally, use it in PythonQt shell:

from PythonQt.instrument import *

inst = Instrument("John","Doe") # create a new object
print (inst)

# print the methods available
print (dir(inst))
inst.setFirstName("Mike")
inst.setLastName("Michels") 

print inst.firstName() + " " + inst.lastName())

Debugging a python script remotely

Pydev remote debugging seems the better way to go.

Cross compiling PythonQt for embedded

So far, I found 2 problems with porting PythonQt to an embedded target running Qt5:

  1. The generated wrappers that comes with PythonQt3.0 pulls in modules that are too heavy for embedded.  There should be a way to remove unwanted modules in the build_all.txt and regenerate the wrappers, but I have not figured out how to do this yet. 
  2. LONG_BIT is defined to 0 in pyport.h for some reason, and trips a C preprocessor error.  Size of long is defined to 8 (as it should be for modern gcc compiler), so LONG_BIT should be defined to 64.  I changed #error to #warning to work around the problem and see what happens.