forked from tomnz/button-shim-go
/
led.go
82 lines (69 loc) · 1.89 KB
/
led.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
package buttonshim
// SetColor sets the RGB pixel to the given color.
func (d *Driver) SetColor(r, g, b byte) {
d.ledColor <- color{r, g, b}
}
// SetBrightness sets the brightness of the pixel.
func (d *Driver) SetBrightness(brightness byte) {
// TODO: Use the actual brightness range of the LED IC
// https://github.com/pimoroni/button-shim/issues/3
d.brightness = brightness
}
// updateLed continually waits for new color signals, building and sending a
// corresponding command to the LED for each.
// Designed to be called in a long-running goroutine.
func (d *Driver) updateLed() {
for {
color := <-d.ledColor
pinQueue := newQueue()
pinQueue.writeByte(0)
pinQueue.writeByte(0)
pinQueue.writeByte(0xef)
pinQueue.writeByte(d.options.gamma[d.scaleVal(color.b)])
pinQueue.writeByte(d.options.gamma[d.scaleVal(color.g)])
pinQueue.writeByte(d.options.gamma[d.scaleVal(color.r)])
pinQueue.writeByte(0)
pinQueue.writeByte(0)
bytes := pinQueue.bytes
msg := []byte{regOutput}
msg = append(msg, bytes...)
if err := d.i2c.Tx(msg, nil); err != nil {
panic(err)
}
}
}
func (d *Driver) scaleVal(val byte) byte {
return byte(uint16(val) * uint16(d.brightness) / 255)
}
// TODO: Revisit all the below... Unnecessarily messy
// queue provides helper functions for constructing a message to transmit to the LED.
type queue struct {
bytes []byte
}
func newQueue() *queue {
return &queue{bytes: []byte{0}}
}
func (q *queue) next() {
if len(q.bytes) == 0 {
q.bytes = []byte{0}
} else {
q.bytes = append(q.bytes, q.bytes[len(q.bytes)-1])
}
}
func (q *queue) setBit(pin, value byte) {
if value != 0 {
q.bytes[len(q.bytes)-1] |= (1 << pin)
} else {
q.bytes[len(q.bytes)-1] &= ^(1 << pin)
}
}
func (q *queue) writeByte(b byte) {
for i := 0; i < 8; i++ {
q.next()
q.setBit(pinLedClock, 0)
q.setBit(pinLedData, b&0x80) // 0b10000000
q.next()
q.setBit(pinLedClock, 1)
b <<= 1
}
}