Generating cool tones using PWM

Hey Gus,

Why not make a harddrive speaker? - YouTube

Is htis what you want? :wink:

By the way, remember the question we had before “Why use analog output?” and then this post came after… This made us think…yeah! why not FEZ play audio? low quality is fine if all we want is tones or short words…I didn’t tell you about this but someone is looking into this feature :wink:

Hahah, yeah, it is! If you think about it, it does make sense. Motors work a lot like speakers…

Ahahah! I just realized that one of my far of cousins works at DMC!!

I added more to the project to allow for usb keyboard input. This will allow tones by pressing keys. I’ll post it later.

So then, when you connect a keyboard to Domino, you can play the simple tunes.

using System;
using System.Threading;
using GHIElectronics.NETMF.Hardware;
using GHIElectronics.NETMF.USBHost;

namespace Fez_Music
{
    public class Program
    {
        static PWM _fmPort = new PWM(PWM.Pin.PWM5);
        static uint _nanoSecond = 1000000000;

        static USBH_Keyboard keyboard = null;
        static object deviceEvents = new object(); ///use for thread syncing.


        static float C = 16.35F;
        static float D = 18.35F;
        static float E = 20.6F;
        static float F = 21.83F;
        static float G = 24.5F;
        static float A = 27.5F;
        static float B = 30.87F;

        static int currentScale = 1;
        public static void Main()
        {

            _fmPort.Set(false);

            USBHostController.DeviceConnectedEvent += new USBH_DeviceConnectionEventHandler(USBHostController_DeviceConnectedEvent);
            USBHostController.DeviceDisconnectedEvent += new USBH_DeviceConnectionEventHandler(USBHostController_DeviceDisconnectedEvent);

            //sleep the main thread so the app doesn't end
            Thread.Sleep(Timeout.Infinite);
        }

        static void USBHostController_DeviceDisconnectedEvent(USBH_Device device)
        {
            if (device.TYPE == USBH_DeviceType.Keyboard)
            {
                lock (deviceEvents)
                {
                    keyboard = null;
                }
            }
        }
        
        static void USBHostController_DeviceConnectedEvent(USBH_Device device)
        {
            if (device.TYPE == USBH_DeviceType.Keyboard)
            {
                USBH_Keyboard _keyboard = new USBH_Keyboard(device);
                _keyboard.KeyDown += new USBH_KeyboardEventHandler(_keyboard_KeyDown);
                _keyboard.KeyUp += new USBH_KeyboardEventHandler(_keyboard_KeyUp);
            }
        }

        static void _keyboard_KeyUp(USBH_Keyboard sender, USBH_KeyboardEventArgs args)
        {
            _fmPort.Set(false);
        }

        /// <summary>
        /// Plays the associated note when the related key is pressed
        /// if the number key is pressed, then the scale of the notes changes.
        /// No 2 keys can be pressed simultainously
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        static void _keyboard_KeyDown(USBH_Keyboard sender, USBH_KeyboardEventArgs args)
        {
            if (args.KeyAscii == 'c')
            {
                HoldNote(C, currentScale);
            }
            else if (args.KeyAscii == 'd')
            {
                HoldNote(D, currentScale);
            }
            else if (args.KeyAscii == 'e')
            {
                HoldNote(E, currentScale);
            }
            else if (args.KeyAscii == 'f')
            {
                HoldNote(F, currentScale);
            }
            else if (args.KeyAscii == 'g')
            {
                HoldNote(G, currentScale);
            }
            else if (args.KeyAscii == 'a')
            {
                HoldNote(A, currentScale);
            }
            else if (args.KeyAscii == 'b')
            {
                HoldNote(B, currentScale);
            }
            try
            {
                int _value = Int16.Parse(args.KeyAscii.ToString()) * 4;
                currentScale = _value > 0 ? _value : 1;
            }
            catch (Exception ex) { }
        }
        /// <summary>
        /// Plays a note on the speaker
        /// </summary>
        /// <param name="frequency">Frequency of the Note</param>
        /// <param name="duration">Duration of the note</param>
        private static void PlayNote(float frequency, int scale, int duration)
        {
            float _hertz = 0;
            _hertz = (float)1 / ((float)frequency * scale);
            _fmPort.SetPulse((uint)(_hertz * _nanoSecond), (uint)((_hertz / 2) * _nanoSecond));
            Thread.Sleep(duration);
            _fmPort.Set(false);
        }

        /// <summary>
        /// Sets the speaker to a specific tone
        /// </summary>
        /// <param name="frequency">frequency of the tone</param>
        /// <param name="scale">the scale of the note</param>
        private static void HoldNote(float frequency, int scale)
        {
            float _hertz = 0;
            _hertz = (float)1 / ((float)frequency * scale);
            _fmPort.SetPulse((uint)(_hertz * _nanoSecond), (uint)((_hertz / 2) * _nanoSecond));
        }
    }
}

When you press the keys corresponding to the notes you will hear the tone. You can then use the number keys to change the scale ( number keys 1 to 9)

Where is the video? :wink:

:frowning: Yea I’m not good at the video. Code however…

Not to nitpick, but…

#
if (args.KeyAscii == 'c')
 #
{
 #
HoldNote(C, currentScale);
 #
}
 #
else if (args.KeyAscii == 'd')
 #
{
 #
HoldNote(D, currentScale);
 #
}
 #
else if (args.KeyAscii == 'e')
 #
{
 #
HoldNote(E, currentScale);
 #
}
 #
else if (args.KeyAscii == 'f')
 #
{
 #
HoldNote(F, currentScale);
 #
}
 #
else if (args.KeyAscii == 'g')
 #
{
 #
HoldNote(G, currentScale);
 #
}
 #
else if (args.KeyAscii == 'a')
 #
{
 #
HoldNote(A, currentScale);
 #
}
 #
else if (args.KeyAscii == 'b')
 #
{
 #
HoldNote(B, currentScale);
 #
}

This would be more appropriate as a switch statement :slight_smile:

Otherwise, your driver looks really neat!

Wouldn’t args.KeyAscii need to return an integral value to be used in a switch statement?

This would work:

	switch (args.KeyAscii)
	{
		case 'c':
			HoldNote(C, currentScale);
			break;
			
		//..etc...
	}

Hum… ok then.

Yep, nothing more than a nitpick, but I just figured I’d let you know that there was a specific language construct for just that sort of thing… :wink:

Nah that’s kewl, char converts to byte so yea it can be used that way :smiley:

Hi guys,
I just post the video from the latest code of kurtnelle.

The first portion of the video from original kurtnelle’s code, and the second portion is Chris’s modified (using switch ).

Thanks Guz, who start this post. Kurtnelle for your codes ( three of them). especially the last one with the USB Host. This is really helpful for me. It’s an excellent sample of USBHost!
And Chris’s coding tips.

Sam

This is great…programmers from around the world coming together on making some fun and awesome projects…even if ti is making tones :slight_smile:

Just think, if we had to user map running, we could see exactly how far spread the source code is :wink:

Something quick and dirty in google maps or something :slight_smile:

I have the DFRobot piezo sound component but no idea how to use it. I see the Utility.Piezo function, but how would it know which connection it’s on? I also see a reference to a FEZ driver for it, but I can’t find it. This can’t be hard! Any help would be appreciated.

Here is another sound example. I’ve ported the Arduino RTTTL sketch to FEZ Domino. RTTTL stands for Ringtone Text Transfer Language and has been used in older Nokia phones. But you can find a lot of RTTTL files in the Web.
The video shows as an example the theme from ‘Misssion Impossible’.

The code can be found at my Google code page including more examples.

Enjoy! ;D