User Tools

Site Tools


tonegen_design

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
Last revision Both sides next revision
tonegen_design [2022/03/16 04:36]
dpisuperadmin [Minimal Tone Generator with Volume Control]
tonegen_design [2022/03/20 03:45]
dpisuperadmin
Line 12: Line 12:
  
 ==== Minimal Tone Generator with Volume Control ==== ==== Minimal Tone Generator with Volume Control ====
-A full synthesizer, as described below, may take more that its fair share of FPGA logic.  This is fine if the goal of the project is a synthesizer but is not fine if the user wants something that just beeps.  This section describes something that beeps and has volume control.+A full synthesizer may take more that its fair share of FPGA logic.  This is fine if the goal of the project is a synthesizer but is not fine if the user wants something that just beeps.  This section describes something that beeps but includes a volume control.
  
-The API for a simple tone generator might specify the musical note to play, the volume in the range of 0 to 100, and the number of milliseconds to play the note.  For example: +The API for a simple tone generator might specify the musical note to play, the volume in the range of 0 to 100, and the number of milliseconds to play the note.  We might also want to play a file of notes where each line the the file has the note, volume, and duration.  For example: 
-    dpset tonegen tone b4 30 200+    dpset tonegen note b4 30 200 
 +    dpset tonegen melody mymelody.txt
  
 {{ wiki:audiotaper.png?200|}} Square waves are easy to generate and have a pleasing sound since they have lots of higher harmonics.  A more difficult question for a simple tone generator is how to control the volume.  Human hearing perceives audio volume on a logarithmic scale.  Electronics manufactures use what is called a 'audio taper' for potentiometers in audio applications. The diagram to the right shows an audio taper and we want our gain control to follow the same curve. {{ wiki:audiotaper.png?200|}} Square waves are easy to generate and have a pleasing sound since they have lots of higher harmonics.  A more difficult question for a simple tone generator is how to control the volume.  Human hearing perceives audio volume on a logarithmic scale.  Electronics manufactures use what is called a 'audio taper' for potentiometers in audio applications. The diagram to the right shows an audio taper and we want our gain control to follow the same curve.
Line 26: Line 27:
  
  
-The other approach to volume control is to build a DAC out of resistors connected to the four FPGA pins dedicated to the peripheral.  Many DACs use what is called an 'R-2R' resistor network of give a linear response to the input values.  (See https://en.wikipedia.org/wiki/Resistor_ladder#R-2R)  We specifically do not want a linear response.  We want one in which the higher values are much greater than their linear equivalents. Shown below is a circuit that does this.  In it we swap the normal linear R-2R network resistors to get a 2R-R resistor network.  The gain of the circuit is clearly non linear.+The other approach to volume control is to build a DAC out of resistors connected to the four FPGA pins dedicated to the peripheral.  Many DACs use what is called an 'R-2R' resistor network of give a linear response to the input values.  (See https://en.wikipedia.org/wiki/Resistor_ladder#R-2R)  We specifically do **not** want a linear response.  We want one in which the higher values are much greater than their linear equivalents. Shown below is a circuit that does this.  In it we swap the normal linear R-2R network resistors to get a 2R-R resistor network.  The gain of the circuit is clearly non linear.
  
 {{wiki:r2-r.png?300}} {{wiki:r2-rgain.png?200}} {{wiki:r2-r.png?300}} {{wiki:r2-rgain.png?200}}
Line 32: Line 33:
 The minimum output of the 2R-R circuit is 0.013 and the maximum value is 0.9935, a ratio of low to high of about 76.  While we have lost a great deal of resolution, we have gone from 4 bits of dynamic range for the linear R-2R network to over 6 bits of dynamic range using a 2R-R network. The minimum output of the 2R-R circuit is 0.013 and the maximum value is 0.9935, a ratio of low to high of about 76.  While we have lost a great deal of resolution, we have gone from 4 bits of dynamic range for the linear R-2R network to over 6 bits of dynamic range using a 2R-R network.
  
-What if we combined the linear pulse density modulation with the non-linear DAC?  We could PDM control each of the FPGA output pins with a separate 4 bit counter.  Doing this gives 64K possible gain setting but since some combinations give the same gain there are only 14000 unique gain settings.  The minimum (one-sixteenth of the LSB) has a gain of 0.000817 and the maximum (all bits high) has a gain of 0.9314, giving us a dynamic range (log2(max/min)) of about 10 bits.   +{{ :wiki:tonegengain.png?200|}} What if we combined the linear pulse density modulation with the non-linear DAC?  We could PDM control each of the FPGA output pins with a separate 4 bit counter.  Doing this gives 64K possible gain settings. Since some combinations give the same gain there are only 14000 unique gain settings.  The minimum (one-sixteenth of the LSB) has a gain of 0.000817 and the maximum (all bits high) has a gain of 0.9314, giving us a dynamic range (log2(max/min)) of about 10 bits.  This is not too bad considering we have a 4 bit DAC. 
  
-Our design now has+Our design is now ready for a Verilog Wishbone implementation.  We should expect it to have 
 a 24 bit phase accumulator, a 24 bit phase accumulator,
 a 24 bit phase offset set by the host, a 24 bit phase offset set by the host,
Line 41: Line 42:
 an 8 bit duration counter (to count milliseconds), and an 8 bit duration counter (to count milliseconds), and
 an 8 bit duration set by the host, an 8 bit duration set by the host,
 +
 +(The diagrams in this section were generated using Octave.  The sources are attached to this section in a wiki comment.  Edit the page or contact the author to get the sources for the diagrams.)
 +
 +
 +
 +/* This block comment has the Octave source code to generate the above tables.
 +% Generate a log plot that shows a typical audio taper
 + x = 1:1:100;% Generate 100 points on an log curve and map the gain
 +% to setting in pwm - nonlinear DAC scheme.  This gives
 +% the actual table to use in the API driver modules.
 +% Manually add {0,0,0,0} and {15,15,15,15}.
 +
 +% Get the target gains
 +x = 1:1:100;
 +out = exp((5 .* x) ./ 100) ./ 150;
 +target_idx = 1;
 +% loop past all possible gains recording the first to pass out(target_idx)
 +idx = 0;
 + for i3 = 0:15;
 +  for i2 = 0:15;
 +   for i1 = 0:15;
 +    for i0 = 0:15;
 +     idx = idx +1;
 +     outval = ((i3 .* .73203) + (i2 .* .19608) + (i1 .* 0.05229) + (i0 .* 0.01307)) ./ 16;
 +     if outval > out(target_idx),
 +         %printf("%d %f {%d, %d, %d, %d},\n", target_idx, outval, i3, i2, i1, i0);
 +         printf("{%d, %d, %d, %d},\n", i3, i2, i1, i0);
 +         target_idx = target_idx + 1;
 +     end
 +    end
 +   end
 +  end
 + end
 +
 + out = exp((5 .* x) ./ 100) ./ 150;
 + plot(x, out);
 + title("Audio Taper", 'fontsize', 24);
 + xlabel("Gain Setting", 'fontsize', 18);
 + ylabel("Gain", 'fontsize', 18);
 + set([gca; findall(gca, 'Type','line')], 'linewidth', 4);
 + grid on;
 + print -dpng '/tmp/audiotaper.png';
 +
 +% Show a plot of linear gain
 +x=0:1:15;
 +out = x ./ 16;
 +plot(x, out);
 +title("Linear Attenuation",'fontsize', 24);
 +xlabel("Gain Setting", 'fontsize', 18);
 +ylabel("Gain", 'fontsize', 18);
 +set([gca; findall(gca, 'Type','line')], 'linewidth', 4);
 +grid on;
 +print -dpng '/tmp/linear-x.png';
 +
 +% Show a plot of a reciprocal gain function
 +x = 0:1:15;
 +out = 1 ./ ( 16 .- x);
 +plot(x, out);
 +title("1/x Attenuation",'fontsize', 24);
 +xlabel("Gain Setting", 'fontsize', 18);
 +ylabel("Gain", 'fontsize', 18);
 +set([gca; findall(gca, 'Type','line')], 'linewidth', 4);
 +grid on;
 +print -dpng '/tmp/one-over-x.png';
 +
 +% Show the output for PDM with the rate set to one-third
 +for x=1:1:32;
 +  if mod(x,3) == 0, out(x) = 1;
 +  else out(x) = 0;
 +  end
 +end
 +subplot(4,1,1), bar(out);
 +axis off
 +
 +% Generate the possible unique gain settings for four bit 2R-R network 
 +% where each bit has a four bit PWM control
 +idx = 0;
 + for i3 = 0:15;
 +  for i2 = 0:15;
 +   for i1 = 0:15;
 +    for i0 = 0:15;
 +     idx = idx +1;
 +     outval =(i3 .* .73203) + (i2 .* .19608) + (i1 .* 0.05229) + (i0 .* 0.01307);
 +     %outval =(i3 .* .5) + (i2 .* .25) + (i1 .* 0.125) + (i0 .* 0.0625);
 +     out(idx, :) = [ outval / 16 , i3, i2, i1, i0 ];
 +    end
 +   end
 +  end
 + end
 + sortout = sort(out);
 + uniqout = unique(sortout);
 + length(uniqout)
 + length(out)
 + uniqout(2)
 + uniqout(length(uniqout))
 +% Generate a plot of the gain of a four bit 2R-R DAC circuit.
 +for i3 = 0:1
 +  for i2 = 0:1
 +    for i1 = 0:1
 +      for i0 = 0:1
 +        idx = (8 .* i3) + (4 .* i2) + (2 .* i1) + (1 .* i0) + 1
 +        out(idx) = (i3 .* .73203) + (i2 .* 0.19608) + (i1 .* 0.05229) + (i0 .* 0.01307)
 +      end
 +    end
 +  end
 +end
 +plot(out);
 +title("2R-R Response",'fontsize', 24);
 +xlabel("Input Code", 'fontsize', 18);
 +ylabel("Vout", 'fontsize', 18);
 +set([gca; findall(gca, 'Type','line')], 'linewidth', 4);
 +grid on;
 +print -dpng '/tmp/r2-2.png';
 +
 +*/
 +
  
  
tonegen_design.txt · Last modified: 2022/03/20 03:51 by dpisuperadmin