/********************************************************************
* *
* Project: CTCSS 12F683 *
* Source: CTCSS_12F683.c *
* Author: Mike McLaren, K8LH *
* Date: 26-Nov-10 *
* Revised: 26-Nov-10 *
* *
* High Performance 12F683 DDS(PWM) CTCSS Tone Generator Demo *
* with 24-bit Phase Accumulator (8.388608-MHz crystal) *
* *
* IDE: MPLAB 8.56 (tabs = 4) *
* Lang: SourceBoost BoostC v7.01, Lite/Free version *
* *
********************************************************************/
#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 = 0; // phase accumulator
u32 phase = 0; // 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
*
*/
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 with
* 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 = 1<<TMR2IE; // 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
}