One of the things on my to-do list has been convert the transmission of the RTTY into the background as an interrupt. When the payload is transmitting at 50 baud it effectively sits around doing nothing for 15 seconds whilst it transmits.
By moving this to an interrupt based routine it can transmit in the background whilst allowing the foreground tasks to run. This means more data being logged, more accurate altitude measurements, faster response to a burst if needed etc.
Having had a good read of http://www.engblaze.com/microcontroller-tutorial-avr-and-arduino-timer-interrupts/ I set about coding up the code to do this one step at a time. Firstly I replicated the high/low code from http://ukhas.org.uk/guides:linkingarduinotontx2#part_1_-_test_circuit_and_test_code
After finding a few code timing errors I think I’ve sorted it out so it runs as a stand alone procedure which TX’s in the back ground. The RFM22B seemed to struggle to switch frequencies fast enough above 300 baud using radio1.setFrequency(RADIO_FREQUENCY_LOW)/radio1.setFrequency(RADIO_FREQUENCY_HIGH). Dave Akerman suggested (as recommended by Navrac) that using the shift frequency register is better way. Indeed it is much faster, results in a much cleaner signal and allowed the baud rate to decode fine up to 600.
So here is what I’ve come up with, it will need further testing and integration into my existing flight code.
/* Interrupt Driven RTTY TX Demo Transmits data via RTTY with an interupt driven subroutine. By Anthony Stirk M0UPU October 2012 Version 5 Thanks and credits : Evolved from Rob Harrison's RTTY Code. Compare match register calculation by Phil Heron. Thanks to : http://www.engblaze.com/microcontroller-tutorial-avr-and-arduino-timer-interrupts/ RFM22B Code from James Coxon http://ukhas.org.uk/guides:rfm22b Suggestion to use Frequency Shift Registers by Dave Akerman (Daveake)/Richard Cresswell (Navrac) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. See <http://www.gnu.org/licenses/>. */ #include <avr/io.h> #include <avr/interrupt.h> #include <util/crc16.h> #include <SPI.h> #include <RFM22.h> #define ASCII 7 // ASCII 7 or 8 #define STOPBITS 2 // Either 1 or 2 #define TXDELAY 0 // Delay between sentence TX's #define RTTY_BAUD 100 // Baud rate for use with RFM22B Max = 600 #define RADIO_FREQUENCY 434.198 #define RFM22B_SDN 3 #define RFM22B_PIN 10 char datastring[80]; char txstring[80]; volatile int txstatus=1; volatile int txstringlength=0; volatile char txc; volatile int txi; volatile int txj; unsigned int count=0; rfm22 radio1(RFM22B_PIN); void setup() { initialise_interrupt(); setupRadio(); } void loop() { sprintf(datastring,"$$$$$M0UPU,%04u,RTTY TEST BEACON RTTY TEST BEACON",count); // Puts the text in the datastring unsigned int CHECKSUM = gps_CRC16_checksum(datastring); // Calculates the checksum for this datastring char checksum_str[6]; sprintf(checksum_str, "*%04X\n", CHECKSUM); strcat(datastring,checksum_str); delay(1000); count++; } ISR(TIMER1_COMPA_vect) { switch(txstatus) { case 0: // This is the optional delay between transmissions. txj++; if(txj>(TXDELAY*RTTY_BAUD)) { txj=0; txstatus=1; } break; case 1: // Initialise transmission, take a copy of the string so it doesn't change mid transmission. strcpy(txstring,datastring); txstringlength=strlen(txstring); txstatus=2; txj=0; break; case 2: // Grab a char and lets go transmit it. if ( txj < txstringlength) { txc = txstring[txj]; txj++; txstatus=3; rtty_txbit (0); // Start Bit; txi=0; } else { txstatus=0; // Should be finished txj=0; } break; case 3: if(txi<ASCII) { txi++; if (txc & 1) rtty_txbit(1); else rtty_txbit(0); txc = txc >> 1; break; } else { rtty_txbit (1); // Stop Bit txstatus=4; txi=0; break; } case 4: if(STOPBITS==2) { rtty_txbit (1); // Stop Bit txstatus=2; break; } else { txstatus=2; break; } } } void rtty_txbit (int bit) { if (bit) { radio1.write(0x73,0x03); // High } else { radio1.write(0x73,0x00); // Low } } void setupRadio(){ pinMode(RFM22B_SDN, OUTPUT); // RFM22B SDN is on ARDUINO A3 digitalWrite(RFM22B_SDN, LOW); delay(1000); rfm22::initSPI(); radio1.init(); radio1.write(0x71, 0x00); // unmodulated carrier //This sets up the GPIOs to automatically switch the antenna depending on Tx or Rx state, only needs to be done at start up radio1.write(0x0b,0x12); radio1.write(0x0c,0x15); radio1.setFrequency(RADIO_FREQUENCY); radio1.write(0x6D, 0x04);// turn tx low power 11db radio1.write(0x07, 0x08); delay(500); } uint16_t gps_CRC16_checksum (char *string) { size_t i; uint16_t crc; uint8_t c; crc = 0xFFFF; // Calculate checksum ignoring the first two $s for (i = 5; i < strlen(string); i++) { c = string[i]; crc = _crc_xmodem_update (crc, c); } return crc; } void initialise_interrupt() { // initialize Timer1 cli(); // disable global interrupts TCCR1A = 0; // set entire TCCR1A register to 0 TCCR1B = 0; // same for TCCR1B OCR1A = F_CPU / 1024 / RTTY_BAUD - 1; // set compare match register to desired timer count: TCCR1B |= (1 << WGM12); // turn on CTC mode: // Set CS10 and CS12 bits for: TCCR1B |= (1 << CS10); TCCR1B |= (1 << CS12); // enable timer compare interrupt: TIMSK1 |= (1 << OCIE1A); sei(); // enable global interrupts }
Hi,
I have found a GPS/Radiometrix interrupt programme that transmits RTTY. The string prints to Serial successfully and shows up on SDR with the typical signal, but it doesn’t yield an intelligible readout on dl-FLDigi. I am using a frequency agile NTX2B together with 4k7 + 4k7 + 32k resistors and am wondering whether I should obtain a straight forward NTX2B.
My NTX2B FA does print and transmit RTTY signals from the two example NTX2B programmes without using resistors but doesn’t do this with the GPS/Radiometrix programme that I am using (basically, Stratodene 3 with a serial link).
I am trying to access the irc resource, but I think I will need to get myself a web site to do this.
Basically, I think I am struggling to ask:
1. does the NTX2B FA do away with the need for resistors (it seems to with your example programmes).
2. does a programme that requires an ordinary NTX2B (ie, needing a resistor driven shift) need tweaking when using the frequency agile version?
Many thanks,
Colin.
Hi Colin,
There is no difference between the stock NTX2B and the HAB Supplies NTX2B-FA other than the frequency agility. Both need the resistor network to generate the tones. Alternatively you can generate tone using PWM (Which may or may not need a resistor). The resistor network is generally simpler.
NTX2B-FA are drop in replacements for the stock Radiometrix NTX2B so nothing will need changing.
Regards