Repository: ManiacalLabs/BiblioPixel
Pull request #1035 (2018-10-30 19:48:38)

Preliminary steps to POV fix
Early steps while I contemplate how to do the frame multiplexing trick.  It's not hard - the question is how to present it to the user?

adammhaile: I don't understand what `direction` has to do with POV?
rec: Right now, POV only scans the matrix in one direction - top to bottom, if I remember the code aright.

But there are four possible directions it could actually scan.  

Experimenting with the two `_flip` variables shows that you can't get to two of them that way - specifically, if the strip were hung horizontally so you moved your head up and down, rather than vertically (or do I have that backwards?)

(Also, to be frank, I'm always looking to add variables that are meaningful so I can add a control to them.  :-D  In a square matrix, attaching a fader to `direction` and moving it around would possibily have mind-blowing effects - or perhaps not, but one way to find out.
adammhaile: ah.... So, a little feature creep.
POV was always sort of written in a way such that there was one correct way
to use it. Not saying it should be expanded, just not sure it's worth doing
it just for the sake of it.

On Tue, Oct 30, 2018 at 3:57 PM Tom Swirly <notifications@github.com> wrote:

> Right now, POV only scans the matrix in one direction - top to bottom, if
> I remember the code aright.
>
> But there are four possible directions it could actually scan.
>
> Experimenting with the two _flip variables shows that you can't get to
> two of them that way - specifically, if the strip were hung horizontally so
> you moved your head up and down, rather than vertically (or do I have that
> backwards?)
>
> (Also, to be frank, I'm always looking to add variables that are
> meaningful so I can add a control to them. :-D In a square matrix,
> attaching a fader to direction and moving it around would possibily have
> mind-blowing effects - or perhaps not, but one way to find out.
>
> —
> You are receiving this because you commented.
> Reply to this email directly, view it on GitHub
> <https://github.com/ManiacalLabs/BiblioPixel/pull/1035#issuecomment-434446765>,
> or mute the thread
> <https://github.com/notifications/unsubscribe-auth/AA6a6p3-PnnDe_QD6fKhrmWGMefkf3jtks5uqK8LgaJpZM4YCuSR>
> .
>

rec: I agree, to be honest.  :-D

In fact, I was doing this as "doodling" while try to figure out the right way to fix the main POV.

The issue is that it's a layout, and layouts aren't supposed to be doing temporal things!  Layouts are supposed to be passive, "index remappy" sort of things.

I'm leaning towards turning POV into a container Animation at this moment, tbh, even though it isn't backwards compatible.  At least we can get really clean coherent timing that way - but it's not perfect either.

Or - logically, POV should be a driver - a driver containing another driver?  

In other words, the POV matrix driver would contain say an LPD8806 strip driver.

We have no such thing until now but there's no particular reason that such a thing shouldn't exist or difficulty in doing it.

But then we have the issue that we again have two different "frame" generators that won't be in synch with each other.
rec: The container Animation is, I have decided, the only correct way to go.  Here's why.

I might very easily want to have a strip Project with a bunch of different animations controlled by Remote or REST, only one of which was POV.  That's not possible if the POV is a Layout.

Generally, we should put as much of our functionality into Animations as possible, is the conclusion of this, because we can switch them in real time.
rec: Well, looking at it in the cold hard light of morning, I agree it's sorta feature creepy but I'm going to push it anyway because I really want to charge forward and fix these three outstanding issues... :-/
rec: And what better time to push creepy code than Halloween?

Patch:
diff --git a/bibliopixel/project/fields.py b/bibliopixel/project/fields.py
index ede5c35..b5a7feb 100644
--- a/bibliopixel/project/fields.py
+++ b/bibliopixel/project/fields.py
@@ -1,5 +1,5 @@
 from . types import (
-    channel_order, color, colors, duration, gamma, int_name, ledtype,
+    channel_order, color, colors, direction, duration, gamma, int_name, ledtype,
     spi_interface)
 
 
@@ -12,6 +12,7 @@ FIELD_TYPES = {
     'color2': color,
     'colors': colors,
     'count': int_name,
+    'direction': direction,
     'duration': duration,
     'func': int_name,
     'gamma': gamma,
diff --git a/bibliopixel/project/types/channel_order.py b/bibliopixel/project/types/channel_order.py
index d7ba7fc..6e5f15a 100644
--- a/bibliopixel/project/types/channel_order.py
+++ b/bibliopixel/project/types/channel_order.py
@@ -4,7 +4,7 @@ from ...drivers.channel_order import ChannelOrder
 USAGE = """
 A ChannelOrder can be initialized with:
 
-* A list, tuple or string of lengths three: '012', 'bgr', (0, 2, 1)
+* A list, tuple or string of length three: '012', 'bgr', (0, 2, 1)
 * An integer from 0 to 5."""
 
 NAMES = {
diff --git a/bibliopixel/project/types/direction.py b/bibliopixel/project/types/direction.py
new file mode 100644
index 0000000..7ee9bc5
--- /dev/null
+++ b/bibliopixel/project/types/direction.py
@@ -0,0 +1,42 @@
+import functools
+
+NAMES = {
+    'up': (0, -1),
+    'down': (0, 1),
+    'left': (-1, 0),
+    'right': (1, 0),
+}
+
+
+@functools.singledispatch
+def make(c):
+    raise ValueError(ERROR % c)
+
+
+@make.register(str)
+def _(c):
+    items = [v for k, v in NAMES.items() if k.startswith(c)]
+    if len(items) != 1:
+        raise ValueError(ERROR % c)
+    return items[0]
+
+
+@make.register(tuple)
+def _(c):
+    if c not in NAMES.values():
+        raise ValueError(ERROR % (c,))
+    return c
+
+
+@make.register(list)
+def _(c):
+    return make(tuple(c))
+
+
+USAGE = """Direction values can be
+* a string 'up', 'down', 'left', 'right', or
+* a string prefix like 'u' or 'ri'
+* one of four numeric pairs (0, -1), (0, 1), (-1, 0), (1, 0).
+"""
+
+ERROR = 'Don\'t understand direction "%s"\n' + USAGE


Test patch:
diff --git a/test/bibliopixel/project/types/direction_test.py b/test/bibliopixel/project/types/direction_test.py
new file mode 100644
index 0000000..7d0927b
--- /dev/null
+++ b/test/bibliopixel/project/types/direction_test.py
@@ -0,0 +1,22 @@
+from . base import TypesBaseTest
+
+
+class DirectionTest(TypesBaseTest):
+    def test_some(self):
+        def test(name, expected):
+            actual = self.make('direction', name)['direction']
+            self.assertEqual(actual, expected)
+
+        test('up', (0, -1))
+        test('r', (1, 0))
+        test((-1, 0), (-1, 0))
+        test([0, 1], (0, 1))
+
+        with self.assertRaises(ValueError):
+            self.make('direction', 'sideways')
+
+        with self.assertRaises(ValueError):
+            self.make('direction', None)
+
+        with self.assertRaises(ValueError):
+            self.make('direction', (-1, -1))