Several years ago I've owned a Kenwood TR751E and I've always regretted that I've sold this rig as looking back it was the best 2m multimode transceiver I've ever owned. So when I suddenly got the chance to buy, in very good condition, not only the TR751E but also the TR851E as a pair of transceivers I didn't think twice !
However one disadvantage of older generation transceivers is that they don't have any CTCSS system. Especially the encoder part is a lack as most repeaters use these tones nowadays.
So I've decided to 'quickly' put some lines of code in an Arduino and make myself a CTCSS encoder. The handy and easy Arduino C-library however isn't particularly optimized when it comes to the utilization of the timer/counters of the ATMega328p that runs the Arduino. And to be honest not for a lot of other parts of the chip as well. But that's the trade-of: easy code for less features. So after a handful of lines of Arduino code I've realized that it would be way more efficient to do this the bits and bytes way and use the MCU registers.
The result is the code you can find here that produces a square wave on pin D9 with the CTCSS frequency selected with an "up" and "down" switch on pin's D2 and D3.
You can use, copy and extend this code freely as long as you include the license that gives these equal right to use, copy and extent it freely again to others !
/******************************************************************************** * * * ATMEGA328P HAM RADIO CTCSS ENCODER * * Version: V2.0 * * * * Created by Geert Vanhulle - ON7GF - November 2018 * * * * 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 * * * ********************************************************************************/ /* ---------------------------------------------------------------------------- * * dit is nog niet de uiteindelijke versie. De output van deze versie is een * blokgolf signaal op pin D9 met de juiste frequentie, doch een blokgolf is * niet 100% bruikbaar als ctcss omdat de harmonischen in het signaal * een ctcss-decoder in de war kunnen brengen. * * De finale versie moet dus direct een sinus kunnen produceren. * ---------------------------------------------------------------------------- */ // 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 }; // isr vlaggen bool up = false; bool dn = false; // actieve toon uit de lijst int toon=0; // interrupt vector up ISR(INT0_vect){ up=true; } // interrupt vector dn ISR(INT1_vect){ dn=true; } 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[0]; OCR1AL = ocrL[0]; /* interrupts */ // pin 2 & 3 als input DDRD &= ~(1 << DDD2); DDRD &= ~(1 << DDD3); // falling edge EICRA |= (1 << ISC11); EICRA &= ~(1 << ISC10); // falling edge EICRA |= (1 << ISC01); EICRA &= ~(1 << ISC00); // enable interrupt EIMSK |= (1 << INT0); EIMSK |= (1 << INT1); /* led's als display welke toon */ // PC0 (A4) ... PC5 (A0) = uitgang DDRC = B00111111; PORTC = B00000000; Serial.begin(9600); displayToon(); } void loop() { if (up) { for (double wait=0; wait<25000; wait++) { int a=0; } // debounce toon++; if (toon>49) {toon=0;} OCR1AH = ocrH[toon]; OCR1AL = ocrL[toon]; displayToon(); up=false; } if (dn) { for (double wait=0; wait<25000; wait++) { int a=0; } // debounce toon--; if (toon<0) {toon=49;} OCR1AH = ocrH[toon]; OCR1AL = ocrL[toon]; displayToon(); dn=false; } } // 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; } } // display welke toon er actief is void displayToon() { //LED's PORTC = toon; // serial monitor Serial.print(toon); Serial.print(" -- "); Serial.print(ctcssFreq[toon]); Serial.print(" -- "); Serial.print(ocrH[toon], HEX); Serial.print(" -- "); Serial.println(ocrL[toon], HEX); }