1 /*
2    Copyright (C) 1998,1999 T. Scott Dattalo
3 
4 This file is part of the libgpsim library of gpsim
5 
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
10 
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 Lesser General Public License for more details.
15 
16 You should have received a copy of the GNU Lesser General Public
17 License along with this library; if not, see
18 <http://www.gnu.org/licenses/lgpl-2.1.html>.
19 */
20 
21 #ifndef SRC_USART_H_
22 #define SRC_USART_H_
23 
24 #include <iostream>
25 #include <memory>
26 
27 #include <stdio.h>
28 
29 #include "pic-processor.h"
30 
31 #include "ioports.h"
32 #include "registers.h"
33 #include "trigger.h"
34 
35 class CLKSignalSink;
36 class PIR;
37 class Processor;
38 class RCSignalControl;
39 class RCSignalSource;
40 class RXSignalSink;
41 class TXSignalControl;
42 class TXSignalSource;
43 class USART_MODULE;
44 class _RCSTA;
45 class _SPBRG;
46 class _TXSTA;
47 
48 
49 // USART Data Transmit Register
50 class _TXREG : public sfr_register, public TriggerObject
51 {
52 public:
53 
54     _TXREG(Processor *pCpu, const char *pName, const char *pDesc,USART_MODULE *);
55     virtual void put(unsigned int);
56     virtual void put_value(unsigned int);
assign_txsta(_TXSTA * new_txsta)57     virtual void assign_txsta(_TXSTA *new_txsta) { m_txsta = new_txsta; };
assign_rcsta(_RCSTA * new_rcsta)58     virtual void assign_rcsta(_RCSTA *new_rcsta) { m_rcsta = new_rcsta; };
59     virtual void callback();
60     virtual void callback_print();
61 
62 private:
63     _TXSTA  *m_txsta;
64     _RCSTA  *m_rcsta;
65     USART_MODULE *mUSART;
66     bool full;
67 };
68 
69 // Transmit Status and Control register
70 class _TXSTA : public sfr_register, public TriggerObject
71 {
72 public:
73     _TXREG  *txreg;
74     _SPBRG  *spbrg;
75     _RCSTA  *rcsta;
76 
77     unsigned int tsr;
78     unsigned int bit_count;
79 
80     enum
81     {
82         TX9D  = 1 << 0,
83         TRMT  = 1 << 1,
84         BRGH  = 1 << 2,
85         SENDB = 1 << 3,
86         SYNC  = 1 << 4,
87         TXEN  = 1 << 5,
88         TX9   = 1 << 6,
89         CSRC  = 1 << 7
90     };
91 
92     _TXSTA(Processor *pCpu, const char *pName, const char *pDesc, USART_MODULE *);
93     ~_TXSTA();
94 
95     virtual void put(unsigned int new_value);
96     virtual void put_value(unsigned int new_value);
97 
98     virtual void transmit_a_bit();
99     virtual void start_transmitting();
100     virtual void stop_transmitting();
101     virtual void transmit_break();
102     virtual void callback();
103     virtual void callback_print();
104     virtual char getState();
105 
106     virtual void enableTXPin();
107     virtual void disableTXPin();
108     virtual void setIOpin(PinModule *);
109     virtual void setCKpin(PinModule *ck_pin);
getIOpin()110     virtual PinModule *getIOpin() { return m_PinModule; }
111     virtual void putTXState(char newTXState);
112 
bTXEN()113     bool bTXEN() { return (value.get() & TXEN) != 0; }
bSYNC()114     bool bSYNC() { return (value.get() & SYNC) != 0; }
bTRMT()115     bool bTRMT() { return (value.get() & TRMT) != 0; }
bCSRC()116     bool bCSRC() { return (value.get() & CSRC) != 0; }
bTX9()117     bool bTX9() { return (value.get() & TX9) != 0; }
bTX9D()118     int  bTX9D() { return (value.get() & TX9D) ? 1 : 0; }
119 
set_pin_pol(bool invert)120     void set_pin_pol ( bool invert ) { bInvertPin = invert; };
121     void releasePin();
122 
123 protected:
124     USART_MODULE *mUSART;
125     PinModule *m_PinModule;
126     TXSignalSource *m_source;
127     TXSignalControl *m_control;
128     CLKSignalSink   *m_clkSink;
129     bool		SourceActive;
130     char m_cTxState;
131     bool bInvertPin;
132 };
133 
134 // USART Data Receive Register
135 class _RCREG : public sfr_register
136 {
137 public:
138 
139     unsigned int oldest_value;  /* rcreg has a 2-deep fifo. The oldest received
140 			       * value is stored here, while the most recent
141 			       * is stored in sfr_register.value . */
142 
143     unsigned int fifo_sp;       /* fifo stack pointer */
144 
145     _RCREG(Processor *pCpu, const char *pName, const char *pDesc, USART_MODULE *);
146     virtual unsigned int get();
147     virtual unsigned int get_value();
148     virtual void push(unsigned int);
149     virtual void pop();
150 
assign_rcsta(_RCSTA * new_rcsta)151     virtual void assign_rcsta(_RCSTA *new_rcsta) { m_rcsta = new_rcsta; };
152 
153 private:
154     USART_MODULE *mUSART;
155     _RCSTA  *m_rcsta;
156 };
157 
158 // Receive Status and Control Register
159 class _RCSTA : public sfr_register, public TriggerObject
160 {
161 
162 public:
163     enum
164     {
165         RX9D = 1<<0,
166         OERR = 1<<1,
167         FERR = 1<<2,
168         ADDEN = 1<<3,
169         CREN = 1<<4,
170         SREN = 1<<5,
171         RX9  = 1<<6,
172         SPEN = 1<<7
173     };
174 
175     enum
176     {
177         RCSTA_DISABLED,
178         RCSTA_WAITING_FOR_START,
179         RCSTA_MAYBE_START,
180         RCSTA_WAITING_MID1,
181         RCSTA_WAITING_MID2,
182         RCSTA_WAITING_MID3,
183         RCSTA_RECEIVING
184     };
185 
186     // The usart samples the middle of the bit three times and
187     // produces a sample based on majority averaging.
188     //
189 
190 #define TOTAL_SAMPLE_STATES    16
191 
192 #define BRGH_FIRST_MID_SAMPLE  4
193 #define BRGH_SECOND_MID_SAMPLE 8
194 #define BRGH_THIRD_MID_SAMPLE  12
195 
196 #define BRGL_FIRST_MID_SAMPLE  7
197 #define BRGL_SECOND_MID_SAMPLE 8
198 #define BRGL_THIRD_MID_SAMPLE  9
199 
200     _RCREG  *rcreg;
201     _SPBRG  *spbrg;
202     _TXSTA  *txsta;
203     _TXREG  *txreg;
204 
205     bool sync_next_clock_edge_high;
206     unsigned int rsr;
207     unsigned int bit_count;
208     unsigned int rx_bit;
209     unsigned int sample,state, sample_state;
210     guint64 future_cycle, last_cycle;
211 
212     _RCSTA(Processor *pCpu, const char *pName, const char *pDesc, USART_MODULE *);
213     ~_RCSTA();
214 
215     virtual void put(unsigned int new_value);
216     virtual void put_value(unsigned int new_value);
217     void receive_a_bit(unsigned);
218     void receive_start_bit();
219     virtual void start_receiving();
220     virtual void stop_receiving();
221     virtual void overrun();
222     virtual void callback();
223     virtual void callback_print();
224     void setState(char new_RxState);
225 //RRR  char getDir() { return m_DTdirection;}
bSPEN()226     bool bSPEN() { return (value.get() & SPEN); }
bSREN()227     bool bSREN() { return (value.get() & SREN); }
bCREN()228     bool bCREN() { return (value.get() & CREN); }
bRX9()229     bool bRX9()  { return (value.get() & RX9); }
230     virtual void setIOpin(PinModule *);
rc_is_idle()231     bool rc_is_idle() { return ( state <= RCSTA_WAITING_FOR_START ); };
232     virtual void enableRCPin(char direction = DIR_OUT);
233     virtual void disableRCPin();
234     void releasePin();
getState()235     virtual char getState() { return m_cTxState;}
236     virtual void putRCState(char newRCState);
237     virtual void sync_start_transmitting();
238     virtual void clock_edge(char new3State);
239     void set_old_clock_state(char new3State);
240 
241 
242 protected:
243     enum
244     {
245         DIR_OUT,
246         DIR_IN
247     };
248     void set_callback_break(unsigned int spbrg_edge);
249 
250     USART_MODULE  *mUSART;
251     PinModule     *m_PinModule;
252     RXSignalSink  *m_sink;
253     char          m_cRxState;
254     bool		SourceActive;
255     RCSignalControl *m_control;
256     RCSignalSource  *m_source;
257     char          m_cTxState;
258     char		m_DTdirection;
259     bool          bInvertPin;
260     bool		old_clock_state;
261 };
262 
263 
264 // BAUD Rate Control Register
265 class _BAUDCON : public sfr_register
266 {
267 public:
268     enum
269     {
270         ABDEN  = 1 << 0,
271         WUE    = 1 << 1,
272         BRG16  = 1 << 3,
273         TXCKP  = 1 << 4,
274         SCKP   = 1 << 4,	// synchronous clock polarity Select bit (16f88x)
275         RXDTP  = 1 << 5,
276         RCIDL  = 1 << 6,
277         ABDOVF = 1 << 7
278     };
279 
280     _TXSTA *txsta;
281     _RCSTA *rcsta;
282 
283     _BAUDCON(Processor *pCpu, const char *pName, const char *pDesc);
284 
285     virtual void put(unsigned int);
286     virtual void put_value(unsigned int);
brg16()287     bool brg16() { return ( value.get() & BRG16 ) != 0; };
txckp()288     bool txckp() { return ( value.get() & TXCKP) != 0; }
rxdtp()289     bool rxdtp() { return ( value.get() & RXDTP) != 0; }
290 };
291 
292 // USART Baud Rate Generator, High Byte
293 class _SPBRGH : public sfr_register
294 {
295 public:
296 
297     _SPBRGH(Processor *pCpu, const char *pName, const char *pDesc);
assign_spbrg(_SPBRG * new_spbrg)298     virtual void assign_spbrg(_SPBRG *new_spbrg) { m_spbrg = new_spbrg; };
299     virtual void put(unsigned int);
300     virtual void put_value(unsigned int);
301 private:
302     _SPBRG   *m_spbrg;
303 };
304 
305 // USART Baud Rate Generator, Low Byte
306 class _SPBRG : public sfr_register, public TriggerObject
307 {
308 public:
309     _TXSTA *txsta;
310     _RCSTA *rcsta;
311     _SPBRGH *brgh;
312     _BAUDCON *baudcon;
313 
314     guint64
315     start_cycle,   // The cycle the SPBRG was started
316     last_cycle,    // The cycle when the spbrg clock last changed
317     future_cycle;  // The next cycle spbrg is predicted to change
318 
319     bool running;
320 
321     _SPBRG(Processor *pCpu, const char *pName, const char *pDesc);
322 
323     virtual void callback();
callback_print()324     virtual void callback_print()
325     {
326         std::cout << "_SPBRG " << name() << " CallBack ID " << CallBackID << '\n';
327     }
328     virtual void start();
329     virtual void get_next_cycle_break();
330     virtual guint64 get_cpu_cycle(unsigned int edges_from_now);
331     virtual guint64 get_last_cycle();
332 
333     virtual void put(unsigned int);
334     virtual void put_value(unsigned int);
335     void set_start_cycle();
336 // protected:
337     virtual unsigned int get_cycles_per_tick();
338 private:
339     guint64 skip;
340 };
341 
342 //---------------------------------------------------------------
343 //---------------------------------------------------------------
344 class USART_MODULE: public apfpin
345 {
346 public:
347 
348     enum
349     {
350         TX_PIN = 0,
351         RX_PIN = 1,
352         CK_PIN
353     };
354 
355     _TXSTA       txsta;
356     _RCSTA       rcsta;
357     _SPBRG       spbrg;
358 
359     _TXREG      *txreg;
360     _RCREG      *rcreg;
361     PIR         *pir;
362 
363     // Extra registers for when it's an EUSART
364     _SPBRGH  spbrgh;
365     _BAUDCON baudcon;
366 
367     explicit USART_MODULE(Processor *pCpu);
368     ~USART_MODULE();
369 
370     void initialize(PIR *,
371                     PinModule *tx_pin, PinModule *rx_pin,
372                     _TXREG *, _RCREG *);
373 
374     virtual void setIOpin(PinModule *pin, int data);
375     bool bIsTXempty();
376     void emptyTX();
377     void full();
378     void set_rcif();
379     void clear_rcif();
380     void mk_rcif_int(PIR *reg, unsigned int bit);
381     void mk_txif_int(PIR *reg, unsigned int bit);
IsEUSART()382     bool IsEUSART() { return is_eusart; };
383     void set_eusart ( bool is_it );
384 
385 private:
386     bool is_eusart;
387     std::unique_ptr<InterruptSource> m_rcif;
388     std::unique_ptr<InterruptSource> m_txif;
389 };
390 
391 
392 
393 #endif
394