SPI or I2C to UART Bridge

Dependents:   SC16IS750_Test mbed_SC16IS750 Xadow_SC16IS750_Test Xadow_MPU9150AHRS

Revision:
4:12446ee9f9c8
Parent:
3:9783b6bde958
Child:
5:ff3e57bebb6a
--- a/SC16IS750.cpp	Thu Feb 20 19:37:55 2014 +0000
+++ b/SC16IS750.cpp	Mon Dec 22 19:04:38 2014 +0000
@@ -1,6 +1,8 @@
 /* SC16IS750 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.  
  *
  * 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,
@@ -231,9 +233,12 @@
 
   // Initialise SC16IS750
 
+  // 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();
@@ -626,19 +631,33 @@
 
 
 
-/** Class SC16IS750_SPI for a converter between SPI and a Serial port
-  *
-  * @code
+//
+// Begin SPI Class Implementation
+//
+
+
+/** Create an SC16IS750_SPI object using a specified SPI bus and CS
   *
-  * @endcode
-  *
-  */
-SC16IS750_SPI::SC16IS750_SPI (SPI *spi, PinName cs) : _spi(spi), _cs(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 
+  */    
+SC16IS750_SPI::SC16IS750_SPI (SPI *spi, PinName cs, PinName rst) : _spi(spi), _cs(cs)  {
   _cs = 1;  // deselect
   
   _spi->format(8, 0);          
   _spi->frequency(1000000);
-//  _spi->frequency(100000);  //test
+
+  // 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 
@@ -646,6 +665,19 @@
 
 };
 
+
+/** Destruct SC16IS750_SPI bridge object
+  *
+  * @param  none
+  * @return none
+  */ 
+SC16IS750_SPI::~SC16IS750_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)
@@ -659,7 +691,6 @@
   _spi->write(data);
   _cs = 1; //  deselect;
 
-
 }
 
 
@@ -706,28 +737,73 @@
   _cs = 1; //  deselect;
 }
 
+
+/** Hardware Reset SC16IS750 device.
+  * This method is only available when the Reset pin has been declared and is also connected
+  *   @param  none
+  *   @return none
+  */
+void SC16IS750_SPI::hwReset() {
+  
+  if (_reset != NULL){
+    _reset->write(0);  //activate
+//    wait_ms(100);
+    wait_ms(1000);   //test only            
+    _reset->write(1);  //deactivate
+  }  
+  else {
+    printf("Hardware Reset pin is not available...\n\r");     
+  }
+
+}
+
 //
 // End SPI Implementation
 //
 
 
-/** Class SC16IS750_I2C for a converter between I2C and a Serial port
-  *
-  * @code
+
+//
+// Begin I2C Implementation
+//
+
+/** Create a SC16IS750_I2C object for a bridge between I2C and a Serial port
   *
-  * @endcode
-  *
-  */
-SC16IS750_I2C::SC16IS750_I2C(I2C *i2c, uint8_t deviceAddress) : _i2c(i2c), _slaveAddress(deviceAddress & 0xFE) {
+  * @param I2C &i2c the I2C port to connect to 
+  * @param char deviceAddress the I2C slave address of the SC16IS750
+  * @param rst Pinname for Reset pin (active low) Optional, Default = NC   
+  *  
+  */  
+SC16IS750_I2C::SC16IS750_I2C(I2C *i2c, uint8_t deviceAddress, PinName rst) : _i2c(i2c), _slaveAddress(deviceAddress & 0xFE) {
 
   _i2c->frequency(400000);
-
+ 
+  // 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 SC16IS750_I2C bridge object
+  *
+  * @param  none
+  * @return none
+  */ 
+SC16IS750_I2C::~SC16IS750_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
@@ -805,6 +881,304 @@
 }
 
 
+/** Hardware Reset SC16IS750 device.
+  * This method is only available when the Reset pin has been declared and is also connected
+  *   @param  none
+  *   @return none
+  */
+void SC16IS750_I2C::hwReset() {
+  
+  if (_reset != NULL){
+    _reset->write(0);  //activate
+//    wait_ms(100);
+    wait_ms(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
+//
+
+
+
+//
+// Begin SPI Class Implementation for 16SCIS752 dual UART
+//
+
+
+/** Create an SC16IS752_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 
+  * @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 SC16IS750_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_ms(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
+  *
+  * @param I2C &i2c the I2C port to connect to 
+  * @param char deviceAddress the I2C slave address of the SC16IS750
+  * @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);
+ 
+  // 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->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_ms(1000);   //test only            
+    _reset->write(1);  //deactivate
+  }  
+  else {
+    printf("Hardware Reset pin is not available...\n\r");     
+  }
+}
+
+
+//
+// End I2C Implementation
+//
+
+
+