Archive for the ‘Hardware projects’ Category

A few years ago I was playing rythm guitar in a small band along with three of my friends. One day, our lead guitarist spotted how useful a looper pedal could be to us, but he was unsure if the purchase was worth the price.

For those of you that are not familiar with this kind of gear, a looper pedal is a device that is daisy-chained between an electric guitar and the amp, recorder, or the rest of your gear. It’s able to record what you play and at some point play it back in the background while you play new stuff. It’s extremely useful where more guitars than available are needed. Usually it can be controlled by means of some footswitch, hence the ‘pedal’ denomination.

I remember that I was shocked of seeing looper pedals starting at $130. Soon, my engineering-obsessive mind started to think of ways of building a cheaper device without compromising quality.

Goals

I made a wishlist for a decent looper pedal features:

  • It should be able to start recording when I tap a switch.
  • It should be able to stop recording and play the loop back when I want.
  • It should allow me to add up more “layers” of sound on top of the existing loop.
  • I should be able to stop it whenever I want.
  • It must feature a decent sound quality.
  • I must stay under $50

Given this list of requirements, I decided to work on a desing, and build a prototype.

Ideas

Okay, two things were clear… I was going to need quite a big deal of RAM to store the audio, and a decent CODEC to DAC/ADC it.

Real-time audio streaming can become a relatively bandwidth-demanding task, so the RAM needed to be both fast and big enough.

In order to control de pedal I was going to need at least two buttons, but that was the smaller of my concerns.

Tools of trade

For this prototype I was lucky to have an Altera DE1 training board I bought to play with FPGAs.

DE1

The board features an Altera Cyclone 2 FPGA, an 8-MByte SDRAM Chip and a WM8731 high-quality, 24-bit, sigma-delta audio encoder/decoder with minijack inputs/outputs.

The RAM is 16-bit wide, and the CODEC is 24-bit, so to achieve CD-Quality (44,100 Hz) the formula would be like:

44,100 Hz x 3 bytes = 132300 bytes per second, or 129 KBps

Then, is the RAM capable of handling that?

With SDRAMs you can R/W in a mode named Burst where you give the starting address and the number of words to read/write and then the words are read/written sequentially with no more overhead. Let’s do some calculations:

What is the minimum frequency needed to stream 24-bit audio@44,1KHz to/from the SDRAM?

A naive calculation would be:

  • 1 word = 16 bits = 2 bytes
  • We need to stream in 24-bit units, that would be 1.5 words, so let’s round it up to 2 words
  • That makes 176.4 Kbps or 88.2 Kwords per second
  • Let’s double it because the looper might be recording new data at the same time it’s playing the old one.
  • Ideally, a theoretical bandwidth of 176.4KHz would suffice, but in practice there is an overhead due to CAS/RAS strobe, the memory switching a page, etc…

This particular chip can run up to 133 Mhz, which yields far more than needed bandwidth. One problem solved 🙂

At this point it looked like everything boiled down to hooking up the SDRAM, the CODEC and some sort of footswitch.

Design

I came up with the following design:
architecture

The board has 2 XTALs, one running at 50MHz and another one running at 27 MHz.

– The SDRAM needs 100MHz, so one of the built-in PLLs in the FPGA was used to double the frequency of the 50MHz XTAL up to 100MHz.

– The audio CODEC streams data at 18.4MHz, so another PLL was used to reduce the 27MHz clock frequency down to 18.4.

  • The rest of the cores run at 50MHz

Let’s examine the rest of the modules I wrote in VHDL:

Reset delay

This module makes sure that every other module has been properly reset and that the PLLs are locked before the whole system starts operating.

Its inputs are just a signal from one of the on-board buttons that acts as a RESET button, the 50MHz clock and the ‘locked’ signals from the PLLs.

When the external reset is just deasserted, or the system is just powered on AND the PLLs are locked, it uses a register to count 3 million cycles of the 50MHz clock and then deasserts the internal reset signal used by the rest of the modules.

CODEC controller

It’s responsible for streaming data to and from the CODEC in I2S format. Its interface with the other modules are a couple of 16-bit busses for input/output streaming data, reset and a 18.4 Mhz clock from the Audio PLL.

I2C controller

The CODEC has a lot of configuration parameters (like gain, volume, input selection, audio format…) that you must configure using I2C@20KHz. This controller operates pretty much on its own and its only task is to send a sequence of predefined commands to configure the CODEC just after RESET. It’s written in Verilog and I grabbed it from the Altera demo cores that came with the board.

MFC (Memory Flow Controller)

This is one of the most complex modules of my looper.

It interfaces with the SDRAM through two FIFOs and is responsible of feeding the looper core with streaming data stored in the SDRAM and to write to the SDRAM data streamed from the looper core. Its interface with the other modules are a couple of 16-bit busses for I/O and a control bus for controlling and signaling these conditions:

  • Input fifo full (tristate)
  • Output fifo empty (tristate)
  • EOL (End Of Loop) (Core → MFC)
  • Busy (MFC → Core)
  • Start writer (MFC → Core)
  • Write enable (MFC → Core)
  • Read enable (MFC → Core)
  • Fifo clock (data in the busses is sync’d to this clock)
  • Reset and clock as usual

The core uses 3 23-bit registers to point to relevant memory addresses inside of the SDRAM:

  • Read address
  • Write address
  • End of loop pointer

The behavior is modeled by three VHDL state machine processes: ‘reader’, ‘writer’ and ‘EOL_marker’.

Reader: When streaming is activated it instructs the SDRAM controller to burst-read data starting at the Read address pointer. When the data is available it’s enqueued in the input FIFO and the Read pointer is incremented (since it’s 23-bit (addressing 8 Mb) it will naturally overflow to 0 when you run out of memory). If the input FIFO becomes full the SDRAM controller stops reading, if it becomes almost empty it starts reading again thus ensuring continuous uninterrupted streaming of audio. The looper core can read data from the input FIFO transparently through the input bus.

Writer: Operates exactly in reverse: It takes data from the output FIFO (enqueued by the looper core) and stores it in the SDRAM via the SDRAM controller starting at the address pointed to by the write pointer. When the FIFO becomes empty, the controller stops storing data. If it becomes almost full then it starts storing data again.

EOL_marker: When the EOL signal is asserted, it first flushes the Output FIFO and then sets the EOL pointer to the address being currently written (i.e: the Write pointer).

It also features a debug sine-wave writer to test the MFC and audio output.

The SDRAM controller is a very cool one I pulled off OpenCores.org. It’s a port of a Xilinx memory controller for a Spartan FPGA to the Altera Cyclone II (specifically for the memory in the DE1 board!). Its greatest features are:

  • Quite parametrisable
  • Features time slot-based dual port (I use one port for reading and the other one for writing).
    • It runs at 100MHz (130MHz was originally supported, but the port doesn’t work at that freq).– Interfaces with your core mostly like a SRAM (address bus, data bus and simple control bus).

Testing the MFC and CODEC

Once I had the MFC and CODEC up and running, I uploaded to the SDRAM a .wav file and then wrote a simple core to stream it through the MFC out to the CODEC to see if it plays back.

I plugged the board to a cheap guitar amp to hear it.

Keyboard controller

Since I needed fairly big keys to be able to control the core while I was playing guitar I opted by having a PS/2 keyboard on the floor and pressing the bigger and most accessible keys (Spacebar and Ctrl’s) with my foot. The DE1 board has a PS/2 port so I chose to use the PS/2 controller that comes with the board (written in Verilog).

With the keyboard you can assert a few commands:

  • Start recording
  • End of loop (the looper starts playing back what you played, but it doesn’t record what you play now).
  • End of loop, but start recording a new ‘layer’ of sound (This allows to overlay what you play now to what is being replayed by the looper).
  • Pause/resume layer recording
  • Pause/resume regular (no-layer) recording

I used a Logitech wireless keyboard connected to the PS/2 port.

Main core

Here’s where everything is glued together. The main core uses FSMs to stream data between the MFC and the CODEC in both directions simultaneously. It’s fairy simple, since most of the complexity is carried by the MFC. It just responds to commands from the keyboard, controls the MFC and CODEC and connects the busses.

It also flashes some of the on-board LEDs as debug indicators.

Results

Does it work?. Yes!, absolutely. Below you can hear me playing random tunes with it. I hadn’t enough cables/connectors to daisy-chain it with an effects processor, so everything is clean (straight from the guitar pickups).

Test 1: (In this test I first record the rithm and then I play a few arrangements over it)

http://www.goear.com/listen/c624ddd/test1-radexx

Test 2: The eye of the tiger! (same as above)

http://www.goear.com/listen/b31235f/test2-radexx

Test 3: “The hell song” by Sum41. Here I demonstrate the ability to pause/unpause the loop playback. (Sounds way better with distortion!)

http://www.goear.com/listen/81d636b/test3-radexx

Test 4: Different tune. Here I first play and record the rithm, then I play on top of it, and at some point I pause the playback.

http://www.goear.com/listen/472965f/test4-radexx

Test 5: Some song by Sum41. Nothing special

http://www.goear.com/listen/35aef1a/test5-radexx

Test 6: Sound Layering test. Here I first play the rithm and I tap the ‘end of loop’ button. Then I layer an arrangement on top of it. And then I play a third voice on top of both layers.

http://www.goear.com/listen/b8df2fc/test6-radexx

Test 6: Sound Layering test 2. This time I stack up to 4 sound layers.

http://www.goear.com/listen/6a24cf0/test7-radexx

Conclussion

  • Not bad as a proof of concept.
  • Implementing it with an FPGA can be quite oversized and a bit expensive. There are a few microcontrollers featuring high pin count and internal SDRAM controller that can run the SDRAM as fast as 66MHz.
  • Good sound quality
  • Can record up to 47 seconds of high-quality audio
  • Solved our problem 🙂
  • The day I brought it to our rehearsal place I only asked for one thing: “Please somebody bring a jack to minijack adaptor so we can plug it to an amp”. Everybody forgot, so we had to hear it in “clean” (no distortion or effects) by using headphones. Shit happens 😦

As always, Thanks for reading!!

Advertisements

Hi everybody!

It’s been quite a while since my last post. I’ve been very busy with my Masters in CG, Games and VR.. wait.., in fact I’m still very busy!!

Today I’d like to tell you guys about a cool project I finished some months ago while I was working at a research institute

Intro

We needed a wireless versatile interface for sensoring buttons, joysticks and other human-operated transducers while maximizing compatibility and lowering production costs.

I had previously designed an HID-compliant USB device for sensing digger and crane controls, but the current trend seems to be something like getting rid of wires and filling the environment with radiation :-p.

I wanted the device to be a BT HID, as it has lots of advantages:

  • Many computers and devices are equipped with BT now, there’s no need to build an USB receiver.
  • Mainstream OSes have built-in drivers for HIDs
  • It can be used out-of-the-box with almost every game/app which supports a joystick/gamepad
  • Can be read directly through DirectInput , etc
  • Robust (CRC, they can live in the range of other BTs or 802.x devices…)
  • Multi-platform

And a few drawbacks:

  • More costly than specific point-to-point solutions such as the nRF family
  • Much more power-hungry

Project requirements

  • Wireless
  • Decent stamina
  • Bluetooth (HID profile)
  • Robust
  • Affordable production cost
  • Small enough to be mounted inside control panels

I conducted a bit of a research and couldn’t find a commercial product which fulfilled our requirements. The only HID bluetooth devices I could find were the Wiimote and the PS3’s sixaxis/dualshock 3. Both closed and in the case of the Wiimote, with a proprietary HID report-based subprotocol. Altough we could have been using the WiiUse library I wanted my own solution instead.

Selecting the components

I spent over two weeks surfing the net for the best suited components, and here’s what I came up with:

The Bluetooth transceiver

There’s plenty of all-in-one Bluetooth modules specially tailored for embedded designs. These are extremely useful since they integrate all the radio and baseband hardware (and even the antenna!) in a tiny self-contained mini-board, freeing the designer of those heavy-duty RF design tasks. But most of them are hardcoded with the RFCOMM Bluetooth profile (RS232 serial port over the Bluetooth link), and don’t allow the user to add or change Bluetooth services.

After trying a few of them and exchanging some e-mails with providers and manufacturers, the best I could find then was the Bluegiga’s WT12, a Class 2 Bluetooth module for embedded systems. What makes it different from everything else is that it’s a low cost module which runs a proprietary but documented firmware called iWrap. The iWrap implements the Bluetooth Stack from L2CAP down to the baseband, you can communicate with an external processor/microcontroller via a baudrate-programmable UART. It features a documented plaintext command set for configuring and interacting with the stack (creating L2CAP connections, notifying the host when a new connection is awaiting to be accepted, etc). They even offered us some free samples!. The drawback was that the iWrap3 firmware didn’t support custom Service registers, so you were basically stuck with the stock profiles.

The Microcontroller

The microcontroller would be in charge of running a fully custom firmware to initialize the iWrap stack, sampling its GPIOs for sensor data, managing the status of the battery and signaling the user of the general status via a 2-color LED among other tasks.

Since I had extensive prior experience with the Microchip’s PICmicro family of microcontrollers I decided to go with the PIC18LF4550 in a QFP package. The 18LF2550 is a small yet powerful 8-bit microcontroller with Flash memory which yields up to 12 MIPS at 48 MHz, has built-in USB, timers, PWM and many more peripherals and a great software toolchain and libraries. The ‘L’ stands for extended voltage range, meaning that it’s able to run at 3.3V which is the logic voltage for the WT12 module.

Power management and battery

I thought it would be great to use a USB port for recharging the battery as the 18LF4550 has built-in USB, and being able to use the USB link instead when the battery is nearly dead.

The MAX1811 is a great battery charger/monitor which is able to charge a Li-Ion single cell battery from a 100mA or 500mA USB port. It signals when the charge has finished, monitors the cell temperature and much more.

For the battery I chose to use the PS3 controller battery since it’s inexpensive, available everywhere and there are extended 1200 mAh versions for over 8 € !.

Finally, for power management I used the TI’s BQ2050, a fuel gauge IC able to communicate with an external host via 1-wire protocol for measures like the remaining charge in the battery among many other parameters.

System diagram

The first prototype

After calculating lots of parameters for discrete components from the datasheets of the ICs I wrote a couple of schematics in a piece of paper and built a handwired prototype on a proto-board.

Note the brown wire mess in the external board. That is the WT12 with its pads directly soldered to wires.

The firmware

That was the toughest part of the whole project. When a problem can be equally caused by a line of code or by a loose wire it always result in lots of fun ;-p

As you can see on the previous photo, I had a Microchip ICD2 (which got broken and was replaced by an ICD3) hooked up to the board. That gave me the greatly appreciated possibility of rebuilding the firmware and uploading it directly to the on-board uC, as well as doing painful remote debugging.

I will save you the nuts and bolts of the firmware, since it quickly grew into a complex and hard to debug piece of software. But I’d like to point its main features:

  • Implements a lexical analyzer to parse messages from the WT12.
  • Fully interrupt-driven. Active waits are avoided at all costs.
  • It efficiently disconnects or scales the clock from various parts of the chip depending on the current usage to save power.
  • Manages the status of a bi-color LED to let the user be aware of the current connection/charge status
  • Switches between USB and Bluetooth mode transparently to the user just plugging/unplugging the USB wire
  • Implements the SDP Bluetooth layer (the one in the iWrap was feature-incomplete for my goals)
  • Implements the BT-HID layer (“)
  • Sensors the inputs as a scan-matrix with up to 32 digital inputs
  • Sensors 8 analog inputs
  • Manages 8 3.3V CMOS compatible outputs
  • Warns the user if the battery is almost dead and turns of the device if the voltage level goes down the minimum safe levels
  • Has a custom HID-based protocol for reading the battery and device status from the PC, or perform other tasks such as remote shutdown
  • Implements the OneWire protocol with two CCP modules
  • Wakes up the device from sleep mode on signal changes
  • Implements a Bluetooth pairing PIN code
  • Is bootloader-capable for upgrading the firmware
That took a few months to develop. Tools like a low cost logic analyzer did often come in handy.

The schematic and board layout

I used CADSoft’s Eagle which is a good CAD/layout software that allows you to design 2 sided boards and it’s free (with some constraints) for non-commercial projects. Of course, I had to create new footprints and symbols for components that were missing in the stock Eagle’s library. The Eagle library from SparkFun was very helpful tough.

The system uses a 3.3V LDO voltage regulator-based power source for both USB and Battery operation modes. For the analog part I built a RL filter before the analog reference voltage input pin for power noise filtering, and each analog input has its own low-pass capacitor.

Regarding the digital inputs, 8 diode arrays were used for the scan-matrix method implementation.

A 16 MHz low profile xtal had been placed near the uC.

The I/O pins are simply IDC connectors, so another board with real sensors or better connectors can be stacked-up to this.

There is a special programming port for connecting the MPLAB ICD PIC programmer to the board.

Once I was happy with the schematic, and it had been tested in the proto-board I moved on to board layout. But before doing so, I had to decide where I was going to send the resulting Gerber files for manufacturing. After looking lots of low-cost prototype PCB manufacturers, I finally came upon to Gold Phoenix (which is the backend for SparkFun’s BatchPCB).

Then I studied their board constraints for prototypes that affected the thickness of the vias and tracks, and also the drill sizes. Fortunately, SparkFun have on their site a .dru design rules file for Eagle which was extremely useful.

The final layout was all carefully placed and routed by hand.

I strictly followed design guides from the manufacturers of the ICs, and used ground planes and different thickness tracks according to good design guidelines.

The WT12 has its pads facing the bottom of the board. It’s intended to be soldered in a reflow facility, so I had to figure out how to solder it by hand. My solution was to make the pads slightly larger in the footprint to be able to melt the solder in its pins by applying heat in the part of the pads that show up under the module.

GoldPhoenix sent us 19 boards

Assembly and test

I still remember how hard my heart was beating when I first connected the battery to the finished and assembled board prototype after a whole evening of tweezers, solder paste and looking through a giant magnifier :D… And turned out It didn’t work the first time!

While tracking down the problem I discovered that the datasheet of the voltage regulator had the pinout completely wrong!. Then I desoldered the part and replaced it with a TO-92 with the pins in place.

.. et voilá !!

Fully assembled board (top)

Fully assembled board (bottom)

It turned out that it worked like a charm!, however a bit more of debugging and development was needed with the final thing!

When it’s on the LED flashes in green, indicating that it’s in visible mode. Then you pair your PC with it and asks you for the PIN code. Once that is done, it’s recognized as a standard USB gamepad with 8 axis and 32 buttons! and it’s ready to use with any application. After 5 minutes of inactivity or on receipt of the shutdown command it turns off.

When any of the digital inputs is asserted it turns on again and tries to reestablish the bluetooth link. When you plug the USB cable the LED turns red and the battery gets recharged. The BT link is dropped and the device uses the USB link.

I didn’t have enough time to perform extensive testing but the battery life was more than decent and it works perfectly.