Sunday, September 10, 2017

Feeltech FY3224S reverse-engineering

I bought a Feeltech FY3224S some time ago, as it seemed like a capable little signal generator for the price. See the discussion in the EEVblog forums.

However, it has a few annoying shortcomings (in addition to not being referenced to Earth ground), such as:
  • signal generation pauses when settings are changed
  • sweep configuration is too simple
  • external modulation possibility is great, but using CH2 to modulate CH1 would be more useful
  • user interface is horrible, etc.
These are clearly things that need to be changed in both the microcontroller as well as the FPGA. As the source code is not available to either of those, it basically means re-writing all of it.

A quick look at the traces reveals that all user interface is handled through the microcontroller - as well as the UART. The microcontroller is then connected to the FPGA through a few lines. The FPGA seems to be 100% dedicated to the signal generation (and counter functions).

I'll concentrate on the FPGA and the signal generation first.

Signal generation scheme (channel 1)

Location of some of the blocks on the board.
There are two dual THS3002 CFA opamps, which are used one IC per channel. Both are powered from the +-12V supplies. In addition there is one dual 4558D VFA opamp, also powered from +-12V supplies. This unit seems to be shared between the channels.

The FPGA directly drives the first R-2R chain (wave DAC), from which the output goes directly to the negative input of one half of the output driver U6. The corresponding positive input is attached to a trimmable voltage divider between 3.3V and GND. This basically amplifies the R-2R output and adds a certain fixed offset. This is the raw waveform signal (although inverted).

The FPGA also feeds a 1 bit signal (a PWM signal) to a second order low pass RC-filter. The filtered signal is then fed into the negative input of one half of the 4558D. The positive input is connected to a trimmable voltage divider between 3.3V and GND. This low-pass filters the output and adds a fixed offset. This is the signal used to generate a DC offset. The fixed offset is added to allow for both positive and negative offsets (50% duty cycle seems to correspond with 0 offset).

The analog switches (74HC4053, also known as triple 1:2 analog mux) and the second R-2R chain form a configurable attenuator. The analog switches are powered from the +-5V supplies. The output from the first amplifier stage is fed to the attenuator, which then again feeds the negative input of the other half of output driver U6. The positive input is fed from the offset generator. This turns the output signal back right side up and adds the configurable offset. The output from the amplifier is fed to the output port through a 50 ohm output impedance. A weird details is that the output is taken from the wiper of a trimmer, which is trimmed all the way to one end. The trimmer end to end resistance is used as the feedback resistor for the final stage. I'm guessing this is meant to allow changing the output impedance of the unit from 50 ohms to up to 1.5 kilo-ohms.

It was a nice surprise that the amplitude of the output is adjusted through a high dynamic range attenuator instead of through the main DAC. The switching speed of the bilateral switches at +-5V is around 15ns, which allows a reasonable amplitude modulation frequency. In fact, 15ns is faster than the main output driver, so modulation should be anything the output can handle. There is a caveat however. More on that later.

DAC and attenuator stages. The lines from the FPGA above are meant to represent the control of the analog switches. Unlabeled wire on right is the attenuator stage output.

Offset and output stages. Unlabeled wire on the left is input from the attenuator stage. Unlabeled wire on the right is output to BNC.
Sorry for the lack of quality in the schematics. Just quick doodles. A much nicer schematic was drawn by forum member g2 on the EEVblog forums.

Channel 2 is assumed to be identical, but I haven't looked at that really yet.

Determining the pin outs for digital to analog stuff

The main R-2R ladder is easy to figure out. The resistors are aligned in a linear fashion, and the output pins feeding them are in incremental order. Thus the high bit is the bit closest to the output of the ladder and the low bit is the one furthest away.

The attenuator, however, has a very convoluted layout. The muxes are controlled from the FPGA in some random order and the resistors are connected to the muxes in some other random order.

The muxes connect to the FPGA as:
  • pin 68 - mux1 s3
  • pin 69 - mux1 s2
  • pin 70 - mux1 s1
  • pin 71 - mux2 s3
  • pin 72 - mux2 s2
  • pin 73 - mux2 s1
  • pin 74 - mux3 s3
  • pin 75 - mux3 s2
  • pin 76 - mux3 s1
  • pin 77 - mux4 s3
  • pin 78 - mux4 s2
  • pin 79 - mux4 s1

While the muxes connect to the R-2R network as seen in the figure below:
Which resistor connects to which mux channel.

Pinouts on the FPGA

The pins used in the waveform DAC of channel 1 are:
  • bit 11 - pin 57
  • bit 10 - pin 56
  • bit 9 - pin 55
  • bit 8 - pin 54
  • bit 7 - pin 53
  • bit 6 - pin 52
  • bit 5 - pin 51
  • bit 4 - pin 50
  • bit 3 - pin 49
  • bit 2 - pin 48
  • bit 1 - pin 47
  • bit 0 - pin 42
The pins used in the attenuator of channel 1 are:
  • bit 11, mux4 s3 - pin 77
  • bit 10, mux4 s1 - pin 79
  • bit 9, mux4 s2 - pin 78
  • bit 8, mux3 s3 - pin 74
  • bit 7, mux3 s1 - pin 76
  • bit 6, mux3 s2 - pin 75
  • bit 5, mux2 s3 - pin 71
  • bit 4, mux2 s1 - pin 73
  • bit 3, mux2 s2 - pin 72
  • bit 2, mux1 s3 - pin 68
  • bit 1, mux1 s1 - pin 70
  • bit 0, mux1 s2 - pin 69
The pin used for channel 1 offset generation (through PWM) is pin 84.

The clock generator @ 24 MHz is connected to pin 10. This is a dedicated clock input pin and allows the use of the internal PLL to increase the clock rate.

FPGA image

The programming interface to the FPGA configuration FLASH is standard Altera pin-out active serial programming on header S10. This is supported by the Altera USB Blaster and clones, which are cheaply available off eBay.

I've successfully swapped the old FPGA image to a new one, and back again to the old. My first test image just generated a PWM signal on the offset pin, and nothing more.

The second test produced an increasing binary count on the output, together with producing a 50% duty cycle PWM on the offset (for a 0 offset) and pulling the attenuation lines high (smallest attenuation). PLL is not in use yet, thus clocking occurs directly at 24 MHz from the oscillator.

Output from a first waveform generating FPGA image

Third test included controlling the attenation bits in incrementing order. This produces mostly what is expected, but with some mild discontinuity at some major bit transitions. This is either due to R-2R inaccuracies or I've made some mistake in the pin order. Probing the bits on the R-2R ladder itself, I've concluded that the bit order is correct and thus the errors are due to inaccuracies in the resistors.
Output signal from incrementing the attenuator bits each waveform cycle
Channel 1 is thus reverse-engineered to the point that all functionality can be used. Channel 2 reverse-engineering might have to wait for some time as I play around with channel 1.


The microcontroller is an STC micro STC12C5A56S2, which is a fairly capable 8051 compatible microcontroller. It has 56kB of FLASH and 1280 bytes RAM. It supports in-circuit programming through the UART using a proprietary protocol. Programming software is available from the manufacturer. However, it seems that downloading the firmware image from the controller is not a simple task. I'll have to either sacrifice the current firmware or buy a new microcontroller - or try to figure out how the read the firmware from the controller.

Capabilities testing

Existing capabilities

Some listings for the unit claim that the sample rate on the FY3224S is 250 MHz. I find this hard to believe, due to a couple of reasons. First, the Cyclone PLL is not capable of producing 250 MHz from a 24 MHz source - the closest it can get is 248 MHz, which of course isn't too far off. Second, the jitter observed on square waves is quite clearly 5 nanoseconds and not the 4 nanoseconds which would be expected of a 250 MHz sample rate. A 5 nanosecond jitter would correspond with a 200 MHz sample clock, which also happens to be a rate, which can be produced from the 24 MHz input.

Sine wave generation probably also isn't 12 bits, as the FPGA lacks the amount of memory. To be able to generate 12 bits output with +-1 LSbit error, the lookup table address needs to be 14 bits (16384 values), which is 196608 bits for one channel. The FPGA has 59904 bits of memory, which can only fit a single 4096 value lookup table. This could be used for sine generation, but then there is no space left for arbitrary waveforms. (Also, since memory lookup can be done only at a rate of 250 MHz they couldn't produce two sine waves at 200 MHz with a shared table). So, either they use some clever magic for generating the sine waves in logic, or they just use even smaller lookup tables. My guess is that they employ the same 2048 value lookup table they use for the arbitrary waveforms also for sine waves. This gives a worst case error of +-7 LSbits in the sine wave output, i.e. the effective output bit count would be around 9 bits. This probably is quite on par with the DA converter (R-2R network) quality, so it probably doesn't hurt anything.

New capabilities

I wrote a 2048 value lookup table sine wave generator. Sine waves are generated fine.
Sine wave generation.

I want the unit to be able to modulate the CH1 signal by CH2 waveform. The idea was to use the attenuator for the modulation. This sort of works, as can be seen in the image below. If you look closely at the negative side peaks, you'll see a bit of the problem.

High frequency sine wave amplitude modulated with low frequency sine wave.
In this second picture the problem is more evident.
High frequency sine wave modulated with slightly lower frequency sine wave.
There is horrible noise on wave. This comes from switching the attenuator setting. The reason I didn't see it before with the triangle wave tests was because the attenuator setting was switched at the same instant as the signal falling edge occurred.

I'm still unsure about what actually causes the noise. It might be because of switching speed differences. The noise occurs at quite a high frequency, so there is some possibility for filtering it out.
Constant voltage output modulated with 1 kHz sine wave
Close-up on one of the noise spikes.
The fallback option is to do modulation through arithmetics and keep the attenuator as the amplitude select. Computing a product of 12 bits times 12 bits is quite complex operation, and is not possible to perform at 200 MHz - in fact a quick test shows doing the product in a single cycle results in a maximum clock frequency of only 50 MHz. To achieve the performance, the operation needs to be pipelined. I'm thinking one bit per cycle, resulting in a 12 stage pipeline.

I'll continue updating this post as I progress.


  1. This comment has been removed by the author.

  2. Hello
    Sorry it was in Danish.
    Thank you for your article about the Feeltech FY3224S.
    I have drawn a partial schematic of the Feeltech FY3224S,
    using your drawings and a little from eevblog.
    If you want, I would like to send it.
    Hope you will continue with Feeltech FY3224S.
    Mvh Gert

    1. Hi!

      Yes. I'd be very interested in the schematic. :-). It's really nice that my work has been useful. I've added an e-mail address in my blogger profile.

      And yes, I'm continuing my work with FY3224S. I'm still hesitating on erasing the original firmware on the microcontroller, and thus I'm just playing around with the FPGA. I guess I'll order some replacement controllers, as they seem to go at around 1 euro on eBay.

  3. Hello
    Did you get my email?

    Perhaps it is better to look for STC12C5A60S2 than STC12C5A56S2.
    There is a larger selection, also in the Develop Board.
    There is little difference between the Flash ram and the Eeprom ram. Datasheet: STC12C5A60S2-en.pdf show the difference.
    But you know much better about it than me, what is best.
    regards Gert

    1. Hi.

      I got the mail yes, as you now know :-).

      Thanks for the info. I was originally looking for the 56S2, which are more expensive, but did notice that 60S2 are cheaper :-).