-
Notifications
You must be signed in to change notification settings - Fork 33
/
Copy pathAS3935_Wire.cpp
455 lines (410 loc) · 9.59 KB
/
AS3935_Wire.cpp
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
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
#include <Wire.h>
#include "AS3935.h"
/*
a line-by-line port of https://github.com/pcfens/particle-as3935/
an exercise for me to write a library.
*/
/**
Constructor.
@param address I2C address of AS3935.
@param interruptPin pin that is tied to IRQ pin of AS3935.
*/
AS3935::AS3935(uint8_t address, uint8_t interruptPin)
{
_address = address;
_interruptPin = interruptPin;
}
AS3935::AS3935::~AS3935()
{
}
/**
Begin using the object with default SDA, and SCL pin numbers.
*/
void AS3935::begin()
{
begin((int) _defaultSDA, (int) _defaultSCL);
}
/**
Begin using the object
- Begin wire
- Enable interrupt pin as INPUT
- Disable Oscillators on interrupt pin.
@param sda SDA pin
@param scl SCL pin
*/
void AS3935::begin(int sda, int scl)
{
Wire.begin(sda, scl);
//pinMode(_interruptPin, INPUT);
disableOscillators();
}
/**
Find the shift required to make the mask use the LSB.
@param mask The mask to find the shift of
@return The number of bit positions to shift the mask
*/
uint8_t AS3935::_getShift(uint8_t mask)
{
uint8_t i = 0;
for (i = 0; ~mask & 1; i++)
mask >>= 1;
return i;
}
/**
Read a byte from a register.
@param reg The register address
@return The value in the register
*/
uint8_t AS3935::readRegister(uint8_t reg)
{
uint8_t v;
Wire.beginTransmission(_address);
Wire.write(reg);
Wire.endTransmission(false);
Wire.requestFrom((int)_address, 1);
v = Wire.read();
return v;
}
/**
Read a byte from a register, return a masked and shifted value
@param reg The register address
@param mask The mask to use when shifting contents
@return An uint8_t with the right most bits containing the masked and
shifted contents of the requested register
*/
uint8_t AS3935::readRegisterWithMask(uint8_t reg, uint8_t mask)
{
uint8_t v;
v = readRegister(reg) & mask;
return (v >> _getShift(mask));
}
/**
Write a masked value to register reg, preserving other bits
@param reg The register address
@param mask The bitmask to mask
@param value The value to write to the register
*/
void AS3935::writeRegisterWithMask(uint8_t reg, uint8_t mask, uint8_t value)
{
uint8_t registerValue;
registerValue = readRegister(reg);
registerValue &= ~(mask);
registerValue |= ((value << (_getShift(mask))) & mask);
Wire.beginTransmission(_address);
Wire.write(reg);
Wire.write(registerValue);
Wire.endTransmission();
}
/**
Write value to register reg.
@param reg the register address to write value to.
@param value the value to write to the register.
*/
void AS3935::writeRegister(uint8_t reg, uint8_t value)
{
writeRegisterWithMask(reg, 0xff, value);
}
/**
Sets all registers in default mode
*/
void AS3935::setDefault(void)
{
writeRegister(0x3c, 0x96);
}
/**
Calibrates the internal RC Oscillators automatically
*/
void AS3935::calibrateRCO(void)
{
writeRegister(0x3D, 0x96);
}
/**
Disable LCO/SRCO/TRCO on IRQ pin.
*/
void AS3935::disableOscillators(void)
{
writeRegisterWithMask(0x08, 0xE0, 0x00);
}
/**
Get interrupt reason
@return one of AS3935_INT_STRIKE, AS3935_INT_DISTURBER, AS3935_INT_NOISE
*/
uint8_t AS3935::getInterruptReason(void)
{
return readRegisterWithMask(0x03, 0b00001111);
}
/**
Return the estimated distance in km to the head of an approaching storm.
@return int8_t value of the estimated distance in km,
AS3935_DISTANCE_OUT_OF_RANGE when out of range, or -1 when the register
value is invalid. See also: 8.9.3 Statistical Distance Estimation
*/
int8_t AS3935::getDistance(void)
{
uint8_t v;
int8_t d;
v = readRegisterWithMask(0x07, 0b00111111);
switch (v) {
case 0b111111:
d = AS3935_DISTANCE_OUT_OF_RANGE;
break;
case 0b101000:
d = 40;
break;
case 0b100101:
d = 37;
break;
case 0b100010:
d = 34;
break;
case 0b011111:
d = 31;
break;
case 0b011011:
d = 27;
break;
case 0b011000:
d = 24;
break;
case 0b010100:
d = 20;
break;
case 0b010001:
d = 17;
break;
case 0b001110:
d = 14;
break;
case 0b001100:
d = 12;
break;
case 0b001010:
d = 10;
break;
case 0b001000:
d = 8;
break;
case 0b000110:
d = 6;
break;
case 0b000101:
d = 5;
break;
case 0b000001:
d = 0;
break;
default:
d = -1;
break;
}
return d;
}
/**
Returns bool whether or not current AFE setting is indoor.
@return true if the setting is indoor, false if not
*/
bool AS3935::isIndoor()
{
return readRegisterWithMask(0x00, 0b11000001) == AS3935_AFE_INDOOR;
}
/**
Set AFE setting to indoor mode
@return true or false whether if setting to indoor mode succeeded.
*/
bool AS3935::setIndoor()
{
writeRegisterWithMask(0x00, 0b11000001, AS3935_AFE_INDOOR);
return isIndoor();
}
/**
Set or unset AFE setting to indoor mode.
@param enable True of false whether to set AFE to indoor mode.
@return true or false whether if setting to indoor mode succeeded.
*/
bool AS3935::setIndoor(bool enable)
{
return enable ? setIndoor() : setOutdoor();
}
/**
Returns bool whether or not current AFE setting is outdoor.
@return true if the setting is outdoor, false if not
*/
bool AS3935::isOutdoor()
{
return readRegisterWithMask(0x00, 0b11000001) == AS3935_AFE_OUTDOOR;
}
/**
Set the AFE setting to outdoor mode.
@return true or false whether if setting to outdoor mode succeeded.
*/
bool AS3935::setOutdoor()
{
writeRegisterWithMask(0x00, 0b11000001, AS3935_AFE_OUTDOOR);
return isOutdoor();
}
/**
Set or unset AFE setting to outdoor mode.
@param enable True of false whether to set AFE to outdoor mode.
@return true or false whether if setting to outdoor mode succeeded.
*/
bool AS3935::setOutdoor(bool enable)
{
return enable ? setOutdoor() : setIndoor();
}
void AS3935::disableDisturbers()
{
writeRegisterWithMask(AS3935_MASK_DIST, 1);
}
void AS3935::enableDisturbers()
{
writeRegisterWithMask(AS3935_MASK_DIST, 0);
}
/**
Get minimum number of lightning
@return uint8_t number of minimum number of lightning, one of 1, 5, 9, or
16.
*/
uint8_t AS3935::getMinimumLightning(void)
{
switch (readRegisterWithMask(0x02, 0b11001111)) {
case 0:
return 1;
break;
case 1:
return 5;
break;
case 2:
return 9;
break;
case 3:
return 16;
break;
default:
return 255;
break;
}
}
/**
Set minimum number of lightning to trigger an event
@param n Minimum number of lightnings, one of 1, 5, 9, or 16.
@return bool whether or not setting the value succeeded.
*/
bool AS3935::setMinimumLightning(uint8_t n)
{
if (n == 1 || n == 5 || n == 9 || n == 16) {
writeRegisterWithMask(0x02, 0b11001111, n);
return getMinimumLightning();
}
return false;
}
/**
Clear the statistics built up by the lightning distance estimation algorithm
block.
*/
void AS3935::clearStats(void)
{
writeRegisterWithMask(0x02, 0b10111111, 1);
delay(2);
writeRegisterWithMask(0x02, 0b10111111, 0);
delay(2);
writeRegisterWithMask(0x02, 0b10111111, 1);
delay(2);
}
/**
Get noise floor level from AS3935.
@return The current noise floor level from the register
*/
uint8_t AS3935::getNoiseFloor(void)
{
return readRegisterWithMask(0x01, 0b01110000);
}
/**
Set noise floor level from AS3935.
@param level The noise floor level, from 0 to 7, to set.
@return true or false whether if setting the level is succeeded
*/
bool AS3935::setNoiseFloor(int level)
{
if (level < 0 || level > 7)
return false;
writeRegisterWithMask(0x01, 0b01110000, level);
return getNoiseFloor() == level;
}
uint16_t AS3935::getSpikeRejection()
{
return readRegisterWithMask(AS3935_SREJ);
}
bool AS3935::setSpikeRejection(int level)
{
if (level < 0 || level > 15)
return false;
writeRegisterWithMask(AS3935_SREJ, level);
return getSpikeRejection() == level;
}
/**
Increase noise floor level by one. When the level raeches to the maximum
value, 7, further call will not increase the level.
@return The noise floor level after the change.
*/
uint8_t AS3935::increaseNoiseFloor(void)
{
int level = getNoiseFloor();
setNoiseFloor(level + 1);
return getNoiseFloor();
}
/**
Decrease noise floor level by one. When the level raeches to the minimum
value, 0, further call will not decrease the level.
@return The noise floor level after the change.
*/
uint8_t AS3935::descreseNoiseFloor(void)
{
int level = getNoiseFloor();
setNoiseFloor(level - 1);
return getNoiseFloor();
}
uint16_t AS3935::getWatchdogThreshold(void)
{
return readRegisterWithMask(AS3935_WDTH);
}
uint16_t AS3935::setWatchdogThreshold(uint16_t wdth)
{
writeRegisterWithMask(AS3935_WDTH, wdth);
return getWatchdogThreshold();
}
void AS3935::reset()
{
//write to 0x3c, value 0x96
Serial.println("-------Reset-------");
writeRegister ((uint8_t)0x3c, (uint8_t)0x96);
delay(2);
}
/**
Set internal capacitor values, from 0 to 120pF in steps of 8pf. Interrupts
are disabled while calibrating.
@param cap Integer, from 0 to 15.
@return the value of the internal capacitor
*/
uint8_t AS3935::setTuningCapacitor(uint8_t cap)
{
if (cap <= 15 || cap >= 0) {
noInterrupts();
writeRegisterWithMask(0x08, 0b00001111, cap);
delay(2);
calibrateRCO();
writeRegisterWithMask(0x08, 0b00100000, 1);
delay(2);
writeRegisterWithMask(0x08, 0b00100000, 0);
interrupts();
}
return readRegisterWithMask(0x08, 0b00001111);
}
/**
Compatibility
@param cap Integer, from 0 to 15.
@sa AS3935::setTuningCapacitor(uint8_t)
*/
void AS3935::calibrate(uint8_t cap)
{
setTuningCapacitor(cap);
}