📄 secs2str.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 + -