BeagleLogic: now also analog

A year and half ago I published a survey on the BeagleLogic wiki where prospective visitors and users were asked which feature they wanted to see in BeagleLogic the most. I compiled the raw responses so far, here they are:BeagleLogic survey

It’s interesting that a majority of prospective users wanted to be able to do analog sampling with BeagleLogic.

And today, it becomes a reality for BeagleLogic users, thanks to the efforts of a team working at Google Research who wanted to use the BeagleBone for data acquisition and had been working independently on an ADC cape for the BeagleBone for a while. When we first got in touch, they already had a board fabricated and assembled and kindly agreed to send me a prototype to let me help BeagleLogic support the board. It excited me as not only would analog sampling support in BeagleLogic become a reality but also their project could benefit from the kernel infrastructure BeagleLogic has established to capture data using the PRUs on the BeagleBone and move it to userspace to be able to realize the full performance of the ADC which would be difficult to achieve through a libprussdrv based solution.

I am happy to tell you today about the PRUDAQ project (link to announcement on Google Open Source Blogs) – an ADC cape for the BeagleBone for doing high-speed analog data acquisition. At the heart of the board is an Analog Devices AD9201, a 10-bit ADC that can sample two channels up to 20MSPS.
PRUDAQ board
The board has been designed by Jason Holt and his team at Google Research and the team at GroupGets as the manufacturing partner have been instrumental in getting the boards manufactured and ready for sale – the board itself is available at their store, and they also offer a bundle with pre-loaded SD card and other accessories.

GroupGets is a secure platform to create or join group buys for things that are out of reach for a single buyer like a high minimum order quantity for a specialty sensor. Their GetLab engineering team also creates custom hardware and software to enhance group buy targets or make them easier to use.

PRUDAQ with the BeagleLogic stack can be a great way for high performance analog data acquisition – the PRUs and the kernel driver can handle simultaneously both channels of the ADC at sample rates up to 19.9 MSPS 1, which corresponds to a data rate of 79.6 MB/s 2. The dual-PRU architecture of BeagleLogic that maintains a clear separation between the sampling operation itself (done by PRU1) and data transfer to memory (done by PRU0) means that on an application level, only the firmware on PRU1 needs to be changed in order to support PRUDAQ, no modification is necessary on the kernel driver side, raw analog data can be directly read through /dev/beaglelogic and this also opens the door to other ADC boards or sensors being able to make use of the high-speed capture framework provided by BeagleLogic by writing suitable firmware extensions.

There’s also an update to the BeagleLogic system image that also builds in PRUDAQ support, and this will be bundled by default in all new BeagleLogic image releases. It is immediately available for download from the images page on the BeagleLogic wiki. For those interested in the firmware, it’s present in the main repository now here. To learn more about the PRUDAQ project, their wiki is a good place to start.

The performance of PRUDAQ has been documented really well and it also highlights the bottlenecks in the later part of the document, which is also relevant to the performance of BeagleLogic.

I’d also take the opportunity to announce collaboration with GroupGets for the first production batch of BeagleLogic capes and a bundle offer – while the BeagleLogic capes aren’t available today, those who purchase the first batch of the PRUDAQ boards from GroupGets will get 10% off their purchase of a BeagleLogic cape as and when it is made available from GroupGets. The first batch buyers of the board will receive a discount code in their email when it’s ready.

Congratulations to the team at Google Research and GroupGets for a successful launch! I am also very grateful to the support provided to me by the Google Summer of Code program and the BeagleBoard.org Foundation in bringing this project to you over the summers 2 years ago, and looking forward to see the new applications that this will make possible.


  1. Due to the nature of the assembly code that samples the PRU pins, it is not possible to sample both channels at 20MSa/s as the external clock needs to be tracked and at 20MSa/s, samples were found to be dropped. However it works OK at 19.9 MSPS with an external clock [tests done by Jason and his team]. It is however, possible to sample both channels simultaneously at the max possible 20MSPS if PRU1 is allowed to clock the ADC. This is a special case and the firmware to do so will be made available in the future. 
  2. ADC samples are 10-bit but use up 16 bits = 2 bytes. So 19.9 MSa/S * 2 channels * 2 bytes/channel = 79.6 MB/s 

Coming Soon: (Yet another) BeagleBone Display+CapTouch cape

TL;DR: This creates a cape for the BeagleBone Black using readily available replacement spare TFT Panels and a capacitive touchscreen originally found in cheap tablets.

[ You can also follow the project at Hackaday.io ]

Thanks to the economy of scale, the market of lower-end tablets is flooded with N brands available at almost throwaway prices. Here one can buy a cheap one for less than ₹3000 ($45) and get a decent 7″ screen with capacitive touch. But when it comes to the BeagleBone Black I either saw that most of touch screens available were resistive and panels with capacitive screens were out of my budget, especially when you know you could leveraging the same economy of scale build one 🙂 . I decided to take on the challenge and build a cape for the BeagleBone out of these readily available parts.

This December during my winter break at Jakarta, I shopped at Glodok and Roxy – the electronics and mobile spare part shopping hubs respectively [compare that to HQB, Shenzhen but at a smaller scale though]. What really caught my attention was 7″ TFT panels and capacitive touch digitizers in shops – the LCDs looked very close to the cheap 7″ LCD panels being sold on eBay and other places with a Realtek-based HDMI converter which I wanted to check out lately (like this).

These panels are known by the name AT070TN9x (x=0,2,3,4) and are originally manufactured by Innolux and have 50-pin connectors with a TTL interface (datasheet here). But were the panels being sold in the markets the same AT070TN92 panels, their clones or something different? I decided to find out and requested at the shops to be able take a photo of a few models of these. Got home and tried to match the pinout on the panel with the AT070TN92. Bingo. Perfect match for almost every one of them. Even though the panels have slight dimensional differences in the bezel, they have the same pin layout and should (hopefully) be the same from the inside.

Tablet LCD - back

Here you can see the one which has KR070PM7T written on it. The giveaways – Pins 1 & 2 (VLED+) shorted, 3 & 4 (VLED-) shorted. Pins 45, 49 and 50 are not connected. If you refer the datasheets, the pin definitions seem to align.

I bought two panels and mix-matched them with available capacitive touch panels to see which one fitted the screen the best. I also bought from a nearby shop the ZIF FPC connectors for the display and the touchscreen. The display one is 50 pins, 0.5mm pitch and the touch panel has 6 pins at a 0.5mm pitch. Not exactly breadboard friendly but very PCB friendly. As seen on the image at the top of the post (not this one) the LCD is sitting over the capacitive touch panel and you can see the 6-pin connections there. No reverse engineering needed for the capacitive touch FPC as the connections for the 6 pins are already highlighted in the image!

Okay, now I had to find a good driver for the LCD. I was aware of the TI TFP401 DVI (HDMI) receiver and could get samples if I wanted. But hey, the BeagleBone converts from TTL to HDMI and then I’m gonna convert HDMI to TTL, right? Why not just cut through the layers and wire the display directly? Should just be D0-D15, VSYNC, HSYNC, PCLK, 3V3, backlight, adjust LCD driver resolution, timings and done. Turns out we’re not done, yet.

The catch

Every LCD requires a high voltage to control the twist of individual liquid crystals. This voltage is usually internally generated using charge pumps but turns out that this “dirty” LCD panel ( DirtyPCBs 😛 ) expects the voltages to be supplied externally to it. The LCD expects approximately 10.4V for AVDD, 16V for VGH and -7V for VGL to be supplied to it. Hmm, how do I generate these?

The answer was not very hard to find. I was able to get Allwinner’s A13 based reference design for tablets that use a display (no points for guessing which one) with a 50 pin interface. Looking at their gate voltage generation circuits, we get this:

lcd-driving-circuit

This app note from Maxim Integrated explains what we’re looking at [scroll down to the end of the appnote]. The AVDD rail draws the maximum current so it gets powered it by the boost converter. Then the diode and the capacitors form a charge pump generating approximately +21 V and -10.4 V from that rail and the Zener regulates it down to the needed voltages. Very cool.

I’ve ordered some boost converters from AliExpress, the ones called SY7201 and XR1151 which are as of now stuck in the Chinese New Year holiday shutdown. Until then I would test with a TPS61061 which I have at hand.

The design

The schematic of a beta cape is almost done and I’m proceeding with routing of the PCB as at the time of writing. Here’s a peek on how the schematic looks right now, the final will be different from this one:

bb-disp-sch1

The beta version is to be a locally fabricated quick turnaround prototype so that I get something to work up the software side until the PCB for the first batch is manufactured. The production cape may include termination resistors or a 74LVC322245 buffer.

The capacitive touch side is simple. Two I2C pins and an interrupt pin to inform of touches. Turns out that the LCD uses only 47 out of the 50 signals and I can squeeze these three lines into the same FPC as the display using an extension cable and adapter PCB. So I’ve done it this way as can be seen above. The Linux kernel already contains a driver for the ft5x06 in drivers/input/touchscreen/edt_ft5x06.c . So getting the touch for the LCD should just be equivalent to writing some device tree code to invoke the module.

That was a long post. The next posts would feature testing of the capacitive touch panel and of the prototype.

The BeagleLogic cape: Assembly and Testing

A day before Christmas, I was greeted by a yellow DHL packet from Hong Kong. The panels had finally arrived after 8 days – I had chosen rush (48hrs turnaround) and express shipping, and it did work out well as I received them before Christmas. The boards turned out to be nice. Not dirty at all and at a price which was reasonable to me.

Assembly

Ready for assembly
Before assembly – the board with applied solder paste and a few parts

I reflowed the board with a hot air gun. Applied solder paste with a toothpick and placed the parts with the naked eye using a pair of good quality tweezers. The passives are all 0603 size (1.5mm x 0.76mm). Since I was yet to receive the batch of BSS138 FETs I ordered, I used a BC847 NPN transistor for the build instead. Reflowing left a couple of solder bridges on the 74LVCH16T245 (now onwards referred to as ‘the 245’) buffer chip (smallest pitched part on board – 0.5mm) which I removed using a solder wick. Then soldered the pin headers manually.

Cleaned up after soldering using nail polish remover. It’s terribly inefficient, and I plan to get a bottle of concentrated isopropyl alcohol (IPA) at some point of time. Here’s the finished result:

“Smoke Test”

A colloquial reference to the first power-on of the assembled circuit. I plugged the cape into the BeagleBone Black and powered on the assembly. The LEDs lit up and the board booted. No smoke or burning smell. Woohoo, test passed, or …

Errata

I then probed the BeagleBone P8 header pins which serve as inputs to BeagleLogic using an LED, and did the same with the input pin headers. The LED were brighter on the inputs to the ‘245 than the P8 pins, which was contrary to expectations. A quick check on the schematics and turns out that I wired the 245 to translate from rail B to rail A while connecting the inputs to rail A and the Bone pins to rail B. Whoops! However I quickly resolved the problem by lifting pads 1 and 24 (DIR1 and DIR2) off the PCB (which was simple as those were on the ends) and soldered a bit of magnet wire through and to one of the pads of C1 going to +3.3V. Neatly done, and a lesson not to design and send off PCBs to a fab while pulling an all-nighter 😛 .

Testing

Once this was done all was back on track and the circuit worked as expected. The cape as designed did not interfere with the boot-up process due to the action of the transistor pull-down that ensured that the buffer did not drive the P8 pins until SYS_RESETn signal was high.

I tested it with SPI signals upto 24 MHz using the BeagleBoard itself and results are good at a 100Msps sample rate. I could also subject the input pins to 5V freely, without fear that I would burn the board. That’s exactly what the cape is meant for, and I’m happy with the results.

I am planning to give away the surplus boards from the first batch so anyone interested in testing it out can get in touch and depending upon where you are, I may be able to send you one of the surplus unpopulated boards (no parts included) which can be assembled yourself (1 IC, 4 passives, 1 transistor and pin headers). The Cape EEPROM section can be left unpopulated without affecting the functionality.

The design files are now available here. I made some changes to the design after fixing the errata, so the cape version is bumped to 1.1 .

Suggestions and feedback on the cape are welcome. The design is Open Hardware, so you have the freedom to use it and improve it as you like. Let me know if there’s anything that could be added in the cape as there is plenty of board real estate.

Introducing: The BeagleLogic Cape

BeagleLogic Cape - 3D Render

After coding up the BeagleLogic project, I thought that it would be great to have an add-on cape for the project that provides buffering and also makes the inputs of the BeagleBone Black tolerant to TTL logic voltage levels (up to 5.5V) allowing BeagleLogic to debug external projects with ease. Hence introducing the BeagleLogic cape, the 3D render of which you can see above. The design is done in KiCad.

The design source and gerbers will be made available on the BeagleLogic GitHub repository after I physically assemble and verify the design.

Design & Layout

The cape design is simple enough to just have a single layer layout, as you can see in the render above the top layer is entirely a ground plane but for a single trace. Since the top isn’t much populated I added useful information on the top silkscreen including indexing the pin headers on the Bone on both sides.

The logic channels are accessed via 2×14 right angled pin headers. The upper row of headers are the actual logic channels while the bottom row is all GND pins. The pin headers are arranged in a MSB-to-LSB fashion. This means that the rightmost pin when viewed from the top is raw bit 0 of the captured logic samples. Note that sigrok will use the names of the actual Bone pins so bit 0 (Channel 1) is to be identified as P8_45, bit 1 (Ch2) is P8_46 and so on. The numbering is a little non-obvious but it’s because that’s the way the pins are arranged on the BeagleBone GPIO header. But don’t worry as the cape lists the pin ID of each logic channel so you don’t have to look it up in the pin diagrams.

One important point here. Only the first 12 channels can be used by default. To use the last two channels, you must disable eMMC first and solder 0R resistors or bridge the two resistors R8 and R9 on the bottom side to enable them. Otherwise the buffer will drive those two pins and you will damage the eMMC of the board and also void the warranty.

Here’s a shot of the schematic (click to enlarge). This is for reference only with respect to the current board and the released schematic may or may not be the same

Cape Schematic

The active buffer is a TI 74LVCH16T245 or equivalent. The buffer is powered from the VDD_3V3B power rail. The OE pin initially pulled is driven using an arrangment of a BSS138 N-MOSFET whose gate is connected to SYS_RESETn of the Bone. This should ensure that the logic input pins, which are also the system boot pins, are not driven by the buffer until the startup has completed.

This version of the design has a 0R resistor through which the VDD_3V3B powers the VDDA side rail of the 16245. If you remove the short and connect it to a 1.8V supply it should become compatible with 1.8V logic levels. I am however thinking of a better solution to the problem and should address this in the next released design.

There’s the officially required cape EEPROM on the bottom side as well, I presume this could be rendered redundant as the community moves towards the Universal Cape concept. But the footprints are there, just in case.

Manufacturing

The first prototype cape has been manufactured by DirtyPCBs.com as a 2-layer Black 10x10cm protopack. It has been shipped as of the time of writing and should reach me next week. I ordered the boards as a Rush order (48h turnaround time) and got it shipped via DHL so that I could have the boards in hand before Christmas rush. I would be using their services further if the boards work out well, looking forward to receive them!

Since I had left space on the panel, and there’s free panelizing so I managed to squeeze some more of my designs into the panel and make the best use of the available real estate. I would write more about those in the coming posts.

So that’s pretty much it. Design suggestions are welcome, and I’ll see if they can be accomodated in the subsequent hardware revisions. Once I test and it all works, the design files will be made available as I have written above.

BeagleLogic: 14 weeks and counting; The journey so far

BeagleLogic was born out of a project idea using the BeagleBone Black, and I am thankful to Jason Kridner and the BeagleBoard.org community for accepting it as a mentored project under the Google Summer of Code 2014. As the GSoC program officially ended last week, here is a video report highlighting what’s been accomplished so far, over a period of 3 months from 19th May to 18th August.

It was an awesome experience this summer, interacting with the community and developing the codebase for a project that showcases the capability of the two little yet powerful integrated Programmable Real-Time Units (PRUs) on the AM335x SoC that powers the BeagleBone Black to realize a 14-channel, 100Msps, 360 MB buffer Logic Analyzer which by far, offers the best value for a 55$ board which you can use not only to develop your embedded projects but also to debug them on-site without any extra hardware requirement. All the magic happens inside the firmware loaded into the PRUs and the kernel driver which manages sharing the system memory with them.

This project also saw me doing many things for the first time. It was the first time I compiled a Linux kernel and wrote myself a kernel module that is now a part of the BeagleBone community kernel, and I look forward to getting it merged upstream. The Web Client for BeagleLogic (link) is my first web application using HTML5 and Bootstrap for a lightweight web client for BeagleLogic. The backend I’ve written for the web client is my first Node.JS based application. I found these frameworks quite interesting and hope to work on projects in these areas in the future.

Google Summer of Code has been the best thing to happen to me so far, and I’ll be looking forward to it in the years to come.

Have fun with BeagleLogic. Also, do write back to me with how BeagleLogic helped you debug helped you debug your circuit and learn more about logic protocols!

BeagleLogic and sigrok: The beginning

This week I spent some time familiarizing myself with the libsigrok components, and developed bindings for BeagleLogic into libsigrok. The development work walked me through non-blocking I/O, which I implemented into the BeagleLogic kernel module only to realize that it had a major bug that causes the client to sleep uninterrupted and froze my BeagleBone Black everytime. The bug got identified and fixed and after that non-blocking I/O worked as expected.

Memory Mapped Kernel Buffers
This was another optimization I made use of in the sigrok bindings. The sigrok library internally keeps logic data in packets and it is exchanged with the host application via pointers. I exploited this good opportunity to use the mmap() functionality I designed into the kernel driver, so the sigrok implmentation just passes a mmap()’ed pointer to the host application instead of read()-ing the data.

However the currently being read buffer still needs to be updated for poll() to work properly. For this reason I implemented dummy reads. When a NULL pointer is passed as the buffer to read(), it does not read any data from the buffer, and just updates the read state within the drivers so that poll() works fine.

The flow of data is like this:

  • libsigrok bindings signal the BeagleLogic module to start the sampling operation, and starts polling on the /dev/beaglelogic node using a GPollFD
  • Once the PRU fills up a data buffer, it sends an IRQ that wakes up the the polling thread and the beaglelogic_receive_data() callback in protocol.c executes
  • The callback sends a packet with the pointer to that segment of data required, and adjusts the internal offsets for the next callback

The process goes on till the sample limit has been reached. BeagleLogic also supports streaming but…

sigrok-cli on the BeagleBone Black
To test the results of the bindings, I ran a sample operation on BeagleLogic using the sigrok bindings and it worked fine. I was able to decode a wave file from my trusty audio player hardware 🙂 to wav right there on the BeagleBone Black using the article on the sigrok blog as a reference. I got 6 seconds of a wave file directly from the dump. This took ~750 seconds to process from RAM on the BeagleBone Black.

I also tested sampling into a 256 MB buffer in the RAM

BeagleLogic goes kernel-mode with PRU remoteproc[Week 2-3]

The first week was spent well in prototyping the PRU firmware. Problems with the memory management [Maximum of 8 MB of memory] and dismal memory copy speeds [10-20 MB/s] with UIO and libprussdrv prompted me to escalate the back-end to the remoteproc kernel driver. It took me a while before I started off based on the WS28xx lighting firmware example to build up the necessary kernel driver infrastructure for BeagleLogic, and it’s now close to the first set of stress tests and actual data capture for the PRU.

Going into the kernel driver, here is a summary of what’s coming up in the next update [the experiment is with dummy data, the PRU’s aren’t engaged] :

Screenshot from 2014-06-11 23:01:19

BeagleLogic Week 1: Building the PRU Firmware

The first week of the Summer of code began with the build of the core PRU firmware for data capture. I coded up firmware for both the Programmable Real-Time units operating in tandem to sample the pins and transfer it to the DDR memory directly. The code can be viewed at these links:
PRU0 assembly code
PRU1 assembly code

It makes good use of the XIN/XOUT broadside interface available for inter-PRU communication allowing movement a chunk of sampled data from PRU1 to PRU0 [currently 8 registers = 16 samples = 32 bytes] in one clock cycle. PRU0 then writes the data into the DDR memory in bursts of 32 bytes. Inter-PRU signalling is achieved through interrupts.

For buffer overflow/underflow detection, there is a global byte counter running in PRU0, which is moved alongwith the logic data “for free” via XOUT. PRU0 compares the received value of the counter with the value received from the previous interrupt, and if they differ by more than 32, then there has been an overflow. Also, when the ARM core is signalled for data, an interrupt counter is incremented. The counter is compared to its previous value, and the delta here again enables us to determine if an underflow has occurred.

This approach works fine for one-shot sampling, and I have been able to achieve all the way up to 4 MSamples of 12 pins running at 100 MHz [40ms], although the limitation on the maximum sample rate is likely to be the hardware of the BeagleBone Black in this case, remember there’s a 47pF capacitive load on the HDMI shared pins, and it is yet to be tested with actual hardware.

Currently there’s only 8 MB of memory shared with the PRU for storing samples, there’s an issue with the UIO kernel driver that prevents reserving more memory. The UIO driver will not be fixed, rather the issue will be addressed in the remoteproc interface of the PRU with the kernel. Until then, there is a workaround by adding mem=448m to the boot command line in uEnv.txt, to reserve the upper 64 MB of the memory for the PRU.

Reducing the sample rate is just inserting more NOPs into the sample loop to adjust the cycles. However, availability of more room between two sampling instructions turn out to be potential cycles for performing RLE (which will be implemented very soon), which seems achievable at 50 MHz.

Overwriting previous chunks of data works fine as well, stress tested upto overwrite 500x. See here for an example run.

The amount of samples collected is still limited by only the amount of memory available. The PRUs are quite fast and capable of sample rates like 100 MHz. The only bottleneck is to hold the data and process it before it runs out, and this is the target for the coming week.

The current test code will be adapted to the sigrok bindings once it is in good shape. The current stable code is available at the repo here, and the latest development is in the “prutest” branch here

Next update due on June 4th.

BeagleLogic Update 0 – 18th May 2014

The introduction video to BeagleLogic is now released! Check it out here:

The slides are available here.

This week I spent time understanding the remoteproc implementation and UIO implementations of the kernel drivers of the PRU in the kernel source tree.

One of the important decisions this week was the confirmation of UIO implementation for the PRU drivers. Although a remoteproc implementation is a better approach, the initial implementation of the core would be in UIO, and as the remoteproc infrastructure improves, BeagleLogic will eventually migrate. Since this would be a core change, it would have minimal impact on the functionality.

All set for May 19th when the coding period commences.

Next update coming up on 21st May.

BeagleLogic Update -1 : 7th May 2014

It’s been almost a week since I began work on BeagleLogic after my finals, and with another 12 days remaining for the Community Bonding period, here’s an update on the things accomplished so far (mostly administrative):

  • We now have beaglelogic.net currently as a mirror to this blog. In due course of time, the project will migrate to its own GitHub pages and website.
  • The GitHub repository for BeagleLogic has been created. This will carry the front-end HTML files mostly, with the actual libraries including sigrok, sigrokdecode and our BeagleLogic Server as submodules to it.
  • Set up a build environment for cross-compilation with the required libs and package config files copied in from the BeagleBone Black Debian System Image (23rd April beta release). Successfully built libsigrok, libsigrokdecode and sigrok-cli and executed on the BeagleBone Black and it decodes a bundled sample DS1307 I2C dump as shown below:
    sigrok-cli SSH BeagleBone Black
    SSH from the BeagleBone Black: Screenshot showing sigrok-cli successfully decoding a dump of DS1307
  • Create the presentation for my project as required by BeagleBoard.org. The draft slides can be viewed here, I will be recording, uploading and posting the video soon, and also updating it at the eLinux wiki page.

The cross compilation, though accomplished, has a few rough edges as I had to edit the pkg-config descriptors for each dependency library for a non-standard prefix. I now use PKG_CONFIG_SYSROOT_DIR and compile with a standard ‘/usr’ prefix with untouched pkgconfig files from the BeagleBone Black, but it seems that a few modifications are needed in the build script to build smoothly. Once this is accomplished, I would be publishing complete build instructions and a cross-compilation script to build sigrok from source for the BeagleBone or BeagleBone Black running Debian Wheezy.

There will be the next update on 14th May 2014, which would be Update 0, after which Update 1 will happen on 21st once coding begins on May 19th.

Stay connected for the latest updates on BeagleLogic.