A simple beacon keyer for the ATtiny13

Roger, G3XBM built a simple beacon for light communication using a K1EL beacon keyer chip and a handful of other components. I didn’t have any of those chips around, but I did have some Atmel ATtiny13s lying around. I hacked this simple program together to send Morse code in two different ways: on pin PB1 (pin six) there is a simple on/off keying signal. On pin PB0 (pin five) there is the same signal, modulated with an 800 hz signal. Roger used a similar output to send a modulated version of his call. I hardcoded this program to transmit slow Morse with three second dits (QRSS3). I loaded this onto an ATtiny13 tonight, and hooked a small white led the PWM output pin through a current limiting resistor. Using a primitive receiver I built before, a solar cell hooked into a Radio Shack powered speaker, I tested it out, and it seemed to work rather well: the 800hz tone was clear and audible. I’ll be playing with this some more, but for now, here’s the code:

/*
 * beaker.c 
 *
 * A simple beacon beeper for the ATtiny13
 */

// #define F_CPU        1200000UL
#define F_CPU   9600000UL

#include <inttypes.h>
#include <avr/io.h>
#include <avr/sleep.h>
#include <util/delay.h>

#define FREQ    (800)
#define DIT_MS  (3000)

#define OUTPUT  PB0             /* 800 Hz PWM signal, OC0A */
#define KEY     PB1             /* Just a keying output */
#define SWITCH  PB4             /* a switch between 12 WPM and QRSS3 */

void
dit()
{
    /* on */
    TCCR0A |= _BV(COM0A0) ;     /* enable OC0A */
    PORTB |= _BV(KEY) ;
    _delay_ms(DIT_MS) ;

    /* off */
    TCCR0A &= ~_BV(COM0A0) ;    /* disable... */
    PORTB &= ~_BV(KEY) ;
    _delay_ms(DIT_MS) ;
}

void
dah()
{
    /* on */
    TCCR0A |= _BV(COM0A0) ;
    PORTB |= _BV(KEY) ;
    _delay_ms(3*DIT_MS) ;

    /* off */
    TCCR0A &= ~_BV(COM0A0) ;
    PORTB &= ~_BV(KEY) ;
    _delay_ms(DIT_MS) ;
}

void
space()
{
    _delay_ms(2*DIT_MS) ;
}

void
ioinit()
{
    DDRB = _BV(KEY) | _BV(OUTPUT) | _BV(SWITCH) ;
    PORTB &= ~_BV(OUTPUT) ;

    TCCR0A = _BV(COM0A0) | _BV(WGM01) ;
    TCCR0B = _BV(CS01) | _BV(CS00) ;
    OCR0A = 93 ;
}

int
main(void) 
{
    ioinit() ;

    for (;;) {
        dah() ; dit() ; dah() ; space() ;
        dah() ; dit() ; dit() ; dit() ; dit() ; space() ;
        dit() ; dit() ; dit() ; dit() ; space() ;
        dah() ; dit() ; dit() ; dah() ; space() ;
        space() ; space() ;
    }

    return 0 ;
}