Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of SC16IS752 by
Diff: SC16IS752.cpp
- Revision:
- 0:ad254d5f94b1
- Child:
- 1:85070c9144a6
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SC16IS752.cpp Wed Aug 10 03:40:03 2016 +0000 @@ -0,0 +1,399 @@ +#include "mbed.h" +#include "SC16IS752.h" +#include <vector> + +#define ENABLE_BULK_TRANSFERS 1 +#define BULK_BLOCK_LEN 16 +#define MAX_BUFF 64 + +extern Serial dbg; + +SC16IS752::SC16IS752(PinName sda, PinName scl, uint8_t deviceAddress, PinName rst, ChannelName channel) : _i2c(sda, scl), _slaveAddress(deviceAddress & 0xFE), _channel(channel) +{ + _i2c.frequency(400000); + _i2c.start(); + _i2c.stop(); + + if (_i2c.read(deviceAddress, &data[0], 1) != 0) + { + dbg.printf(RED "I2C device is not detected\r\n" DEF); + } + else + { + dbg.printf(GRE "I2C device is detected\r\n" DEF); + } + + data[0]=0; + _i2c.start(); + _i2c.stop(); + + if (rst != NC) + { + _reset = new DigitalOut(rst); //Construct new pin + _reset->write(1); //Deactivate + } + else + { + _reset = NULL; //Construct dummy pin + } +} + +SC16IS752::~SC16IS752() +{ + if (_reset != NULL) {delete _reset;} // Reset pin +} + +bool SC16IS752::wr(char adr, char data) +{ + w[0] = adr | _channel; + w[1] = data; + if (_i2c.write(_slaveAddress, w, 2) != 0) return 0; + + return true; +} + +void SC16IS752::wrblock(const char *data, int len ) +{ + int i; + + _i2c.start(); + _i2c.write(_slaveAddress); + _i2c.write(THR | _channel); + + for (i=0; i<len; i++) + { + _i2c.write(data[i]); + wait_ms(1); + } + + _i2c.stop(); +} + +char SC16IS752::rd(char adr) +{ + char start = adr | _channel;; + if (_i2c.write(_slaveAddress, &start, 1, true) != 0) dbg.printf(RED "SPR No Ack!\r\n" DEF); + if (_i2c.read(_slaveAddress, r, 1) != 0) dbg.printf(RED "SPR No Ack!\r\n" DEF); + + return r[0]; +} + +bool SC16IS752::swReset() +{ + if(wr(IOCTRL, IOC_SW_RST)) + return true; + else return 0; +} + +bool SC16IS752::baud(int baudrate) +{ + unsigned long divisor = SC16IS752_BAUDRATE_DIVISOR(baudrate); + char lcr_tmp; + + _config.baudrate = baudrate; + + lcr_tmp = rd(LCR); + if(!wr(LCR, lcr_tmp | LCR_ENABLE_DIV)) return 0; + if(!wr(DLL, ( divisor & 0xFF))) return 0; + if(!wr(DLH, ((divisor >> 8) & 0xFF))) return 0; + if(!wr(LCR, lcr_tmp)) return 0; + + return true; +} + +bool SC16IS752::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; + } + + 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; + + if(!wr(LCR, lcr_tmp)) return 0; + + return true; +} + +bool SC16IS752::set_flow_control(Flow type, PinName flow1, PinName flow2) +{ + char lcr_tmp; + char efr_tmp = 0x00; + + 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; + } + + _config.flowctrl = efr_tmp | EFR_ENABLE_ENHANCED_FUNCTIONS; + + lcr_tmp = rd(LCR); + if(!wr(LCR, LCR_ENABLE_ENHANCED_FUNCTIONS)) return 0; + if(!wr(EFR, _config.flowctrl)) return 0; + if(!wr(LCR, lcr_tmp)) return 0; + + return true; +} + +bool SC16IS752::set_flow_triggers(int resume, int halt) +{ + halt = halt & 0x0F; + resume = resume & 0x0F; + if (halt <= resume) + { + halt = TCR_HALT_DEFAULT; + resume = TCR_RESUME_DEFAULT; + } + + if(!wr(TCR, (resume << 4) | halt)) return 0; + + return true; +} + +bool SC16IS752::set_modem_control() +{ + if (SC16IS752_PRESCALER == SC16IS752_PRESCALER_1) + { + if(!wr(MCR, MCR_PRESCALE_1 | MCR_ENABLE_TCR_TLR)) return 0; + } + else + { + if(!wr(MCR, MCR_PRESCALE_4 | MCR_ENABLE_TCR_TLR)) return 0; + } + + return true; +} + +bool SC16IS752::connected() +{ + char TEST_CHARACTER = 'A'; + + if(!wr(SPR, TEST_CHARACTER)) return 0; + + char test = rd(SPR); + + dbg.printf("read char: %c\r\n",test); + + if(test == TEST_CHARACTER) + return true; + else return 0; +} + +bool SC16IS752::set_fifo_control(bool stat) +{ + _config.fifoenable = stat; + + _config.fifoformat = FCR_RX_IRQ_8 | FCR_TX_IRQ_8; + + if (_config.fifoenable) + if(!wr(FCR, _config.fifoformat | FCR_ENABLE_FIFO)) return 0; + else + if(!wr(FCR, _config.fifoformat)) return 0; + + if(!wr(TLR, 0x00)) return 0; + + return true; +} + +bool SC16IS752::flush() +{ + if(!wr(FCR, FCR_TX_FIFO_RST | FCR_RX_FIFO_RST)) return 0; + + if (_config.fifoenable) + if(!wr(FCR, _config.fifoformat | FCR_ENABLE_FIFO)) return 0; + else + if(!wr(FCR, _config.fifoformat)) return 0; + + return true; +} + +bool SC16IS752::readable() +{ + if (rd(LSR) & LSR_DR) // Data in Receiver Bit, at least one character waiting + { + dbg.printf(GRE "Serial is readable\r\n" DEF); + return true; + } + else + { + dbg.printf(RED "Serial is not readable\r\n" DEF); + return false; + } +} + +int SC16IS752::readableCount() +{ + int result = (int)rd(RXLVL); + dbg.printf("readable count = %d\r\n", result); + return result; +} + +int SC16IS752::writeable() +{ + if (rd(LSR) & LSR_THRE) // THR Empty, space for at least one character + { + dbg.printf(GRE "Serial is writeable\r\n" DEF); + return true; + } + else + { + dbg.printf(RED "Serial is writeable\r\n" DEF); + return false; + } +} + +int SC16IS752::writeableCount() +{ + int result = (int)rd(TXLVL); + dbg.printf("writeable count = %d\r\n", result); + return result; +} + +int SC16IS752::get() +{ + if (!readable()) + { + return -1; + } + char res = rd(RHR); + return res; +} + +int SC16IS752::put(int value) +{ + while (writeableCount() == 0); +// { +// wait_us(1); +// }; + + if(!wr(THR, value)) return false; + + return true; +} + +void SC16IS752::writeString(const char *str) +{ + int len = strlen(str); + int count = 0; + + while(len) + { + int blk = MAX_BUFF; + + if(len < blk) + blk = len; + + if (blk > 0) + { + for(int i=0; i<blk; i++) + { + while (writeableCount() == 0) + { + wait_us(10); + }; + wr(THR, str[i + (count * blk)]); + } + + len = len - blk; + count++; + } + else len = 0; + } +} + +void SC16IS752::writeBytes(const char *data, int len) +{ +#if ENABLE_BULK_TRANSFERS + int idx; + + while (len > BULK_BLOCK_LEN) + { + while(rd(TXLVL) < BULK_BLOCK_LEN) + { + wait_us(10); + }; + + wrblock(data, BULK_BLOCK_LEN); + + len -= BULK_BLOCK_LEN; + data += BULK_BLOCK_LEN; + } + + for (idx=0; idx<len; idx++) + { + while (rd(TXLVL) == 0) + { + wait_us(10); + }; + wr(THR, data[idx]); + } +#else + int idx; + + for (idx=0; idx<len; idx++) + { + while (rd(TXLVL) == 0) + { + wait_us(10); + }; + wr(THR, str[idx]); + } +#endif +} + + +bool SC16IS752::init(int baudrate) +{ + if(!swReset())return 0; + if(!baud(baudrate))return 0; + if(!format())return 0; + if(!set_flow_control())return 0; + if(!set_fifo_control())return 0; + if(!flush())return 0; + if(!set_modem_control())return 0; + if(!set_flow_triggers())return 0; + + return true; +}