Skip to content
This repository was archived by the owner on Jan 4, 2021. It is now read-only.

Commit 1b94d0a

Browse files
committed
Commit for api v0.2.0
1 parent d62aa85 commit 1b94d0a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+1271
-191
lines changed

MetaWear.DotNet/Properties/AssemblyInfo.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,4 @@
3232
// by using the '*' as shown below:
3333
// [assembly: AssemblyVersion("1.0.*")]
3434
[assembly: AssemblyVersion("1.0.0.0")]
35-
[assembly: AssemblyFileVersion("0.1.0")]
35+
[assembly: AssemblyFileVersion("0.2.0")]

MetaWear.Impl/AccelerometerBmi160.cs

Lines changed: 75 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,85 @@ namespace MbientLab.MetaWear.Impl {
99
[DataContract]
1010
class AccelerometerBmi160 : AccelerometerBosch, IAccelerometerBmi160 {
1111
public const byte IMPLEMENTATION = 0x1;
12-
12+
13+
private const byte STEP_DETECTOR_INTERRUPT_ENABLE = 0x17,
14+
STEP_DETECTOR_CONFIG = 0x18,
15+
STEP_DETECTOR_INTERRUPT = 0x19,
16+
STEP_COUNTER_DATA = 0x1a,
17+
STEP_COUNTER_RESET = 0x1b;
1318
private static readonly float[] FREQUENCIES = new float[] { 0.078125f, 1.5625f, 3.125f, 6.25f, 12.5f, 25f, 50f, 100f, 200f, 400f, 800f, 1600f };
19+
private static void applyDetectorMode(byte[] config, StepDetectorMode mode) {
20+
switch (mode) {
21+
case StepDetectorMode.Normal:
22+
config[0] = 0x15;
23+
config[1] |= 0x3;
24+
break;
25+
case StepDetectorMode.Sensitive:
26+
config[0] = 0x2d;
27+
break;
28+
case StepDetectorMode.Robust:
29+
config[0] = 0x1d;
30+
config[1] |= 0x7;
31+
break;
32+
}
33+
}
34+
35+
private class StepCounterDataProducer : ForcedDataProducer, IStepCounterDataProducer {
36+
private readonly byte[] config = new byte[] { 0x00, 0x08 };
37+
38+
internal StepCounterDataProducer(DataTypeBase dataTypeBase, IModuleBoardBridge bridge) : base(dataTypeBase, bridge) {
39+
}
40+
41+
public void Configure(StepDetectorMode mode = StepDetectorMode.Normal) {
42+
applyDetectorMode(config, mode);
43+
bridge.sendCommand(ACCELEROMETER, STEP_DETECTOR_CONFIG, config);
44+
}
45+
46+
public void Reset() {
47+
bridge.sendCommand(new byte[] { (byte)ACCELEROMETER, STEP_COUNTER_RESET });
48+
}
49+
}
50+
51+
private class StepDetectorDataProducer : AsyncDataProducerV2, IStepDetectorDataProducer {
52+
private readonly byte[] config = new byte[] { 0x00, 0x00 };
53+
54+
internal StepDetectorDataProducer(DataTypeBase dataTypeBase, IModuleBoardBridge bridge) : base(STEP_DETECTOR_INTERRUPT_ENABLE, 0x1, dataTypeBase, bridge) {
55+
}
56+
57+
public void Configure(StepDetectorMode mode = StepDetectorMode.Normal) {
58+
applyDetectorMode(config, mode);
59+
bridge.sendCommand(ACCELEROMETER, STEP_DETECTOR_CONFIG, config);
60+
}
61+
}
1462

1563
[DataMember] private readonly byte[] accDataConfig = new byte[] { 0x28, 0x03 };
64+
[DataMember] private IntegralDataType stepCounterDataType, stepDetectorDataType;
65+
66+
protected IStepCounterDataProducer stepCounter;
67+
protected IStepDetectorDataProducer stepDetector;
68+
69+
public IStepCounterDataProducer StepCounter {
70+
get {
71+
if (stepCounter == null) {
72+
stepCounter = new StepCounterDataProducer(stepCounterDataType, bridge);
73+
}
74+
return stepCounter;
75+
}
76+
}
77+
78+
public IStepDetectorDataProducer StepDetector {
79+
get {
80+
if (stepDetector == null) {
81+
stepDetector = new StepDetectorDataProducer(stepDetectorDataType, bridge);
82+
}
83+
return stepDetector;
84+
}
85+
}
1686

17-
public AccelerometerBmi160(IModuleBoardBridge bridge) : base(bridge) { }
87+
public AccelerometerBmi160(IModuleBoardBridge bridge) : base(bridge) {
88+
stepCounterDataType = new IntegralDataType(ACCELEROMETER, Util.setRead(STEP_COUNTER_DATA), new DataAttributes(new byte[] { 2 }, 1, 0, false));
89+
stepDetectorDataType = new IntegralDataType(ACCELEROMETER, STEP_DETECTOR_INTERRUPT, new DataAttributes(new byte[] { 1 }, 1, 0, false));
90+
}
1891

1992
public void Configure(OutputDataRate odr, DataRange range) {
2093
accDataConfig[0] &= 0xf0;

MetaWear.Impl/DataAttributes.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@ internal DataAttributes dataProcessorCopySigned(bool newSigned) {
3939
return new DataAttributes(sizesCopy, copies, 0, newSigned);
4040
}
4141

42+
internal DataAttributes dataProcessorCopyCopies(byte newCopies) {
43+
byte[] sizesCopy = new byte[sizes.Length];
44+
Array.Copy(sizes, sizesCopy, sizes.Length);
45+
return new DataAttributes(sizesCopy, newCopies, 0, signed);
46+
}
47+
4248
public byte length() {
4349
return (byte)(unitLength() * copies);
4450
}

MetaWear.Impl/DataProcessor.cs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,13 @@ internal NullEditor(byte[] config, DataTypeBase source, IModuleBoardBridge bridg
3737
[KnownType(typeof(ThresholdEditorInner))]
3838
[KnownType(typeof(DifferentialEditorInner))]
3939
[KnownType(typeof(TimeEditorInner))]
40+
[KnownType(typeof(PackerEditorInner))]
41+
[KnownType(typeof(NullEditor))]
4042
[KnownType(typeof(DataTypeBase))]
4143
[DataContract]
4244
class DataProcessor : ModuleImplBase, IDataProcessor {
43-
internal const byte TIME_PASSTHROUGH_REVISION = 1;
45+
internal const byte TYPE_ACCOUNTER = 0x11, TYPE_PACKER = 0x10;
46+
internal const byte TIME_PASSTHROUGH_REVISION = 1, ENHANCED_STREAMING_REVISION = 2, HPF_REVISION = 2;
4447
internal const byte ADD = 2,
4548
NOTIFY = 3,
4649
STATE = 4,
@@ -56,6 +59,7 @@ class DataProcessor : ModuleImplBase, IDataProcessor {
5659
private LinkedList<Tuple<DataTypeBase, EditorImplBase>> pendingProcessors;
5760
private Queue<byte> successfulProcessors;
5861
private TaskCompletionSource<Queue<byte>> createProcessorsTask;
62+
private Dictionary<string, IForcedDataProducer> stateDataProducers;
5963

6064
public DataProcessor(IModuleBoardBridge bridge) : base(bridge) {
6165
}
@@ -78,6 +82,7 @@ internal override void restoreTransientVars(IModuleBoardBridge bridge) {
7882
}
7983

8084
protected override void init() {
85+
stateDataProducers = new Dictionary<string, IForcedDataProducer>();
8186
bridge.addRegisterResponseHandler(Tuple.Create((byte) DATA_PROCESSOR, ADD), response => {
8287
createTimeout.Dispose();
8388

@@ -96,7 +101,15 @@ protected override void init() {
96101
}
97102

98103
public IForcedDataProducer State(string name) {
99-
throw new NotImplementedException();
104+
if (stateDataProducers.TryGetValue(name, out var producer)) {
105+
return producer;
106+
}
107+
if (nameToId.TryGetValue(name, out var id) && activeProcessors.TryGetValue(id, out var value)) {
108+
producer = new ForcedDataProducer(value.Item1, bridge);
109+
stateDataProducers.Add(name, producer);
110+
return producer;
111+
}
112+
return null;
100113
}
101114

102115
public T Edit<T>(string name) where T : class, IEditor {
@@ -150,5 +163,9 @@ void removeProcessor(bool sync, byte id) {
150163

151164
activeProcessors.Remove(id);
152165
}
166+
167+
internal Tuple<DataTypeBase, EditorImplBase> lookupProcessor(byte id) {
168+
return activeProcessors.TryGetValue(id, out var result) ? result : null;
169+
}
153170
}
154171
}

MetaWear.Impl/FloatDataType.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public override T Value<T>() {
2121

2222
if (type == typeof(float)) {
2323
if (datatype.attributes.signed) {
24-
switch (datatype.attributes.length()) {
24+
switch (Math.Min(datatype.attributes.unitLength(), bytes.Length - offset)) {
2525
case 1:
2626
return (T)Convert.ChangeType((sbyte) (bytes[offset]) / Scale, type);
2727
case 2:
@@ -33,7 +33,7 @@ public override T Value<T>() {
3333
return (T)Convert.ChangeType(BitConverter.ToInt32(bytes, offset) / Scale, type);
3434
}
3535
} else {
36-
switch (datatype.attributes.length()) {
36+
switch (Math.Min(datatype.attributes.unitLength(), bytes.Length - offset)) {
3737
case 1:
3838
return (T)Convert.ChangeType(bytes[offset] / Scale, type);
3939
case 2:

MetaWear.Impl/Logging.cs

Lines changed: 58 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,19 @@ public override void disableStream(IModuleBoardBridge bridge) { }
6767
public override void addDataHandler(IModuleBoardBridge bridge) { }
6868
}
6969

70+
[DataContract]
71+
class TimeReference {
72+
public byte resetUid;
73+
public long tick;
74+
public DateTime timestamp;
75+
76+
public TimeReference(byte resetUid, long tick, DateTime timestamp) {
77+
this.timestamp = timestamp;
78+
this.tick = tick;
79+
this.resetUid = resetUid;
80+
}
81+
}
82+
7083
[DataContract]
7184
class Logging : ModuleImplBase, ILogging {
7285
private const double TICK_TIME_STEP = (48.0 / 32768.0) * 1000.0;
@@ -81,8 +94,8 @@ class Logging : ModuleImplBase, ILogging {
8194
CIRCULAR_BUFFER = 0xb,
8295
READOUT_PAGE_COMPLETED = 0xd, READOUT_PAGE_CONFIRM = 0xe;
8396

84-
[DataMember] private Tuple<byte, uint, DateTime> latestReference;
85-
[DataMember] private Dictionary<byte, Tuple<byte, uint, DateTime>> logReferenceTicks= new Dictionary<byte, Tuple<byte, uint, DateTime>>();
97+
[DataMember] private TimeReference latestReference;
98+
[DataMember] private Dictionary<byte, TimeReference> logReferenceTicks= new Dictionary<byte, TimeReference>();
8699
[DataMember] private Dictionary<byte, LoggedDataConsumer> dataLoggers= new Dictionary<byte, LoggedDataConsumer>();
87100
[DataMember] private Dictionary<byte, uint> lastTimestamp= new Dictionary<byte, uint>();
88101

@@ -97,6 +110,9 @@ public override void tearDown() {
97110
}
98111

99112
public override void disconnected() {
113+
foreach (var e in lastTimestamp) {
114+
rollbackTimestamps[e.Key] = e.Value;
115+
}
100116
if (downloadTask != null) {
101117
downloadTask.SetCanceled();
102118
downloadTask = null;
@@ -105,16 +121,11 @@ public override void disconnected() {
105121

106122
private void processLogData(byte[] logEntry, int offset) {
107123
byte logId = (byte)(logEntry[0 + offset] & 0x1f), resetUid = (byte)((logEntry[0 + offset] & ~0x1f) >> 5);
108-
if (!logReferenceTicks.TryGetValue(resetUid, out var reference)) {
109-
reference = latestReference;
110-
}
111124

112125
uint tick = BitConverter.ToUInt32(logEntry, 1 + offset);
113-
DateTime timestamp = reference.Item3.AddMilliseconds((uint) ((tick - reference.Item2) * TICK_TIME_STEP));
114-
115-
if (!lastTimestamp.TryGetValue(logId, out var cachedTick) || cachedTick < tick) {
116-
lastTimestamp[logId] = tick;
117-
126+
if (!rollbackTimestamps.TryGetValue(resetUid, out uint rollback) || rollback < tick) {
127+
var timestamp = computeTimestamp(resetUid, tick);
128+
118129
byte[] logData = new byte[LOG_ENTRY_SIZE];
119130
Array.Copy(logEntry, 5 + offset, logData, 0, LOG_ENTRY_SIZE);
120131

@@ -127,6 +138,7 @@ private void processLogData(byte[] logEntry, int offset) {
127138
}
128139

129140
protected override void init() {
141+
rollbackTimestamps = new Dictionary<byte, uint>();
130142
bridge.addRegisterResponseHandler(Tuple.Create((byte)LOGGING, TRIGGER), response => {
131143
nReqLogIds--;
132144
nextLogger.addId(response[2]);
@@ -149,29 +161,37 @@ protected override void init() {
149161
uint nEntriesLeft = BitConverter.ToUInt32(response, 2);
150162

151163
if (nEntriesLeft == 0) {
152-
lastTimestamp.Clear();
164+
rollbackTimestamps.Clear();
153165
downloadTask.SetResult(true);
154166
downloadTask = null;
155167
} else {
156168
updateHandler?.Invoke(nEntriesLeft, nLogEntries);
157169
}
158170
});
159171
bridge.addRegisterResponseHandler(Tuple.Create((byte)LOGGING, Util.setRead(TIME)), response => {
160-
uint tick = BitConverter.ToUInt32(response, 2);
161-
byte resetUid = (response.Length > 6) ? response[6] : (byte) 0xff;
162-
163-
latestReference = Tuple.Create(resetUid, tick, DateTime.Now);
164-
if (resetUid != 0xff) {
165-
logReferenceTicks[resetUid] = latestReference;
172+
// if in the middle of a log download, don't update the reference
173+
// rollbackTimestamps var is cleared after readout progress hits 0
174+
if (rollbackTimestamps.Count == 0) {
175+
uint tick = BitConverter.ToUInt32(response, 2);
176+
byte resetUid = (response.Length > 6) ? response[6] : (byte)0xff;
177+
178+
latestReference = new TimeReference(resetUid, tick, DateTime.Now);
179+
if (resetUid != 0xff) {
180+
logReferenceTicks[resetUid] = latestReference;
181+
}
166182
}
167183

168-
queryTimeTask.SetResult(true);
184+
if (queryTimeTask != null) {
185+
queryTimeTask.SetResult(true);
186+
queryTimeTask = null;
187+
}
169188
});
170189
bridge.addRegisterResponseHandler(Tuple.Create((byte)LOGGING, Util.setRead(LENGTH)), response => {
171190
int payloadSize = response.Length - 2;
172191
nLogEntries = BitConverter.ToUInt32(response, 2);
173192

174193
if (nLogEntries == 0) {
194+
rollbackTimestamps.Clear();
175195
downloadTask.SetResult(true);
176196
downloadTask = null;
177197
} else {
@@ -201,6 +221,7 @@ public void ClearEntries() {
201221
private TaskCompletionSource<bool> downloadTask;
202222
private Action<uint, uint> updateHandler;
203223
private Action<LogDownloadError, byte, DateTime, byte[]> errorHandler;
224+
private Dictionary<byte, uint> rollbackTimestamps;
204225

205226
public Task DownloadAsync(uint nUpdates, Action<uint, uint> updateHandler, Action<LogDownloadError, byte, DateTime, byte[]> errorHandler) {
206227
if (downloadTask != null) {
@@ -301,5 +322,24 @@ private void createLogger() {
301322
createLoggerTask.SetResult(successfulLoggers);
302323
}
303324
}
325+
326+
internal DateTime computeTimestamp(byte resetUid, uint tick) {
327+
if (!logReferenceTicks.TryGetValue(resetUid, out var reference)) {
328+
reference = latestReference;
329+
}
330+
331+
if (lastTimestamp.TryGetValue(resetUid, out uint previous) && previous > tick) {
332+
var offset = (tick - lastTimestamp[resetUid] + (lastTimestamp[resetUid] - reference.tick)) * TICK_TIME_STEP;
333+
reference.timestamp = reference.timestamp.AddMilliseconds((long) (offset));
334+
reference.tick = tick;
335+
336+
if (rollbackTimestamps.ContainsKey(resetUid)) {
337+
rollbackTimestamps[resetUid] = tick;
338+
}
339+
}
340+
341+
lastTimestamp[resetUid] = tick;
342+
return reference.timestamp.AddMilliseconds((long)((tick - reference.tick) * TICK_TIME_STEP));
343+
}
304344
}
305345
}

MetaWear.Impl/MagnetometerBmm150.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ namespace MbientLab.MetaWear.Impl {
99
[KnownType(typeof(Bmm150CartesianFloatData))]
1010
[DataContract]
1111
class MagnetometerBmm150 : ModuleImplBase, IMagnetometerBmm150 {
12-
private const byte PACKED_MAG_REVISION = 1;
12+
private const byte PACKED_MAG_REVISION = 1, SUSPEND_REVISION = 2;
1313
private const byte POWER_MODE = 1,
1414
DATA_INTERRUPT_ENABLE = 2, DATA_RATE = 3, DATA_REPETITIONS = 4, MAG_DATA = 5,
1515
PACKED_MAG_DATA = 0x09;
@@ -76,6 +76,9 @@ public MagnetometerBmm150(IModuleBoardBridge bridge) : base(bridge) {
7676
}
7777

7878
public void Configure(ushort xyReps = 9, ushort zReps = 15, OutputDataRate odr = OutputDataRate._10Hz) {
79+
if (bridge.lookupModuleInfo(MAGNETOMETER).revision >= SUSPEND_REVISION) {
80+
Stop();
81+
}
7982
bridge.sendCommand(new byte[] { (byte) MAGNETOMETER, DATA_REPETITIONS, (byte)((xyReps - 1) / 2), (byte)(zReps - 1) });
8083
bridge.sendCommand(new byte[] { (byte) MAGNETOMETER, DATA_RATE, (byte)odr });
8184
}
@@ -104,5 +107,11 @@ public void Start() {
104107
public void Stop() {
105108
bridge.sendCommand(new byte[] { (byte) MAGNETOMETER, POWER_MODE, 0 });
106109
}
110+
111+
public void Suspend() {
112+
if (bridge.lookupModuleInfo(MAGNETOMETER).revision >= SUSPEND_REVISION) {
113+
bridge.sendCommand(new byte[] { (byte)MAGNETOMETER, POWER_MODE, 2 });
114+
}
115+
}
107116
}
108117
}

0 commit comments

Comments
 (0)