' ========================================================================= ' ' File...... Happy_New_Year.BSP ' Purpose... New Year's Countdown Clock ' Author.... Jon Williams ' E-mail.... jwilliams@parallax.com ' Started... ' Updated... 31 DEC 2003 ' ' {$STAMP BS2p} ' {$PBASIC 2.5} ' ' ========================================================================= ' -----[ Program Description ]--------------------------------------------- ' ' This program takes a data stream from a GPS receiver and uses its time ' (which comes from an automic clock in GPS satellites) and will display ' the hour of the year in countdown form (mm:ss). Output is to a SEETRON ' 4x20 serial LCD. ' ' Prior to the final hour countdown the display alternates between the ' current local time and year. ' ' A Garmin eTrex GPS was used and Garmin text output selected so that the ' GPS clock could be read at one second resolution (not possible when using ' NMEA output at 4800 baud -- there's too much data and readings of any ' given string are two seconds apart). ' ' For details on GPS text input see the November 2003 issue of Nuts & Volts ' ("Stamp Applications") column -- available for download from Parallax. ' -----[ Revision History ]------------------------------------------------ ' -----[ I/O Definitions ]------------------------------------------------- LCD PIN 15 ' serial to 4x20 LCD GPS PIN 14 ' serial in from GPS Speaker PIN 10 ' to Audio Amp AppMod ' -----[ Constants ]------------------------------------------------------- N9600 CON $40F0 Null CON 0 ' null = 1 ms delay CrsrHm CON 1 ' cursor home BigOn CON 2 ' big characters BigOff CON 3 ' -- off NoCrsr CON 4 ' no cursor ULCrsr CON 5 ' underline cursor BlnkCrsr CON 6 ' blinking cursor ClrLcd CON 12 ' clear LCD BLOn CON 14 ' backlight on BLOff CON 15 ' -- off PosCmd CON 16 ' positioning command ClrCol CON 17 ' clear column RtAlign CON 18 ' right align Esc CON 27 EST CON 5 ' Eastern Standard Time CST CON 6 ' Central MST CON 7 ' Mountain PST CON 8 ' Pacific UtcAdj CON 24 - CST ' adjust UTC for Dallas, TX BaseYr CON 2000 ' -----[ Variables ]------------------------------------------------------- idx VAR Byte ' loop counter fldWidth VAR Nib ' width of data field workVal VAR Word ' temp value from parsing char VAR Byte ' character from SPRAM yr VAR Word ' year mo VAR Byte ' month dt VAR Byte ' date hr VAR Byte ' hours mn VAR Byte ' minutes sc VAR Byte ' seconds cdMn VAR Byte ' countdown minutes cdSc VAR Byte ' countdown seconds ' -----[ EEPROM Data ]----------------------------------------------------- ' -----[ Initialization ]-------------------------------------------------- Setup: PAUSE 500 ' let LCD initialize SEROUT LCD, N9600, [BLOn] ' backlight on Get_Base_Year: GOSUB Get_GPS GOSUB Parse_Date IF ((mo = 1) AND (dt = 1)) THEN ' already New Year at UTC! yr = yr + BaseYr - 1 ELSE yr = yr + BaseYr ENDIF ' -----[ Program Code ]---------------------------------------------------- Main: DO ' show clock for 5 seconds DO GOSUB Get_GPS GOSUB Parse_Time GOSUB Localize_Time GOSUB Show_Big_Time LOOP UNTIL ((sc // 5) = 4) ' show current year for 5 seconds DO GOSUB Get_GPS GOSUB Parse_Time GOSUB Localize_Time GOSUB Show_Big_Year LOOP UNTIL ((sc // 5) = 4) LOOP UNTIL (hr = 11) Countdown_Last_Hour: DO GOSUB Get_GPS GOSUB Parse_Time GOSUB Localize_Time cdMn = 59 - mn cdSc = 60 - sc // 60 GOSUB Show_Countdown LOOP UNTIL (hr = 12) ' update new year and show it! yr = yr + 1 GOSUB Show_Big_Year ' At this point the BASIC Stamp could set off fireworks or other ' really cool stuff -- you're on your own for that, though. END ' -----[ Subroutines ]----------------------------------------------------- Get_GPS: SERIN GPS, N9600, 3750, NO_GPS, [WAIT("@"), SPSTR 13] RETURN No_GPS: SEROUT LCD, N9600, [ClrLcd, "No GPS"] PAUSE 3000 SEROUT LCD, N9600, [ClrLcd] GOTO Get_GPS ' Get raw date from GPS string Parse_Date: idx = 0 : fldWidth = 2 ' year (2 digits) GOSUB Parse_Field yr = workVal idx = 2 : fldWidth = 2 ' month (1 - 12) GOSUB Parse_Field mo = workVal idx = 4 : fldWidth = 2 ' date (1 - 31) GOSUB Parse_Field dt = workVal RETURN ' Get raw time (UTC) from GPS string Parse_Time: idx = 6 : fldWidth = 2 ' hours GOSUB Parse_Field hr = workVal idx = 8 : fldWidth = 2 ' minutes GOSUB Parse_Field mn = workVal idx = 10 : fldWidth = 2 ' seconds GOSUB Parse_Field sc = workVal RETURN ' Parses numeric data field from GPS string in ScratchPad ' -- pass digits in field in "fldWidth" (destroyed in use) ' -- value returned in "workVal" Parse_Field: workVal = 0 ' clear return value IF (fldWidth < 6) THEN ' valid fldWidth? DO WHILE (fldWidth > 0) workVal = workVal * 10 ' shift result digits left GET idx, char ' get digit from field workVal = workVal + (char - "0") ' convert, add into value fldWidth = fldWidth - 1 ' decrement field width idx = idx + 1 ' point to next digit LOOP ENDIF RETURN ' Adjust time to location and change to 12 hour format Localize_Time: hr = hr + UtcAdj // 24 ' update for local position hr = hr // 12 ' set to AM/PM format IF (hr = 0) THEN hr = 12 RETURN ' Show year in big digits on LCD Show_Big_Year: SEROUT LCD, N9600, [ClrLcd, PosCmd, 1 + 64] SEROUT LCD, N9600, [BigOn, DEC4 yr, BigOff] RETURN Show_Big_Time: SEROUT LCD, N9600, [ClrLcd] ' seconds SEROUT LCD, N9600, [PosCmd, 11 + 64] SEROUT LCD, N9600, [BigOn, DEC2 mn, BigOff] ' minutes IF (hr < 10) THEN SEROUT LCD, N9600, [PosCmd, 5 + 64] SEROUT LCD, N9600, [BigOn, DEC1 hr, BigOff] ELSE SEROUT LCD, N9600, [CrsrHm] SEROUT LCD, N9600, [BigOn, DEC2 hr, BigOff] ENDIF RETURN ' Show last hour in countdown mode (mm ss) ' -- beep final 10 seconds Show_Countdown: SEROUT LCD, N9600, [ClrLcd] ' seconds SEROUT LCD, N9600, [PosCmd, 11 + 64] SEROUT LCD, N9600, [BigOn, DEC2 cdSc, BigOff] ' minutes SEROUT LCD, N9600, [CrsrHm] IF (cdMn < 10) THEN SEROUT LCD, N9600, [PosCmd, 5 + 64] SEROUT LCD, N9600, [BigOn, DEC1 cdMn, BigOff] ELSE SEROUT LCD, N9600, [BigOn, DEC2 cdMn, BigOff] ENDIF ' beep last 10 seconds ' -- 880 Hz for 0.1 sec IF ((cdMn = 0) AND (cdSc < 11)) THEN FREQOUT Speaker, 390, 234 ENDIF RETURN