RETRO ROBOT E

Dependents:   RETRO_ROBOT_SC16IS750E

Fork of SC16IS750 by Wim Huiskamp

Files at this revision

API Documentation at this revision

Comitter:
wim
Date:
Sun Feb 09 14:58:06 2014 +0000
Parent:
0:d64854a60f95
Child:
2:76cb93b511f2
Commit message:
working proto, tested on BOB

Changed in this revision

SC16IS750.cpp Show annotated file Show diff for this revision Revisions of this file
SC16IS750.h Show annotated file Show diff for this revision Revisions of this file
--- a/SC16IS750.cpp	Wed Jan 22 16:39:37 2014 +0000
+++ b/SC16IS750.cpp	Sun Feb 09 14:58:06 2014 +0000
@@ -1,6 +1,5 @@
 /* SC16IS750 interface 
- *   /////////////////////v1.0 Tedd OKANO, 18 Jul 2012, I2C I/F only, MIT License
- *   v1.1 WH, Nov 2013, Added SPI I/F and more methods, MIT License
+ *   v0.1 WH, Nov 2013, Ported to mbed, Sparkfun Libs used as example. Added I2C and SPI I/F and more methods
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
  * and associated documentation files (the "Software"), to deal in the Software without restriction,
@@ -22,7 +21,7 @@
 
 
 /** Abstract class SC16IS750 for converter between either SPI or I2C and a Serial port
-  *
+  * Constructor for this Abstract Class is protected  
   * Supports both SPI and I2C interfaces through derived classes
   *
   * @code
@@ -31,7 +30,8 @@
   */
 //SC16IS750::SC16IS750() : Serial(NC, NC) {   //Fout ???
 SC16IS750::SC16IS750() {  
-  init();  // initialise UART registers
+// Dont call _init() here since the SPI or I2C port have not yet been configured...
+  //_init();  // initialise UART registers
 }
 
 
@@ -46,10 +46,11 @@
   _config.baudrate = baudrate;               // Save baudrate
 
   lcr_tmp = this->readRegister(LCR);                            // Read current LCR register
-  this->writeRegister(LCR, lcr_tmp | LCR_DIV_ENA);              // Enable Divisor registers
+  this->writeRegister(LCR, lcr_tmp | LCR_ENABLE_DIV);           // Enable Divisor registers
   this->writeRegister(DLL, ( divisor       & 0xFF));            //   write divisor LSB
   this->writeRegister(DLH, ((divisor >> 8) & 0xFF));            //   write divisor MSB
   this->writeRegister(LCR, lcr_tmp);                            // Restore LCR register, activate regular RBR, THR and IER registers  
+  
 }
 
 
@@ -101,54 +102,164 @@
 
 };
 
+/** Generate a break condition on the serial line
+  */
+void SC16IS750::send_break() {
+  // Wait for 1.5 frames before clearing the break condition
+  // This will have different effects on our platforms, but should
+  // ensure that we keep the break active for at least one frame.
+  // We consider a full frame (1 start bit + 8 data bits bits + 
+  // 1 parity bit + 2 stop bits = 12 bits) for computation.
+  // One bit time (in us) = 1000000/_baud
+  // Twelve bits: 12000000/baud delay
+  // 1.5 frames: 18000000/baud delay
+  set_break(true);
+  wait_us(18000000/_config.baudrate);
+  set_break(false);    
+};
+    
+/** Set a break condition on the serial line
+  *  @param enable  break condition
+  */
+void SC16IS750::set_break(bool enable) {
 
-/**
-  * Initialise the UART.
+  if (enable) {
+    _config.dataformat |= LCR_BRK_ENA;      // Save dataformat         
+  }
+  else {
+    _config.dataformat &= ~LCR_BRK_ENA;     // Save dataformat           
+  }
+
+  this->writeRegister(LCR, _config.dataformat); // Set LCR register
+}
+
+/** Set the flow control type on the serial port
+  *  Added for compatibility with Serial Class.
+  *  SC16IS750 supports only Flow, Pins can not be selected.
   *
-  * If initialisation fails this method does not return.
+  *  @param type the flow control type (Disabled, RTS, CTS, RTSCTS)     
+  *  @param flow1 the first flow control pin (RTS for RTS or RTSCTS, CTS for CTS)
+  *  @param flow2 the second flow control pin (CTS for RTSCTS)
   */
-void SC16IS750::init() {
+void SC16IS750::set_flow_control(Flow type, PinName flow1, PinName flow2) {
+  char lcr_tmp; 
+  char efr_tmp = 0x00;
+  
+  // We need to enable flow control to prevent overflow of buffers and
+  // lose data when used with fast devices like the WiFly.
+
+  switch (type) {
+     case Disabled : 
+                     break;
+     case RTS:       efr_tmp = EFR_ENABLE_RTS;
+                     break;     
+     case CTS:       efr_tmp = EFR_ENABLE_CTS;                     
+                     break;     
+     case RTSCTS:    efr_tmp = EFR_ENABLE_RTS | EFR_ENABLE_CTS;
+                     break;
+     default:             ;    
+
+  }
+
+  //Save flowcontrol state
+  //enable enhanced functions  
+  _config.flowctrl = efr_tmp | EFR_ENABLE_ENHANCED_FUNCTIONS,
+
+  lcr_tmp = this->readRegister(LCR);                       // save LRC register
+  this->writeRegister(LCR, LCR_ENABLE_ENHANCED_FUNCTIONS); // write magic number 0xBF to enable access to EFR register
+  this->writeRegister(EFR, _config.flowctrl);              // set flow and enable enhanced functions
+  this->writeRegister(LCR, lcr_tmp);                       // restore LCR register
+}  
+ 
+
+/** Initialise internal registers
+  * Should be in protection section. Public for testing purposes
+  * If initialisation fails this method does not return.    
+  *   @param none
+  *   @return none 
+  */
+void SC16IS750::_init() {
 
   // Initialise SC16IS750
 
+  // Software reset, assuming there is no access to the HW Reset pin
+  swReset();
+  
   // Set default baudrate and save in _config
+  // LCR, DLL/DLH  
   baud();
 
   // Set dataflow and save in _config
-  // We need to enable flow control or we overflow buffers and
-  // lose data when used with the WiFly. Note that flow control 
-  // needs to be enabled on the WiFly for this to work but it's
-  // possible to do that with flow control enabled here but not there.
-  // TODO: Make this able to be configured externally?
-  _config.flowctrl = EFR_ENABLE_CTS | EFR_ENABLE_RTS | EFR_ENABLE_ENHANCED_FUNCTIONS,
-
-  this->writeRegister(LCR, 0xBF); // access EFR register
-  this->writeRegister(EFR, _config.flowctrl); // enable enhanced registers
+  // LCR, EFR
+  set_flow_control(); 
   
   // Set default dataformat and save in _config
+  // LCR 
   format();  
 
+  // Set default break condition and save in _config
+  // LCR   
+  //set_break();
+  
   // Set default fifoformat and save in _config
-  this->writeRegister(FCR, 0x06); // reset TXFIFO, reset RXFIFO, non FIFO mode
-  this->writeRegister(FCR, 0x01); // enable FIFO mode   
+  // FCR
+  _config.fifoenable = true;  
+  _config.fifoformat = FCR_RX_IRQ_NONE | FCR_ENA_FIFO_64;
+  flush();
 
   // The UART bridge should now be successfully initialised.
 
-
   // Test if UART bridge is present and initialised
   if(!connected()){ 
 #if(0)  
     // Lock up if we fail to initialise UART bridge.
-    while(1) {
-    };
+    while(1) {};
 #else    
     printf("Failed to initialise UART bridge\r\n");    
+#endif    
+  }
+  else {
+    printf("Initialised UART bridge!\r\n");      
+  }
+
+}
+
+/**
+  * Flush the UART FIFOs while maintaining current FIFO mode.
+  *   @param  none
+  *   @return none
+  */
+void SC16IS750::flush() {
+
+  // reset TXFIFO, reset RXFIFO, non FIFO mode  
+  this->writeRegister(FCR, FCR_TXFIFO_RST | FCR_RXFIFO_RST);
+  
+  if (_config.fifoenable)
+    // enable FIFO mode and set FIFO control values  
+    this->writeRegister(FCR, _config.fifoformat | FCR_ENABLE_FIFO);
+  else
+    // disable FIFO mode and set FIFO control values  
+    this->writeRegister(FCR, _config.fifoformat);
+  
+#if(0)
+//original
+ /*
+   * Flush characters from SC16IS750 receive buffer.
+   */
+
+  // Note: This may not be the most appropriate flush approach.
+  //       It might be better to just flush the UART's buffer
+  //       rather than the buffer of the connected device
+  //       which is essentially what this does.
+  while(readable() > 0) {
+    getc();
   }
 #endif
 
 }
 
 
+
 /**
   * Check that UART is connected and operational.
   *  @param  none
@@ -169,18 +280,10 @@
   *   @return 1 if there is a character available to read, 0 otherwise
   */
 int SC16IS750::readable() {
-  /**
-   * Get the number of chars (characters) available for reading.
-   *
-   * This is data that's already arrived and stored in the receive
-   * buffer (which holds 64 chars).
-   * This alternative just checks if there's data but doesn't
-   * return how many characters are in the buffer:
-   */
   return (this->readRegister(LSR) & 0x01);
 }
 
-/** Determine if how many characters available to read.
+/** Determine how many characters are available to read.
   *   @return int Characters available to read
   */
 int SC16IS750::readableCount() {
@@ -201,12 +304,12 @@
   return (this->writableCount() > 0);  // Check datasheet for faster version
 }
 
-/** Determine if how many characters available to write.
-  *   @return int Characters available to write
+/** Determine how much space available for writing characters.
+  *   @return int character space available to write
   */
 int SC16IS750::writableCount() {
   /*
-   * Get the number of chars (characters) available for reading.
+   * Get the available space for writing characters.
    *
    * This is data that's already stored in the transmit
    * buffer (which holds 64 chars).
@@ -217,15 +320,13 @@
 }
 
 
-
-char SC16IS750::getc() {
-  /*
-   * Read char from UART.
-   *
-   * Returns char read or or -1 if no data available.
-   *
-   * Acts in the same manner as 'Serial.read()'.
-   */
+/**
+  * Read char from UART Bridge.
+  * Acts in the same manner as 'Serial.read()'.  
+  *   @param none    
+  *   @return char read or -1 if no data available. 
+  */ 
+int SC16IS750::getc() {
 
   if (!readable()) {
     return -1;
@@ -234,16 +335,19 @@
   return this->readRegister(RHR);
 }
 
-
-void SC16IS750::putc(char value) {
-  /*
-   * Write char to UART.
-   */
-
+/**
+  * Write char to UART Bridge. Blocking when no free space in FIFO
+  *   @param value char to be written    
+  *   @return value written  
+  */ 
+int SC16IS750::putc(int value) {
   while (this->readRegister(TXLVL) == 0) {
     // Wait for space in TX buffer
+    wait_us(10);
   };
   this->writeRegister(THR, value);
+  
+  return value;
 }
 
 
@@ -254,6 +358,7 @@
   write((const uint8_t *) str, strlen(str));  
   while (this->readRegister(TXLVL) < 64) {
     // Wait for empty TX buffer (slow)
+    wait_us(10);    
     // (But apparently still not slow enough to ensure delivery.)
   };
 }
@@ -279,89 +384,108 @@
 }
 #endif
 
-void SC16IS750::flush() {
-  /*
-   * Flush characters from SC16IS750 receive buffer.
-   */
-
-  // Note: This may not be the most appropriate flush approach.
-  //       It might be better to just flush the UART's buffer
-  //       rather than the buffer of the connected device
-  //       which is essentially what this does.
-  while(readable() > 0) {
-    getc();
-  }
-}
-
-
+/** Set direction of I/O port pins.
+  * This method is specific to the SPI-I2C UART and not found on the 16750
+  *   @param  bits Bitpattern for I/O (1=output, 0=input)
+  *   @return none
+  */
 void SC16IS750::ioSetDirection(unsigned char bits) {
   this->writeRegister(IODIR, bits);
 }
 
-
+/** Set bits of I/O port pins.
+  * This method is specific to the SPI-I2C UART and not found on the 16750
+  *   @param  bits Bitpattern for I/O (1= set output bit, 0 = clear output bit)
+  *   @return none
+  */
 void SC16IS750::ioSetState(unsigned char bits) {
   this->writeRegister(IOSTATE, bits);
 }
 
+/** Get bits of I/O port pins.
+  * This method is specific to the SPI-I2C UART and not found on the 16750
+  *   @param  none
+  *   @return bits Bitpattern for I/O (1= bit set, 0 = bit cleared)
+  */
+unsigned char SC16IS750::ioGetState() {
+  return this->readRegister(IOSTATE) ;
+}
 
 
-// Begin SPI Implementation
+/** Software Reset SC16IS750 device.
+  * This method is specific to the SPI-I2C UART and not found on the 16750
+  *   @param  none
+  *   @return none
+  */
+void SC16IS750::swReset() {
+  this->writeRegister(IOCTRL, IOC_SW_RST);     
+}
+
+
+//
+// End Abstract Class Implementation
 //
 
+
+
 /** Class SC16IS750_SPI for a converter between SPI and a Serial port
   *
+  * @code
+  *
+  * @endcode
+  *
   */
 SC16IS750_SPI::SC16IS750_SPI (SPI *spi, PinName cs) : _spi(spi), _cs(cs)  {
   _cs = 1;  // deselect
   
   _spi->format(8, 0);          
   _spi->frequency(1000000);
- 
+//  _spi->frequency(100000);  //test
+
+  // Dont call _init() until SPI port has been configured.
+  // That is why _init() is not called in parent Constructor 
+  _init();
+
 };
 
 /** Write value to internal register.
   * Pure virtual, must be declared in derived class.   
-  *   @param register_address  The address of the Register (enum RegisterName)
+  *   @param registerAddress   The address of the Register (enum RegisterName)
   *   @param data              The 8bit value to write
   *   @return none 
   */
 void SC16IS750_SPI::writeRegister(RegisterName registerAddress, char data) {
-  /*
-   * Write <data> char to the SC16IS750 register <registerAddress>
-   */
 
   _cs = 0; //  select;
   _spi->write(registerAddress);
   _spi->write(data);
   _cs = 1; //  deselect;
-  
-  
+
+#if(0)  
 //Test only  
   DigitalOut myled2(LED_GREEN);  
   myled2 = 0; //LED On
   wait(0.2);
   myled2 = 1; //LED Off
   wait(0.6);  
+#endif  
 }
 
 
 /** Read value from internal register.
-  *   @param register_address  The address of the Register (enum RegisterName)
+  *   @param registerAddress   The address of the Register (enum RegisterName)
   *   @return char             The 8bit value read from the register
   */
 char SC16IS750_SPI::readRegister(RegisterName registerAddress) {
-  /*
-   * Read char from SC16IS750 register at <registerAddress>.
-   */
 
   // Used in SPI read operations to flush slave's shift register
-  const char SPI_DUMMY_char = 0xFF; 
+  const char SPI_DUMMY_CHAR = 0xFF; 
 
   char result;
 
   _cs = 0; //  select;
   _spi->write(SPI_READ_MODE_FLAG | registerAddress);
-  result = _spi->write(SPI_DUMMY_char);
+  result = _spi->write(SPI_DUMMY_CHAR);
   _cs = 1; //  deselect;
 
   return result;  
@@ -369,23 +493,28 @@
 
 //
 // End SPI Implementation
+//
 
 
-// Begin I2C Implementation
-//
-
 /** Class SC16IS750_I2C for a converter between I2C and a Serial port
   *
+  * @code
+  *
+  * @endcode
+  *
   */
 SC16IS750_I2C::SC16IS750_I2C(I2C *i2c, uint8_t deviceAddress) : _i2c(i2c), _slaveAddress(deviceAddress) {
 
-    _i2c->frequency(400000);
+  _i2c->frequency(400000);
 
+  // Dont call _init() until I2C port has been configured.
+  // That is why _init() is not called in parent Constructor 
+  _init();
 }
 
 
 /** Write value to internal register.
-  *   @param register_address  The address of the Register (enum RegisterName)
+  *   @param registerAddress   The address of the Register (enum RegisterName)
   *   @param data              The 8bit value to write
   *   @return none 
   */
@@ -400,7 +529,7 @@
 
 
 /** Read value from internal register.
-  *   @param register_address  The address of the Register (enum RegisterName)
+  *   @param registerAddress   The address of the Register (enum RegisterName)
   *   @return char             The 8bit value read from the register
   */
 char SC16IS750_I2C::readRegister(RegisterName registerAddress) {
@@ -420,4 +549,5 @@
 
 
 //
-// End I2C Implementation
\ No newline at end of file
+// End I2C Implementation
+//
\ No newline at end of file
--- a/SC16IS750.h	Wed Jan 22 16:39:37 2014 +0000
+++ b/SC16IS750.h	Sun Feb 09 14:58:06 2014 +0000
@@ -1,6 +1,5 @@
 /* SC16IS750 interface 
- *   /////////////////////v1.0 Tedd OKANO, 18 Jul 2012, I2C I/F only, MIT License
- *   v1.1 WH, Nov 2013, Added SPI I/F and more methods, MIT License
+ *   v0.1 WH, Nov 2013, Ported to mbed, Sparkfun Libs used as example. Added I2C and SPI I/F and more methods 
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
  * and associated documentation files (the "Software"), to deal in the Software without restriction,
@@ -20,16 +19,32 @@
 #ifndef _SC16IS750_H
 #define _SC16IS750_H
 
+//I2C Slaveaddresses                     A1  A0 
+#define SC16IS750_SA0           0x90  /* VDD VDD */
+#define SC16IS750_SA1           0x92  /* VDD VSS */
+#define SC16IS750_SA2           0x94  /* VDD SCL */
+#define SC16IS750_SA3           0x95  /* VDD SDA */
+#define SC16IS750_SA4           0x98  /* VSS VDD */
+#define SC16IS750_SA5           0x9A  /* VSS VSS */
+#define SC16IS750_SA6           0x9C  /* VSS SCL */
+#define SC16IS750_SA7           0x9E  /* VSS SDA */
+#define SC16IS750_SA8           0xA0  /* SCL VDD */
+#define SC16IS750_SA9           0xA2  /* SCL VSS */
+#define SC16IS750_SA10          0xA4  /* SCL SCL */
+#define SC16IS750_SA11          0xA6  /* SCL SDA */
+#define SC16IS750_SA12          0xA8  /* SDA VDD */
+#define SC16IS750_SA13          0xAA  /* SDA VSS */
+#define SC16IS750_SA14          0xAC  /* SDA SCL */
+#define SC16IS750_SA15          0xAE  /* SDA SDA */
+
 //Default I2C Slaveaddress
-#define DEFAULT_SC16IS750_ADDR  0x9A
+#define DEFAULT_SC16IS750_ADDR  SC16IS750_SA0
 
 //Default baudrate
 #define DEFAULT_BAUD_RATE       9600
 
 #define ENABLE_BULK_TRANSFERS   0x01
 
-//#include "Configuration.h"
-
 #define XTAL_FREQUENCY 14745600UL // On-board crystal (New mid-2010 Version)
 
 // See datasheet section 7.8 for configuring the
@@ -56,9 +71,10 @@
 #define LCR_BRK_ENA              0x40
 #define LCR_BRK_DIS              0x00
 
-#define LCR_DIV_ENA              0x80
-#define LCR_DIV_DIS              0x00
+#define LCR_ENABLE_DIV           0x80
+#define LCR_DISABLE_DIV          0x00
 
+#define LCR_ENABLE_ENHANCED_FUNCTIONS (0xBF)
 
 // See section 8.10 of the datasheet for definitions
 // of bits in the Enhanced Features Register (EFR)
@@ -66,6 +82,77 @@
 #define EFR_ENABLE_RTS                (1 << 6)
 #define EFR_ENABLE_ENHANCED_FUNCTIONS (1 << 4)
 
+
+// See section 8.xx of the datasheet for definitions
+// of bits in the Flow Control Register (FCR)
+#define FCR_RX_IRQ_14                 (3 << 6)
+#define FCR_RX_IRQ_8                  (2 << 6)
+#define FCR_RX_IRQ_4                  (1 << 6)
+#define FCR_RX_IRQ_1                  (0 << 6)
+#define FCR_RX_IRQ_NONE               (0 << 6)
+#define FCR_ENA_FIFO_64               (1 << 5)
+#define FCR_TXFIFO_RST                (1 << 2)
+#define FCR_RXFIFO_RST                (1 << 1)
+#define FCR_ENABLE_FIFO               (1 << 0)
+
+
+
+/*
+ * Interrupt enable register.
+ */
+
+#define IER_ERBI  (0x01) /* Enable received data available interrupt            */
+#define IER_ETBEI (0x02) /* Enable transmitter holding register empty interrupt */
+#define IER_ELSI  (0x04) /* Enable receiver line status interrupt               */
+#define IER_EDSSI (0x08) /* Enable modem status interrupt                       */
+#define IER_SLEEP (0x10) /* Enable sleep mode                                   */
+
+/*
+ * Modem control register.
+ */
+
+#define MCR_MDTR (0x01) /* Data terminal ready. */
+#define MCR_MRTS (0x02) /* Request to send.     */
+//#define MCR_TCR_TLR_BIT (6)
+#define MCR_ENABLE_TCR_TLR (1 << 2)
+
+/*
+ * Line status register.
+ */
+
+#define LSR_DR   (0x01) /* Data ready                                  */
+#define LSR_OE   (0x02) /* Overrun error                               */
+#define LSR_PE   (0x04) /* Parity error                                */
+#define LSR_FE   (0x08) /* Framing error                               */
+#define LSR_BI   (0x10) /* Break interrupt                             */
+#define LSR_THRE (0x20) /* Transmitter holding register (FIFO empty)   */
+#define LSR_TEMT (0x40) /* Transmitter empty (FIFO and TSR both empty) */
+
+/*
+ * Interrupt identification register.
+ * Bit 0 is set to 0 if an IT is pending.
+ * Bits 1 and 2 are used to identify the IT.
+ */
+
+#define IIR_BITS_USED  (0x07)
+#define IIR_IT_NOT_PENDING (0x01)
+#define IIR_RX_DATA        (0x04)
+#define IIR_TX_EMPTY       (0x02)
+#define IIR_MODEM_STATUS   (0x00)
+
+
+/*
+ * IO Control register.
+ * Bit 0 is set to 0 to enable latch of IO inputs.
+ * Bit 1 is set to enable GPIO[7-4] as /RI, /CD, /DTR, /DST.
+ * Bit 2 is set to enable software reset.
+ */
+#define IOC_ENA_LATCH      (0x01)
+#define IOC_ENA_MODEM      (0x02)
+#define IOC_SW_RST         (0x04)
+
+
+
 // See Chapter 11 of datasheet
 #define SPI_READ_MODE_FLAG      0x80
 
@@ -85,87 +172,192 @@
 
 //  SC16IS750 Register definitions (shifted to align)
     enum RegisterName { 
-        RHR         = 0x00 << 3,
-        THR         = 0x00 << 3,
-        IER         = 0x01 << 3,
-        FCR         = 0x02 << 3,
-        IIR         = 0x02 << 3,
-        LCR         = 0x03 << 3,
-        MCR         = 0x04 << 3,
-        LSR         = 0x05 << 3,
-        MSR         = 0x06 << 3,
-        SPR         = 0x07 << 3,
-        TCR         = 0x06 << 3,
-        TLR         = 0x07 << 3,
-        TXLVL       = 0x08 << 3,
-        RXLVL       = 0x09 << 3,
-        IODIR       = 0x0A << 3,
-        IOSTATE     = 0x0B << 3,
-        IOINTMSK    = 0x0C << 3,
-        reserved    = 0x0D << 3,
-        IOCTRL      = 0x0E << 3,
-        EFCR        = 0x0F << 3,
-        DLL         = 0x00 << 3,
-        DLH         = 0x01 << 3,
-        EFR         = 0x02 << 3,
-        XON1        = 0x04 << 3,
-        XON2        = 0x05 << 3,
-        XOFF1       = 0x06 << 3,
-        XOFF2       = 0x07 << 3,
+/*
+ * 16750 addresses. Registers accessed when LCR[7] = 0.
+ */   
+        RHR         = 0x00 << 3, /* Rx buffer register     - Read access  */
+        THR         = 0x00 << 3, /* Tx holding register    - Write access */
+        IER         = 0x01 << 3, /* Interrupt enable reg   - RD/WR access */
+
+/*
+ * 16750 addresses. Registers accessed when LCR[7] = 1.
+ */       
+        DLL         = 0x00 << 3, /* Divisor latch (LSB)    - RD/WR access */
+        DLH         = 0x01 << 3, /* Divisor latch (MSB)    - RD/WR access */
+
+/*
+ * 16750 addresses. IIR/FCR is accessed when LCR[7:0] <> 0xBF.
+ *                  Bit 5 of the FCR register is accessed when LCR[7] = 1.
+ */       
+        IIR         = 0x02 << 3, /* Interrupt id. register - Read only    */
+        FCR         = 0x02 << 3, /* FIFO control register  - Write only   */
+/*
+ * 16750 addresses. EFR is accessed when LCR[7:0] = 0xBF.
+ */       
+        EFR         = 0x02 << 3, /* Enhanced features reg  - RD/WR access */     
+
+/*
+ * 16750 addresses.
+ */       
+        LCR         = 0x03 << 3, /* Line control register  - RD/WR access */
+/*
+ * 16750 addresses. MCR/LSR is accessed when LCR[7:0] <> 0xBF.
+ *                  Bit 7 of the MCR register is accessed when EFR[4] = 1.
+ */       
+        MCR         = 0x04 << 3, /* Modem control register - RD/WR access */
+        LSR         = 0x05 << 3, /* Line status register   - Read only    */
+ 
+/*
+ * 16750 addresses. MSR/SPR is accessed when LCR[7:0] <> 0xBF.
+ *                  MSR, SPR register is accessed when EFR[1]=0 and MCR[2]=0.
+ */       
+        MSR         = 0x06 << 3, /* Modem status register  - Read only    */
+        SPR         = 0x07 << 3, /* Scratchpad register    - RD/WR access */
+/*
+ * 16750 addresses. TCR/TLR is accessed when LCR[7:0] <> 0xBF.
+ *                  TCR, TLR register is accessed when EFR[1]=1 and MCR[2]=1.
+ */       
+        TCR         = 0x06 << 3, /* Transmission control register - RD/WR access */
+        TLR         = 0x07 << 3, /* Trigger level register        - RD/WR access */
+
+/*
+ * 16750 addresses. XON, XOFF is accessed when LCR[7:0] = 0xBF.
+ */       
+        XON1        = 0x04 << 3, /* XON1 register          - RD/WR access */
+        XON2        = 0x05 << 3, /* XON2 register          - RD/WR access */
+        XOFF1       = 0x06 << 3, /* XOFF1 register         - RD/WR access */
+        XOFF2       = 0x07 << 3, /* XOFF2 register         - RD/WR access */
+
+/*
+ * 16750 addresses.
+ */       
+        TXLVL       = 0x08 << 3, /* TX FIFO Level register - Read only    */
+        RXLVL       = 0x09 << 3, /* RX FIFO Level register - Read only    */
+        IODIR       = 0x0A << 3, /* IO Pin Direction reg   - RD/WR access */
+        IOSTATE     = 0x0B << 3, /* IO Pin State reg       - Read only    */
+        IOINTENA    = 0x0C << 3, /* IO Interrupt Enable    - RD/WR access */
+//        reserved    = 0x0D << 3,
+        IOCTRL      = 0x0E << 3, /* IO Control register    - RD/WR access */
+        EFCR        = 0x0F << 3, /* Extra features reg     - RD/WR access */
+
     } ;
 
 
+ // This enum used to be part of SerialBase class (access via SerialBase.h).
+ //  It seems not be supported anymore. The enums for Parity have moved to Serial now..  
+    enum Flow {
+        Disabled = 0,
+        RTS,
+        CTS,
+        RTSCTS
+    };
+ 
+  
 // SC16IS750 configuration register values
+// Several configuration registers are write-only. Need to save values to allow restoring.
 struct SC16IS750_cfg {
   char baudrate;
   char dataformat;  
   char flowctrl;  
-  char fifoformat;    
+  char fifoformat;
+  bool fifoenable;      
 };
 
-/** Constructor
-  *  
-  */
-  SC16IS750();  
 
 /** Determine if there is a character available to read.
   *   @return 1 if there is a character available to read, 0 otherwise
   */
-    int readable();
+  int readable();
 
-/** Determine if how many characters available to read.
+/** Determine how many characters available for reading.
   *   @return int Characters available to read
   */
-    int readableCount();
+  int readableCount();
 
 /** Determine if there is space available to write a character.    
   *   @return 1 if there is a space for a character to write, 0 otherwise
   */
-    int writable();
+  int writable();
 
-/** Determine if how much space is available to write characters.
-  *   @return int Characterspace available for writing
+/** Determine how much space available for writing characters.
+  *   @return int character space available to write
   */
-    int writableCount();
-        
-    char getc();  
-    void putc(char value);    
+  int writableCount();
+
 
-    void write(const char *str);
+/**
+  * Read char from UART Bridge.
+  * Acts in the same manner as 'Serial.read()'.  
+  *   @param none    
+  *   @return char read or -1 if no data available. 
+  */ 
+  int getc();  
+  
+/**
+  * Write char to UART Bridge. Blocking when no free space in FIFO
+  *   @param value char to be written    
+  *   @return value written  
+  */
+  int putc(int value);    
+
+  void write(const char *str);
     
 /** Set baudrate of the serial port.    
   *  @param  baud integer baudrate (4800, 9600 etc)
   *  @return none
   */
-    void baud(int baudrate = DEFAULT_BAUD_RATE);   
+  void baud(int baudrate = DEFAULT_BAUD_RATE);   
 
 /** Set the transmission format used by the serial port.   
   *   @param bits      The number of bits in a word (5-8; default = 8)
   *   @param parity    The parity used (Serial::None, Serial::Odd, Serial::Even, Serial::Forced1, Serial::Forced0; default = Serial::None)
   *   @param stop_bits The number of stop bits (1 or 2; default = 1) 
   */
-    void format(int bits=8, Serial::Parity parity=Serial::None, int stop_bits=1);
+  void format(int bits=8, Serial::Parity parity=Serial::None, int stop_bits=1);
+#if(0)
+/** Attach a function to call whenever a serial interrupt is generated
+  *
+  *  @param fptr A pointer to a void function, or 0 to set as none
+  *  @param type Which serial interrupt to attach the member function to (Seriall::RxIrq for receive, TxIrq for transmit buffer empty)
+  */
+  void attach(void (*fptr)(void), IrqType type=RxIrq);
+ 
+/** Attach a member function to call whenever a serial interrupt is generated
+  *
+  *  @param tptr pointer to the object to call the member function on
+  *  @param mptr pointer to the member function to be called
+  *  @param type Which serial interrupt to attach the member function to (Seriall::RxIrq for receive, TxIrq for transmit buffer empty)
+  */
+  template<typename T>
+    void attach(T* tptr, void (T::*mptr)(void), IrqType type=RxIrq) {
+      if((mptr != NULL) && (tptr != NULL)) {
+          _irq[type].attach(tptr, mptr);
+          serial_irq_set(&_serial, (SerialIrq)type, 1);
+      }
+  }
+#endif
+ 
+/** Generate a break condition on the serial line
+  */
+  void send_break();
 
+
+/** Set a break condition on the serial line
+  *  @param enable  break condition
+  */
+  void set_break(bool enable=false);
+    
+
+/** Set the flow control type on the serial port
+  *  Added for compatibility with Serial Class.
+  *  SC16IS750 supports only Flow, Pins can not be selected.  
+  *
+  *  @param type the flow control type (Disabled, RTS, CTS, RTSCTS)     
+  *  @param flow1 the first flow control pin (RTS for RTS or RTSCTS, CTS for CTS)
+  *  @param flow2 the second flow control pin (CTS for RTSCTS)
+  */
+  void set_flow_control(Flow type=Disabled, PinName flow1=NC, PinName flow2=NC);
+ 
 /**
   * Check that UART is connected and operational.
   *   @param  none
@@ -179,38 +371,85 @@
 #else
  //   using Print::write;
 #endif
-    void flush();
+
+/** Flush the UART FIFOs while maintaining current FIFO mode.
+  *   @param  none
+  *   @return none
+  */
+  void flush();
 
 //required for Stream
-    int peek() {return 0;};
+  int peek() {return 0;};
+
+
+/** Set direction of I/O port pins.
+  * This method is specific to the SPI-I2C UART and not found on the 16750
+  *   @param  bits Bitpattern for I/O (1=output, 0=input)
+  *   @return none
+  */
+  void ioSetDirection(unsigned char bits);
 
-    // These are specific to the SPI UART
-    void ioSetDirection(unsigned char bits);
-   void ioSetState(unsigned char bits);
+/** Set bits of I/O port pins.
+  * This method is specific to the SPI-I2C UART and not found on the 16750
+  *   @param  bits Bitpattern for I/O (1= set output bit, 0 = clear output bit)
+  *   @return none
+  */
+  void ioSetState(unsigned char bits);
+
+/** Get bits of I/O port pins.
+  * This method is specific to the SPI-I2C UART and not found on the 16750
+  *   @param  none
+  *   @return bits Bitpattern for I/O (1= bit set, 0 = bit cleared)
+  */
+  unsigned char ioGetState();
+
+
+/** Software Reset SC16IS750 device.
+  * This method is specific to the SPI-I2C UART and not found on the 16750
+  *   @param  none
+  *   @return none
+  */
+  void swReset();
+
 
 /** Write value to internal register.
   * Pure virtual, must be declared in derived class.   
-  *   @param register_address  The address of the Register (enum RegisterName)
+  *   @param registerAddress   The address of the Register (enum RegisterName)
   *   @param data              The 8bit value to write
   *   @return none 
   */
-   virtual void writeRegister (RegisterName register_address, char data ) =0;
+  virtual void writeRegister (RegisterName register_address, char data ) =0;
 
 /** Read value from internal register.
   * Pure virtual, must be declared in derived class.   
-  *   @param register_address  The address of the Register (enum RegisterName)
+  *   @param registerAddress   The address of the Register (enum RegisterName)
   *   @return char             The 8bit value read from the register
   */
-   virtual char readRegister (RegisterName register_address ) =0;
+  virtual char readRegister (RegisterName register_address ) =0;
+
 
+/** Initialise internal registers
+  * Should be in protection section. Public for testing purposes
+  * If initialisation fails this method does not return.    
+  *   @param none
+  *   @return none 
+  */
+  void _init();
+  
 protected:
 //protected is accessible to derived classes, but not to external users
 
+/** Constructor for this Abstract Class is protected
+  *  
+  */
+  SC16IS750();  
+
+
 SC16IS750_cfg _config;
 
 private:
 //private is not accessible to derived classes, nor external users
-    void init();
+
 };
 
 
@@ -249,14 +488,14 @@
   SC16IS750_SPI(SPI *spi, PinName cs);
 
 /** Write value to internal register.
-  *   @param register_address  The address of the Register (enum RegisterName)
+  *   @param registerAddress   The address of the Register (enum RegisterName)
   *   @param data              The 8bit value to write
   *   @return none 
   */
   virtual void writeRegister(SC16IS750::RegisterName registerAddress, char data);
 
 /** Read value from internal register.
-  *   @param register_address  The address of the Register (enum RegisterName)
+  *   @param registerAddress   The address of the Register (enum RegisterName)
   *   @return char             The 8bit value read from the register
   */
   virtual char readRegister(SC16IS750::RegisterName registerAddress);
@@ -307,14 +546,14 @@
   SC16IS750_I2C(I2C *i2c, uint8_t deviceAddress = DEFAULT_SC16IS750_ADDR);
 
 /** Write value to internal register.
-  *   @param register_address  The address of the Register (enum RegisterName)
+  *   @param registerAddress   The address of the Register (enum RegisterName)
   *   @param data              The 8bit value to write
   *   @return none 
   */
   virtual void writeRegister(SC16IS750::RegisterName register_address, char data );
 
 /** Read value from internal register.
-  *   @param register_address  The address of the Register (enum RegisterName)
+  *   @param registerAddress   The address of the Register (enum RegisterName)
   *   @return char             The 8bit value read from the register
   */
   virtual char readRegister(SC16IS750::RegisterName register_address );