📄 plc2.c
字号:
/*
* Released under the GNU GPL. See http://www.gnu.org/licenses/gpl.txt
*
* This program is part of TinyPLC
*
* TinyPLC is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundatation; version 2 of the License.
*
* TinyPLC is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
/*
* My thanks to my employer, Athena Controls (www.athenacontrols.com)
* for allowing me to open source this project.
*/
/*
* TinyPLC kernel
* Processor: Atmel MEGA1281 or Atmel MEGA2561
* Compiler: Codevision AVR C compiler, 1.24.8e
*
* TinyPLC editor/compiler
* Processor: PC-clone, VESA video (mode 0x105, 1024x768x256)
* Compiler: DeSmet C, version 2.51 (PCC version 1.2)
*
* Revision history:
* Programmer Date Comments
* ---------------- --------- ---------------------------------------------
* William Couture 3/19/2006 Original code
* William Couture 9/13/2006 Modify for GPL release
*/
#include "plc.h"
int getnumber(str,val)
BYTE *str;
DWORD *val;
{
WORD ishex;
WORD isneg;
DWORD v;
DWORD digit;
isneg = FALSE;
ishex = FALSE;
if ((str[0] == '0') && (toupper(str[1]) == 'X'))
{
ishex = TRUE;
str += 2;
}
v = 0;
if (str[0] == '-')
{
isneg = TRUE;
str++;
}
if (!str[0])
return(FALSE); /* empty string */
if ((isneg) && (ishex))
return(FALSE); /* negative hex won't fly here... */
while (*str)
{
*str = toupper(*str);
if ((*str >= '0') && (*str <= '9'))
digit = *str - '0';
else
if ((ishex) && (*str >= 'A') && (*str <= 'F'))
digit = *str - 'A' + 10;
else
return(FALSE);
if (ishex)
v <<= 4;
else
v *= 10;
v += digit;
str++;
}
if (isneg)
v = -v;
*val = v;
return(TRUE);
}
int parse_io_str(str,type,reg)
BYTE *str, *type;
DWORD *reg;
{
BYTE ch;
DWORD val;
*type = UNUSED_TYPE; /* default to FALSE */
*reg = 0;
if (!str[0])
return(FALSE);
if ((ch = toupper(str[0])) == INPUT_PREFIX)
{
if ((getnumber(&str[1],&val)) && (!(val & 0x80000000L))
&& (val < NUM_INPUTS))
{
*type = INPUT_TYPE;
*reg = FIRST_INPUT + val;
return(TRUE);
}
return(beep());
}
if ((ch = toupper(str[0])) == VAR_PREFIX)
{
if ((getnumber(&str[1],&val)) && (!(val & 0x80000000L))
&& (val < NUM_VARS))
{
*type = VAR_TYPE;
*reg = FIRST_VAR + val;
return(TRUE);
}
return(beep());
}
if ((ch = toupper(str[0])) == TIMER_PREFIX)
{
if ((getnumber(&str[1],&val)) && (!(val & 0x80000000L))
&& (val < NUM_TIMERS))
{
*type = TIMER_TYPE;
*reg = FIRST_TIMER + (val << 1);
return(TRUE);
}
return(beep());
}
if ((ch = toupper(str[0])) == COUNTER_PREFIX)
{
if ((getnumber(&str[1],&val)) && (!(val & 0x80000000L))
&& (val < NUM_COUNTERS))
{
*type = COUNTER_TYPE;
*reg = FIRST_COUNTER + val;
return(TRUE);
}
return(beep());
}
if ((ch = toupper(str[0])) == ONESHOT_PREFIX)
{
if ((getnumber(&str[1],&val)) && (!(val & 0x80000000L))
&& (val < NUM_ONESHOTS))
{
*type = ONESHOT_TYPE;
*reg = FIRST_ONESHOT + val;
return(TRUE);
}
return(beep());
}
if ((ch = toupper(str[0])) == ANALOG_PREFIX)
{
if ((getnumber(&str[1],&val)) && (!(val & 0x80000000L))
&& (val < NUM_ANALOGS))
{
*type = ANALOG_TYPE;
*reg = FIRST_ANALOG + val;
return(TRUE);
}
return(beep());
}
if ((ch = toupper(str[0])) == OUTPUT_PREFIX)
{
if ((getnumber(&str[1],&val)) && (!(val & 0x80000000L))
&& (val < NUM_OUTPUTS))
{
*type = OUTPUT_TYPE;
*reg = FIRST_OUTPUT + val;
return(TRUE);
}
return(beep());
}
if ((ch = toupper(str[0])) == LABEL_PREFIX)
{
if ((getnumber(&str[1],&val)) && (!(val & ~255L)))
{
*type = LABEL_TYPE;
*reg = (BYTE)val;
return(TRUE);
}
return(beep());
}
if (getnumber(str,&val))
{
if (val & ~255L)
{
if (val & ~65535L)
{
*type = DWORDVAL_TYPE;
*reg = val;
return(TRUE);
}
*type = WORDVAL_TYPE;
*reg = (WORD)val;
return(TRUE);
}
*type = BYTEVAL_TYPE;
*reg = (BYTE)val;
return(TRUE);
}
return(beep());
}
BYTE *logicnodetype_names[NUM_VAR_TYPES] =
{
NULL,
"X",
"V",
"T",
"C",
"R",
"A",
"Y",
"L",
NULL,
NULL,
NULL
};
WORD regbase[NUM_VAR_TYPES] =
{
0,
FIRST_INPUT,
FIRST_VAR,
FIRST_TIMER,
FIRST_COUNTER,
FIRST_ONESHOT,
FIRST_ANALOG,
FIRST_OUTPUT,
0,
0,
0,
0
};
showregtype(r,c,type,reg)
WORD r, c;
BYTE type;
DWORD reg;
{
BYTE astr[16];
if (type == UNUSED_TYPE)
{
smallstrout(r,c," "); /* make sure previous content is erased */
smallstrout(r,c,"?");
}
else
{
if (type == BYTEVAL_TYPE)
sprintf(astr,"%d",reg & 0xff);
else
if (type == WORDVAL_TYPE)
sprintf(astr,"%u",reg & 0xffff);
else
if (type == DWORDVAL_TYPE)
sprintf(astr,"%ld",reg);
else
if (type == TIMER_TYPE)
sprintf(astr,"%s%02d",logicnodetype_names[type],((reg & 0xff)-regbase[type]) >> 1);
else
sprintf(astr,"%s%02d",logicnodetype_names[type],(reg & 0xff)-regbase[type]);
smallstrout(r,c,astr);
}
}
void erase_node_notes(r,c)
{
smallstrout(r-TEXTHEIGHTSMALL,c," ");
smallstrout(r+TEXTHEIGHT,c," ");
}
void clear_node(nodeptr)
struct logic_element *nodeptr;
{
WORD i;
for (i = 0; i < OPCODE_MAX; i++)
{
nodeptr->opcode[i] = 0;
nodeptr->opflags[i] = UNUSED_TYPE;
}
}
WORD compile_node(nodeptr,len,buf)
struct logic_element *nodeptr;
WORD len;
BYTE *buf;
{
WORD i;
for (i = 0; i < len; i++)
{
buf[i] = nodeptr->opcode[i];
if ((i) && (nodeptr->opflags[i] == UNUSED_TYPE)) /* input type not known */
return(COMPILE_UNKNOWN_PARAMS);
}
return(COMPILE_OK);
}
WORD compile_endian_node(nodeptr,ofs,buf,len)
struct logic_element *nodeptr;
WORD ofs;
BYTE *buf;
WORD len;
{
WORD i;
for (i = 0; i < ofs; i++)
{
buf[i] = nodeptr->opcode[i];
if ((i) && (nodeptr->opflags[i] == UNUSED_TYPE)) /* input type not known */
return(COMPILE_UNKNOWN_PARAMS);
}
if ((nodeptr->opflags[ofs] != WORDVAL_TYPE) && (nodeptr->opflags[ofs] != DWORDVAL_TYPE))
return(COMPILE_UNKNOWN_PARAMS);
if (is_littleendian)
{
buf[ofs] = nodeptr->opcode[ofs]; /* little-endian */
buf[ofs+1] = nodeptr->opcode[ofs+1];
if (nodeptr->opflags[ofs] == DWORDVAL_TYPE)
{
buf[ofs+2] = nodeptr->opcode[ofs+2];
buf[ofs+3] = nodeptr->opcode[ofs+3];
}
}
else
{
if (nodeptr->opflags[ofs] == DWORDVAL_TYPE)
{
buf[ofs] = nodeptr->opcode[ofs+3]; /* big-endian */
buf[ofs+1] = nodeptr->opcode[ofs+2];
buf[ofs+2] = nodeptr->opcode[ofs+1];
buf[ofs+3] = nodeptr->opcode[ofs];
}
else
{
buf[ofs] = nodeptr->opcode[ofs+1]; /* big-endian */
buf[ofs+1] = nodeptr->opcode[ofs];
}
}
return(COMPILE_OK);
}
void inp_init(nodeptr)
struct logic_element *nodeptr;
{
BYTE str[12];
BYTE type;
DWORD reg;
get_values("N/O Input","Input ? ",NULL,NULL,str,NULL,NULL);
if (parse_io_str(str,&type,®))
{
if (type != LABEL_TYPE)
{
nodeptr->opcode[0] = INP;
nodeptr->opcode[1] = reg;
nodeptr->opflags[1] = type;
}
else
beep();
}
}
void inp_del(r,c,nodeptr)
WORD r,c;
struct logic_element *nodeptr;
{
erase_node_notes(r,c);
clear_node(nodeptr);
}
void inp_draw(r,c,nodeptr,fg,bg)
WORD r,c;
struct logic_element *nodeptr;
WORD fg,bg;
{
cstrout(r,c,objs[INP_OBJ].label,fg,bg);
coverlay(r,c,objs[INP_OBJ].overlay,fg);
showregtype(r-TEXTHEIGHTSMALL,c+2*TEXTWIDTH,nodeptr->opflags[1],(DWORD)nodeptr->opcode[1]);
}
WORD inp_comp(nodeptr,len,buf)
struct logic_element *nodeptr;
WORD *len;
BYTE *buf;
{
*len = 2;
return(compile_node(nodeptr,*len,buf));
}
void ninp_init(nodeptr)
struct logic_element *nodeptr;
{
BYTE str[12];
BYTE type;
DWORD reg;
get_values("N/C Input","Input ? ",NULL,NULL,str,NULL,NULL);
if (parse_io_str(str,&type,®))
{
if (type != LABEL_TYPE)
{
nodeptr->opcode[0] = NINP;
nodeptr->opcode[1] = reg;
nodeptr->opflags[1] = type;
}
else
beep();
}
}
void ninp_del(r,c,nodeptr)
WORD r,c;
struct logic_element *nodeptr;
{
erase_node_notes(r,c);
clear_node(nodeptr);
}
void ninp_draw(r,c,nodeptr,fg,bg)
WORD r,c;
struct logic_element *nodeptr;
WORD fg,bg;
{
cstrout(r,c,objs[NINP_OBJ].label,fg,bg);
coverlay(r,c,objs[NINP_OBJ].overlay,fg);
showregtype(r-TEXTHEIGHTSMALL,c+2*TEXTWIDTH,nodeptr->opflags[1],(DWORD)nodeptr->opcode[1]);
}
WORD ninp_comp(nodeptr,len,buf)
struct logic_element *nodeptr;
WORD *len;
BYTE *buf;
{
*len = 2;
return(compile_node(nodeptr,*len,buf));
}
void out_init(nodeptr)
struct logic_element *nodeptr;
{
BYTE str[12];
BYTE type;
DWORD reg;
get_values("N/O Output","Output ? ",NULL,NULL,str,NULL,NULL);
if (parse_io_str(str,&type,®))
{
if ((type == VAR_TYPE) || (type == OUTPUT_TYPE))
{
nodeptr->opcode[0] = OUT;
nodeptr->opcode[1] = reg;
nodeptr->opflags[1] = type;
}
else
beep();
}
}
void out_del(r,c,nodeptr)
WORD r,c;
struct logic_element *nodeptr;
{
erase_node_notes(r,c);
clear_node(nodeptr);
}
void out_draw(r,c,nodeptr,fg,bg)
WORD r,c;
struct logic_element *nodeptr;
WORD fg,bg;
{
cstrout(r,c,objs[OUT_OBJ].label,fg,bg);
coverlay(r,c,objs[OUT_OBJ].overlay,fg);
showregtype(r-TEXTHEIGHTSMALL,c+2*TEXTWIDTH,nodeptr->opflags[1],(DWORD)nodeptr->opcode[1]);
}
WORD out_comp(nodeptr,len,buf)
struct logic_element *nodeptr;
WORD *len;
BYTE *buf;
{
*len = 2;
return(compile_node(nodeptr,*len,buf));
}
void nout_init(nodeptr)
struct logic_element *nodeptr;
{
BYTE str[12];
BYTE type;
DWORD reg;
get_values("N/C Output","Output ? ",NULL,NULL,str,NULL,NULL);
if (parse_io_str(str,&type,®))
{
if ((type == VAR_TYPE) || (type == OUTPUT_TYPE))
{
nodeptr->opcode[0] = NOUT;
nodeptr->opcode[1] = reg;
nodeptr->opflags[1] = type;
}
else
beep();
}
}
void nout_del(r,c,nodeptr)
WORD r,c;
struct logic_element *nodeptr;
{
erase_node_notes(r,c);
clear_node(nodeptr);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -