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

📄 secs2str.c

📁 SECS I, SECS II协议通讯源码
💻 C
字号:
/*
 * secs2str.c
 *
 * Stream handling functions, generic, & secs2 main routine
 *
 *
 * Code by David Lindauer, CIMple technologies
 *
 */
#include <stdio.h>
#include <setjmp.h>
#include "secs2.h"
#include "menus.h"

extern SECS1_BLOCK receive_blocks[NUMBER_RECEIVE_BLOCKS];
extern EXPECTED expected_blocks[NUMBER_EXPECTED_BLOCKS];
extern int last_expected_block;
extern int receive_current, receive_number;
extern BOOL any_data;
extern BOOL secs1_initted;
extern BOOL secs1_retrylimit;
extern int EstablishCommunicationsTimeout;
extern NUMBER secspre_establish;
extern int interblock_time, reply_time;
extern NUMBER secspre_interblock, secspre_reply;
extern BOOL discarding_duplicates;
extern SECS_TIMER to_interchar, to_protocol;
extern NUMBER secspre_interchar, secspre_protocol;
extern int retries, device_id;
extern COMMSTATES CommStates;
extern NUMBER secspre_retries, secspre_devid;
extern MODIFY secspre_baud;
extern int baudlist[];
extern PASSFUNC streamlist[], streaminit[];
extern BOOL host_metric;
extern int version;
extern CTEXT secs_softrev[SECS2_SOFTLEN+1];
extern BOOL send_nothing;

INTVAL secsdef_establish[] = {((INTVAL)TO_ESTABLISH) / 10};
INTVAL secsdef_interblock[] = {((INTVAL)TO_INTERBLOCK) / 10};
INTVAL secsdef_reply[] = {((INTVAL)TO_REPLY) / 10};
INTVAL secsdef_interchar[] = {((INTVAL) TO_INTERCHAR) /10};
INTVAL secsdef_protocol[] = {((INTVAL) TO_PROTOCOL) /10};
INTVAL secsdef_retries[] = {(INTVAL) DF_RETRY};
INTVAL secsdef_devid[] = {(INTVAL) DF_DEVID};

/* Jump here on errors */
jmp_buf secs2_jump;

/* Error queue, insert and delete pointers */
SECS2_ERROR error_list[NUMBER_SECS2_ERRORS];
int err_insert, err_delete;

/* Current block being sent */
int send_current;

// True to prevent contention between seperate processes that wish to send
// data
BOOL locked;

/* Format byte received */
static int format_byte;

/* Reading from this expected list */
static int expected_read;

/*
* Pull an error from the queue and send it out
*/
void Secs2ErrorWrite(void)
{
  int i;
  while (err_insert != err_delete) {
    // Make header
    Secs2bInitheader(TRUE,FALSE,error_list[err_delete].stream,
            error_list[err_delete].func);
    // Put out the header which was in error
    IF_BINARY(10);
    for (i=0; i<10; i++)
      SB(*(((BYTE *) &error_list[err_delete].h) + i));
    // Flag data as sent
    Secs2bFlagSent();

    // Flip to next error
    if (++err_delete >= NUMBER_SECS2_ERRORS)
      err_delete = 0;
  }
}
/*
* Put an error in the error queue
*/
void Secs2ErrorInsert(int stream, int func, SECS1_HEADER *h, int expectedNumber)
{
  // Save stream & func & header
  error_list[err_insert].stream = stream;
  error_list[err_insert].func = func;
  error_list[err_insert].h = *h;

  // Bump to next error and get rid of the associated receive blocks
  if (++err_insert >= NUMBER_SECS2_ERRORS)
    err_insert = 0;
  MraUnregisterExpected(expectedNumber);
}
/* Register a bad data error
*/
void Secs2BaddataError(void)
{
  // Which is, too much data or bad format for data
  BtpUnallocAll();
  Secs2ErrorInsert(ST_ERRORS,ER_BADDATA,
          &receive_blocks[receive_current].h, expected_read);
  longjmp(secs2_jump,1);
}
/*
* Unrecognized function error
*/
void Secs2UnrecfunError(void)
{
  BtpUnallocAll();
  Secs2ErrorInsert(ST_ERRORS,ER_UNRECFUN,
          &receive_blocks[expected_blocks[expected_read].firstblock].h,
          expected_read);
  longjmp(secs2_jump,1);
}
/*
* Unrecognized stream error
*/
void Secs2UnrecstreamError(void)
{
  BtpUnallocAll();
  Secs2ErrorInsert(ST_ERRORS,ER_UNRECSTR,
          &receive_blocks[expected_blocks[expected_read].firstblock].h,
          expected_read);
  longjmp(secs2_jump,1);
}
/*
* Too much data error
*/
void Secs2ToomuchdataError(void )
{
  BtpUnallocAll();
  Secs2ErrorInsert(ST_ERRORS,ER_2MUCHDAT,
          &receive_blocks[receive_current].h,expected_read);
  longjmp(secs2_jump,1);
}
// Exit with error if there is data other than the header
void Secs2CheckHeaderOnly(void)
{
  SECS1_BLOCK *p;
  p = &receive_blocks[receive_current = expected_blocks[expected_read].firstblock];
  if (!p->h.E || p->length)
    Secs2ToomuchdataError();
  receive_number = RECEIVE_COMPLETE;
}
/* Get a Format byte and length from buffer
*/
int Secs2bReceiveFormat(void)
{
  int format,retval;

  // Get the format
  format = RB();

  // Get the length of the data
  format_byte = format & 0xfc;
  switch (format & 3) {
    case 0:
            Secs2BaddataError();
            /* Never returns */
    case 1:
            retval = RB();
            break;
    case 2:
            retval = RW();
            break;
    case 3:
            retval = (RB() << 16) + RW();
            break;
  }
  return(retval);
}
/*
* Error if the expected format byte is not here
  */
int Secs2bFormatValidate(int format)
{
  int retval;
  retval = Secs2bReceiveFormat();
  if (format != format_byte) {
    Secs2BaddataError();
    /* Never returns */
  }
  return(retval);
}
/*
* Put out a format byte and length
*/
void Secs2Format(uint command, uint len)
{
  if (len > 65535) {
    SB((BYTE)(command+3));
    SB((BYTE)(len >> 16));
    SW(len & 0xffff);
  }
  else
    if (len > 255) {
      SB((BYTE)(command+2));
      SW(len);
    }
    else {
      SB((BYTE)(command+1));
      SB((BYTE)(len));
    }
}
/*
* Routine used by stream handlers to vector off to the appropriate
* function handler
*/
void Secs2FuncDispatch(int number, PASSFUNC *funclist)
{
  BOOL done = FALSE;
  int i = 0, func;


  func = receive_blocks[expected_blocks[number].firstblock].h.Lmessage;
  expected_read = number;

  while (!done) {
    // Can't handle func 0; if at end of list give an error
    if (( func == 0) || (funclist[i].val == 0))
      Secs2UnrecfunError();
    else
      if (funclist[i].val == func) {
        done = TRUE;
        (* funclist[i].func)(0);
      }
    i++;
  }
}
/*
* Vector off to the appropriate stream handler
*/
void Secs2StreamDispatch(int number)
{
  BOOL done = FALSE;
  int i = 0, stream, func;

  stream = receive_blocks[expected_blocks[number].firstblock].h.Umessage;
  func = receive_blocks[expected_blocks[number].firstblock].h.Lmessage;

  // Lock out asynchronous stuff
  Secs2LockSend();

  // Init for send and receive
  Secs2bReceiveSetup(number);
  Secs2bInitheader(FALSE,FALSE,stream,func+1);
  while (!done) {
    if ((stream == 0) || (streamlist[i].val == 0))
      Secs2UnrecstreamError();
    else
      if (streamlist[i].val == stream) {
        done = TRUE;
        (* streamlist[i].func)(number);
      }
    i++;
  }

  // See if too much data was received
  if (receive_number != RECEIVE_COMPLETE)
    Secs2ToomuchdataError();
  else
    Secs2bFlagSent();

  // Clean up
  Secs2UnlockSend();
  MraUnregisterExpected(number);
}
// power-up routine
void Secs2pup(BOOL power_up)
{
  int i = 0;

  // Initialize the revision number
  sprintf(secs_softrev,"%3d.%02d", version/100, version %100);

  if (power_up) {

    host_metric = FALSE;

    err_insert = 0;
    err_delete = 0;

    send_nothing = FALSE;

    receive_current = 0;
    receive_number = 0;

    send_current = 0;

    locked = FALSE;

    // Initialize for SECS2 sends
    Secs2bSendInit();

  }
  // Call stream init routines
  while (streaminit[i].val)
    (streaminit[i++].func)(power_up);
}
// Secs 2 idle process
void Secs2Idle(void)
{
  setjmp(secs2_jump);
  Secs2EstablishCommunications();

  // We'll return here after any errors
  setjmp(secs2_jump);
  Secs2UnlockSend();
  while (TRUE) {
    int i;
    Pause();

    // Write out any errors
    Secs2ErrorWrite();

    // Service any expected block which needs it
    for (i=0; i< last_expected_block; i++)
      switch (expected_blocks[i].status) {
        case MRA_COMPLETE:
                Secs2StreamDispatch(i--);
                break;
        case MRA_ABORT:
                MraUnregisterExpected(i--);
                break;
      }

    // Now if SECS1 couldn't succeed with multiple retries reestablish communications
    if (secs1_retrylimit) {
      BtpFlushSend();
      secs1_retrylimit = FALSE;
      Secs2EstablishCommunications();
    }
  }
}
// Synchronize SECS 1 & SECS2 variables with the menus
void Secs2SyncPresets(int mode)
{
  if (mode == MF_PRESET_CHANGE) {
    int last_baud = CommStates.BaudRate;
    interblock_time = (int) (secspre_interblock.value * 10);
    reply_time = (int) (secspre_reply.value * 10);
    to_interchar.length = (int) (secspre_interchar.value * 10);
    to_protocol.length = (int) (secspre_protocol.value * 10);
    EstablishCommunicationsTimeout = (int) (secspre_establish.value * 10);
    retries = (int) (secspre_retries.value);
    device_id = (int) (secspre_devid.value);
    CommStates.BaudRate = baudlist[secspre_baud.value];
    if (CommStates.BaudRate != last_baud)
      Secs1CharInit();
  }
}

⌨️ 快捷键说明

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