-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrainbow.go
150 lines (128 loc) · 4.08 KB
/
rainbow.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
package dmxthing
import (
"fmt"
"github.com/scottlaird/udmx"
)
// RainbowLightP5 controls a Quasar Science Rainbow light bar (the
// original model, not Rainbow 2 or Double Rainbow), in DMX profile 5.
// In this mode, the light listens on two DMX addresses; the lower one
// is an 8-bit brightness and the upper one is an 8-bit color
// temperature.
type RainbowLightP5 struct {
dmx *udmx.Device
dmxid uint16
}
// NewRainbowLightP5 creates a new RainbowLightP5 using a
// specific DMX controller and at a specific DMX address.
func NewRainbowLightP5(dmx *udmx.Device, dmxid uint16) *RainbowLightP5 {
a := &RainbowLightP5{
dmx: dmx,
dmxid: dmxid,
}
return a
}
// SetBrightness sets the brightness of the DMX light.
func (a *RainbowLightP5) SetBrightness(b int) {
brightness := uint16(float64(b) * 2.55) // Input range is 0-100, output should be 0-255.
_ = a.dmx.Set(a.dmxid, brightness)
}
// SetColorTemp sets the color temperature of the DMX light.
// The temperature should be specified in degrees K.
func (a *RainbowLightP5) SetColorTemp(c int) {
// Map c=2000..6000 linearly onto 1..255.
v := uint16(((float32(c)-2000)*254/4000 + 1))
fmt.Printf("Setting color temp to %d for %dK\n", v, c)
if v > 255 {
// Entertainingly, sending weird enough values to UDMX
// can crash the controller, so we're better off
// panicking here than crashing it and requireing a
// the controller to be power-cycled.
panic("Color temp out of range!")
}
_ = a.dmx.Set(a.dmxid+1, v)
}
func (a *RainbowLightP5) MinColorTemp() int {
return 2000
}
func (a *RainbowLightP5) MaxColorTemp() int {
return 6000
}
// RainbowLightP12 controls a Quasar Science Rainbow light bar (the
// original model, not Rainbow 2 or Double Rainbow), in DMX profile
// 12. In this mode, the light listens to a block of 12 DMX
// addresses:
//
// dmxid+0: intensity (high 8 bits)
//
// +1: intensity (low 8 bits)
// +2: color temp (2000k to 6000k mapped onto 0..255)
// +3: plus/minus green
// +4: crossfade fraction color/rgb high
// +5: crossfade fraction color/rgb low
// +6: red
// +7: green
// +8: blue
// +9: FX
// +10: FX rate
// +11: FX size
//
// Right now, only intensity and color temp are used, but various
// special effect settings will be exposed in the future.
type RainbowLightP12 struct {
dmx *udmx.Device
dmxid uint16
}
// NewRainbowLightP12 creates a new RainbowLightP12 using a
// specific DMX controller and at a specific DMX address.
func NewRainbowLightP12(dmx *udmx.Device, dmxid uint16) *RainbowLightP12 {
a := &RainbowLightP12{
dmx: dmx,
dmxid: dmxid,
}
return a
}
// SetBrightness sets the brightness of the DMX light.
func (a *RainbowLightP12) SetBrightness(b int) {
// In this mode, the light uses 16-bit brightness. For my
// use, I care more about the dimmest possible setting than I
// do about fine control at the high/middle end, so I'm going
// to map the 0..100 input onto the middle 8 bits for now.
v := b * 16
l := uint16(v & 0xff)
h := uint16(v >> 8)
_ = a.dmx.Set(a.dmxid, h)
_ = a.dmx.Set(a.dmxid+1, l)
}
// SetColorTemp sets the color temperature of the DMX light.
// The temperature should be specified in degrees K.
func (a *RainbowLightP12) SetColorTemp(c int) {
// Map c=2000..6000 linearly onto 1..255.
v := uint16(((float32(c)-2000)*254/4000 + 1))
fmt.Printf("Setting color temp to %d for %dK\n", v, c)
if v > 255 {
// Entertainingly, sending weird enough values to UDMX
// can crash the controller, so we're better off
// panicking here than crashing it and requireing a
// the controller to be power-cycled.
panic("Color temp out of range!")
}
_ = a.dmx.Set(a.dmxid+2, v)
}
// SetFX sets the light's FX setting.
func (a *RainbowLightP12) SetFX(x int) {
_ = a.dmx.Set(a.dmxid+9, uint16(x))
}
// SetFXRate sets the light's FX rate.
func (a *RainbowLightP12) SetFXRate(x int) {
_ = a.dmx.Set(a.dmxid+10, uint16(x))
}
// SetFXSize sets the light's FX size.
func (a *RainbowLightP12) SetFXSize(x int) {
_ = a.dmx.Set(a.dmxid+11, uint16(x))
}
func (a *RainbowLightP12) MinColorTemp() int {
return 2000
}
func (a *RainbowLightP12) MaxColorTemp() int {
return 6000
}