forked from mrmorphic/hwio
-
Notifications
You must be signed in to change notification settings - Fork 0
/
module_odroidc1_analog.go
153 lines (122 loc) · 3.88 KB
/
module_odroidc1_analog.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
package hwio
import (
"errors"
"fmt"
"os"
"strconv"
)
// ODroidC1AnalogModule is a module for handling the Odroid C1 analog hardware, which is not generic.
type ODroidC1AnalogModule struct {
name string
analogInitialised bool
definedPins ODroidC1AnalogModulePinDefMap
openPins map[Pin]*ODroidC1AnalogModuleOpenPin
}
// Represents the definition of an analog pin, which should contain all the info required to open, close, read and write the pin
// using FS drivers.
type ODroidC1AnalogModulePinDef struct {
pin Pin
analogLogical int
}
// A map of GPIO pin definitions.
type ODroidC1AnalogModulePinDefMap map[Pin]*ODroidC1AnalogModulePinDef
type ODroidC1AnalogModuleOpenPin struct {
pin Pin
analogLogical int
// path to file representing analog pin
analogFile string
valueFile *os.File
}
func NewODroidC1AnalogModule(name string) (result *ODroidC1AnalogModule) {
result = &ODroidC1AnalogModule{name: name}
result.openPins = make(map[Pin]*ODroidC1AnalogModuleOpenPin)
return result
}
// Set options of the module. Parameters we look for include:
// - "pins" - an object of type ODroidC1AnalogModulePinDefMap
func (module *ODroidC1AnalogModule) SetOptions(options map[string]interface{}) error {
v := options["pins"]
if v == nil {
return fmt.Errorf("Module '%s' SetOptions() did not get 'pins' values", module.GetName())
}
module.definedPins = v.(ODroidC1AnalogModulePinDefMap)
return nil
}
// enable GPIO module. It doesn't allocate any pins immediately.
func (module *ODroidC1AnalogModule) Enable() error {
// once-off initialisation of analog
if !module.analogInitialised {
module.analogInitialised = true
// attempt to assign all pins to this module
for pin, _ := range module.definedPins {
// attempt to assign this pin for this module.
e := AssignPin(pin, module)
if e != nil {
return e
}
e = module.makeOpenAnalogPin(pin)
if e != nil {
return e
}
}
}
return nil
}
// disables module and release any pins assigned.
func (module *ODroidC1AnalogModule) Disable() error {
// Unassign any pins we may have assigned
for pin, _ := range module.definedPins {
// attempt to assign this pin for this module.
UnassignPin(pin)
}
// if there are any open analog pins, close them
for _, openPin := range module.openPins {
openPin.analogClose()
}
return nil
}
func (module *ODroidC1AnalogModule) GetName() string {
return module.name
}
func (module *ODroidC1AnalogModule) AnalogRead(pin Pin) (value int, e error) {
openPin := module.openPins[pin]
if openPin == nil {
return 0, errors.New("Pin is being read for analog value but has not been opened. Have you called PinMode?")
}
return openPin.analogGetValue()
}
func (module *ODroidC1AnalogModule) makeOpenAnalogPin(pin Pin) error {
p := module.definedPins[pin]
if p == nil {
return fmt.Errorf("Pin %d is not known to analog module", pin)
}
path := fmt.Sprintf("/sys/class/saradc/saradc_ch%d", p.analogLogical)
result := &ODroidC1AnalogModuleOpenPin{pin: pin, analogLogical: p.analogLogical, analogFile: path}
module.openPins[pin] = result
e := result.analogOpen()
if e != nil {
return e
}
return nil
}
func (op *ODroidC1AnalogModuleOpenPin) analogOpen() error {
// Open analog input file computed from the calculated path of actual analog files and the analog pin name
f, e := os.OpenFile(op.analogFile, os.O_RDONLY, 0666)
op.valueFile = f
return e
}
func (op *ODroidC1AnalogModuleOpenPin) analogGetValue() (int, error) {
var b []byte
b = make([]byte, 5)
n, e := op.valueFile.ReadAt(b, 0)
// if there's an error and no byte were read, quit now. If we didn't get all the bytes we asked for, which
// is generally the case, we will get an error as well but would have got some bytes.
if e != nil && n == 0 {
return 0, e
}
value, e := strconv.Atoi(string(b[:n-1]))
return value, e
}
func (op *ODroidC1AnalogModuleOpenPin) analogClose() error {
return op.valueFile.Close()
}