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

📄 serial.cc

📁 Small Device C Compiler 面向Inter8051
💻 CC
字号:
/* * Simulator of microcontrollers (serial.cc) * * Copyright (C) 1999,99 Drotos Daniel, Talker Bt. *  * To contact author send email to drdani@mazsola.iit.uni-miskolc.hu * *//* This file is part of microcontroller simulator: ucsim.UCSIM is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2 of the License, or(at your option) any later version.UCSIM is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with UCSIM; see the file COPYING.  If not, write to the FreeSoftware Foundation, 59 Temple Place - Suite 330, Boston, MA02111-1307, USA. *//*@1@*/#include "ddconfig.h"#include <stdio.h>#include <stdlib.h>#include <ctype.h>#include <termios.h>#include <unistd.h>#include <errno.h>#include <fcntl.h>#include <sys/time.h>#include <strings.h>// prj#include "globals.h"// local#include "serialcl.h"#include "regs51.h"#include "uc51cl.h"cl_serial::cl_serial(class cl_uc *auc):  cl_hw(auc, HW_UART, 0, "uart"){}cl_serial::~cl_serial(void){  if (serial_out)    {      if (isatty(fileno(serial_out)))	tcsetattr(fileno(serial_out), TCSANOW, &saved_attributes_out);      fclose(serial_out);    }  if (serial_in)    {      if (isatty(fileno(serial_in)))	tcsetattr(fileno(serial_in), TCSANOW, &saved_attributes_in);      fclose(serial_in);    }}intcl_serial::init(void){  class cl_mem *sfr;  int i;  struct termios tattr;  sfr= uc->mem(MEM_SFR);  if (sfr)    {      //sbuf= sfr->register_hw(SBUF, this, 0);      //pcon= sfr->register_hw(PCON, this, 0);      //scon= sfr->register_hw(SCON, this, 0);      register_cell(sfr, SBUF, &sbuf, wtd_restore_write);      register_cell(sfr, PCON, &pcon, wtd_restore_write);      register_cell(sfr, SCON, &scon, wtd_restore_write);    }  serial_in = (FILE*)application->args->get_parg(0, "Ser_in");  serial_out= (FILE*)application->args->get_parg(0, "Ser_out");  if (serial_in)    {      // making `serial' unbuffered      if (setvbuf(serial_in, NULL, _IONBF, 0))	perror("Unbuffer serial input channel");      // setting O_NONBLOCK      if ((i= fcntl(fileno(serial_in), F_GETFL, 0)) < 0)	perror("Get flags of serial input");      i|= O_NONBLOCK;      if (fcntl(fileno(serial_in), F_SETFL, i) < 0)	perror("Set flags of serial input");      // switching terminal to noncanonical mode      if (isatty(fileno(serial_in)))	{	  tcgetattr(fileno(serial_in), &saved_attributes_in);	  tcgetattr(fileno(serial_in), &tattr);	  tattr.c_lflag&= ~(ICANON|ECHO);	  tattr.c_cc[VMIN] = 1;	  tattr.c_cc[VTIME]= 0;	  tcsetattr(fileno(serial_in), TCSAFLUSH, &tattr);	}      else	fprintf(stderr, "Warning: serial input interface connected to a "		"non-terminal file.\n");    }  if (serial_out)    {      // making `serial' unbuffered      if (setvbuf(serial_out, NULL, _IONBF, 0))	perror("Unbuffer serial output channel");      // setting O_NONBLOCK      if ((i= fcntl(fileno(serial_out), F_GETFL, 0)) < 0)	perror("Get flags of serial output");      i|= O_NONBLOCK;      if (fcntl(fileno(serial_out), F_SETFL, i) < 0)	perror("Set flags of serial output");      // switching terminal to noncanonical mode      if (isatty(fileno(serial_out)))	{	  tcgetattr(fileno(serial_out), &saved_attributes_out);	  tcgetattr(fileno(serial_out), &tattr);	  tattr.c_lflag&= ~(ICANON|ECHO);	  tattr.c_cc[VMIN] = 1;	  tattr.c_cc[VTIME]= 0;	  tcsetattr(fileno(serial_out), TCSAFLUSH, &tattr);	}      else	fprintf(stderr, "Warning: serial output interface connected to a "		"non-terminal file.\n");    }  class cl_hw *t2= uc->get_hw(HW_TIMER, 2, 0);  if ((there_is_t2= t2 != 0))    {      t_mem d= sfr->get(T2CON);      t2_baud= d & (bmRCLK | bmTCLK);    }  else    t2_baud= DD_FALSE;  return(0);}voidcl_serial::new_hw_added(class cl_hw *new_hw){  if (new_hw->cathegory == HW_TIMER &&      new_hw->id == 2)    {      there_is_t2= DD_TRUE;      t_mem d= uc->mem(MEM_SFR)->get(T2CON);      t2_baud= d & (bmRCLK | bmTCLK);    }}voidcl_serial::added_to_uc(void){  uc->it_sources->add(new cl_it_src(bmES , SCON, bmTI , 0x0023, false,				    "serial transmit", 6));  uc->it_sources->add(new cl_it_src(bmES , SCON, bmRI , 0x0023, false,				    "serial receive", 6));}t_memcl_serial::read(class cl_cell *cell){  if (cell == sbuf)    return(s_in);  else    return(cell->get());}voidcl_serial::write(class cl_cell *cell, t_mem *val){  if (cell == sbuf)    {      s_out= *val;      s_sending= DD_TRUE;      s_tr_bit = 0;      s_tr_tick= 0;      s_tr_t1= 0;    }  if (cell == scon)    {      _mode= *val >> 6;      _bmREN= *val & bmREN;      _bits= 8;      switch (_mode)	{	case 0:	  _bits= 8;	  _divby= 12;	  break;	case 1:	  _bits= 10;	  _divby= _bmSMOD?16:32;	  break;	case 2:	  _bits= 11;	  _divby= _bmSMOD?16:32;	  break;	case 3:	  _bits= 11;	  _divby= _bmSMOD?16:32;	  break;	}    }  else if (cell == pcon)    {      _bmSMOD= *val & bmSMOD;      /*switch (_mode)	{	case 1:	  _divby= _bmSMOD?16:32;	  break;	case 2:	  _divby= _bmSMOD?16:32;	  break;	case 3:	  _divby= _bmSMOD?16:32;	  break;	  }*/      if (_mode)	_divby= _bmSMOD?16:32;    }}/*voidcl_serial::mem_cell_changed(class cl_mem *mem, t_addr addr){  class cl_mem *sfr= uc->mem(MEM_SFR);  t_mem d;  d= sbuf->get();  write(sbuf, &d);  d= pcon->get();  write(pcon, &d);  d= scon->get();  write(scon, &d);}*/intcl_serial::serial_bit_cnt(void){  //int divby= 12;  int *tr_src= 0, *rec_src= 0;  switch (_mode)    {    case 0:      //divby  = 12;      tr_src = &s_tr_tick;      rec_src= &s_rec_tick;      break;    case 1:    case 3:      //divby  = (/*pcon->get()&bmSMOD*/_bmSMOD)?16:32;      tr_src = &s_tr_t1;      rec_src= &s_rec_t1;      break;    case 2:      //divby  = (/*pcon->get()&bmSMOD*/_bmSMOD)?16:32;      tr_src = &s_tr_tick;      rec_src= &s_rec_tick;      break;    }  if (t2_baud)    _divby= 16;  if (s_sending)    {      while (*tr_src >= _divby)	{	  (*tr_src)-= _divby;	  s_tr_bit++;	  //printf("serial bit sent %d\n",uc->ticks->ticks);	}    }  if (s_receiving)    {      while (*rec_src >= _divby)	{	  (*rec_src)-= _divby;	  s_rec_bit++;	}    }  return(0);}intcl_serial::tick(int cycles){  char c;  serial_bit_cnt(/*_mode*/);  if (s_sending &&      (s_tr_bit >= _bits))    {      s_sending= DD_FALSE;      scon->set_bit1(bmTI);      if (serial_out)	{	  putc(s_out, serial_out);	  fflush(serial_out);	}      s_tr_bit-= _bits;      //printf("serial out %d bit rems %d\n",s_tr_bit,uc->ticks->ticks);    }  if ((/*scn & bmREN*/_bmREN) &&      serial_in &&      !s_receiving)    {      fd_set set; static struct timeval timeout= {0,0};      FD_ZERO(&set);      FD_SET(fileno(serial_in), &set);      int i= select(fileno(serial_in)+1, &set, NULL, NULL, &timeout);      if (i > 0 &&      	  FD_ISSET(fileno(serial_in), &set))	{	  s_receiving= DD_TRUE;	  s_rec_bit= 0;	  s_rec_tick= /*uc51->*/s_rec_t1= 0;	}    }  if (s_receiving &&      (s_rec_bit >= _bits))    {      if (::read(fileno(serial_in), &c, 1) == 1)	{	  s_in= c;	  sbuf->set(s_in);	  received(c);	}      s_receiving= DD_FALSE;      s_rec_bit-= _bits;    }    int l;  s_tr_tick+= (l= cycles * uc->clock_per_cycle());  s_rec_tick+= l;  return(0);}voidcl_serial::received(int c){  scon->set_bit1(bmRI);}voidcl_serial::reset(void){  s_tr_t1    = 0;  s_rec_t1   = 0;  s_tr_tick  = 0;  s_rec_tick = 0;  s_in       = 0;  s_out      = 0;  s_sending  = DD_FALSE;  s_receiving= DD_FALSE;  s_rec_bit  = 0;  s_tr_bit   = 0;}voidcl_serial::happen(class cl_hw *where, enum hw_event he, void *params){  if (where->cathegory == HW_TIMER)    {      if (where->id == 1)	{	  //printf("serial: timer overflowed %ld\n", uc->ticks->ticks);	  s_rec_t1++;	  s_tr_t1++;	}      if (where->id == 2 /*&& there_is_t2*/)	{	  switch (he)	    {	    case EV_T2_MODE_CHANGED:	      {		if (!t2_baud)		  s_rec_t1= s_tr_t1= 0;		t_mem *d= (t_mem *)params;		t2_baud= *d & (bmRCLK | bmTCLK);		break;	      }	    case EV_OVERFLOW:	      //printf("T2 baud ov r%d t%d\n",s_rec_t1,s_tr_t1);	      s_rec_t1++;	      s_tr_t1++;	      break;	    default: break;	    }	}    }}voidcl_serial::print_info(class cl_console *con){  char *modes[]= { "Shift, fixed clock",		   "8 bit UART timer clocked",		   "9 bit UART fixed clock",		   "9 bit UART timer clocked" };  int sc= scon->get();  con->dd_printf("%s[%d]", id_string, id);  int mode= (sc&(bmSM0|bmSM1))>>6;  con->dd_printf(" %s", modes[mode]);  if (mode == 1 || mode == 2)    con->dd_printf(" (timer%d)", (t2_baud)?2:1);  con->dd_printf(" MultiProc=%s",		 (mode&2)?((sc&bmSM2)?"ON":"OFF"):"none");  con->dd_printf(" irq=%s", (uc->get_mem(MEM_SFR, IE)&bmES)?"en":"dis");  con->dd_printf(" prio=%d", uc->it_priority(bmPS));  con->dd_printf("\n");  con->dd_printf("Receiver");  con->dd_printf(" %s", (sc&bmREN)?"ON":"OFF");  con->dd_printf(" RB8=%c", (sc&bmRB8)?'1':'0');  con->dd_printf(" irq=%c", (sc&bmRI)?'1':'0');  con->dd_printf("\n");  con->dd_printf("Transmitter");  con->dd_printf(" TB8=%c", (sc&bmTB8)?'1':'0');  con->dd_printf(" irq=%c", (sc&bmTI)?'1':'0');  con->dd_printf("\n");  /*con->dd_printf("s_rec_t1=%d s_rec_bit=%d s_rec_tick=%d\n",		 s_rec_t1, s_rec_bit, s_rec_tick);  con->dd_printf("s_tr_t1=%d s_tr_bit=%d s_tr_tick=%d\n",		 s_tr_t1, s_tr_bit, s_tr_tick);		 con->dd_printf("divby=%d bits=%d\n", _divby, _bits);*/}/* End of s51.src/serial.cc */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -