Netduino home hardware projects downloads community

Jump to content


The Netduino forums have been replaced by new forums at community.wildernesslabs.co. This site has been preserved for archival purposes only and the ability to make new accounts or posts has been turned off.

quadral's Content

There have been 1 items by quadral (Search limited from 29-March 23)


By content type

See this member's

Sort by                Order  

#6049 Netduino Iambic Morse Code Keyer

Posted by quadral on 13 December 2010 - 09:44 PM in Project Showcase

This is an iambic Morse code keyer. A dual lever paddle, a piezo buzzer and a potentiometer are connected to the Netduino. For details see attached file. The dual lever paddle consists of two separately actuated switches, one for the dits and one for the dahs. The speed of the keyer (5..50 wpm) is adjusted by the potentiometer. The Morse characters are decoded and printed on the debug console. The keyer supports iambic mode A and B. You have to change a constant in the code to select the iambic mode.

Have fun!

using System;
using System.Threading;
using System.Collections;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware;
using SecretLabs.NETMF.Hardware.Netduino;

namespace iambic_keyer
{
    public class Program
    {
        static OutputPort pin_led = new OutputPort(Pins.ONBOARD_LED, false);
        static PWM pin_buzzer = new PWM(Pins.GPIO_PIN_D10);
        static InputPort pin_left = new InputPort(Pins.GPIO_PIN_D11, false, Port.ResistorMode.PullUp);
        static InputPort pin_right = new InputPort(Pins.GPIO_PIN_D12, false, Port.ResistorMode.PullUp);
        static AnalogInput pin_speed = new AnalogInput(Pins.GPIO_PIN_A0); 

        static bool both_paddles_old;
        static bool both_paddles_released;

        enum TIMER_STATE
        {
            IDLE1, IDLE2, IDLE3, ON1, ON2, OFF
        };
        static TIMER_STATE timer_state;

        static long dit_time;
        static long duration;

        enum KEYER_MODE
        {
            IAMBIC_A, IAMBIC_B
        };
        static KEYER_MODE keyer_mode;

        static long element_stop_time;
        static long char_stop_time;
        static long word_stop_time;

        static uint buzzer_period;

        static int mchar;
        static int mchar_elements;

        static Hashtable mcode_tab = new Hashtable();


        
        public static void Main()
        {
            setup();

            while (true)
            {
                loop();
            }
        }



        static void setup()
        {

            mcode_tab[0x0201] = "A";  // 01
            mcode_tab[0x0408] = "B";  // 1000
            mcode_tab[0x040A] = "C";  // 1010
            mcode_tab[0x0304] = "D";  // 100
            mcode_tab[0x0100] = "E";  // 0
            mcode_tab[0x0402] = "F";  // 0010
            mcode_tab[0x0306] = "G";  // 110
            mcode_tab[0x0400] = "H";  // 0000
            mcode_tab[0x0200] = "I";  // 00
            mcode_tab[0x0407] = "J";  // 0111
            mcode_tab[0x0305] = "K";  // 101
            mcode_tab[0x0404] = "L";  // 0100
            mcode_tab[0x0203] = "M";  // 11
            mcode_tab[0x0202] = "N";  // 10
            mcode_tab[0x0307] = "O";  // 111
            mcode_tab[0x0406] = "P";  // 0110
            mcode_tab[0x040D] = "Q";  // 1101
            mcode_tab[0x0302] = "R";  // 010
            mcode_tab[0x0300] = "S";  // 000
            mcode_tab[0x0101] = "T";  // 1 
            mcode_tab[0x0301] = "U";  // 001
            mcode_tab[0x0401] = "V";  // 0001 
            mcode_tab[0x0303] = "W";  // 011 
            mcode_tab[0x0409] = "X";  // 1001 
            mcode_tab[0x040B] = "Y";  // 1011 
            mcode_tab[0x040C] = "Z";  // 1100 

            mcode_tab[0x050F] = "1";  // 01111 
            mcode_tab[0x0507] = "2";  // 00111
            mcode_tab[0x0503] = "3";  // 00011 
            mcode_tab[0x0501] = "4";  // 00001 
            mcode_tab[0x0500] = "5";  // 00000 
            mcode_tab[0x0510] = "6";  // 10000 
            mcode_tab[0x0518] = "7";  // 11000 
            mcode_tab[0x051C] = "8";  // 11100 
            mcode_tab[0x051E] = "9";  // 11110
            mcode_tab[0x051F] = "0";  // 11111 

            mcode_tab[0x0511] = "=";  // 10001
            mcode_tab[0x0615] = ".";  // 010101
            mcode_tab[0x0605] = "SK"; // 000101
            mcode_tab[0x0516] = "KN"; // 10110
            mcode_tab[0x0512] = "/";  // 10010
            mcode_tab[0x060C] = "?";  // 001100

            both_paddles_old = false;
            both_paddles_released = false;
            timer_state = TIMER_STATE.IDLE3;
            duration = 1; // 1 = dit, 3 = dah

            mchar = 0;
            mchar_elements = 0;

            pin_speed.SetRange(5, 50);  // wpm: 5 .. 50

            buzzer_period = 1000000 / 800; // buzzer frequency: 800 Hz

//            keyer_mode = KEYER_MODE.IAMBIC_A;
            keyer_mode = KEYER_MODE.IAMBIC_B;

        }




        static void loop()
        {
            int wpm = pin_speed.Read();
            bool right_paddle = !pin_right.Read();
            bool left_paddle = !pin_left.Read();
            long milliseconds = Utility.GetMachineTime().Ticks / System.TimeSpan.TicksPerMillisecond;

            dit_time = 1022 / wpm; // dit duration in milliseconds

            bool both_paddles = left_paddle && right_paddle;
            both_paddles_released = both_paddles_released || (both_paddles_old && !both_paddles);
            both_paddles_old = both_paddles;

            switch (timer_state)
            {
                case TIMER_STATE.IDLE1:
                    if (milliseconds >= char_stop_time)
                    {
                        int mcode;
                        mcode = mchar_elements << 8 | mchar;
                        object x = mcode_tab[mcode];
                        if (x != null)
                        {
                            Debug.Print(x.ToString());
                        }
                        mchar_elements = 0;
                        mchar = 0;
                        timer_state = TIMER_STATE.IDLE2;
                    }
                    goto ts_idle3;

                case TIMER_STATE.IDLE2:
                    if (milliseconds >= word_stop_time)
                    {
                        Debug.Print(" ");
                        timer_state = TIMER_STATE.IDLE3;
                    }
                    goto ts_idle3;

                case TIMER_STATE.IDLE3:
                ts_idle3:
                    if (keyer_mode == KEYER_MODE.IAMBIC_B && both_paddles_released)
                    {
                        both_paddles_released = false;
                        duration = duration == 1 ? 3 : 1;
                        timer_state = TIMER_STATE.ON1;
                    }
                    else if (left_paddle && !right_paddle)
                    {
                        duration = 1; // dit
                        timer_state = TIMER_STATE.ON1;
                    }
                    else if (!left_paddle && right_paddle)
                    {
                        duration = 3; // dah
                        timer_state = TIMER_STATE.ON1;
                    }
                    else if (left_paddle && right_paddle)
                    {
                        duration = duration == 1 ? 3 : 1;
                        timer_state = TIMER_STATE.ON1;
                    }
                    break;

                case TIMER_STATE.ON1:
                    element_stop_time = milliseconds + dit_time * duration; // dit or dah
                    pin_buzzer.SetPulse(buzzer_period, buzzer_period / 2); // Buzzer on
                    pin_led.Write(true); // LED on
                    timer_state = TIMER_STATE.ON2;
                    break;

                case TIMER_STATE.ON2:
                    if (milliseconds >= element_stop_time)
                    {
                        element_stop_time = milliseconds + dit_time; // space after dit or dah
                        pin_buzzer.SetPulse(0, 0); // Buzzer off
                        pin_led.Write(false); // LED off
                        timer_state = TIMER_STATE.OFF;
                    }
                    break;

                case TIMER_STATE.OFF:
                    if (milliseconds >= element_stop_time)
                    {
                        if (mchar_elements < 8)
                        {
                            switch (duration)
                            {
                                case 1:
                                    mchar = mchar << 1;  // dit = 0
                                    mchar_elements++;
                                    break;
                                case 3:
                                    mchar = (mchar << 1) + 1;  // dah = 1
                                    mchar_elements++;
                                    break;
                            }
                        }
                        char_stop_time = milliseconds + dit_time * 3; // gap between letters
                        word_stop_time = milliseconds + dit_time * 7; // gap between words
                        timer_state = TIMER_STATE.IDLE1;
                    }
                    break;

            }

        }

    }
}




Attached Thumbnails

  • netduino_keyer.png




home    hardware    projects    downloads    community    where to buy    contact Copyright © 2016 Wilderness Labs Inc.  |  Legal   |   CC BY-SA
This webpage is licensed under a Creative Commons Attribution-ShareAlike License.