' File... HAPB_SCS.BSP ' Author... Earl Foster ' Date... 11112006 ' Modified... 12312007 ' {$STAMP BS2p} ' {$PBASIC 2.5} ' Purpose: Obtain high altitude photos of the Earth. HAPB_SCS stands for ' High Altitude Photographic Balloon Secondary Computer System. This program ' works in conjunction with HAPB_PCS (HAPB_Primary Computer System) but can be a ' stand alone program. ' This program displays GPS information via a LCD screen and provide visual ' indications that the HAPB-PCS is working. It is a very useful program when ' not connected to a PC but provides no value during flight. ' $GPGGA, POS_UTC,LAT,LAT_D,LON,LON_D,FIX,SAT,HDOP,ALT,M,GEO_ALT,M,DGPS,DRS,*CC ' POS_UTC - UTC of position. Hours, minutes and seconds. (hhmmss) ' LAT - Latitude (ddmm.ffff) ' LAT_D - Latitude direction. (N = North, S = South) ' LON - Longitude (dddmm.ffff) ' LON_D - Longitude direction (E = East, W = West) ' FIX - GPS quality indication, 0 = fix not available, 1 = Non-differential, ' 2 = Differential, 6 = Estimated ' SAT - Number of Satellites in use, 00 to 12 ' --- HDOP, ALT, GEO_ALT are variable length ' HDOP - Horizontal diluation of precision, 0.5 to 99.9 ' ALT - Antenna height above'below mean sea level, -9999.9 to 99999.9 meters ' M - constant ' GEO_ALT - Geoidal height, -999.9 to 9999.9 meters ' M - constant ' DGPS - Differential GPS data age, null if FIX <> 2 ' DRS - Differential Reference Station ID, null if FIX <> 2 ' *CC - Checksum #SELECT $STAMP #CASE BS2, BS2E, BS2PE T1200 CON 813 T2400 CON 396 T4800 CON 188 T9600 CON 84 T19K2 CON 32 TMidi CON 12 T38K4 CON 6 #CASE BS2SX, BS2P T1200 CON 2063 T2400 CON 1021 T4800 CON 500 T9600 CON 240 T19K2 CON 110 TMidi CON 60 T38K4 CON 45 #CASE BS2PX T1200 CON 3313 T2400 CON 1646 T4800 CON 813 T9600 CON 396 T19K2 CON 188 TMidi CON 108 T38K4 CON 84 #ENDSELECT PFCAI PIN 14 ' Primary Flight Computer Active Indicator SatAcquired PIN 7 ' Satellite Acquired Indicator LT0 PIN 0 ' External Lights LT1 PIN 1 LT2 PIN 2 LT3 PIN 3 LT4 PIN 4 ' --- LCD Contants TxPin CON 6 PauseShort CON 300 ' animation pauses PauseLong CON 600 ' --- GPS Contants GPSpin CON 8 ' GPS serial input N4800 CON 16884 ' GPS baud rate CST CON 6 ' UTC Central time correction DegSym CON 176 ' degrees symbol for report MinSym CON 39 ' minutes symbol ' --- GPS Variables UTC_HR VAR Byte ' Universal hour field UTC_MN VAR Byte ' Universal minutes field UTC_SC VAR Byte ' Universal seconds field Degrees VAR Byte ' Navigation Degrees Minutes VAR Byte ' Navigation Minutes DMinutes VAR Word ' Navigation Decimal Minutes Altitude VAR Word ' Sea level Height idx VAR Byte ' Index into GPS data in SPRAM Work VAR Word ' Scrap data and numeric conversions fldWidth VAR Nib ' Width of field char VAR Byte ' General purpose byte size variable ' ---Secondary Computer Start HIGH PFCAI ' --- Initialization LCD GOSUB LCDSetup GOSUB LCD_Splash_Screen ProgramSetup: GOSUB Seeking_Satellites SEROUT TxPin, T19K2, [$0c] ' Clear LCD PAUSE 5 ' ---- Main Program Main: SERIN GPSpin, N4800, 4000, No_GPS, [WAIT("GPGGA,"), SPSTR 82] ' Setup link to GPS and process ' Showing captured data will be replaced with storing captured data procedure GOSUB Parse_GPS_Altitude GOSUB Show_Headers SEROUT TxPin, T19K2, [$8A, DEC5 Altitude */ $0348, " Feet"] GOSUB Parse_GPS_Time SELECT UTC_HR CASE >= 12 UTC_HR = UTC_HR - CST CASE ELSE UTC_HR = UTC_HR + CST ENDSELECT SEROUT TxPin, T19K2, [$9E, DEC2 UTC_HR, ":", DEC2 UTC_MN, ":", DEC2 UTC_SC] GOSUB Parse_GPS_Lat ' Show Latitude coordinates in degrees and decimal minutes SEROUT TxPin, T19K2, [$AF, DEC2 Degrees, " ", DEC2 Minutes,".", DEC4 DMinutes, MinSym, " N"] GOSUB Parse_GPS_Long ' Show Longitude coordinates in degrees and decimal minutes SEROUT TxPin, T19K2, [$C2, DEC3 Degrees, " ", DEC2 Minutes, ".", DEC4 DMinutes, MinSym, " W"] ' GOSUB DigitalVideo GOTO Main ' Start over again END ' ---- Subroutines LCDSetup: HIGH TxPin ' Set pin high to be a serial port PAUSE 100 ' Pause for Serial LCD to initialize ' Define custom characters ' $00 = Ballon SEROUT TxPin, T19K2, [$F8,$04,$0E,$1F,$1F,$1F,$0E,$0E,$04] ' $01 = Payload SEROUT TxPin, T19K2, [$F9,$04,$04,$0E,$04,$1F,$1F,$00,$00] ' $02 1st Earth Panel SEROUT TxPin, T19K2, [$FA,$00,$00,$00,$00,$01,$03,$07,$09] ' $03 2nd Earth Panel SEROUT TxPin, T19K2, [$FB,$00,$03,$07,$0F,$1F,$1F,$09,$08] ' $04 3rd Earth Panel SEROUT TxPin, T19K2, [$FC,$0F,$18,$10,$10,$10,$00,$00,$10] ' $05 4th Earth Panel SEROUT TxPin, T19K2, [$FD,$1C,$03,$03,$00,$00,$01,$03,$07] ' $06 5th Earth Panel SEROUT TxPin, T19K2, [$FE,$00,$18,$06,$01,$00,$10,$1C,$1E] ' $07 6th Earth Panel SEROUT TxPin, T19K2, [$FF,$00,$00,$00,$00,$10,$18,$04,$0E] SEROUT TxPin, T19K2, [$16,$0C] PAUSE 5 RETURN LCD_Splash_Screen: PAUSE 20 ' Show the earth rise SEROUT TxPin, T19K2, [$11] PAUSE PauseShort SEROUT TxPin, T19K2, [$BC, $02, $03, $04, $05, $06, $07] ' Step 1 PAUSE PauseLong ' Ballon and payload come out SEROUT TxPin, T19K2, [$BD, $00] ' Balloon drifts into screen Step 2 PAUSE PauseShort SEROUT TxPin, T19K2, [$BD, " "] ' Clear cell Step 3 SEROUT TxPin, T19K2, [$BE, $00] ' Moves over one cell SEROUT TxPin, T19K2, [$BD, $03] ' Put 2nd earth back PAUSE PauseShort SEROUT TxPin, T19K2, [$BE, " "] ' Clear cell Step 4 SEROUT TxPin, T19K2, [$BF, " "] ' Clear cell SEROUT TxPin, T19K2, [$AB, $00] ' Moves over another cell SEROUT TxPin, T19K2, [$BE, $04] ' Put 3rd earth back SEROUT TxPin, T19K2, [$BF, $01] ' Show payload PAUSE PauseShort SEROUT TxPin, T19K2, [$AB, " "] ' Clear cell Step 5 SEROUT TxPin, T19K2, [$BF, " "] ' Clear cell SEROUT TxPin, T19K2, [$BF, $05] ' Put 4th earth back SEROUT TxPin, T19K2, [$98, $00] ' Moves up one cell SEROUT TxPin, T19K2, [$AC, $01] ' Show payload PAUSE PAUSEShort SEROUT TxPin, T19K2, [$98, " "] ' Clear cell Step 6 SEROUT TxPin, T19K2, [$AC, " "] ' Clear cell SEROUT TxPin, T19K2, [$99, $00] ' Moves over another slot SEROUT TxPin, T19K2, [$AD, $01] ' Show payload PAUSE PAUSEShort SEROUT TxPin, T19K2, [$99, " "] ' Clear cell Step 7 SEROUT TxPin, T19K2, [$AD, " "] ' Clear cell SEROUT TxPin, T19K2, [$9A, $00] ' Moves over another cell SEROUT TxPin, T19K2, [$AE, $01] ' Show payload PAUSE PAUSEShort SEROUT TxPin, T19K2, [$9A, " "] ' Clear cell Step 8 SEROUT TxPin, T19K2, [$AE, " "] ' Clear cell SEROUT TxPin, T19K2, [$87, $00] ' Moves over another cell SEROUT TxPin, T19K2, [$9B, $01] ' Show payload PAUSE PauseLong SEROUT TxPin, T19K2, [$8C, "HAPB"] ' Show project Information Step 9 SEROUT TxPin, T19K2, [$9E, "Designed"] ' Step 10 SEROUT TxPin, T19K2, [$B5, "By"] ' Step 11 SEROUT TxPin, T19K2, [$C5, "Earl Foster"] ' Step 12 PAUSE 2000 ' Keep splash screen active for 2 seconds RETURN ' This procedure loops until the a valid position is received ' by the GPRMC "Status" string is obtained. After GPS receives ' an "A" for valid position. Seeking_Satellites: DO SERIN GPSpin, N4800, 3000, No_GPS,[WAIT("GPRMC,"), SKIP 7, STR Char\1] ' Get Status SEROUT TxPin, T19K2, [$0c] ' Clear LCD PAUSE 5 SEROUT TxPin, T19K2, [$80, " Seeking Satellites"] PAUSE 200 SEROUT TxPin, T19K2, [$80, " "] SEROUT TxPin, T19K2, [$94, " Seeking Satellites"] PAUSE 200 SEROUT TxPin, T19K2, [$94, " "] SEROUT TxPin, T19K2, [$A8, " Seeking Satellites"] PAUSE 200 SEROUT TxPin, T19K2, [$A8, " "] SEROUT TxPin, T19K2, [$BC, " Seeking Satellites"] PAUSE 200 LOOP UNTIL Char = "A" SEROUT TxPin, T19K2, [$0c] ' Clear LCD PAUSE 5 SEROUT TxPin, T19K2, [$A8, "Satellites Acquired"] HIGH SatAcquired PAUSE 1000 'SEROUT TxPin, T19K2, [$12] RETURN Show_Headers: SEROUT TxPin, T19K2, [$80, "Altitude: "] SEROUT TxPin, T19K2, [$94, "Time: "] SEROUT TxPin, T19K2, [$A8, "Lat: "] SEROUT TxPin, T19K2, [$BC, "Long:"] RETURN ' No GPS detected, keep searching until found No_GPS: SEROUT TxPin, T19K2, [$0c] ' Clear LCD PAUSE 5 SEROUT TxPin, T19K2, [$80, " No GPS Detected"] PAUSE 2500 GOTO ProgramSetup ' Get the Altitude ' Altitude is a variable length field ' it follows the 8th comma in the GPGGA string ' which has variable length due to HDOP field having a variable field length. ' First Do loop finds the proper index starting point ' for the altitude by knowing that the altitude follows the 8th comma. ' Second Do loop finds the width of the field. Fractional ' meters are not necessary in this project so the loop stops when it finds ' the decimal point. ' Note: fldWidth and Work is used twice to reduce the number of declarations in the program Parse_GPS_Altitude: idx = 0 : fldWidth = 0 DO GET idx, char IF char = "," THEN fldWidth = fldWidth + 1 idx = idx + 1 ELSE idx = idx + 1 ENDIF LOOP UNTIL fldWidth = 8 ' 8th comma found fldWidth = 0 : work = idx ' Reset fldWidth, idx is copied DO GET work, char ' Work is used to continue indexing IF char = "." THEN ' through the string until the period work = work + 1 ' found. As long as there is no period ELSE ' the field width continues to increment fldWidth = fldWidth + 1 work = work + 1 ENDIF LOOP UNTIL char = "." GOSUB String_To_Value Altitude = Work IF Altitude < 1000 THEN TOGGLE LT0 PAUSE 250 TOGGLE LT0 TOGGLE LT1 PAUSE 250 TOGGLE LT1 TOGGLE LT2 PAUSE 250 TOGGLE LT2 TOGGLE LT3 PAUSE 250 TOGGLE LT3 TOGGLE LT4 PAUSE 250 TOGGLE LT4 PAUSE 250 ENDIF RETURN ' Get the Latitude information ' hhmmss,ddmm.ffff,N,dddmm.ffff ' 01234567890123456789012345678 ' numbers above are used for proper index value for fixed fields Parse_GPS_Time: idx = 0 : fldWidth = 2 ' Hours GOSUB String_To_Value UTC_HR = Work idx = 2 : fldWidth = 2 ' Minutes GOSUB String_To_Value UTC_MN = Work idx = 4 : fldWidth = 2 ' Seconds GOSUB String_To_Value UTC_SC = Work RETURN ' Get the latitude ' North and South America are in the Northern Latitude Hemisphere ' therefore it is unnecesary to extract it from the string for ' for this project. Parse_GPS_Lat: idx = 7 : fldWidth = 2 ' Degrees GOSUB String_To_Value Degrees = Work idx = 9 : fldWidth = 2 ' Minutes GOSUB String_To_Value Minutes = Work idx = 12 : fldWidth = 4 ' Decimal Minutes GOSUB String_To_Value DMinutes = Work RETURN ' Get the Longitude information ' North and South America are in the Western Longitude Hemisphere ' therefore it is unnecesary to extract it from the string for ' this project Parse_GPS_Long: idx = 19 : fldWidth = 3 ' Degrees GOSUB String_To_Value Degrees = Work idx = 22 : fldWidth = 2 ' Minutes GOSUB String_To_Value Minutes = Work idx = 25 : fldWidth = 4 ' Decimal Minutes GOSUB String_To_Value DMinutes = Work RETURN ' Convert string data (nnnn) to numeric value ' idx - location of first digit in data ' fldWidth - width of data field (1 to 5) ' Work - returns numeric value of field String_To_Value: Work = 0 IF (fldWidth = 0) OR (fldWidth > 5) THEN String_To_Value_Done Get_Field_Digit: GET idx, char ' get digit from field Work = Work + (char - "0") ' convert, add into value fldWidth = fldWidth - 1 ' decrement field width IF (fldWidth = 0) THEN String_To_Value_Done Work = Work * 10 ' shift result digits left idx = idx + 1 ' point to next digit GOTO Get_Field_Digit String_To_Value_Done: RETURN