The following example shows scripting FTDI MPSSE usage to interface OPT3001 lighting sensor on I2C bus. As usual, paste the script into console, compile, and run, providing you have proper HW config ready, and have proper OPT3001 I2C address in script code.
/// FTxxxx MPSSE script test.
/// Interfacing the I2C with OPT3001 on it.
///
// Enumerate available MPSSE devices
var devInfos = EsFtdiDriver::enumerate(
true, //< Include busy devices
true //< Include only MPSSE-capable devices
);
if( !devInfos#countGet() )
throw "Could not find any MPSSE-capable devices";
// Take the first found device and open it
var dev = EsFtdiDriver::deviceCreate(
EsFtdiDeviceKind$$MPSSE_I2C,
devInfos[0]
);
if( !dev )
throw EsStr::format(
"Could not create MPSSE device of type %s for %s",
EsFtdiDeviceKind$$MPSSE_I2C$$label,
devInfos[0]
);
if( !dev.open() )
throw EsStr::format(
"Could not open MPSSE device %s",
devInfos[0]
);
// Set OS systicks period to 1 ms
var systick = EsUtilities::systickChange(
1
);
const c_opt3001_addr = 0x44;
function opt3001rawToVal(raw)
{
return ((raw & 0x0FFF) * (1 << (raw >> 12)) ) / 100.;
}
/*
function opt3001valToRaw(val)
{
val *= 100.;
return ((raw & 0x0FFF) * (1 << (raw >> 12)) ) / 100.;
}*/
function opt3001registerRead(bus, addr, reg)
var buff;
{
bus.write(
addr,
reg#asByte(),
EsFtdiMpsseI2cIO$$START_BIT
);
buff = bus.read(
addr,
2,
EsFtdiMpsseI2cIO$$START_BIT|
EsFtdiMpsseI2cIO$$STOP_BIT|
EsFtdiMpsseI2cIO$$NACK_LAST_BYTE
);
if( 2 == buff#countGet() )
return buff[1] + (buff[0] << 8);
}
function opt3001registerWrite(bus, addr, reg, data)
var buff = B"\0\0\0";
{
buff[0] = reg;
buff[1] = (data >> 8) & 0xFF;
buff[2] = (data & 0xFF);
return 3 == bus.write(
addr,
buff,
EsFtdiMpsseI2cIO$$START_BIT|
EsFtdiMpsseI2cIO$$STOP_BIT|
EsFtdiMpsseI2cIO$$BREAK_ON_NACK
);
}
// ID would contain [MFG ID, DEV ID] on successful read
function opt3001idRead(bus, addr)
var id = [];
{
id += opt3001registerRead(bus, addr, 0x7E);
id += opt3001registerRead(bus, addr, 0x7F);
return id;
}
function opt3001limitLowRead(bus, addr)
{
return opt3001rawToVal(
opt3001registerRead(
bus,
addr,
0x02
)
);
}
function opt3001limitHighRead(bus, addr)
{
return opt3001rawToVal(
opt3001registerRead(
bus,
addr,
0x03
)
);
}
function opt3001configRead(bus, addr)
var raw, cfg = []; //< range, conv time, conv mode, overflow, conv ready, result higher, result lower, INT latch mode, INT polarity mode, mask exp in result, fault count till INT
{
raw = opt3001registerRead(bus, addr, 0x01);
cfg += (raw >> 12) & 0x0F; //< Range
cfg += (raw & 0x0800) ? //< Conversion time
800 :
100;
cfg += ((raw >> 9) & 0x03); //< Conv mode
cfg += (raw >> 8) & 0x01; //< Overflow
cfg += (raw >> 7) & 0x01; //< Conversion ready
cfg += (raw >> 6) & 0x01; //< Result is higher
cfg += (raw >> 5) & 0x01; //< Result is lower
cfg += (raw >> 4) & 0x01; //< INT latch mode
cfg += (raw >> 3) & 0x01; //< INT Polarity
cfg += (raw >> 2) & 0x01; //< Mask exponent in result
cfg += raw & 0x03; //< Fault count till INT
return cfg;
}
function opt3001configWrite(bus, addr, range, convTime, convMode, latchMode, polMode, expMask, faultCnt )
var raw; //< conv mode, overflow, conv ready, result higher, result lower, INT latch mode, INT polarity mode, mask exp in result, fault count till INT
{
raw = (range & 0x0F) << 12;
if( 800 == convTime )
raw |= 0x0800;
raw += (convMode & 0x03) << 9;
raw += (latchMode & 0x01) << 4;
raw += (polMode & 0x01) << 3;
raw += (expMask & 0x01) << 2;
raw += (faultCnt & 0x03);
return opt3001registerWrite(
bus,
addr,
0x01,
raw
);
}
function opt3001resultRead(bus, addr)
{
return opt3001rawToVal(
opt3001registerRead(
bus,
addr,
0
)
);
}
dev$clockRate = EsFtdiMpsseI2cClock$$FAST;
dev.configApply();
// Lookup devices on I1C bus
var addr, addrs = [], tmp, str, tmo;
for(addr = 0; addr < 128; ++addr)
{
// Ping devices for read
if(
dev.ping(
addr,
false
)
)
addrs += addr;
}
if( addrs#countGet() )
{
EsScriptDebug::log(
"Found I2C devices on bus: %s",
addrs
);
if( c_opt3001_addr in addrs )
{
EsScriptDebug::log(
"OPT3001 found."
);
tmp = opt3001idRead(dev, c_opt3001_addr);
EsScriptDebug::log(
"OPT3001 IDs: [MFG: 0x%04X DEV: 0x%04X]",
tmp[0],
tmp[1]
);
tmp = opt3001configRead(dev, c_opt3001_addr);
str = "OPT3001 config:\nrange=" + tmp[0]#asString() +
"\nconv time=" + tmp[1]#asString() +
"\nconv mode=" + (( 0 == tmp[2] ) ? "Shutdown" : (( 1 == tmp[2] ) ? "Single-shot" : "Continuous")) +
"\noverflow=" + tmp[3]#asString() +
"\nconv ready=" + tmp[4]#asString() +
"\nresult higher=" + tmp[5]#asString() +
"\nresult lower=" + tmp[6]#asString() +
"\nINT latch mode=" + (tmp[7] ? "Window" : "Hysteresis") +
"\nINT polarity mode=" + (tmp[8] ? "Active High" : "Active Low") +
"\nmask EXP in result=" + tmp[9]#asString() +
"\nfault count till INT=" + (1 << tmp[10]);
EsScriptDebug::log(
"%s\nStarting one-shot conversions...",
str
);
tmo = 100;
while( 1 )
{
if(
!opt3001configWrite(
dev,
c_opt3001_addr,
0x0C,
tmo,
1,
0, //< Hyst. mode
1, //< Active high
0, //< Do not mask EXP
3 //< Fault count = 8
)
)
{
EsScriptDebug::log("Could not start conversion");
break;
}
EsThreadWorker::sleep(tmo+200);
tmp = opt3001configRead(dev, c_opt3001_addr);
str = EsStr::format(
"Result: RNG:%d, EXP:%dms, MOD:%d, OVF:%d, READY:%d, LUX:%0.2f",
tmp[0],
tmp[1],
tmp[2],
tmp[3],
tmp[4],
opt3001resultRead(dev, c_opt3001_addr)
);
EsScriptDebug::log(str);
}
}
}
else
EsScriptDebug::log(
"I2C devices not found"
);
dev.close();
// Restore OS systicks
EsUtilities::systickRestore( systick );