This repository has been archived by the owner on Sep 20, 2023. It is now read-only.
/
sn3218.go
141 lines (122 loc) · 3.4 KB
/
sn3218.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
// Copyright 2018 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
package sn3218
import (
"errors"
"periph.io/x/periph/conn/i2c"
)
const (
i2cAddress = 0x54
cmdEnableOutput = 0x00
cmdSetBrightnessValues = 0x01
cmdEnableLeds = 0x13
cmdUpdate = 0x16
cmdReset = 0x17
)
// Dev is a handler to sn3218 controller.
type Dev struct {
i2c i2c.Dev
on [18]bool
brightness [18]byte
}
// New returns a handle to a SN3218 LED driver.
func New(bus i2c.Bus) (*Dev, error) {
d := &Dev{
i2c: i2c.Dev{Bus: bus, Addr: i2cAddress},
}
if err := d.reset(); err != nil {
return nil, err
}
return d, nil
}
// Halt resets the registers and switches the driver off.
func (d *Dev) Halt() error {
return d.reset()
}
// WakeUp returns from sleep mode and switches the channels according to the states in the register of SN3218.
func (d *Dev) WakeUp() error {
_, err := d.i2c.Write([]byte{cmdEnableOutput, 0x01})
return err
}
// Sleep sends SN3218 to sleep mode while keeping the states in the registers.
func (d *Dev) Sleep() error {
_, err := d.i2c.Write([]byte{cmdEnableOutput, 0x00})
return err
}
// GetState returns the state (on/off) and the brightness (0..255) of the
// Channel 0..17.
func (d *Dev) GetState(channel int) (bool, byte, error) {
if channel < 0 || channel >= 18 {
return false, 0, errors.New("channel number out of range 0..17")
}
return d.on[channel], d.brightness[channel], nil
}
// Switch switched the channel (0..18) to state (on/off).
func (d *Dev) Switch(channel int, state bool) error {
if channel < 0 || channel >= 18 {
return errors.New("channel number out of range 0..17")
}
d.on[channel] = state
return d.updateStates()
}
// SwitchAll switches all channels according to the state (on/off).
func (d *Dev) SwitchAll(state bool) error {
for i := 0; i < 18; i++ {
d.on[i] = state
}
return d.updateStates()
}
// Brightness sets the brightness of led (0..17) to value (0..255).
func (d *Dev) Brightness(channel int, value byte) error {
if channel < 0 || channel >= 18 {
return errors.New("channel number out of range 0..17")
}
d.brightness[channel] = value
return d.updateBrightness()
}
// BrightnessAll sets the brightness of all channels to the value (0..255).
func (d *Dev) BrightnessAll(value byte) error {
for i := 0; i < 18; i++ {
d.brightness[i] = value
}
return d.updateBrightness()
}
// Reset resets the registers to the default values.
func (d *Dev) reset() error {
_, err := d.i2c.Write([]byte{cmdReset, 0xFF})
d.on = [18]bool{}
d.brightness = [18]byte{}
return err
}
func (d *Dev) stateArrayToInt() uint {
var result uint
for i := uint(0); i < uint(18); i++ {
state := uint(1)
if !d.on[i] {
state = uint(0)
}
result |= (state << i)
}
return result
}
func (d *Dev) update() error {
_, err := d.i2c.Write([]byte{cmdUpdate, 0xFF})
return err
}
func (d *Dev) updateStates() error {
mask := d.stateArrayToInt()
cmd := [...]byte{cmdEnableLeds, byte(mask & 0x3F), byte((mask >> 6) & 0x3F), byte((mask >> 12) & 0x3F)}
if _, err := d.i2c.Write(cmd[:]); err != nil {
return err
}
return d.update()
}
func (d *Dev) updateBrightness() error {
cmd := [19]byte{cmdSetBrightnessValues}
copy(cmd[1:], d.brightness[:])
if _, err := d.i2c.Write(cmd[:]); err != nil {
return err
}
return d.update()
}