RBAPI(bool) i2c_InitSW2(unsigned devs, int i2c0mode, unsigned long i2c0clkdelay, int i2c1mode, unsigned long i2c1clkdelay) { int i; if (I2C_ioSection != -1) { err_SetMsg(ERROR_I2C_INUSE, "I2C lib was already opened"); return false; } if ((I2C_ioSection = io_Init()) == -1) return false; #ifdef ROBOIO switch (roboio_GetRBVer()) { case RB_100b1: case RB_100b2: case RB_100b3: case RB_100: case RB_100RD: case RB_110: case RB_050: devs = devs & I2C_USEMODULE0; break; default: devs = 0; break; } #endif I2C_swMode[0] = i2c0mode; I2CSW_delay[0] = i2c0clkdelay; I2C_swMode[1] = i2c1mode; I2CSW_delay[1] = i2c1clkdelay; I2C_action[0] = I2C_action[1] = I2CACT_DISABLE; for (i=0; i<2; i++) { if ((i == 0) && ((devs & I2C_USEMODULE0) == 0)) continue; if ((i == 1) && ((devs & I2C_USEMODULE1) == 0)) continue; I2C_action[i] = I2CACT_IDLE; // switch GPIO/I2C pins into GPIO pins OLD_I2CGPIO3FLAG[i] = read_sb_reg(SB_IPFCTRL3_REG) & OLD_I2CGPIO3MASK[i]; // backup GPIO/I2C switch flag write_sb_reg(SB_IPFCTRL3_REG, read_sb_reg(SB_IPFCTRL3_REG) & (~OLD_I2CGPIO3MASK[i])); OLD_I2CGPIO3DIR[i] = io_inpb(GPIO3_DIR) & (0x03 << (i*2+4)); // backup GPIO3 DIR OLD_I2CGPIO3VAL[i] = io_inpb(GPIO3_DATA) & (0x03 << (i*2+4)); // backup GPIO3 VAL // set GPIO pins as INPUT state (equiv. to OUT 1 of I2C lines) io_outpb(GPIO3_DIR, io_inpb(GPIO3_DIR) & ~(0x03 << (i*2+4))); } return true; }
RBAPI(void) com_DisableFIFO32(int com) { if ((com < 0) || (com > 3)) return; if (com == COM_PORT1) write_sb_regb(COM_ctrlREG[com], read_sb_regb(COM_ctrlREG[com]) & ~((unsigned char)1<<4)); else // COM2 ~ COM4 write_sb_reg(COM_ctrlREG[com], read_sb_reg(COM_ctrlREG[com]) & ~(1L<<21)); }
RBAPI(void) com_DisableTurboMode(int com) { if ((com < 0) || (com > 3) || (io_CpuID() != CPU_VORTEX86DX_3)) return; if (com == COM_PORT1) write_sb_regb(COM_ctrlREG[com], read_sb_regb(COM_ctrlREG[com]) & ~((unsigned char)1<<6)); else // COM2 ~ COM4 write_sb_reg(COM_ctrlREG[com], read_sb_reg(COM_ctrlREG[com]) & ~(1L<<22)); }
RBAPI(bool) spi_Init2(unsigned baseaddr, int clkmode) { int i; if(spi_InUse() == true) { err_SetMsg(ERROR_SPI_INUSE, "SPI was already opened"); return false; } if ((SPI_ioSection = io_Init()) == -1) return false; //NOTE: base address should be selected carefully to avoid conflicts with other devices! if (baseaddr != 0xffff) spi_SetBaseAddress(baseaddr); else { baseaddr = spi_SetDefaultBaseAddress(); if ((baseaddr == 0x0000) || (baseaddr == 0xffff)) spi_SetBaseAddress(0xfc00); } spidx_DisableCS(); spi_ClearErrors(); // enable FIFO and set clock divisor //if (spi_SetControlREG(0x10 + SPI_CLKMODE[clkmode]) == false) if (spi_SetControlREG(0x10 + get_spidivisor(clkmode)) == false) { spi_Close(); err_SetMsg(ERROR_SPI_INITFAIL, "fail to write SPI Control Register"); return false; } // clear the input buffer if it is not empty for (i=0; i<20; i++) { if (spi_InputReady() == false) break; if (spidx_Read() == 0xffff) { spi_Close(); err_SetMsg(ERROR_SPI_INITFAIL, "fail to clear SPI input buffer"); return false; } } // switch GPIO3[3:0] to external SPI interface OLD_SPIGPIO3FLAG = read_sb_reg(SB_MULTIFUNC_REG); write_sb_reg(SB_MULTIFUNC_REG, OLD_SPIGPIO3FLAG | 1L); OLD_SPIGPIO3FLAG = OLD_SPIGPIO3FLAG & 1L; return true; }
RBAPI(bool) com_IsFIFO32Mode(int com) { if ((com < 0) || (com > 3)) return false; if (com == COM_PORT1) { if ((read_sb_regb(COM_ctrlREG[com]) & ((unsigned char)1<<4)) == 0) return false; } else { if ((read_sb_reg(COM_ctrlREG[com]) & (1L<<21)) == 0L) return false; } return true; }
RBAPI(bool) com_IsTurboMode(int com) { if ((com < 0) || (com > 3) || (io_CpuID() != CPU_VORTEX86DX_3)) return false; if (com == COM_PORT1) { if ((read_sb_regb(COM_ctrlREG[com]) & ((unsigned char)1<<6)) == 0) return false; } else { if ((read_sb_reg(COM_ctrlREG[com]) & (1L<<22)) == 0L) return false; } return true; }
RBAPI(void) spi_Close(void) { if (SPISW_active == true) return; if (SPI_ioSection == -1) return; spidx_DisableCS(); spi_ClearErrors(); // restore GPIO3[3:0]/external SPI switch setting if (OLD_SPIGPIO3FLAG != 0xffffffffL) write_sb_reg(SB_MULTIFUNC_REG, (read_sb_reg(SB_MULTIFUNC_REG) & 0xfffffffeL) + OLD_SPIGPIO3FLAG); io_Close(SPI_ioSection); SPI_ioSection = -1; OLD_SPIGPIO3FLAG = 0xffffffffL; }
RBAPI(void) spi_CloseSW(void) { if (spi_InUse() == false) return; if (SPISW_active == false) return; if (OLD_SPIGPIO3FLAG != 0xffffffffL) write_sb_reg(SB_MULTIFUNC_REG, (read_sb_reg(SB_MULTIFUNC_REG) & 0xfffffffeL) + OLD_SPIGPIO3FLAG); // restore GPIO3[3:0] io_outpb(GPIO3_DIR, (io_inpb(GPIO3_DIR) & 0xf0) + OLD_SPIGPIODIR); io_outpb(GPIO3_DATA, (io_inpb(GPIO3_DATA) & 0xf0) + OLD_SPIGPIODATA); io_Close(SPI_ioSection); SPI_ioSection = -1; OLD_SPIGPIO3FLAG = 0xffffffffL; SPISW_active = false; }
RBAPI(void) i2c_Close(void) { int i; if (I2C_ioSection == -1) return; for (i=0; i<2; i++) //restore GPIO3/I2C switch setting { if (I2C_action[i] == I2CACT_DISABLE) continue; io_outpb(GPIO3_DIR, (io_inpb(GPIO3_DIR) & (~(0x03 << (i*2+4)))) | OLD_I2CGPIO3DIR[i]); //restore GPIO3 DIR io_outpb(GPIO3_DATA, (io_inpb(GPIO3_DATA) & (~(0x03 << (i*2+4)))) | OLD_I2CGPIO3VAL[i]); //restore GPIO3 VAL write_sb_reg(SB_IPFCTRL3_REG, (read_sb_reg(SB_IPFCTRL3_REG) & (~OLD_I2CGPIO3MASK[i])) | OLD_I2CGPIO3FLAG[i]); //restore GPIO/I2C switch flag I2C_action[i] = I2CACT_DISABLE; } io_Close(I2C_ioSection); I2C_ioSection = -1; }
RBAPI(bool) spi_InitSW(int mode, unsigned long clkdelay) { if(spi_InUse() == true) { err_SetMsg(ERROR_SPI_INUSE, "SPI was already opened"); return false; } if ((SPI_ioSection = io_Init()) == -1) return false; SPISW_mode = mode; SPISW_delay = clkdelay; // set the initial state of SPI GPIO pins OLD_SPIGPIODIR = io_inpb(GPIO3_DIR); OLD_SPIGPIODATA = io_inpb(GPIO3_DATA); io_outpb(GPIO3_DIR, (OLD_SPIGPIODIR & 0xf0) | 0x07); if ((SPISW_mode & SPIMODE_CPOL1) != 0) io_outpb(GPIO3_DATA, (OLD_SPIGPIODATA & 0xf0) + 0x03); // SPI_CLK = 1, SPI_CS = 1 else io_outpb(GPIO3_DATA, (OLD_SPIGPIODATA & 0xf0) + 0x01); // SPI_CLK = 0, SPI_CS = 1 OLD_SPIGPIODIR = OLD_SPIGPIODIR & 0x0f; OLD_SPIGPIODATA = OLD_SPIGPIODATA & 0x0f; // switch to GPIO interface OLD_SPIGPIO3FLAG = read_sb_reg(SB_MULTIFUNC_REG); write_sb_reg(SB_MULTIFUNC_REG, OLD_SPIGPIO3FLAG & 0xfffffffeL); OLD_SPIGPIO3FLAG = OLD_SPIGPIO3FLAG & 1L; SPISW_active = true; return true; }
RBAPI(bool) i2c_Init2(unsigned baseaddr, unsigned devs, int i2c0irq, int i2c1irq) { int i; if (I2C_ioSection != -1) { err_SetMsg(ERROR_I2C_INUSE, "I2C lib was already opened"); return false; } if ((I2C_ioSection = io_Init()) == -1) return false; //NOTE: base address should be selected carefully to avoid conflicts with other devices! if (baseaddr != 0xffff) i2c_SetBaseAddress(baseaddr); else { if (i2c_SetDefaultBaseAddress() == 0x0000) i2c_SetBaseAddress(0xfb00); } #ifdef ROBOIO switch (roboio_GetRBVer()) { case RB_100b1: case RB_100b2: case RB_100b3: case RB_100: case RB_100RD: case RB_110: case RB_050: devs = devs & I2C_USEMODULE0; i2c1irq = I2CIRQ_DISABLE; break; default: devs = 0; i2c0irq = i2c1irq = I2CIRQ_DISABLE; break; } #endif i2c_SetIRQ(i2c0irq, i2c1irq); I2C_swMode[0] = I2C_swMode[1] = I2CSW_DISABLE; I2C_action[0] = I2C_action[1] = I2CACT_DISABLE; for (i=0; i<2; i++) { if ((i == 0) && ((devs & I2C_USEMODULE0) == 0)) continue; if ((i == 1) && ((devs & I2C_USEMODULE1) == 0)) continue; I2C_action[i] = I2CACT_IDLE; //switch GPIO/I2C pins into GPIO pins OLD_I2CGPIO3FLAG[i] = read_sb_reg(SB_IPFCTRL3_REG) & OLD_I2CGPIO3MASK[i]; //backup GPIO/I2C switch flag write_sb_reg(SB_IPFCTRL3_REG, read_sb_reg(SB_IPFCTRL3_REG) & (~OLD_I2CGPIO3MASK[i])); //send START & STOP signal to reset I2C devices OLD_I2CGPIO3DIR[i] = io_inpb(GPIO3_DIR) & (0x03 << (i*2+4)); //backup GPIO3 DIR OLD_I2CGPIO3VAL[i] = io_inpb(GPIO3_DATA) & (0x03 << (i*2+4)); //backup GPIO3 VAL //set_pins(i, 1, 1); delay_ms(1); //SCL = 1, SDA = 1; START //set_pins(i, 1, 0); delay_ms(1); //SCL = 1, SDA = 0 //set_pins(i, 0, 0); delay_ms(1); //SCL = 0, SDA = 0 //Note: if we send the above START, some I2C sensors, such as ADI ADXL345, may fail to respond //set_pins(i, 0, 0); delay_ms(1); //SCL = 0, SDA = 0; STOP //Note: if we perform the line above, some I2C sensors, such as MEMSIC MXC6202, may fail to respond //set_pins(i, 1, 0); delay_ms(1); //SCL = 1, SDA = 0 //set_pins(i, 1, 1); delay_ms(1); //SCL = 1, SDA = 1 //Note: the above lines work for all sensors we tested, but we disable them to avoid unexpected sensor behaviors if (i2c_Reset(i) == false) // assume the status of GPIO/I2C pins are GPIO "IN" or "OUT 1" { i2c_Close(); err_SetMsg(ERROR_I2C_INITFAIL, "can't reset the I2C modules"); return false; } i2c_DisableINT(i, I2CINT_ALL); i2c_ClearSTAT(i, I2CSTAT_ALL); //Remarks: for DX ver.2, we must disable the noise filter to ensure that 3.3Mbps works in high-speed mode i2c_DisableNoiseFilter(i); //i2c_EnableNoiseFilter(i); i2c_DisableStandardHSM(i); //SCL open-drain in high-speed mode //i2c_EnableStandardHSM(i); i2c_SetSpeed(i, I2CMODE_AUTO, 100000L); //default 100Kbps i2cslave_SetAddr(i, 0x7f); //set slave address 0x7F by default (change this if it collide with external I2C devices) i2cslave_EnableACK(i); //switch GPIO pins into I2C SCL,SDA pins //Remarks: Vortex86DX's H/W I2C has an issue here; if you call i2c_Reset() in case GPIO/SCL pin = GPIO out 0, // then, whenever you switch GPIO/SCL pin to SCL pin, the SCL pin always first send the 10 reset dummy clocks write_sb_reg(SB_IPFCTRL3_REG, read_sb_reg(SB_IPFCTRL3_REG) | OLD_I2CGPIO3MASK[i]); } return true; }
_RB_INLINE unsigned short uart_getbaseaddr(int com) { return (unsigned short)(read_sb_reg(COM_addrREG[com]) & 0xfff8L); }
/**************************** Internal Functions ****************************/ _RB_INLINE bool uart_isenabled(int com) { if (com == COM_PORT1) return ((read_sb_regb(COM_ctrlREG[com]) & 0x80) == 0)? false : true; else return ((read_sb_reg(COM_ctrlREG[com]) & (0x01L << 23)) == 0L)? false : true; }
RBAPI(bool) i2c_Initialize2(unsigned devs, int i2c0irq, int i2c1irq) { int i; if (I2C_ioSection != -1) { err_SetMsg(ERROR_I2C_INUSE, "I2C lib was already opened"); return false; } if ((I2C_ioSection = io_Init()) == -1) return false; if (i2c_SetDefaultBaseAddress() == 0x0000) i2c_SetBaseAddress(0xfb00); i2c_SetIRQ(i2c0irq, i2c1irq); I2C_action[0] = I2C_action[1] = I2CACT_DISABLE; for (i=0; i<2; i++) { if ((i == 0) && ((devs & I2C_USEMODULE0) == 0)) continue; if ((i == 1) && ((devs & I2C_USEMODULE1) == 0)) continue; I2C_action[i] = I2CACT_IDLE; //switch GPIO/I2C pins into GPIO pins OLD_I2CGPIO3FLAG[i] = read_sb_reg(SB_IPFCTRL3_REG) & OLD_I2CGPIO3MASK[i]; //backup GPIO/I2C switch flag write_sb_reg(SB_IPFCTRL3_REG, read_sb_reg(SB_IPFCTRL3_REG) & (~OLD_I2CGPIO3MASK[i])); //send START & STOP signal to reset I2C devices OLD_I2CGPIO3DIR[i] = io_inpb(0x9b) & (0x03 << (i*2+4)); //backup GPIO3 DIR OLD_I2CGPIO3VAL[i] = io_inpb(0x7b) & (0x03 << (i*2+4)); //backup GPIO3 VAL //set_pins(i, 1, 1); delay_ms(1); //SCL = 1, SDA = 1; START //set_pins(i, 1, 0); delay_ms(1); //SCL = 1, SDA = 0 //set_pins(i, 0, 0); delay_ms(1); //SCL = 0, SDA = 0 //Note: if we send the above START, some I2C sensors, such as ADI ADXL345, may fail to respond //set_pins(i, 0, 0); delay_ms(1); //SCL = 0, SDA = 0; STOP //Note: if we perform the line above, some I2C sensors, such as MEMSIC MXC6202, may fail to respond set_pins(i, 1, 0); delay_ms(1); //SCL = 1, SDA = 0 set_pins(i, 1, 1); delay_ms(1); //SCL = 1, SDA = 1 if (i2c_Reset(i) == false) { i2c_Close(); err_SetMsg(ERROR_I2C_INITFAIL, "can't reset the I2C modules"); return false; } i2c_DisableINT(i, I2CINT_ALL); i2c_ClearSTAT(i, I2CSTAT_ALL); //Remarks: for DX ver.2, we must disable the noise filter to ensure that 3.3Mbps works in high-speed mode i2c_DisableNoiseFilter(i); //i2c_EnableNoiseFilter(i); i2c_DisableStandardHSM(i); //SCL open-drain in high-speed mode //i2c_EnableStandardHSM(i); i2c_SetSpeed(i, I2CMODE_AUTO, 100000L); //default 100Kbps i2cslave_SetAddr(i, 0x7f); //set slave address 0x7F by default (change this if it collide with external I2C devices) i2cslave_EnableACK(i); //switch GPIO pins into I2C SCL,SDA pins //Remarks: Vortex86DX's H/W I2C has an issue here; if you call i2c_Reset() in case GPIO/SCL pin = GPIO out 0, // then, whenever you switch GPIO/SCL pin to SCL pin, the SCL pin always first send the 10 reset dummy clocks write_sb_reg(SB_IPFCTRL3_REG, read_sb_reg(SB_IPFCTRL3_REG) | OLD_I2CGPIO3MASK[i]); } return true; }