Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 09:47 18 Sep 2025 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : MM+: GUI controlled waveform generator

Author Message
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 10406
Posted: 04:32am 19 Sep 2015
Copy link to clipboard 
Print this post

While developing the tutorial on CFunctions I played with the CVREF voltage hardware in the PIC32, something new for me. By configuring this you can get a 4-bit DAC output on pin-23 of the 64-bit MM+ (pin-29 on the 100 pin part, pin 25 of a 28-pin MX170 and pin 14 of a 44-pin part). In the tutorial thread we developed a very simple demo of the CFunction. This was only intended to help in the tutorial but the functionality that could be achieved was surprisingly good.

In this "full" version I have added a GUI using the touch screen on the ILI9341 display running on a MM+. It allows a range of waveforms to be created between 1 and 50,000Hz. The user interface would need reworking on a uM2 to replace the GUI commands but the cFunction will work as is.




The CFunction was written to run until it receives a ground input on a specified I/O pin. I've changed this and used the new facilities in 4.7 to tell it to look at the T_IRQ pin.

"while(PinRead(Option->TOUCH_IRQ))"

So when the touch input is used it automatically returns control to Basic which can then process the GUI commands. Much to my surprise this works beautifully and is a very simple protocol that can be used for many applications.

The GUI allows selection between sine, triangle, square, and saw tooth waves. I have also modified the CFunction to accept the frequency as a floating point number. This allows the exact frequencies such as middle-C (261.6 Hz) to be input.

Of course a 4-bit DAC gives a fairly rough waveform but with judicious use of an RC-filter it can be smoothed to give a quite good output.

10Kohm/1nF works nicely at 1000Hz
10Kohm/220pf works at 5000HZ

In the picture I've used 10K/4.7nF with a 261.6 HZ Middle-C output





If you really wanted to be clever you could connect the ground end of a range of capacitors to various PIC pins and select the filtering based on the frequency chosen by switching pins between high impedance (inputs) or low outputs.

Just one point about the output from CVREF (DAC). It is very high impedance so I use a BUF634 after the filter to create a 50ohm output.

The BUF634 is a great device if a little pricey. It is a unity gain opamp with up to 250ma drive capability in a 5-pin TO220 style package. Only 4 pins need to be used, VCC, GND, Vin, Vout, and it works happily on a single 5V supply. It even survives a continuous short-circuited output. Of course any unity-gain stable, single supply, opamp with near rail-rail output could be used.

Another use of the CVREF would be to use it to create a tone output at a specific frequency for a specific time. If anyone is interested in this let me know and I'll post a modified version of the CFunction.

The Basic code for the Function Generator is :


'
' Micromite + frequency generator
'
' Uses the CVREF output on pin 23 as a 4-bit DAC
'
' The gui is designed for a ILI9341 display in landscape mode
'
dim frequency!=261.6 'middle C
dim mode$="sine"
DIM rtrn%
DIM sinewave%(31)=( 8,9,10,12,13,14,14,15,15,15,14,14,13,12,10,9,7,6,5,4,2,1,1,0,0,0,1,1,2,3,5,6)
CLS
gui interrupt pendown,penup
text 15,10,"Wave Select"
Text 195,10,"Micromite"
text 195,30,"FGen V1.0"
TEXT 195,160,"Frequency"
for i=0 to 359 step 3
circle 193+i/3,90+30*sin(rad(i)),2,,,rgb(magenta),rgb(magenta)
next i
gUI FRAME #1,"",0,0,180,239,rgb(green)
GUI Radio #2,"Sine",20,40,20,rgb(yellow)
GUI Radio #3,"Triangle",20,70,20,rgb(yellow)
GUI Radio #4,"Square",20,100,20,rgb(yellow)
GUI Radio #5,"Saw",20,130,20,rgb(yellow)
GUI Radio #6,"Off",20,160,20,rgb(green)
GUI Radio #7,"Exit",20,205,20,rgb(red)
GUI FRAME #8,"",185,0,134,150,rgb(green)
GUI FRAME #9,"",185,155,134,30,RGB(yellow)
GUI numberbox #10,185,190,134,49,rgb(yellow)
ctrlval(#2)=1
ctrlval(#10)=frequency!
rtrn% = funcgen(frequency!,mode$,sinewave%())
do
loop
'
sub pendown
end sub
'
sub penup
if ctrlval(#2) then mode$="sine"
if ctrlval(#3) then mode$="triangle"
if ctrlval(#4) then mode$="square"
if ctrlval(#5) then mode$="saw"
if ctrlval(#6) then mode$="off"
if ctrlval(#7) then
cls
end
endif
frequency!=ctrlval(#10)
if frequency!>50000 then frequency!=50000 'max usable frequency
if frequency!<=0 then frequency!=1 'min usable frequency
pause 150 ' wait for bounces
text 15,10,"Wave Select" ' Repaint a non-GUI item
if mode$<>"off" then rtrn%=funcgen(frequency!,mode$,sinewave%())
end sub

CFunction funcgen
00000000
27BDFFC8 AFBF0034 AFBE0030 AFB7002C AFB60028 AFB50024 AFB40020 AFB3001C
AFB20018 AFB10014 AFB00010 00A08021 00C0B821 3C119D00 8E330058 8C920000
8E22009C 0040F809 3C044200 02402021 0260F809 00402821 0040A021 8E330064
8E230000 8E220080 8C640000 0040F809 00002821 00409021 8E22009C 0040F809
3C044000 02402021 0260F809 00402821 8E32007C 8E230064 00402021 0060F809
02802821 0240F809 00402021 00408821 00001021 40824800 0220B021 3C159D00
24120053 3C13BF81 24140020 10000022 0011F140 40024800 0043102B 1440FFFD
00000000 82020001 10520006 00711821 10470004 2C860010 01041023 10000010
0086100B 82060002 50C9000D 8CA20000 14CA0003 00000000 10000009 8CA20000
10CB0004 2C820010 14CC0005 00041042 2C820010 00003021 01A2300B 00C01021
34428040 AE629800 24840001 1494FFE1 24A50008 02DEB021 8EA30090 8EA20020
0040F809 80640017 1040000B 02E02821 02C01821 00002021 24090049 240A0069
240B0051 240D000F 240C0071 24070073 1000FFD0 2408001F 34038000 3C02BF81
AC439804 02201021 00001821 8FBF0034 8FBE0030 8FB7002C 8FB60028 8FB50024
8FB40020 8FB3001C 8FB20018 8FB10014 8FB00010 03E00008 27BD0038
End CFunction


The Cfunction code is:


long long funcgen(float *freq, char mode[], long long sinewave[]){
unsigned int step;
unsigned int ramp;
float samplefreq=FMul(*freq,LoadFloat(0x42000000)); //frequency at which each step must be changed
float tick_rate;
tick_rate = FDiv(IntToFloat(CurrentCpuSpeed),LoadFloat(0x40000000)); //get the number of clock ticks per second
unsigned int dwell=FloatToInt(FDiv(tick_rate,samplefreq));
unsigned int next_clock=dwell;
unsigned int current_ticks=0;
asm volatile("mtc0 %0, $9": "+r"(current_ticks)); //set the current number of ticks to 0
while(PinRead(Option->TOUCH_IRQ)){
for ( ramp = 0; ramp <= 31; ramp ++){
do{
asm volatile("mfc0 %0, $9" : "=r"(current_ticks));//get the time in ticks since zeroed
}while(current_ticks<next_clock);
next_clock+=dwell;
if(mode[1]!=83 && mode[1]!=115){ //mode doesn't start with an "S" or "s"
if ( ramp <= 15 ){
// ramp up
step = ramp;
} else {
// ramp down
step = 31 - ramp;
}
} else if (mode[2]==73 || mode[2]==105) { //sIne wave
step=sinewave[ramp];
} else if (mode[2]==81 || mode[2]==113){ //sQuare wave
step = ramp >15 ? 0 : 15;
} else { //must be saw tooth
step=ramp/2;
}
CVREFOpen( CVREF_ENABLE | CVREF_OUTPUT_ENABLE | CVREF_RANGE_HIGH| CVREF_SOURCE_AVDD | step );
}
}
CVREFClose(); // Disable CVREF (not executed)
return dwell;
}

 
kiiid

Guru

Joined: 11/05/2013
Location: United Kingdom
Posts: 671
Posted: 07:26am 19 Sep 2015
Copy link to clipboard 
Print this post

I must say, this is a *VERY* good job!
http://rittle.org

--------------
 
Chris Roper
Senior Member

Joined: 19/05/2015
Location: South Africa
Posts: 280
Posted: 11:35am 19 Sep 2015
Copy link to clipboard 
Print this post

This is the first application I have seen that actually makes me want to go out and purchase a touch screen display. This could easily form the basis of a hybrid digital/analogue synthesiser among several other uses that spring to mind.

Cheers
Chris



http://caroper.blogspot.com/
 
viscomjim
Guru

Joined: 08/01/2014
Location: United States
Posts: 925
Posted: 04:22pm 19 Sep 2015
Copy link to clipboard 
Print this post

simply amazing matherp!!!!!!! This just keep getting better and better.
 
WhiteWizzard
Guru

Joined: 05/04/2013
Location: United Kingdom
Posts: 2948
Posted: 08:30pm 19 Sep 2015
Copy link to clipboard 
Print this post

Peter,

Just like the other posts have mentioned, this is absolutely brilliant
And what a great demonstration as to the power of the MM, wonderfully showing the speed that something quite 'complex' can be created.

The most annoying thing is that I am away from home this weekend so can not try it out for a couple more days!

If anyone out there tries this, please post a comment as to how you get on . . . .

WW

 
boss

Senior Member

Joined: 19/08/2011
Location: Canada
Posts: 268
Posted: 06:43am 20 Sep 2015
Copy link to clipboard 
Print this post


@matherp

And if you add one of these AD9833 modules you get the signal generator covers band from less then 1Hz to 12.5 MHz (with simple low pass filter or ~6MHz w/o filter.
The module price is ~$6 for basic not -amplified module while amplified version is around $10. Together with graphic display you have a nice equipment for less than $30.







Bo



 
Print this page


To reply to this topic, you need to log in.

The Back Shed's forum code is written, and hosted, in Australia.
© JAQ Software 2025