Search This Blog

Tuesday, March 14, 2017

Auto Generate a 'C' Function Prototype Header File

There is a lot of discussion on the proper way to use header files in Embedded C projects. I don't want to get into that discussion, rather I want to present a tool that is useful for my usage. If you don't agree with my use model, that's OK, you don't have to use this tool that way, it is very adaptable to any situation! [1]

I use header files for three things,

  1. One big one that has all the #includes in it so that every module has the proper references to things like: <stdio.h> and <math.h>.
  2. One that has the global program data in it.
  3. One that has the various public function prototypes (signatures) in it.
The first two are relatively easy to make and maintain. They also settle down quickly in a project as the tasks they maintain are defined early on and while there may be refactoring, they rarely change much.

#3 however is constantly changing and even in a small project it may grow to many, many function prototypes and refactoring causes constant updating.

It is tedious to have to change the data in two places when refactoring or when adding functionality through public functions in an embedded C program.

Auto Generation to the Rescue

I knew that someone somewhere must have written a utility that reads a directory, looks through all the '.c' files and auto-generates a header with all the public function prototypes in it.

Sure enough I found some C code written in 1993, by a Mr. Richard Hipp on the InterWebs that does just that [2].

It's a small program, all in one file and only several pages long. I brought it into Pelles C [3] to see if I could compile it under Win 7 and almost unbelievably it compiled with only a few simple changes. For code written in 1993 that compiles on Windows that seems almost unbelievable to me!

What the program is supposed to do is read every '.c' (and or '.h') file in a directory, extract the public functions and write them as function prototypes into individual '.h' files or one big '.h' file that can be added to the project.

Functions are marked as local (i.e. not for exporting into the '.h' file) by either using the keyword: 'static' or by the use of a 'LOCAL' define (see the program documentation [2]).

The program is wonderfully written, easy to follow and worked straight up out of the box, with one exception.

To read all the '.c' files at once to make a single output file the program depends on the UNIX ability to do wildcard expansion on the command line. MSDOS does not have that capability, so I had to wrap the makeheaders.exe in a MSDOS Batch file to make it work the way I wanted to use it.

MakeHeaders is so complete, it has the ability to pipe in a file list of names on the command line and then make a single big '.h' file. Mr. Hipp thought of everything. The batch file that I used is below.

REM Make one big Header File
dir /B *.c > mkhdr_input.txt
makeheaders -h -f mkhdr_input.txt >AutoGeneratedPrototypes.h
del mkhdr_input.txt
pause

 

Listing 1 – A MSDOS batch file to operate the MakeHeaders program work the way I wanted it to. Upon running it makes a temporary file with all the names of the '.c' files in the current directory. Then it feeds this list into the makeheaders.exe. The program then parses all the files picking out the public function prototypes to write into one big '.h' file.

The batch file of Listing 1 first makes a file called: “mkhdr_input.txt” that contains just the file names. The “dir /B” switch is for the bare format which will list just the file names.

The makeheaders.exe is then fed with the mkhdr_input.txt file as input. The '-h' switch causes makeheaders to make one big '.h' file as output and then it redirects the output to the standard output which I redirect to the file AutoGeneratedPrototypes.h with the “>” redirect command.

The '-f' switch tells makeheaers that it will get it's input from the file specified, in this case: “mkhdr_input.txt”

Finally I just cleanup by deleting the: “mkhdr_input.txt” file.

There are many other options and ways to make the MakeHeaders program operate so be sure to check out the documentation [2]. For example the same list input can be used to make an individual '.h' file that corresponds to every '.c' file in the directory. This format is preferred by many and in very large programs may be preferable.

I just add the AutoGeneratedHeaders.h in my master 'include .h' file and the rest is automatic.

Perfect Function Prototypes Every Time

Now, anytime I refactor or add public functions to any source file I can just double click on the MakeHeaders.bat file and a new AutoGeneratedPrototypes.h file is made all ready for compiling.

Extra Bonus

If you want to use MakeHeaders to create a single, individual '.h' file for every '.c' file just use the batch file below.

REM Make A Seperate Header File for Each *.C file
for %%G IN (*.c) DO MakeHeaders %%G
pause


References:

[1] To find out more about the various ways to use header files, do a Google Search like,
https://www.google.com/search?q=proper+use+of+c+header+files

Then pick a strategy that makes sense for you.

[2] Make Headers program. As of March 2017, the source code and documentation can be found at,
    http://www.hwaci.com/sw/mkhdr/

     -Or here,

          https://fossil-scm.org/home/file/tools/makeheaders.c

          https://fossil-scm.org/home/doc/trunk/tools/makeheaders.html

[3] Pelles C – A very good freeware C Compiler for Windows,
    http://www.pellesc.de/



Article By: Steve Hageman www.AnalogHome.com     

We design custom: Analog, RF and Embedded systems for a wide variety of industrial and commercial clients. Please feel free to contact us if we can help on your next project.  

This Blog does not use cookies (other than the edible ones). 

Monday, March 6, 2017

Simple Circuits Add to Versatility of the AD9834 Direct Digital Synthesizer IC


The little AD9834 Direct Digital Synthesizer (DDS) made by Analog Devices is a powerhouse of a design that is found in all sorts of products from Radios to Power Supplies. It is the “NE555” of DDS chips in it's popularity [1].

The AD9834 consists of a 28 bit programmable DDS Core and a 10 Bit Current Output DAC. The Nominal DAC output current is 0 to 3 mA. This current can conveniently be output directly into a 200 Ohm load to generate a 0 to 600 mV output voltage (See figure 1).


Figure 1 – Standard output circuit configuration for AD9834 with a FSADJ resistor of 6.81k provides a fixed 0 to 600 mV output.

Note: The following circuits are simplified and do not show power supply connections or proper bypassing. Please refer to the parts specific data sheets for complete usage information.

While 0 to 600 mV may be useful in many applications it is not particular useful if the output voltage needs to be user adjustable or bipolar. This is especially true when the DDS is used like a function generator where the end user needs an adjustable amplitude.

Adjustable DAC Full Scale Current

The first approach to adding an adjustable output to the AD934 is to attack the DAC current setting resistor. This resistor is nominally 6.81k for a DAC current of 0 to 3mA. The voltage at pin 1 (FSADJ) is nominally 1.15 Volts and this generates a current in the 6.81k resistor of 0.1689 mA (1.15/6810). This current gets scaled by 18 times internally in the AD9834 to get to the final 3mA DAC Full Scale Current.

The internal design of this circuit lends itself to controlling the DAC full Scale current over a reasonable range and this can be a useful and inexpensive way to get an analog or digital adjustment on the DDS output voltage.

As shown in Figure 2, a simple precision OPAMP from Linear Technology [2] used in a scaling circuit has been added to the DDS to control the DDS output voltage over a 4:1 range. Maximum DDS output voltage for this circuit is achieved for a 0 Volt control input.

A potentiometer or any 0 to 5V DAC output can be use as the 0 to 5V input to allow complete digital control of the DDS output voltage.



Figure 2 – A simple OPAMP circuit added to the AD9834 can give the AD9834 a 4:1 output Adjustment Range for a 0 to 5 Volt input signal. The Input signal could be a Potentiometer or from a 0 to 5V DAC.

 
The limiting factor in the maximum achievable adjustment range of the circuit in Figure 2 is the AC performance of the DDS DAC. While the output can be adjusted down from its maximum value the feedthrough glitches from the DAC switches will remain the same and the linearity of the DAC will suffer at lower output levels. Note also, that any excess noise on the 0 to 5V control voltage will additionally cause AM Modulation on the DDS output so add filtering as may be required by your application.

I have used this circuit in Figure 2 for a 4:1 adjustability with decent results. Your mileage may vary, so be sure to check the AC parameters that are important in your specific application.

Multiplying DAC on the DDS Output

For the ultimate in digital adjustability a Multiplying DAC  (MDAC) can be used at the output of the DDS to get 2^14 (16384:1) or better than 80 dB of adjustment range.

The AD5453 family from Analog Devices is a very high bandwidth Multiplying DAC [3] that comes in 8, 10, 12 and 14 bit resolutions. It takes in a AC reference voltage and outputs a Current that is scaled by a Digital Control Word.

Most MDAC's have a very low -3 dB bandwidth on the order of 20 kHz, the High Speed AD5453 when used with a suitable OPAMP output has a -3 dB bandwidth of 10 MHz or better. The maximum attenuation (or how low you can control the output) is flat to 300 kHz at 14 bits, rising to 1MHz at 12 bits, 3MHz at 10 bits finally rising to 10 MHz at 8 bits.



Figure 3 – Combining a high speed AD5453 MDAC and a LT1087 Dual OPAMP allows very complete control of the AD9834 DDS output.


Note: The 10 uF capacitor sets the low frequency roll off. With the 10 uF value shown the low frequency, -3 dB point is below 2 Hz. (The input resistance of the AD5453 VREF Pin is 7k Ohms minimum).

Note: The 1.5pF capacitors should be adjusted in the final circuit for maximum output flatness over frequency.

The circuit of Figure 3 provides a +/- 5 Volt output with low distortion to 1 MHz and provides 80 dB plus of output voltage adjustment range. Additionally the output can be offset from -5V to +5V with the addition of an offset adjustment control via a low cost DAC or POT (Offset Adjust Input).

DDS Output Control At Even Higher Frequencies

If you need to operate the AD9834 at even higher frequencies, closer to the maximum specified fundamental output of 37.5 MHz, or even operating in “Super Nyquist” mode [4] you should look at a 50 Ohm CMOS RF Attenuator like those manufactured by Peregrine Semiconductor [5]. The PE43711 has a frequency range down to 9 kHz and 31 dB of control with 0.25 dB steps all the way to 6 GHz. At higher frequencies you will probably be designing around 50 ohm circuit impedance's anyway so this should not be much of an issue. Multiple PE43711's can be connected in series to get more attenuation in 31 dB chunks.

Note: At lower RF frequencies, less than about 50 MHz, CMOS, SiGe and Silicon based IC's are preferred to GaAs IC's. This is because the GaAs IC's typically have worse harmonic distortion (Especially very bad 2nd harmonic distortion) at low RF frequencies.

References:

[1] The NE555 timer is arguably the most popular linear IC of all time.

[2] Linear Technology LT1677 Precision and LT1087 High Speed OPAMPS are manufactured by Linear Technology Inc. Now a part of Analog Devices.

[3] Analog Devices Application Note: “Multiplying DACs Excel at Handling AC Signals”.

[4] Super Nyquist Mode, See: Analog Devices Application Note AN-939

[5] Peregrine Semiconductor, Inc



Article By: Steve Hageman www.AnalogHome.com 
 

We design custom: Analog, RF and Embedded systems for a wide variety of industrial and commercial clients. Please feel free to contact us if we can help on your next project.

This Blog does not use cookies (other than the edible ones).