Skip to content

Commit dde71c9

Browse files
committed
- fixed compile error in file SpiTransferBufferSpecs.cs (missing explicit cast at line 227)
- FileGpioConnection: replaced Raspberry specific platform check against a generic Unix check (this make it compatible with other /sys/class/gpio compatible platforms, eg. Banana Pi) - Added Default driver fallback to FileGpioConnection on non-Raspberry Pi systems - Added support for Grove Chainable RGB Led modules
1 parent ac26340 commit dde71c9

File tree

5 files changed

+272
-15
lines changed

5 files changed

+272
-15
lines changed
Lines changed: 253 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,253 @@
1+
#region References
2+
3+
using System;
4+
using Raspberry.IO;
5+
using Raspberry.Timers;
6+
using Raspberry.IO.GeneralPurpose;
7+
using System.Collections.Generic;
8+
9+
#endregion
10+
11+
namespace Raspberry.IO.Components.Leds.GroveRgb
12+
{
13+
/// <summary>
14+
/// Represents a connection with Grove Chainable RGB Led modules.
15+
/// @see http://www.seeedstudio.com/wiki/Grove_-_Chainable_RGB_LED
16+
/// </summary>
17+
public class GroveRgbConnection
18+
{
19+
#region Fields
20+
21+
IGpioConnectionDriver driver;
22+
ProcessorPin dataPin;
23+
ProcessorPin clockPin;
24+
List<RgbColor> ledColors;
25+
26+
#endregion
27+
28+
#region Instance Management
29+
30+
public GroveRgbConnection(ConnectorPin dataPin, ConnectorPin clockPin, int ledCount)
31+
{
32+
ledColors = new List<RgbColor>();
33+
for(int i = 0; i < ledCount; i++)
34+
{
35+
// Initialize all leds with white color
36+
ledColors.Add(new RgbColor());
37+
}
38+
this.dataPin = dataPin.ToProcessor();
39+
this.clockPin = clockPin.ToProcessor();
40+
if (Raspberry.Board.Current.IsRaspberryPi)
41+
{
42+
driver = new GpioConnectionDriver();
43+
}
44+
else
45+
{
46+
driver = new FileGpioConnectionDriver();
47+
}
48+
driver.Allocate(this.dataPin, PinDirection.Output);
49+
driver.Allocate(this.clockPin, PinDirection.Output);
50+
}
51+
52+
#endregion
53+
54+
55+
#region Methods
56+
57+
/// <summary>
58+
/// Sets the color of a led.
59+
/// </summary>
60+
/// <param name="ledNumber">Led number (zero based index).</param>
61+
/// <param name="red">Red.</param>
62+
/// <param name="green">Green.</param>
63+
/// <param name="blue">Blue.</param>
64+
public void SetColorRgb(int ledNumber, byte red, byte green, byte blue)
65+
{
66+
// Send data frame prefix (32x "0")
67+
SendByte(0x00);
68+
SendByte(0x00);
69+
SendByte(0x00);
70+
SendByte(0x00);
71+
72+
// Send color data for each one of the leds
73+
for (int i = 0; i < ledColors.Count; i++)
74+
{
75+
if (i == ledNumber)
76+
{
77+
ledColors[i].Red = red;
78+
ledColors[i].Green = green;
79+
ledColors[i].Blue = blue;
80+
}
81+
82+
// Start by sending a byte with the format "1 1 /B7 /B6 /G7 /G6 /R7 /R6"
83+
byte prefix = Convert.ToByte ("11000000", 2);
84+
if ((blue & 0x80) == 0)
85+
prefix |= Convert.ToByte ("00100000", 2);
86+
if ((blue & 0x40) == 0)
87+
prefix |= Convert.ToByte ("00010000", 2);
88+
if ((green & 0x80) == 0)
89+
prefix |= Convert.ToByte ("00001000", 2);
90+
if ((green & 0x40) == 0)
91+
prefix |= Convert.ToByte ("00000100", 2);
92+
if ((red & 0x80) == 0)
93+
prefix |= Convert.ToByte ("00000010", 2);
94+
if ((red & 0x40) == 0)
95+
prefix |= Convert.ToByte ("00000001", 2);
96+
97+
SendByte(prefix);
98+
99+
// Now must send the 3 colors
100+
SendByte(ledColors[i].Blue);
101+
SendByte(ledColors[i].Green);
102+
SendByte(ledColors[i].Red);
103+
}
104+
105+
// Terminate data frame (32x "0")
106+
SendByte(0x00);
107+
SendByte(0x00);
108+
SendByte(0x00);
109+
SendByte(0x00);
110+
}
111+
112+
/// <summary>
113+
/// Sets the color of a led.
114+
/// </summary>
115+
/// <param name="ledNumber">Led number (zero based index).</param>
116+
/// <param name="h">Hue.</param>
117+
/// <param name="s">Saturation.</param>
118+
/// <param name="v">Value.</param>
119+
public void SetColorHsv(int ledNumber, double h, double s, double v)
120+
{
121+
RgbColor color = HsvToRgb(h, s, v);
122+
SetColorRgb(ledNumber, color.Red, color.Green, color.Blue);
123+
}
124+
125+
#endregion
126+
127+
#region Private Helpers
128+
129+
private void SendByte(byte data)
130+
{
131+
// Send one bit at a time, starting with the MSB
132+
for (byte i = 0; i < 8; i++)
133+
{
134+
// If MSB is 1, write one and clock it, else write 0 and clock
135+
if ((data & 0x80) != 0)
136+
driver.Write(dataPin, true);
137+
else
138+
driver.Write(dataPin, false);
139+
140+
// clk():
141+
driver.Write(clockPin, false);
142+
HighResolutionTimer.Sleep(0.02m);
143+
driver.Write(clockPin, true);
144+
HighResolutionTimer.Sleep(0.02m);
145+
146+
// Advance to the next bit to send
147+
data <<= 1;
148+
}
149+
}
150+
151+
private int Clamp(int i)
152+
{
153+
if (i < 0) i = 0;
154+
if (i > 255) i = 255;
155+
return i;
156+
}
157+
158+
private RgbColor HsvToRgb(double hue, double sat, double val)
159+
{
160+
byte r = 0, g = 0, b = 0;
161+
double H = hue * 360D;
162+
while (H < 0) { H += 360; };
163+
while (H >= 360) { H -= 360; };
164+
double R, G, B;
165+
if (val <= 0)
166+
{
167+
R = G = B = 0;
168+
}
169+
else if (sat <= 0)
170+
{
171+
R = G = B = val;
172+
}
173+
else
174+
{
175+
double hf = H / 60.0;
176+
int i = (int)Math.Floor(hf);
177+
double f = hf - i;
178+
double pv = val * (1 - sat);
179+
double qv = val * (1 - sat * f);
180+
double tv = val * (1 - sat * (1 - f));
181+
switch (i)
182+
{
183+
// Red is the dominant color
184+
case 0:
185+
R = val;
186+
G = tv;
187+
B = pv;
188+
break;
189+
// Green is the dominant color
190+
case 1:
191+
R = qv;
192+
G = val;
193+
B = pv;
194+
break;
195+
case 2:
196+
R = pv;
197+
G = val;
198+
B = tv;
199+
break;
200+
// Blue is the dominant color
201+
case 3:
202+
R = pv;
203+
G = qv;
204+
B = val;
205+
break;
206+
case 4:
207+
R = tv;
208+
G = pv;
209+
B = val;
210+
break;
211+
// Red is the dominant color
212+
case 5:
213+
R = val;
214+
G = pv;
215+
B = qv;
216+
break;
217+
// Just in case we overshoot on our math by a little, we put these here. Since its a switch it won't slow us down at all to put these here.
218+
case 6:
219+
R = val;
220+
G = tv;
221+
B = pv;
222+
break;
223+
case -1:
224+
R = val;
225+
G = pv;
226+
B = qv;
227+
break;
228+
// The color is not defined, we should throw an error.
229+
default:
230+
R = G = B = val; // Just pretend its black/white
231+
break;
232+
}
233+
}
234+
r = (byte)Clamp((int)(R * 255.0));
235+
g = (byte)Clamp((int)(G * 255.0));
236+
b = (byte)Clamp((int)(B * 255.0));
237+
238+
return new RgbColor(){ Red = r, Green = g, Blue = b };
239+
}
240+
241+
#endregion
242+
243+
}
244+
245+
public class RgbColor
246+
{
247+
public byte Red;
248+
public byte Green;
249+
public byte Blue;
250+
}
251+
252+
}
253+

Raspberry.IO.Components/Raspberry.IO.Components.csproj

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
<PropertyGroup>
44
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
55
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
6-
<ProductVersion>8.0.30703</ProductVersion>
7-
<SchemaVersion>2.0</SchemaVersion>
86
<ProjectGuid>{8388CFCA-E3DB-43F7-B049-2CB195211CE8}</ProjectGuid>
97
<OutputType>Library</OutputType>
108
<AppDesignerFolder>Properties</AppDesignerFolder>
@@ -33,20 +31,17 @@
3331
<WarningLevel>4</WarningLevel>
3432
</PropertyGroup>
3533
<ItemGroup>
36-
<Reference Include="Common.Logging, Version=2.2.0.0, Culture=neutral, PublicKeyToken=af08829b84f0328e, processorArchitecture=MSIL">
37-
<SpecificVersion>False</SpecificVersion>
34+
<Reference Include="System" />
35+
<Reference Include="System.Core" />
36+
<Reference Include="Common.Logging">
3837
<HintPath>..\packages\Common.Logging.2.2.0\lib\net40\Common.Logging.dll</HintPath>
3938
</Reference>
40-
<Reference Include="Common.Logging.Core, Version=2.2.0.0, Culture=neutral, PublicKeyToken=af08829b84f0328e, processorArchitecture=MSIL">
41-
<SpecificVersion>False</SpecificVersion>
39+
<Reference Include="Common.Logging.Core">
4240
<HintPath>..\packages\Common.Logging.Core.2.2.0\lib\net40\Common.Logging.Core.dll</HintPath>
4341
</Reference>
44-
<Reference Include="Raspberry.System, Version=1.2.0.0, Culture=neutral, processorArchitecture=MSIL">
45-
<SpecificVersion>False</SpecificVersion>
42+
<Reference Include="Raspberry.System">
4643
<HintPath>..\packages\Raspberry.System.1.3.0\lib\net40\Raspberry.System.dll</HintPath>
4744
</Reference>
48-
<Reference Include="System" />
49-
<Reference Include="System.Core" />
5045
</ItemGroup>
5146
<ItemGroup>
5247
<Compile Include="..\SharedAssemblyInfo.cs">
@@ -110,6 +105,7 @@
110105
<Compile Include="Sensors\VariableResistiveDividerConnection.cs" />
111106
<Compile Include="Sensors\Temperature\Tmp36\Tmp36Connection.cs" />
112107
<Compile Include="Sensors\ResistiveDivider.cs" />
108+
<Compile Include="Leds\GroveRgb\GroveRgbConnection.cs" />
113109
</ItemGroup>
114110
<ItemGroup>
115111
<ProjectReference Include="..\Raspberry.IO.InterIntegratedCircuit\Raspberry.IO.InterIntegratedCircuit.csproj">
@@ -125,10 +121,14 @@
125121
<Name>Raspberry.IO.SerialPeripheralInterface</Name>
126122
</ProjectReference>
127123
<ProjectReference Include="..\Raspberry.IO\Raspberry.IO.csproj">
128-
<Project>{ace64f17-87e5-43e7-97a0-bdde19059c61}</Project>
124+
<Project>{ACE64F17-87E5-43E7-97A0-BDDE19059C61}</Project>
129125
<Project>{D2E41147-5BF6-4109-A497-C76284F3C020}</Project>
130126
<Name>Raspberry.IO</Name>
131127
</ProjectReference>
128+
<ProjectReference Include="..\Raspberry.IO.GeneralPurpose\Raspberry.IO.GeneralPurpose.csproj">
129+
<Project>{281C71ED-C36D-408E-8BAA-75C381DC17E7}</Project>
130+
<Name>Raspberry.IO.GeneralPurpose</Name>
131+
</ProjectReference>
132132
</ItemGroup>
133133
<ItemGroup>
134134
<None Include="packages.config" />
@@ -143,4 +143,8 @@
143143
<Target Name="AfterBuild">
144144
</Target>
145145
-->
146+
<ItemGroup>
147+
<Folder Include="Leds\" />
148+
<Folder Include="Leds\GroveRgb\" />
149+
</ItemGroup>
146150
</Project>

Raspberry.IO.GeneralPurpose/FileGpioConnectionDriver.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ public class FileGpioConnectionDriver : IGpioConnectionDriver
2828
/// </summary>
2929
public FileGpioConnectionDriver()
3030
{
31-
if (!Board.Current.IsRaspberryPi)
32-
throw new NotSupportedException("FileGpioConnectionDriver is only supported on Raspberry Pi");
31+
if (System.Environment.OSVersion.Platform != PlatformID.Unix)
32+
throw new NotSupportedException("FileGpioConnectionDriver is only supported in Unix");
3333
}
3434

3535
#endregion

Raspberry.IO.GeneralPurpose/GpioConnectionSettings.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ public static IGpioConnectionDriver DefaultDriver
141141
var configurationSection = ConfigurationManager.GetSection("gpioConnection") as GpioConnectionConfigurationSection;
142142
return configurationSection != null && !String.IsNullOrEmpty(configurationSection.DriverTypeName)
143143
? (IGpioConnectionDriver) Activator.CreateInstance(Type.GetType(configurationSection.DriverTypeName, true))
144-
: new GpioConnectionDriver();
144+
: (Raspberry.Board.Current.IsRaspberryPi ? (IGpioConnectionDriver)new GpioConnectionDriver() : (IGpioConnectionDriver)new FileGpioConnectionDriver());
145145
}
146146
}
147147

UnitTests/Tests.Raspberry.IO.SerialPeripheralInterface/SpiTransferBufferSpecs.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ public void Should_the_control_structure_have_the_requested_wordsize() {
224224
[Test]
225225
public void Should_the_control_structure_have_the_requested_chip_select_change_value() {
226226
// ReSharper disable once UnreachableCode
227-
buffer.ControlStructure.ChipSelectChange.Should().Be(REQUESTED_CHIP_SELECT_CHANGE ? 1 : 0);
227+
buffer.ControlStructure.ChipSelectChange.Should().Be(REQUESTED_CHIP_SELECT_CHANGE ? (byte)1 : (byte)0);
228228
}
229229

230230
[Test]

0 commit comments

Comments
 (0)