SPI or I2C to UART Bridge
Dependents: SC16IS750_Test mbed_SC16IS750 Xadow_SC16IS750_Test Xadow_MPU9150AHRS
Diff: SC16IS750.cpp
- Revision:
- 4:12446ee9f9c8
- Parent:
- 3:9783b6bde958
- Child:
- 5:ff3e57bebb6a
diff -r 9783b6bde958 -r 12446ee9f9c8 SC16IS750.cpp --- 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 +// + + +