/****************************************************************************/
/* Copyright 2014 MBARI.                                                    */
/* Monterey Bay Aquarium Research Institute Proprietary Information.        */
/* All rights reserved.                                                     */
/****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <time.h>

#include <modbus.h>

#define SLAVE_ID        0x01
#define DEFAULT_BAUD    19200L    
#define TOTAL_COILS     16
#define SAMPS           128
#define MODBUS_DEBUG    FALSE
void byteSwap16(char* bytes);

int main(int argc, char* argv[])
{
   int ret;
   int reg_addr;
   uint16_t dest[8];
   double average,sum;
   double temp;
   modbus_t *ctx;
   long baud;
   
   uint16_t input;
   
   time_t tm_val;
   char buff[64];
   struct tm* tm_info;
   

   if ( argc < 3)
   {
      printf("LOOP_TEST compiled with libmodbus version %s on %s at %s\n\n", 
             LIBMODBUS_VERSION_STRING, __DATE__, __TIME__);

      printf("Usage: loop_test port address [baud]\n");
      printf("Default baud is %ld\n\n", DEFAULT_BAUD);
      printf("Example:\n");
      printf("./loop_test com1 0x1FF\n");

      return -1;
   }

   /* get reg address */
   reg_addr = (int)strtol(argv[2], NULL, 10)-1;//adjust for libmodbus address input shift. 
    
   /* set the baud rate */    
   baud = DEFAULT_BAUD;

   sum = 0;

   if ( argc == 4 )
   {
      baud = atol(argv[3]);

      switch ( baud )
      {
        case 9600:   break;
        case 19200:  break;
        case 38400:  break;
        case 57600:  break;
        case 115200: break;
        default: 
            printf("Invalid baud: %ld\n", baud);
            printf("Supported bauds: 9600, 19200, 38400, 57600, 115200\n");
            return -1;
      }
   }

   /* init the modbus interface */
   ctx = modbus_new_rtu(argv[1], baud, 'N', 8, 2);

   if (ctx == NULL) 
   {
      fprintf(stderr, "Unable to allocate libmodbus context\n");
      return -1;
   }

   modbus_set_debug(ctx, MODBUS_DEBUG);
   modbus_set_error_recovery(ctx, MODBUS_ERROR_RECOVERY_LINK);
   modbus_set_slave(ctx, SLAVE_ID);

   if (modbus_connect(ctx) == -1) 
   {
      fprintf(stderr, "ERROR Connection failed: %s\n",
              modbus_strerror(errno));
      modbus_free(ctx);
      return -1;
   }

#define RD_REG  1
   
   for(int i=0;i<SAMPS;i++)
   {
       ret = modbus_read_registers(ctx, reg_addr, RD_REG, dest);

       input = dest[0];
       //temp /= 10.0;
      
      /* check for errors */
      if (ret != RD_REG) 
      {
          printf("FAILED\n");
         
        /* Close the connection */
        modbus_close(ctx);
        modbus_free(ctx);

        time(&tm_val);
        tm_info = localtime(&tm_val);

        strftime(buff, 64, "%Y:%m:%d %H:%M:%S\n", tm_info);
        printf(buff);        
        
        return -1;
      }
      else
      {
        //add to samps array
        sum += (double)input; 
        temp = (2.9*((double)input)+1.7-250)/28;
        printf("ADDRESS 0x%04X, REG 0x%04X, INPUT %hu, TEMP %4.4f\n", reg_addr, dest[0], input,temp);
        ret = 0;
      }
   
   }
    
   average = sum / SAMPS;
   printf("AVERAGE COUNTS OVER %i SAMPS: %4.1f\n",SAMPS,average);

   /* Close the connection */
   modbus_close(ctx);
   modbus_free(ctx);

   return ret;
}

void byteSwap16(char* bytes)
{
    char swap_buff[2];
    
    swap_buff[0] = bytes[0];
    swap_buff[1] = bytes[1];
    
    bytes[0] = swap_buff[1];
    bytes[1] = swap_buff[0];
}

