MTK3339 GPS AGPS, Help needed

I am using a GPS sensor based on the MTK3339 which is generally working correctly, however when I try to upload the EPO file to the GPS, it always fails (at packet 10 which is the last in a satellite set). Is there anyone who has in depth knowledge of what I am trying to acheive, or can read both C# & Python to see where I am going wrong.

I have posed the full GPS driver to [url]https://gist.github.com/networkfusion/a3b3fbc415bb88a06ec2[/url] but this is my EPO part (excusing the code quality as I am just trying to get it to work first):


byte[] epoPacket = new byte[191];
        int epoCount = 0;
        bool finalEpoPacketRequired = false;
        bool flagStop = false;
        //int totEPOcnt = 0;
        byte[] epoFileData;
        int failCount = 0;
        int SatSetSize = 60;
        int currentFileDataIndex = 0;

        enum CommsProtocol
        {
            Binary,
            ASCII
        }

        CommsProtocol currentProtocol = CommsProtocol.ASCII;

        public void UpdateEpoData(byte[] fileData) //TODO: try and use https://github.com/f5eng/mt3339-utils/blob/gps/epoloader as this fails.
        {
            this.failCount = 0;
            this.epoCount = 0;
            this.epoFileData = fileData;
            //this.flagAGPS = false;
            this.finalEpoPacketRequired = false;
            this.flagStop = false;
            //this.totEPOcnt = epoFileData.Length / SatSetSize; // = 32

            if (this.epoFileData.Length % 1920 != 0)
            {
                if (Debugger.IsAttached) { Debug.Print("EPO File is corrupt"); }
            }
            else
            {
                var b = UTF8Encoding.UTF8.GetBytes(ENTER_BINARY_MODE);
                serialPort.Write(b, 0, b.Length); // GPS chipset from nmea- to bin-mode at 57600bps
                Thread.Sleep(500);
                serialPort.Close();

                currentProtocol = CommsProtocol.Binary;

                serialPort.BaudRate = 57600;
                serialPort.Open();

                if (Debugger.IsAttached) { Debug.Print("Starting to send epo packets"); }
                this.SendEpoPacket();
                
            }

        }

        int satSet = 0;
        int packetInSatSet = 0;

        private void SendEpoPacket()
        {
            if (this.flagStop)
            {
                if (Debugger.IsAttached) { Debug.Print("finished EPO file setup, going back to nema mode"); }
                this.finalEpoPacketRequired = false;
                this.flagStop = false;
                this.SetModeNMEA(9600);

                Thread.Sleep(1000);
                this.serialPort.Write("$PMTK607*33\r\n");

                return;
            }

            if (this.finalEpoPacketRequired)
            {
                if (Debugger.IsAttached) { Debug.Print("sending the final epo packet"); }
                this.flagStop = true;
                this.epoCount = 65535; //0xffff

                this.GenerateEpoPacket(0, true);
                this.serialPort.Write(this.epoPacket, 0, 191);

                return;
            }


            if (packetInSatSet != 10)
            {
                Debug.Print("Sending 3 sats");
                if (Debugger.IsAttached) { Debug.Print("sending an epo packet"); }

                this.GenerateEpoPacket(180);
                this.serialPort.Write(this.epoPacket, 0, 191);

                this.epoCount++;
                packetInSatSet++;
            }
            else
            {
                Debug.Print("Sending 2 sats");
                int num = epoFileData.Length - currentFileDataIndex; //should be 120?!
                if (num < 121)
                {
                    this.finalEpoPacketRequired = true;

                    if (Debugger.IsAttached)
                    {

                        Debug.Print("current file index is: " + currentFileDataIndex);
                        Debug.Print("file size is: " + epoFileData.Length);
                        Debug.Print("got " + num + ". It should be 120... but is it?");
                    }   

                }

                this.GenerateEpoPacket(120);
                this.serialPort.Write(this.epoPacket, 0, 191);
                this.epoCount++;
                packetInSatSet = 0;
                satSet++;
          
            }

        }

        private void GenerateEpoPacket(int epoMaxCount, bool isFinalPacket = false)
        {
            epoPacket = new byte[191];
            this.epoPacket[0] = 0x04; this.epoPacket[1] = 0X24;             //Preamble
            this.epoPacket[2] = 0xBF; this.epoPacket[3] = 0x00;             //Length
            this.epoPacket[4] = 0xD2; this.epoPacket[5] = 0x02;             //Command: EPO Packet

            this.epoPacket[6] = (byte)(this.epoCount & 0xFF);               //Message ID part 1
            this.epoPacket[7] = (byte)((this.epoCount >> 8) & 0xFF);        //Message ID part 2

            if (!isFinalPacket)
            {
                int epoPacketIndex = 8;

                for (int i = epoPacketIndex; i <= (epoMaxCount + epoPacketIndex) -1; i++)
                {
                    this.epoPacket[i] = epoFileData[currentFileDataIndex];
                    currentFileDataIndex++;
                }
            }
            else
            {
                this.finalEpoPacketRequired = true;
            }

            this.epoPacket[188] = this.GenerateChecksum(this.epoPacket);    //Checksum
            this.epoPacket[189] = 0x0D; this.epoPacket[190] = 0x0A;         //End word
        }


        private void SetModeNMEA(int baudRate)
        {
            byte[] NemaPacket = new byte[14];
            NemaPacket[0] = 0x04; NemaPacket[1] = 0x24;                    // Preamble
            NemaPacket[2] = 0x0E; NemaPacket[3] = 0x00;                    // Length
            NemaPacket[4] = 0xFD; NemaPacket[5] = 0x00;                    // Command: Change UART packet protocol
            NemaPacket[6] = 0x00;                                          // PMTK protocol
            NemaPacket[7] = (byte)(baudRate & 0xFF);                       // Set UART baudrate (4 bytes)
            NemaPacket[8] = (byte)((baudRate >> 8) & 0xFF);
            NemaPacket[9] = (byte)((baudRate >> 16) & 0xFF);
            NemaPacket[10] = (byte)((baudRate >> 24) & 0xFF);
            NemaPacket[11] = GenerateChecksum(NemaPacket);                  // Checksum
            NemaPacket[12] = 0x0D; NemaPacket[13] = 0x0A;                   // End word

            this.serialPort.Write(NemaPacket, 0, 14);
            Thread.Sleep(500);
            serialPort.Close();
            serialPort.BaudRate = baudRate;
            currentProtocol = CommsProtocol.ASCII;
            serialPort.Open();
            if (Debugger.IsAttached) { Debug.Print("Set to NEMA mode"); }
        }

        byte GenerateChecksum(byte[] packet)
        {
            var xorByte = packet[2];                                        //Avoid the preamble
            int endIndex = packet.Length - 3;                               //Avoid the End word
            for (int i = 3; i <= endIndex; i++)
            {
                xorByte ^= (byte)(packet[i] & 0xff);
            }
            return xorByte;
        }

        bool readInProgress = false;
        void serialPort_DataReceived(GTI.Serial sender)
        {
            try
            {
                if (!readInProgress)
                {
                    readInProgress = true;

                    while (sender.BytesToRead > 0)
                    {
                        byte[] receivedBytes = new byte[100];
                        int i = 0;
                        if (currentProtocol == CommsProtocol.Binary)
                        {
                            receivedBytes[i] = (byte)serialPort.ReadByte();
                            i++;
                        }
                        if (receivedBytes[0] == 0x04 | currentProtocol == CommsProtocol.ASCII)
                        {
                            receivedBytes[i] = (byte)serialPort.ReadByte();
                            if (receivedBytes[i] == 0x24)
                            {
                                //Debug.Print("got packet start");
                                i++;
                                while (true)
                                {
                                    //read until the endword is received
                                    receivedBytes[i] = (byte)serialPort.ReadByte();
                                    if (receivedBytes[i] == 0x0A)
                                    {
                                        if (currentProtocol == CommsProtocol.Binary)
                                        {
                                            //Debug.Print("got packet end");
                                            ParseACK(receivedBytes);
                                        }
                                        else
                                        {
                                            serialPort_LineReceived(new string(UTF8Encoding.UTF8.GetChars(receivedBytes)));
                                        }
                                        break;
                                    }
                                    i++;
                                }
                            }
                        }
                    }


                    readInProgress = false;
                }
            }
            catch (Exception ex)
            {
                if (Debugger.IsAttached) { Debug.Print("binary mode: error receiving bytes, " + ex); }
            }
        }

        private void ParseACK(byte[] receivedBytes)
        {
            try
            {
                bool success = false;
                if ((receivedBytes[0] == (byte)0x04) & (receivedBytes[1] == (byte)0x24) &                // Preamble (4, 36)
                    (receivedBytes[2] == (byte)0x0C) & (receivedBytes[3] == (byte)0x00) &                // Response Length (12, 0)
                    (receivedBytes[4] == (byte)0x02) & (receivedBytes[5] == (byte)0x00) &                // Command ID (2, 0)
                    (receivedBytes[6] == (byte)(this.epoCount - 1 & 0xff) & (receivedBytes[7] == (byte)(this.epoCount - 1 >> 8))))// && ((millis()-startTime)<timeOut))  // LSB-MSB sequence
                {
                    if (receivedBytes[8] != 0x01) //the sent epo data was unsuccessful
                    {
                        this.SetModeNMEA(9600);
                        if (Debugger.IsAttached) { Debug.Print("EPO File is corrupt at packet" + (epoCount - 1) + ", exiting"); }
                        success = true;
                    }
                    else
                    {
                        if (Debugger.IsAttached) { Debug.Print("EPO packet successful, sending the next one"); }
                        this.SendEpoPacket();
                    }
                }
                if (!success)
                {
                    if (Debugger.IsAttached) { Debug.Print("Packet incorrect, ignoring"); }

                    this.failCount++;
                }
                if (this.failCount >= 1920)
                {
                    this.SetModeNMEA(9600);
                    if (Debugger.IsAttached) { Debug.Print("EPO File upload has failed too many times, exiting."); }
                }

            }
            catch (Exception ex)
            {
                if (Debugger.IsAttached) { Debug.Print(ex.ToString()); }
                this.SetModeNMEA(9600);
            }


        }

I call this from the main program using:


try
            {

                TraceLog("Downloading EPO data", LogType.Information);
                var strName = "gtopagpsenduser01";
                var strPWD = "enduser080807";
                var strFTPPath = "ftp.gtop-tech.com";
                //byte[] data;

                TraceLog("Connecting to FTP Server", LogType.Information);
                FtpClient ftpclient = new FtpClient();
                ftpclient.connectToRemoteFtpServer(strFTPPath, 21, strName, strPWD);

                var ltemp = ftpclient.getfilesize("MTK14.EPO");
                byte[] buffer = new byte[ltemp];
                TraceLog("Receiving file via FTP", LogType.Information);
                ftpclient.download("MTK14.EPO", buffer);

                TraceLog("Updating GPS sensor", LogType.Information);
                gps.UpdateEpoData(buffer);
            }
            catch (Exception ex)
            {

                TraceLog(ex.ToString(), LogType.Error);
            }

I have also found a python solution: [url]https://github.com/f5eng/mt3339-utils[/url] if it helps.

1 Like

Is no one interested in helping with this?

The lack of response probably means the answer to the above question is no. I’ve used this particular GPS on a gadgeteer module, but have never implemented the EPO file upload.

Have you seen this? https://www.adafruit.com/datasheets/GTop%20EPO%20Format%20and%20Protocol-v14.pdf

What is the problem you are running into ? Do you expect to someone to debug the entire code ? Maybe no one else has this GPS




serialPort.Write(b, 0, b.Length); // GPS chipset from nmea- to bin-mode at 57600bps
                Thread.Sleep(500);
                serialPort.Close();


Dont you need a serialPort.Open () ?

@ Rajesh - as mentioned in the first post, when I try to upload the EPO file to the GPS, it always fails (at packet 10 which is the last in a satellite set). If you download the full version of the driver and run it, the serial port is opened. The posted code is only to show the EPO uploading part.

@ ransomhall I plan on doing more debugging on this later but was wondering if anyone had got the EPO part working before.

I have also seen the adafruit spec documentation and feel I have implemented it correctly but if anyone can see that I have done something incorrect then I would be most grateful. once it is working I will post the driver to codeshare.