Go here to sign up for The Embedded Muse.
TEM Logo The Embedded Muse
Issue Number 298, February 1, 2016
Copyright 2016 The Ganssle Group

Editor: Jack Ganssle, jack@ganssle.com

   Jack Ganssle, Editor of The Embedded Muse

You may redistribute this newsletter for noncommercial purposes. For commercial use contact jack@ganssle.com.

Contents
Editor's Notes

Are you a member of the 1%? I don't mean the economically elite; rather, the software engineering elite. Those who inject just about 11 bugs, in requirements gathering through coding, per thousand lines of code. The 99% do much worse, averaging about 120 bugs per KLOC.

Wouldn't you want to be in the top tier of developers? That is part of what my one-day Better Firmware Faster seminar is all about: giving your team the tools they need to operate at a measurably world-class level, producing code with far fewer bugs in less time. It's fast-paced, fun, and uniquely covers the issues faced by embedded developers. Information here shows how your team can benefit by having this seminar presented at your facility.

I'm now on Twitter.

Quotes and Thoughts

"The competent programmer is fully aware of the strictly limited size of his own skull." - Edsger W. Dijkstra

Tools and Tips

Please submit clever ideas or thoughts about tools, techniques and resources you love or hate. Here are the tool reviews submitted in the past.

Dave Harper found a nice x86 compiler:

I recently needed to speed up a Tcl script that was running on a Windows system and decided to rewrite it in C. After having numerous installation problems with Visual Studio, I started looking around and discovered Pelles C (http://www.smorgasbordet.com/pellesc/). This is a freeware development kit for windows with optimizing C compiler, IDE, source level debugger, profiler and a host of other goodies. Plus, it's fast - application load times and compile times run circles around other applications I've used. Surprisingly for freeware, it comes with some of the most extensive documentation I've seen (over 2100 pages after I converted a CHM file to PDF). The wiki page is not that great, but there is a forum for any questions the documentation doesn't address.

Highly recommended.

Phil Ouellette had some comments about FreeRTOS and uEZ-GUI:

The comment was made about there being no such thing as free tools.

Well obviously there is a cost of adoption, but I have to say that FreeRTOS is about the freest and one of the most useful tools I have ever been pleased to use.

* OS Download (with full source) is free.
* Documentation cost is nominal ($65 for the reference manual plus a processor specific tutorial manual).
* Support is incredible, both from the vendor and from a sea of interested user.
* 3rd party engineering support is readily available when you need it.

One of the best examples of how pervasive FreeRTOS is, Future Designs Inc (FDI) EziGui example code. This is well written code that is very well integrated on top of FreeRTOS. I was able to design several commercial products using this tool as a head start development tool and the credit is in large part due to FreeRTOS.

There really is no reason to be paying runtime royalties for an ARM Cortex M RTOS when FreeRTOS is around.

He later added:

I really like the FDI products. Good guys to work with. If you need a low performance (not Android) man-machine graphical interface their EzGui is pretty compelling. Works well as is for low quantity production products. DFI will also do quick turn contract design and manufacturing here in the USA which I have found to be useful.

There are some fantastic inexpensive ARM Cortex M family development tools available. I think Rowley's Crossworks ARM is an incredible value for a fully featured, supported IDE. It is based on the GNU tool chain, but Rowley provides a fully worked out implementation for your specific processor choice and even includes board support packages for most reference designs. You can buy a fully functioning personal use license for $150 (for non-commercial use only) and the full commercial license is only $1500. I have used ARM's RSVD, Keil's' MDK-ARM and IAR's EWARM. I find Rowley's product to be just as productive, well implemented and supported as the tool chains costing 4 to 6 times as much.

Segger's J-Link is a great little JTAG debugger. I used one at work and when I retired bought myself an educational J-Link for $60. Rowley supports this debugger directly, just select it from the drop down menu and everything is configured and working.

Compared to where we started (8051 macro assembler plus Intel Blue-Box anyone), we have it so easy now.

Freebies and Discounts

FRDM-KL25Z Development Board

Reader feedback about these giveaways has been very positive. So this month I'm giving away a FRDM-KL25Z development board, which was kindly provided by Freescale. This board has a Cortex M0+ MCU. One neat feature is that it works with the mbed tool chain, which is a web-hosted C compiler. There's nothing to install. For small projects and experiments it's a really fast way to get started.

The contest will close at the end of February, 2016. It's just a matter of filling out your email address. As always, that will be used only for the giveaway, and nothing else. Enter via this link.

Long-Term Project Support

In the last Muse there was some discussion about maintaining tools for years to support a code base.

Jerry Trantow has an approach that never occurred to me:

I am also faced with support and development of aviation software using ancient tools. (TMS320C31 with Code Composer IDE last updated in 2001) The compiler/linker work on newer OS, but the debugger requires XP. I have found it is much easier to maintain an XP virtual machine for development than keeping an old computer around. I have successfully used VMWare for many years and with multiple computers. The last time ran the VM, I did need to disable a USB3.0 card, but other than that the VM just keeps working.

I highly recommend putting the old computers out of their misery and using a VM. VMs can easily be archived and can run on multiple computers. You also get the benefits of using your latest monitors, keyboards, trackballs, etc...

In a second email Jerry wrote:

The basic peripherals (USB emulators with XP drivers, serial ports, etc..) all work under the VM. It's also convenient to copy the VM to a laptop when I work on-site. I can't imagine trying to dig up the old tools every time I change computers. I should also note, that even with ancient build tools I use a modern IDE running on Win10 using a makefile to call the old assembler, compiler and linker. I only use the XP VM for running the debugger. The VM allows me to share directories so this is pretty smooth. This setup also lets me leverage the latest versions of tools like SVN and Lint that are running on my main development machine.

I did run into a problem a few months ago trying to update an old VisualStudio maintenance GUI written in the late 90s that went along with some C31 software. The task was to update the GUI originally written for Win2000/XP to run on Win8/10. It turns out my VM Workstation 6.5.5 is too old to create Win8/10 VMs and the current VM Workstation 12 doesn't work with really old VMs. If that project comes through, I will upgrade VM Workstation and create an XP VM for running the original and Win7, Win8, Win10 VMs for testing my changes. Archiving multiple old computers wouldn't make much sense in this situation.

Sergio Caprile agreed:

Regarding a working system with proper IDE and tools, virtual machines are a life saver these days, you can have a working "machine" in a couple files in your disk, and free software like Virtualbox. It has to have a "recent" OS although, from W2000 up (I guess) or Linux. W98 and others can be run with more expensive alternatives.

The problems is, as you say, storage. Perhaps paying for (encrypted) cloud storage or having multiple backups on different media types can help, but, anyway, it passes the ball to the systems guys, as for us developers is just a matter of backing up data, subject we already discussed some time ago.

Bob Snyder has a twist on this:

I can add one more item to the long list of risk factors for long-term project support. I am currently using two software tools that I love: DipTrace for schematic and PCB layout, and Eazfuscator for obfuscation of Windows programs developed in Visual Studio .NET.

Both of the companies have provided me with great tech support.

And both are located in Ukraine!

I had no idea SpinRite works on SSDs. Cogoman01 wrote:

I'd say that's quite a valid concern, but also anyone who gets bit by BITROT should know about SpinRite, by Gibson Research Corporation.

Software originally intended to fix BITROT on spinning discs can actually recover SSDs too, and from some of the success stories users have sent to Steve Gibson, it can recover some speed that's been lost to multiple reads of inconsistent data.  SpinRite won't recover a dead drive, but it can read weak bits and write them back out strongly, allowing a good drive with BITROT to continue in use.  Of course, one should ALWAYS have a backup.

  He also came up with a great solution to logging in to multiple web sites called SQRL (Squirrel) which stands for Secure Quick Reliable Login.  The code isn't finalized yet, but I can't wait till it's available!

The Wikipedia article is a bit fuzzy on SpinRite's efficacy on solid state drives. Gibson claims it is effective on SSDs, but I'm a bit skeptical.

Review of Digilent's Waveforms 2015 and Analog Discovery 2 Oscilloscope

Richard Wall reviewed Digilent's Waveforms 2015 software and their Analog Discovery 2 oscilloscope, and was kind enough to let me publish it. I reviewed the original Analog Discovery here.

I have been designing microprocessor based control systems since 1976 (that's no mistake -- yes for 40 years!) I have worked in industry for 18 years and academia for 25 years. The instruments I have relied on for the vast majority of my hardware diagnostic efforts have been the multimeter and the oscilloscope. Verifying processor input and outputs is fundamental to quality digital systems development. I used a Fluke 100MHz dual channel digital oscilloscope for many years. However, since I acquired a Digilent Analog Discovery and the Windows based Digilent Waveforms software, I have not used the Fluke Oscilloscope. My current processor of choice is the Microchip PIC32® and either the MPLAB X and/or the Arduino IDE. My office environment I most often use is a Windows 8 PC with two monitors. I use the Analog Discovery / Waveforms extensively. I have recently investigated the updated versions called Waveforms 2015 / Analog Discovery 2.

The following is a list a few of the advantages of using Analog Discovery system with either the Waveforms or Waveforms 2015.

  • The Waveforms software is free.
  • The Analog Discovery is considerably less expensive than a conventional laboratory oscilloscope / logic analyzer.
  • There is considerable time savings and convenience of having the design hardware instrumentation on one PC monitor and the processor code on another.
  • The Analog Discovery small package size consumes minimal bench top space,
  • I have never experienced any issues with for the Waveforms software USB interface.
  • The ability to use logic analyzer inputs to trigger analog measurements has proven to be very valuable.
  • A PC can easily capture the Waveform displays and incorporate the capture into into word processor documents. Additional annotation can be added using a program like Visio.
  • Ability to use the Analog Discovery as a data collection system for post processing.

Waveforms 2015 improvements:

  • The Waveforms 2015 is compatible with the Electronics Explorer, Analog Explorer and the Analog Explorer 2 hardware.
  • More than 2 markers can be added to the timing diagrams
  • It is nice the protocol list appear when adding new channels.
  • It is nice to have the programmable power supplies back.
  • The meter function complements the static logic functions. Great to see -- see suggestions below.
  • The learning time to upgrade from the original Waveforms to Waveforms 2015 is minimal.

Analog Discovery Improvement Suggestions:

  • The pin terminals get loose after extended use. The issue can be resolved by replacing the signal cable assembly (part # 310-064).
  • Add the CAN protocol to the list of interpreters. (This will put the product on the automobile makers' radar.)
  • Replicate conventional multimeter functions:
    • Resistance / Capacitance measuring probe or feature.
    • Add frequency / duty cycle measuring features to meter function.

Waveforms 2015 Documentation Improvement Suggestions:

  • Documentation: Interpreter -- ambiguous meaning - a more intuitive meaning is term is simply "protocol".

 

A Simple 'Stateless' Decoder for Quadrature Encoders

Recently readers have sent in their code and ideas for handling quadrature inputs. Bill Mather submitted a really nice analysis, with code:

There are 2 issues here -- ensuring a clean Gray Code (i.e. no invalid states), and doing a correct, fast or low-overhead decode of the valid Gray Code. My research shows no code which correctly handles Gray Code phase errors in all cases, so I looked for a best-case scenario.

For debouncing, I follow Tim Wescott's outlook -- make everything as reliable as possible, so my algorithm presumes clean input, provided by hardware debouncing, which for our hardware is a simple RC signal shaper with hysteresis, and a limited pulse repetition rate.

My extension to the discussion is to derive the previous state by using edge interrupts (to give the phase changing), and a read of the current phase inputs (to give both current and previous states). The LPC1347 can support separate interrupts for each phase -- the example code is for this CPU.

For Gray Code, the rotation direction can be determined by the phase edge and the resulting phase state. After developing my routine, I have found a reference to this technique -- the KL25Z manual MK20DX256VLH7-K20P64M72SF1RM.pdf describes the hardware algorithm in section 36.4.25 Quadrature Decoder mode, page 890. It also appears to ignore phase errors in the decoder.

Given the standard Quadrature Encoder / Gray Code signal, and ignoring phase errors:


traversing FWD, the signals are <AB> (00, 10, 11, 01, 00),
and, traversing REV, the signals are <AB> (00, 01, 11, 10, 00).

This gives the same maps as all other algorithms show. However, re-arranging the maps, to be in terms of a single channel instead of in terms of time, two interesting tables result:

 change ChB (low bit)			change ChA (high bit)
        0[0] - 0[1] R				[0]0 - [1]0 F
        0[1] - 0[0] F				[0]1 - [1]1 R
        1[0] - 1[1] F				[1]0 - [0]0 R
        1[1] - 1[0] R				[1]1 - [0]1 F
   dir = (A==B) ? Fwd : Rev;		dir = (A==B) ? Rev : Fwd;

This change map demonstrates that on any edge, the direction of rotation is determined by the channel changing its state, and the comparison of the two states after the edge, as per the 'C' ternary code for ChB:

        dir = (A==B) ? Fwd : Rev;

If the pulse repetition rate is limited, and the inputs are decoded in interrupt routines, the overhead for decoding can be determined. With a standard panel input rotary switch encoder such as the Bourns PEL12T with 24 detents per revolution, using a (10K/0.1uF) 1mS RC shaper on each of the encoder signals allowing the ISRs servicing the QEI signals to require a maximum of 1% of CPU capacity, a rotation rate of 10 revs/sec can be supported.

This algorithm can be implemented in a simple way in LPC1347 interrupt routines.

The physical setup for this example is:
* An LPCXpressoLPC1347 Rev A demo board from Embedded Artists, and
* An eBay "12mm Rotary Encoder Switch", - highly available and very low cost, and
* A PEL12T as a high quality moderate cost Quadrature Encoder signal sources.

Connection:
* The Quadrature encoder pins were connected to pin 8 (PIO0_2) and pin 6 (PIO0_8). (Note: Pin Reads are simultaneous for bits in same 32 bit I/O address)

This code requires :
* the rate of signal edges be limited. This project uses a simple 10K/0.1uF RC circuit on the switches giving a 1mS time constant for each quadrature channel.
* The LPC input pins being set to mode:
- PIO
- No Pullup/PullDown
- Hysteresis enabled -- to prevent oscillation as the signal rises and falls.

typedef uint32_t QEI_TYPE;
#define ioBIT(port,bit)	( 1ULL << (((port) ? (32) : (0)) + (bit)))
// read current pin state
#define GPIO_GET(mask)	(*((uint64_t *)&(LPC_GPIO->PIN)) & (mask))		
#define	iQeiChA		(ioBIT(0, 2))					                    // edge
#define pQeiChA		PIO0_2
#define iQeiChB		(ioBIT(0, 8))					                    // edge
#define pQeiChB		PIO0_8
#define MASK_QEI		(iQeiChA | iQeiChB)

// Rotary-Encoder Interrupt Handler triggered by Phase 0 and 1 Rising AND 
// Falling edges
// 1    ___     ___     ___     ___     ___
// 0 __|   |___|   |___|   |___|   |___|   |____    ChA
// 1      ___     ___     ___     ___     ___
// 0 ____|   |___|   |___|   |___|   |___|   |__    ChB
// FWD A B C D A B C D a b c d a b c d back
// change map - when result is (ChA==ChB), then moves in direction X, else 
// direction Y
//  change low bit 0[1]                 change high bit [1]0
//          00 - 01 R                       00 - 10 F
//          01 - 00 F                       01 - 11 R
//          10 - 11 F                       10 - 00 R
//          11 - 10 R                       11 - 01 F
//      dir = (A==B) ? Fwd : Rev;       dir = (A==B) ? Rev : Fwd;
//
// Uses switch connected to IO-pin shaped with a 1mSec RC circuit.
//  IO-pin must have HYSteresis enabled, to prevent oscillation on pin during 
// switching.

 // dir = (A==B) ? Fwd : Rev
#define QEI_CW(v, p, m)     ((v) += (((p) == 0) || ((p) == (m))) ? 1 : -1) 
// dir = (A==B) ? Rev : Fwd
#define QEI_CCW(v, p, m)    ((v) -= (((p) == 0) || ((p) == (m))) ? 1 : -1)  


volatile int32_t qeiPosition = 0;

//-----------------------------------------------------------
// - Quadrature Encoder Interface Channel A
//-----------------------------------------------------------
void PIN_INT1_IRQHandler(void)
{
    // grab the current state ASAP
    QEI_TYPE newQEI = GPIO_GET(MASK_QEI);

    // Enable the next interrupt capture.
    // Clear RISING/FALLING EDGE interrupt flag
    LPC_GPIO_PIN_INT->IST = (1UL << PIN_INT1_IRQn); 

    // Process the edge
    QEI_CCW(qeiPosition, newQEI, MASK_QEI);
}

//-----------------------------------------------------------
// - Quadrature Encoder Interface Channel B
//-----------------------------------------------------------
void PIN_INT2_IRQHandler(void)
{
    // grab the current state ASAP
    QEI_TYPE newQEI = GPIO_GET(MASK_QEI);

    // Enable the next interrupt capture.
    // Clear RISING/FALLING EDGE interrupt flag
    LPC_GPIO_PIN_INT->IST = (1UL << PIN_INT2_IRQn); 
    // Process the edge
    QEI_CW(qeiPosition, newQEI, MASK_QEI);
}

//-----------------------------------------------------------
// GPIO pin interrupts configuration
//-----------------------------------------------------------
// GPIO pin interrupt 1 set for: QeiChA triggered with BOTH EDGE
// GPIO pin interrupt 2 set for: QeiChB triggered with BOTH EDGE
// Need to set HYS to prevent chatter on RC signal rise/fall time.
//-----------------------------------------------------------
void SetupQeiDecoder (void)
//-----------------------------------------------------------
{
    // enable clock for GPIO pin interrupt (default is disabled)
    LPC_SYSCON->SYSAHBCLKCTRL |= (1UL << 19);   

    // Set to: PIO, No PU/PD, HYSteresis
    LPC_IOCON->pQeiChA    = (1L << 5);    
    // Set to: PIO, No PU/PD, HYSteresis     
    LPC_IOCON->pQeiChB    = (1L << 5);         
    // use edges for INTs
    LPC_GPIO_PIN_INT->ISEL = (ISEL_EDGE << QEI_INT_CHA
                            | ISEL_EDGE << QEI_INT_CHA);  
    // trigger on rising edge   
    LPC_GPIO_PIN_INT->IENR = (IEN_ENA << QEI_INT_CHA
                            | IEN_ENA << QEI_INT_CHB); 
    // trigger on falling edge  
    LPC_GPIO_PIN_INT->IENF = (IEN_ENA << QEI_INT_CHA
                            | IEN_ENA << QEI_INT_CHB);     

    LPC_SYSCON->PINTSEL[QEI_INT_CHA] = ioPOS(iQeiChA);
    LPC_SYSCON->PINTSEL[QEI_INT_CHB] = ioPOS(iQeiChB);

    //-------------------------------------------------------
    // Vectored Interrupt initialization
    // Interrupt routing is fast, so can be any priority
    //-------------------------------------------------------
    // Clear both interrupt flags and pending interrupts, before setting 
    // and enabling them.

    // Clear RISING/FALLING EDGE interrupt flag
    LPC_GPIO_PIN_INT->IST = (IEN_ENA << QEI_INT_CHA
                            | IEN_ENA << QEI_INT_CHB);   
    // Enable INT for QEI CHA
    NVIC_ClearPendingIRQ(QEI_INT_CHA);
    // Default priority group 0, can be 0(highest) - 31(lowest)
    NVIC_SetPriority(QEI_INT_CHA, 0);   
    NVIC_EnableIRQ(QEI_INT_CHA);        // Enable GPIO pin interrupt 1

    // Enable INT for QEI CHA
    NVIC_ClearPendingIRQ(QEI_INT_CHB);
    // Default priority group 0, can be 0(highest) - 31(lowest)
    NVIC_SetPriority(QEI_INT_CHB, 0);   
    NVIC_EnableIRQ(QEI_INT_CHB);        // Enable GPIO pin interrupt 1
}
Jobs!

Let me know if you’re hiring embedded engineers. No recruiters please, and I reserve the right to edit ads to fit the format and intents of this newsletter. Please keep it to 100 words. There is no charge for a job ad.

 
Joke For The Week

Note: These jokes are archived at www.ganssle.com/jokes.htm.

The joke in the last Muse spawned some related ones. From Dave Kellogg:

Regarding the joke in 19 Jan 2016 Muse:
Q1: "What is the object-oriented way to become wealthy?"

A1: Inheritance

Then ask:
Q2: What is the C++ way of getting rich?

A2: Multiple inheritance!

From Charles Manning:

Q: "Why is C++ better for getting wealthy than C# and Java?"

A: "C++ supports multiple inheritance"

Advertise With Us

Advertise in The Embedded Muse! Over 25,000 embedded developers get this twice-monthly publication. .

About The Embedded Muse

The Embedded Muse is Jack Ganssle's newsletter. Send complaints, comments, and contributions to me at jack@ganssle.com.

The Embedded Muse is supported by The Ganssle Group, whose mission is to help embedded folks get better products to market faster.