/*
 ******************************************************************************
 *  Copyright 1994 DeltaLink bv. All Rights Reserved.
 ******************************************************************************
 *
 * DeltaLink Modicon Modbus Plus protocol library
 *
 * File: mpencode.c
 *
 * This file contains the implementation of the Modicon Modbus Plus protocol
 * conform the DeltaLink communication interface for FactoryLink.
 *
 */
#ifdef NT
#pragma warning( disable : 4201 4214 4121)
#include <windef.h>
#endif

#include	<stdlib.h>
#include	<stdio.h>
#include	<string.h>
#include	<time.h>

#include	<format.h>

#include	<netbios.h>
#include	<netlib.h>

#include	<mbp.h>

#include	<mbcom.h>


/* defines for encoded data */

#define E_OUTPUT         'O'        /* output */
#define E_INPUT          'I'        /* input */
#define E_ANALOG         'A'        /* analog */
#define E_HREG           'H'        /* holding registers */

static char mtype[] = { E_OUTPUT, E_INPUT, '?', E_ANALOG, E_HREG};

#define E_BIT            'F'        /* bit */
#define E_BYTE           'B'        /* byte */
#define E_DL             'L'        /* left byte */
#define E_DR             'R'        /* right byte */
#define E_WORD           'W'        /* word */
#define E_LONG           'D'        /* long */

/*-----------------------------------------------------------------------------
 * FUNCTION: int mpencode( JOB *, DS *, DS *, uint, uint, void *)
 *
 * PURPOSE:
 *
 * This function sets the receive and send buffer and then performs a FETCH operation
 * with the SIEMENS PLC.
 *
 -----------------------------------------------------------------------------*/
int mpencode( JOB *job, DS *enc_ds, DS *dest, uint code, uint start, void *val) {

  ENCODE *encode = ( ENCODE *)( ( char *)job->dev->buf[ COM_WRITE] + USER_BUF_START);
  char   *data = ( char *)encode + sizeof( ENCODE);


  /* set the addressing information for the encoded write */

  memcpy( &job->dataset, enc_ds, sizeof( DS));

  /*
   * save data to destination
   */
  memcpy( data, ( char *)val, Com_Get_Tx_Len( job));

  /* mark a new incoming command for PLC */

  encode->chg_flag = 0xff;

  /* set the org, type and address of the element */

  encode->org     = mtype[ dest->type];

  #ifdef HOST_LOW_2_HIGH
	_swab( ( char *)&start, ( char *)&encode->address, 2);
  #else
	encode->address = ( uchar)start;
  #endif

  job->len += sizeof( ENCODE);
  job->dataset.len = job->len / job->dataset.boundary;

  /*
   * evaluate the code parameter
   */
  if( code < CDE_NIBBLE) {                   /* perform a bit operation */

    encode->type = E_BIT;

    /*
     * adjust the bit number by adding one
     */
		encode->bit  = ( uchar)(code - CDE_B0_15 +1);
  }
  else if( code < CDE_BYTE)
    return MP_NOT_ENCODE;

  else if( code < CDE_SIGNED) {

    switch( code) {

      case CDE_BYTE:
      case CDE_UBYTE:

        encode->type = E_DR;

        break;

      case CDE_BYTE + 8:
      case CDE_UBYTE + 8:

        encode->type = E_DL;

        break;
      default:
        return MP_NOT_ENCODE;
    }
  }
  else if( code < CDE_LONG) {

    /*
     * the encoded value received is always as a value in the HOST format
     */
    switch( code) {

      case CDE_SIGNED:
      case CDE_UNSIGNED:

        encode->type = E_WORD;
        break;

      default:
        return MP_NOT_ENCODE;
    }

  }
  else if( code < CDE_DOUBLE_IEEE_FLT) {

    encode->type = E_LONG;

  }
  else
    return MP_NOT_ENCODE;

  #ifdef INTEL
  swab( ( char *)encode, ( char *)encode, sizeof( ENCODE));
  #endif

  return 0;
}
