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

📄 plc2.c

📁 单片PLC,AT2581实现梯形图功能,可作为参考
💻 C
📖 第 1 页 / 共 4 页
字号:
/*
 *  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,&reg))
      {
      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,&reg))
      {
      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,&reg))
      {
      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,&reg))
      {
      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 + -