/*****************************************************************************
 * Copyright (c) 2002-2020 MBARI
 * Monterey Bay Aquarium Research Institute, all rights reserved.
 *****************************************************************************
 * @file    DeltaT.h
 * @authors r. henthorn
 * @date    07/23/2020
 * @brief   DeltaT client interface module
 *
 * Project: LRAUV Obstacle Avoidance (oahu)
 * Summary: Modeled after the Dorado DeltaT interface. Read Imagenex Delta T
 *         (idt) packets from UDP socket. Use Idt83pParser to create Idt83pData
 *         objects for application use.
 *****************************************************************************/

 #ifndef DELTAT_H
 #define DELTAT_H

/*****************************************************************************
 * Copyright Information:
 * Copyright 2002-2020 MBARI
 * Monterey Bay Aquarium Research Institute, all rights reserved.
 *
 * Terms of Use:
 * 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 3 of the License, or (at your option)
 * any later version. You can access the GPLv3 license at
 * http://www.gnu.org/licenses/gpl-3.0.html
 *
 * 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 (http://www.gnu.org/licenses/gpl-3.0.html).
 *
 * MBARI provides the documentation and software code "as is", with no
 * warranty, express or implied, as to the software, title, non-infringement
 * of third party rights, merchantability, or fitness for any particular
 * purpose, the accuracy of the code, or the performance or results which you
 * may obtain from its use. You assume the entire risk associated with use of
 * the code, and you agree to be responsible for the entire cost of repair or
 * servicing of the program with which you are using the code.
 *
 * In no event shall MBARI be liable for any damages,whether general, special,
 * incidental or consequential damages, arising out of your use of the
 * software, including, but not limited to,the loss or corruption of your data
 * or damages of any kind resulting from use of the software, any prohibited
 * use, or your inability to use the software. You agree to defend, indemnify
 * and hold harmless MBARI and its officers, directors, and employees against
 * any claim,loss,liability or expense,including attorneys' fees,resulting from
 * loss of or damage to property or the injury to or death of any person
 * arising out of the use of the software.
 *
 * The MBARI software is provided without obligation on the part of the
 * Monterey Bay Aquarium Research Institute to assist in its use, correction,
 * modification, or enhancement.
 *
 * MBARI assumes no responsibility or liability for any third party and/or
 * commercial software required for the database or applications. Licensee
 * agrees to obtain and maintain valid licenses for any additional third party
 * software required.
 *****************************************************************************/

/******************************
 * Headers
 ******************************/

#include <stdint.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include "Idt83pParser.h"
#include "DeltaTLog.h"

/******************************
 * Macros
 ******************************/

#define DELTAT_DEFAULT_NAME    "idt"
#define DELTAT_DEFAULT_PORT    4040
#define DELTAT_DEFAULT_TIMEOUT  500    // in ms
#define DELTAT_BUF_SIZE (IDT_HDR_SIZE+(IDT_MAX_BEAMS*(IDT_B_BYTES+IDT_I_BYTES)))
#define DELTAT_EC_BUF_SIZE      256

// default external control switch values
#define DELTAT_DEFAULT_ENABLE       0  // 0=>83P, 1=>83B
#define DELTAT_DEFAULT_RANGE       10  // 2=5m 3=10m 4=20m 5=30m 6=40m 7=50m 8=60m 9=80m 10=100m 11=150m
#define DELTAT_DEFAULT_GAIN        12  // 0-20 dB
#define DELTAT_DEFAULT_DGAIN       50  // 0-100 %
#define DELTAT_DEFAULT_GAINEQUAL    0  // on/off
#define DELTAT_DEFAULT_SECTOR       3  // 0=>30 1=>60 2=>90 3=>120
#define DELTAT_DEFAULT_WIDTH        1  // 0=>Wide 1=>Normal 2=>Narrow 3=>Mixed
#define DELTAT_DEFAULT_BEAMS        2  // 0=>480 1=>240 2=>120
#define DELTAT_DEFAULT_AVERAGE      3  // 3, 5, 7, or 9
#define DELTAT_DEFAULT_SOS       1490  // 1400 to 1600 m/s
#define DELTAT_DEFAULT_MODE         0  // 0=>sector 1=>Linear 2=>Perspective 3=>Profile 4=>Beamtest
#define DELTAT_DEFAULT_MINRANGE     1  // 0 - 100 m
#define DELTAT_DEFAULT_MINLEVEL    25  // 10 - 90 %
#define DELTAT_DEFAULT_XD_DIR       0  // 0=>Down 1=>Up
#define DELTAT_DEFAULT_TILT       225  // -45 to +45 then add 180 offset (e.g. 45 to 225) 50=>-90 51=>90
#define DELTAT_DEFAULT_POINT_DETECT 1  // on/off
#define DELTAT_DEFAULT_POINT_FILTER 2  // 0=>1st return 1=>max return 2=>bottom following
#define DELTAT_DEFAULT_RECORD837    1  // on/off
#define DELTAT_DEFAULT_RECORD83B    0  // on/off
#define DELTAT_DEFAULT_RECORD83P    1  // on/off
#define DELTAT_DEFAULT_TRIGGER      0  // 0=>Off 2=>On-Neg 3=>On-Pos
#define DELTAT_DEFAULT_XMIT_DELAY   0  // 0-10000 (0 to 1 sec)
#define DELTAT_CONFIG_120BEAMS      2
#define DELTAT_CONFIG_240BEAMS      1


class DeltaT
{
public:

   // configure the DeltaT object as per a config file
   static void configDeltaT(DeltaT *d, const char* cfgfilepath);

   // Use a config object to construct DeltaT object
   // When dataSourceFile is non-NULL, the driver will
   // read raw packets from the file instead of the
   // beamformer socket.
   typedef struct deltatconfig_
   {
      const char *name;            // Name of object (NULL=>use default)
      uint32_t    port;            // Listen for data on this port
      bool        logData;         // Log raw and beam data to files
      const char *dataSourceFile;  // when non NULL read data from this file
      uint32_t    readTimeout;     // in ms 0=>use default
   } DeltaTConfig;

   DeltaT();
   DeltaT(const char* name, const uint32_t port, const bool logData=false);
   DeltaT(const DeltaTConfig &config);
   virtual ~DeltaT();

   uint32_t    getPort() { return _port; }
   const char* getName() { return _name; }
   int         getSock() { return _sockfd; }

   // attempt to read a packet from a DeltaT source.
   // return parsed info in the Idt83pData parameter object.
   // returns NULL if unsuccessful.
   // otherwise, returns pointer to the parsed data in the
   // Idt83pData parameter object passed in.
   virtual Idt83pData* getData(Idt83pData *data);

   /* external control settings */
   int setOutputEnable(int enable);
   int setRange(int range);
   int setGain(int gain);
   int setGainEqualization(int equal);           // on/off
   int setSectorSize(int size);
   int setBeamWidth(int width);
   int setNumBeams(int nbeams);
   int setAvgFilter(int avg);                    // on/off
   int setSOS(int sos);                          // m/s
   int setRunMode(int run);
   int setProfileMinRange(int mrange);
   int setProfileMinLevel(int level);
   int setTransducerDirection(int dir);
   int setProfileTiltAngle(int angle);
   int setRecord83P(int r83P);                   // on/off
   int setRecord837(int r837);                   // on/off
   int setRecord83B(int r83B);                   // on/off
   int setProfilePointDetection(int ppd);        // on/off
   int setProfilePointFilter(int ppf);
   int setExternalTriggerControl(int etc);       // on/off
   int setExternalTriggerXmitDelay(int delay);   // ms
   int setDisplayGain(int dgain);

   /* data */

protected:

   // attempt to read from either a socket or raw DeltaT data file.
   // return parsed info in the Idt83pData parameter object.
   // returns the number of bytes read if successful.
   // returns < 0 if unsuccessful.
   // otherwise, returns pointer to the parsed data in the
   // Idt83pData parameter object passed in.
   int readData(Idt83pData *data);

   void initializeName(const char* name);
   void initializeLogs(bool logData);
   int  initializeSource();

   void createRawFile();
   void closeSock();

   /* data */

   uint32_t   _port;
   uint32_t   _timeout;  // in ms
   char*      _name;
   char*      _dataSourceFile;
   int        _sockfd;
   int        _raw;
   DeltaTLog* _log;
   char       _receive_buf[DELTAT_BUF_SIZE];

   struct sockaddr_in _client_addr;
   struct sockaddr_in _server_addr;

   /* external control members */
   int _send;
   char _send_buf[DELTAT_EC_BUF_SIZE];
   int _range, _gain, _equal, _sector, _sos, _width, _nbeams, _avg;
   int _enable, _level, _delay, _r83P, _r83B, _r837, _mrange;
   int _run, _ppf, _dir, _ppd, _etc, _dgain, _angle, _mode;

   int setSend()   { _send = 1; return 0; }
   int resetSend() { _send = 0; return 0; }
   int prepECMsg();
   int sendEC();

private:

   /* data */
};
#endif
