/*
CTCSS ... sub audio tone generator (replacement for Yaesu FTS-7)
Target µC: ATtiny44
Auf der IARU Konferenz in Südafrika wurde beschlossen alle FM Umsetzter bis Ende 2014 mit CTCSS Tönen
auszustatten. Nach Möglichkeit sind die unten angeführten Töne zu verwenden:
OE1 EIA 01 67,0 Hz
OE2 EIA 08 88,5 Hz
OE3 EIA 26 162,2 Hz
OE4 EIA 11 84,8 Hz
OE5 EIA 12 100,0 Hz
OE6 EIA 13 103,5 Hz
OE7 EIA 04 77,0 Hz
OE8 EIA 08 88,5 Hz
OE9 EIA 07 85,4 Hz
Ausnahme: OE1XUU EIA26 162.2Hz
Die CTCSS Frequenz kann über PA2..PA0 gewählt werden
2012/10/07 OE1GCA, initial version
2013/02/23 OE1GCA, changes for ATtiny44
2013/05/09 OE1GCA, corrected fuse bits
avr-gcc -mmcu=attiny44 ctcss_t44.c -o ctcss_t44
avr-objcopy -O ihex ctcss_t44 ctcss_t44.hex
avrdude -c stk500v2 -pt44 -P/dev/ttyUSB0 -U lfuse:w:0x7f:m -U hfuse:w:0xdc:m
avrdude -c stk500v2 -pt44 -P/dev/ttyUSB0 -U flash:w:ctcss_t44.hex
(c) 2012,2013 by OE1GCA
*/
#include <avr/io.h>
#include <stdio.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#define F_CPU 12000000UL // 12 MHz
// fpwm = fclk / N*(1+TOP), where N is the prescaler (1, 8, 64, 256 or 1024)
// prescaler: 8
/* pwm sinus lookup table */
const uint16_t SLUT_32[8][32] PROGMEM = {
/* 162.2 Hz */ {
145,173,200,225,247,265,278,286,289,286,278,265,247,225,200,173,145,116,89,64,42,24,11,3,0,3,11,24,42,64,89,116},
/* 67 Hz */ {
350,418,483,544,597,640,672,692,699,692,672,640,597,544,483,418,350,281,216,155,102,59,27,7,0,7,27,59,102,155,216,281},
/* 88.5 Hz */ {
265,316,366,411,452,484,509,524,529,524,509,484,452,411,366,316,265,213,163,118,77,45,20,5,0,5,20,45,77,118,163,213},
/* 84.8 Hz */ {
276,330,382,429,471,505,531,547,552,547,531,505,471,429,382,330,276,222,170,123,81,47,21,5,0,5,21,47,81,123,170,222},
/* 100 Hz */ {
234,280,324,364,399,429,450,464,468,464,450,429,399,364,324,280,234,188,144,104,69,39,18,4,0,4,18,39,69,104,144,188},
/* 103.5 Hz */ {
226,270,312,352,386,414,435,448,452,448,435,414,386,352,312,270,226,182,140,100,66,38,17,4,0,4,17,38,66,100,140,182},
/* 77 Hz */ {
304,363,420,473,519,557,585,602,608,602,585,557,519,473,420,363,304,245,188,135,89,51,23,6,0,6,23,51,89,135,188,245},
/* 85.4 Hz */ {
274,327,379,426,468,502,527,543,548,543,527,502,468,426,379,327,274,221,169,122,80,46,21,5,0,5,21,46,80,122,169,221}
};
/* frequency factor */
const uint16_t FLUT[8] PROGMEM = { 289, 699, 529, 552, 468, 452, 608, 548 };
/* Zugriff auf PROGMEM: pgm_read_byte (&SLUT_32[]); */
/*PWM Ausgang: OC1A (PA6) */
/* global variables */
unsigned char F = 0;
ISR(TIM1_OVF_vect) /* timer 1 overflow */
{
static int i=0;
unsigned int w;
// update pwm register
w = pgm_read_word (&SLUT_32[F][i]);
OCR1AH = (unsigned char) (w>>8);
OCR1AL = (unsigned char) w;
i++;
if (i > 31)
i = 0;
PORTA |= (1<<PA7);
PORTA &= ~(1<<PA7);
}
int main(void){
unsigned char port,oldport=0;
// setup direction=OUT, OC1A PWM output
DDRA |= _BV(PA6);
DDRA |= _BV(PA7);
DDRB |= _BV(PB2);
// enable pullups
PORTA = ((1<<PA0) | (1<<PA1) | (1<<PA2) | (1<<PA3) | (1<<PA4) | (1<<PA5) | (1<<PA7));
PORTB = (1<<PB2); // unused pin
// initialization of timer/counter1
// mode = 14
TCCR1A = (1<<WGM11) | (1<<COM1A1) | (1<<COM1A0);
TCCR1B = (1<<CS11) | (1<<WGM12) | (1<<WGM13);
// set TOP value
F = (PINA & 0x07); // read switch, ctcss f-selection
ICR1H = (unsigned char) (pgm_read_word (&FLUT[F])>>8);
ICR1L = (unsigned char) pgm_read_word (&FLUT[F]);
// enable interrupt
TIMSK1 = (1<<TOIE1);
sei();
while(1){
port = PINA & (1<<PA3); // RX/TX input
if (oldport != port) {
oldport = port;
if (port == 0) {
PORTB |= (1<<PB2);
sei(); // enable CTCSS output on TX
}
else {
PORTB &= ~(1<<PB2);
cli(); // disable CTCSS output on RX
}
}
}
return 0;
}