# Library for interfacing with a TSL2561 as used on the jeelabs lux plug
namespace eval jeelux {
package require piio
namespace path ::twowire
variable slaveaddr 0x29
variable regs {
control 0x80 timing 0x81 threshlow 0xA2 threshhigh 0xA4
interrupt 0x86 crc 0x88 id 0x8A data0 0xAC data1 0xAE
}
namespace ensemble create -subcommands {
luxplug close id channel lux
}
proc luxplug {bus {num 1}} {
variable slaveaddr
set fd [twowire $bus [expr {$slaveaddr + ($num << 4)}]]
# Power up the device
power $fd 1
return $fd
}
proc close {fd} {
# Power down the device
power $fd 0
chan close $fd
}
proc readreg {fd name} {
variable regs
set reg [dict get $regs $name]
if {$reg & 0x20} {
return [readregword $fd $reg]
} else {
return [readregbyte $fd $reg]
}
}
proc writereg {fd name val} {
variable regs
set reg [dict get $regs $name]
if {$reg & 0x20} {
writeregword $fd $reg $val
} else {
writeregbyte $fd $reg $val
}
}
# Control device power
proc power {fd state} {
writereg $fd control [expr {$state ? 3 : 0}]
}
# Get the individual light values
proc channel {fd chan} {
if {!$chan} {
return [readreg $fd data0]
} else {
return [readreg $fd data1]
}
}
# Product ID - is supposed to return 0x10, but comes out as 0x80
proc id {fd} {
return [readreg $fd id]
}
proc threshold {fd low high} {
writereg $fd threshlow $low
writereg $fd threshhigh $high
}
# T package
proc lux {fd} {
set scale [expr {1 << 14}]
set ch0 [expr {([channel $fd 0] * $scale) >> 10}]
# Prevent divide by zero situations
if {$ch0 == 0} {return 0}
set ch1 [expr {([channel $fd 1] * $scale) >> 10}]
set ratio1 [expr {($ch1 << 10) / $ch0}]
set ratio [expr {$ratio1 + 1 >> 1}]
if {$ratio < 0} {
set b 0; set m 0
} elseif {$ratio <= 0x0040} {
set b 0x01f2; set m 0x01be
} elseif {$ratio <= 0x0040} {
set b 0x0214; set m 0x02d1
} elseif {$ratio <= 0x00c0} {
set b 0x023f; set m 0x037b
} elseif {$ratio <= 0x0100} {
set b 0x0270; set m 0x03fe
} elseif {$ratio <= 0x0138} {
set b 0x016f; set m 0x01fc
} elseif {$ratio <= 0x019a} {
set b 0x00d2; set m 0x00fb
} elseif {$ratio <= 0x029a} {
set b 0x0018; set m 0x0012
} else {
set b 0; set m 0
}
set temp [expr {$ch0 * $b - $ch1 * $m}]
if {$temp < 0} {set temp 0}
return [expr {($temp + (1 << 13)) >> 14}]
}
}