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;
}
}