📄 stream2.c
字号:
/*
* Stream2.c
*
* preset handling, service program load/save, commands, time, reset, loopback
*
*
* Code by David Lindauer, CIMple technologies
*
*/
#include <string.h>
#include <stdio.h>
#include "menus.h"
#include "secs2.h"
#include "units.h"
extern char secs_model[6];
extern PR_STRUC secs_presetlist[];
extern BOOL *secs_cmdlist[];
extern uint language;
extern char **unitext[];
extern int enquire_list[NUMBER_ENQUIRIES];
extern int receive_number;
extern BOOL reset_disable;
extern int reset_type;
extern PROGFUNC secs2_spl_functions[];
/* Number of preset specifiers */
static int number_preset = 0;
/* Number of command specifiers */
static int number_cmd = 0;
/* Response code for changing preset values */
static int response_code;
/* Used during service program i/o */
static CTEXT spid[SPID_LENGTH+1];
static PLFUNC spl_func;
/*
* Note: a PRESET is the same as a SELECT variable;
* an ACTUAL is the same as a STATUS variable
* Unlike the MENUS portion of the code which can only handle
* FLOATING format, secs-2 protocol can handle virtually any format.
* Thus binary, integer, and floating data can be sent intermixed
*
* the routines which put values out and get values in are largely
* untested for other than the deffault format
*/
// Service Program routines will mostly work if the data transfer routines are
// written for the specific program type
// Refer to code for stream 8 code for an idea how to do this
// Routine to load the SPID
static void LoadSpid(void)
{
int i;
// Verify data
if (FV(FM_BINARY) != SPID_LENGTH)
Secs2BaddataError();
// Read in string
for (i=0;i<SPID_LENGTH;i++)
spid[i] = (BYTE) RB();
spid[SPID_LENGTH] = '\0';
}
// Routine to parse the SPID and return a function to load/save data
static BOOL GetSpidFunc(void)
{
PROGFUNC *spv = secs2_spl_functions;
// Invalidate Grants whenever a new SPID comes in
spl_func = 0;
while(spv->validate) {
if ((*spv->validate)(spid)) {
// Get the exec routine, this being non-zero will allow it to be called
spl_func = spv->exec;
return(TRUE);
}
spv++;
}
return(FALSE);
}
// See if we have enough space to load a program
// SERVICE PROGRAM LOAD ENQUIRE
static void S2f1(void)
{
BYTE return_code = GRANT_OK;
int length;
// Get the SPID and the requested length
LoadSpid();
if (FV(FM_UINT) != 4)
Secs2BaddataError();
length = RI();
// See if we recognize this SPID and there is enough buffer space
// for reception
if (GetSpidFunc()) {
// Valid SPID, now see if length + FM_BYTE format is available
if (length + 4 > MraFreeBuffers()*MAX_BLOCK_LEN)
return_code = GRANT_NOSPACE;
}
else
return_code = GRANT_BADSPID;
// If error, disallow grant
if (return_code != GRANT_OK)
spl_func = 0;
// Now tell the host
IF_BINARY(1);
SB(return_code);
}
// Get a program
// SERVICE PROGRAM SEND
static void S2f3(void)
{
BYTE return_code;
// if no GRANT was requested return with an error
if (spl_func == 0) {
return_code = SPAACK_NOGRANT;
receive_number = RECEIVE_COMPLETE;
}
else
return_code = (*spl_func)(SPL_SEND);
// Can't do it again
spl_func = 0;
// Out the return_code
IF_BINARY(1);
SB(return_code);
}
// Send a program
// SERVICE PROGRAM LOAD REQUEST
static void S2f5(void)
{
// Get the SPID
LoadSpid();
if (GetSpidFunc())
(*spl_func)(SPL_LOAD);
else
IF_BINARY(0);
// Invalidate send requests
spl_func = 0;
}
// Run a program
// SERVICE PROGRAM RUN SEND
static void S2f7(void)
{
BYTE return_code;
// Get the SPID and run the program
LoadSpid();
if (GetSpidFunc())
return_code = (*spl_func)(SPL_RUN);
else
return_code = CSAACK_BADSPID;
// Not intended for GRANTS
spl_func = 0;
// Send the return code
IF_BINARY(1);
SB(return_code);
}
/*
* Put out a preset value
*/
static void PrPutValue(int number)
{
switch (secs_presetlist[number].units) {
int temp;
case UN_BINARY:
IF_BINARY(1);
SB(* ((BYTE *) (secs_presetlist[number].value)));
break;
case UN_BOOL:
IF_BOOL(1);
SB(* ((BYTE *) (secs_presetlist[number].value)));
break;
case UN_ASCII:
IF_ASCII(temp = strlen((char *) secs_presetlist[number].value));
SA((char *) secs_presetlist[number].value,temp);
break;
case UN_MODE:
IF_INT(1);
SI(((MODIFY *)secs_presetlist[number].value)->value);
break;
case UN_INT:
IF_INT(1);
SI(* ((int *) (secs_presetlist[number].value)));
break;
case UN_FLOAT:
IF_FLOAT(1);
SF(* ((float *) (secs_presetlist[number].value)));
break;
default:
Secs2bSendValue(((PREREC *)secs_presetlist[number].value)->preset->value,
((PREREC *)secs_presetlist[number].value)->preset->units);
break;
}
}
/*
* Put out a preset low limit
*/
static void PrPutLowLim(int number)
{
switch (secs_presetlist[number].units) {
case UN_BINARY:
IF_BINARY(1);
SB(0);
break;
case UN_BOOL:
IF_BOOL(1);
SB(0);
break;
case UN_ASCII:
IF_ASCII(0);
break;
case UN_MODE:
IF_INT(1);
SI(0);
break;
case UN_INT:
IF_INT(1);
SI(0);
break;
case UN_FLOAT:
IF_FLOAT(1);
SF(0.0F);
break;
default:
Secs2bSendValue( (float) ((PREREC *)secs_presetlist[number].value)->lolim,
((PREREC *)secs_presetlist[number].value)->preset->units);
break;
}
}
/*
* Put out a preset high limit
*/
static void PrPuthilim(int number)
{
switch (secs_presetlist[number].units) {
case UN_BINARY:
IF_BINARY(1);
SB(255);
break;
case UN_BOOL:
IF_BOOL(1);
SB(255);
break;
case UN_ASCII:
IF_ASCII(0);
break;
case UN_MODE:
IF_INT(1);
SI(((MODIFY *)secs_presetlist[number].value)->limit-1);
break;
case UN_INT:
IF_INT(1);
SI(0);
break;
case UN_FLOAT:
IF_FLOAT(1);
SF( 0.0F);
break;
default:
Secs2bSendValue( (float) ((PREREC *)secs_presetlist[number].value)->hilim,
((PREREC *)secs_presetlist[number].value)->preset->units);
break;
}
}
/*
* Put out a preset default
*/
static void PrPutDefault(int number)
{
switch (secs_presetlist[number].units) {
case UN_BINARY:
IF_BINARY(1);
SB(0 );
break;
case UN_BOOL:
IF_BOOL(1);
SB(0);
break;
case UN_ASCII:
IF_ASCII(0);
break;
case UN_MODE:
IF_INT(1);
SI(0);
break;
case UN_INT:
IF_INT(1);
SI(0);
break;
case UN_FLOAT:
IF_FLOAT(1);
SF(0.0F);
break;
default:
Secs2bSendValue((float) ((PREREC *)secs_presetlist[number].value)->preset->value,
((PREREC *)secs_presetlist[number].value)->preset->units);
break;
}
}
/*
* Receive a preset value
* Note that receiving binary or ascii strings is dangerous because no
* limit checking is done on the incoming length
*/
static void PrGetValue(BOOL changing)
{
uint i, len;
int number, itemp;
float ftemp;
if (FV(FM_LIST) != 2)
Secs2BaddataError();
if (FV(FM_UWORD) != 2)
Secs2BaddataError();
number = RW();
if (number >= number_preset) {
response_code = EAC_BADCONST;
return;
}
switch (secs_presetlist[number].units) {
case UN_BINARY:
len = FV(FM_BINARY);
for (i=0; i<len; i++)
if (changing)
*(((BYTE *)secs_presetlist[number].value)+i) = (BYTE) RB();
else
RB();
break;
case UN_BOOL:
FV(FM_BOOL);
if (changing) {
if (RB())
*((BOOL *)secs_presetlist[number].value) = TRUE;
else
*((BOOL *)secs_presetlist[number].value) = FALSE;
}
else
RB();
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -