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 : MM2(+): Tone command
Author | Message | ||||
matherp Guru Joined: 11/12/2012 Location: United KingdomPosts: 8605 |
Here is some code that will output a tone on any pin. This uses some of the new features in V5.1 and also some of Nathan's magic. It cannot be used at the same time as IR functionality. The format of the command is: TONE pin_number, frequency in Hz, duration in seconds The output is a square wave of the selected frequency. The command is non-blocking and returns to Basic immediately so to play "music" as in the example you need to pause after issuing the command before the next note. The frequency and duration are completely independent of the CPU speed. If the command is issued while a note is playing the new note will immediately replace the old one. There is only one restriction: calls to tone must be made with the frequency and duration defined by floating point variables and not literals so dim freq!= 400.0 dim dur! = 1.0 TONE 12, freq!, dur! is valid TONE 12, 400.0, 1.0 won't work and will lock up the Micromite As always the demo sticks a finger up to copyright option explicit option default none 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 i%,n!,duration!,notelength! 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 n!=happy_birthday_n!(i%) duration!=happy_birthday_d!(i%)*cadence! notelength!=duration! -0.05 'set a small gap between notes tone 12, n!, notelength! pause duration! * 1000' wait for the duration of the note played next i% end ' CSUB tone 00000022 'T1Int 3C029D00 8C43008C 8C640008 8C630004 AC830000 8C43008C 8C62000C 2444FFFF 1440000F AC64000C 24030010 3C02BF88 AC431064 3C02BF88 AC401068 3C02BF80 AC400600 3C029D00 8C4300AC AC600000 8C43008C AC600004 8C42008C AC400008 03E00008 00000000 'getFPC 27BDFFF8 AFBF0004 00852023 03E42021 ACC40000 8FBF0004 03E00008 27BD0008 'main 27BDFFC8 AFBF0034 AFB60030 AFB5002C AFB40028 AFB30024 AFB20020 AFB1001C AFB00018 0080A821 00A09021 00C08821 00002021 3C059D00 24A500D0 27A60010 0411FFE7 00000000 3C109D00 8E020058 8E440000 0040F809 8E250000 00408821 8E130058 8E02009C 0040F809 3C044000 02202021 0260F809 00402821 0040B021 8E020000 8C420000 8E03008C 3C04A5A5 3484A5A5 AC640000 3C0304C4 3463B401 0043182A 54600006 00022FC2 24430003 28450000 0065100B 10000003 00022883 00A22821 00052843 3C109D00 8E020080 00A02021 0040F809 00052FC3 8E030064 00402021 0060F809 8E450000 00408821 24120001 10000009 24140001 8E02009C 0040F809 3C044100 02202021 0260F809 00402821 00408821 001290C0 8E130068 8E020080 3404FFFF 0040F809 00002821 02202021 0260F809 00402821 5054FFEF 8E130064 24030010 3C02BF88 AC431064 3C02BF88 AC401068 3C109D00 8E020010 8EA40000 24050008 0040F809 00003021 8E13008C 8E020024 8EA40000 0040F809 24050007 AE620008 8E13008C 8E020028 0040F809 8EA40000 24030001 00431004 AE620004 8E02001C 8EA40000 0040F809 24050005 8FA40010 8E0200AC 3C039D00 24630000 00641821 AC430000 8E13008C 8E02007C 0040F809 02C02021 AE62000C 24020008 12420005 24100010 3A520040 24020020 00008021 0052800A 3C029D00 8C42007C 0040F809 02202021 3C03BF80 AC620620 36108000 3C02BF80 AC500600 2403001C 3C02BF88 AC4310A4 24030004 3C02BF88 AC4310A8 24020010 3C03BF88 AC621034 3C03BF88 AC621064 3C03BF88 AC621068 8FBF0034 8FB60030 8FB5002C 8FB40028 8FB30024 8FB20020 8FB1001C 8FB00018 03E00008 27BD0038 End CSUB C-source for those interested: #define _SUPPRESS_PLIB_WARNING // required for XC1.33 Later compiler versions will need PLIB to be installed #include <plib.h> // the pre Harmony peripheral libraries #include "../cfunctions.h" #define magic 0 #define t1pin 1 #define t1port 2 #define t1count 3 // void T1Int(void){ *(volatile unsigned int *)CFuncRam[t1port]=CFuncRam[t1pin]; if(!(CFuncRam[t1count]--)){ mT1IntEnable(0); T1CON=0; CFuncT1=0; CFuncRam[t1pin]=0; CFuncRam[t1port]=0; } } __attribute__((noinline)) void getFPC(void *a, void *b, volatile unsigned int *c) { *c = (unsigned int) (__builtin_return_address (0) - (b -a)) ; } void main(long long *pin, float *frequency, float *duration){ volatile unsigned int libAddr ; getFPC(NULL,&&getFPCLab,&libAddr) ; // warning can be ignored, stupid editor getFPCLab: { } int ps,clockspeed,divide=1; float counts,tickspersecond,tickrate; counts=FMul(*frequency,*duration); counts=FMul(counts,LoadFloat(0x40000000)); //number of interrupts for the pulse train clockspeed=CurrentCpuSpeed; CFuncRam[magic]=0xA5A5A5A5; if(clockspeed>80000000){ //start by assuming divide by 1 clockspeed/=4; } else { clockspeed/=2; } tickspersecond=IntToFloat(clockspeed); tickrate=FDiv(tickspersecond,*frequency); while(FCmp(tickrate,IntToFloat(0xFFFF))==1){ tickrate=FDiv(tickrate,LoadFloat(0x41000000)); divide*=8; } mT1IntEnable(0); ExtCfg(*pin,EXT_DIG_OUT,0); CFuncRam[t1port]=(int)(volatile unsigned int *)GetPortAddr(*pin,LATINV); CFuncRam[t1pin]=1<<GetPinBit(*pin); PinSetBit(*pin, LATCLR); CFuncT1=(unsigned int)&T1Int + libAddr; CFuncRam[t1count]=FloatToInt(counts); //used to hold count of cycles ps=0; if(divide==8)ps=0x10; if(divide==64)ps=0x20; PR1 = FloatToInt(tickrate); T1CON = 0x8000 | ps; // T5 on, prescaler as input mT1SetIntPriority(1); // high priority mT1ClearIntFlag(); // clear interrupt flag mT1IntEnable(1); } |
||||
twofingers Guru Joined: 02/06/2014 Location: GermanyPosts: 1141 |
Hi Peter, as always: big thanks for the demo and the C source! Regards Michael EDIT: Works great! (MX170/28 MMBasic 5.1). Output pin: 16 |
||||
Dylan Regular Member Joined: 17/06/2013 Location: NetherlandsPosts: 81 |
http://www.theguardian.com/music/2015/dec/10/happy-birthday-to-you-song-public-domain-warner-chappell-relinquish-copyrig ht Remove space before ht. Broken forum. |
||||
paceman Guru Joined: 07/10/2011 Location: AustraliaPosts: 1329 |
Hey, that's great Peter, we've got our TONE command back again. Here's one from DownUnder to our English friends. Best performed with cadence=0.15 (more serious!) Greg dim i%,n!,duration!,notelength!
dim a_tribute_n!(15)=(G4!,G4!,A5!,Fs4_Gb4!,G4!,A5!,B5!,B5!,C5!,B5!,A5!,G4!,A5!,G4!,Fs4_Gb4!,G4!) dim a_tribute_d!(15)=(4,4,4,6,2,4,4,4,4,6,2,4,4,4,4,6) for i% = 0 to 15 n!=a_tribute_n!(i%) duration!=a_tribute_d!(i%)*cadence! Edit: Ooops, got that seriously wrong - my suggested cadence should be 0.15 not 0.5. |
||||
paceman Guru Joined: 07/10/2011 Location: AustraliaPosts: 1329 |
Peter, I've just been looking at this some more and if you look at this WikipediA reference it seems the octave changes Vs frequency constants in the original post are incorrect. The reference says that octave changes occur between notes B and C, not between G and A. There's a table of "Standard Concert Pitch" near the bottom of the reference which gives the note/octave notations Vs the frequencies. I checked through it all and the following table below should be correct. I don't know whether your list is supposed to use a non-standard notation but I guess Happy Birthday would need a slightly modified note/octave list to sound "normal" with the standard one. Greg 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_Ab0! = 25.96 const A0! = 27.50 const As0_Bb0! = 29.14 const B0! = 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_Ab1! = 51.91 const A1! = 55.00 const As1_Bb1! = 58.27 const B1! = 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_Ab2! = 103.83 const A2! = 110.00 const As2_Bb2! = 116.54 const B2! = 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_Ab3! = 207.65 const A3! = 220.00 const As3_Bb3! = 233.08 const B3! = 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_Ab4! = 415.30 const A4! = 440.00 const As4_Bb4! = 466.16 const B4! = 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_Ab5! = 830.61 const A5! = 880.00 const As5_Bb5! = 932.33 const B5! = 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_Ab6! = 1661.22 const A6! = 1760.00 const As6_Bb6! = 1864.66 const B6! = 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_Ab7! = 3322.44 const A7! = 3520.00 const As7_Bb7! = 3729.31 const B7! = 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_Ab8! = 6644.88 const A8! = 7040.00 const As8_Bb8! = 7458.62 const B8! = 7902.13 |
||||
matherp Guru Joined: 11/12/2012 Location: United KingdomPosts: 8605 |
Now that's just silly but thanks for the correction |
||||
paceman Guru Joined: 07/10/2011 Location: AustraliaPosts: 1329 |
Actually it's dead simple to correct the notes - just change to the next lower octave for any notes starting with A or B, e.g. A4 becomes A3. For Happy Birthday the modified line is: Greg dim happy_birthday_n!(24)=(G4!,G4!,A4!,G4!,C5!,B4!,G4!,G4!,A4!,G4!,D5!,C5!,G4!,G4!, G4!,E5!,C5!,B4!,A4!,F5!,F5!,E5!,C5!,D5!,C5!)
|
||||
paceman Guru Joined: 07/10/2011 Location: AustraliaPosts: 1329 |
Yea, I'll never be even Mozart's toe, but it seems there is a reason. If you look at this link, and the piano keyboard layout you can see there's no sharp/flat (black) keys between the B & C's or the E & F's. In your original table there are several Gs_Ab notes, e.g. const Gs3_Ab4! = 207.65
which don't occur on a piano keyboard (maybe they do on something else, didgeridoo??) but it seems mixing the octave notation like that is a no-no. Why they don't break octaves between E/F instead of B/C I've no idea but I guess some clever person way back just went for it! Greg |
||||
hitsware Guru Joined: 23/11/2012 Location: United StatesPosts: 535 |
What is the advantage over simply using PWM ? |
||||
paceman Guru Joined: 07/10/2011 Location: AustraliaPosts: 1329 |
You can use PWM but it doesn't have a 'duration' parameter so the timing for each note would need separate coding and be considerably more complicated. Also the duty cycle parameter for PWM is redundant for music - it will always be 50% for music. Peter's C function also makes it available on all pins whereas the available PWM pins are more restricted. As he says though you can't use the MM's IR capability with it. Greg |
||||
hitsware Guru Joined: 23/11/2012 Location: United StatesPosts: 535 |
> it will always be 50% for music Not at all. Different duty cycles can be used for different timbres. > (maybe they do on something else, didgeridoo??) Assuming the equally tempered 12 note system, the digideroo has the same notes as the piano. It is only our construction of 'scales' that give the keyboard layout it has. |
||||
hitsware Guru Joined: 23/11/2012 Location: United StatesPosts: 535 |
@matherp what the musical universe is waiting for : https://www.parallax.com/sites/default/files/downloads/28020-PWMPAL-Documentation.pdf manifested on a micromite ...... but 32 bit resolution for dividers |
||||
paceman Guru Joined: 07/10/2011 Location: AustraliaPosts: 1329 |
Not at all. Different duty cycles can be used for different timbres. Yes, my bad, I probably should have said 'tones' rather than 'music' but you're right, even then timbre can be changed by duty cycle. Assuming the equally tempered 12 note system, the digideroo has the same notes as the piano. It is only our construction of 'scales' that give the keyboard layout it has. That was my attempt at humour and imagining a very other-worldly instrument. I guess if one of our original didgeridoo players had written down his music there would be no scales and none of us could read it - which makes you wonder if aboriginal rock art ever contains something like that. Greg |
||||
hitsware Guru Joined: 23/11/2012 Location: United StatesPosts: 535 |
https://www.youtube.com/watch?v=NaBI1SqIhak |
||||
matherp Guru Joined: 11/12/2012 Location: United KingdomPosts: 8605 |
https://www.parallax.com/sites/default/files/downloads/28020-PWMPAL-Documentation.pdf manifested on a micromite ...... but 32 bit resolution for dividers What are you asking for? Variable duty cycle? |
||||
hitsware Guru Joined: 23/11/2012 Location: United StatesPosts: 535 |
> What are you asking for? 4 channels individual pins, frequency, duty cycle each runs in backround once set probably easiest with chip with 4 hardware timers if there is one ? |
||||
Print this page |