pro ulf_read_dat, $
   filepath, $
   datestr, $
   timestr, $
   latstr, $
   latdstr, $
   lonstr, $
   londstr, $
   datacount, $
   data_arr


;open the data file:
dat_fh = 1
openr, dat_fh, filepath, /get_lun ;open the data file

;read the GPS NMEA header
;example:
;$GPRMC,084222,A,7803.6598,N,01337.2191,E,0.000,0.0,310813,2.9,E*78
;RMC          recommended mimimum sentence C
;084222       fix taken at 08:24:22
;A            status: a active; v void
;7803.6598,N  lat - 78 deg. 03.6598' N
;01337.2191,E lon - 13 deg. 37.2191' E
;0.000        speed
;0.0          track angle
;310813       date - 31 of August, 2013
;2.9,E        magnetic variation
;*78          checksum
nmea_string = string('')
readf, dat_fh, nmea_string
point_lun, dat_fh, 0
print, nmea_string
;parse date, time, latitude, longitude from the NMEA string
nmea_chars = strarr(strlen(nmea_string))
for i=0, strlen(nmea_string) - 1 do begin
    nmea_chars(i) = strmid(nmea_string, i, 1)
endfor
delim = where(nmea_chars eq ',')
timestr = strmid(nmea_string, delim(0)+1, 6)
datestr = strmid(nmea_string, delim(8)+1, 6)
year = strmid(datestr, 4, 2)

;subtract 2^10 week (7168 day) rollover uncertainty offset
if year eq '35' then begin
   month = strcompress(fix(strmid(datestr,2,2)), /remove_all)
   day = strcompress(fix(strmid(datestr,0,2)), /remove_all)
   py_str = '/usr/bin/python -c "from datetime import timedelta; from datetime import datetime; d = timedelta(days=-7168); print datetime(2035,'+month+', '+day+') + d"'
   spawn, py_str, date_new
   year_new = strmid(date_new, 2, 2)
   month_new = strmid(date_new, 5, 2)
   day_new = strmid(date_new, 8, 2)
   datestr = day_new+month_new+year_new
endif
if year eq '36' then begin
   month = strcompress(fix(strmid(datestr,2,2)), /remove_all)
   day = strcompress(fix(strmid(datestr,0,2)), /remove_all)
   py_str = '/usr/bin/python -c "from datetime import timedelta; from datetime import datetime; d = timedelta(days=-7168); print datetime(2036,'+month+', '+day+') + d"'
   spawn, py_str, date_new
   year_new = strmid(date_new, 2, 2)
   month_new = strmid(date_new, 5, 2)
   day_new = strmid(date_new, 8, 2)
   datestr = day_new+month_new+year_new
endif
if year eq '37' then begin
   month = strcompress(fix(strmid(datestr,2,2)), /remove_all)
   day = strcompress(fix(strmid(datestr,0,2)), /remove_all)
   py_str = '/usr/bin/python -c "from datetime import timedelta; from datetime import datetime; d = timedelta(days=-7168); print datetime(2037,'+month+', '+day+') + d"'
   spawn, py_str, date_new
   year_new = strmid(date_new, 2, 2)
   month_new = strmid(date_new, 5, 2)
   day_new = strmid(date_new, 8, 2)
   datestr = day_new+month_new+year_new
endif
if year eq '38' then begin
   month = strcompress(fix(strmid(datestr,2,2)), /remove_all)
   day = strcompress(fix(strmid(datestr,0,2)), /remove_all)
   py_str = '/usr/bin/python -c "from datetime import timedelta; from datetime import datetime; d = timedelta(days=-7168); print datetime(2038,'+month+', '+day+') + d"'
   spawn, py_str, date_new
   year_new = strmid(date_new, 2, 2)
   month_new = strmid(date_new, 5, 2)
   day_new = strmid(date_new, 8, 2)
   datestr = day_new+month_new+year_new
endif
if year eq '39' then begin
   month = strcompress(fix(strmid(datestr,2,2)), /remove_all)
   day = strcompress(fix(strmid(datestr,0,2)), /remove_all)
   py_str = '/usr/bin/python -c "from datetime import timedelta; from datetime import datetime; d = timedelta(days=-7168); print datetime(2039,'+month+', '+day+') + d"'
   spawn, py_str, date_new
   year_new = strmid(date_new, 2, 2)
   month_new = strmid(date_new, 5, 2)
   day_new = strmid(date_new, 8, 2)
   datestr = day_new+month_new+year_new
endif
;3 * 2^10 rollover
if year eq '75' then begin
   month = strcompress(fix(strmid(datestr,2,2)), /remove_all)
   day = strcompress(fix(strmid(datestr,0,2)), /remove_all)
   py_str = '/usr/bin/python -c "from datetime import timedelta; from datetime import datetime; d = timedelta(days=-21504); print datetime(2035,'+month+', '+day+') + d"'
   spawn, py_str, date_new
   year_new = strmid(date_new, 2, 2)
   month_new = strmid(date_new, 5, 2)
   day_new = strmid(date_new, 8, 2)
   datestr = day_new+month_new+year_new
endif

;add 2^10 week (7168 day) rollover uncertainty offset
if year eq '98' then begin
   month = strcompress(fix(strmid(datestr,2,2)), /remove_all)
   day = strcompress(fix(strmid(datestr,0,2)), /remove_all)
   py_str = '/usr/bin/python -c "from datetime import timedelta; from datetime import datetime; d = timedelta(days=+7168); print datetime(1998,'+month+', '+day+') + d"'
   spawn, py_str, date_new
   year_new = strmid(date_new, 2, 2)
   month_new = strmid(date_new, 5, 2)
   day_new = strmid(date_new, 8, 2)
   datestr = day_new+month_new+year_new
endif
if year eq '99' then begin
   month = strcompress(fix(strmid(datestr,2,2)), /remove_all)
   day = strcompress(fix(strmid(datestr,0,2)), /remove_all)
   py_str = '/usr/bin/python -c "from datetime import timedelta; from datetime import datetime; d = timedelta(days=+7168); print datetime(1999,'+month+', '+day+') + d"'
   spawn, py_str, date_new
   year_new = strmid(date_new, 2, 2)
   month_new = strmid(date_new, 5, 2)
   day_new = strmid(date_new, 8, 2)
   datestr = day_new+month_new+year_new
endif

if year eq '00' then begin
   month = strcompress(fix(strmid(datestr,2,2)), /remove_all)
   day = strcompress(fix(strmid(datestr,0,2)), /remove_all)
   py_str = '/usr/bin/python -c "from datetime import timedelta; from datetime import datetime; d = timedelta(days=+7168); print datetime(2000,'+month+', '+day+') + d"'
   spawn, py_str, date_new
   year_new = strmid(date_new, 2, 2)
   month_new = strmid(date_new, 5, 2)
   day_new = strmid(date_new, 8, 2)
   datestr = day_new+month_new+year_new
endif

if year eq '02' then begin
   month = strcompress(fix(strmid(datestr,2,2)), /remove_all)
   day = strcompress(fix(strmid(datestr,0,2)), /remove_all)
   py_str = '/usr/bin/python -c "from datetime import timedelta; from datetime import datetime; d = timedelta(days=+7168); print datetime(2002,'+month+', '+day+') + d"'
   spawn, py_str, date_new
   year_new = strmid(date_new, 2, 2)
   month_new = strmid(date_new, 5, 2)
   day_new = strmid(date_new, 8, 2)
   datestr = day_new+month_new+year_new
endif

; Mark added September 9, 2022
if year eq '03' then begin
   month = strcompress(fix(strmid(datestr,2,2)), /remove_all)
   day = strcompress(fix(strmid(datestr,0,2)), /remove_all)
   py_str = '/usr/bin/python -c "from datetime import timedelta; from datetime import datetime; d = timedelta(days=+7168); print datetime(2003,'+month+', '+day+') + d"'

   spawn, py_str, date_new
   year_new = strmid(date_new, 2, 2)
   month_new = strmid(date_new, 5, 2)
   day_new = strmid(date_new, 8, 2)
   datestr = day_new+month_new+year_new
endif

print, datestr + ' ' + timestr
latstr = strmid(nmea_string, delim(2)+1, 9)
latdstr = strmid(nmea_string, delim(3)+1, 1)

lonstr = strmid(nmea_string, delim(4)+1, 10)
londstr = strmid(nmea_string, delim(5)+1, 1)

;get the size of the file
status = FSTAT(dat_fh)
filesize = status.size

;the next line associates the variable gps_end as a byte array - in other
;words, ALL of the data are interpreted as bytes at this point. This is done
;in order to locate the CR/LF after the NMEA string.
cr        = bytarr(100) ;the maximum length of NMEA string is 80
gps_end   = assoc(dat_fh, cr)

;next line searches the gps_end array for occurrences of a line feed.
last_gps  = where(gps_end(0) eq 10)

;next line gets the index number of the first occurrence of a line feed.
last_gps  = last_gps(0)

;get the channels and clock divider from the 3 bytes after the end of
;the nmea string
bheader = bytarr(3)
assoc_header = assoc(dat_fh, bheader, last_gps+1)
;find number of channel bits set
header = assoc_header[0]
print, header, format='(3z5)'
num_chan = bit_population(header[0])
if num_chan ne 2 then begin
   print, 'more than 2 channels'
   stop
endif
clock_divider = header[1] * 256 + header[2]
;sample rate in Hz is 10KHz clock / number of channels / clock_divider
sample_rate = 10000 / num_chan / clock_divider

;get the channel count and data count
datacount = (filesize - (last_gps + 4)) / (num_chan * 2)

;The next line associates the variable 'data' as a uintarr. in addition, the
;association is made such that the first integer is located at last_gps+4 bytes
;from the beginning of the file. This comes from Paul's information
bdata     = uintarr(datacount * num_chan)
data      = assoc(dat_fh, bdata, last_gps+4)

;the following assigns the first data array to bx, swapping byte ordering in
;the process.
dbdt      = swap_endian(data[0])

;finally, the 16-bit data are masked to 12 bits, converted to signed integers,
; have the midrange point (2048) subtracted and are scaled.
;dbdt      = (fix((dbdt and (2^12-1))) - 2048)/204.8

;don't forget to close the data file!!!!
free_lun, dat_fh

;at this point, all of the data have been read in, although the various
;channels still need to be extracted. This would be done something like:

x_indices = lindgen(datacount) * 2 ;to get an array of even numbered indices

;then
data_arr  = uintarr(num_chan, datacount)
print, 'datacount: ', datacount
data_arr[0, *] = dbdt[x_indices]
data_arr[1, *] = dbdt[x_indices+1]

gps_sync = ishft((reform(data_arr[0, *]) AND '8000'x), -15)
w_sync = where(gps_sync eq 1, sync_count)

if sync_count ge 2 then begin

   sync_delta = w_sync[1:sync_count-1] - w_sync[0:sync_count-2]
   w_no_sync = where(sync_delta ne 10, no_sync_count)
   if no_sync_count gt 0 then print, max(sync_delta)

endif else begin

   print, 'no sync?'

endelse

end