-
Notifications
You must be signed in to change notification settings - Fork 1
/
uncertainty.go
157 lines (132 loc) · 4.13 KB
/
uncertainty.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
package uncertainty // import uncertainty "github.com/awonak/UncertaintyGo"
import (
"log"
"machine"
"math"
)
const (
// GPIO mapping to Uncertainty panel.
CVInput = machine.ADC0
CV1 = machine.GPIO27
CV2 = machine.GPIO28
CV3 = machine.GPIO29
CV4 = machine.GPIO0
CV5 = machine.GPIO3
CV6 = machine.GPIO4
CV7 = machine.GPIO2
CV8 = machine.GPIO1
// Number of times to read analog input for an average reading.
ReadSamples = 25
// Calibrated average min read uint16 voltage within a 0-5v range.
MinCalibratedRead = 415
// Calibrated average max read uint16 voltage within a 0-5v range.
MaxCalibratedRead = 29582
// Upper limit of voltage read by the cv input.
MaxReadVoltage float32 = 5.0
// Min and Max voltage range available to be used by the cv output.
MinVoltage float32 = 0.0
MaxVoltage float32 = 5.0
// The default PWM frequncy is 100khz (1 second in nanoseconds / 100k).
// This results in a period of 10,000ns per cycle.
defaultPeriod uint64 = 1e9 / 100_000
)
var (
// The array of 8 configured cv outputs
Outputs [8]*Output
// Package private variable for the cv input peripherial.
cvInput machine.ADC
)
// PWM is the interface necessary for configuring a cv output for PWM.
type PWM interface {
Configure(config machine.PWMConfig) error
Channel(pin machine.Pin) (channel uint8, err error)
Top() uint32
Set(channel uint8, value uint32)
SetPeriod(period uint64) error
}
// Output represents a single cv output.
type Output struct {
Pin machine.Pin
PWM PWM
ch uint8
}
func NewOutput(pin machine.Pin, pwm PWM) *Output {
// Configure the PWM with the default period.
err := pwm.Configure(machine.PWMConfig{
Period: defaultPeriod,
})
if err != nil {
log.Fatalf("pwm Configure(%v) error: %v", pin, err.Error())
}
ch, err := pwm.Channel(pin)
if err != nil {
log.Fatalf("pwm Channel(%v) error: %v", pin, err.Error())
}
return &Output{pin, pwm, ch}
}
// High will set the current output to a high voltage of roughly 5v.
func (o *Output) High() {
o.PWM.Set(o.ch, o.PWM.Top())
}
// Low will set the current output to a low voltage of roughly 0v.
func (o *Output) Low() {
o.PWM.Set(o.ch, 0)
}
// Voltage sets the current output voltage within a range of 0.0 to 5.0.
func (o *Output) Voltage(v float32) {
v = Clamp(v, MinVoltage, MaxVoltage)
cv := (v / MaxVoltage) * float32(o.PWM.Top())
o.PWM.Set(o.ch, uint32(cv))
}
// Value sets the current output voltage within a range of 0 to 32767.
func (o *Output) Value(v int) {
v = Clamp(v, 0, math.MaxInt16)
o.PWM.Set(o.ch, uint32(v))
}
// Read will return the cv input scaled to 0v-5v as an int with 0 for 0v and 32767 for 5v.
func Read() int {
var sum int
for i := 0; i < ReadSamples; i++ {
read := int(cvInput.Get()) - math.MaxInt16
if read < 0 {
read = 0
}
sum += read
}
return sum / ReadSamples
}
// ReadVoltage will return the cv input scaled to 0v-5v as a float with 0.0 for 0v and 5.0 for 5v.
func ReadVoltage() float32 {
read := Read()
return MaxReadVoltage * (float32(read-MinCalibratedRead) / float32(MaxCalibratedRead-MinCalibratedRead))
}
type clampable interface {
~uint8 | ~uint16 | ~int | ~float32
}
// Clamp will return the given value within the given high and low range.
func Clamp[V clampable](value, low, high V) V {
if value >= high {
return high
}
if value <= low {
return low
}
return value
}
func init() {
// Initialize the cv input GPIO as an analog input.
machine.InitADC()
cvInput = machine.ADC{Pin: CVInput}
cvInput.Configure(machine.ADCConfig{})
// Create 8 configured outputs with Pin and PWM configurations per output.
Outputs = [8]*Output{
NewOutput(CV1, machine.PWM5), // GPIO27 peripherals: PWM5 channel B
NewOutput(CV2, machine.PWM6), // GPIO28 peripherals: PWM6 channel A
NewOutput(CV3, machine.PWM6), // GPIO29 peripherals: PWM6 channel B
NewOutput(CV4, machine.PWM0), // GPIO0 peripherals: PWM0 channel A
NewOutput(CV5, machine.PWM1), // GPIO3 peripherals: PWM1 channel B
NewOutput(CV6, machine.PWM2), // GPIO4 peripherals: PWM2 channel A
NewOutput(CV7, machine.PWM1), // GPIO2 peripherals: PWM1 channel A
NewOutput(CV8, machine.PWM0), // GPIO1 peripherals: PWM0 channel B
}
}