Arduino CTCSS single frequency

filter

Some time ago I've published an article how to build a CTCSS encoder using an Arduino.

Now I've receive a question from Konstantinos, SV1ONW where the answer might interest other people too.

He wanted to use the CTCSS encoder in their local repeater, but for this only a single tone is required,
and to avoid the need to select the correct tone with the up/down push-buttons he asked me if it was
possible to have the encoder produce a single tone only.

A solution would be to simply take the same code and boot with the requested frequency,
however this still leaves the risk of the floating up/down inputs that could by accident alter the frequency.

So I've adapted the code here and removed the push-button code and added some comment how to setup the frequency.

Finally, in order to get a nice sine-wave one needs to add a low-pass filter on the output-pin "D9".
I've added a drawing here on top of the page of a filter that I've build that seems to be working fine :

/********************************************************************************
 *                                                                              *
 *                      ATMEGA328P HAM RADIO CTCSS ENCODER                      *
 *                                Version: V3.1                                 *
 *                                                                              *
 *                Created by Geert Vanhulle - ON7GF - June 2019                 *
 *                                                                              *
 * Released under GPL3 - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007   *    
 *                                                                              *
 *    Derivative work can only be distributed under these same license terms    *
 *    For the full license text goto: fsf.org - The Free Software Foundation    *
 *                                                                              *
 ********************************************************************************/


/* ----------------------------------------------------------------------------
 *  
 *  this is a single frequency version of the original CTCSS project
 *  on an othere article here on my website. It's a reduced code version
 *  
 *  a lowpass filter needs to be added to get a nice sinewave
 *   
   ---------------------------------------------------------------------------- */

// tabel gegevens
byte ocrL[50]; byte ocrH[50];

// ctcss tonen
float ctcssFreq[] =   {  67.0,    69.3,    71.9,    74.4,    77.0,   79.7,    82.5,    85.4,    88.5,    91.5,
                         94.8,    97.4,   100.0,   103.5,   107.2,  110.9,   114.8,   118.8,   123.0,   127.3, 
                        131.8,   136.5,   141.3,   146.2,   151.4,  156.7,   159.8,   162.2,   165.5,   167.9,  
                        171.3,   173.8,   177.3,   179.9,   183.5,  186.2,   189.9,   192.8,   196.6,   199.5,
                        203.5,   206.5,   210.7,   218.1,   225.7,  229.1,   233.6,   241.8,   250.3,    254.1      
};

// Change this variable to get the correct tone from the list above
// To do so you need to count the position in the list starting from zero 
// For example: 67Hz = 0  ---  69.3Hz = 1 --- 71.9Hz = 2 --- and so on... 
// Here the variable is set for 88Hz = 8 

int ctcsstone=8;



void setup() {

 ctcsscalc();

 /* frequentie-deler */ 
 // configuratie Timer1
 TCCR1A = 0x50;
 TCCR1B = 0x0A;
 TCCR1C = 0x00;

 // zet pin PB1 = OCR1A = "D9" als output
 DDRB |= 1 << PB1; 

 // zet het deeltal in het output compare register
 OCR1AH = ocrH[ctcsstone];
 OCR1AL = ocrL[ctcsstone];

}

void loop() { }




// bereken deeltal ocrnx voor elke frequentie
void ctcsscalc() {

  int N = 8;
  int clk = 16; // 16 MHz clock

  for (int n=0; n<50; n++) {
  
    int ocrLH = ( clk * 1000000 ) / (( 2 * N * ctcssFreq[n] ) - 1 );
       
    ocrH[n] = ocrLH >> 8;
    ocrL[n] = ocrLH & 0x00FF;

  }
}