'********************************************************************
'* GPS Coordinate display on LCD
'* uP: AT89S8313
'* Language: BASCOM-AVR 1.11.7.4
'* Date: 2005.Jan.22
'* Version: V2.00
'* Author: Brett England
'********************************************************************
$regfile = "2313def.dat"
$crystal = 8000000
$baud = 4800
' condition compilation flag
Const Debug = 0
#if Debug
Dim Temp_i As Byte
#endif
Dim Rs232_exit As Byte ' Sec count for RS232 timeout
Dim Read_ok As Bit ' Valid GPS frame found
Dim Data_ok As Bit ' Start of GPS frame
Dim Read_num As Byte ' RS232 character count
Dim S2 As String * 16 ' LCD output buffer
Dim Gps_state As Bit
Dim Gps_date As String * 7 ' DDMMYY + comma
Dim Gps_time As String * 6 ' HHMMSS
Dim Latitude As String * 9
Dim Longitude As String * 10
Dim North_south As Byte ' N/S
Dim East_west As Byte ' E/W
Dim Spin_c As Bit ' Toggles when no data Rx
Dim Temp_j As Byte
Dim Time1_count As Byte ' Second ticker
Dim Time1_store As Byte
Dim Time1_ok As Bit ' Internal timer overflow ind
Dim Eventime As Bit ' Set every other second
Config Lcdpin = Pin , Db4 = Portb.4 , Db5 = Portb.5 , Db6 = Portb.6 , Db7 = Portb.7 , E = Portb.3 , Rs = Portb.2
Config Lcd = 16 * 1 'configure lcd screen
' Once enabled, the timer counts each clock period (or you can select a
' divided down input clock if you prefer). When the timer overflows (65536
' counts) you get an interrupt. With a 8MHz clock, this doesn't work out to
' anything very useful. At 8MHz, each clock pulse is 125nS and 65536 of them
' is 8.192 milliseconds.
' I want a timer that resolves to 1000mS, so the first step is to divide down
' the input clock . Input clock to divide by 256, so now each clock pulse is
' worth (8.192/256)=32uS.
' The trick is to preload the counter with a value that will cause it to count
' for 1000mS. Each time the counter expires, you can force the new number back
' into the timer register. We need 1/.000032 or 31250 counts. However, the
' counter expires at 65536, so the correct number to preload is 65536-31250 or
' 34285 This way, the timer will count up 31250 counts (1 second) and
' expire.
Const 1000ms = 34285
Config Timer1 = Timer , Prescale = 256
On Timer1 Timer1_int ' Timer Overflow ISR
On Urxc Rec_rs232 ' Serial Rx ISR
Cls
Cursor Off Noblink
Time1_count = 0 : Timer1 = 1000ms : Time1_ok = 0 : Spin_c = 0
Start Timer1
Enable Timer1
Enable Interrupts
' Main Program LOOP
' Screen updates rotate every 2 seconds
' T+1 - Latitude
' T+3 - Longitude
' T+5 - Date/Time
' GPS unit polling occurs at
' T+0,T+2,T+4
Do
If Time1_ok = 1 Then
Read_ok = 0 : Read_num = 0 : Data_ok = 0
Stop Timer1
' Every even second check GPS
If Eventime = 0 Then
Gps_date = "" : Gps_time = "" : Latitude = "" : Longitude = ""
Gps_state = 0
Gosub Rs232_r
Else
' Odd duty cycle tasks (2sec spacing)
If Time1_count = 1 Then
If North_south = 78 Then ' "N" -> 78
S2 = "North "
Else
S2 = "South "
End If
S2 = S2 + Latitude
Elseif Time1_count = 3 Then
If East_west = 69 Then ' "E" -> 69
S2 = "East "
Else
S2 = "West "
End If
S2 = S2 + Longitude
Elseif Time1_count = 5 Then
S2 = Gps_date + " " + Gps_time
End If
End If
' Animate symbol to show activity when no valid GPS data found
If Gps_state = 0 Then
S2 = "No GPS Frame "
If Spin_c = 0 Then
S2 = S2 + "*"
Set Spin_c
Else
S2 = S2 + "+"
Reset Spin_c
End If
End If
Cls
Lcd S2
Reset Time1_ok
Start Timer1
End If
Loop
' Timer interrupt handler
Timer1_int:
Timer1 = 1000ms
Set Time1_ok
Incr Time1_count
Incr Rs232_exit
If Time1_count > 5 Then Time1_count = 0 ' 6sec wrap - 0..5
Eventime = Time1_count.0
Return
' Decode the following string from an Etrex GPS receiver
'$GPRMC,103044,A,5125.5210,N,00012.3645,W,0.0,304.9,290105,2.6,W,A*1E
'12345678901234567890123456789012345678901234567890123456789012345678
' 11111111112222222222333333333344444444445555555555666666666
Rec_rs232:
Incr Read_num
If Udr = 36 Then '"$"-->36
Read_num = 1 : Data_ok = 1 : Temp_j = 0
Elseif Data_ok = 1 Then
Select Case Read_num
Case 6:
If Udr <> 67 Then Data_ok = 0 '"C"-->67
Case 8 To 13:
Gps_time = Gps_time + Chr(udr)
Case 15:
If Udr = 65 Then Gps_state = 1 '"A"-->65
Case 17 To 25:
Latitude = Latitude + Chr(udr)
Case 27:
North_south = Udr ' N/S indicator
Case 29 To 38:
Longitude = Longitude + Chr(udr)
Case 40:
East_west = Udr ' E/W indicator
' The next two parameters after E/W indicator are:
' Speed over ground, Course over ground - They vary dynamically in size.
Case Is > 40:
' Note: The gps_date var will contain the date plus the trailing comma.
' Start on 3rd comma after E/W indicator
If Temp_j = 3 Then Gps_date = Gps_date + Chr(udr)
If Udr = 44 Then Incr Temp_j '","-->44
If Temp_j >= 4 Then Read_ok = 1
End Select
End If
#if Debug
' Display 1st 16 characters after $ (should be a GPS message)
' Note: With this code enabled the interrupt may take too long
' to service URXC and characters can be dropped.
If Data_ok = 1 And Read_num < 17 Then
Locate 1 , Read_num
Lcd Chr(udr)
End If
#endif
Rs232_exit = 0
Return
Rs232_r:
#if Debug
Locate 1 , 1
Lcd "Reading GPS"
#endif
Reset Usr.7
Reset Ucr.7
Enable Urxc
Rs232_exit = 0
' Don't let the RS232 timeout code affect the next task in the main loop.
Time1_store = Time1_count
Start Timer1
Do
' The GPS unit sends data every 2secs, so on the 3rd sec if no data has
' been received then stop waiting.
If Rs232_exit > 2 Then Exit Do
Loop Until Read_ok = 1
Disable Urxc 'disable receive ISR
Stop Timer1
Time1_count = Time1_store
Return