SPI or I2C to UART Bridge
Dependents: SC16IS750_Test mbed_SC16IS750 Xadow_SC16IS750_Test Xadow_MPU9150AHRS
Revision 2:76cb93b511f2, committed 2014-02-13
- Comitter:
- wim
- Date:
- Thu Feb 13 17:12:02 2014 +0000
- Parent:
- 1:0440152c5387
- Child:
- 3:9783b6bde958
- Commit message:
- Testversion 2
Changed in this revision
SC16IS750.cpp | Show annotated file Show diff for this revision Revisions of this file |
SC16IS750.h | Show annotated file Show diff for this revision Revisions of this file |
--- a/SC16IS750.cpp Sun Feb 09 14:58:06 2014 +0000 +++ b/SC16IS750.cpp Thu Feb 13 17:12:02 2014 +0000 @@ -1,5 +1,5 @@ /* SC16IS750 interface - * v0.1 WH, Nov 2013, Ported to mbed, Sparkfun Libs used as example. Added I2C and SPI I/F and more methods + * v0.1 WH, Nov 2013, Sparkfun Libs used as example. Added I2C I/F and many more methods. * * Permission is hereby granted, free of charge, to any person obtaining a copy of this software * and associated documentation files (the "Software"), to deal in the Software without restriction, @@ -19,6 +19,7 @@ #include "mbed.h" #include "SC16IS750.h" +#define ENABLE_BULK_TRANSFERS 0x01 /** Abstract class SC16IS750 for converter between either SPI or I2C and a Serial port * Constructor for this Abstract Class is protected @@ -40,7 +41,7 @@ * @return none */ void SC16IS750::baud(int baudrate) { - unsigned long divisor = BAUD_RATE_DIVISOR(baudrate); + unsigned long divisor = SC16IS750_BAUDRATE_DIVISOR(baudrate); char lcr_tmp; _config.baudrate = baudrate; // Save baudrate @@ -58,6 +59,7 @@ * @param bits The number of bits in a word (5-8; default = 8) * @param parity The parity used (Serial::None, Serial::Odd, Serial::Even, Serial::Forced1, Serial::Forced0; default = Serial::None) * @param stop_bits The number of stop bits (1 or 2; default = 1) + * @return none */ void SC16IS750::format(int bits, Serial::Parity parity, int stop_bits) { char lcr_tmp = 0x00; @@ -103,6 +105,7 @@ }; /** Generate a break condition on the serial line + * @return none */ void SC16IS750::send_break() { // Wait for 1.5 frames before clearing the break condition @@ -120,6 +123,7 @@ /** Set a break condition on the serial line * @param enable break condition + * @return none */ void SC16IS750::set_break(bool enable) { @@ -136,10 +140,12 @@ /** Set the flow control type on the serial port * Added for compatibility with Serial Class. * SC16IS750 supports only Flow, Pins can not be selected. + * This method sets only hardware flow control. SC16IS750 supports XON/XOFF, but this is not implemented. * * @param type the flow control type (Disabled, RTS, CTS, RTSCTS) - * @param flow1 the first flow control pin (RTS for RTS or RTSCTS, CTS for CTS) - * @param flow2 the second flow control pin (CTS for RTSCTS) + * @param flow1 the first flow control pin (RTS for RTS or RTSCTS, CTS for CTS) - NOT USED + * @param flow2 the second flow control pin (CTS for RTSCTS) - NOT USED + * @return none */ void SC16IS750::set_flow_control(Flow type, PinName flow1, PinName flow2) { char lcr_tmp; @@ -161,15 +167,55 @@ } - //Save flowcontrol state - //enable enhanced functions - _config.flowctrl = efr_tmp | EFR_ENABLE_ENHANCED_FUNCTIONS, + //Save flowcontrol mode and enable enhanced functions + _config.flowctrl = efr_tmp | EFR_ENABLE_ENHANCED_FUNCTIONS; lcr_tmp = this->readRegister(LCR); // save LRC register this->writeRegister(LCR, LCR_ENABLE_ENHANCED_FUNCTIONS); // write magic number 0xBF to enable access to EFR register this->writeRegister(EFR, _config.flowctrl); // set flow and enable enhanced functions this->writeRegister(LCR, lcr_tmp); // restore LCR register } + +/** Set the RX FIFO flow control levels + * This method sets only hardware flow control levels. SC16IS750 supports XON/XOFF, but this is not implemented. + * Should be called BEFORE Auto RTS is enabled. + * + * @param resume trigger level to resume transmission (0..15, meaning 0-60 with a granularity of 4) + * @param halt trigger level to resume transmission (0..15, meaning 0-60 with granularity of 4) + * @return none + */ +void SC16IS750::set_flow_triggers(int resume, int halt) { + + // sanity checks + halt = halt & 0x0F; + resume = resume & 0x0F; + if (halt <= resume) { + halt = TCR_HALT_DEFAULT; + resume = TCR_RESUME_DEFAULT; + } + + // Note: TCR accessible only when EFR[4]=1 and MCR[2]=1 + this->writeRegister(TCR, (resume << 4) | halt); // set TCR register +} + + +/** Set the Modem Control register + * This method sets prescaler, enables TCR and TLR + * + * @param none + * @return none + */ +void SC16IS750::set_modem_control() { + + //Note MCR[7:4] and MCR[2] only accessible when EFR[4] is set + if (SC16IS750_PRESCALER == SC16IS750_PRESCALER_1) { // Default prescaler after reset + this->writeRegister(MCR, MCR_PRESCALE_1 | MCR_ENABLE_TCR_TLR); + } + else { + this->writeRegister(MCR, MCR_PRESCALE_4 | MCR_ENABLE_TCR_TLR); + } +} + /** Initialise internal registers @@ -184,29 +230,40 @@ // Software reset, assuming there is no access to the HW Reset pin swReset(); - - // Set default baudrate and save in _config - // LCR, DLL/DLH + + // Set default baudrate (depends on prescaler) and save in _config + // DLL/DLH baud(); - // Set dataflow and save in _config - // LCR, EFR - set_flow_control(); - // Set default dataformat and save in _config // LCR format(); + // Set dataflow mode and Enables enhanced functions + // Save in _config + // EFR + set_flow_control(); + + + // FIFO control, sets TX and RX trigger levels and enables FIFO and save in _config + // Note FCR[5:4] only accessible when EFR[4] is set (enhanced functions enable) + // FCR, TLR + set_fifo_control(); + flush(); + + // Modem control, sets prescaler, enable TCR and TLR + // Note MCR[7:4] and MCR[2] only accessible when EFR[4] is set (enhanced functions enable) + set_modem_control(); + + // Set RTS trigger levels + // Note TCR only accessible when EFR[4] is set (enhanced functions enable) and MCR[2] is set + set_flow_triggers(); + + // Set default break condition and save in _config // LCR //set_break(); - - // Set default fifoformat and save in _config - // FCR - _config.fifoenable = true; - _config.fifoformat = FCR_RX_IRQ_NONE | FCR_ENA_FIFO_64; - flush(); - + // The UART bridge should now be successfully initialised. // Test if UART bridge is present and initialised @@ -224,12 +281,48 @@ } + +/** FIFO control, sets TX and RX trigger levels and enables FIFO and save in _config + * Note FCR[5:4] (=TX_IRQ_LVL) only accessible when EFR[4] is set (enhanced functions enable) + * Note TLR only accessible when EFR[4] is set (enhanced functions enable) and MCR[2] is set + * @param none + * @return none + */ +void SC16IS750::set_fifo_control() { + + // Set default fifoformat + // FCR + _config.fifoenable = true; + + // Note FCR[5:4] (=TX_IRQ_LVL) only accessible when EFR[4] is set (enhanced functions enable) +// _config.fifoformat = FCR_RX_IRQ_8 | FCR_TX_IRQ_56; + _config.fifoformat = FCR_RX_IRQ_8 | FCR_TX_IRQ_8; //Default + + if (_config.fifoenable) + // enable FIFO mode and set FIFO control values + this->writeRegister(FCR, _config.fifoformat | FCR_ENABLE_FIFO); + else + // disable FIFO mode and set FIFO control values + this->writeRegister(FCR, _config.fifoformat); + + // Set Trigger level register TLR for RX and TX interrupt generation + // Note TLR only accessible when EFR[4] is set (enhanced functions enable) and MCR[2] is set + // TRL Trigger levels for RX and TX are 0..15, meaning 0-60 with a granularity of 4 chars + // When TLR for RX or TX are 'Zero' the corresponding values in FCR are used. The FCR settings + // have less resolution (only 4 levels) so TLR is considered an enhanced function. + this->writeRegister(TLR, 0x00); // Use FCR Levels +// this->writeRegister(TLR, (TLR_RX_DEFAULT << 4) | TLR_TX_DEFAULT); // Use Default enhanced levels + +} + + /** * Flush the UART FIFOs while maintaining current FIFO mode. * @param none * @return none */ void SC16IS750::flush() { + // FCR is Write Only, use saved _config // reset TXFIFO, reset RXFIFO, non FIFO mode this->writeRegister(FCR, FCR_TXFIFO_RST | FCR_RXFIFO_RST); @@ -277,22 +370,30 @@ /** Determine if there is a character available to read. + * This is data that's already arrived and stored in the receive + * buffer (which holds 64 chars). + * * @return 1 if there is a character available to read, 0 otherwise */ int SC16IS750::readable() { - return (this->readRegister(LSR) & 0x01); + +// if (this->readableCount() > 0) { // Check count + if (this->readRegister(LSR) & LSR_DR) { // Data in Receiver Bit, at least one character waiting + return 1; + } + else { + return 0; + } + } /** Determine how many characters are available to read. + * This is data that's already arrived and stored in the receive + * buffer (which holds 64 chars). + * * @return int Characters available to read */ int SC16IS750::readableCount() { - /* - * Get the number of chars (characters) available for reading. - * - * This is data that's already arrived and stored in the receive - * buffer (which holds 64 chars). - */ return (this->readRegister(RXLVL)); } @@ -301,22 +402,25 @@ * @return 1 if there is a space for a character to write, 0 otherwise */ int SC16IS750::writable() { - return (this->writableCount() > 0); // Check datasheet for faster version + +// if ((this->writableCount() > 0) { // Check count + if (this->readRegister(LSR) & LSR_THRE) { // THR Empty, space for at least one character + return 1; + } + else { + return 0; + } } /** Determine how much space available for writing characters. + * This considers data that's already stored in the transmit + * buffer (which holds 64 chars). + * * @return int character space available to write */ int SC16IS750::writableCount() { - /* - * Get the available space for writing characters. - * - * This is data that's already stored in the transmit - * buffer (which holds 64 chars). - */ - return (this->readRegister(TXLVL)); -// return (readRegister(64 - TXLVL)); //Check datasheet + return (this->readRegister(TXLVL)); // TX Level } @@ -341,6 +445,7 @@ * @return value written */ int SC16IS750::putc(int value) { + while (this->readRegister(TXLVL) == 0) { // Wait for space in TX buffer wait_us(10); @@ -350,39 +455,62 @@ return value; } - +/** + * Write char string to UART Bridge. Blocking when no free space in FIFO + * @param *str char string to be written + * @return none + */ void SC16IS750::write(const char *str) { - /* - * Write string to UART. - */ - write((const uint8_t *) str, strlen(str)); - while (this->readRegister(TXLVL) < 64) { - // Wait for empty TX buffer (slow) - wait_us(10); - // (But apparently still not slow enough to ensure delivery.) - }; -} #if ENABLE_BULK_TRANSFERS -void SC16IS750::write(const uint8_t *buffer, size_t size) { - /* + + #define BULK_BLOCK_LEN 16 + int len, idx; - Write buffer to UART. - - */ - //select(); - //transfer(THR); // TODO: Change this when we modify register addresses? (Even though it's 0x00.) + len = strlen(str); - while(size > 16) { - //transfer_bulk(buffer, 16); //ringbuffer? - size -= 16; - buffer += 16; + // Write blocks of BULK_BLOCK_LEN + while (len > BULK_BLOCK_LEN) { + while(this->readRegister(TXLVL) < BULK_BLOCK_LEN) { + // Wait for space in TX buffer + wait_us(10); + }; + + // Write a block of BULK_BLOCK_LEN bytes + // Note: can be optimized by writing registeraddress once and then repeatedsly write the bytes. + for (idx=0; idx<BULK_BLOCK_LEN; idx++) { + this->writeRegister(THR, str[idx]); + }; + + len -= BULK_BLOCK_LEN; + str += BULK_BLOCK_LEN; } - //transfer_bulk(buffer, size); + + // Write remaining bytes + for (idx=0; idx<len; idx++) { + while (this->readRegister(TXLVL) == 0) { + // Wait for space in TX buffer + wait_us(10); + }; + this->writeRegister(THR, str[idx]); + } + - //deselect(); +#else + int len, idx; + + len = strlen(str); + for (idx=0; idx<len; idx++) { + while (this->readRegister(TXLVL) == 0) { + // Wait for space in TX buffer + wait_us(10); + }; + this->writeRegister(THR, str[idx]); + } +#endif } -#endif + + /** Set direction of I/O port pins. * This method is specific to the SPI-I2C UART and not found on the 16750
--- a/SC16IS750.h Sun Feb 09 14:58:06 2014 +0000 +++ b/SC16IS750.h Thu Feb 13 17:12:02 2014 +0000 @@ -1,5 +1,5 @@ /* SC16IS750 interface - * v0.1 WH, Nov 2013, Ported to mbed, Sparkfun Libs used as example. Added I2C and SPI I/F and more methods + * v0.1 WH, Nov 2013, Sparkfun Libs used as example. Added I2C I/F and many more methods * * Permission is hereby granted, free of charge, to any person obtaining a copy of this software * and associated documentation files (the "Software"), to deal in the Software without restriction, @@ -20,106 +20,91 @@ #define _SC16IS750_H //I2C Slaveaddresses A1 A0 -#define SC16IS750_SA0 0x90 /* VDD VDD */ -#define SC16IS750_SA1 0x92 /* VDD VSS */ -#define SC16IS750_SA2 0x94 /* VDD SCL */ -#define SC16IS750_SA3 0x95 /* VDD SDA */ -#define SC16IS750_SA4 0x98 /* VSS VDD */ -#define SC16IS750_SA5 0x9A /* VSS VSS */ -#define SC16IS750_SA6 0x9C /* VSS SCL */ -#define SC16IS750_SA7 0x9E /* VSS SDA */ -#define SC16IS750_SA8 0xA0 /* SCL VDD */ -#define SC16IS750_SA9 0xA2 /* SCL VSS */ -#define SC16IS750_SA10 0xA4 /* SCL SCL */ -#define SC16IS750_SA11 0xA6 /* SCL SDA */ -#define SC16IS750_SA12 0xA8 /* SDA VDD */ -#define SC16IS750_SA13 0xAA /* SDA VSS */ -#define SC16IS750_SA14 0xAC /* SDA SCL */ -#define SC16IS750_SA15 0xAE /* SDA SDA */ +#define SC16IS750_SA0 0x90 /* VDD VDD */ +#define SC16IS750_SA1 0x92 /* VDD VSS */ +#define SC16IS750_SA2 0x94 /* VDD SCL */ +#define SC16IS750_SA3 0x95 /* VDD SDA */ +#define SC16IS750_SA4 0x98 /* VSS VDD */ +#define SC16IS750_SA5 0x9A /* VSS VSS */ +#define SC16IS750_SA6 0x9C /* VSS SCL */ +#define SC16IS750_SA7 0x9E /* VSS SDA */ +#define SC16IS750_SA8 0xA0 /* SCL VDD */ +#define SC16IS750_SA9 0xA2 /* SCL VSS */ +#define SC16IS750_SA10 0xA4 /* SCL SCL */ +#define SC16IS750_SA11 0xA6 /* SCL SDA */ +#define SC16IS750_SA12 0xA8 /* SDA VDD */ +#define SC16IS750_SA13 0xAA /* SDA VSS */ +#define SC16IS750_SA14 0xAC /* SDA SCL */ +#define SC16IS750_SA15 0xAE /* SDA SDA */ //Default I2C Slaveaddress -#define DEFAULT_SC16IS750_ADDR SC16IS750_SA0 +#define SC16IS750_DEFAULT_ADDR SC16IS750_SA0 + + +/** See datasheet section 7.8 for configuring the + * "Programmable baud rate generator" + */ +#define SC16IS750_XTAL_FREQ 14745600UL /* On-board crystal (New mid-2010 Version) */ +#define SC16IS750_PRESCALER_1 1 /* Default prescaler after reset */ +#define SC16IS750_PRESCALER_4 4 /* Selectable by setting MCR[7] */ +#define SC16IS750_PRESCALER SC16IS750_PRESCALER_1 +#define SC16IS750_BAUDRATE_DIVISOR(baud) ((SC16IS750_XTAL_FREQ/SC16IS750_PRESCALER)/(baud*16UL)) //Default baudrate -#define DEFAULT_BAUD_RATE 9600 - -#define ENABLE_BULK_TRANSFERS 0x01 - -#define XTAL_FREQUENCY 14745600UL // On-board crystal (New mid-2010 Version) - -// See datasheet section 7.8 for configuring the -// "Programmable baud rate generator" -#define PRESCALER 1 // Default prescaler after reset -#define BAUD_RATE_DIVISOR(baud) ((XTAL_FREQUENCY/PRESCALER)/(baud*16UL)) - -// See section 8.4 of the datasheet for definitions -// of bits in the Line Control Register (LCR) -#define LCR_BITS5 0x00 -#define LCR_BITS6 0x01 -#define LCR_BITS7 0x02 -#define LCR_BITS8 0x03 - -#define LCR_BITS1 0x00 -#define LCR_BITS2 0x04 - -#define LCR_NONE 0x00 -#define LCR_ODD 0x08 -#define LCR_EVEN 0x18 -#define LCR_FORCED1 0x28 -#define LCR_FORCED0 0x38 - -#define LCR_BRK_ENA 0x40 -#define LCR_BRK_DIS 0x00 - -#define LCR_ENABLE_DIV 0x80 -#define LCR_DISABLE_DIV 0x00 - -#define LCR_ENABLE_ENHANCED_FUNCTIONS (0xBF) - -// See section 8.10 of the datasheet for definitions -// of bits in the Enhanced Features Register (EFR) -#define EFR_ENABLE_CTS (1 << 7) -#define EFR_ENABLE_RTS (1 << 6) -#define EFR_ENABLE_ENHANCED_FUNCTIONS (1 << 4) +#define SC16IS750_DEFAULT_BAUDRATE 9600 -// See section 8.xx of the datasheet for definitions -// of bits in the Flow Control Register (FCR) -#define FCR_RX_IRQ_14 (3 << 6) -#define FCR_RX_IRQ_8 (2 << 6) -#define FCR_RX_IRQ_4 (1 << 6) -#define FCR_RX_IRQ_1 (0 << 6) -#define FCR_RX_IRQ_NONE (0 << 6) -#define FCR_ENA_FIFO_64 (1 << 5) +/** See section 8.3 of the datasheet for definitions + * of bits in the FIFO Control Register (FCR) + */ +#define FCR_RX_IRQ_60 (3 << 6) +#define FCR_RX_IRQ_56 (2 << 6) +#define FCR_RX_IRQ_16 (1 << 6) +#define FCR_RX_IRQ_8 (0 << 6) +//TX Level only accessible when EFR[4] is set +#define FCR_TX_IRQ_56 (3 << 4) +#define FCR_TX_IRQ_32 (2 << 4) +#define FCR_TX_IRQ_16 (1 << 4) +#define FCR_TX_IRQ_8 (0 << 4) +//#define FCR_RESERVED (1 << 3) #define FCR_TXFIFO_RST (1 << 2) #define FCR_RXFIFO_RST (1 << 1) #define FCR_ENABLE_FIFO (1 << 0) +//FIFO size +#define SC16IS750_FIFO_RX 64 +#define SC16IS750_FIFO_TX 64 -/* - * Interrupt enable register. - */ +/** See section 8.4 of the datasheet for definitions + * of bits in the Line Control Register (LCR) + */ +#define LCR_BITS5 0x00 +#define LCR_BITS6 0x01 +#define LCR_BITS7 0x02 +#define LCR_BITS8 0x03 -#define IER_ERBI (0x01) /* Enable received data available interrupt */ -#define IER_ETBEI (0x02) /* Enable transmitter holding register empty interrupt */ -#define IER_ELSI (0x04) /* Enable receiver line status interrupt */ -#define IER_EDSSI (0x08) /* Enable modem status interrupt */ -#define IER_SLEEP (0x10) /* Enable sleep mode */ +#define LCR_BITS1 0x00 +#define LCR_BITS2 0x04 -/* - * Modem control register. - */ +#define LCR_NONE 0x00 +#define LCR_ODD 0x08 +#define LCR_EVEN 0x18 +#define LCR_FORCED1 0x28 +#define LCR_FORCED0 0x38 + +#define LCR_BRK_ENA 0x40 +#define LCR_BRK_DIS 0x00 -#define MCR_MDTR (0x01) /* Data terminal ready. */ -#define MCR_MRTS (0x02) /* Request to send. */ -//#define MCR_TCR_TLR_BIT (6) -#define MCR_ENABLE_TCR_TLR (1 << 2) +#define LCR_ENABLE_DIV 0x80 +#define LCR_DISABLE_DIV 0x00 + +#define LCR_ENABLE_ENHANCED_FUNCTIONS (0xBF) -/* - * Line status register. - */ +/** See section 8.5 of the datasheet for definitions + * of bits in the Line status register (LSR) + */ #define LSR_DR (0x01) /* Data ready */ #define LSR_OE (0x02) /* Overrun error */ #define LSR_PE (0x04) /* Parity error */ @@ -127,34 +112,107 @@ #define LSR_BI (0x10) /* Break interrupt */ #define LSR_THRE (0x20) /* Transmitter holding register (FIFO empty) */ #define LSR_TEMT (0x40) /* Transmitter empty (FIFO and TSR both empty) */ +#define LSR_FFE (0x80) /* At least one PE, FE or BI in FIFO */ -/* - * Interrupt identification register. - * Bit 0 is set to 0 if an IT is pending. - * Bits 1 and 2 are used to identify the IT. - */ + +/** See section 8.6 of the datasheet for definitions + * of bits in the Modem control register (MCR) + */ +#define MCR_MDTR (1 << 0) /* Data Terminal Ready pin control. */ +#define MCR_MRTS (1 << 1) /* Request to Send pin control when not in Auto RTS mode.*/ +#define MCR_ENABLE_TCR_TLR (1 << 2) +#define MCR_ENABLE_LOOPBACK (1 << 4) +#define MCR_ENABLE_XON_ANY_CHAR (1 << 5) +#define MCR_ENABLE_IRDA (1 << 6) +#define MCR_PRESCALE_1 (0 << 7) +#define MCR_PRESCALE_4 (1 << 7) + -#define IIR_BITS_USED (0x07) -#define IIR_IT_NOT_PENDING (0x01) -#define IIR_RX_DATA (0x04) -#define IIR_TX_EMPTY (0x02) -#define IIR_MODEM_STATUS (0x00) +/** See section 8.7 of the datasheet for definitions + * of bits in the Modem status register (MSR) + */ + + +/** See section 8.8 of the datasheet for definitions + * of bits in the Interrupt enable register (IER) + */ +#define IER_ERBI (0x01) /* Enable received data available interrupt */ +#define IER_ETBEI (0x02) /* Enable transmitter holding register empty interrupt */ +#define IER_ELSI (0x04) /* Enable receiver line status interrupt */ +#define IER_EDSSI (0x08) /* Enable modem status interrupt */ +#define IER_SLEEP (0x10) /* Enable sleep mode */ -/* - * IO Control register. - * Bit 0 is set to 0 to enable latch of IO inputs. - * Bit 1 is set to enable GPIO[7-4] as /RI, /CD, /DTR, /DST. - * Bit 2 is set to enable software reset. - */ -#define IOC_ENA_LATCH (0x01) -#define IOC_ENA_MODEM (0x02) -#define IOC_SW_RST (0x04) +/** See section 8.9 of the datasheet for definitions + * of bits in the Interrupt identification register (IIR) + * Bit 0 is set to 0 if an IT is pending. + * Bits 1 and 2 are used to identify the IT. + */ +#define IIR_BITS_USED (0x07) +#define IIR_IT_NOT_PENDING (0x01) +#define IIR_RX_DATA (0x04) +#define IIR_TX_EMPTY (0x02) +#define IIR_MODEM_STATUS (0x00) + + +/** See section 8.10 of the datasheet for definitions + * of bits in the Enhanced Features Register (EFR) + */ +#define EFR_ENABLE_CTS (1 << 7) +#define EFR_ENABLE_RTS (1 << 6) +#define EFR_ENABLE_XOFF2_CHAR_DETECT (1 << 5) +#define EFR_ENABLE_ENHANCED_FUNCTIONS (1 << 4) +// EFR[3:0] are used to define Software Flow Control mode +// See section 7.3 +#define EFR_DISABLE_TX_FLOW_CTRL (0x0 << 2) +#define EFR_TX_XON2_XOFF2 (0x1 << 2) +#define EFR_TX_XON1_XOFF1 (0x2 << 2) +#define EFR_TX_XON2_1_XOFF2_1 (0x3 << 2) + +#define EFR_DISABLE_RX_FLOW_CTRL (0x0 << 0) +#define EFR_RX_XON2_XOFF2 (0x1 << 0) +#define EFR_RX_XON1_XOFF1 (0x2 << 0) +#define EFR_RX_XON2_1_XOFF2_1 (0x3 << 0) + +#define EFR_TX_XON2_XOFF2_RX_FLOW (0x1 << 2) | (0x3 << 0) +#define EFR_TX_XON1_XOFF1_RX_FLOW (0x2 << 2) | (0x3 << 0) +#define EFR_TX_XON2_1_XOFF2_1_RX_FLOW (0x3 << 2) | (0x3 << 0) +/** See section 8.12 of the datasheet for definitions + * of bits in the Transmission Control Register (TCR) + * Trigger level to halt transmission: 0..15 (meaning 0-60 with a granularity of 4) + * Trigger level to resume transmission: 0..15 (meaning 0-60 with a granularity of 4) + */ +#define TCR_HALT_DEFAULT (0x0E) +#define TCR_RESUME_DEFAULT (0x04) + + +/** See section 8.13 of the datasheet for definitions + * of bits in the Trigger Level Register (TLR) + * Trigger level for TX interrupt: 0..15 (meaning 0-60 with a granularity of 4) + * Trigger level for RX interrupt: 0..15 (meaning 0-60 with a granularity of 4) + */ +#define TLR_TX_DEFAULT (0x0E) +#define TLR_RX_DEFAULT (0x04) + + +/** + * See section 8.19 of the datasheet for definitions + * of bits in the IO Control register (IOC) + * + * Bit 0 is set to 0 to enable latch of IO inputs. + * Bit 1 is set to enable GPIO[7-4] as /RI, /CD, /DTR, /DST. + * Bit 2 is set to enable software reset. + */ +#define IOC_ENA_LATCH (0x01) +#define IOC_ENA_MODEM (0x02) +#define IOC_SW_RST (0x04) + + // See Chapter 11 of datasheet -#define SPI_READ_MODE_FLAG 0x80 +#define SPI_READ_MODE_FLAG (0x80) /** Abstract class SC16IS750 for a converter between either SPI or I2C and a Serial port @@ -265,13 +323,19 @@ /** Determine if there is a character available to read. + * This is data that's already arrived and stored in the receive + * buffer (which holds 64 chars). + * * @return 1 if there is a character available to read, 0 otherwise */ int readable(); -/** Determine how many characters available for reading. +/** Determine how many characters are available to read. + * This is data that's already arrived and stored in the receive + * buffer (which holds 64 chars). + * * @return int Characters available to read - */ + */ int readableCount(); /** Determine if there is space available to write a character. @@ -279,9 +343,13 @@ */ int writable(); + /** Determine how much space available for writing characters. + * This considers data that's already stored in the transmit + * buffer (which holds 64 chars). + * * @return int character space available to write - */ + */ int writableCount(); @@ -300,20 +368,28 @@ */ int putc(int value); + +/** + * Write char string to UART Bridge. Blocking when no free space in FIFO + * @param *str char string to be written + * @return none + */ void write(const char *str); /** Set baudrate of the serial port. * @param baud integer baudrate (4800, 9600 etc) * @return none */ - void baud(int baudrate = DEFAULT_BAUD_RATE); + void baud(int baudrate = SC16IS750_DEFAULT_BAUDRATE); /** Set the transmission format used by the serial port. * @param bits The number of bits in a word (5-8; default = 8) * @param parity The parity used (Serial::None, Serial::Odd, Serial::Even, Serial::Forced1, Serial::Forced0; default = Serial::None) * @param stop_bits The number of stop bits (1 or 2; default = 1) + * @return none */ void format(int bits=8, Serial::Parity parity=Serial::None, int stop_bits=1); + #if(0) /** Attach a function to call whenever a serial interrupt is generated * @@ -327,6 +403,7 @@ * @param tptr pointer to the object to call the member function on * @param mptr pointer to the member function to be called * @param type Which serial interrupt to attach the member function to (Seriall::RxIrq for receive, TxIrq for transmit buffer empty) + * @return none */ template<typename T> void attach(T* tptr, void (T::*mptr)(void), IrqType type=RxIrq) { @@ -338,25 +415,51 @@ #endif /** Generate a break condition on the serial line + * @param none + * @return none */ void send_break(); /** Set a break condition on the serial line * @param enable break condition + * @return none */ void set_break(bool enable=false); /** Set the flow control type on the serial port * Added for compatibility with Serial Class. - * SC16IS750 supports only Flow, Pins can not be selected. + * SC16IS750 supports only Flow, Pins can not be selected. + * This method sets only hardware flow control. SC16IS750 supports XON/XOFF, but this is not implemented. * * @param type the flow control type (Disabled, RTS, CTS, RTSCTS) * @param flow1 the first flow control pin (RTS for RTS or RTSCTS, CTS for CTS) * @param flow2 the second flow control pin (CTS for RTSCTS) + * @return none */ void set_flow_control(Flow type=Disabled, PinName flow1=NC, PinName flow2=NC); + + +/** Set the RX FIFO flow control levels + * This method sets only hardware flow control levels. SC16IS750 supports XON/XOFF, but this is not implemented. + * Should be called BEFORE Auto RTS is enabled. + * + * @param resume trigger level to resume transmission (0..15, meaning 0-60 with a granularity of 4) + * @param halt trigger level to resume transmission (0..15, meaning 0-60 with granularity of 4) + * @return none + */ + void set_flow_triggers(int resume = TCR_RESUME_DEFAULT, int halt = TCR_HALT_DEFAULT); + + +/** Set the Modem Control register + * This method sets prescaler, enables TCR and TLR + * + * @param none + * @return none + */ + void set_modem_control(); + /** * Check that UART is connected and operational. @@ -366,11 +469,15 @@ bool connected(); -#if ENABLE_BULK_TRANSFERS - void write(const uint8_t *buffer, size_t size); -#else - // using Print::write; -#endif + +/** FIFO control, sets TX and RX trigger levels and enables FIFO and save in _config + * Note FCR[5:4] (=TX_IRQ_LVL) only accessible when EFR[4] is set (enhanced functions enable) + * Note TLR only accessible when EFR[4] is set (enhanced functions enable) and MCR[2] is set + * @param none + * @return none + */ + void set_fifo_control(); + /** Flush the UART FIFOs while maintaining current FIFO mode. * @param none @@ -439,12 +546,13 @@ protected: //protected is accessible to derived classes, but not to external users -/** Constructor for this Abstract Class is protected + +/** Constructor is protected for this abstract Class * */ SC16IS750(); - +// Save config settings SC16IS750_cfg _config; private: @@ -471,6 +579,9 @@ * while(1) { * serial_spi.ioSetState(0x00); * wait(0.5); + * serial_spi.ioSetState(0xFF); + * wait(0.5); + * serial_spi.putc('*'); * pc.putc('*'); * } * } @@ -529,6 +640,9 @@ * while(1) { * serial_i2c.ioSetState(0x00); * wait(0.5); + * serial_i2c.ioSetState(0xFF); + * wait(0.5); + * serial_i2c.putc('*'); * pc.putc('*'); * } * } @@ -543,7 +657,7 @@ * @param I2C &i2c the I2C port to connect to * @param char deviceAddress the address of the SC16IS750 */ - SC16IS750_I2C(I2C *i2c, uint8_t deviceAddress = DEFAULT_SC16IS750_ADDR); + SC16IS750_I2C(I2C *i2c, uint8_t deviceAddress = SC16IS750_DEFAULT_ADDR); /** Write value to internal register. * @param registerAddress The address of the Register (enum RegisterName)