Am 17.11.2015 um 11:45 schrieb Matthias Urlichs:
> On 17.11.2015 06:39, Nigel Titley wrote:
>> iButtonlink have confirmed that the Link45/LinkUSB doesn't crawl the OW 
>> bus but expects the higher level code to do this.
> 
> The question is whether it supports the "match ROM + command+data +
> search ROM" sequence used to selectively enumerate the buses behind a
> DS2409, as required when you use one of the Smart-On commands.
> 
> Doing this in higher-level code, i.e. by permanently turning on the main
> or aux buses, is not trivial. You'd need (external) locking, and be very
> careful about which bus segment you associate newly-discovered devices to.
> 
> On the other hand, all things considered I'd expect things to be faster
> with a permanent bus connection, since I'd only have to send a bus reset
> once per command (plus maybe one to select the correct bus), not per
> traversed segment. Similarly for conditional search, which is going to
> be a win for multiple DS2409s on a bus (like in a hub).
> 
I have an application where I simply use the DS2409 as a "link locator"
type of device.

             V                V
             |Main            |Main
             |    Aux         |    Aux
Host ---- DS2409 --------- DS2409 ------


I use my special patch to have the bus connected through all Aux lines
permanently. Don't use the OWFS branches at all, don't touch them.

I do a conditional search on the whole bus each 500ms. That isn't a
costly operation, as usually there is not a single chip responding to
it. When an iButton is connected to the "Main" stub of a DS2409, it
discharges the stub a bit during its own power-up, causing the edge
detector to trigger and the DS2409 in question to report on the
conditional search.

Then, I use another tweak in the patch to read the iButton ID on the
main branch of that DS2409 through the "Read ROM" command. That way I
can both locate the iButton at a single lock and minimize the number of
costly "Search ROM" operations needed.

(Why Main and Aux are reversed? Because the main channel edge detector
responds to conditional search, the Aux does not. Duh!)




> 
> NB: while we're looking at the DS2409 code ... OWCH:
> 
> /* 2409 switch -- branch status  -- note that bit value is reversed */
> static ZERO_OR_ERROR FS_r_branch(struct one_wire_query *owq)
> {
>     BYTE data = 0 ;
> 
>     OWQ_U(owq) = (((data) & 0x01) | ((data >> 1) & 0x02)) ^ 0x03;
>     return GB_to_Z_OR_E(OW_r_control(&data, PN(owq))) ;
> }
> 
> Wouldn't it make slightly more sense to *first* read data and *then* set
> the return value? :-P
> 
Wait, wait. What do you object here exactly?



> Since this code demonstrably cannot have worked since 2010 (Paul did a
> "minor cleanup" that broke it, cf. git change fc0c93a31) and nobody
> noticed, I propose to replace the currently-useless "branch" two-bit
> array with a single value (0: no bus selected, 1:main, 2:aux) 
>
Errm. That's exactly the same as a "two-bit-array" with valid values 00,
01, 10.


> that can
> be read and written to, in case one wants to (or has to) manually switch
> branches in external code.
> 
> Any objections? Otherwise I'll prepare a patch.
> 
The reason I have used "mainselect" and "auxselect" in my patch was it
is a write-only value anyway and I did not want to introduce arbitrary
numerical values to have a meaning.


Kind regards

        Jan


--- owfs-3.1p0.orig/module/owlib/src/c/ow_2409.c	2015-03-15 02:27:40.000000000 +0100
+++ owfs-3.1p0/module/owlib/src/c/ow_2409.c	2015-09-16 21:19:47.977652966 +0200
@@ -41,11 +41,20 @@
 #include "owfs_config.h"
 #include "ow_2409.h"
 
+#define _1W_STATUS_READ_WRITE  0x5A
+#define _1W_ALL_LINES_OFF      0x66
+#define _1W_DISCHARGE_LINES    0x99
+#define _1W_DIRECT_ON_MAIN     0xA5
+#define _1W_SMART_ON_MAIN      0xCC
+#define _1W_SMART_ON_AUX       0x33
+
 /* ------- Prototypes ----------- */
 
 /* DS2409 switch */
 WRITE_FUNCTION(FS_discharge);
 WRITE_FUNCTION(FS_clearevent);
+WRITE_FUNCTION(FS_select);
+READ_FUNCTION(FS_readlock);
 READ_FUNCTION(FS_r_control);
 WRITE_FUNCTION(FS_w_control);
 READ_FUNCTION(FS_r_sensed);
@@ -59,6 +68,10 @@
 	F_STANDARD,
 	{"discharge", PROPERTY_LENGTH_YESNO, NON_AGGREGATE, ft_yesno, fc_stable, NO_READ_FUNCTION, FS_discharge, VISIBLE, NO_FILETYPE_DATA, },
 	{"clearevent", PROPERTY_LENGTH_YESNO, NON_AGGREGATE, ft_yesno, fc_stable, NO_READ_FUNCTION, FS_clearevent, VISIBLE, NO_FILETYPE_DATA, },
+	{"auxselect", PROPERTY_LENGTH_YESNO, NON_AGGREGATE, ft_yesno, fc_stable, NO_READ_FUNCTION, FS_select, VISIBLE, {.i=_1W_SMART_ON_AUX}, },
+	{"mainselect", PROPERTY_LENGTH_YESNO, NON_AGGREGATE, ft_yesno, fc_stable, NO_READ_FUNCTION, FS_select, VISIBLE, {.i=_1W_SMART_ON_MAIN}, },
+	{"auxlock", 18, NON_AGGREGATE, ft_ascii, fc_volatile, FS_readlock, NO_WRITE_FUNCTION, VISIBLE, {.i=_1W_SMART_ON_AUX}, },
+	{"mainlock", 18, NON_AGGREGATE, ft_ascii, fc_volatile, FS_readlock, NO_WRITE_FUNCTION, VISIBLE, {.i=_1W_SMART_ON_MAIN}, },
 	{"control", PROPERTY_LENGTH_UNSIGNED, NON_AGGREGATE, ft_unsigned, fc_stable, FS_r_control, FS_w_control, VISIBLE, NO_FILETYPE_DATA, },
 	{"sensed", PROPERTY_LENGTH_BITFIELD, &A2409, ft_bitfield, fc_volatile, FS_r_sensed, NO_WRITE_FUNCTION, VISIBLE, NO_FILETYPE_DATA, },
 	{"branch", PROPERTY_LENGTH_BITFIELD, &A2409, ft_bitfield, fc_volatile, FS_r_branch, NO_WRITE_FUNCTION, VISIBLE, NO_FILETYPE_DATA, },
@@ -77,13 +90,8 @@
 static GOOD_OR_BAD OW_discharge(const struct parsedname *pn);
 static GOOD_OR_BAD OW_clearevent(const struct parsedname *pn);
 static GOOD_OR_BAD OW_w_control(const UINT data, const struct parsedname *pn);
-
-#define _1W_STATUS_READ_WRITE  0x5A
-#define _1W_ALL_LINES_OFF      0x66
-#define _1W_DISCHARGE_LINES    0x99
-#define _1W_DIRECT_ON_MAIN     0xA5
-#define _1W_SMART_ON_MAIN      0xCC
-#define _1W_SMART_ON_AUX       0x33
+static GOOD_OR_BAD OW_select(const struct parsedname *pn);
+static ZERO_OR_ERROR OW_readlock(struct one_wire_query *owq);
 
 /* discharge 2409 lines */
 static ZERO_OR_ERROR FS_discharge(struct one_wire_query *owq)
@@ -113,6 +121,21 @@
 	return 0;
 }
 
+/* Explicity select one path. */
+static ZERO_OR_ERROR FS_select(struct one_wire_query *owq)
+{
+	if ((OWQ_Y(owq)!=0) && BAD( OW_select(PN(owq)) ) ) {
+		return -EINVAL;
+	}
+	return 0;
+}
+
+/* Read ROM (0x0f command code) on a path. */
+static ZERO_OR_ERROR FS_readlock(struct one_wire_query *owq)
+{
+	return OW_readlock(owq);
+}
+
 /* 2409 switch -- branch pin voltage */
 static ZERO_OR_ERROR FS_r_sensed(struct one_wire_query *owq)
 {
@@ -209,6 +232,65 @@
 	 return BUS_transaction(t, pn) ;
 }
 
+static GOOD_OR_BAD OW_select(const struct parsedname *pn)
+{
+	BYTE sel[] = { 0x00, 0xff, };
+	BYTE info[2];
+ 	struct transaction_log t[] = {
+		TRXN_START,
+		TRXN_WRITE2(sel),
+		TRXN_READ2(info),
+		TRXN_END,
+	};
+
+	// Select path by node given.
+	sel[0] = pn->selected_filetype->data.i;
+
+	// Could certainly couple this with next transaction
+	RETURN_BAD_IF_BAD(BUS_transaction(t, pn)) ;
+
+	/* Check that Info corresponds */
+	return info[1] == sel[0] ? gbGOOD : gbBAD;
+}
+
+static ZERO_OR_ERROR OW_readlock(struct one_wire_query *owq)
+{
+	struct parsedname *pn = PN(owq);
+	struct parsedname pn_directory;
+	ASCII ad[30] = { 0x00, };
+	BYTE resp[SERIAL_NUMBER_SIZE];
+	BYTE match[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, };
+	BYTE collisions[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, };
+	BYTE sel[] = { 0x00, 0xff, };
+	BYTE info[] = { 0x00, 0xff, };
+	BYTE read_ROM[] = {	_1W_OLD_READ_ROM, };
+
+	struct transaction_log t[] = {
+		TRXN_START,
+		TRXN_WRITE2(sel),
+		TRXN_READ2(info),
+		TRXN_WRITE1(read_ROM),
+		TRXN_READ(resp, SERIAL_NUMBER_SIZE),
+		TRXN_END,
+	};
+	
+	// Select path by node given.
+	sel[0] = pn->selected_filetype->data.i;
+
+	// Do the transaction.
+	RETURN_BAD_IF_BAD(BUS_transaction(t, pn)) ;
+
+	LEVEL_DEBUG("dat=" SNformat " crc8=%02x", SNvar(resp), CRC8(resp, 7));
+	if ((memcmp(resp, collisions, SERIAL_NUMBER_SIZE) != 0) && (memcmp(resp, match, SERIAL_NUMBER_SIZE) != 0) && (CRC8(resp, SERIAL_NUMBER_SIZE) == 0)) {
+		/* non-empty, and no CRC error, return device id. */
+		FS_devicename(ad, sizeof(ad), resp, pn);
+	} else {
+		/* No key in the lock, or more than one. */
+		ad[0]='\0' ;
+	}
+	return OWQ_format_output_offset_and_size_z(ad, owq);
+}
+
 static GOOD_OR_BAD OW_w_control(const UINT data, const struct parsedname *pn)
 {
 	const BYTE d[] = { 0x20, 0xA0, 0x00, 0x40, };
------------------------------------------------------------------------------
_______________________________________________
Owfs-developers mailing list
Owfs-developers@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/owfs-developers

Reply via email to