📄 secs2blk.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(¤t);
}
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(¤t);
}
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 + -