While APRS and AX.25 provide data integrity, my programming skills lacked the expertise to implement this method. So I started thinking about using the amateur radio standard AFSK RTTY at 170Hz shift. Data integrity should be maintained fairly accurate because the receiving station and payload will be in Line of Site with each other. The payload TM signal should be very strong at the receiving station(s).
Searching this site and using Google, I could only find a couple of articles in the PICAXE forum and none on this forum.
Reading the GPS NEMA 0183 data was simple, converting the $GPGGA NEMA string ASCII data into Baudot and readying it for transmit it was a bit trickier
Here is my prototype PIC RTTY Telemetry project:
http://www.n6vmo.com/PIC/SARCHAB7.zip
'************************************************* *************** '* Name : SARCHAB7.BAS * '* Author : [select VIEW...EDITOR OPTIONS] * '* Notice : Copyright (c) 2011 [select VIEW...EDITOR OPTIONS] * '* : All Rights Reserved * '* Date : 6/17/2011 * '* Version : 1.0 * '* Notes : * '* : * '************************************************* *************** 'PICBASIC PRO program to read a 4800 BAUD GPS GPGGA/RMC NEMA ' 0183 string and transmit it using BAUDOT (RTTY) with standard amateur ' radio AFSK 170Hz shift, using the XR2206 modem and the PIC16F627. ' ' INCLUDE "BS2DEFS.BAS" DEFINE HSER_CLROERR 1 'USART CLEAR OVERFLOW ERROR DEFINE HSER_TXSTA 24H 'SET USART TX STAUS REG DEFINE HSER_RCSTA 90H 'SET USART RC STAUS REG DEFINE HSER_BAUD 4800 'SET USART BAUD RATE define HSER_SPBRG 50 'SET PIC OSC FOR 4800 BAUD RXDATA VAR BYTE (50) UTC VAR BYTE (10) RMCUTC VAR BYTE (10) LAT VAR BYTE (9) RMCLAT VAR BYTE (9) NS VAR BYTE (2) RMCNS VAR BYTE (2) EW VAR BYTE (2) RMCEW VAR BYTE (2) LNG VAR BYTE (10) RMCLNG VAR BYTE (10) ALT VAR BYTE (7) FQ VAR BYTE (1) SATS VAR BYTE (2) HDP VAR BYTE (3) SPD VAR BYTE (5) TRK VAR BYTE (5) PIR1 = $0C 'ASSIGN USART RX INTERUPT REG PTT VAR PORTB.4 'ASSIGN PTT PIN O Var PORTB.5 'ASSIGN BAUDOT OUTPUT PIN CUT VAR PORTB.6 'ASSIGN CUTDOWN OUTPUT PIN I VAR BYTE L VAR BYTE BAUDOTDATA VAR BYTE BAUDOTBIT VAR BIT BEACONCOUNT VAR BYTE ADDRESS vAR WORD ALTFT VAR WORD FEET VAR WORD SPDMPH VAR BYTE MPH VAR BYTE BEACONCOUNT = 1 '---------------------------------------------------------------- MAIN: IF BEACONCOUNT = 5 THEN BEACONCOUNT = 1 GOSUB READGPS GOSUB PUSHTOTALKON GOSUB DISPLAYFORMAT GOSUB METRICSAE GOSUB TXGGARMCDATA BEACONCOUNT = BEACONCOUNT + 1 IF BEACONCOUNT = 5 THEN GOSUB BEACON IF BEACONCOUNT = 5 THEN GOSUB WEB GOSUB PUSHTOTALKOFF GOSUB CUTDWN 'PAUSE 60000 'PAUSE FOR 60 SECONDS BETWEEN TRANSMISSIONS GOTO MAIN '-----------------------Read GPGAA NEMA 0183 Data READGPS: 'G G A , HSERIN [WAIT (71,71,65,44), STR UTC \6] HSERIN [WAIT (44), STR LAT \9] HSERIN [WAIT (44), STR NS \1] HSERIN [WAIT (44), STR LNG \10] HSERIN [WAIT (44), STR EW \1] HSERIN [WAIT (44), STR FQ \1] HSERIN [WAIT (44), STR SATS \2] HSERIN [WAIT (44), STR HDP \3] HSERIN [WAIT (44), STR ALT \6\44] '------------------------Read GPRMC NEMA 0183 Data 'R M C , HSERIN [WAIT (82,77,67,44), STR RMCUTC \6] HSERIN [WAIT (44), STR RMCLAT \9] HSERIN [WAIT (44), STR RMCNS \1] HSERIN [WAIT (44), STR RMCLNG \10] HSERIN [WAIT (44), STR RMCEW \1] HSERIN [WAIT (44), STR SPD \4] HSERIN [WAIT (44), STR TRK \5] RETURN '--------------------------PTT OUTPUT----------------------------- PUSHTOTALKON: HIGH PTT PAUSE 500 RETURN '--------------------------PTT OUTPUT----------------------------- PUSHTOTALKOFF: LOW PTT PAUSE 500 RETURN '-------------------------FORMAT RX STATION----------------------- DISPLAYFORMAT: GOSUB LTR 'SEND LTR FOR I = 0 TO 4 GOSUB TX NEXT I GOSUB FIG 'SEND FIGS FOR I = 0 TO 4 GOSUB TX NEXT I GOSUB CRTN 'SEND CR FOR I = 0 TO 1 GOSUB TX NEXT I GOSUB LF 'SEND LF FOR I = 0 TO 1 GOSUB TX NEXT I RETURN '------------------------------------------------------------- TXGGARMCDATA: '------------------UTC--------------------------- ADDRESS = $FB0 'UTC ADDRESS FOR L = 0 TO 5 PEEKCODE ADDRESS, BAUDOTDATA GOSUB TX ADDRESS = ADDRESS + 1 NEXT L FOR L = 0 TO 5 'MOVE UTC INTO RXDATA RXDATA (L) = UTC (L) GOSUB TRANSLATE 'TRANSLATE ASCII TO BAUDOT GOSUB TX 'TRANSMIT BYTE NEXT L GOSUB CRTN GOSUB TX GOSUB LF GOSUB TX '------------------LAT------------------------------------------ ADDRESS = $F60 'LAT ADDRESS FOR L = 0 TO 5 PEEKCODE ADDRESS, BAUDOTDATA GOSUB TX ADDRESS = ADDRESS + 1 NEXT L FOR L = 0 TO 8 'MOVE LAT INTO RXDATA RXDATA (L) = LAT (L) GOSUB TRANSLATE 'TRANSLATE ASCII TO BAUDOT GOSUB TX 'TRANSMIT BYTE NEXT L GOSUB CRTN GOSUB TX GOSUB LF GOSUB TX '-------------------LNG-------------------------------------------- ADDRESS = $F70 'LNG ADDRESS FOR L = 0 TO 5 PEEKCODE ADDRESS, BAUDOTDATA GOSUB TX ADDRESS = ADDRESS + 1 NEXT L FOR L = 0 TO 9 'MOVE LNG INTO RXDATA RXDATA (L) = LNG (L) GOSUB TRANSLATE 'TRANSLATE ASCII TO BAUDOT GOSUB TX 'TRANSMIT BYTE NEXT L GOSUB CRTN GOSUB TX GOSUB LF GOSUB TX '---------------------------------------------------------------- ADDRESS = $F80 'ALT ADDRESS FOR L = 0 TO 5 PEEKCODE ADDRESS, BAUDOTDATA GOSUB TX ADDRESS = ADDRESS + 1 NEXT L FOR L = 0 TO 5 'MOVE ALT INTO RXDATA RXDATA (L) = ALT (L) GOSUB TRANSLATE 'TRANSLATE ASCII TO BAUDOT GOSUB TX 'TRANSMIT BYTE NEXT L GOSUB CRTN GOSUB TX GOSUB LF GOSUB TX '-----------------------SPEED-------------------------- ADDRESS = $F90 'SPD ADDRESS FOR L = 0 TO 5 PEEKCODE ADDRESS, BAUDOTDATA GOSUB TX ADDRESS = ADDRESS + 1 NEXT L FOR L = 0 TO 3 'MOVE SPD INTO RXDATA RXDATA (L) = SPD (L) GOSUB TRANSLATE 'TRANSLATE ASCII TO BAUDOT GOSUB TX 'TRANSMIT BYTE NEXT L GOSUB CRTN GOSUB TX GOSUB LF GOSUB TX '-----------------------TRACK--------------------------- ADDRESS = $FA0 'TRK ADDRESS FOR L = 0 TO 5 PEEKCODE ADDRESS, BAUDOTDATA GOSUB TX ADDRESS = ADDRESS + 1 NEXT L FOR L = 0 TO 4 'MOVE TRK INTO RXDATA RXDATA (L) = TRK (L) GOSUB TRANSLATE 'TRANSLATE ASCII TO BAUDOT GOSUB TX 'TRANSMIT BYTE NEXT L GOSUB CRTN GOSUB TX GOSUB LF GOSUB TX RETURN END '---------------------TRANSLATE ACSII TO BAUDOT------------------ TRANSLATE: IF RXDATA (L) = "0" THEN BAUDOTDATA = 13 IF RXDATA (L) = "1" THEN BAUDOTDATA = 29 IF RXDATA (L) = "2" THEN BAUDOTDATA = 25 IF RXDATA (L) = "3" THEN BAUDOTDATA = 16 IF RXDATA (L) = "4" THEN BAUDOTDATA = 10 IF RXDATA (L) = "5" THEN BAUDOTDATA = 1 IF RXDATA (L) = "6" THEN BAUDOTDATA = 21 IF RXDATA (L) = "7" THEN BAUDOTDATA = 28 IF RXDATA (L) = "8" THEN BAUDOTDATA = 12 IF RXDATA (L) = "9" THEN BAUDOTDATA = 3 IF RXDATA (L) = "," THEN BAUDOTDATA = 6 'Convert "," to SPACE IF RXDATA (L) = "." THEN BAUDOTDATA = 7 RETURN '------------------------------------------------------------------ TX: GOSUB SPACE 'SEND START BIT LOW 22mS BAUDOTBIT = BAUDOTDATA.BIT4 IF BAUDOTBIT = 0 THEN GOSUB SPACE IF BAUDOTBIT = 1 THEN GOSUB MARK BAUDOTBIT = BAUDOTDATA.BIT3 IF BAUDOTBIT = 0 THEN GOSUB SPACE IF BAUDOTBIT = 1 THEN GOSUB MARK BAUDOTBIT = BAUDOTDATA.BIT2 IF BAUDOTBIT = 0 THEN GOSUB SPACE IF BAUDOTBIT = 1 THEN GOSUB MARK BAUDOTBIT = BAUDOTDATA.BIT1 IF BAUDOTBIT = 0 THEN GOSUB SPACE IF BAUDOTBIT = 1 THEN GOSUB MARK BAUDOTBIT = BAUDOTDATA.BIT0 IF BAUDOTBIT = 0 THEN GOSUB SPACE IF BAUDOTBIT = 1 THEN GOSUB MARK GOSUB STOPBIT 'SEND STOP BIT HIGH 44mS RETURN '-----------------------METRIC TO SAE CONVERTION METRICSAE: IF ALT(4)=46 THEN GOSUB LOWER 'CHECK FOR "." ALTFT = ((ALT(0)-48)*10000)+ ((ALT(1)-48)*1000)+ ((ALT(2)-48)*100)+ ((ALT(3)-48)*10)+(ALT(4)-48) FEET = (ALTFT */ 845) 'CONVERT METERS TO FEET GOSUB KNOTS RETURN LOWER: ALTFT = ((ALT(0)-48)*1000)+ ((ALT(1)-48)*100)+ ((ALT(2)-48)*10)+ (ALT(3)-48) FEET = (ALTFT */ 845)'CONVERT METERS TO FEET KNOTS: SPDMPH = ((SPD(0)-48)*10)+ (SPD(1)-48) MPH = (SPDMPH */ 295) 'CONVERT KNOTS TO MPH RETURN '-----------------------CUTDOWN-------------------------- CUTDWN: IF FEET > 61000 THEN HIGH PTT 'COUTDOWWN COMMAND SET FOR 61000' PAUSE 5000 'SUPPLY CD CURRENT FOR 5 SECONDS LOW CUT RETURN '-----------------------MARK AND SPACE------------------- MARK: low O PAUSE 22 RETURN SPACE: high O PAUSE 22 RETURN STOPBIT: low O PAUSE 44 RETURN '---------------------------------------------------------- LTR: BAUDOTDATA = 31 RETURN FIG: BAUDOTDATA = 27 RETURN CRTN: BAUDOTDATA = 8 RETURN LF: BAUDOTDATA = 2 RETURN '------------------------------------------------------------ BEACON: ADDRESS = $F00 'BEACON TEXT STORAGE LOCATION FOR L = 0 TO 51 PEEKCODE ADDRESS, BAUDOTDATA GOSUB TX ADDRESS = ADDRESS + 1 NEXT L RETURN '------------------------------------------------------ WEB: ADDRESS = $F40 'BEACON TEXT STORAGE LOCATION FOR L = 0 TO 28 PEEKCODE ADDRESS, BAUDOTDATA GOSUB TX ADDRESS = ADDRESS + 1 NEXT L RETURN END 'BEACONTEXT W6AB SARCHAB X1/HF TRACKING NET ON 7.180 POKECODE @$F00, 2,8,31,25,27,21,31,24,19,4,20,24,10,14,5,24 POKECODE @$F10, 19,4,23,27,29,27,2,8,31,5,22,4,1,10,24,14 POKECODE @$F20, 30,12,6,11,4,6,16,1,4,3,6,4,27,28,7,29 POKECODE @$F30, 12,13,2,8 'WEB ADDRESS F40 - F5C (29) POKECODE @$F40, 31,25,25,25,27,7,31,20,24,1,16,9,9,12,1,16 POKECODE @$F50, 24,10,14,27,7,31,14,3,7,4,27,2,8 'LATITUDE: F60 - F6B (6) POKECODE @$F60, 31,9,24,1,27,14 'LONGITUDE: F70 - F7C (6) POKECODE @$F70, 31,9,3,6,27,14 'ALTITUDE: F80 - F8B (6) POKECODE @$F80, 31,24,9,1,27,14 'SPEED: POKECODE @$F90, 31,20,13,18,27,14 'TRACK: POKECODE @$FA0, 31,1,10,30,27,14 'UTC: POKECODE @$FB0, 31,28,1,14,27,14
Re: K42 and Timer Interrupts
Thanks for the explanation.
Ioannis - 28th April 2025, 19:28I misinterpreted these paragraphs. My understanding was to have ASYNC cleared and use Fosc/4.
Ioannis