UART to I2C master(s) converter, targetting to emulate SC18IM700(NXP) chip
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
- https://developer.mbed.org/platforms/Switch-Science-mbed-LPC824/
- https://developer.mbed.org/platforms/LPCXpresso824-MAX/
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-30
- Revision:
- 42:da85c17ea495
- Parent:
- 41:b7c84115a2dd
- Child:
- 76:fcbc456010e0
File content as of revision 42:da85c17ea495:
/** 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; } }