-
Notifications
You must be signed in to change notification settings - Fork 0
/
registers.go
351 lines (295 loc) · 7.95 KB
/
registers.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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
package nrf
import "strconv"
func (d *Device) byteReg(addr byte) byte {
var buf [1]byte
d.Reg(addr, buf[:])
return buf[0]
}
type Status byte
const (
FullTx Status = 1 << iota // Tx FIFO full flag.
_
_
_
MaxRT // Maximum number of Tx retransmits interrupt.
TxDS // Data Sent Tx FIFO interrupt.
RxDR // Data Ready Rx FIFO interrupt.
)
// RxPipe returns data pipe number for the payload available for reading from
// RxFifo or -1 if RxFifo is empty
func (s Status) RxPipe() int {
n := int(s) & 0x0e
if n == 0x0e {
return -1
}
return n >> 1
}
func flags(f string, mask, b byte) string {
buf := make([]byte, len(f))
m := byte(0x80)
for i := range buf {
if f[i] == '+' {
for mask&m == 0 {
m >>= 1
}
if b&m == 0 {
buf[i] = '-'
} else {
buf[i] = '+'
}
m >>= 1
} else {
buf[i] = f[i]
}
}
return string(buf)
}
func (s Status) String() string {
return flags("RxDR+ TxDS+ MaxRT+ FullTx+ RxPipe:", 0x71, byte(s)) +
strconv.Itoa(s.RxPipe())
}
type Config byte
const (
PrimRx Config = 1 << iota // Rx/Tx control 1: PRX, 0: PTX.
PwrUp // 1: power up, 0: power down.
CRCO // CRC encoding scheme 0: one byte, 1: two bytes.
EnCRC // Enable CRC. Force 1 if one of bits in AA is 1.
MaskMaxRT // If 1 then mask interrupt caused by MaxRT.
MaskTxDS // If 1 then mask interrupt caused by TxDS.
MaskRxDR // If 1 then mask interrupt caused by RxDR.
)
func (c Config) String() string {
return flags(
"Mask(RxDR+ TxDS+ MaxRT+) EnCRC+ CRCO+ PwrUp+ PrimRx+",
0x7f, byte(c),
)
}
// Config returns value of CONFIG register.
func (d *Device) Config() Config {
return Config(d.byteReg(0))
}
// SetCfg sets value of CONFIG register.
func (d *Device) SetCfg(c Config) {
d.SetReg(0, byte(c))
}
// Pipe is a bitfield that represents nRF24L01+ Rx data pipes.
type Pipe byte
const (
P0 Pipe = 1 << iota
P1
P2
P3
P4
P5
PAll = P0 | P1 | P2 | P3 | P4 | P5
)
func (p Pipe) String() string {
return flags("P5+ P4+ P3+ P2+ P1+ P0+", 0x3f, byte(p))
}
// AA returns value of EN_AA (Enable ‘Auto Acknowledgment’ Function) register.
func (d *Device) AA() Pipe {
return Pipe(d.byteReg(1))
}
// SetAA sets value of EN_AA (Enable ‘Auto Acknowledgment’ Function) register.
func (d *Device) SetAA(p Pipe) {
d.SetReg(1, byte(p))
}
// RxAE returns value of EN_RXADDR (Enabled RX Addresses) register.
func (d *Device) RxAE() Pipe {
return Pipe(d.byteReg(2))
}
// SetRxAE sets value of EN_RXADDR (Enabled RX Addresses) register.
func (d *Device) SetRxAE(p Pipe) {
d.SetReg(2, byte(p))
}
// AW returns value of SETUP_AW (Setup of Address Widths) register increased
// by two.
func (d *Device) AW() int {
return int(d.byteReg(3)) + 2
}
// SetAW sets value of SETUP_AW (Setup of Address Widths) register to (alen-2).
func (d *Device) SetALen(alen int) {
if alen < 3 || alen > 5 {
panic("alen<3 || alen>5")
}
d.SetReg(3, byte(alen-2))
}
// Retr returns value of SETUP_RETR (Setup of Automatic Retransmission)
// register converted to number of retries and delay betwee retries.
func (d *Device) Retr() (cnt, dlyus int) {
b := d.byteReg(4)
cnt = int(b & 0xf)
dlyus = (int(b>>4) + 1) * 250
return
}
// SetRetr sets value of SETUP_RETR (Setup of Automatic Retransmission)
// register using cnt as number of retries and dlyus as delay betwee retries.
func (d *Device) SetRetr(cnt, dlyus int) {
if uint(cnt) > 15 {
panic("cnt<0 || cnt>15")
}
if dlyus < 250 || dlyus > 4000 {
panic("dlyus<250 || dlyus>4000")
}
d.SetReg(4, byte((dlyus/250-1)<<4|cnt))
}
// Ch returns value of RF_CH (RF Channel) register.
func (d *Device) Ch() int {
return int(d.byteReg(5))
}
// SetCh sets value of RF_CH (RF Channel) register.
func (d *Device) SetCh(ch int) {
if uint(ch) > 127 {
panic("ch<0 || ch>127")
}
d.SetReg(5, byte(ch))
}
type RF byte
const (
LNAHC RF = 1 << iota // (nRF24L01.LNA_HCURR) Rx LNA gain 0: -1.5dB,-0.8mA.
_
_
DRHigh // (RF_DR_HIGH) Select high speed data rate 0: 1Mbps, 1: 2Mbps.
Lock // (PLL_LOCK) Force PLL lock signal. Only used in test.
DRLow // (RF_DR_LOW) Set RF Data Rate to 250kbps.
_
Wave // (CONT_WAVE) Enables continuous carrier transmit when 1.
)
// Pwr returns RF output power in Tx mode [dBm].
func (rf RF) Pwr() int {
return 3*int(rf&6) - 18
}
func Pwr(dbm int) RF {
switch {
case dbm < -18:
dbm = -18
case dbm > 0:
dbm = 0
}
return RF((18+dbm)/3) & 6
}
func (rf RF) String() string {
return flags("Wave+ DRLow+ Lock+ DRHigh+ LNAHC+ Pwr:", 0xb9, byte(rf)) +
strconv.Itoa(rf.Pwr()) + "dBm"
}
// RF returns value of RF_SETUP register.
func (d *Device) RF() RF {
return RF(d.byteReg(6))
}
// RF sets value of RF_SETUP register.
func (d *Device) SetRF(rf RF) {
d.SetReg(6, byte(rf))
}
// Clear clears specified bits in STATUS register.
func (d *Device) Clear(stat Status) {
d.SetReg(7, byte(stat))
}
// TxCnt returns values of PLOS and ARC counters from OBSERVE_TX register.
func (d *Device) TxCnt() (plos, arc int) {
b := d.byteReg(8)
arc = int(b & 0xf)
plos = int(b >> 4)
return
}
// RPD returns value of RPD (Received Power Detector) register (is RP > -64dBm).
// In case of nRF24L01 it returns value of.CD (Carrier Detect) register.
func (d *Device) RPD() bool {
return d.byteReg(9)&1 != 0
}
func checkPN(pn int) {
if uint(pn) > 5 {
panic("pn<0 || pn>5")
}
}
func checkAddr(addr []byte) {
if len(addr) > 5 {
panic("len(addr)>5")
}
}
func checkPNA(pn int, addr []byte) {
checkPN(pn)
checkAddr(addr)
if pn > 1 && len(addr) > 1 {
panic("pn>1 && len(addr)>1")
}
}
// RxAddr reads address assigned to Rx pipe pn into addr.
func (d *Device) RxAddr(pn int, addr []byte) {
checkPNA(pn, addr)
d.Reg(byte(0xa+pn), addr)
}
// RxAddr0 returns least significant byte of address assigned to Rx pipe pn.
func (d *Device) RxAddr0(pn int) byte {
checkPN(pn)
return d.byteReg(byte(0xa + pn))
}
// SetRxAddr sets address assigned to Rx pipe pn to addr.
func (d *Device) SetRxAddr(pn int, addr ...byte) {
checkPNA(pn, addr)
d.SetReg(byte(0xa+pn), addr...)
}
// TxAddr reads value of TX_ADDR (Transmit address) into addr.
func (d *Device) TxAddr(addr []byte) {
checkAddr(addr)
d.Reg(0x10, addr)
}
// SetTxAddr sets value of TX_ADDR (Transmit address).
func (d *Device) SetTxAddr(addr ...byte) {
checkAddr(addr)
d.SetReg(0x10, addr...)
}
// RxPW returns Rx payload width set for pipe pn.
func (d *Device) RxPW(pn int) int {
checkPN(pn)
return int(d.byteReg(byte(0x11+pn))) & 0x3f
}
// SetRxPW sets Rx payload width for pipe pn.
func (d *Device) SetRxPW(pn, pw int) {
checkPN(pn)
if uint(pw) > 32 {
panic("pw<0 || pw>32")
}
d.SetReg(byte(0x11+pn), byte(pw))
}
type FIFO byte
const (
RxEmpty FIFO = 1 << iota // 1: Rx FIFO empty, 0: Data in Rx FIFO.
RxFull // 1: Rx FIFO full, 0: Avail.locations in Rx FIFO.
_
_
TxEmpty // 1: Tx FIFO empty, 0: Data in Tx FIFO.
TxFull // 1: Tx FIFO full, 0: Available locations in Tx FIFO.
TxReuse // 1: Reuse last transmitted payload.
)
func (f FIFO) String() string {
return flags("TxReuse+ TxFull+ TxEmpty+ RxFull+ RxEmpty+", 0x73, byte(f))
}
// FIFO returns value of FIFO_STATUS register.
func (d *Device) FIFO() FIFO {
return FIFO(d.byteReg(0x17))
}
// DynPD returns value of DYNPD (Enable dynamic payload length) register.
func (d *Device) DynPD() Pipe {
return Pipe(d.byteReg(0x1c))
}
// SetDynPD sets value of DYNPD (Enable dynamic payload length) register.
func (d *Device) SetDynPD(p Pipe) {
d.SetReg(0x1c, byte(p))
}
type Feature byte
const (
DynAck Feature = 1 << iota // 1: Enables the W_TX_PAYLOAD_NOACK command.
AckPay // 1: Enables payload with ACK
DPL // 1: Enables dynamic payload length
)
func (f Feature) String() string {
return flags("DPL+ AckPay+ DynAck+", 7, byte(f))
}
// Feature returns value of FEATURE register.
func (d *Device) Feature() Feature {
return Feature(d.byteReg(0x1d))
}
// SetFeature sets value of FEATURE register.
func (d *Device) SetFeature(f Feature) {
d.SetReg(0x1d, byte(f))
}