📄 plc.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
*/
#define BROKEN_ADD_OR_BRANCH
/* #define SIMPLE_ADDROW */
#define SHOW_NODES
#define _PLC_C_
#include "plc.h"
#include "charset.h"
#include "bigchar.h"
char buff_512[1024]; /* OK, so I lied... */
int vesalist[512];
WORD vesa_mode;
int have_vesamode;
int have_vgamode;
int vesalistsize;
#define FREQUENCY 115200L /* frequency IN to UART */
#define COMM_RETRY_MAX 3
#define QUEUE_SIZE 4096 /* chars in IN/OUT buf, keep this a power of 2 */
BYTE in_queue[QUEUE_SIZE];
WORD in_queue_head;
WORD in_queue_tail;
BYTE out_queue[QUEUE_SIZE];
WORD out_queue_head;
WORD out_queue_tail;
/* 8250 registers */
#define REC 0 /* UART receive reg */
#define XMIT 0 /* UART transmit reg */
#define INT_EN 1 /* UART int. enable reg */
#define INT_ID 2 /* UART int. ident. reg */
#define LINE_CONTROL 3 /* UART line control reg */
#define MODEM_CONTROL 4 /* UART modem control reg */
#define LINE_STATUS 5 /* UART line status reg */
#define MODEM_STATUS 6 /* UART modem status reg */
#define BAUD_LSB 0 /* UART baud divisor reg */
#define BAUD_MSB 1 /* UART baud divisor reg */
#define FCR_REG 2 /* FCR reg for 16550+ */
BYTE old_uart_setup[8];
#define NONE 0 /* Handshake param none */
#define HDW 1 /* Handshake param hardware */
#define XON 2 /* Handshake param software */
/* Interrupt enable register */
#define RX_INT 0x01 /* Receive interrupt mask */
#define TBE_INT 0x02 /* Transmit buffer empty mask */
#define ERR_INT 0x04 /* Error interrupt mask */
#define RS_INT 0x08 /* Line interrupt mask */
/* Interrupt id register */
#define OUT2 0x08 /* Out 2 line */
#define DTR 0x01 /* DTR high */
#define RTS 0x02 /* RTS high */
#define CTS 0x10
#define DSR 0x20
#define XMTRDY 0x20
#define TXR 0 /* Transmit register (WRITE) */
WORD commbase = 0x03f8; /* default to COMM 1 */
WORD irqnum = 4; /* default to COMM 1 */
DWORD baudrate = 9600;
WORD comm_int_seg, comm_int_ofs; /* save area */
BYTE tempstr[128];
WORD videopage;
#define MENUSPACING (TEXTHEIGHT + 8)
#define MENULINE(n) (144 + n * MENUSPACING)
#define ENDLINE(n) (144 + TEXTHEIGHT + n * MENUSPACING)
#define MENUCOL1 0
#define ENDCOL1 (5 * TEXTWIDTH)
#define MENUCOL2 (TEXTWIDTH * 8)
#define ENDCOL2 (TEXTWIDTH * 13)
int havemouse, mouser, mousec; /* Need SIGNED! */
int mousecolor = LTBLUE;
BYTE mouse_cursor[9] = { MOUSE_CURSOR, 0 };
BYTE mouse_overlay[9];
#define MOUSE_SAVE_ROWS TEXTHEIGHT
#define MOUSE_SAVE_COLS 8 * TEXTWIDTH
BYTE mouse_cursor_save[MOUSE_SAVE_ROWS][MOUSE_SAVE_COLS];
WORD mouse_object = NULL_OBJ;
WORD curpos_r, curpos_c;
BYTE null_str[] = { 0 };
BYTE three_char_inp[] = { START_NO_IN, CHAR_BOX, CHAR_BOX, CHAR_BOX, END_NO_IN, 0 };
BYTE two_char_inp[] = { START_NO_IN, CHAR_BOX, CHAR_BOX, END_NO_IN, VERT_BAR, 0 };
BYTE three_char_out[] = { START_NO_OUT, CHAR_BOX, CHAR_BOX, CHAR_BOX, END_NO_OUT, 0 };
BYTE two_char_out[] = { START_NO_OUT, CHAR_BOX, CHAR_BOX, END_NO_OUT, VERT_BAR, 0 };
BYTE no_input[] = { VERT_BAR, VERT_BAR, START_NO_IN, END_NO_IN, VERT_BAR, 0 };
BYTE nc_input[] = { VERT_BAR, VERT_BAR, START_NC_IN, END_NC_IN, VERT_BAR, 0 };
BYTE no_output[] = { VERT_BAR, VERT_BAR, START_NO_OUT, END_NO_OUT, VERT_BAR, 0 };
BYTE nc_output[] = { VERT_BAR, VERT_BAR, START_NC_OUT, END_NC_OUT, VERT_BAR, 0 };
BYTE lat_output[] = { START_NO_OUT, CHAR_BOX, CHAR_BOX, CHAR_BOX, END_NO_OUT, 0 };
BYTE or_branch[] = { BRANCH_BAR, START_BRANCH, END_BRANCH, BRANCH_BAR, BRANCH_BAR, 0 };
BYTE expand_branch[] = { BRANCH_BAR, START_BRANCH, END_BRANCH, EXPAND_BRANCH, BRANCH_BAR, 0 };
BYTE ladder_left[] = { LEFT_EDGE, 0 };
BYTE ladder_right[] = { RIGHT_EDGE, 0 };
BYTE rung_element[] = { VERT_BAR, VERT_BAR, VERT_BAR, VERT_BAR, VERT_BAR, VERT_BAR, VERT_BAR, VERT_BAR, 0 };
BYTE blank_element[] = " ";
/* 12345 */
BYTE or_null[] = { VERT_BAR, 0 };
BYTE or_link[] = { OR_VERT_T, 0 };
BYTE or_vertical[] = { OR_VERT_BAR, 0 };
BYTE or_start[] = { OR_LEFT, 0 };
BYTE or_start_t[] = { OR_LEFT_T, 0 };
BYTE or_end[] = { OR_RIGHT, 0 };
BYTE or_end_t[] = { OR_RIGHT_T, 0 };
BYTE scroll_uparrow[] = { SCROLL_UPARROW, 0 };
BYTE scroll_downarrow[] = { SCROLL_DOWNARROW, 0 };
BYTE scroll_bar[] = { SCROLL_BAR, 0 };
BYTE scroll_box[] = { SCROLL_BOX, 0 };
void filesave(), fileload(), newladder(), download();
void onestep(), linestep(), run(), stop();
#ifdef SIMPLE_ADDROW
void addrow(), delrow();
#else
void appendrow();
#endif
void pickup(), quit();
void scrollladder();
void inp_init(), ninp_init(), out_init(), nout_init(), lout_init(), uout_init();
void add_init(), sub_init(), mul_init(), div_init(), mod_init();
void and_init(), or_init(), xor_init(), not_init(), neg_init();
void equ_init(), neq_init(), grt_init(), geq_init(), les_init(), leq_init();
void mov_init(), jmp_init(), osr_init(), ctt_init(), ctf_init();
void tmt_init(), tmf_init(), rtmt_init(), rtmf_init(), reset_init(), lbl_init();
void inv_init();
void inp_del(), ninp_del(), out_del(), nout_del(), lout_del(), uout_del();
void add_del(), sub_del(), mul_del(), div_del(), mod_del();
void and_del(), or_del(), xor_del(), not_del(), neg_del();
void equ_del(), neq_del(), grt_del(), geq_del(), les_del(), leq_del();
void mov_del(), jmp_del(), osr_del(), ctt_del(), ctf_del();
void tmt_del(), tmf_del(), rtmt_del(), rtmf_del(), reset_del(), lbl_del();
void inv_del();
void inp_draw(), ninp_draw(), out_draw(), nout_draw(), lout_draw(), uout_draw();
void add_draw(), sub_draw(), mul_draw(), div_draw(), mod_draw();
void and_draw(), or_draw(), xor_draw(), not_draw(), neg_draw();
void equ_draw(), neq_draw(), grt_draw(), geq_draw(), les_draw(), leq_draw();
void mov_draw(), jmp_draw(), osr_draw(), ctt_draw(), ctf_draw();
void tmt_draw(), tmf_draw(), rtmt_draw(), rtmf_draw(), reset_draw(), lbl_draw();
void inv_draw();
WORD inp_comp(), ninp_comp(), out_comp(), nout_comp(), lout_comp(), uout_comp();
WORD add_comp(), sub_comp(), mul_comp(), div_comp(), mod_comp();
WORD and_comp(), or_comp(), xor_comp(), not_comp(), neg_comp();
WORD equ_comp(), neq_comp(), grt_comp(), geq_comp(), les_comp(), leq_comp();
WORD mov_comp(), jmp_comp(), osr_comp(), ctt_comp(), ctf_comp();
WORD tmt_comp(), tmf_comp(), rtmt_comp(), rtmf_comp(), reset_comp(), lbl_comp();
WORD inv_comp();
void nullfn();
struct obj objs[NUMBER_OF_OBJECTS] = /* indexed by enum objtypes */
{
{ blank_element, no_input, inp_init, inp_del, inp_draw, inp_comp },
{ blank_element, nc_input, ninp_init, ninp_del, ninp_draw, ninp_comp },
{ blank_element, no_output, out_init, out_del, out_draw, out_comp },
{ blank_element, nc_output, nout_init, nout_del, nout_draw, nout_comp },
{ " LAT ", lat_output, lout_init, lout_del, lout_draw, lout_comp },
{ " UNL ", lat_output, uout_init, uout_del, uout_draw, uout_comp },
{ " ADD ", three_char_out, add_init, add_del, add_draw, add_comp },
{ " SUB ", three_char_out, sub_init, sub_del, sub_draw, sub_comp },
{ " MUL ", three_char_out, mul_init, mul_del, mul_draw, mul_comp },
{ " DIV ", three_char_out, div_init, div_del, div_draw, div_comp },
{ " MOD ", three_char_out, mod_init, mod_del, mod_draw, mod_comp },
{ " AND ", three_char_out, and_init, and_del, and_draw, and_comp },
{ " OR ", two_char_out, or_init, or_del, or_draw, or_comp },
{ " XOR ", three_char_out, xor_init, xor_del, xor_draw, xor_comp },
{ " NOT ", three_char_out, not_init, not_del, not_draw, not_comp },
{ " NEG ", three_char_out, neg_init, neg_del, neg_draw, neg_comp },
{ " EQ ", two_char_inp, equ_init, equ_del, equ_draw, equ_comp },
{ " NE ", two_char_inp, neq_init, neq_del, neq_draw, neq_comp },
{ " GT ", two_char_inp, grt_init, grt_del, grt_draw, grt_comp },
{ " GE ", two_char_inp, geq_init, geq_del, geq_draw, geq_comp },
{ " LT ", two_char_inp, les_init, les_del, les_draw, les_comp },
{ " LE ", two_char_inp, leq_init, leq_del, leq_draw, leq_comp },
{ " MOV ", three_char_out, mov_init, mov_del, mov_draw, mov_comp },
{ " JMP ", three_char_out, jmp_init, jmp_del, jmp_draw, jmp_comp },
{ " OSR ", three_char_inp, osr_init, osr_del, osr_draw, osr_comp },
{ " CTT ", three_char_inp, ctt_init, ctt_del, ctt_draw, ctt_comp },
{ " CTF ", three_char_inp, ctf_init, ctf_del, ctf_draw, ctf_comp },
{ " TMT ", three_char_inp, tmt_init, tmt_del, tmt_draw, tmt_comp },
{ " TMF ", three_char_inp, tmf_init, tmf_del, tmf_draw, tmf_comp },
{ " RTT ", three_char_inp, rtmt_init, rtmt_del, rtmt_draw, rtmt_comp },
{ " RTF ", three_char_inp, rtmf_init, rtmf_del, rtmf_draw, rtmf_comp },
{ " RST ", three_char_inp, reset_init,reset_del,reset_draw,reset_comp},
{ " INV ", three_char_inp, inv_init, inv_del, inv_draw, inv_comp },
{ " LBL ", three_char_inp, lbl_init, lbl_del, lbl_draw, lbl_comp },
{ "Save", null_str, nullfn, nullfn, nullfn, nullfn },
{ "Load", null_str, nullfn, nullfn, nullfn, nullfn },
{ "New", null_str, nullfn, nullfn, nullfn, nullfn },
{ "Download" null_str, nullfn, nullfn, nullfn, nullfn },
{ "AddRow", null_str, nullfn, nullfn, nullfn, nullfn },
{ "DelRow", null_str, nullfn, nullfn, nullfn, nullfn },
{ "OneStep" null_str, nullfn, nullfn, nullfn, nullfn },
{ "LineStep", null_str, nullfn, nullfn, nullfn, nullfn },
{ "Run", null_str, nullfn, nullfn, nullfn, nullfn },
{ "Stop", null_str, nullfn, nullfn, nullfn, nullfn },
{ blank_element, or_branch, nullfn, nullfn, nullfn, nullfn },
{ blank_element, expand_branch, nullfn, nullfn, nullfn, nullfn },
{ "(c) Bill", null_str, nullfn, nullfn, nullfn, nullfn },
{ " Couture", null_str, nullfn, nullfn, nullfn, nullfn },
{ " 2006", null_str, nullfn, nullfn, nullfn, nullfn },
{ "V0.01A", null_str, nullfn, nullfn, nullfn, nullfn },
{ "Exit", null_str, nullfn, nullfn, nullfn, nullfn },
{ null_str, null_str, nullfn, nullfn, nullfn, nullfn }, /* ladder object */
{ null_str, null_str, nullfn, nullfn, nullfn, nullfn }, /* default mouse_object */
{ null_str, null_str, nullfn, nullfn, nullfn, nullfn } /* scroll object */
};
struct element_info menu[] =
{
{ 0, TEXTHEIGHT, MENUCOL1, MENUCOL1 + 4 * TEXTWIDTH, SAVE_OBJ, filesave, NULL },
{ 0, TEXTHEIGHT, MENUCOL2, MENUCOL2 + 4 * TEXTWIDTH, LOAD_OBJ, fileload, NULL },
{ 32, 32+TEXTHEIGHT, MENUCOL1, MENUCOL1 + 3 * TEXTWIDTH, NEW_OBJ, newladder, NULL },
{ 32, 32+TEXTHEIGHT, MENUCOL2, MENUCOL2 + 7 * TEXTWIDTH, DOWNLOAD_OBJ, download, NULL },
#ifdef SIMPLE_ADDROW
{ 56, 56+TEXTHEIGHT, MENUCOL1, MENUCOL1 + 6 * TEXTWIDTH, ADDROW_OBJ, addrow, NULL },
{ 56, 56+TEXTHEIGHT, MENUCOL2, MENUCOL2 + 6 * TEXTWIDTH, DELROW_OBJ, delrow, NULL },
#else
{ 56, 56+TEXTHEIGHT, MENUCOL1, MENUCOL1 + 6 * TEXTWIDTH, ADDROW_OBJ, pickup, appendrow },
{ 56, 56+TEXTHEIGHT, MENUCOL2, MENUCOL2 + 6 * TEXTWIDTH, DELROW_OBJ, pickup, NULL },
#endif
{ 88, 88+TEXTHEIGHT, MENUCOL1, MENUCOL1 + 7 * TEXTWIDTH, ONESTEP_OBJ,onestep, NULL },
{ 88, 88+TEXTHEIGHT, MENUCOL2, MENUCOL2 + 7 * TEXTWIDTH, LINESTEP_OBJ,linestep, NULL },
{ 112, 112+TEXTHEIGHT, MENUCOL1, MENUCOL1 + 3 * TEXTWIDTH, RUN_OBJ, run, NULL },
{ 112, 112+TEXTHEIGHT, MENUCOL2, MENUCOL2 + 4 * TEXTWIDTH, STOP_OBJ, stop, NULL },
{ MENULINE(0), ENDLINE(0), MENUCOL1, ENDCOL1, INP_OBJ, pickup, NULL },
{ MENULINE(0), ENDLINE(0), MENUCOL2, ENDCOL2, NINP_OBJ, pickup, NULL },
{ MENULINE(1), ENDLINE(1), MENUCOL1, ENDCOL1, OUT_OBJ, pickup, NULL },
{ MENULINE(1), ENDLINE(1), MENUCOL2, ENDCOL2, NOUT_OBJ, pickup, NULL },
{ MENULINE(2), ENDLINE(2), MENUCOL1, ENDCOL1, LOUT_OBJ, pickup, NULL },
{ MENULINE(2), ENDLINE(2), MENUCOL2, ENDCOL2, UOUT_OBJ, pickup, NULL },
{ MENULINE(3), ENDLINE(3), MENUCOL1, ENDCOL1, ADD_OBJ, pickup, NULL },
{ MENULINE(3), ENDLINE(3), MENUCOL2, ENDCOL2, SUB_OBJ, pickup, NULL },
{ MENULINE(4), ENDLINE(4), MENUCOL1, ENDCOL1, MUL_OBJ, pickup, NULL },
{ MENULINE(4), ENDLINE(4), MENUCOL2, ENDCOL2, DIV_OBJ, pickup, NULL },
{ MENULINE(5), ENDLINE(5), MENUCOL1, ENDCOL1, MOD_OBJ, pickup, NULL },
{ MENULINE(5), ENDLINE(5), MENUCOL2, ENDCOL2, NEG_OBJ, pickup, NULL },
{ MENULINE(6), ENDLINE(6), MENUCOL1, ENDCOL1, AND_OBJ, pickup, NULL },
{ MENULINE(6), ENDLINE(6), MENUCOL2, ENDCOL2, OR_OBJ pickup, NULL },
{ MENULINE(7), ENDLINE(7), MENUCOL1, ENDCOL1, XOR_OBJ, pickup, NULL },
{ MENULINE(7), ENDLINE(7), MENUCOL2, ENDCOL2, NOT_OBJ, pickup, NULL },
{ MENULINE(8), ENDLINE(8), MENUCOL1, ENDCOL1, EQU_OBJ, pickup, NULL },
{ MENULINE(8), ENDLINE(8), MENUCOL2, ENDCOL2, NEQ_OBJ, pickup, NULL },
{ MENULINE(9), ENDLINE(9), MENUCOL1, ENDCOL1, GRT_OBJ, pickup, NULL },
{ MENULINE(9), ENDLINE(9), MENUCOL2, ENDCOL2, GEQ_OBJ, pickup, NULL },
{ MENULINE(10), ENDLINE(10), MENUCOL1, ENDCOL1, LES_OBJ, pickup, NULL },
{ MENULINE(10), ENDLINE(10), MENUCOL2, ENDCOL2, LEQ_OBJ pickup, NULL },
{ MENULINE(11), ENDLINE(11), MENUCOL1, ENDCOL1, MOV_OBJ, pickup, NULL },
{ MENULINE(11), ENDLINE(11), MENUCOL2, ENDCOL2, OSR_OBJ, pickup, NULL },
{ MENULINE(12), ENDLINE(12), MENUCOL1, ENDCOL1, JMP_OBJ, pickup, NULL },
{ MENULINE(12), ENDLINE(12), MENUCOL2, ENDCOL2, LBL_OBJ, pickup, NULL },
{ MENULINE(13), ENDLINE(13), MENUCOL1, ENDCOL1, CTT_OBJ, pickup, NULL },
{ MENULINE(13), ENDLINE(13), MENUCOL2, ENDCOL2, CTF_OBJ, pickup, NULL },
{ MENULINE(14), ENDLINE(14), MENUCOL1, ENDCOL1, TMT_OBJ, pickup, NULL },
{ MENULINE(14), ENDLINE(14), MENUCOL2, ENDCOL2, TMF_OBJ, pickup, NULL },
{ MENULINE(15), ENDLINE(15), MENUCOL1, ENDCOL1, RTMT_OBJ, pickup, NULL },
{ MENULINE(15), ENDLINE(15), MENUCOL2, ENDCOL2, RTMF_OBJ, pickup, NULL },
{ MENULINE(16), ENDLINE(16), MENUCOL1, ENDCOL1, RESET_OBJ, pickup, NULL },
{ MENULINE(16), ENDLINE(16), MENUCOL2, ENDCOL2, INVERT_OBJ,pickup, NULL },
{ MENULINE(17), ENDLINE(17), MENUCOL1, ENDCOL1, ORBRANCH_OBJ, pickup, NULL },
{ MENULINE(17), ENDLINE(17), MENUCOL2, ENDCOL2, EXPAND_OBJ,pickup, NULL },
{ MENULINE(20), ENDLINE(20), MENUCOL1, ENDCOL1, COPYR1_OBJ,NULL, NULL },
{ MENULINE(20), ENDLINE(20), MENUCOL2, ENDCOL2, COPYR2_OBJ,NULL, NULL },
{ MENULINE(21), ENDLINE(21), MENUCOL1, ENDCOL1, COPYR3_OBJ,NULL, NULL },
{ MENULINE(22), ENDLINE(22), MENUCOL1, ENDCOL1, VERSION_OBJ,NULL, NULL },
{ MENULINE(25), ENDLINE(25), MENUCOL1, ENDCOL1, EXIT_OBJ, quit, NULL },
{ SCROLL_TOP, SCROLL_BOTTOM,SCROLL_LEFTCOL, SCROLL_RIGHTCOL, SCROLL_OBJ, scrollladder, NULL }
};
#define NUM_MENU_ELEMENTS 52
WORD screen_index = NUM_MENU_ELEMENTS;
struct element_info *screen_list[SCREEN_MAX];
WORD dirty = FALSE;
WORD exitflag = FALSE;
WORD quickexit = FALSE;
/* WORD quickexit = TRUE; */ /* default for testing */
void ladder_node_add();
void ladder_node_del();
struct ladder_rung rungs[MAX_RUNGS];
WORD used_rungs[MAX_RUNGS];
WORD rung_list[MAX_RUNGS+1];
WORD ladder_size = 1;
#define FILEVERSION_LEN 16
/* BYTE fileversion[FILEVERSION_LEN] = "Athena 0.00A"; */
/* 0123456789ab */
BYTE fileversion[FILEVERSION_LEN] = "TinyPLC 0.01A";
/* 0123456789abc */
DWORD modbus_dataregs[PLC_MEMORY_LOCS];
BYTE program[MAX_PROGRAM];
WORD program_len;
WORD label_addresses[NUM_LABELS];
WORD scroll_baserow;
WORD is_littleendian = TRUE;
WORD peekw(), get_timer();
main(argc,argv)
int argc;
char *argv[];
{
WORD i, j;
get_vesa_mode();
havemouse = init_mouse();
if (!vesa_mode)
{
printf("Error: suitable VESA mode not found!\n");
exit(1);
}
if (!havemouse)
{
printf("No mouse available!\n");
exit(1);
}
for (i = 1; i < argc; i++)
{
if (argv[i][0] == '-')
{
switch(toupper(argv[i][1]))
{
case 'B': /* Baudrate */
if (!argv[i][2])
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -