Discussion:
[Owfs-developers] Hiding incompatible device variants
Alastair D'Silva
2017-02-10 21:04:21 UTC
Permalink
Hi folks,

I've written a 1Wire slave implementation for ARM (which I will be open
sourcing), in order to implement some functionality that does not exist in
the 1Wire world (multichannel RGBW control).

Given the small amount of address space available in the family, I figured
the best course of action for further implementations would be to keep the
family code, and add a command to allow the master to query the device
specifics.

The problem I am now facing is how to cache the information, and despatch
calls to the appropriate driver (of which there is only 1 at the moment)
once a device appears on the bus.

I was thinking of adding an opaque, device instance specific struct pointer
somewhere under the parsedname struct, as well as init and term function
pointers in the device struct. The init call could then query the device
subtype, and stash it away in the device instance specific struct, and
potentially alter the visibility of the files so that only the relevant
content is visible to the user.

Could you please advise whether I am on the right track, or if there is a
better solution?

Cheers,
--
Alastair D'Silva mob: 0423 762 819
skype: alastair_dsilva msn: ***@d-silva.org
blog: http://alastair.d-silva.org Twitter: @EvilDeece
Jan Kandziora
2017-02-11 00:07:40 UTC
Permalink
Post by Alastair D'Silva
Hi folks,
I've written a 1Wire slave implementation for ARM (which I will be open
sourcing), in order to implement some functionality that does not exist in
the 1Wire world (multichannel RGBW control).
Given the small amount of address space available in the family, I figured
the best course of action for further implementations would be to keep the
family code, and add a command to allow the master to query the device
specifics.
What is your device emulating? A DS2408? There is some code inside OWFS'
DS2408 codebase which handles the various HD44780 displays connected to
the DS2408. It's ugly, it's error-prone and it's hard to debug.

Please don't require us to put even more quirks into the existing driver
sources.

If you make your own device, please give it its own family code and
create your own driver source file in the owlib tree. We are going to
face at most twenty fundamentally different designs of homebrewn devices
and there's plenty of unused address space for that.

Kind regards

Jan
Colin Reese
2017-02-11 00:13:58 UTC
Permalink
I want so badly an avr owfs slave. There are no available ADCs, and the
DIO are expensive and a pain to use.

I never got MOAT to work. I would use ARM if it worked out of the box.

Colin
Post by Jan Kandziora
Post by Alastair D'Silva
Hi folks,
I've written a 1Wire slave implementation for ARM (which I will be open
sourcing), in order to implement some functionality that does not exist in
the 1Wire world (multichannel RGBW control).
Given the small amount of address space available in the family, I figured
the best course of action for further implementations would be to keep the
family code, and add a command to allow the master to query the device
specifics.
What is your device emulating? A DS2408? There is some code inside OWFS'
DS2408 codebase which handles the various HD44780 displays connected to
the DS2408. It's ugly, it's error-prone and it's hard to debug.
Please don't require us to put even more quirks into the existing driver
sources.
If you make your own device, please give it its own family code and
create your own driver source file in the owlib tree. We are going to
face at most twenty fundamentally different designs of homebrewn devices
and there's plenty of unused address space for that.
Kind regards
Jan
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
_______________________________________________
Owfs-developers mailing list
https://lists.sourceforge.net/lists/listinfo/owfs-developers
Matthias Urlichs
2017-02-11 08:25:30 UTC
Permalink
Post by Colin Reese
I never got MOAT to work.
I should be able to help with that.

MoaT is on my back burner right now because I need to finish whipping
KNX into releaseable shape, but I do have a couple of working setups.
--
-- Matthias Urlichs
Alastair D'Silva
2017-02-11 05:16:34 UTC
Permalink
-----Original Message-----
Sent: Saturday, 11 February 2017 11:08 AM
To: OWFS (One-wire file system) discussion and help <owfs-
Subject: Re: [Owfs-developers] Hiding incompatible device variants
Post by Alastair D'Silva
Hi folks,
I've written a 1Wire slave implementation for ARM (which I will be
open sourcing), in order to implement some functionality that does not
exist in the 1Wire world (multichannel RGBW control).
Given the small amount of address space available in the family, I
figured the best course of action for further implementations would be
to keep the family code, and add a command to allow the master to
query the device specifics.
What is your device emulating? A DS2408? There is some code inside OWFS'
I do have a working DS2408 emulation, but that was more to test that I have
the low level protocol correct. This is a new device, with new commands.
DS2408 codebase which handles the various HD44780 displays connected to
the DS2408. It's ugly, it's error-prone and it's hard to debug.
Please don't require us to put even more quirks into the existing driver
sources.
Agreed, what I was thinking of was adding an init/term function and a struct
that represents a device instance (rather than a whole family of devices),
and adding a DeviceEntryExtended2 to set that up. That way, the driver can
query the device when inited, find out it's real type, and pass the
appropriate filetype table (probably from a separate .c file), so we don't
have the horrible overloading that exists in the DS2408 driver.

What I'm stuck on is that none of the existing infrastructure seems to have
a concept of a device instance, only types of devices, and I'm not sure it
can be easily retrofitted.

Regardless of whether I have a second level of device types, I don't think I
can do without a struct to have device instance state. My use case is this:
- The implementation library allows an arbitrary number of channels
- I have a command which returns the number of channels
- I would only like to display files for the permitted channels
- I would like to avoid querying the device every time a directory listing
is done

If you have any ideas, I'm all ears. Maybe querying the device for it's
state when necessary wouldn't be disastrous...
If you make your own device, please give it its own family code and create
your own driver source file in the owlib tree. We are going to face at
most
twenty fundamentally different designs of homebrewn devices and there's
plenty of unused address space for that.
That feels a lot like "640kb ought to be enough for everyone"...

<later>
By the way, if you do an onewire LED driver, the feature I adore most is
synchronous control over a whole bus. So multiple LED units can be pre-
programmed to dim in a controlled fashion starting at a single point in
time.
You had to implement a new command similar to "Convert T" to achieve this.
That would break any existing driver but is extremly simple to implement
in
your own driver (and the simultanenous code, of course).
That sounds like a great idea, thanks.

These are the commands I have implemented currently:
ALL_OFF (sets all the channels on the device off, maybe a candidate
for a simultaneous command?)
COUNT_CHANNELS returns the number of available channels to the master
SET_CHANNEL fades a channel to a specified RGBW value over a
specified time
GET_CHANNEL gets the current RGBW value of a channel, and the
fade time remaining

It should be relatively straightforward to add a COMMIT command which only
starts fading the requested channels once received.

Do you have any other suggestions?
Johan Ström
2017-02-11 08:08:16 UTC
Permalink
Post by Jan Kandziora
By the way, if you do an onewire LED driver, the feature I adore most is
synchronous control over a whole bus. So multiple LED units can be pre-
programmed to dim in a controlled fashion starting at a single point in
time.
You had to implement a new command similar to "Convert T" to achieve this.
That would break any existing driver but is extremly simple to implement
in
your own driver (and the simultanenous code, of course).
That sounds like a great idea, thanks.
ALL_OFF (sets all the channels on the device off, maybe a candidate
for a simultaneous command?)
COUNT_CHANNELS returns the number of available channels to the master
SET_CHANNEL fades a channel to a specified RGBW value over a
specified time
GET_CHANNEL gets the current RGBW value of a channel, and the
fade time remaining
It should be relatively straightforward to add a COMMIT command which only
starts fading the requested channels once received.
I've done some (not yet published) work on MoaT (another custom slave)
to add some LED PWM'ing capabilities. It have been on pause lately
though, but the prototype is lying on my desk and have been fading a LED
strip up and down for a few months now.

Anyway, my prototype has support for the following settings/modes:
* Direct PWM duty cycle control (for setting a static value)
* "Breath" / ramp / flash mode: Fades back and forth between two min/max
values, with adjustable step size (how much to inc/dec the PWM output),
step duration (how long to wait between each inc/dec), and hold duration
(how long to wait at min/max). With zero step duration it's just
flashing between min/max.
* Repeat mode: same as above but just repeats the specified number of
times. Useful for i.e "flash 10 times then stay off" (or on, configurable).

This gives quite a few parameters to control for each channel though,
could perhaps be simplified or improved..
I had the same idea about a "master" control, can probably be very
useful indeed!

Well, just wanted to throw it out there.. Perhaps it can inspire some
good ideas, and perhaps that can inspire me to get back on working with
it :)

/Johan
Colin Reese
2017-02-11 08:12:13 UTC
Permalink
If you could point me to a known working hardware/software configuration on or offline I would be quite grateful.

Thanks,
Colin
Post by Johan Ström
Post by Jan Kandziora
By the way, if you do an onewire LED driver, the feature I adore most is
synchronous control over a whole bus. So multiple LED units can be pre-
programmed to dim in a controlled fashion starting at a single point in
time.
You had to implement a new command similar to "Convert T" to achieve this.
That would break any existing driver but is extremly simple to implement
in
your own driver (and the simultanenous code, of course).
That sounds like a great idea, thanks.
ALL_OFF (sets all the channels on the device off, maybe a candidate
for a simultaneous command?)
COUNT_CHANNELS returns the number of available channels to the master
SET_CHANNEL fades a channel to a specified RGBW value over a
specified time
GET_CHANNEL gets the current RGBW value of a channel, and the
fade time remaining
It should be relatively straightforward to add a COMMIT command which only
starts fading the requested channels once received.
I've done some (not yet published) work on MoaT (another custom slave)
to add some LED PWM'ing capabilities. It have been on pause lately
though, but the prototype is lying on my desk and have been fading a LED
strip up and down for a few months now.
* Direct PWM duty cycle control (for setting a static value)
* "Breath" / ramp / flash mode: Fades back and forth between two min/max
values, with adjustable step size (how much to inc/dec the PWM output),
step duration (how long to wait between each inc/dec), and hold duration
(how long to wait at min/max). With zero step duration it's just
flashing between min/max.
* Repeat mode: same as above but just repeats the specified number of
times. Useful for i.e "flash 10 times then stay off" (or on, configurable).
This gives quite a few parameters to control for each channel though,
could perhaps be simplified or improved..
I had the same idea about a "master" control, can probably be very
useful indeed!
Well, just wanted to throw it out there.. Perhaps it can inspire some
good ideas, and perhaps that can inspire me to get back on working with
it :)
/Johan
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
_______________________________________________
Owfs-developers mailing list
https://lists.sourceforge.net/lists/listinfo/owfs-developers
Alastair D'Silva
2017-02-11 09:18:52 UTC
Permalink
-----Original Message-----
Sent: Saturday, 11 February 2017 7:12 PM
To: OWFS (One-wire file system) discussion and help <owfs-
Subject: Re: [Owfs-developers] Hiding incompatible device variants
If you could point me to a known working hardware/software configuration
on or offline I would be quite grateful.
Thanks,
Colin
I'll release what I have shortly - I just need to get clearance from my workplace (maybe in the next week?)
--
Alastair D'Silva mob: 0423 762 819
skype: alastair_dsilva msn: ***@d-silva.org
blog: http://alastair.d-silva.org Twitter: @EvilDeece
Johan Ström
2017-02-11 09:24:24 UTC
Permalink
Post by Colin Reese
If you could point me to a known working hardware/software configuration on or offline I would be quite grateful.
Thanks,
Colin
Ok, so here is a pretty much copy-paste solution which should work:

I'm running with a Mega88 with the internal 8Mhz RC. I have a custom
file "mydevices.cfg" [1] in the moat source dir.
I build & program the device with

make CFG=mydevices.cfg burn_mymoat

Or, to just test build: skip burn_ prefix

avrdude is used to program via an Avr-ISPmkII.
python3 is required for Cfg
the regular AVR stack is required (avr-gcc, avr-objcopy etc)

The first time you run the command it will allocate a random ID and add
"onewire_id" to the cfg file.

Hope this can help you get started!

/Johan



[1] mydevices.cfg:

_include: world.cfg
env:
prog: avrispmkii -P usb
avrdude: avrdude

devices:
_default:
_ref: defaults.target.m88
types:
_ref: defaults.types
code: []

mymoat:
_ref: defaults.target.m88
_doc: Mega88PU-A with 8Mhz RC
types:
port: 12
adc: 9
status: 1
port:

# See world.cfg for what the ^ and * etc symbols mean!

1: B2^* # Green LED (low to light)
2: B1^* # Red LED (low to light)
3: B0_*
4: D7~+*

5: D6_* # Unused
6: D5_* # Unused
7: B7_* # Unused
8: B6_* # Unused

9: D4_* # Unused
10: D3_* # Unused
# # D2 is 1W
11: D1_* # Unused
12: D0_* # Unused
# PC6 is reset, already has external pull-up

# PC0-PC5 + ADC6-7 are used as ADC. No pullup necessary
unused: [B5,B4,B3]

adc:
1: 0*
2: 1*
3: 2*
4: 3*
5: 4*
6: 5*
7: 6*
8: 7*
9: T-* # temperature
Colin Reese
2017-02-11 09:45:40 UTC
Permalink
Thanks!

I'll get out the programmer shortly and test this out. I only have 328s around but from what I remember it's an easy change in the config file. I just fiddled for some time and nothing ever popped up on my bus.

Colin
Post by Johan Ström
Post by Colin Reese
If you could point me to a known working hardware/software configuration on or offline I would be quite grateful.
Thanks,
Colin
I'm running with a Mega88 with the internal 8Mhz RC. I have a custom
file "mydevices.cfg" [1] in the moat source dir.
I build & program the device with
make CFG=mydevices.cfg burn_mymoat
Or, to just test build: skip burn_ prefix
avrdude is used to program via an Avr-ISPmkII.
python3 is required for Cfg
the regular AVR stack is required (avr-gcc, avr-objcopy etc)
The first time you run the command it will allocate a random ID and add
"onewire_id" to the cfg file.
Hope this can help you get started!
/Johan
_include: world.cfg
prog: avrispmkii -P usb
avrdude: avrdude
_ref: defaults.target.m88
_ref: defaults.types
code: []
_ref: defaults.target.m88
_doc: Mega88PU-A with 8Mhz RC
port: 12
adc: 9
status: 1
# See world.cfg for what the ^ and * etc symbols mean!
1: B2^* # Green LED (low to light)
2: B1^* # Red LED (low to light)
3: B0_*
4: D7~+*
5: D6_* # Unused
6: D5_* # Unused
7: B7_* # Unused
8: B6_* # Unused
9: D4_* # Unused
10: D3_* # Unused
# # D2 is 1W
11: D1_* # Unused
12: D0_* # Unused
# PC6 is reset, already has external pull-up
# PC0-PC5 + ADC6-7 are used as ADC. No pullup necessary
unused: [B5,B4,B3]
1: 0*
2: 1*
3: 2*
4: 3*
5: 4*
6: 5*
7: 6*
8: 7*
9: T-* # temperature
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
_______________________________________________
Owfs-developers mailing list
https://lists.sourceforge.net/lists/listinfo/owfs-developers
Matthias Urlichs
2017-02-11 08:21:30 UTC
Permalink
Post by Alastair D'Silva
If you have any ideas, I'm all ears. Maybe querying the device for it's
state when necessary wouldn't be disastrous...
*its state. :-P

You might want to look at the MoaT driver, which does something similar.
--
-- Matthias Urlichs
Jan Kandziora
2017-02-11 10:03:56 UTC
Permalink
Post by Alastair D'Silva
Post by Jan Kandziora
DS2408 codebase which handles the various HD44780 displays connected to
the DS2408. It's ugly, it's error-prone and it's hard to debug.
Please don't require us to put even more quirks into the existing driver
sources.
Agreed, what I was thinking of was adding an init/term function and a struct
that represents a device instance (rather than a whole family of devices),
and adding a DeviceEntryExtended2 to set that up. That way, the driver can
query the device when inited, find out it's real type, and pass the
appropriate filetype table (probably from a separate .c file), so we don't
have the horrible overloading that exists in the DS2408 driver.
All the things owlib knows about a family is purely static. This is
required for the correct interaction of owserver and the client, which
may be an abitrary number of owserver layers.

Changing that creates a horrible amount of complexity. Please don't do
that. We can't possibly maintain it. I was glad I found a simple trick
for the "external" sensors where the upper level owservers know nothing
about lower level definitions but it's ugly, too.
Post by Alastair D'Silva
What I'm stuck on is that none of the existing infrastructure seems to have
a concept of a device instance, only types of devices, and I'm not sure it
can be easily retrofitted.
You are right. OWFS does not store anything device-specific. It's
stateless in that regard, which is a wise choice because devices may be
in an arbitrary state depending whether they had been powered on or off.

(The only exception is the cache, but that's a node->value store only
for user programs which isn't queried for owlib's internal workings. You
could query it but please don't do it. It would confuse unaware
programmers.)

If you'd need to distinguish device states, please store these on the
device itself. If you need owlib to do a quick check for a state after a
device command, include a 1-bit cycle to query that state before
continuing. It's simple to implement and the robust way to do it.
Post by Alastair D'Silva
Regardless of whether I have a second level of device types, I don't think I
- The implementation library allows an arbitrary number of channels
- I have a command which returns the number of channels
This is something the user program (on top of OWFS) has to know. So the
user program is the place to store that information.
Post by Alastair D'Silva
- I would only like to display files for the permitted channels
This is a nice-to-have feature. Given the amount of complexity you have
to add to support this, I would first walk away, then turn around, throw
something heavy at it, then run away.
Post by Alastair D'Silva
- I would like to avoid querying the device every time a directory listing
is done
You are right. Doing so would be bad.
Post by Alastair D'Silva
If you have any ideas, I'm all ears. Maybe querying the device for it's
state when necessary wouldn't be disastrous...
Include the number of R/G/B channels into the second/third etc byte of
the ID so OWFS magically knows it just from looking at the ID.

There are plenty of ID bits available and the number of devices ever
manufactured sure wouldn't hit millions.
Post by Alastair D'Silva
That feels a lot like "640kb ought to be enough for everyone"...
It was. What went wrong wasn't that number but DOS living for too long
though better solutions existed.

You don't have that problem. You are not required to stick to an
inferior system. Your slaves are just software. If a better solution
comes up later, there's no problem to re-flash the devices.

(Please include a way to self-program your devices via onewire.)
Post by Alastair D'Silva
Post by Jan Kandziora
By the way, if you do an onewire LED driver, the feature I adore most is
synchronous control over a whole bus. So multiple LED units can be pre-
programmed to dim in a controlled fashion starting at a single point in
time.
You had to implement a new command similar to "Convert T" to achieve this.
That would break any existing driver but is extremly simple to implement
inyour own driver (and the simultanenous code, of course).
That sounds like a great idea, thanks.
ALL_OFF (sets all the channels on the device off, maybe a candidate
for a simultaneous command?)
Yes.
Post by Alastair D'Silva
COUNT_CHANNELS returns the number of available channels to the master
Please do that in a static manner.
Post by Alastair D'Silva
SET_CHANNEL fades a channel to a specified RGBW value over a
specified time
GET_CHANNEL gets the current RGBW value of a channel, and the
fade time remaining
It should be relatively straightforward to add a COMMIT command which
only starts fading the requested channels once received.
A much better design would allow the user program to push presets into
the device RAM, and into a EEPROM backing store for each preset slot.
Whether to store a RAM preset into EEPROM is selected by another
command. That's the way the other onewire devices do it.

That way, the device doesn't have to be set-up after each power fail.
But even if you don't have a backing store, complex presets for a number
of channels reflect real-life requirements for lighting applications.

Presets could simply be ramps (start value absolute, end value–absolute
or relative, speed) but the slot should be able to include an arbitrary
number of channels involved.

The COMMIT command does have to use the preset slot, not the channel! We
are doing a synchronous command over multiple devices so channel numbers
aren't unique. You would introduce a tie between the channels on
different devices.

If you want to make it perfect, give the COMMIT command another byte
besides the preset slot which is checked against a user-presetable
and/or-mask inside the device and only react when the masks match.


Include a setting which controls what happens if any ramp isn't
completed when a new "COMMIT" command (masked, of course) arrives.
Options: Switch to new preset from ramp start value/switch to new preset
from current ramp value/ignore and signal error.



Your GET_CHANNEL command makes no sense to me. Basically it asks me to
use the device as a time source for my user program fading control. Why
would I do that? If I had multiple devices, which source should I
select? That's arcane design. Avoid!
Post by Alastair D'Silva
Do you have any other suggestions?
Please include a POR state bit and a way to query/reset it. This makes
life much easier for user programs which have to make sure all devices
are set up properly.

Include a conditional search filter which triggers on POR, "Fade
completed" and "Error condition". And a status register to find out
which condition hit.

The idea is the user program starts a conditional search multiple times
per second and most of the time no device at all reacts. That way
conditional search is a cheap operation.

When a device needs new directives, it reacts to conditional search and
is serviced by the user program.


Kind regards

Jan
Matthias Urlichs
2017-02-11 11:26:37 UTC
Permalink
Post by Jan Kandziora
Post by Alastair D'Silva
- I would only like to display files for the permitted channels
This is a nice-to-have feature. Given the amount of complexity you have
to add to support this, I would first walk away, then turn around, throw
something heavy at it, then run away.
MoaT implements something like this. It's not that difficult / complex
IMHO. The key idea is to store the list of permitted channels on the
device. You need a command to retrieve that information anyway, so use
its result in owfs to limit the number of channels.
--
-- Matthias Urlichs
Jan Kandziora
2017-02-11 12:27:51 UTC
Permalink
Post by Matthias Urlichs
Post by Jan Kandziora
Post by Alastair D'Silva
- I would only like to display files for the permitted channels
This is a nice-to-have feature. Given the amount of complexity you have
to add to support this, I would first walk away, then turn around, throw
something heavy at it, then run away.
MoaT implements something like this. It's not that difficult / complex
IMHO. The key idea is to store the list of permitted channels on the
device. You need a command to retrieve that information anyway, so use
its result in owfs to limit the number of channels.
The latter is the difficult and complex part, because you have to inform
all layers in the owfs setup about that change.

There are no provisions for that. It had to be introduced from scratch,
change a number of core components. All that for a feature which is just
nice-to-have and not used by any other component but these two.

Kind regards

Jan

Jan Kandziora
2017-02-11 00:13:37 UTC
Permalink
Post by Alastair D'Silva
I've written a 1Wire slave implementation for ARM (which I will be
open sourcing), in order to implement some functionality that does
not exist in the 1Wire world (multichannel RGBW control).
By the way, if you do an onewire LED driver, the feature I adore most is
synchronous control over a whole bus. So multiple LED units can be
pre-programmed to dim in a controlled fashion starting at a single point
in time.

You had to implement a new command similar to "Convert T" to achieve
this. That would break any existing driver but is extremly simple to
implement in your own driver (and the simultanenous code, of course).

Kind regards

Jan
Loading...