UART to I2C master(s) converter, targetting to emulate SC18IM700(NXP) chip

Dependencies:   mbed

UART to I2C master(s) converter, targetting to emulate SC18IM700(NXP) chip

Features

up to 4x I2C master

  • for LPC824 implement, we can use up to 4 channels of I2C masters
    • 1x Fm+ and 3x Fm I2C channels
  • for LPC1768 implement, we can use up to 2 channels of I2C masters
    • 2x Fm I2C channels
  • for LPC11U35 implement, only one channel for I2C master, but program uses USB CDC class for UART communication (means no external USB-Serial converter chip)
    • 1x Fm+ I2C channels

1x SPI master

up to 2x 8bit GPIO

Tested Platforms

LPC824

LPC1768

LPC11U35

Quote:

LPC11U35 implement requires importing USBDevice library to use USBSerial class

visit https://github.com/K4zuki/tinyI2C for more information

main.cpp

Committer:
K4zuki
Date:
2016-08-31
Revision:
76:fcbc456010e0
Parent:
42:da85c17ea495

File content as of revision 76:fcbc456010e0:

/** uart_i2c_conv for LPC824
*/

#include "mbed.h"
#include "settings.h"
//Table 3. ASCII commands supported by SC18IM700
//ASCII command Hex value Command function
//[X] S 0x53 I2C-bus START
//[X] P 0x50 I2C/SPI-bus STOP
//[X] R 0x52 read SC18IM700 internal register
//[X] W 0x57 write to SC18IM700 internal register
//[?] I 0x49 read GPIO port
//[?] O 0x4F write to GPIO port
//[_] Z 0x5A power down
//[X] C 0x43 change channel
//[_] E 0x45 SPI transfer start
//[_] V 0x__ enable VDDIO output to chip

/**
"C| '0'| P"
"C| '1'| P"
"C| '2'| P"
"C| '3'| P"
"S| 0x_8 _0| 0x_0 _4| 0x_D _E _A _D _B _E _A _F| P"
"S| 0x_8 _0| 0x_0 _4| 0x_D _E _A _D _B _E _A _F| S| 0x_8 _1| 0x_0 _4| P"
"S| 0x_8 _1| 0x_0 _4| P"
"R| '0'| P"
"R| '0'| '1'| ...| P"
"W| '0' 0x_a _a| P"
"W| '0' 0x_a _a| '1' 0x_b _b| ...| P"
"I| '0'| P"
"O| '0'| 0x_a _a| P"
"E| 0x_0 _4| 0x_0 _0| 0x_D _E _A _D _B _E _A _F| P" //write
"E| 0x_0 _4| 0x_0 _4| 0x_D _E _A _D _B _E _A _F| P" //write and read
*/
int main()
{
    I2C* dev = &dev1;

#ifdef isUART
    pc.baud(115200);
#endif
    _spi.frequency(8000000);

    bool s = false;
    dev1.frequency(400000);//800k; works around 940kHz with 200ohm pullups/ not work at 1M?
#if defined(TARGET_SSCI824) || defined(TARGET_LP824MAX)
    dev1.frequency(800000);//800k; works around 940kHz with 200ohm pullups/ not work at 1M?
    LPC_IOCON->PIO0_11 &= ~(0x03<<8);
    LPC_IOCON->PIO0_11 |= (0x02<<8);
    LPC_IOCON->PIO0_10 &= ~(0x03<<8);
    LPC_IOCON->PIO0_10 |= (0x02<<8);
#elif defined(TARGET_MCU_LPC11U35_501) || defined(TARGET_LPC11U35_401)
    dev1.frequency(800000);//800k; works around 940kHz with 200ohm pullups/ not work at 1M?
    LPC_IOCON->PIO0_4 &= ~(0x03<<8);
    LPC_IOCON->PIO0_4 |= (0x02<<8);
    LPC_IOCON->PIO0_5 &= ~(0x03<<8);
    LPC_IOCON->PIO0_5 |= (0x02<<8);
#endif

#ifdef isI2C2
    dev2.frequency(400000);//400k
#endif
#ifdef isI2C3
    dev3.frequency(400000);//400k
#endif
#ifdef isI2C4
    dev4.frequency(400000);//400k
#endif
#ifdef isGPIO1
    DigitalInOut* gpio1[] = {
        &_GPIO10,
        &_GPIO11,
        &_GPIO12,
        &_GPIO13,
        &_GPIO14,
        &_GPIO15,
        &_GPIO16,
        &_GPIO17,
    };
    for(int k = 0; k < 8; k++){
        gpio1[k]->input();
        gpio1[k]->mode( PullUp );
    }
#endif

    DigitalInOut* gpio0[] = {
        &_GPIO00,
        &_GPIO01,
        &_GPIO02,
        &_GPIO03,
        &_GPIO04,
        &_GPIO05,
        &_GPIO06,
        &_GPIO07,
    };
    for(int k = 0; k < 8; k++){
        gpio0[k]->input();
        gpio0[k]->mode( PullUp );
    }

    int ack = 0;
    int plength = 0;
    int recieve[256];
    char send[256];
    for(int k = 0; k < 256; k+=4){
        // cafe moca
        recieve[k+0] = send[k+0] = 0xC4;
        recieve[k+1] = send[k+1] = 0xFE;
        recieve[k+2] = send[k+2] = 0xE0;
        recieve[k+3] = send[k+3] = 0xCA;
    }

    int read = 0;
    int address = 0;
    int data = 0;
    int _data = 0;
    int length = 0;
    int channel = 0;
    int format = 8;
    int enabled = 0;
    int disabled = 0;
    enum command_e {
        CMD_S='S',
        CMD_P='P',
        CMD_C='C',
        CMD_R='R',
        CMD_W='W',
        CMD_I='I',
        CMD_O='O',
        CMD_E='E',
    };
    enum channel_e {
        CH0 = '0',
        CH1 = '1',
        CH2 = '2',
        CH3 = '3',
    };
    enum register_e {
        CHIP_ID = '0',
        GPIO0_STAT = '1',
        GPIO1_STAT = '2',
        GPIO0_CONF = '3',
        GPIO1_CONF = '4',
        I2C_CONF = '5',
        SPI_CONF = '6',
        REG7,
        REG8,
        REG9,
    };
//    enum chipID_e {
//        ID_LPC824 = '0',
//        ID_LPC1768 = '1',
//        ID_LPC11UXX = '2',
//    };
//    static const uint8_t chip_id=ID_LPC824;
    static uint8_t registers[]={
        chip_id,
        0x00,
        0x00,
        0x00,
        0x00,
        0xFF,
        0x70,
        REG7,
        REG8,
        REG9,
    };

    int i=0;
    while(1) {
        i=0;
        length=0;
        while(true) {
            read = pc.getc();
            recieve[i] = read;
            i++;
            if(read == 'P') {
                plength = i;
                break;
            }
        }
        i=0;
        while(i < plength) {
            switch(recieve[i]) {
                case CMD_C:
                {
                    s = false;
                    channel=recieve[i+1];
                    switch(channel) {
                        case CH0:
                        {
                            channel = CH0;
                            dev = &dev1;
                            break;
                        }
#ifdef isI2C2
                        case CH1:
                        {
                            channel = CH1;
                            dev = &dev2;
                            break;
                        }
#endif
#ifdef isI2C3
                        case CH2:
                        {
                            channel = CH2;
                            dev = &dev3;
                            break;
                        }
#endif
#ifdef isI2C4
                        case CH3:
                        {
                            channel = CH3;
                            dev = &dev4;
                            break;
                        }
#endif
                        default:
                        {
                            channel = CH0;
                            dev = &dev1;
                            break;
                        }
                    }
                    i += 2;
                    break;
                }
                case CMD_S:
                {
                    s = true;
                    ack = plength - 2 - (i+1) + (recieve[i+2] & 0x01);
                    if(ack >= 4){ //valid packet
                        address = 0xff & (recieve[i+1] << 4 | (recieve[i+2] & 0x0F));
                        length = 0xff & (recieve[i+3] << 4 | (recieve[i+4] & 0x0F));

                        if(address & 0x01) { //read
                            ack = dev->read(address, send, length, false); //added
                            send[length] = ack;
                            length += 1;
                            i += 5;
                        } else { // write
                            for(int j = 0; j < (length * 2); j+=2) {
                                ack = 0xff&((recieve[5+j] << 4) | (recieve[6+j] & 0x0F));
                                *(send+(j/2)) = ack; //added
                            }
                            ack = dev->write(address, send, length, true); //added
                            i += (5 + length * 2);
                            send[0] = ack;
                            length = 1;
                        }
                    }else{
                        pc.printf("bad packet! %d, %d, %02X, %d\n\r",plength,i,recieve[(i+2)]&0x0F,ack);
                        s = false;
                        i = plength;
                    }
                    break;
                }
                case CMD_P:
                {
                    if(s){
                        dev->stop();
                        s = false;
                        if(send[length-1] == 0){
                            pc.printf("ACK,");
                        }else{
                            pc.printf("NAK,");
                        }
                        length--;
                    }
                    i = plength;
                    for(int j=0; j<length; j++) {
                        pc.printf("%02X,",send[j]);
                    }
                    pc.printf("ok\n\r");
                    break;
                }
                case CMD_R:
                {
                    s = false;
                    length = plength - 2;
                    if(length < 1){
                        pc.printf("bad packet! %d\n\r",length);
                        i = plength + 1;
                        length = 0;
                    }else{
                        for(int j = 0; j < length; j++){
                            address = recieve[i+1+j];
                            switch(address){
                                case CHIP_ID:
                                {
                                    data = chip_id;
                                    break;
                                }
                                case GPIO0_STAT:
                                {
                                    for(int k = 0; k < 8; k++){
                                        _data = gpio0[k]->read();
                                        data |= (_data << k);
                                    }
                                    registers[GPIO0_STAT-'0'] = data;
                                    break;
                                }
                                case GPIO0_CONF:
                                {
                                    data = registers[GPIO0_CONF-'0'];
                                    break;
                                }
#ifdef isGPIO1
                                case GPIO1_STAT:
                                {
                                    for(int k = 0; k < 8; k++){
                                        _data = gpio1[k]->read();
                                        data |= (_data << k);
                                    }
                                    registers[GPIO1_STAT-'0'] = data;
                                    break;
                                }
                                case GPIO1_CONF:
                                {
                                    data = registers[GPIO1_CONF-'0'];
                                    break;
                                }
#endif
                                case I2C_CONF:
                                {
                                    data = registers[I2C_CONF-'0'];
                                    break;
                                }
                                case SPI_CONF:
                                {
                                    data = registers[SPI_CONF-'0'];
                                    break;
                                }
                                default:
                                {
                                    data = 0xAA;
                                    break;
                                }
                            }
                            send[j] = (char)data;
                            data = 0;
                        }
                        i += (length+1);
                    }
                    break;
                }
                case CMD_W:
                {
                    s = false;
                    length = plength - 2;
                    if(length < 3){
                        pc.printf("bad packet! %d\n\r",length);
                        i = plength + 1;
                        length = 0;
                    }else{
                        for(int j = 0; j < length; j +=3){
                            address = recieve[i+1+j];
                            data = 0xff & (recieve[i+2+j] << 4 | (recieve[i+3+j] & 0x0F));
                            _data = 0;
                            switch(address){
                                case CHIP_ID:
                                {
                                    //READ ONLY: do nothing
                                    data = registers[CHIP_ID-'0'];
                                    break;
                                }
                                case GPIO0_STAT:
                                {
                                    _data = registers[GPIO0_CONF-'0'];
                                    for(int k=0; k<8; k++){
                                        if(_data&0x01){ // output
                                            gpio0[k]->write((data>>k)&0x01);
                                        }else{ // input
                                            ; // do nothing
                                        }
                                        _data >>= 1;
                                    }
                                    break;
                                }
                                case GPIO0_CONF:
                                {
                                    registers[GPIO0_CONF-'0'] = data;
                                    for(int k = 0; k < 8; k++){
                                        if(data & 0x01){//output
                                            gpio0[k]->output();
                                        }else{//input
                                            gpio0[k]->input();
                                            gpio0[k]->mode(PullUp);
                                        }
                                        data >>= 1;
                                    }
                                    data = registers[GPIO0_CONF-'0'];
                                    break;
                                }
#ifdef isGPIO1
                                case GPIO1_STAT:
                                {
                                    _data = registers[GPIO1_CONF-'0'];
                                    for(int k = 0; k < 8; k++){
                                        if(_data & 0x01){ // output
                                            gpio1[k]->write((data>>k)&0x01);
                                        }else{ // input
                                            ; // do nothing
                                        }
                                        _data >>= 1;
                                    }
                                    break;
                                }
                                case GPIO1_CONF:
                                {
                                    registers[GPIO1_CONF-'0'] = data;
                                    for(int k = 0; k < 6; k++){
                                        if(data & 0x01){//output
                                            gpio1[k]->output();
                                        }else{//input
                                            gpio1[k]->input();
                                            gpio1[k]->mode(PullUp);
                                        }
                                        data >>= 1;
                                    }
                                    data = registers[GPIO1_CONF-'0'];
                                    break;
                                }
#endif
                                case I2C_CONF:
                                {
                                    registers[I2C_CONF-'0'] = data;
#if defined(TARGET_LPC1768)
                                    dev1.frequency(100000 * ((0x03 & (data >> 6)) + 1));
#else
                                    dev1.frequency(200000 * ((0x03 & (data >> 6)) + 1));
#endif
#ifdef isI2C2
                                    dev2.frequency(100000 * ((0x03 & (data >> 4)) + 1));
#endif
#ifdef isI2C3
                                    dev3.frequency(100000 * ((0x03 & (data >> 2)) + 1));
#endif
#ifdef isI2C4
                                    dev4.frequency(100000 * ((0x03 & (data >> 0)) + 1));
#endif
                                    break;
                                }
                                case SPI_CONF:
                                {
                                    registers[SPI_CONF-'0'] = data;
                                    format = ((data & 0x04) + 4) << 1;
                                    _spi.format(format, 0x03 & (data));
                                    _spi.frequency(1000000 * ((0x07 & (data >> 4)) + 1));
                                    enabled = (data & 0x08) >> 3;
                                    /*
                                    7 not used
                                    6:4 frequency
                                    3 CE pol
                                    2 word size(0=8bit,1=16bit)
                                    1:0 pol(corresponds to spi.format())
                                    */
                                    disabled = ~enabled;
                                    break;
                                }
                                default:
                                {
                                    break;
                                }
                            }
                            send[j/3] = data;
                        }
                        i += (length + 1);
                        length /= 3;
                    }
                    break;
                }
                case CMD_I:
                {
                    s = false;
                    length = plength - 2;
                    if(length < 1){
                        pc.printf("bad packet! %d\n\r",length);
                        i = plength + 1;
                        length = 0;
                    }else{
                        for(int j=0; j<length; j++){
                            address = recieve[i+1+j];
                            _data=0;
                            switch(address){
                                case GPIO0_STAT:
                                {
                                    for(int k=0; k<8; k++){
                                        _data = gpio0[k]->read();
                                        data |= (_data << k);
                                    }
                                    registers[GPIO0_STAT-'0'] = data;
                                    break;
                                }
#ifdef isGPIO1
                                case GPIO1_STAT:
                                {
                                    for(int k=0; k<8; k++){
                                        _data = gpio1[k]->read();
                                        data |= (_data << k);
                                    }
                                    registers[GPIO1_STAT-'0'] = data;
                                    break;
                                }
#endif
                                default:
                                {
                                    data = 0xAA;
                                    break;
                                }
                            }
                            send[j] = (char)data;
                            data = 0;
                        }
                        i += (length+1);
                    }
                    break;
                }
                case CMD_O:
                {
                    s = false;
                    length = plength - 2;
                    if(length < 3){
                        pc.printf("bad packet! %d\n\r",length);
                        i = plength + 1;
                        length = 0;
                    }else{
                        for(int j=0; j<length; j+=3){
                            address = recieve[i+1+j];
                            data = 0xff & (recieve[i+2+j] << 4 | (recieve[i+3+j] & 0x0F));
                            switch(address){
                                case GPIO0_STAT:
                                {
                                    _data = registers[GPIO0_CONF-'0'];
                                    for(int k=0; k<8; k++){
                                        if(_data&0x01){ // output
                                            gpio0[k]->write(data&0x01);
                                        }else{ // input
                                            ; // do nothing
                                        }
                                        data >>= 1;
                                        _data >>= 1;
                                    }
                                    break;
                                }
#ifdef isGPIO1
                                case GPIO1_STAT:
                                {
                                    _data = registers[GPIO1_CONF-'0'];
                                    for(int k=0; k<8; k++){
                                        if(_data&0x01){ // output
                                            gpio1[k]->write(data&0x01);
                                        }else{ // input
                                            ; // do nothing
                                        }
                                        data >>= 1;
                                        _data >>= 1;
                                    }
                                    break;
                                }
#endif
                                default:
                                {
                                    break;
                                }
                            }
                            send[j/3] = data;
                        }
                    }
                    i += (length+1);
                    length /= 3;
//                    pc.printf("command O is not implemented, ");
                    break;
                }
                case CMD_E:
                {
                    s = false;
                    /*
                    "0|   1   2|   3   4|   5   6  7  8  9 10 11 12|13" //plength=14
                    "E| 0x_0 _1| 0x_0 _0| 0x_D _E| P"                   //minimum plength=8
                    "E| 0x_0 _1| 0x_0 _0| 0x_D _E|_A _D| P"             //minimum plength=10(16bit)
                    "E| 0x_0 _4| 0x_0 _0| 0x_D _E _A _D _B _E _A _F| P" //write
                    "E| 0x_0 _4| 0x_0 _4| 0x_D _E _A _D _B _E _A _F| P" //write and read
                    */
                    length = plength - 2; //6
                    if(length < 6){
                        pc.printf("bad packet! %d\n\r",length);
                        i = plength + 1;
                        length = 0;
                    }else{
                        length = length-4; //actual data in packet
                        data = 0xff & ((recieve[i+1]<<4) | (recieve[i+2]&0x0F)); // write length
                        read = 0xff & ((recieve[i+3]<<4) | (recieve[i+4]&0x0F)); // read length
                        switch(format){
                            case 8:
                            {
                                _cs.write(enabled);
                                for(int j = 0; j < length; j += 2){
                                    _data = 0xff & ((recieve[i+5+j+0]<<4) | (recieve[i+5+j+1]&0x0F));
                                    ack = _spi.write(_data);
//                                    pc.printf("s%02X,",_data);
                                    send[j/2] = ack;
                                }
                                for(int j = length; j < (length+2*read); j+=2){
                                    ack = _spi.write(0xAA); //dummy data to write
//                                    pc.printf("a%02X,",ack);
                                    send[j/2] = ack;
                                }
                                _cs.write(disabled);
                                break;
                            }
                            case 16:
                            {
                                if((data%2) || (read%2)){ //invalid
                                    pc.printf("bad packet! %d, %d\n\r",data,read);
                                    i = plength + 1;
                                    length = 0;
                                }else{
                                    _cs.write(enabled);
                                    for(int j = 0; j < length; j += 4){
                                        _data = 0xffff & (((recieve[i+5+j+0] & 0x0F)<<12)|
                                                        ((recieve[i+5+j+1] & 0x0F)<<8 )|
                                                        ((recieve[i+5+j+2] & 0x0F)<<4 )|
                                                        ((recieve[i+5+j+3] & 0x0F)<<0 )
                                                        );
                                        ack = _spi.write(_data);
//                                        pc.printf("s%04X,",_data);
                                        send[(j/2)+0] = 0xFF & (ack>>8);
                                        send[(j/2)+1] = 0xFF & (ack>>0);
                                    }
                                    for(int j = length; j < (length+2*read); j += 4){
                                        ack = _spi.write(0xAAAA); //dummy data to write
//                                        pc.printf("a%04X,",ack);
                                        send[(j/2)+0] = 0xFF & (ack>>8);
                                        send[(j/2)+1] = 0xFF & (ack>>0);
                                    }
                                    _cs.write(disabled);
                                }
                                break;
                            }
                            default:
                            {
                                pc.printf("this shold not happen %d\n\r",format);
                                break;
                            }

                        }
//                        pc.printf("command E is for SPI transmission\n\r");
                        length = read + data;
                        i = (plength-1);
                    }
                    break;
                }
                case 'Z':
                {
                    s = false;
                    pc.printf("command Z is not implemented\n\r");
                    i=plength;
                    break;
                }
                case 'V':
                {
                    s = false;
                    pc.printf("command V is not implemented\n\r");
                    i=plength;
                    break;
                }
                default:
                {
                    s = false;
                    pc.printf("command %c is not implemented\n\r", recieve[i]);
                    i=plength;
                    break;
                }
            }
        }
        i=0;
        length=0;
    }
}