' ' ThunderBolt LCD ' ' ' Version 2.3RM, 3 January, 2020 ' ' Written by Adam Maurer VK4GHZ ' ' Purpose: ' ' Read the HEX data packets, sent every second, from a Trimble Thunderbolt GPSDO, and displays data ' on an LCD screen. ' Data packets occupy 200mS. ' There is 800mS available to process the data, (some of which is sent to the uM-FPU 64 co-processor, ' and back) and ultimately display the results on the LCD. ' ' Slot #0 generates the Splash Page ' ' ' Version Author Notes ' --------------- ------- ---------------------------------------------------------------------- ' 0.1 01-10-11 VK4GHZ First attempt with 20X2 ' 0.2 12-10-11 VK4GHZ Upgraded to 28X2 ' 0.21 15-10-11 VK4GHZ Added protection diode, and tweaked ADC calculation to compensate ' for voltage drop across diode. ' 0.30 16-10-11 VK4GHZ Added um-FPU64 symbols ' 0.70 03-11-11 VK4GHZ Added rotary switch to manually select displayed page ' 1.00 19-11-11 VK4GHZ First Release Version ' 1.10 19-07-17 VK4GHZ Added Altitude (MSL) on page 3 ' 2.0 27-07-17 VK4GHZ Added # sats to page 1 ' 2.1 28-07-17 VK4GHZ Slots 0=splash, slot 1=p1 & p2, slot 2=p3, slot 3=p4 ' 2.2 09-08-17 VK4GHZ Date correction for Day of Month and Month after GPS Week 1024 rollover on 30-Jul-2017 ' Week # & TOW are used to translate D, M and Y ' 2.3RM 03-01-20 VK4GHZ Date removed and replaced with abbreviated RX Mode ' '--------------------------------------------------------------------------------------------------------------- ' ' HARDWARE CONNECTIONS ' ____________ ' Rst-|o U |-B.7 LCD D7 ' ADC0 In A.0-| |-B.6 LCD D6 ' Rotary Sw A.1-| |-B.5 LCD D5 ' Rotary Sw A.2-| PICAXE28X2 |-B.4 LCD D4 ' Rotary Sw A.3-| |-B.3 LCD D3 ' SerIn-| |-B.2 LCD D2 ' SerOut-| |-B.1 LCD D1 ' 0V-| |-B.0 LCD D0 ' Res-| |-+V ' Res-| |-0V ' DMS Format C.0-| |-C.7 GPS RS232 ' Critical Alarm LED C.1-| |-C.6 LCD Enable ' Minor Alarm LED C.2-| |-C.5 LCD R/S ' i2C SCL C.3-|____________|-C.4 i2C SDA ' ' '--------------------------------------------------------------------------------------------------------------- ' *** Directives *** #slot 0 ' Specifcy Programing Slot ' #com 13 ' Specify download port #picaxe 28X2 ' Specify processor ' #terminal 19200 ' Open terminal window #terminal off #no_data ' *** Constants *** symbol enable =C.6 ' LCD enable pin connected to C.6 symbol RegSel =C.5 ' LCD RegSel pin connected to C.5 symbol ADCPort =0 ' ADC 0 (Input A.0) to read system volts symbol CAlarmLED =C.1 ' Critical Alarm LED output symbol MAlarmLED =C.2 ' Minor Alarm LED Output symbol GPSIn =C.7 ' RS-232 Serial Input from GPS symbol LatLonFormat=pinC.0 ' symbol newB.0 =outpinB.0 ' Substitute LCD B.0 data to C.7 so B.0 can be used as a Hardware INT ' *** Variables *** symbol char =b0 ' Character to be sent to LCD symbol cmd =b1 ' Command to be sent to LCD symbol index =b2 ' Used as counter in For-Next loops symbol msgpointer =b3 ' Address Pointer to retrieve string for display on LCD symbol strstart =b4 ' Start position for string symbol pageNum =b5 ' String Length symbol pageCount =b6 ' End position for string symbol ADCval =b7 ' ADC HEX value symbol Vin =w4 ' b8 & b9 symbol Temp =b10 ' Temporary Byte ' *** B10 ALSO USED BY uM-FPF64 *** symbol Temp1 =b11 ' Temporary Byte symbol Temp2 =b12 ' Temporary Byte symbol TempWord =w5 symbol Temp3 =b13 ' Temporary Byte symbol Temp4 =b14 ' Temporary Byte symbol SPByte =b15 symbol wordindexL =b16 ' w8 MSB symbol wordindexM =b17 ' w8 LSB symbol wordindex =w8 ' b16 & b17 symbol Timing =b18 symbol Second =b19 ' Also used for firmware version Major byte symbol FirmMajor =b19 ' Also used for Seconds symbol Minute =b20 ' Also used for firmware version Minor byte symbol FirmMinor =b20 ' Also used for Minutes symbol Hour =b21 symbol Day =b22 symbol Month =b23 symbol YearL =b24 ' w12 LSB symbol YearM =b25 ' w12 MSB symbol Year =w12 ' b24 & b25 symbol Page =b26 symbol RMode =b27 symbol DMode =b28 symbol Survey =b29 symbol CAlarmsL =b30 symbol CAlarmsM =b31 symbol CAlarms =w15 ' b30 & b31 symbol MAlarmsL =b32 symbol MAlarmsM =b33 symbol MAlarms =w16 ' b32 & b33 symbol GPSStatus =b34 symbol DActivity =b35 symbol ppbM =b36 symbol ppb3 =b37 symbol ppb2 =b38 symbol ppbL =b39 symbol LatM =b40 symbol Lat7 =b41 symbol Lat6 =b42 symbol Lat5 =b43 symbol Lat4 =b44 symbol Lat3 =b45 symbol Lat2 =b46 symbol LatL =b47 symbol LonM =b48 symbol Lon7 =b49 symbol Lon6 =b50 symbol Lon5 =b51 symbol Lon4 =b52 symbol Lon3 =b53 symbol Lon2 =b54 symbol LonL =b55 '=============================================================================== '-------------------- uM-FPU64 I2C definitions ------------------- 2007-07-11 '=============================================================================== symbol fpuID = 0xC8 ' uM-FPU I2C address ;-------------------- uM-FPU V3 opcode definitions ----------------------------- symbol NOP = 0x00 ' No Operation symbol CLR = 0x03 ' reg[nn] = 0 symbol SELECTA = 0x01 ' Select register A symbol FWRITE = 0x16 ' Write 32-bit float to reg[nn] symbol FWRITEA = 0x17 ' Write 32-bit float to reg[A] symbol FREAD = 0x1A ' Read 32-bit float from reg[nn] symbol FREADA = 0x1B ' Read 32-bit float from reg[A] symbol ATOF = 0x1E ' Convert ASCII to float, store in reg[0] symbol FTOA = 0x1F ' Convert float to ASCII symbol FSET = 0x20 ' reg[A] = reg[nn] symbol FABS = 0x32 ' reg[A] = |reg[A]| symbol FADDI = 0x33 ' reg[A] = reg[A] + float(bb) symbol FMULI = 0x36 ' reg[A] = reg[A] * float(bb) symbol FDIVI = 0x37 ' reg[A] = reg[A] / float(bb) symbol DEGREES = 0x4E ' reg[A] = degrees(reg[A]) symbol FLOOR = 0x51 ' reg[A] = floor(reg[A]) symbol FIX = 0x61 ' symbol FRAC = 0x63 ' reg[A] = fraction(reg[A]) symbol DWRITE = 0x72 ' Write 64-bit register symbol DREAD = 0x73 ' Read 64-bit register symbol LREADBYTE = 0x98 ' Read lower 8 bits of reg[A] symbol SYNC = 0xF0 ' Get synchronization byte symbol READSTATUS = 0xF1 ' Read status byte symbol READSTR = 0xF2 ' Read string from string buffer symbol VERSION = 0xF3 ' Copy version string to string buffer symbol SETREAD = 0xFD ' Set read mode symbol SYNC_CHAR = 0x5C ' sync character symbol LEFT = 0x14 symbol FWRITE0 = 0x19 symbol FSTATUSA = 0x3C symbol FNEG = 0x3E symbol FSUB0 = 0x2B symbol FSPLIT = 0x64 symbol LTOA = 0x9B symbol STRINS = 0xE5 symbol FSET0 = 0x29 symbol RIGHT = 0x15 symbol FMUL = 0x24 symbol SQRT = 0x41 '-------------------- uM-FPU variables ----------------------------------------- symbol dataByte = b10 ' data byte symbol format = b10 ' format (same as dataByte) symbol statusByte = b10 ' status byte (same as dataByte) '-------------------- uM-FPU status bits --------------------------------------- symbol IS_ZERO = 0x81 ' positive zero symbol IS_NZERO = 0x83 ' negative zero symbol IS_NEGATIVE = 0x82 ' negative symbol IS_NAN = 0x84 ' NaN (Not-a-Number) symbol IS_PINF = 0x88 ' positive infinity symbol IS_NINF = 0x8A ' negative infinity '-------------------- uM-FPU register definitions ------------------------------ symbol Regppb = 1 ' uM-FPU64 32-bit Register for ppb FP value symbol RegDAC = 2 ' uM-FPU64 32-bit Register for DAC FP value symbol RegLat = 129 ' uM-FPU64 64-bit Register for Lat 64-bit value symbol RegLon = 130 ' uM-FPU64 64-bit Register for Lon 64-bit value symbol RegLatNew = 131 ' Processed lat value for grid square calculation symbol RegLatDeg = 132 ' symbol RegLatMin = 133 ' symbol RegLatSec = 134 ' symbol RegLatDegRem= 160 ' symbol RegLonNew = 135 ' Processed lon value for grid square calculation symbol RegLonDeg = 136 ' symbol RegLonMin = 137 ' symbol RegLonSec = 138 ' symbol RegGrid1 = 141 ' symbol RegGrid2 = 142 ' symbol RegGrid3N = 143 ' symbol RegGrid3 = 144 ' symbol RegGrid4N = 145 ' symbol RegGrid4 = 146 ' symbol RegGrid5 = 148 ' symbol RegGrid6 = 150 ' ' ********************* Begin Main Program ************************************** dirsA = %00000000 ' Set A0 A1 A2 A3 as inputs dirsB = %11111111 ' Set all as outputs dirsC = %11111110 ' Set C.0 as Input, all others as outputs setfreq m16 start: ' *** Initialize the LCD ********************************************************* pause 200 ' Pause 100 mS for LCD initialization cmd = $38 ' Setup for 8-bits, 2 lines & 5X7 dots gosub outCmd ' Send Command to LCD pause 100 cmd = $0C ' Display on, cursor off gosub outCmd ' Send Command to LCD gosub clearPage ' ' Load Custom Degree Character into LCD CG RAM (add=0) ' cmd = 64 ' Load command byte gosub outCmd pause 1 char=40 gosub outChar char=52 gosub outChar char=40 gosub outChar char=32 gosub outChar char=32 gosub outChar char=32 gosub outChar char=32 gosub outChar char=32 gosub outChar ' Load Custom "p" Character with decender into LCD CG RAM (add=1) ' cmd = 72 ' Load command byte gosub outCmd pause 1 char=32 gosub outChar char=32 gosub outChar char=46 gosub outChar char=49 gosub outChar char=49 gosub outChar char=62 gosub outChar char=48 gosub outChar char=48 gosub outChar ' Load Custom "g" Character with decender into LCD CG RAM (add=2) ' cmd = 80 ' Load command byte gosub outCmd pause 1 char=32 gosub outChar char=32 gosub outChar char=47 gosub outChar char=49 gosub outChar char=49 gosub outChar char=47 gosub outChar char=33 gosub outChar char=46 gosub outChar ' Load Custom "q" Character with decender into LCD CG RAM (add=3) ' cmd = 88 ' Load Command byte gosub outCmd pause 1 char=32 gosub outChar char=32 gosub outChar char=45 gosub outChar char=51 gosub outChar char=49 gosub outChar char=47 gosub outChar char=33 gosub outChar char=33 gosub outChar ' Load Custom "1" Character with underline into LCD CG RAM (add=4) ' cmd = 96 ' Load Command byte gosub outCmd pause 1 char=36 gosub outChar char=44 gosub outChar char=36 gosub outChar char=36 gosub outChar char=36 gosub outChar char=36 gosub outChar char=46 gosub outChar char=63 gosub outChar ' Load Custom "2" Character with underline into LCD CG RAM (add=5) ' cmd = 104 ' Load Command byte gosub outCmd pause 1 char=46 gosub outChar char=49 gosub outChar char=33 gosub outChar char=34 gosub outChar char=36 gosub outChar char=40 gosub outChar char=63 gosub outChar char=63 gosub outChar ' Load Custom "3" Character with underline into LCD CG RAM (add=6) ' cmd = 112 ' Load Command byte gosub outCmd pause 1 char=63 gosub outChar char=34 gosub outChar char=36 gosub outChar char=34 gosub outChar char=33 gosub outChar char=49 gosub outChar char=46 gosub outChar char=63 gosub outChar ' Load Custom "4" Character with underline into LCD CG RAM (add=7) ' cmd = 120 ' Load Command byte gosub outCmd pause 1 char=34 gosub outChar char=38 gosub outChar char=42 gosub outChar char=50 gosub outChar char=63 gosub outChar char=34 gosub outChar char=34 gosub outChar char=63 gosub outChar pause 10 ' *** Initialize uM-FPU64 Co Processor ******************************************* gosub fpu_reset ' Reset the uM-FPU64 gosub clearPage ' '**** Display Splash Page 1 ************************************************************ cmd = $80 ' Goto Line 1 gosub outCmd ' for index = 0 to 19 lookup index,("Thunderbolt Display"),char gosub outChar next index 'char=3 ' Custom "y" (with descender) 'gosub outChar cmd = $C0 ' Goto Line 2 gosub outCmd ' high RegSel for index = 0 to 19 lookup index,("Ver: 2.3RM by "),char gosub outChar next index cmd = $94 ' Goto Line 3 gosub OutCmd ' high RegSel for index = 0 to 19 lookup index,("Adam Maurer VK4GHZ "),outPinsB pulsout enable,1 next index for pageCount=1 to 5 ' Update & Display PSU volts 4 times over 2 seconds gosub PSU pause 1000 ' Pause 500 mS next pageCount gosub clearPage '**** Display Splash Page 2 ************************************************************ cmd = $80 ' Goto Line 1 gosub outCmd ' for index = 0 to 19 lookup index,("Thunderbolt Firmware"),char gosub outChar next index cmd = $C0 ' Goto Line 2 gosub outCmd ' high RegSel for index = 0 to 4 lookup index,("Ver: "),char gosub outChar next index gosub readVer ' Read Firmware Version get 1,Temp ' Get 1st byte received if Temp=$45 then ' If 1st byte = $45 then version info was received get 2,FirmMajor ' Get Firmware version major byte from ScratchPad reg #2 get 3,FirmMinor ' Get Firmware minor byte from ScratchPad reg #3 bintoascii FirmMajor, Temp,Temp1,Temp2 char=Temp2 ' eg: Display units digit "3" gosub outChar char="." ' "." gosub outChar bintoascii FirmMinor, Temp,Temp1,Temp2 char=Temp1 ' eg: Display tens digit "0" gosub outChar char=Temp2 ' eg: Display units digit "0" gosub outChar temp=6 gosub space ' 11 spaces temp=5 gosub space cmd = $D4 ' Goto Line 4 gosub OutCmd ' high RegSel for index = 0 to 19 lookup index,("Initialising "),outPinsB pulsout enable,1 next index pause 8000 else cmd = $C5 ' Goto Line 2 pos 6 gosub OutCmd ' for index = 0 to 14 lookup index,("Not available "),char gosub outChar next index pause 2000 ' Pause 1000 mS cmd=$94 ' Goto Line 3 gosub OutCmd for index = 0 to 19 lookup index,("Power up GPS and "),char gosub outChar next index cmd=$D4 ' Goto Line 4 gosub OutCmd for index = 0 to 19 lookup index,("display at same time"),char gosub outChar next index pause 10000 ' Pause 5000 mS endif gosub clearPage run 1 ' Run Slot #1 for main program ' ************************ End Main Program - Subroutines Follow *********************** '--------------------------------------------------------------------------------------- ' Sends Command to LCD outCmd: low RegSel ' set up for command byte outpinsB = cmd ' load byte onto outpinsB ' newB.0 = bit8 pulsout enable,1 ' send data pause 1 high RegSel return outChar: high RegSel outpinsB = char ' newB.0 = bit0 pulsout enable,1 pause 1 return '--------------------------------------------------------------------------------------- ' Clear Page clearPage: cmd = $01 ' Display Clear gosub outCmd ' return '--------------------------------------------------------------------------------------- ' Space Subroutine space: high RegSel char = " " ' load byte onto outpinsB outpinsB = char ' newB.0 = bit0 on Temp goto space1, space1, space2, space3, space4, space5, space6 space6: pulsout enable,1 ' send data space5: pulsout enable,1 ' send data space4: pulsout enable,1 ' send data space3: pulsout enable,1 ' send data space2: pulsout enable,1 ' send data space1: pulsout enable,1 ' send data return '--------------------------------------------------------------------------------------- ' PSU Voltage PSU: let adcsetup=ADCPort readadc10 ADCPort, Wordindex ' Read ADC port for supply volts Vin=Wordindex*14/10+83 ' With 13.8V input (before diode), ADC Val=207 cmd = $D4 ' Goto Line 4 gosub outCmd ' ' ((207 x 255) / 40) + 67 = for index = 0 to 4 lookup index,("PSU: "),char gosub outChar next index bintoascii Vin, Temp,Temp1,Temp2,Temp3,Temp4 if Temp1 = 49 then ' Only print Volts 10's digit if it's a "1" char=Temp1 gosub outChar endif char=Temp2 ' Volts Units digit gosub outChar char="." ' Decimal Point gosub outChar char=Temp3 ' Volts 100's mV digit gosub outChar char=Temp4 ' Volts 10's mV digit gosub outChar char="V" ' "V" gosub outChar char=" " ' Space gosub outChar ' Display ADC value as a decimal ' gosub Space ' bintoascii Wordindex, Temp,Temp1,Temp2,Temp3,Temp4 ' char = Temp ' pulsout enable,1 ' char = Temp1 ' pulsout enable,1 ' char = Temp2 ' pulsout enable,1 ' char = Temp3 ' pulsout enable,1 ' char = Temp4 ' pulsout enable,1 return '**** Read Thunderbolt Firmware Version ************************************************ ' Read 0x45 Software Version Information ' Commander requests this packet on power up. ' Thunderbolt, Display and Commander must all power up together to see the F/W version number. ' If 0x45 packet has not been received, the display was connected AFTER Thundrbolt was powered up. readVer: ptr=1 ' 1 2 3 serin [8000,noGPS],GPSIn,T9600_16,($10),@ptrinc,@ptrinc,@ptrinc 'serin [8000,resumeSplash2],GPSIn,T9600_16,($10,$45),@ptrinc,@ptrinc,@ptrinc,@ptrinc ' This reads in the raw data, and looks for "$45" ' 2nd and 3rd byte received will be firmware version number return '---- GPS Not Connected Error Page 1 ------------------------------------------------------ noGPS: gosub clearpage cmd=$80 ' Goto Line 1 gosub OutCmd for index = 0 to 19 lookup index,("No Thunderbolt Data "),char gosub outChar next index cmd=$C0 ' Goto Line 2 gosub OutCmd for index = 0 to 19 lookup index,("Config GPS: 9600 8N1"),char gosub outChar next index cmd=$94 ' Goto Line 3 gosub OutCmd for index = 0 to 19 lookup index,("Data: DB9 pin 2 "),char gosub outChar next index cmd=$D4 ' Goto Line 4 gosub OutCmd for index = 0 to 19 lookup index,("GND: DB9 pin 5 "),char gosub outChar next index pause 10000 ' Pause 5 seconds goto start '---- Interrupt Routine ------------------------------------------------------------------- interrupt: return '---- Read results from uM-FPU64 Co-Processor onto LCD ------------------------------------ readumfpu: writei2c 0,(LREADBYTE) readi2c 0, (dataByte) ' char=dataByte ' gosub outChar return '---- Print results from uM-FPU64 Co-Processor onto LCD ------------------------------------ print_lat_lon: writei2c 0,(FTOA,format) gosub fpu_wait writei2c 0,(READSTR) do readi2c 0, (dataByte ) ' display zero terminated string if dataByte = 0 then exit char = dataByte ' gosub outChar loop return '=============================================================================== '-------------------- uM-FPU64 I2C support routines ----------------- 2011-10-17 '=============================================================================== fpu_reset: hi2csetup i2cmaster, fpuID, i2cfast_16, i2cbyte hi2cout 1, (0) ' reset the uM-FPU pause 10 ' wait for reset to complete hi2cout 0, (SYNC) ' check for synchronization goto fpu_readStatus2 fpu_wait: hi2cin 0, (statusByte) ' wait for ready status if statusByte <> 0 then fpu_wait return fpu_readStatus: gosub fpu_wait ' read status byte hi2cout 0, (READSTATUS) fpu_readStatus2: hi2cin 0, (statusByte) ' read status byte return print_version: hi2cout 0, (VERSION) ' get the uM-FPU version string goto print_fpuString ' print it print_float: format = 0 ' set for free format ' (fall through to print_floatFormat) print_floatFormat: hi2cout 0, (FTOA, format) ' convert floating point to formatted ASCII goto print_fpuString ' print the string print_long: format = 0 ' set for free format ' (fall through to print_longFormat) print_longFormat: hi2cout 0, (LTOA, format) ' convert long integer to formatted ASCII ' (fall through to print_fpuString) print_fpuString: hi2cout 0, (SETREAD) gosub fpu_wait ' wait until uM-FPU is ready hi2cout 0, (READSTR) print_string2: hi2cin 0, (dataByte) ' display zero terminated string if dataByte = 0 then Print_String3 if dataByte > 127 then Print_String3 sertxd(dataByte) goto Print_String2 print_string3: return ' end of string '==================== end of uM-FPU64 I2C support routines ====================