|
Forum Index : Microcontroller and PC projects : Micromite Musical Box
| Page 1 of 2 |
|||||
| Author | Message | ||||
| matherp Guru Joined: 11/12/2012 Location: United KingdomPosts: 10572 |
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 |
||||
| twofingers Guru Joined: 02/06/2014 Location: GermanyPosts: 1672 |
the Happy Birthday shock? Happy Birthday!
Michael causality ≠ correlation ≠ coincidence |
||||
Grogster![]() Admin Group Joined: 31/12/2012 Location: New ZealandPosts: 9755 |
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? Smoke makes things work. When the smoke gets out, it stops! |
||||
| WhiteWizzard Guru Joined: 05/04/2013 Location: United KingdomPosts: 2959 |
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 KingdomPosts: 10572 |
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 ZealandPosts: 9755 |
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 ZealandPosts: 9755 |
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 KingdomPosts: 2959 |
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 KingdomPosts: 10572 |
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 ZealandPosts: 9755 |
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 KingdomPosts: 10572 |
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 ZealandPosts: 9755 |
Acknowledged. Will do. Smoke makes things work. When the smoke gets out, it stops! |
||||
Grogster![]() Admin Group Joined: 31/12/2012 Location: New ZealandPosts: 9755 |
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: GermanyPosts: 1672 |
BTW here's something interesting about the Happy Birthday (PDF) song. causality ≠ correlation ≠ coincidence |
||||
| WhiteWizzard Guru Joined: 05/04/2013 Location: United KingdomPosts: 2959 |
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: GermanyPosts: 1672 |
The point is But we should be happy and should not pursue the topic. Michael causality ≠ correlation ≠ coincidence |
||||
| MikeO Senior Member Joined: 11/09/2011 Location: AustraliaPosts: 275 |
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 KingdomPosts: 10572 |
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 ZealandPosts: 9755 |
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 StatesPosts: 535 |
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 |
|||||
| The Back Shed's forum code is written, and hosted, in Australia. | © JAQ Software 2025 |