-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathexample_test.go
218 lines (197 loc) · 5 KB
/
example_test.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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
package ring_test
import (
"bufio"
"fmt"
"image/color"
"log"
"math"
"os"
"sync"
"time"
"github.com/cgxeiji/ring"
)
func Example() {
// Initialize the ring.
r, err := ring.New(&ring.Options{
LedCount: 12, // adjust this to the number of LEDs you have
MaxBrightness: 180, // value from 0 to 255
})
r.Offset(-math.Pi / 3) // you can set a rotation offset for the ring
if err != nil {
log.Fatal(err)
}
// Make sure to properly close the ring.
defer r.Close()
// Create a new layer. This will be a static white background.
bg, err := ring.NewLayer(&ring.LayerOptions{
Resolution: 1, // set to 1 pixel because it is a uniform color background
ContentMode: ring.ContentScale, // this scales the pixel to the whole ring
})
if err != nil {
log.Fatal(err)
}
// Set all pixels of the layer to white.
bg.SetAll(color.White)
// Add the layer to the ring.
r.AddLayer(bg)
// Create a mask layer. This will fade the background.
bgMask, err := ring.NewLayer(&ring.LayerOptions{
Resolution: 1, // set to 1 pixel because it is a uniform mask
})
if err != nil {
log.Fatal(err)
}
r.AddLayer(bgMask)
// Render the ring.
if err := r.Render(); err != nil {
log.Fatal(err)
}
// Wait for 1 second to see the beauty of the freshly rendered layer.
time.Sleep(1 * time.Second)
// Create another layer. This will set 3 pixels to red, green and blue,
// and a hidden purple pixel with transparency of 200, that rotate
// counter-clockwise.
triRotate, err := ring.NewLayer(&ring.LayerOptions{
Resolution: 48,
})
if err != nil {
log.Fatal(err)
}
// We can immediately add the layer to the ring. By default, new layers
// are initialized with transparent pixels. The new layer is added on top
// of the previous layers.
r.AddLayer(triRotate)
// Set the colors.
triRotate.SetPixel(0, color.NRGBA{128, 0, 0, 200}) // dark red
triRotate.SetPixel(3, color.NRGBA{0, 128, 0, 200}) // dark green
triRotate.SetPixel(6, color.NRGBA{0, 0, 128, 200}) // dark blue
triRotate.SetPixel(24, color.NRGBA{128, 0, 255, 200}) // purple
// Render the ring.
if err := r.Render(); err != nil {
log.Fatal(err)
}
// Wait for 1 second to see the beauty of both layers.
time.Sleep(1 * time.Second)
// Create another layer. This will set a pixel that will blink every 500ms.
blink, err := ring.NewLayer(&ring.LayerOptions{
Resolution: 3, // we are going to set the 3rd pixel (index: 2) to blink
ContentMode: ring.ContentCrop, // this crops the layer to avoid repetition
})
if err != nil {
log.Fatal(err)
}
// Add the layer to the ring. This will be on top of the previous two
// layers.
r.AddLayer(blink)
// Set the color. We can use any variable that implements the color.Color
// interface.
blink.SetPixel(2, color.CMYK{255, 0, 0, 0})
// Render the ring.
if err := r.Render(); err != nil {
log.Fatal(err)
}
// Wait for 1 second and enjoy the view.
time.Sleep(1 * time.Second)
/* ANIMATION SETUP */
done := make(chan struct{}) // this will cancel all animations
render := make(chan struct{}) // this will request a concurrent-safe render
var ws sync.WaitGroup // this makes sure we close all goroutines
/* render goroutine */
ws.Add(1)
go func() {
defer ws.Done()
for {
select {
case <-done:
return
case <-render:
if err := r.Render(); err != nil {
log.Fatal(err)
}
}
}
}()
/* fading goroutine */
ws.Add(1)
go func() {
defer ws.Done()
c := color.NRGBA{0, 0, 0, 0}
step := uint8(5)
for {
for a := uint8(0); a < 255; a += step {
c.A = a
bgMask.SetAll(c)
select {
case <-done:
return
case render <- struct{}{}:
}
time.Sleep(20 * time.Millisecond)
}
for a := uint8(255); a > 0; a -= step {
c.A = a
bgMask.SetAll(c)
select {
case <-done:
return
case render <- struct{}{}:
}
time.Sleep(20 * time.Millisecond)
}
}
}()
/* rotation goroutine */
ws.Add(1)
go func() {
defer ws.Done()
for {
for a := 0.0; a < math.Pi*2; a += 0.01 {
triRotate.Rotate(a)
select {
case <-done:
return
case render <- struct{}{}:
}
time.Sleep(20 * time.Millisecond)
}
}
}()
/* blinking goroutine */
ws.Add(1)
go func() {
defer ws.Done()
c := color.CMYK{255, 0, 0, 0}
timer := time.NewTicker(500 * time.Millisecond)
on := true
for {
select {
case <-done:
return
case <-timer.C:
if on {
blink.SetPixel(2, color.Transparent)
on = false
} else {
blink.SetPixel(2, c)
on = true
}
select {
case <-done:
return
case render <- struct{}{}:
}
}
}
}()
fmt.Println("Press [ENTER] to exit")
stdin := bufio.NewReader(os.Stdin)
stdin.ReadString('\n')
// Stop all animations
close(done)
// Wait for goroutines to exit
ws.Wait()
// Remember that we called a defer `r.Close()` at the beginning of the
// code. This will turn off the LEDs and clean up the resources used by the
// ring before exiting. Otherwise, the ring will stay on with the latest
// render.
}