ATmega8 – Delta Modulation – Audio Sinewave Generator

Go To Last Post
45 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This is a project in progress.

[ 1 ] Let us assume that a code is written to create a table for one cycle of a normalized sinewave digitized by {N} samples.

[ 2 ] Let us assume that a code is written to emulate a Delta modulator and create a table for the generated delta bit stream, {N} bits, of the previous digitized sinewave for a ‘given’ Delta step, {Stp}. The parameter {Stp} determines the bit pattern of the Delta stream table.

[ 3 ] Let us define the audio spectrum bandwidth as being from about 20 Hz to 20 KHz.

[ 4 ] Let us assume that a code is written to read, in a loop, the Delta bits from the table, as in [ 2 ], and output each bit in 4 MCU cycles.

[ 5 ] By using an 8 MHz crystal, the Delta bit rate at the MCU output pin would be 2 MHz {Fd_hi}.

[ 6 ] To generate 20 KHz sinewave {Fhi_top}, {N} =  {Fd_hi} / {Fhi_top} = 100 bits (and 100 samples, as in [ 1 ])

[ 7 ] Let us accept that the SRAM space of ATmega8 limits the highest value of {N} at 3080 bits.

[ 8 ] The frequency {Fhi_btm} of the generated sinewave with {N}=3080 would be 649.35 Hz

[ 9 ] Let us define the higher band {BWhi} of the audio spectrum as being from about 650 Hz to 20 KHz and the lower band {BWlo} from about 20 Hz to 650 Hz. The frequencies of  {BWlo} could, therefore, be generated by lowering {Fd_hi} 32 times; that is {Fd_lo}=2,000,000/32= 62,500 Hz.   

[ 10 ] The Delta bits, outputted at one MCU pin, that generate the sine waves of the higher band {BWhi} could be filtered by one LPF (as a 3rd order Sallen-Key one}. This same filter could be used for {BWlo} by inserting (or switching) 3 capacitors in parallel with the original ones.

 

The sole advantage of this basic topology that generates audio sinewave signals is reducing the complexity and cost of the hardware to minimum (relative to known audio sinewave generators).

 

As I wrote at the beginning, it is a project in progress. Its codes are written for ATmega8 and checked by the simulator only (but their results are verified by using Excel and LTspice). I didn’t have time yet (in my cold room with 2h/24h mains voltage only and almost no fuel) to finish the design of its test circuit to find out (and verify practically) the optimum Delta Step {Stp} for every {N}; from 96 bits (12-byte table) to 3080 bits (385-byte table).

 

The purpose of sharing this project here is to give it a better chance to be updated, in one way or another, by those who are (or may be) interested in its field.

 

Kerim

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Wow.

 

That is an interesting technique, and can certainly be made to work.

After you have it working, I would suggest you also program a uC as a DDS signal generator.

At low audio frequencies you can do this with C, Basic, etc., you don't have to write tight Asm code and place the data on "boundaries", etc.

 

DDS uses as high an ISR rate as you can get, which maximizes the number of data samples / period as the frequency of the generated signal increases.

 

For audio frequencies, one can also just use a low ISR rate and calculate the samples on the fly, with no look-up table.

 

Remember, that using an "extra" micro, dedicated to a specific task within a bigger project, is a perfectly valid design approach.

(Unless you are building 1000's of PCBs..., then optimizing the design to fit one uC might be a "better" approach.)

 

JC

 

Edit:

This photo is a DDS generated 40 KHz sine wave, followed by a Sallen Key LPF, (or two, in series, I don't recall...).

It shows how few steps the sine wave needs if one follows it by a (reasonably) decent LPF.

 

JC

 

 

 

 

Last Edited: Mon. Jan 24, 2022 - 06:55 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

DocJC wrote:

After you have it working, I would suggest you also program a uC as a DDS signal generator.

....

This photo is a DDS generated 40 KHz sine wave, followed by a Sallen Key LPF, (or two, in series, I don't recall...).

 

Since, in the project, the frequency of the delta clock is >100 times the frequency of the generated audio sine waves, both for {BWhi} and {BWlo}, even a simple 3-RC filter, at the output pin, works fine. In a practical circuit, this simple passive filter needs a buffer (an opamp) so I decided to replace it with an opamp that works as a LPF and a buffer at the same time; like the Sallen Key one.

 

By the way, I heard of DDS generator and wrote some codes for it. But, in my knowledge, to get low THD for every audio frequency (from 650 Hz to 20 KHz, or from 20 Hz to 650 Hz), the DDS hardware for a rather wide bandwidth, say Fhi/Flo = 32 , is not as simple as its code. Please notify me if I am wrong.

 

I mean:

Do you think one LPF block could be used for a DDS signal generator to output sine waves, say from 650 Hz to 20 KHz for example? In this case, I guess a controlled LPF filter would be needed.

And doesn't DDS need rather very low tolerance resistors?

 

On my side, having low tolerance resistors and a practical (and low-cost) wide-band controlled LPF filter is out of question. So I had to find out a new solution that requires a simple doable circuit though the price is creating rather complex, as in [ 1 ] and [2 ], and out of the box, as in [ 4 ], codes.

 

Last Edited: Mon. Jan 24, 2022 - 09:32 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

In this basic project, the possible frequencies that can be generated satisfy the formula:

 

F_audio = F_delta / {N}

where {N} is an integer in the range 96 to 3080

 

For the audio high-band (650 Hz - 20 KHz), F_delta = 2,000,000 Hz

For the audio  low-band (  20 Hz - 650 Hz), F_delta =      62,500 Hz

Last Edited: Mon. Jan 24, 2022 - 09:43 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 The Delta bits, outputted at one MCU pin, 

Does this remind you, in some regards, of the one bit DAC that was been popularized in CD players (well, if they are still popular)?  They had a lot of advantages, so perhaps you are onto something--maybe somewhat reinventing a different wheel, but on an AVR platform.  Will be interesting to see your result.

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

KerimF wrote:

[ 2 ] Let us assume that a code is written to emulate a Delta modulator and create a table for the generated delta bit stream, {N} bits, of the previous digitized sinewave for a ‘given’ Delta step, {Stp}. The parameter {Stp} determines the bit pattern of the Delta stream table.

[ 6 ] To generate 20 KHz sinewave {Fhi_top}, {N} =  {Fd_hi} / {Fhi_top} = 100 bits (and 100 samples, as in [ 1 ])

[ 7 ] Let us accept that the SRAM space of ATmega8 limits the highest value of {N} at 3080 bits.

[ 8 ] The frequency {Fhi_btm} of the generated sinewave with {N}=3080 would be 649.35 Hz

 

The sole advantage of this basic topology that generates audio sinewave signals is reducing the complexity and cost of the hardware to minimum (relative to known audio sinewave generators).

Delta modulation is very simple, but storing bits is somewhat inefficient and the frequency steps are quite large.

 

There was work done years ago, on minimal-edge sine generation, called 'Magic sine waves' that looked to reduce the lower harmonics of the bit stream.

You could think of this as a special case of delta-modulation, more filter friendly. 

https://www.tinaja.com/glib/sinq...

 

These days, even low end newer MCUs come with DACs, so there is no need to be as memory wasteful or bit-bash in audio sinewave generators

In 2022+ it is better to select a MCU with a DAC, and you can greatly improve performance.

 

You can then run a DDS or a table lookup, or a combination of both, chosen for best performance.

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

KerimF wrote:

In this basic project, the possible frequencies that can be generated satisfy the formula:

 

F_audio = F_delta / {N}

where {N} is an integer in the range 96 to 3080

 

For the audio high-band (650 Hz - 20 KHz), F_delta = 2,000,000 Hz

For the audio  low-band (  20 Hz - 650 Hz), F_delta =      62,500 Hz

 

That is a low number of sample points, for a delta bitstream,  and the update freq step will need to select one of two low pass filters.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

KerimF wrote:

By the way, I heard of DDS generator and wrote some codes for it.

But, in my knowledge, to get low THD for every audio frequency (from 650 Hz to 20 KHz, or from 20 Hz to 650 Hz), the DDS hardware for a rather wide bandwidth, say Fhi/Flo = 32 , is not as simple as its code. Please notify me if I am wrong.

I mean:

Do you think one LPF block could be used for a DDS signal generator to output sine waves, say from 650 Hz to 20 KHz for example? In this case, I guess a controlled LPF filter would be needed.

DDS can cover 20Hz - 20kHz with a single filter. At lower frequencies, you simply get more points on the sine, until you exceed the table and then it repeats some same-Y points as needed.

The simplest (fastest) table is a full sine, and for best DAC use, is should be > 2*pi*DAC, > Pi * DAC **  so a 12 10 bit index into a 8 bit ROM table 

 

** I checked this again to refresh my memory, and the optimum min ROM table size is pi*DAC, so a 256 byte DAC can give 45' slopes (staircases) with a 806 byte table.

For DDS that would usually mean the next binary size of 1024 byte table. 

 

KerimF wrote:

And doesn't DDS need rather very low tolerance resistors?

'need' is relative.  MCUs with DACs have no precision demands on resistors at all.

A MCU without a DAC, can still have a DAC made with ordinary resistors, that is good to > 100 steps in Y.

 

Using same batch resistors/same value, you can get better matching and tracking, so a lazy 8 bit DAC would use 23 resistors (this from the web)

 

Improving the resistor tolerance would reduce the THD. 

 

Last Edited: Wed. Jan 26, 2022 - 09:05 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I recently cut/pasted and compiled the code from this page Sigma_Delta ...  http://www.thinkcreate.org/index...

it works as far as producing a sine wave.  The links to other pages were interesting. 

I reserve my right to assemble!
Brawndo's got what plants crave... It's got electrolytes!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Plexd wrote:

I recently cut/pasted and compiled the code from this page Sigma_Delta ...  http://www.thinkcreate.org/index...

it works as far as producing a sine wave.  The links to other pages were interesting. 

Yes, interesting.

If you were going to update the PPM pin at DDS rates, which are relatively slow ( /110 in that case), why not use other chip HW that can use a higher clock rate ?

eg a PWM set for 110 steps, could update at the same speed, but with a big gain in granularity.

Even a SPI or UART can be used as a 3-bit DAC

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Who-me wrote:

KerimF wrote:

 

[ 2 ] Let us assume that a code is written to emulate a Delta modulator and create a table for the generated delta bit stream, {N} bits, of the previous digitized sinewave for a ‘given’ Delta step, {Stp}. The parameter {Stp} determines the bit pattern of the Delta stream table.

[ 6 ] To generate 20 KHz sinewave {Fhi_top}, {N} =  {Fd_hi} / {Fhi_top} = 100 bits (and 100 samples, as in [ 1 ])

[ 7 ] Let us accept that the SRAM space of ATmega8 limits the highest value of {N} at 3080 bits.

[ 8 ] The frequency {Fhi_btm} of the generated sinewave with {N}=3080 would be 649.35 Hz

 

The sole advantage of this basic topology that generates audio sinewave signals is reducing the complexity and cost of the hardware to minimum (relative to known audio sinewave generators).

Delta modulation is very simple, but storing bits is somewhat inefficient and the frequency steps are quite large.

 

I am not sure of what you mean by 'inefficient'. For example, for 20 KHz, {N}=100 bits here, the bits are stored in 12 bytes + 1 byte for the remaining 4 bits. Even for 650 Hz, the 3080 bits are stored in 385 bytes.

About the frequency steps in this project, the largest one is 96/95 --> 1% and the smallest one is 3080/3079 --> 0.03%.

 

Who-me wrote:

There was work done years ago, on minimal-edge sine generation, called 'Magic sine waves' that looked to reduce the lower harmonics of the bit stream.

You could think of this as a special case of delta-modulation, more filter friendly. 

https://www.tinaja.com/glib/sinq...

 

Thank you for the link. I will read the PDF file.

 

Who-me wrote:

hese days, even low end newer MCUs come with DACs, so there is no need to be as memory wasteful or bit-bash in audio sinewave generators

In 2022+ it is better to select a MCU with a DAC, and you can greatly improve performance.

You can then run a DDS or a table lookup, or a combination of both, chosen for best performance.

 

You are totally right. Thank you for the suggestion.

But where I live I see myself fortunate to find and buy even a rather old MCU, as ATmega8L; also for being able, about 5 years ago, to download from ATMEL an assembler/simulator for it (This rather special situation is due to the world's regulations imposed, since long, on the region in which I was born and live). Before ATmega8L, I had to use AT89C2051 to build an inverter/charger for sale. The inverter had a soft start (to protect the MOSFETs from the in-rush current). its output voltage is regulated when the battery voltage > 12V (or 24V). Also its charger had a constant charging current which could be preset by the user and reduces gradually, till it compensate the battery leakage current, when the battery voltage reaches its preset limit (the 50Hz mains voltage between 190Vac and 245Vac). I was able able using it after being able downloading a DOS assembler for it (TASM.EXE). Obviously, before C51 family, I had to use the CPU Z80 in my products.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Who-me wrote:
That is a low number of sample points, for a delta bitstream,  and the update freq step will need to select one of two low pass filters.

 

Thank you for your remarks.

 

In my first tests, 96 bits (for one cycle of 20 KHz) generated a sine wave with THD<1% at the output of 3-pole RC passive filter. This may be bad in some hi-fi applications.

The ATmega8L needs to add 3 capacitors for the same LPF (passive or active) if the requested frequency is below 650 Hz. Also, this may be undesirable for some applications.

 

Last Edited: Tue. Jan 25, 2022 - 09:19 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Who-me wrote:
DDS can cover 20Hz - 20kHz with a single filter. At lower frequencies, you simply get more points on the sine, until you exceed the table and then it repeats some same-Y points as needed.

 

Sorry, I didn't get you well here.

The basic DDS code, I heard of, generates the low frequencies by stretching every step while reading a sinewave table (256 steps if I remember well). Perhaps I have to read more about DDS.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Perhaps a reader wonders why I had to write the code of OP line [ 4 ] with 4-cycle intervals for an 8 MHz crystal instead of 8-cycle by using 16 MHz.

For the time being, I have ATmega8L only, and running it with a 16 MHz crystal is not recommended.

 

At the beginning, I supposed I can run the ATmega8L with 16 MHz and I wrote a code for 8-cycle intervals which is somehow simple to do.

Then, I thought the MCU can run reliably with 10 MHz. For this case, I wrote another code for 5-cycle intervals to generate the 2 MHz Delta clock.

Finally, I liked challenging myself and let writing a code with 4-cycle intervals as homework to a student (myself) which should be presented to a teacher (also myself) smiley 

It took me many months before being inspired how to write it (I am not very smart after all).

Anyway, let us review it more closely. Its obvious purpose is to output a bit (read from a table where bits are saved in bytes +1 byte for the remaining bits, if existed) every 4 cycles.

It has to also detect that all bits are read from the table so that the next bit is the first bit of the stream (also read from the same table).

Although, in the final project, an interrupt (as of TWI) could be used to break the main loop in order to request a new frequency, the code, I wrote now for tests, detects also the status of an external switch for the same purpose. In this case, the requested frequency could be read by ADC pins using trimmers (at least two, for fine tuning) since there are about 6 thousands frequencies to select from.

 

Naturally, by using the 4-cycle code, the Delta clock could be doubled (4 MHz) when ATmega8A is used with 16 MHz crystal. In this case the 100-bit table, for example, will generate a 40 KHz sinewave instead of 20 KHz.

 

For instance, I have the impression that by using a number of Delta bits which is lower than 96 (for one sinewave cycle) will also work to generate higher frequencies with practical low THD (by finding out the optimum Delta Step for each frequency while running the code of OP [ 2 ] ). So when my room returns to be rather warm in the coming spring I will likely find out the lowest number {N} that gives a practical sinewave (having THD below 3%, for example).

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have distant memories of a sound output technique called BTC3 by "Roman Black"

 

http://www.romanblack.com/picsou...

 

which I think is maybe something like the technique proposed in this thread. His algo is further explained at:

 

http://www.romanblack.com/btc_al...

 

10-15 years ago it was seen as the "cheap alternative" to doing AVR audio rather than either an R-2R resistor ladder or PWM/filter and most importantly it allowed you to encode your "WAV samples" or whatever as 1bit deltas rather than 8bit PCM or whatever. It was that ability to pack the sounds into small 1/2/4K micros that I think was its major appeal.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Who-me wrote:

There was work done years ago, on minimal-edge sine generation, called 'Magic sine waves' that looked to reduce the lower harmonics of the bit stream.

You could think of this as a special case of delta-modulation, more filter friendly. 

https://www.tinaja.com/glib/sinq...

 

I read the PDF file of the ‘Magic sine waves’. It gives indeed many interesting and clear ideas, as you said; for example, about how to reduce to zero specific harmonics.

Based on what it recommends exactly (the clocking rate for a 60 Hertz output is 25.2 kHz) the highest audio frequency which could be generated with 2 MHz clock is about 4,762 Hz. But I believe that, by following its general tricks, other bit streams, with low THD, could be found to cover higher frequencies with a 2 MHz clock.

 

Thank you again for the PDF link.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

I have distant memories of a sound output technique called BTC3 by "Roman Black"

 

http://www.romanblack.com/picsou...

 

which I think is maybe something like the technique proposed in this thread. His algo is further explained at:

 

http://www.romanblack.com/btc_al...

 

10-15 years ago it was seen as the "cheap alternative" to doing AVR audio rather than either an R-2R resistor ladder or PWM/filter and most importantly it allowed you to encode your "WAV samples" or whatever as 1bit deltas rather than 8bit PCM or whatever. It was that ability to pack the sounds into small 1/2/4K micros that I think was its major appeal.

 

Thank you.

I will visit these two links.

 

Added:

Romanblack project is about reproducing a voice signal (stored as an 8-bit wav file) by using one (or two) MCU pin.

In my project, the code generates a continuous audio sinewave whose frequency could be determined by the received value of its index which could be 0 (about 20 Hz) to 5967 (about 20 KHz).

 

 

 

Last Edited: Tue. Jan 25, 2022 - 01:31 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

KerimF wrote:

Who-me wrote:

DDS can cover 20Hz - 20kHz with a single filter. At lower frequencies, you simply get more points on the sine, until you exceed the table and then it repeats some same-Y points as needed.

 

Sorry, I didn't get you well here.

The basic DDS code, I heard of, generates the low frequencies by stretching every step while reading a sinewave table (256 steps if I remember well). Perhaps I have to read more about DDS.

Effectively, yes,  'repeats some same-Y points as needed' and ' low frequencies by stretching every step' are saying the same thing.

With a 8-bit DAC, you are well under 1% distortion on the Y axis and the X table can be any size, but usually is large enough to give at least every Y value a location.. ( > 1600 bytes for simple single sine )

 

If the idea of repeating points on the very lowest frequencies worries you, as being lost precision, it's common to  have more than one DDS choice in a generator.

A MCU with a 12b DAC for example, could read using a 16b adder and a 8b DAC for the fastest DDS loop, but then change to a 24b or 32b adder and 12b DAC which slows the loop somewhat, but improves dF and dV 

 

There are also R-2R DAC designs out there, that tack the PWM onto the last bit. If we consider a DDS loop as being 16-32 sysclks ballpark, that PWM-LSB allows you to add 4 or 5 extra bits of DAC granularity.

Thus even a Mega8 can give 12-13b DAC, and you are really just limited by the flash size for the sine table choice. 

 

Another hybrid of this, is to use 2 lower precision PWM and 2 mixing resistors to (greatly) improve the PWM speed.

eg a 16 clk DDS loop, can support 16 step PWM and R:16R can mix two PWM to give 8b DAC, or a 32 clk DDS loop can support 32 step PWM and R:32R can mix two PWM for 10b DAC

 

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Who-me wrote:

Yes, interesting.

If you were going to update the PPM pin at DDS rates, which are relatively slow ( /110 in that case), why not use other chip HW that can use a higher clock rate ?

eg a PWM set for 110 steps, could update at the same speed, but with a big gain in granularity.

Even a SPI or UART can be used as a 3-bit DAC

  •  

I don't do "C" but am trying to get an idea of where to start with PPM, PDM, Delta-sigma or whatever it's called. The code (with the link I gave), I do not understand. Will have to look at the Dis-asm later. This is another new rabbithole journey.

I did like the pdf article link you posted, I think that's closer to what I'm looking for.

Adafruit and Sparkfun have cheap boards to process quality audio/MP3 but for me, "where's the fun in that?"...  learning is more fun and I don't monetize this. For me it's not critical.

 

clawson wrote:
10-15 years ago it was seen as the "cheap alternative" to doing AVR audio rather than either an R-2R resistor ladder or PWM/filter and most importantly it allowed you to encode your "WAV samples" or whatever as 1bit deltas rather than 8bit PCM or whatever. It was that ability to pack the sounds into small 1/2/4K micros that I think was its major appeal.

Good resource: I had issues with the low bitrate @ ~ 8KHz, there was squealing between speech/audio bursts until I doubled or tripled the frequency for the 0xAA,0x55 runs longer than 2 or 3 bytes. You can get usable results even with the 8 bit baseline PIC chips. Lotta 'Bang for the Buck' in this method. Thanks for reminding me about Roman. 

 

I reserve my right to assemble!
Brawndo's got what plants crave... It's got electrolytes!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I do not understand.

First, understand PWM-- you will make an average value, as given by the % duty, 0 to 100%.  Say it is 30%   ...it will be on for 30%  (of the period).. then off for 70%, then on for 30%..then off for ..repeat.  A filter will smooth this out into the average (will a small remaining ripple).  These long stretches of time result in somewhat a low freq on/off cycling.  Since the times are based on counts, a finer control requires more counts of resolution.  This means a full cycle requires more counts overall.  That would be no problemo, except AVR timer can only count so fast, and timers handle only so many bits.  So in reality, this means the on/off freq goes down (maybe way down).  Averaging a low freq is tougher.   Imagine instead, taking these long on & off times, getting out your ginsu knife and chopping them up, then shuffling the little on/off piece together like a deck of cards.   You still have the same total on time & off time, but they take turns at a much higher frequency.  The higher freq makes it much easier to filter & unwanted switching noise is pushed higher up into the freq spectrum where it will only bother your dogs.  

 

    

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Wed. Jan 26, 2022 - 02:50 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Plexd wrote:

Who-me wrote:

Yes, interesting.

If you were going to update the PPM pin at DDS rates, which are relatively slow ( /110 in that case), why not use other chip HW that can use a higher clock rate ?

eg a PWM set for 110 steps, could update at the same speed, but with a big gain in granularity.

Even a SPI or UART can be used as a 3-bit DAC

I don't do "C" but am trying to get an idea of where to start with PPM, PDM, Delta-sigma or whatever it's called. The code (with the link I gave), I do not understand. Will have to look at the Dis-asm later. This is another new rabbithole journey.

I did like the pdf article link you posted, I think that's closer to what I'm looking for.

 

I guess it depends on your end-use needs, but to me, updating a single bit at interrupt rates, does not feel like the best use of today's MCU devices.  ( Which is why their example is a modest 1kHz)

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Who-me wrote:

KerimF wrote:

 

Who-me wrote:

DDS can cover 20Hz - 20kHz with a single filter. At lower frequencies, you simply get more points on the sine, until you exceed the table and then it repeats some same-Y points as needed.

 

Sorry, I didn't get you well here.

The basic DDS code, I heard of, generates the low frequencies by stretching every step while reading a sinewave table (256 steps if I remember well). Perhaps I have to read more about DDS.

Effectively, yes,  'repeats some same-Y points as needed' and ' low frequencies by stretching every step' are saying the same thing.

With a 8-bit DAC, you are well under 1% distortion on the Y axis and the X table can be any size, but usually is large enough to give at least every Y value a location.. ( > 1600 bytes for simple single sine )

 

If the idea of repeating points on the very lowest frequencies worries you, as being lost precision, it's common to  have more than one DDS choice in a generator.

A MCU with a 12b DAC for example, could read using a 16b adder and a 8b DAC for the fastest DDS loop, but then change to a 24b or 32b adder and 12b DAC which slows the loop somewhat, but improves dF and dV 

 

There are also R-2R DAC designs out there, that tack the PWM onto the last bit. If we consider a DDS loop as being 16-32 sysclks ballpark, that PWM-LSB allows you to add 4 or 5 extra bits of DAC granularity.

Thus even a Mega8 can give 12-13b DAC, and you are really just limited by the flash size for the sine table choice. 

 

Another hybrid of this, is to use 2 lower precision PWM and 2 mixing resistors to (greatly) improve the PWM speed.

eg a 16 clk DDS loop, can support 16 step PWM and R:16R can mix two PWM to give 8b DAC, or a 32 clk DDS loop can support 32 step PWM and R:32R can mix two PWM for 10b DAC

 

 

Thank you for presenting many possible alternatives.

On my side, I used looking for practical solutions that let me (me; not an engineer who can get any component/device and tool he/she hears of) build a working project (hardware and firmware) for a certain application.

I mean your solutions are great for many engineers who started be interested in signal processing. But, on my side, I avoid using R-2R ladders and PWM to name a few.

 

In other words, in theory, most solutions sound good. But, in real life, some of them (or all of them perhaps) could be practical for a certain engineer.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sine wave Delta Modulator on LTspice

 

My first step in this project was to draw an LTspice Delta modulator for a normalized sinewave (Vp=1V).

I attached an updated version of it (the original one wasn't clear and had minor bugs).

 

The main two parameters on the schematic are:

 

bits (the number of bits in one cycle)

i_step (it determines the level of the Delta step)

Added: Also see the parameter Kb below.

 

The other parameters are:

 

Np (It could be 1 or 2, the number of cycles to be modulated; =1 if bits even, =2 if bits odd)

Kb (it could be 1 or 32; =1 for the higher band, =32 for the lower band)

Fck (the frequency of the Delta clock)

Fin (the frequency of the audio sinewave)

E (the end time of simulation)

Ne (the number of the sinewave cycles to be simulated)

S (for the number of the sinewave cycles to be displayed)

Nn and Nh (the number of harmonics for the FFT log; generated by the .four command)

 

Notes:

[ 1 ]

.wave dlt0096_120u0.wav 8 2000K V(PLS)

If the .wave command is enabled the generated Delta bits will be stored in an 8-bit wav file. I change its name for different ‘bits’ or ‘i_step’. The actual name is for bits=96 bits and i_step=120u.

[ 2 ]

CalcDeltaTest.txt is just a list of the tests, I did at the beginning, on which the values of ‘bits’ were chosen to be multiple of 8 only and i_step were found for a normalized peak amplitude, Vp, to be close to 340mV. 

 

Attachment(s): 

Last Edited: Wed. Jan 26, 2022 - 02:54 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

That's very Boss!....have you considered using a 2nd order modulator  for improved performance.

 

https://www.beis.de/Elektronik/D...

https://www.beis.de/Elektronik/D...

 

Wonder if some of the programmable logic in the newer AVRs could do some of the work?  Maybe somebody has has tried.

 

Thanks for posting your simulation!

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

avrcandies wrote:

....have you considered using a 2nd order modulator  for improved performance.

https://www.beis.de/Elektronik/D...

 

In my knowledge, a simple LP filter will not recover the original signal properly by just filtering the bit stream output of a 2nd order modulator.

But, if this is not the case, I hope you or someone else will be able to notify me.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

One may wonder that the Delta modulator above (post #23) has no integral block(s) at all.

The reason is that a sine wave is, at the same time, the integral and the derivative of a cosine wave (and vice versa).

Last Edited: Wed. Jan 26, 2022 - 03:39 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

KerimF wrote:

On my side, I used looking for practical solutions that let me ...

... But, on my side, I avoid using R-2R ladders and PWM to name a few.

 

but R-2R and PWM are practical. PWM even comes for free, on the MCU you already have. ( I'll grant that DACs are relatively new, and not on MCU's that you, and many others, can get. )

 

The best solutions, come from using the resource in the MCU to best purpose.  :)

 

Engineering is the art of making what you want, from what you can get.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

KerimF wrote:

If the .wave command is enabled the generated Delta bits will be stored in an 8-bit wav file. I change its name for different ‘bits’ or ‘i_step’. The actual name is for bits=96 bits and i_step=120u.

If you like the look of a single serial bit stream from a D-FF, then consider the SPI capable ports in the MCU you have on hand.

That uses a string of D-FF to output one new data bit every 2 sysclks, and can be fed from a 16 clk Table loop. **

 

Addit:

16 clk is enough to manage a variable sized table, or a DDS adder has enough time to read PDM data for SPI output (3 bits) and Nibble data for PWM data (4 bits), to give a total of 7 bits of y axis update every 16 sysclks

The SPI and PWM pins are then resistor merged.  Not sure which is best to weight as MSB, maybe the PDM on SPI, as the spectrum is higher ? 

 

** Ah yes, there is an issue on older AVRs, where UART in SPI mode can pump 8 bits in 16 clks, but SPI port has a lost clock cycle. so it needs 18 clks to pump 8 bits. (minor detail)

See : https://www.avrfreaks.net/commen...

Last Edited: Wed. Jan 26, 2022 - 09:58 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Who-me wrote:
Engineering is the art of making what you want, from what you can get.

Oo, I'm going to copy that!  wink

 

FF = PI > S.E.T

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 Bitstreams produced by higher order modulators produce less noise at the low pass filter outputs

...seems to support lowpass RC filtering.  Are you aware of  anything to the contrary?

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ki0bk wrote:

Who-me wrote:
Engineering is the art of making what you want, from what you can get.

Oo, I'm going to copy that!  wink

 

I can't claim that it's original, it's been around a while :)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

avrcandies wrote:

 Bitstreams produced by higher order modulators produce less noise at the low pass filter outputs

...seems to support lowpass RC filtering.  Are you aware of  anything to the contrary?

 

I wish you are right. I mean I wonder why some ICs are produced to demodulate bit streams of Sigma-Delta of 2nd order and above.
Do you know of any reference that presents, in any way, a sigma-delta demodulator of second order? 

On my side, I couldn't find such a reference. Instead, I got tons of ideas about delta modulators smiley

 

Going to the 2nd order means that I have to rework almost all the calculations and codes of the project.

I will likely do it if I will be sure that an LP filter is enough to generate the sinewave properly (and I will be real surprised if this is the case wink ).;

 

Last Edited: Thu. Jan 27, 2022 - 08:28 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Who-me wrote:
but R-2R and PWM are practical. PWM even comes for free, on the MCU you already have.

 

Sorry, because I believe that, by using DDS code and R-2R, the circuit will not be as simple as a 3-pole RC filter (using low-cost resistors and capacitors) to generate sinewave from 20 Hz to 20 KHz. I do till I examine/analyse another simple circuit that does the same job and is based on the DDS topology.

 

I guess what I said also applies if PWM is used.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Who-me wrote:

KerimF wrote:

 

If the .wave command is enabled the generated Delta bits will be stored in an 8-bit wav file. I change its name for different ‘bits’ or ‘i_step’. The actual name is for bits=96 bits and i_step=120u.

 

 

If you like the look of a single serial bit stream from a D-FF, then consider the SPI capable ports in the MCU you have on hand.

 

D-FF ?

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

KerimF wrote:

Who-me wrote:

KerimF wrote:

 

If the .wave command is enabled the generated Delta bits will be stored in an 8-bit wav file. I change its name for different ‘bits’ or ‘i_step’. The actual name is for bits=96 bits and i_step=120u.

 

 

If you like the look of a single serial bit stream from a D-FF, then consider the SPI capable ports in the MCU you have on hand.

 

D-FF ?

 

D Flip Flip - Tagged A1 in your simulation schematic above. A SPI port is a series of 8 of those.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Who-me wrote:

KerimF wrote:

 

 

Who-me wrote:

 

KerimF wrote:

 

If the .wave command is enabled the generated Delta bits will be stored in an 8-bit wav file. I change its name for different ‘bits’ or ‘i_step’. The actual name is for bits=96 bits and i_step=120u.

 

 

If you like the look of a single serial bit stream from a D-FF, then consider the SPI capable ports in the MCU you have on hand.

 

D-FF ?

 

D Flip Flip - Tagged A1 in your simulation schematic above. A SPI port is a series of 8 of those.

 

Oh, I see. Thank you.

Sorry for not being clearer, I drew the schematic above not to emulate the MCU generator, but a conventional delta modulator of 1st order, followed by a 3-pole RC filter. Its purpose was to get a closer idea of the output THD and amplitude (after the passive filter) in function of frequency (by varying the parameter 'bits') and the delta step (by varying 'i_fd'). When I liked getting the generated bit stream (having a certain THD and amplitude for one frequency), I saved it as a wave file. Then I read its bit pattern (1/0) by using Excel.

 

If you remember well, my first attempt for this kind of generator was by using SPI ( https://www.avrfreaks.net/forum/... , post #38 ). But SPI doesn't have a free run mode and its break delay (1.25 or 1.5 cycle) let my work be somehow imperfect (not as good as I like it to be), no matter what I did for many months. So I dropped it for good.

Fortunately, I was inspired, lately, how to write a rather very fast code to output bits (1/0), read from an 8-bit byte table (to save memory space), with 4 MCU cycles only (for ATmega8L with 8 MHz crystal, OP [ 4 ] ).

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

KerimF wrote:

If you remember well, my first attempt for this kind of generator was by using SPI ( https://www.avrfreaks.net/forum/... , post #38 ). But SPI doesn't have a free run mode and its break delay (1.25 or 1.5 cycle) let my work be somehow imperfect (not as good as I like it to be), no matter what I did for many months. So I dropped it for good.

Fortunately, I was inspired, lately, how to write a rather very fast code to output bits (1/0), read from an 8-bit byte table (to save memory space), with 4 MCU cycles only (for ATmega8L with 8 MHz crystal, OP [ 4 ] ).

The SPI artifact is less than ideal, but it is not a brick wall, and SPI can output Sysclk/2 not Sysclk/4.

From what I've read (eg here http://www.batsocks.co.uk/readme... )  it idles MOSI hi, and needs an additional continual-load-delay of +1 SPI period (not needed in UART SPI mode) thus giving 9 bit period 'frames' or 18 sysclk frames, at highest SPI speed..

Is that what you saw ?  

In DAC terms, that is simply a fixed offset of 1/9 VCC.

Last Edited: Fri. Jan 28, 2022 - 09:23 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Who-me wrote:

In DAC terms, that is simply a fixed offset of 1/9 VCC.

 

Actually the fixed offset is  1.25/9.25 or 1.5/9.5 smiley  (this depends on the phase setting between the clock and data signals).  I wished it is 1/9.

So I wrote codes for these two odd cases and worked with them for many months. I got sinewaves for 102 frequencies (51 high + 51 low) by making 'bits' a multiple of 8 (since the SPI register is 8 bits) and creating tables for stream_bits = bits * 9.5/8 or * 9.25/8. These two odd offsets ended up giving me headaches laugh

 

In this project, things are changed dramatically. It became possible for me to create the main table of every frequency and its auxiliary ones automatically (by suitable codes of course) for the best output THD or for a certain desired amplitude. Also the number of available frequencies, in theory, increased from 51 to 2984 (3080-96) in every band (high and low). I said, in theory, because I decided lately to limit the frequency resolution (from 20 Hz to 20,000 Hz) to be not higher than 1% and not lower than 0.5%. So in case I will enable the internal RC oscillator at 8 MHz, the output frequency could be tuned between any two successive ones (+/- 0.5% is not big for this).

 

I divorced SPI so it is free for anyone now devil

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

KerimF wrote:

Who-me wrote:

In DAC terms, that is simply a fixed offset of 1/9 VCC.

Actually the fixed offset is  1.25/9.25 or 1.5/9.5 smiley  (this depends on the phase setting between the clock and data signals).  I wished it is 1/9.

Strange, that does not agree with the Video notes I linked to. Was that for Sysclk/4, not Sysclk/2 ?

Otherwise I cannot see where a quarter clock cycle can come from, as that is less than Sysclk at Sysclk/2 ? (but is possible at sysclk/4) 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Who-me wrote:

KerimF wrote:

 

 

Who-me wrote:

 

In DAC terms, that is simply a fixed offset of 1/9 VCC.

Actually the fixed offset is  1.25/9.25 or 1.5/9.5 smiley  (this depends on the phase setting between the clock and data signals).  I wished it is 1/9.

Strange, that does not agree with the Video notes I linked to. Was that for Sysclk/4, not Sysclk/2 ?

Otherwise I cannot see where a quarter clock cycle can come from, as that is less than Sysclk at Sysclk/2 ? (but is possible at sysclk/4) 

 

 

In the register SPCR, the bits, SPR1 and SPR0, set the SPI clock rate:
00 fosc/4
01 fosc/16
10 fosc/64
11 fosc/128

 

It seems that the AVR MCU on the video (I couldn't see it) is not ATmega8. 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

KerimF wrote:

Who-me wrote:

KerimF wrote:

 

 

Who-me wrote:

 

In DAC terms, that is simply a fixed offset of 1/9 VCC.

Actually the fixed offset is  1.25/9.25 or 1.5/9.5 smiley  (this depends on the phase setting between the clock and data signals).  I wished it is 1/9.

Strange, that does not agree with the Video notes I linked to. Was that for Sysclk/4, not Sysclk/2 ?

Otherwise I cannot see where a quarter clock cycle can come from, as that is less than Sysclk at Sysclk/2 ? (but is possible at sysclk/4) 

In the register SPCR, the bits, SPR1 and SPR0, set the SPI clock rate:
00 fosc/4
01 fosc/16
10 fosc/64
11 fosc/128

A /4 could explain the 0.25 SPI clk quanta.

 

There is also this, in ATmega8 data  : Bit 0  SPI2X: Double SPI Speed Bit, allows a /2 setting

 

I did find this, which is for a lower speed SPI test, but does revel one important detail = notice on 2nd byte how MOSI goes hi on last clock edge, ( = 9th bit issue)  but the duration is less than SPI CLK, shows that the DATA load resets the SPI clock divider. 

That also can explain how you saw fractional SPI period delays.

 

 

From https://mansfield-devine.com/spe...

 

It still should be possible to get a stable 18 sysclk frame, for a /2 SPI clock divider, otherwise those AVR video examples would not work.

Newer AVRs with a FIFO in the SPI port, I expect do not have this issue.

 

 

Last Edited: Sat. Jan 29, 2022 - 07:11 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Who-me wrote:

There is also this, in ATmega8 data  : Bit 0  SPI2X: Double SPI Speed Bit, allows a /2 setting

 

You are right.

I didn't use it because I had to also double the number of bits for every frequency to generate 20 Hz to 20 KHz of interest. Also the number of bits should be a multiple of 8 only (no fraction) which lets the resolution of the generated frequencies be wider 8 times.

 

But, obviously, setting this bit, with a 16 MHz crystal (ATmega8A), higher frequencies could be generated with ease (80.81 KHz for 99-bit stream... the fixed 9th bits included).

 

In any case (using SPI or not), the optimum pattern of the delta bit stream needs to be found, for every possible frequency, that gives the lowest THD or a desired output amplitude.

 

Let us agree that the fixed extra 9th bit (even with no bit fraction), included in the SPI stream, lets writing an automated code, to find out the optimum table for every possible frequency, be a bit harder than in the case of a clean bit stream.

 

Naturally, after I found out how to write a code that outputs continuously successive bits (not necessarily a multiple of 8), read from an 8-bit byte table (of 1 period), with an interval of 4 cycles only, using the SPI protocol became no more a priority for this project.

I will upload this code ( OP [ 4 ] ) in the near future after uploading and discussing the previous ones ( OP [ 1 ] and [ 2 ] ), I did, first. For instance, I doubt this code could be found by searching on the internet. I was able writing it not because I am smarter than the expert programmers in the world but because I really felt the need to do it. In other words, even the most intelligent human on earth won't find a certain solution if he is not interested in finding it in the first place. That is why we may hear the saying: "Necessity is the mother of invention".

 

Last Edited: Sun. Jan 30, 2022 - 07:54 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

KerimF wrote:

Naturally, after I found out how to write a code that outputs continuously successive bits (not necessarily a multiple of 8), read from an 8-bit byte table (of 1 period), with an interval of 4 cycles only

 

Interesting. I wonder if that's the same technique I used to generate video with no additional chips?

#1 Hardware Problem? https://www.avrfreaks.net/forum/...

#2 Hardware Problem? Read AVR042.

#3 All grounds are not created equal

#4 Have you proved your chip is running at xxMHz?

#5 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand."

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Brian Fairchild wrote:

KerimF wrote:

Naturally, after I found out how to write a code that outputs continuously successive bits (not necessarily a multiple of 8), read from an 8-bit byte table (of 1 period), with an interval of 4 cycles only

 

Interesting. I wonder if that's the same technique I used to generate video with no additional chips?

 

About 40 years ago, I tried appending a moving message to analog video signals outputted by a video recorder (Sony Betamax). I had to leave this project before finishing it completely because I had to focus instead on the ones which were needed by the local consumers/market and from which I was able to gain my daily bread wink

I am not sure now what could be required for generating the today's digital video, but surely the bit rate needs to be relatively very high and your code seems to be very interesting as well.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

KerimF wrote:

...but surely the bit rate needs to be relatively very high and your code seems to be very interesting as well.

 

This was analogue video.

 

My engineering background is broadcast TV and I was interested to see if I could generate a full specification PAL synchronising signal which met all the requirement of the standards, all in an AVR. I've done it previously, using '51 series chips, but needed external logic chips. The '51 dealt with the vertical signals, and the genlock PLL, but H sync was a counter chain. The magic Fcpu for an AVR turns out to be 12MHz and after a bid of ASM code I had a fully compliant sync signal. I then wondered if I could use it to generate a character display to identify the signal source. It turns out that you can but it needs a 'trick' to output a bitstream which has no gaps. SPI was out as the early AVRs had that gap. So I came up with a neat way to do it with minimal CPU cycles.

#1 Hardware Problem? https://www.avrfreaks.net/forum/...

#2 Hardware Problem? Read AVR042.

#3 All grounds are not created equal

#4 Have you proved your chip is running at xxMHz?

#5 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand."