ea79cabbe98a3aec078cb2edc577e5b88ab407b1
[fw/sdcc] / sim / ucsim / s51.src / uc52.cc
1 /*
2  * Simulator of microcontrollers (uc52.cc)
3  *
4  * Copyright (C) 1999,99 Drotos Daniel, Talker Bt.
5  * 
6  * To contact author send email to drdani@mazsola.iit.uni-miskolc.hu
7  *
8  */
9
10 /* This file is part of microcontroller simulator: ucsim.
11
12 UCSIM is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
16
17 UCSIM is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with UCSIM; see the file COPYING.  If not, write to the Free
24 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
25 02111-1307, USA. */
26 /*@1@*/
27
28 #include "ddconfig.h"
29
30 #include <stdio.h>
31
32 // local
33 #include "uc52cl.h"
34 #include "regs51.h"
35 #include "timer2cl.h"
36
37
38 /*
39  * Making an 8052 CPU object
40  */
41
42 t_uc52::t_uc52(int Itype, int Itech, class cl_sim *asim):
43   t_uc51(Itype, Itech, asim)
44 {
45   it_sources->add(new cl_it_src(bmET2, T2CON, bmTF2, 0x002b, false,
46                                 "timer #2 TF2"));
47   exf2it= new cl_it_src(bmET2, T2CON, bmEXF2, 0x002b, false,
48                         "timer #2 EXF2");
49   it_sources->add(exf2it);
50 }
51
52
53 void
54 t_uc52::mk_hw_elements(void)
55 {
56   class cl_hw *h;
57
58   t_uc51::mk_hw_elements();
59   hws->add(h= new cl_timer2(this));
60   h->init();
61 }
62
63
64 /*
65  * Calculating address of indirectly addressed IRAM cell
66  *
67  * If CPU is 8051 and addr is over 127, it must be illegal! But in 52
68  * it is legal.
69  *
70  */
71
72 uchar *
73 t_uc52::get_indirect(uchar addr, int *res)
74 {
75   *res= resGO;
76   return(&(/*MEM(MEM_IRAM)*/iram->umem8[addr]));
77 }
78
79
80 /*
81  * Simulating timers
82  *
83  * Calling inherited method to simulate timer #0 and #1 and then 
84  * simulating timer #2.
85  *
86  */
87
88 int
89 t_uc52::do_timers(int cycles)
90 {
91   int res;
92
93   if ((res= t_uc51::do_timers(cycles)) != resGO)
94     return(res);
95   return(do_timer2(cycles));
96 }
97
98
99 /*
100  * Simulating timer 2
101  */
102
103 int
104 t_uc52::do_timer2(int cycles)
105 {
106   bool nocount= DD_FALSE;
107   uint t2con= get_mem(MEM_SFR, T2CON);
108
109   exf2it->activate();
110   if (!(t2con & bmTR2))
111     /* Timer OFF */
112     return(resGO);
113
114   if (t2con & (bmRCLK | bmTCLK))
115     return(do_t2_baud(cycles));
116
117   /* Determining nr of input clocks */
118   if (!(t2con & bmTR2))
119     nocount= DD_TRUE; // Timer OFF
120   else
121     if (t2con & bmC_T2)
122       {
123         // Counter mode, falling edge on P1.0 (T2)
124         if ((prev_p1 & bmT2) &&
125             !(get_mem(MEM_SFR, P1) & port_pins[1] & bmT2))
126           cycles= 1;
127         else
128           nocount= DD_TRUE;
129       }
130   /* Counting */
131   while (cycles--)
132     {
133       if (t2con & bmCP_RL2)
134         do_t2_capture(&cycles, nocount);
135       else
136         do_t2_reload(&cycles, nocount);
137     }// while cycles
138   
139   return(resGO);
140 }
141
142
143 /*
144  * Baud rate generator mode of Timer #2
145  */
146
147 int
148 t_uc52::do_t2_baud(int cycles)
149 {
150   uint t2con= get_mem(MEM_SFR, T2CON);
151   uint p1= get_mem(MEM_SFR, P1);
152
153   /* Baud Rate Generator */
154   if ((prev_p1 & bmT2EX) &&
155       !(p1 & port_pins[1] & bmT2EX) &&
156       (t2con & bmEXEN2))
157     mem(MEM_SFR)->set_bit1(T2CON, bmEXF2);
158   if (t2con & bmC_T2)
159     {
160       if ((prev_p1 & bmT2) &&
161           !(p1 & port_pins[1] & bmT2))
162         cycles= 1;
163       else
164         cycles= 0;
165     }
166   else
167     cycles*= 6;
168   if (t2con & bmTR2)
169     while (cycles--)
170       {
171         if (!/*++(MEM(MEM_SFR)[TL2])*/sfr->add(TL2, 1))
172           if (!/*++(MEM(MEM_SFR)[TH2])*/sfr->add(TH2, 1))
173             {
174               //MEM(MEM_SFR)[TH2]= MEM(MEM_SFR)[RCAP2H];
175               sfr->set(TH2, sfr->get(RCAP2H));
176               //MEM(MEM_SFR)[TL2]= MEM(MEM_SFR)[RCAP2L];
177               sfr->set(TL2, sfr->get(RCAP2L));
178               s_rec_t2++;
179               s_tr_t2++;
180             }
181       }
182   return(resGO);
183 }
184
185
186 /*
187  * Capture function of Timer #2
188  */
189
190 void
191 t_uc52::do_t2_capture(int *cycles, bool nocount)
192 {
193   uint p1= get_mem(MEM_SFR, P1);
194   uint t2con= get_mem(MEM_SFR, T2CON);
195
196   /* Capture mode */
197   if (nocount)
198     *cycles= 0;
199   else
200     {
201       if (!/*++(MEM(MEM_SFR)[TL2])*/sfr->add(TL2, 1))
202         {
203           if (!/*++(MEM(MEM_SFR)[TH2])*/sfr->add(TH2, 1))
204             mem(MEM_SFR)->set_bit1(T2CON, bmTF2);
205         }
206     }
207   // capture
208   if ((prev_p1 & bmT2EX) &&
209       !(p1 & port_pins[1] & bmT2EX) &&
210       (t2con & bmEXEN2))
211     {
212       //MEM(MEM_SFR)[RCAP2H]= MEM(MEM_SFR)[TH2];
213       sfr->set(RCAP2H, sfr->get(TH2));
214       //MEM(MEM_SFR)[RCAP2L]= MEM(MEM_SFR)[TL2];
215       sfr->set(RCAP2L, sfr->get(TL2));
216       mem(MEM_SFR)->set_bit1(T2CON, bmEXF2);
217       prev_p1&= ~bmT2EX; // Falling edge has been handled
218     }
219 }
220
221
222 /*
223  * Auto Reload mode of Timer #2, counting UP
224  */
225
226 void
227 t_uc52::do_t2_reload(int *cycles, bool nocount)
228 {
229   int overflow;
230   bool ext2= 0;
231   
232   /* Auto-Relode mode */
233   overflow= 0;
234   if (nocount)
235     *cycles= 0;
236   else
237     {
238       if (!/*++(MEM(MEM_SFR)[TL2])*/sfr->add(TL2, 1))
239         {
240           if (!/*++(MEM(MEM_SFR)[TH2])*/sfr->add(TH2, 1))
241             {
242               mem(MEM_SFR)->set_bit1(T2CON, bmTF2);
243               overflow++;
244             }
245         }
246     }
247   // reload
248   if ((prev_p1 & bmT2EX) &&
249       !(get_mem(MEM_SFR, P1) & port_pins[1] & bmT2EX) &&
250       (get_mem(MEM_SFR, T2CON) & bmEXEN2))
251     {
252       ext2= DD_TRUE;
253       mem(MEM_SFR)->set_bit1(T2CON, bmEXF2);
254       prev_p1&= ~bmT2EX; // Falling edge has been handled
255     }
256   if (overflow ||
257       ext2)
258     {
259       //MEM(MEM_SFR)[TH2]= MEM(MEM_SFR)[RCAP2H];
260       sfr->set(TH2, sfr->get(RCAP2H));
261       //MEM(MEM_SFR)[TL2]= MEM(MEM_SFR)[RCAP2L];
262       sfr->set(TL2, sfr->get(RCAP2L));
263     }
264 }
265
266
267 /*
268  *
269  */
270
271 int
272 t_uc52::serial_bit_cnt(int mode)
273 {
274   int divby= 12;
275   int *tr_src= 0, *rec_src= 0;
276
277   switch (mode)
278     {
279     case 0:
280       divby  = 12;
281       tr_src = &s_tr_tick;
282       rec_src= &s_rec_tick;
283       break;
284     case 1:
285     case 3:
286       divby  = (get_mem(MEM_SFR, PCON)&bmSMOD)?16:32;
287       tr_src = (get_mem(MEM_SFR, T2CON)&bmTCLK)?(&s_tr_t2):(&s_tr_t1);
288       rec_src= (get_mem(MEM_SFR, T2CON)&bmTCLK)?(&s_rec_t2):(&s_rec_t1);
289       break;
290     case 2:
291       divby  = (get_mem(MEM_SFR, PCON)&bmSMOD)?16:32;
292       tr_src = &s_tr_tick;
293       rec_src= &s_rec_tick;
294       break;
295     }
296   if (s_sending)
297     {
298       while (*tr_src >= divby)
299         {
300           (*tr_src)-= divby;
301           s_tr_bit++;
302         }
303     }
304   if (s_receiving)
305     {
306       while (*rec_src >= divby)
307         {
308           (*rec_src)-= divby;
309           s_rec_bit++;
310         }
311     }
312   return(0);
313 }
314
315
316 /* End of s51.src/uc52.cc */