/****************************************************************************/
/* Copyright (c) 2015 MBARI                                                 */
/* MBARI Proprietary Information. All rights reserved.                      */
/****************************************************************************/
/* Summary  : Power Buoy Data Logger CANBus instrument reader class         */
/* Filename : CanBus.hpp                                                    */
/* Author   : Henthorn                                                      */
/* Project  : Power Buoy                                                    */
/* Version  : 1.0                                                           */
/* Created  : 04/20/2015                                                    */
/* Modified :                                                               */
/* Archived :                                                               */
/****************************************************************************/
/* Modification History:                                                    */
/****************************************************************************/
/*                                                                          */
/* This class is the data source reader for the CANBus instruments on the   */
/* Power Buoy. It is derived from the generic FileSource class.             */
/*                                                                          */
/****************************************************************************/

#ifndef _CANBUS_
#define _CANBUS_

#include <linux/can.h>
#include <linux/can/raw.h>

#include "FileSource.hpp"

class CSVWriter;

class CanBus : public FileSource
{

public:

   // The data contained in a Power Controller CanBUS frame
   //
   struct PC_Record {
      //float  can_time;
      short  seq_num;
      float  rpm;
      float  sd_rpm;
      float  voltage;
      float  power;
      float  bcurrent;
      float  lcurrent;
      float  torque;
      float  diff_press;
      float  bridgedc;
      float  loaddc;
      float  scale;
      float  retract;
      float  target_v;
      unsigned short  status;
      float  sd_rpm_target;
   };

   // The data contained in a Battery Controller CanBUS frame
   //
   struct BC_Record {
      //float  can_time;
      short  seq_num;
      float  voltage;
      float  ips;
      float  vbalance;
      float  vstopcharge;
      float  gfault;
      float  hydrogen;
      unsigned short  status;
   };

#if 0
Packet 0:  (unchanged)
LoadCell  :  Rangefinder : UpperSpringPressure : Lower Spring Pressure

Scaling as before:

Packet 1:  (entirely changed)
epoch most sig. word:  epoch least sig word :  salinity most sig. word :  salinity least significant word

When re-assembled, the epoch seconds is a long that is seconds since 1970 UTC and can just be logged as that.
When re-assembled, the salinity is an unsigned long that is salinity in S/m multiplied by 1000000.  i.e. micro Siemens/m

Packet 2: (only first integer is changed)
temperature  :  Status  :  0  :   0

Here, temperature is an integer representing milli-degrees C.  i.e.  Divide by 1000 to get degrees C.

#endif

   // The data contained in a Spring Controller CanBUS frame
   //
   struct SC_Record {
      //float  can_time;
      short  seq_num;
      short  load;
      float  range;
      float  upsi;
      float  lpsi;
      unsigned long epoch;
      float  salinity;
      float  temperature;
      short  status;
   };

   // The data contained in a Rudder Controller CanBUS frame
   //
   struct RC_Record {
      //float          can_time;
      short          seq_num;
      float          x_vel;       // m/s
      float          y_vel;
      float          z_vel;
      float          pressure;    // psi
      char           b_amp1;      //counts
      char           b_amp2;
      char           b_amp3;
      char           b_cor1;      // percentage
      char           b_cor2;
      char           b_cor3;
      float          target;      // heading data (-180 to +180)
      float          measured;
      float          filtered;
      short          rudder;      // counts
      float          ram;         // inches
      float          qtn[4];
      float          mag[3];      // gauss
      unsigned short status;      // bit field
      float          ang_rate[3]; // rad/sec
      unsigned short vpe_status;  // bit field
      float          accel[3];    // m/sec^2
      short          position;    // Rudder position
      float          p_gain;
      float          i_gain;
      float          d_gain;
      float          period;      // update period
      unsigned short ftc;         // Filter time constant
   };



   // Open a connection to the data source.
   //
   CanBus(const char* cansock, CSVWriter* w = NULL);

   ~CanBus();

   // Return 0 if full record was read
   // Otherwise, return the number of bytes still needed for
   // a full record.
   // Return < 0 on error.
   //
   int read_data(char verbose);

   // Return the latest full data record in the buffer supplied by the caller.
   // Return the number of bytes written to the buffer (0 or more).
   // Return < 0 on error.
   //
   int get_record(const char *buffer);

protected:

   unsigned create_mask(unsigned a, unsigned b);
   void make_masks() {
      _seq_mask  = create_mask(0,8);
      _data_mask = create_mask(9,13);
      _src_mask  = create_mask(14,17);
   }



   // Handle Power Controller frame
   //
   int handle_power_msg(struct can_frame);

   // Handle Pneumatic Spring Controller frame
   //
   int handle_spring_msg(struct can_frame);

   // Handle Battery Controller frame
   //
   int handle_battery_msg(struct can_frame);

   // Handle Battery Controller frame
   //
   int handle_rudder_msg(struct can_frame);

   char* _cansock;   // e.g., "can0", "can1"
   int   _curr_sc_seq;
   int   _curr_rc_seq;

   unsigned _seq_mask, _data_mask, _src_mask;

   struct CanBus::PC_Record  _pc_record;
   struct CanBus::BC_Record  _bc_record;
   struct CanBus::SC_Record  _sc_record;
   struct CanBus::RC_Record  _rc_record;

   CSVWriter* _logger;

   char _verbose;
};

#endif
