#!/bin/sh
#
# see http://aprs.gids.nl/nmea

# DEV=${1:-/dev/ttymxc0}
DEV=${1:-/dev/ttymxc4}
BAUD=${2:-4800} #might need to go to 9600?

[ $VERBOSE ] || VERBOSE=0

#Estimated Moving Avgerage: EMA = EMA * (1 – APLHA) + NEWAVG * ALPHA
#Variables for calculating moving averages: 
#SRN_EMA: EMA for sattellite signal strength
#SAT_EMA: EMA for number of visible sattellites
SRN_AVG=0 #srn_sum / srn_cnt
ALPHA=$(echo ${3:-10} | awk '{alph = 1/$1; print alph}') #default of last 10

echo "Device:$DEV"
echo "Baud  :$BAUD"

stty -F $DEV $BAUD cs8

debug() {
        [ $VERBOSE -ge $1 ] && echo $2
}

# GPS DOP and active satellites
gsa() {
        local i x sats type fix pdop hdop vdop

        #debug 1 "gsa: $1"
        oIFS=${IFS}
        IFS=','
        i=0
        sats=
        for x in $1; do
                case $i in
                        1) type=$x;;
                        2) fix=$x;;
                        3) sats="$sats$x ";;
                        4) sats="$sats$x ";;
                        5) sats="$sats$x ";;
                        6) sats="$sats$x ";;
                        7) sats="$sats$x ";;
                        8) sats="$sats$x ";;
                        9) sats="$sats$x ";;
                        10) sats="$sats$x ";;
                        11) sats="$sats$x ";;
                        12) sats="$sats$x ";;
                        13) sats="$sats$x ";;
                        14) sats="$sats$x ";;
                        15) pdop=$x;;
                        16) hdop=$x;;
                        17) vdop=$x;;
                esac
                i=$((i+1))
        done

        case $type in
                M) type=manual;;
                A) type=automatic;;
        esac
        case $fix in
                2) fix=2;; #2D
                3) fix=3;; #3D
        esac

        [ ${fix} -ne 1 ] && echo "GSA: $fix $type $sats"
        IFS=${oIFS}
}

# Fix data
gga() {
        local i x time lat lon type svs prec alt altm

        #debug 1 "gga: $1"
        oIFS=${IFS}
        IFS=','
        i=0
        for x in $1; do
                case $i in
                        1) time=$x;;
                        2) lat=$x;;
                        3) lat=$lat$x;;
                        4) lon=$x;;
                        5) lon=$lon$x;;
                        6) type=$x;;
                        7) svs=$x;;
                        8) prec=$x;;
                        9) alt=$x;;
                esac
                i=$((i+1))
        done

        case $type in
                1) type=1;; #GPS
                2) type=2;; #DGPS
        esac

        [ ${type} -ne 0 ] && echo "$qual Fix: $time: $svs $lat/$lon/$alt"
        IFS=${oIFS}
}

gsv() {
        local i x s msgtot msgnum inview crc line
        local prn1 elev1 az1 snr1
        local prn2 elev2 az2 snr2
        local prn3 elev3 az3 snr3
        local prn4 elev4 az4 snr4

        line=${1%%\**}
        oIFS=${IFS}
        IFS=','
        i=0
        for x in $line; do
                case $i in
                        1) msgtot=$x;;
                        2) msgnum=$x
                                [ $msgnum -eq 1 ] && {
                                        echo "GPS DATA BEGINS:"
                                        srn_cnt=0
                                        srn_sum=0
                                        sat_cnt=0
                                }
                                ;;
                        3) inview=$x;;
                        4) prn1=$x;;
                        5) elev1=$x;;
                        6) sz1=$x;;
                        7) snr1=$x;;
                        8) prn2=$x;;
                        9) elev2=$x;;
                        10) sz2=$x;;
                        11) snr2=$x;;
                        12) prn3=$x;;
                        13) elev3=$x;;
                        14) sz3=$x;;
                        15) snr3=$x;;
                        16) prn4=$x;;
                        17) elev4=$x;;
                        18) sz4=$x;;
                        19) snr4=${x%%\**}; crc=${x##*\*};;
                esac
                case $i in
                        7|11|15|19) 
                                [ $i -eq 19 ] && x=$snr4
                                #echo "i is $i, X is $x"
                                [ "$x" ] && [ $x -gt 0 ] && {
                                        srn_cnt=$(( srn_cnt + 1 ))
                                        srn_sum=$(( srn_sum + x ))
                                };;
                esac
                i=$((i+1))
        done


        s=$(( ((msgnum-1)) *4))
        echo "Message $msgnum of $msgtot"
        debug 1 "gsv: $1"
        [ "$snr1" -o "$snr2" -o "$snr3" -o "$snr4" ] || echo "-- No Satellites --"
        # [ "$snr1" -o "$snr2" -o "$snr3" -o "$snr4" ] && echo "----BEGIN GPS DATA----"
        [ "$snr1" ] && printf "%02d:%s:%s:%s:%s\n" $((s+1)) $prn1 $elev1 $sz1 $snr1 && sat_cnt=$((sat_cnt+1))
        [ "$snr2" ] && printf "%02d:%s:%s:%s:%s\n" $((s+2)) $prn2 $elev2 $sz2 $snr2 && sat_cnt=$((sat_cnt+1))
        [ "$snr3" ] && printf "%02d:%s:%s:%s:%s\n" $((s+3)) $prn3 $elev3 $sz3 $snr3 && sat_cnt=$((sat_cnt+1))
        [ "$snr4" ] && printf "%02d:%s:%s:%s:%s\n" $((s+4)) $prn4 $elev4 $sz4 $snr4 && sat_cnt=$((sat_cnt+1))
        # [ "$snr1" -o "$snr2" -o "$snr3" -o "$snr4" ] && echo "-----END GPS DATA-----"

        [ $msgnum -eq $msgtot ] && {
                # echo "srn_cnt is $srn_cnt"
                [ "$srn_cnt" -eq 0 ] && SRN_AVG=0
                [ "$srn_cnt" -ne 0 ] && SRN_AVG=$(echo "$srn_sum $srn_cnt" | awk '{avg = $1/$2; print avg}')
                [ "$SRN_EMA" ] || SRN_EMA=$SRN_AVG
                SRN_EMA=$(echo "$SRN_AVG $SRN_EMA $ALPHA" | awk '{EMA = $2 * (1 - $3) + $1 * $3; print EMA}')
                [ "$SAT_EMA" ] || SAT_EMA=$srn_cnt
                SAT_EMA=$(echo "$srn_cnt $SAT_EMA $ALPHA" | awk '{EMA = $2 * (1 - $3) + $1 * $3; print EMA}')
                printf "SRN average: %s, Visible Satellite Average: %s,\
 Current Satellites in view: %s\n\n" $SRN_EMA $SAT_EMA $sat_cnt
        }

        IFS=${oIFS}
}

oIFS=${IFS}

while [ 1 ]; do
		IFS='' read -r line
        debug 2 "${#line}: $line"

        # use case statement for easy regex
        case "$line" in
                *GSV,*) gsv "$line";;
                *GSA,*) gsa "$line";;
                *GGA,*) gga "$line";;
        esac
done < $DEV

IFS=$oIFS

########### END ##############


### from OSP to NMEA script
# #!/bin/sh

# # Make sure we talk to the device at its current configured data format
# # (assuming power-on default of 4800 8N1)
# stty -F /dev/gpsdevice 4800 cs8

# # change to mode=0 (OSP/SiRF binary) 9600bd 8N1
# echo "\$PSRF100,0,9600,8,1,0*0C" > /dev/gpsdevice
# echo "\$PSRF100,1,9600,8,1,0*0D" > /dev/gpsdevice

# # set new tty baudrate for future communication
# stty -F /dev/gpsdevice 9600

## changing baud rate of NMEA
#stty -F /dev/ttymxc4 4800 cs8
#echo "\$PSRF100,1,9600,8,1,0*0D" > /dev/ttymxc4
#stty -F /dev/ttymxc4 9600
