-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
130 lines (120 loc) · 2.83 KB
/
main.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
/*
Infrared
A library for interacting with infrared remote controls which use the NEC protocol from a Raspberry-Pi
*/
package infrared
import (
"errors"
"fmt"
"math/big"
"time"
"github.com/stianeikeland/go-rpio/v4"
)
// Only used internally
type pulse struct {
Value uint8
Length int64
}
// Main module struct
type IfScanner struct {
Pin rpio.Pin
Initialized bool
Scanning bool
}
var (
Scanner = IfScanner{
Pin: 0,
Initialized: false,
Scanning: false,
}
)
var (
ErrInitialized = errors.New("cannot initialize scanner: scanner is already initialized")
ErrNotInitialized = errors.New("cannot scan: not initialized: use Setup() before scanning")
ErrAlreadyScanning = errors.New("cannot concurrently scan: wait until scanning is finished before starting another scan")
ErrCannotInitialize = errors.New("failed to initialize: hardware failure")
)
// Functions
// Scans for received codes, this method is blocking
// Can return errors ErrNotInitialized or ErrAlreadyScanning
// Returns the received code as a hexadecimal string
func (scanner *IfScanner) Scan() (string, error) {
if scanner.Scanning {
return "", ErrAlreadyScanning
}
if !scanner.Initialized {
return "", ErrNotInitialized
}
scanner.Scanning = true
var count1 int = 0
var command []pulse = make([]pulse, 0)
var binary = make([]byte, 0)
binary = append(binary, 1)
var previousValue uint8 = 0
var value = uint8(scanner.Pin.Read())
for value == 1 {
value = uint8(scanner.Pin.Read())
time.Sleep(time.Microsecond * 100)
}
startTime := time.Now()
for {
time.Sleep(time.Nanosecond * 50)
if value != previousValue {
now := time.Now()
pulseLength := now.Sub(startTime)
startTime = now
command = append(command, pulse{Value: previousValue, Length: pulseLength.Microseconds()})
}
if value == 1 {
count1 += 1
} else {
count1 = 0
}
if count1 > 10000 {
break
}
previousValue = value
value = uint8(scanner.Pin.Read())
}
for _, item := range command {
if item.Value == 1 {
if item.Length > 1000 {
binary = append(binary, 0)
binary = append(binary, 1)
} else {
binary = append(binary, 0)
}
}
}
if len(binary) > 34 {
binary = binary[:34]
}
res := ""
for _, v := range binary {
if v == 1 {
res += "1"
} else {
res += "0"
}
}
result := new(big.Int)
result.SetString(res, 2)
scanner.Scanning = false
return fmt.Sprintf("%x", result), nil
}
// Initializes the scanner and binds it to a certain pin
// Example: `scanner.Setup(4)`
// This function has to be called before using `scanner.Scan()`
func (scanner *IfScanner) Setup(pinNumber uint8) error {
if scanner.Initialized {
return ErrInitialized
}
if err := rpio.Open(); err != nil {
return err
}
// Set the pin to input
scanner.Pin = rpio.Pin(pinNumber)
scanner.Pin.Input()
scanner.Initialized = true
return nil
}