How do I discern Maidenhead Locator from GPS lat long info.

# Thread: How do I discern Maidenhead Locator from GPS lat long info.

1. ## How do I discern Maidenhead Locator from GPS lat long info.

Hi all,

I have some idea but maths is not my strong point. I have written what I considered to be the process but not a working code. Am I on the right lines ?(See end)

This is the relevant information to achieve the locator.

.
Longitude is always the first, followed by latitude, for each pair. For simplicity, let's assume that West and South are negative lat/long, as is a common convention. For example purposes, I'm going to use 32.123 W, 14.321 N. The key thing is to do the following.:
Longitude
1. Add 180 to the longitude, and take the integer value /20, and add one. Then figure out which letter of the alphabet that corresponds to, usually written in upper case. The example will be 147.877/20=7. Adding one will give the 8th letter of the alphabet, or G. Note 7.877 is remaining.
2. Take the remainder of what is left, and divide by 2, rounding down. This is the number, no conversion required. The example will give a value of 3. Note 1.877 is remaining.
3. Take the remainder that is left, and multiply by 12, and add one. Round down to the nearest integer.. This is the letter of the alphabet, usually written in lower case. The example gives a value of 22+1=23. This will be the letter w.
Latitude
1. Add 90 to the latitude, and take the integer value /10, and add one. Then figure out which letter of the alphabet that corresponds to, usually written in upper case. The example will be 104.321/10=10. Adding one will give the 8th letter of the alphabet, or J. Note 4.321 is remaining.
2. Take the remainder of what is left, and round down. This is the number, no conversion required. The example will give a value of 4. Note 0.321 is remaining.
3. Take the remainder that is left, and multiply by 24, and add one. Round down to the nearest integer.. This is the letter of the alphabet, usually written in lower case. The example gives a value of 7+1=8. This will be the letter g.
Putting them together by pairs, and alternating first longitude then latitude, gives the grid square for 32.123 W, 14.321 N to be GJ34wg.

I have the info from the RMC string as :-

Code:
```latdeg VAR BYTE 'degrees latitude
latmin VAR BYTE 'minutes latitude
NS VAR BYTE 'north or south
londeg VAR BYTE 'degrees longitude
lonmin VAR BYTE 'minutes longitude
EO VAR BYTE 'east or west```
My idea of the process is something like this :-

Code:
```locator:
lonloc1=londeg + lonmin + 180
lonloc2=lonloc1/20
lonloc3=lonloc1//20
maid1=lonloc2+1
lookup maid1    ; first main letter

lonloc4=lonloc3//2
maid3=lonloc3/2     ;first number

maid5=lonloc4*12+1
lookup maid5      ; 1st  2nd letter

latloc1=latdeg + latmin + 90
latloc2=latloc1/10+1
latloc3=latloc1//10
maid1=latloc2+1
lookup maid2    ; second main letter

maid4=latloc3     ; second number

maid6=latloc3*24+1
lookup maid6      ; 2nd 2nd letter

maidenhead=maid1, maid2, maid3, maid4, maid5, maid6```

2. ## Re: How do I discern Maidenhead Locator from GPS lat long info.

Weird - I've had this one on my list of things to make for about a year - I got a bit of a start, then other things took over.

Don't know if this helps, but HERE is a BASIC program that I was going to try to convert.

If I get going on this again, I'll keep you updated - and please let me know how you're doing with it too.

Andy

3. ## Re: How do I discern Maidenhead Locator from GPS lat long info.

OK thanks for that I will look at it.

Meanwhile here is the full code i have for getting the NMEA data I want to display. NOTE the code for maidenhead is the same as above, a work in progress. All untested as yet.
I do have a fully working code in asm but wanted it in PBP for experimental purposes.

Code:
```'
' Program to display returned value of a GPS on RB0
' LCD in 4-BIT mode PIC16F628 controller 4Mhz clock Fuse PWRT BODEN
'
'GPS sentence: \$GPRMC,192144.62,A,5041.6058,N,00412.6124,E,0.45,3 57.74,081205,,*0B

Define LCD_DREG PORTA          ' Port for LCD Data
Define LCD_DBIT 0                   ' Use upper 4 bits of Port
Define LCD_RSREG PORTB         ' Port for RegisterSelect (RS) bit
Define LCD_RSBIT 4                 ' Port Pin for RS bit  (pin9)
Define LCD_EREG PORTB          ' Port for Enable (E) bit
Define LCD_EBIT 5                   ' Port Pin for E bit    (pin7)
Define LCB_BITS 4                   ' Using 4-bit bus
Define LCD_LINES 4                  ' Using 2 line Display
Define LCD_COMMANDUS 2000      ' Command Delay (uS)
define LCD_DATAUS 50              ' Data Delay (uS)

DEFINE OSC 4
CMCON = 7
OPTION_REG.7=0                 ' Enable Pull-Up's
GPSin VAR PORTB.0
LED  VAR PortA.4               ' flash per second

TRISA.0=0
TRISA.1=0
TRISA.2=0
TRISA.3=0

TRISA.4=0 ; LED

PAUSE 500

PORTA=0
PORTB=0

'Allocate Variables for GPS:
TimeOut CON 3000
baudGPS CON 24764 '16572 + 8192 (bit 13)

hh VAR BYTE           'hours
mm VAR BYTE          'minutes
knots VAR WORD     'speed in knots (units)
knotsten VAR BYTE   'speed in knots (tens)
latdeg VAR BYTE      'degrees latitude
latmin VAR BYTE      'minutes latitude
NS VAR BYTE          'north or south
londeg VAR BYTE     'degrees longitude
lonmin VAR BYTE     'minutes longitude
EO VAR BYTE          'east or west
j VAR BYTE             'day
m VAR BYTE            'month
a VAR BYTE            'year

fix VAR WORD        'GPS fix

LCDOut \$FE, 1        'Clear Screen

LCDOut \$fe,\$80," GPS Decoder "
LCDOut \$FE,\$c0, " G8VLQ "
Pause 2000
LCDOut \$FE, 1

SerIn2 GPSin,baudGPS,Timeout,[wait("\$GPRMC"),wait(","),DEC2 hh,DEC2 mm,wait(","),fix,wait(","),DEC2 latdeg,DEC2 latmin,wait(","),NS,wait(","),DEC3 londeg,DEC2 lonmin,wait(","),EO,wait(","),knots,wait("."),DEC2 knotsten,wait(","),DEC3 course,wait(","),DEC2 j,DEC2 m,DEC2 a]

flash:                       ;not accurate pps
led high
led low

IF fix="V" Then                                            'if no GPS fix
GOTO LCD1
EndIF

LCD:                  ; LATER put time and date on first line , remove names
; callsign and QRA (maidenhead) on second line

LCDOut \$fe,\$80,"DATE: ",DEC2 j,"-",DEC2 m,"-",DEC2 a                                     ; 80 1st line
LCDOUT \$fe,\$c0,"TIME: ",DEC2 hh,":",DEC2 mm                                                 ; c0 2nd line
LCDOut \$fe,\$94,"LAT:",DEC2 latdeg,",",DEC2 latmin," ",NS                                  ; 94 3rd line
LCDOut \$fe,\$d4,"LON:",DEC2 londeg,",",DEC2 lonmin," ",EO                                ; d4 4th line

GoTo GPS

LCD1:                       ; If invalid data, just shows gps string is received

LCDOut \$fe,\$80,"  Invalid data  "                                                                       ; 80 1st line
LCDOUT \$fe,\$c0,"     No Fix     "                                                                       ; c0 2nd line
LCDOut \$fe,\$94,"LAT:",DEC2 latdeg,",",DEC2 latmin," ",NS                                 ; 94 3rd line
LCDOut \$fe,\$d4,"LON:",DEC2 londeg,",",DEC2 lonmin," ",EO                                ; d4 4th line

GoTo GPS

locator:
lonloc1=londeg + lonmin + 180
lonloc2=lonloc1/20
lonloc3=lonloc1//20
maid1=lonloc2+1
lookup maid1                         ; first main letter

lonloc4=lonloc3//2
maid3=lonloc3/2                      ;first number

maid5=lonloc4*12+1
lookup maid5                         ; 1st  2nd letter

latloc1=latdeg + latmin + 90
latloc2=latloc1/10+1
latloc3=latloc1//10
maid1=latloc2+1
lookup maid2                         ; second main letter

maid4=latloc3                        ; second number

maid6=latloc3*24+1
lookup maid6                         ; 2nd 2nd letter

maidenhead=maid1, maid2, maid3, maid4, maid5, maid6

speed:
LCDOUT \$fe,1
LCDOut \$fe,\$80,"SPEED :",knots,".",DEC2 knotsten," KNT"

END```
Last edited by tasmod; - 6th March 2014 at 07:54. Reason: spelling

4. ## Re: How do I discern Maidenhead Locator from GPS lat long info.

Thanks! I'll have a look at that.

5. ## Re: How do I discern Maidenhead Locator from GPS lat long info.

BTW, what are you building? Mine was an idea when I was driving around talking on Amateur Radio Satellites. We were in Grand Forks, North Dakota, and I was waiting for my wife to come out of a store. There happened to be an AO-51 pass happening right then, so I made a couple of contacts - only I had NO IDEA what my grid square was! I used my Winnipeg one, and thought "it would be nice to have a handheld, GPS-based unit that displays your current grid square to 6 digits". And the idea was born. I'll get to it, probably right after I finish the smoker controller I'm working on right now.

Did you happen to notice how I list my location on the forum? I guess great minds really DO think alike!

Andy
Last edited by andywpg; - 8th March 2014 at 18:37. Reason: spelling

6. ## Re: How do I discern Maidenhead Locator from GPS lat long info.

Hi Andy,

The project is already working, I just wanted more information displayed on LCD. The LCD board piggybacks the LCD display. It has a 16F818 which deals with the NMEA string and ADC functions.

It's a GPS Disciplined Oscillator producing 10MHz to 10-12 signal. For accuracy of frequency and timing for MS and EME.

It remains extremely stable but I am slightly improving it by logging the PLL control voltage and the TCXO temp swing.
By logging I can get a mean control position for either start up purposes or short term 'dropout' from gps. Thus it will keep accuracy for short term outage. If the unit is turned off then on, I can apply the correct PLL control voltage until the gps locks again. Although watching the PLL voltage swing whilst trying to lock was fascinating.

It also produces a very accurate 1PPS output. I later intend to use this to trigger the NMEA sentence display. You may be aware that the sentence suffers from lag or slight offset depending if the gps module decides to send another, other, information sentence. In my case at the moment it is 1.635 secs BEHIND actual time as my module occasionally sends out the powerID string which puts the timing RMC sentence out.
I will be turning all off except the RMC sentence. At the moment it is testing phase.

I get a very strong signal from the 60kHz time signal from Anthorn in the UK so I can actually compare the second epoch via SpecLab software visually.

7. ## Re: How do I discern Maidenhead Locator from GPS lat long info.

Trying to work through the example in post #1.

Originally Posted by tasmod
gives the grid square for 32.123 W, 14.321 N to be GJ34wg.
The best I can come up with is HK33xv at that location.
Are you sure about the example in post #1?

And it seems that Andy is in Winnipeg Manitoba Canada.
And you are near Gainsborough, U.K.

If those are close, I can't be that far off with the calculations.

8. ## Re: How do I discern Maidenhead Locator from GPS lat long info.

Originally Posted by Darrel Taylor
And it seems that Andy is in Winnipeg Manitoba Canada.
Absolutely correct

And you're right - HK33xv is in the ocean off of Cape Verde

And 14.321N 32.123W converts to HK34wh - darn near exactly what you calculated
Last edited by andywpg; - 12th March 2014 at 23:13.

9. ## Re: How do I discern Maidenhead Locator from GPS lat long info.

Thanks Andy, I knew I couldn't be that far off.

But apparently, I need to work on the math some more.
Darned Floating-Point ...

10. Woohoo!

HK34wh it is!!
And it's not even midnight yet.

It's some really ugly code right now, will need to add some "Pretty" to it.

Are you guy's using PBP3?

If not, there's only so much "Pretty" I can add.

11. ## Re: How do I discern Maidenhead Locator from GPS lat long info.

Just realised you discerned my physical location from my locator. So your code should be OK.

I did the calc by hand and got it to the example Locator given. ODD. Also needed to reverse calc the 'leftovers'

One thing not mentioned is W is a negative longtitude. I need put an IF THEN in my code to deal with the 180 for a negative W rather than E.

If you have ugly code then that's ok with me. I'm using 2.50 Darrel. Long time coding but not enough to be good with PBP

The routine could also decode the 8th place pair too, which is as close as Maidenhead gets.
Last edited by tasmod; - 13th March 2014 at 08:33.

12. ## Re: How do I discern Maidenhead Locator from GPS lat long info.

Darn it.

Scrap what I said about the example. I found my scratch pad and realised I used my own GPS co-ordinates to check the formula given to get my locator. I didn't use the example after all.

13. ## Re: How do I discern Maidenhead Locator from GPS lat long info.

Originally Posted by Darrel Taylor
Woohoo!

HK34wh it is!!
And it's not even midnight yet.

It's some really ugly code right now, will need to add some "Pretty" to it.

Are you guy's using PBP3?
I am - I look forward to seeing your code because math and I do not get along well.....

That's actually one of the reasons I have been delaying this project - the math was a bit above me right now.... I have just been using the AMSAT page to convert and see where a grid square takes me on the map.
Last edited by andywpg; - 13th March 2014 at 14:42.

14. An afterthought, before the fact.
I went through this trying to make sure it didn't require PBP3 since Rob doesn't have it. But now that I've posted it, I realized it requires PBP 2.60 or later. DOH!
At least you can download the free PBP3 trial version and compile it with that, or you can change the arrayread/arraywrite statements, so I'm not changing it.
---------------------------------- -------------------------------- ----------------------------------

Ok, here goes ...
It's not as ugly as it was, but without PBP3 there's only so much you can do.

This code is based on the Perl script on the Wikipedia site for Maidenhead Locator System by Chris Ruvolo.
Although I had to do things quite differently for the Microchip Floating-Point routines.

The Microchip Floating-Point routines for PBP are available from http://melabs.com/resources/fp.htm
Extract the .zip file to the same folder as your source code, or this code.

To try to make things easy, the routines start out with a String in the same format as the Lat/Lon data of the \$GPRMC sentence.

For instance, an approximation of the IO93ok square is 0 degrees, 47.70 minutes West Longitude by 53 degrees, 26.20 minutes North latitude.
\$GPRMC will present the data as .... 5326.20,N and 00047.70,W.
These can be parsed from the GPS data, or entered manually with the following two statements ... Note that they are null terminated.
Code:
```ARRAYWRITE LonStr,["00047.70,W",0]  ; -0° 47.70'
ARRAYWRITE LatStr,["5326.20,N",0]   ; 53° 26.20```
I am entering them manually for this sample.

I'm using the 24-bit Floating-Point routines, since it gave the same results as the 32-bit FP, but you can use either one by simply changing the include file.
I imagine the 32-bit routines will be better around the edges of each square, but I haven't confirmed that.

I'm using a 16F1937, so if you are using an 18F ... you'll need to use the 18F FP includes.

Obviously, you need to initialize your hardware configs first.
Code:
```; Filename    : Maidenhead.pbp
; Compiler    : PICBASIC PRO Compiler
; Target PIC  : 16F1937, but will work with most any chip
; Oscillator  : ANY
; Description : PICBASIC PRO program to convert between
;             : GPS Sexagesimal to Maidenhead coordinate systems
;-------------------------------------------------------------------------------

; use only one of the FP includes
INCLUDE "FP20.bas"     ; 24-bit Floating Point for 14-bit cores with RAM at \$20
;INCLUDE "FP2032.bas"   ; 32-bit Floating Point for 14-bit cores with RAM at \$20

DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive
DEFINE HSER_TXSTA 20h ' Enable transmit, BRGH = 0
DEFINE HSER_SPBRG 25  ' 19200 Baud @ 32MHz, 0.16%
DEFINE HSER_CLROERR 1 ' Clear overflow automatically

HSEROUT ["16F1937, 32Mhz, PBP3 not required",13,10,13,10]

MH     VAR BYTE[6]

LonStr    VAR BYTE[12]
LatStr    VAR BYTE[12]
LonDeg    VAR BYTE
LonMin    VAR BYTE
LonMinDec VAR BYTE
LonDir    VAR BYTE
LatDeg    VAR BYTE
LatMin    VAR BYTE
LatMinDec VAR BYTE
LatDir    VAR BYTE

ARRAYWRITE LonStr,["00047.70,W",0]  ; -0° 47.70'  <-- Enter location here
ARRAYWRITE LatStr,["5326.20,N",0]   ; 53° 26.20'

HSEROUT ["LonStr  = ", STR LonStr,13,10]          ; display manual input
HSEROUT ["LatStr  = ", STR LatStr,13,10]

;----[parse strings as if they came from a GPS]---------------------------------
ARRAYREAD LonStr,[DEC3 LonDeg, DEC2 LonMin, Dec LonMinDec, LonDir]
ARRAYREAD LatStr,[DEC2 LatDeg, DEC2 LatMin, Dec LatMinDec, LatDir]

;----[convert Longitude Sexagesimal to Decimal Degrees]-------------------------
Aint = LonMinDec : GOSUB ItoFA    ; decimal portion of Minutes
Bint = 100 : GOSUB ItoFB          ; divided by 100
GOSUB fpdiv
Bint = LonMin : GOSUB ItoFB       ; add whole portion of Minutes
Bint = 60 : GOSUB ItoFB           ; divide by 60
GOSUB fpdiv
Bint = LonDeg : GOSUB ItoFB       ; add degrees
IF LonDir = "W" THEN              ; if west of Prime Meridian
GOSUB AtoB
Aint = 0    : GOSUB ItoFA     ; subtract from 0 to negate
GOSUB fpsub
ENDIF

Bint = 180  : GOSUB ItoFB         ; add 180

;----[Have Longitude in AARG as Float]------------------------------------------
GOSUB SaveLon                     ; save Longitude for later
Bint = 20   : GOSUB ItoFB         ; Lon / 20
GOSUB fpdiv
GOSUB SaveAARG                    ; save AARG for modulus
GOSUB FtoIA                       ; get integer
MH(0) = "A" + Aint                ; + "A" = First character

; -- do  Lon // 20 --- (modulus)
Bint = Aint                       ; copy integer result to BARG
GOSUB ItoFB                       ; convert it to float
GOSUB RestoreAARG                 ; restore Lon / 20 to AARG
GOSUB fpsub                       ; subtract integer
Bint = 20                         ; multiply times original divisor (20)
GOSUB ItoFB
GOSUB fpmul                       ; AARG now contains the modulus

Bint = 2    : GOSUB ItoFB         ; divide modulus by 2
GOSUB fpdiv
GOSUB FtoIA                       ; get integer
MH(2) = "0" + Aint                ; + "0" = Third character

GOSUB RestoreLon                  ; restore Longitude
Bint = 2 : GOSUB ItoFB
GOSUB fpdiv                       ; divide by 2

GOSUB FtoIA                       ; get integer
Bint = Aint * 2  : GOSUB ItoFB    ; put int * 2 in BARG, change back to float
GOSUB RestoreLon                  ; restore original Longitude
GOSUB fpsub                       ; subtract A - B

Bint = 12 : GOSUB ItoFB           ; Multiply * 12
GOSUB fpmul
GOSUB FtoIA                       ; get integer

MH(4) = "a" + Aint                ; + "a" = Fifth Character

;----[convert Latitude Sexagesimal to Decimal Degrees]--------------------------
Aint = LatMinDec : GOSUB ItoFA    ; decimal portion of Minutes
Bint = 100 : GOSUB ItoFB          ; divided by 100
GOSUB fpdiv
Bint = LatMin : GOSUB ItoFB       ; add whole portion of Minutes
Bint = 60 : GOSUB ItoFB           ; divide by 60
GOSUB fpdiv
Bint = LatDeg : GOSUB ItoFB       ; add degrees
IF LatDir = "S" THEN              ; if south of equator
GOSUB AtoB
Aint = 0    : GOSUB ItoFA     ; subtract from 0 to negate
GOSUB fpsub
ENDIF

Bint = 90  : GOSUB ItoFB          ; add 90

;----[Have Latitude  in AARG as Float]------------------------------------------
GOSUB SaveLon                     ; save Latitude for later
Bint = 10   : GOSUB ItoFB         ; Lat / 10
GOSUB fpdiv
GOSUB SaveAARG                    ; save AARG for modulus
GOSUB FtoIA
MH(1) = "A" + Aint                ; + "A" = Second character

; -- do  Lat // 10 --- (modulus)
Bint = Aint                       ; copy integer result to BARG
GOSUB ItoFB                       ; convert it to float
GOSUB RestoreAARG                 ; restore Lat / 10 to AARG
GOSUB fpsub                       ; subtract integer
Bint = 10                         ; multiply times original divisor (10)
GOSUB ItoFB
GOSUB fpmul                       ; AARG now contains the modulus

GOSUB FtoIA
MH(3) = "0" + Aint                ; + "0" = Fourth character

GOSUB RestoreLon                  ; restore original Latitude
GOSUB FtoIA                       ; get integer
Bint = Aint : GOSUB ItoFB         ; put int in BARG, change back to float
GOSUB RestoreLon                  ; restore original Latitude
GOSUB fpsub                       ; subtract A - B

Bint = 24 : GOSUB ItoFB           ; Multiply * 24
GOSUB fpmul
GOSUB FtoIA                       ; get integer

MH(5) = "a" + Aint                ; + "a" = Sixth character

HSEROUT ["LOC ",STR MH\6,13,10,13,10] ; show final result

Main:                             ; blink an LED when done
HIGH PORTA.0
PAUSE 500
LOW PORTA.0
PAUSE 500
GOTO Main

;-------------------------------------------------------------------------------
Aexp_Copy    VAR BYTE
AARGB0_Copy  VAR BYTE
AARGB1_Copy  VAR BYTE
AARGB2_Copy  VAR BYTE

Aexp_Lon     VAR BYTE
AARGB0_Lon   VAR BYTE
AARGB1_Lon   VAR BYTE
AARGB2_Lon   VAR BYTE

SaveAARG:
Aexp_Copy = Aexp
AARGB0_Copy = AARGB0
AARGB1_Copy = AARGB1
AARGB2_Copy = AARGB2
RETURN

RestoreAARG:
Aexp = Aexp_Copy
AARGB0 = AARGB0_Copy
AARGB1 = AARGB1_Copy
AARGB2 = AARGB2_Copy
RETURN

AtoB:
Bexp = Aexp
BARGB0 = AARGB0
BARGB1 = AARGB1
BARGB2 = AARGB2
RETURN

SaveLon:
Aexp_Lon = Aexp
AARGB0_Lon = AARGB0
AARGB1_Lon = AARGB1
AARGB2_Lon = AARGB2
RETURN

RestoreLon:
Aexp = Aexp_Lon
AARGB0 = AARGB0_Lon
AARGB1 = AARGB1_Lon
AARGB2 = AARGB2_Lon
RETURN```
The output from the program in a terminal looks like this ...
Code:
```Maidenhead Locator
16F1937, 32Mhz, PBP3 not required

LonStr  = 00047.70,W
LatStr  = 5326.20,N
LOC IO93ok```
If you are using an Enhanced 14-bit core like the 16F1937 that I'm using ... you'll need to add the processor to the DEV_FAM.INC file from the FP.zip
For the 16F1937 add this towards the bottom of the file (before the if statement).
Code:
```    IFDEF   __16F1937          ; Generic Processor Type
P16CXX      SET    TRUE        ; If P16CXX, use INHX8M file format.
P16_MAP2    SET    TRUE        ;
ENDIF```
References:
Last edited by Darrel Taylor; - 14th March 2014 at 06:09.

15. ## Re: How do I discern Maidenhead Locator from GPS lat long info.

Umm, WOW! Thanks Darrel! And my brain thanks you even more, since it gets uppity when it has to do complex math!

16. ## Re: How do I discern Maidenhead Locator from GPS lat long info.

And a WOW from me Darrel. Thanks for your help. Surprisingly I think I can follow and understand the code

Sorry I'm late back to the thread. One of the winter bugs has had hold of me, not the type I can rewrite

The project code I posted above doesn't work in the Serin2 GPS routine. Either the line is incorrect or the speed. I've tried every speed and state but no joy. Signal is at the pic pin every second.

The code compiles but says 'error, expected [ ' but they are there?

I will try out the code shortly, many thanks again.

17. ## Re: How do I discern Maidenhead Locator from GPS lat long info.

Originally Posted by tasmod
The code compiles but says 'error, expected [ ' but they are there?
The SERIN2 line has a value for the timeout, but there's no label for it to jump to.

18. ## Re: How do I discern Maidenhead Locator from GPS lat long info.

Doh, sometimes you can't see the wood for the trees !

Thanks again Darrel, you've no idea how many times I looked at that line.

Code is working at base level now and info is on screen, next is to incorporate the Locator code of yours.

19. ## Re: How do I discern Maidenhead Locator from GPS lat long info.

Awesome!

Can't wait to see an IO93ok on that LCD.

20. ## Re: How do I discern Maidenhead Locator from GPS lat long info.

Hi Darrel,
Hmm, I wanted to move on to final stages of the project adding the locator code but before I could I came up against something I've not had before.

I was using a 16f628A and wanted to port across to a 16F818 for a single adc channel use. (Monitor a pll control voltage)

I had errors of "Argument out of range" when I added my usual working ADC code. It works standalone on the 818 nicely.

The code for gps alone works in the 818 as per lcd pic. So I'm lost now.

In the working gps code alone, no adc code. I did have some very odd messages re 'out of range' with the code with END at the finish of the code. It seemed like something was hidden in the space in MCS. Deleting back to the final Goto GPS cleared the messages.

This is the gps code with adc which errors. I daren't add the locator code yet

Code:
```;
;
; 			        PIC16F818
;                          __________
;     D6-------------RAN2 |1       18| RAN1---------D5
;     D7-------------RAN3 |2       17| RAN0---------D4
;     LED------------RAN4 |3       16| OSC1--------XTAL
;     +5V-----------!MCLR |4       15| OSC2--------XTAL
;     Ground----------Vss |5       14| VDD---------+5 V
;     NMEA data-------RB0 |6       13| RB7---------Not used
;     Serial data out-RB1 |7       12| RB6---------Not used
;     Not used--------RB2 |8       11| RB5---------LCD Enable
;     Pushbutton------RB3 |9       10| RB4---------LCD Register select
;                          ----------
;

;====================================================================='
' Program to display returned value of a GPS on RB0
' LCD in 4-BIT mode PIC16F818 controller 4Mhz clock Fuse PWRT BODEN
'
'GPS sentence: \$GPRMC,192144.62,A,5041.6058,N,00412.6124,E,0.45,3 57.74,081205,,*0B

Define LCD_DREG PORTA          ' Port for LCD Data
Define LCD_DBIT 0              ' Use upper 4 bits of Port
Define LCD_RSREG PORTB         ' Port for RegisterSelect (RS) bit
Define LCD_RSBIT 4             ' Port Pin for RS bit  (pin9)
Define LCD_EREG PORTB          ' Port for Enable (E) bit
Define LCD_EBIT 5              ' Port Pin for E bit    (pin7)
Define LCB_BITS 4              ' Using 4-bit bus
Define LCD_LINES 4             ' Using 2 line Display
Define LCD_COMMANDUS 1500      ' Command Delay (uS)
define LCD_DATAUS 50           ' Data Delay (uS)

DEFINE OSC 4

OPTION_REG.7=0                 ' Enable Pull-Up's
GPSin VAR PORTB.0
ADCON1 = %10000100 ' Set PORTA analog and RIGHT justify result
ADCON0 = %01010001 ' Configure and turn on A/D Module channel 4 Fosc 8
PAUSE 500

'Declare variables
val VAR WORD      ' final calculated adc valuesWORD' final calculated adc values
volt VAR WORD     ' scaled value real part
voltd1 VAR WORD   ' scaled value first decimal place
voltd2 VAR WORD   ' scaled value second decimal place
i var byte        ' counter

'Allocate Variables for GPS:
TimeOut CON 2000

hh VAR BYTE             'hours
mm VAR BYTE             'minutes
ss VAR BYTE             'seconds
knots VAR WORD          'speed in knots (units)
knotsten VAR BYTE       'speed in knots (tens)
latdeg VAR BYTE         'degrees latitude
latmin VAR BYTE         'minutes latitude
NS VAR BYTE             'north or south
londeg VAR BYTE         'degrees longitude
lonmin VAR BYTE         'minutes longitude
EW VAR BYTE             'east or west
d VAR BYTE              'day
m VAR BYTE              'month
y VAR BYTE              'year

fix VAR WORD 'GPS fix

LCDOut \$fe,\$80,"   GPS Decoder  "
LCDOut \$FE,\$c0, "    G8VLQ Mk1  "
Pause 500
LCDOut \$FE, 1           'Clear Screen

SerIn2 GPSin,188,Timeout,LCD1,[wait("\$GPRMC"),wait(","),DEC2 hh,DEC2 mm,DEC2 ss,wait(",")_
,fix,wait(","),DEC2 latdeg,DEC2 latmin,wait(","),NS,wait(","),DEC3 londeg,DEC2 lonmin,_
wait(","),EW,wait(","),knots,wait("."),DEC2 knotsten,wait(","),DEC3 course,wait(","),DEC2 d,DEC2 m,DEC2 y]

IF fix="V" Then         'if no GPS fix
GOTO LCD1
EndIF

gosub PLL

LCD:

LCDOut \$fe,\$80,DEC2 d,"-",DEC2 m,"-",DEC2 y," ",#volt, ".", # voltd1,# voltd2, "Vdc"            ; 80 1st line
LCDOUT \$fe,\$c0,"    ",DEC2 hh,":",DEC2 mm,":",DEC2 ss,"    "                                ; c0 2nd line
LCDOut \$fe,\$90," LAT: ",DEC2 latdeg,",",DEC2 latmin," ",NS                                 ; 90 3rd line
LCDOut \$fe,\$d0," LON: ",DEC2 londeg,",",DEC2 lonmin," ",EW                                 ; d0 4th line

GoTo GPS

LCD1:       ; If invalid data, just shows gps string is received

LCDOut \$fe,\$80,#volt, ".", # voltd1,# voltd2, "Vdc"                                         ; 80 1st line
LCDOUT \$fe,\$c0,"     No Fix       "                                                       ; c0 2nd line
LCDOut \$fe,\$90," LAT: ",DEC2 latdeg,",",DEC2 latmin," ",NS                                ; 90 3rd line
LCDOut \$fe,\$d0," LON: ",DEC2 londeg,",",DEC2 lonmin," ",EW                                ; d0 4th line

goto GPS

LCD2:      ; 20 character display. Put time and date on first line , removed names.
; callsign and QRA (maidenhead) on second line

LCDOut \$fe,\$80,DEC2 d,"-",DEC2 m,"-",DEC2 y,DEC2 hh,":",DEC2 mm                         ; 80 1st line
LCDOut \$fe,\$80," G8VLQ   "                                                              ; c0 2nd line
LCDOut \$fe,\$90,"LAT: ",DEC2 latdeg,",",DEC2 latmin," ",NS                                ; 90 3rd line
LCDOut \$fe,\$d0,"LON: ",DEC2 londeg,",",DEC2 lonmin," ",EW                                ; d0 4th line

GoTo GPS

PLL:
Val = 0                       ' Value returned is the average of 5 conversions
For i = 0 TO 4
ADCON0.4 = 1                  ' Start conversion
NoteDone:
pause 1
IF ADCON0.4 = 1 Then NoteDone
nEXT I
VAL = VAL/5
' Calculate Volatage to 2 decimal places
volt = val * 5/1024
voltd1 = ( val * 5//1024) * 10/1024
Voltd2 = ((val *5 //1024) * 10//1024) * 10/1024
RETURN```

21. ## Re: How do I discern Maidenhead Locator from GPS lat long info.

The 16F628A has 2K words of program space.
The 16F818 only has 1K words.

You're going to need a bigger chip.
The Maidenhead routine with Floating point libraries will take >1.5K by itself.

You'll need at least 4K, but why not get one with 8K so you won't have the problem again later.
I'm sure you'll want to add a Morse Code transmitter and receiver some day.

22. ## Re: How do I discern Maidenhead Locator from GPS lat long info.

Now that was completely stupid of me, I apologise for such a silly mistake. I had never seen the message before and assumed it was a code error.

I never gave it a thought to look at the chip spec. The reason to change over to 818 was just one adc input. The chip otherwise is pin compatible for what I've already done.

I think I will remake a new display pcb and use the 16f876 28 pin chip that has 8k.

The project uses the chip to accept the NMEA string from a Rockwell gps module and display it. This older gps module also produces accurate 1PPS and 10kHz signals when gps has a fix.
I'm using these signals on a pll and divider board to lock a 10mhz tcxo.

In its present application it would have worked fine but I wanted to monitor the gps pll control voltage on the board to check for frequency lock.
If the voltage was 1.65v then the oscillator was in lock state.
The display did show whether the satellites produced a fix but not whether the oscillator had locked against the 10khz frequency. Watching the pll control voltage hunt back and forth whilst the gps attempted a fix was facinating but impractical for 'normal' usage.

Once I have the display running again I'll report back.

23. ## Re: How do I discern Maidenhead Locator from GPS lat long info.

Just looked in my box o bits and found a 18f1330 which is pin compatible with 4k space.

Not quite pin compatible unfortunately, ports mixed
Last edited by tasmod; - 24th March 2014 at 10:02.

24. ## Re: How do I discern Maidenhead Locator from GPS lat long info.

Here you go Darrel -

That display is huge at 4inch by 2 inch (See pic chip in background) Used a 16f876a in the end. That's your BigDigit code put to use as well.
Display shows 1.65v which indicates to me that the oscillator control voltage is stable and in lock.

Code needs some polishing especially Month but that's a work in progress :-

Code:
```;
;
; 			        PIC16F876a
;                          __________
;                   !MCLR |1        28| RB7------D7
;     PLL Volt--AN0---RA0 |2        27| RB6------D6
;         Temp--AN1---RA1 |3        26| RB5------D5
;               AN2---RA2 |4        25| RB4------D4
;               AN3---RA3 |5        24| RB3------LCD E
;         NMEA data---RA4 |6        23| RB2------LCD RS
;               AN4---RA5 |7        22| RB1------
;            Ground---Vss |8        21| RB0------
;             OSC1---XTAL |9        20| VDD------ +5 V
;             OSC2---XTAL |10       19| Vss------Ground
;                  ---RC0 |11       18| RC7------
;                  ---RC1 |12       17| RC6------
;                  ---RC2 |13       16| RC5------
;           pbutton---RC3 |14       15| RC4------
;                          ----------
;
;   Serial data out               Not used    Not used
;====================================================================='
' Program to display returned value of a GPS on RA4
' LCD in 4-BIT mode PIC16F876a controller 4Mhz clock Fuse PWRT BODEN
'
'GPS sentence: \$GPRMC,192144.62,A,5041.6058,N,00412.6124,E,0.45,3 57.74,081205,,*0B

@__config_HS_OSC
@__config_BOD_OFF
@__config_PWRT_ON
@__config_WDT_ON
@__config_PROTECT_OFF
@__config_LVP_OFF

;-- Place a copy of these variables in your Main program -------------------
;--   The compiler will tell you which lines to un-comment                --
;--   Do Not un-comment these lines                                       --
;---------------------------------------------------------------------------
;wsave   VAR BYTE    \$20     SYSTEM      ' location for W if in bank0
wsave   VAR BYTE    \$70     SYSTEM      ' alternate save location for W
' if using \$70, comment wsave1-3

' --- IF any of these three lines cause an error ?? ------------------------
'       Comment them out to fix the problem ----
' -- Which variables are needed, depends on the Chip you are using --
wsave1  VAR BYTE    \$A0     SYSTEM      ' location for W if in bank1
wsave2  VAR BYTE    \$120    SYSTEM      ' location for W if in bank2
;wsave3  VAR BYTE    \$1A0    SYSTEM      ' location for W if in bank3
' --------------------------------------------------------------------------

INCLUDE "FP20.bas"     ; 24-bit Floating Point for 14-bit cores with RAM at \$20

Define LCD_DREG PORTB          ' Port for LCD Data
Define LCD_DBIT 4              ' Set LCD starting data bit
Define LCD_RSREG PORTB         ' Port for RegisterSelect (RS) bit
Define LCD_RSBIT 2             ' Port Pin for RS bit  (pin9)
Define LCD_EREG PORTB          ' Port for Enable (E) bit
Define LCD_EBIT 3              ' Port Pin for E bit    (pin7)
Define LCB_BITS 4              ' Using 4-bit bus

Define LCD_COMMANDUS 1500      ' Command Delay (uS)
define LCD_DATAUS 50           ' Data Delay (uS)

DEFINE OSC 4

OPTION_REG.7=0                 ' Enable Pull-Up's
GPSin VAR PORTA.4
Pbutton VAR PORTC.3

ADCON1 = %10000100 ' Set PORTA analog and RIGHT justify result
ADCON0 = %01000001 ' Configure and turn on A/D Module channel 0 Fosc 8
PAUSE 500

'Declare variables
val VAR WORD      ' final calculated adc valuesWORD' final calculated adc values
volt VAR WORD     ' scaled value real part
voltd1 VAR WORD   ' scaled value first decimal place
voltd2 VAR WORD   ' scaled value second decimal place
i var byte        ' counter

'Allocate Variables for GPS:
TimeOut CON 2000

hh VAR BYTE             'hours
mm VAR BYTE             'minutes
ss VAR BYTE             'seconds
knots VAR WORD          'speed in knots (units)
knotsten VAR BYTE       'speed in knots (tens)
latdeg VAR BYTE         'degrees latitude
latmin VAR BYTE         'minutes latitude
latsecs VAR BYTE        'seconds latitude
NS VAR BYTE             'north or south
londeg VAR BYTE         'degrees longitude
lonmin VAR BYTE         'minutes longitude
lonsecs VAR BYTE        'seconds longtitude
EW VAR BYTE             'east or west
d VAR BYTE              'day
m VAR BYTE              'month
y VAR BYTE              'year

MH     VAR BYTE[6]

LonMinDec VAR BYTE
LonDir    VAR BYTE

LatMinDec VAR BYTE
LatDir    VAR BYTE

nPos  var byte
nDig  var byte

'Set up the digits (http://www.darreltaylor.com/files/CustChar.htm)
LCDOUT  \$FE,\$40,\$03,\$03,\$03,\$03,\$03,\$03,\$03,\$03  ' Cust Char #0
'LCDOUT  \$FE,\$40,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02  ' Cust Char #0
LCDOUT  \$FE,\$48,\$1F,\$1F,\$1B,\$1B,\$1B,\$1B,\$1B,\$1B  ' Cust Char #1
LCDOUT  \$FE,\$50,\$1F,\$1F,\$18,\$18,\$18,\$18,\$1F,\$1F  ' Cust Char #2
LCDOUT  \$FE,\$58,\$03,\$03,\$03,\$03,\$03,\$03,\$1F,\$1F  ' Cust Char #3
LCDOUT  \$FE,\$60,\$1F,\$1F,\$1B,\$1B,\$1B,\$1B,\$1F,\$1F  ' Cust Char #4
LCDOUT  \$FE,\$68,\$1B,\$1B,\$1B,\$1B,\$1B,\$1B,\$1F,\$1F  ' Cust Char #5
LCDOUT  \$FE,\$70,\$1F,\$1F,\$03,\$03,\$03,\$03,\$1F,\$1F  ' Cust Char #6
LCDOUT  \$FE,\$78,\$1F,\$1F,\$03,\$03,\$03,\$03,\$03,\$03  ' Cust Char #7
LCDOUT  \$FE,\$40,\$03,\$03,\$03,\$03,\$03,\$03,\$03,\$03  ' Cust Char #8

fix VAR WORD 'GPS fix

LCDOut \$fe,\$80,"    GPS Decoder     "
LCDOut \$FE,\$c0," G8VLQ  March 2014  "
Pause 3000
LCDOut \$FE, 1           'Clear Screen

SerIn2 GPSin,188,Timeout,Clock,[wait("\$GPRMC"),wait(","),DEC2 hh,DEC2 mm,DEC2 ss,wait(","),fix,wait(",")_
,DEC2 latdeg,DEC2 latmin,wait("."),DEC2 latsecs,wait(","),NS,wait(","),DEC3 londeg,DEC2 lonmin,wait("."),DEC2 lonsecs,_
wait(","),EW,wait(","),knots,wait("."),DEC2 knotsten,wait(","),DEC3 course,wait(","),DEC2 d,DEC2 m,DEC2 y]

LonMinDec = lonmin
LatMinDec = latmin
LonDir = EW
LatDir = NS

gosub PLL         ;pll control voltage
GOSUB Clock      ; Large digit clock
goto GPS

If m = 01 then gosub January          ; show month
If m = 02 then gosub February
If m = 03 then gosub March
If m = 04 then gosub April
If m = 05 then gosub May
If m = 06 then gosub June
If m = 07 then gosub July
If m = 08 then gosub August
If m = 09 then gosub September
If m = 10 then gosub October
If m = 11 then gosub November
If m = 12 then gosub December

;-------------------------------------------------------------

PLL:
Val = 0                       ' Value returned is the average of 5 conversions
For i = 0 TO 4
ADCON0.2 = 1                  ' Start conversion
NotDone:
pause 1
IF ADCON0.2 = 1 Then NotDone
nEXT I
VAL = VAL/5
' Calculate Voltage to 2 decimal places
volt = val * 5/1024
voltd1 = ( val * 5//1024) * 10/1024
Voltd2 = ((val *5 //1024) * 10//1024) * 10/1024
RETURN

;---------------------------------------------

Locator:
;----[convert Longitude Sexagesimal to Decimal Degrees]-------------------------
Aint = LonMinDec : GOSUB ItoFA    ; decimal portion of Minutes
Bint = 100 : GOSUB ItoFB          ; divided by 100
GOSUB fpdiv
Bint = LonMin : GOSUB ItoFB       ; add whole portion of Minutes
Bint = 60 : GOSUB ItoFB           ; divide by 60
GOSUB fpdiv
Bint = LonDeg : GOSUB ItoFB       ; add degrees
IF LonDir = "W" THEN              ; if west of Prime Meridian
GOSUB AtoB
Aint = 0    : GOSUB ItoFA     ; subtract from 0 to negate
GOSUB fpsub
ENDIF

Bint = 180  : GOSUB ItoFB         ; add 180

;----[Have Longitude in AARG as Float]------------------------------------------
GOSUB SaveLon                     ; save Longitude for later
Bint = 20   : GOSUB ItoFB         ; Lon / 20
GOSUB fpdiv
GOSUB SaveAARG                    ; save AARG for modulus
GOSUB FtoIA                       ; get integer
MH(0) = "A" + Aint                ; + "A" = First character

; -- do  Lon // 20 --- (modulus)
Bint = Aint                       ; copy integer result to BARG
GOSUB ItoFB                       ; convert it to float
GOSUB RestoreAARG                 ; restore Lon / 20 to AARG
GOSUB fpsub                       ; subtract integer
Bint = 20                         ; multiply times original divisor (20)
GOSUB ItoFB
GOSUB fpmul                       ; AARG now contains the modulus

Bint = 2    : GOSUB ItoFB         ; divide modulus by 2
GOSUB fpdiv
GOSUB FtoIA                       ; get integer
MH(2) = "0" + Aint                ; + "0" = Third character

GOSUB RestoreLon                  ; restore Longitude
Bint = 2 : GOSUB ItoFB
GOSUB fpdiv                       ; divide by 2

GOSUB FtoIA                       ; get integer
Bint = Aint * 2  : GOSUB ItoFB    ; put int * 2 in BARG, change back to float
GOSUB RestoreLon                  ; restore original Longitude
GOSUB fpsub                       ; subtract A - B

Bint = 12 : GOSUB ItoFB           ; Multiply * 12
GOSUB fpmul
GOSUB FtoIA                       ; get integer

MH(4) = "a" + Aint                ; + "a" = Fifth Character

;----[convert Latitude Sexagesimal to Decimal Degrees]--------------------------
Aint = LatMinDec : GOSUB ItoFA    ; decimal portion of Minutes
Bint = 100 : GOSUB ItoFB          ; divided by 100
GOSUB fpdiv
Bint = LatMin : GOSUB ItoFB       ; add whole portion of Minutes
Bint = 60 : GOSUB ItoFB           ; divide by 60
GOSUB fpdiv
Bint = LatDeg : GOSUB ItoFB       ; add degrees
IF LatDir = "S" THEN              ; if south of equator
GOSUB AtoB
Aint = 0    : GOSUB ItoFA     ; subtract from 0 to negate
GOSUB fpsub
ENDIF

Bint = 90  : GOSUB ItoFB          ; add 90

;----[Have Latitude  in AARG as Float]------------------------------------------
GOSUB SaveLon                     ; save Latitude for later
Bint = 10   : GOSUB ItoFB         ; Lat / 10
GOSUB fpdiv
GOSUB SaveAARG                    ; save AARG for modulus
GOSUB FtoIA
MH(1) = "A" + Aint                ; + "A" = Second character

; -- do  Lat // 10 --- (modulus)
Bint = Aint                       ; copy integer result to BARG
GOSUB ItoFB                       ; convert it to float
GOSUB RestoreAARG                 ; restore Lat / 10 to AARG
GOSUB fpsub                       ; subtract integer
Bint = 10                         ; multiply times original divisor (10)
GOSUB ItoFB
GOSUB fpmul                       ; AARG now contains the modulus

GOSUB FtoIA
MH(3) = "0" + Aint                ; + "0" = Fourth character

GOSUB RestoreLon                  ; restore original Latitude
GOSUB FtoIA                       ; get integer
Bint = Aint : GOSUB ItoFB         ; put int in BARG, change back to float
GOSUB RestoreLon                  ; restore original Latitude
GOSUB fpsub                       ; subtract A - B

Bint = 24 : GOSUB ItoFB           ; Multiply * 24
GOSUB fpmul
GOSUB FtoIA                       ; get integer

MH(5) = "a" + Aint                ; + "a" = Sixth character

RETURN
;-------------------------------------------------------------------------------
Aexp_Copy    VAR BYTE
AARGB0_Copy  VAR BYTE
AARGB1_Copy  VAR BYTE
AARGB2_Copy  VAR BYTE

Aexp_Lon     VAR BYTE
AARGB0_Lon   VAR BYTE
AARGB1_Lon   VAR BYTE
AARGB2_Lon   VAR BYTE

SaveAARG:
Aexp_Copy = Aexp
AARGB0_Copy = AARGB0
AARGB1_Copy = AARGB1
AARGB2_Copy = AARGB2
RETURN

RestoreAARG:
Aexp = Aexp_Copy
AARGB0 = AARGB0_Copy
AARGB1 = AARGB1_Copy
AARGB2 = AARGB2_Copy
RETURN

AtoB:
Bexp = Aexp
BARGB0 = AARGB0
BARGB1 = AARGB1
BARGB2 = AARGB2
RETURN

SaveLon:
Aexp_Lon = Aexp
AARGB0_Lon = AARGB0
AARGB1_Lon = AARGB1
AARGB2_Lon = AARGB2
RETURN

RestoreLon:
Aexp = Aexp_Lon
AARGB0 = AARGB0_Lon
AARGB1 = AARGB1_Lon
AARGB2 = AARGB2_Lon
RETURN
;---------------------------------------

January:
LCDOut \$fe,\$80,DEC2 d," Jan ",DEC2 y,"  ",DEC2 hh,":",DEC2 mm,":",DEC2 ss
RETURN

February:
LCDOut \$fe,\$80,DEC2 d," Feb ",DEC2 y,"  ",DEC2 hh,":",DEC2 mm,":",DEC2 ss
RETURN

March:
LCDOut \$fe,\$80,DEC2 d," Mar ",DEC2 y,"  ",DEC2 hh,":",DEC2 mm,":",DEC2 ss
RETURN

April:
LCDOut \$fe,\$80,DEC2 d," Apr ",DEC2 y,"  ",DEC2 hh,":",DEC2 mm,":",DEC2 ss
RETURN

May:
LCDOut \$fe,\$80,DEC2 d," May ",DEC2 y,"  ",DEC2 hh,":",DEC2 mm,":",DEC2 ss
RETURN

June:
LCDOut \$fe,\$80,DEC2 d," Jun ",DEC2 y,"  ",DEC2 hh,":",DEC2 mm,":",DEC2 ss
RETURN

July:
LCDOut \$fe,\$80,DEC2 d," Jul ",DEC2 y,"  ",DEC2 hh,":",DEC2 mm,":",DEC2 ss
RETURN

August:
LCDOut \$fe,\$80,DEC2 d," Aug ",DEC2 y,"  ",DEC2 hh,":",DEC2 mm,":",DEC2 ss
RETURN

September:
LCDOut \$fe,\$80,DEC2 d," Sep ",DEC2 y,"  ",DEC2 hh,":",DEC2 mm,":",DEC2 ss
RETURN

October:
LCDOut \$fe,\$80,DEC2 d," Oct ",DEC2 y,"  ",DEC2 hh,":",DEC2 mm,":",DEC2 ss
RETURN

November:
LCDOut \$fe,\$80,DEC2 d," Nov ",DEC2 y,"  ",DEC2 hh,":",DEC2 mm,":",DEC2 ss
RETURN

December:
LCDOut \$fe,\$80,DEC2 d," Dec ",DEC2 y,"  ",DEC2 hh,":",DEC2 mm,":",DEC2 ss
RETURN

;--------------------------------------------------------------------------

Clock:                     ;Display time

nDig=hh dig 1 : nPos=1 : gosub displaydigit
nDig=hh dig 0 : nPos=2 : gosub displaydigit
npos=3 : gosub colon
ndig=mm dig 1 : npos=4 : gosub displaydigit
ndig=mm dig 0 : npos=5 : gosub displaydigit
npos=6 : gosub colon
ndig=ss dig 1 : npos=7 : gosub displaydigit
ndig=ss dig 0 : npos=8 : gosub displaydigit

LCDOut \$fe,\$80+9,"  ",DEC2 d,"-",DEC2 m,"-",DEC2 y
LCDOut \$fe,\$c0+9,"    ",#volt, ".", # voltd1,# voltd2,"v"
LCDOUT \$fe,\$94,"   G8VLQ    ",STR MH\6
LCDOut \$fe,\$d4,DEC2 latdeg,\$DF,DEC2 latmin,"'",DEC2 latsecs,NS," ",DEC2 londeg,\$DF,DEC2 lonmin,"'",DEC2 lonsecs,EW                           ; ,#volt, ".", # voltd1,# voltd2,"v"   ; d4 4th line

displaydigit:
if ndig=0 then gosub zero
if ndig=1 then gosub one
if ndig=2 then gosub two
if ndig=3 then gosub three
if ndig=4 then gosub four
if ndig=5 then gosub five
if ndig=6 then gosub six
if ndig=7 then gosub seven
if ndig=8 then gosub eight
if ndig=9 then gosub nine
return

Zero:
LCDOUT \$FE,\$80+nPos,1
LCDOUT \$FE,\$C0+nPos,5
return

One:
LCDOUT \$FE,\$80+nPos,0
LCDOUT \$FE,\$C0+nPos,0
return

Two:
LCDOUT \$FE,\$80+nPos,7
LCDOUT \$FE,\$C0+nPos,2
return

Three:
LCDOUT \$FE,\$80+nPos,6
LCDOUT \$FE,\$C0+nPos,3
return

Four:
LCDOUT \$FE,\$80+nPos,5
LCDOUT \$FE,\$C0+nPos,0
return

Five:
LCDOUT \$FE,\$80+nPos,2
LCDOUT \$FE,\$C0+nPos,3
return

Six:
LCDOUT \$FE,\$80+nPos,2
LCDOUT \$FE,\$C0+nPos,5
return

Seven:
LCDOUT \$FE,\$80+nPos,7
LCDOUT \$FE,\$C0+nPos,0
return

Eight:
LCDOUT \$FE,\$80+nPos,4
LCDOUT \$FE,\$C0+nPos,5
return

Nine:
LCDOUT \$FE,\$80+nPos,4
LCDOUT \$FE,\$C0+nPos,3
return

colon:
lcdout \$fe,\$80+nPos,\$A5
lcdout \$FE,\$C0+nPos,\$2E
return```
Last edited by tasmod; - 2nd April 2014 at 12:12.

25. ## Re: How do I discern Maidenhead Locator from GPS lat long info.

WooHoo!! That's Beeeeauuuutiful Rob!

I'm so glad to see it working.

I do have some suggestions for you about the configs, Months, volts ...

P.S. Nice picture of yourself too.

26. ## Re: How do I discern Maidenhead Locator from GPS lat long info.

Glad you like it Darrel. I'm very pleased with it. Any ideas very welcome.

I have also coded a full digit clock over the four lines. At the moment it's a standalone code due to the character loading. Is it possible to load the second set of characters, replacing the original, on a button push ? Maybe using EXT ?

The idea was to have dual display, button push changes from that shown in pic to a full clock and back again on another push.

Last edited by tasmod; - 2nd April 2014 at 20:55.

27. ## Re: How do I discern Maidenhead Locator from GPS lat long info.

Yes, you can have as many custom character sets as you want.
But only one set can be loaded at a time.

In your last code, the configs you have aren't doing anything.
They should look like this ... make sure the defaults are commented out in the 16F876A.inc file in your PBP folder.
Code:
`@  __config  _HS_OSC & _WDT_ON & _PWRTE_ON & _BODEN_OFF & _LVP_OFF & _CPD_OFF & _WRT_OFF & _DEBUG_OFF & _CP_OFF`
And how's this look for the Months ...
Code:
```DateTime:
LCDOut \$fe,\$80,DEC2 d," "
GOSUB ShowMonth
LCDOut " ",DEC2 y,"  ",DEC2 hh,":",DEC2 mm,":",DEC2 ss
RETURN

ShowMonth:
Idx = (m - 1) * 3
FOR X = Idx TO Idx + 2
LOOKUP X,["JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC"],Char
LCDOUT Char
NEXT X
RETURN```

28. ## Re: How do I discern Maidenhead Locator from GPS lat long info.

Hmm, I've always had problems with configs.

A single line config errors out. Multiple lines actually works and sets my programmer fuses OK.

I also have severe problems with Mpasmwin 5.20 giving hundreds of errors with PBP which I now just ignore.

I like the Months code. That's one of the things I just couldn't get right but I was thinking that way.

The brain is full of different ideas for the project, so many options. Even thought of two lcds.

29. Originally Posted by tasmod
A single line config errors out. Multiple lines actually works and sets my programmer fuses OK.
Code:
```@__config_HS_OSC
@__config_BOD_OFF
@__config_PWRT_ON
@__config_WDT_ON
@__config_PROTECT_OFF
@__config_LVP_OFF```
Those lines are not configuration statements.
They are actually assembly language labels. You could use an asm GOTO to jump to any one of them.
They will not set the configuration bits in your programmer.

If the one line __config I gave you gives an error, it's probably the "Overwriting address 2007" error that means you didn't comment the default configs in the .inc file.

I also have severe problems with Mpasmwin 5.20 giving hundreds of errors with PBP which I now just ignore.
You should track down every error and fix it.
How would you know if there are real errors if you always just ignore them.
If you don't know what they mean ... get help.

Code:
```LCDOUT  \$FE,\$40,\$03,\$03,\$03,\$03,\$03,\$03,\$03,\$03  ' Cust Char #0
'LCDOUT  \$FE,\$40,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02  ' Cust Char #0
LCDOUT  \$FE,\$48,\$1F,\$1F,\$1B,\$1B,\$1B,\$1B,\$1B,\$1B  ' Cust Char #1
LCDOUT  \$FE,\$50,\$1F,\$1F,\$18,\$18,\$18,\$18,\$1F,\$1F  ' Cust Char #2
LCDOUT  \$FE,\$58,\$03,\$03,\$03,\$03,\$03,\$03,\$1F,\$1F  ' Cust Char #3
LCDOUT  \$FE,\$60,\$1F,\$1F,\$1B,\$1B,\$1B,\$1B,\$1F,\$1F  ' Cust Char #4
LCDOUT  \$FE,\$68,\$1B,\$1B,\$1B,\$1B,\$1B,\$1B,\$1F,\$1F  ' Cust Char #5
LCDOUT  \$FE,\$70,\$1F,\$1F,\$03,\$03,\$03,\$03,\$1F,\$1F  ' Cust Char #6
LCDOUT  \$FE,\$78,\$1F,\$1F,\$03,\$03,\$03,\$03,\$03,\$03  ' Cust Char #7
LCDOUT  \$FE,\$40,\$03,\$03,\$03,\$03,\$03,\$03,\$03,\$03  ' Cust Char #8```
You'll have another set of similar lines for your 4-line big digits.
Executing those lines will overwrite the customs characters you previously loaded.

However, you can only have 8 custom characters at a time, and you have 9 listed above.
The one commented as Cust Char #8, is actually Cust Char #0 and will overwrite the first Cust Char #0. Good thing they're the same.

30. ## Re: How do I discern Maidenhead Locator from GPS lat long info.

Hi Darrel,

The code I posted was the last working example on this PC connected to the net. The actual programming pc is in another room and not net connected (deliberately). There were a couple of errors, the second \$40 character set was one and a missing RETURN was another.
The Month routine was deliberately moved down from the GPS loop. Since the post I moved it into the loop and reformatted the display lines to suit the new layout. I will however look at the array solution now.

I've always had problems with Mpasmwin and errors. For instance the code posted has 891 errors at assembly, all of which relate to standard PBP instructions. e.g. LCDOUT alone is an error, FOR is an error etc. etc.

This is a sample around your Locator code :-
Error[122] C:\FPOINT\NMEA16F876ABIG.ASM 1049 : Illegal opcode (_LatDir)
Warning[207] C:\FPOINT\NMEA16F876ABIG.ASM 1052 : Found label after column 1. (GOSUB?L)
Error[122] C:\FPOINT\NMEA16F876ABIG.ASM 1052 : Illegal opcode (_AtoB)
Warning[207] C:\FPOINT\NMEA16F876ABIG.ASM 1058 : Found label after column 1. (GOSUB?L)
Error[122] C:\FPOINT\NMEA16F876ABIG.ASM 1058 : Illegal opcode (_itofa)
Warning[207] C:\FPOINT\NMEA16F876ABIG.ASM 1061 : Found label after column 1. (GOSUB?L)
Error[122] C:\FPOINT\NMEA16F876ABIG.ASM 1061 : Illegal opcode (_fpsub)
Warning[207] C:\FPOINT\NMEA16F876ABIG.ASM 1064 : Found label after column 1. (LABEL?L)
Error[122] C:\FPOINT\NMEA16F876ABIG.ASM 1064 : Illegal opcode (L00042)
Warning[207] C:\FPOINT\NMEA16F876ABIG.ASM 1070 : Found label after column 1. (GOSUB?L)
Error[122] C:\FPOINT\NMEA16F876ABIG.ASM 1070 : Illegal opcode (_itofb)
Warning[207] C:\FPOINT\NMEA16F876ABIG.ASM 1073 : Found label after column 1. (GOSUB?L)
Error[122] C:\FPOINT\NMEA16F876ABIG.ASM 1073 : Illegal opcode (_fpadd)
Warning[207] C:\FPOINT\NMEA16F876ABIG.ASM 1076 : Found label after column 1. (GOSUB?L)
Error[122] C:\FPOINT\NMEA16F876ABIG.ASM 1076 : Illegal opcode (_SaveLon)
Warning[207] C:\FPOINT\NMEA16F876ABIG.ASM 1082 : Found label after column 1. (GOSUB?L)
Error[122] C:\FPOINT\NMEA16F876ABIG.ASM 1082 : Illegal opcode (_itofb)
Warning[207] C:\FPOINT\NMEA16F876ABIG.ASM 1085 : Found label after column 1. (GOSUB?L)
Error[122] C:\FPOINT\NMEA16F876ABIG.ASM 1085 : Illegal opcode (_fpdiv)
Warning[207] C:\FPOINT\NMEA16F876ABIG.ASM 1088 : Found label after column 1. (GOSUB?L)
Error[122] C:\FPOINT\NMEA16F876ABIG.ASM 1088 : Illegal opcode (_SaveAARG)
Warning[207] C:\FPOINT\NMEA16F876ABIG.ASM 1091 : Found label after column 1. (GOSUB?L)
Error[122] C:\FPOINT\NMEA16F876ABIG.ASM 1091 : Illegal opcode (_ftoia)
Warning[207] C:\FPOINT\NMEA16F876ABIG.ASM 1094 : Found label after column 1. (ADD?CWB)
Error[108] C:\FPOINT\NMEA16F876ABIG.ASM 1094 : Illegal character (0)
I will re-install 5.20 and see if it cures it. I'm sure years back I didn't have the problem.

31. ## Re: How do I discern Maidenhead Locator from GPS lat long info.

SOLVED. Wrong MPASM Suite.

I'm using PBP2.50 and at some point I must have upgraded the MPASM Suite to 8.90.
I needed to delete and re-install 8.15 instead.

I now get a complete compile and assemble without any errors.

Just needed to think quietly about the problem.

32. ## Re: How do I discern Maidenhead Locator from GPS lat long info.

Darrel,

I tried incorporating your Month code but it causes odd errors in the ShowMonth, based on the FOR/NEXT loop and especially the idx. This is maybe where I placed it in the code but I will continue to try it.

Right now I have completed the code using the long Month code and I'm able to toggle back and forth between all info onscreen and the fullscreen big digit clock.

Code:
```;
;
; 			        PIC16F876a
;                          __________
;                          !MCLR |1        28| RB7------D7
;     PLL Volt--AN0---RA0 |2        27| RB6------D6
;         Temp--AN1---RA1 |3        26| RB5------D5
;                    AN2---RA2 |4        25| RB4------D4
;                    AN3---RA3 |5        24| RB3------LCD E
;           NMEA data---RA4 |6        23| RB2------LCD RS
;                    AN4---RA5 |7        22| RB1------
;                Ground---Vss |8        21| RB0------
;                OSC1---XTAL |9        20| VDD------ +5 V
;                OSC2---XTAL |10       19| Vss------Ground
;                         ---RC0 |11       18| RC7------
;                         ---RC1 |12       17| RC6------
;                         ---RC2 |13       16| RC5------
;              pbutton---RC3 |14       15| RC4------
;                          ----------
;
;
;====================================================================='
' Program to display returned value of a GPS on RA4
' LCD in 4-BIT mode PIC16F876a controller 4Mhz clock Fuse PWRT BODEN
'
'GPS sentence: \$GPRMC,192144.62,A,5041.6058,N,00412.6124,E,0.45,3 57.74,081205,,*0B

@  __config  _HS_OSC & _WDT_ON & _PWRTE_ON & _BODEN_OFF & _LVP_OFF & _CPD_OFF & _WRT_OFF & _DEBUG_OFF & _CP_OFF

;-- Place a copy of these variables in your Main program -------------------
;--   The compiler will tell you which lines to un-comment                --
;--   Do Not un-comment these lines                                       --
;---------------------------------------------------------------------------
;wsave   VAR BYTE    \$20     SYSTEM      ' location for W if in bank0
wsave   VAR BYTE    \$70     SYSTEM      ' alternate save location for W
' if using \$70, comment wsave1-3

' --- IF any of these three lines cause an error ?? ------------------------
'       Comment them out to fix the problem ----
' -- Which variables are needed, depends on the Chip you are using --
'wsave1  VAR BYTE    \$A0     SYSTEM      ' location for W if in bank1
'wsave2  VAR BYTE    \$120    SYSTEM      ' location for W if in bank2
;wsave3  VAR BYTE    \$1A0    SYSTEM      ' location for W if in bank3
' --------------------------------------------------------------------------

INCLUDE "FP20.bas"     ; 24-bit Floating Point for 14-bit cores with RAM at \$20

Define LCD_DREG PORTB          ' Port for LCD Data
Define LCD_DBIT 4              ' Set LCD starting data bit
Define LCD_RSREG PORTB         ' Port for RegisterSelect (RS) bit
Define LCD_RSBIT 2             ' Port Pin for RS bit  (pin9)
Define LCD_EREG PORTB          ' Port for Enable (E) bit
Define LCD_EBIT 3              ' Port Pin for E bit    (pin7)
Define LCB_BITS 4              ' Using 4-bit bus

Define LCD_COMMANDUS 1500      ' Command Delay (uS)
define LCD_DATAUS 50           ' Data Delay (uS)

DEFINE OSC 4

OPTION_REG.7=0                 ' Enable Pull-Up's
GPSin VAR PORTA.4
Pbutton VAR PORTC.3

ADCON1 = %10000100 ' Set PORTA analog and RIGHT justify result
ADCON0 = %01000001 ' Configure and turn on A/D Module channel 0 Fosc 8
PAUSE 500

'Declare variables
val VAR WORD      ' final calculated adc valuesWORD' final calculated adc values
volt VAR WORD     ' scaled value real part
voltd1 VAR WORD   ' scaled value first decimal place
voltd2 VAR WORD   ' scaled value second decimal place
i var byte        ' counter

'Allocate Variables for GPS:
TimeOut CON 2000

hh VAR BYTE             'hours
mm VAR BYTE             'minutes
ss VAR BYTE             'seconds
knots VAR WORD          'speed in knots (units)
knotsten VAR BYTE       'speed in knots (tens)
latdeg VAR BYTE         'degrees latitude
latmin VAR BYTE         'minutes latitude
latsecs VAR BYTE        'seconds latitude
NS VAR BYTE             'north or south
londeg VAR BYTE         'degrees longitude
lonmin VAR BYTE         'minutes longitude
lonsecs VAR BYTE        'seconds longtitude
EW VAR BYTE             'east or west
d VAR BYTE              'day
m VAR BYTE              'month
y VAR BYTE              'year
butt VAR BYTE           'pushbutton variable
marker VAR BYTE         'toggle marker

MH     VAR BYTE[6]

LonMinDec VAR BYTE
LonDir    VAR BYTE

LatMinDec VAR BYTE
LatDir    VAR BYTE

nPos  var byte
nDig  var byte

fix VAR WORD 'GPS fix

LCDOut \$fe,\$80,"    GPS Decoder     "
LCDOut \$FE,\$c0," G8VLQ  March 2014  "
Pause 3000
LCDOut \$FE, 1           'Clear Screen

butt = 0
marker = 0

SerIn2 GPSin,188,Timeout,Clock,[wait("\$GPRMC"),wait(","),DEC2 hh,DEC2 mm,DEC2 ss,wait(","),fix,wait(",")_
,DEC2 latdeg,DEC2 latmin,wait("."),DEC2 latsecs,wait(","),NS,wait(","),DEC3 londeg,DEC2 lonmin,wait("."),DEC2 lonsecs,_
wait(","),EW,wait(","),knots,wait("."),DEC2 knotsten,wait(","),DEC3 course,wait(","),DEC2 d,DEC2 m,DEC2 y]

IF marker = 1 THEN BigClock

LonMinDec = lonmin
LatMinDec = latmin
LonDir = EW
LatDir = NS

BUTTON Pbutton,0,100,0,butt,1,BigClockClear

If m = 01 then gosub January          ; show month
If m = 02 then gosub February
If m = 03 then gosub March
If m = 04 then gosub April
If m = 05 then gosub May
If m = 06 then gosub June
If m = 07 then gosub July
If m = 08 then gosub August
If m = 09 then gosub September
If m = 10 then gosub October
If m = 11 then gosub November
If m = 12 then gosub December

gosub PLL         ;pll control voltage
GOSUB Clock       ;Large digit clock
goto GPS          ; ##########################################################################################

;-------------------------------------------------------------

PLL:
Val = 0                       ' Value returned is the average of 5 conversions
For i = 0 TO 4
ADCON0.2 = 1                  ' Start conversion
NotDone:
pause 1
IF ADCON0.2 = 1 Then NotDone
nEXT I
VAL = VAL/5
' Calculate Voltage to 2 decimal places
volt = val * 5/1024
voltd1 = ( val * 5//1024) * 10/1024
Voltd2 = ((val *5 //1024) * 10//1024) * 10/1024
RETURN

;---------------------------------------------

Locator:
;----[convert Longitude Sexagesimal to Decimal Degrees]-------------------------
Aint = LonMinDec : GOSUB ItoFA    ; decimal portion of Minutes
Bint = 100 : GOSUB ItoFB          ; divided by 100
GOSUB fpdiv
Bint = LonMin : GOSUB ItoFB       ; add whole portion of Minutes
Bint = 60 : GOSUB ItoFB           ; divide by 60
GOSUB fpdiv
Bint = LonDeg : GOSUB ItoFB       ; add degrees
IF LonDir = "W" THEN              ; if west of Prime Meridian
GOSUB AtoB
Aint = 0    : GOSUB ItoFA     ; subtract from 0 to negate
GOSUB fpsub
ENDIF

Bint = 180  : GOSUB ItoFB         ; add 180

;----[Have Longitude in AARG as Float]------------------------------------------
GOSUB SaveLon                     ; save Longitude for later
Bint = 20   : GOSUB ItoFB         ; Lon / 20
GOSUB fpdiv
GOSUB SaveAARG                    ; save AARG for modulus
GOSUB FtoIA                       ; get integer
MH(0) = "A" + Aint                ; + "A" = First character

; -- do  Lon // 20 --- (modulus)
Bint = Aint                       ; copy integer result to BARG
GOSUB ItoFB                       ; convert it to float
GOSUB RestoreAARG                 ; restore Lon / 20 to AARG
GOSUB fpsub                       ; subtract integer
Bint = 20                         ; multiply times original divisor (20)
GOSUB ItoFB
GOSUB fpmul                       ; AARG now contains the modulus

Bint = 2    : GOSUB ItoFB         ; divide modulus by 2
GOSUB fpdiv
GOSUB FtoIA                       ; get integer
MH(2) = "0" + Aint                ; + "0" = Third character

GOSUB RestoreLon                  ; restore Longitude
Bint = 2 : GOSUB ItoFB
GOSUB fpdiv                       ; divide by 2

GOSUB FtoIA                       ; get integer
Bint = Aint * 2  : GOSUB ItoFB    ; put int * 2 in BARG, change back to float
GOSUB RestoreLon                  ; restore original Longitude
GOSUB fpsub                       ; subtract A - B

Bint = 12 : GOSUB ItoFB           ; Multiply * 12
GOSUB fpmul
GOSUB FtoIA                       ; get integer

MH(4) = "a" + Aint                ; + "a" = Fifth Character

;----[convert Latitude Sexagesimal to Decimal Degrees]--------------------------
Aint = LatMinDec : GOSUB ItoFA    ; decimal portion of Minutes
Bint = 100 : GOSUB ItoFB          ; divided by 100
GOSUB fpdiv
Bint = LatMin : GOSUB ItoFB       ; add whole portion of Minutes
Bint = 60 : GOSUB ItoFB           ; divide by 60
GOSUB fpdiv
Bint = LatDeg : GOSUB ItoFB       ; add degrees
IF LatDir = "S" THEN              ; if south of equator
GOSUB AtoB
Aint = 0    : GOSUB ItoFA     ; subtract from 0 to negate
GOSUB fpsub
ENDIF

Bint = 90  : GOSUB ItoFB          ; add 90

;----[Have Latitude  in AARG as Float]------------------------------------------
GOSUB SaveLon                     ; save Latitude for later
Bint = 10   : GOSUB ItoFB         ; Lat / 10
GOSUB fpdiv
GOSUB SaveAARG                    ; save AARG for modulus
GOSUB FtoIA
MH(1) = "A" + Aint                ; + "A" = Second character

; -- do  Lat // 10 --- (modulus)
Bint = Aint                       ; copy integer result to BARG
GOSUB ItoFB                       ; convert it to float
GOSUB RestoreAARG                 ; restore Lat / 10 to AARG
GOSUB fpsub                       ; subtract integer
Bint = 10                         ; multiply times original divisor (10)
GOSUB ItoFB
GOSUB fpmul                       ; AARG now contains the modulus

GOSUB FtoIA
MH(3) = "0" + Aint                ; + "0" = Fourth character

GOSUB RestoreLon                  ; restore original Latitude
GOSUB FtoIA                       ; get integer
Bint = Aint : GOSUB ItoFB         ; put int in BARG, change back to float
GOSUB RestoreLon                  ; restore original Latitude
GOSUB fpsub                       ; subtract A - B

Bint = 24 : GOSUB ItoFB           ; Multiply * 24
GOSUB fpmul
GOSUB FtoIA                       ; get integer

MH(5) = "a" + Aint                ; + "a" = Sixth character

RETURN
;-------------------------------------------------------------------------------
Aexp_Copy    VAR BYTE
AARGB0_Copy  VAR BYTE
AARGB1_Copy  VAR BYTE
AARGB2_Copy  VAR BYTE

Aexp_Lon     VAR BYTE
AARGB0_Lon   VAR BYTE
AARGB1_Lon   VAR BYTE
AARGB2_Lon   VAR BYTE

SaveAARG:
Aexp_Copy = Aexp
AARGB0_Copy = AARGB0
AARGB1_Copy = AARGB1
AARGB2_Copy = AARGB2
RETURN

RestoreAARG:
Aexp = Aexp_Copy
AARGB0 = AARGB0_Copy
AARGB1 = AARGB1_Copy
AARGB2 = AARGB2_Copy
RETURN

AtoB:
Bexp = Aexp
BARGB0 = AARGB0
BARGB1 = AARGB1
BARGB2 = AARGB2
RETURN

SaveLon:
Aexp_Lon = Aexp
AARGB0_Lon = AARGB0
AARGB1_Lon = AARGB1
AARGB2_Lon = AARGB2
RETURN

RestoreLon:
Aexp = Aexp_Lon
AARGB0 = AARGB0_Lon
AARGB1 = AARGB1_Lon
AARGB2 = AARGB2_Lon
RETURN
;---------------------------------------

January:
LCDOut \$fe,\$80+9,DEC2 d," Jan ","20",DEC2 y
RETURN

February:
LCDOut \$fe,\$80+9,DEC2 d," Feb ","20",DEC2 y
RETURN

March:
LCDOut \$fe,\$80+9,DEC2 d," Mar ","20",DEC2 y
RETURN

April:
LCDOut \$fe,\$80+9,DEC2 d," Apr ","20",DEC2 y
RETURN

May:
LCDOut \$fe,\$80+9,DEC2 d," May ","20",DEC2 y
RETURN

June:
LCDOut \$fe,\$80+9,DEC2 d," Jun ","20",DEC2 y
RETURN

July:
LCDOut \$fe,\$80+9,DEC2 d," Jul ","20",DEC2 y
RETURN

August:
LCDOut \$fe,\$80+9,DEC2 d," Aug ","20",DEC2 y
RETURN

September:
LCDOut \$fe,\$80+9,DEC2 d," Sep ","20",DEC2 y
RETURN

October:
LCDOut \$fe,\$80+9,DEC2 d," Oct ","20",DEC2 y
RETURN

November:
LCDOut \$fe,\$80+9,DEC2 d," Nov ","20",DEC2 y
RETURN

December:
LCDOut \$fe,\$80+9,DEC2 d," Dec ","20",DEC2 y
RETURN

;--------------------------------------------------------------------------
ClockClear:

LCDOut \$FE, 1           'Clear Screen
marker = 0
GOTO GPS

Clock:
;Display time

'Set up the digits (http://www.darreltaylor.com/files/CustChar.htm)
LCDOUT  \$FE,\$40,\$03,\$03,\$03,\$03,\$03,\$03,\$03,\$03  ' Cust Char #0
LCDOUT  \$FE,\$48,\$1F,\$1F,\$1B,\$1B,\$1B,\$1B,\$1B,\$1B  ' Cust Char #1
LCDOUT  \$FE,\$50,\$1F,\$1F,\$18,\$18,\$18,\$18,\$1F,\$1F  ' Cust Char #2
LCDOUT  \$FE,\$58,\$03,\$03,\$03,\$03,\$03,\$03,\$1F,\$1F  ' Cust Char #3
LCDOUT  \$FE,\$60,\$1F,\$1F,\$1B,\$1B,\$1B,\$1B,\$1F,\$1F  ' Cust Char #4
LCDOUT  \$FE,\$68,\$1B,\$1B,\$1B,\$1B,\$1B,\$1B,\$1F,\$1F  ' Cust Char #5
LCDOUT  \$FE,\$70,\$1F,\$1F,\$03,\$03,\$03,\$03,\$1F,\$1F  ' Cust Char #6
LCDOUT  \$FE,\$78,\$1F,\$1F,\$03,\$03,\$03,\$03,\$03,\$03  ' Cust Char #7

nDig=hh dig 1 : nPos=0 : gosub displaydigit
nDig=hh dig 0 : nPos=1 : gosub displaydigit
npos=2 : gosub colon
ndig=mm dig 1 : npos=3 : gosub displaydigit
ndig=mm dig 0 : npos=4 : gosub displaydigit
npos=5 : gosub colon
ndig=ss dig 1 : npos=6 : gosub displaydigit
ndig=ss dig 0 : npos=7 : gosub displaydigit

LCDOut \$fe,\$c0+9,"    ",#volt, ".", # voltd1,# voltd2,"v"
LCDOUT \$fe,\$94,"   G8VLQ    ",STR MH\6
LCDOut \$fe,\$d4,DEC2 latdeg,\$DF,DEC2 latmin,"'",DEC2 latsecs,NS,"  ",DEC2 londeg,\$DF,DEC2 lonmin,"'",DEC2 lonsecs,EW                           ; ,#volt, ".", # voltd1,# voltd2,"v"   ; d4 4th line

RETURN

displaydigit:
if ndig=0 then gosub zero
if ndig=1 then gosub one
if ndig=2 then gosub two
if ndig=3 then gosub three
if ndig=4 then gosub four
if ndig=5 then gosub five
if ndig=6 then gosub six
if ndig=7 then gosub seven
if ndig=8 then gosub eight
if ndig=9 then gosub nine
return

Zero:
LCDOUT \$FE,\$80+nPos,1
LCDOUT \$FE,\$C0+nPos,5
return

One:
LCDOUT \$FE,\$80+nPos,0
LCDOUT \$FE,\$C0+nPos,0
return

Two:
LCDOUT \$FE,\$80+nPos,7
LCDOUT \$FE,\$C0+nPos,2
return

Three:
LCDOUT \$FE,\$80+nPos,6
LCDOUT \$FE,\$C0+nPos,3
return

Four:
LCDOUT \$FE,\$80+nPos,5
LCDOUT \$FE,\$C0+nPos,0
return

Five:
LCDOUT \$FE,\$80+nPos,2
LCDOUT \$FE,\$C0+nPos,3
return

Six:
LCDOUT \$FE,\$80+nPos,2
LCDOUT \$FE,\$C0+nPos,5
return

Seven:
LCDOUT \$FE,\$80+nPos,7
LCDOUT \$FE,\$C0+nPos,0
return

Eight:
LCDOUT \$FE,\$80+nPos,4
LCDOUT \$FE,\$C0+nPos,5
return

Nine:
LCDOUT \$FE,\$80+nPos,4
LCDOUT \$FE,\$C0+nPos,3
return

colon:
lcdout \$fe,\$80+nPos,\$A5
lcdout \$FE,\$C0+nPos,\$A5
return

;---------------------------------------------------------------------------
BigClockClear:

LCDOut \$FE, 1           'Clear Screen
marker = 1

BigClock:

'Set up the digits (http://www.darreltaylor.com/files/CustChar.htm)
LCDOUT  \$FE,\$40,\$07,\$07,\$07,\$07,\$07,\$07,\$07,\$07  ' Cust Char #0
LCDOUT  \$FE,\$48,\$1C,\$1C,\$1C,\$1C,\$1C,\$1C,\$1C,\$1C  ' Cust Char #1
LCDOUT  \$FE,\$50,\$03,\$07,\$0F,\$1E,\$1C,\$1C,\$1C,\$1C  ' Cust Char #2
LCDOUT  \$FE,\$58,\$18,\$1C,\$1E,\$0F,\$07,\$07,\$07,\$07  ' Cust Char #3
LCDOUT  \$FE,\$60,\$1C,\$1C,\$1C,\$1C,\$1E,\$0F,\$07,\$03  ' Cust Char #4
LCDOUT  \$FE,\$68,\$07,\$07,\$07,\$07,\$0F,\$1E,\$1C,\$18  ' Cust Char #5
LCDOUT  \$FE,\$70,\$1F,\$1F,\$1F,\$00,\$00,\$00,\$00,\$00  ' Cust Char #6
LCDOUT  \$FE,\$78,\$00,\$00,\$00,\$00,\$00,\$1F,\$1F,\$1F  ' Cust Char #7

BUTTON Pbutton,0,100,0,butt,1,ClockClear

;Display time

nDig=hh dig 1 : nPos=0 : gosub displaydigit1
nDig=hh dig 0 : nPos=3 : gosub displaydigit1
npos=6 : gosub colon1
ndig=mm dig 1 : npos=7 : gosub displaydigit1
ndig=mm dig 0 : npos=10 : gosub displaydigit1
npos=13 : gosub colon1
ndig=ss dig 1 : npos=14 : gosub displaydigit1
ndig=ss dig 0 : npos=17 : gosub displaydigit1

GOTO GPS

displaydigit1:
if ndig=0 then gosub Zero1
if ndig=1 then gosub One1
if ndig=2 then gosub Two1
if ndig=3 then gosub Three1
if ndig=4 then gosub Four1
if ndig=5 then gosub Five1
if ndig=6 then gosub Six1
if ndig=7 then gosub Seven1
if ndig=8 then gosub Eight1
if ndig=9 then gosub Nine1
RETURN

Zero1:
LCDOUT \$FE,\$80+nPos,2
LCDOUT \$FE,\$81+nPos,3
LCDOUT \$FE,\$C0+nPos,1
LCDOUT \$FE,\$C1+nPos,0
LCDOUT \$FE,\$94+nPos,1
LCDOUT \$FE,\$95+nPos,0
LCDOUT \$FE,\$D4+nPos,4
LCDOUT \$FE,\$D5+nPos,5
RETURN

One1:
LCDOUT \$FE,\$80+nPos," "
LCDOUT \$FE,\$81+nPos,0
LCDOUT \$FE,\$C0+nPos," "
LCDOUT \$FE,\$C1+nPos,0
LCDOUT \$FE,\$94+nPos," "
LCDOUT \$FE,\$95+nPos,0
LCDOUT \$FE,\$D4+nPos," "
LCDOUT \$FE,\$D5+nPos,0
RETURN

Two1:
LCDOUT \$FE,\$80+nPos,6
LCDOUT \$FE,\$81+nPos,3
LCDOUT \$FE,\$C0+nPos,7
LCDOUT \$FE,\$C1+nPos,5
LCDOUT \$FE,\$94+nPos,1
LCDOUT \$FE,\$95+nPos," "
LCDOUT \$FE,\$D4+nPos,4
LCDOUT \$FE,\$D5+nPos,7
RETURN

Three1:
LCDOUT \$FE,\$80+nPos,6
LCDOUT \$FE,\$81+nPos,3
LCDOUT \$FE,\$C0+nPos,7
LCDOUT \$FE,\$C1+nPos,5
LCDOUT \$FE,\$94+nPos," "
LCDOUT \$FE,\$95+nPos,3
LCDOUT \$FE,\$D4+nPos,7
LCDOUT \$FE,\$D5+nPos,5
RETURN

Four1:
LCDOUT \$FE,\$80+nPos,1
LCDOUT \$FE,\$81+nPos," "
LCDOUT \$FE,\$C0+nPos,4
LCDOUT \$FE,\$C1+nPos,7
LCDOUT \$FE,\$94+nPos," "
LCDOUT \$FE,\$95+nPos,1
LCDOUT \$FE,\$D4+nPos," "
LCDOUT \$FE,\$D5+nPos,1
RETURN

Five1:
LCDOUT \$FE,\$80+nPos,2
LCDOUT \$FE,\$81+nPos,6
LCDOUT \$FE,\$C0+nPos,1
LCDOUT \$FE,\$C1+nPos," "
LCDOUT \$FE,\$94+nPos,6
LCDOUT \$FE,\$95+nPos,3
LCDOUT \$FE,\$D4+nPos,7
LCDOUT \$FE,\$D5+nPos,5
RETURN

Six1:
LCDOUT \$FE,\$80+nPos,2
LCDOUT \$FE,\$81+nPos,6
LCDOUT \$FE,\$C0+nPos,1
LCDOUT \$FE,\$C1+nPos," "
LCDOUT \$FE,\$94+nPos,2
LCDOUT \$FE,\$95+nPos,3
LCDOUT \$FE,\$D4+nPos,4
LCDOUT \$FE,\$D5+nPos,5
RETURN

Seven1:
LCDOUT \$FE,\$80+nPos,6
LCDOUT \$FE,\$81+nPos,3
LCDOUT \$FE,\$C0+nPos," "
LCDOUT \$FE,\$C1+nPos,0
LCDOUT \$FE,\$94+nPos," "
LCDOUT \$FE,\$95+nPos,0
LCDOUT \$FE,\$D4+nPos," "
LCDOUT \$FE,\$D5+nPos,0
RETURN

Eight1:
LCDOUT \$FE,\$80+nPos,2
LCDOUT \$FE,\$81+nPos,3
LCDOUT \$FE,\$C0+nPos,4
LCDOUT \$FE,\$C1+nPos,5
LCDOUT \$FE,\$94+nPos,2
LCDOUT \$FE,\$95+nPos,3
LCDOUT \$FE,\$D4+nPos,4
LCDOUT \$FE,\$D5+nPos,5
RETURN

Nine1:
LCDOUT \$FE,\$80+nPos,2
LCDOUT \$FE,\$81+nPos,3
LCDOUT \$FE,\$C0+nPos,4
LCDOUT \$FE,\$C1+nPos,5
LCDOUT \$FE,\$94+nPos," "
LCDOUT \$FE,\$95+nPos,0
LCDOUT \$FE,\$D4+nPos,7
LCDOUT \$FE,\$D5+nPos,5
RETURN

colon1:
LCDOUT \$FE,\$C0+nPos,\$A5
LCDOUT \$FE,\$94+nPos,\$A5
RETURN```
Last edited by tasmod; - 3rd April 2014 at 10:31.

33. ## Re: How do I discern Maidenhead Locator from GPS lat long info.

Forgive me oh codemaster Darrel.

The idiot has been programming again. I am but a lowly code serf with an aged addled brain.......................................I forgot to declare the variables in your Month routine.

34. ## Re: How do I discern Maidenhead Locator from GPS lat long info.

Complete working prototype system

Rockwell GPS Module on right. PLL and TCXO board on left. TCXO is small vertical board top left. Small board at top with all wires is 7805 5v reg board.

Rear of LCD showing piggyback decoder.

Last edited by tasmod; - 3rd April 2014 at 12:04.

35. ## Re: How do I discern Maidenhead Locator from GPS lat long info.

Darrel,

I wondered how difficult it would be to add the final two numerical digits of the locator so that it is the full 8 digit string.

I nearly destroyed the prototype when I took it out in the car to test the locator code. The car voltage meant the regulator board became really hot, I was afraid it would fail.

Thanks,

36. ## Re: How do I discern Maidenhead Locator from GPS lat long info.

The code was based on the pearl script on the Wikipedia page, which only shows how to get 6 digits.

Do you know of somewhere that shows how to get the last two digits?

37. ## Re: How do I discern Maidenhead Locator from GPS lat long info.

Surprisingly I do have it in asm if that helps. I think this is the applicable code after GPS string is parsed. Loc 1 to 8 are the Maidenhead.

I wanted it all in PBP so I could do what I wanted to achieve. The final two are numeric digits. Mine is 03 if that helps re the original code.

Code:
```;'''''''''''''''  Process LONG term '''''''''''''''''''''''''''''''''
bcf     STATUS, C
rrf     LongD           ;Easiest to work with LongD/2 everywhere
btfss   STATUS, C       ;  as Loc works on 2 deg intervals
goto    NoLongMinsUpdate

movlw   LOW(d'6000')    ;Add 1 degree's worth of carry into the
addwf   LongMLo         ;   minutes registers if LongD/2 has a carry
btfsc   STATUS, C
incf    LongMHi
movlw   HIGH(d'6000')   ;LongM in range 0 -  12000
NoLongMinsUpdate            ;LongD' now in range 0 - 90
btfss   NEGLONG
goto    PosLong
comf    LongD
incf    LongD           ;LongD' now in 2's complement +/-90

movf    LongMLo, w      ;Normalise LongM = 12000 - LongM
sublw   LOW(d'12000')
movwf   LongMLo         ;if borrow, C = 0, so increment the subtrahend
btfss   STATUS, C
incf    LongMHi
movf    LongMHi, w
sublw   HIGH(d'12000')
movwf   LongMHi

decf    LongD           ;Correct Degrees

PosLong
movlw   d'90'
addwf   LongD           ;Normalise D' to 0-180
movf    LongD, w
movwf   ALo
clrf    AHi

movlw   d'10'
call    DivMod          ;Mod out in A, Div out in B
movf    BLo, W
movwf   Loc1
movf    ALo, w
movwf   Loc3

rrf     LongMHi         ;Divide by 4 to give range 0 - 2999
rrf     LongMLo
rrf     LongMHi
rrf     LongMLo
movlw   0x3F
andwf   LongMHi

movf    LongMLo, w      ;Mins * 100 / 4  DIV 125
movwf   ALo
movf    LongMHi, w
movwf   AHi
movlw   d'125'
call    DivMod          ;Mod out in A, Div out in B
movf    BLo, w
movwf   Loc5

;Recover  MOD term (scaled 0 - 124) which stays in ALo
clrf    AHi
bcf     STATUS, C
rlf     ALo             ;Scale to 0 - 248
movlw   d'25'
call    DivMod          ;Mod out in A, Div out in B
movf    BLo, w
movwf   Loc7	;Result in LongD, LongMHi, LongMLo , NEGLONG

;'''''''''''''''''''Now DO LAT term , LatD is already in range 0 - 90''''''''''''''''''
btfss   NEGLAT
goto    PosLat
comf    LatD
incf    LatD            ;LatD now in 2's complement +/-90

movf    LatMLo, w       ;Normalise LatM = 6000 - LatM
sublw   LOW(d'6000')
movwf   LatMLo
btfss   STATUS, C       ;if borrow, C = 0, so increment the subtrahend
incf    LatMHi
movf    LatMHi, w
sublw   HIGH(d'6000')
movwf   LatMHi

decf    LatD            ;Correct the degrees

PosLat
movlw   d'90'
movf    LatD, w
movwf   ALo
clrf    AHi

movlw   d'10'
call    DivMod          ;Mod out in A, Div out in B
movf    BLo, W
movwf   Loc2
movf    ALo, w
movwf   Loc4

bcf     STATUS, C
rrf     LatMHi          ;Divide by 2 to give range 0 - 2999
rrf     LatMLo

movf    LatMLo, w       ;Mins * 100 / 2  DIV 125
movwf   ALo
movf    LatMHi, w
movwf   AHi
movlw   d'125'
call    DivMod          ;Mod out in A, Div out in B
movf    BLo, w
movwf   Loc6

;Recover  MOD term (scaled 0 - 124) which stays in ALo
clrf    AHi
bcf     STATUS, C
rlf     ALo             ;Scale to 0 - 248
movlw   d'25'
call    DivMod
movf    BLo, w
movwf   Loc8	;Result in LatD, LatMHi, LatMLo , NEGLAT

ShowLoc
movf    Loc1, W
call    LcdData
movf    Loc2, W
call    LcdData
movf    Loc3, W
call    LcdData
movf    Loc4, W
call    LcdData
movf    Loc5, W
call    LcdData
movf    Loc6, W
call    LcdData
movf    Loc7, W
call    LcdData
movf    Loc8, W
call    LcdData

return```

38. ## Re: How do I discern Maidenhead Locator from GPS lat long info.

I have made a separate switchable sub for the Big Digit clock which just uses the h, m, s, part of the gps string called alone.

Pic of result. As near accurate to second as code allows.

Last edited by tasmod; - 15th April 2014 at 20:15.

39. ## Re: How do I discern Maidenhead Locator from GPS lat long info.

Darrel,

I found this regarding the 4th pair.

THIRD PAIR (aa-xx)
Each field can be further divided into (24) 5 minutes (0.083333 degrees) longitudinal
by (24) 2.5 minute (0.0416665 degrees) latitudinal zones.

The first character encodes the longitude and the second encodes the latitude with
letters “a” thru “x” (refer to example 3 below).

Example 3:
Longitude = 0.338038 {Refer to example 2}
= 0.338038 / 0.083333
= 4 remainder 0.004706
= e
(location in 5th zone)
Latitude = 0.664048
= 0.664048 / 0.0416665
= 15 remainder 0.0390505
= p
(location in 16th zone)

FOURTH PAIR (00-99)
Each field can be further subdivided into (10) 30 seconds (0.008333 degrees) longitudinal
by (10) 15 seconds (0.004166) latitudinal zones. The first character encodes the longitude
and the second encodes the latitude with numbers “0” thru “9” (refer to example 4 below).

Example 4:
Longitude = 0.004706 {Refer to example 3}
= 0.004706 / 0.008333
= 0 remainder 0.004706
= 0
(location in 1st zone)
Latitude = 0.0390505 {Refer to example 3}
= 0.0390505 / 0.004166
= 9 remainder 0.001556
= 9
(location in 10th zone)

40. ## Re: How do I discern Maidenhead Locator from GPS lat long info.

But the routines from the pearl script don't leave the variables in the right state to do the last part.

I'm trying to recreate it in a spreadsheet to see what values the variables should have at that point.
But finding time to look at it is difficult right now.

Just wanted to let you know I'm still working on it.

#### Posting Permissions

• You may not post new threads
• You may not post replies
• You may not post attachments
• You may not edit your posts