⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 secs2blk.c

📁 SECS I, SECS II协议通讯源码
💻 C
字号:
/*
 * secs2blk.c
 *
 * Block read and write functions
 *
 * Code by David Lindauer, CIMple technologies
 *
 */
#include <setjmp.h>
#include <string.h>
#include "menus.h"
#include "secs2.h"
#include "units.h"

extern SECS1_BLOCK send_blocks[NUMBER_SEND_BLOCKS];
extern SECS1_BLOCK receive_blocks[NUMBER_RECEIVE_BLOCKS];
extern int device_id;
extern EXPECTED expected_blocks[NUMBER_EXPECTED_BLOCKS];
extern int last_expected_block;
extern jmp_buf secs2_jump;
extern int send_first;

// Set true if host is in metric mode
// Note this is a different variable from the touch-screen select, ergo
// the host must set it if it wants metric units
BOOL host_metric;

/* For ASCII input */
char receive_buf[MAX_RECEIVE_BUF];

/* True if no response is to be made */
BOOL send_nothing = FALSE;

/* Block being received, associated expected entry, position within block */
int receive_current = 0;
int receive_number = 0;

/* Header currently going out */
static SECS1_HEADER send_header;

/* Block currently being sent */
static int send_current = 0;
static int receive_draw;
static int receive_length;

/* Bookmark for above */
static int bm_number;
static int bm_current;
static int bm_draw;
static int bm_length;

/* Lock for multiple process contention */
static BOOL locked = FALSE;

// Current system bytes for send
static int system4, system3, system2, system1;

/*
* Wait around until send lock is released, then lock it
*/
void Secs2LockSend()
{
  while (locked) Pause();
    locked = TRUE;
}
/*
* Release lock
*/
void Secs2UnlockSend()
{
  locked = FALSE;
}
/*
* Receive 1 byte from buffer
* move to next block if necessary
  */
int RB(void)
{
  int retval;

  if (receive_current == NO_RECEIVE_MESSAGE)
    // IF current block undefined
    if (last_expected_block == 0)
      // error if no data anywhere
      return(NO_RECEIVE_MESSAGE);
    else {
      if (receive_number == RECEIVE_COMPLETE) {
        // error if undefined data
        Secs2BaddataError();
        /* Never returns */
      }
      // Skip until next block of non-zero length
      receive_current = expected_blocks[receive_number].firstblock;
      while ((receive_blocks[receive_current].length == 0)
          && !receive_blocks[receive_current].h.E)
        receive_current = receive_blocks[receive_current].nextblock;

      // If we never found one there is an error
      if ((receive_length = receive_blocks[receive_current].length) == 0)
        Secs2BaddataError();

      // Otherwise start at the beginning of the block
      receive_draw = 0;
      Pause();
    }

  // Get a byte
  retval = receive_blocks[receive_current].data[receive_draw];
  receive_draw++;

  if (!--receive_length)
    if (!receive_blocks[receive_current].h.E) {
      // Skip to next block if done with this
      receive_current = receive_blocks[receive_current].nextblock;
      receive_draw = 0;
      Pause();
    }
    else {
      // No more blocks, flag it
      receive_number = RECEIVE_COMPLETE;
    }
  return(retval);
}
// Receive a word
int Secs2bReceiveWord(void)
{
  return((RB()<<8)+RB());
}
// Receive an int ( DWORD)
int Secs2bReceiveInt(void)
{
  return((RW()<<16)+RW());
}
// Receive ASCII
PTEXT Secs2bReceiveAscii(int len)
{
  int i;
  if (len > MAX_RECEIVE_BUF) {
    Secs2BaddataError();
    /* Never returns */
  }
  for (i=0; i<len; i++)
    receive_buf[i] = (BYTE) RB();
  return(receive_buf);
}
// Receive floating
float Secs2bReceiveFloat(void)
{
  int i;
  float floatbuf;
  for (i=0; i< 4; i++)
    ((PTEXT )&floatbuf)[i] = (BYTE) RB();

  return(floatbuf);
}
// Receive double floating
double Secs2bReceiveDfloat(void)
{
  int i;
  double doublebuf;
  for (i=0; i< 8; i++)
    ((PTEXT )&doublebuf)[i] = (BYTE) RB();

  return(doublebuf);
}
/*
* Initialize for receive
  */
void Secs2bReceiveSetup(int number)
{
  receive_number = number;    // This expected block
  receive_current = RECEIVE_COMPLETE;       // No receive block selected
  receive_draw = 0;           // Start at beginning
}
/* Handle bookmarks */
// Set the position in the input stream so we can go back later
void Secs2bSetBookmark(void)
{
  bm_draw = receive_draw;
  bm_current = receive_current;
  bm_number = receive_number;
  bm_length = receive_length;
}
// Go back
void Secs2bRestoreBookmark(void)
{
  receive_draw = bm_draw;
  receive_current = bm_current;
  receive_number = bm_number;
  receive_length = bm_length;
}
/* Initialize a send header, first block */
void Secs2bInitheader(BOOL async, BOOL waiting, int stream,int func)
{
  send_nothing = FALSE;
  send_header.Udevice = (BYTE) (device_id >> 8);
  send_header.Ldevice = (BYTE) (device_id & 0xff);
  send_header.Umessage = (BYTE) stream;
  send_header.Lmessage = (BYTE) func;
  send_header.Ublock = 0;
  send_header.Lblock = 1;
  send_header.R = TRUE;		/* Sending TO host */
  send_header.W = (BYTE)waiting;
  send_header.E = 0;

  if (async) {
    /* Conformance for SEC-1 SYSTEM BYTES requirements */
    // For messages we originate
    if (++system4 == 0)
      if (++system3== 0)
        system4 = 1;
    send_header.system4 =(BYTE) system4;
    send_header.system3 =(BYTE) system3;
    send_header.system2 =(BYTE) system2;
    send_header.system1 =(BYTE) system1;
  }
  else {
    // For messages which are replies we just copy the system bytes from
    // the original message
    SECS1_HEADER *p;
    p =&receive_blocks[expected_blocks[receive_number].firstblock].h;
    send_header.system4 = p->system4;
    send_header.system3 = p->system3;
    send_header.system2 = p->system2;
    send_header.system1 = p->system1;
  }

  // Allocate a buffer
  send_current = Secs2AllocSend(TRUE);
}
/* Go to next block of a multiple block transfer */
void Secs2bNextheader(void)
{
  uint last_current;

  last_current = send_current;

  // Up the block number and allocate a new block
  if (++send_header.Lblock == 0)
    ++send_header.Ublock;
  send_current = Secs2AllocSend(FALSE);
  send_blocks[last_current].nextblock = send_current;
}
// Change the stream and func of the outgoing header
// Better do this BEFORE filling up the buffers or it won't register correctly
void Secs2bChangeheader( int stream, int func)
{
  send_header.Umessage = (BYTE) stream;
  send_header.Lmessage = (BYTE) func;
  send_blocks[send_current].h.Umessage = (BYTE) stream;
  send_blocks[send_current].h.Lmessage = (BYTE) func;
}
/*
* flush all blocks marked for send
*/
void Secs2bFlagSent(void)
{
  // Quit if someone deallocated the message
  if (send_first == BTP_NO_FIRST) return;

  if (send_nothing) {
  // IF sending nothing just deallocate the blocks
    send_nothing = FALSE;
    BtpUnallocAll();
  }
  else
    if (send_current == send_first) {
      // IF only one block mark it for send
      send_blocks[send_current].h.E = TRUE;
      send_blocks[send_current].ready_to_send = TRUE;
    }
    else {
      if (send_blocks[send_current].length == 0) {
        // IF multiple blocks and nothing put in the last block back up one
        int pos;
        pos = send_first;
        while (send_blocks[pos].nextblock != (unsigned) send_current)
          pos = send_blocks[pos].nextblock;

        // Now deallocate the empty block by pretending it was the first block
        // allocated and deallocating everything
        send_first = send_current;
        BtpUnallocAll();
        send_current = pos;
      }
      // Mark last block, then mark all as ready to send
      send_blocks[send_current].h.E = TRUE;
      send_blocks[send_current].ready_to_send = TRUE;
      do {
        send_blocks[send_first].ready_to_send = TRUE;
        send_first = send_blocks[send_first].nextblock;
      } while (send_first != send_current);
    }
}
/*
* Allocate send buffer
*/
int Secs2AllocSend(BOOL first)
{
  int retval;

  // Get a buffer, return an error if our send buffers are full
  if ((retval = BtpAllocSend(first)) == BTP_ALLOC_ERR)
    Secs2ToomuchdataError();

  // Initialize it
  send_blocks[retval].length = 0;
  send_blocks[retval].h = send_header;

  Pause();
  return(retval);
}
/*
* Send a byte,
* Move to next buffer if necessary
  */
void Secs2bSendByte(BYTE data)
{
  BYTE * len;

  // Put byte
  len = &send_blocks[send_current].length;
  send_blocks[send_current].data[(*len)++] = data;

  // If done, get a new block
  if ((*len) == MAX_BLOCK_LEN)
    Secs2bNextheader();
}
// Send a word
void Secs2bSendWord(uint data)
{
  SB((BYTE)(data >> 8));
  SB((BYTE)(data & 0xff));
}
// Send an int (DWORD)
void SI( uint data)
{
  SB((BYTE)(data >> 24));
  SB((BYTE)((data >> 16) & 0xff));
  SB((BYTE)((data >> 8) & 0xff));
  SB((BYTE)(data & 0xff));
}
// Send ASCII
void Secs2bSendAscii( PTEXT data, int len)
{
  int i;
  for (i=0; i<len; i++)
    SB(data[i]);
}
// Send Floating point
void Secs2bSendFloat(float data)
{
  int i;
  for (i=0; i<4 ;i++)
    SB(((PTEXT ) &data)[i]);
}
// Send double
void Secs2bSendDfloat(double data)
{
  int i;
  for (i=0; i<8 ;i++)
    SB(((PTEXT ) &data)[i]);
}
/* Initialize for first send */

void Secs2bSendInit(void)
{
  // System bytes = 0
  system4 = 0;
  system3 = 0;
  system2 = 0;
  system1 = 0;
  // Init header data
  Secs2bInitheader(FALSE, FALSE,0,0);

  // Deallocate any blocks sitting around
  BtpFlushSend();
}
// Routine to send a PRESET value
void Secs2bSendValue(INTVAL data, int units)
{
  // Convert to metric if necessary
  if (host_metric) {
    PRESET current;
    current.units = units;
    current.value = data;
    data = ConvertToMetric(&current);
  }

  if (units & UNI_TIME) {
    int value;

    // Time values are reported as integers
    value = ((int)data/100)*60 + ((int)data % 100);
    IF_INT(1);
    SI(value);
  }
  else
    if (units & UNI_INTEGER) {
      int value;

      // So are integer values
      value = (int) data;
      IF_INT(1);
      SI(value);
    }
    else {
      // But other values are all single precision floating point
      IF_FLOAT(1);
      SF((float)data);
    }
}
// Receive a value
INTVAL Secs2bReceiveValue(int units)
{
  INTVAL data;
  if (( units & UNI_TIME) || (units & UNI_INTEGER)) {
    // Read in a time or integer value
    FV(FM_INT);
    data = (INTVAL) RI();
    if (units & UNI_TIME)
      // adjust if is a time value
      data = (INTVAL) ((((int)data)/60)*100 + (((int)data) %60));
  }
  else {
    // Otherwise we are getting a floating point value
    FV(FM_FLOAT);
    data = (INTVAL)RF();
  }

  // Now convert to english if in metric mode
  if (host_metric) {
    PRESET current;
    current.units = units;
    current.value = data;
    data = ConvertToEnglish(&current);
  }
  return(data);
}
// Send units text
void Secs2bSendUnits(int units)
{
  PTEXT theUnits;
  int temp;

  // Get the SEMI units text
  theUnits = GetUnitText(units, UNI_SEMI);

  // Put it out
  IF_ASCII(temp = strlen(theUnits));
  SA( theUnits, temp);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -