irsan julfikar / SC16IS752

Fork of SC16IS752 by irsan julfikar

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;
+}