Code:
/********************************************************************
* *
* Project: CTCSS 12F683 *
* Source: CTCSS_12F683.c *
* Author: Mike McLaren, K8LH *
* Date: 26-Nov-10 *
* Revised: 26-Nov-10 *
* *
* untested 12F683 DDS(PWM) CTCSS Tone Generator with 24-bit *
* Phase Accumulator (Fosc = 8.388608-MHz) *
* *
* IDE: MPLAB 8.56 (tabs = 4) *
* Lang: SourceBoost BoostC v7.01, Lite/Free version *
* *
********************************************************************
*
* CTCSS tone frequencies
*
* 67.0 Hz 69.3 Hz 71.9 Hz 74.4 Hz 77.0 Hz
* 79.7 Hz 82.5 Hz 85.4 Hz 88.5 Hz 91.5 Hz
* 94.8 Hz 97.4 Hz 100.0 Hz 103.5 Hz 107.2 Hz
* 110.9 Hz 114.8 Hz 118.8 Hz 123.0 Hz 127.3 Hz
* 131.8 Hz 136.5 Hz 141.3 Hz 146.2 Hz 151.4 Hz
* 156.7 Hz 159.8 Hz 162.2 Hz 165.5 Hz 167.9 Hz
* 171.3 Hz 173.8 Hz 177.3 Hz 179.9 Hz 183.5 Hz
* 186.2 Hz 189.9 Hz 192.8 Hz 196.6 Hz 199.5 Hz
* 203.5 Hz 206.5 Hz 210.7 Hz 218.1 Hz 225.7 Hz
* 229.1 Hz 233.6 Hz 241.8 Hz 250.3 Hz 254.1 Hz
*
*/
#include system.h
#pragma DATA _CONFIG, _MCLRE_OFF, _WDT_OFF, _HS_OSC
#pragma CLOCK_FREQ 8388608 // using an 8.388608-MHz crystal
//--< function prototypes >------------------------------------------
//--< type definitions >---------------------------------------------
typedef unsigned char u08;
typedef unsigned int u16;
typedef unsigned long u32;
#define r08 rom char*
//--< variables >----------------------------------------------------
u32 accum; // phase accumulator
u32 phase; // phase offset (DDS tuning word)
r08 sinetbl = { 100,102,104,107,109,112,114,117,119,121,
124,126,129,131,133,135,138,140,142,144,
147,149,151,153,155,157,159,161,163,165,
167,168,170,172,174,175,177,178,180,181,
183,184,185,187,188,189,190,191,192,193,
194,194,195,196,197,197,198,198,198,199,
199,199,199,199,200,199,199,199,199,199,
198,198,198,197,197,196,195,194,194,193,
192,191,190,189,188,187,185,184,183,181,
180,178,177,175,174,172,170,168,167,165,
163,161,159,157,155,153,151,149,147,144,
142,140,138,135,133,131,129,126,124,121,
119,117,114,112,109,107,104,102, 99, 97,
95, 92, 90, 87, 85, 82, 80, 78, 75, 73,
70, 68, 66, 64, 61, 59, 57, 55, 52, 50,
48, 46, 44, 42, 40, 38, 36, 34, 32, 31,
29, 27, 25, 24, 22, 21, 19, 18, 16, 15,
14, 12, 11, 10, 9, 8, 7, 6, 5, 5,
4, 3, 2, 2, 1, 1, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
1, 2, 2, 3, 4, 5, 5, 6, 7, 8,
9, 10, 11, 12, 14, 15, 16, 18, 19, 21,
22, 24, 25, 27, 29, 31, 32, 34, 36, 38,
40, 42, 44, 46, 48, 50, 52, 55, 57, 59,
61, 64, 66, 68, 70, 73, 75, 78, 80, 82,
85, 87, 90, 92, 95, 97 };
//--< defines >------------------------------------------------------
//--< isr >----------------------------------------------------------
/*
* 12F/16F1xxx DDS-PWM CTCSS "Access Tone Generator" Notes
* =======================================================
*
* using an 8.388608 MHz crystal
*
* Tcy = 1 / 8388608 * 4 = 476.837158203125 nsecs
*
* using a 200 cycle PWM period provides a DDS frequency of
*
* Fdds = 1 / (200 Tcy) = 10,485.76 Hz
*
* frequency resolution using a 24 bit phase accumulator is
*
* Fres = Fdds / 2^24
* Fres = 10485.76 / 16777216 = 0.000625 Hz
*
* dds tuning word (phase offset) can be calculated a couple
* different ways. since the dds frequency resolution (Fres)
* is basically 0.01-Hz divided by 16, you can calculate the
* phase offset by mulitplying desired Fout output frequency
* by 1600. the phase offset for an Fout of 254.1-Hz is;
*
* phase = (Fout * 100) * 16
* = (254.1 * 100) * 16 = 406560
*
* phase = 25410 << 4 = 406560
*
* or you can also calculate phase offset like this (yuch!);
*
* phase = Fout / Fres
* = 254.1 / 0.000625 = 406560
*
* phase = Fout * 2^24 / Fdds
* = 254.1 * 16777216 / 10485.76 = 406560
*
* the highest CTCSS frequency (254.1 Hz) will produce the
* smallest number of sine wave D/A output points per cycle;
*
* INT(10485.76 / 254.1) = 41 output points per cycle
*
* use the most significant 8 bits of the 24-bit phase
* accumulator as the sine table index.
*
*/
void interrupt() // 200-cycles (10485.76-Hz)
{ pir1.TMR2IF = 0; // clear TMR2 interrupt flag
accum += phase; // add phase offset to accum
ccpr1l = sinetbl[accum>>16]; // sine duty cycle value for
} // next PWM period
//--< main >---------------------------------------------------------
void main()
{
cmcon0 = 7; // comparator off, digital I/O
ansel = 0; // a2d module off, digital I/O
trisio = 0b00111011; // GP2 output, all others input
/*
* setup PWM module for 200 cycle interrupts (10485.76-Hz using
* an 8.388608-MHz clock)
*
*/
ccp1con = 0b00001100; // 00001100
// --00---- DC1B<1:0>, duty cycle b1:b0
// ----1100 CCP1M<3:0>, pwm mode
t2con = 0b00000000; // 00000000
// -0000--- TOUTPS<3:0>, postscale 1
// -----0-- TMR2ON, timer off
// ------00 T2CKPS<1:0>, prescale 1
// for 476.837158203125 nsec 'ticks'
pr2 = 200-1; // for 95.367431640625 usec interrupts
ccpr1l = 0; // 0% duty cycle
pie1.TMR2IE = 1; // enable Timer 2 interrupts
pir1 = 0; // clear all peripheral interrupt flags
intcon.PEIE = 1; // enable peripheral interrupts
intcon.GIE = 1; // enable global interrupts
t2con.TMR2ON = 1; // turn TMR2 on
phase = 25410 << 4; // phase offset for 254.1-Hz tone
while(1); // loop forever
}
Bookmarks