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