Skip to content

Commit 7a667aa

Browse files
committed
NRF52LL ADC and documentation improvements
1 parent 7727618 commit 7a667aa

File tree

2 files changed

+64
-25
lines changed

2 files changed

+64
-25
lines changed

devices/NRF52LL.js

Lines changed: 37 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,9 @@ exports.lpcomp = function(opts) {
206206
eEnd // event when ADC has filled DMA buffer
207207
setDMA : function({ptr,cnt}) // set new DMA buffer
208208
// double-buffered so can be set again right after tStart
209+
start : function() // configure ADC (called automatically when 'saadc' created)
209210
sample : function(cnt) // Make `cnt*channels.length` readings and return the result. resets DMA
211+
stop : function() // uninitialise so that normal analogRead works
210212
}
211213
*/
212214
exports.saadc = function(opts) {
@@ -227,6 +229,7 @@ exports.saadc = function(opts) {
227229
poke32(addr+0x630, 0|o.cnt);
228230
},
229231
sample : function(cnt) {
232+
poke32(o.enable, 1);
230233
cnt = cnt||1;
231234
if (cnt>1 && !opts.samplerate)
232235
throw "Can't do >1 sample with no samplerate specified";
@@ -241,7 +244,37 @@ exports.saadc = function(opts) {
241244
while (!peek32(o.eEnd));
242245
poke32(o.tStop,1);
243246
o.setDMA(); // don't try and write to this buffer now we're not using it any more
247+
poke32(addr+0x104, 0); // clear end flag
248+
poke32(o.enable, 0);
244249
return buf.slice(0,cnt*opts.channels.length);
250+
},
251+
start : function() {
252+
this.stop();
253+
// config channels
254+
opts.channels.forEach(function(ch, idx) {
255+
var a = addr+0x510 + idx*16;
256+
var v = (pulls.indexOf(ch.pinpull)) |
257+
(pulls.indexOf(ch.npinpull)<<4) |
258+
(gains.indexOf(ch.gain)<<8) |
259+
((!!ch.refvdd)<<12) |
260+
(tacqs.indexOf(ch.tacq)<<16) |
261+
((ch.npin!==undefined)<<20) | // differential if npin is supplied
262+
((!!opts.oversample)<<24);
263+
poke32(a+8, v); // options
264+
poke32(a, 0|(new Pin(ch.pin).getInfo().channel+1)); // pin pos - undefined -> 0
265+
poke32(a+4, 0|((ch.npin&&new Pin(ch.npin).getInfo().channel)+1)); // pin neg - undefined -> 0
266+
});
267+
poke32(addr+0x5F0, (opts.resolution-8)>>1);
268+
poke32(addr+0x5F4, 0|opts.oversample);
269+
poke32(addr+0x5F8, opts.samplerate | ((!!opts.samplerate)<<12));
270+
o.setDMA(opts.dma);
271+
},
272+
stop : function() {
273+
poke32(o.enable, 0);
274+
poke32(addr+0x5F4, 0); // disable oversample
275+
// disable all ADC channels
276+
for (var i=0;i<8;i++)
277+
poke32(addr+0x510 + i*16, 0);
245278
}
246279
};
247280
var pulls = [undefined, "down","up","vcc/2"];
@@ -251,38 +284,21 @@ exports.saadc = function(opts) {
251284
if (!opts.channels || opts.channels.length>8) throw "Invalid channels";
252285
if (opts.oversample && opts.channels.length>1)throw "Can't oversample with >1 channel";
253286
if (opts.samplerate && opts.channels.length>1)throw "Can't use samplerate with >1 channel";
254-
poke32(o.enable, 0);
255-
// disable all ADC channels
256-
for (var i=0;i<8;i++)
257-
poke32(addr+0x510 + i*16, 0);
258-
// config those specified
287+
// check channel info
259288
opts.channels.forEach(function(ch, idx) {
260-
var a = addr+0x510 + idx*16;
261289
if (!ch.gain) ch.gain=1;
262290
if (!ch.tacq) ch.tacq=3;
263291
if (pulls.indexOf(ch.pinpull)<0) throw "Invalid pinpull";
264292
if (pulls.indexOf(ch.npinpull)<0) throw "Invalid npinpull";
265293
if (gains.indexOf(ch.gain)<0) throw "Invalid gain";
266294
if (tacqs.indexOf(ch.tacq)<0) throw "Invalid tacq";
267-
var v = (pulls.indexOf(ch.pinpull)) |
268-
(pulls.indexOf(ch.npinpull)<<4) |
269-
(gains.indexOf(ch.gain)<<8) |
270-
((!!ch.refvdd)<<12) |
271-
(tacqs.indexOf(ch.tacq)<<16) |
272-
((ch.npin!==undefined)<<20) | // differential if npin is supplied
273-
((!!opts.oversample)<<24);
274-
poke32(a+8, v); // options
275-
poke32(a, 0|(new Pin(ch.pin).getInfo().channel+1)); // pin pos - undefined -> 0
276-
poke32(a+4, 0|((ch.npin&&new Pin(ch.npin).getInfo().channel)+1)); // pin neg - undefined -> 0
277295
});
278-
poke32(addr+0x5F0, (opts.resolution-8)>>1);
279-
poke32(addr+0x5F4, 0|opts.oversample);
280-
poke32(addr+0x5F8, opts.samplerate | ((!!opts.samplerate)<<12));
281-
o.setDMA(opts.dma);
282-
poke32(o.enable, 1);
296+
// setup
297+
o.start();
283298
return o;
284299
};
285300

301+
286302
/** Real time counter
287303
You should only set on ch2 as 0 and 1 are used by Espruino/Bluetooth
288304
This function intentionally doesn't set state itself to allow you

devices/NRF52LL.md

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ nRF52 Low Level Interface Library
44

55
<span style="color:red">:warning: **Please view the correctly rendered version of this page at https://www.espruino.com/NRF52LL. Links, lists, videos, search, and other features will not work correctly when viewed on GitHub** :warning:</span>
66

7-
* KEYWORDS: Module,nRF52,nRF5x,nRF52832,Puck.js
8-
* USES: Puck.js,Pixl.js,MDBT42Q,nRF52832,nRF52
7+
* KEYWORDS: Module,nRF52,nRF5x,nRF52832,Low Level,Hardware,Differential,SAADC,GPIOTE,LPCOMP,PPI,TIMER
8+
* USES: Puck.js,Pixl.js,Jolt.js,MDBT42Q,nRF52832,nRF52
99

1010
The nRF52 microcontroller used in [Puck.js](/Puck.js), [Pixl.js](/Pixl.js) and [MDBT42Q](/MDBT42Q) has a load of really interesting peripherals built-in, not all of which are exposed by Espruino. The microcontroller also contains something called PPI - the "Programmable Peripheral Interconnect". This allows you to 'wire' peripherals together internally.
1111

@@ -140,7 +140,7 @@ setWatch(function() {
140140

141141
### Make one reading from the ADC:
142142

143-
Uses ADC.
143+
Uses the ADC (much line `analogRead` but with more options)
144144

145145
```JS
146146
var ll = require("NRF52LL");
@@ -153,6 +153,27 @@ var saadc = ll.saadc({
153153
} ]
154154
});
155155
print(saadc.sample()[0]);
156+
saadc.stop(); // deconfigure so analogRead works again (use saadc.start() to redo)
157+
```
158+
159+
### Make a differential from the ADC:
160+
161+
Use the ADC to measure the voltage difference between D30 and D31,
162+
with the maximum gain and oversampling provided by the hardware.
163+
164+
```JS
165+
var ll = require("NRF52LL");
166+
var saadc = ll.saadc({
167+
channels : [ { // channel 0
168+
pin:D30, npin:D31,
169+
gain:4,
170+
tacq:40,
171+
refvdd:true,
172+
} ],
173+
oversample : 8
174+
});
175+
print(saadc.sample()[0]);
176+
saadc.stop(); // deconfigure so analogRead works again (use saadc.start() to redo)
156177
```
157178

158179
### Read a buffer of data from the ADC
@@ -186,6 +207,7 @@ poke32(saadc.tSample,1); // start!
186207
while (!peek32(saadc.eEnd)); // wait until it ends
187208
poke32(saadc.tStop,1);
188209
print("Done!", buf);
210+
saadc.stop(); // deconfigure so analogRead works again (use saadc.start() to redo)
189211
```
190212

191213
### Read a buffer of data from the ADC, alternating between 2 pins
@@ -203,7 +225,7 @@ var buf = new Int16Array(128);
203225
// ADC
204226
var saadc = ll.saadc({
205227
channels : [ {
206-
pin:D31, // channel 0
228+
pin:D31, // channel 0
207229
gain:1/4,
208230
refvdd:true
209231
}, {
@@ -226,6 +248,7 @@ while (!peek32(saadc.eEnd)); // wait until sampling ends
226248
poke32(tmr.tStop,1);
227249
poke32(saadc.tStop,1);
228250
print("Done!", buf);
251+
saadc.stop(); // deconfigure so analogRead works again (use saadc.start() to redo)
229252
```
230253

231254
### Use the RTC to toggle the state of a LED

0 commit comments

Comments
 (0)