'18F4520 XTL 20MHz AZEL LCD BUTT-LOCATION 120516 1300 'BUTTON PORTD.1 (Op in SIM) sets BASE as Input NMEA. 'Base to Remote: Range, Azimuth, elev2, Altitude 'NOTE: a label with a "1" suffix is the Local/Base station 'and "2" is the Remote location 'NOTE ONLY WORKS WEST OF MERIDIAN 'SIM-CIRCUIT CHANGE ALL LINES WITH >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 'Define SIMULATION_WAITMS_VALUE = 1 'Comment out for circuit in for SIM >>>>>>>>>>>>>>>>>> Define SINGLE_DECIMAL_PLACES = 6 Define CLOCK_FREQUENCY = 20 AllDigital Define CONFIG1L = 0x00 Define CONFIG1H = 0x02 Define CONFIG2L = 0x0c Define CONFIG2H = 0x00 Define CONFIG3L = 0x00 Define CONFIG3H = 0x81 Define CONFIG4L = 0x80 Define CONFIG4H = 0x00 Define CONFIG5L = 0x0f Define CONFIG5H = 0xc0 Define CONFIG6L = 0x0f Define CONFIG6H = 0xe0 Define CONFIG7L = 0x0f Define CONFIG7H = 0x40 TRISA = %00000001 TRISB = %00000000 TRISC = %10000000 '3-LCD RS, 4-LCD R/W 5-E TRISD = %00000010 'RD1 = ind 4-5-6-7-LCD DATA TRISE = %00000000 'PORTE.3=MCLR should this be input? 'setup temp variables Dim ascbfr(6) As Byte Dim binval As Long Dim bval2 As Long Dim lz1 As Byte Dim ind As Byte Dim str1(80) As Byte 'UART RXD buffer array Dim char As Byte Dim rxi As Byte Dim ix As Byte Dim ic As Byte Dim cp(16) As Byte Dim lenlat As Byte Dim lenlon As Byte Dim lenalt As Byte Dim quad As Byte Dim baselat As Single Dim baselon As Single Dim remlat As Single Dim remlon As Single Dim basecos As Single Dim londiff As Single Dim latdiff As Single Dim azimuth As Single 'Axxx Dim altmtr1 As Single Dim altmtr2 As Single Dim altval As Single Dim altsign As String Dim range12 As Single '12 = between 1 and 2 Dim elev2 As Single 'Remote Exxx Dim elesign As String '"-" or "+" Dim atn As Single Dim atn2 As Single Dim myarctan As Single Dim rad As Single '1 radian=180°/pi = 57.2958° (approx) rad = 57.295779 Symbol led = RB4 Symbol indbutt = PORTD.1 'SIM 0=AT START baselat = remlat baselon = remlon 'CMCON = 7????????????????????/ '# Define LCD_DREG = PORTD 'Port for LCD Data Define LCD_DBIT = 4 'Use upper 4 bits of Port Define LCD_RWREG = PORTC 'Port for E Define LCD_RWBIT = 5 'Pin for E (pin24) Define LCD_RSREG = PORTC 'Port for (R/W) Define LCD_RSBIT = 4 'Pin for RW bit (pin23) Define LCD_EREG = PORTD 'Port for Enable (RS) Define LCD_EBIT = 3 'Pin for RS bit (pin22) Define LCD_BITS = 4 'Using 4-bit bus Define LCD_LINES = 4 'Using 4 line Display Define LCD_CHARS = 20 Define LCD_COMMANDUS = 5000 'delay after LCDCMDOUT, default value is 5000 Define LCD_DATAUS = 100 'delay after LCDOUT, default value is 100 Define LCD_INITMS = 100 'delay used by LCDINIT, default value is 100 'Define LCD_READ_BUSY_FLAG = 1 Lcdinit '# 'USE INDX BUTTON TO LET baselat=remlat AT START 'NMEA uses Decimal Degrees, minutes. basecos = Cos(baselat / rad) Hseropen 9600 Hserout "Base:TEST.", #baselat, " ", #baselon, " ", #altmtr1, CrLf '############################################ 'Lcdcmdout LcdLine1Home Lcdout "LCD TEST " '############################################# WaitMs 100 Disable High 'HIGH priority interrupt (Time critical) Disable Low 'LOW priority interrupt (Time critical) get_neo: If RCSTA.OERR = 1 Then 'if over run error then flush RXD buffer RCSTA.CREN = 0 RCSTA.CREN = 1 char = RCREG char = RCREG PIR1.RCIF = 0 Endif sync1: 'wait for a $ start of string If PIR1.RCIF = 0 Then Goto sync1 char = RCREG If char <> 0x24 Then Goto sync1 '$' str1(1) = char rxi = 2 getmsg: 'read and save GPGGA msg If PIR1.RCIF = 0 Then Goto getmsg char = RCREG str1(rxi) = char rxi = rxi + 1 If rxi > 80 Then Goto get_neo 'msg bfr over run 'If char = 0x3f Then Goto eomsg '(0x3f = ?)SIM>>>>>>>>>>>>>>>>>>>>>>>>>>>. If char = 0x0a Then Goto eomsg '(0x0a = LF)CIRCUIT>>>>>>>>>>>>>>>>>>>>>>>> Goto getmsg eomsg: If rxi < 60 Then 'invalid msg Goto get_neo Endif If str1(5) = 0x47 Then 'G' ic = 1 For ix = 1 To 79 'find and save comma positions in msg If str1(ix) = 0x2c Then '0x2c = comma cp(ic) = ix 'adjust field start/stop, save comma positions Select Case ic Case 2 cp(2) = ix + 1 Case 3 cp(3) = ix - 1 Case 4 cp(4) = ix + 1 Case 5 cp(5) = ix - 1 Case 9 cp(9) = ix + 1 Case 10 cp(10) = ix - 1 EndSelect ic = ic + 1 Endif Hserout str1(ix) 'show msg 'If str1(ix) = 0x3f Then Goto cpos '0x3f (?)eomsg char'SIM>>>>>>>>>>>>>>. If str1(ix) = 0x0a Then Goto cpos '0x0a (LF) eomsg char'CIRCUIT>>>>>>>>>>>>>>. Next ix Else Goto nocoord Endif cpos: 'For ic = 1 To 16 'recall comma delimters 'ix = cp(ic) 'from comma position buffer 'Next ic getlatstr: lenlat = (cp(3) - cp(2)) + 1 For ix = cp(2) To cp(3) str1(ix) = str1(ix) And 0x0f Next ix getlonstr: lenlon = (cp(5) - cp(4)) + 1 For ix = cp(4) To cp(5) str1(ix) = str1(ix) And 0x0f Next ix getaltstr: altsign = "+" lenalt = (cp(10) - cp(9)) + 1 For ix = cp(9) To cp(10) If str1(ix) = "-" Then altsign = "-" lenalt = lenalt - 1 cp(9) = cp(9) + 1 Endif str1(ix) = str1(ix) And 0x0f Next ix 'make single number values 'lat ix = cp(2) 'DDMM.MMMMM remlat = str1(ix) * 10 'tens deg 10 to 90 ix = ix + 1 remlat = remlat + str1(ix) 'units 0 to 9 ix = ix + 1 remlat = remlat + str1(ix) / 6 'tens mins ix = ix + 1 remlat = remlat + str1(ix) / 60 'unit mins ix = ix + 2 'dp remlat = remlat + str1(ix) / 600 ix = ix + 1 remlat = remlat + str1(ix) / 6000 ix = ix + 1 remlat = remlat + str1(ix) / 60000 ix = ix + 1 remlat = remlat + str1(ix) / 600000 'lon ix = cp(4) 'DDDMM.MMMMM remlon = str1(ix) * 100 'hundreds ded ix = ix + 1 remlon = remlon + str1(ix) * 10 'tens ix = ix + 1 remlon = remlon + str1(ix) 'units ix = ix + 1 remlon = remlon + str1(ix) / 6 'tens mins ix = ix + 1 remlon = remlon + str1(ix) / 60 'unit mins ix = ix + 2 'dp remlon = remlon + str1(ix) / 600 ix = ix + 1 remlon = remlon + str1(ix) / 6000 ix = ix + 1 remlon = remlon + str1(ix) / 60000 ix = ix + 1 remlon = remlon + str1(ix) / 600000 'alt Select Case lenalt 'use alt data len to format Case 3 ix = cp(9) altmtr2 = str1(ix) ix = ix + 2 altmtr2 = altmtr2 + str1(ix) / 10 Case 4 ix = cp(9) altmtr2 = str1(ix) * 10 ix = ix + 1 altmtr2 = altmtr2 + str1(ix) ix = ix + 2 altmtr2 = altmtr2 + str1(ix) / 10 Case 5 ix = cp(9) altmtr2 = str1(ix) * 100 ix = ix + 1 altmtr2 = altmtr2 + str1(ix) * 10 ix = ix + 1 altmtr2 = altmtr2 + str1(ix) ix = ix + 2 altmtr2 = altmtr2 + str1(ix) / 10 Case 6 ix = cp(9) altmtr2 = str1(ix) * 1000 ix = ix + 1 altmtr2 = altmtr2 + str1(ix) * 100 ix = ix + 1 altmtr2 = altmtr2 + str1(ix) * 10 ix = ix + 1 altmtr2 = altmtr2 + str1(ix) ix = ix + 2 altmtr2 = altmtr2 + str1(ix) / 10 EndSelect If altsign = "-" Then altmtr2 = altmtr2 * -1 Endif '//////////////////////////////////////////////////////////////// If indbutt = 0 Then 'SIM 0=AT START baselat = remlat baselon = remlon REVERSE IN CIRCUIT led = 1 baselat = remlat baselon = remlon Else led = 0 Endif '############################################################# 'Lcdcmdout LcdLine1Home 'Lcdout "B ", #baselat, " ", #baselon, " ", CrLf '>>>>>>>>>>>>>>>>>> 'Lcdcmdout LcdLine2Home 'Lcdout "R ", #remlat, " ", #remlon, " ", CrLf '>>>>>>>>>>>>>>>>>> '############################################################## '///////////////////////////////////////////////////////////////// 'calc lat/lon differences latdiff = remlat - baselat londiff = baselon - remlon londiff = londiff * basecos 'londiff * base lat cosine latdiff = latdiff * 60 'degrees to mins londiff = londiff * 60 'test for quadrant set quadrant value to calc azimuth If latdiff > 0 And londiff > 0 Then quad = 0 Endif If latdiff < 0 And londiff > 0 Then latdiff = latdiff * -1 quad = 1 Endif If latdiff < 0 And londiff < 0 Then londiff = londiff * -1 latdiff = latdiff * -1 quad = 2 Endif If latdiff > 0 And londiff < 0 Then londiff = londiff * -1 quad = 3 Endif 'calc ratio of diffs atn = londiff / latdiff 'calc the angle in degrees using ratio atn2 = atn * atn If atn <= 1 Then myarctan = atn / (0.281125 * atn2 + 1) * 57.296 Else myarctan = (1.5708 - atn / (atn2 + 0.28125)) * 57.296 Endif 'convert angle to azimuth 0 thru 360 deg Select Case quad Case 0 myarctan = myarctan Case 1 myarctan = 180 - myarctan Case 2 myarctan = 180 + myarctan Case 3 myarctan = 360 - myarctan EndSelect azimuth = myarctan range12 = Sqrt(latdiff * latdiff + londiff * londiff) range12 = range12 * 1852 altval = altmtr2 'make alt an integer If altmtr1 <= altmtr2 Then 'set alt sign altmtr2 = altmtr2 - altmtr1 elesign = "+" Goto calcatn Endif If altmtr2 < altmtr1 Then altmtr2 = altmtr1 - altmtr2 elesign = "-" Endif calcatn: 'calc the angle in degrees using ratio atn = altmtr2 / range12 atn2 = atn * atn If atn <= 1 Then myarctan = atn / (0.281125 * atn2 + 1) * 57.296 Else myarctan = (1.5708 - atn / (atn2 + 0.28125)) * 57.296 Endif elev2 = myarctan 'ELEV2 = Exxx combined with ELESIGN "-" or "+" If elesign = "-" Then elev2 = 359 - elev2 Endif '##################################################################### 'Lcdcmdout LcdLine3Home 'Lcdout "A ", #azimuth, " ", CrLf '>>>>>>>>>>>>>>>>>> 'Lcdcmdout LcdLine4Home 'Lcdout "E ", #elev2, " ", CrLf '>>>>>>>>>>>>>>>>>> '##################################################################### 'change singles to integer for formatting binval = range12 * 10 Gosub bin2asc Hserout "Rng:", ascbfr(0), ascbfr(1), ascbfr(2), ascbfr(3), ascbfr(4), "m " binval = 10 * azimuth Gosub bin2asc Hserout "Azm:", ascbfr(2), ascbfr(3), ascbfr(4), ".", ascbfr(5), 0xba, " " binval = 10 * altval Gosub bin2asc Hserout "Alt:", altsign, ascbfr(1), ascbfr(2), ascbfr(3), ascbfr(4), ".", ascbfr(5), "m " binval = 10 * elev2 Gosub bin2asc Hserout "Elv:", elesign, ascbfr(2), ascbfr(3), ascbfr(4), ".", ascbfr(5), 0xba, CrLf nocoord: rxi = 1 binval = 10 * azimuth Gosub bin2asc Hserout "A", ascbfr(2), ascbfr(3), ascbfr(4) binval = 10 * elev2 Gosub bin2asc Hserout "E", ascbfr(2), ascbfr(3), ascbfr(4), CrLf, CrLf Goto get_neo End 'convert LONG < 1,000,000 to 6 ascii chars in ascbfr bin2asc: ascbfr(0) = binval / 100000 bval2 = ascbfr(0) * 100000 binval = binval - bval2 ascbfr(1) = binval / 10000 binval = binval Mod 10000 ascbfr(2) = binval / 1000 binval = binval Mod 1000 ascbfr(3) = binval / 100 binval = binval Mod 100 ascbfr(4) = binval / 10 ascbfr(5) = binval Mod 10 'results are BCD (Binary coded decimal)so 'convert to ASCII for LCD and set leading zero's to spaces lz1 = 0 For ind = 0 To 3 If ascbfr(ind) = 0 And lz1 = 0 Then 'LZL?????? ascbfr(ind) = ascbfr(ind) Or 0x30 '20. make this 0x30 to show LZ's???? Else ascbfr(ind) = ascbfr(ind) Or 0x30 lz1 = 1 Endif Next ind 'always show units and decimal For ind = 4 To 5 ascbfr(ind) = ascbfr(ind) Or 0x30 Next ind Return