The Netduino forums have been replaced by new forums at community.wildernesslabs.co.
This site has been preserved for archival purposes only
and the ability to make new accounts or posts has been turned off.
First (as another poster pointed out), this is integer division. In most languages, integer division always rounds down. For example, in real life 129/64 = 2.015625 but a computer doing integer division would round it down to exactly 2.
The question is, what can we do when we want "round up" behavior rather than "round down"? The standard trick is
replace
numerator / denominator
with
(numerator + (denominator-1)) / denominator
It has to be written this way because we want to add 1 except when the numerator is evenly divisible by the denominator.
Consider these examples in real life (using a calculator):
(127/64) = [font="helvetica, arial, sans-serif;"]1.984375, which rounds up to 2[/font]
(128/64) = 2 (exactly)
(129/64) = [font="helvetica, arial, sans-serif;"]2.015625, which rounds up to 3[/font]
Now let's imagine that we are only allowed to round down. Then:
[font="helvetica, arial, sans-serif;"](127+63)/64 = 2.96875, which rounds down to 2[/font]
[font="helvetica, arial, sans-serif;"](128+63)/64 = 2.984375, which rounds down to 2[/font]
[font="helvetica, arial, sans-serif;"](129+63)/64 = exactly 3, which rounds down to 3[/font]
[font="helvetica, arial, sans-serif;"]You can see that we get the same output (2, 2, 3) as we did in the "round up" case, but we were able to solve our problem using only "round down" operations.[/font]
You can try it on other cases and see that the substitution trick always gets you the same answer but you only need to ever round down, not up.
Now, as for why you want to round up. As you point out, your code fragment looks a little strange because it's all constants and you could have computed it yourself. Normally however this kind of thing appears in programs where one value (say, numLEDs) is a variable, not a constant. If you replace (most) of the occurrences of "32" with "numLEDs" in this program, you can see how this could be convenient.
Now as for your other questions:
The reason the high bit (0x80) is set on all the color bytes has to do with the protocol, which simply requires it
The reason line 13 exists is because the author is trying to write defensive code. The colors array occurs in groups of three. Line 18 sets the red component of each triple (which occur in any given triple at offset 0 of the triple). Line 17 sets the green component (which occurs at offset 1). But you'll notice that the blue component is not set inside the loop. Line 13 exists to make sure that any unset values have the default value of 0x80 (again, the protocol requires that the high bit be asserted in all of these bytes). This is probably overkill. If it were me, I'd probably delete line 13 and insert a new line in the inner for loop, namely: [color=rgb(0,0,0);font-family:monospace;font-size:13px;background-color:rgb(250,250,250);]colors[/color][color=rgb(102,102,0);font-family:monospace;font-size:13px;background-color:rgb(250,250,250);][[/color][color=rgb(0,0,0);font-family:monospace;font-size:13px;background-color:rgb(250,250,250);]i [/color][color=rgb(102,102,0);font-family:monospace;font-size:13px;background-color:rgb(250,250,250);]*[/color][color=rgb(0,0,0);font-family:monospace;font-size:13px;background-color:rgb(250,250,250);] [/color][color=rgb(0,102,102);font-family:monospace;font-size:13px;background-color:rgb(250,250,250);]3[/color][color=rgb(0,0,0);font-family:monospace;font-size:13px;background-color:rgb(250,250,250);] [/color][color=rgb(102,102,0);font-family:monospace;font-size:13px;background-color:rgb(250,250,250);]+[/color][color=rgb(0,0,0);font-family:monospace;font-size:13px;background-color:rgb(250,250,250);] [/color][font="monospace;font-size:13px;background-color:rgb(250,250,250);"]2[/font][color=rgb(102,102,0);font-family:monospace;font-size:13px;background-color:rgb(250,250,250);]][/color][color=rgb(0,0,0);font-family:monospace;font-size:13px;background-color:rgb(250,250,250);] [/color][color=rgb(102,102,0);font-family:monospace;font-size:13px;background-color:rgb(250,250,250);]=[/color][color=rgb(0,0,0);font-family:monospace;font-size:13px;background-color:rgb(250,250,250);] [/color][color=rgb(0,102,102);font-family:monospace;font-size:13px;background-color:rgb(250,250,250);]0x80; // put this before line 17[/color]
I'm not sure what source code you adapted this from, but the lengthy comments on top of https://github.com/a...ter/LPD8806.cpp pretty much explain why this is so, almost. (almost!)
In particular, there's this paragraph:
[color=rgb(153,153,136);font-style:italic;]Curiously, zero bytes can only travel one meter (32[/color]
[color=rgb(153,153,136);font-style:italic;]LEDs) down the line before needing backup; the next meter requires an[/color]
[color=rgb(153,153,136);font-style:italic;]extra zero byte, and so forth. [/color]
If the constants in the array involved "31 and 32" rather then "63 and 64", this would match the above explanation perfectly. In other words, given the number of LEDs we have, we need to compute how many "meters" of strip we have. As a result of the above explanation, I would have expected to see a line like this:
I bought one of these: http://www.adafruit.com/products/306 and can drive it from netduino using the modified example code on the adafruit site:
using Microsoft.SPOT.Hardware; public static void LightStripSpi() { var spi = new SPI(new SPI.Configuration(Cpu.Pin.GPIO_NONE, false, 0, 0, false, true, 10000, SPI.SPI_module.SPI1)); var colors = new byte[3 * 32]; var zeros = new byte[3 * ((32 + 63) / 64)]; while (true) { // all pixels off for (int i = 0; i < colors.Length; ++i) colors[i] = (byte)(0x80 | 0); // a progressive yellow/red blend for (byte i = 0; i < 32; ++i) { colors[i * 3 + 1] = 0x80 | 32; colors[i * 3 + 0] = (byte)(0x80 | (32 - i)); spi.Write(colors); spi.Write(zeros); Thread.Sleep(1000 / 32); // march at 32 pixels per second } } }
I can't for the life of me figure out what line 8 is doing:
var zeros = new byte[3 * ((32 + 63) / 64)];
I know it's creating a byte array. I assume the values of 63 and 64 are related to the no of LED's (32). Pretty poor example really: would be much clearer if no of LED's was defined as a variable or const.
Anyway why not just use:
new byte[3 * 32]
I've never used byte arrays before, but it looks like byte[3 * 32] creates an array of 96 bytes (which makes sense: 1 byte per color * 3 * 32 LEDs) and it looks like byte[3 * ((32 + 63) / 64) creates a byte array of 4.453125 bytes - clearly this can't be what it's doing. Can anyone enlighten me?
It also seems that the zeros array never gets initialized to anything, so I'm surprised spi.Write(zeros) actually does clear the LEDs.
I know it's writing a value to the i-th array member, but not sure why the color is OR'd with the color value. I guess it's just setting the MSB to 1, but not sure why.
evaluate what's in parenthesis first and use integer math.
32 + 63 = 95
95 / 64 = 1
1 * 3 = 3
[color=rgb(40,40,40);font-family:helvetica, arial, sans-serif;]var zeros = new byte[3];[/color]
[color=rgb(40,40,40);font-family:helvetica, arial, sans-serif;]why all the extra math? That's usually done to communicate that it's not an arbitrary number that the programmer has selected, but some function of other stuff. I have no idea why +63. [/color]
As fars as the zeros not being set, the c# compiler always initializes everything to zero. Numerics are 0 or 0.0, bools are false, and references are null. It's the same as this
Just thinking out loud, could the reason for the "+63" be to make sure no matter what, the value always comes up as 1? unless the "32" is zero, then your value at the end will always be 1 or larger (as long as the "32" value is less than 65).
I may be WAAAAAAY off base.
But then looking back at the code, 32+63 is hard coded, not a variable. Why not just place
var zeros = new byte[3]
[font="tahoma, geneva, sans-serif;"]? [/font] You would get the same result.
First (as another poster pointed out), this is integer division. In most languages, integer division always rounds down. For example, in real life 129/64 = 2.015625 but a computer doing integer division would round it down to exactly 2.
The question is, what can we do when we want "round up" behavior rather than "round down"? The standard trick is
replace
numerator / denominator
with
(numerator + (denominator-1)) / denominator
It has to be written this way because we want to add 1 except when the numerator is evenly divisible by the denominator.
Consider these examples in real life (using a calculator):
(127/64) = [font="helvetica, arial, sans-serif;"]1.984375, which rounds up to 2[/font]
(128/64) = 2 (exactly)
(129/64) = [font="helvetica, arial, sans-serif;"]2.015625, which rounds up to 3[/font]
Now let's imagine that we are only allowed to round down. Then:
[font="helvetica, arial, sans-serif;"](127+63)/64 = 2.96875, which rounds down to 2[/font]
[font="helvetica, arial, sans-serif;"](128+63)/64 = 2.984375, which rounds down to 2[/font]
[font="helvetica, arial, sans-serif;"](129+63)/64 = exactly 3, which rounds down to 3[/font]
[font="helvetica, arial, sans-serif;"]You can see that we get the same output (2, 2, 3) as we did in the "round up" case, but we were able to solve our problem using only "round down" operations.[/font]
You can try it on other cases and see that the substitution trick always gets you the same answer but you only need to ever round down, not up.
Now, as for why you want to round up. As you point out, your code fragment looks a little strange because it's all constants and you could have computed it yourself. Normally however this kind of thing appears in programs where one value (say, numLEDs) is a variable, not a constant. If you replace (most) of the occurrences of "32" with "numLEDs" in this program, you can see how this could be convenient.
Now as for your other questions:
The reason the high bit (0x80) is set on all the color bytes has to do with the protocol, which simply requires it
The reason line 13 exists is because the author is trying to write defensive code. The colors array occurs in groups of three. Line 18 sets the red component of each triple (which occur in any given triple at offset 0 of the triple). Line 17 sets the green component (which occurs at offset 1). But you'll notice that the blue component is not set inside the loop. Line 13 exists to make sure that any unset values have the default value of 0x80 (again, the protocol requires that the high bit be asserted in all of these bytes). This is probably overkill. If it were me, I'd probably delete line 13 and insert a new line in the inner for loop, namely: [color=rgb(0,0,0);font-family:monospace;font-size:13px;background-color:rgb(250,250,250);]colors[/color][color=rgb(102,102,0);font-family:monospace;font-size:13px;background-color:rgb(250,250,250);][[/color][color=rgb(0,0,0);font-family:monospace;font-size:13px;background-color:rgb(250,250,250);]i [/color][color=rgb(102,102,0);font-family:monospace;font-size:13px;background-color:rgb(250,250,250);]*[/color][color=rgb(0,0,0);font-family:monospace;font-size:13px;background-color:rgb(250,250,250);] [/color][color=rgb(0,102,102);font-family:monospace;font-size:13px;background-color:rgb(250,250,250);]3[/color][color=rgb(0,0,0);font-family:monospace;font-size:13px;background-color:rgb(250,250,250);] [/color][color=rgb(102,102,0);font-family:monospace;font-size:13px;background-color:rgb(250,250,250);]+[/color][color=rgb(0,0,0);font-family:monospace;font-size:13px;background-color:rgb(250,250,250);] [/color][font="monospace;font-size:13px;background-color:rgb(250,250,250);"]2[/font][color=rgb(102,102,0);font-family:monospace;font-size:13px;background-color:rgb(250,250,250);]][/color][color=rgb(0,0,0);font-family:monospace;font-size:13px;background-color:rgb(250,250,250);] [/color][color=rgb(102,102,0);font-family:monospace;font-size:13px;background-color:rgb(250,250,250);]=[/color][color=rgb(0,0,0);font-family:monospace;font-size:13px;background-color:rgb(250,250,250);] [/color][color=rgb(0,102,102);font-family:monospace;font-size:13px;background-color:rgb(250,250,250);]0x80; // put this before line 17[/color]
I'm not sure what source code you adapted this from, but the lengthy comments on top of https://github.com/a...ter/LPD8806.cpp pretty much explain why this is so, almost. (almost!)
In particular, there's this paragraph:
[color=rgb(153,153,136);font-style:italic;]Curiously, zero bytes can only travel one meter (32[/color]
[color=rgb(153,153,136);font-style:italic;]LEDs) down the line before needing backup; the next meter requires an[/color]
[color=rgb(153,153,136);font-style:italic;]extra zero byte, and so forth. [/color]
If the constants in the array involved "31 and 32" rather then "63 and 64", this would match the above explanation perfectly. In other words, given the number of LEDs we have, we need to compute how many "meters" of strip we have. As a result of the above explanation, I would have expected to see a line like this:
It does have info for the arduino and the libs, but I read this
"[color=rgb(82,82,82);font-family:'Helvetica Neue', Helvetica, Arial, sans-serif;]Driving these strips from Netduino (or other .Net Micro Framwork boards like FEZ Panda) is very convenient and doesn't require a code library if SPI ports are used."[/color]
and assumed that the way you drove it from Netduino was totally different (i.e. not SPI). Guess I misunderstood