/*

*/

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <linux/ipc.h>
#include <linux/msg.h>
#include <signal.h>
#include <mqueue.h>
#include <pthread.h>
#include <errno.h>
#include	"dsgwd_pi.h"
#include	"crc.h"

void    GPGLL (char string[]);
void    GPGGA (char string[]);
void    GPRMC (char string[]);
void    GPS_A (char string[]);
void    dprs_message (char string[]);


unsigned char	InetLat[8], InetLong[9];
unsigned char	InetCall[8];
unsigned char	InetMsg[20];
unsigned char	InetAtitude[6];
unsigned char	InetSpeed[3];
unsigned char	InetDirection[3];
unsigned char	RadioLat[8], RadioLong[9];
unsigned char	RadioCall[8];
unsigned char	RadioMsg[20];
unsigned char	RadioAtitude[6];
unsigned char	RadioSpeed[3];
unsigned char	RadioDirection[3];
unsigned char	Radio_GPS_A_MSG[120];
unsigned char	Inet_GPS_A_MSG[120];
unsigned char	Radio_GPS_A_Msg_send;
unsigned char	Inet_GPS_A_Msg_send;
unsigned char	DprsOpen = 0;
unsigned int	AprsInetTimer = 0;
unsigned int	AprsRadioTimer = 0;
unsigned int	DprsBeaconTimer = 0;
unsigned char	DprsMsgDstCallSign[10];
unsigned char	DprsMsgSrcCallSign[10];
unsigned char	AprsCallTBLCnt;
unsigned char	ReqLoadAprsCallCheck;
unsigned char	DprsMsgDstCallSignSave[9];

char	RadioDprsSend, InetDprsSend;
	
unsigned char	dprs_data[150];
unsigned char	dprs_pnt = 0;

void	DprsData(char  Sdata[])
{
	unsigned char	len;

	len = Sdata[0] & 0x0f;
	if ((dprs_pnt + len) >= 120)
	{
		dprs_pnt = 0;
		return;
	} 
	memcpy (&dprs_data[dprs_pnt], &Sdata[1], len);
	dprs_pnt += len;
	if (dprs_data[dprs_pnt - 1] == 0x0d) dprs_data[dprs_pnt++] = 0x0a;
	if (dprs_data[dprs_pnt - 1] == 0x0a)
	{
		if (gps_sumcheck(dprs_data))
		{
				dprs_data[dprs_pnt - 1] = 0x00;
				if(!memcmp (dprs_data, "$GPGLL,", 7)) GPGLL (&dprs_data[7]);
				else if(!memcmp (dprs_data, "$GPGGA,", 7)) GPGGA (&dprs_data[7]);
				else if(!memcmp (dprs_data, "$GPRMC,", 7)) GPRMC (&dprs_data[7]);
				else if(!memcmp (dprs_data, "$$CRC", 5)) GPS_A (&dprs_data[10]);
				else if(dprs_data[0] != '$') dprs_message(dprs_data);
		}

		dprs_pnt = 0;
	} 
}

int	gps_sumcheck(char string[])
{
	unsigned char	*pnt;
	unsigned char	sum, csum, tmp;

	if (!memcmp (string, "$$CRC", 5))
	{
		return GPS_A_SumCheck(string);
	}
	pnt = string;
	sum = 0;
	if (*pnt == '$') pnt++;
	while (*pnt !='*')
	{
		if ((*pnt == 0x0a) || (*pnt == 0x0d)) return FALSE;
		sum ^= *pnt;
		pnt++;
	}
	pnt++;
	tmp = *pnt - '0';
	if (tmp > 16) tmp -= 7;
	csum = tmp << 4;
	pnt++;
	tmp = *pnt - '0';
	if (tmp > 16) tmp -= 7;
	csum += tmp;
	if (csum == sum) return TRUE;
	return FALSE;
}

void	GPGLL (char string[])
{
	unsigned char	*pnt;
	unsigned char	i;

	pnt = string;
	i = 0;
	while (*pnt != ',')
	{
		if (i < 7)
		{
			InetLat[i] = *pnt;
			i++;
		}
		pnt++;
	}
	pnt++;
	RadioLat[7] = *pnt;
	pnt += 2;

	i = 0;
	while (*pnt != ',')
	{
		if (i < 8)
		{
			InetLong[i] = *pnt;
			i++;
		}
		pnt++;
	}
	pnt++;
	InetLong[8] = *pnt;
}

void	GPGGA (char string[])
{
	unsigned char	*pnt;
	unsigned char	i;
	unsigned int	d;
	unsigned char	tmp[10];
	unsigned int	k;

	pnt = string;
	while (*pnt != ',') pnt++;
	pnt++;
	i = 0;
	while (*pnt != ',')
	{
		if (i < 7)
		{
			InetLat[i] = *pnt;
			i++;
		}
		pnt++;
	}
	pnt++;
	InetLat[7] = *pnt;
	pnt += 2;

	i = 0;
	while (*pnt != ',')
	{
		if (i < 8)
		{
			InetLong[i] = *pnt;
			i++;
		}
		pnt++;
	}
	pnt++;
	InetLong[8] = *pnt;

	pnt += 2;
	while (*pnt != ',') pnt++;
	pnt++;
	while (*pnt != ',') pnt++;
	pnt++;
	while (*pnt != ',') pnt++;
	pnt++;
	i = 0;
	while (*pnt != ',')
	{
		if (i < 8)
		{
			tmp[i] = *pnt;
			i++;
		}
		pnt++;
	}
	tmp[i] = 0x00;
	d = atof ((char *)tmp);
	k = d / 0.3048 + 0.5;
	sprintf ((char *)InetAtitude, "%06d", k); 
}

void	GPRMC (char string[])
{
	unsigned int	d;
	unsigned char	tmp[10];
	unsigned int	k;
	unsigned char	*pnt;
	unsigned char	i;

	pnt = string;
	while (*pnt != ',') pnt++;
	pnt++;
	while (*pnt != ',') pnt++;
	pnt++;
	i = 0;
	while (*pnt != ',')
	{
		if (i < 7)
		{
			InetLat[i] = *pnt;
			i++;
		}
		pnt++;
	}
	pnt++;
	InetLat[7] = *pnt;
	pnt += 2;

	i = 0;
	while (*pnt != ',')
	{
		if (i < 8)
		{
			InetLong[i] = *pnt;
			i++;
		}
		pnt++;
	}
	pnt++;
	InetLong[8] = *pnt;
	pnt += 2;
	i = 0;
	while (*pnt != ',')
	{
		if (i < 9)
		{
			tmp[i] = *pnt;
			i++;
		}
		pnt++;
	}
	tmp[i] = 0x00;
	d = atof ((char *)tmp);
	k = d + 0,5;
	sprintf ((char *)InetSpeed, "%03d", k);

	pnt++;
	i = 0;
	while (*pnt != ',')
	{
		if (i < 9)
		{
			tmp[i] = *pnt;
			i++;
		}
		pnt++;
	}
	tmp[i] = 0x00;
	d = atof ((char *)tmp);
	k = d + 0,5;
	sprintf ((char *)InetDirection, "%03d", k);
}

void	dprs_message (char string[])
{
	unsigned char	*pnt;
	unsigned char	i, k;
	unsigned char	len;

//	len = strlen ((char *)&string);
//	if (len <= 9) return;

	pnt = string;
	i = 0;
	memset (InetCall, 0x20, 8);
	while (*pnt != ',')
	{
		if (*pnt == 0x00) return;
		if (i < 8)
		{
			InetCall[i] = *pnt;
			i++;
		}
		pnt++;
	}
	k = 0;
	for (i = 0 ; i < 8 ; i++)
	{
		if (InetCall[i] != 0x20)
		{
			InetCall[k] = InetCall[i];
			k++;
		} else {
			if (InetCall[k-1] != '-')
			{
				InetCall[k] = '-';
				k++;
			}
		}
	}

	if (InetCall[k-1] == '-') InetCall[k-1] = 0x00;

	if (k < 7)
	{
		for (i = k ; i < 8 ; i++)
		{
			InetCall[k] = 0x00;
		}
	}

	memset (InetMsg, 0x00, 20);
	len = strlen (&string[9]);
	if (len == 0) return;
	memcpy (InetMsg, &string[9], len);
	InetDprsSend = TRUE;
}

/*
	CRC update routine
 */
unsigned int	update_crc_dstar( unsigned int  crc, unsigned char c )
{
    unsigned int	tmp, short_c;

    short_c  = 0x00ff &  c;
	
    tmp = (crc & 0x00ff) ^ short_c;
    crc = (crc >> 8)  ^ crc_tabccitt[tmp];

    return crc;

}  /* update_crc_dstar */


/*
	CRC reslut routine
 */

unsigned int	result_crc_dstar(unsigned int crc)
{

    unsigned int	tmp;

      crc = ~crc;
      tmp = crc;
      crc = (crc << 8) | (tmp >> 8 & 0xff);

    return crc;

}  /* result_crc_dstar */

int	GPS_A_SumCheck(char string[])
{
	unsigned int	crc_dstar_ffff, k, k0, k1, k2, k3;
	char	*pnt;
	
    crc_dstar_ffff = 0xffff;	/* nornal value 0xffff */
	pnt = string + 10;

	while (*pnt != 0x0a)
	{
		crc_dstar_ffff = update_crc_dstar( crc_dstar_ffff, *pnt);
		pnt++;
	}

	crc_dstar_ffff = result_crc_dstar(crc_dstar_ffff);

	k0 = string[5] - '0';
	if (k0 > 16) k0 -= 7;
	k1 = string[6] - '0';
	if (k1 > 16) k1 -= 7;
	k2 = string[7] - '0';
	if (k2 > 16) k2 -= 7;
	k3 = string[8] - '0';
	if (k3 > 16) k3 -= 7;
	k1 += k0 * 16;
	k3 += k2 * 16;
    k = k1 | (k3 << 8);

	if (k == crc_dstar_ffff) return TRUE;
	return	FALSE;
}

void	GPS_A (char string[])
{
	memcpy (Radio_GPS_A_MSG, string, strlen((char *)string));
	Radio_GPS_A_Msg_send = TRUE;
}
