SPI or I2C to UART Bridge

Dependents:   SC16IS750_Test mbed_SC16IS750 Xadow_SC16IS750_Test Xadow_MPU9150AHRS

Files at this revision

API Documentation at this revision

Comitter:
wim
Date:
Thu Feb 13 17:12:02 2014 +0000
Parent:
1:0440152c5387
Child:
3:9783b6bde958
Commit message:
Testversion 2

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	Sun Feb 09 14:58:06 2014 +0000
+++ b/SC16IS750.cpp	Thu Feb 13 17:12:02 2014 +0000
@@ -1,5 +1,5 @@
 /* SC16IS750 interface 
- *   v0.1 WH, Nov 2013, Ported to mbed, Sparkfun Libs used as example. Added I2C and SPI I/F and more methods
+ *   v0.1 WH, Nov 2013, Sparkfun Libs used as example. Added I2C I/F and many 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,
@@ -19,6 +19,7 @@
 #include    "mbed.h"
 #include    "SC16IS750.h"
 
+#define ENABLE_BULK_TRANSFERS          0x01
 
 /** Abstract class SC16IS750 for converter between either SPI or I2C and a Serial port
   * Constructor for this Abstract Class is protected  
@@ -40,7 +41,7 @@
   *  @return none
   */
 void SC16IS750::baud(int baudrate) {
-  unsigned long divisor = BAUD_RATE_DIVISOR(baudrate);
+  unsigned long divisor = SC16IS750_BAUDRATE_DIVISOR(baudrate);
   char lcr_tmp;
   
   _config.baudrate = baudrate;               // Save baudrate
@@ -58,6 +59,7 @@
   *   @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 SC16IS750::format(int bits, Serial::Parity parity, int stop_bits) {
   char lcr_tmp = 0x00;
@@ -103,6 +105,7 @@
 };
 
 /** Generate a break condition on the serial line
+  *  @return none 
   */
 void SC16IS750::send_break() {
   // Wait for 1.5 frames before clearing the break condition
@@ -120,6 +123,7 @@
     
 /** Set a break condition on the serial line
   *  @param enable  break condition
+  *  @return none   
   */
 void SC16IS750::set_break(bool enable) {
 
@@ -136,10 +140,12 @@
 /** Set the flow control type on the serial port
   *  Added for compatibility with Serial Class.
   *  SC16IS750 supports only Flow, Pins can not be selected.
+  *  This method sets only hardware flow control. SC16IS750 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)
+  *  @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 SC16IS750::set_flow_control(Flow type, PinName flow1, PinName flow2) {
   char lcr_tmp; 
@@ -161,15 +167,55 @@
 
   }
 
-  //Save flowcontrol state
-  //enable enhanced functions  
-  _config.flowctrl = efr_tmp | EFR_ENABLE_ENHANCED_FUNCTIONS,
+  //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 only hardware flow control levels. SC16IS750 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 SC16IS750::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 SC16IS750::set_modem_control() {
+
+  //Note MCR[7:4] and MCR[2] only accessible when EFR[4] is set
+  if (SC16IS750_PRESCALER == SC16IS750_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
@@ -184,29 +230,40 @@
 
   // Software reset, assuming there is no access to the HW Reset pin
   swReset();
-  
-  // Set default baudrate and save in _config
-  // LCR, DLL/DLH  
+
+  // Set default baudrate (depends on prescaler) and save in _config
+  // DLL/DLH  
   baud();
 
-  // Set dataflow and save in _config
-  // LCR, EFR
-  set_flow_control(); 
-  
   // 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 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();
-  
-  // Set default fifoformat and save in _config
-  // 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
@@ -224,12 +281,48 @@
 
 }
 
+
+/** 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 SC16IS750::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 SC16IS750::flush() {
+  // FCR is Write Only, use saved _config
 
   // reset TXFIFO, reset RXFIFO, non FIFO mode  
   this->writeRegister(FCR, FCR_TXFIFO_RST | FCR_RXFIFO_RST);
@@ -277,22 +370,30 @@
 
 
 /** 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 SC16IS750::readable() {
-  return (this->readRegister(LSR) & 0x01);
+  
+//  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 SC16IS750::readableCount() {
-  /*
-   * 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).
-   */
 
   return (this->readRegister(RXLVL));
 }
@@ -301,22 +402,25 @@
   *   @return 1 if there is a space for a character to write, 0 otherwise
   */
 int SC16IS750::writable() {
-  return (this->writableCount() > 0);  // Check datasheet for faster version
+ 
+//  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 SC16IS750::writableCount() {
-  /*
-   * Get the available space for writing characters.
-   *
-   * This is data that's already stored in the transmit
-   * buffer (which holds 64 chars).
-   */
 
-  return (this->readRegister(TXLVL));
-//  return (readRegister(64 - TXLVL));  //Check datasheet
+  return (this->readRegister(TXLVL));  // TX Level
 }
 
 
@@ -341,6 +445,7 @@
   *   @return value written  
   */ 
 int SC16IS750::putc(int value) {
+
   while (this->readRegister(TXLVL) == 0) {
     // Wait for space in TX buffer
     wait_us(10);
@@ -350,39 +455,62 @@
   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 SC16IS750::write(const char *str) {
-  /*
-   * Write string to UART.
-   */
-  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.)
-  };
-}
 
 #if ENABLE_BULK_TRANSFERS
-void SC16IS750::write(const uint8_t *buffer, size_t size) {
-  /*
+
+  #define BULK_BLOCK_LEN  16
+  int len, idx;
   
-    Write buffer to UART.
- 
-   */
-  //select();
-  //transfer(THR); // TODO: Change this when we modify register addresses? (Even though it's 0x00.) 
+  len = strlen(str);  
 
-  while(size > 16) {
-    //transfer_bulk(buffer, 16); //ringbuffer?
-    size -= 16;
-    buffer += 16;
+  // 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
+    // Note: can be optimized by writing registeraddress once and then repeatedsly write the bytes.
+    for (idx=0; idx<BULK_BLOCK_LEN; idx++) {
+      this->writeRegister(THR, str[idx]);
+    };
+        
+    len -= BULK_BLOCK_LEN;
+    str += BULK_BLOCK_LEN;
   }
-  //transfer_bulk(buffer, size);
+  
+  // Write remaining 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]);
+  }  
+
 
-  //deselect();
+#else
+  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  
 }
-#endif
+
+
 
 /** Set direction of I/O port pins.
   * This method is specific to the SPI-I2C UART and not found on the 16750
--- a/SC16IS750.h	Sun Feb 09 14:58:06 2014 +0000
+++ b/SC16IS750.h	Thu Feb 13 17:12:02 2014 +0000
@@ -1,5 +1,5 @@
 /* SC16IS750 interface 
- *   v0.1 WH, Nov 2013, Ported to mbed, Sparkfun Libs used as example. Added I2C and SPI I/F and more methods 
+ *   v0.1 WH, Nov 2013, Sparkfun Libs used as example. Added I2C I/F and many 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,106 +20,91 @@
 #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 */
+#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  SC16IS750_SA0
+#define SC16IS750_DEFAULT_ADDR   SC16IS750_SA0
+
+
+/** See datasheet section 7.8 for configuring the
+  * "Programmable baud rate generator"
+  */
+#define SC16IS750_XTAL_FREQ              14745600UL /* On-board crystal (New mid-2010 Version) */
+#define SC16IS750_PRESCALER_1                   1   /* Default prescaler after reset           */
+#define SC16IS750_PRESCALER_4                   4   /* Selectable by setting MCR[7]            */
+#define SC16IS750_PRESCALER                      SC16IS750_PRESCALER_1  
+#define SC16IS750_BAUDRATE_DIVISOR(baud)       ((SC16IS750_XTAL_FREQ/SC16IS750_PRESCALER)/(baud*16UL))
 
 //Default baudrate
-#define DEFAULT_BAUD_RATE       9600
-
-#define ENABLE_BULK_TRANSFERS   0x01
-
-#define XTAL_FREQUENCY 14745600UL // On-board crystal (New mid-2010 Version)
-
-// See datasheet section 7.8 for configuring the
-// "Programmable baud rate generator"
-#define PRESCALER                  1 // Default prescaler after reset
-#define BAUD_RATE_DIVISOR(baud) ((XTAL_FREQUENCY/PRESCALER)/(baud*16UL))
-
-// 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.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_ENHANCED_FUNCTIONS (1 << 4)
+#define SC16IS750_DEFAULT_BAUDRATE     9600
 
 
-// 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)
+/** 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_TXFIFO_RST                (1 << 2)
 #define FCR_RXFIFO_RST                (1 << 1)
 #define FCR_ENABLE_FIFO               (1 << 0)
 
+//FIFO size
+#define SC16IS750_FIFO_RX                  64
+#define SC16IS750_FIFO_TX                  64
 
 
-/*
- * Interrupt enable register.
- */
+/** 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 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                                   */
+#define LCR_BITS1                      0x00
+#define LCR_BITS2                      0x04
 
-/*
- * Modem control register.
- */
+#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 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)
+#define LCR_ENABLE_DIV                 0x80
+#define LCR_DISABLE_DIV                0x00
+
+#define LCR_ENABLE_ENHANCED_FUNCTIONS (0xBF)
 
-/*
- * Line status register.
- */
 
+/** See section 8.5 of the datasheet for definitions
+  * of bits in the Line status register (LSR)
+  */
 #define LSR_DR   (0x01) /* Data ready                                  */
 #define LSR_OE   (0x02) /* Overrun error                               */
 #define LSR_PE   (0x04) /* Parity error                                */
@@ -127,34 +112,107 @@
 #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           */
 
-/*
- * Interrupt identification register.
- * Bit 0 is set to 0 if an IT is pending.
- * Bits 1 and 2 are used to identify the IT.
- */
+
+/** 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.*/
+#define MCR_ENABLE_TCR_TLR            (1 << 2)
+#define MCR_ENABLE_LOOPBACK           (1 << 4)
+#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)
+
 
-#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)
+/** See section 8.7 of the datasheet for definitions
+  * of bits in the Modem status register (MSR)
+  */
+
+
+/** See section 8.8 of the datasheet for definitions
+  * of bits in the Interrupt enable register (IER)
+  */
+#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                                   */
 
 
-/*
- * 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 section 8.9 of the datasheet for definitions
+  * of bits in the Interrupt identification register (IIR)
+  * 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)
+
+
+/** 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)
+  *   Trigger level to halt transmission: 0..15 (meaning 0-60 with a granularity of 4) 
+  *   Trigger level to resume transmission: 0..15 (meaning 0-60 with a granularity of 4) 
+  */
+#define TCR_HALT_DEFAULT                (0x0E)
+#define TCR_RESUME_DEFAULT              (0x04)  
+
+  
+/** See section 8.13 of the datasheet for definitions
+  * of bits in the Trigger Level Register (TLR)
+  *   Trigger level for TX interrupt: 0..15 (meaning 0-60 with a granularity of 4) 
+  *   Trigger level for RX interrupt: 0..15 (meaning 0-60 with a granularity of 4) 
+  */
+#define TLR_TX_DEFAULT                  (0x0E)
+#define TLR_RX_DEFAULT                  (0x04)  
+
+
+/**
+  * 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)
+#define IOC_SW_RST                      (0x04)
+
+
 // See Chapter 11 of datasheet
-#define SPI_READ_MODE_FLAG      0x80
+#define SPI_READ_MODE_FLAG              (0x80)
 
 
 /** Abstract class SC16IS750 for a converter between either SPI or I2C and a Serial port
@@ -265,13 +323,19 @@
 
 
 /** 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 available for reading.
+/** 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.    
@@ -279,9 +343,13 @@
   */
   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();
 
 
@@ -300,20 +368,28 @@
   */
   int putc(int value);    
 
+
+/**
+  * Write char string to UART Bridge. Blocking when no free space in FIFO
+  *   @param *str char string to be written    
+  *   @return none  
+  */
   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 = SC16IS750_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, Serial::Parity parity=Serial::None, int stop_bits=1);
+  
 #if(0)
 /** Attach a function to call whenever a serial interrupt is generated
   *
@@ -327,6 +403,7 @@
   *  @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) {
@@ -338,25 +415,51 @@
 #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.
-  *  SC16IS750 supports only Flow, Pins can not be selected.  
+  *  SC16IS750 supports only Flow, Pins can not be selected. 
+  *  This method sets only hardware flow control. SC16IS750 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 only hardware flow control levels. SC16IS750 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.
@@ -366,11 +469,15 @@
   bool connected();
 
          
-#if ENABLE_BULK_TRANSFERS
-    void write(const uint8_t *buffer, size_t size);
-#else
- //   using Print::write;
-#endif
+
+/** 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 set_fifo_control();
+
 
 /** Flush the UART FIFOs while maintaining current FIFO mode.
   *   @param  none
@@ -439,12 +546,13 @@
 protected:
 //protected is accessible to derived classes, but not to external users
 
-/** Constructor for this Abstract Class is protected
+
+/** Constructor is protected for this abstract Class
   *  
   */
   SC16IS750();  
 
-
+// Save config settings
 SC16IS750_cfg _config;
 
 private:
@@ -471,6 +579,9 @@
  *   while(1) { 
  *     serial_spi.ioSetState(0x00);
  *     wait(0.5);
+ *     serial_spi.ioSetState(0xFF); 
+ *     wait(0.5); 
+ *     serial_spi.putc('*');  
  *     pc.putc('*');                
  *   }
  * }
@@ -529,6 +640,9 @@
  *   while(1) { 
  *     serial_i2c.ioSetState(0x00);
  *     wait(0.5);
+ *     serial_i2c.ioSetState(0xFF); 
+ *     wait(0.5); 
+ *     serial_i2c.putc('*');   
  *     pc.putc('*');                
  *   }
  * }
@@ -543,7 +657,7 @@
   * @param I2C &i2c the I2C port to connect to 
   * @param char deviceAddress the address of the SC16IS750
   */  
-  SC16IS750_I2C(I2C *i2c, uint8_t deviceAddress = DEFAULT_SC16IS750_ADDR);
+  SC16IS750_I2C(I2C *i2c, uint8_t deviceAddress = SC16IS750_DEFAULT_ADDR);
 
 /** Write value to internal register.
   *   @param registerAddress   The address of the Register (enum RegisterName)