SC16IS740 I2C to UART Bridge, based on SC16IS750 by Wim Huiskamp https://os.mbed.com/users/wim/code/SC16IS750/

Dependents:   SC16IS740_test

Files at this revision

API Documentation at this revision

Comitter:
elelthvd
Date:
Wed Aug 12 05:16:11 2020 +0000
Commit message:
Renames for use with SC16IS740 on the Mikroe UART I2C/SPI Click board and updated Mbed OS 6 calls.;

Changed in this revision

SC16IS740.cpp Show annotated file Show diff for this revision Revisions of this file
SC16IS740.h Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r db4396ad001f SC16IS740.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SC16IS740.cpp	Wed Aug 12 05:16:11 2020 +0000
@@ -0,0 +1,1190 @@
+/* SC16IS740 I2C or SPI to UART bridge 
+ *   v0.1 WH, Nov 2013, Sparkfun WiFly Shield code library alpha 0 used as example, Added I2C I/F and many more methods.
+ *                      https://forum.sparkfun.com/viewtopic.php?f=13&t=21846
+ *   v0.2 WH, Feb 2014, Added Doxygen Documentation, Added Hardware Reset pin methods. 
+ *   v0.3 WH, Dec 2014, Added support for SC16IS752 dual UART.  
+ *   v0.4 WH, Dec 2014, Added Repeated Start for I2C readRegister(). Set I2C clock at 100kb/s. Fixed and added some comments.
+ *   v0.5 LVD, Aug 2020, Renames for use with SC16IS740 on the Mikroe UART I2C/SPI Click board and updated Mbed OS 6 calls.
+ *
+ * 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,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include    "mbed.h"
+#include    "SC16IS740.h"
+
+#define ENABLE_BULK_TRANSFERS             1
+#define BULK_BLOCK_LEN                   16
+
+/**
+    The SC16IS740 is functionally and electrically
+    identical to the SC16IS740, with the exception of the programmable I/O pins which are
+    only present on the SC16IS740.
+ */
+/** Abstract class SC16IS740 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
+  *
+  * @endcode
+  */
+SC16IS740::SC16IS740() { 
+//SC16IS740::SC16IS740() : Serial(NC, NC) {   //Fout, mag geen NC zijn
+//SC16IS740::SC16IS740() : SerialBase(NC, NC) { //Fout, mag geen NC zijn
+// Dont call _init() here since the SPI or I2C port have not yet been configured...
+  //_init();  // initialise UART registers
+}
+
+
+/** Set baudrate of the serial port.    
+  *  @param  baud integer baudrate (4800, 9600 etc)
+  *  @return none
+  */
+void SC16IS740::baud(int baudrate) {
+  unsigned long divisor = SC16IS740_BAUDRATE_DIVISOR(baudrate);
+  char lcr_tmp;
+  
+  _config.baudrate = baudrate;               // Save baudrate
+
+  lcr_tmp = this->readRegister(LCR);                            // Read current LCR register
+  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  
+  
+}
+
+
+/** 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) 
+  *   @return none   
+  */
+void SC16IS740::format(int bits, BufferedSerial::Parity parity, int stop_bits) {
+  char lcr_tmp = 0x00;
+  
+  switch (bits) {
+    case 5:  lcr_tmp |= LCR_BITS5;
+             break;
+    case 6:  lcr_tmp |= LCR_BITS6;
+             break;
+    case 7:  lcr_tmp |= LCR_BITS7;
+             break;
+    case 8:  lcr_tmp |= LCR_BITS8;
+             break;
+    default: lcr_tmp |= LCR_BITS8;     
+  }
+
+  switch (parity) {
+    case BufferedSerial::None:    lcr_tmp |= LCR_NONE;
+                          break;
+    case BufferedSerial::Odd:     lcr_tmp |= LCR_ODD;
+                          break;
+    case BufferedSerial::Even:    lcr_tmp |= LCR_EVEN;
+                          break;
+    case BufferedSerial::Forced1: lcr_tmp |= LCR_FORCED1;
+                          break;
+    case BufferedSerial::Forced0: lcr_tmp |= LCR_FORCED0;
+                          break;                      
+    default:              lcr_tmp |= LCR_NONE;     
+  }
+
+  switch (stop_bits) {
+    case 1:  lcr_tmp |= LCR_BITS1;
+             break;
+    case 2:  lcr_tmp |= LCR_BITS2;
+             break;
+    default: lcr_tmp |= LCR_BITS1;     
+  }
+
+  _config.dataformat = lcr_tmp;      // Save dataformat   
+
+  this->writeRegister(LCR, lcr_tmp); // Set LCR register, activate regular RBR, THR and IER registers  
+
+};
+
+/** Generate a break condition on the serial line
+  *  @return none 
+  */
+void SC16IS740::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
+  *  @return none   
+  */
+void SC16IS740::set_break(bool enable) {
+
+  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.
+  *  SC16IS740 supports only Flow, Pins can not be selected.
+  *  This method sets hardware flow control. SC16IS740 supports XON/XOFF, but this is not implemented.  
+  *
+  *  @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) - NOT USED
+  *  @param flow2 the second flow control pin (CTS for RTSCTS) - NOT USED
+  *  @return none   
+  */
+void SC16IS740::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 mode and 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
+}  
+
+/** Set the RX FIFO flow control levels
+  *  This method sets hardware flow control levels. SC16IS740 supports XON/XOFF, but this is not implemented.
+  *  Should be called BEFORE Auto RTS is enabled.  
+  *
+  *  @param resume trigger level to resume transmission (0..15, meaning 0-60 with a granularity of 4)     
+  *  @param halt trigger level to resume transmission (0..15, meaning 0-60 with granularity of 4)       
+  *  @return none   
+  */
+void SC16IS740::set_flow_triggers(int resume, int halt) {
+
+  // sanity checks
+  halt = halt & 0x0F;
+  resume = resume & 0x0F;  
+  if (halt <= resume) {
+    halt   = TCR_HALT_DEFAULT;
+    resume = TCR_RESUME_DEFAULT;  
+  }
+
+  // Note: TCR accessible only when EFR[4]=1 and MCR[2]=1
+  this->writeRegister(TCR, (resume << 4) | halt);          // set TCR register
+}
+
+
+/** Set the Modem Control register
+  *  This method sets prescaler, enables TCR and TLR
+  *
+  *  @param none 
+  *  @return none 
+  */
+void SC16IS740::set_modem_control() {
+
+  //Note MCR[7:4] and MCR[2] only accessible when EFR[4] is set
+  if (SC16IS740_PRESCALER == SC16IS740_PRESCALER_1) { // Default prescaler after reset
+    this->writeRegister(MCR, MCR_PRESCALE_1 | MCR_ENABLE_TCR_TLR);
+  }  
+  else { 
+    this->writeRegister(MCR, MCR_PRESCALE_4 | MCR_ENABLE_TCR_TLR);
+  }
+}  
+
+ 
+
+/** 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 SC16IS740::_init() {
+
+  // Initialise SC16IS740
+
+  // Hardware reset, assuming there is a HW Reset pin
+  this->hwReset();  
+
+  // Software reset, assuming there is no access to the HW Reset pin
+  swReset();
+  
+  // Set default baudrate (depends on prescaler) and save in _config
+  // DLL/DLH  
+  baud();
+
+  // Set default dataformat and save in _config
+  // LCR 
+  format();  
+
+  // Set dataflow mode and Enables enhanced functions
+  // Save in _config
+  // EFR
+  set_flow_control(); 
+  
+
+  // FIFO control, sets TX and RX IRQ trigger levels and enables FIFO and save in _config
+  // Note FCR[5:4] only accessible when EFR[4] is set (enhanced functions enable)
+  // FCR, TLR
+  set_fifo_control();
+  flush();
+
+  // Modem control, sets prescaler, enable TCR and TLR
+  // Note MCR[7:4] and MCR[2] only accessible when EFR[4] is set (enhanced functions enable)
+  set_modem_control();
+
+  // Set RTS trigger levels
+  // Note TCR only accessible when EFR[4] is set (enhanced functions enable) and MCR[2] is set
+  set_flow_triggers();
+
+
+  // Set default break condition and save in _config
+  // LCR   
+  //set_break();
+ 
+  // 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) {};
+#else    
+    printf("Failed to initialise UART bridge\r\n");    
+#endif    
+  }
+  else {
+    printf("Initialised UART bridge!\r\n");      
+  }
+
+}
+
+
+/** FIFO control, sets TX and RX trigger levels and enables FIFO and save in _config
+  *  Note FCR[5:4] (=TX_IRQ_LVL) only accessible when EFR[4] is set (enhanced functions enable)
+  *  Note TLR only accessible when EFR[4] is set (enhanced functions enable) and MCR[2] is set 
+  *   @param  none
+  *   @return none
+  */
+void SC16IS740::set_fifo_control() {
+
+  // Set default fifoformat 
+  // FCR
+  _config.fifoenable = true;  
+
+  // Note FCR[5:4] (=TX_IRQ_LVL) only accessible when EFR[4] is set (enhanced functions enable)
+//  _config.fifoformat = FCR_RX_IRQ_8 | FCR_TX_IRQ_56;
+  _config.fifoformat = FCR_RX_IRQ_8 | FCR_TX_IRQ_8;  //Default
+
+  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);
+
+  // Set Trigger level register TLR for RX and TX interrupt generation
+  // Note TLR only accessible when EFR[4] is set (enhanced functions enable) and MCR[2] is set
+  //   TRL Trigger levels for RX and TX are 0..15, meaning 0-60 with a granularity of 4 chars    
+  // When TLR for RX or TX are 'Zero' the corresponding values in FCR are used. The FCR settings
+  // have less resolution (only 4 levels) so TLR is considered an enhanced function.
+  this->writeRegister(TLR, 0x00);                                     // Use FCR Levels
+//  this->writeRegister(TLR, (TLR_RX_DEFAULT << 4) | TLR_TX_DEFAULT);   // Use Default enhanced levels
+
+}    
+
+
+/**
+  * Flush the UART FIFOs while maintaining current FIFO mode.
+  *   @param  none
+  *   @return none
+  */
+void SC16IS740::flush() {
+  // FCR is Write Only, use saved _config
+
+  // reset TXFIFO, reset RXFIFO, non FIFO mode  
+  this->writeRegister(FCR, FCR_TX_FIFO_RST | FCR_RX_FIFO_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 SC16IS740 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
+  *  @return bool true when connected, false otherwise
+  */
+bool SC16IS740::connected() {
+  // Perform read/write test to check if UART is working
+  const char TEST_CHARACTER = 'H';
+
+  this->writeRegister(SPR, TEST_CHARACTER);
+
+  return (this->readRegister(SPR) == TEST_CHARACTER);
+}
+
+
+/** Determine if there is a character available to read.
+  * This is data that's already arrived and stored in the receive
+  * buffer (which holds 64 chars).
+  *
+  *   @return 1 if there is a character available to read, 0 otherwise
+  */
+int SC16IS740::readable() {
+  
+//  if (this->readableCount() > 0) { // Check count
+  if (this->readRegister(LSR) & LSR_DR) { // Data in Receiver Bit, at least one character waiting
+    return 1;
+  }
+  else {
+    return 0; 
+  }
+}
+
+/** Determine how many characters are available to read.
+  * This is data that's already arrived and stored in the receive
+  * buffer (which holds 64 chars).
+  *
+  *   @return int Characters available to read
+  */
+int SC16IS740::readableCount() {
+
+  return (this->readRegister(RXLVL));
+}
+
+/** 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 SC16IS740::writable() {
+ 
+//  if ((this->writableCount() > 0) { // Check count
+  if (this->readRegister(LSR) & LSR_THRE) { // THR Empty, space for at least one character
+    return 1;
+  }
+  else {
+    return 0;  
+  }
+}
+
+/** Determine how much space available for writing characters.
+  * This considers data that's already stored in the transmit
+  * buffer (which holds 64 chars).
+  *
+  *   @return int character space available to write
+  */
+int SC16IS740::writableCount() {
+
+  return (this->readRegister(TXLVL));  // TX Level
+}
+
+
+/**
+  * 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 SC16IS740::getc() {
+
+  if (!readable()) {
+    return -1;
+  }
+
+  return this->readRegister(RHR);
+}
+
+
+/**
+  * Write char to UART Bridge. Blocking when no free space in FIFO
+  *   @param value char to be written    
+  *   @return value written  
+  */ 
+int SC16IS740::putc(int value) {
+
+  while (this->readRegister(TXLVL) == 0) {
+    // Wait for space in TX buffer
+    wait_us(10);
+  };
+  this->writeRegister(THR, value);
+  
+  return value;
+}
+
+
+/**
+  * Write char string to UART Bridge. Blocking when no free space in FIFO
+  *   @param *str char string to be written    
+  *   @return none  
+  */
+void SC16IS740::writeString(const char *str) {
+
+#if ENABLE_BULK_TRANSFERS
+  int len, idx;
+  
+  len = strlen(str);  
+
+  // Write blocks of BULK_BLOCK_LEN  
+  while (len > BULK_BLOCK_LEN) {
+    while(this->readRegister(TXLVL) < BULK_BLOCK_LEN) {
+      // Wait for space in TX buffer
+      wait_us(10);
+    };  
+  
+    // Write a block of BULK_BLOCK_LEN bytes
+#if (0)    
+    // Note: can be optimized by writing registeraddress once and then repeatedly write the bytes.
+    for (idx=0; idx<BULK_BLOCK_LEN; idx++) {
+      this->writeRegister(THR, str[idx]);
+    };
+#else
+    // optimized
+    this->writeDataBlock(str, BULK_BLOCK_LEN);    
+#endif
+              
+    len -= BULK_BLOCK_LEN;
+    str += BULK_BLOCK_LEN;
+  }
+  
+  // Write remaining bytes 
+  // Note: can be optimized by writing registeraddress once and then repeatedly write the bytes.  
+  for (idx=0; idx<len; idx++) {
+    while (this->readRegister(TXLVL) == 0) {
+      // Wait for space in TX buffer
+      wait_us(10);
+    };
+    this->writeRegister(THR, str[idx]);
+  }  
+
+
+#else
+  // Single writes instead of bulktransfer
+  int len, idx;
+  
+  len = strlen(str);
+  for (idx=0; idx<len; idx++) {
+    while (this->readRegister(TXLVL) == 0) {
+      // Wait for space in TX buffer
+      wait_us(10);
+    };
+    this->writeRegister(THR, str[idx]);
+  }  
+#endif  
+}
+
+
+/**
+  * Write byte array to UART Bridge. Blocking when no free space in FIFO
+  *   @param *data byte array to be written    
+  *   @param len   number of bytes to write  
+  *   @return none  
+  */
+void SC16IS740::writeBytes(const char *data, int len) {
+
+#if ENABLE_BULK_TRANSFERS
+  int idx;
+  
+  // Write blocks of BULK_BLOCK_LEN  
+  while (len > BULK_BLOCK_LEN) {
+    while(this->readRegister(TXLVL) < BULK_BLOCK_LEN) {
+      // Wait for space in TX buffer
+      wait_us(10);
+    };  
+  
+    // Write a block of BULK_BLOCK_LEN bytes
+#if (0)    
+    // Note: can be optimized by writing registeraddress once and then repeatedly write the bytes.
+    for (idx=0; idx<BULK_BLOCK_LEN; idx++) {
+      this->writeRegister(THR, data[idx]);
+    };
+#else
+    // optimized
+    this->writeDataBlock(data, BULK_BLOCK_LEN);    
+#endif
+              
+    len  -= BULK_BLOCK_LEN;
+    data += BULK_BLOCK_LEN;
+  }
+  
+  // Write remaining bytes 
+  // Note: can be optimized by writing registeraddress once and then repeatedly write the bytes.  
+  for (idx=0; idx<len; idx++) {
+    while (this->readRegister(TXLVL) == 0) {
+      // Wait for space in TX buffer
+      wait_us(10);
+    };
+    this->writeRegister(THR, data[idx]);
+  }  
+
+
+#else
+  // Single writes instead of bulktransfer
+  int idx;
+  
+  for (idx=0; idx<len; idx++) {
+    while (this->readRegister(TXLVL) == 0) {
+      // Wait for space in TX buffer
+      wait_us(10);
+    };
+    this->writeRegister(THR, str[idx]);
+  }  
+#endif  
+}
+
+
+/** Set direction of I/O port pins.
+  * This method is specific to the SPI-I2C UART and not found on the 16750
+  * Note: The SC16IS752 does not have separate GPIOs for Channel_A and Channel_B.
+  *   @param  bits Bitpattern for I/O (1=output, 0=input)
+  *   @return none
+  */
+void SC16IS740::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
+  * Note: The SC16IS752 does not have separate GPIOs for Channel_A and Channel_B.  
+  *   @param  bits Bitpattern for I/O (1= set output bit, 0 = clear output bit)
+  *   @return none
+  */
+void SC16IS740::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
+  * Note: The SC16IS752 does not have separate GPIOs for Channel_A and Channel_B.  
+  *   @param  none
+  *   @return bits Bitpattern for I/O (1= bit set, 0 = bit cleared)
+  */
+unsigned char SC16IS740::ioGetState() {
+  return this->readRegister(IOSTATE) ;
+}
+
+
+/** Software Reset SC16IS740 device.
+  * This method is specific to the SPI-I2C UART and not found on the 16750
+  * Note: The SC16IS752 does not have separate Reset for Channel_A and Channel_B.  
+  *   @param  none
+  *   @return none
+  */
+void SC16IS740::swReset() {
+  this->writeRegister(IOCTRL, IOC_SW_RST);     
+}
+
+
+//
+// End Abstract Class Implementation
+//
+
+
+
+//
+// Begin SPI Class Implementation
+//
+
+
+/** Create an SC16IS740_SPI object using a specified SPI bus and CS
+  *
+  * @param SPI &spi the SPI port to connect to 
+  * @param cs  Pinname of the CS pin (active low)
+  * @param rst Pinname for Reset pin (active low) Optional, Default = NC 
+  */    
+SC16IS740_SPI::SC16IS740_SPI (SPI *spi, PinName cs, PinName rst) : _spi(spi), _cs(cs)  {
+  _cs = 1;  // deselect
+  
+  _spi->format(8, 0);          
+  _spi->frequency(1000000);
+
+  // The hardware Reset pin is optional. Test and make sure whether it exists or not to prevent illegal access.
+  if (rst != NC) {
+    _reset = new DigitalOut(rst);   //Construct new pin 
+    _reset->write(1);               //Deactivate    
+  }
+  else {
+    // No Hardware Reset pin       
+    _reset = NULL;                  //Construct dummy pin     
+  }  
+
+
+  // Dont call _init() until SPI port has been configured.
+  // That is why _init() is not called in parent Constructor 
+  _init();
+
+};
+
+
+/** Destruct SC16IS740_SPI bridge object
+  *
+  * @param  none
+  * @return none
+  */ 
+SC16IS740_SPI::~SC16IS740_SPI() {
+   if (_reset != NULL) {delete _reset;}  // Reset pin
+}
+
+/** Write value to internal register.
+  * Pure virtual, must be declared in derived class.   
+  *   @param registerAddress   The address of the Register (enum RegisterName)
+  *   @param data              The 8bit value to write
+  *   @return none 
+  */
+void SC16IS740_SPI::writeRegister(RegisterName registerAddress, char data) {
+
+  _cs = 0; //  select;
+  _spi->write(registerAddress);
+  _spi->write(data);
+  _cs = 1; //  deselect;
+
+}
+
+
+/** Read value from internal register.
+  *   @param registerAddress   The address of the Register (enum RegisterName)
+  *   @return char             The 8bit value read from the register
+  */
+char SC16IS740_SPI::readRegister(RegisterName registerAddress) {
+
+  // Used in SPI read operations to flush slave's shift register
+  const char SPI_DUMMY_CHAR = 0xFF; 
+
+  char result;
+
+  _cs = 0; //  select;
+  _spi->write(SPI_READ_MODE_FLAG | registerAddress);
+  result = _spi->write(SPI_DUMMY_CHAR);
+  _cs = 1; //  deselect;
+
+  return result;  
+}
+
+
+/** Write multiple datavalues to Transmitregister.
+  * More Efficient implementation than writing individual bytes
+  * Assume that previous check confirmed that the FIFO has sufficient free space to store the data  
+  * Pure virtual, must be declared in derived class.   
+  *   @param char* databytes   The pointer to the block of data
+  *   @param len               The number of bytes to write
+  *   @return none 
+  */
+void SC16IS740_SPI::writeDataBlock (const char *data, int len) {
+  int i;
+  
+  _cs = 0; //  select;
+  
+  // Select the Transmit Holding Register
+  // Assume that previous check confirmed that the FIFO has sufficient free space to store the data
+  _spi->write(THR);
+  
+  for (i=0; i<len; i++, data++)
+    _spi->write(*data);
+    
+  _cs = 1; //  deselect;
+}
+
+
+/** Hardware Reset SC16IS740 device.
+  * This method is only available when the Reset pin has been declared and is also connected
+  *   @param  none
+  *   @return none
+  */
+void SC16IS740_SPI::hwReset() {
+  
+  if (_reset != NULL){
+    _reset->write(0);  //activate
+    //wait_us(100*1000);   //test only            
+    // ThisThread::sleep_for(100ms); //test only  
+    _reset->write(1);  //deactivate
+  }  
+  else {
+    printf("Hardware Reset pin is not available...\n\r");     
+  }
+
+}
+
+//
+// End SPI Implementation
+//
+
+
+
+//
+// Begin I2C Implementation
+//
+
+/** Create a SC16IS740_I2C object for a bridge between I2C and a Serial port
+  *
+  * @param I2C &i2c the I2C port to connect to 
+  * @param char deviceAddress the I2C slave address of the SC16IS740
+  * @param rst Pinname for Reset pin (active low) Optional, Default = NC   
+  *  
+  */  
+SC16IS740_I2C::SC16IS740_I2C(I2C *i2c, uint8_t deviceAddress, PinName rst) : _i2c(i2c), _slaveAddress(deviceAddress & 0xFE) {
+
+//  _i2c->frequency(400000);
+  _i2c->frequency(100000);  
+ 
+  // The hardware Reset pin is optional. Test and make sure whether it exists or not to prevent illegal access.
+  if (rst != NC) {
+    _reset = new DigitalOut(rst);   //Construct new pin 
+    _reset->write(1);               //Deactivate    
+  }
+  else {
+    // No Hardware Reset pin       
+    _reset = NULL;                  //Construct dummy pin     
+  }  
+  
+  // Dont call _init() until I2C port has been configured.
+  // That is why _init() is not called in parent Constructor 
+  _init();
+}
+
+
+/** Destruct SC16IS740_I2C bridge object
+  *
+  * @param  none
+  * @return none
+  */ 
+SC16IS740_I2C::~SC16IS740_I2C() {
+   if (_reset != NULL) {delete _reset;}  // Reset pin
+}
+
+
+/** Write value to internal register.
+  *   @param registerAddress   The address of the Register (enum RegisterName)
+  *   @param data              The 8bit value to write
+  *   @return none 
+  */
+void SC16IS740_I2C::writeRegister(RegisterName registerAddress, char data) {
+  char w[2];
+
+  w[0] = registerAddress;
+  w[1] = data;
+
+  _i2c->write( _slaveAddress, w, 2 );
+}
+
+
+/** Read value from internal register.
+  *   @param registerAddress   The address of the Register (enum RegisterName)
+  *   @return char             The 8bit value read from the register
+  */
+char SC16IS740_I2C::readRegister(RegisterName registerAddress) {
+  /*
+   * Read char from SC16IS740 register at <registerAddress>.
+   */
+   char w[1];
+   char r[1];
+    
+   w[0] = registerAddress;
+    
+//   _i2c->write( _slaveAddress, w, 1 );
+   _i2c->write(_slaveAddress, w, 1, true);   //Repeated Start   
+   _i2c->read( _slaveAddress, r, 1 );
+
+   return ( r[0] );
+}
+
+
+/** Write multiple datavalues to Transmitregister.
+  * More Efficient implementation than writing individual bytes
+  * Assume that previous check confirmed that the FIFO has sufficient free space to store the data
+  * Pure virtual, must be declared in derived class.   
+  *   @param char* databytes   The pointer to the block of data
+  *   @param len               The number of bytes to write
+  *   @return none 
+  */
+void SC16IS740_I2C::writeDataBlock (const char *data, int len) {
+  
+#if(0)  
+  int i;
+  char w[BULK_BLOCK_LEN];
+  
+  // Select the Transmit Holding Register
+  // Assume that previous check confirmed that the FIFO has sufficient free space to store the data
+  w[0] = THR;
+
+  // copy the data..
+  for (i=0; i<len; i++)
+    w[i+1] = data[i];
+    
+  _i2c->write( _slaveAddress, w, len + 1);  
+#else
+  int i;
+  
+  _i2c->start();
+  _i2c->write(_slaveAddress); 
+
+  // Select the Transmit Holding Register
+  // Assume that previous check confirmed that the FIFO has sufficient free space to store the data
+  _i2c->write(THR);
+
+  // send the data..
+  for (i=0; i<len; i++)
+    _i2c->write(data[i]);
+    
+  _i2c->stop();  
+#endif
+}
+
+
+/** Hardware Reset SC16IS740 device.
+  * This method is only available when the Reset pin has been declared and is also connected
+  *   @param  none
+  *   @return none
+  */
+void SC16IS740_I2C::hwReset() {
+  
+  if (_reset != NULL){
+    _reset->write(0);  //activate
+//    wait_ms(100);
+    wait_us(1000*1000);   //test only            
+    _reset->write(1);  //deactivate
+  }  
+  else {
+    printf("Hardware Reset pin is not available...\n\r");     
+  }
+}
+
+
+//
+// End I2C Implementation
+//
+
+
+
+//
+// Begin SPI Class Implementation for 16SCIS752 dual UART
+//
+
+
+/** Create an SC16IS752_SPI object using a specified SPI bus and CS
+  * Note: The SC16IS752 does not have separate GPIOs for Channel_A and Channel_B. 
+  * Note: The SC16IS752 does not have separate Reset for Channel_A and Channel_B.     
+  *
+  * @param SPI &spi the SPI port to connect to 
+  * @param cs  Pinname of the CS pin (active low)
+  * @param rst Pinname for Reset pin (active low) Optional, Default = NC 
+  * @param channel UART ChannelName, Default = Channel_A      
+  */    
+SC16IS752_SPI::SC16IS752_SPI (SPI *spi, PinName cs, PinName rst, ChannelName channel) : _spi(spi), _cs(cs), _channel(channel)  {
+  _cs = 1;  // deselect
+  
+  _spi->format(8, 0);          
+  _spi->frequency(1000000);
+
+  // The hardware Reset pin is optional. Test and make sure whether it exists or not to prevent illegal access.
+  if (rst != NC) {
+    _reset = new DigitalOut(rst);   //Construct new pin 
+    _reset->write(1);               //Deactivate    
+  }
+  else {
+    // No Hardware Reset pin       
+    _reset = NULL;                  //Construct dummy pin     
+  }  
+
+
+  // Dont call _init() until SPI port has been configured.
+  // That is why _init() is not called in parent Constructor 
+  _init();
+
+};
+
+
+/** Destruct SC16IS740_SPI bridge object
+  *
+  * @param  none
+  * @return none
+  */ 
+SC16IS752_SPI::~SC16IS752_SPI() {
+   if (_reset != NULL) {delete _reset;}  // Reset pin
+}
+
+
+/** Write value to internal register.
+  * Pure virtual, must be declared in derived class.   
+  *   @param registerAddress   The address of the Register (enum RegisterName)
+  *   @param data              The 8bit value to write
+  *   @return none 
+  */
+void SC16IS752_SPI::writeRegister(RegisterName registerAddress, char data) {
+
+  _cs = 0; //  select;
+  _spi->write(registerAddress | _channel);
+  _spi->write(data);
+  _cs = 1; //  deselect;
+
+}
+
+
+/** Read value from internal register.
+  *   @param registerAddress   The address of the Register (enum RegisterName)
+  *   @return char             The 8bit value read from the register
+  */
+char SC16IS752_SPI::readRegister(RegisterName registerAddress) {
+
+  // Used in SPI read operations to flush slave's shift register
+  const char SPI_DUMMY_CHAR = 0xFF; 
+
+  char result;
+
+  _cs = 0; //  select;
+  _spi->write(SPI_READ_MODE_FLAG | registerAddress | _channel);
+  result = _spi->write(SPI_DUMMY_CHAR);
+  _cs = 1; //  deselect;
+
+  return result;  
+}
+
+
+/** Write multiple datavalues to Transmitregister.
+  * More Efficient implementation than writing individual bytes
+  * Assume that previous check confirmed that the FIFO has sufficient free space to store the data  
+  * Pure virtual, must be declared in derived class.   
+  *   @param char* databytes   The pointer to the block of data
+  *   @param len               The number of bytes to write
+  *   @return none 
+  */
+void SC16IS752_SPI::writeDataBlock (const char *data, int len) {
+  int i;
+  
+  _cs = 0; //  select;
+  
+  // Select the Transmit Holding Register
+  // Assume that previous check confirmed that the FIFO has sufficient free space to store the data
+  _spi->write(THR | _channel);
+  
+  for (i=0; i<len; i++, data++)
+    _spi->write(*data);
+    
+  _cs = 1; //  deselect;
+}
+
+
+/** Hardware Reset SC16IS752 device.
+  * This method is only available when the Reset pin has been declared and is also connected
+  *   @param  none
+  *   @return none
+  */
+void SC16IS752_SPI::hwReset() {
+  
+  if (_reset != NULL){
+    _reset->write(0);  //activate
+//    wait_ms(100);
+    wait_us(1000*1000);   //test only            
+    _reset->write(1);  //deactivate
+  }  
+  else {
+    printf("Hardware Reset pin is not available...\n\r");     
+  }
+
+}
+
+//
+// End SPI Implementation
+//
+
+
+
+//
+// Begin I2C Implementation for 16SCIS752 dual UART
+//
+
+/** Create a SC16IS752_I2C object for a bridge between I2C and a Serial port
+  * Note: The SC16IS752 does not have separate GPIOs for Channel_A and Channel_B. 
+  * Note: The SC16IS752 does not have separate Reset for Channel_A and Channel_B.     
+  *
+  * @param I2C &i2c the I2C port to connect to 
+  * @param char deviceAddress the I2C slave address of the SC16IS740
+  * @param rst Pinname for Reset pin (active low) Optional, Default = NC   
+  * @param channel UART Channel, Default = Channel_A    
+  */  
+SC16IS752_I2C::SC16IS752_I2C(I2C *i2c, uint8_t deviceAddress, PinName rst, ChannelName channel) : _i2c(i2c), _slaveAddress(deviceAddress & 0xFE), _channel(channel) {
+
+//  _i2c->frequency(400000);
+  _i2c->frequency(100000);
+   
+  // The hardware Reset pin is optional. Test and make sure whether it exists or not to prevent illegal access.
+  if (rst != NC) {
+    _reset = new DigitalOut(rst);   //Construct new pin 
+    _reset->write(1);               //Deactivate    
+  }
+  else {
+    // No Hardware Reset pin       
+    _reset = NULL;                  //Construct dummy pin     
+  }  
+  
+  // Dont call _init() until I2C port has been configured.
+  // That is why _init() is not called in parent Constructor 
+  _init();
+}
+
+
+/** Destruct SC16IS752_I2C bridge object
+  *
+  * @param  none
+  * @return none
+  */ 
+SC16IS752_I2C::~SC16IS752_I2C() {
+   if (_reset != NULL) {delete _reset;}  // Reset pin
+}
+
+
+/** Write value to internal register.
+  *   @param registerAddress   The address of the Register (enum RegisterName)
+  *   @param data              The 8bit value to write
+  *   @return none 
+  */
+void SC16IS752_I2C::writeRegister(RegisterName registerAddress, char data) {
+  char w[2];
+
+  w[0] = registerAddress | _channel;
+  w[1] = data;
+
+  _i2c->write( _slaveAddress, w, 2 );
+}
+
+
+/** Read value from internal register.
+  *   @param registerAddress   The address of the Register (enum RegisterName)
+  *   @return char             The 8bit value read from the register
+  */
+char SC16IS752_I2C::readRegister(RegisterName registerAddress) {
+  /*
+   * Read char from SC16IS752 register at <registerAddress>.
+   */
+   char w[1];
+   char r[1];
+    
+   w[0] = registerAddress | _channel;
+    
+//   _i2c->write( _slaveAddress, w, 1 );
+   _i2c->write(_slaveAddress, w, 1, true);   //Repeated Start
+   _i2c->read(_slaveAddress, r, 1 );
+
+   return ( r[0] );
+}
+
+
+/** Write multiple datavalues to Transmitregister.
+  * More Efficient implementation than writing individual bytes
+  * Assume that previous check confirmed that the FIFO has sufficient free space to store the data
+  * Pure virtual, must be declared in derived class.   
+  *   @param char* databytes   The pointer to the block of data
+  *   @param len               The number of bytes to write
+  *   @return none 
+  */
+void SC16IS752_I2C::writeDataBlock (const char *data, int len) {
+  
+#if(0)  
+  int i;
+  char w[BULK_BLOCK_LEN];
+  
+  // Select the Transmit Holding Register
+  // Assume that previous check confirmed that the FIFO has sufficient free space to store the data
+  w[0] = THR | _channel;
+
+  // copy the data..
+  for (i=0; i<len; i++)
+    w[i+1] = data[i];
+    
+  _i2c->write( _slaveAddress, w, len + 1);  
+#else
+  int i;
+  
+  _i2c->start();
+  _i2c->write(_slaveAddress); 
+
+  // Select the Transmit Holding Register
+  // Assume that previous check confirmed that the FIFO has sufficient free space to store the data
+  _i2c->write(THR | _channel);
+
+  // send the data..
+  for (i=0; i<len; i++)
+    _i2c->write(data[i]);
+    
+  _i2c->stop();  
+#endif
+}
+
+
+/** Hardware Reset SC16IS752 device.
+  * This method is only available when the Reset pin has been declared and is also connected
+  *   @param  none
+  *   @return none
+  */
+void SC16IS752_I2C::hwReset() {
+  
+  if (_reset != NULL){
+    _reset->write(0);  //activate
+//    wait_ms(100);
+    wait_us(1000*1000);   //test only            
+    _reset->write(1);  //deactivate
+  }  
+  else {
+    printf("Hardware Reset pin is not available...\n\r");     
+  }
+}
+
+
+//
+// End I2C Implementation
+//
\ No newline at end of file
diff -r 000000000000 -r db4396ad001f SC16IS740.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SC16IS740.h	Wed Aug 12 05:16:11 2020 +0000
@@ -0,0 +1,1091 @@
+/* SC16IS740 I2C or SPI to UART bridge 
+ *   v0.1 WH, Nov 2013, Sparkfun WiFly Shield code library alpha 0 used as example, Added I2C I/F and many more methods.
+ *                      https://forum.sparkfun.com/viewtopic.php?f=13&t=21846
+ *   v0.2 WH, Feb 2014, Added Doxygen Documentation, Added Hardware Reset pin methods.
+ *   v0.3 WH, Dec 2014, Added support for SC16IS752 dual UART. 
+ *   v0.4 WH, Dec 2014, Added Repeated Start for I2C readRegister(). Set I2C clock at 100kb/s. Fixed and added some comments. 
+ *   v0.5 LVD, Aug 2020, Renames for use with SC16IS740 on the Mikroe UART I2C/SPI Click board and updated Mbed OS 6 calls.
+ *
+ * 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,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef _SC16IS740_H
+#define _SC16IS740_H
+
+/**
+ *  Mikroe UART I2C/SPI click 
+ *  Uses SC16IS740IPW,112 in SPI mode by default, 
+ *  Has HW reset, (740) model does not have GPIO pins
+ *  1.8432MHz connected to XTAL1
+ */
+
+#include "mbed.h"
+#include "Stream.h"
+//#include <SerialBase.h>
+
+//I2C Slaveaddresses                     A1  A0 
+#define SC16IS740_SA0            0x90  /* VDD VDD */
+#define SC16IS740_SA1            0x92  /* VDD VSS */
+#define SC16IS740_SA2            0x94  /* VDD SCL */
+#define SC16IS740_SA3            0x95  /* VDD SDA */
+#define SC16IS740_SA4            0x98  /* VSS VDD */
+#define SC16IS740_SA5            0x9A  /* VSS VSS */
+#define SC16IS740_SA6            0x9C  /* VSS SCL */
+#define SC16IS740_SA7            0x9E  /* VSS SDA */
+#define SC16IS740_SA8            0xA0  /* SCL VDD */
+#define SC16IS740_SA9            0xA2  /* SCL VSS */
+#define SC16IS740_SA10           0xA4  /* SCL SCL */
+#define SC16IS740_SA11           0xA6  /* SCL SDA */
+#define SC16IS740_SA12           0xA8  /* SDA VDD */
+#define SC16IS740_SA13           0xAA  /* SDA VSS */
+#define SC16IS740_SA14           0xAC  /* SDA SCL */
+#define SC16IS740_SA15           0xAE  /* SDA SDA */
+
+//Default I2C Slaveaddress
+#define SC16IS740_DEFAULT_ADDR   SC16IS740_SA0
+
+
+/** See datasheet section 7.8 for configuring the
+  * "Programmable baud rate generator"
+  */
+  /* https://github.com/sparkfun/WiFly-Shield/blob/master/Libraries/Arduino/src/SpiUart.cpp*/
+//#define SC16IS740_XTAL_FREQ              14745600UL /* On-board crystal (New mid-2010 Version) */
+  /* https://github.com/MikroElektronika/UART_I2C-SPI_click/blob/master/library/__uarti2cspi_driver.c */
+#define SC16IS740_XTAL_FREQ              1843200UL  /* On-board crystal (Mikroe UART I2C/SPI click) */
+#define SC16IS740_PRESCALER_1                   1   /* Default prescaler after reset           */
+#define SC16IS740_PRESCALER_4                   4   /* Selectable by setting MCR[7]            */
+#define SC16IS740_PRESCALER                      SC16IS740_PRESCALER_1  
+#define SC16IS740_BAUDRATE_DIVISOR(baud)       ((SC16IS740_XTAL_FREQ/SC16IS740_PRESCALER)/(baud*16UL))
+
+//Default baudrate
+#define SC16IS740_DEFAULT_BAUDRATE           9600
+
+
+/** See section 8.3 of the datasheet for definitions
+  * of bits in the FIFO Control Register (FCR)
+  */
+#define FCR_RX_IRQ_60                 (3 << 6)
+#define FCR_RX_IRQ_56                 (2 << 6)
+#define FCR_RX_IRQ_16                 (1 << 6)
+#define FCR_RX_IRQ_8                  (0 << 6)
+//TX Level only accessible when EFR[4] is set
+#define FCR_TX_IRQ_56                 (3 << 4)
+#define FCR_TX_IRQ_32                 (2 << 4)
+#define FCR_TX_IRQ_16                 (1 << 4)
+#define FCR_TX_IRQ_8                  (0 << 4)
+//#define FCR_RESERVED                  (1 << 3)
+#define FCR_TX_FIFO_RST               (1 << 2)
+#define FCR_RX_FIFO_RST               (1 << 1)
+#define FCR_ENABLE_FIFO               (1 << 0)
+
+//FIFO size
+#define SC16IS740_FIFO_RX                  64
+#define SC16IS740_FIFO_TX                  64
+
+
+/** See section 8.4 of the datasheet for definitions
+  * of bits in the Line Control Register (LCR)
+  */
+#define LCR_BITS5                      0x00
+#define LCR_BITS6                      0x01
+#define LCR_BITS7                      0x02
+#define LCR_BITS8                      0x03
+
+#define LCR_BITS1                      0x00
+#define LCR_BITS2                      0x04
+
+#define LCR_NONE                       0x00
+#define LCR_ODD                        0x08
+#define LCR_EVEN                       0x18
+#define LCR_FORCED1                    0x28
+#define LCR_FORCED0                    0x38
+
+#define LCR_BRK_ENA                    0x40
+#define LCR_BRK_DIS                    0x00
+
+#define LCR_ENABLE_DIV                 0x80
+#define LCR_DISABLE_DIV                0x00
+
+#define LCR_ENABLE_ENHANCED_FUNCTIONS (0xBF)
+
+
+/** See section 8.5 of the datasheet for definitions
+  * of bits in the Line status register (LSR)
+  */
+#define LSR_DR   (0x01) /* Data ready in RX FIFO                       */
+#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) */
+#define LSR_FFE  (0x80) /* At least one PE, FE or BI in FIFO           */
+
+
+/** See section 8.6 of the datasheet for definitions
+  * of bits in the Modem control register (MCR)
+  */
+#define MCR_MDTR                      (1 << 0) /* Data Terminal Ready pin control. */
+#define MCR_MRTS                      (1 << 1) /* Request to Send pin control when not in Auto RTS mode.*/
+//MCR[2] only accessible when EFR[4] is set
+#define MCR_ENABLE_TCR_TLR            (1 << 2)
+#define MCR_ENABLE_LOOPBACK           (1 << 4)
+//MCR[7:5] only accessible when EFR[4] is set
+#define MCR_ENABLE_XON_ANY_CHAR       (1 << 5)
+#define MCR_ENABLE_IRDA               (1 << 6)
+#define MCR_PRESCALE_1                (0 << 7)
+#define MCR_PRESCALE_4                (1 << 7)
+
+
+/** See section 8.7 of the datasheet for definitions
+  * of bits in the Modem status register (MSR)
+  */
+#define MSR_DCTS                      (1 << 0) /* Delta CTS - CTS Changed State      */
+#define MSR_DDSR                      (1 << 1) /* Delta DSR - DSR Changed State      */
+#define MSR_DDI                       (1 << 2) /* Delta DI  - DI  Changed State      */
+#define MSR_DCD                       (1 << 3) /* Delta CD  - CD  Changed State      */
+#define MSR_CTS                       (1 << 4) /* CTS State - Complement of NCTS pin */
+//MSR[7:5] only accessible when GPIO[7:4] are set as modem pin
+#define MSR_DSR                       (1 << 5) /* DSR State - Complement of NDSR pin */
+#define MSR_RI                        (1 << 6) /* RI State  - Complement of  NRI pin */
+#define MSR_CD                        (1 << 7) /* CD State  - Complement of  NCD pin */
+
+
+/** See section 8.8 of the datasheet for definitions
+  * of bits in the Interrupt enable register (IER)
+  */
+#define IER_ERHRI (0x01) /* Enable received data available interrupt            */
+#define IER_ETHRI (0x02) /* Enable transmitter holding register empty interrupt */
+#define IER_ELSI  (0x04) /* Enable receiver line status interrupt               */
+#define IER_EMSI  (0x08) /* Enable modem status interrupt                       */
+//IER[7:5] only accessible when EFR[4] is set
+#define IER_SLEEP (0x10) /* Enable sleep mode                                   */
+#define IER_XOFFI (0x20) /* Enable XOFF interrupt                               */
+#define IER_RTSI  (0x40) /* Enable RTS interrupt                                */
+#define IER_CTSI  (0x80) /* Enable CTS interrupt                                */
+
+
+/** See section 8.9 of the datasheet for definitions
+  * of bits in the Interrupt identification register (IIR)
+  * Bit 0 is set to 0 if an IRQ is pending.
+  * Bits 1..5 are used to identify the IRQ source.
+  */
+#define IIR_IRQ_NOT_PENDING             (0x01)  /* IRQ Not Pending              */
+#define IIR_TX_EMPTY                    (0x02)  /* THR Interrupt                */
+#define IIR_RX_DATA                     (0x04)  /* RHR Interrupt                */
+#define IIR_RX_ERROR                    (0x06)  /* Line Status Error Interrupt  */
+#define IIR_RX_TIMEOUT                  (0x0B)  /* RX Timeout Interrupt         */
+#define IIR_RX_XOFF                     (0x10)  /* RX XOff Interrupt            */
+#define IIR_DCTS_DRTS                   (0x20)  /* Delta CTS or RTS Interrupt   */
+#define IIR_DIO                         (0x30)  /* Delta GPIO pin Interrupt     */
+
+#define IIR_BITS_USED                   (0x07)
+
+
+/** See section 8.10 of the datasheet for definitions
+  * of bits in the Enhanced Features Register (EFR)
+  */
+#define EFR_ENABLE_CTS                  (1 << 7)
+#define EFR_ENABLE_RTS                  (1 << 6)
+#define EFR_ENABLE_XOFF2_CHAR_DETECT    (1 << 5)
+#define EFR_ENABLE_ENHANCED_FUNCTIONS   (1 << 4)
+// EFR[3:0] are used to define Software Flow Control mode
+// See section 7.3
+#define EFR_DISABLE_TX_FLOW_CTRL        (0x0 << 2)
+#define EFR_TX_XON2_XOFF2               (0x1 << 2)
+#define EFR_TX_XON1_XOFF1               (0x2 << 2)
+#define EFR_TX_XON2_1_XOFF2_1           (0x3 << 2)
+
+#define EFR_DISABLE_RX_FLOW_CTRL        (0x0 << 0)
+#define EFR_RX_XON2_XOFF2               (0x1 << 0)
+#define EFR_RX_XON1_XOFF1               (0x2 << 0)
+#define EFR_RX_XON2_1_XOFF2_1           (0x3 << 0)
+
+#define EFR_TX_XON2_XOFF2_RX_FLOW       (0x1 << 2) | (0x3 << 0)
+#define EFR_TX_XON1_XOFF1_RX_FLOW       (0x2 << 2) | (0x3 << 0)
+#define EFR_TX_XON2_1_XOFF2_1_RX_FLOW   (0x3 << 2) | (0x3 << 0)
+
+
+
+/** See section 8.12 of the datasheet for definitions
+  * of bits in the Transmission Control Register (TCR)
+  * These levels control when RTS is asserted or de-asserted and auto RTS is enabled. Note that XON/XOFF is not supported in this lib.
+  *   Trigger level to halt transmission to the device   : 0..15 (meaning 0-60 with a granularity of 4) 
+  *     RTS is de-asserted when RX FIFO is above the set trigger level (i.e. buffer is getting full)  
+  *   Trigger level to resume transmission to the device : 0..15 (meaning 0-60 with a granularity of 4) 
+  *     RTS is asserted again when RX FIFO drops below the set trigger level (i.e. buffer has room again)    
+  */
+#define TCR_HALT_DEFAULT                (0x0E)
+#define TCR_RESUME_DEFAULT              (0x08)  
+
+/** See section 8.12 of the datasheet for definitions
+  * Note: The device will stop transmissions from the TX FIFO when CTS is de-asserted by external receiver and 
+  *       auto CTS is enabled. Note that XON/XOFF is not supported in this lib.
+  */
+  
+    
+/** See section 7.5 and 8.13 of the datasheet for definitions
+  * of bits in the Trigger Level Register (TLR) control when an IRQ is generated.
+  *   Trigger level for TX interrupt: 0..15 (meaning 0-60 with a granularity of 4) 
+  *     IRQ when TX FIFO is above the set trigger level (i.e. buffer is getting full)
+  *   Trigger level for RX interrupt: 0..15 (meaning 0-60 with a granularity of 4) 
+  *     IRQ when RX FIFO is above the set trigger level (i.e. data is waiting to be read)
+  */
+#define TLR_TX_DEFAULT                  (0x0E)
+#define TLR_RX_DEFAULT                  (0x04)  
+
+
+/**
+  * See section 8.16, 8.17, 8.18 of the datasheet for definitions
+  * of bits in the IO Direction (IODIR), IO State (IOSTATE) and IO Interrupt Enable register (IOINTENA)
+  * 
+  * Basically a direct mapping of register bits to GPIO pin.
+  */
+
+
+/**
+  * See section 8.19 of the datasheet for definitions
+  * of bits in the IO Control register (IOC)
+  * 
+  * 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) /* Set GPIO[7:4] pins to modem functions */
+#define IOC_SW_RST                      (0x04) 
+
+
+/**
+  * See section 8.20 of the datasheet for definitions
+  * of bits in the Extra Features Control register (EFCR)
+  * 
+  */
+#define EFCR_ENA_RS485                  (0x01)  
+#define EFCR_DIS_RX                     (0x02)    
+#define EFCR_DIS_TX                     (0x04)    
+#define EFCR_ENA_TX_RTS                 (0x10)    
+#define EFCR_INV_RTS_RS485              (0x20)    
+#define EFCR_ENA_IRDA                   (0x80)    
+
+// See Chapter 11 of datasheet
+#define SPI_READ_MODE_FLAG              (0x80)
+
+
+/** Abstract class SC16IS740 for a bridge between either SPI or I2C and a Serial port
+  *
+  * Supports both SPI and I2C interfaces through derived classes
+  *
+  * @code
+  *
+  * @endcode
+  */
+//class SC16IS740 {
+//class SC16IS740 : public SerialBase, public Stream {    // Wrong, Serialbase can not be constructed for NC,NC
+class SC16IS740 : public Stream {    
+public:
+
+//  SC16IS740 Register definitions (shifted to align)
+    enum RegisterName { 
+/*
+ * 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       - RD/WR access */
+        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
+    };
+ 
+//  SC16IS752 Channel definitions (shifted to align)
+    enum ChannelName { 
+      Channel_A     = 0x00 << 1,   
+      Channel_B     = 0x01 << 1         
+    };
+  
+// SC16IS740 configuration register values
+// Several configuration registers are write-only. Need to save values to allow restoring.
+struct SC16IS740_cfg {
+  char baudrate;
+  char dataformat;  
+  char flowctrl;  
+  char fifoformat;
+  bool fifoenable;      
+};
+
+
+/** Determine if there is a character available to read.
+  * This is data that's already arrived and stored in the receive
+  * buffer (which holds 64 chars).
+  *
+  *   @return 1 if there is a character available to read, 0 otherwise
+  */
+  int readable();
+
+/** Determine how many characters are available to read.
+  * This is data that's already arrived and stored in the receive
+  * buffer (which holds 64 chars).
+  *
+  *   @return int Characters available to read
+  */ 
+  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();
+
+  
+/** Determine how much space available for writing characters.
+  * This considers data that's already stored in the transmit
+  * buffer (which holds 64 chars).
+  *
+  *   @return int character space available to write
+  */  
+  int writableCount();
+
+/**
+  * 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 c);
+ 
+
+#if DOXYGEN_ONLY
+  /** Write a formatted string to the UART Bridge. Blocking when no free space in FIFO
+    *
+    * @param format A printf-style format string, followed by the
+    *               variables to use in formatting the string.
+    */
+   int printf(const char* format, ...);
+#endif
+
+
+/**
+  * Write char string to UART Bridge. Blocking when no free space in FIFO
+  *   @param *str char string to be written    
+  *   @return none  
+  */
+  void writeString(const char *str);
+
+
+/**
+  * Write byte array to UART Bridge. Blocking when no free space in FIFO
+  *   @param *data byte array to be written    
+  *   @param len   number of bytes to write  
+  *   @return none  
+  */
+  void writeBytes(const char *data, int len);
+    
+/** Set baudrate of the serial port.    
+  *  @param  baud integer baudrate (4800, 9600 etc)
+  *  @return none
+  */
+  void baud(int baudrate = SC16IS740_DEFAULT_BAUDRATE);   
+
+/** 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) 
+  *   @return none   
+  */
+  void format(int bits=8, BufferedSerial::Parity parity=BufferedSerial::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)
+  *  @return none   
+  */
+  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
+  *  @param none
+  *  @return none 
+  */
+  void send_break();
+
+
+/** Set a break condition on the serial line
+  *  @param enable  break condition
+  *  @return none   
+  */
+  void set_break(bool enable=false);
+    
+
+/** Set the flow control type on the serial port
+  *  Added for compatibility with Serial Class.
+  *  SC16IS740 supports only Flow, Pins can not be selected. 
+  *  This method sets hardware flow control levels. SC16IS740 supports XON/XOFF, but this is not implemented.  
+  *
+  *  @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)
+  *  @return none   
+  */
+  void set_flow_control(Flow type=Disabled, PinName flow1=NC, PinName flow2=NC);
+
+
+/** Set the RX FIFO flow control levels
+  *  This method sets hardware flow control levels. SC16IS740 supports XON/XOFF, but this is not implemented.   
+  *  Should be called BEFORE Auto RTS is enabled.    
+  *
+  *  @param resume trigger level to resume transmission (0..15, meaning 0-60 with a granularity of 4)     
+  *  @param halt trigger level to resume transmission (0..15, meaning 0-60 with granularity of 4)           
+  *  @return none   
+  */
+  void set_flow_triggers(int resume = TCR_RESUME_DEFAULT, int halt = TCR_HALT_DEFAULT);
+
+
+/** Set the Modem Control register
+  *  This method sets prescaler, enables TCR and TLR
+  *
+  *  @param none 
+  *  @return none 
+  */
+  void set_modem_control();
+
+ 
+/**
+  * Check that UART is connected and operational.
+  *   @param  none
+  *   @return bool true when connected, false otherwise
+  */
+  bool connected();
+
+         
+
+/** FIFO control, sets TX and RX IRQ trigger levels and enables FIFO and save in _config
+  *  Note FCR[5:4] (=TX_IRQ_LVL) only accessible when EFR[4] is set (enhanced functions enable)
+  *  Note TLR only accessible when EFR[4] is set (enhanced functions enable) and MCR[2] is set 
+  *   @param  none
+  *   @return none
+  */
+  void set_fifo_control();
+
+
+/** Flush the UART FIFOs while maintaining current FIFO mode.
+  *   @param  none
+  *   @return none
+  */
+  void flush();
+
+
+/** Set direction of I/O port pins.
+  * This method is specific to the SPI-I2C UART and not found on the 16750
+  * Note: The SC16IS752 does not have separate GPIOs for Channel_A and Channel_B.    
+  *   @param  bits Bitpattern for I/O (1=output, 0=input)
+  *   @return none
+  */
+  void ioSetDirection(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
+  * Note: The SC16IS752 does not have separate GPIOs for Channel_A and Channel_B.    
+  *   @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
+  * Note: The SC16IS752 does not have separate GPIOs for Channel_A and Channel_B.    
+  *   @param  none
+  *   @return bits Bitpattern for I/O (1= bit set, 0 = bit cleared)
+  */
+  unsigned char ioGetState();
+
+
+/** Software Reset SC16IS740 device.
+  * This method is specific to the SPI-I2C UART and not found on the 16750
+  * Note: The SC16IS752 does not have separate Reset for Channel_A and Channel_B.    
+  *   @param  none
+  *   @return none
+  */
+  void swReset();
+
+
+/** Hardware Reset SC16IS740 device.
+  * Pure virtual, must be declared in derived class.   
+  * This method is only functional when the Reset pin has been declared and is also connected
+  *   @param  none
+  *   @return none
+  */
+  virtual void hwReset() =0;
+
+/** Write value to internal register.
+  * Pure virtual, must be declared in derived class.   
+  *   @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;
+
+/** Read value from internal register.
+  * Pure virtual, must be declared in derived class.   
+  *   @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;
+
+/** Write multiple datavalues to Transmitregister.
+  * More Efficient implementation than writing individual bytes
+  * Pure virtual, must be declared in derived class.   
+  *   @param char* databytes   The pointer to the block of data
+  *   @param len               The number of bytes to write
+  *   @return none 
+  */
+  virtual void writeDataBlock (const char *data, int len ) =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 is protected for this abstract Class
+  *  
+  */
+  SC16IS740();  
+
+/** Needed to implement Stream
+  *
+  * Read char from UART Bridge.
+  * Acts in the same manner as 'Serial.read()'.  
+  *   @param none    
+  *   @return char read or -1 if no data available. 
+  */  
+  virtual int _getc() {
+    return getc();
+  }
+
+
+/** Needed to implement Stream
+  *
+  * Write char to UART Bridge. Blocking when no free space in FIFO
+  *   @param value char to be written    
+  *   @return value written  
+  */
+  virtual int _putc(int c) {
+    return putc(c); 
+  }
+  
+/** Needed to implement Stream
+  *
+  */
+  virtual int peek() {return 0;};
+  
+
+// Save config settings
+SC16IS740_cfg _config;
+
+private:
+//private is not accessible to derived classes, nor external users
+
+};
+
+
+
+/** Class SC16IS740_SPI for a bridge between SPI and a Serial port
+ *
+ * @code
+ * #include "mbed.h"
+ * #include "SC16IS740.h"
+ *
+ * SPI spi(PTD2, PTD3, PTD1); //MOSI, MISO, SCK
+ * SC16IS740_SPI serial_spi(&spi, PTD0);
+ * 
+ * Serial pc(USBTX,USBRX);
+ *
+ * int main() {
+ *   pc.printf("\nHello World!\n");
+ *
+ *   while(1) { 
+ *     serial_spi.ioSetState(0x00);
+ *     wait(0.5);
+ *     serial_spi.ioSetState(0xFF); 
+ *     wait(0.5); 
+ *     serial_spi.putc('*');  
+ *     pc.putc('*');                
+ *   }
+ * }
+ *
+ * @endcode
+ */
+class SC16IS740_SPI : public SC16IS740 {
+public:
+
+/** Create an SC16IS740_SPI object using a specified SPI bus and CS
+  *
+  * @param SPI &spi the SPI port to connect to 
+  * @param cs  Pinname of the CS pin (active low)
+  * @param rst Pinname for Reset pin (active low) Optional, Default = NC 
+  */  
+  SC16IS740_SPI(SPI *spi, PinName cs, PinName rst = NC);
+
+/** Destruct SC16IS740_SPI bridge object
+  *
+  * @param  none
+  * @return none
+  */ 
+  virtual ~SC16IS740_SPI();
+
+
+/** Write value to internal register.
+  *   @param registerAddress   The address of the Register (enum RegisterName)
+  *   @param data              The 8bit value to write
+  *   @return none 
+  */
+  virtual void writeRegister(SC16IS740::RegisterName registerAddress, char data);
+
+/** Read value from internal register.
+  *   @param registerAddress   The address of the Register (enum RegisterName)
+  *   @return char             The 8bit value read from the register
+  */
+  virtual char readRegister(SC16IS740::RegisterName registerAddress);
+
+/** Write multiple datavalues to Transmitregister.
+  * More Efficient implementation than writing individual bytes
+  * Assume that previous check confirmed that the FIFO has sufficient free space to store the data 
+  * 
+  *   @param char* databytes   The pointer to the block of data
+  *   @param len               The number of bytes to write
+  *   @return none 
+  */
+  virtual void writeDataBlock (const char *data, int len );
+
+/** Hardware Reset SC16IS740 device.
+  * This method is only functional when the Reset pin has been declared and is also connected
+  *   @param  none
+  *   @return none
+  */
+  virtual void hwReset();
+
+
+protected:
+//protected is accessible to derived classes, but not to external users
+
+
+private:
+  SPI *_spi;          //SPI bus reference
+  DigitalOut _cs;     //CS of SPI device (active low)
+
+/** Optional Hardware Reset pin for the bridge device (active low)
+  * Default PinName value is NC
+  */
+  DigitalOut* _reset; //Reset the Bridge device (active low)
+
+};
+
+
+
+/** Class SC16IS740_I2C for a bridge between I2C and a Serial port
+ *
+ * @code
+ * #include "mbed.h"
+ * #include "SC16IS740.h"
+ *
+ * I2C i2c(PTE0, PTE1);       //SDA, SCL
+ * SC16IS740_I2C serial_i2c(&i2c, SC16IS740_DEFAULT_ADDR);
+ *
+ * Serial pc(USBTX,USBRX);
+ *
+ * int main() {
+ *   pc.printf("\nHello World!\n");
+ *
+ *   while(1) { 
+ *     serial_i2c.ioSetState(0x00);
+ *     wait(0.5);
+ *     serial_i2c.ioSetState(0xFF); 
+ *     wait(0.5); 
+ *     serial_i2c.putc('*');   
+ *     pc.putc('*');                
+ *   }
+ * }
+ *
+ * @endcode
+ */
+class SC16IS740_I2C : public SC16IS740 {
+public:
+
+/** Create an SC16IS740_I2C object using a specified I2C bus and slaveaddress
+  *
+  * @param I2C &i2c the I2C port to connect to 
+  * @param char deviceAddress the address of the SC16IS740
+  * @param rst Pinname for Reset pin (active low) Optional, Default = NC   
+  */  
+  SC16IS740_I2C(I2C *i2c, uint8_t deviceAddress = SC16IS740_DEFAULT_ADDR, PinName rst = NC);
+
+
+/** Destruct SC16IS740_I2C bridge object
+  *
+  * @param  none
+  * @return none
+  */ 
+  virtual ~SC16IS740_I2C();
+
+
+/** Write value to internal register.
+  *   @param registerAddress   The address of the Register (enum RegisterName)
+  *   @param data              The 8bit value to write
+  *   @return none 
+  */
+  virtual void writeRegister(SC16IS740::RegisterName register_address, char data );
+
+/** Read value from internal register.
+  *   @param registerAddress   The address of the Register (enum RegisterName)
+  *   @return char             The 8bit value read from the register
+  */
+  virtual char readRegister(SC16IS740::RegisterName register_address );
+
+
+/** Write multiple datavalues to Transmitregister.
+  * More Efficient implementation than writing individual bytes
+  * Assume that previous check confirmed that the FIFO has sufficient free space to store the data 
+  * Pure virtual, must be declared in derived class.   
+  *   @param char* databytes   The pointer to the block of data
+  *   @param len               The number of bytes to write
+  *   @return none 
+  */
+  virtual void writeDataBlock (const char *data, int len );
+
+
+/** Hardware Reset SC16IS740 device.
+  * This method is only functional when the Reset pin has been declared and is also connected
+  *   @param  none
+  *   @return none
+  */
+  virtual void hwReset();
+
+
+protected:
+//protected is accessible to derived classes, but not to external users
+
+
+private:
+  I2C *_i2c;                    //I2C bus reference
+  uint8_t _slaveAddress;        //I2C Slave address of device
+
+/** Optional Hardware Reset pin for the bridge device (active low)
+  * Default PinName value is NC
+  */
+  DigitalOut* _reset;           //Reset the Bridge device (active low)
+
+};
+
+
+
+/** Class SC16IS752_SPI for a bridge between SPI and a Serial port
+ *
+ * @code
+ * #include "mbed.h"
+ * #include "SC16IS740.h"
+ *
+ * SPI spi(PTD2, PTD3, PTD1); //MOSI, MISO, SCK
+ * SC16IS740_SPI serial_spi(&spi, PTD0, NC, SC16IS740::Channel_B);
+ * 
+ * Serial pc(USBTX,USBRX);
+ *
+ * int main() {
+ *   pc.printf("\nHello World!\n");
+ *
+ *   while(1) { 
+ *     serial_spi.ioSetState(0x00);
+ *     wait(0.5);
+ *     serial_spi.ioSetState(0xFF); 
+ *     wait(0.5); 
+ *     serial_spi.putc('*');  
+ *     pc.putc('*');                
+ *   }
+ * }
+ *
+ * @endcode
+ */
+class SC16IS752_SPI : public SC16IS740 {
+public:
+
+/** Create an SC16IS752_SPI object using a specified SPI bus and CS
+  * Note: The SC16IS752 does not have separate GPIOs for Channel_A and Channel_B.  
+  * Note: The SC16IS752 does not have separate Reset for Channel_A and Channel_B.    
+  *
+  * @param SPI &spi the SPI port to connect to 
+  * @param cs  Pinname of the CS pin (active low)
+  * @param rst Pinname for Reset pin (active low) Optional, Default = NC 
+  * @param channel UART ChannelName, Default = Channel_A    
+  */  
+  SC16IS752_SPI(SPI *spi, PinName cs, PinName rst = NC, ChannelName channel = SC16IS740::Channel_A );
+
+/** Destruct SC16IS752_SPI bridge object
+  *
+  * @param  none
+  * @return none
+  */ 
+  virtual ~SC16IS752_SPI();
+
+
+/** Write value to internal register.
+  *   @param registerAddress   The address of the Register (enum RegisterName)
+  *   @param data              The 8bit value to write
+  *   @return none 
+  */
+  virtual void writeRegister(SC16IS740::RegisterName registerAddress, char data);
+
+/** Read value from internal register.
+  *   @param registerAddress   The address of the Register (enum RegisterName)
+  *   @return char             The 8bit value read from the register
+  */
+  virtual char readRegister(SC16IS740::RegisterName registerAddress);
+
+/** Write multiple datavalues to Transmitregister.
+  * More Efficient implementation than writing individual bytes
+  * Assume that previous check confirmed that the FIFO has sufficient free space to store the data 
+  * 
+  *   @param char* databytes   The pointer to the block of data
+  *   @param len               The number of bytes to write
+  *   @return none 
+  */
+  virtual void writeDataBlock (const char *data, int len );
+
+/** Hardware Reset SC16IS740 device.
+  * This method is only functional when the Reset pin has been declared and is also connected
+  *   @param  none
+  *   @return none
+  */
+  virtual void hwReset();
+
+
+protected:
+//protected is accessible to derived classes, but not to external users
+
+
+private:
+  SPI *_spi;          //SPI bus reference
+  DigitalOut _cs;     //CS of SPI device (active low)
+
+/** Optional Hardware Reset pin for the bridge device (active low)
+  * Default PinName value is NC
+  */
+  DigitalOut* _reset; //Reset the Bridge device (active low)
+
+// Save Channel setting
+  ChannelName _channel; 
+};
+
+
+
+/** Class SC16IS752_I2C for a bridge between I2C and a Serial port
+ *
+ * @code
+ * #include "mbed.h"
+ * #include "SC16IS740.h"
+ *
+ * I2C i2c(PTE0, PTE1);       //SDA, SCL
+ * SC16IS752_I2C serial_i2c(&i2c, SC16IS740_DEFAULT_ADDR, NC, SC16IS740::Channel_A);
+ *
+ * Serial pc(USBTX,USBRX);
+ *
+ * int main() {
+ *   pc.printf("\nHello World!\n");
+ *
+ *   while(1) { 
+ *     serial_i2c.ioSetState(0x00);
+ *     wait(0.5);
+ *     serial_i2c.ioSetState(0xFF); 
+ *     wait(0.5); 
+ *     serial_i2c.putc('*');   
+ *     pc.putc('*');                
+ *   }
+ * }
+ *
+ * @endcode
+ */
+class SC16IS752_I2C : public SC16IS740 {
+public:
+
+/** Create an SC16IS752_I2C object using a specified I2C bus, slaveaddress and Channel
+  * Note: The SC16IS752 does not have separate GPIOs for Channel_A and Channel_B. 
+  * Note: The SC16IS752 does not have separate Reset for Channel_A and Channel_B.     
+  *
+  * @param I2C &i2c the I2C port to connect to 
+  * @param char deviceAddress the address of the SC16IS740
+  * @param rst Pinname for Reset pin (active low) Optional, Default = NC
+  * @param channel UART ChannelName, Default = Channel_A  
+  */  
+  SC16IS752_I2C(I2C *i2c, uint8_t deviceAddress = SC16IS740_DEFAULT_ADDR, PinName rst = NC, ChannelName channel = SC16IS740::Channel_A);
+
+
+/** Destruct SC16IS752_I2C bridge object
+  *
+  * @param  none
+  * @return none
+  */ 
+  virtual ~SC16IS752_I2C();
+
+
+/** Write value to internal register.
+  *   @param registerAddress   The address of the Register (enum RegisterName)
+  *   @param data              The 8bit value to write
+  *   @return none 
+  */
+  virtual void writeRegister(SC16IS740::RegisterName register_address, char data );
+
+/** Read value from internal register.
+  *   @param registerAddress   The address of the Register (enum RegisterName)
+  *   @return char             The 8bit value read from the register
+  */
+  virtual char readRegister(SC16IS740::RegisterName register_address );
+
+
+/** Write multiple datavalues to Transmitregister.
+  * More Efficient implementation than writing individual bytes
+  * Assume that previous check confirmed that the FIFO has sufficient free space to store the data 
+  * Pure virtual, must be declared in derived class.   
+  *   @param char* databytes   The pointer to the block of data
+  *   @param len               The number of bytes to write
+  *   @return none 
+  */
+  virtual void writeDataBlock (const char *data, int len );
+
+
+/** Hardware Reset SC16IS752 device.
+  * This method is only functional when the Reset pin has been declared and is also connected
+  *   @param  none
+  *   @return none
+  */
+  virtual void hwReset();
+
+
+protected:
+//protected is accessible to derived classes, but not to external users
+
+
+private:
+  I2C *_i2c;                    //I2C bus reference
+  uint8_t _slaveAddress;        //I2C Slave address of device
+
+/** Optional Hardware Reset pin for the bridge device (active low)
+  * Default PinName value is NC
+  */
+  DigitalOut* _reset;           //Reset the Bridge device (active low)
+
+// Save Channel setting
+  ChannelName _channel; 
+
+};
+
+
+#endif  //  _SC16IS740_H