I'm working on a project whereby I want to use the Pi to send some morse code (CW) over FM by feeding the CW signal into the mic input of a handheld radio I've stripped down.

The idea stems from this website where the chap is using a PIC based solution to generate some hard coded CW and feed into the mic input of the rig. I built one of these and downloaded his code and it works great.

Instead of using a PIC, can I use the Pi? I have some basic code to send logical 1's and 0's to the GPIO pin, actually the code I've doctored from various sites detailing how to send RTTY in C, but essentially its about switching the pin on / off at the right times. I dont get how the PIC itself generates audio. When i've tried putting the GPIO pin connected to the mic input, I'm not getting anything. I didnt really expect to, but I cant even make out any discernable changes in voltage.

Am I barking up the wrong tree? Any pointers appreciated.

2 Answers 2


You're actually pretty close at this point. The problem is that Morse code works on the basis of a carrier wave. That is to say a tone is either generated or not. While this is similar to binary on/off logic, the latter is actually simply a case of on or off of a static signal. It's the difference between generating ___----___--__ and generating ___-^_-___-^__.

The way the guy you linked does this is by turning the pin on and off very rapidly when transmitting so that a square wave approximates the sine wave a normal Morse code transmitter would use. This is different from simply turning the pin on and off. What you get as a result is a tone generated that sounds a bit more jagged than normal, but is a tone. His code uses a 1 millisecond delay, so you get an approximate frequency of 1000 Hz out. It should be possible to implement this on the Pi, but keep in mind that the Pi isn't real-time so it may hiss and stutter a little bit. It should still be understandable.

The guy's code for transmit a dah looks like this:

dah     MOVLW       01      ;   subroutine to do dah
        MOVWF       2E
agn3dah MOVLW       dahlen
        SUBWF       2E,W
        BTFSC       03,0
        GOTO        enddah
        BSF         06,1    ;   turn on pin B1
        MOVLW       01
        MOVWF       30
        CALL        time    ;   wait 1 millisecond
        BCF         06,1    ;   turn off pin B1
        MOVLW       01
        MOVWF       30
        CALL        time    ;   wait 1 millisecond
        MOVF        2E,W
        INCF        2E,F
        GOTO        agn3dah ;   loop up to do it again.
enddah  MOVLW       3C      ;   add a small delay
        MOVWF       30
        CALL        time    ;   wait 1 millisecond
        RETLW       00

That's a horrible mess of assembly, but it translate to something roughly like this in Python:

import RPi.GPIO as GPIO
import time
GPIO.setup(27, GPIO.OUT)
GPIO.output(27, GPIO.LOW)

def dah():
    for i in range(1, 99):
        GPIO.output(27, GPIO.HIGH)
        GPIO.output(27, GPIO.LOW)

The other approach would be to use something like a buzzer connected to the GPIO pin.

  • great reply thanks fred, appreciate the code also. a buzzer would be a good test actually, didnt think of that. will keep you posted :-)
    – user13523
    Commented Mar 16, 2014 at 14:08
  • Why not just use PWM as output, set the frequency to something audible (e.g. 2000Hz), and the duty cycle to 50% (and 0% for off).
    – Gerben
    Commented Mar 16, 2014 at 14:59
  • PWM might be made to work in this scenario, but it's a lot of extra overhead I think. Also, 2000 Hz is really quite high pitched. ><
    – Fred
    Commented Mar 16, 2014 at 20:44
  • thanks Gerben, good tip. About 600Hz will probably do for me though :-)
    – user13523
    Commented Mar 16, 2014 at 22:13
  • turns out i was on the right track all along - but wasnt using the correct GPIO numbering. I'm using wiringPi and was getting confused with pin numbers / GPIO numbers and wiringPi Pin numbers. sorted now though lol
    – user13523
    Commented Mar 18, 2014 at 16:26

Follow up to above answer:

CW is not FM, unless you plan to modulate a carrier with audio tones that comprise a sequence of Morse code. While you can use PWM, keep in mind that square waves are a really bad approximation of sine waves, and will generate many spurious emissions. Don't use it unless you plan to experiment for really short periods of time, or, if you possess a good, narrow passband filter that effectively smooths out your signal. In a short distance (and a transmit power output of, assuming a purely resistive feedpoint impedance of 50 ohms, I would guess that you would get about 0.22 watts of power, which will work for a short distance indoors.

Being a ham radio operator, I am obligated to tell you that, unless you plan to work in the ISM bands, you will need a license to legally transmit.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.