RETRO ROBOT E
Dependents: RETRO_ROBOT_SC16IS750E
Fork of SC16IS750 by
Revision 6:b57b71c0879a, committed 2015-03-02
- Comitter:
- RLRiedinger
- Date:
- Mon Mar 02 04:20:07 2015 +0000
- Parent:
- 5:ff3e57bebb6a
- Commit message:
- RETRO ROBOT E
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 |
diff -r ff3e57bebb6a -r b57b71c0879a SC16IS750.cpp --- a/SC16IS750.cpp Wed Dec 24 01:05:49 2014 +0000 +++ b/SC16IS750.cpp Mon Mar 02 04:20:07 2015 +0000 @@ -1,4 +1,5 @@ -/* SC16IS750 I2C or SPI to UART bridge +/* + * 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. @@ -20,1168 +21,1555 @@ * 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 "SC16IS750.h" + +#include "mbed.h" +#include "SC16IS750.h" #define ENABLE_BULK_TRANSFERS 1 #define BULK_BLOCK_LEN 16 - -/** Abstract class SC16IS750 for converter between either SPI or I2C and a Serial port - * Constructor for this Abstract Class is protected - * Supports both SPI and I2C interfaces through derived classes - * - * @code - * - * @endcode - */ -SC16IS750::SC16IS750() { -//SC16IS750::SC16IS750() : Serial(NC, NC) { //Fout, mag geen NC zijn -//SC16IS750::SC16IS750() : 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 SC16IS750::baud(int baudrate) { - unsigned long divisor = SC16IS750_BAUDRATE_DIVISOR(baudrate); - char lcr_tmp; + +/* + * Abstract class SC16IS750 for converter between either SPI or I2C and a Serial port + * Constructor for this Abstract Class is protected + * Supports both SPI and I2C interfaces through derived classes + * + * @code + * + * @endcode + */ - _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 +SC16IS750::SC16IS750() { + + // SC16IS750::SC16IS750() : Serial(NC, NC) { //Fout, mag geen NC zijn + // SC16IS750::SC16IS750() : SerialBase(NC, NC) { //Fout, mag geen NC zijn + // Dont call _init() here since the SPI or I2C port have not yet been configured... + // _init(); // initialize UART registers } - + +/* + * Set baudrate of the serial port. + * @param baud integer baudrate (4800, 9600 etc) + * @return none + */ -/** 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 SC16IS750::format(int bits, Serial::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; - } +void SC16IS750::baud(unsigned long SC16IS750_XTAL_FREQ, int baudrate) { + +/* + #define SC16IS750_XTAL_FREQ 14745600UL // On-board crystal (New mid-2010 Version) + #define SC16IS750_XTAL_FREQ 12288000UL // On-board crystal (New mid-2010 Version) + #define SC16IS750_BAUDRATE_DIVISOR(baud) ((SC16IS750_XTAL_FREQ / SC16IS750_PRESCALER)/(baud * 16UL)) +*/ + + unsigned long divisor = (SC16IS750_XTAL_FREQ / SC16IS750_PRESCALER) / (baudrate * 16UL); + + 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 - switch (parity) { - case Serial::None: lcr_tmp |= LCR_NONE; - break; - case Serial::Odd: lcr_tmp |= LCR_ODD; - break; - case Serial::Even: lcr_tmp |= LCR_EVEN; - break; - case Serial::Forced1: lcr_tmp |= LCR_FORCED1; - break; - case Serial::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 +} + +/* + * 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 SC16IS750::format(int bits, Serial::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; + break; + + } + + switch (parity) { + + case Serial::None: + lcr_tmp |= LCR_NONE; + break; + + case Serial::Odd: + lcr_tmp |= LCR_ODD; + break; + + case Serial::Even: + lcr_tmp |= LCR_EVEN; + break; + + case Serial::Forced1: + lcr_tmp |= LCR_FORCED1; + break; + + case Serial::Forced0: + lcr_tmp |= LCR_FORCED0; + break; + + default: + lcr_tmp |= LCR_NONE; + break; + + } + + switch (stop_bits) { + + case 1: + lcr_tmp |= LCR_BITS1; + break; + + case 2: + lcr_tmp |= LCR_BITS2; + break; + + default: + lcr_tmp |= LCR_BITS1; + break; + + } + + _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 - */ + +/* + * Generate a break condition on the serial line + * @param none + * @return none + */ + void SC16IS750::send_break() { - // Wait for 1.5 frames before clearing the break condition - // This will have different effects on our platforms, but should - // ensure that we keep the break active for at least one frame. - // We consider a full frame (1 start bit + 8 data bits bits + - // 1 parity bit + 2 stop bits = 12 bits) for computation. - // One bit time (in us) = 1000000/_baud - // Twelve bits: 12000000/baud delay - // 1.5 frames: 18000000/baud delay - set_break(true); - wait_us(18000000/_config.baudrate); - set_break(false); -}; + + // 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 a break condition on the serial line - * @param enable break condition - * @return none - */ + 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 SC16IS750::set_break(bool enable) { if (enable) { - _config.dataformat |= LCR_BRK_ENA; // Save dataformat - } - else { - _config.dataformat &= ~LCR_BRK_ENA; // Save dataformat + + _config.dataformat |= LCR_BRK_ENA; // Save dataformat + + } else { + + _config.dataformat &= ~LCR_BRK_ENA; // Save dataformat + } this->writeRegister(LCR, _config.dataformat); // Set LCR register + } - -/** Set the flow control type on the serial port - * Added for compatibility with Serial Class. - * SC16IS750 supports only Flow, Pins can not be selected. - * This method sets 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) - 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; - 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. + +/* + * 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 hardware flow control levels. 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 + */ - 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 -} +void SC16IS750::set_flow_control(Flow type, PinName flow1, PinName flow2) { + + char lcr_tmp; + char efr_tmp = 0x00; + + // We need to enable flow control to prevent overflow of buffers and + // lose data when used with fast devices like the WiFly. + + switch (type) { + + case Disabled: + break; + + case RTS: + efr_tmp = EFR_ENABLE_RTS; + break; + + case CTS: + efr_tmp = EFR_ENABLE_CTS; + break; + + case RTSCTS: + efr_tmp = EFR_ENABLE_RTS | EFR_ENABLE_CTS; + break; + + default: + break; + + } + + //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. 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 - */ +} + +/* + * Set the RX FIFO flow control levels + * This method sets 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 + + // 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 + */ - -/** 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); + + } - //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 + +/** Initialize internal registers * Should be in protection section. Public for testing purposes * If initialisation fails this method does not return. * @param none * @return none */ -void SC16IS750::_init() { - - // Initialise SC16IS750 - - // 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(); +void SC16IS750::_init() { + + // Initialize 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(); + + // 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 initialized. + + // Test if UART bridge is present and initialized + + if (!connected()) { + + #if (0) + + // Lock up if we fail to initialize UART bridge. + + while(1){}; + + #else + + // printf("Failed to initialize UART bridge\r\n"); + + #endif + + } else { + + // printf("Initialized UART bridge!\r\n"); + + } + +} + +/* + * 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 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 + */ - // Set default dataformat and save in _config - // LCR - format(); +void SC16IS750::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 SC16IS750 receive buffer. + */ + + // Note: This may not be the most appropriate flush approach. + // It might be better to just flush the UART's buffer + // rather than the buffer of the connected device + // which is essentially what this does. + + while(readable() > 0) { + + getc(); + + } + + #endif + +} + +/* + * + * Check that UART is connected and operational. + * @param none + * @return bool true when connected, false otherwise + */ + +bool SC16IS750::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); - // Set dataflow mode and Enables enhanced functions - // Save in _config - // EFR - set_flow_control(); +} + +/* + * 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() { + // 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() { + + 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 SC16IS750::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 SC16IS750::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 SC16IS750::getc() { - // 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(); + if (!readable()) { + + return -1; + + } else { + + 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 SC16IS750::putc(int value) { + + while (this->readRegister(TXLVL) == 0) { + + // Wait for space in TX buffer + + wait_us(10); + + } + + this->writeRegister(THR, value); + + return value; - // 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(); - +} + +/* + * + * Write char string to UART Bridge. Blocking when no free space in FIFO + * @param *str char string to be written + * @return none + */ + +void SC16IS750::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 - // Set default break condition and save in _config - // LCR - //set_break(); - - // The UART bridge should now be successfully initialised. +} + +/* + * + * 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 SC16IS750::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 - // 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"); - } +} + +/* + * 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 SC16IS750::ioSetDirection(unsigned char bits) { + + this->writeRegister(IODIR, bits); + +} + +/* + * Set bits of I/O port pins. + * This method is specific to the SPI-I2C UART and not found on the 16750 + * 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 SC16IS750::ioSetState(unsigned char bits) { + + this->writeRegister(IOSTATE, bits); + +} + +/* + * Get bits of I/O port pins. + * This method is specific to the SPI-I2C UART and not found on the 16750 + * 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 SC16IS750::ioGetState() { + + return this->readRegister(IOSTATE) ; + +} + +/* + * Software Reset SC16IS750 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 SC16IS750::swReset() { + + this->writeRegister(IOCTRL, IOC_SW_RST); + } - -/** 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 - -} +// +// End Abstract Class Implementation +// + +// +// Begin SPI Class Implementation +// - -/** - * 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_TX_FIFO_RST | FCR_RX_FIFO_RST); +/* + * Create an SC16IS750_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 + */ - 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); +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); + + // 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 + */ -#if(0) -//original - /* - * Flush characters from SC16IS750 receive buffer. - */ - - // Note: This may not be the most appropriate flush approach. - // It might be better to just flush the UART's buffer - // rather than the buffer of the connected device - // which is essentially what this does. - while(readable() > 0) { - getc(); - } -#endif +SC16IS750_SPI::~SC16IS750_SPI() { + + if (_reset != NULL) { + + delete _reset; + + } // Reset pin } -/** - * Check that UART is connected and operational. - * @param none - * @return bool true when connected, false otherwise - */ -bool SC16IS750::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 SC16IS750::readable() { +/* + * Write value to internal register. + * @param registerAddress The address of the Register (enum RegisterName) + * @param data The 8bit value to write + * @return none + */ -// 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() { - - 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 SC16IS750::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 SC16IS750::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 SC16IS750::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 SC16IS750::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 SC16IS750::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 -} - +void SC16IS750_SPI::writeRegister(RegisterName registerAddress, char data) { + + _cs = 0; // Select; + _spi->write(registerAddress); + _spi->write(data); + _cs = 1; // Deselect; -/** - * 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 SC16IS750::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; +} + +/* + * Read value from internal register. + * @param registerAddress The address of the Register (enum RegisterName) + * @return char The 8bit value read from the register + */ - 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 SC16IS750::ioSetDirection(unsigned char bits) { - this->writeRegister(IODIR, bits); -} - -/** Set bits of I/O port pins. - * This method is specific to the SPI-I2C UART and not found on the 16750 - * 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 SC16IS750::ioSetState(unsigned char bits) { - this->writeRegister(IOSTATE, bits); -} - -/** Get bits of I/O port pins. - * This method is specific to the SPI-I2C UART and not found on the 16750 - * 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 SC16IS750::ioGetState() { - return this->readRegister(IOSTATE) ; -} - - -/** Software Reset SC16IS750 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 SC16IS750::swReset() { - this->writeRegister(IOCTRL, IOC_SW_RST); -} - - -// -// End Abstract Class Implementation -// - - - -// -// Begin SPI Class Implementation -// - - -/** Create an SC16IS750_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 - */ -SC16IS750_SPI::SC16IS750_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 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) - * @param data The 8bit value to write - * @return none - */ -void SC16IS750_SPI::writeRegister(RegisterName registerAddress, char data) { - - _cs = 0; // select; - _spi->write(registerAddress); - _spi->write(data); - _cs = 1; // deselect; +char SC16IS750_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; } - - -/** Read value from internal register. - * @param registerAddress The address of the Register (enum RegisterName) - * @return char The 8bit value read from the register - */ -char SC16IS750_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 - */ + +/* + * 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 + */ + void SC16IS750_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); + + 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 - _cs = 1; // deselect; -} - + _spi->write(THR); + + for (i = 0; i < len; i++, data++) { + + _spi->write(*data); + + } + + _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() { +} + +/* + * Hardware Reset SC16IS750 device. + * This method is only functional when the Reset pin has been declared and is also connected + * @param none + * @return none + */ - 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"); - } +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 // - - - + // // Begin I2C Implementation // -/** Create a SC16IS750_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 - * - */ +/* + * Create a SC16IS750_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 + * + */ + SC16IS750_I2C::SC16IS750_I2C(I2C *i2c, uint8_t deviceAddress, PinName rst) : _i2c(i2c), _slaveAddress(deviceAddress & 0xFE) { + + //_i2c->frequency(400000); + + _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(); -// _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 SC16IS750_I2C bridge object + * + * @param none + * @return none + */ -/** Destruct SC16IS750_I2C bridge object - * - * @param none - * @return none - */ SC16IS750_I2C::~SC16IS750_I2C() { - if (_reset != NULL) {delete _reset;} // Reset pin + + 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 - */ + +/* + * Write value to internal register. + * @param registerAddress The address of the Register (enum RegisterName) + * @param data The 8bit value to write + * @return none + */ + void SC16IS750_I2C::writeRegister(RegisterName registerAddress, char data) { - char w[2]; + + char w[2]; + + w[0] = registerAddress; + w[1] = data; + + _i2c->write(_slaveAddress, 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 - */ + +/* + * Read value from internal register. + * @param registerAddress The address of the Register (enum RegisterName) + * @return char The 8bit value read from the register + */ + char SC16IS750_I2C::readRegister(RegisterName registerAddress) { - /* - * Read char from SC16IS750 register at <registerAddress>. - */ - char w[1]; - char r[1]; + + /* + * Read char from SC16IS750 register at <registerAddress>. + */ - w[0] = 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] ); -} - + // _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 SC16IS750_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; +} + +/* + * 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 + */ - _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]); +void SC16IS750_I2C::writeDataBlock (const char *data, int len) { - _i2c->stop(); -#endif -} - + #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 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() { +} + +/* + * Hardware Reset SC16IS750 device. + * This method is only available when the Reset pin has been declared and is also connected + * @param none + * @return none + */ - 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"); - } +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 // - - - + // // 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 +/* + * 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 + */ - _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 - } - +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(); - // 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 } - + +/* + * Destruct SC16IS750_SPI bridge object + * + * @param none + * @return none + */ -/** 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 - */ +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; + + _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 - */ + +/* + * 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; + + // 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; - _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 - */ + +/* + * 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); + + 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 - _cs = 1; // deselect; -} - + _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() { +} + +/* + * Hardware Reset SC16IS752 device. + * This method is only available when the Reset pin has been declared and is also connected + * @param none + * @return none + */ - 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"); - } +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 - * 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 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); - _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 - } +/* + * 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 SC16IS750 + * @param rst Pinname for Reset pin (active low) Optional, Default = NC + * @param channel UART Channel, Default = Channel_A + */ - // Dont call _init() until I2C port has been configured. - // That is why _init() is not called in parent Constructor - _init(); -} - +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 ); } +/* + * Destruct SC16IS752_I2C bridge object + * + * @param none + * @return none + */ -/** 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]; +SC16IS752_I2C::~SC16IS752_I2C() { - 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] ); + if (_reset != NULL) {delete _reset;} // Reset pin + } - - -/** 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) { + +/* + * Write value to internal register. + * @param registerAddress The address of the Register (enum RegisterName) + * @param data The 8bit value to write + * @return none + */ -#if(0) - int i; - char w[BULK_BLOCK_LEN]; +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 + */ - // 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; +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]); - // copy the data.. - for (i=0; i<len; i++) - w[i+1] = data[i]; - - _i2c->write( _slaveAddress, w, len + 1); -#else - int i; +} + +/* + * 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 + */ - _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]); +void SC16IS752_I2C::writeDataBlock (const char *data, int len) { - _i2c->stop(); -#endif -} - + #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 - */ +} + +/* + * 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"); - } + + 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 // - - -
diff -r ff3e57bebb6a -r b57b71c0879a SC16IS750.h --- a/SC16IS750.h Wed Dec 24 01:05:49 2014 +0000 +++ b/SC16IS750.h Mon Mar 02 04:20:07 2015 +0000 @@ -1,4 +1,5 @@ -/* SC16IS750 I2C or SPI to UART bridge +/* + * 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. @@ -20,73 +21,83 @@ * 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 _SC16IS750_H #define _SC16IS750_H +#include "Stream.h" -#include "Stream.h" //#include <SerialBase.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 */ +// I2C Slaveaddresses A1 A0 -//Default I2C Slaveaddress +#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 SC16IS750_DEFAULT_ADDR SC16IS750_SA0 +/* + * See datasheet section 7.8 for configuring the + * "Programmable baud rate generator" + */ -/** 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)) +#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 -//Default baudrate +// Default baudrate + #define SC16IS750_DEFAULT_BAUDRATE 9600 +/* + * See section 8.3 of the datasheet for definitions + * of bits in the FIFO Control Register (FCR) + */ -/** 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 + +// 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_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 +// FIFO size + #define SC16IS750_FIFO_RX 64 #define SC16IS750_FIFO_TX 64 +/* + * See section 8.4 of the datasheet for definitions + * of bits in the Line Control Register (LCR) + */ -/** 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 @@ -109,89 +120,106 @@ #define LCR_ENABLE_ENHANCED_FUNCTIONS (0xBF) +/* + * See section 8.5 of the datasheet for definitions + * of bits in the Line status register (LSR) + */ -/** 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 */ +#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) + */ -/** 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_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) + */ -/** 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 */ +#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 */ + +#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) + */ -/** 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 */ +#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 */ +#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 */ +/* + * 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) + */ -/** 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) @@ -206,62 +234,63 @@ #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) + */ -/** 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) - */ +/* + * 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.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. - */ +/* + * 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_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) + */ -/** - * 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) @@ -270,426 +299,514 @@ #define EFCR_ENA_IRDA (0x80) // See Chapter 11 of datasheet + #define SPI_READ_MODE_FLAG (0x80) +/* + * Abstract class SC16IS750 for a bridge between either SPI or I2C and a Serial port + * + * Supports both SPI and I2C interfaces through derived classes + * + * @code + * + * @endcode + */ -/** Abstract class SC16IS750 for a bridge between either SPI or I2C and a Serial port - * - * Supports both SPI and I2C interfaces through derived classes - * - * @code - * - * @endcode - */ //class SC16IS750 { //class SC16IS750 : public SerialBase, public Stream { // Wrong, Serialbase can not be constructed for NC,NC -class SC16IS750 : public Stream { + +class SC16IS750 : public Stream { + public: // SC16IS750 Register definitions (shifted to align) - enum RegisterName { + + 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 */ + */ + + 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 */ + */ + + 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 */ + */ + + 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 */ + */ + + EFR = 0x02 << 3, // Enhanced features reg - RD/WR access /* * 16750 addresses. - */ - LCR = 0x03 << 3, /* Line control register - RD/WR access */ + */ + + 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 */ + */ + + 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 */ + */ + + 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 */ + */ + + 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 */ + */ + + 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 */ + */ + + 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.. + // 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 { + + enum ChannelName { + Channel_A = 0x00 << 1, - Channel_B = 0x01 << 1 + Channel_B = 0x01 << 1 + }; // SC16IS750 configuration register values // Several configuration registers are write-only. Need to save values to allow restoring. + struct SC16IS750_cfg { + char baudrate; char dataformat; char flowctrl; char fifoformat; - bool fifoenable; + 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 + */ -/** 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 - */ +/* + * 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 - */ +/* + * 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 - */ +/* + * 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. - */ +/* + * + * 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 - */ +/* + * + * 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. - */ + + /* + * 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 + */ -/** - * 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 + */ -/** - * 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 = SC16IS750_DEFAULT_BAUDRATE); +/* + * Set baudrate of the serial port. + * @param baud integer baudrate (4800, 9600 etc) + * @return none + */ + + void baud(unsigned long SC16IS750_XTAL_FREQ = 14745600UL, 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); +/* + * 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 - * - * @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) - */ + +/* + * 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); - } - } +/* + * 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 - */ +/* + * 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 + */ -/** Set a break condition on the serial line - * @param enable break condition - * @return none - */ - void set_break(bool enable=false); - + 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. - * This method sets hardware flow control levels. 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 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 hardware flow control levels. 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 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 - */ +/* + * Set the RX FIFO flow control levels + * This method sets 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 + */ -/** 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 + */ - -/** - * 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 + */ -/** 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 + */ -/** 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 + */ -/** 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 - */ +/* + * 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) - */ +/* + * 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 SC16IS750 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 + */ -/** Software Reset SC16IS750 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 SC16IS750 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 + */ -/** Hardware Reset SC16IS750 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 - */ +/* + * 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 - */ +/* + * 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 - */ +/* + * 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 + */ -/** 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 - + +// protected is accessible to derived classes, but not to external users -/** Constructor is protected for this abstract Class - * - */ +/* + * Constructor is protected for this abstract Class + */ + SC16IS750(); -/** 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. - */ +/* + * 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 + */ -/** 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); + + return putc(c); + } -/** Needed to implement Stream - * - */ +/* + * Needed to implement Stream + * + */ + virtual int peek() {return 0;}; - // Save config settings + SC16IS750_cfg _config; private: -//private is not accessible to derived classes, nor external users + +// private is not accessible to derived classes, nor external users }; - - -/** Class SC16IS750_SPI for a bridge between SPI and a Serial port +/* + * Class SC16IS750_SPI for a bridge between SPI and a Serial port * * @code * #include "mbed.h" @@ -715,80 +832,94 @@ * * @endcode */ + class SC16IS750_SPI : public SC16IS750 { + public: -/** Create an SC16IS750_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 - */ +/* + * Create an SC16IS750_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 + */ + SC16IS750_SPI(SPI *spi, PinName cs, PinName rst = NC); -/** Destruct SC16IS750_SPI bridge object - * - * @param none - * @return none - */ +/* + * Destruct SC16IS750_SPI bridge object + * + * @param none + * @return none + */ + virtual ~SC16IS750_SPI(); +/* + * Write value to internal register. + * @param registerAddress The address of the Register (enum RegisterName) + * @param data The 8bit value to write + * @return none + */ -/** 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(SC16IS750::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 - */ +/* + * 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(SC16IS750::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 - */ +/* + * 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 SC16IS750 device. - * This method is only functional when the Reset pin has been declared and is also connected - * @param none - * @return none - */ +/* + * Hardware Reset SC16IS750 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 - + +// 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) + + 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) +/* + * Optional Hardware Reset pin for the bridge device (active low) + * Default PinName value is NC + */ + + DigitalOut* _reset; // Reset the Bridge device (active low) }; - - -/** Class SC16IS750_I2C for a bridge between I2C and a Serial port +/* + * Class SC16IS750_I2C for a bridge between I2C and a Serial port * * @code * #include "mbed.h" * #include "SC16IS750.h" * - * I2C i2c(PTE0, PTE1); //SDA, SCL + * I2C i2c(PTE0, PTE1); // SDA, SCL * SC16IS750_I2C serial_i2c(&i2c, SC16IS750_DEFAULT_ADDR); * * Serial pc(USBTX,USBRX); @@ -808,83 +939,94 @@ * * @endcode */ + class SC16IS750_I2C : public SC16IS750 { + public: -/** Create an SC16IS750_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 SC16IS750 - * @param rst Pinname for Reset pin (active low) Optional, Default = NC - */ +/* + * Create an SC16IS750_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 SC16IS750 + * @param rst Pinname for Reset pin (active low) Optional, Default = NC + */ + SC16IS750_I2C(I2C *i2c, uint8_t deviceAddress = SC16IS750_DEFAULT_ADDR, PinName rst = NC); +/* + * Destruct SC16IS750_I2C bridge object + * + * @param none + * @return none + */ -/** Destruct SC16IS750_I2C bridge object - * - * @param none - * @return none - */ virtual ~SC16IS750_I2C(); +/* + * Write value to internal register. + * @param registerAddress The address of the Register (enum RegisterName) + * @param data The 8bit value to write + * @return none + */ -/** 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(SC16IS750::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 - */ +/* + * 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(SC16IS750::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 + */ -/** 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 SC16IS750 device. + * This method is only functional when the Reset pin has been declared and is also connected + * @param none + * @return none + */ -/** Hardware Reset SC16IS750 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 - + +// 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 + + 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) +/* + * 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 +/* + * Class SC16IS752_SPI for a bridge between SPI and a Serial port * * @code * #include "mbed.h" * #include "SC16IS750.h" * - * SPI spi(PTD2, PTD3, PTD1); //MOSI, MISO, SCK + * SPI spi(PTD2, PTD3, PTD1); // MOSI, MISO, SCK * SC16IS750_SPI serial_spi(&spi, PTD0, NC, SC16IS750::Channel_B); * * Serial pc(USBTX,USBRX); @@ -904,79 +1046,95 @@ * * @endcode */ + class SC16IS752_SPI : public SC16IS750 { + 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 - */ +/* + * 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 = SC16IS750::Channel_A ); -/** Destruct SC16IS752_SPI bridge object - * - * @param none - * @return none - */ +/* + * 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 + */ -/** 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(SC16IS750::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 - */ +/* + * 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(SC16IS750::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 - */ +/* + * 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 SC16IS750 device. - * This method is only functional when the Reset pin has been declared and is also connected - * @param none - * @return none - */ +/* + * Hardware Reset SC16IS750 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 - + +// 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 - */ +/* + * 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 +/* + * Class SC16IS752_I2C for a bridge between I2C and a Serial port * * @code * #include "mbed.h" @@ -1002,79 +1160,91 @@ * * @endcode */ + class SC16IS752_I2C : public SC16IS750 { + 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 SC16IS750 - * @param rst Pinname for Reset pin (active low) Optional, Default = NC - * @param channel UART ChannelName, Default = Channel_A - */ +/* + * 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 SC16IS750 + * @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 = SC16IS750_DEFAULT_ADDR, PinName rst = NC, ChannelName channel = SC16IS750::Channel_A); +/* + * Destruct SC16IS752_I2C bridge object + * + * @param none + * @return none + */ -/** 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 + */ -/** 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(SC16IS750::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 - */ +/* + * 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(SC16IS750::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 + */ -/** 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 + */ -/** 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 - + +// 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 + + 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) +/* + * 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 // _SC16IS750_H