#ifndef LCXMODEM_H
#define LCXMODEM_H

#include "BuoyLauncherMsgs.h"
#include <SerialDevice.h>

#define SOH    (BYTE)0x01   // start-of-packet character
#define EOT    (BYTE)0x04   // end-of-transmission char
#define ACK    (BYTE)0x06
#define NAK    (BYTE)0x15

#ifdef BOOL
   #undef  BOOL
#endif
#define BOOL int

#ifdef BYTE
   #undef  BYTE
#endif
#define BYTE unsigned char

#ifdef WORD
   #undef  WORD
#endif
#define WORD unsigned short

#ifdef DWORD
   #undef  DWORD
#endif
#define DWORD unsigned long

#ifdef HIBYTE
   #undef HIBYTE
#endif
#define HIBYTE(x)   (BYTE)(((x) >> 8) & 0x00FF)

#ifdef LOBYTE
   #undef LOBYTE
#endif
#define LOBYTE(x)   (BYTE)((x) & 0x00FF)

#define  FALSE  0
#define  TRUE   (!FALSE)

#define ERRORMAX               6
#define RETRYMAX               4
#define PACKET_SIZE         1024
#define LAUNCH_CYCLE_WAIT_MIN  4L  


 struct BuoyStatus    // LC will have an array of these, one for each buoy
{
   BYTE   bBuoyNumber;
   BYTE   bMainBattVolts;
   BYTE   bAuxBattVolts;
   BYTE   bTempDegC;
   time_t lTimeSecBuoy;
   long   lARGOSBytesAvail;
   long   lArchiveBytesAvail;
   long   lPicoBytesAvail;
   long   lDataMemoryBuoy;
};

struct LauncherStatus
{
   BYTE   bLauncherError;
   BYTE   bLastLaunchOK;
   BYTE   bBuoyResponsive;
   BYTE   bNextBuoyReady;
   BYTE   bCurrentBuoyNumber;
   BYTE   bNextBuoyNumber;
   BYTE   bTotalNumBuoys;
   BYTE   bNumBuoysRemain;
   BYTE   bNumBuoysLaunched;
   BYTE   bTT8SupplyVoltsL;
   BYTE   bMotorSupplyVoltsL;
   BYTE   bTempDegCL;
   time_t lTimeSecL;
   long   lARGOSBytesL;
   long   lArchiveBytesL;
   long   lPicoBytesAvailL;
   long   lDataMemoryL;
   // 12 buoys
   // although maybe this should be just for the current buoy
   struct BuoyStatus Buoy;
};

// error codes re comms with Buoy
enum BuoyErrors
{
   BOUY_OK = -100, // start here so we do not get confused with ACK/NAK
   BAD_BUOY,
   BUOYCLOCKNOTSET,
   OVERALLTIMEOUT,
   CHARTIMEOUT,
   BADCOMMAND,
   BADCHECKSUM,
   BADRESPONSE,
   BADXMODEMSEND,
   BADXMODEMRCV,
   BADLAUNCHERDISK,
   LAUNCHERDISKFULL,
   MAXBUOYARCHIVEBYTES,
   DATAFILECORRUPTED,
   BADBUOYDISK,
   BADGPS,
   NODATA,
   ESCAPE_KEY,
   ROT_ONE_TO_DATA,
   ROT_ONE_TO_LAUNCH,
   ROT_FORWARD,
   ROT_REVERSE,
   STOP_ROT,
   LAUNCH_FROM_DATA_POS,
   PUSH_BUOY_OUT,
   ARMS_OUT,
   RETRACT_ARMS,
   STOP_ARMS
};

enum  DataXferSWErrors  // errors in data transfer
{
   OKAY = 0,
   BAD_LAUNCHER,
   BUOY_NOT_TALKING,
   BUOY_FULL_OF_DATA,
   OVERALL_TIMEOUT,
   CHAR_TIMEOUT,
   BAD_COMMAND,
   BAD_CHECKSUM,
   BAD_RESPONSE,
   XMODEM_ERROR,
   LAUNCH_ERROR,
   LAUNCHER_DISK_FULL,
   UNKNOWN_ERROR,
};

enum  DataXferHWErrors  // errors in data transfer
{
   BUOY_DISK,
   BUOY_MEM,
   LAUNCHER_DISK,
   LAUNCHER_MEM
};

class LcXmodem {

public:

  LcXmodem(SerialDevice *device);

  virtual ~LcXmodem();

  int    send30Xmodem(BYTE *sendata, long numbytes);
  int    sendXmodem(BYTE *senddata, long numbytes);
  int    receiveXmodem(BYTE *r, long *p);
  void   resetSeqCount();

protected:

  SerialDevice *_device;

  void SendByte(BYTE);
  void SendChar(char);
  void FlushPacket();
  int GetCharTimeout(char *b, time_t timeout_sec);
  BYTE _packetData[PACKET_SIZE+5];
  int _nBytes;
  char _seqCount;
};

#endif    // on LCXMODEM_H
