Goldilocks Analogue – Testing 2

Recap

I’ve been working (slowly) on a new development for my ATmega1284p platform, called Goldilocks.

My initial design for the Goldilocks Analogue was flawed in several ways, so I revised the design and produced a new prototype.

Here it is:

P1010277

Goldilocks Analogue – Prototype 2

Now that the new prototype for the Goldilocks Analogue is completed, it is time to test it to see how successful the design was. And interestingly, in the time that I’ve been designing the Goldilocks Analogue, Stanford University in collaboration with Texas Instruments have produced their own Analog Shield.

So this test will compare the Goldilocks Analogue with its dual channel 12bit MCP4822 DAC with the Stanford Analog Shield quad channel 16bit DAC8564 DAC. In a later test sequence, using the same test tone, I compare the Goldilocks Analogue with the Open Music Labs Audio Codec Shield using a Wolfson Micro WM8731 24 bit Codec with ADC, DAC, and signal processing capabilities.

Summary (TL;DR)

The test platform is essentially the same ATmega1284p device, clocked at 22.1184MHz. For the Goldilocks Analogue it is integrated on to the main board. For the Analog Shield I used a Goldilocks device as provided in the Pozible project.

You don’t need a lot of space to have great tools. I’m using a Red Pitaya device, configured as an oscilloscope and as a spectrum analyser, together with a Saleae Logic to capture SPI transactions.

P1010271

Micro Test bench – Red Pitaya and Saleae Logic

Both Goldilocks Analogue and Analog Shield are comfortably capable of producing reasonable quality stereo signals at 44.1kHz sampling rate. Both devices output beautiful looking 43.1Hz sine waves, at 44.1kHz reconstruction rate, from a 16 bit 1024 sample Sine Wave.

The Goldilocks Analogue produces 0V to 4.096V 1:1 buffered signals from its DC outputs, and an AC amplified headphone output in parallel. The Analog Shield produces -5V to +5V balanced amplified signals from the 0 to 2.5V DAC.

GA&AS_Scope

Full Swing 43.1Hz Sine Wave Goldilocks Analogue – Blue 0V to +4.096V Analog Shield – Red -5v to +5V

The Analog Shield shows a lot of harmonics at high frequencies as shown. Comparing the two solutions, the Analog Shield doesn’t do justice to the extra 4 bits (theoretically 98dB SNR 16 bit DAC), over the Goldilocks Analogue (theoretically 74dB SNR 12 bit DAC). The BOM price difference between MCP4822 ($4.60) and DAC8564 ($20) is hard to justify given the performance demonstrated.

I think that using the platform of the AVR ATmega (Arduino) there is little point using a 16 bit DAC. There is too much noise (many mV) in the power supply and around Goldilocks or Arduino Uno or Mega boards to make more than 10 to 12 bits of DAC resolution (or ADC resolution) in any way relevant.

GA&AS_43Hz_976kHz

Overlaid 976kHz Spectrum – Analog Shield Red – Shows significant harmonics

Stanford – TI Analog Shield

As part of its microcontroller course, Stanford University required a platform to sample and generate analogue signals. The Standford – TI Analog Shield arose from this need.

The Analog Shield contains a Texas Instrument quad channel ADC and a quad channel DAC, together with a variable voltage supply. I have not tested the ADC.

The DAC capability is based on a Texas Instrument DAC8564 device. This device has many interesting features, including the ability to synchronise loading of updated digital outputs, and to maintain multiple power-down states. The DAC8564 has many great features, and it comes with a price tag to match its capabilities.

P1010273

Analog Shield – Quad 16bit DAC & Quad 16bit ADC – Stanford University & Texas Instruments

Signals generated by the DAC8564 (from 0v to 2.5V) are biased around 0V and amplified to produce a 10V full swing output. The output exhibits some “cramping” around 0x0000 (-5V) outputs.

AS_Schematic_RevD

Analog Shield – Quad DAC Schematic – -5V to +5V full swing

Head to Head

Testing was done using a 16 bit 1024 sample Sine Wave file. Outputs were generated by a timer triggered to interrupt every 22.7us (44.1kHz), and produce a new output level. Testing should show only a main signal at 43.1Hz, and the reproduction frequency of 44.1kHz. The Goldilocks Analogue discards the lower 4 bits of the samples and only outputs the 12 most significant bits.

Theoretically, the Goldilocks Analogue MCP4822 DAC should be able to achieve 74dB SNR, with its 12 bits of resolution, based on the rule of thumb SINAD = (6.02 x BITS) + 1.76. For the Analog Shield DAC8564 the number is 98db SNR.

P1010270

Head to Head Testing – Using Red Pitaya and Saleae Logic

All outputs generated by a 1024 sample 16bit Sine wave, generated with a 44.1kHz reconstruction sample rate, triggered by an interrupt timer.

GA_43.1Hz

Goldilocks Analogue – 43Hz Sine Wave – Two Channels – One Channel Inverted

AS_43.1Hz

Analog Shield – 43Hz Sine Wave – Two Channels – One Channel Inverted

In previous testing on the Goldilocks Analogue prototype I had found that my OpAmp devices were unable to achieve 0V properly. In this new prototype I have produced a stable -1.186V Vss supply for the OpAmp. The signals at 0x000 show that I’ve achieved the required result, with the output being smooth down to the 0x000 level, and up to 0xFFF as well.

GA_43.1Hz_4V

Goldilocks Analogue – 0xFFF Output

GA_43.1Hz_0V

Goldilocks Analogue – 0x000 Output

The Analog Shield also produces smooth signals, but it does display some compression around 0x0000 levels. Possibly because of some issues with generating the Vss rail for the OpAmps.

AS_43.1Hz_+5V

Analog Shield – 0xFFFF Output

AS_43.1Hz_-5V

Analog Shield – 0x0000 Output – Slight Clipping

Looking at the spectra generated by both implementations up to 953Hz it is possible to see harmonics from the Sine Wave, and other low frequency noise.

The spectra are not directly comparable, because the Goldilocks Analogue is producing a 4V full swing, or -4dBm, whilst the Analog Shield is producing a 10V full swing, or 3.7dBm. Distortions in the Analog Shield need to be reduced by 7.7dB to be equivalent to distortion in the Goldilocks Analogue.

The spectrum produced by the Goldilocks Analogue shows most distortion is below -70dB, and that the noise floor lies below -100dB.

GA_43.1Hz_953Hz

Goldilocks Analogue – 43.1Hz Sine Wave – 953Hz Spectrum

The Analog Shield has a significant noise present at 50Hz, which may be caused by noise leakage through the PC USB power supply not being completely filtered before the supply is provided to the DAC8564. Other noise rises above -80dB, and is present right across the spectrum.

AS_43.1Hz_953Kz

Analog Shield – 43.1Hz Sine Wave – 953Hz Spectrum

In the spectra out to 7.6kHz we are looking at the clearly audible range, which is the main use case for the devices.

The Goldilocks Analogue has noise carriers out to around 4.5kHz, but they are all below -80dB. After 4.5kHz the only noise remains below -100dB.

GA_43.1Hz_7.6kHz

Goldilocks Analogue – 43.1Hz Sine Wave – 7.6kHz Spectrum

The Analog Shield shows noise carriers out to only 2.5kHz, but on one channel these are above -80dB. Otherwise the test shows mainly background noise below -100dB beyond 2.5kHz.

AS_43.1Hz_7.6kHz

Analog Shield – 43.1Hz Sine Wave – 7.6kHz Spectrum

The spectra out to 61kHz should show a noise carrier generated by the reconstruction frequency of 44.1kHz.

The Goldilocks Analogue shows the spectrum maintains is low noise level below -90dB right out to the end of the audible range, and further out to the reconstruction carrier at 44.1kHz.

GA_43.1Hz_61kHz

Goldilocks Analogue – 43.1Hz Sine Wave – 61kHz Spectrum

Similarly, the Analog Shield is quiet out beyond the audible range. It exhibits a strong noise carrier at the reconstruction frequency. Also, it shows some beat frequencies generated by a small noise carrier at 10kHz, and the reconstruction carrier. These noise carriers might be caused by the TPS61093 boost power supply used to generate the +ve and -ve supplies for the output buffer OpAmps, although it has a characteristic frequency at 1.2MHz, or it might be leakage from some other device.

AS_43.1Hz_61kHz

Analog Shield – 43.1Hz Sine Wave – 61kHz Spectrum – Harmonics around 44.1kHz reconstruction frequency

The final two spectra show the signal out to 976kHz. We’d normally expect to simply see the noise floor, beyond the 44.1kHz reconstruction carrier noise.

The Goldilocks Analogue has a noise carrier at around 210kHz. This could be generated by one or both of the TPS60403 devices used to generate the negative AVss supply. These devices have a typical switching frequency of 250kHz, specified between 150kHz and 300kHz, so this is possible. Aside from the single carrier mentioned, there is no further noise out to 976kHz.

GA_43.1Hz_976kHz

Goldilocks Analogue – 43.1Hz Sine Wave – 976kHz Spectrum

The Analog Shield shows the reconstruction carrier noise at -50dB, and then harmonics of this carrier all the way out to 976kHz. Not sure why these artifacts are appearing. There is a chance that noise derived from these signals is impacting the overall outcome for the DAC8564.

AS_43.1Hz_976kHz

Analog Shield – 43.1Hz Sine Wave – 976kHz Spectrum

Using the Saleae Logic we can capture the SPI transactions generating the analogue result. To maintain the 44.1kHz reconstruction rate a set of samples needs to be transferred every 22.7us.

In the code I’ve used to generate the signal an interrupt timer triggers every 22.7us indicated by the rising edge of “Channel 6”. Once the interrupt has finished processing it lowers the Channel 6 line, indicating that control has returned to the main program. If required the main program has to use the remaining time to generate the required signal. Clearly the faster the SPI transaction to set up the transaction can be completed the more time available for other purposes.

The MCP4822 found in the Goldilocks Analogue has 4 control bits and 12 data bits, which are transferred in 2 8 bit transactions. To set two channels only 4 SPI transactions are required, taking 7.25us.

GA_43.1Hz_44.1kHz_sample_SPI_transaction

Goldilocks Analog SPI transaction – Interrupt duration 7.25us

The DAC8564 used in the Analog Shield has 8 control bits and 16 data bits, which are transferred in 3 8 bit transactions, or 24 SPI clock cycles. For two channels this takes 6 SPI transactions and 9.08us.

Both devices leave sufficient time for calculation of simple VCO, or other multiply based, effects in real time with 44.1kHz dual channel. Halving the sample rate to 22.05kHz would be necessary to provide more opportunity to retrieve data from uSD cards or other more complex data sources.

AS_43.1Hz_44.1kHz_sample_SPI_transaction

Analog Shield SPI Transaction – Interrupt duration 9.083us

The final reality check in this Head-to-Head comparison is provided by Digikey. I must say that some of the features of the DAC8564 had convinced me to look at migrating the production Goldilocks Analogue to use this new TI DAC. However, seeing that the BOM cost for the TI DAC is approximately 4 times greater than the MCP4822 device soon cooled those thoughts.

Given the cost sensitive nature of the Arduino environment it is not practical to use a device costing nearly US$20 on the Goldilocks Analogue platform, irrespective of its performance.

And, given that the Analog Shield provides no justification in terms of signal quality over the existing Goldilocks Analogue solution there seems to be no technical merit in changing the DAC specification, either.

The Microchip MCP4822 is available from US$4.60 at Digikey.

GA_MCP4822_digikey

Digikey MCP4822 Pricing

The Texas Instrument DAC8564 is available from US$18.60 at Digikey.

AS_DAC8564_digikey

Digikey DAC8464 Pricing

Design Review

The remaining features and functions of the Goldilocks Analogue have been tested, and resulting from these tests I’m going to make the following redesigns and changes.

  • Revert to tri-state buffers for uSD I/O logic conversion CMOS 5v to CMOS 3v3 – Bi-directional translators pure fail! I tried both TI TXB and TXS devices and they simply didn’t work as specified.
  • Remove USART pin-out – unnecessary feature and just takes board space.
  • Move DAC pin-out to right hand edge of the prototyping space – easier to use if not covered by UNO format shield. As the Goldilocks Analogue is slightly longer than standard Arduino UNO shields, putting the DAC DC output pins outside the shield outline on the right hand end of the board will allow easier access for connections.
  • Increase prototyping space – fill in space freed by pin-out removals.
  • Use smaller packages where possible – heading for production.
  • Increase bypass capacitors on uSD 3V supply – uSD cards consume significant current, potential for instability because of long 3V3 supply
  • Use a JTAG pin for MCP4822 LDAC – to enable synchronization of the DAC channels.

Ice Tube Clock – Hands Free Mod

Since banning tablets in the bedroom overnight, Miss10 has needed an alarm clock. So, for the last few months we’ve been looking for something suitably cool, and inexpensive.

As it happens, the Adafruit Ice Tube Clock Kit is exactly the right answer. Exactly the right amount of powder blue glow that is needed, matched with undeniable 80’s Russian retro chic.

Ice Tube Clock in use.

Ice Tube Clock in use.

We spent the past few nights building it, doing a bit of three handed soldering, and joint assembly.

As usual, things need to be modified to be truly personal, so we added some special touches that set her clock apart.

Using a 5ppm 32kHz crystal, rather than the provided 20ppm crystal, should keep accuracy within half a second per day (worst case) and only adds a few cents to the build.

Also, it is a bit inconvenient to reach around the back of the clock to read the date and activate the snooze function. So, we added an IR sensor to button 2 (the Set button) to enable these functions with just a hand wave.

Pololu Sharp 10cm IR Distance Sensor is mounted directly on top of the 5V regulator for several reasons.

  • To stay inside the short range null (<2cm) and reflections, the IR sensor needed to be at the front of the housing.
  • To keep the Vacuum Florescent Display seemingly floating in the case, the IR sensor needed to be low profile.
  • To prevent the sensor draining the standby battery, the IR sensor needed to be powered off the main power supply (before the isolation diode).

Using a few carefully bent mounting pins (provided with the IR sensor), it is fairly easy to solder the IR sensor directly onto the legs of the regulator, providing a neat mounting point. The sensor line, generating a low signal when triggered, is run around the end of the PCB and paralleled onto the Switch 2 active pin.

With the IR sensor in place, a hand wave is all it takes to trigger another 10 minutes snooze. Which, on second thought, is probably not such a good idea.

P1010239

Ice Tube PCB Assembled.

 

P1010242

The Ice Tube Clock in service.

Goldilocks Analogue – Prototyping 2

Introduction

Following my initial design article, and the testing article, I’ve put quite a lot of thought into how I can make this Goldilocks Analogue device best achieve my stated goals. Pictured is the only Goldilocks Analogue Prototype in existence.

Goldilocks Analogue - Top Left

Goldilocks Analogue Prototype – Analogue section front of image.

From the testing it was clear that the MCP4822 DAC fully achieved the goals that I had set out to achieve, but that my design for the analogue buffer stage behind it was really quite bad. Fixing it was going to take some thought.

I have decided to separate the analogue output stage into two sections. An AC section which drives the headphone socket, with a designed for purpose headphone amplifier device, and a DC section using a high current rail to rail OpAmp and a negative 1.18V supply rail to allow the OpAmp to fully reach GND or the equivalent 0x000 digital input.

I also found a better solution for the uSD level translation. There is a device designed for purpose, which I’ve now designed into the Goldilocks Analogue.

DAC – MCP4822

The selected dual DAC uses the SPI bus to write 12 bit values to each of its channels. The increments are either 1mV or 0.5mV giving full scale at DC 4.096V or 2.048V depending which scale factor is being used. The testing showed that the DAC is capable of achieving close to the 72dB of SNR that is its theoretical capability.

DAC 43Hz Sine - 7k6Hz

So from my point of view the DAC, and the AVcc filtering system employed to provide a clean analogue power rail, have achieved their design goal. Let’s not change anything.

Headphone (AC) Output – TPA6132A2

Driving a headphone socket with a nominal impedance of 32 ohm is a hard job for an OpAmp, and they are not designed specifically for this job. Therefore, I thought it would be best to separate the two outputs into two separate full-time output devices, specialised for their purposes (AC headphones, and DC PID or general pin-out).  Both Goldilocks Analogue output options are driven simultaneously, and they will not interfere with each other.

GoldilocksAnalogueDACAmplifiers

For the AC and headphone output, using a specific single ended “DirectPath” headphone amplifier device enabled me to remove the large output coupling capacitors but still achieve a good low frequency output response.

The TPA6132A2 is capable of driving 25 mW into 16 ohm headphones. Its amplifier architecture operates from a single supply voltage and uses an internal charge pump to generate a negative supply rail for the headphone amplifier. The output voltages are centred around 0 V and are capable of positive and negative voltage swings. This means that the TPA6132A2 doesn’t need output blocking capacitors, and therefore can achieve a very good low-frequency fidelity. Using the 1 uF input capacitors stops any turn-on pop or noise, and achieves a low frequency corner below 10 Hz.

As the DAC outputs a signal with up to 4 V peak to peak, I have set the gain on the TPA6132A2 to -6dB. This should result in the full range of the headphone signal being 1 V peak to peak, with approximately 25 mW being delivered into 32 ohm headphones.

The TPA6132 also has a very high power supply an RF noise rejection ratio. Although I’ve gone to a lot of effort to filter the AVcc power supply, the power supply noise generated was still significant. Having over 90 dB PSRR will help to keep the output quiet.

Analogue (DC) Output – TS922A

I originally selected a highly regarded audiophile OpAmp for use in the Goldilocks Analogue. That device was incapable of operating close to its GND rail, and caused significant distortion in the output signal. Based on that experience, I decided to use a rail-to-rail output OpAmp to provide the DC buffered signal.

Even though rail-to-rail OpAmp devices are sold as full Vcc to Vss outputs, under high current loading they all have significant output droop. The only way to avoid this is to avoid driving the (any) OpAmp close to its supply rails.

The positive rail is ok. The supply voltage is a well regulated 5 V DC, and the maximum voltage required from the OpAmp is 4.096 V which is 0xFFF input to the DAC. It is the Ground Rail, which causes the issue, as the OpAmp will be unable to deliver the analogue equivalent 0x000 under high current situations.

The only way to get an OpAmp to deliver a solid GND potential output, is to supply it with a negative supply voltage Vss.  Getting a Vss rail is described below.

The TS922A device is designed for high current rail-to-rail outputs, and is specified to work into 32 ohm headphones, 75 ohm video, and 600 ohm inputs. This DC coupled output can be used to drive PID, Triac or any other application requiring a precise analogue signal up to around 50 kHz.

OpAmp Vss (negative) rail

The TS922A can support over 50 mA per channel output, but at this current its output resistance has dropped its ability to reach both rails to greater than 300 mV. Specifically, it can only reach between 0.3 V and 4.4 V. Therefore to enable the output signal to reach GND potential, we have to generate a Vss  with greater than -0.3 V, and capable of supplying in excess of 100 mA (over OpAmp both channels).

I looked at a number of options for charge coupled devices, and decided that the cheapest and best way was to use two paralleled TPS60403 devices to each generate -5 V 60 mA from the 5V power rail. These devices don’t filter their output, but since we are not going to use the -5 V directly, this doesn’t matter.

GoldilocksAnalogueVccNegative

Following the generation of the -5 V supply, I’ve decided on a TPS72301 variable voltage 200 mA linear regulator, configured to generate its reference voltage -1.186 V, to provide a regulated Vss. Using the internal reference voltage saves a few resistors, and it still generates sufficient negative voltage to enable the OpAmp to easily reach true GND potential.

uSD Card Level Translation – TXS0104

Some further analysis of the voltage translation application revealed that the TXS0104 is designed to exactly suit the purpose of interfacing SPI bus at up to 24 MHz. As a side benefit it is a much smaller package, which recovers prototyping space back to the original Goldilocks benchmark. It is also cheaper than the general purpose OpAmps previously used.

Initially, the prototype used the TXB0104 device, but it was unsuccessful. The 4kOhm output resistance combined with less than optimal uSD card characteristics meant that the design failed. The TXB series cannot drive anything with pull-up or pull-down greater than 50kOhm. The uSD card is specified to have 10kOhm to 100kOhm integrated pull-up resistors, but in practice they all seem to be around 10kOhm. The schematic below will be updated to show TXS shortly.

GoldilocksAnalogueTranslate

The PCB Layout

The board layout has been completed, and a PCB ordered to this design.

More detail soon.

GoldilocksAnalogue

Top Signal Layer
GoldilocksAnalogueTopRatsnest

GND Signal Layer
GoldilocksAnalogueRoute2Ratsnest

5V Signal Layer
GoldilocksAnalogueRoute15Ratsnest

Bottom Signal Layer
GoldilocksAnalogueBottomRatsnest

 

 

As of June 2014, I’ve now got all the parts, and the PCB ready for a new prototype. This new version was  constructed late July 2014 and is awaiting basic testing.

Version 2 of the prototype

Version 2 of the prototype, fresh out of the oven.

 

As of August 2014, I have started testing. So far the analogue design seems to check out, with both the headphone (AC biased) circuitry and the OpAmp (DC biased) circuitry performing as intended. More testing soon, and a new post.

Goldilocks Analogue demonstrating a clean DC biased sign wave (to 0V) .

Goldilocks Analogue demonstrating a clean DC biased sign wave (to 0V) .

The spectrum at the output of the TS922A OpAmp is cleaner now than directly at the MCP4822 DAC output of the previous prototype iteration.

The nominal 12 bit DAC capabilities are able to achieve 72dB SNR. Target achieved.

Spectrum at the output of the OpAmp.

Spectrum at the output of the OpAmp.

Goldilocks Analogue – Testing

Introduction

This post follows on from the and gives some insight into the results of the first board prototype board assembled.

Updated - Goldilocks Analogue

Updated – Goldilocks Analogue

The information will develop over the next few weeks, as I add more information and test results.

I’ve built a new Goldilocks Analogue design and I have described the changes and additions.

Discussion

Well I’ve had my  Goldilocks Analogue on my desk now for a few nights, and I’m very impressed that it seems to generally meet the specification that was intended.

The code for setting the DAC levels is currently only optimised for setting two values at a time. Specifically, it is not a streaming function. Never-the-less, it is possible to achieve the stated goal for both DAC channels. The actual number achieved is 108 kSamples/second, shown below, or 18.8us to transmit 2 samples on 2 channels.

I’ve been testing the Goldilocks Analogue DAC stage and found (what I should have known) that I needed an output buffer op-amp able to do negative rail (0V) input and output to support the MCP4822 0v to 4.095V ranging DAC, so I’m going to order some soon.

Unfortunately the OPA4350 (rail to rail high current), at over $10 each, is nearly as expensive as the audiophile OPA4132 I specified previously.

There seems to be a pin compatible alternative, the TS924A, which is about $2 each, but several orders of magnitude worse in performance.

For Example: OPA4350 vs TS924A
Gain Bandwidth Product: 38MHz vs 4MHz
Slew Rate: 22V/μs vs 1.3V/μs
Total Harmonic Distortion: 0.0006% vs 0.005%

Is it worth the difference, when working with a 12 bit DAC in the presence of mV of power supply noise? I’ll revisit this with the next design notes.

How about 5V?

To build an effective DAC I’ve learned that we need to have an effective quiet 5V power supply, with as little noise as possible. To put this into context, the 12 bit MCP4822 generates a 1mV per level difference. I noticed there is quite a few mV of noise on the 5V supply of the Goldilocks Analogue. Not what I was hoping to see, so I’ve gone back to see how that compares with predecessors.

All measurements are taken with a 100MHz Rigol DS1102E, with 150MHz probes grounded onto the USB socket of each board respectively. The probes are directly on the regulator output capacitor, which should be the quietest point on the board, and then directly off Vcc on the MCU for the DIL boards, or a nearby test point for the SMD boards.

First stop is a reference design Arduino Uno R2 board. As a starting point the Uno shows 16mV on the power supply, and 35mV on the MCU. Let’s see how some other boards compare.

Arduino_Uno

Arduino Uno

The Freetronics Eleven board also uses a linear regulator, similar (if not identical to) the Arduino Uno. However the capacitor arrangement must be somewhat more effective because the noise present on the output capacitor is less than 6mV. This is significantly better than on the Arduino Uno, and even measured against the Vcc pin the supply noise remains significantly lower than the Uno.

This Freetronics Eleven board was running at 22.1184MHz rather than the standard Arduino speed, but that doesn’t seem to affect the result.

Freetronics_Eleven

Freetronics Eleven

Next up is the Seeed Studio ADK boards is an ATmega2560 board running at 16MHz, which also uses a linear regulator. The ADK board exhibits the same quiet supply found in the Freetronics Eleven, and has very similar characteristics on the Vcc test point as well.

Seeed_ADK

Seeed Studio ADK

The Goldilocks v1.1 resulting from the Pozible project is my true point of reference. I hope to be able to do slightly better than this board, by better layout of the same SMPS circuit that is used across all of the Freetronics range of products.

In measurement, the Goldilocks v1.1 sets a very high standard to surpass. Even though there is a 500kHz SMPS running in the supply, the Vcc supply capacitor shows very low noise of only 5.29mV, and the Vcc noise on the test point is only 12.0mV.

GoldilocksV1

Goldilocks V1.1

The Goldilocks Analogue Prototype 1 uses the same SMPS circuit present across the entire range of Freetronics boards, but using an optimised (for this application) layout. Shorter internal tracks should result in slightly faster smoothing, and better regulation, although the effect at normal currents would be minimal.

In comparison with the  Goldilocks v1.1, there seems to be slightly less noise at the supply capacitor with less than 5mV showing, although this effect is marginal. The noise on the Vcc line seems to be similar.

Goldilocks_Analogue

Goldilocks Analogue Prototype 1

SMPS

Having looked at the power supplies at rest, and built a baseline of what to expect, here are some screenshots of the Goldilocks SMPS under load. Port D is being switched from 0x00 to 0xFF at 30kHz. The first screenshot shows one of the Port D pins on channel 1, and the Vcc (5V) line at the supply capacitor on channel 2. Note that there is 24mV of noise on the Vcc supply capacitor, even without drawing much current.

GoldilocksAnalogue_NoLoad_Vcc

This second screenshot shows the same set up, but with 8 LEDs being driven off the Port D. Channel 2 shows the variation in supply capacitor Vcc under the increased load.

GoldilocksAnalogue_8LED_Vcc_Macro

So the big question is whether the new layout of the SMPS has achieved anything. Well, based on this simple test, it would seem to have generated a fairly significant improvement.

The below two screenshots shows the trailing edge of the 8 LED power load being switched off. Note that on the supply Vcc there is some oscillation and instability as the SMPS recovers from the load reduction.

This first screenshot shows the Goldilocks V1.1 situation, with a ripple of 832mV peak to peak.

GoldilocksV1_8LED_Vcc_Micro

With the Goldilocks Analogue, the peak to peak ripple is reduced to under 600mV, which is a 25% improvement in this situation.

GoldilocksAnalogue_8LED_Vcc

Sine Waves

I’m using my new Red Pitaya to analyse the output of the Goldilocks Analogue output state, with a 43.066Hz Sine wave (1024 samples played out at 44.1kHz) as the input to the DAC.

MCP4822 DAC

This shows the sine wave generated at the output of the low pass filter (23kHz -3dB single pole design). This is almost exactly as we would like to see.
Post Filter 43Hz Sine - Oscilloscope
Looking at the lower segment of the sine wave below and the image above, it is almost perfect to 0V and to 4.096V peak to peak.
Post Filter 43Hz Sine - Oscilloscope Segment
Looking at this sine wave on the spectrum analyser across the band up to 7.6kHz, we can see the noise floor is 70dB down from the signal exiting the DAC. It seems the DAC performs as advertised.
DAC 43Hz Sine - 7k6Hz
Looking across the band to 61kHz, we can see the peak at -70dbm from the 44.1kHz sampling noise. Unfortunately, the single pole filter doesn’t do much to suppress this noise source.
DAC 43Hz Sine - 61kHz
To get an idea of whether the 23kHz filter is working as expected, we need to look out to the 976kHz band. The next two images contract the signal before and after the Filter.
DAC 43Hz Sine - 976kHz

The lower image shows that noise peaks out to 200kHz have been properly suppressed, so the filter is working but it is too slow to hit the 41kHz noise.

Post Filter 43Hz Sine - 976kHz

Op Amps

The Op Amp selection was a mistake. Rather than thinking about the application correctly, I simply sought out the best “musical” Op Amp. The audiophile OPA4132 is absolutely not the right tool for this job. And these images show why.

Driving into a 1kOhm resistance, the output of the OPA4132 is shaved off as the op amp output amplifier saturates as it approaches the 0V rail (or Ground rail). The top of the waveform is OK, as we are still 1V from the Vcc rail. Under higher loading, such as headphones at 32Ohm, the signal is worse, much worse.

OpAmp 43Hz Sine - 1kOhm - Oscilloscope

Looking at this (initially as an open circuit) view and then with the 1kOhm loading imposed, we can see the difficulty the op amp has with the signal.

OpAmp 43Hz Sine OpenCircuit - 953Hz

The noise peaks (created by the flattening of the sine wave) are at least 10dB greater under a small load. As the load increases the situation gets worse.

OpAmp 43Hz Sine 1kOhm - 953Hz

OpAmp 43Hz Sine 1kOhm - 7k6Hz

OpAmp 43Hz Sine 1kOhm - 61kHz

To fix this issue, I will need to use a rail to rail high current op amp, and also make sure that I create a small negative rail (-o.23V using a LM7705) to allow the op amp to reach 0V effectively.

Amongst the Burr Brown range the best alternative seems to be the OPA2353, which can support almost 40mA of current, and can effectively drive 75Ohm loads. Unfortunately the OPA2353 (rail to rail high current) costs about $6 each,

There seems to be a pin compatible alternative, the TS922A, which is about $2 each, but several orders of magnitude worse in performance. However, it can supply 80mA and effectively drive 32Ohm headphones.

For Example: OPA2353 vs TS922A
Gain Bandwidth Product: 44MHz vs 4MHz
Slew Rate: 22V/μs vs 1.3V/μs
Total Harmonic Distortion: 0.0006% vs 0.005%

Errata

Reset button can be moved closer to the edge.

AVcc supply capacitors are too close together, and need to have bigger pads.

Use the DAC out header spare pin to pin-out the AVcc, for testing or use on prototyping area.

AVcc inductor is not correct footprint (device much larger).

AVcc ferrite bead is not correct footprint (device much smaller).

Remove analogue potentiometers, unnecessary as DAC is extraordinarily accurate.

Put pin-out on DC output, and headphone socket on AC output 100uF capacitors.

Replace Analogue Op Am with LM7705 and TS922A. This generates 0V to 4.096V required to properly buffer the MCP4822 DAC. LM7705 can’t sustain 80mA, but for small DC signals (up to 20mA) we will have accurate buffering of the DAC, and for headphones, it is an analogue signal anyway.

Replace uSD Op Amps with TXB0104, more suitable for the purpose.

These errata have been addressed in the new Goldilocks Analogue design and I have described the changes and additions.

Gameduino 2 with Goldilocks and EVE

My Gameduino 2 was delivered just a few weeks ago, and I’ve spent too much time with it already. It is the latest Kickstarter project by James Bowman. James has written a Gameduino 2 Book too.

Sourcecode for the below examples is located at GitHub AVRfreeRTOS lib_ft800 and the application is located at GA_Synth.

Recently, I’ve used the Gameduino 2 together with the Goldilocks Analogue to implement a multi-oscillator audio synthesizer GUI, using many FTDI EVE GPU co-processor widgets. The use of widgets linked with the integrated touch functionality really simplifies the programming of complex GUIs.

The ability to add a large touch screen, with integrated audio and accelerometer to any Arduino project is a great thing. Previously, you had to move to 32 bit processors with LVDS interfaces to work with LCD screens, but the new FT800 EVE Graphical Processing Unit (GPU) integrates all of the graphic issues and allow you to drive it with a very high level object orientated graphics language. For example it takes just one command to create an entire clock face with hour, minute, and second-hands.

The Gameduino 2, via the FT800 EVE chip, provides the following capabilities:

  • 32-bit internal color precision
  • OpenGL-style command set
  • 256 KBytes of video RAM
  • smooth sprite rotate and zoom with bilinear filtering
  • smooth circle and line drawing in hardware – 16x antialiased
  • JPEG loading in hardware
  • audio tones and WAV audio output
  • built-in rendering of gradients, text, dials, sliders, clocks and buttons
  • intelligent touch capabilities, where objects can be tagged and recognised.

The FT800 runs the 4.3 inch 480×272 TFT touch panel screen at 60 Hz and drives a mono headphone output.

EVE Block Diagram

First off, there’s a demo of some of the capabilities of the Gameduino 2. I’ll come to the drivers later, but the Arduino compatible platform used here is the Goldilocks ATmega1284P from Freetronics. The Goldilocks is in my opinion the best platform to use with the Gameduino 2. Firstly there is the extra RAM and Flash capabilities in line with the ATmega1284p MCU. But also importantly the Goldilocks holds the Pre-R3 Arduino Uno connector standard, with the SPI pins located correctly on Pins 11, 12, and 13. And the INT0 interrupt located on Pin 2. This means that it can be used with the Gameduino 2, out of the box. No hacking required.

The Goldilocks Analogue is an upgraded replacement for the original Goldilocks, with many additional features. Thank you for pledging on the Goldilocks Analogue Kickstarter Project page, which was successfully closed on November 19th 2015, with 124% funding. Now that the Kickstarter pledges have been shipped, the new Goldilocks Analogue is now available on Tindie.

I sell on Tindie

Must be addicted to these touch screens. I’ve just received an Australian designed 4D Systems FT843 Screen. It has possibly an identical screen to the Gameduino 2, but is based on a R3 Arduino shield format (SPI on ICSP) called the ADAM (Arduino Display Adapter Module), which means that it will work on any current Arduino hardware, without hacking. The FT843 ADAM supports a RESET line, which resolves the only problem I’ve noted with the Gameduino 2. Unfortunately, audio is not supported by a 3.5mm jack but rather by a pin-out option. The FT843 uses Swizzle 0, unlike the Gameduino 2 which uses Swizzle 3, and has the Display SPI Select on either D9 or D4 rather than on D8 like the Gameduino 2. Other than these simple configuration options, it similar.

4D Systems FT843 on Goldilocks 1284p

4D Systems FT843 on Goldilocks 1284p

Demo

The screen shows 5 sets of demonstrations. These demos are provided by FTDI, and typically in an Arduino Uno you would have to choose which of the 5 sets you want to see. With the extra capabilities of the Goldilocks, it is possible to load all of them simultaneously in 110kB of flash.

Set 0 focusses on individual commands that are loaded into the Display List. The Display List is essentially a list of commands that is executed or rendered for each frame of display. A Display List will be rendered indefinitely, until it is swapped by another Display List. Two Display Lists are maintained in a double buffering arrangement. One is written, whilst the other is displayed.

Set 1 exhibits some of the co-processor command capabilities, that allow complex objects to be created with only one command. A clock, slider, dial, or a rows of buttons can be created easily in this manner.

Set 2 shows the JPEG image rendering capabilities in RGB and in 8 bit mono.

Set 3 demonstrates custom font capabilities. There are 16 fonts available in the ROM of the FT800 EVE, but you can add your own as is desired.

Set 4 shows some advanced co-processor capabilities, such as touch tag recognition, no touch (zero MCU activity) screensaver, capturing screen sketches, and inbuilt audio options.

The main screen shows an analogue clock that is drawn with one co-processor command. Real time is generated by a 32,768Hz Crystal driving the Goldilocks Timer 2 for a system clock. The accuracy of the clock is limited only by the accuracy of the watch crystal, and I’ve built mine with a 5ppm version, which should be enough to keep within a few seconds per month.

Sample Application

The FTDI provided sample application covers most of the available commands and options for the FT800 EVE GPU.

The FT_SampleApp.h file contains definitions of functions implemented for the main application. These code snippets are not really useful beyond demonstrations of capability of the GPU, but never the less demonstrate how each specific feature of the FT800 EVE GPU can be utilised.

Driver

Because the FT800 EVE GPU has a very capable object orientated graphics language, the FTDI drivers present a very capable high level interface to the user. FTDI have prepared an excellent starting point from which I could easily make customisations suitable for the AVR ATmega Arduino hardware that I prefer to use.

The FTDI driver set is separated into a Command Layer, and into a Hardware Abstraction Layer (HAL). This separation makes it easy to customise for the AVR ATmega platform, but retains the standard FTDI command language for easy implementation of their example applications, and portability of code written for their command language.

To use the FT800 EVE drivers for the Gameduino 2 it is only necessary to include the FT_Platform.h file in the main program. This file contains references to all of the other files needed.

#include "../lib_ft800/FT_DataTypes.h"
#include "../lib_ft800/FT_X11_RGB.h"
#include "../lib_ft800/FT_Gpu.h"
#include "../lib_ft800/FT_Gpu_Hal.h"
#include "../lib_ft800/FT_Hal_Utils.h"
#include "../lib_ft800/FT_CoPro_Cmds.h"
#include "../lib_ft800/FT_API.h"

The FT_DataTypes.h file contains FTDI type definitions for the specific data types needed for the FT800 EVE GPU. This is mainly used to abstract the drivers for varying MCU. For the AVR it is not absolutely necessary, but it will help when the code is used on other platforms.

The FT_X11_RGB.h file contains the standard colour set used in X11 colours and on the Web, which are stored PROGMEM. I’ve written a small macro that will insert these into commands needing 24 bit colour settings. These colours will be stored and referenced from PROGMEM when they are called from either of the X11 specific macros defined in FT_Gpu.h If they are not called from the program, they will be discarded by the linker and not waste space in the final linked program.

X11 Colours

The FT_Gpu.h file contains all the definitions for command and register setting options. I have significantly rearranged the layout and comments in this file, compared to the FTDI version. Hopefully it is arranged in a way that allows options applying to specific commands and registers to be quickly located.

By writing DL commands to the Display List which are configured by the options in the FT_Gpu.h file it is possible to control most of the low level functions in the FT800 EVE GPU. The Display List is used by the FT800 GPU to render the screen, so it is only the contents of the active Display List that appear on the screen.

In the FT_Gpu_Hal.h file the commands specific to the SPI bus (or the I2C bus if this transfer mechanism is being used) are defined.

I have simplified out some HAL options provided by FTDI for high performance MCU, that might be constrained writing to the SPI bus at only 30MHz, the maximum FT800 SPI bus rate. The Goldilocks SPI bus only runs at 11MHz, and the standard Arduino Uno SPI bus only runs at 8 MHz, so those optimisations don’t help, and they also consume RAM for streaming buffers.

But, I have integrated a multi-byte SPI transfer into the HAL, which don’t use additional RAM buffer space, as they write via a pointer. This is probably the best way to work the SPI bus in the Arduino environment. I have also implemented multi byte SPI transfer directly from the PROGMEM for Strings, and for precomputed commands.

As a preferred option, I’ve implemented PROGMEM storage of Strings for all commands. The commands utilising RAM storage of Strings are retained for compatibility, and to allow computed Strings to be used.

All of the FTDI provided commands now have optional *_P variants which take PROGMEM strings, rather than RAM strings. This saves eleven hundred bytes of RAM used for strings, just in the demonstration programs provided by FTDI and shown in the Demo!

The FT_Hal_Util.h file contains some simple utility macros.

The FT_CoPro_Cmds.h file contains definitions for all of the available co-processor commands. These command are written to the co-processor command buffer, and are used to generate low level commands that appear in the Display List and be rendered for each frame.

Many of the co-processor commands replicate functionality of setting specific registers with options via the Display List GPU commands. This is useful because it is possible to programme the co-processor to implement a task and remain at the object orientated view of the screen, even though the a individual command may be a simple GPU setting that could have been done at Display List command level. Having all the commands available at co-processor level obviates the need to switch between the two “modes” of operation and thought.

I extracted a few of the standard functions that are needed irrespective of the specific application into an API. The FT_API.h file contains these simple command sequences, for booting up the Gameduino 2, and for managing the screen brightness. It also contains precalculated simplified sin, cos, and atan functions useful when drawing circles and clocks.

The API level also contains calls on the Hardware Abstraction Layer that are simply passed through. These calls are flattened by avr-gcc to save digging ourselves into a stack wasting function call hole.

And, of course, everything is integrated into the freeRTOS v8.0.0 port that I support on Sourceforge, AVRfreeRTOS, which gives non-blocking timing, tasks, semaphores, queues, and all aspects of freeRTOS that are so great.

As an example of the power of this combination of freeRTOS and the FT800 object orientated command language we can describe the method used to create an accurate well rendered clock on the Gameduino 2 screen. Using the 3 commands below, we obtain the clock face seen in my demo video main screen.

time(&currentTime); // get a time stamp in current seconds elapsed from Midnight, Jan 1 2000 UTC (the Y2K 'epoch'), as maintained by freeRTOS.
localtime_r(&currentTime, &calendar); // converts the time stamp pointed to by currentTime into broken-down time in a calendar structure, expressed as Local time.
FT_GPU_CoCmd_Clock(phost, FT_DispWidth - (FT_DispHeight/2), FT_DispHeight/2, FT_DispHeight/2 - 20, OPT_3D, calendar.tm_hour, calendar.tm_min, calendar.tm_sec, 0); // draw a clock in 3D rendering.

I’ve updated the clock function to include a touch screen time setting interface. Using the FT800 Touch Tags, and Button generation, this process is really incredibly easy.

Hardware

I’ve taken the liberty of borrowing some of James’ pictures for this story. They can originally be found here.

Gameduino 2 Pinout

Note that because of the wrap around connector and cable for the LCD screen, it is not possible to use the Arduino R3 pin out. The SPI bus pins are located at the traditional location on Pin 11 though Pin 13. Unless you want to hack your board, you’re limited to using Arduino Uno style boards.

Gameduino 2 Shield

Unfortunately, the FTDI FT800 Reset pin has not been implemented by the Gameduino 2. Using an ISP to programme the Arduino usually “accidentally” puts the FT800 EVE GPU into an unsupported state. This means that the Gameduino 2 and Arduino usually have to be power-cycled or hard Reset following each programming iteration. It would have been good to tie the FT800 Reset pin to the Arduino Reset pin via a short (ms) delay chip, to obviate the need to remove power to generate the hard Reset for the FT800.

Hello World & other examples

I thought it might be interesting to compare the code required to achieve the demonstration outcomes that James Bowman provides on the Gameduino2 site, with the code required to achieve the same result using freeRTOS and the FTDI style driver. So I’ve implemented three simple examples, “Hello World”, “Sprites”, and “Blobs” from his library.

All of the examples have been built using an Arduino Uno ATmega328p as the MCU hardware platform.

helloworld

The Hello World application simply initialises the Gameduino2, sets the colour to which the screen shall be cleared, and then writes text with the OPT_CENTER option to center it in the X and Y axis. As there is no delay, this is written as often and as fast as the MCU can repeat the loop.

#include 
#include 

void setup()
{
  GD.begin();
}

void loop()
{
  GD.ClearColorRGB(0x103000);
  GD.Clear();
  GD.cmd_text(240, 136, 31, OPT_CENTER, "Hello world");
  GD.swap();
}

The same result can be generated in C using freeRTOS and the FTDI Drivers. I have commented extensively within the code below.

/* freeRTOS Scheduler include files. */
/* these four header files encompass the full freeRTOS real-time OS features,
   of multiple prioritised tasks each with their own stack space, queues for moving data,
   and scheduling tasks, and semaphores for controlling execution flows */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"

/* Gameduino 2 include file. */
#include "FT_Platform.h"

/*------Global used for HAL context management---------*/
extern FT_GPU_HAL_Context_t * phost;           // optional, just to make it clear where this variable comes from.
                                               // It is automatically included, so this line is actually unnecessary.

/*--------------Function Definitions-------------------*/

int main(void) __attribute__((OS_main));       // optional, just good practice.
                                               // Saves a few bytes of stack because the return from main() is not implemented.

static void TaskWriteLCD(void *pvParameters);  // define a single task to write to Gameduino 2 LCD.
                                               // typically multiple concurrent tasks are defined,
                                               // but in this case to replicate the Arduino environment, just one is implemented.

/*-----------------Functions---------------------------*/
/* Main program loop */
int main(void)
{
  xTaskCreate(            // create a task to write on the Gameduino 2 LCD
       TaskWriteLCD
    ,  (const portCHAR *)"WriteLCD"
    ,  128                // number of bytes for this task stack
    ,  NULL
    ,  3		  // priority of this task (1 is highest priority, 4 lowest).
    ,  NULL );

  vTaskStartScheduler();  // now freeRTOS has taken over, and the pre-emptive scheduler is running.
}

 

/*-----------------------------------------------------------*/
/* Tasks                                                     */
/*-----------------------------------------------------------*/

static void TaskWriteLCD(void *pvParameters) // A Task to write to Gameduino 2 LCD
{
  (void) pvParameters;

  FT_API_Boot_Config();  // initialise the Gameduino 2.

  while(1)               // a freeRTOS task should never return
  {
    FT_API_Write_CoCmd( CMD_DLSTART );                       // initialise and start a Display List
//  FT_API_Write_CoCmd( CLEAR_COLOR_RGB(0x10, 0x30, 0x00) ); // set the colour to which the screen is cleared (using RGB triplets) as in GD2 library OR
    FT_API_Write_CoCmd( CLEAR_COLOR_X11(FORESTGREEN) );      // set the colour to which the screen is cleared (using X11 colour definitions)
    FT_API_Write_CoCmd( CLEAR(1,1,1) );                      // clear the screen

    FT_GPU_CoCmd_Text_P(phost,FT_DispWidth/2, FT_DispHeight/2, 31, OPT_CENTER, PSTR("Hello world"));
      // write "Hello World" to X and Y centre of screen using OPT_CENTER  with the largest font 31
      // The string "Hello world" is stored in PROGMEM
      // Functions with *_P all use PROGMEM Strings (and don't consume RAM)
      // FT_DispWidth and FT_DispHeight are global variables set to orientate us in a flexible consistent way,
      // without hard coding the screen resolution.

    FT_API_Write_CoCmd( DISPLAY() );                         // close the Display List (DL) opened by CMD_DLSTART()
    FT_API_Write_CoCmd( CMD_SWAP );                          // swap the active Display List (double buffering), to display the new "Hello World" commands written to the Display List
  }
}

sprites

The Sprites application is similar to the original one built for the Gameduino, but here each sprite is rotating around a random point. The 2001 random points are stored in a PROGMEM array sprites. This takes 8K of flash. A second PROGMEM array circle holds the 256 XY coordinates to make the sprite move in a circle. The only RAM used is a single byte t used to keep track of the current rotation position, by counting iterations.

#include 
#include 
#include 

#include "sprites_assets.h"

void setup()
{
  GD.begin();
  GD.copy(sprites_assets, sizeof(sprites_assets));
}

static byte t;

void loop()
{
  GD.Clear();
  GD.Begin(BITMAPS);
  byte j = t;
  uint32_t v, r;

  int nspr = min(2001, max(256, 19 * t));

  PROGMEM prog_uint32_t *pv = sprites;
  for (int i = 0; i < nspr; i++) {
    v = pgm_read_dword(pv++);
    r = pgm_read_dword(circle + j++);
    GD.cmd32(v + r);
  }

  GD.ColorRGB(0x000000);
  GD.ColorA(140);
  GD.LineWidth(28 * 16);
  GD.Begin(LINES);
  GD.Vertex2ii(240 - 110, 136, 0, 0);
  GD.Vertex2ii(240 + 110, 136, 0, 0);

  GD.RestoreContext();

  GD.cmd_number(215, 110, 31, OPT_RIGHTX, nspr);
  GD.cmd_text( 229, 110, 31, 0, "sprites");

  GD.swap();
  t++;
}

The code in freeRTOS is similar. I have commented within the code.

/* freeRTOS Scheduler include files. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"

/* Gameduino 2 include file. */
#include "FT_Platform.h"

// The include file containing the sprite graphics, and the special command sequence
#include "sprites_assets.h

/*------Global used for HAL context management---------*/
extern FT_GPU_HAL_Context_t * phost;           // optional, just to make it clear where this variable comes from

/*--------------Function Definitions-------------------*/

int main(void) __attribute__((OS_main));       // optional, just good practice

static void TaskWriteLCD(void *pvParameters);  // define a single task to write to Gameduino 2 LCD

/*-----------------Functions---------------------------*/

/* Main program loop */
int main(void)
{
  xTaskCreate(             // create a task to write on the Gameduino 2 LCD
    TaskWriteLCD
    ,  (const portCHAR *)"WriteLCD"
    ,  128                 // number of bytes for this task stack
    ,  NULL
    ,  3                   // priority of task (1 is highest priority, 4 lowest).
    ,  NULL );

  vTaskStartScheduler();   // now freeRTOS has taken over, and the pre-emptive scheduler is running
}

 

/*-----------------------------------------------------------*/
/* Tasks                                                     */
/*-----------------------------------------------------------*/

static void TaskWriteLCD(void *pvParameters) // A Task to write to Gameduino 2 LCD
{
  (void) pvParameters;

  uint8_t t = 0;         // iterate over the code for 255 times, before restarting with 256 sprites where t = 0

  FT_API_Boot_Config();  // initialise the Gameduino 2.
  FT_GPU_HAL_WrCmdBuf_P(phost, sprites_assets, sizeof(sprites_assets));
    // Copy James' magic list of commands into the command buffer.
    // These co-processor commands are "compiled" into their 4 byte equivalents, and I haven't decoded them in detail.
    // But, since the FT800 is reading the same double word codes, it doesn't really matter how they're generated.

  while(1)               // a freeRTOS task should never return
  {
    FT_API_Write_CoCmd( CMD_DLSTART );       // initialise and start a Display List (DL)
    FT_API_Write_CoCmd( CLEAR(1,1,1) );      // clear the screen

    FT_API_Write_CoCmd( BEGIN(BITMAPS) );    // start to write BITMAPS into the DL
    uint8_t j = t;
    uint32_t v;
    uint32_t r;
    int16_t nspr = min(2001, max(256, 19 * t));
    ft_prog_uint32_t * pv = sprites;         //  pv is the sprite BITMAP pointer

    for (uint16_t i = 0; i < nspr; ++i) {
      v = pgm_read_dword(pv++);              // determine which sprite we're controlling
      r = pgm_read_dword(circle + j++);      // circle is the rotation control
      FT_GPU_HAL_WrCmd32(phost, v + r);      // the sprite address and the location are written here to the co-processor
    }
    FT_API_Write_CoCmd( END());              // finish writing BITMAPS into the Display List

    FT_API_Write_CoCmd( BEGIN(LINES) );      // start to write LINES into the Display List
    FT_API_Write_CoCmd( COLOR_RGB(0x00, 0x00, 0x00) );  // set the line colour to black 0x000000
    FT_API_Write_CoCmd( COLOR_A(140) );                 // set alpha channel transparency
    FT_API_Write_CoCmd( LINE_WIDTH( 28 * 16) );
    FT_API_Write_CoCmd( VERTEX2II(240 - 110, 136, 0, 0) );  // start to draw an alpha transparency background line
    FT_API_Write_CoCmd( VERTEX2II(240 + 110, 136, 0, 0) );  // finish the line
    FT_API_Write_CoCmd( END() );             // finish writing LINES into the Display List

    FT_API_Write_CoCmd( RESTORE_CONTEXT() ); // With no prior SAVE_CONTEXT() command, this restores the default colours and values.

    FT_GPU_CoCmd_Number(phost, 215, 110, 31, OPT_RIGHTX, nspr);    // write a number.
    FT_GPU_CoCmd_Text_P(phost, 229, 110, 31, 0, PSTR("sprites"));  // write using a PROGMEM stored string function, to save RAM
      //  phost is a pointer to the context for the Gameduino2.
      //  Mainly used where there may be multiple screens present, but in this case several state and semaphore items are maintained.

    FT_API_Write_CoCmd( DISPLAY() );          // close the active Display List (DL) opened by CMD_DLSTART()
    FT_API_Write_CoCmd( CMD_SWAP );           // Do a DL swap to render the just written DL

    t++;    // t will roll over and will restart the number of sprites to the minimum of 256
  }
}

main2

blobs is a sketching demonstration, as you paint on the touch screen a trail of circles follows.
The code keeps a history of the last 128 touch positions, and draws the transparent, randomly coloured circles.

#include 
#include 
#include 

#define NBLOBS      128
#define OFFSCREEN   -16384

struct xy {
  int x, y;
} blobs[NBLOBS];

void setup()
{
  GD.begin();

  for (int i = 0; i < NBLOBS; i++) {
    blobs[i].x = OFFSCREEN;
    blobs[i].y = OFFSCREEN;
  }
}

void loop()
{
  static byte blob_i;
  GD.get_inputs();
  if (GD.inputs.x != -32768) {
    blobs[blob_i].x = GD.inputs.x << 4;
    blobs[blob_i].y = GD.inputs.y << 4;
  } else {
    blobs[blob_i].x = OFFSCREEN;
    blobs[blob_i].y = OFFSCREEN;
  }
  blob_i = (blob_i + 1) & (NBLOBS - 1);

  GD.ClearColorRGB(0xe0e0e0);
  GD.Clear();

  GD.Begin(POINTS);
  for (int i = 0; i < NBLOBS; i++) {
    // Blobs fade away and swell as they age
    GD.ColorA(i << 1);
    GD.PointSize((1024 + 16) - (i << 3));

    // Random color for each blob, keyed from (blob_i + i)
    uint8_t j = (blob_i + i) & (NBLOBS - 1);
    byte r = j * 17;
    byte g = j * 23;
    byte b = j * 147;
    GD.ColorRGB(r, g, b);

    // Draw it!
    GD.Vertex2f(blobs[j].x, blobs[j].y);
  }
  GD.swap();
}

The code in freeRTOS is similar, but the touch functionality is derived directly from the FT800 register containing the most recent screen touch location. I have commented within the code.

/* freeRTOS Scheduler include files. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"

/* Gameduino 2 include file. */
#include "FT_Platform.h"

#define NBLOBS 128
#define OFFSCREEN -16384

/*———-Global used for HAL management————-*/
extern FT_GPU_HAL_Context_t * phost; // optional, just to make it clear where this comes from

struct xy { // somewhere to store all the blob locations
int16_t x, y;
} blobs[NBLOBS];

/*————–Function Definitions——————-*/

int main(void) __attribute__((OS_main)); // optional, just good practice

static void TaskWriteLCD(void *pvParameters); // define a single task to write to Gameduino 2 LCD

/*—————–Functions—————————*/

/* Main program loop */
int main(void)
{
xTaskCreate( // create a task to write on the Gameduino 2 LCD
TaskWriteLCD
, (const portCHAR *)"WriteLCD"
, 128 // number of bytes for the task stack
, NULL
, 3 // priority of task (1 is highest priority, 4 lowest).
, NULL );

vTaskStartScheduler(); // now freeRTOS has taken over, and the scheduler is running
}

 

/*———————————————————–*/
/* Tasks */
/*———————————————————–*/

static void TaskWriteLCD(void *pvParameters) // A Task to write to Gameduino 2 LCD
{
(void) pvParameters;

FT_API_Boot_Config(); // initialise the Gameduino 2.
FT_API_Touch_Config(); // initialise the FT800 Touch capability.

for (uint8_t i = 0; i > 16) & 0xffff) << 4; // read where x axis touch occurred, and scale it
blobs[blob_i].y = (int16_t)(readTouch & 0xffff) << 4; // read where y axis touch occurred, and scale it
} else {
blobs[blob_i].x = OFFSCREEN; // if there was no touch, draw the blob OFFSCREEN
blobs[blob_i].y = OFFSCREEN;
}
blob_i = (blob_i + 1) & (NBLOBS – 1); // increment to the next blob for touch interaction

// this is the display interface stuff
FT_API_Write_CoCmd( CMD_DLSTART ); // initialise and start a display list (DL)

FT_API_Write_CoCmd( CLEAR_COLOR_RGB(0xe0, 0xe0, 0xe0) );// set the colour to which the screen will be cleared
FT_API_Write_CoCmd( CLEAR(1,1,1) ); // clear the screen

FT_API_Write_CoCmd( BEGIN(POINTS) ); // start to write POINTS into the Display List (DL)

for (uint8_t i = 0; i < NBLOBS; ++i)
{
// Blobs fade away and swell as they age
FT_API_Write_CoCmd( COLOR_A(i << 1) ); // set an alpha transparency
FT_API_Write_CoCmd( POINT_SIZE((1024 + 16) – (i << 3)) );

// Random colour for each blob, keyed from (blob_i + i)
uint8_t j = (blob_i + i) & (NBLOBS – 1);
uint8_t r = j * 17;
uint8_t g = j * 23;
uint8_t b = j * 147;
FT_API_Write_CoCmd( COLOR_RGB(r, g, b) );

// Draw it!
FT_API_Write_CoCmd( VERTEX2F(blobs[j].x, blobs[j].y) );
}

FT_API_Write_CoCmd( END() ); // finish writing POINTS into the active DL

FT_API_Write_CoCmd( DISPLAY() ); // close the active Display List (DL)
FT_API_Write_CoCmd( CMD_SWAP ); // Do a DL swap to render the just written DL
}
}

I intend to build a few more demonstrations of the code, and to copy some games that James has already implemented, because I'm not a game designer.

SATA on UDOO

My SSD and eSATA caddy have arrived. So now we plug it all in and off we go.

Some testing on my amd64 Ubuntu Linux Machine, for comparison with the uSD cards used for the UDOO currently.

The SanDisk Black uSD card behaves in the amd64 machine, just as it did in the UDOO previously.
SanDisk_BlackSD_4GB

Now we test the SanDisk Extreme ii SSD, connected via USB3.0.
SanDisk_Extreme2_USB3

Quite a difference.
If we can get close to this performance in the UDOO, then it will be worth the money spent.

UDOO and SSD Preparation

The guide available on elinux describes all of the steps required for booting the UDOO from the SATA drive.

First prepare a small uSD card to be the boot drive. Format it with one ext3 partition, and install the u-boot bootloader as usual.

sudo dd if=u-boot-q.imx of=/dev/<MICROSD_DEVICE> bs=512 seek=2

This is sufficient to get the UDOO to boot.

Now prepare the SSD, by formatting it in the same way you formatted the uSD previously. I’m now adding an additional linux-swap partition about 2GB in size. Although there are warnings about using SSD for swap, if you’re using a full desktop on your UDOO, your browser won’t respect the memory limitation and you’ll create worse problems.

Although the 8MB free space is not currently used in the SATA SSD, because u-boot is contained on the uSD. My guess is that at some time soon the UDOO team will get the u-boot loadable on the SATA drive, and then this space will be needed.

Once the SSD is prepared, then the fastest way to replicate your already created environment is to copy disk to disk.

cd /media
sudo cp -rp UDOO_SDroot/* UDOO_SSDroot
sudo cp -rp UDOO_SDhome/* UDOO_SSDhome
sync; sync

One final thing is to change the references in the /etc/fstab from

/dev/mmcblk0p1 to /dev/sda1 for /
/dev/mmcblk0p2 to /dev/sda2 for /home
/dev/mmcblk0p3 to /dev/sda3 for swap

Now, plug the SSD caddy into the UDOO, and put the uSD in its slot.

First boot

When first booting the UDOO, interrupt the auto boot process and enter the commands noted in the elinux instructions.
Open a serial terminal to your PC with a baud of 115200 8n1. Reset the UDOO and press any key over serial terminal when prompted to cancel the autoboot. If you miss the prompt, you can press reset on the UDOO.

setenv bootdev "sata init; sata dev 0; ext2load sata 0"
setenv root root=/dev/sda1
saveenv
boot

And the UDOO should boot as normal, but from the eSATA drive.

Note that there can be errors with eSATA / USB3.0 casings. I initially chose one which uses the Prolific PL2773, which implements the attachment as a USB Bulk-Only Mass Storage Class. Unfortunately this storage class doesn’t have the capability to pass TRIM commands.

But, although the attachment for the SSD doesn’t have TRIM capability, the SSD reports that it does have this capability, via eSATA, and this confuses the Kernel.

Errors are caused by the Kernel calling for TRIM on the swap space during the boot process.

How to fix this? Well the simplest way is to throw away the disk casing and connect the SSD drive directly. So, this is what I did. The disk performance also increases markedly too!

UDOO SSD speed testing

The UDOO SATA port doesn’t achieve quite the same throughput as the amd64 desktop does over USB3. But the speed increase over the uSD card is significant, and is very noticeable in use. Worth doing, in any case.
SanDisk_Extreme2_eSATA

After removing the SSD drive from the housing, and driving it directly, the performance increase can be seen. The average read rate has doubled to over 110MB/s and the access time has decreased by a third making it about the same speed as on the amd64 desktop.

In practice the desktop feels even smoother. Great result!
Screenshot from 2013-11-18 23:08:14

UDOO Ubuntu 12.04 Guide

Recently, my Quad core UDOO board arrived in the post. Initially, I tried the two provided uSD cards, with Ubuntu 11.10 and Android 4.2.2. I was a little disappointed that the Android version didn’t seem to work out of the box, but probably I did something wrong. What was more disappointing was that the provided Ubuntu operating system Ubuntu 11.10, is already past End of Life. Releasing a brand new device with an EOL operating system; I’m not sure what the UDOO team (or actually Freescale) are thinking.

Image

Ok, so It is time to go my own way to get something that will remain viable for the long term. I use Ubuntu 12.04 LTS on my machines that aren’t running debian. So it is natural that I’d try the same Ubuntu Precise LTS solution, which is supported through to 2017, on my UDOO board too.

A bit of searching found Dave Cheney, who has written about installing Precise on his UDOO quad. However, Dave assumes that there is a working UDOO Linaro system from which to derive the result. I didn’t have that starting point, so I needed to find a solution from the uSD card inserted into my amd64 (Intel) machine, and build from a chroot armhf on amd64 solution. Fortunately, there are some references for how to take this path too.

Following this initial process, there are quite a few steps to get to a desktop GUI from the very simple Ubuntu core file system starting point, none of which are documented clearly. So, knowing that I’d need to take this path again (after I break something) it is time to write the steps down.

Get all the pieces of code necessary

From the UDOO Downloads page, get the latest versions of U-boot, Kernel, and Kernel Modules, relevant for your UDOO. Either the Quad versions or the Dual versions.

From the Ubuntu Core page, download the ubuntu-core-xx.xx.xx-core-armhf.tar.gz latest version that is there when you read this. At the time of writing it is 12.04.3. I’m led to believe that any recent version of Ubuntu Core would also work (see comments). There’s plenty of opportunity to experiment.

Prepare the uSD Card

Use the largest uSD card that you can find. Also, get the fastest one available at a reasonable price. I have now loaded the system on to a Sandisk Ultra uSD card, and compared the speeds to a Sandisk “Black” card. It is worth getting a “faster” uSD Card for the operating system, but perhaps not especially the “fastest”. The Black card’s performance is quite variable, and particularly the Average Access time ranges from 1.4ms up to 3ms, whereas the Ultra card’s Average Access time is consistently 0.9ms to 1.0ms after repeated testing. The other parameters seem consistently similar.

Black (Class 4 ) Minimum 19.5Mb/s Maximum 22.4Mb/s Average 21.0Mb/s Access 1.5ms
Ultra (Class 10) Minimum 19.6Mb/s Maximum 22.5Mb/s Average 21.0Mb/s Access 0.9ms

I have done some testing with a SATA SSD to compare it with these uSD Cards. If you can use a SSD as the root disk, then you’ll have a much more responsive experience.

Extreme ii SSD Minimum 81.6Mb/s Maximum 124.3Mb/s Average 110.4Mb/s Access 0.2ms

The elinux wiki has instructions for creating a bootable uSD card for UDOO. These are easy to follow, so I’ll not repeat all the details here. Using GParted I only left 8 MByte space before the start of the primary partition, and I labelled it “UDOO”. I also split the card in half, creating a secondary partition for the /home partition. This may take some time to complete, if your uSD is slow…

Image

Image

Before mounting the newly created filesystems, install the U-boot file into the first 8 MByte of the uSD card. Be sure to pick the descriptor for the root of the card (not the first partition). For me <MICROSD_DEVICE> is /dev/sdg.

Be very sure you’ re using the correct device; using the wrong device identifier will result in the loss of all data on the Hard Drive of the host PC used as you will overwrite the MBR.

sudo dd if=u-boot-q.imx of=/dev/&lt;MICROSD_DEVICE&gt; bs=512 seek=2

Create the Filesystem

Mount the just-created root partition on the uSD card. It will appear at /media/UDOO if you chose the same label as suggested. Then extract the tar.gz file containing the file system onto the uSD card with the following command, where <NAME_OF_TAR_FS> is the Ubuntu Core file downloaded previously.

sudo tar -xzvpf &lt;NAME_OF_TAR_FS&gt; -C /media/UDOO/

First, extract the Kernel Modules to the same current folder, and then copy the Kernel file and the Kernel Modules to the uSD.

sudo cp -p uImage /media/UDOO/boot
sudo cp -rp lib/modules/* /media/UDOO/lib/modules/

So, now the uSD card is complete, and the new Precise UDOO should boot.

But wait,… there’s more. The Ubuntu Core is absolutely the minimum required to get started. There’s not even a user defined, so if we want to log into the new system we have to do a little more to get ourselves started.

Chroot from amd64 into armhf

To be able to execute armhf commands from an amd64 platform we need to use qemu. So for that to work we need to make sure we’ve got qemu installed on the host platform. Check using dpkg.

dpkg -l qemu-user-static

Have your SD Card mounted on your Linux PC and go to your Ubuntu Core folder:

cd /media/UDOO

Copy the qemu for arm file:

sudo cp /usr/bin/qemu-arm-static usr/bin/

Make sure you have your network settings properly configured:

sudo mv etc/resolv.conf etc/resolv.conf.saved
sudo cp /etc/resolv.conf etc/resolv.conf

Then, mount sys, proc and dev:

for m in `echo 'sys dev proc'`; do sudo mount /$m ./$m -o bind; done

Finally, chroot into the target filesystem:

sudo LC_ALL=C chroot . /bin/bash

You are now in your ‘chroot’ which means you can run commands as if you were on your target ARM device.

Using the ‘chroot’

The first step is to verify the network connection is fine. You can run:

apt-get update

You are now ready to install any new package in your Ubuntu Core Filesystem using APT tools.

In the armhf ‘chroot’

Now we can do some commands to make the UDOO environment more complete.

apt-get update
apt-get install apt-utils whiptail language-pack-en-base
dpkg-reconfigure tzdata
apt-get upgrade
apt-get install sudo vim-tiny less net-tools openssh-server wpasupplicant isc-dhcp-client ntp #(and any other packages you want)

Adding a user

Out of the Ubuntu Core box, there is no user defined. so we have to add at least “SOMEUSER” to enable us to log into the system.

adduser SOMEUSER
adduser SOMEUSER adm
adduser SOMEUSER sudo

Fixing the Console

The UDOO serial port (the uUSB connector closest to the corner of the board) operates at 115200 baud, but by default the Ubuntu Core image is not configured to take over on /dev/console at the correct baud. The simplest solution to fix this is to copy the tty1 configuration to the console configuration, and then adjust to the correct baud rate.

cp /etc/init/tty1.conf /etc/init/console.conf
vi /etc/init/console.conf

change the last line to

exec /sbin/getty -8 115200 console

Enabling the Ethernet

The wired Ethernet port is not automatically enabled. Edit the interfaces file and add two lines.

vi /etc/network/interfaces

auto eth0
iface eth0 inet dhcp

Other Niceties

Obtain the Ubuntu universe packages. The /etc/apt/sources.list file has most of the sources commented out. These comments should be removed, before installing a GUI.

vi /etc/apt/sources.list

Leaving the ‘chroot’

If you want to get out of the ‘chroot’ just type:

exit

Un-mount the target filesystem: Make sure you stay at the UDOO root point /media/UDOO/ and run the following commands. Go back to the original network settings. And the qemu can be removed too.

for m in `echo 'sys dev proc'`; do sudo umount ./$m; done
sudo mv etc/resolv.conf.saved etc/resolv.conf
sudo rm usr/bin/qemu-arm-static
sync; sync

Booting into UDOO Precise LTS

Insert the new UDOO Precise LTS file system uSD into the appropriate place, and then start up the serial console to watch the system boot. The serial port uUSB connector is the one closest to the RESET button, and should be connected at 115200 baud 8n1. It will appear on an amd64 Ubuntu machine as /dev/ttyUSB0.

UDOO uSD

When the system is booted the hdmi interfaced terminal should work successfully too. Use the login details you created above to log in, and profit!

Building the Desktop

From this point it is possible to install the GUI of choice. I have tried with LXDE, but given this is a Quad Core device, it may well run well with the standard Unity Desktop.

Installing LXDE or Unity (the standard Ubuntu desktop) can be done once you’re logged into the UDOO board, by either of these commands.

sudo apt-get install lxde-desktop
# OR
sudo apt-get install ubuntu-desktop

Once you have rebooted into your new desktop, it is useful to move the home directories over to the second partition that was prepared. The full desktop environments identify the second uSD partition and mount it automatically as /media/home.

sudo cp -rp /home/* /media/home

Edit the /etc/fstab file to get the partition to mount at /home, and reboot.

One thing missing (in a short amount of testing) is the firmware for the WiFi device. The best place to find the latest firmware-ralink is in the debian Sid repository. It is the same file for all architectures.

sudo dpkg -i firmware-ralink_0.43_all.deb

Final Thoughts

Compared to the Raspberry Pi the UDOO environment certainly runs very hot. The large heat sink on the UDOO is very necessary, whereby the Raspberry Pi doesn’t even need a heatsink. I guess that Freescale has packed a lot more (4x more?) into the same space that Broadcom used for its design, and that consumes more energy. Certainly, the lack of a GPU driver module and user space tools for the display, forcing software rendering doesn’t help. Hopefully Freescale will get their act together soon and Open Source the Vivante GC2000 driver code, or at least the hardware definitions to allow the Etnaviv team to progress quickly.

Neither Raspberry Pi nor UDOO are capable of being battery powered devices, which makes them pretty useless for any Internet of Things sensor project, IHMO. So, I’m not sure what kind of applications they’re really trying to address? Doesn’t matter, they’re still pretty cool devices and I’m going to be using the UDOO often.

Making waves – Open Music Labs’ DSP Shield – Arduino – freeRTOS

There’s a great new Arduino Uno (pre-R3) Shield available from Open Music Labs. Their Audio Codec Shield is an Arduino shield that uses the Wolfson WM8731 codec. It is capable of sampling and reproducing audio up to 88kHz, 24bit stereo, but for use with the Arduino it is practically limited to 44kHz, 16bit stereo. The Audio Codec Shield has 1/8″ stereo input and headphone output jacks, a single pole analogue input aliasing filter, and 2 potentiometer for varying parameters in the program on the fly.

Open Music Labs WM8731

The Open Music Labs provides a some libraries and code examples for use with the Arduino IDE, and also with the Maple IDE. But, rather than just use the existing code, I thought it would be fun to develop some freeRTOS libraries from their basis code.

I spent quite some time understanding exactly how the WM8731 worked, and what was needed to make it perform, in a RTOS environment. It is clear, that to work at the audio rate of 44.1kHz, that the Arduino needs to be clocked by a hard interrupt, rather than by a soft timer. So, I spent some time designing and playing with different methods of driving the board.

Initially, I thought it would be good to limit the interrupt processing to constant clock in and clock out of data, that MUST happen every sample (at 44.1kHz) or the sound sampling or playback is simply broken, and allow the interrupt to semaphore a further processing task to wake it up. However, once I understood just how limited the time available is for processing, it became apparent that (at least for the 16MHz Arduino) there is no time left to muck about with a RTOS, and everything has to be kept as simple and regular as possible.

Never the less, the freeRTOS code is useful to provide serial and I2C libraries to set up the board, and possibly to do some other tasks where possible.

The resulting code consists of just one freeRTOS Task, that initialises the Shield, and then suspends itself indefinitely. The freeRTOS Scheduler keeps on running, but finding no available task will just pend itself until its next timer tick.

  AudioCodec_ADC_init();    // initialise the potentiometer sampling.
  AudioCodec_SPI_init();    // initialise the SPI bus for special purpose Audio Codec use.
  AudioCodec_init();        // initialise the Audio Codec using I2C bus.
  AudioCodec_Timer1_init(); // set up the sampling Timer1, runs at audio sampling rate.
  vTaskSuspend(NULL);       // well, we're pretty much done here...

First the Arduino ADC is initialised into free running mode, to provide inputs from the two potentiometers on the Shield. The Open Music Labs have provided an analysis of the Arduino ADC, and they show that the free running mode provides the lowest noise floor. Not that it is important to have a low noise floor for this purpose, as it is just potentiometer sampling. However, they missed the trick of using decimation to improve the sampling resolution, choosing instead to use a dead-band for the sampling. I’ve changed the ADC initialisation to do variable sample decimation, depending on the bit depth desired.

This is the example code for a single potentiometer.

static inline void AudioCodec_ADC(uint16_t* _mod0value)
{
  if (ADCSRA & (1 << ADIF))     // check if sample ready
  {
    _mod0temp += ADCW;  // fetch ADCL first to freeze sample is done by the compiler
    ADCSRA = 0xf7;      // reset the interrupt flag
    if (--_i == 0)      // check if enough samples have been collected
    {
      _mod0temp >>= DECIMATE;   // Decimate the summed samples
                                // (to get better accuracy), see AVR8003.doc
      *_mod0value = _mod0temp;  // move temp value to the output
      _mod0temp = 0x0000;       // reset temp value
      _i = _BV(2 * DECIMATE);   // reset loop counter
    }
  }
}

Then the SPI bus is configured to sample the data from the ADC on the WM8731, and to write data back to the DAC. Since we’re using the DSP interface, which is very similar to the SPI bus interface, with 16 bit transfers, the SPI mechanics can be used effectively, removing the need to bit-bang the interface. I found that although SPI Mode 0 nominally looks to be correct, it would lose the most significant bit of most transactions, being the left channel input values. I needed to use Mode 3 to get effective transactions.

The I2C bus is used on pins A4 and A5, which is pre-R3 format. I would digress to say that decision not to continue to support the SDA/SCL pins being available on A4 and A5 is a very bad one, in my opinion. There are many old, and this quite new, Shields that will simply be broken by this decision. Simply, bad for the Arduino legacy.

I have completed the register and pin definitions in the header file, to allow simple selection of the configuration, by adding the appropriate bit values into the register settings.

The initial I2C command transaction looks like this.

I2C command preamble

Here is a bit more detail on the DIGITAL_PATH_CONTROL command.

Vol I2C preamble detail

The true heart of the project lies within the use of Timer 1 to signal the 44.1kHz timing required to produce the sound samples. An interrupt driven by the Timer 1 counter signals the transfer of data, performing any audio processing required on the incoming data, and writing it to the output ready for the next transfer, and sampling the analogue potentiometers to use them as as mod inputs on the signal. The Timer 1 counter is incremented by counting the CLKOUT line coming from the Shield.

ISR(TIMER1_COMPA_vect)
{
  // WM8731 data transfer routine
  // move data from and to the WM8731 - done first for regularity (reduced jitter).
  AudioCodec_data(&left_in, &right_in, left_out, right_out);

  // audio processing routine - do processing on input - prepare output
  AudioCodec_dsp();

  // adc sampling routine
  // sampling the potentiometers (no sound here)
  AudioCodec_ADC(&mod0_value, &mod1_value);

  // end mark - check for end of interrupt - for debugging only
  PORTD |= _BV(PORTD6);   // Ping Audio Shield buffer line.
  PORTD &= ~_BV(PORTD6);
}

As I noted above, timing is everything. Based on the plots below, it takes exactly 6us for the AudioCodec_data() function to transfer the data from and to the WM8731. This doesn’t seem like very long, but to maintain a sample rate of 44.1kHz, each transaction must be completed in less than 22.7us, as shown below.

Vol 44kHz mid

The logic trace below shows the situation with the simplest AudioCodec_dsp() function available. Here the DSP processing is completed with over 15.7us to spare. The actual AudioCodec_data() function takes exactly 6us to complete (T1-T2), and can be used as a scale for other logic traces below.

inline void AudioCodec_dsp(void) // straight through connection I-O
{
  left_out  =  left_in; // put in to out on left channel
  right_out =  right_in; // put in to out on right channel
}

Simple IO Snapshot

Other more complicated routines, such as a sine-wave Voltage Controlled Oscillator (digital of course) take a little more time from our limited budget, needing 9.6us to complete.

VCO snapshot

I have used the same code on a Freetronics Eleven, an Arduino Uno clone, overclocked to 22.1184MHz, and as can be seen below, it results in the AudioCodec_data() function taking 4.33us (vs 6us standard) and the VCO code taking 6.125us (vs 9.6us standard). Whilst these savings are relatively small, by comparing the two logic traces, I think they do change the result enough to make it worthwhile for this application.

VCO Overclocked Arduino

Code is as usual on Sourceforge in avrfreeRTOS.

In further work, I will build some useful DSP programs from the examples provided, such as a reverb or flanger filter.

UPDATE

After reading this article on the MicroMonsterModular I’m going to play with adding some new sequences.

This WurstCaptures web site can help to build them quickly, and CounterComplex has a few ideas too.

output = t * (t >> (pot1>>4) | t >> (pot2>>4) )&((pot3>>3) + 16)
output = (t * (( t>>9 | t>>13 ) & 15)) & 129
output = (t * (t>>8 + t>>9)*100) + sin(t)
output = t * (((t>>12)|(t>>8))&(63&(t>>4)))

On which tool to use and when

Recently, I’ve been thinking about tools and what to use as my preferred “platform” for this hobby I call hacking. Actually, I’ve been worrying about this since October 2011, when I first wrote the proposal for the Goldilocks, my project for building a 1284p based Arduino Uno clone.

In 2011, I had tried to build several projects utilising uIP and other IP stacks (W5100 Arduino Ethernet), and RFID and uSDCard FatFS support as some of the foundations. I found that the Arduino Uno simply didn’t allow me to do anything requiring complex libraries, because it lacked RAM resources. Because of these issues, I tried two things. Firstly, I started using the Arduino Mega platform, and I also tried to use ARM based platforms with Arduino physical compatibility (e.g. Maple, Teensy, kl25z). Also, people have commented, why not use a RaspberryPi or BeagleBone as the platform for your projects, they are cheap and 50 times more capable than the Arduino Uno.

I wasted a lot of time in 2012 looking at how to achieve what I want to learn, without actually getting much satisfaction. Each one of the noted suggestions has issues, but the key issue is always complexity. I keep on coming back to the AVR ATmega 8 bit platform as the right answer. These notes are my attempt to discuss (justify) why I think that may apply for others too.

My interest lies in working with a soldering iron (hardware) and a compiler, and understanding how software interacts with the physical world. The ability to directly and explicitly influence the state of a pin on a micro-controller, either in C language or in assembler is the point of the exercise. Being able to interact with physical devices, through low level bus protocols, such as SPI or I2C, or standards, such as servo-motor timing or TCP/IP, enables me to understand what the sensors, motors, and actuators of the world really do.

Many platforms attempt to abstract away the “complexity” of dealing with these issues, and give their users the power to achieve much more in short periods of time with high level languages such as Python, or JavaScript. These languages give their users rich platforms which can quickly integrate into web applications. That in itself is a great thing, but it is simply not what interests me.

The key advantage of the AVR ATmega platform is that the platform is absolutely mature, completely open, and is very scalable. The power of the ability to compile and link a simple C program with avr-gcc, and upload it to an AVR with avrdude (either with a bootloader, or SPI interface) cannot overstated. These tools with avr-libc make the AVR ATmega platform very easy to love, and easy to scale with.

In comparison, the ARM based platforms mentioned, as well as others I’ve not mentioned, suffer from a very fragmented approach to library availability, support from the C compiler, and proprietary approaches uploading compiled code. Specifically, each ARM platform seems to need to have its own libraries and linker scripts and, because of the nature of the ARM licencing, each platform may have different capabilities and ways of servicing its hardware interfaces. All very confusing for me at least.

So why not use a RaspberryPi or a BeagleBoard? Well whilst both of these are great platforms (which I also own and use), they are normally used with a full scale Linux based operating system. Having the systematic overhead of a Hardware Abstraction Layer, and device driver interfaces just takes away the purity of simple one machine instruction equals one physical outcome.

I guess what I’m saying that one day I’ll migrate to ARM based 32 bit systems for this kind of enjoyment, but that day is not today.

“Goldilocks” 1284p Arduino UNO Clone

The Pozible project for Goldilocks boards is funded and closed.
Pozible Goldilocks

As featured in Make.

Freetronics Goldilocks is now sold out.
Freetronics Goldilocks

But, Freetronics are considering making a new version.
Please add your wish list here.

Also, I’m working on a new version, Goldilocks Analogue with an integrated dual channel DAC. Now a second prototype of the Goldilocks Analogue has been designed and tested. It has taken a year, because I’ve been using the existing Goldilocks boards for a number of projects. Now I’m designing (hopefully) the final iteration of the Goldilocks Analogue before it goes into production.

I have a Kickstarter project to get the Goldilocks Analogue into production. The project was successfully funded.

I sell on Tindie

Updated Firmware for Goldilocks (Pozible & Freetronics)

  •  LUFA 140928 for ATmega32u2 DFU and for U2duino (USB to USART).
  • Increased bootloader timeout for ATmega1284p.
  • Updated IDE file structure to provide support for Arduino IDE 1.6.x.
  • Renumbered I/O pins for greater commonality with Arduino core.
  • Also added a Goldilocks Analogue Bootloader, running at 24.576MHz

Look for Goldilocks in the Unofficial Boards Support List, and follow the instructions in the Goldilocks Analogue User Manual.

Background

This proposal is to implement an Arduino clone using the ATmega1284p MCU, as replacement for the normal ATmega328p MCU, bringing significant improvements and longevity into the existing Arduino platform.

The current Arduino Uno and Leonardo devices cater for many applications, but they are becoming limited for some modern applications, such as Ethernet networking, SD Card storage, and USB based systems. The limitation in SRAM in the 328p and 32u4 is the most apparent issue, and this is the most difficult to supplement with external components. The Uno R3 platform is too small for demanding applications, and therefore not the right solution.

Arduino Mega devices are available which provide more RAM (but still less than Goldilocks) and many more interface pins, but unfortunately many of the standard Arduino Shields will not work with the Mega, unless you are prepared to hack them. The Mega platform is too big for the standard Shields, and therefore not the right solution.

Arduino and others are moving towards 32 bit MCU devices, including ARM Cortex based platforms such as the Arduino Due, which brings significantly more resource into play, but these platforms will require a major re-education of  users, and may actually fragment the Arduino user group. Also, these ARM processor based devices must be operated at 3.3V and can only supply 4mA per I/O, which makes them incompatible with many of the existing Arduino Shields.

I believe the Goldilocks solution is to use the Arduino Uno / Leonardo R3 physical format, for 100% Arduino Shield compatibility at 5V and with the standard pin layout. But using the ATmega1284p processor to provide significant improvements in RAM, FLASH, EEPROM, interfaces, and other factors.

I’ve been working with Arduino devices now for some years, and have found that my interest remains in fully understanding the way the “bare metal” processor is working. The Arduino platform gives me that opportunity.
https://sourceforge.net/projects/avrfreertos/

Whilst many argue that the days of 8 bit processors are numbered, and that devices such as the Raspberry Pi are the future, I would say that there remains a need for very simple, but very capable platforms, such as the “Goldilocks” platform proposed here. Raspberry Pi and others are essentially Linux machines, and are addressing different needs to this platform.

The 1284p MCU has already been used by the RepRap project as a platform in their minimalist Arduino platform, as a result of them experiencing similar resource limitation issues. The RepRap 1284p platform maintains Arduino code compatibility (boot-loader, board descriptions, avrdude) but abandons physical compatibility, as theirs is a special purpose application and has no need to support Arduino Shields.

http://www.kirbyand.co.uk/serendipity/index.php?/pages/Min644pWarez.html
http://www.kirbyand.co.uk/serendipity/index.php?/pages/min644p.html

Similarly Pololu use the 1284p in their Orangutan SVP platform, but again theirs is a special application, which incorporates many robotics interfaces, and deviates from both the Arduino physical and software platform. Pololu also implement an on-board ISP, which removes the need for the Arduino serial bootloader freeing more space for program code.

http://www.pololu.com/catalog/product/1327

Recently, others are starting to use the 1284p as the “Goldilocks” solution between 328p and 2560. This helps with establishing the precedent for the “Goldilocks” with the Arduino IDE and its hardware descriptions.
http://maniacbug.wordpress.com/2011/11/27/arduino-on-atmega1284p-4/
http://arduino.cc/forum/index.php/topic,64612.0.html
http://blog.stevemarple.co.uk/2011/11/calunium-pcb-version.html
http://www.bajdi.com/bajduino/bajduino-1284/
http://forum.freetronics.com/viewtopic.php?f=6&t=330

This is the final Goldilocks v1.1 board, that was prepared for Pozible Supporters.

Goldilocks 20MHz PCB

Here are some screenshots of the prototype board design.

Goldilocks Front Side

Differences between 328p and 1284p

The ATmega1284p has a number of significant differences from the 328p that make it a great MCU for the Arduino platform. Some are listed below, in no particular order.

  • 16kByte SRAM = 8x Uno SRAM

The 1284p has 8x more SRAM than the 328p, and also has double the SRAM of the 2560. There is no other AVR ATmega MCU with this much SRAM.

For Ethernet, video, and USB applications where large frame buffers need to be maintained or manipulated, the flexibility of having 16kByte of SRAM will change the kind of applications that can be implemented.

  • 4x Uno Flash & 2x Uno EEPROM

The 1284p has 4x more Flash and 2x more EEPROM than the 328p and therefore can store larger programs and non-volatile data. 

  • 2x Programmable USART

The 1284p has 2 programmable USARTs. These appear on Digital pin 0,1 and 2,3. This allows users to maintain the serial monitor connection with the Arduino IDE, whilst addressing another application, such as a GPS device. For new users and experienced alike having two serial interfaces will be a big improvement. 

  • Independent Analogue Platform (separate I2C bus pins)

Using the SMD package for the 1284p allows the board layout to implement a fully independent analogue platform. This is because the I2C bus pins are on a separate port to the ADC pins, and the ADC pins have no “alternate function” except for the PCINT function. Also separate AVCC and GND pins allow the analogue PA Port to be powered and grounded separately from the digital section of the MCU.

  • Timer 3 (Extra 16bit timer)

The 1284p has an extra 16bit timer, Timer 3, that is not present on any other ATmega MCU. Timer 3 does not have PWM outputs (unlike Timer 0, Timer 1, and Timer 2), and therefore is free to use as a powerful internal Tick counter, for example in a RTOS. freeRTOS has already been modified to utilise this Timer 3. Timer 3 (Extra 16bit timer)

  • Timer 2 (Real Time Clock Oscillator)

The 1284p has a 32.768 kHz capable timer, that can be fitted with an accurate watch crystal to enable real time keeping. Use of the avr-libc time.h functionality (present only in upstream release currently) allows an efficient SystemTick to match with advance time and date functions.

  • JTAG Interface

The 1284p implements a JTAG functionality which will allow advanced developers the option to debug their code.

  • Better PWM access

The 1284p brings additional 8bit Timer 2 PWM outputs onto PD, which creates the option for 2 additional PWM options on this port. It also removes the sharing of the important 16bit PWM pins with the SPI interface, by moving them to PD4 & PD5, thus simplifying interface assignments. 

  • Extra I/O pins (e.g. for internal SS pins)

The 1284p has additional digital I/O pins on the PB port. These pins could be utilised for on-board Slave Select pins (for example), without stealing on-header digital pins and freeing the Arduino Pin 10 for Shield SPI SS use exclusively.

Design Improvements on “Uno”

  • Add through-holes for all I/O

The existing Freetronics 2011 has space for prototyping, but doesn’t make any allowance for connecting pins to the prototyping space. Trying to solder jumpers between the I/O pins on the board backside is not very pretty, and also not robust for permanent prototyping. The Arduino Uno or Leonardo doesn’t have any prototyping space at all.

Suggest to include a row of through-holes inside the each of the pin headers to allow a header or jumper to be soldered to the I/O lead effectively.

Align the rows of through-holes to the 1/10” pitch, and to prototyping area pin pitch, to allow “Goldilocks” to have header pins soldered on the bottom, and be inserted into a standard breadboard.

  • Replicate SPI and I2C  to through-holes (with additional 1284p Alternate SS I/O).

The SPI and I2C interfaces are used for many daughter card options (from Sparkfun for example). Some examples include RTC, acceleration & magnetic sensors.

These mini-cards need access to the SPI or I2C interfaces which are shared with I/O pins. Bringing these SPI and I2C pins with Vcc and GND onto through-holes in the standard order (of Sparkfun cards, for example) at the left and right ends (respectively) of the prototyping area would simplify prototyping with these interfaces.

This is now implemented on the Arduino Uno Rev 3. as additional pins for I2C.

http://www.arduino.cc/en/Main/arduinoBoardUno

But, the additional through-holes remain valuable for the prototyping area.

  • Add JTAG Interface

Adding a standard JTAG interface at the edge of the card would allow in circuit debugging to be implemented. Whilst there may not be sufficient space to implement a standard JTAG connector, there would be space to bring the JTAG pins onto through-holes for headers.

  • Add a Micro SD Cage

There is space to add the long term storage capability brought by an integral Micro SD Card cage. Many projects require logging of sensor data, or capturing or playback of information, and the Micro SD card format is the easiest way to get data onto and off of any format of PC or Smartphone. The ATmega1284p also has plenty of SRAM to allow large buffers for reading and writing to the Micro SD card, so it makes sense to include it as a most needed option.

  • Link ATmega32u2 and ATmega1284p SPI interfaces

The USB-serial interface on the Uno is implemented by a ATmega16u2 device, but its SPI bus is only connected to the SPI programming header, and the SS pin is not even brought out. The Goldilocks will allow the ATmega32u2 MOSI, MISO, CLK, pins to to be easily bridged (solder pads on rear of board), and bring the SS pins of both ATmega devices to a patch pad. This will allow the two devices to work in concert for demanding multi-processing applications, involving USB and other peripherals.

  • Isolate analogue platform (optional SCL & SDA bridge)

For some applications digital noise and voltage droop (when using servo PWM), can have a significant impact on the accuracy of ADC conversions. Using the SMD 1284p it is possible to completely electrically isolate the digital Vcc and analogue AVcc and GND planes, as well as isolating the ADC converter within the MCU. A separate rectifier, or low pass filter could be used to provide AVcc.

The option to bridge the 1284p I2C pins on SDA and SCL with A4 and A5, where needed for compatibility with Arduino Shields, should be maintained through the use of solder bridges. 

  • Move Reset to edge

It is more common to need to use the Reset button with a shield in place, and if the Reset button is placed close to the edge (even vertically mounted, like the Seeed ADK main board), it can still be reached with a fingernail. Arduino Uno R3 implements this by moving Reset to the upper edge, near the USB connector.

  • Clock at 20MHz (or 22.1184MHz)

There is little reason to continue to run the MCU at 16MHZ, and given the MCU is specified to 20MHZ, being able to do 5 things, where previously we could only do 4, seems like a worthwhile improvement. Also, the use of a through hole precision crystal (not a SMD resonator) allows the use of after-market timing choices, eg 22.1184MHz for more accurate UART timings.

Design

This is the Goldilocks v1.0 prototype.

GOLDILOCKS-prototype-top

This is a proposal to map the ATmega1284p pins to the Arduino physical platform.

Arduino
UNO R3
328p Feature 328p Pin 1284p Pin 1284p Feature Comment
Analog 0 PC0 PA0
Analog 1 PC1 PA1
Analog 2 PC2 PA2
Analog 3 PC3 PA3
Analog 4 SDA PC4 PA4 PC1 I2C -> Bridged
Analog 5 SCL PC5 PA5 PC0 I2C -> Bridged
Reset Reset PC6 RESET Separate Pin
Digital 0 RX PD0 PDO RX0
Digital 1 TX PD1 PD1 TX0
Digital 2 INT0 PD2 PD2 INT0 / RX1 Xtra USART1
Digital 3 INT1 / PWM2 PD3 PD3 INT1 / TX1 Xtra USART1
Digital 4 PD4 PD4 PWM1 16bit PWM
Digital 5 PWM0 PD5 PD5 PWM1 16bit PWM
Digital 6 PWM0 PD6 PD6 PWM2
Digital 7 PD7 PD7 PWM2
Digital 8 PB0 PB2 INT2 Xtra External Interrupt
-> ATmega32u2 x-pad
Digital 9 PWM1 PB1 PB3 PWM0
Digital 10 SS / PWM1 PB2 PB4 SS / PWM0 SPI
-> ATmega32u2 x-pad
Digital 11 MOSI / PWM2 PB3 PB5 MOSI SPI
Digital 12 MISO PB4 PB6 MISO SPI
Digital 13 SCK PB5 PB7 SCK SPI
 (Digital 14) PB0 -> SDCard SPI SS
 (Digital 15) PB1 -> SDCard Card Sense
SCL PC0 SCL I2C – Separate
SDA PC1 SDA I2C – Separate
PC2 TCK JTAG
PC3 TMS JTAG
PC4 TDO JTAG
PC5 TDI JTAG
XTAL1 PB6 PC6 TOSC1 Unused
XTAL2 PB7 PC7 TOSC2 Unused
 (Analog 6) PA6 Unused -> Pad / Hole
 (Analog 7) PA7 Unused -> Pad / Hole

Here’s a picture of one of the two prototype boards, where I have added some additional items. I have changed the 1284p crystal to 22.1184MHz, and added a 5ppm 32kHz watch crystal for testing the avr-libc provided time.h functions.

Also I added header sockets for the 32u2 so that I could test its ability to program the 1284p using the LUFA AVRISP code, and determine how much decoupling should be added to the SPI bus link option. This is to ensure that even if the SPI bus is linked between the two MCU, that the 32u2 can’t lock up the SPI bus for devices trying to talk to the 1284p.

Also, I’ve added bridges for the SCL/SDA pins to the A4/A5 pins for old format (pre R3) shields.

P1030259

I’ve prepared a preliminary distribution of the entire code set for goldilocks, including the lufa 130313 code used in the 32u2 and the stk500v2 bootloader used in the 1284p. This code is laid out in the arduino manner, with the directories matching the usual layout of Arduino boards.

The production board design was finalised on June 28th and sent for manufacturing. The v1.1 production boards are shown below. Pick and place pictures soon.

Goldilocks v1.1 PCB Front

Goldilocks v1.1 PCB Front

Goldilocks v1.1 PCB Back

Goldilocks v1.1 PCB Back

Firmware

Moved support to the Arduino IDE Boards Manager.

Recompiled bootloader binaries with avr-gcc 4.9.2.

Returned to the original 2013 pins_arduino.h pin numbering, now that analogRead() issues are corrected.

Look for Goldilocks in the Unofficial Boards Support List, and follow the instructions in the Goldilocks Analogue User Manual.

Support for Arduino IDE 1.6.x.

Increased 1284p bootloader time out to 4 seconds.

Set upload speed to 38400 (single speed UART) for Goldilocks Analogue.

Goldilocks_20160108 Files

Support for Arduino IDE 1.5.x. Updated to LUFA 140928 for DFU and U2duino for 32u2.

No change for 1284p. Added Goldilocks Analogue bootloader, but no LUFA required because of FTDI USB interface.

Updated directory structure to support Arduino IDE 1.5.x. Modified pins_arduino.h to support analogRead() correctly.

Goldilocks 20150101 Files

Updated to LUFA 130901 for DFU and U2duino for 32u2. No change for 1284p.

Goldilocks 20130918 Files

Obsolete – Fixed USART mismatch by adjusting stk500v2 bootloader to 38,400 baud.

Goldilocks 20130818 Files

Obsolete – Fixed 32U2 tristate RESET issue.

Goldilocks 20130814 Files

Obsolete – Fixed stk500v2 bootloader monitor issues and included compiled firmware files.

Goldilocks 20130605 Files

Obsolete – Initial release.

Goldilocks 20130601 Files