Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 02:06 13 Nov 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 : Micromite Musical Box

     Page 1 of 2    
Author Message
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 10572
Posted: 05:44am 19 Sep 2015
Copy link to clipboard 
Print this post

I'm feeling silly this afternoon

Here is a CFunction that outputs a sine wave of a specified frequency for a specified length of time using the CVREF output on the Micromite (pin-23 of the 64-bit MM+, pin-29 on the 100 pin MM+, pin 25 of a 28-pin uM2 and pin 14 on a 44-pin uM2). Use a 10K resistor from the pin to your amplifier and a 4.7nF capacitor across the input of the amplifier. Please note you need 4.7b28 or later to run this.

Here is the clever bit:


long long tone(float *freq, float *duration, 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;
unsigned int duration_in_ticks;
tick_rate = FDiv(IntToFloat(CurrentCpuSpeed),LoadFloat(0x40000000)); //get the number of clock ticks per second
duration_in_ticks=FloatToInt(FMul(*duration,tick_rate));
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(current_ticks<duration_in_ticks){
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;
step=sinewave[ramp];
CVREFOpen( CVREF_ENABLE | CVREF_OUTPUT_ENABLE | CVREF_RANGE_HIGH| CVREF_SOURCE_AVDD | step );
}
}
CVREFClose(); // Disable CVREF (not executed)
return dwell;
}


and here is the very silly bit


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)
const C0! = 16.35
const Cs0_Db0! = 17.32
const D0! = 18.35
const Ds0_Eb0! = 19.45
const E0! = 20.60
const F0! = 21.83
const Fs0_Gb0! = 23.12
const G0! = 24.50
const Gs0_Ab1! = 25.96
const A1! = 27.50
const As1_Bb1! = 29.14
const B1! = 30.87
const C1! = 32.70
const Cs1_Db1! = 34.65
const D1! = 36.71
const Ds1_Eb1! = 38.89
const E1! = 41.20
const F1! = 43.65
const Fs1_Gb1! = 46.25
const G1! = 49.00
const Gs1_Ab2! = 51.91
const A2! = 55.00
const As2_Bb2! = 58.27
const B2! = 61.74
const C2! = 65.41
const Cs2_Db2! = 69.30
const D2! = 73.42
const Ds2_Eb2! = 77.78
const E2! = 82.41
const F2! = 87.31
const Fs2_Gb2! = 92.50
const G2! = 98.00
const Gs2_Ab3! = 103.83
const A3! = 110.00
const As3_Bb3! = 116.54
const B3! = 123.47
const C3! = 130.81
const Cs3_Db3! = 138.59
const D3! = 146.83
const Ds3_Eb3! = 155.56
const E3! = 164.81
const F3! = 174.61
const Fs3_Gb3! = 185.00
const G3! = 196.00
const Gs3_Ab4! = 207.65
const A4! = 220.00
const As4_Bb4! = 233.08
const B4! = 246.94
const C4! = 261.63
const Cs4_Db4! = 277.18
const D4! = 293.66
const Ds4_Eb4! = 311.13
const E4! = 329.63
const F4! = 349.23
const Fs4_Gb4! = 369.99
const G4! = 392.00
const Gs4_Ab5! = 415.30
const A5! = 440.00
const As5_Bb5! = 466.16
const B5! = 493.88
const C5! = 523.25
const Cs5_Db5! = 554.37
const D5! = 587.33
const Ds5_Eb5! = 622.25
const E5! = 659.25
const F5! = 698.46
const Fs5_Gb5! = 739.99
const G5! = 783.99
const Gs5_Ab6! = 830.61
const A6! = 880.00
const As6_Bb6! = 932.33
const B6! = 987.77
const C6! = 1046.50
const Cs6_Db6! = 1108.73
const D6! = 1174.66
const Ds6_Eb6! = 1244.51
const E6! = 1318.51
const F6! = 1396.91
const Fs6_Gb6! = 1479.98
const G6! = 1567.98
const Gs6_Ab7! = 1661.22
const A7! = 1760.00
const As7_Bb7! = 1864.66
const B7! = 1975.53
const C7! = 2093.00
const Cs7_Db7! = 2217.46
const D7! = 2349.32
const Ds7_Eb7! = 2489.02
const E7! = 2637.02
const F7! = 2793.83
const Fs7_Gb7! = 2959.96
const G7! = 3135.96
const Gs7_Ab8! = 3322.44
const A8! = 3520.00
const As8_Bb8! = 3729.31
const B8! = 3951.07
const C8! = 4186.01
const Cs8_Db8! = 4434.92
const D8! = 4698.63
const Ds8_Eb8! = 4978.03
const E8! = 5274.04
const F8! = 5587.65
const Fs8_Gb8! = 5919.91
const G8! = 6271.93
const Gs8_Ab9! = 6644.88
const A9! = 7040.00
const As9_Bb9! = 7458.62
const B9! = 7902.13
const cadence!=0.1 ' length of a 1/16th note in seconds
dim note!,duration!
DIM i%,rtrn%
dim happy_birthday_n!(24)=(G4!,G4!,A5!,G4!,C5!,B5!,G4!,G4!,A5!,G4!,D5!,C5!,G4!,G4!, G4!,E5!,C5!,B5!,A5!,F5!,F5!,E5!,C5!,D5!,C5!)
DIM happy_birthday_d!(24)=(6,2,4,4,4,8,6,2,4,4,4,8,6,2,4,4,4,4,4,6,2,4,4,4,8) 'length of notes in 1/16ths, crochet = 4/16
for i% = 0 to 24
note!=happy_birthday_n!(i%)
duration!=happy_birthday_d!(i%)*cadence!
rtrn%=tone(note!,duration!,sinewave%())
next i%
end
CFunction tone
00000000
27BDFFD0 AFBF002C AFB50028 AFB40024 AFB30020 AFB2001C AFB10018 AFB00014
00A08821 00C09021 3C109D00 8E140058 8C930000 8E02009C 0040F809 3C044200
02602021 0280F809 00402821 0040A821 8E140064 8E030000 8E020080 8C640000
0040F809 00002821 00409821 8E02009C 0040F809 3C044000 02602021 0280F809
00402821 00409821 8E14007C 8E020058 8E240000 0040F809 02602821 0280F809
00402021 00408821 8E14007C 8E020064 02602021 0040F809 02A02821 0280F809
00402021 00001821 40834800 0071182B 14600013 00405021 10000018 34048000
40034800 0065202B 1480FFFD 00000000 00A22821 8CE40000 34848040 AD249800
24C60001 14C8FFF6 24E70008 0071182B 14600006 014B5021 10000008 34048000
3C09BF81 24080020 00025940 02403821 01402821 1000FFEA 00003021 3C03BF81
AC649804 00001821 8FBF002C 8FB50028 8FB40024 8FB30020 8FB2001C 8FB10018
8FB00014 03E00008 27BD0030
End CFunction
Edited by matherp 2015-09-20
 
twofingers

Guru

Joined: 02/06/2014
Location: Germany
Posts: 1672
Posted: 07:25am 19 Sep 2015
Copy link to clipboard 
Print this post

  matherp said  I'm feeling silly this afternoon

the Happy Birthday shock? Happy Birthday!

Michael


causality ≠ correlation ≠ coincidence
 
Grogster

Admin Group

Joined: 31/12/2012
Location: New Zealand
Posts: 9755
Posted: 06:47pm 19 Sep 2015
Copy link to clipboard 
Print this post

Happy birthday to you, then.

You came up with this at a perfect time, as I had just about finished adding a 2nd MM chip to act as a PWM sound generator to my latest project, and now I don't have to.

I have yet to test your sample code, but am about to do that shortly.

Also, getting at pin23 on the MM+ might be tricky - it's pretty well boxed in by other tracking, however, there is always the wire link if you are desperate....(I try to make all my boards with no wire links if at all possible)

EDIT: Works on Beta 31, but works even better with a DC blocking cap in series with the output. I used 100n, and removed the 4n7, so you end up with a 10k resistor and 100n in series with pin23 and the audio input of the amp. Without the DC blocking cap, it still works OK, but you get nasty clicking sounds at the end of each note.

This is fantastic, and I can now get rid of the 170 I was going to use to do the same thing. I could not use the PWM channels on the MM+, as they were already all assigned, so this has really been brilliant timing, Peter!

EDIT: How do you issue just simple notes to the Cfunction WITHOUT all the constants and DIM's etc - I need to just be able to issue a single line of code, and have the Cfunction play that note, then return. I have tried several variations of the syntax to the Cfunction, but MMBASIC just moans that "Number too large." - even with numbers as low as 1 or 1.00.

Little prod?Edited by Grogster 2015-09-21
Smoke makes things work. When the smoke gets out, it stops!
 
WhiteWizzard
Guru

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

Ditto what Grogs is asking . . . How to drive the 'sound pin' with a simple one-liner.

Have not yet examined the code but this could be a useful addition to several projects I am working on here (freeing up the needed PWM pin). Need to drive a piezo at reasonable volume so will be trying this out as soon as I get back home.

Bad timing though Peter as I had already left home with the family to celebrate my daughters birthday. I have a MuP with me but no speaker/amp

WW
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 10572
Posted: 09:33pm 19 Sep 2015
Copy link to clipboard 
Print this post

  Quote  How to drive the 'sound pin' with a simple one-liner


If you had been reading the CFunction tutorials carefully you would know the answer

You can't use float literals with CFunctions so:

i%=tone(261.6,0.5,sinewave%()) won't work

a!=261.6
b!=0.5
i%=tone(a!,b!,sinewave%()) should work fine

Of course you need to have run something first to load up sinewave%()
 
Grogster

Admin Group

Joined: 31/12/2012
Location: New Zealand
Posts: 9755
Posted: 09:43pm 19 Sep 2015
Copy link to clipboard 
Print this post

I don't get what the call to 'sinewave%' is all about. You have note in a!, you have duration in b!. There is an array with data in sinewave, but then you call it in the Cfunction with no reference to any point in the array - '()' - I don't follow that.

I have been reading through the other Cfunction thread, but I am having trouble following it. I will keep reading it, but C code confuses the hell out of me. I guess it is simply cos I don't understand any of the C language syntax, so it just looks like gobble-de-gook to me. However, given some time, I am sure I could pick it up, but I don't have enough of the aformentioned time.
Smoke makes things work. When the smoke gets out, it stops!
 
Grogster

Admin Group

Joined: 31/12/2012
Location: New Zealand
Posts: 9755
Posted: 09:49pm 19 Sep 2015
Copy link to clipboard 
Print this post

Owwwww - I am getting a result now.....





I am just using zero for the 'Sinewave%' reference, and it is giving me tones, which is what I want.
Smoke makes things work. When the smoke gets out, it stops!
 
WhiteWizzard
Guru

Joined: 05/04/2013
Location: United Kingdom
Posts: 2959
Posted: 09:56pm 19 Sep 2015
Copy link to clipboard 
Print this post

Grogs, Silly question - does changing the value from 0 effectively change the volume? I am assuming the Sinewave data 'simulates' amplitude of the output??
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 10572
Posted: 09:58pm 19 Sep 2015
Copy link to clipboard 
Print this post

  Quote  I am just using zero for the 'Sinewave%' reference, and it is giving me tones, which is what I want.


You don't need anything in between the brackets. This is just the same as passing an array to a Basic function - see the example of passing arrays in the MMBasic manual.

The syntax "sinewave%()" just says pass the complete array. "sinewave%(0)" happens to work because the address of "sinewave(0)" is the same as the address of the start of the array but is not really correct and wouldn't work in Basic
 
Grogster

Admin Group

Joined: 31/12/2012
Location: New Zealand
Posts: 9755
Posted: 10:02pm 19 Sep 2015
Copy link to clipboard 
Print this post

Owwwww - try this code:


B=0.01
Do
For D=500 To 1000 Step 15
X=tone(D,B,0)
Next
Loop


Naturally, you need the Cfunction.

This is a nice alarm sound.

The experimentation continues.....
Smoke makes things work. When the smoke gets out, it stops!
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 10572
Posted: 10:10pm 19 Sep 2015
Copy link to clipboard 
Print this post

  Quote  Owwwww - try this code:


I have no idea what that is doing. The Cfunction is taking the contents of the memory from location 0 and using it as input to the DAC. It could be anything and it is a complete fluke you don't get a processor exception.

The sinewave%() array has amplitude values for a sine wave tailored for a 4-bit DAC.

Just put:

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)

into mm.startup and then your calls will always have access to it.
 
Grogster

Admin Group

Joined: 31/12/2012
Location: New Zealand
Posts: 9755
Posted: 10:13pm 19 Sep 2015
Copy link to clipboard 
Print this post

Acknowledged. Will do.
Smoke makes things work. When the smoke gets out, it stops!
 
Grogster

Admin Group

Joined: 31/12/2012
Location: New Zealand
Posts: 9755
Posted: 11:28pm 19 Sep 2015
Copy link to clipboard 
Print this post

Here are my tests, and now I understand how sinewave% is working, this code produces some alarm sounds.


DIM SW%(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)

T1=500:T2=250:T3=175:D=0.2
Do
For A=1 To 2
X=SOUND(T1,D,SW%())
X=SOUND(T2,D,SW%())
Next
Pause 3500
Loop

test1:
D=0.1
X=SOUND(T1,D,SW%())
X=SOUND(T2,D,SW%())
X=SOUND(T3,D,SW%())

test2:
B=0.01
Do
For D=500 To 1000 Step 100
X=SOUND(D,B,SW%())
Next
Loop

test3:
D=0.01
Do
For A=250 To 500
X=SOUND(A,D,SW%())
Next
Loop

test4:
D=0.1
Do
For A=1000 To 2000 Step 100
X=SOUND(A,D,SW%())
Next
Loop

test5:
D=0.015
Do
For A=1000 To 500 Step -50
X=SOUND(A,D,SW%())
Next
Loop

test6:
D=0.005
Do
For A=200 To 500 Step 25
X=SOUND(A,D,SW%())
Next
For A=500 To 200 Step -25
X=SOUND(A,D,SW%())
Next
Loop


End


CFunction SOUND
00000000
27BDFFD0 AFBF002C AFB50028 AFB40024 AFB30020 AFB2001C AFB10018 AFB00014
00A08821 00C09021 3C109D00 8E140058 8C930000 8E02009C 0040F809 3C044200
02602021 0280F809 00402821 0040A821 8E140064 8E030000 8E020080 8C640000
0040F809 00002821 00409821 8E02009C 0040F809 3C044000 02602021 0280F809
00402821 00409821 8E14007C 8E020058 8E240000 0040F809 02602821 0280F809
00402021 00408821 8E14007C 8E020064 02602021 0040F809 02A02821 0280F809
00402021 00001821 40834800 0071182B 14600013 00405021 10000018 34048000
40034800 0065202B 1480FFFD 00000000 00A22821 8CE40000 34848040 AD249800
24C60001 14C8FFF6 24E70008 0071182B 14600006 014B5021 10000008 34048000
3C09BF81 24080020 00025940 02403821 01402821 1000FFEA 00003021 3C03BF81
AC649804 00001821 8FBF002C 8FB50028 8FB40024 8FB30020 8FB2001C 8FB10018
8FB00014 03E00008 27BD0030
End CFunction


RUN this code, then [CTRL]-[C] to break the first loop, then GOTO the test routines to try the different sounds.

It is quite interesting, the crazy sounds you can make.
Smoke makes things work. When the smoke gets out, it stops!
 
twofingers

Guru

Joined: 02/06/2014
Location: Germany
Posts: 1672
Posted: 03:24am 23 Sep 2015
Copy link to clipboard 
Print this post

BTW here's something interesting about the Happy Birthday (PDF) song.
causality ≠ correlation ≠ coincidence
 
WhiteWizzard
Guru

Joined: 05/04/2013
Location: United Kingdom
Posts: 2959
Posted: 08:35am 23 Sep 2015
Copy link to clipboard 
Print this post

  twofingers said   BTW here's something interesting about the Happy Birthday (PDF) song.


43 pages of typical legal waffle to basically say that you can, (or is it that you can't) play Happy Birthday!

Do you think lawyers actually have fun creating documents like this? At least it keeps them in a job with mere mortals like us, and the rest of the planet, needing it interpreted into plain english!

Sorry - hope there are no lawyers out there reading this









 
twofingers

Guru

Joined: 02/06/2014
Location: Germany
Posts: 1672
Posted: 10:05pm 23 Sep 2015
Copy link to clipboard 
Print this post

  WhiteWizzard said  
  twofingers said   BTW here's something interesting about the Happy Birthday (PDF) song.


43 pages of typical legal waffle to basically say that you can, (or is it that you can't) play Happy Birthday!

Do you think lawyers actually have fun creating documents like this? At least it keeps them in a job with mere mortals like us, and the rest of the planet, needing it interpreted into plain english!

Sorry - hope there are no lawyers out there reading this


The point is
  Quote  Without the court judgement, it would not have been freely available in the public domain in the US until 2030, and in the EU until 31 December 2016. (Guardian )

But we should be happy and should not pursue the topic.

Michael
causality ≠ correlation ≠ coincidence
 
MikeO
Senior Member

Joined: 11/09/2011
Location: Australia
Posts: 275
Posted: 11:28pm 10 Dec 2015
Copy link to clipboard 
Print this post

Hi Matherp, I was hoping to use this Tone cfunction but I have been unable to make it work satisfactorily. I was planning to use a Piezo speaker but there is minimal drive out of the port. When I look with the scope although it is working the output is not driving to ground it is only riding on the very top of the dc level at 3.3v, it is only varying by maybe 50mv. Now what I have noticed is that if I set up the pin 25 (I am using a 28 pin MM2) as an output and run a short program that creates a square wave the wave form is perfect full waveform however after running the Tone Cfunction, your test program , If I go back and load my pin 25 test squarewave again, it also only produces a very small wave form on the top dc level. This will remain this way until you power cycle the chip. I have tried another chip and different versions b31 37 and ver 5.00, all behave the same. Any ideas.



Codenquilts
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 10572
Posted: 12:44am 11 Dec 2015
Copy link to clipboard 
Print this post

The output of CVREF is very high impedance. To test the program put a 100K resistor between pin 25 and GND and have a look on the scope (x10 probe). If this works then the piezo speaker is loading the pin too much. I've only tried it using an amp and haven't tried a 28-pin chip but it works on 44-pin and 64-pin so there is no reason 28 won't. Don't use any sort of SETPIN command in your program - the CFunction does this for you

The program leaves the pin as a CVREF output overriding SETPIN so that is why your square wave acts the same after running - reboot to fix this
 
Grogster

Admin Group

Joined: 31/12/2012
Location: New Zealand
Posts: 9755
Posted: 02:36am 11 Dec 2015
Copy link to clipboard 
Print this post

I have used this Cfunction a couple of times since matherp released it, and I can say it works great. I expect you are loading the pin too much, as Peter says.

In my case, I used a 10k resistor in series with the pin, and a 100n DC blocking cap before coupling that to an audio amplifier, and the tones are perfect. I have tried the Cfunction on a 28-pin device, and it works fine.

Just for the purposes of experimentation, have you tried coupling the CVREF output to an amp and little speaker? I would be suggesting you try that next to prove you are getting an output.
Smoke makes things work. When the smoke gets out, it stops!
 
hitsware
Guru

Joined: 23/11/2012
Location: United States
Posts: 535
Posted: 07:44am 11 Dec 2015
Copy link to clipboard 
Print this post

Not to negate the cleveritude of the CFunction sine wave,
but for musical purposes the simple PWM commands are,
perhaps, more germane. Too much effort towards the medium
can cloud the message. I went for years pursuing sinewaves
for music, only to end up back at squarewaves ......
But granted the PWM does allow for tonal varience.
It takes 2 outputs and an external gate, but 2 PWM's to
a XOR can also produce a sinewave (FWIW)
 
     Page 1 of 2    
Print this page
The Back Shed's forum code is written, and hosted, in Australia.
© JAQ Software 2025