# Library for interfacing with a DS1621 temperature sensor

namespace eval dallas {
    package require piio
    namespace path ::twowire

    variable slaveaddr 0x48
    variable regs {
	ReadTemp 0xaa AccessTH 0xa1 AccessTL 0xa2 AccessCfg 0xac
	ReadCnt 0xa8 ReadSlope 0xa9 StartConvT 0xee StopConvT 0x22
    }

    namespace ensemble create -subcommands {
	ds1621 convert temperature
    }

    # Connect with the device
    proc ds1621 {bus {num 0}} {
	variable slaveaddr
	return [twowire $bus [expr {$slaveaddr + $num}]]
    }

    # Start a temperature measurement
    proc convert {fd} {
	variable regs
	if {([readregbyte $fd [dict get $regs AccessCfg]] & 0x1) == 0} {
	    # Set to oneshot operation
	    writeregbyte $fd [dict get $regs AccessCfg] 1
	}
	writebyte $fd [dict get $regs StartConvT]
    }

    # Obtain the measurement results
    proc temperature {fd} {
	variable regs
	while {([readregbyte $fd [dict get $regs AccessCfg]] & 0x80) == 0} {
	    after 50
	}
	set data [readregword $fd [dict get $regs ReadTemp]]
	binary scan [binary format s $data] S result
	set rem [readregbyte $fd [dict get $regs ReadCnt]]
	set num [readregbyte $fd [dict get $regs ReadSlope]]
	return [format %.1f \
	  [expr {($result / 256) - 0.25 + double($num - $rem) / $num}]]
    }
}
