
/**********************************************************************************************
    Copyright (C) 2007 Oliver Eichler oliver.eichler@gmx.de
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA

  Garmin and MapSource are registered trademarks or trademarks of Garmin Ltd.
  or one of its subsidiaries.

**********************************************************************************************/
#ifndef GARMIN_H
#define GARMIN_H

#include <string.h>
#include "Platform.h"

namespace Garmin
{
#pragma pack(1)

    /*
     * Important notice:  The packed structs below contain data in little endian, and accessing
     * them directly may fail if the machine does not support unaligned accesses.  Either use
     * the overloaded operators << and >> to move the data into the properly aligned internal
     * structures or access the data using the macros from ../Platform.h.
     */

    // note: no << or >> operator available, be sure to access the fields properly
    struct Product_Data_t
    {
        uint16_t product_id;
        int16_t  software_version;
        char     str[1];
    };

    // note: no << or >> operator available, be sure to access the fields properly
    struct Protocol_Data_t
    {
        uint8_t  tag;
        uint16_t data;
    };

    struct D108_Wpt_t
    {
        uint8_t  wpt_class;
        uint8_t  color;
        uint8_t  dspl;
        uint8_t  attr;
        uint16_t smbl;
        uint8_t  subclass[18];
        int32_t  lat;
        int32_t  lon;
        float    alt;
        float    dpth;
        float    dist;
        char     state[2];
        char     cc[2];
        char     str[1];
    };

    struct D109_Wpt_t
    {
        uint8_t  dtyp;
        uint8_t  wpt_class;
        uint8_t  dspl_color;
        uint8_t  attr;
        uint16_t smbl;
        uint8_t  subclass[18];
        int32_t  lat;
        int32_t  lon;
        float    alt;
        float    dpth;
        float    dist;
        char     state[2];
        char     cc[2];
        uint32_t ete;
        char     str[1];
    };

    struct D110_Wpt_t
    {
        uint8_t  dtyp;
        uint8_t  wpt_class;
        uint8_t  dspl_color;
        uint8_t  attr;
        uint16_t smbl;
        uint8_t  subclass[18];
        int32_t  lat;
        int32_t  lon;
        float    alt;
        float    dpth;
        float    dist;
        char     state[2];
        char     cc[2];
        uint32_t ete;
        float    temp;
        uint32_t time;
        uint16_t wpt_cat;
        char     str[1];
    };

    struct D202_Rte_Hdr_t
    {
        char     ident[1];
    };

    struct D210_Rte_Link_t
    {
        uint16_t rte_class;
        uint16_t subclass_1;
        uint32_t subclass_2;
        uint32_t subclass_3;
        uint32_t subclass_4;
        uint32_t subclass_5;
        char     ident[1];
    };

    struct D301_Trk_t
    {
        int32_t  lat;
        int32_t  lon;
        uint32_t time;
        float    alt;
        float    dpth;
        uint8_t  new_trk;
    };

    struct D302_Trk_t
    {
        int32_t  lat;
        int32_t  lon;
        uint32_t time;
        float    alt;
        float    dpth;
        float    temp;
        uint8_t  new_trk;
    };

    struct D304_Trk_t
    {
        int32_t  lat;
        int32_t  lon;
        uint32_t time;
        float    alt;            // 32
        float    distance;
        uint8_t  heart_rate;
        uint8_t  cadence;
        uint8_t sensor;
    };

    // same as D312, but without color=16=transparent
    struct D310_Trk_Hdr_t
    {
        uint8_t  dspl;
        uint8_t  color;
        char     ident[1];
    };

    struct D311_Trk_Hdr_t
    {
        uint16_t ident;
    };

    struct D312_Trk_Hdr_t
    {
        uint8_t  dspl;
        uint8_t  color;
        char     ident[1];
    };

    // note: no << or >> operator available, be sure to access the fields properly
    struct Map_Request_t
    {
        uint32_t dummy1;
        uint16_t dummy2;
        char     section[13];
    };

    struct Map_Info_t
    {
        uint8_t  tok;            ///< should be 0x4c
        uint16_t size;           ///< total entry size will be size + sizeof(tok) + sizeof(size)
        uint16_t product;        ///< product code as it can be found in the registry
        uint16_t dummy;          ///< country / char. set?
        uint32_t mapId;          ///< same id as in tdb and map filename
        char     name1[1];
        /*
        There are several 0 terminated strings:
        "map name"
        "tile name"
        */
    };
    /*
    quint32 ???                 ///< the map id as it is used in the FAT table
    quint32 ???                 ///< always 0x00000000 (end token?)
    */

    struct D800_Pvt_Data_t
    {
        float    alt;
        float    epe;
        float    eph;
        float    epv;
        uint16_t fix;
        double   tow;
        double   lat;
        double   lon;
        float    east;
        float    north;
        float    up;
        float    msl_hght;
        int16_t  leap_scnds;
        uint32_t wn_days;
    };

#pragma pack()

    // ---------------------------------------------------------------------------------------

    enum serial_e
    {
        Pid_Ack_Byte           = 6
        ,Pid_Nak_Byte           = 21
    };

    enum L000_e
    {
        Pid_Protocol_Array     = 253
        ,Pid_Product_Rqst       = 254
        ,Pid_Product_Data       = 255
        ,Pid_Ext_Product_Data   = 248
    };

    enum L001_e
    {
        Pid_Command_Data       = 10
                                 //0x0C
        ,Pid_Xfer_Cmplt         = 12
        ,Pid_Prx_Wpt_Data       = 19
        ,Pid_Wpt_Data           = 35
                                 //0x1B
        ,Pid_Records            = 27
                                 //0x1D
        ,Pid_Rte_Hdr            = 29
                                 //0x1E
        ,Pid_Rte_Wpt_Data       = 30
        ,Pid_Trk_Data           = 34
        ,Pid_Pvt_Data           = 51
                                 //????
        ,Pid_Capacity_Data      = 95
                                 //0x62
        ,Pid_Rte_Link_Data      = 98
        ,Pid_Trk_Hdr            = 99
                                 //????
        ,Pid_Tx_Unlock_Key      = 108
                                 //????
        ,Pid_Ack_Unlock_key     = 109

        ,Pid_Req_Icon_Id        = 0x371
        ,Pid_Ack_Icon_Id        = 0x372

        ,Pid_Req_Clr_Tbl        = 0x376
        ,Pid_Ack_Clr_Tbl        = 0x377
        ,Pid_Icon_Data          = 0x375
        ,Pid_Ack_Icon_Data      = 0x374

    };

    enum A010_e
    {
        Cmnd_Abort_Transfer    = 0
        ,Cmnd_Transfer_Prx      = 3
        ,Cmnd_Transfer_Rte      = 4
        ,Cmnd_Transfer_Trk      = 6
        ,Cmnd_Transfer_Wpt      = 7
        ,Cmnd_Transfer_Mem      = 63
        ,Cmnd_Start_Pvt_Data    = 49
        ,Cmnd_Stop_Pvt_Data     = 50
    };

    struct Wpt_t;

    extern void operator<<(Wpt_t& tar, const D108_Wpt_t& src);
    extern int  operator>>(const Wpt_t& src, D108_Wpt_t& tar);

    extern void operator<<(Wpt_t& tar, const D109_Wpt_t& src);
    extern int  operator>>(const Wpt_t& src, D109_Wpt_t& tar);

    extern void operator<<(Wpt_t& tar, const D110_Wpt_t& src);
    extern int  operator>>(const Wpt_t& src, D110_Wpt_t& tar);

    struct Track_t;
    struct TrkPt_t;

    extern void operator<<(Track_t& tar, const D310_Trk_Hdr_t& src);
    extern void operator<<(Track_t& tar, const D311_Trk_Hdr_t& src);
    extern void operator<<(Track_t& tar, const D312_Trk_Hdr_t& src);
    extern int  operator>>(const Track_t& src, D312_Trk_Hdr_t& tar);

    extern void operator<<(TrkPt_t& tar, const D301_Trk_t& src);
    extern void operator<<(TrkPt_t& tar, const D302_Trk_t& src);
    extern void operator<<(TrkPt_t& tar, const D304_Trk_t& src);
    extern int  operator>>(const TrkPt_t& src, D302_Trk_t& tar);

    struct Pvt_t;
    extern void operator<<(Pvt_t& tar, const D800_Pvt_Data_t& src);

    struct Route_t;
    extern void operator<<(Route_t& tar, const D202_Rte_Hdr_t& src);
    extern int  operator>>(const Route_t& src, D202_Rte_Hdr_t& tar);
    struct RtePt_t;
    extern void operator<<(RtePt_t& tar, const D210_Rte_Link_t& src);
    extern int  operator>>(const RtePt_t& src, D210_Rte_Link_t& tar);

    struct Map_t;
    extern int operator<<(Map_t& tar, const Map_Info_t& src);
}
#endif                           //GARMIN_H
